summaryrefslogtreecommitdiff
path: root/chromium/components
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-20 13:40:20 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-22 12:41:23 +0000
commit7961cea6d1041e3e454dae6a1da660b453efd238 (patch)
treec0eeb4a9ff9ba32986289c1653d9608e53ccb444 /chromium/components
parentb7034d0803538058e5c9d904ef03cf5eab34f6ef (diff)
downloadqtwebengine-chromium-7961cea6d1041e3e454dae6a1da660b453efd238.tar.gz
BASELINE: Update Chromium to 78.0.3904.130
Change-Id: If185e0c0061b3437531c97c9c8c78f239352a68b Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components')
-rw-r--r--chromium/components/BUILD.gn21
-rw-r--r--chromium/components/OWNERS1
-rw-r--r--chromium/components/account_id/OWNERS1
-rw-r--r--chromium/components/account_id/mojom/account_id.typemap4
-rw-r--r--chromium/components/app_modal/OWNERS1
-rw-r--r--chromium/components/app_modal/views/OWNERS1
-rw-r--r--chromium/components/app_modal_strings_grdp/OWNERS1
-rw-r--r--chromium/components/arc/BUILD.gn12
-rw-r--r--chromium/components/arc/DEPS3
-rw-r--r--chromium/components/arc/OWNERS2
-rw-r--r--chromium/components/arc/app_permissions/arc_app_permissions_bridge.h2
-rw-r--r--chromium/components/arc/appfuse/arc_appfuse_bridge.h2
-rw-r--r--chromium/components/arc/arc_features.cc23
-rw-r--r--chromium/components/arc/arc_features.h5
-rw-r--r--chromium/components/arc/arc_features_parser.cc5
-rw-r--r--chromium/components/arc/arc_prefs.cc54
-rw-r--r--chromium/components/arc/arc_prefs.h11
-rw-r--r--chromium/components/arc/arc_util.cc80
-rw-r--r--chromium/components/arc/arc_util.h5
-rw-r--r--chromium/components/arc/arc_util_unittest.cc13
-rw-r--r--chromium/components/arc/audio/arc_audio_bridge.h2
-rw-r--r--chromium/components/arc/bitmap/OWNERS6
-rw-r--r--chromium/components/arc/bitmap/bitmap_mojom_traits.cc (renamed from chromium/components/arc/bitmap/bitmap_struct_traits.cc)15
-rw-r--r--chromium/components/arc/bitmap/bitmap_mojom_traits.h (renamed from chromium/components/arc/bitmap/bitmap_struct_traits.h)8
-rw-r--r--chromium/components/arc/bluetooth/OWNERS8
-rw-r--r--chromium/components/arc/bluetooth/bluetooth_mojom_traits.cc (renamed from chromium/components/arc/bluetooth/bluetooth_struct_traits.cc)8
-rw-r--r--chromium/components/arc/bluetooth/bluetooth_mojom_traits.h (renamed from chromium/components/arc/bluetooth/bluetooth_struct_traits.h)11
-rw-r--r--chromium/components/arc/bluetooth/bluetooth_mojom_traits_unittest.cc (renamed from chromium/components/arc/bluetooth/bluetooth_struct_traits_unittest.cc)2
-rw-r--r--chromium/components/arc/bluetooth/bluetooth_type_converters.h2
-rw-r--r--chromium/components/arc/camera/arc_camera_bridge.h2
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge.cc8
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge.h2
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc22
-rw-r--r--chromium/components/arc/common/app.typemap5
-rw-r--r--chromium/components/arc/common/bitmap.typemap13
-rw-r--r--chromium/components/arc/common/bluetooth.typemap21
-rw-r--r--chromium/components/arc/common/ime.typemap4
-rw-r--r--chromium/components/arc/common/print.typemap19
-rw-r--r--chromium/components/arc/common/print_spooler.mojom18
-rw-r--r--chromium/components/arc/common/timer.typemap10
-rw-r--r--chromium/components/arc/common/typemaps.gni18
-rw-r--r--chromium/components/arc/common/video_encode_accelerator.typemap24
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc4
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.h2
-rw-r--r--chromium/components/arc/disk_quota/arc_disk_quota_bridge.h2
-rw-r--r--chromium/components/arc/file_system/OWNERS6
-rw-r--r--chromium/components/arc/file_system/file_system_mojom_traits.cc (renamed from chromium/components/arc/file_system/file_system_struct_traits.cc)4
-rw-r--r--chromium/components/arc/file_system/file_system_mojom_traits.h (renamed from chromium/components/arc/file_system/file_system_struct_traits.h)8
-rw-r--r--chromium/components/arc/ime/arc_ime_bridge_impl.h2
-rw-r--r--chromium/components/arc/ime/arc_ime_service.cc7
-rw-r--r--chromium/components/arc/ime/arc_ime_service.h1
-rw-r--r--chromium/components/arc/ime/arc_ime_service_unittest.cc2
-rw-r--r--chromium/components/arc/intent_helper/OWNERS7
-rw-r--r--chromium/components/arc/intent_helper/activity_icon_loader.cc2
-rw-r--r--chromium/components/arc/intent_helper/activity_icon_loader.h4
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge.h2
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc2
-rw-r--r--chromium/components/arc/intent_helper/factory_reset_delegate.h2
-rw-r--r--chromium/components/arc/intent_helper/intent_filter.cc2
-rw-r--r--chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc (renamed from chromium/components/arc/intent_helper/intent_filter_struct_traits.cc)16
-rw-r--r--chromium/components/arc/intent_helper/intent_filter_mojom_traits.h (renamed from chromium/components/arc/intent_helper/intent_filter_struct_traits.h)8
-rw-r--r--chromium/components/arc/intent_helper/intent_filter_unittest.cc2
-rw-r--r--chromium/components/arc/intent_helper/link_handler_model.h2
-rw-r--r--chromium/components/arc/intent_helper/open_url_delegate.h2
-rw-r--r--chromium/components/arc/keymaster/arc_keymaster_bridge.h2
-rw-r--r--chromium/components/arc/lock_screen/arc_lock_screen_bridge.h2
-rw-r--r--chromium/components/arc/media_session/arc_media_session_bridge.cc3
-rw-r--r--chromium/components/arc/media_session/arc_media_session_bridge.h2
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service.cc223
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service.h90
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service_unittest.cc358
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.cc2
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.h4
-rw-r--r--chromium/components/arc/mojom/ARC_SECURITY_OWNERS (renamed from chromium/components/arc/common/ARC_SECURITY_OWNERS)0
-rw-r--r--chromium/components/arc/mojom/BUILD.gn (renamed from chromium/components/arc/common/BUILD.gn)21
-rw-r--r--chromium/components/arc/mojom/OWNERS (renamed from chromium/components/arc/common/OWNERS)6
-rw-r--r--chromium/components/arc/mojom/accessibility_helper.mojom (renamed from chromium/components/arc/common/accessibility_helper.mojom)39
-rw-r--r--chromium/components/arc/mojom/app.mojom (renamed from chromium/components/arc/common/app.mojom)6
-rw-r--r--chromium/components/arc/mojom/app.typemap6
-rw-r--r--chromium/components/arc/mojom/app_mojom_traits.h (renamed from chromium/components/arc/common/app_struct_traits.h)8
-rw-r--r--chromium/components/arc/mojom/app_permissions.mojom (renamed from chromium/components/arc/common/app_permissions.mojom)0
-rw-r--r--chromium/components/arc/mojom/appfuse.mojom (renamed from chromium/components/arc/common/appfuse.mojom)0
-rw-r--r--chromium/components/arc/mojom/arc_bridge.mojom (renamed from chromium/components/arc/common/arc_bridge.mojom)100
-rw-r--r--chromium/components/arc/mojom/arc_gfx_mojom_traits.cc (renamed from chromium/components/arc/common/arc_gfx_struct_traits.cc)2
-rw-r--r--chromium/components/arc/mojom/arc_gfx_mojom_traits.h (renamed from chromium/components/arc/common/arc_gfx_struct_traits.h)8
-rw-r--r--chromium/components/arc/mojom/audio.mojom (renamed from chromium/components/arc/common/audio.mojom)0
-rw-r--r--chromium/components/arc/mojom/auth.mojom (renamed from chromium/components/arc/common/auth.mojom)47
-rw-r--r--chromium/components/arc/mojom/backup_settings.mojom (renamed from chromium/components/arc/common/backup_settings.mojom)0
-rw-r--r--chromium/components/arc/mojom/bitmap.mojom (renamed from chromium/components/arc/common/bitmap.mojom)0
-rw-r--r--chromium/components/arc/mojom/bitmap.typemap13
-rw-r--r--chromium/components/arc/mojom/bluetooth.mojom (renamed from chromium/components/arc/common/bluetooth.mojom)0
-rw-r--r--chromium/components/arc/mojom/bluetooth.typemap21
-rw-r--r--chromium/components/arc/mojom/boot_phase_monitor.mojom (renamed from chromium/components/arc/common/boot_phase_monitor.mojom)0
-rw-r--r--chromium/components/arc/mojom/camera.mojom (renamed from chromium/components/arc/common/camera.mojom)2
-rw-r--r--chromium/components/arc/mojom/cast_receiver.mojom (renamed from chromium/components/arc/common/cast_receiver.mojom)0
-rw-r--r--chromium/components/arc/mojom/cert_store.mojom (renamed from chromium/components/arc/common/cert_store.mojom)0
-rw-r--r--chromium/components/arc/mojom/clipboard.mojom (renamed from chromium/components/arc/common/clipboard.mojom)0
-rw-r--r--chromium/components/arc/mojom/crash_collector.mojom (renamed from chromium/components/arc/common/crash_collector.mojom)0
-rw-r--r--chromium/components/arc/mojom/disk_quota.mojom (renamed from chromium/components/arc/common/disk_quota.mojom)0
-rw-r--r--chromium/components/arc/mojom/enterprise_reporting.mojom (renamed from chromium/components/arc/common/enterprise_reporting.mojom)0
-rw-r--r--chromium/components/arc/mojom/file_system.mojom (renamed from chromium/components/arc/common/file_system.mojom)4
-rw-r--r--chromium/components/arc/mojom/file_system.typemap (renamed from chromium/components/arc/common/file_system.typemap)8
-rw-r--r--chromium/components/arc/mojom/gfx.mojom (renamed from chromium/components/arc/common/gfx.mojom)0
-rw-r--r--chromium/components/arc/mojom/gfx.typemap (renamed from chromium/components/arc/common/gfx.typemap)6
-rw-r--r--chromium/components/arc/mojom/ime.mojom (renamed from chromium/components/arc/common/ime.mojom)2
-rw-r--r--chromium/components/arc/mojom/ime.typemap4
-rw-r--r--chromium/components/arc/mojom/ime_mojom_traits.h (renamed from chromium/components/arc/common/ime_struct_traits.h)8
-rw-r--r--chromium/components/arc/mojom/input_method_manager.mojom (renamed from chromium/components/arc/common/input_method_manager.mojom)4
-rw-r--r--chromium/components/arc/mojom/intent_common.mojom (renamed from chromium/components/arc/common/intent_common.mojom)0
-rw-r--r--chromium/components/arc/mojom/intent_helper.mojom (renamed from chromium/components/arc/common/intent_helper.mojom)6
-rw-r--r--chromium/components/arc/mojom/intent_helper.typemap (renamed from chromium/components/arc/common/intent_helper.typemap)6
-rw-r--r--chromium/components/arc/mojom/keymaster.mojom (renamed from chromium/components/arc/common/keymaster.mojom)0
-rw-r--r--chromium/components/arc/mojom/kiosk.mojom (renamed from chromium/components/arc/common/kiosk.mojom)0
-rw-r--r--chromium/components/arc/mojom/lock_screen.mojom (renamed from chromium/components/arc/common/lock_screen.mojom)0
-rw-r--r--chromium/components/arc/mojom/media_session.mojom (renamed from chromium/components/arc/common/media_session.mojom)0
-rw-r--r--chromium/components/arc/mojom/metrics.mojom (renamed from chromium/components/arc/common/metrics.mojom)0
-rw-r--r--chromium/components/arc/mojom/midis.mojom (renamed from chromium/components/arc/common/midis.mojom)0
-rw-r--r--chromium/components/arc/mojom/net.mojom (renamed from chromium/components/arc/common/net.mojom)0
-rw-r--r--chromium/components/arc/mojom/notifications.mojom (renamed from chromium/components/arc/common/notifications.mojom)4
-rw-r--r--chromium/components/arc/mojom/obb_mounter.mojom (renamed from chromium/components/arc/common/obb_mounter.mojom)0
-rw-r--r--chromium/components/arc/mojom/oemcrypto.mojom (renamed from chromium/components/arc/common/oemcrypto.mojom)2
-rw-r--r--chromium/components/arc/mojom/oemcrypto_daemon.mojom (renamed from chromium/components/arc/common/oemcrypto_daemon.mojom)6
-rw-r--r--chromium/components/arc/mojom/pip.mojom (renamed from chromium/components/arc/common/pip.mojom)0
-rw-r--r--chromium/components/arc/mojom/policy.mojom (renamed from chromium/components/arc/common/policy.mojom)0
-rw-r--r--chromium/components/arc/mojom/power.mojom (renamed from chromium/components/arc/common/power.mojom)0
-rw-r--r--chromium/components/arc/mojom/print.mojom (renamed from chromium/components/arc/common/print.mojom)118
-rw-r--r--chromium/components/arc/mojom/print.typemap19
-rw-r--r--chromium/components/arc/mojom/print_common.mojom123
-rw-r--r--chromium/components/arc/mojom/print_spooler.mojom52
-rw-r--r--chromium/components/arc/mojom/process.mojom (renamed from chromium/components/arc/common/process.mojom)35
-rw-r--r--chromium/components/arc/mojom/property.mojom (renamed from chromium/components/arc/common/property.mojom)0
-rw-r--r--chromium/components/arc/mojom/protected_buffer_manager.mojom (renamed from chromium/components/arc/common/protected_buffer_manager.mojom)2
-rw-r--r--chromium/components/arc/mojom/rotation_lock.mojom (renamed from chromium/components/arc/common/rotation_lock.mojom)0
-rw-r--r--chromium/components/arc/mojom/scale_factor.mojom (renamed from chromium/components/arc/common/scale_factor.mojom)0
-rw-r--r--chromium/components/arc/mojom/screen_capture.mojom (renamed from chromium/components/arc/common/screen_capture.mojom)4
-rw-r--r--chromium/components/arc/mojom/storage_manager.mojom (renamed from chromium/components/arc/common/storage_manager.mojom)0
-rw-r--r--chromium/components/arc/mojom/timer.mojom (renamed from chromium/components/arc/common/timer.mojom)0
-rw-r--r--chromium/components/arc/mojom/timer.typemap10
-rw-r--r--chromium/components/arc/mojom/tracing.mojom (renamed from chromium/components/arc/common/tracing.mojom)0
-rw-r--r--chromium/components/arc/mojom/tts.mojom (renamed from chromium/components/arc/common/tts.mojom)0
-rw-r--r--chromium/components/arc/mojom/typemaps.gni18
-rw-r--r--chromium/components/arc/mojom/usb_host.mojom (renamed from chromium/components/arc/common/usb_host.mojom)0
-rw-r--r--chromium/components/arc/mojom/video.mojom (renamed from chromium/components/arc/common/video.mojom)6
-rw-r--r--chromium/components/arc/mojom/video_accelerator_mojom_traits.cc (renamed from chromium/components/arc/common/video_accelerator_struct_traits.cc)2
-rw-r--r--chromium/components/arc/mojom/video_accelerator_mojom_traits.h (renamed from chromium/components/arc/common/video_accelerator_struct_traits.h)8
-rw-r--r--chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc (renamed from chromium/components/arc/common/video_accelerator_struct_traits_unittest.cc)4
-rw-r--r--chromium/components/arc/mojom/video_common.mojom (renamed from chromium/components/arc/common/video_common.mojom)0
-rw-r--r--chromium/components/arc/mojom/video_common.typemap (renamed from chromium/components/arc/common/video_common.typemap)8
-rw-r--r--chromium/components/arc/mojom/video_decode_accelerator.mojom (renamed from chromium/components/arc/common/video_decode_accelerator.mojom)16
-rw-r--r--chromium/components/arc/mojom/video_encode_accelerator.mojom (renamed from chromium/components/arc/common/video_encode_accelerator.mojom)2
-rw-r--r--chromium/components/arc/mojom/video_encode_accelerator.typemap24
-rw-r--r--chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc (renamed from chromium/components/arc/common/video_encode_accelerator_struct_traits.cc)4
-rw-r--r--chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.h (renamed from chromium/components/arc/common/video_encode_accelerator_struct_traits.h)8
-rw-r--r--chromium/components/arc/mojom/video_protected_buffer_allocator.mojom (renamed from chromium/components/arc/common/video_protected_buffer_allocator.mojom)2
-rw-r--r--chromium/components/arc/mojom/voice_interaction_arc_home.mojom (renamed from chromium/components/arc/common/voice_interaction_arc_home.mojom)2
-rw-r--r--chromium/components/arc/mojom/voice_interaction_framework.mojom (renamed from chromium/components/arc/common/voice_interaction_framework.mojom)4
-rw-r--r--chromium/components/arc/mojom/volume_mounter.mojom (renamed from chromium/components/arc/common/volume_mounter.mojom)6
-rw-r--r--chromium/components/arc/mojom/volume_mounter.typemap (renamed from chromium/components/arc/common/volume_mounter.typemap)10
-rw-r--r--chromium/components/arc/mojom/wake_lock.mojom (renamed from chromium/components/arc/common/wake_lock.mojom)0
-rw-r--r--chromium/components/arc/mojom/wallpaper.mojom (renamed from chromium/components/arc/common/wallpaper.mojom)0
-rw-r--r--chromium/components/arc/net/always_on_vpn_manager_unittest.cc4
-rw-r--r--chromium/components/arc/net/arc_net_host_impl.cc6
-rw-r--r--chromium/components/arc/net/arc_net_host_impl.h4
-rw-r--r--chromium/components/arc/net/arc_net_host_impl_unittest.cc4
-rw-r--r--chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h2
-rw-r--r--chromium/components/arc/power/arc_power_bridge.cc13
-rw-r--r--chromium/components/arc/power/arc_power_bridge.h4
-rw-r--r--chromium/components/arc/power/arc_power_bridge_unittest.cc6
-rw-r--r--chromium/components/arc/print_spooler/OWNERS2
-rw-r--r--chromium/components/arc/property/arc_property_bridge.h2
-rw-r--r--chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h2
-rw-r--r--chromium/components/arc/session/arc_bridge_host_impl.cc100
-rw-r--r--chromium/components/arc/session/arc_bridge_host_impl.h2
-rw-r--r--chromium/components/arc/session/arc_bridge_service.cc100
-rw-r--r--chromium/components/arc/session/arc_bridge_service.h4
-rw-r--r--chromium/components/arc/session/arc_data_remover.cc2
-rw-r--r--chromium/components/arc/session/arc_data_remover.h2
-rw-r--r--chromium/components/arc/session/arc_data_remover_unittest.cc4
-rw-r--r--chromium/components/arc/session/arc_session_impl.cc23
-rw-r--r--chromium/components/arc/session/arc_session_impl.h2
-rw-r--r--chromium/components/arc/session/arc_session_impl_unittest.cc4
-rw-r--r--chromium/components/arc/session/arc_session_runner.cc3
-rw-r--r--chromium/components/arc/session/arc_session_runner.h2
-rw-r--r--chromium/components/arc/session/arc_session_runner_unittest.cc7
-rw-r--r--chromium/components/arc/session/arc_vm_client_adapter.cc217
-rw-r--r--chromium/components/arc/session/arc_vm_client_adapter_unittest.cc303
-rw-r--r--chromium/components/arc/session/connection_holder.h4
-rw-r--r--chromium/components/arc/storage_manager/arc_storage_manager.h2
-rw-r--r--chromium/components/arc/timer/OWNERS6
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge.cc6
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge.h4
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge_unittest.cc10
-rw-r--r--chromium/components/arc/timer/arc_timer_mojom_traits.cc (renamed from chromium/components/arc/timer/arc_timer_struct_traits.cc)2
-rw-r--r--chromium/components/arc/timer/arc_timer_mojom_traits.h (renamed from chromium/components/arc/timer/arc_timer_struct_traits.h)8
-rw-r--r--chromium/components/arc/usb/usb_host_bridge.cc22
-rw-r--r--chromium/components/arc/usb/usb_host_bridge.h11
-rw-r--r--chromium/components/arc/video_accelerator/BUILD.gn2
-rw-r--r--chromium/components/arc/video_accelerator/DEPS2
-rw-r--r--chromium/components/arc/video_accelerator/OWNERS1
-rw-r--r--chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc149
-rw-r--r--chromium/components/arc/video_accelerator/arc_video_accelerator_util.h18
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc97
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h6
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc163
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h2
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h2
-rw-r--r--chromium/components/arc/video_accelerator/protected_buffer_manager.cc1
-rw-r--r--chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h2
-rw-r--r--chromium/components/arc/volume_mounter/OWNERS6
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc70
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h17
-rw-r--r--chromium/components/arc/volume_mounter/volume_mounter_mojom_traits.cc (renamed from chromium/components/arc/volume_mounter/volume_mounter_struct_traits.cc)2
-rw-r--r--chromium/components/arc/volume_mounter/volume_mounter_mojom_traits.h (renamed from chromium/components/arc/volume_mounter/volume_mounter_struct_traits.h)8
-rw-r--r--chromium/components/arc/wake_lock/arc_wake_lock_bridge.cc16
-rw-r--r--chromium/components/arc/wake_lock/arc_wake_lock_bridge.h4
-rw-r--r--chromium/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc9
-rw-r--r--chromium/components/assist_ranker/OWNERS1
-rw-r--r--chromium/components/assist_ranker/base_predictor_unittest.cc4
-rw-r--r--chromium/components/assist_ranker/ranker_model_loader_impl.cc5
-rw-r--r--chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc6
-rw-r--r--chromium/components/assist_ranker/ranker_url_fetcher.cc3
-rw-r--r--chromium/components/autofill/DEPS2
-rw-r--r--chromium/components/autofill/android/java/strings/translations/autofill_strings_mr.xtb2
-rw-r--r--chromium/components/autofill/content/browser/autofill_internals_log_router_unittest.cc4
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc18
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h8
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.cc5
-rw-r--r--chromium/components/autofill/content/common/mojom/BUILD.gn2
-rw-r--r--chromium/components/autofill/content/common/mojom/autofill_driver.mojom5
-rw-r--r--chromium/components/autofill/content/renderer/BUILD.gn1
-rw-r--r--chromium/components/autofill/content/renderer/DEPS1
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc21
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.h2
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector.cc35
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector.h11
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc285
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.h40
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc88
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.h13
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc143
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc57
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.h9
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn13
-rw-r--r--chromium/components/autofill/core/browser/DEPS1
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl.cc5
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc10
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css29
-rw-r--r--chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.html26
-rw-r--r--chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js24
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.h2
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant_unittest.cc10
-rw-r--r--chromium/components/autofill/core/browser/autofill_browser_util.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_browser_util.h26
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h12
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc9
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.cc120
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.h7
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc23
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver.h10
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc14
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments_unittest.cc25
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc15
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.h2
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.cc7
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.h5
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler_proxy.cc3
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler_proxy.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc170
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h42
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc381
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc30
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h30
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc7
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_type.cc11
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc49
-rw-r--r--chromium/components/autofill/core/browser/data_model/phone_number_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/field_filler_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.cc25
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.h8
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer_unittest.cc97
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/address_field.cc90
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/address_field.h10
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/address_field_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/credit_card_field.cc71
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/credit_card_field.h11
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/credit_card_field_unittest.cc5
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/email_field.cc6
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/email_field.h5
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/form_field.cc85
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/form_field.h31
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/name_field.cc61
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/name_field.h4
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/name_field_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/phone_field.cc51
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/phone_field.h11
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/phone_field_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/price_field.cc5
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/price_field.h4
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/price_field_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/search_field.cc5
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/search_field.h4
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/search_field_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/travel_field.cc14
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/travel_field.h5
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc88
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h27
-rw-r--r--chromium/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc18
-rw-r--r--chromium/components/autofill/core/browser/geo/subkey_requester_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/logging/log_buffer.cc144
-rw-r--r--chromium/components/autofill/core/browser/logging/log_buffer.h86
-rw-r--r--chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc166
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc3
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc103
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h77
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc253
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc19
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h2
-rw-r--r--chromium/components/autofill/core/browser/payments/card_unmask_delegate.cc8
-rw-r--r--chromium/components/autofill/core/browser/payments/card_unmask_delegate.h14
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc115
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager.h31
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc229
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc19
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h33
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc17
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc421
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h148
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc383
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc23
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager.h5
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc517
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.cc37
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.h16
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc141
-rw-r--r--chromium/components/autofill/core/browser/payments/legal_message_line_unittest.cc26
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc13
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc175
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.h46
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client_unittest.cc226
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_util.cc18
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_util.h6
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_util_unittest.cc28
-rw-r--r--chromium/components/autofill/core/browser/payments/strike_database.cc4
-rw-r--r--chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/payments/strike_database_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/payments/test_authentication_requester.cc10
-rw-r--r--chromium/components/autofill/core/browser/payments/test_authentication_requester.h5
-rw-r--r--chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc69
-rw-r--r--chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h27
-rw-r--r--chromium/components/autofill/core/browser/payments/test_legal_message_line.h44
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.cc45
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.h4
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc22
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc70
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc5
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h8
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.cc14
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.h11
-rw-r--r--chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc24
-rw-r--r--chromium/components/autofill/core/browser/ui/accessory_sheet_data.h11
-rw-r--r--chromium/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/DEPS5
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.cc3
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc3
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h9
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc21
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h11
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc82
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/save_card_bubble_controller.h105
-rw-r--r--chromium/components/autofill/core/browser/ui/suggestion_selection.cc15
-rw-r--r--chromium/components/autofill/core/browser/ui/suggestion_selection.h2
-rw-r--r--chromium/components/autofill/core/browser/ui/suggestion_selection_unittest.cc122
-rw-r--r--chromium/components/autofill/core/browser/validation.cc10
-rw-r--r--chromium/components/autofill/core/browser/validation.h6
-rw-r--r--chromium/components/autofill/core/browser/validation_unittest.cc79
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h7
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc136
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h88
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc26
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h9
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h7
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc31
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h16
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc808
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h162
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc1366
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc36
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h11
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc161
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc50
-rw-r--r--chromium/components/autofill/core/common/autofill_features.cc23
-rw-r--r--chromium/components/autofill/core/common/autofill_features.h4
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/log_message.h5
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/logging_scope.h4
-rw-r--r--chromium/components/autofill/core/common/autofill_payments_features.cc35
-rw-r--r--chromium/components/autofill/core/common/autofill_payments_features.h6
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.cc14
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.h5
-rw-r--r--chromium/components/autofill/core/common/autofill_regex_constants.cc6
-rw-r--r--chromium/components/autofill/core/common/autofill_regex_constants.h8
-rw-r--r--chromium/components/autofill/core/common/autofill_regexes.cc15
-rw-r--r--chromium/components/autofill/core/common/autofill_regexes.h4
-rw-r--r--chromium/components/autofill/core/common/form_field_data.h7
-rw-r--r--chromium/components/autofill/core/common/mojom/BUILD.gn2
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types.mojom2
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types.typemap26
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc2
-rw-r--r--chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc4
-rw-r--r--chromium/components/autofill/core/common/password_form.cc19
-rw-r--r--chromium/components/autofill/core/common/password_form.h18
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.cc9
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data_unittest.cc35
-rw-r--r--chromium/components/autofill/core/common/password_generation_util.cc5
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc57
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.h25
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.mm15
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent_unittests.mm45
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.h1
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.mm6
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm2
-rw-r--r--chromium/components/autofill/ios/browser/autofill_util.h9
-rw-r--r--chromium/components/autofill/ios/browser/autofill_util.mm4
-rw-r--r--chromium/components/autofill/ios/browser/fake_autofill_agent.mm30
-rw-r--r--chromium/components/autofill/ios/browser/fake_js_autofill_manager.mm18
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.h1
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm1
-rw-r--r--chromium/components/autofill/ios/form_util/test_form_activity_tab_helper.mm1
-rw-r--r--chromium/components/autofill_assistant/OWNERS1
-rw-r--r--chromium/components/autofill_assistant/browser/BUILD.gn39
-rw-r--r--chromium/components/autofill_assistant/browser/DEPS1
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_delegate.h19
-rw-r--r--chromium/components/autofill_assistant/browser/actions/autofill_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/autofill_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/autofill_action_unittest.cc117
-rw-r--r--chromium/components/autofill_assistant/browser/actions/click_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/click_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc609
-rw-r--r--chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h93
-rw-r--r--chromium/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc487
-rw-r--r--chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc8
-rw-r--r--chromium/components/autofill_assistant/browser/actions/focus_element_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/focus_element_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/get_payment_information_action.cc362
-rw-r--r--chromium/components/autofill_assistant/browser/actions/get_payment_information_action.h67
-rw-r--r--chromium/components/autofill_assistant/browser/actions/highlight_element_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/highlight_element_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h25
-rw-r--r--chromium/components/autofill_assistant/browser/actions/prompt_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/prompt_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc8
-rw-r--r--chromium/components/autofill_assistant/browser/actions/select_option_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/select_option_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_attribute_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_attribute_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.cc256
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.h51
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc226
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc125
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_form_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_form_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/upload_dom_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/upload_dom_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_dom_action_unittest.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/batch_element_checker.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/batch_element_checker.h4
-rw-r--r--chromium/components/autofill_assistant/browser/batch_element_checker_unittest.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/client.h4
-rw-r--r--chromium/components/autofill_assistant/browser/client_memory.cc32
-rw-r--r--chromium/components/autofill_assistant/browser/client_memory.h32
-rw-r--r--chromium/components/autofill_assistant/browser/client_settings.cc21
-rw-r--r--chromium/components/autofill_assistant/browser/client_settings.h23
-rw-r--r--chromium/components/autofill_assistant/browser/client_status.cc8
-rw-r--r--chromium/components/autofill_assistant/browser/controller.cc216
-rw-r--r--chromium/components/autofill_assistant/browser/controller.h36
-rw-r--r--chromium/components/autofill_assistant/browser/controller_observer.cc9
-rw-r--r--chromium/components/autofill_assistant/browser/controller_observer.h16
-rw-r--r--chromium/components/autofill_assistant/browser/controller_unittest.cc273
-rw-r--r--chromium/components/autofill_assistant/browser/details.cc43
-rw-r--r--chromium/components/autofill_assistant/browser/details.h4
-rw-r--r--chromium/components/autofill_assistant/browser/details_unittest.cc245
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_cc.template16
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_h.template9
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_client.cc51
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_client.h16
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/message_dispatcher.h16
-rw-r--r--chromium/components/autofill_assistant/browser/element_area.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/element_area.h2
-rw-r--r--chromium/components/autofill_assistant/browser/element_area_unittest.cc14
-rw-r--r--chromium/components/autofill_assistant/browser/element_precondition.cc3
-rw-r--r--chromium/components/autofill_assistant/browser/element_precondition.h2
-rw-r--r--chromium/components/autofill_assistant/browser/element_precondition_unittest.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc14
-rw-r--r--chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h14
-rw-r--r--chromium/components/autofill_assistant/browser/metrics.cc42
-rw-r--r--chromium/components/autofill_assistant/browser/metrics.h40
-rw-r--r--chromium/components/autofill_assistant/browser/mock_controller_observer.h7
-rw-r--r--chromium/components/autofill_assistant/browser/mock_personal_data_manager.cc13
-rw-r--r--chromium/components/autofill_assistant/browser/mock_personal_data_manager.h32
-rw-r--r--chromium/components/autofill_assistant/browser/mock_website_login_fetcher.cc12
-rw-r--r--chromium/components/autofill_assistant/browser/mock_website_login_fetcher.h46
-rw-r--r--chromium/components/autofill_assistant/browser/payment_request.cc18
-rw-r--r--chromium/components/autofill_assistant/browser/protocol_utils.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/retry_timer.cc3
-rw-r--r--chromium/components/autofill_assistant/browser/retry_timer.h2
-rw-r--r--chromium/components/autofill_assistant/browser/retry_timer_unittest.cc11
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor.cc50
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor.h19
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor_delegate.h10
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor_unittest.cc26
-rw-r--r--chromium/components/autofill_assistant/browser/script_precondition.h2
-rw-r--r--chromium/components/autofill_assistant/browser/script_precondition_unittest.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/script_tracker.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/script_tracker.h2
-rw-r--r--chromium/components/autofill_assistant/browser/script_tracker_unittest.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/self_delete_full_card_requester.cc3
-rw-r--r--chromium/components/autofill_assistant/browser/self_delete_full_card_requester.h2
-rw-r--r--chromium/components/autofill_assistant/browser/service.proto106
-rw-r--r--chromium/components/autofill_assistant/browser/service_impl.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/ui_delegate.h57
-rw-r--r--chromium/components/autofill_assistant/browser/user_data.cc25
-rw-r--r--chromium/components/autofill_assistant/browser/user_data.h (renamed from chromium/components/autofill_assistant/browser/payment_request.h)47
-rw-r--r--chromium/components/autofill_assistant/browser/web/element_finder.cc422
-rw-r--r--chromium/components/autofill_assistant/browser/web/element_finder.h102
-rw-r--r--chromium/components/autofill_assistant/browser/web/element_position_getter.cc171
-rw-r--r--chromium/components/autofill_assistant/browser/web/element_position_getter.h83
-rw-r--r--chromium/components/autofill_assistant/browser/web/mock_web_controller.cc (renamed from chromium/components/autofill_assistant/browser/mock_web_controller.cc)2
-rw-r--r--chromium/components/autofill_assistant/browser/web/mock_web_controller.h (renamed from chromium/components/autofill_assistant/browser/mock_web_controller.h)8
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller.cc (renamed from chromium/components/autofill_assistant/browser/web_controller.cc)899
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller.h (renamed from chromium/components/autofill_assistant/browser/web_controller.h)123
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc (renamed from chromium/components/autofill_assistant/browser/web_controller_browsertest.cc)24
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller_util.cc84
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller_util.h70
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller_worker.h27
-rw-r--r--chromium/components/autofill_assistant/browser/website_login_fetcher.cc16
-rw-r--r--chromium/components/autofill_assistant/browser/website_login_fetcher.h51
-rw-r--r--chromium/components/autofill_assistant/browser/website_login_fetcher_impl.cc176
-rw-r--r--chromium/components/autofill_assistant/browser/website_login_fetcher_impl.h54
-rw-r--r--chromium/components/autofill_payments_strings.grdp52
-rw-r--r--chromium/components/background_task_scheduler/BUILD.gn21
-rw-r--r--chromium/components/background_task_scheduler/README.md70
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskBroadcastReceiver.java26
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskFactory.java18
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java19
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java13
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskReflection.java73
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManager.java88
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java10
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java19
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerFactory.java34
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java148
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java121
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java152
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java244
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java28
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverter.java214
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java4
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java508
-rw-r--r--chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/scheduled_task.proto65
-rw-r--r--chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplWithMockTest.java82
-rw-r--r--chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java79
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java229
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java147
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManagerTest.java52
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java155
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java91
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java158
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java52
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverterTest.java244
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java178
-rw-r--r--chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TestBackgroundTaskFactory.java19
-rw-r--r--chromium/components/background_task_scheduler/android/proguard.flags10
-rw-r--r--chromium/components/base32/OWNERS2
-rw-r--r--chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h7
-rw-r--r--chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc4
-rw-r--r--chromium/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc4
-rw-r--r--chromium/components/bookmark_component_strings.grdp2
-rw-r--r--chromium/components/bookmarks/browser/bookmark_codec.cc34
-rw-r--r--chromium/components/bookmarks/browser/bookmark_codec.h12
-rw-r--r--chromium/components/bookmarks/browser/bookmark_codec_unittest.cc195
-rw-r--r--chromium/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc4
-rw-r--r--chromium/components/bookmarks/browser/bookmark_model.cc18
-rw-r--r--chromium/components/bookmarks/browser/bookmark_model_unittest.cc10
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node.cc44
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node.h32
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node_data.cc8
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node_data.h4
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node_data_ios.cc2
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node_data_mac.mm8
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc17
-rw-r--r--chromium/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm4
-rw-r--r--chromium/components/bookmarks/browser/bookmark_storage.cc5
-rw-r--r--chromium/components/bookmarks/browser/bookmark_storage.h5
-rw-r--r--chromium/components/bookmarks/browser/bookmark_utils.cc62
-rw-r--r--chromium/components/bookmarks/browser/bookmark_utils.h10
-rw-r--r--chromium/components/bookmarks/browser/bookmark_utils_unittest.cc13
-rw-r--r--chromium/components/bookmarks/browser/url_index.cc5
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc5
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc4
-rw-r--r--chromium/components/browser_sync/OWNERS2
-rw-r--r--chromium/components/browser_sync/browser_sync_client.h5
-rw-r--r--chromium/components/browser_sync/browser_sync_switches.cc5
-rw-r--r--chromium/components/browser_sync/browser_sync_switches.h7
-rw-r--r--chromium/components/browser_sync/profile_sync_components_factory_impl.cc60
-rw-r--r--chromium/components/browser_sync/profile_sync_components_factory_impl.h8
-rw-r--r--chromium/components/browser_sync/profile_sync_service_bookmark_unittest.cc3
-rw-r--r--chromium/components/browser_watcher/watcher_metrics_provider_win.cc7
-rw-r--r--chromium/components/browser_watcher/watcher_metrics_provider_win.h2
-rw-r--r--chromium/components/browser_watcher/watcher_metrics_provider_win_unittest.cc6
-rw-r--r--chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc5
-rw-r--r--chromium/components/browsing_data/content/conditional_cache_counting_helper.cc185
-rw-r--r--chromium/components/browsing_data/content/conditional_cache_counting_helper.h50
-rw-r--r--chromium/components/browsing_data/core/BUILD.gn2
-rw-r--r--chromium/components/browsing_data/core/browsing_data_utils_unittest.cc4
-rw-r--r--chromium/components/browsing_data/core/counters/browsing_data_counter_unittest.cc4
-rw-r--r--chromium/components/browsing_data/core/features.cc14
-rw-r--r--chromium/components/browsing_data/core/features.h19
-rw-r--r--chromium/components/browsing_data/core/history_notice_utils_unittest.cc4
-rw-r--r--chromium/components/browsing_data_strings_grdp/OWNERS1
-rw-r--r--chromium/components/captive_portal/OWNERS1
-rw-r--r--chromium/components/captive_portal/captive_portal_detector.cc2
-rw-r--r--chromium/components/captive_portal/captive_portal_detector_unittest.cc4
-rw-r--r--chromium/components/cast_certificate/cast_cert_validator.cc5
-rw-r--r--chromium/components/cast_certificate/cast_crl.cc5
-rw-r--r--chromium/components/cast_channel/cast_message_handler_unittest.cc17
-rw-r--r--chromium/components/cast_channel/cast_message_util.cc4
-rw-r--r--chromium/components/cast_channel/cast_message_util.h2
-rw-r--r--chromium/components/cast_channel/cast_socket.cc15
-rw-r--r--chromium/components/cast_channel/cast_socket_service.cc4
-rw-r--r--chromium/components/cast_channel/cast_socket_service_unittest.cc5
-rw-r--r--chromium/components/cast_channel/cast_socket_unittest.cc6
-rw-r--r--chromium/components/cast_channel/cast_transport_unittest.cc4
-rw-r--r--chromium/components/cast_channel/keep_alive_delegate_unittest.cc4
-rw-r--r--chromium/components/cbor/OWNERS2
-rw-r--r--chromium/components/cdm/browser/BUILD.gn2
-rw-r--r--chromium/components/cdm/browser/cdm_message_filter_android.cc5
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl.cc3
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl.h4
-rw-r--r--chromium/components/cdm/renderer/widevine_key_system_properties.cc24
-rw-r--r--chromium/components/certificate_transparency/chrome_ct_policy_enforcer.h13
-rw-r--r--chromium/components/certificate_transparency/chrome_require_ct_delegate_unittest.cc6
-rw-r--r--chromium/components/certificate_transparency/data/log_list.json257
-rw-r--r--chromium/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap6
-rw-r--r--chromium/components/chromeos_camera/BUILD.gn25
-rw-r--r--chromium/components/chromeos_camera/OWNERS3
-rw-r--r--chromium/components/chromeos_camera/common/BUILD.gn8
-rw-r--r--chromium/components/chromeos_camera/common/dmabuf.mojom27
-rw-r--r--chromium/components/chromeos_camera/common/jpeg_encode_accelerator.mojom10
-rw-r--r--chromium/components/chromeos_camera/common/jpeg_encode_accelerator.typemap2
-rw-r--r--chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.mojom16
-rw-r--r--chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.typemap4
-rw-r--r--chromium/components/chromeos_camera/dmabuf_utils.cc67
-rw-r--r--chromium/components/chromeos_camera/dmabuf_utils.h30
-rw-r--r--chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.cc36
-rw-r--r--chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.h15
-rw-r--r--chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc162
-rw-r--r--chromium/components/chromeos_camera/mjpeg_decode_accelerator.h74
-rw-r--r--chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc527
-rw-r--r--chromium/components/chromeos_camera/mojo_jpeg_encode_accelerator_service.cc99
-rw-r--r--chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.cc33
-rw-r--r--chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h5
-rw-r--r--chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.cc142
-rw-r--r--chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.h17
-rw-r--r--chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service_unittest.cc10
-rw-r--r--chromium/components/cloud_devices/common/cloud_device_description.cc4
-rw-r--r--chromium/components/cloud_devices/common/printer_description_unittest.cc1218
-rw-r--r--chromium/components/component_updater/OWNERS1
-rw-r--r--chromium/components/component_updater/component_installer.cc4
-rw-r--r--chromium/components/component_updater/component_installer_unittest.cc11
-rw-r--r--chromium/components/component_updater/component_updater_service_unittest.cc6
-rw-r--r--chromium/components/component_updater/crl_set_remover.cc5
-rw-r--r--chromium/components/component_updater/timer_unittest.cc8
-rw-r--r--chromium/components/components_chromium_strings.grd16
-rw-r--r--chromium/components/components_google_chrome_strings.grd16
-rw-r--r--chromium/components/components_strings.grd2
-rw-r--r--chromium/components/consent_auditor/consent_sync_bridge_impl_unittest.cc4
-rw-r--r--chromium/components/constrained_window/constrained_window_views.cc8
-rw-r--r--chromium/components/content_capture/common/BUILD.gn6
-rw-r--r--chromium/components/content_capture/common/OWNERS4
-rw-r--r--chromium/components/content_capture/common/content_capture.typemap10
-rw-r--r--chromium/components/content_capture/common/content_capture_data.mojom2
-rw-r--r--chromium/components/content_capture/common/content_capture_mojom_traits.cc (renamed from chromium/components/content_capture/common/content_capture_struct_traits.cc)4
-rw-r--r--chromium/components/content_capture/common/content_capture_mojom_traits.h (renamed from chromium/components/content_capture/common/content_capture_struct_traits.h)6
-rw-r--r--chromium/components/content_capture/common/content_capture_mojom_traits_unittest.cc (renamed from chromium/components/content_capture/common/content_capture_struct_traits_unittest.cc)4
-rw-r--r--chromium/components/content_settings/core/browser/BUILD.gn1
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_registry.cc22
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings.cc61
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings.h32
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings_policy_handler.cc4
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc13
-rw-r--r--chromium/components/content_settings/core/browser/cookie_settings_unittest.cc270
-rw-r--r--chromium/components/content_settings/core/common/BUILD.gn21
-rw-r--r--chromium/components/content_settings/core/common/DEPS1
-rw-r--r--chromium/components/content_settings/core/common/OWNERS4
-rw-r--r--chromium/components/content_settings/core/common/content_settings.cc1
-rw-r--r--chromium/components/content_settings/core/common/content_settings.typemap4
-rw-r--r--chromium/components/content_settings/core/common/content_settings_mojom_traits.cc (renamed from chromium/components/content_settings/core/common/content_settings_struct_traits.cc)2
-rw-r--r--chromium/components/content_settings/core/common/content_settings_mojom_traits.h (renamed from chromium/components/content_settings/core/common/content_settings_struct_traits.h)6
-rw-r--r--chromium/components/content_settings/core/common/content_settings_types.h5
-rw-r--r--chromium/components/content_settings/core/common/cookie_settings_base.cc68
-rw-r--r--chromium/components/content_settings/core/common/cookie_settings_base.h91
-rw-r--r--chromium/components/content_settings/core/common/cookie_settings_base_unittest.cc49
-rw-r--r--chromium/components/content_settings/core/common/features.h3
-rw-r--r--chromium/components/content_settings/core/common/pref_names.cc7
-rw-r--r--chromium/components/content_settings/core/common/pref_names.h2
-rw-r--r--chromium/components/contextual_search/core/browser/public.cc1
-rw-r--r--chromium/components/contextual_search/core/browser/public.h1
-rw-r--r--chromium/components/crash/content/app/BUILD.gn46
-rw-r--r--chromium/components/crash/content/app/breakpad_linux.cc33
-rw-r--r--chromium/components/crash/content/app/breakpad_linux.h7
-rw-r--r--chromium/components/crash/content/app/chrome_crashpad_handler.cc19
-rw-r--r--chromium/components/crash/content/app/crashpad.h4
-rw-r--r--chromium/components/crash/content/app/crashpad_android.cc51
-rw-r--r--chromium/components/crash/content/app/crashpad_mac.mm5
-rw-r--r--chromium/components/crash/content/app/crashpad_win.cc5
-rw-r--r--chromium/components/crash/content/browser/child_process_crash_observer_android.cc4
-rw-r--r--chromium/components/crash/content/browser/crash_handler_host_linux.cc9
-rw-r--r--chromium/components/crash/content/browser/crash_memory_metrics_collector_android.cc11
-rw-r--r--chromium/components/crash/content/browser/crash_memory_metrics_collector_android.h5
-rw-r--r--chromium/components/crash/content/browser/crash_metrics_reporter_android_unittest.cc7
-rwxr-xr-xchromium/components/crash/content/tools/generate_breakpad_symbols.py14
-rw-r--r--chromium/components/crash/core/browser/crashes_ui_util.cc4
-rw-r--r--chromium/components/crash/core/browser/crashes_ui_util.h4
-rw-r--r--chromium/components/cronet/android/BUILD.gn124
-rw-r--r--chromium/components/cronet/ios/BUILD.gn2
-rw-r--r--chromium/components/crx_file/BUILD.gn1
-rw-r--r--chromium/components/crx_file/OWNERS1
-rw-r--r--chromium/components/crx_file/crx_verifier.cc107
-rw-r--r--chromium/components/crx_file/crx_verifier.h8
-rw-r--r--chromium/components/crx_file/crx_verifier_unittest.cc87
-rw-r--r--chromium/components/data_reduction_proxy/DEPS1
-rw-r--r--chromium/components/data_reduction_proxy/OWNERS2
-rw-r--r--chromium/components/data_reduction_proxy/content/DEPS1
-rw-r--r--chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc6
-rw-r--r--chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.h3
-rw-r--r--chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc23
-rw-r--r--chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc1
-rw-r--r--chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h6
-rw-r--r--chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc12
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/BUILD.gn9
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc569
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc387
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc18
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h11
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc29
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h10
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc29
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc12
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h7
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc21
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc7
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc440
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h274
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc105
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc15
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h4
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc12
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc343
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h178
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h17
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_unittest.cc (renamed from chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc)200
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc70
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h51
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc15
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc44
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc207
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h84
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc59
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h24
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc110
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc20
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc29
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc6
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc9
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h5
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc146
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h30
-rw-r--r--chromium/components/data_use_measurement/core/data_use_measurement.cc2
-rw-r--r--chromium/components/dbus/menu/BUILD.gn11
-rw-r--r--chromium/components/dbus/menu/DEPS2
-rw-r--r--chromium/components/dbus/menu/menu.cc251
-rw-r--r--chromium/components/dbus/menu/menu.h35
-rw-r--r--chromium/components/dbus/menu/menu_property_list.cc123
-rw-r--r--chromium/components/dbus/menu/menu_property_list.h35
-rw-r--r--chromium/components/dbus/menu/menu_property_list_unittest.cc361
-rw-r--r--chromium/components/dbus/menu/types.cc20
-rw-r--r--chromium/components/dbus/menu/types.h48
-rw-r--r--chromium/components/dbus/menu/types_unittest.cc63
-rw-r--r--chromium/components/discardable_memory/OWNERS2
-rw-r--r--chromium/components/discardable_memory/service/discardable_shared_memory_manager.cc6
-rw-r--r--chromium/components/discardable_memory/service/discardable_shared_memory_manager_unittest.cc6
-rw-r--r--chromium/components/dom_distiller/content/browser/distillability_driver.cc28
-rw-r--r--chromium/components/dom_distiller/content/browser/distillability_driver.h11
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils.cc13
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils.h23
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc47
-rw-r--r--chromium/components/dom_distiller/content/browser/distiller_javascript_utils.cc6
-rw-r--r--chromium/components/dom_distiller/content/browser/distiller_javascript_utils.h2
-rw-r--r--chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.cc2
-rw-r--r--chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.h3
-rw-r--r--chromium/components/dom_distiller/content/renderer/distillability_agent.cc72
-rw-r--r--chromium/components/dom_distiller/content/renderer/distillability_agent.h5
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc4
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h6
-rw-r--r--chromium/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DistilledPagePrefs.java15
-rw-r--r--chromium/components/dom_distiller/core/distilled_content_store_unittest.cc14
-rw-r--r--chromium/components/dom_distiller/core/distilled_page_prefs_android.cc4
-rw-r--r--chromium/components/dom_distiller/core/distilled_page_prefs_android.h4
-rw-r--r--chromium/components/dom_distiller/core/distilled_page_prefs_unittests.cc4
-rw-r--r--chromium/components/dom_distiller/core/distiller_unittest.cc6
-rw-r--r--chromium/components/dom_distiller/core/distiller_url_fetcher_unittest.cc7
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_features.cc7
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_features.h4
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service_android.cc4
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service_android.h4
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service_unittest.cc4
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc4
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_switches.cc5
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_switches.h5
-rw-r--r--chromium/components/dom_distiller/core/task_tracker_unittest.cc4
-rw-r--r--chromium/components/dom_distiller/ios/distiller_page_ios.mm2
-rw-r--r--chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc9
-rw-r--r--chromium/components/dom_distiller/webui/dom_distiller_ui.cc2
-rw-r--r--chromium/components/domain_reliability/OWNERS1
-rw-r--r--chromium/components/domain_reliability/quic_error_mapping.cc2
-rw-r--r--chromium/components/domain_reliability/uploader_unittest.cc6
-rw-r--r--chromium/components/download/content/factory/BUILD.gn1
-rw-r--r--chromium/components/download/content/factory/download_service_factory_helper.cc7
-rw-r--r--chromium/components/download/content/factory/download_service_factory_helper.h5
-rw-r--r--chromium/components/download/database/download_db_impl.cc44
-rw-r--r--chromium/components/download/database/download_db_impl.h18
-rw-r--r--chromium/components/download/database/download_db_impl_unittest.cc17
-rw-r--r--chromium/components/download/internal/background_service/blob_task_proxy.h2
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.cc8
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl.cc8
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_unittest.cc8
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc4
-rw-r--r--chromium/components/download/internal/background_service/stats.cc41
-rw-r--r--chromium/components/download/internal/common/BUILD.gn5
-rw-r--r--chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java13
-rw-r--r--chromium/components/download/internal/common/base_file.cc10
-rw-r--r--chromium/components/download/internal/common/download_db_cache.cc3
-rw-r--r--chromium/components/download/internal/common/download_db_cache_unittest.cc21
-rw-r--r--chromium/components/download/internal/common/download_file_impl.cc28
-rw-r--r--chromium/components/download/internal/common/download_file_unittest.cc7
-rw-r--r--chromium/components/download/internal/common/download_item_impl.cc83
-rw-r--r--chromium/components/download/internal/common/download_item_impl_delegate.cc5
-rw-r--r--chromium/components/download/internal/common/download_item_impl_unittest.cc85
-rw-r--r--chromium/components/download/internal/common/download_job.cc16
-rw-r--r--chromium/components/download/internal/common/download_job_factory.cc22
-rw-r--r--chromium/components/download/internal/common/download_job_impl.cc9
-rw-r--r--chromium/components/download/internal/common/download_job_impl.h7
-rw-r--r--chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc8
-rw-r--r--chromium/components/download/internal/common/download_response_handler.cc28
-rw-r--r--chromium/components/download/internal/common/download_stats.cc46
-rw-r--r--chromium/components/download/internal/common/download_ukm_helper_unittest.cc4
-rw-r--r--chromium/components/download/internal/common/download_url_loader_factory_getter.cc23
-rw-r--r--chromium/components/download/internal/common/download_url_loader_factory_getter_impl.cc25
-rw-r--r--chromium/components/download/internal/common/download_utils.cc16
-rw-r--r--chromium/components/download/internal/common/download_worker.cc42
-rw-r--r--chromium/components/download/internal/common/download_worker.h24
-rw-r--r--chromium/components/download/internal/common/in_progress_download_manager.cc120
-rw-r--r--chromium/components/download/internal/common/parallel_download_job.cc18
-rw-r--r--chromium/components/download/internal/common/parallel_download_job.h32
-rw-r--r--chromium/components/download/internal/common/parallel_download_job_unittest.cc101
-rw-r--r--chromium/components/download/internal/common/resource_downloader.cc47
-rw-r--r--chromium/components/download/internal/common/resource_downloader.h27
-rw-r--r--chromium/components/download/internal/common/save_package_download_job.cc4
-rw-r--r--chromium/components/download/internal/common/save_package_download_job.h3
-rw-r--r--chromium/components/download/internal/common/url_download_handler_factory.cc80
-rw-r--r--chromium/components/download/internal/common/url_download_request_handle.cc18
-rw-r--r--chromium/components/download/internal/common/url_loader_factory_provider.cc29
-rw-r--r--chromium/components/download/public/common/BUILD.gn9
-rw-r--r--chromium/components/download/public/common/base_file.h15
-rw-r--r--chromium/components/download/public/common/download_create_info.h7
-rw-r--r--chromium/components/download/public/common/download_features.cc4
-rw-r--r--chromium/components/download/public/common/download_file.h15
-rw-r--r--chromium/components/download/public/common/download_file_impl.h22
-rw-r--r--chromium/components/download/public/common/download_item_factory.h4
-rw-r--r--chromium/components/download/public/common/download_item_impl.h31
-rw-r--r--chromium/components/download/public/common/download_item_impl_delegate.h6
-rw-r--r--chromium/components/download/public/common/download_job.h13
-rw-r--r--chromium/components/download/public/common/download_job_factory.h18
-rw-r--r--chromium/components/download/public/common/download_request_handle_interface.h29
-rw-r--r--chromium/components/download/public/common/download_response_handler.h7
-rw-r--r--chromium/components/download/public/common/download_stats.h13
-rw-r--r--chromium/components/download/public/common/download_url_loader_factory_getter.h57
-rw-r--r--chromium/components/download/public/common/download_url_loader_factory_getter_impl.h39
-rw-r--r--chromium/components/download/public/common/download_url_parameters.cc3
-rw-r--r--chromium/components/download/public/common/download_url_parameters.h9
-rw-r--r--chromium/components/download/public/common/download_utils.h2
-rw-r--r--chromium/components/download/public/common/in_progress_download_manager.h66
-rw-r--r--chromium/components/download/public/common/input_stream.cc13
-rw-r--r--chromium/components/download/public/common/input_stream.h7
-rw-r--r--chromium/components/download/public/common/mock_download_file.h15
-rw-r--r--chromium/components/download/public/common/mock_download_item_impl.h17
-rw-r--r--chromium/components/download/public/common/quarantine_connection.h21
-rw-r--r--chromium/components/download/public/common/url_download_handler.h9
-rw-r--r--chromium/components/download/public/common/url_download_handler_factory.h31
-rw-r--r--chromium/components/download/public/common/url_download_request_handle.h11
-rw-r--r--chromium/components/download/public/common/url_loader_factory_provider.h40
-rw-r--r--chromium/components/error_page/common/localized_error.cc6
-rw-r--r--chromium/components/error_page_strings.grdp3
-rw-r--r--chromium/components/exo/BUILD.gn6
-rw-r--r--chromium/components/exo/DEPS2
-rw-r--r--chromium/components/exo/OWNERS1
-rw-r--r--chromium/components/exo/buffer.cc8
-rw-r--r--chromium/components/exo/client_controlled_shell_surface.cc50
-rw-r--r--chromium/components/exo/client_controlled_shell_surface.h4
-rw-r--r--chromium/components/exo/client_controlled_shell_surface_unittest.cc17
-rw-r--r--chromium/components/exo/data_device.cc45
-rw-r--r--chromium/components/exo/data_device.h13
-rw-r--r--chromium/components/exo/data_offer.cc101
-rw-r--r--chromium/components/exo/data_offer.h17
-rw-r--r--chromium/components/exo/data_offer_unittest.cc101
-rw-r--r--chromium/components/exo/data_source.cc115
-rw-r--r--chromium/components/exo/data_source.h36
-rw-r--r--chromium/components/exo/data_source_delegate.h2
-rw-r--r--chromium/components/exo/data_source_unittest.cc33
-rw-r--r--chromium/components/exo/display.cc5
-rw-r--r--chromium/components/exo/drag_drop_operation.cc306
-rw-r--r--chromium/components/exo/drag_drop_operation.h129
-rw-r--r--chromium/components/exo/fullscreen_shell_surface.cc37
-rw-r--r--chromium/components/exo/fullscreen_shell_surface.h14
-rw-r--r--chromium/components/exo/fullscreen_shell_surface_unittest.cc85
-rw-r--r--chromium/components/exo/gamepad_delegate.h11
-rw-r--r--chromium/components/exo/gaming_seat.cc5
-rw-r--r--chromium/components/exo/gaming_seat_unittest.cc6
-rw-r--r--chromium/components/exo/keyboard.cc3
-rw-r--r--chromium/components/exo/keyboard.h2
-rw-r--r--chromium/components/exo/mime_utils.cc5
-rw-r--r--chromium/components/exo/mime_utils.h2
-rw-r--r--chromium/components/exo/mime_utils_unittest.cc6
-rw-r--r--chromium/components/exo/pointer.cc14
-rw-r--r--chromium/components/exo/pointer.h7
-rw-r--r--chromium/components/exo/pointer_unittest.cc106
-rw-r--r--chromium/components/exo/seat.cc78
-rw-r--r--chromium/components/exo/seat.h30
-rw-r--r--chromium/components/exo/seat_unittest.cc89
-rw-r--r--chromium/components/exo/shell_surface_base.cc15
-rw-r--r--chromium/components/exo/surface.cc21
-rw-r--r--chromium/components/exo/surface.h20
-rw-r--r--chromium/components/exo/surface_unittest.cc49
-rw-r--r--chromium/components/exo/touch.cc6
-rw-r--r--chromium/components/exo/touch.h5
-rw-r--r--chromium/components/exo/touch_unittest.cc83
-rw-r--r--chromium/components/exo/vsync_timing_manager.h2
-rw-r--r--chromium/components/exo/wayland/BUILD.gn6
-rw-r--r--chromium/components/exo/wayland/DEPS2
-rw-r--r--chromium/components/exo/wayland/clients/blur_main.cc4
-rw-r--r--chromium/components/exo/wayland/clients/client_base.cc42
-rw-r--r--chromium/components/exo/wayland/clients/client_base.h2
-rw-r--r--chromium/components/exo/wayland/clients/explicit_synchronization.cc4
-rw-r--r--chromium/components/exo/wayland/clients/fullscreen_shell_main.cc4
-rw-r--r--chromium/components/exo/wayland/clients/rects.cc4
-rw-r--r--chromium/components/exo/wayland/clients/simple_main.cc4
-rw-r--r--chromium/components/exo/wayland/clients/subsurface.cc4
-rw-r--r--chromium/components/exo/wayland/clients/vulkan.cc5
-rw-r--r--chromium/components/exo/wayland/clients/yuv.cc4
-rw-r--r--chromium/components/exo/wayland/serial_tracker.cc82
-rw-r--r--chromium/components/exo/wayland/serial_tracker.h76
-rw-r--r--chromium/components/exo/wayland/server.cc29
-rw-r--r--chromium/components/exo/wayland/server.h13
-rw-r--r--chromium/components/exo/wayland/wayland_keyboard_delegate.cc28
-rw-r--r--chromium/components/exo/wayland/wayland_keyboard_delegate.h10
-rw-r--r--chromium/components/exo/wayland/wayland_pointer_delegate.cc30
-rw-r--r--chromium/components/exo/wayland/wayland_pointer_delegate.h10
-rw-r--r--chromium/components/exo/wayland/wayland_touch_delegate.cc26
-rw-r--r--chromium/components/exo/wayland/wayland_touch_delegate.h10
-rw-r--r--chromium/components/exo/wayland/wayland_watcher.cc2
-rw-r--r--chromium/components/exo/wayland/wayland_watcher.h8
-rw-r--r--chromium/components/exo/wayland/wl_compositor.cc6
-rw-r--r--chromium/components/exo/wayland/wl_data_device_manager.cc67
-rw-r--r--chromium/components/exo/wayland/wl_data_device_manager.h19
-rw-r--r--chromium/components/exo/wayland/wl_seat.cc19
-rw-r--r--chromium/components/exo/wayland/wl_seat.h18
-rw-r--r--chromium/components/exo/wayland/zaura_shell.cc22
-rw-r--r--chromium/components/exo/wayland/zaura_shell_unittest.cc20
-rw-r--r--chromium/components/exo/wayland/zcr_gaming_input.cc58
-rw-r--r--chromium/components/exo/wayland/zcr_notification_shell.cc5
-rw-r--r--chromium/components/exo/wayland/zcr_remote_shell.cc276
-rw-r--r--chromium/components/exo/wayland/zcr_remote_shell.h2
-rw-r--r--chromium/components/exo/wayland/zcr_remote_shell_unittest.cc18
-rw-r--r--chromium/components/exo/wayland/zwp_fullscreen_shell.cc24
-rw-r--r--chromium/components/exo/wayland/zwp_text_input_manager.cc52
-rw-r--r--chromium/components/exo/wayland/zwp_text_input_manager.h13
-rw-r--r--chromium/components/exo/wayland/zxdg_shell.cc188
-rw-r--r--chromium/components/exo/wayland/zxdg_shell.h18
-rw-r--r--chromium/components/favicon/core/BUILD.gn2
-rw-r--r--chromium/components/favicon/core/favicon_handler_unittest.cc7
-rw-r--r--chromium/components/favicon/core/favicon_server_fetcher_params.cc62
-rw-r--r--chromium/components/favicon/core/favicon_server_fetcher_params.h48
-rw-r--r--chromium/components/favicon/core/favicon_service_impl_unittest.cc4
-rw-r--r--chromium/components/favicon/core/history_ui_favicon_request_handler.h1
-rw-r--r--chromium/components/favicon/core/history_ui_favicon_request_handler_impl.cc75
-rw-r--r--chromium/components/favicon/core/history_ui_favicon_request_handler_impl.h17
-rw-r--r--chromium/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc252
-rw-r--r--chromium/components/favicon/core/large_icon_service.h4
-rw-r--r--chromium/components/favicon/core/large_icon_service_impl.cc46
-rw-r--r--chromium/components/favicon/core/large_icon_service_impl.h21
-rw-r--r--chromium/components/favicon/core/large_icon_service_impl_unittest.cc153
-rw-r--r--chromium/components/favicon/ios/web_favicon_driver.mm2
-rw-r--r--chromium/components/favicon_base/favicon_url_parser.cc105
-rw-r--r--chromium/components/favicon_base/favicon_url_parser.h47
-rw-r--r--chromium/components/favicon_base/favicon_url_parser_unittest.cc88
-rw-r--r--chromium/components/feature_engagement/README.md9
-rw-r--r--chromium/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java7
-rw-r--r--chromium/components/feature_engagement/internal/android/tracker_impl_android.cc4
-rw-r--r--chromium/components/feature_engagement/internal/android/tracker_impl_android.h2
-rw-r--r--chromium/components/feature_engagement/internal/in_memory_event_store_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/internal/never_availability_model_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/internal/tracker_impl_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/public/event_constants.cc3
-rw-r--r--chromium/components/feature_engagement/public/event_constants.h6
-rw-r--r--chromium/components/feature_engagement/public/feature_constants.cc8
-rw-r--r--chromium/components/feature_engagement/public/feature_constants.h3
-rw-r--r--chromium/components/feature_engagement/public/feature_list.cc3
-rw-r--r--chromium/components/feature_engagement/public/feature_list.h6
-rw-r--r--chromium/components/feed/content/feed_offline_host_unittest.cc6
-rw-r--r--chromium/components/feed/core/feed_content_database.cc149
-rw-r--r--chromium/components/feed/core/feed_content_database.h30
-rw-r--r--chromium/components/feed/core/feed_content_database_unittest.cc109
-rw-r--r--chromium/components/feed/core/feed_content_mutation.cc2
-rw-r--r--chromium/components/feed/core/feed_content_mutation.h2
-rw-r--r--chromium/components/feed/core/feed_content_mutation_unittest.cc8
-rw-r--r--chromium/components/feed/core/feed_image_manager_unittest.cc6
-rw-r--r--chromium/components/feed/core/feed_journal_database.cc139
-rw-r--r--chromium/components/feed/core/feed_journal_database.h39
-rw-r--r--chromium/components/feed/core/feed_journal_database_unittest.cc118
-rw-r--r--chromium/components/feed/core/feed_journal_mutation.cc2
-rw-r--r--chromium/components/feed/core/feed_journal_mutation.h2
-rw-r--r--chromium/components/feed/core/feed_journal_mutation_unittest.cc6
-rw-r--r--chromium/components/feed/core/feed_networking_host.cc2
-rw-r--r--chromium/components/feed/core/feed_networking_host_unittest.cc27
-rw-r--r--chromium/components/feedback/anonymizer_tool.cc216
-rw-r--r--chromium/components/feedback/anonymizer_tool.h40
-rw-r--r--chromium/components/feedback/anonymizer_tool_unittest.cc547
-rw-r--r--chromium/components/feedback/feedback_data.cc15
-rw-r--r--chromium/components/feedback/feedback_data_unittest.cc4
-rw-r--r--chromium/components/feedback/feedback_report.cc15
-rw-r--r--chromium/components/feedback/feedback_report.h19
-rw-r--r--chromium/components/feedback/feedback_uploader.cc22
-rw-r--r--chromium/components/feedback/feedback_uploader.h6
-rw-r--r--chromium/components/feedback/feedback_uploader_dispatch_unittest.cc6
-rw-r--r--chromium/components/feedback/feedback_uploader_factory.cc4
-rw-r--r--chromium/components/feedback/feedback_uploader_unittest.cc15
-rw-r--r--chromium/components/feedback/system_logs/system_logs_fetcher.cc7
-rw-r--r--chromium/components/flags_strings.grdp121
-rw-r--r--chromium/components/flags_ui/feature_entry.h2
-rw-r--r--chromium/components/flags_ui/flags_state.cc1
-rw-r--r--chromium/components/flags_ui/flags_state.h5
-rw-r--r--chromium/components/flags_ui/flags_ui_constants.cc1
-rw-r--r--chromium/components/flags_ui/flags_ui_constants.h1
-rw-r--r--chromium/components/flags_ui/resources/flags.css6
-rw-r--r--chromium/components/flags_ui/resources/flags.html60
-rw-r--r--chromium/components/flags_ui/resources/flags.js55
-rw-r--r--chromium/components/gcm_driver/BUILD.gn4
-rw-r--r--chromium/components/gcm_driver/android/BUILD.gn1
-rw-r--r--chromium/components/gcm_driver/instance_id/BUILD.gn12
-rw-r--r--chromium/components/gcm_driver/instance_id/android/BUILD.gn3
-rw-r--r--chromium/components/google/OWNERS1
-rw-r--r--chromium/components/google/core/browser/BUILD.gn49
-rw-r--r--chromium/components/google/core/browser/DEPS7
-rw-r--r--chromium/components/google/core/browser/OWNERS2
-rw-r--r--chromium/components/google/core/browser/google_pref_names.cc17
-rw-r--r--chromium/components/google/core/browser/google_pref_names.h17
-rw-r--r--chromium/components/google/core/browser/google_url_tracker.cc226
-rw-r--r--chromium/components/google/core/browser/google_url_tracker.h137
-rw-r--r--chromium/components/google/core/browser/google_url_tracker_client.cc11
-rw-r--r--chromium/components/google/core/browser/google_url_tracker_client.h49
-rw-r--r--chromium/components/google/core/browser/google_url_tracker_unittest.cc360
-rw-r--r--chromium/components/google/core/common/BUILD.gn15
-rw-r--r--chromium/components/google/core/common/google_util.cc5
-rw-r--r--chromium/components/google/core/common/google_util.h2
-rw-r--r--chromium/components/google/core/common/google_util_unittest.cc (renamed from chromium/components/google/core/browser/google_util_unittest.cc)6
-rw-r--r--chromium/components/guest_os/BUILD.gn55
-rw-r--r--chromium/components/guest_os/DEPS9
-rw-r--r--chromium/components/guest_os/OWNERS1
-rw-r--r--chromium/components/guest_os/README.md2
-rw-r--r--chromium/components/guest_os/guest_os_engagement_metrics.cc227
-rw-r--r--chromium/components/guest_os/guest_os_engagement_metrics.h131
-rw-r--r--chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc220
-rw-r--r--chromium/components/guest_os/guest_os_prefs.cc43
-rw-r--r--chromium/components/guest_os/guest_os_prefs.h28
-rw-r--r--chromium/components/gwp_asan/BUILD.gn11
-rw-r--r--chromium/components/gwp_asan/OWNERS1
-rw-r--r--chromium/components/gwp_asan/buildflags/buildflags.gni5
-rw-r--r--chromium/components/gwp_asan/client/BUILD.gn5
-rw-r--r--chromium/components/gwp_asan/client/DEPS1
-rw-r--r--chromium/components/gwp_asan/client/guarded_page_allocator.cc25
-rw-r--r--chromium/components/gwp_asan/client/guarded_page_allocator.h4
-rw-r--r--chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc4
-rw-r--r--chromium/components/gwp_asan/client/sampling_state.h24
-rw-r--r--chromium/components/gwp_asan/common/allocator_state.h4
-rw-r--r--chromium/components/gwp_asan/common/crash_key_name.h2
-rw-r--r--chromium/components/gwp_asan/crash_handler/BUILD.gn24
-rw-r--r--chromium/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc6
-rw-r--r--chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc111
-rw-r--r--chromium/components/handoff/OWNERS2
-rw-r--r--chromium/components/heap_profiling/BUILD.gn1
-rw-r--r--chromium/components/heap_profiling/DEPS4
-rw-r--r--chromium/components/heap_profiling/OWNERS1
-rw-r--r--chromium/components/heap_profiling/client_connection_manager.cc65
-rw-r--r--chromium/components/heap_profiling/supervisor.cc35
-rw-r--r--chromium/components/heap_profiling/test_driver.cc23
-rw-r--r--chromium/components/history/core/browser/BUILD.gn6
-rw-r--r--chromium/components/history/core/browser/browsing_history_service.cc33
-rw-r--r--chromium/components/history/core/browser/browsing_history_service.h6
-rw-r--r--chromium/components/history/core/browser/browsing_history_service_unittest.cc23
-rw-r--r--chromium/components/history/core/browser/expire_history_backend_unittest.cc6
-rw-r--r--chromium/components/history/core/browser/history_backend.h1
-rw-r--r--chromium/components/history/core/browser/history_backend_unittest.cc4
-rw-r--r--chromium/components/history/core/browser/history_querying_unittest.cc4
-rw-r--r--chromium/components/history/core/browser/history_service.cc4
-rw-r--r--chromium/components/history/core/browser/history_service_unittest.cc8
-rw-r--r--chromium/components/history/core/browser/in_memory_database.cc11
-rw-r--r--chromium/components/history/core/browser/in_memory_history_backend.cc9
-rw-r--r--chromium/components/history/core/browser/in_memory_history_backend.h4
-rw-r--r--chromium/components/history/core/browser/sync/delete_directive_handler_unittest.cc4
-rw-r--r--chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc9
-rw-r--r--chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.h2
-rw-r--r--chromium/components/history/core/browser/sync/history_model_worker.cc89
-rw-r--r--chromium/components/history/core/browser/sync/history_model_worker.h55
-rw-r--r--chromium/components/history/core/browser/sync/history_model_worker_unittest.cc236
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_model_type_controller.cc10
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_model_type_controller.h2
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_bridge.cc4
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_bridge.h3
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc4
-rw-r--r--chromium/components/history/core/browser/thumbnail_database.cc1
-rw-r--r--chromium/components/history/core/browser/top_sites.h4
-rw-r--r--chromium/components/history/core/browser/top_sites_backend.cc4
-rw-r--r--chromium/components/history/core/browser/top_sites_cache.cc82
-rw-r--r--chromium/components/history/core/browser/top_sites_cache.h104
-rw-r--r--chromium/components/history/core/browser/top_sites_cache_unittest.cc133
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.cc63
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.h29
-rw-r--r--chromium/components/history/core/browser/top_sites_impl_unittest.cc51
-rw-r--r--chromium/components/history/core/browser/web_history_service.cc2
-rw-r--r--chromium/components/history/core/browser/web_history_service_unittest.cc4
-rw-r--r--chromium/components/image_fetcher/core/cache/image_cache.cc10
-rw-r--r--chromium/components/image_fetcher/core/cache/image_cache_unittest.cc4
-rw-r--r--chromium/components/image_fetcher/core/cache/image_data_store_disk_unittest.cc4
-rw-r--r--chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc14
-rw-r--r--chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc6
-rw-r--r--chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc6
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher.cc4
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc10
-rw-r--r--chromium/components/image_fetcher/core/image_fetcher_impl_unittest.cc6
-rw-r--r--chromium/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc6
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper.mm3
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm4
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm5
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm4
-rw-r--r--chromium/components/infobars/core/infobar_delegate.cc23
-rw-r--r--chromium/components/infobars/core/infobar_delegate.h15
-rw-r--r--chromium/components/keyed_service/OWNERS2
-rw-r--r--chromium/components/keyed_service/content/browser_context_keyed_service_factory.h2
-rw-r--r--chromium/components/keyed_service/core/refcounted_keyed_service.h2
-rw-r--r--chromium/components/language/content/browser/geo_language_model_unittest.cc13
-rw-r--r--chromium/components/language/content/browser/geo_language_provider.cc5
-rw-r--r--chromium/components/language/content/browser/geo_language_provider_unittest.cc23
-rw-r--r--chromium/components/language/content/browser/test_utils.cc17
-rw-r--r--chromium/components/language/content/browser/test_utils.h13
-rw-r--r--chromium/components/language/core/common/language_experiments.cc2
-rw-r--r--chromium/components/language_usage_metrics/OWNERS1
-rw-r--r--chromium/components/leveldb_proto/BUILD.gn4
-rw-r--r--chromium/components/leveldb_proto/OWNERS1
-rw-r--r--chromium/components/leveldb_proto/content/BUILD.gn21
-rw-r--r--chromium/components/leveldb_proto/content/proto_database_provider_factory.cc45
-rw-r--r--chromium/components/leveldb_proto/content/proto_database_provider_factory.h55
-rw-r--r--chromium/components/leveldb_proto/internal/leveldb_database.h3
-rw-r--r--chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h4
-rw-r--r--chromium/components/leveldb_proto/internal/proto_database_impl.h6
-rw-r--r--chromium/components/leveldb_proto/internal/proto_database_impl_unittest.cc6
-rw-r--r--chromium/components/leveldb_proto/internal/proto_database_selector.cc55
-rw-r--r--chromium/components/leveldb_proto/internal/proto_database_selector.h40
-rw-r--r--chromium/components/leveldb_proto/internal/proto_leveldb_wrapper.h3
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database.cc47
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database.h3
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database_client.cc31
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database_client.h70
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc17
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database_provider.h3
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database_unittest.cc8
-rw-r--r--chromium/components/leveldb_proto/internal/unique_proto_database.h3
-rw-r--r--chromium/components/leveldb_proto/internal/unique_proto_database_unittest.cc12
-rw-r--r--chromium/components/leveldb_proto/public/proto_database.h3
-rw-r--r--chromium/components/leveldb_proto/public/proto_database_provider.h7
-rw-r--r--chromium/components/leveldb_proto/public/shared_proto_database_client_list.cc4
-rw-r--r--chromium/components/leveldb_proto/public/shared_proto_database_client_list.h6
-rw-r--r--chromium/components/link_header_util/BUILD.gn13
-rw-r--r--chromium/components/link_header_util/OWNERS4
-rw-r--r--chromium/components/link_header_util/link_header_util_fuzzer.cc29
-rw-r--r--chromium/components/location/android/java/src/org/chromium/components/location/LocationUtils.java8
-rw-r--r--chromium/components/login/OWNERS2
-rw-r--r--chromium/components/login/localized_values_builder.cc19
-rw-r--r--chromium/components/login/localized_values_builder.h19
-rw-r--r--chromium/components/login/secure_module_util_chromeos.cc5
-rw-r--r--chromium/components/management_strings.grdp31
-rw-r--r--chromium/components/media_message_center/BUILD.gn5
-rw-r--r--chromium/components/media_message_center/media_controls_progress_view.cc188
-rw-r--r--chromium/components/media_message_center/media_controls_progress_view.h57
-rw-r--r--chromium/components/media_message_center/media_controls_progress_view_unittest.cc295
-rw-r--r--chromium/components/media_message_center/media_notification_background.cc66
-rw-r--r--chromium/components/media_message_center/media_notification_background.h21
-rw-r--r--chromium/components/media_message_center/media_notification_background_unittest.cc64
-rw-r--r--chromium/components/media_message_center/media_notification_container.h15
-rw-r--r--chromium/components/media_message_center/media_notification_controller.h19
-rw-r--r--chromium/components/media_message_center/media_notification_item.cc144
-rw-r--r--chromium/components/media_message_center/media_notification_item.h45
-rw-r--r--chromium/components/media_message_center/media_notification_util.cc13
-rw-r--r--chromium/components/media_message_center/media_notification_util.h8
-rw-r--r--chromium/components/media_message_center/media_notification_view.cc43
-rw-r--r--chromium/components/media_message_center/media_notification_view.h10
-rw-r--r--chromium/components/media_message_center/media_notification_view_unittest.cc215
-rw-r--r--chromium/components/metrics/BUILD.gn7
-rw-r--r--chromium/components/metrics/call_stack_profile_collector.h2
-rw-r--r--chromium/components/metrics/child_call_stack_profile_collector.h2
-rw-r--r--chromium/components/metrics/child_call_stack_profile_collector_unittest.cc4
-rw-r--r--chromium/components/metrics/cloned_install_detector.cc4
-rw-r--r--chromium/components/metrics/delegating_provider.cc13
-rw-r--r--chromium/components/metrics/delegating_provider.h3
-rw-r--r--chromium/components/metrics/drive_metrics_provider.cc4
-rw-r--r--chromium/components/metrics/field_trials_provider.cc19
-rw-r--r--chromium/components/metrics/field_trials_provider.h14
-rw-r--r--chromium/components/metrics/field_trials_provider_unittest.cc12
-rw-r--r--chromium/components/metrics/file_metrics_provider.cc6
-rw-r--r--chromium/components/metrics/gpu/gpu_metrics_provider.cc1
-rw-r--r--chromium/components/metrics/metrics_log.cc33
-rw-r--r--chromium/components/metrics/metrics_log_unittest.cc33
-rw-r--r--chromium/components/metrics/metrics_provider.cc5
-rw-r--r--chromium/components/metrics/metrics_provider.h12
-rw-r--r--chromium/components/metrics/metrics_service.cc39
-rw-r--r--chromium/components/metrics/metrics_service.h13
-rw-r--r--chromium/components/metrics/metrics_service_accessor.cc5
-rw-r--r--chromium/components/metrics/metrics_service_unittest.cc41
-rw-r--r--chromium/components/metrics/metrics_state_manager.cc5
-rw-r--r--chromium/components/metrics/net/DEPS4
-rw-r--r--chromium/components/metrics/net/net_metrics_log_uploader.cc2
-rw-r--r--chromium/components/metrics/net/net_metrics_log_uploader_unittest.cc4
-rw-r--r--chromium/components/metrics/net/network_metrics_provider.cc4
-rw-r--r--chromium/components/metrics/net/network_metrics_provider_unittest.cc12
-rw-r--r--chromium/components/metrics/persistent_histograms.cc8
-rw-r--r--chromium/components/metrics/public/mojom/BUILD.gn (renamed from chromium/components/metrics/public/interfaces/BUILD.gn)0
-rw-r--r--chromium/components/metrics/public/mojom/OWNERS (renamed from chromium/components/metrics/public/interfaces/OWNERS)0
-rw-r--r--chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom (renamed from chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom)0
-rw-r--r--chromium/components/metrics/public/mojom/call_stack_profile_collector_test.mojom (renamed from chromium/components/metrics/public/interfaces/call_stack_profile_collector_test.mojom)2
-rw-r--r--chromium/components/metrics/public/mojom/single_sample_metrics.mojom (renamed from chromium/components/metrics/public/interfaces/single_sample_metrics.mojom)0
-rw-r--r--chromium/components/metrics/single_sample_metrics.h2
-rw-r--r--chromium/components/metrics/single_sample_metrics_factory_impl.h2
-rw-r--r--chromium/components/metrics/single_sample_metrics_factory_impl_unittest.cc4
-rw-r--r--chromium/components/metrics/ui/screen_info_metrics_provider.cc18
-rw-r--r--chromium/components/metrics/ui/screen_info_metrics_provider.h5
-rw-r--r--chromium/components/metrics/ui/screen_info_metrics_provider_unittest.cc4
-rw-r--r--chromium/components/metrics/version_utils.cc3
-rw-r--r--chromium/components/metrics_services_manager/OWNERS1
-rw-r--r--chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java43
-rw-r--r--chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java21
-rw-r--r--chromium/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java53
-rw-r--r--chromium/components/mirroring/browser/BUILD.gn4
-rw-r--r--chromium/components/mirroring/browser/cast_remoting_sender.cc2
-rw-r--r--chromium/components/mirroring/browser/cast_remoting_sender.h2
-rw-r--r--chromium/components/mirroring/browser/cast_remoting_sender_unittest.cc8
-rw-r--r--chromium/components/mirroring/browser/single_client_video_capture_host.cc39
-rw-r--r--chromium/components/mirroring/browser/single_client_video_capture_host.h29
-rw-r--r--chromium/components/mirroring/browser/single_client_video_capture_host_unittest.cc15
-rw-r--r--chromium/components/mirroring/mojom/BUILD.gn13
-rw-r--r--chromium/components/mirroring/mojom/constants.mojom7
-rw-r--r--chromium/components/mirroring/mojom/mirroring_service.mojom2
-rw-r--r--chromium/components/mirroring/mojom/resource_provider.mojom13
-rw-r--r--chromium/components/mirroring/mojom/session_observer.mojom3
-rw-r--r--chromium/components/mirroring/service/BUILD.gn23
-rw-r--r--chromium/components/mirroring/service/DEPS1
-rw-r--r--chromium/components/mirroring/service/captured_audio_input.cc2
-rw-r--r--chromium/components/mirroring/service/captured_audio_input.h2
-rw-r--r--chromium/components/mirroring/service/captured_audio_input_unittest.cc12
-rw-r--r--chromium/components/mirroring/service/fake_network_service.cc14
-rw-r--r--chromium/components/mirroring/service/fake_network_service.h12
-rw-r--r--chromium/components/mirroring/service/fake_video_capture_host.cc6
-rw-r--r--chromium/components/mirroring/service/fake_video_capture_host.h30
-rw-r--r--chromium/components/mirroring/service/manifest.cc35
-rw-r--r--chromium/components/mirroring/service/manifest.h16
-rw-r--r--chromium/components/mirroring/service/media_remoter.h4
-rw-r--r--chromium/components/mirroring/service/media_remoter_unittest.cc24
-rw-r--r--chromium/components/mirroring/service/message_dispatcher_unittest.cc40
-rw-r--r--chromium/components/mirroring/service/mirror_settings.cc10
-rw-r--r--chromium/components/mirroring/service/mirror_settings.h4
-rw-r--r--chromium/components/mirroring/service/mirroring_service.cc44
-rw-r--r--chromium/components/mirroring/service/mirroring_service.h28
-rw-r--r--chromium/components/mirroring/service/remoting_sender.h2
-rw-r--r--chromium/components/mirroring/service/remoting_sender_unittest.cc14
-rw-r--r--chromium/components/mirroring/service/rtp_stream_unittest.cc16
-rw-r--r--chromium/components/mirroring/service/session.cc41
-rw-r--r--chromium/components/mirroring/service/session.h4
-rw-r--r--chromium/components/mirroring/service/session_monitor_unittest.cc24
-rw-r--r--chromium/components/mirroring/service/session_unittest.cc32
-rw-r--r--chromium/components/mirroring/service/udp_socket_client.cc6
-rw-r--r--chromium/components/mirroring/service/udp_socket_client.h6
-rw-r--r--chromium/components/mirroring/service/udp_socket_client_unittest.cc8
-rw-r--r--chromium/components/mirroring/service/video_capture_client.cc37
-rw-r--r--chromium/components/mirroring/service/video_capture_client_unittest.cc12
-rw-r--r--chromium/components/mirroring/service/wifi_status_monitor_unittest.cc10
-rw-r--r--chromium/components/module_installer/OWNERS1
-rw-r--r--chromium/components/module_installer/android/BUILD.gn93
-rw-r--r--chromium/components/module_installer/android/build/ModuleInstallerConfig.template19
-rw-r--r--chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java178
-rw-r--r--chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java35
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ApkModuleInstaller.java20
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/FakeModuleInstallerBackend.java (renamed from chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java)3
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Module.java (renamed from chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java)46
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstaller.java (renamed from chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java)24
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerBackend.java (renamed from chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerBackend.java)4
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerImpl.java208
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInterface.java (renamed from chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java)4
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInterfaceProcessor.java (renamed from chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterfaceProcessor.java)0
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java (renamed from chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java)0
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java (renamed from chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java)23
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Timer.java41
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ModuleActivityObserver.java64
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategy.java18
-rw-r--r--chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java30
-rw-r--r--chromium/components/module_installer/android/junit/src/org/chromium/components/module_installer/observers/ModuleActivityObserverTest.java162
-rw-r--r--chromium/components/navigation_interception/OWNERS2
-rw-r--r--chromium/components/navigation_interception/intercept_navigation_delegate.cc1
-rw-r--r--chromium/components/navigation_interception/intercept_navigation_throttle.cc15
-rw-r--r--chromium/components/navigation_metrics/OWNERS1
-rw-r--r--chromium/components/net_log/net_export_file_writer.cc4
-rw-r--r--chromium/components/net_log/net_export_file_writer_unittest.cc7
-rw-r--r--chromium/components/neterror/resources/offline.js9
-rw-r--r--chromium/components/network_hints/common/OWNERS4
-rw-r--r--chromium/components/network_hints/common/network_hints_messages.h8
-rw-r--r--chromium/components/network_hints/renderer/prescient_networking_dispatcher.cc8
-rw-r--r--chromium/components/network_hints/renderer/prescient_networking_dispatcher.h7
-rw-r--r--chromium/components/network_hints/renderer/renderer_preconnect.cc12
-rw-r--r--chromium/components/network_hints/renderer/renderer_preconnect.h8
-rw-r--r--chromium/components/network_session_configurator/browser/network_session_configurator.cc48
-rw-r--r--chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc55
-rw-r--r--chromium/components/network_session_configurator/common/network_features.cc3
-rw-r--r--chromium/components/network_session_configurator/common/network_features.h4
-rw-r--r--chromium/components/network_time/network_time_test_utils.cc61
-rw-r--r--chromium/components/network_time/network_time_test_utils.h12
-rw-r--r--chromium/components/network_time/network_time_tracker.cc2
-rw-r--r--chromium/components/network_time/network_time_tracker_unittest.cc7
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service.cc3
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service_unittest.cc4
-rw-r--r--chromium/components/ntp_snippets/features.cc2
-rw-r--r--chromium/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc6
-rw-r--r--chromium/components/ntp_snippets/remote/json_request.cc4
-rw-r--r--chromium/components/ntp_snippets/remote/json_request.h5
-rw-r--r--chromium/components/ntp_snippets/remote/json_request_unittest.cc2
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_database.cc36
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc32
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc1
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc10
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc6
-rw-r--r--chromium/components/ntp_snippets_strings_grdp/OWNERS1
-rw-r--r--chromium/components/ntp_tiles/BUILD.gn4
-rw-r--r--chromium/components/ntp_tiles/OWNERS5
-rw-r--r--chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc18
-rw-r--r--chromium/components/ntp_tiles/icon_cacher_impl.cc3
-rw-r--r--chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc45
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.cc2
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.h7
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites_unittest.cc4
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl.cc11
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl_unittest.cc9
-rw-r--r--chromium/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java6
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_item_bridge.cc9
-rw-r--r--chromium/components/offline_pages/content/renovations/render_frame_script_injector.cc2
-rw-r--r--chromium/components/offline_pages/content/renovations/render_frame_script_injector.h4
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified.cc19
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified.h2
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc4
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_utils.cc3
-rw-r--r--chromium/components/offline_pages/core/offline_page_archiver.h3
-rw-r--r--chromium/components/offline_pages/core/offline_page_model.h2
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc11
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc6
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_importer_impl.cc3
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc2
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc2
-rw-r--r--chromium/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc6
-rw-r--r--chromium/components/offline_pages/core/stub_offline_page_model.cc2
-rw-r--r--chromium/components/offline_pages/core/stub_offline_page_model.h2
-rw-r--r--chromium/components/onc/OWNERS1
-rw-r--r--chromium/components/onc/docs/onc_spec.md63
-rw-r--r--chromium/components/onc/onc_constants.cc19
-rw-r--r--chromium/components/onc/onc_constants.h18
-rw-r--r--chromium/components/open_from_clipboard/OWNERS4
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc18
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc15
-rw-r--r--chromium/components/optimization_guide/BUILD.gn15
-rw-r--r--chromium/components/optimization_guide/DEPS1
-rw-r--r--chromium/components/optimization_guide/OWNERS2
-rw-r--r--chromium/components/optimization_guide/command_line_top_host_provider.cc49
-rw-r--r--chromium/components/optimization_guide/command_line_top_host_provider.h41
-rw-r--r--chromium/components/optimization_guide/command_line_top_host_provider_unittest.cc61
-rw-r--r--chromium/components/optimization_guide/hint_cache_store.cc82
-rw-r--r--chromium/components/optimization_guide/hint_cache_store.h10
-rw-r--r--chromium/components/optimization_guide/hint_cache_store_unittest.cc128
-rw-r--r--chromium/components/optimization_guide/hint_cache_unittest.cc10
-rw-r--r--chromium/components/optimization_guide/hints_component_util.cc124
-rw-r--r--chromium/components/optimization_guide/hints_component_util.h31
-rw-r--r--chromium/components/optimization_guide/hints_component_util_unittest.cc178
-rw-r--r--chromium/components/optimization_guide/hints_fetcher.cc108
-rw-r--r--chromium/components/optimization_guide/hints_fetcher.h46
-rw-r--r--chromium/components/optimization_guide/hints_fetcher_unittest.cc245
-rw-r--r--chromium/components/optimization_guide/hints_processing_util.cc25
-rw-r--r--chromium/components/optimization_guide/hints_processing_util.h5
-rw-r--r--chromium/components/optimization_guide/hints_processing_util_unittest.cc38
-rw-r--r--chromium/components/optimization_guide/host_filter_unittest.cc64
-rw-r--r--chromium/components/optimization_guide/optimization_filter.cc (renamed from chromium/components/optimization_guide/host_filter.cc)43
-rw-r--r--chromium/components/optimization_guide/optimization_filter.h (renamed from chromium/components/optimization_guide/host_filter.h)41
-rw-r--r--chromium/components/optimization_guide/optimization_filter_unittest.cc101
-rw-r--r--chromium/components/optimization_guide/optimization_guide_constants.cc3
-rw-r--r--chromium/components/optimization_guide/optimization_guide_constants.h4
-rw-r--r--chromium/components/optimization_guide/optimization_guide_decider.h69
-rw-r--r--chromium/components/optimization_guide/optimization_guide_enums.h62
-rw-r--r--chromium/components/optimization_guide/optimization_guide_features.cc41
-rw-r--r--chromium/components/optimization_guide/optimization_guide_features.h24
-rw-r--r--chromium/components/optimization_guide/optimization_guide_prefs.cc56
-rw-r--r--chromium/components/optimization_guide/optimization_guide_prefs.h10
-rw-r--r--chromium/components/optimization_guide/optimization_guide_service_unittest.cc8
-rw-r--r--chromium/components/optimization_guide/proto/hints.proto3
-rw-r--r--chromium/components/optimization_guide/test_hints_component_creator.cc87
-rw-r--r--chromium/components/optimization_guide/top_host_provider.h3
-rw-r--r--chromium/components/os_crypt/BUILD.gn2
-rw-r--r--chromium/components/os_crypt/key_storage_keyring.cc3
-rw-r--r--chromium/components/os_crypt/key_storage_keyring_unittest.cc6
-rw-r--r--chromium/components/os_crypt/key_storage_kwallet_unittest.cc3
-rw-r--r--chromium/components/os_crypt/key_storage_libsecret.cc3
-rw-r--r--chromium/components/os_crypt/key_storage_linux.cc3
-rw-r--r--chromium/components/os_crypt/keychain_password_mac.mm3
-rw-r--r--chromium/components/os_crypt/keychain_password_mac_unittest.mm6
-rw-r--r--chromium/components/ownership/owner_settings_service.cc3
-rw-r--r--chromium/components/ownership/owner_settings_service.h2
-rw-r--r--chromium/components/page_image_annotation/DEPS1
-rw-r--r--chromium/components/page_image_annotation/content/renderer/DEPS1
-rw-r--r--chromium/components/page_image_annotation/content/renderer/content_page_annotator_driver.cc11
-rw-r--r--chromium/components/page_image_annotation/core/page_annotator.cc6
-rw-r--r--chromium/components/page_image_annotation/core/page_annotator.h6
-rw-r--r--chromium/components/page_image_annotation/core/page_annotator_unittest.cc21
-rw-r--r--chromium/components/page_info_strings.grdp23
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_DESCRIPTION.png.sha12
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_TITLE.png.sha12
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_SUMMARY.png.sha11
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_NATIVE_FILE_SYSTEM_WRITE.png.sha11
-rw-r--r--chromium/components/page_load_metrics/OWNERS13
-rw-r--r--chromium/components/page_load_metrics/common/BUILD.gn53
-rw-r--r--chromium/components/page_load_metrics/common/DEPS5
-rw-r--r--chromium/components/page_load_metrics/common/page_end_reason.h58
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics.mojom268
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics_constants.h17
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics_util.cc65
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics_util.h40
-rw-r--r--chromium/components/page_load_metrics/common/page_load_timing.cc61
-rw-r--r--chromium/components/page_load_metrics/common/page_load_timing.h27
-rw-r--r--chromium/components/page_load_metrics/renderer/BUILD.gn50
-rw-r--r--chromium/components/page_load_metrics/renderer/DEPS16
-rw-r--r--chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc155
-rw-r--r--chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h127
-rw-r--r--chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc422
-rw-r--r--chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h125
-rw-r--r--chromium/components/page_load_metrics/renderer/metrics_render_frame_observer_unittest.cc225
-rw-r--r--chromium/components/page_load_metrics/renderer/page_resource_data_use.cc196
-rw-r--r--chromium/components/page_load_metrics/renderer/page_resource_data_use.h101
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc276
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h130
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc378
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_sender.h29
-rw-r--r--chromium/components/password_manager/OWNERS1
-rw-r--r--chromium/components/password_manager/README.md5
-rw-r--r--chromium/components/password_manager/content/browser/BUILD.gn1
-rw-r--r--chromium/components/password_manager/content/browser/DEPS1
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.cc29
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.h9
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver_unittest.cc3
-rw-r--r--chromium/components/password_manager/content/browser/password_manager_log_router_factory_unittest.cc4
-rw-r--r--chromium/components/password_manager/content/common/credential_manager.typemap8
-rw-r--r--chromium/components/password_manager/core/browser/BUILD.gn37
-rw-r--r--chromium/components/password_manager/core/browser/DEPS1
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc6
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc2
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc6
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_service_unittest.cc12
-rw-r--r--chromium/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc16
-rw-r--r--chromium/components/password_manager/core/browser/browser_save_password_progress_logger.cc113
-rw-r--r--chromium/components/password_manager/core/browser/browser_save_password_progress_logger.h14
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl.cc16
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl.h18
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc108
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_password_form_manager.cc14
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_password_form_manager.h4
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc6
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc15
-rw-r--r--chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc27
-rw-r--r--chromium/components/password_manager/core/browser/fake_form_fetcher.cc18
-rw-r--r--chromium/components/password_manager/core/browser/fake_form_fetcher.h16
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher.h14
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher_impl.cc23
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher_impl.h26
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc10
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/form_parser.cc130
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc105
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.cc2
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.h1
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc5
-rw-r--r--chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_impl.cc2
-rw-r--r--chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc12
-rw-r--r--chromium/components/password_manager/core/browser/hash_password_manager.cc29
-rw-r--r--chromium/components/password_manager/core/browser/hash_password_manager.h21
-rw-r--r--chromium/components/password_manager/core/browser/hsts_query_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/http_auth_manager_impl.cc11
-rw-r--r--chromium/components/password_manager/core/browser/http_auth_manager_impl.h6
-rw-r--r--chromium/components/password_manager/core/browser/http_auth_manager_unittest.cc32
-rw-r--r--chromium/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc18
-rw-r--r--chromium/components/password_manager/core/browser/http_password_store_migrator_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password.cc27
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password.h13
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password_iterator.cc124
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password_iterator.h67
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password_iterator_unittest.cc118
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password_unittest.cc28
-rw-r--r--chromium/components/password_manager/core/browser/import/password_importer.cc5
-rw-r--r--chromium/components/password_manager/core/browser/import/password_importer_unittest.cc6
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/BUILD.gn85
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/DEPS4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc289
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h110
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc369
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc141
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/encryption_utils.h60
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/encryption_utils_unittest.cc139
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn43
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_api.proto106
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_check.h36
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h53
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc36
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h31
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl_unittest.cc86
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h54
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.cc186
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.h65
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.cc16
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h73
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_unittest.cc114
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc98
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h65
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc116
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.cc14
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h27
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.cc32
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.h33
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate.cc114
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate.h82
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate_helper.cc42
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate_helper.h58
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc180
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate_unittest.cc162
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc34
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h47
-rw-r--r--chromium/components/password_manager/core/browser/login_database.cc89
-rw-r--r--chromium/components/password_manager/core/browser/login_database.h22
-rw-r--r--chromium/components/password_manager/core/browser/login_database_ios_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/login_database_unittest.cc166
-rw-r--r--chromium/components/password_manager/core/browser/mock_password_store.h10
-rw-r--r--chromium/components/password_manager/core/browser/new_password_form_manager.cc1167
-rw-r--r--chromium/components/password_manager/core/browser/new_password_form_manager.h414
-rw-r--r--chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc2041
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_form_filling.cc23
-rw-r--r--chromium/components/password_manager/core/browser/password_form_filling.h1
-rw-r--r--chromium/components/password_manager/core/browser/password_form_filling_unittest.cc101
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager.cc1598
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager.h544
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager_unittest.cc6029
-rw-r--r--chromium/components/password_manager/core/browser/password_form_metrics_recorder.cc9
-rw-r--r--chromium/components/password_manager/core/browser/password_form_metrics_recorder.h18
-rw-r--r--chromium/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc24
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_state.cc1
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_state_unittest.cc6
-rw-r--r--chromium/components/password_manager/core/browser/password_manager.cc666
-rw-r--r--chromium/components/password_manager/core/browser/password_manager.h106
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_client.cc6
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_client.h43
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_constants.cc8
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_constants.h6
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_recorder_unittest.cc8
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_util.cc60
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_util.h165
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_onboarding.cc170
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_onboarding.h122
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_onboarding_unittest.cc389
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_test_utils.cc1
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_test_utils.h1
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_unittest.cc1417
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util.cc27
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util.h21
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util_unittest.cc21
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc5
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detection_manager_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detector.cc12
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detector.h2
-rw-r--r--chromium/components/password_manager/core/browser/password_store.cc74
-rw-r--r--chromium/components/password_manager/core/browser/password_store.h56
-rw-r--r--chromium/components/password_manager/core/browser/password_store_change.h1
-rw-r--r--chromium/components/password_manager/core/browser/password_store_default.cc18
-rw-r--r--chromium/components/password_manager/core/browser/password_store_default.h9
-rw-r--r--chromium/components/password_manager/core/browser/password_store_default_unittest.cc18
-rw-r--r--chromium/components/password_manager/core/browser/password_store_factory_util.cc20
-rw-r--r--chromium/components/password_manager/core/browser/password_store_factory_util.h4
-rw-r--r--chromium/components/password_manager/core/browser/password_store_signin_notifier.cc5
-rw-r--r--chromium/components/password_manager/core/browser/password_store_sync.h9
-rw-r--r--chromium/components/password_manager/core/browser/password_store_unittest.cc254
-rw-r--r--chromium/components/password_manager/core/browser/password_sync_util.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_sync_util_unittest.cc13
-rw-r--r--chromium/components/password_manager/core/browser/psl_matching_helper.cc39
-rw-r--r--chromium/components/password_manager/core/browser/psl_matching_helper.h12
-rw-r--r--chromium/components/password_manager/core/browser/psl_matching_helper_unittest.cc10
-rw-r--r--chromium/components/password_manager/core/browser/store_metrics_reporter.cc21
-rw-r--r--chromium/components/password_manager/core/browser/store_metrics_reporter.h8
-rw-r--r--chromium/components/password_manager/core/browser/store_metrics_reporter_unittest.cc141
-rw-r--r--chromium/components/password_manager/core/browser/stub_password_manager_client.cc22
-rw-r--r--chromium/components/password_manager/core/browser/stub_password_manager_client.h15
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_model_type_controller.cc5
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_model_type_controller.h1
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_sync_bridge.cc34
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc2
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_syncable_service.cc13
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc13
-rw-r--r--chromium/components/password_manager/core/browser/sync_credentials_filter.cc21
-rw-r--r--chromium/components/password_manager/core/browser/sync_credentials_filter.h20
-rw-r--r--chromium/components/password_manager/core/browser/sync_credentials_filter_unittest.cc32
-rw-r--r--chromium/components/password_manager/core/browser/sync_username_test_base.cc33
-rw-r--r--chromium/components/password_manager/core/browser/sync_username_test_base.h6
-rw-r--r--chromium/components/password_manager/core/browser/test_password_store.cc23
-rw-r--r--chromium/components/password_manager/core/browser/test_password_store.h6
-rw-r--r--chromium/components/password_manager/core/browser/votes_uploader.cc26
-rw-r--r--chromium/components/password_manager/core/browser/votes_uploader.h13
-rw-r--r--chromium/components/password_manager/core/browser/votes_uploader_unittest.cc24
-rw-r--r--chromium/components/password_manager/core/common/password_manager_features.cc29
-rw-r--r--chromium/components/password_manager/core/common/password_manager_features.h6
-rw-r--r--chromium/components/password_manager/core/common/password_manager_pref_names.cc7
-rw-r--r--chromium/components/password_manager/core/common/password_manager_pref_names.h10
-rw-r--r--chromium/components/password_manager/core/common/passwords_directory_util_ios.cc9
-rw-r--r--chromium/components/password_manager/core/common/passwords_directory_util_ios_unittest.cc4
-rw-r--r--chromium/components/password_manager/ios/password_form_helper.mm2
-rw-r--r--chromium/components/password_manager/ios/password_form_helper_unittest.mm2
-rw-r--r--chromium/components/password_manager/ios/password_suggestion_helper.mm2
-rw-r--r--chromium/components/payments/content/BUILD.gn2
-rw-r--r--chromium/components/payments/content/android/java/src/org/chromium/components/payments/PaymentHandlerHost.java15
-rw-r--r--chromium/components/payments/content/android/payment_handler_host.cc28
-rw-r--r--chromium/components/payments/content/android/payment_handler_host.h22
-rw-r--r--chromium/components/payments/content/android/payment_manifest_parser_android.cc5
-rw-r--r--chromium/components/payments/content/android/payment_manifest_parser_android.h6
-rw-r--r--chromium/components/payments/content/installable_payment_app_crawler.cc2
-rw-r--r--chromium/components/payments/content/mock_identity_observer.cc18
-rw-r--r--chromium/components/payments/content/mock_identity_observer.h36
-rw-r--r--chromium/components/payments/content/payment_handler_host.cc96
-rw-r--r--chromium/components/payments/content/payment_handler_host.h54
-rw-r--r--chromium/components/payments/content/payment_instrument_unittest.cc8
-rw-r--r--chromium/components/payments/content/payment_request.cc93
-rw-r--r--chromium/components/payments/content/payment_request.h27
-rw-r--r--chromium/components/payments/content/payment_request_spec.cc19
-rw-r--r--chromium/components/payments/content/payment_request_spec.h23
-rw-r--r--chromium/components/payments/content/payment_request_state.cc44
-rw-r--r--chromium/components/payments/content/payment_request_state.h42
-rw-r--r--chromium/components/payments/content/payment_request_state_unittest.cc88
-rw-r--r--chromium/components/payments/content/service_worker_payment_instrument.cc41
-rw-r--r--chromium/components/payments/content/service_worker_payment_instrument.h36
-rw-r--r--chromium/components/payments/content/service_worker_payment_instrument_unittest.cc14
-rw-r--r--chromium/components/payments/core/autofill_payment_instrument.cc8
-rw-r--r--chromium/components/payments/core/autofill_payment_instrument.h10
-rw-r--r--chromium/components/payments/core/can_make_payment_query_unittest.cc4
-rw-r--r--chromium/components/payments/core/features.cc5
-rw-r--r--chromium/components/payments/core/features.h4
-rw-r--r--chromium/components/payments/core/journey_logger.cc80
-rw-r--r--chromium/components/payments/core/journey_logger.h15
-rw-r--r--chromium/components/payments/core/journey_logger_unittest.cc6
-rw-r--r--chromium/components/payments/core/payment_manifest_downloader.cc2
-rw-r--r--chromium/components/payments/core/payment_manifest_downloader_unittest.cc6
-rw-r--r--chromium/components/pdf/OWNERS1
-rw-r--r--chromium/components/pdf/common/BUILD.gn2
-rw-r--r--chromium/components/pdf/common/pdf.mojom2
-rw-r--r--chromium/components/pdf/renderer/BUILD.gn15
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree.cc585
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree.h61
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc570
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree_unittest.cc146
-rw-r--r--chromium/components/pdf/renderer/pdf_ax_action_target.cc143
-rw-r--r--chromium/components/pdf/renderer/pdf_ax_action_target.h62
-rw-r--r--chromium/components/pdf/renderer/pepper_pdf_host.cc8
-rw-r--r--chromium/components/pdf/renderer/pepper_pdf_host.h5
-rw-r--r--chromium/components/pdf_strings_grdp/OWNERS1
-rw-r--r--chromium/components/plugins/OWNERS1
-rw-r--r--chromium/components/plugins/renderer/DEPS1
-rw-r--r--chromium/components/plugins/renderer/webview_plugin.cc20
-rw-r--r--chromium/components/plugins/renderer/webview_plugin.h4
-rw-r--r--chromium/components/policy/BUILD.gn37
-rw-r--r--chromium/components/policy/core/browser/BUILD.gn2
-rw-r--r--chromium/components/policy/core/common/BUILD.gn6
-rw-r--r--chromium/components/policy_strings.grdp11
-rw-r--r--chromium/components/policy_strings_grdp/OWNERS2
-rw-r--r--chromium/components/prefs/in_memory_pref_store_unittest.cc6
-rw-r--r--chromium/components/prefs/json_pref_store.h5
-rw-r--r--chromium/components/prefs/json_pref_store_unittest.cc82
-rw-r--r--chromium/components/prefs/overlay_user_pref_store_unittest.cc7
-rw-r--r--chromium/components/prefs/persistent_pref_store_unittest.cc6
-rw-r--r--chromium/components/prefs/persistent_pref_store_unittest.h8
-rw-r--r--chromium/components/prefs/pref_member_unittest.cc7
-rw-r--r--chromium/components/prefs/pref_notifier_impl.cc8
-rw-r--r--chromium/components/previews/DEPS1
-rw-r--r--chromium/components/previews/content/BUILD.gn12
-rw-r--r--chromium/components/previews/content/DEPS2
-rw-r--r--chromium/components/previews/content/previews_decider.h (renamed from chromium/components/previews/core/previews_decider.h)44
-rw-r--r--chromium/components/previews/content/previews_decider_impl.cc100
-rw-r--r--chromium/components/previews/content/previews_decider_impl.h25
-rw-r--r--chromium/components/previews/content/previews_decider_impl_unittest.cc556
-rw-r--r--chromium/components/previews/content/previews_hints.cc128
-rw-r--r--chromium/components/previews/content/previews_hints.h13
-rw-r--r--chromium/components/previews/content/previews_hints_unittest.cc253
-rw-r--r--chromium/components/previews/content/previews_optimization_guide.h218
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_decider.cc211
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_decider.h62
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_decider_unittest.cc355
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_impl.cc (renamed from chromium/components/previews/content/previews_optimization_guide.cc)176
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_impl.h223
-rw-r--r--chromium/components/previews/content/previews_optimization_guide_impl_unittest.cc (renamed from chromium/components/previews/content/previews_optimization_guide_unittest.cc)797
-rw-r--r--chromium/components/previews/content/previews_ui_service_unittest.cc6
-rw-r--r--chromium/components/previews/core/BUILD.gn22
-rw-r--r--chromium/components/previews/core/previews_black_list.h18
-rw-r--r--chromium/components/previews/core/previews_black_list_unittest.cc4
-rw-r--r--chromium/components/previews/core/previews_constants.cc12
-rw-r--r--chromium/components/previews/core/previews_constants.h16
-rw-r--r--chromium/components/previews/core/previews_experiments.cc65
-rw-r--r--chromium/components/previews/core/previews_experiments.h42
-rw-r--r--chromium/components/previews/core/previews_experiments_unittest.cc1
-rw-r--r--chromium/components/previews/core/previews_logger.cc10
-rw-r--r--chromium/components/previews/core/previews_logger_unittest.cc26
-rw-r--r--chromium/components/previews/core/test_previews_decider.cc41
-rw-r--r--chromium/components/previews/core/test_previews_decider.h38
-rw-r--r--chromium/components/printing/browser/BUILD.gn3
-rw-r--r--chromium/components/printing/browser/DEPS7
-rw-r--r--chromium/components/printing/browser/print_composite_client.cc54
-rw-r--r--chromium/components/printing/browser/print_composite_client.h13
-rw-r--r--chromium/components/printing/browser/print_manager.cc60
-rw-r--r--chromium/components/printing/browser/print_manager.h47
-rw-r--r--chromium/components/printing/browser/print_media_l10n.cc39
-rw-r--r--chromium/components/printing/browser/print_media_l10n.h3
-rw-r--r--chromium/components/printing/browser/print_media_l10n_unittest.cc20
-rw-r--r--chromium/components/printing/browser/printer_capabilities.cc20
-rw-r--r--chromium/components/printing/browser/printer_capabilities_unittest.cc4
-rw-r--r--chromium/components/printing/common/BUILD.gn12
-rw-r--r--chromium/components/printing/common/OWNERS3
-rw-r--r--chromium/components/printing/common/print.mojom12
-rw-r--r--chromium/components/printing/common/print_messages.h9
-rw-r--r--chromium/components/printing/renderer/DEPS1
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper.cc33
-rw-r--r--chromium/components/proxy_config/OWNERS1
-rw-r--r--chromium/components/proxy_config/ios/proxy_service_factory.cc6
-rw-r--r--chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc4
-rw-r--r--chromium/components/quirks/OWNERS1
-rw-r--r--chromium/components/quirks/quirks_client.cc5
-rw-r--r--chromium/components/quirks/quirks_client.h2
-rw-r--r--chromium/components/quirks/quirks_manager.cc11
-rw-r--r--chromium/components/quirks/quirks_manager.h3
-rw-r--r--chromium/components/rappor/log_uploader.cc2
-rw-r--r--chromium/components/rappor/log_uploader_unittest.cc7
-rw-r--r--chromium/components/reading_list/core/reading_list_store_unittest.cc4
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm38
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h4
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm133
-rw-r--r--chromium/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm5
-rw-r--r--chromium/components/remote_cocoa/common/BUILD.gn10
-rw-r--r--chromium/components/remote_cocoa/common/native_widget_ns_window.mojom7
-rw-r--r--chromium/components/remote_cocoa/common/native_widget_ns_window_host.mojom8
-rw-r--r--chromium/components/remote_cocoa/common/text_input_host.mojom4
-rw-r--r--chromium/components/renderer_context_menu/render_view_context_menu_base.cc16
-rw-r--r--chromium/components/renderer_context_menu/render_view_context_menu_base.h7
-rw-r--r--chromium/components/renderer_context_menu/render_view_context_menu_proxy.h8
-rw-r--r--chromium/components/reset_password_strings_grdp/OWNERS2
-rw-r--r--chromium/components/resources/BUILD.gn2
-rw-r--r--chromium/components/resources/OWNERS3
-rw-r--r--chromium/components/resources/components_resources.grd1
-rw-r--r--chromium/components/resources/components_scaled_resources.grd2
-rw-r--r--chromium/components/resources/onboarding_welcome_scaled_resources.grdp11
-rw-r--r--chromium/components/resources/supervised_user_error_page_resources.grdp4
-rw-r--r--chromium/components/resources/welcome_scaled_resources.grdp11
-rw-r--r--chromium/components/rlz/BUILD.gn2
-rw-r--r--chromium/components/safe_browsing/BUILD.gn327
-rw-r--r--chromium/components/safe_browsing/DEPS2
-rw-r--r--chromium/components/safe_browsing/OWNERS5
-rw-r--r--chromium/components/safe_browsing/android/remote_database_manager.cc15
-rw-r--r--chromium/components/safe_browsing/android/remote_database_manager_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc12
-rw-r--r--chromium/components/safe_browsing/base_ui_manager.cc9
-rw-r--r--chromium/components/safe_browsing/browser/BUILD.gn11
-rw-r--r--chromium/components/safe_browsing/browser/DEPS2
-rw-r--r--chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc204
-rw-r--r--chromium/components/safe_browsing/browser/base_parallel_resource_throttle.h70
-rw-r--r--chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc285
-rw-r--r--chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc60
-rw-r--r--chromium/components/safe_browsing/browser/browser_url_loader_throttle.h6
-rw-r--r--chromium/components/safe_browsing/browser/safe_browsing_network_context.cc77
-rw-r--r--chromium/components/safe_browsing/browser/safe_browsing_network_context.h15
-rw-r--r--chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc137
-rw-r--r--chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.h12
-rw-r--r--chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc107
-rw-r--r--chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.h64
-rw-r--r--chromium/components/safe_browsing/browser/threat_details.cc19
-rw-r--r--chromium/components/safe_browsing/browser/threat_details.h5
-rw-r--r--chromium/components/safe_browsing/browser/threat_details_cache.cc12
-rw-r--r--chromium/components/safe_browsing/browser/threat_details_history.cc4
-rw-r--r--chromium/components/safe_browsing/buildflags.gni26
-rw-r--r--chromium/components/safe_browsing/common/BUILD.gn1
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing_prefs.cc34
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing_prefs.h81
-rw-r--r--chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/db/BUILD.gn100
-rw-r--r--chromium/components/safe_browsing/db/allowlist_checker_client_unittest.cc21
-rw-r--r--chromium/components/safe_browsing/db/database_manager.cc8
-rw-r--r--chromium/components/safe_browsing/db/database_manager.h4
-rw-r--r--chromium/components/safe_browsing/db/database_manager_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/db/v4_database_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/db/v4_local_database_manager.cc42
-rw-r--r--chromium/components/safe_browsing/db/v4_local_database_manager.h11
-rw-r--r--chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/db/v4_protocol_manager_util.cc1
-rw-r--r--chromium/components/safe_browsing/db/v4_protocol_manager_util.h10
-rw-r--r--chromium/components/safe_browsing/db/v4_store.cc2
-rw-r--r--chromium/components/safe_browsing/db/v4_store_unittest.cc5
-rw-r--r--chromium/components/safe_browsing/db/v4_update_protocol_manager.cc11
-rw-r--r--chromium/components/safe_browsing/db/v4_update_protocol_manager_unittest.cc7
-rw-r--r--chromium/components/safe_browsing/features.cc31
-rw-r--r--chromium/components/safe_browsing/features.h14
-rw-r--r--chromium/components/safe_browsing/password_protection/BUILD.gn7
-rw-r--r--chromium/components/safe_browsing/password_protection/metrics_util.cc179
-rw-r--r--chromium/components/safe_browsing/password_protection/metrics_util.h28
-rw-r--r--chromium/components/safe_browsing/password_protection/mock_password_protection_service.h33
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_request.cc79
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_request.h27
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_service.cc214
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_service.h122
-rw-r--r--chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc360
-rw-r--r--chromium/components/safe_browsing/ping_manager.cc6
-rw-r--r--chromium/components/safe_browsing/proto/webprotect.proto55
-rw-r--r--chromium/components/safe_browsing/realtime/BUILD.gn35
-rw-r--r--chromium/components/safe_browsing/realtime/policy_engine.cc50
-rw-r--r--chromium/components/safe_browsing/realtime/policy_engine.h37
-rw-r--r--chromium/components/safe_browsing/realtime/policy_engine_unittest.cc73
-rw-r--r--chromium/components/safe_browsing/realtime/url_lookup_service.cc180
-rw-r--r--chromium/components/safe_browsing/realtime/url_lookup_service.h99
-rw-r--r--chromium/components/safe_browsing/realtime/url_lookup_service_unittest.cc111
-rw-r--r--chromium/components/safe_browsing/renderer/BUILD.gn1
-rw-r--r--chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.h6
-rw-r--r--chromium/components/safe_browsing/renderer/threat_dom_details.cc4
-rw-r--r--chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/triggers/ad_popup_trigger.cc4
-rw-r--r--chromium/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc2
-rw-r--r--chromium/components/safe_browsing/triggers/ad_redirect_trigger.cc28
-rw-r--r--chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc4
-rw-r--r--chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/triggers/suspicious_site_trigger.cc4
-rw-r--r--chromium/components/safe_browsing/triggers/suspicious_site_trigger_unittest.cc3
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc4
-rw-r--r--chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc48
-rw-r--r--chromium/components/safe_browsing/verdict_cache_manager.cc23
-rw-r--r--chromium/components/safe_browsing/verdict_cache_manager.h8
-rw-r--r--chromium/components/safe_browsing/verdict_cache_manager_unittest.cc192
-rw-r--r--chromium/components/safe_browsing/web_ui/BUILD.gn1
-rw-r--r--chromium/components/safe_browsing/web_ui/resources/safe_browsing.html4
-rw-r--r--chromium/components/safe_browsing/web_ui/resources/safe_browsing.js17
-rw-r--r--chromium/components/safe_browsing/web_ui/safe_browsing_ui.cc189
-rw-r--r--chromium/components/safe_browsing/web_ui/safe_browsing_ui.h28
-rw-r--r--chromium/components/safe_browsing/web_ui/safe_browsing_ui_unittest.cc4
-rw-r--r--chromium/components/safe_search_api/safe_search/safe_search_url_checker_client.cc2
-rw-r--r--chromium/components/safe_search_api/safe_search/safe_search_url_checker_client_unittest.cc4
-rw-r--r--chromium/components/safe_search_api/url_checker_unittest.cc2
-rw-r--r--chromium/components/search/BUILD.gn2
-rw-r--r--chromium/components/search/OWNERS3
-rw-r--r--chromium/components/search_engines/BUILD.gn4
-rw-r--r--chromium/components/search_engines/android/OWNERS3
-rw-r--r--chromium/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrlService.java25
-rw-r--r--chromium/components/search_engines/android/template_url_android.cc3
-rw-r--r--chromium/components/search_engines/android/template_url_service_android.cc39
-rw-r--r--chromium/components/search_engines/android/template_url_service_android.h13
-rw-r--r--chromium/components/search_engines/default_search_manager.cc2
-rw-r--r--chromium/components/search_engines/default_search_manager.h1
-rw-r--r--chromium/components/search_engines/default_search_manager_unittest.cc1
-rw-r--r--chromium/components/search_engines/keyword_table.cc24
-rw-r--r--chromium/components/search_engines/keyword_table.h5
-rw-r--r--chromium/components/search_engines/keyword_table_unittest.cc5
-rw-r--r--chromium/components/search_engines/keyword_web_data_service.cc125
-rw-r--r--chromium/components/search_engines/keyword_web_data_service.h33
-rw-r--r--chromium/components/search_engines/prepopulated_engines.json12
-rw-r--r--chromium/components/search_engines/prepopulated_engines_schema.json2
-rw-r--r--chromium/components/search_engines/search_engines_test_util.cc1
-rw-r--r--chromium/components/search_engines/search_terms_data.cc4
-rw-r--r--chromium/components/search_engines/template_url.cc5
-rw-r--r--chromium/components/search_engines/template_url.h1
-rw-r--r--chromium/components/search_engines/template_url_data.cc8
-rw-r--r--chromium/components/search_engines/template_url_data.h4
-rw-r--r--chromium/components/search_engines/template_url_data_util.cc4
-rw-r--r--chromium/components/search_engines/template_url_service.cc111
-rw-r--r--chromium/components/search_engines/template_url_service.h25
-rw-r--r--chromium/components/search_engines/template_url_service_util_unittest.cc78
-rw-r--r--chromium/components/search_engines/template_url_unittest.cc27
-rw-r--r--chromium/components/search_engines/util.cc72
-rw-r--r--chromium/components/search_engines/util.h16
-rw-r--r--chromium/components/search_provider_logos/logo_service_impl.cc9
-rw-r--r--chromium/components/search_provider_logos/logo_service_impl_unittest.cc4
-rw-r--r--chromium/components/security_interstitials/OWNERS1
-rw-r--r--chromium/components/security_interstitials/content/connection_help_ui.cc2
-rw-r--r--chromium/components/security_interstitials/content/unsafe_resource.cc9
-rw-r--r--chromium/components/security_interstitials/core/BUILD.gn2
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/images/heavy_ad.svg1
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/interstitial_large.js3
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css2
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css4
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.js15
-rw-r--r--chromium/components/security_interstitials/core/browser/resources/list_of_interstitials.html8
-rw-r--r--chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc2
-rw-r--r--chromium/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc2
-rw-r--r--chromium/components/security_interstitials_strings.grdp34
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_BILLING_TITLE.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_HEADING_WIFI.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI_SSID.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIRED.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha12
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_DESCRIPTION.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_TITLE.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_IGNORE_BUTTON.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_LEAVE_BUTTON.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_NAME.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE.png.sha11
-rw-r--r--chromium/components/security_interstitials_strings_grdp/OWNERS1
-rw-r--r--chromium/components/security_state/content/content_utils.cc29
-rw-r--r--chromium/components/security_state/content/content_utils_unittest.cc6
-rw-r--r--chromium/components/security_state/core/security_state.cc41
-rw-r--r--chromium/components/security_state/core/security_state.h36
-rw-r--r--chromium/components/security_state/core/security_state_unittest.cc12
-rw-r--r--chromium/components/security_state_strings_grdp/OWNERS1
-rw-r--r--chromium/components/send_tab_to_self/OWNERS1
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_bridge.cc4
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc4
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc9
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.h2
-rw-r--r--chromium/components/services/OWNERS1
-rw-r--r--chromium/components/services/app_service/public/cpp/BUILD.gn10
-rw-r--r--chromium/components/services/app_service/public/cpp/file_handler_info.cc25
-rw-r--r--chromium/components/services/app_service/public/cpp/file_handler_info.h47
-rw-r--r--chromium/components/services/filesystem/BUILD.gn33
-rw-r--r--chromium/components/services/filesystem/DEPS2
-rw-r--r--chromium/components/services/filesystem/OWNERS2
-rw-r--r--chromium/components/services/filesystem/directory_impl_unittest.cc50
-rw-r--r--chromium/components/services/filesystem/directory_test_helper.cc59
-rw-r--r--chromium/components/services/filesystem/directory_test_helper.h35
-rw-r--r--chromium/components/services/filesystem/file_impl_unittest.cc56
-rw-r--r--chromium/components/services/filesystem/file_system_app.cc87
-rw-r--r--chromium/components/services/filesystem/file_system_app.h44
-rw-r--r--chromium/components/services/filesystem/file_system_impl.cc70
-rw-r--r--chromium/components/services/filesystem/file_system_impl.h54
-rw-r--r--chromium/components/services/filesystem/files_test_base.cc44
-rw-r--r--chromium/components/services/filesystem/files_test_base.h48
-rw-r--r--chromium/components/services/filesystem/main.cc12
-rw-r--r--chromium/components/services/filesystem/public/cpp/BUILD.gn16
-rw-r--r--chromium/components/services/filesystem/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/filesystem/public/cpp/manifest.cc30
-rw-r--r--chromium/components/services/filesystem/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/filesystem/public/mojom/BUILD.gn1
-rw-r--r--chromium/components/services/filesystem/public/mojom/file_system.mojom21
-rw-r--r--chromium/components/services/font/BUILD.gn24
-rw-r--r--chromium/components/services/font/DEPS1
-rw-r--r--chromium/components/services/font/font_loader_unittest.cc43
-rw-r--r--chromium/components/services/font/font_service_app.cc22
-rw-r--r--chromium/components/services/font/font_service_app.h22
-rw-r--r--chromium/components/services/font/main.cc12
-rw-r--r--chromium/components/services/font/public/cpp/BUILD.gn15
-rw-r--r--chromium/components/services/font/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/font/public/cpp/font_loader.cc13
-rw-r--r--chromium/components/services/font/public/cpp/font_loader.h8
-rw-r--r--chromium/components/services/font/public/cpp/font_service_thread.cc50
-rw-r--r--chromium/components/services/font/public/cpp/font_service_thread.h24
-rw-r--r--chromium/components/services/font/public/cpp/manifest.cc32
-rw-r--r--chromium/components/services/font/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/font/public/mojom/BUILD.gn1
-rw-r--r--chromium/components/services/font/public/mojom/constants.mojom7
-rw-r--r--chromium/components/services/heap_profiling/BUILD.gn8
-rw-r--r--chromium/components/services/heap_profiling/OWNERS1
-rw-r--r--chromium/components/services/heap_profiling/connection_manager.cc15
-rw-r--r--chromium/components/services/heap_profiling/connection_manager.h3
-rw-r--r--chromium/components/services/heap_profiling/heap_profiling_service.cc202
-rw-r--r--chromium/components/services/heap_profiling/heap_profiling_service.h80
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/BUILD.gn21
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/controller.cc32
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/controller.h24
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/manifest.cc39
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/profiling_client.cc9
-rw-r--r--chromium/components/services/heap_profiling/public/cpp/profiling_client.h11
-rw-r--r--chromium/components/services/heap_profiling/public/mojom/BUILD.gn1
-rw-r--r--chromium/components/services/heap_profiling/public/mojom/constants.mojom7
-rw-r--r--chromium/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom6
-rw-r--r--chromium/components/services/leveldb/BUILD.gn30
-rw-r--r--chromium/components/services/leveldb/DEPS2
-rw-r--r--chromium/components/services/leveldb/OWNERS2
-rw-r--r--chromium/components/services/leveldb/env_mojo.cc9
-rw-r--r--chromium/components/services/leveldb/leveldb_app.cc36
-rw-r--r--chromium/components/services/leveldb/leveldb_app.h47
-rw-r--r--chromium/components/services/leveldb/leveldb_service_impl.cc36
-rw-r--r--chromium/components/services/leveldb/leveldb_service_impl.h22
-rw-r--r--chromium/components/services/leveldb/leveldb_service_unittest.cc145
-rw-r--r--chromium/components/services/leveldb/main.cc12
-rw-r--r--chromium/components/services/leveldb/public/cpp/BUILD.gn14
-rw-r--r--chromium/components/services/leveldb/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/leveldb/public/cpp/manifest.cc31
-rw-r--r--chromium/components/services/leveldb/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/leveldb/public/mojom/leveldb.mojom9
-rw-r--r--chromium/components/services/leveldb/remote_iterator_unittest.cc48
-rw-r--r--chromium/components/services/patch/BUILD.gn23
-rw-r--r--chromium/components/services/patch/DEPS3
-rw-r--r--chromium/components/services/patch/OWNERS2
-rw-r--r--chromium/components/services/patch/content/BUILD.gn21
-rw-r--r--chromium/components/services/patch/content/DEPS (renamed from chromium/components/leveldb_proto/content/DEPS)3
-rw-r--r--chromium/components/services/patch/content/patch_service.cc24
-rw-r--r--chromium/components/services/patch/content/patch_service.h21
-rw-r--r--chromium/components/services/patch/file_patcher_impl.cc6
-rw-r--r--chromium/components/services/patch/file_patcher_impl.h14
-rw-r--r--chromium/components/services/patch/in_process_file_patcher.cc36
-rw-r--r--chromium/components/services/patch/in_process_file_patcher.h22
-rw-r--r--chromium/components/services/patch/patch_service.cc29
-rw-r--r--chromium/components/services/patch/patch_service.h33
-rw-r--r--chromium/components/services/patch/public/cpp/BUILD.gn18
-rw-r--r--chromium/components/services/patch/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/patch/public/cpp/manifest.cc41
-rw-r--r--chromium/components/services/patch/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/patch/public/cpp/patch.cc35
-rw-r--r--chromium/components/services/patch/public/cpp/patch.h8
-rw-r--r--chromium/components/services/patch/public/mojom/BUILD.gn7
-rw-r--r--chromium/components/services/patch/public/mojom/constants.mojom7
-rw-r--r--chromium/components/services/pdf_compositor/BUILD.gn13
-rw-r--r--chromium/components/services/pdf_compositor/DEPS2
-rw-r--r--chromium/components/services/pdf_compositor/pdf_compositor_impl.cc72
-rw-r--r--chromium/components/services/pdf_compositor/pdf_compositor_impl.h35
-rw-r--r--chromium/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc30
-rw-r--r--chromium/components/services/pdf_compositor/pdf_compositor_service.cc104
-rw-r--r--chromium/components/services/pdf_compositor/pdf_compositor_service.h55
-rw-r--r--chromium/components/services/pdf_compositor/pdf_compositor_service_unittest.cc198
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/BUILD.gn28
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/manifest.cc38
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc28
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h21
-rw-r--r--chromium/components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h2
-rw-r--r--chromium/components/services/pdf_compositor/public/mojom/BUILD.gn1
-rw-r--r--chromium/components/services/pdf_compositor/public/mojom/pdf_compositor.mojom10
-rw-r--r--chromium/components/services/quarantine/BUILD.gn5
-rw-r--r--chromium/components/services/quarantine/public/cpp/BUILD.gn17
-rw-r--r--chromium/components/services/quarantine/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/quarantine/public/cpp/manifest.cc46
-rw-r--r--chromium/components/services/quarantine/public/cpp/manifest.h18
-rw-r--r--chromium/components/services/quarantine/public/mojom/quarantine.mojom3
-rw-r--r--chromium/components/services/quarantine/quarantine_impl.cc14
-rw-r--r--chromium/components/services/quarantine/quarantine_impl.h11
-rw-r--r--chromium/components/services/quarantine/quarantine_service.cc46
-rw-r--r--chromium/components/services/quarantine/quarantine_service.h42
-rw-r--r--chromium/components/services/quarantine/quarantine_service_unittest.cc31
-rw-r--r--chromium/components/services/storage/BUILD.gn42
-rw-r--r--chromium/components/services/storage/DEPS3
-rw-r--r--chromium/components/services/storage/OWNERS3
-rw-r--r--chromium/components/services/storage/dom_storage/dom_storage_database.cc340
-rw-r--r--chromium/components/services/storage/dom_storage/dom_storage_database.h190
-rw-r--r--chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc437
-rw-r--r--chromium/components/services/storage/origin_context_impl.cc32
-rw-r--r--chromium/components/services/storage/origin_context_impl.h41
-rw-r--r--chromium/components/services/storage/partition_impl.cc55
-rw-r--r--chromium/components/services/storage/partition_impl.h65
-rw-r--r--chromium/components/services/storage/partition_impl_unittest.cc134
-rw-r--r--chromium/components/services/storage/public/mojom/BUILD.gn18
-rw-r--r--chromium/components/services/storage/public/mojom/OWNERS2
-rw-r--r--chromium/components/services/storage/public/mojom/origin_context.mojom14
-rw-r--r--chromium/components/services/storage/public/mojom/partition.mojom16
-rw-r--r--chromium/components/services/storage/public/mojom/storage_service.mojom24
-rw-r--r--chromium/components/services/storage/storage_service_impl.cc51
-rw-r--r--chromium/components/services/storage/storage_service_impl.h62
-rw-r--r--chromium/components/services/storage/storage_service_impl_unittest.cc132
-rw-r--r--chromium/components/services/unzip/BUILD.gn25
-rw-r--r--chromium/components/services/unzip/DEPS1
-rw-r--r--chromium/components/services/unzip/OWNERS2
-rw-r--r--chromium/components/services/unzip/content/BUILD.gn21
-rw-r--r--chromium/components/services/unzip/content/DEPS3
-rw-r--r--chromium/components/services/unzip/content/unzip_service.cc41
-rw-r--r--chromium/components/services/unzip/content/unzip_service.h29
-rw-r--r--chromium/components/services/unzip/in_process_unzipper.cc35
-rw-r--r--chromium/components/services/unzip/in_process_unzipper.h22
-rw-r--r--chromium/components/services/unzip/public/cpp/BUILD.gn30
-rw-r--r--chromium/components/services/unzip/public/cpp/OWNERS4
-rw-r--r--chromium/components/services/unzip/public/cpp/manifest.cc40
-rw-r--r--chromium/components/services/unzip/public/cpp/manifest.h16
-rw-r--r--chromium/components/services/unzip/public/cpp/test_unzip_service.cc41
-rw-r--r--chromium/components/services/unzip/public/cpp/test_unzip_service.h51
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip.cc51
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip.h10
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip_unittest.cc25
-rw-r--r--chromium/components/services/unzip/public/mojom/BUILD.gn7
-rw-r--r--chromium/components/services/unzip/public/mojom/constants.mojom7
-rw-r--r--chromium/components/services/unzip/unzip_service.cc29
-rw-r--r--chromium/components/services/unzip/unzip_service.h34
-rw-r--r--chromium/components/services/unzip/unzipper_impl.cc7
-rw-r--r--chromium/components/services/unzip/unzipper_impl.h14
-rw-r--r--chromium/components/session_manager/OWNERS1
-rw-r--r--chromium/components/session_manager/core/OWNERS1
-rw-r--r--chromium/components/session_manager/core/session_manager.cc17
-rw-r--r--chromium/components/session_manager/core/session_manager.h1
-rw-r--r--chromium/components/session_manager/core/session_manager_observer.h11
-rw-r--r--chromium/components/sessions/BUILD.gn12
-rw-r--r--chromium/components/sessions/OWNERS1
-rw-r--r--chromium/components/sessions/content/OWNERS1
-rw-r--r--chromium/components/sessions/content/content_test_helper.cc37
-rw-r--r--chromium/components/sessions/content/content_test_helper.h31
-rw-r--r--chromium/components/sessions/core/DEPS3
-rw-r--r--chromium/components/sessions/core/base_session_service.cc5
-rw-r--r--chromium/components/sessions/core/serialized_navigation_entry_test_helper.cc15
-rw-r--r--chromium/components/sessions/core/serialized_navigation_entry_test_helper.h6
-rw-r--r--chromium/components/sessions/core/session_command.cc4
-rw-r--r--chromium/components/sessions/core/session_command.h10
-rw-r--r--chromium/components/sessions/core/session_service_commands.cc101
-rw-r--r--chromium/components/sessions/core/session_service_commands.h4
-rw-r--r--chromium/components/sessions/core/session_types.cc10
-rw-r--r--chromium/components/sessions/core/session_types.h35
-rw-r--r--chromium/components/sessions/ios/OWNERS1
-rw-r--r--chromium/components/sessions/ios/ios_live_tab.h4
-rw-r--r--chromium/components/signin/README9
-rw-r--r--chromium/components/signin/README.md13
-rw-r--r--chromium/components/signin/core/browser/BUILD.gn2
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.cc4
-rw-r--r--chromium/components/signin/core/browser/account_investigator_unittest.cc14
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.cc71
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.h5
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate.cc4
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate.h23
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_unittest.cc596
-rw-r--r--chromium/components/signin/core/browser/android/BUILD.gn1
-rw-r--r--chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java20
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_android.cc4
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_android.h4
-rw-r--r--chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc11
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc24
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h9
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc42
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller.cc13
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller.h12
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller_unittest.cc38
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper_unittest.cc8
-rw-r--r--chromium/components/signin/core/browser/signin_investigator_unittest.cc4
-rw-r--r--chromium/components/signin/internal/README.md3
-rw-r--r--chromium/components/signin/internal/identity_manager/BUILD.gn1
-rw-r--r--chromium/components/signin/internal/identity_manager/DEPS2
-rw-r--r--chromium/components/signin/internal/identity_manager/README.md72
-rw-r--r--chromium/components/signin/internal/identity_manager/account_fetcher_service.h6
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service.cc29
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service.h15
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc66
-rw-r--r--chromium/components/signin/internal/identity_manager/android/BUILD.gn9
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h6
-rw-r--r--chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc94
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h12
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc170
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc144
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h7
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc118
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h4
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc2
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc9
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc4
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager.h6
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc4
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc2
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h5
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc4
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc53
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h45
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h18
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc29
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h4
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc85
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm10
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc5
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h43
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc106
-rw-r--r--chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc7
-rw-r--r--chromium/components/signin/ios/browser/BUILD.gn2
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service_unittest.mm8
-rw-r--r--chromium/components/signin/ios/browser/active_state_manager_impl_unittest.mm2
-rw-r--r--chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc6
-rw-r--r--chromium/components/signin/public/README.md4
-rw-r--r--chromium/components/signin/public/base/README.md3
-rw-r--r--chromium/components/signin/public/base/signin_client.cc4
-rw-r--r--chromium/components/signin/public/base/signin_client.h8
-rw-r--r--chromium/components/signin/public/base/signin_metrics.h3
-rw-r--r--chromium/components/signin/public/base/signin_pref_names.cc6
-rw-r--r--chromium/components/signin/public/base/signin_pref_names.h1
-rw-r--r--chromium/components/signin/public/base/test_signin_client.cc12
-rw-r--r--chromium/components/signin/public/base/test_signin_client.h4
-rw-r--r--chromium/components/signin/public/identity_manager/BUILD.gn5
-rw-r--r--chromium/components/signin/public/identity_manager/README.md137
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher.cc4
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher.h125
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc4
-rw-r--r--chromium/components/signin/public/identity_manager/account_info.cc18
-rw-r--r--chromium/components/signin/public/identity_manager/account_info.h11
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc4
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc35
-rw-r--r--chromium/components/signin/public/identity_manager/android/BUILD.gn19
-rw-r--r--chromium/components/signin/public/identity_manager/android/DEPS5
-rw-r--r--chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountId.java51
-rw-r--r--chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountInfo.java84
-rw-r--r--chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java106
-rw-r--r--chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc4
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager.cc79
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager.h80
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_unittest.cc103
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment.cc4
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment.h4
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc15
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_utils.cc25
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_utils.h10
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc1
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h119
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc4
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_mutator.h5
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc18
-rw-r--r--chromium/components/signin/public/webdata/README.md3
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc4
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc6
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_platform_win.cc8
-rw-r--r--chromium/components/spellcheck/browser/spellcheck_platform_win_unittest.cc6
-rw-r--r--chromium/components/spellcheck/browser/spelling_service_client.cc2
-rw-r--r--chromium/components/spellcheck/common/OWNERS4
-rw-r--r--chromium/components/spellcheck/common/spellcheck.typemap6
-rw-r--r--chromium/components/spellcheck/common/spellcheck_features.cc2
-rw-r--r--chromium/components/spellcheck/common/spellcheck_mojom_traits.cc (renamed from chromium/components/spellcheck/common/spellcheck_struct_traits.cc)2
-rw-r--r--chromium/components/spellcheck/common/spellcheck_mojom_traits.h (renamed from chromium/components/spellcheck/common/spellcheck_struct_traits.h)6
-rw-r--r--chromium/components/spellcheck/renderer/empty_local_interface_provider.h2
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc4
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_unittest.cc49
-rw-r--r--chromium/components/ssl_errors/OWNERS1
-rw-r--r--chromium/components/ssl_errors/error_classification_unittest.cc6
-rw-r--r--chromium/components/ssl_errors/error_info.cc10
-rw-r--r--chromium/components/ssl_errors_strings_grdp/OWNERS1
-rw-r--r--chromium/components/startup_metric_utils/browser/pref_names.cc3
-rw-r--r--chromium/components/startup_metric_utils/browser/pref_names.h1
-rw-r--r--chromium/components/startup_metric_utils/browser/startup_metric_utils.cc80
-rw-r--r--chromium/components/startup_metric_utils/browser/startup_metric_utils.h4
-rw-r--r--chromium/components/storage_monitor/BUILD.gn2
-rw-r--r--chromium/components/storage_monitor/OWNERS1
-rw-r--r--chromium/components/storage_monitor/image_capture_device.mm4
-rw-r--r--chromium/components/storage_monitor/image_capture_device_manager_unittest.mm6
-rw-r--r--chromium/components/storage_monitor/media_storage_util.cc4
-rw-r--r--chromium/components/storage_monitor/media_storage_util_unittest.cc16
-rw-r--r--chromium/components/storage_monitor/mtp_manager_client_chromeos.cc5
-rw-r--r--chromium/components/storage_monitor/mtp_manager_client_chromeos.h2
-rw-r--r--chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc6
-rw-r--r--chromium/components/storage_monitor/portable_device_watcher_win.cc8
-rw-r--r--chromium/components/storage_monitor/portable_device_watcher_win.h2
-rw-r--r--chromium/components/storage_monitor/storage_monitor_chromeos.cc12
-rw-r--r--chromium/components/storage_monitor/storage_monitor_chromeos.h2
-rw-r--r--chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc12
-rw-r--r--chromium/components/storage_monitor/storage_monitor_dummy.cc38
-rw-r--r--chromium/components/storage_monitor/storage_monitor_linux.cc14
-rw-r--r--chromium/components/storage_monitor/storage_monitor_linux_unittest.cc12
-rw-r--r--chromium/components/storage_monitor/storage_monitor_mac.mm9
-rw-r--r--chromium/components/storage_monitor/storage_monitor_mac_unittest.mm6
-rw-r--r--chromium/components/storage_monitor/storage_monitor_unittest.cc10
-rw-r--r--chromium/components/storage_monitor/storage_monitor_win_unittest.cc4
-rw-r--r--chromium/components/storage_monitor/volume_mount_watcher_win.cc51
-rw-r--r--chromium/components/storage_monitor/volume_mount_watcher_win.h2
-rw-r--r--chromium/components/strings/components_chromium_strings_mr.xtb2
-rw-r--r--chromium/components/strings/components_google_chrome_strings_ml.xtb7
-rw-r--r--chromium/components/strings/components_google_chrome_strings_mr.xtb2
-rw-r--r--chromium/components/strings/components_strings_am.xtb90
-rw-r--r--chromium/components/strings/components_strings_ar.xtb92
-rw-r--r--chromium/components/strings/components_strings_bg.xtb90
-rw-r--r--chromium/components/strings/components_strings_bn.xtb93
-rw-r--r--chromium/components/strings/components_strings_ca.xtb108
-rw-r--r--chromium/components/strings/components_strings_cs.xtb90
-rw-r--r--chromium/components/strings/components_strings_da.xtb95
-rw-r--r--chromium/components/strings/components_strings_de.xtb98
-rw-r--r--chromium/components/strings/components_strings_el.xtb93
-rw-r--r--chromium/components/strings/components_strings_en-GB.xtb93
-rw-r--r--chromium/components/strings/components_strings_es-419.xtb90
-rw-r--r--chromium/components/strings/components_strings_es.xtb93
-rw-r--r--chromium/components/strings/components_strings_et.xtb93
-rw-r--r--chromium/components/strings/components_strings_fa.xtb93
-rw-r--r--chromium/components/strings/components_strings_fi.xtb97
-rw-r--r--chromium/components/strings/components_strings_fil.xtb93
-rw-r--r--chromium/components/strings/components_strings_fr.xtb90
-rw-r--r--chromium/components/strings/components_strings_gu.xtb93
-rw-r--r--chromium/components/strings/components_strings_hi.xtb94
-rw-r--r--chromium/components/strings/components_strings_hr.xtb93
-rw-r--r--chromium/components/strings/components_strings_hu.xtb98
-rw-r--r--chromium/components/strings/components_strings_id.xtb93
-rw-r--r--chromium/components/strings/components_strings_it.xtb93
-rw-r--r--chromium/components/strings/components_strings_iw.xtb93
-rw-r--r--chromium/components/strings/components_strings_ja.xtb92
-rw-r--r--chromium/components/strings/components_strings_kn.xtb91
-rw-r--r--chromium/components/strings/components_strings_ko.xtb90
-rw-r--r--chromium/components/strings/components_strings_lt.xtb93
-rw-r--r--chromium/components/strings/components_strings_lv.xtb90
-rw-r--r--chromium/components/strings/components_strings_ml.xtb172
-rw-r--r--chromium/components/strings/components_strings_mr.xtb171
-rw-r--r--chromium/components/strings/components_strings_ms.xtb93
-rw-r--r--chromium/components/strings/components_strings_nl.xtb90
-rw-r--r--chromium/components/strings/components_strings_no.xtb93
-rw-r--r--chromium/components/strings/components_strings_pl.xtb93
-rw-r--r--chromium/components/strings/components_strings_pt-BR.xtb90
-rw-r--r--chromium/components/strings/components_strings_pt-PT.xtb93
-rw-r--r--chromium/components/strings/components_strings_ro.xtb90
-rw-r--r--chromium/components/strings/components_strings_ru.xtb92
-rw-r--r--chromium/components/strings/components_strings_sk.xtb94
-rw-r--r--chromium/components/strings/components_strings_sl.xtb93
-rw-r--r--chromium/components/strings/components_strings_sr.xtb93
-rw-r--r--chromium/components/strings/components_strings_sv.xtb93
-rw-r--r--chromium/components/strings/components_strings_sw.xtb97
-rw-r--r--chromium/components/strings/components_strings_ta.xtb100
-rw-r--r--chromium/components/strings/components_strings_te.xtb90
-rw-r--r--chromium/components/strings/components_strings_th.xtb90
-rw-r--r--chromium/components/strings/components_strings_tr.xtb91
-rw-r--r--chromium/components/strings/components_strings_uk.xtb90
-rw-r--r--chromium/components/strings/components_strings_vi.xtb93
-rw-r--r--chromium/components/strings/components_strings_zh-CN.xtb92
-rw-r--r--chromium/components/strings/components_strings_zh-TW.xtb90
-rw-r--r--chromium/components/subresource_filter/FILTER_LIST_GENERATION.md9
-rw-r--r--chromium/components/subresource_filter/content/browser/BUILD.gn4
-rw-r--r--chromium/components/subresource_filter/content/browser/DEPS1
-rw-r--r--chromium/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc4
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc298
-rw-r--r--chromium/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc11
-rw-r--r--chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.cc9
-rw-r--r--chromium/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc4
-rw-r--r--chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc4
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc111
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h15
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc151
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.cc42
-rw-r--r--chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.h34
-rw-r--r--chromium/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc6
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc47
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h1
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc64
-rw-r--r--chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc58
-rw-r--r--chromium/components/subresource_filter/core/common/BUILD.gn2
-rw-r--r--chromium/components/subresource_filter/core/common/indexed_ruleset_fuzzer.cc3
-rw-r--r--chromium/components/subresource_filter/core/common/load_policy.cc15
-rw-r--r--chromium/components/subresource_filter/core/common/load_policy.h9
-rw-r--r--chromium/components/subresource_filter/core/common/load_policy_unittest.cc22
-rw-r--r--chromium/components/subresource_filter/tools/BUILD.gn7
-rw-r--r--chromium/components/subresource_filter/tools/filter_tool_main.cc36
-rw-r--r--chromium/components/suggestions/BUILD.gn2
-rw-r--r--chromium/components/suggestions/suggestions_service_impl.cc4
-rw-r--r--chromium/components/suggestions/suggestions_service_impl.h7
-rw-r--r--chromium/components/suggestions/suggestions_service_impl_unittest.cc54
-rw-r--r--chromium/components/supervised_user_error_page/BUILD.gn46
-rw-r--r--chromium/components/supervised_user_error_page/DEPS9
-rw-r--r--chromium/components/supervised_user_error_page/OWNERS4
-rw-r--r--chromium/components/supervised_user_error_page/resources/OWNERS2
-rw-r--r--chromium/components/supervised_user_error_page/resources/default_100_percent/logo_avatar_circle_blue_color.pngbin1531 -> 0 bytes
-rw-r--r--chromium/components/supervised_user_error_page/resources/default_200_percent/logo_avatar_circle_blue_color.pngbin2976 -> 0 bytes
-rw-r--r--chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.css536
-rw-r--r--chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.html65
-rw-r--r--chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js150
-rw-r--r--chromium/components/supervised_user_error_page/supervised_user_error_page.cc183
-rw-r--r--chromium/components/supervised_user_error_page/supervised_user_error_page.h42
-rw-r--r--chromium/components/supervised_user_error_page/supervised_user_error_page_unittest.cc208
-rw-r--r--chromium/components/supervised_user_error_page_strings.grdp86
-rw-r--r--chromium/components/supervised_user_error_page_strings_grdp/OWNERS1
-rw-r--r--chromium/components/supervised_user_error_page_strings_grdp/README.md5
-rw-r--r--chromium/components/sync/BUILD.gn7
-rw-r--r--chromium/components/sync/mojom/syncer.typemap2
-rw-r--r--chromium/components/sync/protocol/BUILD.gn24
-rw-r--r--chromium/components/sync_bookmarks/OWNERS1
-rw-r--r--chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc4
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc4
-rw-r--r--chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc3
-rw-r--r--chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc29
-rw-r--r--chromium/components/sync_device_info/device_info_sync_bridge_unittest.cc4
-rw-r--r--chromium/components/sync_device_info/fake_device_info_tracker.cc8
-rw-r--r--chromium/components/sync_device_info/fake_device_info_tracker.h3
-rw-r--r--chromium/components/sync_preferences/pref_model_associator.cc11
-rw-r--r--chromium/components/sync_sessions/DEPS2
-rw-r--r--chromium/components/sync_sessions/favicon_cache.h6
-rw-r--r--chromium/components/sync_sessions/favicon_cache_unittest.cc9
-rw-r--r--chromium/components/sync_sessions/local_session_event_handler_impl.cc4
-rw-r--r--chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc4
-rw-r--r--chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc58
-rw-r--r--chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc8
-rw-r--r--chromium/components/sync_sessions/proxy_tabs_data_type_controller.h4
-rw-r--r--chromium/components/sync_sessions/session_model_type_controller.cc16
-rw-r--r--chromium/components/sync_sessions/session_model_type_controller.h2
-rw-r--r--chromium/components/sync_sessions/session_store_unittest.cc4
-rw-r--r--chromium/components/sync_sessions/session_sync_bridge_unittest.cc4
-rw-r--r--chromium/components/sync_sessions/session_sync_test_helper.cc2
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker.cc2
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker_unittest.cc15
-rw-r--r--chromium/components/sync_sessions/synced_session_unittest.cc8
-rw-r--r--chromium/components/sync_sessions/synced_window_delegate.h7
-rw-r--r--chromium/components/sync_sessions/test_synced_window_delegates_getter.cc6
-rw-r--r--chromium/components/sync_sessions/test_synced_window_delegates_getter.h3
-rw-r--r--chromium/components/sync_user_events/user_event_model_type_controller.cc14
-rw-r--r--chromium/components/sync_user_events/user_event_model_type_controller.h2
-rw-r--r--chromium/components/sync_user_events/user_event_service_impl_unittest.cc4
-rw-r--r--chromium/components/sync_user_events/user_event_sync_bridge_unittest.cc4
-rw-r--r--chromium/components/timers/OWNERS1
-rw-r--r--chromium/components/timers/alarm_timer_chromeos.cc2
-rw-r--r--chromium/components/timers/alarm_timer_chromeos.h2
-rw-r--r--chromium/components/timers/alarm_timer_unittest.cc50
-rw-r--r--chromium/components/tracing/child/background_tracing_agent_impl_unittest.cc4
-rw-r--r--chromium/components/tracing/common/trace_startup_config.cc40
-rw-r--r--chromium/components/tracing/common/trace_startup_config.h4
-rw-r--r--chromium/components/translate/content/common/translate.typemap8
-rw-r--r--chromium/components/ui_devtools/BUILD.gn26
-rw-r--r--chromium/components/ui_devtools/DEPS2
-rw-r--r--chromium/components/ui_devtools/agent_util.cc55
-rw-r--r--chromium/components/ui_devtools/agent_util.h22
-rw-r--r--chromium/components/ui_devtools/connector_delegate.h27
-rw-r--r--chromium/components/ui_devtools/css_agent.cc80
-rw-r--r--chromium/components/ui_devtools/css_agent.h5
-rw-r--r--chromium/components/ui_devtools/css_agent_unittest.cc63
-rw-r--r--chromium/components/ui_devtools/devtools_protocol_encoding.cc14
-rw-r--r--chromium/components/ui_devtools/devtools_protocol_encoding.h12
-rw-r--r--chromium/components/ui_devtools/devtools_server.h7
-rw-r--r--chromium/components/ui_devtools/devtools_server_unittest.cc6
-rw-r--r--chromium/components/ui_devtools/dom_agent.cc12
-rw-r--r--chromium/components/ui_devtools/dom_agent.h6
-rw-r--r--chromium/components/ui_devtools/inspector_protocol_config.json20
-rw-r--r--chromium/components/ui_devtools/protocol.json228
-rw-r--r--chromium/components/ui_devtools/tracing_agent.cc541
-rw-r--r--chromium/components/ui_devtools/tracing_agent.h116
-rw-r--r--chromium/components/ui_devtools/ui_element.cc14
-rw-r--r--chromium/components/ui_devtools/ui_element.h21
-rw-r--r--chromium/components/ui_devtools/views/BUILD.gn2
-rw-r--r--chromium/components/ui_devtools/views/DEPS1
-rw-r--r--chromium/components/ui_devtools/views/devtools_server_util.cc8
-rw-r--r--chromium/components/ui_devtools/views/devtools_server_util.h5
-rw-r--r--chromium/components/ui_devtools/views/dom_agent_unittest.cc59
-rw-r--r--chromium/components/ui_devtools/views/element_utility.cc12
-rw-r--r--chromium/components/ui_devtools/views/element_utility.h5
-rw-r--r--chromium/components/ui_devtools/views/overlay_agent_unittest.cc2
-rw-r--r--chromium/components/ui_devtools/views/overlay_agent_views.cc16
-rw-r--r--chromium/components/ui_devtools/views/page_agent_views.cc99
-rw-r--r--chromium/components/ui_devtools/views/page_agent_views.h9
-rw-r--r--chromium/components/ui_devtools/views/page_agent_views_unittest.cc193
-rw-r--r--chromium/components/ui_devtools/views/view_element.cc65
-rw-r--r--chromium/components/ui_devtools/views/view_element.h1
-rw-r--r--chromium/components/ui_devtools/views/view_element_unittest.cc49
-rw-r--r--chromium/components/ui_devtools/views/widget_element.cc5
-rw-r--r--chromium/components/ui_devtools/views/widget_element.h1
-rw-r--r--chromium/components/ui_devtools/views/widget_element_unittest.cc2
-rw-r--r--chromium/components/ui_devtools/views/window_element.cc7
-rw-r--r--chromium/components/ui_devtools/views/window_element.h1
-rw-r--r--chromium/components/ui_metrics/OWNERS3
-rw-r--r--chromium/components/ukm/app_source_url_recorder_test.cc4
-rw-r--r--chromium/components/ukm/content/source_url_recorder_browsertest.cc9
-rw-r--r--chromium/components/ukm/debug/ukm_internals.js2
-rw-r--r--chromium/components/ukm/ukm_recorder_impl.cc17
-rw-r--r--chromium/components/ukm/ukm_service.cc12
-rw-r--r--chromium/components/ukm/ukm_service.h14
-rw-r--r--chromium/components/ukm/ukm_service_unittest.cc18
-rw-r--r--chromium/components/undo/bookmark_undo_service.cc5
-rw-r--r--chromium/components/undo/bookmark_undo_service.h8
-rw-r--r--chromium/components/undo_strings.grdp4
-rw-r--r--chromium/components/unified_consent/unified_consent_service_unittest.cc4
-rw-r--r--chromium/components/update_client/BUILD.gn15
-rw-r--r--chromium/components/update_client/DEPS3
-rw-r--r--chromium/components/update_client/OWNERS1
-rw-r--r--chromium/components/update_client/action_runner.cc2
-rw-r--r--chromium/components/update_client/action_runner_win.cc9
-rw-r--r--chromium/components/update_client/background_downloader_win.cc4
-rw-r--r--chromium/components/update_client/component.cc18
-rw-r--r--chromium/components/update_client/component_patcher_unittest.cc36
-rw-r--r--chromium/components/update_client/component_patcher_unittest.h4
-rw-r--r--chromium/components/update_client/component_unpacker_unittest.cc15
-rw-r--r--chromium/components/update_client/crx_downloader.cc2
-rw-r--r--chromium/components/update_client/crx_downloader_unittest.cc15
-rw-r--r--chromium/components/update_client/net/network_impl.cc10
-rw-r--r--chromium/components/update_client/patch/patch_impl.cc18
-rw-r--r--chromium/components/update_client/patch/patch_impl.h14
-rw-r--r--chromium/components/update_client/ping_manager_unittest.cc9
-rw-r--r--chromium/components/update_client/protocol_serializer_json.cc4
-rw-r--r--chromium/components/update_client/protocol_serializer_json_unittest.cc8
-rw-r--r--chromium/components/update_client/request_sender_unittest.cc9
-rw-r--r--chromium/components/update_client/task_traits.h6
-rw-r--r--chromium/components/update_client/test_configurator.cc17
-rw-r--r--chromium/components/update_client/test_configurator.h7
-rw-r--r--chromium/components/update_client/test_installer.cc4
-rw-r--r--chromium/components/update_client/unzip/unzip_impl.cc17
-rw-r--r--chromium/components/update_client/unzip/unzip_impl.h14
-rw-r--r--chromium/components/update_client/update_checker.cc2
-rw-r--r--chromium/components/update_client/update_checker_unittest.cc14
-rw-r--r--chromium/components/update_client/update_client_unittest.cc143
-rw-r--r--chromium/components/update_client/update_query_params.cc19
-rw-r--r--chromium/components/update_client/updater_state.cc5
-rw-r--r--chromium/components/update_client/updater_state_unittest.cc8
-rw-r--r--chromium/components/update_client/url_fetcher_downloader.cc6
-rw-r--r--chromium/components/update_client/utils_unittest.cc2
-rw-r--r--chromium/components/upload_list/text_log_upload_list_unittest.cc4
-rw-r--r--chromium/components/upload_list/upload_list.cc8
-rw-r--r--chromium/components/url_formatter/BUILD.gn6
-rw-r--r--chromium/components/url_formatter/OWNERS1
-rw-r--r--chromium/components/url_formatter/elide_url_unittest.cc6
-rw-r--r--chromium/components/url_formatter/spoof_checks/OWNERS1
-rw-r--r--chromium/components/url_formatter/spoof_checks/idn_spoof_checker.cc77
-rw-r--r--chromium/components/url_formatter/spoof_checks/idn_spoof_checker.h22
-rw-r--r--chromium/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc139
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/BUILD.gn (renamed from chromium/components/url_formatter/top_domains/BUILD.gn)18
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/README23
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/domains.list5001
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/domains.skeletons5011
-rwxr-xr-xchromium/components/url_formatter/spoof_checks/top_domains/make_alexa_top_list.py (renamed from chromium/components/url_formatter/top_domains/make_alexa_top_list.py)0
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_for_edit_distance.cc (renamed from chromium/components/url_formatter/top_domains/make_top_domain_list_for_edit_distance.cc)4
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/make_top_domain_skeletons.cc (renamed from chromium/components/url_formatter/top_domains/make_top_domain_skeletons.cc)8
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/test_domains.list (renamed from chromium/components/url_formatter/top_domains/test_domains.list)1
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/test_domains.skeletons (renamed from chromium/components/url_formatter/top_domains/test_domains.skeletons)3
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top500_domains.h (renamed from chromium/components/url_formatter/top_domains/top500_domains.h)6
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domain_generator.cc (renamed from chromium/components/url_formatter/top_domains/top_domain_generator.cc)25
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.cc (renamed from chromium/components/url_formatter/top_domains/top_domain_state_generator.cc)4
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.h (renamed from chromium/components/url_formatter/top_domains/top_domain_state_generator.h)8
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util.cc (renamed from chromium/components/url_formatter/top_domains/top_domain_util.cc)2
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util.h (renamed from chromium/components/url_formatter/top_domains/top_domain_util.h)6
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util_unittest.cc (renamed from chromium/components/url_formatter/top_domains/top_domain_util_unittest.cc)2
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/top_domains_trie.template (renamed from chromium/components/url_formatter/top_domains/top_domains_trie.template)0
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/trie_entry.cc (renamed from chromium/components/url_formatter/top_domains/trie_entry.cc)4
-rw-r--r--chromium/components/url_formatter/spoof_checks/top_domains/trie_entry.h (renamed from chromium/components/url_formatter/top_domains/trie_entry.h)7
-rw-r--r--chromium/components/url_formatter/top_domains/README24
-rw-r--r--chromium/components/url_formatter/top_domains/alexa_domains.list9174
-rw-r--r--chromium/components/url_formatter/top_domains/alexa_domains.skeletons9185
-rw-r--r--chromium/components/url_formatter/url_fixer_unittest.cc2
-rw-r--r--chromium/components/url_formatter/url_formatter.cc5
-rw-r--r--chromium/components/url_formatter/url_formatter.h7
-rw-r--r--chromium/components/url_matcher/OWNERS1
-rw-r--r--chromium/components/url_pattern_index/OWNERS3
-rw-r--r--chromium/components/user_manager/OWNERS1
-rw-r--r--chromium/components/user_manager/fake_user_manager.cc5
-rw-r--r--chromium/components/user_manager/fake_user_manager.h1
-rw-r--r--chromium/components/user_manager/user.cc18
-rw-r--r--chromium/components/user_manager/user.h8
-rw-r--r--chromium/components/user_manager/user_manager.cc32
-rw-r--r--chromium/components/user_manager/user_manager.h25
-rw-r--r--chromium/components/user_manager/user_manager_base.cc27
-rw-r--r--chromium/components/user_manager/user_manager_base.h5
-rw-r--r--chromium/components/user_prefs/OWNERS1
-rw-r--r--chromium/components/variations/child_process_field_trial_syncer_unittest.cc4
-rw-r--r--chromium/components/variations/client_filterable_state.h5
-rw-r--r--chromium/components/variations/net/BUILD.gn2
-rw-r--r--chromium/components/variations/proto/study.proto16
-rw-r--r--chromium/components/variations/service/BUILD.gn1
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.cc9
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.h30
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator_unittest.cc11
-rw-r--r--chromium/components/variations/service/variations_service.cc16
-rw-r--r--chromium/components/variations/service/variations_service.h17
-rw-r--r--chromium/components/variations/service/variations_service_client.h14
-rw-r--r--chromium/components/variations/service/variations_service_unittest.cc5
-rw-r--r--chromium/components/variations/study_filtering.cc10
-rw-r--r--chromium/components/variations/study_filtering.h3
-rw-r--r--chromium/components/variations/study_filtering_unittest.cc17
-rw-r--r--chromium/components/variations/synthetic_trial_registry_unittest.cc4
-rw-r--r--chromium/components/variations/variations_associated_data.h10
-rw-r--r--chromium/components/variations/variations_crash_keys_unittest.cc4
-rw-r--r--chromium/components/variations/variations_http_header_provider_unittest.cc14
-rw-r--r--chromium/components/variations/variations_id_collection_unittest.cc4
-rw-r--r--chromium/components/variations/variations_request_scheduler_mobile_unittest.cc8
-rw-r--r--chromium/components/variations/variations_request_scheduler_unittest.cc4
-rw-r--r--chromium/components/vector_icons/BUILD.gn3
-rw-r--r--chromium/components/vector_icons/devices.icon34
-rw-r--r--chromium/components/vector_icons/notifications_off.icon38
-rw-r--r--chromium/components/vector_icons/queue_music.icon32
-rw-r--r--chromium/components/version_info/BUILD.gn1
-rw-r--r--chromium/components/version_info/android/java/VersionConstants.java.version4
-rw-r--r--chromium/components/version_info/android/java/src/org/chromium/components/version_info/VersionConstantsBridge.java2
-rw-r--r--chromium/components/version_info/version_info.cc3
-rw-r--r--chromium/components/version_ui/resources/about_version.html1
-rw-r--r--chromium/components/version_ui/resources/about_version.js40
-rw-r--r--chromium/components/version_ui/version_ui_constants.cc14
-rw-r--r--chromium/components/version_ui/version_ui_constants.h13
-rw-r--r--chromium/components/visitedlink/browser/visitedlink_master.cc10
-rw-r--r--chromium/components/visitedlink/browser/visitedlink_master.h5
-rw-r--r--chromium/components/viz/OWNERS2
-rw-r--r--chromium/components/viz/client/BUILD.gn4
-rw-r--r--chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc1
-rw-r--r--chromium/components/viz/client/local_surface_id_provider.cc19
-rw-r--r--chromium/components/viz/client/local_surface_id_provider.h35
-rw-r--r--chromium/components/viz/common/BUILD.gn25
-rw-r--r--chromium/components/viz/common/display/de_jelly.cc59
-rw-r--r--chromium/components/viz/common/display/de_jelly.h35
-rw-r--r--chromium/components/viz/common/display/renderer_settings.h2
-rw-r--r--chromium/components/viz/common/features.cc17
-rw-r--r--chromium/components/viz/common/features.h4
-rw-r--r--chromium/components/viz/common/frame_sinks/begin_frame_source.cc3
-rw-r--r--chromium/components/viz/common/frame_sinks/begin_frame_source.h7
-rw-r--r--chromium/components/viz/common/frame_timing_details.h2
-rw-r--r--chromium/components/viz/common/gl_helper_benchmark.cc4
-rw-r--r--chromium/components/viz/common/gpu/context_cache_controller_unittest.cc2
-rw-r--r--chromium/components/viz/common/gpu/metal_api_proxy.h8
-rw-r--r--chromium/components/viz/common/gpu/metal_api_proxy.mm119
-rw-r--r--chromium/components/viz/common/gpu/metal_context_provider.mm86
-rw-r--r--chromium/components/viz/common/gpu/vulkan_in_process_context_provider.cc3
-rw-r--r--chromium/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java16
-rw-r--r--chromium/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java152
-rw-r--r--chromium/components/viz/common/quads/compositor_frame_metadata.h22
-rw-r--r--chromium/components/viz/common/quads/draw_quad_unittest.cc3
-rw-r--r--chromium/components/viz/common/quads/shared_quad_state.cc8
-rw-r--r--chromium/components/viz/common/quads/shared_quad_state.h19
-rw-r--r--chromium/components/viz/common/quads/surface_draw_quad.cc4
-rw-r--r--chromium/components/viz/common/quads/surface_draw_quad.h6
-rw-r--r--chromium/components/viz/common/resources/resource_format_utils.cc9
-rw-r--r--chromium/components/viz/common/switches.cc17
-rw-r--r--chromium/components/viz/common/switches.h4
-rw-r--r--chromium/components/viz/demo/BUILD.gn6
-rw-r--r--chromium/components/viz/demo/client/demo_client.h2
-rw-r--r--chromium/components/viz/demo/demo_main.cc14
-rw-r--r--chromium/components/viz/demo/host/demo_host.h4
-rw-r--r--chromium/components/viz/demo/service/demo_service.cc6
-rw-r--r--chromium/components/viz/demo/service/demo_service.h6
-rw-r--r--chromium/components/viz/host/BUILD.gn16
-rw-r--r--chromium/components/viz/host/DEPS7
-rw-r--r--chromium/components/viz/host/client_frame_sink_video_capturer.h4
-rw-r--r--chromium/components/viz/host/gpu_client.cc2
-rw-r--r--chromium/components/viz/host/gpu_client.h2
-rw-r--r--chromium/components/viz/host/gpu_host_impl.cc8
-rw-r--r--chromium/components/viz/host/gpu_host_impl.h11
-rw-r--r--chromium/components/viz/host/hit_test/DEPS2
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query.cc56
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query.h11
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query_fuzzer.cc3
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query_unittest.cc73
-rw-r--r--chromium/components/viz/host/host_display_client.h2
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager.cc10
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager.h4
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager_unittest.cc2
-rw-r--r--chromium/components/viz/host/host_gpu_memory_buffer_manager.cc2
-rw-r--r--chromium/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc2
-rw-r--r--chromium/components/viz/host/layered_window_updater_impl.h2
-rw-r--r--chromium/components/viz/host/renderer_settings_creation.cc6
-rw-r--r--chromium/components/viz/service/BUILD.gn23
-rw-r--r--chromium/components/viz/service/DEPS4
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc1
-rw-r--r--chromium/components/viz/service/display/DEPS2
-rw-r--r--chromium/components/viz/service/display/bsp_tree_perftest.cc7
-rw-r--r--chromium/components/viz/service/display/damage_frame_annotator.cc99
-rw-r--r--chromium/components/viz/service/display/damage_frame_annotator.h50
-rw-r--r--chromium/components/viz/service/display/dc_layer_overlay.cc393
-rw-r--r--chromium/components/viz/service/display/dc_layer_overlay.h62
-rw-r--r--chromium/components/viz/service/display/direct_renderer.cc40
-rw-r--r--chromium/components/viz/service/display/direct_renderer.h5
-rw-r--r--chromium/components/viz/service/display/display.cc58
-rw-r--r--chromium/components/viz/service/display/display.h8
-rw-r--r--chromium/components/viz/service/display/display_resource_provider.cc146
-rw-r--r--chromium/components/viz/service/display/display_resource_provider.h39
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_unittest.cc48
-rw-r--r--chromium/components/viz/service/display/display_scheduler.h1
-rw-r--r--chromium/components/viz/service/display/display_scheduler_unittest.cc2
-rw-r--r--chromium/components/viz/service/display/external_use_client.cc28
-rw-r--r--chromium/components/viz/service/display/external_use_client.h96
-rw-r--r--chromium/components/viz/service/display/gl_renderer.cc126
-rw-r--r--chromium/components/viz/service/display/gl_renderer.h8
-rw-r--r--chromium/components/viz/service/display/gl_renderer_unittest.cc89
-rw-r--r--chromium/components/viz/service/display/overlay_candidate.cc4
-rw-r--r--chromium/components/viz/service/display/overlay_candidate.h3
-rw-r--r--chromium/components/viz/service/display/overlay_candidate_validator.cc36
-rw-r--r--chromium/components/viz/service/display/overlay_candidate_validator.h30
-rw-r--r--chromium/components/viz/service/display/overlay_processor.cc154
-rw-r--r--chromium/components/viz/service/display/overlay_processor.h71
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_fullscreen.cc12
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_fullscreen.h2
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_single_on_top.cc11
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_single_on_top.h2
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay.cc28
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay.h4
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc11
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay_cast.h1
-rw-r--r--chromium/components/viz/service/display/overlay_unittest.cc480
-rw-r--r--chromium/components/viz/service/display/renderer_perftest.cc25
-rw-r--r--chromium/components/viz/service/display/renderer_pixeltest.cc10
-rw-r--r--chromium/components/viz/service/display/resource_metadata.cc18
-rw-r--r--chromium/components/viz/service/display/resource_metadata.h57
-rw-r--r--chromium/components/viz/service/display/skia_output_surface.h40
-rw-r--r--chromium/components/viz/service/display/skia_renderer.cc214
-rw-r--r--chromium/components/viz/service/display/skia_renderer.h16
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.cc828
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.h133
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_unittest.cc384
-rw-r--r--chromium/components/viz/service/display_embedder/DEPS1
-rw-r--r--chromium/components/viz/service/display_embedder/compositing_mode_reporter_impl.h2
-rw-r--r--chromium/components/viz/service/display_embedder/direct_context_provider.cc21
-rw-r--r--chromium/components/viz/service/display_embedder/image_context.cc51
-rw-r--r--chromium/components/viz/service/display_embedder/image_context.h87
-rw-r--r--chromium/components/viz/service/display_embedder/image_context_impl.cc217
-rw-r--r--chromium/components/viz/service/display_embedder/image_context_impl.h116
-rw-r--r--chromium/components/viz/service/display_embedder/output_surface_provider.h2
-rw-r--r--chromium/components/viz/service/display_embedder/output_surface_provider_impl.cc12
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.cc1
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.h3
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.cc1
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.h3
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.cc97
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.h3
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.cc41
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.h5
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control_unittest.cc24
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.cc1
-rw-r--r--chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.h3
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device.cc68
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device.h18
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc228
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.h36
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_gl.cc52
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_gl.h21
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_offscreen.cc83
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_offscreen.h14
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_vulkan.cc6
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_x11.cc4
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_x11.h2
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc254
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl.h30
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc363
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h35
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_win.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_win.h2
-rw-r--r--chromium/components/viz/service/display_embedder/viz_process_context_provider.cc8
-rw-r--r--chromium/components/viz/service/display_embedder/vsync_parameter_listener.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc43
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h17
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc88
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc26
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h9
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc3
-rw-r--r--chromium/components/viz/service/frame_sinks/external_begin_frame_source_mojo.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h6
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc16
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h6
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc16
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc27
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h3
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc2
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/video_detector.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/video_detector_unittest.cc2
-rw-r--r--chromium/components/viz/service/gl/DEPS2
-rw-r--r--chromium/components/viz/service/gl/OWNERS1
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl.cc24
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl.h13
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl_unittest.cc2
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.cc17
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.h2
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc3
-rw-r--r--chromium/components/viz/service/main/BUILD.gn10
-rw-r--r--chromium/components/viz/service/main/DEPS3
-rw-r--r--chromium/components/viz/service/main/viz_compositor_thread_runner.h87
-rw-r--r--chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc (renamed from chromium/components/viz/service/main/viz_compositor_thread_runner.cc)79
-rw-r--r--chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h91
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.cc29
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.h15
-rw-r--r--chromium/components/viz/service/surfaces/surface.cc37
-rw-r--r--chromium/components/viz/service/surfaces/surface.h12
-rw-r--r--chromium/components/viz/service/surfaces/surface_allocation_group.cc5
-rw-r--r--chromium/components/viz/service/surfaces/surface_client.h6
-rw-r--r--chromium/components/viz/test/BUILD.gn2
-rw-r--r--chromium/components/web_cache/OWNERS1
-rw-r--r--chromium/components/web_cache/browser/web_cache_manager_unittest.cc4
-rw-r--r--chromium/components/web_modal/OWNERS1
-rw-r--r--chromium/components/web_resource/BUILD.gn3
-rw-r--r--chromium/components/web_resource/OWNERS5
-rw-r--r--chromium/components/web_resource/eula_accepted_notifier.cc3
-rw-r--r--chromium/components/web_resource/resource_request_allowed_notifier_unittest.cc6
-rw-r--r--chromium/components/web_resource/web_resource_service.cc5
-rw-r--r--chromium/components/web_resource/web_resource_service_unittest.cc4
-rw-r--r--chromium/components/webdata/common/BUILD.gn1
-rw-r--r--chromium/components/webdata/common/web_database.cc2
-rw-r--r--chromium/components/webdata/common/web_database_migration_unittest.cc35
-rw-r--r--chromium/components/webdata_services/web_data_service_wrapper.cc45
-rw-r--r--chromium/components/webrtc_logging/OWNERS1
-rw-r--r--chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc4
-rw-r--r--chromium/components/wifi/wifi_test.cc12
-rw-r--r--chromium/components/zucchini/zucchini_main.cc2
2828 files changed, 77076 insertions, 67008 deletions
diff --git a/chromium/components/BUILD.gn b/chromium/components/BUILD.gn
index 4754a74e631..8152a082205 100644
--- a/chromium/components/BUILD.gn
+++ b/chromium/components/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/chrome_build.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//components/nacl/features.gni")
+import("//components/safe_browsing/buildflags.gni")
import("//components/ui_devtools/devtools.gni")
import("//media/media_options.gni")
import("//ppapi/buildflags/buildflags.gni")
@@ -97,9 +98,8 @@ test("components_unittests") {
"//components/flags_ui:unit_tests",
"//components/gcm_driver:unit_tests",
"//components/gcm_driver/crypto:unit_tests",
- "//components/google/core/browser:unit_tests",
+ "//components/google/core/common:unit_tests",
"//components/grpc_support/test:unit_tests",
- "//components/gwp_asan:unit_tests",
"//components/history/core/browser:unit_tests",
"//components/history/core/common:unit_tests",
"//components/image_fetcher/core:unit_tests",
@@ -136,6 +136,7 @@ test("components_unittests") {
"//components/security_state/core:unit_tests",
"//components/send_tab_to_self:unit_tests",
"//components/services/heap_profiling/public/cpp:unit_tests",
+ "//components/services/storage:tests",
"//components/services/unzip:unit_tests",
"//components/sessions:unit_tests",
"//components/signin/core/browser:unit_tests",
@@ -148,7 +149,6 @@ test("components_unittests") {
"//components/subresource_filter/core/common:unit_tests",
"//components/subresource_filter/tools:unit_tests",
"//components/suggestions:unit_tests",
- "//components/supervised_user_error_page:unit_tests",
"//components/sync:unit_tests",
"//components/sync_bookmarks:unit_tests",
"//components/sync_device_info:unit_tests",
@@ -166,7 +166,7 @@ test("components_unittests") {
"//components/update_client:unit_tests",
"//components/upload_list:unit_tests",
"//components/url_formatter:unit_tests",
- "//components/url_formatter/top_domains:unit_tests",
+ "//components/url_formatter/spoof_checks/top_domains:unit_tests",
"//components/url_matcher:unit_tests",
"//components/url_pattern_index:unit_tests",
"//components/variations:unit_tests",
@@ -239,6 +239,7 @@ test("components_unittests") {
"//components/optimization_guide:unit_tests",
"//components/page_image_annotation/content/renderer:unit_tests",
"//components/page_image_annotation/core:unit_tests",
+ "//components/page_load_metrics/renderer:unit_tests",
"//components/password_manager/content/browser:unit_tests",
"//components/payments/content:unit_tests",
"//components/payments/content/utility:unit_tests",
@@ -298,6 +299,7 @@ test("components_unittests") {
"//components/policy/android:policy_java",
"//components/signin/core/browser",
"//components/signin/core/browser/android:java",
+ "//components/signin/public/identity_manager/android:java",
"//components/spellcheck/browser/android:java",
"//components/variations/android:variations_java",
"//content/public/android:content_java",
@@ -341,7 +343,8 @@ test("components_unittests") {
if (is_chromeos) {
deps += [
"//components/arc:unit_tests",
- "//components/arc/common:unit_tests",
+ "//components/arc/mojom:unit_tests",
+ "//components/guest_os:unit_tests",
"//components/ownership:unit_tests",
"//components/timers:unit_tests",
"//components/user_manager:unit_tests",
@@ -369,6 +372,7 @@ test("components_unittests") {
deps += [
"//components/safe_browsing:verdict_cache_manager_unittest",
"//components/safe_browsing/db:unit_tests_desktop",
+ "//components/safe_browsing/realtime:unit_tests",
]
} else if (safe_browsing_mode == 2) {
deps += [ "//components/safe_browsing/android:unit_tests_mobile" ]
@@ -387,6 +391,10 @@ test("components_unittests") {
deps += [ "//components/dbus/menu:unit_tests" ]
}
+ if (enable_plugins) {
+ deps += [ "//components/pdf/renderer:unit_tests" ]
+ }
+
# No components should depend on Chrome.
assert_no_deps = [ "//chrome/*" ]
@@ -552,7 +560,7 @@ if (!is_ios) {
if (is_android) {
sources += [
- "autofill_assistant/browser/web_controller_browsertest.cc",
+ "autofill_assistant/browser/web/web_controller_browsertest.cc",
"test/android/browsertests_apk/components_browser_tests_jni_onload.cc",
]
sources -= [ "autofill/content/browser/risk/fingerprint_browsertest.cc" ]
@@ -579,7 +587,6 @@ if (!is_ios) {
sources += [ "dom_distiller/standalone/content_extractor_browsertest.cc" ]
deps += [
"//components/leveldb_proto",
- "//components/leveldb_proto/content:factory",
"//components/prefs:test_support",
"//components/sync_preferences:test_support",
]
diff --git a/chromium/components/OWNERS b/chromium/components/OWNERS
index c4c3e8dce54..753dbd57499 100644
--- a/chromium/components/OWNERS
+++ b/chromium/components/OWNERS
@@ -30,7 +30,6 @@ per-file reset_password_strings.grdp=file://components/safe_browsing/OWNERS
per-file security_interstitials_strings.grdp=file://components/security_interstitials/OWNERS
per-file security_state_strings.grdp=file://components/security_state/OWNERS
per-file ssl_errors_strings.grdp=file://components/ssl_errors/OWNERS
-per-file supervised_user_error_page_strings.grdp=file://components/supervised_user_error_page/OWNERS
per-file sync_ui_strings.grdp=file://components/sync/OWNERS
per-file translate_strings.grdp=file://components/translate/OWNERS
per-file undo_strings.grdp=file://components/undo/OWNERS
diff --git a/chromium/components/account_id/OWNERS b/chromium/components/account_id/OWNERS
index e2162608009..fddf52bf762 100644
--- a/chromium/components/account_id/OWNERS
+++ b/chromium/components/account_id/OWNERS
@@ -1,4 +1,3 @@
alemate@chromium.org
-rogerta@chromium.org
xiyuan@chromium.org
# COMPONENT: Services>SignIn
diff --git a/chromium/components/account_id/mojom/account_id.typemap b/chromium/components/account_id/mojom/account_id.typemap
index 55884c28f81..da3ae8f92f9 100644
--- a/chromium/components/account_id/mojom/account_id.typemap
+++ b/chromium/components/account_id/mojom/account_id.typemap
@@ -9,6 +9,6 @@ public_deps = [
"//components/account_id",
]
type_mappings = [
- "signin.mojom.AccountType=AccountType",
- "signin.mojom.AccountId=AccountId",
+ "signin.mojom.AccountType=::AccountType",
+ "signin.mojom.AccountId=::AccountId",
]
diff --git a/chromium/components/app_modal/OWNERS b/chromium/components/app_modal/OWNERS
index 704db9fc248..9c92ae3e5c3 100644
--- a/chromium/components/app_modal/OWNERS
+++ b/chromium/components/app_modal/OWNERS
@@ -1 +1,2 @@
avi@chromium.org
+# COMPONENT: Blink>WindowDialog
diff --git a/chromium/components/app_modal/views/OWNERS b/chromium/components/app_modal/views/OWNERS
new file mode 100644
index 00000000000..82163ec7ad4
--- /dev/null
+++ b/chromium/components/app_modal/views/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Internals>Views>Desktop
diff --git a/chromium/components/app_modal_strings_grdp/OWNERS b/chromium/components/app_modal_strings_grdp/OWNERS
index d092bde2ed3..5d0f3d9ea79 100644
--- a/chromium/components/app_modal_strings_grdp/OWNERS
+++ b/chromium/components/app_modal_strings_grdp/OWNERS
@@ -1 +1,2 @@
file://components/app_modal/OWNERS
+# COMPONENT: Blink>WindowDialog
diff --git a/chromium/components/arc/BUILD.gn b/chromium/components/arc/BUILD.gn
index b8b2b203908..63568d5672b 100644
--- a/chromium/components/arc/BUILD.gn
+++ b/chromium/components/arc/BUILD.gn
@@ -102,7 +102,8 @@ static_library("arc") {
"//chromeos/network",
"//components/account_id",
"//components/exo",
- "//components/google/core/browser",
+ "//components/google/core/common",
+ "//components/guest_os",
"//components/onc",
"//components/prefs",
"//components/session_manager/core",
@@ -143,6 +144,7 @@ static_library("prefs") {
deps = [
":arc_base_enums",
+ "//components/guest_os:prefs",
"//components/prefs",
]
}
@@ -174,6 +176,7 @@ static_library("arc_base_utils") {
"//ash/public/cpp",
"//base",
"//chromeos/constants",
+ "//chromeos/dbus:dbus",
"//chromeos/dbus/session_manager",
"//components/exo",
"//ui/aura",
@@ -237,7 +240,7 @@ static_library("arc_base") {
":arc_base_utils",
":connection_holder",
":prefs",
- "//components/arc/common",
+ "//components/arc/mojom",
"//dbus",
]
}
@@ -267,7 +270,7 @@ static_library("notification_test_support") {
public_deps = [
":connection_holder",
- "//components/arc/common:notifications",
+ "//components/arc/mojom:notifications",
]
}
@@ -335,7 +338,7 @@ source_set("unit_tests") {
sources = [
"arc_features_parser_unittest.cc",
"arc_util_unittest.cc",
- "bluetooth/bluetooth_struct_traits_unittest.cc",
+ "bluetooth/bluetooth_mojom_traits_unittest.cc",
"bluetooth/bluetooth_type_converters_unittest.cc",
"clipboard/arc_clipboard_bridge_unittest.cc",
"ime/arc_ime_service_unittest.cc",
@@ -352,7 +355,6 @@ source_set("unit_tests") {
"session/arc_data_remover_unittest.cc",
"session/arc_session_impl_unittest.cc",
"session/arc_session_runner_unittest.cc",
- "session/arc_vm_client_adapter_unittest.cc",
"timer/arc_timer_bridge_unittest.cc",
"wake_lock/arc_wake_lock_bridge_unittest.cc",
]
diff --git a/chromium/components/arc/DEPS b/chromium/components/arc/DEPS
index 2f1503f0451..955ca638cc5 100644
--- a/chromium/components/arc/DEPS
+++ b/chromium/components/arc/DEPS
@@ -3,6 +3,7 @@ include_rules = [
"+chromeos/constants",
"+chromeos/cryptohome",
"+chromeos/dbus",
+ "+components/guest_os",
"+components/account_id",
"+components/exo",
"+components/keyed_service",
@@ -38,6 +39,6 @@ specific_include_rules = {
"+ui/aura",
],
".*_unittest.cc": [
- "+content/public/test/test_browser_thread_bundle.h"
+ "+content/public/test/browser_task_environment.h"
],
}
diff --git a/chromium/components/arc/OWNERS b/chromium/components/arc/OWNERS
index ab4ebe9c76a..d2b9a649ec6 100644
--- a/chromium/components/arc/OWNERS
+++ b/chromium/components/arc/OWNERS
@@ -2,3 +2,5 @@ hidehiko@chromium.org
yusukes@chromium.org
# backup reviewer
elijahtaylor@chromium.org
+
+# COMPONENT: Platform>Apps>ARC
diff --git a/chromium/components/arc/app_permissions/arc_app_permissions_bridge.h b/chromium/components/arc/app_permissions/arc_app_permissions_bridge.h
index c83e4b90051..7c3ba6fc33c 100644
--- a/chromium/components/arc/app_permissions/arc_app_permissions_bridge.h
+++ b/chromium/components/arc/app_permissions/arc_app_permissions_bridge.h
@@ -6,7 +6,7 @@
#define COMPONENTS_ARC_APP_PERMISSIONS_ARC_APP_PERMISSIONS_BRIDGE_H_
#include "base/macros.h"
-#include "components/arc/common/app_permissions.mojom.h"
+#include "components/arc/mojom/app_permissions.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/appfuse/arc_appfuse_bridge.h b/chromium/components/arc/appfuse/arc_appfuse_bridge.h
index 615f01b2ceb..963f38e18a1 100644
--- a/chromium/components/arc/appfuse/arc_appfuse_bridge.h
+++ b/chromium/components/arc/appfuse/arc_appfuse_bridge.h
@@ -8,7 +8,7 @@
#include <stdint.h>
#include "base/macros.h"
-#include "components/arc/common/appfuse.mojom.h"
+#include "components/arc/mojom/appfuse.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/arc_features.cc b/chromium/components/arc/arc_features.cc
index e3293d027f6..e5502898ddc 100644
--- a/chromium/components/arc/arc_features.cc
+++ b/chromium/components/arc/arc_features.cc
@@ -6,10 +6,6 @@
namespace arc {
-// Controls whether ARC is available for CHILD accounts.
-const base::Feature kAvailableForChildAccountFeature{
- "ArcAvailableForChildAccount", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Controls whether ARC++ app runtime performance statistics collection is
// enabled.
const base::Feature kAppRuntimePerormanceStatistics{
@@ -52,14 +48,17 @@ const base::Feature kEnableUnifiedAudioFocusFeature{
const base::Feature kFilePickerExperimentFeature{
"ArcFilePickerExperiment", base::FEATURE_ENABLED_BY_DEFAULT};
-// Controls experimental ARC graphic buffers visualization tools.
-const base::Feature kGraphicBuffersVisualizationTool{
- "ArcGraphicBuffersVisualizationTool", base::FEATURE_DISABLED_BY_DEFAULT};
+// Toggles between native bridge implementations for ARC.
+// Note, that we keep the original feature name to preserve
+// corresponding metrics.
+const base::Feature kNativeBridgeToggleFeature{
+ "ArcNativeBridgeExperiment", base::FEATURE_ENABLED_BY_DEFAULT};
-// Controls experimental native bridge feature for ARC.
-const base::Feature kNativeBridgeExperimentFeature {
- "ArcNativeBridgeExperiment", base::FEATURE_ENABLED_BY_DEFAULT
-};
+// Controls ARC picture-in-picture feature. If this is enabled, then Android
+// will control which apps can enter PIP. If this is disabled, then ARC PIP
+// will be disabled.
+const base::Feature kPictureInPictureFeature{"ArcPictureInPicture",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Controls experimental print spooler feature for ARC.
const base::Feature kPrintSpoolerExperimentFeature{
@@ -80,7 +79,7 @@ const base::Feature kUsbHostFeature{"ArcUsbHost",
// When enabled, chrome://settings and Files.app will ask if the user wants
// to expose USB storage devices to ARC.
const base::Feature kUsbStorageUIFeature{"ArcUsbStorageUI",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Controls ARC VPN integration.
// When enabled, Chrome traffic will be routed through VPNs connected in
diff --git a/chromium/components/arc/arc_features.h b/chromium/components/arc/arc_features.h
index ea3a79876a4..6cbf9eb7d49 100644
--- a/chromium/components/arc/arc_features.h
+++ b/chromium/components/arc/arc_features.h
@@ -12,7 +12,6 @@
namespace arc {
// Please keep alphabetized.
-extern const base::Feature kAvailableForChildAccountFeature;
extern const base::Feature kAppRuntimePerormanceStatistics;
extern const base::Feature kBootCompletedBroadcastFeature;
extern const base::Feature kCleanArcDataOnRegularToChildTransitionFeature;
@@ -22,8 +21,8 @@ extern const base::Feature kEnableDocumentsProviderInFilesAppFeature;
extern const base::Feature kEnableRegularToChildTransitionFeature;
extern const base::Feature kEnableUnifiedAudioFocusFeature;
extern const base::Feature kFilePickerExperimentFeature;
-extern const base::Feature kGraphicBuffersVisualizationTool;
-extern const base::Feature kNativeBridgeExperimentFeature;
+extern const base::Feature kNativeBridgeToggleFeature;
+extern const base::Feature kPictureInPictureFeature;
extern const base::Feature kPrintSpoolerExperimentFeature;
extern const base::Feature kSmartTextSelectionFeature;
extern const base::Feature kUsbHostFeature;
diff --git a/chromium/components/arc/arc_features_parser.cc b/chromium/components/arc/arc_features_parser.cc
index 8c031c1f3d6..1235e2d3ae3 100644
--- a/chromium/components/arc/arc_features_parser.cc
+++ b/chromium/components/arc/arc_features_parser.cc
@@ -141,8 +141,9 @@ ArcFeatures& ArcFeatures::operator=(ArcFeatures&& other) = default;
void ArcFeaturesParser::GetArcFeatures(
base::OnceCallback<void(base::Optional<ArcFeatures>)> callback) {
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&ReadOnFileThread, base::FilePath(kArcFeaturesJsonFile)),
std::move(callback));
}
diff --git a/chromium/components/arc/arc_prefs.cc b/chromium/components/arc/arc_prefs.cc
index 9b2b91b93f2..8065710be4c 100644
--- a/chromium/components/arc/arc_prefs.cc
+++ b/chromium/components/arc/arc_prefs.cc
@@ -7,6 +7,7 @@
#include <string>
+#include "components/guest_os/guest_os_prefs.h"
#include "components/prefs/pref_registry_simple.h"
namespace arc {
@@ -40,8 +41,14 @@ const char kArcDataRemoveRequested[] = "arc.data.remove_requested";
// SetArcPlayStoreEnabledForProfile()) in chrome/browser/chromeos/arc/arc_util.
const char kArcEnabled[] = "arc.enabled";
// A preference to control if ARC can access removable media on the host side.
+// TODO(fukino): Remove this pref once "Play Store applications can't access
+// this device" toast in Files app becomes aware of kArcVisibleExternalStorages.
+// crbug.com/998512.
const char kArcHasAccessToRemovableMedia[] =
"arc.has_access_to_removable_media";
+// A preference to keep list of external storages which are visible to Android
+// apps. (i.e. can be read/written by Android apps.)
+const char kArcVisibleExternalStorages[] = "arc.visible_external_storages";
// A preference that indicates that initial settings need to be applied. Initial
// settings are applied only once per new OptIn once mojo settings instance is
// ready. Each OptOut resets this preference. Note, its sense is close to
@@ -99,38 +106,9 @@ const char kArcCompatibleFilesystemChosen[] =
// Integer pref indicating the ecryptfs to ext4 migration strategy. One of
// options: forbidden = 0, migrate = 1, wipe = 2 or minimal migrate = 4.
const char kEcryptfsMigrationStrategy[] = "ecryptfs_migration_strategy";
-// A preference that persists total engagement time across sessions, which is
-// accumulated and sent to UMA once a day.
-const char kEngagementTimeTotal[] = "arc.metrics.engagement_time.total";
-// A preference that persists foreground engagement time across sessions, which
-// is accumulated and sent to UMA once a day.
-const char kEngagementTimeForeground[] =
- "arc.metrics.engagement_time.foreground";
-// A preference that persists background engagement time across sessions, which
-// is accumulated and sent to UMA once a day.
-const char kEngagementTimeBackground[] =
- "arc.metrics.engagement_time.background";
-// A preference that saves the OS version when engagement time was last
-// recorded. Old results will be discarded if a version change is detected.
-const char kEngagementTimeOsVersion[] =
- "arc.metrics.engagement_time.os_version";
-// A preference that saves the day ID (number of days since origin of Time) when
-// engagement time was last recorded. Accumulated results are sent to UMA if day
-// ID has changed.
-const char kEngagementTimeDayId[] = "arc.metrics.engagement_time.day_id";
-// A preference that indicates the user has allowed voice interaction services
-// to access the "context" (text and graphic content that is currently on
-// screen). This preference can be overridden by the
-// VoiceInteractionContextEnabled administrator policy.
-const char kVoiceInteractionContextEnabled[] =
- "settings.voice_interaction.context.enabled";
-// A preference that indicates the user has enabled voice interaction services.
-const char kVoiceInteractionEnabled[] = "settings.voice_interaction.enabled";
-// A preference that indicates the user has allowed voice interaction services
-// to use hotword listening. This preference can be overridden by the
-// VoiceInteractionHotwordEnabled administrator policy.
-const char kVoiceInteractionHotwordEnabled[] =
- "settings.voice_interaction.hotword.enabled";
+// Preferences for storing engagement time data, as per
+// GuestOsEngagementMetrics.
+const char kEngagementPrefsPrefix[] = "arc.metrics";
// ======== LOCAL STATE PREFS ========
@@ -166,6 +144,9 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
kArcSupervisionTransition,
static_cast<int>(ArcSupervisionTransition::NO_TRANSITION));
+ guest_os::prefs::RegisterEngagementProfilePrefs(registry,
+ kEngagementPrefsPrefix);
+
// Sorted in lexicographical order.
registry->RegisterBooleanPref(kAlwaysOnVpnLockdown, false);
registry->RegisterStringPref(kAlwaysOnVpnPackage, std::string());
@@ -182,14 +163,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(kArcSkippedReportingNotice, false);
registry->RegisterBooleanPref(kArcTermsAccepted, false);
registry->RegisterBooleanPref(kArcTermsShownInOobe, false);
- registry->RegisterTimeDeltaPref(kEngagementTimeBackground, base::TimeDelta());
- registry->RegisterIntegerPref(kEngagementTimeDayId, 0);
- registry->RegisterTimeDeltaPref(kEngagementTimeForeground, base::TimeDelta());
- registry->RegisterStringPref(kEngagementTimeOsVersion, "");
- registry->RegisterTimeDeltaPref(kEngagementTimeTotal, base::TimeDelta());
- registry->RegisterBooleanPref(kVoiceInteractionContextEnabled, false);
- registry->RegisterBooleanPref(kVoiceInteractionEnabled, false);
- registry->RegisterBooleanPref(kVoiceInteractionHotwordEnabled, false);
+ registry->RegisterListPref(kArcVisibleExternalStorages);
}
} // namespace prefs
diff --git a/chromium/components/arc/arc_prefs.h b/chromium/components/arc/arc_prefs.h
index 671128c6bba..d4d00f56366 100644
--- a/chromium/components/arc/arc_prefs.h
+++ b/chromium/components/arc/arc_prefs.h
@@ -39,16 +39,9 @@ ARC_EXPORT extern const char kArcSkippedReportingNotice[];
ARC_EXPORT extern const char kArcSupervisionTransition[];
ARC_EXPORT extern const char kArcTermsAccepted[];
ARC_EXPORT extern const char kArcTermsShownInOobe[];
+ARC_EXPORT extern const char kArcVisibleExternalStorages[];
ARC_EXPORT extern const char kEcryptfsMigrationStrategy[];
-ARC_EXPORT extern const char kEngagementTimeBackground[];
-ARC_EXPORT extern const char kEngagementTimeDayId[];
-ARC_EXPORT extern const char kEngagementTimeForeground[];
-ARC_EXPORT extern const char kEngagementTimeOsVersion[];
-ARC_EXPORT extern const char kEngagementTimeTotal[];
-// TODO(b/110211045): Move Assistant related prefs to ash.
-ARC_EXPORT extern const char kVoiceInteractionContextEnabled[];
-ARC_EXPORT extern const char kVoiceInteractionEnabled[];
-ARC_EXPORT extern const char kVoiceInteractionHotwordEnabled[];
+ARC_EXPORT extern const char kEngagementPrefsPrefix[];
// Local state prefs in lexicographical order.
ARC_EXPORT extern const char kStabilityMetrics[];
diff --git a/chromium/components/arc/arc_util.cc b/chromium/components/arc/arc_util.cc
index d5084ad4a0e..245e442e6cc 100644
--- a/chromium/components/arc/arc_util.cc
+++ b/chromium/components/arc/arc_util.cc
@@ -11,7 +11,10 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
+#include "base/optional.h"
#include "chromeos/constants/chromeos_switches.h"
+#include "chromeos/dbus/concierge_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "components/arc/arc_features.h"
#include "components/exo/shell_surface_util.h"
@@ -48,6 +51,46 @@ void SetArcCpuRestrictionCallback(
LOG(ERROR) << "Failed to " << message << " ARC";
}
+void OnSetArcVmCpuRestriction(
+ base::Optional<vm_tools::concierge::SetVmCpuRestrictionResponse> response) {
+ if (!response) {
+ LOG(ERROR) << "Failed to call SetVmCpuRestriction";
+ return;
+ }
+ if (!response->success())
+ LOG(ERROR) << "SetVmCpuRestriction for ARCVM failed";
+}
+
+void SetArcVmCpuRestriction(bool do_restrict) {
+ auto* client = chromeos::DBusThreadManager::Get()->GetConciergeClient();
+ if (!client) {
+ LOG(WARNING) << "ConciergeClient is not available";
+ return;
+ }
+
+ vm_tools::concierge::SetVmCpuRestrictionRequest request;
+ request.set_cpu_cgroup(vm_tools::concierge::CPU_CGROUP_ARCVM);
+ request.set_cpu_restriction_state(
+ do_restrict ? vm_tools::concierge::CPU_RESTRICTION_BACKGROUND
+ : vm_tools::concierge::CPU_RESTRICTION_FOREGROUND);
+
+ client->SetVmCpuRestriction(request,
+ base::BindOnce(&OnSetArcVmCpuRestriction));
+}
+
+void SetArcContainerCpuRestriction(bool do_restrict) {
+ if (!chromeos::SessionManagerClient::Get()) {
+ LOG(WARNING) << "SessionManagerClient is not available";
+ return;
+ }
+
+ const login_manager::ContainerCpuRestrictionState state =
+ do_restrict ? login_manager::CONTAINER_CPU_RESTRICTION_BACKGROUND
+ : login_manager::CONTAINER_CPU_RESTRICTION_FOREGROUND;
+ chromeos::SessionManagerClient::Get()->SetArcCpuRestriction(
+ state, base::BindOnce(SetArcCpuRestrictionCallback, state));
+}
+
} // namespace
bool IsArcAvailable() {
@@ -77,16 +120,6 @@ bool IsArcVmEnabled() {
chromeos::switches::kEnableArcVm);
}
-void EnableArcVmForTesting() {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- chromeos::switches::kEnableArcVm);
-}
-
-void DisableArcVmForTesting() {
- base::CommandLine::ForCurrentProcess()->RemoveSwitch(
- chromeos::switches::kEnableArcVm);
-}
-
bool ShouldArcAlwaysStart() {
const auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(chromeos::switches::kArcStartMode))
@@ -167,12 +200,6 @@ bool IsArcAllowedForUser(const user_manager::User* user) {
return false;
}
- if (user->GetType() == user_manager::USER_TYPE_CHILD &&
- !base::FeatureList::IsEnabled(arc::kAvailableForChildAccountFeature)) {
- VLOG(1) << "ARC usage by Child users is prohibited";
- return false;
- }
-
return true;
}
@@ -205,21 +232,16 @@ int GetTaskIdFromWindowAppId(const std::string& app_id) {
}
void SetArcCpuRestriction(bool do_restrict) {
- if (!chromeos::SessionManagerClient::Get()) {
- LOG(WARNING) << "SessionManagerClient is not available";
- return;
- }
-
// Ignore any calls to restrict the ARC container if the specified command
// line flag is set.
if (chromeos::switches::IsArcCpuRestrictionDisabled() && do_restrict)
return;
- const login_manager::ContainerCpuRestrictionState state =
- do_restrict ? login_manager::CONTAINER_CPU_RESTRICTION_BACKGROUND
- : login_manager::CONTAINER_CPU_RESTRICTION_FOREGROUND;
- chromeos::SessionManagerClient::Get()->SetArcCpuRestriction(
- state, base::BindOnce(SetArcCpuRestrictionCallback, state));
+ if (IsArcVmEnabled()) {
+ SetArcVmCpuRestriction(do_restrict);
+ } else {
+ SetArcContainerCpuRestriction(do_restrict);
+ }
}
bool IsArcForceCacheAppIcon() {
@@ -249,13 +271,15 @@ bool IsArcPlayAutoInstallDisabled() {
// static
int32_t GetLcdDensityForDeviceScaleFactor(float device_scale_factor) {
- // Keep this consistent with wayland_client.cpp on Android side.
- // TODO(oshima): Consider sending this through wayland.
+ // TODO(b/131884992): Remove the logic to update default lcd density once
+ // per-display-density is supported.
constexpr float kEpsilon = 0.001;
if (std::abs(device_scale_factor - 2.25f) < kEpsilon)
return 280;
if (std::abs(device_scale_factor - 1.6f) < kEpsilon)
return 213; // TVDPI
+ if (std::abs(device_scale_factor - 2.5f) < kEpsilon)
+ return 320; // XHDPI
constexpr float kChromeScaleToAndroidScaleRatio = 0.75f;
constexpr int32_t kDefaultDensityDpi = 160;
diff --git a/chromium/components/arc/arc_util.h b/chromium/components/arc/arc_util.h
index f6b7b929cf1..7660757d220 100644
--- a/chromium/components/arc/arc_util.h
+++ b/chromium/components/arc/arc_util.h
@@ -43,11 +43,6 @@ bool IsArcAvailable();
// Returns true if ARC VM is enabled.
bool IsArcVmEnabled();
-// These two methods used for testing only add and remove the arcvm flag so that
-// IsArcVmEnabled() returns the corresponding result.
-void EnableArcVmForTesting();
-void DisableArcVmForTesting();
-
// Returns true if ARC should always start within the primary user session
// (opted in user or not), and other supported mode such as guest and Kiosk
// mode.
diff --git a/chromium/components/arc/arc_util_unittest.cc b/chromium/components/arc/arc_util_unittest.cc
index fd75726b1ac..db092c67fd4 100644
--- a/chromium/components/arc/arc_util_unittest.cc
+++ b/chromium/components/arc/arc_util_unittest.cc
@@ -231,18 +231,6 @@ TEST_F(ArcUtilTest, IsArcAllowedForUser) {
EXPECT_TRUE(IsArcAllowedForUser(ephemeral_user));
}
-TEST_F(ArcUtilTest, IsArcAllowedForChildUserWithExperiment) {
- auto* command_line = base::CommandLine::ForCurrentProcess();
- command_line->InitFromArgv(
- {"", "--enable-features=ArcAvailableForChildAccount"});
- base::test::ScopedFeatureList feature_list;
- feature_list.InitFromCommandLine(
- command_line->GetSwitchValueASCII(switches::kEnableFeatures),
- command_line->GetSwitchValueASCII(switches::kDisableFeatures));
- const FakeUser user(user_manager::USER_TYPE_CHILD);
- EXPECT_TRUE(IsArcAllowedForUser(&user));
-}
-
TEST_F(ArcUtilTest, ArcStartModeDefault) {
auto* command_line = base::CommandLine::ForCurrentProcess();
command_line->InitFromArgv({"", "--arc-availability=installed"});
@@ -266,6 +254,7 @@ TEST_F(ArcUtilTest, ScaleFactorToDensity) {
EXPECT_EQ(213, GetLcdDensityForDeviceScaleFactor(1.6f));
EXPECT_EQ(240, GetLcdDensityForDeviceScaleFactor(2.0f));
EXPECT_EQ(280, GetLcdDensityForDeviceScaleFactor(2.25f));
+ EXPECT_EQ(320, GetLcdDensityForDeviceScaleFactor(2.5f));
// Bad scale factors shouldn't blow up.
EXPECT_EQ(160, GetLcdDensityForDeviceScaleFactor(0.5f));
diff --git a/chromium/components/arc/audio/arc_audio_bridge.h b/chromium/components/arc/audio/arc_audio_bridge.h
index 347b91cf023..7ef4c147b42 100644
--- a/chromium/components/arc/audio/arc_audio_bridge.h
+++ b/chromium/components/arc/audio/arc_audio_bridge.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "chromeos/audio/cras_audio_handler.h"
-#include "components/arc/common/audio.mojom.h"
+#include "components/arc/mojom/audio.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/arc/bitmap/OWNERS b/chromium/components/arc/bitmap/OWNERS
index ef5cf841917..012a33c0b1c 100644
--- a/chromium/components/arc/bitmap/OWNERS
+++ b/chromium/components/arc/bitmap/OWNERS
@@ -1,3 +1,3 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/bitmap/bitmap_struct_traits.cc b/chromium/components/arc/bitmap/bitmap_mojom_traits.cc
index 868734b4c27..9abd471de49 100644
--- a/chromium/components/arc/bitmap/bitmap_struct_traits.cc
+++ b/chromium/components/arc/bitmap/bitmap_mojom_traits.cc
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/arc/bitmap/bitmap_struct_traits.h"
+#include "components/arc/bitmap/bitmap_mojom_traits.h"
namespace mojo {
-bool StructTraits<arc::mojom::ArcBitmapDataView, SkBitmap>::
- Read(arc::mojom::ArcBitmapDataView data, SkBitmap* out) {
+bool StructTraits<arc::mojom::ArcBitmapDataView, SkBitmap>::Read(
+ arc::mojom::ArcBitmapDataView data,
+ SkBitmap* out) {
mojo::ArrayDataView<uint8_t> pixel_data;
data.GetPixelDataDataView(&pixel_data);
SkImageInfo info = SkImageInfo::Make(
- data.width(), data.height(),
- kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ data.width(), data.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType);
if (info.computeByteSize(info.minRowBytes()) > pixel_data.size()) {
// Insufficient buffer size.
return false;
@@ -22,9 +22,8 @@ bool StructTraits<arc::mojom::ArcBitmapDataView, SkBitmap>::
// Create the SkBitmap object which wraps the arc bitmap pixels. This
// doesn't copy and |data| and |bitmap| share the buffer.
SkBitmap bitmap;
- if (!bitmap.installPixels(info,
- const_cast<uint8_t*>(pixel_data.data()),
- info.minRowBytes())) {
+ if (!bitmap.installPixels(info, const_cast<uint8_t*>(pixel_data.data()),
+ info.minRowBytes())) {
// Error in installing pixels.
return false;
}
diff --git a/chromium/components/arc/bitmap/bitmap_struct_traits.h b/chromium/components/arc/bitmap/bitmap_mojom_traits.h
index d750ce813b6..a39b987785f 100644
--- a/chromium/components/arc/bitmap/bitmap_struct_traits.h
+++ b/chromium/components/arc/bitmap/bitmap_mojom_traits.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_BITMAP_BITMAP_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_BITMAP_BITMAP_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_BITMAP_BITMAP_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_BITMAP_BITMAP_MOJOM_TRAITS_H_
#include "base/containers/span.h"
-#include "components/arc/common/bitmap.mojom.h"
+#include "components/arc/mojom/bitmap.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace mojo {
@@ -28,4 +28,4 @@ struct StructTraits<arc::mojom::ArcBitmapDataView, SkBitmap> {
} // namespace mojo
-#endif // COMPONENTS_ARC_BITMAP_BITMAP_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_BITMAP_BITMAP_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/bluetooth/OWNERS b/chromium/components/arc/bluetooth/OWNERS
index 40f6a3e842b..28b1b58bb21 100644
--- a/chromium/components/arc/bluetooth/OWNERS
+++ b/chromium/components/arc/bluetooth/OWNERS
@@ -1,7 +1,7 @@
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
-per-file *_type_converter*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_type_converter*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/bluetooth/bluetooth_struct_traits.cc b/chromium/components/arc/bluetooth/bluetooth_mojom_traits.cc
index e10d42f9fb3..9272ce6b909 100644
--- a/chromium/components/arc/bluetooth/bluetooth_struct_traits.cc
+++ b/chromium/components/arc/bluetooth/bluetooth_mojom_traits.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 "components/arc/bluetooth/bluetooth_struct_traits.h"
+#include "components/arc/bluetooth/bluetooth_mojom_traits.h"
#include <initializer_list>
#include <map>
@@ -124,9 +124,9 @@ StructTraits<arc::mojom::BluetoothUUIDDataView, device::BluetoothUUID>::uuid(
// static
bool StructTraits<arc::mojom::BluetoothUUIDDataView,
- device::BluetoothUUID>::Read(
- arc::mojom::BluetoothUUIDDataView data,
- device::BluetoothUUID* output) {
+ device::BluetoothUUID>::Read(arc::mojom::BluetoothUUIDDataView
+ data,
+ device::BluetoothUUID* output) {
std::vector<uint8_t> address_bytes;
if (!data.ReadUuid(&address_bytes))
return false;
diff --git a/chromium/components/arc/bluetooth/bluetooth_struct_traits.h b/chromium/components/arc/bluetooth/bluetooth_mojom_traits.h
index 5ae85d1cfc6..c696fc8a632 100644
--- a/chromium/components/arc/bluetooth/bluetooth_struct_traits.h
+++ b/chromium/components/arc/bluetooth/bluetooth_mojom_traits.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_BLUETOOTH_BLUETOOTH_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_BLUETOOTH_BLUETOOTH_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_BLUETOOTH_BLUETOOTH_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_BLUETOOTH_BLUETOOTH_MOJOM_TRAITS_H_
#include <memory>
#include <vector>
-#include "components/arc/common/bluetooth.mojom.h"
+#include "components/arc/mojom/bluetooth.mojom.h"
#include "device/bluetooth/bluetooth_advertisement.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
@@ -17,8 +17,7 @@
namespace mojo {
template <>
-struct EnumTraits<arc::mojom::BluetoothDeviceType,
- device::BluetoothTransport> {
+struct EnumTraits<arc::mojom::BluetoothDeviceType, device::BluetoothTransport> {
static arc::mojom::BluetoothDeviceType ToMojom(
device::BluetoothTransport type) {
switch (type) {
@@ -134,4 +133,4 @@ struct StructTraits<arc::mojom::BluetoothAdvertisementDataView,
} // namespace mojo
-#endif // COMPONENTS_ARC_BLUETOOTH_BLUETOOTH_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_BLUETOOTH_BLUETOOTH_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/bluetooth/bluetooth_struct_traits_unittest.cc b/chromium/components/arc/bluetooth/bluetooth_mojom_traits_unittest.cc
index b6ddaae7125..fa371a2c8d6 100644
--- a/chromium/components/arc/bluetooth/bluetooth_struct_traits_unittest.cc
+++ b/chromium/components/arc/bluetooth/bluetooth_mojom_traits_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 "components/arc/bluetooth/bluetooth_struct_traits.h"
+#include "components/arc/bluetooth/bluetooth_mojom_traits.h"
#include <string>
#include <utility>
diff --git a/chromium/components/arc/bluetooth/bluetooth_type_converters.h b/chromium/components/arc/bluetooth/bluetooth_type_converters.h
index 67a43e7436e..c410f2d7b5d 100644
--- a/chromium/components/arc/bluetooth/bluetooth_type_converters.h
+++ b/chromium/components/arc/bluetooth/bluetooth_type_converters.h
@@ -10,7 +10,7 @@
#include <string>
#include <utility>
-#include "components/arc/common/bluetooth.mojom.h"
+#include "components/arc/mojom/bluetooth.mojom.h"
#include "device/bluetooth/bluetooth_gatt_service.h"
#include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
#include "device/bluetooth/bluez/bluetooth_service_record_bluez.h"
diff --git a/chromium/components/arc/camera/arc_camera_bridge.h b/chromium/components/arc/camera/arc_camera_bridge.h
index 43ab1c311fd..e327a711e32 100644
--- a/chromium/components/arc/camera/arc_camera_bridge.h
+++ b/chromium/components/arc/camera/arc_camera_bridge.h
@@ -9,7 +9,7 @@
#include <memory>
#include "base/macros.h"
-#include "components/arc/common/camera.mojom.h"
+#include "components/arc/mojom/camera.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge.cc b/chromium/components/arc/clipboard/arc_clipboard_bridge.cc
index fa49041af96..c4c677f46a9 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge.cc
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -48,7 +48,7 @@ mojom::ClipRepresentationPtr CreateHTML(const ui::Clipboard* clipboard) {
std::string url;
uint32_t fragment_start, fragment_end;
- clipboard->ReadHTML(ui::ClipboardType::kCopyPaste, &markup16, &url,
+ clipboard->ReadHTML(ui::ClipboardBuffer::kCopyPaste, &markup16, &url,
&fragment_start, &fragment_end);
std::string text(base::UTF16ToUTF8(
@@ -73,7 +73,7 @@ mojom::ClipRepresentationPtr CreatePlainText(const ui::Clipboard* clipboard) {
// present, only use Bookmark.
clipboard->ReadBookmark(&title, &text);
if (text.size() == 0)
- clipboard->ReadAsciiText(ui::ClipboardType::kCopyPaste, &text);
+ clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, &text);
return mojom::ClipRepresentation::New(mime_type,
mojom::ClipValue::NewText(text));
@@ -84,7 +84,7 @@ mojom::ClipDataPtr GetClipData(const ui::Clipboard* clipboard) {
std::vector<base::string16> mime_types;
bool contains_files;
- clipboard->ReadAvailableTypes(ui::ClipboardType::kCopyPaste, &mime_types,
+ clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste, &mime_types,
&contains_files);
mojom::ClipDataPtr clip_data(mojom::ClipData::New());
@@ -172,7 +172,7 @@ void ArcClipboardBridge::SetClipContent(mojom::ClipDataPtr clip_data) {
// Order is important. AutoReset should outlive ScopedClipboardWriter.
base::AutoReset<bool> auto_reset(&event_originated_at_instance_, true);
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
for (const auto& repr : clip_data->representations) {
const std::string& mime_type(repr->mime_type);
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge.h b/chromium/components/arc/clipboard/arc_clipboard_bridge.h
index 0e26b276c40..1056ad5a080 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge.h
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/clipboard.mojom.h"
+#include "components/arc/mojom/clipboard.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
#include "ui/base/clipboard/clipboard_observer.h"
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc b/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
index 838de85ee7b..b2e541ea8d4 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
@@ -10,11 +10,11 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h"
-#include "components/arc/common/clipboard.mojom.h"
+#include "components/arc/mojom/clipboard.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/test/connection_holder_util.h"
#include "components/arc/test/fake_clipboard_instance.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
@@ -74,7 +74,7 @@ class ArcClipboardBridgeTest : public testing::Test {
}
protected:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<ArcBridgeService> arc_bridge_service_;
std::unique_ptr<ArcClipboardBridge> clipboard_bridge_;
std::unique_ptr<FakeClipboardInstance> clipboard_instance_;
@@ -84,7 +84,7 @@ class ArcClipboardBridgeTest : public testing::Test {
TEST_F(ArcClipboardBridgeTest, GetClipContent_PlainText) {
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteText(base::UTF8ToUTF16(kSampleText));
}
@@ -100,7 +100,7 @@ TEST_F(ArcClipboardBridgeTest, GetClipContent_PlainText) {
TEST_F(ArcClipboardBridgeTest, GetClipContent_Html) {
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteHTML(base::UTF8ToUTF16(kSampleHtml), std::string());
}
@@ -121,13 +121,13 @@ TEST_F(ArcClipboardBridgeTest, SetClipContent_PlainText) {
std::vector<base::string16> mime_types;
bool contains_files;
- GetClipboard()->ReadAvailableTypes(ui::ClipboardType::kCopyPaste, &mime_types,
- &contains_files);
+ GetClipboard()->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste,
+ &mime_types, &contains_files);
ASSERT_EQ(1u, mime_types.size());
EXPECT_EQ(ui::kMimeTypeText, base::UTF16ToUTF8(mime_types[0]));
base::string16 result;
- GetClipboard()->ReadText(ui::ClipboardType::kCopyPaste, &result);
+ GetClipboard()->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
EXPECT_EQ(kSampleText, base::UTF16ToUTF8(result));
}
@@ -138,15 +138,15 @@ TEST_F(ArcClipboardBridgeTest, SetClipContent_Html) {
std::vector<base::string16> mime_types;
bool contains_files;
- GetClipboard()->ReadAvailableTypes(ui::ClipboardType::kCopyPaste, &mime_types,
- &contains_files);
+ GetClipboard()->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste,
+ &mime_types, &contains_files);
ASSERT_EQ(1u, mime_types.size());
EXPECT_EQ(ui::kMimeTypeHTML, base::UTF16ToUTF8(mime_types[0]));
base::string16 markup16;
std::string url;
uint32_t fragment_start, fragment_end;
- GetClipboard()->ReadHTML(ui::ClipboardType::kCopyPaste, &markup16, &url,
+ GetClipboard()->ReadHTML(ui::ClipboardBuffer::kCopyPaste, &markup16, &url,
&fragment_start, &fragment_end);
base::string16 result =
markup16.substr(fragment_start, fragment_end - fragment_start);
diff --git a/chromium/components/arc/common/app.typemap b/chromium/components/arc/common/app.typemap
deleted file mode 100644
index a6f3cfbf317..00000000000
--- a/chromium/components/arc/common/app.typemap
+++ /dev/null
@@ -1,5 +0,0 @@
-mojom = "//components/arc/common/app.mojom"
-public_headers = [ "//components/arc/app/arc_playstore_search_request_state.h" ]
-traits_headers = [ "//components/arc/common/app_struct_traits.h" ]
-type_mappings =
- [ "arc.mojom.AppDiscoveryRequestState=arc::ArcPlayStoreSearchRequestState" ]
diff --git a/chromium/components/arc/common/bitmap.typemap b/chromium/components/arc/common/bitmap.typemap
deleted file mode 100644
index 73529dc3611..00000000000
--- a/chromium/components/arc/common/bitmap.typemap
+++ /dev/null
@@ -1,13 +0,0 @@
-mojom = "//components/arc/common/bitmap.mojom"
-public_headers = [ "//third_party/skia/include/core/SkBitmap.h" ]
-traits_headers = [ "//components/arc/bitmap/bitmap_struct_traits.h" ]
-sources = [
- "//components/arc/bitmap/bitmap_struct_traits.cc",
-]
-deps = [
- "//skia",
-]
-public_deps = [
- "//skia",
-]
-type_mappings = [ "arc.mojom.ArcBitmap=SkBitmap" ]
diff --git a/chromium/components/arc/common/bluetooth.typemap b/chromium/components/arc/common/bluetooth.typemap
deleted file mode 100644
index d620cccabe9..00000000000
--- a/chromium/components/arc/common/bluetooth.typemap
+++ /dev/null
@@ -1,21 +0,0 @@
-mojom = "//components/arc/common/bluetooth.mojom"
-public_headers = [
- "//device/bluetooth/bluetooth_advertisement.h",
- "//device/bluetooth/bluetooth_common.h",
- "//device/bluetooth/public/cpp/bluetooth_uuid.h",
- "//device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h",
-]
-traits_headers = [ "//components/arc/bluetooth/bluetooth_struct_traits.h" ]
-sources = [
- "//components/arc/bluetooth/bluetooth_struct_traits.cc",
-]
-deps = [
- "//device/bluetooth",
- "//device/bluetooth/public/cpp",
-]
-type_mappings = [
- "arc.mojom.BluetoothDeviceType=device::BluetoothTransport",
- "arc.mojom.BluetoothSdpAttributeType=bluez::BluetoothServiceAttributeValueBlueZ::Type",
- "arc.mojom.BluetoothUUID=device::BluetoothUUID",
- "arc.mojom.BluetoothAdvertisement=std::unique_ptr<device::BluetoothAdvertisement::Data>[move_only]",
-]
diff --git a/chromium/components/arc/common/ime.typemap b/chromium/components/arc/common/ime.typemap
deleted file mode 100644
index ba967cf09fe..00000000000
--- a/chromium/components/arc/common/ime.typemap
+++ /dev/null
@@ -1,4 +0,0 @@
-mojom = "//components/arc/common/ime.mojom"
-public_headers = [ "//ui/base/ime/text_input_type.h" ]
-traits_headers = [ "//components/arc/common/ime_struct_traits.h" ]
-type_mappings = [ "arc.mojom.TextInputType=ui::TextInputType" ]
diff --git a/chromium/components/arc/common/print.typemap b/chromium/components/arc/common/print.typemap
deleted file mode 100644
index c8bb9251091..00000000000
--- a/chromium/components/arc/common/print.typemap
+++ /dev/null
@@ -1,19 +0,0 @@
-mojom = "//components/arc/common/print.mojom"
-public_headers = [
- "//printing/backend/print_backend.h",
- "//printing/page_range.h",
- "//ui/gfx/geometry/size.h",
-]
-traits_headers = [ "//chrome/browser/chromeos/arc/print/print_struct_traits.h" ]
-sources = [
- "//chrome/browser/chromeos/arc/print/print_struct_traits.cc",
-]
-deps = []
-public_deps = [
- "//printing:printing",
-]
-type_mappings = [
- "arc.mojom.PrintPageRange=printing::PageRange",
- "arc.mojom.PrintResolution=gfx::Size",
- "arc.mojom.PrinterCapabilities=printing::PrinterSemanticCapsAndDefaults",
-]
diff --git a/chromium/components/arc/common/print_spooler.mojom b/chromium/components/arc/common/print_spooler.mojom
deleted file mode 100644
index 81c415b78e7..00000000000
--- a/chromium/components/arc/common/print_spooler.mojom
+++ /dev/null
@@ -1,18 +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.
-//
-// Next MinVersion: 1
-
-module arc.mojom;
-
-// Next method ID: 0
-interface PrintSpoolerHost {
- // TODO(jschettler): Add methods to open and close print preview
-};
-
-// Next method ID: 1
-interface PrintSpoolerInstance {
- // Establishes full-duplex communication with the host.
- [MinVersion=0] Init@0(PrintSpoolerHost host_ptr) => ();
-}; \ No newline at end of file
diff --git a/chromium/components/arc/common/timer.typemap b/chromium/components/arc/common/timer.typemap
deleted file mode 100644
index df7d6f3401c..00000000000
--- a/chromium/components/arc/common/timer.typemap
+++ /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.
-
-mojom = "//components/arc/common/timer.mojom"
-traits_headers = [ "//components/arc/timer/arc_timer_struct_traits.h" ]
-sources = [
- "//components/arc/timer/arc_timer_struct_traits.cc",
-]
-type_mappings = [ "arc.mojom.ClockId=clockid_t" ]
diff --git a/chromium/components/arc/common/typemaps.gni b/chromium/components/arc/common/typemaps.gni
deleted file mode 100644
index 7756be687e1..00000000000
--- a/chromium/components/arc/common/typemaps.gni
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-typemaps = [
- "//components/arc/common/app.typemap",
- "//components/arc/common/bitmap.typemap",
- "//components/arc/common/bluetooth.typemap",
- "//components/arc/common/file_system.typemap",
- "//components/arc/common/gfx.typemap",
- "//components/arc/common/ime.typemap",
- "//components/arc/common/intent_helper.typemap",
- "//components/arc/common/print.typemap",
- "//components/arc/common/timer.typemap",
- "//components/arc/common/video_common.typemap",
- "//components/arc/common/video_encode_accelerator.typemap",
- "//components/arc/common/volume_mounter.typemap",
-]
diff --git a/chromium/components/arc/common/video_encode_accelerator.typemap b/chromium/components/arc/common/video_encode_accelerator.typemap
deleted file mode 100644
index 5210cc6379d..00000000000
--- a/chromium/components/arc/common/video_encode_accelerator.typemap
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//components/arc/common/video_encode_accelerator.mojom"
-public_headers = [ "//media/video/video_encode_accelerator.h" ]
-public_deps = [
- "//base",
- "//media/gpu",
-]
-traits_headers =
- [ "//components/arc/common/video_encode_accelerator_struct_traits.h" ]
-sources = [
- "//components/arc/common/video_encode_accelerator_struct_traits.cc",
-]
-deps = [
- "//base",
-]
-type_mappings = [
- "arc.mojom.VideoFrameStorageType=media::VideoEncodeAccelerator::Config::StorageType",
- "arc.mojom.VideoEncodeAccelerator.Error=media::VideoEncodeAccelerator::Error",
- "arc.mojom.VideoEncodeProfile=media::VideoEncodeAccelerator::SupportedProfile",
- "arc.mojom.VideoEncodeAcceleratorConfig=media::VideoEncodeAccelerator::Config",
-]
diff --git a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
index a265482e39b..8cc5dbcb344 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -91,8 +91,8 @@ ArcCrashCollectorBridge::~ArcCrashCollectorBridge() {
void ArcCrashCollectorBridge::DumpCrash(const std::string& type,
mojo::ScopedHandle pipe) {
- base::PostTaskWithTraits(
- FROM_HERE, {base::WithBaseSyncPrimitives()},
+ base::PostTask(
+ FROM_HERE, {base::ThreadPool(), base::WithBaseSyncPrimitives()},
base::BindOnce(&RunCrashReporter, type, device_, board_, cpu_abi_,
mojo::UnwrapPlatformHandle(std::move(pipe)).TakeFD()));
}
diff --git a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
index 9da78baf6e7..af1814d4a19 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/macros.h"
-#include "components/arc/common/crash_collector.mojom.h"
+#include "components/arc/mojom/crash_collector.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/disk_quota/arc_disk_quota_bridge.h b/chromium/components/arc/disk_quota/arc_disk_quota_bridge.h
index 3b8c73f0055..1ceca5687c1 100644
--- a/chromium/components/arc/disk_quota/arc_disk_quota_bridge.h
+++ b/chromium/components/arc/disk_quota/arc_disk_quota_bridge.h
@@ -6,7 +6,7 @@
#define COMPONENTS_ARC_DISK_QUOTA_ARC_DISK_QUOTA_BRIDGE_H_
#include "base/macros.h"
-#include "components/arc/common/disk_quota.mojom.h"
+#include "components/arc/mojom/disk_quota.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/file_system/OWNERS b/chromium/components/arc/file_system/OWNERS
index ef5cf841917..012a33c0b1c 100644
--- a/chromium/components/arc/file_system/OWNERS
+++ b/chromium/components/arc/file_system/OWNERS
@@ -1,3 +1,3 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/file_system/file_system_struct_traits.cc b/chromium/components/arc/file_system/file_system_mojom_traits.cc
index df97e6bb621..9af0c129a1e 100644
--- a/chromium/components/arc/file_system/file_system_struct_traits.cc
+++ b/chromium/components/arc/file_system/file_system_mojom_traits.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/arc/file_system/file_system_struct_traits.h"
+#include "components/arc/file_system/file_system_mojom_traits.h"
#include "base/logging.h"
-#include "components/arc/common/file_system.mojom.h"
+#include "components/arc/mojom/file_system.mojom.h"
namespace mojo {
diff --git a/chromium/components/arc/file_system/file_system_struct_traits.h b/chromium/components/arc/file_system/file_system_mojom_traits.h
index eae87efd1f4..d69f407ed1e 100644
--- a/chromium/components/arc/file_system/file_system_struct_traits.h
+++ b/chromium/components/arc/file_system/file_system_mojom_traits.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_FILE_SYSTEM_FILE_SYSTEM_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_FILE_SYSTEM_FILE_SYSTEM_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_FILE_SYSTEM_FILE_SYSTEM_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_FILE_SYSTEM_FILE_SYSTEM_MOJOM_TRAITS_H_
-#include "components/arc/common/file_system.mojom.h"
+#include "components/arc/mojom/file_system.mojom.h"
#include "storage/browser/fileapi/watcher_manager.h"
namespace mojo {
@@ -20,4 +20,4 @@ struct EnumTraits<arc::mojom::ChangeType, storage::WatcherManager::ChangeType> {
} // namespace mojo
-#endif // COMPONENTS_ARC_FILE_SYSTEM_FILE_SYSTEM_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_FILE_SYSTEM_FILE_SYSTEM_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/ime/arc_ime_bridge_impl.h b/chromium/components/arc/ime/arc_ime_bridge_impl.h
index eb68bd47220..f5ac479fb35 100644
--- a/chromium/components/arc/ime/arc_ime_bridge_impl.h
+++ b/chromium/components/arc/ime/arc_ime_bridge_impl.h
@@ -9,8 +9,8 @@
#include "base/macros.h"
#include "base/strings/string16.h"
-#include "components/arc/common/ime.mojom.h"
#include "components/arc/ime/arc_ime_bridge.h"
+#include "components/arc/mojom/ime.mojom.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/components/arc/ime/arc_ime_service.cc b/chromium/components/arc/ime/arc_ime_service.cc
index 5b4a0c02da5..5db6d525c89 100644
--- a/chromium/components/arc/ime/arc_ime_service.cc
+++ b/chromium/components/arc/ime/arc_ime_service.cc
@@ -252,6 +252,13 @@ void ArcImeService::OnWindowPropertyChanged(aura::Window* window,
}
}
+void ArcImeService::OnWindowRemoved(aura::Window* removed_window) {
+ // |this| can lose the IME focus because |focused_arc_window_| may have
+ // children other than ExoSurface e.g. WebContentsViewAura for CustomTabs.
+ // Restore the IME focus when such a window is removed.
+ ReattachInputMethod(nullptr, focused_arc_window_);
+}
+
////////////////////////////////////////////////////////////////////////////////
// Overridden from exo::WMHelper::FocusChangeObserver:
diff --git a/chromium/components/arc/ime/arc_ime_service.h b/chromium/components/arc/ime/arc_ime_service.h
index c8f20c8c8fe..9b68a96f7e1 100644
--- a/chromium/components/arc/ime/arc_ime_service.h
+++ b/chromium/components/arc/ime/arc_ime_service.h
@@ -84,6 +84,7 @@ class ArcImeService : public KeyedService,
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override;
+ void OnWindowRemoved(aura::Window* removed_window) override;
// Overridden from aura::client::FocusChangeObserver:
void OnWindowFocused(aura::Window* gained_focus,
diff --git a/chromium/components/arc/ime/arc_ime_service_unittest.cc b/chromium/components/arc/ime/arc_ime_service_unittest.cc
index 0fa67211789..ee62ec60690 100644
--- a/chromium/components/arc/ime/arc_ime_service_unittest.cc
+++ b/chromium/components/arc/ime/arc_ime_service_unittest.cc
@@ -11,7 +11,7 @@
#include "ash/keyboard/ui/keyboard_ui_controller.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/arc/common/ime.mojom.h"
+#include "components/arc/mojom/ime.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/test/test_window_delegate.h"
diff --git a/chromium/components/arc/intent_helper/OWNERS b/chromium/components/arc/intent_helper/OWNERS
index 99a8310c6ae..d2e1c3575fe 100644
--- a/chromium/components/arc/intent_helper/OWNERS
+++ b/chromium/components/arc/intent_helper/OWNERS
@@ -1,5 +1,6 @@
djacobo@chromium.org
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
+# COMPONENT: Platform>Apps>Foundation
diff --git a/chromium/components/arc/intent_helper/activity_icon_loader.cc b/chromium/components/arc/intent_helper/activity_icon_loader.cc
index 970e1b39849..5bcebf5a201 100644
--- a/chromium/components/arc/intent_helper/activity_icon_loader.cc
+++ b/chromium/components/arc/intent_helper/activity_icon_loader.cc
@@ -165,7 +165,7 @@ bool ActivityIconLoader::ActivityName::operator<(
}
ActivityIconLoader::ActivityIconLoader()
- : scale_factor_(GetSupportedScaleFactor()), weak_ptr_factory_(this) {}
+ : scale_factor_(GetSupportedScaleFactor()) {}
ActivityIconLoader::~ActivityIconLoader() = default;
diff --git a/chromium/components/arc/intent_helper/activity_icon_loader.h b/chromium/components/arc/intent_helper/activity_icon_loader.h
index 3b07589fd21..835eae82c5e 100644
--- a/chromium/components/arc/intent_helper/activity_icon_loader.h
+++ b/chromium/components/arc/intent_helper/activity_icon_loader.h
@@ -15,7 +15,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
#include "ui/base/layout.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"
@@ -112,7 +112,7 @@ class ActivityIconLoader {
THREAD_CHECKER(thread_checker_);
// This must come last to make sure weak pointers are invalidated first.
- base::WeakPtrFactory<ActivityIconLoader> weak_ptr_factory_;
+ base::WeakPtrFactory<ActivityIconLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ActivityIconLoader);
};
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
index 94d7f97a2c9..e1be685f248 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -14,9 +14,9 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/intent_helper.mojom.h"
#include "components/arc/intent_helper/activity_icon_loader.h"
#include "components/arc/intent_helper/arc_intent_helper_observer.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
#include "url/gurl.h"
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
index 18edc662742..072e957ff9b 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc
@@ -8,8 +8,8 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "components/arc/common/intent_helper.mojom.h"
#include "components/arc/intent_helper/open_url_delegate.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/arc/intent_helper/factory_reset_delegate.h b/chromium/components/arc/intent_helper/factory_reset_delegate.h
index edddbe34db6..0ac61513aa2 100644
--- a/chromium/components/arc/intent_helper/factory_reset_delegate.h
+++ b/chromium/components/arc/intent_helper/factory_reset_delegate.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_ARC_INTENT_HELPER_FACTORY_RESET_DELEGATE_H_
#define COMPONENTS_ARC_INTENT_HELPER_FACTORY_RESET_DELEGATE_H_
-#include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
namespace arc {
diff --git a/chromium/components/arc/intent_helper/intent_filter.cc b/chromium/components/arc/intent_helper/intent_filter.cc
index d82b8ba260f..bb4720a0932 100644
--- a/chromium/components/arc/intent_helper/intent_filter.cc
+++ b/chromium/components/arc/intent_helper/intent_filter.cc
@@ -8,7 +8,7 @@
#include "base/compiler_specific.h"
#include "base/strings/string_util.h"
-#include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
#include "url/gurl.h"
namespace arc {
diff --git a/chromium/components/arc/intent_helper/intent_filter_struct_traits.cc b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc
index 1a33f43a5eb..0ae02e7fd69 100644
--- a/chromium/components/arc/intent_helper/intent_filter_struct_traits.cc
+++ b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.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 "components/arc/intent_helper/intent_filter_struct_traits.h"
+#include "components/arc/intent_helper/intent_filter_mojom_traits.h"
#include <string>
#include <utility>
@@ -12,9 +12,9 @@
namespace mojo {
-bool StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter>::
- Read(arc::mojom::IntentFilterDataView data,
- arc::IntentFilter* out) {
+bool StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter>::Read(
+ arc::mojom::IntentFilterDataView data,
+ arc::IntentFilter* out) {
std::vector<arc::IntentFilter::AuthorityEntry> authorities;
if (!data.ReadDataAuthorities(&authorities))
return false;
@@ -33,7 +33,7 @@ bool StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter>::
}
bool StructTraits<arc::mojom::AuthorityEntryDataView,
- arc::IntentFilter::AuthorityEntry>::
+ arc::IntentFilter::AuthorityEntry>::
Read(arc::mojom::AuthorityEntryDataView data,
arc::IntentFilter::AuthorityEntry* out) {
std::string host;
@@ -45,9 +45,9 @@ bool StructTraits<arc::mojom::AuthorityEntryDataView,
}
bool StructTraits<arc::mojom::PatternMatcherDataView,
- arc::IntentFilter::PatternMatcher>::
- Read(arc::mojom::PatternMatcherDataView data,
- arc::IntentFilter::PatternMatcher* out) {
+ arc::IntentFilter::PatternMatcher>::
+ Read(arc::mojom::PatternMatcherDataView data,
+ arc::IntentFilter::PatternMatcher* out) {
std::string pattern;
if (!data.ReadPattern(&pattern))
return false;
diff --git a/chromium/components/arc/intent_helper/intent_filter_struct_traits.h b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.h
index 421001dad36..7ef52ca347f 100644
--- a/chromium/components/arc/intent_helper/intent_filter_struct_traits.h
+++ b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_MOJOM_TRAITS_H_
#include <string>
#include <vector>
#include "base/containers/span.h"
-#include "components/arc/common/intent_helper.mojom.h"
#include "components/arc/intent_helper/intent_filter.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
namespace mojo {
@@ -83,4 +83,4 @@ struct StructTraits<arc::mojom::PatternMatcherDataView,
} // namespace mojo
-#endif // COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/intent_helper/intent_filter_unittest.cc b/chromium/components/arc/intent_helper/intent_filter_unittest.cc
index 73a9d3fe934..0bcc241b0e4 100644
--- a/chromium/components/arc/intent_helper/intent_filter_unittest.cc
+++ b/chromium/components/arc/intent_helper/intent_filter_unittest.cc
@@ -9,8 +9,8 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
-#include "components/arc/common/intent_helper.mojom.h"
#include "components/arc/intent_helper/intent_filter.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/components/arc/intent_helper/link_handler_model.h b/chromium/components/arc/intent_helper/link_handler_model.h
index 3cf7bf32c95..5c7cc9e87c9 100644
--- a/chromium/components/arc/intent_helper/link_handler_model.h
+++ b/chromium/components/arc/intent_helper/link_handler_model.h
@@ -11,8 +11,8 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
-#include "components/arc/common/intent_helper.mojom.h"
#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/components/arc/intent_helper/open_url_delegate.h b/chromium/components/arc/intent_helper/open_url_delegate.h
index 602b62def4c..b4bc58796fe 100644
--- a/chromium/components/arc/intent_helper/open_url_delegate.h
+++ b/chromium/components/arc/intent_helper/open_url_delegate.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_ARC_INTENT_HELPER_OPEN_URL_DELEGATE_H_
#define COMPONENTS_ARC_INTENT_HELPER_OPEN_URL_DELEGATE_H_
-#include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
class GURL;
diff --git a/chromium/components/arc/keymaster/arc_keymaster_bridge.h b/chromium/components/arc/keymaster/arc_keymaster_bridge.h
index 32833e3f8d7..a5ed47eb5b7 100644
--- a/chromium/components/arc/keymaster/arc_keymaster_bridge.h
+++ b/chromium/components/arc/keymaster/arc_keymaster_bridge.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "components/arc/common/keymaster.mojom.h"
+#include "components/arc/mojom/keymaster.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
index 4274763f8ee..9d1c7757412 100644
--- a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
+++ b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/lock_screen.mojom.h"
+#include "components/arc/mojom/lock_screen.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/session_manager/core/session_manager_observer.h"
diff --git a/chromium/components/arc/media_session/arc_media_session_bridge.cc b/chromium/components/arc/media_session/arc_media_session_bridge.cc
index e5c0dbdf0ba..a532ce0ce42 100644
--- a/chromium/components/arc/media_session/arc_media_session_bridge.cc
+++ b/chromium/components/arc/media_session/arc_media_session_bridge.cc
@@ -91,7 +91,8 @@ void ArcMediaSessionBridge::SetupAudioFocus() {
content::GetSystemConnector()->BindInterface(
media_session::mojom::kServiceName, &audio_focus_ptr);
- audio_focus_ptr->SetSourceName(kAudioFocusSourceName);
+ audio_focus_ptr->SetSource(base::UnguessableToken::Create(),
+ kAudioFocusSourceName);
DVLOG(2) << "ArcMediaSessionBridge will enable audio focus";
ms_instance->EnableAudioFocus(std::move(audio_focus_ptr));
diff --git a/chromium/components/arc/media_session/arc_media_session_bridge.h b/chromium/components/arc/media_session/arc_media_session_bridge.h
index 9d81768a41d..8cb89bed047 100644
--- a/chromium/components/arc/media_session/arc_media_session_bridge.h
+++ b/chromium/components/arc/media_session/arc_media_session_bridge.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/macros.h"
-#include "components/arc/common/media_session.mojom.h"
+#include "components/arc/mojom/media_session.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/arc/metrics/arc_metrics_service.cc b/chromium/components/arc/metrics/arc_metrics_service.cc
index cfc8161d338..3d1b52a331a 100644
--- a/chromium/components/arc/metrics/arc_metrics_service.cc
+++ b/chromium/components/arc/metrics/arc_metrics_service.cc
@@ -13,9 +13,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
-#include "base/system/sys_info.h"
-#include "base/time/default_clock.h"
-#include "base/time/default_tick_clock.h"
#include "chromeos/dbus/power_manager/idle.pb.h"
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
@@ -26,7 +23,6 @@
#include "components/arc/session/arc_bridge_service.h"
#include "components/exo/wm_helper.h"
#include "components/prefs/pref_service.h"
-#include "components/session_manager/core/session_manager.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
#include "ui/events/ozone/gamepad/gamepad_provider_ozone.h"
@@ -35,6 +31,8 @@ namespace arc {
namespace {
+constexpr char kUmaPrefix[] = "Arc";
+
constexpr base::TimeDelta kUmaMinTime = base::TimeDelta::FromMilliseconds(1);
constexpr base::TimeDelta kUmaMaxTime = base::TimeDelta::FromSeconds(60);
constexpr int kUmaNumBuckets = 50;
@@ -45,11 +43,6 @@ constexpr char kArcProcessNamePrefix[] = "org.chromium.arc.";
constexpr char kGmsProcessNamePrefix[] = "com.google.android.gms";
constexpr char kBootProgressEnableScreen[] = "boot_progress_enable_screen";
-constexpr base::TimeDelta kUpdateEngagementTimePeriod =
- base::TimeDelta::FromMinutes(1);
-constexpr base::TimeDelta kSaveEngagementTimeToPrefsPeriod =
- base::TimeDelta::FromMinutes(30);
-
std::string BootTypeToString(mojom::BootType boot_type) {
switch (boot_type) {
case mojom::BootType::UNKNOWN:
@@ -65,40 +58,6 @@ std::string BootTypeToString(mojom::BootType boot_type) {
return "";
}
-inline int GetDayId(const base::Clock* clock) {
- return clock->Now().LocalMidnight().since_origin().InDays();
-}
-
-class ArcWindowDelegateImpl : public ArcMetricsService::ArcWindowDelegate {
- public:
- explicit ArcWindowDelegateImpl(ArcMetricsService* service)
- : service_(service) {}
-
- ~ArcWindowDelegateImpl() override = default;
-
- bool IsArcAppWindow(const aura::Window* window) const override {
- return arc::IsArcAppWindow(window);
- }
-
- void RegisterActivationChangeObserver() override {
- // If WMHelper doesn't exist, do nothing. This occurs in tests.
- if (exo::WMHelper::HasInstance())
- exo::WMHelper::GetInstance()->AddActivationObserver(service_);
- }
-
- void UnregisterActivationChangeObserver() override {
- // If WMHelper is already destroyed, do nothing.
- // TODO(crbug.com/748380): Fix shutdown order.
- if (exo::WMHelper::HasInstance())
- exo::WMHelper::GetInstance()->RemoveActivationObserver(service_);
- }
-
- private:
- ArcMetricsService* const service_; // Owned by ArcMetricsService
-
- DISALLOW_COPY_AND_ASSIGN(ArcWindowDelegateImpl);
-};
-
// Singleton factory for ArcMetricsService.
class ArcMetricsServiceFactory
: public internal::ArcBrowserContextKeyedServiceFactoryBase<
@@ -140,61 +99,34 @@ BrowserContextKeyedServiceFactory* ArcMetricsService::GetFactory() {
ArcMetricsService::ArcMetricsService(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service),
- arc_window_delegate_(std::make_unique<ArcWindowDelegateImpl>(this)),
- process_observer_(this),
- pref_service_(user_prefs::UserPrefs::Get(context)),
- clock_(base::DefaultClock::GetInstance()),
- tick_clock_(base::DefaultTickClock::GetInstance()),
- last_update_ticks_(tick_clock_->NowTicks()),
- weak_ptr_factory_(this) {
+ guest_os_engagement_metrics_(user_prefs::UserPrefs::Get(context),
+ base::BindRepeating(arc::IsArcAppWindow),
+ prefs::kEngagementPrefsPrefix,
+ kUmaPrefix),
+ process_observer_(this) {
arc_bridge_service_->metrics()->SetHost(this);
arc_bridge_service_->process()->AddObserver(&process_observer_);
- arc_window_delegate_->RegisterActivationChangeObserver();
- session_manager::SessionManager::Get()->AddObserver(this);
- chromeos::PowerManagerClient::Get()->AddObserver(this);
+ // If WMHelper doesn't exist, do nothing. This occurs in tests.
+ if (exo::WMHelper::HasInstance())
+ exo::WMHelper::GetInstance()->AddActivationObserver(this);
ui::GamepadProviderOzone::GetInstance()->AddGamepadObserver(this);
- DCHECK(pref_service_);
- RestoreEngagementTimeFromPrefs();
- update_engagement_time_timer_.Start(FROM_HERE, kUpdateEngagementTimePeriod,
- this,
- &ArcMetricsService::UpdateEngagementTime);
- save_engagement_time_to_prefs_timer_.Start(
- FROM_HERE, kSaveEngagementTimeToPrefsPeriod, this,
- &ArcMetricsService::SaveEngagementTimeToPrefs);
-
StabilityMetricsManager::Get()->SetArcNativeBridgeType(
NativeBridgeType::UNKNOWN);
}
ArcMetricsService::~ArcMetricsService() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- save_engagement_time_to_prefs_timer_.Stop();
- update_engagement_time_timer_.Stop();
- UpdateEngagementTime();
- SaveEngagementTimeToPrefs();
ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this);
- chromeos::PowerManagerClient::Get()->RemoveObserver(this);
- session_manager::SessionManager::Get()->RemoveObserver(this);
- arc_window_delegate_->UnregisterActivationChangeObserver();
+ // If WMHelper is already destroyed, do nothing.
+ // TODO(crbug.com/748380): Fix shutdown order.
+ if (exo::WMHelper::HasInstance())
+ exo::WMHelper::GetInstance()->RemoveActivationObserver(this);
arc_bridge_service_->process()->RemoveObserver(&process_observer_);
arc_bridge_service_->metrics()->SetHost(nullptr);
}
-void ArcMetricsService::SetArcWindowDelegateForTesting(
- std::unique_ptr<ArcWindowDelegate> delegate) {
- arc_window_delegate_ = std::move(delegate);
-}
-
-void ArcMetricsService::SetClockForTesting(base::Clock* clock) {
- clock_ = clock;
-}
-
-void ArcMetricsService::SetTickClockForTesting(base::TickClock* tick_clock) {
- tick_clock_ = tick_clock;
-}
-
void ArcMetricsService::OnProcessConnectionReady() {
VLOG(2) << "Start updating process list.";
request_process_list_timer_.Start(FROM_HERE, kRequestProcessListPeriod, this,
@@ -326,8 +258,7 @@ void ArcMetricsService::OnWindowActivated(
wm::ActivationChangeObserver::ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) {
- UpdateEngagementTime();
- was_arc_window_active_ = arc_window_delegate_->IsArcAppWindow(gained_active);
+ was_arc_window_active_ = arc::IsArcAppWindow(gained_active);
if (!was_arc_window_active_) {
gamepad_interaction_recorded_ = false;
return;
@@ -337,19 +268,6 @@ void ArcMetricsService::OnWindowActivated(
UserInteractionType::APP_CONTENT_WINDOW_INTERACTION);
}
-void ArcMetricsService::OnSessionStateChanged() {
- UpdateEngagementTime();
- was_session_active_ =
- session_manager::SessionManager::Get()->session_state() ==
- session_manager::SessionState::ACTIVE;
-}
-
-void ArcMetricsService::ScreenIdleStateChanged(
- const power_manager::ScreenIdleState& proto) {
- UpdateEngagementTime();
- was_screen_dimmed_ = proto.dimmed();
-}
-
void ArcMetricsService::OnGamepadEvent(const ui::GamepadEvent& event) {
if (!was_arc_window_active_)
return;
@@ -364,125 +282,18 @@ void ArcMetricsService::OnTaskCreated(int32_t task_id,
const std::string& package_name,
const std::string& activity,
const std::string& intent) {
- UpdateEngagementTime();
task_ids_.push_back(task_id);
+ guest_os_engagement_metrics_.SetBackgroundActive(true);
}
void ArcMetricsService::OnTaskDestroyed(int32_t task_id) {
- UpdateEngagementTime();
auto it = std::find(task_ids_.begin(), task_ids_.end(), task_id);
if (it == task_ids_.end()) {
LOG(WARNING) << "unknown task_id, background time might be undermeasured";
return;
}
task_ids_.erase(it);
-}
-
-void ArcMetricsService::RestoreEngagementTimeFromPrefs() {
- // Restore accumulated results only if they were recorded on the same OS
- // version.
- if (pref_service_->GetString(prefs::kEngagementTimeOsVersion) ==
- base::SysInfo::OperatingSystemVersion()) {
- day_id_ = pref_service_->GetInteger(prefs::kEngagementTimeDayId);
- engagement_time_total_ =
- pref_service_->GetTimeDelta(prefs::kEngagementTimeTotal);
- engagement_time_foreground_ =
- pref_service_->GetTimeDelta(prefs::kEngagementTimeForeground);
- engagement_time_background_ =
- pref_service_->GetTimeDelta(prefs::kEngagementTimeBackground);
- } else {
- ResetEngagementTimePrefs();
- }
-
- RecordEngagementTimeToUmaIfNeeded();
-}
-
-void ArcMetricsService::SaveEngagementTimeToPrefs() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(pref_service_);
-
- pref_service_->SetString(prefs::kEngagementTimeOsVersion,
- base::SysInfo::OperatingSystemVersion());
- pref_service_->SetInteger(prefs::kEngagementTimeDayId, day_id_);
- pref_service_->SetTimeDelta(prefs::kEngagementTimeTotal,
- engagement_time_total_);
- pref_service_->SetTimeDelta(prefs::kEngagementTimeForeground,
- engagement_time_foreground_);
- pref_service_->SetTimeDelta(prefs::kEngagementTimeBackground,
- engagement_time_background_);
-}
-
-void ArcMetricsService::UpdateEngagementTime() {
- VLOG(2) << "last state: dimmed=" << was_screen_dimmed_
- << " active=" << was_session_active_
- << " focus=" << was_arc_window_active_
- << " #tasks=" << task_ids_.size();
-
- base::TimeTicks now = tick_clock_->NowTicks();
- base::TimeDelta elapsed = now - last_update_ticks_;
-
- if (ShouldAccumulateEngagementTotalTime()) {
- VLOG(2) << "accumulate to total time " << elapsed;
- engagement_time_total_ += elapsed;
- if (ShouldAccumulateEngagementForegroundTime()) {
- VLOG(2) << "accumulate to foreground time " << elapsed;
- engagement_time_foreground_ += elapsed;
- } else if (ShouldAccumulateEngagementBackgroundTime()) {
- VLOG(2) << "accumulate to background time " << elapsed;
- engagement_time_background_ += elapsed;
- }
- }
-
- last_update_ticks_ = now;
- RecordEngagementTimeToUmaIfNeeded();
-}
-
-void ArcMetricsService::RecordEngagementTimeToUmaIfNeeded() {
- if (!ShouldRecordEngagementTimeToUma())
- return;
- VLOG(2) << "day changed, recording engagement time to UMA";
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Arc.EngagementTime.Total", engagement_time_total_,
- base::TimeDelta::FromSeconds(1),
- base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Arc.EngagementTime.ArcTotal",
- engagement_time_foreground_ + engagement_time_background_,
- base::TimeDelta::FromSeconds(1),
- base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Arc.EngagementTime.Foreground", engagement_time_foreground_,
- base::TimeDelta::FromSeconds(1),
- base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Arc.EngagementTime.Background", engagement_time_background_,
- base::TimeDelta::FromSeconds(1),
- base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
- ResetEngagementTimePrefs();
-}
-
-void ArcMetricsService::ResetEngagementTimePrefs() {
- day_id_ = GetDayId(clock_);
- engagement_time_total_ = base::TimeDelta();
- engagement_time_foreground_ = base::TimeDelta();
- engagement_time_background_ = base::TimeDelta();
- SaveEngagementTimeToPrefs();
-}
-
-bool ArcMetricsService::ShouldAccumulateEngagementTotalTime() const {
- return was_session_active_ && !was_screen_dimmed_;
-}
-
-bool ArcMetricsService::ShouldAccumulateEngagementForegroundTime() const {
- return was_arc_window_active_;
-}
-
-bool ArcMetricsService::ShouldAccumulateEngagementBackgroundTime() const {
- return task_ids_.size() > 0;
-}
-
-bool ArcMetricsService::ShouldRecordEngagementTimeToUma() const {
- return day_id_ != GetDayId(clock_);
+ guest_os_engagement_metrics_.SetBackgroundActive(!task_ids_.empty());
}
ArcMetricsService::ProcessObserver::ProcessObserver(
diff --git a/chromium/components/arc/metrics/arc_metrics_service.h b/chromium/components/arc/metrics/arc_metrics_service.h
index ba3a11f768b..fefddb6c18b 100644
--- a/chromium/components/arc/metrics/arc_metrics_service.h
+++ b/chromium/components/arc/metrics/arc_metrics_service.h
@@ -15,27 +15,20 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
-#include "chromeos/dbus/power/power_manager_client.h"
-#include "components/arc/common/metrics.mojom.h"
-#include "components/arc/common/process.mojom.h"
+#include "components/arc/mojom/metrics.mojom.h"
+#include "components/arc/mojom/process.mojom.h"
#include "components/arc/session/connection_observer.h"
+#include "components/guest_os/guest_os_engagement_metrics.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "components/session_manager/core/session_manager_observer.h"
#include "ui/events/ozone/gamepad/gamepad_observer.h"
#include "ui/wm/public/activation_change_observer.h"
class BrowserContextKeyedServiceFactory;
-class PrefService;
namespace aura {
class Window;
} // namespace aura
-namespace base {
-class Clock;
-class TickClock;
-} // namespace base
-
namespace content {
class BrowserContext;
} // namespace content
@@ -47,32 +40,9 @@ class ArcBridgeService;
// Collects information from other ArcServices and send UMA metrics.
class ArcMetricsService : public KeyedService,
public wm::ActivationChangeObserver,
- public session_manager::SessionManagerObserver,
- public chromeos::PowerManagerClient::Observer,
public mojom::MetricsHost,
public ui::GamepadObserver {
public:
- // Delegate for handling window focus observation that is used to track ARC
- // app usage metrics.
- class ArcWindowDelegate {
- public:
- virtual ~ArcWindowDelegate() = default;
- // Returns whether |window| is an ARC window.
- virtual bool IsArcAppWindow(const aura::Window* window) const = 0;
- virtual void RegisterActivationChangeObserver() = 0;
- virtual void UnregisterActivationChangeObserver() = 0;
- };
-
- // Sets the fake ArcWindowDelegate for testing.
- void SetArcWindowDelegateForTesting(
- std::unique_ptr<ArcWindowDelegate> delegate);
-
- // Sets Clock for testing.
- void SetClockForTesting(base::Clock* clock);
-
- // Sets TickClock for testing.
- void SetTickClockForTesting(base::TickClock* tick_clock);
-
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcMetricsService* GetForBrowserContext(
@@ -102,13 +72,6 @@ class ArcMetricsService : public KeyedService,
aura::Window* gained_active,
aura::Window* lost_active) override;
- // session_manager::SessionManagerObserver overrides.
- void OnSessionStateChanged() override;
-
- // chromeos::PowerManagerClient::Observer overrides.
- void ScreenIdleStateChanged(
- const power_manager::ScreenIdleState& proto) override;
-
// ui::GamepadObserver overrides.
void OnGamepadEvent(const ui::GamepadEvent& event) override;
@@ -145,63 +108,24 @@ class ArcMetricsService : public KeyedService,
mojom::BootType boot_type,
base::Optional<base::TimeTicks> arc_start_time);
- // Restores accumulated ARC++ engagement time in previous sessions from
- // profile preferences.
- void RestoreEngagementTimeFromPrefs();
-
- // Called periodically to save accumulated results to profile preferences.
- void SaveEngagementTimeToPrefs();
-
- // Called whenever engagement state is changed. Time spent in last state is
- // accumulated to corresponding metrics.
- void UpdateEngagementTime();
-
- // Records accumulated engagement time metrics to UMA if necessary (i.e. day
- // has changed).
- void RecordEngagementTimeToUmaIfNeeded();
-
- // Resets accumulated engagement times to zero, and updates both OS version
- // and day ID.
- void ResetEngagementTimePrefs();
-
- bool ShouldAccumulateEngagementTotalTime() const;
- bool ShouldAccumulateEngagementForegroundTime() const;
- bool ShouldAccumulateEngagementBackgroundTime() const;
- bool ShouldRecordEngagementTimeToUma() const;
-
THREAD_CHECKER(thread_checker_);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- std::unique_ptr<ArcWindowDelegate> arc_window_delegate_;
+
+ // Helper class for tracking engagement metrics.
+ guest_os::GuestOsEngagementMetrics guest_os_engagement_metrics_;
ProcessObserver process_observer_;
base::RepeatingTimer request_process_list_timer_;
- PrefService* const pref_service_;
- const base::Clock* clock_;
- const base::TickClock* tick_clock_;
- base::RepeatingTimer update_engagement_time_timer_;
- base::RepeatingTimer save_engagement_time_to_prefs_timer_;
- base::TimeTicks last_update_ticks_;
-
- // States for determining which engagement metrics should we accumulate to.
- bool was_session_active_ = false;
- bool was_screen_dimmed_ = false;
bool was_arc_window_active_ = false;
std::vector<int32_t> task_ids_;
- // Accumulated results and associated state which are saved to profile
- // preferences at fixed interval.
- int day_id_ = 0;
- base::TimeDelta engagement_time_total_;
- base::TimeDelta engagement_time_foreground_;
- base::TimeDelta engagement_time_background_;
-
bool gamepad_interaction_recorded_ = false;
// Always keep this the last member of this class to make sure it's the
// first thing to be destructed.
- base::WeakPtrFactory<ArcMetricsService> weak_ptr_factory_;
+ base::WeakPtrFactory<ArcMetricsService> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcMetricsService);
};
diff --git a/chromium/components/arc/metrics/arc_metrics_service_unittest.cc b/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
index dd91dfb8ce4..c48b29206e1 100644
--- a/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
+++ b/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -6,19 +6,12 @@
#include <algorithm>
#include <array>
-#include <memory>
-#include <string>
#include <utility>
#include "ash/public/cpp/app_types.h"
#include "base/metrics/histogram_samples.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/time/clock.h"
-#include "base/time/tick_clock.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power/fake_power_manager_client.h"
-#include "chromeos/dbus/power_manager/idle.pb.h"
#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_service_manager.h"
@@ -27,133 +20,15 @@
#include "components/arc/test/test_browser_context.h"
#include "components/prefs/testing_pref_service.h"
#include "components/session_manager/core/session_manager.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
namespace arc {
namespace {
-// Fake ArcWindowDelegate to help test recording UMA on focus changes,
-// not depending on the full setup of Exo and Ash.
-class FakeArcWindowDelegate : public ArcMetricsService::ArcWindowDelegate {
- public:
- FakeArcWindowDelegate() = default;
- ~FakeArcWindowDelegate() override = default;
-
- bool IsArcAppWindow(const aura::Window* window) const override {
- return focused_window_id_ == arc_window_id_;
- }
-
- void RegisterActivationChangeObserver() override {}
- void UnregisterActivationChangeObserver() override {}
-
- std::unique_ptr<aura::Window> CreateFakeArcWindow() {
- const int id = next_id_++;
- arc_window_id_ = id;
- std::unique_ptr<aura::Window> window(
- base::WrapUnique(aura::test::CreateTestWindowWithDelegate(
- &dummy_delegate_, id, gfx::Rect(), nullptr)));
- window->SetProperty(aura::client::kAppType,
- static_cast<int>(ash::AppType::ARC_APP));
- return window;
- }
-
- std::unique_ptr<aura::Window> CreateFakeNonArcWindow() {
- const int id = next_id_++;
- return base::WrapUnique(aura::test::CreateTestWindowWithDelegate(
- &dummy_delegate_, id, gfx::Rect(), nullptr));
- }
-
- void FocusWindow(const aura::Window* window) {
- focused_window_id_ = window->id();
- }
-
- private:
- aura::test::TestWindowDelegate dummy_delegate_;
- int next_id_ = 0;
- int arc_window_id_ = 0;
- int focused_window_id_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(FakeArcWindowDelegate);
-};
-
-// Fake base::Clock to simulate wall clock time changes, which ArcMetricsService
-// uses to determine if cumulative metrics should be recorded to UMA.
-class FakeClock : public base::Clock {
- public:
- FakeClock() : now_(base::Time::Now()) {}
-
- ~FakeClock() override = default;
-
- base::Time Now() const override { return now_; }
-
- void TimeElapsed(base::TimeDelta delta) { now_ += delta; }
-
- private:
- base::Time now_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeClock);
-};
-
-// Fake base::TickClock to simulate time changes which are being recorded by
-// metrics.
-class FakeTickClock : public base::TickClock {
- public:
- FakeTickClock() = default;
- ~FakeTickClock() override = default;
-
- base::TimeTicks NowTicks() const override { return now_ticks_; }
-
- void TimeElapsed(base::TimeDelta delta) { now_ticks_ += delta; }
-
- private:
- base::TimeTicks now_ticks_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeTickClock);
-};
-
-// Helper class that initializes and shuts down dbus clients for testing.
-class DBusThreadManagerLifetimeHelper {
- public:
- DBusThreadManagerLifetimeHelper() {
- chromeos::PowerManagerClient::InitializeFake();
- chromeos::SessionManagerClient::InitializeFakeInMemory();
- }
-
- ~DBusThreadManagerLifetimeHelper() {
- chromeos::SessionManagerClient::Shutdown();
- chromeos::PowerManagerClient::Shutdown();
- }
-};
-
-// Helper class that ensures lifetime of StabilityMetricsManager for testing.
-class ScopedStabilityMetricsManager {
- public:
- ScopedStabilityMetricsManager() {
- prefs::RegisterLocalStatePrefs(local_state_.registry());
- StabilityMetricsManager::Initialize(&local_state_);
- }
-
- ~ScopedStabilityMetricsManager() { StabilityMetricsManager::Shutdown(); }
-
- private:
- TestingPrefServiceSimple local_state_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedStabilityMetricsManager);
-};
-
-// Initializes dependencies before creating ArcMetricsService instance.
-ArcMetricsService* CreateArcMetricsService(TestBrowserContext* context) {
- // Register preferences for ARC++ engagement time metrics.
- prefs::RegisterProfilePrefs(context->pref_registry());
-
- return ArcMetricsService::GetForBrowserContextForTesting(context);
-}
-
// The event names the container sends to Chrome.
constexpr std::array<const char*, 11> kBootEvents{
"boot_progress_start",
@@ -170,24 +45,33 @@ constexpr std::array<const char*, 11> kBootEvents{
class ArcMetricsServiceTest : public testing::Test {
protected:
- ArcMetricsServiceTest()
- : arc_service_manager_(std::make_unique<ArcServiceManager>()),
- context_(std::make_unique<TestBrowserContext>()),
- service_(CreateArcMetricsService(context_.get())) {
+ ArcMetricsServiceTest() {
+ prefs::RegisterLocalStatePrefs(local_state_.registry());
+ StabilityMetricsManager::Initialize(&local_state_);
+ chromeos::PowerManagerClient::InitializeFake();
+ chromeos::SessionManagerClient::InitializeFakeInMemory();
chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
- auto fake_arc_window_delegate = std::make_unique<FakeArcWindowDelegate>();
- fake_arc_window_delegate_ = fake_arc_window_delegate.get();
- service_->SetArcWindowDelegateForTesting(
- std::move(fake_arc_window_delegate));
- fake_arc_window_ = fake_arc_window_delegate_->CreateFakeArcWindow();
- fake_non_arc_window_ = fake_arc_window_delegate_->CreateFakeNonArcWindow();
+ arc_service_manager_ = std::make_unique<ArcServiceManager>();
+ context_ = std::make_unique<TestBrowserContext>();
+ prefs::RegisterProfilePrefs(context_->pref_registry());
+ service_ =
+ ArcMetricsService::GetForBrowserContextForTesting(context_.get());
- service_->SetClockForTesting(&fake_clock_);
- service_->SetTickClockForTesting(&fake_tick_clock_);
+ CreateFakeWindows();
}
- ~ArcMetricsServiceTest() override {}
+ ~ArcMetricsServiceTest() override {
+ fake_non_arc_window_.reset();
+ fake_arc_window_.reset();
+
+ context_.reset();
+ arc_service_manager_.reset();
+
+ chromeos::SessionManagerClient::Shutdown();
+ chromeos::PowerManagerClient::Shutdown();
+ StabilityMetricsManager::Shutdown();
+ }
ArcMetricsService* service() { return service_; }
@@ -210,53 +94,29 @@ class ArcMetricsServiceTest : public testing::Test {
return events;
}
- void SetSessionState(session_manager::SessionState state) {
- session_manager_.SetSessionState(state);
- }
-
- void SetScreenDimmed(bool is_screen_dimmed) {
- power_manager::ScreenIdleState screen_idle_state;
- screen_idle_state.set_dimmed(is_screen_dimmed);
- GetPowerManagerClient()->SendScreenIdleStateChanged(screen_idle_state);
- }
-
- void TriggerRecordEngagementTimeToUma() {
- // Trigger UMA record by changing to next day.
- fake_clock_.TimeElapsed(base::TimeDelta::FromDays(1));
- service_->OnSessionStateChanged();
- }
-
- FakeArcWindowDelegate* fake_arc_window_delegate() {
- return fake_arc_window_delegate_;
- }
aura::Window* fake_arc_window() { return fake_arc_window_.get(); }
aura::Window* fake_non_arc_window() { return fake_non_arc_window_.get(); }
- FakeTickClock* fake_tick_clock() { return &fake_tick_clock_; }
-
private:
- chromeos::FakePowerManagerClient* GetPowerManagerClient() {
- return static_cast<chromeos::FakePowerManagerClient*>(
- chromeos::PowerManagerClient::Get());
+ void CreateFakeWindows() {
+ fake_arc_window_.reset(aura::test::CreateTestWindowWithId(
+ /*id=*/0, nullptr));
+ fake_arc_window_->SetProperty(aura::client::kAppType,
+ static_cast<int>(ash::AppType::ARC_APP));
+ fake_non_arc_window_.reset(aura::test::CreateTestWindowWithId(
+ /*id=*/1, nullptr));
}
- content::TestBrowserThreadBundle thread_bundle_;
- std::unique_ptr<ArcServiceManager> arc_service_manager_;
-
- // DBusThreadManager, SessionManager and StabilityMetricsManager should
- // outlive TestBrowserContext which destructs ArcMetricsService in dtor.
- DBusThreadManagerLifetimeHelper dbus_thread_manager_lifetime_helper_;
+ content::BrowserTaskEnvironment task_environment_;
+ TestingPrefServiceSimple local_state_;
session_manager::SessionManager session_manager_;
- ScopedStabilityMetricsManager scoped_stability_metrics_manager_;
+
+ std::unique_ptr<ArcServiceManager> arc_service_manager_;
std::unique_ptr<TestBrowserContext> context_;
+ ArcMetricsService* service_;
std::unique_ptr<aura::Window> fake_arc_window_;
std::unique_ptr<aura::Window> fake_non_arc_window_;
- FakeArcWindowDelegate* fake_arc_window_delegate_; // Owned by |service_|
- FakeClock fake_clock_;
- FakeTickClock fake_tick_clock_;
-
- ArcMetricsService* const service_;
DISALLOW_COPY_AND_ASSIGN(ArcMetricsServiceTest);
};
@@ -398,7 +258,6 @@ TEST_F(ArcMetricsServiceTest, ReportNativeBridge) {
TEST_F(ArcMetricsServiceTest, RecordArcWindowFocusAction) {
base::HistogramTester tester;
- fake_arc_window_delegate()->FocusWindow(fake_arc_window());
service()->OnWindowActivated(
wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
@@ -413,7 +272,6 @@ TEST_F(ArcMetricsServiceTest, RecordNothingNonArcWindowFocusAction) {
base::HistogramTester tester;
// Focus an ARC window once so that the histogram is created.
- fake_arc_window_delegate()->FocusWindow(fake_arc_window());
service()->OnWindowActivated(
wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
fake_arc_window(), nullptr);
@@ -422,7 +280,6 @@ TEST_F(ArcMetricsServiceTest, RecordNothingNonArcWindowFocusAction) {
static_cast<int>(UserInteractionType::APP_CONTENT_WINDOW_INTERACTION), 1);
// Focusing a non-ARC window should not increase the bucket count.
- fake_arc_window_delegate()->FocusWindow(fake_non_arc_window());
service()->OnWindowActivated(
wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
fake_non_arc_window(), nullptr);
@@ -432,150 +289,5 @@ TEST_F(ArcMetricsServiceTest, RecordNothingNonArcWindowFocusAction) {
static_cast<int>(UserInteractionType::APP_CONTENT_WINDOW_INTERACTION), 1);
}
-TEST_F(ArcMetricsServiceTest, RecordEngagementTimeSessionLocked) {
- base::HistogramTester tester;
-
- // Make session inactive for 1 sec. Nothing should be recorded.
- SetSessionState(session_manager::SessionState::LOCKED);
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(0), 1);
-}
-
-TEST_F(ArcMetricsServiceTest, RecordEngagementTimeSessionActive) {
- base::HistogramTester tester;
-
- // Make session active for 1 sec. Should be recorded as total time.
- SetSessionState(session_manager::SessionState::ACTIVE);
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(0), 1);
-}
-
-TEST_F(ArcMetricsServiceTest, RecordEngagementTimeScreenDimmed) {
- base::HistogramTester tester;
- SetSessionState(session_manager::SessionState::ACTIVE);
-
- // Dim screen off for 1 sec. Nothing should be recorded.
- SetScreenDimmed(true);
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(0), 1);
-}
-
-TEST_F(ArcMetricsServiceTest, RecordEngagementTimeArcWindowFocused) {
- base::HistogramTester tester;
- SetSessionState(session_manager::SessionState::ACTIVE);
-
- // Focus an ARC++ window for 1 sec. Should be recorded as total time and
- // foreground time.
- fake_arc_window_delegate()->FocusWindow(fake_arc_window());
- service()->OnWindowActivated(
- wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
- fake_arc_window(), nullptr);
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(0), 1);
-}
-
-TEST_F(ArcMetricsServiceTest, RecordEngagementTimeNonArcWindowFocused) {
- base::HistogramTester tester;
- SetSessionState(session_manager::SessionState::ACTIVE);
-
- // Focus an non-ARC++ window for 1 sec. Should be recorded as total time.
- fake_arc_window_delegate()->FocusWindow(fake_non_arc_window());
- service()->OnWindowActivated(
- wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
- fake_arc_window(), nullptr);
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(0), 1);
-}
-
-TEST_F(ArcMetricsServiceTest, RecordEngagementTimeAppInBackground) {
- base::HistogramTester tester;
- SetSessionState(session_manager::SessionState::ACTIVE);
-
- // Open an ARC++ app in the background and wait for 1 sec. Should be recorded
- // as total time and background time.
- service()->OnTaskCreated(1, "", "", "");
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(0), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(1), 1);
-}
-
-TEST_F(ArcMetricsServiceTest,
- RecordEngagementTimeAppInBackgroundAndArcWindowFocused) {
- base::HistogramTester tester;
- SetSessionState(session_manager::SessionState::ACTIVE);
-
- // With an ARC++ app in the background, focus an ARC++ window for 1 sec.
- // Should be recorded as total time and foreground time.
- service()->OnTaskCreated(1, "", "", "");
- fake_arc_window_delegate()->FocusWindow(fake_arc_window());
- service()->OnWindowActivated(
- wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
- fake_arc_window(), nullptr);
- fake_tick_clock()->TimeElapsed(base::TimeDelta::FromSeconds(1));
-
- TriggerRecordEngagementTimeToUma();
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Total",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.ArcTotal",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Foreground",
- base::TimeDelta::FromSeconds(1), 1);
- tester.ExpectTimeBucketCount("Arc.EngagementTime.Background",
- base::TimeDelta::FromSeconds(0), 1);
-}
-
} // namespace
} // namespace arc
diff --git a/chromium/components/arc/midis/arc_midis_bridge.cc b/chromium/components/arc/midis/arc_midis_bridge.cc
index 69bdfd2d69c..4972701ee82 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.cc
+++ b/chromium/components/arc/midis/arc_midis_bridge.cc
@@ -47,7 +47,7 @@ ArcMidisBridge* ArcMidisBridge::GetForBrowserContext(
ArcMidisBridge::ArcMidisBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), weak_factory_(this) {
+ : arc_bridge_service_(bridge_service) {
arc_bridge_service_->midis()->SetHost(this);
}
diff --git a/chromium/components/arc/midis/arc_midis_bridge.h b/chromium/components/arc/midis/arc_midis_bridge.h
index 9874336d508..2e49a60239e 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.h
+++ b/chromium/components/arc/midis/arc_midis_bridge.h
@@ -10,7 +10,7 @@
#include <vector>
#include "base/macros.h"
-#include "components/arc/common/midis.mojom.h"
+#include "components/arc/mojom/midis.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
@@ -46,7 +46,7 @@ class ArcMidisBridge : public KeyedService,
mojom::MidisHostPtr midis_host_ptr_;
// WeakPtrFactory to use for callbacks.
- base::WeakPtrFactory<ArcMidisBridge> weak_factory_;
+ base::WeakPtrFactory<ArcMidisBridge> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcMidisBridge);
};
diff --git a/chromium/components/arc/common/ARC_SECURITY_OWNERS b/chromium/components/arc/mojom/ARC_SECURITY_OWNERS
index 84c8d11c9e8..84c8d11c9e8 100644
--- a/chromium/components/arc/common/ARC_SECURITY_OWNERS
+++ b/chromium/components/arc/mojom/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/common/BUILD.gn b/chromium/components/arc/mojom/BUILD.gn
index c8064bb814c..9b89c58a421 100644
--- a/chromium/components/arc/common/BUILD.gn
+++ b/chromium/components/arc/mojom/BUILD.gn
@@ -9,7 +9,7 @@ import("//mojo/public/tools/bindings/mojom.gni")
# inclusion is done through read_file(), which does not respect the global
# defines for GN, so it itself cannot use the "is_chromeos" variable.
if (is_chromeos) {
- mojom("common") {
+ mojom("mojom") {
sources = [
"accessibility_helper.mojom",
"app.mojom",
@@ -47,6 +47,7 @@ if (is_chromeos) {
"policy.mojom",
"power.mojom",
"print.mojom",
+ "print_common.mojom",
"print_spooler.mojom",
"process.mojom",
"property.mojom",
@@ -68,13 +69,13 @@ if (is_chromeos) {
public_deps = [
":media",
":notifications",
- "//media/capture/video/chromeos/mojo:cros_camera",
+ "//media/capture/video/chromeos/mojom:cros_camera",
"//mojo/public/mojom/base",
"//services/device/public/mojom:usb",
"//services/media_session/public/mojom",
"//services/resource_coordinator/public/mojom",
"//ui/accessibility/mojom",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
"//url/mojom:url_mojom_gurl",
]
}
@@ -91,7 +92,7 @@ if (is_chromeos) {
}
# Media related mojo interfaces. These are used by
- # //services/viz/public/interfaces. We have this separate mojom target to
+ # //services/viz/public/mojom. We have this separate mojom target to
# avoid pulling in unnecessary interfaces.
mojom("media") {
sources = [
@@ -105,17 +106,17 @@ if (is_chromeos) {
]
public_deps = [
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
]
}
- source_set("struct_traits") {
+ source_set("mojom_traits") {
sources = [
- "ime_struct_traits.h",
+ "ime_mojom_traits.h",
]
deps = [
- ":common",
+ ":mojom",
"//ui/base/ime:text_input_types",
]
}
@@ -123,11 +124,11 @@ if (is_chromeos) {
source_set("unit_tests") {
testonly = true
sources = [
- "video_accelerator_struct_traits_unittest.cc",
+ "video_accelerator_mojom_traits_unittest.cc",
]
deps = [
- ":common",
+ ":mojom",
"//media",
"//mojo/public/cpp/test_support:test_utils",
"//testing/gtest",
diff --git a/chromium/components/arc/common/OWNERS b/chromium/components/arc/mojom/OWNERS
index 539b2efbb79..33e669b224a 100644
--- a/chromium/components/arc/common/OWNERS
+++ b/chromium/components/arc/mojom/OWNERS
@@ -6,6 +6,6 @@ per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
per-file *.typemap=file:ARC_SECURITY_OWNERS
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file:ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file:ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/common/accessibility_helper.mojom b/chromium/components/arc/mojom/accessibility_helper.mojom
index 9aecc7657dc..f03ae13bda2 100644
--- a/chromium/components/arc/common/accessibility_helper.mojom
+++ b/chromium/components/arc/mojom/accessibility_helper.mojom
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 16
+// Next MinVersion: 17
module arc.mojom;
-import "components/arc/common/gfx.mojom";
+import "components/arc/mojom/gfx.mojom";
// For future maintainers, each of the below enums were hand picked
// from their equivalents in the Android source. Keep them in the
@@ -376,6 +376,36 @@ struct AccessibilityActionData {
[MinVersion=13] int32 end_index;
};
+// The type of shadow used for Chrome captions.
+// https://developer.android.com/reference/android/view/accessibility/CaptioningManager.CaptionStyle
+[Extensible]
+enum CaptionTextShadowType {
+ // Edge type value specifying no character edges.
+ NONE = 0,
+
+ // Edge type value specifying uniformly outlined character edges.
+ UNIFORM = 1,
+
+ // Edge type value specifying drop-shadowed character edges.
+ DROP_SHADOW = 2,
+
+ // Edge type value specifying raised bevel character edges.
+ RAISED = 3,
+
+ // Edge type value specifying depressed bevel character edges.
+ DEPRESSED = 4,
+};
+
+// Encapsulates settings to stylize captions.
+// https://developer.android.com/reference/android/view/accessibility/CaptioningManager.CaptionStyle.html
+struct CaptionStyle {
+ string user_locale;
+ string text_size;
+ string text_color;
+ string background_color;
+ CaptionTextShadowType text_shadow_type;
+};
+
// Interface for Android communicating to Chrome.
// Deprecated method IDs: 0
// Next method ID: 3
@@ -392,7 +422,7 @@ interface AccessibilityHelperHost {
// Interface for communicating to Android.
// Deprecated method IDs: 0, 1, 3, 5
-// Next method ID: 10
+// Next method ID: 11
interface AccessibilityHelperInstance {
// Establishes full-duplex communication with the host.
[MinVersion=9] Init@7(AccessibilityHelperHost host) => ();
@@ -416,4 +446,7 @@ interface AccessibilityHelperInstance {
// Returns Rect specifying location, or null if textLocation is not available.
[MinVersion=13] RefreshWithExtraData@9(AccessibilityActionData refresh_data)
=> (Rect? text_location);
+
+ // Requests the service to set the caption style.
+ [MinVersion=16] SetCaptionStyle@10(CaptionStyle style);
};
diff --git a/chromium/components/arc/common/app.mojom b/chromium/components/arc/mojom/app.mojom
index 8513efbc592..ba6af7956bd 100644
--- a/chromium/components/arc/common/app.mojom
+++ b/chromium/components/arc/mojom/app.mojom
@@ -6,9 +6,9 @@
module arc.mojom;
-import "components/arc/common/app_permissions.mojom";
-import "components/arc/common/gfx.mojom";
-import "components/arc/common/scale_factor.mojom";
+import "components/arc/mojom/app_permissions.mojom";
+import "components/arc/mojom/gfx.mojom";
+import "components/arc/mojom/scale_factor.mojom";
import "ui/accessibility/mojom/ax_assistant_structure.mojom";
// Describes installation result.
diff --git a/chromium/components/arc/mojom/app.typemap b/chromium/components/arc/mojom/app.typemap
new file mode 100644
index 00000000000..c3e3ed9bde3
--- /dev/null
+++ b/chromium/components/arc/mojom/app.typemap
@@ -0,0 +1,6 @@
+mojom = "//components/arc/mojom/app.mojom"
+public_headers = [ "//components/arc/app/arc_playstore_search_request_state.h" ]
+traits_headers = [ "//components/arc/mojom/app_mojom_traits.h" ]
+type_mappings = [
+ "arc.mojom.AppDiscoveryRequestState=::arc::ArcPlayStoreSearchRequestState",
+]
diff --git a/chromium/components/arc/common/app_struct_traits.h b/chromium/components/arc/mojom/app_mojom_traits.h
index 43e587de8fe..cfa23d089f5 100644
--- a/chromium/components/arc/common/app_struct_traits.h
+++ b/chromium/components/arc/mojom/app_mojom_traits.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_COMMON_APP_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_COMMON_APP_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_MOJOM_APP_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_MOJOM_APP_MOJOM_TRAITS_H_
#include "components/arc/app/arc_playstore_search_request_state.h"
-#include "components/arc/common/app.mojom-shared.h"
+#include "components/arc/mojom/app.mojom-shared.h"
namespace mojo {
@@ -122,4 +122,4 @@ struct EnumTraits<arc::mojom::AppDiscoveryRequestState,
} // namespace mojo
-#endif // COMPONENTS_ARC_COMMON_APP_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_MOJOM_APP_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/common/app_permissions.mojom b/chromium/components/arc/mojom/app_permissions.mojom
index 0454b7411a1..0454b7411a1 100644
--- a/chromium/components/arc/common/app_permissions.mojom
+++ b/chromium/components/arc/mojom/app_permissions.mojom
diff --git a/chromium/components/arc/common/appfuse.mojom b/chromium/components/arc/mojom/appfuse.mojom
index ee81f3c788b..ee81f3c788b 100644
--- a/chromium/components/arc/common/appfuse.mojom
+++ b/chromium/components/arc/mojom/appfuse.mojom
diff --git a/chromium/components/arc/common/arc_bridge.mojom b/chromium/components/arc/mojom/arc_bridge.mojom
index 491cdc2da05..c0a6a2d068a 100644
--- a/chromium/components/arc/common/arc_bridge.mojom
+++ b/chromium/components/arc/mojom/arc_bridge.mojom
@@ -4,56 +4,56 @@
module arc.mojom;
-import "components/arc/common/accessibility_helper.mojom";
-import "components/arc/common/app.mojom";
-import "components/arc/common/app_permissions.mojom";
-import "components/arc/common/appfuse.mojom";
-import "components/arc/common/audio.mojom";
-import "components/arc/common/auth.mojom";
-import "components/arc/common/backup_settings.mojom";
-import "components/arc/common/bluetooth.mojom";
-import "components/arc/common/boot_phase_monitor.mojom";
-import "components/arc/common/camera.mojom";
-import "components/arc/common/cast_receiver.mojom";
-import "components/arc/common/cert_store.mojom";
-import "components/arc/common/clipboard.mojom";
-import "components/arc/common/crash_collector.mojom";
-import "components/arc/common/disk_quota.mojom";
-import "components/arc/common/enterprise_reporting.mojom";
-import "components/arc/common/file_system.mojom";
-import "components/arc/common/ime.mojom";
-import "components/arc/common/input_method_manager.mojom";
-import "components/arc/common/intent_helper.mojom";
-import "components/arc/common/keymaster.mojom";
-import "components/arc/common/kiosk.mojom";
-import "components/arc/common/lock_screen.mojom";
-import "components/arc/common/media_session.mojom";
-import "components/arc/common/metrics.mojom";
-import "components/arc/common/midis.mojom";
-import "components/arc/common/net.mojom";
-import "components/arc/common/notifications.mojom";
-import "components/arc/common/obb_mounter.mojom";
-import "components/arc/common/oemcrypto.mojom";
-import "components/arc/common/pip.mojom";
-import "components/arc/common/policy.mojom";
-import "components/arc/common/power.mojom";
-import "components/arc/common/print.mojom";
-import "components/arc/common/print_spooler.mojom";
-import "components/arc/common/process.mojom";
-import "components/arc/common/property.mojom";
-import "components/arc/common/rotation_lock.mojom";
-import "components/arc/common/screen_capture.mojom";
-import "components/arc/common/storage_manager.mojom";
-import "components/arc/common/timer.mojom";
-import "components/arc/common/tracing.mojom";
-import "components/arc/common/tts.mojom";
-import "components/arc/common/usb_host.mojom";
-import "components/arc/common/video.mojom";
-import "components/arc/common/voice_interaction_arc_home.mojom";
-import "components/arc/common/voice_interaction_framework.mojom";
-import "components/arc/common/volume_mounter.mojom";
-import "components/arc/common/wake_lock.mojom";
-import "components/arc/common/wallpaper.mojom";
+import "components/arc/mojom/accessibility_helper.mojom";
+import "components/arc/mojom/app.mojom";
+import "components/arc/mojom/app_permissions.mojom";
+import "components/arc/mojom/appfuse.mojom";
+import "components/arc/mojom/audio.mojom";
+import "components/arc/mojom/auth.mojom";
+import "components/arc/mojom/backup_settings.mojom";
+import "components/arc/mojom/bluetooth.mojom";
+import "components/arc/mojom/boot_phase_monitor.mojom";
+import "components/arc/mojom/camera.mojom";
+import "components/arc/mojom/cast_receiver.mojom";
+import "components/arc/mojom/cert_store.mojom";
+import "components/arc/mojom/clipboard.mojom";
+import "components/arc/mojom/crash_collector.mojom";
+import "components/arc/mojom/disk_quota.mojom";
+import "components/arc/mojom/enterprise_reporting.mojom";
+import "components/arc/mojom/file_system.mojom";
+import "components/arc/mojom/ime.mojom";
+import "components/arc/mojom/input_method_manager.mojom";
+import "components/arc/mojom/intent_helper.mojom";
+import "components/arc/mojom/keymaster.mojom";
+import "components/arc/mojom/kiosk.mojom";
+import "components/arc/mojom/lock_screen.mojom";
+import "components/arc/mojom/media_session.mojom";
+import "components/arc/mojom/metrics.mojom";
+import "components/arc/mojom/midis.mojom";
+import "components/arc/mojom/net.mojom";
+import "components/arc/mojom/notifications.mojom";
+import "components/arc/mojom/obb_mounter.mojom";
+import "components/arc/mojom/oemcrypto.mojom";
+import "components/arc/mojom/pip.mojom";
+import "components/arc/mojom/policy.mojom";
+import "components/arc/mojom/power.mojom";
+import "components/arc/mojom/print.mojom";
+import "components/arc/mojom/print_spooler.mojom";
+import "components/arc/mojom/process.mojom";
+import "components/arc/mojom/property.mojom";
+import "components/arc/mojom/rotation_lock.mojom";
+import "components/arc/mojom/screen_capture.mojom";
+import "components/arc/mojom/storage_manager.mojom";
+import "components/arc/mojom/timer.mojom";
+import "components/arc/mojom/tracing.mojom";
+import "components/arc/mojom/tts.mojom";
+import "components/arc/mojom/usb_host.mojom";
+import "components/arc/mojom/video.mojom";
+import "components/arc/mojom/voice_interaction_arc_home.mojom";
+import "components/arc/mojom/voice_interaction_framework.mojom";
+import "components/arc/mojom/volume_mounter.mojom";
+import "components/arc/mojom/wake_lock.mojom";
+import "components/arc/mojom/wallpaper.mojom";
// Next MinVersion: 48
// Deprecated method IDs: 101, 105
diff --git a/chromium/components/arc/common/arc_gfx_struct_traits.cc b/chromium/components/arc/mojom/arc_gfx_mojom_traits.cc
index 20858df1123..c56397edbee 100644
--- a/chromium/components/arc/common/arc_gfx_struct_traits.cc
+++ b/chromium/components/arc/mojom/arc_gfx_mojom_traits.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 "components/arc/common/arc_gfx_struct_traits.h"
+#include "components/arc/mojom/arc_gfx_mojom_traits.h"
namespace mojo {
diff --git a/chromium/components/arc/common/arc_gfx_struct_traits.h b/chromium/components/arc/mojom/arc_gfx_mojom_traits.h
index 02c4edf9023..82d420911f2 100644
--- a/chromium/components/arc/common/arc_gfx_struct_traits.h
+++ b/chromium/components/arc/mojom/arc_gfx_mojom_traits.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_COMMON_ARC_GFX_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_COMMON_ARC_GFX_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_MOJOM_ARC_GFX_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_MOJOM_ARC_GFX_MOJOM_TRAITS_H_
-#include "components/arc/common/gfx.mojom.h"
+#include "components/arc/mojom/gfx.mojom.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/range/range.h"
@@ -31,4 +31,4 @@ struct StructTraits<arc::mojom::RangeDataView, gfx::Range> {
} // namespace mojo
-#endif // COMPONENTS_ARC_COMMON_ARC_GFX_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_MOJOM_ARC_GFX_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/common/audio.mojom b/chromium/components/arc/mojom/audio.mojom
index eceb20e4cdf..eceb20e4cdf 100644
--- a/chromium/components/arc/common/audio.mojom
+++ b/chromium/components/arc/mojom/audio.mojom
diff --git a/chromium/components/arc/common/auth.mojom b/chromium/components/arc/mojom/auth.mojom
index f723c1e85ba..837231cc354 100644
--- a/chromium/components/arc/common/auth.mojom
+++ b/chromium/components/arc/mojom/auth.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 21
+// Next MinVersion: 23
module arc.mojom;
@@ -102,6 +102,45 @@ enum AccountCheckStatus {
// corresponding UMA callsite in Chrome arc::UpdateAuthAccountCheckStatus.
};
+[Extensible]
+enum MainAccountResolutionStatus {
+ // No hash code was set for the main account. System contains no account of
+ // required type.
+ [MinVersion=22] NO_HASH_CODE_NO_ACCOUNT = 0,
+
+ // No hash code was set for the main account. System contains only single
+ // account of required type.
+ [MinVersion=22] NO_HASH_CODE_SINGLE_ACCOUNT = 1,
+
+ // No hash code was set for the main account. System contains multiple
+ // accounts of required type.
+ [MinVersion=22] NO_HASH_CODE_MULTIPLE_ACCOUNTS = 2,
+
+ // Hash code was set but no account currently available.
+ [MinVersion=22] HASH_CODE_NO_ACCOUNT = 3,
+
+ // Hash code was set but it does not match single account of required type.
+ [MinVersion=22] HASH_CODE_DO_NOT_MATCH_SINGLE_ACCOUNT = 4,
+
+ // Hash code was set but it does not match multiple accounts of required
+ // type.
+ [MinVersion=22] HASH_CODE_DO_NOT_MATCH_MULTIPLE_ACCOUNTS = 5,
+
+ // Hash code was set and it matches single account of required type.
+ [MinVersion=22] HASH_CODE_MATCH_SINGLE_ACCOUNT = 6,
+
+ // Hash code was set and it matches one of multiple accounts of required
+ // type.
+ [MinVersion=22] HASH_CODE_MATCH_MULTIPLE_ACCOUNTS = 7,
+
+ // Hash code collides with multiple accounts of required type.
+ [MinVersion=22] HASH_CODE_COLLIDE_FOR_MULTIPLE_ACCOUNTS = 8,
+
+ // NOTE: If you add any entries to this enum, you must also update the
+ // corresponding UMA ArcAuthMainAccountResolutionStatus at
+ // tools/metrics/histograms/enums.xml.
+};
+
// These values describe the result of ARC attempting to change supervision
// state after an account type change.
[Extensible]
@@ -296,7 +335,7 @@ interface AuthHost {
[MinVersion=20] HandleUpdateCredentialsRequest@17(string account_name);
};
-// Next Method ID: 5
+// Next Method ID: 6
interface AuthInstance {
// DEPRECATED: Please use Init@2 instead.
InitDeprecated@0(AuthHost host_ptr);
@@ -325,4 +364,8 @@ interface AuthInstance {
// Gets the list of Google accounts in ARC. Called during the one-time
// migration of accounts from ARC to Chrome OS Account Manager.
[MinVersion=19] GetGoogleAccounts@4() => (array<ArcAccountInfo> accounts);
+
+ // Gets resolution status of main account for statistics reporting.
+ [MinVersion=22] GetMainAccountResolutionStatus@5()
+ => (MainAccountResolutionStatus status);
};
diff --git a/chromium/components/arc/common/backup_settings.mojom b/chromium/components/arc/mojom/backup_settings.mojom
index 4ebb2ce2e09..4ebb2ce2e09 100644
--- a/chromium/components/arc/common/backup_settings.mojom
+++ b/chromium/components/arc/mojom/backup_settings.mojom
diff --git a/chromium/components/arc/common/bitmap.mojom b/chromium/components/arc/mojom/bitmap.mojom
index 02d96647b6c..02d96647b6c 100644
--- a/chromium/components/arc/common/bitmap.mojom
+++ b/chromium/components/arc/mojom/bitmap.mojom
diff --git a/chromium/components/arc/mojom/bitmap.typemap b/chromium/components/arc/mojom/bitmap.typemap
new file mode 100644
index 00000000000..31574898894
--- /dev/null
+++ b/chromium/components/arc/mojom/bitmap.typemap
@@ -0,0 +1,13 @@
+mojom = "//components/arc/mojom/bitmap.mojom"
+public_headers = [ "//third_party/skia/include/core/SkBitmap.h" ]
+traits_headers = [ "//components/arc/bitmap/bitmap_mojom_traits.h" ]
+sources = [
+ "//components/arc/bitmap/bitmap_mojom_traits.cc",
+]
+deps = [
+ "//skia",
+]
+public_deps = [
+ "//skia",
+]
+type_mappings = [ "arc.mojom.ArcBitmap=::SkBitmap" ]
diff --git a/chromium/components/arc/common/bluetooth.mojom b/chromium/components/arc/mojom/bluetooth.mojom
index 67720f4e604..67720f4e604 100644
--- a/chromium/components/arc/common/bluetooth.mojom
+++ b/chromium/components/arc/mojom/bluetooth.mojom
diff --git a/chromium/components/arc/mojom/bluetooth.typemap b/chromium/components/arc/mojom/bluetooth.typemap
new file mode 100644
index 00000000000..47715225355
--- /dev/null
+++ b/chromium/components/arc/mojom/bluetooth.typemap
@@ -0,0 +1,21 @@
+mojom = "//components/arc/mojom/bluetooth.mojom"
+public_headers = [
+ "//device/bluetooth/bluetooth_advertisement.h",
+ "//device/bluetooth/bluetooth_common.h",
+ "//device/bluetooth/public/cpp/bluetooth_uuid.h",
+ "//device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h",
+]
+traits_headers = [ "//components/arc/bluetooth/bluetooth_mojom_traits.h" ]
+sources = [
+ "//components/arc/bluetooth/bluetooth_mojom_traits.cc",
+]
+deps = [
+ "//device/bluetooth",
+ "//device/bluetooth/public/cpp",
+]
+type_mappings = [
+ "arc.mojom.BluetoothDeviceType=::device::BluetoothTransport",
+ "arc.mojom.BluetoothSdpAttributeType=::bluez::BluetoothServiceAttributeValueBlueZ::Type",
+ "arc.mojom.BluetoothUUID=::device::BluetoothUUID",
+ "arc.mojom.BluetoothAdvertisement=::std::unique_ptr<::device::BluetoothAdvertisement::Data>[move_only]",
+]
diff --git a/chromium/components/arc/common/boot_phase_monitor.mojom b/chromium/components/arc/mojom/boot_phase_monitor.mojom
index 045270f3e1f..045270f3e1f 100644
--- a/chromium/components/arc/common/boot_phase_monitor.mojom
+++ b/chromium/components/arc/mojom/boot_phase_monitor.mojom
diff --git a/chromium/components/arc/common/camera.mojom b/chromium/components/arc/mojom/camera.mojom
index 424bf5b659d..04106e6cec1 100644
--- a/chromium/components/arc/common/camera.mojom
+++ b/chromium/components/arc/mojom/camera.mojom
@@ -6,7 +6,7 @@
module arc.mojom;
-import "media/capture/video/chromeos/mojo/cros_camera_service.mojom";
+import "media/capture/video/chromeos/mojom/cros_camera_service.mojom";
struct CameraDeviceInfo {
string device_path@0;
diff --git a/chromium/components/arc/common/cast_receiver.mojom b/chromium/components/arc/mojom/cast_receiver.mojom
index 3801a1fcb2a..3801a1fcb2a 100644
--- a/chromium/components/arc/common/cast_receiver.mojom
+++ b/chromium/components/arc/mojom/cast_receiver.mojom
diff --git a/chromium/components/arc/common/cert_store.mojom b/chromium/components/arc/mojom/cert_store.mojom
index eabf6b13731..eabf6b13731 100644
--- a/chromium/components/arc/common/cert_store.mojom
+++ b/chromium/components/arc/mojom/cert_store.mojom
diff --git a/chromium/components/arc/common/clipboard.mojom b/chromium/components/arc/mojom/clipboard.mojom
index 11ea94683c4..11ea94683c4 100644
--- a/chromium/components/arc/common/clipboard.mojom
+++ b/chromium/components/arc/mojom/clipboard.mojom
diff --git a/chromium/components/arc/common/crash_collector.mojom b/chromium/components/arc/mojom/crash_collector.mojom
index fb827b89f3f..fb827b89f3f 100644
--- a/chromium/components/arc/common/crash_collector.mojom
+++ b/chromium/components/arc/mojom/crash_collector.mojom
diff --git a/chromium/components/arc/common/disk_quota.mojom b/chromium/components/arc/mojom/disk_quota.mojom
index 006537a6c95..006537a6c95 100644
--- a/chromium/components/arc/common/disk_quota.mojom
+++ b/chromium/components/arc/mojom/disk_quota.mojom
diff --git a/chromium/components/arc/common/enterprise_reporting.mojom b/chromium/components/arc/mojom/enterprise_reporting.mojom
index 3130ee9fc54..3130ee9fc54 100644
--- a/chromium/components/arc/common/enterprise_reporting.mojom
+++ b/chromium/components/arc/mojom/enterprise_reporting.mojom
diff --git a/chromium/components/arc/common/file_system.mojom b/chromium/components/arc/mojom/file_system.mojom
index 8b237704b72..16f0b9a12cf 100644
--- a/chromium/components/arc/common/file_system.mojom
+++ b/chromium/components/arc/mojom/file_system.mojom
@@ -6,8 +6,8 @@
module arc.mojom;
-import "components/arc/common/bitmap.mojom";
-import "components/arc/common/intent_common.mojom";
+import "components/arc/mojom/bitmap.mojom";
+import "components/arc/mojom/intent_common.mojom";
import "url/mojom/url.mojom";
// Represents a document in Android DocumentsProvider.
diff --git a/chromium/components/arc/common/file_system.typemap b/chromium/components/arc/mojom/file_system.typemap
index e21e8490f6a..8ea6051a9cf 100644
--- a/chromium/components/arc/common/file_system.typemap
+++ b/chromium/components/arc/mojom/file_system.typemap
@@ -2,13 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom = "//components/arc/common/file_system.mojom"
+mojom = "//components/arc/mojom/file_system.mojom"
public_headers = [ "//storage/browser/fileapi/watcher_manager.h" ]
public_deps = [
"//storage/browser",
]
-traits_headers = [ "//components/arc/file_system/file_system_struct_traits.h" ]
+traits_headers = [ "//components/arc/file_system/file_system_mojom_traits.h" ]
sources = [
- "//components/arc/file_system/file_system_struct_traits.cc",
+ "//components/arc/file_system/file_system_mojom_traits.cc",
]
-type_mappings = [ "arc.mojom.ChangeType=storage::WatcherManager::ChangeType" ]
+type_mappings = [ "arc.mojom.ChangeType=::storage::WatcherManager::ChangeType" ]
diff --git a/chromium/components/arc/common/gfx.mojom b/chromium/components/arc/mojom/gfx.mojom
index aaf58a27b7e..aaf58a27b7e 100644
--- a/chromium/components/arc/common/gfx.mojom
+++ b/chromium/components/arc/mojom/gfx.mojom
diff --git a/chromium/components/arc/common/gfx.typemap b/chromium/components/arc/mojom/gfx.typemap
index be462bc0ab5..48ba64aabfe 100644
--- a/chromium/components/arc/common/gfx.typemap
+++ b/chromium/components/arc/mojom/gfx.typemap
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom = "//components/arc/common/gfx.mojom"
+mojom = "//components/arc/mojom/gfx.mojom"
public_headers = [
"//ui/gfx/geometry/rect.h",
@@ -13,10 +13,10 @@ deps = [
"//ui/gfx",
]
-traits_headers = [ "//components/arc/common/arc_gfx_struct_traits.h" ]
+traits_headers = [ "//components/arc/mojom/arc_gfx_mojom_traits.h" ]
sources = [
- "//components/arc/common/arc_gfx_struct_traits.cc",
+ "//components/arc/mojom/arc_gfx_mojom_traits.cc",
]
type_mappings = [
diff --git a/chromium/components/arc/common/ime.mojom b/chromium/components/arc/mojom/ime.mojom
index 3e103302e6c..14b38312b8e 100644
--- a/chromium/components/arc/common/ime.mojom
+++ b/chromium/components/arc/mojom/ime.mojom
@@ -6,7 +6,7 @@
module arc.mojom;
-import "components/arc/common/gfx.mojom";
+import "components/arc/mojom/gfx.mojom";
// Represents the type of text input field currently focused.
[Extensible]
diff --git a/chromium/components/arc/mojom/ime.typemap b/chromium/components/arc/mojom/ime.typemap
new file mode 100644
index 00000000000..d82e98af726
--- /dev/null
+++ b/chromium/components/arc/mojom/ime.typemap
@@ -0,0 +1,4 @@
+mojom = "//components/arc/mojom/ime.mojom"
+public_headers = [ "//ui/base/ime/text_input_type.h" ]
+traits_headers = [ "//components/arc/mojom/ime_mojom_traits.h" ]
+type_mappings = [ "arc.mojom.TextInputType=::ui::TextInputType" ]
diff --git a/chromium/components/arc/common/ime_struct_traits.h b/chromium/components/arc/mojom/ime_mojom_traits.h
index c366cff17ef..c79568373b8 100644
--- a/chromium/components/arc/common/ime_struct_traits.h
+++ b/chromium/components/arc/mojom/ime_mojom_traits.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_COMMON_IME_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_COMMON_IME_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_MOJOM_IME_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_MOJOM_IME_MOJOM_TRAITS_H_
-#include "components/arc/common/ime.mojom-shared.h"
+#include "components/arc/mojom/ime.mojom-shared.h"
#include "ui/base/ime/text_input_type.h"
namespace mojo {
@@ -107,4 +107,4 @@ struct EnumTraits<arc::mojom::TextInputType, ui::TextInputType> {
} // namespace mojo
-#endif // COMPONENTS_ARC_COMMON_IME_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_MOJOM_IME_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/common/input_method_manager.mojom b/chromium/components/arc/mojom/input_method_manager.mojom
index c5c0b930d2b..c8e3dcde029 100644
--- a/chromium/components/arc/common/input_method_manager.mojom
+++ b/chromium/components/arc/mojom/input_method_manager.mojom
@@ -7,8 +7,8 @@
module arc.mojom;
import "mojo/public/mojom/base/string16.mojom";
-import "components/arc/common/gfx.mojom";
-import "components/arc/common/ime.mojom";
+import "components/arc/mojom/gfx.mojom";
+import "components/arc/mojom/ime.mojom";
// Represents the information of an Android IME.
struct ImeInfo {
diff --git a/chromium/components/arc/common/intent_common.mojom b/chromium/components/arc/mojom/intent_common.mojom
index d18b11e08a0..d18b11e08a0 100644
--- a/chromium/components/arc/common/intent_common.mojom
+++ b/chromium/components/arc/mojom/intent_common.mojom
diff --git a/chromium/components/arc/common/intent_helper.mojom b/chromium/components/arc/mojom/intent_helper.mojom
index ab63854fe9f..acf15f732b6 100644
--- a/chromium/components/arc/common/intent_helper.mojom
+++ b/chromium/components/arc/mojom/intent_helper.mojom
@@ -6,9 +6,9 @@
module arc.mojom;
-import "components/arc/common/bitmap.mojom";
-import "components/arc/common/intent_common.mojom";
-import "components/arc/common/scale_factor.mojom";
+import "components/arc/mojom/bitmap.mojom";
+import "components/arc/mojom/intent_common.mojom";
+import "components/arc/mojom/scale_factor.mojom";
[Extensible]
enum PatternType {
diff --git a/chromium/components/arc/common/intent_helper.typemap b/chromium/components/arc/mojom/intent_helper.typemap
index 5b1a17ceb56..3a774f359d8 100644
--- a/chromium/components/arc/common/intent_helper.typemap
+++ b/chromium/components/arc/mojom/intent_helper.typemap
@@ -2,12 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom = "//components/arc/common/intent_helper.mojom"
+mojom = "//components/arc/mojom/intent_helper.mojom"
public_headers = [ "//components/arc/intent_helper/intent_filter.h" ]
traits_headers =
- [ "//components/arc/intent_helper/intent_filter_struct_traits.h" ]
+ [ "//components/arc/intent_helper/intent_filter_mojom_traits.h" ]
sources = [
- "//components/arc/intent_helper/intent_filter_struct_traits.cc",
+ "//components/arc/intent_helper/intent_filter_mojom_traits.cc",
]
type_mappings = [
"arc.mojom.IntentFilter=::arc::IntentFilter[move_only]",
diff --git a/chromium/components/arc/common/keymaster.mojom b/chromium/components/arc/mojom/keymaster.mojom
index 24475b72636..24475b72636 100644
--- a/chromium/components/arc/common/keymaster.mojom
+++ b/chromium/components/arc/mojom/keymaster.mojom
diff --git a/chromium/components/arc/common/kiosk.mojom b/chromium/components/arc/mojom/kiosk.mojom
index 39beb508f79..39beb508f79 100644
--- a/chromium/components/arc/common/kiosk.mojom
+++ b/chromium/components/arc/mojom/kiosk.mojom
diff --git a/chromium/components/arc/common/lock_screen.mojom b/chromium/components/arc/mojom/lock_screen.mojom
index a19bc32dbbd..a19bc32dbbd 100644
--- a/chromium/components/arc/common/lock_screen.mojom
+++ b/chromium/components/arc/mojom/lock_screen.mojom
diff --git a/chromium/components/arc/common/media_session.mojom b/chromium/components/arc/mojom/media_session.mojom
index f8e2c936c5f..f8e2c936c5f 100644
--- a/chromium/components/arc/common/media_session.mojom
+++ b/chromium/components/arc/mojom/media_session.mojom
diff --git a/chromium/components/arc/common/metrics.mojom b/chromium/components/arc/mojom/metrics.mojom
index 8a603cde00c..8a603cde00c 100644
--- a/chromium/components/arc/common/metrics.mojom
+++ b/chromium/components/arc/mojom/metrics.mojom
diff --git a/chromium/components/arc/common/midis.mojom b/chromium/components/arc/mojom/midis.mojom
index 4a8e1735e20..4a8e1735e20 100644
--- a/chromium/components/arc/common/midis.mojom
+++ b/chromium/components/arc/mojom/midis.mojom
diff --git a/chromium/components/arc/common/net.mojom b/chromium/components/arc/mojom/net.mojom
index 731445ab940..731445ab940 100644
--- a/chromium/components/arc/common/net.mojom
+++ b/chromium/components/arc/mojom/net.mojom
diff --git a/chromium/components/arc/common/notifications.mojom b/chromium/components/arc/mojom/notifications.mojom
index 85f6ee81564..a208c0b47a1 100644
--- a/chromium/components/arc/common/notifications.mojom
+++ b/chromium/components/arc/mojom/notifications.mojom
@@ -6,8 +6,8 @@
module arc.mojom;
-import "components/arc/common/bitmap.mojom";
-import "components/arc/common/gfx.mojom";
+import "components/arc/mojom/bitmap.mojom";
+import "components/arc/mojom/gfx.mojom";
// These values must be matched with the NOTIFICATION_EVENT_* constants in
// com.android.server.ArcNotificationListenerService.
diff --git a/chromium/components/arc/common/obb_mounter.mojom b/chromium/components/arc/mojom/obb_mounter.mojom
index d3659753320..d3659753320 100644
--- a/chromium/components/arc/common/obb_mounter.mojom
+++ b/chromium/components/arc/mojom/obb_mounter.mojom
diff --git a/chromium/components/arc/common/oemcrypto.mojom b/chromium/components/arc/mojom/oemcrypto.mojom
index 21db429814d..2c4b74737da 100644
--- a/chromium/components/arc/common/oemcrypto.mojom
+++ b/chromium/components/arc/mojom/oemcrypto.mojom
@@ -5,7 +5,7 @@
// Next MinVersion: 3
// The original version of this file lives in the Chromium repository at:
-// src/components/arc/common/oemcrypto.mojom
+// src/components/arc/mojom/oemcrypto.mojom
// This file defines the mojo interface between Android, Chrome and the
// Chrome OS daemon for the Widevine L1 OEMCrypto implementation used in ARC++.
diff --git a/chromium/components/arc/common/oemcrypto_daemon.mojom b/chromium/components/arc/mojom/oemcrypto_daemon.mojom
index 887c175228e..a7128c91449 100644
--- a/chromium/components/arc/common/oemcrypto_daemon.mojom
+++ b/chromium/components/arc/mojom/oemcrypto_daemon.mojom
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// The original version of this file lives in the Chromium repository at:
-// src/components/arc/common/oemcrypto_daemon.mojom
+// src/components/arc/mojom/oemcrypto_daemon.mojom
// This file defines the mojo interface used between Chrome and the Chrome OS
// daemon for establishing the connection from Android to the Chrome OS
@@ -13,8 +13,8 @@
module arc_oemcrypto.mojom;
-import "components/arc/common/oemcrypto.mojom";
-import "components/arc/common/protected_buffer_manager.mojom";
+import "components/arc/mojom/oemcrypto.mojom";
+import "components/arc/mojom/protected_buffer_manager.mojom";
// OemCryptoHostDaemon is implemented by the OemCrypto daemon running in
// Chrome OS and has Connect called from the Browser process in Chrome.
diff --git a/chromium/components/arc/common/pip.mojom b/chromium/components/arc/mojom/pip.mojom
index ce620e0f570..ce620e0f570 100644
--- a/chromium/components/arc/common/pip.mojom
+++ b/chromium/components/arc/mojom/pip.mojom
diff --git a/chromium/components/arc/common/policy.mojom b/chromium/components/arc/mojom/policy.mojom
index 71489020452..71489020452 100644
--- a/chromium/components/arc/common/policy.mojom
+++ b/chromium/components/arc/mojom/policy.mojom
diff --git a/chromium/components/arc/common/power.mojom b/chromium/components/arc/mojom/power.mojom
index b3304bf856c..b3304bf856c 100644
--- a/chromium/components/arc/common/power.mojom
+++ b/chromium/components/arc/mojom/power.mojom
diff --git a/chromium/components/arc/common/print.mojom b/chromium/components/arc/mojom/print.mojom
index f74d468ca4c..c7eb2e736a7 100644
--- a/chromium/components/arc/common/print.mojom
+++ b/chromium/components/arc/mojom/print.mojom
@@ -6,123 +6,7 @@
module arc.mojom;
-// android.print.PageRange
-struct PrintPageRange {
- // First page inclusive.
- int32 start;
- // Last page inclusive.
- int32 end;
-};
-
-// android.print.PrintAttributes.MediaSize
-struct PrintMediaSize {
- // Id unique among media sizes.
- string id;
- // Localized label.
- string label;
- int32 width_mils;
- int32 height_mils;
-};
-
-// android.print.PrintAttributes.Resolution
-struct PrintResolution {
- // Id unique among resolutions.
- string id;
- // Localized label.
- string label;
- int32 horizontal_dpi;
- int32 vertical_dpi;
-};
-
-// android.print.PrintAttributes.Margins
-struct PrintMargins {
- int32 left_mils;
- int32 top_mils;
- int32 right_mils;
- int32 bottom_mils;
-};
-
-// android.print.PrintAttributes.COLOR_MODE_*
-[Extensible]
-enum PrintColorMode {
- MONOCHROME = 1,
- COLOR = 2,
-};
-
-// android.print.PrintAttributes.DUPLEX_MODE_*
-[Extensible]
-enum PrintDuplexMode {
- NONE = 1,
- LONG_EDGE = 2,
- SHORT_EDGE = 4,
-};
-
-// android.print.PrintDocumentInfo.CONTENT_TYPE_*
-[Extensible]
-enum PrintContentType {
- UNKNOWN = -1,
- DOCUMENT = 0,
- PHOTO = 1,
-};
-
-// android.print.PrintAttributes
-struct PrintAttributes {
- PrintMediaSize? media_size;
- PrintResolution? resolution;
- PrintMargins? min_margins;
- PrintColorMode color_mode;
- PrintDuplexMode duplex_mode;
-};
-
-struct PrintJobRequest {
- // android.printservice.PrintJob fields:
- array<int8> id;
- string label;
- string? printer_id;
- int64 creation_time;
- int32 copies;
- array<PrintPageRange> pages;
- PrintAttributes attributes;
- // android.print.PrintDocumentInfo fields:
- string document_name;
- int32 document_page_count;
- PrintContentType content_type;
- int64 data_size;
- // android.printservice.PrintDocument fields:
- handle? data;
-};
-
-// android.print.PrinterInfo.STATUS_*
-[Extensible]
-enum PrinterStatus {
- IDLE = 1,
- BUSY = 2,
- UNAVAILABLE = 3,
-};
-
-// android.print.PrinterCapabilitiesInfo
-struct PrinterCapabilities {
- array<PrintMediaSize> media_sizes;
- array<PrintResolution> resolutions;
- PrintMargins min_margins;
- PrintColorMode color_modes;
- PrintDuplexMode duplex_modes;
- PrintAttributes defaults;
-};
-
-// android.print.PrinterInfo
-struct PrinterInfo {
- // Id unique among printers.
- string id;
- // Localized name.
- string name;
- PrinterStatus status;
- // Localized description.
- string? description;
- // Intent for provider-specific settings.
- string? info_intent;
- PrinterCapabilities? capabilities;
-};
+import "components/arc/mojom/print_common.mojom";
// android.printservice.PrinterDiscoverySession implementation.
// This is called by container when printing is requested and printer discovery
diff --git a/chromium/components/arc/mojom/print.typemap b/chromium/components/arc/mojom/print.typemap
new file mode 100644
index 00000000000..231f12f8593
--- /dev/null
+++ b/chromium/components/arc/mojom/print.typemap
@@ -0,0 +1,19 @@
+mojom = "//components/arc/mojom/print_common.mojom"
+public_headers = [
+ "//printing/backend/print_backend.h",
+ "//printing/page_range.h",
+ "//ui/gfx/geometry/size.h",
+]
+traits_headers = [ "//chrome/browser/chromeos/arc/print/print_mojom_traits.h" ]
+sources = [
+ "//chrome/browser/chromeos/arc/print/print_mojom_traits.cc",
+]
+deps = []
+public_deps = [
+ "//printing:printing",
+]
+type_mappings = [
+ "arc.mojom.PrintPageRange=::printing::PageRange",
+ "arc.mojom.PrintResolution=::gfx::Size",
+ "arc.mojom.PrinterCapabilities=::printing::PrinterSemanticCapsAndDefaults",
+]
diff --git a/chromium/components/arc/mojom/print_common.mojom b/chromium/components/arc/mojom/print_common.mojom
new file mode 100644
index 00000000000..006181d8d2b
--- /dev/null
+++ b/chromium/components/arc/mojom/print_common.mojom
@@ -0,0 +1,123 @@
+// Copyright 2019 The Chromium 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 arc.mojom;
+
+// android.print.PageRange
+struct PrintPageRange {
+ // First page inclusive.
+ int32 start;
+ // Last page inclusive.
+ int32 end;
+};
+
+// android.print.PrintAttributes.MediaSize
+struct PrintMediaSize {
+ // Id unique among media sizes.
+ string id;
+ // Localized label.
+ string label;
+ int32 width_mils;
+ int32 height_mils;
+};
+
+// android.print.PrintAttributes.Resolution
+struct PrintResolution {
+ // Id unique among resolutions.
+ string id;
+ // Localized label.
+ string label;
+ int32 horizontal_dpi;
+ int32 vertical_dpi;
+};
+
+// android.print.PrintAttributes.Margins
+struct PrintMargins {
+ int32 left_mils;
+ int32 top_mils;
+ int32 right_mils;
+ int32 bottom_mils;
+};
+
+// android.print.PrintAttributes.COLOR_MODE_*
+[Extensible]
+enum PrintColorMode {
+ MONOCHROME = 1,
+ COLOR = 2,
+};
+
+// android.print.PrintAttributes.DUPLEX_MODE_*
+[Extensible]
+enum PrintDuplexMode {
+ NONE = 1,
+ LONG_EDGE = 2,
+ SHORT_EDGE = 4,
+};
+
+// android.print.PrintDocumentInfo.CONTENT_TYPE_*
+[Extensible]
+enum PrintContentType {
+ UNKNOWN = -1,
+ DOCUMENT = 0,
+ PHOTO = 1,
+};
+
+// android.print.PrintAttributes
+struct PrintAttributes {
+ PrintMediaSize? media_size;
+ PrintResolution? resolution;
+ PrintMargins? min_margins;
+ PrintColorMode color_mode;
+ PrintDuplexMode duplex_mode;
+};
+
+struct PrintJobRequest {
+ // android.printservice.PrintJob fields:
+ array<int8> id;
+ string label;
+ string? printer_id;
+ int64 creation_time;
+ int32 copies;
+ array<PrintPageRange> pages;
+ PrintAttributes attributes;
+ // android.print.PrintDocumentInfo fields:
+ string document_name;
+ int32 document_page_count;
+ PrintContentType content_type;
+ int64 data_size;
+ // android.printservice.PrintDocument fields:
+ handle? data;
+};
+
+// android.print.PrinterInfo.STATUS_*
+[Extensible]
+enum PrinterStatus {
+ IDLE = 1,
+ BUSY = 2,
+ UNAVAILABLE = 3,
+};
+
+// android.print.PrinterCapabilitiesInfo
+struct PrinterCapabilities {
+ array<PrintMediaSize> media_sizes;
+ array<PrintResolution> resolutions;
+ PrintMargins min_margins;
+ PrintColorMode color_modes;
+ PrintDuplexMode duplex_modes;
+ PrintAttributes defaults;
+};
+
+// android.print.PrinterInfo
+struct PrinterInfo {
+ // Id unique among printers.
+ string id;
+ // Localized name.
+ string name;
+ PrinterStatus status;
+ // Localized description.
+ string? description;
+ // Intent for provider-specific settings.
+ string? info_intent;
+ PrinterCapabilities? capabilities;
+};
diff --git a/chromium/components/arc/mojom/print_spooler.mojom b/chromium/components/arc/mojom/print_spooler.mojom
new file mode 100644
index 00000000000..978be91e01e
--- /dev/null
+++ b/chromium/components/arc/mojom/print_spooler.mojom
@@ -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.
+//
+// Next MinVersion: 3
+
+module arc.mojom;
+
+import "components/arc/mojom/print_common.mojom";
+
+// Represents the Chrome side of a print session. Used by ARC to send
+// print-related messages to Chrome and interact with the ARC Custom Tab used
+// for printing.
+// Closing the interface will close the ARC Custom Tab.
+// Next method ID: 0
+interface PrintSessionHost {
+};
+
+// Represents the ARC side of a print session. Used by Chrome to send
+// print-related messages to ARC and request rendered print documents.
+// Next method ID: 1
+interface PrintSessionInstance {
+ // Called when Chrome print preview is closed.
+ [MinVersion=2] OnPrintPreviewClosed@0();
+
+ // TODO(jschettler): Add method to render a print document.
+};
+
+// Used by ARC to create a new print session. A print session is used to print a
+// document from ARC using Chrome print preview.
+// Next method ID: 1
+interface PrintSpoolerHost {
+ // Opens the file owned by |scoped_handle| in Chrome print preview in an ARC
+ // Custom Tab.
+ // The |task_id| and |surface_id| specify the Android task and the surface on
+ // which the ARC Custom Tab should be shown.
+ // The |top_margin| is the height of the space at the top of the window.
+ // The returned |host| will be null if errors occur while saving the print
+ // document or locating the Android surface.
+ [MinVersion=1] StartPrintInCustomTab@0(handle scoped_handle,
+ int32 task_id,
+ int32 surface_id,
+ int32 top_margin,
+ PrintSessionInstance instance)
+ => (PrintSessionHost? host);
+};
+
+// Next method ID: 1
+interface PrintSpoolerInstance {
+ // Establishes full-duplex communication with the host.
+ [MinVersion=0] Init@0(PrintSpoolerHost host_ptr) => ();
+};
diff --git a/chromium/components/arc/common/process.mojom b/chromium/components/arc/mojom/process.mojom
index 1dd08326bad..76b68ac375c 100644
--- a/chromium/components/arc/common/process.mojom
+++ b/chromium/components/arc/mojom/process.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Next MinVersion: 8
+// Next MinVersion: 9
module arc.mojom;
@@ -109,7 +109,19 @@ struct RunningAppProcessInfo {
int64 last_activity_time;
};
-// Next Method ID: 8
+// Describes the memory usage of an ARC process.
+struct ArcMemoryDump {
+ // PID (within ARC's PID namespace) of the process.
+ uint32 pid;
+
+ // Resident Set Size (RSS) in kilobytes
+ uint32 resident_set_kb = 0;
+
+ // Private footprint (RSS + swap usage) in kilobytes
+ uint32 private_footprint_kb = 0;
+};
+
+// Next Method ID: 10
interface ProcessInstance {
// Requests ARC instance to kill a process.
[MinVersion=1]
@@ -120,11 +132,22 @@ interface ProcessInstance {
// Requests memory usage dumps for all ARC application processes.
[MinVersion=7]
- RequestApplicationProcessMemoryInfo@6()
- => (memory_instrumentation.mojom.GlobalMemoryDump dump);
+ RequestApplicationProcessMemoryInfoDeprecated@6()
+ => (memory_instrumentation.mojom.GlobalMemoryDump dump);
// Requests memory usage dumps for all ARC system processes.
[MinVersion=7]
- RequestSystemProcessMemoryInfo@7(array<uint32> nspids)
- => (memory_instrumentation.mojom.GlobalMemoryDump dump);
+ RequestSystemProcessMemoryInfoDeprecated@7(array<uint32> nspids)
+ => (memory_instrumentation.mojom.GlobalMemoryDump dump);
+
+ // Requests memory usage dumps for all ARC application processes.
+ [MinVersion=8]
+ RequestApplicationProcessMemoryInfo@8()
+ => (array<ArcMemoryDump> process_dumps);
+
+ // Requests memory usage dumps for all ARC system processes.
+ [MinVersion=8]
+ RequestSystemProcessMemoryInfo@9(array<uint32> nspids)
+ => (array<ArcMemoryDump> process_dumps);
+
};
diff --git a/chromium/components/arc/common/property.mojom b/chromium/components/arc/mojom/property.mojom
index 8e1ca2e874f..8e1ca2e874f 100644
--- a/chromium/components/arc/common/property.mojom
+++ b/chromium/components/arc/mojom/property.mojom
diff --git a/chromium/components/arc/common/protected_buffer_manager.mojom b/chromium/components/arc/mojom/protected_buffer_manager.mojom
index 298f6d3bbf2..633bab84235 100644
--- a/chromium/components/arc/common/protected_buffer_manager.mojom
+++ b/chromium/components/arc/mojom/protected_buffer_manager.mojom
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// The original version of this file lives in the Chromium repository at:
-// src/components/arc/common/protected_buffer_manager.mojom
+// src/components/arc/mojom/protected_buffer_manager.mojom
module arc.mojom;
diff --git a/chromium/components/arc/common/rotation_lock.mojom b/chromium/components/arc/mojom/rotation_lock.mojom
index 9bfeb524a52..9bfeb524a52 100644
--- a/chromium/components/arc/common/rotation_lock.mojom
+++ b/chromium/components/arc/mojom/rotation_lock.mojom
diff --git a/chromium/components/arc/common/scale_factor.mojom b/chromium/components/arc/mojom/scale_factor.mojom
index df38c5c035b..df38c5c035b 100644
--- a/chromium/components/arc/common/scale_factor.mojom
+++ b/chromium/components/arc/mojom/scale_factor.mojom
diff --git a/chromium/components/arc/common/screen_capture.mojom b/chromium/components/arc/mojom/screen_capture.mojom
index 8a3bc852adf..960012ca016 100644
--- a/chromium/components/arc/common/screen_capture.mojom
+++ b/chromium/components/arc/mojom/screen_capture.mojom
@@ -8,14 +8,14 @@
// permissions to capture the entire desktop and then also perform that capture.
// The original version of this file lives in the Chromium repository at:
-// src/components/arc/common/screen_capture.mojom
+// src/components/arc/mojom/screen_capture.mojom
// Next MinVersion: 2
module arc.mojom;
// For gfx::Size.
-import "components/arc/common/video_common.mojom";
+import "components/arc/mojom/video_common.mojom";
// Implemented by Chrome in order to allow requesting of permissions to perform
// desktop capture as well as creating a session for it.
diff --git a/chromium/components/arc/common/storage_manager.mojom b/chromium/components/arc/mojom/storage_manager.mojom
index 2e4295dd240..2e4295dd240 100644
--- a/chromium/components/arc/common/storage_manager.mojom
+++ b/chromium/components/arc/mojom/storage_manager.mojom
diff --git a/chromium/components/arc/common/timer.mojom b/chromium/components/arc/mojom/timer.mojom
index 4d8760e3096..4d8760e3096 100644
--- a/chromium/components/arc/common/timer.mojom
+++ b/chromium/components/arc/mojom/timer.mojom
diff --git a/chromium/components/arc/mojom/timer.typemap b/chromium/components/arc/mojom/timer.typemap
new file mode 100644
index 00000000000..2226601b3fe
--- /dev/null
+++ b/chromium/components/arc/mojom/timer.typemap
@@ -0,0 +1,10 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//components/arc/mojom/timer.mojom"
+traits_headers = [ "//components/arc/timer/arc_timer_mojom_traits.h" ]
+sources = [
+ "//components/arc/timer/arc_timer_mojom_traits.cc",
+]
+type_mappings = [ "arc.mojom.ClockId=::clockid_t" ]
diff --git a/chromium/components/arc/common/tracing.mojom b/chromium/components/arc/mojom/tracing.mojom
index aa1f5a2f3bc..aa1f5a2f3bc 100644
--- a/chromium/components/arc/common/tracing.mojom
+++ b/chromium/components/arc/mojom/tracing.mojom
diff --git a/chromium/components/arc/common/tts.mojom b/chromium/components/arc/mojom/tts.mojom
index b013a1b2c21..b013a1b2c21 100644
--- a/chromium/components/arc/common/tts.mojom
+++ b/chromium/components/arc/mojom/tts.mojom
diff --git a/chromium/components/arc/mojom/typemaps.gni b/chromium/components/arc/mojom/typemaps.gni
new file mode 100644
index 00000000000..6b295325ab4
--- /dev/null
+++ b/chromium/components/arc/mojom/typemaps.gni
@@ -0,0 +1,18 @@
+# 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.
+
+typemaps = [
+ "//components/arc/mojom/app.typemap",
+ "//components/arc/mojom/bitmap.typemap",
+ "//components/arc/mojom/bluetooth.typemap",
+ "//components/arc/mojom/file_system.typemap",
+ "//components/arc/mojom/gfx.typemap",
+ "//components/arc/mojom/ime.typemap",
+ "//components/arc/mojom/intent_helper.typemap",
+ "//components/arc/mojom/print.typemap",
+ "//components/arc/mojom/timer.typemap",
+ "//components/arc/mojom/video_common.typemap",
+ "//components/arc/mojom/video_encode_accelerator.typemap",
+ "//components/arc/mojom/volume_mounter.typemap",
+]
diff --git a/chromium/components/arc/common/usb_host.mojom b/chromium/components/arc/mojom/usb_host.mojom
index ff41f57cbaa..ff41f57cbaa 100644
--- a/chromium/components/arc/common/usb_host.mojom
+++ b/chromium/components/arc/mojom/usb_host.mojom
diff --git a/chromium/components/arc/common/video.mojom b/chromium/components/arc/mojom/video.mojom
index acc40a454c2..22f2558e8c9 100644
--- a/chromium/components/arc/common/video.mojom
+++ b/chromium/components/arc/mojom/video.mojom
@@ -6,9 +6,9 @@
module arc.mojom;
-import "components/arc/common/video_decode_accelerator.mojom";
-import "components/arc/common/video_encode_accelerator.mojom";
-import "components/arc/common/video_protected_buffer_allocator.mojom";
+import "components/arc/mojom/video_decode_accelerator.mojom";
+import "components/arc/mojom/video_encode_accelerator.mojom";
+import "components/arc/mojom/video_protected_buffer_allocator.mojom";
// Deprecated method IDs: 0
// Next method ID: 2
diff --git a/chromium/components/arc/common/video_accelerator_struct_traits.cc b/chromium/components/arc/mojom/video_accelerator_mojom_traits.cc
index 4116b28ca39..cd270013b47 100644
--- a/chromium/components/arc/common/video_accelerator_struct_traits.cc
+++ b/chromium/components/arc/mojom/video_accelerator_mojom_traits.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 "components/arc/common/video_accelerator_struct_traits.h"
+#include "components/arc/mojom/video_accelerator_mojom_traits.h"
namespace mojo {
diff --git a/chromium/components/arc/common/video_accelerator_struct_traits.h b/chromium/components/arc/mojom/video_accelerator_mojom_traits.h
index f9c959f8863..9ac646001ef 100644
--- a/chromium/components/arc/common/video_accelerator_struct_traits.h
+++ b/chromium/components/arc/mojom/video_accelerator_mojom_traits.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 COMPONENTS_ARC_COMMON_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_COMMON_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_MOJOM_VIDEO_ACCELERATOR_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_MOJOM_VIDEO_ACCELERATOR_MOJOM_TRAITS_H_
#include <memory>
-#include "components/arc/common/video_common.mojom.h"
+#include "components/arc/mojom/video_common.mojom.h"
#include "components/arc/video_accelerator/video_frame_plane.h"
#include "media/base/decode_status.h"
#include "media/base/video_codecs.h"
@@ -147,4 +147,4 @@ struct EnumTraits<arc::mojom::DecodeStatus, media::DecodeStatus> {
} // namespace mojo
-#endif // COMPONENTS_ARC_COMMON_VIDEO_ACCELERATOR_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_MOJOM_VIDEO_ACCELERATOR_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/common/video_accelerator_struct_traits_unittest.cc b/chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc
index 6d2e655bbda..76c21ca2a95 100644
--- a/chromium/components/arc/common/video_accelerator_struct_traits_unittest.cc
+++ b/chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/arc/common/video_accelerator_struct_traits.h"
+#include "components/arc/mojom/video_accelerator_mojom_traits.h"
#include <vector>
-#include "components/arc/common/video_common.mojom.h"
+#include "components/arc/mojom/video_common.mojom.h"
#include "media/base/video_frame_layout.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/test_support/test_utils.h"
diff --git a/chromium/components/arc/common/video_common.mojom b/chromium/components/arc/mojom/video_common.mojom
index 3ead5042db6..3ead5042db6 100644
--- a/chromium/components/arc/common/video_common.mojom
+++ b/chromium/components/arc/mojom/video_common.mojom
diff --git a/chromium/components/arc/common/video_common.typemap b/chromium/components/arc/mojom/video_common.typemap
index 9eb47ee6195..61488691c93 100644
--- a/chromium/components/arc/common/video_common.typemap
+++ b/chromium/components/arc/mojom/video_common.typemap
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom = "//components/arc/common/video_common.mojom"
+mojom = "//components/arc/mojom/video_common.mojom"
public_headers = [
"//components/arc/video_accelerator/video_frame_plane.h",
"//media/base/decode_status.h",
@@ -16,11 +16,11 @@ public_deps = [
"//media",
]
-traits_headers = [ "//components/arc/common/video_accelerator_struct_traits.h" ]
+traits_headers = [ "//components/arc/mojom/video_accelerator_mojom_traits.h" ]
sources = [
- "//components/arc/common/video_accelerator_struct_traits.cc",
- "//components/arc/common/video_accelerator_struct_traits.h",
+ "//components/arc/mojom/video_accelerator_mojom_traits.cc",
+ "//components/arc/mojom/video_accelerator_mojom_traits.h",
]
deps = [
diff --git a/chromium/components/arc/common/video_decode_accelerator.mojom b/chromium/components/arc/mojom/video_decode_accelerator.mojom
index 625b62a0d19..56bf60dd8c3 100644
--- a/chromium/components/arc/common/video_decode_accelerator.mojom
+++ b/chromium/components/arc/mojom/video_decode_accelerator.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 5
+// Next MinVersion: 4
// This file defines the mojo interface between Android and Chromium for video
// decoding. Any Mojo callee that returns a value does so by callback.
@@ -17,8 +17,8 @@
module arc.mojom;
-import "components/arc/common/gfx.mojom";
-import "components/arc/common/video_common.mojom";
+import "components/arc/mojom/gfx.mojom";
+import "components/arc/mojom/video_common.mojom";
// Information of the bitstream buffer.
struct BitstreamBuffer {
@@ -78,7 +78,7 @@ struct VideoDecodeAcceleratorConfig {
// the dummy buffer.
//
// Deprecated method IDs: 3, 7, 8
-// Next method ID: 11
+// Next method ID: 10
interface VideoDecodeAccelerator {
[Extensible]
enum Result {
@@ -104,13 +104,7 @@ interface VideoDecodeAccelerator {
// Sets the number of output picture buffers.
// This releases any buffers in use/imported previously.
- AssignPictureBuffersDeprecated@2(uint32 count);
-
- // Sets the number of output picture buffers. |size| is the frame size
- // adjusted by Android.
- // This releases any buffers in use/imported previously.
- [MinVersion=4]
- AssignPictureBuffers@10(uint32 count, Size size);
+ AssignPictureBuffers@2(uint32 count);
// Imports a buffer to be used by the accelerator with specified
// |picture_buffer_id|.
diff --git a/chromium/components/arc/common/video_encode_accelerator.mojom b/chromium/components/arc/mojom/video_encode_accelerator.mojom
index b4c9f417340..0bf30f7de9d 100644
--- a/chromium/components/arc/common/video_encode_accelerator.mojom
+++ b/chromium/components/arc/mojom/video_encode_accelerator.mojom
@@ -7,7 +7,7 @@
module arc.mojom;
-import "components/arc/common/video_common.mojom";
+import "components/arc/mojom/video_common.mojom";
// Next MinVersion: 4
diff --git a/chromium/components/arc/mojom/video_encode_accelerator.typemap b/chromium/components/arc/mojom/video_encode_accelerator.typemap
new file mode 100644
index 00000000000..89e99e89487
--- /dev/null
+++ b/chromium/components/arc/mojom/video_encode_accelerator.typemap
@@ -0,0 +1,24 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//components/arc/mojom/video_encode_accelerator.mojom"
+public_headers = [ "//media/video/video_encode_accelerator.h" ]
+public_deps = [
+ "//base",
+ "//media/gpu",
+]
+traits_headers =
+ [ "//components/arc/mojom/video_encode_accelerator_mojom_traits.h" ]
+sources = [
+ "//components/arc/mojom/video_encode_accelerator_mojom_traits.cc",
+]
+deps = [
+ "//base",
+]
+type_mappings = [
+ "arc.mojom.VideoFrameStorageType=::media::VideoEncodeAccelerator::Config::StorageType",
+ "arc.mojom.VideoEncodeAccelerator.Error=::media::VideoEncodeAccelerator::Error",
+ "arc.mojom.VideoEncodeProfile=::media::VideoEncodeAccelerator::SupportedProfile",
+ "arc.mojom.VideoEncodeAcceleratorConfig=::media::VideoEncodeAccelerator::Config",
+]
diff --git a/chromium/components/arc/common/video_encode_accelerator_struct_traits.cc b/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc
index 72bcd884f3d..e38ad164c0e 100644
--- a/chromium/components/arc/common/video_encode_accelerator_struct_traits.cc
+++ b/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/arc/common/video_encode_accelerator_struct_traits.h"
+#include "components/arc/mojom/video_encode_accelerator_mojom_traits.h"
#include "base/optional.h"
-#include "components/arc/common/video_accelerator_struct_traits.h"
+#include "components/arc/mojom/video_accelerator_mojom_traits.h"
namespace mojo {
diff --git a/chromium/components/arc/common/video_encode_accelerator_struct_traits.h b/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.h
index aa3078c0a7b..3b2f742646b 100644
--- a/chromium/components/arc/common/video_encode_accelerator_struct_traits.h
+++ b/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_COMMON_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_COMMON_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_MOJOM_VIDEO_ENCODE_ACCELERATOR_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_MOJOM_VIDEO_ENCODE_ACCELERATOR_MOJOM_TRAITS_H_
-#include "components/arc/common/video_encode_accelerator.mojom.h"
+#include "components/arc/mojom/video_encode_accelerator.mojom.h"
#include "media/video/video_encode_accelerator.h"
namespace mojo {
@@ -128,4 +128,4 @@ struct StructTraits<arc::mojom::VideoEncodeAcceleratorConfigDataView,
} // namespace mojo
-#endif // COMPONENTS_ARC_COMMON_VIDEO_ENCODE_ACCELERATOR_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_MOJOM_VIDEO_ENCODE_ACCELERATOR_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/common/video_protected_buffer_allocator.mojom b/chromium/components/arc/mojom/video_protected_buffer_allocator.mojom
index c133cafecc4..dbb9eda3ef3 100644
--- a/chromium/components/arc/common/video_protected_buffer_allocator.mojom
+++ b/chromium/components/arc/mojom/video_protected_buffer_allocator.mojom
@@ -6,7 +6,7 @@
module arc.mojom;
-import "components/arc/common/video_common.mojom";
+import "components/arc/mojom/video_common.mojom";
// Next method ID: 3
interface VideoProtectedBufferAllocator {
diff --git a/chromium/components/arc/common/voice_interaction_arc_home.mojom b/chromium/components/arc/mojom/voice_interaction_arc_home.mojom
index 10d5d57b7c7..f91b1be6e4c 100644
--- a/chromium/components/arc/common/voice_interaction_arc_home.mojom
+++ b/chromium/components/arc/mojom/voice_interaction_arc_home.mojom
@@ -6,7 +6,7 @@
module arc.mojom;
-import "components/arc/common/gfx.mojom";
+import "components/arc/mojom/gfx.mojom";
import "mojo/public/mojom/base/string16.mojom";
// Represents view structure to be passed to ARC. The view
diff --git a/chromium/components/arc/common/voice_interaction_framework.mojom b/chromium/components/arc/mojom/voice_interaction_framework.mojom
index 56bcc58d948..2873ad90dfa 100644
--- a/chromium/components/arc/common/voice_interaction_framework.mojom
+++ b/chromium/components/arc/mojom/voice_interaction_framework.mojom
@@ -6,10 +6,10 @@
module arc.mojom;
-import "components/arc/common/gfx.mojom";
+import "components/arc/mojom/gfx.mojom";
// There is another copy of the VoiceInteractionState definition in
-// //ash/public/interfaces/voice_interaction_controller.mojom
+// //ash/public/mojom/voice_interaction_controller.mojom
// Please also update the other one if you change it.
// The duplicate definition is because we do not use extensible widely
// (crbug.com/731893).
diff --git a/chromium/components/arc/common/volume_mounter.mojom b/chromium/components/arc/mojom/volume_mounter.mojom
index 27401b9a59b..c8059971fa9 100644
--- a/chromium/components/arc/common/volume_mounter.mojom
+++ b/chromium/components/arc/mojom/volume_mounter.mojom
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Next MinVersion: 3
+
module arc.mojom;
[Extensible]
@@ -36,6 +38,10 @@ struct MountPointInfo {
// The device type that contains this mount point. If unknown, the event
// should be ignored.
DeviceType device_type;
+ // Whether the mounted volume should be visible to Android apps.
+ // This is a user-controlled setting, which is accessible in "External
+ // storage preferences" screen in device settings.
+ [MinVersion=2] bool visible;
};
// Next Method ID: 1
diff --git a/chromium/components/arc/common/volume_mounter.typemap b/chromium/components/arc/mojom/volume_mounter.typemap
index 4a025cf050b..34424125d29 100644
--- a/chromium/components/arc/common/volume_mounter.typemap
+++ b/chromium/components/arc/mojom/volume_mounter.typemap
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-mojom = "//components/arc/common/volume_mounter.mojom"
+mojom = "//components/arc/mojom/volume_mounter.mojom"
public_headers = [
"//chromeos/chromeos_export.h",
"//chromeos/dbus/cros_disks_client.h",
@@ -10,11 +10,11 @@ public_headers = [
"//chromeos/disks/disk_mount_manager.h",
]
traits_headers =
- [ "//components/arc/volume_mounter/volume_mounter_struct_traits.h" ]
+ [ "//components/arc/volume_mounter/volume_mounter_mojom_traits.h" ]
sources = [
- "//components/arc/volume_mounter/volume_mounter_struct_traits.cc",
+ "//components/arc/volume_mounter/volume_mounter_mojom_traits.cc",
]
type_mappings = [
- "arc.mojom.DeviceType=chromeos::DeviceType",
- "arc.mojom.MountEvent=chromeos::disks::DiskMountManager::MountEvent",
+ "arc.mojom.DeviceType=::chromeos::DeviceType",
+ "arc.mojom.MountEvent=::chromeos::disks::DiskMountManager::MountEvent",
]
diff --git a/chromium/components/arc/common/wake_lock.mojom b/chromium/components/arc/mojom/wake_lock.mojom
index 44217547422..44217547422 100644
--- a/chromium/components/arc/common/wake_lock.mojom
+++ b/chromium/components/arc/mojom/wake_lock.mojom
diff --git a/chromium/components/arc/common/wallpaper.mojom b/chromium/components/arc/mojom/wallpaper.mojom
index 3048e4560a7..3048e4560a7 100644
--- a/chromium/components/arc/common/wallpaper.mojom
+++ b/chromium/components/arc/mojom/wallpaper.mojom
diff --git a/chromium/components/arc/net/always_on_vpn_manager_unittest.cc b/chromium/components/arc/net/always_on_vpn_manager_unittest.cc
index d18bf1c1b65..d4ff7dcaa3d 100644
--- a/chromium/components/arc/net/always_on_vpn_manager_unittest.cc
+++ b/chromium/components/arc/net/always_on_vpn_manager_unittest.cc
@@ -14,7 +14,7 @@
#include "chromeos/network/network_handler.h"
#include "components/arc/arc_prefs.h"
#include "components/prefs/testing_pref_service.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
@@ -80,7 +80,7 @@ class AlwaysOnVpnManagerTest : public testing::Test {
TestingPrefServiceSimple* pref_service() { return &pref_service_; }
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
TestingPrefServiceSimple pref_service_;
DISALLOW_COPY_AND_ASSIGN(AlwaysOnVpnManagerTest);
diff --git a/chromium/components/arc/net/arc_net_host_impl.cc b/chromium/components/arc/net/arc_net_host_impl.cc
index 0ea0f510843..83ff44b4c13 100644
--- a/chromium/components/arc/net/arc_net_host_impl.cc
+++ b/chromium/components/arc/net/arc_net_host_impl.cc
@@ -230,7 +230,7 @@ arc::mojom::ConnectionStateType TranslateConnectionState(
state == shill::kStateConfiguration)
return arc::mojom::ConnectionStateType::CONNECTING;
if ((state == shill::kStateIdle) || (state == shill::kStateFailure) ||
- (state == ""))
+ (state == shill::kStateDisconnect) || (state == ""))
return arc::mojom::ConnectionStateType::NOT_CONNECTED;
if (chromeos::NetworkState::StateIsPortalled(state))
return arc::mojom::ConnectionStateType::PORTAL;
@@ -239,7 +239,7 @@ arc::mojom::ConnectionStateType TranslateConnectionState(
// The remaining cases defined in shill dbus-constants are legacy values from
// Flimflam and are not expected to be encountered. These are: kStateCarrier,
- // kStateActivationFailure, kStateDisconnect, and kStateOffline.
+ // kStateActivationFailure, and kStateOffline.
NOTREACHED() << "Unknown connection state: " << state;
return arc::mojom::ConnectionStateType::NOT_CONNECTED;
}
@@ -458,7 +458,7 @@ ArcNetHostImpl* ArcNetHostImpl::GetForBrowserContextForTesting(
ArcNetHostImpl::ArcNetHostImpl(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), weak_factory_(this) {
+ : arc_bridge_service_(bridge_service) {
arc_bridge_service_->net()->SetHost(this);
arc_bridge_service_->net()->AddObserver(this);
}
diff --git a/chromium/components/arc/net/arc_net_host_impl.h b/chromium/components/arc/net/arc_net_host_impl.h
index fca8d74ba01..79d19676d33 100644
--- a/chromium/components/arc/net/arc_net_host_impl.h
+++ b/chromium/components/arc/net/arc_net_host_impl.h
@@ -18,7 +18,7 @@
#include "base/values.h"
#include "chromeos/network/network_connection_observer.h"
#include "chromeos/network/network_state_handler_observer.h"
-#include "components/arc/common/net.mojom.h"
+#include "components/arc/mojom/net.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -165,7 +165,7 @@ class ArcNetHostImpl : public KeyedService,
PrefService* pref_service_ = nullptr;
THREAD_CHECKER(thread_checker_);
- base::WeakPtrFactory<ArcNetHostImpl> weak_factory_;
+ base::WeakPtrFactory<ArcNetHostImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcNetHostImpl);
};
diff --git a/chromium/components/arc/net/arc_net_host_impl_unittest.cc b/chromium/components/arc/net/arc_net_host_impl_unittest.cc
index 2dab5b4168a..d43dbad1dda 100644
--- a/chromium/components/arc/net/arc_net_host_impl_unittest.cc
+++ b/chromium/components/arc/net/arc_net_host_impl_unittest.cc
@@ -11,7 +11,7 @@
#include "components/arc/arc_service_manager.h"
#include "components/arc/test/test_browser_context.h"
#include "components/prefs/testing_pref_service.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace arc {
@@ -34,7 +34,7 @@ class ArcNetHostImplTest : public testing::Test {
TestingPrefServiceSimple* pref_service() { return &pref_service_; }
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<ArcServiceManager> arc_service_manager_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<TestBrowserContext> context_;
diff --git a/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h b/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h
index 8756ab62ebf..707ea27a979 100644
--- a/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h
+++ b/chromium/components/arc/obb_mounter/arc_obb_mounter_bridge.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/macros.h"
-#include "components/arc/common/obb_mounter.mojom.h"
+#include "components/arc/mojom/obb_mounter.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/power/arc_power_bridge.cc b/chromium/components/arc/power/arc_power_bridge.cc
index 4985b11674d..7603476c237 100644
--- a/chromium/components/arc/power/arc_power_bridge.cc
+++ b/chromium/components/arc/power/arc_power_bridge.cc
@@ -19,6 +19,7 @@
#include "components/arc/arc_service_manager.h"
#include "components/arc/session/arc_bridge_service.h"
#include "content/public/browser/system_connector.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -73,12 +74,12 @@ class ArcPowerBridge::WakeLockRequestor {
// Initialize |wake_lock_| if this is the first time we're using it.
if (!wake_lock_) {
- device::mojom::WakeLockProviderPtr provider;
- connector_->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&provider));
+ mojo::Remote<device::mojom::WakeLockProvider> provider;
+ connector_->Connect(device::mojom::kServiceName,
+ provider.BindNewPipeAndPassReceiver());
provider->GetWakeLockWithoutContext(
type_, device::mojom::WakeLockReason::kOther, "ARC",
- mojo::MakeRequest(&wake_lock_));
+ wake_lock_.BindNewPipeAndPassReceiver());
}
wake_lock_->RequestWakeLock();
@@ -114,7 +115,7 @@ class ArcPowerBridge::WakeLockRequestor {
int num_android_requests_ = 0;
// Lazily initialized in response to first request.
- device::mojom::WakeLockPtr wake_lock_;
+ mojo::Remote<device::mojom::WakeLock> wake_lock_;
DISALLOW_COPY_AND_ASSIGN(WakeLockRequestor);
};
@@ -127,7 +128,7 @@ ArcPowerBridge* ArcPowerBridge::GetForBrowserContext(
ArcPowerBridge::ArcPowerBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service), weak_ptr_factory_(this) {
+ : arc_bridge_service_(bridge_service) {
arc_bridge_service_->power()->SetHost(this);
arc_bridge_service_->power()->AddObserver(this);
}
diff --git a/chromium/components/arc/power/arc_power_bridge.h b/chromium/components/arc/power/arc_power_bridge.h
index 94fc7dbc527..3533089adea 100644
--- a/chromium/components/arc/power/arc_power_bridge.h
+++ b/chromium/components/arc/power/arc_power_bridge.h
@@ -12,7 +12,7 @@
#include "base/optional.h"
#include "base/timer/timer.h"
#include "chromeos/dbus/power/power_manager_client.h"
-#include "components/arc/common/power.mojom.h"
+#include "components/arc/mojom/power.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
@@ -105,7 +105,7 @@ class ArcPowerBridge : public KeyedService,
// about brightness changes.
base::OneShotTimer notify_brightness_timer_;
- base::WeakPtrFactory<ArcPowerBridge> weak_ptr_factory_;
+ base::WeakPtrFactory<ArcPowerBridge> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcPowerBridge);
};
diff --git a/chromium/components/arc/power/arc_power_bridge_unittest.cc b/chromium/components/arc/power/arc_power_bridge_unittest.cc
index 427ea5747fb..0bef551b69a 100644
--- a/chromium/components/arc/power/arc_power_bridge_unittest.cc
+++ b/chromium/components/arc/power/arc_power_bridge_unittest.cc
@@ -7,11 +7,11 @@
#include <utility>
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "chromeos/dbus/power/fake_power_manager_client.h"
#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
#include "chromeos/dbus/power_manager/suspend.pb.h"
-#include "components/arc/common/power.mojom.h"
+#include "components/arc/mojom/power.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/test/connection_holder_util.h"
#include "components/arc/test/fake_power_instance.h"
@@ -103,7 +103,7 @@ class ArcPowerBridgeTest : public testing::Test {
return chromeos::FakePowerManagerClient::Get();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
service_manager::TestConnectorFactory connector_factory_;
diff --git a/chromium/components/arc/print_spooler/OWNERS b/chromium/components/arc/print_spooler/OWNERS
new file mode 100644
index 00000000000..060b5bfc5ef
--- /dev/null
+++ b/chromium/components/arc/print_spooler/OWNERS
@@ -0,0 +1,2 @@
+bmgordon@chromium.org
+jschettler@chromium.org
diff --git a/chromium/components/arc/property/arc_property_bridge.h b/chromium/components/arc/property/arc_property_bridge.h
index 27d37fd0266..f116134972a 100644
--- a/chromium/components/arc/property/arc_property_bridge.h
+++ b/chromium/components/arc/property/arc_property_bridge.h
@@ -14,7 +14,7 @@
#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/property.mojom.h"
+#include "components/arc/mojom/property.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
index 7f2acfadd53..034cad3c741 100644
--- a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
+++ b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
@@ -9,7 +9,7 @@
#include "ash/public/cpp/tablet_mode_observer.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/rotation_lock.mojom.h"
+#include "components/arc/mojom/rotation_lock.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/arc/session/arc_bridge_host_impl.cc b/chromium/components/arc/session/arc_bridge_host_impl.cc
index 45584862d06..1dd5de99370 100644
--- a/chromium/components/arc/session/arc_bridge_host_impl.cc
+++ b/chromium/components/arc/session/arc_bridge_host_impl.cc
@@ -10,56 +10,56 @@
#include "ash/public/cpp/arc_notifications_host_initializer.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "components/arc/common/accessibility_helper.mojom.h"
-#include "components/arc/common/app.mojom.h"
-#include "components/arc/common/app_permissions.mojom.h"
-#include "components/arc/common/appfuse.mojom.h"
-#include "components/arc/common/audio.mojom.h"
-#include "components/arc/common/auth.mojom.h"
-#include "components/arc/common/backup_settings.mojom.h"
-#include "components/arc/common/bluetooth.mojom.h"
-#include "components/arc/common/boot_phase_monitor.mojom.h"
-#include "components/arc/common/camera.mojom.h"
-#include "components/arc/common/cast_receiver.mojom.h"
-#include "components/arc/common/cert_store.mojom.h"
-#include "components/arc/common/clipboard.mojom.h"
-#include "components/arc/common/crash_collector.mojom.h"
-#include "components/arc/common/disk_quota.mojom.h"
-#include "components/arc/common/enterprise_reporting.mojom.h"
-#include "components/arc/common/file_system.mojom.h"
-#include "components/arc/common/ime.mojom.h"
-#include "components/arc/common/input_method_manager.mojom.h"
-#include "components/arc/common/intent_helper.mojom.h"
-#include "components/arc/common/keymaster.mojom.h"
-#include "components/arc/common/kiosk.mojom.h"
-#include "components/arc/common/lock_screen.mojom.h"
-#include "components/arc/common/media_session.mojom.h"
-#include "components/arc/common/metrics.mojom.h"
-#include "components/arc/common/midis.mojom.h"
-#include "components/arc/common/net.mojom.h"
-#include "components/arc/common/notifications.mojom.h"
-#include "components/arc/common/obb_mounter.mojom.h"
-#include "components/arc/common/oemcrypto.mojom.h"
-#include "components/arc/common/pip.mojom.h"
-#include "components/arc/common/policy.mojom.h"
-#include "components/arc/common/power.mojom.h"
-#include "components/arc/common/print.mojom.h"
-#include "components/arc/common/print_spooler.mojom.h"
-#include "components/arc/common/process.mojom.h"
-#include "components/arc/common/property.mojom.h"
-#include "components/arc/common/rotation_lock.mojom.h"
-#include "components/arc/common/screen_capture.mojom.h"
-#include "components/arc/common/storage_manager.mojom.h"
-#include "components/arc/common/timer.mojom.h"
-#include "components/arc/common/tracing.mojom.h"
-#include "components/arc/common/tts.mojom.h"
-#include "components/arc/common/usb_host.mojom.h"
-#include "components/arc/common/video.mojom.h"
-#include "components/arc/common/voice_interaction_arc_home.mojom.h"
-#include "components/arc/common/voice_interaction_framework.mojom.h"
-#include "components/arc/common/volume_mounter.mojom.h"
-#include "components/arc/common/wake_lock.mojom.h"
-#include "components/arc/common/wallpaper.mojom.h"
+#include "components/arc/mojom/accessibility_helper.mojom.h"
+#include "components/arc/mojom/app.mojom.h"
+#include "components/arc/mojom/app_permissions.mojom.h"
+#include "components/arc/mojom/appfuse.mojom.h"
+#include "components/arc/mojom/audio.mojom.h"
+#include "components/arc/mojom/auth.mojom.h"
+#include "components/arc/mojom/backup_settings.mojom.h"
+#include "components/arc/mojom/bluetooth.mojom.h"
+#include "components/arc/mojom/boot_phase_monitor.mojom.h"
+#include "components/arc/mojom/camera.mojom.h"
+#include "components/arc/mojom/cast_receiver.mojom.h"
+#include "components/arc/mojom/cert_store.mojom.h"
+#include "components/arc/mojom/clipboard.mojom.h"
+#include "components/arc/mojom/crash_collector.mojom.h"
+#include "components/arc/mojom/disk_quota.mojom.h"
+#include "components/arc/mojom/enterprise_reporting.mojom.h"
+#include "components/arc/mojom/file_system.mojom.h"
+#include "components/arc/mojom/ime.mojom.h"
+#include "components/arc/mojom/input_method_manager.mojom.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
+#include "components/arc/mojom/keymaster.mojom.h"
+#include "components/arc/mojom/kiosk.mojom.h"
+#include "components/arc/mojom/lock_screen.mojom.h"
+#include "components/arc/mojom/media_session.mojom.h"
+#include "components/arc/mojom/metrics.mojom.h"
+#include "components/arc/mojom/midis.mojom.h"
+#include "components/arc/mojom/net.mojom.h"
+#include "components/arc/mojom/notifications.mojom.h"
+#include "components/arc/mojom/obb_mounter.mojom.h"
+#include "components/arc/mojom/oemcrypto.mojom.h"
+#include "components/arc/mojom/pip.mojom.h"
+#include "components/arc/mojom/policy.mojom.h"
+#include "components/arc/mojom/power.mojom.h"
+#include "components/arc/mojom/print.mojom.h"
+#include "components/arc/mojom/print_spooler.mojom.h"
+#include "components/arc/mojom/process.mojom.h"
+#include "components/arc/mojom/property.mojom.h"
+#include "components/arc/mojom/rotation_lock.mojom.h"
+#include "components/arc/mojom/screen_capture.mojom.h"
+#include "components/arc/mojom/storage_manager.mojom.h"
+#include "components/arc/mojom/timer.mojom.h"
+#include "components/arc/mojom/tracing.mojom.h"
+#include "components/arc/mojom/tts.mojom.h"
+#include "components/arc/mojom/usb_host.mojom.h"
+#include "components/arc/mojom/video.mojom.h"
+#include "components/arc/mojom/voice_interaction_arc_home.mojom.h"
+#include "components/arc/mojom/voice_interaction_framework.mojom.h"
+#include "components/arc/mojom/volume_mounter.mojom.h"
+#include "components/arc/mojom/wake_lock.mojom.h"
+#include "components/arc/mojom/wallpaper.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/session/mojo_channel.h"
#include "content/public/browser/system_connector.h"
diff --git a/chromium/components/arc/session/arc_bridge_host_impl.h b/chromium/components/arc/session/arc_bridge_host_impl.h
index 0f5868dd50e..901fb37f36e 100644
--- a/chromium/components/arc/session/arc_bridge_host_impl.h
+++ b/chromium/components/arc/session/arc_bridge_host_impl.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/arc_bridge.mojom.h"
+#include "components/arc/mojom/arc_bridge.mojom.h"
#include "components/arc/session/connection_holder.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
diff --git a/chromium/components/arc/session/arc_bridge_service.cc b/chromium/components/arc/session/arc_bridge_service.cc
index 485b0fea947..f7bd98c969c 100644
--- a/chromium/components/arc/session/arc_bridge_service.cc
+++ b/chromium/components/arc/session/arc_bridge_service.cc
@@ -5,56 +5,56 @@
#include "components/arc/session/arc_bridge_service.h"
// These header is necessary for instantiation of ConnectionHolder.
-#include "components/arc/common/accessibility_helper.mojom.h"
-#include "components/arc/common/app.mojom.h"
-#include "components/arc/common/app_permissions.mojom.h"
-#include "components/arc/common/appfuse.mojom.h"
-#include "components/arc/common/arc_bridge.mojom.h"
-#include "components/arc/common/audio.mojom.h"
-#include "components/arc/common/auth.mojom.h"
-#include "components/arc/common/backup_settings.mojom.h"
-#include "components/arc/common/bluetooth.mojom.h"
-#include "components/arc/common/boot_phase_monitor.mojom.h"
-#include "components/arc/common/camera.mojom.h"
-#include "components/arc/common/cast_receiver.mojom.h"
-#include "components/arc/common/cert_store.mojom.h"
-#include "components/arc/common/clipboard.mojom.h"
-#include "components/arc/common/crash_collector.mojom.h"
-#include "components/arc/common/disk_quota.mojom.h"
-#include "components/arc/common/enterprise_reporting.mojom.h"
-#include "components/arc/common/file_system.mojom.h"
-#include "components/arc/common/ime.mojom.h"
-#include "components/arc/common/input_method_manager.mojom.h"
-#include "components/arc/common/intent_helper.mojom.h"
-#include "components/arc/common/keymaster.mojom.h"
-#include "components/arc/common/kiosk.mojom.h"
-#include "components/arc/common/lock_screen.mojom.h"
-#include "components/arc/common/media_session.mojom.h"
-#include "components/arc/common/metrics.mojom.h"
-#include "components/arc/common/midis.mojom.h"
-#include "components/arc/common/net.mojom.h"
-#include "components/arc/common/obb_mounter.mojom.h"
-#include "components/arc/common/oemcrypto.mojom.h"
-#include "components/arc/common/pip.mojom.h"
-#include "components/arc/common/policy.mojom.h"
-#include "components/arc/common/power.mojom.h"
-#include "components/arc/common/print.mojom.h"
-#include "components/arc/common/print_spooler.mojom.h"
-#include "components/arc/common/process.mojom.h"
-#include "components/arc/common/property.mojom.h"
-#include "components/arc/common/rotation_lock.mojom.h"
-#include "components/arc/common/screen_capture.mojom.h"
-#include "components/arc/common/storage_manager.mojom.h"
-#include "components/arc/common/timer.mojom.h"
-#include "components/arc/common/tracing.mojom.h"
-#include "components/arc/common/tts.mojom.h"
-#include "components/arc/common/usb_host.mojom.h"
-#include "components/arc/common/video.mojom.h"
-#include "components/arc/common/voice_interaction_arc_home.mojom.h"
-#include "components/arc/common/voice_interaction_framework.mojom.h"
-#include "components/arc/common/volume_mounter.mojom.h"
-#include "components/arc/common/wake_lock.mojom.h"
-#include "components/arc/common/wallpaper.mojom.h"
+#include "components/arc/mojom/accessibility_helper.mojom.h"
+#include "components/arc/mojom/app.mojom.h"
+#include "components/arc/mojom/app_permissions.mojom.h"
+#include "components/arc/mojom/appfuse.mojom.h"
+#include "components/arc/mojom/arc_bridge.mojom.h"
+#include "components/arc/mojom/audio.mojom.h"
+#include "components/arc/mojom/auth.mojom.h"
+#include "components/arc/mojom/backup_settings.mojom.h"
+#include "components/arc/mojom/bluetooth.mojom.h"
+#include "components/arc/mojom/boot_phase_monitor.mojom.h"
+#include "components/arc/mojom/camera.mojom.h"
+#include "components/arc/mojom/cast_receiver.mojom.h"
+#include "components/arc/mojom/cert_store.mojom.h"
+#include "components/arc/mojom/clipboard.mojom.h"
+#include "components/arc/mojom/crash_collector.mojom.h"
+#include "components/arc/mojom/disk_quota.mojom.h"
+#include "components/arc/mojom/enterprise_reporting.mojom.h"
+#include "components/arc/mojom/file_system.mojom.h"
+#include "components/arc/mojom/ime.mojom.h"
+#include "components/arc/mojom/input_method_manager.mojom.h"
+#include "components/arc/mojom/intent_helper.mojom.h"
+#include "components/arc/mojom/keymaster.mojom.h"
+#include "components/arc/mojom/kiosk.mojom.h"
+#include "components/arc/mojom/lock_screen.mojom.h"
+#include "components/arc/mojom/media_session.mojom.h"
+#include "components/arc/mojom/metrics.mojom.h"
+#include "components/arc/mojom/midis.mojom.h"
+#include "components/arc/mojom/net.mojom.h"
+#include "components/arc/mojom/obb_mounter.mojom.h"
+#include "components/arc/mojom/oemcrypto.mojom.h"
+#include "components/arc/mojom/pip.mojom.h"
+#include "components/arc/mojom/policy.mojom.h"
+#include "components/arc/mojom/power.mojom.h"
+#include "components/arc/mojom/print.mojom.h"
+#include "components/arc/mojom/print_spooler.mojom.h"
+#include "components/arc/mojom/process.mojom.h"
+#include "components/arc/mojom/property.mojom.h"
+#include "components/arc/mojom/rotation_lock.mojom.h"
+#include "components/arc/mojom/screen_capture.mojom.h"
+#include "components/arc/mojom/storage_manager.mojom.h"
+#include "components/arc/mojom/timer.mojom.h"
+#include "components/arc/mojom/tracing.mojom.h"
+#include "components/arc/mojom/tts.mojom.h"
+#include "components/arc/mojom/usb_host.mojom.h"
+#include "components/arc/mojom/video.mojom.h"
+#include "components/arc/mojom/voice_interaction_arc_home.mojom.h"
+#include "components/arc/mojom/voice_interaction_framework.mojom.h"
+#include "components/arc/mojom/volume_mounter.mojom.h"
+#include "components/arc/mojom/wake_lock.mojom.h"
+#include "components/arc/mojom/wallpaper.mojom.h"
namespace arc {
diff --git a/chromium/components/arc/session/arc_bridge_service.h b/chromium/components/arc/session/arc_bridge_service.h
index d3f0f3b4f59..cc0f132ab2f 100644
--- a/chromium/components/arc/session/arc_bridge_service.h
+++ b/chromium/components/arc/session/arc_bridge_service.h
@@ -12,8 +12,8 @@ namespace arc {
namespace mojom {
-// Instead of including components/arc/common/arc_bridge.mojom.h, list all the
-// instance classes here for faster build.
+// Instead of including components/arc/mojom/arc_bridge.mojom.h, list all
+// the instance classes here for faster build.
class AccessibilityHelperHost;
class AccessibilityHelperInstance;
class AppHost;
diff --git a/chromium/components/arc/session/arc_data_remover.cc b/chromium/components/arc/session/arc_data_remover.cc
index c6e99114718..89d76725943 100644
--- a/chromium/components/arc/session/arc_data_remover.cc
+++ b/chromium/components/arc/session/arc_data_remover.cc
@@ -30,7 +30,7 @@ constexpr char kArcRemoveDataUpstartJob[] = "arc_2dremove_2ddata";
ArcDataRemover::ArcDataRemover(PrefService* prefs,
const cryptohome::Identification& cryptohome_id)
- : cryptohome_id_(cryptohome_id), weak_factory_(this) {
+ : cryptohome_id_(cryptohome_id) {
pref_.Init(prefs::kArcDataRemoveRequested, prefs);
}
diff --git a/chromium/components/arc/session/arc_data_remover.h b/chromium/components/arc/session/arc_data_remover.h
index ba4bc456d9b..187e6137ede 100644
--- a/chromium/components/arc/session/arc_data_remover.h
+++ b/chromium/components/arc/session/arc_data_remover.h
@@ -65,7 +65,7 @@ class ArcDataRemover {
// TODO(yusukes): Remove the member variable.
std::string user_id_hash_;
- base::WeakPtrFactory<ArcDataRemover> weak_factory_;
+ base::WeakPtrFactory<ArcDataRemover> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcDataRemover);
};
diff --git a/chromium/components/arc/session/arc_data_remover_unittest.cc b/chromium/components/arc/session/arc_data_remover_unittest.cc
index 75c4d6caffd..51f8851e409 100644
--- a/chromium/components/arc/session/arc_data_remover_unittest.cc
+++ b/chromium/components/arc/session/arc_data_remover_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/dbus_thread_manager.h"
@@ -72,7 +72,7 @@ class ArcDataRemoverTest : public testing::Test {
private:
TestingPrefServiceSimple prefs_;
const cryptohome::Identification cryptohome_id_{EmptyAccountId()};
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<TestUpstartClient> test_upstart_client_;
DISALLOW_COPY_AND_ASSIGN(ArcDataRemoverTest);
diff --git a/chromium/components/arc/session/arc_session_impl.cc b/chromium/components/arc/session/arc_session_impl.cc
index 04efc71f7db..0a45db110aa 100644
--- a/chromium/components/arc/session/arc_session_impl.cc
+++ b/chromium/components/arc/session/arc_session_impl.cc
@@ -145,7 +145,7 @@ class ArcSessionDelegateImpl : public ArcSessionImpl::Delegate {
const version_info::Channel channel_;
// WeakPtrFactory to use callbacks.
- base::WeakPtrFactory<ArcSessionDelegateImpl> weak_factory_;
+ base::WeakPtrFactory<ArcSessionDelegateImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcSessionDelegateImpl);
};
@@ -156,12 +156,11 @@ ArcSessionDelegateImpl::ArcSessionDelegateImpl(
version_info::Channel channel)
: arc_bridge_service_(arc_bridge_service),
default_scale_factor_retriever_(retriever),
- channel_(channel),
- weak_factory_(this) {}
+ channel_(channel) {}
void ArcSessionDelegateImpl::CreateSocket(CreateSocketCallback callback) {
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(&ArcSessionDelegateImpl::CreateSocketInternal),
std::move(callback));
}
@@ -181,8 +180,8 @@ base::ScopedFD ArcSessionDelegateImpl::ConnectMojo(
// For production, |socket_fd| passed from session_manager is either a valid
// socket or a valid file descriptor (/dev/null). For testing, |socket_fd|
// might be invalid.
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(&ArcSessionDelegateImpl::ConnectMojoInternal,
std::move(socket_fd), std::move(cancel_fd)),
base::BindOnce(&ArcSessionDelegateImpl::OnMojoConnected,
@@ -201,8 +200,8 @@ void ArcSessionDelegateImpl::GetLcdDensity(GetLcdDensityCallback callback) {
void ArcSessionDelegateImpl::GetFreeDiskSpace(
GetFreeDiskSpaceCallback callback) {
- PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
+ PostTaskAndReplyWithResult(
+ FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
base::FilePath("/home")),
std::move(callback));
@@ -337,9 +336,7 @@ std::unique_ptr<ArcSessionImpl::Delegate> ArcSessionImpl::CreateDelegate(
}
ArcSessionImpl::ArcSessionImpl(std::unique_ptr<Delegate> delegate)
- : delegate_(std::move(delegate)),
- client_(ArcClientAdapter::Create()),
- weak_factory_(this) {
+ : delegate_(std::move(delegate)), client_(ArcClientAdapter::Create()) {
DCHECK(client_);
client_->AddObserver(this);
}
@@ -368,7 +365,7 @@ void ArcSessionImpl::OnLcdDensity(int32_t lcd_density) {
state_ = State::STARTING_MINI_INSTANCE;
StartArcMiniContainerRequest request;
request.set_native_bridge_experiment(
- base::FeatureList::IsEnabled(arc::kNativeBridgeExperimentFeature));
+ base::FeatureList::IsEnabled(arc::kNativeBridgeToggleFeature));
request.set_arc_file_picker_experiment(
base::FeatureList::IsEnabled(arc::kFilePickerExperimentFeature));
// Enable Custom Tabs only on Dev and Cannary, and only when Mash is enabled.
diff --git a/chromium/components/arc/session/arc_session_impl.h b/chromium/components/arc/session/arc_session_impl.h
index 9742edf246e..14c7078ac8c 100644
--- a/chromium/components/arc/session/arc_session_impl.h
+++ b/chromium/components/arc/session/arc_session_impl.h
@@ -256,7 +256,7 @@ class ArcSessionImpl : public ArcSession, public ArcClientAdapter::Observer {
std::unique_ptr<mojom::ArcBridgeHost> arc_bridge_host_;
// WeakPtrFactory to use callbacks.
- base::WeakPtrFactory<ArcSessionImpl> weak_factory_;
+ base::WeakPtrFactory<ArcSessionImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcSessionImpl);
};
diff --git a/chromium/components/arc/session/arc_session_impl_unittest.cc b/chromium/components/arc/session/arc_session_impl_unittest.cc
index 83f7951c037..130bb566429 100644
--- a/chromium/components/arc/session/arc_session_impl_unittest.cc
+++ b/chromium/components/arc/session/arc_session_impl_unittest.cc
@@ -13,7 +13,7 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
@@ -224,7 +224,7 @@ class ArcSessionImplTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
user_manager::ScopedUserManager scoped_user_manager_{
std::make_unique<user_manager::FakeUserManager>()};
diff --git a/chromium/components/arc/session/arc_session_runner.cc b/chromium/components/arc/session/arc_session_runner.cc
index fe656884a18..b02c6586f4e 100644
--- a/chromium/components/arc/session/arc_session_runner.cc
+++ b/chromium/components/arc/session/arc_session_runner.cc
@@ -120,8 +120,7 @@ bool IsRequestAllowed(const base::Optional<ArcInstanceMode>& current_mode,
ArcSessionRunner::ArcSessionRunner(const ArcSessionFactory& factory)
: restart_delay_(kDefaultRestartDelay),
restart_after_crash_count_(0),
- factory_(factory),
- weak_ptr_factory_(this) {}
+ factory_(factory) {}
ArcSessionRunner::~ArcSessionRunner() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chromium/components/arc/session/arc_session_runner.h b/chromium/components/arc/session/arc_session_runner.h
index 42e0c18f5d1..fcd005eb279 100644
--- a/chromium/components/arc/session/arc_session_runner.h
+++ b/chromium/components/arc/session/arc_session_runner.h
@@ -147,7 +147,7 @@ class ArcSessionRunner : public ArcSession::Observer {
std::string user_id_hash_;
// WeakPtrFactory to use callbacks.
- base::WeakPtrFactory<ArcSessionRunner> weak_ptr_factory_;
+ base::WeakPtrFactory<ArcSessionRunner> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcSessionRunner);
};
diff --git a/chromium/components/arc/session/arc_session_runner_unittest.cc b/chromium/components/arc/session/arc_session_runner_unittest.cc
index dcea0d3be8e..f8ae89159c1 100644
--- a/chromium/components/arc/session/arc_session_runner_unittest.cc
+++ b/chromium/components/arc/session/arc_session_runner_unittest.cc
@@ -13,7 +13,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "components/arc/arc_util.h"
#include "components/arc/session/arc_session_runner.h"
@@ -56,8 +56,7 @@ class ArcSessionRunnerTest : public testing::Test,
public ArcSessionRunner::Observer {
public:
ArcSessionRunnerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
void SetUp() override {
chromeos::SessionManagerClient::InitializeFakeInMemory();
@@ -137,7 +136,7 @@ class ArcSessionRunnerTest : public testing::Test,
bool stopped_called_;
bool restarting_called_;
std::unique_ptr<ArcSessionRunner> arc_session_runner_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(ArcSessionRunnerTest);
};
diff --git a/chromium/components/arc/session/arc_vm_client_adapter.cc b/chromium/components/arc/session/arc_vm_client_adapter.cc
index 2cd1ba715f6..caae3723ce9 100644
--- a/chromium/components/arc/session/arc_vm_client_adapter.cc
+++ b/chromium/components/arc/session/arc_vm_client_adapter.cc
@@ -9,50 +9,22 @@
#include <vector>
#include "base/bind.h"
-#include "base/guid.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
-#include "base/system/sys_info.h"
+#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
-#include "chromeos/dbus/concierge_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/debug_daemon_client.h"
+#include "chromeos/dbus/login_manager/arc.pb.h"
+#include "chromeos/dbus/upstart/upstart_client.h"
#include "components/arc/arc_util.h"
namespace arc {
-namespace {
-
-constexpr char kHomeDirectory[] = "/home";
-constexpr char kKernelPath[] = "/opt/google/vms/android/vmlinux";
-constexpr char kRootFsPath[] = "/opt/google/vms/android/system.raw.img";
-constexpr char kVendorImagePath[] = "/opt/google/vms/android/vendor.raw.img";
-
-chromeos::ConciergeClient* GetConciergeClient() {
- return chromeos::DBusThreadManager::Get()->GetConciergeClient();
-}
-
-std::vector<std::string> CreateKernelParams() {
- // TODO(cmtm): Generate the same parameters as arc-setup based on both
- // StartArcMiniContainerRequest and UpgradeArcContainerRequest.
-
- // TODO(yusukes): Enable SELinux.
- std::vector<std::string> params{
- {"androidboot.selinux=permissive"},
- {"androidboot.hardware=bertha"},
- {"androidboot.debuggable=1"},
- {"androidboot.native_bridge=libhoudini.so"},
- };
- return params;
-}
-
-} // namespace
-
class ArcVmClientAdapter : public ArcClientAdapter {
public:
- ArcVmClientAdapter() : weak_factory_(this) {}
+ ArcVmClientAdapter() {}
~ArcVmClientAdapter() override = default;
// ArcClientAdapter overrides:
@@ -60,26 +32,43 @@ class ArcVmClientAdapter : public ArcClientAdapter {
chromeos::VoidDBusMethodCallback callback) override {
// TODO(yusukes): Support mini ARC.
VLOG(2) << "Mini ARCVM instance is not supported.";
+ // Save the lcd density and auto update mode for the later call to
+ // UpgradeArc.
+ lcd_density_ = request.lcd_density();
+ if (request.play_store_auto_update() ==
+ login_manager::
+ StartArcMiniContainerRequest_PlayStoreAutoUpdate_AUTO_UPDATE_ON) {
+ play_store_auto_update_ = true;
+ } else if (
+ request.play_store_auto_update() ==
+ login_manager::
+ StartArcMiniContainerRequest_PlayStoreAutoUpdate_AUTO_UPDATE_OFF) {
+ play_store_auto_update_ = false;
+ }
base::PostTask(FROM_HERE, base::BindOnce(std::move(callback), true));
}
void UpgradeArc(const UpgradeArcContainerRequest& request,
chromeos::VoidDBusMethodCallback callback) override {
- VLOG(1) << "Starting Concierge service";
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->StartConcierge(
- base::BindOnce(&ArcVmClientAdapter::OnConciergeStarted,
- weak_factory_.GetWeakPtr(), std::move(callback),
- CreateKernelParams()));
+ VLOG(1) << "Starting ARCVM";
+ std::vector<std::string> env{
+ {"USER_ID_HASH=" + user_id_hash_},
+ {base::StringPrintf("ARC_LCD_DENSITY=%d", lcd_density_)},
+ };
+ if (play_store_auto_update_) {
+ env.push_back(base::StringPrintf("PLAY_STORE_AUTO_UPDATE=%d",
+ *play_store_auto_update_));
+ }
+ chromeos::UpstartClient::Get()->StartJob("arcvm", env, std::move(callback));
}
void StopArcInstance() override {
VLOG(1) << "Stopping arcvm";
- vm_tools::concierge::StopVmRequest request;
- request.set_name(kArcVmName);
- request.set_owner_id(user_id_hash_);
- GetConciergeClient()->StopVm(
- request, base::BindOnce(&ArcVmClientAdapter::OnVmStopped,
- weak_factory_.GetWeakPtr()));
+ std::vector<std::string> env{{"USER_ID_HASH=" + user_id_hash_}};
+ chromeos::UpstartClient::Get()->StopJob(
+ "arcvm", env,
+ base::BindOnce(&ArcVmClientAdapter::OnVmStopped,
+ weak_factory_.GetWeakPtr()));
}
void SetUserIdHashForProfile(const std::string& hash) override {
@@ -96,147 +85,21 @@ class ArcVmClientAdapter : public ArcClientAdapter {
observer.ArcInstanceStopped();
}
- void OnConciergeStarted(chromeos::VoidDBusMethodCallback callback,
- std::vector<std::string> params,
- bool success) {
- if (!success) {
- LOG(ERROR) << "Failed to start Concierge service for arcvm";
- std::move(callback).Run(false);
- return;
- }
- VLOG(1) << "Concierge service started for arcvm.";
-
- // TODO(cmtm): Export host-side /data to the VM, and remove the call.
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
- base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
- base::FilePath(kHomeDirectory)),
- base::BindOnce(&ArcVmClientAdapter::CreateDiskImageAfterSizeCheck,
- weak_factory_.GetWeakPtr(), std::move(callback),
- std::move(params)));
- }
-
- // TODO(cmtm): Export host-side /data to the VM, and remove the function.
- void CreateDiskImageAfterSizeCheck(chromeos::VoidDBusMethodCallback callback,
- std::vector<std::string> params,
- int64_t free_disk_bytes) {
- VLOG(2) << "Got free disk size: " << free_disk_bytes;
- if (user_id_hash_.empty()) {
- LOG(ERROR) << "User ID hash is not set";
- std::move(callback).Run(false);
- return;
- }
-
- vm_tools::concierge::CreateDiskImageRequest request;
- request.set_cryptohome_id(user_id_hash_);
- request.set_disk_path(kArcVmName);
- // The type of disk image to be created.
- request.set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
- request.set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT);
- // The logical size of the new disk image, in bytes.
- request.set_disk_size(free_disk_bytes / 2);
-
- GetConciergeClient()->CreateDiskImage(
- std::move(request),
- base::BindOnce(&ArcVmClientAdapter::OnDiskImageCreated,
- weak_factory_.GetWeakPtr(), std::move(callback),
- std::move(params)));
- }
-
- void OnDiskImageCreated(
- chromeos::VoidDBusMethodCallback callback,
- std::vector<std::string> params,
- base::Optional<vm_tools::concierge::CreateDiskImageResponse> reply) {
- if (!reply.has_value()) {
- LOG(ERROR) << "Failed to create disk image. Empty response.";
- std::move(callback).Run(false);
- return;
- }
-
- const vm_tools::concierge::CreateDiskImageResponse& response =
- reply.value();
- if (response.status() != vm_tools::concierge::DISK_STATUS_EXISTS &&
- response.status() != vm_tools::concierge::DISK_STATUS_CREATED) {
- LOG(ERROR) << "Failed to create disk image: "
- << response.failure_reason();
- std::move(callback).Run(false);
- return;
- }
- VLOG(1) << "Disk image for arcvm created. status=" << response.status()
- << ", disk=" << response.disk_path();
-
- DCHECK(!user_id_hash_.empty());
- vm_tools::concierge::StartArcVmRequest request;
- request.set_name(kArcVmName);
- request.set_owner_id(user_id_hash_);
-
- request.add_params("root=/dev/vda");
- // TODO(b/135229848): Use ro unless rw is requested.
- request.add_params("rw");
- request.add_params("init=/init");
- for (auto& param : params)
- request.add_params(std::move(param));
-
- vm_tools::concierge::VirtualMachineSpec* vm = request.mutable_vm();
- vm->set_kernel(kKernelPath);
- // Add / as /dev/vda.
- vm->set_rootfs(kRootFsPath);
-
- // Add /data as /dev/vdb.
- vm_tools::concierge::DiskImage* disk_image = request.add_disks();
- disk_image->set_path(response.disk_path());
- disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
- disk_image->set_writable(true);
- disk_image->set_do_mount(true);
- // Add /vendor as /dev/vdc.
- disk_image = request.add_disks();
- disk_image->set_path(kVendorImagePath);
- disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
- disk_image->set_writable(false);
- disk_image->set_do_mount(true);
-
- GetConciergeClient()->StartArcVm(
- request,
- base::BindOnce(&ArcVmClientAdapter::OnVmStarted,
- weak_factory_.GetWeakPtr(), std::move(callback)));
- }
-
- void OnVmStarted(chromeos::VoidDBusMethodCallback callback,
- base::Optional<vm_tools::concierge::StartVmResponse> reply) {
- if (!reply.has_value()) {
- LOG(ERROR) << "Failed to start arcvm. Empty response.";
- std::move(callback).Run(false);
- return;
- }
-
- const vm_tools::concierge::StartVmResponse& response = reply.value();
- if (response.status() != vm_tools::concierge::VM_STATUS_RUNNING) {
- LOG(ERROR) << "Failed to start arcvm: status=" << response.status()
- << ", reason=" << response.failure_reason();
- std::move(callback).Run(false);
- return;
- }
- VLOG(1) << "arcvm started.";
- std::move(callback).Run(true);
- // TODO(yusukes): Share folders like Downloads/ with ARCVM.
- }
-
- void OnVmStopped(base::Optional<vm_tools::concierge::StopVmResponse> reply) {
- if (!reply.has_value()) {
- LOG(ERROR) << "Failed to stop arcvm. Empty response.";
- } else {
- const vm_tools::concierge::StopVmResponse& response = reply.value();
- if (!response.success())
- LOG(ERROR) << "Failed to stop arcvm: " << response.failure_reason();
- }
+ void OnVmStopped(bool result) {
+ if (!result)
+ LOG(ERROR) << "Failed to stop arcvm.";
OnArcInstanceStopped();
}
// A hash of the primary profile user ID.
std::string user_id_hash_;
+ int32_t lcd_density_;
+
+ base::Optional<bool> play_store_auto_update_;
+
// For callbacks.
- base::WeakPtrFactory<ArcVmClientAdapter> weak_factory_;
+ base::WeakPtrFactory<ArcVmClientAdapter> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapter);
};
diff --git a/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc b/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc
deleted file mode 100644
index a957206e046..00000000000
--- a/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ /dev/null
@@ -1,303 +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 "components/arc/session/arc_vm_client_adapter.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "base/task/post_task.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_concierge_client.h"
-#include "chromeos/dbus/fake_debug_daemon_client.h"
-#include "chromeos/dbus/login_manager/arc.pb.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace arc {
-namespace {
-
-constexpr const char kUserIdHash[] = "this_is_a_valid_user_id_hash";
-
-// A debugd client that can fail to start Concierge.
-// TODO(yusukes): Merge the feature to FakeDebugDaemonClient.
-class TestDebugDaemonClient : public chromeos::FakeDebugDaemonClient {
- public:
- TestDebugDaemonClient() = default;
- ~TestDebugDaemonClient() override = default;
-
- void StartConcierge(ConciergeCallback callback) override {
- start_concierge_called_ = true;
- std::move(callback).Run(start_concierge_result_);
- }
-
- bool start_concierge_called() const { return start_concierge_called_; }
- void set_start_concierge_result(bool result) {
- start_concierge_result_ = result;
- }
-
- private:
- bool start_concierge_called_ = false;
- bool start_concierge_result_ = true;
-
- DISALLOW_COPY_AND_ASSIGN(TestDebugDaemonClient);
-};
-
-// A concierge that remembers the parameter passed to StartArcVm.
-// TODO(yusukes): Merge the feature to FakeConciergeClient.
-class TestConciergeClient : public chromeos::FakeConciergeClient {
- public:
- TestConciergeClient() = default;
- ~TestConciergeClient() override = default;
-
- void StartArcVm(
- const vm_tools::concierge::StartArcVmRequest& request,
- chromeos::DBusMethodCallback<vm_tools::concierge::StartVmResponse>
- callback) override {
- start_arc_vm_request_ = request;
- chromeos::FakeConciergeClient::StartArcVm(request, std::move(callback));
- }
-
- const vm_tools::concierge::StartArcVmRequest& start_arc_vm_request() const {
- return start_arc_vm_request_;
- }
-
- private:
- vm_tools::concierge::StartArcVmRequest start_arc_vm_request_;
-
- DISALLOW_COPY_AND_ASSIGN(TestConciergeClient);
-};
-
-class ArcVmClientAdapterTest : public testing::Test,
- public ArcClientAdapter::Observer {
- public:
- ArcVmClientAdapterTest() {
- // Create and set new fake clients every time to reset clients' status.
- chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
- std::make_unique<TestDebugDaemonClient>());
- chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
- std::make_unique<TestConciergeClient>());
- }
-
- ~ArcVmClientAdapterTest() override {
- chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
- nullptr);
- chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
- nullptr);
- }
-
- void SetUp() override {
- run_loop_ = std::make_unique<base::RunLoop>();
- adapter_ = CreateArcVmClientAdapter();
- arc_instance_stopped_called_ = false;
- adapter_->AddObserver(this);
-
- // The fake client returns VM_STATUS_STARTING by default. Change it
- // to VM_STATUS_RUNNING which is used by ARCVM.
- vm_tools::concierge::StartVmResponse start_vm_response;
- start_vm_response.set_status(vm_tools::concierge::VM_STATUS_RUNNING);
- GetTestConciergeClient()->set_start_vm_response(start_vm_response);
- }
-
- void TearDown() override {
- adapter_->RemoveObserver(this);
- adapter_.reset();
- run_loop_.reset();
- }
-
- // ArcClientAdapter::Observer:
- void ArcInstanceStopped() override {
- arc_instance_stopped_called_ = true;
- run_loop()->Quit();
- }
-
- void ExpectTrueThenQuit(bool result) {
- EXPECT_TRUE(result);
- run_loop()->Quit();
- }
-
- void ExpectFalseThenQuit(bool result) {
- EXPECT_FALSE(result);
- run_loop()->Quit();
- }
-
- protected:
- bool GetStartConciergeCalled() {
- return GetTestDebugDaemonClient()->start_concierge_called();
- }
-
- void SetStartConciergeResponse(bool response) {
- GetTestDebugDaemonClient()->set_start_concierge_result(response);
- }
-
- void SetValidUserIdHash() { adapter()->SetUserIdHashForProfile(kUserIdHash); }
-
- void RestartRunLoop() { run_loop_ = std::make_unique<base::RunLoop>(); }
-
- base::RunLoop* run_loop() { return run_loop_.get(); }
- ArcClientAdapter* adapter() { return adapter_.get(); }
- bool arc_instance_stopped_called() const {
- return arc_instance_stopped_called_;
- }
- TestConciergeClient* GetTestConciergeClient() {
- return static_cast<TestConciergeClient*>(
- chromeos::DBusThreadManager::Get()->GetConciergeClient());
- }
-
- private:
- TestDebugDaemonClient* GetTestDebugDaemonClient() {
- return static_cast<TestDebugDaemonClient*>(
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient());
- }
-
- std::unique_ptr<base::RunLoop> run_loop_;
- std::unique_ptr<ArcClientAdapter> adapter_;
- bool arc_instance_stopped_called_;
-
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
-
- DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapterTest);
-};
-
-// Tests that SetUserIdHashForProfile() doesn't crash.
-TEST_F(ArcVmClientAdapterTest, SetUserIdHashForProfile) {
- adapter()->SetUserIdHashForProfile("deadbeef");
-}
-
-// Tests that StartMiniArc() always succeeds.
-TEST_F(ArcVmClientAdapterTest, StartMiniArc) {
- StartArcMiniContainerRequest req;
- adapter()->StartMiniArc(
- req, base::BindOnce(&ArcVmClientAdapterTest::ExpectTrueThenQuit,
- base::Unretained(this)));
- run_loop()->Run();
- // Also confirm that no VM is started. ARCVM doesn't support mini ARC.
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
-}
-
-// Tests that StopArcInstance() notifies the observer.
-TEST_F(ArcVmClientAdapterTest, StopArcInstance) {
- adapter()->StopArcInstance();
- run_loop()->Run();
- EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
- EXPECT_TRUE(arc_instance_stopped_called());
-}
-
-// Tests that UpgradeArc() handles StartConcierge() failures properly. This test
-// inherits ArcVmClientAdapterTest because it uses its own DebugDaemonClient
-// instead of the default one for testing.
-TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartConciergeFailure) {
- SetValidUserIdHash();
- // Inject failure to StartConcierge().
- SetStartConciergeResponse(false);
- UpgradeArcContainerRequest req;
- adapter()->UpgradeArc(
- req, base::BindOnce(&ArcVmClientAdapterTest::ExpectFalseThenQuit,
- base::Unretained(this)));
- run_loop()->Run();
- EXPECT_TRUE(GetStartConciergeCalled());
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
-
- // Try to stop the VM.
- RestartRunLoop();
- adapter()->StopArcInstance();
- run_loop()->Run();
- EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
- EXPECT_TRUE(arc_instance_stopped_called());
-}
-
-// Tests that "no user ID hash" failure is handled properly.
-TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoUserId) {
- // Don't call SetValidUserIdHash(). Note that we cannot call StartArcVm()
- // without a valid ID.
- UpgradeArcContainerRequest req;
- adapter()->UpgradeArc(
- req, base::BindOnce(&ArcVmClientAdapterTest::ExpectFalseThenQuit,
- base::Unretained(this)));
- run_loop()->Run();
- EXPECT_TRUE(GetStartConciergeCalled());
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
-
- // Try to stop the VM.
- RestartRunLoop();
- adapter()->StopArcInstance();
- run_loop()->Run();
- EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
- EXPECT_TRUE(arc_instance_stopped_called());
-}
-
-// Tests that StartArcVm() failure is handled properly.
-TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmFailure) {
- SetValidUserIdHash();
- // Inject failure to StartArcVm().
- vm_tools::concierge::StartVmResponse start_vm_response;
- start_vm_response.set_status(vm_tools::concierge::VM_STATUS_UNKNOWN);
- GetTestConciergeClient()->set_start_vm_response(start_vm_response);
-
- UpgradeArcContainerRequest req;
- adapter()->UpgradeArc(
- req, base::BindOnce(&ArcVmClientAdapterTest::ExpectFalseThenQuit,
- base::Unretained(this)));
- run_loop()->Run();
- EXPECT_TRUE(GetStartConciergeCalled());
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
-
- // Try to stop the VM.
- RestartRunLoop();
- adapter()->StopArcInstance();
- run_loop()->Run();
- EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
- EXPECT_TRUE(arc_instance_stopped_called());
-}
-
-// Tests that successful StartArcVm() call is handled properly.
-TEST_F(ArcVmClientAdapterTest, UpgradeArc_Success) {
- SetValidUserIdHash();
- UpgradeArcContainerRequest req;
- adapter()->UpgradeArc(
- req, base::BindOnce(&ArcVmClientAdapterTest::ExpectTrueThenQuit,
- base::Unretained(this)));
- run_loop()->Run();
- EXPECT_TRUE(GetStartConciergeCalled());
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
-
- // Try to stop the VM.
- RestartRunLoop();
- adapter()->StopArcInstance();
- run_loop()->Run();
- EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
- EXPECT_TRUE(arc_instance_stopped_called());
-}
-
-// Tests that StartArcVm() is called with valid parameters.
-TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmParams) {
- SetValidUserIdHash();
- UpgradeArcContainerRequest req;
- adapter()->UpgradeArc(
- req, base::BindOnce(&ArcVmClientAdapterTest::ExpectTrueThenQuit,
- base::Unretained(this)));
- run_loop()->Run();
- ASSERT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
-
- // Verify parameters
- const auto& params = GetTestConciergeClient()->start_arc_vm_request();
- EXPECT_EQ("arcvm", params.name());
- EXPECT_EQ(kUserIdHash, params.owner_id());
- EXPECT_FALSE(params.vm().kernel().empty());
- // Make sure system.raw.img is passed.
- EXPECT_FALSE(params.vm().rootfs().empty());
- // Make sure vendor.raw.img is passed.
- EXPECT_LE(1, params.disks_size());
- EXPECT_LT(0, params.params_size());
-}
-
-} // namespace
-} // namespace arc
diff --git a/chromium/components/arc/session/connection_holder.h b/chromium/components/arc/session/connection_holder.h
index d7dd71a7a11..74763701f9b 100644
--- a/chromium/components/arc/session/connection_holder.h
+++ b/chromium/components/arc/session/connection_holder.h
@@ -63,7 +63,7 @@ template <typename InstanceType, typename HostType>
class ConnectionHolderImpl {
public:
explicit ConnectionHolderImpl(ConnectionNotifier* connection_notifier)
- : connection_notifier_(connection_notifier), weak_ptr_factory_(this) {}
+ : connection_notifier_(connection_notifier) {}
InstanceType* instance() { return IsConnected() ? instance_ : nullptr; }
uint32_t instance_version() const {
@@ -174,7 +174,7 @@ class ConnectionHolderImpl {
// Created when both |instance_| and |host_| ptr are set.
std::unique_ptr<mojo::Binding<HostType>> binding_;
- base::WeakPtrFactory<ConnectionHolderImpl> weak_ptr_factory_;
+ base::WeakPtrFactory<ConnectionHolderImpl> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ConnectionHolderImpl);
};
diff --git a/chromium/components/arc/storage_manager/arc_storage_manager.h b/chromium/components/arc/storage_manager/arc_storage_manager.h
index ccad8538b92..e1002a3535f 100644
--- a/chromium/components/arc/storage_manager/arc_storage_manager.h
+++ b/chromium/components/arc/storage_manager/arc_storage_manager.h
@@ -9,7 +9,7 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "components/arc/common/storage_manager.mojom.h"
+#include "components/arc/mojom/storage_manager.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
diff --git a/chromium/components/arc/timer/OWNERS b/chromium/components/arc/timer/OWNERS
index ef5cf841917..012a33c0b1c 100644
--- a/chromium/components/arc/timer/OWNERS
+++ b/chromium/components/arc/timer/OWNERS
@@ -1,3 +1,3 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/timer/arc_timer_bridge.cc b/chromium/components/arc/timer/arc_timer_bridge.cc
index 5f327b7a424..091b2ff9f56 100644
--- a/chromium/components/arc/timer/arc_timer_bridge.cc
+++ b/chromium/components/arc/timer/arc_timer_bridge.cc
@@ -17,7 +17,7 @@
#include "components/arc/arc_service_manager.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/timer/arc_timer_bridge.h"
-#include "components/arc/timer/arc_timer_struct_traits.h"
+#include "components/arc/timer/arc_timer_mojom_traits.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -100,9 +100,7 @@ ArcTimerBridge* ArcTimerBridge::GetForBrowserContextForTesting(
ArcTimerBridge::ArcTimerBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service),
- binding_(this),
- weak_ptr_factory_(this) {
+ : arc_bridge_service_(bridge_service), binding_(this) {
arc_bridge_service_->timer()->SetHost(this);
arc_bridge_service_->timer()->AddObserver(this);
}
diff --git a/chromium/components/arc/timer/arc_timer_bridge.h b/chromium/components/arc/timer/arc_timer_bridge.h
index 7657e36e0aa..f67c7d4d461 100644
--- a/chromium/components/arc/timer/arc_timer_bridge.h
+++ b/chromium/components/arc/timer/arc_timer_bridge.h
@@ -15,7 +15,7 @@
#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
-#include "components/arc/common/timer.mojom.h"
+#include "components/arc/mojom/timer.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -87,7 +87,7 @@ class ArcTimerBridge : public KeyedService,
mojo::Binding<mojom::TimerHost> binding_;
- base::WeakPtrFactory<ArcTimerBridge> weak_ptr_factory_;
+ base::WeakPtrFactory<ArcTimerBridge> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcTimerBridge);
};
diff --git a/chromium/components/arc/timer/arc_timer_bridge_unittest.cc b/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
index f0b6ecb44c8..0d0a485c313 100644
--- a/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
+++ b/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
@@ -17,16 +17,16 @@
#include "base/time/time.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/arc/arc_service_manager.h"
-#include "components/arc/common/timer.mojom.h"
+#include "components/arc/mojom/timer.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/session/connection_holder.h"
#include "components/arc/test/connection_holder_util.h"
#include "components/arc/test/fake_timer_instance.h"
#include "components/arc/test/test_browser_context.h"
#include "components/arc/timer/arc_timer_bridge.h"
-#include "components/arc/timer/arc_timer_struct_traits.h"
+#include "components/arc/timer/arc_timer_mojom_traits.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -89,7 +89,7 @@ class ArcTimerStore {
class ArcTimerTest : public testing::Test {
public:
ArcTimerTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
+ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {
chromeos::PowerManagerClient::InitializeFake();
timer_bridge_ = ArcTimerBridge::GetForBrowserContextForTesting(&context_);
// This results in ArcTimerBridge::OnInstanceReady being called.
@@ -125,7 +125,7 @@ class ArcTimerTest : public testing::Test {
bool StoreReadFds(const std::vector<clockid_t> clocks,
std::vector<base::ScopedFD> read_fds);
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
ArcServiceManager arc_service_manager_;
TestBrowserContext context_;
FakeTimerInstance timer_instance_;
diff --git a/chromium/components/arc/timer/arc_timer_struct_traits.cc b/chromium/components/arc/timer/arc_timer_mojom_traits.cc
index 77c37ae8eff..c6360545edc 100644
--- a/chromium/components/arc/timer/arc_timer_struct_traits.cc
+++ b/chromium/components/arc/timer/arc_timer_mojom_traits.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 "components/arc/timer/arc_timer_struct_traits.h"
+#include "components/arc/timer/arc_timer_mojom_traits.h"
#include <utility>
diff --git a/chromium/components/arc/timer/arc_timer_struct_traits.h b/chromium/components/arc/timer/arc_timer_mojom_traits.h
index 40adac5a39c..3ab26b086f4 100644
--- a/chromium/components/arc/timer/arc_timer_struct_traits.h
+++ b/chromium/components/arc/timer/arc_timer_mojom_traits.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 COMPONENTS_ARC_TIMER_ARC_TIMER_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_TIMER_ARC_TIMER_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_TIMER_ARC_TIMER_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_TIMER_ARC_TIMER_MOJOM_TRAITS_H_
#include <time.h>
-#include "components/arc/common/timer.mojom.h"
+#include "components/arc/mojom/timer.mojom.h"
namespace mojo {
@@ -19,4 +19,4 @@ struct EnumTraits<arc::mojom::ClockId, clockid_t> {
} // namespace mojo
-#endif // COMPONENTS_ARC_TIMER_ARC_TIMER_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_TIMER_ARC_TIMER_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/usb/usb_host_bridge.cc b/chromium/components/arc/usb/usb_host_bridge.cc
index c0c12d8894f..49a2c88ea11 100644
--- a/chromium/components/arc/usb/usb_host_bridge.cc
+++ b/chromium/components/arc/usb/usb_host_bridge.cc
@@ -194,6 +194,9 @@ void ArcUsbHostBridge::GetDeviceInfo(const std::string& guid,
device::mojom::UsbDeviceInfoPtr info = iter->second->Clone();
// b/69295049 the other side doesn't like optional strings.
+ info->manufacturer_name = info->manufacturer_name.value_or(base::string16());
+ info->product_name = info->product_name.value_or(base::string16());
+ info->serial_number = info->serial_number.value_or(base::string16());
for (const device::mojom::UsbConfigurationInfoPtr& cfg :
info->configurations) {
cfg->configuration_name =
@@ -214,19 +217,18 @@ void ArcUsbHostBridge::OnConnectionReady() {
if (delegate_)
delegate_->AttachDevicesToArcVm();
- // Request UsbDeviceManagerPtr from DeviceService.
- content::GetSystemConnector()->BindInterface(
- device::mojom::kServiceName, mojo::MakeRequest(&usb_manager_));
- usb_manager_.set_connection_error_handler(
+ // Receive mojo::Remote<UsbDeviceManager> from DeviceService.
+ content::GetSystemConnector()->Connect(
+ device::mojom::kServiceName, usb_manager_.BindNewPipeAndPassReceiver());
+ usb_manager_.set_disconnect_handler(
base::BindOnce(&ArcUsbHostBridge::Disconnect, base::Unretained(this)));
// Listen for added/removed device events.
- DCHECK(!client_binding_);
- device::mojom::UsbDeviceManagerClientAssociatedPtrInfo client;
- client_binding_.Bind(mojo::MakeRequest(&client));
+ DCHECK(!client_receiver_.is_bound());
usb_manager_->EnumerateDevicesAndSetClient(
- std::move(client), base::BindOnce(&ArcUsbHostBridge::InitDeviceList,
- weak_factory_.GetWeakPtr()));
+ client_receiver_.BindNewEndpointAndPassRemote(),
+ base::BindOnce(&ArcUsbHostBridge::InitDeviceList,
+ weak_factory_.GetWeakPtr()));
}
void ArcUsbHostBridge::OnConnectionClosed() {
@@ -327,7 +329,7 @@ void ArcUsbHostBridge::Disconnect() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
usb_manager_.reset();
- client_binding_.Close();
+ client_receiver_.reset();
devices_.clear();
}
diff --git a/chromium/components/arc/usb/usb_host_bridge.h b/chromium/components/arc/usb/usb_host_bridge.h
index 265e06064ce..8082b97470e 100644
--- a/chromium/components/arc/usb/usb_host_bridge.h
+++ b/chromium/components/arc/usb/usb_host_bridge.h
@@ -12,10 +12,11 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
-#include "components/arc/common/usb_host.mojom.h"
+#include "components/arc/mojom/usb_host.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
#include "services/device/public/mojom/usb_manager_client.mojom.h"
@@ -110,9 +111,9 @@ class ArcUsbHostBridge : public KeyedService,
mojom::UsbHostHostPtr usb_host_ptr_;
// Connection to the DeviceService for usb manager.
- device::mojom::UsbDeviceManagerPtr usb_manager_;
- mojo::AssociatedBinding<device::mojom::UsbDeviceManagerClient>
- client_binding_{this};
+ mojo::Remote<device::mojom::UsbDeviceManager> usb_manager_;
+ mojo::AssociatedReceiver<device::mojom::UsbDeviceManagerClient>
+ client_receiver_{this};
// A mapping from GUID -> UsbDeviceInfoPtr for each attached USB device.
std::map<std::string, device::mojom::UsbDeviceInfoPtr> devices_;
diff --git a/chromium/components/arc/video_accelerator/BUILD.gn b/chromium/components/arc/video_accelerator/BUILD.gn
index 4f20af52d73..5674e657faa 100644
--- a/chromium/components/arc/video_accelerator/BUILD.gn
+++ b/chromium/components/arc/video_accelerator/BUILD.gn
@@ -19,7 +19,7 @@ static_library("video_accelerator") {
]
deps = [
- "//components/arc/common:media",
+ "//components/arc/mojom:media",
"//media",
"//ui/ozone",
]
diff --git a/chromium/components/arc/video_accelerator/DEPS b/chromium/components/arc/video_accelerator/DEPS
index ab60a062a08..affce5ebc9e 100644
--- a/chromium/components/arc/video_accelerator/DEPS
+++ b/chromium/components/arc/video_accelerator/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+components/arc/common",
+ "+components/arc/mojom",
"+gpu/config/gpu_preferences.h",
"+media/base",
"+media/gpu",
diff --git a/chromium/components/arc/video_accelerator/OWNERS b/chromium/components/arc/video_accelerator/OWNERS
index 346d6c9af8a..8794119b983 100644
--- a/chromium/components/arc/video_accelerator/OWNERS
+++ b/chromium/components/arc/video_accelerator/OWNERS
@@ -1,4 +1,3 @@
hiroh@chromium.org
kcwu@chromium.org
-piman@chromium.org
posciak@chromium.org
diff --git a/chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc b/chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc
index adc6db3c2e4..ad5eba91784 100644
--- a/chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc
+++ b/chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc
@@ -8,14 +8,98 @@
#include <unistd.h>
#include "base/files/platform_file.h"
+#include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
+#include "media/base/video_frame.h"
#include "media/gpu/macros.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace arc {
+namespace {
+
+bool VerifyGpuMemoryBufferHandle(media::VideoPixelFormat pixel_format,
+ const gfx::Size& coded_size,
+ const gfx::GpuMemoryBufferHandle& gmb_handle) {
+ if (gmb_handle.type != gfx::NATIVE_PIXMAP) {
+ VLOGF(1) << "Unexpected GpuMemoryBufferType: " << gmb_handle.type;
+ return false;
+ }
+
+ const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format);
+ if (num_planes != gmb_handle.native_pixmap_handle.planes.size() ||
+ num_planes == 0) {
+ VLOGF(1) << "Invalid number of dmabuf planes passed: "
+ << gmb_handle.native_pixmap_handle.planes.size()
+ << ", expected: " << num_planes;
+ return false;
+ }
+
+ // Offsets monotonically increase and strides monotonically decrease.
+ // Note: this offset assumption might not be correct if planes are stored in
+ // multiple buffers.
+ // TODO(b/127230761): Remove this offset check once one fd is given per one
+ // plane.
+ for (size_t i = 1; i < num_planes; i++) {
+ if (gmb_handle.native_pixmap_handle.planes[i].offset <
+ gmb_handle.native_pixmap_handle.planes[i - 1].offset) {
+ return false;
+ }
+ if (gmb_handle.native_pixmap_handle.planes[i - 1].stride <
+ gmb_handle.native_pixmap_handle.planes[i].stride) {
+ return false;
+ }
+ }
+
+ size_t prev_buffer_end = 0;
+ for (size_t i = 0; i < num_planes; i++) {
+ const auto& plane = gmb_handle.native_pixmap_handle.planes[i];
+ DVLOGF(4) << "Plane " << i << ", offset: " << plane.offset
+ << ", stride: " << plane.stride;
+
+ size_t file_size_in_bytes;
+ if (!plane.fd.is_valid() ||
+ !GetFileSize(plane.fd.get(), &file_size_in_bytes))
+ return false;
+
+ size_t plane_height =
+ media::VideoFrame::Rows(i, pixel_format, coded_size.height());
+ base::CheckedNumeric<size_t> min_plane_size =
+ base::CheckMul(plane.stride, plane_height);
+ if (!min_plane_size.IsValid() || min_plane_size.ValueOrDie() > plane.size) {
+ VLOGF(1) << "Invalid strides/sizes";
+ return false;
+ }
+
+ // Check |offset| + (the size of a plane) on each plane is not larger than
+ // |file_size_in_bytes|. This ensures we don't access out of a buffer
+ // referred by |fd|.
+ base::CheckedNumeric<size_t> min_buffer_size =
+ base::CheckAdd(plane.offset, plane.size);
+ if (!min_buffer_size.IsValid() ||
+ min_buffer_size.ValueOrDie() > file_size_in_bytes) {
+ VLOGF(1) << "Invalid strides/offsets";
+ return false;
+ }
+
+ // The end of the previous plane must not be bigger than the offset of the
+ // current plane.
+ // TODO(b/127230761): Remove this check once one fd is given per one plane.
+ if (prev_buffer_end > base::checked_cast<size_t>(plane.offset)) {
+ VLOGF(1) << "Invalid offset";
+ return false;
+ }
+ prev_buffer_end = min_buffer_size.ValueOrDie();
+ }
+
+ return true;
+}
+
+} // namespace
+
base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle) {
if (!handle.is_valid()) {
- VLOGF(1) << "Handle is invalid.";
+ VLOGF(1) << "Handle is invalid";
return base::ScopedFD();
}
@@ -31,10 +115,15 @@ base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle) {
}
bool GetFileSize(const int fd, size_t* size) {
+ if (fd < 0) {
+ VLOGF(1) << "Invalid file descriptor";
+ return false;
+ }
+
off_t fd_size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if (fd_size < 0u) {
- VPLOGF(1) << "Fail to find the size of fd.";
+ VPLOGF(1) << "Fail to find the size of fd";
return false;
}
@@ -50,4 +139,60 @@ bool GetFileSize(const int fd, size_t* size) {
return true;
}
+base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
+ media::VideoPixelFormat pixel_format,
+ const gfx::Size& coded_size,
+ base::ScopedFD fd,
+ const std::vector<VideoFramePlane>& planes) {
+ const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format);
+ if (planes.size() != num_planes || planes.size() == 0) {
+ VLOGF(1) << "Invalid number of dmabuf planes passed: " << planes.size()
+ << ", expected: " << num_planes;
+ return base::nullopt;
+ }
+
+ std::array<base::ScopedFD, media::VideoFrame::kMaxPlanes> scoped_fds;
+ DCHECK_LE(num_planes, media::VideoFrame::kMaxPlanes);
+ scoped_fds[0] = std::move(fd);
+ for (size_t i = 1; i < num_planes; ++i) {
+ scoped_fds[i].reset(HANDLE_EINTR(dup(scoped_fds[0].get())));
+ if (!scoped_fds[i].is_valid()) {
+ VLOGF(1) << "Failed to duplicate fd";
+ return base::nullopt;
+ }
+ }
+
+ gfx::GpuMemoryBufferHandle gmb_handle;
+ gmb_handle.type = gfx::NATIVE_PIXMAP;
+ for (size_t i = 0; i < num_planes; ++i) {
+ // NOTE: planes[i].stride and planes[i].offset both are int32_t. stride and
+ // offset in NativePixmapPlane are uint32_t and uint64_t, respectively.
+ if (!base::IsValueInRangeForNumericType<uint32_t>(planes[i].stride)) {
+ VLOGF(1) << "Invalid stride";
+ return base::nullopt;
+ }
+ if (!base::IsValueInRangeForNumericType<uint64_t>(planes[i].offset)) {
+ VLOGF(1) << "Invalid offset";
+ return base::nullopt;
+ }
+ uint32_t stride = base::checked_cast<uint32_t>(planes[i].stride);
+ uint64_t offset = base::checked_cast<uint64_t>(planes[i].offset);
+
+ size_t plane_height =
+ media::VideoFrame::Rows(i, pixel_format, coded_size.height());
+ base::CheckedNumeric<uint64_t> current_size =
+ base::CheckMul(stride, plane_height);
+ if (!current_size.IsValid()) {
+ VLOGF(1) << "Invalid stride/height";
+ return base::nullopt;
+ }
+ gmb_handle.native_pixmap_handle.planes.emplace_back(
+ stride, offset, current_size.ValueOrDie(), std::move(scoped_fds[i]));
+ }
+
+ if (!VerifyGpuMemoryBufferHandle(pixel_format, coded_size, gmb_handle))
+ return base::nullopt;
+ return gmb_handle;
+}
+
} // namespace arc
diff --git a/chromium/components/arc/video_accelerator/arc_video_accelerator_util.h b/chromium/components/arc/video_accelerator/arc_video_accelerator_util.h
index 3bcfa385ada..cb7fa51e6a5 100644
--- a/chromium/components/arc/video_accelerator/arc_video_accelerator_util.h
+++ b/chromium/components/arc/video_accelerator/arc_video_accelerator_util.h
@@ -5,16 +5,32 @@
#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
#define COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
+#include <vector>
+
#include "base/files/scoped_file.h"
+#include "base/optional.h"
+#include "components/arc/video_accelerator/video_frame_plane.h"
+#include "media/base/video_types.h"
#include "mojo/public/cpp/system/handle.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
namespace arc {
// Creates ScopedFD from given mojo::ScopedHandle.
// Returns invalid ScopedFD on failure.
base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle);
-// Return the file size of |fd|.
+// Return the file size of |fd| in bytes.
bool GetFileSize(const int fd, size_t* size);
+// Return GpuMemoryBufferHandle iff |planes| are valid for a video frame located
+// on |fd| and of |pixel_format| and |coded_size|. Otherwise returns
+// base::nullopt.
+base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
+ media::VideoPixelFormat pixel_format,
+ const gfx::Size& coded_size,
+ base::ScopedFD fd,
+ const std::vector<VideoFramePlane>& planes);
} // namespace arc
#endif // COMPONENTS_ARC_VIDEO_ACCELERATOR_ARC_VIDEO_ACCELERATOR_UTIL_H_
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
index 86e04b25c0f..54e75950b54 100644
--- a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
@@ -68,42 +68,6 @@ arc::mojom::VideoDecodeAccelerator::Result ConvertErrorCode(
}
}
-// Return true iff |planes| is valid for a video frame located on |dmabuf_fd|
-// and of |pixel_format|.
-bool VerifyDmabuf(media::VideoPixelFormat pixel_format,
- const gfx::Size& coded_size,
- int dmabuf_fd,
- const std::vector<arc::VideoFramePlane>& planes) {
- const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format);
- if (planes.size() != num_planes || num_planes == 0) {
- VLOGF(1) << "Invalid number of dmabuf planes passed: " << planes.size()
- << ", expected: " << num_planes;
- return false;
- }
-
- size_t size;
- if (!arc::GetFileSize(dmabuf_fd, &size))
- return false;
-
- for (size_t i = 0; i < planes.size(); ++i) {
- const auto& plane = planes[i];
-
- DVLOGF(4) << "Plane " << i << ", offset: " << plane.offset
- << ", stride: " << plane.stride;
-
- size_t rows = media::VideoFrame::Rows(i, pixel_format, coded_size.height());
- base::CheckedNumeric<size_t> current_size(plane.offset);
- current_size += base::CheckMul(plane.stride, rows);
-
- if (!current_size.IsValid() || current_size.ValueOrDie() > size) {
- VLOGF(1) << "Invalid strides/offsets.";
- return false;
- }
- }
-
- return true;
-}
-
} // namespace
namespace arc {
@@ -438,13 +402,7 @@ void GpuArcVideoDecodeAccelerator::Decode(
}
}
-void GpuArcVideoDecodeAccelerator::AssignPictureBuffersDeprecated(
- uint32_t count) {
- AssignPictureBuffers(count, pending_coded_size_);
-}
-
-void GpuArcVideoDecodeAccelerator::AssignPictureBuffers(uint32_t count,
- const gfx::Size& size) {
+void GpuArcVideoDecodeAccelerator::AssignPictureBuffers(uint32_t count) {
VLOGF(2) << "count=" << count;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!vda_) {
@@ -458,15 +416,17 @@ void GpuArcVideoDecodeAccelerator::AssignPictureBuffers(uint32_t count,
mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT);
return;
}
-
- coded_size_ = size;
- std::vector<media::PictureBuffer> buffers;
- for (uint32_t id = 0; id < count; ++id) {
- buffers.push_back(
- media::PictureBuffer(static_cast<int32_t>(id), coded_size_));
+ if (assign_picture_buffers_called_) {
+ VLOGF(1) << "AssignPictureBuffers is called twice without "
+ << "ImportBufferForPicture()";
+ client_->NotifyError(
+ mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT);
+ return;
}
+
+ coded_size_ = pending_coded_size_;
output_buffer_count_ = static_cast<size_t>(count);
- vda_->AssignPictureBuffers(buffers);
+ assign_picture_buffers_called_ = true;
}
void GpuArcVideoDecodeAccelerator::ImportBufferForPicture(
@@ -527,33 +487,30 @@ void GpuArcVideoDecodeAccelerator::ImportBufferForPicture(
}
gmb_handle.native_pixmap_handle = std::move(protected_native_pixmap);
} else {
- if (!VerifyDmabuf(pixel_format, coded_size_, handle_fd.get(), planes)) {
- VLOGF(1) << "Failed verifying dmabuf";
+ auto handle = CreateGpuMemoryBufferHandle(pixel_format, coded_size_,
+ std::move(handle_fd), planes);
+ if (!handle) {
+ VLOGF(1) << "Failed to create GpuMemoryBufferHandle";
client_->NotifyError(
mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT);
return;
}
+ gmb_handle = std::move(handle).value();
+ }
- const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format);
-
- // TODO(crbug.com/911370): Remove this workaround once Android passes one fd
- // per plane.
- std::array<base::ScopedFD, media::VideoFrame::kMaxPlanes> scoped_fds;
- scoped_fds[0].reset(handle_fd.release());
- for (size_t i = 1; i < num_planes; ++i) {
- scoped_fds[i].reset(HANDLE_EINTR(dup(scoped_fds[0].get())));
- if (!scoped_fds[i].is_valid()) {
- VLOGF(1) << "Failed to duplicate fd.";
- client_->NotifyError(
- mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
- return;
- }
+ // This is the first time of ImportBufferForPicture() after
+ // AssignPictureBuffers() is called. Call VDA::AssignPictureBuffers() here.
+ if (assign_picture_buffers_called_) {
+ gfx::Size picture_size(gmb_handle.native_pixmap_handle.planes[0].stride,
+ coded_size_.height());
+ std::vector<media::PictureBuffer> buffers;
+ for (size_t id = 0; id < output_buffer_count_; ++id) {
+ buffers.push_back(
+ media::PictureBuffer(static_cast<int32_t>(id), picture_size));
}
- for (size_t i = 0; i < planes.size(); ++i) {
- gmb_handle.native_pixmap_handle.planes.emplace_back(
- planes[i].stride, planes[i].offset, 0, std::move(scoped_fds[i]));
- }
+ vda_->AssignPictureBuffers(std::move(buffers));
+ assign_picture_buffers_called_ = false;
}
vda_->ImportBufferForPicture(picture_buffer_id, pixel_format,
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
index b7a0433234f..5de76657dd5 100644
--- a/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
@@ -13,7 +13,7 @@
#include "base/callback_forward.h"
#include "base/files/scoped_file.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/video_decode_accelerator.mojom.h"
+#include "components/arc/mojom/video_decode_accelerator.mojom.h"
#include "gpu/config/gpu_preferences.h"
#include "media/video/video_decode_accelerator.h"
@@ -64,8 +64,7 @@ class GpuArcVideoDecodeAccelerator
mojom::VideoDecodeClientPtr client,
InitializeCallback callback) override;
void Decode(mojom::BitstreamBufferPtr bitstream_buffer) override;
- void AssignPictureBuffersDeprecated(uint32_t count) override;
- void AssignPictureBuffers(uint32_t count, const gfx::Size& size) override;
+ void AssignPictureBuffers(uint32_t count) override;
void ImportBufferForPicture(int32_t picture_buffer_id,
mojom::HalPixelFormat format,
mojo::ScopedHandle handle,
@@ -152,6 +151,7 @@ class GpuArcVideoDecodeAccelerator
bool secure_mode_ = false;
size_t output_buffer_count_ = 0;
+ bool assign_picture_buffers_called_ = false;
THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(GpuArcVideoDecodeAccelerator);
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
index 7dfb9b31c93..214cf3b94ba 100644
--- a/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
@@ -8,7 +8,10 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/logging.h"
+#include "base/memory/platform_shared_memory_region.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
#include "base/system/sys_info.h"
#include "components/arc/video_accelerator/arc_video_accelerator_util.h"
#include "media/base/video_types.h"
@@ -20,6 +23,43 @@
namespace arc {
+namespace {
+base::Optional<media::VideoFrameLayout> CreateVideoFrameLayout(
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::GpuMemoryBufferHandle& gmb_handle) {
+ const size_t num_planes = gmb_handle.native_pixmap_handle.planes.size();
+
+ std::vector<media::VideoFrameLayout::Plane> layout_planes(num_planes);
+ for (size_t i = 0; i < num_planes; i++) {
+ const auto& plane = gmb_handle.native_pixmap_handle.planes[i];
+ if (!base::IsValueInRangeForNumericType<int32_t>(plane.stride)) {
+ DLOG(ERROR) << "Invalid stride";
+ return base::nullopt;
+ }
+ if (!base::IsValueInRangeForNumericType<size_t>(plane.offset)) {
+ DLOG(ERROR) << "Invalid offset";
+ return base::nullopt;
+ }
+ if (!base::IsValueInRangeForNumericType<size_t>(plane.size)) {
+ DLOG(ERROR) << "Invalid size";
+ return base::nullopt;
+ }
+
+ // convert uint32_t -> int32_t.
+ layout_planes[i].stride = base::checked_cast<int32_t>(plane.stride);
+ // convert uint64_t -> size_t
+ layout_planes[i].offset = base::checked_cast<size_t>(plane.offset);
+ // convert uint64_t -> size_t
+ layout_planes[i].size = base::checked_cast<size_t>(plane.size);
+ }
+
+ gfx::Size frame_size(layout_planes[0].stride, coded_size.height());
+ return media::VideoFrameLayout::CreateWithPlanes(format, frame_size,
+ std::move(layout_planes));
+}
+} // namespace
+
GpuArcVideoEncodeAccelerator::GpuArcVideoEncodeAccelerator(
const gpu::GpuPreferences& gpu_preferences)
: gpu_preferences_(gpu_preferences),
@@ -134,8 +174,42 @@ void GpuArcVideoEncodeAccelerator::EncodeDmabuf(
int64_t timestamp,
bool force_keyframe,
EncodeCallback callback) {
- client_->NotifyError(Error::kInvalidArgumentError);
- NOTIMPLEMENTED();
+ if (format != media::PIXEL_FORMAT_NV12) {
+ DLOG(ERROR) << "Formats other than NV12 are unsupported. format=" << format;
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
+ auto gmb_handle =
+ CreateGpuMemoryBufferHandle(format, coded_size_, std::move(fd), planes);
+ if (!gmb_handle) {
+ DLOG(ERROR) << "Failed to create GpuMemoryBufferHandle";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
+ auto layout = CreateVideoFrameLayout(format, coded_size_, *gmb_handle);
+ if (!layout) {
+ DLOG(ERROR) << "Failed to create VideoFrameLayout.";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
+ std::vector<base::ScopedFD> scoped_fds;
+ for (auto& plane : gmb_handle->native_pixmap_handle.planes) {
+ scoped_fds.push_back(std::move(plane.fd));
+ }
+ auto frame = media::VideoFrame::WrapExternalDmabufs(
+ *layout, gfx::Rect(visible_size_), visible_size_, std::move(scoped_fds),
+ base::TimeDelta::FromMicroseconds(timestamp));
+ if (!frame) {
+ DLOG(ERROR) << "Failed to create VideoFrame";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
+ frame->AddDestructionObserver(std::move(callback));
+ accelerator_->Encode(std::move(frame), force_keyframe);
}
void GpuArcVideoEncodeAccelerator::EncodeSharedMemory(
@@ -151,48 +225,67 @@ void GpuArcVideoEncodeAccelerator::EncodeSharedMemory(
return;
}
- size_t allocation_size =
- media::VideoFrame::AllocationSize(format, coded_size_);
+ auto gmb_handle = CreateGpuMemoryBufferHandle(
+ format, coded_size_, base::ScopedFD(HANDLE_EINTR(dup(fd.get()))), planes);
+ if (!gmb_handle) {
+ DLOG(ERROR) << "Failed to create GpuMemoryBufferHandle";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
+ auto layout = CreateVideoFrameLayout(format, coded_size_, *gmb_handle);
+ if (!layout) {
+ DLOG(ERROR) << "Failed to create VideoFrameLayout.";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
+ base::CheckedNumeric<size_t> map_size = 0;
+ for (const auto& plane : layout->planes()) {
+ map_size = map_size.Max(plane.offset + plane.size);
+ }
+ if (!map_size.IsValid()) {
+ DLOG(ERROR) << "Invalid map_size";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+
// TODO(rockot): Pass GUIDs through Mojo. https://crbug.com/713763.
// TODO(rockot): This fd comes from a mojo::ScopedHandle in
// GpuArcVideoService::BindSharedMemory. That should be passed through,
// rather than pulling out the fd. https://crbug.com/713763.
- // TODO(rockot): Pass through a real size rather than |0|.
base::UnguessableToken guid = base::UnguessableToken::Create();
- base::SharedMemoryHandle shm_handle(base::FileDescriptor(fd.release(), true),
- 0u, guid);
- auto shm = std::make_unique<base::SharedMemory>(shm_handle, true);
-
- base::CheckedNumeric<off_t> map_offset = planes[0].offset;
- base::CheckedNumeric<size_t> map_size = allocation_size;
- const uint32_t aligned_offset =
- planes[0].offset % base::SysInfo::VMAllocationGranularity();
- map_offset -= aligned_offset;
- map_size += aligned_offset;
-
- if (!map_offset.IsValid() || !map_size.IsValid()) {
- DLOG(ERROR) << "Invalid map_offset or map_size";
- client_->NotifyError(Error::kInvalidArgumentError);
- return;
- }
- if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
+ base::subtle::PlatformSharedMemoryRegion platform_region =
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ std::move(fd),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ map_size.ValueOrDie(), guid);
+ base::UnsafeSharedMemoryRegion shared_region =
+ base::UnsafeSharedMemoryRegion::Deserialize(std::move(platform_region));
+ base::WritableSharedMemoryMapping mapping =
+ shared_region.MapAt(0u, map_size.ValueOrDie());
+ if (!mapping.IsValid()) {
DLOG(ERROR) << "Failed to map memory.";
client_->NotifyError(Error::kPlatformFailureError);
return;
}
- uint8_t* shm_memory = reinterpret_cast<uint8_t*>(shm->memory());
- auto frame = media::VideoFrame::WrapExternalSharedMemory(
- format, coded_size_, gfx::Rect(visible_size_), visible_size_,
- shm_memory + aligned_offset, allocation_size, shm_handle,
- planes[0].offset, base::TimeDelta::FromMicroseconds(timestamp));
-
- // Add the function to relase |shm| and |callback| to |frame|'s destruction
- // observer. When the |frame| goes out of scope, it unmaps and releases the
- // shared memory as well as executes |callback|.
- frame->AddDestructionObserver(base::BindOnce(
- base::DoNothing::Once<std::unique_ptr<base::SharedMemory>>(),
- std::move(shm)));
+ uint8_t* shm_memory = mapping.GetMemoryAsSpan<uint8_t>().data();
+ auto frame = media::VideoFrame::WrapExternalYuvDataWithLayout(
+ *layout, gfx::Rect(visible_size_), visible_size_,
+ shm_memory + layout->planes()[0].offset,
+ shm_memory + layout->planes()[1].offset,
+ shm_memory + layout->planes()[2].offset,
+ base::TimeDelta::FromMicroseconds(timestamp));
+ if (!frame) {
+ DLOG(ERROR) << "Failed to create VideoFrame";
+ client_->NotifyError(Error::kInvalidArgumentError);
+ return;
+ }
+ frame->BackWithOwnedSharedMemory(std::move(shared_region),
+ std::move(mapping));
+ // Add the function to |callback| to |frame|'s destruction observer. When the
+ // |frame| goes out of scope, it executes |callback|.
frame->AddDestructionObserver(std::move(callback));
accelerator_->Encode(frame, force_keyframe);
}
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
index 806b8dc8e59..523e04ff4e5 100644
--- a/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
@@ -11,7 +11,7 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
-#include "components/arc/common/video_encode_accelerator.mojom.h"
+#include "components/arc/mojom/video_encode_accelerator.mojom.h"
#include "components/arc/video_accelerator/video_frame_plane.h"
#include "gpu/config/gpu_preferences.h"
#include "media/video/video_encode_accelerator.h"
diff --git a/chromium/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h b/chromium/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
index 4235d86344f..26fe128192c 100644
--- a/chromium/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
+++ b/chromium/components/arc/video_accelerator/gpu_arc_video_protected_buffer_allocator.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "components/arc/common/video_protected_buffer_allocator.mojom.h"
+#include "components/arc/mojom/video_protected_buffer_allocator.mojom.h"
#include "mojo/public/cpp/system/handle.h"
namespace arc {
diff --git a/chromium/components/arc/video_accelerator/protected_buffer_manager.cc b/chromium/components/arc/video_accelerator/protected_buffer_manager.cc
index af955f36d34..3acab7df92b 100644
--- a/chromium/components/arc/video_accelerator/protected_buffer_manager.cc
+++ b/chromium/components/arc/video_accelerator/protected_buffer_manager.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/system/sys_info.h"
+#include "base/threading/thread_checker.h"
#include "components/arc/video_accelerator/protected_buffer_allocator.h"
#include "media/gpu/macros.h"
#include "mojo/public/cpp/system/buffer.h"
diff --git a/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h b/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h
index 79e3c2c3452..3390984a80a 100644
--- a/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h
+++ b/chromium/components/arc/video_accelerator/protected_buffer_manager_proxy.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_PROXY_H_
-#include "components/arc/common/protected_buffer_manager.mojom.h"
+#include "components/arc/mojom/protected_buffer_manager.mojom.h"
namespace arc {
diff --git a/chromium/components/arc/volume_mounter/OWNERS b/chromium/components/arc/volume_mounter/OWNERS
index be9c82ab353..a4479e996dc 100644
--- a/chromium/components/arc/volume_mounter/OWNERS
+++ b/chromium/components/arc/volume_mounter/OWNERS
@@ -1,5 +1,5 @@
hashimoto@chromium.org
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=file://components/arc/common/ARC_SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=file://components/arc/mojom/ARC_SECURITY_OWNERS
diff --git a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
index a79e6d18dda..0470fac7ecb 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
@@ -8,6 +8,7 @@
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
+#include "base/metrics/histogram_functions.h"
#include "base/task/post_task.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/disks/disk.h"
@@ -72,8 +73,7 @@ ArcVolumeMounterBridge* ArcVolumeMounterBridge::GetForBrowserContextForTesting(
ArcVolumeMounterBridge::ArcVolumeMounterBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service),
- pref_service_(user_prefs::UserPrefs::Get(context)),
- weak_ptr_factory_(this) {
+ pref_service_(user_prefs::UserPrefs::Get(context)) {
DCHECK(pref_service_);
arc_bridge_service_->volume_mounter()->AddObserver(this);
arc_bridge_service_->volume_mounter()->SetHost(this);
@@ -81,11 +81,11 @@ ArcVolumeMounterBridge::ArcVolumeMounterBridge(content::BrowserContext* context,
DiskMountManager::GetInstance()->AddObserver(this);
change_registerar_.Init(pref_service_);
- // Start monitoring |kArcHasAccessToRemovableMedia| changes. Note that the
+ // Start monitoring |kArcVisibleExternalStorages| changes. Note that the
// registerar automatically stops monitoring the pref in its dtor.
change_registerar_.Add(
- prefs::kArcHasAccessToRemovableMedia,
- base::BindRepeating(&ArcVolumeMounterBridge::OnPrefChanged,
+ prefs::kArcVisibleExternalStorages,
+ base::BindRepeating(&ArcVolumeMounterBridge::OnVisibleStoragesChanged,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -97,8 +97,7 @@ ArcVolumeMounterBridge::~ArcVolumeMounterBridge() {
// Sends MountEvents of all existing MountPoints in cros-disks.
void ArcVolumeMounterBridge::SendAllMountEvents() {
- if (base::FeatureList::IsEnabled(chromeos::features::kMyFilesVolume))
- SendMountEventForMyFiles();
+ SendMountEventForMyFiles();
for (const auto& keyValue : DiskMountManager::GetInstance()->mount_points()) {
OnMountEvent(DiskMountManager::MountEvent::MOUNTING,
@@ -123,28 +122,31 @@ void ArcVolumeMounterBridge::SendMountEventForMyFiles() {
volume_mounter_instance->OnMountEvent(mojom::MountPointInfo::New(
DiskMountManager::MOUNTING, kMyFilesPath, kMyFilesPath, kMyFilesUuid,
- device_label, device_type));
+ device_label, device_type, false));
}
-bool ArcVolumeMounterBridge::HasAccessToRemovableMedia() const {
- DCHECK(pref_service_);
- // If the UI is not enabled, allow the access.
- if (!base::FeatureList::IsEnabled(arc::kUsbStorageUIFeature))
- return true;
- return pref_service_->GetBoolean(prefs::kArcHasAccessToRemovableMedia);
+bool ArcVolumeMounterBridge::IsVisibleToAndroidApps(
+ const std::string& uuid) const {
+ const base::ListValue* uuid_list =
+ pref_service_->GetList(prefs::kArcVisibleExternalStorages);
+ for (auto& value : uuid_list->GetList()) {
+ if (value.is_string() && value.GetString() == uuid)
+ return true;
+ }
+ return false;
}
-void ArcVolumeMounterBridge::OnPrefChanged() {
- if (HasAccessToRemovableMedia()) {
- // Mount everything again. Mounting the same disk (e.g. MyFiles) again is
- // allowed and is no-op.
- SendAllMountEvents();
- return;
- }
- // Unmount everything except for MyFiles.
- for (const auto& keyValue : DiskMountManager::GetInstance()->mount_points()) {
+void ArcVolumeMounterBridge::OnVisibleStoragesChanged() {
+ // Remount all external mount points when the list of visible storage changes.
+ for (const auto& key_value :
+ DiskMountManager::GetInstance()->mount_points()) {
OnMountEvent(DiskMountManager::MountEvent::UNMOUNTING,
- chromeos::MountError::MOUNT_ERROR_NONE, keyValue.second);
+ chromeos::MountError::MOUNT_ERROR_NONE, key_value.second);
+ }
+ for (const auto& key_value :
+ DiskMountManager::GetInstance()->mount_points()) {
+ OnMountEvent(DiskMountManager::MountEvent::MOUNTING,
+ chromeos::MountError::MOUNT_ERROR_NONE, key_value.second);
}
}
@@ -174,15 +176,6 @@ void ArcVolumeMounterBridge::OnMountEvent(
return;
}
- // Do not propagate MOUNTING event to ARC when the media sharing setting is
- // turned off. The other event (i.e. UNMOUNTING) should still go through.
- if (event == DiskMountManager::MountEvent::MOUNTING &&
- !HasAccessToRemovableMedia()) {
- VLOG(2) << "Disk at " << mount_info.source_path
- << " is not allowed to be shared with ARC";
- return;
- }
-
// Get disks informations that are needed by Android MountService.
const chromeos::disks::Disk* disk =
DiskMountManager::GetInstance()->FindDiskBySourcePath(
@@ -213,9 +206,18 @@ void ArcVolumeMounterBridge::OnMountEvent(
if (!volume_mounter_instance)
return;
+ const bool visible = IsVisibleToAndroidApps(fs_uuid);
volume_mounter_instance->OnMountEvent(mojom::MountPointInfo::New(
event, mount_info.source_path, mount_info.mount_path, fs_uuid,
- device_label, device_type));
+ device_label, device_type, visible));
+ if (event == DiskMountManager::MountEvent::MOUNTING &&
+ (device_type == chromeos::DeviceType::DEVICE_TYPE_USB ||
+ device_type == chromeos::DeviceType::DEVICE_TYPE_SD)) {
+ // Record visibilities of the mounted devices only when they are removable
+ // storages (e.g. USB sticks or SD cards).
+ base::UmaHistogramBoolean("Arc.ExternalStorage.MountedMediaVisibility",
+ visible);
+ }
}
void ArcVolumeMounterBridge::RequestAllMountPoints() {
diff --git a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
index abc8daf3306..27cf43fa0c9 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/disks/disk_mount_manager.h"
-#include "components/arc/common/volume_mounter.mojom.h"
+#include "components/arc/mojom/volume_mounter.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
@@ -55,29 +55,20 @@ class ArcVolumeMounterBridge
// mojom::VolumeMounterHost overrides:
void RequestAllMountPoints() override;
- bool files_app_toast_shown() const { return files_app_toast_shown_; }
- void set_files_app_toast_shown(bool files_app_toast_shown) {
- files_app_toast_shown_ = files_app_toast_shown;
- }
-
private:
void SendAllMountEvents();
void SendMountEventForMyFiles();
- bool HasAccessToRemovableMedia() const;
- void OnPrefChanged();
+ bool IsVisibleToAndroidApps(const std::string& uuid) const;
+ void OnVisibleStoragesChanged();
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
PrefService* const pref_service_;
PrefChangeRegistrar change_registerar_;
- // A flag to remember if the ARC toast UI in Files.app has been shown in the
- // current user session.
- bool files_app_toast_shown_ = false;
-
- base::WeakPtrFactory<ArcVolumeMounterBridge> weak_ptr_factory_;
+ base::WeakPtrFactory<ArcVolumeMounterBridge> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcVolumeMounterBridge);
};
diff --git a/chromium/components/arc/volume_mounter/volume_mounter_struct_traits.cc b/chromium/components/arc/volume_mounter/volume_mounter_mojom_traits.cc
index b516fd79d4d..54299f5c80d 100644
--- a/chromium/components/arc/volume_mounter/volume_mounter_struct_traits.cc
+++ b/chromium/components/arc/volume_mounter/volume_mounter_mojom_traits.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 "components/arc/volume_mounter/volume_mounter_struct_traits.h"
+#include "components/arc/volume_mounter/volume_mounter_mojom_traits.h"
#include "base/logging.h"
diff --git a/chromium/components/arc/volume_mounter/volume_mounter_struct_traits.h b/chromium/components/arc/volume_mounter/volume_mounter_mojom_traits.h
index e235db29637..c18da661fdf 100644
--- a/chromium/components/arc/volume_mounter/volume_mounter_struct_traits.h
+++ b/chromium/components/arc/volume_mounter/volume_mounter_mojom_traits.h
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_ARC_VOLUME_MOUNTER_VOLUME_MOUNTER_STRUCT_TRAITS_H_
-#define COMPONENTS_ARC_VOLUME_MOUNTER_VOLUME_MOUNTER_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_ARC_VOLUME_MOUNTER_VOLUME_MOUNTER_MOJOM_TRAITS_H_
+#define COMPONENTS_ARC_VOLUME_MOUNTER_VOLUME_MOUNTER_MOJOM_TRAITS_H_
#include "chromeos/disks/disk_mount_manager.h"
-#include "components/arc/common/volume_mounter.mojom.h"
+#include "components/arc/mojom/volume_mounter.mojom.h"
namespace mojo {
@@ -28,4 +28,4 @@ struct EnumTraits<arc::mojom::MountEvent,
} // namespace mojo
-#endif // COMPONENTS_ARC_VOLUME_MOUNTER_VOLUME_MOUNTER_STRUCT_TRAITS_H_
+#endif // COMPONENTS_ARC_VOLUME_MOUNTER_VOLUME_MOUNTER_MOJOM_TRAITS_H_
diff --git a/chromium/components/arc/wake_lock/arc_wake_lock_bridge.cc b/chromium/components/arc/wake_lock/arc_wake_lock_bridge.cc
index f5bfb90338f..fda1d063dd0 100644
--- a/chromium/components/arc/wake_lock/arc_wake_lock_bridge.cc
+++ b/chromium/components/arc/wake_lock/arc_wake_lock_bridge.cc
@@ -14,7 +14,7 @@
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/wake_lock/arc_wake_lock_bridge.h"
#include "content/public/browser/system_connector.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -69,12 +69,12 @@ class ArcWakeLockBridge::WakeLockRequester {
// Initialize |wake_lock_| if this is the first time we're using it.
DVLOG(1) << "Partial wake lock new acquire. Count: " << wake_lock_count_;
if (!wake_lock_) {
- device::mojom::WakeLockProviderPtr provider;
- connector_->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&provider));
+ mojo::Remote<device::mojom::WakeLockProvider> provider;
+ connector_->Connect(device::mojom::kServiceName,
+ provider.BindNewPipeAndPassReceiver());
provider->GetWakeLockWithoutContext(
type_, device::mojom::WakeLockReason::kOther, kWakeLockReason,
- mojo::MakeRequest(&wake_lock_));
+ wake_lock_.BindNewPipeAndPassReceiver());
}
wake_lock_->RequestWakeLock();
@@ -118,7 +118,7 @@ class ArcWakeLockBridge::WakeLockRequester {
int64_t wake_lock_count_ = 0;
// Lazily initialized in response to first request.
- device::mojom::WakeLockPtr wake_lock_;
+ mojo::Remote<device::mojom::WakeLock> wake_lock_;
DISALLOW_COPY_AND_ASSIGN(WakeLockRequester);
};
@@ -142,9 +142,7 @@ ArcWakeLockBridge* ArcWakeLockBridge::GetForBrowserContextForTesting(
ArcWakeLockBridge::ArcWakeLockBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
- : arc_bridge_service_(bridge_service),
- binding_(this),
- weak_ptr_factory_(this) {
+ : arc_bridge_service_(bridge_service), binding_(this) {
arc_bridge_service_->wake_lock()->SetHost(this);
arc_bridge_service_->wake_lock()->AddObserver(this);
}
diff --git a/chromium/components/arc/wake_lock/arc_wake_lock_bridge.h b/chromium/components/arc/wake_lock/arc_wake_lock_bridge.h
index 4a1d1cdc962..ade0bd71b29 100644
--- a/chromium/components/arc/wake_lock/arc_wake_lock_bridge.h
+++ b/chromium/components/arc/wake_lock/arc_wake_lock_bridge.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "components/arc/common/wake_lock.mojom.h"
+#include "components/arc/mojom/wake_lock.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/common/service_manager_connection.h"
@@ -80,7 +80,7 @@ class ArcWakeLockBridge : public KeyedService,
mojo::Binding<mojom::WakeLockHost> binding_;
- base::WeakPtrFactory<ArcWakeLockBridge> weak_ptr_factory_;
+ base::WeakPtrFactory<ArcWakeLockBridge> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ArcWakeLockBridge);
};
diff --git a/chromium/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc b/chromium/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
index e0605d89094..19601946010 100644
--- a/chromium/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
+++ b/chromium/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
@@ -9,8 +9,8 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/arc/common/power.mojom.h"
+#include "base/test/task_environment.h"
+#include "components/arc/mojom/power.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/test/connection_holder_util.h"
#include "components/arc/test/fake_power_instance.h"
@@ -27,8 +27,7 @@ using device::mojom::WakeLockType;
class ArcWakeLockBridgeTest : public testing::Test {
public:
ArcWakeLockBridgeTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
wake_lock_provider_(
connector_factory_.RegisterInstance(device::mojom::kServiceName)) {
bridge_service_ = std::make_unique<ArcBridgeService>();
@@ -98,7 +97,7 @@ class ArcWakeLockBridgeTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
service_manager::TestConnectorFactory connector_factory_;
device::TestWakeLockProvider wake_lock_provider_;
diff --git a/chromium/components/assist_ranker/OWNERS b/chromium/components/assist_ranker/OWNERS
index 8aee8cf06a5..00608e84ab7 100644
--- a/chromium/components/assist_ranker/OWNERS
+++ b/chromium/components/assist_ranker/OWNERS
@@ -3,3 +3,4 @@ charleszhao@chromium.org
hamelphi@chromium.org
jiameng@chromium.org
rogerm@chromium.org
+# COMPONENT: UI>ML
diff --git a/chromium/components/assist_ranker/base_predictor_unittest.cc b/chromium/components/assist_ranker/base_predictor_unittest.cc
index 9339229b0e4..84201845051 100644
--- a/chromium/components/assist_ranker/base_predictor_unittest.cc
+++ b/chromium/components/assist_ranker/base_predictor_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/assist_ranker/fake_ranker_model_loader.h"
#include "components/assist_ranker/predictor_config.h"
#include "components/assist_ranker/proto/ranker_example.pb.h"
@@ -113,7 +113,7 @@ class BasePredictorTest : public ::testing::Test {
private:
// Sets up the task scheduling/task-runner environment for each test.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
// Sets itself as the global UkmRecorder on construction.
ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
diff --git a/chromium/components/assist_ranker/ranker_model_loader_impl.cc b/chromium/components/assist_ranker/ranker_model_loader_impl.cc
index ad8dd63830f..abbc1c638fa 100644
--- a/chromium/components/assist_ranker/ranker_model_loader_impl.cc
+++ b/chromium/components/assist_ranker/ranker_model_loader_impl.cc
@@ -95,8 +95,9 @@ RankerModelLoaderImpl::RankerModelLoaderImpl(
base::FilePath model_path,
GURL model_url,
std::string uma_prefix)
- : background_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ : background_task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
validate_model_cb_(std::move(validate_model_cb)),
on_model_available_cb_(std::move(on_model_available_cb)),
diff --git a/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc b/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
index c8476fe8bcf..c47266484d2 100644
--- a/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
+++ b/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
@@ -16,7 +16,7 @@
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/assist_ranker/proto/ranker_model.pb.h"
#include "components/assist_ranker/proto/translate_ranker_model.pb.h"
@@ -76,7 +76,7 @@ class RankerModelLoaderImplTest : public ::testing::Test {
void OnModelAvailable(std::unique_ptr<RankerModel> model);
// Sets up the task scheduling/task-runner environment for each test.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
// Override the default URL loader to return custom responses for tests.
network::TestURLLoaderFactory test_loader_factory_;
@@ -175,7 +175,7 @@ bool RankerModelLoaderImplTest::DoLoaderTest(const base::FilePath& model_path,
test_shared_loader_factory_, model_path, model_url,
"RankerModelLoaderImplTest");
loader->NotifyOfRankerActivity();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
return true;
}
diff --git a/chromium/components/assist_ranker/ranker_url_fetcher.cc b/chromium/components/assist_ranker/ranker_url_fetcher.cc
index 6b8a2616ab0..b57f1610eaf 100644
--- a/chromium/components/assist_ranker/ranker_url_fetcher.cc
+++ b/chromium/components/assist_ranker/ranker_url_fetcher.cc
@@ -77,8 +77,7 @@ bool RankerURLFetcher::Request(
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url_;
- resource_request->load_flags =
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
if (max_retry_on_5xx_ > 0) {
diff --git a/chromium/components/autofill/DEPS b/chromium/components/autofill/DEPS
index 909ce7fa731..1e677456fea 100644
--- a/chromium/components/autofill/DEPS
+++ b/chromium/components/autofill/DEPS
@@ -4,6 +4,8 @@ include_rules = [
"+components/strings/grit/components_strings.h",
"+google_apis/gaia/gaia_urls.h",
"+net",
+ "+mojo/public",
+ "+third_party/protobuf",
"+third_party/skia",
"+third_party/zlib/google",
"+ui",
diff --git a/chromium/components/autofill/android/java/strings/translations/autofill_strings_mr.xtb b/chromium/components/autofill/android/java/strings/translations/autofill_strings_mr.xtb
index c0bea6599bb..48d2a9bd969 100644
--- a/chromium/components/autofill/android/java/strings/translations/autofill_strings_mr.xtb
+++ b/chromium/components/autofill/android/java/strings/translations/autofill_strings_mr.xtb
@@ -1,5 +1,5 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="mr">
-<translation id="1112374155460533568">अॉटोफिल पॉपअप दाखवत आहे</translation>
+<translation id="1112374155460533568">ऑटोफिल पॉपअप दाखवत आहे</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/components/autofill/content/browser/autofill_internals_log_router_unittest.cc b/chromium/components/autofill/content/browser/autofill_internals_log_router_unittest.cc
index 752a1d48831..fdb6ff29ae7 100644
--- a/chromium/components/autofill/content/browser/autofill_internals_log_router_unittest.cc
+++ b/chromium/components/autofill/content/browser/autofill_internals_log_router_unittest.cc
@@ -7,8 +7,8 @@
#include "components/autofill/core/browser/logging/log_receiver.h"
#include "components/autofill/core/browser/logging/log_router.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -30,7 +30,7 @@ class MockLogReceiver : public autofill::LogReceiver {
class AutofillLogRouterFactoryTest : public testing::Test {
public:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
void SetUp() override {
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index c3a047a24d3..68239ae09f5 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -41,7 +41,8 @@ ContentAutofillDriver::ContentAutofillDriver(
AutofillProvider* provider)
: render_frame_host_(render_frame_host),
autofill_manager_(nullptr),
- key_press_handler_manager_(this) {
+ key_press_handler_manager_(this),
+ log_manager_(client->GetLogManager()) {
// AutofillManager isn't used if provider is valid, Autofill provider is
// currently used by Android WebView only.
if (provider) {
@@ -86,12 +87,6 @@ ui::AXTreeID ContentAutofillDriver::GetAxTreeId() const {
return render_frame_host_->GetAXTreeID();
}
-net::URLRequestContextGetter* ContentAutofillDriver::GetURLRequestContext() {
- return content::BrowserContext::GetDefaultStoragePartition(
- render_frame_host_->GetSiteInstance()->GetBrowserContext())->
- GetURLRequestContext();
-}
-
scoped_refptr<network::SharedURLLoaderFactory>
ContentAutofillDriver::GetURLLoaderFactory() {
return content::BrowserContext::GetDefaultStoragePartition(
@@ -104,13 +99,13 @@ bool ContentAutofillDriver::RendererIsAvailable() {
}
void ContentAutofillDriver::ConnectToAuthenticator(
- blink::mojom::InternalAuthenticatorRequest request) {
+ mojo::PendingReceiver<blink::mojom::InternalAuthenticator> receiver) {
#if defined(OS_ANDROID)
- render_frame_host_->GetJavaInterfaces()->GetInterface(std::move(request));
+ render_frame_host_->GetJavaInterfaces()->GetInterface(std::move(receiver));
#else
authenticator_impl_ = std::make_unique<content::InternalAuthenticatorImpl>(
render_frame_host_, url::Origin::Create(payments::GetBaseSecureUrl()));
- authenticator_impl_->Bind(std::move(request));
+ authenticator_impl_->Bind(std::move(receiver));
#endif
}
@@ -338,7 +333,8 @@ void ContentAutofillDriver::RemoveHandler(
}
void ContentAutofillDriver::SetAutofillProvider(AutofillProvider* provider) {
- autofill_handler_ = std::make_unique<AutofillHandlerProxy>(this, provider);
+ autofill_handler_ =
+ std::make_unique<AutofillHandlerProxy>(this, log_manager_, provider);
GetAutofillAgent()->SetUserGestureRequired(false);
GetAutofillAgent()->SetSecureContextRequired(true);
GetAutofillAgent()->SetFocusRequiresScroll(false);
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index 5de70a3f716..c2496dc87b0 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -19,6 +19,7 @@
#include "components/autofill/core/browser/autofill_manager.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
namespace content {
class NavigationHandle;
@@ -29,6 +30,7 @@ namespace autofill {
class AutofillClient;
class AutofillProvider;
+class LogManager;
// Class that drives autofill flow in the browser process based on
// communication from the renderer and from the external world. There is one
@@ -56,11 +58,11 @@ class ContentAutofillDriver : public AutofillDriver,
bool IsIncognito() const override;
bool IsInMainFrame() const override;
ui::AXTreeID GetAxTreeId() const override;
- net::URLRequestContextGetter* GetURLRequestContext() override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
bool RendererIsAvailable() override;
void ConnectToAuthenticator(
- blink::mojom::InternalAuthenticatorRequest request) override;
+ mojo::PendingReceiver<blink::mojom::InternalAuthenticator> receiver)
+ override;
void SendFormDataToRenderer(int query_id,
RendererFormDataAction action,
const FormData& data) override;
@@ -173,6 +175,8 @@ class ContentAutofillDriver : public AutofillDriver,
KeyPressHandlerManager key_press_handler_manager_;
+ LogManager* const log_manager_;
+
mojo::AssociatedReceiver<mojom::AutofillDriver> receiver_{this};
mojo::AssociatedRemote<mojom::AutofillAgent> autofill_agent_;
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.cc b/chromium/components/autofill/content/browser/risk/fingerprint.cc
index c0e2d8d9223..e640bf8c7bd 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.cc
@@ -175,7 +175,6 @@ void AddGpuInfoToFingerprint(Fingerprint::MachineCharacteristics* machine,
graphics->set_vendor_id(active_gpu.vendor_id);
graphics->set_device_id(active_gpu.device_id);
graphics->set_driver_version(active_gpu.driver_version);
- graphics->set_driver_date(active_gpu.driver_date);
}
// Waits for all asynchronous data required for the fingerprint to be loaded,
@@ -221,7 +220,8 @@ class FingerprintDataLoader : public content::GpuDataManagerObserver {
// Ensures that any observer registrations for the GPU data are cleaned up by
// the time this object is destroyed.
- ScopedObserver<content::GpuDataManager, FingerprintDataLoader> gpu_observer_;
+ ScopedObserver<content::GpuDataManager, content::GpuDataManagerObserver>
+ gpu_observer_{this};
// Data that will be passed on to the next loading phase. See the comment for
// GetFingerprint() for a description of these variables.
@@ -273,7 +273,6 @@ FingerprintDataLoader::FingerprintDataLoader(
base::OnceCallback<void(std::unique_ptr<Fingerprint>)> callback,
service_manager::Connector* connector)
: gpu_data_manager_(content::GpuDataManager::GetInstance()),
- gpu_observer_(this),
obfuscated_gaia_id_(obfuscated_gaia_id),
window_bounds_(window_bounds),
content_bounds_(content_bounds),
diff --git a/chromium/components/autofill/content/common/mojom/BUILD.gn b/chromium/components/autofill/content/common/mojom/BUILD.gn
index 312d0622d42..c9d9cdfacf9 100644
--- a/chromium/components/autofill/content/common/mojom/BUILD.gn
+++ b/chromium/components/autofill/content/common/mojom/BUILD.gn
@@ -13,7 +13,7 @@ mojom("mojom") {
public_deps = [
"//components/autofill/core/common/mojom:mojo_types",
"//mojo/public/mojom/base",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
"//url/mojom:url_mojom_gurl",
]
}
diff --git a/chromium/components/autofill/content/common/mojom/autofill_driver.mojom b/chromium/components/autofill/content/common/mojom/autofill_driver.mojom
index 3f867735c28..b7fa28ae376 100644
--- a/chromium/components/autofill/content/common/mojom/autofill_driver.mojom
+++ b/chromium/components/autofill/content/common/mojom/autofill_driver.mojom
@@ -8,7 +8,7 @@ import "components/autofill/core/common/mojom/autofill_types.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/text_direction.mojom";
import "mojo/public/mojom/base/time.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
import "url/mojom/url.mojom";
// There is one instance of this interface per render frame host in the browser
@@ -127,6 +127,9 @@ interface PasswordManagerDriver {
mojo_base.mojom.String16 typed_username,
int32 options, gfx.mojom.RectF bounds);
+ // Instructs the browser to show the Touch To Fill UI.
+ ShowTouchToFill();
+
// Checks the safe browsing reputation of the website where the focused
// username/password field is on.
CheckSafeBrowsingReputation(
diff --git a/chromium/components/autofill/content/renderer/BUILD.gn b/chromium/components/autofill/content/renderer/BUILD.gn
index 7afe41f5826..95d49af5ae5 100644
--- a/chromium/components/autofill/content/renderer/BUILD.gn
+++ b/chromium/components/autofill/content/renderer/BUILD.gn
@@ -43,6 +43,7 @@ jumbo_static_library("renderer") {
"//base:i18n",
"//components/autofill/content/common/mojom",
"//components/autofill/core/common",
+ "//components/safe_browsing:buildflags",
"//components/strings",
"//content/public/common",
"//content/public/renderer",
diff --git a/chromium/components/autofill/content/renderer/DEPS b/chromium/components/autofill/content/renderer/DEPS
index 693c485473a..ac347ebee19 100644
--- a/chromium/components/autofill/content/renderer/DEPS
+++ b/chromium/components/autofill/content/renderer/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+content/public/common",
"+content/public/renderer",
+ "+components/safe_browsing/buildflags.h",
"+third_party/re2",
# Allow inclusion of WebKit API files.
"+third_party/blink/public/common",
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index 7b886347fb6..5c479361950 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -203,7 +203,7 @@ void AutofillAgent::DidChangeScrollOffset() {
->PostTask(FROM_HERE,
base::BindOnce(&AutofillAgent::DidChangeScrollOffsetImpl,
weak_ptr_factory_.GetWeakPtr(), element_));
- } else if (!IsKeyboardAccessoryEnabled()) {
+ } else {
HidePopup();
}
}
@@ -224,8 +224,7 @@ void AutofillAgent::DidChangeScrollOffsetImpl(
}
// Ignore subsequent scroll offset changes.
- if (!IsKeyboardAccessoryEnabled())
- HidePopup();
+ HidePopup();
}
void AutofillAgent::FocusedElementChanged(const WebElement& element) {
@@ -639,8 +638,7 @@ void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
// criteria are not met.
WebString value = element.EditingValue();
if (value.length() > kMaxDataLength ||
- (!IsKeyboardAccessoryEnabled() && !options.autofill_on_empty_values &&
- value.IsEmpty()) ||
+ (!options.autofill_on_empty_values && value.IsEmpty()) ||
(options.requires_caret_at_end &&
(element.SelectionStart() != element.SelectionEnd() ||
element.SelectionEnd() != static_cast<int>(value.length())))) {
@@ -840,6 +838,10 @@ void AutofillAgent::HidePopup() {
is_popup_possibly_visible_ = false;
is_generation_popup_possibly_visible_ = false;
+ // The keyboard accessory has a separate, more complex hiding logic.
+ if (IsKeyboardAccessoryEnabled())
+ return;
+
GetAutofillDriver()->HidePopup();
}
@@ -910,9 +912,12 @@ void AutofillAgent::SelectFieldOptionsChanged(
weak_ptr_factory_.GetWeakPtr(), element));
}
-bool AutofillAgent::TryToShowTouchToFill(const WebFormControlElement& element) {
- // This is currently only implemented for passwords. Consider supporting other
- // autofill types in the future as well.
+bool AutofillAgent::ShouldSuppressKeyboard(
+ const WebFormControlElement& element) {
+ // The keyboard should be suppressed if we can show the Touch To Fill UI.
+ //
+ // Note: This is currently only implemented for passwords. Consider supporting
+ // other autofill types in the future as well.
return IsTouchToFillEnabled() &&
password_autofill_agent_->TryToShowTouchToFill(element);
}
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.h b/chromium/components/autofill/content/renderer/autofill_agent.h
index ce3619c5ebb..e552ea1c5a6 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/autofill_agent.h
@@ -204,7 +204,7 @@ class AutofillAgent : public content::RenderFrameObserver,
const blink::WebFormControlElement& element) override;
void SelectControlDidChange(
const blink::WebFormControlElement& element) override;
- bool TryToShowTouchToFill(
+ bool ShouldSuppressKeyboard(
const blink::WebFormControlElement& element) override;
void HandleFocusChangeComplete();
diff --git a/chromium/components/autofill/content/renderer/html_based_username_detector.cc b/chromium/components/autofill/content/renderer/html_based_username_detector.cc
index d43ea915ea7..1d5608b0f51 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector.cc
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector.cc
@@ -5,7 +5,9 @@
#include "components/autofill/content/renderer/html_based_username_detector.h"
#include <algorithm>
+#include <string>
#include <tuple>
+#include <utility>
#include "base/containers/flat_set.h"
#include "base/i18n/case_conversion.h"
@@ -15,6 +17,7 @@
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/html_based_username_detector_vocabulary.h"
+#include "components/autofill/core/common/form_data.h"
#include "third_party/blink/public/web/web_form_element.h"
using blink::WebFormControlElement;
@@ -223,23 +226,25 @@ void RemoveFieldsWithNegativeWords(
void FindWordsFromCategoryInForm(
const std::vector<UsernameFieldData>& possible_usernames_data,
const CategoryOfWords& category,
- std::vector<blink::WebInputElement>* username_predictions) {
+ std::vector<uint32_t>* username_predictions) {
// Auxiliary element that contains the first field (in order of appearance in
// the form) in which a substring is encountered.
- WebInputElement chosen_field;
+ uint32_t chosen_field_renderer_id = FormData::kNotSetFormRendererId;
size_t fields_found = 0;
for (const UsernameFieldData& field_data : possible_usernames_data) {
if (ContainsWordFromCategory(field_data, category)) {
- if (fields_found == 0)
- chosen_field = field_data.input_element;
+ if (fields_found == 0) {
+ chosen_field_renderer_id =
+ field_data.input_element.UniqueRendererFormControlId();
+ }
fields_found++;
}
}
if (fields_found > 0 && fields_found <= 2)
- if (!base::Contains(*username_predictions, chosen_field))
- username_predictions->push_back(chosen_field);
+ if (!base::Contains(*username_predictions, chosen_field_renderer_id))
+ username_predictions->push_back(chosen_field_renderer_id);
}
// Find username elements if there is no cached result for the given form and
@@ -247,7 +252,7 @@ void FindWordsFromCategoryInForm(
void FindUsernameFieldInternal(
const std::vector<blink::WebFormControlElement>& all_control_elements,
const FormData& form_data,
- std::vector<blink::WebInputElement>* username_predictions) {
+ std::vector<uint32_t>* username_predictions) {
DCHECK(username_predictions);
DCHECK(username_predictions->empty());
@@ -279,9 +284,16 @@ void FindUsernameFieldInternal(
}
}
+// Returns the |unique_renderer_id| of a given |WebFormElement|. If
+// |WebFormElement::IsNull()| return |kNotSetFormRendererId|.
+uint32_t GetFormRendererId(WebFormElement form) {
+ return form.IsNull() ? FormData::kNotSetFormRendererId
+ : form.UniqueRendererFormId();
+}
+
} // namespace
-const std::vector<WebInputElement>& GetPredictionsFieldBasedOnHtmlAttributes(
+const std::vector<uint32_t>& GetPredictionsFieldBasedOnHtmlAttributes(
const std::vector<WebFormControlElement>& all_control_elements,
const FormData& form_data,
UsernameDetectorCache* username_detector_cache) {
@@ -293,18 +305,17 @@ const std::vector<WebInputElement>& GetPredictionsFieldBasedOnHtmlAttributes(
// All elements in |all_control_elements| should have the same |Form()|.
DCHECK(AllElementsBelongsToSameForm(all_control_elements));
-
- const WebFormElement form = all_control_elements[0].Form();
+ const WebFormElement form = all_control_elements.at(0).Form();
// True if the cache has no entry for |form|.
bool cache_miss = true;
// Iterator pointing to the entry for |form| if the entry for |form| is found.
UsernameDetectorCache::iterator form_position;
std::tie(form_position, cache_miss) = username_detector_cache->insert(
- std::make_pair(form, std::vector<WebInputElement>()));
+ std::make_pair(GetFormRendererId(form), std::vector<uint32_t>()));
if (cache_miss) {
- std::vector<WebInputElement> username_predictions;
+ std::vector<uint32_t> username_predictions;
FindUsernameFieldInternal(all_control_elements, form_data,
&username_predictions);
if (!username_predictions.empty())
diff --git a/chromium/components/autofill/content/renderer/html_based_username_detector.h b/chromium/components/autofill/content/renderer/html_based_username_detector.h
index ffebdd8b2b9..7b55abdd5cd 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector.h
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector.h
@@ -6,6 +6,7 @@
#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_HTML_BASED_USERNAME_DETECTOR_H_
#include <map>
+#include <vector>
#include "components/autofill/core/common/password_form.h"
#include "third_party/blink/public/web/web_form_control_element.h"
@@ -13,10 +14,9 @@
namespace autofill {
-// The detector's cache is a map from WebFormElement to the list of predictions
-// for the given form (in the order of decreasing reliability).
-using UsernameDetectorCache =
- std::map<blink::WebFormElement, std::vector<blink::WebInputElement>>;
+// The detector's cache is a map from a |unique_renderer_id| to the list of
+// predictions for the given form (in the order of decreasing reliability).
+using UsernameDetectorCache = std::map<uint32_t, std::vector<uint32_t>>;
// Classifier for getting username field by analyzing HTML attribute values.
// The algorithm looks for words that are likely to point to username field (ex.
@@ -29,8 +29,7 @@ using UsernameDetectorCache =
// data. Otherwise, the detector will be run and the outcome will be saved to
// the cache. The function returns a reference to the vector of predictions,
// which is stored in the cache.
-const std::vector<blink::WebInputElement>&
-GetPredictionsFieldBasedOnHtmlAttributes(
+const std::vector<uint32_t>& GetPredictionsFieldBasedOnHtmlAttributes(
const std::vector<blink::WebFormControlElement>& all_control_elements,
const FormData& form_data,
UsernameDetectorCache* username_detector_cache);
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index a61ea84ab19..2a5bc31ad6a 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -33,6 +33,7 @@
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/safe_browsing/buildflags.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
@@ -265,15 +266,13 @@ void FindFormElements(content::RenderFrame* render_frame,
WebVector<WebFormElement> forms;
doc.Forms(forms);
- for (size_t i = 0; i < forms.size(); ++i) {
- WebFormElement fe = forms[i];
-
+ for (const WebFormElement& form : forms) {
// Action URL must match.
- if (data.action != form_util::GetCanonicalActionForForm(fe))
+ if (data.action != form_util::GetCanonicalActionForForm(form))
continue;
std::vector<WebFormControlElement> control_elements =
- form_util::ExtractAutofillableElementsInForm(fe);
+ form_util::ExtractAutofillableElementsInForm(form);
FormInputElementMap cur_map;
if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
&cur_map))
@@ -305,11 +304,6 @@ bool DoUsernamesMatch(const base::string16& potential_suggestion,
potential_suggestion);
}
-// Returns whether the given |element| is editable.
-bool IsElementAutocompletable(const WebInputElement& element) {
- return IsElementEditable(element);
-}
-
// Returns whether the |username_element| is allowed to be autofilled.
//
// Note that if the user interacts with the |password_field| and the
@@ -318,8 +312,7 @@ bool IsElementAutocompletable(const WebInputElement& element) {
// if it has been classified as username by accident.
bool IsUsernameAmendable(const WebInputElement& username_element,
bool is_password_field_selected) {
- return !username_element.IsNull() &&
- IsElementAutocompletable(username_element) &&
+ return !username_element.IsNull() && IsElementEditable(username_element) &&
(!is_password_field_selected || username_element.IsAutofilled() ||
username_element.Value().IsEmpty());
}
@@ -557,8 +550,7 @@ WebInputElement FindUsernameElementPrecedingPasswordElement(
--iter;
const WebInputElement* input = ToWebInputElement(&*iter);
if (input && input->IsTextField() && !input->IsPasswordFieldForAutofill() &&
- IsElementAutocompletable(*input) &&
- form_util::IsWebElementVisible(*input)) {
+ IsElementEditable(*input) && form_util::IsWebElementVisible(*input)) {
return *input;
}
}
@@ -573,6 +565,25 @@ WebInputElement ConvertToWebInput(const WebFormControlElement& element) {
return input ? *input : WebInputElement();
}
+// Returns true if |element|'s frame origin is not PSL matched with the origin
+// of any parent frame.
+bool IsInCrossOriginIframe(const WebInputElement& element) {
+ WebFrame* cur_frame = element.GetDocument().GetFrame();
+ WebString bottom_frame_origin = cur_frame->GetSecurityOrigin().ToString();
+
+ DCHECK(cur_frame);
+
+ while (cur_frame->Parent()) {
+ cur_frame = cur_frame->Parent();
+ if (!IsPublicSuffixDomainMatch(
+ bottom_frame_origin.Utf8(),
+ cur_frame->GetSecurityOrigin().ToString().Utf8())) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -752,7 +763,7 @@ bool PasswordAutofillAgent::FillSuggestion(
if (!FindPasswordInfoForElement(*element, &username_element,
&password_element, &password_info) ||
- !IsElementAutocompletable(password_element)) {
+ (!password_element.IsNull() && !IsElementEditable(password_element))) {
return false;
}
@@ -764,7 +775,7 @@ bool PasswordAutofillAgent::FillSuggestion(
// Call OnFieldAutofilled before WebInputElement::SetAutofillState which may
// cause frame closing.
- if (password_generation_agent_)
+ if (!password_element.IsNull() && password_generation_agent_)
password_generation_agent_->OnFieldAutofilled(password_element);
if (IsUsernameAmendable(username_element,
@@ -773,7 +784,8 @@ bool PasswordAutofillAgent::FillSuggestion(
FillField(&username_element, username);
}
- FillPasswordFieldAndSave(&password_element, password);
+ if (!password_element.IsNull())
+ FillPasswordFieldAndSave(&password_element, password);
WebInputElement mutable_filled_element = *element;
mutable_filled_element.SetSelectionRange(element->Value().length(),
@@ -830,7 +842,7 @@ bool PasswordAutofillAgent::PreviewSuggestion(
if (!FindPasswordInfoForElement(*element, &username_element,
&password_element, &password_info) ||
- !IsElementAutocompletable(password_element)) {
+ (!password_element.IsNull() && !IsElementEditable(password_element))) {
return false;
}
@@ -845,9 +857,11 @@ bool PasswordAutofillAgent::PreviewSuggestion(
form_util::PreviewSuggestion(username_element.SuggestedValue().Utf16(),
username_query_prefix_, &username_element);
}
- password_autofill_state_ = password_element.GetAutofillState();
- password_element.SetSuggestedValue(password);
- password_element.SetAutofillState(WebAutofillState::kPreviewed);
+ if (!password_element.IsNull()) {
+ password_autofill_state_ = password_element.GetAutofillState();
+ password_element.SetSuggestedValue(password);
+ password_element.SetAutofillState(WebAutofillState::kPreviewed);
+ }
return true;
}
@@ -958,8 +972,13 @@ bool PasswordAutofillAgent::IsUsernameOrPasswordField(
bool PasswordAutofillAgent::TryToShowTouchToFill(
const WebFormControlElement& control_element) {
const WebInputElement* element = ToWebInputElement(&control_element);
- return element && (base::Contains(web_input_to_password_info_, *element) ||
- base::Contains(password_to_username_, *element));
+ if (!element || (!base::Contains(web_input_to_password_info_, *element) &&
+ !base::Contains(password_to_username_, *element))) {
+ return false;
+ }
+
+ GetPasswordManagerDriver()->ShowTouchToFill();
+ return true;
}
bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
@@ -974,7 +993,8 @@ bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
if (IsUsernameOrPasswordField(element)) {
WebLocalFrame* frame = render_frame()->GetWebFrame();
GURL frame_url = GURL(frame->GetDocument().Url());
-#if defined(SAFE_BROWSING_DB_LOCAL)
+// Enabled on desktop and Android
+#if BUILDFLAG(FULL_SAFE_BROWSING) || BUILDFLAG(SAFE_BROWSING_DB_REMOTE)
if (!checked_safe_browsing_reputation_) {
checked_safe_browsing_reputation_ = true;
GURL action_url =
@@ -989,13 +1009,11 @@ bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
return false;
}
- // If autocomplete='off' is set on the form elements, no suggestion dialog
- // should be shown. However, return |true| to indicate that this is a known
- // password form and that the request to show suggestions has been handled (as
- // a no-op).
- if (!element.IsTextField() || !IsElementAutocompletable(element) ||
- !IsElementAutocompletable(password_element))
+ // Check that all fillable elements are editable.
+ if (!element.IsTextField() || !IsElementEditable(element) ||
+ (!password_element.IsNull() && !IsElementEditable(password_element))) {
return true;
+ }
if (element.NameForAutofill().IsEmpty() &&
!DoesFormContainAmbiguousOrEmptyNames(password_info->fill_data)) {
@@ -1381,18 +1399,29 @@ void PasswordAutofillAgent::FillUsingRendererIDs(
GetPasswordManagerDriver().get()));
logger->LogMessage(Logger::STRING_ON_FILL_PASSWORD_FORM_METHOD);
}
+
+ bool username_password_fields_not_set =
+ form_data.username_field.unique_renderer_id ==
+ FormFieldData::kNotSetFormControlRendererId &&
+ form_data.password_field.unique_renderer_id ==
+ FormFieldData::kNotSetFormControlRendererId;
+ if (username_password_fields_not_set) {
+ // No fields for filling were found during parsing, which means filling
+ // fallback case. So save data for fallback filling.
+ MaybeStoreFallbackData(form_data);
+ return;
+ }
+
WebInputElement username_element, password_element;
std::tie(username_element, password_element) =
FindUsernamePasswordElements(form_data);
- if (password_element.IsNull()) {
+ bool is_single_username_fill = form_data.password_field.unique_renderer_id ==
+ FormFieldData::kNotSetFormControlRendererId;
+ WebElement main_element =
+ is_single_username_fill ? username_element : password_element;
+ if (main_element.IsNull()) {
MaybeStoreFallbackData(form_data);
- if (form_data.password_field.unique_renderer_id ==
- FormFieldData::kNotSetFormControlRendererId) {
- // If the password_field.unique_renderer_id was not set, this was never
- // meant as an honest attempt to fill the form. Therefore, don't log it as
- // such.
- return;
- }
+ // TODO(https://crbug.com/959776): Fix logging for single username.
LogFirstFillingResult(form_data, FillingResult::kNoPasswordElement);
return;
}
@@ -1407,8 +1436,8 @@ void PasswordAutofillAgent::FillUsingRendererIDs(
return;
}
- FillFormOnPasswordReceived(form_data, username_element, password_element,
- &field_data_manager_, logger.get());
+ FillUserNameAndPassword(username_element, password_element, form_data,
+ logger.get());
}
// mojom::PasswordAutofillAgent:
@@ -1446,8 +1475,8 @@ void PasswordAutofillAgent::FillPasswordForm(
element.IsPasswordFieldForAutofill()
? element
: web_input_to_password_info_[element].password_field;
- FillFormOnPasswordReceived(form_data, username_element, password_element,
- &field_data_manager_, logger.get());
+ FillUserNameAndPassword(username_element, password_element, form_data,
+ logger.get());
}
}
@@ -1572,6 +1601,13 @@ std::unique_ptr<PasswordForm> PasswordAutofillAgent::GetPasswordFormFromWebForm(
}
std::unique_ptr<PasswordForm>
+PasswordAutofillAgent::GetSimplifiedPasswordFormFromWebForm(
+ const WebFormElement& web_form) {
+ return CreateSimplifiedPasswordFormFromWebForm(web_form,
+ &field_data_manager_);
+}
+
+std::unique_ptr<PasswordForm>
PasswordAutofillAgent::GetPasswordFormFromUnownedInputElements() {
// The element's frame might have been detached in the meantime (see
// http://crbug.com/585363, comments 5 and 6), in which case |frame| will
@@ -1588,6 +1624,18 @@ PasswordAutofillAgent::GetPasswordFormFromUnownedInputElements() {
&username_detector_cache_);
}
+std::unique_ptr<PasswordForm>
+PasswordAutofillAgent::GetSimplifiedPasswordFormFromUnownedInputElements() {
+ content::RenderFrame* frame = render_frame();
+ if (!frame)
+ return nullptr;
+ WebLocalFrame* web_frame = frame->GetWebFrame();
+ if (!web_frame)
+ return nullptr;
+ return CreateSimplifiedPasswordFormFromUnownedInputElements(
+ *web_frame, &field_data_manager_);
+}
+
// mojom::PasswordAutofillAgent:
void PasswordAutofillAgent::SetLoggingState(bool active) {
logging_state_active_ = active;
@@ -1670,7 +1718,7 @@ void PasswordAutofillAgent::ClearPreview(WebInputElement* username,
username->SetSelectionRange(username_query_prefix_.length(),
username->Value().length());
}
- if (!password->SuggestedValue().IsEmpty()) {
+ if (!password->IsNull() && !password->SuggestedValue().IsEmpty()) {
password->SetSuggestedValue(WebString());
password->SetAutofillState(password_autofill_state_);
}
@@ -1709,18 +1757,26 @@ void PasswordAutofillAgent::ProvisionallySavePassword(
}
bool PasswordAutofillAgent::FillUserNameAndPassword(
- WebInputElement* username_element,
- WebInputElement* password_element,
+ WebInputElement username_element,
+ WebInputElement password_element,
const PasswordFormFillData& fill_data,
- bool exact_username_match,
- bool username_may_use_prefilled_placeholder,
- FieldDataManager* field_data_manager,
RendererSavePasswordProgressLogger* logger) {
if (logger)
logger->LogMessage(Logger::STRING_FILL_USERNAME_AND_PASSWORD_METHOD);
+ bool is_single_username_fill = password_element.IsNull();
+ WebInputElement main_element =
+ is_single_username_fill ? username_element : password_element;
+
+ if (IsInCrossOriginIframe(main_element)) {
+ if (logger)
+ logger->LogMessage(Logger::STRING_FAILED_TO_FILL_INTO_IFRAME);
+ LogFirstFillingResult(fill_data, FillingResult::kBlockedByFrameHierarchy);
+ return false;
+ }
+
// Don't fill username if password can't be set.
- if (!IsElementAutocompletable(*password_element)) {
+ if (!IsElementEditable(main_element)) {
if (logger) {
logger->LogMessage(
Logger::STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT);
@@ -1746,24 +1802,24 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
// or email" or there is a server hint that it is just a placeholder).
bool prefilled_placeholder_username = false;
- if (!username_element->IsNull()) {
+ if (!username_element.IsNull()) {
// This is a heuristic guess. If the credential is stored for
// www.example.com, the username may be prefilled with "@example.com".
std::string possible_email_domain =
GetRegistryControlledDomain(fill_data.origin);
prefilled_placeholder_username =
- !username_element->Value().IsEmpty() &&
- (PossiblePrefilledUsernameValue(username_element->Value().Utf8(),
+ !username_element.Value().IsEmpty() &&
+ (PossiblePrefilledUsernameValue(username_element.Value().Utf8(),
possible_email_domain) ||
- username_may_use_prefilled_placeholder);
- if (!username_element->Value().IsEmpty() &&
+ fill_data.username_may_use_prefilled_placeholder);
+ if (!username_element.Value().IsEmpty() &&
!prefilled_placeholder_username) {
// Username is filled with content that was not on a list of known
// placeholder texts (e.g. "username or email") nor there is server-side
// data that this value is placeholder.
- current_username = username_element->Value().Utf16();
- } else if (IsElementAutocompletable(*username_element)) {
+ current_username = username_element.Value().Utf16();
+ } else if (IsElementEditable(username_element)) {
current_username = fill_data.username_field.value;
}
}
@@ -1772,11 +1828,14 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
base::string16 username;
base::string16 password;
+ bool exact_username_match =
+ username_element.IsNull() || IsElementEditable(username_element);
+
FindMatchesByUsername(fill_data, current_username, exact_username_match,
logger, &username, &password);
- if (password.empty()) {
- if (!username_element->IsNull() && !username_element->Value().IsEmpty() &&
+ if (password.empty() && !is_single_username_fill) {
+ if (!username_element.IsNull() && !username_element.Value().IsEmpty() &&
!prefilled_placeholder_username) {
LogPrefilledUsernameFillOutcome(
PrefilledUsernameFillOutcome::kPrefilledUsernameNotOverridden);
@@ -1797,52 +1856,31 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
// Call OnFieldAutofilled before WebInputElement::SetAutofillState which may
// cause frame closing.
- if (password_generation_agent_)
- password_generation_agent_->OnFieldAutofilled(*password_element);
+ if (password_generation_agent_ && !is_single_username_fill)
+ password_generation_agent_->OnFieldAutofilled(password_element);
// Input matches the username, fill in required values.
- if (!username_element->IsNull() &&
- IsElementAutocompletable(*username_element)) {
- if (!username.empty() && (username_element->Value().IsEmpty() ||
+ if (!username_element.IsNull() && IsElementEditable(username_element)) {
+ if (!username.empty() && (username_element.Value().IsEmpty() ||
prefilled_placeholder_username)) {
- username_element->SetSuggestedValue(WebString::FromUTF16(username));
- gatekeeper_.RegisterElement(username_element);
+ AutofillField(username, username_element);
if (prefilled_placeholder_username) {
LogPrefilledUsernameFillOutcome(
PrefilledUsernameFillOutcome::
kPrefilledPlaceholderUsernameOverridden);
}
}
- field_data_manager->UpdateFieldDataMap(
- *username_element, username,
- FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD);
- username_element->SetAutofillState(WebAutofillState::kAutofilled);
+ username_element.SetAutofillState(WebAutofillState::kAutofilled);
if (logger)
- logger->LogElementName(Logger::STRING_USERNAME_FILLED, *username_element);
+ logger->LogElementName(Logger::STRING_USERNAME_FILLED, username_element);
}
- // Wait to fill in the password until a user gesture occurs. This is to make
- // sure that we do not fill in the DOM with a password until we believe the
- // user is intentionally interacting with the page.
- if (password_element->Value().Utf16() != password)
- password_element->SetSuggestedValue(WebString::FromUTF16(password));
- field_data_manager->UpdateFieldDataMap(
- *password_element, password,
- FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD);
- gatekeeper_.RegisterElement(password_element);
- password_element->SetAutofillState(WebAutofillState::kAutofilled);
-
- if (logger)
- logger->LogElementName(Logger::STRING_PASSWORD_FILLED, *password_element);
-
- if (!username.empty() && !username_element->IsNull()) {
- autofilled_elements_cache_.emplace(
- username_element->UniqueRendererFormControlId(),
- WebString::FromUTF16(username));
+ if (!is_single_username_fill) {
+ AutofillField(password, password_element);
+ if (logger)
+ logger->LogElementName(Logger::STRING_PASSWORD_FILLED, password_element);
}
- autofilled_elements_cache_.emplace(
- password_element->UniqueRendererFormControlId(),
- WebString::FromUTF16(password));
+
LogFirstFillingResult(fill_data, FillingResult::kSuccess);
return true;
}
@@ -1856,52 +1894,6 @@ void PasswordAutofillAgent::LogPrefilledUsernameFillOutcome(
outcome);
}
-bool PasswordAutofillAgent::FillFormOnPasswordReceived(
- const PasswordFormFillData& fill_data,
- WebInputElement username_element,
- WebInputElement password_element,
- FieldDataManager* field_data_manager,
- RendererSavePasswordProgressLogger* logger) {
- // Do not fill if the password field is in a chain of iframes not having
- // identical origin.
- WebFrame* cur_frame = password_element.GetDocument().GetFrame();
- WebString bottom_frame_origin = cur_frame->GetSecurityOrigin().ToString();
-
- DCHECK(cur_frame);
-
- while (cur_frame->Parent()) {
- cur_frame = cur_frame->Parent();
- if (!IsPublicSuffixDomainMatch(
- bottom_frame_origin.Utf8(),
- cur_frame->GetSecurityOrigin().ToString().Utf8())) {
- if (logger)
- logger->LogMessage(Logger::STRING_FAILED_TO_FILL_INTO_IFRAME);
- LogFirstFillingResult(fill_data, FillingResult::kBlockedByFrameHierarchy);
- return false;
- }
- }
-
- // If we can't modify the password, don't try to set the username
- if (!IsElementAutocompletable(password_element)) {
- if (logger) {
- logger->LogMessage(
- Logger::STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT);
- }
- LogFirstFillingResult(fill_data,
- FillingResult::kPasswordElementIsNotAutocompleteable);
- return false;
- }
-
- bool exact_username_match =
- username_element.IsNull() || IsElementEditable(username_element);
- // Use the exact match for the editable username fields and allow prefix
- // match for read-only username fields.
- return FillUserNameAndPassword(
- &username_element, &password_element, fill_data, exact_username_match,
- fill_data.username_may_use_prefilled_placeholder, field_data_manager,
- logger);
-}
-
void PasswordAutofillAgent::OnProvisionallySaveForm(
const WebFormElement& form,
const WebFormControlElement& element,
@@ -1955,10 +1947,8 @@ void PasswordAutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
}
void PasswordAutofillAgent::HidePopup() {
- AutofillAgent* agent = autofill_agent_.get();
- if (agent) {
+ if (autofill_agent_)
autofill_agent_->GetAutofillDriver()->HidePopup();
- }
}
const mojo::AssociatedRemote<mojom::PasswordManagerDriver>&
@@ -2127,4 +2117,19 @@ void PasswordAutofillAgent::TryFixAutofilledForm(
}
}
+void PasswordAutofillAgent::AutofillField(const base::string16& value,
+ WebInputElement field) {
+ if (field.Value().Utf16() != value)
+ field.SetSuggestedValue(WebString::FromUTF16(value));
+ field.SetAutofillState(WebAutofillState::kAutofilled);
+ // Wait to fill until a user gesture occurs. This is to make sure that we do
+ // not fill in the DOM with a password until we believe the user is
+ // intentionally interacting with the page.
+ gatekeeper_.RegisterElement(&field);
+ field_data_manager_.UpdateFieldDataMap(
+ field, value, FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD);
+ autofilled_elements_cache_.emplace(field.UniqueRendererFormControlId(),
+ WebString::FromUTF16(value));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.h b/chromium/components/autofill/content/renderer/password_autofill_agent.h
index 3fbdf21327b..6346b5f2d92 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.h
@@ -7,6 +7,7 @@
#include <map>
#include <memory>
+#include <string>
#include <utility>
#include <vector>
@@ -225,9 +226,19 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
std::unique_ptr<PasswordForm> GetPasswordFormFromWebForm(
const blink::WebFormElement& web_form);
+ // Creates a |PasswordForm| from |web_form|, that contains only the
+ // |form_data|, the origin and the gaia flags.
+ std::unique_ptr<PasswordForm> GetSimplifiedPasswordFormFromWebForm(
+ const blink::WebFormElement& web_form);
+
// Creates a |PasswordForm| of fields that are not enclosed in any <form> tag.
std::unique_ptr<PasswordForm> GetPasswordFormFromUnownedInputElements();
+ // Creates a |PasswordForm| containing only the |form_data|, origin and gaia
+ // flags, for fields that are not enclosed in any <form> tag.
+ std::unique_ptr<PasswordForm>
+ GetSimplifiedPasswordFormFromUnownedInputElements();
+
bool logging_state_active() const { return logging_state_active_; }
// Determine whether the current frame is allowed to access the password
@@ -392,16 +403,10 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// This function attempts to fill |username_element| and |password_element|
// with values from |fill_data|. The |username_element| and |password_element|
// will only have the suggestedValue set. If a match is found, return true and
- // |field_data_manager| will be modified with the autofilled credentials and
- // |FieldPropertiesFlags::AUTOFILLED| flag.
- // If |username_may_use_prefilled_placeholder| then this function may
- // overwrite the value of username field.
- bool FillUserNameAndPassword(blink::WebInputElement* username_element,
- blink::WebInputElement* password_element,
+ // Returns true if the password is filled.
+ bool FillUserNameAndPassword(blink::WebInputElement username_element,
+ blink::WebInputElement password_element,
const PasswordFormFillData& fill_data,
- bool exact_username_match,
- bool username_may_use_prefilled_placeholder,
- FieldDataManager* field_data_manager,
RendererSavePasswordProgressLogger* logger);
// Logs whether a username value that was prefilled by the website was
@@ -409,18 +414,6 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// only one value per |PasswordAutofillAgent| instance.
void LogPrefilledUsernameFillOutcome(PrefilledUsernameFillOutcome outcome);
- // Attempts to fill |username_element| and |password_element| with the
- // |fill_data|. Will use the data corresponding to the preferred username,
- // unless the |username_element| already has a value set. In that case,
- // attempts to fill the password matching the already filled username, if
- // such a password exists. The |password_element| will have the
- // |suggestedValue| set. Returns true if the password is filled.
- bool FillFormOnPasswordReceived(const PasswordFormFillData& fill_data,
- blink::WebInputElement username_element,
- blink::WebInputElement password_element,
- FieldDataManager* field_data_manager,
- RendererSavePasswordProgressLogger* logger);
-
// Helper function called when form submission is successful.
void FireSubmissionIfFormDisappear(mojom::SubmissionIndicatorEvent event);
@@ -468,6 +461,11 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
void TryFixAutofilledForm(
std::vector<blink::WebFormControlElement>* control_elements) const;
+ // Autofills |field| with |value| and updates |gatekeeper_|,
+ // |field_data_manager_|, |autofilled_elements_cache_|. |field| should be
+ // non-null.
+ void AutofillField(const base::string16& value, blink::WebInputElement field);
+
// The logins we have filled so far with their associated info.
WebInputToPasswordInfoMap web_input_to_password_info_;
// A (sort-of) reverse map to |web_input_to_password_info_|.
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
index 0560d4430f3..9e6c94e1581 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -39,6 +39,7 @@
#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"
+using blink::WebElement;
using blink::WebFormControlElement;
using blink::WebFormElement;
using blink::WebInputElement;
@@ -386,7 +387,7 @@ const FormFieldData* FindUsernameInPredictions(
// representation of that form. |username_detector_cache| is optional, and can
// be used to spare recomputation if called multiple times for the same form.
std::vector<uint32_t> GetUsernamePredictions(
- const std::vector<blink::WebFormControlElement>& control_elements,
+ const std::vector<WebFormControlElement>& control_elements,
const FormData& form_data,
UsernameDetectorCache* username_detector_cache) {
std::vector<uint32_t> username_predictions;
@@ -396,30 +397,22 @@ std::vector<uint32_t> GetUsernamePredictions(
if (!username_detector_cache)
username_detector_cache = &dummy_cache;
- const std::vector<WebInputElement>& username_predictions_dom =
- GetPredictionsFieldBasedOnHtmlAttributes(control_elements, form_data,
- username_detector_cache);
- username_predictions.reserve(username_predictions_dom.size());
- for (const WebInputElement& element : username_predictions_dom) {
- username_predictions.push_back(element.UniqueRendererFormControlId());
- }
- return username_predictions;
+ return GetPredictionsFieldBasedOnHtmlAttributes(control_elements, form_data,
+ username_detector_cache);
}
// Get information about a login form encapsulated in a PasswordForm struct.
// If an element of |form| has an entry in |nonscript_modified_values|, the
// associated string is used instead of the element's value to create
// the PasswordForm.
-bool GetPasswordForm(
- const GURL& form_origin,
- const std::vector<blink::WebFormControlElement>& control_elements,
- PasswordForm* password_form,
- const FormsPredictionsMap* form_predictions,
- UsernameDetectorCache* username_detector_cache) {
+bool GetPasswordForm(const GURL& form_origin,
+ const std::vector<WebFormControlElement>& control_elements,
+ PasswordForm* password_form,
+ const FormsPredictionsMap* form_predictions,
+ UsernameDetectorCache* username_detector_cache) {
DCHECK(!control_elements.empty());
const FormData& form_data = password_form->form_data;
-
PasswordContents password_contents = GetPasswordContents(form_data.fields);
switch (password_contents) {
case PasswordContents::kEnabled:
@@ -435,7 +428,6 @@ bool GetPasswordForm(
case PasswordContents::kNone:
return false;
}
-
// Evaluate the context of the fields.
password_form->form_data.username_predictions = GetUsernamePredictions(
control_elements, form_data, username_detector_cache);
@@ -823,10 +815,10 @@ bool IsGaiaReauthenticationForm(const blink::WebFormElement& form) {
bool has_rart_field = false;
bool has_continue_field = false;
- blink::WebVector<blink::WebFormControlElement> web_control_elements;
+ blink::WebVector<WebFormControlElement> web_control_elements;
form.GetFormControlElements(web_control_elements);
- for (const blink::WebFormControlElement& element : web_control_elements) {
+ for (const WebFormControlElement& element : web_control_elements) {
// We're only interested in the presence
// of <input type="hidden" /> elements.
static base::NoDestructor<WebString> kHidden("hidden");
@@ -860,6 +852,31 @@ bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form) {
return should_skip_password == "1";
}
+std::unique_ptr<PasswordForm> CreateSimplifiedPasswordFormFromWebForm(
+ const WebFormElement& web_form,
+ const FieldDataManager* field_data_manager) {
+ if (web_form.IsNull())
+ return nullptr;
+
+ auto password_form = std::make_unique<PasswordForm>();
+ password_form->origin =
+ form_util::GetCanonicalOriginForDocument(web_form.GetDocument());
+ password_form->signon_realm = GetSignOnRealm(password_form->origin);
+
+ password_form->form_data.is_gaia_with_skip_save_password_form =
+ IsGaiaWithSkipSavePasswordForm(web_form) ||
+ IsGaiaReauthenticationForm(web_form);
+
+ if (!WebFormElementToFormData(web_form, WebFormControlElement(),
+ field_data_manager, form_util::EXTRACT_VALUE,
+ &password_form->form_data,
+ nullptr /* FormFieldData */)) {
+ return nullptr;
+ }
+
+ return password_form;
+}
+
std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
const WebFormElement& web_form,
const FieldDataManager* field_data_manager,
@@ -876,12 +893,12 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
IsGaiaWithSkipSavePasswordForm(web_form) ||
IsGaiaReauthenticationForm(web_form);
- blink::WebVector<blink::WebFormControlElement> control_elements;
+ blink::WebVector<WebFormControlElement> control_elements;
web_form.GetFormControlElements(control_elements);
if (control_elements.empty())
return nullptr;
- if (!WebFormElementToFormData(web_form, blink::WebFormControlElement(),
+ if (!WebFormElementToFormData(web_form, WebFormControlElement(),
field_data_manager, form_util::EXTRACT_VALUE,
&password_form->form_data,
nullptr /* FormFieldData */)) {
@@ -897,13 +914,38 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
return password_form;
}
+std::unique_ptr<PasswordForm>
+CreateSimplifiedPasswordFormFromUnownedInputElements(
+ const WebLocalFrame& frame,
+ const FieldDataManager* field_data_manager) {
+ std::vector<WebElement> fieldsets;
+ std::vector<WebFormControlElement> control_elements =
+ form_util::GetUnownedFormFieldElements(frame.GetDocument().All(),
+ &fieldsets);
+ if (control_elements.empty())
+ return nullptr;
+
+ auto password_form = std::make_unique<PasswordForm>();
+ if (!UnownedPasswordFormElementsAndFieldSetsToFormData(
+ fieldsets, control_elements, nullptr, frame.GetDocument(),
+ field_data_manager, form_util::EXTRACT_VALUE,
+ &password_form->form_data, nullptr /* FormFieldData */)) {
+ return nullptr;
+ }
+
+ password_form->origin =
+ form_util::GetCanonicalOriginForDocument(frame.GetDocument());
+ password_form->signon_realm = GetSignOnRealm(password_form->origin);
+ return password_form;
+}
+
std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
const WebLocalFrame& frame,
const FieldDataManager* field_data_manager,
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache) {
- std::vector<blink::WebElement> fieldsets;
- std::vector<blink::WebFormControlElement> control_elements =
+ std::vector<WebElement> fieldsets;
+ std::vector<WebFormControlElement> control_elements =
form_util::GetUnownedFormFieldElements(frame.GetDocument().All(),
&fieldsets);
if (control_elements.empty())
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
index 390db0b8c40..e02034c893b 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -82,6 +82,12 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache);
+// Creates a |PasswordForm| from DOM which only contains the |form_data| as well
+// as origin, action and gaia flags.
+std::unique_ptr<PasswordForm> CreateSimplifiedPasswordFormFromWebForm(
+ const blink::WebFormElement& form,
+ const FieldDataManager* field_data_manager);
+
// Same as CreatePasswordFormFromWebForm() but for input elements that are not
// enclosed in <form> element.
std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
@@ -90,6 +96,13 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache);
+// Same as CreateSimlePasswordFormFromWebForm() but for input elements that are
+// not enclosed in <form> element.
+std::unique_ptr<PasswordForm>
+CreateSimplifiedPasswordFormFromUnownedInputElements(
+ const blink::WebLocalFrame& frame,
+ const FieldDataManager* field_data_manager);
+
// The "Realm" for the sign-on. This is scheme, host, port.
std::string GetSignOnRealm(const GURL& origin);
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
index 53988a94ec9..02b36b862d4 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -30,10 +30,12 @@
#include "third_party/blink/public/web/web_input_element.h"
#include "third_party/blink/public/web/web_local_frame.h"
+using blink::WebElement;
using blink::WebFormControlElement;
using blink::WebFormElement;
-using blink::WebLocalFrame;
using blink::WebInputElement;
+using blink::WebLocalFrame;
+using blink::WebString;
using blink::WebVector;
namespace autofill {
@@ -286,6 +288,16 @@ class PasswordFormConversionUtilsTest : public content::RenderViewTest {
content::RenderViewTest::TearDown();
}
+ uint32_t GetRendererIdFromWebElementId(WebString id) {
+ WebLocalFrame* frame = GetMainFrame();
+ if (!frame || frame->GetDocument().IsNull())
+ return FormData::kNotSetFormRendererId;
+ WebElement element = frame->GetDocument().GetElementById(id);
+ if (element.IsNull())
+ return FormData::kNotSetFormRendererId;
+ return element.To<WebInputElement>().UniqueRendererFormControlId();
+ }
+
UsernameDetectorCache username_detector_cache_;
private:
@@ -373,73 +385,87 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_DeveloperGroupAttributes) {
const char* first_text_field_parameters[3];
const char* second_text_field_parameters[3];
const char* expected_username_element;
+ const WebString expected_username_id;
const char* expected_username_value;
} cases[] = {
// There are both field name and id.
- {{"username", "id", "johnsmith"},
- {"email", "id", "js@google.com"},
+ {{"username", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"username",
+ "x1d",
"johnsmith"},
// there is no field id.
- {{"username", "", "johnsmith"},
- {"email", "", "js@google.com"},
+ {{"username", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"username",
+ "x1d",
"johnsmith"},
// Upper or mixed case shouldn't matter.
- {{"uSeRnAmE", "id", "johnsmith"},
- {"email", "id", "js@google.com"},
+ {{"uSeRnAmE", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"uSeRnAmE",
+ "x1d",
"johnsmith"},
// Check removal of special characters.
- {{"u1_s2-e3~r4/n5(a)6m#e", "", "johnsmith"},
- {"email", "", "js@google.com"},
+ {{"u1_s2-e3~r4/n5(a)6m#e", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"u1_s2-e3~r4/n5(a)6m#e",
+ "x1d",
"johnsmith"},
// Check guard between field name and field id.
{{"us", "ername", "johnsmith"},
- {"email", "", "js@google.com"},
+ {"email", "id", "js@google.com"},
"email",
+ "id",
"js@google.com"},
// Check removal of fields with latin negative words in developer group.
- {{"email", "", "js@google.com"},
- {"fake_username", "", "johnsmith"},
+ {{"email", "x", "js@google.com"},
+ {"fake_username", "y", "johnsmith"},
"email",
+ "x",
"js@google.com"},
{{"email", "mail", "js@google.com"},
{"user_name", "fullname", "johnsmith"},
"email",
+ "mail",
"js@google.com"},
// Identify latin translations of "username".
- {{"benutzername", "", "johnsmith"},
- {"email", "", "js@google.com"},
+ {{"benutzername", "x", "johnsmith"},
+ {"email", "y", "js@google.com"},
"benutzername",
+ "x",
"johnsmith"},
// Identify latin translations of "user".
- {{"utilizator", "", "johnsmith"},
- {"email", "", "js@google.com"},
+ {{"utilizator", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"utilizator",
+ "x1d",
"johnsmith"},
// Identify technical words.
- {{"loginid", "", "johnsmith"},
- {"email", "", "js@google.com"},
+ {{"loginid", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"loginid",
+ "x1d",
"johnsmith"},
// Identify weak words.
- {{"usrname", "", "johnsmith"},
- {"email", "", "js@google.com"},
+ {{"usrname", "x1d", "johnsmith"},
+ {"email", "y1d", "js@google.com"},
"email",
+ "y1d",
"js@google.com"},
// If a word matches in maximum 2 fields, it is accepted.
// First encounter is selected as username.
- {{"username", "", "johnsmith"},
- {"repeat_username", "", "johnsmith"},
+ {{"username", "x1d", "johnsmith"},
+ {"repeat_username", "y1d", "johnsmith"},
"username",
+ "x1d",
"johnsmith"},
// A short word should be enclosed between delimiters. Otherwise, an
// Occurrence doesn't count.
{{"identity_name", "idn", "johnsmith"},
- {"id", "id", "123"},
+ {"id", "xid", "123"},
"id",
+ "xid",
"123"}};
for (size_t i = 0; i < base::size(cases); ++i) {
@@ -459,10 +485,12 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_DeveloperGroupAttributes) {
std::string html = builder.ProduceHTML();
username_detector_cache_.clear();
+
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
- ASSERT_TRUE(password_form);
+ uint32_t username_renderer_id =
+ GetRendererIdFromWebElementId(cases[i].expected_username_id);
EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
password_form->username_element);
@@ -471,9 +499,8 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_DeveloperGroupAttributes) {
// Check that the username field was found by HTML detector.
ASSERT_EQ(1u, username_detector_cache_.size());
ASSERT_FALSE(username_detector_cache_.begin()->second.empty());
- EXPECT_EQ(
- cases[i].expected_username_element,
- username_detector_cache_.begin()->second[0].NameForAutofill().Utf8());
+ EXPECT_EQ(username_renderer_id,
+ username_detector_cache_.begin()->second[0]);
}
}
@@ -481,11 +508,11 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
// If word matches in more than 2 fields, we don't match on it.
// We search for match with another word.
PasswordFormBuilder builder(kTestFormActionURL);
- builder.AddTextFieldWithoutAutocomplete("address", "user", "someaddress", "",
+ builder.AddTextFieldWithoutAutocomplete("address", "xuser", "someaddress", "",
"");
- builder.AddTextFieldWithoutAutocomplete("loginid", "user", "johnsmith", "",
+ builder.AddTextFieldWithoutAutocomplete("loginid", "yuser", "johnsmith", "",
"");
- builder.AddTextFieldWithoutAutocomplete("tel", "user", "sometel", "", "");
+ builder.AddTextFieldWithoutAutocomplete("tel", "zuser", "sometel", "", "");
builder.AddPasswordField("password", "secret", nullptr);
builder.AddSubmitButton("submit");
std::string html = builder.ProduceHTML();
@@ -494,6 +521,8 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
+ uint32_t username_renderer_id = GetRendererIdFromWebElementId("yuser");
+
ASSERT_TRUE(password_form);
EXPECT_EQ(base::UTF8ToUTF16("loginid"), password_form->username_element);
@@ -501,9 +530,7 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_SeveralDetections) {
// Check that the username field was found by HTML detector.
ASSERT_EQ(1u, username_detector_cache_.size());
ASSERT_EQ(1u, username_detector_cache_.begin()->second.size());
- EXPECT_EQ(
- "loginid",
- username_detector_cache_.begin()->second[0].NameForAutofill().Utf8());
+ EXPECT_EQ(username_renderer_id, username_detector_cache_.begin()->second[0]);
}
TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_UserGroupAttributes) {
@@ -520,69 +547,82 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_UserGroupAttributes) {
const char* first_text_field_parameters[4];
const char* second_text_field_parameters[4];
const char* expected_username_element;
+ const WebString expected_username_id;
const char* expected_username_value;
} cases[] = {
// Label information will decide username.
{{"name1", "id1", "johnsmith", "Username:"},
{"name2", "id2", "js@google.com", "Email:"},
"name1",
+ "id1",
"johnsmith"},
// Placeholder information will decide username.
{{"name1", "id1", "js@google.com", "Email:"},
{"name2", "id2", "johnsmith", "Username:"},
"name2",
+ "id2",
"johnsmith"},
// Check removal of special characters.
{{"name1", "id1", "johnsmith", "U s er n a m e:"},
{"name2", "id2", "js@google.com", "Email:"},
"name1",
+ "id1",
"johnsmith"},
// Check removal of fields with latin negative words in user group.
{{"name1", "id1", "johnsmith", "Username password:"},
{"name2", "id2", "js@google.com", "Email:"},
"name2",
+ "id2",
"js@google.com"},
// Check removal of fields with non-latin negative words in user group.
{{"name1", "id1", "js@google.com", "Email:"},
{"name2", "id2", "johnsmith", "የይለፍቃልየይለፍቃል:"},
"name1",
+ "id1",
"js@google.com"},
// Identify latin translations of "username".
{{"name1", "id1", "johnsmith", "Username:"},
{"name2", "id2", "js@google.com", "Email:"},
"name1",
+ "id1",
"johnsmith"},
// Identify non-latin translations of "username".
{{"name1", "id1", "johnsmith", "用户名:"},
{"name2", "id2", "js@google.com", "Email:"},
"name1",
+ "id1",
"johnsmith"},
// Identify latin translations of "user".
{{"name1", "id1", "johnsmith", "Wosuta:"},
{"name2", "id2", "js@google.com", "Email:"},
"name1",
+ "id1",
"johnsmith"},
// Identify non-latin translations of "user".
{{"name1", "id1", "johnsmith", "истифода:"},
{"name2", "id2", "js@google.com", "Email:"},
"name1",
+ "id1",
"johnsmith"},
// Identify weak words.
{{"name1", "id1", "johnsmith", "Insert your login details:"},
{"name2", "id2", "js@google.com", "Insert your email:"},
"name1",
+ "id1",
"johnsmith"},
// Check user group priority, compared to developer group.
// User group should have higher priority than developer group.
- {{"email", "", "js@google.com", "Username:"},
- {"username", "", "johnsmith", "Email:"},
+ {{"email", "id1", "js@google.com", "Username:"},
+ {"username", "id2", "johnsmith", "Email:"},
"email",
+ "id1",
"js@google.com"},
// Check treatment for short dictionary words. "uid" has higher priority,
// but its occurrence is ignored because it is a part of another word.
- {{"name1", "", "johnsmith", "Insert your id:"},
+ {{"name1", "noword", "johnsmith", "Insert your id:"},
{"name2", "uidentical", "js@google.com", "Insert something:"},
"name1",
+ "noword",
"johnsmith"}};
for (size_t i = 0; i < base::size(cases); ++i) {
@@ -607,6 +647,9 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_UserGroupAttributes) {
std::unique_ptr<PasswordForm> password_form =
LoadHTMLAndConvertForm(html, nullptr, false);
+ uint32_t username_renderer_id =
+ GetRendererIdFromWebElementId(cases[i].expected_username_id);
+
ASSERT_TRUE(password_form);
EXPECT_EQ(base::UTF8ToUTF16(cases[i].expected_username_element),
@@ -616,9 +659,8 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetector_UserGroupAttributes) {
// Check that the username field was found by HTML detector.
ASSERT_EQ(1u, username_detector_cache_.size());
ASSERT_FALSE(username_detector_cache_.begin()->second.empty());
- EXPECT_EQ(
- cases[i].expected_username_element,
- username_detector_cache_.begin()->second[0].NameForAutofill().Utf8());
+ EXPECT_EQ(username_renderer_id,
+ username_detector_cache_.begin()->second[0]);
}
}
@@ -638,9 +680,10 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache) {
base::HistogramTester histogram_tester;
std::unique_ptr<PasswordForm> password_form =
CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
+
EXPECT_TRUE(password_form);
ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form, detector_cache.begin()->first);
+ EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
EXPECT_TRUE(detector_cache.begin()->second.empty());
histogram_tester.ExpectUniqueSample("PasswordManager.UsernameDetectionMethod",
UsernameDetectionMethod::BASE_HEURISTIC,
@@ -655,7 +698,7 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache) {
CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
EXPECT_TRUE(password_form);
ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form, detector_cache.begin()->first);
+ EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
EXPECT_TRUE(detector_cache.begin()->second.empty());
histogram_tester.ExpectUniqueSample("PasswordManager.UsernameDetectionMethod",
UsernameDetectionMethod::BASE_HEURISTIC,
@@ -668,9 +711,10 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache) {
CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
EXPECT_TRUE(password_form);
ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form, detector_cache.begin()->first);
+ EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
ASSERT_EQ(1u, detector_cache.begin()->second.size());
- EXPECT_EQ("id", detector_cache.begin()->second[0].NameForAutofill().Utf8());
+ EXPECT_EQ(control_elements[0].UniqueRendererFormControlId(),
+ detector_cache.begin()->second[0]);
EXPECT_THAT(
histogram_tester.GetAllSamples("PasswordManager.UsernameDetectionMethod"),
testing::UnorderedElementsAre(
@@ -684,9 +728,10 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache) {
CreatePasswordFormFromWebForm(form, nullptr, nullptr, &detector_cache);
EXPECT_TRUE(password_form);
ASSERT_EQ(1u, detector_cache.size());
- EXPECT_EQ(form, detector_cache.begin()->first);
+ EXPECT_EQ(form.UniqueRendererFormId(), detector_cache.begin()->first);
ASSERT_EQ(1u, detector_cache.begin()->second.size());
- EXPECT_EQ("id", detector_cache.begin()->second[0].NameForAutofill().Utf8());
+ EXPECT_EQ(control_elements[0].UniqueRendererFormControlId(),
+ detector_cache.begin()->second[0]);
EXPECT_THAT(
histogram_tester.GetAllSamples("PasswordManager.UsernameDetectionMethod"),
testing::UnorderedElementsAre(
@@ -716,9 +761,11 @@ TEST_F(PasswordFormConversionUtilsTest, HTMLDetectorCache_SkipSomePredictions) {
// Add predictions for "email" and "id" fields to the cache.
UsernameDetectorCache username_detector_cache;
- username_detector_cache[control_elements[0].Form()] = {
- *ToWebInputElement(&control_elements[1]), // email
- *ToWebInputElement(&control_elements[2])}; // id
+ username_detector_cache[control_elements[0].Form().UniqueRendererFormId()] = {
+ ToWebInputElement(&control_elements[1])
+ ->UniqueRendererFormControlId(), // email
+ ToWebInputElement(&control_elements[2])
+ ->UniqueRendererFormControlId()}; // id
// A user typed only into "id" and "password" fields. So, the prediction for
// "email" field should be ignored despite it is more reliable than prediction
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index 8a9f32db64b..5aafec2069b 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -143,12 +143,10 @@ PasswordGenerationAgent::PasswordGenerationAgent(
PasswordAutofillAgent* password_agent,
blink::AssociatedInterfaceRegistry* registry)
: content::RenderFrameObserver(render_frame),
- enabled_(password_generation::IsPasswordGenerationEnabled()),
mark_generation_element_(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kShowAutofillSignatures)),
password_agent_(password_agent) {
- LogBoolean(Logger::STRING_GENERATION_RENDERER_ENABLED, enabled_);
registry->AddInterface(base::BindRepeating(
&PasswordGenerationAgent::BindPendingReceiver, base::Unretained(this)));
password_agent_->SetPasswordGenerationAgent(this);
@@ -268,10 +266,11 @@ PasswordGenerationAgent::CreatePasswordFormToPresave() {
// change username and password values.
std::unique_ptr<PasswordForm> password_form;
if (!current_generation_item_->generation_element_.Form().IsNull()) {
- password_form = password_agent_->GetPasswordFormFromWebForm(
+ password_form = password_agent_->GetSimplifiedPasswordFormFromWebForm(
current_generation_item_->generation_element_.Form());
} else {
- password_form = password_agent_->GetPasswordFormFromUnownedInputElements();
+ password_form =
+ password_agent_->GetSimplifiedPasswordFormFromUnownedInputElements();
}
if (password_form) {
password_form->type = PasswordForm::Type::kGenerated;
@@ -286,8 +285,8 @@ void PasswordGenerationAgent::FoundFormEligibleForGeneration(
const PasswordFormGenerationData& form) {
generation_enabled_fields_[form.new_password_renderer_id] = form;
+ // Mark the input element as |has_been_password_for_autofill_|.
if (mark_generation_element_) {
- // Mark the input element with renderer id |form.new_password_renderer_id|.
if (!render_frame())
return;
WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
@@ -296,8 +295,11 @@ void PasswordGenerationAgent::FoundFormEligibleForGeneration(
WebFormControlElement new_password_input =
form_util::FindFormControlElementsByUniqueRendererId(
doc, form.new_password_renderer_id);
- if (!new_password_input.IsNull())
+ if (!new_password_input.IsNull()) {
+ // Mark the input element with renderer id
+ // |form.new_password_renderer_id|.
new_password_input.SetAttribute("password_creation_field", "1");
+ }
}
}
@@ -396,7 +398,6 @@ bool PasswordGenerationAgent::FocusedNodeHasChanged(
MaybeCreateCurrentGenerationItem(
*element, it->second.confirmation_password_renderer_id);
}
-
if (!current_generation_item_ ||
*element != current_generation_item_->generation_element_) {
return false;
@@ -530,12 +531,20 @@ void PasswordGenerationAgent::AutomaticGenerationAvailable() {
void PasswordGenerationAgent::ShowEditingPopup() {
if (!render_frame())
return;
- GetPasswordGenerationDriver()->ShowPasswordEditingPopup(
+
+ gfx::RectF bounding_box =
render_frame()->GetRenderView()->ElementBoundsInWindow(
- current_generation_item_->generation_element_),
- *CreatePasswordFormToPresave(),
+ current_generation_item_->generation_element_);
+
+ std::unique_ptr<PasswordForm> password_form = CreatePasswordFormToPresave();
+ DCHECK(password_form);
+
+ uint32_t generation_element_renderer_id =
current_generation_item_->generation_element_
- .UniqueRendererFormControlId());
+ .UniqueRendererFormControlId();
+
+ GetPasswordGenerationDriver()->ShowPasswordEditingPopup(
+ bounding_box, *password_form, generation_element_renderer_id);
current_generation_item_->editing_popup_shown_ = true;
}
@@ -567,29 +576,31 @@ void PasswordGenerationAgent::PasswordNoLongerGenerated() {
}
void PasswordGenerationAgent::MaybeCreateCurrentGenerationItem(
- WebInputElement element,
+ WebInputElement generation_element,
uint32_t confirmation_password_renderer_id) {
// Do not create |current_generation_item_| if it already is created for
- // |element| or the user accepted generated password. So if the user accepted
- // the generated password, generation is not offered on any other field.
+ // |generation_element| or the user accepted generated password. So if the
+ // user accepted the generated password, generation is not offered on any
+ // other field.
if (current_generation_item_ &&
- (current_generation_item_->generation_element_ == element ||
+ (current_generation_item_->generation_element_ == generation_element ||
current_generation_item_->password_is_generated_))
return;
std::unique_ptr<PasswordForm> password_form =
- element.Form().IsNull()
- ? password_agent_->GetPasswordFormFromUnownedInputElements()
- : password_agent_->GetPasswordFormFromWebForm(element.Form());
+ generation_element.Form().IsNull()
+ ? password_agent_->GetSimplifiedPasswordFormFromUnownedInputElements()
+ : password_agent_->GetSimplifiedPasswordFormFromWebForm(
+ generation_element.Form());
if (!password_form)
return;
- std::vector<blink::WebInputElement> passwords = {element};
+ std::vector<blink::WebInputElement> passwords = {generation_element};
WebFormControlElement confirmation_password =
form_util::FindFormControlElementsByUniqueRendererId(
- element.GetDocument(), confirmation_password_renderer_id);
+ generation_element.GetDocument(), confirmation_password_renderer_id);
if (!confirmation_password.IsNull()) {
WebInputElement* input = ToWebInputElement(&confirmation_password);
@@ -598,9 +609,11 @@ void PasswordGenerationAgent::MaybeCreateCurrentGenerationItem(
}
current_generation_item_.reset(new GenerationItemInfo(
- element, std::move(*password_form), std::move(passwords)));
+ generation_element, std::move(*password_form), std::move(passwords)));
+
+ generation_element.SetHasBeenPasswordField();
- element.SetAttribute("aria-autocomplete", "list");
+ generation_element.SetAttribute("aria-autocomplete", "list");
}
const mojo::AssociatedRemote<mojom::PasswordManagerDriver>&
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.h b/chromium/components/autofill/content/renderer/password_generation_agent.h
index 460bbced618..31de17b9bba 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.h
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.h
@@ -91,10 +91,6 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
}
#endif
- protected:
- // Use to force enable during testing.
- void set_enabled(bool enabled) { enabled_ = enabled; }
-
private:
// Contains information about generation status for an element for the
// lifetime of the possible interaction.
@@ -164,13 +160,10 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
// the last focused password element.
blink::WebInputElement last_focused_password_element_;
- // Contains correspondence between generaiton enabled element and data for
+ // Contains correspondence between generation enabled element and data for
// generation.
std::map<uint32_t, PasswordFormGenerationData> generation_enabled_fields_;
- // If this feature is enabled. Controlled by Finch.
- bool enabled_;
-
// True iff the generation element should be marked with special HTML
// attribute (only for experimental purposes).
const bool mark_generation_element_;
diff --git a/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
index bf66816c533..badd66a6a3b 100644
--- a/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
+++ b/chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -6,7 +6,7 @@
#include "base/optional.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -63,6 +63,8 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
int options,
const gfx::RectF& bounds) override {}
+ void ShowTouchToFill() override {}
+
void RecordSavePasswordProgress(const std::string& log) override {
called_record_save_ = true;
log_ = log;
@@ -100,7 +102,7 @@ class TestLogger : public RendererSavePasswordProgressLogger {
} // namespace
TEST(RendererSavePasswordProgressLoggerTest, SendLog) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
FakeContentPasswordManagerDriver fake_driver;
mojom::PasswordManagerDriverPtr driver_ptr =
fake_driver.CreateInterfacePtrAndBind();
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 9f728098186..44b052554fe 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -33,6 +33,8 @@ jumbo_static_library("browser") {
"autofill-inl.h",
"autofill_address_util.cc",
"autofill_address_util.h",
+ "autofill_browser_util.cc",
+ "autofill_browser_util.h",
"autofill_client.cc",
"autofill_client.h",
"autofill_data_util.cc",
@@ -160,8 +162,6 @@ jumbo_static_library("browser") {
"metrics/form_event_logger_base.h",
"metrics/form_events.h",
"payments/account_info_getter.h",
- "payments/autofill_wallet_data_type_controller.cc",
- "payments/autofill_wallet_data_type_controller.h",
"payments/autofill_wallet_model_type_controller.cc",
"payments/autofill_wallet_model_type_controller.h",
"payments/card_unmask_delegate.cc",
@@ -247,8 +247,6 @@ jumbo_static_library("browser") {
"webdata/autofill_change.h",
"webdata/autofill_entry.cc",
"webdata/autofill_entry.h",
- "webdata/autofill_profile_data_type_controller.cc",
- "webdata/autofill_profile_data_type_controller.h",
"webdata/autofill_profile_model_type_controller.cc",
"webdata/autofill_profile_model_type_controller.h",
"webdata/autofill_profile_sync_bridge.cc",
@@ -264,8 +262,6 @@ jumbo_static_library("browser") {
"webdata/autofill_table_encryptor_factory.h",
"webdata/autofill_wallet_metadata_sync_bridge.cc",
"webdata/autofill_wallet_metadata_sync_bridge.h",
- "webdata/autofill_wallet_metadata_syncable_service.cc",
- "webdata/autofill_wallet_metadata_syncable_service.h",
"webdata/autofill_wallet_sync_bridge.cc",
"webdata/autofill_wallet_sync_bridge.h",
"webdata/autofill_webdata_backend.h",
@@ -309,7 +305,6 @@ jumbo_static_library("browser") {
sources += [
"ui/payments/local_card_migration_bubble_controller.h",
"ui/payments/local_card_migration_dialog_controller.h",
- "ui/payments/save_card_bubble_controller.h",
]
}
@@ -344,6 +339,7 @@ jumbo_static_library("browser") {
"proto:legacy_proto_bridge",
"//base",
"//base:i18n",
+ "//build:branding_buildflags",
"//components/google/core/common",
"//components/history/core/browser",
"//components/infobars/core",
@@ -416,6 +412,7 @@ jumbo_static_library("test_support") {
"payments/test_credit_card_save_manager.h",
"payments/test_credit_card_save_strike_database.cc",
"payments/test_credit_card_save_strike_database.h",
+ "payments/test_legal_message_line.h",
"payments/test_local_card_migration_manager.cc",
"payments/test_local_card_migration_manager.h",
"payments/test_payments_client.cc",
@@ -571,7 +568,6 @@ source_set("unit_tests") {
"logging/log_buffer_unittest.cc",
"logging/log_manager_unittest.cc",
"logging/log_router_unittest.cc",
- "payments/autofill_wallet_data_type_controller_unittest.cc",
"payments/credit_card_access_manager_unittest.cc",
"payments/credit_card_cvc_authenticator_unittest.cc",
"payments/credit_card_save_manager_unittest.cc",
@@ -599,7 +595,6 @@ source_set("unit_tests") {
"webdata/autofill_sync_bridge_util_unittest.cc",
"webdata/autofill_table_unittest.cc",
"webdata/autofill_wallet_metadata_sync_bridge_unittest.cc",
- "webdata/autofill_wallet_metadata_syncable_service_unittest.cc",
"webdata/autofill_wallet_sync_bridge_unittest.cc",
"webdata/web_data_service_unittest.cc",
]
diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS
index 5e23fe731f6..b2ccc4b308e 100644
--- a/chromium/components/autofill/core/browser/DEPS
+++ b/chromium/components/autofill/core/browser/DEPS
@@ -42,6 +42,7 @@ specific_include_rules = {
"+components/ukm",
],
"(test_)?credit_card_fido_authenticator\.(cc|h)": [
+ "+device/fido/fido_constants.h",
"+third_party/blink/public/mojom/webauthn/authenticator.mojom.h",
"+third_party/blink/public/mojom/webauthn/internal_authenticator.mojom.h",
],
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl.cc b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
index 7d47f05c664..2d5ce94e97e 100644
--- a/chromium/components/autofill/core/browser/address_normalizer_impl.cc
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
@@ -156,8 +156,9 @@ AddressNormalizerImpl::AddressNormalizerImpl(std::unique_ptr<Source> source,
// shutdown. This is important to prevent an access race when the destructor
// of |storage| accesses an ObserverList that lives on the current sequence.
// https://crbug.com/829122
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(
&CreateAddressValidator, std::move(source),
DeleteOnTaskRunnerStorageUniquePtr(
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc b/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc
index 37f0a9735cd..a3c5cfe306a 100644
--- a/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/address_normalizer.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -94,7 +94,7 @@ class AddressNormalizerTest : public testing::Test {
~AddressNormalizerTest() override {}
void WaitForAddressValidatorInitialization() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
bool normalization_successful() const { return success_; }
@@ -103,7 +103,7 @@ class AddressNormalizerTest : public testing::Test {
TestAddressNormalizer* normalizer() { return &normalizer_; }
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool AreRulesLoadedForRegion(const std::string& region_code) {
return normalizer_.AreRulesLoadedForRegion(region_code);
@@ -187,7 +187,7 @@ TEST_F(AddressNormalizerTest,
base::Unretained(this)));
// Let the timeout execute.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Since the rules are never loaded and the timeout is 0, the callback should
// get notified that the address could not be normalized.
@@ -338,7 +338,7 @@ TEST_F(AddressNormalizerTest, FormatPhone_AddressNotNormalizedAsync) {
base::Unretained(this)));
// Let the timeout execute.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Make sure the address was not normalized.
EXPECT_FALSE(normalization_successful());
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
index d47ec4f7668..dd8098f25d8 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -12,7 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
@@ -150,7 +150,7 @@ class AutocompleteHistoryManagerTest : public testing::Test {
date_last_used);
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<MockWebDataService> web_data_service_;
std::unique_ptr<AutocompleteHistoryManager> autocomplete_manager_;
std::unique_ptr<PrefService> prefs_;
diff --git a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css
index 2df889c0dc5..8dcdccf06e3 100644
--- a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css
+++ b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css
@@ -29,6 +29,29 @@
display: block;
}
+#version-info {
+ padding: 3px;
+ margin: 3px;
+}
+
+.version {
+ font-family: monospace;
+ max-width: 430px;
+ padding-left: 5px;
+ word-break: break-word;
+ vertical-align: top;
+}
+
+.label {
+ font-family: monospace;
+ vertical-align: top;
+ font-weight: 200;
+}
+
+.log-entry {
+ padding: 3px;
+}
+
/*
* Colors can be taken from
* https://material.io/design/color/#tools-for-picking-colors
@@ -40,7 +63,7 @@
}
.log-entry[scope='Parsing'] {
- background-color: #FFCDD2;
+ background-color: #FFECB3;
}
.log-entry[scope='Filling'] {
@@ -51,6 +74,10 @@
background-color: #BBDEFB;
}
+.log-entry[scope='AutofillServer'] {
+ background-color: #D7CCC8;
+}
+
.form {
padding: 3px;
margin: 3px;
diff --git a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.html b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.html
index 220e6b5b748..8ab1132de55 100644
--- a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.html
+++ b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.html
@@ -14,6 +14,32 @@
<h1 id="h1-title"></h1>
<div id="logging-note"></div>
<div id="logging-note-incognito"></div>
+<div id="version-info">
+ <table>
+ <tr>
+ <td class="label">Version:</td>
+ <td class="version"><span>$i18n{version}</span>
+ (<span>$i18n{official}</span>)
+ <span>$i18n{version_modifier}</span></td>
+ </tr>
+ <tr>
+ <td class="label">Revision:</td>
+ <td class="version"><span>$i18n{cl}</span></td>
+ </tr>
+ <tr>
+ <td class="label">User Agent:</td>
+ <td class="version"><span>$i18n{useragent}</span></td>
+ </tr>
+ <tr>
+ <td class="label">App Locale:</td>
+ <td class="version"><span>$i18n{app_locale}</span></td>
+ </tr>
+ <tr>
+ <td class="label">Variations:</td>
+ <td class="version" id="variations-list"></td>
+ </tr>
+ </table>
+</div>
<div id="log-entries">
</div>
</body>
diff --git a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js
index 96b18a5b232..91fcdf8ae3d 100644
--- a/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js
+++ b/chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js
@@ -16,7 +16,7 @@ function addLog(logText) {
// Converts an internal representation of nodes to actual DOM nodes that can
// be attached to the DOM. The internal representation has the following
// properties for each node:
-// - type: 'node' | 'text'
+// - type: 'element' | 'text'
// - value: name of tag | text content
// - children (opt): list of child nodes
// - attributes (opt): dictionary of name/value pairs
@@ -24,7 +24,7 @@ function nodeToDomNode(node) {
if (node.type === 'text') {
return document.createTextNode(node.value);
}
- // Else the node is of type 'node'.
+ // Else the node is of type 'element'.
var domNode = document.createElement(node.value);
if ('children' in node) {
node.children.forEach((child) => {
@@ -47,7 +47,15 @@ function addRawLog(node) {
return;
}
logDiv.appendChild(document.createElement('hr'));
- logDiv.appendChild(nodeToDomNode(node));
+ if (node.type === 'fragment') {
+ if ('children' in node) {
+ node.children.forEach((child) => {
+ logDiv.appendChild(nodeToDomNode(child));
+ });
+ }
+ } else {
+ logDiv.appendChild(nodeToDomNode(node));
+ }
}
function setUpAutofillInternals() {
@@ -75,6 +83,16 @@ function notifyAboutIncognito(isIncognito) {
document.body.dataset.incognito = isIncognito;
}
+function notifyAboutVariations(variations) {
+ var list = document.createElement("div");
+ for (let item of variations) {
+ list.appendChild(document.createTextNode(item));
+ list.appendChild(document.createElement("br"));
+ }
+ var variationsList = document.getElementById("variations-list");
+ variationsList.appendChild(list);
+}
+
document.addEventListener("DOMContentLoaded", function(event) {
chrome.send('loaded');
});
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.cc b/chromium/components/autofill/core/browser/autofill_assistant.cc
index 7871113f1f6..e357fa874c7 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant.cc
@@ -16,9 +16,7 @@
namespace autofill {
AutofillAssistant::AutofillAssistant(AutofillManager* autofill_manager)
- : credit_card_form_data_(nullptr),
- autofill_manager_(autofill_manager),
- weak_ptr_factory_(this) {}
+ : credit_card_form_data_(nullptr), autofill_manager_(autofill_manager) {}
AutofillAssistant::~AutofillAssistant() {}
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.h b/chromium/components/autofill/core/browser/autofill_assistant.h
index ecd60f91914..450e567a636 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.h
+++ b/chromium/components/autofill/core/browser/autofill_assistant.h
@@ -56,7 +56,7 @@ class AutofillAssistant : public payments::FullCardRequest::ResultDelegate {
// AutofillAssistant.
AutofillManager* autofill_manager_;
- base::WeakPtrFactory<AutofillAssistant> weak_ptr_factory_;
+ base::WeakPtrFactory<AutofillAssistant> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AutofillAssistant);
};
diff --git a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
index f29ec920e89..95b0e1aef02 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
@@ -11,7 +11,7 @@
#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -148,7 +148,7 @@ class AutofillAssistantTest : public testing::Test {
return static_cast<CardUnmaskDelegate*>(full_card_request);
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
testing::NiceMock<TestAutofillDriver> autofill_driver_;
TestPersonalDataManager pdm_;
@@ -315,9 +315,9 @@ TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_SubmitCvc) {
autofill_assistant_->ShowAssistForCreditCard(card);
- CardUnmaskDelegate::UnmaskResponse unmask_response;
- unmask_response.cvc = base::ASCIIToUTF16("123");
- full_card_unmask_delegate()->OnUnmaskResponse(unmask_response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails unmask_details;
+ unmask_details.cvc = base::ASCIIToUTF16("123");
+ full_card_unmask_delegate()->OnUnmaskPromptAccepted(unmask_details);
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_browser_util.cc b/chromium/components/autofill/core/browser/autofill_browser_util.cc
new file mode 100644
index 00000000000..db8b6be16ee
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_browser_util.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 "components/autofill/core/browser/autofill_browser_util.h"
+
+#include "components/autofill/core/browser/autofill_client.h"
+
+namespace autofill {
+
+bool IsFormOrClientNonSecure(AutofillClient* client, const FormData& form) {
+ return !client->IsContextSecure() ||
+ (form.action.is_valid() && form.action.SchemeIs("http"));
+}
+
+bool ShouldAllowCreditCardFallbacks(AutofillClient* client,
+ const FormData& form) {
+ // Skip the form check if there wasn't a form yet:
+ if (form.unique_renderer_id == FormData::kNotSetFormRendererId)
+ return client->IsContextSecure();
+ return !IsFormOrClientNonSecure(client, form);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_browser_util.h b/chromium/components/autofill/core/browser/autofill_browser_util.h
new file mode 100644
index 00000000000..f684ef3e67e
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_browser_util.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 COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_BROWSER_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_BROWSER_UTIL_H_
+
+#include <stddef.h>
+
+#include "components/autofill/core/common/form_data.h"
+
+namespace autofill {
+
+class AutofillClient;
+
+// Checks whether a given form is considered insecure (by origin or action).
+bool IsFormOrClientNonSecure(AutofillClient* client, const FormData& form);
+
+// Returns true if context provided by the client and the given form are
+// considered "secure enough" to manually fill credit card data.
+bool ShouldAllowCreditCardFallbacks(AutofillClient* client,
+ const FormData& form);
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_BROWSER_UTIL_H_
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index 09dcb891d39..09e305852ec 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -213,6 +213,11 @@ class AutofillClient : public RiskDataLoader {
typedef base::RepeatingCallback<void(const std::string&)>
MigrationDeleteCardCallback;
+ // Callback to run if the OK button or the cancel button in the
+ // WebauthnOfferDialog is clicked. Will pass to CreditCardFIDOAuthenticator a
+ // bool indicating if offer was accepted or declined.
+ typedef base::RepeatingCallback<void(bool)> WebauthnOfferDialogCallback;
+
~AutofillClient() override {}
// Returns the channel for the installation. In branded builds, this will be
@@ -299,6 +304,13 @@ class AutofillClient : public RiskDataLoader {
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) = 0;
+ // Will show a dialog offering the option to use device's platform
+ // authenticator in the future instead of CVC to verify the card being
+ // unmasked. Runs |callback| is the OK button or the cancel button in the
+ // dialog is clicked. This is only implemented on desktop.
+ virtual void ShowWebauthnOfferDialog(
+ WebauthnOfferDialogCallback callback) = 0;
+
// Runs |callback| if the |profile| should be imported as personal data.
virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index 17835b05088..02d4f378146 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/branding_buildflags.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
@@ -54,11 +55,11 @@ const PaymentRequestData kPaymentRequestData[]{
{autofill::kVisaCard, "visa", IDR_AUTOFILL_CC_VISA, IDS_AUTOFILL_CC_VISA},
};
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const PaymentRequestData kGooglePayBrandingRequestData = {
"googlePay", "googlePay", IDR_AUTOFILL_GOOGLE_PAY,
IDS_AUTOFILL_CC_GOOGLE_PAY};
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
const PaymentRequestData kGenericPaymentRequestData = {
autofill::kGenericCard, "generic", IDR_AUTOFILL_CC_GENERIC,
@@ -522,11 +523,11 @@ const PaymentRequestData& GetPaymentRequestData(
if (issuer_network == data.issuer_network)
return data;
}
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
if (issuer_network == kGooglePayBrandingRequestData.issuer_network) {
return kGooglePayBrandingRequestData;
}
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
return kGenericPaymentRequestData;
}
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc
index 068d1df6e00..4513830064b 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc
@@ -24,12 +24,17 @@
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/autofill_driver.h"
+#include "components/autofill/core/browser/autofill_internals_service.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/logging/log_buffer.h"
+#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/browser/proto/legacy_proto_bridge.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_internals/log_message.h"
+#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
@@ -175,9 +180,10 @@ void LogHttpResponseData(AutofillDownloadManager::RequestType request_type,
int response_code,
int net_error,
base::TimeDelta request_duration) {
- int response_or_error_code =
- (net_error == net::OK || net_error == net::ERR_FAILED) ? response_code
- : net_error;
+ int response_or_error_code = net_error;
+ if (net_error == net::OK || net_error == net::ERR_HTTP_RESPONSE_CODE_FAILURE)
+ response_or_error_code = response_code;
+
switch (request_type) {
case AutofillDownloadManager::REQUEST_QUERY:
base::UmaHistogramSparse("Autofill.Query.HttpResponseOrErrorCode",
@@ -336,9 +342,9 @@ std::ostream& operator<<(std::ostream& out,
out << "form_signature: " << upload.form_signature() << "\n";
out << "data_present: " << upload.data_present() << "\n";
out << "submission: " << upload.submission() << "\n";
- if (!upload.action_signature())
+ if (upload.action_signature())
out << "action_signature: " << upload.action_signature() << "\n";
- if (!upload.login_form_signature())
+ if (upload.login_form_signature())
out << "login_form_signature: " << upload.login_form_signature() << "\n";
if (!upload.form_name().empty())
out << "form_name: " << upload.form_name() << "\n";
@@ -376,6 +382,73 @@ std::ostream& operator<<(std::ostream& out,
return out;
}
+std::string FieldTypeToString(int type) {
+ return base::StrCat(
+ {base::NumberToString(type), std::string("/"),
+ AutofillType(static_cast<ServerFieldType>(type)).ToString()});
+}
+
+LogBuffer& operator<<(LogBuffer& out,
+ const autofill::AutofillUploadContents& upload) {
+ if (!out.active())
+ return out;
+ out << Tag{"div"} << Attrib{"class", "form"};
+ out << Tag{"table"};
+ out << Tr{} << "client_version:" << upload.client_version();
+ out << Tr{} << "data_present:" << upload.data_present();
+ out << Tr{} << "autofill_used:" << upload.autofill_used();
+ out << Tr{} << "submission:" << upload.submission();
+ if (upload.has_submission_event()) {
+ out << Tr{}
+ << "submission_event:" << static_cast<int>(upload.submission_event());
+ }
+ if (upload.action_signature())
+ out << Tr{} << "action_signature:" << upload.action_signature();
+ if (upload.login_form_signature())
+ out << Tr{} << "login_form_signature:" << upload.login_form_signature();
+ if (!upload.form_name().empty())
+ out << Tr{} << "form_name:" << upload.form_name();
+ if (upload.has_passwords_revealed())
+ out << Tr{} << "passwords_revealed:" << upload.passwords_revealed();
+ if (upload.has_has_form_tag())
+ out << Tr{} << "has_form_tag:" << upload.has_form_tag();
+
+ out << Tr{} << "form_signature:" << upload.form_signature();
+ for (const auto& field : upload.field()) {
+ out << Tr{} << Attrib{"style", "font-weight: bold"}
+ << "field_signature:" << field.signature();
+
+ std::vector<std::string> types_as_strings;
+ types_as_strings.reserve(field.autofill_type_size());
+ for (int type : field.autofill_type())
+ types_as_strings.emplace_back(FieldTypeToString(type));
+ out << Tr{} << "autofill_type:" << types_as_strings;
+
+ LogBuffer validities;
+ validities << Tag{"span"} << "[";
+ for (const auto& type_validities : field.autofill_type_validities()) {
+ validities << "(type: " << type_validities.type()
+ << ", validities: " << type_validities.validity() << ")";
+ }
+ validities << "]";
+ out << Tr{} << "validity_states" << std::move(validities);
+
+ if (!field.name().empty())
+ out << Tr{} << "name:" << field.name();
+ if (!field.autocomplete().empty())
+ out << Tr{} << "autocomplete:" << field.autocomplete();
+ if (!field.type().empty())
+ out << Tr{} << "type:" << field.type();
+ if (field.generation_type()) {
+ out << Tr{}
+ << "generation_type:" << static_cast<int>(field.generation_type());
+ }
+ }
+ out << CTag{"table"};
+ out << CTag{"div"};
+ return out;
+}
+
// Returns true if an upload of |form| triggered by |form.submission_source()|
// can be throttled/suppressed. This is true if |prefs| indicates that this
// upload has already happened within the last update window. Updates |prefs|
@@ -528,10 +601,12 @@ std::vector<variations::VariationID>*
AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver,
Observer* observer,
- const std::string& api_key)
+ const std::string& api_key,
+ LogManager* log_manager)
: driver_(driver),
observer_(observer),
api_key_(api_key),
+ log_manager_(log_manager),
autofill_server_url_(GetAutofillServerURL()),
throttle_reset_period_(GetThrottleResetPeriod()),
max_form_cache_size_(kAutofillDownloadManagerMaxFormCacheSize),
@@ -541,7 +616,10 @@ AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver,
AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver,
Observer* observer)
- : AutofillDownloadManager(driver, observer, kDefaultAPIKey) {}
+ : AutofillDownloadManager(driver,
+ observer,
+ kDefaultAPIKey,
+ /*log_manager=*/nullptr) {}
AutofillDownloadManager::~AutofillDownloadManager() = default;
@@ -619,7 +697,11 @@ bool AutofillDownloadManager::StartUploadRequest(
bool allow_upload =
!(can_throttle_upload && (throttling_is_enabled || is_small_form));
AutofillMetrics::LogUploadEvent(form.submission_source(), allow_upload);
- if (!allow_upload)
+
+ // For debugging purposes, even throttled uploads are logged. If no log
+ // manager is active, the function can exit early for throttled uploads.
+ bool needs_logging = log_manager_ && log_manager_->IsLoggingActive();
+ if (!needs_logging && !allow_upload)
return false;
AutofillUploadContents upload;
@@ -661,6 +743,15 @@ bool AutofillDownloadManager::StartUploadRequest(
request_data.payload = std::move(payload);
DVLOG(1) << "Sending Autofill Upload Request:\n" << upload;
+ if (log_manager_) {
+ log_manager_->Log() << LoggingScope::kAutofillServer
+ << LogMessage::kSendAutofillUpload << Br{}
+ << "Allow upload?: " << allow_upload << Br{}
+ << "Data: " << Br{} << upload;
+ }
+
+ if (!allow_upload)
+ return false;
return StartRequest(std::move(request_data));
}
@@ -757,8 +848,7 @@ bool AutofillDownloadManager::StartRequest(FormRequestData request_data) {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = request_url;
- resource_request->load_flags =
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = method;
// Add Chrome experiment state to the request headers.
@@ -892,9 +982,7 @@ void AutofillDownloadManager::OnSimpleLoaderComplete(
url_loaders_.erase(it);
CHECK(request_data.form_signatures.size());
- // net:ERR_FAILED is not an HTTP response code, but if none is available, the
- // UMA logging can accept this as a generic fallback as well.
- int response_code = net::ERR_FAILED;
+ int response_code = -1; // Invalid response code.
if (simple_loader->ResponseInfo() && simple_loader->ResponseInfo()->headers) {
response_code = simple_loader->ResponseInfo()->headers->response_code();
}
@@ -917,8 +1005,10 @@ void AutofillDownloadManager::OnSimpleLoaderComplete(
(response_body != nullptr) ? *response_body : "";
DVLOG(1) << "AutofillDownloadManager: "
<< RequestTypeToString(request_data.request_type)
- << " request has failed with response code " << response_code
- << " and error message from the server " << error_message;
+ << " request has failed with net error "
+ << simple_loader->NetError() << " and HTTP response code "
+ << response_code << " and error message from the server "
+ << error_message;
observer_->OnServerRequestError(request_data.form_signatures[0],
request_data.request_type, response_code);
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.h b/chromium/components/autofill/core/browser/autofill_download_manager.h
index b9f63cc3afa..88ce53237a5 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.h
@@ -31,6 +31,7 @@ namespace autofill {
class AutofillDriver;
class FormStructure;
+class LogManager;
const size_t kMaxAPIQueryGetSize = 10240; // 10 KiB
@@ -82,7 +83,8 @@ class AutofillDownloadManager {
// effect if using API.
AutofillDownloadManager(AutofillDriver* driver,
Observer* observer,
- const std::string& api_key);
+ const std::string& api_key,
+ LogManager* log_manager);
virtual ~AutofillDownloadManager();
// Starts a query request to Autofill servers. The observer is called with the
@@ -194,6 +196,9 @@ class AutofillDownloadManager {
// Callback function to retrieve API key.
const std::string api_key_;
+ // Access to leave log messages for chrome://autofill-internals, may be null.
+ LogManager* const log_manager_; // WEAK
+
// The autofill server URL root: scheme://host[:port]/path excluding the
// final path component for the request and the query params.
const GURL autofill_server_url_;
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
index 08d9a32c10a..d3fbc3484e4 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -23,7 +23,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -165,7 +165,11 @@ class AutofillDownloadManagerWithCustomPayloadSize
Observer* observer,
const std::string& api_key,
size_t length)
- : AutofillDownloadManager(driver, observer, api_key), length_(length) {}
+ : AutofillDownloadManager(driver,
+ observer,
+ api_key,
+ /*log_manager=*/nullptr),
+ length_(length) {}
protected:
size_t GetPayloadLength(base::StringPiece payload) const override {
@@ -247,7 +251,7 @@ class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer,
};
ScopedActiveAutofillExperiments scoped_active_autofill_experiments;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::list<ResponseData> responses_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
network::TestURLLoaderFactory test_url_loader_factory_;
@@ -345,7 +349,8 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
form_structures.push_back(std::make_unique<FormStructure>(form));
// Make download manager.
- AutofillDownloadManager download_manager(&driver_, this, "dummykey");
+ AutofillDownloadManager download_manager(&driver_, this, "dummykey",
+ /*log_manager=*/nullptr);
// Request with id 0.
base::HistogramTester histogram;
@@ -542,7 +547,8 @@ TEST_F(AutofillDownloadManagerTest, QueryAPITest) {
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::make_unique<FormStructure>(form));
- AutofillDownloadManager download_manager(&driver_, this, "dummykey");
+ AutofillDownloadManager download_manager(&driver_, this, "dummykey",
+ /*log_manager=*/nullptr);
// Start the query request and look if it is successful. No response was
// received yet.
@@ -755,7 +761,8 @@ TEST_F(AutofillDownloadManagerTest, UploadToAPITest) {
form_structure.set_submission_source(SubmissionSource::FORM_SUBMISSION);
std::unique_ptr<PrefService> pref_service = test::PrefServiceForTesting();
- AutofillDownloadManager download_manager(&driver_, this, "dummykey");
+ AutofillDownloadManager download_manager(&driver_, this, "dummykey",
+ /*log_manager=*/nullptr);
EXPECT_TRUE(download_manager.StartUploadRequest(form_structure, true,
ServerFieldTypeSet(), "",
true, pref_service.get()));
@@ -1485,8 +1492,8 @@ class AutofillServerCommunicationTest
return succeeded;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO};
base::test::ScopedCommandLine scoped_command_line_;
base::test::ScopedFeatureList scoped_feature_list_1_;
base::test::ScopedFeatureList scoped_feature_list_2_;
diff --git a/chromium/components/autofill/core/browser/autofill_driver.h b/chromium/components/autofill/core/browser/autofill_driver.h
index 47aa24b65bf..b9e205706e4 100644
--- a/chromium/components/autofill/core/browser/autofill_driver.h
+++ b/chromium/components/autofill/core/browser/autofill_driver.h
@@ -10,15 +10,12 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "components/autofill/core/common/form_data.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#if !defined(OS_IOS)
#include "third_party/blink/public/mojom/webauthn/internal_authenticator.mojom.h"
#endif
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace network {
class SharedURLLoaderFactory;
}
@@ -59,9 +56,6 @@ class AutofillDriver {
// Returns the ax tree id associated with this driver.
virtual ui::AXTreeID GetAxTreeId() const = 0;
- // Returns the URL request context information associated with this driver.
- virtual net::URLRequestContextGetter* GetURLRequestContext() = 0;
-
// Returns the URL loader factory associated with this driver.
virtual scoped_refptr<network::SharedURLLoaderFactory>
GetURLLoaderFactory() = 0;
@@ -72,7 +66,7 @@ class AutofillDriver {
#if !defined(OS_IOS)
// Binds the mojom request in order to facilitate WebAuthn flows.
virtual void ConnectToAuthenticator(
- blink::mojom::InternalAuthenticatorRequest request) = 0;
+ mojo::PendingReceiver<blink::mojom::InternalAuthenticator> receiver) = 0;
#endif
// Forwards |data| to the renderer. |query_id| is the id of the renderer's
diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
index 7e11d2a33f8..54c431018dd 100644
--- a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -100,7 +100,7 @@ class AutofillDriverFactoryTest : public testing::Test {
protected:
// For TestAutofillDriver.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockAutofillClient client_;
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index 643d4036dbc..4ad323a4874 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -96,20 +96,6 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
// Wallet feature must be on.
DCHECK(base::FeatureList::IsEnabled(
features::kAutofillEnableAccountWalletStorage));
- if (!base::FeatureList::IsEnabled(
- features::kAutofillEnableAccountWalletStorageUpload)) {
- // We're not enabling uploads in the account wallet mode, so suppress
- // the upload prompt.
- AutofillMetrics::LogCardUploadEnabledMetric(
- AutofillMetrics::CardUploadEnabledMetric::
- ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED,
- sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED";
- }
- return false;
- }
}
// Also don't offer upload for users that have a secondary sync passphrase.
diff --git a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
index 7fbc4f247df..353901b47e5 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -192,31 +192,6 @@ TEST_F(AutofillExperimentsTest, IsCardUploadEnabled_TransportModeOnly) {
AutofillMetrics::CardUploadEnabledMetric::CARD_UPLOAD_ENABLED, 1);
}
-TEST_F(AutofillExperimentsTest,
- IsCardUploadEnabled_TransportSyncDoesNotHaveUploadEnabled) {
- scoped_feature_list_.InitWithFeatures(
- /*enable_features=*/{features::kAutofillUpstream,
- features::kAutofillEnableAccountWalletStorage},
- /*disable_features=*/{
- features::kAutofillEnableAccountWalletStorageUpload});
- // When we have no primary account, Sync will start in Transport-only mode
- // (if allowed).
- sync_service_.SetIsAuthenticatedAccountPrimary(false);
-
- EXPECT_FALSE(IsCreditCardUploadEnabled(
- AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled));
- histogram_tester.ExpectUniqueSample(
- "Autofill.CardUploadEnabled",
- AutofillMetrics::CardUploadEnabledMetric::
- ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED,
- 1);
- histogram_tester.ExpectUniqueSample(
- "Autofill.CardUploadEnabled.SignedInAndSyncFeatureEnabled",
- AutofillMetrics::CardUploadEnabledMetric::
- ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED,
- 1);
-}
-
TEST_F(
AutofillExperimentsTest,
IsCardUploadEnabled_TransportSyncDoesNotHaveAutofillProfileActiveDataType) {
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index 11fcb06e71a..60c4d7feb19 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -154,18 +154,9 @@ bool AutofillExternalDelegate::HasActiveScreenReader() const {
void AutofillExternalDelegate::OnAutofillAvailabilityEvent(
bool has_suggestions) {
-#if defined(OS_CHROMEOS)
- // If the platform is ChromeOS, then the (un)availability of suggestions must
- // be communicated via Blink because ChromeOS uses accessibility objects that
- // live on both sides of the renderer-browser divide.
+ // Availability of suggestions should be communicated to Blink because
+ // accessibility objects live in both the renderer and browser processes.
driver_->RendererShouldSetSuggestionAvailability(has_suggestions);
-#else
- // On non-ChromeOS platforms, a static bool in AXPlatformNode is (un)set to
- // communicate suggestions' (un)availability. This works because
- // AXPlatformNodes reside on only the browser side.
- has_suggestions ? ui::AXPlatformNode::OnInputSuggestionsAvailable()
- : ui::AXPlatformNode::OnInputSuggestionsUnavailable();
-#endif // defined(OS_CHROMEOS)
}
void AutofillExternalDelegate::SetCurrentDataListValues(
@@ -376,7 +367,7 @@ void AutofillExternalDelegate::ApplyAutofillOptions(
suggestions->back().icon = "googlePay";
#else
suggestions->back().icon =
- ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeEnabled()
+ ui::NativeTheme::GetInstanceForNativeUi()->ShouldUseDarkColors()
? "googlePayDark"
: "googlePay";
#endif
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.h b/chromium/components/autofill/core/browser/autofill_external_delegate.h
index 6bcc3466034..2e2b8139e78 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.h
@@ -103,6 +103,8 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// values or settings.
void Reset();
+ const FormData& query_form() const { return query_form_; }
+
protected:
base::WeakPtr<AutofillExternalDelegate> GetWeakPtr();
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index c9d6c18f01f..a2c018bfd72 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -13,7 +13,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
@@ -181,7 +181,7 @@ class AutofillExternalDelegateUnitTest : public testing::Test {
kQueryId, suggestions, /*autoselect_first_suggestion=*/false);
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockAutofillClient> autofill_client_;
std::unique_ptr<testing::NiceMock<MockAutofillDriver>> autofill_driver_;
diff --git a/chromium/components/autofill/core/browser/autofill_handler.cc b/chromium/components/autofill/core/browser/autofill_handler.cc
index 40cc43fc396..065949cfb27 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler.cc
@@ -6,6 +6,7 @@
#include "base/containers/adapters.h"
#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/core/common/signatures_util.h"
@@ -49,7 +50,9 @@ bool CachedFormNeedsUpdate(const FormData& live_form,
using base::TimeTicks;
-AutofillHandler::AutofillHandler(AutofillDriver* driver) : driver_(driver) {}
+AutofillHandler::AutofillHandler(AutofillDriver* driver,
+ LogManager* log_manager)
+ : driver_(driver), log_manager_(log_manager) {}
AutofillHandler::~AutofillHandler() = default;
@@ -293,7 +296,7 @@ bool AutofillHandler::ParseForm(const FormData& form,
}
}
- form_structure->DetermineHeuristicTypes();
+ form_structure->DetermineHeuristicTypes(log_manager_);
// Hold the parsed_form_structure we intend to return. We can use this to
// reference the form_signature when transferring ownership below.
diff --git a/chromium/components/autofill/core/browser/autofill_handler.h b/chromium/components/autofill/core/browser/autofill_handler.h
index afde406d22a..aa79f09e107 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.h
+++ b/chromium/components/autofill/core/browser/autofill_handler.h
@@ -27,6 +27,7 @@ class AutofillField;
struct FormData;
struct FormFieldData;
class FormStructure;
+class LogManager;
// This class defines the interface should be implemented by autofill
// implementation in browser side to interact with AutofillDriver.
@@ -141,7 +142,7 @@ class AutofillHandler {
const FormStructureMap& form_structures() const { return form_structures_; }
protected:
- AutofillHandler(AutofillDriver* driver);
+ AutofillHandler(AutofillDriver* driver, LogManager* log_manager);
virtual void OnFormSubmittedImpl(const FormData& form,
bool known_success,
@@ -212,6 +213,8 @@ class AutofillHandler {
// outlive this object.
AutofillDriver* const driver_;
+ LogManager* const log_manager_;
+
// Our copy of the form data.
FormStructureMap form_structures_;
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
index b7074e62e6c..8a9fcaf4558 100644
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -11,8 +11,9 @@ namespace autofill {
using base::TimeTicks;
AutofillHandlerProxy::AutofillHandlerProxy(AutofillDriver* driver,
+ LogManager* log_manager,
AutofillProvider* provider)
- : AutofillHandler(driver), provider_(provider) {}
+ : AutofillHandler(driver, log_manager), provider_(provider) {}
AutofillHandlerProxy::~AutofillHandlerProxy() {}
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.h b/chromium/components/autofill/core/browser/autofill_handler_proxy.h
index 632578cab5a..152292c21ab 100644
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.h
+++ b/chromium/components/autofill/core/browser/autofill_handler_proxy.h
@@ -15,7 +15,9 @@ class AutofillProvider;
// This class forwards AutofillHandler calls to AutofillProvider.
class AutofillHandlerProxy : public AutofillHandler {
public:
- AutofillHandlerProxy(AutofillDriver* driver, AutofillProvider* provider);
+ AutofillHandlerProxy(AutofillDriver* driver,
+ LogManager* log_manager,
+ AutofillProvider* provider);
~AutofillHandlerProxy() override;
void OnFocusNoLongerOnForm() override;
diff --git a/chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc b/chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc
index 5d45ba839af..2baaee02348 100644
--- a/chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_internals_service_unittest.cc
@@ -17,7 +17,7 @@ TEST(AutofillInternalsService, Scope) {
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
EXPECT_EQ(R"({"attributes":{"class":"log-entry","scope":"Context"},)"
- R"("type":"node","value":"div"})",
+ R"("type":"element","value":"div"})",
json);
}
@@ -28,7 +28,7 @@ TEST(AutofillInternalsService, Message) {
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
EXPECT_EQ(R"({"attributes":{"class":"log-message","message":"ParsedForms"},)"
R"("children":[{"type":"text","value":"Parsed forms:"}],)"
- R"("type":"node","value":"div"})",
+ R"("type":"element","value":"div"})",
json);
}
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 823105c3d40..98281bbf87f 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -37,6 +37,7 @@
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
+#include "components/autofill/core/browser/autofill_browser_util.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
@@ -56,8 +57,6 @@
#include "components/autofill/core/browser/geo/country_names.h"
#include "components/autofill/core/browser/geo/phone_number_i18n.h"
#include "components/autofill/core/browser/logging/log_manager.h"
-#include "components/autofill/core/browser/metrics/address_form_event_logger.h"
-#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/metrics/form_events.h"
#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
#include "components/autofill/core/browser/payments/payments_client.h"
@@ -254,6 +253,98 @@ void LogAutofillTypePredictionsAvailable(
<< std::move(buffer);
}
+// Finds the first field in |form_structure| with |field.value|=|value|.
+AutofillField* FindFirstFieldWithValue(const FormStructure& form_structure,
+ const base::string16& value) {
+ for (const auto& field : form_structure) {
+ base::string16 trimmed_value;
+ base::TrimWhitespace(field->value, base::TRIM_ALL, &trimmed_value);
+ if (trimmed_value == value)
+ return field.get();
+ }
+ return nullptr;
+}
+
+// Heuristically identifies all possible credit card verification fields.
+AutofillField* HeuristicallyFindCVCField(const FormStructure& form_structure) {
+ // Stores a pointer to the explicitly found expiration year.
+ bool found_explicit_expiration_year_field = false;
+
+ // The first pass checks the existence of an explicitly marked field for the
+ // credit card expiration year.
+ for (const auto& field : form_structure) {
+ const ServerFieldTypeSet& type_set = field->possible_types();
+ if (type_set.find(CREDIT_CARD_EXP_2_DIGIT_YEAR) != type_set.end() ||
+ type_set.find(CREDIT_CARD_EXP_4_DIGIT_YEAR) != type_set.end()) {
+ found_explicit_expiration_year_field = true;
+ break;
+ }
+ }
+
+ // Keeps track if a credit card number field was found.
+ bool credit_card_number_found = false;
+
+ // In the second pass, the CVC field is heuristically searched for.
+ // A field is considered a CVC field, iff:
+ // * it appears after the credit card number field;
+ // * it has the |UNKNOWN_TYPE| prediction;
+ // * it does not look like an expiration year or an expiration year was
+ // already found;
+ // * it is filled with a 3-4 digit number;
+ for (const auto& field : form_structure) {
+ const ServerFieldTypeSet& type_set = field->possible_types();
+
+ // Checks if the field is of |CREDIT_CARD_NUMBER| type.
+ if (type_set.find(CREDIT_CARD_NUMBER) != type_set.end()) {
+ credit_card_number_found = true;
+ continue;
+ }
+ // Skip the field if no credit card number was found yet.
+ if (!credit_card_number_found) {
+ continue;
+ }
+
+ // Don't consider fields that already have any prediction.
+ if (type_set.find(UNKNOWN_TYPE) == type_set.end())
+ continue;
+ // |UNKNOWN_TYPE| should come alone.
+ DCHECK_EQ(1u, type_set.size());
+
+ base::string16 trimmed_value;
+ base::TrimWhitespace(field->value, base::TRIM_ALL, &trimmed_value);
+
+ // Skip the field if it can be confused with a expiration year.
+ if (!found_explicit_expiration_year_field &&
+ IsPlausible4DigitExpirationYear(trimmed_value)) {
+ continue;
+ }
+
+ // Skip the field if its value does not like a CVC value.
+ if (!IsPlausibleCreditCardCVCNumber(trimmed_value))
+ continue;
+
+ return field.get();
+ }
+ return nullptr;
+}
+
+// Iff the CVC of the credit card is known, find the first field with this
+// value (also set |properties_mask| to |KNOWN_VALUE|). Otherwise, heuristically
+// search for the CVC field if any.
+AutofillField* GetBestPossibleCVCField(
+ const FormStructure& form_structure,
+ base::string16 last_unlocked_credit_card_cvc) {
+ if (!last_unlocked_credit_card_cvc.empty()) {
+ AutofillField* result =
+ FindFirstFieldWithValue(form_structure, last_unlocked_credit_card_cvc);
+ if (result)
+ result->properties_mask = FieldPropertiesFlags::KNOWN_VALUE;
+ return result;
+ }
+
+ return HeuristicallyFindCVCField(form_structure);
+}
+
} // namespace
AutofillManager::FillingContext::FillingContext() = default;
@@ -552,11 +643,20 @@ bool AutofillManager::MaybeStartVoteUploadProcess(
// so that we can safely pass the address to the first callback regardless of
// the (undefined) order in which the callback parameters are computed.
FormStructure* raw_form = form_structure.get();
- base::PostTaskWithTraitsAndReply(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReply(
+ FROM_HERE,
+ // If the priority is BEST_EFFORT, the task can be preempted, which is
+ // thought to cause high memory usage (as memory is retained by the task
+ // while it is preempted).
+ //
+ // TODO(fdoray): Update when the hypothesis that setting the priority to
+ // USER_VISIBLE instead of BEST_EFFORT fixes memory usage. Consider
+ // keeping BEST_EFFORT priority, but manually enforcing a limit on the
+ // number of outstanding tasks. https://crbug.com/974249
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&AutofillManager::DeterminePossibleFieldTypesForUpload,
- copied_profiles, copied_credit_cards, app_locale_,
- raw_form),
+ copied_profiles, copied_credit_cards,
+ last_unlocked_credit_card_cvc_, app_locale_, raw_form),
base::BindOnce(&AutofillManager::UploadFormDataAsyncCallback,
weak_ptr_factory_.GetWeakPtr(),
base::Owned(form_structure.release()),
@@ -662,8 +762,7 @@ void AutofillManager::OnTextFieldDidChangeImpl(const FormData& form,
}
bool AutofillManager::IsFormNonSecure(const FormData& form) const {
- return !client_->IsContextSecure() ||
- (form.action.is_valid() && form.action.SchemeIs("http"));
+ return IsFormOrClientNonSecure(client_, form);
}
void AutofillManager::OnQueryFormFieldAutofillImpl(
@@ -1005,6 +1104,12 @@ void AutofillManager::DidShowSuggestions(bool has_autofill_suggestions,
form_structure->form_parsed_timestamp(),
sync_state_, driver()->IsIncognito());
}
+
+ if (autofill_field->Type().group() == CREDIT_CARD &&
+ base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardAuthentication)) {
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ }
}
void AutofillManager::OnHidePopup() {
@@ -1194,6 +1299,8 @@ void AutofillManager::OnCreditCardFetched(bool did_succeed,
return;
}
+ last_unlocked_credit_card_cvc_ = cvc;
+
FormStructure* form_structure = nullptr;
AutofillField* autofill_field = nullptr;
if (!GetCachedFormAndField(credit_card_form_, credit_card_field_,
@@ -1234,6 +1341,10 @@ bool AutofillManager::IsRichQueryEnabled(version_info::Channel channel) {
channel != version_info::Channel::BETA;
}
+const FormData& AutofillManager::last_query_form() const {
+ return external_delegate_->query_form();
+}
+
bool AutofillManager::ShouldUploadForm(const FormStructure& form) {
return IsAutofillEnabled() && !driver()->IsIncognito() &&
form.ShouldBeUploaded();
@@ -1285,6 +1396,11 @@ void AutofillManager::UploadFormData(const FormStructure& submitted_form,
ServerFieldTypeSet non_empty_types;
personal_data_->GetNonEmptyTypes(&non_empty_types);
+ // AS CVC is not stored, treat it separately.
+ if (!last_unlocked_credit_card_cvc_.empty() ||
+ non_empty_types.find(CREDIT_CARD_NUMBER) != non_empty_types.end()) {
+ non_empty_types.insert(CREDIT_CARD_VERIFICATION_CODE);
+ }
download_manager_->StartUploadRequest(
submitted_form, was_autofilled, non_empty_types,
@@ -1322,6 +1438,7 @@ void AutofillManager::Reset() {
credit_card_query_id_ = -1;
credit_card_form_ = FormData();
credit_card_field_ = FormFieldData();
+ last_unlocked_credit_card_cvc_.clear();
credit_card_action_ = AutofillDriver::FORM_DATA_ACTION_PREVIEW;
initial_interaction_timestamp_ = TimeTicks();
external_delegate_->Reset();
@@ -1334,8 +1451,9 @@ AutofillManager::AutofillManager(
PersonalDataManager* personal_data,
AutocompleteHistoryManager* autocomplete_history_manager,
const std::string app_locale,
- AutofillDownloadManagerState enable_download_manager)
- : AutofillHandler(driver),
+ AutofillDownloadManagerState enable_download_manager,
+ std::unique_ptr<CreditCardAccessManager> cc_access_manager)
+ : AutofillHandler(driver, client->GetLogManager()),
client_(client),
log_manager_(client_->GetLogManager()),
app_locale_(app_locale),
@@ -1355,21 +1473,21 @@ AutofillManager::AutofillManager(
form_interactions_ukm_logger_.get(),
personal_data_,
client_)),
- credit_card_access_manager_(std::make_unique<CreditCardAccessManager>(
- driver,
- client_,
- personal_data_,
- credit_card_form_event_logger_.get())),
#if defined(OS_ANDROID) || defined(OS_IOS)
autofill_assistant_(this),
#endif
is_rich_query_enabled_(IsRichQueryEnabled(client->GetChannel())) {
DCHECK(driver);
DCHECK(client_);
+ credit_card_access_manager_ = cc_access_manager
+ ? std::move(cc_access_manager)
+ : std::make_unique<CreditCardAccessManager>(
+ driver, client_, personal_data_,
+ credit_card_form_event_logger_.get());
if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
version_info::Channel channel = client_->GetChannel();
- download_manager_.reset(
- new AutofillDownloadManager(driver, this, GetAPIKeyForUrl(channel)));
+ download_manager_.reset(new AutofillDownloadManager(
+ driver, this, GetAPIKeyForUrl(channel), client_->GetLogManager()));
}
CountryNames::SetLocaleString(app_locale_);
}
@@ -1452,9 +1570,9 @@ void AutofillManager::FillOrPreviewDataModelForm(
filling_contexts_map_.find(form_structure->GetIdentifierForRefill());
if (itr != filling_contexts_map_.end())
filling_context = itr->second.get();
- bool could_attempt_refill =
- filling_context != nullptr && !filling_context->attempted_refill &&
- !is_refill && !is_credit_card;
+ bool could_attempt_refill = filling_context != nullptr &&
+ !filling_context->attempted_refill &&
+ !is_refill && !is_credit_card;
for (size_t i = 0; i < form_structure->field_count(); ++i) {
// On the renderer, the section is used regardless of the autofill status.
@@ -1843,13 +1961,13 @@ void AutofillManager::UpdateInitialInteractionTimestamp(
void AutofillManager::DeterminePossibleFieldTypesForUpload(
const std::vector<AutofillProfile>& profiles,
const std::vector<CreditCard>& credit_cards,
+ const base::string16& last_unlocked_credit_card_cvc,
const std::string& app_locale,
FormStructure* submitted_form) {
// For each field in the |submitted_form|, extract the value. Then for each
// profile or credit card, identify any stored types that match the value.
for (size_t i = 0; i < submitted_form->field_count(); ++i) {
AutofillField* field = submitted_form->field(i);
-
if (!field->possible_types().empty() && field->IsEmpty()) {
// This is a password field in a sign-in form. Skip checking its type
// since |field->value| is not set.
@@ -1887,6 +2005,16 @@ void AutofillManager::DeterminePossibleFieldTypesForUpload(
field->set_possible_types(matching_types);
}
+ // As CVCs are not stored, run special heuristics to detect CVC-like values.
+ AutofillField* cvc_field =
+ GetBestPossibleCVCField(*submitted_form, last_unlocked_credit_card_cvc);
+ if (cvc_field) {
+ ServerFieldTypeSet possible_types = cvc_field->possible_types();
+ possible_types.erase(UNKNOWN_TYPE);
+ possible_types.insert(CREDIT_CARD_VERIFICATION_CODE);
+ cvc_field->set_possible_types(possible_types);
+ }
+
AutofillManager::DisambiguateUploadTypes(submitted_form);
}
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index 35472453f78..905f5b8ff4a 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -7,6 +7,7 @@
#include <map>
#include <memory>
+#include <set>
#include <string>
#include <vector>
@@ -107,7 +108,7 @@ class AutofillManager : public AutofillHandler,
virtual bool ShouldShowCreditCardSigninPromo(const FormData& form,
const FormFieldData& field);
- // Handlers for the "Set Cards From Account" row. This row should be shown to
+ // Handlers for the "Show Cards From Account" row. This row should be shown to
// users who have cards in their account and can use Sync Transport. Clicking
// the row records the user's consent to see these cards on this device, and
// refreshes the popup.
@@ -165,6 +166,10 @@ class AutofillManager : public AutofillHandler,
return download_manager_.get();
}
+ CreditCardAccessManager* credit_card_access_manager() {
+ return credit_card_access_manager_.get();
+ }
+
payments::FullCardRequest* GetOrCreateFullCardRequest();
base::WeakPtr<payments::FullCardRequest::UIDelegate>
@@ -235,15 +240,20 @@ class AutofillManager : public AutofillHandler,
// neither on the STABLE nor BETA release channel.
static bool IsRichQueryEnabled(version_info::Channel channel);
+ // Returns the last form the autofill manager considered in this frame.
+ virtual const FormData& last_query_form() const;
+
protected:
// Test code should prefer to use this constructor.
- AutofillManager(AutofillDriver* driver,
- AutofillClient* client,
- PersonalDataManager* personal_data,
- AutocompleteHistoryManager* autocomplete_history_manager,
- const std::string app_locale = "en-US",
- AutofillDownloadManagerState enable_download_manager =
- DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ AutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ PersonalDataManager* personal_data,
+ AutocompleteHistoryManager* autocomplete_history_manager,
+ const std::string app_locale = "en-US",
+ AutofillDownloadManagerState enable_download_manager =
+ DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ std::unique_ptr<CreditCardAccessManager> cc_access_manager = nullptr);
// Uploads the form data to the Autofill server. |observed_submission|
// indicates that upload is the result of a submission event.
@@ -464,6 +474,7 @@ class AutofillManager : public AutofillHandler,
static void DeterminePossibleFieldTypesForUpload(
const std::vector<AutofillProfile>& profiles,
const std::vector<CreditCard>& credit_cards,
+ const base::string16& last_unlocked_credit_card_cvc,
const std::string& app_locale,
FormStructure* submitted_form);
@@ -582,6 +593,7 @@ class AutofillManager : public AutofillHandler,
FormData credit_card_form_;
FormFieldData credit_card_field_;
CreditCard credit_card_;
+ base::string16 last_unlocked_credit_card_cvc_;
// Ablation experiment turns off autofill, but logging still has to be kept
// for metrics analysis.
@@ -623,6 +635,7 @@ class AutofillManager : public AutofillHandler,
friend class AutofillMetricsTest;
friend class FormStructureBrowserTest;
friend class GetMatchingTypesTest;
+ friend class CreditCardAccessoryControllerTest;
FRIEND_TEST_ALL_PREFIXES(ProfileMatchingTypesTest,
DeterminePossibleFieldTypesForUpload);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
@@ -631,6 +644,19 @@ class AutofillManager : public AutofillHandler,
DeterminePossibleFieldTypesForUploadStressTest);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, DisambiguateUploadTypes);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, CrowdsourceUPIVPA);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, CrowdsourceCVCFieldByValue);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ CrowdsourceCVCFieldAfterExpDateByHeuristics);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ CrowdsourceCVCFieldDisableHeurisitcs);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ CrowdsourceNoCVCDueToInvalidCandidateValue);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ CrowdsourceNoCVCFieldDueToMissingCreditCardNumber);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ CrowdsourceCVCFieldAfterInvalidExpDateByHeuristics);
+ FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
+ CrowdsourceCVCFieldBeforeExpDateByHeuristics);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
DisabledAutofillDispatchesError);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index 853c5c1ef46..3aee9d14555 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -23,9 +23,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -65,11 +66,8 @@
#include "components/strings/grit/components_strings.h"
#include "components/sync/driver/test_sync_service.h"
#include "components/variations/variations_associated_data.h"
-#include "components/variations/variations_params_manager.h"
#include "components/version_info/channel.h"
#include "net/base/url_util.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -274,6 +272,31 @@ void ExpectFilledCreditCardYearMonthWithYearMonth(int page_id,
month, year, has_address_fields, true, true);
}
+void CheckThatOnlyFieldByIndexHasThisPossibleType(
+ const FormStructure& form_structure,
+ size_t field_index,
+ ServerFieldType type,
+ FieldPropertiesMask mask) {
+ EXPECT_TRUE(field_index < form_structure.field_count());
+
+ for (size_t i = 0; i < form_structure.field_count(); i++) {
+ if (i == field_index) {
+ EXPECT_THAT(form_structure.field(i)->possible_types(), ElementsAre(type));
+ EXPECT_EQ(mask, form_structure.field(i)->properties_mask);
+ } else {
+ EXPECT_THAT(form_structure.field(i)->possible_types(),
+ Not(Contains(type)));
+ }
+ }
+}
+
+void CheckThatNoFieldHasThisPossibleType(const FormStructure& form_structure,
+ ServerFieldType type) {
+ for (size_t i = 0; i < form_structure.field_count(); i++) {
+ EXPECT_THAT(form_structure.field(i)->possible_types(), Not(Contains(type)));
+ }
+}
+
class MockAutofillDriver : public TestAutofillDriver {
public:
MockAutofillDriver() {}
@@ -316,9 +339,6 @@ class AutofillManagerTest : public testing::Test {
autofill_driver_ =
std::make_unique<testing::NiceMock<MockAutofillDriver>>();
- request_context_ = new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get());
- autofill_driver_->SetURLRequestContext(request_context_.get());
payments::TestPaymentsClient* payments_client =
new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(),
@@ -348,8 +368,6 @@ class AutofillManagerTest : public testing::Test {
/*call_parent_methods=*/false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
- variation_params_.ClearAllVariationParams();
-
// Initialize the TestPersonalDataManager with some default data.
CreateTestAutofillProfiles();
CreateTestCreditCards();
@@ -411,8 +429,6 @@ class AutofillManagerTest : public testing::Test {
personal_data_.SetPrefService(nullptr);
personal_data_.ClearCreditCards();
-
- request_context_ = nullptr;
}
void GetAutofillSuggestions(int query_id,
@@ -545,7 +561,9 @@ class AutofillManagerTest : public testing::Test {
autofill_manager_->credit_card_access_manager_->cvc_authenticator_
->full_card_request_.get();
DCHECK(full_card_request);
- full_card_request->OnDidGetRealPan(result, real_pan);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ full_card_request->OnDidGetRealPan(result,
+ response.with_real_pan(real_pan));
}
// Convenience method to cast the FullCardRequest into a CardUnmaskDelegate.
@@ -593,17 +611,15 @@ class AutofillManagerTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockAutofillClient autofill_client_;
std::unique_ptr<MockAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
std::unique_ptr<TestAutofillExternalDelegate> external_delegate_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_;
scoped_refptr<AutofillWebDataService> database_;
MockAutofillDownloadManager* download_manager_;
TestPersonalDataManager personal_data_;
std::unique_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager_;
- variations::testing::VariationParamsManager variation_params_;
base::test::ScopedFeatureList scoped_feature_list_;
private:
@@ -2208,7 +2224,7 @@ TEST_F(AutofillManagerTest, WillFillCreditCardNumber) {
TEST_F(AutofillManagerTest, FillCreditCardForm_LogFieldWasAutofill) {
// Set up our form data.
FormData form;
- // Construct a form with 4 fields: cardholder name, card number,
+ // Construct a form with a 4 fields: cardholder name, card number,
// expiration date and cvc.
CreateTestCreditCardFormData(&form, true, true);
std::vector<FormData> forms(1, form);
@@ -5038,7 +5054,7 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) {
base::HistogramTester histogram_tester;
AutofillManager::DeterminePossibleFieldTypesForUpload(
- profiles, credit_cards, "en-us", &form_structure);
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
ASSERT_EQ(1U, form_structure.field_count());
@@ -5186,8 +5202,8 @@ TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesWithMultipleValidities) {
form_structure.field(i)->set_server_type(test_fields[i].field_type);
}
- AutofillManager::DeterminePossibleFieldTypesForUpload(profiles, {}, "en-us",
- &form_structure);
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, {}, base::string16(), "en-us", &form_structure);
ASSERT_EQ(test_fields.size(), form_structure.field_count());
@@ -5374,7 +5390,7 @@ TEST_F(AutofillManagerTest, DisambiguateUploadTypes) {
}
AutofillManager::DeterminePossibleFieldTypesForUpload(
- profiles, credit_cards, "en-us", &form_structure);
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
ASSERT_EQ(test_fields.size(), form_structure.field_count());
// Make sure the disambiguation method selects the expected upload type.
@@ -5407,13 +5423,316 @@ TEST_F(AutofillManagerTest, CrowdsourceUPIVPA) {
FormStructure form_structure(form);
AutofillManager::DeterminePossibleFieldTypesForUpload(
- profiles, credit_cards, "en-us", &form_structure);
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
EXPECT_THAT(form_structure.field(0)->possible_types(), ElementsAre(UPI_VPA));
EXPECT_THAT(form_structure.field(1)->possible_types(),
Not(Contains(UPI_VPA)));
}
+// If a server-side credit card is unmasked by entering the CVC, the
+// AutofillManager reuses the CVC value to identify a potentially existing CVC
+// form field to cast a |CREDIT_CARD_VERIFICATION_CODE|-type vote.
+TEST_F(AutofillManagerTest, CrowdsourceCVCFieldByValue) {
+ std::vector<AutofillProfile> profiles;
+ std::vector<CreditCard> credit_cards;
+
+ const char cvc[] = "1234";
+ const char four_digit_but_not_cvc[] = "6676";
+ const char credit_card_number[] = "4234-5678-9012-3456";
+
+ FormData form;
+ FormFieldData field1;
+ test::CreateTestFormField("number", "number", credit_card_number, "text",
+ &field1);
+ form.fields.push_back(field1);
+
+ // This field would not be detected as CVC heuristically if the CVC value
+ // wouldn't be known.
+ FormFieldData field2;
+ test::CreateTestFormField("not_cvc", "not_cvc", four_digit_but_not_cvc,
+ "text", &field2);
+ form.fields.push_back(field2);
+
+ // This field has the CVC value used to unlock the card and should be detected
+ // as the CVC field.
+ FormFieldData field3;
+ test::CreateTestFormField("c_v_c", "c_v_c", cvc, "text", &field3);
+ form.fields.push_back(field3);
+
+ FormStructure form_structure(form);
+ form_structure.field(0)->set_possible_types({CREDIT_CARD_NUMBER});
+
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, credit_cards, base::ASCIIToUTF16(cvc), "en-us",
+ &form_structure);
+
+ CheckThatOnlyFieldByIndexHasThisPossibleType(
+ form_structure, 2, CREDIT_CARD_VERIFICATION_CODE,
+ FieldPropertiesFlags::KNOWN_VALUE);
+}
+
+// Expiration year field was detected by the server. The other field with a
+// 4-digit value should be detected as CVC.
+TEST_F(AutofillManagerTest,
+ CrowdsourceCVCFieldAfterInvalidExpDateByHeuristics) {
+ FormData form;
+ FormFieldData field;
+
+ const char credit_card_number[] = "4234-5678-9012-3456";
+ const char actual_credit_card_exp_year[] = "2030";
+ const char user_entered_credit_card_exp_year[] = "2031";
+ const char cvc[] = "1234";
+
+ test::CreateTestFormField("number", "number", credit_card_number, "text",
+ &field);
+ form.fields.push_back(field);
+
+ // Expiration date, but is not the expiration date of the used credit card.
+ FormFieldData field1;
+ test::CreateTestFormField("exp_year", "exp_year",
+ user_entered_credit_card_exp_year, "text", &field1);
+ form.fields.push_back(field1);
+
+ // Must be CVC since expiration date was already identified.
+ FormFieldData field2;
+ test::CreateTestFormField("cvc_number", "cvc_number", cvc, "text", &field2);
+ form.fields.push_back(field2);
+
+ FormStructure form_structure(form);
+
+ // Set the field types.
+ form_structure.field(0)->set_possible_types({CREDIT_CARD_NUMBER});
+ form_structure.field(1)->set_possible_types({CREDIT_CARD_EXP_4_DIGIT_YEAR});
+ form_structure.field(2)->set_possible_types({UNKNOWN_TYPE});
+
+ // Set up the test credit cards.
+ std::vector<CreditCard> credit_cards;
+ CreditCard credit_card;
+ test::SetCreditCardInfo(&credit_card, "John Doe", credit_card_number, "04",
+ actual_credit_card_exp_year, "1");
+ credit_card.set_guid("00000000-0000-0000-0000-000000000003");
+ credit_cards.push_back(credit_card);
+
+ // Set up the test profiles.
+ std::vector<AutofillProfile> profiles;
+
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
+
+ CheckThatOnlyFieldByIndexHasThisPossibleType(form_structure, 2,
+ CREDIT_CARD_VERIFICATION_CODE,
+ FieldPropertiesFlags::NO_FLAGS);
+}
+
+// Tests if the CVC field is heuristically detected if it appears after the
+// expiration year field as it was predicted by the server.
+// The value in the CVC field would be a valid expiration year value.
+TEST_F(AutofillManagerTest, CrowdsourceCVCFieldAfterExpDateByHeuristics) {
+ FormData form;
+ FormFieldData field;
+
+ const char credit_card_number[] = "4234-5678-9012-3456";
+ const char actual_credit_card_exp_year[] = "2030";
+ const char cvc[] = "1234";
+
+ test::CreateTestFormField("number", "number", credit_card_number, "text",
+ &field);
+ form.fields.push_back(field);
+
+ // Expiration date, that is the expiration date of the used credit card.
+ FormFieldData field1;
+ test::CreateTestFormField("date_or_cvc1", "date_or_cvc1",
+ actual_credit_card_exp_year, "text", &field1);
+ form.fields.push_back(field1);
+
+ // Must be CVC since expiration date was already identified.
+ FormFieldData field2;
+ test::CreateTestFormField("date_or_cvc2", "date_or_cvc2", cvc, "text",
+ &field2);
+ form.fields.push_back(field2);
+
+ FormStructure form_structure(form);
+
+ // Set the field types.
+ form_structure.field(0)->set_possible_types({CREDIT_CARD_NUMBER});
+ form_structure.field(1)->set_possible_types({CREDIT_CARD_EXP_4_DIGIT_YEAR});
+ form_structure.field(2)->set_possible_types({UNKNOWN_TYPE});
+
+ // Set up the test credit cards.
+ std::vector<CreditCard> credit_cards;
+ CreditCard credit_card;
+ test::SetCreditCardInfo(&credit_card, "John Doe", credit_card_number, "04",
+ actual_credit_card_exp_year, "1");
+ credit_card.set_guid("00000000-0000-0000-0000-000000000003");
+ credit_cards.push_back(credit_card);
+
+ // Set up the test profiles.
+ std::vector<AutofillProfile> profiles;
+
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
+
+ CheckThatOnlyFieldByIndexHasThisPossibleType(form_structure, 2,
+ CREDIT_CARD_VERIFICATION_CODE,
+ FieldPropertiesFlags::NO_FLAGS);
+}
+
+// Tests if the CVC field is heuristically detected if it contains a value which
+// is not a valid expiration year.
+TEST_F(AutofillManagerTest, CrowdsourceCVCFieldBeforeExpDateByHeuristics) {
+ FormData form;
+ FormFieldData field;
+
+ const char credit_card_number[] = "4234-5678-9012-3456";
+ const char actual_credit_card_exp_year[] = "2030";
+ const char user_entered_credit_card_exp_year[] = "2031";
+
+ test::CreateTestFormField("number", "number", credit_card_number, "text",
+ &field);
+ form.fields.push_back(field);
+
+ // Must be CVC since it is an implausible expiration date.
+ FormFieldData field2;
+ test::CreateTestFormField("date_or_cvc2", "date_or_cvc2", "2130", "text",
+ &field2);
+ form.fields.push_back(field2);
+
+ // A field which is filled with a plausible expiration date which is not the
+ // date of the credit card.
+ FormFieldData field1;
+ test::CreateTestFormField("date_or_cvc1", "date_or_cvc1",
+ user_entered_credit_card_exp_year, "text", &field1);
+ form.fields.push_back(field1);
+
+ FormStructure form_structure(form);
+
+ // Set the field types.
+ form_structure.field(0)->set_possible_types({CREDIT_CARD_NUMBER});
+ form_structure.field(1)->set_possible_types({UNKNOWN_TYPE});
+ form_structure.field(2)->set_possible_types({UNKNOWN_TYPE});
+
+ // Set up the test credit cards.
+ std::vector<CreditCard> credit_cards;
+ CreditCard credit_card;
+ test::SetCreditCardInfo(&credit_card, "John Doe", credit_card_number, "04",
+ actual_credit_card_exp_year, "1");
+ credit_card.set_guid("00000000-0000-0000-0000-000000000003");
+ credit_cards.push_back(credit_card);
+
+ // Set up the test profiles.
+ std::vector<AutofillProfile> profiles;
+
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
+
+ CheckThatOnlyFieldByIndexHasThisPossibleType(form_structure, 1,
+ CREDIT_CARD_VERIFICATION_CODE,
+ FieldPropertiesFlags::NO_FLAGS);
+}
+
+// Tests if no CVC field is heuristically detected due to the missing of a
+// credit card number field.
+TEST_F(AutofillManagerTest, CrowdsourceNoCVCFieldDueToMissingCreditCardNumber) {
+ FormData form;
+ FormFieldData field;
+
+ const char credit_card_number[] = "4234-5678-9012-3456";
+ const char actual_credit_card_exp_year[] = "2030";
+ const char user_entered_credit_card_exp_year[] = "2031";
+ const char cvc[] = "2031";
+
+ test::CreateTestFormField("number", "number", credit_card_number, "text",
+ &field);
+ form.fields.push_back(field);
+
+ // Server predicted as expiration year.
+ FormFieldData field1;
+ test::CreateTestFormField("date_or_cvc1", "date_or_cvc1",
+ user_entered_credit_card_exp_year, "text", &field1);
+ form.fields.push_back(field1);
+
+ // Must be CVC since expiration date was already identified.
+ FormFieldData field2;
+ test::CreateTestFormField("date_or_cvc2", "date_or_cvc2", cvc, "text",
+ &field2);
+ form.fields.push_back(field2);
+
+ FormStructure form_structure(form);
+
+ // Set the field types.
+ form_structure.field(0)->set_possible_types({UNKNOWN_TYPE});
+ form_structure.field(1)->set_possible_types({CREDIT_CARD_EXP_4_DIGIT_YEAR});
+ form_structure.field(2)->set_possible_types({UNKNOWN_TYPE});
+
+ // Set up the test credit cards.
+ std::vector<CreditCard> credit_cards;
+ CreditCard credit_card;
+ test::SetCreditCardInfo(&credit_card, "John Doe", credit_card_number, "04",
+ actual_credit_card_exp_year, "1");
+ credit_card.set_guid("00000000-0000-0000-0000-000000000003");
+ credit_cards.push_back(credit_card);
+
+ // Set up the test profiles.
+ std::vector<AutofillProfile> profiles;
+
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
+ CheckThatNoFieldHasThisPossibleType(form_structure,
+ CREDIT_CARD_VERIFICATION_CODE);
+}
+
+// Test if no CVC is found because the candidate has no valid CVC value.
+TEST_F(AutofillManagerTest, CrowdsourceNoCVCDueToInvalidCandidateValue) {
+ FormData form;
+ FormFieldData field;
+
+ const char credit_card_number[] = "4234-5678-9012-3456";
+ const char credit_card_exp_year[] = "2030";
+ const char cvc[] = "12";
+
+ test::CreateTestFormField("number", "number", credit_card_number, "text",
+ &field);
+ form.fields.push_back(field);
+
+ // Server predicted as expiration year.
+ FormFieldData field1;
+ test::CreateTestFormField("date_or_cvc1", "date_or_cvc1",
+ credit_card_exp_year, "text", &field1);
+ form.fields.push_back(field1);
+
+ // Must be CVC since expiration date was already identified.
+ FormFieldData field2;
+ test::CreateTestFormField("date_or_cvc2", "date_or_cvc2", cvc, "text",
+ &field2);
+ form.fields.push_back(field2);
+
+ FormStructure form_structure(form);
+
+ // Set the field types.
+ form_structure.field(0)->set_possible_types(
+ {CREDIT_CARD_NUMBER, UNKNOWN_TYPE});
+ form_structure.field(1)->set_possible_types({CREDIT_CARD_EXP_4_DIGIT_YEAR});
+ form_structure.field(2)->set_possible_types({UNKNOWN_TYPE});
+
+ // Set up the test credit cards.
+ std::vector<CreditCard> credit_cards;
+ CreditCard credit_card;
+ test::SetCreditCardInfo(&credit_card, "John Doe", credit_card_number, "04",
+ credit_card_exp_year, "1");
+ credit_card.set_guid("00000000-0000-0000-0000-000000000003");
+ credit_cards.push_back(credit_card);
+
+ // Set up the test profiles.
+ std::vector<AutofillProfile> profiles;
+
+ AutofillManager::DeterminePossibleFieldTypesForUpload(
+ profiles, credit_cards, base::string16(), "en-us", &form_structure);
+
+ CheckThatNoFieldHasThisPossibleType(form_structure,
+ CREDIT_CARD_VERIFICATION_CODE);
+}
+
TEST_F(AutofillManagerTest, RemoveProfile) {
// Add and remove an Autofill profile.
AutofillProfile profile;
@@ -5765,10 +6084,10 @@ TEST_F(AutofillManagerTest, DontOfferToSavePaymentsCard) {
form.fields[i].value = ASCIIToUTF16("2017");
}
- CardUnmaskDelegate::UnmaskResponse response;
- response.should_store_pan = false;
- response.cvc = ASCIIToUTF16("123");
- full_card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.should_store_pan = false;
+ details.cvc = ASCIIToUTF16("123");
+ full_card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4012888888881881");
autofill_manager_->OnFormSubmitted(form, false,
SubmissionSource::FORM_SUBMISSION);
@@ -5779,12 +6098,12 @@ TEST_F(AutofillManagerTest, FillInUpdatedExpirationDate) {
CreditCard card;
PrepareForRealPanResponse(&form, &card);
- CardUnmaskDelegate::UnmaskResponse response;
- response.should_store_pan = false;
- response.cvc = ASCIIToUTF16("123");
- response.exp_month = ASCIIToUTF16("02");
- response.exp_year = ASCIIToUTF16("2018");
- full_card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.should_store_pan = false;
+ details.cvc = ASCIIToUTF16("123");
+ details.exp_month = ASCIIToUTF16("02");
+ details.exp_year = ASCIIToUTF16("2018");
+ full_card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4012888888881881");
}
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index 2427d940f93..a845b3daed5 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -16,7 +16,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_driven_test.h"
@@ -183,7 +183,7 @@ class AutofillMergeTest : public DataDrivenTest,
// Deserializes |str| into a field type.
ServerFieldType StringToFieldType(const std::string& str);
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
PersonalDataManagerMock personal_data_;
std::unique_ptr<FormDataImporter> form_data_importer_;
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 09435462998..e2ad2699390 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -82,18 +82,16 @@ std::string PreviousSaveCreditCardPromptUserDecisionToString(
return previous_response;
}
-// Reduce FormSignature space (in UKM) to a small range for privacy reasons.
+} // namespace
+
int64_t HashFormSignature(autofill::FormSignature form_signature) {
return static_cast<uint64_t>(form_signature) % 1021;
}
-// Reduce FieldSignature space (in UKM) to a small range for privacy reasons.
int64_t HashFieldSignature(autofill::FieldSignature field_signature) {
return static_cast<uint64_t>(field_signature) % 1021;
}
-} // namespace
-
// First, translates |field_type| to the corresponding logical |group| from
// |FieldTypeGroupForMetrics|. Then, interpolates this with the given |metric|,
// which should be in the range [0, |num_possible_metrics|).
@@ -609,22 +607,6 @@ void AutofillMetrics::LogLocalCardMigrationNotOfferedDueToMaxStrikesMetric(
}
// static
-void AutofillMetrics::LogUploadDisallowedForNetworkMetric(
- const std::string& network) {
- UploadDisallowedForNetworkMetric metric;
- if (network == kEloCard) {
- metric = DISALLOWED_ELO;
- } else if (network == kJCBCard) {
- metric = DISALLOWED_JCB;
- } else {
- NOTREACHED();
- return;
- }
- UMA_HISTOGRAM_ENUMERATION("Autofill.CreditCardUploadDisallowedForNetwork",
- metric);
-}
-
-// static
void AutofillMetrics::LogUploadOfferedCardOriginMetric(
UploadOfferedCardOriginMetric metric) {
DCHECK_LT(metric, NUM_UPLOAD_OFFERED_CARD_ORIGIN_METRICS);
@@ -651,14 +633,6 @@ void AutofillMetrics::LogSaveCardCardholderNameWasEdited(bool edited) {
}
// static
-void AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
- BillingIdStatus status) {
- DCHECK_LE(status, BillingIdStatus::kMaxValue);
- UMA_HISTOGRAM_ENUMERATION("Autofill.PaymentsCustomerDataBillingIdStatus",
- status);
-}
-
-// static
void AutofillMetrics::LogCardUploadDecisionMetrics(
int upload_decision_metrics) {
DCHECK(upload_decision_metrics);
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index 310b3080bc7..7ebd53ccb73 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -35,6 +35,12 @@ class CreditCard;
// A given maximum is enforced to minimize the number of buckets generated.
extern const int kMaxBucketsCount;
+// Reduce FormSignature space (in UKM) to a small range for privacy reasons.
+int64_t HashFormSignature(autofill::FormSignature form_signature);
+
+// Reduce FieldSignature space (in UKM) to a small range for privacy reasons.
+int64_t HashFieldSignature(autofill::FieldSignature field_signature);
+
class AutofillMetrics {
public:
enum AutofillProfileAction {
@@ -53,13 +59,6 @@ class AutofillMetrics {
AUTOFILL_FORM_SUBMITTED_STATE_ENUM_SIZE,
};
- enum class BillingIdStatus {
- MISSING = 0,
- PARSE_ERROR = 1,
- VALID = 2,
- kMaxValue = VALID,
- };
-
enum CardUploadDecisionMetric {
// All the required conditions were satisfied using either the form fields
// or we prompted the user to fix one or more conditions in the card upload
@@ -204,14 +203,6 @@ class AutofillMetrics {
kMaxValue = SERVER,
};
- // Metric to measure volume of cards that are disallowed for upload by their
- // network, most likely due to their network being blocked by Google Payments.
- enum UploadDisallowedForNetworkMetric {
- DISALLOWED_ELO = 0,
- DISALLOWED_JCB = 1,
- kMaxValue = DISALLOWED_JCB,
- };
-
// Metric to measure if a card for which upload was offered is already stored
// as a local card on the device or if it has not yet been seen.
enum UploadOfferedCardOriginMetric {
@@ -796,7 +787,7 @@ class AutofillMetrics {
SYNC_SERVICE_PERSISTENT_AUTH_ERROR = 1,
SYNC_SERVICE_MISSING_AUTOFILL_WALLET_DATA_ACTIVE_TYPE = 2,
SYNC_SERVICE_MISSING_AUTOFILL_PROFILE_ACTIVE_TYPE = 3,
- ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED = 4,
+ // Deprecated: ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED = 4,
USING_SECONDARY_SYNC_PASSPHRASE = 5,
LOCAL_SYNC_ENABLED = 6,
PAYMENTS_INTEGRATION_DISABLED = 7,
@@ -923,10 +914,6 @@ class AutofillMetrics {
static void LogLocalCardMigrationNotOfferedDueToMaxStrikesMetric(
SaveTypeMetric metric);
- // When credit card upload is disallowed for a particular network, logs which
- // network was blocked.
- static void LogUploadDisallowedForNetworkMetric(const std::string& network);
-
// When credit card upload is offered, logs whether the card being offered is
// already a local card on the device or not.
static void LogUploadOfferedCardOriginMetric(
@@ -946,9 +933,6 @@ class AutofillMetrics {
// from its prefilled value or not.
static void LogSaveCardCardholderNameWasEdited(bool edited);
- // Logs the PaymentsCustomerData billing ID status at the time of use.
- static void LogPaymentsCustomerDataBillingIdStatus(BillingIdStatus status);
-
// |upload_decision_metrics| is a bitmask of |CardUploadDecisionMetric|.
static void LogCardUploadDecisionMetrics(int upload_decision_metrics);
static void LogCreditCardInfoBarMetric(
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index 84cb8984bdd..33cc102717a 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -19,7 +19,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
@@ -283,7 +283,7 @@ class AutofillMetricsTest : public testing::Test {
// Purge recorded UKM metrics for running more tests.
void PurgeUKM();
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockAutofillClient autofill_client_;
ukm::TestUkmRecorder* test_ukm_recorder_;
syncer::TestSyncService sync_service_;
@@ -400,7 +400,8 @@ void AutofillMetricsTest::OnDidGetRealPan(
->GetOrCreateCVCAuthenticator()
->full_card_request_.get();
DCHECK(full_card_request);
- full_card_request->OnDidGetRealPan(result, real_pan);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ full_card_request->OnDidGetRealPan(result, response.with_real_pan(real_pan));
}
void AutofillMetricsTest::RecreateCreditCards(
diff --git a/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc
index e2cd547cb56..545c62144a8 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc
@@ -13,7 +13,7 @@
#include "base/bind.h"
#include "base/guid.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -105,7 +105,7 @@ class AutofillProfileValidatorTest : public testing::Test {
expected_validity_;
private:
- base::test::ScopedTaskEnvironment scoped_task_scheduler;
+ base::test::TaskEnvironment scoped_task_scheduler;
DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidatorTest);
};
diff --git a/chromium/components/autofill/core/browser/autofill_type.cc b/chromium/components/autofill/core/browser/autofill_type.cc
index a019c24a1ce..d141a0dbcd3 100644
--- a/chromium/components/autofill/core/browser/autofill_type.cc
+++ b/chromium/components/autofill/core/browser/autofill_type.cc
@@ -94,6 +94,9 @@ FieldTypeGroup GroupTypeOfServerFieldType(ServerFieldType field_type) {
case PROBABLY_NEW_PASSWORD:
case NOT_NEW_PASSWORD:
case CONFIRMATION_PASSWORD:
+ case NOT_PASSWORD:
+ case SINGLE_USERNAME:
+ case NOT_USERNAME:
return PASSWORD_FIELD;
case NO_SERVER_DATA:
@@ -123,9 +126,9 @@ FieldTypeGroup GroupTypeOfServerFieldType(ServerFieldType field_type) {
case UNKNOWN_TYPE:
return NO_GROUP;
- default:
- return NO_GROUP;
}
+ NOTREACHED();
+ return NO_GROUP;
}
FieldTypeGroup GroupTypeOfHtmlFieldType(HtmlFieldType field_type,
@@ -193,9 +196,9 @@ FieldTypeGroup GroupTypeOfHtmlFieldType(HtmlFieldType field_type,
case HTML_TYPE_UNSPECIFIED:
case HTML_TYPE_UNRECOGNIZED:
return NO_GROUP;
- default:
- return NO_GROUP;
}
+ NOTREACHED();
+ return NO_GROUP;
}
AutofillType::AutofillType(ServerFieldType field_type)
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc b/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc
index 84eecdc0f29..beda49cdaf0 100644
--- a/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -55,6 +55,15 @@ const char* const kInvalidNumbers[] = {
"3056 9309 0259 04aa", /* non-digit characters */
};
+// Time moves on. Today is yesterday's tomorrow. Tests don't like time moving
+// on, in particular if Credit Card expiration is compared to local time.
+// Use this function to generate a year in the future.
+base::string16 GetYearInTheFuture() {
+ base::Time::Exploded now;
+ base::Time::Now().LocalExplode(&now);
+ return base::NumberToString16(now.year + 4);
+}
+
} // namespace
TEST(CreditCardTest, GetObfuscatedStringForCardDigits) {
@@ -694,6 +703,8 @@ TEST(CreditCardTest, IconResourceId) {
}
TEST(CreditCardTest, UpdateFromImportedCard_UpdatedWithNameAndExpirationDate) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -704,18 +715,20 @@ TEST(CreditCardTest, UpdateFromImportedCard_UpdatedWithNameAndExpirationDate) {
b.set_guid(base::GenerateGUID());
b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
// |a| should be updated with the information from |b|.
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(test::kEmptyOrigin, a.origin());
EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
- EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
}
TEST(CreditCardTest,
UpdateFromImportedCard_UpdatedWithNameAndInvalidExpirationDateMonth) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -729,7 +742,7 @@ TEST(CreditCardTest,
b.set_guid(base::GenerateGUID());
b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("0"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(test::kEmptyOrigin, a.origin());
@@ -766,6 +779,8 @@ TEST(CreditCardTest,
TEST(CreditCardTest,
UpdateFromImportedCard_UpdatedWithEmptyNameAndValidExpirationDate) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -778,19 +793,21 @@ TEST(CreditCardTest,
b.set_guid(base::GenerateGUID());
b.SetRawInfo(CREDIT_CARD_NAME_FULL, base::string16());
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ(test::kEmptyOrigin, a.origin());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"),
a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
- EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
}
TEST(
CreditCardTest,
UpdateFromImportedCard_VerifiedCardNotUpdatedWithEmptyExpirationDateMonth) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -805,7 +822,7 @@ TEST(
b.set_origin(test::kEmptyOrigin);
b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("0"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
@@ -867,6 +884,8 @@ TEST(CreditCardTest,
TEST(CreditCardTest,
UpdateFromImportedCard_ExpiredVerifiedCardNotUpdatedWithDifferentName) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -882,7 +901,7 @@ TEST(CreditCardTest,
b.set_origin(test::kEmptyOrigin);
b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger"));
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
@@ -894,6 +913,8 @@ TEST(CreditCardTest,
TEST(CreditCardTest,
UpdateFromImportedCard_ExpiredVerifiedCardUpdatedWithSameName) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -908,14 +929,14 @@ TEST(CreditCardTest,
b.set_guid(base::GenerateGUID());
b.set_origin(test::kEmptyOrigin);
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2023"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"),
a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
- EXPECT_EQ(ASCIIToUTF16("2023"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
}
TEST(CreditCardTest,
@@ -946,6 +967,8 @@ TEST(CreditCardTest,
TEST(CreditCardTest,
UpdateFromImportedCard_VerifiedCardUpdatedWithVerifiedCard) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -959,18 +982,20 @@ TEST(CreditCardTest,
b.set_guid(base::GenerateGUID());
b.set_origin(kSettingsOrigin);
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
EXPECT_EQ(ASCIIToUTF16("John Dillinger"),
a.GetRawInfo(CREDIT_CARD_NAME_FULL));
EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH));
- EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
+ EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
}
TEST(CreditCardTest,
UpdateFromImportedCard_VerifiedCardNotUpdatedWithDifferentCard) {
+ const base::string16 kYearInFuture = GetYearInTheFuture();
+
CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin);
test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012",
"09", "2017", "1");
@@ -985,7 +1010,7 @@ TEST(CreditCardTest,
b.set_origin(kSettingsOrigin);
b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111"));
b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08"));
- b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019"));
+ b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture);
EXPECT_FALSE(a.UpdateFromImportedCard(b, "en-US"));
EXPECT_EQ("Chrome settings", a.origin());
diff --git a/chromium/components/autofill/core/browser/data_model/phone_number_unittest.cc b/chromium/components/autofill/core/browser/data_model/phone_number_unittest.cc
index 4e680da28bb..29456dcf536 100644
--- a/chromium/components/autofill/core/browser/data_model/phone_number_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/phone_number_unittest.cc
@@ -231,8 +231,8 @@ TEST(PhoneNumberTest, PhoneCombineHelper) {
ASCIIToUTF16("123"))); // Incorrect city code.
EXPECT_TRUE(number4.SetInfo(AutofillType(PHONE_HOME_NUMBER),
ASCIIToUTF16("2345680")));
- EXPECT_FALSE(number4.ParseNumber(profile, "en-US", &parsed_phone));
- EXPECT_EQ(base::string16(), parsed_phone);
+ EXPECT_TRUE(number4.ParseNumber(profile, "en-US", &parsed_phone));
+ EXPECT_EQ(ASCIIToUTF16("1232345680"), parsed_phone);
PhoneNumber::PhoneCombineHelper number5;
EXPECT_TRUE(number5.SetInfo(AutofillType(PHONE_HOME_CITY_AND_NUMBER),
diff --git a/chromium/components/autofill/core/browser/field_filler_unittest.cc b/chromium/components/autofill/core/browser/field_filler_unittest.cc
index fbdf18cf0c7..7ad2e1e19f6 100644
--- a/chromium/components/autofill/core/browser/field_filler_unittest.cc
+++ b/chromium/components/autofill/core/browser/field_filler_unittest.cc
@@ -16,7 +16,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/address_normalizer.h"
#include "components/autofill/core/browser/address_normalizer_impl.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -758,14 +758,14 @@ class AutofillSelectWithStatesTest
std::unique_ptr<Storage>(new NullStorage), "en-US");
// Make sure the normalizer is done initializing its member(s) in
// background task(s).
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
protected:
AddressNormalizer* normalizer() { return normalizer_.get(); }
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<AddressNormalizerImpl> normalizer_;
DISALLOW_COPY_AND_ASSIGN(AutofillSelectWithStatesTest);
diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc
index 0c8baeed8f2..5851f7d6358 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer.cc
@@ -155,21 +155,6 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
if (!imported_credit_card)
return;
- // Check if the imported card is from a network that is currently disallowed,
- // often due to Google Payments not accepting a certain card network. If so,
- // don't offer to upload the card. We can fall back to local save as long as
- // it's a new card instead of an existing local card.
- if (!credit_card_save_manager_->IsUploadEnabledForNetwork(
- imported_credit_card->network())) {
- is_credit_card_upstream_enabled = false;
- AutofillMetrics::LogUploadDisallowedForNetworkMetric(
- imported_credit_card->network());
- if (imported_credit_card_record_type_ ==
- ImportedCreditCardRecordType::LOCAL_CARD) {
- return;
- }
- }
-
// We have a card to save; decide what type of save flow to display.
if (is_credit_card_upstream_enabled) {
// Attempt to offer upload save. Because we pass
@@ -490,6 +475,8 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm(
const FormStructure& form,
bool* has_duplicate_field_type) {
*has_duplicate_field_type = false;
+ has_non_focusable_field_ = false;
+ from_dynamic_change_form_ = false;
CreditCard candidate_credit_card;
@@ -502,14 +489,6 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm(
// information into the field, then skip it.
if (!field->IsFieldFillable() || value.empty())
continue;
- // If the field is non-focusable (hidden) after the user entered information
- // into it, then skip it, unless the experiment to import non-focusable
- // forms is enabled.
- if (!field->is_focusable &&
- !base::FeatureList::IsEnabled(
- features::kAutofillImportNonFocusableCreditCardForms)) {
- continue;
- }
AutofillType field_type = field->Type();
// Field was not identified as a credit card field.
diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h
index 9678400c066..1fd598e0ba2 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.h
+++ b/chromium/components/autofill/core/browser/form_data_importer.h
@@ -168,9 +168,6 @@ class FormDataImporter {
ImportFormData_HiddenCreditCardFormAfterEntered);
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
- ImportFormData_HiddenCreditCardFormAfterEnteredWithExpOff);
- FRIEND_TEST_ALL_PREFIXES(
- FormDataImporterTest,
ImportFormData_ImportCreditCardRecordType_FullServerCard);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
ImportFormData_ImportCreditCardRecordType_LocalCard);
@@ -181,7 +178,10 @@ class FormDataImporter {
ImportFormData_ImportCreditCardRecordType_NewCard);
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
- ImportFormData_ImportCreditCardRecordType_NoCard_ExpiredCard);
+ ImportFormData_ImportCreditCardRecordType_NoCard_ExpiredCard_EditableExpDateOff);
+ FRIEND_TEST_ALL_PREFIXES(
+ FormDataImporterTest,
+ ImportFormData_ImportCreditCardRecordType_NewCard_ExpiredCard_WithExpDateFixFlow);
FRIEND_TEST_ALL_PREFIXES(
FormDataImporterTest,
ImportFormData_ImportCreditCardRecordType_NoCard_InvalidCardNumber);
diff --git a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
index b599a4851aa..703f2ae0d00 100644
--- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -16,13 +16,12 @@
#include "base/command_line.h"
#include "base/feature_list.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
@@ -224,11 +223,8 @@ class FormDataImporterTestBase {
run_loop.Run();
}
- // The temporary directory should be deleted at the end to ensure that
- // files are not used anymore and deletion succeeds.
- base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
std::unique_ptr<PrefService> prefs_;
scoped_refptr<AutofillWebDataService> autofill_database_service_;
scoped_refptr<WebDatabaseService> web_database_;
@@ -245,8 +241,7 @@ class FormDataImporterTest : public FormDataImporterTestBase,
void SetUp() override {
OSCryptMocker::SetUp();
prefs_ = test::PrefServiceForTesting();
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath path = temp_dir_.GetPath().AppendASCII("TestWebDB");
+ base::FilePath path(WebDatabase::kInMemoryPath);
web_database_ =
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
@@ -1437,8 +1432,11 @@ TEST_F(FormDataImporterTest, ImportCreditCard_InvalidCardNumber) {
ASSERT_EQ(0U, personal_data_manager_->GetCreditCards().size());
}
-// Tests that an invalid credit card expiration is not extracted.
+// Tests that an invalid credit card expiration is not extracted when the
+// expiration date fix flow experiment is disabled.
TEST_F(FormDataImporterTest, ImportCreditCard_InvalidExpiryDate) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillUpstreamEditableExpirationDate);
FormData form;
form.url = GURL("https://wwww.foo.com");
@@ -2369,8 +2367,11 @@ TEST_F(FormDataImporterTest,
}
// Ensures that |imported_credit_card_record_type_| is set correctly.
-TEST_F(FormDataImporterTest,
- ImportFormData_ImportCreditCardRecordType_NoCard_ExpiredCard) {
+TEST_F(
+ FormDataImporterTest,
+ ImportFormData_ImportCreditCardRecordType_NoCard_ExpiredCard_EditableExpDateOff) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillUpstreamEditableExpirationDate);
// Simulate a form submission with an expired credit card.
FormData form;
form.url = GURL("https://wwww.foo.com");
@@ -2393,6 +2394,33 @@ TEST_F(FormDataImporterTest,
}
// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(
+ FormDataImporterTest,
+ ImportFormData_ImportCreditCardRecordType_NewCard_ExpiredCard_WithExpDateFixFlow) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillUpstreamEditableExpirationDate);
+ // Simulate a form submission with an expired credit card.
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
+ "1999");
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes();
+ std::unique_ptr<CreditCard> imported_credit_card;
+ EXPECT_TRUE(form_data_importer_->ImportFormData(
+ form_structure, /*profile_autofill_enabled=*/true,
+ /*credit_card_autofill_enabled=*/true,
+ /*should_return_local_card=*/true, &imported_credit_card));
+ ASSERT_TRUE(imported_credit_card);
+ // |imported_credit_card_record_type_| should be NEW_CARD because card was
+ // successfully imported from the form via the expiration date fix flow.
+ ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+ FormDataImporter::ImportedCreditCardRecordType::NEW_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
TEST_F(FormDataImporterTest,
ImportFormData_ImportCreditCardRecordType_NoCard_NoCardOnForm) {
// Simulate a form submission with no credit card on form.
@@ -2797,9 +2825,6 @@ TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
// Tests that a credit card form that is hidden after receiving input still
// imports the card.
TEST_F(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillImportNonFocusableCreditCardForms);
-
FormData form;
form.url = GURL("https://wwww.foo.com");
@@ -2847,48 +2872,6 @@ TEST_F(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
EXPECT_EQ(0, expected_card.Compare(*results[0]));
}
-// Tests that a credit card form that is hidden after receiving input does not
-// import the card when the experiment is off.
-TEST_F(FormDataImporterTest,
- ImportFormData_HiddenCreditCardFormAfterEnteredWithExpOff) {
- scoped_feature_list_.InitAndDisableFeature(
- features::kAutofillImportNonFocusableCreditCardForms);
-
- FormData form;
- form.url = GURL("https://wwww.foo.com");
-
- FormFieldData field;
-
- test::CreateTestFormField("Name on card:", "name_on_card", "Biggie Smalls",
- "text", &field);
- field.is_focusable = false;
- form.fields.push_back(field);
- test::CreateTestFormField("Card Number:", "card_number", "4111111111111111",
- "text", &field);
- field.is_focusable = false;
- form.fields.push_back(field);
- test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
- &field);
- field.is_focusable = false;
- form.fields.push_back(field);
- test::CreateTestFormField("Exp Month:", "exp_month", "01", "text", &field);
- field.is_focusable = false;
- form.fields.push_back(field);
- test::CreateTestFormField("Exp Year:", "exp_year", "2999", "text", &field);
- field.is_focusable = false;
- form.fields.push_back(field);
-
- FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes();
- std::unique_ptr<CreditCard> imported_credit_card;
- // Returns false because the credit card import was failed.
- EXPECT_FALSE(form_data_importer_->ImportFormData(
- form_structure, /*profile_autofill_enabled=*/true,
- /*credit_card_autofill_enabled=*/true,
- /*should_return_local_card=*/false, &imported_credit_card));
- ASSERT_FALSE(imported_credit_card);
-}
-
TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
EnableWalletCardImport();
diff --git a/chromium/components/autofill/core/browser/form_parsing/address_field.cc b/chromium/components/autofill/core/browser/form_parsing/address_field.cc
index cc0a747e59c..37dbe02838f 100644
--- a/chromium/components/autofill/core/browser/form_parsing/address_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/address_field.cc
@@ -44,11 +44,12 @@ const int AddressField::kCityMatchType =
const int AddressField::kStateMatchType =
MATCH_DEFAULT | MATCH_SELECT | MATCH_SEARCH;
-std::unique_ptr<FormField> AddressField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> AddressField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
if (scanner->IsEnd())
return nullptr;
- std::unique_ptr<AddressField> address_field(new AddressField);
+ std::unique_ptr<AddressField> address_field(new AddressField(log_manager));
const AutofillField* const initial_field = scanner->Cursor();
size_t saved_cursor = scanner->SaveCursor();
@@ -61,13 +62,15 @@ std::unique_ptr<FormField> AddressField::Parse(AutofillScanner* scanner) {
while (!scanner->IsEnd()) {
const size_t cursor = scanner->SaveCursor();
// Ignore "Address Lookup" field. http://crbug.com/427622
- if (ParseField(scanner, base::UTF8ToUTF16(kAddressLookupRe), nullptr) ||
- ParseField(scanner, base::UTF8ToUTF16(kAddressNameIgnoredRe),
- nullptr)) {
+ if (ParseField(scanner, base::UTF8ToUTF16(kAddressLookupRe), nullptr,
+ {log_manager, "kAddressLookupRe"}) ||
+ ParseField(scanner, base::UTF8ToUTF16(kAddressNameIgnoredRe), nullptr,
+ {log_manager, "kAddressNameIgnoreRe"})) {
continue;
// Ignore email addresses.
} else if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kEmailRe),
- MATCH_DEFAULT | MATCH_TEXT_AREA, nullptr)) {
+ MATCH_DEFAULT | MATCH_TEXT_AREA, nullptr,
+ {log_manager, "kEmailRe"})) {
continue;
} else if (address_field->ParseAddressLines(scanner) ||
address_field->ParseCityStateZipCode(scanner) ||
@@ -75,8 +78,10 @@ std::unique_ptr<FormField> AddressField::Parse(AutofillScanner* scanner) {
address_field->ParseCompany(scanner)) {
has_trailing_non_labeled_fields = false;
continue;
- } else if (ParseField(scanner, attention_ignored, nullptr) ||
- ParseField(scanner, region_ignored, nullptr)) {
+ } else if (ParseField(scanner, attention_ignored, nullptr,
+ {log_manager, "kAttentionIgnoredRe"}) ||
+ ParseField(scanner, region_ignored, nullptr,
+ {log_manager, "kRegionIgnoredRe"})) {
// We ignore the following:
// * Attention.
// * Province/Region/Other.
@@ -119,8 +124,9 @@ std::unique_ptr<FormField> AddressField::Parse(AutofillScanner* scanner) {
return nullptr;
}
-AddressField::AddressField()
- : company_(nullptr),
+AddressField::AddressField(LogManager* log_manager)
+ : log_manager_(log_manager),
+ company_(nullptr),
address1_(nullptr),
address2_(nullptr),
address3_(nullptr),
@@ -164,7 +170,8 @@ bool AddressField::ParseCompany(AutofillScanner* scanner) {
if (company_)
return false;
- return ParseField(scanner, UTF8ToUTF16(kCompanyRe), &company_);
+ return ParseField(scanner, UTF8ToUTF16(kCompanyRe), &company_,
+ {log_manager_, "kCompanyRe"});
}
bool AddressField::ParseAddressLines(AutofillScanner* scanner) {
@@ -181,13 +188,17 @@ bool AddressField::ParseAddressLines(AutofillScanner* scanner) {
base::string16 pattern = UTF8ToUTF16(kAddressLine1Re);
base::string16 label_pattern = UTF8ToUTF16(kAddressLine1LabelRe);
- if (!ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, &address1_) &&
+ if (!ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, &address1_,
+ {log_manager_, "kAddressLine1Re"}) &&
!ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT,
- &address1_) &&
+ &address1_,
+ {log_manager_, "kAddressLine1LabelRe"}) &&
!ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT | MATCH_TEXT_AREA,
- &street_address_) &&
+ &street_address_,
+ {log_manager_, "kAddressLine1Re"}) &&
!ParseFieldSpecifics(scanner, label_pattern,
- MATCH_LABEL | MATCH_TEXT_AREA, &street_address_))
+ MATCH_LABEL | MATCH_TEXT_AREA, &street_address_,
+ {log_manager_, "kAddressLine1LabelRe"}))
return false;
if (street_address_)
@@ -198,17 +209,19 @@ bool AddressField::ParseAddressLines(AutofillScanner* scanner) {
// discussion on https://codereview.chromium.org/741493003/
pattern = UTF8ToUTF16(kAddressLine2Re);
label_pattern = UTF8ToUTF16(kAddressLine2LabelRe);
- if (!ParseField(scanner, pattern, &address2_) &&
+ if (!ParseField(scanner, pattern, &address2_,
+ {log_manager_, "kAddressLine2Re"}) &&
!ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT,
- &address2_))
+ &address2_, {log_manager_, "kAddressLine2LabelRe"}))
return true;
// Optionally parse address line 3. This uses the same label regexp as
// address 2 above.
pattern = UTF8ToUTF16(kAddressLinesExtraRe);
- if (!ParseField(scanner, pattern, &address3_) &&
+ if (!ParseField(scanner, pattern, &address3_,
+ {log_manager_, "kAddressLinesExtraRe"}) &&
!ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT,
- &address3_))
+ &address3_, {log_manager_, "kAddressLine2LabelRe"}))
return true;
// Try for surplus lines, which we will promptly discard. Some pages have 4
@@ -217,7 +230,8 @@ bool AddressField::ParseAddressLines(AutofillScanner* scanner) {
// Since these are rare, don't bother considering unlabeled lines as extra
// address lines.
pattern = UTF8ToUTF16(kAddressLinesExtraRe);
- while (ParseField(scanner, pattern, nullptr)) {
+ while (ParseField(scanner, pattern, nullptr,
+ {log_manager_, "kAddressLinesExtraRe"})) {
// Consumed a surplus line, try for another.
}
return true;
@@ -230,7 +244,7 @@ bool AddressField::ParseCountry(AutofillScanner* scanner) {
scanner->SaveCursor();
if (ParseFieldSpecifics(scanner, UTF8ToUTF16(kCountryRe),
MATCH_DEFAULT | MATCH_SELECT | MATCH_SEARCH,
- &country_)) {
+ &country_, {log_manager_, "kCountryRe"})) {
return true;
}
@@ -239,7 +253,8 @@ bool AddressField::ParseCountry(AutofillScanner* scanner) {
scanner->Rewind();
return ParseFieldSpecifics(
scanner, UTF8ToUTF16(kCountryLocationRe),
- MATCH_LABEL | MATCH_NAME | MATCH_SELECT | MATCH_SEARCH, &country_);
+ MATCH_LABEL | MATCH_NAME | MATCH_SELECT | MATCH_SEARCH, &country_,
+ {log_manager_, "kCountryLocationRe"});
}
bool AddressField::ParseZipCode(AutofillScanner* scanner) {
@@ -247,13 +262,14 @@ bool AddressField::ParseZipCode(AutofillScanner* scanner) {
return false;
if (!ParseFieldSpecifics(scanner, UTF8ToUTF16(kZipCodeRe), kZipCodeMatchType,
- &zip_)) {
+ &zip_, {log_manager_, "kZipCodeRe"})) {
return false;
}
// Look for a zip+4, whose field name will also often contain
// the substring "zip".
- ParseFieldSpecifics(scanner, UTF8ToUTF16(kZip4Re), kZipCodeMatchType, &zip4_);
+ ParseFieldSpecifics(scanner, UTF8ToUTF16(kZip4Re), kZipCodeMatchType, &zip4_,
+ {log_manager_, "kZip4Re"});
return true;
}
@@ -262,7 +278,7 @@ bool AddressField::ParseCity(AutofillScanner* scanner) {
return false;
return ParseFieldSpecifics(scanner, UTF8ToUTF16(kCityRe), kCityMatchType,
- &city_);
+ &city_, {log_manager_, "kCityRe"});
}
bool AddressField::ParseState(AutofillScanner* scanner) {
@@ -270,24 +286,25 @@ bool AddressField::ParseState(AutofillScanner* scanner) {
return false;
return ParseFieldSpecifics(scanner, UTF8ToUTF16(kStateRe), kStateMatchType,
- &state_);
+ &state_, {log_manager_, "kStateRe"});
}
AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelSeparately(
AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
- AutofillField** match) {
+ AutofillField** match,
+ const RegExLogging& logging) {
if (scanner->IsEnd())
return RESULT_MATCH_NONE;
AutofillField* cur_match = nullptr;
size_t saved_cursor = scanner->SaveCursor();
- bool parsed_name = ParseFieldSpecifics(scanner, pattern,
- match_type & ~MATCH_LABEL, &cur_match);
+ bool parsed_name = ParseFieldSpecifics(
+ scanner, pattern, match_type & ~MATCH_LABEL, &cur_match, logging);
scanner->RewindTo(saved_cursor);
- bool parsed_label = ParseFieldSpecifics(scanner, pattern,
- match_type & ~MATCH_NAME, &cur_match);
+ bool parsed_label = ParseFieldSpecifics(
+ scanner, pattern, match_type & ~MATCH_NAME, &cur_match, logging);
if (parsed_name && parsed_label) {
if (match)
*match = cur_match;
@@ -361,7 +378,8 @@ AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForZipCode(
return RESULT_MATCH_NONE;
ParseNameLabelResult result = ParseNameAndLabelSeparately(
- scanner, UTF8ToUTF16(kZipCodeRe), kZipCodeMatchType, &zip_);
+ scanner, UTF8ToUTF16(kZipCodeRe), kZipCodeMatchType, &zip_,
+ {log_manager_, "kZipCodeRe"});
if (result != RESULT_MATCH_NAME_LABEL || scanner->IsEnd())
return result;
@@ -382,7 +400,7 @@ AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForZipCode(
// Look for a zip+4, whose field name will also often contain
// the substring "zip".
ParseFieldSpecifics(scanner, UTF8ToUTF16(kZip4Re), kZipCodeMatchType,
- &zip4_);
+ &zip4_, {log_manager_, "kZip4Re"});
}
return result;
}
@@ -393,7 +411,8 @@ AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForCity(
return RESULT_MATCH_NONE;
return ParseNameAndLabelSeparately(scanner, UTF8ToUTF16(kCityRe),
- kCityMatchType, &city_);
+ kCityMatchType, &city_,
+ {log_manager_, "kCityRe"});
}
AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForState(
@@ -402,7 +421,8 @@ AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForState(
return RESULT_MATCH_NONE;
return ParseNameAndLabelSeparately(scanner, UTF8ToUTF16(kStateRe),
- kStateMatchType, &state_);
+ kStateMatchType, &state_,
+ {log_manager_, "kStateRe"});
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_parsing/address_field.h b/chromium/components/autofill/core/browser/form_parsing/address_field.h
index b28669df049..cf92d076544 100644
--- a/chromium/components/autofill/core/browser/form_parsing/address_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/address_field.h
@@ -19,10 +19,12 @@ namespace autofill {
class AutofillField;
class AutofillScanner;
+class LogManager;
class AddressField : public FormField {
public:
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
@@ -52,7 +54,7 @@ class AddressField : public FormField {
static const int kCityMatchType;
static const int kStateMatchType;
- AddressField();
+ explicit AddressField(LogManager* log_manager);
bool ParseCompany(AutofillScanner* scanner);
bool ParseAddressLines(AutofillScanner* scanner);
@@ -74,7 +76,8 @@ class AddressField : public FormField {
AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
- AutofillField** match);
+ AutofillField** match,
+ const RegExLogging& logging);
// Run matches on the name and label separately. If the return result is
// RESULT_MATCH_NAME_LABEL, then |scanner| advances and the field is set.
@@ -83,6 +86,7 @@ class AddressField : public FormField {
ParseNameLabelResult ParseNameAndLabelForCity(AutofillScanner* scanner);
ParseNameLabelResult ParseNameAndLabelForState(AutofillScanner* scanner);
+ LogManager* log_manager_;
AutofillField* company_;
AutofillField* address1_;
AutofillField* address2_;
diff --git a/chromium/components/autofill/core/browser/form_parsing/address_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/address_field_unittest.cc
index e7d874b701f..568a2cd0cf9 100644
--- a/chromium/components/autofill/core/browser/form_parsing/address_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/address_field_unittest.cc
@@ -31,7 +31,7 @@ class AddressFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<AddressField> Parse(AutofillScanner* scanner) {
- std::unique_ptr<FormField> field = AddressField::Parse(scanner);
+ std::unique_ptr<FormField> field = AddressField::Parse(scanner, nullptr);
return std::unique_ptr<AddressField>(
static_cast<AddressField*>(field.release()));
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/credit_card_field.cc b/chromium/components/autofill/core/browser/form_parsing/credit_card_field.cc
index a022adb29d0..36e09498599 100644
--- a/chromium/components/autofill/core/browser/form_parsing/credit_card_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/credit_card_field.cc
@@ -80,11 +80,12 @@ bool FieldCanFitDataForFieldType(int max_length, ServerFieldType type) {
} // namespace
// static
-std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
if (scanner->IsEnd())
return nullptr;
- auto credit_card_field = std::make_unique<CreditCardField>();
+ auto credit_card_field = std::make_unique<CreditCardField>(log_manager);
size_t saved_cursor = scanner->SaveCursor();
int nb_unknown_fields = 0;
@@ -93,12 +94,13 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
// the bottom of the loop.
for (int fields = 0; !scanner->IsEnd(); ++fields) {
// Ignore gift card fields.
- if (IsGiftCardField(scanner))
+ if (IsGiftCardField(scanner, log_manager))
break;
if (!credit_card_field->cardholder_) {
if (ParseField(scanner, base::UTF8ToUTF16(kNameOnCardRe),
- &credit_card_field->cardholder_)) {
+ &credit_card_field->cardholder_,
+ {log_manager, "kNameOnCardRe"})) {
continue;
}
@@ -110,7 +112,8 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
// expiration date (which usually appears at the end).
if (fields > 0 && !credit_card_field->expiration_month_ &&
ParseField(scanner, base::UTF8ToUTF16(kNameOnCardContextualRe),
- &credit_card_field->cardholder_)) {
+ &credit_card_field->cardholder_,
+ {log_manager, "kNameOnCardContextualRe"})) {
continue;
}
} else if (!credit_card_field->cardholder_last_) {
@@ -120,7 +123,8 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
// the end).
if (!credit_card_field->expiration_month_ &&
ParseField(scanner, base::UTF8ToUTF16(kLastNameRe),
- &credit_card_field->cardholder_last_)) {
+ &credit_card_field->cardholder_last_,
+ {log_manager, "kLastNameRe"})) {
continue;
}
}
@@ -144,9 +148,9 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
const int kMatchNumTelAndPwd =
MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE | MATCH_PASSWORD;
if (!credit_card_field->verification_ &&
- ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardCvcRe),
- kMatchNumTelAndPwd,
- &credit_card_field->verification_)) {
+ ParseFieldSpecifics(
+ scanner, base::UTF8ToUTF16(kCardCvcRe), kMatchNumTelAndPwd,
+ &credit_card_field->verification_, {log_manager, "kCardCvcRe"})) {
// A couple of sites have multiple verification codes right after another.
// Allow the classification of these codes one by one.
AutofillField* const saved_cvv = credit_card_field->verification_;
@@ -160,7 +164,8 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
scanner->RewindTo(scanner->SaveCursor() - 2);
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardCvcRe),
kMatchNumTelAndPwd,
- &credit_card_field->verification_)) {
+ &credit_card_field->verification_,
+ {log_manager, "kCardCvcRe"})) {
// Reset the current cvv (The verification parse overwrote it).
credit_card_field->verification_ = saved_cvv;
// Put the scanner back to the field right after the current cvv.
@@ -182,7 +187,8 @@ std::unique_ptr<FormField> CreditCardField::Parse(AutofillScanner* scanner) {
// doesn't have bad side effects.
AutofillField* current_number_field;
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kCardNumberRe),
- kMatchNumTelAndPwd, &current_number_field)) {
+ kMatchNumTelAndPwd, &current_number_field,
+ {log_manager, "kCardNumberRe"})) {
// Avoid autofilling any credit card number field having very low or high
// |start_index| on the HTML form.
size_t start_index = 0;
@@ -348,25 +354,30 @@ bool CreditCardField::LikelyCardTypeSelectField(AutofillScanner* scanner) {
}
// static
-bool CreditCardField::IsGiftCardField(AutofillScanner* scanner) {
+bool CreditCardField::IsGiftCardField(AutofillScanner* scanner,
+ LogManager* log_manager) {
if (scanner->IsEnd())
return false;
size_t saved_cursor = scanner->SaveCursor();
- if (ParseField(scanner, base::UTF8ToUTF16(kDebitCardRe), nullptr)) {
+ if (ParseField(scanner, base::UTF8ToUTF16(kDebitCardRe), nullptr,
+ {log_manager, "kDebitCardRe"})) {
scanner->RewindTo(saved_cursor);
return false;
}
- if (ParseField(scanner, base::UTF8ToUTF16(kDebitGiftCardRe), nullptr)) {
+ if (ParseField(scanner, base::UTF8ToUTF16(kDebitGiftCardRe), nullptr,
+ {log_manager, "kDebitGiftCardRe"})) {
scanner->RewindTo(saved_cursor);
return false;
}
- return ParseField(scanner, base::UTF8ToUTF16(kGiftCardRe), nullptr);
+ return ParseField(scanner, base::UTF8ToUTF16(kGiftCardRe), nullptr,
+ {log_manager, "kGiftCardRe"});
}
-CreditCardField::CreditCardField()
- : cardholder_(nullptr),
+CreditCardField::CreditCardField(LogManager* log_manager)
+ : log_manager_(log_manager),
+ cardholder_(nullptr),
cardholder_last_(nullptr),
type_(nullptr),
verification_(nullptr),
@@ -450,18 +461,21 @@ bool CreditCardField::ParseExpirationDate(AutofillScanner* scanner) {
const int kMatchCCType = MATCH_DEFAULT | MATCH_NUMBER | MATCH_TELEPHONE |
MATCH_SELECT | MATCH_SEARCH;
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kExpirationMonthRe),
- kMatchCCType, &expiration_month_) &&
+ kMatchCCType, &expiration_month_,
+ {log_manager_, "kExpirationMonthRe"}) &&
ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kExpirationYearRe),
- kMatchCCType, &expiration_year_)) {
+ kMatchCCType, &expiration_year_,
+ {log_manager_, "kExpirationYearRe"})) {
return true;
}
// If that fails, look for just MM and/or YY(YY).
scanner->RewindTo(month_year_saved_cursor);
if (ParseFieldSpecifics(scanner, base::ASCIIToUTF16("^mm$"), kMatchCCType,
- &expiration_month_) &&
+ &expiration_month_, {log_manager_, "^mm$"}) &&
ParseFieldSpecifics(scanner, base::ASCIIToUTF16("^(yy|yyyy)$"),
- kMatchCCType, &expiration_year_)) {
+ kMatchCCType, &expiration_year_,
+ {log_manager_, "^(yy|yyyy)$"})) {
return true;
}
@@ -476,9 +490,9 @@ bool CreditCardField::ParseExpirationDate(AutofillScanner* scanner) {
return false;
// Try to look for a 2-digit year expiration date.
- if (ParseFieldSpecifics(scanner,
- base::UTF8ToUTF16(kExpirationDate2DigitYearRe),
- kMatchCCType, &expiration_date_)) {
+ if (ParseFieldSpecifics(
+ scanner, base::UTF8ToUTF16(kExpirationDate2DigitYearRe), kMatchCCType,
+ &expiration_date_, {log_manager_, "kExpirationDate2DigitYearRe"})) {
exp_year_type_ = CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
expiration_month_ = nullptr;
return true;
@@ -486,7 +500,8 @@ bool CreditCardField::ParseExpirationDate(AutofillScanner* scanner) {
// Try to look for a generic expiration date field. (2 or 4 digit year)
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kExpirationDateRe),
- kMatchCCType, &expiration_date_)) {
+ kMatchCCType, &expiration_date_,
+ {log_manager_, "kExpirationDateRe"})) {
// If such a field exists, but it cannot fit a 4-digit year expiration
// date, then the likely possibility is that it is a 2-digit year expiration
// date.
@@ -501,9 +516,9 @@ bool CreditCardField::ParseExpirationDate(AutofillScanner* scanner) {
// Try to look for a 4-digit year expiration date.
if (FieldCanFitDataForFieldType(current_field_max_length,
CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR) &&
- ParseFieldSpecifics(scanner,
- base::UTF8ToUTF16(kExpirationDate4DigitYearRe),
- kMatchCCType, &expiration_date_)) {
+ ParseFieldSpecifics(
+ scanner, base::UTF8ToUTF16(kExpirationDate4DigitYearRe), kMatchCCType,
+ &expiration_date_, {log_manager_, "kExpirationDate4DigitYearRe"})) {
expiration_month_ = nullptr;
return true;
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/credit_card_field.h b/chromium/components/autofill/core/browser/form_parsing/credit_card_field.h
index 271bf63d811..9db7aec100f 100644
--- a/chromium/components/autofill/core/browser/form_parsing/credit_card_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/credit_card_field.h
@@ -17,12 +17,14 @@ namespace autofill {
class AutofillField;
class AutofillScanner;
+class LogManager;
class CreditCardField : public FormField {
public:
- CreditCardField();
+ explicit CreditCardField(LogManager* log_manager);
~CreditCardField() override;
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
@@ -47,7 +49,8 @@ class CreditCardField : public FormField {
// |scanner| advances if this returns true.
// Prepaid debit cards do not count as gift cards, since they can be used like
// a credit card.
- static bool IsGiftCardField(AutofillScanner* scanner);
+ static bool IsGiftCardField(AutofillScanner* scanner,
+ LogManager* log_manager);
// Parses the expiration month/year/date fields. Returns true if it finds
// something new.
@@ -62,6 +65,8 @@ class CreditCardField : public FormField {
// It can be either a date or both the month and the year.
bool HasExpiration() const;
+ LogManager* log_manager_; // Optional.
+
AutofillField* cardholder_; // Optional.
// Occasionally pages have separate fields for the cardholder's first and
diff --git a/chromium/components/autofill/core/browser/form_parsing/credit_card_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/credit_card_field_unittest.cc
index 336599888c2..bb3a00be07f 100644
--- a/chromium/components/autofill/core/browser/form_parsing/credit_card_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/credit_card_field_unittest.cc
@@ -33,7 +33,8 @@ class CreditCardFieldTestBase {
// |field_|.
void Parse() {
AutofillScanner scanner(list_);
- std::unique_ptr<FormField> field = CreditCardField::Parse(&scanner);
+ std::unique_ptr<FormField> field =
+ CreditCardField::Parse(&scanner, nullptr);
field_ = std::unique_ptr<CreditCardField>(
static_cast<CreditCardField*>(field.release()));
}
@@ -43,7 +44,7 @@ class CreditCardFieldTestBase {
AutofillScanner scanner(list_);
while (!scanner.IsEnd()) {
- field = CreditCardField::Parse(&scanner);
+ field = CreditCardField::Parse(&scanner, nullptr);
field_ = std::unique_ptr<CreditCardField>(
static_cast<CreditCardField*>(field.release()));
if (field_ == nullptr) {
diff --git a/chromium/components/autofill/core/browser/form_parsing/email_field.cc b/chromium/components/autofill/core/browser/form_parsing/email_field.cc
index 5ab26472b2c..f14ed87c2ba 100644
--- a/chromium/components/autofill/core/browser/form_parsing/email_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/email_field.cc
@@ -11,10 +11,12 @@
namespace autofill {
// static
-std::unique_ptr<FormField> EmailField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> EmailField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
AutofillField* field;
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kEmailRe),
- MATCH_DEFAULT | MATCH_EMAIL, &field)) {
+ MATCH_DEFAULT | MATCH_EMAIL, &field,
+ {log_manager, "kEmailRe"})) {
return std::make_unique<EmailField>(field);
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/email_field.h b/chromium/components/autofill/core/browser/form_parsing/email_field.h
index 0716e7f99b9..4c521264c09 100644
--- a/chromium/components/autofill/core/browser/form_parsing/email_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/email_field.h
@@ -13,9 +13,12 @@
namespace autofill {
+class LogManager;
+
class EmailField : public FormField {
public:
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
explicit EmailField(const AutofillField* field);
protected:
diff --git a/chromium/components/autofill/core/browser/form_parsing/form_field.cc b/chromium/components/autofill/core/browser/form_parsing/form_field.cc
index f317ef37427..266bd688bfe 100644
--- a/chromium/components/autofill/core/browser/form_parsing/form_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/form_field.cc
@@ -12,10 +12,12 @@
#include <utility>
#include "base/logging.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/autofill_internals_service.h"
#include "components/autofill/core/browser/form_parsing/address_field.h"
#include "components/autofill/core/browser/form_parsing/autofill_scanner.h"
#include "components/autofill/core/browser/form_parsing/credit_card_field.h"
@@ -26,7 +28,10 @@
#include "components/autofill/core/browser/form_parsing/search_field.h"
#include "components/autofill/core/browser/form_parsing/travel_field.h"
#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_internals/log_message.h"
+#include "components/autofill/core/common/autofill_internals/logging_scope.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/autofill_util.h"
@@ -47,7 +52,8 @@ const float FormField::kBaseSearchParserScore = 0.8f;
// static
FieldCandidatesMap FormField::ParseFormFields(
const std::vector<std::unique_ptr<AutofillField>>& fields,
- bool is_form_tag) {
+ bool is_form_tag,
+ LogManager* log_manager) {
// Set up a working copy of the fields to be processed.
std::vector<AutofillField*> processed_fields;
for (const auto& field : fields) {
@@ -67,31 +73,37 @@ FieldCandidatesMap FormField::ParseFormFields(
FieldCandidatesMap field_candidates;
// Email pass.
- ParseFormFieldsPass(EmailField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(EmailField::Parse, processed_fields, &field_candidates,
+ log_manager);
const size_t email_count = field_candidates.size();
// Phone pass.
- ParseFormFieldsPass(PhoneField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(PhoneField::Parse, processed_fields, &field_candidates,
+ log_manager);
// Travel pass.
- ParseFormFieldsPass(TravelField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(TravelField::Parse, processed_fields, &field_candidates,
+ log_manager);
// Address pass.
ParseFormFieldsPass(autofill::AddressField::Parse, processed_fields,
- &field_candidates);
+ &field_candidates, log_manager);
// Credit card pass.
ParseFormFieldsPass(CreditCardField::Parse, processed_fields,
- &field_candidates);
+ &field_candidates, log_manager);
// Price pass.
- ParseFormFieldsPass(PriceField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(PriceField::Parse, processed_fields, &field_candidates,
+ log_manager);
// Name pass.
- ParseFormFieldsPass(NameField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(NameField::Parse, processed_fields, &field_candidates,
+ log_manager);
// Search pass.
- ParseFormFieldsPass(SearchField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(SearchField::Parse, processed_fields, &field_candidates,
+ log_manager);
// Do not autofill a form if there aren't enough fields. Otherwise, it is
// very easy to have false positives. See http://crbug.com/447332
@@ -110,15 +122,17 @@ FieldCandidatesMap FormField::ParseFormFields(
// static
bool FormField::ParseField(AutofillScanner* scanner,
const base::string16& pattern,
- AutofillField** match) {
- return ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, match);
+ AutofillField** match,
+ const RegExLogging& logging) {
+ return ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, match, logging);
}
// static
bool FormField::ParseFieldSpecifics(AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
- AutofillField** match) {
+ AutofillField** match,
+ const RegExLogging& logging) {
if (scanner->IsEnd())
return false;
@@ -127,7 +141,7 @@ bool FormField::ParseFieldSpecifics(AutofillScanner* scanner,
if (!MatchesFormControlType(field->form_control_type, match_type))
return false;
- return MatchAndAdvance(scanner, pattern, match_type, match);
+ return MatchAndAdvance(scanner, pattern, match_type, match, logging);
}
// static
@@ -154,9 +168,10 @@ void FormField::AddClassification(const AutofillField* field,
bool FormField::MatchAndAdvance(AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
- AutofillField** match) {
+ AutofillField** match,
+ const RegExLogging& logging) {
AutofillField* field = scanner->Cursor();
- if (FormField::Match(field, pattern, match_type)) {
+ if (FormField::Match(field, pattern, match_type, logging)) {
if (match)
*match = field;
scanner->Advance();
@@ -169,27 +184,49 @@ bool FormField::MatchAndAdvance(AutofillScanner* scanner,
// static
bool FormField::Match(const AutofillField* field,
const base::string16& pattern,
- int match_type) {
+ int match_type,
+ const RegExLogging& logging) {
+ bool found_match = false;
+ base::StringPiece match_type_string;
+ base::StringPiece16 value;
+ base::string16 match;
+
if ((match_type & FormField::MATCH_LABEL) &&
- MatchesPattern(field->label, pattern)) {
- return true;
+ MatchesPattern(field->label, pattern, &match)) {
+ found_match = true;
+ match_type_string = "Match in label";
+ value = field->label;
+ } else if ((match_type & FormField::MATCH_NAME) &&
+ MatchesPattern(field->parseable_name(), pattern, &match)) {
+ found_match = true;
+ match_type_string = "Match in name";
+ value = field->parseable_name();
}
- if ((match_type & FormField::MATCH_NAME) &&
- MatchesPattern(field->parseable_name(), pattern)) {
- return true;
+ if (found_match && logging.log_manager) {
+ LogBuffer table_rows;
+ table_rows << Tr{} << "Match type:" << match_type_string;
+ table_rows << Tr{} << "RegEx:" << logging.regex_name;
+ table_rows << Tr{} << "Value: " << HighlightValue(value, match);
+ // The matched substring is reported once more as the highlighting is not
+ // particularly copy&paste friendly.
+ table_rows << Tr{} << "Matched substring: " << match;
+ logging.log_manager->Log()
+ << LoggingScope::kParsing << LogMessage::kLocalHeuristicRegExMatched
+ << Tag{"table"} << std::move(table_rows) << CTag{"table"};
}
- return false;
+ return found_match;
}
// static
void FormField::ParseFormFieldsPass(ParseFunction parse,
const std::vector<AutofillField*>& fields,
- FieldCandidatesMap* field_candidates) {
+ FieldCandidatesMap* field_candidates,
+ LogManager* log_manager) {
AutofillScanner scanner(fields);
while (!scanner.IsEnd()) {
- std::unique_ptr<FormField> form_field = parse(&scanner);
+ std::unique_ptr<FormField> form_field = parse(&scanner, log_manager);
if (form_field == nullptr) {
scanner.Advance();
} else {
diff --git a/chromium/components/autofill/core/browser/form_parsing/form_field.h b/chromium/components/autofill/core/browser/form_parsing/form_field.h
index 9ea02ccdb32..ba404c2ab19 100644
--- a/chromium/components/autofill/core/browser/form_parsing/form_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/form_field.h
@@ -18,6 +18,16 @@ namespace autofill {
class AutofillField;
class AutofillScanner;
+class LogManager;
+
+// This helper struct allows passing information into ParseField /
+// ParseFieldSpecifics that can be used to create a log entry in
+// chrome://autofill-internals explaining which regular expressions
+// were matched by local heuristics.
+struct RegExLogging {
+ LogManager* const log_manager = nullptr;
+ const char* regex_name = "";
+};
// Represents a logical form field in a web form. Classes that implement this
// interface can identify themselves as a particular type of form field, e.g.
@@ -31,7 +41,8 @@ class FormField {
// returned FieldCandidatesMap.
static FieldCandidatesMap ParseFormFields(
const std::vector<std::unique_ptr<AutofillField>>& fields,
- bool is_form_tag);
+ bool is_form_tag,
+ LogManager* log_manager = nullptr);
protected:
// A bit-field used for matching specific parts of a field in question.
@@ -74,7 +85,8 @@ class FormField {
// success and fills |match| with a pointer to the field.
static bool ParseField(AutofillScanner* scanner,
const base::string16& pattern,
- AutofillField** match);
+ AutofillField** match,
+ const RegExLogging& logging = {});
// Parses the stream of fields in |scanner| with regular expression |pattern|
// as specified in the |match_type| bit field (see |MatchType|). If |match|
@@ -84,7 +96,8 @@ class FormField {
static bool ParseFieldSpecifics(AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
- AutofillField** match);
+ AutofillField** match,
+ const RegExLogging& logging = {});
// Attempts to parse a field with an empty label. Returns true
// on success and fills |match| with a pointer to the field.
@@ -113,7 +126,8 @@ class FormField {
// Function pointer type for the parsing function that should be passed to the
// ParseFormFieldsPass() helper function.
- typedef std::unique_ptr<FormField> ParseFunction(AutofillScanner* scanner);
+ typedef std::unique_ptr<FormField> ParseFunction(AutofillScanner* scanner,
+ LogManager* log_manager);
// Matches |pattern| to the contents of the field at the head of the
// |scanner|.
@@ -122,13 +136,15 @@ class FormField {
static bool MatchAndAdvance(AutofillScanner* scanner,
const base::string16& pattern,
int match_type,
- AutofillField** match);
+ AutofillField** match,
+ const RegExLogging& logging = {});
// Matches the regular expression |pattern| against the components of |field|
// as specified in the |match_type| bit field (see |MatchType|).
static bool Match(const AutofillField* field,
const base::string16& pattern,
- int match_type);
+ int match_type,
+ const RegExLogging& logging = {});
// Perform a "pass" over the |fields| where each pass uses the supplied
// |parse| method to match content to a given field type.
@@ -138,7 +154,8 @@ class FormField {
// |field_candidates|.
static void ParseFormFieldsPass(ParseFunction parse,
const std::vector<AutofillField*>& fields,
- FieldCandidatesMap* field_candidates);
+ FieldCandidatesMap* field_candidates,
+ LogManager* log_manager = nullptr);
DISALLOW_COPY_AND_ASSIGN(FormField);
};
diff --git a/chromium/components/autofill/core/browser/form_parsing/name_field.cc b/chromium/components/autofill/core/browser/form_parsing/name_field.cc
index d542d9bf973..6cba9662782 100644
--- a/chromium/components/autofill/core/browser/form_parsing/name_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/name_field.cc
@@ -21,7 +21,8 @@ namespace {
// A form field that can parse a full name field.
class FullNameField : public NameField {
public:
- static std::unique_ptr<FullNameField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FullNameField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
explicit FullNameField(AutofillField* field);
protected:
@@ -37,10 +38,13 @@ class FullNameField : public NameField {
class FirstLastNameField : public NameField {
public:
static std::unique_ptr<FirstLastNameField> ParseSpecificName(
- AutofillScanner* scanner);
+ AutofillScanner* scanner,
+ LogManager* log_manager);
static std::unique_ptr<FirstLastNameField> ParseComponentNames(
- AutofillScanner* scanner);
- static std::unique_ptr<FirstLastNameField> Parse(AutofillScanner* scanner);
+ AutofillScanner* scanner,
+ LogManager* log_manager);
+ static std::unique_ptr<FirstLastNameField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
@@ -59,14 +63,16 @@ class FirstLastNameField : public NameField {
} // namespace
// static
-std::unique_ptr<FormField> NameField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> NameField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
if (scanner->IsEnd())
return nullptr;
// Try FirstLastNameField first since it's more specific.
- std::unique_ptr<FormField> field = FirstLastNameField::Parse(scanner);
+ std::unique_ptr<FormField> field =
+ FirstLastNameField::Parse(scanner, log_manager);
if (!field)
- field = FullNameField::Parse(scanner);
+ field = FullNameField::Parse(scanner, log_manager);
return field;
}
@@ -75,11 +81,12 @@ void NameField::AddClassifications(FieldCandidatesMap* field_candidates) const {
}
// static
-std::unique_ptr<FullNameField> FullNameField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FullNameField> FullNameField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
// Exclude e.g. "username" or "nickname" fields.
scanner->SaveCursor();
- bool should_ignore =
- ParseField(scanner, UTF8ToUTF16(kNameIgnoredRe), nullptr);
+ bool should_ignore = ParseField(scanner, UTF8ToUTF16(kNameIgnoredRe), nullptr,
+ {log_manager, "kNameIgnoredRe"});
scanner->Rewind();
if (should_ignore)
return nullptr;
@@ -88,7 +95,8 @@ std::unique_ptr<FullNameField> FullNameField::Parse(AutofillScanner* scanner) {
// for example, Travelocity_Edit travel profile.html contains a field
// "Travel Profile Name".
AutofillField* field = nullptr;
- if (ParseField(scanner, UTF8ToUTF16(kNameRe), &field))
+ if (ParseField(scanner, UTF8ToUTF16(kNameRe), &field,
+ {log_manager, "kNameRe"}))
return std::make_unique<FullNameField>(field);
return nullptr;
@@ -102,14 +110,16 @@ void FullNameField::AddClassifications(
FullNameField::FullNameField(AutofillField* field) : field_(field) {}
std::unique_ptr<FirstLastNameField> FirstLastNameField::ParseSpecificName(
- AutofillScanner* scanner) {
+ AutofillScanner* scanner,
+ LogManager* log_manager) {
// Some pages (e.g. Overstock_comBilling.html, SmithsonianCheckout.html)
// have the label "Name" followed by two or three text fields.
std::unique_ptr<FirstLastNameField> v(new FirstLastNameField);
scanner->SaveCursor();
AutofillField* next = nullptr;
- if (ParseField(scanner, UTF8ToUTF16(kNameSpecificRe), &v->first_name_) &&
+ if (ParseField(scanner, UTF8ToUTF16(kNameSpecificRe), &v->first_name_,
+ {log_manager, "kNameSpecificRe"}) &&
ParseEmptyLabel(scanner, &next)) {
if (ParseEmptyLabel(scanner, &v->last_name_)) {
// There are three name fields; assume that the middle one is a
@@ -129,7 +139,8 @@ std::unique_ptr<FirstLastNameField> FirstLastNameField::ParseSpecificName(
// static
std::unique_ptr<FirstLastNameField> FirstLastNameField::ParseComponentNames(
- AutofillScanner* scanner) {
+ AutofillScanner* scanner,
+ LogManager* log_manager) {
std::unique_ptr<FirstLastNameField> v(new FirstLastNameField);
scanner->SaveCursor();
@@ -148,12 +159,13 @@ std::unique_ptr<FirstLastNameField> FirstLastNameField::ParseComponentNames(
// Skip over any unrelated fields, e.g. "username" or "nickname".
if (ParseFieldSpecifics(scanner, UTF8ToUTF16(kNameIgnoredRe),
MATCH_DEFAULT | MATCH_SELECT | MATCH_SEARCH,
- nullptr)) {
+ nullptr, {log_manager, "kNameIgnoredRe"})) {
continue;
}
if (!v->first_name_ &&
- ParseField(scanner, UTF8ToUTF16(kFirstNameRe), &v->first_name_)) {
+ ParseField(scanner, UTF8ToUTF16(kFirstNameRe), &v->first_name_,
+ {log_manager, "kFirstNameRe"})) {
continue;
}
@@ -163,18 +175,21 @@ std::unique_ptr<FirstLastNameField> FirstLastNameField::ParseComponentNames(
// "txtmiddlename"); such a field probably actually represents a
// middle initial.
if (!v->middle_name_ &&
- ParseField(scanner, UTF8ToUTF16(kMiddleInitialRe), &v->middle_name_)) {
+ ParseField(scanner, UTF8ToUTF16(kMiddleInitialRe), &v->middle_name_,
+ {log_manager, "kMiddleInitialRe"})) {
v->middle_initial_ = true;
continue;
}
if (!v->middle_name_ &&
- ParseField(scanner, UTF8ToUTF16(kMiddleNameRe), &v->middle_name_)) {
+ ParseField(scanner, UTF8ToUTF16(kMiddleNameRe), &v->middle_name_,
+ {log_manager, "kMiddleNameRe"})) {
continue;
}
if (!v->last_name_ &&
- ParseField(scanner, UTF8ToUTF16(kLastNameRe), &v->last_name_)) {
+ ParseField(scanner, UTF8ToUTF16(kLastNameRe), &v->last_name_,
+ {log_manager, "kLastNameRe"})) {
continue;
}
@@ -192,10 +207,12 @@ std::unique_ptr<FirstLastNameField> FirstLastNameField::ParseComponentNames(
// static
std::unique_ptr<FirstLastNameField> FirstLastNameField::Parse(
- AutofillScanner* scanner) {
- std::unique_ptr<FirstLastNameField> field = ParseSpecificName(scanner);
+ AutofillScanner* scanner,
+ LogManager* log_manager) {
+ std::unique_ptr<FirstLastNameField> field =
+ ParseSpecificName(scanner, log_manager);
if (!field)
- field = ParseComponentNames(scanner);
+ field = ParseComponentNames(scanner, log_manager);
return field;
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/name_field.h b/chromium/components/autofill/core/browser/form_parsing/name_field.h
index c7e79bb5438..00433ff2ca7 100644
--- a/chromium/components/autofill/core/browser/form_parsing/name_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/name_field.h
@@ -17,11 +17,13 @@
namespace autofill {
class AutofillScanner;
+class LogManager;
// A form field that can parse either a FullNameField or a FirstLastNameField.
class NameField : public FormField {
public:
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
protected:
NameField() {}
diff --git a/chromium/components/autofill/core/browser/form_parsing/name_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/name_field_unittest.cc
index b582da8ab48..a04c74808d1 100644
--- a/chromium/components/autofill/core/browser/form_parsing/name_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/name_field_unittest.cc
@@ -30,7 +30,7 @@ class NameFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<NameField> Parse(AutofillScanner* scanner) {
- std::unique_ptr<FormField> field = NameField::Parse(scanner);
+ std::unique_ptr<FormField> field = NameField::Parse(scanner, nullptr);
return std::unique_ptr<NameField>(static_cast<NameField*>(field.release()));
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/phone_field.cc b/chromium/components/autofill/core/browser/form_parsing/phone_field.cc
index 0dc60c0dc84..691760805de 100644
--- a/chromium/components/autofill/core/browser/form_parsing/phone_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/phone_field.cc
@@ -130,7 +130,8 @@ const PhoneField::Parser PhoneField::kPhoneFieldGrammars[] = {
};
// static
-std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
if (scanner->IsEnd())
return nullptr;
@@ -147,8 +148,10 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
for (; i < base::size(kPhoneFieldGrammars) &&
kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR;
++i) {
- if (!ParsePhoneField(scanner, GetRegExp(kPhoneFieldGrammars[i].regex),
- &parsed_fields[kPhoneFieldGrammars[i].phone_part]))
+ if (!ParsePhoneField(
+ scanner, GetRegExp(kPhoneFieldGrammars[i].regex),
+ &parsed_fields[kPhoneFieldGrammars[i].phone_part],
+ {log_manager, GetRegExpName(kPhoneFieldGrammars[i].regex)}))
break;
if (kPhoneFieldGrammars[i].max_size &&
(!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length ||
@@ -191,9 +194,11 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
// Look for a third text box.
if (!phone_field->parsed_phone_fields_[FIELD_SUFFIX]) {
if (!ParsePhoneField(scanner, kPhoneSuffixRe,
- &phone_field->parsed_phone_fields_[FIELD_SUFFIX])) {
+ &phone_field->parsed_phone_fields_[FIELD_SUFFIX],
+ {log_manager, "kPhoneSuffixRe"})) {
ParsePhoneField(scanner, kPhoneSuffixSeparatorRe,
- &phone_field->parsed_phone_fields_[FIELD_SUFFIX]);
+ &phone_field->parsed_phone_fields_[FIELD_SUFFIX],
+ {log_manager, "kPhoneSuffixSeparatorRe"});
}
}
@@ -201,7 +206,8 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner) {
// The extension is not actually used, so this just eats the field so other
// parsers do not mistaken it for something else.
ParsePhoneField(scanner, kPhoneExtensionRe,
- &phone_field->parsed_phone_fields_[FIELD_EXTENSION]);
+ &phone_field->parsed_phone_fields_[FIELD_EXTENSION],
+ {log_manager, "kPhoneExtensionRe"});
return std::move(phone_field);
}
@@ -285,12 +291,41 @@ std::string PhoneField::GetRegExp(RegexType regex_id) {
}
// static
+const char* PhoneField::GetRegExpName(RegexType regex_id) {
+ switch (regex_id) {
+ case REGEX_COUNTRY:
+ return "kCountryCodeRe";
+ case REGEX_AREA:
+ return "kAreaCodeRe|kAreaCodeNotextRe";
+ case REGEX_AREA_NOTEXT:
+ return "kAreaCodeNotextRe";
+ case REGEX_PHONE:
+ return "kPhoneRe";
+ case REGEX_PREFIX_SEPARATOR:
+ return "kPhonePrefixSeparatorRe";
+ case REGEX_PREFIX:
+ return "kPhonePrefixRe";
+ case REGEX_SUFFIX_SEPARATOR:
+ return "kPhoneSuffixSeparatorRe";
+ case REGEX_SUFFIX:
+ return "kPhoneSuffixRe";
+ case REGEX_EXTENSION:
+ return "kPhoneExtensionRe";
+ default:
+ NOTREACHED();
+ break;
+ }
+ return "";
+}
+
+// static
bool PhoneField::ParsePhoneField(AutofillScanner* scanner,
const std::string& regex,
- AutofillField** field) {
+ AutofillField** field,
+ const RegExLogging& logging) {
return ParseFieldSpecifics(scanner, base::UTF8ToUTF16(regex),
MATCH_DEFAULT | MATCH_TELEPHONE | MATCH_NUMBER,
- field);
+ field, logging);
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_parsing/phone_field.h b/chromium/components/autofill/core/browser/form_parsing/phone_field.h
index 59f3380c558..4d1990b2733 100644
--- a/chromium/components/autofill/core/browser/form_parsing/phone_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/phone_field.h
@@ -21,6 +21,7 @@ namespace autofill {
class AutofillField;
class AutofillScanner;
+class LogManager;
// A phone number in one of the following formats:
// - area code, prefix, suffix
@@ -30,7 +31,8 @@ class PhoneField : public FormField {
public:
~PhoneField() override;
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
@@ -87,10 +89,15 @@ class PhoneField : public FormField {
// Returns the regular expression string corresponding to |regex_id|
static std::string GetRegExp(RegexType regex_id);
+ // Returns the constant name of the regex corresponding to |regex_id|.
+ // This is useful for logging purposes.
+ static const char* GetRegExpName(RegexType regex_id);
+
// Convenient wrapper for ParseFieldSpecifics().
static bool ParsePhoneField(AutofillScanner* scanner,
const std::string& regex,
- AutofillField** field);
+ AutofillField** field,
+ const RegExLogging& logging);
// FIELD_PHONE is always present; holds suffix if prefix is present.
// The rest could be NULL.
diff --git a/chromium/components/autofill/core/browser/form_parsing/phone_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/phone_field_unittest.cc
index cdac7c96c89..45196a1937b 100644
--- a/chromium/components/autofill/core/browser/form_parsing/phone_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/phone_field_unittest.cc
@@ -39,7 +39,7 @@ class PhoneFieldTest : public testing::Test {
protected:
// Downcast for tests.
static std::unique_ptr<PhoneField> Parse(AutofillScanner* scanner) {
- std::unique_ptr<FormField> field = PhoneField::Parse(scanner);
+ std::unique_ptr<FormField> field = PhoneField::Parse(scanner, nullptr);
return std::unique_ptr<PhoneField>(
static_cast<PhoneField*>(field.release()));
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/price_field.cc b/chromium/components/autofill/core/browser/form_parsing/price_field.cc
index 51de7a2f7a9..c0b100d630e 100644
--- a/chromium/components/autofill/core/browser/form_parsing/price_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/price_field.cc
@@ -12,12 +12,13 @@
namespace autofill {
// static
-std::unique_ptr<FormField> PriceField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> PriceField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
AutofillField* field;
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kPriceRe),
MATCH_DEFAULT | MATCH_NUMBER | MATCH_SELECT |
MATCH_TEXT_AREA | MATCH_SEARCH,
- &field)) {
+ &field, {log_manager, kPriceRe})) {
return std::make_unique<PriceField>(field);
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/price_field.h b/chromium/components/autofill/core/browser/form_parsing/price_field.h
index f973be32b8d..512e95bc8a5 100644
--- a/chromium/components/autofill/core/browser/form_parsing/price_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/price_field.h
@@ -15,12 +15,14 @@ namespace autofill {
class AutofillField;
class AutofillScanner;
+class LogManager;
// Price fields are not filled by autofill, but identifying them will help to
// reduce the number of false positives.
class PriceField : public FormField {
public:
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
PriceField(const AutofillField* field);
protected:
diff --git a/chromium/components/autofill/core/browser/form_parsing/price_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/price_field_unittest.cc
index a588b8c3c70..18c4923766b 100644
--- a/chromium/components/autofill/core/browser/form_parsing/price_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/price_field_unittest.cc
@@ -31,7 +31,7 @@ class PriceFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<PriceField> Parse(AutofillScanner* scanner) {
- std::unique_ptr<FormField> field = PriceField::Parse(scanner);
+ std::unique_ptr<FormField> field = PriceField::Parse(scanner, nullptr);
return std::unique_ptr<PriceField>(
static_cast<PriceField*>(field.release()));
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/search_field.cc b/chromium/components/autofill/core/browser/form_parsing/search_field.cc
index 456464f225d..95818bb0e7e 100644
--- a/chromium/components/autofill/core/browser/form_parsing/search_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/search_field.cc
@@ -12,11 +12,12 @@
namespace autofill {
// static
-std::unique_ptr<FormField> SearchField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> SearchField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
AutofillField* field;
if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kSearchTermRe),
MATCH_DEFAULT | MATCH_SEARCH | MATCH_TEXT_AREA,
- &field)) {
+ &field, {log_manager, "kSearchTermRe"})) {
return std::make_unique<SearchField>(field);
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/search_field.h b/chromium/components/autofill/core/browser/form_parsing/search_field.h
index 88044fb0591..04dc074d03d 100644
--- a/chromium/components/autofill/core/browser/form_parsing/search_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/search_field.h
@@ -15,12 +15,14 @@ namespace autofill {
class AutofillField;
class AutofillScanner;
+class LogManager;
// Search fields are not filled by autofill, but identifying them will help
// to reduce the number of false positives.
class SearchField : public FormField {
public:
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
SearchField(const AutofillField* field);
protected:
diff --git a/chromium/components/autofill/core/browser/form_parsing/search_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/search_field_unittest.cc
index 9d394cad8be..112beac0cd0 100644
--- a/chromium/components/autofill/core/browser/form_parsing/search_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/search_field_unittest.cc
@@ -31,7 +31,7 @@ class SearchFieldTest : public testing::Test {
// Downcast for tests.
static std::unique_ptr<SearchField> Parse(AutofillScanner* scanner) {
- std::unique_ptr<FormField> field = SearchField::Parse(scanner);
+ std::unique_ptr<FormField> field = SearchField::Parse(scanner, nullptr);
return std::unique_ptr<SearchField>(
static_cast<SearchField*>(field.release()));
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/travel_field.cc b/chromium/components/autofill/core/browser/form_parsing/travel_field.cc
index ec806f5ee0f..c36e6cfd951 100644
--- a/chromium/components/autofill/core/browser/form_parsing/travel_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/travel_field.cc
@@ -15,20 +15,22 @@ namespace autofill {
TravelField::~TravelField() = default;
// static
-std::unique_ptr<FormField> TravelField::Parse(AutofillScanner* scanner) {
+std::unique_ptr<FormField> TravelField::Parse(AutofillScanner* scanner,
+ LogManager* log_manager) {
if (!scanner || scanner->IsEnd()) {
return nullptr;
}
auto travel_field = std::make_unique<TravelField>();
if (ParseField(scanner, base::UTF8ToUTF16(kPassportRe),
- &travel_field->passport_) ||
+ &travel_field->passport_, {log_manager, "kPassportRe"}) ||
ParseField(scanner, base::UTF8ToUTF16(kTravelOriginRe),
- &travel_field->origin_) ||
+ &travel_field->origin_, {log_manager, "kTravelOriginRe"}) ||
ParseField(scanner, base::UTF8ToUTF16(kTravelDestinationRe),
- &travel_field->destination_) ||
- ParseField(scanner, base::UTF8ToUTF16(kFlightRe),
- &travel_field->flight_)) {
+ &travel_field->destination_,
+ {log_manager, "kTravelDestinationRe"}) ||
+ ParseField(scanner, base::UTF8ToUTF16(kFlightRe), &travel_field->flight_,
+ {log_manager, "kFlightRe"})) {
// If any regex matches, then we found a travel field.
return std::move(travel_field);
}
diff --git a/chromium/components/autofill/core/browser/form_parsing/travel_field.h b/chromium/components/autofill/core/browser/form_parsing/travel_field.h
index 85ab3e0385d..465e5b0ee62 100644
--- a/chromium/components/autofill/core/browser/form_parsing/travel_field.h
+++ b/chromium/components/autofill/core/browser/form_parsing/travel_field.h
@@ -12,11 +12,14 @@
namespace autofill {
+class LogManager;
+
class TravelField : public FormField {
public:
~TravelField() override;
- static std::unique_ptr<FormField> Parse(AutofillScanner* scanner);
+ static std::unique_ptr<FormField> Parse(AutofillScanner* scanner,
+ LogManager* log_manager);
protected:
void AddClassifications(FieldCandidatesMap* field_candidates) const override;
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index 1f4246d90fe..22b536cd140 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -20,6 +20,7 @@
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
@@ -73,8 +74,8 @@ const char kShippingMode[] = "shipping";
const int kCommonNamePrefixRemovalFieldThreshold = 3;
const int kMinCommonNamePrefixLength = 16;
-// Returns true if the scheme given by |url| is one for which autfill is allowed
-// to activate. By default this only returns true for HTTP and HTTPS.
+// Returns true if the scheme given by |url| is one for which autofill is
+// allowed to activate. By default this only returns true for HTTP and HTTPS.
bool HasAllowedScheme(const GURL& url) {
return url.SchemeIsHTTPOrHTTPS() ||
base::FeatureList::IsEnabled(
@@ -585,7 +586,8 @@ FormStructure::FormStructure(const FormData& form)
form_parsed_timestamp_(base::TimeTicks::Now()),
passwords_were_revealed_(false),
password_symbol_vote_(0),
- developer_engagement_metrics_(0) {
+ developer_engagement_metrics_(0),
+ unique_renderer_id_(form.unique_renderer_id) {
// Copy the form fields.
std::map<base::string16, size_t> unique_names;
for (const FormFieldData& field : form.fields) {
@@ -613,7 +615,7 @@ FormStructure::FormStructure(const FormData& form)
FormStructure::~FormStructure() {}
-void FormStructure::DetermineHeuristicTypes() {
+void FormStructure::DetermineHeuristicTypes(LogManager* log_manager) {
const auto determine_heuristic_types_start_time = base::TimeTicks::Now();
// First, try to detect field types based on each field's |autocomplete|
@@ -626,7 +628,7 @@ void FormStructure::DetermineHeuristicTypes() {
// prediction routines.
if (ShouldRunHeuristics()) {
const FieldCandidatesMap field_type_map =
- FormField::ParseFormFields(fields_, is_form_tag_);
+ FormField::ParseFormFields(fields_, is_form_tag_, log_manager);
for (const auto& field : fields_) {
const auto iter = field_type_map.find(field->unique_name());
if (iter != field_type_map.end()) {
@@ -1360,6 +1362,7 @@ FormData FormStructure::ToFormData() const {
data.url = source_url_;
data.action = target_url_;
data.main_frame_origin = main_frame_origin_;
+ data.unique_renderer_id = unique_renderer_id_;
for (size_t i = 0; i < fields_.size(); ++i) {
data.fields.push_back(FormFieldData(*fields_[i]));
@@ -1560,13 +1563,13 @@ void FormStructure::ApplyRationalizationsToFieldAndLog(
}
void FormStructure::RationalizeAddressLineFields(
- SectionedFieldsIndexes& sections_of_address_indexes,
+ SectionedFieldsIndexes* sections_of_address_indexes,
AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) {
// The rationalization happens within sections.
- for (sections_of_address_indexes.Reset();
- !sections_of_address_indexes.IsFinished();
- sections_of_address_indexes.WalkForwardToTheNextSection()) {
- auto current_section = sections_of_address_indexes.CurrentSection();
+ for (sections_of_address_indexes->Reset();
+ !sections_of_address_indexes->IsFinished();
+ sections_of_address_indexes->WalkForwardToTheNextSection()) {
+ auto current_section = sections_of_address_indexes->CurrentSection();
// The rationalization only applies to sections that have 2 or 3 visible
// street address predictions.
@@ -1689,8 +1692,8 @@ bool FormStructure::FieldShouldBeRationalizedToCountry(size_t upper_index) {
}
void FormStructure::RationalizeAddressStateCountry(
- SectionedFieldsIndexes& sections_of_state_indexes,
- SectionedFieldsIndexes& sections_of_country_indexes,
+ SectionedFieldsIndexes* sections_of_state_indexes,
+ SectionedFieldsIndexes* sections_of_country_indexes,
AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) {
// Walk on the sections of state and country indexes simultaneously. If they
// both point to the same section, it means that that section includes both
@@ -1701,24 +1704,24 @@ void FormStructure::RationalizeAddressStateCountry(
// the pointer that points to the earlier section forward. Stop when both
// sections of indexes are processed. (This resembles the merge in the merge
// sort.)
- sections_of_state_indexes.Reset();
- sections_of_country_indexes.Reset();
+ sections_of_state_indexes->Reset();
+ sections_of_country_indexes->Reset();
- while (!sections_of_state_indexes.IsFinished() ||
- !sections_of_country_indexes.IsFinished()) {
+ while (!sections_of_state_indexes->IsFinished() ||
+ !sections_of_country_indexes->IsFinished()) {
auto current_section_of_state_indexes =
- sections_of_state_indexes.CurrentSection();
+ sections_of_state_indexes->CurrentSection();
auto current_section_of_country_indexes =
- sections_of_country_indexes.CurrentSection();
+ sections_of_country_indexes->CurrentSection();
// If there are still sections left with both country and state type, and
// state and country current sections are equal, then that section has both
// state and country. No rationalization needed.
- if (!sections_of_state_indexes.IsFinished() &&
- !sections_of_country_indexes.IsFinished() &&
- fields_[sections_of_state_indexes.CurrentIndex()]->section ==
- fields_[sections_of_country_indexes.CurrentIndex()]->section) {
- sections_of_state_indexes.WalkForwardToTheNextSection();
- sections_of_country_indexes.WalkForwardToTheNextSection();
+ if (!sections_of_state_indexes->IsFinished() &&
+ !sections_of_country_indexes->IsFinished() &&
+ fields_[sections_of_state_indexes->CurrentIndex()]->section ==
+ fields_[sections_of_country_indexes->CurrentIndex()]->section) {
+ sections_of_state_indexes->WalkForwardToTheNextSection();
+ sections_of_country_indexes->WalkForwardToTheNextSection();
continue;
}
@@ -1732,14 +1735,14 @@ void FormStructure::RationalizeAddressStateCountry(
upper_index = current_section_of_state_indexes[0];
lower_index = current_section_of_state_indexes[1];
}
- sections_of_state_indexes.WalkForwardToTheNextSection();
+ sections_of_state_indexes->WalkForwardToTheNextSection();
} else {
// We only rationalize when we have exactly two visible fields of a kind.
if (current_section_of_country_indexes.size() == 2) {
upper_index = current_section_of_country_indexes[0];
lower_index = current_section_of_country_indexes[1];
}
- sections_of_country_indexes.WalkForwardToTheNextSection();
+ sections_of_country_indexes->WalkForwardToTheNextSection();
}
// This is when upper and lower indexes are not changed, meaning that there
@@ -1799,13 +1802,13 @@ void FormStructure::RationalizeRepeatedFields(
}
RationalizeAddressLineFields(
- sectioned_field_indexes_by_type[ADDRESS_HOME_STREET_ADDRESS],
+ &(sectioned_field_indexes_by_type[ADDRESS_HOME_STREET_ADDRESS]),
form_interactions_ukm_logger);
// Since the billing types are mapped to the non-billing ones, no need to
// take care of ADDRESS_BILLING_STATE and .. .
RationalizeAddressStateCountry(
- sectioned_field_indexes_by_type[ADDRESS_HOME_STATE],
- sectioned_field_indexes_by_type[ADDRESS_HOME_COUNTRY],
+ &(sectioned_field_indexes_by_type[ADDRESS_HOME_STATE]),
+ &(sectioned_field_indexes_by_type[ADDRESS_HOME_COUNTRY]),
form_interactions_ukm_logger);
}
@@ -2186,31 +2189,38 @@ void FormStructure::RationalizeTypeRelationships() {
LogBuffer& operator<<(LogBuffer& buffer, const FormStructure& form) {
buffer << Tag{"div"} << Attrib{"class", "form"};
buffer << Tag{"table"};
- buffer << MakeTr2Cells("Form signature:", form.form_signature());
- buffer << MakeTr2Cells("Form name:", form.form_name());
- buffer << MakeTr2Cells("Target URL:", form.target_url());
+ buffer << Tr{} << "Form signature:"
+ << base::StrCat({base::NumberToString(form.form_signature()), " - ",
+ base::NumberToString(
+ HashFormSignature(form.form_signature()))});
+ buffer << Tr{} << "Form name:" << form.form_name();
+ buffer << Tr{} << "Target URL:" << form.target_url();
for (size_t i = 0; i < form.field_count(); ++i) {
buffer << Tag{"tr"};
buffer << Tag{"td"} << "Field " << i << ": " << CTag{};
const AutofillField* field = form.field(i);
buffer << Tag{"td"};
buffer << Tag{"table"};
- buffer << MakeTr2Cells("Signature:", field->GetFieldSignature());
- buffer << MakeTr2Cells("Name:", field->parseable_name());
+ buffer << Tr{} << "Signature:"
+ << base::StrCat(
+ {base::NumberToString(field->GetFieldSignature()), " - ",
+ base::NumberToString(
+ HashFieldSignature(field->GetFieldSignature()))});
+ buffer << Tr{} << "Name:" << field->parseable_name();
auto type = field->Type().ToString();
auto heuristic_type = AutofillType(field->heuristic_type()).ToString();
auto server_type = AutofillType(field->server_type()).ToString();
- buffer << MakeTr2Cells("Type:",
- base::StrCat({type, " (heuristic: ", heuristic_type,
- ", server: ", server_type, ")"}));
- buffer << MakeTr2Cells("Section:", field->section);
+ buffer << Tr{} << "Type:"
+ << base::StrCat({type, " (heuristic: ", heuristic_type,
+ ", server: ", server_type, ")"});
+ buffer << Tr{} << "Section:" << field->section;
constexpr size_t kMaxLabelSize = 100;
const base::string16 truncated_label =
field->label.substr(0, std::min(field->label.length(), kMaxLabelSize));
- buffer << MakeTr2Cells("Label:", truncated_label);
+ buffer << Tr{} << "Label:" << truncated_label;
buffer << CTag{"table"};
buffer << CTag{"td"};
buffer << CTag{"tr"};
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index ad64a76ec55..7a90138c297 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -39,6 +39,7 @@ class TimeTicks;
namespace autofill {
class LogBuffer;
+class LogManager;
// Password attributes (whether a password has special symbols, numeric, etc.)
enum class PasswordAttribute {
@@ -63,7 +64,7 @@ class FormStructure {
// Runs several heuristics against the form fields to determine their possible
// types.
- void DetermineHeuristicTypes();
+ void DetermineHeuristicTypes(LogManager* log_manager = nullptr);
// Encodes the proto |upload| request from this FormStructure.
// In some cases, a |login_form_signature| is included as part of the upload.
@@ -282,12 +283,11 @@ class FormStructure {
const std::pair<PasswordAttribute, bool>& vote) {
password_attributes_vote_ = vote;
}
-#if defined(UNIT_TEST)
+
base::Optional<std::pair<PasswordAttribute, bool>>
- get_password_attributes_vote_for_testing() const {
+ get_password_attributes_vote() const {
return password_attributes_vote_;
}
-#endif
void set_password_length_vote(const size_t noisified_password_length) {
DCHECK(password_attributes_vote_.has_value())
@@ -295,14 +295,15 @@ class FormStructure {
"|password_attributes_vote_| has no value.";
password_length_vote_ = noisified_password_length;
}
-#if defined(UNIT_TEST)
- size_t get_password_length_vote_for_testing() const {
+
+ size_t get_password_length_vote() const {
DCHECK(password_attributes_vote_.has_value())
<< "|password_length_vote_| doesn't make sense if "
"|password_attributes_vote_| has no value.";
return password_length_vote_;
}
+#if defined(UNIT_TEST)
mojom::SubmissionIndicatorEvent get_submission_event_for_testing() const {
return submission_event_;
}
@@ -315,14 +316,12 @@ class FormStructure {
password_symbol_vote_ = noisified_symbol;
}
-#if defined(UNIT_TEST)
- int get_password_symbol_vote_for_testing() {
+ int get_password_symbol_vote() const {
DCHECK(password_attributes_vote_.has_value())
<< "|password_symbol_vote_| doesn't make sense if "
"|password_attributes_vote_| has no value";
return password_symbol_vote_;
}
-#endif
mojom::SubmissionSource submission_source() const {
return submission_source_;
@@ -359,6 +358,8 @@ class FormStructure {
value_from_dynamic_change_form_ = v;
}
+ uint32_t unique_renderer_id() const { return unique_renderer_id_; }
+
private:
friend class AutofillMergeTest;
friend class FormStructureTest;
@@ -454,13 +455,13 @@ class FormStructure {
// Two or three fields predicted as the whole address should be address lines
// 1, 2 and 3 instead.
void RationalizeAddressLineFields(
- SectionedFieldsIndexes& sections_of_address_indexes,
+ SectionedFieldsIndexes* sections_of_address_indexes,
AutofillMetrics::FormInteractionsUkmLogger*);
// Rationalize state and country interdependently.
void RationalizeAddressStateCountry(
- SectionedFieldsIndexes& sections_of_state_indexes,
- SectionedFieldsIndexes& sections_of_country_indexes,
+ SectionedFieldsIndexes* sections_of_state_indexes,
+ SectionedFieldsIndexes* sections_of_country_indexes,
AutofillMetrics::FormInteractionsUkmLogger*);
// Tunes the fields with identical predictions.
@@ -627,6 +628,8 @@ class FormStructure {
bool value_from_dynamic_change_form_ = false;
+ uint32_t unique_renderer_id_;
+
DISALLOW_COPY_AND_ASSIGN(FormStructure);
};
diff --git a/chromium/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc b/chromium/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc
index afcf07ba45c..4f4e36e3357 100644
--- a/chromium/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc
+++ b/chromium/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc
@@ -101,14 +101,14 @@ INSTANTIATE_TEST_SUITE_P(
ParseNumberTestCase{false, "1234", "US"},
// Too long strings should not be parsed.
ParseNumberTestCase{false, GenerateTooLongString(), "US"},
- // Test for string with exactly 7 digits.
- // Still a possible number with unknown("ZZ") deduced region.
- ParseNumberTestCase{true, "17134567", "US", "7134567", "", "1", "ZZ"},
+ // Test for string with exactly 7 digits. It is too short.
+ // Should fail parsing in US.
+ ParseNumberTestCase{false, "17134567", "US"},
// Does not have area code, but still a possible number with
// unknown("ZZ") deduced region.
ParseNumberTestCase{true, "7134567", "US", "7134567", "", "", "ZZ"},
// Valid Canadian toll-free number.
- ParseNumberTestCase{true, "3101234", "US", "3101234", "", "", "CA"},
+ ParseNumberTestCase{true, "3101234", "CA", "3101234", "", "", "ZZ"},
// Test for string with greater than 7 digits but less than 10 digits.
// Should fail parsing in US.
ParseNumberTestCase{false, "123456789", "US"},
@@ -132,8 +132,10 @@ INSTANTIATE_TEST_SUITE_P(
ParseNumberTestCase{false, "1\xC0", "US"},
// Test for string with exactly 10 digits.
// Should give back phone number and city code.
- // This one going to fail because of the incorrect area code.
- ParseNumberTestCase{false, "1234567890", "US"},
+ // This one has an incorrect area code but could still be a possible
+ // number with unknown("ZZ") deducted region.
+ ParseNumberTestCase{true, "1234567890", "US", "1234567890", "", "",
+ "ZZ"},
// This is actually not a valid number because the first number after
// area code is 1. But it's still a possible number, just with deduced
// country set to unknown("ZZ").
@@ -401,8 +403,8 @@ INSTANTIATE_TEST_SUITE_P(
// A US phone with the country code is correctly formatted as an US
// number.
PhoneNumberFormatCase("+1 415-555-5555", "MX", "+1 415-555-5555"),
- // "+52 1 415 555 5555" is a valid number for Mexico,
- PhoneNumberFormatCase("1 415-555-5555", "MX", "+52 1 415 555 5555"),
+ // "+52 415 555 5555" is a valid number for Mexico,
+ PhoneNumberFormatCase("1 415-555-5555", "MX", "+52 415 555 5555"),
// Without a country code, the phone is formatted for the profile's
// country.
PhoneNumberFormatCase("415-555-5555", "MX", "+52 415 555 5555"),
diff --git a/chromium/components/autofill/core/browser/geo/subkey_requester_unittest.cc b/chromium/components/autofill/core/browser/geo/subkey_requester_unittest.cc
index 4ae481a5fa8..cb9673365d9 100644
--- a/chromium/components/autofill/core/browser/geo/subkey_requester_unittest.cc
+++ b/chromium/components/autofill/core/browser/geo/subkey_requester_unittest.cc
@@ -11,7 +11,7 @@
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
@@ -102,7 +102,7 @@ class SubKeyRequesterTest : public testing::Test {
~SubKeyRequesterTest() override {}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<TestSubKeyRequester> requester_;
private:
@@ -157,7 +157,7 @@ TEST_F(SubKeyRequesterTest, StartRequest_RulesNotLoaded_WillNotLoad) {
requester_->StartRegionSubKeysRequest(kLocale, kLanguage, 0, std::move(cb));
// Let the timeout execute.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Since the rules are never loaded and the timeout is 0, the delegate should
// get notified that the subkeys could not be received.
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer.cc b/chromium/components/autofill/core/browser/logging/log_buffer.cc
index 8a07c418d8b..8bbd7a9df7b 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer.cc
+++ b/chromium/components/autofill/core/browser/logging/log_buffer.cc
@@ -6,12 +6,28 @@
#include <string>
+#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
namespace autofill {
namespace {
+bool IsElement(const base::Value& value) {
+ const std::string* type = value.FindStringKey("type");
+ return type && *type == "element";
+}
+
+bool IsTextNode(const base::Value& value) {
+ const std::string* type = value.FindStringKey("type");
+ return type && *type == "text";
+}
+
+bool IsFragment(const base::Value& value) {
+ const std::string* type = value.FindStringKey("type");
+ return type && *type == "fragment";
+}
+
void AppendChildToLastNode(std::vector<base::Value>* buffer,
base::Value&& new_child) {
if (buffer->empty()) {
@@ -20,6 +36,8 @@ void AppendChildToLastNode(std::vector<base::Value>* buffer,
}
base::Value& parent = buffer->back();
+ // Elements and Fragments can have children, but TextNodes cannot.
+ DCHECK(!IsTextNode(parent));
if (auto* children = parent.FindListKey("children")) {
children->GetList().push_back(std::move(new_child));
@@ -31,21 +49,66 @@ void AppendChildToLastNode(std::vector<base::Value>* buffer,
parent.SetKey("children", base::Value(std::move(list)));
}
+// This is an optimization to reduce the number of text nodes in the DOM.
+// Sequences of appended StringPieces are coalesced into one. If many strings
+// are appended, this has quadratic runtime. But the number of strings
+// and the lengths of strings should be relatively small and we reduce the
+// memory consumption of the DOM, which may grow rather large.
+//
+// If the last child of the element in buffer is a text node, append |text| to
+// it and return true (successful coalescing). Otherwise return false.
+bool TryCoalesceString(std::vector<base::Value>* buffer,
+ base::StringPiece text) {
+ if (buffer->empty())
+ return false;
+ base::Value& parent = buffer->back();
+ auto* children = parent.FindListKey("children");
+ if (!children)
+ return false;
+ DCHECK(!children->GetList().empty());
+ auto& last_child = children->GetList().back();
+ if (!IsTextNode(last_child))
+ return false;
+ std::string* old_text = last_child.FindStringKey("value");
+ old_text->append(text.data(), text.size());
+ return true;
+}
+
+base::Value CreateEmptyFragment() {
+ base::Value::DictStorage storage;
+ storage.try_emplace("type", std::make_unique<base::Value>("fragment"));
+ return base::Value(storage);
+}
+
} // namespace
-LogBuffer::LogBuffer() = default;
+LogBuffer::LogBuffer() {
+ buffer_.push_back(CreateEmptyFragment());
+}
+
LogBuffer::LogBuffer(LogBuffer&& other) noexcept = default;
LogBuffer::~LogBuffer() = default;
base::Value LogBuffer::RetrieveResult() {
- if (buffer_.empty())
- return base::Value();
+ // The buffer should always start with a fragment.
+ DCHECK(buffer_.size() >= 1);
// Close not-yet-closed tags.
while (buffer_.size() > 1)
*this << CTag{};
- return std::exchange(buffer_.back(), base::Value());
+ auto* children = buffer_[0].FindListKey("children");
+ if (!children || children->GetList().empty())
+ return base::Value();
+
+ // If the fragment has a single child, return that directly.
+ if (children->GetList().size() == 1) {
+ base::Value result = std::move(children->GetList().back());
+ children->GetList().pop_back();
+ return result;
+ }
+
+ return std::exchange(buffer_.back(), CreateEmptyFragment());
}
LogBuffer& operator<<(LogBuffer& buf, Tag&& tag) {
@@ -53,7 +116,7 @@ LogBuffer& operator<<(LogBuffer& buf, Tag&& tag) {
return buf;
base::Value::DictStorage storage;
- storage.try_emplace("type", std::make_unique<base::Value>("node"));
+ storage.try_emplace("type", std::make_unique<base::Value>("element"));
storage.try_emplace("value",
std::make_unique<base::Value>(std::move(tag.name)));
buf.buffer_.emplace_back(std::move(storage));
@@ -63,8 +126,7 @@ LogBuffer& operator<<(LogBuffer& buf, Tag&& tag) {
LogBuffer& operator<<(LogBuffer& buf, CTag&& tag) {
if (!buf.active())
return buf;
- // Don't close the very first opened tag. It stays and gets returned in the
- // end.
+ // Don't close the fragment. It stays and gets returned in the end.
if (buf.buffer_.size() <= 1)
return buf;
@@ -80,6 +142,7 @@ LogBuffer& operator<<(LogBuffer& buf, Attrib&& attrib) {
return buf;
base::Value& node = buf.buffer_.back();
+ DCHECK(IsElement(node));
if (auto* attributes = node.FindDictKey("attributes")) {
attributes->SetKey(std::move(attrib.name),
@@ -104,6 +167,12 @@ LogBuffer& operator<<(LogBuffer& buf, base::StringPiece text) {
if (!buf.active())
return buf;
+ if (text.empty())
+ return buf;
+
+ if (TryCoalesceString(&buf.buffer_, text))
+ return buf;
+
base::Value::DictStorage storage;
storage.try_emplace("type", std::make_unique<base::Value>("text"));
// This text is not HTML escaped because the rest of the frame work takes care
@@ -125,6 +194,15 @@ LogBuffer& operator<<(LogBuffer& buf, LogBuffer&& buffer) {
base::Value node_to_add(buffer.RetrieveResult());
if (node_to_add.is_none())
return buf;
+
+ if (IsFragment(node_to_add)) {
+ auto* children = node_to_add.FindListKey("children");
+ if (!children)
+ return buf;
+ for (auto& child : children->GetList())
+ AppendChildToLastNode(&buf.buffer_, std::exchange(child, base::Value()));
+ return buf;
+ }
AppendChildToLastNode(&buf.buffer_, std::move(node_to_add));
return buf;
}
@@ -137,4 +215,56 @@ LogBuffer& operator<<(LogBuffer& buf, const GURL& url) {
return buf << url.GetOrigin().spec();
}
+LogTableRowBuffer::LogTableRowBuffer(LogBuffer* parent) : parent_(parent) {
+ *parent_ << Tag{"tr"};
+}
+
+LogTableRowBuffer::LogTableRowBuffer(LogTableRowBuffer&& buffer) noexcept
+ : parent_(buffer.parent_) {
+ // Prevent double closing of the <tr> tag.
+ buffer.parent_ = nullptr;
+}
+
+LogTableRowBuffer::~LogTableRowBuffer() {
+ if (parent_)
+ *parent_ << CTag{};
+}
+
+LogTableRowBuffer operator<<(LogBuffer& buf, Tr&& tr) {
+ return LogTableRowBuffer(&buf);
+}
+
+LogTableRowBuffer&& operator<<(LogTableRowBuffer&& buf, Attrib&& attrib) {
+ *buf.parent_ << std::move(attrib);
+ return std::move(buf);
+}
+
+namespace {
+// Highlights the first |needle| in |haystack| by wrapping it in <b> tags.
+template <typename STRING_TYPE>
+LogBuffer HighlightValueInternal(base::BasicStringPiece<STRING_TYPE> haystack,
+ base::BasicStringPiece<STRING_TYPE> needle) {
+ using StringPieceT = base::BasicStringPiece<STRING_TYPE>;
+ LogBuffer buffer;
+ size_t pos = haystack.find(needle);
+ if (pos == StringPieceT::npos || needle.empty()) {
+ buffer << haystack;
+ return buffer;
+ }
+ buffer << haystack.substr(0, pos);
+ buffer << Tag{"b"} << needle << CTag{"b"};
+ buffer << haystack.substr(pos + needle.size());
+ return buffer;
+}
+} // namespace
+
+LogBuffer HighlightValue(base::StringPiece haystack, base::StringPiece needle) {
+ return HighlightValueInternal(haystack, needle);
+}
+
+LogBuffer HighlightValue(base::StringPiece16 haystack,
+ base::StringPiece16 needle) {
+ return HighlightValueInternal(haystack, needle);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer.h b/chromium/components/autofill/core/browser/logging/log_buffer.h
index c14994b0dfc..2dd9c4c74b4 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer.h
+++ b/chromium/components/autofill/core/browser/logging/log_buffer.h
@@ -14,6 +14,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/values.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
#include "url/gurl.h"
// The desired pattern to generate log messages is to pass a scope, a log
@@ -73,19 +74,9 @@ struct Attrib {
// An <br> HTML tag, note that this does not need to be closed.
struct Br {};
-// A table row containing two cells. This generates
-// <tr><td>%1</td><td>%2</td></tr>
-template <typename T1, typename T2>
-struct Tr2Cells {
- T1 cell1;
- T2 cell2;
-};
-
-// Helper function to create Tr2Cells entries w/o specifying the type names.
-template <typename T1, typename T2>
-Tr2Cells<T1, T2> MakeTr2Cells(T1&& cell1, T2&& cell2) {
- return Tr2Cells<T1, T2>{std::forward<T1>(cell1), std::forward<T2>(cell2)};
-}
+// A table row tag. This is syntactic sugar for logging data into a table.
+// See LogTableRowBuffer below.
+struct Tr {};
// A buffer into which you can stream values. See the top of this header file
// for samples.
@@ -112,13 +103,14 @@ class LogBuffer {
// The stack of values being constructed. Each item is a dictionary with the
// following attributes:
- // - type: 'node' | 'text'
+ // - type: 'element' | 'fragment' | 'text'
// - value: name of tag | text content
// - children (opt): list of child nodes
// - attributes (opt): dictionary of name/value pairs
// The |buffer_| serves as a stack where the last element is being
// constructed. Once it is read (i.e. closed via a CTag), it is popped from
// the stack and attached as a child of the previously second last element.
+ // Only the first element of buffer_ is a 'fragment' and it is never closed.
std::vector<base::Value> buffer_;
bool active_ = true;
@@ -161,12 +153,70 @@ LogBuffer& operator<<(LogBuffer& buf, LogBuffer&& buffer);
// reasons.
LogBuffer& operator<<(LogBuffer& buf, const GURL& url);
-template <typename T1, typename T2>
-LogBuffer& operator<<(LogBuffer& buf, Tr2Cells<T1, T2>&& row) {
- return buf << Tag{"tr"} << Tag{"td"} << std::move(row.cell1) << CTag{}
- << Tag{"td"} << std::move(row.cell2) << CTag{} << CTag{};
+template <typename T>
+LogBuffer& operator<<(LogBuffer& buf,
+ const ::google::protobuf::RepeatedField<T>& values) {
+ buf << "[";
+ for (int i = 0; i < values.size(); ++i) {
+ if (i)
+ buf << ", ";
+ buf << values.Get(i);
+ }
+ buf << "]";
+ return buf;
+}
+
+template <typename T>
+LogBuffer& operator<<(LogBuffer& buf, const std::vector<T>& values) {
+ buf << "[";
+ for (size_t i = 0; i < values.size(); ++i) {
+ if (i)
+ buf << ", ";
+ buf << values.at(i);
+ }
+ buf << "]";
+ return buf;
}
+// This is syntactic sugar for creating table rows in a LogBuffer. Each
+// value streamed into this LogTableRowBuffer is wrapped by a <td> element.
+// The entire row is wrapped by a <tr>.
+//
+// Here is an example:
+// LogBuffer buf;
+// buf << Tr{} << Attrib{"style", "color: red"} << "Foo" << "Bar";
+// This creates:
+// <tr style="color: red"><td>Foo</td><td>Bar</td></tr>.
+class LogTableRowBuffer {
+ public:
+ explicit LogTableRowBuffer(LogBuffer* parent);
+ LogTableRowBuffer(LogTableRowBuffer&& buffer) noexcept;
+ ~LogTableRowBuffer();
+
+ private:
+ template <typename T>
+ friend LogTableRowBuffer&& operator<<(LogTableRowBuffer&& buf, T&& value);
+ friend LogTableRowBuffer&& operator<<(LogTableRowBuffer&& buf,
+ Attrib&& attrib);
+
+ LogBuffer* parent_ = nullptr;
+};
+
+LogTableRowBuffer operator<<(LogBuffer& buf, Tr&& tr);
+
+template <typename T>
+LogTableRowBuffer&& operator<<(LogTableRowBuffer&& buf, T&& value) {
+ *buf.parent_ << Tag{"td"} << std::forward<T>(value) << CTag{};
+ return std::move(buf);
+}
+
+LogTableRowBuffer&& operator<<(LogTableRowBuffer&& buf, Attrib&& attrib);
+
+// Highlights the first |needle| in |haystack| by wrapping it in <b> tags.
+LogBuffer HighlightValue(base::StringPiece haystack, base::StringPiece needle);
+LogBuffer HighlightValue(base::StringPiece16 haystack,
+ base::StringPiece16 needle);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_BUFFER_H_
diff --git a/chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc b/chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc
index 90a518b96a9..3b4b6c94ab6 100644
--- a/chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc
+++ b/chromium/components/autofill/core/browser/logging/log_buffer_unittest.cc
@@ -60,7 +60,7 @@ TEST(LogBuffer, UnclosedTag) {
buffer << Tag{"foo"};
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"type":"node","value":"foo"})", json);
+ EXPECT_EQ(R"({"type":"element","value":"foo"})", json);
}
TEST(LogBuffer, ClosedTag) {
@@ -68,7 +68,7 @@ TEST(LogBuffer, ClosedTag) {
buffer << Tag{"foo"} << CTag{};
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"type":"node","value":"foo"})", json);
+ EXPECT_EQ(R"({"type":"element","value":"foo"})", json);
}
TEST(LogBuffer, NestedTag) {
@@ -76,8 +76,8 @@ TEST(LogBuffer, NestedTag) {
buffer << Tag{"foo"} << Tag{"bar"} << CTag{} << CTag{};
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"children":[{"type":"node","value":"bar"}],)"
- R"("type":"node","value":"foo"})",
+ EXPECT_EQ(R"({"children":[{"type":"element","value":"bar"}],)"
+ R"("type":"element","value":"foo"})",
json);
}
@@ -86,8 +86,8 @@ TEST(LogBuffer, NestedTagClosingTooOften) {
buffer << Tag{"foo"} << Tag{"bar"} << CTag{} << CTag{} << CTag{};
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"children":[{"type":"node","value":"bar"}],)"
- R"("type":"node","value":"foo"})",
+ EXPECT_EQ(R"({"children":[{"type":"element","value":"bar"}],)"
+ R"("type":"element","value":"foo"})",
json);
}
@@ -96,8 +96,8 @@ TEST(LogBuffer, NestedTagClosingNotAtAll) {
buffer << Tag{"foo"} << Tag{"bar"};
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"children":[{"type":"node","value":"bar"}],)"
- R"("type":"node","value":"foo"})",
+ EXPECT_EQ(R"({"children":[{"type":"element","value":"bar"}],)"
+ R"("type":"element","value":"foo"})",
json);
}
@@ -107,10 +107,11 @@ TEST(LogBuffer, NestedTagWithAttributes) {
<< CTag{} << Attrib{"f1", "1"};
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(R"({"attributes":{"f1":"1"},"children":[)"
- R"({"attributes":{"b1":"1","b2":"2"},"type":"node","value":"bar"})"
- R"(],"type":"node","value":"foo"})",
- json);
+ EXPECT_EQ(
+ R"({"attributes":{"f1":"1"},"children":[)"
+ R"({"attributes":{"b1":"1","b2":"2"},"type":"element","value":"bar"})"
+ R"(],"type":"element","value":"foo"})",
+ json);
}
TEST(LogBuffer, DivWithBr) {
@@ -119,8 +120,19 @@ TEST(LogBuffer, DivWithBr) {
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
EXPECT_EQ(R"({"children":[{"type":"text","value":"foo"},)"
- R"({"type":"node","value":"br"},{"type":"text","value":"bar"}],)"
- R"("type":"node","value":"div"})",
+ R"({"type":"element","value":"br"},{"type":"text","value":"bar"}],)"
+ R"("type":"element","value":"div"})",
+ json);
+}
+
+TEST(LogBuffer, CoalesceStrings) {
+ LogBuffer buffer;
+ buffer << Tag{"div"} << "foo"
+ << "bar";
+ std::string json;
+ EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
+ EXPECT_EQ(R"({"children":[{"type":"text","value":"foobar"}],)"
+ R"("type":"element","value":"div"})",
json);
}
@@ -145,21 +157,117 @@ TEST(LogBuffer, CanStreamCustomObjects) {
buffer << o;
std::string json;
EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
- EXPECT_EQ(
- R"({"children":[)" // table
- /**/ R"({"children":[)" // tr
- /****/ R"({"children":[{"type":"text","value":"x"}],)" // td
- /******/ R"("type":"node","value":"td"},)"
- /****/ R"({"children":[{"type":"text","value":"42"}],)" // td
- /******/ R"("type":"node","value":"td"}],)"
- /****/ R"("type":"node","value":"tr"},)" // continuation of tr
- /**/ R"({"children":[)" // tr
- /****/ R"({"children":[{"type":"text","value":"y"}],)"
- /******/ R"("type":"node","value":"td"},)"
- /****/ R"({"children":[{"type":"text","value":"foobar\u003C!--"}],)"
- /******/ R"("type":"node","value":"td"}],)"
- /**/ R"("type":"node","value":"tr"}],"type":"node","value":"table"})",
- json);
+ EXPECT_EQ(R"({"children":[)" // table
+ /**/ R"({"children":[)" // tr
+ /****/ R"({"children":[{"type":"text","value":"x"}],)" // td
+ /******/ R"("type":"element","value":"td"},)"
+ /****/ R"({"children":[{"type":"text","value":"42"}],)" // td
+ /******/ R"("type":"element","value":"td"}],)"
+ /****/ R"("type":"element","value":"tr"},)" // continuation of tr
+ /**/ R"({"children":[)" // tr
+ /****/ R"({"children":[{"type":"text","value":"y"}],)"
+ /******/ R"("type":"element","value":"td"},)"
+ /****/ R"({"children":[{"type":"text","value":"foobar\u003C!--"}],)"
+ /******/ R"("type":"element","value":"td"}],)"
+ /**/ R"("type":"element","value":"tr"}],"type":"element",)"
+ /****/ R"("value":"table"})",
+ json);
+}
+
+TEST(LogBuffer, LogTableRowBuffer) {
+ LogBuffer expected;
+ expected << Tag{"table"};
+ expected << Tag{"tr"} << Attrib{"class", "awesome"} << Tag{"td"} << "Foo"
+ << CTag{"td"} << Tag{"td"} << "Bar" << CTag{"td"} << CTag{"tr"};
+ expected << CTag{"table"};
+ LogBuffer actual;
+ actual << Tag{"table"};
+ actual << Tr{} << Attrib{"class", "awesome"} << "Foo"
+ << "Bar";
+ actual << CTag{"table"};
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
+}
+
+TEST(LogBuffer, CreateFragment) {
+ LogBuffer buffer;
+ buffer << "foo" << Br{} << "bar";
+ std::string json;
+ EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
+ EXPECT_EQ(R"({"children":[{"type":"text","value":"foo"},)"
+ R"({"type":"element","value":"br"},{"type":"text","value":"bar"}],)"
+ R"("type":"fragment"})",
+ json);
+}
+
+TEST(LogBuffer, AppendFragmentByInlining) {
+ LogBuffer tmp_buffer;
+ tmp_buffer << "foo" << Br{} << "bar";
+ LogBuffer buffer;
+ buffer << std::move(tmp_buffer);
+ std::string json;
+ EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
+ EXPECT_EQ(R"({"children":[{"type":"text","value":"foo"},)"
+ R"({"type":"element","value":"br"},{"type":"text","value":"bar"}],)"
+ R"("type":"fragment"})",
+ json);
+}
+
+TEST(LogBuffer, AppendSingleElementBuffer) {
+ LogBuffer tmp_buffer;
+ tmp_buffer << "foo";
+ LogBuffer buffer;
+ buffer << std::move(tmp_buffer);
+ std::string json;
+ EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
+ EXPECT_EQ(R"({"type":"text","value":"foo"})", json);
+}
+
+TEST(LogBuffer, Highlight) {
+ LogBuffer expected;
+ expected << "foo" << Tag{"b"} << "bar" << CTag{"b"} << "baz";
+ LogBuffer actual;
+ actual << HighlightValue("foobarbaz", "bar");
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
+}
+
+TEST(LogBuffer, HighlightAtStart) {
+ LogBuffer expected;
+ expected << Tag{"b"} << "foo" << CTag{"b"} << "barbaz";
+ LogBuffer actual;
+ actual << HighlightValue("foobarbaz", "foo");
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
+}
+
+TEST(LogBuffer, HighlightAtEnd) {
+ LogBuffer expected;
+ expected << "foobar" << Tag{"b"} << "baz" << CTag{"b"};
+ LogBuffer actual;
+ actual << HighlightValue("foobarbaz", "baz");
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
+}
+
+TEST(LogBuffer, HighlightEmpty) {
+ LogBuffer expected;
+ expected << "foobarbaz";
+ LogBuffer actual;
+ actual << HighlightValue("foobarbaz", "");
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
+}
+
+TEST(LogBuffer, HighlightNotFound) {
+ LogBuffer expected;
+ expected << "foobarbaz";
+ LogBuffer actual;
+ actual << HighlightValue("foobarbaz", "notfound");
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
+}
+
+TEST(LogBuffer, HighlightEmptyString) {
+ LogBuffer expected;
+ expected << "";
+ LogBuffer actual;
+ actual << HighlightValue("", "");
+ EXPECT_EQ(expected.RetrieveResult(), actual.RetrieveResult());
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
index c1a0a534140..b969466c133 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/payments/legal_message_line.h"
@@ -92,7 +93,7 @@ bool AutofillSaveCardInfoBarDelegateMobile::LegalMessagesParsedSuccessfully() {
}
bool AutofillSaveCardInfoBarDelegateMobile::IsGooglePayBrandingEnabled() const {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return upload_;
#else
return false;
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc b/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc
deleted file mode 100644
index e6521472b88..00000000000
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc
+++ /dev/null
@@ -1,103 +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 "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/prefs/pref_service.h"
-#include "components/sync/base/data_type_histogram.h"
-#include "components/sync/driver/sync_client.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync/model/sync_error.h"
-#include "components/sync/model/syncable_service.h"
-
-namespace browser_sync {
-
-AutofillWalletDataTypeController::AutofillWalletDataTypeController(
- syncer::ModelType type,
- scoped_refptr<base::SequencedTaskRunner> db_thread,
- const base::RepeatingClosure& dump_stack,
- syncer::SyncService* sync_service,
- syncer::SyncClient* sync_client,
- const PersonalDataManagerProvider& pdm_provider,
- const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
- : AsyncDirectoryTypeController(type,
- dump_stack,
- sync_service,
- sync_client,
- syncer::GROUP_DB,
- std::move(db_thread)),
- pdm_provider_(pdm_provider),
- callback_registered_(false),
- web_data_service_(web_data_service),
- currently_enabled_(IsEnabled()) {
- DCHECK(type == syncer::AUTOFILL_WALLET_METADATA);
- pref_registrar_.Init(sync_client->GetPrefService());
- pref_registrar_.Add(
- autofill::prefs::kAutofillWalletImportEnabled,
- base::BindRepeating(&AutofillWalletDataTypeController::OnUserPrefChanged,
- base::Unretained(this)));
- pref_registrar_.Add(
- autofill::prefs::kAutofillCreditCardEnabled,
- base::BindRepeating(&AutofillWalletDataTypeController::OnUserPrefChanged,
- base::AsWeakPtr(this)));
-}
-
-AutofillWalletDataTypeController::~AutofillWalletDataTypeController() {}
-
-bool AutofillWalletDataTypeController::StartModels() {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(state(), MODEL_STARTING);
-
- if (!IsEnabled())
- return false;
-
- if (!web_data_service_)
- return false;
-
- if (web_data_service_->IsDatabaseLoaded())
- return true;
-
- if (!callback_registered_) {
- web_data_service_->RegisterDBLoadedCallback(
- base::BindRepeating(&AutofillWalletDataTypeController::OnModelLoaded,
- base::AsWeakPtr(this)));
- callback_registered_ = true;
- }
-
- return false;
-}
-
-bool AutofillWalletDataTypeController::ReadyForStart() const {
- DCHECK(CalledOnValidThread());
- return currently_enabled_;
-}
-
-void AutofillWalletDataTypeController::OnUserPrefChanged() {
- DCHECK(CalledOnValidThread());
-
- bool new_enabled = IsEnabled();
- if (currently_enabled_ == new_enabled)
- return; // No change to sync state.
- currently_enabled_ = new_enabled;
-
- sync_service()->ReadyForStartChanged(type());
-}
-
-bool AutofillWalletDataTypeController::IsEnabled() {
- DCHECK(CalledOnValidThread());
-
- // Require the user-visible pref to be enabled to sync Wallet data/metadata.
- return sync_client()->GetPrefService()->GetBoolean(
- autofill::prefs::kAutofillWalletImportEnabled) &&
- sync_client()->GetPrefService()->GetBoolean(
- autofill::prefs::kAutofillCreditCardEnabled);
-}
-
-} // namespace browser_sync
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h b/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h
deleted file mode 100644
index 4412d51f792..00000000000
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h
+++ /dev/null
@@ -1,77 +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 COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/sequenced_task_runner.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/sync/driver/async_directory_type_controller.h"
-
-namespace autofill {
-class AutofillWebDataService;
-class PersonalDataManager;
-} // namespace autofill
-
-namespace syncer {
-class SyncClient;
-class SyncService;
-} // namespace syncer
-
-namespace browser_sync {
-
-// Controls syncing of AUTOFILL_WALLET_METADATA.
-class AutofillWalletDataTypeController
- : public syncer::AsyncDirectoryTypeController {
- public:
- using PersonalDataManagerProvider =
- base::RepeatingCallback<autofill::PersonalDataManager*()>;
-
- // |type| should be AUTOFILL_WALLET_METADATA.
- // |dump_stack| is called when an unrecoverable error occurs.
- AutofillWalletDataTypeController(
- syncer::ModelType type,
- scoped_refptr<base::SequencedTaskRunner> db_thread,
- const base::RepeatingClosure& dump_stack,
- syncer::SyncService* sync_service,
- syncer::SyncClient* sync_client,
- const PersonalDataManagerProvider& pdm_provider,
- const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
- ~AutofillWalletDataTypeController() override;
-
- // AsyncDirectoryTypeController implementation.
- bool StartModels() override;
- bool ReadyForStart() const override;
-
- private:
- // Callback for changes to the autofill pref.
- void OnUserPrefChanged();
-
- // Returns true if the prefs are set such that wallet sync should be enabled.
- bool IsEnabled();
-
- // Callback that allows accessing PersonalDataManager lazily.
- const PersonalDataManagerProvider pdm_provider_;
-
- // Whether the database loaded callback has been registered.
- bool callback_registered_;
-
- // A reference to the AutofillWebDataService for this controller.
- scoped_refptr<autofill::AutofillWebDataService> web_data_service_;
-
- // Stores whether we're currently syncing wallet data. This is the last
- // value computed by IsEnabled.
- bool currently_enabled_;
-
- // Registrar for listening to kAutofillWalletSyncExperimentEnabled status.
- PrefChangeRegistrar pref_registrar_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillWalletDataTypeController);
-};
-
-} // namespace browser_sync
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc b/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc
deleted file mode 100644
index b6cdd6096b1..00000000000
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/testing_pref_service.h"
-#include "components/sync/driver/configure_context.h"
-#include "components/sync/driver/data_type_controller_mock.h"
-#include "components/sync/driver/fake_generic_change_processor.h"
-#include "components/sync/driver/mock_sync_service.h"
-#include "components/sync/driver/sync_client_mock.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync/model/fake_syncable_service.h"
-#include "components/sync/model/sync_error.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace browser_sync {
-
-namespace {
-
-using autofill::AutofillWebDataService;
-using testing::_;
-using testing::Return;
-
-// Fake WebDataService implementation that stubs out the database loading.
-class FakeWebDataService : public AutofillWebDataService {
- public:
- FakeWebDataService(
- const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner)
- : AutofillWebDataService(ui_task_runner, db_task_runner),
- is_database_loaded_(false),
- db_loaded_callback_(base::RepeatingCallback<void(void)>()) {}
-
- // Mark the database as loaded and send out the appropriate notification.
- void LoadDatabase() {
- is_database_loaded_ = true;
-
- if (!db_loaded_callback_.is_null()) {
- db_loaded_callback_.Run();
- // Clear the callback here or the WDS and DTC will have refs to each other
- // and create a memory leak.
- // TODO(crbug.com/941530): Solve this with a OnceCallback. Note that
- // RegisterDBLoadedCallback overrides other functions that still use
- // base::[Repeating]Callbacks, so it would affect non-Autofill code.
- db_loaded_callback_ = base::RepeatingCallback<void(void)>();
- }
- }
-
- bool IsDatabaseLoaded() override { return is_database_loaded_; }
-
- void RegisterDBLoadedCallback(
- const base::RepeatingCallback<void(void)>& callback) override {
- db_loaded_callback_ = callback;
- }
-
- private:
- ~FakeWebDataService() override {}
-
- bool is_database_loaded_;
- base::RepeatingCallback<void(void)> db_loaded_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeWebDataService);
-};
-
-class AutofillWalletDataTypeControllerTest : public testing::Test {
- public:
- AutofillWalletDataTypeControllerTest() : last_type_(syncer::UNSPECIFIED) {
- ON_CALL(sync_service_, GetUserShare()).WillByDefault(Return(&user_share_));
- }
-
- ~AutofillWalletDataTypeControllerTest() override {}
-
- void SetUp() override {
- prefs_.registry()->RegisterBooleanPref(
- autofill::prefs::kAutofillWalletImportEnabled, true);
- prefs_.registry()->RegisterBooleanPref(
- autofill::prefs::kAutofillCreditCardEnabled, true);
-
- ON_CALL(sync_client_, GetPrefService()).WillByDefault(Return(&prefs_));
- ON_CALL(sync_client_, GetSyncableServiceForType(_))
- .WillByDefault(Return(syncable_service_.AsWeakPtr()));
-
- web_data_service_ = base::MakeRefCounted<FakeWebDataService>(
- base::ThreadTaskRunnerHandle::Get(),
- base::ThreadTaskRunnerHandle::Get());
- autofill_wallet_dtc_ = std::make_unique<AutofillWalletDataTypeController>(
- syncer::AUTOFILL_WALLET_METADATA, base::ThreadTaskRunnerHandle::Get(),
- /*dump_stack=*/base::DoNothing(), &sync_service_, &sync_client_,
- AutofillWalletDataTypeController::PersonalDataManagerProvider(),
- web_data_service_);
-
- last_type_ = syncer::UNSPECIFIED;
- last_error_ = syncer::SyncError();
- }
-
- void TearDown() override {
- // Make sure WebDataService is shutdown properly on DB thread before we
- // destroy it.
- // Must be done before we pump the loop.
- syncable_service_.StopSyncing(syncer::AUTOFILL_WALLET_METADATA);
- }
-
- protected:
- void SetStartExpectations() {
- autofill_wallet_dtc_->SetGenericChangeProcessorFactoryForTest(
- std::make_unique<syncer::FakeGenericChangeProcessorFactory>(
- std::make_unique<syncer::FakeGenericChangeProcessor>(
- syncer::AUTOFILL_WALLET_METADATA)));
- }
-
- bool Start() {
- autofill_wallet_dtc_->LoadModels(
- syncer::ConfigureContext(),
- base::BindRepeating(
- &AutofillWalletDataTypeControllerTest::OnLoadFinished,
- base::Unretained(this)));
- base::RunLoop().RunUntilIdle();
- if (autofill_wallet_dtc_->state() !=
- syncer::DataTypeController::MODEL_LOADED) {
- return false;
- }
- autofill_wallet_dtc_->StartAssociating(base::BindRepeating(
- &syncer::StartCallbackMock::Run, base::Unretained(&start_callback_)));
- base::RunLoop().RunUntilIdle();
- return true;
- }
-
- void OnLoadFinished(syncer::ModelType type, const syncer::SyncError& error) {
- last_type_ = type;
- last_error_ = error;
- }
-
- base::test::ScopedTaskEnvironment task_environment_;
- TestingPrefServiceSimple prefs_;
- syncer::UserShare user_share_;
- testing::NiceMock<syncer::MockSyncService> sync_service_;
- syncer::StartCallbackMock start_callback_;
- syncer::FakeSyncableService syncable_service_;
- std::unique_ptr<AutofillWalletDataTypeController> autofill_wallet_dtc_;
- scoped_refptr<FakeWebDataService> web_data_service_;
- testing::NiceMock<syncer::SyncClientMock> sync_client_;
-
- syncer::ModelType last_type_;
- syncer::SyncError last_error_;
-};
-
-TEST_F(AutofillWalletDataTypeControllerTest, StartDatatypeEnabled) {
- SetStartExpectations();
- web_data_service_->LoadDatabase();
- EXPECT_CALL(start_callback_,
- Run(syncer::DataTypeController::OK, testing::_, testing::_));
-
- EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING,
- autofill_wallet_dtc_->state());
- Start();
- EXPECT_FALSE(last_error_.IsSet());
- EXPECT_EQ(syncer::AUTOFILL_WALLET_METADATA, last_type_);
- EXPECT_EQ(syncer::DataTypeController::RUNNING, autofill_wallet_dtc_->state());
-}
-
-TEST_F(AutofillWalletDataTypeControllerTest,
- DatatypeDisabledByWalletImportWhileRunning) {
- SetStartExpectations();
- web_data_service_->LoadDatabase();
- EXPECT_CALL(start_callback_,
- Run(syncer::DataTypeController::OK, testing::_, testing::_));
-
- EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING,
- autofill_wallet_dtc_->state());
- Start();
- EXPECT_EQ(syncer::DataTypeController::RUNNING, autofill_wallet_dtc_->state());
- EXPECT_FALSE(last_error_.IsSet());
- EXPECT_EQ(syncer::AUTOFILL_WALLET_METADATA, last_type_);
-
- EXPECT_CALL(sync_service_,
- ReadyForStartChanged(syncer::AUTOFILL_WALLET_METADATA));
- autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, false);
- autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, true);
- EXPECT_FALSE(autofill_wallet_dtc_->ReadyForStart());
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(AutofillWalletDataTypeControllerTest,
- DatatypeDisabledByCreditCardsWhileRunning) {
- SetStartExpectations();
- web_data_service_->LoadDatabase();
- EXPECT_CALL(start_callback_,
- Run(syncer::DataTypeController::OK, testing::_, testing::_));
-
- EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING,
- autofill_wallet_dtc_->state());
- Start();
- EXPECT_EQ(syncer::DataTypeController::RUNNING, autofill_wallet_dtc_->state());
- EXPECT_FALSE(last_error_.IsSet());
- EXPECT_EQ(syncer::AUTOFILL_WALLET_METADATA, last_type_);
-
- EXPECT_CALL(sync_service_,
- ReadyForStartChanged(syncer::AUTOFILL_WALLET_METADATA));
- autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, true);
- autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, false);
- EXPECT_FALSE(autofill_wallet_dtc_->ReadyForStart());
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(AutofillWalletDataTypeControllerTest,
- DatatypeDisabledByWalletImportAtStartup) {
- SetStartExpectations();
- web_data_service_->LoadDatabase();
- autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, false);
- autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, true);
- EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING,
- autofill_wallet_dtc_->state());
- Start();
- base::RunLoop().RunUntilIdle();
- // OnLoadFinished() should not have been called.
- EXPECT_EQ(syncer::UNSPECIFIED, last_type_);
-}
-
-TEST_F(AutofillWalletDataTypeControllerTest,
- DatatypeDisabledByCreditCardsAtStartup) {
- SetStartExpectations();
- web_data_service_->LoadDatabase();
- autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, true);
- autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, false);
- EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING,
- autofill_wallet_dtc_->state());
- Start();
- base::RunLoop().RunUntilIdle();
- // OnLoadFinished() should not have been called.
- EXPECT_EQ(syncer::UNSPECIFIED, last_type_);
-}
-
-} // namespace
-
-} // namespace browser_sync
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
index c907e80f286..787a9e3428d 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
+++ b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
@@ -72,22 +72,25 @@ void AutofillWalletModelTypeController::Stop(
ModelTypeController::Stop(shutdown_reason, std::move(callback));
}
-bool AutofillWalletModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+AutofillWalletModelTypeController::GetPreconditionState() const {
DCHECK(CalledOnValidThread());
// Not being in a persistent error state implies not being in a web signout
// state.
// TODO(https://crbug.com/819729): Add integration tests for web signout and
// other persistent auth errors.
- return pref_service_->GetBoolean(
- autofill::prefs::kAutofillWalletImportEnabled) &&
- pref_service_->GetBoolean(
- autofill::prefs::kAutofillCreditCardEnabled) &&
- !sync_service_->GetAuthError().IsPersistentError();
+ bool preconditions_met =
+ pref_service_->GetBoolean(
+ autofill::prefs::kAutofillWalletImportEnabled) &&
+ pref_service_->GetBoolean(autofill::prefs::kAutofillCreditCardEnabled) &&
+ !sync_service_->GetAuthError().IsPersistentError();
+ return preconditions_met ? PreconditionState::kPreconditionsMet
+ : PreconditionState::kMustStopAndClearData;
}
void AutofillWalletModelTypeController::OnUserPrefChanged() {
DCHECK(CalledOnValidThread());
- sync_service_->ReadyForStartChanged(type());
+ sync_service_->DataTypePreconditionChanged(type());
}
void AutofillWalletModelTypeController::SubscribeToPrefChanges() {
@@ -105,7 +108,7 @@ void AutofillWalletModelTypeController::SubscribeToPrefChanges() {
void AutofillWalletModelTypeController::OnStateChanged(
syncer::SyncService* sync) {
DCHECK(CalledOnValidThread());
- sync_service_->ReadyForStartChanged(type());
+ sync_service_->DataTypePreconditionChanged(type());
}
} // namespace browser_sync
diff --git a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
index cee6054e828..6cc8addad3b 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
+++ b/chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
@@ -43,7 +43,7 @@ class AutofillWalletModelTypeController : public syncer::ModelTypeController,
// DataTypeController overrides.
void Stop(syncer::ShutdownReason shutdown_reason,
StopCallback callback) override;
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
// syncer::SyncServiceObserver implementation.
void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/chromium/components/autofill/core/browser/payments/card_unmask_delegate.cc b/chromium/components/autofill/core/browser/payments/card_unmask_delegate.cc
index 82d06ecd0ac..367b09d5e55 100644
--- a/chromium/components/autofill/core/browser/payments/card_unmask_delegate.cc
+++ b/chromium/components/autofill/core/browser/payments/card_unmask_delegate.cc
@@ -6,12 +6,12 @@
namespace autofill {
-CardUnmaskDelegate::UnmaskResponse::UnmaskResponse()
+CardUnmaskDelegate::UserProvidedUnmaskDetails::UserProvidedUnmaskDetails()
: should_store_pan(false) {}
-CardUnmaskDelegate::UnmaskResponse::UnmaskResponse(
- const UnmaskResponse& other) = default;
+CardUnmaskDelegate::UserProvidedUnmaskDetails::UserProvidedUnmaskDetails(
+ const UserProvidedUnmaskDetails& other) = default;
-CardUnmaskDelegate::UnmaskResponse::~UnmaskResponse() {}
+CardUnmaskDelegate::UserProvidedUnmaskDetails::~UserProvidedUnmaskDetails() {}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/card_unmask_delegate.h b/chromium/components/autofill/core/browser/payments/card_unmask_delegate.h
index 729e5a34cc7..c28a28be89f 100644
--- a/chromium/components/autofill/core/browser/payments/card_unmask_delegate.h
+++ b/chromium/components/autofill/core/browser/payments/card_unmask_delegate.h
@@ -13,10 +13,10 @@ namespace autofill {
class CardUnmaskDelegate {
public:
- struct UnmaskResponse {
- UnmaskResponse();
- UnmaskResponse(const UnmaskResponse& other);
- ~UnmaskResponse();
+ struct UserProvidedUnmaskDetails {
+ UserProvidedUnmaskDetails();
+ UserProvidedUnmaskDetails(const UserProvidedUnmaskDetails& other);
+ ~UserProvidedUnmaskDetails();
// User input data.
base::string16 cvc;
@@ -29,11 +29,15 @@ class CardUnmaskDelegate {
// State of "copy to this device" checkbox.
bool should_store_pan;
+
+ // User is opting-in for FIDO Authentication for future card unmasking.
+ bool enable_fido_auth = false;
};
// Called when the user has attempted a verification. Prompt is still
// open at this point.
- virtual void OnUnmaskResponse(const UnmaskResponse& response) = 0;
+ virtual void OnUnmaskPromptAccepted(
+ const UserProvidedUnmaskDetails& details) = 0;
// Called when the unmask prompt is closed (e.g., cancelled).
virtual void OnUnmaskPromptClosed() = 0;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc
index ec5281bda95..ab11f3c6a1b 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -33,12 +33,20 @@ namespace autofill {
namespace {
// Timeout to wait for unmask details from Google Payments in milliseconds.
constexpr int64_t kUnmaskDetailsResponseTimeout = 1000;
+// Time to wait between multiple calls to GetUnmaskDetails().
+constexpr int64_t kDelayForGetUnmaskDetails = 3 * 60 * 1000; // 3 min
+
// Used for asynchronously waiting for |event| to be signaled.
bool WaitForEvent(base::WaitableEvent* event) {
event->declare_only_used_while_idle();
return event->TimedWait(
base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeout));
}
+
+// Used with PostTaskWithDelay() to signal event after a timeout.
+void SignalEvent(base::WaitableEvent* event) {
+ event->Signal();
+}
} // namespace
CreditCardAccessManager::CreditCardAccessManager(
@@ -61,7 +69,9 @@ CreditCardAccessManager::CreditCardAccessManager(
form_event_logger_(form_event_logger),
ready_to_start_authentication_(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ can_fetch_unmask_details_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::SIGNALED) {}
CreditCardAccessManager::~CreditCardAccessManager() {}
@@ -104,12 +114,20 @@ std::vector<CreditCard*> CreditCardAccessManager::GetCreditCardsToSuggest() {
bool CreditCardAccessManager::ShouldDisplayGPayLogo() {
for (const CreditCard* credit_card : GetCreditCardsToSuggest()) {
- if (credit_card->record_type() == CreditCard::LOCAL_CARD)
+ if (IsLocalCard(credit_card))
return false;
}
return true;
}
+bool CreditCardAccessManager::ServerCardsAvailable() {
+ for (const CreditCard* credit_card : GetCreditCardsToSuggest()) {
+ if (!IsLocalCard(credit_card))
+ return true;
+ }
+ return false;
+}
+
bool CreditCardAccessManager::DeleteCard(const CreditCard* card) {
// Server cards cannot be deleted from within Chrome.
bool allowed_to_delete = IsLocalCard(card);
@@ -149,12 +167,28 @@ CreditCard* CreditCardAccessManager::GetCreditCard(std::string guid) {
}
void CreditCardAccessManager::PrepareToFetchCreditCard() {
+#if !defined(OS_IOS)
+ // No need to fetch details if there are no server cards.
+ if (!ServerCardsAvailable())
+ return;
+
+ // Do not make an unnecessary preflight call unless signaled.
+ if (!can_fetch_unmask_details_.IsSignaled())
+ return;
+
// Reset in case a late response was ignored.
ready_to_start_authentication_.Reset();
-#if !defined(OS_IOS)
- GetOrCreateFIDOAuthenticator()->IsUserVerifiable(base::BindOnce(
- &CreditCardAccessManager::GetUnmaskDetailsIfUserIsVerifiable,
- weak_ptr_factory_.GetWeakPtr()));
+
+ // If |is_user_verifiable_| is set, then directly call
+ // GetUnmaskDetailsIfUserIsVerifiable(), otherwise fetch value for
+ // |is_user_verifiable_|.
+ if (is_user_verifiable_.has_value()) {
+ GetUnmaskDetailsIfUserIsVerifiable(is_user_verifiable_.value());
+ } else {
+ GetOrCreateFIDOAuthenticator()->IsUserVerifiable(base::BindOnce(
+ &CreditCardAccessManager::GetUnmaskDetailsIfUserIsVerifiable,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
#endif
}
@@ -164,8 +198,9 @@ void CreditCardAccessManager::GetUnmaskDetailsIfUserIsVerifiable(
// If user is verifiable, then make preflight call to payments to fetch unmask
// details, otherwise the only option is to perform CVC Auth, which does not
- // require any.
- if (is_user_verifiable_) {
+ // require any. Do nothing if request is already in progress.
+ if (is_user_verifiable_ && !unmask_details_request_in_progress_) {
+ unmask_details_request_in_progress_ = true;
payments_client_->GetUnmaskDetails(
base::BindOnce(&CreditCardAccessManager::OnDidGetUnmaskDetails,
weak_ptr_factory_.GetWeakPtr()),
@@ -176,6 +211,7 @@ void CreditCardAccessManager::GetUnmaskDetailsIfUserIsVerifiable(
void CreditCardAccessManager::OnDidGetUnmaskDetails(
AutofillClient::PaymentsRpcResult result,
AutofillClient::UnmaskDetails& unmask_details) {
+ unmask_details_request_in_progress_ = false;
unmask_details_.offer_fido_opt_in = unmask_details.offer_fido_opt_in;
unmask_details_.unmask_auth_method = unmask_details.unmask_auth_method;
unmask_details_.fido_request_options =
@@ -183,7 +219,24 @@ void CreditCardAccessManager::OnDidGetUnmaskDetails(
unmask_details_.fido_eligible_card_ids =
unmask_details.fido_eligible_card_ids;
+ // Set delay as fido request timeout if available, otherwise set to default.
+ int delay_ms = kDelayForGetUnmaskDetails;
+ if (unmask_details_.fido_request_options.is_dict()) {
+ const auto* request_timeout =
+ unmask_details_.fido_request_options.FindKeyOfType(
+ "timeout_millis", base::Value::Type::INTEGER);
+ if (request_timeout)
+ delay_ms = request_timeout->GetInt();
+ }
+
+#if !defined(OS_IOS)
+ GetOrCreateFIDOAuthenticator()->SyncUserOptIn(unmask_details);
+#endif
ready_to_start_authentication_.Signal();
+
+ base::PostDelayedTask(
+ FROM_HERE, base::BindOnce(&SignalEvent, &can_fetch_unmask_details_),
+ base::TimeDelta::FromMilliseconds(delay_ms));
}
void CreditCardAccessManager::FetchCreditCard(
@@ -208,8 +261,8 @@ void CreditCardAccessManager::FetchCreditCard(
if (AuthenticationRequiresUnmaskDetails()) {
// Wait for |ready_to_start_authentication_| to be signaled by
// OnDidGetUnmaskDetails() or until timeout before calling Authenticate().
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock()},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(&WaitForEvent, &ready_to_start_authentication_),
base::BindOnce(&CreditCardAccessManager::Authenticate,
weak_ptr_factory_.GetWeakPtr()));
@@ -218,9 +271,23 @@ void CreditCardAccessManager::FetchCreditCard(
}
}
+void CreditCardAccessManager::FIDOAuthOptChange(bool opt_in,
+ base::Value creation_options) {
+#if defined(OS_IOS)
+ return;
+#else
+ if (opt_in) {
+ GetOrCreateFIDOAuthenticator()->Register(std::move(creation_options));
+ } else {
+ GetOrCreateFIDOAuthenticator()->OptOut();
+ }
+#endif
+}
+
void CreditCardAccessManager::Authenticate(bool did_get_unmask_details) {
// Reset now that we have started authentication.
ready_to_start_authentication_.Reset();
+ unmask_details_request_in_progress_ = false;
// Do not use FIDO if card is not listed in unmask details, as each Card must
// be CVC authed at least once per device.
@@ -265,11 +332,30 @@ CreditCardAccessManager::GetOrCreateFIDOAuthenticator() {
#endif
void CreditCardAccessManager::OnCVCAuthenticationComplete(
- bool did_succeed,
- const CreditCard* card,
- const base::string16& cvc) {
+ const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response) {
is_authentication_in_progress_ = false;
- accessor_->OnCreditCardFetched(did_succeed, card, cvc);
+ accessor_->OnCreditCardFetched(response.did_succeed, response.card,
+ response.cvc);
+ can_fetch_unmask_details_.Signal();
+
+ if (!response.did_succeed)
+ return;
+
+#if defined(OS_ANDROID)
+ // Now that unmask flow is complete, on Android, if GetRealPan includes
+ // |creation_options|, completely hand over registration flow to
+ // CreditCardFIDOAuthenticator.
+ if (response.creation_options.has_value()) {
+ DCHECK(response.creation_options->is_dict());
+ GetOrCreateFIDOAuthenticator()->Register(
+ response.creation_options->Clone());
+ }
+#elif !defined(OS_IOS)
+ // CreditCardFIDOAuthenticator does not exist on iOS.
+ // On desktop, prompts dialog to show the authentication offer.
+ if (unmask_details_.offer_fido_opt_in)
+ GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog();
+#endif
}
#if !defined(OS_IOS)
@@ -279,6 +365,7 @@ void CreditCardAccessManager::OnFIDOAuthenticationComplete(
if (did_succeed) {
is_authentication_in_progress_ = false;
accessor_->OnCreditCardFetched(did_succeed, card);
+ can_fetch_unmask_details_.Signal();
} else {
// Fall back to CVC if WebAuthn failed.
// TODO(crbug/949269): Add metrics to log fallback CVC auths.
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h
index 1b8c449e5b7..0307279777c 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -83,9 +83,16 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
void PrepareToFetchCreditCard();
// Calls |accessor->OnCreditCardFetched()| once credit card is fetched.
- void FetchCreditCard(const CreditCard* card,
- base::WeakPtr<Accessor> accessor,
- const base::TimeTicks& timestamp = base::TimeTicks());
+ virtual void FetchCreditCard(
+ const CreditCard* card,
+ base::WeakPtr<Accessor> accessor,
+ const base::TimeTicks& timestamp = base::TimeTicks());
+
+ // If |opt_in| = true, opts the user into using FIDO authentication for card
+ // unmasking. Otherwise, opts the user out. If |creation_options| is set,
+ // WebAuthn registration prompt will be invoked to create a new credential.
+ void FIDOAuthOptChange(bool opt_in,
+ base::Value creation_options = base::Value());
CreditCardCVCAuthenticator* GetOrCreateCVCAuthenticator();
@@ -106,6 +113,9 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
}
#endif
+ // Returns false if all suggested cards are local cards, otherwise true.
+ bool ServerCardsAvailable();
+
// Invoked from CreditCardFIDOAuthenticator::IsUserVerifiable().
// |is_user_verifiable| is set to true only if user has a verifying platform
// authenticator. e.g. Touch/Face ID, Windows Hello, Android fingerprint,
@@ -125,9 +135,8 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// CreditCardCVCAuthenticator::Requester:
void OnCVCAuthenticationComplete(
- bool did_succeed,
- const CreditCard* card = nullptr,
- const base::string16& cvc = base::string16()) override;
+ const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response)
+ override;
#if !defined(OS_IOS)
// CreditCardFIDOAuthenticator::Requester:
@@ -187,6 +196,12 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// Authenticate() is called when signaled.
base::WaitableEvent ready_to_start_authentication_;
+ // Required to avoid any unnecessary preflight calls to Payments servers.
+ // Initial state is signaled. Resets when PrepareToFetchCreditCard() is
+ // called. Signaled after an authentication is complete or after a timeout.
+ // GetUnmaskDetailsIfUserIsVerifiable() is not called unless this is signaled.
+ base::WaitableEvent can_fetch_unmask_details_;
+
// The credit card being accessed.
const CreditCard* card_;
@@ -195,6 +210,10 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// and enabled.
base::Optional<bool> is_user_verifiable_;
+ // True only if currently waiting on unmask details. This avoids making
+ // unnecessary calls to payments.
+ bool unmask_details_request_in_progress_ = false;
+
// The object attempting to access a card.
base::WeakPtr<Accessor> accessor_;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
index 634af6bc8c0..f45ea4e58c5 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -25,10 +25,11 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -60,8 +61,6 @@
#include "components/sync/driver/test_sync_service.h"
#include "components/version_info/channel.h"
#include "net/base/url_util.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -81,6 +80,20 @@ namespace {
const char kTestGUID[] = "00000000-0000-0000-0000-000000000001";
const char kTestNumber[] = "4234567890123456"; // Visa
+#if !defined(OS_IOS)
+// Base64 encoding of "This is a test challenge".
+constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
+// Base64 encoding of "This is a test Credential ID".
+const char kCredentialId[] = "VGhpcyBpcyBhIHRlc3QgQ3JlZGVudGlhbCBJRC4=";
+const char kGooglePaymentsRpid[] = "google.com";
+
+std::string BytesToBase64(const std::vector<uint8_t> bytes) {
+ std::string base64;
+ base::Base64Encode(std::string(bytes.begin(), bytes.end()), &base64);
+ return base64;
+}
+#endif
+
class TestAccessor : public CreditCardAccessManager::Accessor {
public:
TestAccessor() {}
@@ -128,10 +141,9 @@ std::string NextMonth() {
class CreditCardAccessManagerTest : public testing::Test {
public:
CreditCardAccessManagerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
- QUEUED) {}
+ : task_environment_(
+ base::test::TaskEnvironment::MainThreadType::DEFAULT,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
@@ -147,9 +159,6 @@ class CreditCardAccessManagerTest : public testing::Test {
accessor_.reset(new TestAccessor());
autofill_driver_ =
std::make_unique<testing::NiceMock<TestAutofillDriver>>();
- request_context_ = new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get());
- autofill_driver_->SetURLRequestContext(request_context_.get());
payments_client_ = new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(),
@@ -173,8 +182,6 @@ class CreditCardAccessManagerTest : public testing::Test {
personal_data_manager_.SetPrefService(nullptr);
personal_data_manager_.ClearCreditCards();
-
- request_context_ = nullptr;
}
bool IsAuthenticationInProgress() {
@@ -210,18 +217,38 @@ class CreditCardAccessManagerTest : public testing::Test {
// Returns true if full card request was sent from CVC auth.
bool GetRealPanForCVCAuth(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) {
+ const std::string& real_pan,
+ bool fido_opt_in = false) {
payments::FullCardRequest* full_card_request =
GetCVCAuthenticator()->full_card_request_.get();
if (!full_card_request)
return false;
- full_card_request->OnDidGetRealPan(result, real_pan);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+#if !defined(OS_IOS)
+ if (fido_opt_in) {
+ response.fido_creation_options =
+ base::Value(base::Value::Type::DICTIONARY);
+ response.fido_creation_options->SetKey("relying_party_id",
+ base::Value(kGooglePaymentsRpid));
+ response.fido_creation_options->SetKey("challenge",
+ base::Value(kTestChallenge));
+ }
+#endif
+ full_card_request->OnDidGetRealPan(result,
+ response.with_real_pan(real_pan));
return true;
}
#if !defined(OS_IOS)
+ void SetUserOptedIn(bool user_is_opted_in) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ user_is_opted_in);
+ }
+
// Returns true if full card request was sent from FIDO auth.
bool GetRealPanForFIDOAuth(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) {
@@ -231,35 +258,39 @@ class CreditCardAccessManagerTest : public testing::Test {
if (!full_card_request)
return false;
- full_card_request->OnDidGetRealPan(result, real_pan);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ full_card_request->OnDidGetRealPan(result,
+ response.with_real_pan(real_pan));
return true;
}
+ // Mocks an OptChange response from Payments Client.
+ void OptChange(AutofillClient::PaymentsRpcResult result,
+ bool user_is_opted_in,
+ base::Value creation_options = base::Value()) {
+ GetFIDOAuthenticator()->OnDidGetOptChangeResult(
+ result, user_is_opted_in, std::move(creation_options));
+ }
+
TestCreditCardFIDOAuthenticator* GetFIDOAuthenticator() {
return static_cast<TestCreditCardFIDOAuthenticator*>(
credit_card_access_manager_->GetOrCreateFIDOAuthenticator());
}
-
- void OnFIDOUserVerification(bool did_succeed) {
- // TODO(crbug/949269): Currently CreditCardFIDOAuthenticator fails by
- // default. Once implemented, update this function along with
- // TestCreditCardFIDOAuthenticator to mock a user verification gesture.
- }
#endif
void InvokeUnmaskDetailsTimeout() {
credit_card_access_manager_->ready_to_start_authentication_.Signal();
+ credit_card_access_manager_->can_fetch_unmask_details_.Signal();
}
- void WaitForCallbacks() { scoped_task_environment_.RunUntilIdle(); }
+ void WaitForCallbacks() { task_environment_.RunUntilIdle(); }
protected:
std::unique_ptr<TestAccessor> accessor_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
payments::TestPaymentsClient* payments_client_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_;
scoped_refptr<AutofillWebDataService> database_;
TestPersonalDataManager personal_data_manager_;
base::test::ScopedFeatureList scoped_feature_list_;
@@ -426,13 +457,77 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCTryAgainFailure) {
}
#if !defined(OS_IOS)
+// Ensures that FetchCreditCard() returns the full PAN upon a successful
+// WebAuthn verification and response from payments.
+TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) {
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(true);
+ payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId,
+ kGooglePaymentsRpid);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // FIDO Success.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::GetAssertion(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ EXPECT_TRUE(GetRealPanForFIDOAuth(AutofillClient::SUCCESS, kTestNumber));
+ EXPECT_TRUE(accessor_->did_succeed());
+
+ EXPECT_EQ(kCredentialId,
+ BytesToBase64(GetFIDOAuthenticator()->GetCredentialId()));
+ EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+}
+
// Ensures that CVC prompt is invoked after WebAuthn fails.
TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOFailureCVCFallback) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
- GetFIDOAuthenticator()->SetUserOptIn(true);
- payments_client_->AddFidoEligibleCard(card->server_id());
+ SetUserOptedIn(true);
+ payments_client_->AddFidoEligibleCard(card->server_id(), kCredentialId,
+ kGooglePaymentsRpid);
+
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ WaitForCallbacks();
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ WaitForCallbacks();
+
+ // FIDO Failure.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::GetAssertion(GetFIDOAuthenticator(),
+ /*did_succeed=*/false);
+ EXPECT_FALSE(GetRealPanForFIDOAuth(AutofillClient::SUCCESS, kTestNumber));
+ EXPECT_FALSE(accessor_->did_succeed());
+
+ // Followed by a fallback to CVC.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::NONE_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
+ EXPECT_TRUE(accessor_->did_succeed());
+ EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+}
+
+// Ensures WebAuthn call is not made if Request Options is missing a Credential
+// ID, and falls back to CVC.
+TEST_F(CreditCardAccessManagerTest,
+ FetchServerCardBadRequestOptionsCVCFallback) {
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(true);
+ // Don't set Credential ID.
+ payments_client_->AddFidoEligibleCard(card->server_id(), /*credential_id=*/"",
+ kGooglePaymentsRpid);
credit_card_access_manager_->PrepareToFetchCreditCard();
WaitForCallbacks();
@@ -441,7 +536,6 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOFailureCVCFallback) {
WaitForCallbacks();
// FIDO Failure.
- OnFIDOUserVerification(/*did_succeed=*/false);
EXPECT_FALSE(GetRealPanForFIDOAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_FALSE(accessor_->did_succeed());
@@ -457,7 +551,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
CreateServerCard(kTestGUID, kTestNumber);
CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
GetFIDOAuthenticator()->SetUserVerifiable(true);
- GetFIDOAuthenticator()->SetUserOptIn(true);
+ SetUserOptedIn(true);
credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
InvokeUnmaskDetailsTimeout();
@@ -469,6 +563,82 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
}
#endif
+// TODO(crbug.com/991037): Add tests for desktop separately after the
+// WebauthnOfferDelegate functions are implemented since the flows are different
+// on desktop and Android.
+#if defined(OS_ANDROID)
+// Ensures that the WebAuthn enrollment prompt is invoked after user opts in.
+TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentSuccess) {
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/true));
+ WaitForCallbacks();
+
+ // Mock user response and OptChange payments call.
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ GetFIDOAuthenticator()->current_flow());
+ TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::SUCCESS, true);
+
+ EXPECT_EQ(kGooglePaymentsRpid, GetFIDOAuthenticator()->GetRelyingPartyId());
+ EXPECT_EQ(kTestChallenge,
+ BytesToBase64(GetFIDOAuthenticator()->GetChallenge()));
+ EXPECT_TRUE(GetFIDOAuthenticator()->IsUserOptedIn());
+}
+
+// Ensures that the failed user verification disallows enrollment.
+TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentUserVerificationFailure) {
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/true));
+
+ // Mock user response.
+ TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
+ /*did_succeed=*/false);
+
+ EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
+}
+
+// Ensures that enrollment does not happen if the server returns a failure.
+TEST_F(CreditCardAccessManagerTest, FIDOEnrollmentServerFailure) {
+ CreateServerCard(kTestGUID, kTestNumber);
+ CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID);
+ GetFIDOAuthenticator()->SetUserVerifiable(true);
+ SetUserOptedIn(false);
+
+ credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
+ InvokeUnmaskDetailsTimeout();
+ WaitForCallbacks();
+
+ EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber,
+ /*fido_opt_in=*/true));
+
+ // Mock user response and OptChange payments call.
+ TestCreditCardFIDOAuthenticator::MakeCredential(GetFIDOAuthenticator(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::PERMANENT_FAILURE, false);
+
+ EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
+}
+#endif
+
// Ensures that |is_authentication_in_progress_| is set correctly.
TEST_F(CreditCardAccessManagerTest, AuthenticationInProgress) {
CreateServerCard(kTestGUID, kTestNumber);
@@ -483,4 +653,7 @@ TEST_F(CreditCardAccessManagerTest, AuthenticationInProgress) {
EXPECT_FALSE(IsAuthenticationInProgress());
}
+// TODO(crbug/949269): Once metrics are added, create test to ensure that
+// PrepareToFetchCreditCard() is properly rate limited.
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
index 36ea378b2a3..7a021d8d032 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.cc
@@ -11,6 +11,11 @@
namespace autofill {
+CreditCardCVCAuthenticator::CVCAuthenticationResponse::
+ CVCAuthenticationResponse() {}
+CreditCardCVCAuthenticator::CVCAuthenticationResponse::
+ ~CVCAuthenticationResponse() {}
+
CreditCardCVCAuthenticator::CreditCardCVCAuthenticator(AutofillClient* client)
: client_(client) {}
@@ -33,14 +38,22 @@ void CreditCardCVCAuthenticator::Authenticate(
}
void CreditCardCVCAuthenticator::OnFullCardRequestSucceeded(
- const payments::FullCardRequest& /*full_card_request*/,
+ const payments::FullCardRequest& full_card_request,
const CreditCard& card,
const base::string16& cvc) {
- requester_->OnCVCAuthenticationComplete(/*did_succeed=*/true, &card, cvc);
+ requester_->OnCVCAuthenticationComplete(
+ CVCAuthenticationResponse()
+ .with_did_succeed(true)
+ .with_card(&card)
+ .with_cvc(cvc)
+ .with_creation_options(
+ std::move(full_card_request.unmask_response_details()
+ .fido_creation_options)));
}
void CreditCardCVCAuthenticator::OnFullCardRequestFailed() {
- requester_->OnCVCAuthenticationComplete(/*did_succeed=*/false);
+ requester_->OnCVCAuthenticationComplete(
+ CVCAuthenticationResponse().with_did_succeed(false));
}
void CreditCardCVCAuthenticator::ShowUnmaskPrompt(
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
index 398602d6918..05ad5b7f02e 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h
@@ -20,13 +20,38 @@ class CreditCardCVCAuthenticator
: public payments::FullCardRequest::ResultDelegate,
public payments::FullCardRequest::UIDelegate {
public:
+ struct CVCAuthenticationResponse {
+ CVCAuthenticationResponse();
+ ~CVCAuthenticationResponse();
+
+ CVCAuthenticationResponse& with_did_succeed(bool b) {
+ did_succeed = b;
+ return *this;
+ }
+ // Data pointed to by |c| must outlive this object.
+ CVCAuthenticationResponse& with_card(const CreditCard* c) {
+ card = c;
+ return *this;
+ }
+ CVCAuthenticationResponse& with_cvc(const base::string16 s) {
+ cvc = base::string16(s);
+ return *this;
+ }
+ CVCAuthenticationResponse& with_creation_options(
+ base::Optional<base::Value> v) {
+ creation_options = std::move(v);
+ return *this;
+ }
+ bool did_succeed = false;
+ const CreditCard* card = nullptr;
+ base::string16 cvc = base::string16();
+ base::Optional<base::Value> creation_options = base::nullopt;
+ };
class Requester {
public:
virtual ~Requester() {}
virtual void OnCVCAuthenticationComplete(
- bool did_succeed,
- const CreditCard* card = nullptr,
- const base::string16& cvc = base::string16()) = 0;
+ const CVCAuthenticationResponse& response) = 0;
};
explicit CreditCardCVCAuthenticator(AutofillClient* client);
~CreditCardCVCAuthenticator() override;
@@ -39,7 +64,7 @@ class CreditCardCVCAuthenticator
// payments::FullCardRequest::ResultDelegate
void OnFullCardRequestSucceeded(
- const payments::FullCardRequest& /*full_card_request*/,
+ const payments::FullCardRequest& full_card_request,
const CreditCard& card,
const base::string16& cvc) override;
void OnFullCardRequestFailed() override;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
index a53305b589e..58a13a370b8 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -24,9 +24,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -57,8 +58,6 @@
#include "components/sync/driver/test_sync_service.h"
#include "components/version_info/channel.h"
#include "net/base/url_util.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -106,9 +105,6 @@ class CreditCardCVCAuthenticatorTest : public testing::Test {
requester_.reset(new TestAuthenticationRequester());
autofill_driver_ =
std::make_unique<testing::NiceMock<TestAutofillDriver>>();
- request_context_ = new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get());
- autofill_driver_->SetURLRequestContext(request_context_.get());
payments::TestPaymentsClient* payments_client =
new payments::TestPaymentsClient(
@@ -127,8 +123,6 @@ class CreditCardCVCAuthenticatorTest : public testing::Test {
personal_data_manager_.SetPrefService(nullptr);
personal_data_manager_.ClearCreditCards();
-
- request_context_ = nullptr;
}
CreditCard CreateServerCard(std::string guid, std::string number) {
@@ -150,15 +144,16 @@ class CreditCardCVCAuthenticatorTest : public testing::Test {
payments::FullCardRequest* full_card_request =
cvc_authenticator_->full_card_request_.get();
DCHECK(full_card_request);
- full_card_request->OnDidGetRealPan(result, real_pan);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ full_card_request->OnDidGetRealPan(result,
+ response.with_real_pan(real_pan));
}
protected:
std::unique_ptr<TestAuthenticationRequester> requester_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_;
scoped_refptr<AutofillWebDataService> database_;
TestPersonalDataManager personal_data_manager_;
base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
index be40974481b..e6c15670b42 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc
@@ -8,24 +8,64 @@
#include <utility>
#include <vector>
+#include "base/base64.h"
+#include "base/containers/flat_set.h"
#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/signin/public/identity_manager/account_info.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
#include "third_party/blink/public/mojom/webauthn/internal_authenticator.mojom.h"
+#include "url/gurl.h"
namespace autofill {
+namespace {
+// Default timeout for user to respond to WebAuthn prompt.
+constexpr int kWebAuthnTimeoutMs = 3 * 60 * 1000; // 3 minutes
+// Timeout to wait for synchronous version of IsUserVerifiable().
+constexpr int kIsUserVerifiableTimeoutMs = 1000;
+constexpr char kGooglePaymentsRpid[] = "google.com";
+constexpr char kGooglePaymentsRpName[] = "Google Payments";
+
+std::vector<uint8_t> Base64ToBytes(std::string base64) {
+ std::string bytes;
+ bool did_succeed = base::Base64Decode(base::StringPiece(base64), &bytes);
+ if (did_succeed) {
+ return std::vector<uint8_t>(bytes.begin(), bytes.end());
+ }
+ return std::vector<uint8_t>{};
+}
+
+base::Value BytesToBase64(const std::vector<uint8_t> bytes) {
+ std::string base64;
+ base::Base64Encode(std::string(bytes.begin(), bytes.end()), &base64);
+ return base::Value(std::move(base64));
+}
+} // namespace
+
CreditCardFIDOAuthenticator::CreditCardFIDOAuthenticator(AutofillDriver* driver,
AutofillClient* client)
: autofill_driver_(driver),
autofill_client_(client),
- payments_client_(client->GetPaymentsClient()) {}
+ payments_client_(client->GetPaymentsClient()),
+ user_is_verifiable_callback_received_(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {}
CreditCardFIDOAuthenticator::~CreditCardFIDOAuthenticator() {}
+void CreditCardFIDOAuthenticator::ShowWebauthnOfferDialog() {
+ autofill_client_->ShowWebauthnOfferDialog(base::BindRepeating(
+ &CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
void CreditCardFIDOAuthenticator::Authenticate(
const CreditCard* card,
base::WeakPtr<Requester> requester,
@@ -35,7 +75,31 @@ void CreditCardFIDOAuthenticator::Authenticate(
requester_ = requester;
form_parsed_timestamp_ = form_parsed_timestamp;
- requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/false);
+ if (card_ && IsValidRequestOptions(request_options.Clone())) {
+ current_flow_ = AUTHENTICATION_FLOW;
+ GetAssertion(ParseRequestOptions(std::move(request_options)));
+ } else {
+ requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/false);
+ }
+}
+
+void CreditCardFIDOAuthenticator::Register(base::Value creation_options) {
+ // If |creation_options| is set, then must enroll a new credential. Otherwise
+ // directly send request to payments for opting in.
+ if (creation_options.is_dict()) {
+ if (IsValidCreationOptions(creation_options)) {
+ current_flow_ = OPT_IN_WITH_CHALLENGE_FLOW;
+ MakeCredential(ParseCreationOptions(creation_options));
+ }
+ } else {
+ current_flow_ = OPT_IN_WITHOUT_CHALLENGE_FLOW;
+ OptChange(/*opt_in=*/true);
+ }
+}
+
+void CreditCardFIDOAuthenticator::OptOut() {
+ current_flow_ = OPT_OUT_FLOW;
+ OptChange(/*opt_in=*/false);
}
void CreditCardFIDOAuthenticator::IsUserVerifiable(
@@ -43,7 +107,7 @@ void CreditCardFIDOAuthenticator::IsUserVerifiable(
if (base::FeatureList::IsEnabled(
features::kAutofillCreditCardAuthentication)) {
autofill_driver_->ConnectToAuthenticator(
- mojo::MakeRequest(&authenticator_));
+ authenticator_.BindNewPipeAndPassReceiver());
authenticator_->IsUserVerifyingPlatformAuthenticatorAvailable(
std::move(callback));
} else {
@@ -51,9 +115,356 @@ void CreditCardFIDOAuthenticator::IsUserVerifiable(
}
}
+bool CreditCardFIDOAuthenticator::IsUserVerifiable() {
+ if (user_is_verifiable_.has_value())
+ return user_is_verifiable_.value();
+
+ IsUserVerifiable(
+ base::BindOnce(&CreditCardFIDOAuthenticator::SetUserIsVerifiable,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ user_is_verifiable_callback_received_.declare_only_used_while_idle();
+ user_is_verifiable_callback_received_.TimedWait(
+ base::TimeDelta::FromMilliseconds(kIsUserVerifiableTimeoutMs));
+
+ return user_is_verifiable_.value_or(false);
+}
+
bool CreditCardFIDOAuthenticator::IsUserOptedIn() {
- // TODO(crbug/949269): Check pref-store for user opt-in.
- return false;
+ return base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardAuthentication) &&
+ ::autofill::prefs::IsCreditCardFIDOAuthEnabled(
+ autofill_client_->GetPrefs());
+}
+
+void CreditCardFIDOAuthenticator::SyncUserOptIn(
+ AutofillClient::UnmaskDetails& unmask_details) {
+ bool is_user_opted_in = IsUserOptedIn();
+
+ // If payments is offering to opt-in, then that means user is not opted in.
+ if (unmask_details.offer_fido_opt_in) {
+ is_user_opted_in = false;
+ }
+
+ // If payments is requesting a FIDO auth, then that means user is opted in.
+ if (unmask_details.unmask_auth_method ==
+ AutofillClient::UnmaskAuthMethod::FIDO) {
+ is_user_opted_in = true;
+ }
+
+ // Update pref setting if needed.
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_->GetPrefs(),
+ is_user_opted_in);
+}
+
+void CreditCardFIDOAuthenticator::GetAssertion(
+ PublicKeyCredentialRequestOptionsPtr request_options) {
+ autofill_driver_->ConnectToAuthenticator(
+ authenticator_.BindNewPipeAndPassReceiver());
+ authenticator_->GetAssertion(
+ std::move(request_options),
+ base::BindOnce(&CreditCardFIDOAuthenticator::OnDidGetAssertion,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CreditCardFIDOAuthenticator::MakeCredential(
+ PublicKeyCredentialCreationOptionsPtr creation_options) {
+ autofill_driver_->ConnectToAuthenticator(
+ authenticator_.BindNewPipeAndPassReceiver());
+ authenticator_->MakeCredential(
+ std::move(creation_options),
+ base::BindOnce(&CreditCardFIDOAuthenticator::OnDidMakeCredential,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CreditCardFIDOAuthenticator::OptChange(bool opt_in,
+ base::Value attestation_response) {
+ payments::PaymentsClient::OptChangeRequestDetails request_details;
+ request_details.app_locale =
+ autofill_client_->GetPersonalDataManager()->app_locale();
+ request_details.opt_in = opt_in;
+ if (attestation_response.is_dict()) {
+ request_details.fido_authenticator_response =
+ std::move(attestation_response);
+ }
+ payments_client_->OptChange(
+ request_details,
+ base::BindOnce(&CreditCardFIDOAuthenticator::OnDidGetOptChangeResult,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CreditCardFIDOAuthenticator::OnDidGetAssertion(
+ AuthenticatorStatus status,
+ GetAssertionAuthenticatorResponsePtr assertion_response) {
+ // End the flow if there was an authentication error.
+ if (status != AuthenticatorStatus::SUCCESS) {
+ current_flow_ = NONE_FLOW;
+ requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/false);
+ return;
+ }
+
+ base::Value response = ParseAssertionResponse(std::move(assertion_response));
+ full_card_request_.reset(new payments::FullCardRequest(
+ autofill_client_, autofill_client_->GetPaymentsClient(),
+ autofill_client_->GetPersonalDataManager(), form_parsed_timestamp_));
+ full_card_request_->GetFullCardViaFIDO(
+ *card_, AutofillClient::UNMASK_FOR_AUTOFILL,
+ weak_ptr_factory_.GetWeakPtr(), std::move(response));
+}
+
+void CreditCardFIDOAuthenticator::OnDidMakeCredential(
+ AuthenticatorStatus status,
+ MakeCredentialAuthenticatorResponsePtr attestation_response) {
+ // End the flow if there was an authentication error.
+ if (status != AuthenticatorStatus::SUCCESS) {
+ current_flow_ = NONE_FLOW;
+ return;
+ }
+
+ OptChange(/*opt_in=*/true,
+ ParseAttestationResponse(std::move(attestation_response)));
+}
+
+void CreditCardFIDOAuthenticator::OnDidGetOptChangeResult(
+ AutofillClient::PaymentsRpcResult result,
+ bool user_is_opted_in,
+ base::Value creation_options) {
+ DCHECK(current_flow_ == OPT_IN_WITHOUT_CHALLENGE_FLOW ||
+ current_flow_ == OPT_OUT_FLOW ||
+ current_flow_ == OPT_IN_WITH_CHALLENGE_FLOW);
+ // End the flow if the server responded with an error.
+ if (result != AutofillClient::PaymentsRpcResult::SUCCESS) {
+ current_flow_ = NONE_FLOW;
+ return;
+ }
+
+ // If response contains |creation_options| and the last opt-in attempt did not
+ // include a challenge, then invoke WebAuthn registration prompt. Otherwise,
+ // set pref to enable FIDO Authentication for card unmask and end the flow.
+ if (creation_options.is_dict() &&
+ current_flow_ == OPT_IN_WITHOUT_CHALLENGE_FLOW) {
+ Register(std::move(creation_options));
+ } else {
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(
+ autofill_client_->GetPrefs(), user_is_opted_in);
+ current_flow_ = NONE_FLOW;
+ }
+}
+
+void CreditCardFIDOAuthenticator::OnWebauthnOfferDialogUserResponse(
+ bool did_accept) {
+ // TODO(crbug.com/): Register and start fetching authentication challenge if
+ // |did_accept|, otherwise cancel any ongoing request.
+}
+
+void CreditCardFIDOAuthenticator::OnFullCardRequestSucceeded(
+ const payments::FullCardRequest& full_card_request,
+ const CreditCard& card,
+ const base::string16& cvc) {
+ DCHECK_EQ(AUTHENTICATION_FLOW, current_flow_);
+ current_flow_ = NONE_FLOW;
+ requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/true, &card);
+}
+
+void CreditCardFIDOAuthenticator::OnFullCardRequestFailed() {
+ DCHECK_EQ(AUTHENTICATION_FLOW, current_flow_);
+ current_flow_ = NONE_FLOW;
+ requester_->OnFIDOAuthenticationComplete(/*did_succeed=*/false);
+}
+
+PublicKeyCredentialRequestOptionsPtr
+CreditCardFIDOAuthenticator::ParseRequestOptions(
+ const base::Value& request_options) {
+ auto options = PublicKeyCredentialRequestOptions::New();
+
+ const auto* rpid = request_options.FindStringKey("relying_party_id");
+ options->relying_party_id = rpid ? *rpid : std::string(kGooglePaymentsRpid);
+
+ const auto* challenge = request_options.FindStringKey("challenge");
+ DCHECK(challenge);
+ options->challenge = Base64ToBytes(*challenge);
+
+ const auto* timeout = request_options.FindKeyOfType(
+ "timeout_millis", base::Value::Type::INTEGER);
+ options->adjusted_timeout = base::TimeDelta::FromMilliseconds(
+ timeout ? timeout->GetInt() : kWebAuthnTimeoutMs);
+
+ options->user_verification = UserVerificationRequirement::kRequired;
+
+ const auto* key_info_list =
+ request_options.FindKeyOfType("key_info", base::Value::Type::LIST);
+ DCHECK(key_info_list);
+ for (const base::Value& key_info : key_info_list->GetList()) {
+ options->allow_credentials.push_back(ParseCredentialDescriptor(key_info));
+ }
+
+ return options;
+}
+
+PublicKeyCredentialCreationOptionsPtr
+CreditCardFIDOAuthenticator::ParseCreationOptions(
+ const base::Value& creation_options) {
+ auto options = PublicKeyCredentialCreationOptions::New();
+
+ const auto* rpid = creation_options.FindStringKey("relying_party_id");
+ options->relying_party.id = rpid ? *rpid : kGooglePaymentsRpid;
+
+ const auto* relying_party_name =
+ creation_options.FindStringKey("relying_party_name");
+ options->relying_party.name =
+ relying_party_name ? *relying_party_name : kGooglePaymentsRpName;
+
+ const auto* icon_url = creation_options.FindStringKey("icon_url");
+ if (icon_url)
+ options->relying_party.icon_url = GURL(*icon_url);
+
+ const std::string gaia =
+ autofill_client_->GetIdentityManager()->GetPrimaryAccountInfo().gaia;
+ options->user.id = std::vector<uint8_t>(gaia.begin(), gaia.end());
+ options->user.name =
+ autofill_client_->GetIdentityManager()->GetPrimaryAccountInfo().email;
+
+ base::Optional<AccountInfo> account_info =
+ autofill_client_->GetIdentityManager()
+ ->FindExtendedAccountInfoForAccountWithRefreshToken(
+ autofill_client_->GetPersonalDataManager()
+ ->GetAccountInfoForPaymentsServer());
+ if (account_info.has_value()) {
+ options->user.display_name = account_info.value().given_name;
+ options->user.icon_url = GURL(account_info.value().picture_url);
+ } else {
+ options->user.display_name = "";
+ }
+
+ const auto* challenge = creation_options.FindStringKey("challenge");
+ DCHECK(challenge);
+ options->challenge = Base64ToBytes(*challenge);
+
+ const auto* identifier_list = creation_options.FindKeyOfType(
+ "algorithm_identifier", base::Value::Type::LIST);
+ if (identifier_list) {
+ for (const base::Value& algorithm_identifier : identifier_list->GetList()) {
+ device::PublicKeyCredentialParams::CredentialInfo parameter;
+ parameter.type = device::CredentialType::kPublicKey;
+ parameter.algorithm = algorithm_identifier.GetInt();
+ options->public_key_parameters.push_back(parameter);
+ }
+ }
+
+ const auto* timeout = creation_options.FindKeyOfType(
+ "timeout_millis", base::Value::Type::INTEGER);
+ options->adjusted_timeout = base::TimeDelta::FromMilliseconds(
+ timeout ? timeout->GetInt() : kWebAuthnTimeoutMs);
+
+ // List of keys that Payments already knows about, and so should not make a
+ // new credential.
+ const auto* excluded_keys_list =
+ creation_options.FindKeyOfType("key_info", base::Value::Type::LIST);
+ if (excluded_keys_list) {
+ for (const base::Value& key_info : excluded_keys_list->GetList()) {
+ options->exclude_credentials.push_back(
+ ParseCredentialDescriptor(key_info));
+ }
+ }
+
+ return options;
+}
+
+PublicKeyCredentialDescriptor
+CreditCardFIDOAuthenticator::ParseCredentialDescriptor(
+ const base::Value& key_info) {
+ std::vector<uint8_t> credential_id;
+ const auto* id = key_info.FindStringKey("credential_id");
+ DCHECK(id);
+ credential_id = Base64ToBytes(*id);
+
+ base::flat_set<FidoTransportProtocol> authenticator_transports;
+ const auto* transports = key_info.FindKeyOfType(
+ "authenticator_transport_support", base::Value::Type::LIST);
+ if (transports && !transports->GetList().empty()) {
+ for (const base::Value& transport_type : transports->GetList()) {
+ base::Optional<FidoTransportProtocol> protocol =
+ device::ConvertToFidoTransportProtocol(
+ base::ToLowerASCII(transport_type.GetString()));
+ if (protocol.has_value())
+ authenticator_transports.insert(*protocol);
+ }
+ }
+
+ return PublicKeyCredentialDescriptor(CredentialType::kPublicKey,
+ credential_id, authenticator_transports);
+}
+
+base::Value CreditCardFIDOAuthenticator::ParseAssertionResponse(
+ GetAssertionAuthenticatorResponsePtr assertion_response) {
+ base::Value response = base::Value(base::Value::Type::DICTIONARY);
+ response.SetKey("credential_id", base::Value(assertion_response->info->id));
+ response.SetKey("authenticator_data",
+ BytesToBase64(assertion_response->authenticator_data));
+ response.SetKey("client_data",
+ BytesToBase64(assertion_response->info->client_data_json));
+ response.SetKey("signature", BytesToBase64(assertion_response->signature));
+ return response;
+}
+
+base::Value CreditCardFIDOAuthenticator::ParseAttestationResponse(
+ MakeCredentialAuthenticatorResponsePtr attestation_response) {
+ base::Value response = base::Value(base::Value::Type::DICTIONARY);
+
+ base::Value fido_attestation_info =
+ base::Value(base::Value::Type::DICTIONARY);
+ fido_attestation_info.SetKey(
+ "client_data",
+ BytesToBase64(attestation_response->info->client_data_json));
+ fido_attestation_info.SetKey(
+ "attestation_object",
+ BytesToBase64(attestation_response->attestation_object));
+
+ base::Value authenticator_transport_list =
+ base::Value(base::Value::Type::LIST);
+ for (FidoTransportProtocol protocol : attestation_response->transports) {
+ authenticator_transport_list.GetList().push_back(
+ base::Value(base::ToUpperASCII(device::ToString(protocol))));
+ }
+
+ response.SetKey("fido_attestation_info", std::move(fido_attestation_info));
+ response.SetKey("authenticator_transport",
+ std::move(authenticator_transport_list));
+
+ return response;
+}
+
+bool CreditCardFIDOAuthenticator::IsValidRequestOptions(
+ const base::Value& request_options) {
+ if (!request_options.is_dict() || request_options.DictEmpty() ||
+ !request_options.FindStringKey("challenge") ||
+ !request_options.FindKeyOfType("key_info", base::Value::Type::LIST)) {
+ return false;
+ }
+
+ const auto* key_info_list =
+ request_options.FindKeyOfType("key_info", base::Value::Type::LIST);
+
+ if (key_info_list->GetList().empty())
+ return false;
+
+ for (const base::Value& key_info : key_info_list->GetList()) {
+ if (!key_info.is_dict() || !key_info.FindStringKey("credential_id"))
+ return false;
+ }
+
+ return true;
+}
+
+bool CreditCardFIDOAuthenticator::IsValidCreationOptions(
+ const base::Value& creation_options) {
+ return creation_options.is_dict() &&
+ creation_options.FindStringKey("challenge");
+}
+
+void CreditCardFIDOAuthenticator::SetUserIsVerifiable(bool user_is_verifiable) {
+ user_is_verifiable_ = user_is_verifiable;
+ user_is_verifiable_callback_received_.Signal();
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
index 83f0efcbf56..01aef853526 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h
@@ -13,11 +13,26 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/payments/full_card_request.h"
#include "components/autofill/core/browser/payments/payments_client.h"
+#include "device/fido/fido_constants.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/webauthn/internal_authenticator.mojom.h"
namespace autofill {
-using blink::mojom::InternalAuthenticatorPtr;
+using blink::mojom::AuthenticatorStatus;
+using blink::mojom::GetAssertionAuthenticatorResponse;
+using blink::mojom::GetAssertionAuthenticatorResponsePtr;
+using blink::mojom::InternalAuthenticator;
+using blink::mojom::MakeCredentialAuthenticatorResponse;
+using blink::mojom::MakeCredentialAuthenticatorResponsePtr;
+using blink::mojom::PublicKeyCredentialCreationOptions;
+using blink::mojom::PublicKeyCredentialCreationOptionsPtr;
+using blink::mojom::PublicKeyCredentialRequestOptions;
+using blink::mojom::PublicKeyCredentialRequestOptionsPtr;
+using device::CredentialType;
+using device::FidoTransportProtocol;
+using device::PublicKeyCredentialDescriptor;
+using device::UserVerificationRequirement;
// Authenticates credit card unmasking through FIDO authentication, using the
// WebAuthn specification, standardized by the FIDO alliance. The Webauthn
@@ -25,8 +40,23 @@ using blink::mojom::InternalAuthenticatorPtr;
// and verify that binding. More information can be found here:
// - https://www.w3.org/TR/webauthn-1/
// - https://fidoalliance.org/fido2/
-class CreditCardFIDOAuthenticator {
+class CreditCardFIDOAuthenticator
+ : public payments::FullCardRequest::ResultDelegate {
public:
+ // Useful for splitting metrics to correct sub-histograms and knowing which
+ // Payments RPC's to send.
+ enum Flow {
+ // No flow is in progress.
+ NONE_FLOW,
+ // Authentication flow.
+ AUTHENTICATION_FLOW,
+ // Registration flow, including a challenge to sign.
+ OPT_IN_WITH_CHALLENGE_FLOW,
+ // Opt-in attempt flow, no challenge to sign.
+ OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ // Opt-out flow.
+ OPT_OUT_FLOW,
+ };
class Requester {
public:
virtual ~Requester() {}
@@ -35,7 +65,10 @@ class CreditCardFIDOAuthenticator {
const CreditCard* card = nullptr) = 0;
};
CreditCardFIDOAuthenticator(AutofillDriver* driver, AutofillClient* client);
- virtual ~CreditCardFIDOAuthenticator();
+ ~CreditCardFIDOAuthenticator() override;
+
+ // Offer the option to use WebAuthn for authenticating future card unmasking.
+ void ShowWebauthnOfferDialog();
// Authentication
void Authenticate(const CreditCard* card,
@@ -43,22 +76,123 @@ class CreditCardFIDOAuthenticator {
base::TimeTicks form_parsed_timestamp,
base::Value request_options);
+ // Registration
+ void Register(base::Value creation_options = base::Value());
+
+ // Opts the user out.
+ void OptOut();
+
// Invokes callback with true if user has a verifying platform authenticator.
// e.g. Touch/Face ID, Windows Hello, Android fingerprint, etc., is available
// and enabled. Otherwise invokes callback with false.
virtual void IsUserVerifiable(base::OnceCallback<void(bool)> callback);
+ // The synchronous version of IsUserVerifiable. Used on settings page load.
+ bool IsUserVerifiable();
+
// Returns true only if the user has opted-in to use WebAuthn for autofill.
virtual bool IsUserOptedIn();
+ // Ensures that local user opt-in pref is in-sync with payments server.
+ void SyncUserOptIn(AutofillClient::UnmaskDetails& unmask_details);
+
+ // Returns the current flow.
+ Flow current_flow() { return current_flow_; }
+
private:
friend class AutofillManagerTest;
friend class CreditCardAccessManagerTest;
friend class CreditCardFIDOAuthenticatorTest;
+ friend class TestCreditCardFIDOAuthenticator;
+ FRIEND_TEST_ALL_PREFIXES(CreditCardFIDOAuthenticatorTest,
+ ParseRequestOptions);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardFIDOAuthenticatorTest,
+ ParseAssertionResponse);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardFIDOAuthenticatorTest,
+ ParseCreationOptions);
+ FRIEND_TEST_ALL_PREFIXES(CreditCardFIDOAuthenticatorTest,
+ ParseAttestationResponse);
+
+ // Invokes the WebAuthn prompt to request user verification to sign the
+ // challenge in |request_options|.
+ virtual void GetAssertion(
+ PublicKeyCredentialRequestOptionsPtr request_options);
+
+ // Invokes the WebAuthn prompt to request user verification to sign the
+ // challenge in |creation_options| and create a key-pair.
+ virtual void MakeCredential(
+ PublicKeyCredentialCreationOptionsPtr creation_options);
+
+ // Makes a request to payments to either opt-in or opt-out the user.
+ void OptChange(bool opt_in, base::Value attestation_response = base::Value());
+
+ // The callback invoked from the WebAuthn prompt including the
+ // |assertion_response|, which will be sent to Google Payments to retrieve
+ // card details.
+ void OnDidGetAssertion(
+ AuthenticatorStatus status,
+ GetAssertionAuthenticatorResponsePtr assertion_response);
+
+ // The callback invoked from the WebAuthn prompt including the
+ // |attestation_response|, which will be sent to Google Payments to enroll the
+ // credential for this user.
+ void OnDidMakeCredential(
+ AuthenticatorStatus status,
+ MakeCredentialAuthenticatorResponsePtr attestation_response);
+
+ // Sets prefstore to enable credit card authentication if rpc was successful.
+ void OnDidGetOptChangeResult(AutofillClient::PaymentsRpcResult result,
+ bool user_is_opted_in,
+ base::Value creation_options = base::Value());
+
+ // The callback invoked from the WebAuthn offer dialog when it is accepted or
+ // declined/cancelled.
+ void OnWebauthnOfferDialogUserResponse(bool did_accept);
+
+ // payments::FullCardRequest::ResultDelegate:
+ void OnFullCardRequestSucceeded(
+ const payments::FullCardRequest& full_card_request,
+ const CreditCard& card,
+ const base::string16& cvc) override;
+ void OnFullCardRequestFailed() override;
+
+ // Converts |request_options| from JSON to mojom pointer.
+ PublicKeyCredentialRequestOptionsPtr ParseRequestOptions(
+ const base::Value& request_options);
+
+ // Converts |creation_options| from JSON to mojom pointer.
+ PublicKeyCredentialCreationOptionsPtr ParseCreationOptions(
+ const base::Value& creation_options);
+
+ // Helper function to parse |key_info| sub-dictionary found in
+ // |request_options| and |creation_options|.
+ PublicKeyCredentialDescriptor ParseCredentialDescriptor(
+ const base::Value& key_info);
+
+ // Converts |assertion_response| from mojom pointer to JSON.
+ base::Value ParseAssertionResponse(
+ GetAssertionAuthenticatorResponsePtr assertion_response);
+
+ // Converts |attestation_response| from mojom pointer to JSON.
+ base::Value ParseAttestationResponse(
+ MakeCredentialAuthenticatorResponsePtr attestation_response);
+
+ // Returns true if |request_options| contains a challenge and has a non-empty
+ // list of keys that each have a Credential ID.
+ bool IsValidRequestOptions(const base::Value& request_options);
+
+ // Returns true if |request_options| contains a challenge.
+ bool IsValidCreationOptions(const base::Value& creation_options);
+
+ // Sets the value for |user_is_verifiable_|.
+ void SetUserIsVerifiable(bool user_is_verifiable);
// Card being unmasked.
const CreditCard* card_;
+ // The current flow in progress.
+ Flow current_flow_ = NONE_FLOW;
+
// Meant for histograms recorded in FullCardRequest.
base::TimeTicks form_parsed_timestamp_;
@@ -72,7 +206,7 @@ class CreditCardFIDOAuthenticator {
payments::PaymentsClient* const payments_client_;
// Authenticator pointer to facilitate WebAuthn.
- InternalAuthenticatorPtr authenticator_;
+ mojo::Remote<InternalAuthenticator> authenticator_;
// Responsible for getting the full card details, including the PAN and the
// CVC.
@@ -81,6 +215,12 @@ class CreditCardFIDOAuthenticator {
// Weak pointer to object that is requesting authentication.
base::WeakPtr<Requester> requester_;
+ // Set when callback for IsUserVerifiable() is invoked with passed value.
+ base::Optional<bool> user_is_verifiable_ = base::nullopt;
+
+ // Signaled when callback for IsUserVerifiable() is invoked.
+ base::WaitableEvent user_is_verifiable_callback_received_;
+
base::WeakPtrFactory<CreditCardFIDOAuthenticator> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CreditCardFIDOAuthenticator);
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
index e3a0c5a8d32..3ec70dc08e8 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc
@@ -24,9 +24,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -61,8 +62,6 @@
#include "components/variations/variations_params_manager.h"
#include "components/version_info/channel.h"
#include "net/base/url_util.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -70,6 +69,8 @@
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
+#include "components/autofill/core/browser/payments/payments_service_url.h"
+
using base::ASCIIToUTF16;
namespace autofill {
@@ -77,6 +78,13 @@ namespace {
const char kTestGUID[] = "00000000-0000-0000-0000-000000000001";
const char kTestNumber[] = "4234567890123456"; // Visa
+const char kTestRelyingPartyId[] = "google.com";
+// Base64 encoding of "This is a test challenge".
+constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
+// Base64 encoding of "This is a test Credential ID".
+const char kTestCredentialId[] = "VGhpcyBpcyBhIHRlc3QgQ3JlZGVudGlhbCBJRC4=";
+// Base64 encoding of "This is a test signature".
+const char kTestSignature[] = "VGhpcyBpcyBhIHRlc3Qgc2lnbmF0dXJl";
std::string NextMonth() {
base::Time::Exploded now;
@@ -84,6 +92,20 @@ std::string NextMonth() {
return base::NumberToString(now.month % 12 + 1);
}
+std::vector<uint8_t> Base64ToBytes(std::string base64) {
+ std::string bytes;
+ bool did_succeed = base::Base64Decode(base::StringPiece(base64), &bytes);
+ if (did_succeed) {
+ return std::vector<uint8_t>(bytes.begin(), bytes.end());
+ }
+ return std::vector<uint8_t>{};
+}
+
+std::string BytesToBase64(const std::vector<uint8_t> bytes) {
+ std::string base64;
+ base::Base64Encode(std::string(bytes.begin(), bytes.end()), &base64);
+ return base64;
+}
} // namespace
class CreditCardFIDOAuthenticatorTest : public testing::Test {
@@ -104,9 +126,6 @@ class CreditCardFIDOAuthenticatorTest : public testing::Test {
requester_.reset(new TestAuthenticationRequester());
autofill_driver_ =
std::make_unique<testing::NiceMock<TestAutofillDriver>>();
- request_context_ = new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get());
- autofill_driver_->SetURLRequestContext(request_context_.get());
payments::TestPaymentsClient* payments_client =
new payments::TestPaymentsClient(
@@ -122,8 +141,6 @@ class CreditCardFIDOAuthenticatorTest : public testing::Test {
// Order of destruction is important as AutofillDriver relies on
// PersonalDataManager to be around when it gets destroyed.
autofill_driver_.reset();
-
- request_context_ = nullptr;
}
CreditCard CreateServerCard(std::string guid, std::string number) {
@@ -140,35 +157,373 @@ class CreditCardFIDOAuthenticatorTest : public testing::Test {
return masked_server_card;
}
+ base::Value GetTestRequestOptions(std::string challenge,
+ std::string relying_party_id,
+ std::string credential_id) {
+ base::Value request_options = base::Value(base::Value::Type::DICTIONARY);
+
+ // Building the following JSON structure--
+ // request_options = {
+ // "challenge": challenge,
+ // "timeout_millis": kTestTimeoutSeconds,
+ // "relying_party_id": relying_party_id,
+ // "key_info": [{
+ // "credential_id": credential_id,
+ // "authenticator_transport_support": ["INTERNAL"]
+ // }]}
+ request_options.SetKey("challenge", base::Value(challenge));
+ request_options.SetKey("relying_party_id", base::Value(relying_party_id));
+
+ base::Value key_info(base::Value::Type::DICTIONARY);
+ key_info.SetKey("credential_id", base::Value(credential_id));
+ key_info.SetKey("authenticator_transport_support",
+ base::Value(base::Value::Type::LIST));
+ key_info
+ .FindKeyOfType("authenticator_transport_support",
+ base::Value::Type::LIST)
+ ->GetList()
+ .push_back(base::Value("INTERNAL"));
+
+ request_options.SetKey("key_info", base::Value(base::Value::Type::LIST));
+ request_options.FindKeyOfType("key_info", base::Value::Type::LIST)
+ ->GetList()
+ .push_back(std::move(key_info));
+ return request_options;
+ }
+
+ base::Value GetTestCreationOptions(std::string challenge,
+ std::string relying_party_id) {
+ base::Value creation_options = base::Value(base::Value::Type::DICTIONARY);
+
+ // Building the following JSON structure--
+ // request_options = {
+ // "challenge": challenge,
+ // "relying_party_id": relying_party_id,
+ // }]}
+ if (!challenge.empty())
+ creation_options.SetKey("challenge", base::Value(challenge));
+ creation_options.SetKey("relying_party_id", base::Value(relying_party_id));
+ return creation_options;
+ }
+
+ // Invokes GetRealPan callback.
+ void GetRealPan(AutofillClient::PaymentsRpcResult result,
+ const std::string& real_pan) {
+ DCHECK(fido_authenticator_->full_card_request_);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ fido_authenticator_->full_card_request_->OnDidGetRealPan(
+ result, response.with_real_pan(real_pan));
+ }
+
+ // Mocks an OptChange response from Payments Client.
+ void OptChange(AutofillClient::PaymentsRpcResult result,
+ bool user_is_opted_in,
+ base::Value creation_options = base::Value()) {
+ fido_authenticator_->OnDidGetOptChangeResult(result, user_is_opted_in,
+ std::move(creation_options));
+ }
+
protected:
std::unique_ptr<TestAuthenticationRequester> requester_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_;
scoped_refptr<AutofillWebDataService> database_;
TestPersonalDataManager personal_data_manager_;
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<CreditCardFIDOAuthenticator> fido_authenticator_;
};
-TEST_F(CreditCardFIDOAuthenticatorTest, IsUserOptedInFalse) {
+TEST_F(CreditCardFIDOAuthenticatorTest, IsUserOptedIn_FlagDisabled) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, IsUserOptedIn_False) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ false);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, IsUserOptedIn_True) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, SyncUserOptIn_OnOfferedOptIn) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+
+ // If payments is offering to opt-in, then that means user is not opted in.
+ AutofillClient::UnmaskDetails unmask_details;
+ unmask_details.offer_fido_opt_in = true;
+ fido_authenticator_->SyncUserOptIn(unmask_details);
EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
}
-TEST_F(CreditCardFIDOAuthenticatorTest, IsUserVerifiableFalse) {
+TEST_F(CreditCardFIDOAuthenticatorTest, SyncUserOptIn_OnFIDOAuthRequest) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ false);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ // If payments is requesting a FIDO auth, then that means user is opted in.
+ AutofillClient::UnmaskDetails unmask_details;
+ unmask_details.unmask_auth_method = AutofillClient::UnmaskAuthMethod::FIDO;
+ fido_authenticator_->SyncUserOptIn(unmask_details);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, IsUserVerifiable_False) {
fido_authenticator_->IsUserVerifiable(
base::BindOnce(&TestAuthenticationRequester::IsUserVerifiableCallback,
requester_->GetWeakPtr()));
EXPECT_FALSE(requester_->is_user_verifiable().value());
}
-TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCardFailure) {
+TEST_F(CreditCardFIDOAuthenticatorTest, Sync_IsUserVerifiable_False) {
+ EXPECT_FALSE(fido_authenticator_->IsUserVerifiable());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, ParseRequestOptions) {
+ base::Value request_options_json = GetTestRequestOptions(
+ kTestChallenge, kTestRelyingPartyId, kTestCredentialId);
+
+ PublicKeyCredentialRequestOptionsPtr request_options_ptr =
+ fido_authenticator_->ParseRequestOptions(std::move(request_options_json));
+ EXPECT_EQ(kTestChallenge, BytesToBase64(request_options_ptr->challenge));
+ EXPECT_EQ(kTestRelyingPartyId, request_options_ptr->relying_party_id);
+ EXPECT_EQ(kTestCredentialId,
+ BytesToBase64(request_options_ptr->allow_credentials.front().id()));
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, ParseAssertionResponse) {
+ GetAssertionAuthenticatorResponsePtr assertion_response_ptr =
+ GetAssertionAuthenticatorResponse::New();
+ assertion_response_ptr->info = blink::mojom::CommonCredentialInfo::New();
+ assertion_response_ptr->info->id = kTestCredentialId;
+ assertion_response_ptr->signature = Base64ToBytes(kTestSignature);
+
+ base::Value assertion_response_json =
+ fido_authenticator_->ParseAssertionResponse(
+ std::move(assertion_response_ptr));
+ EXPECT_EQ(kTestCredentialId,
+ *assertion_response_json.FindStringKey("credential_id"));
+ EXPECT_EQ(kTestSignature,
+ *assertion_response_json.FindStringKey("signature"));
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, ParseCreationOptions) {
+ base::Value creation_options_json =
+ GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId);
+
+ PublicKeyCredentialCreationOptionsPtr creation_options_ptr =
+ fido_authenticator_->ParseCreationOptions(
+ std::move(creation_options_json));
+ EXPECT_EQ(kTestChallenge, BytesToBase64(creation_options_ptr->challenge));
+ EXPECT_EQ(kTestRelyingPartyId, creation_options_ptr->relying_party.id);
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, ParseAttestationResponse) {
+ MakeCredentialAuthenticatorResponsePtr attestation_response_ptr =
+ MakeCredentialAuthenticatorResponse::New();
+ attestation_response_ptr->info = blink::mojom::CommonCredentialInfo::New();
+ attestation_response_ptr->attestation_object = Base64ToBytes(kTestSignature);
+
+ base::Value attestation_response_json =
+ fido_authenticator_->ParseAttestationResponse(
+ std::move(attestation_response_ptr));
+ EXPECT_EQ(kTestSignature, *attestation_response_json.FindStringPath(
+ "fido_attestation_info.attestation_object"));
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCard_BadRequestOptions) {
CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
fido_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
- base::TimeTicks::Now(), base::Value());
+ base::TimeTicks::Now(),
+ base::Value(base::Value::Type::DICTIONARY));
+ EXPECT_FALSE(requester_->did_succeed());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest,
+ AuthenticateCard_UserVerificationFailed) {
+ CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
+
+ fido_authenticator_->Authenticate(&card, requester_->GetWeakPtr(),
+ base::TimeTicks::Now(),
+ base::Value(base::Value::Type::DICTIONARY));
+
+ TestCreditCardFIDOAuthenticator::GetAssertion(fido_authenticator_.get(),
+ /*did_succeed=*/false);
+ EXPECT_FALSE(requester_->did_succeed());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest,
+ AuthenticateCard_PaymentsResponseError) {
+ CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
+
+ fido_authenticator_->Authenticate(
+ &card, requester_->GetWeakPtr(), base::TimeTicks::Now(),
+ GetTestRequestOptions(kTestChallenge, kTestRelyingPartyId,
+ kTestCredentialId));
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock user verification.
+ TestCreditCardFIDOAuthenticator::GetAssertion(fido_authenticator_.get(),
+ /*did_succeed=*/true);
+ GetRealPan(AutofillClient::PaymentsRpcResult::NETWORK_ERROR, "");
+
EXPECT_FALSE(requester_->did_succeed());
}
+TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCard_Success) {
+ CreditCard card = CreateServerCard(kTestGUID, kTestNumber);
+
+ fido_authenticator_->Authenticate(
+ &card, requester_->GetWeakPtr(), base::TimeTicks::Now(),
+ GetTestRequestOptions(kTestChallenge, kTestRelyingPartyId,
+ kTestCredentialId));
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::AUTHENTICATION_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock user verification and payments response.
+ TestCreditCardFIDOAuthenticator::GetAssertion(fido_authenticator_.get(),
+ /*did_succeed=*/true);
+ GetRealPan(AutofillClient::PaymentsRpcResult::SUCCESS, kTestNumber);
+
+ EXPECT_TRUE(requester_->did_succeed());
+ EXPECT_EQ(ASCIIToUTF16(kTestNumber), requester_->number());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, OptIn_PaymentsResponseError) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register();
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock payments response.
+ OptChange(AutofillClient::PaymentsRpcResult::NETWORK_ERROR,
+ /*user_is_opted_in=*/false);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, OptIn_Success) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register();
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock payments response.
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, Register_BadCreationOptions) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register(
+ GetTestCreationOptions(/*challenge=*/"", kTestRelyingPartyId));
+
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, Register_UserResponseFailure) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register(
+ GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId));
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock user response and payments response.
+ TestCreditCardFIDOAuthenticator::MakeCredential(fido_authenticator_.get(),
+ /*did_succeed=*/false);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, Register_Success) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register(
+ GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId));
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock user response and payments response.
+ TestCreditCardFIDOAuthenticator::MakeCredential(fido_authenticator_.get(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest,
+ Register_EnrollAttemptReturnsCreationOptions) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->Register();
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITHOUT_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock payments response with challenge to invoke enrollment flow.
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/false,
+ GetTestCreationOptions(kTestChallenge, kTestRelyingPartyId));
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_IN_WITH_CHALLENGE_FLOW,
+ fido_authenticator_->current_flow());
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+
+ // Mock user response and second payments response.
+ TestCreditCardFIDOAuthenticator::MakeCredential(fido_authenticator_.get(),
+ /*did_succeed=*/true);
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/true);
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+}
+
+TEST_F(CreditCardFIDOAuthenticatorTest, OptOut_Success) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAuthentication);
+ ::autofill::prefs::SetCreditCardFIDOAuthEnabled(autofill_client_.GetPrefs(),
+ true);
+
+ EXPECT_TRUE(fido_authenticator_->IsUserOptedIn());
+
+ fido_authenticator_->OptOut();
+ EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::OPT_OUT_FLOW,
+ fido_authenticator_->current_flow());
+
+ // Mock payments response.
+ OptChange(AutofillClient::PaymentsRpcResult::SUCCESS,
+ /*user_is_opted_in=*/false);
+ EXPECT_FALSE(fido_authenticator_->IsUserOptedIn());
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc
index 8e6d097ba7a..05b70b7d8dc 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -276,19 +276,6 @@ bool CreditCardSaveManager::IsCreditCardUploadEnabled() {
personal_data_manager_->GetSyncSigninState(), client_->GetLogManager());
}
-bool CreditCardSaveManager::IsUploadEnabledForNetwork(
- const std::string& network) {
- if (network == kEloCard &&
- base::FeatureList::IsEnabled(features::kAutofillUpstreamDisallowElo)) {
- return false;
- } else if (network == kJCBCard &&
- base::FeatureList::IsEnabled(
- features::kAutofillUpstreamDisallowJcb)) {
- return false;
- }
- return true;
-}
-
void CreditCardSaveManager::OnDidUploadCard(
AutofillClient::PaymentsRpcResult result,
const std::string& server_id) {
@@ -367,9 +354,7 @@ void CreditCardSaveManager::OnDidGetUploadDetails(
if (result == AutofillClient::SUCCESS) {
// Do *not* call payments_client_->Prepare() here. We shouldn't send
// credentials until the user has explicitly accepted a prompt to upload.
- if (base::FeatureList::IsEnabled(
- features::kAutofillDoNotUploadSaveUnsupportedCards) &&
- !supported_card_bin_ranges.empty() &&
+ if (!supported_card_bin_ranges.empty() &&
!payments::IsCreditCardNumberSupported(upload_request_.card.number(),
supported_card_bin_ranges)) {
// Attempt local card save if card not already saved.
@@ -434,8 +419,10 @@ void CreditCardSaveManager::OfferCardLocalSave() {
observer_for_testing_->OnOfferLocalSave();
client_->ConfirmSaveCreditCardLocally(
local_card_save_candidate_,
- AutofillClient::SaveCreditCardOptions().with_show_prompt(
- show_save_prompt_.value_or(true)),
+ AutofillClient::SaveCreditCardOptions()
+ .with_show_prompt(show_save_prompt_.value_or(true))
+ .with_from_dynamic_change_form(from_dynamic_change_form_)
+ .with_has_non_focusable_field(has_non_focusable_field_),
base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnLocalSave,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h
index 7154e7fba66..0fe7b67101f 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_manager.h
@@ -120,11 +120,6 @@ class CreditCardSaveManager {
// are satisfied.
virtual bool IsCreditCardUploadEnabled();
- // Returns true if the given |network| is allowed for upload to Google
- // Payments, false otherwise. Mainly used for blacklisting upload of certain
- // networks.
- bool IsUploadEnabledForNetwork(const std::string& network);
-
// For testing.
void SetAppLocale(std::string app_locale) { app_locale_ = app_locale; }
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index 52399d394ab..721fab518e0 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -17,9 +17,10 @@
#include "base/guid.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -51,8 +52,6 @@
#include "components/prefs/pref_service.h"
#include "components/sync/driver/test_sync_service.h"
#include "components/ukm/test_ukm_recorder.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -76,9 +75,6 @@ using UkmDeveloperEngagementType = ukm::builders::Autofill_DeveloperEngagement;
const base::Time kArbitraryTime = base::Time::FromDoubleT(25);
const base::Time kMuchLaterTime = base::Time::FromDoubleT(5000);
-const char kEloCardNumber[] = "5067111111111112";
-const char kJcbCardNumber[] = "3528111111111110";
-
std::string NextYear() {
base::Time::Exploded now;
base::Time::Now().LocalExplode(&now);
@@ -153,9 +149,6 @@ class CreditCardSaveManagerTest : public testing::Test {
/*profile_database=*/database_,
/*is_off_the_record=*/false);
autofill_driver_.reset(new TestAutofillDriver());
- request_context_ = new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get());
- autofill_driver_->SetURLRequestContext(request_context_.get());
payments_client_ = new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(),
autofill_client_.GetIdentityManager(), &personal_data_);
@@ -187,8 +180,6 @@ class CreditCardSaveManagerTest : public testing::Test {
personal_data_.SetPrefService(nullptr);
personal_data_.ClearCreditCards();
-
- request_context_ = nullptr;
}
void FormsSeen(const std::vector<FormData>& forms) {
@@ -358,11 +349,10 @@ class CreditCardSaveManagerTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_;
scoped_refptr<AutofillWebDataService> database_;
MockPersonalDataManager personal_data_;
MockAutocompleteHistoryManager autocomplete_history_manager_;
@@ -695,8 +685,6 @@ TEST_F(CreditCardSaveManagerTest, LocalCreditCard_ExpirationDateMissing) {
// Tests metrics for supporting unfocused card form.
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_WithNonFocusableField) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillImportNonFocusableCreditCardForms);
credit_card_save_manager_->SetCreditCardUploadEnabled(true);
// Create, fill and submit an address form in order to establish a recent
@@ -740,13 +728,10 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_WithNonFocusableField) {
AutofillMetrics::UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD);
}
-// Tests upload card save will still work as usual when supporting unfocused
-// card form experiment is off.
-TEST_F(CreditCardSaveManagerTest,
- UploadCreditCard_WithNonFocusableField_ExpOff) {
- scoped_feature_list_.InitAndDisableFeature(
- features::kAutofillImportNonFocusableCreditCardForms);
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+// Tests local card save will still work as usual when supporting unfocused card
+// form feature is already on.
+TEST_F(CreditCardSaveManagerTest, LocalCreditCard_WithNonFocusableField) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -774,19 +759,83 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
}
-// Tests local card save will still work as usual when supporting unfocused card
-// form feature is already on.
-TEST_F(CreditCardSaveManagerTest, LocalCreditCard_WithNonFocusableField) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillImportNonFocusableCreditCardForms);
+// Tests that |has_non_focusable_field| is correctly sent to AutofillClient when
+// offering local save.
+TEST_F(CreditCardSaveManagerTest,
+ Local_UploadDisabled_SaveCreditCardOptions_WithNonFocusableField) {
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+ // Set up our credit card form data with non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions()
+ .with_split_names(true)
+ .with_is_from_non_focusable_form(true));
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().has_non_focusable_field);
+}
+
+// Tests that |has_non_focusable_field| is correctly sent to AutofillClient when
+// upload failed because of unsupported bin and falling back to local save.
+TEST_F(CreditCardSaveManagerTest,
+ Local_UnsupportedCard_SaveCreditCardOptions_WithNonFocusableField) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ // Set supported bin range so that the used card is unsupported.
+ std::vector<std::pair<int, int>> supported_card_bin_ranges{
+ std::make_pair(34, 34), std::make_pair(300, 305)};
+ payments_client_->SetSupportedBINRanges(supported_card_bin_ranges);
+
+ // Set up our credit card form data with non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions()
+ .with_split_names(true)
+ .with_is_from_non_focusable_form(true));
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().has_non_focusable_field);
+}
+
+// Tests that |has_non_focusable_field| is correctly sent to AutofillClient when
+// GetDetailsForSaveCard failed and falling back to local save.
+TEST_F(
+ CreditCardSaveManagerTest,
+ Local_GetDetailsForSaveCardFails_SaveCreditCardOptions_WithNonFocusableField) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ // Anything other than "en-US" will cause GetUploadDetails to return a failure
+ // response.
+ credit_card_save_manager_->SetAppLocale("pt-BR");
+
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -813,20 +862,18 @@ TEST_F(CreditCardSaveManagerTest, LocalCreditCard_WithNonFocusableField) {
credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().has_non_focusable_field);
}
-// Tests local card save will still work as usual when supporting unfocused card
-// form experiment is off.
+// Tests that |has_non_focusable_field| is correctly sent to AutofillClient when
+// offering upload save.
TEST_F(CreditCardSaveManagerTest,
- LocalCreditCard_WithNonFocusableField_ExpOff) {
- scoped_feature_list_.InitAndDisableFeature(
- features::kAutofillImportNonFocusableCreditCardForms);
- credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+ Upload_SaveCreditCardOptions_WithNonFocusableField) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -854,11 +901,204 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
credit_card_form.fields[5].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().has_non_focusable_field);
+}
+
+// Tests that |has_non_focusable_field| is not sent to AutofillClient when the
+// form does not have any non-focusable fields.
+TEST_F(CreditCardSaveManagerTest,
+ SaveCreditCardOptions_WithoutNonFocusableField) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+
+ // Set up our credit card form data without any non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions().with_split_names(true));
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
- EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_FALSE(
+ autofill_client_.get_save_credit_card_options().has_non_focusable_field);
+}
+
+// Tests that |from_dynamic_change_form| is correctly sent to AutofillClient
+// when offering local save.
+TEST_F(CreditCardSaveManagerTest,
+ Local_UploadDisabled_SaveCreditCardOptions_WithDynamicForms) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+
+ // Set up our credit card form data without any non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions().with_split_names(true));
+ // Use the two same forms for FormsSeen to mock the dynamic change forms.
+ FormsSeen(std::vector<FormData>(2, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().from_dynamic_change_form);
+}
+
+// Tests that |from_dynamic_change_form| is correctly sent to AutofillClient
+// when upload failed because of unsupported bin and falling back to local save.
+TEST_F(CreditCardSaveManagerTest,
+ Local_UnsupportedCard_SaveCreditCardOptions_WithDynamicForms) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ // Set supported bin range so that the used card is unsupported.
+ std::vector<std::pair<int, int>> supported_card_bin_ranges{
+ std::make_pair(34, 34), std::make_pair(300, 305)};
+ payments_client_->SetSupportedBINRanges(supported_card_bin_ranges);
+
+ // Set up our credit card form data without any non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions().with_split_names(true));
+ // Use the two same forms for FormsSeen to mock the dynamic change forms.
+ FormsSeen(std::vector<FormData>(2, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().from_dynamic_change_form);
+}
+
+// Tests that |from_dynamic_change_form| is correctly sent to AutofillClient
+// when GetDetailsForSaveCard failed and falling back to local save.
+TEST_F(
+ CreditCardSaveManagerTest,
+ Local_GetDetailsForSaveCardFails_SaveCreditCardOptions_WithDynamicForms) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ // Anything other than "en-US" will cause GetUploadDetails to return a failure
+ // response.
+ credit_card_save_manager_->SetAppLocale("pt-BR");
+
+ // Create, fill and submit an address form in order to establish a recent
+ // profile which can be selected for the upload request.
+ FormData address_form;
+ test::CreateTestAddressFormData(&address_form);
+ FormsSeen(std::vector<FormData>(1, address_form));
+ ExpectUniqueFillableFormParsedUkm();
+
+ ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data without any non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions().with_split_names(true));
+ // Use the two same forms for FormsSeen to mock the dynamic change forms.
+ FormsSeen(std::vector<FormData>(2, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().from_dynamic_change_form);
+}
+
+// Tests that |from_dynamic_change_form| is correctly sent to AutofillClient
+// when offering upload save.
+TEST_F(CreditCardSaveManagerTest,
+ Upload_SaveCreditCardOptions_WithDynamicForms) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
+ // Create, fill and submit an address form in order to establish a recent
+ // profile which can be selected for the upload request.
+ FormData address_form;
+ test::CreateTestAddressFormData(&address_form);
+ FormsSeen(std::vector<FormData>(1, address_form));
+ ExpectUniqueFillableFormParsedUkm();
+
+ ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data without any non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions().with_split_names(true));
+ // Use the two same forms for FormsSeen to mock the dynamic change forms.
+ FormsSeen(std::vector<FormData>(2, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_TRUE(
+ autofill_client_.get_save_credit_card_options().from_dynamic_change_form);
+}
+
+// Tests that |from_dynamic_change_form| is not sent to AutofillClient when the
+// form is not dynamically changing.
+TEST_F(CreditCardSaveManagerTest, SaveCreditCardOptions_WithoutDynamicForms) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+
+ // Set up our credit card form data without any non_focusable form field.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form,
+ CreditCardFormOptions().with_split_names(true));
+ // Only using one form for FormsSeen will not be treated as dynamic change
+ // form.
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo");
+ credit_card_form.fields[1].value = ASCIIToUTF16("Master");
+ credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[4].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[5].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+ EXPECT_FALSE(
+ autofill_client_.get_save_credit_card_options().from_dynamic_change_form);
}
// Tests that a credit card inferred from a form with a credit card first and
@@ -2720,7 +2960,37 @@ TEST_F(
}
TEST_F(CreditCardSaveManagerTest,
- UploadCreditCard_RequestExpirationDateIfTestingExperimentOn) {
+ UploadCreditCard_DoNotRequestExpirationDate_EditableExpDateOff) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillUpstreamEditableExpirationDate);
+ // Create, fill and submit an address form in order to establish a recent
+ // profile which can be selected for the upload request.
+ FormData address_form;
+ test::CreateTestAddressFormData(&address_form);
+ FormsSeen(std::vector<FormData>(1, address_form));
+ ManuallyFillAddressForm("John", "Smith", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("John Smith");
+ credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[2].value = ASCIIToUTF16("");
+ credit_card_form.fields[3].value = ASCIIToUTF16("");
+ credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
+ EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
+}
+
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_RequestExpirationDateViaExpDateFixFlow) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillUpstreamEditableExpirationDate);
// Create, fill and submit an address form in order to establish a recent
@@ -2936,7 +3206,7 @@ TEST_F(
}
TEST_F(CreditCardSaveManagerTest,
- UploadCreditCard_RequestCardholderNameIfTestingExperimentOn) {
+ UploadCreditCard_RequestCardholderNameViaNameFixFlow) {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillUpstreamAlwaysRequestCardholderName);
@@ -4249,165 +4519,6 @@ TEST_F(CreditCardSaveManagerTest,
payments_client_->upload_card_source_in_request());
}
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloDisallowed) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillUpstreamDisallowElo);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
- FormsSeen(std::vector<FormData>(1, credit_card_form));
-
- // Edit the data, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
- credit_card_form.fields[1].value = ASCIIToUTF16(kEloCardNumber);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // With Elo disallowed, local save should be offered and upload save should
- // not.
- FormSubmitted(credit_card_form);
- EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
- EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that the correct histogram entry was logged.
- histogram_tester.ExpectUniqueSample(
- "Autofill.CreditCardUploadDisallowedForNetwork",
- AutofillMetrics::DISALLOWED_ELO, 1);
-}
-
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloAllowed) {
- scoped_feature_list_.InitAndDisableFeature(
- features::kAutofillUpstreamDisallowElo);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
- FormsSeen(std::vector<FormData>(1, credit_card_form));
-
- // Edit the data, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
- credit_card_form.fields[1].value = ASCIIToUTF16(kEloCardNumber);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // With the feature flag off, the Elo card should be allowed to be uploaded as
- // normal.
- FormSubmitted(credit_card_form);
- EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
- EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that no histogram entry was logged.
- histogram_tester.ExpectTotalCount(
- "Autofill.CreditCardUploadDisallowedForNetwork", 0);
-}
-
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_JcbDisallowed) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillUpstreamDisallowJcb);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
- FormsSeen(std::vector<FormData>(1, credit_card_form));
-
- // Edit the data, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
- credit_card_form.fields[1].value = ASCIIToUTF16(kJcbCardNumber);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // With JCB disallowed, local save should be offered and upload save should
- // not.
- FormSubmitted(credit_card_form);
- EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
- EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that the correct histogram entry was logged.
- histogram_tester.ExpectUniqueSample(
- "Autofill.CreditCardUploadDisallowedForNetwork",
- AutofillMetrics::DISALLOWED_JCB, 1);
-}
-
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_JcbAllowed) {
- scoped_feature_list_.InitAndDisableFeature(
- features::kAutofillUpstreamDisallowJcb);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
- FormsSeen(std::vector<FormData>(1, credit_card_form));
-
- // Edit the data, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
- credit_card_form.fields[1].value = ASCIIToUTF16(kJcbCardNumber);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // With the feature flag off, the JCB card should be allowed to be uploaded as
- // normal.
- FormSubmitted(credit_card_form);
- EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
- EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that no histogram entry was logged.
- histogram_tester.ExpectTotalCount(
- "Autofill.CreditCardUploadDisallowedForNetwork", 0);
-}
-
-// We can't tell what network a card is until *after* FormDataImporter imports
-// it, making it possible to deny upload save for a pre-existing local card.
-// This test ensures that we do not offer local save (again) for the card that
-// FormDataImporter imported.
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_DisallowedLocalCard) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillUpstreamDisallowElo);
-
- // Add a local credit card that will match what we will enter below.
- CreditCard local_card;
- test::SetCreditCardInfo(&local_card, "Flo Master", kEloCardNumber,
- NextMonth().c_str(), NextYear().c_str(), "1");
- local_card.set_record_type(CreditCard::LOCAL_CARD);
- personal_data_.AddCreditCard(local_card);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, CreditCardFormOptions());
- FormsSeen(std::vector<FormData>(1, credit_card_form));
-
- // Edit the data, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
- credit_card_form.fields[1].value = ASCIIToUTF16(kEloCardNumber);
- credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
- credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // The card is disallowed, but because it is already a local card, local save
- // should not be offered again.
- FormSubmitted(credit_card_form);
- EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled());
- EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that the correct histogram entry was logged.
- histogram_tester.ExpectUniqueSample(
- "Autofill.CreditCardUploadDisallowedForNetwork",
- AutofillMetrics::DISALLOWED_ELO, 1);
-}
-
// Tests that a card with some strikes (but not max strikes) should still show
// the save bubble/infobar.
TEST_F(CreditCardSaveManagerTest,
@@ -4975,8 +5086,6 @@ TEST_F(CreditCardSaveManagerTest,
// Tests that if a card doesn't fall in any of the supported bin ranges, local
// save is offered rather than upload save.
TEST_F(CreditCardSaveManagerTest, UploadSaveNotOfferedForUnsupportedCard) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillDoNotUploadSaveUnsupportedCards);
std::vector<std::pair<int, int>> supported_card_bin_ranges{
std::make_pair(4111, 4113), std::make_pair(34, 34),
std::make_pair(300, 305)};
@@ -5003,8 +5112,6 @@ TEST_F(CreditCardSaveManagerTest, UploadSaveNotOfferedForUnsupportedCard) {
// Tests that if a card doesn't fall in any of the supported bin ranges, but is
// already saved, then local save is not offered.
TEST_F(CreditCardSaveManagerTest, LocalSaveNotOfferedForSavedUnsupportedCard) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillDoNotUploadSaveUnsupportedCards);
std::vector<std::pair<int, int>> supported_card_bin_ranges{
std::make_pair(4111, 4113), std::make_pair(34, 34),
std::make_pair(300, 305)};
@@ -5037,8 +5144,6 @@ TEST_F(CreditCardSaveManagerTest, LocalSaveNotOfferedForSavedUnsupportedCard) {
// Tests that if a card falls in one of the supported bin ranges, upload save
// is offered.
TEST_F(CreditCardSaveManagerTest, UploadSaveOfferedForSupportedCard) {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillDoNotUploadSaveUnsupportedCards);
// Set supported BIN ranges.
std::vector<std::pair<int, int>> supported_card_bin_ranges{
std::make_pair(4111, 4113)};
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.cc b/chromium/components/autofill/core/browser/payments/full_card_request.cc
index 0c08b8f2107..2d8be66ebc5 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.cc
@@ -89,8 +89,8 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
card.ShouldUpdateExpiration(AutofillClock::Now()));
if (should_unmask_card_) {
payments_client_->Prepare();
- request_->billing_customer_number = GetBillingCustomerId(
- personal_data_manager_, /*should_log_validity=*/true);
+ request_->billing_customer_number =
+ GetBillingCustomerId(personal_data_manager_);
}
request_->fido_assertion_info = std::move(fido_assertion_info);
@@ -114,23 +114,25 @@ bool FullCardRequest::IsGettingFullCard() const {
return !!request_;
}
-void FullCardRequest::OnUnmaskResponse(const UnmaskResponse& response) {
- if (!response.exp_month.empty())
- request_->card.SetRawInfo(CREDIT_CARD_EXP_MONTH, response.exp_month);
+void FullCardRequest::OnUnmaskPromptAccepted(
+ const UserProvidedUnmaskDetails& user_response) {
+ if (!user_response.exp_month.empty())
+ request_->card.SetRawInfo(CREDIT_CARD_EXP_MONTH, user_response.exp_month);
- if (!response.exp_year.empty())
- request_->card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, response.exp_year);
+ if (!user_response.exp_year.empty())
+ request_->card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ user_response.exp_year);
if (request_->card.record_type() == CreditCard::LOCAL_CARD &&
!request_->card.guid().empty() &&
- (!response.exp_month.empty() || !response.exp_year.empty())) {
+ (!user_response.exp_month.empty() || !user_response.exp_year.empty())) {
personal_data_manager_->UpdateCreditCard(request_->card);
}
if (!should_unmask_card_) {
if (result_delegate_)
result_delegate_->OnFullCardRequestSucceeded(*this, request_->card,
- response.cvc);
+ user_response.cvc);
if (ui_delegate_)
ui_delegate_->OnUnmaskVerificationResult(AutofillClient::SUCCESS);
Reset();
@@ -138,7 +140,7 @@ void FullCardRequest::OnUnmaskResponse(const UnmaskResponse& response) {
return;
}
- request_->user_response = response;
+ request_->user_response = user_response;
if (!request_->risk_data.empty())
SendUnmaskCardRequest();
}
@@ -164,8 +166,9 @@ void FullCardRequest::SendUnmaskCardRequest() {
weak_ptr_factory_.GetWeakPtr()));
}
-void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) {
+void FullCardRequest::OnDidGetRealPan(
+ AutofillClient::PaymentsRpcResult result,
+ payments::PaymentsClient::UnmaskResponseDetails& response_details) {
AutofillMetrics::LogRealPanDuration(
AutofillClock::Now() - real_pan_request_timestamp_, result);
@@ -188,14 +191,19 @@ void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
}
case AutofillClient::SUCCESS: {
- DCHECK(!real_pan.empty());
+ DCHECK(!response_details.real_pan.empty());
request_->card.set_record_type(CreditCard::FULL_SERVER_CARD);
- request_->card.SetNumber(base::UTF8ToUTF16(real_pan));
+ request_->card.SetNumber(base::UTF8ToUTF16(response_details.real_pan));
request_->card.SetServerStatus(CreditCard::OK);
if (request_->user_response.should_store_pan)
personal_data_manager_->UpdateServerCreditCard(request_->card);
+ // TODO(crbug/949269): Once |fido_opt_in| is added to
+ // UserProvidedUnmaskDetails, clear out |creation_options| from
+ // |response_details_| if |user_response.fido_opt_in| was not set to true
+ // to avoid an unwanted registration prompt.
+ unmask_response_details_ = response_details;
if (result_delegate_)
result_delegate_->OnFullCardRequestSucceeded(
*this, request_->card, request_->user_response.cvc);
@@ -216,6 +224,7 @@ void FullCardRequest::Reset() {
ui_delegate_ = nullptr;
request_.reset();
should_unmask_card_ = false;
+ unmask_response_details_ = payments::PaymentsClient::UnmaskResponseDetails();
}
} // namespace payments
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.h b/chromium/components/autofill/core/browser/payments/full_card_request.h
index 7bde432873b..9d5338b3c3d 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.h
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.h
@@ -89,8 +89,14 @@ class FullCardRequest final : public CardUnmaskDelegate {
bool IsGettingFullCard() const;
// Called by the payments client when a card has been unmasked.
- void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan);
+ void OnDidGetRealPan(
+ AutofillClient::PaymentsRpcResult result,
+ payments::PaymentsClient::UnmaskResponseDetails& response_details);
+
+ payments::PaymentsClient::UnmaskResponseDetails unmask_response_details()
+ const {
+ return unmask_response_details_;
+ }
base::TimeTicks form_parsed_timestamp() const {
return form_parsed_timestamp_;
@@ -115,7 +121,8 @@ class FullCardRequest final : public CardUnmaskDelegate {
base::Value fido_assertion_info);
// CardUnmaskDelegate:
- void OnUnmaskResponse(const UnmaskResponse& response) override;
+ void OnUnmaskPromptAccepted(
+ const UserProvidedUnmaskDetails& user_response) override;
void OnUnmaskPromptClosed() override;
// Called by autofill client when the risk data has been loaded.
@@ -156,6 +163,9 @@ class FullCardRequest final : public CardUnmaskDelegate {
// The timestamp when the form is parsed. For histograms.
base::TimeTicks form_parsed_timestamp_;
+ // Includes all details from GetRealPan response.
+ payments::PaymentsClient::UnmaskResponseDetails unmask_response_details_;
+
// Enables destroying FullCardRequest while CVC prompt is showing or a server
// communication is pending.
base::WeakPtrFactory<FullCardRequest> weak_ptr_factory_{this};
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
index 4919848e8b1..f4fb8e536a2 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -102,11 +102,12 @@ class FullCardRequestTest : public testing::Test {
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) {
- request_->OnDidGetRealPan(result, real_pan);
+ payments::PaymentsClient::UnmaskResponseDetails response;
+ request_->OnDidGetRealPan(result, response.with_real_pan(real_pan));
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
MockPersonalDataManager personal_data_;
MockResultDelegate result_delegate_;
MockUIDelegate ui_delegate_;
@@ -151,9 +152,9 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaCvc) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -189,9 +190,9 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForLocalCard) {
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -212,9 +213,9 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForFullServerCard) {
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -239,11 +240,11 @@ TEST_F(FullCardRequestTest,
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- response.exp_year = base::ASCIIToUTF16("2051");
- response.exp_month = base::ASCIIToUTF16("12");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ details.exp_year = base::ASCIIToUTF16("2051");
+ details.exp_month = base::ASCIIToUTF16("12");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -271,11 +272,11 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForExpiredFullServerCard) {
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- response.exp_year = base::ASCIIToUTF16("2051");
- response.exp_month = base::ASCIIToUTF16("12");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ details.exp_year = base::ASCIIToUTF16("2051");
+ details.exp_month = base::ASCIIToUTF16("12");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -315,15 +316,15 @@ TEST_F(FullCardRequestTest, SecondRequestOkAfterFirstFinished) {
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
card_unmask_delegate()->OnUnmaskPromptClosed();
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- card_unmask_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -353,9 +354,9 @@ TEST_F(FullCardRequestTest, PermanentFailure) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::PERMANENT_FAILURE, "");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -372,9 +373,9 @@ TEST_F(FullCardRequestTest, NetworkError) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::NETWORK_ERROR, "");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -391,9 +392,9 @@ TEST_F(FullCardRequestTest, TryAgainFailureGiveUp) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::TRY_AGAIN_FAILURE, "");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -417,12 +418,12 @@ TEST_F(FullCardRequestTest, TryAgainFailureRetry) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("789");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("789");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::TRY_AGAIN_FAILURE, "");
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -442,11 +443,11 @@ TEST_F(FullCardRequestTest, UpdateExpDateForMaskedServerCard) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- response.exp_month = base::ASCIIToUTF16("12");
- response.exp_year = base::ASCIIToUTF16("2050");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ details.exp_month = base::ASCIIToUTF16("12");
+ details.exp_year = base::ASCIIToUTF16("2050");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -468,11 +469,11 @@ TEST_F(FullCardRequestTest, UpdateExpDateForFullServerCard) {
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- response.exp_month = base::ASCIIToUTF16("12");
- response.exp_year = base::ASCIIToUTF16("2050");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ details.exp_month = base::ASCIIToUTF16("12");
+ details.exp_year = base::ASCIIToUTF16("2050");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -500,11 +501,11 @@ TEST_F(FullCardRequestTest, UpdateExpDateForLocalCard) {
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- response.exp_month = base::ASCIIToUTF16("12");
- response.exp_year = base::ASCIIToUTF16("2051");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ details.exp_month = base::ASCIIToUTF16("12");
+ details.exp_year = base::ASCIIToUTF16("2051");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -526,12 +527,12 @@ TEST_F(FullCardRequestTest, SaveRealPan) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- response.exp_month = base::ASCIIToUTF16("12");
- response.exp_year = base::ASCIIToUTF16("2050");
- response.should_store_pan = true;
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ details.exp_month = base::ASCIIToUTF16("12");
+ details.exp_year = base::ASCIIToUTF16("2050");
+ details.should_store_pan = true;
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -551,9 +552,9 @@ TEST_F(FullCardRequestTest, UnmaskForPaymentRequest) {
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
AutofillClient::UNMASK_FOR_PAYMENT_REQUEST,
result_delegate()->AsWeakPtr(), ui_delegate()->AsWeakPtr());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
card_unmask_delegate()->OnUnmaskPromptClosed();
}
@@ -579,9 +580,9 @@ TEST_F(FullCardRequestTest, IsGettingFullCardForMaskedServerCard) {
EXPECT_TRUE(request()->IsGettingFullCard());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
EXPECT_TRUE(request()->IsGettingFullCard());
@@ -616,9 +617,9 @@ TEST_F(FullCardRequestTest, IsGettingFullCardForLocalCard) {
EXPECT_TRUE(request()->IsGettingFullCard());
- CardUnmaskDelegate::UnmaskResponse response;
- response.cvc = base::ASCIIToUTF16("123");
- card_unmask_delegate()->OnUnmaskResponse(response);
+ CardUnmaskDelegate::UserProvidedUnmaskDetails details;
+ details.cvc = base::ASCIIToUTF16("123");
+ card_unmask_delegate()->OnUnmaskPromptAccepted(details);
EXPECT_FALSE(request()->IsGettingFullCard());
diff --git a/chromium/components/autofill/core/browser/payments/legal_message_line_unittest.cc b/chromium/components/autofill/core/browser/payments/legal_message_line_unittest.cc
index d5a10a1b5cc..b126d82d075 100644
--- a/chromium/components/autofill/core/browser/payments/legal_message_line_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/legal_message_line_unittest.cc
@@ -11,6 +11,7 @@
#include "base/json/json_reader.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "components/autofill/core/browser/payments/test_legal_message_line.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,31 +19,6 @@ namespace autofill {
using Link = LegalMessageLine::Link;
-// A legal message line that allows for modifications.
-class TestLegalMessageLine : public LegalMessageLine {
- public:
- TestLegalMessageLine() {}
-
- TestLegalMessageLine(const std::string& ascii_text) { set_text(ascii_text); }
-
- TestLegalMessageLine(const std::string& ascii_text,
- const std::vector<Link>& links) {
- set_text(ascii_text);
- set_links(links);
- }
-
- ~TestLegalMessageLine() override {}
-
- void set_text(const std::string& ascii_text) {
- text_ = base::ASCIIToUTF16(ascii_text);
- }
-
- void set_links(const std::vector<Link>& links) { links_ = links; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestLegalMessageLine);
-};
-
// A test case.
struct TestCase {
std::string message_json;
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
index b78e7c8bc56..e1441ba421d 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -16,9 +16,10 @@
#include "base/guid.h"
#include "base/metrics/metrics_hashes.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -49,8 +50,6 @@
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
#include "components/sync/driver/test_sync_service.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -69,9 +68,6 @@ class LocalCardMigrationManagerTest : public testing::Test {
personal_data_.SetPrefService(autofill_client_.GetPrefs());
personal_data_.SetSyncServiceForTest(&sync_service_);
autofill_driver_.reset(new TestAutofillDriver());
- request_context_ = new net::TestURLRequestContextGetter(
- base::ThreadTaskRunnerHandle::Get());
- autofill_driver_->SetURLRequestContext(request_context_.get());
payments_client_ = new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(),
autofill_client_.GetIdentityManager(), &personal_data_);
@@ -111,8 +107,6 @@ class LocalCardMigrationManagerTest : public testing::Test {
personal_data_.SetPrefService(nullptr);
personal_data_.ClearCreditCards();
-
- request_context_ = nullptr;
}
void FormsSeen(const std::vector<FormData>& forms) {
@@ -311,11 +305,10 @@ class LocalCardMigrationManagerTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
- scoped_refptr<net::TestURLRequestContextGetter> request_context_;
TestPersonalDataManager personal_data_;
MockAutocompleteHistoryManager autocomplete_history_manager_;
syncer::TestSyncService sync_service_;
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index 01424172900..b097a05e500 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -57,6 +57,9 @@ const char kUnmaskCardRequestFormat[] =
"requestContentType=application/json; charset=utf-8&request=%s"
"&s7e_13_cvc=%s";
+const char kOptChangeRequestPath[] =
+ "payments/apis/chromepaymentsservice/autofillauthoptchange";
+
const char kGetUploadDetailsRequestPath[] =
"payments/apis/chromepaymentsservice/getdetailsforsavecard";
@@ -322,10 +325,11 @@ class GetUnmaskDetailsRequest : public PaymentsRequest {
class UnmaskCardRequest : public PaymentsRequest {
public:
- UnmaskCardRequest(const PaymentsClient::UnmaskRequestDetails& request_details,
- const bool full_sync_enabled,
- base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
- const std::string&)> callback)
+ UnmaskCardRequest(
+ const PaymentsClient::UnmaskRequestDetails& request_details,
+ const bool full_sync_enabled,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ PaymentsClient::UnmaskResponseDetails&)> callback)
: request_details_(request_details),
full_sync_enabled_(full_sync_enabled),
callback_(std::move(callback)) {
@@ -372,6 +376,10 @@ class UnmaskCardRequest : public PaymentsRequest {
if (base::StringToInt(request_details_.user_response.exp_year, &value))
request_dict.SetKey("expiration_year", base::Value(value));
+ request_dict.SetKey(
+ "opt_in_fido_auth",
+ base::Value(request_details_.user_response.enable_fido_auth));
+
if (request_details_.fido_assertion_info.is_dict()) {
request_dict.SetKey("fido_assertion_info",
std::move(request_details_.fido_assertion_info));
@@ -404,26 +412,108 @@ class UnmaskCardRequest : public PaymentsRequest {
void ParseResponse(const base::Value& response) override {
const auto* pan = response.FindStringKey("pan");
- real_pan_ = pan ? *pan : std::string();
+ response_details_.real_pan = pan ? *pan : std::string();
+
+ const auto* creation_options = response.FindKeyOfType(
+ "fido_creation_options", base::Value::Type::DICTIONARY);
+ if (creation_options)
+ response_details_.fido_creation_options = creation_options->Clone();
}
- bool IsResponseComplete() override { return !real_pan_.empty(); }
+ bool IsResponseComplete() override {
+ return !response_details_.real_pan.empty();
+ }
void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
- std::move(callback_).Run(result, real_pan_);
+ std::move(callback_).Run(result, response_details_);
}
private:
PaymentsClient::UnmaskRequestDetails request_details_;
const bool full_sync_enabled_;
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
- const std::string&)>
+ PaymentsClient::UnmaskResponseDetails&)>
callback_;
- std::string real_pan_;
+ PaymentsClient::UnmaskResponseDetails response_details_;
DISALLOW_COPY_AND_ASSIGN(UnmaskCardRequest);
};
+class OptChangeRequest : public PaymentsRequest {
+ public:
+ OptChangeRequest(
+ const PaymentsClient::OptChangeRequestDetails& request_details,
+ OptChangeCallback callback,
+ const bool full_sync_enabled)
+ : request_details_(request_details),
+ callback_(std::move(callback)),
+ full_sync_enabled_(full_sync_enabled) {}
+ ~OptChangeRequest() override {}
+
+ std::string GetRequestUrlPath() override { return kOptChangeRequestPath; }
+
+ std::string GetRequestContentType() override { return "application/json"; }
+
+ std::string GetRequestContent() override {
+ base::Value request_dict(base::Value::Type::DICTIONARY);
+ base::Value context(base::Value::Type::DICTIONARY);
+ context.SetKey("language_code", base::Value(request_details_.app_locale));
+ context.SetKey("billable_service",
+ base::Value(kUnmaskCardBillableServiceNumber));
+ request_dict.SetKey("context", std::move(context));
+
+ if (ShouldUseActiveSignedInAccount()) {
+ base::Value chrome_user_context(base::Value::Type::DICTIONARY);
+ chrome_user_context.SetKey("full_sync_enabled",
+ base::Value(full_sync_enabled_));
+ request_dict.SetKey("chrome_user_context",
+ std::move(chrome_user_context));
+ }
+
+ request_dict.SetKey("opt_in", base::Value(request_details_.opt_in));
+
+ if (request_details_.fido_authenticator_response.is_dict()) {
+ request_dict.SetKey(
+ "fido_authenticator_response",
+ std::move(request_details_.fido_authenticator_response));
+ }
+
+ std::string request_content;
+ base::JSONWriter::Write(request_dict, &request_content);
+ VLOG(3) << "autofillauthoptchange request body: " << request_content;
+ return request_content;
+ }
+
+ void ParseResponse(const base::Value& response) override {
+ const auto* user_is_opted_in =
+ response.FindKeyOfType("user_is_opted_in", base::Value::Type::BOOLEAN);
+ if (user_is_opted_in)
+ user_is_opted_in_ = user_is_opted_in->GetBool();
+
+ const auto* fido_creation_options = response.FindKeyOfType(
+ "fido_creation_options", base::Value::Type::DICTIONARY);
+ if (fido_creation_options)
+ fido_creation_options_ = fido_creation_options->Clone();
+ }
+
+ bool IsResponseComplete() override { return user_is_opted_in_.has_value(); }
+
+ void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
+ std::move(callback_).Run(
+ result, user_is_opted_in_.value_or(!request_details_.opt_in),
+ std::move(fido_creation_options_));
+ }
+
+ private:
+ PaymentsClient::OptChangeRequestDetails request_details_;
+ OptChangeCallback callback_;
+ const bool full_sync_enabled_;
+ base::Optional<bool> user_is_opted_in_;
+ base::Value fido_creation_options_;
+
+ DISALLOW_COPY_AND_ASSIGN(OptChangeRequest);
+};
+
class GetUploadDetailsRequest : public PaymentsRequest {
public:
GetUploadDetailsRequest(
@@ -864,6 +954,32 @@ PaymentsClient::UnmaskRequestDetails::UnmaskRequestDetails(
}
PaymentsClient::UnmaskRequestDetails::~UnmaskRequestDetails() {}
+PaymentsClient::UnmaskResponseDetails::UnmaskResponseDetails() {}
+PaymentsClient::UnmaskResponseDetails::UnmaskResponseDetails(
+ const UnmaskResponseDetails& other) {
+ *this = other;
+}
+PaymentsClient::UnmaskResponseDetails::~UnmaskResponseDetails() {}
+PaymentsClient::UnmaskResponseDetails& PaymentsClient::UnmaskResponseDetails::
+operator=(const PaymentsClient::UnmaskResponseDetails& other) {
+ real_pan = other.real_pan;
+ if (other.fido_creation_options.has_value()) {
+ fido_creation_options = other.fido_creation_options->Clone();
+ } else {
+ fido_creation_options.reset();
+ }
+ return *this;
+}
+
+PaymentsClient::OptChangeRequestDetails::OptChangeRequestDetails() {}
+PaymentsClient::OptChangeRequestDetails::OptChangeRequestDetails(
+ const OptChangeRequestDetails& other) {
+ app_locale = other.app_locale;
+ opt_in = other.opt_in;
+ fido_authenticator_response = other.fido_authenticator_response.Clone();
+}
+PaymentsClient::OptChangeRequestDetails::~OptChangeRequestDetails() {}
+
PaymentsClient::UploadRequestDetails::UploadRequestDetails() {}
PaymentsClient::UploadRequestDetails::UploadRequestDetails(
const UploadRequestDetails& other) = default;
@@ -903,12 +1019,20 @@ void PaymentsClient::GetUnmaskDetails(GetUnmaskDetailsCallback callback,
void PaymentsClient::UnmaskCard(
const PaymentsClient::UnmaskRequestDetails& request_details,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
- const std::string&)> callback) {
+ PaymentsClient::UnmaskResponseDetails&)> callback) {
IssueRequest(
std::make_unique<UnmaskCardRequest>(
request_details, account_info_getter_->IsSyncFeatureEnabled(),
std::move(callback)),
- true);
+ /*authenticate=*/true);
+}
+
+void PaymentsClient::OptChange(const OptChangeRequestDetails request_details,
+ OptChangeCallback callback) {
+ IssueRequest(std::make_unique<OptChangeRequest>(
+ request_details, std::move(callback),
+ account_info_getter_->IsSyncFeatureEnabled()),
+ /*authenticate=*/true);
}
void PaymentsClient::GetUploadDetails(
@@ -927,7 +1051,7 @@ void PaymentsClient::GetUploadDetails(
addresses, detected_values, active_experiments,
account_info_getter_->IsSyncFeatureEnabled(), app_locale,
std::move(callback), billable_service_number, upload_card_source),
- false);
+ /*authenticate=*/false);
}
void PaymentsClient::UploadCard(
@@ -938,7 +1062,7 @@ void PaymentsClient::UploadCard(
std::make_unique<UploadCardRequest>(
request_details, account_info_getter_->IsSyncFeatureEnabled(),
std::move(callback)),
- true);
+ /*authenticate=*/true);
}
void PaymentsClient::MigrateCards(
@@ -985,21 +1109,18 @@ void PaymentsClient::IssueRequest(std::unique_ptr<PaymentsRequest> request,
void PaymentsClient::InitializeResourceRequest() {
resource_request_ = std::make_unique<network::ResourceRequest>();
resource_request_->url = GetRequestUrl(request_->GetRequestUrlPath());
- resource_request_->load_flags = net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DISABLE_CACHE;
+ resource_request_->load_flags = net::LOAD_DISABLE_CACHE;
+ resource_request_->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request_->method = "POST";
- if (base::FeatureList::IsEnabled(
- features::kAutofillSendExperimentIdsInPaymentsRPCs)) {
- // Add Chrome experiment state to the request headers.
- net::HttpRequestHeaders headers;
- // User is always signed-in to be able to upload card to Google Payments.
- variations::AppendVariationsHeader(
- resource_request_->url,
- is_off_the_record_ ? variations::InIncognito::kYes
- : variations::InIncognito::kNo,
- variations::SignedIn::kYes, resource_request_.get());
- }
+
+ // Add Chrome experiment state to the request headers.
+ net::HttpRequestHeaders headers;
+ // User is always signed-in to be able to upload card to Google Payments.
+ variations::AppendVariationsHeader(
+ resource_request_->url,
+ is_off_the_record_ ? variations::InIncognito::kYes
+ : variations::InIncognito::kNo,
+ variations::SignedIn::kYes, resource_request_.get());
}
void PaymentsClient::OnSimpleLoaderComplete(
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h
index 72420713ff1..07523979cc2 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/payments_client.h
@@ -53,6 +53,11 @@ typedef base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
AutofillClient::UnmaskDetails&)>
GetUnmaskDetailsCallback;
+// Callback type for OptChange callback.
+typedef base::OnceCallback<
+ void(AutofillClient::PaymentsRpcResult, bool, base::Value)>
+ OptChangeCallback;
+
// Billable service number is defined in Payments server to distinguish
// different requests.
const int kUnmaskCardBillableServiceNumber = 70154;
@@ -85,10 +90,38 @@ class PaymentsClient {
AutofillClient::UnmaskCardReason reason;
CreditCard card;
std::string risk_data;
- CardUnmaskDelegate::UnmaskResponse user_response;
+ CardUnmaskDelegate::UserProvidedUnmaskDetails user_response;
base::Value fido_assertion_info;
};
+ // Information retrieved from an UnmaskRequest.
+ struct UnmaskResponseDetails {
+ UnmaskResponseDetails();
+ UnmaskResponseDetails(const UnmaskResponseDetails& other);
+ ~UnmaskResponseDetails();
+ UnmaskResponseDetails& operator=(const UnmaskResponseDetails& other);
+
+ UnmaskResponseDetails& with_real_pan(std::string r) {
+ real_pan = r;
+ return *this;
+ }
+
+ std::string real_pan;
+ base::Optional<base::Value> fido_creation_options;
+ };
+
+ // Information required to either opt-in or opt-out a user for FIDO
+ // Authentication.
+ struct OptChangeRequestDetails {
+ OptChangeRequestDetails();
+ OptChangeRequestDetails(const OptChangeRequestDetails& other);
+ ~OptChangeRequestDetails();
+
+ std::string app_locale;
+ bool opt_in;
+ base::Value fido_authenticator_response;
+ };
+
// A collection of the information required to make a credit card upload
// request.
struct UploadRequestDetails {
@@ -161,15 +194,20 @@ class PaymentsClient {
void Prepare();
// The user has interacted with a credit card form and may attempt to unmask a
- // card. This request returns what method of authentication is required, along
- // with any information to facilitate the authentication.
+ // card. This request returns what method of authentication is suggested,
+ // along with any information to facilitate the authentication.
virtual void GetUnmaskDetails(GetUnmaskDetailsCallback callback,
const std::string& app_locale);
// The user has attempted to unmask a card with the given cvc.
void UnmaskCard(const UnmaskRequestDetails& request_details,
base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
- const std::string&)> callback);
+ UnmaskResponseDetails&)> callback);
+
+ // Opts-in or opts-out the user to use FIDO authentication for card unmasking
+ // on this device.
+ void OptChange(const OptChangeRequestDetails request_details,
+ OptChangeCallback callback);
// Determine if the user meets the Payments service's conditions for upload.
// The service uses |addresses| (from which names and phone numbers are
diff --git a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
index 90710eff8f2..39f0e812a59 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -15,7 +15,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "components/autofill/core/browser/autofill_experiments.h"
@@ -90,7 +90,7 @@ class PaymentsClientTest : public testing::Test {
result_ = AutofillClient::NONE;
server_id_.clear();
- real_pan_.clear();
+ unmask_response_details_ = nullptr;
legal_message_.reset();
has_variations_header_ = false;
@@ -112,21 +112,11 @@ class PaymentsClientTest : public testing::Test {
void TearDown() override { client_.reset(); }
- void EnableAutofillSendExperimentIdsInPaymentsRPCs() {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillSendExperimentIdsInPaymentsRPCs);
- }
-
void EnableAutofillGetPaymentsIdentityFromSync() {
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillGetPaymentsIdentityFromSync);
}
- void DisableAutofillSendExperimentIdsInPaymentsRPCs() {
- scoped_feature_list_.InitAndDisableFeature(
- features::kAutofillSendExperimentIdsInPaymentsRPCs);
- }
-
// Registers a field trial with the specified name and group and an associated
// google web property variation id.
void CreateFieldTrialWithId(const std::string& trial_name,
@@ -145,9 +135,18 @@ class PaymentsClientTest : public testing::Test {
}
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) {
+ PaymentsClient::UnmaskResponseDetails& response) {
result_ = result;
- real_pan_ = real_pan;
+ unmask_response_details_ = &response;
+ }
+
+ void OnDidGetOptChangeResult(AutofillClient::PaymentsRpcResult result,
+ bool user_is_opted_in,
+ base::Value fido_creation_options) {
+ result_ = result;
+ user_is_opted_in_ = user_is_opted_in;
+ if (fido_creation_options.is_dict())
+ fido_creation_options_ = fido_creation_options.Clone();
}
void OnDidGetUploadDetails(
@@ -168,10 +167,11 @@ class PaymentsClientTest : public testing::Test {
void OnDidMigrateLocalCards(
AutofillClient::PaymentsRpcResult result,
- std::unique_ptr<std::unordered_map<std::string, std::string>> save_result,
+ std::unique_ptr<std::unordered_map<std::string, std::string>>
+ migration_save_results,
const std::string& display_text) {
result_ = result;
- save_result_ = std::move(save_result);
+ migration_save_results_ = std::move(migration_save_results);
display_text_ = display_text;
}
@@ -207,6 +207,17 @@ class PaymentsClientTest : public testing::Test {
weak_ptr_factory_.GetWeakPtr()));
}
+ // If |opt_in| is set to true, then opts the user in to use FIDO
+ // authentication for card unmasking. Otherwise opts the user out.
+ void StartOptChangeRequest(bool opt_in) {
+ PaymentsClient::OptChangeRequestDetails request_details;
+ request_details.opt_in = opt_in;
+ client_->OptChange(
+ request_details,
+ base::BindOnce(&PaymentsClientTest::OnDidGetOptChangeResult,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
// Issue a GetUploadDetails request.
void StartGettingUploadDetails(
PaymentsClient::UploadCardSource upload_card_source =
@@ -286,15 +297,28 @@ class PaymentsClientTest : public testing::Test {
AutofillClient::PaymentsRpcResult result_;
AutofillClient::UnmaskDetails* unmask_details_;
+ // Server ID of a saved card via credit card upload save.
std::string server_id_;
- std::string real_pan_;
+ // Status of the user's FIDO auth opt-in; returned from an OptChange call.
+ base::Optional<bool> user_is_opted_in_;
+ // FIDO auth enrollment creation options; returned from an OptChange call.
+ base::Value fido_creation_options_;
+ // The UnmaskResponseDetails retrieved from an UnmaskRequest. Includes PAN.
+ PaymentsClient::UnmaskResponseDetails* unmask_response_details_ = nullptr;
+ // The legal message returned from a GetDetails upload save preflight call.
std::unique_ptr<base::Value> legal_message_;
+ // A list of card BIN ranges supported by Google Payments, returned from a
+ // GetDetails upload save preflight call.
std::vector<std::pair<int, int>> supported_card_bin_ranges_;
+ // Credit cards to be upload saved during a local credit card migration call.
std::vector<MigratableCreditCard> migratable_credit_cards_;
- std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
+ // A mapping of results from a local credit card migration call.
+ std::unique_ptr<std::unordered_map<std::string, std::string>>
+ migration_save_results_;
+ // A tip message to be displayed during local card migration.
std::string display_text_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
TestPersonalDataManager test_personal_data_;
@@ -371,7 +395,7 @@ TEST_F(PaymentsClientTest, OAuthError) {
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
- EXPECT_TRUE(real_pan_.empty());
+ EXPECT_TRUE(unmask_response_details_->real_pan.empty());
}
TEST_F(PaymentsClientTest,
@@ -390,7 +414,7 @@ TEST_F(PaymentsClientTest, UnmaskSuccessViaCVC) {
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_EQ("1234", real_pan_);
+ EXPECT_EQ("1234", unmask_response_details_->real_pan);
}
TEST_F(PaymentsClientTest, UnmaskSuccessViaFIDO) {
@@ -398,7 +422,20 @@ TEST_F(PaymentsClientTest, UnmaskSuccessViaFIDO) {
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_EQ("1234", real_pan_);
+ EXPECT_EQ("1234", unmask_response_details_->real_pan);
+}
+
+TEST_F(PaymentsClientTest, UnmaskSuccessViaCVCWithCreationOptions) {
+ StartUnmasking(CardUnmaskOptions().with_use_fido(false));
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK,
+ "{ \"pan\": \"1234\", \"fido_creation_options\": "
+ "{\"relying_party_id\": \"google.com\"}}");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_EQ("1234", unmask_response_details_->real_pan);
+ EXPECT_EQ("google.com",
+ *unmask_response_details_->fido_creation_options->FindStringKey(
+ "relying_party_id"));
}
TEST_F(PaymentsClientTest, UnmaskSuccessAccountFromSyncTest) {
@@ -407,7 +444,7 @@ TEST_F(PaymentsClientTest, UnmaskSuccessAccountFromSyncTest) {
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_EQ("1234", real_pan_);
+ EXPECT_EQ("1234", unmask_response_details_->real_pan);
}
TEST_F(PaymentsClientTest, UnmaskIncludesChromeUserContext) {
@@ -488,6 +525,42 @@ TEST_F(PaymentsClientTest, UnmaskLogsBlankCvcLength) {
"Autofill.CardUnmask.CvcLength.ForAutofill", 0, 1);
}
+TEST_F(PaymentsClientTest, OptInSuccess) {
+ StartOptChangeRequest(/*opt_in=*/true);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK, "{ \"user_is_opted_in\": true }");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_TRUE(user_is_opted_in_.value());
+}
+
+TEST_F(PaymentsClientTest, OptInServerUnresponsive) {
+ StartOptChangeRequest(/*opt_in=*/true);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_REQUEST_TIMEOUT, "");
+ EXPECT_EQ(AutofillClient::NETWORK_ERROR, result_);
+ EXPECT_FALSE(user_is_opted_in_.value());
+}
+
+TEST_F(PaymentsClientTest, OptOutSuccess) {
+ StartOptChangeRequest(/*opt_in=*/false);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK, "{ \"user_is_opted_in\": false }");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_FALSE(user_is_opted_in_.value());
+}
+
+TEST_F(PaymentsClientTest, EnrollAttemptReturnsCreationOptions) {
+ StartOptChangeRequest(/*opt_in=*/true);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK,
+ "{ \"user_is_opted_in\": false, \"fido_creation_options\": { "
+ "\"relying_party_id\": \"google.com\"} }");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_FALSE(user_is_opted_in_.value());
+ EXPECT_EQ("google.com",
+ *fido_creation_options_.FindStringKey("relying_party_id"));
+}
+
TEST_F(PaymentsClientTest, GetDetailsSuccess) {
StartGettingUploadDetails();
ReturnResponse(
@@ -635,8 +708,7 @@ TEST_F(PaymentsClientTest, GetUploadDetailsVariationsTest) {
// observe some other field trial list, so reset it.
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
// Note: This needs a base::FieldTrialList instance because it does not use
- // ScopedFeatureList, which provides its own, unlike other tests that do via
- // DisableAutofillSendExperimentIdsInPaymentsRPCs().
+ // ScopedFeatureList, which provides its own, unlike other tests that do.
base::FieldTrialList field_trial_list_(nullptr);
CreateFieldTrialWithId("AutofillTest", "Group", 369);
StartGettingUploadDetails();
@@ -647,21 +719,6 @@ TEST_F(PaymentsClientTest, GetUploadDetailsVariationsTest) {
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
}
-TEST_F(PaymentsClientTest, GetUploadDetailsVariationsTestExperimentFlagOff) {
- // Register a trial and variation id, so that there is data in variations
- // headers. Also, the variations header provider may have been registered to
- // observe some other field trial list, so reset it.
- DisableAutofillSendExperimentIdsInPaymentsRPCs();
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
- CreateFieldTrialWithId("AutofillTest", "Group", 369);
- StartGettingUploadDetails();
-
- // Note that experiment information is stored in X-Client-Data.
- EXPECT_FALSE(HasVariationsHeader());
-
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
-}
-
TEST_F(PaymentsClientTest, GetDetailsIncludeBillableServiceNumber) {
StartGettingUploadDetails();
@@ -765,8 +822,7 @@ TEST_F(PaymentsClientTest, UploadCardVariationsTest) {
// observe some other field trial list, so reset it.
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
// Note: This needs a base::FieldTrialList instance because it does not use
- // ScopedFeatureList, which provides its own, unlike other tests that do via
- // DisableAutofillSendExperimentIdsInPaymentsRPCs().
+ // ScopedFeatureList, which provides its own, unlike other tests that do.
base::FieldTrialList field_trial_list_(nullptr);
CreateFieldTrialWithId("AutofillTest", "Group", 369);
StartUploading(/*include_cvc=*/true);
@@ -778,29 +834,13 @@ TEST_F(PaymentsClientTest, UploadCardVariationsTest) {
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
}
-TEST_F(PaymentsClientTest, UploadCardVariationsTestExperimentFlagOff) {
- // Register a trial and variation id, so that there is data in variations
- // headers. Also, the variations header provider may have been registered to
- // observe some other field trial list, so reset it.
- DisableAutofillSendExperimentIdsInPaymentsRPCs();
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
- CreateFieldTrialWithId("AutofillTest", "Group", 369);
- StartUploading(/*include_cvc=*/true);
-
- // Note that experiment information is stored in X-Client-Data.
- EXPECT_FALSE(HasVariationsHeader());
-
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
-}
-
TEST_F(PaymentsClientTest, UnmaskCardVariationsTest) {
// Register a trial and variation id, so that there is data in variations
// headers. Also, the variations header provider may have been registered to
// observe some other field trial list, so reset it.
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
// Note: This needs a base::FieldTrialList instance because it does not use
- // ScopedFeatureList, which provides its own, unlike other tests that do via
- // DisableAutofillSendExperimentIdsInPaymentsRPCs().
+ // ScopedFeatureList, which provides its own, unlike other tests that do.
base::FieldTrialList field_trial_list_(nullptr);
CreateFieldTrialWithId("AutofillTest", "Group", 369);
StartUnmasking(CardUnmaskOptions());
@@ -812,27 +852,14 @@ TEST_F(PaymentsClientTest, UnmaskCardVariationsTest) {
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
}
-TEST_F(PaymentsClientTest, UnmaskCardVariationsTestExperimentOff) {
- // Register a trial and variation id, so that there is data in variations
- // headers. Also, the variations header provider may have been registered to
- // observe some other field trial list, so reset it.
- DisableAutofillSendExperimentIdsInPaymentsRPCs();
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
- CreateFieldTrialWithId("AutofillTest", "Group", 369);
- StartUnmasking(CardUnmaskOptions());
-
- // Note that experiment information is stored in X-Client-Data.
- EXPECT_FALSE(HasVariationsHeader());
-
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
-}
-
TEST_F(PaymentsClientTest, MigrateCardsVariationsTest) {
// Register a trial and variation id, so that there is data in variations
// headers. Also, the variations header provider may have been registered to
// observe some other field trial list, so reset it.
- EnableAutofillSendExperimentIdsInPaymentsRPCs();
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
+ // Note: This needs a base::FieldTrialList instance because it does not use
+ // ScopedFeatureList, which provides its own, unlike other tests that do.
+ base::FieldTrialList field_trial_list_(nullptr);
CreateFieldTrialWithId("AutofillTest", "Group", 369);
StartMigrating(/*has_cardholder_name=*/true);
IssueOAuthToken();
@@ -843,21 +870,6 @@ TEST_F(PaymentsClientTest, MigrateCardsVariationsTest) {
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
}
-TEST_F(PaymentsClientTest, MigrateCardsVariationsTestExperimentFlagOff) {
- // Register a trial and variation id, so that there is data in variations
- // headers. Also, the variations header provider may have been registered to
- // observe some other field trial list, so reset it.
- DisableAutofillSendExperimentIdsInPaymentsRPCs();
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
- CreateFieldTrialWithId("AutofillTest", "Group", 369);
- StartMigrating(/*has_cardholder_name=*/true);
-
- // Note that experiment information is stored in X-Client-Data.
- EXPECT_FALSE(HasVariationsHeader());
-
- variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
-}
-
TEST_F(PaymentsClientTest, UploadSuccessWithoutServerId) {
StartUploading(/*include_cvc=*/true);
IssueOAuthToken();
@@ -1074,11 +1086,13 @@ TEST_F(PaymentsClientTest, MigrationSuccessWithSaveResult) {
"FAILURE\"}],\"value_prop_display_text\":\"display text\"}");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_TRUE(save_result_.get());
- EXPECT_TRUE(save_result_->find("0") != save_result_->end());
- EXPECT_TRUE(save_result_->at("0") == "SUCCESS");
- EXPECT_TRUE(save_result_->find("1") != save_result_->end());
- EXPECT_TRUE(save_result_->at("1") == "TEMPORARY_FAILURE");
+ EXPECT_TRUE(migration_save_results_.get());
+ EXPECT_TRUE(migration_save_results_->find("0") !=
+ migration_save_results_->end());
+ EXPECT_TRUE(migration_save_results_->at("0") == "SUCCESS");
+ EXPECT_TRUE(migration_save_results_->find("1") !=
+ migration_save_results_->end());
+ EXPECT_TRUE(migration_save_results_->at("1") == "TEMPORARY_FAILURE");
}
TEST_F(PaymentsClientTest, MigrationMissingSaveResult) {
@@ -1087,7 +1101,7 @@ TEST_F(PaymentsClientTest, MigrationMissingSaveResult) {
ReturnResponse(net::HTTP_OK,
"{\"value_prop_display_text\":\"display text\"}");
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
- EXPECT_EQ(nullptr, save_result_.get());
+ EXPECT_EQ(nullptr, migration_save_results_.get());
}
TEST_F(PaymentsClientTest, MigrationSuccessWithDisplayText) {
@@ -1111,7 +1125,7 @@ TEST_F(PaymentsClientTest, RetryFailure) {
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"error\": { \"code\": \"INTERNAL\" } }");
EXPECT_EQ(AutofillClient::TRY_AGAIN_FAILURE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ("", unmask_response_details_->real_pan);
}
TEST_F(PaymentsClientTest, PermanentFailure) {
@@ -1120,7 +1134,7 @@ TEST_F(PaymentsClientTest, PermanentFailure) {
ReturnResponse(net::HTTP_OK,
"{ \"error\": { \"code\": \"ANYTHING_ELSE\" } }");
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ("", unmask_response_details_->real_pan);
}
TEST_F(PaymentsClientTest, MalformedResponse) {
@@ -1128,7 +1142,7 @@ TEST_F(PaymentsClientTest, MalformedResponse) {
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"error_code\": \"WRONG_JSON_FORMAT\" }");
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ("", unmask_response_details_->real_pan);
}
TEST_F(PaymentsClientTest, ReauthNeeded) {
@@ -1138,17 +1152,17 @@ TEST_F(PaymentsClientTest, ReauthNeeded) {
ReturnResponse(net::HTTP_UNAUTHORIZED, "");
// No response yet.
EXPECT_EQ(AutofillClient::NONE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ(nullptr, unmask_response_details_);
// Second HTTP_UNAUTHORIZED causes permanent failure.
IssueOAuthToken();
ReturnResponse(net::HTTP_UNAUTHORIZED, "");
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ("", unmask_response_details_->real_pan);
}
result_ = AutofillClient::NONE;
- real_pan_.clear();
+ unmask_response_details_ = nullptr;
{
StartUnmasking(CardUnmaskOptions());
@@ -1159,13 +1173,13 @@ TEST_F(PaymentsClientTest, ReauthNeeded) {
ReturnResponse(net::HTTP_UNAUTHORIZED, "");
// No response yet.
EXPECT_EQ(AutofillClient::NONE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ(nullptr, unmask_response_details_);
// HTTP_OK after first HTTP_UNAUTHORIZED results in success.
IssueOAuthToken();
ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
EXPECT_EQ(AutofillClient::SUCCESS, result_);
- EXPECT_EQ("1234", real_pan_);
+ EXPECT_EQ("1234", unmask_response_details_->real_pan);
}
}
@@ -1174,7 +1188,7 @@ TEST_F(PaymentsClientTest, NetworkError) {
IssueOAuthToken();
ReturnResponse(net::HTTP_REQUEST_TIMEOUT, std::string());
EXPECT_EQ(AutofillClient::NETWORK_ERROR, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ("", unmask_response_details_->real_pan);
}
TEST_F(PaymentsClientTest, OtherError) {
@@ -1182,7 +1196,7 @@ TEST_F(PaymentsClientTest, OtherError) {
IssueOAuthToken();
ReturnResponse(net::HTTP_FORBIDDEN, std::string());
EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
- EXPECT_EQ("", real_pan_);
+ EXPECT_EQ("", unmask_response_details_->real_pan);
}
} // namespace payments
diff --git a/chromium/components/autofill/core/browser/payments/payments_util.cc b/chromium/components/autofill/core/browser/payments/payments_util.cc
index 59876db5a1f..7437638ad6a 100644
--- a/chromium/components/autofill/core/browser/payments/payments_util.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_util.cc
@@ -6,7 +6,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
-#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -17,8 +16,7 @@ namespace {
constexpr int kCustomerHasNoBillingCustomerNumber = 0;
}
-int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
- bool should_log_validity) {
+int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager) {
DCHECK(personal_data_manager);
// Get billing customer ID from the synced PaymentsCustomerData.
@@ -28,21 +26,7 @@ int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
int64_t billing_customer_id = 0;
if (base::StringToInt64(base::StringPiece(customer_data->customer_id),
&billing_customer_id)) {
- if (should_log_validity) {
- AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
- AutofillMetrics::BillingIdStatus::VALID);
- }
return billing_customer_id;
- } else {
- if (should_log_validity) {
- AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
- AutofillMetrics::BillingIdStatus::PARSE_ERROR);
- }
- }
- } else {
- if (should_log_validity) {
- AutofillMetrics::LogPaymentsCustomerDataBillingIdStatus(
- AutofillMetrics::BillingIdStatus::MISSING);
}
}
return kCustomerHasNoBillingCustomerNumber;
diff --git a/chromium/components/autofill/core/browser/payments/payments_util.h b/chromium/components/autofill/core/browser/payments/payments_util.h
index b384e036949..2e2cf761dfc 100644
--- a/chromium/components/autofill/core/browser/payments/payments_util.h
+++ b/chromium/components/autofill/core/browser/payments/payments_util.h
@@ -18,10 +18,8 @@ namespace payments {
// Returns the billing customer ID (a.k.a. the customer number) for the Google
// Payments account for this user. Obtains it from the synced data. Returns 0
-// if the customer ID was not found. If |should_log_validity| is true, will
-// report on the validity state of the customer ID in PaymentsCustomerData.
-int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
- bool should_log_validity = false);
+// if the customer ID was not found.
+int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager);
// Returns if the customer has an existing Google payments account.
bool HasGooglePaymentsAccount(PersonalDataManager* personal_data_manager);
diff --git a/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc b/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc
index 631d3212c21..27a324939f8 100644
--- a/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc
@@ -7,8 +7,6 @@
#include "base/guid.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
@@ -30,43 +28,23 @@ class PaymentsUtilTest : public testing::Test {
};
TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_Normal) {
- base::HistogramTester histogram_tester;
-
personal_data_manager_.SetPaymentsCustomerData(
std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
- EXPECT_EQ(123456, GetBillingCustomerId(&personal_data_manager_,
- /*should_log_validity=*/true));
-
- histogram_tester.ExpectUniqueSample(
- "Autofill.PaymentsCustomerDataBillingIdStatus",
- AutofillMetrics::BillingIdStatus::VALID, 1);
+ EXPECT_EQ(123456, GetBillingCustomerId(&personal_data_manager_));
}
TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_Garbage) {
- base::HistogramTester histogram_tester;
-
personal_data_manager_.SetPaymentsCustomerData(
std::make_unique<PaymentsCustomerData>(/*customer_id=*/"garbage"));
- EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_,
- /*should_log_validity=*/true));
-
- histogram_tester.ExpectUniqueSample(
- "Autofill.PaymentsCustomerDataBillingIdStatus",
- AutofillMetrics::BillingIdStatus::PARSE_ERROR, 1);
+ EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_));
}
TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_NoData) {
- base::HistogramTester histogram_tester;
-
// Explictly do not set PaymentsCustomerData. Nothing crashes and the returned
// customer ID is 0.
- EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_,
- /*should_log_validity=*/true));
- histogram_tester.ExpectUniqueSample(
- "Autofill.PaymentsCustomerDataBillingIdStatus",
- AutofillMetrics::BillingIdStatus::MISSING, 1);
+ EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_));
}
TEST_F(PaymentsUtilTest, HasGooglePaymentsAccount_Normal) {
diff --git a/chromium/components/autofill/core/browser/payments/strike_database.cc b/chromium/components/autofill/core/browser/payments/strike_database.cc
index 0ed9e17b039..0860cd0e0b3 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database.cc
+++ b/chromium/components/autofill/core/browser/payments/strike_database.cc
@@ -30,8 +30,8 @@ StrikeDatabase::StrikeDatabase(
auto strike_database_path =
profile_path.Append(FILE_PATH_LITERAL("AutofillStrikeDatabase"));
- auto database_task_runner = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ auto database_task_runner = base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
db_ = db_provider->GetDB<StrikeData>(
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc b/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc
index 853d0a23e76..ef331aa3fda 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc
@@ -10,7 +10,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
@@ -43,12 +43,12 @@ class StrikeDatabaseIntegratorTestStrikeDatabaseTest : public ::testing::Test {
// to a task runner, requires running the loop to complete.
strike_database_.reset();
strike_database_service_.reset();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
protected:
base::HistogramTester* GetHistogramTester() { return &histogram_tester_; }
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<leveldb_proto::ProtoDatabaseProvider> db_provider_;
std::unique_ptr<StrikeDatabase> strike_database_service_;
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_unittest.cc b/chromium/components/autofill/core/browser/payments/strike_database_unittest.cc
index f03e13cd6e6..9810e4a6f70 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/strike_database_unittest.cc
@@ -11,7 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
#include "components/leveldb_proto/public/proto_database.h"
@@ -129,7 +129,7 @@ class StrikeDatabaseTest : public ::testing::Test {
protected:
base::HistogramTester* GetHistogramTester() { return &histogram_tester_; }
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<leveldb_proto::ProtoDatabaseProvider> db_provider_;
std::unique_ptr<TestStrikeDatabase> strike_database_;
base::ScopedTempDir temp_dir_;
diff --git a/chromium/components/autofill/core/browser/payments/test_authentication_requester.cc b/chromium/components/autofill/core/browser/payments/test_authentication_requester.cc
index 4c56fab5050..276ae5866bf 100644
--- a/chromium/components/autofill/core/browser/payments/test_authentication_requester.cc
+++ b/chromium/components/autofill/core/browser/payments/test_authentication_requester.cc
@@ -19,13 +19,11 @@ TestAuthenticationRequester::GetWeakPtr() {
}
void TestAuthenticationRequester::OnCVCAuthenticationComplete(
- bool did_succeed,
- const CreditCard* card,
- const base::string16& cvc) {
- did_succeed_ = did_succeed;
+ const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response) {
+ did_succeed_ = response.did_succeed;
if (did_succeed_) {
- DCHECK(card);
- number_ = card->number();
+ DCHECK(response.card);
+ number_ = response.card->number();
}
}
diff --git a/chromium/components/autofill/core/browser/payments/test_authentication_requester.h b/chromium/components/autofill/core/browser/payments/test_authentication_requester.h
index 0a76ea34ad8..d2f692b8de2 100644
--- a/chromium/components/autofill/core/browser/payments/test_authentication_requester.h
+++ b/chromium/components/autofill/core/browser/payments/test_authentication_requester.h
@@ -37,9 +37,8 @@ class TestAuthenticationRequester
// CreditCardCVCAuthenticator::Requester:
void OnCVCAuthenticationComplete(
- bool did_succeed,
- const CreditCard* card = nullptr,
- const base::string16& cvc = base::string16()) override;
+ const CreditCardCVCAuthenticator::CVCAuthenticationResponse& response)
+ override;
#if !defined(OS_IOS)
// CreditCardFIDOAuthenticator::Requester:
diff --git a/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc b/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
index 192047c6bff..e8a556c8081 100644
--- a/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
+++ b/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.cc
@@ -20,13 +20,74 @@ TestCreditCardFIDOAuthenticator::TestCreditCardFIDOAuthenticator(
TestCreditCardFIDOAuthenticator::~TestCreditCardFIDOAuthenticator() {}
+void TestCreditCardFIDOAuthenticator::GetAssertion(
+ PublicKeyCredentialRequestOptionsPtr request_options) {
+ request_options_ = std::move(request_options);
+}
+
+void TestCreditCardFIDOAuthenticator::MakeCredential(
+ PublicKeyCredentialCreationOptionsPtr creation_options) {
+ creation_options_ = std::move(creation_options);
+}
+
+// static
+void TestCreditCardFIDOAuthenticator::GetAssertion(
+ CreditCardFIDOAuthenticator* fido_authenticator,
+ bool did_succeed) {
+ if (did_succeed) {
+ GetAssertionAuthenticatorResponsePtr response =
+ GetAssertionAuthenticatorResponse::New();
+ response->info = blink::mojom::CommonCredentialInfo::New();
+ fido_authenticator->OnDidGetAssertion(AuthenticatorStatus::SUCCESS,
+ std::move(response));
+ } else {
+ fido_authenticator->OnDidGetAssertion(
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+ }
+}
+
+// static
+void TestCreditCardFIDOAuthenticator::MakeCredential(
+ CreditCardFIDOAuthenticator* fido_authenticator,
+ bool did_succeed) {
+ if (did_succeed) {
+ MakeCredentialAuthenticatorResponsePtr response =
+ MakeCredentialAuthenticatorResponse::New();
+ response->info = blink::mojom::CommonCredentialInfo::New();
+ fido_authenticator->OnDidMakeCredential(AuthenticatorStatus::SUCCESS,
+ std::move(response));
+ } else {
+ fido_authenticator->OnDidMakeCredential(
+ AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
+ }
+}
+
+std::vector<uint8_t> TestCreditCardFIDOAuthenticator::GetCredentialId() {
+ DCHECK(!request_options_->allow_credentials.empty());
+ return request_options_->allow_credentials.front().id();
+}
+
+std::vector<uint8_t> TestCreditCardFIDOAuthenticator::GetChallenge() {
+ if (request_options_) {
+ return request_options_->challenge;
+ } else {
+ DCHECK(creation_options_);
+ return creation_options_->challenge;
+ }
+}
+
+std::string TestCreditCardFIDOAuthenticator::GetRelyingPartyId() {
+ if (request_options_) {
+ return request_options_->relying_party_id;
+ } else {
+ DCHECK(creation_options_);
+ return creation_options_->relying_party.id;
+ }
+}
+
void TestCreditCardFIDOAuthenticator::IsUserVerifiable(
base::OnceCallback<void(bool)> callback) {
return std::move(callback).Run(is_user_verifiable_);
}
-bool TestCreditCardFIDOAuthenticator::IsUserOptedIn() {
- return is_user_opted_in_;
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h b/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h
index eb462f3c845..6830abc780c 100644
--- a/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h
+++ b/chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h
@@ -26,24 +26,39 @@ class TestCreditCardFIDOAuthenticator : public CreditCardFIDOAuthenticator {
AutofillClient* client);
~TestCreditCardFIDOAuthenticator() override;
+ // CreditCardFIDOAuthenticator:
+ void GetAssertion(
+ PublicKeyCredentialRequestOptionsPtr request_options) override;
+ void MakeCredential(
+ PublicKeyCredentialCreationOptionsPtr creation_options) override;
+
+ // Invokes fido_authenticator->OnDidGetAssertion().
+ static void GetAssertion(CreditCardFIDOAuthenticator* fido_authenticator,
+ bool did_succeed);
+
+ // Invokes fido_authenticator->OnDidMakeCredential().
+ static void MakeCredential(CreditCardFIDOAuthenticator* fido_authenticator,
+ bool did_succeed);
+
+ // Getter methods to query Request Options.
+ std::vector<uint8_t> GetCredentialId();
+ std::vector<uint8_t> GetChallenge();
+ std::string GetRelyingPartyId();
+
void SetUserVerifiable(bool is_user_verifiable) {
is_user_verifiable_ = is_user_verifiable;
}
- void SetUserOptIn(bool is_user_opted_in) {
- is_user_opted_in_ = is_user_opted_in;
- }
-
// CreditCardFIDOAuthenticator:
void IsUserVerifiable(base::OnceCallback<void(bool)> callback) override;
- bool IsUserOptedIn() override;
private:
friend class AutofillManagerTest;
friend class CreditCardAccessManagerTest;
+ PublicKeyCredentialRequestOptionsPtr request_options_;
+ PublicKeyCredentialCreationOptionsPtr creation_options_;
bool is_user_verifiable_ = false;
- bool is_user_opted_in_ = false;
DISALLOW_COPY_AND_ASSIGN(TestCreditCardFIDOAuthenticator);
};
diff --git a/chromium/components/autofill/core/browser/payments/test_legal_message_line.h b/chromium/components/autofill/core/browser/payments/test_legal_message_line.h
new file mode 100644
index 00000000000..1fdfcd66a69
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/test_legal_message_line.h
@@ -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.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_LEGAL_MESSAGE_LINE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_LEGAL_MESSAGE_LINE_H_
+
+#include <string>
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/payments/legal_message_line.h"
+
+namespace autofill {
+
+using Link = LegalMessageLine::Link;
+
+// A legal message line that allows for modifications.
+class TestLegalMessageLine : public LegalMessageLine {
+ public:
+ TestLegalMessageLine() {}
+
+ TestLegalMessageLine(const std::string& ascii_text) { set_text(ascii_text); }
+
+ TestLegalMessageLine(const std::string& ascii_text,
+ const std::vector<Link>& links) {
+ set_text(ascii_text);
+ set_links(links);
+ }
+
+ ~TestLegalMessageLine() override {}
+
+ void set_text(const std::string& ascii_text) {
+ text_ = base::ASCIIToUTF16(ascii_text);
+ }
+
+ void set_links(const std::vector<Link>& links) { links_ = links; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestLegalMessageLine);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_LEGAL_MESSAGE_LINE_H_
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.cc b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
index e4022a9dbf8..88ba1252ce0 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
@@ -12,8 +12,15 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace autofill {
+
namespace payments {
+namespace {
+// Base64 encoding of "This is a test challenge".
+constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
+constexpr int kTestTimeoutSeconds = 180;
+} // namespace
+
TestPaymentsClient::TestPaymentsClient(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_,
signin::IdentityManager* identity_manager,
@@ -73,12 +80,46 @@ void TestPaymentsClient::AllowFidoRegistration(bool offer_fido_opt_in) {
unmask_details_.offer_fido_opt_in = offer_fido_opt_in;
}
-void TestPaymentsClient::AddFidoEligibleCard(std::string server_id) {
+void TestPaymentsClient::AddFidoEligibleCard(std::string server_id,
+ std::string credential_id,
+ std::string relying_party_id) {
unmask_details_.offer_fido_opt_in = false;
unmask_details_.unmask_auth_method = AutofillClient::UnmaskAuthMethod::FIDO;
+ unmask_details_.fido_eligible_card_ids.insert(server_id);
unmask_details_.fido_request_options =
base::Value(base::Value::Type::DICTIONARY);
- unmask_details_.fido_eligible_card_ids.insert(server_id);
+
+ // Building the following JSON structure--
+ // fido_request_options = {
+ // "challenge": kTestChallenge,
+ // "timeout_millis": kTestTimeoutSeconds,
+ // "relying_party_id": relying_party_id,
+ // "key_info": [{
+ // "credential_id": credential_id,
+ // "authenticator_transport_support": ["INTERNAL"]
+ // }]}
+ unmask_details_.fido_request_options.SetKey("challenge",
+ base::Value(kTestChallenge));
+ unmask_details_.fido_request_options.SetKey("timeout_millis",
+ base::Value(kTestTimeoutSeconds));
+ unmask_details_.fido_request_options.SetKey("relying_party_id",
+ base::Value(relying_party_id));
+
+ base::Value key_info(base::Value::Type::DICTIONARY);
+ if (!credential_id.empty())
+ key_info.SetKey("credential_id", base::Value(credential_id));
+ key_info.SetKey("authenticator_transport_support",
+ base::Value(base::Value::Type::LIST));
+ key_info
+ .FindKeyOfType("authenticator_transport_support", base::Value::Type::LIST)
+ ->GetList()
+ .push_back(base::Value("INTERNAL"));
+ unmask_details_.fido_request_options.SetKey(
+ "key_info", base::Value(base::Value::Type::LIST));
+ unmask_details_.fido_request_options
+ .FindKeyOfType("key_info", base::Value::Type::LIST)
+ ->GetList()
+ .push_back(std::move(key_info));
}
void TestPaymentsClient::SetServerIdForCardUpload(std::string server_id) {
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.h b/chromium/components/autofill/core/browser/payments/test_payments_client.h
index 573abadaba8..01763edd62f 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.h
@@ -58,7 +58,9 @@ class TestPaymentsClient : public payments::PaymentsClient {
void AllowFidoRegistration(bool offer_fido_opt_in = true);
- void AddFidoEligibleCard(std::string server_id);
+ void AddFidoEligibleCard(std::string server_id,
+ std::string credential_id,
+ std::string relying_party_id);
void SetServerIdForCardUpload(std::string);
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index 5d47a0f3124..41cd4d5bb74 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -554,9 +554,7 @@ void PersonalDataManager::OnAccountsCookieDeletedByUserAction() {
AutofillSyncSigninState PersonalDataManager::GetSyncSigninState() const {
// Check if the user is signed out.
if (!sync_service_ || !identity_manager_ ||
- syncer::DetermineAccountToUse(identity_manager_,
- /*allow_secondary_accounts=*/true)
- .account_info.IsEmpty()) {
+ syncer::DetermineAccountToUse(identity_manager_).account_info.IsEmpty()) {
return AutofillSyncSigninState::kSignedOut;
}
@@ -1147,8 +1145,8 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions(
std::vector<AutofillProfile*> matched_profiles;
std::vector<Suggestion> suggestions =
suggestion_selection::GetPrefixMatchedSuggestions(
- type, field_contents_canon, comparator, sorted_profiles,
- &matched_profiles);
+ type, field_contents, field_contents_canon, comparator,
+ field_is_autofilled, sorted_profiles, &matched_profiles);
// Don't show two suggestions if one is a subset of the other.
std::vector<AutofillProfile*> unique_matched_profiles;
@@ -1304,11 +1302,8 @@ bool PersonalDataManager::ShouldSuggestServerCards() const {
base::FeatureList::IsEnabled(
features::kAutofillEnableAccountWalletStorage)) {
// For SyncTransport, only show server cards if the user has opted in to
- // seeing them in the dropdown, or if the feature to always show server
- // cards is enabled.
- if (!base::FeatureList::IsEnabled(
- features::kAutofillAlwaysShowServerCardsInSyncTransport) &&
- !prefs::IsUserOptedInWalletSyncTransport(
+ // seeing them in the dropdown.
+ if (!prefs::IsUserOptedInWalletSyncTransport(
pref_service_,
sync_service_->GetAuthenticatedAccountInfo().account_id)) {
return false;
@@ -1949,13 +1944,6 @@ bool PersonalDataManager::ShouldShowCardsFromAccountOption() const {
DCHECK(base::FeatureList::IsEnabled(
features::kAutofillEnableAccountWalletStorage));
- // If the feature to always show the server cards in sync transport mode is
- // enabled, don't show the option.
- if (base::FeatureList::IsEnabled(
- features::kAutofillAlwaysShowServerCardsInSyncTransport)) {
- return false;
- }
-
bool is_opted_in = prefs::IsUserOptedInWalletSyncTransport(
pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id);
diff --git a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
index e9b8ac07354..ed12c5048f9 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -16,7 +16,6 @@
#include "base/base64.h"
#include "base/command_line.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/i18n/time_formatting.h"
#include "base/rand_util.h"
@@ -26,8 +25,8 @@
#include "base/synchronization/waitable_event.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -150,8 +149,7 @@ class PersonalDataManagerTestBase {
void SetUpTest() {
OSCryptMocker::SetUp();
prefs_ = test::PrefServiceForTesting();
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath path = temp_dir_.GetPath().AppendASCII("TestWebDB");
+ base::FilePath path(WebDatabase::kInMemoryPath);
profile_web_database_ =
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
@@ -299,11 +297,8 @@ class PersonalDataManagerTestBase {
run_loop.Run();
}
- // The temporary directory should be deleted at the end to ensure that
- // files are not used anymore and deletion succeeds.
- base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
std::unique_ptr<PrefService> prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
signin::IdentityTestEnvironment identity_test_env_;
@@ -6745,11 +6740,6 @@ TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode) {
// Make sure that the opt in is necessary to show server cards if the
// appropriate feature is disabled.
TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode_NeedOptIn) {
- // Disable the feature that always shows server cards in sync transport.
- base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndDisableFeature(
- features::kAutofillAlwaysShowServerCardsInSyncTransport);
-
// Set up PersonalDataManager in transport mode.
ResetPersonalDataManager(USER_MODE_NORMAL,
/*use_sync_transport_mode=*/true);
@@ -6777,29 +6767,6 @@ TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode_NeedOptIn) {
EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
}
-
-// Make sure that the opt in is not necessary to show server cards if the
-// appropriate feature is enabled.
-TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode_NoOptInNeeded) {
- // Enable the feature that always shows server cards in sync transport.
- base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(
- features::kAutofillAlwaysShowServerCardsInSyncTransport);
-
- // Set up PersonalDataManager in transport mode.
- ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/true);
- SetUpThreeCardTypes();
- AccountInfo active_info = SetActiveSecondaryAccount();
-
- // Check that the server cards are available for suggestion.
- EXPECT_EQ(3U, personal_data_->GetCreditCards().size());
- EXPECT_EQ(
- 3U, personal_data_->GetCreditCardsToSuggest(/*include_server_cards=*/true)
- .size());
- EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size());
- EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
-}
#endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
// Tests that all the non settings origins of autofill profiles are cleared but
@@ -7654,18 +7621,6 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) {
histogram_tester.ExpectUniqueSample(kHistogramName, false, 1);
}
- // Enable feature to always show server cards. The function should now return
- // false.
- {
- base::test::ScopedFeatureList scoped_features;
- scoped_features.InitWithFeatures(
- /*enabled_features=*/
- {features::kAutofillEnableAccountWalletStorage,
- features::kAutofillAlwaysShowServerCardsInSyncTransport},
- /*disabled_features=*/{});
- EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
- }
-
// Set that the user already opted-in. Check that the function now returns
// false.
::autofill::prefs::SetUserOptedInWalletSyncTransport(
@@ -7772,18 +7727,6 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) {
// Make sure the function returns false.
EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
- // Enable feature to always show server cards. The function should still
- // return false.
- {
- base::test::ScopedFeatureList scoped_features;
- scoped_features.InitWithFeatures(
- /*enabled_features=*/
- {features::kAutofillEnableAccountWalletStorage,
- features::kAutofillAlwaysShowServerCardsInSyncTransport},
- /*disabled_features=*/{});
- EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
- }
-
// Set that the user already opted-in. Check that the function still returns
// false.
::autofill::prefs::SetUserOptedInWalletSyncTransport(
@@ -7924,6 +7867,10 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) {
// Make sure there are no opt-ins recorded yet.
ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
+
+ // Account wallet storage only makes sense together with support for
+ // unconsented primary accounts, i.e. on Win/Mac/Linux.
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
{
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
@@ -7967,6 +7914,7 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) {
prefs::ClearSyncTransportOptIns(prefs_.get());
ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(),
active_info.account_id));
+#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
///////////////////////////////////////////////////////////
// kSignedOut
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index 8a9b809fa57..89baf299c69 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -107,6 +107,9 @@ void TestAutofillClient::ShowLocalCardMigrationResults(
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) {}
+void TestAutofillClient::ShowWebauthnOfferDialog(
+ WebauthnOfferDialogCallback callback) {}
+
void TestAutofillClient::ConfirmSaveAutofillProfile(
const AutofillProfile& profile,
base::OnceClosure callback) {
@@ -121,6 +124,7 @@ void TestAutofillClient::ConfirmSaveCreditCardLocally(
LocalSaveCardPromptCallback callback) {
confirm_save_credit_card_locally_called_ = true;
offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt;
+ save_credit_card_options_ = options;
std::move(callback).Run(AutofillClient::ACCEPTED);
}
@@ -148,6 +152,7 @@ void TestAutofillClient::ConfirmSaveCreditCardToCloud(
SaveCreditCardOptions options,
UploadSaveCardPromptCallback callback) {
offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt;
+ save_credit_card_options_ = options;
std::move(callback).Run(AutofillClient::ACCEPTED, {});
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index 68c1b327492..2f8b9bdda12 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -64,6 +64,7 @@ class TestAutofillClient : public AutofillClient {
const base::string16& tip_message,
const std::vector<MigratableCreditCard>& migratable_credit_cards,
MigrationDeleteCardCallback delete_local_card_callback) override;
+ void ShowWebauthnOfferDialog(WebauthnOfferDialogCallback callback) override;
void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) override;
void ConfirmSaveCreditCardLocally(
@@ -159,6 +160,10 @@ class TestAutofillClient : public AutofillClient {
return offer_to_save_credit_card_bubble_was_shown_.value();
}
+ SaveCreditCardOptions get_save_credit_card_options() {
+ return save_credit_card_options_.value();
+ }
+
MockAutocompleteHistoryManager* GetMockAutocompleteHistoryManager() {
return &mock_autocomplete_history_manager_;
}
@@ -200,6 +205,9 @@ class TestAutofillClient : public AutofillClient {
// otherwise.
base::Optional<bool> credit_card_name_fix_flow_bubble_was_shown_;
+ // Populated if local save or upload was offered.
+ base::Optional<SaveCreditCardOptions> save_credit_card_options_;
+
std::vector<std::string> migration_card_selection_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillClient);
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.cc b/chromium/components/autofill/core/browser/test_autofill_driver.cc
index 05abf3aaf2b..dd51b9637b6 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.cc
@@ -15,8 +15,7 @@
namespace autofill {
TestAutofillDriver::TestAutofillDriver()
- : url_request_context_(nullptr),
- test_shared_loader_factory_(
+ : test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {}
@@ -35,10 +34,6 @@ ui::AXTreeID TestAutofillDriver::GetAxTreeId() const {
return ui::AXTreeIDUnknown();
}
-net::URLRequestContextGetter* TestAutofillDriver::GetURLRequestContext() {
- return url_request_context_;
-}
-
scoped_refptr<network::SharedURLLoaderFactory>
TestAutofillDriver::GetURLLoaderFactory() {
return test_shared_loader_factory_;
@@ -50,7 +45,7 @@ bool TestAutofillDriver::RendererIsAvailable() {
#if !defined(OS_IOS)
void TestAutofillDriver::ConnectToAuthenticator(
- blink::mojom::InternalAuthenticatorRequest request) {}
+ mojo::PendingReceiver<blink::mojom::InternalAuthenticator> receiver) {}
#endif
void TestAutofillDriver::SendFormDataToRenderer(int query_id,
@@ -102,11 +97,6 @@ void TestAutofillDriver::SetIsInMainFrame(bool is_in_main_frame) {
is_in_main_frame_ = is_in_main_frame;
}
-void TestAutofillDriver::SetURLRequestContext(
- net::URLRequestContextGetter* url_request_context) {
- url_request_context_ = url_request_context;
-}
-
void TestAutofillDriver::SetSharedURLLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
test_shared_loader_factory_ = url_loader_factory;
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.h b/chromium/components/autofill/core/browser/test_autofill_driver.h
index 160f561f256..d65c2b23cd8 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.h
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_driver.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/network/test/test_url_loader_factory.h"
namespace autofill {
@@ -24,14 +25,12 @@ class TestAutofillDriver : public AutofillDriver {
bool IsIncognito() const override;
bool IsInMainFrame() const override;
ui::AXTreeID GetAxTreeId() const override;
- // Returns the value passed in to the last call to |SetURLRequestContext()|
- // or NULL if that method has never been called.
- net::URLRequestContextGetter* GetURLRequestContext() override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
bool RendererIsAvailable() override;
#if !defined(OS_IOS)
void ConnectToAuthenticator(
- blink::mojom::InternalAuthenticatorRequest request) override;
+ mojo::PendingReceiver<blink::mojom::InternalAuthenticator> receiver)
+ override;
#endif
void SendFormDataToRenderer(int query_id,
RendererFormDataAction action,
@@ -58,14 +57,10 @@ class TestAutofillDriver : public AutofillDriver {
void SetIsIncognito(bool is_incognito);
void SetIsInMainFrame(bool is_in_main_frame);
- // Sets the URL request context for this instance. |url_request_context|
- // should outlive this instance.
- void SetURLRequestContext(net::URLRequestContextGetter* url_request_context);
void SetSharedURLLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
private:
- net::URLRequestContextGetter* url_request_context_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
bool is_incognito_ = false;
diff --git a/chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc b/chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc
index 3f9740deba0..a9b7596b284 100644
--- a/chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc
+++ b/chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc
@@ -127,7 +127,13 @@ std::ostream& operator<<(std::ostream& os, const AccessoryTabType& type) {
AccessorySheetData::AccessorySheetData(AccessoryTabType sheet_type,
base::string16 title)
- : sheet_type_(sheet_type), title_(std::move(title)) {}
+ : AccessorySheetData(sheet_type, std::move(title), base::string16()) {}
+AccessorySheetData::AccessorySheetData(AccessoryTabType sheet_type,
+ base::string16 title,
+ base::string16 warning)
+ : sheet_type_(sheet_type),
+ title_(std::move(title)),
+ warning_(std::move(warning)) {}
AccessorySheetData::AccessorySheetData(const AccessorySheetData& data) =
default;
@@ -144,13 +150,13 @@ AccessorySheetData& AccessorySheetData::operator=(AccessorySheetData&& data) =
bool AccessorySheetData::operator==(const AccessorySheetData& data) const {
return sheet_type_ == data.sheet_type_ && title_ == data.title_ &&
- user_info_list_ == data.user_info_list_ &&
+ warning_ == data.warning_ && user_info_list_ == data.user_info_list_ &&
footer_commands_ == data.footer_commands_;
}
std::ostream& operator<<(std::ostream& os, const AccessorySheetData& data) {
os << data.get_sheet_type() << " with title: \"" << data.title()
- << "\", user info list: [";
+ << "\", warning: \"" << data.warning() << "\", and user info list: [";
for (const UserInfo& user_info : data.user_info_list()) {
os << user_info << ", ";
}
@@ -167,6 +173,18 @@ AccessorySheetData::Builder::Builder(AccessoryTabType type,
AccessorySheetData::Builder::~Builder() = default;
+AccessorySheetData::Builder&& AccessorySheetData::Builder::SetWarning(
+ base::string16 warning) && {
+ // Calls SetWarning(base::string16 warning)()& since |this| is an lvalue.
+ return std::move(SetWarning(std::move(warning)));
+}
+
+AccessorySheetData::Builder& AccessorySheetData::Builder::SetWarning(
+ base::string16 warning) & {
+ accessory_sheet_data_.set_warning(std::move(warning));
+ return *this;
+}
+
AccessorySheetData::Builder&& AccessorySheetData::Builder::AddUserInfo(
std::string origin) && {
// Calls AddUserInfo()& since |this| is an lvalue.
diff --git a/chromium/components/autofill/core/browser/ui/accessory_sheet_data.h b/chromium/components/autofill/core/browser/ui/accessory_sheet_data.h
index 1c1fa83067b..351e1c03f41 100644
--- a/chromium/components/autofill/core/browser/ui/accessory_sheet_data.h
+++ b/chromium/components/autofill/core/browser/ui/accessory_sheet_data.h
@@ -119,6 +119,9 @@ class AccessorySheetData {
class Builder;
AccessorySheetData(AccessoryTabType sheet_type, base::string16 title);
+ AccessorySheetData(AccessoryTabType sheet_type,
+ base::string16 title,
+ base::string16 warning);
AccessorySheetData(const AccessorySheetData& data);
AccessorySheetData(AccessorySheetData&& data);
@@ -130,6 +133,9 @@ class AccessorySheetData {
const base::string16& title() const { return title_; }
AccessoryTabType get_sheet_type() const { return sheet_type_; }
+ const base::string16& warning() const { return warning_; }
+ void set_warning(base::string16 warning) { warning_ = std::move(warning); }
+
void add_user_info(UserInfo user_info) {
user_info_list_.emplace_back(std::move(user_info));
}
@@ -153,6 +159,7 @@ class AccessorySheetData {
private:
AccessoryTabType sheet_type_;
base::string16 title_;
+ base::string16 warning_;
std::vector<UserInfo> user_info_list_;
std::vector<FooterCommand> footer_commands_;
};
@@ -177,6 +184,10 @@ class AccessorySheetData::Builder {
Builder(AccessoryTabType type, base::string16 title);
~Builder();
+ // Adds a warning string to the accessory sheet.
+ Builder&& SetWarning(base::string16 warning) &&;
+ Builder& SetWarning(base::string16 warning) &;
+
// Adds a new UserInfo object to |accessory_sheet_data_|.
Builder&& AddUserInfo(std::string origin = std::string()) &&;
Builder& AddUserInfo(std::string origin = std::string()) &;
diff --git a/chromium/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc b/chromium/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc
index 13268e2c6c0..701d6ac20d0 100644
--- a/chromium/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/label_formatter_utils_unittest.cc
@@ -189,7 +189,7 @@ TEST(LabelFormatterUtilsTest, HaveSamePhoneNumbers_SamePhoneNumbers) {
AutofillProfile profile2 =
AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile2, "Maria", "Margaretha", "Winckelmann", "", "",
- "", "", "", "", "", "DE", "4903045042823");
+ "", "", "", "", "", "DE", "493045042823");
AutofillProfile profile3 =
AutofillProfile(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile3, "Maria", "Margaretha", "Winckelmann", "", "",
diff --git a/chromium/components/autofill/core/browser/ui/payments/DEPS b/chromium/components/autofill/core/browser/ui/payments/DEPS
deleted file mode 100644
index 04111f6283e..00000000000
--- a/chromium/components/autofill/core/browser/ui/payments/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-specific_include_rules = {
- "save_card_bubble_controller\.h": [
- "+components/signin/public/identity_manager/account_info.h",
- ]
-}
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.cc b/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.cc
index 692d285cfc5..920eafd7e66 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view_delegate_mobile.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/grit/components_scaled_resources.h"
#include "components/strings/grit/components_strings.h"
@@ -37,7 +38,7 @@ CardExpirationDateFixFlowViewDelegateMobile::
}
int CardExpirationDateFixFlowViewDelegateMobile::GetIconId() const {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER;
#else
return 0;
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc
index a668bbe6f87..94d6dc8b052 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view_delegate_mobile.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "components/grit/components_scaled_resources.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
@@ -35,7 +36,7 @@ CardNameFixFlowViewDelegateMobile::~CardNameFixFlowViewDelegateMobile() {
}
int CardNameFixFlowViewDelegateMobile::GetIconId() const {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER;
#else
return 0;
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h
index b4c5da8a029..8a33e40f7dd 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h
@@ -18,10 +18,11 @@ class CardUnmaskPromptController {
public:
// Interaction.
virtual void OnUnmaskDialogClosed() = 0;
- virtual void OnUnmaskResponse(const base::string16& cvc,
- const base::string16& exp_month,
- const base::string16& exp_year,
- bool should_store_pan) = 0;
+ virtual void OnUnmaskPromptAccepted(const base::string16& cvc,
+ const base::string16& exp_month,
+ const base::string16& exp_year,
+ bool should_store_pan,
+ bool enable_fido_auth) = 0;
virtual void NewCardLinkClicked() = 0;
// State.
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
index 1015cfb9d56..f4918d2ff28 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.cc
@@ -46,7 +46,7 @@ void CardUnmaskPromptControllerImpl::ShowPrompt(
new_card_link_clicked_ = false;
shown_timestamp_ = AutofillClock::Now();
- pending_response_ = CardUnmaskDelegate::UnmaskResponse();
+ pending_details_ = CardUnmaskDelegate::UserProvidedUnmaskDetails();
card_unmask_view_ = card_unmask_view;
card_ = card;
reason_ = reason;
@@ -106,37 +106,38 @@ void CardUnmaskPromptControllerImpl::OnUnmaskDialogClosed() {
delegate_->OnUnmaskPromptClosed();
}
-void CardUnmaskPromptControllerImpl::OnUnmaskResponse(
+void CardUnmaskPromptControllerImpl::OnUnmaskPromptAccepted(
const base::string16& cvc,
const base::string16& exp_month,
const base::string16& exp_year,
- bool should_store_pan) {
+ bool should_store_pan,
+ bool enable_fido_auth) {
verify_timestamp_ = AutofillClock::Now();
unmasking_number_of_attempts_++;
unmasking_result_ = AutofillClient::NONE;
card_unmask_view_->DisableAndWaitForVerification();
DCHECK(InputCvcIsValid(cvc));
- base::TrimWhitespace(cvc, base::TRIM_ALL, &pending_response_.cvc);
+ base::TrimWhitespace(cvc, base::TRIM_ALL, &pending_details_.cvc);
if (ShouldRequestExpirationDate()) {
DCHECK(InputExpirationIsValid(exp_month, exp_year));
- pending_response_.exp_month = exp_month;
- pending_response_.exp_year = exp_year;
+ pending_details_.exp_month = exp_month;
+ pending_details_.exp_year = exp_year;
}
if (CanStoreLocally()) {
- pending_response_.should_store_pan = should_store_pan;
+ pending_details_.should_store_pan = should_store_pan;
// Remember the last choice the user made (on this device).
pref_service_->SetBoolean(prefs::kAutofillWalletImportStorageCheckboxState,
should_store_pan);
} else {
DCHECK(!should_store_pan);
- pending_response_.should_store_pan = false;
+ pending_details_.should_store_pan = false;
}
// There is a chance the delegate has disappeared (i.e. tab closed) before the
// unmask response came in. Avoid a crash.
if (delegate_)
- delegate_->OnUnmaskResponse(pending_response_);
+ delegate_->OnUnmaskPromptAccepted(pending_details_);
}
void CardUnmaskPromptControllerImpl::NewCardLinkClicked() {
@@ -292,7 +293,7 @@ void CardUnmaskPromptControllerImpl::LogOnCloseEvents() {
verify_timestamp_);
}
- bool final_should_store_pan = pending_response_.should_store_pan;
+ bool final_should_store_pan = pending_details_.should_store_pan;
if (unmasking_result_ == AutofillClient::SUCCESS && final_should_store_pan) {
AutofillMetrics::LogUnmaskPromptEvent(
AutofillMetrics::UNMASK_PROMPT_SAVED_CARD_LOCALLY);
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h
index 97fb2f9d103..dd174d24644 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl.h
@@ -35,10 +35,11 @@ class CardUnmaskPromptControllerImpl : public CardUnmaskPromptController {
// CardUnmaskPromptController implementation.
void OnUnmaskDialogClosed() override;
- void OnUnmaskResponse(const base::string16& cvc,
- const base::string16& exp_month,
- const base::string16& exp_year,
- bool should_store_pan) override;
+ void OnUnmaskPromptAccepted(const base::string16& cvc,
+ const base::string16& exp_month,
+ const base::string16& exp_year,
+ bool should_store_pan,
+ bool enable_fido_auth) override;
void NewCardLinkClicked() override;
base::string16 GetWindowTitle() const override;
base::string16 GetInstructionsMessage() const override;
@@ -79,7 +80,7 @@ class CardUnmaskPromptControllerImpl : public CardUnmaskPromptController {
// Timestamp of the last time the user clicked the Verify button.
base::Time verify_timestamp_;
- CardUnmaskDelegate::UnmaskResponse pending_response_;
+ CardUnmaskDelegate::UserProvidedUnmaskDetails pending_details_;
base::WeakPtrFactory<CardUnmaskPromptControllerImpl> weak_pointer_factory_{
this};
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
index 7f4566aec37..418ac6c636e 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_unmask_prompt_controller_impl_unittest.cc
@@ -34,19 +34,20 @@ class TestCardUnmaskDelegate : public CardUnmaskDelegate {
virtual ~TestCardUnmaskDelegate() {}
// CardUnmaskDelegate implementation.
- void OnUnmaskResponse(const UnmaskResponse& response) override {
- response_ = response;
+ void OnUnmaskPromptAccepted(
+ const UserProvidedUnmaskDetails& details) override {
+ details_ = details;
}
void OnUnmaskPromptClosed() override {}
- const UnmaskResponse& response() { return response_; }
+ const UserProvidedUnmaskDetails& details() { return details_; }
base::WeakPtr<TestCardUnmaskDelegate> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
- UnmaskResponse response_;
+ UserProvidedUnmaskDetails details_;
base::WeakPtrFactory<TestCardUnmaskDelegate> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(TestCardUnmaskDelegate);
@@ -106,8 +107,9 @@ class CardUnmaskPromptControllerImplGenericTest {
void ShowPromptAndSimulateResponse(bool should_store_pan) {
ShowPrompt();
- controller_->OnUnmaskResponse(ASCIIToUTF16("444"), ASCIIToUTF16("01"),
- ASCIIToUTF16("2050"), should_store_pan);
+ controller_->OnUnmaskPromptAccepted(ASCIIToUTF16("444"), ASCIIToUTF16("01"),
+ ASCIIToUTF16("2050"), should_store_pan,
+ /*enable_fido_auth=*/false);
EXPECT_EQ(should_store_pan,
pref_service_->GetBoolean(
prefs::kAutofillWalletImportStorageCheckboxState));
@@ -167,7 +169,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogClosedNoAttempts) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogClosedAbandonUnmasking) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -178,7 +180,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogClosedAbandonUnmasking) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogClosedFailedToUnmaskRetriable) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
base::HistogramTester histogram_tester;
@@ -196,7 +198,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogClosedFailedToUnmaskRetriable) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogClosedFailedToUnmaskNonRetriable) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
controller_->OnVerificationResult(AutofillClient::PERMANENT_FAILURE);
base::HistogramTester histogram_tester;
@@ -214,7 +216,7 @@ TEST_F(CardUnmaskPromptControllerImplTest,
}
TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardFirstAttempt) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -230,11 +232,12 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardFirstAttempt) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardAfterFailure) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
- controller_->OnUnmaskResponse(ASCIIToUTF16("444"), ASCIIToUTF16("01"),
- ASCIIToUTF16("2050"),
- false /* should_store_pan */);
+ controller_->OnUnmaskPromptAccepted(ASCIIToUTF16("444"), ASCIIToUTF16("01"),
+ ASCIIToUTF16("2050"),
+ /*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -246,7 +249,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskedCardAfterFailure) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogSavedCardLocally) {
- ShowPromptAndSimulateResponse(true);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/true);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -259,7 +262,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogSavedCardLocally) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptIn) {
SetImportCheckboxState(false);
- ShowPromptAndSimulateResponse(true);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/true);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -270,7 +273,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptIn) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptIn) {
SetImportCheckboxState(false);
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -281,7 +284,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptIn) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptOut) {
SetImportCheckboxState(true);
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -292,7 +295,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidOptOut) {
TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptOut) {
SetImportCheckboxState(true);
- ShowPromptAndSimulateResponse(true);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/true);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -303,7 +306,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDidNotOptOut) {
TEST_F(CardUnmaskPromptControllerImplTest, DontLogForHiddenCheckbox) {
controller_->set_can_store_locally(false);
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -333,7 +336,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationNoAttempts) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationAbandonUnmasking) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -344,7 +347,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationAbandonUnmasking) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationFailedToUnmaskRetriable) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
base::HistogramTester histogram_tester;
@@ -357,7 +360,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationFailedToUnmaskRetriable) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogDurationFailedToUnmaskNonRetriable) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
controller_->OnVerificationResult(AutofillClient::PERMANENT_FAILURE);
base::HistogramTester histogram_tester;
@@ -369,7 +372,7 @@ TEST_F(CardUnmaskPromptControllerImplTest,
}
TEST_F(CardUnmaskPromptControllerImplTest, LogDurationCardFirstAttempt) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -382,11 +385,12 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogDurationCardFirstAttempt) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogDurationUnmaskedCardAfterFailure) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
- controller_->OnUnmaskResponse(
+ controller_->OnUnmaskPromptAccepted(
base::ASCIIToUTF16("444"), base::ASCIIToUTF16("01"),
- base::ASCIIToUTF16("2050"), false /* should_store_pan */);
+ base::ASCIIToUTF16("2050"), /*should_store_pan=*/false,
+ /*enable_fido_auth=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -398,7 +402,7 @@ TEST_F(CardUnmaskPromptControllerImplTest,
}
TEST_F(CardUnmaskPromptControllerImplTest, LogTimeBeforeAbandonUnmasking) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnUnmaskDialogClosed();
@@ -408,7 +412,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogTimeBeforeAbandonUnmasking) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanResultSuccess) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -418,7 +422,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanResultSuccess) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanTryAgainFailure) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
@@ -429,7 +433,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogRealPanTryAgainFailure) {
}
TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskingDurationResultSuccess) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::SUCCESS);
@@ -442,7 +446,7 @@ TEST_F(CardUnmaskPromptControllerImplTest, LogUnmaskingDurationResultSuccess) {
TEST_F(CardUnmaskPromptControllerImplTest,
LogUnmaskingDurationTryAgainFailure) {
- ShowPromptAndSimulateResponse(false);
+ ShowPromptAndSimulateResponse(/*should_store_pan=*/false);
base::HistogramTester histogram_tester;
controller_->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE);
@@ -487,10 +491,11 @@ TEST_P(CvcInputValidationTest, CvcInputValidation) {
if (!cvc_case.valid)
return;
- controller_->OnUnmaskResponse(ASCIIToUTF16(cvc_case.input), ASCIIToUTF16("1"),
- ASCIIToUTF16("2050"), false);
+ controller_->OnUnmaskPromptAccepted(
+ ASCIIToUTF16(cvc_case.input), ASCIIToUTF16("1"), ASCIIToUTF16("2050"),
+ /*should_store_pan=*/false, /*enable_fido_auth=*/false);
EXPECT_EQ(ASCIIToUTF16(cvc_case.canonicalized_input),
- delegate_->response().cvc);
+ delegate_->details().cvc);
}
INSTANTIATE_TEST_SUITE_P(CardUnmaskPromptControllerImplTest,
@@ -528,10 +533,11 @@ TEST_P(CvcInputAmexValidationTest, CvcInputValidation) {
if (!cvc_case_amex.valid)
return;
- controller_->OnUnmaskResponse(ASCIIToUTF16(cvc_case_amex.input),
- base::string16(), base::string16(), false);
+ controller_->OnUnmaskPromptAccepted(
+ ASCIIToUTF16(cvc_case_amex.input), base::string16(), base::string16(),
+ /*should_store_pan=*/false, /*enable_fido_auth=*/false);
EXPECT_EQ(ASCIIToUTF16(cvc_case_amex.canonicalized_input),
- delegate_->response().cvc);
+ delegate_->details().cvc);
}
INSTANTIATE_TEST_SUITE_P(CardUnmaskPromptControllerImplTest,
diff --git a/chromium/components/autofill/core/browser/ui/payments/save_card_bubble_controller.h b/chromium/components/autofill/core/browser/ui/payments/save_card_bubble_controller.h
deleted file mode 100644
index fe735b6e1d8..00000000000
--- a/chromium/components/autofill/core/browser/ui/payments/save_card_bubble_controller.h
+++ /dev/null
@@ -1,105 +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 COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_SAVE_CARD_BUBBLE_CONTROLLER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_SAVE_CARD_BUBBLE_CONTROLLER_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/payments/legal_message_line.h"
-#include "components/autofill/core/browser/sync_utils.h"
-#include "components/signin/public/identity_manager/account_info.h"
-#include "url/gurl.h"
-
-class Profile;
-
-namespace signin_metrics {
-enum class AccessPoint;
-}
-
-namespace autofill {
-
-class CreditCard;
-class SaveCardBubbleView;
-enum class BubbleType;
-
-// Interface that exposes controller functionality to SaveCardBubbleView.
-class SaveCardBubbleController {
- public:
- SaveCardBubbleController() {}
- virtual ~SaveCardBubbleController() {}
-
- // Returns the title that should be displayed in the bubble.
- virtual base::string16 GetWindowTitle() const = 0;
-
- // Returns the explanatory text that should be displayed in the bubble.
- // Returns an empty string if no message should be displayed.
- virtual base::string16 GetExplanatoryMessage() const = 0;
-
- // Returns the button label text for save card bubbles.
- virtual base::string16 GetAcceptButtonText() const = 0;
- virtual base::string16 GetDeclineButtonText() const = 0;
-
- // Returns the account info of the signed-in user.
- virtual const AccountInfo& GetAccountInfo() const = 0;
-
- // Returns the profile.
- virtual Profile* GetProfile() const = 0;
-
- // Returns the card that will be uploaded if the user accepts.
- virtual const CreditCard& GetCard() const = 0;
-
- // Returns whether the dialog should include a textfield requesting the user
- // to confirm/provide cardholder name.
- virtual bool ShouldRequestNameFromUser() const = 0;
-
- // Returns whether the dialog should include a pair of dropdown lists
- // allowing the user to provide expiration date.
- virtual bool ShouldRequestExpirationDateFromUser() const = 0;
-
- // Returns whether or not a sign in / sync promo needs to be shown.
- virtual bool ShouldShowSignInPromo() const = 0;
-
- // Returns true iff the card saved animation should be shown.
- virtual bool ShouldShowCardSavedAnimation() const = 0;
-
- // Interaction.
- // OnSyncPromoAccepted is called when the Dice Sign-in promo is clicked.
- virtual void OnSyncPromoAccepted(const AccountInfo& account,
- signin_metrics::AccessPoint access_point,
- bool is_default_promo_account) = 0;
- // OnSaveButton takes in a struct representing the cardholder name,
- // expiration date month and expiration date year confirmed/entered by the
- // user if they were requested, or struct with empty strings otherwise.
- virtual void OnSaveButton(const AutofillClient::UserProvidedCardDetails&
- user_provided_card_details) = 0;
- virtual void OnCancelButton() = 0;
- virtual void OnLegalMessageLinkClicked(const GURL& url) = 0;
- virtual void OnManageCardsClicked() = 0;
- virtual void OnBubbleClosed() = 0;
- // Once the animation ends, it shows a new bubble if needed.
- virtual void OnAnimationEnded() = 0;
-
- // State.
-
- // Returns empty vector if no legal message should be shown.
- virtual const LegalMessageLines& GetLegalMessageLines() const = 0;
- // Returns true iff is showing or has showed bubble for upload save.
- virtual bool IsUploadSave() const = 0;
- // Returns the current state of the bubble.
- virtual BubbleType GetBubbleType() const = 0;
- // Returns the current sync state.
- virtual AutofillSyncSigninState GetSyncState() const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleController);
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_SAVE_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chromium/components/autofill/core/browser/ui/suggestion_selection.cc b/chromium/components/autofill/core/browser/ui/suggestion_selection.cc
index 23119174590..1281ad65ae9 100644
--- a/chromium/components/autofill/core/browser/ui/suggestion_selection.cc
+++ b/chromium/components/autofill/core/browser/ui/suggestion_selection.cc
@@ -67,8 +67,10 @@ constexpr size_t kMaxPrunedUniqueSuggestionsCount = 3;
std::vector<Suggestion> GetPrefixMatchedSuggestions(
const AutofillType& type,
+ const base::string16& raw_field_contents,
const base::string16& field_contents_canon,
const AutofillProfileComparator& comparator,
+ bool field_is_autofilled,
const std::vector<AutofillProfile*>& profiles,
std::vector<AutofillProfile*>* matched_profiles) {
std::vector<Suggestion> suggestions;
@@ -81,6 +83,19 @@ std::vector<Suggestion> GetPrefixMatchedSuggestions(
if (profile->ShouldSkipFillingOrSuggesting(type.GetStorableType()))
continue;
+ // Don't offer to fill the exact same value again. If detailed suggestions
+ // with different secondary data is available, it would appear to offer
+ // refilling the whole form with something else. E.g. the same name with a
+ // work and a home address would appear twice but a click would be a noop.
+ // TODO(fhorschig): Consider refilling form instead (at on least Android).
+#if defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(features::kAutofillKeyboardAccessory) &&
+ field_is_autofilled &&
+ profile->GetRawInfo(type.GetStorableType()) == raw_field_contents) {
+ continue;
+ }
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
base::string16 value =
GetInfoInOneLine(profile, type, comparator.app_locale());
if (value.empty())
diff --git a/chromium/components/autofill/core/browser/ui/suggestion_selection.h b/chromium/components/autofill/core/browser/ui/suggestion_selection.h
index d012faae1b5..fb0dd776d66 100644
--- a/chromium/components/autofill/core/browser/ui/suggestion_selection.h
+++ b/chromium/components/autofill/core/browser/ui/suggestion_selection.h
@@ -30,8 +30,10 @@ extern const size_t kMaxPrunedUniqueSuggestionsCount;
// |kMaxSuggestedProfilesCount| are returned.
std::vector<Suggestion> GetPrefixMatchedSuggestions(
const AutofillType& type,
+ const base::string16& raw_field_contents,
const base::string16& field_contents_canon,
const AutofillProfileComparator& comparator,
+ bool field_is_autofilled,
const std::vector<AutofillProfile*>& profiles,
std::vector<AutofillProfile*>* matched_profiles);
diff --git a/chromium/components/autofill/core/browser/ui/suggestion_selection_unittest.cc b/chromium/components/autofill/core/browser/ui/suggestion_selection_unittest.cc
index 2bb414b4c2d..0eac1dcbc39 100644
--- a/chromium/components/autofill/core/browser/ui/suggestion_selection_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/suggestion_selection_unittest.cc
@@ -23,6 +23,7 @@
namespace autofill {
namespace suggestion_selection {
+using base::ASCIIToUTF16;
using testing::Each;
using testing::ElementsAre;
using testing::Field;
@@ -85,7 +86,7 @@ class SuggestionSelectionTest : public testing::Test {
}
base::string16 GetCanonicalUtf16Content(const char* content) {
- return comparator_.NormalizeForComparison(base::ASCIIToUTF16(content));
+ return comparator_.NormalizeForComparison(ASCIIToUTF16(content));
}
std::vector<Suggestion> CreateSuggestions(
@@ -114,13 +115,14 @@ TEST_F(SuggestionSelectionTest,
std::vector<AutofillProfile*> matched_profiles;
auto suggestions = GetPrefixMatchedSuggestions(
- AutofillType(NAME_FIRST), GetCanonicalUtf16Content("Mar"), comparator_,
+ AutofillType(NAME_FIRST), ASCIIToUTF16("Mar"),
+ GetCanonicalUtf16Content("Mar"), comparator_, false,
{profile1.get(), profile2.get()}, &matched_profiles);
ASSERT_EQ(1U, suggestions.size());
ASSERT_EQ(1U, matched_profiles.size());
- EXPECT_THAT(suggestions, ElementsAre(Field(&Suggestion::value,
- base::ASCIIToUTF16("Marion"))));
+ EXPECT_THAT(suggestions,
+ ElementsAre(Field(&Suggestion::value, ASCIIToUTF16("Marion"))));
}
TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_NoMatchingProfile) {
@@ -128,9 +130,10 @@ TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_NoMatchingProfile) {
CreateProfileUniquePtr("Bob");
std::vector<AutofillProfile*> matched_profiles;
- auto suggestions = GetPrefixMatchedSuggestions(
- AutofillType(NAME_FIRST), GetCanonicalUtf16Content("Mar"), comparator_,
- {profile1.get()}, &matched_profiles);
+ auto suggestions =
+ GetPrefixMatchedSuggestions(AutofillType(NAME_FIRST), ASCIIToUTF16("Mar"),
+ GetCanonicalUtf16Content("Mar"), comparator_,
+ false, {profile1.get()}, &matched_profiles);
ASSERT_TRUE(matched_profiles.empty());
ASSERT_TRUE(suggestions.empty());
@@ -139,9 +142,10 @@ TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_NoMatchingProfile) {
TEST_F(SuggestionSelectionTest,
GetPrefixMatchedSuggestions_EmptyProfilesInput) {
std::vector<AutofillProfile*> matched_profiles;
- auto suggestions = GetPrefixMatchedSuggestions(
- AutofillType(NAME_FIRST), GetCanonicalUtf16Content("Mar"), comparator_,
- {}, &matched_profiles);
+ auto suggestions =
+ GetPrefixMatchedSuggestions(AutofillType(NAME_FIRST), ASCIIToUTF16("Mar"),
+ GetCanonicalUtf16Content("Mar"), comparator_,
+ false, {}, &matched_profiles);
ASSERT_TRUE(matched_profiles.empty());
ASSERT_TRUE(suggestions.empty());
@@ -165,23 +169,24 @@ TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_LimitProfiles) {
});
std::vector<AutofillProfile*> matched_profiles;
- auto suggestions = GetPrefixMatchedSuggestions(
- AutofillType(NAME_FIRST), GetCanonicalUtf16Content("Mar"), comparator_,
- profiles_pointers, &matched_profiles);
+ auto suggestions =
+ GetPrefixMatchedSuggestions(AutofillType(NAME_FIRST), ASCIIToUTF16("Mar"),
+ GetCanonicalUtf16Content("Mar"), comparator_,
+ false, profiles_pointers, &matched_profiles);
// Marie should not be found.
ASSERT_EQ(kMaxSuggestedProfilesCount, suggestions.size());
ASSERT_EQ(kMaxSuggestedProfilesCount, matched_profiles.size());
- EXPECT_THAT(suggestions, Each(Field(&Suggestion::value,
- Not(base::ASCIIToUTF16("Marie")))));
+ EXPECT_THAT(suggestions,
+ Each(Field(&Suggestion::value, Not(ASCIIToUTF16("Marie")))));
EXPECT_THAT(matched_profiles,
Each(ResultOf(
[](const AutofillProfile* profile_ptr) {
return profile_ptr->GetRawInfo(NAME_FIRST);
},
- Not(base::ASCIIToUTF16("Marie")))));
+ Not(ASCIIToUTF16("Marie")))));
}
TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_SkipInvalid) {
@@ -206,7 +211,7 @@ TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_SkipInvalid) {
profile_client_invalid_country_empty->SetValidityState(
ADDRESS_HOME_STATE, AutofillProfile::INVALID, AutofillProfile::CLIENT);
profile_client_invalid_country_empty->SetRawInfo(ADDRESS_HOME_COUNTRY,
- base::ASCIIToUTF16(""));
+ ASCIIToUTF16(""));
const std::vector<AutofillProfile*> profiles_data = {
profile_server_invalid.get(), profile_client_invalid.get(),
@@ -214,14 +219,15 @@ TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_SkipInvalid) {
std::vector<AutofillProfile*> matched_profiles;
auto suggestions = GetPrefixMatchedSuggestions(
- AutofillType(ADDRESS_HOME_STATE), GetCanonicalUtf16Content("C"),
- comparator_, profiles_data, &matched_profiles);
+ AutofillType(ADDRESS_HOME_STATE), ASCIIToUTF16("C"),
+ GetCanonicalUtf16Content("C"), comparator_, false, profiles_data,
+ &matched_profiles);
ASSERT_EQ(2U, suggestions.size());
ASSERT_EQ(2U, matched_profiles.size());
EXPECT_THAT(suggestions,
- ElementsAre(Field(&Suggestion::value, base::ASCIIToUTF16("CA")),
- Field(&Suggestion::value, base::ASCIIToUTF16("CA"))));
+ ElementsAre(Field(&Suggestion::value, ASCIIToUTF16("CA")),
+ Field(&Suggestion::value, ASCIIToUTF16("CA"))));
std::vector<AutofillProfile*> expected_result;
expected_result.push_back(profile_valid.get());
@@ -247,9 +253,8 @@ TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_SingleDedupe) {
ASSERT_EQ(1U, unique_suggestions.size());
ASSERT_EQ(1U, unique_matched_profiles.size());
- EXPECT_THAT(
- unique_suggestions,
- ElementsAre(Field(&Suggestion::value, base::ASCIIToUTF16("Bob"))));
+ EXPECT_THAT(unique_suggestions,
+ ElementsAre(Field(&Suggestion::value, ASCIIToUTF16("Bob"))));
}
TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_MultipleDedupe) {
@@ -274,11 +279,10 @@ TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_MultipleDedupe) {
ASSERT_EQ(3U, unique_suggestions.size());
ASSERT_EQ(3U, unique_matched_profiles.size());
- EXPECT_THAT(
- unique_suggestions,
- ElementsAre(Field(&Suggestion::value, base::ASCIIToUTF16("Bob")),
- Field(&Suggestion::value, base::ASCIIToUTF16("Bob")),
- Field(&Suggestion::value, base::ASCIIToUTF16("Mary"))));
+ EXPECT_THAT(unique_suggestions,
+ ElementsAre(Field(&Suggestion::value, ASCIIToUTF16("Bob")),
+ Field(&Suggestion::value, ASCIIToUTF16("Bob")),
+ Field(&Suggestion::value, ASCIIToUTF16("Mary"))));
}
TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_DedupeLimit) {
@@ -308,7 +312,7 @@ TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_DedupeLimit) {
// All profiles are different.
for (size_t i = 0; i < unique_suggestions.size(); i++) {
- ASSERT_EQ(base::ASCIIToUTF16(base::StringPrintf("Bob %zu", i)),
+ ASSERT_EQ(ASCIIToUTF16(base::StringPrintf("Bob %zu", i)),
unique_suggestions[i].value);
}
}
@@ -343,7 +347,7 @@ TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_PruneSuggestions) {
// All profiles are different.
for (size_t i = 0; i < unique_suggestions.size(); i++) {
- ASSERT_EQ(base::ASCIIToUTF16(base::StringPrintf("Bob %zu", i)),
+ ASSERT_EQ(ASCIIToUTF16(base::StringPrintf("Bob %zu", i)),
unique_suggestions[i].value);
}
}
@@ -521,17 +525,15 @@ TEST_F(SuggestionSelectionTest, RemoveProfilesNotUsedSinceTimestamp) {
TEST_F(SuggestionSelectionTest,
PrepareSuggestions_DiscardDuplicateSuggestions) {
- std::vector<Suggestion> suggestions{
- Suggestion(base::ASCIIToUTF16("Jon Snow")),
- Suggestion(base::ASCIIToUTF16("Jon Snow")),
- Suggestion(base::ASCIIToUTF16("Jon Snow")),
- Suggestion(base::ASCIIToUTF16("Jon Snow"))};
+ std::vector<Suggestion> suggestions{Suggestion(ASCIIToUTF16("Jon Snow")),
+ Suggestion(ASCIIToUTF16("Jon Snow")),
+ Suggestion(ASCIIToUTF16("Jon Snow")),
+ Suggestion(ASCIIToUTF16("Jon Snow"))};
const std::vector<base::string16> labels{
- base::ASCIIToUTF16("2 Beyond-the-Wall Rd"),
- base::ASCIIToUTF16("1 Winterfell Ln"),
- base::ASCIIToUTF16("2 Beyond-the-Wall Rd"),
- base::ASCIIToUTF16("2 Beyond-the-Wall Rd.")};
+ ASCIIToUTF16("2 Beyond-the-Wall Rd"), ASCIIToUTF16("1 Winterfell Ln"),
+ ASCIIToUTF16("2 Beyond-the-Wall Rd"),
+ ASCIIToUTF16("2 Beyond-the-Wall Rd.")};
PrepareSuggestions(labels, &suggestions, comparator_);
@@ -540,45 +542,41 @@ TEST_F(SuggestionSelectionTest,
EXPECT_THAT(
suggestions,
ElementsAre(
- AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Jon Snow")),
- Field(&Suggestion::label,
- base::ASCIIToUTF16("2 Beyond-the-Wall Rd"))),
- AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Jon Snow")),
- Field(&Suggestion::label,
- base::ASCIIToUTF16("1 Winterfell Ln")))));
+ AllOf(
+ Field(&Suggestion::value, ASCIIToUTF16("Jon Snow")),
+ Field(&Suggestion::label, ASCIIToUTF16("2 Beyond-the-Wall Rd"))),
+ AllOf(Field(&Suggestion::value, ASCIIToUTF16("Jon Snow")),
+ Field(&Suggestion::label, ASCIIToUTF16("1 Winterfell Ln")))));
}
TEST_F(SuggestionSelectionTest,
PrepareSuggestions_KeepNonDuplicateSuggestions) {
- std::vector<Suggestion> suggestions{
- Suggestion(base::ASCIIToUTF16("Sansa")),
- Suggestion(base::ASCIIToUTF16("Sansa")),
- Suggestion(base::ASCIIToUTF16("Brienne"))};
+ std::vector<Suggestion> suggestions{Suggestion(ASCIIToUTF16("Sansa")),
+ Suggestion(ASCIIToUTF16("Sansa")),
+ Suggestion(ASCIIToUTF16("Brienne"))};
- const std::vector<base::string16> labels{
- base::ASCIIToUTF16("1 Winterfell Ln"), base::ASCIIToUTF16(""),
- base::ASCIIToUTF16("1 Winterfell Ln")};
+ const std::vector<base::string16> labels{ASCIIToUTF16("1 Winterfell Ln"),
+ ASCIIToUTF16(""),
+ ASCIIToUTF16("1 Winterfell Ln")};
PrepareSuggestions(labels, &suggestions, comparator_);
EXPECT_THAT(
suggestions,
ElementsAre(
- AllOf(
- Field(&Suggestion::value, base::ASCIIToUTF16("Sansa")),
- Field(&Suggestion::label, base::ASCIIToUTF16("1 Winterfell Ln"))),
- AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Sansa")),
- Field(&Suggestion::label, base::ASCIIToUTF16(""))),
- AllOf(Field(&Suggestion::value, base::ASCIIToUTF16("Brienne")),
- Field(&Suggestion::label,
- base::ASCIIToUTF16("1 Winterfell Ln")))));
+ AllOf(Field(&Suggestion::value, ASCIIToUTF16("Sansa")),
+ Field(&Suggestion::label, ASCIIToUTF16("1 Winterfell Ln"))),
+ AllOf(Field(&Suggestion::value, ASCIIToUTF16("Sansa")),
+ Field(&Suggestion::label, ASCIIToUTF16(""))),
+ AllOf(Field(&Suggestion::value, ASCIIToUTF16("Brienne")),
+ Field(&Suggestion::label, ASCIIToUTF16("1 Winterfell Ln")))));
}
TEST_F(SuggestionSelectionTest, PrepareSuggestions_SameStringInValueAndLabel) {
std::vector<Suggestion> suggestions{
Suggestion(base::UTF8ToUTF16("4 Mañana Road"))};
- const std::vector<base::string16> labels{base::ASCIIToUTF16("4 manana road")};
+ const std::vector<base::string16> labels{ASCIIToUTF16("4 manana road")};
PrepareSuggestions(labels, &suggestions, comparator_);
EXPECT_THAT(suggestions,
diff --git a/chromium/components/autofill/core/browser/validation.cc b/chromium/components/autofill/core/browser/validation.cc
index 7bdf644c32c..79c8c2aa263 100644
--- a/chromium/components/autofill/core/browser/validation.cc
+++ b/chromium/components/autofill/core/browser/validation.cc
@@ -91,7 +91,7 @@ bool HasCorrectLength(const base::string16& number) {
return true;
}
-// TODO (crbug.com/927767): Add unit tests for this function.
+// TODO(crbug.com/927767): Add unit tests for this function.
bool PassesLuhnCheck(const base::string16& number) {
// Use the Luhn formula [3] to validate the number.
// [3] http://en.wikipedia.org/wiki/Luhn_algorithm
@@ -351,4 +351,12 @@ bool IsInternationalBankAccountNumber(const base::string16& value) {
base::ASCIIToUTF16(kInternationalBankAccountNumberRe));
}
+bool IsPlausibleCreditCardCVCNumber(const base::string16& value) {
+ return MatchesPattern(value, base::ASCIIToUTF16(kCreditCardCVCPattern));
+}
+
+bool IsPlausible4DigitExpirationYear(const base::string16& value) {
+ return MatchesPattern(value,
+ base::ASCIIToUTF16(kCreditCard4DigitExpYearPattern));
+}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/validation.h b/chromium/components/autofill/core/browser/validation.h
index fb72dc6cc51..de07018eabf 100644
--- a/chromium/components/autofill/core/browser/validation.h
+++ b/chromium/components/autofill/core/browser/validation.h
@@ -93,6 +93,12 @@ bool IsUPIVirtualPaymentAddress(const base::string16& value);
// (IBAN). See https://en.wikipedia.org/wiki/International_Bank_Account_Number
bool IsInternationalBankAccountNumber(const base::string16& value);
+// Return true if |value| is a 3 or 4 digit number.
+bool IsPlausibleCreditCardCVCNumber(const base::string16& value);
+
+// Returns true if the value is a 4 digit year in this century.
+bool IsPlausible4DigitExpirationYear(const base::string16& value);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_VALIDATION_H_
diff --git a/chromium/components/autofill/core/browser/validation_unittest.cc b/chromium/components/autofill/core/browser/validation_unittest.cc
index a1b2dd38e14..4dfe0400384 100644
--- a/chromium/components/autofill/core/browser/validation_unittest.cc
+++ b/chromium/components/autofill/core/browser/validation_unittest.cc
@@ -38,26 +38,17 @@ struct SecurityCodeCardTypePair {
// From https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
const char* const kValidNumbers[] = {
- "378282246310005",
- "3714 4963 5398 431",
- "3787-3449-3671-000",
- "5610591081018250",
- "3056 9309 0259 04",
- "3852-0000-0232-37",
- "6011111111111117",
- "6011 0009 9013 9424",
- "3530-1113-3330-0000",
+ "378282246310005", "3714 4963 5398 431", "3787-3449-3671-000",
+ "5610591081018250", "3056 9309 0259 04", "3852-0000-0232-37",
+ "6011111111111117", "6011 0009 9013 9424", "3530-1113-3330-0000",
"3566002020360505",
"5555 5555 5555 4444", // Mastercard.
"5105-1051-0510-5100",
"4111111111111111", // Visa.
- "4012 8888 8888 1881",
- "4222-2222-2222-2",
- "5019717010103742",
- "6331101999990016",
- "6247130048162403",
- "4532261615476013542", // Visa, 19 digits.
- "6362970000457013", // Elo
+ "4012 8888 8888 1881", "4222-2222-2222-2", "5019717010103742",
+ "6331101999990016", "6247130048162403",
+ "4532261615476013542", // Visa, 19 digits.
+ "6362970000457013", // Elo
};
const char* const kInvalidNumbers[] = {
"4111 1111 112", /* too short */
@@ -78,15 +69,15 @@ const IntExpirationDate kInvalidCreditCardIntExpirationDate[] = {
{ 2015, 0 }, // Zero is legal in the CC class but is not a valid date.
};
const SecurityCodeCardTypePair kValidSecurityCodeCardTypePairs[] = {
- { "323", kGenericCard }, // 3-digit CSC.
- { "3234", kAmericanExpressCard }, // 4-digit CSC.
+ {"323", kGenericCard}, // 3-digit CSC.
+ {"3234", kAmericanExpressCard}, // 4-digit CSC.
};
const SecurityCodeCardTypePair kInvalidSecurityCodeCardTypePairs[] = {
- { "32", kGenericCard }, // CSC too short.
- { "323", kAmericanExpressCard }, // CSC too short.
- { "3234", kGenericCard }, // CSC too long.
- { "12345", kAmericanExpressCard }, // CSC too long.
- { "asd", kGenericCard }, // non-numeric CSC.
+ {"32", kGenericCard}, // CSC too short.
+ {"323", kAmericanExpressCard}, // CSC too short.
+ {"3234", kGenericCard}, // CSC too long.
+ {"12345", kAmericanExpressCard}, // CSC too long.
+ {"asd", kGenericCard}, // non-numeric CSC.
};
const char* const kValidEmailAddress[] = {
"user@example",
@@ -100,6 +91,14 @@ const char* const kInvalidEmailAddress[] = {
"user@",
"user@=example.com"
};
+const char* const kUnplausibleCreditCardExpirationYears[] = {
+ "2009", "2134", "1111", "abcd", "2101"};
+const char* const kPlausibleCreditCardExpirationYears[] = {"2018", "2099",
+ "2010", "2050"};
+const char* const kUnplausibleCreditCardCVCNumbers[] = {"abc", "21", "11111",
+ "21a1"};
+const char* const kPlausibleCreditCardCVCNumbers[] = {"1234", "2099", "111",
+ "982"};
} // namespace
TEST(AutofillValidation, IsValidCreditCardNumber) {
@@ -113,6 +112,36 @@ TEST(AutofillValidation, IsValidCreditCardNumber) {
}
}
+// Tests the plausibility of supplied credit card expiration years.
+TEST(AutofillValidation, IsPlausibleCreditCardExparationYear) {
+ for (const char* plausible_year : kPlausibleCreditCardExpirationYears) {
+ EXPECT_TRUE(
+ IsPlausible4DigitExpirationYear(base::ASCIIToUTF16(plausible_year)))
+ << plausible_year;
+ }
+
+ for (const char* unplausible_year : kUnplausibleCreditCardExpirationYears) {
+ EXPECT_FALSE(
+ IsPlausible4DigitExpirationYear(base::ASCIIToUTF16(unplausible_year)))
+ << unplausible_year;
+ }
+}
+
+// Test the plausibility of supplied CVC numbers.
+TEST(AutofillValidation, IsPlausibleCreditCardCVCNumber) {
+ for (const char* plausible_cvc : kPlausibleCreditCardCVCNumbers) {
+ EXPECT_TRUE(
+ IsPlausibleCreditCardCVCNumber(base::ASCIIToUTF16(plausible_cvc)))
+ << plausible_cvc;
+ }
+
+ for (const char* unplausible_cvc : kUnplausibleCreditCardCVCNumbers) {
+ EXPECT_FALSE(
+ IsPlausibleCreditCardCVCNumber(base::ASCIIToUTF16(unplausible_cvc)))
+ << unplausible_cvc;
+ }
+}
+
TEST(AutofillValidation, IsValidCreditCardIntExpirationDate) {
base::Time now;
ASSERT_TRUE(base::Time::FromString(kCurrentDate, &now));
@@ -347,8 +376,8 @@ TEST_P(AutofillCCNumberValidationTest, IsValidCreditCardNumber) {
}
}
-const static std::set<std::string> kAllBasicCardNetworks{
- "amex", "discover", "diners", "elo", "jcb",
+static const std::set<std::string> kAllBasicCardNetworks{
+ "amex", "discover", "diners", "elo", "jcb",
"mastercard", "mir", "unionpay", "visa"};
INSTANTIATE_TEST_SUITE_P(
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
index 4e4f151e152..557cbac1485 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -15,7 +15,6 @@
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/proto/autofill_sync.pb.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/sync/model/entity_data.h"
@@ -303,8 +302,7 @@ AutocompleteSyncBridge::AutocompleteSyncBridge(
AutofillWebDataBackend* backend,
std::unique_ptr<ModelTypeChangeProcessor> change_processor)
: ModelTypeSyncBridge(std::move(change_processor)),
- web_data_backend_(backend),
- scoped_observer_(this) {
+ web_data_backend_(backend) {
DCHECK(web_data_backend_);
scoped_observer_.Add(web_data_backend_);
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
index 78f71ad157f..197e46af932 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
@@ -14,6 +14,7 @@
#include "base/supports_user_data.h"
#include "base/threading/thread_checker.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h"
@@ -23,7 +24,6 @@
namespace autofill {
class AutofillTable;
-class AutofillWebDataBackend;
class AutofillWebDataService;
class AutocompleteSyncBridge
@@ -79,8 +79,9 @@ class AutocompleteSyncBridge
// SupportsUserData, so it's guaranteed to outlive |this|.
AutofillWebDataBackend* const web_data_backend_;
- ScopedObserver<AutofillWebDataBackend, AutocompleteSyncBridge>
- scoped_observer_;
+ ScopedObserver<AutofillWebDataBackend,
+ AutofillWebDataServiceObserverOnDBSequence>
+ scoped_observer_{this};
DISALLOW_COPY_AND_ASSIGN(AutocompleteSyncBridge);
};
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
index cb4168f852c..7ae1e1cadbc 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
@@ -17,7 +17,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
@@ -293,7 +293,7 @@ class AutocompleteSyncBridgeTest : public testing::Test {
private:
ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
deleted file mode 100644
index 2becf32a1b5..00000000000
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 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 "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/feature_list.h"
-#include "base/metrics/histogram.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/prefs/pref_service.h"
-#include "components/sync/driver/sync_client.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync/model/sync_error.h"
-#include "components/sync/model/syncable_service.h"
-
-namespace browser_sync {
-
-AutofillProfileDataTypeController::AutofillProfileDataTypeController(
- scoped_refptr<base::SequencedTaskRunner> db_thread,
- const base::Closure& dump_stack,
- syncer::SyncService* sync_service,
- syncer::SyncClient* sync_client,
- const PersonalDataManagerProvider& pdm_provider,
- const scoped_refptr<autofill::AutofillWebDataService>& web_data_service)
- : AsyncDirectoryTypeController(syncer::AUTOFILL_PROFILE,
- dump_stack,
- sync_service,
- sync_client,
- syncer::GROUP_DB,
- std::move(db_thread)),
- pdm_provider_(pdm_provider),
- web_data_service_(web_data_service),
- callback_registered_(false),
- currently_enabled_(IsEnabled()) {
- pref_registrar_.Init(sync_client->GetPrefService());
- pref_registrar_.Add(
- autofill::prefs::kAutofillProfileEnabled,
- base::Bind(&AutofillProfileDataTypeController::OnUserPrefChanged,
- base::AsWeakPtr(this)));
-}
-
-void AutofillProfileDataTypeController::WebDatabaseLoaded() {
- DCHECK(CalledOnValidThread());
- OnModelLoaded();
-}
-
-void AutofillProfileDataTypeController::OnPersonalDataChanged() {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(state(), MODEL_STARTING);
-
- pdm_provider_.Run()->RemoveObserver(this);
-
- if (!web_data_service_)
- return;
-
- if (web_data_service_->IsDatabaseLoaded()) {
- OnModelLoaded();
- } else if (!callback_registered_) {
- web_data_service_->RegisterDBLoadedCallback(
- base::Bind(&AutofillProfileDataTypeController::WebDatabaseLoaded,
- base::AsWeakPtr(this)));
- callback_registered_ = true;
- }
-}
-
-AutofillProfileDataTypeController::~AutofillProfileDataTypeController() {}
-
-bool AutofillProfileDataTypeController::StartModels() {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(state(), MODEL_STARTING);
-
- if (!IsEnabled())
- return false;
-
- autofill::PersonalDataManager* personal_data = pdm_provider_.Run();
-
- // Waiting for the personal data is subtle: we do this as the PDM resets
- // its cache of unique IDs once it gets loaded. If we were to proceed with
- // association, the local ids in the mappings would wind up colliding.
- if (!personal_data->IsDataLoaded()) {
- personal_data->AddObserver(this);
- return false;
- }
-
- if (!web_data_service_)
- return false;
-
- if (web_data_service_->IsDatabaseLoaded())
- return true;
-
- if (!callback_registered_) {
- web_data_service_->RegisterDBLoadedCallback(
- base::Bind(&AutofillProfileDataTypeController::WebDatabaseLoaded,
- base::AsWeakPtr(this)));
- callback_registered_ = true;
- }
-
- return false;
-}
-
-void AutofillProfileDataTypeController::StopModels() {
- DCHECK(CalledOnValidThread());
- pdm_provider_.Run()->RemoveObserver(this);
-}
-
-bool AutofillProfileDataTypeController::ReadyForStart() const {
- DCHECK(CalledOnValidThread());
- return currently_enabled_;
-}
-
-void AutofillProfileDataTypeController::OnUserPrefChanged() {
- DCHECK(CalledOnValidThread());
-
- bool new_enabled = IsEnabled();
- if (currently_enabled_ == new_enabled)
- return; // No change to sync state.
- currently_enabled_ = new_enabled;
-
- sync_service()->ReadyForStartChanged(type());
-}
-
-bool AutofillProfileDataTypeController::IsEnabled() {
- DCHECK(CalledOnValidThread());
-
- // Require the user-visible pref to be enabled to sync Autofill Profile data.
- return autofill::prefs::IsProfileAutofillEnabled(
- sync_client()->GetPrefService());
-}
-
-} // namespace browser_sync
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
deleted file mode 100644
index f755ca28659..00000000000
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 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 COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/scoped_observer.h"
-#include "base/sequenced_task_runner.h"
-#include "components/autofill/core/browser/personal_data_manager_observer.h"
-#include "components/prefs/pref_change_registrar.h"
-#include "components/sync/driver/async_directory_type_controller.h"
-
-namespace autofill {
-class AutofillWebDataService;
-class PersonalDataManager;
-} // namespace autofill
-
-namespace syncer {
-class SyncClient;
-class SyncService;
-} // namespace syncer
-
-namespace browser_sync {
-
-// Controls syncing of the AUTOFILL_PROFILE data type.
-class AutofillProfileDataTypeController
- : public syncer::AsyncDirectoryTypeController,
- public autofill::PersonalDataManagerObserver {
- public:
- using PersonalDataManagerProvider =
- base::RepeatingCallback<autofill::PersonalDataManager*()>;
-
- // |dump_stack| is called when an unrecoverable error occurs.
- AutofillProfileDataTypeController(
- scoped_refptr<base::SequencedTaskRunner> db_thread,
- const base::Closure& dump_stack,
- syncer::SyncService* sync_service,
- syncer::SyncClient* sync_client,
- const PersonalDataManagerProvider& pdm_provider,
- const scoped_refptr<autofill::AutofillWebDataService>& web_data_service);
- ~AutofillProfileDataTypeController() override;
-
- // PersonalDataManagerObserver:
- void OnPersonalDataChanged() override;
-
- protected:
- // AsyncDirectoryTypeController:
- bool StartModels() override;
- void StopModels() override;
- bool ReadyForStart() const override;
-
- private:
- // Callback to notify that WebDatabase has loaded.
- void WebDatabaseLoaded();
-
- // Callback for changes to the autofill pref.
- void OnUserPrefChanged();
-
- // Returns true if the pref is set such that autofill sync should be enabled.
- bool IsEnabled();
-
- // Callback that allows accessing PersonalDataManager lazily.
- const PersonalDataManagerProvider pdm_provider_;
-
- // A reference to the AutofillWebDataService for this controller.
- scoped_refptr<autofill::AutofillWebDataService> web_data_service_;
-
- // Whether the database loaded callback has been registered.
- bool callback_registered_;
-
- // Registrar for listening to kAutofillWEnabled status.
- PrefChangeRegistrar pref_registrar_;
-
- // Stores whether we're currently syncing autofill data. This is the last
- // value computed by IsEnabled.
- bool currently_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillProfileDataTypeController);
-};
-
-} // namespace browser_sync
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
index 8385d72a5fb..eeda7a580d9 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
@@ -20,8 +20,7 @@ AutofillProfileModelTypeController::AutofillProfileModelTypeController(
: ModelTypeController(syncer::AUTOFILL_PROFILE,
std::move(delegate_on_disk)),
pref_service_(pref_service),
- sync_service_(sync_service),
- currently_enabled_(IsEnabled()) {
+ sync_service_(sync_service) {
pref_registrar_.Init(pref_service_);
pref_registrar_.Add(
autofill::prefs::kAutofillProfileEnabled,
@@ -33,27 +32,18 @@ AutofillProfileModelTypeController::AutofillProfileModelTypeController(
AutofillProfileModelTypeController::~AutofillProfileModelTypeController() =
default;
-bool AutofillProfileModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+AutofillProfileModelTypeController::GetPreconditionState() const {
DCHECK(CalledOnValidThread());
- return currently_enabled_;
+ // Require the user-visible pref to be enabled to sync Autofill Profile data.
+ return autofill::prefs::IsProfileAutofillEnabled(pref_service_)
+ ? PreconditionState::kPreconditionsMet
+ : PreconditionState::kMustStopAndClearData;
}
void AutofillProfileModelTypeController::OnUserPrefChanged() {
DCHECK(CalledOnValidThread());
-
- bool new_enabled = IsEnabled();
- if (currently_enabled_ == new_enabled)
- return;
- currently_enabled_ = new_enabled;
-
- sync_service_->ReadyForStartChanged(type());
-}
-
-bool AutofillProfileModelTypeController::IsEnabled() {
- DCHECK(CalledOnValidThread());
-
- // Require the user-visible pref to be enabled to sync Autofill Profile data.
- return autofill::prefs::IsProfileAutofillEnabled(pref_service_);
+ sync_service_->DataTypePreconditionChanged(type());
}
} // namespace browser_sync
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
index 38aafd7d8d2..ed684b9e63e 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
@@ -30,25 +30,18 @@ class AutofillProfileModelTypeController : public syncer::ModelTypeController {
~AutofillProfileModelTypeController() override;
// DataTypeController overrides.
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
private:
// Callback for changes to the autofill pref.
void OnUserPrefChanged();
- // Returns true if the pref is set such that autofill sync should be enabled.
- bool IsEnabled();
-
PrefService* const pref_service_;
syncer::SyncService* const sync_service_;
// Registrar for listening to prefs::kAutofillProfileEnabled.
PrefChangeRegistrar pref_registrar_;
- // Stores whether we're currently syncing autofill data. This is the last
- // value computed by IsEnabled.
- bool currently_enabled_;
-
DISALLOW_COPY_AND_ASSIGN(AutofillProfileModelTypeController);
};
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
index d253d3754b9..a7f39a9b9cc 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc
@@ -19,7 +19,6 @@
#include "components/autofill/core/browser/proto/autofill_sync.pb.h"
#include "components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/sync/model/entity_data.h"
#include "components/sync/model/metadata_change_list.h"
@@ -79,8 +78,7 @@ AutofillProfileSyncBridge::AutofillProfileSyncBridge(
AutofillWebDataBackend* backend)
: syncer::ModelTypeSyncBridge(std::move(change_processor)),
app_locale_(app_locale),
- web_data_backend_(backend),
- scoped_observer_(this) {
+ web_data_backend_(backend) {
DCHECK(web_data_backend_);
scoped_observer_.Add(web_data_backend_);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h
index bc5539d6c4d..d03693a76ea 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h
@@ -14,6 +14,7 @@
#include "base/supports_user_data.h"
#include "base/threading/thread_checker.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/sync/model/model_type_sync_bridge.h"
@@ -27,7 +28,6 @@ namespace autofill {
class AutofillProfileSyncDifferenceTracker;
class AutofillTable;
-class AutofillWebDataBackend;
class AutofillWebDataService;
enum class AutofillProfileSyncChangeOrigin;
@@ -107,8 +107,9 @@ class AutofillProfileSyncBridge
// SupportsUserData, so it's guaranteed to outlive |this|.
AutofillWebDataBackend* const web_data_backend_;
- ScopedObserver<AutofillWebDataBackend, AutofillProfileSyncBridge>
- scoped_observer_;
+ ScopedObserver<AutofillWebDataBackend,
+ AutofillWebDataServiceObserverOnDBSequence>
+ scoped_observer_{this};
DISALLOW_COPY_AND_ASSIGN(AutofillProfileSyncBridge);
};
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
index fe32010cd57..e0579be7e08 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc
@@ -18,7 +18,7 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_profile_sync_util.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -321,7 +321,7 @@ class AutofillProfileSyncBridgeTest : public testing::Test {
private:
autofill::TestAutofillClock test_clock_;
ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc
index 799ff0034ba..5a30b96128b 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc
@@ -8,7 +8,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_profile_sync_util.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -107,7 +107,7 @@ class AutofillProfileSyncDifferenceTrackerTestBase : public testing::Test {
private:
autofill::TestAutofillClock test_clock_;
base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
AutofillTable table_;
WebDatabase db_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
index 58201f7e9b2..8ca4ca830a3 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -11,7 +11,6 @@
#include "base/base64.h"
#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/pickle.h"
#include "components/autofill/core/browser/data_model/autofill_metadata.h"
@@ -19,7 +18,6 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_util.h"
@@ -328,9 +326,7 @@ AutofillWalletMetadataSyncBridge::AutofillWalletMetadataSyncBridge(
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
AutofillWebDataBackend* web_data_backend)
: ModelTypeSyncBridge(std::move(change_processor)),
- web_data_backend_(web_data_backend),
- scoped_observer_(this),
- track_wallet_data_(false) {
+ web_data_backend_(web_data_backend) {
DCHECK(web_data_backend_);
scoped_observer_.Add(web_data_backend_);
@@ -343,11 +339,6 @@ AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-void AutofillWalletMetadataSyncBridge::OnWalletDataTrackingStateChanged(
- bool is_tracking) {
- track_wallet_data_ = is_tracking;
-}
-
std::unique_ptr<syncer::MetadataChangeList>
AutofillWalletMetadataSyncBridge::CreateMetadataChangeList() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -475,26 +466,10 @@ void AutofillWalletMetadataSyncBridge::LoadDataCacheAndMetadata() {
for (const auto& it : addresses_metadata) {
cache_[GetStorageKeyForWalletMetadataTypeAndId(
WalletMetadataSpecifics::ADDRESS, it.first)] = it.second;
- // TODO(crbug.com/949034): Consider adding standard functions for recording
- // large times in seconds/minutes.
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Autofill.WalletUseDateInMinutes.Address",
- /*sample=*/(AutofillClock::Now() - it.second.use_date).InMinutes(),
- /*min=*/base::TimeDelta::FromMinutes(1).InMinutes(),
- /*max=*/base::TimeDelta::FromDays(365).InMinutes(),
- /*bucket_count=*/50);
}
for (const auto& it : cards_metadata) {
cache_[GetStorageKeyForWalletMetadataTypeAndId(
WalletMetadataSpecifics::CARD, it.first)] = it.second;
- // TODO(crbug.com/949034): Consider adding standard functions for recording
- // large times in seconds/minutes.
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Autofill.WalletUseDateInMinutes.Card",
- /*sample=*/(AutofillClock::Now() - it.second.use_date).InMinutes(),
- /*min=*/base::TimeDelta::FromMinutes(1).InMinutes(),
- /*max=*/base::TimeDelta::FromDays(365).InMinutes(),
- /*bucket_count=*/50);
}
// Load the metadata and send to the processor.
@@ -548,7 +523,6 @@ void AutofillWalletMetadataSyncBridge::DeleteOldOrphanMetadata() {
return;
}
- int deleted_count = 0;
std::unique_ptr<MetadataChangeList> metadata_change_list =
CreateMetadataChangeList();
for (const std::string storage_key : old_orphan_keys) {
@@ -558,11 +532,8 @@ void AutofillWalletMetadataSyncBridge::DeleteOldOrphanMetadata() {
parsed_storage_key.metadata_id)) {
cache_.erase(storage_key);
change_processor()->Delete(storage_key, metadata_change_list.get());
- ++deleted_count;
}
}
- UMA_HISTOGRAM_COUNTS_100("Sync.WalletMetadata.DeletedOldOrphans",
- deleted_count);
// Commit the transaction to make sure the data and the metadata is written
// down (especially on Android where we cannot rely on committing transactions
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
index e808b4c0fed..43d98a1eb62 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
@@ -14,6 +14,7 @@
#include "base/sequence_checker.h"
#include "base/supports_user_data.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h"
@@ -27,7 +28,6 @@ struct EntityData;
namespace autofill {
class AutofillTable;
-class AutofillWebDataBackend;
class AutofillWebDataService;
// Sync bridge responsible for propagating local changes to the processor and
@@ -53,10 +53,6 @@ class AutofillWalletMetadataSyncBridge
AutofillWebDataBackend* web_data_backend);
~AutofillWalletMetadataSyncBridge() override;
- // Determines whether this bridge should be monitoring the Wallet data. This
- // should be called whenever the data bridge sync state changes.
- void OnWalletDataTrackingStateChanged(bool is_tracking);
-
base::WeakPtr<AutofillWalletMetadataSyncBridge> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
@@ -128,18 +124,14 @@ class AutofillWalletMetadataSyncBridge
// SupportsUserData, so it's guaranteed to outlive |this|.
AutofillWebDataBackend* const web_data_backend_;
- ScopedObserver<AutofillWebDataBackend, AutofillWalletMetadataSyncBridge>
- scoped_observer_;
+ ScopedObserver<AutofillWebDataBackend,
+ AutofillWebDataServiceObserverOnDBSequence>
+ scoped_observer_{this};
// Cache of the local data that allows figuring out the diff for local
// changes; keyed by storage keys.
std::map<std::string, AutofillMetadata> cache_;
- // Indicates whether we should rely on wallet data being actively synced. If
- // true, the bridge will prune metadata entries without corresponding wallet
- // data entry.
- bool track_wallet_data_;
-
// The bridge should be used on the same sequence where it is constructed.
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
index 70da95f6a80..eeae78ff20d 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
@@ -17,8 +17,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/data_model/autofill_metadata.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -452,7 +451,7 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test {
int response_version = 0;
autofill::TestAutofillClock test_clock_;
ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
@@ -867,7 +866,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
// Verify that old orphan metadata gets deleted on startup.
TEST_F(AutofillWalletMetadataSyncBridgeTest, DeleteOldOrphanMetadataOnStartup) {
- base::HistogramTester histogram_tester;
WalletMetadataSpecifics profile =
CreateWalletMetadataSpecificsForAddressWithDetails(
kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
@@ -889,8 +887,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, DeleteOldOrphanMetadataOnStartup) {
EXPECT_CALL(*backend(), CommitChanges());
ResetBridge();
- histogram_tester.ExpectBucketCount("Sync.WalletMetadata.DeletedOldOrphans",
- /*bucket=*/2, /*count=*/1);
ASSERT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
}
@@ -898,7 +894,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, DeleteOldOrphanMetadataOnStartup) {
// Verify that recent orphan metadata does not get deleted on startup.
TEST_F(AutofillWalletMetadataSyncBridgeTest,
DoNotDeleteOldNonOrphanMetadataOnStartup) {
- base::HistogramTester histogram_tester;
WalletMetadataSpecifics profile =
CreateWalletMetadataSpecificsForAddressWithDetails(
kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
@@ -918,8 +913,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
EXPECT_CALL(*backend(), CommitChanges()).Times(0);
ResetBridge();
- histogram_tester.ExpectTotalCount("Sync.WalletMetadata.DeletedOldOrphans",
- /*count=*/0);
EXPECT_THAT(
GetAllLocalDataInclRestart(),
@@ -929,7 +922,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
// Verify that recent orphan metadata does not get deleted on startup.
TEST_F(AutofillWalletMetadataSyncBridgeTest,
DoNotDeleteRecentOrphanMetadataOnStartup) {
- base::HistogramTester histogram_tester;
WalletMetadataSpecifics profile =
CreateWalletMetadataSpecificsForAddressWithDetails(
kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
@@ -948,8 +940,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
EXPECT_CALL(*backend(), CommitChanges()).Times(0);
ResetBridge();
- histogram_tester.ExpectTotalCount("Sync.WalletMetadata.DeletedOldOrphans",
- /*count=*/0);
EXPECT_THAT(
GetAllLocalDataInclRestart(),
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
deleted file mode 100644
index 2d97e51bef0..00000000000
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
+++ /dev/null
@@ -1,808 +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 "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
-
-#include <stddef.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/time/time.h"
-#include "components/autofill/core/browser/data_model/autofill_data_model.h"
-#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/browser/webdata/autofill_change.h"
-#include "components/autofill/core/browser/webdata/autofill_table.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_clock.h"
-#include "components/autofill/core/common/autofill_util.h"
-#include "components/sync/model/sync_change.h"
-#include "components/sync/model/sync_change_processor.h"
-#include "components/sync/model/sync_data.h"
-#include "components/sync/model/sync_error_factory.h"
-#include "components/sync/protocol/sync.pb.h"
-
-namespace autofill {
-
-namespace {
-
-void* AutofillWalletMetadataSyncableServiceUserDataKey() {
- // Use the address of a static so that COMDAT folding won't ever fold
- // with something else.
- static int user_data_key = 0;
- return reinterpret_cast<void*>(&user_data_key);
-}
-
-// Sets the common syncable |metadata| for the |local_data_model|.
-void SetCommonMetadata(sync_pb::WalletMetadataSpecifics::Type type,
- const std::string& server_id,
- const AutofillDataModel& local_data_model,
- sync_pb::WalletMetadataSpecifics* metadata) {
- metadata->set_type(type);
- metadata->set_id(server_id);
- metadata->set_use_count(local_data_model.use_count());
- metadata->set_use_date(local_data_model.use_date().ToInternalValue());
-}
-
-// Returns syncable metadata for the |local_profile|.
-syncer::SyncData BuildSyncData(sync_pb::WalletMetadataSpecifics::Type type,
- const std::string& server_id,
- const AutofillProfile& local_profile) {
- sync_pb::EntitySpecifics entity;
- sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
- SetCommonMetadata(type, server_id, local_profile, metadata);
- metadata->set_address_has_converted(local_profile.has_converted());
- std::string sync_tag = "address-" + server_id;
-
- return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
-}
-
-// Returns syncable metadata for the |local_card|.
-syncer::SyncData BuildSyncData(sync_pb::WalletMetadataSpecifics::Type type,
- const std::string& server_id,
- const CreditCard& local_card) {
- sync_pb::EntitySpecifics entity;
- sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
- SetCommonMetadata(type, server_id, local_card, metadata);
- // The strings must be in valid UTF-8 to sync.
- std::string billing_address_id;
- base::Base64Encode(local_card.billing_address_id(), &billing_address_id);
- metadata->set_card_billing_address_id(billing_address_id);
- std::string sync_tag = "card-" + server_id;
-
- return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
-}
-
-// If the metadata exists locally, undelete it on the sync server.
-template <class DataType>
-void UndeleteMetadataIfExisting(
- const std::string& server_id,
- const sync_pb::WalletMetadataSpecifics::Type& metadata_type,
- std::unordered_map<std::string, std::unique_ptr<DataType>>* locals,
- syncer::SyncChangeList* changes_to_sync) {
- const auto& it = locals->find(server_id);
- if (it != locals->end()) {
- std::unique_ptr<DataType> local_metadata = std::move(it->second);
- locals->erase(it);
- changes_to_sync->push_back(syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_ADD,
- BuildSyncData(metadata_type, server_id, *local_metadata)));
- }
-}
-
-syncer::SyncDataList::iterator FindServerIdAndTypeInCache(
- const std::string& server_id,
- const sync_pb::WalletMetadataSpecifics::Type& type,
- syncer::SyncDataList* cache) {
- for (auto it = cache->begin(); it != cache->end(); ++it) {
- if (server_id == it->GetSpecifics().wallet_metadata().id() &&
- type == it->GetSpecifics().wallet_metadata().type()) {
- return it;
- }
- }
-
- return cache->end();
-}
-
-syncer::SyncDataList::iterator FindItemInCache(const syncer::SyncData& item,
- syncer::SyncDataList* cache) {
- return FindServerIdAndTypeInCache(
- item.GetSpecifics().wallet_metadata().id(),
- item.GetSpecifics().wallet_metadata().type(), cache);
-}
-
-void RemoveItemFromCache(const syncer::SyncData& item,
- syncer::SyncDataList* cache) {
- auto it = FindItemInCache(item, cache);
- if (it != cache->end())
- cache->erase(it);
-}
-
-void AddOrUpdateItemInCache(const syncer::SyncData& item,
- syncer::SyncDataList* cache) {
- auto it = FindItemInCache(item, cache);
- if (it != cache->end())
- *it = item;
- else
- cache->push_back(item);
-}
-
-void ApplyChangesToCache(const syncer::SyncChangeList& changes,
- syncer::SyncDataList* cache) {
- for (const syncer::SyncChange& change : changes) {
- switch (change.change_type()) {
- case syncer::SyncChange::ACTION_ADD:
- // Intentional fall through.
- case syncer::SyncChange::ACTION_UPDATE:
- AddOrUpdateItemInCache(change.sync_data(), cache);
- break;
-
- case syncer::SyncChange::ACTION_DELETE:
- RemoveItemFromCache(change.sync_data(), cache);
- break;
-
- case syncer::SyncChange::ACTION_INVALID:
- NOTREACHED();
- break;
- }
- }
-}
-
-template <class DataType>
-bool AreLocalUseStatsUpdated(const sync_pb::WalletMetadataSpecifics& remote,
- const DataType& local) {
- return base::checked_cast<size_t>(remote.use_count()) < local.use_count() &&
- base::Time::FromInternalValue(remote.use_date()) < local.use_date();
-}
-
-bool IsLocalBillingAddressUpdated(
- const sync_pb::WalletMetadataSpecifics& remote,
- const CreditCard& local) {
- std::string remote_billing_address_id;
- base::Base64Decode(remote.card_billing_address_id(),
- &remote_billing_address_id);
- return local.billing_address_id() != remote_billing_address_id;
-}
-
-bool IsLocalHasConvertedStatusUpdated(
- const sync_pb::WalletMetadataSpecifics& remote,
- const AutofillProfile& local) {
- return remote.address_has_converted() != local.has_converted();
-}
-
-// Merges the metadata of the remote and local versions of the data model.
-void MergeCommonMetadata(
- const sync_pb::WalletMetadataSpecifics& remote_metadata,
- AutofillDataModel* local_model,
- bool* is_remote_outdated,
- bool* is_local_modified) {
- size_t remote_use_count =
- base::checked_cast<size_t>(remote_metadata.use_count());
- base::Time remote_use_date =
- base::Time::FromInternalValue(remote_metadata.use_date());
-
- // If the two models have the same metadata, do nothing.
- if (local_model->use_count() == remote_use_count &&
- local_model->use_date() == remote_use_date) {
- return;
- }
-
- // Special case for local models with a use_count of one. This means the local
- // model was only created, never used. The remote model should always be
- // preferred.
- // This situation can happen for new Chromium instances where there is no data
- // yet on disk, making the use_date artifically high. Once the metadata sync
- // kicks in, we should use that value.
- if (local_model->use_count() == 1) {
- local_model->set_use_date(remote_use_date);
- local_model->set_use_count(remote_use_count);
- *is_local_modified = true;
- } else {
- // Otherwise, just keep the most recent use date and biggest use count.
- if (local_model->use_date() < remote_use_date) {
- local_model->set_use_date(remote_use_date);
- *is_local_modified = true;
- } else if (local_model->use_date() > remote_use_date) {
- *is_remote_outdated = true;
- }
-
- if (local_model->use_count() < remote_use_count) {
- local_model->set_use_count(remote_use_count);
- *is_local_modified = true;
- } else if (local_model->use_count() > remote_use_count) {
- *is_remote_outdated = true;
- }
- }
-}
-
-// Merges the metadata of the remote and local versions of the profile.
-void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
- AutofillProfile* local_profile,
- bool* is_remote_outdated,
- bool* is_local_modified) {
- // Merge the has_converted status.
- if (local_profile->has_converted() !=
- remote_metadata.address_has_converted()) {
- if (!local_profile->has_converted()) {
- local_profile->set_has_converted(true);
- *is_local_modified = true;
- } else {
- *is_remote_outdated = true;
- }
- }
-
- // Merge the use_count and use_date.
- MergeCommonMetadata(remote_metadata, local_profile, is_remote_outdated,
- is_local_modified);
-}
-
-// Whether the |current_billing_address_id| is considered outdated compared to
-// the |proposed_billing_address_id|.
-bool IsBillingAddressOutdated(const std::string& current_billing_address_id,
- const std::string& proposed_billing_address_id) {
- DCHECK(current_billing_address_id != proposed_billing_address_id);
-
- // If the current billing address is empty, or if the current one refers to a
- // server address and the proposed one refers to a local address, the current
- // billing address is considered outdated.
- return current_billing_address_id.empty() ||
- (current_billing_address_id.size() != kLocalGuidSize &&
- proposed_billing_address_id.size() == kLocalGuidSize);
-}
-
-// Merges the metadata of the remote and local versions of the credit card.
-void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
- CreditCard* local_card,
- bool* is_remote_outdated,
- bool* is_local_modified) {
- // Merge the billing_address_id. Do this before updating the use_count
- // because it may be used to determine what id to keep.
- std::string remote_billing_address_id;
- base::Base64Decode(remote_metadata.card_billing_address_id(),
- &remote_billing_address_id);
-
- if (local_card->billing_address_id() != remote_billing_address_id) {
- if (IsBillingAddressOutdated(local_card->billing_address_id(),
- remote_billing_address_id)) {
- local_card->set_billing_address_id(remote_billing_address_id);
- *is_local_modified = true;
- } else if (IsBillingAddressOutdated(remote_billing_address_id,
- local_card->billing_address_id())) {
- *is_remote_outdated = true;
- } else {
- // The cards have a different non-empty billing address id and both refer
- // to the same type of address. Keep the billing address id of the most
- // recently used card. If both have the same timestamp, the remote version
- // should be kept in order to stabilize the values.
- base::Time remote_use_date =
- base::Time::FromInternalValue(remote_metadata.use_date());
- if (local_card->use_date() <= remote_use_date) {
- local_card->set_billing_address_id(remote_billing_address_id);
- *is_local_modified = true;
- } else {
- *is_remote_outdated = true;
- }
- }
- }
-
- // Merge the use_count and use_date.
- MergeCommonMetadata(remote_metadata, local_card, is_remote_outdated,
- is_local_modified);
-}
-
-// Merges |remote| metadata into a collection of metadata |locals|. Returns true
-// if the corresponding local metadata was found.
-//
-// Stores an "update" in |changes_to_sync| if |remote| corresponds to an item in
-// |locals| that has higher use count and later use date.
-template <class DataType>
-bool MergeRemote(
- const syncer::SyncData& remote,
- const base::Callback<bool(const DataType&)>& updater,
- bool* is_any_local_modified,
- std::unordered_map<std::string, std::unique_ptr<DataType>>* locals,
- syncer::SyncChangeList* changes_to_sync) {
- DCHECK(locals);
- DCHECK(changes_to_sync);
-
- const sync_pb::WalletMetadataSpecifics& remote_metadata =
- remote.GetSpecifics().wallet_metadata();
- auto it = locals->find(remote_metadata.id());
- if (it == locals->end())
- return false;
-
- std::unique_ptr<DataType> local_metadata = std::move(it->second);
- locals->erase(it);
-
- bool is_local_modified = false;
- bool is_remote_outdated = false;
- MergeMetadata(remote_metadata, local_metadata.get(), &is_remote_outdated,
- &is_local_modified);
-
- if (is_remote_outdated) {
- changes_to_sync->push_back(syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
- BuildSyncData(remote_metadata.type(), remote_metadata.id(),
- *local_metadata)));
- }
-
- if (is_local_modified) {
- updater.Run(*local_metadata);
- *is_any_local_modified = true;
- }
-
- return true;
-}
-
-template <typename DataType>
-std::string GetServerId(const DataType& data) {
- std::string server_id;
- base::Base64Encode(data.server_id(), &server_id);
- return server_id;
-}
-
-} // namespace
-
-AutofillWalletMetadataSyncableService::
- ~AutofillWalletMetadataSyncableService() {}
-
-void AutofillWalletMetadataSyncableService::OnWalletDataTrackingStateChanged(
- bool is_tracking) {
- DCHECK_NE(track_wallet_data_, is_tracking);
- track_wallet_data_ = is_tracking;
- if (is_tracking && sync_processor_) {
- MergeData(cache_);
- }
-}
-
-void AutofillWalletMetadataSyncableService::WaitUntilReadyToSync(
- base::OnceClosure done) {
- // Not used in the legacy directory-based architecture.
- NOTREACHED();
-}
-
-syncer::SyncMergeResult
-AutofillWalletMetadataSyncableService::MergeDataAndStartSyncing(
- syncer::ModelType type,
- const syncer::SyncDataList& initial_sync_data,
- std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
- std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!sync_processor_);
- DCHECK(!sync_error_factory_);
- DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
-
- sync_processor_ = std::move(sync_processor);
- sync_error_factory_ = std::move(sync_error_factory);
-
- cache_ = initial_sync_data;
-
- syncer::SyncMergeResult result(syncer::AUTOFILL_WALLET_METADATA);
- if (track_wallet_data_) {
- result = MergeData(initial_sync_data);
- }
-
- // Record ages for individual metadata entities to UMA.
- for (const syncer::SyncData& data : cache_) {
- const sync_pb::WalletMetadataSpecifics& specifics =
- data.GetSpecifics().wallet_metadata();
- base::Time use_date = base::Time::FromDeltaSinceWindowsEpoch(
- base::TimeDelta::FromMicroseconds(specifics.use_date()));
- switch (specifics.type()) {
- case sync_pb::WalletMetadataSpecifics::ADDRESS:
- // TODO(crbug.com/949034): Consider adding standard functions for
- // recording large times in seconds/minutes.
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Autofill.WalletUseDateInMinutes.Address",
- /*sample=*/(AutofillClock::Now() - use_date).InMinutes(),
- /*min=*/base::TimeDelta::FromMinutes(1).InMinutes(),
- /*max=*/base::TimeDelta::FromDays(365).InMinutes(),
- /*bucket_count=*/50);
- break;
- case sync_pb::WalletMetadataSpecifics::CARD:
- // TODO(crbug.com/949034): Consider adding standard functions for
- // recording large times in seconds/minutes.
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Autofill.WalletUseDateInMinutes.Card",
- /*sample=*/(AutofillClock::Now() - use_date).InMinutes(),
- /*min=*/base::TimeDelta::FromMinutes(1).InMinutes(),
- /*max=*/base::TimeDelta::FromDays(365).InMinutes(),
- /*bucket_count=*/50);
- break;
- case sync_pb::WalletMetadataSpecifics::UNKNOWN:
- NOTREACHED();
- break;
- }
- }
-
- // Notify that sync has started. This callback does not currently take into
- // account whether we're actually tracking wallet data.
- if (web_data_backend_)
- web_data_backend_->NotifyThatSyncHasStarted(type);
- return result;
-}
-
-void AutofillWalletMetadataSyncableService::StopSyncing(
- syncer::ModelType type) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
-
- sync_processor_.reset();
- sync_error_factory_.reset();
- cache_.clear();
-}
-
-syncer::SyncDataList AutofillWalletMetadataSyncableService::GetAllSyncData(
- syncer::ModelType type) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);
-
- syncer::SyncDataList data_list;
- std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
- std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
- if (GetLocalData(&profiles, &cards)) {
- for (const auto& it : profiles) {
- data_list.push_back(BuildSyncData(
- sync_pb::WalletMetadataSpecifics::ADDRESS, it.first, *it.second));
- }
-
- for (const auto& it : cards) {
- data_list.push_back(BuildSyncData(sync_pb::WalletMetadataSpecifics::CARD,
- it.first, *it.second));
- }
- }
-
- return data_list;
-}
-
-syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges(
- const base::Location& from_here,
- const syncer::SyncChangeList& changes_from_sync) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- ApplyChangesToCache(changes_from_sync, &cache_);
-
- // If we're not tracking wallet data, we can't rely on the local wallet
- // data being up-to-date, so we should not do any merging with local data.
- if (!track_wallet_data_) {
- return syncer::SyncError();
- }
-
- std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
- std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
- GetLocalData(&profiles, &cards);
-
- // base::Unretained is used because the callbacks are invoked synchronously.
- base::Callback<bool(const AutofillProfile&)> address_updater =
- base::Bind(&AutofillWalletMetadataSyncableService::UpdateAddressStats,
- base::Unretained(this));
- base::Callback<bool(const CreditCard&)> card_updater =
- base::Bind(&AutofillWalletMetadataSyncableService::UpdateCardStats,
- base::Unretained(this));
-
- bool is_any_local_modified = false;
-
- syncer::SyncChangeList changes_to_sync;
- for (const syncer::SyncChange& change : changes_from_sync) {
- const sync_pb::WalletMetadataSpecifics& remote_metadata =
- change.sync_data().GetSpecifics().wallet_metadata();
- switch (change.change_type()) {
- case syncer::SyncChange::ACTION_ADD:
- // Intentional fall through.
- case syncer::SyncChange::ACTION_UPDATE:
- switch (remote_metadata.type()) {
- case sync_pb::WalletMetadataSpecifics::ADDRESS:
- MergeRemote(change.sync_data(), address_updater,
- &is_any_local_modified, &profiles, &changes_to_sync);
- break;
-
- case sync_pb::WalletMetadataSpecifics::CARD:
- MergeRemote(change.sync_data(), card_updater,
- &is_any_local_modified, &cards, &changes_to_sync);
- break;
-
- case sync_pb::WalletMetadataSpecifics::UNKNOWN:
- NOTREACHED();
- break;
- }
- break;
-
- // Metadata should only be deleted when the underlying data is deleted.
- case syncer::SyncChange::ACTION_DELETE:
- switch (remote_metadata.type()) {
- case sync_pb::WalletMetadataSpecifics::ADDRESS:
- UndeleteMetadataIfExisting(
- remote_metadata.id(), sync_pb::WalletMetadataSpecifics::ADDRESS,
- &profiles, &changes_to_sync);
- break;
-
- case sync_pb::WalletMetadataSpecifics::CARD:
- UndeleteMetadataIfExisting(remote_metadata.id(),
- sync_pb::WalletMetadataSpecifics::CARD,
- &cards, &changes_to_sync);
- break;
-
- case sync_pb::WalletMetadataSpecifics::UNKNOWN:
- NOTREACHED();
- break;
- }
- break;
-
- case syncer::SyncChange::ACTION_INVALID:
- NOTREACHED();
- break;
- }
- }
-
- syncer::SyncError status;
- if (!changes_to_sync.empty())
- status = SendChangesToSyncServer(changes_to_sync);
- if (is_any_local_modified) {
- // TODO(crbug.com/900607): Remove the need to listen to
- // AutofillMultipleChangedBySync() in the new USS implementation so that we
- // can get rid of this hack.
- DCHECK(!ignore_multiple_changed_notification_);
- ignore_multiple_changed_notification_ = true;
- web_data_backend_->NotifyOfMultipleAutofillChanges();
- ignore_multiple_changed_notification_ = false;
- }
-
- return status;
-}
-
-void AutofillWalletMetadataSyncableService::AutofillProfileChanged(
- const AutofillProfileChange& change) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(change.data_model());
- if (!track_wallet_data_) {
- return;
- }
-
- if (sync_processor_ && change.type() == AutofillProfileChange::UPDATE &&
- change.data_model()->record_type() != AutofillProfile::LOCAL_PROFILE) {
- std::string server_id = GetServerId(*change.data_model());
- auto it = FindServerIdAndTypeInCache(
- server_id, sync_pb::WalletMetadataSpecifics::ADDRESS, &cache_);
- if (it == cache_.end())
- return;
-
- const sync_pb::WalletMetadataSpecifics& remote =
- it->GetSpecifics().wallet_metadata();
- const AutofillProfile& local = *change.data_model();
-
-
- if (!AreLocalUseStatsUpdated(remote, local) &&
- !IsLocalHasConvertedStatusUpdated(remote, local)) {
- return;
- }
-
- SendChangesToSyncServer(syncer::SyncChangeList(
- 1, syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
- BuildSyncData(sync_pb::WalletMetadataSpecifics::ADDRESS,
- server_id, local))));
- }
-}
-
-void AutofillWalletMetadataSyncableService::CreditCardChanged(
- const CreditCardChange& change) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!track_wallet_data_) {
- return;
- }
-
- if (sync_processor_ && change.data_model() &&
- change.data_model()->record_type() != CreditCard::LOCAL_CARD) {
- std::string server_id = GetServerId(*change.data_model());
- auto it = FindServerIdAndTypeInCache(
- server_id, sync_pb::WalletMetadataSpecifics::CARD, &cache_);
- if (it == cache_.end())
- return;
- // Deletions and creations are treated by Wallet data sync (and propagated
- // here by AutofillMultipleChangedBySync()). We only treat updates here.
- if (change.type() != AutofillProfileChange::UPDATE) {
- return;
- }
-
- const sync_pb::WalletMetadataSpecifics& remote =
- it->GetSpecifics().wallet_metadata();
- const CreditCard& local = *change.data_model();
- if (!AreLocalUseStatsUpdated(remote, local) &&
- !IsLocalBillingAddressUpdated(remote, local)) {
- return;
- }
-
- SendChangesToSyncServer(syncer::SyncChangeList(
- 1,
- syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
- BuildSyncData(sync_pb::WalletMetadataSpecifics::CARD,
- server_id, local))));
- }
-}
-
-void AutofillWalletMetadataSyncableService::AutofillMultipleChangedBySync() {
- if (ignore_multiple_changed_notification_) {
- // TODO(crbug.com/900607): Remove the need to listen to
- // AutofillMultipleChangedBySync() in the new USS implementation so that we
- // can get rid of this hack.
- return;
- }
-
- if (sync_processor_ && track_wallet_data_)
- MergeData(cache_);
-}
-
-// static
-void AutofillWalletMetadataSyncableService::CreateForWebDataServiceAndBackend(
- AutofillWebDataService* web_data_service,
- AutofillWebDataBackend* web_data_backend,
- const std::string& app_locale) {
- web_data_service->GetDBUserData()->SetUserData(
- AutofillWalletMetadataSyncableServiceUserDataKey(),
- std::make_unique<AutofillWalletMetadataSyncableService>(web_data_backend,
- app_locale));
-}
-
-// static
-AutofillWalletMetadataSyncableService*
-AutofillWalletMetadataSyncableService::FromWebDataService(
- AutofillWebDataService* web_data_service) {
- return static_cast<AutofillWalletMetadataSyncableService*>(
- web_data_service->GetDBUserData()->GetUserData(
- AutofillWalletMetadataSyncableServiceUserDataKey()));
-}
-
-AutofillWalletMetadataSyncableService::AutofillWalletMetadataSyncableService(
- AutofillWebDataBackend* web_data_backend,
- const std::string& app_locale)
- : web_data_backend_(web_data_backend),
- scoped_observer_(this),
- track_wallet_data_(false),
- ignore_multiple_changed_notification_(false) {
- scoped_observer_.Add(web_data_backend_);
-}
-
-bool AutofillWalletMetadataSyncableService::GetLocalData(
- std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>* profiles,
- std::unordered_map<std::string, std::unique_ptr<CreditCard>>* cards) const {
- std::vector<std::unique_ptr<AutofillProfile>> profile_list;
- bool success =
- AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
- ->GetServerProfiles(&profile_list);
- while (!profile_list.empty()) {
- auto server_id = GetServerId(*profile_list.front());
- (*profiles)[server_id] = std::move(profile_list.front());
- profile_list.erase(profile_list.begin());
- }
-
- std::vector<std::unique_ptr<CreditCard>> card_list;
- success &= AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
- ->GetServerCreditCards(&card_list);
- while (!card_list.empty()) {
- auto server_id = GetServerId(*card_list.front());
- (*cards)[server_id] = std::move(card_list.front());
- card_list.erase(card_list.begin());
- }
-
- return success;
-}
-
-bool AutofillWalletMetadataSyncableService::UpdateAddressStats(
- const AutofillProfile& profile) {
- return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
- ->UpdateServerAddressMetadata(profile);
-}
-
-bool AutofillWalletMetadataSyncableService::UpdateCardStats(
- const CreditCard& credit_card) {
- return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
- ->UpdateServerCardMetadata(credit_card);
-}
-
-syncer::SyncError
-AutofillWalletMetadataSyncableService::SendChangesToSyncServer(
- const syncer::SyncChangeList& changes_to_sync) {
- DCHECK(sync_processor_);
- ApplyChangesToCache(changes_to_sync, &cache_);
- return sync_processor_->ProcessSyncChanges(FROM_HERE, changes_to_sync);
-}
-
-syncer::SyncMergeResult AutofillWalletMetadataSyncableService::MergeData(
- const syncer::SyncDataList& sync_data) {
- // If we're not tracking wallet data, we can't rely on the local wallet
- // data being up-to-date, so we should not do any merging with local data.
- DCHECK(track_wallet_data_);
-
- std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
- std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
- GetLocalData(&profiles, &cards);
-
- syncer::SyncMergeResult result(syncer::AUTOFILL_WALLET_METADATA);
- result.set_num_items_before_association(profiles.size() + cards.size());
-
- // base::Unretained is used because the callbacks are invoked synchronously.
- base::Callback<bool(const AutofillProfile&)> address_updater =
- base::Bind(&AutofillWalletMetadataSyncableService::UpdateAddressStats,
- base::Unretained(this));
- base::Callback<bool(const CreditCard&)> card_updater =
- base::Bind(&AutofillWalletMetadataSyncableService::UpdateCardStats,
- base::Unretained(this));
-
- bool is_any_local_modified = false;
-
- syncer::SyncChangeList changes_to_sync;
- for (const syncer::SyncData& remote : sync_data) {
- DCHECK(remote.IsValid());
- DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, remote.GetDataType());
- switch (remote.GetSpecifics().wallet_metadata().type()) {
- case sync_pb::WalletMetadataSpecifics::ADDRESS:
- if (!MergeRemote(remote, address_updater, &is_any_local_modified,
- &profiles, &changes_to_sync)) {
- changes_to_sync.push_back(syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_DELETE, remote));
- }
- break;
-
- case sync_pb::WalletMetadataSpecifics::CARD:
- if (!MergeRemote(remote, card_updater, &is_any_local_modified, &cards,
- &changes_to_sync)) {
- changes_to_sync.push_back(syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_DELETE, remote));
- }
- break;
-
- case sync_pb::WalletMetadataSpecifics::UNKNOWN:
- NOTREACHED();
- break;
- }
- }
-
- // The remainder of |profiles| were not listed in |sync_data|.
- for (const auto& it : profiles) {
- changes_to_sync.push_back(syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_ADD,
- BuildSyncData(sync_pb::WalletMetadataSpecifics::ADDRESS, it.first,
- *it.second)));
- }
-
- // The remainder of |cards| were not listed in |sync_data|.
- for (const auto& it : cards) {
- changes_to_sync.push_back(
- syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD,
- BuildSyncData(sync_pb::WalletMetadataSpecifics::CARD,
- it.first, *it.second)));
- }
-
- // The only operation that is performed locally in response to a sync is an
- // update. Adds and deletes are performed in response to changes to the Wallet
- // data.
- result.set_num_items_after_association(result.num_items_before_association());
- result.set_num_items_added(0);
- result.set_num_items_deleted(0);
-
- if (!changes_to_sync.empty())
- result.set_error(SendChangesToSyncServer(changes_to_sync));
- if (is_any_local_modified) {
- // TODO(crbug.com/900607): Remove the need to listen to
- // AutofillMultipleChangedBySync() in the new USS implementation so that we
- // can get rid of this hack.
- DCHECK(!ignore_multiple_changed_notification_);
- ignore_multiple_changed_notification_ = true;
- web_data_backend_->NotifyOfMultipleAutofillChanges();
- ignore_multiple_changed_notification_ = false;
- }
-
- return result;
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
deleted file mode 100644
index 25845d1aa36..00000000000
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
+++ /dev/null
@@ -1,162 +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 COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_METADATA_SYNCABLE_SERVICE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_METADATA_SYNCABLE_SERVICE_H_
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/scoped_observer.h"
-#include "base/supports_user_data.h"
-#include "base/threading/thread_checker.h"
-#include "components/autofill/core/browser/webdata/autofill_change.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
-#include "components/sync/model/sync_error.h"
-#include "components/sync/model/sync_merge_result.h"
-#include "components/sync/model/syncable_service.h"
-#include "components/sync/protocol/autofill_specifics.pb.h"
-
-namespace base {
-class Location;
-}
-
-namespace syncer {
-class SyncChangeProcessor;
-class SyncErrorFactory;
-}
-
-namespace autofill {
-
-class AutofillProfile;
-class AutofillWebDataBackend;
-class AutofillWebDataService;
-class CreditCard;
-
-// Syncs usage counts and last use dates (metadata) for Wallet cards and
-// addresses (data).
-//
-// The sync server generates the data, and the client can only download it. No
-// data upload is possible. Chrome generates the corresponding metadata locally
-// and uses the sync server to propagate the metadata to the other instances of
-// Chrome. See the design doc at https://goo.gl/LS2y6M for more details.
-class AutofillWalletMetadataSyncableService
- : public base::SupportsUserData::Data,
- public syncer::SyncableService,
- public AutofillWebDataServiceObserverOnDBSequence {
- public:
- AutofillWalletMetadataSyncableService(
- AutofillWebDataBackend* web_data_backend,
- const std::string& app_locale);
-
- ~AutofillWalletMetadataSyncableService() override;
-
- // Determines whether this bridge should be monitoring the Wallet data. This
- // should be called whenever the data bridge sync state changes.
- void OnWalletDataTrackingStateChanged(bool is_tracking);
-
- base::WeakPtr<AutofillWalletMetadataSyncableService> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- // syncer::SyncableService implementation.
- void WaitUntilReadyToSync(base::OnceClosure done) override;
- syncer::SyncMergeResult MergeDataAndStartSyncing(
- syncer::ModelType type,
- const syncer::SyncDataList& initial_sync_data,
- std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
- std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) override;
- void StopSyncing(syncer::ModelType type) override;
- syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
- syncer::SyncError ProcessSyncChanges(
- const base::Location& from_here,
- const syncer::SyncChangeList& changes_from_sync) override;
-
- // AutofillWebDataServiceObserverOnDBSequence implementation.
- void AutofillProfileChanged(const AutofillProfileChange& change) override;
- void CreditCardChanged(const CreditCardChange& change) override;
- void AutofillMultipleChangedBySync() override;
-
- // Creates a new AutofillWalletMetadataSyncableService and hangs it off of
- // |web_data_service|, which takes ownership. This method should only be
- // called on |web_data_service|'s DB sequence. |web_data_backend| is expected
- // to outlive this object.
- static void CreateForWebDataServiceAndBackend(
- AutofillWebDataService* web_data_service,
- AutofillWebDataBackend* web_data_backend,
- const std::string& app_locale);
-
- // Retrieves the AutofillWalletMetadataSyncableService stored on
- // |web_data_service|.
- static AutofillWalletMetadataSyncableService* FromWebDataService(
- AutofillWebDataService* web_data_service);
-
- protected:
- // Populates the provided |profiles| and |cards| with mappings from server ID
- // to server profiles and server cards read from disk. This data contains the
- // usage stats. Returns true on success.
- virtual bool GetLocalData(
- std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>*
- profiles,
- std::unordered_map<std::string, std::unique_ptr<CreditCard>>* cards)
- const;
-
- // Updates the stats for |profile| stored on disk. Does not trigger
- // notifications that this profile was updated.
- virtual bool UpdateAddressStats(const AutofillProfile& profile);
-
- // Updates the stats for |credit_card| stored on disk. Does not trigger
- // notifications that this credit card was updated.
- virtual bool UpdateCardStats(const CreditCard& credit_card);
-
- // Sends the |changes_to_sync| to the sync server.
- virtual syncer::SyncError SendChangesToSyncServer(
- const syncer::SyncChangeList& changes_to_sync);
-
- private:
- // Merges local metadata with |sync_data|.
- //
- // Sends an "update" to the sync server if |sync_data| contains metadata that
- // is present locally, but local metadata has higher use count and later use
- // date.
- //
- // Sends a "create" to the sync server if |sync_data| does not have some local
- // metadata.
- //
- // Sends a "delete" to the sync server if |sync_data| contains metadata that
- // is not present locally.
- syncer::SyncMergeResult MergeData(const syncer::SyncDataList& sync_data);
-
- base::ThreadChecker thread_checker_;
- AutofillWebDataBackend* web_data_backend_; // Weak ref.
- ScopedObserver<AutofillWebDataBackend, AutofillWalletMetadataSyncableService>
- scoped_observer_;
- std::unique_ptr<syncer::SyncChangeProcessor> sync_processor_;
- std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory_;
-
- // Local metadata plus metadata for the data that hasn't synced down yet.
- syncer::SyncDataList cache_;
-
- // Indicates whether we should rely on wallet data being actively synced. If
- // true, the service will prune metadata entries without corresponding wallet
- // data entry.
- bool track_wallet_data_;
-
- // Indicates that we should ignore multiple changed notification. This is used
- // to block reflection and not to act on notification that we've triggered
- // ourselves.
- bool ignore_multiple_changed_notification_;
-
- base::WeakPtrFactory<AutofillWalletMetadataSyncableService> weak_ptr_factory_{
- this};
-
- DISALLOW_COPY_AND_ASSIGN(AutofillWalletMetadataSyncableService);
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_METADATA_SYNCABLE_SERVICE_H_
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
deleted file mode 100644
index eda11cef185..00000000000
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
+++ /dev/null
@@ -1,1366 +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 "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/time/time.h"
-#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
-#include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
-#include "components/sync/model/sync_change.h"
-#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
-#include "components/sync/model/sync_error_factory_mock.h"
-#include "components/sync/protocol/autofill_specifics.pb.h"
-#include "components/sync/protocol/sync.pb.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace autofill {
-namespace {
-
-using testing::DoAll;
-using testing::ElementsAre;
-using testing::Invoke;
-using testing::NiceMock;
-using testing::Return;
-using testing::Test;
-using testing::UnorderedElementsAre;
-using testing::Value;
-using testing::_;
-
-// Non-UTF8 server IDs.
-const char kAddr1[] = "addr1\xEF\xBF\xBE";
-const char kAddr2[] = "addr2\xEF\xBF\xBE";
-const char kCard1[] = "card1\xEF\xBF\xBE";
-const char kCard2[] = "card2\xEF\xBF\xBE";
-
-// Base64 encodings of the server IDs. These are suitable for syncing, because
-// they are valid UTF-8.
-const char kAddr1Utf8[] = "YWRkcjHvv74=";
-const char kAddr2Utf8[] = "YWRkcjLvv74=";
-const char kCard1Utf8[] = "Y2FyZDHvv74=";
-const char kCard2Utf8[] = "Y2FyZDLvv74=";
-
-// Unique sync tags for the server IDs.
-const char kAddr1SyncTag[] = "address-YWRkcjHvv74=";
-const char kAddr2SyncTag[] = "address-YWRkcjLvv74=";
-const char kCard1SyncTag[] = "card-Y2FyZDHvv74=";
-const char kCard2SyncTag[] = "card-Y2FyZDLvv74=";
-
-// Local profile GUID in UTF8 and non-UTF8.
-const char kLocalAddr1[] = "e171e3ed-858a-4dd5-9bf3-8517f14ba5fc";
-const char kLocalAddr2[] = "fa232b9a-f248-4e5a-8d76-d46f821c0c5f";
-const char kLocalAddr1Utf8[] =
- "ZTE3MWUzZWQtODU4YS00ZGQ1LTliZjMtODUxN2YxNGJhNWZj";
-
-// Map values are owned by the caller to GetLocalData.
-ACTION_P2(GetCopiesOf, profiles, cards) {
- for (const auto& profile : *profiles) {
- std::string utf8_server_id;
- base::Base64Encode(profile.server_id(), &utf8_server_id);
- (*arg0)[utf8_server_id] = std::make_unique<AutofillProfile>(profile);
- }
-
- for (const auto& card : *cards) {
- std::string utf8_server_id;
- base::Base64Encode(card.server_id(), &utf8_server_id);
- (*arg1)[utf8_server_id] = std::make_unique<CreditCard>(card);
- }
-}
-
-ACTION_P(SaveDataIn, list) {
- for (auto& item : *list) {
- if (item.server_id() == arg0.server_id()) {
- item = arg0;
- return;
- }
- }
-
- list->push_back(arg0);
-}
-
-// A syncable service for Wallet metadata that mocks out disk IO.
-class MockService : public AutofillWalletMetadataSyncableService {
- public:
- MockService(AutofillWebDataBackend* web_data_backend)
- : AutofillWalletMetadataSyncableService(web_data_backend, std::string()) {
- ON_CALL(*this, GetLocalData(_, _))
- .WillByDefault(DoAll(GetCopiesOf(&server_profiles_, &server_cards_),
- Return(true)));
-
- ON_CALL(*this, UpdateAddressStats(_))
- .WillByDefault(DoAll(SaveDataIn(&server_profiles_), Return(true)));
-
- ON_CALL(*this, UpdateCardStats(_))
- .WillByDefault(DoAll(SaveDataIn(&server_cards_), Return(true)));
-
- ON_CALL(*this, SendChangesToSyncServer(_))
- .WillByDefault(
- Invoke(this, &MockService::SendChangesToSyncServerConcrete));
- }
-
- ~MockService() override {}
-
- MOCK_METHOD1(UpdateAddressStats, bool(const AutofillProfile&));
- MOCK_METHOD1(UpdateCardStats, bool(const CreditCard&));
- MOCK_METHOD1(SendChangesToSyncServer,
- syncer::SyncError(const syncer::SyncChangeList&));
-
- void ClearServerData() {
- server_profiles_.clear();
- server_cards_.clear();
- }
-
- private:
- MOCK_CONST_METHOD2(
- GetLocalData,
- bool(std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>*,
- std::unordered_map<std::string, std::unique_ptr<CreditCard>>*));
-
- syncer::SyncError SendChangesToSyncServerConcrete(
- const syncer::SyncChangeList& changes) {
- return AutofillWalletMetadataSyncableService::SendChangesToSyncServer(
- changes);
- }
-
- syncer::SyncDataList GetAllSyncDataConcrete(syncer::ModelType type) const {
- return AutofillWalletMetadataSyncableService::GetAllSyncData(type);
- }
-
- std::vector<AutofillProfile> server_profiles_;
- std::vector<CreditCard> server_cards_;
-
- DISALLOW_COPY_AND_ASSIGN(MockService);
-};
-
-class AutofillWalletMetadataSyncableServiceTest : public Test {
- public:
- AutofillWalletMetadataSyncableServiceTest()
- : local_(&backend_), remote_(&backend_) {}
- ~AutofillWalletMetadataSyncableServiceTest() override {}
-
- void SetUp() {
- local_.OnWalletDataTrackingStateChanged(true);
- remote_.OnWalletDataTrackingStateChanged(true);
- }
-
- // Outlives local_ and remote_.
- NiceMock<MockAutofillWebDataBackend> backend_;
-
- // Outlived by backend_.
- NiceMock<MockService> local_;
- NiceMock<MockService> remote_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AutofillWalletMetadataSyncableServiceTest);
-};
-
-// Verify that nothing is sent to the sync server when there's no metadata on
-// disk.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, NoMetadataToReturn) {
- EXPECT_TRUE(local_.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA).empty());
-}
-
-AutofillProfile BuildAddress(const std::string& server_id,
- int64_t use_count,
- int64_t use_date,
- bool has_converted) {
- AutofillProfile profile(AutofillProfile::SERVER_PROFILE, server_id);
- profile.set_use_count(use_count);
- profile.set_use_date(base::Time::FromInternalValue(use_date));
- profile.set_has_converted(has_converted);
- return profile;
-}
-
-CreditCard BuildCard(const std::string& server_id,
- int64_t use_count,
- int64_t use_date,
- const std::string& billing_address_id) {
- CreditCard card(CreditCard::MASKED_SERVER_CARD, server_id);
- card.set_use_count(use_count);
- card.set_use_date(base::Time::FromInternalValue(use_date));
- card.set_billing_address_id(billing_address_id);
- return card;
-}
-
-MATCHER_P6(SyncAddressDataMatches,
- sync_tag,
- metadata_type,
- server_id,
- use_count,
- use_date,
- has_converted,
- "") {
- return arg.IsValid() &&
- syncer::AUTOFILL_WALLET_METADATA == arg.GetDataType() &&
- sync_tag == syncer::SyncDataLocal(arg).GetTag() &&
- metadata_type == arg.GetSpecifics().wallet_metadata().type() &&
- server_id == arg.GetSpecifics().wallet_metadata().id() &&
- use_count == arg.GetSpecifics().wallet_metadata().use_count() &&
- use_date == arg.GetSpecifics().wallet_metadata().use_date() &&
- has_converted ==
- arg.GetSpecifics().wallet_metadata().address_has_converted();
-}
-
-MATCHER_P6(SyncCardDataMatches,
- sync_tag,
- metadata_type,
- server_id,
- use_count,
- use_date,
- billing_address_id,
- "") {
- return arg.IsValid() &&
- syncer::AUTOFILL_WALLET_METADATA == arg.GetDataType() &&
- sync_tag == syncer::SyncDataLocal(arg).GetTag() &&
- metadata_type == arg.GetSpecifics().wallet_metadata().type() &&
- server_id == arg.GetSpecifics().wallet_metadata().id() &&
- use_count == arg.GetSpecifics().wallet_metadata().use_count() &&
- use_date == arg.GetSpecifics().wallet_metadata().use_date() &&
- billing_address_id ==
- arg.GetSpecifics().wallet_metadata().card_billing_address_id();
-}
-
-// Verify that all metadata from disk is sent to the sync server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, ReturnAllMetadata) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
-
- EXPECT_THAT(local_.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA),
- UnorderedElementsAre(
- SyncAddressDataMatches(
- kAddr1SyncTag, sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2, true),
- SyncCardDataMatches(kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4, kAddr1Utf8)));
-}
-
-void MergeMetadata(MockService* local, MockService* remote) {
- // The wrapper for |remote| gives it a null change processor, so sending
- // changes is not possible.
- ON_CALL(*remote, SendChangesToSyncServer(_))
- .WillByDefault(Return(syncer::SyncError()));
-
- std::unique_ptr<syncer::SyncErrorFactoryMock> errors(
- new syncer::SyncErrorFactoryMock);
- EXPECT_CALL(*errors, CreateAndUploadError(_, _)).Times(0);
- EXPECT_FALSE(
- local
- ->MergeDataAndStartSyncing(
- syncer::AUTOFILL_WALLET_METADATA,
- remote->GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(remote)),
- std::move(errors))
- .error()
- .IsSet());
-}
-
-// Verify that nothing is written to disk or sent to the sync server when two
-// empty clients are syncing.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, TwoEmptyClients) {
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-MATCHER_P2(SyncChangeMatches, change_type, sync_tag, "") {
- return arg.IsValid() && change_type == arg.change_type() &&
- sync_tag == syncer::SyncDataLocal(arg.sync_data()).GetTag() &&
- syncer::AUTOFILL_WALLET_METADATA == arg.sync_data().GetDataType();
-}
-
-// Verify that remote data without local counterpart is deleted during the
-// initial merge.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, DeleteFromServerOnMerge) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE,
- kCard1SyncTag))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that remote data without local counterpart is kept when we're not
-// tracking wallet data.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DeleteFromServerOnMerge_NotWhenNotTracking) {
- local_.OnWalletDataTrackingStateChanged(false);
-
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that remote data without local counterpart is deleted when we start
-// tracking wallet data after the initial merge happened.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DeleteFromServerOnMerge_MergeBeforeTracking) {
- local_.OnWalletDataTrackingStateChanged(false);
-
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE,
- kCard1SyncTag))));
-
- MergeMetadata(&local_, &remote_);
-
- local_.OnWalletDataTrackingStateChanged(true);
-}
-
-MATCHER_P7(SyncAddressChangeAndDataMatch,
- change_type,
- sync_tag,
- metadata_type,
- server_id,
- use_count,
- use_date,
- has_converted,
- "") {
- return Value(arg, SyncChangeMatches(change_type, sync_tag)) &&
- Value(arg.sync_data(),
- SyncAddressDataMatches(sync_tag, metadata_type, server_id,
- use_count, use_date, has_converted));
-}
-
-MATCHER_P7(SyncCardChangeAndDataMatch,
- change_type,
- sync_tag,
- metadata_type,
- server_id,
- use_count,
- use_date,
- billing_address_id,
- "") {
- return Value(arg, SyncChangeMatches(change_type, sync_tag)) &&
- Value(arg.sync_data(),
- SyncCardDataMatches(sync_tag, metadata_type, server_id,
- use_count, use_date, billing_address_id));
-}
-
-// Verify that local data is sent to the sync server during the initial merge,
-// if the server does not have the data already.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4, kAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that no data is written to disk or sent to the sync server if the
-// local and remote data are identical during the initial merge.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- IgnoreIdenticalValuesOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-MATCHER_P4(AutofillAddressMetadataMatches,
- server_id,
- use_count,
- use_date,
- has_converted,
- "") {
- return arg.server_id() == server_id &&
- arg.use_count() == base::checked_cast<size_t>(use_count) &&
- arg.use_date() == base::Time::FromInternalValue(use_date) &&
- arg.has_converted() == has_converted;
-}
-
-MATCHER_P4(AutofillCardMetadataMatches,
- server_id,
- use_count,
- use_date,
- billing_address_id,
- "") {
- return arg.server_id() == server_id &&
- arg.use_count() == base::checked_cast<size_t>(use_count) &&
- arg.use_date() == base::Time::FromInternalValue(use_date) &&
- arg.billing_address_id() == billing_address_id;
-}
-
-// Verify that remote data with higher values of use count and last use date is
-// saved to disk during the initial merge.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValuesLocallyOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 10, 20, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
- kAddr1, 10, 20, true)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 30, 40, kAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that local data with higher values of use count and last use date is
-// sent to the sync server during the initial merge.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SendHigherValuesToServerOnMerge) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 10, 20, true));
- local_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 10, 20, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 30, 40, kAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that lower or equal values of metadata are not sent to the sync server
-// when local metadata is updated.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DontSendLowerValueToServerOnSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr1, 0, 0, true);
- CreditCard card = BuildCard(kCard1, 3, 4, kAddr1);
-
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, address.guid(), &address));
- local_.CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
-}
-
-// Verify that higher values of metadata are sent to the sync server when local
-// metadata is updated.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SendHigherValuesToServerOnLocalSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr1, 10, 20, true);
- CreditCard card = BuildCard(kCard1, 30, 40, kAddr2);
-
- EXPECT_CALL(local_,
- SendChangesToSyncServer(ElementsAre(SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20,
- true))));
- EXPECT_CALL(local_,
- SendChangesToSyncServer(ElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40,
- kAddr2Utf8))));
-
- local_.AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, address.guid(), &address));
- local_.CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
-}
-
-// Verify that other changed metadata elements are sent to the sync server when
-// local metadata is updated.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SendChangedMetadataToServerOnLocalSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr1, 1, 2, true);
- CreditCard card = BuildCard(kCard1, 3, 4, kAddr2);
-
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(ElementsAre(SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 1, 2, true))));
- EXPECT_CALL(local_,
- SendChangesToSyncServer(ElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 3, 4,
- kAddr2Utf8))));
-
- local_.AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, address.guid(), &address));
- local_.CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
-}
-
-// Verify that one-off addition of metadata is not sent to the sync
-// server. Metadata add and delete trigger multiple changes notification
-// instead.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DontAddToServerOnSingleChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- AutofillProfile address = BuildAddress(kAddr2, 5, 6, false);
- CreditCard card = BuildCard(kCard2, 7, 8, kAddr2);
-
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.AutofillProfileChanged(AutofillProfileChange(
- AutofillProfileChange::UPDATE, address.guid(), &address));
- local_.CreditCardChanged(
- CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
-}
-
-// Verify that new metadata is sent to the sync server when multiple metadata
-// values change at once.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- // These methods do not trigger notifications or sync:
- local_.UpdateAddressStats(BuildAddress(kAddr2, 5, 6, true));
- local_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
-
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_ADD, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr2Utf8, 5, 6, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_ADD, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard2Utf8, 7, 8, kAddr2Utf8))));
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that higher values of existing metadata are sent to the sync server
-// when multiple metadata values change at once.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- UpdateToHigherValueOnServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- // These methods do not trigger notifications or sync:
- local_.UpdateAddressStats(BuildAddress(kAddr1, 5, 6, true));
- local_.UpdateCardStats(BuildCard(kCard1, 7, 8, kAddr2));
-
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 5, 6, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 7, 8, kAddr2Utf8))));
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that lower values of existing metadata are not sent to the sync server
-// when multiple metadata values change at once.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DontUpdateToLowerValueOnServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- // These methods do not trigger notifications or sync:
- local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0, false));
- local_.UpdateCardStats(BuildCard(kCard1, 0, 0, kAddr2));
-
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that erased local metadata is also erased from the sync server when
-// multiple metadata values change at once.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DeleteFromServerOnMultiChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- // This method dooes not trigger notifications or sync:
- local_.ClearServerData();
-
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE,
- kCard1SyncTag))));
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that erased local metadata is not erased from the sync server when
-// the service is not tracking Wallet data.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DeleteFromServerOnMultiChange_NotWhenNotTracking) {
- local_.OnWalletDataTrackingStateChanged(false);
-
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- // This method dooes not trigger notifications or sync:
- local_.ClearServerData();
-
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that erased local metadata is also erased from the sync server when
-// we start tracking Wallet data after multiple metadata values change at once.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DeleteFromServerOnMultiChange_ChangeBeforeTracking) {
- local_.OnWalletDataTrackingStateChanged(false);
-
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- // This method dooes not trigger notifications or sync:
- local_.ClearServerData();
-
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE,
- kCard1SyncTag))));
-
- local_.AutofillMultipleChangedBySync();
- local_.OnWalletDataTrackingStateChanged(true);
-}
-
-// Verify that empty sync change from the sync server does not trigger writing
-// to disk or sending any data to the sync server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, EmptySyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.ProcessSyncChanges(FROM_HERE, syncer::SyncChangeList());
-}
-
-void BuildBasicChange(syncer::SyncChange::SyncChangeType change_type,
- const std::string& sync_tag,
- sync_pb::WalletMetadataSpecifics::Type metadata_type,
- const std::string& server_id,
- int64_t use_count,
- int64_t use_date,
- sync_pb::EntitySpecifics* entity) {
- entity->mutable_wallet_metadata()->set_type(metadata_type);
- entity->mutable_wallet_metadata()->set_id(server_id);
- entity->mutable_wallet_metadata()->set_use_count(use_count);
- entity->mutable_wallet_metadata()->set_use_date(use_date);
-}
-
-syncer::SyncChange BuildAddressChange(
- syncer::SyncChange::SyncChangeType change_type,
- const std::string& sync_tag,
- sync_pb::WalletMetadataSpecifics::Type metadata_type,
- const std::string& server_id,
- int64_t use_count,
- int64_t use_date,
- bool has_converted) {
- sync_pb::EntitySpecifics entity;
- BuildBasicChange(change_type, sync_tag, metadata_type, server_id, use_count,
- use_date, &entity);
- entity.mutable_wallet_metadata()->set_address_has_converted(has_converted);
- return syncer::SyncChange(
- FROM_HERE, change_type,
- syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity));
-}
-
-syncer::SyncChange BuildCardChange(
- syncer::SyncChange::SyncChangeType change_type,
- const std::string& sync_tag,
- sync_pb::WalletMetadataSpecifics::Type metadata_type,
- const std::string& server_id,
- int64_t use_count,
- int64_t use_date,
- const std::string& billing_address_id) {
- sync_pb::EntitySpecifics entity;
- BuildBasicChange(change_type, sync_tag, metadata_type, server_id, use_count,
- use_date, &entity);
- entity.mutable_wallet_metadata()->set_card_billing_address_id(
- billing_address_id);
- return syncer::SyncChange(
- FROM_HERE, change_type,
- syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity));
-}
-
-// Verify that new metadata from the sync server is ignored when processing
-// on-going sync changes. There should be no disk writes or messages to the sync
-// server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- IgnoreNewMetadataFromServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_ADD, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 5, 6, true));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_ADD, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 7, 8, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that higher values of metadata from the sync server are saved to
-// disk when processing on-going sync changes.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValuesFromServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20, true));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 30, 40, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
- kAddr1, 10, 20, true)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 30, 40, kAddr2)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that higher local values of metadata are sent to the sync server when
-// processing on-going sync changes.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SendHigherValuesToServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 2, 2, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4, kAddr1Utf8))));
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that addition of known metadata is treated the same as an update.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- TreatAdditionOfKnownMetadataAsUpdateOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 2, 2, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4, kAddr1Utf8))));
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that an update of locally unknown metadata is ignored. There should be
-// no disk writes and no messages sent to the server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- IgnoreUpdateOfUnknownMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 0, 0, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 0, 0, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that deletion from the sync server of locally unknown metadata is
-// ignored. There should be no disk writes and no messages sent to the server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- IgnoreDeleteOfUnknownMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_DELETE, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 0, 0, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_DELETE, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 0, 0, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that deletion from the sync server of locally existing metadata will
-// trigger an undelete message sent to the server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- UndeleteExistingMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 0, 0, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_DELETE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 0, 0, kAddr2Utf8));
-
- EXPECT_CALL(local_, UpdateAddressStats(_)).Times(0);
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 2, 2, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4, kAddr1Utf8))));
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-// Verify that processing sync changes maintains the local cache of sync server
-// data, which is used to avoid calling the expensive GetAllSyncData() function.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- CacheIsUpToDateAfterSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
- local_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
- local_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
- remote_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 50, 60, kAddr1Utf8));
- local_.ProcessSyncChanges(FROM_HERE, changes);
- // This method dooes not trigger notifications or sync:
- local_.ClearServerData();
-
- EXPECT_CALL(
- local_,
- SendChangesToSyncServer(UnorderedElementsAre(
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kAddr1SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kAddr2SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, kCard1SyncTag),
- SyncChangeMatches(syncer::SyncChange::ACTION_DELETE,
- kCard2SyncTag))));
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that Wallet data arriving after metadata will not send lower metadata
-// values to the sync server.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValuesLocallyOnLateDataArrival) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 5, 6, true));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 7, 8, kAddr2Utf8));
- local_.ProcessSyncChanges(FROM_HERE, changes);
- local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0, true));
- local_.UpdateCardStats(BuildCard(kCard1, 0, 0, kAddr2));
-
- EXPECT_CALL(local_, UpdateAddressStats(
- AutofillAddressMetadataMatches(kAddr1, 5, 6, true)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 7, 8, kAddr2)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that processing a small subset of metadata changes before any Wallet
-// data arrived will not cause sending lower metadata values to the sync server
-// once the data finally arrives.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValuesLocallyOnLateDataArrivalAfterPartialUpdates) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
- remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
- remote_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr1));
- MergeMetadata(&local_, &remote_);
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 9, 10, false));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard1Utf8, 11, 12, kAddr2Utf8));
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr2SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr2Utf8, 13, 14, true));
- changes.push_back(BuildCardChange(
- syncer::SyncChange::ACTION_UPDATE, kCard2SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD, kCard2Utf8, 15, 16, kAddr1Utf8));
- local_.ProcessSyncChanges(FROM_HERE, changes);
- changes.resize(2);
- local_.ProcessSyncChanges(FROM_HERE, changes);
- local_.UpdateAddressStats(BuildAddress(kAddr1, 0, 0, false));
- local_.UpdateAddressStats(BuildAddress(kAddr2, 0, 0, false));
- local_.UpdateCardStats(BuildCard(kCard1, 0, 0, kAddr1));
- local_.UpdateCardStats(BuildCard(kCard2, 0, 0, kAddr2));
-
- EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
- kAddr1, 9, 10, false)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 11, 12, kAddr2)));
- EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
- kAddr2, 13, 14, true)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard2, 15, 16, kAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.AutofillMultipleChangedBySync();
-}
-
-// Verify that the merge logic keeps the best data on a field by field basis.
-// Make sure that if the better data is split across the local and server
-// version, both are updated with the merge results.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, SaveHigherValues_Mixed1) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 20, true));
- local_.UpdateCardStats(BuildCard(kCard1, 30, 4, ""));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 10, 2, false));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
-
- EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
- kAddr1, 10, 20, true)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 30, 40, kAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 10, 20, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 30, 40, kAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that the merge logic keeps the best data on a field by field basis.
-// Make sure that if the better data is split across the local and server
-// version, both are updated with the merge results.
-// Same as SaveHigherValues_Mixed1 but with the higher values moved from local
-// to server and vice versa.
-TEST_F(AutofillWalletMetadataSyncableServiceTest, SaveHigherValues_Mixed2) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 10, 2, false));
- local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 20, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 30, 4, ""));
-
- EXPECT_CALL(local_, UpdateAddressStats(AutofillAddressMetadataMatches(
- kAddr1, 10, 20, true)));
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 30, 40, kAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(UnorderedElementsAre(
- SyncAddressChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 10, 20, true),
- SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 30, 40, kAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id refering to a Wallet address, the one with the most recent
-// (bigger) use date is kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentServerBillingAddressId_LocalMostRecent) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
-
- // The value from the local should be kept because it has a more recent use
- // date.
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(
- UnorderedElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 40, kAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id refering to a Wallet address, the one with the most recent
-// (bigger) use date is kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentServerBillingAddressId_RemoteMostRecent) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr2));
-
- // The value from the remote should be kept because it has a more recent use
- // date.
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 3, 40, kAddr2)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id refering to a local profile, the one with the most recent (bigger)
-// use date is kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentLocalBillingAddressId_LocalMostRecent) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kLocalAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr2));
-
- // The value from the local should be kept because it has a more recent use
- // date.
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(
- UnorderedElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 40, kLocalAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id refering to a local profile, the one with the most recent (bigger)
-// use date is kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentLocalBillingAddressId_RemoteMostRecent) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kLocalAddr2));
-
- // The value from the remote should be kept because it has a more recent use
- // date.
- EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
- kCard1, 3, 40, kLocalAddr2)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id, the one refering to a local profile is always kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentBillingAddressId_KeepLocalId_Local) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
-
- // The billing address from the local version of the card should be kept since
- // it refers to a local autofill profile.
- EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
- EXPECT_CALL(local_, SendChangesToSyncServer(
- UnorderedElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 3, 4, kLocalAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id, the one refering to a local profile is always kept, even id the
-// other was used more recently.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentBillingAddressId_KeepLocalId_Remote) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
-
- // The billing address from the remote version of the card should be kept
- // since it refers to a local autofill profile.
- EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
- kCard1, 3, 4, kLocalAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id, the one refering to a local profile is always kept, even id the
-// other was used more recently. Also makes sure that for the rest of the fields
-// the highest values are kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValues_DifferentBillingAddressId_KeepLocalId_Local) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr2));
-
- // The billing address from the local version of the card should be kept since
- // it refers to a local autofill profile. The highest use stats should
- // be kept.
- EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
- kCard1, 30, 40, kLocalAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(
- UnorderedElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 30, 40, kLocalAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id, the one refering to a local profile is always kept. Also makes
-// sure that for the rest of the fields the highest values are kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValues_DifferentBillingAddressId_KeepLocalId_Remote) {
- local_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr2));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
-
- // The billing address from the remote version of the card should be kept
- // since it refers to a local autofill profile. The highest use stats should
- // be kept.
- EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
- kCard1, 30, 40, kLocalAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(
- UnorderedElementsAre(SyncCardChangeAndDataMatch(
- syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
- sync_pb::WalletMetadataSpecifics::CARD,
- kCard1Utf8, 30, 40, kLocalAddr1Utf8))));
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id refering to a Wallet address with the same timestamp, the remote
-// one is kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentServerBillingAddressId_BothSameTimestamp) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
-
- // The value from the remote should be kept to promote a stable set of values.
- EXPECT_CALL(local_, UpdateCardStats(
- AutofillCardMetadataMatches(kCard1, 3, 4, kAddr2)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if both local and server have a different non empty billing
-// address id refering to a local profile with the same timestamp, the remote
-// one is kept.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- DifferentLocalBillingAddressId_BothSameTimestamp) {
- local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr2));
-
- // The value from the remote should be kept to promote a stable set of values.
- EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
- kCard1, 3, 4, kLocalAddr2)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Verify that if the local card has a use_count of one, its use_date is
-// replaced even if it is more recent (new cards are created with a use_date set
-// to the current time).
-TEST_F(AutofillWalletMetadataSyncableServiceTest, NewLocalCard) {
- local_.UpdateCardStats(BuildCard(kCard1, 1, 5000, kLocalAddr1));
- remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
-
- EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
- kCard1, 3, 4, kLocalAddr1)));
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- MergeMetadata(&local_, &remote_);
-}
-
-// Tests that processing remote changes does not trigger a merge. This is a
-// specific test for reflection blocking in notifications.
-TEST_F(AutofillWalletMetadataSyncableServiceTest,
- RemoteChangesDoNotTriggerMerge) {
- // Make the backend broadcast back the notifications it receives
- ON_CALL(backend_, NotifyOfMultipleAutofillChanges())
- .WillByDefault(
- DoAll(Invoke(&local_, &MockService::AutofillMultipleChangedBySync),
- Invoke(&remote_, &MockService::AutofillMultipleChangedBySync)));
-
- // Get initial data from |remote_| into |local_|.
- local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- local_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
- remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
- MergeMetadata(&local_, &remote_);
-
- // Silently update local card in the DB.
- local_.UpdateCardStats(BuildCard(kCard1, 7, 8, kAddr1));
-
- // Receive a remote update of the address.
- syncer::SyncChangeList changes;
- changes.push_back(BuildAddressChange(
- syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
- sync_pb::WalletMetadataSpecifics::ADDRESS, kAddr1Utf8, 10, 20, true));
-
- // Processing remote change should not trigger a commit of the local change.
- EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
-
- local_.ProcessSyncChanges(FROM_HERE, changes);
-}
-
-} // namespace
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
index 1115ef255af..c9bc282c991 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -140,13 +140,11 @@ std::unique_ptr<EntityData> CreateEntityDataFromPaymentsCustomerData(
// static
void AutofillWalletSyncBridge::CreateForWebDataServiceAndBackend(
const std::string& app_locale,
- const base::RepeatingCallback<void(bool)>& active_callback,
AutofillWebDataBackend* web_data_backend,
AutofillWebDataService* web_data_service) {
web_data_service->GetDBUserData()->SetUserData(
&kAutofillWalletSyncBridgeUserDataKey,
std::make_unique<AutofillWalletSyncBridge>(
- active_callback,
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
syncer::AUTOFILL_WALLET_DATA,
/*dump_stack=*/base::RepeatingClosure()),
@@ -162,12 +160,9 @@ syncer::ModelTypeSyncBridge* AutofillWalletSyncBridge::FromWebDataService(
}
AutofillWalletSyncBridge::AutofillWalletSyncBridge(
- const base::RepeatingCallback<void(bool)>& active_callback,
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
AutofillWebDataBackend* web_data_backend)
: ModelTypeSyncBridge(std::move(change_processor)),
- active_callback_(active_callback),
- initial_sync_done_(false),
web_data_backend_(web_data_backend) {
DCHECK(web_data_backend_);
@@ -201,11 +196,6 @@ base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
// metadata bridge can track changes in the data bridge and react accordingly.
SetSyncData(entity_data, /*notify_metadata_bridge=*/true);
- // After the first sync, we are sure that initial sync is done.
- if (!initial_sync_done_) {
- initial_sync_done_ = true;
- active_callback_.Run(true);
- }
// TODO(crbug.com/853688): Update the AutofillTable API to know about write
// errors and report them here.
return base::nullopt;
@@ -260,16 +250,10 @@ void AutofillWalletSyncBridge::ApplyStopSyncChanges(
// If a metadata change list gets passed in, that means sync is actually
// disabled, so we want to delete the payments data.
if (delete_metadata_change_list) {
- if (initial_sync_done_) {
- active_callback_.Run(false);
- }
-
// Do not notify the metadata bridge because we do not want to upstream the
// deletions. The metadata bridge deletes its data independently when sync
// gets stopped.
SetSyncData(syncer::EntityChangeList(), /*notify_metadata_bridge=*/false);
-
- initial_sync_done_ = false;
}
}
@@ -361,12 +345,7 @@ bool AutofillWalletSyncBridge::SetWalletCards(
ComputeAutofillWalletDiff(existing_cards, wallet_cards);
if (!diff.IsEmpty()) {
- if (base::FeatureList::IsEnabled(
- ::switches::kSyncUSSAutofillWalletMetadata)) {
- table->SetServerCardsData(wallet_cards);
- } else {
- table->SetServerCreditCards(wallet_cards);
- }
+ table->SetServerCardsData(wallet_cards);
if (notify_metadata_bridge) {
for (const CreditCardChange& change : diff.changes) {
web_data_backend_->NotifyOfCreditCardChanged(change);
@@ -399,12 +378,7 @@ bool AutofillWalletSyncBridge::SetWalletAddresses(
ComputeAutofillWalletDiff(existing_addresses, wallet_addresses);
if (!diff.IsEmpty()) {
- if (base::FeatureList::IsEnabled(
- ::switches::kSyncUSSAutofillWalletMetadata)) {
- table->SetServerAddressesData(wallet_addresses);
- } else {
- table->SetServerProfiles(wallet_addresses);
- }
+ table->SetServerAddressesData(wallet_addresses);
if (notify_metadata_bridge) {
for (const AutofillProfileChange& change : diff.changes) {
web_data_backend_->NotifyOfAutofillProfileChanged(change);
@@ -517,8 +491,6 @@ AutofillTable* AutofillWalletSyncBridge::GetAutofillTable() {
}
void AutofillWalletSyncBridge::LoadMetadata() {
- DCHECK(!initial_sync_done_);
-
if (!web_data_backend_ || !web_data_backend_->GetDatabase() ||
!GetAutofillTable()) {
change_processor()->ReportError(
@@ -535,10 +507,6 @@ void AutofillWalletSyncBridge::LoadMetadata() {
}
change_processor()->ModelReadyToSync(std::move(batch));
- if (change_processor()->IsTrackingMetadata()) {
- initial_sync_done_ = true;
- active_callback_.Run(true);
- }
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
index 8ca747f91c2..2e99e2e4cbc 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -35,11 +35,8 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
// Factory method that hides dealing with change_processor and also stores the
// created bridge within |web_data_service|. This method should only be
// called on |web_data_service|'s DB thread.
- // |active_callback| will be called with a boolean describing whether Wallet
- // data is actively sync whenever the state changes.
static void CreateForWebDataServiceAndBackend(
const std::string& app_locale,
- const base::RepeatingCallback<void(bool)>& active_callback,
AutofillWebDataBackend* webdata_backend,
AutofillWebDataService* web_data_service);
@@ -47,7 +44,6 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
AutofillWebDataService* web_data_service);
explicit AutofillWalletSyncBridge(
- const base::RepeatingCallback<void(bool)>& active_callback,
std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
AutofillWebDataBackend* web_data_backend);
~AutofillWalletSyncBridge() override;
@@ -130,13 +126,6 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
// processor so that it can start tracking changes.
void LoadMetadata();
- // Callback to let the metadata bridge know that whether the card data
- // is actively syncing.
- const base::RepeatingCallback<void(bool)> active_callback_;
-
- // Stores whether initial sync has been done.
- bool initial_sync_done_;
-
// AutofillProfileSyncBridge is owned by |web_data_backend_| through
// SupportsUserData, so it's guaranteed to outlive |this|.
AutofillWebDataBackend* const web_data_backend_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
index 19c63cf94c8..50741416fb7 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -16,7 +16,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_metadata.h"
@@ -188,33 +188,9 @@ MATCHER_P2(AddChange, key, data, "") {
return true;
}
-// Class that enables or disables USS based on test parameter. Must be the first
-// base class of the test fixture.
-// TODO(jkrcal): When the new implementation fully launches, remove this class,
-// convert all tests from *_P back to *_F and remove the instance at the end.
-class UssSwitchToggler : public testing::WithParamInterface<bool> {
- public:
- UssSwitchToggler() {
- if (IsWalletMetadataOnUSS()) {
- override_features_.InitAndEnableFeature(
- ::switches::kSyncUSSAutofillWalletMetadata);
- } else {
- override_features_.InitAndDisableFeature(
- ::switches::kSyncUSSAutofillWalletMetadata);
- }
- }
-
- protected:
- bool IsWalletMetadataOnUSS() { return GetParam(); }
-
- private:
- base::test::ScopedFeatureList override_features_;
-};
-
} // namespace
-class AutofillWalletSyncBridgeTest : public UssSwitchToggler,
- public testing::Test {
+class AutofillWalletSyncBridgeTest : public testing::Test {
public:
AutofillWalletSyncBridgeTest() {}
~AutofillWalletSyncBridgeTest() override {}
@@ -249,8 +225,7 @@ class AutofillWalletSyncBridgeTest : public UssSwitchToggler,
EXPECT_TRUE(table()->UpdateModelTypeState(syncer::AUTOFILL_WALLET_DATA,
model_type_state));
bridge_ = std::make_unique<AutofillWalletSyncBridge>(
- active_callback_.Get(), mock_processor_.CreateForwardingProcessor(),
- &backend_);
+ mock_processor_.CreateForwardingProcessor(), &backend_);
}
void StartSyncing(
@@ -329,42 +304,36 @@ class AutofillWalletSyncBridgeTest : public UssSwitchToggler,
MockAutofillWebDataBackend* backend() { return &backend_; }
- base::MockCallback<base::RepeatingCallback<void(bool)>>* active_callback() {
- return &active_callback_;
- }
-
private:
autofill::TestAutofillClock test_clock_;
ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
NiceMock<MockAutofillWebDataBackend> backend_;
AutofillTable table_;
WebDatabase db_;
testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_;
std::unique_ptr<AutofillWalletSyncBridge> bridge_;
- NiceMock<base::MockCallback<base::RepeatingCallback<void(bool)>>>
- active_callback_;
DISALLOW_COPY_AND_ASSIGN(AutofillWalletSyncBridgeTest);
};
// The following 3 tests make sure client tags stay stable.
-TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForAddress) {
+TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForAddress) {
AutofillWalletSpecifics specifics =
CreateAutofillWalletSpecificsForAddress(kAddr1SpecificsId);
EXPECT_EQ(bridge()->GetClientTag(*SpecificsToEntity(specifics)),
kAddr1SyncTag);
}
-TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForCard) {
+TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCard) {
AutofillWalletSpecifics specifics =
CreateAutofillWalletSpecificsForCard(kCard1SpecificsId);
EXPECT_EQ(bridge()->GetClientTag(*SpecificsToEntity(specifics)),
kCard1SyncTag);
}
-TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
+TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
AutofillWalletSpecifics specifics =
CreateAutofillWalletSpecificsForPaymentsCustomerData(
kCustomerDataSyncTag);
@@ -373,28 +342,28 @@ TEST_P(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
}
// The following 3 tests make sure storage keys stay stable.
-TEST_P(AutofillWalletSyncBridgeTest, GetStorageKeyForAddress) {
+TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForAddress) {
AutofillWalletSpecifics specifics1 =
CreateAutofillWalletSpecificsForAddress(kAddr1SpecificsId);
EXPECT_EQ(bridge()->GetStorageKey(*SpecificsToEntity(specifics1)),
kAddr1SpecificsId);
}
-TEST_P(AutofillWalletSyncBridgeTest, GetStorageKeyForCard) {
+TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForCard) {
AutofillWalletSpecifics specifics2 =
CreateAutofillWalletSpecificsForCard(kCard1SpecificsId);
EXPECT_EQ(bridge()->GetStorageKey(*SpecificsToEntity(specifics2)),
kCard1SpecificsId);
}
-TEST_P(AutofillWalletSyncBridgeTest, GetStorageKeyForCustomerData) {
+TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForCustomerData) {
AutofillWalletSpecifics specifics3 =
CreateAutofillWalletSpecificsForPaymentsCustomerData(kCustomerDataId);
EXPECT_EQ(bridge()->GetStorageKey(*SpecificsToEntity(specifics3)),
kCustomerDataId);
}
-TEST_P(AutofillWalletSyncBridgeTest,
+TEST_F(AutofillWalletSyncBridgeTest,
GetAllDataForDebugging_ShouldReturnAllData) {
AutofillProfile address1 = test::GetServerProfile();
AutofillProfile address2 = test::GetServerProfile2();
@@ -427,7 +396,7 @@ TEST_P(AutofillWalletSyncBridgeTest,
// Tests that when a new wallet card and new wallet address are sent by the
// server, the client only keeps the new data.
-TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
// Create one profile and one card on the client.
AutofillProfile address1 = test::GetServerProfile();
table()->SetServerProfiles({address1});
@@ -459,12 +428,9 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
NotifyOfCreditCardChanged(RemoveChange(card1.server_id())));
StartSyncing({profile_specifics2, card_specifics2, customer_data_specifics});
- if (IsWalletMetadataOnUSS()) {
- // This bridge does not store metadata, i.e. billing_address_id. Strip it
- // off so that the expectations below pass.
- card_specifics2.mutable_masked_card()->set_billing_address_id(
- std::string());
- }
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card_specifics2.mutable_masked_card()->set_billing_address_id(std::string());
// Only the server card should be present on the client.
EXPECT_THAT(GetAllLocalData(),
@@ -475,7 +441,7 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
// Tests that in initial sync, no metrics are recorded for new addresses and
// cards.
-TEST_P(AutofillWalletSyncBridgeTest,
+TEST_F(AutofillWalletSyncBridgeTest,
MergeSyncData_NewWalletAddressAndCardNoMetricsInitialSync) {
ResetProcessor();
ResetBridge(/*initial_sync_done=*/false);
@@ -496,13 +462,11 @@ TEST_P(AutofillWalletSyncBridgeTest,
EXPECT_CALL(*backend(), CommitChanges());
StartSyncing({profile_specifics, card_specifics, customer_data_specifics});
- if (IsWalletMetadataOnUSS()) {
- ExpectCountsOfWalletMetadataInDB(/*cards_count=*/0u, /*address_count=*/0u);
+ ExpectCountsOfWalletMetadataInDB(/*cards_count=*/0u, /*address_count=*/0u);
- // This bridge does not store metadata, i.e. billing_address_id. Strip it
- // off so that the expectations below pass.
- card_specifics.mutable_masked_card()->set_billing_address_id(std::string());
- }
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card_specifics.mutable_masked_card()->set_billing_address_id(std::string());
EXPECT_THAT(GetAllLocalData(),
UnorderedElementsAre(EqualsSpecifics(profile_specifics),
@@ -512,7 +476,7 @@ TEST_P(AutofillWalletSyncBridgeTest,
// Tests that when a new payments customer data is sent by the server, the
// client only keeps the new data.
-TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
// Create one profile, one card and one customer data entry on the client.
AutofillProfile address = test::GetServerProfile();
table()->SetServerProfiles({address});
@@ -546,7 +510,7 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
// Tests that when the server sends no cards or address, the client should
// delete all it's existing data.
-TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
// Create one profile and one card on the client.
AutofillProfile local_profile = test::GetServerProfile();
table()->SetServerProfiles({local_profile});
@@ -561,18 +525,16 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
NotifyOfCreditCardChanged(RemoveChange(local_card.server_id())));
StartSyncing({});
- if (IsWalletMetadataOnUSS()) {
- // This bridge should not touch the metadata; should get deleted by the
- // metadata bridge.
- ExpectCountsOfWalletMetadataInDB(/*cards_count=*/1u, /*address_count=*/1u);
- }
+ // This bridge should not touch the metadata; should get deleted by the
+ // metadata bridge.
+ ExpectCountsOfWalletMetadataInDB(/*cards_count=*/1u, /*address_count=*/1u);
EXPECT_TRUE(GetAllLocalData().empty());
}
// Test that when the server sends the same address and card as the client has,
// nothing changes on the client.
-TEST_P(AutofillWalletSyncBridgeTest,
+TEST_F(AutofillWalletSyncBridgeTest,
MergeSyncData_SameWalletAddressAndCardAndCustomerData) {
// Create one profile and one card on the client.
AutofillProfile profile = test::GetServerProfile();
@@ -606,7 +568,7 @@ TEST_P(AutofillWalletSyncBridgeTest,
// Tests that when there are multiple changes happening at the same time, the
// data from the server is what the client ends up with.
-TEST_P(AutofillWalletSyncBridgeTest,
+TEST_F(AutofillWalletSyncBridgeTest,
MergeSyncData_AddRemoveAndPreserveWalletAddressAndCard) {
// Create two profile and one card on the client.
AutofillProfile profile = test::GetServerProfile();
@@ -638,12 +600,9 @@ TEST_P(AutofillWalletSyncBridgeTest,
NotifyOfCreditCardChanged(AddChange(card2.server_id(), card2)));
StartSyncing({profile_specifics, card2_specifics, customer_data_specifics});
- if (IsWalletMetadataOnUSS()) {
- // This bridge does not store metadata, i.e. billing_address_id. Strip it
- // off so that the expectations below pass.
- card2_specifics.mutable_masked_card()->set_billing_address_id(
- std::string());
- }
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card2_specifics.mutable_masked_card()->set_billing_address_id(std::string());
// Make sure that the client only has the data from the server.
EXPECT_THAT(GetAllLocalData(),
@@ -654,7 +613,7 @@ TEST_P(AutofillWalletSyncBridgeTest,
// Test that all field values for a address sent form the server are copied on
// the address on the client.
-TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) {
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) {
// Create a profile to be synced from the server.
AutofillProfile profile = test::GetServerProfile();
AutofillWalletSpecifics profile_specifics;
@@ -708,7 +667,7 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) {
// Test that all field values for a card sent form the server are copied on the
// card on the client.
-TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
// Create a card to be synced from the server.
CreditCard card = test::GetMaskedServerCard();
// Add this value type as it is not added by default but should be synced.
@@ -718,12 +677,10 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
StartSyncing({card_specifics});
- if (IsWalletMetadataOnUSS()) {
- // This bridge does not store metadata, i.e. billing_address_id. Strip it
- // off so that the expectations below pass.
- card.set_billing_address_id(std::string());
- card_specifics.mutable_masked_card()->set_billing_address_id(std::string());
- }
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card.set_billing_address_id(std::string());
+ card_specifics.mutable_masked_card()->set_billing_address_id(std::string());
EXPECT_THAT(GetAllLocalData(),
UnorderedElementsAre(EqualsSpecifics(card_specifics)));
@@ -747,14 +704,11 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
EXPECT_FALSE(card.LastFourDigits().empty());
EXPECT_NE(0, card.expiration_month());
EXPECT_NE(0, card.expiration_year());
- if (!IsWalletMetadataOnUSS()) {
- EXPECT_FALSE(card.billing_address_id().empty());
- }
EXPECT_NE(CreditCard::CARD_TYPE_UNKNOWN, card.card_type());
EXPECT_FALSE(card.bank_name().empty());
}
-TEST_P(AutofillWalletSyncBridgeTest, LoadMetadataCalled) {
+TEST_F(AutofillWalletSyncBridgeTest, LoadMetadataCalled) {
EXPECT_TRUE(table()->UpdateSyncMetadata(syncer::AUTOFILL_WALLET_DATA, "key",
EntityMetadata()));
@@ -765,7 +719,7 @@ TEST_P(AutofillWalletSyncBridgeTest, LoadMetadataCalled) {
ResetBridge(/*initial_sync_done=*/true);
}
-TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
+TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
// Create one profile and one card on the client.
AutofillProfile local_profile = test::GetServerProfile();
table()->SetServerProfiles({local_profile});
@@ -782,16 +736,14 @@ TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
bridge()->ApplyStopSyncChanges(
std::make_unique<syncer::InMemoryMetadataChangeList>());
- if (IsWalletMetadataOnUSS()) {
- // This bridge should not touch the metadata; should get deleted by the
- // metadata bridge.
- ExpectCountsOfWalletMetadataInDB(/*cards_count=*/1u, /*address_count=*/1u);
- }
+ // This bridge should not touch the metadata; should get deleted by the
+ // metadata bridge.
+ ExpectCountsOfWalletMetadataInDB(/*cards_count=*/1u, /*address_count=*/1u);
EXPECT_TRUE(GetAllLocalData().empty());
}
-TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
+TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
// Create one profile and one card on the client.
AutofillProfile local_profile = test::GetServerProfile();
table()->SetServerProfiles({local_profile});
@@ -811,33 +763,4 @@ TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
EXPECT_FALSE(GetAllLocalData().empty());
}
-TEST_P(AutofillWalletSyncBridgeTest, NotifiesWhenActivelySyncing) {
- testing::InSequence seq;
-
- ResetProcessor();
-
- EXPECT_CALL(*active_callback(), Run(true));
- ResetBridge(/*initial_sync_done=*/true);
-
- // Start and stop sync to check that we notify the callback.
- StartSyncing({});
-
- EXPECT_CALL(*active_callback(), Run(false));
- // Stopping sync with change list to indicate that the type is disabled.
- bridge()->ApplyStopSyncChanges(
- std::make_unique<syncer::InMemoryMetadataChangeList>());
-
- EXPECT_CALL(*active_callback(), Run(true));
- // Start and stop sync again to make sure we notify the callback again.
- StartSyncing({});
- // Passing in a non-null metadata change list indicates to the bridge that
- // sync is stopping but the data type is not disabled, so we should not get
- // a callback.
- bridge()->ApplyStopSyncChanges(/*delete_metadata_change_list=*/nullptr);
-}
-
-INSTANTIATE_TEST_SUITE_P(USS,
- AutofillWalletSyncBridgeTest,
- ::testing::Values(false, true));
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc
index e4fc19f8c14..8a3d73167f7 100644
--- a/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -7,7 +7,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -17,8 +16,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h"
-#include "base/task/thread_pool/thread_pool.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -92,19 +91,17 @@ class MockAutofillWebDataServiceObserver
class WebDataServiceTest : public testing::Test {
public:
WebDataServiceTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
protected:
void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath path = temp_dir_.GetPath().AppendASCII("TestWebDB");
+ base::FilePath path(WebDatabase::kInMemoryPath);
// TODO(pkasting): http://crbug.com/740773 This should likely be sequenced,
// not single-threaded; it's also possible the various uses of this below
// should each use their own sequences instead of sharing this one.
- auto db_task_runner =
- base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()});
+ auto db_task_runner = base::CreateSingleThreadTaskRunner(
+ {base::ThreadPool(), base::MayBlock()});
wdbs_ = new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
db_task_runner);
wdbs_->AddTable(std::make_unique<AutofillTable>());
@@ -121,14 +118,13 @@ class WebDataServiceTest : public testing::Test {
wdbs_->ShutdownDatabase();
wds_ = nullptr;
wdbs_ = nullptr;
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::FilePath profile_dir_;
scoped_refptr<AutofillWebDataService> wds_;
scoped_refptr<WebDatabaseService> wdbs_;
- base::ScopedTempDir temp_dir_;
};
class WebDataServiceAutofillTest : public WebDataServiceTest {
@@ -210,7 +206,7 @@ TEST_F(WebDataServiceAutofillTest, FormFillAdd) {
static const int limit = 10;
handle = wds_->GetFormValuesForElementName(
name1_, base::string16(), limit, &consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
EXPECT_EQ(value1_, consumer.result()[0].key().value());
@@ -287,7 +283,7 @@ TEST_F(WebDataServiceAutofillTest, ProfileAdd) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<AutofillProfile>>>
consumer;
WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
EXPECT_EQ(profile, *consumer.result()[0]);
@@ -306,7 +302,7 @@ TEST_F(WebDataServiceAutofillTest, ProfileRemove) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<AutofillProfile>>>
consumer;
WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
EXPECT_EQ(profile, *consumer.result()[0]);
@@ -325,7 +321,7 @@ TEST_F(WebDataServiceAutofillTest, ProfileRemove) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<AutofillProfile>>>
consumer2;
WebDataServiceBase::Handle handle2 = wds_->GetAutofillProfiles(&consumer2);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle2, consumer2.handle());
ASSERT_EQ(0U, consumer2.result().size());
}
@@ -351,7 +347,7 @@ TEST_F(WebDataServiceAutofillTest, ProfileUpdate) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<AutofillProfile>>>
consumer;
WebDataServiceBase::Handle handle = wds_->GetAutofillProfiles(&consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(2U, consumer.result().size());
EXPECT_EQ(profile2, *consumer.result()[0]);
@@ -373,7 +369,7 @@ TEST_F(WebDataServiceAutofillTest, ProfileUpdate) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<AutofillProfile>>>
consumer2;
WebDataServiceBase::Handle handle2 = wds_->GetAutofillProfiles(&consumer2);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle2, consumer2.handle());
ASSERT_EQ(2U, consumer2.result().size());
EXPECT_EQ(profile2_changed, *consumer2.result()[0]);
@@ -389,7 +385,7 @@ TEST_F(WebDataServiceAutofillTest, CreditAdd) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
consumer;
WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
EXPECT_EQ(card, *consumer.result()[0]);
@@ -405,7 +401,7 @@ TEST_F(WebDataServiceAutofillTest, CreditCardRemove) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
consumer;
WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(1U, consumer.result().size());
EXPECT_EQ(credit_card, *consumer.result()[0]);
@@ -417,7 +413,7 @@ TEST_F(WebDataServiceAutofillTest, CreditCardRemove) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
consumer2;
WebDataServiceBase::Handle handle2 = wds_->GetCreditCards(&consumer2);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle2, consumer2.handle());
ASSERT_EQ(0U, consumer2.result().size());
}
@@ -435,7 +431,7 @@ TEST_F(WebDataServiceAutofillTest, CreditUpdate) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
consumer;
WebDataServiceBase::Handle handle = wds_->GetCreditCards(&consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, consumer.handle());
ASSERT_EQ(2U, consumer.result().size());
EXPECT_EQ(card2, *consumer.result()[0]);
@@ -450,7 +446,7 @@ TEST_F(WebDataServiceAutofillTest, CreditUpdate) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
consumer2;
WebDataServiceBase::Handle handle2 = wds_->GetCreditCards(&consumer2);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle2, consumer2.handle());
ASSERT_EQ(2U, consumer2.result().size());
EXPECT_NE(card2, *consumer2.result()[0]);
@@ -471,7 +467,7 @@ TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) {
profile_consumer;
WebDataServiceBase::Handle handle =
wds_->GetAutofillProfiles(&profile_consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, profile_consumer.handle());
ASSERT_EQ(1U, profile_consumer.result().size());
EXPECT_EQ(profile, *profile_consumer.result()[0]);
@@ -484,7 +480,7 @@ TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
card_consumer;
handle = wds_->GetCreditCards(&card_consumer);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle, card_consumer.handle());
ASSERT_EQ(1U, card_consumer.result().size());
EXPECT_EQ(credit_card, *card_consumer.result()[0]);
@@ -504,7 +500,7 @@ TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) {
profile_consumer2;
WebDataServiceBase::Handle handle2 =
wds_->GetAutofillProfiles(&profile_consumer2);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle2, profile_consumer2.handle());
ASSERT_EQ(0U, profile_consumer2.result().size());
@@ -512,7 +508,7 @@ TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) {
AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>>
card_consumer2;
handle2 = wds_->GetCreditCards(&card_consumer2);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(handle2, card_consumer2.handle());
ASSERT_EQ(0U, card_consumer2.result().size());
}
diff --git a/chromium/components/autofill/core/common/autofill_features.cc b/chromium/components/autofill/core/common/autofill_features.cc
index b0504b4fa64..d7a0b6e4957 100644
--- a/chromium/components/autofill/core/common/autofill_features.cc
+++ b/chromium/components/autofill/core/common/autofill_features.cc
@@ -34,11 +34,6 @@ const base::Feature kAutofillAllowNonHttpActivation{
const base::Feature kAutofillAlwaysFillAddresses{
"AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
-// Controls whether the server cards are always shown when the user is in sync
-// transport mode, or if an explicit opt-in is required.
-const base::Feature kAutofillAlwaysShowServerCardsInSyncTransport{
- "AlwaysShowServerCardsInSyncTransport", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Controls the use of GET (instead of POST) to fetch cacheable autofill query
// responses.
const base::Feature kAutofillCacheQueryResponses{
@@ -55,12 +50,6 @@ const base::Feature kAutofillCreditCardAssist{
const base::Feature kAutofillEnableAccountWalletStorage{
"AutofillEnableAccountWalletStorage", base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls whether we show also upload prompts when we are using the
-// account-based storage for server cards.
-const base::Feature kAutofillEnableAccountWalletStorageUpload{
- "AutofillEnableAccountWalletStorageUpload",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Controls whether we use COMPANY as part of Autofill
const base::Feature kAutofillEnableCompanyName{
"AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -86,7 +75,7 @@ const base::Feature kAutofillEnforceMinRequiredFieldsForUpload{
// When enabled, gets payment identity from sync service instead of
// identity manager.
const base::Feature kAutofillGetPaymentsIdentityFromSync{
- "AutofillGetPaymentsIdentityFromSync", base::FEATURE_DISABLED_BY_DEFAULT};
+ "AutofillGetPaymentsIdentityFromSync", base::FEATURE_ENABLED_BY_DEFAULT};
// When enabled, autofill suggestions are displayed in the keyboard accessory
// instead of the regular popup.
@@ -149,11 +138,6 @@ const base::Feature kAutofillSaveOnProbablySubmitted{
const base::Feature kAutofillServerCommunication{
"AutofillServerCommunication", base::FEATURE_ENABLED_BY_DEFAULT};
-// Controls whether the payments settings page should list the credit cards
-// split by type: Local of from Account.
-const base::Feature kAutofillSettingsCardTypeSplit{
- "AutofillSettingsCardTypeSplit", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Controls whether autofill suggestions are filtered by field values previously
// filled by website.
const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms{
@@ -194,11 +178,6 @@ const base::Feature kAutofillUseImprovedLabelDisambiguation{
"AutofillUseImprovedLabelDisambiguation",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls whether password generation is offered automatically on fields
-// perceived as eligible for generation.
-const base::Feature kAutomaticPasswordGeneration = {
- "AutomaticPasswordGeneration", base::FEATURE_ENABLED_BY_DEFAULT};
-
#if defined(OS_ANDROID)
// Controls whether the Autofill manual fallback for Addresses and Payments is
// present on Android.
diff --git a/chromium/components/autofill/core/common/autofill_features.h b/chromium/components/autofill/core/common/autofill_features.h
index e3a45a8032b..8e6937f5447 100644
--- a/chromium/components/autofill/core/common/autofill_features.h
+++ b/chromium/components/autofill/core/common/autofill_features.h
@@ -24,12 +24,10 @@ namespace features {
extern const base::Feature kAutofillAddressNormalizer;
extern const base::Feature kAutofillAllowNonHttpActivation;
extern const base::Feature kAutofillAlwaysFillAddresses;
-extern const base::Feature kAutofillAlwaysShowServerCardsInSyncTransport;
extern const base::Feature kAutofillCacheQueryResponses;
extern const base::Feature kAutofillCreateDataForTest;
extern const base::Feature kAutofillCreditCardAssist;
extern const base::Feature kAutofillEnableAccountWalletStorage;
-extern const base::Feature kAutofillEnableAccountWalletStorageUpload;
extern const base::Feature kAutofillEnableCompanyName;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForQuery;
@@ -48,7 +46,6 @@ extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
extern const base::Feature kAutofillRichMetadataQueries;
extern const base::Feature kAutofillSaveOnProbablySubmitted;
extern const base::Feature kAutofillServerCommunication;
-extern const base::Feature kAutofillSettingsCardTypeSplit;
extern const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms;
extern const base::Feature kAutofillShowAutocompleteConsoleWarnings;
extern const base::Feature kAutofillShowTypePredictions;
@@ -57,7 +54,6 @@ extern const base::Feature kAutofillTokenPrefixMatching;
extern const base::Feature kAutofillUploadThrottling;
extern const base::Feature kAutofillUseApi;
extern const base::Feature kAutofillUseImprovedLabelDisambiguation;
-extern const base::Feature kAutomaticPasswordGeneration;
#if defined(OS_ANDROID)
extern const base::Feature kAutofillManualFallbackAndroid;
diff --git a/chromium/components/autofill/core/common/autofill_internals/log_message.h b/chromium/components/autofill/core/common/autofill_internals/log_message.h
index 828420fbc62..4862e5e448e 100644
--- a/chromium/components/autofill/core/common/autofill_internals/log_message.h
+++ b/chromium/components/autofill/core/common/autofill_internals/log_message.h
@@ -12,7 +12,10 @@ namespace autofill {
// Generator for log message. If you need to find the call site for a log
// message, take the first parameter (e.g. ParsedForms) and search for
// that name prefixed with a k (e.g. kParsedForms) in code search.
-#define AUTOFILL_LOG_MESSAGE_TEMPLATES(T) T(ParsedForms, "Parsed forms:")
+#define AUTOFILL_LOG_MESSAGE_TEMPLATES(T) \
+ T(ParsedForms, "Parsed forms:") \
+ T(SendAutofillUpload, "Sending Autofill Upload Request:") \
+ T(LocalHeuristicRegExMatched, "RegEx of local heuristic matched:")
// Log messages for chrome://autofill-internals.
#define AUTOFILL_TEMPLATE(NAME, MESSAGE) k##NAME,
diff --git a/chromium/components/autofill/core/common/autofill_internals/logging_scope.h b/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
index 53ded127d52..ac719ca73dd 100644
--- a/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
+++ b/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
@@ -19,7 +19,9 @@ namespace autofill {
/* Log messages related to filling of forms. */ \
T(Filling) \
/* Log messages related to the submission of forms. */ \
- T(Submission)
+ T(Submission) \
+ /* Log messages related to communication with autofill server. */ \
+ T(AutofillServer)
// Define a bunch of logging scopes: kContext, kParsing, ...
#define AUTOFILL_TEMPLATE(NAME) k##NAME,
diff --git a/chromium/components/autofill/core/common/autofill_payments_features.cc b/chromium/components/autofill/core/common/autofill_payments_features.cc
index 1b376c749df..6fd64901fe7 100644
--- a/chromium/components/autofill/core/common/autofill_payments_features.cc
+++ b/chromium/components/autofill/core/common/autofill_payments_features.cc
@@ -50,10 +50,6 @@ const base::Feature kAutofillCreditCardUploadFeedback{
const base::Feature kAutofillDoNotMigrateUnsupportedLocalCards{
"AutofillDoNotMigrateUnsupportedLocalCards",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-const base::Feature kAutofillDoNotUploadSaveUnsupportedCards{
- "AutofillDoNotUploadSaveUnsupportedCards",
base::FEATURE_ENABLED_BY_DEFAULT};
// Controls whether the credit card downstream keyboard accessory shows
@@ -77,12 +73,6 @@ const base::Feature kAutofillEnableToolbarStatusChip{
const base::Feature kAutofillImportDynamicForms{
"AutofillImportDynamicForms", base::FEATURE_ENABLED_BY_DEFAULT};
-// When enabled, a credit card form that is hidden after receiving input can
-// import the card.
-const base::Feature kAutofillImportNonFocusableCreditCardForms{
- "AutofillImportNonFocusableCreditCardForms",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Controls whether offering to migrate cards will consider data from the
// Autofill strike database (new version).
const base::Feature kAutofillLocalCardMigrationUsesStrikeSystemV2{
@@ -112,11 +102,9 @@ const base::Feature kAutofillSaveCreditCardUsesImprovedMessaging{
"AutofillSaveCreditCardUsesImprovedMessaging",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls whether experiment ids should be sent through
-// Google Payments RPCs or not.
-const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs{
- "AutofillSendExperimentIdsInPaymentsRPCs",
- base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether to show updated UI for the card unmask prompt.
+const base::Feature kAutofillUpdatedCardUnmaskPromptUi{
+ "AutofillUpdatedCardUnmaskPromptUi", base::FEATURE_DISABLED_BY_DEFAULT};
// Controls offering credit card upload to Google Payments. Cannot ever be
// ENABLED_BY_DEFAULT because it's a country-specific whitelist. There are
@@ -148,14 +136,6 @@ const base::Feature kAutofillUpstreamBlankCardholderNameField{
"AutofillUpstreamBlankCardholderNameField",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls whether ELO cards should be uploaded to Google Payments.
-const base::Feature kAutofillUpstreamDisallowElo{
- "AutofillUpstreamDisallowElo", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Controls whether JCB cards should be uploaded to Google Payments.
-const base::Feature kAutofillUpstreamDisallowJcb{
- "AutofillUpstreamDisallowJcb", base::FEATURE_DISABLED_BY_DEFAULT};
-
// If enabled, Chrome Upstream can request the user to enter/confirm cardholder
// name in the offer-to-save bubble if it was not detected or was conflicting
// during the checkout flow and the user is NOT a Google Payments customer.
@@ -169,8 +149,13 @@ const base::Feature kAutofillUpstreamEditableCardholderName{
};
const base::Feature kAutofillUpstreamEditableExpirationDate{
- "AutofillUpstreamEditableExpirationDate",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ "AutofillUpstreamEditableExpirationDate",
+#if defined(OS_ANDROID)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
bool ShouldShowImprovedUserConsentForCreditCardSave() {
#if defined(OS_WIN) || defined(OS_MACOSX) || \
diff --git a/chromium/components/autofill/core/common/autofill_payments_features.h b/chromium/components/autofill/core/common/autofill_payments_features.h
index 95264e112bf..b0f0e2827e5 100644
--- a/chromium/components/autofill/core/common/autofill_payments_features.h
+++ b/chromium/components/autofill/core/common/autofill_payments_features.h
@@ -23,24 +23,20 @@ extern const base::Feature kAutofillCreditCardAblationExperiment;
extern const base::Feature kAutofillCreditCardAuthentication;
extern const base::Feature kAutofillCreditCardUploadFeedback;
extern const base::Feature kAutofillDoNotMigrateUnsupportedLocalCards;
-extern const base::Feature kAutofillDoNotUploadSaveUnsupportedCards;
extern const base::Feature kAutofillDownstreamUseGooglePayBrandingOniOS;
extern const base::Feature kAutofillEnableLocalCardMigrationForNonSyncUser;
extern const base::Feature kAutofillEnableToolbarStatusChip;
extern const base::Feature kAutofillImportDynamicForms;
-extern const base::Feature kAutofillImportNonFocusableCreditCardForms;
extern const base::Feature kAutofillLocalCardMigrationUsesStrikeSystemV2;
extern const base::Feature kAutofillNoLocalSaveOnUnmaskSuccess;
extern const base::Feature kAutofillNoLocalSaveOnUploadSuccess;
extern const base::Feature kAutofillSaveCardShowNoThanks;
extern const base::Feature kAutofillSaveCreditCardUsesImprovedMessaging;
-extern const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs;
+extern const base::Feature kAutofillUpdatedCardUnmaskPromptUi;
extern const base::Feature kAutofillUpstream;
extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
extern const base::Feature kAutofillUpstreamAlwaysRequestCardholderName;
extern const base::Feature kAutofillUpstreamBlankCardholderNameField;
-extern const base::Feature kAutofillUpstreamDisallowElo;
-extern const base::Feature kAutofillUpstreamDisallowJcb;
extern const base::Feature kAutofillUpstreamEditableCardholderName;
extern const base::Feature kAutofillUpstreamEditableExpirationDate;
diff --git a/chromium/components/autofill/core/common/autofill_prefs.cc b/chromium/components/autofill/core/common/autofill_prefs.cc
index 9f7210897cc..7801f45ada6 100644
--- a/chromium/components/autofill/core/common/autofill_prefs.cc
+++ b/chromium/components/autofill/core/common/autofill_prefs.cc
@@ -43,6 +43,10 @@ int GetSyncTransportOptInBitFieldForAccount(const PrefService* prefs,
const char kAutofillAcceptSaveCreditCardPromptState[] =
"autofill.accept_save_credit_card_prompt_state";
+// Boolean that is true if FIDO Authentication is enabled for card unmasking.
+const char kAutofillCreditCardFIDOAuthEnabled[] =
+ "autofill.credit_card_fido_auth_enabled";
+
// Boolean that is true if Autofill is enabled and allowed to save credit card
// data.
const char kAutofillCreditCardEnabled[] = "autofill.credit_card_enabled";
@@ -153,6 +157,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
// Non-synced prefs. Used for per-device choices, e.g., signin promo.
+ registry->RegisterBooleanPref(prefs::kAutofillCreditCardFIDOAuthEnabled,
+ false);
registry->RegisterIntegerPref(
prefs::kAutofillCreditCardSigninPromoImpressionCount, 0);
registry->RegisterBooleanPref(prefs::kAutofillJapanCityFieldMigrated, false);
@@ -219,6 +225,14 @@ void SetAutofillEnabled(PrefService* prefs, bool enabled) {
SetCreditCardAutofillEnabled(prefs, enabled);
}
+bool IsCreditCardFIDOAuthEnabled(PrefService* prefs) {
+ return prefs->GetBoolean(kAutofillCreditCardFIDOAuthEnabled);
+}
+
+void SetCreditCardFIDOAuthEnabled(PrefService* prefs, bool enabled) {
+ prefs->SetBoolean(kAutofillCreditCardFIDOAuthEnabled, enabled);
+}
+
bool IsCreditCardAutofillEnabled(const PrefService* prefs) {
return prefs->GetBoolean(kAutofillCreditCardEnabled);
}
diff --git a/chromium/components/autofill/core/common/autofill_prefs.h b/chromium/components/autofill/core/common/autofill_prefs.h
index a33f91d5e1e..f807434285e 100644
--- a/chromium/components/autofill/core/common/autofill_prefs.h
+++ b/chromium/components/autofill/core/common/autofill_prefs.h
@@ -20,6 +20,7 @@ namespace prefs {
// component. Keep alphabetized, and document each in the .cc file.
extern const char kAutofillAcceptSaveCreditCardPromptState[];
// Do not get/set the value of this pref directly. Use provided getter/setter.
+extern const char kAutofillCreditCardFIDOAuthEnabled[];
extern const char kAutofillCreditCardEnabled[];
extern const char kAutofillCreditCardSigninPromoImpressionCount[];
// Please use kAutofillCreditCardEnabled and kAutofillProfileEnabled instead.
@@ -69,6 +70,10 @@ bool IsAutofillEnabled(const PrefService* prefs);
void SetAutofillEnabled(PrefService* prefs, bool enabled);
+bool IsCreditCardFIDOAuthEnabled(PrefService* prefs);
+
+void SetCreditCardFIDOAuthEnabled(PrefService* prefs, bool enabled);
+
bool IsCreditCardAutofillEnabled(const PrefService* prefs);
void SetCreditCardAutofillEnabled(PrefService* prefs, bool enabled);
diff --git a/chromium/components/autofill/core/common/autofill_regex_constants.cc b/chromium/components/autofill/core/common/autofill_regex_constants.cc
index 077f1b040c8..7cb75718ae4 100644
--- a/chromium/components/autofill/core/common/autofill_regex_constants.cc
+++ b/chromium/components/autofill/core/common/autofill_regex_constants.cc
@@ -501,6 +501,12 @@ const char kUPIVirtualPaymentAddressRe[] =
const char kInternationalBankAccountNumberRe[] =
"^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}$";
+// Matches all 3 and 4 digit numbers.
+const char kCreditCardCVCPattern[] = "^\\d{3,4}$";
+
+// Matches numbers in the range [2010-2099].
+const char kCreditCard4DigitExpYearPattern[] = "^[2][0][1-9][0-9]$";
+
/////////////////////////////////////////////////////////////////////////////
// form_structure.cc
/////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/components/autofill/core/common/autofill_regex_constants.h b/chromium/components/autofill/core/common/autofill_regex_constants.h
index 5fcbab3fab6..67a2ead5088 100644
--- a/chromium/components/autofill/core/common/autofill_regex_constants.h
+++ b/chromium/components/autofill/core/common/autofill_regex_constants.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 COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEX_CONSTANTS_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEX_CONSTANTS_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEX_CONSTANTS_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEX_CONSTANTS_H_
namespace autofill {
@@ -61,6 +61,8 @@ extern const char kTravelOriginRe[];
extern const char kTravelDestinationRe[];
extern const char kFlightRe[];
extern const char kPriceRe[];
+extern const char kCreditCardCVCPattern[];
+extern const char kCreditCard4DigitExpYearPattern[];
// Used to match field data that might be a UPI Virtual Payment Address.
// See:
@@ -85,4 +87,4 @@ extern const char kUrlSearchActionRe[];
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEX_CONSTANTS_H_
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEX_CONSTANTS_H_
diff --git a/chromium/components/autofill/core/common/autofill_regexes.cc b/chromium/components/autofill/core/common/autofill_regexes.cc
index c4402bcfbb0..b141cb2d0f6 100644
--- a/chromium/components/autofill/core/common/autofill_regexes.cc
+++ b/chromium/components/autofill/core/common/autofill_regexes.cc
@@ -8,6 +8,7 @@
#include <unordered_map>
#include <utility>
+#include "base/i18n/unicodestring.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/no_destructor.h"
@@ -62,7 +63,8 @@ icu::RegexMatcher* AutofillRegexes::GetMatcher(const base::string16& pattern) {
namespace autofill {
bool MatchesPattern(const base::string16& input,
- const base::string16& pattern) {
+ const base::string16& pattern,
+ base::string16* match) {
static base::NoDestructor<AutofillRegexes> g_autofill_regexes;
static base::NoDestructor<base::Lock> g_lock;
base::AutoLock lock(*g_lock);
@@ -72,9 +74,16 @@ bool MatchesPattern(const base::string16& input,
matcher->reset(icu_input);
UErrorCode status = U_ZERO_ERROR;
- UBool match = matcher->find(0, status);
+ UBool matched = matcher->find(0, status);
DCHECK(U_SUCCESS(status));
- return match == TRUE;
+
+ if (matched == TRUE && match) {
+ icu::UnicodeString match_unicode = matcher->group(0, status);
+ DCHECK(U_SUCCESS(status));
+ *match = base::i18n::UnicodeStringToString16(match_unicode);
+ }
+
+ return matched == TRUE;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_regexes.h b/chromium/components/autofill/core/common/autofill_regexes.h
index 1bf1aa73a6c..9bed8f717ce 100644
--- a/chromium/components/autofill/core/common/autofill_regexes.h
+++ b/chromium/components/autofill/core/common/autofill_regexes.h
@@ -12,8 +12,10 @@ namespace autofill {
// Case-insensitive regular expression matching.
// Returns true if |pattern| is found in |input|.
+// If |match| is not nullptr, the matched part is assigned to it.
bool MatchesPattern(const base::string16& input,
- const base::string16& pattern);
+ const base::string16& pattern,
+ base::string16* match = nullptr);
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/form_field_data.h b/chromium/components/autofill/core/common/form_field_data.h
index 0fa56be4a73..b9d4f9d6013 100644
--- a/chromium/components/autofill/core/common/form_field_data.h
+++ b/chromium/components/autofill/core/common/form_field_data.h
@@ -103,9 +103,10 @@ struct FormFieldData {
// TODO(crbug.com/896689): Expand the logic/application of this to other
// platforms and/or merge this concept with |unique_renderer_id|.
base::string16 unique_id;
-#define EXPECT_EQ_UNIQUE_ID() EXPECT_EQ(expected.unique_id, actual.unique_id)
+#define EXPECT_EQ_UNIQUE_ID(expected, actual) \
+ EXPECT_EQ((expected).unique_id, (actual).unique_id)
#else
-#define EXPECT_EQ_UNIQUE_ID()
+#define EXPECT_EQ_UNIQUE_ID(expected, actual)
#endif
// The name by which autofill knows this field. This is generally either the
@@ -184,7 +185,7 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field);
// |FormFieldData|s in test code.
#define EXPECT_FORM_FIELD_DATA_EQUALS(expected, actual) \
do { \
- EXPECT_EQ_UNIQUE_ID(); \
+ EXPECT_EQ_UNIQUE_ID(expected, actual); \
EXPECT_EQ(expected.label, actual.label); \
EXPECT_EQ(expected.name, actual.name); \
EXPECT_EQ(expected.value, actual.value); \
diff --git a/chromium/components/autofill/core/common/mojom/BUILD.gn b/chromium/components/autofill/core/common/mojom/BUILD.gn
index 118d4d5fd82..f3ca8036267 100644
--- a/chromium/components/autofill/core/common/mojom/BUILD.gn
+++ b/chromium/components/autofill/core/common/mojom/BUILD.gn
@@ -11,7 +11,7 @@ mojom("mojo_types") {
public_deps = [
"//mojo/public/mojom/base",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
]
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types.mojom b/chromium/components/autofill/core/common/mojom/autofill_types.mojom
index 503138cdd93..8e8a3c3c44d 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types.mojom
+++ b/chromium/components/autofill/core/common/mojom/autofill_types.mojom
@@ -7,7 +7,7 @@ module autofill.mojom;
import "mojo/public/mojom/base/text_direction.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/string16.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types.typemap b/chromium/components/autofill/core/common/mojom/autofill_types.typemap
index 99febf4ba1d..6b444c359f4 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types.typemap
+++ b/chromium/components/autofill/core/common/mojom/autofill_types.typemap
@@ -23,20 +23,20 @@ deps = [
"//base",
"//base:i18n",
"//components/autofill/core/common",
- "//ui/gfx/geometry/mojo:struct_traits",
+ "//ui/gfx/geometry/mojom:mojom_traits",
]
type_mappings = [
- "autofill.mojom.FormData=autofill::FormData",
- "autofill.mojom.FormDataPredictions=autofill::FormDataPredictions",
- "autofill.mojom.FormFieldData=autofill::FormFieldData",
- "autofill.mojom.FormFieldDataPredictions=autofill::FormFieldDataPredictions",
- "autofill.mojom.FormsPredictionsMap=autofill::FormsPredictionsMap",
- "autofill.mojom.PasswordAndRealm=autofill::PasswordAndRealm",
- "autofill.mojom.PasswordForm=autofill::PasswordForm",
- "autofill.mojom.PasswordFormFieldPredictionMap=autofill::PasswordFormFieldPredictionMap",
- "autofill.mojom.PasswordFormFillData=autofill::PasswordFormFillData",
- "autofill.mojom.PasswordFormGenerationData=autofill::PasswordFormGenerationData",
- "autofill.mojom.PasswordGenerationUIData=autofill::password_generation::PasswordGenerationUIData",
- "autofill.mojom.ValueElementPair=autofill::ValueElementPair",
+ "autofill.mojom.FormData=::autofill::FormData",
+ "autofill.mojom.FormDataPredictions=::autofill::FormDataPredictions",
+ "autofill.mojom.FormFieldData=::autofill::FormFieldData",
+ "autofill.mojom.FormFieldDataPredictions=::autofill::FormFieldDataPredictions",
+ "autofill.mojom.FormsPredictionsMap=::autofill::FormsPredictionsMap",
+ "autofill.mojom.PasswordAndRealm=::autofill::PasswordAndRealm",
+ "autofill.mojom.PasswordForm=::autofill::PasswordForm",
+ "autofill.mojom.PasswordFormFieldPredictionMap=::autofill::PasswordFormFieldPredictionMap",
+ "autofill.mojom.PasswordFormFillData=::autofill::PasswordFormFillData",
+ "autofill.mojom.PasswordFormGenerationData=::autofill::PasswordFormGenerationData",
+ "autofill.mojom.PasswordGenerationUIData=::autofill::password_generation::PasswordGenerationUIData",
+ "autofill.mojom.ValueElementPair=::autofill::ValueElementPair",
]
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
index f7ba57fe941..9128a8523fc 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
+++ b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -7,7 +7,7 @@
#include "base/i18n/rtl.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
-#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
+#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
#include "url/mojom/origin_mojom_traits.h"
#include "url/mojom/url_gurl_mojom_traits.h"
diff --git a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
index 7dec39808d7..37c68ad829a 100644
--- a/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
+++ b/chromium/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
@@ -254,7 +254,7 @@ class AutofillTypeTraitsTestImpl : public testing::Test,
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
mojo::BindingSet<TypeTraitsTest> bindings_;
};
diff --git a/chromium/components/autofill/core/common/password_form.cc b/chromium/components/autofill/core/common/password_form.cc
index 17bfc76e371..fc34f742b52 100644
--- a/chromium/components/autofill/core/common/password_form.cc
+++ b/chromium/components/autofill/core/common/password_form.cc
@@ -63,6 +63,7 @@ void PasswordFormToJSON(const PasswordForm& form,
ValueElementVectorToString(form.all_possible_passwords));
target->SetBoolean("blacklisted", form.blacklisted_by_user);
target->SetBoolean("preferred", form.preferred);
+ target->SetDouble("date_last_used", form.date_last_used.ToDoubleT());
target->SetDouble("date_created", form.date_created.ToDoubleT());
target->SetDouble("date_synced", form.date_synced.ToDoubleT());
target->SetString("type", ToString(form.type));
@@ -108,16 +109,33 @@ bool PasswordForm::IsPossibleChangePasswordFormWithoutUsername() const {
return IsPossibleChangePasswordForm() && username_element.empty();
}
+bool PasswordForm::HasUsernameElement() const {
+ return has_renderer_ids ? username_element_renderer_id !=
+ FormFieldData::kNotSetFormControlRendererId
+ : !username_element.empty();
+}
+
bool PasswordForm::HasPasswordElement() const {
return has_renderer_ids ? password_element_renderer_id !=
FormFieldData::kNotSetFormControlRendererId
: !password_element.empty();
}
+bool PasswordForm::HasNewPasswordElement() const {
+ return has_renderer_ids ? new_password_element_renderer_id !=
+ FormFieldData::kNotSetFormControlRendererId
+ : !new_password_element.empty();
+}
+
bool PasswordForm::IsFederatedCredential() const {
return !federation_origin.opaque();
}
+bool PasswordForm::IsSingleUsername() const {
+ return HasUsernameElement() && !HasPasswordElement() &&
+ !HasNewPasswordElement();
+}
+
bool PasswordForm::operator==(const PasswordForm& form) const {
return scheme == form.scheme && signon_realm == form.signon_realm &&
origin == form.origin && action == form.action &&
@@ -143,6 +161,7 @@ bool PasswordForm::operator==(const PasswordForm& form) const {
new_password_value == form.new_password_value &&
preferred == form.preferred && date_created == form.date_created &&
date_synced == form.date_synced &&
+ date_last_used == form.date_last_used &&
blacklisted_by_user == form.blacklisted_by_user && type == form.type &&
times_used == form.times_used &&
form_data.SameFormAs(form.form_data) &&
diff --git a/chromium/components/autofill/core/common/password_form.h b/chromium/components/autofill/core/common/password_form.h
index 4d8c4eb8458..348900b8212 100644
--- a/chromium/components/autofill/core/common/password_form.h
+++ b/chromium/components/autofill/core/common/password_form.h
@@ -209,6 +209,14 @@ struct PasswordForm {
// When parsing an HTML form, this is not used.
bool preferred = false;
+ // When the login was last used by the user to login to the site. Defaults to
+ // |date_created|, except for passwords that were migrated from the
+ // |preferred| flag. Their default is set when migrating the login database to
+ // have the "date_last_used" column.
+ //
+ // When parsing an HTML form, this is not used.
+ base::Time date_last_used;
+
// When the login was saved (by chrome).
//
// When parsing an HTML form, this is not used.
@@ -305,11 +313,21 @@ struct PasswordForm {
bool IsPossibleChangePasswordFormWithoutUsername() const;
// Returns true if current password element is set.
+ bool HasUsernameElement() const;
+
+ // Returns true if current password element is set.
bool HasPasswordElement() const;
+ // Returns true if current password element is set.
+ bool HasNewPasswordElement() const;
+
// True iff |federation_origin| isn't empty.
bool IsFederatedCredential() const;
+ // True if username element is set and password and new password elements are
+ // not set.
+ bool IsSingleUsername() const;
+
// Equality operators for testing.
bool operator==(const PasswordForm& form) const;
bool operator!=(const PasswordForm& form) const;
diff --git a/chromium/components/autofill/core/common/password_form_fill_data.cc b/chromium/components/autofill/core/common/password_form_fill_data.cc
index 920903cac57..db08ce036bb 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data.cc
@@ -38,10 +38,11 @@ PasswordFormFillData::PasswordFormFillData(
// by the password autocomplete code.
username_field.value = preferred_match.username_value;
password_field.value = preferred_match.password_value;
- if (!form_on_page.only_for_fallback) {
- // Fill fields identifying information only for non-fallback case. In
- // fallback case, a fill popup is shown on clicking on each password
- // field so no need in any field identifiers.
+ if (!form_on_page.only_for_fallback &&
+ (form_on_page.HasPasswordElement() || form_on_page.IsSingleUsername())) {
+ // Fill fields identifying information only for non-fallback case when
+ // password element is found. In other cases a fill popup is shown on
+ // clicking on each password field so no need in any field identifiers.
username_field.name = form_on_page.username_element;
username_field.unique_renderer_id =
form_on_page.username_element_renderer_id;
diff --git a/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc b/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc
index c6f50027125..b794cc1115f 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data_unittest.cc
@@ -262,4 +262,39 @@ TEST(PasswordFormFillDataTest, RendererIDs) {
EXPECT_TRUE(result.username_may_use_prefilled_placeholder);
}
+// Tests that nor username nor password fields are set when password element is
+// not found.
+TEST(PasswordFormFillDataTest, NoPasswordElement) {
+ // Create the current form on the page.
+ PasswordForm form_on_page;
+ form_on_page.origin = GURL("https://foo.com/");
+ form_on_page.has_renderer_ids = true;
+ form_on_page.username_element_renderer_id = 123;
+ // Set no password element.
+ form_on_page.password_element_renderer_id =
+ std::numeric_limits<uint32_t>::max();
+ form_on_page.new_password_element_renderer_id = 456;
+
+ // Create an exact match in the database.
+ PasswordForm preferred_match = form_on_page;
+ preferred_match.username_value = ASCIIToUTF16("test@gmail.com");
+ preferred_match.password_value = ASCIIToUTF16("test");
+ preferred_match.preferred = true;
+
+ FormData form_data;
+ form_data.unique_renderer_id = 42;
+ form_data.is_form_tag = true;
+ form_on_page.form_data = form_data;
+
+ PasswordFormFillData result(form_on_page, {} /* matches */, preferred_match,
+ true);
+
+ // Check that nor username nor password fields are set.
+ EXPECT_EQ(true, result.has_renderer_ids);
+ EXPECT_EQ(std::numeric_limits<uint32_t>::max(),
+ result.username_field.unique_renderer_id);
+ EXPECT_EQ(std::numeric_limits<uint32_t>::max(),
+ result.password_field.unique_renderer_id);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/password_generation_util.cc b/chromium/components/autofill/core/common/password_generation_util.cc
index 2b74353e903..8bab183bf31 100644
--- a/chromium/components/autofill/core/common/password_generation_util.cc
+++ b/chromium/components/autofill/core/common/password_generation_util.cc
@@ -44,10 +44,5 @@ void LogPasswordGenerationEvent(PasswordGenerationEvent event) {
event, EVENT_ENUM_COUNT);
}
-bool IsPasswordGenerationEnabled() {
- return base::FeatureList::IsEnabled(
- autofill::features::kAutomaticPasswordGeneration);
-}
-
} // namespace password_generation
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.cc b/chromium/components/autofill/core/common/save_password_progress_logger.cc
index 542fe87cd6e..91807e55dce 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -275,10 +275,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "provisionally_saved_forms_[form_frame]";
case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVE_FORM_METHOD:
return "PasswordManager::ProvisionallySaveForm";
- case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD:
- return "PasswordManager::ProvisionallySavePassword";
- case SavePasswordProgressLogger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM:
- return "ProvisionallySavePassword form";
case SavePasswordProgressLogger::STRING_IS_SAVING_ENABLED:
return "IsSavingAndFillingEnabled";
case SavePasswordProgressLogger::STRING_EMPTY_PASSWORD:
@@ -356,8 +352,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "PasswordStore is not available";
case SavePasswordProgressLogger::STRING_CREATE_LOGIN_MANAGERS_METHOD:
return "PasswordManager::CreatePendingLoginManagers";
- case SavePasswordProgressLogger::STRING_OLD_NUMBER_LOGIN_MANAGERS:
- return "Number of pending login managers (before)";
case SavePasswordProgressLogger::STRING_NEW_NUMBER_LOGIN_MANAGERS:
return "Number of pending login managers (after)";
case SavePasswordProgressLogger::
@@ -377,8 +371,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Signature of form";
case SavePasswordProgressLogger::STRING_FORM_FETCHER_STATE:
return "FormFetcherImpl::state_";
- case SavePasswordProgressLogger::STRING_ADDING_SIGNATURE:
- return "Adding manager for form";
case SavePasswordProgressLogger::STRING_UNOWNED_INPUTS_VISIBLE:
return "Some control elements not associated to a form element are "
"visible";
@@ -413,18 +405,18 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Form name";
case SavePasswordProgressLogger::STRING_FIELDS:
return "Form fields";
- case SavePasswordProgressLogger::STRING_SERVER_PREDICTIONS:
- return "Server predictions";
case SavePasswordProgressLogger::STRING_FORM_VOTES:
return "Form votes";
+ case SavePasswordProgressLogger::STRING_FIRSTUSE_FORM_VOTE:
+ return "FirstUse vote";
+ case SavePasswordProgressLogger::STRING_PASSWORD_FORM_VOTE:
+ return "PasswordForm vote";
case SavePasswordProgressLogger::STRING_REUSE_FOUND:
return "Password reused from ";
case SavePasswordProgressLogger::STRING_GENERATION_DISABLED_SAVING_DISABLED:
return "Generation disabled: saving disabled";
case SavePasswordProgressLogger::STRING_GENERATION_DISABLED_NO_SYNC:
return "Generation disabled: no sync";
- case STRING_GENERATION_RENDERER_ENABLED:
- return "Generation renderer enabled";
case STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM:
return "Generation invalid PasswordForm";
case STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS:
@@ -482,6 +474,47 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "HttpAuthManager::SetObserver";
case SavePasswordProgressLogger::STRING_HTTPAUTH_ON_DETACH_OBSERVER:
return "HttpAuthManager::DetachObserver";
+ case SavePasswordProgressLogger::STRING_SHOW_ONBOARDING:
+ return "Show onboarding experience and offer to save password";
+ case STRING_LEAK_DETECTION_FINISHED:
+ return "Leak detection finished with result";
+ case STRING_LEAK_DETECTION_SIGNED_OUT_ERROR:
+ return "Leak detection failed: signed out";
+ case STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR:
+ return "Leak detection failed: can't get a token";
+ case STRING_LEAK_DETECTION_ENCRYPTION_ERROR:
+ return "Leak detection failed: encryption";
+ case STRING_LEAK_DETECTION_INVALID_SERVER_RESPONSE_ERROR:
+ return "Leak detection failed: invalid server response";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE:
+ return "Uploading password requirements vote for using lowercase letters";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE:
+ return "Uploading password requirements vote for using lowercase letters";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS:
+ return "Uploading password requirements vote for using numbers";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL:
+ return "Uploading password requirements vote for using special symbols";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIFIC_SPECIAL_SYMBOL:
+ return "Used specific special symbol";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_PASSWORD_LENGTH:
+ return "Uploading password requirements vote for password length";
+ case SavePasswordProgressLogger::
+ STRING_PASSWORD_REQUIREMENTS_VOTE_NO_PASSWORD_ATTRIBUTES:
+ return "No password requirements attributed set";
+ case STRING_SAVE_PASSWORD_HASH:
+ return "Password hash is saved";
+ case STRING_DID_NAVIGATE_MAIN_FRAME:
+ return "PasswordManager::DidNavigateMainFrame";
+ case STRING_NAVIGATION_NTP:
+ return "Navigation to New Tab page";
+ case STRING_SERVER_PREDICTIONS:
+ return "Server predictions";
case SavePasswordProgressLogger::STRING_INVALID:
return "INVALID";
// Intentionally no default: clause here -- all IDs need to get covered.
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.h b/chromium/components/autofill/core/common/save_password_progress_logger.h
index 300afcdc358..f1899def840 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.h
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.h
@@ -78,8 +78,6 @@ class SavePasswordProgressLogger {
STRING_FRAME_NOT_MAIN_FRAME,
STRING_PROVISIONALLY_SAVED_FORM_FOR_FRAME,
STRING_PROVISIONALLY_SAVE_FORM_METHOD,
- STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD,
- STRING_PROVISIONALLY_SAVE_PASSWORD_FORM,
STRING_IS_SAVING_ENABLED,
STRING_EMPTY_PASSWORD,
STRING_EXACT_MATCH,
@@ -117,7 +115,6 @@ class SavePasswordProgressLogger {
STRING_FETCH_METHOD,
STRING_NO_STORE,
STRING_CREATE_LOGIN_MANAGERS_METHOD,
- STRING_OLD_NUMBER_LOGIN_MANAGERS,
STRING_NEW_NUMBER_LOGIN_MANAGERS,
STRING_PASSWORD_MANAGEMENT_ENABLED_FOR_CURRENT_PAGE,
STRING_SHOW_LOGIN_PROMPT_METHOD,
@@ -126,7 +123,6 @@ class SavePasswordProgressLogger {
STRING_CHANGE_PASSWORD_FORM,
STRING_PROCESS_FRAME_METHOD,
STRING_FORM_SIGNATURE,
- STRING_ADDING_SIGNATURE,
STRING_FORM_FETCHER_STATE,
STRING_UNOWNED_INPUTS_VISIBLE,
STRING_ON_FILL_PASSWORD_FORM_METHOD,
@@ -144,12 +140,12 @@ class SavePasswordProgressLogger {
STRING_PASSWORD_FILLED,
STRING_FORM_NAME,
STRING_FIELDS,
- STRING_SERVER_PREDICTIONS,
STRING_FORM_VOTES,
+ STRING_FIRSTUSE_FORM_VOTE,
+ STRING_PASSWORD_FORM_VOTE,
STRING_REUSE_FOUND,
STRING_GENERATION_DISABLED_SAVING_DISABLED,
STRING_GENERATION_DISABLED_NO_SYNC,
- STRING_GENERATION_RENDERER_ENABLED,
STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM,
STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS,
STRING_GENERATION_RENDERER_NO_PASSWORD_MANAGER_ACCESS,
@@ -177,6 +173,23 @@ class SavePasswordProgressLogger {
STRING_HTTPAUTH_ON_PROMPT_USER,
STRING_HTTPAUTH_ON_SET_OBSERVER,
STRING_HTTPAUTH_ON_DETACH_OBSERVER,
+ STRING_SHOW_ONBOARDING,
+ STRING_LEAK_DETECTION_FINISHED,
+ STRING_LEAK_DETECTION_SIGNED_OUT_ERROR,
+ STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR,
+ STRING_LEAK_DETECTION_ENCRYPTION_ERROR,
+ STRING_LEAK_DETECTION_INVALID_SERVER_RESPONSE_ERROR,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIFIC_SPECIAL_SYMBOL,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_PASSWORD_LENGTH,
+ STRING_PASSWORD_REQUIREMENTS_VOTE_NO_PASSWORD_ATTRIBUTES,
+ STRING_SAVE_PASSWORD_HASH,
+ STRING_DID_NAVIGATE_MAIN_FRAME,
+ STRING_NAVIGATION_NTP,
+ STRING_SERVER_PREDICTIONS,
STRING_INVALID, // Represents a string returned in a case of an error.
STRING_MAX = STRING_INVALID
};
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.mm b/chromium/components/autofill/ios/browser/autofill_agent.mm
index fadbcb4e1fe..092c7847147 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent.mm
@@ -52,7 +52,7 @@
#include "ios/web/public/js_messaging/web_frame_util.h"
#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/navigation/navigation_context.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#import "ios/web/public/web_state/web_state_observer_bridge.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -422,6 +422,15 @@ autofillManagerFromWebState:(web::WebState*)webState
inFrame:frame
completionHandler:suggestionHandledCompletion_];
suggestionHandledCompletion_ = nil;
+ } else if (suggestion.identifier ==
+ autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS) {
+ web::WebFrame* frame =
+ GetWebFrameWithId(webState_, base::SysNSStringToUTF8(frameID));
+ autofill::AutofillManager* autofillManager =
+ [self autofillManagerFromWebState:webState_ webFrame:frame];
+ if (autofillManager) {
+ autofillManager->OnUserAcceptedCardsFromAccountOption();
+ }
} else {
NOTREACHED() << "unknown identifier " << suggestion.identifier;
}
@@ -530,6 +539,10 @@ autofillManagerFromWebState:(web::WebState*)webState
// Show "GPay branding" icon
value = base::SysUTF16ToNSString(popup_suggestion.value);
has_gpay_branding = true;
+ } else if (popup_suggestion.frontend_id ==
+ autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS) {
+ // Show opt-in for showing cards from account.
+ value = base::SysUTF16ToNSString(popup_suggestion.value);
}
if (!value)
diff --git a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
index 03ddeb89eee..7a83d99dfce 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -22,7 +22,7 @@
#import "ios/web/public/test/fakes/fake_web_frames_manager.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
#import "ios/web/public/test/fakes/test_web_state.h"
-#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "ios/web/public/test/web_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
@@ -37,6 +37,7 @@
using autofill::POPUP_ITEM_ID_CLEAR_FORM;
using autofill::POPUP_ITEM_ID_GOOGLE_PAY_BRANDING;
+using autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS;
using base::test::ios::WaitUntilCondition;
// Subclass of web::FakeWebFrame that allow to set a callback before any
@@ -104,7 +105,7 @@ class AutofillAgentTests : public PlatformTest {
webState:&test_web_state_];
}
- web::TestWebThreadBundle thread_bundle_;
+ web::WebTaskEnvironment task_environment_;
web::TestBrowserState test_browser_state_;
web::TestWebState test_web_state_;
web::FakeWebFrame* fake_main_frame_ = nullptr;
@@ -283,6 +284,46 @@ TEST_F(AutofillAgentTests,
EXPECT_FALSE(completion_handler_success);
}
+// Tests that "Show credit cards from account" opt-in is shown.
+TEST_F(AutofillAgentTests, onSuggestionsReady_ShowAccountCards) {
+ __block NSArray<FormSuggestion*>* completion_handler_suggestions = nil;
+ __block BOOL completion_handler_called = NO;
+
+ // Make the suggestions available to AutofillAgent.
+ std::vector<autofill::Suggestion> suggestions;
+ suggestions.push_back(
+ autofill::Suggestion("", "", "", POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS));
+ [autofill_agent_
+ showAutofillPopup:suggestions
+ popupDelegate:base::WeakPtr<autofill::AutofillPopupDelegate>()];
+
+ // Retrieves the suggestions.
+ auto completionHandler = ^(NSArray<FormSuggestion*>* suggestions,
+ id<FormSuggestionProvider> delegate) {
+ completion_handler_suggestions = [suggestions copy];
+ completion_handler_called = YES;
+ };
+ [autofill_agent_ retrieveSuggestionsForForm:@"form"
+ fieldIdentifier:@"address"
+ fieldType:@"text"
+ type:@"focus"
+ typedValue:@""
+ frameID:@"frameID"
+ webState:&test_web_state_
+ completionHandler:completionHandler];
+ test_web_state_.WasShown();
+
+ // Wait until the expected handler is called.
+ WaitUntilCondition(^bool() {
+ return completion_handler_called;
+ });
+
+ // "Show credit cards from account" should be the only suggestion.
+ EXPECT_EQ(1U, completion_handler_suggestions.count);
+ EXPECT_EQ(POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS,
+ completion_handler_suggestions[0].identifier);
+}
+
// Tests that when Autofill suggestions are made available to AutofillAgent
// "Clear Form" is moved to the start of the list and the order of other
// suggestions remains unchanged.
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.h b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
index 326dcaaa2b7..9783f364b46 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
@@ -41,7 +41,6 @@ class AutofillDriverIOS : public AutofillDriver {
bool IsIncognito() const override;
bool IsInMainFrame() const override;
ui::AXTreeID GetAxTreeId() const override;
- net::URLRequestContextGetter* GetURLRequestContext() override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
bool RendererIsAvailable() override;
void SendFormDataToRenderer(int query_id,
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
index 784c028812c..7c18d5f3b6d 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -11,7 +11,7 @@
#import "ios/web/common/origin_util.h"
#include "ios/web/public/browser_state.h"
#include "ios/web/public/js_messaging/web_frame_util.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "ui/accessibility/ax_tree_id.h"
@@ -77,10 +77,6 @@ ui::AXTreeID AutofillDriverIOS::GetAxTreeId() const {
return ui::AXTreeIDUnknown();
}
-net::URLRequestContextGetter* AutofillDriverIOS::GetURLRequestContext() {
- return web_state_->GetBrowserState()->GetRequestContext();
-}
-
scoped_refptr<network::SharedURLLoaderFactory>
AutofillDriverIOS::GetURLLoaderFactory() {
return base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
index cc3c6d6e7a4..5260665f970 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
@@ -4,8 +4,6 @@
#include "components/autofill/ios/browser/autofill_driver_ios_webframe.h"
-#import "ios/web/public/web_state/web_state.h"
-
namespace autofill {
// static
diff --git a/chromium/components/autofill/ios/browser/autofill_util.h b/chromium/components/autofill/ios/browser/autofill_util.h
index 9e427ead281..8e8e6dabeb6 100644
--- a/chromium/components/autofill/ios/browser/autofill_util.h
+++ b/chromium/components/autofill/ios/browser/autofill_util.h
@@ -8,10 +8,17 @@
#include <vector>
#import "ios/web/public/js_messaging/web_frame.h"
-#import "ios/web/public/web_state/web_state.h"
+@class CRWJSInjectionReceiver;
class GURL;
+namespace base {
+class DictionaryValue;
+}
+namespace web {
+class WebState;
+}
+
namespace autofill {
struct FormData;
diff --git a/chromium/components/autofill/ios/browser/autofill_util.mm b/chromium/components/autofill/ios/browser/autofill_util.mm
index a17223e1408..862e8778a64 100644
--- a/chromium/components/autofill/ios/browser/autofill_util.mm
+++ b/chromium/components/autofill/ios/browser/autofill_util.mm
@@ -22,6 +22,7 @@
#import "ios/web/public/navigation/navigation_item.h"
#import "ios/web/public/navigation/navigation_manager.h"
#include "ios/web/public/security/ssl_status.h"
+#import "ios/web/public/web_state.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -44,8 +45,7 @@ bool IsContextSecureForWebState(web::WebState* web_state) {
const web::SSLStatus& ssl = nav_item->GetSSL();
return nav_item->GetURL().SchemeIsCryptographic() && ssl.certificate &&
- (!net::IsCertStatusError(ssl.cert_status) ||
- net::IsCertStatusMinorError(ssl.cert_status));
+ !net::IsCertStatusError(ssl.cert_status);
}
std::unique_ptr<base::Value> ParseJson(NSString* json_string) {
diff --git a/chromium/components/autofill/ios/browser/fake_autofill_agent.mm b/chromium/components/autofill/ios/browser/fake_autofill_agent.mm
index 2f5f8cb5707..1f5793c096a 100644
--- a/chromium/components/autofill/ios/browser/fake_autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/fake_autofill_agent.mm
@@ -69,7 +69,7 @@
webState:(web::WebState*)webState
completionHandler:
(SuggestionsAvailableCompletion)completion {
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
NSString* key = [self keyForFormName:formName
fieldIdentifier:fieldIdentifier
@@ -86,13 +86,12 @@
frameID:(NSString*)frameID
webState:(web::WebState*)webState
completionHandler:(SuggestionsReadyCompletion)completion {
- base::PostTaskWithTraits(
- FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
- NSString* key = [self keyForFormName:formName
- fieldIdentifier:fieldIdentifier
- frameID:frameID];
- completion(_suggestionsByFormAndFieldName[key], self);
- }));
+ base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+ NSString* key = [self keyForFormName:formName
+ fieldIdentifier:fieldIdentifier
+ frameID:frameID];
+ completion(_suggestionsByFormAndFieldName[key], self);
+ }));
}
- (void)didSelectSuggestion:(FormSuggestion*)suggestion
@@ -100,14 +99,13 @@
fieldIdentifier:(NSString*)fieldIdentifier
frameID:(NSString*)frameID
completionHandler:(SuggestionHandledCompletion)completion {
- base::PostTaskWithTraits(
- FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
- NSString* key = [self keyForFormName:formName
- fieldIdentifier:fieldIdentifier
- frameID:frameID];
- _selectedSuggestionByFormAndFieldName[key] = suggestion;
- completion();
- }));
+ base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+ NSString* key = [self keyForFormName:formName
+ fieldIdentifier:fieldIdentifier
+ frameID:frameID];
+ _selectedSuggestionByFormAndFieldName[key] = suggestion;
+ completion();
+ }));
}
#pragma mark - Private Methods
diff --git a/chromium/components/autofill/ios/browser/fake_js_autofill_manager.mm b/chromium/components/autofill/ios/browser/fake_js_autofill_manager.mm
index daff0e61be0..fa5c6e04bad 100644
--- a/chromium/components/autofill/ios/browser/fake_js_autofill_manager.mm
+++ b/chromium/components/autofill/ios/browser/fake_js_autofill_manager.mm
@@ -25,16 +25,14 @@
fieldIdentifier:(NSString*)fieldIdentifier
inFrame:(web::WebFrame*)frame
completionHandler:(ProceduralBlock)completionHandler {
- base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
- _lastClearedFormName = [formName copy];
- _lastClearedFieldIdentifier =
- [fieldIdentifier copy];
- _lastClearedFrameIdentifier =
- frame ? base::SysUTF8ToNSString(
- frame->GetFrameId())
- : nil;
- completionHandler();
- }));
+ base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+ _lastClearedFormName = [formName copy];
+ _lastClearedFieldIdentifier = [fieldIdentifier copy];
+ _lastClearedFrameIdentifier =
+ frame ? base::SysUTF8ToNSString(frame->GetFrameId())
+ : nil;
+ completionHandler();
+ }));
}
@end
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
index 7b2d7bab679..dc40fa6199f 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/values.h"
-#import "ios/web/public/web_state/ui/crw_web_view_proxy.h"
#include "ios/web/public/web_state/web_state_observer.h"
#import "ios/web/public/web_state/web_state_user_data.h"
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm
index 2110fc1574d..e8b7601f086 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm
@@ -11,6 +11,7 @@
#include "components/autofill/ios/form_util/form_activity_observer.h"
#include "components/autofill/ios/form_util/form_activity_params.h"
#include "ios/web/public/js_messaging/web_frame.h"
+#import "ios/web/public/ui/crw_web_view_proxy.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
diff --git a/chromium/components/autofill/ios/form_util/test_form_activity_tab_helper.mm b/chromium/components/autofill/ios/form_util/test_form_activity_tab_helper.mm
index 2cb1d7c3429..1414c396b67 100644
--- a/chromium/components/autofill/ios/form_util/test_form_activity_tab_helper.mm
+++ b/chromium/components/autofill/ios/form_util/test_form_activity_tab_helper.mm
@@ -8,7 +8,6 @@
#include "components/autofill/ios/form_util/form_activity_observer.h"
#include "components/autofill/ios/form_util/form_activity_params.h"
#include "components/autofill/ios/form_util/form_activity_tab_helper.h"
-#import "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
diff --git a/chromium/components/autofill_assistant/OWNERS b/chromium/components/autofill_assistant/OWNERS
index 931f689fa18..30097619a2b 100644
--- a/chromium/components/autofill_assistant/OWNERS
+++ b/chromium/components/autofill_assistant/OWNERS
@@ -2,6 +2,7 @@
arbesser@google.com
gogerald@chromium.org
jdemeulenaere@chromium.org
+marianfe@google.com
mcarlen@chromium.org
rouslan@chromium.org
szermatt@chromium.org
diff --git a/chromium/components/autofill_assistant/browser/BUILD.gn b/chromium/components/autofill_assistant/browser/BUILD.gn
index f14503f8667..9ddc5a1b583 100644
--- a/chromium/components/autofill_assistant/browser/BUILD.gn
+++ b/chromium/components/autofill_assistant/browser/BUILD.gn
@@ -23,7 +23,7 @@ java_cpp_enum("autofill_assistant_enums_java") {
sources = [
"metrics.h",
"overlay_state.h",
- "payment_request.h",
+ "user_data.h",
"viewport_mode.h",
]
}
@@ -38,14 +38,14 @@ jumbo_static_library("browser") {
"actions/autofill_action.h",
"actions/click_action.cc",
"actions/click_action.h",
+ "actions/collect_user_data_action.cc",
+ "actions/collect_user_data_action.h",
"actions/configure_bottom_sheet_action.cc",
"actions/configure_bottom_sheet_action.h",
"actions/expect_navigation_action.cc",
"actions/expect_navigation_action.h",
"actions/focus_element_action.cc",
"actions/focus_element_action.h",
- "actions/get_payment_information_action.cc",
- "actions/get_payment_information_action.h",
"actions/highlight_element_action.cc",
"actions/highlight_element_action.h",
"actions/navigate_action.cc",
@@ -114,8 +114,6 @@ jumbo_static_library("browser") {
"metrics.cc",
"metrics.h",
"overlay_state.h",
- "payment_request.cc",
- "payment_request.h",
"protocol_utils.cc",
"protocol_utils.h",
"rectf.cc",
@@ -148,9 +146,22 @@ jumbo_static_library("browser") {
"ui_delegate.h",
"user_action.cc",
"user_action.h",
+ "user_data.cc",
+ "user_data.h",
"viewport_mode.h",
- "web_controller.cc",
- "web_controller.h",
+ "web/element_finder.cc",
+ "web/element_finder.h",
+ "web/element_position_getter.cc",
+ "web/element_position_getter.h",
+ "web/web_controller.cc",
+ "web/web_controller.h",
+ "web/web_controller_util.cc",
+ "web/web_controller_util.h",
+ "web/web_controller_worker.h",
+ "website_login_fetcher.cc",
+ "website_login_fetcher.h",
+ "website_login_fetcher_impl.cc",
+ "website_login_fetcher_impl.h",
]
deps = [
@@ -160,6 +171,7 @@ jumbo_static_library("browser") {
"//components/autofill/core/browser",
"//components/autofill/core/common",
"//components/autofill_assistant/browser/devtools",
+ "//components/password_manager/core/browser:browser",
"//components/signin/public/identity_manager",
"//components/strings:components_strings_grit",
"//components/version_info",
@@ -174,25 +186,31 @@ source_set("unit_tests") {
testonly = true
sources = [
"actions/autofill_action_unittest.cc",
+ "actions/collect_user_data_action_unittest.cc",
"actions/configure_bottom_sheet_action_unittest.cc",
"actions/mock_action_delegate.cc",
"actions/mock_action_delegate.h",
"actions/popup_message_action_unittest.cc",
"actions/prompt_action_unittest.cc",
+ "actions/set_form_field_value_action_unittest.cc",
+ "actions/show_details_action_unittest.cc",
"actions/wait_for_document_action_unittest.cc",
"actions/wait_for_dom_action_unittest.cc",
"batch_element_checker_unittest.cc",
"controller_unittest.cc",
+ "details_unittest.cc",
"element_area_unittest.cc",
"element_precondition_unittest.cc",
"fake_script_executor_delegate.cc",
"fake_script_executor_delegate.h",
"mock_controller_observer.cc",
"mock_controller_observer.h",
+ "mock_personal_data_manager.cc",
+ "mock_personal_data_manager.h",
"mock_service.cc",
"mock_service.h",
- "mock_web_controller.cc",
- "mock_web_controller.h",
+ "mock_website_login_fetcher.cc",
+ "mock_website_login_fetcher.h",
"protocol_utils_unittest.cc",
"retry_timer_unittest.cc",
"script_executor_unittest.cc",
@@ -201,6 +219,8 @@ source_set("unit_tests") {
"selector_unittest.cc",
"string_conversions_util_unittest.cc",
"trigger_context_unittest.cc",
+ "web/mock_web_controller.cc",
+ "web/mock_web_controller.h",
]
deps = [
@@ -209,6 +229,7 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/autofill/core/browser:test_support",
+ "//components/strings:components_strings_grit",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/autofill_assistant/browser/DEPS b/chromium/components/autofill_assistant/browser/DEPS
index 514714e5892..bc88f173919 100644
--- a/chromium/components/autofill_assistant/browser/DEPS
+++ b/chromium/components/autofill_assistant/browser/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+chrome/android/features/autofill_assistant/test_support_jni_headers",
"+components/autofill",
+ "+components/password_manager/core/browser",
"+components/version_info/version_info.h",
"+content/public/browser",
"+content/public/test",
diff --git a/chromium/components/autofill_assistant/browser/actions/action.cc b/chromium/components/autofill_assistant/browser/actions/action.cc
index 8f3c3a69c44..e5e644b5ac7 100644
--- a/chromium/components/autofill_assistant/browser/actions/action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/action.cc
@@ -101,8 +101,8 @@ std::ostream& operator<<(std::ostream& out,
case ActionProto::ActionInfoCase::kStop:
out << "Stop";
break;
- case ActionProto::ActionInfoCase::kGetPaymentInformation:
- out << "GetPaymentInformation";
+ case ActionProto::ActionInfoCase::kCollectUserData:
+ out << "CollectUserData";
break;
case ActionProto::ActionInfoCase::kSetAttribute:
out << "SetAttribute";
diff --git a/chromium/components/autofill_assistant/browser/actions/action_delegate.h b/chromium/components/autofill_assistant/browser/actions/action_delegate.h
index e532ac116e8..74360d76adb 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/chromium/components/autofill_assistant/browser/actions/action_delegate.h
@@ -36,8 +36,10 @@ namespace autofill_assistant {
class ClientMemory;
class ClientStatus;
struct ClientSettings;
-struct PaymentRequestOptions;
+struct UserData;
+struct CollectUserDataOptions;
class UserAction;
+class WebsiteLoginFetcher;
// Action delegate called when processing actions.
class ActionDelegate {
@@ -106,10 +108,10 @@ class ActionDelegate {
// Have the UI leave the prompt state and go back to its previous state.
virtual void CancelPrompt() = 0;
- // Asks the user to provide the data used by UseAddressAction and
- // UseCreditCardAction.
- virtual void GetPaymentInformation(
- std::unique_ptr<PaymentRequestOptions> options) = 0;
+ // Asks the user to provide the requested user data.
+ virtual void CollectUserData(
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) = 0;
using GetFullCardCallback =
base::OnceCallback<void(std::unique_ptr<autofill::CreditCard> card,
@@ -254,9 +256,16 @@ class ActionDelegate {
// Get current personal data manager.
virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0;
+ // Get current login fetcher.
+ virtual WebsiteLoginFetcher* GetWebsiteLoginFetcher() = 0;
+
// Get associated web contents.
virtual content::WebContents* GetWebContents() = 0;
+ // Returns the e-mail address that corresponds to the access token or an empty
+ // string.
+ virtual std::string GetAccountEmailAddress() = 0;
+
// Sets or updates contextual information.
// Passing nullptr clears the contextual information.
virtual void SetDetails(std::unique_ptr<Details> details) = 0;
diff --git a/chromium/components/autofill_assistant/browser/actions/autofill_action.cc b/chromium/components/autofill_assistant/browser/actions/autofill_action.cc
index 004702ea6c5..4f67d3fda67 100644
--- a/chromium/components/autofill_assistant/browser/actions/autofill_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/autofill_action.cc
@@ -24,7 +24,7 @@ namespace autofill_assistant {
AutofillAction::AutofillAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
if (proto.has_use_address()) {
is_autofill_card_ = false;
prompt_ = proto.use_address().prompt();
diff --git a/chromium/components/autofill_assistant/browser/actions/autofill_action.h b/chromium/components/autofill_assistant/browser/actions/autofill_action.h
index 434ce7eeaad..327a55a1c69 100644
--- a/chromium/components/autofill_assistant/browser/actions/autofill_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/autofill_action.h
@@ -149,7 +149,7 @@ class AutofillAction : public Action {
std::unique_ptr<BatchElementChecker> batch_element_checker_;
ProcessActionCallback process_action_callback_;
- base::WeakPtrFactory<AutofillAction> weak_ptr_factory_;
+ base::WeakPtrFactory<AutofillAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AutofillAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/autofill_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
index e59863adfdc..e2ad48920ba 100644
--- a/chromium/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
@@ -6,20 +6,15 @@
#include <utility>
-#include "base/bind.h"
#include "base/guid.h"
-#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_callback_support.h"
-#include "build/build_config.h"
+#include "base/test/mock_callback.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
-#include "components/autofill_assistant/browser/client_memory.h"
-#include "components/autofill_assistant/browser/client_status.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
-#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/mock_personal_data_manager.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -31,94 +26,32 @@ using ::testing::Eq;
using ::testing::Expectation;
using ::testing::InSequence;
using ::testing::Invoke;
-using ::testing::IsNull;
-using ::testing::Not;
using ::testing::NotNull;
using ::testing::Return;
-using ::testing::StrNe;
-
-class MockPersonalDataManager : public autofill::PersonalDataManager {
- public:
- MockPersonalDataManager() : PersonalDataManager("en-US") {}
- ~MockPersonalDataManager() override {}
-
- // PersonalDataManager:
- std::string SaveImportedProfile(
- const autofill::AutofillProfile& profile) override {
- std::vector<autofill::AutofillProfile> profiles;
- std::string merged_guid =
- MergeProfile(profile, &profiles_, "en-US", &profiles);
- if (merged_guid == profile.guid())
- profiles_.push_back(std::make_unique<autofill::AutofillProfile>(profile));
- return merged_guid;
- }
-
- autofill::AutofillProfile* GetProfileByGUID(
- const std::string& guid) override {
- autofill::AutofillProfile* result = nullptr;
- for (const auto& profile : profiles_) {
- if (profile->guid() != guid)
- continue;
- result = profile.get();
- break;
- }
-
- return result;
- }
-
- private:
- std::vector<std::unique_ptr<autofill::AutofillProfile>> profiles_;
-
- DISALLOW_COPY_AND_ASSIGN(MockPersonalDataManager);
-};
-
-// A callback that expects to be called immediately.
-//
-// This relies on mocked methods calling their callbacks immediately (which is
-// the case in this test).
-class DirectCallback {
- public:
- DirectCallback() : was_run_(false), result_(nullptr) {}
-
- // Returns a base::OnceCallback. The current instance must exist until
- // GetResultOrDie is called.
- base::OnceCallback<void(std::unique_ptr<ProcessedActionProto>)> Get() {
- return base::BindOnce(&DirectCallback::Run, base::Unretained(this));
- }
-
- ProcessedActionProto* GetResultOrDie() {
- CHECK(was_run_);
- return result_.get();
- }
-
- private:
- void Run(std::unique_ptr<ProcessedActionProto> result) {
- was_run_ = true;
- result_ = std::move(result);
- }
-
- bool was_run_;
- std::unique_ptr<ProcessedActionProto> result_;
-};
+using ::testing::SaveArgPointee;
class AutofillActionTest : public testing::Test {
public:
void SetUp() override {
+ // Build two identical autofill profiles. One for the memory, one for the
+ // mock.
auto autofill_profile = std::make_unique<autofill::AutofillProfile>(
base::GenerateGUID(), autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(autofill_profile.get(), kFirstName, "",
kLastName, kEmail, "", "", "", "", "", "",
"", "");
- personal_data_manager_ = std::make_unique<MockPersonalDataManager>();
- personal_data_manager_->SaveImportedProfile(*autofill_profile);
-
+ autofill::test::SetProfileInfo(&autofill_profile_, kFirstName, "",
+ kLastName, kEmail, "", "", "", "", "", "",
+ "", "");
client_memory_.set_selected_address(kAddressName,
std::move(autofill_profile));
+ ON_CALL(mock_personal_data_manager_, GetProfileByGUID)
+ .WillByDefault(Return(&autofill_profile_));
ON_CALL(mock_action_delegate_, GetClientMemory)
.WillByDefault(Return(&client_memory_));
ON_CALL(mock_action_delegate_, GetPersonalDataManager)
- .WillByDefault(Return(personal_data_manager_.get()));
+ .WillByDefault(Return(&mock_personal_data_manager_));
ON_CALL(mock_action_delegate_, RunElementChecks)
.WillByDefault(Invoke([this](BatchElementChecker* checker) {
checker->Run(&mock_web_controller_);
@@ -179,17 +112,19 @@ class AutofillActionTest : public testing::Test {
ProcessedActionStatusProto ProcessAction(const ActionProto& action_proto) {
AutofillAction action(&mock_action_delegate_, action_proto);
- // We can use DirectCallback given that methods in ActionDelegate are mocked
- // and return directly.
- DirectCallback callback;
- action.ProcessAction(callback.Get());
- return callback.GetResultOrDie()->status();
+ ProcessedActionProto capture;
+ EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&capture));
+ action.ProcessAction(callback_.Get());
+ return capture.status();
}
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ MockPersonalDataManager mock_personal_data_manager_;
MockActionDelegate mock_action_delegate_;
MockWebController mock_web_controller_;
ClientMemory client_memory_;
- std::unique_ptr<autofill::PersonalDataManager> personal_data_manager_;
+
+ autofill::AutofillProfile autofill_profile_;
};
#if !defined(OS_ANDROID)
@@ -229,16 +164,14 @@ TEST_F(AutofillActionTest, PreconditionFailedPopulatesUnexpectedErrorInfo) {
AutofillAction action(&mock_action_delegate_, action_proto);
- // We can use DirectCallback given that methods in ActionDelegate are mocked
- // and return directly.
- DirectCallback callback;
- action.ProcessAction(callback.Get());
+ ProcessedActionProto processed_action;
+ EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&processed_action));
+ action.ProcessAction(callback_.Get());
- auto* processed_action = callback.GetResultOrDie();
EXPECT_EQ(ProcessedActionStatusProto::PRECONDITION_FAILED,
- processed_action->status());
+ processed_action.status());
const auto& error_info =
- processed_action->status_details().autofill_error_info();
+ processed_action.status_details().autofill_error_info();
EXPECT_EQ(base::JoinString({kAddressName, "one_more"}, ","),
error_info.client_memory_address_key_names());
EXPECT_EQ(kAddressName, error_info.address_key_requested());
diff --git a/chromium/components/autofill_assistant/browser/actions/click_action.cc b/chromium/components/autofill_assistant/browser/actions/click_action.cc
index 299b9d9dec3..a26f48cc922 100644
--- a/chromium/components/autofill_assistant/browser/actions/click_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/click_action.cc
@@ -14,7 +14,7 @@
namespace autofill_assistant {
ClickAction::ClickAction(ActionDelegate* delegate, const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_click());
switch (proto.click().click_type()) {
case ClickProto_ClickType_NOT_SET: // default: TAP
diff --git a/chromium/components/autofill_assistant/browser/actions/click_action.h b/chromium/components/autofill_assistant/browser/actions/click_action.h
index 3c1e96e86ea..5c2b6afc2fe 100644
--- a/chromium/components/autofill_assistant/browser/actions/click_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/click_action.h
@@ -33,7 +33,7 @@ class ClickAction : public Action {
void OnClick(ProcessActionCallback callback, const ClientStatus& status);
ClickType click_type_;
- base::WeakPtrFactory<ClickAction> weak_ptr_factory_;
+ base::WeakPtrFactory<ClickAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ClickAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc
new file mode 100644
index 00000000000..5bf0d0be09f
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc
@@ -0,0 +1,609 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/collect_user_data_action.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/android/locale_utils.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/geo/address_i18n.h"
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
+#include "components/autofill_assistant/browser/client_memory.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/metrics.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/website_login_fetcher_impl.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
+#include "third_party/libaddressinput/chromium/addressinput_util.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+using autofill_assistant::CollectUserDataOptions;
+using autofill_assistant::TermsAndConditionsState;
+bool IsCompleteContact(
+ const autofill::AutofillProfile* profile,
+ const CollectUserDataOptions& collect_user_data_options) {
+ if (!collect_user_data_options.request_payer_name &&
+ !collect_user_data_options.request_payer_email &&
+ !collect_user_data_options.request_payer_phone) {
+ return true;
+ }
+
+ if (!profile) {
+ return false;
+ }
+
+ if (collect_user_data_options.request_payer_name &&
+ profile->GetRawInfo(autofill::NAME_FULL).empty()) {
+ return false;
+ }
+
+ if (collect_user_data_options.request_payer_email &&
+ profile->GetRawInfo(autofill::EMAIL_ADDRESS).empty()) {
+ return false;
+ }
+
+ if (collect_user_data_options.request_payer_phone &&
+ profile->GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER).empty()) {
+ return false;
+ }
+ return true;
+}
+
+bool IsCompleteAddress(const autofill::AutofillProfile* profile,
+ bool require_postal_code) {
+ if (!profile) {
+ return false;
+ }
+ auto address_data = autofill::i18n::CreateAddressDataFromAutofillProfile(
+ *profile, base::android::GetDefaultLocaleString());
+ if (!autofill::addressinput::HasAllRequiredFields(*address_data)) {
+ return false;
+ }
+
+ if (require_postal_code && address_data->postal_code.empty()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool IsCompleteBillingAddress(
+ const autofill::AutofillProfile* profile,
+ const CollectUserDataOptions& collect_user_data_options) {
+ return !collect_user_data_options.request_payment_method ||
+ IsCompleteAddress(
+ profile, collect_user_data_options.require_billing_postal_code);
+}
+
+bool IsCompleteShippingAddress(
+ const autofill::AutofillProfile* profile,
+ const CollectUserDataOptions& collect_user_data_options) {
+ return !collect_user_data_options.request_shipping ||
+ IsCompleteAddress(profile, /* require_postal_code = */ false);
+}
+
+bool IsCompleteCreditCard(
+ autofill::PersonalDataManager* personal_data_manager,
+ const autofill::CreditCard* credit_card,
+ const CollectUserDataOptions& collect_user_data_options) {
+ if (!collect_user_data_options.request_payment_method) {
+ return true;
+ }
+
+ if (!credit_card) {
+ return false;
+ }
+
+ if (credit_card->record_type() != autofill::CreditCard::MASKED_SERVER_CARD &&
+ !credit_card->HasValidCardNumber()) {
+ // Can't check validity of masked server card numbers because they are
+ // incomplete until decrypted.
+ return false;
+ }
+
+ if (!credit_card->HasValidExpirationDate() ||
+ credit_card->billing_address_id().empty()) {
+ return false;
+ }
+
+ auto* address_profile = personal_data_manager->GetProfileByGUID(
+ credit_card->billing_address_id());
+ if (!IsCompleteBillingAddress(address_profile, collect_user_data_options)) {
+ return false;
+ }
+
+ std::string basic_card_network =
+ autofill::data_util::GetPaymentRequestData(credit_card->network())
+ .basic_card_issuer_network;
+ if (!collect_user_data_options.supported_basic_card_networks.empty() &&
+ std::find(collect_user_data_options.supported_basic_card_networks.begin(),
+ collect_user_data_options.supported_basic_card_networks.end(),
+ basic_card_network) ==
+ collect_user_data_options.supported_basic_card_networks.end()) {
+ return false;
+ }
+ return true;
+}
+
+bool IsValidLoginChoice(
+ const std::string& choice_identifier,
+ const CollectUserDataOptions& collect_user_data_options) {
+ return !collect_user_data_options.request_login_choice ||
+ !choice_identifier.empty();
+}
+
+bool IsValidTermsChoice(
+ TermsAndConditionsState terms_state,
+ const CollectUserDataOptions& collect_user_data_options) {
+ return collect_user_data_options.accept_terms_and_conditions_text.empty() ||
+ terms_state != TermsAndConditionsState::NOT_SELECTED;
+}
+
+} // namespace
+
+namespace autofill_assistant {
+
+CollectUserDataAction::LoginDetails::LoginDetails(
+ bool _choose_automatically_if_no_other_options,
+ const std::string& _payload,
+ const WebsiteLoginFetcher::Login& _login)
+ : choose_automatically_if_no_other_options(
+ _choose_automatically_if_no_other_options),
+ payload(_payload),
+ login(_login) {}
+
+CollectUserDataAction::LoginDetails::LoginDetails(
+ bool _choose_automatically_if_no_other_options,
+ const std::string& _payload)
+ : choose_automatically_if_no_other_options(
+ _choose_automatically_if_no_other_options),
+ payload(_payload) {}
+
+CollectUserDataAction::LoginDetails::~LoginDetails() = default;
+
+CollectUserDataAction::CollectUserDataAction(ActionDelegate* delegate,
+ const ActionProto& proto)
+ : Action(delegate, proto) {
+ DCHECK(proto_.has_collect_user_data());
+}
+
+CollectUserDataAction::~CollectUserDataAction() {
+ delegate_->GetPersonalDataManager()->RemoveObserver(this);
+
+ // Report UMA histograms.
+ if (shown_to_user_) {
+ Metrics::RecordPaymentRequestPrefilledSuccess(initially_prefilled,
+ action_successful_);
+ Metrics::RecordPaymentRequestAutofillChanged(personal_data_changed_,
+ action_successful_);
+ Metrics::RecordPaymentRequestMandatoryPostalCode(
+ proto_.collect_user_data().require_billing_postal_code(),
+ initial_card_has_billing_postal_code_, action_successful_);
+ }
+}
+
+void CollectUserDataAction::InternalProcessAction(
+ ProcessActionCallback callback) {
+ callback_ = std::move(callback);
+ auto collect_user_data_options = CreateOptionsFromProto();
+ if (!collect_user_data_options) {
+ EndAction(ClientStatus(INVALID_ACTION));
+ return;
+ }
+
+ // If Chrome password manager logins are requested, we need to asynchronously
+ // obtain them before showing the UI.
+ auto collect_user_data = proto_.collect_user_data();
+ auto password_manager_option = std::find_if(
+ collect_user_data.login_details().login_options().begin(),
+ collect_user_data.login_details().login_options().end(),
+ [&](const LoginDetailsProto::LoginOptionProto& option) {
+ return option.type_case() ==
+ LoginDetailsProto::LoginOptionProto::kPasswordManager;
+ });
+ bool requests_pwm_logins =
+ password_manager_option !=
+ collect_user_data.login_details().login_options().end();
+
+ collect_user_data_options->confirm_callback = base::BindOnce(
+ &CollectUserDataAction::OnGetUserData, weak_ptr_factory_.GetWeakPtr(),
+ std::move(collect_user_data));
+ collect_user_data_options->additional_actions_callback =
+ base::BindOnce(&CollectUserDataAction::OnAdditionalActionTriggered,
+ weak_ptr_factory_.GetWeakPtr());
+ collect_user_data_options->terms_link_callback =
+ base::BindOnce(&CollectUserDataAction::OnTermsAndConditionsLinkClicked,
+ weak_ptr_factory_.GetWeakPtr());
+ if (requests_pwm_logins) {
+ delegate_->GetWebsiteLoginFetcher()->GetLoginsForUrl(
+ delegate_->GetWebContents()->GetLastCommittedURL(),
+ base::BindOnce(&CollectUserDataAction::OnGetLogins,
+ weak_ptr_factory_.GetWeakPtr(), *password_manager_option,
+ std::move(collect_user_data_options)));
+ } else {
+ ShowToUser(std::move(collect_user_data_options));
+ }
+}
+
+void CollectUserDataAction::EndAction(const ClientStatus& status) {
+ action_successful_ = status.ok();
+ UpdateProcessedAction(status);
+ std::move(callback_).Run(std::move(processed_action_proto_));
+}
+
+void CollectUserDataAction::OnGetLogins(
+ const LoginDetailsProto::LoginOptionProto& login_option,
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::vector<WebsiteLoginFetcher::Login> logins) {
+ for (const auto& login : logins) {
+ LoginChoice choice = {
+ base::NumberToString(collect_user_data_options->login_choices.size()),
+ login.username, login_option.preselection_priority()};
+ collect_user_data_options->login_choices.emplace_back(std::move(choice));
+ login_details_map_.emplace(
+ choice.identifier,
+ std::make_unique<LoginDetails>(
+ login_option.choose_automatically_if_no_other_options(),
+ login_option.payload(), login));
+ }
+ ShowToUser(std::move(collect_user_data_options));
+}
+
+void CollectUserDataAction::ShowToUser(
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options) {
+ // Create and set initial state.
+ auto user_data = std::make_unique<UserData>();
+ auto collect_user_data = proto_.collect_user_data();
+ switch (collect_user_data.terms_and_conditions_state()) {
+ case CollectUserDataProto::NOT_SELECTED:
+ user_data->terms_and_conditions = NOT_SELECTED;
+ break;
+ case CollectUserDataProto::ACCEPTED:
+ user_data->terms_and_conditions = ACCEPTED;
+ break;
+ case CollectUserDataProto::REVIEW_REQUIRED:
+ user_data->terms_and_conditions = REQUIRES_REVIEW;
+ break;
+ }
+
+ if (collect_user_data_options->request_login_choice &&
+ collect_user_data_options->login_choices.empty()) {
+ EndAction(ClientStatus(COLLECT_USER_DATA_ERROR));
+ return;
+ }
+
+ // Special case: if the only available login option has
+ // |choose_automatically_if_no_other_options=true|, the section will not be
+ // shown.
+ bool only_login_requested =
+ collect_user_data_options->request_login_choice &&
+ !collect_user_data_options->request_payer_name &&
+ !collect_user_data_options->request_payer_email &&
+ !collect_user_data_options->request_payer_phone &&
+ !collect_user_data_options->request_shipping &&
+ !collect_user_data_options->request_payment_method &&
+ !collect_user_data.request_terms_and_conditions();
+
+ if (collect_user_data_options->login_choices.size() == 1 &&
+ login_details_map_
+ .at(collect_user_data_options->login_choices.at(0).identifier)
+ ->choose_automatically_if_no_other_options) {
+ collect_user_data_options->request_login_choice = false;
+ user_data->login_choice_identifier.assign(
+ collect_user_data_options->login_choices[0].identifier);
+
+ // If only the login section is requested and the choice has already been
+ // made implicitly, the entire UI will not be shown and the action will
+ // complete immediately.
+ if (only_login_requested) {
+ user_data->succeed = true;
+ std::move(collect_user_data_options->confirm_callback)
+ .Run(std::move(user_data));
+ return;
+ }
+ }
+
+ // Gather info for UMA histograms.
+ if (!shown_to_user_) {
+ shown_to_user_ = true;
+ initially_prefilled = CheckInitialAutofillDataComplete(
+ delegate_->GetPersonalDataManager(), *collect_user_data_options);
+ delegate_->GetPersonalDataManager()->AddObserver(this);
+ }
+
+ if (collect_user_data.has_prompt()) {
+ delegate_->SetStatusMessage(collect_user_data.prompt());
+ }
+ delegate_->CollectUserData(std::move(collect_user_data_options),
+ std::move(user_data));
+}
+
+void CollectUserDataAction::OnGetUserData(
+ const CollectUserDataProto& collect_user_data,
+ std::unique_ptr<UserData> user_data) {
+ if (!callback_)
+ return;
+
+ bool succeed = user_data->succeed;
+ if (succeed) {
+ if (collect_user_data.request_payment_method()) {
+ DCHECK(user_data->card);
+ std::string card_issuer_network =
+ autofill::data_util::GetPaymentRequestData(user_data->card->network())
+ .basic_card_issuer_network;
+ processed_action_proto_->mutable_collect_user_data_result()
+ ->set_card_issuer_network(card_issuer_network);
+ delegate_->GetClientMemory()->set_selected_card(
+ std::move(user_data->card));
+
+ if (!collect_user_data.billing_address_name().empty()) {
+ DCHECK(user_data->billing_address);
+ delegate_->GetClientMemory()->set_selected_address(
+ collect_user_data.billing_address_name(),
+ std::move(user_data->billing_address));
+ }
+ }
+
+ if (!collect_user_data.shipping_address_name().empty()) {
+ DCHECK(user_data->shipping_address);
+ delegate_->GetClientMemory()->set_selected_address(
+ collect_user_data.shipping_address_name(),
+ std::move(user_data->shipping_address));
+ }
+
+ if (collect_user_data.has_contact_details()) {
+ DCHECK(user_data->contact_profile);
+ auto contact_details_proto = collect_user_data.contact_details();
+
+ if (contact_details_proto.request_payer_name()) {
+ Metrics::RecordPaymentRequestFirstNameOnly(
+ user_data->contact_profile
+ ->GetRawInfo(autofill::ServerFieldType::NAME_LAST)
+ .empty());
+ }
+
+ if (contact_details_proto.request_payer_email()) {
+ processed_action_proto_->mutable_collect_user_data_result()
+ ->set_payer_email(
+ base::UTF16ToUTF8(user_data->contact_profile->GetRawInfo(
+ autofill::ServerFieldType::EMAIL_ADDRESS)));
+ }
+
+ if (!contact_details_proto.contact_details_name().empty()) {
+ delegate_->GetClientMemory()->set_selected_address(
+ contact_details_proto.contact_details_name(),
+ std::move(user_data->contact_profile));
+ }
+ }
+
+ if (collect_user_data.has_login_details()) {
+ auto login_details =
+ login_details_map_.find(user_data->login_choice_identifier);
+ DCHECK(login_details != login_details_map_.end());
+ if (login_details->second->login.has_value()) {
+ delegate_->GetClientMemory()->set_selected_login(
+ *login_details->second->login);
+ }
+
+ processed_action_proto_->mutable_collect_user_data_result()
+ ->set_login_payload(login_details->second->payload);
+ }
+
+ processed_action_proto_->mutable_collect_user_data_result()
+ ->set_is_terms_and_conditions_accepted(
+ user_data->terms_and_conditions ==
+ TermsAndConditionsState::ACCEPTED);
+ }
+
+ EndAction(succeed ? ClientStatus(ACTION_APPLIED)
+ : ClientStatus(COLLECT_USER_DATA_ERROR));
+}
+
+void CollectUserDataAction::OnAdditionalActionTriggered(int index) {
+ if (!callback_)
+ return;
+
+ processed_action_proto_->mutable_collect_user_data_result()
+ ->set_additional_action_index(index);
+ EndAction(ClientStatus(ACTION_APPLIED));
+}
+
+void CollectUserDataAction::OnTermsAndConditionsLinkClicked(int link) {
+ if (!callback_)
+ return;
+
+ processed_action_proto_->mutable_collect_user_data_result()->set_terms_link(
+ link);
+ EndAction(ClientStatus(ACTION_APPLIED));
+}
+
+std::unique_ptr<CollectUserDataOptions>
+CollectUserDataAction::CreateOptionsFromProto() {
+ auto collect_user_data_options = std::make_unique<CollectUserDataOptions>();
+ auto collect_user_data = proto_.collect_user_data();
+
+ if (collect_user_data.has_contact_details()) {
+ auto contact_details = collect_user_data.contact_details();
+ collect_user_data_options->request_payer_email =
+ contact_details.request_payer_email();
+ collect_user_data_options->request_payer_name =
+ contact_details.request_payer_name();
+ collect_user_data_options->request_payer_phone =
+ contact_details.request_payer_phone();
+ }
+
+ std::copy(collect_user_data.supported_basic_card_networks().begin(),
+ collect_user_data.supported_basic_card_networks().end(),
+ std::back_inserter(
+ collect_user_data_options->supported_basic_card_networks));
+
+ collect_user_data_options->request_shipping =
+ !collect_user_data.shipping_address_name().empty();
+ collect_user_data_options->request_payment_method =
+ collect_user_data.request_payment_method();
+ collect_user_data_options->require_billing_postal_code =
+ collect_user_data.require_billing_postal_code();
+ collect_user_data_options->billing_postal_code_missing_text =
+ collect_user_data.billing_postal_code_missing_text();
+ if (collect_user_data_options->require_billing_postal_code &&
+ collect_user_data_options->billing_postal_code_missing_text.empty()) {
+ return nullptr;
+ }
+ collect_user_data_options->request_login_choice =
+ collect_user_data.has_login_details();
+ collect_user_data_options->login_section_title.assign(
+ collect_user_data.login_details().section_title());
+
+ // Transform login options to concrete login choices.
+ for (const auto& login_option :
+ collect_user_data.login_details().login_options()) {
+ switch (login_option.type_case()) {
+ case LoginDetailsProto::LoginOptionProto::kCustom: {
+ LoginChoice choice = {
+ base::NumberToString(
+ collect_user_data_options->login_choices.size()),
+ login_option.custom().label(),
+ login_option.has_preselection_priority()
+ ? login_option.preselection_priority()
+ : -1};
+ collect_user_data_options->login_choices.emplace_back(
+ std::move(choice));
+ login_details_map_.emplace(
+ choice.identifier,
+ std::make_unique<LoginDetails>(
+ login_option.choose_automatically_if_no_other_options(),
+ login_option.payload()));
+ break;
+ }
+ case LoginDetailsProto::LoginOptionProto::kPasswordManager: {
+ // Will be retrieved later.
+ break;
+ }
+ case LoginDetailsProto::LoginOptionProto::TYPE_NOT_SET: {
+ // Login option specified, but type not set (should never happen).
+ return nullptr;
+ }
+ }
+ }
+
+ // TODO(crbug.com/806868): Maybe we could refactor this to make the confirm
+ // chip and direct_action part of the additional_actions.
+ std::string confirm_text = collect_user_data.confirm_button_text();
+ if (confirm_text.empty()) {
+ confirm_text =
+ l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM);
+ }
+ collect_user_data_options->confirm_action.mutable_chip()->set_text(
+ confirm_text);
+ collect_user_data_options->confirm_action.mutable_chip()->set_type(
+ HIGHLIGHTED_ACTION);
+ *collect_user_data_options->confirm_action.mutable_direct_action() =
+ collect_user_data.confirm_direct_action();
+
+ for (auto action : collect_user_data.additional_actions()) {
+ collect_user_data_options->additional_actions.push_back(action);
+ }
+
+ if (collect_user_data.request_terms_and_conditions()) {
+ collect_user_data_options->show_terms_as_checkbox =
+ collect_user_data.show_terms_as_checkbox();
+ collect_user_data_options->accept_terms_and_conditions_text =
+ collect_user_data.accept_terms_and_conditions_text();
+ if (collect_user_data_options->accept_terms_and_conditions_text.empty()) {
+ collect_user_data_options->accept_terms_and_conditions_text =
+ l10n_util::GetStringUTF8(
+ IDS_AUTOFILL_ASSISTANT_3RD_PARTY_TERMS_ACCEPT);
+ }
+ }
+
+ collect_user_data_options->default_email =
+ delegate_->GetAccountEmailAddress();
+
+ return collect_user_data_options;
+}
+
+bool CollectUserDataAction::CheckInitialAutofillDataComplete(
+ autofill::PersonalDataManager* personal_data_manager,
+ const CollectUserDataOptions& collect_user_data_options) {
+ bool request_contact = collect_user_data_options.request_payer_name ||
+ collect_user_data_options.request_payer_email ||
+ collect_user_data_options.request_payer_phone;
+ if (request_contact || collect_user_data_options.request_shipping) {
+ auto profiles = personal_data_manager->GetProfiles();
+ if (request_contact) {
+ auto completeContactIter = std::find_if(
+ profiles.begin(), profiles.end(),
+ [&collect_user_data_options](const auto& profile) {
+ return IsCompleteContact(profile, collect_user_data_options);
+ });
+ if (completeContactIter == profiles.end()) {
+ return false;
+ }
+ }
+
+ if (collect_user_data_options.request_shipping) {
+ auto completeAddressIter =
+ std::find_if(profiles.begin(), profiles.end(),
+ [&collect_user_data_options](const auto* profile) {
+ return IsCompleteShippingAddress(
+ profile, collect_user_data_options);
+ });
+ if (completeAddressIter == profiles.end()) {
+ return false;
+ }
+ }
+ }
+
+ if (collect_user_data_options.request_payment_method) {
+ auto credit_cards = personal_data_manager->GetCreditCards();
+ auto completeCardIter = std::find_if(
+ credit_cards.begin(), credit_cards.end(),
+ [&collect_user_data_options,
+ personal_data_manager](const auto* credit_card) {
+ return IsCompleteCreditCard(personal_data_manager, credit_card,
+ collect_user_data_options);
+ });
+ if (completeCardIter == credit_cards.end()) {
+ return false;
+ }
+ if (collect_user_data_options.require_billing_postal_code) {
+ initial_card_has_billing_postal_code_ = true;
+ }
+ }
+ return true;
+}
+
+// static
+bool CollectUserDataAction::IsUserDataComplete(
+ autofill::PersonalDataManager* personal_data_manager,
+ const UserData& user_data,
+ const CollectUserDataOptions& options) {
+ return IsCompleteContact(user_data.contact_profile.get(), options) &&
+ IsCompleteBillingAddress(user_data.billing_address.get(), options) &&
+ IsCompleteShippingAddress(user_data.shipping_address.get(), options) &&
+ IsCompleteCreditCard(personal_data_manager, user_data.card.get(),
+ options) &&
+ IsValidLoginChoice(user_data.login_choice_identifier, options) &&
+ IsValidTermsChoice(user_data.terms_and_conditions, options);
+}
+
+void CollectUserDataAction::OnPersonalDataChanged() {
+ personal_data_changed_ = true;
+ delegate_->GetPersonalDataManager()->RemoveObserver(this);
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h
new file mode 100644
index 00000000000..b6c9abc520f
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h
@@ -0,0 +1,93 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_COLLECT_USER_DATA_ACTION_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_COLLECT_USER_DATA_ACTION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/autofill_assistant/browser/actions/action.h"
+#include "components/autofill_assistant/browser/user_data.h"
+#include "components/autofill_assistant/browser/website_login_fetcher.h"
+
+namespace autofill_assistant {
+
+// Shows a UI to collect user data required for subsequent actions.
+class CollectUserDataAction : public Action,
+ public autofill::PersonalDataManagerObserver {
+ public:
+ explicit CollectUserDataAction(ActionDelegate* delegate,
+ const ActionProto& proto);
+ ~CollectUserDataAction() override;
+
+ // From autofill::PersonalDataManagerObserver.
+ void OnPersonalDataChanged() override;
+
+ static bool IsUserDataComplete(
+ autofill::PersonalDataManager* personal_data_manager,
+ const UserData& user_data,
+ const CollectUserDataOptions& collect_user_data_options);
+
+ private:
+ struct LoginDetails {
+ LoginDetails(bool choose_automatically_if_no_other_options,
+ const std::string& payload);
+ LoginDetails(bool choose_automatically_if_no_other_options,
+ const std::string& payload,
+ const WebsiteLoginFetcher::Login& login);
+ ~LoginDetails();
+ bool choose_automatically_if_no_other_options;
+ std::string payload;
+ // Only for Chrome PWM login details.
+ base::Optional<WebsiteLoginFetcher::Login> login;
+ };
+
+ void InternalProcessAction(ProcessActionCallback callback) override;
+ void EndAction(const ClientStatus& status);
+
+ void OnGetUserData(const CollectUserDataProto& collect_user_data,
+ std::unique_ptr<UserData> user_data);
+ void OnAdditionalActionTriggered(int index);
+ void OnTermsAndConditionsLinkClicked(int link);
+
+ void OnGetLogins(
+ const LoginDetailsProto::LoginOptionProto& login_option,
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::vector<WebsiteLoginFetcher::Login> logins);
+ void ShowToUser(
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options);
+
+ // Creates a new instance of |CollectUserDataOptions| from |proto_|.
+ std::unique_ptr<CollectUserDataOptions> CreateOptionsFromProto();
+
+ // Will update |initial_card_has_billing_postal_code_|.
+ bool CheckInitialAutofillDataComplete(
+ autofill::PersonalDataManager* personal_data_manager,
+ const CollectUserDataOptions& collect_user_data_options);
+
+ bool shown_to_user_ = false;
+ bool initially_prefilled = false;
+ bool personal_data_changed_ = false;
+ bool action_successful_ = false;
+ bool initial_card_has_billing_postal_code_ = false;
+ ProcessActionCallback callback_;
+
+ // Maps login choice identifiers to the corresponding login details.
+ std::map<std::string, std::unique_ptr<LoginDetails>> login_details_map_;
+
+ base::WeakPtrFactory<CollectUserDataAction> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(CollectUserDataAction);
+};
+
+} // namespace autofill_assistant
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_COLLECT_USER_DATA_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc
new file mode 100644
index 00000000000..166759c831c
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc
@@ -0,0 +1,487 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/collect_user_data_action.h"
+
+#include <utility>
+
+#include "base/guid.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/mock_personal_data_manager.h"
+#include "components/autofill_assistant/browser/mock_website_login_fetcher.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace {
+const char kFakeUrl[] = "https://www.example.com";
+const char kFakeUsername[] = "user@example.com";
+const char kFakePassword[] = "example_password";
+
+const char kMemoryLocation[] = "billing";
+} // namespace
+
+namespace autofill_assistant {
+namespace {
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::Eq;
+using ::testing::Invoke;
+using ::testing::Property;
+using ::testing::Return;
+
+class CollectUserDataActionTest : public content::RenderViewHostTestHarness {
+ public:
+ void SetUp() override {
+ RenderViewHostTestHarness::SetUp();
+
+ ON_CALL(mock_action_delegate_, GetClientMemory)
+ .WillByDefault(Return(&client_memory_));
+ ON_CALL(mock_action_delegate_, GetPersonalDataManager)
+ .WillByDefault(Return(&mock_personal_data_manager_));
+ ON_CALL(mock_action_delegate_, GetWebsiteLoginFetcher)
+ .WillByDefault(Return(&mock_website_login_fetcher_));
+ ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+ .WillByDefault(Invoke([](std::unique_ptr<CollectUserDataOptions>
+ collect_user_data_options,
+ std::unique_ptr<UserData> user_data) {
+ std::move(collect_user_data_options->confirm_callback)
+ .Run(std::move(user_data));
+ }));
+
+ ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
+ .WillByDefault(
+ RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{
+ WebsiteLoginFetcher::Login(GURL(kFakeUrl), kFakeUsername)}));
+ ON_CALL(mock_website_login_fetcher_, OnGetPasswordForLogin(_, _))
+ .WillByDefault(RunOnceCallback<1>(true, kFakePassword));
+
+ content::WebContentsTester::For(web_contents())
+ ->SetLastCommittedURL(GURL(kFakeUrl));
+ ON_CALL(mock_action_delegate_, GetWebContents())
+ .WillByDefault(Return(web_contents()));
+ }
+
+ protected:
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ MockPersonalDataManager mock_personal_data_manager_;
+ MockWebsiteLoginFetcher mock_website_login_fetcher_;
+ MockActionDelegate mock_action_delegate_;
+ ClientMemory client_memory_;
+};
+
+TEST_F(CollectUserDataActionTest, PromptIsShown) {
+ const char kPrompt[] = "Some message.";
+
+ ActionProto action_proto;
+ action_proto.mutable_collect_user_data()->set_prompt(kPrompt);
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+
+ EXPECT_CALL(mock_action_delegate_, SetStatusMessage(kPrompt));
+ EXPECT_CALL(callback_, Run(_));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(CollectUserDataActionTest, SelectLogin) {
+ ActionProto action_proto;
+ auto* login_details =
+ action_proto.mutable_collect_user_data()->mutable_login_details();
+ auto* login_option = login_details->add_login_options();
+ login_option->mutable_password_manager();
+ login_option->set_payload("payload");
+
+ // Action should fetch the logins, but not the passwords.
+ EXPECT_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(GURL(kFakeUrl), _))
+ .Times(1);
+ EXPECT_CALL(mock_website_login_fetcher_, OnGetPasswordForLogin(_, _))
+ .Times(0);
+
+ ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+ .WillByDefault(Invoke(
+ [](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) {
+ user_data->succeed = true;
+ user_data->login_choice_identifier.assign(
+ collect_user_data_options->login_choices[0].identifier);
+ std::move(collect_user_data_options->confirm_callback)
+ .Run(std::move(user_data));
+ }));
+
+ EXPECT_CALL(callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::collect_user_data_result,
+ Property(&CollectUserDataResultProto::login_payload,
+ "payload"))))));
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(CollectUserDataActionTest, LoginChoiceAutomaticIfNoOtherOptions) {
+ ActionProto action_proto;
+ auto* collect_user_data = action_proto.mutable_collect_user_data();
+ collect_user_data->set_request_terms_and_conditions(false);
+ auto* login_details = collect_user_data->mutable_login_details();
+ auto* login_option = login_details->add_login_options();
+ login_option->mutable_custom()->set_label("Guest Checkout");
+ login_option->set_payload("guest");
+ login_option->set_choose_automatically_if_no_other_options(true);
+ login_option = login_details->add_login_options();
+ login_option->mutable_password_manager();
+ login_option->set_payload("password_manager");
+
+ ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
+ .WillByDefault(
+ RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{}));
+
+ EXPECT_CALL(mock_action_delegate_, CollectUserData(_, _)).Times(0);
+ EXPECT_CALL(callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::collect_user_data_result,
+ Property(&CollectUserDataResultProto::login_payload,
+ "guest"))))));
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(CollectUserDataActionTest, SelectLoginFailsIfNoOptionAvailable) {
+ ActionProto action_proto;
+ auto* collect_user_data = action_proto.mutable_collect_user_data();
+ auto* login_details = collect_user_data->mutable_login_details();
+ auto* login_option = login_details->add_login_options();
+ login_option->mutable_password_manager();
+ login_option->set_payload("password_manager");
+
+ ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
+ .WillByDefault(
+ RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{}));
+
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ COLLECT_USER_DATA_ERROR))));
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(CollectUserDataActionTest, SelectContactDetails) {
+ ActionProto action_proto;
+ auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
+ collect_user_data_proto->set_request_terms_and_conditions(false);
+ auto* contact_details_proto =
+ collect_user_data_proto->mutable_contact_details();
+ contact_details_proto->set_contact_details_name(kMemoryLocation);
+ contact_details_proto->set_request_payer_name(true);
+ contact_details_proto->set_request_payer_email(true);
+ contact_details_proto->set_request_payer_phone(true);
+
+ autofill::AutofillProfile contact_profile;
+ contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL,
+ base::UTF8ToUTF16("Marion Mitchell Morrison"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FIRST,
+ base::UTF8ToUTF16("Marion"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_MIDDLE,
+ base::UTF8ToUTF16("Mitchell"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_LAST,
+ base::UTF8ToUTF16("Morrison"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::EMAIL_ADDRESS,
+ base::UTF8ToUTF16("marion@me.xyz"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16("16505678910"));
+
+ ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+ .WillByDefault(Invoke(
+ [=](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) {
+ user_data->succeed = true;
+ user_data->contact_profile =
+ std::make_unique<autofill::AutofillProfile>(contact_profile);
+ std::move(collect_user_data_options->confirm_callback)
+ .Run(std::move(user_data));
+ }));
+
+ EXPECT_CALL(callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::collect_user_data_result,
+ Property(&CollectUserDataResultProto::payer_email,
+ "marion@me.xyz"))))));
+
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+
+ EXPECT_EQ(client_memory_.has_selected_address(kMemoryLocation), true);
+ auto* profile = client_memory_.selected_address(kMemoryLocation);
+ EXPECT_EQ(profile->GetRawInfo(autofill::NAME_FULL),
+ base::UTF8ToUTF16("Marion Mitchell Morrison"));
+ EXPECT_EQ(profile->GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER),
+ base::UTF8ToUTF16("16505678910"));
+ EXPECT_EQ(profile->GetRawInfo(autofill::EMAIL_ADDRESS),
+ base::UTF8ToUTF16("marion@me.xyz"));
+}
+
+TEST_F(CollectUserDataActionTest, SelectPaymentMethod) {
+ ActionProto action_proto;
+ action_proto.mutable_collect_user_data()->set_request_payment_method(true);
+ action_proto.mutable_collect_user_data()->set_request_terms_and_conditions(
+ false);
+
+ autofill::AutofillProfile billing_profile(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetProfileInfo(&billing_profile, "Marion", "Mitchell",
+ "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA",
+ "91601", "US", "16505678910");
+ ON_CALL(mock_personal_data_manager_, GetProfileByGUID(billing_profile.guid()))
+ .WillByDefault(Return(&billing_profile));
+
+ autofill::CreditCard credit_card(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetCreditCardInfo(&credit_card, "Marion Mitchell",
+ "4111 1111 1111 1111", "01", "2020",
+ billing_profile.guid());
+
+ ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+ .WillByDefault(Invoke(
+ [=](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) {
+ user_data->card =
+ std::make_unique<autofill::CreditCard>(credit_card);
+ user_data->succeed = true;
+ std::move(collect_user_data_options->confirm_callback)
+ .Run(std::move(user_data));
+ }));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::collect_user_data_result,
+ Property(&CollectUserDataResultProto::card_issuer_network,
+ "visa"))))));
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+
+ EXPECT_EQ(client_memory_.has_selected_card(), true);
+ EXPECT_THAT(client_memory_.selected_card()->Compare(credit_card), Eq(0));
+}
+
+TEST_F(CollectUserDataActionTest, MandatoryPostalCodeWithoutErrorMessageFails) {
+ ActionProto action_proto;
+ action_proto.mutable_collect_user_data()->set_request_payment_method(true);
+ action_proto.mutable_collect_user_data()->set_require_billing_postal_code(
+ true);
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(CollectUserDataActionTest, ContactDetailsCanHandleUtf8) {
+ ActionProto action_proto;
+ auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
+ collect_user_data_proto->set_request_terms_and_conditions(false);
+ auto* contact_details_proto =
+ collect_user_data_proto->mutable_contact_details();
+ contact_details_proto->set_contact_details_name(kMemoryLocation);
+ contact_details_proto->set_request_payer_name(true);
+ contact_details_proto->set_request_payer_email(true);
+
+ // Name = 艾丽森 in UTF-8.
+ autofill::AutofillProfile contact_profile;
+ contact_profile.SetRawInfo(
+ autofill::ServerFieldType::NAME_FULL,
+ base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE"));
+ contact_profile.SetRawInfo(
+ autofill::ServerFieldType::EMAIL_ADDRESS,
+ base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE@example.com"));
+
+ ON_CALL(mock_action_delegate_, CollectUserData(_, _))
+ .WillByDefault(Invoke(
+ [=](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) {
+ user_data->succeed = true;
+ user_data->contact_profile =
+ std::make_unique<autofill::AutofillProfile>(contact_profile);
+ std::move(collect_user_data_options->confirm_callback)
+ .Run(std::move(user_data));
+ }));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(
+ &ProcessedActionProto::collect_user_data_result,
+ Property(&CollectUserDataResultProto::payer_email,
+ "\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE@example.com"))))));
+ CollectUserDataAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+
+ EXPECT_EQ(client_memory_.has_selected_address(kMemoryLocation), true);
+ auto* profile = client_memory_.selected_address(kMemoryLocation);
+ EXPECT_EQ(profile->GetRawInfo(autofill::NAME_FULL),
+ base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE"));
+ EXPECT_EQ(
+ profile->GetRawInfo(autofill::EMAIL_ADDRESS),
+ base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE@example.com"));
+}
+
+TEST_F(CollectUserDataActionTest, UserDataComplete_Contact) {
+ UserData user_data;
+ CollectUserDataOptions options;
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.contact_profile = std::make_unique<autofill::AutofillProfile>(
+ base::GenerateGUID(), kFakeUrl);
+ options.request_payer_email = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.contact_profile->SetRawInfo(
+ autofill::ServerFieldType::EMAIL_ADDRESS,
+ base::UTF8ToUTF16("joedoe@example.com"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ options.request_payer_name = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.contact_profile->SetRawInfo(autofill::ServerFieldType::NAME_FULL,
+ base::UTF8ToUTF16("Joe Doe"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ options.request_payer_phone = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.contact_profile->SetRawInfo(
+ autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16("+1 23 456 789 01"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+}
+
+TEST_F(CollectUserDataActionTest, UserDataComplete_Payment) {
+ UserData user_data;
+ CollectUserDataOptions options;
+
+ options.request_payment_method = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ // Valid credit card, but no billing address.
+ user_data.card =
+ std::make_unique<autofill::CreditCard>(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetCreditCardInfo(user_data.card.get(), "Marion Mitchell",
+ "4111 1111 1111 1111", "01", "2020",
+ /* billing_address_id = */ "");
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ // Valid credit card, but invalid billing address.
+ user_data.card->set_billing_address_id("invalid");
+ ON_CALL(mock_personal_data_manager_, GetProfileByGUID("invalid"))
+ .WillByDefault(Return(nullptr));
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ // Incomplete billing address.
+ user_data.billing_address = std::make_unique<autofill::AutofillProfile>(
+ base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetProfileInfo(user_data.billing_address.get(), "Marion",
+ "Mitchell", "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA",
+ /* zipcode = */ "", "US", "16505678910");
+ ON_CALL(mock_personal_data_manager_,
+ GetProfileByGUID(user_data.billing_address->guid()))
+ .WillByDefault(Return(user_data.billing_address.get()));
+ user_data.card->set_billing_address_id(user_data.billing_address->guid());
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
+ base::UTF8ToUTF16("91601"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ // Zip code is optional in Argentinian address.
+ user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
+ base::UTF8ToUTF16(""));
+ user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_COUNTRY,
+ base::UTF8ToUTF16("AR"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ options.require_billing_postal_code = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
+ base::UTF8ToUTF16("B1675"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+}
+
+TEST_F(CollectUserDataActionTest, UserDataComplete_Terms) {
+ UserData user_data;
+ CollectUserDataOptions options;
+ options.accept_terms_and_conditions_text.assign("Accept T&C");
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.terms_and_conditions = REQUIRES_REVIEW;
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.terms_and_conditions = ACCEPTED;
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+}
+
+TEST_F(CollectUserDataActionTest, UserDataComplete_Login) {
+ UserData user_data;
+ CollectUserDataOptions options;
+ options.request_login_choice = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.login_choice_identifier.assign("1");
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+}
+
+TEST_F(CollectUserDataActionTest, UserDataComplete_ShippingAddress) {
+ UserData user_data;
+ CollectUserDataOptions options;
+ options.request_shipping = true;
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ // Incomplete address.
+ user_data.shipping_address = std::make_unique<autofill::AutofillProfile>(
+ base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetProfileInfo(user_data.shipping_address.get(), "Marion",
+ "Mitchell", "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA",
+ /* zipcode = */ "", "US", "16505678910");
+ EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+
+ user_data.shipping_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
+ base::UTF8ToUTF16("91601"));
+ EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
+ &mock_personal_data_manager_, user_data, options));
+}
+
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.cc b/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.cc
index cc57336970f..6a14521a74c 100644
--- a/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.cc
@@ -14,7 +14,7 @@ namespace autofill_assistant {
ConfigureBottomSheetAction::ConfigureBottomSheetAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {}
+ : Action(delegate, proto) {}
ConfigureBottomSheetAction::~ConfigureBottomSheetAction() {}
diff --git a/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.h b/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.h
index 87395c16d54..085d9c58ade 100644
--- a/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action.h
@@ -28,7 +28,7 @@ class ConfigureBottomSheetAction : public Action {
ProcessActionCallback callback_;
base::OneShotTimer timer_;
- base::WeakPtrFactory<ConfigureBottomSheetAction> weak_ptr_factory_;
+ base::WeakPtrFactory<ConfigureBottomSheetAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ConfigureBottomSheetAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc
index d33e4093249..c6bfd87453d 100644
--- a/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc
@@ -9,9 +9,9 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -29,7 +29,7 @@ using ::testing::SizeIs;
class ConfigureBottomSheetActionTest : public testing::Test {
public:
ConfigureBottomSheetActionTest()
- : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ : task_env_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
ON_CALL(mock_action_delegate_, GetViewportMode())
@@ -84,7 +84,7 @@ class ConfigureBottomSheetActionTest : public testing::Test {
// task_env_ must be first to guarantee other field
// creation run in that environment.
- base::test::ScopedTaskEnvironment task_env_;
+ base::test::TaskEnvironment task_env_;
MockActionDelegate mock_action_delegate_;
MockWebController mock_web_controller_;
diff --git a/chromium/components/autofill_assistant/browser/actions/focus_element_action.cc b/chromium/components/autofill_assistant/browser/actions/focus_element_action.cc
index 9d56127c8d5..44efa8d0398 100644
--- a/chromium/components/autofill_assistant/browser/actions/focus_element_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/focus_element_action.cc
@@ -16,7 +16,7 @@ namespace autofill_assistant {
FocusElementAction::FocusElementAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_focus_element());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/focus_element_action.h b/chromium/components/autofill_assistant/browser/actions/focus_element_action.h
index 61fa364b628..145f692ae50 100644
--- a/chromium/components/autofill_assistant/browser/actions/focus_element_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/focus_element_action.h
@@ -31,7 +31,7 @@ class FocusElementAction : public Action {
void OnFocusElement(ProcessActionCallback callback,
const ClientStatus& status);
- base::WeakPtrFactory<FocusElementAction> weak_ptr_factory_;
+ base::WeakPtrFactory<FocusElementAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(FocusElementAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/get_payment_information_action.cc b/chromium/components/autofill_assistant/browser/actions/get_payment_information_action.cc
deleted file mode 100644
index 4f647963cc8..00000000000
--- a/chromium/components/autofill_assistant/browser/actions/get_payment_information_action.cc
+++ /dev/null
@@ -1,362 +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 "components/autofill_assistant/browser/actions/get_payment_information_action.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/android/locale_utils.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_data_util.h"
-#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/browser/geo/address_i18n.h"
-#include "components/autofill_assistant/browser/actions/action_delegate.h"
-#include "components/autofill_assistant/browser/client_memory.h"
-#include "components/autofill_assistant/browser/metrics.h"
-#include "components/autofill_assistant/browser/service.pb.h"
-#include "components/strings/grit/components_strings.h"
-#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
-#include "third_party/libaddressinput/chromium/addressinput_util.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace autofill_assistant {
-
-GetPaymentInformationAction::GetPaymentInformationAction(
- ActionDelegate* delegate,
- const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
- DCHECK(proto_.has_get_payment_information());
-}
-
-GetPaymentInformationAction::~GetPaymentInformationAction() {
- delegate_->GetPersonalDataManager()->RemoveObserver(this);
-
- // Report UMA histograms.
- if (presented_to_user_) {
- Metrics::RecordPaymentRequestPrefilledSuccess(initially_prefilled,
- action_successful_);
- Metrics::RecordPaymentRequestAutofillChanged(personal_data_changed_,
- action_successful_);
- }
-}
-
-void GetPaymentInformationAction::InternalProcessAction(
- ProcessActionCallback callback) {
- callback_ = std::move(callback);
- auto payment_options = CreateOptionsFromProto();
- if (!payment_options) {
- UpdateProcessedAction(INVALID_ACTION);
- action_successful_ = false;
- std::move(callback).Run(std::move(processed_action_proto_));
- return;
- }
- auto get_payment_information = proto_.get_payment_information();
- if (get_payment_information.has_prompt()) {
- delegate_->SetStatusMessage(get_payment_information.prompt());
- }
- payment_options->confirm_callback = base::BindOnce(
- &GetPaymentInformationAction::OnGetPaymentInformation,
- weak_ptr_factory_.GetWeakPtr(), std::move(get_payment_information));
- payment_options->additional_actions_callback =
- base::BindOnce(&GetPaymentInformationAction::OnAdditionalActionTriggered,
- weak_ptr_factory_.GetWeakPtr());
- payment_options->terms_link_callback = base::BindOnce(
- &GetPaymentInformationAction::OnTermsAndConditionsLinkClicked,
- weak_ptr_factory_.GetWeakPtr());
-
- // Gather info for UMA histograms.
- if (!presented_to_user_) {
- presented_to_user_ = true;
- initially_prefilled = IsInitialAutofillDataComplete(
- delegate_->GetPersonalDataManager(), *payment_options);
- delegate_->GetPersonalDataManager()->AddObserver(this);
- }
-
- delegate_->GetPaymentInformation(std::move(payment_options));
-}
-
-void GetPaymentInformationAction::OnGetPaymentInformation(
- const GetPaymentInformationProto& get_payment_information,
- std::unique_ptr<PaymentInformation> payment_information) {
- if (!callback_)
- return;
-
- bool succeed = payment_information->succeed;
- if (succeed) {
- if (get_payment_information.ask_for_payment()) {
- DCHECK(payment_information->card);
- std::string card_issuer_network =
- autofill::data_util::GetPaymentRequestData(
- payment_information->card->network())
- .basic_card_issuer_network;
- processed_action_proto_->mutable_payment_details()
- ->set_card_issuer_network(card_issuer_network);
- delegate_->GetClientMemory()->set_selected_card(
- std::move(payment_information->card));
-
- if (!get_payment_information.billing_address_name().empty()) {
- DCHECK(payment_information->billing_address);
- delegate_->GetClientMemory()->set_selected_address(
- get_payment_information.billing_address_name(),
- std::move(payment_information->billing_address));
- }
- }
-
- if (!get_payment_information.shipping_address_name().empty()) {
- DCHECK(payment_information->shipping_address);
- delegate_->GetClientMemory()->set_selected_address(
- get_payment_information.shipping_address_name(),
- std::move(payment_information->shipping_address));
- }
-
- if (get_payment_information.has_contact_details()) {
- auto contact_details_proto = get_payment_information.contact_details();
- autofill::AutofillProfile contact_profile;
- contact_profile.SetRawInfo(
- autofill::ServerFieldType::NAME_FULL,
- base::UTF8ToUTF16(payment_information->payer_name));
- autofill::data_util::NameParts parts = autofill::data_util::SplitName(
- base::UTF8ToUTF16(payment_information->payer_name));
- contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FIRST,
- parts.given);
- contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_MIDDLE,
- parts.middle);
- contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_LAST,
- parts.family);
- contact_profile.SetRawInfo(
- autofill::ServerFieldType::EMAIL_ADDRESS,
- base::UTF8ToUTF16(payment_information->payer_email));
- contact_profile.SetRawInfo(
- autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
- base::UTF8ToUTF16(payment_information->payer_phone));
- if (!contact_details_proto.contact_details_name().empty()) {
- delegate_->GetClientMemory()->set_selected_address(
- contact_details_proto.contact_details_name(),
- std::make_unique<autofill::AutofillProfile>(contact_profile));
- }
- }
- processed_action_proto_->mutable_payment_details()
- ->set_is_terms_and_conditions_accepted(
- payment_information->terms_and_conditions ==
- TermsAndConditionsState::ACCEPTED);
- processed_action_proto_->mutable_payment_details()->set_payer_email(
- payment_information->payer_email);
- }
-
- UpdateProcessedAction(succeed ? ACTION_APPLIED : PAYMENT_REQUEST_ERROR);
- action_successful_ = succeed;
- std::move(callback_).Run(std::move(processed_action_proto_));
-}
-
-void GetPaymentInformationAction::OnAdditionalActionTriggered(int index) {
- if (!callback_)
- return;
-
- UpdateProcessedAction(ACTION_APPLIED);
- processed_action_proto_->mutable_payment_details()
- ->set_additional_action_index(index);
- action_successful_ = true;
- std::move(callback_).Run(std::move(processed_action_proto_));
-}
-
-void GetPaymentInformationAction::OnTermsAndConditionsLinkClicked(int link) {
- if (!callback_)
- return;
-
- UpdateProcessedAction(ACTION_APPLIED);
- processed_action_proto_->mutable_payment_details()->set_terms_link(link);
- action_successful_ = true;
- std::move(callback_).Run(std::move(processed_action_proto_));
-}
-
-std::unique_ptr<PaymentRequestOptions>
-GetPaymentInformationAction::CreateOptionsFromProto() const {
- auto payment_options = std::make_unique<PaymentRequestOptions>();
- auto get_payment_information = proto_.get_payment_information();
-
- if (get_payment_information.has_contact_details()) {
- auto contact_details = get_payment_information.contact_details();
- payment_options->request_payer_email =
- contact_details.request_payer_email();
- payment_options->request_payer_name = contact_details.request_payer_name();
- payment_options->request_payer_phone =
- contact_details.request_payer_phone();
- }
-
- std::copy(get_payment_information.supported_basic_card_networks().begin(),
- get_payment_information.supported_basic_card_networks().end(),
- std::back_inserter(payment_options->supported_basic_card_networks));
-
- payment_options->request_shipping =
- !get_payment_information.shipping_address_name().empty();
- payment_options->request_payment_method =
- get_payment_information.ask_for_payment();
- payment_options->require_billing_postal_code =
- get_payment_information.require_billing_postal_code();
- payment_options->billing_postal_code_missing_text =
- get_payment_information.billing_postal_code_missing_text();
- if (payment_options->require_billing_postal_code &&
- payment_options->billing_postal_code_missing_text.empty()) {
- return nullptr;
- }
-
- // TODO(crbug.com/806868): Maybe we could refactor this to make the confirm
- // chip and direct_action part of the additional_actions.
- std::string confirm_text = get_payment_information.confirm_button_text();
- if (confirm_text.empty()) {
- confirm_text =
- l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM);
- }
- payment_options->confirm_action.mutable_chip()->set_text(confirm_text);
- payment_options->confirm_action.mutable_chip()->set_type(HIGHLIGHTED_ACTION);
- *payment_options->confirm_action.mutable_direct_action() =
- get_payment_information.confirm_direct_action();
-
- for (auto action : get_payment_information.additional_actions()) {
- payment_options->additional_actions.push_back(action);
- }
-
- switch (get_payment_information.terms_and_conditions_state()) {
- case GetPaymentInformationProto::NOT_SELECTED:
- payment_options->initial_terms_and_conditions = NOT_SELECTED;
- break;
- case GetPaymentInformationProto::ACCEPTED:
- payment_options->initial_terms_and_conditions = ACCEPTED;
- break;
- case GetPaymentInformationProto::REVIEW_REQUIRED:
- payment_options->initial_terms_and_conditions = REQUIRES_REVIEW;
- break;
- }
-
- if (get_payment_information.request_terms_and_conditions()) {
- payment_options->show_terms_as_checkbox =
- get_payment_information.show_terms_as_checkbox();
- payment_options->accept_terms_and_conditions_text =
- get_payment_information.accept_terms_and_conditions_text();
- if (payment_options->accept_terms_and_conditions_text.empty()) {
- payment_options->accept_terms_and_conditions_text =
- l10n_util::GetStringUTF8(
- IDS_AUTOFILL_ASSISTANT_3RD_PARTY_TERMS_ACCEPT);
- }
- }
-
- return payment_options;
-}
-
-bool GetPaymentInformationAction::IsInitialAutofillDataComplete(
- autofill::PersonalDataManager* personal_data_manager,
- const PaymentRequestOptions& payment_options) const {
- bool request_contact = payment_options.request_payer_name ||
- payment_options.request_payer_email ||
- payment_options.request_payer_phone;
- if (request_contact || payment_options.request_shipping) {
- auto profiles = personal_data_manager->GetProfiles();
- if (request_contact) {
- auto completeContactIter =
- std::find_if(profiles.begin(), profiles.end(),
- [&payment_options](const auto& profile) {
- return IsCompleteContact(*profile, payment_options);
- });
- if (completeContactIter == profiles.end()) {
- return false;
- }
- }
-
- if (payment_options.request_shipping) {
- auto completeAddressIter =
- std::find_if(profiles.begin(), profiles.end(),
- [&payment_options](const auto* profile) {
- return IsCompleteAddress(*profile, payment_options);
- });
- if (completeAddressIter == profiles.end()) {
- return false;
- }
- }
- }
-
- if (payment_options.request_payment_method) {
- auto credit_cards = personal_data_manager->GetCreditCards();
- auto completeCardIter = std::find_if(
- credit_cards.begin(), credit_cards.end(),
- [&payment_options](const auto* credit_card) {
- return IsCompleteCreditCard(*credit_card, payment_options);
- });
- if (completeCardIter == credit_cards.end()) {
- return false;
- }
- }
- return true;
-}
-
-bool GetPaymentInformationAction::IsCompleteContact(
- const autofill::AutofillProfile& profile,
- const PaymentRequestOptions& payment_options) {
- if (payment_options.request_payer_name &&
- profile.GetRawInfo(autofill::NAME_FULL).empty()) {
- return false;
- }
-
- if (payment_options.request_payer_email &&
- profile.GetRawInfo(autofill::EMAIL_ADDRESS).empty()) {
- return false;
- }
-
- if (payment_options.request_payer_phone &&
- profile.GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER).empty()) {
- return false;
- }
- return true;
-}
-
-bool GetPaymentInformationAction::IsCompleteAddress(
- const autofill::AutofillProfile& profile,
- const PaymentRequestOptions& payment_options) {
- if (!payment_options.request_shipping) {
- return true;
- }
-
- auto address_data = autofill::i18n::CreateAddressDataFromAutofillProfile(
- profile, base::android::GetDefaultLocaleString());
- return autofill::addressinput::HasAllRequiredFields(*address_data);
-}
-
-bool GetPaymentInformationAction::IsCompleteCreditCard(
- const autofill::CreditCard& credit_card,
- const PaymentRequestOptions& payment_options) {
- if (credit_card.record_type() != autofill::CreditCard::MASKED_SERVER_CARD &&
- !credit_card.HasValidCardNumber()) {
- // Can't check validity of masked server card numbers because they are
- // incomplete until decrypted.
- return false;
- }
-
- if (!credit_card.HasValidExpirationDate() ||
- credit_card.billing_address_id().empty()) {
- return false;
- }
-
- std::string basic_card_network =
- autofill::data_util::GetPaymentRequestData(credit_card.network())
- .basic_card_issuer_network;
- if (!payment_options.supported_basic_card_networks.empty() &&
- std::find(payment_options.supported_basic_card_networks.begin(),
- payment_options.supported_basic_card_networks.end(),
- basic_card_network) ==
- payment_options.supported_basic_card_networks.end()) {
- return false;
- }
- return true;
-}
-
-void GetPaymentInformationAction::OnPersonalDataChanged() {
- personal_data_changed_ = true;
- delegate_->GetPersonalDataManager()->RemoveObserver(this);
-}
-
-} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/get_payment_information_action.h b/chromium/components/autofill_assistant/browser/actions/get_payment_information_action.h
deleted file mode 100644
index 2de78be8ce3..00000000000
--- a/chromium/components/autofill_assistant/browser/actions/get_payment_information_action.h
+++ /dev/null
@@ -1,67 +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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_GET_PAYMENT_INFORMATION_ACTION_H_
-#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_GET_PAYMENT_INFORMATION_ACTION_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/personal_data_manager_observer.h"
-#include "components/autofill_assistant/browser/actions/action.h"
-#include "components/autofill_assistant/browser/payment_request.h"
-
-namespace autofill_assistant {
-
-// Triggers PaymentRequest to collect user data.
-class GetPaymentInformationAction
- : public Action,
- public autofill::PersonalDataManagerObserver {
- public:
- explicit GetPaymentInformationAction(ActionDelegate* delegate,
- const ActionProto& proto);
- ~GetPaymentInformationAction() override;
-
- // From autofill::PersonalDataManagerObserver.
- void OnPersonalDataChanged() override;
-
- private:
- void InternalProcessAction(ProcessActionCallback callback) override;
-
- void OnGetPaymentInformation(
- const GetPaymentInformationProto& get_payment_information,
- std::unique_ptr<PaymentInformation> payment_information);
- void OnAdditionalActionTriggered(int index);
- void OnTermsAndConditionsLinkClicked(int link);
-
- // Creates a new instance of |PaymentRequestOptions| from |proto_|.
- std::unique_ptr<PaymentRequestOptions> CreateOptionsFromProto() const;
-
- bool IsInitialAutofillDataComplete(
- autofill::PersonalDataManager* personal_data_manager,
- const PaymentRequestOptions& payment_options) const;
- static bool IsCompleteContact(const autofill::AutofillProfile& profile,
- const PaymentRequestOptions& payment_options);
- static bool IsCompleteAddress(const autofill::AutofillProfile& profile,
- const PaymentRequestOptions& payment_options);
- static bool IsCompleteCreditCard(
- const autofill::CreditCard& credit_card,
- const PaymentRequestOptions& payment_options);
-
- bool presented_to_user_ = false;
- bool initially_prefilled = false;
- bool personal_data_changed_ = false;
- bool action_successful_ = false;
- ProcessActionCallback callback_;
- base::WeakPtrFactory<GetPaymentInformationAction> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GetPaymentInformationAction);
-};
-
-} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_GET_PAYMENT_INFORMATION_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/highlight_element_action.cc b/chromium/components/autofill_assistant/browser/actions/highlight_element_action.cc
index 9f0dffbdbac..5c549006ef3 100644
--- a/chromium/components/autofill_assistant/browser/actions/highlight_element_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/highlight_element_action.cc
@@ -14,7 +14,7 @@ namespace autofill_assistant {
HighlightElementAction::HighlightElementAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_highlight_element());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/highlight_element_action.h b/chromium/components/autofill_assistant/browser/actions/highlight_element_action.h
index b84952b5580..9b0830079c5 100644
--- a/chromium/components/autofill_assistant/browser/actions/highlight_element_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/highlight_element_action.h
@@ -33,7 +33,7 @@ class HighlightElementAction : public Action {
void OnHighlightElement(ProcessActionCallback callback,
const ClientStatus& status);
- base::WeakPtrFactory<HighlightElementAction> weak_ptr_factory_;
+ base::WeakPtrFactory<HighlightElementAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(HighlightElementAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h b/chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h
index 713c1a8cc76..c708be319e1 100644
--- a/chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -13,10 +13,10 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/client_settings.h"
-#include "components/autofill_assistant/browser/payment_request.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/top_padding.h"
#include "components/autofill_assistant/browser/user_action.h"
+#include "components/autofill_assistant/browser/user_data.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -108,8 +108,10 @@ class MockActionDelegate : public ActionDelegate {
void(const Selector& selector,
base::OnceCallback<void(const ClientStatus&)> callback));
- MOCK_METHOD1(GetPaymentInformation,
- void(std::unique_ptr<PaymentRequestOptions> options));
+ MOCK_METHOD2(
+ CollectUserData,
+ void(std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data));
MOCK_METHOD1(OnGetFullCard,
void(base::OnceCallback<void(const autofill::CreditCard& card,
@@ -146,7 +148,7 @@ class MockActionDelegate : public ActionDelegate {
int delay_in_millisecond,
base::OnceCallback<void(const ClientStatus&)> callback) {
OnSetFieldValue(selector, value, callback);
- OnSetFieldValue(selector, value, delay_in_millisecond, delay_in_millisecond,
+ OnSetFieldValue(selector, value, simulate_key_presses, delay_in_millisecond,
callback);
}
@@ -168,11 +170,20 @@ class MockActionDelegate : public ActionDelegate {
const std::string& value,
base::OnceCallback<void(const ClientStatus&)> callback));
- MOCK_METHOD4(SendKeyboardInput,
+ void SendKeyboardInput(
+ const Selector& selector,
+ const std::vector<UChar32>& codepoints,
+ int delay_in_millisecond,
+ base::OnceCallback<void(const ClientStatus&)> callback) {
+ OnSendKeyboardInput(selector, codepoints, delay_in_millisecond, callback);
+ }
+
+ MOCK_METHOD4(OnSendKeyboardInput,
void(const Selector& selector,
const std::vector<UChar32>& codepoints,
int delay_in_millisecond,
- base::OnceCallback<void(const ClientStatus&)> callback));
+ base::OnceCallback<void(const ClientStatus&)>& callback));
+
MOCK_METHOD2(GetOuterHtml,
void(const Selector& selector,
base::OnceCallback<void(const ClientStatus&,
@@ -187,7 +198,9 @@ class MockActionDelegate : public ActionDelegate {
MOCK_METHOD0(Restart, void());
MOCK_METHOD0(GetClientMemory, ClientMemory*());
MOCK_METHOD0(GetPersonalDataManager, autofill::PersonalDataManager*());
+ MOCK_METHOD0(GetWebsiteLoginFetcher, WebsiteLoginFetcher*());
MOCK_METHOD0(GetWebContents, content::WebContents*());
+ MOCK_METHOD0(GetAccountEmailAddress, std::string());
MOCK_METHOD1(SetDetails, void(std::unique_ptr<Details> details));
MOCK_METHOD1(SetInfoBox, void(const InfoBox& info_box));
MOCK_METHOD0(ClearInfoBox, void());
diff --git a/chromium/components/autofill_assistant/browser/actions/prompt_action.cc b/chromium/components/autofill_assistant/browser/actions/prompt_action.cc
index e48091c61ad..4ac8e2c68ea 100644
--- a/chromium/components/autofill_assistant/browser/actions/prompt_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/prompt_action.cc
@@ -19,7 +19,7 @@
namespace autofill_assistant {
PromptAction::PromptAction(ActionDelegate* delegate, const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_prompt());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/prompt_action.h b/chromium/components/autofill_assistant/browser/actions/prompt_action.h
index 20bf76943d2..f166292890e 100644
--- a/chromium/components/autofill_assistant/browser/actions/prompt_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/prompt_action.h
@@ -69,7 +69,7 @@ class PromptAction : public Action {
std::unique_ptr<base::RepeatingTimer> timer_;
- base::WeakPtrFactory<PromptAction> weak_ptr_factory_;
+ base::WeakPtrFactory<PromptAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PromptAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
index 1e7d19b31a0..009a4513f1f 100644
--- a/chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
@@ -10,9 +10,9 @@
#include "base/callback.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -33,7 +33,7 @@ using ::testing::UnorderedElementsAre;
class PromptActionTest : public testing::Test {
public:
PromptActionTest()
- : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ : task_env_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
ON_CALL(mock_web_controller_, OnElementCheck(_, _))
@@ -56,7 +56,7 @@ class PromptActionTest : public testing::Test {
protected:
// task_env_ must be first to guarantee other field
// creation run in that environment.
- base::test::ScopedTaskEnvironment task_env_;
+ base::test::TaskEnvironment task_env_;
MockActionDelegate mock_action_delegate_;
MockWebController mock_web_controller_;
diff --git a/chromium/components/autofill_assistant/browser/actions/select_option_action.cc b/chromium/components/autofill_assistant/browser/actions/select_option_action.cc
index a77c1f452a2..3c9b96ffd36 100644
--- a/chromium/components/autofill_assistant/browser/actions/select_option_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/select_option_action.cc
@@ -14,7 +14,7 @@ namespace autofill_assistant {
SelectOptionAction::SelectOptionAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_select_option());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/select_option_action.h b/chromium/components/autofill_assistant/browser/actions/select_option_action.h
index 0175ce0d832..7da3615866f 100644
--- a/chromium/components/autofill_assistant/browser/actions/select_option_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/select_option_action.h
@@ -31,7 +31,7 @@ class SelectOptionAction : public Action {
void OnSelectOption(ProcessActionCallback callback,
const ClientStatus& status);
- base::WeakPtrFactory<SelectOptionAction> weak_ptr_factory_;
+ base::WeakPtrFactory<SelectOptionAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SelectOptionAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/set_attribute_action.cc b/chromium/components/autofill_assistant/browser/actions/set_attribute_action.cc
index 721dc982bc8..7e72315358c 100644
--- a/chromium/components/autofill_assistant/browser/actions/set_attribute_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/set_attribute_action.cc
@@ -14,7 +14,7 @@ namespace autofill_assistant {
SetAttributeAction::SetAttributeAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK_GT(proto_.set_attribute().element().selectors_size(), 0);
DCHECK_GT(proto_.set_attribute().attribute_size(), 0);
}
diff --git a/chromium/components/autofill_assistant/browser/actions/set_attribute_action.h b/chromium/components/autofill_assistant/browser/actions/set_attribute_action.h
index 1cccdcea968..57b3f9d1920 100644
--- a/chromium/components/autofill_assistant/browser/actions/set_attribute_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/set_attribute_action.h
@@ -31,7 +31,7 @@ class SetAttributeAction : public Action {
void OnSetAttribute(ProcessActionCallback callback,
const ClientStatus& status);
- base::WeakPtrFactory<SetAttributeAction> weak_ptr_factory_;
+ base::WeakPtrFactory<SetAttributeAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SetAttributeAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.cc b/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
index e2838c8a9a7..80552b759b9 100644
--- a/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
@@ -10,157 +10,188 @@
#include "base/callback.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
-#include "components/autofill_assistant/browser/string_conversions_util.h"
namespace autofill_assistant {
+SetFormFieldValueAction::FieldInput::FieldInput(
+ std::unique_ptr<std::vector<UChar32>> _keyboard_input)
+ : keyboard_input(std::move(_keyboard_input)) {}
+
+SetFormFieldValueAction::FieldInput::FieldInput(std::string _value)
+ : value(_value) {}
+
+SetFormFieldValueAction::FieldInput::FieldInput(bool _use_password)
+ : use_password(_use_password) {}
+
+SetFormFieldValueAction::FieldInput::FieldInput(FieldInput&& other) = default;
+
+SetFormFieldValueAction::FieldInput::~FieldInput() {}
+
SetFormFieldValueAction::SetFormFieldValueAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_set_form_value());
DCHECK_GT(proto_.set_form_value().element().selectors_size(), 0);
DCHECK_GT(proto_.set_form_value().value_size(), 0);
- DCHECK(proto_.set_form_value().value(0).has_text());
}
SetFormFieldValueAction::~SetFormFieldValueAction() {}
void SetFormFieldValueAction::InternalProcessAction(
ProcessActionCallback callback) {
- Selector selector =
- Selector(proto_.set_form_value().element()).MustBeVisible();
- if (selector.empty()) {
+ process_action_callback_ = std::move(callback);
+ selector_ = Selector(proto_.set_form_value().element()).MustBeVisible();
+ if (selector_.empty()) {
DVLOG(1) << __func__ << ": empty selector";
- UpdateProcessedAction(INVALID_SELECTOR);
- std::move(callback).Run(std::move(processed_action_proto_));
+ EndAction(ClientStatus(INVALID_SELECTOR));
return;
}
+
+ // Check proto fields.
+ for (const auto& keypress : proto_.set_form_value().value()) {
+ switch (keypress.keypress_case()) {
+ case SetFormFieldValueProto_KeyPress::kKeycode:
+ // DEPRECATED: the field `keycode' used to contain a single character to
+ // input as text. Since there is no easy way to convert keycodes to
+ // text, this field is now deprecated and only works for US-ASCII
+ // characters. You should use the `keyboard_input' field instead.
+ if (keypress.keycode() >= 128) {
+ DVLOG(1) << "SetFormFieldValueAction: field `keycode' is deprecated "
+ << "and only supports US-ASCII values (encountered "
+ << keypress.keycode() << "). Use field `key' instead.";
+ EndAction(ClientStatus(INVALID_ACTION));
+ return;
+ }
+ field_inputs_.emplace_back(
+ /* keyboard_input = */ std::make_unique<std::vector<UChar32>>(
+ 1, keypress.keycode()));
+ break;
+ case SetFormFieldValueProto_KeyPress::kKeyboardInput:
+ if (keypress.keyboard_input().empty()) {
+ DVLOG(1) << "SetFormFieldValueAction: field 'keyboard_input' must be "
+ "non-empty if set.";
+ EndAction(ClientStatus(INVALID_ACTION));
+ return;
+ }
+ field_inputs_.emplace_back(
+ /* keyboard_input = */ std::make_unique<std::vector<UChar32>>(
+ UTF8ToUnicode(keypress.keyboard_input())));
+ break;
+ case SetFormFieldValueProto_KeyPress::kUseUsername:
+ FALLTHROUGH;
+ case SetFormFieldValueProto_KeyPress::kUsePassword:
+ // Login information must have been stored by a previous action.
+ if (!delegate_->GetClientMemory()->has_selected_login()) {
+ DVLOG(1) << "SetFormFieldValueAction: requested login details not "
+ "available in client memory.";
+ EndAction(ClientStatus(PRECONDITION_FAILED));
+ return;
+ }
+ if (keypress.keypress_case() ==
+ SetFormFieldValueProto_KeyPress::kUseUsername) {
+ field_inputs_.emplace_back(/* value = */ delegate_->GetClientMemory()
+ ->selected_login()
+ ->username);
+ } else {
+ field_inputs_.emplace_back(/* use_password = */ true);
+ }
+ break;
+ case SetFormFieldValueProto_KeyPress::kText:
+ // Currently no check required.
+ field_inputs_.emplace_back(/* value = */ keypress.text());
+ break;
+ default:
+ DVLOG(1) << "Unrecognized field for SetFormFieldValueProto_KeyPress";
+ EndAction(ClientStatus(INVALID_ACTION));
+ return;
+ }
+ }
+
delegate_->ShortWaitForElement(
- selector, base::BindOnce(&SetFormFieldValueAction::OnWaitForElement,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(callback), selector));
+ selector_, base::BindOnce(&SetFormFieldValueAction::OnWaitForElement,
+ weak_ptr_factory_.GetWeakPtr()));
}
-void SetFormFieldValueAction::OnWaitForElement(ProcessActionCallback callback,
- const Selector& selector,
- bool element_found) {
+void SetFormFieldValueAction::OnWaitForElement(bool element_found) {
if (!element_found) {
- UpdateProcessedAction(ELEMENT_RESOLUTION_FAILED);
- std::move(callback).Run(std::move(processed_action_proto_));
+ EndAction(ClientStatus(ELEMENT_RESOLUTION_FAILED));
return;
}
// Start with first value, then call OnSetFieldValue() recursively until done.
- OnSetFieldValue(std::move(callback), selector, /* next = */ 0,
- OkClientStatus());
+ OnSetFieldValue(/* next = */ 0, OkClientStatus());
}
-void SetFormFieldValueAction::OnSetFieldValue(ProcessActionCallback callback,
- const Selector& selector,
- int next,
+void SetFormFieldValueAction::OnSetFieldValue(int next,
const ClientStatus& status) {
// If something went wrong or we are out of values: finish
if (!status.ok() || next >= proto_.set_form_value().value_size()) {
- UpdateProcessedAction(status);
- std::move(callback).Run(std::move(processed_action_proto_));
+ EndAction(status);
return;
}
- const auto& key_field = proto_.set_form_value().value(next);
bool simulate_key_presses = proto_.set_form_value().simulate_key_presses();
int delay_in_millisecond = proto_.set_form_value().delay_in_millisecond();
- switch (key_field.keypress_case()) {
- case SetFormFieldValueProto_KeyPress::kText:
- if (simulate_key_presses || key_field.text().empty()) {
- // If we are already using keyboard simulation or we are trying to set
- // an empty value, no need to trigger keyboard fallback. Simply move on
- // to next value after |SetFieldValue| is done.
- delegate_->SetFieldValue(
- selector, key_field.text(), simulate_key_presses,
- delay_in_millisecond,
- base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- selector,
- /* next = */ next + 1));
+ auto next_field_callback = base::BindOnce(
+ &SetFormFieldValueAction::OnSetFieldValue, weak_ptr_factory_.GetWeakPtr(),
+ /* next = */ next + 1);
+ for (const auto& field_input : field_inputs_) {
+ if (field_input.keyboard_input) {
+ delegate_->SendKeyboardInput(selector_, *field_input.keyboard_input,
+ delay_in_millisecond,
+ std::move(next_field_callback));
+ } else if (field_input.use_password) {
+ delegate_->GetWebsiteLoginFetcher()->GetPasswordForLogin(
+ *delegate_->GetClientMemory()->selected_login(),
+ base::BindOnce(&SetFormFieldValueAction::OnGetPassword,
+ weak_ptr_factory_.GetWeakPtr(),
+ /* field_index = */ next));
+ } else {
+ if (simulate_key_presses || field_input.value.empty()) {
+ delegate_->SetFieldValue(selector_, field_input.value,
+ simulate_key_presses, delay_in_millisecond,
+ std::move(next_field_callback));
} else {
- // Trigger a check for keyboard fallback when |SetFieldValue| is done.
delegate_->SetFieldValue(
- selector, key_field.text(), simulate_key_presses,
+ selector_, field_input.value, simulate_key_presses,
delay_in_millisecond,
base::BindOnce(
&SetFormFieldValueAction::OnSetFieldValueAndCheckFallback,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback), selector,
- /* next = */ next));
+ weak_ptr_factory_.GetWeakPtr(),
+ /* field_index = */ next,
+ /* requested_value = */ field_input.value));
}
- break;
- case SetFormFieldValueProto_KeyPress::kKeycode:
- // DEPRECATED: the field `keycode' used to contain a single character to
- // input as text. Since there is no easy way to convert keycodes to text,
- // this field is now deprecated and only works for US-ASCII characters.
- // You should use the `keyboard_input' field instead.
- if (key_field.keycode() < 128) { // US-ASCII
- delegate_->SendKeyboardInput(
- selector, {key_field.keycode()}, delay_in_millisecond,
- base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- selector,
- /* next = */ next + 1));
- } else {
- DVLOG(3)
- << "SetFormFieldValueProto_KeyPress: field `keycode' is deprecated "
- << "and only supports US-ASCII values (encountered "
- << key_field.keycode() << "). Use field `key' instead.";
- OnSetFieldValue(std::move(callback), selector, next,
- ClientStatus(INVALID_ACTION));
- }
- break;
- case SetFormFieldValueProto_KeyPress::kKeyboardInput:
- delegate_->SendKeyboardInput(
- selector, UTF8ToUnicode(key_field.keyboard_input()),
- delay_in_millisecond,
- base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- selector,
- /* next = */ next + 1));
- break;
- default:
- DVLOG(1) << "Unrecognized field for SetFormFieldValueProto_KeyPress";
- OnSetFieldValue(std::move(callback), selector, next,
- ClientStatus(INVALID_ACTION));
- break;
+ }
}
}
void SetFormFieldValueAction::OnSetFieldValueAndCheckFallback(
- ProcessActionCallback callback,
- const Selector& selector,
- int next,
+ int field_index,
+ const std::string& requested_value,
const ClientStatus& status) {
if (!status.ok()) {
- OnSetFieldValue(std::move(callback), selector, next + 1, status);
+ EndAction(status);
return;
}
delegate_->GetFieldValue(
- selector, base::BindOnce(&SetFormFieldValueAction::OnGetFieldValue,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(callback), selector, next));
+ selector_, base::BindOnce(&SetFormFieldValueAction::OnGetFieldValue,
+ weak_ptr_factory_.GetWeakPtr(), field_index,
+ requested_value));
}
-void SetFormFieldValueAction::OnGetFieldValue(ProcessActionCallback callback,
- const Selector& selector,
- int next,
- bool get_value_status,
- const std::string& value) {
- const auto& key_field = proto_.set_form_value().value(next);
-
+void SetFormFieldValueAction::OnGetFieldValue(
+ int field_index,
+ const std::string& requested_value,
+ bool get_value_status,
+ const std::string& actual_value) {
// Move to next value if |GetFieldValue| failed.
if (!get_value_status) {
- OnSetFieldValue(std::move(callback), selector, next + 1, OkClientStatus());
+ OnSetFieldValue(field_index + 1, OkClientStatus());
return;
}
// If value is still empty while it is not supposed to be, trigger keyboard
// simulation fallback.
- if (key_field.text().size() > 0 && value.empty()) {
+ if (!requested_value.empty() && actual_value.empty()) {
// Report a key press simulation fallback has happened.
auto result = SetFormFieldValueProto::Result();
result.set_fallback_to_simulate_key_presses(true);
@@ -169,17 +200,46 @@ void SetFormFieldValueAction::OnGetFieldValue(ProcessActionCallback callback,
// Run |SetFieldValue| with keyboard simulation on and move on to next value
// afterwards.
delegate_->SetFieldValue(
- selector, key_field.text(), /*simulate_key_presses = */ true,
+ selector_, requested_value, /*simulate_key_presses = */ true,
proto_.set_form_value().delay_in_millisecond(),
base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- selector,
- /* next = */ next + 1));
+ weak_ptr_factory_.GetWeakPtr(),
+ /* next = */ field_index + 1));
return;
}
// Move to next value in all other cases.
- OnSetFieldValue(std::move(callback), selector, next + 1, OkClientStatus());
+ OnSetFieldValue(field_index + 1, OkClientStatus());
+}
+
+void SetFormFieldValueAction::OnGetPassword(int field_index,
+ bool success,
+ std::string password) {
+ if (!success) {
+ EndAction(ClientStatus(AUTOFILL_INFO_NOT_AVAILABLE));
+ return;
+ }
+ bool simulate_key_presses = proto_.set_form_value().simulate_key_presses();
+ int delay_in_millisecond = proto_.set_form_value().delay_in_millisecond();
+ if (simulate_key_presses) {
+ delegate_->SetFieldValue(
+ selector_, password, simulate_key_presses, delay_in_millisecond,
+ base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue,
+ weak_ptr_factory_.GetWeakPtr(),
+ /* next = */ field_index + 1));
+ } else {
+ delegate_->SetFieldValue(
+ selector_, password, simulate_key_presses, delay_in_millisecond,
+ base::BindOnce(
+ &SetFormFieldValueAction::OnSetFieldValueAndCheckFallback,
+ weak_ptr_factory_.GetWeakPtr(),
+ /* next = */ field_index, /* requested_value = */ password));
+ }
+}
+
+void SetFormFieldValueAction::EndAction(const ClientStatus& status) {
+ UpdateProcessedAction(status);
+ std::move(process_action_callback_).Run(std::move(processed_action_proto_));
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.h b/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.h
index 48a98920937..b00c045999e 100644
--- a/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.h
@@ -8,9 +8,11 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
+#include "components/autofill_assistant/browser/string_conversions_util.h"
namespace autofill_assistant {
@@ -22,30 +24,49 @@ class SetFormFieldValueAction : public Action {
~SetFormFieldValueAction() override;
private:
+ // A field input as extracted from the proto, but already checked for
+ // validity.
+ struct FieldInput {
+ explicit FieldInput(std::unique_ptr<std::vector<UChar32>> keyboard_input);
+ explicit FieldInput(std::string value);
+ explicit FieldInput(bool use_password);
+ FieldInput(FieldInput&& other);
+ ~FieldInput();
+
+ // The keys to press if either |keycode| or |keyboard_input| is set, else
+ // nullptr.
+ std::unique_ptr<std::vector<UChar32>> keyboard_input = nullptr;
+ // True if the value should be retrieved from the login details in client
+ // memory.
+ bool use_password = false;
+ // The string to input (for all other cases).
+ std::string value;
+ };
+
// Overrides Action:
void InternalProcessAction(ProcessActionCallback callback) override;
- void OnWaitForElement(ProcessActionCallback callback,
- const Selector& selector,
- bool element_found);
+ void OnWaitForElement(bool element_found);
- void OnGetFieldValue(ProcessActionCallback callback,
- const Selector& selector,
- int next,
+ void OnGetFieldValue(int field_index,
+ const std::string& requested_value,
bool status,
- const std::string& value);
+ const std::string& actual_value);
- void OnSetFieldValue(ProcessActionCallback callback,
- const Selector& selector,
- int next,
- const ClientStatus& status);
+ void OnSetFieldValue(int next, const ClientStatus& status);
- void OnSetFieldValueAndCheckFallback(ProcessActionCallback callback,
- const Selector& selector,
- int next,
+ void OnSetFieldValueAndCheckFallback(int field_index,
+ const std::string& requested_value,
const ClientStatus& status);
- base::WeakPtrFactory<SetFormFieldValueAction> weak_ptr_factory_;
+ void OnGetPassword(int field_index, bool success, std::string password);
+
+ void EndAction(const ClientStatus& status);
+
+ Selector selector_;
+ std::vector<FieldInput> field_inputs_;
+ ProcessActionCallback process_action_callback_;
+ base::WeakPtrFactory<SetFormFieldValueAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SetFormFieldValueAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
new file mode 100644
index 00000000000..4ca89445421
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/set_form_field_value_action.h"
+
+#include <string>
+#include <utility>
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/client_memory.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/mock_website_login_fetcher.h"
+#include "components/autofill_assistant/browser/string_conversions_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace {
+const char kFakeUrl[] = "https://www.example.com";
+const char kFakeSelector[] = "#some_selector";
+const char kFakeUsername[] = "user@example.com";
+const char kFakePassword[] = "example_password";
+} // namespace
+
+namespace autofill_assistant {
+namespace {
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Pointee;
+using ::testing::Property;
+using ::testing::Return;
+
+class SetFormFieldValueActionTest : public testing::Test {
+ public:
+ void SetUp() override {
+ set_form_field_proto_ = proto_.mutable_set_form_value();
+ set_form_field_proto_->mutable_element()->add_selectors(kFakeSelector);
+ set_form_field_proto_->mutable_element()->set_visibility_requirement(
+ MUST_BE_VISIBLE);
+ ON_CALL(mock_action_delegate_, GetClientMemory)
+ .WillByDefault(Return(&client_memory_));
+ ON_CALL(mock_action_delegate_, GetWebsiteLoginFetcher)
+ .WillByDefault(Return(&mock_website_login_fetcher_));
+ ON_CALL(mock_action_delegate_, OnShortWaitForElement(_, _))
+ .WillByDefault(RunOnceCallback<1>(true));
+ ON_CALL(mock_action_delegate_, OnSetFieldValue(_, _, _, _, _))
+ .WillByDefault(RunOnceCallback<4>(OkClientStatus()));
+
+ ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
+ .WillByDefault(
+ RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{
+ WebsiteLoginFetcher::Login(GURL(kFakeUrl), kFakeUsername)}));
+ ON_CALL(mock_website_login_fetcher_, OnGetPasswordForLogin(_, _))
+ .WillByDefault(RunOnceCallback<1>(true, kFakePassword));
+ client_memory_.set_selected_login({GURL(kFakeUrl), kFakeUsername});
+ fake_selector_ = Selector({kFakeSelector}).MustBeVisible();
+ }
+
+ protected:
+ Selector fake_selector_;
+ MockActionDelegate mock_action_delegate_;
+ MockWebsiteLoginFetcher mock_website_login_fetcher_;
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ ActionProto proto_;
+ SetFormFieldValueProto* set_form_field_proto_;
+ ClientMemory client_memory_;
+};
+
+TEST_F(SetFormFieldValueActionTest, RequestedUsernameButNoLoginInClientMemory) {
+ ClientMemory empty_client_memory;
+ ON_CALL(mock_action_delegate_, GetClientMemory)
+ .WillByDefault(Return(&empty_client_memory));
+ auto* value = set_form_field_proto_->add_value();
+ value->set_use_username(true);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ PRECONDITION_FAILED))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, RequestedPasswordButNoLoginInClientMemory) {
+ ClientMemory empty_client_memory;
+ ON_CALL(mock_action_delegate_, GetClientMemory)
+ .WillByDefault(Return(&empty_client_memory));
+ auto* value = set_form_field_proto_->add_value();
+ value->set_use_password(true);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ PRECONDITION_FAILED))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, RequestedPasswordButPasswordNotAvailable) {
+ ON_CALL(mock_website_login_fetcher_, OnGetPasswordForLogin(_, _))
+ .WillByDefault(RunOnceCallback<1>(false, std::string()));
+ auto* value = set_form_field_proto_->add_value();
+ value->set_use_password(true);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ AUTOFILL_INFO_NOT_AVAILABLE))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, NonAsciiKeycode) {
+ auto* value = set_form_field_proto_->add_value();
+ value->set_keycode(UTF8ToUnicode("𠜎")[0]);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, Username) {
+ auto* value = set_form_field_proto_->add_value();
+ value->set_use_username(true);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ ON_CALL(mock_action_delegate_, OnGetFieldValue(_, _))
+ .WillByDefault(RunOnceCallback<1>(true, kFakeUsername));
+ EXPECT_CALL(mock_action_delegate_,
+ OnSetFieldValue(fake_selector_, kFakeUsername, _, _, _))
+ .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, Password) {
+ auto* value = set_form_field_proto_->add_value();
+ value->set_use_password(true);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ ON_CALL(mock_action_delegate_, OnGetFieldValue(_, _))
+ .WillByDefault(RunOnceCallback<1>(true, kFakePassword));
+ EXPECT_CALL(mock_action_delegate_,
+ OnSetFieldValue(fake_selector_, kFakePassword, _, _, _))
+ .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, Keycode) {
+ auto* value = set_form_field_proto_->add_value();
+ value->set_keycode(13); // carriage return
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ EXPECT_CALL(mock_action_delegate_,
+ OnSendKeyboardInput(fake_selector_, std::vector<int>{13}, _, _))
+ .WillOnce(RunOnceCallback<3>(OkClientStatus()));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, KeyboardInput) {
+ auto* value = set_form_field_proto_->add_value();
+ std::string keyboard_input = "SomeQuery𠜎\r";
+ value->set_keyboard_input(keyboard_input);
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ EXPECT_CALL(
+ mock_action_delegate_,
+ OnSendKeyboardInput(fake_selector_, UTF8ToUnicode(keyboard_input), _, _))
+ .WillOnce(RunOnceCallback<3>(OkClientStatus()));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ action.ProcessAction(callback_.Get());
+}
+
+TEST_F(SetFormFieldValueActionTest, Text) {
+ auto* value = set_form_field_proto_->add_value();
+ value->set_text("SomeText𠜎");
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+ ON_CALL(mock_action_delegate_, OnGetFieldValue(_, _))
+ .WillByDefault(RunOnceCallback<1>(true, "SomeText𠜎"));
+ EXPECT_CALL(mock_action_delegate_,
+ OnSetFieldValue(fake_selector_, "SomeText𠜎", _, _, _))
+ .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ action.ProcessAction(callback_.Get());
+}
+
+// Test that automatic fallback to simulate keystrokes works.
+TEST_F(SetFormFieldValueActionTest, Fallback) {
+ auto* value = set_form_field_proto_->add_value();
+ value->set_text("123");
+ SetFormFieldValueAction action(&mock_action_delegate_, proto_);
+
+ ON_CALL(mock_action_delegate_, OnGetFieldValue(_, _))
+ .WillByDefault(RunOnceCallback<1>(true, ""));
+
+ {
+ InSequence seq;
+ EXPECT_CALL(mock_action_delegate_,
+ OnSetFieldValue(fake_selector_, "123",
+ /* simulate_key_presses = */ false, _, _));
+ EXPECT_CALL(mock_action_delegate_,
+ OnSetFieldValue(fake_selector_, "123",
+ /* simulate_key_presses = */ true, _, _));
+ }
+
+ EXPECT_CALL(callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::set_form_field_value_result,
+ Property(&SetFormFieldValueProto::Result::
+ fallback_to_simulate_key_presses,
+ true))))));
+
+ action.ProcessAction(callback_.Get());
+}
+
+} // namespace
+} // namespace autofill_assistant \ No newline at end of file
diff --git a/chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc
new file mode 100644
index 00000000000..ba827814ea9
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/show_details_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/geo/country_names.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/client_memory.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Property;
+using ::testing::Return;
+
+class ShowDetailsActionTest : public testing::Test {
+ public:
+ ShowDetailsActionTest() {}
+
+ void SetUp() override {
+ autofill::CountryNames::SetLocaleString("us-en");
+
+ ON_CALL(mock_action_delegate_, GetClientMemory())
+ .WillByDefault(Return(&client_memory_));
+ ON_CALL(mock_action_delegate_, SetDetails(_)).WillByDefault(Return());
+ }
+
+ protected:
+ void Run() {
+ ActionProto action_proto;
+ *action_proto.mutable_show_details() = proto_;
+ ShowDetailsAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+ }
+
+ std::unique_ptr<autofill::CreditCard> MakeCreditCard() {
+ return std::make_unique<autofill::CreditCard>();
+ }
+
+ std::unique_ptr<autofill::AutofillProfile> MakeAutofillProfile() {
+ auto profile = std::make_unique<autofill::AutofillProfile>();
+ autofill::test::SetProfileInfo(profile.get(), "Charles", "Hardin", "Holley",
+ "buddy@gmail.com", "Decca", "123 Apple St.",
+ "unit 6", "Lubbock", "Texas", "79401", "US",
+ "23456789012");
+ return profile;
+ }
+
+ ClientMemory client_memory_;
+ MockActionDelegate mock_action_delegate_;
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ ShowDetailsProto proto_;
+};
+
+TEST_F(ShowDetailsActionTest, EmptyIsValid) {
+ EXPECT_CALL(mock_action_delegate_, SetDetails(_));
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ Run();
+}
+
+TEST_F(ShowDetailsActionTest, DetailsCase) {
+ proto_.mutable_details();
+
+ EXPECT_CALL(mock_action_delegate_, SetDetails(_));
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ Run();
+}
+
+TEST_F(ShowDetailsActionTest, ContactDetailsCase) {
+ proto_.set_contact_details("contact");
+ client_memory_.set_selected_address("contact", MakeAutofillProfile());
+
+ EXPECT_CALL(mock_action_delegate_, SetDetails(_));
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ Run();
+}
+
+TEST_F(ShowDetailsActionTest, ShippingAddressCase) {
+ proto_.set_shipping_address("shipping");
+ client_memory_.set_selected_address("shipping", MakeAutofillProfile());
+
+ EXPECT_CALL(mock_action_delegate_, SetDetails(_));
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ Run();
+}
+
+TEST_F(ShowDetailsActionTest, CreditCardCase) {
+ proto_.set_credit_card(true);
+ client_memory_.set_selected_card(MakeCreditCard());
+
+ EXPECT_CALL(mock_action_delegate_, SetDetails(_));
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ Run();
+}
+
+TEST_F(ShowDetailsActionTest, CreditCardRequestedButNotAvailable) {
+ proto_.set_credit_card(true);
+ EXPECT_CALL(mock_action_delegate_, SetDetails(_)).Times(0);
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+ Run();
+}
+
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/show_form_action.cc b/chromium/components/autofill_assistant/browser/actions/show_form_action.cc
index 5c4f5db0512..62f26a66473 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_form_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/show_form_action.cc
@@ -17,7 +17,7 @@ namespace autofill_assistant {
ShowFormAction::ShowFormAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_show_form() && proto_.show_form().has_form());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/show_form_action.h b/chromium/components/autofill_assistant/browser/actions/show_form_action.h
index 34bfb018063..fc6e0fc2a5f 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_form_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/show_form_action.h
@@ -37,7 +37,7 @@ class ShowFormAction : public Action {
const SelectionInputProto::Result& result);
ProcessActionCallback callback_;
- base::WeakPtrFactory<ShowFormAction> weak_ptr_factory_;
+ base::WeakPtrFactory<ShowFormAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ShowFormAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/upload_dom_action.cc b/chromium/components/autofill_assistant/browser/actions/upload_dom_action.cc
index 46ceb80b697..a339b62eb84 100644
--- a/chromium/components/autofill_assistant/browser/actions/upload_dom_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/upload_dom_action.cc
@@ -15,7 +15,7 @@ namespace autofill_assistant {
UploadDomAction::UploadDomAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_upload_dom());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/upload_dom_action.h b/chromium/components/autofill_assistant/browser/actions/upload_dom_action.h
index 5346e0b4bb9..1d757f74f62 100644
--- a/chromium/components/autofill_assistant/browser/actions/upload_dom_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/upload_dom_action.h
@@ -29,7 +29,7 @@ class UploadDomAction : public Action {
const ClientStatus& status,
const std::string& outer_html);
- base::WeakPtrFactory<UploadDomAction> weak_ptr_factory_;
+ base::WeakPtrFactory<UploadDomAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(UploadDomAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc
index 467e36c176a..db02dac65cf 100644
--- a/chromium/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc
@@ -11,7 +11,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -33,7 +33,7 @@ using ::testing::SizeIs;
class WaitForDocumentActionTest : public testing::Test {
public:
WaitForDocumentActionTest()
- : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ : task_env_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
ON_CALL(mock_action_delegate_, OnWaitForDocumentReadyState(_, _, _))
@@ -61,7 +61,7 @@ class WaitForDocumentActionTest : public testing::Test {
protected:
// task_env_ must be first to guarantee other field
// creation run in that environment.
- base::test::ScopedTaskEnvironment task_env_;
+ base::test::TaskEnvironment task_env_;
MockActionDelegate mock_action_delegate_;
WaitForDocumentProto proto_;
diff --git a/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.cc b/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
index d04ab32f04f..7fdc7791df5 100644
--- a/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
@@ -22,7 +22,7 @@ namespace autofill_assistant {
WaitForDomAction::WaitForDomAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {}
+ : Action(delegate, proto) {}
WaitForDomAction::~WaitForDomAction() {}
diff --git a/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.h b/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.h
index dad8ed517d1..d56fa4c6191 100644
--- a/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action.h
@@ -74,7 +74,7 @@ class WaitForDomAction : public Action {
bool require_all_ = false;
std::vector<Condition> conditions_;
- base::WeakPtrFactory<WaitForDomAction> weak_ptr_factory_;
+ base::WeakPtrFactory<WaitForDomAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WaitForDomAction);
};
diff --git a/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action_unittest.cc
index 152a5b44a40..15426de05de 100644
--- a/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/wait_for_dom_action_unittest.cc
@@ -11,7 +11,7 @@
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
diff --git a/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.cc b/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.cc
index 6cf1918b152..f23519a09fb 100644
--- a/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.cc
@@ -13,7 +13,7 @@ namespace autofill_assistant {
WaitForNavigationAction::WaitForNavigationAction(ActionDelegate* delegate,
const ActionProto& proto)
- : Action(delegate, proto), weak_ptr_factory_(this) {
+ : Action(delegate, proto) {
DCHECK(proto_.has_wait_for_navigation());
}
diff --git a/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.h b/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.h
index 1515c464baa..db1535d408b 100644
--- a/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.h
@@ -34,7 +34,7 @@ class WaitForNavigationAction : public Action {
ProcessActionCallback callback_;
base::OneShotTimer timer_;
- base::WeakPtrFactory<WaitForNavigationAction> weak_ptr_factory_;
+ base::WeakPtrFactory<WaitForNavigationAction> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WaitForNavigationAction);
};
diff --git a/chromium/components/autofill_assistant/browser/batch_element_checker.cc b/chromium/components/autofill_assistant/browser/batch_element_checker.cc
index ef03a1c0af9..4cdad7c760c 100644
--- a/chromium/components/autofill_assistant/browser/batch_element_checker.cc
+++ b/chromium/components/autofill_assistant/browser/batch_element_checker.cc
@@ -10,11 +10,11 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
namespace autofill_assistant {
-BatchElementChecker::BatchElementChecker() : weak_ptr_factory_(this) {}
+BatchElementChecker::BatchElementChecker() {}
BatchElementChecker::~BatchElementChecker() {}
diff --git a/chromium/components/autofill_assistant/browser/batch_element_checker.h b/chromium/components/autofill_assistant/browser/batch_element_checker.h
index dabe7ee173d..9cf893626ee 100644
--- a/chromium/components/autofill_assistant/browser/batch_element_checker.h
+++ b/chromium/components/autofill_assistant/browser/batch_element_checker.h
@@ -40,7 +40,7 @@ class BatchElementChecker {
using GetFieldValueCallback =
base::OnceCallback<void(bool, const std::string&)>;
- // Checks an an element.
+ // Checks an element.
//
// New element checks cannot be added once Run has been called.
void AddElementCheck(const Selector& selector, ElementCheckCallback callback);
@@ -90,7 +90,7 @@ class BatchElementChecker {
std::vector<base::OnceCallback<void()>> all_done_;
- base::WeakPtrFactory<BatchElementChecker> weak_ptr_factory_;
+ base::WeakPtrFactory<BatchElementChecker> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(BatchElementChecker);
};
diff --git a/chromium/components/autofill_assistant/browser/batch_element_checker_unittest.cc b/chromium/components/autofill_assistant/browser/batch_element_checker_unittest.cc
index 5523c71018d..37695c241c5 100644
--- a/chromium/components/autofill_assistant/browser/batch_element_checker_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/batch_element_checker_unittest.cc
@@ -11,8 +11,8 @@
#include "base/bind_helpers.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
+#include "base/test/task_environment.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::base::test::RunOnceCallback;
diff --git a/chromium/components/autofill_assistant/browser/client.h b/chromium/components/autofill_assistant/browser/client.h
index f71247f0d52..8e372fd1e7a 100644
--- a/chromium/components/autofill_assistant/browser/client.h
+++ b/chromium/components/autofill_assistant/browser/client.h
@@ -15,6 +15,7 @@ class PersonalDataManager;
namespace autofill_assistant {
class AccessTokenFetcher;
+class WebsiteLoginFetcher;
// A client interface that needs to be supplied to the controller by the
// embedder.
@@ -44,6 +45,9 @@ class Client {
// Returns the current active personal data manager.
virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0;
+ // Returns the currently active login fetcher.
+ virtual WebsiteLoginFetcher* GetWebsiteLoginFetcher() = 0;
+
// Returns the server URL to be used for requests to the backend.
virtual std::string GetServerUrl() = 0;
diff --git a/chromium/components/autofill_assistant/browser/client_memory.cc b/chromium/components/autofill_assistant/browser/client_memory.cc
index ddfa6fd0d7b..2f7dfcdebb1 100644
--- a/chromium/components/autofill_assistant/browser/client_memory.cc
+++ b/chromium/components/autofill_assistant/browser/client_memory.cc
@@ -10,23 +10,24 @@
namespace autofill_assistant {
-ClientMemory::ClientMemory() = default;
-ClientMemory::~ClientMemory() = default;
+ClientMemory::ClientMemory() {}
+ClientMemory::~ClientMemory() {}
-const autofill::CreditCard* ClientMemory::selected_card() {
+const autofill::CreditCard* ClientMemory::selected_card() const {
if (selected_card_.has_value())
return selected_card_->get();
return nullptr;
}
-bool ClientMemory::has_selected_card() {
+bool ClientMemory::has_selected_card() const {
return selected_card_.has_value();
}
const autofill::AutofillProfile* ClientMemory::selected_address(
- const std::string& name) {
- if (selected_addresses_.find(name) != selected_addresses_.end())
- return selected_addresses_[name].get();
+ const std::string& name) const {
+ auto it = selected_addresses_.find(name);
+ if (it != selected_addresses_.end())
+ return it->second.get();
return nullptr;
}
@@ -42,10 +43,25 @@ void ClientMemory::set_selected_address(
selected_addresses_[name] = std::move(address);
}
-bool ClientMemory::has_selected_address(const std::string& name) {
+bool ClientMemory::has_selected_address(const std::string& name) const {
return selected_addresses_.find(name) != selected_addresses_.end();
}
+void ClientMemory::set_selected_login(const WebsiteLoginFetcher::Login& login) {
+ selected_login_ = login;
+}
+
+bool ClientMemory::has_selected_login() const {
+ return selected_login_.has_value();
+}
+
+const WebsiteLoginFetcher::Login* ClientMemory::selected_login() const {
+ if (selected_login_.has_value()) {
+ return &(*selected_login_);
+ }
+ return nullptr;
+}
+
std::string ClientMemory::GetAllAddressKeyNames() const {
std::vector<std::string> entries;
for (const auto& entry : selected_addresses_) {
diff --git a/chromium/components/autofill_assistant/browser/client_memory.h b/chromium/components/autofill_assistant/browser/client_memory.h
index 1175e9bf418..ee24fb35d0a 100644
--- a/chromium/components/autofill_assistant/browser/client_memory.h
+++ b/chromium/components/autofill_assistant/browser/client_memory.h
@@ -11,45 +11,55 @@
#include "base/optional.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill_assistant/browser/website_login_fetcher.h"
namespace autofill_assistant {
// Data shared between scripts and actions.
class ClientMemory {
public:
ClientMemory();
- virtual ~ClientMemory();
+ ~ClientMemory();
// Selected credit card, if any. It will be a nullptr if didn't select
// anything or if selected 'Fill manually'.
- virtual const autofill::CreditCard* selected_card();
+ const autofill::CreditCard* selected_card() const;
// Return true if card has been selected, otherwise return false.
// Note that selected_card() might return nullptr when has_selected_card() is
// true because fill manually was chosen.
- virtual bool has_selected_card();
+ bool has_selected_card() const;
// Selected address for |name|. It will be a nullptr if didn't select anything
// or if selected 'Fill manually'.
- virtual const autofill::AutofillProfile* selected_address(
- const std::string& name);
+ const autofill::AutofillProfile* selected_address(
+ const std::string& name) const;
// Return true if address has been selected, otherwise return false.
// Note that selected_address() might return nullptr when
// has_selected_address() is true because fill manually was chosen.
- virtual bool has_selected_address(const std::string& name);
+ bool has_selected_address(const std::string& name) const;
// Set the selected card.
- virtual void set_selected_card(std::unique_ptr<autofill::CreditCard> card);
+ void set_selected_card(std::unique_ptr<autofill::CreditCard> card);
// Set the selected address for |name|.
- virtual void set_selected_address(
- const std::string& name,
- std::unique_ptr<autofill::AutofillProfile> address);
+ void set_selected_address(const std::string& name,
+ std::unique_ptr<autofill::AutofillProfile> address);
- virtual std::string GetAllAddressKeyNames() const;
+ // Set the selected login.
+ void set_selected_login(const WebsiteLoginFetcher::Login& login);
+
+ // Return true if a login has been selected, otherwise false.
+ bool has_selected_login() const;
+
+ // The selected login or nullptr if no login was selected.
+ const WebsiteLoginFetcher::Login* selected_login() const;
+
+ std::string GetAllAddressKeyNames() const;
private:
base::Optional<std::unique_ptr<autofill::CreditCard>> selected_card_;
+ base::Optional<WebsiteLoginFetcher::Login> selected_login_;
// The address key requested by the autofill action.
std::map<std::string, std::unique_ptr<autofill::AutofillProfile>>
diff --git a/chromium/components/autofill_assistant/browser/client_settings.cc b/chromium/components/autofill_assistant/browser/client_settings.cc
index 81d8f2909f3..f375b67fdbd 100644
--- a/chromium/components/autofill_assistant/browser/client_settings.cc
+++ b/chromium/components/autofill_assistant/browser/client_settings.cc
@@ -44,6 +44,27 @@ void ClientSettings::UpdateFromProto(const ClientSettingsProto& proto) {
if (proto.has_document_ready_check_count()) {
document_ready_check_count = proto.document_ready_check_count();
}
+ if (proto.has_enable_graceful_shutdown()) {
+ enable_graceful_shutdown = proto.enable_graceful_shutdown();
+ }
+ if (proto.has_graceful_shutdown_delay_ms()) {
+ graceful_shutdown_delay =
+ base::TimeDelta::FromMilliseconds(proto.graceful_shutdown_delay_ms());
+ }
+ if (proto.has_cancel_delay_ms()) {
+ cancel_delay = base::TimeDelta::FromMilliseconds(proto.cancel_delay_ms());
+ }
+ if (proto.has_tap_count()) {
+ tap_count = proto.tap_count();
+ }
+ if (proto.has_tap_tracking_duration_ms()) {
+ tap_tracking_duration =
+ base::TimeDelta::FromMilliseconds(proto.tap_tracking_duration_ms());
+ }
+ if (proto.has_tap_shutdown_delay_ms()) {
+ tap_shutdown_delay =
+ base::TimeDelta::FromMilliseconds(proto.tap_shutdown_delay_ms());
+ }
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/client_settings.h b/chromium/components/autofill_assistant/browser/client_settings.h
index 0aaae220f5f..f007b58db5c 100644
--- a/chromium/components/autofill_assistant/browser/client_settings.h
+++ b/chromium/components/autofill_assistant/browser/client_settings.h
@@ -61,6 +61,29 @@ struct ClientSettings {
// ready.
int document_ready_check_count = 50;
+ // Whether graceful shutdown should be enabled. If false, the UI stays
+ // up until it's dismissed.
+ bool enable_graceful_shutdown = true;
+
+ // How long to wait before shutting down during graceful shutdown. If 0
+ // shutdown happens immediately.
+ base::TimeDelta graceful_shutdown_delay = base::TimeDelta::FromSeconds(5);
+
+ // How much time to give users to tap undo when they tap a cancel button.
+ base::TimeDelta cancel_delay = base::TimeDelta::FromSeconds(5);
+
+ // If the user taps the overlay that many time within |tap_duration| turn the
+ // UI off and give them |tap_shutdown_delay| to undo. If 0, unexpected taps
+ // are ignored.
+ int tap_count = 3;
+
+ // Reset the unexpected tap counter after that time.
+ base::TimeDelta tap_tracking_duration = base::TimeDelta::FromSeconds(5);
+
+ // How much time to give users to tap undo when after |tap_count| unexpected
+ // taps where
+ base::TimeDelta tap_shutdown_delay = base::TimeDelta::FromSeconds(5);
+
void UpdateFromProto(const ClientSettingsProto& proto);
private:
diff --git a/chromium/components/autofill_assistant/browser/client_status.cc b/chromium/components/autofill_assistant/browser/client_status.cc
index da69a37a193..6ee79da9bef 100644
--- a/chromium/components/autofill_assistant/browser/client_status.cc
+++ b/chromium/components/autofill_assistant/browser/client_status.cc
@@ -62,8 +62,8 @@ std::ostream& operator<<(std::ostream& out,
case ProcessedActionStatusProto::OTHER_ACTION_STATUS:
out << "OTHER_ACTION_STATUS";
break;
- case ProcessedActionStatusProto::PAYMENT_REQUEST_ERROR:
- out << "PAYMENT_REQUEST_ERROR";
+ case ProcessedActionStatusProto::COLLECT_USER_DATA_ERROR:
+ out << "COLLECT_USER_DATA_ERROR";
break;
case ProcessedActionStatusProto::UNSUPPORTED_ACTION:
out << "UNSUPPORTED_ACTION";
@@ -122,6 +122,10 @@ std::ostream& operator<<(std::ostream& out,
out << "NAVIGATION_ERROR";
break;
+ case ProcessedActionStatusProto::AUTOFILL_INFO_NOT_AVAILABLE:
+ out << "AUTOFILL_INFO_NOT_AVAILABLE";
+ break;
+
// Intentionally no default case to make compilation fail if a new value
// was added to the enum but not to this list.
}
diff --git a/chromium/components/autofill_assistant/browser/controller.cc b/chromium/components/autofill_assistant/browser/controller.cc
index 764236a9307..d1343ff116a 100644
--- a/chromium/components/autofill_assistant/browser/controller.cc
+++ b/chromium/components/autofill_assistant/browser/controller.cc
@@ -15,6 +15,7 @@
#include "base/task/post_task.h"
#include "base/time/tick_clock.h"
#include "base/values.h"
+#include "components/autofill_assistant/browser/actions/collect_user_data_action.h"
#include "components/autofill_assistant/browser/controller_observer.h"
#include "components/autofill_assistant/browser/features.h"
#include "components/autofill_assistant/browser/metrics.h"
@@ -96,8 +97,7 @@ Controller::Controller(content::WebContents* web_contents,
service_(service ? std::move(service)
: ServiceImpl::Create(web_contents->GetBrowserContext(),
client_)),
- navigating_to_new_document_(web_contents->IsWaitingForResponse()),
- weak_ptr_factory_(this) {}
+ navigating_to_new_document_(web_contents->IsWaitingForResponse()) {}
Controller::~Controller() = default;
@@ -145,10 +145,18 @@ autofill::PersonalDataManager* Controller::GetPersonalDataManager() {
return client_->GetPersonalDataManager();
}
+WebsiteLoginFetcher* Controller::GetWebsiteLoginFetcher() {
+ return client_->GetWebsiteLoginFetcher();
+}
+
content::WebContents* Controller::GetWebContents() {
return web_contents();
}
+std::string Controller::GetAccountEmailAddress() {
+ return client_->GetAccountEmailAddress();
+}
+
void Controller::SetTouchableElementArea(const ElementAreaProto& area) {
touchable_element_area()->SetFromProto(area);
}
@@ -468,6 +476,10 @@ void Controller::GetOverlayColors(OverlayColors* colors) const {
*colors = *overlay_colors_;
}
+const ClientSettings& Controller::GetClientSettings() const {
+ return settings_;
+}
+
void Controller::ReportNavigationStateChanged() {
// Listeners are called in the same order they were added.
for (auto* listener : listeners_) {
@@ -482,7 +494,7 @@ void Controller::EnterStoppedState() {
ClearInfoBox();
SetDetails(nullptr);
SetUserActions(nullptr);
- SetPaymentRequestOptions(nullptr);
+ SetCollectUserDataOptions(nullptr, nullptr);
EnterState(AutofillAssistantState::STOPPED);
}
@@ -563,11 +575,10 @@ void Controller::StartPeriodicScriptChecks() {
if (periodic_script_check_scheduled_)
return;
periodic_script_check_scheduled_ = true;
- base::PostDelayedTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&Controller::OnPeriodicScriptCheck,
- weak_ptr_factory_.GetWeakPtr()),
- settings_.periodic_script_check_interval);
+ base::PostDelayedTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&Controller::OnPeriodicScriptCheck,
+ weak_ptr_factory_.GetWeakPtr()),
+ settings_.periodic_script_check_interval);
}
void Controller::StopPeriodicScriptChecks() {
@@ -597,11 +608,10 @@ void Controller::OnPeriodicScriptCheck() {
}
script_tracker()->CheckScripts();
- base::PostDelayedTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&Controller::OnPeriodicScriptCheck,
- weak_ptr_factory_.GetWeakPtr()),
- settings_.periodic_script_check_interval);
+ base::PostDelayedTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&Controller::OnPeriodicScriptCheck,
+ weak_ptr_factory_.GetWeakPtr()),
+ settings_.periodic_script_check_interval);
}
void Controller::OnGetScripts(const GURL& url,
@@ -630,8 +640,12 @@ void Controller::OnGetScripts(const GURL& url,
Metrics::DropOutReason::GET_SCRIPTS_UNPARSABLE);
return;
}
- if (response_proto.has_client_settings())
+ if (response_proto.has_client_settings()) {
settings_.UpdateFromProto(response_proto.client_settings());
+ for (ControllerObserver& observer : observers_) {
+ observer.OnClientSettingsChanged(settings_);
+ }
+ }
std::vector<std::unique_ptr<Script>> scripts;
for (const auto& script_proto : response_proto.scripts()) {
@@ -911,154 +925,138 @@ std::string Controller::GetDebugContext() {
return output_js;
}
-const PaymentRequestOptions* Controller::GetPaymentRequestOptions() const {
- return payment_request_options_.get();
+const CollectUserDataOptions* Controller::GetCollectUserDataOptions() const {
+ return collect_user_data_options_.get();
}
-const PaymentInformation* Controller::GetPaymentRequestInformation() const {
- return payment_request_info_.get();
+const UserData* Controller::GetUserData() const {
+ return user_data_.get();
}
-void Controller::OnPaymentRequestContinueButtonClicked() {
- if (!payment_request_options_ || !payment_request_info_)
+void Controller::OnCollectUserDataContinueButtonClicked() {
+ if (!collect_user_data_options_ || !user_data_)
return;
- auto callback = std::move(payment_request_options_->confirm_callback);
- auto payment_request_info = std::move(payment_request_info_);
+ auto callback = std::move(collect_user_data_options_->confirm_callback);
+ auto user_data = std::move(user_data_);
// TODO(crbug.com/806868): succeed is currently always true, but we might want
- // to set it to false and propagate the result to GetPaymentInformationAction
+ // to set it to false and propagate the result to CollectUserDataAction
// when the user clicks "Cancel" during that action.
- payment_request_info->succeed = true;
+ user_data->succeed = true;
- SetPaymentRequestOptions(nullptr);
- std::move(callback).Run(std::move(payment_request_info));
+ SetCollectUserDataOptions(nullptr, nullptr);
+ std::move(callback).Run(std::move(user_data));
}
-void Controller::OnPaymentRequestAdditionalActionTriggered(int index) {
- if (!payment_request_options_)
+void Controller::OnCollectUserDataAdditionalActionTriggered(int index) {
+ if (!collect_user_data_options_)
return;
auto callback =
- std::move(payment_request_options_->additional_actions_callback);
- SetPaymentRequestOptions(nullptr);
+ std::move(collect_user_data_options_->additional_actions_callback);
+ SetCollectUserDataOptions(nullptr, nullptr);
std::move(callback).Run(index);
}
void Controller::OnTermsAndConditionsLinkClicked(int link) {
- if (!payment_request_info_)
+ if (!user_data_)
return;
- auto callback = std::move(payment_request_options_->terms_link_callback);
- SetPaymentRequestOptions(nullptr);
+ auto callback = std::move(collect_user_data_options_->terms_link_callback);
+ SetCollectUserDataOptions(nullptr, nullptr);
std::move(callback).Run(link);
}
void Controller::SetShippingAddress(
std::unique_ptr<autofill::AutofillProfile> address) {
- if (!payment_request_info_)
+ if (!user_data_)
return;
- payment_request_info_->shipping_address = std::move(address);
+ user_data_->shipping_address = std::move(address);
for (ControllerObserver& observer : observers_) {
- observer.OnPaymentRequestInformationChanged(payment_request_info_.get());
+ observer.OnUserDataChanged(user_data_.get());
}
- UpdatePaymentRequestActions();
+ UpdateCollectUserDataActions();
}
-void Controller::SetBillingAddress(
- std::unique_ptr<autofill::AutofillProfile> address) {
- if (!payment_request_info_)
+void Controller::SetContactInfo(
+ std::unique_ptr<autofill::AutofillProfile> profile) {
+ if (!user_data_)
return;
- payment_request_info_->billing_address = std::move(address);
+ user_data_->contact_profile = std::move(profile);
for (ControllerObserver& observer : observers_) {
- observer.OnPaymentRequestInformationChanged(payment_request_info_.get());
+ observer.OnUserDataChanged(user_data_.get());
}
- UpdatePaymentRequestActions();
+ UpdateCollectUserDataActions();
}
-void Controller::SetContactInfo(std::string name,
- std::string phone,
- std::string email) {
- if (!payment_request_info_)
+void Controller::SetCreditCard(std::unique_ptr<autofill::CreditCard> card) {
+ if (!user_data_)
return;
- payment_request_info_->payer_name = name;
- payment_request_info_->payer_phone = phone;
- payment_request_info_->payer_email = email;
+ autofill::AutofillProfile* billing_profile =
+ !card || card->billing_address_id().empty()
+ ? nullptr
+ : GetPersonalDataManager()->GetProfileByGUID(
+ card->billing_address_id());
+ if (billing_profile) {
+ auto billing_address =
+ std::make_unique<autofill::AutofillProfile>(*billing_profile);
+ user_data_->billing_address = std::move(billing_address);
+ } else {
+ user_data_->billing_address.reset();
+ }
+
+ user_data_->card = std::move(card);
for (ControllerObserver& observer : observers_) {
- observer.OnPaymentRequestInformationChanged(payment_request_info_.get());
+ observer.OnUserDataChanged(user_data_.get());
}
- UpdatePaymentRequestActions();
+ UpdateCollectUserDataActions();
}
-void Controller::SetCreditCard(std::unique_ptr<autofill::CreditCard> card) {
- if (!payment_request_info_)
+void Controller::SetTermsAndConditions(
+ TermsAndConditionsState terms_and_conditions) {
+ if (!user_data_)
return;
- payment_request_info_->card = std::move(card);
+ user_data_->terms_and_conditions = terms_and_conditions;
+ UpdateCollectUserDataActions();
for (ControllerObserver& observer : observers_) {
- observer.OnPaymentRequestInformationChanged(payment_request_info_.get());
+ observer.OnUserDataChanged(user_data_.get());
}
- UpdatePaymentRequestActions();
}
-void Controller::SetTermsAndConditions(
- TermsAndConditionsState terms_and_conditions) {
- if (!payment_request_info_)
+void Controller::SetLoginOption(std::string identifier) {
+ if (!user_data_ || !collect_user_data_options_)
return;
- payment_request_info_->terms_and_conditions = terms_and_conditions;
- UpdatePaymentRequestActions();
+ user_data_->login_choice_identifier.assign(identifier);
+ UpdateCollectUserDataActions();
for (ControllerObserver& observer : observers_) {
- observer.OnPaymentRequestInformationChanged(payment_request_info_.get());
+ observer.OnUserDataChanged(user_data_.get());
}
}
-void Controller::UpdatePaymentRequestActions() {
+void Controller::UpdateCollectUserDataActions() {
// TODO(crbug.com/806868): This method uses #SetUserActions(), which means
// that updating the PR action buttons will also clear the suggestions. We
// should update the action buttons only if there are use cases of PR +
// suggestions.
- if (!payment_request_options_ || !payment_request_info_) {
+ if (!collect_user_data_options_ || !user_data_) {
SetUserActions(nullptr);
return;
}
- bool contact_info_ok = (!payment_request_options_->request_payer_name ||
- !payment_request_info_->payer_name.empty()) &&
- (!payment_request_options_->request_payer_email ||
- !payment_request_info_->payer_email.empty()) &&
- (!payment_request_options_->request_payer_phone ||
- !payment_request_info_->payer_phone.empty());
-
- bool shipping_address_ok = !payment_request_options_->request_shipping ||
- payment_request_info_->shipping_address;
+ bool confirm_button_enabled = CollectUserDataAction::IsUserDataComplete(
+ GetPersonalDataManager(), *user_data_, *collect_user_data_options_);
- bool payment_method_ok = !payment_request_options_->request_payment_method ||
- payment_request_info_->card;
-
- bool billing_address_ok =
- !payment_request_options_->require_billing_postal_code ||
- (payment_request_info_->billing_address &&
- !payment_request_info_->billing_address
- ->GetRawInfo(autofill::ADDRESS_HOME_ZIP)
- .empty());
-
- bool terms_ok =
- payment_request_info_->terms_and_conditions != NOT_SELECTED ||
- payment_request_options_->accept_terms_and_conditions_text.empty();
-
- bool confirm_button_enabled = contact_info_ok && shipping_address_ok &&
- payment_method_ok && billing_address_ok &&
- terms_ok;
-
- UserAction confirm(payment_request_options_->confirm_action);
+ UserAction confirm(collect_user_data_options_->confirm_action);
confirm.SetEnabled(confirm_button_enabled);
if (confirm_button_enabled) {
confirm.SetCallback(
- base::BindOnce(&Controller::OnPaymentRequestContinueButtonClicked,
+ base::BindOnce(&Controller::OnCollectUserDataContinueButtonClicked,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -1066,12 +1064,12 @@ void Controller::UpdatePaymentRequestActions() {
user_actions->emplace_back(std::move(confirm));
// Add additional actions.
- for (size_t i = 0; i < payment_request_options_->additional_actions.size();
+ for (size_t i = 0; i < collect_user_data_options_->additional_actions.size();
++i) {
- auto action = payment_request_options_->additional_actions[i];
+ auto action = collect_user_data_options_->additional_actions[i];
user_actions->push_back({action.chip(), action.direct_action()});
user_actions->back().SetCallback(
- base::BindOnce(&Controller::OnPaymentRequestAdditionalActionTriggered,
+ base::BindOnce(&Controller::OnCollectUserDataAdditionalActionTriggered,
weak_ptr_factory_.GetWeakPtr(), i));
}
@@ -1345,28 +1343,22 @@ void Controller::OnTouchableAreaChanged(
}
}
-void Controller::SetPaymentRequestOptions(
- std::unique_ptr<PaymentRequestOptions> options) {
+void Controller::SetCollectUserDataOptions(
+ std::unique_ptr<CollectUserDataOptions> options,
+ std::unique_ptr<UserData> information) {
DCHECK(!options ||
(options->confirm_callback && options->additional_actions_callback &&
options->terms_link_callback));
- if (payment_request_options_ == nullptr && options == nullptr)
+ if (collect_user_data_options_ == nullptr && options == nullptr)
return;
- if (options) {
- payment_request_info_ = std::make_unique<PaymentInformation>();
-
- // TODO(crbug.com/806868): set initial state according to proto.
- payment_request_info_->terms_and_conditions =
- options->initial_terms_and_conditions;
- }
-
- payment_request_options_ = std::move(options);
- UpdatePaymentRequestActions();
+ collect_user_data_options_ = std::move(options);
+ user_data_ = std::move(information);
+ UpdateCollectUserDataActions();
for (ControllerObserver& observer : observers_) {
- observer.OnPaymentRequestOptionsChanged(payment_request_options_.get());
- observer.OnPaymentRequestInformationChanged(payment_request_info_.get());
+ observer.OnCollectUserDataOptionsChanged(collect_user_data_options_.get());
+ observer.OnUserDataChanged(user_data_.get());
}
}
diff --git a/chromium/components/autofill_assistant/browser/controller.h b/chromium/components/autofill_assistant/browser/controller.h
index a6a32bcedbe..a7777502fb3 100644
--- a/chromium/components/autofill_assistant/browser/controller.h
+++ b/chromium/components/autofill_assistant/browser/controller.h
@@ -17,7 +17,6 @@
#include "components/autofill_assistant/browser/client_settings.h"
#include "components/autofill_assistant/browser/element_area.h"
#include "components/autofill_assistant/browser/metrics.h"
-#include "components/autofill_assistant/browser/payment_request.h"
#include "components/autofill_assistant/browser/script.h"
#include "components/autofill_assistant/browser/script_executor_delegate.h"
#include "components/autofill_assistant/browser/script_tracker.h"
@@ -26,7 +25,8 @@
#include "components/autofill_assistant/browser/trigger_context.h"
#include "components/autofill_assistant/browser/ui_delegate.h"
#include "components/autofill_assistant/browser/user_action.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/user_data.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
@@ -96,7 +96,9 @@ class Controller : public ScriptExecutorDelegate,
ClientMemory* GetClientMemory() override;
const TriggerContext* GetTriggerContext() override;
autofill::PersonalDataManager* GetPersonalDataManager() override;
+ WebsiteLoginFetcher* GetWebsiteLoginFetcher() override;
content::WebContents* GetWebContents() override;
+ std::string GetAccountEmailAddress() override;
void SetTouchableElementArea(const ElementAreaProto& area) override;
void SetStatusMessage(const std::string& message) override;
std::string GetStatusMessage() const override;
@@ -125,8 +127,9 @@ class Controller : public ScriptExecutorDelegate,
void RemoveListener(ScriptExecutorDelegate::Listener* listener) override;
void EnterState(AutofillAssistantState state) override;
- void SetPaymentRequestOptions(
- std::unique_ptr<PaymentRequestOptions> options) override;
+ void SetCollectUserDataOptions(
+ std::unique_ptr<CollectUserDataOptions> options,
+ std::unique_ptr<UserData> information) override;
void OnScriptError(const std::string& error_message,
Metrics::DropOutReason reason);
@@ -143,18 +146,16 @@ class Controller : public ScriptExecutorDelegate,
int index,
std::unique_ptr<TriggerContext> context) override;
std::string GetDebugContext() override;
- const PaymentRequestOptions* GetPaymentRequestOptions() const override;
- const PaymentInformation* GetPaymentRequestInformation() const override;
+ const CollectUserDataOptions* GetCollectUserDataOptions() const override;
+ const UserData* GetUserData() const override;
void SetShippingAddress(
std::unique_ptr<autofill::AutofillProfile> address) override;
- void SetBillingAddress(
- std::unique_ptr<autofill::AutofillProfile> address) override;
- void SetContactInfo(std::string name,
- std::string phone,
- std::string email) override;
+ void SetContactInfo(
+ std::unique_ptr<autofill::AutofillProfile> profile) override;
void SetCreditCard(std::unique_ptr<autofill::CreditCard> card) override;
void SetTermsAndConditions(
TermsAndConditionsState terms_and_conditions) override;
+ void SetLoginOption(std::string identifier) override;
void OnTermsAndConditionsLinkClicked(int link) override;
void GetTouchableArea(std::vector<RectF>* area) const override;
void GetRestrictedArea(std::vector<RectF>* area) const override;
@@ -166,6 +167,7 @@ class Controller : public ScriptExecutorDelegate,
ViewportMode GetViewportMode() override;
ConfigureBottomSheetProto::PeekMode GetPeekMode() override;
void GetOverlayColors(OverlayColors* colors) const override;
+ const ClientSettings& GetClientSettings() const override;
const FormProto* GetForm() const override;
void SetCounterValue(int input_index, int counter_index, int value) override;
void SetChoiceSelected(int input_index,
@@ -224,9 +226,9 @@ class Controller : public ScriptExecutorDelegate,
void OnScriptSelected(const ScriptHandle& handle,
std::unique_ptr<TriggerContext> context);
- void UpdatePaymentRequestActions();
- void OnPaymentRequestContinueButtonClicked();
- void OnPaymentRequestAdditionalActionTriggered(int index);
+ void UpdateCollectUserDataActions();
+ void OnCollectUserDataContinueButtonClicked();
+ void OnCollectUserDataAdditionalActionTriggered(int index);
// Overrides ScriptTracker::Listener:
void OnNoRunnableScriptsForPage() override;
@@ -337,8 +339,8 @@ class Controller : public ScriptExecutorDelegate,
std::unique_ptr<OverlayColors> overlay_colors_;
- std::unique_ptr<PaymentRequestOptions> payment_request_options_;
- std::unique_ptr<PaymentInformation> payment_request_info_;
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options_;
+ std::unique_ptr<UserData> user_data_;
std::unique_ptr<FormProto> form_;
std::unique_ptr<FormProto::Result> form_result_;
@@ -388,7 +390,7 @@ class Controller : public ScriptExecutorDelegate,
// taken.
base::Optional<Metrics::DropOutReason> delayed_shutdown_reason_;
- base::WeakPtrFactory<Controller> weak_ptr_factory_;
+ base::WeakPtrFactory<Controller> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Controller);
};
diff --git a/chromium/components/autofill_assistant/browser/controller_observer.cc b/chromium/components/autofill_assistant/browser/controller_observer.cc
index ba003cef782..15fd36975ea 100644
--- a/chromium/components/autofill_assistant/browser/controller_observer.cc
+++ b/chromium/components/autofill_assistant/browser/controller_observer.cc
@@ -18,10 +18,9 @@ void ControllerObserver::OnBubbleMessageChanged(const std::string& message) {}
void ControllerObserver::CloseCustomTab() {}
void ControllerObserver::OnUserActionsChanged(
const std::vector<UserAction>& user_actions) {}
-void ControllerObserver::OnPaymentRequestOptionsChanged(
- const PaymentRequestOptions* options) {}
-void ControllerObserver::OnPaymentRequestInformationChanged(
- const PaymentInformation* state) {}
+void ControllerObserver::OnCollectUserDataOptionsChanged(
+ const CollectUserDataOptions* options) {}
+void ControllerObserver::OnUserDataChanged(const UserData* state) {}
void ControllerObserver::OnDetailsChanged(const Details* details) {}
void ControllerObserver::OnInfoBoxChanged(const InfoBox* info_box) {}
void ControllerObserver::OnProgressChanged(int progress) {}
@@ -36,5 +35,7 @@ void ControllerObserver::OnPeekModeChanged(
void ControllerObserver::OnOverlayColorsChanged(
const UiDelegate::OverlayColors& colors) {}
void ControllerObserver::OnFormChanged(const FormProto* form) {}
+void ControllerObserver::OnClientSettingsChanged(
+ const ClientSettings& settings) {}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/controller_observer.h b/chromium/components/autofill_assistant/browser/controller_observer.h
index 2e6fcff13bb..2c57627757a 100644
--- a/chromium/components/autofill_assistant/browser/controller_observer.h
+++ b/chromium/components/autofill_assistant/browser/controller_observer.h
@@ -14,11 +14,11 @@
#include "components/autofill_assistant/browser/details.h"
#include "components/autofill_assistant/browser/info_box.h"
#include "components/autofill_assistant/browser/metrics.h"
-#include "components/autofill_assistant/browser/payment_request.h"
#include "components/autofill_assistant/browser/script.h"
#include "components/autofill_assistant/browser/state.h"
#include "components/autofill_assistant/browser/ui_delegate.h"
#include "components/autofill_assistant/browser/user_action.h"
+#include "components/autofill_assistant/browser/user_data.h"
#include "components/autofill_assistant/browser/viewport_mode.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
@@ -47,13 +47,12 @@ class ControllerObserver : public base::CheckedObserver {
virtual void OnUserActionsChanged(
const std::vector<UserAction>& user_actions);
- // Gets or clears request for payment information.
- virtual void OnPaymentRequestOptionsChanged(
- const PaymentRequestOptions* options);
+ // Report that the options configuring a CollectUserDataAction have changed.
+ virtual void OnCollectUserDataOptionsChanged(
+ const CollectUserDataOptions* options);
- // Updates the currently selected contact information / payment method.
- virtual void OnPaymentRequestInformationChanged(
- const PaymentInformation* state);
+ // Updates the currently selected user data (e.g., contact information).
+ virtual void OnUserDataChanged(const UserData* state);
// Called when details have changed. Details will be null if they have been
// cleared.
@@ -102,6 +101,9 @@ class ControllerObserver : public base::CheckedObserver {
// Called when the form has changed.
virtual void OnFormChanged(const FormProto* form);
+
+ // Called when client settings have changed.
+ virtual void OnClientSettingsChanged(const ClientSettings& settings);
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CONTROLLER_OBSERVER_H_
diff --git a/chromium/components/autofill_assistant/browser/controller_unittest.cc b/chromium/components/autofill_assistant/browser/controller_unittest.cc
index fbedd27b015..66e4249393a 100644
--- a/chromium/components/autofill_assistant/browser/controller_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/controller_unittest.cc
@@ -7,18 +7,21 @@
#include <memory>
#include <utility>
+#include "base/guid.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill_assistant/browser/features.h"
#include "components/autofill_assistant/browser/mock_controller_observer.h"
+#include "components/autofill_assistant/browser/mock_personal_data_manager.h"
#include "components/autofill_assistant/browser/mock_service.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
#include "components/autofill_assistant/browser/service.h"
#include "components/autofill_assistant/browser/trigger_context.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -58,9 +61,10 @@ class FakeClient : public Client {
// Implements Client
std::string GetApiKey() override { return ""; }
AccessTokenFetcher* GetAccessTokenFetcher() override { return nullptr; }
- autofill::PersonalDataManager* GetPersonalDataManager() override {
- return nullptr;
+ MockPersonalDataManager* GetPersonalDataManager() override {
+ return &mock_personal_data_manager_;
}
+ WebsiteLoginFetcher* GetWebsiteLoginFetcher() override { return nullptr; }
std::string GetServerUrl() override { return ""; }
std::string GetAccountEmailAddress() override { return ""; }
std::string GetLocale() override { return ""; }
@@ -68,6 +72,22 @@ class FakeClient : public Client {
MOCK_METHOD1(Shutdown, void(Metrics::DropOutReason reason));
MOCK_METHOD0(AttachUI, void());
MOCK_METHOD0(DestroyUI, void());
+
+ private:
+ MockPersonalDataManager mock_personal_data_manager_;
+};
+
+// Same as non-mock, but provides default mock callbacks.
+struct MockCollectUserDataOptions : public CollectUserDataOptions {
+ MockCollectUserDataOptions() {
+ base::MockOnceCallback<void(std::unique_ptr<UserData>)>
+ mock_confirm_callback;
+ confirm_callback = std::move(mock_confirm_callback.Get());
+ base::MockOnceCallback<void(int)> mock_actions_callback;
+ additional_actions_callback = std::move(mock_actions_callback.Get());
+ base::MockOnceCallback<void(int)> mock_terms_callback;
+ terms_link_callback = std::move(mock_terms_callback.Get());
+ }
};
} // namespace
@@ -76,8 +96,8 @@ class ControllerTest : public content::RenderViewHostTestHarness {
public:
ControllerTest()
: RenderViewHostTestHarness(
- base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
~ControllerTest() override {}
void SetUp() override {
@@ -91,7 +111,7 @@ class ControllerTest : public content::RenderViewHostTestHarness {
mock_service_ = service.get();
controller_ = std::make_unique<Controller>(
- web_contents(), &fake_client_, thread_bundle()->GetMockTickClock(),
+ web_contents(), &fake_client_, task_environment()->GetMockTickClock(),
std::move(service));
controller_->SetWebControllerForTest(std::move(web_controller));
@@ -195,8 +215,8 @@ class ControllerTest : public content::RenderViewHostTestHarness {
UiDelegate* GetUiDelegate() { return controller_.get(); }
- // |thread_bundle_| must be the first field, to make sure that everything runs
- // in the same task environment.
+ // |task_environment_| must be the first field, to make sure that everything
+ // runs in the same task environment.
base::test::ScopedFeatureList scoped_feature_list_;
base::TimeTicks now_;
std::vector<AutofillAssistantState> states_;
@@ -503,42 +523,42 @@ TEST_F(ControllerTest, Stop) {
}
TEST_F(ControllerTest, Reset) {
- // 1. Fetch scripts for URL, which in contains a single "reset" script.
- SupportsScriptResponseProto script_response;
- auto* reset_script = AddRunnableScript(&script_response, "reset");
- RunOnce(reset_script);
- std::string script_response_str;
- script_response.SerializeToString(&script_response_str);
- EXPECT_CALL(*mock_service_, OnGetScriptsForUrl(_, _, _))
- .WillRepeatedly(RunOnceCallback<2>(true, script_response_str));
+ // 1. Fetch scripts for URL, which in contains a single "reset" script.
+ SupportsScriptResponseProto script_response;
+ auto* reset_script = AddRunnableScript(&script_response, "reset");
+ RunOnce(reset_script);
+ std::string script_response_str;
+ script_response.SerializeToString(&script_response_str);
+ EXPECT_CALL(*mock_service_, OnGetScriptsForUrl(_, _, _))
+ .WillRepeatedly(RunOnceCallback<2>(true, script_response_str));
- Start("http://a.example.com/path");
- EXPECT_THAT(controller_->GetUserActions(),
- ElementsAre(Property(&UserAction::chip,
- Field(&Chip::text, StrEq("reset")))));
+ Start("http://a.example.com/path");
+ EXPECT_THAT(controller_->GetUserActions(),
+ ElementsAre(Property(&UserAction::chip,
+ Field(&Chip::text, StrEq("reset")))));
- // 2. Execute the "reset" script, which contains a reset action.
- ActionsResponseProto actions_response;
- actions_response.add_actions()->mutable_reset();
- std::string actions_response_str;
- actions_response.SerializeToString(&actions_response_str);
- EXPECT_CALL(*mock_service_, OnGetActions(StrEq("reset"), _, _, _, _, _))
- .WillOnce(RunOnceCallback<5>(true, actions_response_str));
+ // 2. Execute the "reset" script, which contains a reset action.
+ ActionsResponseProto actions_response;
+ actions_response.add_actions()->mutable_reset();
+ std::string actions_response_str;
+ actions_response.SerializeToString(&actions_response_str);
+ EXPECT_CALL(*mock_service_, OnGetActions(StrEq("reset"), _, _, _, _, _))
+ .WillOnce(RunOnceCallback<5>(true, actions_response_str));
- controller_->GetClientMemory()->set_selected_card(
- std::make_unique<autofill::CreditCard>());
- EXPECT_TRUE(controller_->GetClientMemory()->has_selected_card());
+ controller_->GetClientMemory()->set_selected_card(
+ std::make_unique<autofill::CreditCard>());
+ EXPECT_TRUE(controller_->GetClientMemory()->has_selected_card());
- EXPECT_TRUE(controller_->PerformUserAction(0));
+ EXPECT_TRUE(controller_->PerformUserAction(0));
- // Resetting should have cleared the client memory
- EXPECT_FALSE(controller_->GetClientMemory()->has_selected_card());
+ // Resetting should have cleared the client memory
+ EXPECT_FALSE(controller_->GetClientMemory()->has_selected_card());
- // The reset script should be available again, even though it's marked
- // RunOnce, as the script state should have been cleared as well.
- EXPECT_THAT(controller_->GetUserActions(),
- ElementsAre(Property(&UserAction::chip,
- Field(&Chip::text, StrEq("reset")))));
+ // The reset script should be available again, even though it's marked
+ // RunOnce, as the script state should have been cleared as well.
+ EXPECT_THAT(controller_->GetUserActions(),
+ ElementsAre(Property(&UserAction::chip,
+ Field(&Chip::text, StrEq("reset")))));
}
TEST_F(ControllerTest, RefreshScriptWhenDomainChanges) {
@@ -715,13 +735,13 @@ TEST_F(ControllerTest, KeepCheckingForElement) {
EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState());
for (int i = 0; i < 3; i++) {
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState());
}
EXPECT_CALL(*mock_web_controller_, OnElementCheck(_, _))
.WillRepeatedly(RunOnceCallback<1>(true));
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(AutofillAssistantState::AUTOSTART_FALLBACK_PROMPT,
controller_->GetState());
@@ -754,7 +774,7 @@ TEST_F(ControllerTest, ScriptTimeoutError) {
Start("http://a.example.com/path");
for (int i = 0; i < 30; i++) {
EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState());
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
}
EXPECT_EQ(AutofillAssistantState::STOPPED, controller_->GetState());
EXPECT_EQ("I give up", controller_->GetStatusMessage());
@@ -788,13 +808,13 @@ TEST_F(ControllerTest, ScriptTimeoutWarning) {
// Warning after 4s, script succeeds and the client continues to wait.
for (int i = 0; i < 4; i++) {
EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState());
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
}
EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState());
EXPECT_EQ("This is slow", controller_->GetStatusMessage());
for (int i = 0; i < 10; i++) {
EXPECT_EQ(AutofillAssistantState::STARTING, controller_->GetState());
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
}
}
@@ -934,7 +954,7 @@ TEST_F(ControllerTest, WaitForNavigationActionTimesOut) {
// No navigation event happened within the action timeout and the script ends.
EXPECT_THAT(processed_actions_capture, SizeIs(0));
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
ASSERT_THAT(processed_actions_capture, SizeIs(2));
EXPECT_EQ(ACTION_APPLIED, processed_actions_capture[0].status());
@@ -972,7 +992,7 @@ TEST_F(ControllerTest, WaitForNavigationActionStartWithinTimeout) {
GURL("http://a.example.com/path"), web_contents()->GetMainFrame());
simulator->SetTransition(ui::PAGE_TRANSITION_LINK);
simulator->Start();
- thread_bundle()->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
// Navigation finishes and the script ends.
EXPECT_THAT(processed_actions_capture, SizeIs(0));
@@ -1394,4 +1414,165 @@ TEST_F(ControllerTest, UnexpectedNavigationDuringPromptAction) {
AutofillAssistantState::STOPPED));
}
+TEST_F(ControllerTest, UserDataFormEmpty) {
+ auto options = std::make_unique<MockCollectUserDataOptions>();
+ auto user_data = std::make_unique<UserData>();
+
+ // Request nothing, expect continue button to be enabled.
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(true)))))
+ .Times(1);
+ EXPECT_CALL(mock_observer_, OnCollectUserDataOptionsChanged(Not(nullptr)))
+ .Times(1);
+ EXPECT_CALL(mock_observer_, OnUserDataChanged(Not(nullptr))).Times(1);
+ controller_->SetCollectUserDataOptions(std::move(options),
+ std::move(user_data));
+}
+
+TEST_F(ControllerTest, UserDataFormContactInfo) {
+ auto options = std::make_unique<MockCollectUserDataOptions>();
+ auto user_data = std::make_unique<UserData>();
+
+ options->request_payer_name = true;
+ options->request_payer_email = true;
+ options->request_payer_phone = true;
+
+ testing::InSequence seq;
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(false)))))
+ .Times(1);
+ controller_->SetCollectUserDataOptions(std::move(options),
+ std::move(user_data));
+
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(true)))))
+ .Times(1);
+
+ autofill::AutofillProfile contact_profile;
+ contact_profile.SetRawInfo(autofill::ServerFieldType::EMAIL_ADDRESS,
+ base::UTF8ToUTF16("joedoe@example.com"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL,
+ base::UTF8ToUTF16("Joe Doe"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16("+1 23 456 789 01"));
+ controller_->SetContactInfo(
+ std::make_unique<autofill::AutofillProfile>(contact_profile));
+ EXPECT_THAT(
+ controller_->GetUserData()->contact_profile->Compare(contact_profile),
+ Eq(0));
+}
+
+TEST_F(ControllerTest, UserDataFormCreditCard) {
+ auto options = std::make_unique<MockCollectUserDataOptions>();
+ auto user_data = std::make_unique<UserData>();
+
+ options->request_payment_method = true;
+ testing::InSequence seq;
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(false)))))
+ .Times(1);
+ controller_->SetCollectUserDataOptions(std::move(options),
+ std::move(user_data));
+
+ // Credit card without billing address is invalid.
+ auto credit_card = std::make_unique<autofill::CreditCard>(
+ base::GenerateGUID(), "https://www.example.com");
+ autofill::test::SetCreditCardInfo(credit_card.get(), "Marion Mitchell",
+ "4111 1111 1111 1111", "01", "2020",
+ /* billing_address_id = */ "");
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(false)))))
+ .Times(1);
+ controller_->SetCreditCard(
+ std::make_unique<autofill::CreditCard>(*credit_card));
+
+ // Credit card with valid billing address is ok.
+ auto billing_address = std::make_unique<autofill::AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com");
+ autofill::test::SetProfileInfo(billing_address.get(), "Marion", "Mitchell",
+ "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA",
+ "91601", "US", "16505678910");
+ credit_card->set_billing_address_id(billing_address->guid());
+ ON_CALL(*fake_client_.GetPersonalDataManager(),
+ GetProfileByGUID(billing_address->guid()))
+ .WillByDefault(Return(billing_address.get()));
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(true)))))
+ .Times(1);
+ controller_->SetCreditCard(
+ std::make_unique<autofill::CreditCard>(*credit_card));
+ EXPECT_THAT(controller_->GetUserData()->card->Compare(*credit_card), Eq(0));
+}
+
+TEST_F(ControllerTest, SetTermsAndConditions) {
+ auto options = std::make_unique<MockCollectUserDataOptions>();
+ auto user_data = std::make_unique<UserData>();
+
+ options->accept_terms_and_conditions_text.assign("Accept T&C");
+ testing::InSequence seq;
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(false)))))
+ .Times(1);
+ controller_->SetCollectUserDataOptions(std::move(options),
+ std::move(user_data));
+
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(true)))))
+ .Times(1);
+ controller_->SetTermsAndConditions(TermsAndConditionsState::ACCEPTED);
+ EXPECT_THAT(controller_->GetUserData()->terms_and_conditions,
+ Eq(TermsAndConditionsState::ACCEPTED));
+}
+
+TEST_F(ControllerTest, SetLoginOption) {
+ auto options = std::make_unique<MockCollectUserDataOptions>();
+ auto user_data = std::make_unique<UserData>();
+
+ options->request_login_choice = true;
+ testing::InSequence seq;
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(false)))))
+ .Times(1);
+ controller_->SetCollectUserDataOptions(std::move(options),
+ std::move(user_data));
+
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(true)))))
+ .Times(1);
+ controller_->SetLoginOption("1");
+ EXPECT_THAT(controller_->GetUserData()->login_choice_identifier, Eq("1"));
+}
+
+TEST_F(ControllerTest, SetShippingAddress) {
+ auto options = std::make_unique<MockCollectUserDataOptions>();
+ auto user_data = std::make_unique<UserData>();
+
+ options->request_shipping = true;
+ testing::InSequence seq;
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(false)))))
+ .Times(1);
+ controller_->SetCollectUserDataOptions(std::move(options),
+ std::move(user_data));
+
+ auto shipping_address = std::make_unique<autofill::AutofillProfile>(
+ base::GenerateGUID(), "https://www.example.com");
+ autofill::test::SetProfileInfo(shipping_address.get(), "Marion", "Mitchell",
+ "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA",
+ "91601", "US", "16505678910");
+ ON_CALL(*fake_client_.GetPersonalDataManager(),
+ GetProfileByGUID(shipping_address->guid()))
+ .WillByDefault(Return(shipping_address.get()));
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(UnorderedElementsAre(
+ Property(&UserAction::enabled, Eq(true)))))
+ .Times(1);
+ controller_->SetShippingAddress(
+ std::make_unique<autofill::AutofillProfile>(*shipping_address));
+ EXPECT_THAT(
+ controller_->GetUserData()->shipping_address->Compare(*shipping_address),
+ Eq(0));
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/details.cc b/chromium/components/autofill_assistant/browser/details.cc
index ac72c77b90f..294d566fced 100644
--- a/chromium/components/autofill_assistant/browser/details.cc
+++ b/chromium/components/autofill_assistant/browser/details.cc
@@ -28,6 +28,7 @@ bool Details::UpdateFromProto(const ShowDetailsProto& proto, Details* details) {
ShowDetailsProto updated_proto = proto;
// Legacy treatment for old proto fields. Can be removed once the backend
// is updated to set the description_line_1/line_2 fields.
+ // TODO(crbug.com/806868): Is this still needed?
if (updated_proto.details().has_description() &&
!updated_proto.details().has_description_line_2()) {
updated_proto.mutable_details()->set_description_line_2(
@@ -124,41 +125,41 @@ bool Details::UpdateFromSelectedCreditCard(const ShowDetailsProto& proto,
base::Value Details::GetDebugContext() const {
base::Value dict(base::Value::Type::DICTIONARY);
- if (!detailsProto().title().empty())
- dict.SetKey("title", base::Value(detailsProto().title()));
+ if (!details_proto().title().empty())
+ dict.SetKey("title", base::Value(details_proto().title()));
- if (!detailsProto().image_url().empty())
- dict.SetKey("image_url", base::Value(detailsProto().image_url()));
+ if (!details_proto().image_url().empty())
+ dict.SetKey("image_url", base::Value(details_proto().image_url()));
- if (!detailsProto().total_price().empty())
- dict.SetKey("total_price", base::Value(detailsProto().total_price()));
+ if (!details_proto().total_price().empty())
+ dict.SetKey("total_price", base::Value(details_proto().total_price()));
- if (!detailsProto().total_price_label().empty())
+ if (!details_proto().total_price_label().empty())
dict.SetKey("total_price_label",
- base::Value(detailsProto().total_price_label()));
+ base::Value(details_proto().total_price_label()));
- if (!detailsProto().description_line_1().empty())
+ if (!details_proto().description_line_1().empty())
dict.SetKey("description_line_1",
- base::Value(detailsProto().description_line_1()));
+ base::Value(details_proto().description_line_1()));
- if (!detailsProto().description_line_2().empty())
+ if (!details_proto().description_line_2().empty())
dict.SetKey("description_line_2",
- base::Value(detailsProto().description_line_2()));
+ base::Value(details_proto().description_line_2()));
- if (!detailsProto().description_line_3().empty())
+ if (!details_proto().description_line_3().empty())
dict.SetKey("description_line_3",
- base::Value(detailsProto().description_line_3()));
+ base::Value(details_proto().description_line_3()));
- if (detailsProto().has_datetime()) {
+ if (details_proto().has_datetime()) {
dict.SetKey("datetime",
base::Value(base::StringPrintf(
"%d-%02d-%02dT%02d:%02d:%02d",
- static_cast<int>(detailsProto().datetime().date().year()),
- detailsProto().datetime().date().month(),
- detailsProto().datetime().date().day(),
- detailsProto().datetime().time().hour(),
- detailsProto().datetime().time().minute(),
- detailsProto().datetime().time().second())));
+ static_cast<int>(details_proto().datetime().date().year()),
+ details_proto().datetime().date().month(),
+ details_proto().datetime().date().day(),
+ details_proto().datetime().time().hour(),
+ details_proto().datetime().time().minute(),
+ details_proto().datetime().time().second())));
}
if (!datetime_.empty())
dict.SetKey("datetime_str", base::Value(datetime_));
diff --git a/chromium/components/autofill_assistant/browser/details.h b/chromium/components/autofill_assistant/browser/details.h
index f19a1eb5eab..ccbdf74875c 100644
--- a/chromium/components/autofill_assistant/browser/details.h
+++ b/chromium/components/autofill_assistant/browser/details.h
@@ -17,9 +17,9 @@ class TriggerContext;
class Details {
public:
- const DetailsProto& detailsProto() const { return proto_; }
+ const DetailsProto& details_proto() const { return proto_; }
const DetailsChangesProto& changes() const { return change_flags_; }
- const std::string GetDatetime() const { return datetime_; }
+ const std::string datetime() const { return datetime_; }
// Returns a dictionary describing the current execution context, which
// is intended to be serialized as JSON string. The execution context is
diff --git a/chromium/components/autofill_assistant/browser/details_unittest.cc b/chromium/components/autofill_assistant/browser/details_unittest.cc
new file mode 100644
index 00000000000..8abf364c17d
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/details_unittest.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 "components/autofill_assistant/browser/details.h"
+
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/geo/country_names.h"
+#include "components/autofill_assistant/browser/details.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/trigger_context.h"
+#include "components/strings/grit/components_strings.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::testing::Eq;
+
+MATCHER_P(EqualsProto, message, "") {
+ std::string expected_serialized, actual_serialized;
+ message.SerializeToString(&expected_serialized);
+ arg.SerializeToString(&actual_serialized);
+ return expected_serialized == actual_serialized;
+}
+
+class DetailsTest : public testing::Test {
+ public:
+ DetailsTest() {}
+
+ void SetUp() override { autofill::CountryNames::SetLocaleString("us-en"); }
+
+ protected:
+ std::unique_ptr<autofill::CreditCard> MakeCreditCard() {
+ return std::make_unique<autofill::CreditCard>();
+ }
+
+ std::unique_ptr<autofill::AutofillProfile> MakeAutofillProfile() {
+ // The email contains a UTF-8 smiley face.
+ auto profile = std::make_unique<autofill::AutofillProfile>();
+ autofill::test::SetProfileInfo(profile.get(), "Charles", "Hardin", "Holley",
+ "\xE2\x98\xBA@gmail.com", "Decca",
+ "123 Apple St.", "unit 6", "Lubbock",
+ "Texas", "79401", "US", "23456789012");
+ return profile;
+ }
+
+ ClientMemory client_memory_;
+};
+
+TEST_F(DetailsTest, DetailsProtoStoredInMemberVariable) {
+ Details details;
+ DetailsProto proto;
+ proto.set_title("title");
+
+ details.SetDetailsProto(proto);
+ EXPECT_THAT(proto, EqualsProto(details.details_proto()));
+}
+
+TEST_F(DetailsTest, DetailsChangesProto) {
+ Details details;
+ DetailsChangesProto proto;
+ proto.set_user_approval_required(true);
+
+ details.SetDetailsChangesProto(proto);
+ EXPECT_THAT(proto, EqualsProto(details.changes()));
+
+ details.ClearChanges();
+ EXPECT_THAT(DetailsChangesProto(), EqualsProto(details.changes()));
+}
+
+TEST_F(DetailsTest, UpdateFromParametersEmpty) {
+ Details details;
+ // Nothing has to be updated.
+ auto context = TriggerContext::CreateEmpty();
+ EXPECT_FALSE(details.UpdateFromParameters(*context));
+}
+
+TEST_F(DetailsTest, UpdateFromParametersShowInitialNoUpdate) {
+ std::map<std::string, std::string> parameters;
+ parameters["DETAILS_SHOW_INITIAL"] = "false";
+ auto context = TriggerContext::Create(parameters, "exps");
+
+ Details details;
+ EXPECT_FALSE(details.UpdateFromParameters(*context));
+}
+
+TEST_F(DetailsTest, UpdateFromParametersUpdateFromDetails) {
+ std::map<std::string, std::string> parameters;
+ parameters["DETAILS_SHOW_INITIAL"] = "true";
+ parameters["DETAILS_TITLE"] = "title";
+ parameters["DETAILS_DESCRIPTION_LINE_1"] = "line1";
+ parameters["DETAILS_DESCRIPTION_LINE_2"] = "line2";
+ parameters["DETAILS_DESCRIPTION_LINE_3"] = "line3";
+ parameters["DETAILS_IMAGE_URL"] = "image";
+ parameters["DETAILS_IMAGE_CLICKTHROUGH_URL"] = "clickthrough";
+ parameters["DETAILS_TOTAL_PRICE_LABEL"] = "total";
+ parameters["DETAILS_TOTAL_PRICE"] = "12";
+
+ auto context = TriggerContext::Create(parameters, "exps");
+
+ Details details;
+ EXPECT_TRUE(details.UpdateFromParameters(*context));
+
+ DetailsProto expected;
+ expected.set_animate_placeholders(true);
+ expected.set_show_image_placeholder(true);
+
+ expected.set_title("title");
+ expected.set_description_line_1("line1");
+ expected.set_description_line_2("line2");
+ expected.set_description_line_3("line3");
+ expected.set_image_url("image");
+ auto* data = expected.mutable_image_clickthrough_data();
+ data->set_allow_clickthrough(true);
+ data->set_clickthrough_url("clickthrough");
+ expected.set_total_price_label("total");
+ expected.set_total_price("12");
+
+ EXPECT_THAT(details.details_proto(), EqualsProto(expected));
+}
+
+TEST_F(DetailsTest, UpdateFromParametersBackwardsCompatibility) {
+ std::map<std::string, std::string> parameters;
+ parameters["MOVIES_MOVIE_NAME"] = "movie_name";
+ parameters["MOVIES_THEATER_NAME"] = "movie_theater";
+ parameters["MOVIES_SCREENING_DATETIME"] = "datetime";
+
+ auto context = TriggerContext::Create(parameters, "exps");
+
+ Details details;
+ EXPECT_TRUE(details.UpdateFromParameters(*context));
+
+ DetailsProto expected;
+ expected.set_animate_placeholders(true);
+ expected.set_show_image_placeholder(true);
+
+ expected.set_title("movie_name");
+ expected.set_description_line_2("movie_theater");
+
+ EXPECT_THAT(details.datetime(), "datetime");
+ EXPECT_THAT(details.details_proto().title(), "movie_name");
+ EXPECT_THAT(details.details_proto().description_line_2(), "movie_theater");
+
+ EXPECT_THAT(details.details_proto(), EqualsProto(expected));
+}
+
+TEST_F(DetailsTest, UpdateFromProtoNoDetails) {
+ Details details;
+ EXPECT_FALSE(Details::UpdateFromProto(ShowDetailsProto(), &details));
+}
+
+TEST_F(DetailsTest, UpdateFromProto) {
+ ShowDetailsProto proto;
+ proto.mutable_details()->set_title("title");
+ proto.mutable_change_flags()->set_user_approval_required(true);
+
+ Details details;
+ EXPECT_TRUE(Details::UpdateFromProto(proto, &details));
+
+ EXPECT_EQ(details.details_proto().title(), "title");
+ EXPECT_TRUE(details.changes().user_approval_required());
+}
+
+TEST_F(DetailsTest, UpdateFromContactDetailsNoAddressInMemory) {
+ EXPECT_FALSE(Details::UpdateFromContactDetails(ShowDetailsProto(),
+ &client_memory_, nullptr));
+}
+
+TEST_F(DetailsTest, UpdateFromContactDetails) {
+ ShowDetailsProto proto;
+ proto.set_contact_details("contact");
+ client_memory_.set_selected_address("contact", MakeAutofillProfile());
+
+ Details details;
+ EXPECT_TRUE(
+ Details::UpdateFromContactDetails(proto, &client_memory_, &details));
+
+ const auto& result = details.details_proto();
+ EXPECT_THAT(result.title(),
+ Eq(l10n_util::GetStringUTF8(IDS_PAYMENTS_CONTACT_DETAILS_LABEL)));
+ EXPECT_THAT(result.description_line_1(), Eq("Charles Hardin Holley"));
+ EXPECT_THAT(result.description_line_2(), Eq("\xE2\x98\xBA@gmail.com"));
+}
+
+TEST_F(DetailsTest, UpdateFromShippingAddressNoAddressInMemory) {
+ EXPECT_FALSE(Details::UpdateFromShippingAddress(ShowDetailsProto(),
+ &client_memory_, nullptr));
+}
+
+TEST_F(DetailsTest, UpdateFromShippingAddress) {
+ ShowDetailsProto proto;
+ proto.set_shipping_address("shipping");
+ client_memory_.set_selected_address("shipping", MakeAutofillProfile());
+
+ Details details;
+ EXPECT_TRUE(
+ Details::UpdateFromShippingAddress(proto, &client_memory_, &details));
+
+ const auto& result = details.details_proto();
+ EXPECT_THAT(
+ result.title(),
+ Eq(l10n_util::GetStringUTF8(IDS_PAYMENTS_SHIPPING_ADDRESS_LABEL)));
+ EXPECT_THAT(result.description_line_1(), Eq("Charles Hardin Holley"));
+ EXPECT_THAT(result.description_line_2(),
+ Eq("123 Apple St.\nunit 6 79401 Lubbock US"));
+}
+
+TEST_F(DetailsTest, UpdateFromSelectedCreditCardEmptyMemory) {
+ ShowDetailsProto proto;
+ proto.set_credit_card(true);
+ EXPECT_FALSE(Details::UpdateFromContactDetails(ShowDetailsProto(),
+ &client_memory_, nullptr));
+}
+
+TEST_F(DetailsTest, UpdateFromSelectedCreditCardNotRequested) {
+ ShowDetailsProto proto;
+ proto.set_credit_card(false);
+ client_memory_.set_selected_card(MakeCreditCard());
+ EXPECT_FALSE(Details::UpdateFromContactDetails(ShowDetailsProto(),
+ &client_memory_, nullptr));
+}
+
+TEST_F(DetailsTest, UpdateFromCreditCard) {
+ ShowDetailsProto proto;
+ proto.set_credit_card(true);
+ client_memory_.set_selected_card(MakeCreditCard());
+
+ Details details;
+ EXPECT_TRUE(
+ Details::UpdateFromSelectedCreditCard(proto, &client_memory_, &details));
+
+ const auto& result = details.details_proto();
+ EXPECT_THAT(
+ result.title(),
+ Eq(l10n_util::GetStringUTF8(IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL)));
+ // The credit card string contains 4 non-ascii dots, we just check that it
+ // does contain something.
+ EXPECT_FALSE(result.description_line_1().empty());
+}
+
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_cc.template b/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_cc.template
index 6fcaa7c87aa..ffa1cde75b6 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_cc.template
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_cc.template
@@ -46,7 +46,9 @@ void Domain::RegisterEventHandlersIfNeeded() {
{% for command in domain.commands %}
{% set class_name = 'ExperimentalDomain' if command.experimental else 'Domain' %}
{% set method_name = command.name | sanitize_literal | to_title_case %}
-void {{class_name}}::{{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback) {
+void {{class_name}}::{{method_name}}(
+ std::unique_ptr<{{method_name}}Params> params,
+ base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)> callback) {
dispatcher_->SendMessage("{{domain.domain}}.{{command.name}}", params->Serialize(), base::BindOnce(&Domain::Handle{{method_name}}Response, std::move(callback)));
}
{# Generate convenience methods that take the required parameters directly. #}
@@ -64,7 +66,7 @@ void {{class_name}}::{{method_name}}({##}
{% endfor %}
{% if command.get("parameters", []) and not command.parameters[0].get("optional", False) %}, {% endif %}{# -#}
{% if command.get("returns", []) -%}
- base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback{##}
+ base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)> callback{##}
{% else -%}
base::OnceClosure callback{##}
{% endif %}) {
@@ -99,18 +101,22 @@ void {{class_name}}::{{method_name}}(std::unique_ptr<{{method_name}}Params> para
{% set method_name = command.name | sanitize_literal | to_title_case %}
// static
-void Domain::Handle{{method_name}}Response(base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback, const base::Value& response) {
+void Domain::Handle{{method_name}}Response(
+ base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)> callback,
+ const MessageDispatcher::ReplyStatus& reply_status,
+ const base::Value& response) {
if (callback.is_null())
return;
+
// This is an error response.
if (response.is_none()) {
- std::move(callback).Run(nullptr);
+ std::move(callback).Run(reply_status, nullptr);
return;
}
ErrorReporter errors;
std::unique_ptr<{{method_name}}Result> result = {{method_name}}Result::Parse(response, &errors);
DCHECK(!errors.HasErrors()) << errors.ToString();
- std::move(callback).Run(std::move(result));
+ std::move(callback).Run(reply_status, std::move(result));
}
{% endfor %}
{% if "events" in domain %}
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_h.template b/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_h.template
index ab5397eddb7..785d4cd7152 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_h.template
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_h.template
@@ -23,7 +23,7 @@
{% if command.description %}
// {{ command.description.replace('\n', '\n // ') }}
{% endif %}
- void {{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)>());
+ void {{method_name}}(std::unique_ptr<{{method_name}}Params> params, base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)> callback = base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)>());
{# Generate convenience methods that take the required parameters directly. #}
{# Don't generate these for experimental commands. #}
{% if "parameters" in command and not command.experimental %}
@@ -37,7 +37,7 @@
{% endfor %}
{% if command.get("parameters", []) and not command.parameters[0].get("optional", False) %}, {% endif %}{# -#}
{% if command.get("returns", []) -%}
- base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback = base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)>(){##}
+ base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)> callback = base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)>(){##}
{% else -%}
base::OnceClosure callback = base::OnceClosure(){##}
{% endif %});
@@ -108,7 +108,10 @@ class Domain {
{% for command in domain.commands %}
{% if not "returns" in command %}{% continue %}{% endif %}
{% set method_name = command.name | sanitize_literal | to_title_case %}
- static void Handle{{method_name}}Response(base::OnceCallback<void(std::unique_ptr<{{method_name}}Result>)> callback, const base::Value& response);
+ static void Handle{{method_name}}Response(
+ base::OnceCallback<void(const MessageDispatcher::ReplyStatus&, std::unique_ptr<{{method_name}}Result>)> callback,
+ const MessageDispatcher::ReplyStatus& reply_status,
+ const base::Value& response);
{% endfor %}
{# Generate event dispatchers. #}
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc b/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc
index 4627fb6cb74..39911cdb7a0 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc
@@ -27,10 +27,9 @@ DevtoolsClient::DevtoolsClient(
runtime_domain_(this),
network_domain_(this),
renderer_crashed_(false),
- next_message_id_(0),
- weak_ptr_factory_(this) {
- browser_main_thread_ = base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI});
+ next_message_id_(0) {
+ browser_main_thread_ =
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI});
agent_host_->AttachClient(this);
}
@@ -57,7 +56,7 @@ network::Domain* DevtoolsClient::GetNetwork() {
void DevtoolsClient::SendMessage(
const char* method,
std::unique_ptr<base::Value> params,
- base::OnceCallback<void(const base::Value&)> callback) {
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)> callback) {
SendMessageWithParams(method, std::move(params), std::move(callback));
}
@@ -133,6 +132,7 @@ bool DevtoolsClient::DispatchMessageReply(
pending_messages_.erase(it);
if (!callback.callback_with_result.is_null()) {
const base::DictionaryValue* result_dict;
+ ReplyStatus status;
if (message_dict.GetDictionary("result", &result_dict)) {
if (browser_main_thread_) {
browser_main_thread_->PostTask(
@@ -140,22 +140,24 @@ bool DevtoolsClient::DispatchMessageReply(
base::BindOnce(
&DevtoolsClient::DispatchMessageReplyWithResultTask,
weak_ptr_factory_.GetWeakPtr(), std::move(owning_message),
- std::move(callback.callback_with_result), result_dict));
+ std::move(callback.callback_with_result), status, result_dict));
} else {
- std::move(callback.callback_with_result).Run(*result_dict);
+ std::move(callback.callback_with_result).Run(status, *result_dict);
}
} else if (message_dict.GetDictionary("error", &result_dict)) {
auto null_value = std::make_unique<base::Value>();
DLOG(ERROR) << "Error in method call result: " << *result_dict;
+ FillReplyStatusFromErrorDict(&status, *result_dict);
if (browser_main_thread_) {
browser_main_thread_->PostTask(
FROM_HERE,
- base::BindOnce(
- &DevtoolsClient::DispatchMessageReplyWithResultTask,
- weak_ptr_factory_.GetWeakPtr(), std::move(null_value),
- std::move(callback.callback_with_result), null_value.get()));
+ base::BindOnce(&DevtoolsClient::DispatchMessageReplyWithResultTask,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(null_value),
+ std::move(callback.callback_with_result), status,
+ null_value.get()));
} else {
- std::move(callback.callback_with_result).Run(*null_value);
+ std::move(callback.callback_with_result).Run(status, *null_value);
}
} else {
NOTREACHED() << "Reply has neither result nor error";
@@ -181,9 +183,10 @@ bool DevtoolsClient::DispatchMessageReply(
void DevtoolsClient::DispatchMessageReplyWithResultTask(
std::unique_ptr<base::Value> owning_message,
- base::OnceCallback<void(const base::Value&)> callback,
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)> callback,
+ const ReplyStatus& reply_status,
const base::Value* result_dict) {
- std::move(callback).Run(*result_dict);
+ std::move(callback).Run(reply_status, *result_dict);
}
bool DevtoolsClient::DispatchEvent(std::unique_ptr<base::Value> owning_message,
@@ -228,6 +231,24 @@ void DevtoolsClient::DispatchEventTask(
event_handler->Run(*result_dict);
}
+void DevtoolsClient::FillReplyStatusFromErrorDict(
+ ReplyStatus* status,
+ const base::DictionaryValue& error_dict) {
+ const base::Value* code;
+ if (error_dict.Get("code", &code) && code->is_int()) {
+ status->error_code = code->GetInt();
+ } else {
+ status->error_code = -1; // unknown error code
+ }
+
+ const base::Value* message;
+ if (error_dict.Get("message", &message) && message->is_string()) {
+ status->error_message = message->GetString();
+ } else {
+ status->error_message = "unknown";
+ }
+}
+
void DevtoolsClient::AgentHostClosed(content::DevToolsAgentHost* agent_host) {
// Agent host is not expected to be closed when this object is alive.
renderer_crashed_ = true;
@@ -241,7 +262,7 @@ DevtoolsClient::Callback::Callback(base::OnceClosure callback)
: callback(std::move(callback)) {}
DevtoolsClient::Callback::Callback(
- base::OnceCallback<void(const base::Value&)> callback)
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)> callback)
: callback_with_result(std::move(callback)) {}
DevtoolsClient::Callback::~Callback() = default;
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_client.h b/chromium/components/autofill_assistant/browser/devtools/devtools_client.h
index 07ba6f5beb9..4b86b9ecc65 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_client.h
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_client.h
@@ -44,7 +44,8 @@ class DevtoolsClient : public MessageDispatcher,
void SendMessage(
const char* method,
std::unique_ptr<base::Value> params,
- base::OnceCallback<void(const base::Value&)> callback) override;
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)> callback)
+ override;
void SendMessage(const char* method,
std::unique_ptr<base::Value> params,
base::OnceClosure callback) override;
@@ -64,13 +65,15 @@ class DevtoolsClient : public MessageDispatcher,
Callback();
Callback(Callback&& other);
explicit Callback(base::OnceClosure callback);
- explicit Callback(base::OnceCallback<void(const base::Value&)> callback);
+ explicit Callback(base::OnceCallback<void(const ReplyStatus&,
+ const base::Value&)> callback);
~Callback();
Callback& operator=(Callback&& other);
base::OnceClosure callback;
- base::OnceCallback<void(const base::Value&)> callback_with_result;
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)>
+ callback_with_result;
};
template <typename CallbackType>
@@ -81,7 +84,8 @@ class DevtoolsClient : public MessageDispatcher,
const base::DictionaryValue& message_dict);
void DispatchMessageReplyWithResultTask(
std::unique_ptr<base::Value> owning_message,
- base::OnceCallback<void(const base::Value&)> callback,
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)> callback,
+ const ReplyStatus& reply_status,
const base::Value* result_dict);
bool DispatchEvent(std::unique_ptr<base::Value> owning_message,
const base::DictionaryValue& message_dict);
@@ -91,6 +95,8 @@ class DevtoolsClient : public MessageDispatcher,
void DispatchEventTask(std::unique_ptr<base::Value> owning_message,
const EventHandler* event_handler,
const base::DictionaryValue* result_dict);
+ void FillReplyStatusFromErrorDict(ReplyStatus* status,
+ const base::DictionaryValue& error_dict);
scoped_refptr<content::DevToolsAgentHost> agent_host_;
scoped_refptr<base::SequencedTaskRunner> browser_main_thread_;
@@ -104,7 +110,7 @@ class DevtoolsClient : public MessageDispatcher,
bool renderer_crashed_;
int next_message_id_;
- base::WeakPtrFactory<DevtoolsClient> weak_ptr_factory_;
+ base::WeakPtrFactory<DevtoolsClient> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DevtoolsClient);
};
diff --git a/chromium/components/autofill_assistant/browser/devtools/message_dispatcher.h b/chromium/components/autofill_assistant/browser/devtools/message_dispatcher.h
index c78c9547a22..a5171389127 100644
--- a/chromium/components/autofill_assistant/browser/devtools/message_dispatcher.h
+++ b/chromium/components/autofill_assistant/browser/devtools/message_dispatcher.h
@@ -22,10 +22,24 @@ namespace autofill_assistant {
// An internal interface for sending DevTools messages from the domain agents.
class MessageDispatcher {
public:
+ // Status of a SendMessage operation.
+ struct ReplyStatus {
+ // Error codes, as a number, -1 if error code is unknown.
+ //
+ // Possible values are listed on:
+ // src/third_party/inspector_protocol/lib/DispatcherBase_h.template
+ long error_code = 0;
+
+ std::string error_message;
+
+ bool is_ok() const { return error_code == 0; }
+ };
+
virtual void SendMessage(
const char* method,
std::unique_ptr<base::Value> params,
- base::OnceCallback<void(const base::Value&)> callback) = 0;
+ base::OnceCallback<void(const ReplyStatus&, const base::Value&)>
+ callback) = 0;
virtual void SendMessage(const char* method,
std::unique_ptr<base::Value> params,
base::OnceClosure callback) = 0;
diff --git a/chromium/components/autofill_assistant/browser/element_area.cc b/chromium/components/autofill_assistant/browser/element_area.cc
index 14f7819a7fd..23ddb009c67 100644
--- a/chromium/components/autofill_assistant/browser/element_area.cc
+++ b/chromium/components/autofill_assistant/browser/element_area.cc
@@ -12,12 +12,12 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill_assistant/browser/script_executor_delegate.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
namespace autofill_assistant {
ElementArea::ElementArea(ScriptExecutorDelegate* delegate)
- : delegate_(delegate), weak_ptr_factory_(this) {
+ : delegate_(delegate) {
DCHECK(delegate_);
}
diff --git a/chromium/components/autofill_assistant/browser/element_area.h b/chromium/components/autofill_assistant/browser/element_area.h
index fe9e2f20746..fe7ee6fe609 100644
--- a/chromium/components/autofill_assistant/browser/element_area.h
+++ b/chromium/components/autofill_assistant/browser/element_area.h
@@ -139,7 +139,7 @@ class ElementArea {
const std::vector<RectF>& restricted_area)>
on_update_;
- base::WeakPtrFactory<ElementArea> weak_ptr_factory_;
+ base::WeakPtrFactory<ElementArea> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ElementArea);
};
diff --git a/chromium/components/autofill_assistant/browser/element_area_unittest.cc b/chromium/components/autofill_assistant/browser/element_area_unittest.cc
index b271af99924..db37aa67579 100644
--- a/chromium/components/autofill_assistant/browser/element_area_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/element_area_unittest.cc
@@ -12,10 +12,10 @@
#include "base/strings/stringprintf.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill_assistant/browser/fake_script_executor_delegate.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
#include "components/autofill_assistant/browser/script_executor_delegate.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::base::test::RunOnceCallback;
@@ -68,8 +68,7 @@ ACTION(DoNothing) {}
class ElementAreaTest : public testing::Test {
protected:
ElementAreaTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
element_area_(&delegate_) {
delegate_.SetWebController(&mock_web_controller_);
delegate_.GetMutableSettings()->element_position_update_interval =
@@ -104,9 +103,9 @@ class ElementAreaTest : public testing::Test {
reported_restricted_area_ = restricted_area;
}
- // scoped_task_environment_ must be first to guarantee other field
+ // task_environment_ must be first to guarantee other field
// creation run in that environment.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockWebController mock_web_controller_;
FakeScriptExecutorDelegate delegate_;
@@ -382,8 +381,7 @@ TEST_F(ElementAreaTest, ElementMovesWithTime) {
EXPECT_THAT(reported_area_, ElementsAre(MatchingRectF(0, 25, 100, 50)));
- scoped_task_environment_.FastForwardBy(
- base::TimeDelta::FromMilliseconds(100));
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(100));
// Updated area is available
std::vector<RectF> rectangles;
diff --git a/chromium/components/autofill_assistant/browser/element_precondition.cc b/chromium/components/autofill_assistant/browser/element_precondition.cc
index a4fee3d502e..45efbfd773c 100644
--- a/chromium/components/autofill_assistant/browser/element_precondition.cc
+++ b/chromium/components/autofill_assistant/browser/element_precondition.cc
@@ -17,8 +17,7 @@ ElementPrecondition::ElementPrecondition(
element_exists,
const google::protobuf::RepeatedPtrField<FormValueMatchProto>&
form_value_match)
- : form_value_match_(form_value_match.begin(), form_value_match.end()),
- weak_ptr_factory_(this) {
+ : form_value_match_(form_value_match.begin(), form_value_match.end()) {
for (const auto& element : element_exists) {
// TODO(crbug.com/806868): Check if we shouldn't skip the script when this
// happens.
diff --git a/chromium/components/autofill_assistant/browser/element_precondition.h b/chromium/components/autofill_assistant/browser/element_precondition.h
index 83b0e8c6161..9e7497f2791 100644
--- a/chromium/components/autofill_assistant/browser/element_precondition.h
+++ b/chromium/components/autofill_assistant/browser/element_precondition.h
@@ -49,7 +49,7 @@ class ElementPrecondition {
base::OnceCallback<void(bool)> callback_;
- base::WeakPtrFactory<ElementPrecondition> weak_ptr_factory_;
+ base::WeakPtrFactory<ElementPrecondition> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ElementPrecondition);
};
diff --git a/chromium/components/autofill_assistant/browser/element_precondition_unittest.cc b/chromium/components/autofill_assistant/browser/element_precondition_unittest.cc
index 5850608fe04..eb00f23c9c3 100644
--- a/chromium/components/autofill_assistant/browser/element_precondition_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/element_precondition_unittest.cc
@@ -12,8 +12,8 @@
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "components/autofill_assistant/browser/batch_element_checker.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/re2/src/re2/re2.h"
diff --git a/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc b/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc
index 6d85266a06d..5ee7fb8b423 100644
--- a/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc
+++ b/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc
@@ -46,10 +46,18 @@ FakeScriptExecutorDelegate::GetPersonalDataManager() {
return nullptr;
}
+WebsiteLoginFetcher* FakeScriptExecutorDelegate::GetWebsiteLoginFetcher() {
+ return nullptr;
+}
+
content::WebContents* FakeScriptExecutorDelegate::GetWebContents() {
return nullptr;
}
+std::string FakeScriptExecutorDelegate::GetAccountEmailAddress() {
+ return std::string();
+}
+
void FakeScriptExecutorDelegate::EnterState(AutofillAssistantState state) {
state_ = state;
}
@@ -94,9 +102,11 @@ void FakeScriptExecutorDelegate::SetUserActions(
user_actions_ = std::move(user_actions);
}
-void FakeScriptExecutorDelegate::SetPaymentRequestOptions(
- std::unique_ptr<PaymentRequestOptions> options) {
+void FakeScriptExecutorDelegate::SetCollectUserDataOptions(
+ std::unique_ptr<CollectUserDataOptions> options,
+ std::unique_ptr<UserData> information) {
payment_request_options_ = std::move(options);
+ payment_request_info_ = std::move(information);
}
void FakeScriptExecutorDelegate::SetViewportMode(ViewportMode mode) {
diff --git a/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h b/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h
index 9930b56405e..607e7f2ab1f 100644
--- a/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h
+++ b/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h
@@ -33,7 +33,9 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
ClientMemory* GetClientMemory() override;
TriggerContext* GetTriggerContext() override;
autofill::PersonalDataManager* GetPersonalDataManager() override;
+ WebsiteLoginFetcher* GetWebsiteLoginFetcher() override;
content::WebContents* GetWebContents() override;
+ std::string GetAccountEmailAddress() override;
void EnterState(AutofillAssistantState state) override;
void SetTouchableElementArea(const ElementAreaProto& element) override;
void SetStatusMessage(const std::string& message) override;
@@ -47,8 +49,9 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
void SetProgressVisible(bool visible) override;
void SetUserActions(
std::unique_ptr<std::vector<UserAction>> user_actions) override;
- void SetPaymentRequestOptions(
- std::unique_ptr<PaymentRequestOptions> options) override;
+ void SetCollectUserDataOptions(
+ std::unique_ptr<CollectUserDataOptions> options,
+ std::unique_ptr<UserData> information) override;
void SetViewportMode(ViewportMode mode) override;
ViewportMode GetViewportMode() override;
void SetPeekMode(ConfigureBottomSheetProto::PeekMode peek_mode) override;
@@ -84,7 +87,9 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
std::vector<UserAction>* GetUserActions() { return user_actions_.get(); }
- PaymentRequestOptions* GetOptions() { return payment_request_options_.get(); }
+ CollectUserDataOptions* GetOptions() {
+ return payment_request_options_.get();
+ }
void UpdateNavigationState(bool navigating, bool error) {
navigating_to_new_document_ = navigating;
@@ -111,7 +116,8 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
std::unique_ptr<Details> details_;
std::unique_ptr<InfoBox> info_box_;
std::unique_ptr<std::vector<UserAction>> user_actions_;
- std::unique_ptr<PaymentRequestOptions> payment_request_options_;
+ std::unique_ptr<CollectUserDataOptions> payment_request_options_;
+ std::unique_ptr<UserData> payment_request_info_;
bool navigating_to_new_document_ = false;
bool navigation_error_ = false;
std::set<ScriptExecutorDelegate::Listener*> listeners_;
diff --git a/chromium/components/autofill_assistant/browser/metrics.cc b/chromium/components/autofill_assistant/browser/metrics.cc
index 57f7ffeb0c0..81fcfcca886 100644
--- a/chromium/components/autofill_assistant/browser/metrics.cc
+++ b/chromium/components/autofill_assistant/browser/metrics.cc
@@ -14,14 +14,23 @@ const char kPaymentRequestPrefilledName[] =
"Android.AutofillAssistant.PaymentRequest.Prefilled";
const char kPaymentRequestAutofillInfoChangedName[] =
"Android.AutofillAssistant.PaymentRequest.AutofillChanged";
+const char kPaymentRequestFirstNameOnly[] =
+ "Android.AutofillAssistant.PaymentRequest.FirstNameOnly";
+const char kPaymentRequestMandatoryPostalCode[] =
+ "Android.AutofillAssistant.PaymentRequest.MandatoryPostalCode";
+static bool DROPOUT_RECORDED = false;
} // namespace
// static
void Metrics::RecordDropOut(DropOutReason reason) {
DCHECK_LE(reason, DropOutReason::kMaxValue);
+ if (DROPOUT_RECORDED) {
+ return;
+ }
DVLOG_IF(3, reason != DropOutReason::AA_START)
<< "Drop out with reason: " << reason;
base::UmaHistogramEnumeration(kDropOutEnumName, reason);
+ DROPOUT_RECORDED = true;
}
// static
@@ -65,4 +74,37 @@ void Metrics::RecordPaymentRequestAutofillChanged(bool changed, bool success) {
}
}
+// static
+void Metrics::RecordPaymentRequestFirstNameOnly(bool first_name_only) {
+ base::UmaHistogramBoolean(kPaymentRequestFirstNameOnly, first_name_only);
+}
+
+// static
+void Metrics::RecordPaymentRequestMandatoryPostalCode(bool required,
+ bool initially_right,
+ bool success) {
+ PaymentRequestMandatoryPostalCode mandatory_postal_code;
+ if (!required) {
+ mandatory_postal_code = PaymentRequestMandatoryPostalCode::NOT_REQUIRED;
+ } else if (initially_right && success) {
+ mandatory_postal_code =
+ PaymentRequestMandatoryPostalCode::REQUIRED_INITIALLY_RIGHT_SUCCESS;
+ } else if (initially_right && !success) {
+ mandatory_postal_code =
+ PaymentRequestMandatoryPostalCode::REQUIRED_INITIALLY_RIGHT_FAILURE;
+ } else if (!initially_right && success) {
+ mandatory_postal_code =
+ PaymentRequestMandatoryPostalCode::REQUIRED_INITIALLY_WRONG_SUCCESS;
+ } else if (!initially_right && !success) {
+ mandatory_postal_code =
+ PaymentRequestMandatoryPostalCode::REQUIRED_INITIALLY_WRONG_FAILURE;
+ } else {
+ DCHECK(false) << "Not reached";
+ return;
+ }
+
+ base::UmaHistogramEnumeration(kPaymentRequestMandatoryPostalCode,
+ mandatory_postal_code);
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/metrics.h b/chromium/components/autofill_assistant/browser/metrics.h
index 09fe07b611e..05b9ada5840 100644
--- a/chromium/components/autofill_assistant/browser/metrics.h
+++ b/chromium/components/autofill_assistant/browser/metrics.h
@@ -100,10 +100,50 @@ class Metrics {
kMaxValue = NOTCHANGED_FAILURE
};
+ // Whether a billing postal code was required and whether the user ultimately
+ // succeeded or not.
+ //
+ // This enum is used in histograms, do not remove/renumber entries. Only add
+ // at the end and update kMaxValue. Also remember to update the
+ // AutofillAssistantPaymentRequestMandatoryPostalCode enum listing
+ // in tools/metrics/histograms/enums.xml.
+ enum class PaymentRequestMandatoryPostalCode {
+ REQUIRED_INITIALLY_WRONG_SUCCESS = 0,
+ REQUIRED_INITIALLY_WRONG_FAILURE = 1,
+ REQUIRED_INITIALLY_RIGHT_SUCCESS = 2,
+ REQUIRED_INITIALLY_RIGHT_FAILURE = 3,
+ NOT_REQUIRED = 4,
+
+ kMaxValue = NOT_REQUIRED
+ };
+
+ // The different ways in which DFM can be installed.
+ //
+ // GENERATED_JAVA_ENUM_PACKAGE: (
+ // org.chromium.chrome.browser.autofill_assistant.metrics)
+ // GENERATED_JAVA_CLASS_NAME_OVERRIDE: FeatureModuleInstallation
+ //
+ // This enum is used in histograms, do not remove/renumber entries. Only add
+ // at the end and update kMaxValue. Also remember to update the
+ // AutofillAssistantFeatureModuleInstallation enum listing in
+ // tools/metrics/histograms/enums.xml.
+ enum class FeatureModuleInstallation {
+ DFM_BACKGROUND_INSTALLATION_REQUESTED = 0,
+ DFM_FOREGROUND_INSTALLATION_SUCCEEDED = 1,
+ DFM_FOREGROUND_INSTALLATION_FAILED = 2,
+ DFM_ALREADY_INSTALLED = 3,
+
+ kMaxValue = DFM_ALREADY_INSTALLED
+ };
+
static void RecordDropOut(DropOutReason reason);
static void RecordPaymentRequestPrefilledSuccess(bool initially_complete,
bool success);
static void RecordPaymentRequestAutofillChanged(bool changed, bool success);
+ static void RecordPaymentRequestFirstNameOnly(bool first_name_only);
+ static void RecordPaymentRequestMandatoryPostalCode(bool required,
+ bool initially_right,
+ bool success);
// Intended for debugging: writes string representation of |reason| to |out|.
friend std::ostream& operator<<(std::ostream& out,
diff --git a/chromium/components/autofill_assistant/browser/mock_controller_observer.h b/chromium/components/autofill_assistant/browser/mock_controller_observer.h
index 6a5510bae28..151bdc1b461 100644
--- a/chromium/components/autofill_assistant/browser/mock_controller_observer.h
+++ b/chromium/components/autofill_assistant/browser/mock_controller_observer.h
@@ -27,8 +27,9 @@ class MockControllerObserver : public ControllerObserver {
MOCK_METHOD1(OnStateChanged, void(AutofillAssistantState));
MOCK_METHOD1(OnUserActionsChanged,
void(const std::vector<UserAction>& user_actions));
- MOCK_METHOD1(OnPaymentRequestChanged,
- void(const PaymentRequestOptions* options));
+ MOCK_METHOD1(OnCollectUserDataOptionsChanged,
+ void(const CollectUserDataOptions* options));
+ MOCK_METHOD1(OnUserDataChanged, void(const UserData* user_data));
MOCK_METHOD1(OnDetailsChanged, void(const Details* details));
MOCK_METHOD1(OnInfoBoxChanged, void(const InfoBox* info_box));
MOCK_METHOD1(OnProgressChanged, void(int progress));
@@ -43,6 +44,8 @@ class MockControllerObserver : public ControllerObserver {
MOCK_METHOD1(OnPeekModeChanged,
void(ConfigureBottomSheetProto::PeekMode peek_mode));
MOCK_METHOD1(OnFormChanged, void(const FormProto* form));
+
+ // TODO(b/141163294): add missing methods and unit tests.
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/mock_personal_data_manager.cc b/chromium/components/autofill_assistant/browser/mock_personal_data_manager.cc
new file mode 100644
index 00000000000..a8ec94e1847
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/mock_personal_data_manager.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 "components/autofill_assistant/browser/mock_personal_data_manager.h"
+
+namespace autofill_assistant {
+
+MockPersonalDataManager::MockPersonalDataManager()
+ : PersonalDataManager("en-US") {}
+MockPersonalDataManager::~MockPersonalDataManager() = default;
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/mock_personal_data_manager.h b/chromium/components/autofill_assistant/browser/mock_personal_data_manager.h
new file mode 100644
index 00000000000..4e9965bb85f
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/mock_personal_data_manager.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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_PERSONAL_DATA_MANAGER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_PERSONAL_DATA_MANAGER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+
+class MockPersonalDataManager : public autofill::PersonalDataManager {
+ public:
+ MockPersonalDataManager();
+ ~MockPersonalDataManager() override;
+
+ MOCK_METHOD1(SaveImportedProfile,
+ std::string(const autofill::AutofillProfile&));
+ MOCK_METHOD1(GetProfileByGUID,
+ autofill::AutofillProfile*(const std::string&));
+ MOCK_CONST_METHOD0(GetProfiles, std::vector<autofill::AutofillProfile*>());
+ MOCK_CONST_METHOD0(GetCreditCards, std::vector<autofill::CreditCard*>());
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_PERSONAL_DATA_MANAGER_H_
diff --git a/chromium/components/autofill_assistant/browser/mock_website_login_fetcher.cc b/chromium/components/autofill_assistant/browser/mock_website_login_fetcher.cc
new file mode 100644
index 00000000000..d538a20b6a1
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/mock_website_login_fetcher.cc
@@ -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.
+
+#include "components/autofill_assistant/browser/mock_website_login_fetcher.h"
+
+namespace autofill_assistant {
+
+MockWebsiteLoginFetcher::MockWebsiteLoginFetcher() {}
+MockWebsiteLoginFetcher::~MockWebsiteLoginFetcher() {}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/mock_website_login_fetcher.h b/chromium/components/autofill_assistant/browser/mock_website_login_fetcher.h
new file mode 100644
index 00000000000..57dc326f007
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/mock_website_login_fetcher.h
@@ -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.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_WEBSITE_LOGIN_FETCHER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_WEBSITE_LOGIN_FETCHER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "components/autofill_assistant/browser/website_login_fetcher.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+
+// Mock login fetcher for unit tests.
+class MockWebsiteLoginFetcher : public WebsiteLoginFetcher {
+ public:
+ MockWebsiteLoginFetcher();
+ ~MockWebsiteLoginFetcher() override;
+
+ void GetLoginsForUrl(
+ const GURL& url,
+ base::OnceCallback<void(std::vector<Login>)> callback) override {
+ OnGetLoginsForUrl(url, callback);
+ }
+
+ MOCK_METHOD2(OnGetLoginsForUrl,
+ void(const GURL& domain,
+ base::OnceCallback<void(std::vector<Login>)>&));
+
+ void GetPasswordForLogin(
+ const Login& login,
+ base::OnceCallback<void(bool, std::string)> callback) override {
+ OnGetPasswordForLogin(login, callback);
+ }
+
+ MOCK_METHOD2(OnGetPasswordForLogin,
+ void(const Login& login,
+ base::OnceCallback<void(bool, std::string)>&));
+
+ DISALLOW_COPY_AND_ASSIGN(MockWebsiteLoginFetcher);
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_WEBSITE_LOGIN_FETCHER_H_
diff --git a/chromium/components/autofill_assistant/browser/payment_request.cc b/chromium/components/autofill_assistant/browser/payment_request.cc
deleted file mode 100644
index 88ed062d0e7..00000000000
--- a/chromium/components/autofill_assistant/browser/payment_request.cc
+++ /dev/null
@@ -1,18 +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 "components/autofill_assistant/browser/payment_request.h"
-
-#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/autofill/core/browser/data_model/credit_card.h"
-
-namespace autofill_assistant {
-
-PaymentInformation::PaymentInformation() = default;
-PaymentInformation::~PaymentInformation() = default;
-
-PaymentRequestOptions::PaymentRequestOptions() = default;
-PaymentRequestOptions::~PaymentRequestOptions() = default;
-
-} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/protocol_utils.cc b/chromium/components/autofill_assistant/browser/protocol_utils.cc
index 8f336e2399f..da35b0958c5 100644
--- a/chromium/components/autofill_assistant/browser/protocol_utils.cc
+++ b/chromium/components/autofill_assistant/browser/protocol_utils.cc
@@ -10,10 +10,10 @@
#include "base/logging.h"
#include "components/autofill_assistant/browser/actions/autofill_action.h"
#include "components/autofill_assistant/browser/actions/click_action.h"
+#include "components/autofill_assistant/browser/actions/collect_user_data_action.h"
#include "components/autofill_assistant/browser/actions/configure_bottom_sheet_action.h"
#include "components/autofill_assistant/browser/actions/expect_navigation_action.h"
#include "components/autofill_assistant/browser/actions/focus_element_action.h"
-#include "components/autofill_assistant/browser/actions/get_payment_information_action.h"
#include "components/autofill_assistant/browser/actions/highlight_element_action.h"
#include "components/autofill_assistant/browser/actions/navigate_action.h"
#include "components/autofill_assistant/browser/actions/popup_message_action.h"
@@ -250,9 +250,9 @@ bool ProtocolUtils::ParseActions(ActionDelegate* delegate,
client_action = std::make_unique<ShowDetailsAction>(delegate, action);
break;
}
- case ActionProto::ActionInfoCase::kGetPaymentInformation: {
+ case ActionProto::ActionInfoCase::kCollectUserData: {
client_action =
- std::make_unique<GetPaymentInformationAction>(delegate, action);
+ std::make_unique<CollectUserDataAction>(delegate, action);
break;
}
case ActionProto::ActionInfoCase::kSetFormValue: {
diff --git a/chromium/components/autofill_assistant/browser/retry_timer.cc b/chromium/components/autofill_assistant/browser/retry_timer.cc
index 047f77ea652..4ded92bbd45 100644
--- a/chromium/components/autofill_assistant/browser/retry_timer.cc
+++ b/chromium/components/autofill_assistant/browser/retry_timer.cc
@@ -9,8 +9,7 @@
namespace autofill_assistant {
-RetryTimer::RetryTimer(base::TimeDelta period)
- : period_(period), weak_ptr_factory_(this) {}
+RetryTimer::RetryTimer(base::TimeDelta period) : period_(period) {}
RetryTimer::~RetryTimer() = default;
void RetryTimer::Start(
diff --git a/chromium/components/autofill_assistant/browser/retry_timer.h b/chromium/components/autofill_assistant/browser/retry_timer.h
index 40f6c12ab89..af5876d6a47 100644
--- a/chromium/components/autofill_assistant/browser/retry_timer.h
+++ b/chromium/components/autofill_assistant/browser/retry_timer.h
@@ -63,7 +63,7 @@ class RetryTimer {
base::OnceCallback<void(bool)> on_done_;
std::unique_ptr<base::OneShotTimer> timer_;
- base::WeakPtrFactory<RetryTimer> weak_ptr_factory_;
+ base::WeakPtrFactory<RetryTimer> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(RetryTimer);
};
diff --git a/chromium/components/autofill_assistant/browser/retry_timer_unittest.cc b/chromium/components/autofill_assistant/browser/retry_timer_unittest.cc
index e467d15d4de..1bad81484dc 100644
--- a/chromium/components/autofill_assistant/browser/retry_timer_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/retry_timer_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::testing::_;
@@ -23,11 +23,10 @@ namespace {
class RetryTimerTest : public testing::Test {
protected:
RetryTimerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void FastForwardOneSecond() {
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
base::RepeatingCallback<void(base::OnceCallback<void(bool)>)>
@@ -65,9 +64,9 @@ class RetryTimerTest : public testing::Test {
captured_callback_ = std::move(callback);
}
- // scoped_task_environment_ must be first to guarantee other field
+ // task_environment_ must be first to guarantee other field
// creation run in that environment.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
int try_count_ = 0;
base::OnceCallback<void(bool)> captured_callback_;
diff --git a/chromium/components/autofill_assistant/browser/script_executor.cc b/chromium/components/autofill_assistant/browser/script_executor.cc
index 5c457225b6c..acef62b3243 100644
--- a/chromium/components/autofill_assistant/browser/script_executor.cc
+++ b/chromium/components/autofill_assistant/browser/script_executor.cc
@@ -23,7 +23,7 @@
#include "components/autofill_assistant/browser/self_delete_full_card_requester.h"
#include "components/autofill_assistant/browser/service.h"
#include "components/autofill_assistant/browser/trigger_context.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
@@ -203,25 +203,28 @@ void ScriptExecutor::ClickOrTapElement(
std::move(callback));
}
-void ScriptExecutor::GetPaymentInformation(
- std::unique_ptr<PaymentRequestOptions> options) {
- options->confirm_callback = base::BindOnce(
- &ScriptExecutor::OnGetPaymentInformation, weak_ptr_factory_.GetWeakPtr(),
- std::move(options->confirm_callback));
- options->additional_actions_callback =
- base::BindOnce(&ScriptExecutor::OnAdditionalActionTriggered,
+void ScriptExecutor::CollectUserData(
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) {
+ collect_user_data_options->confirm_callback = base::BindOnce(
+ &ScriptExecutor::OnGetUserData, weak_ptr_factory_.GetWeakPtr(),
+ std::move(collect_user_data_options->confirm_callback));
+ collect_user_data_options->additional_actions_callback = base::BindOnce(
+ &ScriptExecutor::OnAdditionalActionTriggered,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(collect_user_data_options->additional_actions_callback));
+ collect_user_data_options->terms_link_callback =
+ base::BindOnce(&ScriptExecutor::OnTermsAndConditionsLinkClicked,
weak_ptr_factory_.GetWeakPtr(),
- std::move(options->additional_actions_callback));
- options->terms_link_callback = base::BindOnce(
- &ScriptExecutor::OnTermsAndConditionsLinkClicked,
- weak_ptr_factory_.GetWeakPtr(), std::move(options->terms_link_callback));
- delegate_->SetPaymentRequestOptions(std::move(options));
+ std::move(collect_user_data_options->terms_link_callback));
+ delegate_->SetCollectUserDataOptions(std::move(collect_user_data_options),
+ std::move(user_data));
delegate_->EnterState(AutofillAssistantState::PROMPT);
}
-void ScriptExecutor::OnGetPaymentInformation(
- base::OnceCallback<void(std::unique_ptr<PaymentInformation>)> callback,
- std::unique_ptr<PaymentInformation> result) {
+void ScriptExecutor::OnGetUserData(
+ base::OnceCallback<void(std::unique_ptr<UserData>)> callback,
+ std::unique_ptr<UserData> result) {
delegate_->EnterState(AutofillAssistantState::RUNNING);
std::move(callback).Run(std::move(result));
}
@@ -294,10 +297,6 @@ void ScriptExecutor::Prompt(
}
void ScriptExecutor::CancelPrompt() {
- // Delete on_terminate_prompt_ if necessary, without running.
- if (on_terminate_prompt_)
- std::move(on_terminate_prompt_);
-
delegate_->SetUserActions(nullptr);
CleanUpAfterPrompt();
}
@@ -492,10 +491,18 @@ autofill::PersonalDataManager* ScriptExecutor::GetPersonalDataManager() {
return delegate_->GetPersonalDataManager();
}
+WebsiteLoginFetcher* ScriptExecutor::GetWebsiteLoginFetcher() {
+ return delegate_->GetWebsiteLoginFetcher();
+}
+
content::WebContents* ScriptExecutor::GetWebContents() {
return delegate_->GetWebContents();
}
+std::string ScriptExecutor::GetAccountEmailAddress() {
+ return delegate_->GetAccountEmailAddress();
+}
+
void ScriptExecutor::SetDetails(std::unique_ptr<Details> details) {
return delegate_->SetDetails(std::move(details));
}
@@ -753,8 +760,7 @@ ScriptExecutor::WaitForDomOperation::WaitForDomOperation(
check_elements_(std::move(check_elements)),
callback_(std::move(callback)),
retry_timer_(main_script->delegate_->GetSettings()
- .periodic_element_check_interval),
- weak_ptr_factory_(this) {}
+ .periodic_element_check_interval) {}
ScriptExecutor::WaitForDomOperation::~WaitForDomOperation() {
delegate_->RemoveListener(this);
diff --git a/chromium/components/autofill_assistant/browser/script_executor.h b/chromium/components/autofill_assistant/browser/script_executor.h
index 749746f75ae..aa79feb0621 100644
--- a/chromium/components/autofill_assistant/browser/script_executor.h
+++ b/chromium/components/autofill_assistant/browser/script_executor.h
@@ -118,8 +118,9 @@ class ScriptExecutor : public ActionDelegate,
const Selector& selector,
ClickAction::ClickType click_type,
base::OnceCallback<void(const ClientStatus&)> callback) override;
- void GetPaymentInformation(
- std::unique_ptr<PaymentRequestOptions> options) override;
+ void CollectUserData(
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) override;
void GetFullCard(GetFullCardCallback callback) override;
void Prompt(std::unique_ptr<std::vector<UserAction>> user_actions) override;
void CancelPrompt() override;
@@ -187,7 +188,9 @@ class ScriptExecutor : public ActionDelegate,
void Restart() override;
ClientMemory* GetClientMemory() override;
autofill::PersonalDataManager* GetPersonalDataManager() override;
+ WebsiteLoginFetcher* GetWebsiteLoginFetcher() override;
content::WebContents* GetWebContents() override;
+ std::string GetAccountEmailAddress() override;
void SetDetails(std::unique_ptr<Details> details) override;
void ClearInfoBox() override;
void SetInfoBox(const InfoBox& info_box) override;
@@ -301,7 +304,7 @@ class ScriptExecutor : public ActionDelegate,
RetryTimer retry_timer_;
- base::WeakPtrFactory<WaitForDomOperation> weak_ptr_factory_;
+ base::WeakPtrFactory<WaitForDomOperation> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WaitForDomOperation);
};
@@ -328,9 +331,9 @@ class ScriptExecutor : public ActionDelegate,
base::OnceCallback<void(ProcessedActionStatusProto)> callback,
bool element_found,
const Result* interrupt_result);
- void OnGetPaymentInformation(
- base::OnceCallback<void(std::unique_ptr<PaymentInformation>)> callback,
- std::unique_ptr<PaymentInformation> result);
+ void OnGetUserData(
+ base::OnceCallback<void(std::unique_ptr<UserData>)> callback,
+ std::unique_ptr<UserData> result);
void OnAdditionalActionTriggered(base::OnceCallback<void(int)> callback,
int index);
void OnTermsAndConditionsLinkClicked(base::OnceCallback<void(int)> callback,
@@ -366,10 +369,6 @@ class ScriptExecutor : public ActionDelegate,
TopPadding last_focused_element_top_padding_;
std::unique_ptr<ElementAreaProto> touchable_element_area_;
- // Callback set by Prompt(). This is called when the prompt is terminated
- // without selecting any chips. nullptr unless showing a prompt.
- base::OnceCallback<void()> on_terminate_prompt_;
-
// Steps towards the requirements for calling |on_expected_navigation_done_|
// to be fulfilled.
enum class ExpectedNavigationStep {
diff --git a/chromium/components/autofill_assistant/browser/script_executor_delegate.h b/chromium/components/autofill_assistant/browser/script_executor_delegate.h
index dd25491675c..f74b05ef5d9 100644
--- a/chromium/components/autofill_assistant/browser/script_executor_delegate.h
+++ b/chromium/components/autofill_assistant/browser/script_executor_delegate.h
@@ -12,9 +12,9 @@
#include "components/autofill_assistant/browser/details.h"
#include "components/autofill_assistant/browser/info_box.h"
-#include "components/autofill_assistant/browser/payment_request.h"
#include "components/autofill_assistant/browser/state.h"
#include "components/autofill_assistant/browser/user_action.h"
+#include "components/autofill_assistant/browser/user_data.h"
#include "components/autofill_assistant/browser/viewport_mode.h"
#include "url/gurl.h"
@@ -33,6 +33,7 @@ class WebController;
class ClientMemory;
struct ClientSettings;
class TriggerContext;
+class WebsiteLoginFetcher;
class ScriptExecutorDelegate {
public:
@@ -51,7 +52,9 @@ class ScriptExecutorDelegate {
virtual ClientMemory* GetClientMemory() = 0;
virtual const TriggerContext* GetTriggerContext() = 0;
virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0;
+ virtual WebsiteLoginFetcher* GetWebsiteLoginFetcher() = 0;
virtual content::WebContents* GetWebContents() = 0;
+ virtual std::string GetAccountEmailAddress() = 0;
virtual void EnterState(AutofillAssistantState state) = 0;
// Make the area of the screen that correspond to the given elements
@@ -64,8 +67,9 @@ class ScriptExecutorDelegate {
virtual void SetDetails(std::unique_ptr<Details> details) = 0;
virtual void SetInfoBox(const InfoBox& info_box) = 0;
virtual void ClearInfoBox() = 0;
- virtual void SetPaymentRequestOptions(
- std::unique_ptr<PaymentRequestOptions> options) = 0;
+ virtual void SetCollectUserDataOptions(
+ std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
+ std::unique_ptr<UserData> user_data) = 0;
virtual void SetProgress(int progress) = 0;
virtual void SetProgressVisible(bool visible) = 0;
virtual void SetUserActions(
diff --git a/chromium/components/autofill_assistant/browser/script_executor_unittest.cc b/chromium/components/autofill_assistant/browser/script_executor_unittest.cc
index 1a791ae5205..f6d73e7576b 100644
--- a/chromium/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -10,12 +10,12 @@
#include "base/strings/strcat.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill_assistant/browser/client_memory.h"
#include "components/autofill_assistant/browser/fake_script_executor_delegate.h"
#include "components/autofill_assistant/browser/mock_service.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
#include "components/autofill_assistant/browser/service.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -76,8 +76,7 @@ class ScriptExecutorTest : public testing::Test,
protected:
ScriptExecutorTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
// Implements ScriptExecutor::Listener
void OnServerPayloadChanged(const std::string& global_payload,
@@ -145,9 +144,9 @@ class ScriptExecutorTest : public testing::Test,
interrupts_.emplace_back(std::move(interrupt));
}
- // scoped_task_environment_ must be first to guarantee other field
+ // task_environment_ must be first to guarantee other field
// creation run in that environment.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
FakeScriptExecutorDelegate delegate_;
Script script_;
StrictMock<MockService> mock_service_;
@@ -364,14 +363,13 @@ TEST_F(ScriptExecutorTest, RunDelayedAction) {
// executor_callback_.Run() not expected to be run just yet, as the action is
// delayed.
executor_->Run(executor_callback_.Get());
- EXPECT_TRUE(scoped_task_environment_.NextTaskIsDelayed());
+ EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
// Moving forward in time triggers action execution.
EXPECT_CALL(executor_callback_,
Run(Field(&ScriptExecutor::Result::success, true)));
- scoped_task_environment_.FastForwardBy(
- base::TimeDelta::FromMilliseconds(1000));
- EXPECT_EQ(scoped_task_environment_.GetPendingMainThreadTaskCount(), 0u);
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1000));
+ EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 0u);
}
TEST_F(ScriptExecutorTest, ClearDetailsWhenFinished) {
@@ -533,7 +531,7 @@ TEST_F(ScriptExecutorTest, WaitForDomWaitUntil) {
OnElementCheck(Eq(Selector({"element"})), _))
.WillRepeatedly(RunOnceCallback<1>(true));
EXPECT_CALL(executor_callback_, Run(_));
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
ASSERT_EQ(1u, processed_actions_capture.size());
EXPECT_EQ(ACTION_APPLIED, processed_actions_capture[0].status());
@@ -562,7 +560,7 @@ TEST_F(ScriptExecutorTest, WaitForDomWaitWhile) {
OnElementCheck(Eq(Selector({"element"})), _))
.WillRepeatedly(RunOnceCallback<1>(false));
EXPECT_CALL(executor_callback_, Run(_));
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
ASSERT_EQ(1u, processed_actions_capture.size());
EXPECT_EQ(ACTION_APPLIED, processed_actions_capture[0].status());
@@ -1012,7 +1010,7 @@ TEST_F(ScriptExecutorTest, PauseWaitForDomWhileNavigating) {
// timeout.
delegate_.UpdateNavigationState(/* navigating= */ true, /* error= */ false);
for (int i = 0; i < 5; i++) {
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
// The end of navigation un-pauses WaitForDom.
@@ -1166,7 +1164,7 @@ TEST_F(ScriptExecutorTest, ReportNavigationEnd) {
EXPECT_CALL(mock_web_controller_,
OnElementCheck(Eq(Selector({"element"})), _))
.WillOnce(RunOnceCallback<1>(true));
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
ASSERT_THAT(processed_actions_capture, SizeIs(1));
EXPECT_EQ(ACTION_APPLIED, processed_actions_capture[0].status());
diff --git a/chromium/components/autofill_assistant/browser/script_precondition.h b/chromium/components/autofill_assistant/browser/script_precondition.h
index a3fc9967218..db4502a4894 100644
--- a/chromium/components/autofill_assistant/browser/script_precondition.h
+++ b/chromium/components/autofill_assistant/browser/script_precondition.h
@@ -16,7 +16,7 @@
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/element_precondition.h"
#include "components/autofill_assistant/browser/service.pb.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
namespace re2 {
class RE2;
diff --git a/chromium/components/autofill_assistant/browser/script_precondition_unittest.cc b/chromium/components/autofill_assistant/browser/script_precondition_unittest.cc
index 12120196cae..d4057a1bff8 100644
--- a/chromium/components/autofill_assistant/browser/script_precondition_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/script_precondition_unittest.cc
@@ -11,9 +11,9 @@
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
#include "components/autofill_assistant/browser/batch_element_checker.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/trigger_context.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/re2/src/re2/re2.h"
diff --git a/chromium/components/autofill_assistant/browser/script_tracker.cc b/chromium/components/autofill_assistant/browser/script_tracker.cc
index 2bfc842305f..a5a593dd652 100644
--- a/chromium/components/autofill_assistant/browser/script_tracker.cc
+++ b/chromium/components/autofill_assistant/browser/script_tracker.cc
@@ -47,9 +47,7 @@ base::Value ToValueArray(const T& v) {
ScriptTracker::ScriptTracker(ScriptExecutorDelegate* delegate,
ScriptTracker::Listener* listener)
- : delegate_(delegate),
- listener_(listener),
- weak_ptr_factory_(this) {
+ : delegate_(delegate), listener_(listener) {
DCHECK(delegate_);
DCHECK(listener_);
}
diff --git a/chromium/components/autofill_assistant/browser/script_tracker.h b/chromium/components/autofill_assistant/browser/script_tracker.h
index 373540bde93..bfb53e46789 100644
--- a/chromium/components/autofill_assistant/browser/script_tracker.h
+++ b/chromium/components/autofill_assistant/browser/script_tracker.h
@@ -176,7 +176,7 @@ class ScriptTracker : public ScriptExecutor::Listener {
// only occurse when |scripts_update| is not nullptr.
std::unique_ptr<std::vector<std::unique_ptr<Script>>> scripts_update_;
- base::WeakPtrFactory<ScriptTracker> weak_ptr_factory_;
+ base::WeakPtrFactory<ScriptTracker> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ScriptTracker);
};
diff --git a/chromium/components/autofill_assistant/browser/script_tracker_unittest.cc b/chromium/components/autofill_assistant/browser/script_tracker_unittest.cc
index 19457bed7c8..131774ab00f 100644
--- a/chromium/components/autofill_assistant/browser/script_tracker_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/script_tracker_unittest.cc
@@ -10,10 +10,10 @@
#include "base/test/mock_callback.h"
#include "components/autofill_assistant/browser/fake_script_executor_delegate.h"
#include "components/autofill_assistant/browser/mock_service.h"
-#include "components/autofill_assistant/browser/mock_web_controller.h"
#include "components/autofill_assistant/browser/protocol_utils.h"
#include "components/autofill_assistant/browser/script_executor_delegate.h"
#include "components/autofill_assistant/browser/service.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
diff --git a/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.cc b/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.cc
index b21d90c96dd..b2b657319cc 100644
--- a/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.cc
+++ b/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.cc
@@ -18,8 +18,7 @@
namespace autofill_assistant {
-SelfDeleteFullCardRequester::SelfDeleteFullCardRequester()
- : weak_ptr_factory_(this) {}
+SelfDeleteFullCardRequester::SelfDeleteFullCardRequester() {}
void SelfDeleteFullCardRequester::GetFullCard(
content::WebContents* web_contents,
diff --git a/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.h b/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.h
index e9e09fa576e..4c01bcfe8ef 100644
--- a/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.h
+++ b/chromium/components/autofill_assistant/browser/self_delete_full_card_requester.h
@@ -38,7 +38,7 @@ class SelfDeleteFullCardRequester
ActionDelegate::GetFullCardCallback callback_;
- base::WeakPtrFactory<SelfDeleteFullCardRequester> weak_ptr_factory_;
+ base::WeakPtrFactory<SelfDeleteFullCardRequester> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SelfDeleteFullCardRequester);
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/service.proto b/chromium/components/autofill_assistant/browser/service.proto
index f865ea64025..e4be415d685 100644
--- a/chromium/components/autofill_assistant/browser/service.proto
+++ b/chromium/components/autofill_assistant/browser/service.proto
@@ -107,6 +107,29 @@ message ClientSettingsProto {
// Maximum number of checks to run while waiting for the document to become
// ready.
optional int32 document_ready_check_count = 9;
+
+ // Whether graceful shutdown should be enabled. If false, the UI stays
+ // up until it's dismissed.
+ optional bool enable_graceful_shutdown = 10;
+
+ // How long to wait before shutting down during graceful shutdown. If 0
+ // shutdown happens immediately.
+ optional int32 graceful_shutdown_delay_ms = 11;
+
+ // How much time to give users to tap undo when they tap a cancel button.
+ optional int32 cancel_delay_ms = 12;
+
+ // If the user taps the overlay that many time within |tap_duration| turn the
+ // UI off and give them |tap_shutdown_delay| to undo. If 0, unexpected taps
+ // are ignored.
+ optional int32 tap_count = 13;
+
+ // Reset the unexpected tap counter after that time.
+ optional int32 tap_tracking_duration_ms = 14;
+
+ // How much time to give users to tap undo when after |tap_count| unexpected
+ // taps where
+ optional int32 tap_shutdown_delay_ms = 15;
}
message ScriptTimeoutError {
@@ -402,7 +425,7 @@ message ActionProto {
ShowDetailsProto show_details = 32;
ResetProto reset = 34;
StopProto stop = 35;
- GetPaymentInformationProto get_payment_information = 36;
+ CollectUserDataProto collect_user_data = 36;
SetAttributeProto set_attribute = 37;
ShowInfoBoxProto show_info_box = 39;
ExpectNavigationProto expect_navigation = 40;
@@ -419,20 +442,22 @@ message ActionProto {
optional bool clean_contextual_ui = 33;
}
-// Result message used to send payment request related data to the server.
-message PaymentDetails {
+// Result of |CollectUserDataProto| to be sent to the server.
+message CollectUserDataResultProto {
optional string card_issuer_network = 1;
// Whether the integrated terms and conditions approval checkbox was checked.
optional bool is_terms_and_conditions_accepted = 2;
// The email address of the payer.
optional string payer_email = 3;
// If set, this means that the user triggered the action in
- // |GetPaymentInformationProto.additional_actions| that has index
+ // |CollectUserDataProto.additional_actions| that has index
// |additional_action_index|.
optional int32 additional_action_index = 4;
// If set, this means that the user clicked on one of the terms and conditions
// links.
optional int32 terms_link = 5;
+ // The payload of the chosen login option.
+ optional bytes login_payload = 6;
}
message ProcessedActionProto {
@@ -446,8 +471,8 @@ message ProcessedActionProto {
oneof result_data {
PromptProto.Choice prompt_choice = 5;
string html_source = 12;
- // Should be set as a result of GetPaymentInformationAction.
- PaymentDetails payment_details = 15;
+ // Should be set as a result of CollectUserDataAction.
+ CollectUserDataResultProto collect_user_data_result = 15;
// Should be set as a result of SetFormFieldValueAction.
SetFormFieldValueProto.Result set_form_field_value_result = 17;
// May be set as a result of WaitForDomProto.
@@ -540,6 +565,12 @@ message UnexpectedErrorInfoProto {
// JavaScript exception column number, within the js snippet that was sent to
// devtools runtime by the client, if reporting a JavaScript error.
optional int32 js_exception_column_number = 5;
+
+ // Error code returned by devtools, if any. 0 is considered a success.
+ optional int32 devtools_error_code = 6;
+
+ // Error message returned by devtools, if any.
+ optional string devtools_error_message = 7;
}
// Message to report autofill related errors for debugging purposes.
@@ -572,8 +603,8 @@ enum ProcessedActionStatusProto {
// ProcessedActionProto.UnexpectedErrorInfoProto contains more details.
OTHER_ACTION_STATUS = 3;
- // The action failed to get payment information.
- PAYMENT_REQUEST_ERROR = 4;
+ // The action failed to collect the requested user data.
+ COLLECT_USER_DATA_ERROR = 4;
// Server asked the client to execute an unknown or unsupported action.
UNSUPPORTED_ACTION = 5;
@@ -609,8 +640,7 @@ enum ProcessedActionStatusProto {
//
// This is currently returned by the autofill action, when it could not find
// the credit card or the address it needs in the client memory. This is
- // usually the sign that the Get Payment Information action was not run or
- // failed.
+ // usually the sign that the CollectUserDataAction was not run or failed.
//
PRECONDITION_FAILED = 10;
@@ -650,6 +680,10 @@ enum ProcessedActionStatusProto {
// A selector included into the current action is invalid.
INVALID_SELECTOR = 20;
+
+ // The requested autofill info (e.g., Chrome password manager login) was not
+ // available. It might have been recently deleted.
+ AUTOFILL_INFO_NOT_AVAILABLE = 21;
}
// The pseudo type values come from
@@ -855,7 +889,8 @@ message UseAddressProto {
repeated RequiredField required_fields = 6;
}
-// Fill a form with a credit card if there is, otherwise fail this action.
+// Fill a form with a credit card if there is one stored in client memory,
+// otherwise fail this action.
message UseCreditCardProto {
// Message used to indicate what form fields should be filled with what
// information.
@@ -1124,9 +1159,42 @@ message ContactDetailsProto {
optional bool request_payer_phone = 4;
}
+message LoginDetailsProto {
+ // A custom login option which will be handled by the backend, e.g.,
+ // 'Guest checkout' or 'Log in with Google'.
+ message LoginOptionCustomProto {
+ // The label to display to the user.
+ optional string label = 1;
+ }
+
+ // Offers all matching Chrome password manager logins for the current website.
+ message LoginOptionPasswordManagerProto {}
+
+ message LoginOptionProto {
+ // If the option was chosen, this payload will be returned to the server.
+ optional bytes payload = 1;
+
+ // Whether the UI should automatically choose this login option if it is the
+ // only available choice.
+ optional bool choose_automatically_if_no_other_options = 2;
+
+ // Determines the priority with which to pre-select this login choice.
+ // The lower the value, the higher the priority.
+ optional int32 preselection_priority = 3;
+ oneof type {
+ LoginOptionCustomProto custom = 4;
+ LoginOptionPasswordManagerProto password_manager = 5;
+ }
+ }
+ // The title for the login selection (e.g., 'Login details for <domain>').
+ optional string section_title = 1;
+ // The list of available login options.
+ repeated LoginOptionProto login_options = 2;
+}
+
// Asks to provide the data used by UseAddressAction and
// UseCreditCardAction.
-message GetPaymentInformationProto {
+message CollectUserDataProto {
enum TermsAndConditionsState {
// No choice has been made yet.
NOT_SELECTED = 0;
@@ -1137,7 +1205,7 @@ message GetPaymentInformationProto {
}
optional string prompt = 1;
- // NOTE: Payment request does not ask separately for billing address.
+ // NOTE: The action does not ask separately for billing address.
// The billing address is associated with the credit card that was picked.
optional string billing_address_name = 2;
// If present will save the shipping address inside the memory under the
@@ -1145,13 +1213,13 @@ message GetPaymentInformationProto {
// under this name can be reused by UseAddressAction.
optional string shipping_address_name = 3;
// When 'true' will ask for the credit card.
- optional bool ask_for_payment = 4;
+ optional bool request_payment_method = 4;
// If non-empty, the UI will filter the available basic-card networks
// accordingly (e.g., only `visa' and `mastercard').
repeated string supported_basic_card_networks = 6;
// Contact details that should be gathered.
optional ContactDetailsProto contact_details = 5;
- // Override for the text of the confirm button in the payment request.
+ // Override for the text of the confirm button.
optional string confirm_button_text = 7;
// The initial state of the terms & conditions choice.
optional TermsAndConditionsState terms_and_conditions_state = 8;
@@ -1180,6 +1248,8 @@ message GetPaymentInformationProto {
// The error message to display when the billing address is missing the
// postal code. This field is mandatory if |require_postal_code| is true.
optional string billing_postal_code_missing_text = 15;
+ // The login details that should be gathered.
+ optional LoginDetailsProto login_details = 16;
}
// Resets Autofill Assistant: clears any state and server payload.
@@ -1323,6 +1393,12 @@ message SetFormFieldValueProto {
// layout. This can also be used for keyboard control sequences such
// as "\r" or "\t".
string keyboard_input = 3;
+ // Use the username from the Chrome password manager login previously
+ // selected in a CollectUserDataAction.
+ bool use_username = 4;
+ // Use the password from the Chrome password manager login previously
+ // selected in a CollectUserDataAction.
+ bool use_password = 5;
}
}
diff --git a/chromium/components/autofill_assistant/browser/service_impl.cc b/chromium/components/autofill_assistant/browser/service_impl.cc
index 793dbe906bc..ea0d62c91fd 100644
--- a/chromium/components/autofill_assistant/browser/service_impl.cc
+++ b/chromium/components/autofill_assistant/browser/service_impl.cc
@@ -171,7 +171,7 @@ void ServiceImpl::StartLoader(Loader* loader) {
auto resource_request = std::make_unique<::network::ResourceRequest>();
resource_request->method = "POST";
resource_request->redirect_mode = ::network::mojom::RedirectMode::kError;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = ::network::mojom::CredentialsMode::kOmit;
if (access_token_.empty()) {
std::string query_str = base::StrCat({"key=", api_key_});
// query_str must remain valid until ReplaceComponents() has returned.
diff --git a/chromium/components/autofill_assistant/browser/ui_delegate.h b/chromium/components/autofill_assistant/browser/ui_delegate.h
index 680f94b9180..b6d5f7c2c31 100644
--- a/chromium/components/autofill_assistant/browser/ui_delegate.h
+++ b/chromium/components/autofill_assistant/browser/ui_delegate.h
@@ -11,14 +11,15 @@
#include "base/optional.h"
#include "components/autofill_assistant/browser/metrics.h"
-#include "components/autofill_assistant/browser/payment_request.h"
#include "components/autofill_assistant/browser/rectf.h"
#include "components/autofill_assistant/browser/state.h"
#include "components/autofill_assistant/browser/user_action.h"
+#include "components/autofill_assistant/browser/user_data.h"
#include "components/autofill_assistant/browser/viewport_mode.h"
namespace autofill_assistant {
class ControllerObserver;
+struct ClientSettings;
// UI delegate called for script executions.
class UiDelegate {
@@ -90,50 +91,51 @@ class UiDelegate {
return PerformUserActionWithContext(index, TriggerContext::CreateEmpty());
}
- // If the controller is waiting for payment request information, this
- // field contains a non-null options describing the request.
- virtual const PaymentRequestOptions* GetPaymentRequestOptions() const = 0;
+ // If the controller is waiting for user data, this field contains a non-null
+ // options describing the request.
+ virtual const CollectUserDataOptions* GetCollectUserDataOptions() const = 0;
- // If the controller is waiting for payment request information, this
- // field contains a non-null object describing the currently selected data.
- virtual const PaymentInformation* GetPaymentRequestInformation() const = 0;
+ // If the controller is waiting for user data, this field contains a non-null
+ // object describing the currently selected data.
+ virtual const UserData* GetUserData() const = 0;
- // Sets shipping address, in response to the current payment request options.
+ // Sets shipping address, in response to the current collect user data
+ // options.
virtual void SetShippingAddress(
std::unique_ptr<autofill::AutofillProfile> address) = 0;
- // Sets billing address, in response to the current payment request options.
- virtual void SetBillingAddress(
- std::unique_ptr<autofill::AutofillProfile> address) = 0;
-
- // Sets contact info, in response to the current payment request options.
- virtual void SetContactInfo(std::string name,
- std::string phone,
- std::string email) = 0;
+ // Sets contact info, in response to the current collect user data options.
+ virtual void SetContactInfo(
+ std::unique_ptr<autofill::AutofillProfile> profile) = 0;
- // Sets credit card, in response to the current payment request options.
+ // Sets credit card, in response to the current collect user data options.
virtual void SetCreditCard(std::unique_ptr<autofill::CreditCard> card) = 0;
// Sets the state of the third party terms & conditions, pertaining to the
- // current payment request options.
+ // current collect user data options.
virtual void SetTermsAndConditions(
TermsAndConditionsState terms_and_conditions) = 0;
+ // Sets the chosen login option, pertaining to the current collect user data
+ // options.
+ virtual void SetLoginOption(std::string identifier) = 0;
+
// Called when the user clicks a link on the terms & conditions message.
virtual void OnTermsAndConditionsLinkClicked(int link) = 0;
- // Adds the rectangles that correspond to the current touchable area to the
- // given vector.
+ // Adds the rectangles that correspond to the current touchable area to
+ // the given vector.
//
- // At the end of this call, |rectangles| contains one element per configured
- // rectangles, though these can correspond to empty rectangles. Coordinates
- // absolute CSS coordinates.
+ // At the end of this call, |rectangles| contains one element per
+ // configured rectangles, though these can correspond to empty rectangles.
+ // Coordinates absolute CSS coordinates.
//
// Note that the vector is not cleared before rectangles are added.
virtual void GetTouchableArea(std::vector<RectF>* rectangles) const = 0;
virtual void GetRestrictedArea(std::vector<RectF>* rectangles) const = 0;
- // Returns the current size of the visual viewport. May be empty if unknown.
+ // Returns the current size of the visual viewport. May be empty if
+ // unknown.
//
// The rectangle is expressed in absolute CSS coordinates.
virtual void GetVisualViewport(RectF* viewport) const = 0;
@@ -150,6 +152,9 @@ class UiDelegate {
// Fills in the overlay colors.
virtual void GetOverlayColors(OverlayColors* colors) const = 0;
+ // Gets the current Client Settings
+ virtual const ClientSettings& GetClientSettings() const = 0;
+
// Returns the current form. May be null if there is no form to show.
virtual const FormProto* GetForm() const = 0;
@@ -163,13 +168,15 @@ class UiDelegate {
int choice_index,
bool selected) = 0;
- // Register an observer. Observers get told about changes to the controller.
+ // Register an observer. Observers get told about changes to the
+ // controller.
virtual void AddObserver(ControllerObserver* observer) = 0;
// Remove a previously registered observer.
virtual void RemoveObserver(const ControllerObserver* observer) = 0;
protected:
+ protected:
UiDelegate() = default;
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/user_data.cc b/chromium/components/autofill_assistant/browser/user_data.cc
new file mode 100644
index 00000000000..c518bdfaf26
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/user_data.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 "components/autofill_assistant/browser/user_data.h"
+
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/common/password_form.h"
+
+namespace autofill_assistant {
+
+LoginChoice::LoginChoice(const std::string& id,
+ const std::string& text,
+ int priority)
+ : identifier(id), label(text), preselect_priority(priority) {}
+LoginChoice::~LoginChoice() = default;
+
+UserData::UserData() = default;
+UserData::~UserData() = default;
+
+CollectUserDataOptions::CollectUserDataOptions() = default;
+CollectUserDataOptions::~CollectUserDataOptions() = default;
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/payment_request.h b/chromium/components/autofill_assistant/browser/user_data.h
index 47b771b28c1..4e394741e4e 100644
--- a/chromium/components/autofill_assistant/browser/payment_request.h
+++ b/chromium/components/autofill_assistant/browser/user_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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_PAYMENT_REQUEST_H_
-#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_PAYMENT_REQUEST_H_
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_USER_DATA_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_USER_DATA_H_
#include <memory>
#include <string>
@@ -21,7 +21,7 @@ class CreditCard;
namespace autofill_assistant {
// GENERATED_JAVA_ENUM_PACKAGE: (
-// org.chromium.chrome.browser.autofill_assistant.payment)
+// org.chromium.chrome.browser.autofill_assistant.user_data)
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: AssistantTermsAndConditionsState
enum TermsAndConditionsState {
NOT_SELECTED = 0,
@@ -29,31 +29,45 @@ enum TermsAndConditionsState {
REQUIRES_REVIEW = 2,
};
-// Struct for holding the payment information data.
-struct PaymentInformation {
- PaymentInformation();
- ~PaymentInformation();
+// Represents a concrete login choice in the UI, e.g., 'Guest checkout' or
+// a particular Chrome PWM login account.
+struct LoginChoice {
+ LoginChoice(const std::string& id, const std::string& text, int priority);
+ ~LoginChoice();
+
+ // Uniquely identifies this login choice.
+ std::string identifier;
+ // The label to display to the user.
+ std::string label;
+ // The priority to pre-select this choice (-1 == not set/automatic).
+ int preselect_priority = -1;
+};
+
+// Struct for holding the user data.
+struct UserData {
+ UserData();
+ ~UserData();
bool succeed = false;
+ std::unique_ptr<autofill::AutofillProfile> contact_profile;
std::unique_ptr<autofill::CreditCard> card;
std::unique_ptr<autofill::AutofillProfile> shipping_address;
std::unique_ptr<autofill::AutofillProfile> billing_address;
- std::string payer_name;
- std::string payer_phone;
- std::string payer_email;
+ std::string login_choice_identifier;
TermsAndConditionsState terms_and_conditions = NOT_SELECTED;
};
// Struct for holding the payment request options.
-struct PaymentRequestOptions {
- PaymentRequestOptions();
- ~PaymentRequestOptions();
+struct CollectUserDataOptions {
+ CollectUserDataOptions();
+ ~CollectUserDataOptions();
bool request_payer_name = false;
bool request_payer_email = false;
bool request_payer_phone = false;
bool request_shipping = false;
bool request_payment_method = false;
+ bool request_login_choice = false;
bool require_billing_postal_code = false;
std::string billing_postal_code_missing_text;
@@ -63,16 +77,17 @@ struct PaymentRequestOptions {
bool show_terms_as_checkbox = false;
std::vector<std::string> supported_basic_card_networks;
+ std::vector<LoginChoice> login_choices;
std::string default_email;
+ std::string login_section_title;
UserActionProto confirm_action;
std::vector<UserActionProto> additional_actions;
TermsAndConditionsState initial_terms_and_conditions = NOT_SELECTED;
- base::OnceCallback<void(std::unique_ptr<PaymentInformation>)>
- confirm_callback;
+ base::OnceCallback<void(std::unique_ptr<UserData>)> confirm_callback;
base::OnceCallback<void(int)> additional_actions_callback;
base::OnceCallback<void(int)> terms_link_callback;
};
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_PAYMENT_REQUEST_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_USER_DATA_H_
diff --git a/chromium/components/autofill_assistant/browser/web/element_finder.cc b/chromium/components/autofill_assistant/browser/web/element_finder.cc
new file mode 100644
index 00000000000..86fadcce821
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/element_finder.cc
@@ -0,0 +1,422 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/web/element_finder.h"
+
+#include "components/autofill_assistant/browser/devtools/devtools_client.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/web_controller_util.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace autofill_assistant {
+
+namespace {
+// Javascript code to get document root element.
+const char* const kGetDocumentElement =
+ R"(
+ (function() {
+ return document.documentElement;
+ }())
+ )";
+
+// Javascript code to query an elements for a selector, either the first
+// (non-strict) or a single (strict) element.
+//
+// Returns undefined if no elements are found, TOO_MANY_ELEMENTS (18) if too
+// many elements were found and strict mode is enabled.
+const char* const kQuerySelector =
+ R"(function (selector, strictMode) {
+ var found = this.querySelectorAll(selector);
+ if(found.length == 0) return undefined;
+ if(found.length > 1 && strictMode) return 18;
+ return found[0];
+ })";
+
+// Javascript code to query a visible elements for a selector, either the first
+// (non-strict) or a single (strict) visible element.q
+//
+// Returns undefined if no elements are found, TOO_MANY_ELEMENTS (18) if too
+// many elements were found and strict mode is enabled.
+const char* const kQuerySelectorWithConditions =
+ R"(function (selector, strict, visible, inner_text_str, value_str) {
+ var found = this.querySelectorAll(selector);
+ var found_index = -1;
+ var inner_text_re = inner_text_str ? RegExp(inner_text_str) : undefined;
+ var value_re = value_str ? RegExp(value_str) : undefined;
+ var match = function(e) {
+ if (visible && e.getClientRects().length == 0) return false;
+ if (inner_text_re && !inner_text_re.test(e.innerText)) return false;
+ if (value_re && !value_re.test(e.value)) return false;
+ return true;
+ };
+ for (let i = 0; i < found.length; i++) {
+ if (match(found[i])) {
+ if (found_index != -1) return 18;
+ found_index = i;
+ if (!strict) break;
+ }
+ }
+ return found_index == -1 ? undefined : found[found_index];
+ })";
+
+bool ConvertPseudoType(const PseudoType pseudo_type,
+ dom::PseudoType* pseudo_type_output) {
+ switch (pseudo_type) {
+ case PseudoType::UNDEFINED:
+ break;
+ case PseudoType::FIRST_LINE:
+ *pseudo_type_output = dom::PseudoType::FIRST_LINE;
+ return true;
+ case PseudoType::FIRST_LETTER:
+ *pseudo_type_output = dom::PseudoType::FIRST_LETTER;
+ return true;
+ case PseudoType::BEFORE:
+ *pseudo_type_output = dom::PseudoType::BEFORE;
+ return true;
+ case PseudoType::AFTER:
+ *pseudo_type_output = dom::PseudoType::AFTER;
+ return true;
+ case PseudoType::BACKDROP:
+ *pseudo_type_output = dom::PseudoType::BACKDROP;
+ return true;
+ case PseudoType::SELECTION:
+ *pseudo_type_output = dom::PseudoType::SELECTION;
+ return true;
+ case PseudoType::FIRST_LINE_INHERITED:
+ *pseudo_type_output = dom::PseudoType::FIRST_LINE_INHERITED;
+ return true;
+ case PseudoType::SCROLLBAR:
+ *pseudo_type_output = dom::PseudoType::SCROLLBAR;
+ return true;
+ case PseudoType::SCROLLBAR_THUMB:
+ *pseudo_type_output = dom::PseudoType::SCROLLBAR_THUMB;
+ return true;
+ case PseudoType::SCROLLBAR_BUTTON:
+ *pseudo_type_output = dom::PseudoType::SCROLLBAR_BUTTON;
+ return true;
+ case PseudoType::SCROLLBAR_TRACK:
+ *pseudo_type_output = dom::PseudoType::SCROLLBAR_TRACK;
+ return true;
+ case PseudoType::SCROLLBAR_TRACK_PIECE:
+ *pseudo_type_output = dom::PseudoType::SCROLLBAR_TRACK_PIECE;
+ return true;
+ case PseudoType::SCROLLBAR_CORNER:
+ *pseudo_type_output = dom::PseudoType::SCROLLBAR_CORNER;
+ return true;
+ case PseudoType::RESIZER:
+ *pseudo_type_output = dom::PseudoType::RESIZER;
+ return true;
+ case PseudoType::INPUT_LIST_BUTTON:
+ *pseudo_type_output = dom::PseudoType::INPUT_LIST_BUTTON;
+ return true;
+ }
+ return false;
+}
+} // namespace
+
+ElementFinder::ElementFinder(content::WebContents* web_contents,
+ DevtoolsClient* devtools_client,
+ const Selector& selector,
+ bool strict)
+ : web_contents_(web_contents),
+ devtools_client_(devtools_client),
+ selector_(selector),
+ strict_(strict),
+ element_result_(std::make_unique<Result>()) {}
+
+ElementFinder::~ElementFinder() = default;
+
+void ElementFinder::Start(Callback callback) {
+ callback_ = std::move(callback);
+
+ if (selector_.empty()) {
+ SendResult(ClientStatus(INVALID_SELECTOR));
+ return;
+ }
+ devtools_client_->GetRuntime()->Evaluate(
+ std::string(kGetDocumentElement),
+ base::BindOnce(&ElementFinder::OnGetDocumentElement,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ElementFinder::SendResult(const ClientStatus& status) {
+ DCHECK(callback_);
+ DCHECK(element_result_);
+ std::move(callback_).Run(status, std::move(element_result_));
+}
+
+void ElementFinder::OnGetDocumentElement(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::EvaluateResult> result) {
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
+ if (!status.ok()) {
+ DVLOG(1) << __func__ << " Failed to get document root element.";
+ SendResult(status);
+ return;
+ }
+ std::string object_id;
+ if (!SafeGetObjectId(result->GetResult(), &object_id)) {
+ DVLOG(1) << __func__ << " Failed to get document root element.";
+ SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
+ return;
+ }
+ element_result_->container_frame_host = web_contents_->GetMainFrame();
+ element_result_->container_frame_selector_index = 0;
+ element_result_->object_id = "";
+ RecursiveFindElement(object_id, 0);
+}
+
+void ElementFinder::RecursiveFindElement(const std::string& object_id,
+ size_t index) {
+ std::vector<std::unique_ptr<runtime::CallArgument>> argument;
+ argument.emplace_back(runtime::CallArgument::Builder()
+ .SetValue(base::Value::ToUniquePtrValue(
+ base::Value(selector_.selectors[index])))
+ .Build());
+ // For finding intermediate elements, strict mode would be more appropriate,
+ // as long as the logic does not support more than one intermediate match.
+ //
+ // TODO(b/129387787): first, add logging to figure out whether it matters and
+ // decide between strict mode and full support for multiple matching
+ // intermeditate elements.
+ argument.emplace_back(
+ runtime::CallArgument::Builder()
+ .SetValue(base::Value::ToUniquePtrValue(base::Value(strict_)))
+ .Build());
+ std::string function;
+ if (index == (selector_.selectors.size() - 1)) {
+ if (selector_.must_be_visible || !selector_.inner_text_pattern.empty() ||
+ !selector_.value_pattern.empty()) {
+ function.assign(kQuerySelectorWithConditions);
+ argument.emplace_back(runtime::CallArgument::Builder()
+ .SetValue(base::Value::ToUniquePtrValue(
+ base::Value(selector_.must_be_visible)))
+ .Build());
+ argument.emplace_back(runtime::CallArgument::Builder()
+ .SetValue(base::Value::ToUniquePtrValue(
+ base::Value(selector_.inner_text_pattern)))
+ .Build());
+ argument.emplace_back(runtime::CallArgument::Builder()
+ .SetValue(base::Value::ToUniquePtrValue(
+ base::Value(selector_.value_pattern)))
+ .Build());
+ }
+ }
+ if (function.empty()) {
+ function.assign(kQuerySelector);
+ }
+ devtools_client_->GetRuntime()->CallFunctionOn(
+ runtime::CallFunctionOnParams::Builder()
+ .SetObjectId(object_id)
+ .SetArguments(std::move(argument))
+ .SetFunctionDeclaration(function)
+ .Build(),
+ base::BindOnce(&ElementFinder::OnQuerySelectorAll,
+ weak_ptr_factory_.GetWeakPtr(), index));
+}
+
+void ElementFinder::OnQuerySelectorAll(
+ size_t index,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result) {
+ if (!result) {
+ // It is possible for a document element to already exist, but not be
+ // available yet to query because the document hasn't been loaded. This
+ // results in OnQuerySelectorAll getting a nullptr result. For this specific
+ // call, it is expected.
+ DVLOG(1) << __func__ << ": Context doesn't exist yet to query selector "
+ << index << " of " << selector_;
+ SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
+ return;
+ }
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
+ if (!status.ok()) {
+ DVLOG(1) << __func__ << ": Failed to query selector " << index << " of "
+ << selector_;
+ SendResult(status);
+ return;
+ }
+ int int_result;
+ if (SafeGetIntValue(result->GetResult(), &int_result)) {
+ DCHECK(int_result == TOO_MANY_ELEMENTS);
+ SendResult(ClientStatus(TOO_MANY_ELEMENTS));
+ return;
+ }
+ std::string object_id;
+ if (!SafeGetObjectId(result->GetResult(), &object_id)) {
+ SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
+ return;
+ }
+
+ if (selector_.selectors.size() == index + 1) {
+ // The pseudo type is associated to the final element matched by
+ // |selector_|, which means that we currently don't handle matching an
+ // element inside a pseudo element.
+ if (selector_.pseudo_type == PseudoType::UNDEFINED) {
+ // Return object id of the element.
+ element_result_->object_id = object_id;
+ SendResult(OkClientStatus());
+ return;
+ }
+
+ // We are looking for a pseudo element associated with this element.
+ dom::PseudoType pseudo_type;
+ if (!ConvertPseudoType(selector_.pseudo_type, &pseudo_type)) {
+ // Return empty result.
+ SendResult(ClientStatus(INVALID_ACTION));
+ return;
+ }
+
+ devtools_client_->GetDOM()->DescribeNode(
+ dom::DescribeNodeParams::Builder().SetObjectId(object_id).Build(),
+ base::BindOnce(&ElementFinder::OnDescribeNodeForPseudoElement,
+ weak_ptr_factory_.GetWeakPtr(), pseudo_type));
+ return;
+ }
+
+ devtools_client_->GetDOM()->DescribeNode(
+ dom::DescribeNodeParams::Builder().SetObjectId(object_id).Build(),
+ base::BindOnce(&ElementFinder::OnDescribeNode,
+ weak_ptr_factory_.GetWeakPtr(), object_id, index));
+}
+
+void ElementFinder::OnDescribeNodeForPseudoElement(
+ dom::PseudoType pseudo_type,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::DescribeNodeResult> result) {
+ if (!result || !result->GetNode()) {
+ DVLOG(1) << __func__ << " Failed to describe the node for pseudo element.";
+ SendResult(UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+
+ auto* node = result->GetNode();
+ if (node->HasPseudoElements()) {
+ for (const auto& pseudo_element : *(node->GetPseudoElements())) {
+ if (pseudo_element->HasPseudoType() &&
+ pseudo_element->GetPseudoType() == pseudo_type) {
+ devtools_client_->GetDOM()->ResolveNode(
+ dom::ResolveNodeParams::Builder()
+ .SetBackendNodeId(pseudo_element->GetBackendNodeId())
+ .Build(),
+ base::BindOnce(&ElementFinder::OnResolveNodeForPseudoElement,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+ }
+ }
+
+ // Failed to find the pseudo element: run the callback with empty result.
+ SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
+}
+
+void ElementFinder::OnResolveNodeForPseudoElement(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::ResolveNodeResult> result) {
+ if (result && result->GetObject() && result->GetObject()->HasObjectId()) {
+ element_result_->object_id = result->GetObject()->GetObjectId();
+ }
+ SendResult(OkClientStatus());
+}
+
+void ElementFinder::OnDescribeNode(
+ const std::string& object_id,
+ size_t index,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::DescribeNodeResult> result) {
+ if (!result || !result->GetNode()) {
+ DVLOG(1) << __func__ << " Failed to describe the node.";
+ SendResult(UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+
+ auto* node = result->GetNode();
+ std::vector<int> backend_ids;
+ if (node->HasContentDocument()) {
+ backend_ids.emplace_back(node->GetContentDocument()->GetBackendNodeId());
+
+ element_result_->container_frame_selector_index = index;
+
+ // Find out the corresponding render frame host through document url and
+ // name.
+ // TODO(crbug.com/806868): Use more attributes to find out the render frame
+ // host if name and document url are not enough to uniquely identify it.
+ std::string frame_name;
+ if (node->HasAttributes()) {
+ const std::vector<std::string>* attributes = node->GetAttributes();
+ for (size_t i = 0; i < attributes->size();) {
+ if ((*attributes)[i] == "name") {
+ frame_name = (*attributes)[i + 1];
+ break;
+ }
+ // Jump two positions since attribute name and value are always paired.
+ i = i + 2;
+ }
+ }
+ element_result_->container_frame_host = FindCorrespondingRenderFrameHost(
+ frame_name, node->GetContentDocument()->GetDocumentURL());
+ if (!element_result_->container_frame_host) {
+ DVLOG(1) << __func__ << " Failed to find corresponding owner frame.";
+ SendResult(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+ } else if (node->HasFrameId()) {
+ // TODO(crbug.com/806868): Support out-of-process iframe.
+ DVLOG(3) << "Warning (unsupported): the element is inside an OOPIF.";
+ SendResult(ClientStatus(UNSUPPORTED));
+ return;
+ }
+
+ if (node->HasShadowRoots()) {
+ // TODO(crbug.com/806868): Support multiple shadow roots.
+ backend_ids.emplace_back(
+ node->GetShadowRoots()->front()->GetBackendNodeId());
+ }
+
+ if (!backend_ids.empty()) {
+ devtools_client_->GetDOM()->ResolveNode(
+ dom::ResolveNodeParams::Builder()
+ .SetBackendNodeId(backend_ids[0])
+ .Build(),
+ base::BindOnce(&ElementFinder::OnResolveNode,
+ weak_ptr_factory_.GetWeakPtr(), index));
+ return;
+ }
+
+ RecursiveFindElement(object_id, ++index);
+}
+
+void ElementFinder::OnResolveNode(
+ size_t index,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::ResolveNodeResult> result) {
+ if (!result || !result->GetObject() || !result->GetObject()->HasObjectId()) {
+ DVLOG(1) << __func__ << " Failed to resolve object id from backend id.";
+ SendResult(UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+
+ RecursiveFindElement(result->GetObject()->GetObjectId(), ++index);
+}
+
+content::RenderFrameHost* ElementFinder::FindCorrespondingRenderFrameHost(
+ std::string name,
+ std::string document_url) {
+ content::RenderFrameHost* ret_frame = nullptr;
+ for (auto* frame : web_contents_->GetAllFrames()) {
+ if (frame->GetFrameName() == name &&
+ frame->GetLastCommittedURL().spec() == document_url) {
+ DCHECK(!ret_frame);
+ ret_frame = frame;
+ }
+ }
+
+ return ret_frame;
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/web/element_finder.h b/chromium/components/autofill_assistant/browser/web/element_finder.h
new file mode 100644
index 00000000000..3acc08bd797
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/element_finder.h
@@ -0,0 +1,102 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_ELEMENT_FINDER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_ELEMENT_FINDER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/devtools/devtools/domains/types_dom.h"
+#include "components/autofill_assistant/browser/devtools/devtools/domains/types_runtime.h"
+#include "components/autofill_assistant/browser/devtools/devtools_client.h"
+#include "components/autofill_assistant/browser/selector.h"
+#include "components/autofill_assistant/browser/web/web_controller_worker.h"
+
+namespace content {
+class WebContents;
+class RenderFrameHost;
+} // namespace content
+
+namespace autofill_assistant {
+class DevtoolsClient;
+
+// Worker class to find element(s) matching a selector.
+class ElementFinder : public WebControllerWorker {
+ public:
+ struct Result {
+ Result() = default;
+ ~Result() = default;
+
+ // The render frame host contains the element.
+ content::RenderFrameHost* container_frame_host;
+
+ // The selector index in the given selectors corresponding to the container
+ // frame. Zero indicates the element is in main frame or the first element
+ // is the container frame selector. Compare main frame with the above
+ // |container_frame_host| to distinguish them.
+ size_t container_frame_selector_index;
+
+ // The object id of the element.
+ std::string object_id;
+ };
+
+ // |web_contents| and |devtools_client| must be valid for the lifetime of the
+ // instance.
+ ElementFinder(content::WebContents* web_contents_,
+ DevtoolsClient* devtools_client,
+ const Selector& selector,
+ bool strict);
+ ~ElementFinder() override;
+
+ using Callback =
+ base::OnceCallback<void(const ClientStatus&, std::unique_ptr<Result>)>;
+
+ // Finds the element and calls the callback.
+ void Start(Callback callback_);
+
+ private:
+ void SendResult(const ClientStatus& status);
+ void OnGetDocumentElement(const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::EvaluateResult> result);
+ void RecursiveFindElement(const std::string& object_id, size_t index);
+ void OnQuerySelectorAll(
+ size_t index,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result);
+ void OnDescribeNodeForPseudoElement(
+ dom::PseudoType pseudo_type,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::DescribeNodeResult> result);
+ void OnResolveNodeForPseudoElement(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::ResolveNodeResult> result);
+ void OnDescribeNode(const std::string& object_id,
+ size_t index,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::DescribeNodeResult> result);
+ void OnResolveNode(size_t index,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::ResolveNodeResult> result);
+ content::RenderFrameHost* FindCorrespondingRenderFrameHost(
+ std::string name,
+ std::string document_url);
+
+ content::WebContents* const web_contents_;
+ DevtoolsClient* const devtools_client_;
+ const Selector selector_;
+ const bool strict_;
+ Callback callback_;
+ std::unique_ptr<Result> element_result_;
+
+ base::WeakPtrFactory<ElementFinder> weak_ptr_factory_{this};
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_ELEMENT_FINDER_H_
diff --git a/chromium/components/autofill_assistant/browser/web/element_position_getter.cc b/chromium/components/autofill_assistant/browser/web/element_position_getter.cc
new file mode 100644
index 00000000000..09e0aab18e3
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/element_position_getter.cc
@@ -0,0 +1,171 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/web/element_position_getter.h"
+
+#include "base/task/post_task.h"
+#include "components/autofill_assistant/browser/devtools/devtools_client.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/web_controller_util.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace {
+
+const char* const kScrollIntoViewIfNeededScript =
+ R"(function(node) {
+ node.scrollIntoViewIfNeeded();
+ })";
+
+} // namespace
+
+namespace autofill_assistant {
+
+ElementPositionGetter::ElementPositionGetter(DevtoolsClient* devtools_client,
+ const ClientSettings& settings)
+ : check_interval_(settings.box_model_check_interval),
+ max_rounds_(settings.box_model_check_count),
+ devtools_client_(devtools_client),
+ weak_ptr_factory_(this) {}
+
+ElementPositionGetter::~ElementPositionGetter() = default;
+
+void ElementPositionGetter::Start(content::RenderFrameHost* frame_host,
+ std::string element_object_id,
+ ElementPositionCallback callback) {
+ object_id_ = element_object_id;
+ callback_ = std::move(callback);
+ remaining_rounds_ = max_rounds_;
+ // TODO(crbug/806868): Consider using autofill_assistant::RetryTimer
+
+ // Wait for a roundtrips through the renderer and compositor pipeline,
+ // otherwise touch event may be dropped because of missing handler.
+ // Note that mouse left button will always be send to the renderer, but it
+ // is slightly better to wait for the changes, like scroll, to be visualized
+ // in compositor as real interaction.
+ frame_host->InsertVisualStateCallback(
+ base::BindOnce(&ElementPositionGetter::OnVisualStateUpdatedCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+ GetAndWaitBoxModelStable();
+}
+
+void ElementPositionGetter::OnVisualStateUpdatedCallback(bool success) {
+ if (success) {
+ visual_state_updated_ = true;
+ return;
+ }
+
+ OnError();
+}
+
+void ElementPositionGetter::GetAndWaitBoxModelStable() {
+ devtools_client_->GetDOM()->GetBoxModel(
+ dom::GetBoxModelParams::Builder().SetObjectId(object_id_).Build(),
+ base::BindOnce(&ElementPositionGetter::OnGetBoxModelForStableCheck,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ElementPositionGetter::OnGetBoxModelForStableCheck(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::GetBoxModelResult> result) {
+ if (!result || !result->GetModel() || !result->GetModel()->GetContent()) {
+ DVLOG(1) << __func__ << " Failed to get box model.";
+ OnError();
+ return;
+ }
+
+ // Return the center of the element.
+ const std::vector<double>* content_box = result->GetModel()->GetContent();
+ DCHECK_EQ(content_box->size(), 8u);
+ int new_point_x =
+ round((round((*content_box)[0]) + round((*content_box)[2])) * 0.5);
+ int new_point_y =
+ round((round((*content_box)[3]) + round((*content_box)[5])) * 0.5);
+
+ // Wait for at least three rounds (~600ms = 3*check_interval_) for visual
+ // state update callback since it might take longer time to return or never
+ // return if no updates.
+ DCHECK(max_rounds_ > 2 && max_rounds_ >= remaining_rounds_);
+ if (has_point_ && new_point_x == point_x_ && new_point_y == point_y_ &&
+ (visual_state_updated_ || remaining_rounds_ + 2 < max_rounds_)) {
+ // Note that there is still a chance that the element's position has been
+ // changed after the last call of GetBoxModel, however, it might be safe to
+ // assume the element's position will not be changed before issuing click or
+ // tap event after stable for check_interval_. In addition, checking again
+ // after issuing click or tap event doesn't help since the change may be
+ // expected.
+ OnResult(new_point_x, new_point_y);
+ return;
+ }
+
+ if (remaining_rounds_ <= 0) {
+ OnError();
+ return;
+ }
+
+ bool is_first_round = !has_point_;
+ has_point_ = true;
+ point_x_ = new_point_x;
+ point_y_ = new_point_y;
+
+ // Scroll the element into view again if it was moved out of view, starting
+ // from the second round.
+ if (!is_first_round) {
+ std::vector<std::unique_ptr<runtime::CallArgument>> argument;
+ argument.emplace_back(
+ runtime::CallArgument::Builder().SetObjectId(object_id_).Build());
+ devtools_client_->GetRuntime()->CallFunctionOn(
+ runtime::CallFunctionOnParams::Builder()
+ .SetObjectId(object_id_)
+ .SetArguments(std::move(argument))
+ .SetFunctionDeclaration(std::string(kScrollIntoViewIfNeededScript))
+ .SetReturnByValue(true)
+ .Build(),
+ base::BindOnce(&ElementPositionGetter::OnScrollIntoView,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ --remaining_rounds_;
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&ElementPositionGetter::GetAndWaitBoxModelStable,
+ weak_ptr_factory_.GetWeakPtr()),
+ check_interval_);
+}
+
+void ElementPositionGetter::OnScrollIntoView(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result) {
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
+ if (!status.ok()) {
+ DVLOG(1) << __func__ << " Failed to scroll the element: " << status;
+ OnError();
+ return;
+ }
+
+ --remaining_rounds_;
+ base::PostDelayedTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&ElementPositionGetter::GetAndWaitBoxModelStable,
+ weak_ptr_factory_.GetWeakPtr()),
+ check_interval_);
+}
+
+void ElementPositionGetter::OnResult(int x, int y) {
+ if (callback_) {
+ std::move(callback_).Run(/* success= */ true, x, y);
+ }
+}
+
+void ElementPositionGetter::OnError() {
+ if (callback_) {
+ std::move(callback_).Run(/* success= */ false, /* x= */ 0, /* y= */ 0);
+ }
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/web/element_position_getter.h b/chromium/components/autofill_assistant/browser/web/element_position_getter.h
new file mode 100644
index 00000000000..6639c419ef8
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/element_position_getter.h
@@ -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.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_ELEMENT_POSITION_GETTER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_ELEMENT_POSITION_GETTER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/client_settings.h"
+#include "components/autofill_assistant/browser/devtools/devtools/domains/types_dom.h"
+#include "components/autofill_assistant/browser/devtools/devtools/domains/types_runtime.h"
+#include "components/autofill_assistant/browser/devtools/devtools_client.h"
+#include "components/autofill_assistant/browser/selector.h"
+#include "components/autofill_assistant/browser/web/web_controller_worker.h"
+
+namespace content {
+class RenderFrameHost;
+} // namespace content
+
+namespace autofill_assistant {
+
+// Worker class to get an element's position in viewport coordinates when it is
+// stable and the frame it belongs to has finished its visual update.
+class ElementPositionGetter : public WebControllerWorker {
+ public:
+ // |devtools_client| must be valid for the lifetime of the instance.
+ ElementPositionGetter(DevtoolsClient* devtools_client,
+ const ClientSettings& settings);
+ ~ElementPositionGetter() override;
+
+ // Callback that receives the position that corresponds to the center
+ // of an element.
+ //
+ // If the first element is false, the call failed. Otherwise, the second
+ // element contains the x position and the third the y position of the center
+ // of the element in viewport coordinates.
+ using ElementPositionCallback = base::OnceCallback<void(bool, int, int)>;
+
+ void Start(content::RenderFrameHost* frame_host,
+ std::string element_object_id,
+ ElementPositionCallback callback);
+
+ private:
+ void OnVisualStateUpdatedCallback(bool success);
+ void GetAndWaitBoxModelStable();
+ void OnGetBoxModelForStableCheck(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<dom::GetBoxModelResult> result);
+ void OnScrollIntoView(const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result);
+ void OnResult(int x, int y);
+ void OnError();
+
+ // Time to wait between two box model checks.
+ const base::TimeDelta check_interval_;
+ // Maximum number of checks to run.
+ const int max_rounds_;
+
+ DevtoolsClient* devtools_client_ = nullptr;
+ std::string object_id_;
+ int remaining_rounds_ = 0;
+ ElementPositionCallback callback_;
+ bool visual_state_updated_ = false;
+
+ // If |has_point_| is true, |point_x_| and |point_y_| contain the last
+ // computed center of the element, in viewport coordinates. Note that
+ // negative coordinates are valid, in case the element is above or to the
+ // left of the viewport.
+ bool has_point_ = false;
+ int point_x_ = 0;
+ int point_y_ = 0;
+
+ base::WeakPtrFactory<ElementPositionGetter> weak_ptr_factory_;
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_ELEMENT_POSITION_GETTER_H_
diff --git a/chromium/components/autofill_assistant/browser/mock_web_controller.cc b/chromium/components/autofill_assistant/browser/web/mock_web_controller.cc
index 21dcf826518..b3046aa2309 100644
--- a/chromium/components/autofill_assistant/browser/mock_web_controller.cc
+++ b/chromium/components/autofill_assistant/browser/web/mock_web_controller.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 "components/autofill_assistant/browser/mock_web_controller.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
namespace autofill_assistant {
diff --git a/chromium/components/autofill_assistant/browser/mock_web_controller.h b/chromium/components/autofill_assistant/browser/web/mock_web_controller.h
index bd2b589e1dd..03e0fb70e9b 100644
--- a/chromium/components/autofill_assistant/browser/mock_web_controller.h
+++ b/chromium/components/autofill_assistant/browser/web/mock_web_controller.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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_WEB_CONTROLLER_H_
-#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_WEB_CONTROLLER_H_
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_MOCK_WEB_CONTROLLER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_MOCK_WEB_CONTROLLER_H_
#include <string>
#include <vector>
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "components/autofill_assistant/browser/actions/click_action.h"
#include "components/autofill_assistant/browser/top_padding.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -119,4 +119,4 @@ class MockWebController : public WebController {
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_WEB_CONTROLLER_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_MOCK_WEB_CONTROLLER_H_
diff --git a/chromium/components/autofill_assistant/browser/web_controller.cc b/chromium/components/autofill_assistant/browser/web/web_controller.cc
index a9494a12a65..85c2ae72466 100644
--- a/chromium/components/autofill_assistant/browser/web_controller.cc
+++ b/chromium/components/autofill_assistant/browser/web/web_controller.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 "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
#include <math.h>
#include <algorithm>
@@ -13,6 +13,7 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -27,6 +28,7 @@
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/rectf.h"
#include "components/autofill_assistant/browser/string_conversions_util.h"
+#include "components/autofill_assistant/browser/web/web_controller_util.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
@@ -75,11 +77,6 @@ const char* const kScrollIntoViewCenterScript =
node.scrollIntoView({block: "center", inline: "center"});
})";
-const char* const kScrollIntoViewIfNeededScript =
- R"(function(node) {
- node.scrollIntoViewIfNeeded();
- })";
-
// Javascript to select a value from a select box. Also fires a "change" event
// to trigger any listeners. Changing the index directly does not trigger this.
const char* const kSelectOptionScript =
@@ -141,54 +138,6 @@ const char* const kSetAttributeScript =
const char* const kGetOuterHtmlScript =
"function () { return this.outerHTML; }";
-// Javascript code to get document root element.
-const char* const kGetDocumentElement =
- R"(
- (function() {
- return document.documentElement;
- }())
- )";
-
-// Javascript code to query an elements for a selector, either the first
-// (non-strict) or a single (strict) element.
-//
-// Returns undefined if no elements are found, TOO_MANY_ELEMENTS (18) if too
-// many elements were found and strict mode is enabled.
-const char* const kQuerySelector =
- R"(function (selector, strictMode) {
- var found = this.querySelectorAll(selector);
- if(found.length == 0) return undefined;
- if(found.length > 1 && strictMode) return 18;
- return found[0];
- })";
-
-// Javascript code to query a visible elements for a selector, either the first
-// (non-strict) or a single (strict) visible element.q
-//
-// Returns undefined if no elements are found, TOO_MANY_ELEMENTS (18) if too
-// many elements were found and strict mode is enabled.
-const char* const kQuerySelectorWithConditions =
- R"(function (selector, strict, visible, inner_text_str, value_str) {
- var found = this.querySelectorAll(selector);
- var found_index = -1;
- var inner_text_re = inner_text_str ? RegExp(inner_text_str) : undefined;
- var value_re = value_str ? RegExp(value_str) : undefined;
- var match = function(e) {
- if (visible && e.getClientRects().length == 0) return false;
- if (inner_text_re && !inner_text_re.test(e.innerText)) return false;
- if (value_re && !value_re.test(e.value)) return false;
- return true;
- };
- for (let i = 0; i < found.length; i++) {
- if (match(found[i])) {
- if (found_index != -1) return 18;
- found_index = i;
- if (!strict) break;
- }
- }
- return found_index == -1 ? undefined : found[found_index];
- })";
-
// Javascript code to query whether the document is ready for interact.
const char* const kIsDocumentReadyForInteract =
R"(function () {
@@ -222,143 +171,6 @@ new Promise((fulfill, reject) => {
})
)";
-bool ConvertPseudoType(const PseudoType pseudo_type,
- dom::PseudoType* pseudo_type_output) {
- switch (pseudo_type) {
- case PseudoType::UNDEFINED:
- break;
- case PseudoType::FIRST_LINE:
- *pseudo_type_output = dom::PseudoType::FIRST_LINE;
- return true;
- case PseudoType::FIRST_LETTER:
- *pseudo_type_output = dom::PseudoType::FIRST_LETTER;
- return true;
- case PseudoType::BEFORE:
- *pseudo_type_output = dom::PseudoType::BEFORE;
- return true;
- case PseudoType::AFTER:
- *pseudo_type_output = dom::PseudoType::AFTER;
- return true;
- case PseudoType::BACKDROP:
- *pseudo_type_output = dom::PseudoType::BACKDROP;
- return true;
- case PseudoType::SELECTION:
- *pseudo_type_output = dom::PseudoType::SELECTION;
- return true;
- case PseudoType::FIRST_LINE_INHERITED:
- *pseudo_type_output = dom::PseudoType::FIRST_LINE_INHERITED;
- return true;
- case PseudoType::SCROLLBAR:
- *pseudo_type_output = dom::PseudoType::SCROLLBAR;
- return true;
- case PseudoType::SCROLLBAR_THUMB:
- *pseudo_type_output = dom::PseudoType::SCROLLBAR_THUMB;
- return true;
- case PseudoType::SCROLLBAR_BUTTON:
- *pseudo_type_output = dom::PseudoType::SCROLLBAR_BUTTON;
- return true;
- case PseudoType::SCROLLBAR_TRACK:
- *pseudo_type_output = dom::PseudoType::SCROLLBAR_TRACK;
- return true;
- case PseudoType::SCROLLBAR_TRACK_PIECE:
- *pseudo_type_output = dom::PseudoType::SCROLLBAR_TRACK_PIECE;
- return true;
- case PseudoType::SCROLLBAR_CORNER:
- *pseudo_type_output = dom::PseudoType::SCROLLBAR_CORNER;
- return true;
- case PseudoType::RESIZER:
- *pseudo_type_output = dom::PseudoType::RESIZER;
- return true;
- case PseudoType::INPUT_LIST_BUTTON:
- *pseudo_type_output = dom::PseudoType::INPUT_LIST_BUTTON;
- return true;
- }
- return false;
-}
-
-// Builds a ClientStatus appropriate for an unexpected error.
-//
-// This should only be used in situations where getting an error cannot be
-// anything but a bug in the client.
-ClientStatus UnexpectedErrorStatus(const std::string& file, int line) {
- ClientStatus status(OTHER_ACTION_STATUS);
- auto* info = status.mutable_details()->mutable_unexpected_error_info();
- info->set_source_file(file);
- info->set_source_line_number(line);
- return status;
-}
-
-// Builds a ClientStatus appropriate for a JavaScript error.
-ClientStatus JavaScriptErrorStatus(const std::string& file,
- int line,
- const runtime::ExceptionDetails* exception) {
- ClientStatus status(UNEXPECTED_JS_ERROR);
- auto* info = status.mutable_details()->mutable_unexpected_error_info();
- info->set_source_file(file);
- info->set_source_line_number(line);
- if (exception) {
- if (exception->HasException() &&
- exception->GetException()->HasClassName()) {
- info->set_js_exception_classname(
- exception->GetException()->GetClassName());
- }
- info->set_js_exception_line_number(exception->GetLineNumber());
- info->set_js_exception_column_number(exception->GetColumnNumber());
- }
- return status;
-}
-
-// Makes sure that the given EvaluateResult exists, is successful and contain a
-// result.
-template <typename T>
-ClientStatus CheckJavaScriptResult(T* result, const char* file, int line) {
- if (!result)
- return JavaScriptErrorStatus(file, line, nullptr);
- if (result->HasExceptionDetails())
- return JavaScriptErrorStatus(file, line, result->GetExceptionDetails());
- if (!result->GetResult())
- return JavaScriptErrorStatus(file, line, nullptr);
- return OkClientStatus();
-}
-
-// Safely gets an object id from a RemoteObject
-bool SafeGetObjectId(const runtime::RemoteObject* result, std::string* out) {
- if (result && result->HasObjectId()) {
- *out = result->GetObjectId();
- return true;
- }
- return false;
-}
-
-// Safely gets a string value from a RemoteObject
-bool SafeGetStringValue(const runtime::RemoteObject* result, std::string* out) {
- if (result && result->HasValue() && result->GetValue()->is_string()) {
- *out = result->GetValue()->GetString();
- return true;
- }
- return false;
-}
-
-// Safely gets a int value from a RemoteObject.
-bool SafeGetIntValue(const runtime::RemoteObject* result, int* out) {
- if (result && result->HasValue() && result->GetValue()->is_int()) {
- *out = result->GetValue()->GetInt();
- return true;
- }
- *out = 0;
- return false;
-}
-
-// Safely gets a boolean value from a RemoteObject
-bool SafeGetBool(const runtime::RemoteObject* result, bool* out) {
- if (result && result->HasValue() && result->GetValue()->is_bool()) {
- *out = result->GetValue()->GetBool();
- return true;
- }
- *out = false;
- return false;
-}
-
// Converts a int that correspond to the DocumentReadyState enum into an
// equivalent quoted Javascript string.
std::string DocumentReadyStateToQuotedJsString(int state) {
@@ -417,8 +229,10 @@ void AppendWaitForDocumentReadyStateFunction(std::string* out) {
template <typename T>
void OnWaitForDocumentReadyState(
base::OnceCallback<void(const ClientStatus&, DocumentReadyState)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<T> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
DVLOG_IF(1, !status.ok())
<< __func__ << " Failed to get document ready state.";
int ready_state;
@@ -427,550 +241,6 @@ void OnWaitForDocumentReadyState(
}
} // namespace
-class WebController::Worker {
- public:
- Worker();
- virtual ~Worker();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Worker);
-};
-WebController::Worker::Worker() = default;
-WebController::Worker::~Worker() = default;
-
-class WebController::ElementPositionGetter : public WebController::Worker {
- public:
- ElementPositionGetter(const ClientSettings& settings);
- ~ElementPositionGetter() override;
-
- // |devtools_client| must be valid for the lifetime of the instance, which is
- // guaranteed since workers are owned by WebController.
- void Start(content::RenderFrameHost* frame_host,
- DevtoolsClient* devtools_client,
- std::string element_object_id,
- ElementPositionCallback callback);
-
- private:
- void OnVisualStateUpdatedCallback(bool success);
- void GetAndWaitBoxModelStable();
- void OnGetBoxModelForStableCheck(
- std::unique_ptr<dom::GetBoxModelResult> result);
- void OnScrollIntoView(std::unique_ptr<runtime::CallFunctionOnResult> result);
- void OnResult(int x, int y);
- void OnError();
-
- // Time to wait between two box model checks.
- const base::TimeDelta check_interval_;
- // Maximum number of checks to run.
- const int max_rounds_;
-
- DevtoolsClient* devtools_client_ = nullptr;
- std::string object_id_;
- int remaining_rounds_ = 0;
- ElementPositionCallback callback_;
- bool visual_state_updated_ = false;
-
- // If |has_point_| is true, |point_x_| and |point_y_| contain the last
- // computed center of the element, in viewport coordinates. Note that
- // negative coordinates are valid, in case the element is above or to the
- // left of the viewport.
- bool has_point_ = false;
- int point_x_ = 0;
- int point_y_ = 0;
-
- base::WeakPtrFactory<ElementPositionGetter> weak_ptr_factory_;
-};
-
-WebController::ElementPositionGetter::ElementPositionGetter(
- const ClientSettings& settings)
- : check_interval_(settings.box_model_check_interval),
- max_rounds_(settings.box_model_check_count),
- weak_ptr_factory_(this) {}
-
-WebController::ElementPositionGetter::~ElementPositionGetter() = default;
-
-void WebController::ElementPositionGetter::Start(
- content::RenderFrameHost* frame_host,
- DevtoolsClient* devtools_client,
- std::string element_object_id,
- ElementPositionCallback callback) {
- devtools_client_ = devtools_client;
- object_id_ = element_object_id;
- callback_ = std::move(callback);
- remaining_rounds_ = max_rounds_;
- // TODO(crbug/806868): Consider using autofill_assistant::RetryTimer
-
- // Wait for a roundtrips through the renderer and compositor pipeline,
- // otherwise touch event may be dropped because of missing handler.
- // Note that mouse left button will always be send to the renderer, but it
- // is slightly better to wait for the changes, like scroll, to be visualized
- // in compositor as real interaction.
- frame_host->InsertVisualStateCallback(base::BindOnce(
- &WebController::ElementPositionGetter::OnVisualStateUpdatedCallback,
- weak_ptr_factory_.GetWeakPtr()));
- GetAndWaitBoxModelStable();
-}
-
-void WebController::ElementPositionGetter::OnVisualStateUpdatedCallback(
- bool success) {
- if (success) {
- visual_state_updated_ = true;
- return;
- }
-
- OnError();
-}
-
-void WebController::ElementPositionGetter::GetAndWaitBoxModelStable() {
- devtools_client_->GetDOM()->GetBoxModel(
- dom::GetBoxModelParams::Builder().SetObjectId(object_id_).Build(),
- base::BindOnce(
- &WebController::ElementPositionGetter::OnGetBoxModelForStableCheck,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void WebController::ElementPositionGetter::OnGetBoxModelForStableCheck(
- std::unique_ptr<dom::GetBoxModelResult> result) {
- if (!result || !result->GetModel() || !result->GetModel()->GetContent()) {
- DVLOG(1) << __func__ << " Failed to get box model.";
- OnError();
- return;
- }
-
- // Return the center of the element.
- const std::vector<double>* content_box = result->GetModel()->GetContent();
- DCHECK_EQ(content_box->size(), 8u);
- int new_point_x =
- round((round((*content_box)[0]) + round((*content_box)[2])) * 0.5);
- int new_point_y =
- round((round((*content_box)[3]) + round((*content_box)[5])) * 0.5);
-
- // Wait for at least three rounds (~600ms = 3*check_interval_) for visual
- // state update callback since it might take longer time to return or never
- // return if no updates.
- DCHECK(max_rounds_ > 2 && max_rounds_ >= remaining_rounds_);
- if (has_point_ && new_point_x == point_x_ && new_point_y == point_y_ &&
- (visual_state_updated_ || remaining_rounds_ + 2 < max_rounds_)) {
- // Note that there is still a chance that the element's position has been
- // changed after the last call of GetBoxModel, however, it might be safe to
- // assume the element's position will not be changed before issuing click or
- // tap event after stable for check_interval_. In addition, checking again
- // after issuing click or tap event doesn't help since the change may be
- // expected.
- OnResult(new_point_x, new_point_y);
- return;
- }
-
- if (remaining_rounds_ <= 0) {
- OnError();
- return;
- }
-
- bool is_first_round = !has_point_;
- has_point_ = true;
- point_x_ = new_point_x;
- point_y_ = new_point_y;
-
- // Scroll the element into view again if it was moved out of view, starting
- // from the second round.
- if (!is_first_round) {
- std::vector<std::unique_ptr<runtime::CallArgument>> argument;
- argument.emplace_back(
- runtime::CallArgument::Builder().SetObjectId(object_id_).Build());
- devtools_client_->GetRuntime()->CallFunctionOn(
- runtime::CallFunctionOnParams::Builder()
- .SetObjectId(object_id_)
- .SetArguments(std::move(argument))
- .SetFunctionDeclaration(std::string(kScrollIntoViewIfNeededScript))
- .SetReturnByValue(true)
- .Build(),
- base::BindOnce(&WebController::ElementPositionGetter::OnScrollIntoView,
- weak_ptr_factory_.GetWeakPtr()));
- return;
- }
-
- --remaining_rounds_;
- base::PostDelayedTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(
- &WebController::ElementPositionGetter::GetAndWaitBoxModelStable,
- weak_ptr_factory_.GetWeakPtr()),
- check_interval_);
-}
-
-void WebController::ElementPositionGetter::OnScrollIntoView(
- std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
- if (!status.ok()) {
- DVLOG(1) << __func__ << " Failed to scroll the element: " << status;
- OnError();
- return;
- }
-
- --remaining_rounds_;
- base::PostDelayedTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(
- &WebController::ElementPositionGetter::GetAndWaitBoxModelStable,
- weak_ptr_factory_.GetWeakPtr()),
- check_interval_);
-}
-
-void WebController::ElementPositionGetter::OnResult(int x, int y) {
- if (callback_) {
- std::move(callback_).Run(/* success= */ true, x, y);
- }
-}
-
-void WebController::ElementPositionGetter::OnError() {
- if (callback_) {
- std::move(callback_).Run(/* success= */ false, /* x= */ 0, /* y= */ 0);
- }
-}
-
-class WebController::ElementFinder : public WebController::Worker {
- public:
- // |devtools_client| and |web_contents| must be valid for the lifetime of the
- // instance, which is guaranteed since workers are owned by WebController.
- ElementFinder(content::WebContents* web_contents_,
- DevtoolsClient* devtools_client,
- const Selector& selector,
- bool strict);
- ~ElementFinder() override;
-
- // Finds the element and call the callback.
- void Start(FindElementCallback callback_);
-
- private:
- void SendResult(const ClientStatus& status);
- void OnGetDocumentElement(std::unique_ptr<runtime::EvaluateResult> result);
- void RecursiveFindElement(const std::string& object_id, size_t index);
- void OnQuerySelectorAll(
- size_t index,
- std::unique_ptr<runtime::CallFunctionOnResult> result);
- void OnDescribeNodeForPseudoElement(
- dom::PseudoType pseudo_type,
- std::unique_ptr<dom::DescribeNodeResult> result);
- void OnResolveNodeForPseudoElement(
- std::unique_ptr<dom::ResolveNodeResult> result);
- void OnDescribeNode(const std::string& object_id,
- size_t index,
- std::unique_ptr<dom::DescribeNodeResult> result);
- void OnResolveNode(size_t index,
- std::unique_ptr<dom::ResolveNodeResult> result);
- content::RenderFrameHost* FindCorrespondingRenderFrameHost(
- std::string name,
- std::string document_url);
-
- content::WebContents* const web_contents_;
- DevtoolsClient* const devtools_client_;
- const Selector selector_;
- const bool strict_;
- FindElementCallback callback_;
- std::unique_ptr<FindElementResult> element_result_;
-
- base::WeakPtrFactory<ElementFinder> weak_ptr_factory_;
-};
-
-WebController::ElementFinder::ElementFinder(content::WebContents* web_contents,
- DevtoolsClient* devtools_client,
- const Selector& selector,
- bool strict)
- : web_contents_(web_contents),
- devtools_client_(devtools_client),
- selector_(selector),
- strict_(strict),
- element_result_(std::make_unique<FindElementResult>()),
- weak_ptr_factory_(this) {}
-
-WebController::ElementFinder::~ElementFinder() = default;
-
-void WebController::ElementFinder::Start(FindElementCallback callback) {
- callback_ = std::move(callback);
-
- if (selector_.empty()) {
- SendResult(ClientStatus(INVALID_SELECTOR));
- return;
- }
- devtools_client_->GetRuntime()->Evaluate(
- std::string(kGetDocumentElement),
- base::BindOnce(&WebController::ElementFinder::OnGetDocumentElement,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void WebController::ElementFinder::SendResult(const ClientStatus& status) {
- DCHECK(callback_);
- DCHECK(element_result_);
- std::move(callback_).Run(status, std::move(element_result_));
-}
-
-void WebController::ElementFinder::OnGetDocumentElement(
- std::unique_ptr<runtime::EvaluateResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
- if (!status.ok()) {
- DVLOG(1) << __func__ << " Failed to get document root element.";
- SendResult(status);
- return;
- }
- std::string object_id;
- if (!SafeGetObjectId(result->GetResult(), &object_id)) {
- DVLOG(1) << __func__ << " Failed to get document root element.";
- SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
- return;
- }
- element_result_->container_frame_host = web_contents_->GetMainFrame();
- element_result_->container_frame_selector_index = 0;
- element_result_->object_id = "";
- RecursiveFindElement(object_id, 0);
-}
-
-void WebController::ElementFinder::RecursiveFindElement(
- const std::string& object_id,
- size_t index) {
- std::vector<std::unique_ptr<runtime::CallArgument>> argument;
- argument.emplace_back(runtime::CallArgument::Builder()
- .SetValue(base::Value::ToUniquePtrValue(
- base::Value(selector_.selectors[index])))
- .Build());
- // For finding intermediate elements, strict mode would be more appropriate,
- // as long as the logic does not support more than one intermediate match.
- //
- // TODO(b/129387787): first, add logging to figure out whether it matters and
- // decide between strict mode and full support for multiple matching
- // intermeditate elements.
- argument.emplace_back(
- runtime::CallArgument::Builder()
- .SetValue(base::Value::ToUniquePtrValue(base::Value(strict_)))
- .Build());
- std::string function;
- if (index == (selector_.selectors.size() - 1)) {
- if (selector_.must_be_visible || !selector_.inner_text_pattern.empty() ||
- !selector_.value_pattern.empty()) {
- function.assign(kQuerySelectorWithConditions);
- argument.emplace_back(runtime::CallArgument::Builder()
- .SetValue(base::Value::ToUniquePtrValue(
- base::Value(selector_.must_be_visible)))
- .Build());
- argument.emplace_back(runtime::CallArgument::Builder()
- .SetValue(base::Value::ToUniquePtrValue(
- base::Value(selector_.inner_text_pattern)))
- .Build());
- argument.emplace_back(runtime::CallArgument::Builder()
- .SetValue(base::Value::ToUniquePtrValue(
- base::Value(selector_.value_pattern)))
- .Build());
- }
- }
- if (function.empty()) {
- function.assign(kQuerySelector);
- }
- devtools_client_->GetRuntime()->CallFunctionOn(
- runtime::CallFunctionOnParams::Builder()
- .SetObjectId(object_id)
- .SetArguments(std::move(argument))
- .SetFunctionDeclaration(function)
- .Build(),
- base::BindOnce(&WebController::ElementFinder::OnQuerySelectorAll,
- weak_ptr_factory_.GetWeakPtr(), index));
-}
-
-void WebController::ElementFinder::OnQuerySelectorAll(
- size_t index,
- std::unique_ptr<runtime::CallFunctionOnResult> result) {
- if (!result) {
- // It is possible for a document element to already exist, but not be
- // available yet to query because the document hasn't been loaded. This
- // results in OnQuerySelectorAll getting a nullptr result. For this specific
- // call, it is expected.
- DVLOG(1) << __func__ << ": Context doesn't exist yet to query selector "
- << index << " of " << selector_;
- SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
- return;
- }
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
- if (!status.ok()) {
- DVLOG(1) << __func__ << ": Failed to query selector " << index << " of "
- << selector_;
- SendResult(status);
- return;
- }
- int int_result;
- if (SafeGetIntValue(result->GetResult(), &int_result)) {
- DCHECK(int_result == TOO_MANY_ELEMENTS);
- SendResult(ClientStatus(TOO_MANY_ELEMENTS));
- return;
- }
- std::string object_id;
- if (!SafeGetObjectId(result->GetResult(), &object_id)) {
- SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
- return;
- }
-
- if (selector_.selectors.size() == index + 1) {
- // The pseudo type is associated to the final element matched by
- // |selector_|, which means that we currently don't handle matching an
- // element inside a pseudo element.
- if (selector_.pseudo_type == PseudoType::UNDEFINED) {
- // Return object id of the element.
- element_result_->object_id = object_id;
- SendResult(OkClientStatus());
- return;
- }
-
- // We are looking for a pseudo element associated with this element.
- dom::PseudoType pseudo_type;
- if (!ConvertPseudoType(selector_.pseudo_type, &pseudo_type)) {
- // Return empty result.
- SendResult(ClientStatus(INVALID_ACTION));
- return;
- }
-
- devtools_client_->GetDOM()->DescribeNode(
- dom::DescribeNodeParams::Builder().SetObjectId(object_id).Build(),
- base::BindOnce(
- &WebController::ElementFinder::OnDescribeNodeForPseudoElement,
- weak_ptr_factory_.GetWeakPtr(), pseudo_type));
- return;
- }
-
- devtools_client_->GetDOM()->DescribeNode(
- dom::DescribeNodeParams::Builder().SetObjectId(object_id).Build(),
- base::BindOnce(&WebController::ElementFinder::OnDescribeNode,
- weak_ptr_factory_.GetWeakPtr(), object_id, index));
-}
-
-void WebController::ElementFinder::OnDescribeNodeForPseudoElement(
- dom::PseudoType pseudo_type,
- std::unique_ptr<dom::DescribeNodeResult> result) {
- if (!result || !result->GetNode()) {
- DVLOG(1) << __func__ << " Failed to describe the node for pseudo element.";
- SendResult(UnexpectedErrorStatus(__FILE__, __LINE__));
- return;
- }
-
- auto* node = result->GetNode();
- if (node->HasPseudoElements()) {
- for (const auto& pseudo_element : *(node->GetPseudoElements())) {
- if (pseudo_element->HasPseudoType() &&
- pseudo_element->GetPseudoType() == pseudo_type) {
- devtools_client_->GetDOM()->ResolveNode(
- dom::ResolveNodeParams::Builder()
- .SetBackendNodeId(pseudo_element->GetBackendNodeId())
- .Build(),
- base::BindOnce(
- &WebController::ElementFinder::OnResolveNodeForPseudoElement,
- weak_ptr_factory_.GetWeakPtr()));
- return;
- }
- }
- }
-
- // Failed to find the pseudo element: run the callback with empty result.
- SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED));
-}
-
-void WebController::ElementFinder::OnResolveNodeForPseudoElement(
- std::unique_ptr<dom::ResolveNodeResult> result) {
- if (result && result->GetObject() && result->GetObject()->HasObjectId()) {
- element_result_->object_id = result->GetObject()->GetObjectId();
- }
- SendResult(OkClientStatus());
-}
-
-void WebController::ElementFinder::OnDescribeNode(
- const std::string& object_id,
- size_t index,
- std::unique_ptr<dom::DescribeNodeResult> result) {
- if (!result || !result->GetNode()) {
- DVLOG(1) << __func__ << " Failed to describe the node.";
- SendResult(UnexpectedErrorStatus(__FILE__, __LINE__));
- return;
- }
-
- auto* node = result->GetNode();
- std::vector<int> backend_ids;
- if (node->HasContentDocument()) {
- backend_ids.emplace_back(node->GetContentDocument()->GetBackendNodeId());
-
- element_result_->container_frame_selector_index = index;
-
- // Find out the corresponding render frame host through document url and
- // name.
- // TODO(crbug.com/806868): Use more attributes to find out the render frame
- // host if name and document url are not enough to uniquely identify it.
- std::string frame_name;
- if (node->HasAttributes()) {
- const std::vector<std::string>* attributes = node->GetAttributes();
- for (size_t i = 0; i < attributes->size();) {
- if ((*attributes)[i] == "name") {
- frame_name = (*attributes)[i + 1];
- break;
- }
- // Jump two positions since attribute name and value are always paired.
- i = i + 2;
- }
- }
- element_result_->container_frame_host = FindCorrespondingRenderFrameHost(
- frame_name, node->GetContentDocument()->GetDocumentURL());
- if (!element_result_->container_frame_host) {
- DVLOG(1) << __func__ << " Failed to find corresponding owner frame.";
- SendResult(UnexpectedErrorStatus(__FILE__, __LINE__));
- return;
- }
- } else if (node->HasFrameId()) {
- // TODO(crbug.com/806868): Support out-of-process iframe.
- DVLOG(3) << "Warning (unsupported): the element is inside an OOPIF.";
- SendResult(ClientStatus(UNSUPPORTED));
- return;
- }
-
- if (node->HasShadowRoots()) {
- // TODO(crbug.com/806868): Support multiple shadow roots.
- backend_ids.emplace_back(
- node->GetShadowRoots()->front()->GetBackendNodeId());
- }
-
- if (!backend_ids.empty()) {
- devtools_client_->GetDOM()->ResolveNode(
- dom::ResolveNodeParams::Builder()
- .SetBackendNodeId(backend_ids[0])
- .Build(),
- base::BindOnce(&WebController::ElementFinder::OnResolveNode,
- weak_ptr_factory_.GetWeakPtr(), index));
- return;
- }
-
- RecursiveFindElement(object_id, ++index);
-}
-
-void WebController::ElementFinder::OnResolveNode(
- size_t index,
- std::unique_ptr<dom::ResolveNodeResult> result) {
- if (!result || !result->GetObject() || !result->GetObject()->HasObjectId()) {
- DVLOG(1) << __func__ << " Failed to resolve object id from backend id.";
- SendResult(UnexpectedErrorStatus(__FILE__, __LINE__));
- return;
- }
-
- RecursiveFindElement(result->GetObject()->GetObjectId(), ++index);
-}
-
-content::RenderFrameHost*
-WebController::ElementFinder::FindCorrespondingRenderFrameHost(
- std::string name,
- std::string document_url) {
- content::RenderFrameHost* ret_frame = nullptr;
- for (auto* frame : web_contents_->GetAllFrames()) {
- if (frame->GetFrameName() == name &&
- frame->GetLastCommittedURL().spec() == document_url) {
- DCHECK(!ret_frame);
- ret_frame = frame;
- }
- }
-
- return ret_frame;
-}
-
// static
std::unique_ptr<WebController> WebController::CreateForWebContents(
content::WebContents* web_contents,
@@ -987,8 +257,7 @@ WebController::WebController(content::WebContents* web_contents,
const ClientSettings* settings)
: web_contents_(web_contents),
devtools_client_(std::move(devtools_client)),
- settings_(settings),
- weak_ptr_factory_(this) {}
+ settings_(settings) {}
WebController::~WebController() {}
@@ -1019,7 +288,7 @@ void WebController::OnFindElementForClickOrTap(
base::OnceCallback<void(const ClientStatus&)> callback,
ClickAction::ClickType click_type,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result) {
+ std::unique_ptr<ElementFinder::Result> result) {
// Found element must belong to a frame.
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to find the element to click or tap.";
@@ -1039,7 +308,7 @@ void WebController::OnFindElementForClickOrTap(
void WebController::OnWaitDocumentToBecomeInteractiveForClickOrTap(
base::OnceCallback<void(const ClientStatus&)> callback,
ClickAction::ClickType click_type,
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
bool result) {
if (!result) {
std::move(callback).Run(ClientStatus(TIMED_OUT));
@@ -1050,7 +319,7 @@ void WebController::OnWaitDocumentToBecomeInteractiveForClickOrTap(
}
void WebController::ClickOrTapElement(
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
ClickAction::ClickType click_type,
base::OnceCallback<void(const ClientStatus&)> callback) {
std::string element_object_id = target_element->object_id;
@@ -1070,11 +339,13 @@ void WebController::ClickOrTapElement(
}
void WebController::OnScrollIntoView(
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
base::OnceCallback<void(const ClientStatus&)> callback,
ClickAction::ClickType click_type,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to scroll the element.";
std::move(callback).Run(status);
@@ -1099,21 +370,22 @@ void WebController::OnScrollIntoView(
}
std::unique_ptr<ElementPositionGetter> getter =
- std::make_unique<ElementPositionGetter>(*settings_);
- ElementPositionGetter* getter_ptr = getter.get();
- pending_workers_[getter_ptr] = std::move(getter);
- getter_ptr->Start(target_element->container_frame_host,
- devtools_client_.get(), target_element->object_id,
- base::BindOnce(&WebController::TapOrClickOnCoordinates,
- weak_ptr_factory_.GetWeakPtr(),
- base::Unretained(getter_ptr),
- std::move(callback), click_type));
+ std::make_unique<ElementPositionGetter>(devtools_client_.get(),
+ *settings_);
+ auto* ptr = getter.get();
+ pending_workers_.emplace_back(std::move(getter));
+ ptr->Start(target_element->container_frame_host, target_element->object_id,
+ base::BindOnce(&WebController::TapOrClickOnCoordinates,
+ weak_ptr_factory_.GetWeakPtr(), ptr,
+ std::move(callback), click_type));
}
void WebController::OnClickJS(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to click (javascript) the element.";
}
@@ -1127,7 +399,9 @@ void WebController::TapOrClickOnCoordinates(
bool has_coordinates,
int x,
int y) {
- pending_workers_.erase(getter_to_release);
+ base::EraseIf(pending_workers_, [getter_to_release](const auto& worker) {
+ return worker.get() == getter_to_release;
+ });
if (!has_coordinates) {
DVLOG(1) << __func__ << " Failed to get element position.";
@@ -1168,11 +442,13 @@ void WebController::OnDispatchPressMouseEvent(
base::OnceCallback<void(const ClientStatus&)> callback,
int x,
int y,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchMouseEventResult> result) {
if (!result) {
DVLOG(1) << __func__
<< " Failed to dispatch mouse left button pressed event.";
- std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__));
+ std::move(callback).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
return;
}
@@ -1190,16 +466,25 @@ void WebController::OnDispatchPressMouseEvent(
void WebController::OnDispatchReleaseMouseEvent(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchMouseEventResult> result) {
+ if (!result) {
+ DVLOG(1) << __func__ << " Failed to dispatch release mouse event.";
+ std::move(callback).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
std::move(callback).Run(OkClientStatus());
}
void WebController::OnDispatchTouchEventStart(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchTouchEventResult> result) {
if (!result) {
DVLOG(1) << __func__ << " Failed to dispatch touch start event.";
- std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__));
+ std::move(callback).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
return;
}
@@ -1216,8 +501,14 @@ void WebController::OnDispatchTouchEventStart(
void WebController::OnDispatchTouchEventEnd(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchTouchEventResult> result) {
- DCHECK(result);
+ if (!result) {
+ DVLOG(1) << __func__ << " Failed to dispatch touch end event.";
+ std::move(callback).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
std::move(callback).Run(OkClientStatus());
}
@@ -1234,7 +525,7 @@ void WebController::ElementCheck(const Selector& selector,
void WebController::OnFindElementForCheck(
base::OnceCallback<void(bool)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result) {
+ std::unique_ptr<ElementFinder::Result> result) {
DVLOG_IF(1,
!status.ok() && status.proto_status() != ELEMENT_RESOLUTION_FAILED)
<< __func__ << ": " << status;
@@ -1254,9 +545,10 @@ void WebController::WaitForWindowHeightChange(
void WebController::OnWaitForWindowHeightChange(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::EvaluateResult> result) {
std::move(callback).Run(
- CheckJavaScriptResult(result.get(), __FILE__, __LINE__));
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__));
}
void WebController::GetDocumentReadyState(
@@ -1299,7 +591,7 @@ void WebController::OnFindElementForWaitForDocumentReadyState(
DocumentReadyState min_ready_state,
base::OnceCallback<void(const ClientStatus&, DocumentReadyState)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element) {
+ std::unique_ptr<ElementFinder::Result> element) {
if (!status.ok()) {
std::move(callback).Run(status, DOCUMENT_UNKNOWN_READY_STATE);
return;
@@ -1329,21 +621,23 @@ void WebController::OnFindElementForWaitForDocumentReadyState(
void WebController::FindElement(const Selector& selector,
bool strict_mode,
- FindElementCallback callback) {
+ ElementFinder::Callback callback) {
auto finder = std::make_unique<ElementFinder>(
web_contents_, devtools_client_.get(), selector, strict_mode);
- ElementFinder* ptr = finder.get();
- pending_workers_[ptr] = std::move(finder);
+ auto* ptr = finder.get();
+ pending_workers_.emplace_back(std::move(finder));
ptr->Start(base::BindOnce(&WebController::OnFindElementResult,
base::Unretained(this), ptr, std::move(callback)));
}
void WebController::OnFindElementResult(
ElementFinder* finder_to_release,
- FindElementCallback callback,
+ ElementFinder::Callback callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result) {
- pending_workers_.erase(finder_to_release);
+ std::unique_ptr<ElementFinder::Result> result) {
+ base::EraseIf(pending_workers_, [finder_to_release](const auto& worker) {
+ return worker.get() == finder_to_release;
+ });
std::move(callback).Run(status, std::move(result));
}
@@ -1351,7 +645,7 @@ void WebController::OnFindElementForFocusElement(
const TopPadding& top_padding,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to find the element to focus on.";
std::move(callback).Run(status);
@@ -1370,7 +664,7 @@ void WebController::OnFindElementForFocusElement(
void WebController::OnWaitDocumentToBecomeInteractiveForFocusElement(
const TopPadding& top_padding,
base::OnceCallback<void(const ClientStatus&)> callback,
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
bool result) {
if (!result) {
std::move(callback).Run(ClientStatus(ELEMENT_UNSTABLE));
@@ -1402,8 +696,10 @@ void WebController::OnWaitDocumentToBecomeInteractiveForFocusElement(
void WebController::OnFocusElement(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
DVLOG_IF(1, !status.ok()) << __func__ << " Failed to focus on element.";
std::move(callback).Run(status);
}
@@ -1429,7 +725,7 @@ void WebController::OnFindElementForFillingForm(
const Selector& selector,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to find the element for filling the form.";
std::move(callback).Run(status);
@@ -1458,8 +754,7 @@ void WebController::OnGetFormAndFieldDataForFillingForm(
const autofill::FormFieldData& form_field) {
if (form_data.fields.empty()) {
DVLOG(1) << __func__ << " Failed to get form data to fill form.";
- std::move(callback).Run(
- UnexpectedErrorStatus(__FILE__, __LINE__)); // unexpected
+ std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__));
return;
}
@@ -1467,8 +762,7 @@ void WebController::OnGetFormAndFieldDataForFillingForm(
ContentAutofillDriver::GetForRenderFrameHost(container_frame_host);
if (!driver) {
DVLOG(1) << __func__ << " Failed to get the autofill driver.";
- std::move(callback).Run(
- UnexpectedErrorStatus(__FILE__, __LINE__)); // unexpected
+ std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__));
return;
}
@@ -1517,7 +811,7 @@ void WebController::OnFindElementForSelectOption(
const std::string& selected_option,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to find the element to select an option.";
std::move(callback).Run(status);
@@ -1542,8 +836,10 @@ void WebController::OnFindElementForSelectOption(
void WebController::OnSelectOption(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to select option.";
std::move(callback).Run(status);
@@ -1551,7 +847,8 @@ void WebController::OnSelectOption(
}
bool found;
if (!SafeGetBool(result->GetResult(), &found)) {
- std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__));
+ std::move(callback).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
return;
}
if (!found) {
@@ -1576,7 +873,7 @@ void WebController::HighlightElement(
void WebController::OnFindElementForHighlightElement(
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
DVLOG(1) << __func__ << " Failed to find the element to highlight.";
std::move(callback).Run(status);
@@ -1600,8 +897,10 @@ void WebController::OnFindElementForHighlightElement(
void WebController::OnHighlightElement(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
DVLOG_IF(1, !status.ok()) << __func__ << " Failed to highlight element.";
std::move(callback).Run(status);
}
@@ -1632,7 +931,7 @@ void WebController::GetFieldValue(
void WebController::OnFindElementForGetFieldValue(
base::OnceCallback<void(bool, const std::string&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
const std::string object_id = element_result->object_id;
if (!status.ok()) {
std::move(callback).Run(/* exists= */ false, "");
@@ -1651,9 +950,11 @@ void WebController::OnFindElementForGetFieldValue(
void WebController::OnGetValueAttribute(
base::OnceCallback<void(bool, const std::string&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
std::string value;
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
// Read the result returned from Javascript code.
DVLOG_IF(1, !status.ok())
<< __func__ << "Failed to get attribute value: " << status;
@@ -1734,7 +1035,7 @@ void WebController::DispatchKeyboardTextDownEvent(
}
if (delay && delay_in_millisecond > 0) {
- base::PostDelayedTaskWithTraits(
+ base::PostDelayedTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&WebController::DispatchKeyboardTextDownEvent,
weak_ptr_factory_.GetWeakPtr(), codepoints, index,
@@ -1797,7 +1098,7 @@ void WebController::OnFindElementForSetFieldValue(
const std::string& value,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
std::move(callback).Run(status);
return;
@@ -1820,9 +1121,10 @@ void WebController::OnFindElementForSetFieldValue(
void WebController::OnSetValueAttribute(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
std::move(callback).Run(
- CheckJavaScriptResult(result.get(), __FILE__, __LINE__));
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__));
}
void WebController::SetAttribute(
@@ -1847,7 +1149,7 @@ void WebController::OnFindElementForSetAttribute(
const std::string& value,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
std::move(callback).Run(status);
return;
@@ -1879,9 +1181,10 @@ void WebController::OnFindElementForSetAttribute(
void WebController::OnSetAttribute(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
std::move(callback).Run(
- CheckJavaScriptResult(result.get(), __FILE__, __LINE__));
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__));
}
void WebController::SendKeyboardInput(
@@ -1912,7 +1215,7 @@ void WebController::OnFindElementForSendKeyboardInput(
const int delay_in_millisecond,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
std::move(callback).Run(status);
return;
@@ -1949,8 +1252,10 @@ void WebController::GetVisualViewport(
void WebController::OnGetVisualViewport(
base::OnceCallback<void(bool, const RectF&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::EvaluateResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok() || !result->GetResult()->HasValue() ||
!result->GetResult()->GetValue()->is_list() ||
result->GetResult()->GetValue()->GetList().size() != 4u) {
@@ -1989,7 +1294,7 @@ void WebController::GetElementPosition(
void WebController::OnFindElementForPosition(
base::OnceCallback<void(bool, const RectF&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result) {
+ std::unique_ptr<ElementFinder::Result> result) {
if (!status.ok()) {
RectF empty;
std::move(callback).Run(false, empty);
@@ -2012,8 +1317,10 @@ void WebController::OnFindElementForPosition(
void WebController::OnGetElementPositionResult(
base::OnceCallback<void(bool, const RectF&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok() || !result->GetResult()->HasValue() ||
!result->GetResult()->GetValue()->is_list() ||
result->GetResult()->GetValue()->GetList().size() != 4u) {
@@ -2038,7 +1345,7 @@ void WebController::OnGetElementPositionResult(
void WebController::OnFindElementForGetOuterHtml(
base::OnceCallback<void(const ClientStatus&, const std::string&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result) {
+ std::unique_ptr<ElementFinder::Result> element_result) {
if (!status.ok()) {
DVLOG(2) << __func__ << " Failed to find element for GetOuterHtml";
std::move(callback).Run(status, "");
@@ -2057,8 +1364,10 @@ void WebController::OnFindElementForGetOuterHtml(
void WebController::OnGetOuterHtml(
base::OnceCallback<void(const ClientStatus&, const std::string&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
DVLOG(2) << __func__ << " Failed to get HTML content for GetOuterHtml";
std::move(callback).Run(status, "");
@@ -2088,8 +1397,10 @@ void WebController::OnWaitForDocumentToBecomeInteractive(
int remaining_rounds,
std::string object_id,
base::OnceCallback<void(bool)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
- ClientStatus status = CheckJavaScriptResult(result.get(), __FILE__, __LINE__);
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok() || remaining_rounds <= 0) {
DVLOG(1) << __func__
<< " Failed to wait for the document to become interactive with "
@@ -2105,7 +1416,7 @@ void WebController::OnWaitForDocumentToBecomeInteractive(
return;
}
- base::PostDelayedTaskWithTraits(
+ base::PostDelayedTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&WebController::WaitForDocumentToBecomeInteractive,
weak_ptr_factory_.GetWeakPtr(), --remaining_rounds,
diff --git a/chromium/components/autofill_assistant/browser/web_controller.h b/chromium/components/autofill_assistant/browser/web/web_controller.h
index 44a27b0ac64..31c32e264ca 100644
--- a/chromium/components/autofill_assistant/browser/web_controller.h
+++ b/chromium/components/autofill_assistant/browser/web/web_controller.h
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_CONTROLLER_H_
-#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_CONTROLLER_H_
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_H_
-#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -24,6 +23,9 @@
#include "components/autofill_assistant/browser/rectf.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/top_padding.h"
+#include "components/autofill_assistant/browser/web/element_finder.h"
+#include "components/autofill_assistant/browser/web/element_position_getter.h"
+#include "components/autofill_assistant/browser/web/web_controller_worker.h"
#include "third_party/icu/source/common/unicode/umachine.h"
#include "url/gurl.h"
@@ -40,7 +42,7 @@ class RenderFrameHost;
namespace autofill {
struct FormData;
struct FormFieldData;
-}
+} // namespace autofill
namespace autofill_assistant {
struct ClientSettings;
@@ -204,47 +206,6 @@ class WebController {
private:
friend class WebControllerBrowserTest;
- // Callback that receives the position that corresponds to the center
- // of an element, from ElementPositionGetter.
- //
- // If the first element is false, the call failed. Otherwise, the second
- // element contains the x position and the third the y position of the center
- // of the element in viewport coordinates.
- using ElementPositionCallback = base::OnceCallback<void(bool, int, int)>;
-
- // Superclass for workers that execute complex operation and keep a pointer to
- // this controller or the devtools client. Workers are owned by
- // pending_workers_ and are removed once the operation is finished.
- class Worker;
-
- // Worker class to get element's position in viewport coordinates when is
- // stable and the frame it belongs finished visual update.
- class ElementPositionGetter;
-
- // Worker class to find element(s) matching a selector. Returns
- // FindElementResult.
- class ElementFinder;
-
- struct FindElementResult {
- FindElementResult() = default;
- ~FindElementResult() = default;
-
- // The render frame host contains the element.
- content::RenderFrameHost* container_frame_host;
-
- // The selector index in the given selectors corresponding to the container
- // frame. Zero indicates the element is in main frame or the first element
- // is the container frame selector. Compare main frame with the above
- // |container_frame_host| to distinguish them.
- size_t container_frame_selector_index;
-
- // The object id of the element.
- std::string object_id;
- };
- using FindElementCallback =
- base::OnceCallback<void(const ClientStatus&,
- std::unique_ptr<FindElementResult>)>;
-
struct FillFormInputData {
FillFormInputData();
~FillFormInputData();
@@ -261,25 +222,27 @@ class WebController {
base::OnceCallback<void(const ClientStatus&)> callback,
ClickAction::ClickType click_type,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result);
+ std::unique_ptr<ElementFinder::Result> result);
void OnWaitDocumentToBecomeInteractiveForClickOrTap(
base::OnceCallback<void(const ClientStatus&)> callback,
ClickAction::ClickType click_type,
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
bool result);
void OnFindElementForTap(
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result);
+ std::unique_ptr<ElementFinder::Result> result);
void ClickOrTapElement(
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
ClickAction::ClickType click_type,
base::OnceCallback<void(const ClientStatus&)> callback);
void OnClickJS(base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
- void OnScrollIntoView(std::unique_ptr<FindElementResult> target_element,
+ void OnScrollIntoView(std::unique_ptr<ElementFinder::Result> target_element,
base::OnceCallback<void(const ClientStatus&)> callback,
ClickAction::ClickType click_type,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void TapOrClickOnCoordinates(
ElementPositionGetter* getter_to_release,
@@ -292,21 +255,26 @@ class WebController {
base::OnceCallback<void(const ClientStatus&)> callback,
int x,
int y,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchMouseEventResult> result);
void OnDispatchReleaseMouseEvent(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchMouseEventResult> result);
void OnDispatchTouchEventStart(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchTouchEventResult> result);
void OnDispatchTouchEventEnd(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<input::DispatchTouchEventResult> result);
void OnFindElementForCheck(base::OnceCallback<void(bool)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result);
+ std::unique_ptr<ElementFinder::Result> result);
void OnWaitForWindowHeightChange(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::EvaluateResult> result);
// Find the element given by |selector|. If multiple elements match
@@ -314,17 +282,17 @@ class WebController {
// found. Otherwise if |strict-mode| is true, do not return any.
void FindElement(const Selector& selector,
bool strict_mode,
- FindElementCallback callback);
+ ElementFinder::Callback callback);
void OnFindElementResult(ElementFinder* finder_to_release,
- FindElementCallback callback,
+ ElementFinder::Callback callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result);
+ std::unique_ptr<ElementFinder::Result> result);
void OnFindElementForFillingForm(
std::unique_ptr<FillFormInputData> data_to_autofill,
const Selector& selector,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnGetFormAndFieldDataForFillingForm(
std::unique_ptr<FillFormInputData> data_to_autofill,
base::OnceCallback<void(const ClientStatus&)> callback,
@@ -335,34 +303,38 @@ class WebController {
const TopPadding& top_padding,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnWaitDocumentToBecomeInteractiveForFocusElement(
const TopPadding& top_padding,
base::OnceCallback<void(const ClientStatus&)> callback,
- std::unique_ptr<FindElementResult> target_element,
+ std::unique_ptr<ElementFinder::Result> target_element,
bool result);
void OnFocusElement(base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnFindElementForSelectOption(
const std::string& selected_option,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnSelectOption(base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnFindElementForHighlightElement(
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnHighlightElement(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnFindElementForGetFieldValue(
base::OnceCallback<void(bool, const std::string&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnGetValueAttribute(
base::OnceCallback<void(bool, const std::string&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void InternalSetFieldValue(
const Selector& selector,
@@ -395,8 +367,9 @@ class WebController {
const std::string& value,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnSetAttribute(base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnFindElementForSendKeyboardInput(
const Selector& selector,
@@ -404,32 +377,36 @@ class WebController {
int delay_in_milli,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnFindElementForSetFieldValue(
const std::string& value,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnSetValueAttribute(
base::OnceCallback<void(const ClientStatus&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnFindElementForGetOuterHtml(
base::OnceCallback<void(const ClientStatus&, const std::string&)>
callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element_result);
+ std::unique_ptr<ElementFinder::Result> element_result);
void OnGetOuterHtml(base::OnceCallback<void(const ClientStatus&,
const std::string&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnFindElementForPosition(
base::OnceCallback<void(bool, const RectF&)> callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> result);
+ std::unique_ptr<ElementFinder::Result> result);
void OnGetVisualViewport(
base::OnceCallback<void(bool, const RectF&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::EvaluateResult> result);
void OnGetElementPositionResult(
base::OnceCallback<void(bool, const RectF&)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
// Creates a new instance of DispatchKeyEventParams for the specified type and
@@ -449,18 +426,14 @@ class WebController {
int remaining_rounds,
std::string object_id,
base::OnceCallback<void(bool)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
- void OnFindElementForDocumentReadyState(
- base::OnceCallback<void(const ClientStatus&, const std::string&)>
- callback,
- const ClientStatus& status,
- std::unique_ptr<FindElementResult> element);
void OnFindElementForWaitForDocumentReadyState(
DocumentReadyState min_ready_state,
base::OnceCallback<void(const ClientStatus&, DocumentReadyState)>
callback,
const ClientStatus& status,
- std::unique_ptr<FindElementResult> element);
+ std::unique_ptr<ElementFinder::Result> element);
// Weak pointer is fine here since it must outlive this web controller, which
// is guaranteed by the owner of this object.
@@ -468,11 +441,11 @@ class WebController {
std::unique_ptr<DevtoolsClient> devtools_client_;
const ClientSettings* const settings_;
- // Workers currently running and using |devtools_client_|.
- std::map<Worker*, std::unique_ptr<Worker>> pending_workers_;
+ // Currently running workers.
+ std::vector<std::unique_ptr<WebControllerWorker>> pending_workers_;
- base::WeakPtrFactory<WebController> weak_ptr_factory_;
+ base::WeakPtrFactory<WebController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WebController);
};
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_CONTROLLER_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_H_
diff --git a/chromium/components/autofill_assistant/browser/web_controller_browsertest.cc b/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc
index 148a116ecfd..9481f480c9c 100644
--- a/chromium/components/autofill_assistant/browser/web_controller_browsertest.cc
+++ b/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc
@@ -10,7 +10,7 @@
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/string_conversions_util.h"
#include "components/autofill_assistant/browser/top_padding.h"
-#include "components/autofill_assistant/browser/web_controller.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -50,6 +50,11 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
paint_occurred_during_last_loop_ = true;
}
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch("allow-pre-commit-input");
+ }
+
void WaitTillPageIsIdle(base::TimeDelta continuous_paint_timeout) {
base::TimeTicks finished_load_time = base::TimeTicks::Now();
bool page_is_loading = false;
@@ -233,7 +238,7 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
void FindElement(const Selector& selector,
ClientStatus* status_out,
- WebController::FindElementResult* result_out) {
+ ElementFinder::Result* result_out) {
base::RunLoop run_loop;
web_controller_->FindElement(
selector, /* strict_mode= */ true,
@@ -246,9 +251,9 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
void OnFindElement(const base::Closure& done_callback,
ClientStatus* status_out,
- WebController::FindElementResult* result_out,
+ ElementFinder::Result* result_out,
const ClientStatus& status,
- std::unique_ptr<WebController::FindElementResult> result) {
+ std::unique_ptr<ElementFinder::Result> result) {
ASSERT_TRUE(result);
done_callback.Run();
if (status_out)
@@ -263,7 +268,7 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
bool is_main_frame) {
SCOPED_TRACE(::testing::Message() << selector << " strict");
ClientStatus status;
- WebController::FindElementResult result;
+ ElementFinder::Result result;
FindElement(selector, &status, &result);
EXPECT_EQ(ACTION_APPLIED, status.proto_status());
CheckFindElementResult(result, expected_index, is_main_frame);
@@ -272,13 +277,13 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
void FindElementExpectEmptyResult(const Selector& selector) {
SCOPED_TRACE(::testing::Message() << selector << " strict");
ClientStatus status;
- WebController::FindElementResult result;
+ ElementFinder::Result result;
FindElement(selector, &status, &result);
EXPECT_EQ(ELEMENT_RESOLUTION_FAILED, status.proto_status());
EXPECT_THAT(result.object_id, IsEmpty());
}
- void CheckFindElementResult(const WebController::FindElementResult& result,
+ void CheckFindElementResult(const ElementFinder::Result& result,
size_t expected_index,
bool is_main_frame) {
if (is_main_frame) {
@@ -672,8 +677,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ClickElement) {
WaitForElementRemove(selector);
}
-IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
- ClickElementInIFrame) {
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ClickElementInIFrame) {
Selector selector;
selector.selectors.emplace_back("#iframe");
selector.selectors.emplace_back("#shadowsection");
@@ -1236,4 +1240,4 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
AnyOf(DOCUMENT_LOADED, DOCUMENT_INTERACTIVE, DOCUMENT_COMPLETE));
}
-} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller_util.cc b/chromium/components/autofill_assistant/browser/web/web_controller_util.cc
new file mode 100644
index 00000000000..aa0f66d7ab0
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/web_controller_util.cc
@@ -0,0 +1,84 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/web/web_controller_util.h"
+
+namespace autofill_assistant {
+
+ClientStatus UnexpectedErrorStatus(const std::string& file, int line) {
+ ClientStatus status(OTHER_ACTION_STATUS);
+ auto* info = status.mutable_details()->mutable_unexpected_error_info();
+ info->set_source_file(file);
+ info->set_source_line_number(line);
+ return status;
+}
+
+ClientStatus UnexpectedDevtoolsErrorStatus(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ const std::string& file,
+ int line) {
+ ClientStatus status = UnexpectedErrorStatus(file, line);
+ if (!reply_status.is_ok()) {
+ auto* info = status.mutable_details()->mutable_unexpected_error_info();
+ info->set_devtools_error_code(reply_status.error_code);
+ info->set_devtools_error_message(reply_status.error_message);
+ }
+ return status;
+}
+
+ClientStatus JavaScriptErrorStatus(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ const std::string& file,
+ int line,
+ const runtime::ExceptionDetails* exception) {
+ ClientStatus status = UnexpectedDevtoolsErrorStatus(reply_status, file, line);
+ status.set_proto_status(UNEXPECTED_JS_ERROR);
+ if (exception) {
+ auto* info = status.mutable_details()->mutable_unexpected_error_info();
+ if (exception->HasException() &&
+ exception->GetException()->HasClassName()) {
+ info->set_js_exception_classname(
+ exception->GetException()->GetClassName());
+ }
+ info->set_js_exception_line_number(exception->GetLineNumber());
+ info->set_js_exception_column_number(exception->GetColumnNumber());
+ }
+ return status;
+}
+
+bool SafeGetObjectId(const runtime::RemoteObject* result, std::string* out) {
+ if (result && result->HasObjectId()) {
+ *out = result->GetObjectId();
+ return true;
+ }
+ return false;
+}
+
+bool SafeGetStringValue(const runtime::RemoteObject* result, std::string* out) {
+ if (result && result->HasValue() && result->GetValue()->is_string()) {
+ *out = result->GetValue()->GetString();
+ return true;
+ }
+ return false;
+}
+
+bool SafeGetIntValue(const runtime::RemoteObject* result, int* out) {
+ if (result && result->HasValue() && result->GetValue()->is_int()) {
+ *out = result->GetValue()->GetInt();
+ return true;
+ }
+ *out = 0;
+ return false;
+}
+
+bool SafeGetBool(const runtime::RemoteObject* result, bool* out) {
+ if (result && result->HasValue() && result->GetValue()->is_bool()) {
+ *out = result->GetValue()->GetBool();
+ return true;
+ }
+ *out = false;
+ return false;
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller_util.h b/chromium/components/autofill_assistant/browser/web/web_controller_util.h
new file mode 100644
index 00000000000..b96669513f1
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/web_controller_util.h
@@ -0,0 +1,70 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_UTIL_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_UTIL_H_
+
+#include <string>
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/devtools/devtools/domains/types_runtime.h"
+#include "components/autofill_assistant/browser/devtools/devtools_client.h"
+
+namespace autofill_assistant {
+
+// Builds a ClientStatus appropriate for an unexpected error.
+//
+// This should only be used in situations where getting an error cannot be
+// anything but a bug in the client and no devtools ReplyStatus is available.
+ClientStatus UnexpectedErrorStatus(const std::string& file, int line);
+
+// Builds a ClientStatus appropriate for an unexpected error in a devtools
+// response.
+//
+// This should only be used in situations where getting an error cannot be
+// anything but a bug in the client.
+ClientStatus UnexpectedDevtoolsErrorStatus(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ const std::string& file,
+ int line);
+
+// Builds a ClientStatus appropriate for a JavaScript error.
+ClientStatus JavaScriptErrorStatus(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ const std::string& file,
+ int line,
+ const runtime::ExceptionDetails* exception);
+
+// Makes sure that the given EvaluateResult exists, is successful and contains a
+// result.
+template <typename T>
+ClientStatus CheckJavaScriptResult(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ T* result,
+ const char* file,
+ int line) {
+ if (!result)
+ return JavaScriptErrorStatus(reply_status, file, line, nullptr);
+ if (result->HasExceptionDetails())
+ return JavaScriptErrorStatus(reply_status, file, line,
+ result->GetExceptionDetails());
+ if (!result->GetResult())
+ return JavaScriptErrorStatus(reply_status, file, line, nullptr);
+ return OkClientStatus();
+}
+
+// Safely gets an object id from a RemoteObject
+bool SafeGetObjectId(const runtime::RemoteObject* result, std::string* out);
+
+// Safely gets a string value from a RemoteObject
+bool SafeGetStringValue(const runtime::RemoteObject* result, std::string* out);
+
+// Safely gets a int value from a RemoteObject.
+bool SafeGetIntValue(const runtime::RemoteObject* result, int* out);
+
+// Safely gets a boolean value from a RemoteObject
+bool SafeGetBool(const runtime::RemoteObject* result, bool* out);
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_UTIL_H_
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller_worker.h b/chromium/components/autofill_assistant/browser/web/web_controller_worker.h
new file mode 100644
index 00000000000..5da5a27b8ca
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/web_controller_worker.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 COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_WORKER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_WORKER_H_
+
+#include "base/macros.h"
+
+namespace autofill_assistant {
+
+// Superclass for workers of |WebController| that execute complex operations.
+// This superclass merely ensures that workers can be memory-managed by
+// others (in particular an instance of |WebController|), by making the
+// base constructor/destructor public.
+class WebControllerWorker {
+ public:
+ WebControllerWorker() = default;
+ virtual ~WebControllerWorker() = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebControllerWorker);
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_WEB_CONTROLLER_WORKER_H_ \ No newline at end of file
diff --git a/chromium/components/autofill_assistant/browser/website_login_fetcher.cc b/chromium/components/autofill_assistant/browser/website_login_fetcher.cc
new file mode 100644
index 00000000000..4ae6a9e3217
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/website_login_fetcher.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 "components/autofill_assistant/browser/website_login_fetcher.h"
+
+namespace autofill_assistant {
+
+WebsiteLoginFetcher::Login::Login(const GURL& _origin,
+ const std::string& _username)
+ : origin(_origin), username(_username) {}
+
+WebsiteLoginFetcher::Login::Login(const Login& other) = default;
+WebsiteLoginFetcher::Login::~Login() = default;
+
+} // namespace autofill_assistant \ No newline at end of file
diff --git a/chromium/components/autofill_assistant/browser/website_login_fetcher.h b/chromium/components/autofill_assistant/browser/website_login_fetcher.h
new file mode 100644
index 00000000000..fe8c36df27c
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/website_login_fetcher.h
@@ -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.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEBSITE_LOGIN_FETCHER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEBSITE_LOGIN_FETCHER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "url/gurl.h"
+
+namespace autofill_assistant {
+
+// Common interface for implementations that fetch login details for websites.
+class WebsiteLoginFetcher {
+ public:
+ // Uniquely represents a particular login.
+ struct Login {
+ Login(const GURL& origin, const std::string& username);
+ Login(const Login& other);
+ ~Login();
+
+ // The scheme, host, port and path of the login website.
+ GURL origin;
+ std::string username;
+ };
+
+ WebsiteLoginFetcher() = default;
+ virtual ~WebsiteLoginFetcher() = default;
+
+ // Asynchronously returns all matching login details for |url| in the
+ // specified callback.
+ virtual void GetLoginsForUrl(
+ const GURL& url,
+ base::OnceCallback<void(std::vector<Login>)> callback) = 0;
+
+ // Retrieves the password for |login| in the specified |callback|, or |false|
+ // if the password could not be retrieved.
+ virtual void GetPasswordForLogin(
+ const Login& login,
+ base::OnceCallback<void(bool, std::string)> callback) = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(WebsiteLoginFetcher);
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEBSITE_LOGIN_FETCHER_H_
diff --git a/chromium/components/autofill_assistant/browser/website_login_fetcher_impl.cc b/chromium/components/autofill_assistant/browser/website_login_fetcher_impl.cc
new file mode 100644
index 00000000000..8352cedc3fb
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/website_login_fetcher_impl.cc
@@ -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.
+
+#include "components/autofill_assistant/browser/website_login_fetcher_impl.h"
+
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "components/password_manager/core/browser/form_fetcher_impl.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace autofill_assistant {
+
+// Represents a pending form fetcher request which will notify the
+// |WebsiteLoginFetcherImpl| when finished.
+class WebsiteLoginFetcherImpl::PendingRequest
+ : public password_manager::FormFetcher::Consumer {
+ public:
+ PendingRequest(
+ const password_manager::PasswordStore::FormDigest& form_digest,
+ const password_manager::PasswordManagerClient* client,
+ base::OnceCallback<void(const PendingRequest*)> notify_finished_callback)
+ : form_fetcher_(
+ std::make_unique<password_manager::FormFetcherImpl>(form_digest,
+ client,
+ true)),
+ notify_finished_callback_(std::move(notify_finished_callback)),
+ weak_ptr_factory_(this) {}
+
+ ~PendingRequest() override = default;
+ void Start() {
+ // Note: Currently, |FormFetcherImpl| has the default state NOT_WAITING.
+ // This has the unfortunate side effect that new consumers are immediately
+ // notified with an empty result. As a workaround to avoid this first
+ // notification, we register as consumer *after* we call |Fetch|.
+ form_fetcher_->Fetch();
+ form_fetcher_->AddConsumer(this);
+ }
+
+ protected:
+ // From password_manager::FormFetcher::Consumer:
+ // This implementation should be called by subclasses when they are finished.
+ void OnFetchCompleted() override {
+ // This needs to be done asynchronously, because it will lead to the
+ // destruction of |this|, which needs to happen *after* this call has
+ // returned.
+ if (notify_finished_callback_) {
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&PendingRequest::NotifyFinished,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(notify_finished_callback_)));
+ }
+ }
+ std::unique_ptr<password_manager::FormFetcher> form_fetcher_;
+
+ private:
+ void NotifyFinished(
+ base::OnceCallback<void(const PendingRequest*)> callback) {
+ form_fetcher_->RemoveConsumer(this);
+ std::move(callback).Run(this);
+ }
+
+ base::OnceCallback<void(const PendingRequest*)> notify_finished_callback_;
+ base::WeakPtrFactory<PendingRequest> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(PendingRequest);
+};
+
+// A pending request to fetch all logins that match the specified |form_digest|.
+class WebsiteLoginFetcherImpl::PendingFetchLoginsRequest
+ : public WebsiteLoginFetcherImpl::PendingRequest {
+ public:
+ PendingFetchLoginsRequest(
+ const password_manager::PasswordStore::FormDigest& form_digest,
+ const password_manager::PasswordManagerClient* client,
+ base::OnceCallback<void(std::vector<Login>)> callback,
+ base::OnceCallback<void(const PendingRequest*)> notify_finished_callback)
+ : PendingRequest(form_digest,
+ client,
+ std::move(notify_finished_callback)),
+ callback_(std::move(callback)) {}
+
+ protected:
+ // From PendingRequest:
+ void OnFetchCompleted() override {
+ std::vector<Login> logins;
+ for (const auto& match : form_fetcher_->GetBestMatches()) {
+ logins.emplace_back(match.second->origin,
+ base::UTF16ToUTF8(match.second->username_value));
+ }
+ std::move(callback_).Run(logins);
+ PendingRequest::OnFetchCompleted();
+ }
+
+ private:
+ base::OnceCallback<void(std::vector<Login>)> callback_;
+};
+
+// A pending request to fetch the password for the specified |login|.
+class WebsiteLoginFetcherImpl::PendingFetchPasswordRequest
+ : public WebsiteLoginFetcherImpl::PendingRequest {
+ public:
+ PendingFetchPasswordRequest(
+ const password_manager::PasswordStore::FormDigest& form_digest,
+ const password_manager::PasswordManagerClient* client,
+ const Login& login,
+ base::OnceCallback<void(bool, std::string)> callback,
+ base::OnceCallback<void(const PendingRequest*)> notify_finished_callback)
+ : PendingRequest(form_digest,
+ client,
+ std::move(notify_finished_callback)),
+ login_(login),
+ callback_(std::move(callback)) {}
+
+ protected:
+ // From PendingRequest:
+ void OnFetchCompleted() override {
+ std::vector<const autofill::PasswordForm*> matches =
+ form_fetcher_->GetNonFederatedMatches();
+ for (const auto* match : matches) {
+ if (base::UTF16ToUTF8(match->username_value) == login_.username) {
+ std::move(callback_).Run(true,
+ base::UTF16ToUTF8(match->password_value));
+ PendingRequest::OnFetchCompleted();
+ return;
+ }
+ }
+ std::move(callback_).Run(false, std::string());
+ PendingRequest::OnFetchCompleted();
+ }
+
+ private:
+ Login login_;
+ base::OnceCallback<void(bool, std::string)> callback_;
+};
+
+WebsiteLoginFetcherImpl::WebsiteLoginFetcherImpl(
+ const password_manager::PasswordManagerClient* client)
+ : client_(client), weak_ptr_factory_(this) {}
+
+WebsiteLoginFetcherImpl::~WebsiteLoginFetcherImpl() = default;
+
+void WebsiteLoginFetcherImpl::GetLoginsForUrl(
+ const GURL& url,
+ base::OnceCallback<void(std::vector<Login>)> callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ password_manager::PasswordStore::FormDigest digest(
+ autofill::PasswordForm::Scheme::kHtml, url.GetOrigin().spec(), GURL());
+ pending_requests_.emplace_back(std::make_unique<PendingFetchLoginsRequest>(
+ digest, client_, std::move(callback),
+ base::BindOnce(&WebsiteLoginFetcherImpl::OnRequestFinished,
+ weak_ptr_factory_.GetWeakPtr())));
+ pending_requests_.back()->Start();
+}
+
+void WebsiteLoginFetcherImpl::GetPasswordForLogin(
+ const Login& login,
+ base::OnceCallback<void(bool, std::string)> callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ password_manager::PasswordStore::FormDigest digest(
+ autofill::PasswordForm::Scheme::kHtml, login.origin.spec(), GURL());
+ pending_requests_.emplace_back(std::make_unique<PendingFetchPasswordRequest>(
+ digest, client_, login, std::move(callback),
+ base::BindOnce(&WebsiteLoginFetcherImpl::OnRequestFinished,
+ weak_ptr_factory_.GetWeakPtr())));
+ pending_requests_.back()->Start();
+}
+
+void WebsiteLoginFetcherImpl::OnRequestFinished(const PendingRequest* request) {
+ base::EraseIf(pending_requests_, [request](const auto& candidate_request) {
+ return candidate_request.get() == request;
+ });
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/website_login_fetcher_impl.h b/chromium/components/autofill_assistant/browser/website_login_fetcher_impl.h
new file mode 100644
index 00000000000..58ea3c27313
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/website_login_fetcher_impl.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEBSITE_LOGIN_FETCHER_IMPL_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEBSITE_LOGIN_FETCHER_IMPL_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/website_login_fetcher.h"
+
+namespace password_manager {
+class PasswordManagerClient;
+} // namespace password_manager
+
+namespace autofill_assistant {
+
+// Native implementation of the autofill assistant website login fetcher, which
+// wraps access to the Chrome password manager.
+class WebsiteLoginFetcherImpl : public WebsiteLoginFetcher {
+ public:
+ WebsiteLoginFetcherImpl(
+ const password_manager::PasswordManagerClient* client);
+ ~WebsiteLoginFetcherImpl() override;
+
+ // From WebsiteLoginFetcher:
+ void GetLoginsForUrl(
+ const GURL& url,
+ base::OnceCallback<void(std::vector<Login>)> callback) override;
+ void GetPasswordForLogin(
+ const Login& login,
+ base::OnceCallback<void(bool, std::string)> callback) override;
+
+ private:
+ class PendingRequest;
+ class PendingFetchLoginsRequest;
+ class PendingFetchPasswordRequest;
+
+ void OnRequestFinished(const PendingRequest* request);
+
+ const password_manager::PasswordManagerClient* client_;
+
+ // Fetch requests owned by the password manager, released when they are
+ // finished.
+ std::vector<std::unique_ptr<PendingRequest>> pending_requests_;
+
+ // Needs to be the last member.
+ base::WeakPtrFactory<WebsiteLoginFetcherImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebsiteLoginFetcherImpl);
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEBSITE_LOGIN_FETCHER_IMPL_H_
diff --git a/chromium/components/autofill_payments_strings.grdp b/chromium/components/autofill_payments_strings.grdp
index b50d29cdd10..b993cfbe7ba 100644
--- a/chromium/components/autofill_payments_strings.grdp
+++ b/chromium/components/autofill_payments_strings.grdp
@@ -307,6 +307,9 @@
<message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN_CVC" desc="Error message that encourages the user to try to re-enter their credit card CVC after a previous failed attempt." formatter_data="android_java">
Check your CVC and try again
</message>
+ <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN_CVC_AND_EXPIRATION_V2" desc="Error message that encourages the user to try to re-enter their credit card CVC or update the expiration dates after a previous failed attempt, according to August 2019 UI guidelines.">
+ Check your CVC and try again or update the expiration date
+ </message>
<if expr="is_android">
<message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN_EXPIRATION_DATE" desc="Error message that encourages the user to try to re-enter their credit card expiration date after a previous failed attempt." formatter_data="android_java">
Check your expiration date and try again
@@ -331,6 +334,9 @@
<message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE" desc="Title for the credit card unmasking dialog.">
Enter the CVC for <ph name="CREDIT_CARD">$1<ex>Visa - 5679</ex></ph>
</message>
+ <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE_V2" desc="Title for the credit card unmasking dialog, according to August 2019 UI guidelines.">
+ Verify your card
+ </message>
<message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_EXPIRED_TITLE" desc="Title for the credit card unmasking dialog when the credit card is expired.">
Enter the expiration date and CVC for <ph name="CREDIT_CARD">$1<ex>Visa - 5679</ex></ph>
</message>
@@ -340,6 +346,9 @@
<message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_LOCAL_CARD" desc="Text explaining what the user should do in the card unmasking dialog. Appears specifically for local cards already stored on the device.">
Once you confirm, your card details will be shared with this site.
</message>
+ <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_V2" desc="Text explaining what the user should do in the card unmasking dialog, according to August 2019 UI guidelines.">
+ Confirm the security code to share your card details with this site
+ </message>
<message name="IDS_AUTOFILL_CARD_UNMASK_CVC_IMAGE_DESCRIPTION" desc="Accessible description for the CVC image. It should describe where to find the CVC on a credit card.">
The CVC is located behind your card.
</message>
@@ -388,9 +397,17 @@
</message>
</if>
</if>
+ <if expr="is_android">
+ <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_ENABLE_FIDO_AUTH_CHECKBOX" desc="Text for checkbox in card unmasking dialog that allows the use of fingerprint to unmask cards starting next time. If checked, then a fingerprint prompt will immediately follow." formatter_data="android_java">
+ Use fingerprint to verify this card next time.
+ </message>
+ </if>
<message name="IDS_AUTOFILL_CARD_UNMASK_CONFIRM_BUTTON" desc="Text for button that confirms the credit card CVC entry dialog.">
Confirm
</message>
+ <message name="IDS_AUTOFILL_CARD_UNMASK_VERIFY_BUTTON" desc="Label text for the ok button in the credit card CVC entry dialog.">
+ Verify
+ </message>
<message name="IDS_AUTOFILL_CARD_UNMASK_EXPIRATION_MONTH" desc="Accessible name for card expiry month field.">
Month
</message>
@@ -416,6 +433,41 @@
CVC
</message>
+ <!-- WebAuthn fingerprint opt-in dialog -->
+ <!-- Desktop only -->
+ <if expr="not is_ios and not is_android">
+ <if expr="is_macosx">
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE" desc="Headline asking the user if they want to use their device's platform authenticator to confirm their cards in the future instead of CVC.">
+ Use Touch ID instead of CVC?
+ </message>
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL" desc="Button that allows the user to use their device's platform authenticator to confirm card use in the future.">
+ Use Touch ID
+ </message>
+ </if>
+ <if expr="is_win">
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE" desc="Headline asking the user if they want to use their device's platform authenticator to confirm their cards in the future instead of CVC.">
+ Use Windows Hello instead of CVC?
+ </message>
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL" desc="Button that allows the user to use their device's platform authenticator to confirm card use in the future.">
+ Use Windows Hello
+ </message>
+ </if>
+ <if expr="not is_win and not is_macosx">
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE" desc="Headline asking the user if they want to use their device's platform authenticator to confirm their cards in the future instead of CVC.">
+ Use WebAuthn instead of CVC?
+ </message>
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL" desc="Button that allows the user to use their device's platform authenticator to confirm card use in the future.">
+ Use WebAuthn
+ </message>
+ </if>
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_INSTRUCTION" desc="Subheading that appears below the headline explaining to the user that they won't have to enter their card's security code if they decide to use their device's platform authenticator in the future.">
+ You won't need to enter a card security code from now on
+ </message>
+ <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_CANCEL_BUTTON_LABEL" desc="Button that allows the user to decline the option of using their device's platform authenticator for card confirmation.">
+ Not now
+ </message>
+ </if>
+
<message name="IDS_AUTOFILL_WALLET_MANAGEMENT_LINK_TEXT" desc="Text for link that allows users to see and edit their Wallet information." formatter_data="android_java">
Edit
</message>
diff --git a/chromium/components/background_task_scheduler/BUILD.gn b/chromium/components/background_task_scheduler/BUILD.gn
index 7db9b4d179a..c0dc4f77982 100644
--- a/chromium/components/background_task_scheduler/BUILD.gn
+++ b/chromium/components/background_task_scheduler/BUILD.gn
@@ -30,10 +30,12 @@ if (is_android) {
android_library("background_task_scheduler_java") {
java_files = [
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTask.java",
+ "android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskBroadcastReceiver.java",
+ "android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskFactory.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java",
- "android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskReflection.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java",
+ "android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManager.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerFactory.java",
@@ -43,20 +45,22 @@ if (is_android) {
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java",
"android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java",
"android/java/src/org/chromium/components/background_task_scheduler/BundleToPersistableBundleConverter.java",
+ "android/java/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverter.java",
"android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java",
"android/java/src/org/chromium/components/background_task_scheduler/TaskParameters.java",
]
- proguard_configs = [ "android/proguard.flags" ]
-
deps = [
":background_task_scheduler_task_ids_java",
+ ":scheduled_task_java",
"$google_play_services_package:google_play_services_base_java",
"$google_play_services_package:google_play_services_basement_java",
"$google_play_services_package:google_play_services_gcm_java",
"$google_play_services_package:google_play_services_tasks_java",
"//base:base_java",
+ "//content/public/android:content_java",
"//third_party/android_deps:com_android_support_support_annotations_java",
+ "//third_party/android_deps:com_google_protobuf_protobuf_lite_java",
]
}
@@ -90,12 +94,15 @@ if (is_android) {
"android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java",
+ "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManagerTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java",
+ "android/junit/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverterTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/ShadowGcmNetworkManager.java",
"android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java",
"android/junit/src/org/chromium/components/background_task_scheduler/TestBackgroundTask.java",
+ "android/junit/src/org/chromium/components/background_task_scheduler/TestBackgroundTaskFactory.java",
]
deps = [
@@ -111,4 +118,12 @@ if (is_android) {
"//third_party/junit",
]
}
+
+ proto_java_library("scheduled_task_java") {
+ proto_path =
+ "android/java/src/org/chromium/components/background_task_scheduler"
+ sources = [
+ "$proto_path/scheduled_task.proto",
+ ]
+ }
}
diff --git a/chromium/components/background_task_scheduler/README.md b/chromium/components/background_task_scheduler/README.md
index 652b7136f95..160441f1c1e 100644
--- a/chromium/components/background_task_scheduler/README.md
+++ b/chromium/components/background_task_scheduler/README.md
@@ -62,6 +62,13 @@ no arguments.**
A task must also have a unique ID, and it must be listed in `TaskIds` to ensure
there is no overlap between different tasks.
+The connection between `TaskIds` and the corresponding `BackgroundTask` classes is done by injecting
+a `BackgroundTaskFactory` class in `BackgroundTaskSchedulerFactory`. For the //chrome embedder
+(which is the only one needing the association), the `ChromeBackgroundTaskFactory` [implementation]
+(https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser
+/background_task_scheduler/ChromeBackgroundTaskFactory.java) was created. Anyone that adds a new
+task id to `TaskIds` should add a case in this class to.
+
## How to schedule a task
A task is scheduled by creating an object containing information about the task,
@@ -73,21 +80,29 @@ There are two main types of tasks; one-off tasks and periodic tasks. One-off
tasks are only executed once, whereas periodic tasks are executed once per
a defined interval.
+There are two steps in the process of creating a TaskInfo:
+
+ 1. the specific timing info is created; there are two objects available - `OneOffInfo` and
+ `PeriodicInfo`; each one of these objects has its own builder;
+ 2. the task info is created using the `createTask` method; other parameters can be set afterwards.
+
As an example for how to create a one-off task that executes in 200 minutes,
you can do the following:
```java
-TaskInfo.createOneOffTask(TaskIds.YOUR_FEATURE,
- MyBackgroundTask.class,
- TimeUnit.MINUTES.toMillis(200)).build();
+TaskInfo.TimingInfo oneOffInfo = TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(200)).build();
+TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
+ oneOffInfo).build();
```
For a periodic task that executes every 200 minutes, you can call:
```java
-TaskInfo.createPeriodicTask(TaskIds.YOUR_FEATURE,
- MyBackgroundTask.class,
- TimeUnit.MINUTES.toMillis(200)).build();
+TaskInfo.TimingInfo periodicInfo = TaskInfo.PeriodicInfo.create()
+ .setIntervalMs(TimeUnit.MINUTES.toMillis(200)).build();
+TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
+ periodicInfo).build();
```
Typically you will also set other required parameters such as what type of
@@ -95,12 +110,11 @@ network conditions are necessary and whether the task requires the device to
be charging. They can be set on the builder like this:
```java
-TaskInfo.createOneOffTask(TaskIds.YOUR_FEATURE,
- MyBackgroundTask.class,
- /* windowStartTimeMs= */
- TimeUnit.MINUTES.toMillis(100)
- /* windowEndTimeMs= */
- TimeUnit.MINUTES.toMillis(200))
+TaskInfo.TimingInfo oneOffInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TimeUnit.MINUTES.toMillis(100))
+ .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(200)).build();
+TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
+ oneOffInfo)
.setRequiresCharging(true)
.setRequiredNetworkType(
TaskInfo.NETWORK_TYPE_UNMETERED)
@@ -137,10 +151,11 @@ Bundle myBundle = new Bundle();
myBundle.putString("foo", "bar");
myBundle.putLong("number", 1337L);
-TaskInfo.createOneOffTask(TaskIds.YOUR_FEATURE,
- MyBackgroundTask.class,
- TimeUnit.MINUTES.toMillis(100)
- TimeUnit.MINUTES.toMillis(200))
+TaskInfo.TimingInfo oneOffInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TimeUnit.MINUTES.toMillis(100))
+ .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(200)).build();
+TaskInfo taskInfo = TaskInfo.createTask(TaskIds.YOUR_FEATURE,
+ oneOffInfo)
.setExtras(myBundle)
.build();
```
@@ -159,6 +174,29 @@ boolean onStartTask(Context context,
}
```
+## Performing actions over TimingInfo objects
+
+To perform actions over the `TimingInfo` objects, based on their implementation, the Visitor design
+pattern was used. A public interface is exposed for this: `TimingInfoVisitor`. To use this
+interface, someone should create a class that would look like this:
+
+```java
+class ImplementedActionVisitor implements TaskInfo.TimingInfoVisitor {
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) { ... }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) { ... }
+}
+```
+
+To use this visitor, someone would make the following calls:
+
+```java
+ImplementedActionVisitor visitor = new ImplementedActionVisitor();
+myTimingInfo.accept(visitor);
+```
+
## Loading Native parts
Some of the tasks running in the background require native parts of the browser
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskBroadcastReceiver.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskBroadcastReceiver.java
new file mode 100644
index 00000000000..b5c47ed4630
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskBroadcastReceiver.java
@@ -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.
+
+package org.chromium.components.background_task_scheduler;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Checks that all requirements set for a BackgroundTask are met and if so, starts running the task.
+ *
+ * Receives the information through a broadcast, which is synchronous in the Main thread. The
+ * execution of the task will be detached to a different thread and the program will wait for the
+ * task to finish through a separate Waiter class.
+ */
+public class BackgroundTaskBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // TODO(crbug.com/970160): Implement general logic.
+
+ // Not implemented. This assures the method is not called by mistake.
+ assert false;
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskFactory.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskFactory.java
new file mode 100644
index 00000000000..92c5a3ee108
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskFactory.java
@@ -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.
+
+package org.chromium.components.background_task_scheduler;
+
+/**
+ * Generic factory interface to inject into {@link BackgroundTaskSchedulerFactory}.
+ * Exposes the interface call for getting the BackgroundTask class instance from the task id.
+ */
+public interface BackgroundTaskFactory {
+ /**
+ * Creates a BackgroundTask class instance for a given task id.
+ * @param taskId the task id for which to create a BackgroundTask class instance.
+ * @return an instance of the corresponding BackgroundTask class or null if task id is unknown.
+ */
+ BackgroundTask getBackgroundTaskFromTaskId(int taskId);
+}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
index 46380ee7705..61151889ffb 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
@@ -91,21 +91,26 @@ public class BackgroundTaskGcmTaskService extends GcmTaskService {
@Override
public int onRunTask(TaskParams params) {
+ final TaskParameters taskParams =
+ BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params);
+
final BackgroundTask backgroundTask =
- BackgroundTaskSchedulerGcmNetworkManager.getBackgroundTaskFromTaskParams(params);
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(taskParams.getTaskId());
if (backgroundTask == null) {
- Log.w(TAG, "Failed to start task. Could not instantiate class.");
+ Log.w(TAG, "Failed to start task. Could not instantiate BackgroundTask class.");
+ // Cancel task if the BackgroundTask class is not found anymore. We assume this means
+ // that the task has been deprecated.
+ BackgroundTaskSchedulerFactory.getScheduler().cancel(
+ ContextUtils.getApplicationContext(), taskParams.getTaskId());
return GcmNetworkManager.RESULT_FAILURE;
}
- Long deadlineTime =
- BackgroundTaskSchedulerGcmNetworkManager.getDeadlineTimeFromTaskParams(params);
- if (deadlineTime != null && mClock.currentTimeMillis() >= deadlineTime) {
+ if (BackgroundTaskSchedulerGcmNetworkManager.didTaskExpire(
+ params, mClock.currentTimeMillis())) {
+ BackgroundTaskSchedulerUma.getInstance().reportTaskExpired(taskParams.getTaskId());
return GcmNetworkManager.RESULT_FAILURE;
}
- final TaskParameters taskParams =
- BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params);
final Waiter waiter = new Waiter(Waiter.MAX_TIMEOUT_SECONDS);
final AtomicBoolean taskNeedsBackgroundProcessing = new AtomicBoolean();
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
index f54aa98238b..8c626d29af1 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
@@ -75,15 +75,18 @@ public class BackgroundTaskJobService extends JobService {
public boolean onStartJob(JobParameters params) {
ThreadUtils.assertOnUiThread();
BackgroundTask backgroundTask =
- BackgroundTaskSchedulerJobService.getBackgroundTaskFromJobParameters(params);
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(params.getJobId());
if (backgroundTask == null) {
- Log.w(TAG, "Failed to start task. Could not instantiate class.");
+ Log.w(TAG, "Failed to start task. Could not instantiate BackgroundTask class.");
+ // Cancel task if the BackgroundTask class is not found anymore. We assume this means
+ // that the task has been deprecated.
+ BackgroundTaskSchedulerFactory.getScheduler().cancel(
+ ContextUtils.getApplicationContext(), params.getJobId());
return false;
}
- Long deadlineTime =
- BackgroundTaskSchedulerJobService.getDeadlineTimeFromJobParameters(params);
- if (deadlineTime != null && mClock.currentTimeMillis() >= deadlineTime) {
+ if (BackgroundTaskSchedulerJobService.didTaskExpire(params, mClock.currentTimeMillis())) {
+ BackgroundTaskSchedulerUma.getInstance().reportTaskExpired(params.getJobId());
return false;
}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskReflection.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskReflection.java
deleted file mode 100644
index 91bbbefc5d1..00000000000
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskReflection.java
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.background_task_scheduler;
-
-import android.support.annotation.Nullable;
-
-import org.chromium.base.Log;
-
-import java.lang.reflect.Constructor;
-
-/**
- * BakgroundTaskReflection contains functionality to construct {@link BackgroundTask} instances from
- * their classname and to inspect whether a particular {@link BackgroundTask} has a parameterless
- * constructor, which is required for any {@link BackgroundTask}.
- */
-final class BackgroundTaskReflection {
- private static final String TAG = "BkgrdTaskReflect";
-
- /**
- * Uses reflection to find the given class and instantiates a {@link BackgroundTask} if the
- * class is valid.
- *
- * @param backgroundTaskClassName the full class name to look for.
- * @return a new {@link BackgroundTask} instance if successful or null when a failure occurs.
- */
- @Nullable
- static BackgroundTask getBackgroundTaskFromClassName(String backgroundTaskClassName) {
- if (backgroundTaskClassName == null) return null;
-
- Class<?> clazz;
- try {
- clazz = Class.forName(backgroundTaskClassName);
- } catch (ClassNotFoundException e) {
- Log.w(TAG, "Unable to find BackgroundTask class with name " + backgroundTaskClassName);
- return null;
- }
-
- if (!BackgroundTask.class.isAssignableFrom(clazz)) {
- Log.w(TAG, "Class " + clazz + " is not a BackgroundTask");
- return null;
- }
-
- try {
- return (BackgroundTask) clazz.newInstance();
- } catch (InstantiationException e) {
- Log.w(TAG, "Unable to instantiate class (InstExc) " + clazz);
- return null;
- } catch (IllegalAccessException e) {
- Log.w(TAG, "Unable to instantiate class (IllAccExc) " + clazz);
- return null;
- }
- }
-
- /**
- * Inspects all public constructors of the given class, and returns true if one of them is
- * parameterless.
- *
- * @param clazz the class to inspect.
- * @return whether the class has a parameterless constructor.
- */
- static boolean hasParameterlessPublicConstructor(Class<? extends BackgroundTask> clazz) {
- for (Constructor<?> constructor : clazz.getConstructors()) {
- if (constructor.getParameterTypes().length == 0) return true;
- }
- return false;
- }
-
- private BackgroundTaskReflection() {
- // No instantiation.
- }
-}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManager.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManager.java
new file mode 100644
index 00000000000..7a488b0f112
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManager.java
@@ -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.
+
+package org.chromium.components.background_task_scheduler;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+
+/**
+ * An implementation of {@link BackgroundTaskSchedulerDelegate} that uses the system API
+ * {@link AlarmManager} to schedule jobs.
+ */
+public class BackgroundTaskSchedulerAlarmManager implements BackgroundTaskSchedulerDelegate {
+ private static final String TAG = "BkgrdTaskSchedulerAM";
+
+ @VisibleForTesting
+ static PendingIntent createPendingIntentFromTaskId(Context context, int taskId) {
+ Intent intent = new Intent(context, BackgroundTaskBroadcastReceiver.class)
+ .putExtra(BACKGROUND_TASK_ID_KEY, taskId);
+ return PendingIntent.getBroadcast(
+ context, taskId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
+ @Override
+ public boolean schedule(Context context, TaskInfo taskInfo) {
+ ThreadUtils.assertOnUiThread();
+
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ PendingIntent pendingIntent = createPendingIntentFromTaskId(context, taskInfo.getTaskId());
+
+ AlarmManagerVisitor alarmManagerVisitor =
+ new AlarmManagerVisitor(alarmManager, pendingIntent);
+ taskInfo.getTimingInfo().accept(alarmManagerVisitor);
+
+ return true;
+ }
+
+ private static class AlarmManagerVisitor implements TaskInfo.TimingInfoVisitor {
+ private AlarmManager mAlarmManager;
+ private PendingIntent mPendingIntent;
+
+ AlarmManagerVisitor(AlarmManager alarmManager, PendingIntent pendingIntent) {
+ mAlarmManager = alarmManager;
+ mPendingIntent = pendingIntent;
+ }
+
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ throw new RuntimeException("One-off tasks should not be scheduled with "
+ + "AlarmManager.");
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ throw new RuntimeException("Periodic tasks should not be scheduled with "
+ + "AlarmManager.");
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ mAlarmManager.setExactAndAllowWhileIdle(
+ /*type= */ AlarmManager.RTC_WAKEUP, exactInfo.getTriggerAtMs(),
+ mPendingIntent);
+ return;
+ }
+
+ mAlarmManager.setExact(
+ /*type= */ AlarmManager.RTC_WAKEUP, exactInfo.getTriggerAtMs(), mPendingIntent);
+ }
+ }
+
+ @Override
+ public void cancel(Context context, int taskId) {
+ ThreadUtils.assertOnUiThread();
+
+ PendingIntent pendingIntent = createPendingIntentFromTaskId(context, taskId);
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ alarmManager.cancel(pendingIntent);
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
index b7c4d6adc32..cebd96247ae 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
@@ -15,11 +15,17 @@ import org.chromium.base.VisibleForTesting;
*/
interface BackgroundTaskSchedulerDelegate {
@VisibleForTesting
- String BACKGROUND_TASK_CLASS_KEY = "_background_task_class";
+ String BACKGROUND_TASK_ID_KEY = "_background_task_id";
@VisibleForTesting
String BACKGROUND_TASK_EXTRAS_KEY = "_background_task_extras";
@VisibleForTesting
- String BACKGROUND_TASK_DEADLINE_KEY = "_background_task_deadline";
+ String BACKGROUND_TASK_SCHEDULE_TIME_KEY = "_background_task_schedule_time";
+ @VisibleForTesting
+ String BACKGROUND_TASK_END_TIME_KEY = "_background_task_end_time";
+ @VisibleForTesting
+ String BACKGROUND_TASK_INTERVAL_TIME_KEY = "_background_task_interval_time";
+ @VisibleForTesting
+ String BACKGROUND_TASK_FLEX_TIME_KEY = "_background_task_flex_time";
/**
* Schedules a background task. See {@link TaskInfo} for information on what types of tasks that
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java
index 1c6fedc6eef..0756eb34775 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java
@@ -56,4 +56,21 @@ public final class BackgroundTaskSchedulerExternalUma {
public static void reportStartupMode(int startupMode) {
BackgroundTaskSchedulerUma.getInstance().reportStartupMode(startupMode);
}
-} \ No newline at end of file
+
+ /**
+ * Returns an affix identifying a given task type in names of memory histograms specific to that
+ * task type. Adding an affix here causes Memory.BackgroundTask.[affix].* histograms to be
+ * emitted. They still need to be added to histograms.xml.
+ * @param taskId The task type.
+ * @return A string with the affix, without separators added, or null if there is no affix
+ * defined for that task type.
+ */
+ public static String toMemoryHistogramAffixFromTaskId(int taskId) {
+ switch (taskId) {
+ case TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID:
+ return "OfflinePrefetch";
+ default:
+ return null;
+ }
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerFactory.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerFactory.java
index 691338830ba..75a750ac425 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerFactory.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerFactory.java
@@ -13,7 +13,8 @@ import org.chromium.base.VisibleForTesting;
* A factory for {@link BackgroundTaskScheduler} that ensures there is only ever a single instance.
*/
public final class BackgroundTaskSchedulerFactory {
- private static BackgroundTaskScheduler sInstance;
+ private static BackgroundTaskScheduler sBackgroundTaskScheduler;
+ private static BackgroundTaskFactory sBackgroundTaskFactory;
static BackgroundTaskSchedulerDelegate getSchedulerDelegateForSdk(int sdkInt) {
if (sdkInt >= Build.VERSION_CODES.M) {
@@ -29,16 +30,35 @@ public final class BackgroundTaskSchedulerFactory {
*/
public static BackgroundTaskScheduler getScheduler() {
ThreadUtils.assertOnUiThread();
- if (sInstance == null) {
- sInstance = new BackgroundTaskSchedulerImpl(
- getSchedulerDelegateForSdk(Build.VERSION.SDK_INT));
+ if (sBackgroundTaskScheduler == null) {
+ sBackgroundTaskScheduler = new BackgroundTaskSchedulerImpl(
+ getSchedulerDelegateForSdk(Build.VERSION.SDK_INT),
+ new BackgroundTaskSchedulerAlarmManager());
}
- return sInstance;
+ return sBackgroundTaskScheduler;
}
@VisibleForTesting
- public static void setSchedulerForTesting(BackgroundTaskScheduler scheduler) {
- sInstance = scheduler;
+ public static void setSchedulerForTesting(BackgroundTaskScheduler backgroundTaskScheduler) {
+ sBackgroundTaskScheduler = backgroundTaskScheduler;
+ }
+
+ /**
+ * @param taskId id of the scheduled task.
+ * @return instance of the {@link BackgroundTask} that implements the functionality for the
+ * task id.
+ */
+ public static BackgroundTask getBackgroundTaskFromTaskId(int taskId) {
+ assert sBackgroundTaskFactory != null;
+ return sBackgroundTaskFactory.getBackgroundTaskFromTaskId(taskId);
+ }
+
+ /**
+ * @param backgroundTaskFactory specific implementation of {@link BackgroundTaskFactory} of
+ * the caller.
+ */
+ public static void setBackgroundTaskFactory(BackgroundTaskFactory backgroundTaskFactory) {
+ sBackgroundTaskFactory = backgroundTaskFactory;
}
// Do not instantiate.
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
index 571589000e4..74a432bd140 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
@@ -42,28 +42,40 @@ class BackgroundTaskSchedulerGcmNetworkManager implements BackgroundTaskSchedule
sClock = clock;
}
- static BackgroundTask getBackgroundTaskFromTaskParams(@NonNull TaskParams taskParams) {
- String backgroundTaskClassName = getBackgroundTaskClassFromTaskParams(taskParams);
- return BackgroundTaskReflection.getBackgroundTaskFromClassName(backgroundTaskClassName);
- }
-
- private static String getBackgroundTaskClassFromTaskParams(@NonNull TaskParams taskParams) {
- Bundle extras = taskParams.getExtras();
- if (extras == null) return null;
- return extras.getString(BACKGROUND_TASK_CLASS_KEY);
- }
-
- static Long getDeadlineTimeFromTaskParams(@NonNull TaskParams taskParams) {
+ /**
+ * Checks if a task expired, based on the current time of the service.
+ *
+ * @param taskParams parameters sent to the service, which contain the scheduling information
+ * regarding expiration.
+ * @param currentTimeMs the current time of the service.
+ * @return true if the task expired and false otherwise.
+ */
+ static boolean didTaskExpire(TaskParams taskParams, long currentTimeMs) {
Bundle extras = taskParams.getExtras();
- if (extras == null || !extras.containsKey(BACKGROUND_TASK_DEADLINE_KEY)) {
- return null;
+ if (extras == null || !extras.containsKey(BACKGROUND_TASK_SCHEDULE_TIME_KEY)) {
+ return false;
}
- return extras.getLong(BACKGROUND_TASK_DEADLINE_KEY);
- }
- private static long getDeadlineTime(TaskInfo taskInfo) {
- long windowEndTimeMs = taskInfo.getOneOffInfo().getWindowEndTimeMs();
- return sClock.currentTimeMillis() + windowEndTimeMs;
+ long scheduleTimeMs = extras.getLong(BACKGROUND_TASK_SCHEDULE_TIME_KEY);
+ if (extras.containsKey(BACKGROUND_TASK_END_TIME_KEY)) {
+ long endTimeMs =
+ extras.getLong(BackgroundTaskSchedulerDelegate.BACKGROUND_TASK_END_TIME_KEY);
+ return TaskInfo.OneOffInfo.getExpirationStatus(
+ scheduleTimeMs, endTimeMs, currentTimeMs);
+ } else {
+ long intervalTimeMs = extras.getLong(BACKGROUND_TASK_INTERVAL_TIME_KEY);
+
+ // If flex is never set, it is given a default value of 10% of the period time, as
+ // per the GcmNetworkManager behaviour. This default value is set in
+ // https://developers.google.com/android/reference/com/google/android/gms/gcm/PeriodicTask.
+ double defaultFlexAsFractionOfInterval = 0.1f;
+
+ long flexTimeMs = extras.getLong(BACKGROUND_TASK_FLEX_TIME_KEY,
+ /*defaultValue=*/(long) (defaultFlexAsFractionOfInterval * intervalTimeMs));
+
+ return TaskInfo.PeriodicInfo.getExpirationStatus(
+ scheduleTimeMs, intervalTimeMs, flexTimeMs, currentTimeMs);
+ }
}
/**
@@ -95,22 +107,13 @@ class BackgroundTaskSchedulerGcmNetworkManager implements BackgroundTaskSchedule
@VisibleForTesting
static Task createTaskFromTaskInfo(@NonNull TaskInfo taskInfo) {
Bundle taskExtras = new Bundle();
- taskExtras.putString(
- BACKGROUND_TASK_CLASS_KEY, taskInfo.getBackgroundTaskClass().getName());
- if (!taskInfo.isPeriodic() && taskInfo.getOneOffInfo().expiresAfterWindowEndTime()) {
- taskExtras.putLong(BACKGROUND_TASK_DEADLINE_KEY, getDeadlineTime(taskInfo));
- }
taskExtras.putBundle(BACKGROUND_TASK_EXTRAS_KEY, taskInfo.getExtras());
- Task.Builder builder;
- if (taskInfo.isPeriodic()) {
- builder = getPeriodicTaskBuilder(taskInfo.getPeriodicInfo());
- } else {
- builder = getOneOffTaskBuilder(taskInfo.getOneOffInfo());
- }
+ TaskBuilderVisitor taskBuilderVisitor = new TaskBuilderVisitor(taskExtras);
+ taskInfo.getTimingInfo().accept(taskBuilderVisitor);
+ Task.Builder builder = taskBuilderVisitor.getBuilder();
- builder.setExtras(taskExtras)
- .setPersisted(taskInfo.isPersisted())
+ builder.setPersisted(taskInfo.isPersisted())
.setRequiredNetwork(getGcmNetworkManagerNetworkTypeFromTypeFromTaskNetworkType(
taskInfo.getRequiredNetworkType()))
.setRequiresCharging(taskInfo.requiresCharging())
@@ -121,27 +124,65 @@ class BackgroundTaskSchedulerGcmNetworkManager implements BackgroundTaskSchedule
return builder.build();
}
- private static Task.Builder getPeriodicTaskBuilder(TaskInfo.PeriodicInfo periodicInfo) {
- PeriodicTask.Builder builder = new PeriodicTask.Builder();
- builder.setPeriod(TimeUnit.MILLISECONDS.toSeconds(periodicInfo.getIntervalMs()));
- if (periodicInfo.hasFlex()) {
- builder.setFlex(TimeUnit.MILLISECONDS.toSeconds(periodicInfo.getFlexMs()));
+ private static class TaskBuilderVisitor implements TaskInfo.TimingInfoVisitor {
+ private Task.Builder mBuilder;
+ private final Bundle mTaskExtras;
+
+ TaskBuilderVisitor(Bundle taskExtras) {
+ mTaskExtras = taskExtras;
+ }
+
+ // Only valid after a TimingInfo object was visited.
+ Task.Builder getBuilder() {
+ return mBuilder;
}
- return builder;
- }
- private static Task.Builder getOneOffTaskBuilder(TaskInfo.OneOffInfo oneOffInfo) {
- OneoffTask.Builder builder = new OneoffTask.Builder();
- long windowStartSeconds = oneOffInfo.hasWindowStartTimeConstraint()
- ? TimeUnit.MILLISECONDS.toSeconds(oneOffInfo.getWindowStartTimeMs())
- : 0;
- long windowEndTimeMs = oneOffInfo.getWindowEndTimeMs();
- if (oneOffInfo.expiresAfterWindowEndTime()) {
- windowEndTimeMs += DEADLINE_DELTA_MS;
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ if (oneOffInfo.expiresAfterWindowEndTime()) {
+ mTaskExtras.putLong(BACKGROUND_TASK_SCHEDULE_TIME_KEY, sClock.currentTimeMillis());
+ mTaskExtras.putLong(BACKGROUND_TASK_END_TIME_KEY, oneOffInfo.getWindowEndTimeMs());
+ }
+
+ OneoffTask.Builder builder = new OneoffTask.Builder();
+ long windowStartSeconds = oneOffInfo.hasWindowStartTimeConstraint()
+ ? TimeUnit.MILLISECONDS.toSeconds(oneOffInfo.getWindowStartTimeMs())
+ : 0;
+ long windowEndTimeMs = oneOffInfo.getWindowEndTimeMs();
+ if (oneOffInfo.expiresAfterWindowEndTime()) {
+ windowEndTimeMs += DEADLINE_DELTA_MS;
+ }
+ builder.setExecutionWindow(
+ windowStartSeconds, TimeUnit.MILLISECONDS.toSeconds(windowEndTimeMs));
+ builder.setExtras(mTaskExtras);
+ mBuilder = builder;
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ if (periodicInfo.expiresAfterWindowEndTime()) {
+ mTaskExtras.putLong(BACKGROUND_TASK_SCHEDULE_TIME_KEY, sClock.currentTimeMillis());
+ mTaskExtras.putLong(
+ BACKGROUND_TASK_INTERVAL_TIME_KEY, periodicInfo.getIntervalMs());
+ if (periodicInfo.hasFlex()) {
+ mTaskExtras.putLong(BACKGROUND_TASK_FLEX_TIME_KEY, periodicInfo.getFlexMs());
+ }
+ }
+
+ PeriodicTask.Builder builder = new PeriodicTask.Builder();
+ builder.setPeriod(TimeUnit.MILLISECONDS.toSeconds(periodicInfo.getIntervalMs()));
+ if (periodicInfo.hasFlex()) {
+ builder.setFlex(TimeUnit.MILLISECONDS.toSeconds(periodicInfo.getFlexMs()));
+ }
+ builder.setExtras(mTaskExtras);
+ mBuilder = builder;
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ throw new RuntimeException("Exact tasks should not be scheduled with "
+ + "GcmNetworkManager.");
}
- builder.setExecutionWindow(
- windowStartSeconds, TimeUnit.MILLISECONDS.toSeconds(windowEndTimeMs));
- return builder;
}
private static int getGcmNetworkManagerNetworkTypeFromTypeFromTaskNetworkType(
@@ -163,13 +204,6 @@ class BackgroundTaskSchedulerGcmNetworkManager implements BackgroundTaskSchedule
@Override
public boolean schedule(Context context, @NonNull TaskInfo taskInfo) {
ThreadUtils.assertOnUiThread();
- if (!BackgroundTaskReflection.hasParameterlessPublicConstructor(
- taskInfo.getBackgroundTaskClass())) {
- Log.e(TAG,
- "BackgroundTask " + taskInfo.getBackgroundTaskClass()
- + " has no parameterless public constructor.");
- return false;
- }
GcmNetworkManager gcmNetworkManager = getGcmNetworkManager(context);
if (gcmNetworkManager == null) {
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
index 853180ba4b7..59892b96f03 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
@@ -12,6 +12,7 @@ import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
+import java.util.Map;
import java.util.Set;
/**
@@ -25,10 +26,13 @@ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler {
private static final String SWITCH_IGNORE_BACKGROUND_TASKS = "ignore-background-tasks";
private final BackgroundTaskSchedulerDelegate mSchedulerDelegate;
+ private final BackgroundTaskSchedulerDelegate mAlarmManagerDelegate;
/** Constructor only for {@link BackgroundTaskSchedulerFactory} and internal component tests. */
- BackgroundTaskSchedulerImpl(BackgroundTaskSchedulerDelegate schedulerDelegate) {
+ BackgroundTaskSchedulerImpl(BackgroundTaskSchedulerDelegate schedulerDelegate,
+ BackgroundTaskSchedulerDelegate alarmManagerDelegate) {
mSchedulerDelegate = schedulerDelegate;
+ mAlarmManagerDelegate = alarmManagerDelegate;
}
@Override
@@ -42,9 +46,17 @@ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler {
try (TraceEvent te = TraceEvent.scoped(
"BackgroundTaskScheduler.schedule", Integer.toString(taskInfo.getTaskId()))) {
ThreadUtils.assertOnUiThread();
- boolean success = mSchedulerDelegate.schedule(context, taskInfo);
+
+ SchedulingVisitor schedulingVisitor = new SchedulingVisitor(context, taskInfo);
+ taskInfo.getTimingInfo().accept(schedulingVisitor);
+ boolean success = schedulingVisitor.getSuccess();
BackgroundTaskSchedulerUma.getInstance().reportTaskScheduled(
taskInfo.getTaskId(), success);
+
+ // Retain expiration metrics
+ MetricsVisitor metricsVisitor = new MetricsVisitor(taskInfo.getTaskId());
+ taskInfo.getTimingInfo().accept(metricsVisitor);
+
if (success) {
BackgroundTaskSchedulerPrefs.addScheduledTask(taskInfo);
}
@@ -52,14 +64,82 @@ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler {
}
}
+ private class SchedulingVisitor implements TaskInfo.TimingInfoVisitor {
+ private Context mContext;
+ private TaskInfo mTaskInfo;
+ private boolean mSuccess;
+
+ SchedulingVisitor(Context context, TaskInfo taskInfo) {
+ mContext = context;
+ mTaskInfo = taskInfo;
+ }
+
+ // Only valid after a TimingInfo object was visited.
+ boolean getSuccess() {
+ return mSuccess;
+ }
+
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ mSuccess = mSchedulerDelegate.schedule(mContext, mTaskInfo);
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ mSuccess = mSchedulerDelegate.schedule(mContext, mTaskInfo);
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ mSuccess = mAlarmManagerDelegate.schedule(mContext, mTaskInfo);
+ }
+ }
+
+ // TODO(crbug.com/996178): Update the documentation for the expiration feature.
+ private class MetricsVisitor implements TaskInfo.TimingInfoVisitor {
+ private final int mTaskId;
+
+ MetricsVisitor(int taskId) {
+ mTaskId = taskId;
+ }
+
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+ mTaskId, oneOffInfo.expiresAfterWindowEndTime());
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+ mTaskId, periodicInfo.expiresAfterWindowEndTime());
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ BackgroundTaskSchedulerUma.getInstance().reportExactTaskCreated(mTaskId);
+ }
+ }
+
@Override
public void cancel(Context context, int taskId) {
try (TraceEvent te = TraceEvent.scoped(
"BackgroundTaskScheduler.cancel", Integer.toString(taskId))) {
ThreadUtils.assertOnUiThread();
BackgroundTaskSchedulerUma.getInstance().reportTaskCanceled(taskId);
+
+ ScheduledTaskProto.ScheduledTask scheduledTask =
+ BackgroundTaskSchedulerPrefs.getScheduledTask(taskId);
BackgroundTaskSchedulerPrefs.removeScheduledTask(taskId);
- mSchedulerDelegate.cancel(context, taskId);
+
+ if (scheduledTask == null) {
+ Log.e(TAG,
+ "Task cannot be canceled because no data was found in"
+ + "storage or data was invalid");
+ return;
+ }
+
+ selectDelegateAndCancel(context, scheduledTask.getType(), taskId);
}
}
@@ -70,6 +150,11 @@ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler {
int oldSdkInt = BackgroundTaskSchedulerPrefs.getLastSdkVersion();
int newSdkInt = Build.VERSION.SDK_INT;
+ // Update tasks stored in the old format to the proto format at Chrome Startup, if
+ // tasks are found to be stored in the old format. This allows to keep only one
+ // implementation of the storage methods.
+ BackgroundTaskSchedulerPrefs.migrateStoredTasksToProto();
+
if (oldSdkInt != newSdkInt) {
// Save the current SDK version to preferences.
BackgroundTaskSchedulerPrefs.setLastSdkVersion(newSdkInt);
@@ -100,17 +185,24 @@ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler {
public void reschedule(Context context) {
try (TraceEvent te = TraceEvent.scoped("BackgroundTaskScheduler.reschedule")) {
ThreadUtils.assertOnUiThread();
- Set<String> scheduledTasksClassNames = BackgroundTaskSchedulerPrefs.getScheduledTasks();
+ Map<Integer, ScheduledTaskProto.ScheduledTask> scheduledTasks =
+ BackgroundTaskSchedulerPrefs.getScheduledTasks();
BackgroundTaskSchedulerPrefs.removeAllTasks();
- for (String className : scheduledTasksClassNames) {
- BackgroundTask task =
- BackgroundTaskReflection.getBackgroundTaskFromClassName(className);
- if (task == null) {
- Log.w(TAG, "Cannot reschedule task for: " + className);
+ for (Map.Entry<Integer, ScheduledTaskProto.ScheduledTask> entry :
+ scheduledTasks.entrySet()) {
+ final BackgroundTask backgroundTask =
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(entry.getKey());
+ if (backgroundTask == null) {
+ Log.w(TAG,
+ "Cannot reschedule task for task id " + entry.getKey() + ". Could not "
+ + "instantiate BackgroundTask class.");
+ // Cancel task if the BackgroundTask class is not found anymore. We assume this
+ // means that the task has been deprecated.
+ selectDelegateAndCancel(context, entry.getValue().getType(), entry.getKey());
continue;
}
- task.reschedule(context);
+ backgroundTask.reschedule(context);
}
}
}
@@ -118,4 +210,13 @@ class BackgroundTaskSchedulerImpl implements BackgroundTaskScheduler {
private boolean osUpgradeChangesDelegateType(int oldSdkInt, int newSdkInt) {
return oldSdkInt < Build.VERSION_CODES.M && newSdkInt >= Build.VERSION_CODES.M;
}
+
+ private void selectDelegateAndCancel(
+ Context context, ScheduledTaskProto.ScheduledTask.Type taskType, int taskId) {
+ if (taskType == ScheduledTaskProto.ScheduledTask.Type.EXACT) {
+ mAlarmManagerDelegate.cancel(context, taskId);
+ } else {
+ mSchedulerDelegate.cancel(context, taskId);
+ }
+ }
}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
index 68d5299abf1..c881e7e6523 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
@@ -19,6 +19,7 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import java.util.List;
+
/**
* An implementation of {@link BackgroundTaskSchedulerDelegate} that uses the system
* {@link JobScheduler} to schedule jobs.
@@ -27,7 +28,7 @@ import java.util.List;
class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelegate {
private static final String TAG = "BkgrdTaskSchedulerJS";
- /** Delta time to use expiration checks. Used to make checks after the end time. */
+ /** Delta time for expiration checks. Used to make checks after the end time. */
static final long DEADLINE_DELTA_MS = 1000;
/** Clock to use so we can mock time in tests. */
@@ -40,28 +41,50 @@ class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelega
sClock = clock;
}
- static BackgroundTask getBackgroundTaskFromJobParameters(JobParameters jobParameters) {
- String backgroundTaskClassName = getBackgroundTaskClassFromJobParameters(jobParameters);
- return BackgroundTaskReflection.getBackgroundTaskFromClassName(backgroundTaskClassName);
- }
-
- private static String getBackgroundTaskClassFromJobParameters(JobParameters jobParameters) {
- PersistableBundle extras = jobParameters.getExtras();
- if (extras == null) return null;
- return extras.getString(BACKGROUND_TASK_CLASS_KEY);
- }
-
- static Long getDeadlineTimeFromJobParameters(JobParameters jobParameters) {
+ /**
+ * Checks if a task expired, based on the current time of the service.
+ *
+ * @param jobParameters parameters sent to the service, which contain the scheduling information
+ * regarding expiration.
+ * @param currentTimeMs the current time of the service.
+ * @return true if the task expired and false otherwise.
+ */
+ static boolean didTaskExpire(JobParameters jobParameters, long currentTimeMs) {
PersistableBundle extras = jobParameters.getExtras();
- if (extras == null || !extras.containsKey(BACKGROUND_TASK_DEADLINE_KEY)) {
- return null;
+ if (extras == null || !extras.containsKey(BACKGROUND_TASK_SCHEDULE_TIME_KEY)) {
+ return false;
}
- return extras.getLong(BACKGROUND_TASK_DEADLINE_KEY);
- }
- private static long getDeadlineTime(TaskInfo taskInfo) {
- long windowEndTimeMs = taskInfo.getOneOffInfo().getWindowEndTimeMs();
- return sClock.currentTimeMillis() + windowEndTimeMs;
+ long scheduleTimeMs = extras.getLong(BACKGROUND_TASK_SCHEDULE_TIME_KEY);
+ if (extras.containsKey(BACKGROUND_TASK_END_TIME_KEY)) {
+ long endTimeMs = extras.getLong(BACKGROUND_TASK_END_TIME_KEY);
+ return TaskInfo.OneOffInfo.getExpirationStatus(
+ scheduleTimeMs, endTimeMs, currentTimeMs);
+ } else {
+ long intervalTimeMs = extras.getLong(BACKGROUND_TASK_INTERVAL_TIME_KEY);
+ // Based on the JobInfo documentation, attempting to declare a smaller period than
+ // this when scheduling a job will result in a job that is still periodic, but will
+ // run with this effective period.
+ if (intervalTimeMs < JobInfo.getMinPeriodMillis()) {
+ intervalTimeMs = JobInfo.getMinPeriodMillis();
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ // Before Android N, there was no control over when the job will execute within
+ // the given interval. This makes it impossible to check for an expiration time.
+ return false;
+ }
+
+ // Since Android N, there was a minimum of 5 min set for the flex value. This
+ // value is considerably lower from the previous one, since the minimum value
+ // allowed for the interval time is of 15 min:
+ // https://android.googlesource.com/platform/frameworks/base/+/refs/heads/oreo-release/core/java/android/app/job/JobInfo.java.
+ long flexTimeMs = extras.getLong(BACKGROUND_TASK_FLEX_TIME_KEY, /*defaultValue=*/
+ JobInfo.getMinFlexMillis());
+
+ return TaskInfo.PeriodicInfo.getExpirationStatus(
+ scheduleTimeMs, intervalTimeMs, flexTimeMs, currentTimeMs);
+ }
}
/**
@@ -89,11 +112,6 @@ class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelega
@VisibleForTesting
static JobInfo createJobInfoFromTaskInfo(Context context, TaskInfo taskInfo) {
PersistableBundle jobExtras = new PersistableBundle();
- jobExtras.putString(BACKGROUND_TASK_CLASS_KEY, taskInfo.getBackgroundTaskClass().getName());
-
- if (!taskInfo.isPeriodic() && taskInfo.getOneOffInfo().expiresAfterWindowEndTime()) {
- jobExtras.putLong(BACKGROUND_TASK_DEADLINE_KEY, getDeadlineTime(taskInfo));
- }
PersistableBundle persistableBundle = getTaskExtrasAsPersistableBundle(taskInfo);
jobExtras.putPersistableBundle(BACKGROUND_TASK_EXTRAS_KEY, persistableBundle);
@@ -102,42 +120,76 @@ class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelega
new JobInfo
.Builder(taskInfo.getTaskId(),
new ComponentName(context, BackgroundTaskJobService.class))
- .setExtras(jobExtras)
.setPersisted(taskInfo.isPersisted())
.setRequiresCharging(taskInfo.requiresCharging())
.setRequiredNetworkType(getJobInfoNetworkTypeFromTaskNetworkType(
taskInfo.getRequiredNetworkType()));
- if (taskInfo.isPeriodic()) {
- builder = getPeriodicJobInfo(builder, taskInfo);
- } else {
- builder = getOneOffJobInfo(builder, taskInfo);
- }
+ JobInfoBuilderVisitor jobInfoBuilderVisitor = new JobInfoBuilderVisitor(builder, jobExtras);
+ taskInfo.getTimingInfo().accept(jobInfoBuilderVisitor);
+ builder = jobInfoBuilderVisitor.getBuilder();
return builder.build();
}
- private static JobInfo.Builder getOneOffJobInfo(JobInfo.Builder builder, TaskInfo taskInfo) {
- TaskInfo.OneOffInfo oneOffInfo = taskInfo.getOneOffInfo();
- if (oneOffInfo.hasWindowStartTimeConstraint()) {
- builder = builder.setMinimumLatency(oneOffInfo.getWindowStartTimeMs());
+ private static class JobInfoBuilderVisitor implements TaskInfo.TimingInfoVisitor {
+ private final JobInfo.Builder mBuilder;
+ private final PersistableBundle mJobExtras;
+
+ JobInfoBuilderVisitor(JobInfo.Builder builder, PersistableBundle jobExtras) {
+ mBuilder = builder;
+ mJobExtras = jobExtras;
}
- long windowEndTimeMs = oneOffInfo.getWindowEndTimeMs();
- if (oneOffInfo.expiresAfterWindowEndTime()) {
- windowEndTimeMs += DEADLINE_DELTA_MS;
+
+ // Only valid after a TimingInfo object was visited.
+ JobInfo.Builder getBuilder() {
+ return mBuilder;
}
- return builder.setOverrideDeadline(windowEndTimeMs);
- }
- private static JobInfo.Builder getPeriodicJobInfo(JobInfo.Builder builder, TaskInfo taskInfo) {
- TaskInfo.PeriodicInfo periodicInfo = taskInfo.getPeriodicInfo();
- if (periodicInfo.hasFlex()) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- return builder.setPeriodic(periodicInfo.getIntervalMs(), periodicInfo.getFlexMs());
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ if (oneOffInfo.expiresAfterWindowEndTime()) {
+ mJobExtras.putLong(
+ BackgroundTaskSchedulerDelegate.BACKGROUND_TASK_SCHEDULE_TIME_KEY,
+ sClock.currentTimeMillis());
+ mJobExtras.putLong(BackgroundTaskSchedulerDelegate.BACKGROUND_TASK_END_TIME_KEY,
+ oneOffInfo.getWindowEndTimeMs());
+ }
+ mBuilder.setExtras(mJobExtras);
+
+ if (oneOffInfo.hasWindowStartTimeConstraint()) {
+ mBuilder.setMinimumLatency(oneOffInfo.getWindowStartTimeMs());
+ }
+ long windowEndTimeMs = oneOffInfo.getWindowEndTimeMs();
+ if (oneOffInfo.expiresAfterWindowEndTime()) {
+ windowEndTimeMs += DEADLINE_DELTA_MS;
+ }
+ mBuilder.setOverrideDeadline(windowEndTimeMs);
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ if (periodicInfo.expiresAfterWindowEndTime()) {
+ mJobExtras.putLong(BACKGROUND_TASK_SCHEDULE_TIME_KEY, sClock.currentTimeMillis());
+ mJobExtras.putLong(BACKGROUND_TASK_INTERVAL_TIME_KEY, periodicInfo.getIntervalMs());
+ if (periodicInfo.hasFlex()) {
+ mJobExtras.putLong(BACKGROUND_TASK_FLEX_TIME_KEY, periodicInfo.getFlexMs());
+ }
+ }
+ mBuilder.setExtras(mJobExtras);
+
+ if (periodicInfo.hasFlex() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ mBuilder.setPeriodic(periodicInfo.getIntervalMs(), periodicInfo.getFlexMs());
+ return;
}
- return builder.setPeriodic(periodicInfo.getIntervalMs());
+ mBuilder.setPeriodic(periodicInfo.getIntervalMs());
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ throw new RuntimeException("Exact tasks should not be scheduled with "
+ + "JobScheduler.");
}
- return builder.setPeriodic(periodicInfo.getIntervalMs());
}
private static int getJobInfoNetworkTypeFromTaskNetworkType(
@@ -160,12 +212,6 @@ class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelega
@Override
public boolean schedule(Context context, TaskInfo taskInfo) {
ThreadUtils.assertOnUiThread();
- if (!BackgroundTaskReflection.hasParameterlessPublicConstructor(
- taskInfo.getBackgroundTaskClass())) {
- Log.e(TAG, "BackgroundTask " + taskInfo.getBackgroundTaskClass()
- + " has no parameterless public constructor.");
- return false;
- }
JobInfo jobInfo = createJobInfoFromTaskInfo(context, taskInfo);
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java
index 607d5b3c9ad..664d2673de5 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefs.java
@@ -4,13 +4,22 @@
package org.chromium.components.background_task_scheduler;
+import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
+import android.os.Bundle;
+import android.util.Base64;
+
+import com.google.protobuf.InvalidProtocolBufferException;
import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
import org.chromium.base.TraceEvent;
+import org.chromium.base.VisibleForTesting;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -18,14 +27,17 @@ import java.util.Set;
*/
public class BackgroundTaskSchedulerPrefs {
private static final String TAG = "BTSPrefs";
- private static final String KEY_SCHEDULED_TASKS = "bts_scheduled_tasks";
+ @VisibleForTesting
+ static final String KEY_SCHEDULED_TASKS = "bts_scheduled_tasks";
private static final String KEY_LAST_SDK_VERSION = "bts_last_sdk_version";
+ private static final String PREF_PACKAGE = "org.chromium.components.background_task_scheduler";
/**
* Class abstracting conversions between a string kept in shared preferences and actual values
* held there.
*/
- private static class ScheduledTaskPreferenceEntry {
+ @VisibleForTesting
+ static class ScheduledTaskPreferenceEntry {
private static final String ENTRY_SEPARATOR = ":";
private String mBackgroundTaskClass;
private int mTaskId;
@@ -72,31 +84,102 @@ public class BackgroundTaskSchedulerPrefs {
return mBackgroundTaskClass + ENTRY_SEPARATOR + mTaskId;
}
- /** Gets the name of background task class in this entry. */
- public String getBackgroundTaskClass() {
- return mBackgroundTaskClass;
- }
-
/** Gets the ID of the task in this entry. */
public int getTaskId() {
return mTaskId;
}
}
+ static void migrateStoredTasksToProto() {
+ try (TraceEvent te = TraceEvent.scoped(
+ "BackgroundTaskSchedulerPrefs.migrateStoredTasksToProto")) {
+ Set<String> scheduledTasks =
+ ContextUtils.getAppSharedPreferences().getStringSet(KEY_SCHEDULED_TASKS, null);
+
+ if (scheduledTasks == null) return;
+ ContextUtils.getAppSharedPreferences().edit().remove(KEY_SCHEDULED_TASKS).apply();
+
+ SharedPreferences.Editor editor = getSharedPreferences().edit();
+ for (String entry : scheduledTasks) {
+ ScheduledTaskPreferenceEntry parsed =
+ ScheduledTaskPreferenceEntry.parseEntry(entry);
+ if (parsed == null) {
+ Log.w(TAG, "Scheduled task could not be parsed from storage.");
+ continue;
+ }
+ editor.putString(
+ String.valueOf(parsed.getTaskId()), getEmptySerializedScheduledTaskProto());
+ BackgroundTaskSchedulerUma.getInstance().reportMigrationToProto(parsed.getTaskId());
+ }
+ editor.apply();
+ }
+ }
+
+ private static String getEmptySerializedScheduledTaskProto() {
+ ScheduledTaskProto.ScheduledTask scheduledTask =
+ ScheduledTaskProto.ScheduledTask.newBuilder().build();
+ return Base64.encodeToString(scheduledTask.toByteArray(), Base64.DEFAULT);
+ }
+
/** Adds a task to scheduler's preferences, so that it can be rescheduled with OS upgrade. */
public static void addScheduledTask(TaskInfo taskInfo) {
try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.addScheduledTask",
Integer.toString(taskInfo.getTaskId()))) {
- SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
- Set<String> scheduledTasks =
- prefs.getStringSet(KEY_SCHEDULED_TASKS, new HashSet<String>(1));
- String prefsEntry = ScheduledTaskPreferenceEntry.createForTaskInfo(taskInfo).toString();
- if (scheduledTasks.contains(prefsEntry)) return;
+ ScheduledTaskProtoVisitor visitor = new ScheduledTaskProtoVisitor(taskInfo.getExtras());
+ taskInfo.getTimingInfo().accept(visitor);
- // Set returned from getStringSet() should not be modified.
- scheduledTasks = new HashSet<>(scheduledTasks);
- scheduledTasks.add(prefsEntry);
- updateScheduledTasks(prefs, scheduledTasks);
+ getSharedPreferences()
+ .edit()
+ .putString(String.valueOf(taskInfo.getTaskId()),
+ visitor.getSerializedScheduledTask())
+ .apply();
+ }
+ }
+
+ private static class ScheduledTaskProtoVisitor implements TaskInfo.TimingInfoVisitor {
+ private String mSerializedScheduledTask;
+ private final Bundle mExtras;
+
+ ScheduledTaskProtoVisitor(Bundle extras) {
+ mExtras = extras;
+ }
+
+ // Only valid after a TimingInfo object was visited.
+ String getSerializedScheduledTask() {
+ return mSerializedScheduledTask;
+ }
+
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ ScheduledTaskProto.ScheduledTask scheduledTask =
+ ScheduledTaskProto.ScheduledTask.newBuilder()
+ .setType(ScheduledTaskProto.ScheduledTask.Type.ONE_OFF)
+ .build();
+ mSerializedScheduledTask =
+ Base64.encodeToString(scheduledTask.toByteArray(), Base64.DEFAULT);
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ ScheduledTaskProto.ScheduledTask scheduledTask =
+ ScheduledTaskProto.ScheduledTask.newBuilder()
+ .setType(ScheduledTaskProto.ScheduledTask.Type.PERIODIC)
+ .build();
+ mSerializedScheduledTask =
+ Base64.encodeToString(scheduledTask.toByteArray(), Base64.DEFAULT);
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ ScheduledTaskProto.ScheduledTask scheduledTask =
+ ScheduledTaskProto.ScheduledTask.newBuilder()
+ .setType(ScheduledTaskProto.ScheduledTask.Type.EXACT)
+ .setTriggerMs(exactInfo.getTriggerAtMs())
+ .addAllExtras(
+ ExtrasToProtoConverter.convertExtrasToProtoExtras(mExtras))
+ .build();
+ mSerializedScheduledTask =
+ Base64.encodeToString(scheduledTask.toByteArray(), Base64.DEFAULT);
}
}
@@ -104,71 +187,99 @@ public class BackgroundTaskSchedulerPrefs {
public static void removeScheduledTask(int taskId) {
try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.removeScheduledTask",
Integer.toString(taskId))) {
- SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
- Set<String> scheduledTasks = getScheduledTaskEntries(prefs);
+ getSharedPreferences().edit().remove(String.valueOf(taskId)).apply();
+ }
+ }
- String entryToRemove = null;
- for (String entry : scheduledTasks) {
- ScheduledTaskPreferenceEntry parsed =
- ScheduledTaskPreferenceEntry.parseEntry(entry);
- if (parsed != null && parsed.getTaskId() == taskId) {
- entryToRemove = entry;
- break;
+ /** Gets a set of scheduled task IDs. */
+ public static Set<Integer> getScheduledTaskIds() {
+ try (TraceEvent te =
+ TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getScheduledTaskIds")) {
+ Set<Integer> result = new HashSet<>();
+ for (String key : getSharedPreferences().getAll().keySet()) {
+ try {
+ result.add(Integer.valueOf(key));
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Incorrect task id: " + key);
}
}
+ return result;
+ }
+ }
- // Entry matching taskId was not found.
- if (entryToRemove == null) return;
+ /**
+ * Gets information associated with a task id.
+ * @param taskId the task id for which to retrieve data.
+ * @return stored data or null if data not found or invalid.
+ */
+ public static ScheduledTaskProto.ScheduledTask getScheduledTask(int taskId) {
+ String serialized = getSharedPreferences().getString(String.valueOf(taskId), null);
+ if (serialized == null) {
+ Log.e(TAG, "No data found for task id: " + taskId);
+ return null;
+ }
- // Set returned from getStringSet() should not be modified.
- scheduledTasks = new HashSet<>(scheduledTasks);
- scheduledTasks.remove(entryToRemove);
- updateScheduledTasks(prefs, scheduledTasks);
+ try {
+ return ScheduledTaskProto.ScheduledTask.parseFrom(Base64.decode(serialized, 0));
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Invalid protocol buffer: " + e);
+ removeScheduledTask(taskId);
+ return null;
}
}
- /** Gets a set of scheduled task class names. */
- public static Set<String> getScheduledTasks() {
+ /**
+ * Gets all current scheduled task.
+ * @return map of task ids associated with scheduled task protos.
+ */
+ public static Map<Integer, ScheduledTaskProto.ScheduledTask> getScheduledTasks() {
try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getScheduledTasks")) {
- SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
- Set<String> scheduledTask = getScheduledTaskEntries(prefs);
- Set<String> scheduledTasksClassNames = new HashSet<>(scheduledTask.size());
- for (String entry : scheduledTask) {
- ScheduledTaskPreferenceEntry parsed =
- ScheduledTaskPreferenceEntry.parseEntry(entry);
- if (parsed != null) {
- scheduledTasksClassNames.add(parsed.getBackgroundTaskClass());
- }
- }
- return scheduledTasksClassNames;
- }
- }
+ Map<Integer, ScheduledTaskProto.ScheduledTask> result = new HashMap<>();
+ for (Map.Entry<String, ?> entry : getSharedPreferences().getAll().entrySet()) {
+ try {
+ int taskId = Integer.valueOf(entry.getKey());
+ ScheduledTaskProto.ScheduledTask scheduledTask =
+ ScheduledTaskProto.ScheduledTask.parseFrom(
+ Base64.decode(String.valueOf(entry.getValue()), 0));
- /** Gets a set of scheduled task IDs. */
- public static Set<Integer> getScheduledTaskIds() {
- try (TraceEvent te =
- TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getScheduledTaskIds")) {
- SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
- Set<String> scheduledTasks = getScheduledTaskEntries(prefs);
- Set<Integer> scheduledTaskIds = new HashSet<>(scheduledTasks.size());
- for (String entry : scheduledTasks) {
- ScheduledTaskPreferenceEntry parsed =
- ScheduledTaskPreferenceEntry.parseEntry(entry);
- if (parsed != null) {
- scheduledTaskIds.add(parsed.getTaskId());
+ result.put(taskId, scheduledTask);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Incorrect task id: " + entry.getKey());
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Invalid protocol buffer: " + e);
+ removeScheduledTask(Integer.valueOf(entry.getKey()));
}
}
- return scheduledTaskIds;
+ return result;
}
}
- /** Removes all scheduled tasks from shared preferences store. */
+ /**
+ * Removes all scheduled tasks from shared preferences store. Removes tasks from the old
+ * storage format and from the proto format.
+ */
public static void removeAllTasks() {
try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.removeAllTasks")) {
ContextUtils.getAppSharedPreferences().edit().remove(KEY_SCHEDULED_TASKS).apply();
+ getSharedPreferences().edit().clear().apply();
}
}
+ /**
+ * Pre-load shared prefs to avoid being blocked on the disk reads in the future.
+ */
+ public static void warmUpSharedPrefs() {
+ try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.warmUpSharedPrefs")) {
+ getSharedPreferences();
+ }
+ }
+
+ /** Returns the BackgroundTaskScheduler SharedPreferences. */
+ private static SharedPreferences getSharedPreferences() {
+ return ContextUtils.getApplicationContext().getSharedPreferences(
+ PREF_PACKAGE, Context.MODE_PRIVATE);
+ }
+
/** Gets the last SDK version on which this instance ran. Defaults to current SDK version. */
public static int getLastSdkVersion() {
try (TraceEvent te = TraceEvent.scoped("BackgroundTaskSchedulerPrefs.getLastSdkVersion")) {
@@ -188,15 +299,4 @@ public class BackgroundTaskSchedulerPrefs {
.apply();
}
}
-
- private static void updateScheduledTasks(SharedPreferences prefs, Set<String> tasks) {
- SharedPreferences.Editor editor = prefs.edit();
- editor.putStringSet(KEY_SCHEDULED_TASKS, tasks);
- editor.apply();
- }
-
- /** Gets the entries for scheduled tasks from shared preferences. */
- private static Set<String> getScheduledTaskEntries(SharedPreferences prefs) {
- return prefs.getStringSet(KEY_SCHEDULED_TASKS, new HashSet<String>(1));
- }
-}
+} \ No newline at end of file
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
index 11024d94bbc..40d176e9161 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -139,6 +139,28 @@ class BackgroundTaskSchedulerUma {
}
}
+ /** Reports metrics for creating an exact tasks. */
+ public void reportExactTaskCreated(int taskId) {
+ cacheEvent("Android.BackgroundTaskScheduler.ExactTaskCreated",
+ toUmaEnumValueFromTaskId(taskId));
+ }
+
+ /** Reports metrics for task scheduling with the expiration feature activated. */
+ public void reportTaskCreatedAndExpirationState(int taskId, boolean expires) {
+ if (expires) {
+ cacheEvent("Android.BackgroundTaskScheduler.TaskCreated.WithExpiration",
+ toUmaEnumValueFromTaskId(taskId));
+ } else {
+ cacheEvent("Android.BackgroundTaskScheduler.TaskCreated.WithoutExpiration",
+ toUmaEnumValueFromTaskId(taskId));
+ }
+ }
+
+ /** Reports metrics for not starting a task because of expiration. */
+ public void reportTaskExpired(int taskId) {
+ cacheEvent("Android.BackgroundTaskScheduler.TaskExpired", toUmaEnumValueFromTaskId(taskId));
+ }
+
/** Reports metrics for task canceling. */
public void reportTaskCanceled(int taskId) {
cacheEvent(
@@ -155,6 +177,12 @@ class BackgroundTaskSchedulerUma {
cacheEvent("Android.BackgroundTaskScheduler.TaskStopped", toUmaEnumValueFromTaskId(taskId));
}
+ /** Reports metrics for migrating scheduled tasks to Protocol Buffer data format. */
+ public void reportMigrationToProto(int taskId) {
+ cacheEvent("Android.BackgroundTaskScheduler.MigrationToProto",
+ toUmaEnumValueFromTaskId(taskId));
+ }
+
/**
* Reports metrics for when a NativeBackgroundTask loads the native library.
* @param taskId An id from {@link TaskIds}.
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverter.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverter.java
new file mode 100644
index 00000000000..732050057ae
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverter.java
@@ -0,0 +1,214 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.background_task_scheduler;
+
+import android.os.Bundle;
+
+import org.chromium.base.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Converts the extras from {@link Bundle} to the specific proto representation in
+ * {@link ScheduledTaskProto.ScheduledTask}.
+ */
+public final class ExtrasToProtoConverter {
+ private static final String TAG = "BTSExtrasC";
+
+ private ExtrasToProtoConverter() {}
+
+ /**
+ * Converts information stored in a {@link Bundle} to its proto buffer representation to be
+ * stored by {@link BackgroundTaskSchedulerPrefs}. In case null values are passed, they are
+ * stored as null Strings.
+ *
+ * @param extras the extras stored for the {@link BackgroundTask}.
+ * @return a list of proto messages representing each extra.
+ */
+ static List<ScheduledTaskProto.ScheduledTask.ExtraItem> convertExtrasToProtoExtras(
+ Bundle extras) {
+ List<ScheduledTaskProto.ScheduledTask.ExtraItem> protoExtras = new ArrayList<>();
+
+ for (String key : extras.keySet()) {
+ Object obj = extras.get(key);
+
+ ScheduledTaskProto.ScheduledTask.ExtraItem.Type type;
+ List<ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue> values = new ArrayList<>();
+
+ if (obj instanceof Boolean) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE;
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setBooleanValue((Boolean) obj)
+ .build());
+ } else if (obj instanceof boolean[]) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.BOOLEAN_ARRAY;
+ boolean[] bundleValues = extras.getBooleanArray(key);
+ for (int i = 0; i < bundleValues.length; i++) {
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setBooleanValue(bundleValues[i])
+ .build());
+ }
+ } else if (obj instanceof Double) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE;
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setDoubleValue((Double) obj)
+ .build());
+ } else if (obj instanceof double[]) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.DOUBLE_ARRAY;
+ double[] bundleValues = extras.getDoubleArray(key);
+ for (int i = 0; i < bundleValues.length; i++) {
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setDoubleValue(bundleValues[i])
+ .build());
+ }
+ } else if (obj instanceof Integer) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE;
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setIntValue((Integer) obj)
+ .build());
+ } else if (obj instanceof int[]) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.INT_ARRAY;
+ int[] bundleValues = extras.getIntArray(key);
+ for (int i = 0; i < bundleValues.length; i++) {
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setIntValue(bundleValues[i])
+ .build());
+ }
+ } else if (obj instanceof Long) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE;
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setLongValue((Long) obj)
+ .build());
+ } else if (obj instanceof long[]) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.LONG_ARRAY;
+ long[] bundleValues = extras.getLongArray(key);
+ for (int i = 0; i < bundleValues.length; i++) {
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setLongValue(bundleValues[i])
+ .build());
+ }
+ } else if (obj instanceof String) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE;
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setStringValue((String) obj)
+ .build());
+ } else if (obj instanceof String[]) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.STRING_ARRAY;
+ String[] bundleValues = extras.getStringArray(key);
+ for (int i = 0; i < bundleValues.length; i++) {
+ values.add(ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setStringValue(bundleValues[i])
+ .build());
+ }
+ } else if (obj == null) {
+ type = ScheduledTaskProto.ScheduledTask.ExtraItem.Type.NULL;
+ } else {
+ Log.e(TAG, "Value not in the list of supported extras for key " + key + ": " + obj);
+ continue;
+ }
+
+ protoExtras.add(ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(key)
+ .setType(type)
+ .addAllValues(values)
+ .build());
+ }
+
+ return protoExtras;
+ }
+
+ /**
+ * Converts information stored in the proto buffer to a {@link Bundle} to be used by the
+ * {@link BackgroundTask}.
+ *
+ * @param protoExtras list of {@link ScheduledTaskProto.ScheduledTask.ExtraItem} objects that
+ * store the extras for the {@link BackgroundTask}.
+ * @return a {@link Bundle} object with all the extras.
+ */
+ static Bundle convertProtoExtrasToExtras(
+ List<ScheduledTaskProto.ScheduledTask.ExtraItem> protoExtras) {
+ Bundle extras = new Bundle();
+
+ for (ScheduledTaskProto.ScheduledTask.ExtraItem protoExtra : protoExtras) {
+ List<ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue> protoValues =
+ protoExtra.getValuesList();
+
+ switch (protoExtra.getType()) {
+ case SINGLE:
+ switch (protoValues.get(0).getOneofValueCase()) {
+ case BOOLEAN_VALUE:
+ extras.putBoolean(
+ protoExtra.getKey(), protoValues.get(0).getBooleanValue());
+ break;
+ case DOUBLE_VALUE:
+ extras.putDouble(
+ protoExtra.getKey(), protoValues.get(0).getDoubleValue());
+ break;
+ case INT_VALUE:
+ extras.putInt(protoExtra.getKey(), protoValues.get(0).getIntValue());
+ break;
+ case LONG_VALUE:
+ extras.putLong(protoExtra.getKey(), protoValues.get(0).getLongValue());
+ break;
+ case STRING_VALUE:
+ extras.putString(
+ protoExtra.getKey(), protoValues.get(0).getStringValue());
+ break;
+ default:
+ Log.e(TAG,
+ "For key " + protoExtra.getKey() + " no value was set,"
+ + " even though the extra was not null.");
+ return null;
+ }
+ break;
+ case BOOLEAN_ARRAY:
+ boolean[] booleanValues = new boolean[protoValues.size()];
+ for (int i = 0; i < protoValues.size(); i++) {
+ booleanValues[i] = protoValues.get(i).getBooleanValue();
+ }
+ extras.putBooleanArray(protoExtra.getKey(), booleanValues);
+ break;
+ case DOUBLE_ARRAY:
+ double[] doubleValues = new double[protoValues.size()];
+ for (int i = 0; i < protoValues.size(); i++) {
+ doubleValues[i] = protoValues.get(i).getDoubleValue();
+ }
+ extras.putDoubleArray(protoExtra.getKey(), doubleValues);
+ break;
+ case INT_ARRAY:
+ int[] intValues = new int[protoValues.size()];
+ for (int i = 0; i < protoValues.size(); i++) {
+ intValues[i] = protoValues.get(i).getIntValue();
+ }
+ extras.putIntArray(protoExtra.getKey(), intValues);
+ break;
+ case LONG_ARRAY:
+ long[] longValues = new long[protoValues.size()];
+ for (int i = 0; i < protoValues.size(); i++) {
+ longValues[i] = protoValues.get(i).getLongValue();
+ }
+ extras.putLongArray(protoExtra.getKey(), longValues);
+ break;
+ case STRING_ARRAY:
+ String[] stringValues = new String[protoValues.size()];
+ for (int i = 0; i < protoValues.size(); i++) {
+ stringValues[i] = protoValues.get(i).getStringValue();
+ }
+ extras.putStringArray(protoExtra.getKey(), stringValues);
+ break;
+ case NULL:
+ extras.putString(protoExtra.getKey(), null);
+ break;
+ default:
+ Log.e(TAG,
+ "For key " + protoExtra.getKey()
+ + " an invalid type was found: " + protoExtra.getType());
+ }
+ }
+
+ return extras;
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
index 54199d73ee2..8229aae0d26 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
@@ -10,7 +10,9 @@ package org.chromium.components.background_task_scheduler;
*/
public final class TaskIds {
// When adding your job id to the list below, remember to make a corresponding update to the
- // BackgroundTaskSchedulerUma#toUmaEnumValueFromTaskId(int) method.
+ // BackgroundTaskSchedulerUma#toUmaEnumValueFromTaskId(int) method. Also, if the new task id
+ // is related to a BackgroundTask class in //chrome, remember to update
+ // ChromeBackgroundTaskFactory#getBackgroundTaskFromTaskId(int).
public static final int TEST = 0x00008378;
public static final int OMAHA_JOB_ID = 0x00011684;
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java
index fb9ed42b1cf..79fc74c1b92 100644
--- a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java
@@ -9,6 +9,8 @@ import android.os.Bundle;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
+import org.chromium.base.Log;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -17,22 +19,61 @@ import java.lang.annotation.RetentionPolicy;
* parameters, such as whether a special type of network is available.
*/
public class TaskInfo {
+ private static final String TAG = "BkgrdTaskInfo";
+
+ /**
+ * Common interface for all types of task information.
+ */
+ public interface TimingInfo {
+ /**
+ * Receives a {@link TimingInfoVisitor}, which will perform actions on this object.
+ * @param visitor object that will perform actions on this instance.
+ */
+ void accept(TimingInfoVisitor visitor);
+ }
+
+ /**
+ * Common interface for actions over TimingInfo implementations.
+ *
+ * This implements the Visitor design pattern over {@link TimingInfo} objects.
+ * For a guide on how to use it, see the `Performing actions over TimingInfo objects` section
+ * in //components/background_task_scheduler/README.md.
+ */
+ public interface TimingInfoVisitor {
+ /**
+ * Applies actions on a given {@link OneOffInfo}. This affects information regarding
+ * timing for a one-off task.
+ * @param oneOffInfo object to act on.
+ */
+ void visit(OneOffInfo oneOffInfo);
+ /**
+ * Applies actions on a given {@link PeriodicInfo}. This affects information regarding
+ * timing for a periodic task.
+ * @param periodicInfo object to act on.
+ */
+ void visit(PeriodicInfo periodicInfo);
+ /**
+ * Applies actions on a given {@link ExactInfo}. This affects information regarding
+ * timing for an exact task.
+ * @param exactInfo object to act on.
+ */
+ void visit(ExactInfo exactInfo);
+ }
+
/**
* Specifies information regarding one-off tasks.
- * This is part of a {@link TaskInfo} iff the task is NOT a periodic task.
*/
- public static class OneOffInfo {
+ public static class OneOffInfo implements TimingInfo {
private final long mWindowStartTimeMs;
private final long mWindowEndTimeMs;
private final boolean mHasWindowStartTimeConstraint;
private final boolean mExpiresAfterWindowEndTime;
- private OneOffInfo(long windowStartTimeMs, long windowEndTimeMs,
- boolean hasWindowStartTimeConstraint, boolean expiresAfterWindowEndTime) {
- mWindowStartTimeMs = windowStartTimeMs;
- mWindowEndTimeMs = windowEndTimeMs;
- mHasWindowStartTimeConstraint = hasWindowStartTimeConstraint;
- mExpiresAfterWindowEndTime = expiresAfterWindowEndTime;
+ private OneOffInfo(Builder builder) {
+ mWindowStartTimeMs = builder.mWindowStartTimeMs;
+ mWindowEndTimeMs = builder.mWindowEndTimeMs;
+ mHasWindowStartTimeConstraint = builder.mHasWindowStartTimeConstraint;
+ mExpiresAfterWindowEndTime = builder.mExpiresAfterWindowEndTime;
}
/**
@@ -66,27 +107,97 @@ public class TaskInfo {
return mExpiresAfterWindowEndTime;
}
+ /**
+ * Checks if a one-off task expired.
+ * @param scheduleTimeMs the time at which the task was scheduled.
+ * @param endTimeMs the time at which the task was set to expire.
+ * @param currentTimeMs the current time to check for expiration.
+ * @return true if the task expired and false otherwise.
+ */
+ static boolean getExpirationStatus(
+ long scheduleTimeMs, long endTimeMs, long currentTimeMs) {
+ return currentTimeMs >= scheduleTimeMs + endTimeMs;
+ }
+
+ @Override
+ public void accept(TimingInfoVisitor visitor) {
+ visitor.visit(this);
+ }
+
@Override
public String toString() {
- return "{windowStartTimeMs: " + mWindowStartTimeMs
- + ", windowEndTimeMs: " + mWindowEndTimeMs
- + "} - expires at window_end_time: " + mExpiresAfterWindowEndTime;
+ StringBuilder sb = new StringBuilder("{");
+ if (hasWindowStartTimeConstraint()) {
+ sb.append("windowStartTimeMs: ").append(mWindowStartTimeMs).append(", ");
+ }
+ sb.append("windowEndTimeMs: ").append(mWindowEndTimeMs).append(", ");
+ sb.append("expiresAfterWindowEndTime (+flex): ").append(mExpiresAfterWindowEndTime);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * @return a new {@link Builder} object to set the values of the one-off task.
+ */
+ public static Builder create() {
+ return new Builder();
+ }
+
+ /**
+ * A helper builder to provide a way to build {@link OneOffInfo}.
+ *
+ * @see #create()
+ */
+ public static final class Builder {
+ private long mWindowStartTimeMs;
+ private long mWindowEndTimeMs;
+ // By default, a {@link OneOffInfo} doesn't have a set start time. The start time is
+ // considered the time of scheduling the task.
+ private boolean mHasWindowStartTimeConstraint;
+ // By default, a {@link OneOffInfo} doesn't have the expiration feature activated.
+ private boolean mExpiresAfterWindowEndTime;
+
+ public Builder setWindowStartTimeMs(long windowStartTimeMs) {
+ mWindowStartTimeMs = windowStartTimeMs;
+ mHasWindowStartTimeConstraint = true;
+ return this;
+ }
+
+ public Builder setWindowEndTimeMs(long windowEndTimeMs) {
+ mWindowEndTimeMs = windowEndTimeMs;
+ return this;
+ }
+
+ public Builder setExpiresAfterWindowEndTime(boolean expiresAfterWindowEndTime) {
+ mExpiresAfterWindowEndTime = expiresAfterWindowEndTime;
+ return this;
+ }
+
+ /**
+ * Build the {@link OneOffInfo object} specified by this builder.
+ *
+ * @return the {@link OneOffInfo} object.
+ */
+ public OneOffInfo build() {
+ return new OneOffInfo(this);
+ }
}
}
/**
* Specifies information regarding periodic tasks.
- * This is part of a {@link TaskInfo} iff the task is a periodic task.
*/
- public static class PeriodicInfo {
+ public static class PeriodicInfo implements TimingInfo {
private final long mIntervalMs;
private final long mFlexMs;
private final boolean mHasFlex;
+ private final boolean mExpiresAfterWindowEndTime;
- private PeriodicInfo(long intervalMs, long flexMs, boolean hasFlex) {
- mIntervalMs = intervalMs;
- mFlexMs = flexMs;
- mHasFlex = hasFlex;
+ private PeriodicInfo(PeriodicInfo.Builder builder) {
+ mIntervalMs = builder.mIntervalMs;
+ mFlexMs = builder.mFlexMs;
+ mHasFlex = builder.mHasFlex;
+ mExpiresAfterWindowEndTime = builder.mExpiresAfterWindowEndTime;
}
/**
@@ -111,17 +222,166 @@ public class TaskInfo {
return mHasFlex;
}
+ /**
+ * @return whether this periodic task expires after {@link #getIntervalMs()} +
+ * {@link #getFlexMs()}
+ * False by default.
+ */
+ public boolean expiresAfterWindowEndTime() {
+ return mExpiresAfterWindowEndTime;
+ }
+
+ /**
+ * Checks if a periodic task expired.
+ * @param scheduleTimeMs the time at which the task was scheduled.
+ * @param intervalTimeMs the interval at which the periodic task was scheduled.
+ * @param flexTimeMs the flex time of the task, either set by the caller or the default one.
+ * @param currentTimeMs the current time to check for expiration.
+ * @return true if the task expired and false otherwise.
+ */
+ static boolean getExpirationStatus(
+ long scheduleTimeMs, long intervalTimeMs, long flexTimeMs, long currentTimeMs) {
+ // Whether the task is executed during the wanted time window is determined here. The
+ // position of the current time in relation to the time window is calculated here.
+ // This position is compared with the time window margins.
+ // For example, if a task is scheduled at 6am with an interval of 5h and a flex of
+ // 5min, the valid starting times in that day are: 10:55am to 11am, 3:55pm to 4pm and
+ // 8:55pm to 9pm. For 7pm as the current time, the time in the interval window is 3h.
+ // This is not inside a valid starting time, so the task is considered expired.
+ // Similarly, for 8:58pm as the current time, the time in the interval window is 4h
+ // and 58min, which fits in a valid interval window.
+ // In the case of a flex value equal or bigger than the interval value, the task
+ // never expires.
+ long timeSinceScheduledMs = currentTimeMs - scheduleTimeMs;
+ long deltaTimeComparedToWindowMs = timeSinceScheduledMs % intervalTimeMs;
+ return deltaTimeComparedToWindowMs < intervalTimeMs - flexTimeMs
+ && flexTimeMs < intervalTimeMs;
+ }
+
+ @Override
+ public void accept(TimingInfoVisitor visitor) {
+ visitor.visit(this);
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
- sb.append("{");
- sb.append("intervalMs: ").append(mIntervalMs);
+ sb.append("intervalMs: ").append(mIntervalMs).append(", ");
if (mHasFlex) {
- sb.append(", flexMs: ").append(mFlexMs);
+ sb.append(", flexMs: ").append(mFlexMs).append(", ");
}
+ sb.append("expiresAfterWindowEndTime (+flex): ").append(mExpiresAfterWindowEndTime);
sb.append("}");
return sb.toString();
}
+
+ /**
+ * @return a new {@link OneOffInfo.Builder} object to set the values of the one-off task.
+ */
+ public static PeriodicInfo.Builder create() {
+ return new PeriodicInfo.Builder();
+ }
+
+ /**
+ * A helper builder to provide a way to build {@link OneOffInfo}.
+ *
+ * @see #create()
+ */
+ public static final class Builder {
+ private long mIntervalMs;
+ private long mFlexMs;
+ // By default, a {@link PeriodicInfo} doesn't have a specified flex and the default
+ // one will be used in the scheduler.
+ private boolean mHasFlex;
+ // By default, a {@link PeriodicInfo} doesn't have the expiration feature activated.
+ private boolean mExpiresAfterWindowEndTime;
+
+ public Builder setIntervalMs(long intervalMs) {
+ mIntervalMs = intervalMs;
+ return this;
+ }
+
+ public Builder setFlexMs(long flexMs) {
+ mFlexMs = flexMs;
+ mHasFlex = true;
+ return this;
+ }
+
+ public Builder setExpiresAfterWindowEndTime(boolean expiresAfterWindowEndTime) {
+ mExpiresAfterWindowEndTime = expiresAfterWindowEndTime;
+ return this;
+ }
+ /**
+ * Build the {@link PeriodicInfo object} specified by this builder.
+ *
+ * @return the {@link PeriodicInfo} object.
+ */
+ public PeriodicInfo build() {
+ return new PeriodicInfo(this);
+ }
+ }
+ }
+
+ /**
+ * Specifies information regarding exact tasks.
+ */
+ static class ExactInfo implements TimingInfo {
+ private final long mTriggerAtMs;
+
+ private ExactInfo(Builder builder) {
+ mTriggerAtMs = builder.mTriggerAtMs;
+ }
+
+ long getTriggerAtMs() {
+ return mTriggerAtMs;
+ }
+
+ @Override
+ public void accept(TimingInfoVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("{");
+ sb.append("triggerAtMs: ").append(mTriggerAtMs).append("}");
+ return sb.toString();
+ }
+
+ /**
+ * @return a new {@link Builder} object to set the values of the exact task.
+ */
+ static Builder create() {
+ return new Builder();
+ }
+
+ /**
+ * A helper builder to provide a way to build {@link ExactInfo}.
+ *
+ * @see #create()
+ */
+ static final class Builder {
+ private long mTriggerAtMs;
+
+ /**
+ * Sets the exact UTC timestamp at which to schedule the exact task.
+ * @param triggerAtMs the UTC timestamp at which the task should be started.
+ * @return the {@link Builder} for creating the {@link ExactInfo} object.
+ */
+ Builder setTriggerAtMs(long triggerAtMs) {
+ mTriggerAtMs = triggerAtMs;
+ return this;
+ }
+
+ /**
+ * Build the {@link ExactInfo object} specified by this builder.
+ *
+ * @return the {@link ExactInfo} object.
+ */
+ ExactInfo build() {
+ return new ExactInfo(this);
+ }
+ }
}
@IntDef({NetworkType.NONE, NetworkType.ANY, NetworkType.UNMETERED})
@@ -154,12 +414,6 @@ public class TaskInfo {
private final int mTaskId;
/**
- * The {@link BackgroundTask} to invoke when this task is run.
- */
- @NonNull
- private final Class<? extends BackgroundTask> mBackgroundTaskClass;
-
- /**
* The extras to provide to the {@link BackgroundTask} when it is run.
*/
@NonNull
@@ -187,38 +441,18 @@ public class TaskInfo {
private final boolean mUpdateCurrent;
/**
- * Whether this task is periodic.
- */
- private final boolean mIsPeriodic;
-
- /**
- * Task information regarding one-off tasks. Non-null iff {@link #mIsPeriodic} is false.
+ * Task information regarding a type of task.
*/
- private final OneOffInfo mOneOffInfo;
-
- /**
- * Task information regarding periodic tasks. Non-null iff {@link #mIsPeriodic} is true.
- */
- private final PeriodicInfo mPeriodicInfo;
+ private final TimingInfo mTimingInfo;
private TaskInfo(Builder builder) {
mTaskId = builder.mTaskId;
- mBackgroundTaskClass = builder.mBackgroundTaskClass;
mExtras = builder.mExtras == null ? new Bundle() : builder.mExtras;
mRequiredNetworkType = builder.mRequiredNetworkType;
mRequiresCharging = builder.mRequiresCharging;
mIsPersisted = builder.mIsPersisted;
mUpdateCurrent = builder.mUpdateCurrent;
- mIsPeriodic = builder.mIsPeriodic;
- if (mIsPeriodic) {
- mOneOffInfo = null;
- mPeriodicInfo =
- new PeriodicInfo(builder.mIntervalMs, builder.mFlexMs, builder.mHasFlex);
- } else {
- mOneOffInfo = new OneOffInfo(builder.mWindowStartTimeMs, builder.mWindowEndTimeMs,
- builder.mHasWindowStartTimeConstraint, builder.mExpiresAfterWindowEndTime);
- mPeriodicInfo = null;
- }
+ mTimingInfo = builder.mTimingInfo;
}
/**
@@ -233,7 +467,13 @@ public class TaskInfo {
*/
@NonNull
public Class<? extends BackgroundTask> getBackgroundTaskClass() {
- return mBackgroundTaskClass;
+ BackgroundTask backgroundTask =
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTaskId);
+ if (backgroundTask == null) {
+ Log.w(TAG, "Cannot get BackgorundTask class from task id " + mTaskId);
+ return null;
+ }
+ return backgroundTask.getClass();
}
/**
@@ -276,28 +516,38 @@ public class TaskInfo {
/**
* @return Whether or not this task is a periodic task.
*/
+ @Deprecated
public boolean isPeriodic() {
- return mIsPeriodic;
+ return mTimingInfo instanceof PeriodicInfo;
}
/**
- * This is part of a {@link TaskInfo} iff the task is NOT a periodic task, i.e.
- * {@link TaskInfo#isPeriodic()} returns false.
- *
- * @return the specific data that is only available for one-off tasks.
- */
+ * This is part of a {@link TaskInfo} iff the task is a one-off task.
+ *
+ * @return the specific data if it is a one-off tasks and null otherwise.
+ */
+ @Deprecated
public OneOffInfo getOneOffInfo() {
- return mOneOffInfo;
+ if (mTimingInfo instanceof OneOffInfo) return (OneOffInfo) mTimingInfo;
+ return null;
}
/**
- * This is part of a {@link TaskInfo} iff the task is a periodic task, i.e.
- * {@link TaskInfo#isPeriodic()} returns true.
+ * This is part of a {@link TaskInfo} iff the task is a periodic task.
*
- * @return the specific data that is only available for periodic tasks.
+ * @return the specific data that if it is a periodic tasks and null otherwise.
*/
+ @Deprecated
public PeriodicInfo getPeriodicInfo() {
- return mPeriodicInfo;
+ if (mTimingInfo instanceof PeriodicInfo) return (PeriodicInfo) mTimingInfo;
+ return null;
+ }
+
+ /**
+ * @return the specific data based on the type of task.
+ */
+ public TimingInfo getTimingInfo() {
+ return mTimingInfo;
}
@Override
@@ -305,23 +555,29 @@ public class TaskInfo {
StringBuilder sb = new StringBuilder();
sb.append("{");
sb.append("taskId: ").append(mTaskId);
- sb.append(", backgroundTaskClass: ").append(mBackgroundTaskClass);
sb.append(", extras: ").append(mExtras);
sb.append(", requiredNetworkType: ").append(mRequiredNetworkType);
sb.append(", requiresCharging: ").append(mRequiresCharging);
sb.append(", isPersisted: ").append(mIsPersisted);
sb.append(", updateCurrent: ").append(mUpdateCurrent);
- sb.append(", isPeriodic: ").append(mIsPeriodic);
- if (isPeriodic()) {
- sb.append(", periodicInfo: ").append(mPeriodicInfo);
- } else {
- sb.append(", oneOffInfo: ").append(mOneOffInfo);
- }
+ sb.append(", timingInfo: ").append(mTimingInfo);
sb.append("}");
return sb.toString();
}
/**
+ * Creates a task that holds all information necessary to schedule it.
+ *
+ * @param taskId the unique task ID for this task. Should be listed in {@link TaskIds}.
+ * @param timingInfo the task information specific to each type of task.
+ * @return the builder which can be used to continue configuration and {@link Builder#build()}.
+ * @see TaskIds
+ */
+ public static Builder createTask(int taskId, TimingInfo timingInfo) {
+ return new Builder(taskId).setTimingInfo(timingInfo);
+ }
+
+ /**
* Schedule a one-off task to execute within a deadline. If windowEndTimeMs is 0, the task will
* run as soon as possible. For executing a task within a time window, see
* {@link #createOneOffTask(int, Class, long, long)}.
@@ -334,10 +590,16 @@ public class TaskInfo {
* prerequisite conditions are not met.
* @return the builder which can be used to continue configuration and {@link Builder#build()}.
* @see TaskIds
+ *
+ * @deprecated the {@see #createTask(int, Class, TimingInfo)} method should be used instead.
+ * This method requires an additional step for the caller: the creation of the specific
+ * {@link TimingInfo} object with the wanted properties.
*/
+ @Deprecated
public static Builder createOneOffTask(
int taskId, Class<? extends BackgroundTask> backgroundTaskClass, long windowEndTimeMs) {
- return new Builder(taskId, backgroundTaskClass, false).setWindowEndTimeMs(windowEndTimeMs);
+ TimingInfo oneOffInfo = OneOffInfo.create().setWindowEndTimeMs(windowEndTimeMs).build();
+ return new Builder(taskId).setTimingInfo(oneOffInfo);
}
/**
@@ -354,31 +616,20 @@ public class TaskInfo {
* prerequisite conditions are not met.
* @return the builder which can be used to continue configuration and {@link Builder#build()}.
* @see TaskIds
+ *
+ * @deprecated the {@see #createTask(int, Class, TimingInfo)} method should be used instead.
+ * This method requires an additional step for the caller: the creation of the specific
+ * {@link TimingInfo} object with the wanted properties.
*/
+ @Deprecated
public static Builder createOneOffTask(int taskId,
Class<? extends BackgroundTask> backgroundTaskClass, long windowStartTimeMs,
long windowEndTimeMs) {
- return new Builder(taskId, backgroundTaskClass, false)
- .setWindowStartTimeMs(windowStartTimeMs)
- .setWindowEndTimeMs(windowEndTimeMs);
- }
-
- /**
- * Schedule a periodic task that will recur at the specified interval, without the need to
- * be rescheduled. The task will continue to recur until
- * {@link BackgroundTaskScheduler#cancel(Context, int)} is invoked with the task ID from this
- * {@link TaskInfo}.
- *
- * @param taskId the unique task ID for this task. Should be listed in {@link TaskIds}.
- * @param backgroundTaskClass the {@link BackgroundTask} class that will be instantiated for
- * this task.
- * @param intervalMs the interval between occurrences of this task in milliseconds.
- * @return the builder which can be used to continue configuration and {@link Builder#build()}.
- * @see TaskIds
- */
- public static Builder createPeriodicTask(
- int taskId, Class<? extends BackgroundTask> backgroundTaskClass, long intervalMs) {
- return new Builder(taskId, backgroundTaskClass, true).setIntervalMs(intervalMs);
+ TimingInfo oneOffInfo = OneOffInfo.create()
+ .setWindowStartTimeMs(windowStartTimeMs)
+ .setWindowEndTimeMs(windowEndTimeMs)
+ .build();
+ return new Builder(taskId).setTimingInfo(oneOffInfo);
}
/**
@@ -399,89 +650,42 @@ public class TaskInfo {
* length at the end of the period. It is reported in milliseconds.
* @return the builder which can be used to continue configuration and {@link Builder#build()}.
* @see TaskIds
+ *
+ * @deprecated the {@see #createTask(int, Class, TimingInfo)} method should be used instead.
+ * This method requires an additional step for the caller: the creation of the specific
+ * {@link TimingInfo} object with the wanted properties.
*/
+ @Deprecated
public static Builder createPeriodicTask(int taskId,
Class<? extends BackgroundTask> backgroundTaskClass, long intervalMs, long flexMs) {
- return new Builder(taskId, backgroundTaskClass, true)
- .setIntervalAndFlexMs(intervalMs, flexMs);
+ TimingInfo periodicInfo =
+ PeriodicInfo.create().setIntervalMs(intervalMs).setFlexMs(flexMs).build();
+ return new Builder(taskId).setTimingInfo(periodicInfo);
}
/**
* A helper builder to provide a way to build {@link TaskInfo}. To create a {@link Builder}
- * use one of the create* class method on {@link TaskInfo}.
+ * use the createTask method on {@link TaskInfo}.
*
- * @see #createOneOffTask(int, Class, long)
- * @see #createOneOffTask(int, Class, long, long)
- * @see #createPeriodicTask(int, Class, long)
- * @see #createPeriodicTask(int, Class, long, long)
+ * @see @createTask(int, Class, TimingInfo)
*/
public static final class Builder {
private final int mTaskId;
- @NonNull
- private final Class<? extends BackgroundTask> mBackgroundTaskClass;
- private final boolean mIsPeriodic;
+
private Bundle mExtras;
@NetworkType
private int mRequiredNetworkType;
private boolean mRequiresCharging;
private boolean mIsPersisted;
private boolean mUpdateCurrent;
+ private TimingInfo mTimingInfo;
- // Data about one-off tasks.
- private long mWindowStartTimeMs;
- private long mWindowEndTimeMs;
- private boolean mHasWindowStartTimeConstraint;
- private boolean mExpiresAfterWindowEndTime;
-
- // Data about periodic tasks.
- private long mIntervalMs;
- private long mFlexMs;
- private boolean mHasFlex;
-
- Builder(int taskId, @NonNull Class<? extends BackgroundTask> backgroundTaskClass,
- boolean isPeriodic) {
+ Builder(int taskId) {
mTaskId = taskId;
- mBackgroundTaskClass = backgroundTaskClass;
- mIsPeriodic = isPeriodic;
- }
-
- Builder setWindowStartTimeMs(long windowStartTimeMs) {
- assert !mIsPeriodic;
- mWindowStartTimeMs = windowStartTimeMs;
- mHasWindowStartTimeConstraint = true;
- return this;
- }
-
- Builder setWindowEndTimeMs(long windowEndTimeMs) {
- assert !mIsPeriodic;
- mWindowEndTimeMs = windowEndTimeMs;
- return this;
- }
-
- /**
- * Set whether the task should expire if not scheduled until the window end time.
- * This should be called only for One-Off tasks.
- *
- * @param expiresAfterWindowEndTime whether the task expires or not.
- * @return this {@link Builder}.
- */
- Builder setExpiresAfterWindowEndTime(boolean expiresAfterWindowEndTime) {
- assert !mIsPeriodic;
- mExpiresAfterWindowEndTime = expiresAfterWindowEndTime;
- return this;
- }
-
- Builder setIntervalMs(long intervalMs) {
- assert mIsPeriodic;
- mIntervalMs = intervalMs;
- return this;
}
- Builder setIntervalAndFlexMs(long intervalMs, long flexMs) {
- assert mIsPeriodic;
- mIntervalMs = intervalMs;
- mFlexMs = flexMs;
- mHasFlex = true;
+ Builder setTimingInfo(TimingInfo timingInfo) {
+ mTimingInfo = timingInfo;
return this;
}
diff --git a/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/scheduled_task.proto b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/scheduled_task.proto
new file mode 100644
index 00000000000..4020735db04
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/scheduled_task.proto
@@ -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.
+
+syntax = "proto3";
+
+option optimize_for = LITE_RUNTIME;
+
+package background_task_scheduler;
+
+option java_package = "org.chromium.components.background_task_scheduler";
+option java_outer_classname = "ScheduledTaskProto";
+
+message ScheduledTask {
+ enum Type {
+ ONE_OFF = 0;
+ PERIODIC = 1;
+ EXACT = 2;
+ }
+
+ // The type of the scheduled task.
+ Type type = 1;
+
+ // UTC timestamp at which an ExactTask will be triggered by AlarmManager.
+ int64 trigger_ms = 2;
+
+ message ExtraItem {
+ enum Type {
+ SINGLE = 0;
+ BOOLEAN_ARRAY = 1;
+ DOUBLE_ARRAY = 2;
+ INT_ARRAY = 3;
+ LONG_ARRAY = 4;
+ STRING_ARRAY = 5;
+ NULL = 6;
+ }
+
+ message ExtraValue {
+ oneof oneof_value {
+ bool boolean_value = 1;
+ double double_value = 2;
+ int32 int_value = 3;
+ int64 long_value = 4;
+ string string_value = 5;
+ }
+ }
+
+ // The key set for this item in the extras.
+ string key = 1;
+
+ // The type of the value associated with this item.
+ Type type = 2;
+
+ // Value set for this item in the extras. Non-array types will store only
+ // one element in this repeated field. Null types will not store any element
+ // in this field. All the types supported in the extras field can be stored
+ // in the ExtraValue message.
+ repeated ExtraValue values = 3;
+ }
+
+ // Extras for the BackgroundTask, stored for an ExactTask. OneOffTask and
+ // PeriodicTask objects store their extras through their scheduling backend
+ // (JobScheduler and GcmNetworkManager).
+ repeated ExtraItem extras = 3;
+} \ No newline at end of file
diff --git a/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplWithMockTest.java b/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplWithMockTest.java
index 67b8520b447..1183537d9a6 100644
--- a/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplWithMockTest.java
+++ b/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplWithMockTest.java
@@ -4,10 +4,10 @@
package org.chromium.components.background_task_scheduler;
-import android.content.Context;
import android.support.test.filters.SmallTest;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -21,67 +21,65 @@ import java.util.concurrent.TimeUnit;
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class BackgroundTaskSchedulerImplWithMockTest {
- private static class TestBackgroundTask implements BackgroundTask {
- @Override
- public boolean onStartTask(
- Context context, TaskParameters taskParameters, TaskFinishedCallback callback) {
- return false;
- }
-
- @Override
- public boolean onStopTask(Context context, TaskParameters taskParameters) {
- return false;
- }
-
- @Override
- public void reschedule(Context context) {}
- }
-
private static final int TEST_MINUTES = 10;
+ private MockBackgroundTaskSchedulerDelegate mDelegate;
+ private BackgroundTaskScheduler mTaskScheduler;
+
+ @Before
+ public void setUp() {
+ mDelegate = new MockBackgroundTaskSchedulerDelegate();
+ mTaskScheduler = new BackgroundTaskSchedulerImpl(
+ mDelegate, new BackgroundTaskSchedulerAlarmManager());
+ }
+
@Test
@SmallTest
public void testOneOffTaskScheduling() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TimeUnit.MINUTES.toMillis(TEST_MINUTES))
- .build();
-
- MockBackgroundTaskSchedulerDelegate delegate = new MockBackgroundTaskSchedulerDelegate();
- BackgroundTaskScheduler taskScheduler = new BackgroundTaskSchedulerImpl(delegate);
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(TEST_MINUTES))
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
TestThreadUtils.runOnUiThreadBlocking(
- () -> { Assert.assertTrue(taskScheduler.schedule(null, oneOffTask)); });
+ () -> { Assert.assertTrue(mTaskScheduler.schedule(null, oneOffTask)); });
- Assert.assertEquals(oneOffTask, delegate.getScheduledTaskInfo());
- Assert.assertEquals(0, delegate.getCanceledTaskId());
+ Assert.assertEquals(oneOffTask, mDelegate.getScheduledTaskInfo());
+ Assert.assertEquals(0, mDelegate.getCanceledTaskId());
}
@Test
@SmallTest
public void testPeriodicTaskScheduling() {
- TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
- TimeUnit.MINUTES.toMillis(TEST_MINUTES))
- .build();
-
- MockBackgroundTaskSchedulerDelegate delegate = new MockBackgroundTaskSchedulerDelegate();
- BackgroundTaskScheduler taskScheduler = new BackgroundTaskSchedulerImpl(delegate);
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.PeriodicInfo.create()
+ .setIntervalMs(TimeUnit.MINUTES.toMillis(TEST_MINUTES))
+ .build();
+ TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
TestThreadUtils.runOnUiThreadBlocking(
- () -> { Assert.assertTrue(taskScheduler.schedule(null, periodicTask)); });
+ () -> { Assert.assertTrue(mTaskScheduler.schedule(null, periodicTask)); });
- Assert.assertEquals(periodicTask, delegate.getScheduledTaskInfo());
- Assert.assertEquals(0, delegate.getCanceledTaskId());
+ Assert.assertEquals(periodicTask, mDelegate.getScheduledTaskInfo());
+ Assert.assertEquals(0, mDelegate.getCanceledTaskId());
}
@Test
@SmallTest
public void testTaskCanceling() {
- MockBackgroundTaskSchedulerDelegate delegate = new MockBackgroundTaskSchedulerDelegate();
- BackgroundTaskScheduler taskScheduler = new BackgroundTaskSchedulerImpl(delegate);
-
- TestThreadUtils.runOnUiThreadBlocking(() -> { taskScheduler.cancel(null, TaskIds.TEST); });
-
- Assert.assertEquals(null, delegate.getScheduledTaskInfo());
- Assert.assertEquals(TaskIds.TEST, delegate.getCanceledTaskId());
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TimeUnit.MINUTES.toMillis(TEST_MINUTES))
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ Assert.assertTrue(mTaskScheduler.schedule(null, oneOffTask));
+ mTaskScheduler.cancel(null, TaskIds.TEST);
+ });
+
+ Assert.assertEquals(null, mDelegate.getScheduledTaskInfo());
+ Assert.assertEquals(TaskIds.TEST, mDelegate.getCanceledTaskId());
}
} \ No newline at end of file
diff --git a/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java b/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java
index c10a8c67ffc..60b2772dd06 100644
--- a/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java
+++ b/chromium/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java
@@ -46,15 +46,14 @@ public class BackgroundTaskSchedulerJobServiceTest {
public void reschedule(Context context) {}
}
- private static final long CLOCK_TIME = 1415926535000L;
+ private static final long CLOCK_TIME_MS = 1415926535000L;
private static final long TIME_50_MIN_TO_MS = TimeUnit.MINUTES.toMillis(50);
private static final long TIME_100_MIN_TO_MS = TimeUnit.MINUTES.toMillis(100);
private static final long TIME_200_MIN_TO_MS = TimeUnit.MINUTES.toMillis(200);
private static final long END_TIME_WITH_DEADLINE_MS =
TIME_200_MIN_TO_MS + BackgroundTaskSchedulerJobService.DEADLINE_DELTA_MS;
- private static final long DEADLINE_TIME_MS = CLOCK_TIME + TIME_200_MIN_TO_MS;
- private BackgroundTaskSchedulerJobService.Clock mClock = () -> CLOCK_TIME;
+ private BackgroundTaskSchedulerJobService.Clock mClock = () -> CLOCK_TIME_MS;
@Before
public void setUp() {
@@ -64,9 +63,9 @@ public class BackgroundTaskSchedulerJobServiceTest {
@Test
@SmallTest
public void testOneOffTaskWithDeadline() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), oneOffTask);
Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId());
@@ -77,24 +76,30 @@ public class BackgroundTaskSchedulerJobServiceTest {
@Test
@SmallTest
public void testOneOffTaskWithDeadlineAndExpiration() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TIME_200_MIN_TO_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), oneOffTask);
Assert.assertEquals(END_TIME_WITH_DEADLINE_MS, jobInfo.getMaxExecutionDelayMillis());
- Assert.assertEquals(DEADLINE_TIME_MS,
+ Assert.assertEquals(CLOCK_TIME_MS,
+ jobInfo.getExtras().getLong(BackgroundTaskSchedulerGcmNetworkManager
+ .BACKGROUND_TASK_SCHEDULE_TIME_KEY));
+ Assert.assertEquals(TIME_200_MIN_TO_MS,
jobInfo.getExtras().getLong(
- BackgroundTaskSchedulerJobService.BACKGROUND_TASK_DEADLINE_KEY));
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_END_TIME_KEY));
}
@Test
@SmallTest
public void testOneOffTaskWithWindow() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TIME_100_MIN_TO_MS)
+ .setWindowEndTimeMs(TIME_200_MIN_TO_MS)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), oneOffTask);
Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId());
@@ -106,26 +111,31 @@ public class BackgroundTaskSchedulerJobServiceTest {
@Test
@SmallTest
public void testOneOffTaskWithWindowAndExpiration() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TIME_100_MIN_TO_MS)
+ .setWindowEndTimeMs(TIME_200_MIN_TO_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), oneOffTask);
Assert.assertEquals(
oneOffTask.getOneOffInfo().getWindowStartTimeMs(), jobInfo.getMinLatencyMillis());
Assert.assertEquals(END_TIME_WITH_DEADLINE_MS, jobInfo.getMaxExecutionDelayMillis());
- Assert.assertEquals(DEADLINE_TIME_MS,
+ Assert.assertEquals(CLOCK_TIME_MS,
+ jobInfo.getExtras().getLong(BackgroundTaskSchedulerGcmNetworkManager
+ .BACKGROUND_TASK_SCHEDULE_TIME_KEY));
+ Assert.assertEquals(TIME_200_MIN_TO_MS,
jobInfo.getExtras().getLong(
- BackgroundTaskSchedulerJobService.BACKGROUND_TASK_DEADLINE_KEY));
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_END_TIME_KEY));
}
@Test
@SmallTest
public void testPeriodicTaskWithoutFlex() {
- TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.PeriodicInfo.create().setIntervalMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), periodicTask);
Assert.assertEquals(periodicTask.getTaskId(), jobInfo.getId());
@@ -136,9 +146,11 @@ public class BackgroundTaskSchedulerJobServiceTest {
@Test
@SmallTest
public void testPeriodicTaskWithFlex() {
- TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS, TIME_50_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create()
+ .setIntervalMs(TIME_200_MIN_TO_MS)
+ .setFlexMs(TIME_50_MIN_TO_MS)
+ .build();
+ TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), periodicTask);
Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getIntervalMillis());
@@ -154,10 +166,10 @@ public class BackgroundTaskSchedulerJobServiceTest {
taskExtras.putString("foo", "bar");
taskExtras.putBoolean("bools", true);
taskExtras.putLong("longs", 1342543L);
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .setExtras(taskExtras)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo oneOffTask =
+ TaskInfo.createTask(TaskIds.TEST, timingInfo).setExtras(taskExtras).build();
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(), oneOffTask);
Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId());
@@ -173,8 +185,9 @@ public class BackgroundTaskSchedulerJobServiceTest {
@Test
@SmallTest
public void testTaskInfoWithManyConstraints() {
- TaskInfo.Builder taskBuilder = TaskInfo.createOneOffTask(
- TaskIds.TEST, TestBackgroundTask.class, TIME_200_MIN_TO_MS);
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo.Builder taskBuilder = TaskInfo.createTask(TaskIds.TEST, timingInfo);
JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
InstrumentationRegistry.getTargetContext(),
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java
index 7a44dfdb412..c666b915d39 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java
@@ -26,6 +26,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
+import org.chromium.base.ContextUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
@@ -43,13 +44,17 @@ public class BackgroundTaskGcmTaskServiceTest {
@Mock
private BackgroundTaskSchedulerDelegate mDelegate;
@Mock
+ private BackgroundTaskSchedulerDelegate mAlarmManagerDelegate;
+ @Mock
private BackgroundTaskSchedulerUma mBackgroundTaskSchedulerUma;
+ @Mock
+ private BackgroundTaskSchedulerImpl mBackgroundTaskSchedulerImpl;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
BackgroundTaskSchedulerFactory.setSchedulerForTesting(
- new BackgroundTaskSchedulerImpl(mDelegate));
+ new BackgroundTaskSchedulerImpl(mDelegate, mAlarmManagerDelegate));
BackgroundTaskSchedulerUma.setInstanceForTesting(mBackgroundTaskSchedulerUma);
sReturnThroughCallback = false;
sNeedsRescheduling = false;
@@ -76,37 +81,46 @@ public class BackgroundTaskGcmTaskServiceTest {
}
}
- private static class TestBackgroundTaskNoPublicConstructor extends TestBackgroundTask {}
+ public class TestBackgroundTaskWithParamsFactory implements BackgroundTaskFactory {
+ @Override
+ public BackgroundTask getBackgroundTaskFromTaskId(int taskId) {
+ return new TestBackgroundTaskWithParams();
+ }
+ }
@Test
@Feature({"BackgroundTaskScheduler"})
public void testStartsAnytimeWithoutDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
+
Bundle taskExtras = new Bundle();
taskExtras.putString("foo", "bar");
- TaskParams taskParams =
- buildTaskParams(TestBackgroundTaskWithParams.class, taskExtras, null);
+ TaskParams taskParams = buildOneOffTaskParams(TaskIds.TEST, taskExtras, null);
BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_SUCCESS);
+ assertEquals(GcmNetworkManager.RESULT_SUCCESS, taskService.onRunTask(taskParams));
assertNotNull(sLastTask);
TaskParameters parameters = sLastTask.getTaskParameters();
- assertEquals(parameters.getTaskId(), TaskIds.TEST);
- assertEquals(parameters.getExtras().getString("foo"), "bar");
+ assertEquals(TaskIds.TEST, parameters.getTaskId());
+ assertEquals("bar", parameters.getExtras().getString("foo"));
verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testDoesNotStartExactlyAtDeadline() {
- TaskParams taskParams = buildTaskParams(
- TestBackgroundTaskWithParams.class, new Bundle(), sClock.currentTimeMillis());
+ public void testOneOffTaskDoesNotStartExactlyAtDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
+
+ TaskParams taskParams = buildOneOffTaskParams(TaskIds.TEST, new Bundle(), new Long(0));
BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
taskService.setClockForTesting(sClock);
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_FAILURE);
+ assertEquals(GcmNetworkManager.RESULT_FAILURE, taskService.onRunTask(taskParams));
assertNull(sLastTask);
@@ -115,13 +129,16 @@ public class BackgroundTaskGcmTaskServiceTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testDoesNotStartAfterDeadline() {
- TaskParams taskParams = buildTaskParams(
- TestBackgroundTaskWithParams.class, new Bundle(), sZeroClock.currentTimeMillis());
+ public void testOneOffTaskDoesNotStartAfterDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
+
+ TaskParams taskParams =
+ buildOneOffTaskParams(TaskIds.TEST, new Bundle(), -sClock.currentTimeMillis());
BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
taskService.setClockForTesting(sClock);
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_FAILURE);
+ assertEquals(GcmNetworkManager.RESULT_FAILURE, taskService.onRunTask(taskParams));
assertNull(sLastTask);
@@ -130,64 +147,62 @@ public class BackgroundTaskGcmTaskServiceTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testStartsBeforeDeadline() {
- TaskParams taskParams = buildTaskParams(
- TestBackgroundTaskWithParams.class, new Bundle(), sClock.currentTimeMillis());
+ public void testOneOffTaskStartsBeforeDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
+
+ TaskParams taskParams =
+ buildOneOffTaskParams(TaskIds.TEST, new Bundle(), sClock.currentTimeMillis());
BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
taskService.setClockForTesting(sZeroClock);
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_SUCCESS);
+ assertEquals(GcmNetworkManager.RESULT_SUCCESS, taskService.onRunTask(taskParams));
assertNotNull(sLastTask);
TaskParameters parameters = sLastTask.getTaskParameters();
- assertEquals(parameters.getTaskId(), TaskIds.TEST);
+ assertEquals(TaskIds.TEST, parameters.getTaskId());
verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testOnRunTaskMissingConstructor() {
- TaskParams taskParams =
- buildTaskParams(TestBackgroundTaskNoPublicConstructor.class, new Bundle(), null);
-
- BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_FAILURE);
- }
-
- @Test
- @Feature({"BackgroundTaskScheduler"})
- public void testOnRuntaskNeedsReschedulingFromCallback() {
+ public void testOneOffTaskOnRuntaskNeedsReschedulingFromCallback() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
sReturnThroughCallback = true;
sNeedsRescheduling = true;
- TaskParams taskParams =
- buildTaskParams(TestBackgroundTaskWithParams.class, new Bundle(), null);
+ TaskParams taskParams = buildOneOffTaskParams(TaskIds.TEST, new Bundle(), null);
BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_RESCHEDULE);
+ assertEquals(GcmNetworkManager.RESULT_RESCHEDULE, taskService.onRunTask(taskParams));
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testOnRuntaskDontRescheduleFromCallback() {
+ public void testOneOffTaskOnRuntaskDontRescheduleFromCallback() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
+
sReturnThroughCallback = true;
sNeedsRescheduling = false;
- TaskParams taskParams =
- buildTaskParams(TestBackgroundTaskWithParams.class, new Bundle(), null);
+ TaskParams taskParams = buildOneOffTaskParams(TaskIds.TEST, new Bundle(), null);
BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
- assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_SUCCESS);
+ assertEquals(GcmNetworkManager.RESULT_SUCCESS, taskService.onRunTask(taskParams));
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testOnInitializeTasksOnPreM() {
+ public void testOneOffTaskOnInitializeTasksOnPreM() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
+
ReflectionHelpers.setStaticField(
Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.LOLLIPOP);
- TaskInfo task = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TimeUnit.DAYS.toMillis(1))
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1)).build();
+ TaskInfo task = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
BackgroundTaskSchedulerPrefs.addScheduledTask(task);
assertEquals(0, TestBackgroundTask.getRescheduleCalls());
@@ -197,11 +212,13 @@ public class BackgroundTaskGcmTaskServiceTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testOnInitializeTasksOnMPlus() {
+ public void testOneOffTaskOnInitializeTasksOnMPlus() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
+
ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.M);
- TaskInfo task = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TimeUnit.DAYS.toMillis(1))
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1)).build();
+ TaskInfo task = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
BackgroundTaskSchedulerPrefs.addScheduledTask(task);
assertEquals(0, TestBackgroundTask.getRescheduleCalls());
@@ -209,17 +226,123 @@ public class BackgroundTaskGcmTaskServiceTest {
assertEquals(0, TestBackgroundTask.getRescheduleCalls());
}
- private static TaskParams buildTaskParams(Class clazz, Bundle taskExtras, Long deadlineTimeMs) {
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testCancelTaskIfTaskIdNotFound() {
+ BackgroundTaskSchedulerFactory.setSchedulerForTesting(mBackgroundTaskSchedulerImpl);
+
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
+
+ TaskParams taskParams = buildOneOffTaskParams(
+ TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID, new Bundle(), sClock.currentTimeMillis());
+
+ BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+ taskService.setClockForTesting(sZeroClock);
+ assertEquals(GcmNetworkManager.RESULT_FAILURE, taskService.onRunTask(taskParams));
+
+ verify(mBackgroundTaskSchedulerImpl, times(1))
+ .cancel(eq(ContextUtils.getApplicationContext()),
+ eq(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskStartsAnytimeWithoutDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
+
+ TaskParams taskParams =
+ buildPeriodicTaskParams(TaskIds.TEST, new Bundle(), null, null, null);
+
+ BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+ assertEquals(GcmNetworkManager.RESULT_SUCCESS, taskService.onRunTask(taskParams));
+
+ verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskStartsWithinDeadlineTimeFrame() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
+
+ TaskParams taskParams = buildPeriodicTaskParams(TaskIds.TEST, new Bundle(),
+ sClock.currentTimeMillis() - TimeUnit.MINUTES.toMillis(14),
+ TimeUnit.MINUTES.toMillis(15), null);
+
+ BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+ taskService.setClockForTesting(sClock);
+ assertEquals(GcmNetworkManager.RESULT_SUCCESS, taskService.onRunTask(taskParams));
+
+ verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskDoesNotStartExactlyAtDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
+
+ TaskParams taskParams = buildPeriodicTaskParams(TaskIds.TEST, new Bundle(),
+ sClock.currentTimeMillis(), TimeUnit.MINUTES.toMillis(15), null);
+
+ BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+ taskService.setClockForTesting(sClock);
+ assertEquals(GcmNetworkManager.RESULT_FAILURE, taskService.onRunTask(taskParams));
+
+ verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskDoesNotStartAfterDeadline() {
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new TestBackgroundTaskWithParamsFactory());
+
+ TaskParams taskParams = buildPeriodicTaskParams(TaskIds.TEST, new Bundle(),
+ sClock.currentTimeMillis() - TimeUnit.MINUTES.toMillis(3),
+ TimeUnit.MINUTES.toMillis(15), null);
+
+ BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+ taskService.setClockForTesting(sClock);
+ assertEquals(GcmNetworkManager.RESULT_FAILURE, taskService.onRunTask(taskParams));
+
+ verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+ }
+
+ private static TaskParams buildOneOffTaskParams(
+ int taskId, Bundle taskExtras, Long windowEndTimeForDeadlineMs) {
+ Bundle extras = new Bundle();
+ extras.putBundle(
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_EXTRAS_KEY, taskExtras);
+ if (windowEndTimeForDeadlineMs != null) {
+ extras.putLong(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_SCHEDULE_TIME_KEY,
+ sClock.currentTimeMillis());
+ extras.putLong(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_END_TIME_KEY,
+ windowEndTimeForDeadlineMs);
+ }
+
+ return new TaskParams(Integer.toString(taskId), extras);
+ }
+
+ private static TaskParams buildPeriodicTaskParams(int taskId, Bundle taskExtras,
+ Long schedulingTimeMs, Long intervalForDeadlineMs, Long flexForDeadlineMs) {
Bundle extras = new Bundle();
extras.putBundle(
BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_EXTRAS_KEY, taskExtras);
- extras.putString(BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_CLASS_KEY,
- clazz.getName());
- if (deadlineTimeMs != null) {
- extras.putLong(BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_DEADLINE_KEY,
- deadlineTimeMs);
+ if (schedulingTimeMs != null) {
+ extras.putLong(
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_SCHEDULE_TIME_KEY,
+ schedulingTimeMs);
+ extras.putLong(
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_INTERVAL_TIME_KEY,
+ intervalForDeadlineMs);
+ if (flexForDeadlineMs != null) {
+ extras.putLong(
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_FLEX_TIME_KEY,
+ flexForDeadlineMs);
+ }
}
- return new TaskParams(Integer.toString(TaskIds.TEST), extras);
+ return new TaskParams(Integer.toString(taskId), extras);
}
}
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java
index 6bfcfc23eb0..f2524aadcfa 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java
@@ -20,9 +20,12 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
+import org.chromium.base.ContextUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
+import java.util.concurrent.TimeUnit;
+
/** Unit tests for {@link BackgroundTaskJobService}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
@@ -32,21 +35,26 @@ public class BackgroundTaskJobServiceTest {
@Mock
private BackgroundTaskSchedulerDelegate mDelegate;
@Mock
+ private BackgroundTaskSchedulerDelegate mAlarmManagerDelegate;
+ @Mock
private BackgroundTaskSchedulerUma mBackgroundTaskSchedulerUma;
+ @Mock
+ private BackgroundTaskSchedulerImpl mBackgroundTaskSchedulerImpl;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
BackgroundTaskSchedulerFactory.setSchedulerForTesting(
- new BackgroundTaskSchedulerImpl(mDelegate));
+ new BackgroundTaskSchedulerImpl(mDelegate, mAlarmManagerDelegate));
BackgroundTaskSchedulerUma.setInstanceForTesting(mBackgroundTaskSchedulerUma);
TestBackgroundTask.reset();
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testTaskStartsAnytimeWithoutDeadline() {
- JobParameters jobParameters = buildJobParameters(null);
+ public void testOneOffTaskStartsAnytimeWithoutDeadline() {
+ JobParameters jobParameters = buildOneOffJobParameters(TaskIds.TEST, null, null);
BackgroundTaskJobService jobService = new BackgroundTaskJobService();
assertFalse(jobService.onStartJob(jobParameters));
@@ -57,8 +65,9 @@ public class BackgroundTaskJobServiceTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testTaskDoesNotStartExactlyAtDeadline() {
- JobParameters jobParameters = buildJobParameters(sClock.currentTimeMillis());
+ public void testOneOffTaskDoesNotStartExactlyAtDeadline() {
+ JobParameters jobParameters =
+ buildOneOffJobParameters(TaskIds.TEST, sClock.currentTimeMillis(), new Long(0));
BackgroundTaskJobService jobService = new BackgroundTaskJobService();
jobService.setClockForTesting(sClock);
@@ -70,8 +79,9 @@ public class BackgroundTaskJobServiceTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testTaskDoesNotStartAfterDeadline() {
- JobParameters jobParameters = buildJobParameters(sZeroClock.currentTimeMillis());
+ public void testOneOffTaskDoesNotStartAfterDeadline() {
+ JobParameters jobParameters =
+ buildOneOffJobParameters(TaskIds.TEST, sZeroClock.currentTimeMillis(), new Long(0));
BackgroundTaskJobService jobService = new BackgroundTaskJobService();
jobService.setClockForTesting(sClock);
@@ -83,8 +93,9 @@ public class BackgroundTaskJobServiceTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testTaskStartsBeforeDeadline() {
- JobParameters jobParameters = buildJobParameters(sClock.currentTimeMillis());
+ public void testOneOffTaskStartsBeforeDeadline() {
+ JobParameters jobParameters = buildOneOffJobParameters(
+ TaskIds.TEST, sClock.currentTimeMillis(), sClock.currentTimeMillis());
BackgroundTaskJobService jobService = new BackgroundTaskJobService();
jobService.setClockForTesting(sZeroClock);
@@ -94,21 +105,121 @@ public class BackgroundTaskJobServiceTest {
assertEquals(0, TestBackgroundTask.getRescheduleCalls());
}
- private static JobParameters buildJobParameters(Long deadlineTime) {
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testCancelOneOffTaskIfTaskIdNotFound() {
+ BackgroundTaskSchedulerFactory.setSchedulerForTesting(mBackgroundTaskSchedulerImpl);
+
+ JobParameters jobParameters =
+ buildOneOffJobParameters(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID, null, null);
+
+ BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+ jobService.setClockForTesting(sZeroClock);
+ assertFalse(jobService.onStartJob(jobParameters));
+
+ verify(mBackgroundTaskSchedulerImpl, times(1))
+ .cancel(eq(ContextUtils.getApplicationContext()),
+ eq(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskStartsAnytimeWithoutDeadline() {
+ JobParameters jobParameters = buildPeriodicJobParameters(TaskIds.TEST, null, null, null);
+
+ BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+ assertFalse(jobService.onStartJob(jobParameters));
+
+ verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskStartsWithinDeadlineTimeFrame() {
+ JobParameters jobParameters = buildPeriodicJobParameters(TaskIds.TEST,
+ sClock.currentTimeMillis() - TimeUnit.MINUTES.toMillis(13),
+ TimeUnit.MINUTES.toMillis(15), null);
+
+ BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+ jobService.setClockForTesting(sClock);
+ assertFalse(jobService.onStartJob(jobParameters));
+
+ verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskDoesNotStartExactlyAtDeadline() {
+ JobParameters jobParameters = buildPeriodicJobParameters(
+ TaskIds.TEST, sClock.currentTimeMillis(), TimeUnit.MINUTES.toMillis(15), null);
+
+ BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+ jobService.setClockForTesting(sClock);
+ assertFalse(jobService.onStartJob(jobParameters));
+
+ verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskDoesNotStartAfterDeadline() {
+ JobParameters jobParameters = buildPeriodicJobParameters(TaskIds.TEST,
+ sClock.currentTimeMillis() - TimeUnit.MINUTES.toMillis(3),
+ TimeUnit.MINUTES.toMillis(15), null);
+
+ BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+ jobService.setClockForTesting(sClock);
+ assertFalse(jobService.onStartJob(jobParameters));
+
+ verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+ assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+ }
+
+ private static JobParameters buildOneOffJobParameters(
+ int taskId, Long schedulingTimeMs, Long windowEndTimeForDeadlineMs) {
+ PersistableBundle extras = new PersistableBundle();
+ if (windowEndTimeForDeadlineMs != null) {
+ extras.putLong(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_SCHEDULE_TIME_KEY,
+ schedulingTimeMs);
+ extras.putLong(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_END_TIME_KEY,
+ windowEndTimeForDeadlineMs);
+ }
+ PersistableBundle taskExtras = new PersistableBundle();
+ extras.putPersistableBundle(
+ BackgroundTaskSchedulerJobService.BACKGROUND_TASK_EXTRAS_KEY, taskExtras);
+
+ return new JobParameters(null /* callback */, taskId, extras, null /* transientExtras */,
+ null /* clipData */, 0 /* clipGrantFlags */, false /* overrideDeadlineExpired */,
+ null /* triggeredContentUris */, null /* triggeredContentAuthorities */,
+ null /* network */);
+ }
+
+ private static JobParameters buildPeriodicJobParameters(
+ int taskId, Long schedulingTimeMs, Long intervalForDeadlineMs, Long flexForDeadlineMs) {
PersistableBundle extras = new PersistableBundle();
- extras.putString(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_CLASS_KEY,
- TestBackgroundTask.class.getName());
- if (deadlineTime != null) {
+ if (schedulingTimeMs != null) {
+ extras.putLong(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_SCHEDULE_TIME_KEY,
+ schedulingTimeMs);
extras.putLong(
- BackgroundTaskSchedulerJobService.BACKGROUND_TASK_DEADLINE_KEY, deadlineTime);
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_INTERVAL_TIME_KEY,
+ intervalForDeadlineMs);
+ if (flexForDeadlineMs != null) {
+ extras.putLong(
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_FLEX_TIME_KEY,
+ flexForDeadlineMs);
+ }
}
PersistableBundle taskExtras = new PersistableBundle();
extras.putPersistableBundle(
BackgroundTaskSchedulerJobService.BACKGROUND_TASK_EXTRAS_KEY, taskExtras);
- return new JobParameters(null /* callback */, TaskIds.TEST, extras,
- null /* transientExtras */, null /* clipData */, 0 /* clipGrantFlags */,
- false /* overrideDeadlineExpired */, null /* triggeredContentUris */,
- null /* triggeredContentAuthorities */, null /* network */);
+ return new JobParameters(null /* callback */, taskId, extras, null /* transientExtras */,
+ null /* clipData */, 0 /* clipGrantFlags */, false /* overrideDeadlineExpired */,
+ null /* triggeredContentUris */, null /* triggeredContentAuthorities */,
+ null /* network */);
}
} \ No newline at end of file
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManagerTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManagerTest.java
new file mode 100644
index 00000000000..5b2350e7d92
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerAlarmManagerTest.java
@@ -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.
+
+package org.chromium.components.background_task_scheduler;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Feature;
+
+import java.util.concurrent.TimeUnit;
+
+/** Unit tests for {@link BackgroundTaskSchedulerAlarmManager}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class BackgroundTaskSchedulerAlarmManagerTest {
+ private static final long CLOCK_TIME_MS = 1415926535000L;
+ private static final long TIME_200_MIN_TO_MS = TimeUnit.MINUTES.toMillis(200);
+
+ private BackgroundTaskSchedulerGcmNetworkManager.Clock mClock = () -> CLOCK_TIME_MS;
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testExactTaskParameters() {
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.ExactInfo.create()
+ .setTriggerAtMs(mClock.currentTimeMillis() + TIME_200_MIN_TO_MS)
+ .build();
+ TaskInfo exactTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ PendingIntent pendingIntent =
+ BackgroundTaskSchedulerAlarmManager.createPendingIntentFromTaskId(
+ ContextUtils.getApplicationContext(), exactTaskInfo.getTaskId());
+
+ Intent intent =
+ new Intent(
+ ContextUtils.getApplicationContext(), BackgroundTaskBroadcastReceiver.class)
+ .putExtra(BackgroundTaskSchedulerAlarmManager.BACKGROUND_TASK_ID_KEY,
+ TaskIds.TEST);
+ assertEquals(PendingIntent.getBroadcast(ContextUtils.getApplicationContext(), TaskIds.TEST,
+ intent, PendingIntent.FLAG_CANCEL_CURRENT),
+ pendingIntent);
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java
index e177fdd7432..8aa1ead1c96 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java
@@ -39,10 +39,6 @@ import java.util.concurrent.TimeUnit;
@Config(manifest = Config.NONE,
shadows = {ShadowGcmNetworkManager.class, ShadowGoogleApiAvailability.class})
public class BackgroundTaskSchedulerGcmNetworkManagerTest {
- private static class TestBackgroundTaskNoPublicConstructor extends TestBackgroundTask {
- protected TestBackgroundTaskNoPublicConstructor() {}
- }
-
ShadowGcmNetworkManager mGcmNetworkManager;
private static final long CLOCK_TIME_MS = 1415926535000L;
@@ -54,7 +50,6 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
private static final long END_TIME_WITH_DEADLINE_S =
(TIME_200_MIN_TO_MS + BackgroundTaskSchedulerGcmNetworkManager.DEADLINE_DELTA_MS)
/ 1000;
- private static final long DEADLINE_TIME_MS = CLOCK_TIME_MS + TIME_200_MIN_TO_MS;
private BackgroundTaskSchedulerGcmNetworkManager.Clock mClock = () -> CLOCK_TIME_MS;
@@ -65,14 +60,15 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
mGcmNetworkManager = (ShadowGcmNetworkManager) Shadow.extract(
GcmNetworkManager.getInstance(ContextUtils.getApplicationContext()));
BackgroundTaskSchedulerGcmNetworkManager.setClockForTesting(mClock);
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
}
@Test
@Feature({"BackgroundTaskScheduler"})
public void testOneOffTaskWithDeadline() {
- TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
assertTrue(task instanceof OneoffTask);
OneoffTask oneOffTask = (OneoffTask) task;
@@ -84,27 +80,33 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
public void testOneOffTaskWithDeadlineAndExpiration() {
- TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TIME_200_MIN_TO_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
assertTrue(task instanceof OneoffTask);
OneoffTask oneOffTask = (OneoffTask) task;
assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
assertEquals(END_TIME_WITH_DEADLINE_S, oneOffTask.getWindowEnd());
assertEquals(0, oneOffTask.getWindowStart());
- assertEquals(DEADLINE_TIME_MS,
+ assertEquals(CLOCK_TIME_MS,
+ task.getExtras().getLong(BackgroundTaskSchedulerGcmNetworkManager
+ .BACKGROUND_TASK_SCHEDULE_TIME_KEY));
+ assertEquals(TIME_200_MIN_TO_MS,
task.getExtras().getLong(
- BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_DEADLINE_KEY));
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_END_TIME_KEY));
}
@Test
@Feature({"BackgroundTaskScheduler"})
public void testOneOffTaskWithWindow() {
- TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TIME_100_MIN_TO_MS)
+ .setWindowEndTimeMs(TIME_200_MIN_TO_MS)
+ .build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
assertTrue(task instanceof OneoffTask);
OneoffTask oneOffTask = (OneoffTask) task;
@@ -116,27 +118,32 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
public void testOneOffTaskWithWindowAndExpiration() {
- TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TIME_100_MIN_TO_MS)
+ .setWindowEndTimeMs(TIME_200_MIN_TO_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
assertTrue(task instanceof OneoffTask);
OneoffTask oneOffTask = (OneoffTask) task;
assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
assertEquals(END_TIME_WITH_DEADLINE_S, oneOffTask.getWindowEnd());
assertEquals(TIME_100_MIN_TO_S, oneOffTask.getWindowStart());
- assertEquals(DEADLINE_TIME_MS,
+ assertEquals(CLOCK_TIME_MS,
+ task.getExtras().getLong(BackgroundTaskSchedulerGcmNetworkManager
+ .BACKGROUND_TASK_SCHEDULE_TIME_KEY));
+ assertEquals(TIME_200_MIN_TO_MS,
task.getExtras().getLong(
- BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_DEADLINE_KEY));
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_END_TIME_KEY));
}
@Test
@Feature({"BackgroundTaskScheduler"})
public void testPeriodicTaskWithoutFlex() {
- TaskInfo periodicTaskInfo = TaskInfo.createPeriodicTask(TaskIds.TEST,
- TestBackgroundTask.class, TIME_200_MIN_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.PeriodicInfo.create().setIntervalMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo periodicTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
Task task =
BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTaskInfo);
assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
@@ -148,10 +155,11 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
public void testPeriodicTaskWithFlex() {
- TaskInfo periodicTaskInfo =
- TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS, TimeUnit.MINUTES.toMillis(50))
- .build();
+ TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create()
+ .setIntervalMs(TIME_200_MIN_TO_MS)
+ .setFlexMs(TimeUnit.MINUTES.toMillis(50))
+ .build();
+ TaskInfo periodicTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
Task task =
BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTaskInfo);
assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
@@ -163,19 +171,43 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testTaskInfoWithExtras() {
+ public void testOneOffTaskInfoWithExtras() {
Bundle userExtras = new Bundle();
userExtras.putString("foo", "bar");
userExtras.putBoolean("bools", true);
userExtras.putLong("longs", 1342543L);
- TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TIME_200_MIN_TO_MS)
- .setExtras(userExtras)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo oneOffTaskInfo =
+ TaskInfo.createTask(TaskIds.TEST, timingInfo).setExtras(userExtras).build();
Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
assertTrue(task instanceof OneoffTask);
- OneoffTask oneOffTask = (OneoffTask) task;
+
+ Bundle taskExtras = task.getExtras();
+ Bundle bundle = taskExtras.getBundle(
+ BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_EXTRAS_KEY);
+ assertEquals(userExtras.keySet().size(), bundle.keySet().size());
+ assertEquals(userExtras.getString("foo"), bundle.getString("foo"));
+ assertEquals(userExtras.getBoolean("bools"), bundle.getBoolean("bools"));
+ assertEquals(userExtras.getLong("longs"), bundle.getLong("longs"));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicTaskInfoWithExtras() {
+ Bundle userExtras = new Bundle();
+ userExtras.putString("foo", "bar");
+ userExtras.putBoolean("bools", true);
+ userExtras.putLong("longs", 1342543L);
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.PeriodicInfo.create().setIntervalMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo periodicTaskInfo =
+ TaskInfo.createTask(TaskIds.TEST, timingInfo).setExtras(userExtras).build();
+ Task task =
+ BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTaskInfo);
+ assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
+ assertTrue(task instanceof PeriodicTask);
Bundle taskExtras = task.getExtras();
Bundle bundle = taskExtras.getBundle(
@@ -189,8 +221,9 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
public void testTaskInfoWithManyConstraints() {
- TaskInfo.Builder taskBuilder = TaskInfo.createOneOffTask(
- TaskIds.TEST, TestBackgroundTask.class, TIME_200_MIN_TO_MS);
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build();
+ TaskInfo.Builder taskBuilder = TaskInfo.createTask(TaskIds.TEST, timingInfo);
Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(
taskBuilder.setIsPersisted(true).build());
@@ -225,13 +258,9 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
public void testGetBackgroundTaskFromTaskParams() {
- Bundle extras = new Bundle();
- extras.putString(BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_CLASS_KEY,
- TestBackgroundTask.class.getName());
-
- TaskParams params = new TaskParams(Integer.toString(TaskIds.TEST), extras);
- BackgroundTask backgroundTask =
- BackgroundTaskSchedulerGcmNetworkManager.getBackgroundTaskFromTaskParams(params);
+ TaskParams params = new TaskParams(Integer.toString(TaskIds.TEST), new Bundle());
+ BackgroundTask backgroundTask = BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(
+ Integer.valueOf(params.getTag()));
assertNotNull(backgroundTask);
assertTrue(backgroundTask instanceof TestBackgroundTask);
@@ -240,9 +269,9 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature({"BackgroundTaskScheduler"})
public void testSchedule() {
- TaskInfo oneOffTaskInfo =
- TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_24_H_TO_MS).build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
assertNull(mGcmNetworkManager.getScheduledTask());
@@ -265,25 +294,13 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature("BackgroundTaskScheduler")
- public void testScheduleNoPublicConstructor() {
- TaskInfo oneOffTaskInfo =
- TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTaskNoPublicConstructor.class,
- TIME_24_H_TO_MS)
- .build();
-
- assertFalse(new BackgroundTaskSchedulerGcmNetworkManager().schedule(
- ContextUtils.getApplicationContext(), oneOffTaskInfo));
- }
-
- @Test
- @Feature("BackgroundTaskScheduler")
public void testScheduleNoGooglePlayServices() {
Shadows.shadowOf(GoogleApiAvailability.getInstance())
.setIsGooglePlayServicesAvailable(ConnectionResult.SERVICE_MISSING);
- TaskInfo oneOffTaskInfo =
- TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_24_H_TO_MS).build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
assertFalse(new BackgroundTaskSchedulerGcmNetworkManager().schedule(
ContextUtils.getApplicationContext(), oneOffTaskInfo));
@@ -292,9 +309,9 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
@Test
@Feature("BackgroundTaskScheduler")
public void testCancel() {
- TaskInfo oneOffTaskInfo =
- TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_24_H_TO_MS).build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
BackgroundTaskSchedulerDelegate delegate = new BackgroundTaskSchedulerGcmNetworkManager();
@@ -312,9 +329,9 @@ public class BackgroundTaskSchedulerGcmNetworkManagerTest {
Shadows.shadowOf(GoogleApiAvailability.getInstance())
.setIsGooglePlayServicesAvailable(ConnectionResult.SERVICE_MISSING);
- TaskInfo oneOffTaskInfo =
- TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
- .build();
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_24_H_TO_MS).build();
+ TaskInfo oneOffTaskInfo = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
// Ensure there was a previously scheduled task.
mGcmNetworkManager.schedule(
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java
index 1d1e43ad203..00fa3c47e09 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java
@@ -45,16 +45,20 @@ public class BackgroundTaskSchedulerImplTest {
@Mock
private BackgroundTaskSchedulerDelegate mDelegate;
@Mock
+ private BackgroundTaskSchedulerDelegate mAlarmManagerDelegate;
+ @Mock
private BackgroundTaskSchedulerUma mBackgroundTaskSchedulerUma;
private ShadowGcmNetworkManager mGcmNetworkManager;
private TaskInfo mTask;
+ private TaskInfo mExpirationTask;
+ private TaskInfo mExactTask;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
BackgroundTaskSchedulerFactory.setSchedulerForTesting(
- new BackgroundTaskSchedulerImpl(mDelegate));
+ new BackgroundTaskSchedulerImpl(mDelegate, mAlarmManagerDelegate));
BackgroundTaskSchedulerUma.setInstanceForTesting(mBackgroundTaskSchedulerUma);
TestBackgroundTask.reset();
@@ -64,9 +68,20 @@ public class BackgroundTaskSchedulerImplTest {
mGcmNetworkManager = (ShadowGcmNetworkManager) Shadow.extract(
GcmNetworkManager.getInstance(ContextUtils.getApplicationContext()));
- mTask = TaskInfo.createOneOffTask(
- TaskIds.TEST, TestBackgroundTask.class, TimeUnit.DAYS.toMillis(1))
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1)).build();
+ mTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ TaskInfo.TimingInfo expirationTimingInfo =
+ TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1))
+ .setExpiresAfterWindowEndTime(true)
.build();
+ mExpirationTask = TaskInfo.createTask(TaskIds.TEST, expirationTimingInfo).build();
+ TaskInfo.TimingInfo exactTimingInfo =
+ TaskInfo.ExactInfo.create().setTriggerAtMs(1415926535000L).build();
+ mExactTask = TaskInfo.createTask(TaskIds.TEST, exactTimingInfo).build();
+
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
}
@Test
@@ -75,9 +90,40 @@ public class BackgroundTaskSchedulerImplTest {
doReturn(true).when(mDelegate).schedule(eq(RuntimeEnvironment.application), eq(mTask));
BackgroundTaskSchedulerFactory.getScheduler().schedule(
RuntimeEnvironment.application, mTask);
- assertTrue(BackgroundTaskSchedulerPrefs.getScheduledTasks().contains(
- mTask.getBackgroundTaskClass().getName()));
+ assertEquals(mTask.getBackgroundTaskClass(),
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTask.getTaskId())
+ .getClass());
verify(mDelegate, times(1)).schedule(eq(RuntimeEnvironment.application), eq(mTask));
+ verify(mAlarmManagerDelegate, times(0))
+ .schedule(eq(RuntimeEnvironment.application), eq(mExactTask));
+ verify(mBackgroundTaskSchedulerUma, times(1))
+ .reportTaskScheduled(eq(TaskIds.TEST), eq(true));
+ verify(mBackgroundTaskSchedulerUma, times(1))
+ .reportTaskCreatedAndExpirationState(eq(TaskIds.TEST), eq(false));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testScheduleTaskWithExpirationSuccessful() {
+ doReturn(true).when(mDelegate).schedule(
+ eq(RuntimeEnvironment.application), eq(mExpirationTask));
+ BackgroundTaskSchedulerFactory.getScheduler().schedule(
+ RuntimeEnvironment.application, mExpirationTask);
+ verify(mBackgroundTaskSchedulerUma, times(1))
+ .reportTaskCreatedAndExpirationState(eq(TaskIds.TEST), eq(true));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testScheduleExactTaskSuccessful() {
+ doReturn(true)
+ .when(mAlarmManagerDelegate)
+ .schedule(eq(RuntimeEnvironment.application), eq(mExactTask));
+ BackgroundTaskSchedulerFactory.getScheduler().schedule(
+ RuntimeEnvironment.application, mExactTask);
+ verify(mAlarmManagerDelegate, times(1))
+ .schedule(eq(RuntimeEnvironment.application), eq(mExactTask));
+ verify(mDelegate, times(0)).schedule(eq(RuntimeEnvironment.application), eq(mExactTask));
verify(mBackgroundTaskSchedulerUma, times(1))
.reportTaskScheduled(eq(TaskIds.TEST), eq(true));
}
@@ -88,8 +134,9 @@ public class BackgroundTaskSchedulerImplTest {
doReturn(false).when(mDelegate).schedule(eq(RuntimeEnvironment.application), eq(mTask));
BackgroundTaskSchedulerFactory.getScheduler().schedule(
RuntimeEnvironment.application, mTask);
- assertFalse(BackgroundTaskSchedulerPrefs.getScheduledTasks().contains(
- mTask.getBackgroundTaskClass().getName()));
+ assertEquals(mTask.getBackgroundTaskClass(),
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTask.getTaskId())
+ .getClass());
verify(mDelegate, times(1)).schedule(eq(RuntimeEnvironment.application), eq(mTask));
}
@@ -101,9 +148,27 @@ public class BackgroundTaskSchedulerImplTest {
doNothing().when(mDelegate).cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
BackgroundTaskSchedulerFactory.getScheduler().cancel(
RuntimeEnvironment.application, TaskIds.TEST);
- assertFalse(BackgroundTaskSchedulerPrefs.getScheduledTasks().contains(
- mTask.getBackgroundTaskClass().getName()));
+ assertEquals(mTask.getBackgroundTaskClass(),
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTask.getTaskId())
+ .getClass());
verify(mDelegate, times(1)).cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+ verify(mAlarmManagerDelegate, times(0))
+ .cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testCancelExactTask() {
+ BackgroundTaskSchedulerPrefs.addScheduledTask(mExactTask);
+
+ doNothing()
+ .when(mAlarmManagerDelegate)
+ .cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+ BackgroundTaskSchedulerFactory.getScheduler().cancel(
+ RuntimeEnvironment.application, TaskIds.TEST);
+ verify(mDelegate, times(0)).cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+ verify(mAlarmManagerDelegate, times(1))
+ .cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
}
@Test
@@ -112,11 +177,15 @@ public class BackgroundTaskSchedulerImplTest {
BackgroundTaskSchedulerPrefs.addScheduledTask(mTask);
assertEquals(0, TestBackgroundTask.getRescheduleCalls());
- assertFalse(BackgroundTaskSchedulerPrefs.getScheduledTasks().isEmpty());
+ assertFalse(BackgroundTaskSchedulerPrefs.getScheduledTaskIds().isEmpty());
BackgroundTaskSchedulerFactory.getScheduler().reschedule(RuntimeEnvironment.application);
assertEquals(1, TestBackgroundTask.getRescheduleCalls());
- assertTrue(BackgroundTaskSchedulerPrefs.getScheduledTasks().isEmpty());
+ assertTrue(BackgroundTaskSchedulerPrefs.getScheduledTaskIds().isEmpty());
+
+ verify(mDelegate, times(0)).cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
+ verify(mAlarmManagerDelegate, times(0))
+ .cancel(eq(RuntimeEnvironment.application), eq(TaskIds.TEST));
}
@Test
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java
index 780b56cdd6a..52762fa2f81 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java
@@ -6,13 +6,21 @@ package org.chromium.components.background_task_scheduler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import android.content.SharedPreferences;
import android.os.Build;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@@ -21,6 +29,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -28,23 +37,34 @@ import java.util.concurrent.TimeUnit;
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class BackgroundTaskSchedulerPrefsTest {
- /**
- * Dummy extension of the class above to ensure scheduled tasks returned from shared
- * preferences are not missing something.
- */
- static class TestBackgroundTask2 extends TestBackgroundTask {}
+ @Spy
+ private BackgroundTaskSchedulerUma mUmaSpy;
private TaskInfo mTask1;
private TaskInfo mTask2;
+ private class AllValidTestBackgroundTaskFactory implements BackgroundTaskFactory {
+ @Override
+ public BackgroundTask getBackgroundTaskFromTaskId(int taskId) {
+ return new TestBackgroundTask();
+ }
+ }
+
@Before
public void setUp() {
- mTask1 = TaskInfo.createOneOffTask(
- TaskIds.TEST, TestBackgroundTask.class, TimeUnit.DAYS.toMillis(1))
- .build();
- mTask2 = TaskInfo.createOneOffTask(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID,
- TestBackgroundTask2.class, TimeUnit.DAYS.toMillis(1))
- .build();
+ MockitoAnnotations.initMocks(this);
+ BackgroundTaskSchedulerUma.setInstanceForTesting(mUmaSpy);
+ doNothing().when(mUmaSpy).assertNativeIsLoaded();
+
+ TaskInfo.TimingInfo timingInfo1 =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1)).build();
+ mTask1 = TaskInfo.createTask(TaskIds.TEST, timingInfo1).build();
+ TaskInfo.TimingInfo timingInfo2 =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1)).build();
+ mTask2 = TaskInfo.createTask(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID, timingInfo2).build();
+
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(
+ new AllValidTestBackgroundTaskFactory());
}
@Test
@@ -52,36 +72,45 @@ public class BackgroundTaskSchedulerPrefsTest {
public void testAddScheduledTask() {
BackgroundTaskSchedulerPrefs.addScheduledTask(mTask1);
assertEquals("We are expecting a single entry.", 1,
- BackgroundTaskSchedulerPrefs.getScheduledTasks().size());
+ BackgroundTaskSchedulerPrefs.getScheduledTaskIds().size());
BackgroundTaskSchedulerPrefs.addScheduledTask(mTask1);
assertEquals("Still there should be only one entry, as duplicate was added.", 1,
- BackgroundTaskSchedulerPrefs.getScheduledTasks().size());
+ BackgroundTaskSchedulerPrefs.getScheduledTaskIds().size());
BackgroundTaskSchedulerPrefs.addScheduledTask(mTask2);
assertEquals("There should be 2 tasks in shared prefs.", 2,
- BackgroundTaskSchedulerPrefs.getScheduledTasks().size());
- TaskInfo task3 = TaskInfo.createOneOffTask(TaskIds.OMAHA_JOB_ID, TestBackgroundTask2.class,
- TimeUnit.DAYS.toMillis(1))
- .build();
+ BackgroundTaskSchedulerPrefs.getScheduledTaskIds().size());
+
+ ScheduledTaskProto.ScheduledTask scheduledTask1 =
+ BackgroundTaskSchedulerPrefs.getScheduledTask(TaskIds.TEST);
+ assertEquals(ScheduledTaskProto.ScheduledTask.Type.ONE_OFF, scheduledTask1.getType());
+ ScheduledTaskProto.ScheduledTask scheduledTask2 =
+ BackgroundTaskSchedulerPrefs.getScheduledTask(
+ TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID);
+ assertEquals(ScheduledTaskProto.ScheduledTask.Type.ONE_OFF, scheduledTask2.getType());
+
+ Map<Integer, ScheduledTaskProto.ScheduledTask> scheduledTasks =
+ BackgroundTaskSchedulerPrefs.getScheduledTasks();
+ assertEquals("These should be 2 shared prefs.", 2, scheduledTasks.size());
+ assertEquals(scheduledTask1, scheduledTasks.get(TaskIds.TEST));
+ assertEquals(scheduledTask2, scheduledTasks.get(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID));
+
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TimeUnit.DAYS.toMillis(1)).build();
+ TaskInfo task3 = TaskInfo.createTask(TaskIds.OMAHA_JOB_ID, timingInfo).build();
BackgroundTaskSchedulerPrefs.addScheduledTask(task3);
- // Still expecting only 2 classes, because of shared class between 2 tasks.
- assertEquals("There should be 2 tasks in shared prefs.", 2,
- BackgroundTaskSchedulerPrefs.getScheduledTasks().size());
-
- Set<String> scheduledTasks = BackgroundTaskSchedulerPrefs.getScheduledTasks();
- assertTrue("mTask1 class name in scheduled tasks.",
- scheduledTasks.contains(mTask1.getBackgroundTaskClass().getName()));
- assertTrue("mTask2 class name in scheduled tasks.",
- scheduledTasks.contains(mTask2.getBackgroundTaskClass().getName()));
- assertTrue("task3 class name in scheduled tasks.",
- scheduledTasks.contains(task3.getBackgroundTaskClass().getName()));
+ assertEquals("There should be 3 tasks in shared prefs.", 3,
+ BackgroundTaskSchedulerPrefs.getScheduledTaskIds().size());
Set<Integer> taskIds = BackgroundTaskSchedulerPrefs.getScheduledTaskIds();
assertTrue(taskIds.contains(mTask1.getTaskId()));
assertTrue(taskIds.contains(mTask2.getTaskId()));
assertTrue(taskIds.contains(task3.getTaskId()));
+ assertEquals("mTask1 class name in scheduled tasks.", TestBackgroundTask.class,
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTask1.getTaskId())
+ .getClass());
}
@Test
@@ -91,21 +120,31 @@ public class BackgroundTaskSchedulerPrefsTest {
BackgroundTaskSchedulerPrefs.addScheduledTask(mTask2);
BackgroundTaskSchedulerPrefs.removeScheduledTask(mTask1.getTaskId());
assertEquals("We are expecting a single entry.", 1,
- BackgroundTaskSchedulerPrefs.getScheduledTasks().size());
+ BackgroundTaskSchedulerPrefs.getScheduledTaskIds().size());
BackgroundTaskSchedulerPrefs.removeScheduledTask(mTask1.getTaskId());
assertEquals("Removing a task which is not there does not affect the task set.", 1,
- BackgroundTaskSchedulerPrefs.getScheduledTasks().size());
-
- Set<String> scheduledTasks = BackgroundTaskSchedulerPrefs.getScheduledTasks();
- assertFalse("mTask1 class name is not in scheduled tasks.",
- scheduledTasks.contains(mTask1.getBackgroundTaskClass().getName()));
- assertTrue("mTask2 class name in scheduled tasks.",
- scheduledTasks.contains(mTask2.getBackgroundTaskClass().getName()));
+ BackgroundTaskSchedulerPrefs.getScheduledTaskIds().size());
Set<Integer> taskIds = BackgroundTaskSchedulerPrefs.getScheduledTaskIds();
assertFalse(taskIds.contains(mTask1.getTaskId()));
assertTrue(taskIds.contains(mTask2.getTaskId()));
+ assertEquals("mTask1 class name in scheduled tasks.", TestBackgroundTask.class,
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTask1.getTaskId())
+ .getClass());
+
+ ScheduledTaskProto.ScheduledTask scheduledTask1 =
+ BackgroundTaskSchedulerPrefs.getScheduledTask(TaskIds.TEST);
+ assertNull(scheduledTask1);
+ ScheduledTaskProto.ScheduledTask scheduledTask2 =
+ BackgroundTaskSchedulerPrefs.getScheduledTask(
+ TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID);
+ assertEquals(ScheduledTaskProto.ScheduledTask.Type.ONE_OFF, scheduledTask2.getType());
+
+ Map<Integer, ScheduledTaskProto.ScheduledTask> scheduledTasks =
+ BackgroundTaskSchedulerPrefs.getScheduledTasks();
+ assertEquals("We are expecting a single entry.", 1, scheduledTasks.size());
+ assertEquals(scheduledTask2, scheduledTasks.get(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID));
}
@Test
@@ -124,7 +163,6 @@ public class BackgroundTaskSchedulerPrefsTest {
.putStringSet("bts_scheduled_tasks", badEntries)
.apply();
assertTrue(BackgroundTaskSchedulerPrefs.getScheduledTaskIds().isEmpty());
- assertTrue(BackgroundTaskSchedulerPrefs.getScheduledTasks().isEmpty());
}
@Test
@@ -134,8 +172,6 @@ public class BackgroundTaskSchedulerPrefsTest {
BackgroundTaskSchedulerPrefs.addScheduledTask(mTask2);
BackgroundTaskSchedulerPrefs.removeAllTasks();
assertTrue("We are expecting a all tasks to be gone.",
- BackgroundTaskSchedulerPrefs.getScheduledTasks().isEmpty());
- assertTrue("We are expecting a all tasks to be gone.",
BackgroundTaskSchedulerPrefs.getScheduledTaskIds().isEmpty());
}
@@ -150,4 +186,48 @@ public class BackgroundTaskSchedulerPrefsTest {
assertEquals(
Build.VERSION_CODES.LOLLIPOP, BackgroundTaskSchedulerPrefs.getLastSdkVersion());
}
+
+ @Test
+ @Feature("BackgroundTaskScheduler")
+ public void testMigrationToProto() {
+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
+ String prefsEntry1 =
+ BackgroundTaskSchedulerPrefs.ScheduledTaskPreferenceEntry.createForTaskInfo(mTask1)
+ .toString();
+ Set<String> scheduledTasks = prefs.getStringSet(
+ BackgroundTaskSchedulerPrefs.KEY_SCHEDULED_TASKS, new HashSet<String>(1));
+ scheduledTasks.add(prefsEntry1);
+
+ String prefsEntry2 =
+ BackgroundTaskSchedulerPrefs.ScheduledTaskPreferenceEntry.createForTaskInfo(mTask2)
+ .toString();
+ scheduledTasks.add(prefsEntry2);
+
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putStringSet(BackgroundTaskSchedulerPrefs.KEY_SCHEDULED_TASKS, scheduledTasks);
+ editor.apply();
+
+ BackgroundTaskSchedulerPrefs.migrateStoredTasksToProto();
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.MigrationToProto"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.MigrationToProto"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_OFFLINE_PAGES));
+
+ Set<Integer> taskIds = BackgroundTaskSchedulerPrefs.getScheduledTaskIds();
+ assertTrue(taskIds.contains(mTask1.getTaskId()));
+ assertTrue(taskIds.contains(mTask2.getTaskId()));
+ assertEquals("mTask1 class name in scheduled tasks.", TestBackgroundTask.class,
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(mTask1.getTaskId())
+ .getClass());
+
+ BackgroundTaskSchedulerPrefs.migrateStoredTasksToProto();
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.MigrationToProto"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.MigrationToProto"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_OFFLINE_PAGES));
+ }
}
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
index 479decf37c7..3b3684b525e 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
@@ -194,6 +194,48 @@ public class BackgroundTaskSchedulerUmaTest {
@Test
@Feature({"BackgroundTaskScheduler"})
+ public void testReportExactTaskCreated() {
+ doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+ BackgroundTaskSchedulerUma.getInstance().reportExactTaskCreated(TaskIds.TEST);
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.ExactTaskCreated"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testReportTaskScheduledWithExpiration() {
+ doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+ BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+ TaskIds.TEST, /* expires= */ true);
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.TaskCreated.WithExpiration"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testReportTaskScheduledWithoutExpiration() {
+ doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+ BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+ TaskIds.TEST, /* expires= */ false);
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.TaskCreated.WithoutExpiration"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testReportTaskExpired() {
+ doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+ BackgroundTaskSchedulerUma.getInstance().reportTaskExpired(TaskIds.TEST);
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.TaskExpired"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
public void testReportTaskCanceled() {
doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
BackgroundTaskSchedulerUma.getInstance().reportTaskCanceled(
@@ -226,6 +268,16 @@ public class BackgroundTaskSchedulerUmaTest {
@Test
@Feature({"BackgroundTaskScheduler"})
+ public void testReportMigrationToProto() {
+ doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+ BackgroundTaskSchedulerUma.getInstance().reportMigrationToProto(TaskIds.TEST);
+ verify(mUmaSpy, times(1))
+ .cacheEvent(eq("Android.BackgroundTaskScheduler.MigrationToProto"),
+ eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+ }
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
public void testReportTaskStartedNativeFullBrowser() {
doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
BackgroundTaskSchedulerExternalUma.reportTaskStartedNative(
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverterTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverterTest.java
new file mode 100644
index 00000000000..dc009d47917
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/ExtrasToProtoConverterTest.java
@@ -0,0 +1,244 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.background_task_scheduler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Bundle;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Feature;
+
+import java.util.List;
+
+/** Unit tests for {@link ExtrasToProtoConverter}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class ExtrasToProtoConverterTest {
+ private static final String BOOLEAN_KEY = "B1";
+ private static final boolean BOOLEAN_VALUE = true;
+ private static final String BOOLEAN_ARRAY_KEY = "B2";
+ private static final boolean[] BOOLEAN_ARRAY_VALUE = {false, true, false};
+
+ private static final String DOUBLE_KEY = "D1";
+ private static final double DOUBLE_VALUE = 43.2;
+ private static final String DOUBLE_ARRAY_KEY = "D2";
+ private static final double[] DOUBLE_ARRAY_VALUE = {1.2, 5.678};
+
+ private static final String INT_KEY = "I1";
+ private static final int INT_VALUE = 10;
+ private static final String INT_ARRAY_KEY = "I2";
+ private static final int[] INT_ARRAY_VALUE = {3, 87, 987};
+
+ private static final String LONG_KEY = "L1";
+ private static final long LONG_VALUE = 47244424241L;
+ private static final String LONG_ARRAY_KEY = "L2";
+ private static final long[] LONG_ARRAY_VALUE = {8744423435L, 748244111123L};
+
+ private static final String STRING_KEY = "S1";
+ private static final String STRING_VALUE = "Extras";
+ private static final String STRING_ARRAY_KEY = "S2";
+ private static final String[] STRING_ARRAY_VALUE = {"ExtrasArray"};
+
+ private static final String NULL_ARRAY_KEY = "N1";
+ private static final String NULL_STRING_KEY = "N2";
+
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testBundleToProtoAndBack() {
+ // Construct Bundle object to store extras.
+ Bundle extras = new Bundle();
+
+ extras.putBoolean(BOOLEAN_KEY, BOOLEAN_VALUE);
+ extras.putBooleanArray(BOOLEAN_ARRAY_KEY, BOOLEAN_ARRAY_VALUE);
+
+ extras.putDouble(DOUBLE_KEY, DOUBLE_VALUE);
+ extras.putDoubleArray(DOUBLE_ARRAY_KEY, DOUBLE_ARRAY_VALUE);
+
+ extras.putInt(INT_KEY, INT_VALUE);
+ extras.putIntArray(INT_ARRAY_KEY, INT_ARRAY_VALUE);
+
+ extras.putLong(LONG_KEY, LONG_VALUE);
+ extras.putLongArray(LONG_ARRAY_KEY, LONG_ARRAY_VALUE);
+
+ extras.putString(STRING_KEY, STRING_VALUE);
+ extras.putStringArray(STRING_ARRAY_KEY, STRING_ARRAY_VALUE);
+
+ extras.putIntArray(NULL_ARRAY_KEY, null);
+ extras.putString(NULL_STRING_KEY, null);
+
+ // Convert extras to the proto representation.
+ List<ScheduledTaskProto.ScheduledTask.ExtraItem> protoExtras =
+ ExtrasToProtoConverter.convertExtrasToProtoExtras(extras);
+
+ // Check conversion.
+ checkExtrasToProtoConversion(protoExtras);
+
+ // Convert proto representation to extras.
+ Bundle convertedExtras = ExtrasToProtoConverter.convertProtoExtrasToExtras(protoExtras);
+
+ // Check conversion.
+ checkProtoToExtrasConversion(extras, convertedExtras);
+ }
+
+ static void checkExtrasToProtoConversion(
+ List<ScheduledTaskProto.ScheduledTask.ExtraItem> protoExtras) {
+ assertEquals(12, protoExtras.size());
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(BOOLEAN_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setBooleanValue(BOOLEAN_VALUE))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(BOOLEAN_ARRAY_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.BOOLEAN_ARRAY)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setBooleanValue(BOOLEAN_ARRAY_VALUE[0]))
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setBooleanValue(BOOLEAN_ARRAY_VALUE[1]))
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setBooleanValue(BOOLEAN_ARRAY_VALUE[2]))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(DOUBLE_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setDoubleValue(DOUBLE_VALUE))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(DOUBLE_ARRAY_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.DOUBLE_ARRAY)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setDoubleValue(DOUBLE_ARRAY_VALUE[0]))
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setDoubleValue(DOUBLE_ARRAY_VALUE[1]))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(INT_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setIntValue(INT_VALUE))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(INT_ARRAY_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.INT_ARRAY)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setIntValue(INT_ARRAY_VALUE[0]))
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setIntValue(INT_ARRAY_VALUE[1]))
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setIntValue(INT_ARRAY_VALUE[2]))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(LONG_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setLongValue(LONG_VALUE))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(LONG_ARRAY_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.LONG_ARRAY)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setLongValue(LONG_ARRAY_VALUE[0]))
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setLongValue(LONG_ARRAY_VALUE[1]))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(STRING_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.SINGLE)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setStringValue(STRING_VALUE))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(STRING_ARRAY_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.STRING_ARRAY)
+ .addValues(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.ExtraValue.newBuilder()
+ .setStringValue(STRING_ARRAY_VALUE[0]))
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(NULL_ARRAY_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.NULL)
+ .build()));
+ assertTrue(protoExtras.contains(
+ ScheduledTaskProto.ScheduledTask.ExtraItem.newBuilder()
+ .setKey(NULL_STRING_KEY)
+ .setType(ScheduledTaskProto.ScheduledTask.ExtraItem.Type.NULL)
+ .build()));
+ }
+
+ static void checkProtoToExtrasConversion(Bundle expectedExtras, Bundle actualExtras) {
+ assertEquals(expectedExtras.keySet().size(), actualExtras.keySet().size());
+ assertEquals(expectedExtras.getBoolean(BOOLEAN_KEY), actualExtras.getBoolean(BOOLEAN_KEY));
+ boolean[] expectedB = expectedExtras.getBooleanArray(BOOLEAN_ARRAY_KEY);
+ boolean[] actualB = actualExtras.getBooleanArray(BOOLEAN_ARRAY_KEY);
+ assertEquals(expectedB.length, actualB.length);
+ assertEquals(expectedB[0], actualB[0]);
+ assertEquals(expectedB[1], actualB[1]);
+ assertEquals(expectedB[2], actualB[2]);
+ double delta = 0.0001;
+ assertEquals(
+ expectedExtras.getDouble(DOUBLE_KEY), actualExtras.getDouble(DOUBLE_KEY), delta);
+ double[] expectedD = expectedExtras.getDoubleArray(DOUBLE_ARRAY_KEY);
+ double[] actualD = actualExtras.getDoubleArray(DOUBLE_ARRAY_KEY);
+ assertEquals(expectedD.length, actualD.length);
+ assertEquals(expectedD[0], actualD[0], delta);
+ assertEquals(expectedD[1], actualD[1], delta);
+ assertEquals(expectedExtras.getInt(INT_KEY), actualExtras.getInt(INT_KEY));
+ int[] expectedI = expectedExtras.getIntArray(INT_ARRAY_KEY);
+ int[] actualI = actualExtras.getIntArray(INT_ARRAY_KEY);
+ assertEquals(expectedI.length, actualI.length);
+ assertEquals(expectedI[0], actualI[0]);
+ assertEquals(expectedI[1], actualI[1]);
+ assertEquals(expectedI[2], actualI[2]);
+ assertEquals(expectedExtras.getLong(LONG_KEY), actualExtras.getLong(LONG_KEY));
+ long[] expectedL = expectedExtras.getLongArray(LONG_ARRAY_KEY);
+ long[] actualL = actualExtras.getLongArray(LONG_ARRAY_KEY);
+ assertEquals(expectedL.length, actualL.length);
+ assertEquals(expectedL[0], actualL[0]);
+ assertEquals(expectedL[1], actualL[1]);
+ assertEquals(expectedExtras.getString(STRING_KEY), actualExtras.getString(STRING_KEY));
+ String[] expectedS = expectedExtras.getStringArray(STRING_ARRAY_KEY);
+ String[] actualS = actualExtras.getStringArray(STRING_ARRAY_KEY);
+ assertEquals(expectedS.length, actualS.length);
+ assertEquals(expectedS[0], actualS[0]);
+ assertEquals(
+ expectedExtras.getIntArray(NULL_ARRAY_KEY), actualExtras.getString(NULL_ARRAY_KEY));
+ assertEquals(
+ expectedExtras.getString(NULL_STRING_KEY), actualExtras.getString(NULL_STRING_KEY));
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java
index c6aea9c38ee..9c5025f8808 100644
--- a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java
@@ -16,74 +16,170 @@ import org.robolectric.annotation.Config;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
+import java.util.concurrent.TimeUnit;
+
/** Unit tests for {@link TaskInfo}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class TaskInfoTest {
- private static final int TEST_START_MS = 300000;
- private static final int TEST_END_MS = 600000;
+ private static final long TEST_START_MS = TimeUnit.MINUTES.toMillis(5);
+ private static final long TEST_END_MS = TimeUnit.MINUTES.toMillis((10));
+ private static final long TEST_FLEX_MS = 100;
@Before
public void setUp() {
TestBackgroundTask.reset();
+ BackgroundTaskSchedulerFactory.setBackgroundTaskFactory(new TestBackgroundTaskFactory());
}
- private void checkGeneralTaskInfoFields(
- TaskInfo taskInfo, int taskId, Class<? extends BackgroundTask> backgroundTaskClass) {
- assertEquals(taskId, taskInfo.getTaskId());
- assertEquals(backgroundTaskClass, taskInfo.getBackgroundTaskClass());
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testGeneralFields() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TEST_END_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+
+ assertEquals(TaskIds.TEST, oneOffTask.getTaskId());
+ assertEquals(TestBackgroundTask.class,
+ BackgroundTaskSchedulerFactory.getBackgroundTaskFromTaskId(TaskIds.TEST)
+ .getClass());
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testExpirationWithinDeadline() {
- TaskInfo oneOffTask =
- TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TEST_END_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
-
- checkGeneralTaskInfoFields(oneOffTask, TaskIds.TEST, TestBackgroundTask.class);
-
- assertFalse(oneOffTask.getOneOffInfo().hasWindowStartTimeConstraint());
- assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowEndTimeMs());
- assertTrue(oneOffTask.getOneOffInfo().expiresAfterWindowEndTime());
-
- assertEquals(null, oneOffTask.getPeriodicInfo());
+ public void testOneOffExpirationWithinDeadline() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowEndTimeMs(TEST_END_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(null, TEST_END_MS, true);
+ oneOffTask.getTimingInfo().accept(visitor);
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testExpirationWithinTimeWindow() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TEST_START_MS, TEST_END_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
+ public void testOneOffExpirationWithinTimeWindow() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TEST_START_MS)
+ .setWindowEndTimeMs(TEST_END_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor =
+ new CheckTimingInfoVisitor(TEST_START_MS, TEST_END_MS, true);
+ oneOffTask.getTimingInfo().accept(visitor);
+ }
- checkGeneralTaskInfoFields(oneOffTask, TaskIds.TEST, TestBackgroundTask.class);
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testOneOffExpirationWithinZeroTimeWindow() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
+ .setWindowStartTimeMs(TEST_END_MS)
+ .setWindowEndTimeMs(TEST_END_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(TEST_END_MS, TEST_END_MS, true);
+ oneOffTask.getTimingInfo().accept(visitor);
+ }
- assertTrue(oneOffTask.getOneOffInfo().hasWindowStartTimeConstraint());
- assertEquals(TEST_START_MS, oneOffTask.getOneOffInfo().getWindowStartTimeMs());
- assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowEndTimeMs());
- assertTrue(oneOffTask.getOneOffInfo().expiresAfterWindowEndTime());
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testOneOffNoParamsSet() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create().build();
+ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(null, new Long(0), false);
+ oneOffTask.getTimingInfo().accept(visitor);
+ }
- assertEquals(null, oneOffTask.getPeriodicInfo());
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicExpirationWithInterval() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create()
+ .setIntervalMs(TEST_END_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(TEST_END_MS, null, true);
+ periodicTask.getTimingInfo().accept(visitor);
}
@Test
@Feature({"BackgroundTaskScheduler"})
- public void testExpirationWithinZeroTimeWindow() {
- TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
- TEST_END_MS, TEST_END_MS)
- .setExpiresAfterWindowEndTime(true)
- .build();
+ public void testPeriodicExpirationWithIntervalAndFlex() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create()
+ .setIntervalMs(TEST_END_MS)
+ .setFlexMs(TEST_FLEX_MS)
+ .setExpiresAfterWindowEndTime(true)
+ .build();
+ TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor =
+ new CheckTimingInfoVisitor(TEST_END_MS, TEST_FLEX_MS, true);
+ periodicTask.getTimingInfo().accept(visitor);
+ }
- checkGeneralTaskInfoFields(oneOffTask, TaskIds.TEST, TestBackgroundTask.class);
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testPeriodicNoParamsSet() {
+ TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create().build();
+ TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(new Long(0), null, false);
+ periodicTask.getTimingInfo().accept(visitor);
+ }
- assertTrue(oneOffTask.getOneOffInfo().hasWindowStartTimeConstraint());
- assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowStartTimeMs());
- assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowEndTimeMs());
- assertTrue(oneOffTask.getOneOffInfo().expiresAfterWindowEndTime());
+ @Test
+ @Feature({"BackgroundTaskScheduler"})
+ public void testExact() {
+ TaskInfo.TimingInfo timingInfo =
+ TaskInfo.ExactInfo.create().setTriggerAtMs(TEST_END_MS).build();
+ TaskInfo exactOneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build();
+ CheckTimingInfoVisitor visitor = new CheckTimingInfoVisitor(TEST_END_MS, null, false);
+ exactOneOffTask.getTimingInfo().accept(visitor);
+ }
- assertEquals(null, oneOffTask.getPeriodicInfo());
+ private class CheckTimingInfoVisitor implements TaskInfo.TimingInfoVisitor {
+ private final Long mStartOrIntervalOrTriggerMs;
+ private final Long mEndOrFlexMs;
+ private final boolean mExpires;
+
+ CheckTimingInfoVisitor(Long startOrIntervalOrTriggerMs, Long endOrFlexMs, boolean expires) {
+ mStartOrIntervalOrTriggerMs = startOrIntervalOrTriggerMs;
+ mEndOrFlexMs = endOrFlexMs;
+ mExpires = expires;
+ }
+
+ @Override
+ public void visit(TaskInfo.OneOffInfo oneOffInfo) {
+ if (mStartOrIntervalOrTriggerMs == null) {
+ assertFalse(oneOffInfo.hasWindowStartTimeConstraint());
+ } else {
+ assertTrue(oneOffInfo.hasWindowStartTimeConstraint());
+ assertEquals(
+ mStartOrIntervalOrTriggerMs.longValue(), oneOffInfo.getWindowStartTimeMs());
+ }
+
+ assertEquals(mEndOrFlexMs.longValue(), oneOffInfo.getWindowEndTimeMs());
+ assertEquals(mExpires, oneOffInfo.expiresAfterWindowEndTime());
+ }
+
+ @Override
+ public void visit(TaskInfo.PeriodicInfo periodicInfo) {
+ assertEquals(mStartOrIntervalOrTriggerMs.longValue(), periodicInfo.getIntervalMs());
+
+ if (mEndOrFlexMs == null) {
+ assertFalse(periodicInfo.hasFlex());
+ } else {
+ assertTrue(periodicInfo.hasFlex());
+ assertEquals(mEndOrFlexMs.longValue(), periodicInfo.getFlexMs());
+ }
+ }
+
+ @Override
+ public void visit(TaskInfo.ExactInfo exactInfo) {
+ assertEquals(mStartOrIntervalOrTriggerMs.longValue(), exactInfo.getTriggerAtMs());
+ }
}
} \ No newline at end of file
diff --git a/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TestBackgroundTaskFactory.java b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TestBackgroundTaskFactory.java
new file mode 100644
index 00000000000..596a8c5fbca
--- /dev/null
+++ b/chromium/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TestBackgroundTaskFactory.java
@@ -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.
+
+package org.chromium.components.background_task_scheduler;
+
+/**
+ * Implementation of {@link BackgroundTaskFactory} for testing.
+ * The default {@link TestBackgroundTask} class is used.
+ */
+public class TestBackgroundTaskFactory implements BackgroundTaskFactory {
+ @Override
+ public BackgroundTask getBackgroundTaskFromTaskId(int taskId) {
+ if (taskId == TaskIds.TEST) {
+ return new TestBackgroundTask();
+ }
+ return null;
+ }
+}
diff --git a/chromium/components/background_task_scheduler/android/proguard.flags b/chromium/components/background_task_scheduler/android/proguard.flags
deleted file mode 100644
index d727fb74439..00000000000
--- a/chromium/components/background_task_scheduler/android/proguard.flags
+++ /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.
-
-# Classes are created via reflection and persisted across app updates, so their
-# class names must not be obfuscated, and constructors kept.
--if class ** implements org.chromium.components.background_task_scheduler.BackgroundTask
--keep class <1> {
- public <init>();
-}
diff --git a/chromium/components/base32/OWNERS b/chromium/components/base32/OWNERS
index 86ef814e23e..388bb34c80f 100644
--- a/chromium/components/base32/OWNERS
+++ b/chromium/components/base32/OWNERS
@@ -1,2 +1,4 @@
gab@chromium.org
robpercival@chromium.org
+
+# COMPONENT: Internals
diff --git a/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h b/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h
index 2c6dc91dd9a..d1e6b6c1da7 100644
--- a/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h
+++ b/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h
@@ -23,15 +23,14 @@ class OptOutBlacklistDelegate {
// Notifies |this| that |host| has been blacklisted at |time|. This method is
// guaranteed to be called when a previously whitelisted host is now
// blacklisted.
- virtual void OnNewBlacklistedHost(const std::string& host,
- base::Time time) = 0;
+ virtual void OnNewBlacklistedHost(const std::string& host, base::Time time) {}
// Notifies |this| that the user blacklisted has changed, and it is
// guaranteed to be called when the user blacklisted status is changed.
- virtual void OnUserBlacklistedStatusChange(bool blacklisted) = 0;
+ virtual void OnUserBlacklistedStatusChange(bool blacklisted) {}
// Notifies |this| that the blacklist is cleared at |time|.
- virtual void OnBlacklistCleared(base::Time time) = 0;
+ virtual void OnBlacklistCleared(base::Time time) {}
};
} // namespace blacklist
diff --git a/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc b/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc
index 2967635e957..085c225d263 100644
--- a/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc
+++ b/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc
@@ -19,8 +19,8 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h"
@@ -271,7 +271,7 @@ class OptOutBlacklistTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
// Observer to |black_list_|.
TestOptOutBlacklistDelegate blacklist_delegate_;
diff --git a/chromium/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc b/chromium/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc
index b251df140d5..4e056a5ad24 100644
--- a/chromium/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc
+++ b/chromium/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc
@@ -16,8 +16,8 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h"
@@ -93,7 +93,7 @@ class OptOutStoreSQLTest : public testing::Test {
void TearDown() override { DestroyStore(); }
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
// The backing SQL store.
std::unique_ptr<OptOutStoreSQL> store_;
diff --git a/chromium/components/bookmark_component_strings.grdp b/chromium/components/bookmark_component_strings.grdp
index 8d4958ac3ac..f000e44db99 100644
--- a/chromium/components/bookmark_component_strings.grdp
+++ b/chromium/components/bookmark_component_strings.grdp
@@ -34,6 +34,6 @@
</message>
</if>
<message name="IDS_TOOLTIP_STAR" desc="The tooltip shown when you hover the star button in the right side of the location bar.">
- Bookmark this page
+ Bookmark this tab
</message>
</grit-part>
diff --git a/chromium/components/bookmarks/browser/bookmark_codec.cc b/chromium/components/bookmarks/browser/bookmark_codec.cc
index 169b37b3428..2e9e427b076 100644
--- a/chromium/components/bookmarks/browser/bookmark_codec.cc
+++ b/chromium/components/bookmarks/browser/bookmark_codec.cc
@@ -11,6 +11,7 @@
#include <utility>
#include "base/base64.h"
+#include "base/guid.h"
#include "base/json/json_string_value_serializer.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
@@ -35,6 +36,7 @@ const char BookmarkCodec::kChecksumKey[] = "checksum";
const char BookmarkCodec::kIdKey[] = "id";
const char BookmarkCodec::kTypeKey[] = "type";
const char BookmarkCodec::kNameKey[] = "name";
+const char BookmarkCodec::kGuidKey[] = "guid";
const char BookmarkCodec::kDateAddedKey[] = "date_added";
const char BookmarkCodec::kURLKey[] = "url";
const char BookmarkCodec::kDateModifiedKey[] = "date_modified";
@@ -51,11 +53,11 @@ static const int kCurrentVersion = 1;
BookmarkCodec::BookmarkCodec()
: ids_reassigned_(false),
+ guids_reassigned_(false),
ids_valid_(true),
maximum_id_(0),
model_sync_transaction_version_(
- BookmarkNode::kInvalidSyncTransactionVersion) {
-}
+ BookmarkNode::kInvalidSyncTransactionVersion) {}
BookmarkCodec::~BookmarkCodec() = default;
@@ -76,6 +78,7 @@ std::unique_ptr<base::Value> BookmarkCodec::Encode(
int64_t sync_transaction_version,
const std::string& sync_metadata_str) {
ids_reassigned_ = false;
+ guids_reassigned_ = false;
InitializeChecksum();
auto roots = std::make_unique<base::DictionaryValue>();
roots->Set(kRootFolderNameKey, EncodeNode(bookmark_bar_node));
@@ -112,7 +115,12 @@ bool BookmarkCodec::Decode(const base::Value& value,
int64_t* max_id,
std::string* sync_metadata_str) {
ids_.clear();
+ guids_ = {BookmarkNode::kRootNodeGuid, BookmarkNode::kBookmarkBarNodeGuid,
+ BookmarkNode::kOtherBookmarksNodeGuid,
+ BookmarkNode::kMobileBookmarksNodeGuid,
+ BookmarkNode::kManagedNodeGuid};
ids_reassigned_ = false;
+ guids_reassigned_ = false;
ids_valid_ = true;
maximum_id_ = 0;
stored_checksum_.clear();
@@ -135,6 +143,8 @@ std::unique_ptr<base::Value> BookmarkCodec::EncodeNode(
value->SetString(kIdKey, id);
const base::string16& title = node->GetTitle();
value->SetString(kNameKey, title);
+ const std::string& guid = node->guid();
+ value->SetString(kGuidKey, guid);
value->SetString(kDateAddedKey,
base::NumberToString(node->date_added().ToInternalValue()));
if (node->is_url()) {
@@ -310,6 +320,22 @@ bool BookmarkCodec::DecodeNode(const base::DictionaryValue& value,
base::string16 title;
value.GetString(kNameKey, &title);
+ std::string guid;
+ // |node| is only passed in for bookmarks of type BookmarkPermanentNode, in
+ // which case we do not need to check for GUID validity as their GUIDs are
+ // hard-coded and not read from the persisted file.
+ if (!node) {
+ // GUIDs can be empty for bookmarks that were created before GUIDs were
+ // required. When encountering one such bookmark we thus assign to it a new
+ // GUID. The same applies if the stored GUID is invalid or a duplicate.
+ if (!value.GetString(kGuidKey, &guid) || guid.empty() ||
+ !base::IsValidGUID(guid) || guids_.count(guid) != 0) {
+ guid = base::GenerateGUID();
+ guids_reassigned_ = true;
+ }
+ guids_.insert(guid);
+ }
+
std::string date_added_string;
if (!value.GetString(kDateAddedKey, &date_added_string))
date_added_string = base::NumberToString(Time::Now().ToInternalValue());
@@ -330,7 +356,7 @@ bool BookmarkCodec::DecodeNode(const base::DictionaryValue& value,
GURL url = GURL(url_string);
if (!node && url.is_valid())
- node = new BookmarkNode(id, url);
+ node = new BookmarkNode(id, guid, url);
else
return false; // Node invalid.
@@ -350,7 +376,7 @@ bool BookmarkCodec::DecodeNode(const base::DictionaryValue& value,
return false;
if (!node) {
- node = new BookmarkNode(id, GURL());
+ node = new BookmarkNode(id, guid, GURL());
} else {
// If a new node is not created, explicitly assign ID to the existing one.
node->set_id(id);
diff --git a/chromium/components/bookmarks/browser/bookmark_codec.h b/chromium/components/bookmarks/browser/bookmark_codec.h
index 45f9283a044..279528dbcd1 100644
--- a/chromium/components/bookmarks/browser/bookmark_codec.h
+++ b/chromium/components/bookmarks/browser/bookmark_codec.h
@@ -90,6 +90,10 @@ class BookmarkCodec {
// false after encoding.
bool ids_reassigned() const { return ids_reassigned_; }
+ // Returns whether the GUIDs were reassigned during decoding. Always returns
+ // false after encoding.
+ bool guids_reassigned() const { return guids_reassigned_; }
+
// Names of the various keys written to the Value.
static const char kRootsKey[];
static const char kRootFolderNameKey[];
@@ -100,6 +104,7 @@ class BookmarkCodec {
static const char kIdKey[];
static const char kTypeKey[];
static const char kNameKey[];
+ static const char kGuidKey[];
static const char kDateAddedKey[];
static const char kURLKey[];
static const char kDateModifiedKey[];
@@ -188,6 +193,9 @@ class BookmarkCodec {
// Whether or not IDs were reassigned by the codec.
bool ids_reassigned_;
+ // Whether or not GUIDs were reassigned by the codec.
+ bool guids_reassigned_;
+
// Whether or not IDs are valid. This is initially true, but set to false
// if an id is missing or not unique.
bool ids_valid_;
@@ -196,6 +204,10 @@ class BookmarkCodec {
// if we have duplicates.
std::set<int64_t> ids_;
+ // Contains the GUID of each of the nodes found in the file. Used to determine
+ // if we have duplicates.
+ std::set<std::string> guids_;
+
// MD5 context used to compute MD5 hash of all bookmark data.
base::MD5Context md5_context_;
diff --git a/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc b/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc
index 0cb5c5f803d..3133e172ca1 100644
--- a/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc
@@ -11,6 +11,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/guid.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_string_value_serializer.h"
#include "base/no_destructor.h"
@@ -60,6 +61,7 @@ void AssertNodesEqual(const BookmarkNode* expected,
ASSERT_TRUE(expected);
ASSERT_TRUE(actual);
EXPECT_EQ(expected->id(), actual->id());
+ EXPECT_EQ(expected->guid(), actual->guid());
EXPECT_EQ(expected->GetTitle(), actual->GetTitle());
EXPECT_EQ(expected->type(), actual->type());
EXPECT_TRUE(expected->date_added() == actual->date_added());
@@ -526,4 +528,195 @@ TEST_F(BookmarkCodecTest, EncodeAndDecodeSyncMetadata) {
EXPECT_EQ(sync_metadata_str, decoded_sync_metadata_str);
}
-} // namespace bookmarks
+TEST_F(BookmarkCodecTest, EncodeAndDecodeGuid) {
+ std::unique_ptr<BookmarkModel> model(CreateTestModel2());
+
+ ASSERT_FALSE(model->bookmark_bar_node()->children()[0]->guid().empty());
+ ASSERT_FALSE(model->bookmark_bar_node()->children()[1]->guid().empty());
+ ASSERT_NE(model->bookmark_bar_node()->children()[0]->guid(),
+ model->bookmark_bar_node()->children()[1]->guid());
+
+ std::string checksum;
+ std::unique_ptr<base::Value> model_value =
+ EncodeHelper(model.get(), /*sync_metadata_str=*/std::string(), &checksum);
+
+ // Decode and check for GUIDs.
+ std::unique_ptr<BookmarkModel> decoded_model = DecodeHelper(
+ *model_value, checksum, &checksum, /*expected_changes=*/false,
+ /*sync_metadata_str=*/nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(AssertModelsEqual(model.get(), decoded_model.get()));
+
+ EXPECT_EQ(model->bookmark_bar_node()->children()[0]->guid(),
+ decoded_model->bookmark_bar_node()->children()[0]->guid());
+ EXPECT_EQ(model->bookmark_bar_node()->children()[1]->guid(),
+ decoded_model->bookmark_bar_node()->children()[1]->guid());
+}
+
+TEST_F(BookmarkCodecTest, ReassignEmptyGUID) {
+ std::unique_ptr<BookmarkModel> model_to_encode(CreateTestModel1());
+
+ BookmarkCodec encoder;
+ std::unique_ptr<base::Value> value(
+ encoder.Encode(model_to_encode.get(), std::string()));
+
+ EXPECT_TRUE(value.get() != nullptr);
+
+ std::unique_ptr<BookmarkModel> decoded_model1(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder1;
+ ASSERT_TRUE(Decode(&decoder1, *value.get(), decoded_model1.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_FALSE(decoder1.guids_reassigned());
+
+ // Change GUID of child to be empty.
+ base::DictionaryValue* child_value;
+ GetBookmarksBarChildValue(value.get(), 0, &child_value);
+ std::string guid;
+ ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &guid));
+ child_value->SetString(BookmarkCodec::kGuidKey, "");
+
+ std::unique_ptr<BookmarkModel> decoded_model2(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder2;
+ ASSERT_TRUE(Decode(&decoder2, *value.get(), decoded_model2.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_NE(guid, decoded_model2->bookmark_bar_node()->children()[0]->guid());
+ EXPECT_NE("", decoded_model2->bookmark_bar_node()->children()[0]->guid());
+ EXPECT_TRUE(decoder2.guids_reassigned());
+}
+
+TEST_F(BookmarkCodecTest, ReassignMissingGUID) {
+ std::unique_ptr<BookmarkModel> model_to_encode(CreateTestModel1());
+
+ BookmarkCodec encoder;
+ std::unique_ptr<base::Value> value(
+ encoder.Encode(model_to_encode.get(), std::string()));
+
+ EXPECT_TRUE(value.get() != nullptr);
+
+ std::unique_ptr<BookmarkModel> decoded_model1(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder1;
+ ASSERT_TRUE(Decode(&decoder1, *value.get(), decoded_model1.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_FALSE(decoder1.guids_reassigned());
+
+ // Change GUID of child to be missing.
+ base::DictionaryValue* child_value;
+ GetBookmarksBarChildValue(value.get(), 0, &child_value);
+ std::string guid;
+ ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &guid));
+ child_value->Remove(BookmarkCodec::kGuidKey, nullptr);
+
+ std::unique_ptr<BookmarkModel> decoded_model2(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder2;
+ ASSERT_TRUE(Decode(&decoder2, *value.get(), decoded_model2.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_NE(guid, decoded_model2->bookmark_bar_node()->children()[0]->guid());
+ EXPECT_TRUE(decoded_model2->bookmark_bar_node()->children()[0]->guid() !=
+ std::string());
+ EXPECT_TRUE(decoder2.guids_reassigned());
+}
+
+TEST_F(BookmarkCodecTest, ReassignInvalidGUID) {
+ const std::string kInvalidGuid = "0000";
+ ASSERT_FALSE(base::IsValidGUID(kInvalidGuid));
+
+ std::unique_ptr<BookmarkModel> model_to_encode(CreateTestModel1());
+
+ BookmarkCodec encoder;
+ std::unique_ptr<base::Value> value(
+ encoder.Encode(model_to_encode.get(), std::string()));
+
+ EXPECT_TRUE(value.get() != nullptr);
+
+ // Change GUID of child to be invalid.
+ base::DictionaryValue* child_value;
+ GetBookmarksBarChildValue(value.get(), 0, &child_value);
+ child_value->SetString(BookmarkCodec::kGuidKey, kInvalidGuid);
+
+ std::string guid;
+ ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &guid));
+ ASSERT_EQ(guid, kInvalidGuid);
+
+ std::unique_ptr<BookmarkModel> decoded_model(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder;
+ ASSERT_TRUE(Decode(&decoder, *value.get(), decoded_model.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_TRUE(base::IsValidGUID(
+ decoded_model->bookmark_bar_node()->children()[0]->guid()));
+}
+
+TEST_F(BookmarkCodecTest, ReassignDuplicateGUID) {
+ std::unique_ptr<BookmarkModel> model_to_encode(CreateTestModel2());
+
+ BookmarkCodec encoder;
+ std::unique_ptr<base::Value> value(
+ encoder.Encode(model_to_encode.get(), std::string()));
+
+ EXPECT_TRUE(value.get() != nullptr);
+
+ base::DictionaryValue* child1_value;
+ GetBookmarksBarChildValue(value.get(), 0, &child1_value);
+
+ std::string child1_guid;
+ ASSERT_TRUE(child1_value->GetString(BookmarkCodec::kGuidKey, &child1_guid));
+
+ base::DictionaryValue* child2_value;
+ GetBookmarksBarChildValue(value.get(), 1, &child2_value);
+
+ // Change GUID of child to be duplicate.
+ child2_value->SetString(BookmarkCodec::kGuidKey, child1_guid);
+
+ std::string child2_guid;
+ ASSERT_TRUE(child2_value->GetString(BookmarkCodec::kGuidKey, &child2_guid));
+ ASSERT_EQ(child1_guid, child2_guid);
+
+ std::unique_ptr<BookmarkModel> decoded_model(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder;
+ ASSERT_TRUE(Decode(&decoder, *value.get(), decoded_model.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_NE(decoded_model->bookmark_bar_node()->children()[0]->guid(),
+ decoded_model->bookmark_bar_node()->children()[1]->guid());
+}
+
+TEST_F(BookmarkCodecTest, ReassignPermanentNodeDuplicateGUID) {
+ std::unique_ptr<BookmarkModel> model_to_encode(CreateTestModel1());
+
+ BookmarkCodec encoder;
+ std::unique_ptr<base::Value> value(
+ encoder.Encode(model_to_encode.get(), std::string()));
+
+ EXPECT_TRUE(value.get() != nullptr);
+
+ base::DictionaryValue* child_value;
+ GetBookmarksBarChildValue(value.get(), 0, &child_value);
+
+ // Change GUID of child to be the root node GUID.
+ child_value->SetString(BookmarkCodec::kGuidKey, BookmarkNode::kRootNodeGuid);
+
+ std::string child_guid;
+ ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &child_guid));
+ ASSERT_EQ(BookmarkNode::kRootNodeGuid, child_guid);
+
+ std::unique_ptr<BookmarkModel> decoded_model(
+ TestBookmarkClient::CreateModel());
+ BookmarkCodec decoder;
+ ASSERT_TRUE(Decode(&decoder, *value.get(), decoded_model.get(),
+ /*sync_metadata_str=*/nullptr));
+
+ EXPECT_NE(BookmarkNode::kRootNodeGuid,
+ decoded_model->bookmark_bar_node()->children()[0]->guid());
+}
+
+} // namespace bookmarks \ No newline at end of file
diff --git a/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc b/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc
index 3541b48d7d2..3c08725b430 100644
--- a/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
@@ -32,7 +32,7 @@ class BookmarkExpandedStateTrackerTest : public testing::Test {
void SetUp() override;
void TearDown() override;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple prefs_;
std::unique_ptr<BookmarkModel> model_;
diff --git a/chromium/components/bookmarks/browser/bookmark_model.cc b/chromium/components/bookmarks/browser/bookmark_model.cc
index c14125630a0..eb2e12c5f40 100644
--- a/chromium/components/bookmarks/browser/bookmark_model.cc
+++ b/chromium/components/bookmarks/browser/bookmark_model.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/guid.h"
#include "base/i18n/string_compare.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -120,7 +121,9 @@ class EmptyUndoDelegate : public BookmarkUndoDelegate {
BookmarkModel::BookmarkModel(std::unique_ptr<BookmarkClient> client)
: client_(std::move(client)),
- owned_root_(std::make_unique<BookmarkNode>(GURL())),
+ owned_root_(std::make_unique<BookmarkNode>(/*id=*/0,
+ BookmarkNode::RootNodeGuid(),
+ GURL())),
root_(owned_root_.get()),
observers_(base::ObserverListPolicy::EXISTING_ONLY),
empty_undo_delegate_(std::make_unique<EmptyUndoDelegate>()) {
@@ -566,8 +569,8 @@ const BookmarkNode* BookmarkModel::AddFolderWithMetaInfo(
DCHECK(!is_root_node(parent));
DCHECK(IsValidIndex(parent, index, true));
- std::unique_ptr<BookmarkNode> new_node =
- std::make_unique<BookmarkNode>(generate_next_node_id(), GURL());
+ std::unique_ptr<BookmarkNode> new_node = std::make_unique<BookmarkNode>(
+ generate_next_node_id(), base::GenerateGUID(), GURL());
new_node->set_date_folder_modified(Time::Now());
// Folders shouldn't have line breaks in their titles.
new_node->SetTitle(title);
@@ -601,8 +604,8 @@ const BookmarkNode* BookmarkModel::AddURLWithCreationTimeAndMetaInfo(
if (creation_time > parent->date_folder_modified())
SetDateFolderModified(parent, creation_time);
- std::unique_ptr<BookmarkNode> new_node =
- std::make_unique<BookmarkNode>(generate_next_node_id(), url);
+ std::unique_ptr<BookmarkNode> new_node = std::make_unique<BookmarkNode>(
+ generate_next_node_id(), base::GenerateGUID(), url);
new_node->SetTitle(title);
new_node->set_date_added(creation_time);
if (meta_info)
@@ -768,11 +771,12 @@ void BookmarkModel::DoneLoading(std::unique_ptr<BookmarkLoadDetails> details) {
next_node_id_ = details->max_id();
if (details->computed_checksum() != details->stored_checksum() ||
- details->ids_reassigned()) {
+ details->ids_reassigned() || details->guids_reassigned()) {
// If bookmarks file changed externally, the IDs may have changed
// externally. In that case, the decoder may have reassigned IDs to make
// them unique. So when the file has changed externally, we should save the
- // bookmarks file to persist new IDs.
+ // bookmarks file to persist such changes. The same applies if new GUIDs
+ // have been assigned to bookmarks.
if (store_)
store_->ScheduleSave();
}
diff --git a/chromium/components/bookmarks/browser/bookmark_model_unittest.cc b/chromium/components/bookmarks/browser/bookmark_model_unittest.cc
index a825780cc48..c08104c6143 100644
--- a/chromium/components/bookmarks/browser/bookmark_model_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_model_unittest.cc
@@ -18,6 +18,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
@@ -25,7 +26,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/bookmarks/browser/bookmark_model_observer.h"
@@ -505,6 +506,7 @@ TEST_F(BookmarkModelTest, AddURL) {
ASSERT_EQ(1u, root->children().size());
ASSERT_EQ(title, new_node->GetTitle());
ASSERT_TRUE(url == new_node->url());
+ ASSERT_TRUE(!new_node->guid().empty());
ASSERT_EQ(BookmarkNode::URL, new_node->type());
ASSERT_TRUE(new_node == model_->GetMostRecentlyAddedUserNodeForURL(url));
@@ -566,6 +568,7 @@ TEST_F(BookmarkModelTest, AddURLWithCreationTimeAndMetaInfo) {
ASSERT_EQ(1u, root->children().size());
ASSERT_EQ(title, new_node->GetTitle());
ASSERT_TRUE(url == new_node->url());
+ ASSERT_TRUE(!new_node->guid().empty());
ASSERT_EQ(BookmarkNode::URL, new_node->type());
ASSERT_EQ(time, new_node->date_added());
ASSERT_TRUE(new_node->GetMetaInfoMap());
@@ -607,6 +610,7 @@ TEST_F(BookmarkModelTest, AddFolder) {
ASSERT_EQ(1u, root->children().size());
ASSERT_EQ(title, new_node->GetTitle());
+ ASSERT_TRUE(!new_node->guid().empty());
ASSERT_EQ(BookmarkNode::FOLDER, new_node->type());
EXPECT_TRUE(new_node->id() != root->id() &&
@@ -1227,7 +1231,7 @@ TEST(BookmarkModelLoadTest, TitledUrlIndexPopulatedOnLoad) {
// Create a model with a single url.
base::ScopedTempDir tmp_dir;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::TaskEnvironment task_environment;
std::unique_ptr<BookmarkModel> model =
std::make_unique<BookmarkModel>(std::make_unique<TestBookmarkClient>());
model->Load(nullptr, tmp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get(),
@@ -1257,7 +1261,7 @@ TEST(BookmarkModelLoadTest, TitledUrlIndexPopulatedOnLoad) {
TEST(BookmarkNodeTest, NodeMetaInfo) {
GURL url;
- BookmarkNode node(url);
+ BookmarkNode node(/*id=*/0, base::GenerateGUID(), url);
EXPECT_FALSE(node.GetMetaInfoMap());
EXPECT_TRUE(node.SetMetaInfo("key1", "value1"));
diff --git a/chromium/components/bookmarks/browser/bookmark_node.cc b/chromium/components/bookmarks/browser/bookmark_node.cc
index 4e1ab88ef79..49d7b118f34 100644
--- a/chromium/components/bookmarks/browser/bookmark_node.cc
+++ b/chromium/components/bookmarks/browser/bookmark_node.cc
@@ -7,6 +7,7 @@
#include <map>
#include <string>
+#include "base/guid.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -22,18 +23,47 @@ const base::char16 kInvalidChars[] = {
0
};
+std::string PermanentNodeTypeToGuid(BookmarkNode::Type type) {
+ switch (type) {
+ case BookmarkNode::BOOKMARK_BAR:
+ return BookmarkNode::kBookmarkBarNodeGuid;
+ case BookmarkNode::OTHER_NODE:
+ return BookmarkNode::kOtherBookmarksNodeGuid;
+ case BookmarkNode::MOBILE:
+ return BookmarkNode::kMobileBookmarksNodeGuid;
+ case BookmarkNode::FOLDER:
+ return BookmarkNode::kManagedNodeGuid;
+ case BookmarkNode::URL:
+ NOTREACHED();
+ return std::string();
+ }
+ NOTREACHED();
+ return std::string();
+}
+
} // namespace
// BookmarkNode ---------------------------------------------------------------
// static
const int64_t BookmarkNode::kInvalidSyncTransactionVersion = -1;
+const char BookmarkNode::kRootNodeGuid[] =
+ "00000000-0000-4000-A000-000000000001";
+const char BookmarkNode::kBookmarkBarNodeGuid[] =
+ "00000000-0000-4000-A000-000000000002";
+const char BookmarkNode::kOtherBookmarksNodeGuid[] =
+ "00000000-0000-4000-A000-000000000003";
+const char BookmarkNode::kMobileBookmarksNodeGuid[] =
+ "00000000-0000-4000-A000-000000000004";
+const char BookmarkNode::kManagedNodeGuid[] =
+ "00000000-0000-4000-A000-000000000005";
+
+std::string BookmarkNode::RootNodeGuid() {
+ return BookmarkNode::kRootNodeGuid;
+}
-BookmarkNode::BookmarkNode(const GURL& url)
- : BookmarkNode(0, url, url.is_empty() ? FOLDER : URL, false) {}
-
-BookmarkNode::BookmarkNode(int64_t id, const GURL& url)
- : BookmarkNode(id, url, url.is_empty() ? FOLDER : URL, false) {}
+BookmarkNode::BookmarkNode(int64_t id, const std::string& guid, const GURL& url)
+ : BookmarkNode(id, guid, url, url.is_empty() ? FOLDER : URL, false) {}
BookmarkNode::~BookmarkNode() = default;
@@ -109,10 +139,12 @@ const GURL& BookmarkNode::GetTitledUrlNodeUrl() const {
}
BookmarkNode::BookmarkNode(int64_t id,
+ const std::string& guid,
const GURL& url,
Type type,
bool is_permanent_node)
: id_(id),
+ guid_(guid),
url_(url),
type_(type),
date_added_(base::Time::Now()),
@@ -131,7 +163,7 @@ void BookmarkNode::InvalidateFavicon() {
// BookmarkPermanentNode -------------------------------------------------------
BookmarkPermanentNode::BookmarkPermanentNode(int64_t id, Type type)
- : BookmarkNode(id, GURL(), type, true) {
+ : BookmarkNode(id, PermanentNodeTypeToGuid(type), GURL(), type, true) {
DCHECK(type != URL);
}
diff --git a/chromium/components/bookmarks/browser/bookmark_node.h b/chromium/components/bookmarks/browser/bookmark_node.h
index 9dc6dfe298e..950c5ab40a9 100644
--- a/chromium/components/bookmarks/browser/bookmark_node.h
+++ b/chromium/components/bookmarks/browser/bookmark_node.h
@@ -45,14 +45,19 @@ class BookmarkNode : public ui::TreeNode<BookmarkNode>, public TitledUrlNode {
typedef std::map<std::string, std::string> MetaInfoMap;
static const int64_t kInvalidSyncTransactionVersion;
+ static const char kRootNodeGuid[];
+ static const char kBookmarkBarNodeGuid[];
+ static const char kOtherBookmarksNodeGuid[];
+ static const char kMobileBookmarksNodeGuid[];
+ static const char kManagedNodeGuid[];
- // Creates a new node with an id of 0 and |url|.
- explicit BookmarkNode(const GURL& url);
- // Creates a new node with |id| and |url|.
- BookmarkNode(int64_t id, const GURL& url);
+ // Creates a new node with |id|, |guid| and |url|.
+ BookmarkNode(int64_t id, const std::string& guid, const GURL& url);
~BookmarkNode() override;
+ static std::string RootNodeGuid();
+
// Returns true if the node is a BookmarkPermanentNode (which does not include
// the root).
bool is_permanent_node() const { return is_permanent_node_; }
@@ -68,6 +73,12 @@ class BookmarkNode : public ui::TreeNode<BookmarkNode>, public TitledUrlNode {
int64_t id() const { return id_; }
void set_id(int64_t id) { id_ = id; }
+ // Returns the GUID for this node.
+ // For bookmark nodes that are managed by the bookmark model, the GUIDs are
+ // persisted across sessions and stable throughout the lifetime of the
+ // bookmark.
+ const std::string& guid() const { return guid_; }
+
const GURL& url() const { return url_; }
void set_url(const GURL& url) { url_ = url; }
@@ -127,7 +138,11 @@ class BookmarkNode : public ui::TreeNode<BookmarkNode>, public TitledUrlNode {
// HistoryContentsProvider.
protected:
- BookmarkNode(int64_t id, const GURL& url, Type type, bool is_permanent_node);
+ BookmarkNode(int64_t id,
+ const std::string& guid,
+ const GURL& url,
+ Type type,
+ bool is_permanent_node);
private:
friend class BookmarkModel;
@@ -162,6 +177,13 @@ class BookmarkNode : public ui::TreeNode<BookmarkNode>, public TitledUrlNode {
// The unique identifier for this node.
int64_t id_;
+ // The GUID for this node. A BookmarkNode GUID is immutable and differs from
+ // the |id_| in that it is consistent across different clients and
+ // stable throughout the lifetime of the bookmark, with the exception of nodes
+ // added to the Managed Bookmarks folder, whose GUIDs are re-assigned at
+ // start-up every time.
+ const std::string guid_;
+
// The URL of this node. BookmarkModel maintains maps off this URL, so changes
// to the URL must be done through the BookmarkModel.
GURL url_;
diff --git a/chromium/components/bookmarks/browser/bookmark_node_data.cc b/chromium/components/bookmarks/browser/bookmark_node_data.cc
index 159e78678d0..583abdad68e 100644
--- a/chromium/components/bookmarks/browser/bookmark_node_data.cc
+++ b/chromium/components/bookmarks/browser/bookmark_node_data.cc
@@ -139,7 +139,7 @@ BookmarkNodeData::~BookmarkNodeData() {
bool BookmarkNodeData::ClipboardContainsBookmarks() {
return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
ui::ClipboardFormatType::GetType(kClipboardFormatString),
- ui::ClipboardType::kCopyPaste);
+ ui::ClipboardBuffer::kCopyPaste);
}
#endif
@@ -175,7 +175,7 @@ bool BookmarkNodeData::ReadFromTuple(const GURL& url,
#if !defined(OS_MACOSX)
void BookmarkNodeData::WriteToClipboard() {
- ui::ScopedClipboardWriter scw(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste);
#if defined(OS_WIN)
const base::string16 kEOL(L"\r\n");
@@ -216,8 +216,8 @@ void BookmarkNodeData::WriteToClipboard() {
pickle, ui::ClipboardFormatType::GetType(kClipboardFormatString));
}
-bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) {
- DCHECK_EQ(type, ui::ClipboardType::kCopyPaste);
+bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardBuffer buffer) {
+ DCHECK_EQ(buffer, ui::ClipboardBuffer::kCopyPaste);
std::string data;
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
clipboard->ReadData(ui::ClipboardFormatType::GetType(kClipboardFormatString),
diff --git a/chromium/components/bookmarks/browser/bookmark_node_data.h b/chromium/components/bookmarks/browser/bookmark_node_data.h
index 2da1f18d231..fa46f3c18d0 100644
--- a/chromium/components/bookmarks/browser/bookmark_node_data.h
+++ b/chromium/components/bookmarks/browser/bookmark_node_data.h
@@ -15,7 +15,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/bookmarks/browser/bookmark_node.h"
-#include "ui/base/clipboard/clipboard_types.h"
+#include "ui/base/clipboard/clipboard_buffer.h"
#include "url/gurl.h"
#if defined(TOOLKIT_VIEWS)
@@ -131,7 +131,7 @@ struct BookmarkNodeData {
// Reads bookmarks from the specified clipboard. Prefers data written via
// WriteToClipboard() but will also attempt to read a plain bookmark.
- bool ReadFromClipboard(ui::ClipboardType type);
+ bool ReadFromClipboard(ui::ClipboardBuffer buffer);
#if defined(TOOLKIT_VIEWS)
// Writes elements to data. If there is only one element and it is a URL
diff --git a/chromium/components/bookmarks/browser/bookmark_node_data_ios.cc b/chromium/components/bookmarks/browser/bookmark_node_data_ios.cc
index 9ff8b605444..3c646744601 100644
--- a/chromium/components/bookmarks/browser/bookmark_node_data_ios.cc
+++ b/chromium/components/bookmarks/browser/bookmark_node_data_ios.cc
@@ -18,7 +18,7 @@ void BookmarkNodeData::WriteToClipboard() {
NOTREACHED();
}
-bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) {
+bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardBuffer buffer) {
NOTREACHED();
return false;
}
diff --git a/chromium/components/bookmarks/browser/bookmark_node_data_mac.mm b/chromium/components/bookmarks/browser/bookmark_node_data_mac.mm
index a6518869a6f..4b84bb177d3 100644
--- a/chromium/components/bookmarks/browser/bookmark_node_data_mac.mm
+++ b/chromium/components/bookmarks/browser/bookmark_node_data_mac.mm
@@ -29,18 +29,18 @@ const ui::ClipboardFormatType& BookmarkNodeData::GetBookmarkFormatType() {
// static
bool BookmarkNodeData::ClipboardContainsBookmarks() {
NSPasteboard* pb =
- ui::ClipboardUtil::PasteboardFromType(ui::ClipboardType::kCopyPaste);
+ ui::ClipboardUtil::PasteboardFromBuffer(ui::ClipboardBuffer::kCopyPaste);
return PasteboardContainsBookmarks(pb);
}
void BookmarkNodeData::WriteToClipboard() {
NSPasteboard* pb =
- ui::ClipboardUtil::PasteboardFromType(ui::ClipboardType::kCopyPaste);
+ ui::ClipboardUtil::PasteboardFromBuffer(ui::ClipboardBuffer::kCopyPaste);
WriteBookmarksToPasteboard(pb, elements, profile_path_);
}
-bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardType type) {
- NSPasteboard* pb = ui::ClipboardUtil::PasteboardFromType(type);
+bool BookmarkNodeData::ReadFromClipboard(ui::ClipboardBuffer buffer) {
+ NSPasteboard* pb = ui::ClipboardUtil::PasteboardFromBuffer(buffer);
base::FilePath file_path;
if (ReadBookmarksFromPasteboard(pb, &elements, &file_path)) {
profile_path_ = file_path;
diff --git a/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc b/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc
index 2abbcde4c00..401a3363ccd 100644
--- a/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
@@ -27,8 +27,7 @@ namespace bookmarks {
class BookmarkNodeDataTest : public testing::Test {
public:
BookmarkNodeDataTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
void SetUp() override {
model_ = TestBookmarkClient::CreateModel();
@@ -56,7 +55,7 @@ class BookmarkNodeDataTest : public testing::Test {
private:
base::ScopedTempDir profile_dir_;
std::unique_ptr<BookmarkModel> model_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(BookmarkNodeDataTest);
};
@@ -289,7 +288,7 @@ TEST_F(BookmarkNodeDataTest, WriteToClipboardURL) {
// Now read the data back in.
base::string16 clipboard_result;
- clipboard().ReadText(ui::ClipboardType::kCopyPaste, &clipboard_result);
+ clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
EXPECT_EQ(base::UTF8ToUTF16(url.spec()), clipboard_result);
}
@@ -319,7 +318,7 @@ TEST_F(BookmarkNodeDataTest, WriteToClipboardMultipleURLs) {
combined_text = base::UTF8ToUTF16(url.spec()) + new_line
+ base::UTF8ToUTF16(url2.spec());
base::string16 clipboard_result;
- clipboard().ReadText(ui::ClipboardType::kCopyPaste, &clipboard_result);
+ clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
EXPECT_EQ(combined_text, clipboard_result);
}
@@ -335,7 +334,7 @@ TEST_F(BookmarkNodeDataTest, WriteToClipboardEmptyFolder) {
// Now read the data back in.
base::string16 clipboard_result;
- clipboard().ReadText(ui::ClipboardType::kCopyPaste, &clipboard_result);
+ clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
EXPECT_EQ(base::ASCIIToUTF16("g1"), clipboard_result);
}
@@ -354,7 +353,7 @@ TEST_F(BookmarkNodeDataTest, WriteToClipboardFolderWithChildren) {
// Now read the data back in.
base::string16 clipboard_result;
- clipboard().ReadText(ui::ClipboardType::kCopyPaste, &clipboard_result);
+ clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
EXPECT_EQ(base::ASCIIToUTF16("g1"), clipboard_result);
}
@@ -382,7 +381,7 @@ TEST_F(BookmarkNodeDataTest, WriteToClipboardFolderAndURL) {
base::string16 folder_title = ASCIIToUTF16("g1");
combined_text = base::ASCIIToUTF16(url.spec()) + new_line + folder_title;
base::string16 clipboard_result;
- clipboard().ReadText(ui::ClipboardType::kCopyPaste, &clipboard_result);
+ clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
EXPECT_EQ(combined_text, clipboard_result);
}
diff --git a/chromium/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm b/chromium/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
index 1f69e85f3fb..411cbdc395e 100644
--- a/chromium/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
+++ b/chromium/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
@@ -11,6 +11,7 @@
#include <memory>
#include "base/files/file_path.h"
+#include "base/guid.h"
#include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h"
#include "components/bookmarks/browser/bookmark_node.h"
@@ -93,7 +94,8 @@ void ConvertNSArrayToElements(
url = GURL(base::SysNSStringToUTF8(url_string));
}
- auto new_node = std::make_unique<BookmarkNode>(url);
+ auto new_node =
+ std::make_unique<BookmarkNode>(/*id=*/0, base::GenerateGUID(), url);
NSNumber* node_id =
base::mac::ObjCCast<NSNumber>(bookmark_dict[kChromiumBookmarkIdKey]);
diff --git a/chromium/components/bookmarks/browser/bookmark_storage.cc b/chromium/components/bookmarks/browser/bookmark_storage.cc
index 0d6cea03998..5611c16a518 100644
--- a/chromium/components/bookmarks/browser/bookmark_storage.cc
+++ b/chromium/components/bookmarks/browser/bookmark_storage.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
+#include "base/guid.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_reader.h"
#include "base/json/json_string_value_serializer.h"
@@ -138,6 +139,7 @@ void LoadBookmarks(const base::FilePath& path,
details->set_computed_checksum(codec.computed_checksum());
details->set_stored_checksum(codec.stored_checksum());
details->set_ids_reassigned(codec.ids_reassigned());
+ details->set_guids_reassigned(codec.guids_reassigned());
details->set_model_meta_info_map(codec.model_meta_info_map());
details->set_model_sync_transaction_version(
codec.model_sync_transaction_version());
@@ -206,7 +208,8 @@ BookmarkLoadDetails::BookmarkLoadDetails(BookmarkClient* client)
// WARNING: do NOT add |client| as a member. Much of this code runs on another
// thread, and |client_| is not thread safe, and/or may be destroyed before
// this.
- root_node_ = std::make_unique<BookmarkNode>(GURL());
+ root_node_ = std::make_unique<BookmarkNode>(
+ /*id=*/0, BookmarkNode::RootNodeGuid(), GURL());
root_node_ptr_ = root_node_.get();
// WARNING: order is important here, various places assume the order is
// constant (but can vary between embedders with the initial visibility
diff --git a/chromium/components/bookmarks/browser/bookmark_storage.h b/chromium/components/bookmarks/browser/bookmark_storage.h
index 16ad0b13666..3f18b59d3cc 100644
--- a/chromium/components/bookmarks/browser/bookmark_storage.h
+++ b/chromium/components/bookmarks/browser/bookmark_storage.h
@@ -100,6 +100,10 @@ class BookmarkLoadDetails {
void set_ids_reassigned(bool value) { ids_reassigned_ = value; }
bool ids_reassigned() const { return ids_reassigned_; }
+ // Whether new GUIDs were assigned to Bookmarks that lacked them.
+ void set_guids_reassigned(bool value) { guids_reassigned_ = value; }
+ bool guids_reassigned() const { return guids_reassigned_; }
+
// Returns the string blob representing the sync metadata in the json file.
// The string blob is set during decode time upon the call to Bookmark::Load.
void set_sync_metadata_str(std::string sync_metadata_str) {
@@ -129,6 +133,7 @@ class BookmarkLoadDetails {
std::string computed_checksum_;
std::string stored_checksum_;
bool ids_reassigned_ = false;
+ bool guids_reassigned_ = false;
scoped_refptr<UrlIndex> url_index_;
// A string blob represetning the sync metadata stored in the json file.
std::string sync_metadata_str_;
diff --git a/chromium/components/bookmarks/browser/bookmark_utils.cc b/chromium/components/bookmarks/browser/bookmark_utils.cc
index 0acb3569d88..d0c26f449ee 100644
--- a/chromium/components/bookmarks/browser/bookmark_utils.cc
+++ b/chromium/components/bookmarks/browser/bookmark_utils.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/files/file_path.h"
+#include "base/guid.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/string_search.h"
#include "base/macros.h"
@@ -94,18 +95,6 @@ bool DoesBookmarkTextContainWords(const base::string16& text,
return true;
}
-// Returns true if |node|s title or url contains the strings in |words|.
-bool DoesBookmarkContainWords(const BookmarkNode* node,
- const std::vector<base::string16>& words) {
- return DoesBookmarkTextContainWords(node->GetTitle(), words) ||
- DoesBookmarkTextContainWords(base::UTF8ToUTF16(node->url().spec()),
- words) ||
- DoesBookmarkTextContainWords(
- url_formatter::FormatUrl(
- node->url(), url_formatter::kFormatUrlOmitNothing,
- net::UnescapeRule::NORMAL, nullptr, nullptr, nullptr),
- words);
-}
// This is used with a tree iterator to skip subtrees which are not visible.
bool PruneInvisibleFolders(const BookmarkNode* node) {
@@ -160,8 +149,8 @@ std::string TruncateUrl(const std::string& url) {
GURL GetUrlFromClipboard() {
base::string16 url_text;
#if !defined(OS_IOS)
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
- &url_text);
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &url_text);
#endif
return GURL(url_text);
}
@@ -195,7 +184,8 @@ void GetBookmarksMatchingPropertiesImpl(
while (iterator.has_next()) {
const BookmarkNode* node = iterator.Next();
if ((!query_words.empty() &&
- !DoesBookmarkContainWords(node, query_words)) ||
+ !DoesBookmarkContainWords(node->GetTitle(), node->url(),
+ query_words)) ||
model->is_permanent_node(node)) {
continue;
}
@@ -303,11 +293,11 @@ void PasteFromClipboard(BookmarkModel* model,
return;
BookmarkNodeData bookmark_data;
- if (!bookmark_data.ReadFromClipboard(ui::ClipboardType::kCopyPaste)) {
+ if (!bookmark_data.ReadFromClipboard(ui::ClipboardBuffer::kCopyPaste)) {
GURL url = GetUrlFromClipboard();
if (!url.is_valid())
return;
- BookmarkNode node(url);
+ BookmarkNode node(/*id=*/0, base::GenerateGUID(), url);
node.SetTitle(base::ASCIIToUTF16(url.spec()));
bookmark_data = BookmarkNodeData(&node);
}
@@ -403,15 +393,9 @@ void GetBookmarksMatchingProperties(BookmarkModel* model,
const QueryFields& query,
size_t max_count,
std::vector<const BookmarkNode*>* nodes) {
- std::vector<base::string16> query_words;
- query_parser::QueryParser parser;
- if (query.word_phrase_query) {
- parser.ParseQueryWords(base::i18n::ToLower(*query.word_phrase_query),
- query_parser::MatchingAlgorithm::DEFAULT,
- &query_words);
- if (query_words.empty())
- return;
- }
+ std::vector<base::string16> query_words = ParseBookmarkQuery(query);
+ if (query.word_phrase_query && query_words.empty())
+ return;
if (query.url) {
// Shortcut into the BookmarkModel if searching for URL.
@@ -430,6 +414,32 @@ void GetBookmarksMatchingProperties(BookmarkModel* model,
}
}
+// Parses the provided query and returns a vector of query words.
+std::vector<base::string16> ParseBookmarkQuery(
+ const bookmarks::QueryFields& query) {
+ std::vector<base::string16> query_words;
+ query_parser::QueryParser parser;
+ if (query.word_phrase_query) {
+ parser.ParseQueryWords(base::i18n::ToLower(*query.word_phrase_query),
+ query_parser::MatchingAlgorithm::DEFAULT,
+ &query_words);
+ }
+ return query_words;
+}
+
+// Returns true if |node|s title or url contains the strings in |words|.
+bool DoesBookmarkContainWords(const base::string16& title,
+ const GURL& url,
+ const std::vector<base::string16>& words) {
+ return DoesBookmarkTextContainWords(title, words) ||
+ DoesBookmarkTextContainWords(base::UTF8ToUTF16(url.spec()), words) ||
+ DoesBookmarkTextContainWords(
+ url_formatter::FormatUrl(url, url_formatter::kFormatUrlOmitNothing,
+ net::UnescapeRule::NORMAL, nullptr,
+ nullptr, nullptr),
+ words);
+}
+
void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(
prefs::kShowBookmarkBar,
diff --git a/chromium/components/bookmarks/browser/bookmark_utils.h b/chromium/components/bookmarks/browser/bookmark_utils.h
index 59a606a011d..62eed75416d 100644
--- a/chromium/components/bookmarks/browser/bookmark_utils.h
+++ b/chromium/components/bookmarks/browser/bookmark_utils.h
@@ -90,6 +90,16 @@ void GetBookmarksMatchingProperties(BookmarkModel* model,
size_t max_count,
std::vector<const BookmarkNode*>* nodes);
+// Parses the provided query and returns a vector of query words.
+std::vector<base::string16> ParseBookmarkQuery(
+ const bookmarks::QueryFields& query);
+
+// Returns true iff |title| or |url| contains each string in |words|. This is
+// used when searching for bookmarks.
+bool DoesBookmarkContainWords(const base::string16& title,
+ const GURL& url,
+ const std::vector<base::string16>& words);
+
// Register user preferences for Bookmarks Bar.
void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc b/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc
index 9cfd4d9fe54..bda72731051 100644
--- a/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc
@@ -12,7 +12,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/bookmarks/browser/base_bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_model.h"
@@ -32,8 +32,7 @@ class BookmarkUtilsTest : public testing::Test,
public BaseBookmarkModelObserver {
public:
BookmarkUtilsTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
grouped_changes_beginning_count_(0),
grouped_changes_ended_count_(0) {}
@@ -74,7 +73,7 @@ class BookmarkUtilsTest : public testing::Test,
}
// Clipboard requires a message loop.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
int grouped_changes_beginning_count_;
int grouped_changes_ended_count_;
@@ -270,7 +269,7 @@ TEST_F(BookmarkUtilsTest, PasteBookmarkFromURL) {
// Write blank text to clipboard.
{
- ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(base::string16());
}
// Now we shouldn't be able to paste from the clipboard.
@@ -278,7 +277,7 @@ TEST_F(BookmarkUtilsTest, PasteBookmarkFromURL) {
// Write some valid url to the clipboard.
{
- ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(url_text);
}
// Now we should be able to paste from the clipboard.
@@ -309,7 +308,7 @@ TEST_F(BookmarkUtilsTest, CopyPaste) {
// Write some text to the clipboard.
{
- ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kCopyPaste);
clipboard_writer.WriteText(ASCIIToUTF16("foo"));
}
diff --git a/chromium/components/bookmarks/browser/url_index.cc b/chromium/components/bookmarks/browser/url_index.cc
index 7a69378eded..7201a2e6b4a 100644
--- a/chromium/components/bookmarks/browser/url_index.cc
+++ b/chromium/components/bookmarks/browser/url_index.cc
@@ -5,6 +5,7 @@
#include "components/bookmarks/browser/url_index.h"
#include "base/containers/adapters.h"
+#include "base/guid.h"
#include "components/bookmarks/browser/url_and_title.h"
namespace bookmarks {
@@ -65,7 +66,7 @@ void UrlIndex::GetNodesWithIconUrl(const GURL& icon_url,
void UrlIndex::GetNodesByUrl(const GURL& url,
std::vector<const BookmarkNode*>* nodes) {
base::AutoLock url_lock(url_lock_);
- BookmarkNode tmp_node(url);
+ BookmarkNode tmp_node(/*id=*/0, base::GenerateGUID(), url);
auto i = nodes_ordered_by_url_set_.find(&tmp_node);
while (i != nodes_ordered_by_url_set_.end() && (*i)->url() == url) {
nodes->push_back(*i);
@@ -109,7 +110,7 @@ UrlIndex::~UrlIndex() = default;
bool UrlIndex::IsBookmarkedNoLock(const GURL& url) {
url_lock_.AssertAcquired();
- BookmarkNode tmp_node(url);
+ BookmarkNode tmp_node(/*id=*/0, base::GenerateGUID(), url);
return (nodes_ordered_by_url_set_.find(&tmp_node) !=
nodes_ordered_by_url_set_.end());
}
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc b/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc
index 8381a20f535..9fa7c302319 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_tracker.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
+#include "base/guid.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -58,8 +59,8 @@ int64_t ManagedBookmarksTracker::LoadInitial(BookmarkNode* folder,
if (!LoadBookmark(list, i, &title, &url, &children))
continue;
- BookmarkNode* child =
- folder->Add(std::make_unique<BookmarkNode>(next_node_id++, url));
+ BookmarkNode* child = folder->Add(std::make_unique<BookmarkNode>(
+ next_node_id++, base::GenerateGUID(), url));
child->SetTitle(title);
if (children) {
child->set_date_folder_modified(base::Time::Now());
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc b/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
index 4015e23a305..2a704a910ac 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
@@ -13,7 +13,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_model_observer.h"
@@ -165,7 +165,7 @@ class ManagedBookmarksTrackerTest : public testing::Test {
}
base::ScopedTempDir scoped_temp_dir_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple prefs_;
std::unique_ptr<BookmarkModel> model_;
MockBookmarkModelObserver observer_;
diff --git a/chromium/components/browser_sync/OWNERS b/chromium/components/browser_sync/OWNERS
index 261ab189a66..2fe6dccaeb6 100644
--- a/chromium/components/browser_sync/OWNERS
+++ b/chromium/components/browser_sync/OWNERS
@@ -1 +1,3 @@
file://components/sync/OWNERS
+# COMPONENT: Services>Sync
+# TEAM: chromium-reviews@chromium.org
diff --git a/chromium/components/browser_sync/browser_sync_client.h b/chromium/components/browser_sync/browser_sync_client.h
index eedb660be8c..9e2829a4340 100644
--- a/chromium/components/browser_sync/browser_sync_client.h
+++ b/chromium/components/browser_sync/browser_sync_client.h
@@ -14,10 +14,6 @@
class BookmarkUndoService;
-namespace autofill {
-class PersonalDataManager;
-} // namespace autofill
-
namespace bookmarks {
class BookmarkModel;
} // namespace bookmarks
@@ -70,7 +66,6 @@ class BrowserSyncClient : public syncer::SyncClient {
virtual sync_sessions::SessionSyncService* GetSessionSyncService() = 0;
virtual send_tab_to_self::SendTabToSelfSyncService*
GetSendTabToSelfSyncService() = 0;
- virtual autofill::PersonalDataManager* GetPersonalDataManager() = 0;
virtual BookmarkUndoService* GetBookmarkUndoService() = 0;
virtual base::RepeatingClosure GetPasswordStateChangedCallback() = 0;
diff --git a/chromium/components/browser_sync/browser_sync_switches.cc b/chromium/components/browser_sync/browser_sync_switches.cc
index aab5affedc8..c1aa1b8352f 100644
--- a/chromium/components/browser_sync/browser_sync_switches.cc
+++ b/chromium/components/browser_sync/browser_sync_switches.cc
@@ -21,4 +21,9 @@ const char kEnableLocalSyncBackend[] = "enable-local-sync-backend";
// flag is present.
const char kLocalSyncBackendDir[] = "local-sync-backend-dir";
+#if defined(OS_ANDROID)
+const base::Feature kSyncManualStartAndroid{"SyncManualStartAndroid",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
} // namespace switches
diff --git a/chromium/components/browser_sync/browser_sync_switches.h b/chromium/components/browser_sync/browser_sync_switches.h
index 1163cb7d0fa..f1e6969080e 100644
--- a/chromium/components/browser_sync/browser_sync_switches.h
+++ b/chromium/components/browser_sync/browser_sync_switches.h
@@ -5,12 +5,19 @@
#ifndef COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
#define COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
+#include "base/feature_list.h"
+#include "build/build_config.h"
+
namespace switches {
extern const char kDisableSyncTypes[];
extern const char kEnableLocalSyncBackend[];
extern const char kLocalSyncBackendDir[];
+#if defined(OS_ANDROID)
+extern const base::Feature kSyncManualStartAndroid;
+#endif
+
} // namespace switches
#endif // COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
diff --git a/chromium/components/browser_sync/profile_sync_components_factory_impl.cc b/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
index cf35dc1912f..f00987fb2ff 100644
--- a/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -10,10 +10,8 @@
#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "build/build_config.h"
-#include "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h"
#include "components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h"
#include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
-#include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
#include "components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h"
#include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h"
#include "components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h"
@@ -30,6 +28,7 @@
#include "components/send_tab_to_self/send_tab_to_self_model_type_controller.h"
#include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
#include "components/sync/base/report_unrecoverable_error.h"
+#include "components/sync/base/sync_base_switches.h"
#include "components/sync/driver/data_type_manager_impl.h"
#include "components/sync/driver/glue/sync_engine_impl.h"
#include "components/sync/driver/model_type_controller.h"
@@ -112,7 +111,10 @@ ProfileSyncComponentsFactoryImpl::ProfileSyncComponentsFactoryImpl(
web_data_service_on_disk,
const scoped_refptr<autofill::AutofillWebDataService>&
web_data_service_in_memory,
- const scoped_refptr<password_manager::PasswordStore>& password_store,
+ const scoped_refptr<password_manager::PasswordStore>&
+ profile_password_store,
+ const scoped_refptr<password_manager::PasswordStore>&
+ account_password_store,
sync_bookmarks::BookmarkSyncService* bookmark_sync_service)
: sync_client_(sync_client),
channel_(channel),
@@ -121,7 +123,8 @@ ProfileSyncComponentsFactoryImpl::ProfileSyncComponentsFactoryImpl(
db_thread_(db_thread),
web_data_service_on_disk_(web_data_service_on_disk),
web_data_service_in_memory_(web_data_service_in_memory),
- password_store_(password_store),
+ profile_password_store_(profile_password_store),
+ account_password_store_(account_password_store),
bookmark_sync_service_(bookmark_sync_service) {
DCHECK(sync_client_);
}
@@ -189,21 +192,10 @@ ProfileSyncComponentsFactoryImpl::CreateCommonDataTypeControllers(
// Wallet data nor Wallet metadata sync is explicitly disabled.
if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) &&
!disabled_types.Has(syncer::AUTOFILL_WALLET_METADATA)) {
- if (base::FeatureList::IsEnabled(
- switches::kSyncUSSAutofillWalletMetadata)) {
- controllers.push_back(CreateWalletModelTypeController(
- syncer::AUTOFILL_WALLET_METADATA,
- base::BindRepeating(&AutofillWalletMetadataDelegateFromDataService),
- sync_service));
- } else {
- controllers.push_back(
- std::make_unique<AutofillWalletDataTypeController>(
- syncer::AUTOFILL_WALLET_METADATA, db_thread_, dump_stack,
- sync_service, sync_client_,
- base::BindRepeating(&BrowserSyncClient::GetPersonalDataManager,
- base::Unretained(sync_client_)),
- web_data_service_on_disk_));
- }
+ controllers.push_back(CreateWalletModelTypeController(
+ syncer::AUTOFILL_WALLET_METADATA,
+ base::BindRepeating(&AutofillWalletMetadataDelegateFromDataService),
+ sync_service));
}
}
@@ -266,8 +258,11 @@ ProfileSyncComponentsFactoryImpl::CreateCommonDataTypeControllers(
history_disabled_pref_));
}
- // Favicon sync is enabled by default. Register unless explicitly disabled.
- if (!disabled_types.Has(syncer::FAVICON_IMAGES) &&
+ // If |kDoNotSyncFaviconDataTypes| feature is enabled, never register
+ // controllers for favicon sync. Otherwise, it is enabled by default and we
+ // should register unless explicitly disabled.
+ if (!base::FeatureList::IsEnabled(switches::kDoNotSyncFaviconDataTypes) &&
+ !disabled_types.Has(syncer::FAVICON_IMAGES) &&
!disabled_types.Has(syncer::FAVICON_TRACKING)) {
controllers.push_back(
std::make_unique<SyncableServiceBasedModelTypeController>(
@@ -288,17 +283,21 @@ ProfileSyncComponentsFactoryImpl::CreateCommonDataTypeControllers(
// disabled.
if (!disabled_types.Has(syncer::PASSWORDS)) {
if (base::FeatureList::IsEnabled(switches::kSyncUSSPasswords)) {
- if (password_store_) {
- // |password_store_| can be null in tests.
+ if (profile_password_store_) {
+ // |profile_password_store_| can be null in tests.
controllers.push_back(
std::make_unique<password_manager::PasswordModelTypeController>(
- password_store_->CreateSyncControllerDelegate(), sync_service,
- sync_client_->GetPasswordStateChangedCallback()));
+ profile_password_store_->CreateSyncControllerDelegate(),
+ account_password_store_
+ ? account_password_store_->CreateSyncControllerDelegate()
+ : nullptr,
+ sync_service, sync_client_->GetPasswordStateChangedCallback()));
}
} else {
controllers.push_back(std::make_unique<PasswordDataTypeController>(
dump_stack, sync_service, sync_client_,
- sync_client_->GetPasswordStateChangedCallback(), password_store_));
+ sync_client_->GetPasswordStateChangedCallback(),
+ profile_password_store_));
}
}
@@ -336,6 +335,15 @@ ProfileSyncComponentsFactoryImpl::CreateCommonDataTypeControllers(
base::Unretained(sync_client_),
syncer::PRINTERS))));
}
+ if (!disabled_types.Has(syncer::WIFI_CONFIGURATIONS) &&
+ base::FeatureList::IsEnabled(switches::kSyncWifiConfigurations)) {
+ controllers.push_back(std::make_unique<ModelTypeController>(
+ syncer::WIFI_CONFIGURATIONS,
+ std::make_unique<syncer::ForwardingModelTypeControllerDelegate>(
+ sync_client_
+ ->GetControllerDelegateForModelType(syncer::WIFI_CONFIGURATIONS)
+ .get())));
+ }
#endif
// Reading list sync is enabled by default only on iOS. Register unless
diff --git a/chromium/components/browser_sync/profile_sync_components_factory_impl.h b/chromium/components/browser_sync/profile_sync_components_factory_impl.h
index 73f9459c79c..f99db6169f7 100644
--- a/chromium/components/browser_sync/profile_sync_components_factory_impl.h
+++ b/chromium/components/browser_sync/profile_sync_components_factory_impl.h
@@ -51,7 +51,10 @@ class ProfileSyncComponentsFactoryImpl
web_data_service_on_disk,
const scoped_refptr<autofill::AutofillWebDataService>&
web_data_service_in_memory,
- const scoped_refptr<password_manager::PasswordStore>& password_store,
+ const scoped_refptr<password_manager::PasswordStore>&
+ profile_password_store,
+ const scoped_refptr<password_manager::PasswordStore>&
+ account_password_store,
sync_bookmarks::BookmarkSyncService* bookmark_sync_service);
~ProfileSyncComponentsFactoryImpl() override;
@@ -119,7 +122,8 @@ class ProfileSyncComponentsFactoryImpl
web_data_service_on_disk_;
const scoped_refptr<autofill::AutofillWebDataService>
web_data_service_in_memory_;
- const scoped_refptr<password_manager::PasswordStore> password_store_;
+ const scoped_refptr<password_manager::PasswordStore> profile_password_store_;
+ const scoped_refptr<password_manager::PasswordStore> account_password_store_;
sync_bookmarks::BookmarkSyncService* const bookmark_sync_service_;
DISALLOW_COPY_AND_ASSIGN(ProfileSyncComponentsFactoryImpl);
diff --git a/chromium/components/browser_sync/profile_sync_service_bookmark_unittest.cc b/chromium/components/browser_sync/profile_sync_service_bookmark_unittest.cc
index 710732a22cd..a6b21b00b3f 100644
--- a/chromium/components/browser_sync/profile_sync_service_bookmark_unittest.cc
+++ b/chromium/components/browser_sync/profile_sync_service_bookmark_unittest.cc
@@ -20,6 +20,7 @@
#include "base/containers/stack.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
@@ -1781,7 +1782,7 @@ void ProfileSyncServiceBookmarkTestWithData::CompareWithTestData(
const BookmarkNode* child_node = node->children()[i].get();
const TestData& item = data[i];
GURL url = GURL(item.url == nullptr ? "" : item.url);
- BookmarkNode test_node(url);
+ BookmarkNode test_node(/*id=*/0, base::GenerateGUID(), url);
test_node.SetTitle(base::UTF8ToUTF16(item.title));
EXPECT_EQ(child_node->GetTitle(), test_node.GetTitle());
if (item.url) {
diff --git a/chromium/components/browser_watcher/watcher_metrics_provider_win.cc b/chromium/components/browser_watcher/watcher_metrics_provider_win.cc
index b59f2b5a202..d535722325a 100644
--- a/chromium/components/browser_watcher/watcher_metrics_provider_win.cc
+++ b/chromium/components/browser_watcher/watcher_metrics_provider_win.cc
@@ -168,8 +168,8 @@ void LogCollectionInitStatus(CollectionInitializationStatus status) {
// Returns a task runner appropriate for running background tasks that perform
// file I/O.
scoped_refptr<base::TaskRunner> CreateBackgroundTaskRunner() {
- return base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ return base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}
@@ -189,8 +189,7 @@ WatcherMetricsProviderWin::WatcherMetricsProviderWin(
user_data_dir_(user_data_dir),
crash_dir_(crash_dir),
exe_details_cb_(exe_details_cb),
- task_runner_(CreateBackgroundTaskRunner()),
- weak_ptr_factory_(this) {}
+ task_runner_(CreateBackgroundTaskRunner()) {}
WatcherMetricsProviderWin::~WatcherMetricsProviderWin() {
}
diff --git a/chromium/components/browser_watcher/watcher_metrics_provider_win.h b/chromium/components/browser_watcher/watcher_metrics_provider_win.h
index df792c9d68c..ef3c981ddbe 100644
--- a/chromium/components/browser_watcher/watcher_metrics_provider_win.h
+++ b/chromium/components/browser_watcher/watcher_metrics_provider_win.h
@@ -65,7 +65,7 @@ class WatcherMetricsProviderWin : public metrics::MetricsProvider {
// registry if metrics reporting is disabled.
scoped_refptr<base::TaskRunner> task_runner_;
- base::WeakPtrFactory<WatcherMetricsProviderWin> weak_ptr_factory_;
+ base::WeakPtrFactory<WatcherMetricsProviderWin> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WatcherMetricsProviderWin);
};
diff --git a/chromium/components/browser_watcher/watcher_metrics_provider_win_unittest.cc b/chromium/components/browser_watcher/watcher_metrics_provider_win_unittest.cc
index f2c70b2bc67..615b2f189fa 100644
--- a/chromium/components/browser_watcher/watcher_metrics_provider_win_unittest.cc
+++ b/chromium/components/browser_watcher/watcher_metrics_provider_win_unittest.cc
@@ -13,7 +13,7 @@
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_reg_util_win.h"
#include "base/win/registry.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -65,7 +65,7 @@ class WatcherMetricsProviderWinTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
registry_util::RegistryOverrideManager override_manager_;
base::HistogramTester histogram_tester_;
};
@@ -138,7 +138,7 @@ TEST_F(WatcherMetricsProviderWinTest, DeletesExitcodeKeyWhenNotReporting) {
provider.OnRecordingDisabled();
// Flush the task(s).
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Make sure the subkey for the pseudo process has been deleted on reporting.
ASSERT_EQ(ERROR_FILE_NOT_FOUND,
diff --git a/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc b/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc
index 8881f97e34f..b91fc183d84 100644
--- a/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc
+++ b/chromium/components/browser_watcher/window_hang_monitor_win_unittest.cc
@@ -11,6 +11,7 @@
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process.h"
@@ -143,7 +144,7 @@ class MonitoredProcessClient {
// Creates a thread then creates the message window on it.
void CreateMessageWindow() {
ASSERT_TRUE(message_window_thread_.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_UI, 0)));
+ base::Thread::Options(base::MessagePumpType::UI, 0)));
bool succeeded = false;
base::WaitableEvent created(
@@ -259,7 +260,7 @@ class HangMonitorThread {
// window for |process|. Blocks until the monitor has been initialized.
bool Start(base::Process process) {
if (!thread_.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_UI, 0))) {
+ base::Thread::Options(base::MessagePumpType::UI, 0))) {
return false;
}
diff --git a/chromium/components/browsing_data/content/conditional_cache_counting_helper.cc b/chromium/components/browsing_data/content/conditional_cache_counting_helper.cc
index a6fe6420bec..5a4dfa520e1 100644
--- a/chromium/components/browsing_data/content/conditional_cache_counting_helper.cc
+++ b/chromium/components/browsing_data/content/conditional_cache_counting_helper.cc
@@ -4,199 +4,26 @@
#include "components/browsing_data/content/conditional_cache_counting_helper.h"
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "net/disk_cache/disk_cache.h"
-#include "net/http/http_cache.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom.h"
-using content::BrowserThread;
-
namespace browsing_data {
-ConditionalCacheCountingHelper::ConditionalCacheCountingHelper(
- base::Time begin_time,
- base::Time end_time,
- net::URLRequestContextGetter* main_context_getter,
- net::URLRequestContextGetter* media_context_getter,
- CacheCountCallback result_callback)
- : calculation_result_(0),
- is_upper_limit_(false),
- result_callback_(std::move(result_callback)),
- begin_time_(begin_time),
- end_time_(end_time),
- is_finished_(false),
- main_context_getter_(main_context_getter),
- media_context_getter_(media_context_getter),
- next_cache_state_(CacheState::NONE),
- cache_(nullptr),
- iterator_(nullptr) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-ConditionalCacheCountingHelper::~ConditionalCacheCountingHelper() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
// static
void ConditionalCacheCountingHelper::Count(
content::StoragePartition* storage_partition,
base::Time begin_time,
base::Time end_time,
CacheCountCallback result_callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!result_callback.is_null());
- // The new path generally can't be used with network service off, since it
- // would only count the main cache, missing the media cache. (There is a way
- // of disabling that separately, but as the feature is in chrome/, we can't be
- // aware of that here).
- //
- // See https://crbug.com/789657 for the bug on media cache and network
- // service.
- //
- // TODO(morlovich): If the media cache goes away, this class can be simplified
- // to just the "network service" path.
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- storage_partition->GetNetworkContext()->ComputeHttpCacheSize(
- begin_time, end_time,
- mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(result_callback),
- /* is_upper_limit = */ false,
- /* result_or_error = */ net::ERR_FAILED));
- } else {
- ConditionalCacheCountingHelper* instance =
- new ConditionalCacheCountingHelper(
- begin_time, end_time, storage_partition->GetURLRequestContext(),
- storage_partition->GetMediaURLRequestContext(),
- std::move(result_callback));
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(
- &ConditionalCacheCountingHelper::CountHttpCacheOnIOThread,
- base::Unretained(instance)));
- }
-}
-
-void ConditionalCacheCountingHelper::Finished() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_finished_);
- is_finished_ = true;
- std::move(result_callback_).Run(is_upper_limit_, calculation_result_);
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
-}
-
-void ConditionalCacheCountingHelper::CountHttpCacheOnIOThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- next_cache_state_ = CacheState::NONE;
- DCHECK_EQ(CacheState::NONE, next_cache_state_);
- DCHECK(main_context_getter_);
- DCHECK(media_context_getter_);
-
- next_cache_state_ = CacheState::CREATE_MAIN;
- DoCountCache(net::OK);
-}
-
-// The expected state sequence is CacheState::NONE --> CacheState::CREATE_MAIN
-// --> CacheState::PROCESS_MAIN --> CacheState::CREATE_MEDIA -->
-// CacheState::PROCESS_MEDIA --> CacheState::DONE.
-// On error, we jump directly to CacheState::DONE.
-void ConditionalCacheCountingHelper::DoCountCache(int64_t rv) {
- DCHECK_NE(CacheState::NONE, next_cache_state_);
- while (rv != net::ERR_IO_PENDING && next_cache_state_ != CacheState::NONE) {
- // On error, finish and return the error code. A valid result value might
- // be of two types - either net::OK from the CREATE states, or the result
- // of calculation from the PROCESS states. Since net::OK == 0, it is valid
- // to simply add the value to the final calculation result.
- if (rv < 0) {
- calculation_result_ = rv;
- next_cache_state_ = CacheState::DONE;
- } else {
- DCHECK_EQ(0, net::OK);
- calculation_result_ += rv;
- }
-
- switch (next_cache_state_) {
- case CacheState::CREATE_MAIN:
- case CacheState::CREATE_MEDIA: {
- // Get a pointer to the cache.
- net::URLRequestContextGetter* getter =
- (next_cache_state_ == CacheState::CREATE_MAIN)
- ? main_context_getter_.get()
- : media_context_getter_.get();
- net::HttpCache* http_cache = getter->GetURLRequestContext()
- ->http_transaction_factory()
- ->GetCache();
-
- next_cache_state_ = (next_cache_state_ == CacheState::CREATE_MAIN)
- ? CacheState::COUNT_MAIN
- : CacheState::COUNT_MEDIA;
-
- rv = http_cache->GetBackend(
- &cache_, base::BindOnce(
- [](ConditionalCacheCountingHelper* self, int rv) {
- self->DoCountCache(static_cast<int64_t>(rv));
- },
- base::Unretained(this)));
-
- break;
- }
- case CacheState::COUNT_MAIN:
- case CacheState::COUNT_MEDIA: {
- next_cache_state_ = (next_cache_state_ == CacheState::COUNT_MAIN)
- ? CacheState::CREATE_MEDIA
- : CacheState::DONE;
-
- // |cache_| can be null if it cannot be initialized.
- if (cache_) {
- if (begin_time_.is_null() && end_time_.is_max()) {
- rv = cache_->CalculateSizeOfAllEntries(
- base::BindOnce(&ConditionalCacheCountingHelper::DoCountCache,
- base::Unretained(this)));
- } else {
- rv = cache_->CalculateSizeOfEntriesBetween(
- begin_time_, end_time_,
- base::BindOnce(&ConditionalCacheCountingHelper::DoCountCache,
- base::Unretained(this)));
- if (rv == net::ERR_NOT_IMPLEMENTED) {
- is_upper_limit_ = true;
- rv = cache_->CalculateSizeOfAllEntries(
- base::BindOnce(&ConditionalCacheCountingHelper::DoCountCache,
- base::Unretained(this)));
- }
- }
- cache_ = nullptr;
- }
- break;
- }
- case CacheState::DONE: {
- cache_ = nullptr;
- next_cache_state_ = CacheState::NONE;
- // Notify the UI thread that we are done.
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&ConditionalCacheCountingHelper::Finished,
- base::Unretained(this)));
- return;
- }
- case CacheState::NONE: {
- NOTREACHED() << "bad state";
- return;
- }
- }
- }
+ storage_partition->GetNetworkContext()->ComputeHttpCacheSize(
+ begin_time, end_time,
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ std::move(result_callback),
+ /* is_upper_limit = */ false,
+ /* result_or_error = */ net::ERR_FAILED));
}
} // namespace browsing_data
diff --git a/chromium/components/browsing_data/content/conditional_cache_counting_helper.h b/chromium/components/browsing_data/content/conditional_cache_counting_helper.h
index 88497b1fabf..8452226b01e 100644
--- a/chromium/components/browsing_data/content/conditional_cache_counting_helper.h
+++ b/chromium/components/browsing_data/content/conditional_cache_counting_helper.h
@@ -10,16 +10,11 @@
#include "base/callback_forward.h"
#include "base/sequenced_task_runner_helpers.h"
#include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
namespace content {
class StoragePartition;
}
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace browsing_data {
// Helper to count the size of the http cache data from a StoragePartition.
@@ -39,51 +34,6 @@ class ConditionalCacheCountingHelper {
CacheCountCallback result_callback);
private:
- enum class CacheState {
- NONE,
- CREATE_MAIN,
- CREATE_MEDIA,
- COUNT_MAIN,
- COUNT_MEDIA,
- DONE
- };
-
- friend class base::DeleteHelper<ConditionalCacheCountingHelper>;
-
- ConditionalCacheCountingHelper(
- base::Time begin_time,
- base::Time end_time,
- net::URLRequestContextGetter* main_context_getter,
- net::URLRequestContextGetter* media_context_getter,
- CacheCountCallback result_callback);
- ~ConditionalCacheCountingHelper();
-
- void Finished();
-
- void CountHttpCacheOnIOThread();
- void DoCountCache(int64_t rv);
-
- // State used for legacy path. Will eventually go away.
-
- // Stores the cache size computation result before it can be returned
- // via a callback. This is either the sum of size of the the two cache
- // backends, or an error code if the calculation failed.
- int64_t calculation_result_;
- bool is_upper_limit_;
-
- CacheCountCallback result_callback_;
- const base::Time begin_time_;
- const base::Time end_time_;
-
- bool is_finished_;
-
- const scoped_refptr<net::URLRequestContextGetter> main_context_getter_;
- const scoped_refptr<net::URLRequestContextGetter> media_context_getter_;
-
- CacheState next_cache_state_;
- disk_cache::Backend* cache_;
-
- std::unique_ptr<disk_cache::Backend::Iterator> iterator_;
DISALLOW_COPY_AND_ASSIGN(ConditionalCacheCountingHelper);
};
diff --git a/chromium/components/browsing_data/core/BUILD.gn b/chromium/components/browsing_data/core/BUILD.gn
index 3a7beb2d4a7..1fcd2d387eb 100644
--- a/chromium/components/browsing_data/core/BUILD.gn
+++ b/chromium/components/browsing_data/core/BUILD.gn
@@ -23,6 +23,8 @@ static_library("core") {
"counters/passwords_counter.h",
"counters/sync_tracker.cc",
"counters/sync_tracker.h",
+ "features.cc",
+ "features.h",
"history_notice_utils.cc",
"history_notice_utils.h",
"pref_names.cc",
diff --git a/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc b/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc
index defe1227caa..870446b1c76 100644
--- a/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc
+++ b/chromium/components/browsing_data/core/browsing_data_utils_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind_helpers.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/browsing_data/core/counters/autofill_counter.h"
@@ -50,7 +50,7 @@ class BrowsingDataUtilsTest : public testing::Test {
PrefService* prefs() { return &prefs_; }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
};
diff --git a/chromium/components/browsing_data/core/counters/browsing_data_counter_unittest.cc b/chromium/components/browsing_data/core/counters/browsing_data_counter_unittest.cc
index 60ddc66c7bf..77f8f603e37 100644
--- a/chromium/components/browsing_data/core/counters/browsing_data_counter_unittest.cc
+++ b/chromium/components/browsing_data/core/counters/browsing_data_counter_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/browsing_data/core/pref_names.h"
@@ -104,7 +104,7 @@ class BrowsingDataCounterTest : public testing::Test {
private:
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<MockBrowsingDataCounter> counter_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(BrowsingDataCounterTest, NoResponse) {
diff --git a/chromium/components/browsing_data/core/features.cc b/chromium/components/browsing_data/core/features.cc
new file mode 100644
index 00000000000..e57c1192202
--- /dev/null
+++ b/chromium/components/browsing_data/core/features.cc
@@ -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.
+
+#include "components/browsing_data/core/features.h"
+
+namespace browsing_data {
+namespace features {
+
+const base::Feature kEnableRemovingAllThirdPartyCookies{
+ "EnableRemovingAllThirdPartyCookies", base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace features
+} // namespace browsing_data
diff --git a/chromium/components/browsing_data/core/features.h b/chromium/components/browsing_data/core/features.h
new file mode 100644
index 00000000000..6543d4081ab
--- /dev/null
+++ b/chromium/components/browsing_data/core/features.h
@@ -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.
+
+#ifndef COMPONENTS_BROWSING_DATA_CORE_FEATURES_H_
+#define COMPONENTS_BROWSING_DATA_CORE_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace browsing_data {
+namespace features {
+
+// Enable removal of all third-party cookies and site data.
+extern const base::Feature kEnableRemovingAllThirdPartyCookies;
+
+} // namespace features
+} // namespace browsing_data
+
+#endif // COMPONENTS_BROWSING_DATA_CORE_FEATURES_H_
diff --git a/chromium/components/browsing_data/core/history_notice_utils_unittest.cc b/chromium/components/browsing_data/core/history_notice_utils_unittest.cc
index 2aacba65a80..e6c89390695 100644
--- a/chromium/components/browsing_data/core/history_notice_utils_unittest.cc
+++ b/chromium/components/browsing_data/core/history_notice_utils_unittest.cc
@@ -9,7 +9,7 @@
#include "base/callback.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/history/core/test/fake_web_history_service.h"
#include "components/sync/base/model_type.h"
#include "components/sync/driver/test_sync_service.h"
@@ -60,7 +60,7 @@ class HistoryNoticeUtilsTest : public ::testing::Test {
std::unique_ptr<syncer::TestSyncService> sync_service_;
std::unique_ptr<history::FakeWebHistoryService> history_service_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(HistoryNoticeUtilsTest, NotSyncing) {
diff --git a/chromium/components/browsing_data_strings_grdp/OWNERS b/chromium/components/browsing_data_strings_grdp/OWNERS
index 93c725018e9..e6911aefb83 100644
--- a/chromium/components/browsing_data_strings_grdp/OWNERS
+++ b/chromium/components/browsing_data_strings_grdp/OWNERS
@@ -1 +1,2 @@
file://components/browsing_data/OWNERS
+# COMPONENT: Privacy
diff --git a/chromium/components/captive_portal/OWNERS b/chromium/components/captive_portal/OWNERS
index a122871fda3..0ece4fbd4c2 100644
--- a/chromium/components/captive_portal/OWNERS
+++ b/chromium/components/captive_portal/OWNERS
@@ -1,3 +1,4 @@
mmenke@chromium.org
# COMPONENT: Internals>Network
+# TEAM: net-dev@chromium.org
diff --git a/chromium/components/captive_portal/captive_portal_detector.cc b/chromium/components/captive_portal/captive_portal_detector.cc
index 051b345377e..e38a821d717 100644
--- a/chromium/components/captive_portal/captive_portal_detector.cc
+++ b/chromium/components/captive_portal/captive_portal_detector.cc
@@ -88,7 +88,7 @@ void CaptivePortalDetector::StartProbe(
// Can't safely use net::LOAD_DISABLE_CERT_NETWORK_FETCHES here,
// since then the connection may be reused without checking the cert.
resource_request->load_flags = net::LOAD_BYPASS_CACHE;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
diff --git a/chromium/components/captive_portal/captive_portal_detector_unittest.cc b/chromium/components/captive_portal/captive_portal_detector_unittest.cc
index badce529de7..4eade3c69b5 100644
--- a/chromium/components/captive_portal/captive_portal_detector_unittest.cc
+++ b/chromium/components/captive_portal/captive_portal_detector_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/captive_portal/captive_portal_testing_utils.h"
@@ -114,7 +114,7 @@ class CaptivePortalDetectorTest : public testing::Test,
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<CaptivePortalDetector> detector_;
};
diff --git a/chromium/components/cast_certificate/cast_cert_validator.cc b/chromium/components/cast_certificate/cast_cert_validator.cc
index 08c5af7ca5c..6cf222ade50 100644
--- a/chromium/components/cast_certificate/cast_cert_validator.cc
+++ b/chromium/components/cast_certificate/cast_cert_validator.cc
@@ -303,14 +303,13 @@ CastCertError VerifyDeviceCertUsingCustomTrustStore(
net::der::GeneralizedTime verification_time;
if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time))
return CastCertError::ERR_UNEXPECTED;
- net::CertPathBuilder::Result result;
net::CertPathBuilder path_builder(
target_cert.get(), trust_store, &path_builder_delegate, verification_time,
net::KeyPurpose::CLIENT_AUTH, net::InitialExplicitPolicy::kFalse,
{net::AnyPolicy()}, net::InitialPolicyMappingInhibit::kFalse,
- net::InitialAnyPolicyInhibit::kFalse, &result);
+ net::InitialAnyPolicyInhibit::kFalse);
path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source);
- path_builder.Run();
+ net::CertPathBuilder::Result result = path_builder.Run();
if (!result.HasValidPath())
return MapToCastError(result);
diff --git a/chromium/components/cast_certificate/cast_crl.cc b/chromium/components/cast_certificate/cast_crl.cc
index c2f38e4398e..03adf78180d 100644
--- a/chromium/components/cast_certificate/cast_crl.cc
+++ b/chromium/components/cast_certificate/cast_crl.cc
@@ -137,13 +137,12 @@ bool VerifyCRL(const Crl& crl,
net::SimplePathBuilderDelegate path_builder_delegate(
2048, net::SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
- net::CertPathBuilder::Result result;
net::CertPathBuilder path_builder(
parsed_cert.get(), trust_store, &path_builder_delegate, verification_time,
net::KeyPurpose::ANY_EKU, net::InitialExplicitPolicy::kFalse,
{net::AnyPolicy()}, net::InitialPolicyMappingInhibit::kFalse,
- net::InitialAnyPolicyInhibit::kFalse, &result);
- path_builder.Run();
+ net::InitialAnyPolicyInhibit::kFalse);
+ net::CertPathBuilder::Result result = path_builder.Run();
if (!result.HasValidPath()) {
VLOG(2) << "CRL - Issuer certificate verification failed.";
// TODO(crbug.com/634443): Log the error information.
diff --git a/chromium/components/cast_channel/cast_message_handler_unittest.cc b/chromium/components/cast_channel/cast_message_handler_unittest.cc
index f835e3c65f2..7f13d4b5142 100644
--- a/chromium/components/cast_channel/cast_message_handler_unittest.cc
+++ b/chromium/components/cast_channel/cast_message_handler_unittest.cc
@@ -10,11 +10,11 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/test/values_test_util.h"
#include "components/cast_channel/cast_test_util.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "services/data_decoder/public/cpp/testing_json_parser.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -73,8 +73,7 @@ MATCHER_P(HasPayloadUtf8, payload, "") {
class CastMessageHandlerTest : public testing::Test {
public:
CastMessageHandlerTest()
- : thread_bundle_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
cast_socket_service_(new base::TestSimpleTaskRunner()),
handler_(&cast_socket_service_,
/* connector */ nullptr,
@@ -146,7 +145,7 @@ class CastMessageHandlerTest : public testing::Test {
}
protected:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<base::RunLoop> run_loop_;
testing::NiceMock<MockCastSocketService> cast_socket_service_;
data_decoder::TestingJsonParser::ScopedFactoryOverride parser_override_;
@@ -246,7 +245,7 @@ TEST_F(CastMessageHandlerTest, RequestAppAvailabilityTimesOut) {
base::Unretained(this)));
EXPECT_CALL(*this, DoOnAppAvailability("ABCDEFAB",
GetAppAvailabilityResult::kUnknown));
- thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
}
TEST_F(CastMessageHandlerTest, AppAvailabilitySentOnlyOnceWhilePending) {
@@ -288,7 +287,7 @@ TEST_F(CastMessageHandlerTest, CloseConnectionFromReceiver) {
})");
OnMessage(response);
// Wait for message to be parsed and handled.
- thread_bundle_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Re-open virtual connection should cause message to be sent.
EXPECT_CALL(*transport_, SendMessage(_, _));
@@ -342,7 +341,7 @@ TEST_F(CastMessageHandlerTest, LaunchSessionTimedOut) {
base::Unretained(this),
LaunchSessionResponse::Result::kTimedOut));
- thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(30));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(30));
EXPECT_EQ(1, session_launch_response_count_);
}
@@ -516,7 +515,7 @@ TEST_F(CastMessageHandlerTest, SetVolumeTimedOut) {
handler_.SendSetVolumeRequest(channel_id_, ParseJson(message_str),
"theSourceId", callback.Get());
EXPECT_CALL(callback, Run(Result::kFailed));
- thread_bundle_.FastForwardBy(kRequestTimeout);
+ task_environment_.FastForwardBy(kRequestTimeout);
}
} // namespace cast_channel
diff --git a/chromium/components/cast_channel/cast_message_util.cc b/chromium/components/cast_channel/cast_message_util.cc
index d3101fcec43..42ddb52026e 100644
--- a/chromium/components/cast_channel/cast_message_util.cc
+++ b/chromium/components/cast_channel/cast_message_util.cc
@@ -60,6 +60,8 @@ const EnumTable<V2MessageType> EnumTable<V2MessageType>::instance(
{V2MessageType::kQueueRemove, "QUEUE_REMOVE"},
{V2MessageType::kQueueReorder, "QUEUE_REORDER"},
{V2MessageType::kQueueUpdate, "QUEUE_UPDATE"},
+ {V2MessageType::kQueueNext, "QUEUE_NEXT"},
+ {V2MessageType::kQueuePrev, "QUEUE_PREV"},
{V2MessageType::kSeek, "SEEK"},
{V2MessageType::kSetVolume, "SET_VOLUME"},
{V2MessageType::kStop, "STOP"},
@@ -467,6 +469,8 @@ bool IsMediaRequestMessageType(V2MessageType type) {
case V2MessageType::kQueueRemove:
case V2MessageType::kQueueReorder:
case V2MessageType::kQueueUpdate:
+ case V2MessageType::kQueueNext:
+ case V2MessageType::kQueuePrev:
case V2MessageType::kSeek:
case V2MessageType::kStopMedia:
return true;
diff --git a/chromium/components/cast_channel/cast_message_util.h b/chromium/components/cast_channel/cast_message_util.h
index 541c690e136..aff239972f5 100644
--- a/chromium/components/cast_channel/cast_message_util.h
+++ b/chromium/components/cast_channel/cast_message_util.h
@@ -68,6 +68,8 @@ enum class V2MessageType {
kQueueRemove,
kQueueReorder,
kQueueUpdate,
+ kQueueNext,
+ kQueuePrev,
kSeek,
kSetVolume,
kStop,
diff --git a/chromium/components/cast_channel/cast_socket.cc b/chromium/components/cast_channel/cast_socket.cc
index 8a5bbda21c1..26ef514da5d 100644
--- a/chromium/components/cast_channel/cast_socket.cc
+++ b/chromium/components/cast_channel/cast_socket.cc
@@ -66,7 +66,7 @@ void OnConnected(
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(std::move(callback), result, local_addr, peer_addr,
std::move(receive_stream), std::move(send_stream)));
@@ -378,13 +378,12 @@ int CastSocketImpl::DoTcpConnect() {
VLOG_WITH_CONNECTION(1) << "DoTcpConnect";
SetConnectState(ConnectionState::TCP_CONNECT_COMPLETE);
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(ConnectOnUIThread, network_context_getter_,
- net::AddressList(open_params_.ip_endpoint),
- mojo::MakeRequest(&tcp_socket_),
- base::BindOnce(&CastSocketImpl::OnConnect,
- weak_factory_.GetWeakPtr())));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(ConnectOnUIThread, network_context_getter_,
+ net::AddressList(open_params_.ip_endpoint),
+ mojo::MakeRequest(&tcp_socket_),
+ base::BindOnce(&CastSocketImpl::OnConnect,
+ weak_factory_.GetWeakPtr())));
return net::ERR_IO_PENDING;
}
diff --git a/chromium/components/cast_channel/cast_socket_service.cc b/chromium/components/cast_channel/cast_socket_service.cc
index 201d19a4389..687760407ee 100644
--- a/chromium/components/cast_channel/cast_socket_service.cc
+++ b/chromium/components/cast_channel/cast_socket_service.cc
@@ -23,8 +23,8 @@ CastSocketService::CastSocketService()
// (1) ChromeURLRequestContextGetter::GetURLRequestContext, which is
// called by CastMediaSinkServiceImpl, must run on IO thread. (2) Parts of
// CastChannel extension API functions run on IO thread.
- task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::IO})) {}
+ task_runner_(
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})) {}
// This is a leaky singleton and the dtor won't be called.
CastSocketService::~CastSocketService() = default;
diff --git a/chromium/components/cast_channel/cast_socket_service_unittest.cc b/chromium/components/cast_channel/cast_socket_service_unittest.cc
index 4ef0bedf1d0..1ee3758a013 100644
--- a/chromium/components/cast_channel/cast_socket_service_unittest.cc
+++ b/chromium/components/cast_channel/cast_socket_service_unittest.cc
@@ -3,11 +3,12 @@
// found in the LICENSE file.
#include "components/cast_channel/cast_socket_service.h"
+
#include "base/memory/ptr_util.h"
#include "base/test/mock_callback.h"
#include "base/test/test_simple_task_runner.h"
#include "components/cast_channel/cast_test_util.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +37,7 @@ class CastSocketServiceTest : public testing::Test {
void TearDown() override { cast_socket_service_ = nullptr; }
protected:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<CastSocketService> cast_socket_service_;
base::MockCallback<CastSocket::OnOpenCallback> mock_on_open_callback_;
MockCastSocketObserver mock_observer_;
diff --git a/chromium/components/cast_channel/cast_socket_unittest.cc b/chromium/components/cast_channel/cast_socket_unittest.cc
index c899a88f661..8942f08caea 100644
--- a/chromium/components/cast_channel/cast_socket_unittest.cc
+++ b/chromium/components/cast_channel/cast_socket_unittest.cc
@@ -32,7 +32,7 @@
#include "components/cast_channel/cast_transport.h"
#include "components/cast_channel/logger.h"
#include "components/cast_channel/proto/cast_channel.pb.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "crypto/rsa_private_key.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
@@ -371,7 +371,7 @@ class TestSocketFactory : public net::ClientSocketFactory {
class CastSocketTestBase : public testing::Test {
protected:
CastSocketTestBase()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
url_request_context_(true),
logger_(new Logger()),
observer_(new MockCastSocketObserver()),
@@ -400,7 +400,7 @@ class CastSocketTestBase : public testing::Test {
TestSocketFactory* client_socket_factory() { return &client_socket_factory_; }
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
net::TestURLRequestContext url_request_context_;
std::unique_ptr<network::NetworkContext> network_context_;
network::mojom::NetworkContextPtr network_context_ptr_;
diff --git a/chromium/components/cast_channel/cast_transport_unittest.cc b/chromium/components/cast_channel/cast_transport_unittest.cc
index 1b3fb379ea2..1879fbb35b5 100644
--- a/chromium/components/cast_channel/cast_transport_unittest.cc
+++ b/chromium/components/cast_channel/cast_transport_unittest.cc
@@ -14,8 +14,8 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/cast_channel/cast_framer.h"
#include "components/cast_channel/cast_socket.h"
#include "components/cast_channel/cast_test_util.h"
@@ -166,7 +166,7 @@ class CastTransportTest : public testing::Test {
run_loop.RunUntilIdle();
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockCastTransportDelegate* delegate_;
MockSocket mock_socket_;
Logger* logger_;
diff --git a/chromium/components/cast_channel/keep_alive_delegate_unittest.cc b/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
index 7b4c25cb669..86577139d92 100644
--- a/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
+++ b/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/timer/mock_timer.h"
@@ -98,7 +98,7 @@ class KeepAliveDelegateTest : public testing::Test {
run_loop.RunUntilIdle();
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockCastSocket socket_;
std::unique_ptr<KeepAliveDelegate> keep_alive_;
scoped_refptr<Logger> logger_;
diff --git a/chromium/components/cbor/OWNERS b/chromium/components/cbor/OWNERS
index c2ed450520b..e2dc046867b 100644
--- a/chromium/components/cbor/OWNERS
+++ b/chromium/components/cbor/OWNERS
@@ -1,3 +1,5 @@
jochen@chromium.org
engedy@chromium.org
file://base/SECURITY_OWNERS
+# COMPONENT: Blink>WebAuthentication
+# TEAM: security-dev@chromium.org
diff --git a/chromium/components/cdm/browser/BUILD.gn b/chromium/components/cdm/browser/BUILD.gn
index e0458ff80bf..2ea9d0b06ed 100644
--- a/chromium/components/cdm/browser/BUILD.gn
+++ b/chromium/components/cdm/browser/BUILD.gn
@@ -15,7 +15,7 @@ jumbo_source_set("browser") {
public_deps = [
"//base",
"//content/public/browser",
- "//media/mojo/interfaces",
+ "//media/mojo/mojom",
"//url",
]
diff --git a/chromium/components/cdm/browser/cdm_message_filter_android.cc b/chromium/components/cdm/browser/cdm_message_filter_android.cc
index ac361329c43..b5672631fdf 100644
--- a/chromium/components/cdm/browser/cdm_message_filter_android.cc
+++ b/chromium/components/cdm/browser/cdm_message_filter_android.cc
@@ -140,8 +140,9 @@ CdmMessageFilterAndroid::CdmMessageFilterAndroid(
bool can_persist_data,
bool force_to_support_secure_codecs)
: BrowserMessageFilter(EncryptedMediaMsgStart),
- task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
+ task_runner_(
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE})),
can_persist_data_(can_persist_data),
force_to_support_secure_codecs_(force_to_support_secure_codecs) {}
diff --git a/chromium/components/cdm/browser/media_drm_storage_impl.cc b/chromium/components/cdm/browser/media_drm_storage_impl.cc
index 59ed7240f79..8a13b32ac20 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl.cc
+++ b/chromium/components/cdm/browser/media_drm_storage_impl.cc
@@ -658,8 +658,7 @@ MediaDrmStorageImpl::MediaDrmStorageImpl(
: FrameServiceBase(render_frame_host, std::move(request)),
pref_service_(pref_service),
get_origin_id_cb_(get_origin_id_cb),
- allow_empty_origin_id_cb_(allow_empty_origin_id_cb),
- weak_factory_(this) {
+ allow_empty_origin_id_cb_(allow_empty_origin_id_cb) {
DVLOG(1) << __func__ << ": origin = " << origin();
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(pref_service_);
diff --git a/chromium/components/cdm/browser/media_drm_storage_impl.h b/chromium/components/cdm/browser/media_drm_storage_impl.h
index 009668d4c77..77f1c4b9b80 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl.h
+++ b/chromium/components/cdm/browser/media_drm_storage_impl.h
@@ -18,7 +18,7 @@
#include "content/public/browser/frame_service_base.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
-#include "media/mojo/interfaces/media_drm_storage.mojom.h"
+#include "media/mojo/mojom/media_drm_storage.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -131,7 +131,7 @@ class MediaDrmStorageImpl final
bool is_initialized_ = false;
// NOTE: Weak pointers must be invalidated before all other member variables.
- base::WeakPtrFactory<MediaDrmStorageImpl> weak_factory_;
+ base::WeakPtrFactory<MediaDrmStorageImpl> weak_factory_{this};
};
} // namespace cdm
diff --git a/chromium/components/cdm/renderer/widevine_key_system_properties.cc b/chromium/components/cdm/renderer/widevine_key_system_properties.cc
index fc87bc182ef..f316475cecf 100644
--- a/chromium/components/cdm/renderer/widevine_key_system_properties.cc
+++ b/chromium/components/cdm/renderer/widevine_key_system_properties.cc
@@ -99,19 +99,27 @@ EmeConfigRule WidevineKeySystemProperties::GetEncryptionSchemeConfigRule(
return EmeConfigRule::NOT_SUPPORTED;
}
+static SupportedCodecs OverrideAv1SupportIfNeeded(SupportedCodecs codecs) {
+ auto result = codecs;
+
+ // Enable AV1 if force-support is enabled.
+ if (base::FeatureList::IsEnabled(media::kWidevineAv1ForceSupportForTesting))
+ result |= media::EME_CODEC_AV1;
+
+ // Disable AV1 if the master switch kWidevineAv1 is disabled.
+ if (!base::FeatureList::IsEnabled(media::kWidevineAv1))
+ result &= ~media::EME_CODEC_AV1;
+
+ return result;
+}
+
SupportedCodecs WidevineKeySystemProperties::GetSupportedCodecs() const {
- // Disable AV1 if feature kWidevineAv1 is disabled
- return base::FeatureList::IsEnabled(media::kWidevineAv1)
- ? codecs_
- : (codecs_ & ~media::EME_CODEC_AV1);
+ return OverrideAv1SupportIfNeeded(codecs_);
}
SupportedCodecs WidevineKeySystemProperties::GetSupportedHwSecureCodecs()
const {
- // Disable AV1 if feature kWidevineAv1 is disabled
- return base::FeatureList::IsEnabled(media::kWidevineAv1)
- ? hw_secure_codecs_
- : (hw_secure_codecs_ & ~media::EME_CODEC_AV1);
+ return OverrideAv1SupportIfNeeded(hw_secure_codecs_);
}
EmeConfigRule WidevineKeySystemProperties::GetRobustnessConfigRule(
diff --git a/chromium/components/certificate_transparency/chrome_ct_policy_enforcer.h b/chromium/components/certificate_transparency/chrome_ct_policy_enforcer.h
index 053cbacd7cc..4e10ca9bb4b 100644
--- a/chromium/components/certificate_transparency/chrome_ct_policy_enforcer.h
+++ b/chromium/components/certificate_transparency/chrome_ct_policy_enforcer.h
@@ -45,6 +45,19 @@ class ChromeCTPolicyEnforcer : public net::CTPolicyEnforcer {
void SetClockForTesting(const base::Clock* clock) { clock_ = clock; }
+ // TODO(https://crbug.com/999240): These are exposed to allow end-to-end
+ // testing by higher layers (i.e. that the ChromeCTPolicyEnforcer is
+ // correctly constructed). When either this issue or https://crbug.com/848277
+ // are fixed, the configuration can be tested independently, and these can
+ // be removed.
+ const std::vector<std::string>& operated_by_google_logs_for_testing() {
+ return operated_by_google_logs_;
+ }
+ const std::vector<std::pair<std::string, base::TimeDelta>>&
+ disqualified_logs_for_testing() {
+ return disqualified_logs_;
+ }
+
private:
// Returns true if the log identified by |log_id| (the SHA-256 hash of the
// log's DER-encoded SPKI) has been disqualified, and sets
diff --git a/chromium/components/certificate_transparency/chrome_require_ct_delegate_unittest.cc b/chromium/components/certificate_transparency/chrome_require_ct_delegate_unittest.cc
index b0df303ce07..4b9ce4dcd35 100644
--- a/chromium/components/certificate_transparency/chrome_require_ct_delegate_unittest.cc
+++ b/chromium/components/certificate_transparency/chrome_require_ct_delegate_unittest.cc
@@ -10,7 +10,7 @@
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_message_loop.h"
#include "base/values.h"
#include "components/certificate_transparency/pref_names.h"
@@ -39,8 +39,8 @@ class ChromeRequireCTDelegateTest : public ::testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
scoped_refptr<net::X509Certificate> cert_;
net::HashValueVector hashes_;
};
diff --git a/chromium/components/certificate_transparency/data/log_list.json b/chromium/components/certificate_transparency/data/log_list.json
index b2f2a41683e..8b3da9b6a3c 100644
--- a/chromium/components/certificate_transparency/data/log_list.json
+++ b/chromium/components/certificate_transparency/data/log_list.json
@@ -11,11 +11,10 @@
"log_id": "Y/Lbzeg7zCzPC3KEJ1drM6SNYXePvXWmOLHHaFRL2I0=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEI3MQm+HzXvaYa2mVlhB4zknbtAT8cSxakmBoJcBKGqGwYS0bhxSpuvABM1kdBTDpQhXnVdcq+LSiukXJRpGHVg==",
"url": "https://ct.googleapis.com/logs/argon2019/",
- "dns": "argon2019.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-02-27T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-06-15T02:30:13Z"
}
},
"temporal_interval": {
@@ -28,11 +27,10 @@
"log_id": "sh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+LkF4=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6Tx2p1yKY4015NyIYvdrk36es0uAc1zA4PQ+TGRY+3ZjUTIYY9Wyu+3q/147JG4vNVKLtDWarZwVqGkg6lAYzA==",
"url": "https://ct.googleapis.com/logs/argon2020/",
- "dns": "argon2020.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-02-27T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-06-15T02:30:13Z"
}
},
"temporal_interval": {
@@ -45,11 +43,10 @@
"log_id": "9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOM=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETeBmZOrzZKo4xYktx9gI2chEce3cw/tbr5xkoQlmhB18aKfsxD+MnILgGNl0FOm0eYGilFVi85wLRIOhK8lxKw==",
"url": "https://ct.googleapis.com/logs/argon2021/",
- "dns": "argon2021.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-02-27T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-06-15T02:30:13Z"
}
},
"temporal_interval": {
@@ -58,15 +55,46 @@
}
},
{
+ "description": "Google 'Argon2022' log",
+ "log_id": "KXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4Q=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeIPc6fGmuBg6AJkv/z7NFckmHvf/OqmjchZJ6wm2qN200keRDg352dWpi7CHnSV51BpQYAj1CQY5JuRAwrrDwg==",
+ "url": "https://ct.googleapis.com/logs/argon2022/",
+ "mmd": 86400,
+ "state": {
+ "qualified": {
+ "timestamp": "2019-08-19T00:00:00Z"
+ }
+ },
+ "temporal_interval": {
+ "start_inclusive": "2022-01-01T00:00:00Z",
+ "end_exclusive": "2023-01-01T00:00:00Z"
+ }
+ },
+ {
+ "description": "Google 'Argon2023' log",
+ "log_id": "6D7Q2j71BjUy51covIlryQPTy9ERa+zraeF3fW0GvW4=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0JCPZFJOQqyEti5M8j13ALN3CAVHqkVM4yyOcKWCu2yye5yYeqDpEXYoALIgtM3TmHtNlifmt+4iatGwLpF3eA==",
+ "url": "https://ct.googleapis.com/logs/argon2023/",
+ "mmd": 86400,
+ "state": {
+ "qualified": {
+ "timestamp": "2019-08-19T00:00:00Z"
+ }
+ },
+ "temporal_interval": {
+ "start_inclusive": "2023-01-01T00:00:00Z",
+ "end_exclusive": "2024-01-01T00:00:00Z"
+ }
+ },
+ {
"description": "Google 'Xenon2019' log",
"log_id": "CEEUmABxUywWGQRgvPxH/cJlOvopLHKzf/hjrinMyfA=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/XyDwqzXL9i2GTjMYkqaEyiRL0Dy9sHq/BTebFdshbvCaXXEh6mjUK0Yy+AsDcI4MpzF1l7Kded2MD5zi420gA==",
"url": "https://ct.googleapis.com/logs/xenon2019/",
- "dns": "xenon2019.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2019-02-21T00:00:00Z"
+ "usable": {
+ "timestamp": "2019-06-17T21:23:01Z"
}
},
"temporal_interval": {
@@ -79,11 +107,10 @@
"log_id": "B7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohw=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZU75VqjyzSTgFZKAnWg1QeYfFFIRZTMK7q3kWWZsmHhQdrBYnHRZ3OA4kUeUx0JN+xX+dSgt1ruqUhhl7jOvmw==",
"url": "https://ct.googleapis.com/logs/xenon2020/",
- "dns": "xenon2020.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2019-02-21T00:00:00Z"
+ "usable": {
+ "timestamp": "2019-06-17T21:23:01Z"
}
},
"temporal_interval": {
@@ -96,11 +123,10 @@
"log_id": "fT7y+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8Nc=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER+1MInu8Q39BwDZ5Rp9TwXhwm3ktvgJzpk/r7dDgGk7ZacMm3ljfcoIvP1E72T8jvyLT1bvdapylajZcTH6W5g==",
"url": "https://ct.googleapis.com/logs/xenon2021/",
- "dns": "xenon2021.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2019-02-21T00:00:00Z"
+ "usable": {
+ "timestamp": "2019-06-17T21:23:01Z"
}
},
"temporal_interval": {
@@ -113,11 +139,10 @@
"log_id": "RqVV63X6kSAwtaKJafTzfREsQXS+/Um4havy/HD+bUc=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+WS9FSxAYlCVEzg8xyGwOrmPonoV14nWjjETAIdZvLvukPzIWBMKv6tDNlQjpIHNrUcUt1igRPpqoKDXw2MeKw==",
"url": "https://ct.googleapis.com/logs/xenon2022/",
- "dns": "xenon2022.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2019-02-21T00:00:00Z"
+ "usable": {
+ "timestamp": "2019-06-17T21:23:01Z"
}
},
"temporal_interval": {
@@ -126,11 +151,26 @@
}
},
{
+ "description": "Google 'Xenon2023' log",
+ "log_id": "rfe++nz/EMiLnT2cHj4YarRnKV3PsQwkyoWGNOvcgoo=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEchY+C+/vzj5g3ZXLY3q5qY1Kb2zcYYCmRV4vg6yU84WI0KV00HuO/8XuQqLwLZPjwtCymeLhQunSxgAnaXSuzg==",
+ "url": "https://ct.googleapis.com/logs/xenon2023/",
+ "mmd": 86400,
+ "state": {
+ "qualified": {
+ "timestamp": "2019-08-19T00:00:00Z"
+ }
+ },
+ "temporal_interval": {
+ "start_inclusive": "2023-01-01T00:00:00Z",
+ "end_exclusive": "2024-01-01T00:00:00Z"
+ }
+ },
+ {
"description": "Google 'Aviator' log",
"log_id": "aPaY+B9kgr46jO65KB1M/HFRXWeT1ETRCmesu09P+8Q=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1/TMabLkDpCjiupacAlP7xNi0I1JYP8bQFAHDG1xhtolSY1l4QgNRzRrvSe8liE+NPWHdjGxfx3JhTsN9x8/6Q==",
"url": "https://ct.googleapis.com/aviator/",
- "dns": "aviator.ct.googleapis.com",
"mmd": 86400,
"state": {
"readonly": {
@@ -147,11 +187,10 @@
"log_id": "KTxRllTIOWW6qlD8WAfUt2+/WHopctykwwz05UVH9Hg=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETtK8v7MICve56qTHHDhhBOuV4IlUaESxZryCfk9QbG9co/CqPvTsgPDbCpp6oFtyAHwlDhnvr7JijXRD9Cb2FA==",
"url": "https://ct.googleapis.com/icarus/",
- "dns": "icarus.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2016-11-03T12:09:00Z"
+ "usable": {
+ "timestamp": "2017-03-06T19:35:01Z"
}
}
},
@@ -160,11 +199,10 @@
"log_id": "pLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BA=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfahLEimAoz2t01p3uMziiLOl/fHTDM0YDOhBRuiBARsV4UvxG2LdNgoIGLrtCzWE0J5APC2em4JlvR8EEEFMoA==",
"url": "https://ct.googleapis.com/pilot/",
- "dns": "pilot.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2014-06-27T18:22:00Z"
+ "usable": {
+ "timestamp": "2014-09-02T20:41:44Z"
}
}
},
@@ -173,11 +211,10 @@
"log_id": "7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/cs=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIFsYyDzBi7MxCAC/oJBXK7dHjG+1aLCOkHjpoHPqTyghLpzA9BYbqvnV16mAw04vUjyYASVGJCUoI3ctBcJAeg==",
"url": "https://ct.googleapis.com/rocketeer/",
- "dns": "rocketeer.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2015-03-26T12:12:00Z"
+ "usable": {
+ "timestamp": "2015-08-04T19:00:05Z"
}
}
},
@@ -186,11 +223,10 @@
"log_id": "u9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e0YU=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEmyGDvYXsRJsNyXSrYc9DjHsIa2xzb4UR7ZxVoV6mrc9iZB7xjI6+NrOiwH+P/xxkRmOFG6Jel20q37hTh58rA==",
"url": "https://ct.googleapis.com/skydiver/",
- "dns": "skydiver.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2016-11-03T12:09:00Z"
+ "usable": {
+ "timestamp": "2017-03-06T19:35:01Z"
}
}
}
@@ -212,11 +248,10 @@
"log_id": "dH7agzGtMxCRIZzOJU9CcMK//V5CIAjGNzV55hB7zFY=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkZHz1v5r8a9LmXSMegYZAg4UW+Ug56GtNfJTDNFZuubEJYgWf4FcC5D+ZkYwttXTDSo4OkanG9b3AI4swIQ28g==",
"url": "https://ct.cloudflare.com/logs/nimbus2019/",
- "dns": "cloudflare-nimbus2019.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-02-12T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-06-15T02:30:13Z"
}
},
"temporal_interval": {
@@ -229,11 +264,10 @@
"log_id": "Xqdz+d9WwOe1Nkh90EngMnqRmgyEoRIShBh1loFxRVg=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01EAhx4o0zPQrXTcYjgCt4MVFsT0Pwjzb1RwrM0lhWDlxAYPP6/gyMCXNkOn/7KFsjL7rwk78tHMpY8rXn8AYg==",
"url": "https://ct.cloudflare.com/logs/nimbus2020/",
- "dns": "cloudflare-nimbus2020.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-02-12T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-06-15T02:30:13Z"
}
},
"temporal_interval": {
@@ -246,11 +280,10 @@
"log_id": "RJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9MzlrW2gag=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExpon7ipsqehIeU1bmpog9TFo4Pk8+9oN8OYHl1Q2JGVXnkVFnuuvPgSo2Ep+6vLffNLcmEbxOucz03sFiematg==",
"url": "https://ct.cloudflare.com/logs/nimbus2021/",
- "dns": "cloudflare-nimbus2021.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-02-12T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-06-15T02:30:13Z"
}
},
"temporal_interval": {
@@ -263,7 +296,6 @@
"log_id": "QcjKsd8iRkoQxqE6CUKHXk4xixsD6+tLx2jwkGKWBvY=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESLJHTlAycmJKDQxIv60pZG8g33lSYxYpCi5gteI6HLevWbFVCdtZx+m9b+0LrwWWl/87mkNN6xE0M4rnrIPA/w==",
"url": "https://ct.cloudflare.com/logs/nimbus2022/",
- "dns": "cloudflare-nimbus2022.ct.googleapis.com",
"mmd": 86400,
"state": {
"qualified": {
@@ -280,7 +312,6 @@
"log_id": "ejKMVNi3LbYg6jjgUh7phBZwMhOFTTvSK8E6V6NS61I=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi/8tkhjLRp0SXrlZdTzNkTd6HqmcmXiDJz3fAdWLgOhjmv4mohvRhwXul9bgW0ODgRwC9UGAgH/vpGHPvIS1qA==",
"url": "https://ct.cloudflare.com/logs/nimbus2023/",
- "dns": "cloudflare-nimbus2023.ct.googleapis.com",
"mmd": 86400,
"state": {
"qualified": {
@@ -305,11 +336,10 @@
"log_id": "VhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAkbFvhu7gkAW6MHSrBlpE1n4+HCFRkC5OLAjgqhkTH+/uzSfSl8ois8ZxAD2NgaTZe1M9akhYlrYkes4JECs6A==",
"url": "https://ct1.digicert-ct.com/log/",
- "dns": "digicert.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2015-01-01T01:41:00Z"
+ "usable": {
+ "timestamp": "2015-05-20T16:40:09Z"
}
}
},
@@ -318,11 +348,10 @@
"log_id": "h3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzF05L2a4TH/BLgOhNKPoioYCrkoRxvcmajeb8Dj4XQmNY+gxa4Zmz3mzJTwe33i0qMVp+rfwgnliQ/bM/oFmhA==",
"url": "https://ct2.digicert-ct.com/log/",
- "dns": "digicert2.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2017-06-04T00:00:00Z"
+ "usable": {
+ "timestamp": "2017-10-10T00:38:10Z"
}
}
},
@@ -331,11 +360,10 @@
"log_id": "4mlLribo6UAJ6IYbtjuD1D7n/nSI+6SPKJMBnd3x2/4=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkZd/ow8X+FSVWAVSf8xzkFohcPph/x6pS1JHh7g1wnCZ5y/8Hk6jzJxs6t3YMAWz2CPd4VkCdxwKexGhcFxD9A==",
"url": "https://yeti2019.ct.digicert.com/log/",
- "dns": "digicert-yeti2019.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-04-06T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-08-24T00:53:07Z"
}
},
"temporal_interval": {
@@ -348,11 +376,10 @@
"log_id": "8JWkWfIA0YJAEC0vk4iOrUv+HUfjmeHQNKawqKqOsnM=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEURAG+Zo0ac3n37ifZKUhBFEV6jfcCzGIRz3tsq8Ca9BP/5XUHy6ZiqsPaAEbVM0uI3Tm9U24RVBHR9JxDElPmg==",
"url": "https://yeti2020.ct.digicert.com/log/",
- "dns": "digicert-yeti2020.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-04-06T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-08-24T00:53:07Z"
}
},
"temporal_interval": {
@@ -365,11 +392,10 @@
"log_id": "XNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDso=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6J4EbcpIAl1+AkSRsbhoY5oRTj3VoFfaf1DlQkfi7Rbe/HcjfVtrwN8jaC+tQDGjF+dqvKhWJAQ6Q6ev6q9Mew==",
"url": "https://yeti2021.ct.digicert.com/log/",
- "dns": "digicert-yeti2021.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-04-06T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-08-24T00:53:07Z"
}
},
"temporal_interval": {
@@ -382,11 +408,10 @@
"log_id": "IkVFB1lVJFaWP6Ev8fdthuAjJmOtwEt/XcaDXG7iDwI=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEn/jYHd77W1G1+131td5mEbCdX/1v/KiYW5hPLcOROvv+xA8Nw2BDjB7y+RGyutD2vKXStp/5XIeiffzUfdYTJg==",
"url": "https://yeti2022.ct.digicert.com/log/",
- "dns": "digicert-yeti2022.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-04-06T00:00:00Z"
+ "usable": {
+ "timestamp": "2018-08-24T00:53:07Z"
}
},
"temporal_interval": {
@@ -399,7 +424,6 @@
"log_id": "Nc8ZG7+xbFe/D61MbULLu7YnICZR6j/hKu+oA8M71kw=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfQ0DsdWYitzwFTvG3F4Nbj8Nv5XIVYzQpkyWsU4nuSYlmcwrAp6m092fsdXEw6w1BAeHlzaqrSgNfyvZaJ9y0Q==",
"url": "https://yeti2023.ct.digicert.com/log/",
- "dns": "digicert-yeti2023.ct.googleapis.com",
"mmd": 86400,
"state": {
"qualified": {
@@ -416,11 +440,10 @@
"log_id": "/kRhCLHQGreKYsz+q2qysrq/86va2ApNizDfLQAIgww=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEX+0nudCKImd7QCtelhMrDW0OXni5RE10tiiClZesmrwUk2iHLCoTHHVV+yg5D4n/rxCRVyRhikPpVDOLMLxJaA==",
"url": "https://nessie2019.ct.digicert.com/log/",
- "dns": "digicert-nessie2019.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-11-06T03:47:10Z"
+ "usable": {
+ "timestamp": "2019-05-09T22:11:02Z"
}
},
"temporal_interval": {
@@ -433,11 +456,10 @@
"log_id": "xlKg7EjOs/yrFwmSxDqHQTMJ6ABlomJSQBujNioXxWU=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4hHIyMVIrR9oShgbQMYEk8WX1lmkfFKB448Gn93KbsZnnwljDHY6MQqEnWfKGgMOq0gh3QK48c5ZB3UKSIFZ4g==",
"url": "https://nessie2020.ct.digicert.com/log/",
- "dns": "digicert-nessie2020.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-11-06T03:47:10Z"
+ "usable": {
+ "timestamp": "2019-05-09T22:11:02Z"
}
},
"temporal_interval": {
@@ -450,11 +472,10 @@
"log_id": "7sCV7o1yZA+S48O5G8cSo2lqCXtLahoUOOZHssvtxfk=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9o7AiwrbGBIX6Lnc47I6OfLMdZnRzKoP5u072nBi6vpIOEooktTi1gNwlRPzGC2ySGfuc1xLDeaA/wSFGgpYFg==",
"url": "https://nessie2021.ct.digicert.com/log/",
- "dns": "digicert-nessie2021.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-11-06T03:47:10Z"
+ "usable": {
+ "timestamp": "2019-05-09T22:11:02Z"
}
},
"temporal_interval": {
@@ -467,11 +488,10 @@
"log_id": "UaOw9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeU=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJyTdaAMoy/5jvg4RR019F2ihEV1McclBKMe2okuX7MCv/C87v+nxsfz1Af+p+0lADGMkmNd5LqZVqxbGvlHYcQ==",
"url": "https://nessie2022.ct.digicert.com/log/",
- "dns": "digicert-nessie2022.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2018-11-06T03:47:10Z"
+ "usable": {
+ "timestamp": "2019-05-09T22:11:02Z"
}
},
"temporal_interval": {
@@ -484,7 +504,6 @@
"log_id": "s3N3B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZo=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEXu8iQwSCRSf2CbITGpUpBtFVt8+I0IU0d1C36Lfe1+fbwdaI0Z5FktfM2fBoI1bXBd18k2ggKGYGgdZBgLKTg==",
"url": "https://nessie2023.ct.digicert.com/log/",
- "dns": "digicert-nessie2023.ct.googleapis.com",
"mmd": 86400,
"state": {
"qualified": {
@@ -501,7 +520,6 @@
"log_id": "3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvsw=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEluqsHEYMG1XcDfy1lCdGV0JwOmkY4r87xNuroPS2bMBTP01CEDPwWJePa75y9CrsHEKqAy8afig1dpkIPSEUhg==",
"url": "https://ct.ws.symantec.com/",
- "dns": "symantec.ct.googleapis.com",
"mmd": 86400,
"state": {
"retired": {
@@ -514,7 +532,6 @@
"log_id": "vHjh38X2PGhGSTNNoQ+hXwl5aSAJwIG08/aRfz7ZuKU=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6pWeAv/u8TNtS4e8zf0ZF2L/lNPQWQc/Ai0ckP7IRzA78d0NuBEMXR2G3avTK0Zm+25ltzv9WWis36b4ztIYTQ==",
"url": "https://vega.ws.symantec.com/",
- "dns": "symantec-vega.ct.googleapis.com",
"mmd": 86400,
"state": {
"retired": {
@@ -527,7 +544,6 @@
"log_id": "FZcEiNe5l6Bb61JRKt7o0ui0oxZSZBIan6v71fha2T8=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEowJkhCK7JewN47zCyYl93UXQ7uYVhY/Z5xcbE4Dq7bKFN61qxdglnfr0tPNuFiglN+qjN2Syxwv9UeXBBfQOtQ==",
"url": "https://sirius.ws.symantec.com/",
- "dns": "symantec-sirius.ct.googleapis.com",
"mmd": 86400,
"state": {
"retired": {
@@ -620,7 +636,6 @@
"log_id": "AwGd8/2FppqOvR+sxtqbpz5Gl3T+d/V5/FoIuDKMHWs=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjicnerZVCXTrbEuUhGW85BXx6lrYfA43zro/bAna5ymW00VQb94etBzSg4j/KS/Oqf/fNN51D8DMGA2ULvw3AQ==",
"url": "https://ctlog-gen2.api.venafi.com/",
- "dns": "venafi2.ct.googleapis.com",
"mmd": 86400,
"state": {
"readonly": {
@@ -685,11 +700,10 @@
"log_id": "VYHUwhaQNgFK6gubVzxT8MDkOHhwJQgXL6OqHQcT0ww=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8m/SiQ8/xfiHHqtls9m7FyOMBg4JVZY9CgiixXGz0akvKD6DEL8S0ERmFe9U4ZiA0M4kbT5nmuk3I85Sk4bagA==",
"url": "https://sabre.ct.comodo.com/",
- "dns": "comodo-sabre.ct.googleapis.com",
"mmd": 86400,
"state": {
- "qualified": {
- "timestamp": "2017-06-20T00:00:00Z"
+ "usable": {
+ "timestamp": "2017-10-10T00:38:10Z"
}
}
},
@@ -698,12 +712,83 @@
"log_id": "b1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RM=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7+R9dC4VFbbpuyOL+yy14ceAmEf7QGlo/EmtYU6DRzwat43f/3swtLr/L8ugFOOt1YU/RFmMjGCL17ixv66MZw==",
"url": "https://mammoth.ct.comodo.com/",
- "dns": "comodo-mammoth.ct.googleapis.com",
+ "mmd": 86400,
+ "state": {
+ "usable": {
+ "timestamp": "2017-10-10T00:38:10Z"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "Let's Encrypt",
+ "email": [
+ "sre@letsencrypt.org"
+ ],
+ "logs": [
+ {
+ "description": "Let's Encrypt 'Oak2019' log",
+ "log_id": "ZZszUPQ7EsxepatOx2XT/ebIgkN3d3jnIAP56yuMMSk=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFkqNKRuZ+Z8IOsnNJrUZ8gwp+KKGOdQrJ/HKhSadK/SJuoCc9+dxQ7awpmWIMr9SKcQeG5uRzG1kVSyFN4Wfcw==",
+ "url": "https://oak.ct.letsencrypt.org/2019/",
"mmd": 86400,
"state": {
"qualified": {
- "timestamp": "2017-06-20T00:00:00Z"
+ "timestamp": "2019-10-02T00:00:00Z"
}
+ },
+ "temporal_interval": {
+ "start_inclusive": "2019-01-01T00:00:00Z",
+ "end_exclusive": "2020-01-07T00:00:00Z"
+ }
+ },
+ {
+ "description": "Let's Encrypt 'Oak2020' log",
+ "log_id": "5xLysDd+GmL7jskMYYTx6ns3y1YdESZb8+DzS/JBVG4=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfzb42Zdr/h7hgqgDCo1vrNJqGqbcUvJGJEER9DDqp19W/wFSB0l166hD+U5cAXchpH8ZkBNUuvOHS0OnJ4oJrQ==",
+ "url": "https://oak.ct.letsencrypt.org/2020/",
+ "mmd": 86400,
+ "state": {
+ "qualified": {
+ "timestamp": "2019-10-02T00:00:00Z"
+ }
+ },
+ "temporal_interval": {
+ "start_inclusive": "2020-01-01T00:00:00Z",
+ "end_exclusive": "2021-01-07T00:00:00Z"
+ }
+ },
+ {
+ "description": "Let's Encrypt 'Oak2021' log",
+ "log_id": "lCC8Ho7VjWyIcx+CiyIsDdHaTV5sT5Q9YdtOL1hNosI=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELsYzGMNwo8rBIlaklBIdmD2Ofn6HkfrjK0Ukz1uOIUC6Lm0jTITCXhoIdjs7JkyXnwuwYiJYiH7sE1YeKu8k9w==",
+ "url": "https://oak.ct.letsencrypt.org/2021/",
+ "mmd": 86400,
+ "state": {
+ "qualified": {
+ "timestamp": "2019-10-02T00:00:00Z"
+ }
+ },
+ "temporal_interval": {
+ "start_inclusive": "2021-01-01T00:00:00Z",
+ "end_exclusive": "2022-01-07T00:00:00Z"
+ }
+ },
+ {
+ "description": "Let's Encrypt 'Oak2022' log",
+ "log_id": "36Veq2iCTx9sre64X04+WurNohKkal6OOxLAIERcKnM=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhjyxDVIjWt5u9sB/o2S8rcGJ2pdZTGA8+IpXhI/tvKBjElGE5r3de4yAfeOPhqTqqc+o7vPgXnDgu/a9/B+RLg==",
+ "url": "https://oak.ct.letsencrypt.org/2022/",
+ "mmd": 86400,
+ "state": {
+ "qualified": {
+ "timestamp": "2019-10-02T00:00:00Z"
+ }
+ },
+ "temporal_interval": {
+ "start_inclusive": "2022-01-01T00:00:00Z",
+ "end_exclusive": "2023-01-07T00:00:00Z"
}
}
]
diff --git a/chromium/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap b/chromium/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap
index 41db7ceee23..3f6702bf106 100644
--- a/chromium/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap
+++ b/chromium/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap
@@ -15,7 +15,7 @@ sources = [
]
type_mappings = [
- "chrome_cleaner.mojom.FilePath=base::FilePath",
- "chrome_cleaner.mojom.RegistryKey=base::string16",
- "chrome_cleaner.mojom.ExtensionId=base::string16",
+ "chrome_cleaner.mojom.FilePath=::base::FilePath",
+ "chrome_cleaner.mojom.RegistryKey=::base::string16",
+ "chrome_cleaner.mojom.ExtensionId=::base::string16",
]
diff --git a/chromium/components/chromeos_camera/BUILD.gn b/chromium/components/chromeos_camera/BUILD.gn
index afead10c0c1..95f048c3a7d 100644
--- a/chromium/components/chromeos_camera/BUILD.gn
+++ b/chromium/components/chromeos_camera/BUILD.gn
@@ -6,6 +6,8 @@ import("//build/config/ui.gni")
import("//media/gpu/args.gni")
import("//testing/test.gni")
+assert(is_chromeos)
+
source_set("jpeg_encode_accelerator") {
sources = [
"jpeg_encode_accelerator.cc",
@@ -46,6 +48,24 @@ source_set("mojo_mjpeg_decode_accelerator") {
]
}
+source_set("utils") {
+ sources = [
+ "dmabuf_utils.cc",
+ "dmabuf_utils.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//components/chromeos_camera/common",
+ "//media",
+ "//ui/gfx/geometry",
+ ]
+
+ deps = [
+ "//mojo/public/cpp/system",
+ ]
+}
+
# TODO(crbug.com/960243): Don't compile these codes for build without vaapi/v4l2
# supported.
source_set("jpeg_encode_accelerator_service") {
@@ -66,6 +86,7 @@ source_set("jpeg_encode_accelerator_service") {
deps = [
":jpeg_encode_accelerator",
+ ":utils",
"//components/chromeos_camera/common",
"//media",
"//media/gpu:buildflags",
@@ -101,6 +122,7 @@ source_set("mjpeg_decode_accelerator_service") {
deps = [
":mjpeg_decode_accelerator",
+ ":utils",
"//components/chromeos_camera/common",
"//media",
"//media/gpu:buildflags",
@@ -179,6 +201,8 @@ test("jpeg_decode_accelerator_unittest") {
":mjpeg_decode_accelerator_service",
"//base",
"//media:test_support",
+ "//media/capture:chromeos_test_utils",
+ "//media/gpu",
"//media/gpu:buildflags",
"//media/gpu/test:helpers",
"//media/parsers",
@@ -206,6 +230,7 @@ test("jpeg_decode_accelerator_unittest") {
deps += [
"//media/gpu/vaapi",
"//media/gpu/vaapi:jpeg_decoder_unit_test",
+
# TODO(crbug.com/986074): we should move this to its own executable, but
# this would imply creating a new Tast wrapper in Chrome OS. So, for
# convenience, we make the WebP tests run with the
diff --git a/chromium/components/chromeos_camera/OWNERS b/chromium/components/chromeos_camera/OWNERS
index f92472c6caa..63bd9523ba5 100644
--- a/chromium/components/chromeos_camera/OWNERS
+++ b/chromium/components/chromeos_camera/OWNERS
@@ -1,5 +1,4 @@
jcliang@chromium.org
-shenghao@chromium.org
shik@chromium.org
wtlee@chromium.org
@@ -8,4 +7,4 @@ chfremer@chromium.org
mcasas@chromium.org
# TEAM: chromeos-camera@chromium.org
-# COMPONENT: OS>Kernel>Camera \ No newline at end of file
+# COMPONENT: OS>Kernel>Camera
diff --git a/chromium/components/chromeos_camera/common/BUILD.gn b/chromium/components/chromeos_camera/common/BUILD.gn
index 66985d28ff3..d49f9e78888 100644
--- a/chromium/components/chromeos_camera/common/BUILD.gn
+++ b/chromium/components/chromeos_camera/common/BUILD.gn
@@ -6,16 +6,14 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("common") {
sources = [
+ "dmabuf.mojom",
"jpeg_encode_accelerator.mojom",
"mjpeg_decode_accelerator.mojom",
]
public_deps = [
- "//media/mojo/interfaces",
+ "//media/mojo/mojom",
"//mojo/public/mojom/base",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
]
-
- # TODO(https://crbug.com/968369): Change to use new names.
- use_old_js_lite_bindings_names = true
}
diff --git a/chromium/components/chromeos_camera/common/dmabuf.mojom b/chromium/components/chromeos_camera/common/dmabuf.mojom
new file mode 100644
index 00000000000..aa946be8cb3
--- /dev/null
+++ b/chromium/components/chromeos_camera/common/dmabuf.mojom
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chromeos_camera.mojom;
+
+import "media/mojo/mojom/media_types.mojom";
+
+// This structure defines a DMA-buf buffer plane. |fd_handle| holds the DMA-buf
+// file descriptor. The layout is specified by |stride|, |offset| and |size|.
+struct DmaBufPlane {
+ handle fd_handle;
+ int32 stride;
+ uint32 offset;
+ uint32 size;
+};
+
+// This structure defines a simplified version of media::VideoFrame backed by
+// DMA-bufs (see media/base/video_frame.h) for Chrome OS usage. The video frame
+// has pixel format |format| and coded size |coded_width|x|coded_height|.
+// Per-plane DMA-buf FDs and layouts are defined in |planes|.
+struct DmaBufVideoFrame {
+ media.mojom.VideoPixelFormat format;
+ uint32 coded_width;
+ uint32 coded_height;
+ array<DmaBufPlane> planes;
+};
diff --git a/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.mojom b/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.mojom
index 8077bfb2633..18752e7edac 100644
--- a/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.mojom
+++ b/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.mojom
@@ -4,7 +4,8 @@
module chromeos_camera.mojom;
-import "media/mojo/interfaces/media_types.mojom";
+import "components/chromeos_camera/common/dmabuf.mojom";
+import "media/mojo/mojom/media_types.mojom";
// Encode errors (see components/chromeos_camera/jpeg_encode_accelerator.h).
enum EncodeStatus {
@@ -17,13 +18,6 @@ enum EncodeStatus {
PLATFORM_FAILURE,
};
-struct DmaBufPlane {
- handle fd_handle;
- int32 stride;
- uint32 offset;
- uint32 size;
-};
-
// GPU process interface exposed to the browser for encoding JPEG images.
interface JpegEncodeAccelerator {
// Initializes the JPEG encoder. Should be called once per encoder
diff --git a/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.typemap b/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.typemap
index db45a0321cc..b2bfa580a98 100644
--- a/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.typemap
+++ b/chromium/components/chromeos_camera/common/jpeg_encode_accelerator.typemap
@@ -20,4 +20,4 @@ deps = [
"//media/base/ipc",
]
-type_mappings = [ "chromeos_camera.mojom.EncodeStatus=chromeos_camera::JpegEncodeAccelerator::Status" ]
+type_mappings = [ "chromeos_camera.mojom.EncodeStatus=::chromeos_camera::JpegEncodeAccelerator::Status" ]
diff --git a/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.mojom b/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.mojom
index eea382214e6..0c96439e9b5 100644
--- a/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.mojom
+++ b/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.mojom
@@ -4,9 +4,10 @@
module chromeos_camera.mojom;
-import "media/mojo/interfaces/media_types.mojom";
+import "components/chromeos_camera/common/dmabuf.mojom";
+import "media/mojo/mojom/media_types.mojom";
import "mojo/public/mojom/base/time.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
// Decode errors (see media/video/jpeg_decode_accelerator.h).
enum DecodeError {
@@ -61,11 +62,22 @@ interface MjpegDecodeAccelerator {
// Returns |buffer_id| and |error| in a callback to notify the
// decode status. |buffer_id| is the id of |input_buffer| and |error| is the
// error code.
+ // TODO(kamesan): deprecate this function when all clients have switched to
+ // DecodeWithDmaBuf().
DecodeWithFD(int32 buffer_id, handle input_fd, uint32 input_buffer_size,
int32 coded_size_width, int32 coded_size_height,
handle output_fd, uint32 output_buffer_size)
=> (int32 buffer_id, DecodeError error);
+ // Decodes one MJPEG image with the given input and output buffers.
+ // |task_id| is used to distinguish different tasks. The input image is stored
+ // in the DMA buffer described by |src_dmabuf_fd|, |src_size|, and
+ // |src_offset|. The decoded result will be put into |dst_frame| backed by DMA
+ // buffer. Returns the decode status |error| in the Mojo callback.
+ DecodeWithDmaBuf(int32 task_id, handle src_dmabuf_fd, uint32 src_size,
+ uint32 src_offset, DmaBufVideoFrame dst_frame)
+ => (DecodeError error);
+
// TODO(c.padhi): This method might not be required, see
// http://crbug.com/699255.
Uninitialize();
diff --git a/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.typemap b/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.typemap
index eeeac224459..8deb9a83e02 100644
--- a/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.typemap
+++ b/chromium/components/chromeos_camera/common/mjpeg_decode_accelerator.typemap
@@ -24,6 +24,6 @@ deps = [
]
type_mappings = [
- "chromeos_camera.mojom.BitstreamBuffer=media::BitstreamBuffer[move_only]",
- "chromeos_camera.mojom.DecodeError=chromeos_camera::MjpegDecodeAccelerator::Error",
+ "chromeos_camera.mojom.BitstreamBuffer=::media::BitstreamBuffer[move_only]",
+ "chromeos_camera.mojom.DecodeError=::chromeos_camera::MjpegDecodeAccelerator::Error",
]
diff --git a/chromium/components/chromeos_camera/dmabuf_utils.cc b/chromium/components/chromeos_camera/dmabuf_utils.cc
new file mode 100644
index 00000000000..dd420e15327
--- /dev/null
+++ b/chromium/components/chromeos_camera/dmabuf_utils.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 "components/chromeos_camera/dmabuf_utils.h"
+
+#include <utility>
+
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/time/time.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_frame_layout.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace chromeos_camera {
+
+scoped_refptr<media::VideoFrame> ConstructVideoFrame(
+ std::vector<mojom::DmaBufPlanePtr> dma_buf_planes,
+ media::VideoPixelFormat pixel_format,
+ const gfx::Size& coded_size) {
+ const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format);
+ if (num_planes != dma_buf_planes.size()) {
+ DLOG(ERROR) << "The number of DMA buf planes does not match the format";
+ return nullptr;
+ }
+ if (coded_size.IsEmpty()) {
+ DLOG(ERROR) << "Invalid coded size: " << coded_size.width() << ", "
+ << coded_size.height();
+ return nullptr;
+ }
+ const gfx::Rect visible_rect(coded_size);
+
+ std::vector<base::ScopedFD> dma_buf_fds(num_planes);
+ std::vector<media::VideoFrameLayout::Plane> planes(num_planes);
+ for (size_t i = 0; i < num_planes; ++i) {
+ mojo::PlatformHandle handle =
+ mojo::UnwrapPlatformHandle(std::move(dma_buf_planes[i]->fd_handle));
+ if (!handle.is_valid()) {
+ DLOG(ERROR) << "Invalid DMA buf file descriptor";
+ return nullptr;
+ }
+ dma_buf_fds[i] = handle.TakeFD();
+ planes[i] = media::VideoFrameLayout::Plane(
+ dma_buf_planes[i]->stride,
+ base::strict_cast<size_t>(dma_buf_planes[i]->offset),
+ base::strict_cast<size_t>(dma_buf_planes[i]->size));
+ }
+ const base::Optional<media::VideoFrameLayout> layout =
+ media::VideoFrameLayout::CreateWithPlanes(pixel_format, coded_size,
+ std::move(planes));
+ if (!layout) {
+ DLOG(ERROR) << "Failed to create video frame layout";
+ return nullptr;
+ }
+
+ return media::VideoFrame::WrapExternalDmabufs(
+ *layout, // layout
+ visible_rect, // visible_rect
+ coded_size, // natural_size
+ std::move(dma_buf_fds), // dmabuf_fds
+ base::TimeDelta()); // timestamp
+}
+
+} // namespace chromeos_camera
diff --git a/chromium/components/chromeos_camera/dmabuf_utils.h b/chromium/components/chromeos_camera/dmabuf_utils.h
new file mode 100644
index 00000000000..f895c0ccf5e
--- /dev/null
+++ b/chromium/components/chromeos_camera/dmabuf_utils.h
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CHROMEOS_CAMERA_DMABUF_UTILS_H_
+#define COMPONENTS_CHROMEOS_CAMERA_DMABUF_UTILS_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/memory/scoped_refptr.h"
+#include "components/chromeos_camera/common/dmabuf.mojom.h"
+#include "media/base/video_types.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+class VideoFrame;
+}
+
+namespace chromeos_camera {
+
+scoped_refptr<media::VideoFrame> ConstructVideoFrame(
+ std::vector<mojom::DmaBufPlanePtr> dma_buf_planes,
+ media::VideoPixelFormat pixel_format,
+ const gfx::Size& coded_size);
+
+} // namespace chromeos_camera
+
+#endif // COMPONENTS_CHROMEOS_CAMERA_DMABUF_UTILS_H_
diff --git a/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.cc b/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.cc
index 1dcbe54ce95..37a70d01be0 100644
--- a/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.cc
+++ b/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.cc
@@ -5,9 +5,12 @@
#include "components/chromeos_camera/fake_mjpeg_decode_accelerator.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "media/base/unaligned_shared_memory.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_types.h"
namespace chromeos_camera {
@@ -15,8 +18,7 @@ FakeMjpegDecodeAccelerator::FakeMjpegDecodeAccelerator(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_task_runner_(std::move(io_task_runner)),
- decoder_thread_("FakeMjpegDecoderThread"),
- weak_factory_(this) {}
+ decoder_thread_("FakeMjpegDecoderThread") {}
FakeMjpegDecodeAccelerator::~FakeMjpegDecodeAccelerator() {
DCHECK(client_task_runner_->BelongsToCurrentThread());
@@ -59,8 +61,17 @@ void FakeMjpegDecodeAccelerator::Decode(
std::move(video_frame), base::Passed(&src_shm)));
}
+void FakeMjpegDecodeAccelerator::Decode(
+ int32_t task_id,
+ base::ScopedFD src_dmabuf_fd,
+ size_t src_size,
+ off_t src_offset,
+ scoped_refptr<media::VideoFrame> dst_frame) {
+ NOTIMPLEMENTED();
+}
+
void FakeMjpegDecodeAccelerator::DecodeOnDecoderThread(
- int32_t bitstream_buffer_id,
+ int32_t task_id,
scoped_refptr<media::VideoFrame> video_frame,
std::unique_ptr<media::UnalignedSharedMemory> src_shm) {
DCHECK(decoder_task_runner_->BelongsToCurrentThread());
@@ -74,32 +85,29 @@ void FakeMjpegDecodeAccelerator::DecodeOnDecoderThread(
client_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&FakeMjpegDecodeAccelerator::OnDecodeDoneOnClientThread,
- weak_factory_.GetWeakPtr(), bitstream_buffer_id));
+ weak_factory_.GetWeakPtr(), task_id));
}
bool FakeMjpegDecodeAccelerator::IsSupported() {
return true;
}
-void FakeMjpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id,
- Error error) {
+void FakeMjpegDecodeAccelerator::NotifyError(int32_t task_id, Error error) {
client_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&FakeMjpegDecodeAccelerator::NotifyErrorOnClientThread,
- weak_factory_.GetWeakPtr(), bitstream_buffer_id, error));
+ weak_factory_.GetWeakPtr(), task_id, error));
}
-void FakeMjpegDecodeAccelerator::NotifyErrorOnClientThread(
- int32_t bitstream_buffer_id,
- Error error) {
+void FakeMjpegDecodeAccelerator::NotifyErrorOnClientThread(int32_t task_id,
+ Error error) {
DCHECK(client_task_runner_->BelongsToCurrentThread());
- client_->NotifyError(bitstream_buffer_id, error);
+ client_->NotifyError(task_id, error);
}
-void FakeMjpegDecodeAccelerator::OnDecodeDoneOnClientThread(
- int32_t input_buffer_id) {
+void FakeMjpegDecodeAccelerator::OnDecodeDoneOnClientThread(int32_t task_id) {
DCHECK(client_task_runner_->BelongsToCurrentThread());
- client_->VideoFrameReady(input_buffer_id);
+ client_->VideoFrameReady(task_id);
}
} // namespace chromeos_camera
diff --git a/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.h b/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.h
index 51b16c3290c..ea51eb559e7 100644
--- a/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.h
+++ b/chromium/components/chromeos_camera/fake_mjpeg_decode_accelerator.h
@@ -34,16 +34,21 @@ class FakeMjpegDecodeAccelerator : public MjpegDecodeAccelerator {
bool Initialize(MjpegDecodeAccelerator::Client* client) override;
void Decode(media::BitstreamBuffer bitstream_buffer,
scoped_refptr<media::VideoFrame> video_frame) override;
+ void Decode(int32_t task_id,
+ base::ScopedFD src_dmabuf_fd,
+ size_t src_size,
+ off_t src_offset,
+ scoped_refptr<media::VideoFrame> dst_frame) override;
bool IsSupported() override;
private:
void DecodeOnDecoderThread(
- int32_t bitstream_buffer_id,
+ int32_t task_id,
scoped_refptr<media::VideoFrame> video_frame,
std::unique_ptr<media::UnalignedSharedMemory> src_shm);
- void NotifyError(int32_t bitstream_buffer_id, Error error);
- void NotifyErrorOnClientThread(int32_t bitstream_buffer_id, Error error);
- void OnDecodeDoneOnClientThread(int32_t input_buffer_id);
+ void NotifyError(int32_t task_id, Error error);
+ void NotifyErrorOnClientThread(int32_t task_id, Error error);
+ void OnDecodeDoneOnClientThread(int32_t task_id);
// Task runner for calls to |client_|.
const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
@@ -56,7 +61,7 @@ class FakeMjpegDecodeAccelerator : public MjpegDecodeAccelerator {
base::Thread decoder_thread_;
scoped_refptr<base::SingleThreadTaskRunner> decoder_task_runner_;
- base::WeakPtrFactory<FakeMjpegDecodeAccelerator> weak_factory_;
+ base::WeakPtrFactory<FakeMjpegDecodeAccelerator> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(FakeMjpegDecodeAccelerator);
};
diff --git a/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc b/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
index e2cf5f33595..fe3ff090e04 100644
--- a/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
+++ b/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
@@ -13,12 +13,13 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -159,7 +160,7 @@ class JpegEncodeAcceleratorTestEnvironment : public ::testing::Environment {
};
void JpegEncodeAcceleratorTestEnvironment::SetUp() {
- // Since base::test::ScopedTaskEnvironment will call
+ // Since base::test::TaskEnvironment will call
// TestTimeouts::action_max_timeout(), TestTimeouts::Initialize() needs to be
// called in advance.
TestTimeouts::Initialize();
@@ -309,9 +310,9 @@ class JpegClient : public JpegEncodeAccelerator::Client {
// support them.
const std::vector<TestImage*>& test_aligned_images_;
- // JpegClient doesn't own |test_images_|.
+ // JpegClient doesn't own |test_unaligned_images_|.
// The resolutions of these images may be unaligned.
- const std::vector<TestImage*>& test_images_;
+ const std::vector<TestImage*>& test_unaligned_images_;
// A map that stores HW encoding start timestamp for each output buffer id.
std::map<int, base::TimeTicks> buffer_id_to_start_time_;
@@ -327,11 +328,14 @@ class JpegClient : public JpegEncodeAccelerator::Client {
media::BitstreamBuffer encoded_buffer_;
// Mapped memory of input file.
- std::unique_ptr<base::SharedMemory> in_shm_;
+ base::UnsafeSharedMemoryRegion in_shm_;
+ base::WritableSharedMemoryMapping in_mapping_;
// Mapped memory of output buffer from hardware encoder.
- std::unique_ptr<base::SharedMemory> hw_out_shm_;
+ base::UnsafeSharedMemoryRegion hw_out_shm_;
+ base::WritableSharedMemoryMapping hw_out_mapping_;
// Mapped memory of output buffer from software encoder.
- std::unique_ptr<base::SharedMemory> sw_out_shm_;
+ base::UnsafeSharedMemoryRegion sw_out_shm_;
+ base::WritableSharedMemoryMapping sw_out_mapping_;
// Output for DMA-buf based encoding.
scoped_refptr<media::VideoFrame> hw_out_frame_;
@@ -345,7 +349,7 @@ JpegClient::JpegClient(const std::vector<TestImage*>& test_aligned_images,
const std::vector<TestImage*>& test_images,
media::test::ClientStateNotification<ClientState>* note)
: test_aligned_images_(test_aligned_images),
- test_images_(test_images),
+ test_unaligned_images_(test_images),
state_(ClientState::CREATED),
note_(note),
gpu_memory_buffer_manager_(new media::LocalGpuMemoryBufferManager()) {}
@@ -395,7 +399,8 @@ void JpegClient::VideoFrameReady(int32_t buffer_id, size_t hw_encoded_size) {
if (buffer_id < static_cast<int32_t>(test_aligned_images_.size())) {
test_image = test_aligned_images_[buffer_id];
} else {
- test_image = test_images_[buffer_id - test_aligned_images_.size()];
+ test_image =
+ test_unaligned_images_[buffer_id - test_aligned_images_.size()];
}
if (hw_out_frame_ && !hw_out_frame_->IsMappable()) {
@@ -439,7 +444,7 @@ bool JpegClient::GetSoftwareEncodeResult(int width,
int y_stride = width;
int u_stride = width / 2;
int v_stride = u_stride;
- uint8_t* yuv_src = static_cast<uint8_t*>(in_shm_->memory());
+ uint8_t* yuv_src = in_mapping_.GetMemoryAsSpan<uint8_t>().data();
const int kBytesPerPixel = 4;
std::vector<uint8_t> rgba_buffer(width * height * kBytesPerPixel);
std::vector<uint8_t> encoded;
@@ -455,7 +460,7 @@ bool JpegClient::GetSoftwareEncodeResult(int width,
return false;
}
- memcpy(sw_out_shm_->memory(), encoded.data(), encoded.size());
+ memcpy(sw_out_mapping_.memory(), encoded.data(), encoded.size());
*sw_encoded_size = encoded.size();
*sw_encode_time = base::TimeTicks::Now() - sw_encode_start;
return true;
@@ -472,7 +477,7 @@ bool JpegClient::CompareHardwareAndSoftwareResults(int width,
int v_stride = u_stride;
const uint8_t* out_mem = static_cast<const uint8_t*>(
- hw_out_frame_ ? hw_out_frame_->data(0) : hw_out_shm_->memory());
+ hw_out_frame_ ? hw_out_frame_->data(0) : hw_out_mapping_.memory());
if (libyuv::ConvertToI420(
out_mem, hw_encoded_size, hw_yuv_result, y_stride,
hw_yuv_result + y_stride * height, u_stride,
@@ -484,8 +489,9 @@ bool JpegClient::CompareHardwareAndSoftwareResults(int width,
uint8_t* sw_yuv_result = new uint8_t[yuv_size];
if (libyuv::ConvertToI420(
- static_cast<const uint8_t*>(sw_out_shm_->memory()), sw_encoded_size,
- sw_yuv_result, y_stride, sw_yuv_result + y_stride * height, u_stride,
+ static_cast<const uint8_t*>(sw_out_mapping_.memory()),
+ sw_encoded_size, sw_yuv_result, y_stride,
+ sw_yuv_result + y_stride * height, u_stride,
sw_yuv_result + y_stride * height + u_stride * height / 2, v_stride,
0, 0, width, height, width, height, libyuv::kRotate0,
libyuv::FOURCC_MJPG)) {
@@ -525,13 +531,13 @@ void JpegClient::NotifyError(int32_t buffer_id,
TestImage* JpegClient::GetTestImage(int32_t bitstream_buffer_id) {
DCHECK_LT(static_cast<size_t>(bitstream_buffer_id),
- test_aligned_images_.size() + test_images_.size());
+ test_aligned_images_.size() + test_unaligned_images_.size());
TestImage* image_file;
if (bitstream_buffer_id < static_cast<int32_t>(test_aligned_images_.size())) {
image_file = test_aligned_images_[bitstream_buffer_id];
} else {
- image_file =
- test_images_[bitstream_buffer_id - test_aligned_images_.size()];
+ image_file = test_unaligned_images_[bitstream_buffer_id -
+ test_aligned_images_.size()];
}
return image_file;
@@ -541,25 +547,33 @@ void JpegClient::PrepareMemory(int32_t bitstream_buffer_id) {
TestImage* test_image = GetTestImage(bitstream_buffer_id);
size_t input_size = test_image->image_data.size();
- if (!in_shm_.get() || input_size > in_shm_->mapped_size()) {
- in_shm_.reset(new base::SharedMemory);
- LOG_ASSERT(in_shm_->CreateAndMapAnonymous(input_size));
+ if (!in_mapping_.IsValid() || input_size > in_mapping_.size()) {
+ in_shm_ = base::UnsafeSharedMemoryRegion::Create(input_size);
+ LOG_ASSERT(in_shm_.IsValid());
+ in_mapping_ = in_shm_.Map();
+ LOG_ASSERT(in_mapping_.IsValid());
}
- memcpy(in_shm_->memory(), test_image->image_data.data(), input_size);
-
- if (!hw_out_shm_.get() ||
- test_image->output_size > hw_out_shm_->mapped_size()) {
- hw_out_shm_.reset(new base::SharedMemory);
- LOG_ASSERT(hw_out_shm_->CreateAndMapAnonymous(test_image->output_size));
+ memcpy(in_mapping_.memory(), test_image->image_data.data(), input_size);
+
+ if (!hw_out_shm_.IsValid() || !hw_out_mapping_.IsValid() ||
+ test_image->output_size > hw_out_mapping_.size()) {
+ hw_out_shm_ =
+ base::UnsafeSharedMemoryRegion::Create(test_image->output_size);
+ LOG_ASSERT(hw_out_shm_.IsValid());
+ hw_out_mapping_ = hw_out_shm_.Map();
+ LOG_ASSERT(hw_out_mapping_.IsValid());
}
- memset(hw_out_shm_->memory(), 0, test_image->output_size);
-
- if (!sw_out_shm_.get() ||
- test_image->output_size > sw_out_shm_->mapped_size()) {
- sw_out_shm_.reset(new base::SharedMemory);
- LOG_ASSERT(sw_out_shm_->CreateAndMapAnonymous(test_image->output_size));
+ memset(hw_out_mapping_.memory(), 0, test_image->output_size);
+
+ if (!sw_out_shm_.IsValid() || !sw_out_mapping_.IsValid() ||
+ test_image->output_size > sw_out_mapping_.size()) {
+ sw_out_shm_ =
+ base::UnsafeSharedMemoryRegion::Create(test_image->output_size);
+ LOG_ASSERT(sw_out_shm_.IsValid());
+ sw_out_mapping_ = sw_out_shm_.Map();
+ LOG_ASSERT(sw_out_mapping_.IsValid());
}
- memset(sw_out_shm_->memory(), 0, test_image->output_size);
+ memset(sw_out_mapping_.memory(), 0, test_image->output_size);
hw_out_frame_ = nullptr;
}
@@ -582,12 +596,12 @@ void JpegClient::SaveToFile(TestImage* test_image,
LOG(INFO) << "Writing HW encode results to "
<< out_filename_hw.MaybeAsASCII();
- ASSERT_EQ(
- static_cast<int>(hw_size),
- base::WriteFile(out_filename_hw,
- static_cast<char*>(hw_out_frame_ ? hw_out_frame_->data(0)
- : hw_out_shm_->memory()),
- hw_size));
+ ASSERT_EQ(static_cast<int>(hw_size),
+ base::WriteFile(
+ out_filename_hw,
+ static_cast<char*>(hw_out_frame_ ? hw_out_frame_->data(0)
+ : hw_out_mapping_.memory()),
+ hw_size));
base::FilePath out_filename_sw = out_filename_hw.InsertBeforeExtension("_sw");
LOG(INFO) << "Writing SW encode results to "
@@ -595,7 +609,7 @@ void JpegClient::SaveToFile(TestImage* test_image,
ASSERT_EQ(
static_cast<int>(sw_size),
base::WriteFile(out_filename_sw,
- static_cast<char*>(sw_out_shm_->memory()), sw_size));
+ static_cast<char*>(sw_out_mapping_.memory()), sw_size));
}
void JpegClient::StartEncode(int32_t bitstream_buffer_id) {
@@ -605,19 +619,16 @@ void JpegClient::StartEncode(int32_t bitstream_buffer_id) {
encoder_->GetMaxCodedBufferSize(test_image->visible_size);
PrepareMemory(bitstream_buffer_id);
- // media::BitstreamBuffer will duplicate hw_out_shm_->handle().
- encoded_buffer_ =
- media::BitstreamBuffer(bitstream_buffer_id, hw_out_shm_->handle(),
- false /* read_only */, test_image->output_size);
+ encoded_buffer_ = media::BitstreamBuffer(
+ bitstream_buffer_id, std::move(hw_out_shm_), test_image->output_size);
scoped_refptr<media::VideoFrame> input_frame_ =
- media::VideoFrame::WrapExternalSharedMemory(
+ media::VideoFrame::WrapExternalData(
media::PIXEL_FORMAT_I420, test_image->visible_size,
gfx::Rect(test_image->visible_size), test_image->visible_size,
- static_cast<uint8_t*>(in_shm_->memory()),
- test_image->image_data.size(), in_shm_->handle(), 0,
- base::TimeDelta());
-
+ in_mapping_.GetMemoryAsSpan<uint8_t>().data(),
+ test_image->image_data.size(), base::TimeDelta());
LOG_ASSERT(input_frame_.get());
+ input_frame_->BackWithSharedMemory(&in_shm_);
buffer_id_to_start_time_[bitstream_buffer_id] = base::TimeTicks::Now();
encoder_->Encode(input_frame_, kJpegDefaultQuality, nullptr,
@@ -670,12 +681,12 @@ class JpegEncodeAcceleratorTest : public ::testing::Test {
// This is needed to allow the usage of methods in post_task.h in
// JpegEncodeAccelerator implementations.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
- // The elements of |test_aligned_images_| and |test_images_| are
+ // The elements of |test_aligned_images_| and |test_unaligned_images_| are
// owned by JpegEncodeAcceleratorTestEnvironment.
std::vector<TestImage*> test_aligned_images_;
- std::vector<TestImage*> test_images_;
+ std::vector<TestImage*> test_unaligned_images_;
protected:
DISALLOW_COPY_AND_ASSIGN(JpegEncodeAcceleratorTest);
@@ -690,16 +701,21 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders,
std::unique_ptr<media::test::ClientStateNotification<ClientState>>>
notes;
std::vector<std::unique_ptr<JpegClient>> clients;
+ std::vector<ClientState> results;
for (size_t i = 0; i < num_concurrent_encoders; i++) {
notes.push_back(
std::make_unique<media::test::ClientStateNotification<ClientState>>());
clients.push_back(std::make_unique<JpegClient>(
- test_aligned_images_, test_images_, notes.back().get()));
+ test_aligned_images_, test_unaligned_images_, notes.back().get()));
encoder_thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&JpegClient::CreateJpegEncoder,
base::Unretained(clients.back().get())));
- ASSERT_EQ(notes[i]->Wait(), ClientState::INITIALIZED);
+ results.push_back(notes[i]->Wait());
+ }
+
+ for (size_t i = 0; i < num_concurrent_encoders; i++) {
+ ASSERT_EQ(results[i], ClientState::INITIALIZED);
}
for (size_t index = 0; index < test_aligned_images_.size(); index++) {
@@ -723,7 +739,11 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders,
}
}
for (size_t i = 0; i < num_concurrent_encoders; i++) {
- ASSERT_EQ(notes[i]->Wait(), ClientState::ENCODE_PASS);
+ results[i] = notes[i]->Wait();
+ }
+
+ for (size_t i = 0; i < num_concurrent_encoders; i++) {
+ ASSERT_EQ(results[i], ClientState::ENCODE_PASS);
}
}
@@ -731,12 +751,12 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders,
// For unaligned images, V4L2 may not be able to encode them so skip for V4L2
// cases.
#else
- for (size_t index = 0; index < test_images_.size(); index++) {
+ for (size_t index = 0; index < test_unaligned_images_.size(); index++) {
int buffer_id = index + test_aligned_images_.size();
VLOG(3) << buffer_id
- << ",width:" << test_images_[index]->visible_size.width();
- VLOG(3) << buffer_id
- << ",height:" << test_images_[index]->visible_size.height();
+ << ",width:" << test_unaligned_images_[index]->visible_size.width();
+ VLOG(3) << buffer_id << ",height:"
+ << test_unaligned_images_[index]->visible_size.height();
if (!is_dma) {
for (size_t i = 0; i < num_concurrent_encoders; i++) {
@@ -754,7 +774,11 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders,
}
}
for (size_t i = 0; i < num_concurrent_encoders; i++) {
- ASSERT_EQ(notes[i]->Wait(), ClientState::ENCODE_PASS);
+ results[i] = notes[i]->Wait();
+ }
+
+ for (size_t i = 0; i < num_concurrent_encoders; i++) {
+ ASSERT_EQ(results[i], ClientState::ENCODE_PASS);
}
}
#endif
@@ -771,7 +795,7 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders,
TEST_F(JpegEncodeAcceleratorTest, SimpleEncode) {
for (size_t i = 0; i < g_env->repeat_; i++) {
for (auto& image : g_env->image_data_user_) {
- test_images_.push_back(image.get());
+ test_aligned_images_.push_back(image.get());
}
}
TestEncode(1, false);
@@ -779,14 +803,13 @@ TEST_F(JpegEncodeAcceleratorTest, SimpleEncode) {
TEST_F(JpegEncodeAcceleratorTest, MultipleEncoders) {
for (auto& image : g_env->image_data_user_) {
- test_images_.push_back(image.get());
+ test_aligned_images_.push_back(image.get());
}
TestEncode(3, false);
}
TEST_F(JpegEncodeAcceleratorTest, ResolutionChange) {
- test_images_.push_back(g_env->image_data_640x368_black_.get());
- test_images_.push_back(g_env->image_data_640x360_black_.get());
+ test_aligned_images_.push_back(g_env->image_data_640x368_black_.get());
test_aligned_images_.push_back(g_env->image_data_1280x720_white_.get());
TestEncode(1, false);
}
@@ -799,14 +822,14 @@ TEST_F(JpegEncodeAcceleratorTest, AlignedSizes) {
}
TEST_F(JpegEncodeAcceleratorTest, CodedSizeAlignment) {
- test_images_.push_back(g_env->image_data_640x360_black_.get());
+ test_unaligned_images_.push_back(g_env->image_data_640x360_black_.get());
TestEncode(1, false);
}
TEST_F(JpegEncodeAcceleratorTest, SimpleDmaEncode) {
for (size_t i = 0; i < g_env->repeat_; i++) {
for (auto& image : g_env->image_data_user_) {
- test_images_.push_back(image.get());
+ test_aligned_images_.push_back(image.get());
}
}
TestEncode(1, true);
@@ -814,14 +837,13 @@ TEST_F(JpegEncodeAcceleratorTest, SimpleDmaEncode) {
TEST_F(JpegEncodeAcceleratorTest, MultipleDmaEncoders) {
for (auto& image : g_env->image_data_user_) {
- test_images_.push_back(image.get());
+ test_aligned_images_.push_back(image.get());
}
TestEncode(3, true);
}
TEST_F(JpegEncodeAcceleratorTest, ResolutionChangeDma) {
- test_images_.push_back(g_env->image_data_640x368_black_.get());
- test_images_.push_back(g_env->image_data_640x360_black_.get());
+ test_aligned_images_.push_back(g_env->image_data_640x368_black_.get());
test_aligned_images_.push_back(g_env->image_data_1280x720_white_.get());
TestEncode(1, true);
}
@@ -834,7 +856,7 @@ TEST_F(JpegEncodeAcceleratorTest, AlignedSizesDma) {
}
TEST_F(JpegEncodeAcceleratorTest, CodedSizeAlignmentDma) {
- test_images_.push_back(g_env->image_data_640x360_black_.get());
+ test_unaligned_images_.push_back(g_env->image_data_640x360_black_.get());
TestEncode(1, true);
}
diff --git a/chromium/components/chromeos_camera/mjpeg_decode_accelerator.h b/chromium/components/chromeos_camera/mjpeg_decode_accelerator.h
index d8c53444dd3..454b4b0c020 100644
--- a/chromium/components/chromeos_camera/mjpeg_decode_accelerator.h
+++ b/chromium/components/chromeos_camera/mjpeg_decode_accelerator.h
@@ -5,19 +5,26 @@
#ifndef COMPONENTS_CHROMEOS_CAMERA_MJPEG_DECODE_ACCELERATOR_H_
#define COMPONENTS_CHROMEOS_CAMERA_MJPEG_DECODE_ACCELERATOR_H_
+#include <stddef.h>
#include <stdint.h>
+#include <sys/types.h>
+#include "base/callback.h"
+#include "base/files/scoped_file.h"
+#include "base/memory/scoped_refptr.h"
#include "media/base/bitstream_buffer.h"
-#include "media/base/video_frame.h"
+
+namespace media {
+class VideoFrame;
+}
namespace chromeos_camera {
// MJPEG decoder interface.
// The input are JPEG images including headers (Huffman tables may be omitted).
-// The output color format is I420. The decoder will convert the color format
-// to I420 if the color space or subsampling does not match that and if it is
-// capable of doing so. The client is responsible for allocating buffers and
-// keeps the ownership of them.
+// The decoder will convert to the output color format if the input color format
+// or subsampling does not match that and if it is capable of doing so. The
+// client is responsible for allocating buffers and keeps the ownership of them.
// The intended use case of this interface is decoding MJPEG images coming
// from camera capture. It can also be used for normal still JPEG image
// decoding, but normal JPEG images may use more JPEG features that may not be
@@ -27,7 +34,7 @@ class MjpegDecodeAccelerator {
// Callback for JPEG decoder initialization.
typedef base::Callback<void(bool success)> InitCB;
- static const int32_t kInvalidBitstreamBufferId = -1;
+ static const int32_t kInvalidTaskId = -1;
// Enumeration of decode errors generated by NotifyError callback. These
// values are persisted to logs. Entries should not be renumbered and numeric
@@ -58,9 +65,8 @@ class MjpegDecodeAccelerator {
public:
// Callback called after each successful Decode().
// Parameters:
- // |bitstream_buffer_id| is the id of BitstreamBuffer corresponding to
- // Decode() call.
- virtual void VideoFrameReady(int32_t bitstream_buffer_id) = 0;
+ // |task_id| is the id passed to Decode() call.
+ virtual void VideoFrameReady(int32_t task_id) = 0;
// Callback to notify errors. Client is responsible for destroying JDA when
// receiving a fatal error, i.e. PLATFORM_FAILURE. For other errors, client
@@ -68,11 +74,11 @@ class MjpegDecodeAccelerator {
// using the same instance of JDA.
// Parameters:
// |error| is the error code.
- // |bitstream_buffer_id| is the bitstream buffer id that resulted in the
- // recoverable error. For PLATFORM_FAILURE, |bitstream_buffer_id| may be
- // kInvalidBitstreamBufferId if the error was not related to any
- // particular buffer being processed.
- virtual void NotifyError(int32_t bitstream_buffer_id, Error error) = 0;
+ // |task_id| is the id passed to Decode() call that resulted in the
+ // recoverable error. For PLATFORM_FAILURE, |task_id| may be
+ // |kInvalidTaskId| if the error was not related to any particular buffer
+ // being processed.
+ virtual void NotifyError(int32_t task_id, Error error) = 0;
protected:
virtual ~Client() {}
@@ -99,24 +105,38 @@ class MjpegDecodeAccelerator {
// Decodes the given bitstream buffer that contains one JPEG frame. It
// supports at least baseline encoding defined in JPEG ISO/IEC 10918-1. The
- // decoder will convert the color format to I420 or return UNSUPPORTED_JPEG
- // if it cannot convert. Client still owns this buffer, but should deallocate
- // or access the buffer only after receiving a decode callback VideoFrameReady
- // with the corresponding bitstream_buffer_id, or NotifyError.
+ // decoder will convert the output to |video_frame->format()| or return
+ // PLATFORM_FAILURE if it cannot convert.
// Parameters:
// |bitstream_buffer| contains encoded JPEG frame.
- // |video_frame| contains an allocated video frame for the output.
- // Client is responsible for filling the coded_size of video_frame and
- // allocating its backing buffer. For now, only shared memory backed
- // VideoFrames are supported. After decode completes, the decoded JPEG frame
- // will be filled into the |video_frame|.
- // Ownership of the |bitstream_buffer| and |video_frame| remains with the
- // client. The client is not allowed to deallocate them before
- // VideoFrameReady or NotifyError() is invoked for given id of
- // |bitstream_buffer|, or destructor returns.
+ // |video_frame| contains an allocated video frame for the output, backed
+ // with an UnsafeSharedMemoryRegion or DMA buffer.
+ //
+ // Client is responsible for filling the |video_frame->coded_size()|,
+ // |video_frame->visible_rect()|, and allocating its backing buffer. For
+ // unsafe shared memory backed VideoFrames, I420 and NV12 formats are
+ // supported. For DMA-buf backed VideoFrames, the supported formats depend on
+ // the underlying hardware implementation. After decode completes, the
+ // decoded JPEG frame will be filled into the |video_frame|. Ownership of the
+ // |bitstream_buffer| and |video_frame| remains with the client. The client
+ // is not allowed to deallocate them before VideoFrameReady or NotifyError()
+ // is invoked for given id of |bitstream_buffer|, or destructor returns.
virtual void Decode(media::BitstreamBuffer bitstream_buffer,
scoped_refptr<media::VideoFrame> video_frame) = 0;
+ // The same as above but the JPEG image is stored in a DMA buffer.
+ // Parameters:
+ // |src_dmabuf_fd| contains encoded JPEG frame.
+ // |src_size| is the size of the JPEG frame.
+ // |src_offset| is the offset at which the JPEG data starts.
+ // |dst_frame| contains an allocated video frame for the output, backed with
+ // an UnsafeSharedMemoryRegion or DMA buffer.
+ virtual void Decode(int32_t task_id,
+ base::ScopedFD src_dmabuf_fd,
+ size_t src_size,
+ off_t src_offset,
+ scoped_refptr<media::VideoFrame> dst_frame) = 0;
+
// Returns true when the JPEG decoder is supported. This can be called before
// Initialize().
virtual bool IsSupported() = 0;
diff --git a/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc b/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
index 640b324d9a6..917452a44ed 100644
--- a/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
+++ b/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
@@ -5,35 +5,55 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
+#include <unistd.h>
#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/platform_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
#include "base/path_service.h"
+#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
#include "components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.h"
#include "components/chromeos_camera/mjpeg_decode_accelerator.h"
#include "media/base/test_data_util.h"
+#include "media/base/video_frame_layout.h"
+#include "media/capture/video/chromeos/local_gpu_memory_buffer_manager.h"
#include "media/gpu/buildflags.h"
+#include "media/gpu/format_utils.h"
#include "media/gpu/test/video_accelerator_unittest_helpers.h"
+#include "media/gpu/test/video_frame_helpers.h"
#include "media/parsers/jpeg_parser.h"
#include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libyuv/include/libyuv.h"
+#include "ui/gfx/buffer_types.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/native_pixmap_handle.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_wrapper.h"
@@ -55,6 +75,10 @@ bool g_save_to_file = false;
// images. This is used for measuring of the similarity of two images.
constexpr double kDecodeSimilarityThreshold = 1.25;
+// The buffer usage used to create GpuMemoryBuffer for testing.
+constexpr gfx::BufferUsage kBufferUsage =
+ gfx::BufferUsage::SCANOUT_CPU_READ_WRITE;
+
// Environment to create test data for all test cases.
class MjpegDecodeAcceleratorTestEnvironment;
MjpegDecodeAcceleratorTestEnvironment* g_env;
@@ -113,14 +137,11 @@ struct ParsedJpegImage {
void InitializeSizes(int width, int height) {
visible_size.SetSize(width, height);
// We don't expect odd dimensions for camera captures.
- DCHECK_EQ(0, width % 2);
- DCHECK_EQ(0, height % 2);
+ ASSERT_EQ(0, width % 2);
+ ASSERT_EQ(0, height % 2);
coded_size.SetSize((visible_size.width() + 1) & ~1,
(visible_size.height() + 1) & ~1);
- // The JPEG decoder will always return the decoded frame in I420 format.
- output_size =
- media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, coded_size);
}
const base::FilePath::StringType& filename() const {
@@ -132,7 +153,6 @@ struct ParsedJpegImage {
std::string data_str;
gfx::Size visible_size;
gfx::Size coded_size;
- size_t output_size;
};
// Global singleton to hold on to common data and other user-defined options.
@@ -163,6 +183,35 @@ class MjpegDecodeAcceleratorTestEnvironment : public ::testing::Environment {
return media::GetTestDataFilePath(file_path);
}
+ // Creates a zero-initialized shared memory backed VideoFrame.
+ scoped_refptr<media::VideoFrame> CreateShmVideoFrame(
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::Size& visible_size);
+
+ // Creates a zero-initialized DMA-buf backed VideoFrame. Also returns the
+ // backing GpuMemoryBuffer in |backing_gmb| if it is not null.
+ scoped_refptr<media::VideoFrame> CreateDmaBufVideoFrame(
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::Size& visible_size,
+ std::unique_ptr<gfx::GpuMemoryBuffer>* backing_gmb = nullptr);
+
+ // Maps |gmb| into a VideoFrame containing the data pointers. |gmb| should
+ // outlive the returned Videoframe.
+ scoped_refptr<media::VideoFrame> MapToVideoFrame(
+ gfx::GpuMemoryBuffer* gmb,
+ const media::VideoFrameLayout& layout,
+ const gfx::Rect& visible_rect);
+
+ // Creates a DMA buffer file descriptor that contains |size| bytes of linear
+ // data initialized with |data|.
+ base::ScopedFD CreateDmaBufFd(const void* data, size_t size);
+
+ // Gets a list of supported DMA-buf frame formats for
+ // CreateDmaBufVideoFrame().
+ std::vector<media::VideoPixelFormat> GetSupportedDmaBufFormats();
+
// Used for InputSizeChange test case. The image size should be smaller than
// |kDefaultJpegFilename|.
std::unique_ptr<ParsedJpegImage> image_data_1280x720_black_;
@@ -185,6 +234,9 @@ class MjpegDecodeAcceleratorTestEnvironment : public ::testing::Environment {
private:
const base::FilePath::CharType* user_jpeg_filenames_;
const base::FilePath::CharType* test_data_path_;
+
+ std::unique_ptr<media::LocalGpuMemoryBufferManager>
+ gpu_memory_buffer_manager_;
};
void MjpegDecodeAcceleratorTestEnvironment::SetUp() {
@@ -211,6 +263,202 @@ void MjpegDecodeAcceleratorTestEnvironment::SetUp() {
auto image_data = ParsedJpegImage::CreateFromFile(input_file);
image_data_user_.push_back(std::move(image_data));
}
+
+ gpu_memory_buffer_manager_ =
+ std::make_unique<media::LocalGpuMemoryBufferManager>();
+}
+
+scoped_refptr<media::VideoFrame>
+MjpegDecodeAcceleratorTestEnvironment::CreateShmVideoFrame(
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::Size& visible_size) {
+ const size_t data_size =
+ media::VideoFrame::AllocationSize(format, coded_size);
+ auto shm_region = base::UnsafeSharedMemoryRegion::Create(data_size);
+ if (!shm_region.IsValid()) {
+ LOG(ERROR) << "Failed to create shared memory";
+ return nullptr;
+ }
+ base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
+ if (!shm_mapping.IsValid()) {
+ LOG(ERROR) << "Failed to map shared memory region";
+ return nullptr;
+ }
+ memset(shm_mapping.memory(), 0, data_size);
+
+ scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData(
+ format, coded_size, gfx::Rect(visible_size), visible_size,
+ shm_mapping.GetMemoryAsSpan<uint8_t>().data(), data_size,
+ base::TimeDelta());
+ if (!frame) {
+ LOG(ERROR) << "Failed to create video frame";
+ return nullptr;
+ }
+ frame->BackWithOwnedSharedMemory(std::move(shm_region),
+ std::move(shm_mapping));
+
+ return frame;
+}
+
+scoped_refptr<media::VideoFrame>
+MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufVideoFrame(
+ media::VideoPixelFormat format,
+ const gfx::Size& coded_size,
+ const gfx::Size& visible_size,
+ std::unique_ptr<gfx::GpuMemoryBuffer>* backing_gmb) {
+ DCHECK(gpu_memory_buffer_manager_);
+
+ // Create a GpuMemoryBuffer and get a NativePixmapHandle from it.
+ const base::Optional<gfx::BufferFormat> gfx_format =
+ media::VideoPixelFormatToGfxBufferFormat(format);
+ if (!gfx_format) {
+ LOG(ERROR) << "Unsupported pixel format: " << format;
+ return nullptr;
+ }
+ std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
+ gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
+ coded_size, *gfx_format, kBufferUsage, gpu::kNullSurfaceHandle);
+ if (!gmb) {
+ LOG(ERROR) << "Failed to create GpuMemoryBuffer";
+ return nullptr;
+ }
+ gfx::GpuMemoryBufferHandle gmb_handle = gmb->CloneHandle();
+ if (gmb_handle.type != gfx::NATIVE_PIXMAP) {
+ LOG(ERROR) << "The GpuMemoryBufferHandle doesn't have type NATIVE_PIXMAP";
+ return nullptr;
+ }
+
+ const size_t num_planes = media::VideoFrame::NumPlanes(format);
+ if (gmb_handle.native_pixmap_handle.planes.size() != num_planes) {
+ LOG(ERROR) << "The number of planes of NativePixmapHandle doesn't match "
+ "the pixel format";
+ return nullptr;
+ }
+
+ // Fill in the memory with zeros.
+ if (!gmb->Map()) {
+ LOG(ERROR) << "Failed to map GpuMemoryBuffer";
+ return nullptr;
+ }
+ for (size_t i = 0; i < num_planes; i++) {
+ gfx::NativePixmapPlane& plane = gmb_handle.native_pixmap_handle.planes[i];
+ memset(gmb->memory(i), 0, plane.size);
+ }
+ gmb->Unmap();
+
+ // Create a VideoFrame from the NativePixmapHandle.
+ std::vector<media::VideoFrameLayout::Plane> planes;
+ std::vector<base::ScopedFD> dmabuf_fds;
+ for (size_t i = 0; i < num_planes; i++) {
+ gfx::NativePixmapPlane& plane = gmb_handle.native_pixmap_handle.planes[i];
+ planes.emplace_back(base::checked_cast<int32_t>(plane.stride),
+ base::checked_cast<size_t>(plane.offset),
+ base::checked_cast<size_t>(plane.size));
+ dmabuf_fds.push_back(std::move(plane.fd));
+ }
+ const base::Optional<media::VideoFrameLayout> layout =
+ media::VideoFrameLayout::CreateWithPlanes(format, coded_size,
+ std::move(planes));
+ if (!layout) {
+ LOG(ERROR) << "Failed to create VideoFrameLayout";
+ return nullptr;
+ }
+
+ if (backing_gmb)
+ *backing_gmb = std::move(gmb);
+
+ return media::VideoFrame::WrapExternalDmabufs(
+ *layout, gfx::Rect(visible_size), visible_size, std::move(dmabuf_fds),
+ base::TimeDelta());
+}
+
+scoped_refptr<media::VideoFrame>
+MjpegDecodeAcceleratorTestEnvironment::MapToVideoFrame(
+ gfx::GpuMemoryBuffer* gmb,
+ const media::VideoFrameLayout& layout,
+ const gfx::Rect& visible_rect) {
+ DCHECK(gmb);
+ if (!gmb->Map()) {
+ LOG(ERROR) << "Failed to map GpuMemoryBuffer";
+ return nullptr;
+ }
+ std::array<uint8_t*, 3> data{};
+ for (size_t i = 0; i < layout.num_planes(); i++)
+ data[i] = static_cast<uint8_t*>(gmb->memory(i));
+ scoped_refptr<media::VideoFrame> frame =
+ media::VideoFrame::WrapExternalYuvDataWithLayout(
+ layout, visible_rect, visible_rect.size(), data[0], data[1], data[2],
+ base::TimeDelta());
+ if (!frame) {
+ LOG(ERROR) << "Failed to create VideoFrame";
+ return nullptr;
+ }
+ frame->AddDestructionObserver(
+ base::BindOnce(&gfx::GpuMemoryBuffer::Unmap, base::Unretained(gmb)));
+ return frame;
+}
+
+base::ScopedFD MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufFd(
+ const void* data,
+ size_t size) {
+ DCHECK(data);
+ DCHECK_GT(size, 0u);
+ DCHECK(gpu_memory_buffer_manager_);
+
+ // The DMA-buf FD is intended to allow importing into hardware accelerators,
+ // so we allocate the buffer by GMB manager instead of simply memfd_create().
+ // The GMB has R_8 format and dimensions (|size|, 1).
+ std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
+ gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
+ gfx::Size(base::checked_cast<int>(size), 1), gfx::BufferFormat::R_8,
+ kBufferUsage, gpu::kNullSurfaceHandle);
+ if (!gmb) {
+ LOG(ERROR) << "Failed to create GpuMemoryBuffer";
+ return base::ScopedFD();
+ }
+
+ gfx::GpuMemoryBufferHandle gmb_handle = gmb->CloneHandle();
+ if (gmb_handle.type != gfx::NATIVE_PIXMAP) {
+ LOG(ERROR) << "The GpuMemoryBufferHandle doesn't have type NATIVE_PIXMAP";
+ return base::ScopedFD();
+ }
+ if (gmb_handle.native_pixmap_handle.planes.size() != 1) {
+ LOG(ERROR) << "The number of planes of NativePixmapHandle is not 1 for R_8 "
+ "format";
+ return base::ScopedFD();
+ }
+ if (gmb_handle.native_pixmap_handle.planes[0].offset != 0) {
+ LOG(ERROR) << "The memory offset is not zero";
+ return base::ScopedFD();
+ }
+
+ // Fill in the memory with |data|.
+ if (!gmb->Map()) {
+ LOG(ERROR) << "Failed to map GpuMemoryBuffer";
+ return base::ScopedFD();
+ }
+ memcpy(gmb->memory(0), data, size);
+ gmb->Unmap();
+
+ return std::move(gmb_handle.native_pixmap_handle.planes[0].fd);
+}
+
+std::vector<media::VideoPixelFormat>
+MjpegDecodeAcceleratorTestEnvironment::GetSupportedDmaBufFormats() {
+ constexpr media::VideoPixelFormat kPreferredFormats[] = {
+ media::PIXEL_FORMAT_NV12,
+ media::PIXEL_FORMAT_YV12,
+ };
+ std::vector<media::VideoPixelFormat> supported_formats;
+ for (const media::VideoPixelFormat format : kPreferredFormats) {
+ const base::Optional<gfx::BufferFormat> gfx_format =
+ media::VideoPixelFormatToGfxBufferFormat(format);
+ if (gfx_format && gpu_memory_buffer_manager_->IsFormatAndUsageSupported(
+ *gfx_format, kBufferUsage))
+ supported_formats.push_back(format);
+ }
+ return supported_formats;
}
enum ClientState {
@@ -226,16 +474,17 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
JpegClient(
const std::vector<ParsedJpegImage*>& test_image_files,
std::unique_ptr<media::test::ClientStateNotification<ClientState>> note,
+ bool use_dmabuf,
bool is_skip);
~JpegClient() override;
void CreateJpegDecoder();
- void StartDecode(int32_t bitstream_buffer_id, bool do_prepare_memory = true);
- void PrepareMemory(int32_t bitstream_buffer_id);
- bool GetSoftwareDecodeResult(int32_t bitstream_buffer_id);
+ void StartDecode(int32_t task_id, bool do_prepare_memory);
+ void PrepareMemory(int32_t task_id);
+ bool GetSoftwareDecodeResult(int32_t task_id);
// MjpegDecodeAccelerator::Client implementation.
- void VideoFrameReady(int32_t bitstream_buffer_id) override;
- void NotifyError(int32_t bitstream_buffer_id,
+ void VideoFrameReady(int32_t task_id) override;
+ void NotifyError(int32_t task_id,
MjpegDecodeAccelerator::Error error) override;
// Accessors.
@@ -250,7 +499,7 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
// Save a video frame that contains a decoded JPEG. The output is a PNG file.
// The suffix will be added before the .png extension.
- void SaveToFile(int32_t bitstream_buffer_id,
+ void SaveToFile(int32_t task_id,
scoped_refptr<media::VideoFrame> in_frame,
const std::string& suffix = "");
@@ -266,25 +515,28 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
// Used to notify another thread about the state. JpegClient owns this.
std::unique_ptr<media::test::ClientStateNotification<ClientState>> note_;
+ // Use DMA-buf backed output buffer for hardware decoder.
+ bool use_dmabuf_;
+
// Skip JDA decode result. Used for testing performance.
bool is_skip_;
- // Mapped memory of input file.
+ // Input shared memory and mapping.
base::UnsafeSharedMemoryRegion in_shm_;
base::WritableSharedMemoryMapping in_shm_mapping_;
- // Mapped memory of output buffer from hardware decoder.
- std::unique_ptr<base::SharedMemory> hw_out_shm_;
- // Video frame corresponding to the output of the hardware decoder.
+ // Input DMA buffer file descriptor.
+ base::ScopedFD in_dmabuf_fd_;
+ // Output video frame from the hardware decoder.
+ std::unique_ptr<gfx::GpuMemoryBuffer> hw_out_gmb_;
+ scoped_refptr<media::VideoFrame> hw_out_dmabuf_frame_;
scoped_refptr<media::VideoFrame> hw_out_frame_;
- // Mapped memory of output buffer from software decoder.
- std::unique_ptr<base::SharedMemory> sw_out_shm_;
- // Video frame corresponding to the output of the software decoder.
+ // Output video frame from the software decoder.
scoped_refptr<media::VideoFrame> sw_out_frame_;
// This should be the first member to get destroyed because |decoder_|
// potentially uses other members in the JpegClient instance. For example,
- // as decode tasks finish in a new thread spawned by |decoder_|, |hw_out_shm_|
- // can be accessed.
+ // as decode tasks finish in a new thread spawned by |decoder_|,
+ // |hw_out_frame_| can be accessed.
std::unique_ptr<MjpegDecodeAccelerator> decoder_;
DISALLOW_COPY_AND_ASSIGN(JpegClient);
@@ -293,10 +545,12 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
JpegClient::JpegClient(
const std::vector<ParsedJpegImage*>& test_image_files,
std::unique_ptr<media::test::ClientStateNotification<ClientState>> note,
+ bool use_dmabuf,
bool is_skip)
: test_image_files_(test_image_files),
state_(CS_CREATED),
note_(std::move(note)),
+ use_dmabuf_(use_dmabuf),
is_skip_(is_skip) {}
JpegClient::~JpegClient() {}
@@ -331,19 +585,31 @@ void JpegClient::CreateJpegDecoder() {
SetState(CS_INITIALIZED);
}
-void JpegClient::VideoFrameReady(int32_t bitstream_buffer_id) {
+void JpegClient::VideoFrameReady(int32_t task_id) {
if (is_skip_) {
SetState(CS_DECODE_PASS);
return;
}
- if (!GetSoftwareDecodeResult(bitstream_buffer_id)) {
+ if (!GetSoftwareDecodeResult(task_id)) {
SetState(CS_ERROR);
return;
}
+
+ if (use_dmabuf_) {
+ // Map and convert the output frame to I420.
+ scoped_refptr<media::VideoFrame> mapped_frame = g_env->MapToVideoFrame(
+ hw_out_gmb_.get(), hw_out_dmabuf_frame_->layout(),
+ hw_out_dmabuf_frame_->visible_rect());
+ ASSERT_TRUE(mapped_frame);
+ hw_out_frame_ = media::test::ConvertVideoFrame(mapped_frame.get(),
+ media::PIXEL_FORMAT_I420);
+ ASSERT_TRUE(hw_out_frame_);
+ }
+
if (g_save_to_file) {
- SaveToFile(bitstream_buffer_id, hw_out_frame_, "_hw");
- SaveToFile(bitstream_buffer_id, sw_out_frame_, "_sw");
+ SaveToFile(task_id, hw_out_frame_, "_hw");
+ SaveToFile(task_id, sw_out_frame_, "_sw");
}
double difference = GetMeanAbsoluteDifference();
@@ -356,37 +622,50 @@ void JpegClient::VideoFrameReady(int32_t bitstream_buffer_id) {
}
}
-void JpegClient::NotifyError(int32_t bitstream_buffer_id,
+void JpegClient::NotifyError(int32_t task_id,
MjpegDecodeAccelerator::Error error) {
- LOG(ERROR) << "Notifying of error " << error << " for buffer id "
- << bitstream_buffer_id;
+ LOG(ERROR) << "Notifying of error " << error << " for task id " << task_id;
SetState(CS_ERROR);
}
-void JpegClient::PrepareMemory(int32_t bitstream_buffer_id) {
- ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id];
-
- size_t input_size = image_file->data_str.size();
- if (!in_shm_mapping_.IsValid() || input_size > in_shm_mapping_.size()) {
- in_shm_ = base::UnsafeSharedMemoryRegion::Create(input_size);
+void JpegClient::PrepareMemory(int32_t task_id) {
+ ParsedJpegImage* image_file = test_image_files_[task_id];
+
+ if (use_dmabuf_) {
+ in_dmabuf_fd_ = g_env->CreateDmaBufFd(image_file->data_str.data(),
+ image_file->data_str.size());
+ ASSERT_TRUE(in_dmabuf_fd_.is_valid());
+
+ // TODO(kamesan): create test cases for more formats when they're used.
+ std::vector<media::VideoPixelFormat> supported_formats =
+ g_env->GetSupportedDmaBufFormats();
+ ASSERT_FALSE(supported_formats.empty());
+ hw_out_dmabuf_frame_ = g_env->CreateDmaBufVideoFrame(
+ supported_formats[0], image_file->coded_size, image_file->visible_size,
+ &hw_out_gmb_);
+ ASSERT_TRUE(hw_out_dmabuf_frame_);
+ ASSERT_TRUE(hw_out_gmb_);
+ } else {
+ in_shm_mapping_ = base::WritableSharedMemoryMapping();
+ in_shm_ =
+ base::UnsafeSharedMemoryRegion::Create(image_file->data_str.size());
+ ASSERT_TRUE(in_shm_.IsValid());
in_shm_mapping_ = in_shm_.Map();
- LOG_ASSERT(in_shm_mapping_.IsValid());
- }
- memcpy(in_shm_mapping_.memory(), image_file->data_str.data(), input_size);
-
- if (!hw_out_shm_.get() ||
- image_file->output_size > hw_out_shm_->mapped_size()) {
- hw_out_shm_.reset(new base::SharedMemory);
- LOG_ASSERT(hw_out_shm_->CreateAndMapAnonymous(image_file->output_size));
+ ASSERT_TRUE(in_shm_mapping_.IsValid());
+ memcpy(in_shm_mapping_.memory(), image_file->data_str.data(),
+ image_file->data_str.size());
+
+ // MJDA only supports I420 format for SHM output buffer.
+ hw_out_frame_ = g_env->CreateShmVideoFrame(media::PIXEL_FORMAT_I420,
+ image_file->coded_size,
+ image_file->visible_size);
+ ASSERT_TRUE(hw_out_frame_);
}
- memset(hw_out_shm_->memory(), 0, image_file->output_size);
- if (!sw_out_shm_.get() ||
- image_file->output_size > sw_out_shm_->mapped_size()) {
- sw_out_shm_.reset(new base::SharedMemory);
- LOG_ASSERT(sw_out_shm_->CreateAndMapAnonymous(image_file->output_size));
- }
- memset(sw_out_shm_->memory(), 0, image_file->output_size);
+ sw_out_frame_ = g_env->CreateShmVideoFrame(media::PIXEL_FORMAT_I420,
+ image_file->coded_size,
+ image_file->visible_size);
+ ASSERT_TRUE(sw_out_frame_);
}
void JpegClient::SetState(ClientState new_state) {
@@ -395,11 +674,11 @@ void JpegClient::SetState(ClientState new_state) {
state_ = new_state;
}
-void JpegClient::SaveToFile(int32_t bitstream_buffer_id,
+void JpegClient::SaveToFile(int32_t task_id,
scoped_refptr<media::VideoFrame> in_frame,
const std::string& suffix) {
LOG_ASSERT(in_frame);
- ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id];
+ ParsedJpegImage* image_file = test_image_files_[task_id];
// First convert to ARGB format. Note that in our case, the coded size and the
// visible size will be the same.
@@ -459,13 +738,13 @@ double JpegClient::GetMeanAbsoluteDifference() {
hw_out_frame_->visible_rect().height());
const size_t columns = media::VideoFrame::Columns(
plane, media::PIXEL_FORMAT_I420, hw_out_frame_->visible_rect().width());
- LOG_ASSERT(hw_out_frame_->stride(plane) == sw_out_frame_->stride(plane));
- const int stride = hw_out_frame_->stride(plane);
+ const int hw_stride = hw_out_frame_->stride(plane);
+ const int sw_stride = sw_out_frame_->stride(plane);
for (size_t row = 0; row < rows; ++row) {
for (size_t col = 0; col < columns; ++col)
mean_abs_difference += std::abs(hw_data[col] - sw_data[col]);
- hw_data += stride;
- sw_data += stride;
+ hw_data += hw_stride;
+ sw_data += sw_stride;
}
num_samples += rows * columns;
}
@@ -474,51 +753,48 @@ double JpegClient::GetMeanAbsoluteDifference() {
return mean_abs_difference;
}
-void JpegClient::StartDecode(int32_t bitstream_buffer_id,
- bool do_prepare_memory) {
- DCHECK_LT(static_cast<size_t>(bitstream_buffer_id), test_image_files_.size());
- ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id];
+void JpegClient::StartDecode(int32_t task_id, bool do_prepare_memory) {
+ ASSERT_LT(base::checked_cast<size_t>(task_id), test_image_files_.size());
+ ParsedJpegImage* image_file = test_image_files_[task_id];
if (do_prepare_memory)
- PrepareMemory(bitstream_buffer_id);
-
- auto dup_region = base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
- in_shm_.Duplicate());
- media::BitstreamBuffer bitstream_buffer(
- bitstream_buffer_id, std::move(dup_region), image_file->data_str.size());
-
- hw_out_frame_ = media::VideoFrame::WrapExternalSharedMemory(
- media::PIXEL_FORMAT_I420, image_file->coded_size,
- gfx::Rect(image_file->visible_size), image_file->visible_size,
- static_cast<uint8_t*>(hw_out_shm_->memory()), image_file->output_size,
- hw_out_shm_->handle(), 0, base::TimeDelta());
- LOG_ASSERT(hw_out_frame_.get());
-
- decoder_->Decode(std::move(bitstream_buffer), hw_out_frame_);
-}
-
-bool JpegClient::GetSoftwareDecodeResult(int32_t bitstream_buffer_id) {
- ParsedJpegImage* image_file = test_image_files_[bitstream_buffer_id];
- sw_out_frame_ = media::VideoFrame::WrapExternalSharedMemory(
- media::PIXEL_FORMAT_I420, image_file->coded_size,
- gfx::Rect(image_file->visible_size), image_file->visible_size,
- static_cast<uint8_t*>(sw_out_shm_->memory()), image_file->output_size,
- sw_out_shm_->handle(), 0, base::TimeDelta());
- LOG_ASSERT(sw_out_shm_.get());
-
- if (libyuv::ConvertToI420(static_cast<uint8_t*>(in_shm_mapping_.memory()),
- image_file->data_str.size(),
- sw_out_frame_->data(media::VideoFrame::kYPlane),
- sw_out_frame_->stride(media::VideoFrame::kYPlane),
- sw_out_frame_->data(media::VideoFrame::kUPlane),
- sw_out_frame_->stride(media::VideoFrame::kUPlane),
- sw_out_frame_->data(media::VideoFrame::kVPlane),
- sw_out_frame_->stride(media::VideoFrame::kVPlane),
- 0, 0, sw_out_frame_->visible_rect().width(),
- sw_out_frame_->visible_rect().height(),
- sw_out_frame_->visible_rect().width(),
- sw_out_frame_->visible_rect().height(),
- libyuv::kRotate0, libyuv::FOURCC_MJPG) != 0) {
+ PrepareMemory(task_id);
+
+ if (use_dmabuf_) {
+ base::ScopedFD duped_in_dmabuf_fd(HANDLE_EINTR(dup(in_dmabuf_fd_.get())));
+ ASSERT_TRUE(duped_in_dmabuf_fd.is_valid());
+ decoder_->Decode(task_id, std::move(duped_in_dmabuf_fd),
+ image_file->data_str.size(), 0 /* src_offset */,
+ hw_out_dmabuf_frame_);
+ } else {
+ base::subtle::PlatformSharedMemoryRegion dup_region =
+ base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
+ in_shm_.Duplicate());
+ ASSERT_EQ(dup_region.GetSize(), image_file->data_str.size());
+ media::BitstreamBuffer bitstream_buffer(task_id, std::move(dup_region),
+ dup_region.GetSize());
+ decoder_->Decode(std::move(bitstream_buffer), hw_out_frame_);
+ }
+}
+
+bool JpegClient::GetSoftwareDecodeResult(int32_t task_id) {
+ DCHECK(sw_out_frame_->IsMappable());
+ DCHECK_EQ(sw_out_frame_->format(), media::PIXEL_FORMAT_I420);
+ ParsedJpegImage* image_file = test_image_files_[task_id];
+ if (libyuv::ConvertToI420(
+ reinterpret_cast<const uint8_t*>(image_file->data_str.data()),
+ image_file->data_str.size(),
+ sw_out_frame_->data(media::VideoFrame::kYPlane),
+ sw_out_frame_->stride(media::VideoFrame::kYPlane),
+ sw_out_frame_->data(media::VideoFrame::kUPlane),
+ sw_out_frame_->stride(media::VideoFrame::kUPlane),
+ sw_out_frame_->data(media::VideoFrame::kVPlane),
+ sw_out_frame_->stride(media::VideoFrame::kVPlane), 0, 0,
+ sw_out_frame_->visible_rect().width(),
+ sw_out_frame_->visible_rect().height(),
+ sw_out_frame_->visible_rect().width(),
+ sw_out_frame_->visible_rect().height(), libyuv::kRotate0,
+ libyuv::FOURCC_MJPG) != 0) {
LOG(ERROR) << "Software decode " << image_file->filename() << " failed.";
return false;
}
@@ -545,7 +821,7 @@ class ScopedJpegClient {
DISALLOW_COPY_AND_ASSIGN(ScopedJpegClient);
};
-class MjpegDecodeAcceleratorTest : public ::testing::Test {
+class MjpegDecodeAcceleratorTest : public ::testing::TestWithParam<bool> {
protected:
MjpegDecodeAcceleratorTest() = default;
@@ -575,7 +851,7 @@ void MjpegDecodeAcceleratorTest::TestDecode(
auto client = std::make_unique<JpegClient>(
images,
std::make_unique<media::test::ClientStateNotification<ClientState>>(),
- false /* is_skip */);
+ GetParam() /* use_dmabuf */, false /* is_skip */);
scoped_clients.emplace_back(
new ScopedJpegClient(decoder_thread.task_runner(), std::move(client)));
@@ -591,7 +867,7 @@ void MjpegDecodeAcceleratorTest::TestDecode(
decoder_thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&JpegClient::StartDecode,
base::Unretained(scoped_client->client()),
- index, true));
+ index, true /* do_prepare_memory */));
}
if (index < expected_status.size()) {
for (const auto& scoped_client : scoped_clients) {
@@ -612,7 +888,7 @@ void MjpegDecodeAcceleratorTest::PerfDecodeByJDA(
auto client = std::make_unique<JpegClient>(
images,
std::make_unique<media::test::ClientStateNotification<ClientState>>(),
- true /* is_skip */);
+ GetParam() /* use_dmabuf */, true /* is_skip */);
auto scoped_client = std::make_unique<ScopedJpegClient>(
decoder_thread.task_runner(), std::move(client));
@@ -621,14 +897,14 @@ void MjpegDecodeAcceleratorTest::PerfDecodeByJDA(
base::Unretained(scoped_client->client())));
ASSERT_EQ(scoped_client->client()->note()->Wait(), CS_INITIALIZED);
- const int32_t bitstream_buffer_id = 0;
- scoped_client->client()->PrepareMemory(bitstream_buffer_id);
+ const int32_t task_id = 0;
+ scoped_client->client()->PrepareMemory(task_id);
const base::ElapsedTimer timer;
for (int index = 0; index < decode_times; index++) {
decoder_thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&JpegClient::StartDecode,
base::Unretained(scoped_client->client()),
- bitstream_buffer_id, false));
+ task_id, false /* do_prepare_memory */));
ASSERT_EQ(scoped_client->client()->note()->Wait(), CS_DECODE_PASS);
}
const base::TimeDelta elapsed_time = timer.Elapsed();
@@ -647,13 +923,13 @@ void MjpegDecodeAcceleratorTest::PerfDecodeBySW(
std::unique_ptr<JpegClient> client = std::make_unique<JpegClient>(
images,
std::make_unique<media::test::ClientStateNotification<ClientState>>(),
- true /* is_skip */);
+ false /* use_dmabuf */, true /* is_skip */);
- const int32_t bitstream_buffer_id = 0;
- client->PrepareMemory(bitstream_buffer_id);
+ const int32_t task_id = 0;
+ client->PrepareMemory(task_id);
const base::ElapsedTimer timer;
for (int index = 0; index < decode_times; index++)
- client->GetSoftwareDecodeResult(bitstream_buffer_id);
+ client->GetSoftwareDecodeResult(task_id);
const base::TimeDelta elapsed_time = timer.Elapsed();
LOG(INFO) << elapsed_time << " for " << decode_times
<< " iterations (avg: " << elapsed_time / decode_times << ") -- "
@@ -696,7 +972,7 @@ scoped_refptr<media::VideoFrame> GetTestDecodedData() {
}
TEST(JpegClientTest, GetMeanAbsoluteDifference) {
- JpegClient client(std::vector<ParsedJpegImage*>(), nullptr, false);
+ JpegClient client(std::vector<ParsedJpegImage*>(), nullptr, false, false);
client.hw_out_frame_ = GetTestDecodedData();
client.sw_out_frame_ = GetTestDecodedData();
@@ -730,7 +1006,7 @@ TEST(JpegClientTest, GetMeanAbsoluteDifference) {
kMaxAllowedDifference);
}
-TEST_F(MjpegDecodeAcceleratorTest, SimpleDecode) {
+TEST_P(MjpegDecodeAcceleratorTest, SimpleDecode) {
std::vector<ParsedJpegImage*> images;
for (auto& image : g_env->image_data_user_)
images.push_back(image.get());
@@ -738,7 +1014,7 @@ TEST_F(MjpegDecodeAcceleratorTest, SimpleDecode) {
TestDecode(images, expected_status);
}
-TEST_F(MjpegDecodeAcceleratorTest, MultipleDecoders) {
+TEST_P(MjpegDecodeAcceleratorTest, MultipleDecoders) {
std::vector<ParsedJpegImage*> images;
for (auto& image : g_env->image_data_user_)
images.push_back(image.get());
@@ -746,7 +1022,7 @@ TEST_F(MjpegDecodeAcceleratorTest, MultipleDecoders) {
TestDecode(images, expected_status, 3 /* num_concurrent_decoders */);
}
-TEST_F(MjpegDecodeAcceleratorTest, InputSizeChange) {
+TEST_P(MjpegDecodeAcceleratorTest, InputSizeChange) {
// The size of |image_data_1280x720_black_| is smaller than
// |image_data_1280x720_default_|.
const std::vector<ParsedJpegImage*> images = {
@@ -757,7 +1033,7 @@ TEST_F(MjpegDecodeAcceleratorTest, InputSizeChange) {
TestDecode(images, expected_status);
}
-TEST_F(MjpegDecodeAcceleratorTest, ResolutionChange) {
+TEST_P(MjpegDecodeAcceleratorTest, ResolutionChange) {
const std::vector<ParsedJpegImage*> images = {
g_env->image_data_640x368_black_.get(),
g_env->image_data_1280x720_default_.get(),
@@ -766,7 +1042,7 @@ TEST_F(MjpegDecodeAcceleratorTest, ResolutionChange) {
TestDecode(images, expected_status);
}
-TEST_F(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
+TEST_P(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
const std::vector<ParsedJpegImage*> images = {
g_env->image_data_640x360_black_.get()};
const std::vector<ClientState> expected_status = {CS_DECODE_PASS};
@@ -774,7 +1050,7 @@ TEST_F(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
}
// Tests whether different JPEG sampling formats will be decoded correctly.
-TEST_F(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
+TEST_P(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
const std::vector<ParsedJpegImage*> images = {
g_env->image_data_640x368_black_.get(),
g_env->image_data_640x368_422_black_.get()};
@@ -782,14 +1058,14 @@ TEST_F(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
TestDecode(images, expected_status);
}
-TEST_F(MjpegDecodeAcceleratorTest, FailureJpeg) {
+TEST_P(MjpegDecodeAcceleratorTest, FailureJpeg) {
const std::vector<ParsedJpegImage*> images = {
g_env->image_data_invalid_.get()};
const std::vector<ClientState> expected_status = {CS_ERROR};
TestDecode(images, expected_status);
}
-TEST_F(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
+TEST_P(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
const std::vector<ParsedJpegImage*> images = {
g_env->image_data_invalid_.get(),
g_env->image_data_1280x720_default_.get()};
@@ -797,7 +1073,7 @@ TEST_F(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
TestDecode(images, expected_status);
}
-TEST_F(MjpegDecodeAcceleratorTest, Abort) {
+TEST_P(MjpegDecodeAcceleratorTest, Abort) {
constexpr size_t kNumOfJpegToDecode = 5;
const std::vector<ParsedJpegImage*> images(
kNumOfJpegToDecode, g_env->image_data_1280x720_default_.get());
@@ -808,7 +1084,7 @@ TEST_F(MjpegDecodeAcceleratorTest, Abort) {
TestDecode(images, expected_status, 2 /* num_concurrent_decoders */);
}
-TEST_F(MjpegDecodeAcceleratorTest, PerfJDA) {
+TEST_P(MjpegDecodeAcceleratorTest, PerfJDA) {
// Only the first image will be used for perf testing.
ASSERT_GE(g_env->image_data_user_.size(), 1u);
const std::vector<ParsedJpegImage*> images = {
@@ -824,6 +1100,15 @@ TEST_F(MjpegDecodeAcceleratorTest, PerfSW) {
PerfDecodeBySW(g_env->perf_decode_times_, images);
}
+std::string TestParamToString(::testing::TestParamInfo<bool> param_info) {
+ return param_info.param ? "DMABUF" : "SHMEM";
+}
+
+INSTANTIATE_TEST_SUITE_P(,
+ MjpegDecodeAcceleratorTest,
+ ::testing::Bool(),
+ TestParamToString);
+
} // namespace
} // namespace chromeos_camera
@@ -840,7 +1125,7 @@ int main(int argc, char** argv) {
LOG_ASSERT(logging::InitLogging(settings));
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- DCHECK(cmd_line);
+ LOG_ASSERT(cmd_line);
const base::FilePath::CharType* jpeg_filenames = nullptr;
const base::FilePath::CharType* test_data_path = nullptr;
diff --git a/chromium/components/chromeos_camera/mojo_jpeg_encode_accelerator_service.cc b/chromium/components/chromeos_camera/mojo_jpeg_encode_accelerator_service.cc
index b0d57b5fa26..d6328917efb 100644
--- a/chromium/components/chromeos_camera/mojo_jpeg_encode_accelerator_service.cc
+++ b/chromium/components/chromeos_camera/mojo_jpeg_encode_accelerator_service.cc
@@ -14,10 +14,13 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "components/chromeos_camera/common/dmabuf.mojom.h"
+#include "components/chromeos_camera/dmabuf_utils.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -31,45 +34,6 @@ namespace {
const int kJpegQuality = 90;
-scoped_refptr<media::VideoFrame> ConstructVideoFrame(
- std::vector<chromeos_camera::mojom::DmaBufPlanePtr> dma_buf_planes,
- media::VideoPixelFormat pixel_format,
- int32_t width,
- int32_t height) {
- size_t num_planes = media::VideoFrame::NumPlanes(pixel_format);
- if (num_planes != dma_buf_planes.size()) {
- DLOG(ERROR) << "The amount of DMA buf planes does not match the format.";
- return nullptr;
- }
- if (width <= 0 || height <= 0) {
- DLOG(ERROR) << "Width and height should > 0: " << width << ", " << height;
- return nullptr;
- }
- gfx::Size coded_size(width, height);
- gfx::Rect visible_rect(coded_size);
-
- std::vector<base::ScopedFD> dma_buf_fds(num_planes);
- std::vector<media::VideoFrameLayout::Plane> planes(num_planes);
-
- for (size_t i = 0; i < num_planes; ++i) {
- dma_buf_fds[i] =
- mojo::UnwrapPlatformHandle(std::move(dma_buf_planes[i]->fd_handle))
- .TakeFD();
- planes[i].stride = dma_buf_planes[i]->stride;
- planes[i].offset = dma_buf_planes[i]->offset;
- planes[i].size = dma_buf_planes[i]->size;
- }
- auto layout = media::VideoFrameLayout::CreateWithPlanes(
- pixel_format, coded_size, std::move(planes));
-
- return media::VideoFrame::WrapExternalDmabufs(
- *layout, // layout
- visible_rect, // visible_rect
- coded_size, // natural_size
- std::move(dma_buf_fds), // dmabuf_fds
- base::TimeDelta()); // timestamp
-}
-
media::VideoPixelFormat ToVideoPixelFormat(uint32_t fourcc_fmt) {
switch (fourcc_fmt) {
case V4L2_PIX_FMT_NV12:
@@ -197,14 +161,16 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
return;
}
- base::UnguessableToken input_guid = base::UnguessableToken::Create();
- base::SharedMemoryHandle input_shm_handle(
- base::FileDescriptor(input_fd, true), input_buffer_size, input_guid);
+ base::UnsafeSharedMemoryRegion input_region =
+ base::UnsafeSharedMemoryRegion::Deserialize(
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ base::ScopedFD(input_fd),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ input_buffer_size, base::UnguessableToken::Create()));
base::subtle::PlatformSharedMemoryRegion output_shm_region =
base::subtle::PlatformSharedMemoryRegion::Take(
- base::subtle::ScopedFDPair(base::ScopedFD(output_fd),
- base::ScopedFD()),
+ base::ScopedFD(output_fd),
base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
output_buffer_size, base::UnguessableToken::Create());
@@ -236,8 +202,8 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
task_id, std::move(callback));
encode_cb_map_.emplace(task_id, std::move(wrapped_callback));
- auto input_shm = std::make_unique<base::SharedMemory>(input_shm_handle, true);
- if (!input_shm->Map(input_buffer_size)) {
+ base::WritableSharedMemoryMapping input_mapping = input_region.Map();
+ if (!input_mapping.IsValid()) {
DLOG(ERROR) << "Could not map input shared memory for buffer id "
<< task_id;
NotifyEncodeStatus(
@@ -246,18 +212,15 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
return;
}
- uint8_t* input_shm_memory = static_cast<uint8_t*>(input_shm->memory());
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
- media::PIXEL_FORMAT_I420, // format
- coded_size, // coded_size
- gfx::Rect(coded_size), // visible_rect
- coded_size, // natural_size
- input_shm_memory, // data
- input_buffer_size, // data_size
- input_shm_handle, // handle
- 0, // data_offset
- base::TimeDelta()); // timestamp
+ uint8_t* input_shm_memory = input_mapping.GetMemoryAsSpan<uint8_t>().data();
+ scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData(
+ media::PIXEL_FORMAT_I420, // format
+ coded_size, // coded_size
+ gfx::Rect(coded_size), // visible_rect
+ coded_size, // natural_size
+ input_shm_memory, // data
+ input_buffer_size, // data_size
+ base::TimeDelta()); // timestamp
if (!frame.get()) {
LOG(ERROR) << "Could not create VideoFrame for buffer id " << task_id;
NotifyEncodeStatus(
@@ -265,10 +228,8 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return;
}
- // Keep |input_shm| referenced until |frame| is destructed.
- frame->AddDestructionObserver(base::BindOnce(
- base::DoNothing::Once<std::unique_ptr<base::SharedMemory>>(),
- base::Passed(&input_shm)));
+ frame->BackWithOwnedSharedMemory(std::move(input_region),
+ std::move(input_mapping));
DCHECK(accelerator_);
accelerator_->Encode(frame, kJpegQuality, exif_buffer.get(),
@@ -286,7 +247,9 @@ void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf(
int32_t coded_size_height,
EncodeWithDmaBufCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (coded_size_width <= 0 || coded_size_height <= 0) {
+
+ const gfx::Size coded_size(coded_size_width, coded_size_height);
+ if (coded_size.IsEmpty()) {
std::move(callback).Run(
0, ::chromeos_camera::JpegEncodeAccelerator::Status::INVALID_ARGUMENT);
return;
@@ -305,16 +268,14 @@ void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf(
}
auto input_video_frame = ConstructVideoFrame(
- std::move(input_planes), ToVideoPixelFormat(input_format),
- coded_size_width, coded_size_height);
+ std::move(input_planes), ToVideoPixelFormat(input_format), coded_size);
if (!input_video_frame) {
std::move(callback).Run(
0, ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return;
}
- auto output_video_frame =
- ConstructVideoFrame(std::move(output_planes), media::PIXEL_FORMAT_MJPEG,
- coded_size_width, coded_size_height);
+ auto output_video_frame = ConstructVideoFrame(
+ std::move(output_planes), media::PIXEL_FORMAT_MJPEG, coded_size);
if (!output_video_frame) {
std::move(callback).Run(
0, ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
diff --git a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.cc b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.cc
index 8c9cc8e5065..39af013fb0b 100644
--- a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.cc
+++ b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.cc
@@ -53,22 +53,20 @@ void MojoMjpegDecodeAccelerator::Decode(
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
DCHECK(jpeg_decoder_.is_bound());
- DCHECK(
- base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle()));
-
- base::SharedMemoryHandle output_handle =
- base::SharedMemory::DuplicateHandle(video_frame->shared_memory_handle());
- if (!base::SharedMemory::IsHandleValid(output_handle)) {
- DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
- return;
- }
+ DCHECK(video_frame->storage_type() == media::VideoFrame::STORAGE_SHMEM)
+ << video_frame->storage_type();
size_t output_buffer_size = media::VideoFrame::AllocationSize(
video_frame->format(), video_frame->coded_size());
+ DCHECK_GE(video_frame->shm_region()->GetSize(), output_buffer_size);
+
mojo::ScopedSharedBufferHandle output_frame_handle =
- mojo::WrapSharedMemoryHandle(
- output_handle, output_buffer_size,
- mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ mojo::WrapUnsafeSharedMemoryRegion(
+ video_frame->shm_region()->Duplicate());
+ if (!output_frame_handle.is_valid()) {
+ DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
+ return;
+ }
// base::Unretained is safe because |this| owns |jpeg_decoder_|.
jpeg_decoder_->Decode(std::move(bitstream_buffer), video_frame->coded_size(),
@@ -78,6 +76,15 @@ void MojoMjpegDecodeAccelerator::Decode(
base::Unretained(this)));
}
+void MojoMjpegDecodeAccelerator::Decode(
+ int32_t task_id,
+ base::ScopedFD src_dmabuf_fd,
+ size_t src_size,
+ off_t src_offset,
+ scoped_refptr<media::VideoFrame> dst_frame) {
+ NOTIMPLEMENTED();
+}
+
bool MojoMjpegDecodeAccelerator::IsSupported() {
return true;
}
@@ -118,7 +125,7 @@ void MojoMjpegDecodeAccelerator::OnDecodeAck(
void MojoMjpegDecodeAccelerator::OnLostConnectionToJpegDecoder() {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
OnDecodeAck(
- kInvalidBitstreamBufferId,
+ kInvalidTaskId,
::chromeos_camera::MjpegDecodeAccelerator::Error::PLATFORM_FAILURE);
}
diff --git a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h
index 1b57915e7a1..51b68e2acab 100644
--- a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h
+++ b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h
@@ -36,6 +36,11 @@ class MojoMjpegDecodeAccelerator : public MjpegDecodeAccelerator {
void InitializeAsync(Client* client, InitCB init_cb) override;
void Decode(media::BitstreamBuffer bitstream_buffer,
scoped_refptr<media::VideoFrame> video_frame) override;
+ void Decode(int32_t task_id,
+ base::ScopedFD src_dmabuf_fd,
+ size_t src_size,
+ off_t src_offset,
+ scoped_refptr<media::VideoFrame> dst_frame) override;
bool IsSupported() override;
private:
diff --git a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.cc b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.cc
index 694231ee91a..57b855a84c9 100644
--- a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.cc
+++ b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.cc
@@ -10,24 +10,28 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/platform_file.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
+#include "base/memory/shared_memory_handle.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/numerics/safe_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
-#include "media/base/bind_to_current_loop.h"
+#include "components/chromeos_camera/common/dmabuf.mojom.h"
+#include "components/chromeos_camera/dmabuf_utils.h"
+#include "media/base/bitstream_buffer.h"
+#include "media/base/video_frame.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace {
-void DecodeFinished(std::unique_ptr<base::SharedMemory> shm) {
- // Do nothing. Because VideoFrame is backed by |shm|, the purpose of this
- // function is to just keep reference of |shm| to make sure it lives until
- // decode finishes.
-}
-
bool VerifyDecodeParams(const gfx::Size& coded_size,
mojo::ScopedSharedBufferHandle* output_handle,
uint32_t output_buffer_size) {
@@ -124,15 +128,16 @@ void MojoMjpegDecodeAcceleratorService::Decode(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
TRACE_EVENT0("jpeg", "MojoMjpegDecodeAcceleratorService::Decode");
- DCHECK_EQ(decode_cb_map_.count(input_buffer.id()), 0u);
- if (decode_cb_map_.count(input_buffer.id()) != 0) {
+ DCHECK_EQ(mojo_cb_map_.count(input_buffer.id()), 0u);
+ if (mojo_cb_map_.count(input_buffer.id()) != 0) {
NotifyDecodeStatus(
input_buffer.id(),
::chromeos_camera::MjpegDecodeAccelerator::Error::INVALID_ARGUMENT);
return;
}
- decode_cb_map_[input_buffer.id()] = std::move(callback);
+ mojo_cb_map_[input_buffer.id()] =
+ base::BindOnce(std::move(callback), input_buffer.id());
if (!VerifyDecodeParams(coded_size, &output_handle, output_buffer_size)) {
NotifyDecodeStatus(
@@ -141,14 +146,14 @@ void MojoMjpegDecodeAcceleratorService::Decode(
return;
}
- base::SharedMemoryHandle memory_handle;
- MojoResult result = mojo::UnwrapSharedMemoryHandle(
- std::move(output_handle), &memory_handle, nullptr, nullptr);
- DCHECK_EQ(MOJO_RESULT_OK, result);
+ base::UnsafeSharedMemoryRegion output_region =
+ mojo::UnwrapUnsafeSharedMemoryRegion(std::move(output_handle));
+ DCHECK(output_region.IsValid());
+ DCHECK_GE(output_region.GetSize(), output_buffer_size);
- std::unique_ptr<base::SharedMemory> output_shm(
- new base::SharedMemory(memory_handle, false));
- if (!output_shm->Map(output_buffer_size)) {
+ base::WritableSharedMemoryMapping mapping =
+ output_region.MapAt(0, output_buffer_size);
+ if (!mapping.IsValid()) {
LOG(ERROR) << "Could not map output shared memory for input buffer id "
<< input_buffer.id();
NotifyDecodeStatus(
@@ -157,18 +162,15 @@ void MojoMjpegDecodeAcceleratorService::Decode(
return;
}
- uint8_t* shm_memory = static_cast<uint8_t*>(output_shm->memory());
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalSharedMemory(
- media::PIXEL_FORMAT_I420, // format
- coded_size, // coded_size
- gfx::Rect(coded_size), // visible_rect
- coded_size, // natural_size
- shm_memory, // data
- output_buffer_size, // data_size
- memory_handle, // handle
- 0, // data_offset
- base::TimeDelta()); // timestamp
+ uint8_t* shm_memory = mapping.GetMemoryAsSpan<uint8_t>().data();
+ scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData(
+ media::PIXEL_FORMAT_I420, // format
+ coded_size, // coded_size
+ gfx::Rect(coded_size), // visible_rect
+ coded_size, // natural_size
+ shm_memory, // data
+ output_buffer_size, // data_size
+ base::TimeDelta()); // timestamp
if (!frame.get()) {
LOG(ERROR) << "Could not create VideoFrame for input buffer id "
<< input_buffer.id();
@@ -177,8 +179,8 @@ void MojoMjpegDecodeAcceleratorService::Decode(
::chromeos_camera::MjpegDecodeAccelerator::Error::PLATFORM_FAILURE);
return;
}
- frame->AddDestructionObserver(
- base::Bind(DecodeFinished, base::Passed(&output_shm)));
+ frame->BackWithOwnedSharedMemory(std::move(output_region),
+ std::move(mapping));
DCHECK(accelerator_);
accelerator_->Decode(std::move(input_buffer), frame);
@@ -193,7 +195,6 @@ void MojoMjpegDecodeAcceleratorService::DecodeWithFD(
mojo::ScopedHandle output_handle,
uint32_t output_buffer_size,
DecodeWithFDCallback callback) {
-#if defined(OS_CHROMEOS)
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::PlatformFile input_fd;
base::PlatformFile output_fd;
@@ -217,27 +218,68 @@ void MojoMjpegDecodeAcceleratorService::DecodeWithFD(
base::subtle::PlatformSharedMemoryRegion input_shm_region =
base::subtle::PlatformSharedMemoryRegion::Take(
- base::subtle::ScopedFDPair(base::ScopedFD(input_fd),
- base::ScopedFD()),
+ base::ScopedFD(input_fd),
base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
input_buffer_size, base::UnguessableToken::Create());
media::BitstreamBuffer in_buffer(buffer_id, std::move(input_shm_region),
input_buffer_size);
gfx::Size coded_size(coded_size_width, coded_size_height);
- base::SharedMemoryHandle output_shm_handle(
- base::FileDescriptor(output_fd, true), output_buffer_size,
- base::UnguessableToken::Create());
+ base::subtle::PlatformSharedMemoryRegion output_shm_region =
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ base::ScopedFD(output_fd),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ output_buffer_size, base::UnguessableToken::Create());
mojo::ScopedSharedBufferHandle output_scoped_handle =
- mojo::WrapSharedMemoryHandle(
- output_shm_handle, output_buffer_size,
- mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+ mojo::WrapPlatformSharedMemoryRegion(std::move(output_shm_region));
Decode(std::move(in_buffer), coded_size, std::move(output_scoped_handle),
output_buffer_size, std::move(callback));
-#else
- NOTREACHED();
-#endif
+}
+
+void MojoMjpegDecodeAcceleratorService::DecodeWithDmaBuf(
+ int32_t task_id,
+ mojo::ScopedHandle src_dmabuf_fd,
+ uint32_t src_size,
+ uint32_t src_offset,
+ mojom::DmaBufVideoFramePtr dst_frame,
+ DecodeWithDmaBufCallback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ TRACE_EVENT0("jpeg", __FUNCTION__);
+
+ if (src_size == 0) {
+ LOG(ERROR) << "Input buffer size should be positive";
+ std::move(callback).Run(
+ ::chromeos_camera::MjpegDecodeAccelerator::Error::INVALID_ARGUMENT);
+ return;
+ }
+ mojo::PlatformHandle src_handle =
+ mojo::UnwrapPlatformHandle(std::move(src_dmabuf_fd));
+ if (!src_handle.is_valid()) {
+ LOG(ERROR) << "Invalid input DMA-buf FD";
+ std::move(callback).Run(
+ ::chromeos_camera::MjpegDecodeAccelerator::Error::INVALID_ARGUMENT);
+ return;
+ }
+
+ const gfx::Size coded_size(base::checked_cast<int>(dst_frame->coded_width),
+ base::checked_cast<int>(dst_frame->coded_height));
+ scoped_refptr<media::VideoFrame> frame = ConstructVideoFrame(
+ std::move(dst_frame->planes), dst_frame->format, coded_size);
+ if (!frame) {
+ LOG(ERROR) << "Failed to create video frame";
+ std::move(callback).Run(
+ ::chromeos_camera::MjpegDecodeAccelerator::Error::INVALID_ARGUMENT);
+ return;
+ }
+
+ DCHECK_EQ(mojo_cb_map_.count(task_id), 0u);
+ mojo_cb_map_[task_id] = std::move(callback);
+
+ DCHECK(accelerator_);
+ accelerator_->Decode(task_id, src_handle.TakeFD(),
+ base::strict_cast<size_t>(src_size),
+ base::strict_cast<off_t>(src_offset), std::move(frame));
}
void MojoMjpegDecodeAcceleratorService::Uninitialize() {
@@ -250,16 +292,16 @@ void MojoMjpegDecodeAcceleratorService::NotifyDecodeStatus(
::chromeos_camera::MjpegDecodeAccelerator::Error error) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- auto iter = decode_cb_map_.find(bitstream_buffer_id);
- DCHECK(iter != decode_cb_map_.end());
- if (iter == decode_cb_map_.end()) {
+ auto iter = mojo_cb_map_.find(bitstream_buffer_id);
+ DCHECK(iter != mojo_cb_map_.end());
+ if (iter == mojo_cb_map_.end()) {
// Silently ignoring abnormal case.
return;
}
- DecodeCallback decode_cb = std::move(iter->second);
- decode_cb_map_.erase(iter);
- std::move(decode_cb).Run(bitstream_buffer_id, error);
+ MojoCallback mojo_cb = std::move(iter->second);
+ mojo_cb_map_.erase(iter);
+ std::move(mojo_cb).Run(error);
}
} // namespace chromeos_camera
diff --git a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.h b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.h
index a5565d0c555..bc488886201 100644
--- a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.h
+++ b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service.h
@@ -7,8 +7,10 @@
#include <stdint.h>
+#include <map>
#include <memory>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
@@ -36,7 +38,10 @@ class MojoMjpegDecodeAcceleratorService
::chromeos_camera::MjpegDecodeAccelerator::Error error) override;
private:
- using DecodeCallbackMap = std::unordered_map<int32_t, DecodeCallback>;
+ // A common wrapper type for Mojo callbacks of Decode* functions.
+ using MojoCallback = base::OnceCallback<void(
+ ::chromeos_camera::MjpegDecodeAccelerator::Error)>;
+ using MojoCallbackMap = std::map<int32_t, MojoCallback>;
// This constructor internally calls
// GpuMjpegDecodeAcceleratorFactory::GetAcceleratorFactories() to
@@ -58,6 +63,12 @@ class MojoMjpegDecodeAcceleratorService
mojo::ScopedHandle output_fd,
uint32_t output_buffer_size,
DecodeWithFDCallback callback) override;
+ void DecodeWithDmaBuf(int32_t task_id,
+ mojo::ScopedHandle src_dmabuf_fd,
+ uint32_t src_size,
+ uint32_t src_offset,
+ mojom::DmaBufVideoFramePtr dst_frame,
+ DecodeWithDmaBufCallback callback) override;
void Uninitialize() override;
void NotifyDecodeStatus(
@@ -67,8 +78,8 @@ class MojoMjpegDecodeAcceleratorService
const std::vector<GpuMjpegDecodeAcceleratorFactory::CreateAcceleratorCB>
accelerator_factory_functions_;
- // A map from bitstream_buffer_id to DecodeCallback.
- DecodeCallbackMap decode_cb_map_;
+ // A map from |task_id| to MojoCallback.
+ MojoCallbackMap mojo_cb_map_;
std::unique_ptr<::chromeos_camera::MjpegDecodeAccelerator> accelerator_;
diff --git a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service_unittest.cc b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service_unittest.cc
index ca2e74f871e..ab46b311c93 100644
--- a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service_unittest.cc
+++ b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator_service_unittest.cc
@@ -8,7 +8,7 @@
#include "base/command_line.h"
#include "base/memory/platform_shared_memory_region.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -46,7 +46,7 @@ class MojoMjpegDecodeAcceleratorServiceTest : public ::testing::Test {
private:
// This is required to allow base::ThreadTaskRunnerHandle::Get() from the
// test execution thread.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(MojoMjpegDecodeAcceleratorServiceTest, InitializeAndDecode) {
@@ -73,8 +73,12 @@ TEST_F(MojoMjpegDecodeAcceleratorServiceTest, InitializeAndDecode) {
base::subtle::PlatformSharedMemoryRegion::CreateUnsafe(
kInputBufferSizeInBytes);
+ // mojo::SharedBufferHandle::Create will make a writable region, but an unsafe
+ // one is needed.
mojo::ScopedSharedBufferHandle output_frame_handle =
- mojo::SharedBufferHandle::Create(kOutputFrameSizeInBytes);
+ mojo::WrapPlatformSharedMemoryRegion(
+ base::subtle::PlatformSharedMemoryRegion::CreateUnsafe(
+ kOutputFrameSizeInBytes));
media::BitstreamBuffer bitstream_buffer(kArbitraryBitstreamBufferId,
std::move(shm_region),
diff --git a/chromium/components/cloud_devices/common/cloud_device_description.cc b/chromium/components/cloud_devices/common/cloud_device_description.cc
index 513a24f97f8..4cdf39dc9a6 100644
--- a/chromium/components/cloud_devices/common/cloud_device_description.cc
+++ b/chromium/components/cloud_devices/common/cloud_device_description.cc
@@ -22,11 +22,11 @@ CloudDeviceDescription::CloudDeviceDescription()
CloudDeviceDescription::~CloudDeviceDescription() = default;
bool CloudDeviceDescription::InitFromString(const std::string& json) {
- std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
+ base::Optional<base::Value> value = base::JSONReader::Read(json);
if (!value)
return false;
- return InitFromValue(base::Value::FromUniquePtrValue(std::move(value)));
+ return InitFromValue(std::move(*value));
}
bool CloudDeviceDescription::InitFromValue(base::Value ticket) {
diff --git a/chromium/components/cloud_devices/common/printer_description_unittest.cc b/chromium/components/cloud_devices/common/printer_description_unittest.cc
index 776892cbc36..5ef909e3545 100644
--- a/chromium/components/cloud_devices/common/printer_description_unittest.cc
+++ b/chromium/components/cloud_devices/common/printer_description_unittest.cc
@@ -17,587 +17,584 @@ namespace cloud_devices {
namespace printer {
-// Replaces ' with " to allow readable JSON constants in tests.
// Makes sure that same JSON value represented by same strings to simplify
// comparison.
std::string NormalizeJson(const std::string& json) {
- std::string result = json;
- base::ReplaceChars(result, "'", "\"", &result);
- std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(result);
- base::JSONWriter::Write(*value, &result);
+ std::string result;
+ base::JSONWriter::Write(*base::JSONReader::Read(json), &result);
return result;
}
-const char kCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'supported_content_type': [ {"
- " 'content_type': 'image/pwg-raster'"
- " }, {"
- " 'content_type': 'image/jpeg'"
- " } ],"
- " 'pwg_raster_config': {"
- " 'document_sheet_back': 'MANUAL_TUMBLE',"
- " 'reverse_order_streaming': true"
- " },"
- " 'color': {"
- " 'option': [ {"
- " 'is_default': true,"
- " 'type': 'STANDARD_COLOR'"
- " }, {"
- " 'type': 'STANDARD_MONOCHROME'"
- " }, {"
- " 'type': 'CUSTOM_MONOCHROME',"
- " 'vendor_id': '123',"
- " 'custom_display_name': 'monochrome'"
- " } ]"
- " },"
- " 'duplex': {"
- " 'option': [ {"
- " 'is_default': true,"
- " 'type': 'LONG_EDGE'"
- " }, {"
- " 'type': 'SHORT_EDGE'"
- " }, {"
- " 'type': 'NO_DUPLEX'"
- " } ]"
- " },"
- " 'page_orientation': {"
- " 'option': [ {"
- " 'type': 'PORTRAIT'"
- " }, {"
- " 'type': 'LANDSCAPE'"
- " }, {"
- " 'is_default': true,"
- " 'type': 'AUTO'"
- " } ]"
- " },"
- " 'copies': {"
- " },"
- " 'margins': {"
- " 'option': [ {"
- " 'is_default': true,"
- " 'type': 'BORDERLESS',"
- " 'top_microns': 0,"
- " 'right_microns': 0,"
- " 'bottom_microns': 0,"
- " 'left_microns': 0"
- " }, {"
- " 'type': 'STANDARD',"
- " 'top_microns': 100,"
- " 'right_microns': 200,"
- " 'bottom_microns': 300,"
- " 'left_microns': 400"
- " }, {"
- " 'type': 'CUSTOM',"
- " 'top_microns': 1,"
- " 'right_microns': 2,"
- " 'bottom_microns': 3,"
- " 'left_microns': 4"
- " } ]"
- " },"
- " 'dpi': {"
- " 'option': [ {"
- " 'horizontal_dpi': 150,"
- " 'vertical_dpi': 250"
- " }, {"
- " 'is_default': true,"
- " 'horizontal_dpi': 600,"
- " 'vertical_dpi': 1600"
- " } ]"
- " },"
- " 'fit_to_page': {"
- " 'option': [ {"
- " 'is_default': true,"
- " 'type': 'NO_FITTING'"
- " }, {"
- " 'type': 'FIT_TO_PAGE'"
- " }, {"
- " 'type': 'GROW_TO_PAGE'"
- " }, {"
- " 'type': 'SHRINK_TO_PAGE'"
- " }, {"
- " 'type': 'FILL_PAGE'"
- " } ]"
- " },"
- " 'page_range': {"
- " },"
- " 'media_size': {"
- " 'option': [ {"
- " 'is_default': true,"
- " 'name': 'NA_LETTER',"
- " 'width_microns': 2222,"
- " 'height_microns': 3333"
- " }, {"
- " 'name': 'ISO_A6',"
- " 'width_microns': 4444,"
- " 'height_microns': 5555"
- " }, {"
- " 'name': 'JPN_YOU4',"
- " 'width_microns': 6666,"
- " 'height_microns': 7777"
- " }, {"
- " 'width_microns': 1111,"
- " 'is_continuous_feed': true,"
- " 'custom_display_name': 'Feed',"
- " 'vendor_id': 'FEED'"
- " } ]"
- " },"
- " 'collate': {"
- " 'default': false"
- " },"
- " 'reverse_order': {"
- " 'default': true"
- " }"
- " }"
- "}";
-
-const char kDefaultCdd[] =
- "{"
- " 'version': '1.0'"
- "}";
-
-const char kBadVersionCdd[] =
- "{"
- " 'version': '1.1',"
- " 'printer': {"
- " }"
- "}";
-
-const char kNoDefaultCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'color': {"
- " 'option': [ {"
- " 'type': 'STANDARD_COLOR'"
- " }, {"
- " 'type': 'STANDARD_MONOCHROME'"
- " } ]"
- " }"
- " }"
- "}";
-
-const char kMultyDefaultCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'color': {"
- " 'option': [ {"
- " 'is_default': true,"
- " 'type': 'STANDARD_COLOR'"
- " }, {"
- " 'is_default': true,"
- " 'type': 'STANDARD_MONOCHROME'"
- " } ]"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeColorOnlyCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_type_supported': [ 'SRGB_8' ],"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeGrayOnlyCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_type_supported': [ 'SGRAY_8' ],"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeColorAndGrayCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_type_supported': [ 'SRGB_8', 'SGRAY_8' ],"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeColorAndUnsupportedCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_type_supported': [ 'SRGB_8', 'SRGB_16' ],"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeNoneCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeNotStringCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_type_supported': [ 8, 16 ],"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kDocumentTypeNotListCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pwg_raster_config': {"
- " 'document_type_supported': 'ROTATED',"
- " 'document_sheet_back': 'ROTATED'"
- " }"
- " }"
- "}";
-
-const char kIntegerRangeVendorCapabilityJson[] =
- "{"
- " 'value_type': 'INTEGER',"
- " 'min': '0',"
- " 'max': '10'"
- "}";
-
-const char kFloatDefaultRangeVendorCapabilityJson[] =
- "{"
- " 'value_type': 'FLOAT',"
- " 'min': '0.0',"
- " 'max': '1.0',"
- " 'default': '0.5'"
- "}";
-
-const char kInvalidTypeRangeVendorCapabilityJson[] =
- "{"
- " 'value_type': 'BOOLEAN',"
- " 'min': '0.0',"
- " 'max': '1.0'"
- "}";
-
-const char kMissingMinValueRangeVendorCapabilityJson[] =
- "{"
- " 'value_type': 'INT',"
- " 'max': '10'"
- "}";
-
-const char kInvalidBoundariesRangeVendorCapabilityJson[] =
- "{"
- " 'value_type': 'INT',"
- " 'min': '10',"
- " 'max': '0'"
- "}";
-
-const char kInvalidDefaultValueRangeVendorCapabilityJson[] =
- "{"
- " 'value_type': 'FLOAT',"
- " 'min': '0.0',"
- " 'max': '5.0',"
- " 'default': '10.0'"
- "}";
-
-const char kSelectVendorCapabilityJson[] =
- "{"
- " 'option': [ {"
- " 'value': 'value_1',"
- " 'display_name': 'name_1'"
- " }, {"
- " 'value': 'value_2',"
- " 'display_name': 'name_2',"
- " 'is_default': true"
- " } ]"
- "}";
-
-const char kNotListSelectVendorCapabilityJson[] =
- "{"
- " 'option': {"
- " 'value': 'value',"
- " 'display_name': 'name'"
- " }"
- "}";
-
-const char kMissingValueSelectVendorCapabilityJson[] =
- "{"
- " 'option': [ {"
- " 'display_name': 'name'"
- " } ]"
- "}";
-
-const char kMissingDisplayNameSelectVendorCapabilityJson[] =
- "{"
- " 'option': [ {"
- " 'value': 'value'"
- " } ]"
- "}";
-
-const char kNoDefaultSelectVendorCapabilityJson[] =
- "{"
- " 'option': [ {"
- " 'value': 'value',"
- " 'display_name': 'name'"
- " } ]"
- "}";
-
-const char kSeveralDefaultsSelectVendorCapabilityJson[] =
- "{"
- " 'option': [ {"
- " 'value': 'value_1',"
- " 'display_name': 'name_1',"
- " 'is_default': true"
- " }, {"
- " 'value': 'value_2',"
- " 'display_name': 'name_2',"
- " 'is_default': true"
- " } ]"
- "}";
-
-const char kBooleanTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'BOOLEAN',"
- " 'default': 'true'"
- "}";
-
-const char kFloatTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'FLOAT',"
- " 'default': '1.0'"
- "}";
-
-const char kIntegerTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'INTEGER',"
- " 'default': '10'"
- "}";
-
-const char kStringTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'STRING',"
- " 'default': 'value'"
- "}";
-
-const char kMissingValueTypeTypedValueVendorCapabilityJson[] =
- "{"
- " 'default': 'value'"
- "}";
-
-const char kInvalidBooleanTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'BOOLEAN',"
- " 'default': '1'"
- "}";
-
-const char kInvalidFloatTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'FLOAT',"
- " 'default': '1.1.1.1'"
- "}";
-
-const char kInvalidIntegerTypedValueVendorCapabilityJson[] =
- "{"
- " 'value_type': 'INTEGER',"
- " 'default': 'true'"
- "}";
-
-const char kVendorCapabilityOnlyCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'vendor_capability': [ {"
- " 'id': 'id_1',"
- " 'display_name': 'name_1',"
- " 'type': 'RANGE',"
- " 'range_cap': {"
- " 'value_type': 'INTEGER',"
- " 'min': '1',"
- " 'max': '10'"
- " }"
- " }, {"
- " 'id': 'id_2',"
- " 'display_name': 'name_2',"
- " 'type': 'SELECT',"
- " 'select_cap': {"
- " 'option': [ {"
- " 'value': 'value',"
- " 'display_name': 'name',"
- " 'is_default': true"
- " } ]"
- " }"
- " }, {"
- " 'id': 'id_3',"
- " 'display_name': 'name_3',"
- " 'type': 'TYPED_VALUE',"
- " 'typed_value_cap': {"
- " 'value_type': 'INTEGER',"
- " 'default': '1'"
- " }"
- " } ]"
- " }"
- "}";
-
-const char kMissingIdVendorCapabilityCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'vendor_capability': [ {"
- " 'display_name': 'name_1',"
- " 'type': 'RANGE',"
- " 'range_cap': {"
- " 'value_type': 'INTEGER',"
- " 'min': '1',"
- " 'max': '10'"
- " }"
- " } ]"
- " }"
- "}";
-
-const char kInvalidInnerCapabilityVendorCapabilityCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'vendor_capability': [ {"
- " 'display_name': 'name_1',"
- " 'type': 'RANGE',"
- " 'range_cap': {"
- " 'value_type': 'INTEGER',"
- " 'min': '10',"
- " 'max': '1'"
- " }"
- " } ]"
- " }"
- "}";
-
-const char kNoInnerCapabilityVendorCapabilityCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'vendor_capability': [ {"
- " 'display_name': 'name_1',"
- " 'type': 'RANGE'"
- " } ]"
- " }"
- "}";
-
-const char kSeveralInnerCapabilitiesVendorCapabilityCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'vendor_capability': [ {"
- " 'id': 'id_1',"
- " 'display_name': 'name_1',"
- " 'type': 'RANGE',"
- " 'range_cap': {"
- " 'value_type': 'INTEGER',"
- " 'min': '1',"
- " 'max': '10'"
- " },"
- " 'select_cap': {"
- " 'option': [ {"
- " 'value': 'value',"
- " 'display_name': 'name',"
- " 'is_default': true"
- " } ]"
- " }"
- " } ]"
- " }"
- "}";
+const char kCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "supported_content_type": [ {
+ "content_type": "image/pwg-raster"
+ }, {
+ "content_type": "image/jpeg"
+ } ],
+ "pwg_raster_config": {
+ "document_sheet_back": "MANUAL_TUMBLE",
+ "reverse_order_streaming": true
+ },
+ "color": {
+ "option": [ {
+ "is_default": true,
+ "type": "STANDARD_COLOR"
+ }, {
+ "type": "STANDARD_MONOCHROME"
+ }, {
+ "type": "CUSTOM_MONOCHROME",
+ "vendor_id": "123",
+ "custom_display_name": "monochrome"
+ } ]
+ },
+ "duplex": {
+ "option": [ {
+ "is_default": true,
+ "type": "LONG_EDGE"
+ }, {
+ "type": "SHORT_EDGE"
+ }, {
+ "type": "NO_DUPLEX"
+ } ]
+ },
+ "page_orientation": {
+ "option": [ {
+ "type": "PORTRAIT"
+ }, {
+ "type": "LANDSCAPE"
+ }, {
+ "is_default": true,
+ "type": "AUTO"
+ } ]
+ },
+ "copies": {
+ },
+ "margins": {
+ "option": [ {
+ "is_default": true,
+ "type": "BORDERLESS",
+ "top_microns": 0,
+ "right_microns": 0,
+ "bottom_microns": 0,
+ "left_microns": 0
+ }, {
+ "type": "STANDARD",
+ "top_microns": 100,
+ "right_microns": 200,
+ "bottom_microns": 300,
+ "left_microns": 400
+ }, {
+ "type": "CUSTOM",
+ "top_microns": 1,
+ "right_microns": 2,
+ "bottom_microns": 3,
+ "left_microns": 4
+ } ]
+ },
+ "dpi": {
+ "option": [ {
+ "horizontal_dpi": 150,
+ "vertical_dpi": 250
+ }, {
+ "is_default": true,
+ "horizontal_dpi": 600,
+ "vertical_dpi": 1600
+ } ]
+ },
+ "fit_to_page": {
+ "option": [ {
+ "is_default": true,
+ "type": "NO_FITTING"
+ }, {
+ "type": "FIT_TO_PAGE"
+ }, {
+ "type": "GROW_TO_PAGE"
+ }, {
+ "type": "SHRINK_TO_PAGE"
+ }, {
+ "type": "FILL_PAGE"
+ } ]
+ },
+ "page_range": {
+ },
+ "media_size": {
+ "option": [ {
+ "is_default": true,
+ "name": "NA_LETTER",
+ "width_microns": 2222,
+ "height_microns": 3333
+ }, {
+ "name": "ISO_A6",
+ "width_microns": 4444,
+ "height_microns": 5555
+ }, {
+ "name": "JPN_YOU4",
+ "width_microns": 6666,
+ "height_microns": 7777
+ }, {
+ "width_microns": 1111,
+ "is_continuous_feed": true,
+ "custom_display_name": "Feed",
+ "vendor_id": "FEED"
+ } ]
+ },
+ "collate": {
+ "default": false
+ },
+ "reverse_order": {
+ "default": true
+ }
+ }
+ })";
+
+const char kDefaultCdd[] = R"(
+ {
+ "version": "1.0"
+ })";
+
+const char kBadVersionCdd[] = R"(
+ {
+ "version": "1.1",
+ "printer": {
+ }
+ })";
+
+const char kNoDefaultCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "color": {
+ "option": [ {
+ "type": "STANDARD_COLOR"
+ }, {
+ "type": "STANDARD_MONOCHROME"
+ } ]
+ }
+ }
+ })";
+
+const char kMultyDefaultCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "color": {
+ "option": [ {
+ "is_default": true,
+ "type": "STANDARD_COLOR"
+ }, {
+ "is_default": true,
+ "type": "STANDARD_MONOCHROME"
+ } ]
+ }
+ }
+ })";
+
+const char kDocumentTypeColorOnlyCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_type_supported": [ "SRGB_8" ],
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kDocumentTypeGrayOnlyCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_type_supported": [ "SGRAY_8" ],
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kDocumentTypeColorAndGrayCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_type_supported": [ "SRGB_8", "SGRAY_8" ],
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kDocumentTypeColorAndUnsupportedCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_type_supported": [ "SRGB_8", "SRGB_16" ],
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kDocumentTypeNoneCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kDocumentTypeNotStringCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_type_supported": [ 8, 16 ],
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kDocumentTypeNotListCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pwg_raster_config": {
+ "document_type_supported": "ROTATED",
+ "document_sheet_back": "ROTATED"
+ }
+ }
+ })";
+
+const char kIntegerRangeVendorCapabilityJson[] = R"(
+ {
+ "value_type": "INTEGER",
+ "min": "0",
+ "max": "10"
+ })";
+
+const char kFloatDefaultRangeVendorCapabilityJson[] = R"(
+ {
+ "value_type": "FLOAT",
+ "min": "0.0",
+ "max": "1.0",
+ "default": "0.5"
+ })";
+
+const char kInvalidTypeRangeVendorCapabilityJson[] = R"(
+ {
+ "value_type": "BOOLEAN",
+ "min": "0.0",
+ "max": "1.0"
+ })";
+
+const char kMissingMinValueRangeVendorCapabilityJson[] = R"(
+ {
+ "value_type": "INT",
+ "max": "10"
+ })";
+
+const char kInvalidBoundariesRangeVendorCapabilityJson[] = R"(
+ {
+ "value_type": "INT",
+ "min": "10",
+ "max": "0"
+ })";
+
+const char kInvalidDefaultValueRangeVendorCapabilityJson[] = R"(
+ {
+ "value_type": "FLOAT",
+ "min": "0.0",
+ "max": "5.0",
+ "default": "10.0"
+ })";
+
+const char kSelectVendorCapabilityJson[] = R"(
+ {
+ "option": [ {
+ "value": "value_1",
+ "display_name": "name_1"
+ }, {
+ "value": "value_2",
+ "display_name": "name_2",
+ "is_default": true
+ } ]
+ })";
+
+const char kNotListSelectVendorCapabilityJson[] = R"(
+ {
+ "option": {
+ "value": "value",
+ "display_name": "name"
+ }
+ })";
+
+const char kMissingValueSelectVendorCapabilityJson[] = R"(
+ {
+ "option": [ {
+ "display_name": "name"
+ } ]
+ })";
+
+const char kMissingDisplayNameSelectVendorCapabilityJson[] = R"(
+ {
+ "option": [ {
+ "value": "value"
+ } ]
+ })";
+
+const char kNoDefaultSelectVendorCapabilityJson[] = R"(
+ {
+ "option": [ {
+ "value": "value",
+ "display_name": "name"
+ } ]
+ })";
+
+const char kSeveralDefaultsSelectVendorCapabilityJson[] = R"(
+ {
+ "option": [ {
+ "value": "value_1",
+ "display_name": "name_1",
+ "is_default": true
+ }, {
+ "value": "value_2",
+ "display_name": "name_2",
+ "is_default": true
+ } ]
+ })";
+
+const char kBooleanTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "BOOLEAN",
+ "default": "true"
+ })";
+
+const char kFloatTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "FLOAT",
+ "default": "1.0"
+ })";
+
+const char kIntegerTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "INTEGER",
+ "default": "10"
+ })";
+
+const char kStringTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "STRING",
+ "default": "value"
+ })";
+
+const char kMissingValueTypeTypedValueVendorCapabilityJson[] = R"(
+ {
+ "default": "value"
+ })";
+
+const char kInvalidBooleanTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "BOOLEAN",
+ "default": "1"
+ })";
+
+const char kInvalidFloatTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "FLOAT",
+ "default": "1.1.1.1"
+ })";
+
+const char kInvalidIntegerTypedValueVendorCapabilityJson[] = R"(
+ {
+ "value_type": "INTEGER",
+ "default": "true"
+ })";
+
+const char kVendorCapabilityOnlyCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "vendor_capability": [ {
+ "id": "id_1",
+ "display_name": "name_1",
+ "type": "RANGE",
+ "range_cap": {
+ "value_type": "INTEGER",
+ "min": "1",
+ "max": "10"
+ }
+ }, {
+ "id": "id_2",
+ "display_name": "name_2",
+ "type": "SELECT",
+ "select_cap": {
+ "option": [ {
+ "value": "value",
+ "display_name": "name",
+ "is_default": true
+ } ]
+ }
+ }, {
+ "id": "id_3",
+ "display_name": "name_3",
+ "type": "TYPED_VALUE",
+ "typed_value_cap": {
+ "value_type": "INTEGER",
+ "default": "1"
+ }
+ } ]
+ }
+ })";
+
+const char kMissingIdVendorCapabilityCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "vendor_capability": [ {
+ "display_name": "name_1",
+ "type": "RANGE",
+ "range_cap": {
+ "value_type": "INTEGER",
+ "min": "1",
+ "max": "10"
+ }
+ } ]
+ }
+ })";
+
+const char kInvalidInnerCapabilityVendorCapabilityCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "vendor_capability": [ {
+ "display_name": "name_1",
+ "type": "RANGE",
+ "range_cap": {
+ "value_type": "INTEGER",
+ "min": "10",
+ "max": "1"
+ }
+ } ]
+ }
+ })";
+
+const char kNoInnerCapabilityVendorCapabilityCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "vendor_capability": [ {
+ "display_name": "name_1",
+ "type": "RANGE"
+ } ]
+ }
+ })";
+
+const char kSeveralInnerCapabilitiesVendorCapabilityCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "vendor_capability": [ {
+ "id": "id_1",
+ "display_name": "name_1",
+ "type": "RANGE",
+ "range_cap": {
+ "value_type": "INTEGER",
+ "min": "1",
+ "max": "10"
+ },
+ "select_cap": {
+ "option": [ {
+ "value": "value",
+ "display_name": "name",
+ "is_default": true
+ } ]
+ }
+ } ]
+ }
+ })";
#if defined(OS_CHROMEOS)
-const char kPinOnlyCdd[] =
- "{"
- " 'version': '1.0',"
- " 'printer': {"
- " 'pin': {"
- " 'supported': true"
- " }"
- " }"
- "}";
+const char kPinOnlyCdd[] = R"(
+ {
+ "version": "1.0",
+ "printer": {
+ "pin": {
+ "supported": true
+ }
+ }
+ })";
#endif // defined(OS_CHROMEOS)
-const char kCjt[] =
- "{"
- " 'version': '1.0',"
- " 'print': {"
- " 'pwg_raster_config': {"
- " 'document_sheet_back': 'MANUAL_TUMBLE',"
- " 'reverse_order_streaming': true"
- " },"
- " 'color': {"
- " 'type': 'STANDARD_MONOCHROME'"
- " },"
- " 'duplex': {"
- " 'type': 'NO_DUPLEX'"
- " },"
- " 'page_orientation': {"
- " 'type': 'LANDSCAPE'"
- " },"
- " 'copies': {"
- " 'copies': 123"
- " },"
- " 'margins': {"
- " 'type': 'CUSTOM',"
- " 'top_microns': 7,"
- " 'right_microns': 6,"
- " 'bottom_microns': 3,"
- " 'left_microns': 1"
- " },"
- " 'dpi': {"
- " 'horizontal_dpi': 562,"
- " 'vertical_dpi': 125"
- " },"
- " 'fit_to_page': {"
- " 'type': 'SHRINK_TO_PAGE'"
- " },"
- " 'page_range': {"
- " 'interval': [ {"
- " 'start': 1,"
- " 'end': 99"
- " }, {"
- " 'start': 150"
- " } ]"
- " },"
- " 'media_size': {"
- " 'name': 'ISO_C7C6',"
- " 'width_microns': 4261,"
- " 'height_microns': 334"
- " },"
- " 'collate': {"
- " 'collate': false"
- " },"
- " 'reverse_order': {"
- " 'reverse_order': true"
- " }"
- " }"
- "}";
-
-const char kDefaultCjt[] =
- "{"
- " 'version': '1.0'"
- "}";
-
-const char kBadVersionCjt[] =
- "{"
- " 'version': '1.1',"
- " 'print': {"
- " }"
- "}";
+const char kCjt[] = R"(
+ {
+ "version": "1.0",
+ "print": {
+ "pwg_raster_config": {
+ "document_sheet_back": "MANUAL_TUMBLE",
+ "reverse_order_streaming": true
+ },
+ "color": {
+ "type": "STANDARD_MONOCHROME"
+ },
+ "duplex": {
+ "type": "NO_DUPLEX"
+ },
+ "page_orientation": {
+ "type": "LANDSCAPE"
+ },
+ "copies": {
+ "copies": 123
+ },
+ "margins": {
+ "type": "CUSTOM",
+ "top_microns": 7,
+ "right_microns": 6,
+ "bottom_microns": 3,
+ "left_microns": 1
+ },
+ "dpi": {
+ "horizontal_dpi": 562,
+ "vertical_dpi": 125
+ },
+ "fit_to_page": {
+ "type": "SHRINK_TO_PAGE"
+ },
+ "page_range": {
+ "interval": [ {
+ "start": 1,
+ "end": 99
+ }, {
+ "start": 150
+ } ]
+ },
+ "media_size": {
+ "name": "ISO_C7C6",
+ "width_microns": 4261,
+ "height_microns": 334
+ },
+ "collate": {
+ "collate": false
+ },
+ "reverse_order": {
+ "reverse_order": true
+ }
+ }
+ })";
+
+const char kDefaultCjt[] = R"(
+ {
+ "version": "1.0"
+ })";
+
+const char kBadVersionCjt[] = R"(
+ {
+ "version": "1.1",
+ "print": {
+ }
+ })";
const struct TestRangeCapabilities {
const char* const json_name;
@@ -669,12 +666,12 @@ TEST(PrinterDescriptionTest, CddInvalid) {
CloudDeviceDescription description;
ColorCapability color;
- EXPECT_FALSE(description.InitFromString(NormalizeJson(kBadVersionCdd)));
+ EXPECT_FALSE(description.InitFromString(kBadVersionCdd));
- EXPECT_TRUE(description.InitFromString(NormalizeJson(kNoDefaultCdd)));
+ EXPECT_TRUE(description.InitFromString(kNoDefaultCdd));
EXPECT_FALSE(color.LoadFrom(description));
- EXPECT_TRUE(description.InitFromString(NormalizeJson(kMultyDefaultCdd)));
+ EXPECT_TRUE(description.InitFromString(kMultyDefaultCdd));
EXPECT_FALSE(color.LoadFrom(description));
}
@@ -760,8 +757,7 @@ TEST(PrinterDescriptionTest, CddSetAll) {
TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) {
{
CloudDeviceDescription description;
- ASSERT_TRUE(
- description.InitFromString(NormalizeJson(kDocumentTypeColorOnlyCdd)));
+ ASSERT_TRUE(description.InitFromString(kDocumentTypeColorOnlyCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_TRUE(pwg_raster.LoadFrom(description));
@@ -774,8 +770,7 @@ TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) {
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(
- description.InitFromString(NormalizeJson(kDocumentTypeGrayOnlyCdd)));
+ ASSERT_TRUE(description.InitFromString(kDocumentTypeGrayOnlyCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_TRUE(pwg_raster.LoadFrom(description));
@@ -788,8 +783,7 @@ TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) {
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(
- NormalizeJson(kDocumentTypeColorAndGrayCdd)));
+ ASSERT_TRUE(description.InitFromString(kDocumentTypeColorAndGrayCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_TRUE(pwg_raster.LoadFrom(description));
@@ -804,8 +798,8 @@ TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) {
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(
- NormalizeJson(kDocumentTypeColorAndUnsupportedCdd)));
+ ASSERT_TRUE(
+ description.InitFromString(kDocumentTypeColorAndUnsupportedCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_TRUE(pwg_raster.LoadFrom(description));
@@ -818,8 +812,7 @@ TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) {
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(
- description.InitFromString(NormalizeJson(kDocumentTypeNoneCdd)));
+ ASSERT_TRUE(description.InitFromString(kDocumentTypeNoneCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_TRUE(pwg_raster.LoadFrom(description));
@@ -830,16 +823,14 @@ TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) {
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(
- description.InitFromString(NormalizeJson(kDocumentTypeNotStringCdd)));
+ ASSERT_TRUE(description.InitFromString(kDocumentTypeNotStringCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_FALSE(pwg_raster.LoadFrom(description));
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(
- description.InitFromString(NormalizeJson(kDocumentTypeNotListCdd)));
+ ASSERT_TRUE(description.InitFromString(kDocumentTypeNotListCdd));
PwgRasterConfigCapability pwg_raster;
EXPECT_FALSE(pwg_raster.LoadFrom(description));
@@ -911,10 +902,10 @@ TEST(PrinterDescriptionTest, CddSetDocumentTypeSupported) {
TEST(PrinterDescriptionTest, CddGetRangeVendorCapability) {
for (const auto& capacity : kTestRangeCapabilities) {
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadDeprecated(NormalizeJson(capacity.json_name));
+ base::Optional<base::Value> value =
+ base::JSONReader::Read(capacity.json_name);
ASSERT_TRUE(value);
- base::Value description = base::Value::FromUniquePtrValue(std::move(value));
+ base::Value description = std::move(*value);
RangeVendorCapability range_capability;
EXPECT_TRUE(range_capability.LoadFrom(description));
EXPECT_EQ(capacity.range_capability, range_capability);
@@ -926,10 +917,10 @@ TEST(PrinterDescriptionTest, CddGetRangeVendorCapability) {
kInvalidBoundariesRangeVendorCapabilityJson,
kInvalidDefaultValueRangeVendorCapabilityJson};
for (const char* invalid_json_name : kInvalidJsonNames) {
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadDeprecated(NormalizeJson(invalid_json_name));
+ base::Optional<base::Value> value =
+ base::JSONReader::Read(invalid_json_name);
ASSERT_TRUE(value);
- base::Value description = base::Value::FromUniquePtrValue(std::move(value));
+ base::Value description = std::move(*value);
RangeVendorCapability range_capability;
EXPECT_FALSE(range_capability.LoadFrom(description));
}
@@ -950,10 +941,10 @@ TEST(PrinterDescriptionTest, CddSetRangeVendorCapability) {
TEST(PrinterDescriptionTest, CddGetSelectVendorCapability) {
{
- std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(
- NormalizeJson(kSelectVendorCapabilityJson));
+ base::Optional<base::Value> value =
+ base::JSONReader::Read(kSelectVendorCapabilityJson);
ASSERT_TRUE(value);
- base::Value description = base::Value::FromUniquePtrValue(std::move(value));
+ base::Value description = std::move(*value);
SelectVendorCapability select_capability;
EXPECT_TRUE(select_capability.LoadFrom(description));
EXPECT_EQ(2u, select_capability.size());
@@ -972,10 +963,10 @@ TEST(PrinterDescriptionTest, CddGetSelectVendorCapability) {
kNoDefaultSelectVendorCapabilityJson,
kSeveralDefaultsSelectVendorCapabilityJson};
for (const char* invalid_json_name : kInvalidJsonNames) {
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadDeprecated(NormalizeJson(invalid_json_name));
+ base::Optional<base::Value> value =
+ base::JSONReader::Read(invalid_json_name);
ASSERT_TRUE(value);
- base::Value description = base::Value::FromUniquePtrValue(std::move(value));
+ base::Value description = std::move(*value);
SelectVendorCapability select_capability;
EXPECT_FALSE(select_capability.LoadFrom(description));
}
@@ -999,10 +990,10 @@ TEST(PrinterDescriptionTest, CddSetSelectVendorCapability) {
TEST(PrinterDescriptionTest, CddGetTypedValueVendorCapability) {
for (const auto& capacity : kTestTypedValueCapabilities) {
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadDeprecated(NormalizeJson(capacity.json_name));
+ base::Optional<base::Value> value =
+ base::JSONReader::Read(capacity.json_name);
ASSERT_TRUE(value);
- base::Value description = base::Value::FromUniquePtrValue(std::move(value));
+ base::Value description = std::move(*value);
TypedValueVendorCapability typed_value_capability;
EXPECT_TRUE(typed_value_capability.LoadFrom(description));
EXPECT_EQ(capacity.typed_value_capability, typed_value_capability);
@@ -1014,10 +1005,10 @@ TEST(PrinterDescriptionTest, CddGetTypedValueVendorCapability) {
kInvalidFloatTypedValueVendorCapabilityJson,
kInvalidIntegerTypedValueVendorCapabilityJson};
for (const char* invalid_json_name : kInvalidJsonNames) {
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadDeprecated(NormalizeJson(invalid_json_name));
+ base::Optional<base::Value> value =
+ base::JSONReader::Read(invalid_json_name);
ASSERT_TRUE(value);
- base::Value description = base::Value::FromUniquePtrValue(std::move(value));
+ base::Value description = std::move(*value);
TypedValueVendorCapability typed_value_capability;
EXPECT_FALSE(typed_value_capability.LoadFrom(description));
}
@@ -1039,8 +1030,7 @@ TEST(PrinterDescriptionTest, CddSetTypedValueVendorCapability) {
TEST(PrinterDescriptionTest, CddGetVendorCapability) {
{
CloudDeviceDescription description;
- ASSERT_TRUE(
- description.InitFromString(NormalizeJson(kVendorCapabilityOnlyCdd)));
+ ASSERT_TRUE(description.InitFromString(kVendorCapabilityOnlyCdd));
VendorCapabilities vendor_capabilities;
EXPECT_TRUE(vendor_capabilities.LoadFrom(description));
@@ -1066,7 +1056,7 @@ TEST(PrinterDescriptionTest, CddGetVendorCapability) {
kSeveralInnerCapabilitiesVendorCapabilityCdd};
for (const char* invalid_json_name : kInvalidJsonNames) {
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(NormalizeJson(invalid_json_name)));
+ ASSERT_TRUE(description.InitFromString(invalid_json_name));
VendorCapabilities vendor_capabilities;
EXPECT_FALSE(vendor_capabilities.LoadFrom(description));
}
@@ -1099,7 +1089,7 @@ TEST(PrinterDescriptionTest, CddSetVendorCapability) {
TEST(PrinterDescriptionTest, CddGetPin) {
{
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(NormalizeJson(kPinOnlyCdd)));
+ ASSERT_TRUE(description.InitFromString(kPinOnlyCdd));
PinCapability pin_capability;
EXPECT_TRUE(pin_capability.LoadFrom(description));
@@ -1107,7 +1097,7 @@ TEST(PrinterDescriptionTest, CddGetPin) {
}
{
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(NormalizeJson(kDefaultCdd)));
+ ASSERT_TRUE(description.InitFromString(kDefaultCdd));
PinCapability pin_capability;
EXPECT_FALSE(pin_capability.LoadFrom(description));
}
@@ -1125,7 +1115,7 @@ TEST(PrinterDescriptionTest, CddSetPin) {
TEST(PrinterDescriptionTest, CddGetAll) {
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(NormalizeJson(kCdd)));
+ ASSERT_TRUE(description.InitFromString(kCdd));
ContentTypesCapability content_types;
PwgRasterConfigCapability pwg_raster_config;
@@ -1247,7 +1237,7 @@ TEST(PrinterDescriptionTest, CjtInit) {
TEST(PrinterDescriptionTest, CjtInvalid) {
CloudDeviceDescription ticket;
- EXPECT_FALSE(ticket.InitFromString(NormalizeJson(kBadVersionCjt)));
+ EXPECT_FALSE(ticket.InitFromString(kBadVersionCjt));
}
TEST(PrinterDescriptionTest, CjtSetAll) {
@@ -1304,7 +1294,7 @@ TEST(PrinterDescriptionTest, CjtSetAll) {
TEST(PrinterDescriptionTest, CjtGetAll) {
CloudDeviceDescription description;
- ASSERT_TRUE(description.InitFromString(NormalizeJson(kCjt)));
+ ASSERT_TRUE(description.InitFromString(kCjt));
ColorTicketItem color;
DuplexTicketItem duplex;
diff --git a/chromium/components/component_updater/OWNERS b/chromium/components/component_updater/OWNERS
index ab443251aa9..833b82cef9d 100644
--- a/chromium/components/component_updater/OWNERS
+++ b/chromium/components/component_updater/OWNERS
@@ -2,3 +2,4 @@ sorin@chromium.org
waffles@chromium.org
# COMPONENT: Internals>Installer>Components
+# TEAM: chrome-updates-dev@chromium.org
diff --git a/chromium/components/component_updater/component_installer.cc b/chromium/components/component_updater/component_installer.cc
index 2cf32b9c43a..e1e5fd2e68e 100644
--- a/chromium/components/component_updater/component_installer.cc
+++ b/chromium/components/component_updater/component_installer.cc
@@ -64,8 +64,8 @@ void ComponentInstaller::Register(ComponentUpdateService* cus,
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Some components may affect user visible features, hence USER_VISIBLE.
- task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ task_runner_ = base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
if (!installer_policy_) {
diff --git a/chromium/components/component_updater/component_installer_unittest.cc b/chromium/components/component_updater/component_installer_unittest.cc
index f963f8b2434..bb10de359d6 100644
--- a/chromium/components/component_updater/component_installer_unittest.cc
+++ b/chromium/components/component_updater/component_installer_unittest.cc
@@ -19,7 +19,7 @@
#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "base/test/scoped_path_override.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
#include "components/component_updater/component_installer.h"
@@ -200,7 +200,7 @@ class ComponentInstallerTest : public testing::Test {
void Unpack(const base::FilePath& crx_path);
ComponentUnpacker::Result result() const { return result_; }
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
private:
void UnpackComplete(const ComponentUnpacker::Result& result);
@@ -246,8 +246,7 @@ void ComponentInstallerTest::Unpack(const base::FilePath& crx_path) {
auto component_unpacker = base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(kSha256Hash), std::end(kSha256Hash)),
crx_path, nullptr, config->GetUnzipperFactory()->Create(),
- config->GetPatcherFactory()->Create(),
- crx_file::VerifierFormat::CRX2_OR_CRX3);
+ config->GetPatcherFactory()->Create(), crx_file::VerifierFormat::CRX3);
component_unpacker->Unpack(base::BindOnce(
&ComponentInstallerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
@@ -357,7 +356,7 @@ TEST_F(ComponentInstallerTest, UnpackPathInstallSuccess) {
EXPECT_EQ(0, result.error);
}));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(base::PathExists(unpack_path));
EXPECT_CALL(update_client(), Stop()).Times(1);
@@ -388,7 +387,7 @@ TEST_F(ComponentInstallerTest, UnpackPathInstallError) {
result.error);
}));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(base::PathExists(unpack_path));
EXPECT_CALL(update_client(), Stop()).Times(1);
diff --git a/chromium/components/component_updater/component_updater_service_unittest.cc b/chromium/components/component_updater/component_updater_service_unittest.cc
index 42552e6c836..d02c62fd9f0 100644
--- a/chromium/components/component_updater/component_updater_service_unittest.cc
+++ b/chromium/components/component_updater/component_updater_service_unittest.cc
@@ -20,7 +20,7 @@
#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "components/component_updater/component_updater_service_internal.h"
@@ -165,7 +165,7 @@ class ComponentUpdaterTest : public testing::Test {
const UpdateScheduler::UserTask& user_task,
const UpdateScheduler::OnStopTaskCallback& on_stop);
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::RunLoop runloop_;
scoped_refptr<TestConfigurator> config_ =
@@ -257,7 +257,7 @@ void ComponentUpdaterTest::RunThreads() {
void ComponentUpdaterTest::RunUpdateTask(
const UpdateScheduler::UserTask& user_task) {
- scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
+ task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE, base::BindRepeating(
[](const UpdateScheduler::UserTask& user_task,
ComponentUpdaterTest* test) {
diff --git a/chromium/components/component_updater/crl_set_remover.cc b/chromium/components/component_updater/crl_set_remover.cc
index 2598e7d3772..d05e0c0d7ed 100644
--- a/chromium/components/component_updater/crl_set_remover.cc
+++ b/chromium/components/component_updater/crl_set_remover.cc
@@ -11,8 +11,9 @@
namespace component_updater {
void DeleteLegacyCRLSet(const base::FilePath& user_data_dir) {
- base::PostTaskWithTraits(
- FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()},
base::BindOnce(base::IgnoreResult(&base::DeleteFile),
user_data_dir.Append(
FILE_PATH_LITERAL("Certificate Revocation Lists")),
diff --git a/chromium/components/component_updater/timer_unittest.cc b/chromium/components/component_updater/timer_unittest.cc
index 9d5c63ead4f..225a6feb340 100644
--- a/chromium/components/component_updater/timer_unittest.cc
+++ b/chromium/components/component_updater/timer_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/component_updater/timer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,12 +19,12 @@ namespace component_updater {
class ComponentUpdaterTimerTest : public testing::Test {
public:
ComponentUpdaterTimerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
~ComponentUpdaterTimerTest() override {}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
};
TEST_F(ComponentUpdaterTimerTest, Start) {
diff --git a/chromium/components/components_chromium_strings.grd b/chromium/components/components_chromium_strings.grd
index cb8023831f5..176583712d0 100644
--- a/chromium/components/components_chromium_strings.grd
+++ b/chromium/components/components_chromium_strings.grd
@@ -188,12 +188,24 @@
<!-- About Flags UI -->
<if expr="not chromeos">
- <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" desc="Notifies the user that they need to relaunch Chromium. Shown next to a button that says 'Relaunch Now'.">
+ <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" translateable="false" desc="Notifies the user that they need to relaunch Chromium. Shown next to a button that says 'Relaunch Now'.">
Your changes will take effect the next time you relaunch Chromium.
</message>
</if>
<if expr="chromeos">
- <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" desc="Notifies the user that they need to restart Chromium OS. Shown next to a button that says 'Restart Now'.">
+ <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" translateable="false" desc="Notifies the user that they need to restart Chromium OS. Shown next to a button that says 'Restart Now'.">
+ Your changes will take effect the next time you restart your device.
+ </message>
+ </if>
+
+ <!-- about:flags/deprecated strings -->
+ <if expr="not chromeos">
+ <message name="IDS_DEPRECATED_FEATURES_RELAUNCH_NOTICE" desc="Notifies the user that they need to relaunch Chromium. Shown next to a button that says 'Relaunch Now'.">
+ Your changes will take effect the next time you relaunch Chromium.
+ </message>
+ </if>
+ <if expr="chromeos">
+ <message name="IDS_DEPRECATED_FEATURES_RELAUNCH_NOTICE" desc="Notifies the user that they need to restart Chromium OS. Shown next to a button that says 'Restart Now'.">
Your changes will take effect the next time you restart your device.
</message>
</if>
diff --git a/chromium/components/components_google_chrome_strings.grd b/chromium/components/components_google_chrome_strings.grd
index 3c41235cc96..a59033248f5 100644
--- a/chromium/components/components_google_chrome_strings.grd
+++ b/chromium/components/components_google_chrome_strings.grd
@@ -188,12 +188,24 @@
<!-- About Flags UI -->
<if expr="not chromeos">
- <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" desc="Notifies the user that they need to relaunch Chrome. Shown next to a button that says 'Relaunch Now'.">
+ <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" translateable="false" desc="Notifies the user that they need to relaunch Chrome. Shown next to a button that says 'Relaunch Now'.">
Your changes will take effect the next time you relaunch Google Chrome.
</message>
</if>
<if expr="chromeos">
- <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" desc="Notifies the user that they need to restart Chrome OS. Shown next to a button that says 'Restart Now'.">
+ <message name="IDS_FLAGS_UI_RELAUNCH_NOTICE" translateable="false" desc="Notifies the user that they need to restart Chrome OS. Shown next to a button that says 'Restart Now'.">
+ Your changes will take effect the next time you restart your device.
+ </message>
+ </if>
+
+ <!-- about:flags/deprecated strings -->
+ <if expr="not chromeos">
+ <message name="IDS_DEPRECATED_FEATURES_RELAUNCH_NOTICE" desc="Notifies the user that they need to relaunch Chrome. Shown next to a button that says 'Relaunch Now'.">
+ Your changes will take effect the next time you relaunch Google Chrome.
+ </message>
+ </if>
+ <if expr="chromeos">
+ <message name="IDS_DEPRECATED_FEATURES_RELAUNCH_NOTICE" desc="Notifies the user that they need to restart Chrome OS. Shown next to a button that says 'Restart Now'.">
Your changes will take effect the next time you restart your device.
</message>
</if>
diff --git a/chromium/components/components_strings.grd b/chromium/components/components_strings.grd
index 4dd5fde0fb9..c4bf49a634d 100644
--- a/chromium/components/components_strings.grd
+++ b/chromium/components/components_strings.grd
@@ -204,6 +204,7 @@
<part file="dom_distiller_strings.grdp" />
<part file="error_page_strings.grdp" />
<part file="find_in_page_strings.grdp" />
+ <part file="flags_strings.grdp" />
<part file="history_strings.grdp" />
<part file="login_dialog_strings.grdp" />
<part file="media_message_center_strings.grdp" />
@@ -223,7 +224,6 @@
<part file="security_interstitials_strings.grdp" />
<part file="security_state_strings.grdp" />
<part file="ssl_errors_strings.grdp" />
- <part file="supervised_user_error_page_strings.grdp" />
<part file="sync_ui_strings.grdp" />
<part file="translate_strings.grdp" />
<part file="undo_strings.grdp" />
diff --git a/chromium/components/consent_auditor/consent_sync_bridge_impl_unittest.cc b/chromium/components/consent_auditor/consent_sync_bridge_impl_unittest.cc
index 8a46ab5fecf..52006af37fb 100644
--- a/chromium/components/consent_auditor/consent_sync_bridge_impl_unittest.cc
+++ b/chromium/components/consent_auditor/consent_sync_bridge_impl_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/mock_model_type_change_processor.h"
#include "components/sync/model/model_type_store_test_util.h"
@@ -164,7 +164,7 @@ class ConsentSyncBridgeImplTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
std::unique_ptr<ConsentSyncBridgeImpl> bridge_;
};
diff --git a/chromium/components/constrained_window/constrained_window_views.cc b/chromium/components/constrained_window/constrained_window_views.cc
index d818daecd1f..d6f68e0a9d4 100644
--- a/chromium/components/constrained_window/constrained_window_views.cc
+++ b/chromium/components/constrained_window/constrained_window_views.cc
@@ -208,12 +208,12 @@ views::Widget* ShowWebModalDialogWithOverlayViews(
views::Widget* CreateWebModalDialogViews(views::WidgetDelegate* dialog,
content::WebContents* web_contents) {
DCHECK_EQ(ui::MODAL_TYPE_CHILD, dialog->GetModalType());
+ web_modal::WebContentsModalDialogManager* manager =
+ web_modal::WebContentsModalDialogManager::FromWebContents(web_contents);
+ CHECK(manager);
return views::DialogDelegate::CreateDialogWidget(
dialog, nullptr,
- web_modal::WebContentsModalDialogManager::FromWebContents(web_contents)
- ->delegate()
- ->GetWebContentsModalDialogHost()
- ->GetHostView());
+ manager->delegate()->GetWebContentsModalDialogHost()->GetHostView());
}
views::Widget* CreateBrowserModalDialogViews(views::DialogDelegate* dialog,
diff --git a/chromium/components/content_capture/common/BUILD.gn b/chromium/components/content_capture/common/BUILD.gn
index 326f9f19ddd..bbe5954e511 100644
--- a/chromium/components/content_capture/common/BUILD.gn
+++ b/chromium/components/content_capture/common/BUILD.gn
@@ -26,7 +26,7 @@ mojom("mojo_interfaces") {
public_deps = [
":mojo_types",
"//mojo/public/mojom/base",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
]
}
@@ -37,7 +37,7 @@ mojom("mojo_types") {
public_deps = [
"//mojo/public/mojom/base",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
]
}
@@ -55,7 +55,7 @@ mojom("mojo_test_types") {
source_set("unit_tests") {
testonly = true
sources = [
- "content_capture_struct_traits_unittest.cc",
+ "content_capture_mojom_traits_unittest.cc",
]
public_deps = [
diff --git a/chromium/components/content_capture/common/OWNERS b/chromium/components/content_capture/common/OWNERS
index 2c44a463856..ae29a36aac8 100644
--- a/chromium/components/content_capture/common/OWNERS
+++ b/chromium/components/content_capture/common/OWNERS
@@ -1,6 +1,6 @@
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/content_capture/common/content_capture.typemap b/chromium/components/content_capture/common/content_capture.typemap
index 9eefc29f786..7e52773f811 100644
--- a/chromium/components/content_capture/common/content_capture.typemap
+++ b/chromium/components/content_capture/common/content_capture.typemap
@@ -6,15 +6,15 @@ mojom = "//components/content_capture/common/content_capture_data.mojom"
public_headers =
[ "//components/content_capture/common/content_capture_data.h" ]
traits_headers =
- [ "//components/content_capture/common/content_capture_struct_traits.h" ]
+ [ "//components/content_capture/common/content_capture_mojom_traits.h" ]
sources = [
- "//components/content_capture/common/content_capture_struct_traits.cc",
- "//components/content_capture/common/content_capture_struct_traits.h",
+ "//components/content_capture/common/content_capture_mojom_traits.cc",
+ "//components/content_capture/common/content_capture_mojom_traits.h",
]
deps = [
"//base",
"//components/content_capture/common:common",
- "//ui/gfx/geometry/mojo:struct_traits",
+ "//ui/gfx/geometry/mojom:mojom_traits",
]
-type_mappings = [ "content_capture.mojom.ContentCaptureData=content_capture::ContentCaptureData" ]
+type_mappings = [ "content_capture.mojom.ContentCaptureData=::content_capture::ContentCaptureData" ]
diff --git a/chromium/components/content_capture/common/content_capture_data.mojom b/chromium/components/content_capture/common/content_capture_data.mojom
index 1f3ece0e685..fb40fb0e6be 100644
--- a/chromium/components/content_capture/common/content_capture_data.mojom
+++ b/chromium/components/content_capture/common/content_capture_data.mojom
@@ -5,7 +5,7 @@
module content_capture.mojom;
import "mojo/public/mojom/base/string16.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
// The mojom definition of content_capture::ContentCaptureData.
struct ContentCaptureData {
diff --git a/chromium/components/content_capture/common/content_capture_struct_traits.cc b/chromium/components/content_capture/common/content_capture_mojom_traits.cc
index 4be5c06232f..64f833dc63e 100644
--- a/chromium/components/content_capture/common/content_capture_struct_traits.cc
+++ b/chromium/components/content_capture/common/content_capture_mojom_traits.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/content_capture/common/content_capture_struct_traits.h"
+#include "components/content_capture/common/content_capture_mojom_traits.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
-#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
+#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
namespace mojo {
diff --git a/chromium/components/content_capture/common/content_capture_struct_traits.h b/chromium/components/content_capture/common/content_capture_mojom_traits.h
index 85dd18ca485..16d9679542f 100644
--- a/chromium/components/content_capture/common/content_capture_struct_traits.h
+++ b/chromium/components/content_capture/common/content_capture_mojom_traits.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 COMPONENTS_CONTENT_CAPTURE_COMMON_CONTENT_CAPTURE_STRUCT_TRAITS_H_
-#define COMPONENTS_CONTENT_CAPTURE_COMMON_CONTENT_CAPTURE_STRUCT_TRAITS_H_
+#ifndef COMPONENTS_CONTENT_CAPTURE_COMMON_CONTENT_CAPTURE_MOJOM_TRAITS_H_
+#define COMPONENTS_CONTENT_CAPTURE_COMMON_CONTENT_CAPTURE_MOJOM_TRAITS_H_
#include <vector>
@@ -39,4 +39,4 @@ class StructTraits<content_capture::mojom::ContentCaptureDataDataView,
} // namespace mojo
-#endif // COMPONENTS_CONTENT_CAPTURE_COMMON_CONTENT_CAPTURE_STRUCT_TRAITS_H_
+#endif // COMPONENTS_CONTENT_CAPTURE_COMMON_CONTENT_CAPTURE_MOJOM_TRAITS_H_
diff --git a/chromium/components/content_capture/common/content_capture_struct_traits_unittest.cc b/chromium/components/content_capture/common/content_capture_mojom_traits_unittest.cc
index f30bf75c62e..41163671b61 100644
--- a/chromium/components/content_capture/common/content_capture_struct_traits_unittest.cc
+++ b/chromium/components/content_capture/common/content_capture_mojom_traits_unittest.cc
@@ -4,7 +4,7 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/content_capture/common/traits_test_service.test-mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +32,7 @@ class ContentCaptureStructTraitsTest : public testing::Test,
std::move(callback).Run(i);
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
mojo::BindingSet<TraitsTestService> traits_test_bindings_;
DISALLOW_COPY_AND_ASSIGN(ContentCaptureStructTraitsTest);
diff --git a/chromium/components/content_settings/core/browser/BUILD.gn b/chromium/components/content_settings/core/browser/BUILD.gn
index 90aa5e8f31a..3918713bb0b 100644
--- a/chromium/components/content_settings/core/browser/BUILD.gn
+++ b/chromium/components/content_settings/core/browser/BUILD.gn
@@ -110,6 +110,7 @@ jumbo_source_set("unit_tests") {
"//components/prefs:test_support",
"//components/sync_preferences:test_support",
"//extensions/buildflags",
+ "//net",
"//ppapi/buildflags:buildflags",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/content_settings/core/browser/content_settings_registry.cc b/chromium/components/content_settings/core/browser/content_settings_registry.cc
index dc67564cd90..b60c49a9da0 100644
--- a/chromium/components/content_settings/core/browser/content_settings_registry.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_registry.cc
@@ -14,6 +14,7 @@
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings.h"
+#include "net/cookies/cookie_util.h"
#if defined(OS_ANDROID)
#include "media/base/android/media_drm_bridge.h"
@@ -349,13 +350,16 @@ void ContentSettingsRegistry::Init() {
ContentSettingsInfo::PERSISTENT,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
+ ContentSetting legacy_cookie_access_initial_default =
+ net::cookie_util::IsSameSiteByDefaultCookiesEnabled()
+ ? CONTENT_SETTING_BLOCK
+ : CONTENT_SETTING_ALLOW;
Register(CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, "legacy-cookie-access",
- CONTENT_SETTING_BLOCK, WebsiteSettingsInfo::UNSYNCABLE,
- WhitelistedSchemes(),
+ legacy_cookie_access_initial_default,
+ WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(),
ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK),
WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
- WebsiteSettingsRegistry::DESKTOP |
- WebsiteSettingsRegistry::PLATFORM_ANDROID,
+ WebsiteSettingsRegistry::ALL_PLATFORMS,
ContentSettingsInfo::INHERIT_IN_INCOGNITO,
ContentSettingsInfo::PERSISTENT,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS);
@@ -491,6 +495,16 @@ void ContentSettingsRegistry::Init() {
ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE,
ContentSettingsInfo::PERSISTENT,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
+
+ Register(CONTENT_SETTINGS_TYPE_NATIVE_FILE_SYSTEM_WRITE_GUARD,
+ "native-file-system-write-guard", CONTENT_SETTING_ASK,
+ WebsiteSettingsInfo::UNSYNCABLE, WhitelistedSchemes(),
+ ValidSettings(CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK),
+ WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
+ WebsiteSettingsRegistry::DESKTOP,
+ ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE,
+ ContentSettingsInfo::PERSISTENT,
+ ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
}
void ContentSettingsRegistry::Register(
diff --git a/chromium/components/content_settings/core/browser/cookie_settings.cc b/chromium/components/content_settings/core/browser/cookie_settings.cc
index 44b4fc031d8..cc7b2843989 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings.cc
@@ -17,8 +17,6 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "extensions/buildflags/buildflags.h"
-#include "net/base/net_errors.h"
-#include "net/base/static_cookie_policy.h"
#include "url/gurl.h"
namespace content_settings {
@@ -26,8 +24,10 @@ namespace content_settings {
CookieSettings::CookieSettings(
HostContentSettingsMap* host_content_settings_map,
PrefService* prefs,
+ bool is_incognito,
const char* extension_scheme)
: host_content_settings_map_(host_content_settings_map),
+ is_incognito_(is_incognito),
extension_scheme_(extension_scheme),
block_third_party_cookies_(false) {
pref_change_registrar_.Init(prefs);
@@ -36,7 +36,7 @@ CookieSettings::CookieSettings(
base::Bind(&CookieSettings::OnCookiePreferencesChanged,
base::Unretained(this)));
pref_change_registrar_.Add(
- prefs::kCookieControlsEnabled,
+ prefs::kCookieControlsMode,
base::Bind(&CookieSettings::OnCookiePreferencesChanged,
base::Unretained(this)));
OnCookiePreferencesChanged();
@@ -59,8 +59,9 @@ void CookieSettings::RegisterProfilePrefs(
registry->RegisterBooleanPref(
prefs::kBlockThirdPartyCookies, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
- registry->RegisterBooleanPref(
- prefs::kCookieControlsEnabled, false,
+ registry->RegisterIntegerPref(
+ prefs::kCookieControlsMode,
+ static_cast<int>(CookieControlsMode::kIncognitoOnly),
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
}
@@ -118,15 +119,27 @@ bool CookieSettings::IsStorageDurable(const GURL& origin) const {
return setting == CONTENT_SETTING_ALLOW;
}
+void CookieSettings::GetSettingForLegacyCookieAccess(
+ const GURL& cookie_domain,
+ ContentSetting* setting) const {
+ DCHECK(setting);
+
+ *setting = host_content_settings_map_->GetContentSetting(
+ cookie_domain, GURL(), CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS,
+ std::string() /* resource_identifier */);
+}
+
void CookieSettings::ShutdownOnUIThread() {
DCHECK(thread_checker_.CalledOnValidThread());
pref_change_registrar_.RemoveAll();
}
-void CookieSettings::GetCookieSetting(const GURL& url,
- const GURL& first_party_url,
- content_settings::SettingSource* source,
- ContentSetting* cookie_setting) const {
+void CookieSettings::GetCookieSettingInternal(
+ const GURL& url,
+ const GURL& first_party_url,
+ bool is_third_party_request,
+ content_settings::SettingSource* source,
+ ContentSetting* cookie_setting) const {
DCHECK(cookie_setting);
// Auto-allow in extensions or for WebUI embedded in a secure origin.
if (first_party_url.SchemeIs(kChromeUIScheme) &&
@@ -158,30 +171,46 @@ void CookieSettings::GetCookieSetting(const GURL& url,
info.secondary_pattern.MatchesAllHosts() &&
ShouldBlockThirdPartyCookies() &&
!first_party_url.SchemeIs(extension_scheme_);
- net::StaticCookiePolicy policy(
- net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES);
// We should always have a value, at least from the default provider.
DCHECK(value);
ContentSetting setting = ValueToContentSetting(value.get());
- bool block =
- block_third && policy.CanAccessCookies(url, first_party_url) != net::OK;
+ bool block = block_third && is_third_party_request;
*cookie_setting = block ? CONTENT_SETTING_BLOCK : setting;
}
CookieSettings::~CookieSettings() {
}
+bool CookieSettings::IsCookieControlsEnabled() {
+ if (!base::FeatureList::IsEnabled(kImprovedCookieControls))
+ return false;
+
+ CookieControlsMode mode = static_cast<CookieControlsMode>(
+ pref_change_registrar_.prefs()->GetInteger(prefs::kCookieControlsMode));
+
+ switch (mode) {
+ case CookieControlsMode::kOn:
+ return true;
+ case CookieControlsMode::kIncognitoOnly:
+ return is_incognito_;
+ case CookieControlsMode::kOff:
+ return false;
+ }
+ return false;
+}
+
void CookieSettings::OnCookiePreferencesChanged() {
DCHECK(thread_checker_.CalledOnValidThread());
bool new_block_third_party_cookies =
pref_change_registrar_.prefs()->GetBoolean(
prefs::kBlockThirdPartyCookies) ||
- (base::FeatureList::IsEnabled(kImprovedCookieControls) &&
- pref_change_registrar_.prefs()->GetBoolean(
- prefs::kCookieControlsEnabled));
+ IsCookieControlsEnabled();
+ // Safe to read |block_third_party_cookies_| without locking here because the
+ // only place that writes to it is this method and it will always be run on
+ // the same thread.
if (block_third_party_cookies_ != new_block_third_party_cookies) {
{
base::AutoLock auto_lock(lock_);
diff --git a/chromium/components/content_settings/core/browser/cookie_settings.h b/chromium/components/content_settings/core/browser/cookie_settings.h
index 481987cec25..975498681ce 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings.h
+++ b/chromium/components/content_settings/core/browser/cookie_settings.h
@@ -24,6 +24,15 @@ class PrefService;
namespace content_settings {
+// This enum is used in prefs, do not change values.
+// The enum needs to correspond to CookieControlsMode in enums.xml.
+enum class CookieControlsMode {
+ kOff = 0,
+ kOn = 1,
+ kIncognitoOnly = 2,
+ kMaxValue = kIncognitoOnly,
+};
+
// Default value for |extension_scheme|.
const char kDummyExtensionScheme[] = ":no-extension-scheme:";
@@ -42,8 +51,11 @@ class CookieSettings : public CookieSettingsBase,
// Creates a new CookieSettings instance.
// The caller is responsible for ensuring that |extension_scheme| is valid for
// the whole lifetime of this instance.
+ // |is_incognito| indicates whether this is an incognito profile. It is not
+ // true for other types of off-the-record profiles like guest mode.
CookieSettings(HostContentSettingsMap* host_content_settings_map,
PrefService* prefs,
+ bool is_incognito,
const char* extension_scheme = kDummyExtensionScheme);
// Returns the default content setting (CONTENT_SETTING_ALLOW,
@@ -102,32 +114,40 @@ class CookieSettings : public CookieSettingsBase,
// This method may be called on any thread.
bool ShouldBlockThirdPartyCookies() const;
+ // content_settings::CookieSettingsBase:
+ void GetSettingForLegacyCookieAccess(const GURL& cookie_domain,
+ ContentSetting* setting) const override;
+
// Detaches the |CookieSettings| from |PrefService|. This methods needs to be
// called before destroying the service. Afterwards, only const methods can be
// called.
void ShutdownOnUIThread() override;
- // content_settings::CookieSettingsBase:
- void GetCookieSetting(const GURL& url,
- const GURL& first_party_url,
- content_settings::SettingSource* source,
- ContentSetting* cookie_setting) const override;
-
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
void AddObserver(Observer* obs) { observers_.AddObserver(obs); }
void RemoveObserver(const Observer* obs) { observers_.RemoveObserver(obs); }
+ bool IsCookieControlsEnabled();
+
private:
~CookieSettings() override;
+ // content_settings::CookieSettingsBase:
+ void GetCookieSettingInternal(const GURL& url,
+ const GURL& first_party_url,
+ bool is_third_party_request,
+ content_settings::SettingSource* source,
+ ContentSetting* cookie_setting) const override;
+
void OnCookiePreferencesChanged();
base::ThreadChecker thread_checker_;
base::ObserverList<Observer> observers_;
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
PrefChangeRegistrar pref_change_registrar_;
+ const bool is_incognito_;
const char* extension_scheme_; // Weak.
// Used around accesses to |block_third_party_cookies_| to guarantee thread
diff --git a/chromium/components/content_settings/core/browser/cookie_settings_policy_handler.cc b/chromium/components/content_settings/core/browser/cookie_settings_policy_handler.cc
index eaabdad7d1c..58bb21c5aec 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings_policy_handler.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings_policy_handler.cc
@@ -4,6 +4,7 @@
#include "components/content_settings/core/browser/cookie_settings_policy_handler.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
@@ -29,7 +30,8 @@ void CookieSettingsPolicyHandler::ApplyPolicySettings(
const base::Value* third_party_cookie_blocking =
policies.GetValue(policy::key::kBlockThirdPartyCookies);
if (third_party_cookie_blocking) {
- prefs->SetBoolean(prefs::kCookieControlsEnabled, false);
+ prefs->SetInteger(prefs::kCookieControlsMode,
+ static_cast<int>(CookieControlsMode::kOff));
}
}
diff --git a/chromium/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc b/chromium/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc
index 5976b17aeae..931fa113b33 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/values.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/policy/core/browser/configuration_policy_pref_store.h"
#include "components/policy/core/browser/configuration_policy_pref_store_test.h"
@@ -39,21 +40,23 @@ TEST_F(CookieSettingsPolicyHandlerTest, ThirdPartyCookieBlockingNotSet) {
policy::PolicyMap policy;
UpdateProviderPolicy(policy);
const base::Value* value;
- EXPECT_FALSE(store_->GetValue(prefs::kCookieControlsEnabled, &value));
+ EXPECT_FALSE(store_->GetValue(prefs::kCookieControlsMode, &value));
}
TEST_F(CookieSettingsPolicyHandlerTest, ThirdPartyCookieBlockingEnabled) {
SetThirdPartyCookiePolicy(true);
const base::Value* value;
- ASSERT_TRUE(store_->GetValue(prefs::kCookieControlsEnabled, &value));
- EXPECT_FALSE(value->GetBool());
+ ASSERT_TRUE(store_->GetValue(prefs::kCookieControlsMode, &value));
+ EXPECT_EQ(static_cast<CookieControlsMode>(value->GetInt()),
+ CookieControlsMode::kOff);
}
TEST_F(CookieSettingsPolicyHandlerTest, ThirdPartyCookieBlockingDisabled) {
SetThirdPartyCookiePolicy(false);
const base::Value* value;
- ASSERT_TRUE(store_->GetValue(prefs::kCookieControlsEnabled, &value));
- EXPECT_FALSE(value->GetBool());
+ ASSERT_TRUE(store_->GetValue(prefs::kCookieControlsMode, &value));
+ EXPECT_EQ(static_cast<CookieControlsMode>(value->GetInt()),
+ CookieControlsMode::kOff);
}
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
index 4f2a18a993d..545389d1c71 100644
--- a/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/chromium/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -6,13 +6,19 @@
#include "base/scoped_observer.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
+#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
+#include "components/content_settings/core/test/content_settings_mock_provider.h"
+#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "extensions/buildflags/buildflags.h"
+#include "net/base/features.h"
+#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -22,9 +28,8 @@ namespace {
class CookieSettingsObserver : public CookieSettings::Observer {
public:
- CookieSettingsObserver(CookieSettings* settings)
- : settings_(settings), scoped_observer(this) {
- scoped_observer.Add(settings);
+ CookieSettingsObserver(CookieSettings* settings) : settings_(settings) {
+ scoped_observer_.Add(settings);
}
void OnThirdPartyCookieBlockingChanged(
@@ -39,7 +44,8 @@ class CookieSettingsObserver : public CookieSettings::Observer {
private:
CookieSettings* settings_;
bool last_value_ = false;
- ScopedObserver<CookieSettings, CookieSettingsObserver> scoped_observer;
+ ScopedObserver<CookieSettings, CookieSettings::Observer> scoped_observer_{
+ this};
DISALLOW_COPY_AND_ASSIGN(CookieSettingsObserver);
};
@@ -55,22 +61,30 @@ class CookieSettingsTest : public testing::Test {
kDomain("example.com"),
kDotDomain(".example.com"),
kSubDomain("www.example.com"),
+ kOtherDomain("www.not-example.com"),
+ kDomainWildcardPattern("[*.]example.com"),
kHttpSite("http://example.com"),
kHttpsSite("https://example.com"),
kHttpsSubdomainSite("https://www.example.com"),
kHttpsSite8080("https://example.com:8080"),
kAllHttpsSitesPattern(ContentSettingsPattern::FromString("https://*")) {
+ }
+
+ ~CookieSettingsTest() override { settings_map_->ShutdownOnUIThread(); }
+
+ void SetUp() override {
+ ContentSettingsRegistry::GetInstance()->ResetForTest();
CookieSettings::RegisterProfilePrefs(prefs_.registry());
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
settings_map_ = new HostContentSettingsMap(
&prefs_, false /* is_off_the_record */, false /* store_last_modified */,
false /* migrate_requesting_and_top_level_origin_settings */);
- cookie_settings_ =
- new CookieSettings(settings_map_.get(), &prefs_, "chrome-extension");
+ cookie_settings_ = new CookieSettings(settings_map_.get(), &prefs_, false,
+ "chrome-extension");
+ cookie_settings_incognito_ = new CookieSettings(
+ settings_map_.get(), &prefs_, true, "chrome-extension");
}
- ~CookieSettingsTest() override { settings_map_->ShutdownOnUIThread(); }
-
protected:
bool ShouldDeleteCookieOnExit(const std::string& domain, bool is_https) {
ContentSettingsForOneType settings;
@@ -81,11 +95,12 @@ class CookieSettingsTest : public testing::Test {
// There must be a valid ThreadTaskRunnerHandle in HostContentSettingsMap's
// scope.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
scoped_refptr<HostContentSettingsMap> settings_map_;
scoped_refptr<CookieSettings> cookie_settings_;
+ scoped_refptr<CookieSettings> cookie_settings_incognito_;
const GURL kBlockedSite;
const GURL kAllowedSite;
const GURL kFirstPartySite;
@@ -94,6 +109,8 @@ class CookieSettingsTest : public testing::Test {
const std::string kDomain;
const std::string kDotDomain;
const std::string kSubDomain;
+ const std::string kOtherDomain;
+ const std::string kDomainWildcardPattern;
const GURL kHttpSite;
const GURL kHttpsSite;
const GURL kHttpsSubdomainSite;
@@ -130,24 +147,63 @@ TEST_F(CookieSettingsTest, CookiesBlockThirdParty) {
EXPECT_FALSE(cookie_settings_->IsCookieSessionOnly(kBlockedSite));
}
-TEST_F(CookieSettingsTest, CookiesControlsEnabled) {
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kImprovedCookieControls);
- ASSERT_TRUE(
+// Test fixture with ImprovedCookieControls enabled.
+class ImprovedCookieControlsCookieSettingsTest : public CookieSettingsTest {
+ public:
+ ImprovedCookieControlsCookieSettingsTest() : CookieSettingsTest() {
+ feature_list_.InitAndEnableFeature(kImprovedCookieControls);
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_F(ImprovedCookieControlsCookieSettingsTest, CookiesControlsDefault) {
+ EXPECT_TRUE(
cookie_settings_->IsCookieAccessAllowed(kBlockedSite, kFirstPartySite));
- prefs_.SetBoolean(prefs::kCookieControlsEnabled, true);
+ EXPECT_FALSE(cookie_settings_incognito_->IsCookieAccessAllowed(
+ kBlockedSite, kFirstPartySite));
+}
+
+TEST_F(ImprovedCookieControlsCookieSettingsTest, CookiesControlsEnabled) {
+ prefs_.SetInteger(prefs::kCookieControlsMode,
+ static_cast<int>(CookieControlsMode::kOn));
EXPECT_FALSE(
cookie_settings_->IsCookieAccessAllowed(kBlockedSite, kFirstPartySite));
+ EXPECT_FALSE(cookie_settings_incognito_->IsCookieAccessAllowed(
+ kBlockedSite, kFirstPartySite));
+}
+
+TEST_F(ImprovedCookieControlsCookieSettingsTest, CookiesControlsDisabled) {
+ prefs_.SetInteger(prefs::kCookieControlsMode,
+ static_cast<int>(CookieControlsMode::kOff));
+ EXPECT_TRUE(
+ cookie_settings_->IsCookieAccessAllowed(kBlockedSite, kFirstPartySite));
+ EXPECT_TRUE(cookie_settings_incognito_->IsCookieAccessAllowed(
+ kBlockedSite, kFirstPartySite));
+}
+
+TEST_F(ImprovedCookieControlsCookieSettingsTest,
+ CookiesControlsEnabledForIncognito) {
+ prefs_.SetInteger(prefs::kCookieControlsMode,
+ static_cast<int>(CookieControlsMode::kIncognitoOnly));
+ EXPECT_TRUE(
+ cookie_settings_->IsCookieAccessAllowed(kBlockedSite, kFirstPartySite));
+ EXPECT_FALSE(cookie_settings_incognito_->IsCookieAccessAllowed(
+ kBlockedSite, kFirstPartySite));
}
TEST_F(CookieSettingsTest, CookiesControlsEnabledButFeatureDisabled) {
- base::test::ScopedFeatureList features;
- features.InitAndDisableFeature(kImprovedCookieControls);
- ASSERT_TRUE(
+ EXPECT_TRUE(
cookie_settings_->IsCookieAccessAllowed(kBlockedSite, kFirstPartySite));
- prefs_.SetBoolean(prefs::kCookieControlsEnabled, true);
+ EXPECT_TRUE(cookie_settings_incognito_->IsCookieAccessAllowed(
+ kBlockedSite, kFirstPartySite));
+ prefs_.SetInteger(prefs::kCookieControlsMode,
+ static_cast<int>(CookieControlsMode::kOn));
EXPECT_TRUE(
cookie_settings_->IsCookieAccessAllowed(kBlockedSite, kFirstPartySite));
+ EXPECT_TRUE(cookie_settings_incognito_->IsCookieAccessAllowed(
+ kBlockedSite, kFirstPartySite));
}
TEST_F(CookieSettingsTest, CookiesAllowThirdParty) {
@@ -416,6 +472,182 @@ TEST_F(CookieSettingsTest, ThirdPartySettingObserver) {
EXPECT_TRUE(observer.last_value());
}
+TEST_F(CookieSettingsTest, LegacyCookieAccessAllowAll) {
+ settings_map_->SetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, CONTENT_SETTING_ALLOW);
+ EXPECT_EQ(
+ net::CookieAccessSemantics::LEGACY,
+ cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(kDomain, true /* is_https */)));
+ EXPECT_EQ(net::CookieAccessSemantics::LEGACY,
+ cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(kDotDomain,
+ true /* is_https */)));
+}
+
+TEST_F(CookieSettingsTest, LegacyCookieAccessBlockAll) {
+ settings_map_->SetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(
+ net::CookieAccessSemantics::NONLEGACY,
+ cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(kDomain, true /* is_https */)));
+ EXPECT_EQ(net::CookieAccessSemantics::NONLEGACY,
+ cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(kDotDomain,
+ false /* is_https */)));
+}
+
+// Test SameSite-by-default disabled (default semantics is LEGACY)
+// TODO(crbug.com/953306): Remove this when legacy code path is removed.
+TEST_F(CookieSettingsTest,
+ LegacyCookieAccessAllowDomainPattern_SameSiteByDefaultDisabled) {
+ // Override the policy provider for this test, since the legacy cookie access
+ // setting can only be set by policy.
+ TestUtils::OverrideProvider(
+ settings_map_.get(), std::make_unique<MockProvider>(),
+ HostContentSettingsMap::ProviderType::POLICY_PROVIDER);
+ settings_map_->SetContentSettingCustomScope(
+ ContentSettingsPattern::FromString(kDomain),
+ ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, std::string(),
+ CONTENT_SETTING_BLOCK);
+ const struct {
+ net::CookieAccessSemantics status;
+ std::string cookie_domain;
+ } kTestCases[] = {
+ // These two test cases are NONLEGACY because they match the setting.
+ {net::CookieAccessSemantics::NONLEGACY, kDomain},
+ {net::CookieAccessSemantics::NONLEGACY, kDotDomain},
+ // These two test cases default into LEGACY.
+ // Subdomain does not match pattern.
+ {net::CookieAccessSemantics::LEGACY, kSubDomain},
+ {net::CookieAccessSemantics::LEGACY, kOtherDomain}};
+ for (const auto& test : kTestCases) {
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, true /* is_https */)));
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, false /* is_https */)));
+ }
+}
+
+// Test SameSite-by-default disabled (default semantics is LEGACY)
+// TODO(crbug.com/953306): Remove this when legacy code path is removed.
+TEST_F(CookieSettingsTest,
+ LegacyCookieAccessAllowDomainWildcardPattern_SameSiteByDefaultDisabled) {
+ // Override the policy provider for this test, since the legacy cookie access
+ // setting can only be set by policy.
+ TestUtils::OverrideProvider(
+ settings_map_.get(), std::make_unique<MockProvider>(),
+ HostContentSettingsMap::ProviderType::POLICY_PROVIDER);
+ settings_map_->SetContentSettingCustomScope(
+ ContentSettingsPattern::FromString(kDomainWildcardPattern),
+ ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, std::string(),
+ CONTENT_SETTING_BLOCK);
+ const struct {
+ net::CookieAccessSemantics status;
+ std::string cookie_domain;
+ } kTestCases[] = {
+ // These three test cases are NONLEGACY because they match the setting.
+ {net::CookieAccessSemantics::NONLEGACY, kDomain},
+ {net::CookieAccessSemantics::NONLEGACY, kDotDomain},
+ // Subdomain matches pattern.
+ {net::CookieAccessSemantics::NONLEGACY, kSubDomain},
+ // This test case defaults into LEGACY.
+ {net::CookieAccessSemantics::LEGACY, kOtherDomain}};
+ for (const auto& test : kTestCases) {
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, true /* is_https */)));
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, false /* is_https */)));
+ }
+}
+
+// Test fixture with SameSiteByDefaultCookies enabled.
+class SameSiteByDefaultCookieSettingsTest : public CookieSettingsTest {
+ public:
+ SameSiteByDefaultCookieSettingsTest() : CookieSettingsTest() {
+ feature_list_.InitAndEnableFeature(
+ net::features::kSameSiteByDefaultCookies);
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Test SameSite-by-default enabled (default semantics is NONLEGACY)
+TEST_F(SameSiteByDefaultCookieSettingsTest,
+ LegacyCookieAccessAllowDomainPattern_SameSiteByDefaultEnabled) {
+ // Override the policy provider for this test, since the legacy cookie access
+ // setting can only be set by policy.
+ TestUtils::OverrideProvider(
+ settings_map_.get(), std::make_unique<MockProvider>(),
+ HostContentSettingsMap::ProviderType::POLICY_PROVIDER);
+ settings_map_->SetContentSettingCustomScope(
+ ContentSettingsPattern::FromString(kDomain),
+ ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, std::string(),
+ CONTENT_SETTING_ALLOW);
+ const struct {
+ net::CookieAccessSemantics status;
+ std::string cookie_domain;
+ } kTestCases[] = {
+ // These two test cases are LEGACY because they match the setting.
+ {net::CookieAccessSemantics::LEGACY, kDomain},
+ {net::CookieAccessSemantics::LEGACY, kDotDomain},
+ // These two test cases default into NONLEGACY.
+ // Subdomain does not match pattern.
+ {net::CookieAccessSemantics::NONLEGACY, kSubDomain},
+ {net::CookieAccessSemantics::NONLEGACY, kOtherDomain}};
+ for (const auto& test : kTestCases) {
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, true /* is_https */)));
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, false /* is_https */)));
+ }
+}
+
+// Test SameSite-by-default enabled (default semantics is NONLEGACY)
+TEST_F(SameSiteByDefaultCookieSettingsTest,
+ LegacyCookieAccessAllowDomainWildcardPattern_SameSiteByDefaultEnabled) {
+ // Override the policy provider for this test, since the legacy cookie access
+ // setting can only be set by policy.
+ TestUtils::OverrideProvider(
+ settings_map_.get(), std::make_unique<MockProvider>(),
+ HostContentSettingsMap::ProviderType::POLICY_PROVIDER);
+ settings_map_->SetContentSettingCustomScope(
+ ContentSettingsPattern::FromString(kDomainWildcardPattern),
+ ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, std::string(),
+ CONTENT_SETTING_ALLOW);
+ const struct {
+ net::CookieAccessSemantics status;
+ std::string cookie_domain;
+ } kTestCases[] = {
+ // These three test cases are LEGACY because they match the setting.
+ {net::CookieAccessSemantics::LEGACY, kDomain},
+ {net::CookieAccessSemantics::LEGACY, kDotDomain},
+ // Subdomain matches pattern.
+ {net::CookieAccessSemantics::LEGACY, kSubDomain},
+ // This test case defaults into NONLEGACY.
+ {net::CookieAccessSemantics::NONLEGACY, kOtherDomain}};
+ for (const auto& test : kTestCases) {
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, true /* is_https */)));
+ EXPECT_EQ(test.status, cookie_settings_->GetCookieAccessSemanticsForDomain(
+ net::cookie_util::CookieOriginToURL(
+ test.cookie_domain, false /* is_https */)));
+ }
+}
+
} // namespace
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/common/BUILD.gn b/chromium/components/content_settings/core/common/BUILD.gn
index f396acdb2e4..78123bb0639 100644
--- a/chromium/components/content_settings/core/common/BUILD.gn
+++ b/chromium/components/content_settings/core/common/BUILD.gn
@@ -18,14 +18,16 @@ jumbo_static_library("common") {
"content_settings_utils.h",
"cookie_settings_base.cc",
"cookie_settings_base.h",
- "features.cc",
- "features.h",
"pref_names.cc",
"pref_names.h",
]
configs += [ "//build/config/compiler:wexit_time_destructors" ]
+ public_deps = [
+ ":features",
+ ]
+
deps = [
"//base",
"//mojo/public/cpp/base",
@@ -62,3 +64,18 @@ mojom("mojo_bindings") {
"//mojo/public/mojom/base",
]
}
+
+component("features") {
+ output_name = "content_settings_features"
+
+ defines = [ "IS_CONTENT_SETTINGS_FEATURES_IMPL" ]
+
+ sources = [
+ "features.cc",
+ "features.h",
+ ]
+
+ deps = [
+ "//base",
+ ]
+}
diff --git a/chromium/components/content_settings/core/common/DEPS b/chromium/components/content_settings/core/common/DEPS
index 7aab7130bcd..43d061f8481 100644
--- a/chromium/components/content_settings/core/common/DEPS
+++ b/chromium/components/content_settings/core/common/DEPS
@@ -3,6 +3,7 @@ include_rules = [
"+mojo/public/cpp/bindings",
"+net/base",
"+net/cookies/cookie_util.h",
+ "+net/cookies/cookie_constants.h",
"+testing",
"+url",
]
diff --git a/chromium/components/content_settings/core/common/OWNERS b/chromium/components/content_settings/core/common/OWNERS
index fda0d857f5e..ab87d1e6148 100644
--- a/chromium/components/content_settings/core/common/OWNERS
+++ b/chromium/components/content_settings/core/common/OWNERS
@@ -1,8 +1,8 @@
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/content_settings/core/common/content_settings.cc b/chromium/components/content_settings/core/common/content_settings.cc
index f8c6e6a7242..5fc4d9fdcb6 100644
--- a/chromium/components/content_settings/core/common/content_settings.cc
+++ b/chromium/components/content_settings/core/common/content_settings.cc
@@ -78,6 +78,7 @@ constexpr HistogramValue kHistogramValue[] = {
{CONTENT_SETTINGS_TYPE_WAKE_LOCK_SCREEN, 54},
{CONTENT_SETTINGS_TYPE_WAKE_LOCK_SYSTEM, 55},
{CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS, 56},
+ {CONTENT_SETTINGS_TYPE_NATIVE_FILE_SYSTEM_WRITE_GUARD, 57},
};
} // namespace
diff --git a/chromium/components/content_settings/core/common/content_settings.typemap b/chromium/components/content_settings/core/common/content_settings.typemap
index 200cd73767d..cac3afda605 100644
--- a/chromium/components/content_settings/core/common/content_settings.typemap
+++ b/chromium/components/content_settings/core/common/content_settings.typemap
@@ -15,9 +15,9 @@ public_headers = [
"//components/content_settings/core/common/content_settings_pattern.h",
]
sources = [
- "//components/content_settings/core/common/content_settings_struct_traits.cc",
+ "//components/content_settings/core/common/content_settings_mojom_traits.cc",
]
-traits_headers = [ "//components/content_settings/core/common/content_settings_struct_traits.h" ]
+traits_headers = [ "//components/content_settings/core/common/content_settings_mojom_traits.h" ]
type_mappings = [
"content_settings.mojom.PatternParts=::ContentSettingsPattern::PatternParts",
"content_settings.mojom.ContentSettingsPattern=::ContentSettingsPattern",
diff --git a/chromium/components/content_settings/core/common/content_settings_struct_traits.cc b/chromium/components/content_settings/core/common/content_settings_mojom_traits.cc
index 74291e690bc..e4faf6a2a5c 100644
--- a/chromium/components/content_settings/core/common/content_settings_struct_traits.cc
+++ b/chromium/components/content_settings/core/common/content_settings_mojom_traits.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 "components/content_settings/core/common/content_settings_struct_traits.h"
+#include "components/content_settings/core/common/content_settings_mojom_traits.h"
namespace mojo {
diff --git a/chromium/components/content_settings/core/common/content_settings_struct_traits.h b/chromium/components/content_settings/core/common/content_settings_mojom_traits.h
index 55d50d612b0..c8b57f679ad 100644
--- a/chromium/components/content_settings/core/common/content_settings_struct_traits.h
+++ b/chromium/components/content_settings/core/common/content_settings_mojom_traits.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 COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_CONTENT_SETTINGS_STRUCT_TRAITS_H
-#define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_CONTENT_SETTINGS_STRUCT_TRAITS_H
+#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_CONTENT_SETTINGS_MOJOM_TRAITS_H_
+#define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_CONTENT_SETTINGS_MOJOM_TRAITS_H_
#include <string>
@@ -152,4 +152,4 @@ struct StructTraits<
} // namespace mojo
-#endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_CONTENT_SETTINGS_STRUCT_TRAITS_H
+#endif // COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_CONTENT_SETTINGS_MOJOM_TRAITS_H_
diff --git a/chromium/components/content_settings/core/common/content_settings_types.h b/chromium/components/content_settings/core/common/content_settings_types.h
index 8f7b2004d9d..8bb5011ffb8 100644
--- a/chromium/components/content_settings/core/common/content_settings_types.h
+++ b/chromium/components/content_settings/core/common/content_settings_types.h
@@ -167,6 +167,11 @@ enum ContentSettingsType {
// in cookie handling are introduced.
CONTENT_SETTINGS_TYPE_LEGACY_COOKIE_ACCESS,
+ // Content settings which stores whether to allow sites to ask for permission
+ // to save changes to an original file selected by the user through the Native
+ // File System API.
+ CONTENT_SETTINGS_TYPE_NATIVE_FILE_SYSTEM_WRITE_GUARD,
+
CONTENT_SETTINGS_NUM_TYPES,
};
diff --git a/chromium/components/content_settings/core/common/cookie_settings_base.cc b/chromium/components/content_settings/core/common/cookie_settings_base.cc
index e4909a9b80e..afbff0630db 100644
--- a/chromium/components/content_settings/core/common/cookie_settings_base.cc
+++ b/chromium/components/content_settings/core/common/cookie_settings_base.cc
@@ -3,10 +3,25 @@
// found in the LICENSE file.
#include "components/content_settings/core/common/cookie_settings_base.h"
+
+#include "base/debug/stack_trace.h"
+#include "base/debug/task_trace.h"
+#include "base/feature_list.h"
+#include "base/logging.h"
+#include "components/content_settings/core/common/features.h"
+#include "net/base/net_errors.h"
+#include "net/base/static_cookie_policy.h"
#include "net/cookies/cookie_util.h"
#include "url/gurl.h"
namespace content_settings {
+namespace {
+bool IsThirdPartyRequest(const GURL& url, const GURL& site_for_cookies) {
+ net::StaticCookiePolicy policy(
+ net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES);
+ return policy.CanAccessCookies(url, site_for_cookies) != net::OK;
+}
+} // namespace
bool CookieSettingsBase::ShouldDeleteCookieOnExit(
const ContentSettingsForOneType& cookie_settings,
@@ -38,14 +53,45 @@ bool CookieSettingsBase::ShouldDeleteCookieOnExit(
return setting == CONTENT_SETTING_SESSION_ONLY || matches_session_only_rule;
}
+void CookieSettingsBase::GetCookieSetting(
+ const GURL& url,
+ const GURL& first_party_url,
+ content_settings::SettingSource* source,
+ ContentSetting* cookie_setting) const {
+ GetCookieSettingInternal(url, first_party_url,
+ IsThirdPartyRequest(url, first_party_url), source,
+ cookie_setting);
+}
+
bool CookieSettingsBase::IsCookieAccessAllowed(
const GURL& url,
const GURL& first_party_url) const {
+ DCHECK(!base::FeatureList::IsEnabled(kImprovedCookieControls) ||
+ !first_party_url.is_empty() || url.is_empty())
+ << url;
ContentSetting setting;
GetCookieSetting(url, first_party_url, nullptr, &setting);
return IsAllowed(setting);
}
+bool CookieSettingsBase::IsCookieAccessAllowed(
+ const GURL& url,
+ const GURL& site_for_cookies,
+ const base::Optional<url::Origin>& top_frame_origin) const {
+ // TODO(crbug.com/988398): top_frame_origin is not yet always available.
+ // Ensure that the DCHECK always passes and remove the FeatureList check.
+ if (!base::FeatureList::IsEnabled(kImprovedCookieControls))
+ return IsCookieAccessAllowed(url, site_for_cookies);
+ DCHECK(top_frame_origin || site_for_cookies.is_empty())
+ << url << " " << site_for_cookies;
+
+ ContentSetting setting;
+ GetCookieSettingInternal(
+ url, top_frame_origin ? top_frame_origin->GetURL() : GURL(),
+ IsThirdPartyRequest(url, site_for_cookies), nullptr, &setting);
+ return IsAllowed(setting);
+}
+
bool CookieSettingsBase::IsCookieSessionOnly(const GURL& origin) const {
ContentSetting setting;
GetCookieSetting(origin, origin, nullptr, &setting);
@@ -53,6 +99,23 @@ bool CookieSettingsBase::IsCookieSessionOnly(const GURL& origin) const {
return setting == CONTENT_SETTING_SESSION_ONLY;
}
+net::CookieAccessSemantics
+CookieSettingsBase::GetCookieAccessSemanticsForDomain(
+ const GURL& cookie_domain) const {
+ ContentSetting setting;
+ GetSettingForLegacyCookieAccess(cookie_domain, &setting);
+ DCHECK(IsValidSettingForLegacyAccess(setting));
+ switch (setting) {
+ case CONTENT_SETTING_ALLOW:
+ return net::CookieAccessSemantics::LEGACY;
+ case CONTENT_SETTING_BLOCK:
+ return net::CookieAccessSemantics::NONLEGACY;
+ default:
+ NOTREACHED();
+ }
+ return net::CookieAccessSemantics::UNKNOWN;
+}
+
// static
bool CookieSettingsBase::IsValidSetting(ContentSetting setting) {
return (setting == CONTENT_SETTING_ALLOW ||
@@ -67,4 +130,9 @@ bool CookieSettingsBase::IsAllowed(ContentSetting setting) {
setting == CONTENT_SETTING_SESSION_ONLY);
}
+// static
+bool CookieSettingsBase::IsValidSettingForLegacyAccess(ContentSetting setting) {
+ return (setting == CONTENT_SETTING_ALLOW || setting == CONTENT_SETTING_BLOCK);
+}
+
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/common/cookie_settings_base.h b/chromium/components/content_settings/core/common/cookie_settings_base.h
index e23181772fe..e410e0d3e40 100644
--- a/chromium/components/content_settings/core/common/cookie_settings_base.h
+++ b/chromium/components/content_settings/core/common/cookie_settings_base.h
@@ -7,10 +7,54 @@
#include <string>
+#include "base/optional.h"
#include "components/content_settings/core/common/content_settings.h"
+#include "net/cookies/cookie_constants.h"
+
+namespace url {
+class Origin;
+}
namespace content_settings {
+// Many CookieSettings methods handle the parameters |url|, |site_for_cookies|
+// |top_frame_origin| and |first_party_url|.
+//
+// |url| is the URL of the requested resource.
+// |site_for_cookies| is usually the URL shown in the omnibox but can also be
+// empty, e.g. for subresource loads initiated from cross-site iframes, and is
+// used to determine if a request is done in a third-party context.
+// |top_frame_origin| is the origin shown in the omnibox.
+//
+// Example:
+// https://a.com/index.html
+// <html>
+// <body>
+// <iframe href="https://b.com/frame.html">
+// <img href="https://a.com/img.jpg>
+// <img href="https://b.com/img.jpg>
+// <img href="https://c.com/img.jpg>
+// </iframe>
+// </body>
+// </html>
+//
+// When each of these resources get fetched, |top_frame_origin| will always be
+// "https://a.com" and |site_for_cookies| is set the following:
+// https://a.com/index.html -> https://a.com/ (1p request)
+// https://b.com/frame.html -> https://a.com/ (3p request)
+// https://a.com/img.jpg -> <empty-url> (treated as 3p request)
+// https://b.com/img.jpg -> <empty-url> (3p because from cross site iframe)
+// https://c.com/img.jpg -> <empty-url> (3p request in cross site iframe)
+//
+// Content settings can be used to allow or block access to cookies.
+// When third-party cookies are blocked, an ALLOW setting will give access to
+// cookies in third-party contexts.
+// The primary pattern of each setting is matched against |url|.
+// The secondary pattern is matched against |top_frame_origin|.
+//
+// Some methods only take |url| and |first_party_url|. For |first_party_url|,
+// clients either pass a value that is like |site_for_cookies| or
+// |top_frame_origin|. This is done inconsistently and needs to be fixed.
class CookieSettingsBase {
public:
CookieSettingsBase() = default;
@@ -31,12 +75,25 @@ class CookieSettingsBase {
bool is_https) const;
// Returns true if the page identified by (|url|, |first_party_url|) is
- // allowed to access (i.e., read or write) cookies.
+ // allowed to access (i.e., read or write) cookies. |first_party_url|
+ // is used to determine third-party-ness of |url|.
//
// This may be called on any thread.
+ // DEPRECATED: Replace with IsCookieAccessAllowed(GURL, GURL, Origin).
bool IsCookieAccessAllowed(const GURL& url,
const GURL& first_party_url) const;
+ // Similar to IsCookieAccessAllowed(GURL, GURL) but provides a mechanism
+ // to specify a separate |site_for_cookies|, which is used to determine
+ // whether a request is in a third_party context and |top_frame_origin|, which
+ // is used to check if there are any content_settings exceptions.
+ // |top_frame_origin| should at least be specified when |site_for_cookies| is
+ // non-empty.
+ bool IsCookieAccessAllowed(
+ const GURL& url,
+ const GURL& site_for_cookies,
+ const base::Optional<url::Origin>& top_frame_origin) const;
+
// Returns true if the cookie set by a page identified by |url| should be
// session only. Querying this only makes sense if |IsCookieAccessAllowed|
// has returned true.
@@ -45,17 +102,41 @@ class CookieSettingsBase {
bool IsCookieSessionOnly(const GURL& url) const;
// A helper for applying third party cookie blocking rules.
- virtual void GetCookieSetting(const GURL& url,
- const GURL& first_party_url,
- content_settings::SettingSource* source,
- ContentSetting* cookie_setting) const = 0;
+ void GetCookieSetting(const GURL& url,
+ const GURL& first_party_url,
+ content_settings::SettingSource* source,
+ ContentSetting* cookie_setting) const;
+
+ // Returns the cookie access semantics (legacy or nonlegacy) to be applied for
+ // cookies on the given domain.
+ //
+ // This may be called on any thread.
+ net::CookieAccessSemantics GetCookieAccessSemanticsForDomain(
+ const GURL& cookie_domain) const;
+
+ // Gets the setting that controls whether legacy access is allowed for a given
+ // cookie domain (provided as a URL).
+ virtual void GetSettingForLegacyCookieAccess(
+ const GURL& cookie_domain,
+ ContentSetting* setting) const = 0;
// Determines whether |setting| is a valid content setting for cookies.
static bool IsValidSetting(ContentSetting setting);
// Determines whether |setting| means the cookie should be allowed.
static bool IsAllowed(ContentSetting setting);
+ // Determines whether |setting| is a valid content setting for legacy cookie
+ // access.
+ static bool IsValidSettingForLegacyAccess(ContentSetting setting);
+
private:
+ virtual void GetCookieSettingInternal(
+ const GURL& url,
+ const GURL& first_party_url,
+ bool is_third_party_request,
+ content_settings::SettingSource* source,
+ ContentSetting* cookie_setting) const = 0;
+
DISALLOW_COPY_AND_ASSIGN(CookieSettingsBase);
};
diff --git a/chromium/components/content_settings/core/common/cookie_settings_base_unittest.cc b/chromium/components/content_settings/core/common/cookie_settings_base_unittest.cc
index 0d960de2392..a606322f064 100644
--- a/chromium/components/content_settings/core/common/cookie_settings_base_unittest.cc
+++ b/chromium/components/content_settings/core/common/cookie_settings_base_unittest.cc
@@ -29,12 +29,17 @@ class CallbackCookieSettings : public CookieSettingsBase {
: callback_(std::move(callback)) {}
// CookieSettingsBase:
- void GetCookieSetting(const GURL& url,
- const GURL& first_party_url,
- content_settings::SettingSource* source,
- ContentSetting* cookie_setting) const override {
+ void GetCookieSettingInternal(const GURL& url,
+ const GURL& first_party_url,
+ bool is_third_party_request,
+ content_settings::SettingSource* source,
+ ContentSetting* cookie_setting) const override {
*cookie_setting = callback_.Run(url);
}
+ void GetSettingForLegacyCookieAccess(const GURL& cookie_domain,
+ ContentSetting* setting) const override {
+ *setting = callback_.Run(cookie_domain);
+ }
private:
GetSettingCallback callback_;
@@ -102,37 +107,48 @@ TEST(CookieSettingsBaseTest, ShouldNotDeleteNoDomainMatch) {
TEST(CookieSettingsBaseTest, CookieAccessNotAllowedWithBlockedSetting) {
CallbackCookieSettings settings(
base::BindRepeating([](const GURL&) { return CONTENT_SETTING_BLOCK; }));
- EXPECT_FALSE(settings.IsCookieAccessAllowed(GURL(), GURL()));
+ EXPECT_FALSE(settings.IsCookieAccessAllowed(GURL(kDomain), GURL(kDomain)));
}
TEST(CookieSettingsBaseTest, CookieAccessAllowedWithAllowSetting) {
CallbackCookieSettings settings(
base::BindRepeating([](const GURL&) { return CONTENT_SETTING_ALLOW; }));
- EXPECT_TRUE(settings.IsCookieAccessAllowed(GURL(), GURL()));
+ EXPECT_TRUE(settings.IsCookieAccessAllowed(GURL(kDomain), GURL(kDomain)));
}
TEST(CookieSettingsBaseTest, CookieAccessAllowedWithSessionOnlySetting) {
CallbackCookieSettings settings(base::BindRepeating(
[](const GURL&) { return CONTENT_SETTING_SESSION_ONLY; }));
- EXPECT_TRUE(settings.IsCookieAccessAllowed(GURL(), GURL()));
+ EXPECT_TRUE(settings.IsCookieAccessAllowed(GURL(kDomain), GURL(kDomain)));
+}
+
+TEST(CookieSettingsBaseTest, LegacyCookieAccessSemantics) {
+ CallbackCookieSettings settings1(
+ base::BindRepeating([](const GURL&) { return CONTENT_SETTING_ALLOW; }));
+ EXPECT_EQ(net::CookieAccessSemantics::LEGACY,
+ settings1.GetCookieAccessSemanticsForDomain(GURL()));
+ CallbackCookieSettings settings2(
+ base::BindRepeating([](const GURL&) { return CONTENT_SETTING_BLOCK; }));
+ EXPECT_EQ(net::CookieAccessSemantics::NONLEGACY,
+ settings2.GetCookieAccessSemanticsForDomain(GURL()));
}
TEST(CookieSettingsBaseTest, IsCookieSessionOnlyWithAllowSetting) {
CallbackCookieSettings settings(
base::BindRepeating([](const GURL&) { return CONTENT_SETTING_ALLOW; }));
- EXPECT_FALSE(settings.IsCookieSessionOnly(GURL()));
+ EXPECT_FALSE(settings.IsCookieSessionOnly(GURL(kDomain)));
}
TEST(CookieSettingsBaseTest, IsCookieSessionOnlyWithBlockSetting) {
CallbackCookieSettings settings(
base::BindRepeating([](const GURL&) { return CONTENT_SETTING_BLOCK; }));
- EXPECT_FALSE(settings.IsCookieSessionOnly(GURL()));
+ EXPECT_FALSE(settings.IsCookieSessionOnly(GURL(kDomain)));
}
TEST(CookieSettingsBaseTest, IsCookieSessionOnlySessionWithOnlySetting) {
CallbackCookieSettings settings(base::BindRepeating(
[](const GURL&) { return CONTENT_SETTING_SESSION_ONLY; }));
- EXPECT_TRUE(settings.IsCookieSessionOnly(GURL()));
+ EXPECT_TRUE(settings.IsCookieSessionOnly(GURL(kDomain)));
}
TEST(CookieSettingsBaseTest, IsValidSetting) {
@@ -149,5 +165,18 @@ TEST(CookieSettingsBaseTest, IsAllowed) {
EXPECT_TRUE(CookieSettingsBase::IsAllowed(CONTENT_SETTING_SESSION_ONLY));
}
+TEST(CookieSettingsBaseTest, IsValidLegacyAccessSetting) {
+ EXPECT_FALSE(CookieSettingsBase::IsValidSettingForLegacyAccess(
+ CONTENT_SETTING_DEFAULT));
+ EXPECT_FALSE(
+ CookieSettingsBase::IsValidSettingForLegacyAccess(CONTENT_SETTING_ASK));
+ EXPECT_TRUE(
+ CookieSettingsBase::IsValidSettingForLegacyAccess(CONTENT_SETTING_ALLOW));
+ EXPECT_TRUE(
+ CookieSettingsBase::IsValidSettingForLegacyAccess(CONTENT_SETTING_BLOCK));
+ EXPECT_FALSE(CookieSettingsBase::IsValidSettingForLegacyAccess(
+ CONTENT_SETTING_SESSION_ONLY));
+}
+
} // namespace
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/common/features.h b/chromium/components/content_settings/core/common/features.h
index 817b2f1cc78..846d495ef9d 100644
--- a/chromium/components/content_settings/core/common/features.h
+++ b/chromium/components/content_settings/core/common/features.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_FEATURES_H_
#define COMPONENTS_CONTENT_SETTINGS_CORE_COMMON_FEATURES_H_
+#include "base/component_export.h"
+
namespace base {
struct Feature;
} // namespace base
@@ -12,6 +14,7 @@ struct Feature;
namespace content_settings {
// Feature to enable a better cookie controls ui.
+COMPONENT_EXPORT(CONTENT_SETTINGS_FEATURES)
extern const base::Feature kImprovedCookieControls;
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/common/pref_names.cc b/chromium/components/content_settings/core/common/pref_names.cc
index 0e51b1c7fc3..42751eee13a 100644
--- a/chromium/components/content_settings/core/common/pref_names.cc
+++ b/chromium/components/content_settings/core/common/pref_names.cc
@@ -10,9 +10,10 @@ namespace prefs {
// regardless of other content settings.
const char kBlockThirdPartyCookies[] = "profile.block_third_party_cookies";
-// Boolean that is true if the new cookie controls UI is enabled. This will
-// block third-party cookies similar to kBlockThirdPartyCookies.
-const char kCookieControlsEnabled[] = "profile.cookie_controls_enabled";
+// CookieControlsMode enum value that decides when the cookie controls UI is
+// enabled. This will block third-party cookies similar to
+// kBlockThirdPartyCookies but with a new UI.
+const char kCookieControlsMode[] = "profile.cookie_controls_mode";
// Version of the pattern format used to define content settings.
const char kContentSettingsVersion[] = "profile.content_settings.pref_version";
diff --git a/chromium/components/content_settings/core/common/pref_names.h b/chromium/components/content_settings/core/common/pref_names.h
index c7aab250b1b..6b843a97fa3 100644
--- a/chromium/components/content_settings/core/common/pref_names.h
+++ b/chromium/components/content_settings/core/common/pref_names.h
@@ -16,7 +16,7 @@ namespace prefs {
// TODO(crbug.com/967668): Remove direct access to these preferences and
// replace with CookieSettings::ShouldBlockThirdPartyCookies().
extern const char kBlockThirdPartyCookies[];
-extern const char kCookieControlsEnabled[];
+extern const char kCookieControlsMode[];
extern const char kContentSettingsVersion[];
extern const char kContentSettingsWindowLastTabIndex[];
diff --git a/chromium/components/contextual_search/core/browser/public.cc b/chromium/components/contextual_search/core/browser/public.cc
index 42755adfdf5..e118db1af79 100644
--- a/chromium/components/contextual_search/core/browser/public.cc
+++ b/chromium/components/contextual_search/core/browser/public.cc
@@ -12,6 +12,7 @@ const char kContextualSearchFieldTrialName[] = "ContextualSearch";
const char kLongpressResolveParamName[] = "longpress_resolve_variation";
const char kLongpressResolveHideOnScroll[] = "1";
const char kLongpressResolvePrivacyAggressive[] = "2";
+const char kLongpressResolvePreserveTap[] = "3";
// Contextual Cards variations and integration Api settings.
const char kContextualCardsVersionParamName[] = "contextual_cards_version";
diff --git a/chromium/components/contextual_search/core/browser/public.h b/chromium/components/contextual_search/core/browser/public.h
index 08181a762c2..aaea50f968e 100644
--- a/chromium/components/contextual_search/core/browser/public.h
+++ b/chromium/components/contextual_search/core/browser/public.h
@@ -42,6 +42,7 @@ extern const char kContextualCardsSimplifiedServerWithDiagnosticChar[];
extern const char kLongpressResolveParamName[];
extern const char kLongpressResolveHideOnScroll[];
extern const char kLongpressResolvePrivacyAggressive[];
+extern const char kLongpressResolvePreserveTap[];
} // namespace contextual_search
diff --git a/chromium/components/crash/content/app/BUILD.gn b/chromium/components/crash/content/app/BUILD.gn
index 529131ef392..62c848e04bb 100644
--- a/chromium/components/crash/content/app/BUILD.gn
+++ b/chromium/components/crash/content/app/BUILD.gn
@@ -69,6 +69,7 @@ static_library("app") {
]
deps = [
"//base",
+ "//build:branding_buildflags",
]
if (is_mac || is_win || is_android) {
@@ -95,13 +96,14 @@ static_library("app") {
"//content/public/common:result_codes",
"//sandbox",
]
+ }
- if (is_linux) {
- deps += [
- "//content/public/common",
- "//third_party/breakpad:client",
- ]
- }
+ if (is_linux) {
+ deps += [ "//third_party/breakpad:client" ]
+ }
+
+ if (is_chromeos) {
+ deps += [ "//content/public/common" ]
}
if (is_win) {
@@ -213,7 +215,7 @@ if (is_win) {
}
}
-if (is_mac) {
+if (is_mac || is_android) {
# We build a chromium-specific crashpad_handler executable so that we can
# define custom UserStreamDataSources.
executable("chrome_crashpad_handler") {
@@ -222,15 +224,11 @@ if (is_mac) {
]
deps = [
- "//components/gwp_asan/buildflags",
- "//third_party/crashpad/crashpad/handler:handler",
+ ":crashpad_handler_main",
+ "//third_party/crashpad/crashpad/handler",
]
- if (enable_gwp_asan) {
- deps += [ "//components/gwp_asan/crash_handler" ]
- }
-
- if (is_component_build) {
+ if (is_mac && is_component_build) {
ldflags = [
# The handler is in
# Chromium.app/Contents/Versions/X/Chromium Framework.framework/Versions/A/Helpers/
@@ -257,6 +255,26 @@ if (is_mac) {
}
}
+if (is_android) {
+ # There is not any normal way to package native executables in an Android APK.
+ # It is normal to package native code as a loadable module but Android's APK
+ # installer will ignore files not named like a shared object, so give the
+ # handler executable an acceptable name.
+ copy("chrome_crashpad_handler_named_as_so") {
+ deps = [
+ ":chrome_crashpad_handler",
+ ]
+
+ sources = [
+ "$root_out_dir/chrome_crashpad_handler",
+ ]
+
+ outputs = [
+ "$root_out_dir/libchrome_crashpad_handler.so",
+ ]
+ }
+}
+
# This source set provides the functionality required for tests, which on Windows
# link the export thunks directly into the test binary.
source_set("test_support") {
diff --git a/chromium/components/crash/content/app/breakpad_linux.cc b/chromium/components/crash/content/app/breakpad_linux.cc
index bb5ee46d3f2..505156ada2d 100644
--- a/chromium/components/crash/content/app/breakpad_linux.cc
+++ b/chromium/components/crash/content/app/breakpad_linux.cc
@@ -45,8 +45,6 @@
#include "components/crash/content/app/crash_reporter_client.h"
#include "components/crash/core/common/crash_keys.h"
#include "content/public/common/content_descriptors.h"
-#include "content/public/common/content_switches.h"
-#include "services/service_manager/embedder/switches.h"
#include "third_party/breakpad/breakpad/src/client/linux/crash_generation/crash_generation_client.h"
#include "third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h"
#include "third_party/breakpad/breakpad/src/client/linux/minidump_writer/directory_reader.h"
@@ -64,6 +62,11 @@
#endif
#include "third_party/lss/linux_syscall_support.h"
+#if defined(OS_CHROMEOS)
+#include "content/public/common/content_switches.h" // nogncheck
+#include "services/service_manager/embedder/switches.h" // nogncheck
+#endif
+
#if defined(ADDRESS_SANITIZER)
#include <ucontext.h> // for getcontext().
#endif
@@ -1065,7 +1068,12 @@ class NonBrowserCrashHandler : public google_breakpad::CrashGenerationClient {
#if !defined(ADDRESS_SANITIZER)
static_assert(5 == kCrashIovSize - 1, "kCrashIovSize should equal 6");
#else
- iov[6].iov_base = const_cast<char*>(g_asan_report_str);
+ if (g_asan_report_str != nullptr) {
+ iov[6].iov_base = const_cast<char*>(g_asan_report_str);
+ } else {
+ static char empty_asan_report[kMaxAsanReportSize + 1];
+ iov[6].iov_base = empty_asan_report;
+ }
iov[6].iov_len = kMaxAsanReportSize + 1;
static_assert(6 == kCrashIovSize - 1, "kCrashIovSize should equal 7");
#endif
@@ -1146,10 +1154,6 @@ void InitCrashKeys() {
void SetCrashLoopBeforeTime(const std::string& process_type,
const base::CommandLine& parsed_command_line) {
#if defined(OS_CHROMEOS)
- if (!ShouldPassCrashLoopBefore(process_type)) {
- return;
- }
-
std::string crash_loop_before =
parsed_command_line.GetSwitchValueASCII(switches::kCrashLoopBefore);
if (crash_loop_before.empty()) {
@@ -2161,21 +2165,6 @@ void SuppressDumpGeneration() {
}
#endif // OS_ANDROID
-#if defined(OS_CHROMEOS)
-bool ShouldPassCrashLoopBefore(const std::string& process_type) {
- if (process_type == ::switches::kRendererProcess ||
- process_type == ::switches::kUtilityProcess ||
- process_type == ::switches::kPpapiPluginProcess ||
- process_type == service_manager::switches::kZygoteProcess) {
- // These process types never cause a log-out, even if they crash. So the
- // normal crash handling process should work fine; we shouldn't need to
- // invoke the special crash-loop mode.
- return false;
- }
- return true;
-}
-#endif // defined(OS_CHROMEOS)
-
bool IsCrashReporterEnabled() {
return g_is_crash_reporter_enabled;
}
diff --git a/chromium/components/crash/content/app/breakpad_linux.h b/chromium/components/crash/content/app/breakpad_linux.h
index fb7f0a8af26..6e95af6ca7f 100644
--- a/chromium/components/crash/content/app/breakpad_linux.h
+++ b/chromium/components/crash/content/app/breakpad_linux.h
@@ -58,13 +58,6 @@ extern void AddGpuFingerprintToMicrodumpCrashHandler(
extern void SuppressDumpGeneration();
#endif // defined(OS_ANDROID)
-#if defined(OS_CHROMEOS)
-// If true, processes of this type should pass crash-loop-before down to the
-// crash reporter and to their children (if the children's type is a process
-// type that wants crash-loop-before).
-bool ShouldPassCrashLoopBefore(const std::string& process_type);
-#endif
-
// Checks if crash reporting is enabled. Note that this is not the same as
// being opted into metrics reporting (and crash reporting), which controls
// whether InitCrashReporter() is called.
diff --git a/chromium/components/crash/content/app/chrome_crashpad_handler.cc b/chromium/components/crash/content/app/chrome_crashpad_handler.cc
index c4b629d8263..997f0699510 100644
--- a/chromium/components/crash/content/app/chrome_crashpad_handler.cc
+++ b/chromium/components/crash/content/app/chrome_crashpad_handler.cc
@@ -2,22 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <memory>
-
-#include "components/gwp_asan/buildflags/buildflags.h"
-#include "third_party/crashpad/crashpad/handler/handler_main.h"
-#include "third_party/crashpad/crashpad/handler/user_stream_data_source.h"
-
-#if BUILDFLAG(ENABLE_GWP_ASAN)
-#include "components/gwp_asan/crash_handler/crash_handler.h"
-#endif
+// Forward declare this for macOS (it's only defined by crashpad on Android.)
+extern "C" int CrashpadHandlerMain(int argc, char* argv[]);
int main(int argc, char* argv[]) {
- crashpad::UserStreamDataSources user_stream_data_sources;
-#if BUILDFLAG(ENABLE_GWP_ASAN)
- user_stream_data_sources.push_back(
- std::make_unique<gwp_asan::UserStreamDataSource>());
-#endif
-
- return crashpad::HandlerMain(argc, argv, &user_stream_data_sources);
+ return CrashpadHandlerMain(argc, argv);
}
diff --git a/chromium/components/crash/content/app/crashpad.h b/chromium/components/crash/content/app/crashpad.h
index 2324c1eb56c..1ffb7f62663 100644
--- a/chromium/components/crash/content/app/crashpad.h
+++ b/chromium/components/crash/content/app/crashpad.h
@@ -170,6 +170,10 @@ void DumpProcessWithoutCrashing(task_t task_port);
// success.
class CrashReporterClient;
bool DumpWithoutCrashingForClient(CrashReporterClient* client);
+
+// Used under WebView to whitelist a memory range so it's accessible using
+// crashpad's ProcessMemory interface.
+void WhitelistMemoryRange(void* begin, size_t size);
#endif // OS_ANDROID
namespace internal {
diff --git a/chromium/components/crash/content/app/crashpad_android.cc b/chromium/components/crash/content/app/crashpad_android.cc
index 991120a9fb1..3db45824e41 100644
--- a/chromium/components/crash/content/app/crashpad_android.cc
+++ b/chromium/components/crash/content/app/crashpad_android.cc
@@ -30,6 +30,8 @@
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/crash/android/jni_headers/PackagePaths_jni.h"
#include "components/crash/content/app/crash_reporter_client.h"
@@ -50,6 +52,43 @@
namespace crashpad {
namespace {
+class MemoryRangeWhitelist {
+ public:
+ MemoryRangeWhitelist() {
+ whitelist_.entries = 0;
+ whitelist_.size = 0;
+ }
+
+ void AddEntry(VMAddress base, VMSize length) {
+ SanitizationMemoryRangeWhitelist::Range new_entry;
+ new_entry.base = base;
+ new_entry.length = length;
+
+ base::AutoLock lock(lock_);
+ std::vector<SanitizationMemoryRangeWhitelist::Range> new_array(array_);
+ new_array.push_back(new_entry);
+ whitelist_.entries = FromPointerCast<VMAddress>(new_array.data());
+ whitelist_.size += 1;
+ array_ = std::move(new_array);
+ }
+
+ SanitizationMemoryRangeWhitelist* GetSanitizationAddress() {
+ return &whitelist_;
+ }
+
+ static MemoryRangeWhitelist* Singleton() {
+ static base::NoDestructor<MemoryRangeWhitelist> singleton;
+ return singleton.get();
+ }
+
+ private:
+ base::Lock lock_;
+ SanitizationMemoryRangeWhitelist whitelist_;
+ std::vector<SanitizationMemoryRangeWhitelist::Range> array_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryRangeWhitelist);
+};
+
bool SetSanitizationInfo(crash_reporter::CrashReporterClient* client,
SanitizationInformation* info) {
const char* const* whitelist = nullptr;
@@ -59,6 +98,8 @@ bool SetSanitizationInfo(crash_reporter::CrashReporterClient* client,
&sanitize_stacks);
info->annotations_whitelist_address = FromPointerCast<VMAddress>(whitelist);
info->target_module_address = FromPointerCast<VMAddress>(target_module);
+ info->memory_range_whitelist_address = FromPointerCast<VMAddress>(
+ MemoryRangeWhitelist::Singleton()->GetSanitizationAddress());
info->sanitize_stacks = sanitize_stacks;
return whitelist != nullptr || target_module != nullptr || sanitize_stacks;
}
@@ -367,7 +408,7 @@ void BuildHandlerArgs(CrashReporterClient* crash_reporter_client,
SetBuildInfoAnnotations(process_annotations);
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Empty means stable.
const bool allow_empty_channel = true;
#else
@@ -397,7 +438,7 @@ bool GetHandlerPath(base::FilePath* exe_dir, base::FilePath* handler_path) {
if (!base::PathService::Get(base::DIR_MODULE, exe_dir)) {
return false;
}
- *handler_path = exe_dir->Append("libcrashpad_handler.so");
+ *handler_path = exe_dir->Append("libchrome_crashpad_handler.so");
return true;
}
@@ -635,6 +676,12 @@ bool DumpWithoutCrashingForClient(CrashReporterClient* client) {
return handler_client.RequestCrashDump(info) == 0;
}
+void WhitelistMemoryRange(void* begin, size_t length) {
+ crashpad::MemoryRangeWhitelist::Singleton()->AddEntry(
+ crashpad::FromPointerCast<crashpad::VMAddress>(begin),
+ static_cast<crashpad::VMSize>(length));
+}
+
namespace internal {
bool StartHandlerForClient(int fd) {
diff --git a/chromium/components/crash/content/app/crashpad_mac.mm b/chromium/components/crash/content/app/crashpad_mac.mm
index a76d264648d..c2de9fe867c 100644
--- a/chromium/components/crash/content/app/crashpad_mac.mm
+++ b/chromium/components/crash/content/app/crashpad_mac.mm
@@ -20,6 +20,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
+#include "build/branding_buildflags.h"
#include "components/crash/content/app/crash_reporter_client.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
#include "third_party/crashpad/crashpad/client/crashpad_client.h"
@@ -43,7 +44,7 @@ std::map<std::string, std::string> GetProcessSimpleAnnotations() {
process_annotations["prod"] =
base::SysNSStringToUTF8(product).append("_Mac");
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Empty means stable.
const bool allow_empty_channel = true;
#else
@@ -132,7 +133,7 @@ base::FilePath PlatformCrashpadInitialization(
crash_reporter_client->GetCrashDumpLocation(&database_path);
crash_reporter_client->GetCrashMetricsLocation(&metrics_path);
-#if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && defined(OFFICIAL_BUILD)
// Only allow the possibility of report upload in official builds. This
// crash server won't have symbols for any other build types.
std::string url = "https://clients2.google.com/cr/report";
diff --git a/chromium/components/crash/content/app/crashpad_win.cc b/chromium/components/crash/content/app/crashpad_win.cc
index 8f55759a6f4..d13ae5cf7e4 100644
--- a/chromium/components/crash/content/app/crashpad_win.cc
+++ b/chromium/components/crash/content/app/crashpad_win.cc
@@ -16,6 +16,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/crash/content/app/crash_export_thunks.h"
#include "components/crash/content/app/crash_reporter_client.h"
@@ -37,7 +38,7 @@ void GetPlatformCrashpadAnnotations(
exe_file, &product_name, &version, &special_build, &channel_name);
(*annotations)["prod"] = base::UTF16ToUTF8(product_name);
(*annotations)["ver"] = base::UTF16ToUTF8(version);
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Empty means stable.
const bool allow_empty_channel = true;
#else
@@ -83,7 +84,7 @@ base::FilePath PlatformCrashpadInitialization(
std::map<std::string, std::string> process_annotations;
GetPlatformCrashpadAnnotations(&process_annotations);
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
std::string url = "https://clients2.google.com/cr/report";
#else
std::string url;
diff --git a/chromium/components/crash/content/browser/child_process_crash_observer_android.cc b/chromium/components/crash/content/browser/child_process_crash_observer_android.cc
index 814f70409c6..16e202a4f9a 100644
--- a/chromium/components/crash/content/browser/child_process_crash_observer_android.cc
+++ b/chromium/components/crash/content/browser/child_process_crash_observer_android.cc
@@ -15,8 +15,8 @@
namespace crash_reporter {
ChildProcessCrashObserver::ChildProcessCrashObserver() {
- task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+ task_runner_ = base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT});
}
ChildProcessCrashObserver::~ChildProcessCrashObserver() = default;
diff --git a/chromium/components/crash/content/browser/crash_handler_host_linux.cc b/chromium/components/crash/content/browser/crash_handler_host_linux.cc
index 328ef37216c..543ad7bd2dd 100644
--- a/chromium/components/crash/content/browser/crash_handler_host_linux.cc
+++ b/chromium/components/crash/content/browser/crash_handler_host_linux.cc
@@ -118,8 +118,9 @@ CrashHandlerHostLinux::CrashHandlerHostLinux(const std::string& process_type,
upload_(upload),
#endif
fd_watch_controller_(FROM_HERE),
- blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE})) {
+ blocking_task_runner_(
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE})) {
int fds[2];
// We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from
// sending datagrams to other sockets on the system. The sandbox may prevent
@@ -136,7 +137,7 @@ CrashHandlerHostLinux::CrashHandlerHostLinux(const std::string& process_type,
process_socket_ = fds[0];
browser_socket_ = fds[1];
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CrashHandlerHostLinux::Init, base::Unretained(this)));
}
@@ -525,7 +526,7 @@ CrashHandlerHost* CrashHandlerHost::Get() {
}
int CrashHandlerHost::GetDeathSignalSocket() {
- static bool initialized = base::PostTaskWithTraits(
+ static bool initialized = base::PostTask(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&CrashHandlerHost::Init, base::Unretained(this)));
DCHECK(initialized);
diff --git a/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.cc b/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.cc
index bf550f928e8..971e9b6e328 100644
--- a/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.cc
+++ b/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.cc
@@ -4,10 +4,13 @@
#include "components/crash/content/browser/crash_memory_metrics_collector_android.h"
+#include <utility>
+
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/bind_interface_helpers.h"
+#include "mojo/public/cpp/bindings/remote.h"
// Keys used to attach handler to the RenderProcessHost
const void* const CrashMemoryMetricsCollector::kCrashMemoryMetricsCollectorKey =
@@ -23,16 +26,16 @@ CrashMemoryMetricsCollector::GetFromRenderProcessHost(
CrashMemoryMetricsCollector::CrashMemoryMetricsCollector(
content::RenderProcessHost* rph) {
// Initialize bindings with CrashMemoryMetricsReporter.
- content::BindInterface(rph,
- mojo::MakeRequest(&crash_memory_metrics_reporter_));
+ content::BindInterface(rph, &crash_memory_metrics_reporter_);
// Create shared memory and pass it to crash_memory_metrics_reporter.
base::UnsafeSharedMemoryRegion shared_metrics_buffer =
base::UnsafeSharedMemoryRegion::Create(
sizeof(blink::OomInterventionMetrics));
metrics_mapping_ = shared_metrics_buffer.Map();
memset(metrics_mapping_.memory(), 0, sizeof(blink::OomInterventionMetrics));
- crash_memory_metrics_reporter_->SetSharedMemory(
- shared_metrics_buffer.Duplicate());
+ mojo::Remote<blink::mojom::CrashMemoryMetricsReporter>(
+ std::move(crash_memory_metrics_reporter_))
+ ->SetSharedMemory(shared_metrics_buffer.Duplicate());
}
CrashMemoryMetricsCollector::~CrashMemoryMetricsCollector() = default;
diff --git a/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.h b/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.h
index e68df1b025a..d8ae25aa51e 100644
--- a/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.h
+++ b/chromium/components/crash/content/browser/crash_memory_metrics_collector_android.h
@@ -7,7 +7,7 @@
#include "components/crash/content/browser/child_exit_observer_android.h"
#include "content/public/browser/content_browser_client.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/public/mojom/crash/crash_memory_metrics_reporter.mojom.h"
@@ -32,7 +32,8 @@ class CrashMemoryMetricsCollector : public base::SupportsUserData::Data {
const blink::OomInterventionMetrics* MemoryMetrics();
private:
- blink::mojom::CrashMemoryMetricsReporterPtr crash_memory_metrics_reporter_;
+ mojo::PendingRemote<blink::mojom::CrashMemoryMetricsReporter>
+ crash_memory_metrics_reporter_;
base::WritableSharedMemoryMapping metrics_mapping_;
DISALLOW_COPY_AND_ASSIGN(CrashMemoryMetricsCollector);
diff --git a/chromium/components/crash/content/browser/crash_metrics_reporter_android_unittest.cc b/chromium/components/crash/content/browser/crash_metrics_reporter_android_unittest.cc
index 97330caf702..086504db9d8 100644
--- a/chromium/components/crash/content/browser/crash_metrics_reporter_android_unittest.cc
+++ b/chromium/components/crash/content/browser/crash_metrics_reporter_android_unittest.cc
@@ -11,7 +11,7 @@
#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace crash_reporter {
@@ -45,8 +45,7 @@ class CrashMetricsReporterObserver : public CrashMetricsReporter::Observer {
class CrashMetricsReporterTest : public testing::Test {
public:
CrashMetricsReporterTest()
- : scoped_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : scoped_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
~CrashMetricsReporterTest() override {}
protected:
@@ -82,7 +81,7 @@ class CrashMetricsReporterTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_environment_;
+ base::test::TaskEnvironment scoped_environment_;
DISALLOW_COPY_AND_ASSIGN(CrashMetricsReporterTest);
};
diff --git a/chromium/components/crash/content/tools/generate_breakpad_symbols.py b/chromium/components/crash/content/tools/generate_breakpad_symbols.py
index 937548cc030..cdd374c33a3 100755
--- a/chromium/components/crash/content/tools/generate_breakpad_symbols.py
+++ b/chromium/components/crash/content/tools/generate_breakpad_symbols.py
@@ -243,13 +243,13 @@ def GetBinaryInfoFromHeaderInfo(header_info):
return BINARY_INFO(*info_split[1:])
-def CreateSymbolDir(options, output_dir):
- """Create the directory to store breakpad symbols in. On Android, we also
- create a symlink in case the hash in the binary is missing."""
+def CreateSymbolDir(options, output_dir, relative_hash_dir):
+ """Create the directory to store breakpad symbols in. On Android/Linux, we
+ also create a symlink in case the hash in the binary is missing."""
mkdir_p(output_dir)
- if options.platform == 'android':
+ if options.platform == 'android' or options.platform == "linux2":
try:
- os.symlink(output_dir, os.path.join(os.path.dirname(output_dir),
+ os.symlink(relative_hash_dir, os.path.join(os.path.dirname(output_dir),
'000000000000000000000000000000000'))
except:
pass
@@ -299,7 +299,7 @@ def GenerateSymbols(options, binaries):
with open(potential_symbol_file, 'rt') as f:
symbol_info = GetBinaryInfoFromHeaderInfo(f.readline())
if symbol_info == binary_info:
- CreateSymbolDir(options, output_dir)
+ CreateSymbolDir(options, output_dir, binary_info.hash)
shutil.copyfile(potential_symbol_file, output_path)
should_dump_syms = False
reason = "Found local symbol file."
@@ -316,7 +316,7 @@ def GenerateSymbols(options, binaries):
with print_lock:
print "Generating symbols for %s" % binary
- CreateSymbolDir(options, output_dir)
+ CreateSymbolDir(options, output_dir, binary_info.hash)
try:
with open(output_path, 'wb') as f:
subprocess.check_call([dump_syms, '-r', binary], stdout=f)
diff --git a/chromium/components/crash/core/browser/crashes_ui_util.cc b/chromium/components/crash/core/browser/crashes_ui_util.cc
index b714115c572..3f2993dd8f5 100644
--- a/chromium/components/crash/core/browser/crashes_ui_util.cc
+++ b/chromium/components/crash/core/browser/crashes_ui_util.cc
@@ -15,7 +15,7 @@
#include "components/strings/grit/components_strings.h"
#include "components/upload_list/upload_list.h"
-namespace crash {
+namespace crash_reporter {
const CrashesUILocalizedString kCrashesUILocalizedStrings[] = {
{"bugLinkText", IDS_CRASH_BUG_LINK_LABEL},
@@ -85,4 +85,4 @@ void UploadListToValue(UploadList* upload_list, base::ListValue* out_value) {
}
}
-} // namespace crash
+} // namespace crash_reporter
diff --git a/chromium/components/crash/core/browser/crashes_ui_util.h b/chromium/components/crash/core/browser/crashes_ui_util.h
index 65dcc5bbe08..953573a3917 100644
--- a/chromium/components/crash/core/browser/crashes_ui_util.h
+++ b/chromium/components/crash/core/browser/crashes_ui_util.h
@@ -13,7 +13,7 @@ class ListValue;
class UploadList;
-namespace crash {
+namespace crash_reporter {
// Mapping between a WebUI resource (identified by |name|) and a GRIT resource
// (identified by |resource_id|).
@@ -38,6 +38,6 @@ extern const char kCrashesUIRequestSingleCrashUpload[];
// Converts and appends the most recent uploads to |out_value|.
void UploadListToValue(UploadList* upload_list, base::ListValue* out_value);
-} // namespace crash
+} // namespace crash_reporter
#endif // COMPONENTS_CRASH_CORE_BROWSER_CRASHES_UI_UTIL_H_
diff --git a/chromium/components/cronet/android/BUILD.gn b/chromium/components/cronet/android/BUILD.gn
index 419b726f6c8..b139de839fd 100644
--- a/chromium/components/cronet/android/BUILD.gn
+++ b/chromium/components/cronet/android/BUILD.gn
@@ -318,6 +318,19 @@ android_library("cronet_impl_common_base_java") {
srcjar_deps = cronet_impl_common_java_srcjar_deps
}
+# cronet_impl_java_util_java.jar - Classes shared between Java Cronet implementations.
+android_library("cronet_impl_java_util_java") {
+ java_files = [
+ "java/src/org/chromium/net/impl/JavaUrlRequestUtils.java",
+ "java/src/org/chromium/net/impl/JavaUploadDataSinkBase.java",
+ ]
+
+ deps = [
+ ":cronet_api_java",
+ "//third_party/android_deps:com_android_support_support_annotations_java",
+ ]
+}
+
# cronet_impl_platform_base_java.jar - Java platform based implementation of the Cronet engine.
android_library("cronet_impl_platform_base_java") {
java_files = [
@@ -331,6 +344,7 @@ android_library("cronet_impl_platform_base_java") {
deps = [
":cronet_api_java",
":cronet_impl_common_base_java",
+ ":cronet_impl_java_util_java",
"//net/android:net_thread_stats_uid_java",
"//third_party/android_deps:com_android_support_support_annotations_java",
"//third_party/jsr-305:jsr_305_javalib",
@@ -340,10 +354,11 @@ android_library("cronet_impl_platform_base_java") {
# cronet_impl_fake_base_java.jar - Fake implementation of Cronet.
android_library("cronet_impl_fake_base_java") {
java_files = [
- "fake/java/org/chromium/net/test/FakeUrlResponse.java",
"fake/java/org/chromium/net/test/FakeCronetController.java",
"fake/java/org/chromium/net/test/FakeCronetEngine.java",
"fake/java/org/chromium/net/test/FakeCronetProvider.java",
+ "fake/java/org/chromium/net/test/FakeUrlRequest.java",
+ "fake/java/org/chromium/net/test/FakeUrlResponse.java",
"fake/java/org/chromium/net/test/ResponseMatcher.java",
"fake/java/org/chromium/net/test/UrlResponseMatcher.java",
]
@@ -351,29 +366,7 @@ android_library("cronet_impl_fake_base_java") {
deps = [
":cronet_api_java",
":cronet_impl_common_base_java",
- ]
-}
-
-# cronet_fake_javatests.jar - Java tests for the fake implementation of Cronet.
-android_library("cronet_fake_javatests") {
- testonly = true
- java_files = [
- "fake/javatests/org/chromium/net/test/FakeUrlResponseTest.java",
- "fake/javatests/org/chromium/net/test/FakeCronetProviderTest.java",
- "fake/javatests/org/chromium/net/test/FakeCronetEngineTest.java",
- "fake/javatests/org/chromium/net/test/FakeCronetControllerTest.java",
- "fake/javatests/org/chromium/net/test/UrlResponseMatcherTest.java",
- ]
-
- deps = [
- ":cronet_api_java",
- ":cronet_impl_common_base_java",
- ":cronet_impl_fake_base_java",
- ":cronet_impl_platform_base_java",
- "//base:base_java_test_support",
- "//third_party/android_sdk:android_test_base_java",
- "//third_party/android_support_test_runner:runner_java",
- "//third_party/junit",
+ ":cronet_impl_java_util_java",
]
}
@@ -505,6 +498,9 @@ action("cronet_combine_proguard_flags") {
script = "//components/cronet/tools/generate_proguard_file.py"
sources = [
"//base/android/proguard/chromium_code.flags",
+
+ # Massage the proguard rules to work with AppReduce.
+ "//components/cronet/android/cronet_appreduce_workaround.patch",
"//components/cronet/android/cronet_impl_native_proguard.cfg",
]
outputs = [
@@ -551,6 +547,14 @@ java_prebuilt("package_impl_native_java") {
]
}
+android_java_prebuilt("package_impl_util_java") {
+ jar_path = "$_package_dir/cronet_impl_util_java.jar"
+ deps = [
+ ":package_api_java",
+ ":repackage_util",
+ ]
+}
+
android_java_prebuilt("package_impl_platform_java") {
jar_path = "$_package_dir/cronet_impl_platform_java.jar"
deps = [
@@ -672,6 +676,12 @@ jar_src("jar_cronet_impl_fake_java_source") {
jar_path = "$_package_dir/cronet_impl_fake_java-src.jar"
}
+jar_src("jar_cronet_impl_util_java_source") {
+ src_search_dirs = [ "java/src" ]
+ source_deps = [ ":cronet_impl_java_util_java" ]
+ jar_path = "$_package_dir/cronet_impl_util_java-src.jar"
+}
+
# List of patterns of .class files to exclude from the jar.
_jar_excluded_patterns = [
# Excludes Android support libraries crbug.com/832770.
@@ -715,6 +725,13 @@ repackage_jars("repackage_fake") {
]
}
+repackage_jars("repackage_util") {
+ output = "$_package_dir/cronet_impl_util_java.jar"
+ deps = [
+ ":cronet_impl_java_util_java",
+ ]
+}
+
repackage_jars("repackage_native") {
output = "$_package_dir/cronet_impl_native_java.jar"
deps = cronet_impl_native_java_deps_to_package + [
@@ -726,8 +743,10 @@ repackage_jars("repackage_native") {
repackage_jars("repackage_common") {
output = "$_package_dir/cronet_impl_common_java.jar"
- deps = cronet_impl_common_java_deps_to_package +
- [ ":cronet_impl_common_base_java" ]
+ deps = cronet_impl_common_java_deps_to_package + [
+ ":cronet_impl_common_base_java",
+ ":cronet_impl_java_util_java",
+ ]
}
if (!is_component_build) {
@@ -875,7 +894,52 @@ if (!is_component_build) {
"test/smoketests/src/org/chromium/net/smoke/NativeCronetTestRule.java",
]
+ # cronet_common_javatests.jar - Cronet Java test common files.
+ android_library("cronet_common_javatests") {
+ testonly = true
+ java_files = [
+ "test/javatests/src/org/chromium/net/TestUrlRequestCallback.java",
+ "test/javatests/src/org/chromium/net/CronetTestRule.java",
+ ]
+ deps = [
+ ":cronet_api_java",
+ ":cronet_impl_all_java",
+ "//base:base_java",
+ "//third_party/android_sdk:android_test_base_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ ]
+ }
+
+ # cronet_fake_javatests.jar - Java tests for the fake implementation of Cronet.
+ android_library("cronet_fake_javatests") {
+ testonly = true
+ java_files = [
+ "fake/javatests/org/chromium/net/test/FakeUrlRequestTest.java",
+ "fake/javatests/org/chromium/net/test/FakeUrlResponseTest.java",
+ "fake/javatests/org/chromium/net/test/FakeCronetProviderTest.java",
+ "fake/javatests/org/chromium/net/test/FakeCronetEngineTest.java",
+ "fake/javatests/org/chromium/net/test/FakeCronetControllerTest.java",
+ "fake/javatests/org/chromium/net/test/UrlResponseMatcherTest.java",
+ ]
+
+ deps = [
+ ":cronet_api_java",
+ ":cronet_common_javatests",
+ ":cronet_impl_common_base_java",
+ ":cronet_impl_fake_base_java",
+ ":cronet_impl_platform_base_java",
+ "//base:base_java_test_support",
+ "//third_party/android_sdk:android_test_base_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
+ ]
+ }
+
cronet_javatests_deps_to_package = [
+ ":cronet_common_javatests",
+ ":cronet_fake_javatests",
":cronet_test_apk_java",
"//base:base_java",
"//base:base_java_test_support",
@@ -884,7 +948,6 @@ if (!is_component_build) {
"//net/android:net_java_test_support",
"//url:url_java",
"//third_party/junit",
- ":cronet_fake_javatests",
]
android_library("cronet_javatests") {
@@ -897,7 +960,6 @@ if (!is_component_build) {
"test/javatests/src/org/chromium/net/Criteria.java",
"test/javatests/src/org/chromium/net/CronetEngineBuilderTest.java",
"test/javatests/src/org/chromium/net/CronetStressTest.java",
- "test/javatests/src/org/chromium/net/CronetTestRule.java",
"test/javatests/src/org/chromium/net/CronetTestRuleTest.java",
"test/javatests/src/org/chromium/net/CronetUploadTest.java",
"test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java",
@@ -917,7 +979,6 @@ if (!is_component_build) {
"test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java",
"test/javatests/src/org/chromium/net/TestNetworkQualityThroughputListener.java",
"test/javatests/src/org/chromium/net/TestUploadDataProvider.java",
- "test/javatests/src/org/chromium/net/TestUrlRequestCallback.java",
"test/javatests/src/org/chromium/net/UploadDataProvidersTest.java",
"test/javatests/src/org/chromium/net/urlconnection/CronetBufferedOutputStreamTest.java",
"test/javatests/src/org/chromium/net/urlconnection/CronetChunkedOutputStreamTest.java",
@@ -988,7 +1049,7 @@ if (!is_component_build) {
"//net:test_support",
]
- enable_multidex = false
+ enable_multidex = true
if (!is_java_debug) {
proguard_enabled = true
@@ -1102,7 +1163,7 @@ if (!is_component_build) {
"//third_party/junit",
]
- enable_multidex = false
+ enable_multidex = true
if (!is_java_debug) {
proguard_enabled = true
proguard_configs = [
@@ -1293,6 +1354,7 @@ if (!is_component_build) {
"//chrome/VERSION",
"api_version.txt",
"cronet_impl_common_proguard.cfg",
+ "cronet_impl_fake_proguard.cfg",
"cronet_impl_platform_proguard.cfg",
]
outputs = [
diff --git a/chromium/components/cronet/ios/BUILD.gn b/chromium/components/cronet/ios/BUILD.gn
index 6dbccdec4f1..79db67c5e2b 100644
--- a/chromium/components/cronet/ios/BUILD.gn
+++ b/chromium/components/cronet/ios/BUILD.gn
@@ -48,7 +48,7 @@ _cronet_deps = [
"//components/prefs:prefs",
"//ios/net",
"//ios/net:network_protocol",
- "//ios/web/public:user_agent",
+ "//ios/web/common:user_agent",
"//ios/web/public/init:global_state",
"//ios/web/init:global_state",
"//net",
diff --git a/chromium/components/crx_file/BUILD.gn b/chromium/components/crx_file/BUILD.gn
index 57667dbba03..4e6eacb23ac 100644
--- a/chromium/components/crx_file/BUILD.gn
+++ b/chromium/components/crx_file/BUILD.gn
@@ -49,6 +49,7 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/crx_file/valid.crx2",
"//components/test/data/crx_file/valid_no_publisher.crx3",
"//components/test/data/crx_file/valid_publisher.crx3",
+ "//components/test/data/crx_file/valid_test_publisher.crx3",
]
outputs = [
"{{bundle_resources_dir}}/" +
diff --git a/chromium/components/crx_file/OWNERS b/chromium/components/crx_file/OWNERS
index 6fbc7dea785..9562f1b3e2a 100644
--- a/chromium/components/crx_file/OWNERS
+++ b/chromium/components/crx_file/OWNERS
@@ -2,3 +2,4 @@ file://extensions/OWNERS
waffles@chromium.org
sorin@chromium.org
+# COMPONENT: Platform>Extensions
diff --git a/chromium/components/crx_file/crx_verifier.cc b/chromium/components/crx_file/crx_verifier.cc
index dbc70b43653..1f523a7f6e6 100644
--- a/chromium/components/crx_file/crx_verifier.cc
+++ b/chromium/components/crx_file/crx_verifier.cc
@@ -29,21 +29,21 @@ namespace crx_file {
namespace {
-// The maximum size the Crx2 parser will tolerate for a public key.
-constexpr uint32_t kMaxPublicKeySize = 1 << 16;
-
-// The maximum size the Crx2 parser will tolerate for a signature.
-constexpr uint32_t kMaxSignatureSize = 1 << 16;
-
// The maximum size the Crx3 parser will tolerate for a header.
constexpr uint32_t kMaxHeaderSize = 1 << 18;
-// The SHA256 hash of the "ecdsa_2017_public" Crx3 key.
+// The SHA256 hash of the DER SPKI "ecdsa_2017_public" Crx3 key.
constexpr uint8_t kPublisherKeyHash[] = {
0x61, 0xf7, 0xf2, 0xa6, 0xbf, 0xcf, 0x74, 0xcd, 0x0b, 0xc1, 0xfe,
0x24, 0x97, 0xcc, 0x9b, 0x04, 0x25, 0x4c, 0x65, 0x8f, 0x79, 0xf2,
0x14, 0x53, 0x92, 0x86, 0x7e, 0xa8, 0x36, 0x63, 0x67, 0xcf};
+// The SHA256 hash of the DER SPKI "ecdsa_2017_public" Crx3 test key.
+constexpr uint8_t kPublisherTestKeyHash[] = {
+ 0x6c, 0x46, 0x41, 0x3b, 0x00, 0xd0, 0xfa, 0x0e, 0x72, 0xc8, 0xd2,
+ 0x5f, 0x64, 0xf3, 0xa6, 0x17, 0x03, 0x0d, 0xde, 0x21, 0x61, 0xbe,
+ 0xb7, 0x95, 0x91, 0x95, 0x83, 0x68, 0x12, 0xe9, 0x78, 0x1e};
+
using VerifierCollection =
std::vector<std::unique_ptr<crypto::SignatureVerifier>>;
using RepeatedProof = google::protobuf::RepeatedPtrField<AsymmetricKeyProof>;
@@ -98,7 +98,8 @@ VerifierResult VerifyCrx3(
const std::vector<std::vector<uint8_t>>& required_key_hashes,
std::string* public_key,
std::string* crx_id,
- bool require_publisher_key) {
+ bool require_publisher_key,
+ bool accept_publisher_test_key) {
// Parse [header-size] and [header].
const uint32_t header_size = ReadAndHashLittleEndianUInt32(file, hash);
if (header_size > kMaxHeaderSize)
@@ -130,10 +131,6 @@ VerifierResult VerifyCrx3(
// Create a set of all required key hashes.
std::set<std::vector<uint8_t>> required_key_set(required_key_hashes.begin(),
required_key_hashes.end());
- if (require_publisher_key) {
- required_key_set.emplace(std::begin(kPublisherKeyHash),
- std::end(kPublisherKeyHash));
- }
using ProofFetcher = const RepeatedProof& (CrxFileHeader::*)() const;
ProofFetcher rsa = &CrxFileHeader::sha256_with_rsa;
@@ -149,6 +146,15 @@ VerifierResult VerifyCrx3(
std::make_pair(rsa, crypto::SignatureVerifier::RSA_PKCS1_SHA256),
std::make_pair(ecdsa, crypto::SignatureVerifier::ECDSA_SHA256)};
+ std::vector<uint8_t> publisher_key(std::begin(kPublisherKeyHash),
+ std::end(kPublisherKeyHash));
+ base::Optional<std::vector<uint8_t>> publisher_test_key;
+ if (accept_publisher_test_key) {
+ publisher_test_key.emplace(std::begin(kPublisherTestKeyHash),
+ std::end(kPublisherTestKeyHash));
+ }
+ bool found_publisher_key = false;
+
// Initialize all verifiers and update them with
// [prefix][signed-header-size][signed-header].
// Clear any elements of required_key_set that are encountered, and watch for
@@ -162,6 +168,10 @@ VerifierResult VerifyCrx3(
std::vector<uint8_t> key_hash(crypto::kSHA256Length);
crypto::SHA256HashString(key, key_hash.data(), key_hash.size());
required_key_set.erase(key_hash);
+ DCHECK_EQ(accept_publisher_test_key, publisher_test_key.has_value());
+ found_publisher_key =
+ found_publisher_key || key_hash == publisher_key ||
+ (accept_publisher_test_key && key_hash == *publisher_test_key);
auto v = std::make_unique<crypto::SignatureVerifier>();
static_assert(sizeof(unsigned char) == sizeof(uint8_t),
"Unsupported char size.");
@@ -178,6 +188,9 @@ VerifierResult VerifyCrx3(
if (public_key_bytes.empty() || !required_key_set.empty())
return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;
+ if (require_publisher_key && !found_publisher_key)
+ return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;
+
// Update and finalize the verifiers with [archive].
if (!ReadHashAndVerifyArchive(file, hash, verifiers))
return VerifierResult::ERROR_SIGNATURE_VERIFICATION_FAILED;
@@ -187,53 +200,6 @@ VerifierResult VerifyCrx3(
return VerifierResult::OK_FULL;
}
-VerifierResult VerifyCrx2(
- base::File* file,
- crypto::SecureHash* hash,
- const std::vector<std::vector<uint8_t>>& required_key_hashes,
- std::string* public_key,
- std::string* crx_id) {
- const uint32_t key_size = ReadAndHashLittleEndianUInt32(file, hash);
- if (key_size > kMaxPublicKeySize)
- return VerifierResult::ERROR_HEADER_INVALID;
- const uint32_t sig_size = ReadAndHashLittleEndianUInt32(file, hash);
- if (sig_size > kMaxSignatureSize)
- return VerifierResult::ERROR_HEADER_INVALID;
- std::vector<uint8_t> key(key_size);
- if (ReadAndHashBuffer(key.data(), key_size, file, hash) !=
- static_cast<int>(key_size))
- return VerifierResult::ERROR_HEADER_INVALID;
- for (const auto& expected_hash : required_key_hashes) {
- // In practice we expect zero or one key_hashes_ for Crx2 files.
- std::vector<uint8_t> hash(crypto::kSHA256Length);
- std::unique_ptr<crypto::SecureHash> sha256 =
- crypto::SecureHash::Create(crypto::SecureHash::SHA256);
- sha256->Update(key.data(), key.size());
- sha256->Finish(hash.data(), hash.size());
- if (hash != expected_hash)
- return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;
- }
-
- std::vector<uint8_t> sig(sig_size);
- if (ReadAndHashBuffer(sig.data(), sig_size, file, hash) !=
- static_cast<int>(sig_size))
- return VerifierResult::ERROR_HEADER_INVALID;
- std::vector<std::unique_ptr<crypto::SignatureVerifier>> verifiers;
- verifiers.push_back(std::make_unique<crypto::SignatureVerifier>());
- if (!verifiers[0]->VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, sig,
- key)) {
- return VerifierResult::ERROR_SIGNATURE_INITIALIZATION_FAILED;
- }
-
- if (!ReadHashAndVerifyArchive(file, hash, verifiers))
- return VerifierResult::ERROR_SIGNATURE_VERIFICATION_FAILED;
-
- const std::string public_key_bytes(key.begin(), key.end());
- base::Base64Encode(public_key_bytes, public_key);
- *crx_id = id_util::GenerateId(public_key_bytes);
- return VerifierResult::OK_FULL;
-}
-
} // namespace
VerifierResult Verify(
@@ -268,20 +234,17 @@ VerifierResult Verify(
const uint32_t version =
ReadAndHashLittleEndianUInt32(&file, file_hash.get());
VerifierResult result;
- if (version == 2)
- LOG(WARNING) << "File '" << crx_path
- << "' is in CRX2 format, which is deprecated and will not be "
- "supported in M78+";
- if (format == VerifierFormat::CRX2_OR_CRX3 &&
- (version == 2 || (diff && version == 0)))
- result = VerifyCrx2(&file, file_hash.get(), required_key_hashes,
- &public_key_local, &crx_id_local);
- else if (version == 3)
- result = VerifyCrx3(&file, file_hash.get(), required_key_hashes,
- &public_key_local, &crx_id_local,
- format == VerifierFormat::CRX3_WITH_PUBLISHER_PROOF);
- else
+ if (version == 3) {
+ bool require_publisher_key =
+ format == VerifierFormat::CRX3_WITH_PUBLISHER_PROOF ||
+ format == VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF;
+ result =
+ VerifyCrx3(&file, file_hash.get(), required_key_hashes,
+ &public_key_local, &crx_id_local, require_publisher_key,
+ format == VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF);
+ } else {
result = VerifierResult::ERROR_HEADER_INVALID;
+ }
if (result != VerifierResult::OK_FULL)
return result;
diff --git a/chromium/components/crx_file/crx_verifier.h b/chromium/components/crx_file/crx_verifier.h
index 35cf1956a24..a2064428026 100644
--- a/chromium/components/crx_file/crx_verifier.h
+++ b/chromium/components/crx_file/crx_verifier.h
@@ -16,9 +16,11 @@ class FilePath;
namespace crx_file {
enum class VerifierFormat {
- CRX2_OR_CRX3, // Accept Crx2 or Crx3.
- CRX3, // Accept only Crx3.
- CRX3_WITH_PUBLISHER_PROOF, // Accept only Crx3 with a publisher proof.
+ CRX3, // Accept only Crx3.
+ CRX3_WITH_TEST_PUBLISHER_PROOF, // Accept only Crx3 with a test or production
+ // publisher proof.
+ CRX3_WITH_PUBLISHER_PROOF, // Accept only Crx3 with a production
+ // publisher proof.
};
enum class VerifierResult {
diff --git a/chromium/components/crx_file/crx_verifier_unittest.cc b/chromium/components/crx_file/crx_verifier_unittest.cc
index 54dd44f0cea..70bcd310476 100644
--- a/chromium/components/crx_file/crx_verifier_unittest.cc
+++ b/chromium/components/crx_file/crx_verifier_unittest.cc
@@ -32,34 +32,32 @@ constexpr char kOjjKey[] =
"mCsHBHFWbqtGhSN4YCAw3DYQzwdTcIVaIA8f2Uo4AZ4INKkrEPRL8o9mZDYtO2YHIQg8pMSRMa"
"6AawBNYi9tZScnmgl5L1qE6z5oIwIDAQAB";
+constexpr char kJlnHash[] = "jlnmailbicnpnbggmhfebbomaddckncf";
+constexpr char kJlnKey[] =
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtYd4M8wBjlPsc/wxS1/uXKMD6GtI7/"
+ "0GLxRe6UXTYtDk91u/"
+ "FdJRK9jHws+"
+ "FO6Yi3XcJGtMvuojiB1j4bdiYBfvRgfTD4b7krWtWM2udKPBtHI9ikAT5aom5Bda8rCPNyaqXC"
+ "6Ax+KTgQpeeJglYu7TTd/"
+ "AePyvlRHtCKNkcvRQLY0b6hccALqoTzyTueDX12c8Htg76syEPbz7hSIPPfq6KEGvuVSxWAejy"
+ "/y6EhwAdXRLpegul9KmL94OY1G6dpycUKwyKeXOcB6Qj5iKNcOqJAaSLxoOZby4G3cI1BcQpp/"
+ "3vYccJ4qouDMfaanLe8CvFlLp4VOn833aJ8PYpLQIDAQAB";
+
} // namespace
namespace crx_file {
using CrxVerifierTest = testing::Test;
-TEST_F(CrxVerifierTest, ValidFullCrx2) {
- const std::vector<std::vector<uint8_t>> keys;
- const std::vector<uint8_t> hash;
- std::string public_key;
- std::string crx_id;
-
- EXPECT_EQ(VerifierResult::OK_FULL,
- Verify(TestFile("valid.crx2"), VerifierFormat::CRX2_OR_CRX3, keys,
- hash, &public_key, &crx_id));
- EXPECT_EQ(std::string(kOjjHash), crx_id);
- EXPECT_EQ(std::string(kOjjKey), public_key);
-}
-
TEST_F(CrxVerifierTest, ValidFullCrx3) {
const std::vector<std::vector<uint8_t>> keys;
const std::vector<uint8_t> hash;
std::string public_key = "UNSET";
std::string crx_id = "UNSET";
- EXPECT_EQ(VerifierResult::OK_FULL, Verify(TestFile("valid_no_publisher.crx3"),
- VerifierFormat::CRX2_OR_CRX3, keys,
- hash, &public_key, &crx_id));
+ EXPECT_EQ(VerifierResult::OK_FULL,
+ Verify(TestFile("valid_no_publisher.crx3"), VerifierFormat::CRX3,
+ keys, hash, &public_key, &crx_id));
EXPECT_EQ(std::string(kOjjHash), crx_id);
EXPECT_EQ(std::string(kOjjKey), public_key);
@@ -94,9 +92,9 @@ TEST_F(CrxVerifierTest, VerifiesFileHash) {
std::string public_key = "UNSET";
std::string crx_id = "UNSET";
- EXPECT_EQ(VerifierResult::OK_FULL, Verify(TestFile("valid_no_publisher.crx3"),
- VerifierFormat::CRX2_OR_CRX3, keys,
- hash, &public_key, &crx_id));
+ EXPECT_EQ(VerifierResult::OK_FULL,
+ Verify(TestFile("valid_no_publisher.crx3"), VerifierFormat::CRX3,
+ keys, hash, &public_key, &crx_id));
EXPECT_EQ(std::string(kOjjHash), crx_id);
EXPECT_EQ(std::string(kOjjKey), public_key);
@@ -131,10 +129,9 @@ TEST_F(CrxVerifierTest, ChecksRequiredKeyHashes) {
const std::vector<std::vector<uint8_t>> good_keys = {good_key};
std::string public_key = "UNSET";
std::string crx_id = "UNSET";
- EXPECT_EQ(
- VerifierResult::OK_FULL,
- Verify(TestFile("valid_no_publisher.crx3"), VerifierFormat::CRX2_OR_CRX3,
- good_keys, hash, &public_key, &crx_id));
+ EXPECT_EQ(VerifierResult::OK_FULL,
+ Verify(TestFile("valid_no_publisher.crx3"), VerifierFormat::CRX3,
+ good_keys, hash, &public_key, &crx_id));
EXPECT_EQ(std::string(kOjjHash), crx_id);
EXPECT_EQ(std::string(kOjjKey), public_key);
@@ -165,6 +162,15 @@ TEST_F(CrxVerifierTest, ChecksPinnedKey) {
public_key = "UNSET";
crx_id = "UNSET";
EXPECT_EQ(VerifierResult::ERROR_REQUIRED_PROOF_MISSING,
+ Verify(TestFile("valid_test_publisher.crx3"),
+ VerifierFormat::CRX3_WITH_PUBLISHER_PROOF, keys, hash,
+ &public_key, &crx_id));
+ EXPECT_EQ("UNSET", crx_id);
+ EXPECT_EQ("UNSET", public_key);
+
+ public_key = "UNSET";
+ crx_id = "UNSET";
+ EXPECT_EQ(VerifierResult::ERROR_REQUIRED_PROOF_MISSING,
Verify(TestFile("valid_no_publisher.crx3"),
VerifierFormat::CRX3_WITH_PUBLISHER_PROOF, keys, hash,
&public_key, &crx_id));
@@ -172,6 +178,37 @@ TEST_F(CrxVerifierTest, ChecksPinnedKey) {
EXPECT_EQ("UNSET", public_key);
}
+TEST_F(CrxVerifierTest, ChecksPinnedKeyAcceptsTest) {
+ const std::vector<uint8_t> hash;
+ const std::vector<std::vector<uint8_t>> keys;
+ std::string public_key = "UNSET";
+ std::string crx_id = "UNSET";
+ EXPECT_EQ(VerifierResult::OK_FULL,
+ Verify(TestFile("valid_publisher.crx3"),
+ VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF, keys, hash,
+ &public_key, &crx_id));
+ EXPECT_EQ(std::string(kOjjHash), crx_id);
+ EXPECT_EQ(std::string(kOjjKey), public_key);
+
+ public_key = "UNSET";
+ crx_id = "UNSET";
+ EXPECT_EQ(VerifierResult::OK_FULL,
+ Verify(TestFile("valid_test_publisher.crx3"),
+ VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF, keys, hash,
+ &public_key, &crx_id));
+ EXPECT_EQ(std::string(kJlnHash), crx_id);
+ EXPECT_EQ(std::string(kJlnKey), public_key);
+
+ public_key = "UNSET";
+ crx_id = "UNSET";
+ EXPECT_EQ(VerifierResult::ERROR_REQUIRED_PROOF_MISSING,
+ Verify(TestFile("valid_no_publisher.crx3"),
+ VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF, keys, hash,
+ &public_key, &crx_id));
+ EXPECT_EQ("UNSET", crx_id);
+ EXPECT_EQ("UNSET", public_key);
+}
+
TEST_F(CrxVerifierTest, NullptrSafe) {
const std::vector<uint8_t> hash;
const std::vector<std::vector<uint8_t>> keys;
@@ -187,8 +224,8 @@ TEST_F(CrxVerifierTest, RequiresDeveloperKey) {
std::string public_key = "UNSET";
std::string crx_id = "UNSET";
EXPECT_EQ(VerifierResult::ERROR_REQUIRED_PROOF_MISSING,
- Verify(TestFile("unsigned.crx3"), VerifierFormat::CRX2_OR_CRX3,
- keys, hash, &public_key, &crx_id));
+ Verify(TestFile("unsigned.crx3"), VerifierFormat::CRX3, keys, hash,
+ &public_key, &crx_id));
EXPECT_EQ("UNSET", crx_id);
EXPECT_EQ("UNSET", public_key);
}
diff --git a/chromium/components/data_reduction_proxy/DEPS b/chromium/components/data_reduction_proxy/DEPS
index 3f3525be8c4..a5bfa08c1e4 100644
--- a/chromium/components/data_reduction_proxy/DEPS
+++ b/chromium/components/data_reduction_proxy/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+components/data_use_measurement/core",
"+components/pref_registry",
"+components/prefs",
+ "+components/previews/core",
"+components/variations",
"+crypto",
"+google_apis",
diff --git a/chromium/components/data_reduction_proxy/OWNERS b/chromium/components/data_reduction_proxy/OWNERS
index 4207f58fe13..337e70f6570 100644
--- a/chromium/components/data_reduction_proxy/OWNERS
+++ b/chromium/components/data_reduction_proxy/OWNERS
@@ -1,6 +1,7 @@
# Primary
tbansal@chromium.org
dougarnett@chromium.org
+mcrouse@chromium.org
rajendrant@chromium.org
robertogden@chromium.org
ryansturm@chromium.org
@@ -58,4 +59,3 @@ per-file *_messages*.h=file://ipc/SECURITY_OWNERS
# :=?II777777777I7III+~, #
# #
################################################################################
-
diff --git a/chromium/components/data_reduction_proxy/content/DEPS b/chromium/components/data_reduction_proxy/content/DEPS
index 9015435dea6..70cf0ee2f3c 100644
--- a/chromium/components/data_reduction_proxy/content/DEPS
+++ b/chromium/components/data_reduction_proxy/content/DEPS
@@ -7,6 +7,7 @@ include_rules = [
"+content/public/browser",
"+content/public/common",
"+net/base",
+ "+third_party/blink/public/common/loader/url_loader_throttle.h",
]
specific_include_rules = {
diff --git a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
index a2fa7d2731b..7edc1c6761b 100644
--- a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
+++ b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.cc
@@ -241,14 +241,12 @@ std::string AddBatchInfoAndSerializeRequest(
DataReductionProxyPingbackClientImpl::DataReductionProxyPingbackClientImpl(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const std::string& channel)
: url_loader_factory_(std::move(url_loader_factory)),
pingback_url_(util::AddApiKeyToUrl(params::GetPingbackURL())),
pingback_reporting_fraction_(0.0),
current_loader_message_count_(0u),
current_loader_crash_count_(0u),
- ui_task_runner_(std::move(ui_task_runner)),
channel_(channel)
#if defined(OS_ANDROID)
,
@@ -359,7 +357,7 @@ void DataReductionProxyPingbackClientImpl::AddRequestToCrashMap(
// being analyzed. 5 seconds should be enough time for breakpad to process the
// dump, while being short enough that the user will probably not shutdown the
// app.
- ui_task_runner_->PostDelayedTask(
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&DataReductionProxyPingbackClientImpl::RemoveFromCrashMap,
weak_factory_.GetWeakPtr(), timing.host_id),
@@ -443,7 +441,7 @@ void DataReductionProxyPingbackClientImpl::CreateLoaderForDataAndStart() {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = pingback_url_;
resource_request->load_flags = net::LOAD_BYPASS_PROXY;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
// Attach variations headers.
variations::AppendVariationsHeader(
diff --git a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.h b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.h
index 99677cd203b..f9df4bb5b8f 100644
--- a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.h
+++ b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.h
@@ -49,7 +49,6 @@ class DataReductionProxyPingbackClientImpl
public:
DataReductionProxyPingbackClientImpl(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const std::string& channel);
~DataReductionProxyPingbackClientImpl() override;
@@ -122,8 +121,6 @@ class DataReductionProxyPingbackClientImpl
// The number of pageload crash messages in the current loader.
size_t current_loader_crash_count_;
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
-
// The release channel of this Chrome instance.
std::string channel_;
diff --git a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
index fc4188f060a..fb893e2583a 100644
--- a/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
+++ b/chromium/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
@@ -18,7 +18,7 @@
#include "base/system/sys_info.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/content/browser/data_reduction_proxy_page_load_timing.h"
@@ -68,11 +68,8 @@ class TestDataReductionProxyPingbackClientImpl
: public DataReductionProxyPingbackClientImpl {
public:
TestDataReductionProxyPingbackClientImpl(
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner)
- : DataReductionProxyPingbackClientImpl(url_loader_factory,
- std::move(thread_task_runner),
- kChannel),
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : DataReductionProxyPingbackClientImpl(url_loader_factory, kChannel),
should_override_random_(false),
override_value_(0.0f),
current_time_(base::Time::Now()) {}
@@ -109,10 +106,9 @@ class TestDataReductionProxyPingbackClientImpl
class DataReductionProxyPingbackClientImplTest : public testing::Test {
public:
DataReductionProxyPingbackClientImplTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC) {
- }
+ : task_environment_(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC) {}
TestDataReductionProxyPingbackClientImpl* pingback_client() const {
return pingback_client_.get();
@@ -135,8 +131,7 @@ class DataReductionProxyPingbackClientImplTest : public testing::Test {
&test_url_loader_factory_);
pingback_client_ =
std::make_unique<TestDataReductionProxyPingbackClientImpl>(
- test_shared_loader_factory_,
- scoped_task_environment_.GetMainThreadTaskRunner());
+ test_shared_loader_factory_);
page_id_ = 0u;
}
@@ -237,7 +232,7 @@ class DataReductionProxyPingbackClientImplTest : public testing::Test {
int num_network_requests() { return num_network_requests_; }
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
private:
network::TestURLLoaderFactory test_url_loader_factory_;
@@ -764,7 +759,7 @@ TEST_F(DataReductionProxyPingbackClientImplTest,
false /* black_listed */);
// Don't report the crash dump details.
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
diff --git a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
index 77043ee492f..0704791c478 100644
--- a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
+++ b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
@@ -13,6 +13,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/data_reduction_proxy/core/common/uma_util.h"
#include "net/base/load_flags.h"
+#include "services/network/public/cpp/resource_response.h"
namespace net {
class HttpRequestHeaders;
diff --git a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
index fedf8213544..3eef694a274 100644
--- a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
+++ b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
@@ -10,8 +10,8 @@
#include "base/sequence_checker.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
-#include "content/public/common/url_loader_throttle.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
namespace data_reduction_proxy {
@@ -25,7 +25,7 @@ struct DataReductionProxyTypeInfo;
// * Restarting the URL loader in order to use a different proxy.
// * Marking data reduction proxies to be bypassed for future requests.
class DataReductionProxyURLLoaderThrottle
- : public content::URLLoaderThrottle,
+ : public blink::URLLoaderThrottle,
public DataReductionProxyThrottleConfigCheckedObserver {
public:
// |manager| is shared between all the DRP Throttles.
@@ -34,7 +34,7 @@ class DataReductionProxyURLLoaderThrottle
DataReductionProxyThrottleManager* manager);
~DataReductionProxyURLLoaderThrottle() override;
- // content::URLLoaderThrottle:
+ // blink::URLLoaderThrottle:
void DetachFromCurrentSequence() override;
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override;
diff --git a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc
index 9c376447da9..a5a8900e517 100644
--- a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc
+++ b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc
@@ -6,9 +6,9 @@
#include "base/run_loop.h"
#include "base/task/post_task.h"
-#include "base/task/thread_pool/thread_pool.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
@@ -18,6 +18,7 @@
#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
+#include "services/network/public/cpp/resource_response.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_reduction_proxy {
@@ -81,7 +82,7 @@ class MockMojoDataReductionProxy : public mojom::DataReductionProxy {
DISALLOW_COPY_AND_ASSIGN(MockMojoDataReductionProxy);
};
-class MockDelegate : public content::URLLoaderThrottle::Delegate {
+class MockDelegate : public blink::URLLoaderThrottle::Delegate {
public:
MockDelegate() = default;
@@ -139,7 +140,7 @@ class DataReductionProxyURLLoaderThrottleTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockMojoDataReductionProxy mock_mojo_data_reduction_proxy_;
};
@@ -156,8 +157,7 @@ TEST_F(DataReductionProxyURLLoaderThrottleTest,
(net::HttpRequestHeaders()), manager.get());
throttle->DetachFromCurrentSequence();
- auto task_runner =
- base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits());
+ auto task_runner = base::CreateSequencedTaskRunner({base::ThreadPool()});
task_runner->DeleteSoon(FROM_HERE, throttle.release());
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/BUILD.gn b/chromium/components/data_reduction_proxy/core/browser/BUILD.gn
index c00b6b408ec..36182921c65 100644
--- a/chromium/components/data_reduction_proxy/core/browser/BUILD.gn
+++ b/chromium/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -17,8 +17,6 @@ browser_sources = [
"data_reduction_proxy_configurator.h",
"data_reduction_proxy_data.cc",
"data_reduction_proxy_data.h",
- "data_reduction_proxy_io_data.cc",
- "data_reduction_proxy_io_data.h",
"data_reduction_proxy_metrics.h",
"data_reduction_proxy_mutable_config_values.cc",
"data_reduction_proxy_mutable_config_values.h",
@@ -29,7 +27,6 @@ browser_sources = [
"data_reduction_proxy_request_options.h",
"data_reduction_proxy_service.cc",
"data_reduction_proxy_service.h",
- "data_reduction_proxy_service_observer.h",
"data_reduction_proxy_settings.cc",
"data_reduction_proxy_settings.h",
"data_reduction_proxy_util.cc",
@@ -60,6 +57,7 @@ if (is_android) {
"//components/data_use_measurement/core:ascriber",
"//components/pref_registry",
"//components/prefs",
+ "//components/previews/core:core",
"//components/variations",
"//components/variations/net",
"//content/public/browser",
@@ -95,6 +93,7 @@ static_library("browser") {
"//components/data_use_measurement/core:ascriber",
"//components/pref_registry",
"//components/prefs",
+ "//components/previews/core:core",
"//components/variations",
"//components/variations/net",
"//content/public/browser",
@@ -137,7 +136,6 @@ static_library("test_support") {
"//components/data_reduction_proxy/core/common:test_support",
"//components/prefs:test_support",
"//components/previews/core:core",
- "//components/previews/core:test_support",
"//net",
"//net:test_support",
"//services/network:test_support",
@@ -174,10 +172,10 @@ source_set("unit_tests") {
"data_reduction_proxy_config_unittest.cc",
"data_reduction_proxy_configurator_unittest.cc",
"data_reduction_proxy_data_unittest.cc",
- "data_reduction_proxy_io_data_unittest.cc",
"data_reduction_proxy_mutable_config_values_unittest.cc",
"data_reduction_proxy_prefs_unittest.cc",
"data_reduction_proxy_request_options_unittest.cc",
+ "data_reduction_proxy_service_unittest.cc",
"data_reduction_proxy_settings_unittest.cc",
"data_reduction_proxy_util_unittest.cc",
"data_usage_store_unittest.cc",
@@ -198,7 +196,6 @@ source_set("unit_tests") {
"//components/data_use_measurement/core:ascriber",
"//components/prefs:test_support",
"//components/previews/core",
- "//components/previews/core:test_support",
"//components/variations",
"//content/public/browser",
"//content/test:test_support",
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
index 6c9f068ec64..a7e97895379 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -87,125 +87,6 @@ void AddInt64ToListPref(size_t index,
std::make_unique<base::Value>(base::NumberToString(value)));
}
-// DailyContentLengthUpdate maintains a data saving pref. The pref is a list
-// of |kNumDaysInHistory| elements of daily total content lengths for the past
-// |kNumDaysInHistory| days.
-void RecordDailyContentLengthHistograms(
- int64_t original_length,
- int64_t received_length,
- int64_t original_length_with_data_reduction_enabled,
- int64_t received_length_with_data_reduction_enabled,
- int64_t original_length_via_data_reduction_proxy,
- int64_t received_length_via_data_reduction_proxy,
- int64_t https_length_with_data_reduction_enabled,
- int64_t short_bypass_length_with_data_reduction_enabled,
- int64_t long_bypass_length_with_data_reduction_enabled,
- int64_t unknown_length_with_data_reduction_enabled) {
- // Report daily UMA only for days having received content.
- if (original_length <= 0 || received_length <= 0)
- return;
-
- // Record metrics in KB.
- UMA_HISTOGRAM_COUNTS_1M("Net.DailyOriginalContentLength",
- original_length >> 10);
- UMA_HISTOGRAM_COUNTS_1M("Net.DailyContentLength", received_length >> 10);
-
- int percent = 0;
- // UMA percentage cannot be negative.
- if (original_length > received_length) {
- percent = (100 * (original_length - received_length)) / original_length;
- }
- UMA_HISTOGRAM_PERCENTAGE("Net.DailyContentSavingPercent", percent);
-
- if (original_length_with_data_reduction_enabled <= 0 ||
- received_length_with_data_reduction_enabled <= 0) {
- return;
- }
-
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.DailyOriginalContentLength_DataReductionProxyEnabled",
- original_length_with_data_reduction_enabled >> 10);
- UMA_HISTOGRAM_COUNTS_1M("Net.DailyContentLength_DataReductionProxyEnabled",
- received_length_with_data_reduction_enabled >> 10);
-
- int percent_data_reduction_proxy_enabled = 0;
- // UMA percentage cannot be negative.
- if (original_length_with_data_reduction_enabled >
- received_length_with_data_reduction_enabled) {
- percent_data_reduction_proxy_enabled =
- 100 * (original_length_with_data_reduction_enabled -
- received_length_with_data_reduction_enabled) /
- original_length_with_data_reduction_enabled;
- }
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentSavingPercent_DataReductionProxyEnabled",
- percent_data_reduction_proxy_enabled);
-
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentPercent_DataReductionProxyEnabled",
- (100 * received_length_with_data_reduction_enabled) / received_length);
-
- DCHECK_GE(https_length_with_data_reduction_enabled, 0);
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.DailyContentLength_DataReductionProxyEnabled_Https",
- https_length_with_data_reduction_enabled >> 10);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentPercent_DataReductionProxyEnabled_Https",
- (100 * https_length_with_data_reduction_enabled) / received_length);
-
- DCHECK_GE(short_bypass_length_with_data_reduction_enabled, 0);
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.DailyContentLength_DataReductionProxyEnabled_ShortBypass",
- short_bypass_length_with_data_reduction_enabled >> 10);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentPercent_DataReductionProxyEnabled_ShortBypass",
- ((100 * short_bypass_length_with_data_reduction_enabled) /
- received_length));
-
- DCHECK_GE(long_bypass_length_with_data_reduction_enabled, 0);
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.DailyContentLength_DataReductionProxyEnabled_LongBypass",
- long_bypass_length_with_data_reduction_enabled >> 10);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentPercent_DataReductionProxyEnabled_LongBypass",
- ((100 * long_bypass_length_with_data_reduction_enabled) /
- received_length));
-
- DCHECK_GE(unknown_length_with_data_reduction_enabled, 0);
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.DailyContentLength_DataReductionProxyEnabled_UnknownBypass",
- unknown_length_with_data_reduction_enabled >> 10);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentPercent_DataReductionProxyEnabled_Unknown",
- ((100 * unknown_length_with_data_reduction_enabled) /
- received_length));
-
- DCHECK_GE(original_length_via_data_reduction_proxy, 0);
- UMA_HISTOGRAM_COUNTS_1M(
- "Net.DailyOriginalContentLength_ViaDataReductionProxy",
- original_length_via_data_reduction_proxy >> 10);
- DCHECK_GE(received_length_via_data_reduction_proxy, 0);
- UMA_HISTOGRAM_COUNTS_1M("Net.DailyContentLength_ViaDataReductionProxy",
- received_length_via_data_reduction_proxy >> 10);
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentPercent_ViaDataReductionProxy",
- (100 * received_length_via_data_reduction_proxy) / received_length);
-
- if (original_length_via_data_reduction_proxy <= 0)
- return;
- int percent_savings_via_data_reduction_proxy = 0;
- if (original_length_via_data_reduction_proxy >
- received_length_via_data_reduction_proxy) {
- percent_savings_via_data_reduction_proxy =
- 100 * (original_length_via_data_reduction_proxy -
- received_length_via_data_reduction_proxy) /
- original_length_via_data_reduction_proxy;
- }
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentSavingPercent_ViaDataReductionProxy",
- percent_savings_via_data_reduction_proxy);
-}
-
void RecordSavingsClearedMetric(DataReductionProxySavingsClearedReason reason) {
DCHECK_GT(DataReductionProxySavingsClearedReason::REASON_COUNT, reason);
UMA_HISTOGRAM_ENUMERATION(
@@ -473,46 +354,9 @@ void DataReductionProxyCompressionStats::Init() {
InitInt64Pref(prefs::kHttpReceivedContentLength);
InitInt64Pref(prefs::kHttpOriginalContentLength);
- InitInt64Pref(prefs::kDailyHttpOriginalContentLengthApplication);
- InitInt64Pref(prefs::kDailyHttpOriginalContentLengthVideo);
- InitInt64Pref(prefs::kDailyHttpOriginalContentLengthUnknown);
- InitInt64Pref(prefs::kDailyHttpReceivedContentLengthApplication);
- InitInt64Pref(prefs::kDailyHttpReceivedContentLengthVideo);
- InitInt64Pref(prefs::kDailyHttpReceivedContentLengthUnknown);
-
- InitInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyApplication);
- InitInt64Pref(prefs::kDailyOriginalContentLengthViaDataReductionProxyVideo);
- InitInt64Pref(prefs::kDailyOriginalContentLengthViaDataReductionProxyUnknown);
- InitInt64Pref(prefs::kDailyContentLengthViaDataReductionProxyApplication);
- InitInt64Pref(prefs::kDailyContentLengthViaDataReductionProxyVideo);
- InitInt64Pref(prefs::kDailyContentLengthViaDataReductionProxyUnknown);
-
- InitInt64Pref(
- prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication);
- InitInt64Pref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo);
- InitInt64Pref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown);
- InitInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledApplication);
- InitInt64Pref(prefs::kDailyContentLengthWithDataReductionProxyEnabledVideo);
- InitInt64Pref(prefs::kDailyContentLengthWithDataReductionProxyEnabledUnknown);
-
// Init all list prefs.
- InitListPref(prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled);
- InitListPref(
- prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
- InitListPref(
- prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
- InitListPref(prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled);
- InitListPref(prefs::kDailyContentLengthViaDataReductionProxy);
- InitListPref(prefs::kDailyContentLengthWithDataReductionProxyEnabled);
InitListPref(prefs::kDailyHttpOriginalContentLength);
InitListPref(prefs::kDailyHttpReceivedContentLength);
- InitListPref(prefs::kDailyOriginalContentLengthViaDataReductionProxy);
- InitListPref(prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
}
void DataReductionProxyCompressionStats::RecordDataUseWithMimeType(
@@ -757,57 +601,8 @@ void DataReductionProxyCompressionStats::ClearDataSavingStatistics(
pref_service_->ClearPref(prefs::kHttpReceivedContentLength);
pref_service_->ClearPref(prefs::kHttpOriginalContentLength);
- pref_service_->ClearPref(prefs::kDailyHttpOriginalContentLengthApplication);
- pref_service_->ClearPref(prefs::kDailyHttpOriginalContentLengthVideo);
- pref_service_->ClearPref(prefs::kDailyHttpOriginalContentLengthUnknown);
- pref_service_->ClearPref(prefs::kDailyHttpReceivedContentLengthApplication);
- pref_service_->ClearPref(prefs::kDailyHttpReceivedContentLengthVideo);
- pref_service_->ClearPref(prefs::kDailyHttpReceivedContentLengthUnknown);
-
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyApplication);
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyVideo);
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyUnknown);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthViaDataReductionProxyApplication);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthViaDataReductionProxyVideo);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthViaDataReductionProxyUnknown);
-
- pref_service_->ClearPref(
- prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication);
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo);
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledApplication);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledVideo);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledUnknown);
-
- pref_service_->ClearPref(
- prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled);
- pref_service_->ClearPref(prefs::kDailyContentLengthViaDataReductionProxy);
- pref_service_->ClearPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabled);
pref_service_->ClearPref(prefs::kDailyHttpOriginalContentLength);
pref_service_->ClearPref(prefs::kDailyHttpReceivedContentLength);
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxy);
- pref_service_->ClearPref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
for (auto iter = list_pref_map_.begin(); iter != list_pref_map_.end();
++iter) {
@@ -866,27 +661,6 @@ void DataReductionProxyCompressionStats::RecordRequestSizePrefs(
DailyDataSavingUpdate total(
this, data_reduction_proxy::prefs::kDailyHttpOriginalContentLength,
data_reduction_proxy::prefs::kDailyHttpReceivedContentLength);
- DailyDataSavingUpdate proxy_enabled(
- this, data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabled,
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabled);
- DailyDataSavingUpdate via_proxy(
- this, data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxy,
- data_reduction_proxy::prefs::kDailyContentLengthViaDataReductionProxy);
- DailyContentLengthUpdate https(
- this, data_reduction_proxy::prefs::
- kDailyContentLengthHttpsWithDataReductionProxyEnabled);
- DailyContentLengthUpdate short_bypass(
- this, data_reduction_proxy::prefs::
- kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
- DailyContentLengthUpdate long_bypass(
- this, data_reduction_proxy::prefs::
- kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
- DailyContentLengthUpdate unknown(
- this, data_reduction_proxy::prefs::
- kDailyContentLengthUnknownWithDataReductionProxyEnabled);
int days_since_last_update = (midnight - then_midnight).InDays();
if (days_since_last_update) {
@@ -894,349 +668,22 @@ void DataReductionProxyCompressionStats::RecordRequestSizePrefs(
SetInt64(data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate,
midnight.ToInternalValue());
- // A new day. Report the previous day's data if exists. We'll lose usage
- // data if the last time Chrome was run was more than a day ago.
- // Here, we prefer collecting less data but the collected data is
- // associated with an accurate date.
- if (days_since_last_update == 1) {
- RecordDailyContentLengthHistograms(
- total.GetOriginalListPrefValue(kNumDaysInHistory - 1),
- total.GetReceivedListPrefValue(kNumDaysInHistory - 1),
- proxy_enabled.GetOriginalListPrefValue(kNumDaysInHistory - 1),
- proxy_enabled.GetReceivedListPrefValue(kNumDaysInHistory - 1),
- via_proxy.GetOriginalListPrefValue(kNumDaysInHistory - 1),
- via_proxy.GetReceivedListPrefValue(kNumDaysInHistory - 1),
- https.GetListPrefValue(kNumDaysInHistory - 1),
- short_bypass.GetListPrefValue(kNumDaysInHistory - 1),
- long_bypass.GetListPrefValue(kNumDaysInHistory - 1),
- unknown.GetListPrefValue(kNumDaysInHistory - 1));
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyHttpOriginalContentLengthApplication,
- "Net.DailyOriginalContentLength_Application");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyHttpReceivedContentLengthApplication,
- "Net.DailyReceivedContentLength_Application");
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthVideo,
- "Net.DailyOriginalContentLength_Video");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthVideo,
- "Net.DailyContentLength_Video");
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthUnknown,
- "Net.DailyOriginalContentLength_UnknownMime");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthUnknown,
- "Net.DailyContentLength_UnknownMime");
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
- "Net.DailyOriginalContentLength_DataReductionProxyEnabled_"
- "Application");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledApplication,
- "Net.DailyContentLength_DataReductionProxyEnabled_Application");
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo,
- "Net.DailyOriginalContentLength_DataReductionProxyEnabled_Video");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledVideo,
- "Net.DailyContentLength_DataReductionProxyEnabled_Video");
- int64_t original_length_with_data_reduction_enabled_video = GetInt64(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo);
- if (original_length_with_data_reduction_enabled_video > 0) {
- int64_t received_length_with_data_reduction_enabled_video =
- GetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledVideo);
- int percent_data_reduction_proxy_enabled_video = 0;
- // UMA percentage cannot be negative.
- // The DataReductionProxy server will only serve optimized video content
- // if the optimized content is smaller than the original content.
- // TODO(ryansturm): Track daily data inflation percents here and
- // elsewhere. http://crbug.com/595818
- if (original_length_with_data_reduction_enabled_video >
- received_length_with_data_reduction_enabled_video) {
- percent_data_reduction_proxy_enabled_video =
- 100 * (original_length_with_data_reduction_enabled_video -
- received_length_with_data_reduction_enabled_video) /
- original_length_with_data_reduction_enabled_video;
- }
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentSavingPercent_DataReductionProxyEnabled_Video",
- percent_data_reduction_proxy_enabled_video);
- }
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
- "Net.DailyOriginalContentLength_DataReductionProxyEnabled_"
- "UnknownMime");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledUnknown,
- "Net.DailyContentLength_DataReductionProxyEnabled_UnknownMime")
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyApplication,
- "Net.DailyOriginalContentLength_ViaDataReductionProxy_Application");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyApplication,
- "Net.DailyContentLength_ViaDataReductionProxy_Application");
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyVideo,
- "Net.DailyOriginalContentLength_ViaDataReductionProxy_Video");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyVideo,
- "Net.DailyContentLength_ViaDataReductionProxy_Video");
- int64_t original_length_via_data_reduction_proxy_video =
- GetInt64(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyVideo);
- if (original_length_via_data_reduction_proxy_video > 0) {
- int64_t received_length_via_data_reduction_proxy_video =
- GetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyVideo);
- int percent_via_data_reduction_proxy_video = 0;
- // UMA percentage cannot be negative.
- // The DataReductionProxy server will only serve optimized video content
- // if the optimized content is smaller than the original content.
- // TODO(ryansturm): Track daily data inflation percents here and
- // elsewhere. http://crbug.com/595818
- if (original_length_via_data_reduction_proxy_video >
- received_length_via_data_reduction_proxy_video) {
- percent_via_data_reduction_proxy_video =
- 100 * (original_length_via_data_reduction_proxy_video -
- received_length_via_data_reduction_proxy_video) /
- original_length_via_data_reduction_proxy_video;
- }
- UMA_HISTOGRAM_PERCENTAGE(
- "Net.DailyContentSavingPercent_ViaDataReductionProxy_Video",
- percent_via_data_reduction_proxy_video);
- }
-
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyUnknown,
- "Net.DailyOriginalContentLength_ViaDataReductionProxy_UnknownMime");
- RECORD_INT64PREF_TO_HISTOGRAM(
- data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyUnknown,
- "Net.DailyContentLength_ViaDataReductionProxy_UnknownMime");
- }
-
+ // The system may go backwards in time by up to a day for legitimate
+ // reasons, such as with changes to the time zone. In such cases, we
+ // keep adding to the current day.
+ // (Actually resetting the numbers when we're more than a day off
+ // happens elsewhere.)
if (days_since_last_update < -1) {
RecordSavingsClearedMetric(
DataReductionProxySavingsClearedReason::SYSTEM_CLOCK_MOVED_BACK);
- }
-
- // The system may go backwards in time by up to a day for legitimate
- // reasons, such as with changes to the time zone. In such cases, we
- // keep adding to the current day which is why we check for
- // |days_since_last_update != -1|.
- // Note: we accept the fact that some reported data is shifted to
- // the adjacent day if users travel back and forth across time zones.
- if (days_since_last_update && (days_since_last_update != -1)) {
- if (days_since_last_update < -1) {
- pref_service_->SetInt64(
- prefs::kDataReductionProxySavingsClearedNegativeSystemClock,
- now.ToInternalValue());
- }
- SetInt64(data_reduction_proxy::prefs::
- kDailyHttpOriginalContentLengthApplication,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyHttpReceivedContentLengthApplication,
- 0);
-
- SetInt64(
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthVideo, 0);
- SetInt64(
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthVideo, 0);
-
- SetInt64(
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthUnknown,
- 0);
- SetInt64(
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthUnknown,
- 0);
-
- SetInt64(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledApplication,
- 0);
-
- SetInt64(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledVideo,
- 0);
-
- SetInt64(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledUnknown,
- 0);
-
- SetInt64(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyApplication,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyApplication,
- 0);
-
- SetInt64(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyVideo,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyVideo,
- 0);
-
- SetInt64(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyUnknown,
- 0);
- SetInt64(data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyUnknown,
- 0);
+ pref_service_->SetInt64(
+ prefs::kDataReductionProxySavingsClearedNegativeSystemClock,
+ now.ToInternalValue());
}
}
total.UpdateForDateChange(days_since_last_update);
- proxy_enabled.UpdateForDateChange(days_since_last_update);
- via_proxy.UpdateForDateChange(days_since_last_update);
- https.UpdateForDateChange(days_since_last_update);
- short_bypass.UpdateForDateChange(days_since_last_update);
- long_bypass.UpdateForDateChange(days_since_last_update);
- unknown.UpdateForDateChange(days_since_last_update);
-
total.Add(original_size, data_used);
- if (with_data_saver_enabled) {
- proxy_enabled.Add(original_size, data_used);
- // Ignore data source cases, if exist, when
- // "with_data_saver_enabled == false"
- switch (request_type) {
- case VIA_DATA_REDUCTION_PROXY:
- via_proxy.Add(original_size, data_used);
- break;
- case HTTPS:
- https.Add(data_used);
- break;
- case SHORT_BYPASS:
- short_bypass.Add(data_used);
- break;
- case LONG_BYPASS:
- long_bypass.Add(data_used);
- break;
- case UPDATE:
- case DIRECT_HTTP:
- // Don't record any request level prefs. If this is an update, this data
- // was already recorded at the URLRequest level. Updates are generally
- // page load level optimizations and don't correspond to request types.
- return;
- case UNKNOWN_TYPE:
- unknown.Add(data_used);
- break;
- default:
- NOTREACHED();
- }
- }
-
- bool via_data_reduction_proxy = request_type == VIA_DATA_REDUCTION_PROXY;
- bool is_application = net::MatchesMimeType("application/*", mime_type);
- bool is_video = net::MatchesMimeType("video/*", mime_type);
- bool is_mime_type_empty = mime_type.empty();
- if (is_application) {
- IncrementDailyUmaPrefs(
- original_size, data_used,
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthApplication,
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthApplication,
- with_data_saver_enabled,
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledApplication,
- via_data_reduction_proxy,
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyApplication,
- data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyApplication);
- } else if (is_video) {
- IncrementDailyUmaPrefs(
- original_size, data_used,
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthVideo,
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthVideo,
- with_data_saver_enabled,
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo,
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledVideo,
- via_data_reduction_proxy,
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyVideo,
- data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyVideo);
- } else if (is_mime_type_empty) {
- IncrementDailyUmaPrefs(
- original_size, data_used,
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthUnknown,
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthUnknown,
- with_data_saver_enabled,
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledUnknown,
- via_data_reduction_proxy,
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyUnknown,
- data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyUnknown);
- }
-}
-
-void DataReductionProxyCompressionStats::IncrementDailyUmaPrefs(
- int64_t original_size,
- int64_t received_size,
- const char* original_size_pref,
- const char* received_size_pref,
- bool data_reduction_proxy_enabled,
- const char* original_size_with_proxy_enabled_pref,
- const char* recevied_size_with_proxy_enabled_pref,
- bool via_data_reduction_proxy,
- const char* original_size_via_proxy_pref,
- const char* received_size_via_proxy_pref) {
- IncreaseInt64Pref(original_size_pref, original_size);
- IncreaseInt64Pref(received_size_pref, received_size);
-
- if (data_reduction_proxy_enabled) {
- IncreaseInt64Pref(original_size_with_proxy_enabled_pref, original_size);
- IncreaseInt64Pref(recevied_size_with_proxy_enabled_pref, received_size);
- }
-
- if (via_data_reduction_proxy) {
- IncreaseInt64Pref(original_size_via_proxy_pref, original_size);
- IncreaseInt64Pref(received_size_via_proxy_pref, received_size);
- }
}
void DataReductionProxyCompressionStats::RecordDataUseByHost(
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
index f7d56f6a85d..4f307708e7b 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
@@ -16,7 +16,7 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
@@ -114,8 +114,8 @@ const char kLastUpdateTime[] = "Wed, 18 Sep 2013 03:45:26";
class DataReductionProxyCompressionStatsTest : public testing::Test {
protected:
DataReductionProxyCompressionStatsTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+ : task_environment_(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {
EXPECT_TRUE(base::Time::FromString(kLastUpdateTime, &now_));
}
@@ -253,128 +253,11 @@ class DataReductionProxyCompressionStatsTest : public testing::Test {
size_t original_count,
const int64_t* received_values,
size_t received_count,
- const int64_t* original_with_data_reduction_proxy_enabled_values,
- size_t original_with_data_reduction_proxy_enabled_count,
- const int64_t* received_with_data_reduction_proxy_enabled_values,
- size_t received_with_data_reduction_proxy_count,
- const int64_t* original_via_data_reduction_proxy_values,
- size_t original_via_data_reduction_proxy_count,
- const int64_t* received_via_data_reduction_proxy_values,
- size_t received_via_data_reduction_proxy_count,
size_t num_days_in_history) {
VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength,
original_values, original_count, num_days_in_history);
VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength,
received_values, received_count, num_days_in_history);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabled,
- original_with_data_reduction_proxy_enabled_values,
- original_with_data_reduction_proxy_enabled_count,
- num_days_in_history);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabled,
- received_with_data_reduction_proxy_enabled_values,
- received_with_data_reduction_proxy_count,
- num_days_in_history);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxy,
- original_via_data_reduction_proxy_values,
- original_via_data_reduction_proxy_count,
- num_days_in_history);
- VerifyPrefList(
- data_reduction_proxy::prefs::kDailyContentLengthViaDataReductionProxy,
- received_via_data_reduction_proxy_values,
- received_via_data_reduction_proxy_count, num_days_in_history);
-
- VerifyPrefInt64(
- data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthApplication,
- original_values ? original_values[original_count - 1] : 0);
- VerifyPrefInt64(
- data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthApplication,
- received_values ? received_values[received_count - 1] : 0);
-
- VerifyPrefInt64(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
- original_with_data_reduction_proxy_enabled_values
- ? original_with_data_reduction_proxy_enabled_values
- [original_with_data_reduction_proxy_enabled_count - 1]
- : 0);
- VerifyPrefInt64(
- data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabledApplication,
- received_with_data_reduction_proxy_enabled_values
- ? received_with_data_reduction_proxy_enabled_values
- [received_with_data_reduction_proxy_count - 1]
- : 0);
-
- VerifyPrefInt64(
- data_reduction_proxy::prefs::
- kDailyOriginalContentLengthViaDataReductionProxyApplication,
- original_via_data_reduction_proxy_values
- ? original_via_data_reduction_proxy_values
- [original_via_data_reduction_proxy_count - 1]
- : 0);
- VerifyPrefInt64(data_reduction_proxy::prefs::
- kDailyContentLengthViaDataReductionProxyApplication,
- received_via_data_reduction_proxy_values
- ? received_via_data_reduction_proxy_values
- [received_via_data_reduction_proxy_count - 1]
- : 0);
- }
-
- // Verify daily data saving pref for request types.
- void VerifyDailyRequestTypeContentLengthPrefLists(
- const int64_t* original_values,
- size_t original_count,
- const int64_t* received_values,
- size_t received_count,
- const int64_t* original_with_data_reduction_proxy_enabled_values,
- size_t original_with_data_reduction_proxy_enabled_count,
- const int64_t* received_with_data_reduction_proxy_enabled_values,
- size_t received_with_data_reduction_proxy_count,
- const int64_t* https_with_data_reduction_proxy_enabled_values,
- size_t https_with_data_reduction_proxy_enabled_count,
- const int64_t* short_bypass_with_data_reduction_proxy_enabled_values,
- size_t short_bypass_with_data_reduction_proxy_enabled_count,
- const int64_t* long_bypass_with_data_reduction_proxy_enabled_values,
- size_t long_bypass_with_data_reduction_proxy_enabled_count,
- const int64_t* unknown_with_data_reduction_proxy_enabled_values,
- size_t unknown_with_data_reduction_proxy_enabled_count) {
- VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength,
- original_values, original_count, kNumDaysInHistory);
- VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength,
- received_values, received_count, kNumDaysInHistory);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabled,
- original_with_data_reduction_proxy_enabled_values,
- original_with_data_reduction_proxy_enabled_count,
- kNumDaysInHistory);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyContentLengthWithDataReductionProxyEnabled,
- received_with_data_reduction_proxy_enabled_values,
- received_with_data_reduction_proxy_count, kNumDaysInHistory);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyContentLengthHttpsWithDataReductionProxyEnabled,
- https_with_data_reduction_proxy_enabled_values,
- https_with_data_reduction_proxy_enabled_count,
- kNumDaysInHistory);
- VerifyPrefList(
- data_reduction_proxy::prefs::
- kDailyContentLengthShortBypassWithDataReductionProxyEnabled,
- short_bypass_with_data_reduction_proxy_enabled_values,
- short_bypass_with_data_reduction_proxy_enabled_count,
- kNumDaysInHistory);
- VerifyPrefList(
- data_reduction_proxy::prefs::
- kDailyContentLengthLongBypassWithDataReductionProxyEnabled,
- long_bypass_with_data_reduction_proxy_enabled_values,
- long_bypass_with_data_reduction_proxy_enabled_count, kNumDaysInHistory);
- VerifyPrefList(data_reduction_proxy::prefs::
- kDailyContentLengthUnknownWithDataReductionProxyEnabled,
- unknown_with_data_reduction_proxy_enabled_values,
- unknown_with_data_reduction_proxy_enabled_count,
- kNumDaysInHistory);
}
int64_t GetInt64(const char* pref_path) {
@@ -500,7 +383,7 @@ class DataReductionProxyCompressionStatsTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<DataReductionProxyTestContext> drp_test_context_;
std::unique_ptr<DataReductionProxyCompressionStats> compression_stats_;
base::Time now_;
@@ -588,9 +471,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, OneResponse) {
kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
FakeNow());
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original, 1, received, 1, original, 1, received,
- 1, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
}
TEST_F(DataReductionProxyCompressionStatsTest, MultipleResponses) {
@@ -600,136 +482,37 @@ TEST_F(DataReductionProxyCompressionStatsTest, MultipleResponses) {
int64_t received[] = {kReceivedLength};
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, false, UNKNOWN_TYPE, FakeNow());
- VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1, nullptr,
- 0, nullptr, 0, nullptr, 0,
- nullptr, 0, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, true, UNKNOWN_TYPE, FakeNow());
original[0] += kOriginalLength;
received[0] += kReceivedLength;
- int64_t original_proxy_enabled[] = {kOriginalLength};
- int64_t received_proxy_enabled[] = {kReceivedLength};
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original_proxy_enabled, 1,
- received_proxy_enabled, 1, nullptr, 0, nullptr, 0, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
FakeNow());
original[0] += kOriginalLength;
received[0] += kReceivedLength;
- original_proxy_enabled[0] += kOriginalLength;
- received_proxy_enabled[0] += kReceivedLength;
- int64_t original_via_proxy[] = {kOriginalLength};
- int64_t received_via_proxy[] = {kReceivedLength};
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original_proxy_enabled, 1,
- received_proxy_enabled, 1, original_via_proxy, 1, received_via_proxy, 1,
- kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, true, UNKNOWN_TYPE, FakeNow());
original[0] += kOriginalLength;
received[0] += kReceivedLength;
- original_proxy_enabled[0] += kOriginalLength;
- received_proxy_enabled[0] += kReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original_proxy_enabled, 1,
- received_proxy_enabled, 1, original_via_proxy, 1, received_via_proxy, 1,
- kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, false, UNKNOWN_TYPE, FakeNow());
original[0] += kOriginalLength;
received[0] += kReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original_proxy_enabled, 1,
- received_proxy_enabled, 1, original_via_proxy, 1, received_via_proxy, 1,
- kNumDaysInHistory);
-}
-
-TEST_F(DataReductionProxyCompressionStatsTest, RequestType) {
- const int64_t kContentLength = 200;
- int64_t received[] = {0};
- int64_t https_received[] = {0};
- int64_t total_received[] = {0};
- int64_t proxy_enabled_received[] = {0};
-
- RecordContentLengthPrefs(
- kContentLength, kContentLength, true, HTTPS, FakeNow());
- total_received[0] += kContentLength;
- proxy_enabled_received[0] += kContentLength;
- https_received[0] += kContentLength;
- VerifyDailyRequestTypeContentLengthPrefLists(
- total_received, 1, total_received, 1,
- proxy_enabled_received, 1, proxy_enabled_received, 1,
- https_received, 1,
- received, 0, // short bypass
- received, 0, // long bypass
- received, 0); // unknown
-
- // Data reduction proxy is not enabled.
- RecordContentLengthPrefs(
- kContentLength, kContentLength, false, HTTPS, FakeNow());
- total_received[0] += kContentLength;
- VerifyDailyRequestTypeContentLengthPrefLists(
- total_received, 1, total_received, 1,
- proxy_enabled_received, 1, proxy_enabled_received, 1,
- https_received, 1,
- received, 0, // short bypass
- received, 0, // long bypass
- received, 0); // unknown
-
- RecordContentLengthPrefs(
- kContentLength, kContentLength, true, HTTPS, FakeNow());
- total_received[0] += kContentLength;
- proxy_enabled_received[0] += kContentLength;
- https_received[0] += kContentLength;
- VerifyDailyRequestTypeContentLengthPrefLists(
- total_received, 1, total_received, 1,
- proxy_enabled_received, 1, proxy_enabled_received, 1,
- https_received, 1,
- received, 0, // short bypass
- received, 0, // long bypass
- received, 0); // unknown
-
- RecordContentLengthPrefs(
- kContentLength, kContentLength, true, SHORT_BYPASS, FakeNow());
- total_received[0] += kContentLength;
- proxy_enabled_received[0] += kContentLength;
- received[0] += kContentLength;
- VerifyDailyRequestTypeContentLengthPrefLists(
- total_received, 1, total_received, 1,
- proxy_enabled_received, 1, proxy_enabled_received, 1,
- https_received, 1,
- received, 1, // short bypass
- received, 0, // long bypass
- received, 0); // unknown
-
- RecordContentLengthPrefs(
- kContentLength, kContentLength, true, LONG_BYPASS, FakeNow());
- total_received[0] += kContentLength;
- proxy_enabled_received[0] += kContentLength;
- VerifyDailyRequestTypeContentLengthPrefLists(
- total_received, 1, total_received, 1, // total
- proxy_enabled_received, 1, proxy_enabled_received, 1,
- https_received, 1,
- received, 1, // short bypass
- received, 1, // long bypass
- received, 0); // unknown
-
- RecordContentLengthPrefs(
- kContentLength, kContentLength, true, UNKNOWN_TYPE, FakeNow());
- total_received[0] += kContentLength;
- proxy_enabled_received[0] += kContentLength;
- VerifyDailyRequestTypeContentLengthPrefLists(
- total_received, 1, total_received, 1,
- proxy_enabled_received, 1, proxy_enabled_received, 1,
- https_received, 1,
- received, 1, // short bypass
- received, 1, // long bypass
- received, 1); // unknown
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
}
TEST_F(DataReductionProxyCompressionStatsTest, ForwardOneDay) {
@@ -749,28 +532,16 @@ TEST_F(DataReductionProxyCompressionStatsTest, ForwardOneDay) {
int64_t original[] = {kOriginalLength, kOriginalLength};
int64_t received[] = {kReceivedLength, kReceivedLength};
- int64_t original_with_data_reduction_proxy_enabled[] = {kOriginalLength, 0};
- int64_t received_with_data_reduction_proxy_enabled[] = {kReceivedLength, 0};
- int64_t original_via_data_reduction_proxy[] = {kOriginalLength, 0};
- int64_t received_via_data_reduction_proxy[] = {kReceivedLength, 0};
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 2, received, 2, original_with_data_reduction_proxy_enabled, 2,
- received_with_data_reduction_proxy_enabled, 2,
- original_via_data_reduction_proxy, 2, received_via_data_reduction_proxy,
- 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 2, received, 2,
+ kNumDaysInHistory);
// Proxy enabled. Not via proxy.
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, true, UNKNOWN_TYPE, FakeNow());
original[1] += kOriginalLength;
received[1] += kReceivedLength;
- original_with_data_reduction_proxy_enabled[1] += kOriginalLength;
- received_with_data_reduction_proxy_enabled[1] += kReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 2, received, 2, original_with_data_reduction_proxy_enabled, 2,
- received_with_data_reduction_proxy_enabled, 2,
- original_via_data_reduction_proxy, 2, received_via_data_reduction_proxy,
- 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 2, received, 2,
+ kNumDaysInHistory);
// Proxy enabled and via proxy.
RecordContentLengthPrefs(
@@ -778,15 +549,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, ForwardOneDay) {
FakeNow());
original[1] += kOriginalLength;
received[1] += kReceivedLength;
- original_with_data_reduction_proxy_enabled[1] += kOriginalLength;
- received_with_data_reduction_proxy_enabled[1] += kReceivedLength;
- original_via_data_reduction_proxy[1] += kOriginalLength;
- received_via_data_reduction_proxy[1] += kReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 2, received, 2, original_with_data_reduction_proxy_enabled, 2,
- received_with_data_reduction_proxy_enabled, 2,
- original_via_data_reduction_proxy, 2, received_via_data_reduction_proxy,
- 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 2, received, 2,
+ kNumDaysInHistory);
// Proxy enabled and via proxy, with content length greater than max int32_t.
const int64_t kBigOriginalLength = 0x300000000LL; // 12G.
@@ -795,15 +559,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, ForwardOneDay) {
VIA_DATA_REDUCTION_PROXY, FakeNow());
original[1] += kBigOriginalLength;
received[1] += kBigReceivedLength;
- original_with_data_reduction_proxy_enabled[1] += kBigOriginalLength;
- received_with_data_reduction_proxy_enabled[1] += kBigReceivedLength;
- original_via_data_reduction_proxy[1] += kBigOriginalLength;
- received_via_data_reduction_proxy[1] += kBigReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 2, received, 2, original_with_data_reduction_proxy_enabled, 2,
- received_with_data_reduction_proxy_enabled, 2,
- original_via_data_reduction_proxy, 2, received_via_data_reduction_proxy,
- 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 2, received, 2,
+ kNumDaysInHistory);
}
TEST_F(DataReductionProxyCompressionStatsTest, PartialDayTimeChange) {
@@ -815,9 +572,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, PartialDayTimeChange) {
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
FakeNow());
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 2, received, 2, original, 2, received, 2, original, 2, received,
- 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 2, received, 2,
+ kNumDaysInHistory);
// Forward 10 hours, stay in the same day.
// See kLastUpdateTime: "Now" in test is 03:45am.
@@ -827,9 +583,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, PartialDayTimeChange) {
FakeNow());
original[1] += kOriginalLength;
received[1] += kReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 2, received, 2, original, 2, received, 2, original, 2, received,
- 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 2, received, 2,
+ kNumDaysInHistory);
// Forward 11 more hours, comes to tomorrow.
AddFakeTimeDeltaInHours(11);
@@ -838,9 +593,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, PartialDayTimeChange) {
FakeNow());
int64_t original2[] = {kOriginalLength * 2, kOriginalLength};
int64_t received2[] = {kReceivedLength * 2, kReceivedLength};
- VerifyDailyDataSavingContentLengthPrefLists(
- original2, 2, received2, 2, original2, 2, received2, 2, original2, 2,
- received2, 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original2, 2, received2, 2,
+ kNumDaysInHistory);
}
TEST_F(DataReductionProxyCompressionStatsTest, BackwardAndForwardOneDay) {
@@ -861,9 +615,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, BackwardAndForwardOneDay) {
FakeNow());
original[0] += kOriginalLength;
received[0] += kReceivedLength;
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original, 1, received, 1, original, 1, received,
- 1, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
histogram_tester.ExpectTotalCount("DataReductionProxy.SavingsCleared.Reason",
0);
@@ -874,9 +627,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, BackwardAndForwardOneDay) {
FakeNow());
int64_t original2[] = {kOriginalLength * 2, kOriginalLength};
int64_t received2[] = {kReceivedLength * 2, kReceivedLength};
- VerifyDailyDataSavingContentLengthPrefLists(
- original2, 2, received2, 2, original2, 2, received2, 2, original2, 2,
- received2, 2, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original2, 2, received2, 2,
+ kNumDaysInHistory);
histogram_tester.ExpectTotalCount("DataReductionProxy.SavingsCleared.Reason",
0);
}
@@ -897,9 +649,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, BackwardTwoDays) {
RecordContentLengthPrefs(
kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY,
FakeNow());
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original, 1, received, 1, original, 1, received,
- 1, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
histogram_tester.ExpectUniqueSample(
"DataReductionProxy.SavingsCleared.Reason",
DataReductionProxySavingsClearedReason::SYSTEM_CLOCK_MOVED_BACK, 1);
@@ -930,63 +681,6 @@ TEST_F(DataReductionProxyCompressionStatsTest, NormalizeHostname) {
EXPECT_EQ("http.www.co.in", NormalizeHostname("http://http.www.co.in"));
}
-TEST_F(DataReductionProxyCompressionStatsTest, RecordUma) {
- const int64_t kOriginalLength = 15000;
- const int64_t kReceivedLength = 10000;
- base::HistogramTester tester;
-
- RecordContentLengthPrefs(kReceivedLength, kOriginalLength, true,
- VIA_DATA_REDUCTION_PROXY, FakeNow());
-
- // Forward one day.
- SetFakeTimeDeltaInHours(24);
-
- // Proxy not enabled. Not via proxy.
- RecordContentLengthPrefs(kReceivedLength, kOriginalLength, false,
- UNKNOWN_TYPE, FakeNow());
-
- // 15000 falls into the 12 KB bucket
- tester.ExpectUniqueSample("Net.DailyOriginalContentLength", 12, 1);
- tester.ExpectUniqueSample("Net.DailyOriginalContentLength_Application", 12,
- 1);
- tester.ExpectUniqueSample(
- "Net.DailyOriginalContentLength_DataReductionProxyEnabled", 12, 1);
- tester.ExpectUniqueSample(
- "Net.DailyOriginalContentLength_DataReductionProxyEnabled_Application",
- 12, 1);
- tester.ExpectUniqueSample(
- "Net.DailyOriginalContentLength_ViaDataReductionProxy", 12, 1);
- tester.ExpectUniqueSample(
- "Net.DailyOriginalContentLength_ViaDataReductionProxy_Application", 12,
- 1);
-
- // 10000 falls into the 9 KB bucket
- tester.ExpectUniqueSample("Net.DailyContentLength", 9, 1);
- tester.ExpectUniqueSample("Net.DailyReceivedContentLength_Application", 9, 1);
- tester.ExpectUniqueSample("Net.DailyContentLength_DataReductionProxyEnabled",
- 9, 1);
- tester.ExpectUniqueSample(
- "Net.DailyContentLength_DataReductionProxyEnabled_Application", 9, 1);
- tester.ExpectUniqueSample("Net.DailyContentLength_ViaDataReductionProxy", 9,
- 1);
- tester.ExpectUniqueSample(
- "Net.DailyContentLength_ViaDataReductionProxy_Application", 9, 1);
-
- // floor((15000 - 10000) * 100) = 33.
- tester.ExpectUniqueSample("Net.DailyContentSavingPercent", 33, 1);
- tester.ExpectUniqueSample(
- "Net.DailyContentSavingPercent_DataReductionProxyEnabled", 33, 1);
- tester.ExpectUniqueSample(
- "Net.DailyContentSavingPercent_ViaDataReductionProxy", 33, 1);
-
- tester.ExpectUniqueSample("Net.DailyContentPercent_DataReductionProxyEnabled",
- 100, 1);
- tester.ExpectUniqueSample("Net.DailyContentPercent_ViaDataReductionProxy",
- 100, 1);
- tester.ExpectUniqueSample(
- "Net.DailyContentPercent_DataReductionProxyEnabled_Unknown", 0, 1);
-}
-
TEST_F(DataReductionProxyCompressionStatsTest, RecordDataUsageSingleSite) {
EnableDataUsageReporting();
base::RunLoop().RunUntilIdle();
@@ -1261,9 +955,8 @@ TEST_F(DataReductionProxyCompressionStatsTest, ClearDataSavingStatistics) {
RecordContentLengthPrefs(kReceivedLength, kOriginalLength, true,
VIA_DATA_REDUCTION_PROXY, FakeNow());
- VerifyDailyDataSavingContentLengthPrefLists(
- original, 1, received, 1, original, 1, received, 1, original, 1, received,
- 1, kNumDaysInHistory);
+ VerifyDailyDataSavingContentLengthPrefLists(original, 1, received, 1,
+ kNumDaysInHistory);
ClearDataSavingStatistics();
base::RunLoop().RunUntilIdle();
@@ -1278,9 +971,7 @@ TEST_F(DataReductionProxyCompressionStatsTest, ClearDataSavingStatistics) {
now);
base::RunLoop().RunUntilIdle();
- VerifyDailyDataSavingContentLengthPrefLists(nullptr, 0, nullptr, 0, nullptr,
- 0, nullptr, 0, nullptr, 0,
- nullptr, 0, 0);
+ VerifyDailyDataSavingContentLengthPrefLists(nullptr, 0, nullptr, 0, 0);
}
TEST_F(DataReductionProxyCompressionStatsTest, WeeklyAggregateDataUse) {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 0121a89fab6..13eac80b690 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -178,21 +178,16 @@ std::string DoGetCurrentNetworkID(
namespace data_reduction_proxy {
DataReductionProxyConfig::DataReductionProxyConfig(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
network::NetworkConnectionTracker* network_connection_tracker,
std::unique_ptr<DataReductionProxyConfigValues> config_values,
DataReductionProxyConfigurator* configurator)
: unreachable_(false),
enabled_by_user_(false),
config_values_(std::move(config_values)),
- io_task_runner_(io_task_runner),
- ui_task_runner_(ui_task_runner),
network_connection_tracker_(network_connection_tracker),
configurator_(configurator),
connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN),
network_properties_manager_(nullptr) {
- DCHECK(io_task_runner_);
DCHECK(network_connection_tracker_);
DCHECK(configurator);
@@ -204,7 +199,7 @@ DataReductionProxyConfig::~DataReductionProxyConfig() {
network_connection_tracker_->RemoveNetworkConnectionObserver(this);
}
-void DataReductionProxyConfig::InitializeOnIOThread(
+void DataReductionProxyConfig::Initialize(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
WarmupURLFetcher::CreateCustomProxyConfigCallback
create_custom_proxy_config_callback,
@@ -215,15 +210,16 @@ void DataReductionProxyConfig::InitializeOnIOThread(
network_properties_manager_->ResetWarmupURLFetchMetrics();
if (!params::IsIncludedInHoldbackFieldTrial()) {
- secure_proxy_checker_.reset(new SecureProxyChecker(url_loader_factory));
- warmup_url_fetcher_.reset(new WarmupURLFetcher(
+ secure_proxy_checker_ =
+ std::make_unique<SecureProxyChecker>(url_loader_factory);
+ warmup_url_fetcher_ = std::make_unique<WarmupURLFetcher>(
create_custom_proxy_config_callback,
base::BindRepeating(
&DataReductionProxyConfig::HandleWarmupFetcherResponse,
base::Unretained(this)),
base::BindRepeating(&DataReductionProxyConfig::GetHttpRttEstimate,
base::Unretained(this)),
- ui_task_runner_, user_agent));
+ user_agent);
}
AddDefaultProxyBypassRules();
@@ -521,9 +517,7 @@ void DataReductionProxyConfig::HandleWarmupFetcherResponse(
// been reached yet. This method may have been called by warmup URL fetcher.
// FetchWarmupProbeURL() may itself call warmup URL fetcher. Posting the call
// here avoids recursive calls to the warmup URL fetcher.
- io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyConfig::FetchWarmupProbeURL,
- weak_factory_.GetWeakPtr()));
+ FetchWarmupProbeURL();
}
void DataReductionProxyConfig::HandleSecureProxyCheckResponse(
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
index 9eb9c828147..e066160e86f 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -29,10 +29,6 @@
#include "net/proxy_resolution/proxy_retry_info.h"
#include "services/network/public/cpp/network_connection_tracker.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace net {
class ProxyServer;
} // namespace net
@@ -85,8 +81,6 @@ class DataReductionProxyConfig
// Reduction Proxy configuration values. |configurator| is the target for a
// configuration update.
DataReductionProxyConfig(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
network::NetworkConnectionTracker* network_connection_tracker,
std::unique_ptr<DataReductionProxyConfigValues> config_values,
DataReductionProxyConfigurator* configurator);
@@ -95,7 +89,7 @@ class DataReductionProxyConfig
// Performs initialization on the IO thread.
// |url_loader_factory| is the network::URLLoaderFactory instance used for
// making URL requests. The requests disable the use of proxies.
- void InitializeOnIOThread(
+ void Initialize(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
WarmupURLFetcher::CreateCustomProxyConfigCallback
create_custom_proxy_config_callback,
@@ -285,9 +279,6 @@ class DataReductionProxyConfig
// Contains the configuration data being used.
std::unique_ptr<DataReductionProxyConfigValues> config_values_;
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
-
#if defined(OS_CHROMEOS)
// Whether the network id should be obtained on a worker thread.
bool get_network_id_asynchronously_ = false;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index d72f5dabf1d..d22b6d72c1a 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -23,9 +23,9 @@
#include "base/values.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
@@ -33,6 +33,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
+#include "components/previews/core/previews_experiments.h"
#include "components/variations/net/variations_http_headers.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
@@ -152,13 +153,13 @@ DataReductionProxyConfigServiceClient::DataReductionProxyConfigServiceClient(
DataReductionProxyRequestOptions* request_options,
DataReductionProxyMutableConfigValues* config_values,
DataReductionProxyConfig* config,
- DataReductionProxyIOData* io_data,
+ DataReductionProxyService* service,
network::NetworkConnectionTracker* network_connection_tracker,
ConfigStorer config_storer)
: request_options_(request_options),
config_values_(config_values),
config_(config),
- io_data_(io_data),
+ service_(service),
network_connection_tracker_(network_connection_tracker),
config_storer_(config_storer),
backoff_policy_(backoff_policy),
@@ -176,9 +177,10 @@ DataReductionProxyConfigServiceClient::DataReductionProxyConfigServiceClient(
DCHECK(request_options);
DCHECK(config_values);
DCHECK(config);
- DCHECK(io_data);
+ DCHECK(service);
DCHECK(config_service_url_.is_valid());
- DCHECK(!params::IsIncludedInHoldbackFieldTrial());
+ DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
+ previews::params::IsLitePageServerPreviewsEnabled());
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
@@ -223,7 +225,7 @@ DataReductionProxyConfigServiceClient::CalculateNextConfigRefreshTime(
return backoff_delay;
}
-void DataReductionProxyConfigServiceClient::InitializeOnIOThread(
+void DataReductionProxyConfigServiceClient::Initialize(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
DCHECK(url_loader_factory);
#if defined(OS_ANDROID)
@@ -415,7 +417,8 @@ void DataReductionProxyConfigServiceClient::OnURLLoadComplete(
void DataReductionProxyConfigServiceClient::RetrieveRemoteConfig() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!params::IsIncludedInHoldbackFieldTrial());
+ DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
+ previews::params::IsLitePageServerPreviewsEnabled());
CreateClientConfigRequest request;
std::string serialized_request;
@@ -440,10 +443,10 @@ void DataReductionProxyConfigServiceClient::RetrieveRemoteConfig() {
uint32_t build;
uint32_t patch;
util::GetChromiumBuildAndPatchAsInts(util::ChromiumVersion(), &build, &patch);
- version_info->set_client(util::GetStringForClient(io_data_->client()));
+ version_info->set_client(util::GetStringForClient(service_->client()));
version_info->set_build(build);
version_info->set_patch(patch);
- version_info->set_channel(io_data_->channel());
+ version_info->set_channel(service_->channel());
request.SerializeToString(&serialized_request);
net::NetworkTrafficAnnotationTag traffic_annotation =
@@ -474,7 +477,7 @@ void DataReductionProxyConfigServiceClient::RetrieveRemoteConfig() {
resource_request->url = config_service_url_;
resource_request->method = "POST";
resource_request->load_flags = net::LOAD_BYPASS_PROXY;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
// Attach variations headers.
url_loader_ = variations::CreateSimpleURLLoaderWithVariationsHeader(
std::move(resource_request), variations::InIncognito::kNo,
@@ -501,7 +504,7 @@ void DataReductionProxyConfigServiceClient::InvalidateConfig() {
config_storer_.Run(std::string());
request_options_->Invalidate();
config_values_->Invalidate();
- io_data_->SetPingbackReportingFraction(0.0f);
+ service_->SetPingbackReportingFraction(0.0f);
config_->OnNewClientConfigFetched();
}
@@ -580,12 +583,12 @@ bool DataReductionProxyConfigServiceClient::ParseAndApplyProxyConfig(
}
DCHECK_LE(0.0f, reporting_fraction);
DCHECK_GE(1.0f, reporting_fraction);
- io_data_->SetPingbackReportingFraction(reporting_fraction);
+ service_->SetPingbackReportingFraction(reporting_fraction);
if (!config.has_proxy_config())
return false;
- io_data_->SetIgnoreLongTermBlackListRules(
+ service_->SetIgnoreLongTermBlackListRules(
config.ignore_long_term_black_list_rules());
// An empty proxy config is OK, and allows the server to effectively turn off
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
index 8e211ba9bfe..6dfacba7080 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
@@ -40,7 +40,7 @@ namespace data_reduction_proxy {
class ClientConfig;
class DataReductionProxyConfig;
-class DataReductionProxyIOData;
+class DataReductionProxyService;
class DataReductionProxyMutableConfigValues;
class DataReductionProxyRequestOptions;
@@ -89,14 +89,14 @@ class DataReductionProxyConfigServiceClient
DataReductionProxyRequestOptions* request_options,
DataReductionProxyMutableConfigValues* config_values,
DataReductionProxyConfig* config,
- DataReductionProxyIOData* io_data,
+ DataReductionProxyService* service,
network::NetworkConnectionTracker* network_connection_tracker,
ConfigStorer config_storer);
~DataReductionProxyConfigServiceClient() override;
// Performs initialization on the IO thread.
- void InitializeOnIOThread(
+ void Initialize(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
// Sets whether the configuration should be retrieved or not.
@@ -200,8 +200,8 @@ class DataReductionProxyConfigServiceClient
// The caller must ensure that the |config_| outlives this instance.
DataReductionProxyConfig* config_;
- // The caller must ensure that the |io_data_| outlives this instance.
- DataReductionProxyIOData* io_data_;
+ // The caller must ensure that the |service_| outlives this instance.
+ DataReductionProxyService* service_;
// Watches for network changes.
network::NetworkConnectionTracker* network_connection_tracker_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index e3a307a3210..d75f2503bad 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -19,7 +19,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_test_utils.h"
@@ -335,11 +335,13 @@ class DataReductionProxyConfigServiceClientTest : public testing::Test {
}
float pingback_reporting_fraction() const {
- return test_context_->io_data()->pingback_reporting_fraction();
+ return test_context_->test_data_reduction_proxy_service()
+ ->pingback_reporting_fraction();
}
bool ignore_blacklist() const {
- return test_context_->io_data()->ignore_blacklist();
+ return test_context_->test_data_reduction_proxy_service()
+ ->ignore_blacklist();
}
void RunUntilIdle() {
@@ -398,8 +400,7 @@ class DataReductionProxyConfigServiceClientTest : public testing::Test {
private:
base::test::ScopedFeatureList scoped_feature_list_;
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory>
@@ -552,8 +553,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
- &test_prefs,
- base::ThreadTaskRunnerHandle::Get());
+ &test_prefs);
manager.SetIsSecureProxyDisallowedByCarrier(true);
configurator()->Enable(manager, http_proxies);
VerifyRemoteSuccess(false);
@@ -691,8 +691,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
NetworkPropertiesManager manager(base::DefaultClock::GetInstance(),
- &test_prefs,
- base::ThreadTaskRunnerHandle::Get());
+ &test_prefs);
manager.SetIsSecureProxyDisallowedByCarrier(true);
configurator()->Enable(manager, http_proxies);
VerifyRemoteSuccess(false);
@@ -837,7 +836,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
for (const auto& test : tests) {
base::HistogramTester histogram_tester;
// Reset the state.
- test_context_->io_data()->test_request_options()->Invalidate();
+ request_options()->Invalidate();
test_context_->pref_service()->ClearPref(
prefs::kDataReductionProxyLastConfigRetrievalTime);
RunUntilIdle();
@@ -868,9 +867,8 @@ TEST_F(DataReductionProxyConfigServiceClientTest,
// Simulate startup which should cause the empty persisted client config to
// be read from the disk.
config_client()->SetRemoteConfigApplied(false);
- test_context_->io_data()->test_request_options()->Invalidate();
- test_context_->data_reduction_proxy_service()->SetIOData(
- test_context_->io_data()->GetWeakPtr());
+ request_options()->Invalidate();
+ test_context_->data_reduction_proxy_service()->ReadPersistedClientConfig();
RunUntilIdle();
EXPECT_NE(test.expect_valid_config,
request_options()->GetSecureSession().empty());
@@ -976,9 +974,8 @@ TEST_F(DataReductionProxyConfigServiceClientTest, MultipleAuthFailures) {
"DataReductionProxy.ConfigService.AuthExpired", true, 1);
DCHECK(test_context_->data_reduction_proxy_service());
- test_context_->io_data()->test_request_options()->Invalidate();
- test_context_->data_reduction_proxy_service()->SetIOData(
- test_context_->io_data()->GetWeakPtr());
+ request_options()->Invalidate();
+ test_context_->data_reduction_proxy_service()->ReadPersistedClientConfig();
test_context_->RunUntilIdle();
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc
index 5953d78ced6..4556efaf9fd 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc
@@ -23,23 +23,15 @@ using testing::_;
namespace data_reduction_proxy {
TestDataReductionProxyConfig::TestDataReductionProxyConfig(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
DataReductionProxyConfigurator* configurator)
: TestDataReductionProxyConfig(
std::make_unique<TestDataReductionProxyParams>(),
- io_task_runner,
- ui_task_runner,
configurator) {}
TestDataReductionProxyConfig::TestDataReductionProxyConfig(
std::unique_ptr<DataReductionProxyConfigValues> config_values,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
DataReductionProxyConfigurator* configurator)
: DataReductionProxyConfig(
- io_task_runner,
- ui_task_runner,
network::TestNetworkConnectionTracker::GetInstance(),
std::move(config_values),
configurator),
@@ -146,12 +138,8 @@ void TestDataReductionProxyConfig::SetWarmupURLFetchAttemptCounts(
MockDataReductionProxyConfig::MockDataReductionProxyConfig(
std::unique_ptr<DataReductionProxyConfigValues> config_values,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
DataReductionProxyConfigurator* configurator)
: TestDataReductionProxyConfig(std::move(config_values),
- io_task_runner,
- ui_task_runner,
configurator) {}
MockDataReductionProxyConfig::~MockDataReductionProxyConfig() {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
index 41fe16c9aa1..d76679a7eef 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
@@ -16,7 +16,6 @@
#include "testing/gmock/include/gmock/gmock.h"
namespace base {
-class SingleThreadTaskRunner;
class TickClock;
}
@@ -33,8 +32,6 @@ class TestDataReductionProxyParams;
class TestDataReductionProxyConfig : public DataReductionProxyConfig {
public:
TestDataReductionProxyConfig(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
DataReductionProxyConfigurator* configurator);
// Creates a |TestDataReductionProxyConfig| with the provided |config_values|.
@@ -42,8 +39,6 @@ class TestDataReductionProxyConfig : public DataReductionProxyConfig {
// DataReductionProxyParams or DataReductionProxyMutableConfigValues).
TestDataReductionProxyConfig(
std::unique_ptr<DataReductionProxyConfigValues> config_values,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
DataReductionProxyConfigurator* configurator);
~TestDataReductionProxyConfig() override;
@@ -132,8 +127,6 @@ class MockDataReductionProxyConfig : public TestDataReductionProxyConfig {
// Creates a |MockDataReductionProxyConfig|.
MockDataReductionProxyConfig(
std::unique_ptr<DataReductionProxyConfigValues> config_values,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
DataReductionProxyConfigurator* configurator);
~MockDataReductionProxyConfig() override;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index f832c583fc8..8912c13b954 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -44,7 +44,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/variations/variations_associated_data.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
@@ -117,10 +117,6 @@ class DataReductionProxyConfigTest : public testing::Test {
test_config()->ResetParamFlagsForTest();
}
- scoped_refptr<base::SingleThreadTaskRunner> task_runner() {
- return task_environment_.GetMainThreadTaskRunner();
- }
-
class TestResponder {
public:
void ExecuteCallback(SecureProxyCheckerCallback callback) {
@@ -173,7 +169,6 @@ class DataReductionProxyConfigTest : public testing::Test {
std::unique_ptr<DataReductionProxyConfig> BuildConfig(
std::unique_ptr<DataReductionProxyParams> params) {
return std::make_unique<DataReductionProxyConfig>(
- task_runner(), task_runner(),
network::TestNetworkConnectionTracker::GetInstance(), std::move(params),
test_context_->configurator());
}
@@ -205,8 +200,8 @@ class DataReductionProxyConfigTest : public testing::Test {
return test_context_->GetConfiguredProxiesForHttp();
}
- content::TestBrowserThreadBundle task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ content::BrowserTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
std::unique_ptr<DataReductionProxyTestContext> test_context_;
@@ -420,13 +415,11 @@ TEST_F(DataReductionProxyConfigTest, WarmupURL) {
base::FieldTrialList::CreateFieldTrial(params::GetQuicFieldTrialName(),
"Enabled");
- TestDataReductionProxyConfig config(task_runner(), task_runner(),
- configurator());
+ TestDataReductionProxyConfig config(configurator());
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), test_context_->pref_service(),
- test_context_->task_runner());
- config.InitializeOnIOThread(
+ base::DefaultClock::GetInstance(), test_context_->pref_service());
+ config.Initialize(
test_context_->url_loader_factory(),
base::BindRepeating([](const std::vector<DataReductionProxyServer>&) {
return network::mojom::CustomProxyConfig::New();
@@ -764,7 +757,6 @@ TEST_F(DataReductionProxyConfigTest,
ASSERT_LT(0U, expected_proxies.size());
DataReductionProxyConfig config(
- task_runner(), task_runner(),
network::TestNetworkConnectionTracker::GetInstance(), std::move(params),
configurator());
@@ -824,7 +816,6 @@ TEST_F(DataReductionProxyConfigTest,
config_values->UpdateValues(proxies_for_http);
std::unique_ptr<DataReductionProxyConfig> config(new DataReductionProxyConfig(
- task_runner(), task_runner(),
network::TestNetworkConnectionTracker::GetInstance(),
std::move(config_values), configurator()));
for (const auto& test : tests) {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
index 93350599b93..0dc526f977b 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
@@ -10,7 +10,7 @@
#include "base/metrics/field_trial.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
@@ -31,8 +31,7 @@ class DataReductionProxyConfiguratorTest : public testing::Test {
void SetUp() override {
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
manager_.reset(new NetworkPropertiesManager(
- base::DefaultClock::GetInstance(), &test_prefs,
- base::ThreadTaskRunnerHandle::Get()));
+ base::DefaultClock::GetInstance(), &test_prefs));
manager_->OnChangeInNetworkID("test");
test_context_ = DataReductionProxyTestContext::Builder().Build();
@@ -102,7 +101,7 @@ class DataReductionProxyConfiguratorTest : public testing::Test {
}
TestingPrefServiceSimple test_prefs;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<DataReductionProxyTestContext> test_context_;
std::unique_ptr<DataReductionProxyConfigurator> config_;
std::unique_ptr<NetworkPropertiesManager> manager_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
index 20568493081..f782e632495 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_unittest.cc
@@ -10,7 +10,7 @@
#include <string>
#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "net/base/request_priority.h"
#include "net/nqe/effective_connection_type.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -26,8 +26,8 @@ class DataReductionProxyDataTest : public testing::Test {
DataReductionProxyDataTest() {}
private:
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
};
TEST_F(DataReductionProxyDataTest, BasicSettersAndGetters) {
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
deleted file mode 100644
index 5984d33fb05..00000000000
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ /dev/null
@@ -1,440 +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 "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/default_clock.h"
-#include "base/time/time.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
-#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_request_headers.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/mojom/network_context.mojom.h"
-
-namespace data_reduction_proxy {
-
-DataReductionProxyIOData::DataReductionProxyIOData(
- Client client,
- PrefService* prefs,
- network::NetworkConnectionTracker* network_connection_tracker,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- bool enabled,
- const std::string& user_agent,
- const std::string& channel)
- : client_(client),
- network_connection_tracker_(network_connection_tracker),
- io_task_runner_(io_task_runner),
- ui_task_runner_(ui_task_runner),
- enabled_(enabled),
- channel_(channel),
- effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
- DCHECK(io_task_runner_);
- DCHECK(ui_task_runner_);
- configurator_.reset(new DataReductionProxyConfigurator());
- configurator_->SetConfigUpdatedCallback(base::BindRepeating(
- &DataReductionProxyIOData::OnProxyConfigUpdated, base::Unretained(this)));
- DataReductionProxyMutableConfigValues* raw_mutable_config = nullptr;
- std::unique_ptr<DataReductionProxyMutableConfigValues> mutable_config =
- std::make_unique<DataReductionProxyMutableConfigValues>();
- raw_mutable_config = mutable_config.get();
- config_.reset(new DataReductionProxyConfig(
- io_task_runner, ui_task_runner, network_connection_tracker_,
- std::move(mutable_config), configurator_.get()));
- request_options_.reset(
- new DataReductionProxyRequestOptions(client_, config_.get()));
- request_options_->Init();
- // It is safe to use base::Unretained here, since it gets executed
- // synchronously on the IO thread, and |this| outlives the caller (since the
- // caller is owned by |this|.
- request_options_->SetUpdateHeaderCallback(base::BindRepeating(
- &DataReductionProxyIOData::UpdateProxyRequestHeaders,
- base::Unretained(this)));
-
- // It is safe to use base::Unretained here, since it gets executed
- // synchronously on the IO thread, and |this| outlives the caller (since the
- // caller is owned by |this|.
- if (!params::IsIncludedInHoldbackFieldTrial()) {
- config_client_.reset(new DataReductionProxyConfigServiceClient(
- GetBackoffPolicy(), request_options_.get(), raw_mutable_config,
- config_.get(), this, network_connection_tracker_,
- base::BindRepeating(&DataReductionProxyIOData::StoreSerializedConfig,
- base::Unretained(this))));
- }
-
- network_properties_manager_.reset(new NetworkPropertiesManager(
- base::DefaultClock::GetInstance(), prefs, ui_task_runner_));
-}
-
-DataReductionProxyIOData::DataReductionProxyIOData(
- PrefService* prefs,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : client_(Client::UNKNOWN),
- network_connection_tracker_(nullptr),
- io_task_runner_(io_task_runner),
- ui_task_runner_(ui_task_runner),
- effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
- DCHECK(ui_task_runner_);
- DCHECK(io_task_runner_);
- network_properties_manager_.reset(new NetworkPropertiesManager(
- base::DefaultClock::GetInstance(), prefs, ui_task_runner_));
-}
-
-DataReductionProxyIOData::~DataReductionProxyIOData() {
- // Guaranteed to be destroyed on IO thread if the IO thread is still
- // available at the time of destruction. If the IO thread is unavailable,
- // then the destruction will happen on the UI thread.
-}
-
-void DataReductionProxyIOData::ShutdownOnUIThread() {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
- network_properties_manager_->ShutdownOnUIThread();
-}
-
-void DataReductionProxyIOData::SetDataReductionProxyService(
- base::WeakPtr<DataReductionProxyService> data_reduction_proxy_service,
- const std::string& user_agent) {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
- service_ = data_reduction_proxy_service;
- url_loader_factory_info_ = service_->url_loader_factory_info();
- // Using base::Unretained is safe here, unless the browser is being shut down
- // before the Initialize task can be executed. The task is only created as
- // part of class initialization.
- if (io_task_runner_->BelongsToCurrentThread()) {
- InitializeOnIOThread(user_agent);
- return;
- }
- io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyIOData::InitializeOnIOThread,
- base::Unretained(this), user_agent));
-}
-
-void DataReductionProxyIOData::InitializeOnIOThread(
- const std::string& user_agent) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- DCHECK(network_properties_manager_);
-
- DCHECK(url_loader_factory_info_);
- auto url_loader_factory = network::SharedURLLoaderFactory::Create(
- std::move(url_loader_factory_info_));
-
- config_->InitializeOnIOThread(
- url_loader_factory,
- base::BindRepeating(&DataReductionProxyIOData::CreateCustomProxyConfig,
- base::Unretained(this), true),
- network_properties_manager_.get(), user_agent);
- if (config_client_)
- config_client_->InitializeOnIOThread(url_loader_factory);
- if (ui_task_runner_->BelongsToCurrentThread()) {
- service_->SetIOData(weak_factory_.GetWeakPtr());
- return;
- }
- ui_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyService::SetIOData, service_,
- weak_factory_.GetWeakPtr()));
-}
-
-bool DataReductionProxyIOData::IsEnabled() const {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- return enabled_;
-}
-
-void DataReductionProxyIOData::SetPingbackReportingFraction(
- float pingback_reporting_fraction) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyService::SetPingbackReportingFraction,
- service_, pingback_reporting_fraction));
-}
-
-void DataReductionProxyIOData::DeleteBrowsingHistory(const base::Time start,
- const base::Time end) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- network_properties_manager_->DeleteHistory();
-}
-
-void DataReductionProxyIOData::OnCacheCleared(const base::Time start,
- const base::Time end) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- network_properties_manager_->DeleteHistory();
-}
-
-// TODO(kundaji): Rename this method to something more descriptive.
-// Bug http://crbug/488190.
-void DataReductionProxyIOData::SetProxyPrefs(bool enabled, bool at_startup) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- enabled_ = enabled;
- config_->SetProxyConfig(enabled, at_startup);
- if (config_client_) {
- config_client_->SetEnabled(enabled);
- if (enabled)
- config_client_->RetrieveConfig();
- }
-
- // If Data Saver is disabled, reset data reduction proxy state.
- if (!enabled) {
- if (proxy_config_client_)
- proxy_config_client_->ClearBadProxiesCache();
- }
-}
-
-void DataReductionProxyIOData::SetDataReductionProxyConfiguration(
- const std::string& serialized_config) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- if (config_client_)
- config_client_->ApplySerializedConfig(serialized_config);
-}
-
-void DataReductionProxyIOData::SetIgnoreLongTermBlackListRules(
- bool ignore_long_term_black_list_rules) {
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &DataReductionProxyService::SetIgnoreLongTermBlackListRules, service_,
- ignore_long_term_black_list_rules));
-}
-
-void DataReductionProxyIOData::UpdateDataUseForHost(int64_t network_bytes,
- int64_t original_bytes,
- const std::string& host) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyService::UpdateDataUseForHost, service_,
- network_bytes, original_bytes, host));
-}
-
-void DataReductionProxyIOData::UpdateContentLengths(
- int64_t data_used,
- int64_t original_size,
- bool data_reduction_proxy_enabled,
- DataReductionProxyRequestType request_type,
- const std::string& mime_type,
- bool is_user_traffic,
- data_use_measurement::DataUseUserData::DataUseContentType content_type,
- int32_t service_hash_code) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindRepeating(&DataReductionProxyService::UpdateContentLengths,
- service_, data_used, original_size,
- data_reduction_proxy_enabled, request_type, mime_type,
- is_user_traffic, content_type, service_hash_code));
-}
-
-void DataReductionProxyIOData::SetUnreachable(bool unreachable) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- ui_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyService::SetUnreachable,
- service_, unreachable));
-}
-
-void DataReductionProxyIOData::SetInt64Pref(const std::string& pref_path,
- int64_t value) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- ui_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyService::SetInt64Pref,
- service_, pref_path, value));
-}
-
-void DataReductionProxyIOData::SetStringPref(const std::string& pref_path,
- const std::string& value) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- ui_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyService::SetStringPref,
- service_, pref_path, value));
-}
-
-void DataReductionProxyIOData::StoreSerializedConfig(
- const std::string& serialized_config) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- SetStringPref(prefs::kDataReductionProxyConfig, serialized_config);
- SetInt64Pref(prefs::kDataReductionProxyLastConfigRetrievalTime,
- (base::Time::Now() - base::Time()).InMicroseconds());
-}
-
-void DataReductionProxyIOData::UpdateProxyRequestHeaders(
- const net::HttpRequestHeaders& headers) {
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyService::SetProxyRequestHeadersOnUI,
- service_, std::move(headers)));
- UpdateCustomProxyConfig();
-}
-
-void DataReductionProxyIOData::OnProxyConfigUpdated() {
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyService::SetConfiguredProxiesOnUI,
- service_, config_->GetAllConfiguredProxies(),
- config_->GetProxiesForHttp()));
- UpdateCustomProxyConfig();
- UpdateThrottleConfig();
-}
-
-network::mojom::CustomProxyConfigPtr
-DataReductionProxyIOData::CreateCustomProxyConfig(
- bool is_warmup_url,
- const std::vector<DataReductionProxyServer>& proxies_for_http) const {
- auto config = network::mojom::CustomProxyConfig::New();
- if (params::IsIncludedInHoldbackFieldTrial()) {
- config->rules =
- configurator_
- ->CreateProxyConfig(is_warmup_url,
- config_->GetNetworkPropertiesManager(),
- std::vector<DataReductionProxyServer>())
- .proxy_rules();
- } else {
- config->rules =
- configurator_
- ->CreateProxyConfig(is_warmup_url,
- config_->GetNetworkPropertiesManager(),
- proxies_for_http)
- .proxy_rules();
- }
-
- net::EffectiveConnectionType type = GetEffectiveConnectionType();
- if (type > net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
- DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_LAST, type);
- config->pre_cache_headers.SetHeader(
- chrome_proxy_ect_header(),
- net::GetNameForEffectiveConnectionType(type));
- }
-
- request_options_->AddRequestHeader(&config->post_cache_headers,
- base::nullopt);
-
- config->assume_https_proxies_support_quic = true;
- config->can_use_proxy_on_http_url_redirect_cycles = false;
-
- return config;
-}
-
-void DataReductionProxyIOData::UpdateCustomProxyConfig() {
- if (!proxy_config_client_)
- return;
-
- proxy_config_client_->OnCustomProxyConfigUpdated(CreateCustomProxyConfig(
- !base::FeatureList::IsEnabled(
- features::kDataReductionProxyDisableProxyFailedWarmup),
- config_->GetProxiesForHttp()));
-}
-
-void DataReductionProxyIOData::UpdateThrottleConfig() {
- if (drp_throttle_config_observers_.empty())
- return;
-
- auto config = CreateThrottleConfig();
-
- drp_throttle_config_observers_.ForAllPtrs(
- [&config](mojom::DataReductionProxyThrottleConfigObserver* observer) {
- observer->OnThrottleConfigChanged(config->Clone());
- });
-}
-
-mojom::DataReductionProxyThrottleConfigPtr
-DataReductionProxyIOData::CreateThrottleConfig() const {
- return DataReductionProxyThrottleManager::CreateConfig(
- config_->GetProxiesForHttp());
-}
-
-void DataReductionProxyIOData::OnEffectiveConnectionTypeChanged(
- net::EffectiveConnectionType type) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- effective_connection_type_ = type;
- UpdateCustomProxyConfig();
-}
-
-void DataReductionProxyIOData::OnRTTOrThroughputEstimatesComputed(
- base::TimeDelta http_rtt) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- config_->OnRTTOrThroughputEstimatesComputed(http_rtt);
-}
-
-net::EffectiveConnectionType
-DataReductionProxyIOData::GetEffectiveConnectionType() const {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- return effective_connection_type_;
-}
-
-void DataReductionProxyIOData::SetCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientPtrInfo config_client_info) {
- proxy_config_client_.Bind(std::move(config_client_info));
- UpdateCustomProxyConfig();
-}
-
-void DataReductionProxyIOData::MarkProxiesAsBad(
- base::TimeDelta bypass_duration,
- const net::ProxyList& bad_proxies,
- mojom::DataReductionProxy::MarkProxiesAsBadCallback callback) {
- // Sanity check the inputs, as this data may originate from a lower-privilege
- // process (renderer).
-
- if (bypass_duration < base::TimeDelta()) {
- LOG(ERROR) << "Received bad MarkProxiesAsBad() -- invalid bypass_duration: "
- << bypass_duration;
- std::move(callback).Run();
- return;
- }
-
- // Limit maximum bypass duration to a day.
- if (bypass_duration > base::TimeDelta::FromDays(1))
- bypass_duration = base::TimeDelta::FromDays(1);
-
- // |bad_proxies| should be DRP servers or this API allows marking arbitrary
- // proxies as bad. It is possible that proxies from an older config are
- // received (FindConfiguredDataReductionProxy() searches recent proxies too).
- for (const auto& proxy : bad_proxies.GetAll()) {
- if (!config_->FindConfiguredDataReductionProxy(proxy)) {
- LOG(ERROR) << "Received bad MarkProxiesAsBad() -- not a DRP server: "
- << proxy.ToURI();
- std::move(callback).Run();
- return;
- }
- }
-
- proxy_config_client_->MarkProxiesAsBad(bypass_duration, bad_proxies,
- std::move(callback));
-}
-
-void DataReductionProxyIOData::AddThrottleConfigObserver(
- mojom::DataReductionProxyThrottleConfigObserverPtr observer) {
- observer->OnThrottleConfigChanged(CreateThrottleConfig());
- drp_throttle_config_observers_.AddPtr(std::move(observer));
-}
-
-void DataReductionProxyIOData::AddThrottleConfigObserverInfo(
- mojom::DataReductionProxyThrottleConfigObserverPtrInfo observer) {
- AddThrottleConfigObserver(
- mojom::DataReductionProxyThrottleConfigObserverPtr(std::move(observer)));
-}
-
-void DataReductionProxyIOData::Clone(mojom::DataReductionProxyRequest request) {
- drp_bindings_.AddBinding(this, std::move(request));
-}
-
-} // namespace data_reduction_proxy
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
deleted file mode 100644
index 30356175355..00000000000
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
+++ /dev/null
@@ -1,274 +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 COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_
-
-#include <stdint.h>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/gtest_prod_util.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 "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy.mojom.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
-#include "components/data_use_measurement/core/data_use_user_data.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
-#include "services/network/public/mojom/network_context.mojom.h"
-
-class PrefService;
-
-namespace network {
-class NetworkConnectionTracker;
-class SharedURLLoaderFactoryInfo;
-}
-
-namespace data_reduction_proxy {
-
-class DataReductionProxyConfig;
-class DataReductionProxyConfigServiceClient;
-class DataReductionProxyConfigurator;
-class DataReductionProxyServer;
-class DataReductionProxyService;
-class NetworkPropertiesManager;
-
-// Contains and initializes all Data Reduction Proxy objects that operate on
-// the IO thread.
-class DataReductionProxyIOData : public mojom::DataReductionProxy {
- public:
- // Constructs a DataReductionProxyIOData object. |enabled| sets the initial
- // state of the Data Reduction Proxy.
- DataReductionProxyIOData(
- Client client,
- PrefService* prefs,
- network::NetworkConnectionTracker* network_connection_tracker,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- bool enabled,
- const std::string& user_agent,
- const std::string& channel);
-
- ~DataReductionProxyIOData() override;
-
- // Performs UI thread specific shutdown logic.
- void ShutdownOnUIThread();
-
- // Sets the Data Reduction Proxy service after it has been created.
- // Virtual for testing.
- virtual void SetDataReductionProxyService(
- base::WeakPtr<DataReductionProxyService> data_reduction_proxy_service,
- const std::string& user_agent);
-
- // Sets user defined preferences for how the Data Reduction Proxy
- // configuration should be set. |at_startup| is true only
- // when DataReductionProxySettings is initialized.
- void SetProxyPrefs(bool enabled, bool at_startup);
-
- // Applies a serialized Data Reduction Proxy configuration.
- void SetDataReductionProxyConfiguration(const std::string& serialized_config);
-
- // When triggering previews, prevent long term black list rules. Overridden in
- // testing.
- virtual void SetIgnoreLongTermBlackListRules(
- bool ignore_long_term_black_list_rules);
-
- // Bridge methods to safely call to the UI thread objects.
- void UpdateDataUseForHost(int64_t network_bytes,
- int64_t original_bytes,
- const std::string& host);
- void UpdateContentLengths(
- int64_t data_used,
- int64_t original_size,
- bool data_reduction_proxy_enabled,
- DataReductionProxyRequestType request_type,
- const std::string& mime_type,
- bool is_user_traffic,
- data_use_measurement::DataUseUserData::DataUseContentType content_type,
- int32_t service_hash_code);
-
- // Returns true if the Data Reduction Proxy is enabled and false otherwise.
- bool IsEnabled() const;
-
- // Changes the reporting fraction for the pingback service to
- // |pingback_reporting_fraction|. Overridden in testing.
- virtual void SetPingbackReportingFraction(float pingback_reporting_fraction);
-
- // Called when the user clears the browsing history.
- void DeleteBrowsingHistory(const base::Time start, const base::Time end);
-
- // Notifies |this| that the user has requested to clear the browser
- // cache. This method is not called if only a subset of site entries are
- // cleared.
- void OnCacheCleared(const base::Time start, const base::Time end);
-
- // Forwards proxy authentication headers to the UI thread.
- void UpdateProxyRequestHeaders(const net::HttpRequestHeaders& headers);
-
- // Notifies |this| that there there is a change in the effective connection
- // type.
- void OnEffectiveConnectionTypeChanged(net::EffectiveConnectionType type);
-
- // Notifies |this| that there there is a change in the HTTP RTT estimate.
- void OnRTTOrThroughputEstimatesComputed(base::TimeDelta http_rtt);
-
- // Returns the current estimate of the effective connection type.
- net::EffectiveConnectionType GetEffectiveConnectionType() const;
-
- // Binds to a config client that can be used to update Data Reduction Proxy
- // settings when the network service is enabled.
- void SetCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientPtrInfo config_client_info);
-
- // Various accessor methods.
- DataReductionProxyConfigurator* configurator() const {
- return configurator_.get();
- }
-
- DataReductionProxyConfig* config() const {
- return config_.get();
- }
-
- DataReductionProxyRequestOptions* request_options() const {
- return request_options_.get();
- }
-
- DataReductionProxyConfigServiceClient* config_client() const {
- return config_client_.get();
- }
-
- mojom::DataReductionProxyThrottleConfigPtr CreateThrottleConfig() const;
-
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner() const {
- return io_task_runner_;
- }
-
- // The production channel of this build.
- std::string channel() const { return channel_; }
-
- // The Client type of this build.
- Client client() const { return client_; }
-
- // mojom::DataReductionProxy implementation:
- void MarkProxiesAsBad(base::TimeDelta bypass_duration,
- const net::ProxyList& bad_proxies,
- MarkProxiesAsBadCallback callback) override;
- void AddThrottleConfigObserver(
- mojom::DataReductionProxyThrottleConfigObserverPtr observer) override;
- void Clone(mojom::DataReductionProxyRequest request) override;
- void AddThrottleConfigObserverInfo(
- mojom::DataReductionProxyThrottleConfigObserverPtrInfo observer);
-
- private:
- friend class TestDataReductionProxyIOData;
- FRIEND_TEST_ALL_PREFIXES(DataReductionProxyIODataTest, TestConstruction);
- FRIEND_TEST_ALL_PREFIXES(DataReductionProxyIODataTest,
- TestResetBadProxyListOnDisableDataSaver);
-
- // Used for testing.
- DataReductionProxyIOData(
- PrefService* prefs,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
-
- // Initializes the weak pointer to |this| on the IO thread. It must be done
- // on the IO thread, since it is used for posting tasks from the UI thread
- // to IO thread objects in a thread safe manner.
- void InitializeOnIOThread(const std::string& user_agent);
-
- // Records that the data reduction proxy is unreachable or not.
- void SetUnreachable(bool unreachable);
-
- // Stores an int64_t value in preferences storage.
- void SetInt64Pref(const std::string& pref_path, int64_t value);
-
- // Stores a string value in preferences storage.
- void SetStringPref(const std::string& pref_path, const std::string& value);
-
- // Stores a serialized Data Reduction Proxy configuration in preferences
- // storage.
- void StoreSerializedConfig(const std::string& serialized_config);
-
- // Creates a config using |proxies_for_http| that can be sent to the
- // NetworkContext.
- network::mojom::CustomProxyConfigPtr CreateCustomProxyConfig(
- bool is_warmup_url,
- const std::vector<DataReductionProxyServer>& proxies_for_http) const;
-
- // Called when the list of proxies changes.
- void OnProxyConfigUpdated();
-
- // Should be called whenever there is a possible change to the custom proxy
- // config.
- void UpdateCustomProxyConfig();
-
- // Should be called whenever there is a possible change to the throttle
- // config.
- void UpdateThrottleConfig();
-
- // The type of Data Reduction Proxy client.
- const Client client_;
-
- // Parameters including DNS names and allowable configurations.
- std::unique_ptr<DataReductionProxyConfig> config_;
-
- // Setter of the Data Reduction Proxy-specific proxy configuration.
- std::unique_ptr<DataReductionProxyConfigurator> configurator_;
-
- // Data Reduction Proxy objects with a UI based lifetime.
- base::WeakPtr<DataReductionProxyService> service_;
-
- // Constructs credentials suitable for authenticating the client.
- std::unique_ptr<DataReductionProxyRequestOptions> request_options_;
-
- // Requests new Data Reduction Proxy configurations from a remote service.
- // May be null.
- std::unique_ptr<DataReductionProxyConfigServiceClient> config_client_;
-
- // Watches for network connection changes.
- network::NetworkConnectionTracker* network_connection_tracker_;
-
- // IO and UI task runners, respectively.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
-
- // Whether the Data Reduction Proxy has been enabled or not by the user. In
- // practice, this can be overridden by the command line.
- bool enabled_;
-
- // The network::SharedURLLoaderFactoryInfo used for making URL requests.
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_;
-
- // The production channel of this build.
- const std::string channel_;
-
- // Created on the UI thread. Guaranteed to be destroyed on IO thread if the
- // IO thread is still available at the time of destruction. If the IO thread
- // is unavailable, then the destruction will happen on the UI thread.
- std::unique_ptr<NetworkPropertiesManager> network_properties_manager_;
-
- // Current estimate of the effective connection type.
- net::EffectiveConnectionType effective_connection_type_;
-
- network::mojom::CustomProxyConfigClientPtr proxy_config_client_;
-
- mojo::BindingSet<mojom::DataReductionProxy> drp_bindings_;
-
- mojo::InterfacePtrSet<mojom::DataReductionProxyThrottleConfigObserver>
- drp_throttle_config_observers_;
-
- base::WeakPtrFactory<DataReductionProxyIOData> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(DataReductionProxyIOData);
-};
-
-} // namespace data_reduction_proxy
-#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
index d18748305a2..2abe27670e9 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
@@ -31,61 +31,8 @@ void RegisterSyncableProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterInt64Pref(prefs::kHttpOriginalContentLength, 0);
registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
- registry->RegisterInt64Pref(prefs::kDailyHttpOriginalContentLengthApplication,
- 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpOriginalContentLengthVideo, 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpOriginalContentLengthUnknown,
- 0L);
registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
- registry->RegisterInt64Pref(prefs::kDailyHttpReceivedContentLengthApplication,
- 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpReceivedContentLengthVideo, 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpReceivedContentLengthUnknown,
- 0L);
-
- registry->RegisterListPref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
- registry->RegisterInt64Pref(
- prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
- 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
- 0L);
- registry->RegisterListPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabled);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledApplication, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledUnknown, 0L);
- registry->RegisterListPref(
- prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxy);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyApplication, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyUnknown, 0L);
- registry->RegisterListPref(prefs::kDailyContentLengthViaDataReductionProxy);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthViaDataReductionProxyApplication, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthViaDataReductionProxyVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthViaDataReductionProxyUnknown, 0L);
registry->RegisterInt64Pref(prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
registry->RegisterStringPref(prefs::kDataReductionProxyConfig, std::string());
@@ -130,59 +77,7 @@ void RegisterPrefs(PrefRegistrySimple* registry) {
prefs::kHttpOriginalContentLength, 0);
registry->RegisterListPref(
prefs::kDailyHttpOriginalContentLength);
- registry->RegisterInt64Pref(prefs::kDailyHttpOriginalContentLengthApplication,
- 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpOriginalContentLengthVideo, 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpOriginalContentLengthUnknown,
- 0L);
registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
- registry->RegisterInt64Pref(prefs::kDailyHttpReceivedContentLengthApplication,
- 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpReceivedContentLengthVideo, 0L);
- registry->RegisterInt64Pref(prefs::kDailyHttpReceivedContentLengthUnknown,
- 0L);
- registry->RegisterListPref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
- registry->RegisterInt64Pref(
- prefs::
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
- 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
- 0L);
- registry->RegisterListPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabled);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledApplication, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabledUnknown, 0L);
- registry->RegisterListPref(
- prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxy);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyApplication, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxyUnknown, 0L);
- registry->RegisterListPref(prefs::kDailyContentLengthViaDataReductionProxy);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthViaDataReductionProxyApplication, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthViaDataReductionProxyVideo, 0L);
- registry->RegisterInt64Pref(
- prefs::kDailyContentLengthViaDataReductionProxyUnknown, 0L);
registry->RegisterInt64Pref(
prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
registry->RegisterStringPref(prefs::kDataReductionProxyConfig, std::string());
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc
index 52730fe1194..62a3ae14b2c 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc
@@ -66,21 +66,6 @@ class DataReductionProxyPrefsTest : public testing::Test {
registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength);
registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength);
- registry->RegisterListPref(
- prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled);
- registry->RegisterListPref(
- prefs::kDailyOriginalContentLengthViaDataReductionProxy);
- registry->RegisterListPref(prefs::kDailyContentLengthViaDataReductionProxy);
registry->RegisterInt64Pref(
prefs::kDailyHttpContentLengthLastUpdateDate, 0L);
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
index bdb5fc29558..e1ad07bd133 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc
@@ -159,7 +159,8 @@ void DataReductionProxyRequestOptions::UpdateCredentials() {
RegenerateRequestHeaderValue();
}
-void DataReductionProxyRequestOptions::SetKeyOnIO(const std::string& key) {
+void DataReductionProxyRequestOptions::SetKeyForTesting(
+ const std::string& key) {
DCHECK(thread_checker_.CalledOnValidThread());
if(!key.empty()) {
key_ = key;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
index d8b2debcffd..6b07e18ba58 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h
@@ -78,8 +78,8 @@ class DataReductionProxyRequestOptions {
// have a default key defined, this function will be called some time after
// this class has been constructed. Android WebView is a platform that does
// this. The caller needs to make sure |this| pointer is valid when
- // SetKeyOnIO is called.
- void SetKeyOnIO(const std::string& key);
+ // SetKey is called.
+ void SetKeyForTesting(const std::string& key);
// Sets the credentials for sending to the Data Reduction Proxy.
void SetSecureSession(const std::string& secure_session);
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
index 32ed7ef1180..e57b6b3ff9a 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
@@ -15,7 +15,7 @@
#include "base/metrics/field_trial.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
@@ -173,14 +173,14 @@ class DataReductionProxyRequestOptionsTest : public testing::Test {
EXPECT_EQ(expected_header, header_value);
}
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
std::unique_ptr<TestDataReductionProxyRequestOptions> request_options_;
std::unique_ptr<DataReductionProxyTestContext> test_context_;
net::HttpRequestHeaders callback_headers_;
};
-TEST_F(DataReductionProxyRequestOptionsTest, AuthorizationOnIOThread) {
+TEST_F(DataReductionProxyRequestOptionsTest, Authorization) {
std::string expected_header;
SetHeaderExpectations(std::string(), kClientStr, kExpectedBuild,
kExpectedPatch, kPageId, std::string(),
@@ -195,7 +195,7 @@ TEST_F(DataReductionProxyRequestOptionsTest, AuthorizationOnIOThread) {
test_context_->RunUntilIdle();
// Now set a key.
- request_options()->SetKeyOnIO(kTestKey2);
+ request_options()->SetKeyForTesting(kTestKey2);
// Write headers.
VerifyExpectedHeader(expected_header, kPageIdValue);
@@ -211,7 +211,7 @@ TEST_F(DataReductionProxyRequestOptionsTest, AuthorizationIgnoresEmptyKey) {
// Now set an empty key. The auth handler should ignore that, and the key
// remains |kTestKey|.
- request_options()->SetKeyOnIO(std::string());
+ request_options()->SetKeyForTesting(std::string());
VerifyExpectedHeader(expected_header, kPageIdValue);
}
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
index 337738c1c0f..4a80db2904a 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
@@ -14,21 +14,28 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
+#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/browser/data_store.h"
+#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
#include "components/data_reduction_proxy/proto/data_store.pb.h"
#include "components/data_use_measurement/core/data_use_measurement.h"
#include "components/prefs/pref_service.h"
-#include "services/network/public/cpp/features.h"
+#include "components/previews/core/previews_experiments.h"
namespace data_reduction_proxy {
@@ -41,26 +48,79 @@ DataReductionProxyService::DataReductionProxyService(
network::NetworkQualityTracker* network_quality_tracker,
network::NetworkConnectionTracker* network_connection_tracker,
data_use_measurement::DataUseMeasurement* data_use_measurement,
- const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
- const base::TimeDelta& commit_delay)
+ const base::TimeDelta& commit_delay,
+ Client client,
+ const std::string& channel,
+ const std::string& user_agent)
: url_loader_factory_(std::move(url_loader_factory)),
pingback_client_(std::move(pingback_client)),
settings_(settings),
prefs_(prefs),
db_data_owner_(new DBDataOwner(std::move(store))),
- ui_task_runner_(ui_task_runner),
- io_task_runner_(io_task_runner),
db_task_runner_(db_task_runner),
- initialized_(false),
network_quality_tracker_(network_quality_tracker),
network_connection_tracker_(network_connection_tracker),
data_use_measurement_(data_use_measurement),
- effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
+ effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
+ client_(client),
+ channel_(channel) {
DCHECK(settings);
DCHECK(network_quality_tracker_);
DCHECK(network_connection_tracker_);
+
+ configurator_ = std::make_unique<DataReductionProxyConfigurator>();
+ // It is safe to use base::Unretained here, since it gets executed
+ // synchronously on the UI thread, and |this| outlives the caller (since the
+ // caller is owned by |this|.
+ configurator_->SetConfigUpdatedCallback(
+ base::BindRepeating(&DataReductionProxyService::OnProxyConfigUpdated,
+ base::Unretained(this)));
+ DataReductionProxyMutableConfigValues* raw_mutable_config = nullptr;
+ std::unique_ptr<DataReductionProxyMutableConfigValues> mutable_config =
+ std::make_unique<DataReductionProxyMutableConfigValues>();
+ raw_mutable_config = mutable_config.get();
+ config_ = std::make_unique<DataReductionProxyConfig>(
+ network_connection_tracker_, std::move(mutable_config),
+ configurator_.get());
+ request_options_ = std::make_unique<DataReductionProxyRequestOptions>(
+ client_, config_.get());
+ request_options_->Init();
+ // It is safe to use base::Unretained here, since it gets executed
+ // synchronously on the UI thread, and |this| outlives the caller (since the
+ // caller is owned by |this|.
+ request_options_->SetUpdateHeaderCallback(
+ base::BindRepeating(&DataReductionProxyService::UpdateProxyRequestHeaders,
+ base::Unretained(this)));
+
+ // It is safe to use base::Unretained here, since it gets executed
+ // synchronously on the UI thread, and |this| outlives the caller (since the
+ // caller is owned by |this|.
+ if (!params::IsIncludedInHoldbackFieldTrial() ||
+ previews::params::IsLitePageServerPreviewsEnabled()) {
+ config_client_ = std::make_unique<DataReductionProxyConfigServiceClient>(
+ GetBackoffPolicy(), request_options_.get(), raw_mutable_config,
+ config_.get(), this, network_connection_tracker_,
+ base::BindRepeating(&DataReductionProxyService::StoreSerializedConfig,
+ base::Unretained(this)));
+ }
+
+ network_properties_manager_ = std::make_unique<NetworkPropertiesManager>(
+ base::DefaultClock::GetInstance(), prefs);
+
+ // It is safe to use base::Unretained here, since it gets executed
+ // synchronously on the UI thread, and |this| outlives the caller (since the
+ // caller is owned by |this|.
+ config_->Initialize(
+ url_loader_factory_,
+ base::BindRepeating(&DataReductionProxyService::CreateCustomProxyConfig,
+ base::Unretained(this), true),
+ network_properties_manager_.get(), user_agent);
+ if (config_client_)
+ config_client_->Initialize(url_loader_factory_);
+
+ ReadPersistedClientConfig();
+
db_task_runner_->PostTask(FROM_HERE,
base::BindOnce(&DBDataOwner::InitializeOnDBThread,
db_data_owner_->GetWeakPtr()));
@@ -70,8 +130,7 @@ DataReductionProxyService::DataReductionProxyService(
}
network_quality_tracker_->AddEffectiveConnectionTypeObserver(this);
network_quality_tracker_->AddRTTAndThroughputEstimatesObserver(this);
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- data_use_measurement_) { // null in unit tests.
+ if (data_use_measurement_) { // null in unit tests.
data_use_measurement_->AddServicesDataUseObserver(this);
}
@@ -90,31 +149,11 @@ DataReductionProxyService::~DataReductionProxyService() {
network_connection_tracker_->RemoveNetworkConnectionObserver(this);
compression_stats_.reset();
db_task_runner_->DeleteSoon(FROM_HERE, db_data_owner_.release());
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- data_use_measurement_) { // null in unit tests.
+ if (data_use_measurement_) { // null in unit tests.
data_use_measurement_->RemoveServicesDataUseObserver(this);
}
}
-void DataReductionProxyService::SetIOData(
- base::WeakPtr<DataReductionProxyIOData> io_data) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- io_data_ = io_data;
- initialized_ = true;
-
- // Notify IO data of the current network quality estimates.
- OnEffectiveConnectionTypeChanged(effective_connection_type_);
- if (http_rtt_) {
- OnRTTOrThroughputEstimatesComputed(http_rtt_.value(), base::TimeDelta(),
- INT32_MAX);
- }
-
- for (DataReductionProxyServiceObserver& observer : observer_list_)
- observer.OnServiceInitialized();
-
- ReadPersistedClientConfig();
-}
-
void DataReductionProxyService::ReadPersistedClientConfig() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -141,11 +180,8 @@ void DataReductionProxyService::ReadPersistedClientConfig() {
if (config_value.empty())
return;
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &DataReductionProxyIOData::SetDataReductionProxyConfiguration,
- io_data_, config_value));
+ if (config_client_)
+ config_client_->ApplySerializedConfig(config_value);
}
void DataReductionProxyService::OnConnectionChanged(
@@ -159,12 +195,7 @@ void DataReductionProxyService::OnEffectiveConnectionTypeChanged(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
effective_connection_type_ = type;
-
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &DataReductionProxyIOData::OnEffectiveConnectionTypeChanged, io_data_,
- type));
+ UpdateCustomProxyConfig();
}
void DataReductionProxyService::OnRTTOrThroughputEstimatesComputed(
@@ -172,14 +203,8 @@ void DataReductionProxyService::OnRTTOrThroughputEstimatesComputed(
base::TimeDelta transport_rtt,
int32_t downstream_throughput_kbps) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
http_rtt_ = http_rtt;
-
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &DataReductionProxyIOData::OnRTTOrThroughputEstimatesComputed,
- io_data_, http_rtt));
+ config_->OnRTTOrThroughputEstimatesComputed(http_rtt);
}
void DataReductionProxyService::Shutdown() {
@@ -233,13 +258,18 @@ void DataReductionProxyService::SetStringPref(const std::string& pref_path,
void DataReductionProxyService::SetProxyPrefs(bool enabled, bool at_startup) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (io_task_runner_->BelongsToCurrentThread()) {
- io_data_->SetProxyPrefs(enabled, at_startup);
- return;
+ config_->SetProxyConfig(enabled, at_startup);
+ if (config_client_) {
+ config_client_->SetEnabled(enabled);
+ if (enabled)
+ config_client_->RetrieveConfig();
+ }
+
+ // If Data Saver is disabled, reset data reduction proxy state.
+ if (!enabled) {
+ for (auto& client : proxy_config_clients_)
+ client->ClearBadProxiesCache();
}
- io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyIOData::SetProxyPrefs,
- io_data_, enabled, at_startup));
}
void DataReductionProxyService::SetPingbackReportingFraction(
@@ -251,9 +281,7 @@ void DataReductionProxyService::SetPingbackReportingFraction(
void DataReductionProxyService::OnCacheCleared(const base::Time start,
const base::Time end) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyIOData::OnCacheCleared,
- io_data_, start, end));
+ network_properties_manager_->DeleteHistory();
}
net::EffectiveConnectionType
@@ -274,18 +302,17 @@ base::Optional<base::TimeDelta> DataReductionProxyService::GetHttpRttEstimate()
return http_rtt_;
}
-void DataReductionProxyService::SetProxyRequestHeadersOnUI(
+void DataReductionProxyService::UpdateProxyRequestHeaders(
const net::HttpRequestHeaders& headers) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
settings_->SetProxyRequestHeaders(headers);
+ UpdateCustomProxyConfig();
}
-void DataReductionProxyService::SetConfiguredProxiesOnUI(
- const net::ProxyList& proxies,
- const std::vector<DataReductionProxyServer>& proxies_for_http) {
+void DataReductionProxyService::OnProxyConfigUpdated() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- settings_->SetConfiguredProxies(proxies);
- settings_->SetProxiesForHttp(proxies_for_http);
+ UpdateCustomProxyConfig();
+ UpdateThrottleConfig();
}
void DataReductionProxyService::SetIgnoreLongTermBlackListRules(
@@ -294,12 +321,10 @@ void DataReductionProxyService::SetIgnoreLongTermBlackListRules(
settings_->SetIgnoreLongTermBlackListRules(ignore_long_term_black_list_rules);
}
-void DataReductionProxyService::SetCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientPtrInfo config_client_info) {
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyIOData::SetCustomProxyConfigClient,
- io_data_, std::move(config_client_info)));
+void DataReductionProxyService::AddCustomProxyConfigClient(
+ mojo::Remote<network::mojom::CustomProxyConfigClient> config_client) {
+ proxy_config_clients_.Add(std::move(config_client));
+ UpdateCustomProxyConfig();
}
void DataReductionProxyService::LoadHistoricalDataUsage(
@@ -348,27 +373,7 @@ void DataReductionProxyService::DeleteBrowsingHistory(const base::Time& start,
FROM_HERE, base::BindOnce(&DBDataOwner::DeleteBrowsingHistory,
db_data_owner_->GetWeakPtr(), start, end));
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyIOData::DeleteBrowsingHistory, io_data_,
- start, end));
-}
-
-void DataReductionProxyService::AddObserver(
- DataReductionProxyServiceObserver* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- observer_list_.AddObserver(observer);
-}
-
-void DataReductionProxyService::RemoveObserver(
- DataReductionProxyServiceObserver* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- observer_list_.RemoveObserver(observer);
-}
-
-bool DataReductionProxyService::Initialized() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return initialized_;
+ network_properties_manager_->DeleteHistory();
}
base::WeakPtr<DataReductionProxyService>
@@ -384,7 +389,6 @@ void DataReductionProxyService::OnServicesDataUse(int32_t service_hash_code,
if (compression_stats_) {
// Record non-content initiated traffic to the Other bucket for data saver
// site-breakdown.
- DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
compression_stats_->RecordDataUseByHost(
util::GetSiteBreakdownOtherHostName(), sent_bytes, sent_bytes,
base::Time::Now());
@@ -402,28 +406,151 @@ void DataReductionProxyService::MarkProxiesAsBad(
base::TimeDelta bypass_duration,
const net::ProxyList& bad_proxies,
MarkProxiesAsBadCallback callback) {
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &DataReductionProxyIOData::MarkProxiesAsBad, io_data_,
- bypass_duration, bad_proxies,
- base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask),
- ui_task_runner_, FROM_HERE, std::move(callback))));
+ // Sanity check the inputs, as this data may originate from a lower-privilege
+ // process (renderer).
+
+ if (bypass_duration < base::TimeDelta()) {
+ LOG(ERROR) << "Received bad MarkProxiesAsBad() -- invalid bypass_duration: "
+ << bypass_duration;
+ std::move(callback).Run();
+ return;
+ }
+
+ // Limit maximum bypass duration to a day.
+ if (bypass_duration > base::TimeDelta::FromDays(1))
+ bypass_duration = base::TimeDelta::FromDays(1);
+
+ // |bad_proxies| should be DRP servers or this API allows marking arbitrary
+ // proxies as bad. It is possible that proxies from an older config are
+ // received (FindConfiguredDataReductionProxy() searches recent proxies too).
+ for (const auto& proxy : bad_proxies.GetAll()) {
+ if (!config_->FindConfiguredDataReductionProxy(proxy)) {
+ LOG(ERROR) << "Received bad MarkProxiesAsBad() -- not a DRP server: "
+ << proxy.ToURI();
+ std::move(callback).Run();
+ return;
+ }
+ }
+
+ for (auto& client : proxy_config_clients_)
+ client->MarkProxiesAsBad(bypass_duration, bad_proxies, std::move(callback));
}
void DataReductionProxyService::AddThrottleConfigObserver(
mojom::DataReductionProxyThrottleConfigObserverPtr observer) {
- io_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&DataReductionProxyIOData::AddThrottleConfigObserverInfo,
- io_data_, observer.PassInterface()));
+ observer->OnThrottleConfigChanged(CreateThrottleConfig());
+ drp_throttle_config_observers_.AddPtr(std::move(observer));
}
void DataReductionProxyService::Clone(
mojom::DataReductionProxyRequest request) {
- io_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DataReductionProxyIOData::Clone, io_data_,
- std::move(request)));
+ drp_bindings_.AddBinding(this, std::move(request));
+}
+
+void DataReductionProxyService::UpdateCustomProxyConfig() {
+ if (params::IsIncludedInHoldbackFieldTrial())
+ return;
+
+ network::mojom::CustomProxyConfigPtr config = CreateCustomProxyConfig(
+ !base::FeatureList::IsEnabled(
+ features::kDataReductionProxyDisableProxyFailedWarmup),
+ config_->GetProxiesForHttp());
+ for (auto& client : proxy_config_clients_)
+ client->OnCustomProxyConfigUpdated(config->Clone());
+}
+
+void DataReductionProxyService::UpdateThrottleConfig() {
+ if (drp_throttle_config_observers_.empty())
+ return;
+
+ auto config = CreateThrottleConfig();
+
+ drp_throttle_config_observers_.ForAllPtrs(
+ [&config](mojom::DataReductionProxyThrottleConfigObserver* observer) {
+ observer->OnThrottleConfigChanged(config->Clone());
+ });
+}
+
+mojom::DataReductionProxyThrottleConfigPtr
+DataReductionProxyService::CreateThrottleConfig() const {
+ return DataReductionProxyThrottleManager::CreateConfig(
+ config_->GetProxiesForHttp());
+}
+
+network::mojom::CustomProxyConfigPtr
+DataReductionProxyService::CreateCustomProxyConfig(
+ bool is_warmup_url,
+ const std::vector<DataReductionProxyServer>& proxies_for_http) const {
+ auto config = network::mojom::CustomProxyConfig::New();
+ if (params::IsIncludedInHoldbackFieldTrial()) {
+ config->rules =
+ configurator_
+ ->CreateProxyConfig(is_warmup_url,
+ config_->GetNetworkPropertiesManager(),
+ std::vector<DataReductionProxyServer>())
+ .proxy_rules();
+ } else {
+ config->rules =
+ configurator_
+ ->CreateProxyConfig(is_warmup_url,
+ config_->GetNetworkPropertiesManager(),
+ proxies_for_http)
+ .proxy_rules();
+ }
+
+ net::EffectiveConnectionType type = GetEffectiveConnectionType();
+ if (type > net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
+ DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_LAST, type);
+ config->pre_cache_headers.SetHeader(
+ chrome_proxy_ect_header(),
+ net::GetNameForEffectiveConnectionType(type));
+ }
+
+ request_options_->AddRequestHeader(&config->post_cache_headers,
+ base::nullopt);
+
+ config->assume_https_proxies_support_quic = true;
+ config->can_use_proxy_on_http_url_redirect_cycles = false;
+
+ return config;
+}
+
+void DataReductionProxyService::StoreSerializedConfig(
+ const std::string& serialized_config) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!params::IsIncludedInHoldbackFieldTrial() ||
+ previews::params::IsLitePageServerPreviewsEnabled());
+
+ SetStringPref(prefs::kDataReductionProxyConfig, serialized_config);
+ SetInt64Pref(prefs::kDataReductionProxyLastConfigRetrievalTime,
+ (base::Time::Now() - base::Time()).InMicroseconds());
+}
+
+void DataReductionProxyService::SetDependenciesForTesting(
+ std::unique_ptr<DataReductionProxyConfig> config,
+ std::unique_ptr<DataReductionProxyRequestOptions> request_options,
+ std::unique_ptr<DataReductionProxyConfigurator> configurator,
+ std::unique_ptr<DataReductionProxyConfigServiceClient> config_client) {
+ config_ = std::move(config);
+ config_->Initialize(
+ url_loader_factory_,
+ base::BindRepeating(&DataReductionProxyService::CreateCustomProxyConfig,
+ base::Unretained(this), true),
+ network_properties_manager_.get(), std::string());
+
+ request_options_ = std::move(request_options);
+ request_options_->SetUpdateHeaderCallback(
+ base::BindRepeating(&DataReductionProxyService::UpdateProxyRequestHeaders,
+ base::Unretained(this)));
+
+ configurator_ = std::move(configurator);
+ configurator_->SetConfigUpdatedCallback(
+ base::BindRepeating(&DataReductionProxyService::OnProxyConfigUpdated,
+ base::Unretained(this)));
+
+ config_client_ = std::move(config_client);
+ if (config_client_)
+ config_client_->Initialize(url_loader_factory_);
}
} // namespace data_reduction_proxy
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
index b57fe63ea0f..8feef2884d4 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
@@ -15,24 +15,25 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/browser/db_data_owner.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy.mojom.h"
#include "components/data_use_measurement/core/data_use_measurement.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/remote_set.h"
#include "net/nqe/effective_connection_type.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/network/public/cpp/network_quality_tracker.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/mojom/network_context.mojom-forward.h"
+#include "services/network/public/mojom/network_context.mojom.h"
class PrefService;
namespace base {
class SequencedTaskRunner;
-class SingleThreadTaskRunner;
class TimeDelta;
}
@@ -44,10 +45,13 @@ class ProxyList;
namespace data_reduction_proxy {
class DataReductionProxyCompressionStats;
-class DataReductionProxyIOData;
-class DataReductionProxyServiceObserver;
-class DataReductionProxySettings;
+class DataReductionProxyConfig;
+class DataReductionProxyConfigServiceClient;
+class DataReductionProxyConfigurator;
+class DataReductionProxyRequestOptions;
class DataReductionProxyServer;
+class DataReductionProxySettings;
+class NetworkPropertiesManager;
// Contains and initializes all Data Reduction Proxy objects that have a
// lifetime based on the UI thread.
@@ -73,22 +77,16 @@ class DataReductionProxyService
network::NetworkQualityTracker* network_quality_tracker,
network::NetworkConnectionTracker* network_connection_tracker,
data_use_measurement::DataUseMeasurement* data_use_measurement,
- const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
- const base::TimeDelta& commit_delay);
+ const base::TimeDelta& commit_delay,
+ Client client,
+ const std::string& channel,
+ const std::string& user_agent);
~DataReductionProxyService() override;
- // Sets the DataReductionProxyIOData weak pointer.
- void SetIOData(base::WeakPtr<DataReductionProxyIOData> io_data);
-
void Shutdown();
- // Indicates whether |this| has been fully initialized. |SetIOData| is the
- // final step in initialization.
- bool Initialized() const;
-
// Records data usage per host.
// Virtual for testing.
virtual void UpdateDataUseForHost(int64_t network_bytes,
@@ -128,12 +126,8 @@ class DataReductionProxyService
void DeleteHistoricalDataUsage();
void DeleteBrowsingHistory(const base::Time& start, const base::Time& end);
- // Methods for adding/removing observers on |this|.
- void AddObserver(DataReductionProxyServiceObserver* observer);
- void RemoveObserver(DataReductionProxyServiceObserver* observer);
-
- // Sets the reporting fraction in the pingback client.
- void SetPingbackReportingFraction(float pingback_reporting_fraction);
+ // Sets the reporting fraction in the pingback client. Virtual for testing.
+ virtual void SetPingbackReportingFraction(float pingback_reporting_fraction);
// Sets |pingback_client_| to be used for testing purposes.
void SetPingbackClientForTesting(
@@ -141,13 +135,19 @@ class DataReductionProxyService
pingback_client_.reset(pingback_client);
}
+ void SetSettingsForTesting(DataReductionProxySettings* settings) {
+ settings_ = settings;
+ }
+
// Notifies |this| that the user has requested to clear the browser
// cache. This method is not called if only a subset of site entries are
// cleared.
void OnCacheCleared(const base::Time start, const base::Time end);
- // When triggering previews, prevent long term black list rules.
- void SetIgnoreLongTermBlackListRules(bool ignore_long_term_black_list_rules);
+ // When triggering previews, prevent long term black list rules. Virtual for
+ // testing.
+ virtual void SetIgnoreLongTermBlackListRules(
+ bool ignore_long_term_black_list_rules);
// Returns the current network quality estimates.
net::EffectiveConnectionType GetEffectiveConnectionType() const;
@@ -156,18 +156,20 @@ class DataReductionProxyService
network::mojom::ConnectionType GetConnectionType() const;
// Sends the given |headers| to |DataReductionProxySettings|.
- void SetProxyRequestHeadersOnUI(const net::HttpRequestHeaders& headers);
+ void UpdateProxyRequestHeaders(const net::HttpRequestHeaders& headers);
- // Sends the given |proxies| and |proxies_for_http| to
- // |DataReductionProxySettings|.
- void SetConfiguredProxiesOnUI(
- const net::ProxyList& proxies,
- const std::vector<DataReductionProxyServer>& proxies_for_http);
+ // Adds a config client that can be used to update Data Reduction Proxy
+ // settings.
+ void AddCustomProxyConfigClient(
+ mojo::Remote<network::mojom::CustomProxyConfigClient> config_client);
- // Sets a config client that can be used to update Data Reduction Proxy
- // settings when the network service is enabled.
- void SetCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientPtrInfo config_client_info);
+ // mojom::DataReductionProxy implementation:
+ void MarkProxiesAsBad(base::TimeDelta bypass_duration,
+ const net::ProxyList& bad_proxies,
+ MarkProxiesAsBadCallback callback) override;
+ void AddThrottleConfigObserver(
+ mojom::DataReductionProxyThrottleConfigObserverPtr observer) override;
+ void Clone(mojom::DataReductionProxyRequest request) override;
// Accessor methods.
DataReductionProxyCompressionStats* compression_stats() const {
@@ -183,13 +185,44 @@ class DataReductionProxyService
return pingback_client_.get();
}
+ DataReductionProxyConfigurator* configurator() const {
+ return configurator_.get();
+ }
+
+ DataReductionProxyConfig* config() const { return config_.get(); }
+
+ DataReductionProxyConfigServiceClient* config_client() const {
+ return config_client_.get();
+ }
+
+ DataReductionProxyRequestOptions* request_options() const {
+ return request_options_.get();
+ }
+
+ // The production channel of this build.
+ std::string channel() const { return channel_; }
+
+ // The Client type of this build.
+ Client client() const { return client_; }
+
base::WeakPtr<DataReductionProxyService> GetWeakPtr();
base::SequencedTaskRunner* GetDBTaskRunnerForTesting() const {
return db_task_runner_.get();
}
+ void SetDependenciesForTesting(
+ std::unique_ptr<DataReductionProxyConfig> config,
+ std::unique_ptr<DataReductionProxyRequestOptions> request_options,
+ std::unique_ptr<DataReductionProxyConfigurator> configurator,
+ std::unique_ptr<DataReductionProxyConfigServiceClient> config_client);
+
private:
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigServiceClientTest,
+ MultipleAuthFailures);
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfigServiceClientTest,
+ ValidatePersistedClientConfig);
+
void OnEffectiveConnectionTypeChanged(
net::EffectiveConnectionType type) override;
@@ -208,13 +241,29 @@ class DataReductionProxyService
// NetworkConnectionTracker::NetworkConnectionObserver
void OnConnectionChanged(network::mojom::ConnectionType type) override;
- // mojom::DataReductionProxy implementation:
- void MarkProxiesAsBad(base::TimeDelta bypass_duration,
- const net::ProxyList& bad_proxies,
- MarkProxiesAsBadCallback callback) override;
- void AddThrottleConfigObserver(
- mojom::DataReductionProxyThrottleConfigObserverPtr observer) override;
- void Clone(mojom::DataReductionProxyRequest request) override;
+ // Called when the list of proxies changes.
+ void OnProxyConfigUpdated();
+
+ // Should be called whenever there is a possible change to the custom proxy
+ // config.
+ void UpdateCustomProxyConfig();
+
+ // Should be called whenever there is a possible change to the throttle
+ // config.
+ void UpdateThrottleConfig();
+
+ // Creates a config that can be sent to the DataReductionProxyThrottleManager.
+ mojom::DataReductionProxyThrottleConfigPtr CreateThrottleConfig() const;
+
+ // Creates a config using |proxies_for_http| that can be sent to the
+ // NetworkContext.
+ network::mojom::CustomProxyConfigPtr CreateCustomProxyConfig(
+ bool is_warmup_url,
+ const std::vector<DataReductionProxyServer>& proxies_for_http) const;
+
+ // Stores a serialized Data Reduction Proxy configuration in preferences
+ // storage.
+ void StoreSerializedConfig(const std::string& serialized_config);
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
@@ -230,23 +279,9 @@ class DataReductionProxyService
std::unique_ptr<DBDataOwner> db_data_owner_;
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
-
- // Used to post tasks to |io_data_|.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
// Used to post tasks to |db_data_owner_|.
scoped_refptr<base::SequencedTaskRunner> db_task_runner_;
- // A weak pointer to DataReductionProxyIOData so that UI based objects can
- // make calls to IO based objects.
- base::WeakPtr<DataReductionProxyIOData> io_data_;
-
- base::ObserverList<DataReductionProxyServiceObserver>::Unchecked
- observer_list_;
-
- bool initialized_;
-
// Must be accessed on UI thread. Guaranteed to be non-null during the
// lifetime of |this|.
network::NetworkQualityTracker* network_quality_tracker_;
@@ -263,6 +298,39 @@ class DataReductionProxyService
network::mojom::ConnectionType connection_type_ =
network::mojom::ConnectionType::CONNECTION_UNKNOWN;
+ // The type of Data Reduction Proxy client.
+ const Client client_;
+
+ // Parameters including DNS names and allowable configurations.
+ std::unique_ptr<DataReductionProxyConfig> config_;
+
+ // Setter of the Data Reduction Proxy-specific proxy configuration.
+ std::unique_ptr<DataReductionProxyConfigurator> configurator_;
+
+ // Constructs credentials suitable for authenticating the client.
+ std::unique_ptr<DataReductionProxyRequestOptions> request_options_;
+
+ // Requests new Data Reduction Proxy configurations from a remote service.
+ // May be null.
+ std::unique_ptr<DataReductionProxyConfigServiceClient> config_client_;
+
+ // The production channel of this build.
+ const std::string channel_;
+
+ // Created on the UI thread. Guaranteed to be destroyed on IO thread if the
+ // IO thread is still available at the time of destruction. If the IO thread
+ // is unavailable, then the destruction will happen on the UI thread.
+ std::unique_ptr<NetworkPropertiesManager> network_properties_manager_;
+
+ // The set of clients that will get updates about changes to the proxy config.
+ mojo::RemoteSet<network::mojom::CustomProxyConfigClient>
+ proxy_config_clients_;
+
+ mojo::BindingSet<mojom::DataReductionProxy> drp_bindings_;
+
+ mojo::InterfacePtrSet<mojom::DataReductionProxyThrottleConfigObserver>
+ drp_throttle_config_observers_;
+
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<DataReductionProxyService> weak_factory_{this};
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h
deleted file mode 100644
index 2654afaee72..00000000000
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_SERVICE_OBSERVER_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_SERVICE_OBSERVER_H_
-
-namespace data_reduction_proxy {
-
-class DataReductionProxyServiceObserver {
- public:
- virtual void OnServiceInitialized() = 0;
-};
-
-} // namespace data_reduction_proxy
-
-#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_SERVICE_OBSERVER_H_
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_unittest.cc
index 4b72a7342d1..32644baf8fc 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service_unittest.cc
@@ -1,8 +1,8 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include <stddef.h>
@@ -30,7 +30,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
@@ -59,25 +59,20 @@ std::string CreateEncodedConfig(
}
} // namespace
-class DataReductionProxyIODataTest : public testing::Test {
+class DataReductionProxyServiceTest : public testing::Test {
public:
- DataReductionProxyIODataTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
-
void SetUp() override {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableDataReductionProxyWarmupURLFetch);
RegisterSimpleProfilePrefs(prefs_.registry());
}
- void RequestCallback(int err) {
- }
+ void RequestCallback(int err) {}
- PrefService* prefs() {
- return &prefs_;
- }
+ PrefService* prefs() { return &prefs_; }
protected:
- content::TestBrowserThreadBundle scoped_task_environment_;
+ content::BrowserTaskEnvironment task_environment_;
private:
TestingPrefServiceSimple prefs_;
@@ -87,8 +82,9 @@ class TestCustomProxyConfigClient
: public network::mojom::CustomProxyConfigClient {
public:
TestCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientRequest request)
- : binding_(this, std::move(request)) {}
+ mojo::PendingReceiver<network::mojom::CustomProxyConfigClient>
+ pending_receiver)
+ : receiver_(this, std::move(pending_receiver)) {}
// network::mojom::CustomProxyConfigClient implementation:
void OnCustomProxyConfigUpdated(
@@ -106,10 +102,10 @@ class TestCustomProxyConfigClient
int num_clear_cache_calls = 0;
private:
- mojo::Binding<network::mojom::CustomProxyConfigClient> binding_;
+ mojo::Receiver<network::mojom::CustomProxyConfigClient> receiver_;
};
-TEST_F(DataReductionProxyIODataTest, TestResetBadProxyListOnDisableDataSaver) {
+TEST_F(DataReductionProxyServiceTest, TestResetBadProxyListOnDisableDataSaver) {
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.SkipSettingsInitialization()
@@ -118,10 +114,11 @@ TEST_F(DataReductionProxyIODataTest, TestResetBadProxyListOnDisableDataSaver) {
drp_test_context->SetDataReductionProxyEnabled(true);
drp_test_context->InitSettings();
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- drp_test_context->io_data()->SetCustomProxyConfigClient(
- std::move(client_ptr_info));
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ drp_test_context->data_reduction_proxy_service()->AddCustomProxyConfigClient(
+ std::move(client_remote));
base::RunLoop().RunUntilIdle();
// Turn Data Saver off.
@@ -132,7 +129,7 @@ TEST_F(DataReductionProxyIODataTest, TestResetBadProxyListOnDisableDataSaver) {
EXPECT_EQ(1, client.num_clear_cache_calls);
}
-TEST_F(DataReductionProxyIODataTest, HoldbackConfiguresProxies) {
+TEST_F(DataReductionProxyServiceTest, HoldbackConfiguresProxies) {
base::FieldTrialList field_trial_list(nullptr);
ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
"DataCompressionProxyHoldback", "Enabled"));
@@ -149,23 +146,24 @@ TEST_F(DataReductionProxyIODataTest, HoldbackConfiguresProxies) {
.is_direct());
}
-TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigClient) {
- auto proxy_server = net::ProxyServer::FromPacString("PROXY foo");
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kDataReductionProxyHttpProxies, proxy_server.ToURI());
-
+TEST_F(DataReductionProxyServiceTest, TestCustomProxyConfigClient) {
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
- DataReductionProxyTestContext::Builder()
- .Build();
+ DataReductionProxyTestContext::Builder().WithConfigClient().Build();
drp_test_context->SetDataReductionProxyEnabled(true);
drp_test_context->test_network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_4G);
- DataReductionProxyIOData* io_data = drp_test_context->io_data();
+ DataReductionProxyService* service =
+ drp_test_context->data_reduction_proxy_service();
+
+ auto proxy_server = net::ProxyServer::FromPacString("PROXY foo");
+ service->config_client()->ApplySerializedConfig(
+ CreateEncodedConfig({DataReductionProxyServer(proxy_server)}));
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- io_data->SetCustomProxyConfigClient(std::move(client_ptr_info));
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ service->AddCustomProxyConfigClient(std::move(client_remote));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server);
@@ -175,19 +173,19 @@ TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigClient) {
client.config->pre_cache_headers.HasHeader(chrome_proxy_ect_header()));
}
-TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigUpdatedOnECTChange) {
+TEST_F(DataReductionProxyServiceTest, TestCustomProxyConfigUpdatedOnECTChange) {
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
- DataReductionProxyTestContext::Builder()
- .Build();
+ DataReductionProxyTestContext::Builder().Build();
drp_test_context->SetDataReductionProxyEnabled(true);
drp_test_context->test_network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_4G);
- DataReductionProxyIOData* io_data = drp_test_context->io_data();
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- io_data->SetCustomProxyConfigClient(std::move(client_ptr_info));
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ drp_test_context->data_reduction_proxy_service()->AddCustomProxyConfigClient(
+ std::move(client_remote));
base::RunLoop().RunUntilIdle();
std::string value;
@@ -204,25 +202,25 @@ TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigUpdatedOnECTChange) {
EXPECT_EQ(value, "2G");
}
-TEST_F(DataReductionProxyIODataTest,
+TEST_F(DataReductionProxyServiceTest,
TestCustomProxyConfigUpdatedOnHeaderChange) {
- DataReductionProxyIOData io_data(
- Client::UNKNOWN, prefs(),
- network::TestNetworkConnectionTracker::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
- std::string() /* user_agent */, std::string() /* channel */);
-
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
+ std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
+ DataReductionProxyTestContext::Builder().Build();
+ drp_test_context->SetDataReductionProxyEnabled(true);
+ DataReductionProxyService* service =
+ drp_test_context->data_reduction_proxy_service();
+
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ service->AddCustomProxyConfigClient(std::move(client_remote));
base::RunLoop().RunUntilIdle();
std::string value;
EXPECT_TRUE(client.config->post_cache_headers.GetHeader(chrome_proxy_header(),
&value));
- io_data.request_options()->SetSecureSession("session_value");
+ service->request_options()->SetSecureSession("session_value");
base::RunLoop().RunUntilIdle();
std::string changed_value;
EXPECT_TRUE(client.config->post_cache_headers.GetHeader(chrome_proxy_header(),
@@ -230,69 +228,64 @@ TEST_F(DataReductionProxyIODataTest,
EXPECT_NE(value, changed_value);
}
-TEST_F(DataReductionProxyIODataTest,
+TEST_F(DataReductionProxyServiceTest,
TestCustomProxyConfigUpdatedOnProxyChange) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kDisableDataReductionProxyWarmupURLFetch);
- DataReductionProxyIOData io_data(
- Client::UNKNOWN, prefs(),
- network::TestNetworkConnectionTracker::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
- std::string() /* user_agent */, std::string() /* channel */);
+ std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
+ DataReductionProxyTestContext::Builder().WithConfigClient().Build();
+ drp_test_context->SetDataReductionProxyEnabled(true);
+ DataReductionProxyService* service =
+ drp_test_context->data_reduction_proxy_service();
+
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), prefs(),
- scoped_task_environment_.GetMainThreadTaskRunner());
- io_data.config()->SetNetworkPropertiesManagerForTesting(
+ base::DefaultClock::GetInstance(), prefs());
+ service->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
- io_data.config()->UpdateConfigForTesting(true, true, true);
+ service->config()->UpdateConfigForTesting(true, true, true);
auto proxy_server1 = net::ProxyServer::FromPacString("PROXY foo");
- io_data.config_client()->ApplySerializedConfig(
+ service->config_client()->ApplySerializedConfig(
CreateEncodedConfig({DataReductionProxyServer(proxy_server1)}));
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ service->AddCustomProxyConfigClient(std::move(client_remote));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server1);
auto proxy_server2 = net::ProxyServer::FromPacString("PROXY bar");
- io_data.config_client()->SetRemoteConfigAppliedForTesting(false);
- io_data.config_client()->ApplySerializedConfig(
+ service->config_client()->SetRemoteConfigAppliedForTesting(false);
+ service->config_client()->ApplySerializedConfig(
CreateEncodedConfig({DataReductionProxyServer(proxy_server2)}));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server2);
}
-TEST_F(DataReductionProxyIODataTest,
+TEST_F(DataReductionProxyServiceTest,
TestCustomProxyConfigHasAlternateProxyListOfCoreProxies) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kDisableDataReductionProxyWarmupURLFetch);
- DataReductionProxyIOData io_data(
- Client::UNKNOWN, prefs(),
- network::TestNetworkConnectionTracker::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
- std::string() /* user_agent */, std::string() /* channel */);
+ std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
+ DataReductionProxyTestContext::Builder().WithConfigClient().Build();
+ drp_test_context->SetDataReductionProxyEnabled(true);
+ DataReductionProxyService* service =
+ drp_test_context->data_reduction_proxy_service();
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), prefs(),
- scoped_task_environment_.GetMainThreadTaskRunner());
- io_data.config()->SetNetworkPropertiesManagerForTesting(
+ base::DefaultClock::GetInstance(), prefs());
+ service->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
- io_data.config()->UpdateConfigForTesting(true, true, true);
+ service->config()->UpdateConfigForTesting(true, true, true);
auto core_proxy_server = net::ProxyServer::FromPacString("PROXY foo");
auto second_proxy_server = net::ProxyServer::FromPacString("PROXY bar");
- io_data.config_client()->ApplySerializedConfig(
+ service->config_client()->ApplySerializedConfig(
CreateEncodedConfig({DataReductionProxyServer(core_proxy_server),
DataReductionProxyServer(second_proxy_server)}));
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ service->AddCustomProxyConfigClient(std::move(client_remote));
base::RunLoop().RunUntilIdle();
net::ProxyConfig::ProxyRules expected_rules;
@@ -304,25 +297,22 @@ TEST_F(DataReductionProxyIODataTest,
EXPECT_TRUE(client.config->rules.Equals(expected_rules));
}
-TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigProperties) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kDisableDataReductionProxyWarmupURLFetch);
- DataReductionProxyIOData io_data(
- Client::UNKNOWN, prefs(),
- network::TestNetworkConnectionTracker::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
- std::string() /* user_agent */, std::string() /* channel */);
+TEST_F(DataReductionProxyServiceTest, TestCustomProxyConfigProperties) {
+ std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
+ DataReductionProxyTestContext::Builder().Build();
+ drp_test_context->SetDataReductionProxyEnabled(true);
+ DataReductionProxyService* service =
+ drp_test_context->data_reduction_proxy_service();
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), prefs(),
- scoped_task_environment_.GetMainThreadTaskRunner());
- io_data.config()->SetNetworkPropertiesManagerForTesting(
+ base::DefaultClock::GetInstance(), prefs());
+ service->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
- io_data.config()->UpdateConfigForTesting(true, true, true);
+ service->config()->UpdateConfigForTesting(true, true, true);
- network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
- TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
- io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
+ mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote;
+ TestCustomProxyConfigClient client(
+ client_remote.BindNewPipeAndPassReceiver());
+ service->AddCustomProxyConfigClient(std::move(client_remote));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(client.config->assume_https_proxies_support_quic);
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
index a0b2217287a..8e532c4c8b2 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -14,7 +14,6 @@
#include "base/time/default_clock.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
@@ -24,7 +23,6 @@
#include "components/prefs/pref_service.h"
#include "net/base/network_change_notifier.h"
#include "net/http/http_request_headers.h"
-#include "services/network/public/cpp/features.h"
namespace {
@@ -52,7 +50,6 @@ namespace data_reduction_proxy {
DataReductionProxySettings::DataReductionProxySettings()
: unreachable_(false),
- deferred_initialization_(false),
prefs_(nullptr),
config_(nullptr),
clock_(base::DefaultClock::GetInstance()) {}
@@ -61,17 +58,14 @@ DataReductionProxySettings::~DataReductionProxySettings() = default;
void DataReductionProxySettings::InitDataReductionProxySettings(
PrefService* prefs,
- DataReductionProxyIOData* io_data,
std::unique_ptr<DataReductionProxyService> data_reduction_proxy_service) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(prefs);
- DCHECK(io_data);
- DCHECK(io_data->config());
DCHECK(data_reduction_proxy_service);
+ DCHECK(data_reduction_proxy_service->config());
prefs_ = prefs;
- config_ = io_data->config();
+ config_ = data_reduction_proxy_service->config();
data_reduction_proxy_service_ = std::move(data_reduction_proxy_service);
- data_reduction_proxy_service_->AddObserver(this);
RecordDataReductionInit();
registrar_.Init(prefs_);
@@ -89,19 +83,11 @@ void DataReductionProxySettings::InitDataReductionProxySettings(
for (auto& observer : observers_)
observer.OnSettingsInitialized();
-}
-void DataReductionProxySettings::OnServiceInitialized() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!deferred_initialization_)
- return;
- deferred_initialization_ = false;
- // Technically, this is not "at startup", but this is the first chance that
- // IO data objects can be called.
- UpdateIOData(true);
- if (proxy_config_client_) {
- data_reduction_proxy_service_->SetCustomProxyConfigClient(
- std::move(proxy_config_client_));
+ while (!proxy_config_clients_.empty()) {
+ data_reduction_proxy_service_->AddCustomProxyConfigClient(
+ std::move(proxy_config_clients_.back()));
+ proxy_config_clients_.pop_back();
}
}
@@ -142,8 +128,7 @@ void DataReductionProxySettings::SetDataSaverEnabledForTesting(
}
bool DataReductionProxySettings::IsDataReductionProxyEnabled() const {
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- !params::IsEnabledWithNetworkService()) {
+ if (!params::IsEnabledWithNetworkService()) {
return false;
}
return IsDataSaverEnabledByUser(GetOriginalProfilePrefs());
@@ -236,11 +221,6 @@ void DataReductionProxySettings::ResetDataReductionStatistics() {
data_reduction_proxy_service_->compression_stats()->ResetStatistics();
}
-void DataReductionProxySettings::UpdateIOData(bool at_startup) {
- data_reduction_proxy_service_->SetProxyPrefs(IsDataReductionProxyEnabled(),
- at_startup);
-}
-
void DataReductionProxySettings::MaybeActivateDataReductionProxy(
bool at_startup) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -301,11 +281,9 @@ void DataReductionProxySettings::MaybeActivateDataReductionProxy(
RecordSettingsEnabledState(DATA_REDUCTION_SETTINGS_ACTION_ON_TO_OFF);
}
}
- // Configure use of the data reduction proxy if it is enabled.
- if (at_startup && !data_reduction_proxy_service_->Initialized())
- deferred_initialization_ = true;
- else
- UpdateIOData(at_startup);
+
+ data_reduction_proxy_service_->SetProxyPrefs(IsDataReductionProxyEnabled(),
+ at_startup);
}
const net::HttpRequestHeaders&
@@ -322,24 +300,14 @@ void DataReductionProxySettings::SetProxyRequestHeaders(
observer.OnProxyRequestHeadersChanged(headers);
}
-void DataReductionProxySettings::SetConfiguredProxies(
- const net::ProxyList& proxies) {
- DCHECK(thread_checker_.CalledOnValidThread());
- configured_proxies_ = proxies;
-}
-
-void DataReductionProxySettings::SetProxiesForHttp(
- const std::vector<DataReductionProxyServer>& proxies_for_http) {
- DCHECK(thread_checker_.CalledOnValidThread());
- proxies_for_http_ = proxies_for_http;
-}
-
bool DataReductionProxySettings::IsConfiguredDataReductionProxy(
const net::ProxyServer& proxy_server) const {
if (proxy_server.is_direct() || !proxy_server.is_valid())
return false;
- for (const auto& drp_proxy : configured_proxies_.GetAll()) {
+ net::ProxyList proxies =
+ data_reduction_proxy_service_->config()->GetAllConfiguredProxies();
+ for (const auto& drp_proxy : proxies.GetAll()) {
if (drp_proxy.host_port_pair().Equals(proxy_server.host_port_pair()))
return true;
}
@@ -358,9 +326,15 @@ void DataReductionProxySettings::RemoveDataReductionProxySettingsObserver(
observers_.RemoveObserver(observer);
}
-void DataReductionProxySettings::SetCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientPtrInfo proxy_config_client) {
- proxy_config_client_ = std::move(proxy_config_client);
+void DataReductionProxySettings::AddCustomProxyConfigClient(
+ mojo::Remote<network::mojom::CustomProxyConfigClient> proxy_config_client) {
+ if (data_reduction_proxy_service_) {
+ data_reduction_proxy_service_->AddCustomProxyConfigClient(
+ std::move(proxy_config_client));
+ return;
+ }
+
+ proxy_config_clients_.push_back(std::move(proxy_config_client));
}
// Metrics methods
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
index a638cfbd092..5527a1ee80c 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
@@ -18,10 +18,10 @@
#include "base/threading/thread_checker.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "url/gurl.h"
@@ -35,7 +35,6 @@ class Clock;
namespace data_reduction_proxy {
class DataReductionProxyConfig;
-class DataReductionProxyIOData;
class DataReductionProxyService;
class DataReductionProxyCompressionStats;
@@ -78,7 +77,7 @@ class DataReductionProxySettingsObserver {
// Central point for configuring the data reduction proxy.
// This object lives on the UI thread and all of its methods are expected to
// be called from there.
-class DataReductionProxySettings : public DataReductionProxyServiceObserver {
+class DataReductionProxySettings {
public:
using SyntheticFieldTrialRegistrationCallback =
base::Callback<bool(base::StringPiece, base::StringPiece)>;
@@ -86,12 +85,11 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
DataReductionProxySettings();
virtual ~DataReductionProxySettings();
- // Initializes the Data Reduction Proxy with the profile prefs and a
- // |DataReductionProxyIOData|. The caller must ensure that all parameters
- // remain alive for the lifetime of the |DataReductionProxySettings| instance.
+ // Initializes the Data Reduction Proxy with the profile prefs. The caller
+ // must ensure that all parameters remain alive for the lifetime of the
+ // |DataReductionProxySettings| instance.
void InitDataReductionProxySettings(
PrefService* prefs,
- DataReductionProxyIOData* io_data,
std::unique_ptr<DataReductionProxyService> data_reduction_proxy_service);
// Sets the |register_synthetic_field_trial_| callback and runs to register
@@ -168,10 +166,6 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
// Sets the headers to use for requests to the compression server.
void SetProxyRequestHeaders(const net::HttpRequestHeaders& headers);
- void SetConfiguredProxies(const net::ProxyList& proxies);
- void SetProxiesForHttp(
- const std::vector<DataReductionProxyServer>& proxies_for_http);
-
// Returns headers to use for requests to the compression server.
const net::HttpRequestHeaders& GetProxyRequestHeaders() const;
@@ -185,10 +179,11 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
void RemoveDataReductionProxySettingsObserver(
DataReductionProxySettingsObserver* observer);
- // Sets a config client that can be used to update Data Reduction Proxy
- // settings when the network service is enabled.
- void SetCustomProxyConfigClient(
- network::mojom::CustomProxyConfigClientPtrInfo proxy_config_client);
+ // Addds a config client that can be used to update Data Reduction Proxy
+ // settings.
+ void AddCustomProxyConfigClient(
+ mojo::Remote<network::mojom::CustomProxyConfigClient>
+ proxy_config_client);
DataReductionProxyService* data_reduction_proxy_service() {
return data_reduction_proxy_service_.get();
@@ -200,10 +195,6 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
return config_;
}
- const std::vector<DataReductionProxyServer> proxies_for_http() const {
- return proxies_for_http_;
- }
-
// Permits changing the underlying |DataReductionProxyConfig| without running
// the initialization loop.
void ResetConfigForTest(DataReductionProxyConfig* config) {
@@ -263,9 +254,6 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
FRIEND_TEST_ALL_PREFIXES(DataReductionProxySettingsTest,
TestDaysSinceSavingsCleared);
- // Override of DataReductionProxyService::Observer.
- void OnServiceInitialized() override;
-
// Registers the trial "SyntheticDataReductionProxySetting" with the group
// "Enabled" or "Disabled". Indicates whether the proxy is turned on or not.
void RegisterDataReductionProxyFieldTrial();
@@ -279,19 +267,8 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
void ResetDataReductionStatistics();
- // Update IO thread objects in response to UI thread changes.
- void UpdateIOData(bool at_startup);
-
bool unreachable_;
- // A call to MaybeActivateDataReductionProxy may take place before the
- // |data_reduction_proxy_service_| has received a DataReductionProxyIOData
- // pointer. In that case, the operation against the IO objects will not
- // succeed and |deferred_initialization_| will be set to true. When
- // OnServiceInitialized is called, if |deferred_initialization_| is true,
- // IO object calls will be performed at that time.
- bool deferred_initialization_;
-
// The number of requests to reload the page with images from the Lo-Fi
// UI until Lo-Fi is disabled for the remainder of the session.
int lo_fi_user_requests_for_images_per_session_;
@@ -322,10 +299,10 @@ class DataReductionProxySettings : public DataReductionProxyServiceObserver {
// The headers to use for requests to the proxy server.
net::HttpRequestHeaders proxy_request_headers_;
- net::ProxyList configured_proxies_;
- std::vector<DataReductionProxyServer> proxies_for_http_;
-
- network::mojom::CustomProxyConfigClientPtrInfo proxy_config_client_;
+ // A list of CustomProxyConfigClients that may have been added before
+ // the DataReductionProxyService was available.
+ std::vector<mojo::Remote<network::mojom::CustomProxyConfigClient>>
+ proxy_config_clients_;
base::ThreadChecker thread_checker_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc
index eabbcde6592..dde964ecea5 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc
@@ -72,10 +72,15 @@ template <class C>
void DataReductionProxySettingsTestBase::ResetSettings(base::Clock* clock) {
MockDataReductionProxySettings<C>* settings =
new MockDataReductionProxySettings<C>();
+ if (settings_) {
+ settings->data_reduction_proxy_service_ =
+ std::move(settings_->data_reduction_proxy_service_);
+ } else {
+ settings->data_reduction_proxy_service_ = test_context_->TakeService();
+ }
+ settings->data_reduction_proxy_service_->SetSettingsForTesting(settings);
settings->config_ = test_context_->config();
settings->prefs_ = test_context_->pref_service();
- settings->data_reduction_proxy_service_ =
- test_context_->CreateDataReductionProxyService(settings);
if (clock)
settings->clock_ = clock;
EXPECT_CALL(*settings, GetOriginalProfilePrefs())
@@ -119,10 +124,8 @@ void DataReductionProxySettingsTestBase::CheckOnPrefChange(
void DataReductionProxySettingsTestBase::InitDataReductionProxy(
bool enabled_at_startup) {
settings_->InitDataReductionProxySettings(
- test_context_->pref_service(), test_context_->io_data(),
- test_context_->CreateDataReductionProxyService(settings_.get()));
- settings_->data_reduction_proxy_service()->SetIOData(
- test_context_->io_data()->GetWeakPtr());
+ test_context_->pref_service(),
+ std::move(settings_->data_reduction_proxy_service_));
settings_->SetCallbackToRegisterSyntheticFieldTrial(base::Bind(
&DataReductionProxySettingsTestBase::OnSyntheticFieldTrialRegistration,
base::Unretained(this)));
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h
index 9abbb32929f..d543fa3fcde 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h
@@ -10,6 +10,7 @@
#include <string>
#include <utility>
+#include "base/message_loop/message_pump_type.h"
#include "base/strings/string_piece.h"
#include "base/task/single_thread_task_executor.h"
#include "base/time/clock.h"
@@ -66,7 +67,7 @@ class DataReductionProxySettingsTestBase : public testing::Test {
base::StringPiece group_name);
protected:
- base::SingleThreadTaskExecutor io_task_executor_{base::MessagePump::Type::IO};
+ base::SingleThreadTaskExecutor io_task_executor_{base::MessagePumpType::IO};
std::unique_ptr<DataReductionProxyTestContext> test_context_;
std::unique_ptr<DataReductionProxySettings> settings_;
base::Time last_update_time_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
index dab0be5bcfe..09b2bb16a48 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
@@ -15,8 +15,8 @@
#include "base/metrics/histogram_samples.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
@@ -129,8 +129,8 @@ TEST(DataReductionProxySettingsStandaloneTest, TestEndToEndSecureProxyCheck) {
data_reduction_proxy::switches::kDataReductionProxyHttpProxies,
kHttpsProxy.ToURI() + ";" + kHttpProxy.ToURI());
- base::test::ScopedTaskEnvironment task_environment{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
struct TestCase {
const char* response_headers;
const char* response_body;
@@ -200,8 +200,8 @@ TEST(DataReductionProxySettingsStandaloneTest, TestEndToEndSecureProxyCheck) {
}
TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) {
- base::test::ScopedTaskEnvironment task_environment{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.WithMockConfig()
@@ -210,8 +210,7 @@ TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) {
.Build();
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), drp_test_context->pref_service(),
- drp_test_context->task_runner());
+ base::DefaultClock::GetInstance(), drp_test_context->pref_service());
drp_test_context->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
@@ -233,8 +232,8 @@ TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) {
}
TEST(DataReductionProxySettingsStandaloneTest, TestIsProxyEnabledOrManaged) {
- base::test::ScopedTaskEnvironment task_environment{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.WithMockConfig()
@@ -243,8 +242,7 @@ TEST(DataReductionProxySettingsStandaloneTest, TestIsProxyEnabledOrManaged) {
.Build();
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), drp_test_context->pref_service(),
- drp_test_context->task_runner());
+ base::DefaultClock::GetInstance(), drp_test_context->pref_service());
drp_test_context->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
drp_test_context->InitSettings();
@@ -275,8 +273,8 @@ TEST(DataReductionProxySettingsStandaloneTest, TestIsProxyEnabledOrManaged) {
}
TEST(DataReductionProxySettingsStandaloneTest, TestCanUseDataReductionProxy) {
- base::test::ScopedTaskEnvironment task_environment{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.WithMockConfig()
@@ -285,8 +283,7 @@ TEST(DataReductionProxySettingsStandaloneTest, TestCanUseDataReductionProxy) {
.Build();
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), drp_test_context->pref_service(),
- drp_test_context->task_runner());
+ base::DefaultClock::GetInstance(), drp_test_context->pref_service());
drp_test_context->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
drp_test_context->InitSettings();
@@ -319,8 +316,7 @@ TEST_F(DataReductionProxySettingsTest, TestMaybeActivateDataReductionProxy) {
// so it won't trigger MaybeActivateDataReductionProxy when the pref value
// is set.
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), test_context_->pref_service(),
- test_context_->task_runner());
+ base::DefaultClock::GetInstance(), test_context_->pref_service());
test_context_->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
@@ -387,9 +383,6 @@ TEST_F(DataReductionProxySettingsTest, TestSettingsEnabledStateHistograms) {
const char kUMAEnabledState[] = "DataReductionProxy.EnabledState";
base::HistogramTester histogram_tester;
- settings_->data_reduction_proxy_service_->SetIOData(
- test_context_->io_data()->GetWeakPtr());
-
// No settings state histograms should be recorded during startup.
test_context_->RunUntilIdle();
histogram_tester.ExpectTotalCount(kUMAEnabledState, 0);
@@ -423,8 +416,6 @@ TEST_F(DataReductionProxySettingsTest, TestDaysSinceEnabledWithTestClock) {
{
base::HistogramTester histogram_tester;
- settings_->data_reduction_proxy_service_->SetIOData(
- test_context_->io_data()->GetWeakPtr());
test_context_->RunUntilIdle();
histogram_tester.ExpectTotalCount(kUMAEnabledState, 0);
@@ -484,8 +475,8 @@ TEST_F(DataReductionProxySettingsTest, TestDaysSinceEnabledWithTestClock) {
// that already have data reduction proxy on.
TEST(DataReductionProxySettingsStandaloneTest,
TestDaysSinceEnabledExistingUser) {
- base::test::ScopedTaskEnvironment task_environment{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
DataReductionProxyTestContext::Builder()
.WithMockConfig()
@@ -494,8 +485,7 @@ TEST(DataReductionProxySettingsStandaloneTest,
.Build();
NetworkPropertiesManager network_properties_manager(
- base::DefaultClock::GetInstance(), drp_test_context->pref_service(),
- drp_test_context->task_runner());
+ base::DefaultClock::GetInstance(), drp_test_context->pref_service());
drp_test_context->config()->SetNetworkPropertiesManagerForTesting(
&network_properties_manager);
@@ -524,8 +514,6 @@ TEST_F(DataReductionProxySettingsTest, TestDaysSinceSavingsCleared) {
prefs::kDataReductionProxySavingsClearedNegativeSystemClock,
clock.Now().ToInternalValue());
- settings_->data_reduction_proxy_service_->SetIOData(
- test_context_->io_data()->GetWeakPtr());
test_context_->RunUntilIdle();
clock.Advance(base::TimeDelta::FromDays(100));
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
index 7060cf2adb3..9c95edea1b1 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -17,7 +17,6 @@
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
@@ -99,7 +98,7 @@ TestDataReductionProxyConfigServiceClient::
DataReductionProxyRequestOptions* request_options,
DataReductionProxyMutableConfigValues* config_values,
DataReductionProxyConfig* config,
- DataReductionProxyIOData* io_data,
+ DataReductionProxyService* service,
network::NetworkConnectionTracker* network_connection_tracker,
ConfigStorer config_storer,
const net::BackoffEntry::Policy& backoff_policy)
@@ -107,7 +106,7 @@ TestDataReductionProxyConfigServiceClient::
request_options,
config_values,
config,
- io_data,
+ service,
network_connection_tracker,
config_storer),
#if defined(OS_ANDROID)
@@ -224,57 +223,48 @@ MockDataReductionProxyService::MockDataReductionProxyService(
network::TestNetworkConnectionTracker::GetInstance(),
nullptr,
task_runner,
- task_runner,
- task_runner,
- base::TimeDelta()) {}
+ base::TimeDelta(),
+ Client::UNKNOWN,
+ std::string(),
+ std::string()) {}
MockDataReductionProxyService::~MockDataReductionProxyService() {
}
-TestDataReductionProxyIOData::TestDataReductionProxyIOData(
+TestDataReductionProxyService::TestDataReductionProxyService(
+ DataReductionProxySettings* settings,
PrefService* prefs,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- std::unique_ptr<DataReductionProxyConfig> config,
- std::unique_ptr<TestDataReductionProxyRequestOptions> request_options,
- std::unique_ptr<DataReductionProxyConfigurator> configurator,
- network::NetworkConnectionTracker* network_connection_tracker,
- bool enabled)
- : DataReductionProxyIOData(prefs, task_runner, task_runner),
- service_set_(false),
- pingback_reporting_fraction_(0.0f),
- test_request_options_(request_options.get()) {
- io_task_runner_ = task_runner;
- ui_task_runner_ = task_runner;
- config_ = std::move(config);
- request_options_ = std::move(request_options);
- configurator_ = std::move(configurator);
- network_connection_tracker_ = network_connection_tracker;
- enabled_ = enabled;
-}
-
-TestDataReductionProxyIOData::~TestDataReductionProxyIOData() {
-}
-
-void TestDataReductionProxyIOData::SetPingbackReportingFraction(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ network::NetworkQualityTracker* network_quality_tracker,
+ const scoped_refptr<base::SequencedTaskRunner>& db_task_runner)
+ : DataReductionProxyService(
+ settings,
+ prefs,
+ url_loader_factory,
+ std::make_unique<TestDataStore>(),
+ nullptr,
+ network_quality_tracker,
+ network::TestNetworkConnectionTracker::GetInstance(),
+ nullptr,
+ db_task_runner,
+ base::TimeDelta(),
+ Client::UNKNOWN,
+ std::string(),
+ std::string()),
+ pingback_reporting_fraction_(0.0f) {}
+
+TestDataReductionProxyService::~TestDataReductionProxyService() {}
+
+void TestDataReductionProxyService::SetPingbackReportingFraction(
float pingback_reporting_fraction) {
pingback_reporting_fraction_ = pingback_reporting_fraction;
}
-void TestDataReductionProxyIOData::SetIgnoreLongTermBlackListRules(
+void TestDataReductionProxyService::SetIgnoreLongTermBlackListRules(
bool ignore_long_term_black_list_rules) {
ignore_blacklist_ = ignore_long_term_black_list_rules;
}
-void TestDataReductionProxyIOData::SetDataReductionProxyService(
- base::WeakPtr<DataReductionProxyService> data_reduction_proxy_service,
- const std::string& user_agent) {
- if (!service_set_)
- DataReductionProxyIOData::SetDataReductionProxyService(
- data_reduction_proxy_service, user_agent);
-
- service_set_ = true;
-}
-
TestDataStore::TestDataStore() {}
TestDataStore::~TestDataStore() {}
@@ -403,8 +393,15 @@ DataReductionProxyTestContext::Builder::Build() {
// In case no |url_loader_factory_| is specified, an instance will be
// created in DataReductionProxyTestContext's ctor.
- if (url_loader_factory_)
+ std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory;
+ if (url_loader_factory_) {
url_loader_factory = url_loader_factory_;
+ } else {
+ test_url_loader_factory = std::make_unique<network::TestURLLoaderFactory>();
+ url_loader_factory =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ test_url_loader_factory.get());
+ }
std::unique_ptr<DataReductionProxyConfigurator> configurator(
new DataReductionProxyConfigurator());
@@ -424,19 +421,18 @@ DataReductionProxyTestContext::Builder::Build() {
}
raw_mutable_config = mutable_config.get();
config.reset(new TestDataReductionProxyConfig(std::move(mutable_config),
- task_runner, task_runner,
configurator.get()));
} else if (use_mock_config_) {
test_context_flags |= USE_MOCK_CONFIG;
- config.reset(new MockDataReductionProxyConfig(
- std::move(params), task_runner, task_runner, configurator.get()));
+ config.reset(new MockDataReductionProxyConfig(std::move(params),
+ configurator.get()));
} else {
test_context_flags ^= USE_MOCK_CONFIG;
if (!proxy_servers_.empty()) {
params->SetProxiesForHttp(proxy_servers_);
}
- config.reset(new TestDataReductionProxyConfig(
- std::move(params), task_runner, task_runner, configurator.get()));
+ config.reset(new TestDataReductionProxyConfig(std::move(params),
+ configurator.get()));
}
std::unique_ptr<TestDataReductionProxyRequestOptions> request_options;
@@ -456,41 +452,50 @@ DataReductionProxyTestContext::Builder::Build() {
test_context_flags |= SKIP_SETTINGS_INITIALIZATION;
}
- if (use_mock_service_)
- test_context_flags |= USE_MOCK_SERVICE;
-
pref_service->registry()->RegisterBooleanPref(prefs::kDataSaverEnabled,
false);
RegisterSimpleProfilePrefs(pref_service->registry());
- std::unique_ptr<TestDataReductionProxyIOData> io_data(
- new TestDataReductionProxyIOData(
- pref_service.get(), task_runner, std::move(config),
- std::move(request_options), std::move(configurator),
- test_network_connection_tracker, true /* enabled */));
+ auto test_network_quality_tracker =
+ std::make_unique<network::TestNetworkQualityTracker>();
+ std::unique_ptr<DataReductionProxyService> service;
+ if (use_mock_service_) {
+ test_context_flags |= USE_MOCK_SERVICE;
+ service = std::make_unique<MockDataReductionProxyService>(
+ settings_.get(), test_network_quality_tracker.get(), pref_service.get(),
+ url_loader_factory, task_runner);
+ } else {
+ service = std::make_unique<TestDataReductionProxyService>(
+ settings_.get(), pref_service.get(), url_loader_factory,
+ test_network_quality_tracker.get(), task_runner);
+ }
if (use_test_config_client_) {
test_context_flags |= USE_TEST_CONFIG_CLIENT;
config_client.reset(new TestDataReductionProxyConfigServiceClient(
- std::move(params), io_data->request_options(), raw_mutable_config,
- io_data->config(), io_data.get(), test_network_connection_tracker,
+ std::move(params), request_options.get(), raw_mutable_config,
+ config.get(), service.get(), test_network_connection_tracker,
base::BindRepeating(&TestConfigStorer::StoreSerializedConfig,
base::Unretained(config_storer.get())),
GetTestBackoffPolicy()));
} else if (use_config_client_) {
config_client.reset(new DataReductionProxyConfigServiceClient(
- GetBackoffPolicy(), io_data->request_options(), raw_mutable_config,
- io_data->config(), io_data.get(), test_network_connection_tracker,
+ GetBackoffPolicy(), request_options.get(), raw_mutable_config,
+ config.get(), service.get(), test_network_connection_tracker,
base::Bind(&TestConfigStorer::StoreSerializedConfig,
base::Unretained(config_storer.get()))));
}
- io_data->set_config_client(std::move(config_client));
+
+ service->SetDependenciesForTesting(
+ std::move(config), std::move(request_options), std::move(configurator),
+ std::move(config_client));
std::unique_ptr<DataReductionProxyTestContext> test_context(
new DataReductionProxyTestContext(
task_runner, std::move(pref_service), url_loader_factory,
- std::move(io_data), std::move(settings_), std::move(config_storer),
- raw_params, test_context_flags));
+ std::move(test_url_loader_factory), std::move(settings_),
+ std::move(service), std::move(test_network_quality_tracker),
+ std::move(config_storer), raw_params, test_context_flags));
if (!skip_settings_initialization_)
test_context->InitSettingsWithoutCheck();
@@ -502,30 +507,28 @@ DataReductionProxyTestContext::DataReductionProxyTestContext(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
std::unique_ptr<TestingPrefServiceSimple> simple_pref_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- std::unique_ptr<TestDataReductionProxyIOData> io_data,
+ std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory,
std::unique_ptr<DataReductionProxySettings> settings,
+ std::unique_ptr<DataReductionProxyService> service,
+ std::unique_ptr<network::TestNetworkQualityTracker>
+ test_network_quality_tracker,
std::unique_ptr<TestConfigStorer> config_storer,
TestDataReductionProxyParams* params,
unsigned int test_context_flags)
: test_context_flags_(test_context_flags),
task_runner_(task_runner),
simple_pref_service_(std::move(simple_pref_service)),
- io_data_(std::move(io_data)),
+ test_shared_url_loader_factory_(url_loader_factory),
+ test_url_loader_factory_(std::move(test_url_loader_factory)),
settings_(std::move(settings)),
+ test_network_quality_tracker_(std::move(test_network_quality_tracker)),
+ service_(std::move(service)),
config_storer_(std::move(config_storer)),
- test_network_quality_tracker_(
- std::make_unique<network::TestNetworkQualityTracker>()),
params_(params) {
- if (url_loader_factory) {
- test_shared_url_loader_factory_ = std::move(url_loader_factory);
- return;
- }
-
- // To be used for EnableDataReductionProxyWithSecureProxyCheckSuccess.
- test_url_loader_factory_ = std::make_unique<network::TestURLLoaderFactory>();
- test_shared_url_loader_factory_ =
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- test_url_loader_factory_.get());
+ if (service_)
+ data_reduction_proxy_service_ = service_.get();
+ else
+ data_reduction_proxy_service_ = settings_->data_reduction_proxy_service();
}
DataReductionProxyTestContext::~DataReductionProxyTestContext() {
@@ -573,37 +576,16 @@ void DataReductionProxyTestContext::DestroySettings() {
}
void DataReductionProxyTestContext::InitSettingsWithoutCheck() {
- settings_->InitDataReductionProxySettings(
- simple_pref_service_.get(), io_data_.get(),
- CreateDataReductionProxyServiceInternal(settings_.get()));
- io_data_->SetDataReductionProxyService(
- settings_->data_reduction_proxy_service()->GetWeakPtr(),
- std::string() /*user_agent*/);
- settings_->data_reduction_proxy_service()->SetIOData(io_data_->GetWeakPtr());
+ DCHECK(service_);
+ settings_->InitDataReductionProxySettings(simple_pref_service_.get(),
+ std::move(service_));
}
std::unique_ptr<DataReductionProxyService>
-DataReductionProxyTestContext::CreateDataReductionProxyService(
- DataReductionProxySettings* settings) {
+DataReductionProxyTestContext::TakeService() {
+ DCHECK(service_);
DCHECK(test_context_flags_ & SKIP_SETTINGS_INITIALIZATION);
- return CreateDataReductionProxyServiceInternal(settings);
-}
-
-std::unique_ptr<DataReductionProxyService>
-DataReductionProxyTestContext::CreateDataReductionProxyServiceInternal(
- DataReductionProxySettings* settings) {
- if (test_context_flags_ & USE_MOCK_SERVICE) {
- return std::make_unique<MockDataReductionProxyService>(
- settings, test_network_quality_tracker_.get(),
- simple_pref_service_.get(), test_shared_url_loader_factory_,
- task_runner_);
- }
- return std::make_unique<DataReductionProxyService>(
- settings, simple_pref_service_.get(), test_shared_url_loader_factory_,
- base::WrapUnique(new TestDataStore()), nullptr,
- test_network_quality_tracker_.get(),
- network::TestNetworkConnectionTracker::GetInstance(), nullptr,
- task_runner_, task_runner_, task_runner_, base::TimeDelta());
+ return std::move(service_);
}
void DataReductionProxyTestContext::
@@ -640,12 +622,20 @@ void DataReductionProxyTestContext::DisableWarmupURLFetchCallback() {
MockDataReductionProxyConfig* DataReductionProxyTestContext::mock_config()
const {
DCHECK(test_context_flags_ & USE_MOCK_CONFIG);
- return reinterpret_cast<MockDataReductionProxyConfig*>(io_data_->config());
+ return reinterpret_cast<MockDataReductionProxyConfig*>(
+ data_reduction_proxy_service()->config());
}
DataReductionProxyService*
DataReductionProxyTestContext::data_reduction_proxy_service() const {
- return settings_->data_reduction_proxy_service();
+ return data_reduction_proxy_service_;
+}
+
+TestDataReductionProxyService*
+DataReductionProxyTestContext::test_data_reduction_proxy_service() const {
+ DCHECK(!(test_context_flags_ & USE_MOCK_SERVICE));
+ return reinterpret_cast<TestDataReductionProxyService*>(
+ data_reduction_proxy_service());
}
MockDataReductionProxyService*
@@ -661,11 +651,12 @@ MockDataReductionProxyRequestOptions*
DataReductionProxyTestContext::mock_request_options() const {
DCHECK(test_context_flags_ & USE_MOCK_REQUEST_OPTIONS);
return reinterpret_cast<MockDataReductionProxyRequestOptions*>(
- io_data_->request_options());
+ data_reduction_proxy_service()->request_options());
}
TestDataReductionProxyConfig* DataReductionProxyTestContext::config() const {
- return reinterpret_cast<TestDataReductionProxyConfig*>(io_data_->config());
+ return reinterpret_cast<TestDataReductionProxyConfig*>(
+ data_reduction_proxy_service()->config());
}
DataReductionProxyMutableConfigValues*
@@ -679,7 +670,7 @@ TestDataReductionProxyConfigServiceClient*
DataReductionProxyTestContext::test_config_client() {
DCHECK(test_context_flags_ & USE_TEST_CONFIG_CLIENT);
return reinterpret_cast<TestDataReductionProxyConfigServiceClient*>(
- io_data_->config_client());
+ data_reduction_proxy_service()->config_client());
}
DataReductionProxyTestContext::TestConfigStorer::TestConfigStorer(
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
index 748c9287f22..51fd026a047 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
@@ -20,7 +20,6 @@
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h"
@@ -87,7 +86,7 @@ class TestDataReductionProxyConfigServiceClient
DataReductionProxyRequestOptions* request_options,
DataReductionProxyMutableConfigValues* config_values,
DataReductionProxyConfig* config,
- DataReductionProxyIOData* io_data,
+ DataReductionProxyService* service,
network::NetworkConnectionTracker* network_connection_tracker,
ConfigStorer config_storer,
const net::BackoffEntry::Policy& backoff_policy);
@@ -193,44 +192,18 @@ class MockDataReductionProxyService : public DataReductionProxyService {
const std::string& host));
};
-// Test version of |DataReductionProxyIOData|, which bypasses initialization in
+// Test version of |DataReductionProxyService|, which bypasses initialization in
// the constructor in favor of explicitly passing in its owned classes. This
// permits the use of test/mock versions of those classes.
-class TestDataReductionProxyIOData : public DataReductionProxyIOData {
+class TestDataReductionProxyService : public DataReductionProxyService {
public:
- TestDataReductionProxyIOData(
+ TestDataReductionProxyService(
+ DataReductionProxySettings* settings,
PrefService* prefs,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- std::unique_ptr<DataReductionProxyConfig> config,
- std::unique_ptr<TestDataReductionProxyRequestOptions> request_options,
- std::unique_ptr<DataReductionProxyConfigurator> configurator,
- network::NetworkConnectionTracker* network_connection_tracker,
- bool enabled);
- ~TestDataReductionProxyIOData() override;
-
- void SetDataReductionProxyService(
- base::WeakPtr<DataReductionProxyService> data_reduction_proxy_service,
- const std::string& user_agent) override;
-
- DataReductionProxyConfigurator* configurator() const {
- return configurator_.get();
- }
-
- void set_config_client(
- std::unique_ptr<DataReductionProxyConfigServiceClient> config_client) {
- config_client_ = std::move(config_client);
- }
- DataReductionProxyConfigServiceClient* config_client() const {
- return config_client_.get();
- }
-
- TestDataReductionProxyRequestOptions* test_request_options() const {
- return test_request_options_;
- }
-
- base::WeakPtr<DataReductionProxyIOData> GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ network::NetworkQualityTracker* network_quality_tracker,
+ const scoped_refptr<base::SequencedTaskRunner>& db_task_runner);
+ ~TestDataReductionProxyService() override;
// Records the reporting fraction that was set by parsing a config.
void SetPingbackReportingFraction(float pingback_reporting_fraction) override;
@@ -246,16 +219,11 @@ class TestDataReductionProxyIOData : public DataReductionProxyIOData {
bool ignore_blacklist() const { return ignore_blacklist_; }
private:
- // Allowed SetDataReductionProxyService to be re-entrant.
- bool service_set_;
-
// Reporting fraction last set via SetPingbackReportingFraction.
- float pingback_reporting_fraction_;
+ float pingback_reporting_fraction_ = 0.0f;
// Whether the long term blacklist rules should be ignored.
bool ignore_blacklist_ = false;
-
- TestDataReductionProxyRequestOptions* test_request_options_;
};
// Test version of |DataStore|. Uses an in memory hash map to store data.
@@ -366,12 +334,9 @@ class DataReductionProxyTestContext {
// the DB task runner are destroyed.
void DestroySettings();
- // Creates a |DataReductionProxyService| object, or a
- // |MockDataReductionProxyService| if built with
- // WithMockDataReductionProxyService. Can only be called if built with
- // SkipSettingsInitialization.
- std::unique_ptr<DataReductionProxyService> CreateDataReductionProxyService(
- DataReductionProxySettings* settings);
+ // Takes ownership of the |DataReductionProxyService| object. Can only be
+ // called if built with SkipSettingsInitialization.
+ std::unique_ptr<DataReductionProxyService> TakeService();
// Enable the Data Reduction Proxy, simulating a successful secure proxy
// check. This can only be called if not built with WithTestConfigurator,
@@ -394,6 +359,10 @@ class DataReductionProxyTestContext {
DataReductionProxyService* data_reduction_proxy_service() const;
+ // Returns the underlying |TestDataReductionProxyService|. This can only be
+ // called if not built with WithMockDataReductionProxyService.
+ TestDataReductionProxyService* test_data_reduction_proxy_service() const;
+
// Returns the underlying |MockDataReductionProxyService|. This can only
// be called if built with WithMockDataReductionProxyService.
MockDataReductionProxyService* mock_data_reduction_proxy_service() const;
@@ -426,11 +395,7 @@ class DataReductionProxyTestContext {
}
DataReductionProxyConfigurator* configurator() const {
- return io_data_->configurator();
- }
-
- TestDataReductionProxyIOData* io_data() const {
- return io_data_.get();
+ return settings_->data_reduction_proxy_service()->configurator();
}
DataReductionProxySettings* settings() const {
@@ -469,15 +434,15 @@ class DataReductionProxyTestContext {
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
std::unique_ptr<TestingPrefServiceSimple> simple_pref_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- std::unique_ptr<TestDataReductionProxyIOData> io_data,
+ std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory,
std::unique_ptr<DataReductionProxySettings> settings,
+ std::unique_ptr<DataReductionProxyService> service,
+ std::unique_ptr<network::TestNetworkQualityTracker>
+ test_network_quality_tracker,
std::unique_ptr<TestConfigStorer> config_storer,
TestDataReductionProxyParams* params,
unsigned int test_context_flags);
- std::unique_ptr<DataReductionProxyService>
- CreateDataReductionProxyServiceInternal(DataReductionProxySettings* settings);
-
unsigned int test_context_flags_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -486,11 +451,12 @@ class DataReductionProxyTestContext {
test_shared_url_loader_factory_;
std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory_;
- std::unique_ptr<TestDataReductionProxyIOData> io_data_;
std::unique_ptr<DataReductionProxySettings> settings_;
- std::unique_ptr<TestConfigStorer> config_storer_;
+ DataReductionProxyService* data_reduction_proxy_service_;
std::unique_ptr<network::TestNetworkQualityTracker>
test_network_quality_tracker_;
+ std::unique_ptr<DataReductionProxyService> service_;
+ std::unique_ptr<TestConfigStorer> config_storer_;
TestDataReductionProxyParams* params_;
diff --git a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc
index 9048ce985d4..e33b64207ef 100644
--- a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.cc
@@ -61,19 +61,8 @@ class NetworkPropertiesManager::PrefManager {
~PrefManager() {}
- base::WeakPtr<PrefManager> GetWeakPtr() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return ui_weak_ptr_factory_.GetWeakPtr();
- }
-
- void ShutdownOnUIThread() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- ui_weak_ptr_factory_.InvalidateWeakPtrs();
- }
-
- void OnChangeInNetworkPropertyOnUIThread(
- const std::string& network_id,
- const NetworkProperties& network_properties) {
+ void OnChangeInNetworkProperty(const std::string& network_id,
+ const NetworkProperties& network_properties) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string serialized_network_properties;
@@ -174,26 +163,17 @@ class NetworkPropertiesManager::PrefManager {
SEQUENCE_CHECKER(sequence_checker_);
- // Used to get |weak_ptr_| to self on the UI thread.
- base::WeakPtrFactory<PrefManager> ui_weak_ptr_factory_{this};
-
DISALLOW_COPY_AND_ASSIGN(PrefManager);
};
-NetworkPropertiesManager::NetworkPropertiesManager(
- base::Clock* clock,
- PrefService* pref_service,
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
+NetworkPropertiesManager::NetworkPropertiesManager(base::Clock* clock,
+ PrefService* pref_service)
: clock_(clock),
- ui_task_runner_(ui_task_runner),
network_properties_container_(ConvertDictionaryValueToParsedPrefs(
pref_service->GetDictionary(prefs::kNetworkProperties))) {
- DCHECK(ui_task_runner_);
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
DCHECK(clock_);
- pref_manager_.reset(new PrefManager(clock_, pref_service));
- pref_manager_weak_ptr_ = pref_manager_->GetWeakPtr();
+ pref_manager_ = std::make_unique<PrefManager>(clock_, pref_service);
ResetWarmupURLFetchMetrics();
@@ -201,24 +181,11 @@ NetworkPropertiesManager::NetworkPropertiesManager(
}
NetworkPropertiesManager::~NetworkPropertiesManager() {
- if (ui_task_runner_->RunsTasksInCurrentSequence() && pref_manager_) {
- pref_manager_->ShutdownOnUIThread();
- }
}
void NetworkPropertiesManager::DeleteHistory() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&NetworkPropertiesManager::PrefManager::DeleteHistory,
- pref_manager_weak_ptr_));
-}
-
-void NetworkPropertiesManager::ShutdownOnUIThread() {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- pref_manager_->ShutdownOnUIThread();
- pref_manager_.reset();
+ pref_manager_->DeleteHistory();
}
void NetworkPropertiesManager::OnChangeInNetworkID(
@@ -259,7 +226,7 @@ void NetworkPropertiesManager::ResetWarmupURLFetchMetrics() {
warmup_url_fetch_attempt_counts_insecure_non_core_ = 0;
}
-void NetworkPropertiesManager::OnChangeInNetworkPropertyOnIOThread() {
+void NetworkPropertiesManager::OnChangeInNetworkProperty() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
network_properties_.set_last_modified(clock_->Now().ToJavaTime());
@@ -268,11 +235,7 @@ void NetworkPropertiesManager::OnChangeInNetworkPropertyOnIOThread() {
network_properties_container_.emplace(
std::make_pair(network_id_, network_properties_));
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&NetworkPropertiesManager::PrefManager::
- OnChangeInNetworkPropertyOnUIThread,
- pref_manager_weak_ptr_, network_id_, network_properties_));
+ pref_manager_->OnChangeInNetworkProperty(network_id_, network_properties_);
}
// static
@@ -317,7 +280,7 @@ void NetworkPropertiesManager::SetIsSecureProxyDisallowedByCarrier(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
network_properties_.set_secure_proxy_disallowed_by_carrier(
disallowed_by_carrier);
- OnChangeInNetworkPropertyOnIOThread();
+ OnChangeInNetworkProperty();
}
bool NetworkPropertiesManager::IsCaptivePortal() const {
@@ -328,7 +291,7 @@ bool NetworkPropertiesManager::IsCaptivePortal() const {
void NetworkPropertiesManager::SetIsCaptivePortal(bool is_captive_portal) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
network_properties_.set_has_captive_portal(is_captive_portal);
- OnChangeInNetworkPropertyOnIOThread();
+ OnChangeInNetworkProperty();
}
bool NetworkPropertiesManager::HasWarmupURLProbeFailed(
@@ -402,7 +365,7 @@ void NetworkPropertiesManager::SetHasWarmupURLProbeFailed(
network_properties_.mutable_insecure_non_core_proxy_flags()
->set_disallowed_due_to_warmup_probe_failure(warmup_url_probe_failed);
}
- OnChangeInNetworkPropertyOnIOThread();
+ OnChangeInNetworkProperty();
}
bool NetworkPropertiesManager::ShouldFetchWarmupProbeURL(
diff --git a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h
index b03c1e2f8c9..be7937bef0a 100644
--- a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h
+++ b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager.h
@@ -22,24 +22,16 @@ class Value;
namespace data_reduction_proxy {
-// Stores the properties of a single network. Created on the UI thread, but
-// lives on the IO thread. Guaranteed to be destroyed on IO thread if the IO
-// thread is still available at the time of destruction. If the IO thread is
-// unavailable, then the destruction will happen on the UI thread.
+// Stores the properties of a single network. Lives on the IO thread.
class NetworkPropertiesManager {
public:
- NetworkPropertiesManager(
- base::Clock* clock,
- PrefService* pref_service,
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner);
+ NetworkPropertiesManager(base::Clock* clock, PrefService* pref_service);
virtual ~NetworkPropertiesManager();
// Called when the user clears the browsing history.
void DeleteHistory();
- void ShutdownOnUIThread();
-
void OnChangeInNetworkID(const std::string& network_id);
// Returns true if usage of secure proxies are allowed on the current network.
@@ -100,13 +92,12 @@ class NetworkPropertiesManager {
typedef std::map<std::string, NetworkProperties> NetworkPropertiesContainer;
// PrefManager writes or updates the network properties prefs. Created on
- // UI thread, and should be used on the UI thread. May be destroyed on UI
- // or IO thread.
+ // UI thread, and should be used on the UI thread.
class PrefManager;
// Called when there is a change in the network property of the current
// network.
- void OnChangeInNetworkPropertyOnIOThread();
+ void OnChangeInNetworkProperty();
static NetworkPropertiesContainer ConvertDictionaryValueToParsedPrefs(
const base::Value* value);
@@ -114,10 +105,7 @@ class NetworkPropertiesManager {
// Clock used for querying current time. Guaranteed to be non-null.
base::Clock* clock_;
- // Task runner on which prefs should be accessed.
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
-
- // Network properties of different networks. Should be accessed on the IO
+ // Network properties of different networks. Should be accessed on the UI
// thread.
NetworkPropertiesContainer network_properties_container_;
@@ -155,4 +143,4 @@ class NetworkPropertiesManager {
} // namespace data_reduction_proxy
-#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_NETWORK_PROPERTIES_MANAGER_H_ \ No newline at end of file
+#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_NETWORK_PROPERTIES_MANAGER_H_
diff --git a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc
index 332eae551bc..0b5cb36be9f 100644
--- a/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/network_properties_manager_unittest.cc
@@ -12,8 +12,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
@@ -29,17 +29,11 @@ namespace {
class TestNetworkPropertiesManager : public NetworkPropertiesManager {
public:
- TestNetworkPropertiesManager(
- PrefService* pref_service,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+ TestNetworkPropertiesManager(PrefService* pref_service)
: TestNetworkPropertiesManager(base::DefaultClock::GetInstance(),
- pref_service,
- ui_task_runner) {}
- TestNetworkPropertiesManager(
- base::Clock* clock,
- PrefService* pref_service,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
- : NetworkPropertiesManager(clock, pref_service, ui_task_runner) {}
+ pref_service) {}
+ TestNetworkPropertiesManager(base::Clock* clock, PrefService* pref_service)
+ : NetworkPropertiesManager(clock, pref_service) {}
~TestNetworkPropertiesManager() override {}
};
@@ -47,10 +41,9 @@ TEST(NetworkPropertyTest, TestSetterGetterCaptivePortal) {
base::HistogramTester histogram_tester;
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
std::string network_id("test");
network_properties_manager.OnChangeInNetworkID(network_id);
@@ -71,8 +64,7 @@ TEST(NetworkPropertyTest, TestSetterGetterCaptivePortal) {
EXPECT_TRUE(
test_prefs.GetDictionary(prefs::kNetworkProperties)->HasKey(network_id));
{
- TestNetworkPropertiesManager network_properties_manager_2(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_2(&test_prefs);
network_properties_manager_2.OnChangeInNetworkID(network_id);
EXPECT_TRUE(network_properties_manager_2.IsCaptivePortal());
}
@@ -84,8 +76,7 @@ TEST(NetworkPropertyTest, TestSetterGetterCaptivePortal) {
base::RunLoop().RunUntilIdle();
{
- TestNetworkPropertiesManager network_properties_manager_2(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_2(&test_prefs);
network_properties_manager_2.OnChangeInNetworkID(network_id);
EXPECT_FALSE(network_properties_manager_2.IsCaptivePortal());
}
@@ -101,10 +92,9 @@ TEST(NetworkPropertyTest, TestSetterGetterCaptivePortal) {
TEST(NetworkPropertyTest, TestSetterGetterDisallowedByCarrier) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
network_properties_manager.SetIsSecureProxyDisallowedByCarrier(true);
EXPECT_FALSE(network_properties_manager.IsSecureProxyAllowed(true));
@@ -120,10 +110,9 @@ TEST(NetworkPropertyTest, TestSetterGetterDisallowedByCarrier) {
TEST(NetworkPropertyTest, TestWarmupURLFailedOnSecureCoreProxy) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
network_properties_manager.SetHasWarmupURLProbeFailed(
true /* secure_proxy */, true /* is_core_proxy */,
@@ -147,10 +136,9 @@ TEST(NetworkPropertyTest, TestWarmupURLFailedOnSecureCoreProxy) {
TEST(NetworkPropertyTest, TestWarmupURLFailedOnInSecureCoreProxy) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
EXPECT_TRUE(network_properties_manager.IsInsecureProxyAllowed(true));
EXPECT_TRUE(network_properties_manager.IsSecureProxyAllowed(true));
@@ -177,10 +165,9 @@ TEST(NetworkPropertyTest, TestWarmupURLFailedOnInSecureCoreProxy) {
TEST(NetworkPropertyTest, TestLimitPrefSize) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
size_t num_network_ids = 100;
@@ -217,8 +204,7 @@ TEST(NetworkPropertyTest, TestLimitPrefSize) {
}
{
- TestNetworkPropertiesManager network_properties_manager_2(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_2(&test_prefs);
for (size_t i = 0; i < num_network_ids; ++i) {
std::string network_id("test" + base::NumberToString(i));
network_properties_manager_2.OnChangeInNetworkID(network_id);
@@ -239,10 +225,9 @@ TEST(NetworkPropertyTest, TestLimitPrefSize) {
TEST(NetworkPropertyTest, TestChangeNetworkIDBackAndForth) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
// First network ID has a captive portal.
std::string first_network_id("test1");
@@ -289,10 +274,9 @@ TEST(NetworkPropertyTest, TestChangeNetworkIDBackAndForth) {
TEST(NetworkPropertyTest, TestNetworkQualitiesOverwrite) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
// First network ID has a captive portal.
std::string first_network_id("test1");
@@ -341,10 +325,9 @@ TEST(NetworkPropertyTest, TestDeleteHistory) {
base::HistogramTester histogram_tester;
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
std::string network_id("test");
network_properties_manager.OnChangeInNetworkID(network_id);
@@ -370,8 +353,7 @@ TEST(NetworkPropertyTest, TestDeleteHistory) {
EXPECT_TRUE(
test_prefs.GetDictionary(prefs::kNetworkProperties)->HasKey(network_id));
{
- TestNetworkPropertiesManager network_properties_manager_2(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_2(&test_prefs);
network_properties_manager_2.OnChangeInNetworkID(network_id);
EXPECT_TRUE(network_properties_manager_2.IsCaptivePortal());
histogram_tester.ExpectBucketCount(
@@ -384,8 +366,7 @@ TEST(NetworkPropertyTest, TestDeleteHistory) {
network_properties_manager.DeleteHistory();
base::RunLoop().RunUntilIdle();
{
- TestNetworkPropertiesManager network_properties_manager_2(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_2(&test_prefs);
network_properties_manager_2.OnChangeInNetworkID(network_id);
EXPECT_FALSE(network_properties_manager_2.IsCaptivePortal());
histogram_tester.ExpectBucketCount(
@@ -402,10 +383,10 @@ TEST(NetworkPropertyTest, TestDeleteOldValues) {
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_clock, &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_clock,
+ &test_prefs);
for (size_t i = 0; i < 5; ++i) {
std::string network_id("test" + base::NumberToString(i));
@@ -433,8 +414,8 @@ TEST(NetworkPropertyTest, TestDeleteOldValues) {
// Entries should not be cleared since all values are less than 30 days old.
{
- TestNetworkPropertiesManager network_properties_manager_2(
- &test_clock, &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_2(&test_clock,
+ &test_prefs);
for (size_t i = 0; i < 10; ++i) {
std::string network_id("test" + base::NumberToString(i));
@@ -446,8 +427,8 @@ TEST(NetworkPropertyTest, TestDeleteOldValues) {
// Only the entries from 5 to 9 should be cleared since they are 40 days old.
test_clock.Advance(base::TimeDelta::FromDays(20));
{
- TestNetworkPropertiesManager network_properties_manager_3(
- &test_clock, &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ TestNetworkPropertiesManager network_properties_manager_3(&test_clock,
+ &test_prefs);
for (size_t i = 0; i < 10; ++i) {
std::string network_id("test" + base::NumberToString(i));
EXPECT_EQ(i >= 5, test_prefs.GetDictionary(prefs::kNetworkProperties)
@@ -462,10 +443,9 @@ TEST(NetworkPropertyTest,
TestingPrefServiceSimple test_prefs;
test_prefs.registry()->RegisterDictionaryPref(prefs::kNetworkProperties);
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
- TestNetworkPropertiesManager network_properties_manager(
- &test_prefs, base::ThreadTaskRunnerHandle::Get());
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
+ TestNetworkPropertiesManager network_properties_manager(&test_prefs);
// First network ID has a captive portal and the canary check failed.
std::string first_network_id("test1");
diff --git a/chromium/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc b/chromium/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc
index a62ccfe6a27..4fd75d00854 100644
--- a/chromium/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc
@@ -97,7 +97,7 @@ void SecureProxyChecker::CheckIfSecureProxyIsAllowed(
resource_request->url = params::GetSecureProxyCheckURL();
resource_request->load_flags =
net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
diff --git a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
index 51338fce8b7..de9c4ca1f9a 100644
--- a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
@@ -31,13 +31,14 @@ namespace {
const int kInvalidResponseCode = -1;
-void BindNetworkContextOnUI(network::mojom::CustomProxyConfigPtr config,
- network::mojom::NetworkContextRequest request,
- const std::string& user_agent) {
+void BindNetworkContext(
+ network::mojom::CustomProxyConfigPtr config,
+ mojo::PendingReceiver<network::mojom::NetworkContext> receiver,
+ const std::string& user_agent) {
auto params = network::mojom::NetworkContextParams::New();
params->user_agent = user_agent;
params->initial_custom_proxy_config = std::move(config);
- content::GetNetworkService()->CreateNetworkContext(std::move(request),
+ content::GetNetworkService()->CreateNetworkContext(std::move(receiver),
std::move(params));
}
}
@@ -46,15 +47,13 @@ WarmupURLFetcher::WarmupURLFetcher(
CreateCustomProxyConfigCallback create_custom_proxy_config_callback,
WarmupURLFetcherCallback callback,
GetHttpRttCallback get_http_rtt_callback,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const std::string& user_agent)
: is_fetch_in_flight_(false),
previous_attempt_counts_(0),
create_custom_proxy_config_callback_(create_custom_proxy_config_callback),
callback_(callback),
get_http_rtt_callback_(get_http_rtt_callback),
- user_agent_(user_agent),
- ui_task_runner_(ui_task_runner) {
+ user_agent_(user_agent) {
DCHECK(create_custom_proxy_config_callback);
DCHECK(!params::IsIncludedInHoldbackFieldTrial());
}
@@ -171,11 +170,8 @@ network::mojom::URLLoaderFactory*
WarmupURLFetcher::GetNetworkServiceURLLoaderFactory(
const DataReductionProxyServer& proxy_server) {
network::mojom::NetworkContextPtr context;
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BindNetworkContextOnUI,
- create_custom_proxy_config_callback_.Run({proxy_server}),
- mojo::MakeRequest(&context_), user_agent_));
+ BindNetworkContext(create_custom_proxy_config_callback_.Run({proxy_server}),
+ mojo::MakeRequest(&context_), user_agent_);
auto factory_params = network::mojom::URLLoaderFactoryParams::New();
factory_params->process_id = network::mojom::kBrowserProcessId;
diff --git a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
index fe60789e5aa..92edc0c74b9 100644
--- a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
+++ b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
@@ -52,7 +52,6 @@ class WarmupURLFetcher {
CreateCustomProxyConfigCallback create_custom_proxy_config_callback,
WarmupURLFetcherCallback callback,
GetHttpRttCallback get_http_rtt_callback,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const std::string& user_agent);
virtual ~WarmupURLFetcher();
@@ -142,8 +141,6 @@ class WarmupURLFetcher {
const std::string user_agent_;
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
-
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(WarmupURLFetcher);
diff --git a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
index 9b52e9561cf..843f7b3ab8f 100644
--- a/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
@@ -16,7 +16,7 @@
#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
@@ -49,7 +49,6 @@ class WarmupURLFetcherTest : public WarmupURLFetcher {
base::Unretained(this)),
base::BindRepeating(&WarmupURLFetcherTest::GetHttpRttEstimate,
base::Unretained(this)),
- base::ThreadTaskRunnerHandle::Get(),
std::string() /*user_agent*/),
url_loader_factory_(url_loader_factory) {}
~WarmupURLFetcherTest() override {}
@@ -127,7 +126,7 @@ class WarmupURLFetcherTest : public WarmupURLFetcher {
// Test that query param for the warmup URL is randomly set.
TEST(WarmupURLFetcherTest, TestGetWarmupURLWithQueryParam) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
@@ -158,7 +157,7 @@ TEST(WarmupURLFetcherTest, TestGetWarmupURLWithQueryParam) {
}
TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLNoViaHeader) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
base::HistogramTester histogram_tester;
@@ -168,7 +167,7 @@ TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLNoViaHeader) {
EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
warmup_url_fetcher.FetchWarmupURL(0, DataReductionProxyServer(proxy_server));
EXPECT_TRUE(warmup_url_fetcher.IsFetchInFlight());
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
auto resource_response_head =
network::CreateResourceResponseHead(net::HTTP_OK);
@@ -204,7 +203,7 @@ TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLNoViaHeader) {
}
TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithViaHeader) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
base::HistogramTester histogram_tester;
@@ -214,7 +213,7 @@ TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithViaHeader) {
EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
warmup_url_fetcher.FetchWarmupURL(0, DataReductionProxyServer(proxy_server));
EXPECT_TRUE(warmup_url_fetcher.IsFetchInFlight());
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
auto resource_response_head =
network::CreateResourceResponseHead(net::HTTP_NOT_FOUND);
@@ -256,7 +255,7 @@ TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithViaHeader) {
TEST(WarmupURLFetcherTest,
TestSuccessfulFetchWarmupURLWithViaHeaderExperimentNotEnabled) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
base::HistogramTester histogram_tester;
@@ -296,7 +295,7 @@ TEST(WarmupURLFetcherTest,
}
TEST(WarmupURLFetcherTest, TestConnectionResetFetchWarmupURL) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
base::HistogramTester histogram_tester;
@@ -338,7 +337,7 @@ TEST(WarmupURLFetcherTest, TestConnectionResetFetchWarmupURL) {
}
TEST(WarmupURLFetcherTest, TestFetchTimesout) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
base::HistogramTester histogram_tester;
@@ -373,8 +372,8 @@ TEST(WarmupURLFetcherTest, TestFetchTimesout) {
}
TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithDelay) {
- base::test::ScopedTaskEnvironment scoped_task_environment(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME);
network::TestURLLoaderFactory test_url_loader_factory;
base::HistogramTester histogram_tester;
@@ -384,7 +383,7 @@ TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithDelay) {
EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
warmup_url_fetcher.SetFetchWaitTime(base::TimeDelta::FromMilliseconds(1));
warmup_url_fetcher.FetchWarmupURL(1, DataReductionProxyServer(proxy_server));
- scoped_task_environment.FastForwardBy(base::TimeDelta::FromMilliseconds(2));
+ task_environment.FastForwardBy(base::TimeDelta::FromMilliseconds(2));
auto resource_response_head =
network::CreateResourceResponseHead(net::HTTP_NOT_FOUND);
@@ -431,7 +430,7 @@ TEST(WarmupURLFetcherTest, TestFetchTimeoutIncreasing) {
base::HistogramTester histogram_tester;
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
DataReductionProxyServer proxy_server(net::ProxyServer::Direct());
@@ -461,7 +460,7 @@ TEST(WarmupURLFetcherTest, TestFetchTimeoutIncreasing) {
TEST(WarmupURLFetcherTest, TestFetchWaitTime) {
base::HistogramTester histogram_tester;
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
network::TestURLLoaderFactory test_url_loader_factory;
DataReductionProxyServer proxy_server(net::ProxyServer::Direct());
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index 0d05569aa0d..ef5e55f12e6 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -22,7 +22,6 @@
#include "net/base/host_port_pair.h"
#include "net/base/proxy_server.h"
#include "net/http/http_status_code.h"
-#include "services/network/public/cpp/features.h"
#include "url/url_constants.h"
#if defined(OS_ANDROID)
@@ -364,9 +363,8 @@ GURL GetSecureProxyCheckURL() {
bool IsEnabledWithNetworkService() {
return base::FeatureList::IsEnabled(
- data_reduction_proxy::features::
- kDataReductionProxyEnabledWithNetworkService) &&
- base::FeatureList::IsEnabled(network::features::kNetworkService);
+ data_reduction_proxy::features::
+ kDataReductionProxyEnabledWithNetworkService);
}
base::Optional<DataReductionProxyTypeInfo> FindConfiguredProxyInVector(
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc
index 334edd3c4b6..81996a64989 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.cc
@@ -50,4 +50,13 @@ TestDataReductionProxyParams::TestDataReductionProxyParams()
return DataReductionProxyParams::proxies_for_http();
}
+net::ProxyList TestDataReductionProxyParams::GetAllConfiguredProxies() const {
+ return configured_proxies_;
+}
+
+void TestDataReductionProxyParams::SetConfiguredProxies(
+ const net::ProxyList& configured_proxies) {
+ configured_proxies_ = configured_proxies;
+}
+
} // namespace data_reduction_proxy
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h
index 819063316fc..10cc6f8fb5f 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h
@@ -28,10 +28,15 @@ class TestDataReductionProxyParams : public DataReductionProxyParams {
const std::vector<DataReductionProxyServer>& proxies_for_http()
const override;
+ net::ProxyList GetAllConfiguredProxies() const override;
+
+ void SetConfiguredProxies(const net::ProxyList& configured_proxies);
+
private:
bool override_non_secure_proxies_;
std::vector<DataReductionProxyServer> proxies_for_http_;
+ net::ProxyList configured_proxies_;
};
} // namespace data_reduction_proxy
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc
index 9b517287d7a..9ba228358c6 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.cc
@@ -9,75 +9,6 @@
namespace data_reduction_proxy {
namespace prefs {
-// A List pref that contains daily totals of the size of all HTTPS
-// content received when the data reduction proxy was enabled.
-const char kDailyContentLengthHttpsWithDataReductionProxyEnabled[] =
- "data_reduction.daily_received_length_https_with_"
- "data_reduction_proxy_enabled";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content received when a bypass of more than 30 minutes is in effect.
-const char kDailyContentLengthLongBypassWithDataReductionProxyEnabled[] =
- "data_reduction.daily_received_length_long_bypass_with_"
- "data_reduction_proxy_enabled";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content received when a bypass of less than 30 minutes is in effect.
-const char kDailyContentLengthShortBypassWithDataReductionProxyEnabled[] =
- "data_reduction.daily_received_length_short_bypass_with_"
- "data_reduction_proxy_enabled";
-
-// TODO(bengr): what is this?
-const char kDailyContentLengthUnknownWithDataReductionProxyEnabled[] =
- "data_reduction.daily_received_length_unknown_with_"
- "data_reduction_proxy_enabled";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content received via the data reduction proxy.
-const char kDailyContentLengthViaDataReductionProxy[] =
- "data_reduction.daily_received_length_via_data_reduction_proxy";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content with application mime-type received via the data reduction proxy.
-const char kDailyContentLengthViaDataReductionProxyApplication[] =
- "data_reduction.daily_received_length_via_data_reduction_proxy_application";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content with video mime-type received via the data reduction proxy.
-const char kDailyContentLengthViaDataReductionProxyVideo[] =
- "data_reduction.daily_received_length_via_data_reduction_proxy_video";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content with unknown mime-type received via the data reduction proxy.
-const char kDailyContentLengthViaDataReductionProxyUnknown[] =
- "data_reduction.daily_received_length_via_data_reduction_proxy_unknown";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content received while the data reduction proxy is enabled.
-const char kDailyContentLengthWithDataReductionProxyEnabled[] =
- "data_reduction.daily_received_length_with_data_reduction_proxy_enabled";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content with application mime-type received while the data reduction proxy is
-// enabled.
-const char kDailyContentLengthWithDataReductionProxyEnabledApplication[] =
- "data_reduction.daily_received_length_with_data_reduction_proxy_enabled_"
- "application";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content with video mime-type received while the data reduction proxy is
-// enabled.
-const char kDailyContentLengthWithDataReductionProxyEnabledVideo[] =
- "data_reduction.daily_received_length_with_data_reduction_proxy_enabled_"
- "video";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS
-// content with unknown mime-type received while the data reduction proxy is
-// enabled.
-const char kDailyContentLengthWithDataReductionProxyEnabledUnknown[] =
- "data_reduction.daily_received_length_with_data_reduction_proxy_enabled_"
- "unknown";
-
// An int64_t pref that contains an internal representation of midnight on the
// date of the last update to |kDailyHttp{Original,Received}ContentLength|.
const char kDailyHttpContentLengthLastUpdateDate[] =
@@ -88,88 +19,11 @@ const char kDailyHttpContentLengthLastUpdateDate[] =
const char kDailyHttpOriginalContentLength[] =
"data_reduction.daily_original_length";
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with application mime-type received from the network.
-const char kDailyHttpOriginalContentLengthApplication[] =
- "data_reduction.daily_original_length_application";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with video mime-type received from the network.
-const char kDailyHttpOriginalContentLengthVideo[] =
- "data_reduction.daily_original_length_video";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with unknown mime-type received from the network.
-const char kDailyHttpOriginalContentLengthUnknown[] =
- "data_reduction.daily_original_length_unknown";
-
// A List pref that contains daily totals of the size of all HTTP/HTTPS content
// received from the network.
const char kDailyHttpReceivedContentLength[] =
"data_reduction.daily_received_length";
-// A List pref that contains daily totals of the size of all HTTP/HTTPS content
-// received with application mime-type from the network.
-const char kDailyHttpReceivedContentLengthApplication[] =
- "data_reduction.daily_received_length_application";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS content
-// received with video mime-type from the network.
-const char kDailyHttpReceivedContentLengthVideo[] =
- "data_reduction.daily_received_length_video";
-
-// A List pref that contains daily totals of the size of all HTTP/HTTPS content
-// received with unknown mime-type from the network.
-const char kDailyHttpReceivedContentLengthUnknown[] =
- "data_reduction.daily_received_length_unknown";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content received via the data reduction proxy.
-const char kDailyOriginalContentLengthViaDataReductionProxy[] =
- "data_reduction.daily_original_length_via_data_reduction_proxy";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with application mime-type received via the data reduction proxy.
-const char kDailyOriginalContentLengthViaDataReductionProxyApplication[] =
- "data_reduction.daily_original_length_via_data_reduction_proxy_application";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with video mime-type received via the data reduction proxy.
-const char kDailyOriginalContentLengthViaDataReductionProxyVideo[] =
- "data_reduction.daily_original_length_via_data_reduction_proxy_video";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with unknown mime-type received via the data reduction proxy.
-const char kDailyOriginalContentLengthViaDataReductionProxyUnknown[] =
- "data_reduction.daily_original_length_via_data_reduction_proxy_unknown";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content received while the data reduction proxy is enabled.
-const char kDailyOriginalContentLengthWithDataReductionProxyEnabled[] =
- "data_reduction.daily_original_length_with_data_reduction_proxy_enabled";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with application mime type received while the data reduction proxy is
-// enabled.
-const char
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication[] =
- "data_reduction.daily_original_length_with_data_reduction_proxy_"
- "enabled_application";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with video mime type received while the data reduction proxy is
-// enabled.
-const char kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo[] =
- "data_reduction.daily_original_length_with_data_reduction_proxy_enabled_"
- "video";
-
-// A List pref that contains daily totals of the original size of all HTTP/HTTPS
-// content with unknown mime type received while the data reduction proxy is
-// enabled.
-const char kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown[] =
- "data_reduction.daily_original_length_with_data_reduction_proxy_enabled_"
- "unknown";
-
// String that specifies the origin allowed to use data reduction proxy
// authentication, if any.
const char kDataReductionProxy[] = "auth.spdyproxy.origin";
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h
index c1f2689b04c..57bcb3ede89 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h
@@ -11,38 +11,10 @@ namespace prefs {
// Alphabetical list of preference names specific to the data_reduction_proxy
// component. Keep alphabetized, and document each in the .cc file.
-extern const char kDailyContentLengthHttpsWithDataReductionProxyEnabled[];
-extern const char kDailyContentLengthLongBypassWithDataReductionProxyEnabled[];
-extern const char kDailyContentLengthShortBypassWithDataReductionProxyEnabled[];
-extern const char kDailyContentLengthUnknownWithDataReductionProxyEnabled[];
-extern const char kDailyContentLengthViaDataReductionProxy[];
-extern const char kDailyContentLengthViaDataReductionProxyApplication[];
-extern const char kDailyContentLengthViaDataReductionProxyVideo[];
-extern const char kDailyContentLengthViaDataReductionProxyUnknown[];
-extern const char kDailyContentLengthWithDataReductionProxyEnabled[];
-extern const char kDailyContentLengthWithDataReductionProxyEnabledApplication[];
-extern const char kDailyContentLengthWithDataReductionProxyEnabledVideo[];
-extern const char kDailyContentLengthWithDataReductionProxyEnabledUnknown[];
extern const char kDailyHttpContentLengthLastUpdateDate[];
extern const char kDailyHttpOriginalContentLength[];
-extern const char kDailyHttpOriginalContentLengthApplication[];
-extern const char kDailyHttpOriginalContentLengthVideo[];
-extern const char kDailyHttpOriginalContentLengthUnknown[];
extern const char kDailyHttpReceivedContentLength[];
-extern const char kDailyHttpReceivedContentLengthApplication[];
-extern const char kDailyHttpReceivedContentLengthVideo[];
-extern const char kDailyHttpReceivedContentLengthUnknown[];
-extern const char kDailyOriginalContentLengthViaDataReductionProxy[];
-extern const char kDailyOriginalContentLengthViaDataReductionProxyApplication[];
-extern const char kDailyOriginalContentLengthViaDataReductionProxyVideo[];
-extern const char kDailyOriginalContentLengthViaDataReductionProxyUnknown[];
-extern const char kDailyOriginalContentLengthWithDataReductionProxyEnabled[];
-extern const char
- kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication[];
-extern const char
- kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo[];
-extern const char
- kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown[];
+
extern const char kDataReductionProxy[];
extern const char kDataSaverEnabled[];
extern const char kDataReductionProxyConfig[];
diff --git a/chromium/components/data_use_measurement/core/data_use_measurement.cc b/chromium/components/data_use_measurement/core/data_use_measurement.cc
index 8386d27a445..d1fb95ece21 100644
--- a/chromium/components/data_use_measurement/core/data_use_measurement.cc
+++ b/chromium/components/data_use_measurement/core/data_use_measurement.cc
@@ -57,7 +57,7 @@ DataUseMeasurement::DataUseMeasurement(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(network_connection_tracker_);
- network_connection_tracker_->AddNetworkConnectionObserver(this);
+ network_connection_tracker_->AddLeakyNetworkConnectionObserver(this);
#if defined(OS_ANDROID)
int64_t bytes = 0;
diff --git a/chromium/components/dbus/menu/BUILD.gn b/chromium/components/dbus/menu/BUILD.gn
index 394ca48970e..ad0135d107f 100644
--- a/chromium/components/dbus/menu/BUILD.gn
+++ b/chromium/components/dbus/menu/BUILD.gn
@@ -2,10 +2,14 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/ui.gni")
+
component("menu") {
sources = [
"menu.cc",
"menu.h",
+ "menu_property_list.cc",
+ "menu_property_list.h",
"properties_interface.cc",
"properties_interface.h",
"success_barrier_callback.cc",
@@ -17,17 +21,24 @@ component("menu") {
deps = [
"//base",
"//base:i18n",
+ ]
+ public_deps = [
"//dbus",
"//skia",
"//ui/base",
"//ui/gfx",
]
+ if (use_x11) {
+ configs += [ "//build/config/linux:x11" ]
+ }
}
source_set("unit_tests") {
testonly = true
sources = [
+ "menu_property_list_unittest.cc",
"success_barrier_callback_unittest.cc",
+ "types_unittest.cc",
]
deps = [
":menu",
diff --git a/chromium/components/dbus/menu/DEPS b/chromium/components/dbus/menu/DEPS
index 153f3f495cf..0d3f0e92940 100644
--- a/chromium/components/dbus/menu/DEPS
+++ b/chromium/components/dbus/menu/DEPS
@@ -1,4 +1,6 @@
include_rules = [
"+dbus",
"+ui/base",
+ "+ui/events/keycodes",
+ "+ui/gfx/image",
]
diff --git a/chromium/components/dbus/menu/menu.cc b/chromium/components/dbus/menu/menu.cc
index 5d409095512..b02b8070068 100644
--- a/chromium/components/dbus/menu/menu.cc
+++ b/chromium/components/dbus/menu/menu.cc
@@ -6,6 +6,7 @@
#include <limits>
#include <memory>
+#include <set>
#include "base/bind.h"
#include "base/callback.h"
@@ -17,7 +18,6 @@
#include "components/dbus/menu/properties_interface.h"
#include "components/dbus/menu/success_barrier_callback.h"
#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/models/simple_menu_model.h"
@@ -46,6 +46,7 @@ const char kPropertyValueStatusNormal[] = "normal";
uint32_t kPropertyValueVersion = 3;
// Signals.
+const char kSignalItemsPropertiesUpdated[] = "ItemsPropertiesUpdated";
const char kSignalLayoutUpdated[] = "LayoutUpdated";
// Creates a variant with the default value for |property_name|, or an empty
@@ -78,6 +79,20 @@ DbusString DbusTextDirection() {
return DbusString(base::i18n::IsRTL() ? "rtl " : "ltr");
}
+void WriteRemovedProperties(dbus::MessageWriter* writer,
+ const MenuPropertyChanges& removed_props) {
+ dbus::MessageWriter removed_props_writer(nullptr);
+ writer->OpenArray("(ias)", &removed_props_writer);
+ for (const auto& pair : removed_props) {
+ dbus::MessageWriter struct_writer(nullptr);
+ removed_props_writer.OpenStruct(&struct_writer);
+ struct_writer.AppendInt32(pair.first);
+ struct_writer.AppendArrayOfStrings(pair.second);
+ removed_props_writer.CloseContainer(&struct_writer);
+ }
+ writer->CloseContainer(&removed_props_writer);
+}
+
} // namespace
DbusMenu::MenuItem::MenuItem(int32_t id,
@@ -165,24 +180,66 @@ DbusMenu::~DbusMenu() = default;
void DbusMenu::SetModel(ui::MenuModel* model, bool send_signal) {
items_.clear();
+ std::map<std::string, DbusVariant> properties;
+ std::vector<int32_t> children;
if (model) {
- std::map<std::string, DbusVariant> properties;
properties["children-display"] = MakeDbusVariant(DbusString("submenu"));
- items_[0] = std::make_unique<MenuItem>(
- 0, std::move(properties), ConvertMenu(model), nullptr, nullptr, -1);
- } else {
- items_[0] = std::make_unique<MenuItem>(
- 0, std::map<std::string, DbusVariant>(), std::vector<int32_t>(),
- nullptr, nullptr, -1);
+ children = ConvertMenu(model);
}
+ items_[0] = std::make_unique<MenuItem>(
+ 0, std::move(properties), std::move(children), nullptr, nullptr, -1);
+
+ if (send_signal)
+ SendLayoutChangedSignal(0);
+}
- if (send_signal) {
- dbus::Signal signal(kInterfaceDbusMenu, kSignalLayoutUpdated);
- dbus::MessageWriter writer(&signal);
- writer.AppendUint32(++revision_); // Revision of the new layout.
- writer.AppendInt32(0); // Parent item whose layout changed.
- menu_->SendSignal(&signal);
+void DbusMenu::MenuLayoutUpdated(ui::MenuModel* model) {
+ MenuItem* item = FindMenuItemForModel(model, items_[0].get());
+ DCHECK(item);
+ DeleteItemChildren(item);
+ item->children = ConvertMenu(model);
+ SendLayoutChangedSignal(item->id);
+}
+
+void DbusMenu::MenuItemsPropertiesUpdated(
+ const std::vector<MenuItemReference>& menu_items) {
+ if (menu_items.empty())
+ return;
+
+ MenuPropertyChanges updated_props;
+ MenuPropertyChanges removed_props;
+ for (const auto& menu_item : menu_items) {
+ ui::MenuModel* menu = menu_item.first;
+ int index = menu_item.second;
+ MenuItem* parent = FindMenuItemForModel(menu, items_[0].get());
+ MenuItem* item = nullptr;
+ for (int32_t id : parent->children) {
+ MenuItem* child = items_[id].get();
+ DCHECK_EQ(child->containing_menu, menu);
+ if (child->containing_menu_index == index) {
+ item = child;
+ break;
+ }
+ }
+ DCHECK(item);
+
+ auto old_properties = std::move(item->properties);
+ item->properties = ComputeMenuPropertiesForMenuItem(menu, index);
+ MenuPropertyList item_updated_props;
+ MenuPropertyList item_removed_props;
+ ComputeMenuPropertyChanges(old_properties, item->properties,
+ &item_updated_props, &item_removed_props);
+ if (!item_updated_props.empty())
+ updated_props[item->id] = std::move(item_updated_props);
+ if (!item_removed_props.empty())
+ removed_props[item->id] = std::move(item_removed_props);
}
+
+ dbus::Signal signal(kInterfaceDbusMenu, kSignalItemsPropertiesUpdated);
+ dbus::MessageWriter writer(&signal);
+ WriteUpdatedProperties(&writer, updated_props);
+ WriteRemovedProperties(&writer, removed_props);
+ menu_->SendSignal(&signal);
}
// static
@@ -270,12 +327,12 @@ void DbusMenu::OnGetGroupProperties(ScopedMethodResponse* response) {
dbus::MessageReader id_reader(nullptr);
if (!response->reader().PopArray(&id_reader))
return;
- std::set<int32_t> ids;
+ std::vector<int32_t> ids;
while (id_reader.HasMoreData()) {
int32_t id;
if (!id_reader.PopInt32(&id))
return;
- ids.insert(id);
+ ids.push_back(id);
}
std::set<std::string> property_filter;
@@ -292,15 +349,14 @@ void DbusMenu::OnGetGroupProperties(ScopedMethodResponse* response) {
dbus::MessageWriter& writer = response->Writer();
dbus::MessageWriter item_writer(nullptr);
writer.OpenArray("(ia{sv})", &item_writer);
- for (const auto& item_pair : items_) {
- if (!ids.empty() && !base::Contains(ids, item_pair.first))
- continue;
+
+ auto write_item = [&](int32_t id, const MenuItem& item) {
dbus::MessageWriter struct_writer(nullptr);
item_writer.OpenStruct(&struct_writer);
- struct_writer.AppendInt32(item_pair.first);
+ struct_writer.AppendInt32(id);
dbus::MessageWriter property_writer(nullptr);
struct_writer.OpenArray("{sv}", &property_writer);
- for (const auto& property_pair : item_pair.second->properties) {
+ for (const auto& property_pair : item.properties) {
if (!property_filter.empty() &&
!base::Contains(property_filter, property_pair.first)) {
continue;
@@ -313,7 +369,19 @@ void DbusMenu::OnGetGroupProperties(ScopedMethodResponse* response) {
}
struct_writer.CloseContainer(&property_writer);
item_writer.CloseContainer(&struct_writer);
+ };
+
+ if (ids.empty()) {
+ for (const auto& item_pair : items_)
+ write_item(item_pair.first, *item_pair.second);
+ } else {
+ for (int32_t id : ids) {
+ auto it = items_.find(id);
+ if (it != items_.end())
+ write_item(id, *it->second);
+ }
}
+
writer.CloseContainer(&item_writer);
}
@@ -321,7 +389,7 @@ void DbusMenu::OnGetLayout(ScopedMethodResponse* response) {
dbus::MessageReader& reader = response->reader();
int32_t id;
int32_t depth;
- std::vector<std::string> property_filter;
+ MenuPropertyList property_filter;
if (!reader.PopInt32(&id) || !reader.PopInt32(&depth) || depth < -1 ||
!reader.PopArrayOfStrings(&property_filter)) {
return;
@@ -393,7 +461,8 @@ bool DbusMenu::EventImpl(dbus::MessageReader* reader, int32_t* id_error) {
return false;
item->containing_menu->ActivatedAt(item->containing_menu_index);
} else {
- DCHECK_EQ("hovered", type);
+ DCHECK(type == "hovered" || type == "opened" || type == "closed")
+ << "Unexpected type: " << type;
// Nothing to do.
}
@@ -407,84 +476,13 @@ std::vector<int32_t> DbusMenu::ConvertMenu(ui::MenuModel* menu) {
items.reserve(menu->GetItemCount());
for (int i = 0; i < menu->GetItemCount(); ++i) {
- // Properties should only be set if they differ from the default values.
- std::map<std::string, DbusVariant> properties;
-
- // The dbusmenu interface has no concept of a "sublabel", "minor text", or
- // "minor icon" like MenuModel has. Ignore these rather than trying to
- // merge them with the regular label and icon.
- base::string16 label = menu->GetLabelAt(i);
- if (!label.empty()) {
- properties["label"] = MakeDbusVariant(DbusString(
- ui::ConvertAcceleratorsFromWindowsStyle(base::UTF16ToUTF8(label))));
- }
-
- if (!menu->IsEnabledAt(i))
- properties["enabled"] = MakeDbusVariant(DbusBoolean(false));
- if (!menu->IsVisibleAt(i))
- properties["visible"] = MakeDbusVariant(DbusBoolean(false));
-
- gfx::Image icon;
- if (menu->GetIconAt(i, &icon)) {
- properties["icon-data"] =
- MakeDbusVariant(DbusByteArray(icon.As1xPNGBytes()));
- }
-
- ui::Accelerator accelerator;
- if (menu->GetAcceleratorAt(i, &accelerator)) {
- std::vector<DbusString> parts;
- if (accelerator.IsCtrlDown())
- parts.push_back(DbusString("Control"));
- if (accelerator.IsAltDown())
- parts.push_back(DbusString("Alt"));
- if (accelerator.IsShiftDown())
- parts.push_back(DbusString("Shift"));
- if (accelerator.IsCmdDown())
- parts.push_back(DbusString("Super"));
- parts.push_back(
- DbusString(base::UTF16ToUTF8(accelerator.KeyCodeToName())));
- properties["shortcut"] = MakeDbusVariant(
- MakeDbusArray(DbusArray<DbusString>(std::move(parts))));
- }
-
- switch (menu->GetTypeAt(i)) {
- case ui::MenuModel::TYPE_COMMAND:
- case ui::MenuModel::TYPE_HIGHLIGHTED:
- // Nothing special to do.
- break;
- case ui::MenuModel::TYPE_CHECK:
- case ui::MenuModel::TYPE_RADIO:
- properties["toggle-type"] = MakeDbusVariant(DbusString(
- menu->GetTypeAt(i) == ui::MenuModel::TYPE_CHECK ? "checkmark"
- : "radio"));
- properties["toggle-state"] =
- MakeDbusVariant(DbusInt32(menu->IsItemCheckedAt(i) ? 1 : 0));
- break;
- case ui::MenuModel::TYPE_SEPARATOR:
- // The dbusmenu interface doesn't have multiple types of separators like
- // MenuModel. Just use a regular separator in all cases.
- properties["type"] = MakeDbusVariant(DbusString("separator"));
- break;
- case ui::MenuModel::TYPE_BUTTON_ITEM:
- // This type of menu represents a row of buttons, but the dbusmenu
- // interface has no equivalent of this. Ignore these items for now
- // since there's currently no uses of it that plumb into this codepath.
- // If there are button menu items in the future, we'd have to fake them
- // with multiple menu items.
- NOTIMPLEMENTED();
- continue;
- case ui::MenuModel::TYPE_SUBMENU:
- case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU:
- properties["children-display"] = MakeDbusVariant(DbusString("submenu"));
- break;
- }
-
ui::MenuModel* submenu = menu->GetSubmenuModelAt(i);
std::vector<int32_t> children = ConvertMenu(submenu);
int32_t id = NextItemId();
items_[id] = std::make_unique<MenuItem>(
- id, std::move(properties), std::move(children), submenu, menu, i);
+ id, ComputeMenuPropertiesForMenuItem(menu, i), std::move(children),
+ submenu, menu, i);
items.push_back(id);
}
@@ -500,7 +498,7 @@ int32_t DbusMenu::NextItemId() {
void DbusMenu::WriteMenuItem(const MenuItem* item,
dbus::MessageWriter* writer,
int32_t depth,
- const std::vector<std::string>& property_filter) {
+ const MenuPropertyList& property_filter) const {
dbus::MessageWriter struct_writer(nullptr);
writer->OpenStruct(&struct_writer);
struct_writer.AppendInt32(item->id);
@@ -525,7 +523,7 @@ void DbusMenu::WriteMenuItem(const MenuItem* item,
for (int32_t child : item->children) {
dbus::MessageWriter variant_writer(nullptr);
children_writer.OpenVariant("(ia{sv}av)", &variant_writer);
- WriteMenuItem(items_[child].get(), &variant_writer,
+ WriteMenuItem(items_.find(child)->second.get(), &variant_writer,
depth == -1 ? -1 : depth - 1, property_filter);
children_writer.CloseContainer(&variant_writer);
}
@@ -534,3 +532,60 @@ void DbusMenu::WriteMenuItem(const MenuItem* item,
writer->CloseContainer(&struct_writer);
}
+
+void DbusMenu::WriteUpdatedProperties(
+ dbus::MessageWriter* writer,
+ const MenuPropertyChanges& updated_props) const {
+ dbus::MessageWriter updated_props_writer(nullptr);
+ writer->OpenArray("(ia{sv})", &updated_props_writer);
+ for (const auto& pair : updated_props) {
+ int32_t id = pair.first;
+ MenuItem* item = items_.find(id)->second.get();
+ dbus::MessageWriter struct_writer(nullptr);
+ updated_props_writer.OpenStruct(&struct_writer);
+ struct_writer.AppendInt32(id);
+ dbus::MessageWriter array_writer(nullptr);
+ struct_writer.OpenArray("{sv}", &array_writer);
+ for (const std::string& key : pair.second) {
+ dbus::MessageWriter dict_entry_writer(nullptr);
+ array_writer.OpenDictEntry(&dict_entry_writer);
+ dict_entry_writer.AppendString(key);
+ item->properties[key].Write(&dict_entry_writer);
+ array_writer.CloseContainer(&dict_entry_writer);
+ }
+ struct_writer.CloseContainer(&array_writer);
+ updated_props_writer.CloseContainer(&struct_writer);
+ }
+ writer->CloseContainer(&updated_props_writer);
+}
+
+DbusMenu::MenuItem* DbusMenu::FindMenuItemForModel(const ui::MenuModel* model,
+ MenuItem* item) const {
+ if (item->menu == model)
+ return item;
+ for (int32_t id : item->children) {
+ MenuItem* child = items_.find(id)->second.get();
+ MenuItem* found = FindMenuItemForModel(model, child);
+ if (found)
+ return found;
+ }
+ return nullptr;
+}
+
+void DbusMenu::DeleteItem(MenuItem* item) {
+ DeleteItemChildren(item);
+ items_.erase(item->id);
+}
+
+void DbusMenu::DeleteItemChildren(MenuItem* item) {
+ for (int32_t id : item->children)
+ DeleteItem(items_.find(id)->second.get());
+}
+
+void DbusMenu::SendLayoutChangedSignal(int32_t id) {
+ dbus::Signal signal(kInterfaceDbusMenu, kSignalLayoutUpdated);
+ dbus::MessageWriter writer(&signal);
+ writer.AppendUint32(++revision_); // Revision of the new layout.
+ writer.AppendInt32(id); // Parent item whose layout changed.
+ menu_->SendSignal(&signal);
+}
diff --git a/chromium/components/dbus/menu/menu.h b/chromium/components/dbus/menu/menu.h
index 5198c809aba..e6f702a5c9a 100644
--- a/chromium/components/dbus/menu/menu.h
+++ b/chromium/components/dbus/menu/menu.h
@@ -7,12 +7,15 @@
#include <map>
#include <memory>
+#include <string>
+#include <utility>
#include <vector>
#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "components/dbus/menu/menu_property_list.h"
#include "components/dbus/menu/types.h"
#include "dbus/bus.h"
#include "dbus/exported_object.h"
@@ -28,19 +31,30 @@ class DbusPropertiesInterface;
class COMPONENT_EXPORT(DBUS) DbusMenu {
public:
using InitializedCallback = base::OnceCallback<void(bool success)>;
+ using MenuItemReference = std::pair<ui::MenuModel*, int>;
// The exported DBus object will not be unregistered upon deletion. It is the
// responsibility of the caller to remove it after |this| is deleted.
DbusMenu(dbus::ExportedObject* exported_object, InitializedCallback callback);
~DbusMenu();
+ // Should be called when there's a new root menu.
void SetModel(ui::MenuModel* model, bool send_signal);
+ // Should be called when items are added/removed/reordered in a menu. Prefer
+ // this over SetModel().
+ void MenuLayoutUpdated(ui::MenuModel* model);
+
+ // Should be called when properties on (a group of) menu items change. Prefer
+ // this over SetModel().
+ void MenuItemsPropertiesUpdated(
+ const std::vector<MenuItemReference>& menu_items);
+
private:
struct MenuItem {
public:
MenuItem(int32_t id,
- std::map<std::string, DbusVariant>&& properties,
+ MenuItemProperties&& properties,
std::vector<int32_t>&& children,
ui::MenuModel* menu,
ui::MenuModel* containing_menu,
@@ -48,8 +62,8 @@ class COMPONENT_EXPORT(DBUS) DbusMenu {
~MenuItem();
const int32_t id;
- const std::map<std::string, DbusVariant> properties;
- const std::vector<int32_t> children;
+ MenuItemProperties properties;
+ std::vector<int32_t> children;
// The MenuModel corresponding to this MenuItem, or null if this MenuItem is
// not a submenu. This can happen for leaf items or an empty root item.
@@ -119,7 +133,20 @@ class COMPONENT_EXPORT(DBUS) DbusMenu {
void WriteMenuItem(const MenuItem* item,
dbus::MessageWriter* writer,
int32_t depth,
- const std::vector<std::string>& property_filter);
+ const MenuPropertyList& property_filter) const;
+
+ void WriteUpdatedProperties(dbus::MessageWriter* writer,
+ const MenuPropertyChanges& updated_props) const;
+
+ // Recursively searches |item| and its descendants for the MenuItem
+ // corresponding to |model|.
+ MenuItem* FindMenuItemForModel(const ui::MenuModel* model,
+ MenuItem* item) const;
+
+ void DeleteItem(MenuItem* item);
+ void DeleteItemChildren(MenuItem* item);
+
+ void SendLayoutChangedSignal(int32_t id);
dbus::ExportedObject* menu_ = nullptr;
diff --git a/chromium/components/dbus/menu/menu_property_list.cc b/chromium/components/dbus/menu/menu_property_list.cc
new file mode 100644
index 00000000000..acbc74fc3e3
--- /dev/null
+++ b/chromium/components/dbus/menu/menu_property_list.cc
@@ -0,0 +1,123 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/dbus/menu/menu_property_list.h"
+
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/image/image.h"
+
+#if defined(USE_X11)
+#include <X11/Xlib.h>
+
+#include "ui/events/keycodes/keyboard_code_conversion_x.h" // nogncheck
+#endif
+
+MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu,
+ int i) {
+ // Properties should only be set if they differ from the default values.
+ MenuItemProperties properties;
+
+ // The dbusmenu interface has no concept of a "sublabel", "minor text", or
+ // "minor icon" like MenuModel has. Ignore these rather than trying to
+ // merge them with the regular label and icon.
+ base::string16 label = menu->GetLabelAt(i);
+ if (!label.empty()) {
+ properties["label"] = MakeDbusVariant(DbusString(
+ ui::ConvertAcceleratorsFromWindowsStyle(base::UTF16ToUTF8(label))));
+ }
+
+ if (!menu->IsEnabledAt(i))
+ properties["enabled"] = MakeDbusVariant(DbusBoolean(false));
+ if (!menu->IsVisibleAt(i))
+ properties["visible"] = MakeDbusVariant(DbusBoolean(false));
+
+ gfx::Image icon;
+ if (menu->GetIconAt(i, &icon)) {
+ properties["icon-data"] =
+ MakeDbusVariant(DbusByteArray(icon.As1xPNGBytes()));
+ }
+
+ ui::Accelerator accelerator;
+ if (menu->GetAcceleratorAt(i, &accelerator)) {
+ std::vector<DbusString> parts;
+ if (accelerator.IsCtrlDown())
+ parts.push_back(DbusString("Control"));
+ if (accelerator.IsAltDown())
+ parts.push_back(DbusString("Alt"));
+ if (accelerator.IsShiftDown())
+ parts.push_back(DbusString("Shift"));
+ if (accelerator.IsCmdDown())
+ parts.push_back(DbusString("Super"));
+#if defined(USE_X11)
+ parts.push_back(DbusString(XKeysymToString(
+ XKeysymForWindowsKeyCode(accelerator.key_code(), false))));
+ properties["shortcut"] =
+ MakeDbusVariant(MakeDbusArray(DbusArray<DbusString>(std::move(parts))));
+#else
+ NOTIMPLEMENTED();
+#endif
+ }
+
+ switch (menu->GetTypeAt(i)) {
+ case ui::MenuModel::TYPE_COMMAND:
+ case ui::MenuModel::TYPE_HIGHLIGHTED:
+ // Nothing special to do.
+ break;
+ case ui::MenuModel::TYPE_CHECK:
+ case ui::MenuModel::TYPE_RADIO:
+ properties["toggle-type"] = MakeDbusVariant(DbusString(
+ menu->GetTypeAt(i) == ui::MenuModel::TYPE_CHECK ? "checkmark"
+ : "radio"));
+ properties["toggle-state"] =
+ MakeDbusVariant(DbusInt32(menu->IsItemCheckedAt(i) ? 1 : 0));
+ break;
+ case ui::MenuModel::TYPE_SEPARATOR:
+ // The dbusmenu interface doesn't have multiple types of separators like
+ // MenuModel. Just use a regular separator in all cases.
+ properties["type"] = MakeDbusVariant(DbusString("separator"));
+ break;
+ case ui::MenuModel::TYPE_BUTTON_ITEM:
+ // This type of menu represents a row of buttons, but the dbusmenu
+ // interface has no equivalent of this. Ignore these items for now
+ // since there's currently no uses of it that plumb into this codepath.
+ // If there are button menu items in the future, we'd have to fake them
+ // with multiple menu items.
+ NOTIMPLEMENTED();
+ break;
+ case ui::MenuModel::TYPE_SUBMENU:
+ case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU:
+ properties["children-display"] = MakeDbusVariant(DbusString("submenu"));
+ break;
+ }
+
+ return properties;
+}
+
+void ComputeMenuPropertyChanges(const MenuItemProperties& old_properties,
+ const MenuItemProperties& new_properties,
+ MenuPropertyList* item_updated_props,
+ MenuPropertyList* item_removed_props) {
+ // Compute updated and removed properties.
+ for (const auto& pair : old_properties) {
+ const std::string& key = pair.first;
+ auto new_it = new_properties.find(key);
+ if (new_it != new_properties.end()) {
+ if (new_it->second != pair.second)
+ item_updated_props->push_back(key);
+ } else {
+ item_removed_props->push_back(key);
+ }
+ }
+ // Compute added properties.
+ for (const auto& pair : new_properties) {
+ const std::string& key = pair.first;
+ if (!base::Contains(old_properties, key))
+ item_updated_props->push_back(key);
+ }
+}
diff --git a/chromium/components/dbus/menu/menu_property_list.h b/chromium/components/dbus/menu/menu_property_list.h
new file mode 100644
index 00000000000..93fd377d174
--- /dev/null
+++ b/chromium/components/dbus/menu/menu_property_list.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DBUS_MENU_MENU_PROPERTY_LIST_H_
+#define COMPONENTS_DBUS_MENU_MENU_PROPERTY_LIST_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "components/dbus/menu/types.h"
+
+using MenuPropertyList = std::vector<std::string>;
+using MenuItemProperties = std::map<std::string, DbusVariant>;
+using MenuPropertyChanges = std::map<int32_t, MenuPropertyList>;
+
+namespace ui {
+class MenuModel;
+}
+
+// Computes properties for the menu item with index |i| in |menu|.
+COMPONENT_EXPORT(DBUS)
+MenuItemProperties ComputeMenuPropertiesForMenuItem(ui::MenuModel* menu, int i);
+
+// Given inputs |old_properties| and |new_properties|, computes outputs
+// |item_updated_props| and |item_removed_props| suitable for use in
+// com.canonical.dbusmenu.ItemsPropertiesUpdated.
+COMPONENT_EXPORT(DBUS)
+void ComputeMenuPropertyChanges(const MenuItemProperties& old_properties,
+ const MenuItemProperties& new_properties,
+ MenuPropertyList* item_updated_props,
+ MenuPropertyList* item_removed_props);
+
+#endif // COMPONENTS_DBUS_MENU_MENU_PROPERTY_LIST_H_
diff --git a/chromium/components/dbus/menu/menu_property_list_unittest.cc b/chromium/components/dbus/menu/menu_property_list_unittest.cc
new file mode 100644
index 00000000000..f700bf6ea1b
--- /dev/null
+++ b/chromium/components/dbus/menu/menu_property_list_unittest.cc
@@ -0,0 +1,361 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/dbus/menu/menu_property_list.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/dbus/menu/types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/base/models/menu_separator_types.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_rep_default.h"
+
+namespace {
+
+class TestMenuModel : public ui::SimpleMenuModel,
+ public ui::SimpleMenuModel::Delegate {
+ public:
+ TestMenuModel(bool checked,
+ bool enabled,
+ bool visible,
+ const base::string16& label,
+ const gfx::Image& icon,
+ const ui::Accelerator& accelerator)
+ : ui::SimpleMenuModel(this),
+ checked_(checked),
+ enabled_(enabled),
+ visible_(visible),
+ label_(label),
+ icon_(icon),
+ accelerator_(accelerator) {}
+ ~TestMenuModel() override = default;
+
+ MenuItemProperties ComputeProperties() {
+ return ComputeMenuPropertiesForMenuItem(this, 0);
+ }
+
+ protected:
+ // ui::MenuModel::
+ bool IsItemDynamicAt(int index) const override {
+ EXPECT_LE(index, 0);
+ // Return true so that GetIconForCommandId() will always be called.
+ return true;
+ }
+
+ // ui::SimpleMenuModel::Delegate:
+ bool IsCommandIdChecked(int command_id) const override {
+ EXPECT_LE(command_id, 0);
+ return checked_;
+ }
+ bool IsCommandIdEnabled(int command_id) const override {
+ EXPECT_LE(command_id, 0);
+ return enabled_;
+ }
+ bool IsCommandIdVisible(int command_id) const override {
+ EXPECT_LE(command_id, 0);
+ return visible_;
+ }
+ base::string16 GetLabelForCommandId(int command_id) const override {
+ EXPECT_LE(command_id, 0);
+ return label_;
+ }
+ bool GetIconForCommandId(int command_id, gfx::Image* icon) const override {
+ EXPECT_LE(command_id, 0);
+ if (icon_.IsEmpty())
+ return false;
+ *icon = icon_;
+ return true;
+ }
+ void ExecuteCommand(int command_id, int event_flags) override {
+ EXPECT_LE(command_id, 0);
+ }
+ bool GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) const override {
+ EXPECT_LE(command_id, 0);
+ if (accelerator_ == ui::Accelerator())
+ return false;
+ *accelerator = accelerator_;
+ return true;
+ }
+
+ private:
+ const bool checked_;
+ const bool enabled_;
+ const bool visible_;
+ const base::string16 label_;
+ const gfx::Image icon_;
+ const ui::Accelerator accelerator_;
+};
+
+class TestMenuModelBuilder {
+ public:
+ TestMenuModelBuilder() = default;
+ ~TestMenuModelBuilder() = default;
+
+ TestMenuModelBuilder SetType(ui::MenuModel::ItemType type) const {
+ TestMenuModelBuilder builder = *this;
+ builder.type_ = type;
+ return builder;
+ }
+
+ TestMenuModelBuilder SetChecked(bool checked) const {
+ TestMenuModelBuilder builder = *this;
+ builder.checked_ = checked;
+ return builder;
+ }
+
+ TestMenuModelBuilder SetEnabled(bool enabled) const {
+ TestMenuModelBuilder builder = *this;
+ builder.enabled_ = enabled;
+ return builder;
+ }
+
+ TestMenuModelBuilder SetVisible(bool visible) const {
+ TestMenuModelBuilder builder = *this;
+ builder.visible_ = visible;
+ return builder;
+ }
+
+ TestMenuModelBuilder SetLabel(const std::string& label) const {
+ TestMenuModelBuilder builder = *this;
+ builder.label_ = base::ASCIIToUTF16(label);
+ return builder;
+ }
+
+ TestMenuModelBuilder SetIcon(const gfx::Image& icon) const {
+ TestMenuModelBuilder builder = *this;
+ builder.icon_ = icon;
+ return builder;
+ }
+
+ TestMenuModelBuilder SetAccelerator(
+ const ui::Accelerator& accelerator) const {
+ TestMenuModelBuilder builder = *this;
+ builder.accelerator_ = accelerator;
+ return builder;
+ }
+
+ std::unique_ptr<TestMenuModel> Build() const {
+ auto menu = std::make_unique<TestMenuModel>(checked_, enabled_, visible_,
+ label_, icon_, accelerator_);
+ switch (type_) {
+ case ui::MenuModel::TYPE_COMMAND:
+ menu->AddItem(0, label_);
+ break;
+ case ui::MenuModel::TYPE_CHECK:
+ menu->AddCheckItem(0, label_);
+ break;
+ case ui::MenuModel::TYPE_RADIO:
+ menu->AddRadioItem(0, label_, 0);
+ break;
+ case ui::MenuModel::TYPE_SEPARATOR:
+ menu->AddSeparator(ui::MenuSeparatorType::SPACING_SEPARATOR);
+ break;
+ case ui::MenuModel::TYPE_BUTTON_ITEM:
+ NOTIMPLEMENTED();
+ break;
+ case ui::MenuModel::TYPE_SUBMENU:
+ menu->AddSubMenu(0, label_, nullptr);
+ break;
+ case ui::MenuModel::TYPE_ACTIONABLE_SUBMENU:
+ menu->AddActionableSubMenu(0, label_, nullptr);
+ break;
+ case ui::MenuModel::TYPE_HIGHLIGHTED:
+ menu->AddHighlightedItemWithIcon(0, label_, icon_.AsImageSkia());
+ break;
+ }
+ return menu;
+ }
+
+ private:
+ ui::MenuModel::ItemType type_ = ui::MenuModel::TYPE_COMMAND;
+ bool checked_ = false;
+ bool enabled_ = true;
+ bool visible_ = true;
+ base::string16 label_;
+ gfx::Image icon_;
+ ui::Accelerator accelerator_;
+};
+
+} // namespace
+
+TEST(MenuPropertyListTest, ComputePropertiesBasic) {
+ auto builder = TestMenuModelBuilder();
+ auto menu = builder.Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Same for TYPE_HIGHLIGHTED.
+ menu = builder.SetType(ui::MenuModel::TYPE_HIGHLIGHTED).Build();
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesCheck) {
+ auto menu = TestMenuModelBuilder().SetType(ui::MenuModel::TYPE_CHECK).Build();
+ MenuItemProperties props;
+ props["toggle-type"] = MakeDbusVariant(DbusString("checkmark"));
+ props["toggle-state"] = MakeDbusVariant(DbusInt32(0));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesRadio) {
+ auto menu = TestMenuModelBuilder().SetType(ui::MenuModel::TYPE_RADIO).Build();
+ MenuItemProperties props;
+ props["toggle-type"] = MakeDbusVariant(DbusString("radio"));
+ props["toggle-state"] = MakeDbusVariant(DbusInt32(0));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesCheckedState) {
+ auto builder = TestMenuModelBuilder().SetChecked(true);
+
+ // Types other than radio and check should not have toggle-state set.
+ auto menu = builder.Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Radio and check buttons should have the toggle-state set.
+ menu = builder.SetType(ui::MenuModel::TYPE_RADIO).Build();
+ props["toggle-type"] = MakeDbusVariant(DbusString("radio"));
+ props["toggle-state"] = MakeDbusVariant(DbusInt32(1));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ menu = builder.SetType(ui::MenuModel::TYPE_CHECK).Build();
+ props["toggle-type"] = MakeDbusVariant(DbusString("checkmark"));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesSeparator) {
+ auto menu =
+ TestMenuModelBuilder().SetType(ui::MenuModel::TYPE_SEPARATOR).Build();
+ MenuItemProperties props;
+ props["type"] = MakeDbusVariant(DbusString("separator"));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesSubmenu) {
+ auto builder = TestMenuModelBuilder();
+ auto menu = builder.SetType(ui::MenuModel::TYPE_SUBMENU).Build();
+ MenuItemProperties props;
+ props["children-display"] = MakeDbusVariant(DbusString("submenu"));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Same for ACTIONABLE_SUBMENU.
+ menu = builder.SetType(ui::MenuModel::TYPE_ACTIONABLE_SUBMENU).Build();
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesEnabledState) {
+ auto builder = TestMenuModelBuilder();
+
+ // Enabled.
+ auto menu = builder.SetEnabled(true).Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Disabled.
+ menu = builder.SetEnabled(false).Build();
+ props["enabled"] = MakeDbusVariant(DbusBoolean(false));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesVisibleState) {
+ auto builder = TestMenuModelBuilder();
+
+ // Visible.
+ auto menu = builder.SetVisible(true).Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Hidden.
+ menu = builder.SetVisible(false).Build();
+ props["visible"] = MakeDbusVariant(DbusBoolean(false));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesLabel) {
+ auto builder = TestMenuModelBuilder();
+
+ // No label.
+ auto menu = builder.SetLabel("").Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Non-empty label.
+ menu = builder.SetLabel("label value").Build();
+ props["label"] = MakeDbusVariant(DbusString("label value"));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+TEST(MenuPropertyListTest, ComputePropertiesIcon) {
+ auto builder = TestMenuModelBuilder();
+
+ // No icon.
+ auto menu = builder.SetIcon(gfx::Image()).Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Non-empty label.
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(10, 10);
+ bitmap.eraseARGB(255, 123, 123, 123);
+ gfx::ImageSkia image_skia;
+ image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, 1.0f));
+ gfx::Image icon(image_skia);
+ menu = builder.SetIcon(icon).Build();
+ props["icon-data"] = MakeDbusVariant(DbusByteArray(icon.As1xPNGBytes()));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+
+#if defined(USE_X11)
+TEST(MenuPropertyListTest, ComputePropertiesAccelerator) {
+ auto builder = TestMenuModelBuilder();
+
+ // No accelerator.
+ auto menu = builder.SetAccelerator(ui::Accelerator()).Build();
+ MenuItemProperties props;
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Set a key.
+ menu = builder.SetAccelerator(ui::Accelerator(ui::VKEY_A, 0)).Build();
+ props["shortcut"] =
+ MakeDbusVariant(MakeDbusArray(MakeDbusArray(DbusString("a"))));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+
+ // Add modifiers.
+ menu = builder
+ .SetAccelerator(ui::Accelerator(
+ ui::VKEY_A,
+ ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN))
+ .Build();
+ props["shortcut"] = MakeDbusVariant(
+ MakeDbusArray(MakeDbusArray(DbusString("Control"), DbusString("Alt"),
+ DbusString("Shift"), DbusString("a"))));
+ EXPECT_EQ(menu->ComputeProperties(), props);
+}
+#endif
+
+TEST(MenuPropertyListTest, ComputePropertyChanges) {
+ MenuItemProperties old_props;
+ old_props["1"] = MakeDbusVariant(DbusInt32(1)); // Remains the same.
+ old_props["2"] = MakeDbusVariant(DbusInt32(2)); // Updates to -2.
+ old_props["3"] = MakeDbusVariant(DbusInt32(3)); // Removed.
+
+ MenuItemProperties new_props;
+ new_props["1"] = MakeDbusVariant(DbusInt32(1));
+ new_props["2"] = MakeDbusVariant(DbusInt32(-2));
+ new_props["4"] = MakeDbusVariant(DbusInt32(4)); // Added.
+
+ MenuPropertyList updated;
+ MenuPropertyList removed;
+ ComputeMenuPropertyChanges(old_props, new_props, &updated, &removed);
+ EXPECT_EQ(updated, (MenuPropertyList{"2", "4"}));
+ EXPECT_EQ(removed, (MenuPropertyList{"3"}));
+}
diff --git a/chromium/components/dbus/menu/types.cc b/chromium/components/dbus/menu/types.cc
index 5694f2dc784..4af3e77c7a7 100644
--- a/chromium/components/dbus/menu/types.cc
+++ b/chromium/components/dbus/menu/types.cc
@@ -9,6 +9,15 @@
DbusType::~DbusType() = default;
+bool DbusType::operator==(const DbusType& other) const {
+ if (GetSignatureDynamic() != other.GetSignatureDynamic())
+ return false;
+ return IsEqual(other);
+}
+bool DbusType::operator!=(const DbusType& other) const {
+ return !(*this == other);
+}
+
DbusBoolean::DbusBoolean(bool value) : value_(value) {}
DbusBoolean::DbusBoolean(DbusBoolean&& other) = default;
DbusBoolean::~DbusBoolean() = default;
@@ -85,6 +94,11 @@ DbusVariant::operator bool() const {
return !!value_;
}
+bool DbusVariant::IsEqual(const DbusType& other_type) const {
+ const DbusVariant* other = static_cast<const DbusVariant*>(&other_type);
+ return *value_ == *other->value_;
+}
+
void DbusVariant::Write(dbus::MessageWriter* writer) const {
dbus::MessageWriter variant_writer(nullptr);
writer->OpenVariant(value_->GetSignatureDynamic(), &variant_writer);
@@ -103,6 +117,12 @@ DbusByteArray::DbusByteArray(scoped_refptr<base::RefCountedMemory> value)
DbusByteArray::DbusByteArray(DbusByteArray&& other) = default;
DbusByteArray::~DbusByteArray() = default;
+bool DbusByteArray::IsEqual(const DbusType& other_type) const {
+ const DbusByteArray* other = static_cast<const DbusByteArray*>(&other_type);
+ return value_->size() == other->value_->size() &&
+ !memcmp(value_->front(), other->value_->front(), value_->size());
+}
+
void DbusByteArray::Write(dbus::MessageWriter* writer) const {
writer->AppendArrayOfBytes(value_->front(), value_->size());
}
diff --git a/chromium/components/dbus/menu/types.h b/chromium/components/dbus/menu/types.h
index 3ba18d5d025..feb317737f9 100644
--- a/chromium/components/dbus/menu/types.h
+++ b/chromium/components/dbus/menu/types.h
@@ -65,6 +65,9 @@ class COMPONENT_EXPORT(DBUS) DbusType {
public:
virtual ~DbusType();
+ bool operator==(const DbusType& other) const;
+ bool operator!=(const DbusType& other) const;
+
// Serializes this object to |writer|.
virtual void Write(dbus::MessageWriter* writer) const = 0;
@@ -75,6 +78,10 @@ class COMPONENT_EXPORT(DBUS) DbusType {
// array is empty, then there would be no DbusType instance to get the
// signature from.
virtual std::string GetSignatureDynamic() const = 0;
+
+ protected:
+ // This is only safe to call after verifying GetSignatureDynamic() matches.
+ virtual bool IsEqual(const DbusType& other_type) const = 0;
};
template <typename T>
@@ -82,8 +89,14 @@ class DbusTypeImpl : public DbusType {
public:
~DbusTypeImpl() override {}
- // DbusType:
std::string GetSignatureDynamic() const override { return T::GetSignature(); }
+
+ protected:
+ // DbusType:
+ bool IsEqual(const DbusType& other_type) const override {
+ const T* other = static_cast<const T*>(&other_type);
+ return static_cast<const T*>(this)->value_ == other->value_;
+ }
};
class COMPONENT_EXPORT(DBUS) DbusBoolean : public DbusTypeImpl<DbusBoolean> {
@@ -98,6 +111,8 @@ class COMPONENT_EXPORT(DBUS) DbusBoolean : public DbusTypeImpl<DbusBoolean> {
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusBoolean>;
+
bool value_;
};
@@ -113,6 +128,8 @@ class COMPONENT_EXPORT(DBUS) DbusInt32 : public DbusTypeImpl<DbusInt32> {
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusInt32>;
+
int32_t value_;
};
@@ -128,6 +145,8 @@ class COMPONENT_EXPORT(DBUS) DbusUint32 : public DbusTypeImpl<DbusUint32> {
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusUint32>;
+
uint32_t value_;
};
@@ -143,6 +162,8 @@ class COMPONENT_EXPORT(DBUS) DbusString : public DbusTypeImpl<DbusString> {
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusString>;
+
std::string value_;
};
@@ -159,6 +180,8 @@ class COMPONENT_EXPORT(DBUS) DbusObjectPath
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusObjectPath>;
+
dbus::ObjectPath value_;
};
@@ -171,14 +194,17 @@ class COMPONENT_EXPORT(DBUS) DbusVariant : public DbusTypeImpl<DbusVariant> {
DbusVariant& operator=(DbusVariant&& other);
- operator bool() const;
+ explicit operator bool() const;
// DbusType:
+ bool IsEqual(const DbusType& other_type) const override;
void Write(dbus::MessageWriter* writer) const override;
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusVariant>;
+
std::unique_ptr<DbusType> value_;
};
@@ -215,6 +241,8 @@ class COMPONENT_EXPORT(DBUS) DbusArray : public DbusTypeImpl<DbusArray<T>> {
}
private:
+ friend class DbusTypeImpl<DbusArray<T>>;
+
std::vector<T> value_;
};
@@ -235,11 +263,14 @@ class COMPONENT_EXPORT(DBUS) DbusByteArray
~DbusByteArray() override;
// DbusType:
+ bool IsEqual(const DbusType& other_type) const override;
void Write(dbus::MessageWriter* writer) const override;
static std::string GetSignature();
private:
+ friend class DbusTypeImpl<DbusByteArray>;
+
scoped_refptr<base::RefCountedMemory> value_;
};
@@ -264,6 +295,8 @@ class COMPONENT_EXPORT(DBUS) DbusStruct
}
private:
+ friend class DbusTypeImpl<DbusStruct<Ts...>>;
+
std::tuple<Ts...> value_;
};
@@ -276,7 +309,7 @@ template <typename K, typename V>
class COMPONENT_EXPORT(DBUS) DbusDictEntry
: public DbusTypeImpl<DbusDictEntry<K, V>> {
public:
- DbusDictEntry(K&& k, V&& v) : k_(std::move(k)), v_(std::move(v)) {}
+ DbusDictEntry(K&& k, V&& v) : value_{std::move(k), std::move(v)} {}
DbusDictEntry(DbusDictEntry<K, V>&& other) = default;
~DbusDictEntry() override = default;
@@ -284,8 +317,8 @@ class COMPONENT_EXPORT(DBUS) DbusDictEntry
void Write(dbus::MessageWriter* writer) const override {
dbus::MessageWriter dict_entry_writer(nullptr);
writer->OpenDictEntry(&dict_entry_writer);
- k_.Write(&dict_entry_writer);
- v_.Write(&dict_entry_writer);
+ value_.first.Write(&dict_entry_writer);
+ value_.second.Write(&dict_entry_writer);
writer->CloseContainer(&dict_entry_writer);
}
@@ -294,8 +327,9 @@ class COMPONENT_EXPORT(DBUS) DbusDictEntry
}
private:
- K k_;
- V v_;
+ friend class DbusTypeImpl<DbusDictEntry<K, V>>;
+
+ std::pair<K, V> value_;
};
template <typename K, typename V>
diff --git a/chromium/components/dbus/menu/types_unittest.cc b/chromium/components/dbus/menu/types_unittest.cc
new file mode 100644
index 00000000000..e6ca1457530
--- /dev/null
+++ b/chromium/components/dbus/menu/types_unittest.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 "components/dbus/menu/types.h"
+
+#include "base/memory/ref_counted_memory.h"
+#include "dbus/object_path.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(DbusTypesTest, GetSignatureDynamic) {
+ // Basic signatures.
+ EXPECT_EQ("b", DbusBoolean(false).GetSignatureDynamic());
+ EXPECT_EQ("i", DbusInt32(0).GetSignatureDynamic());
+ EXPECT_EQ("u", DbusUint32(0).GetSignatureDynamic());
+ EXPECT_EQ("s", DbusString("").GetSignatureDynamic());
+ EXPECT_EQ("o", DbusObjectPath(dbus::ObjectPath("/")).GetSignatureDynamic());
+ EXPECT_EQ("v", MakeDbusVariant(DbusInt32(0)).GetSignatureDynamic());
+ EXPECT_EQ("ai", MakeDbusArray(DbusInt32(0)).GetSignatureDynamic());
+ std::vector<unsigned char> buf{1, 2, 3};
+ EXPECT_EQ("ay", DbusByteArray(base::RefCountedBytes::TakeVector(&buf))
+ .GetSignatureDynamic());
+ EXPECT_EQ("(ib)",
+ MakeDbusStruct(DbusInt32(0), DbusBoolean(0)).GetSignatureDynamic());
+ EXPECT_EQ(
+ "{si}",
+ MakeDbusDictEntry(DbusString(""), DbusInt32(0)).GetSignatureDynamic());
+
+ // A more complex signature. This is the return type of
+ // com.canonical.dbusmenu.GetLayout.
+ EXPECT_EQ("a(ia{sv}av)",
+ MakeDbusArray(MakeDbusStruct(DbusInt32(0),
+ MakeDbusArray(MakeDbusDictEntry(
+ DbusString(""),
+ MakeDbusVariant(DbusInt32(0)))),
+ DbusArray<DbusVariant>()))
+ .GetSignatureDynamic());
+}
+
+TEST(DbusTypesTest, IsEqual) {
+ // Types that have different signatures should never be equal.
+ EXPECT_NE(DbusInt32(0), DbusBoolean(false));
+ EXPECT_NE(DbusInt32(0), MakeDbusVariant(DbusInt32(0)));
+
+ // Basic test.
+ EXPECT_EQ(DbusInt32(3), DbusInt32(3));
+ EXPECT_NE(DbusInt32(3), DbusInt32(4));
+
+ // DbusVariant compares it's pointed-to value, not the pointers themselves.
+ EXPECT_EQ(MakeDbusVariant(DbusInt32(3)), MakeDbusVariant(DbusInt32(3)));
+ EXPECT_NE(MakeDbusVariant(DbusInt32(3)), MakeDbusVariant(DbusInt32(4)));
+
+ // DbusByteArray does a deep comparison of its data, not a comparison on
+ // pointers.
+ std::vector<unsigned char> buf1{1, 2, 3};
+ std::vector<unsigned char> buf2{1, 2, 3};
+ EXPECT_EQ(DbusByteArray(base::RefCountedBytes::TakeVector(&buf1)),
+ DbusByteArray(base::RefCountedBytes::TakeVector(&buf2)));
+ buf1 = {1, 2, 3};
+ buf2 = {3, 2, 1};
+ EXPECT_NE(DbusByteArray(base::RefCountedBytes::TakeVector(&buf1)),
+ DbusByteArray(base::RefCountedBytes::TakeVector(&buf2)));
+}
diff --git a/chromium/components/discardable_memory/OWNERS b/chromium/components/discardable_memory/OWNERS
index 08bb2dd3f93..55aedf969aa 100644
--- a/chromium/components/discardable_memory/OWNERS
+++ b/chromium/components/discardable_memory/OWNERS
@@ -1,2 +1,4 @@
reveman@chromium.org
penghuang@chromium.org
+
+# COMPONENT: Internals
diff --git a/chromium/components/discardable_memory/service/discardable_shared_memory_manager.cc b/chromium/components/discardable_memory/service/discardable_shared_memory_manager.cc
index 52fab71e784..934627f071f 100644
--- a/chromium/components/discardable_memory/service/discardable_shared_memory_manager.cc
+++ b/chromium/components/discardable_memory/service/discardable_shared_memory_manager.cc
@@ -157,6 +157,12 @@ int64_t GetDefaultMemoryLimit() {
// Chromecast devices. Set value here as IsLowEndDevice() is used on some, but
// not all Chromecast devices.
int64_t max_default_memory_limit = 64 * kMegabyte;
+#elif defined(OS_FUCHSIA)
+ // Fuchsia doesn't implement MemoryPressureMonitor and the default limit is
+ // too high for some devices. Set it to the same value as for low-end devices.
+ // TODO(crbug.com/996030): Implement MemoryPressureMonitor for Fuchsia and
+ // remove this ifdef.
+ int64_t max_default_memory_limit = 64 * kMegabyte;
#else
#if defined(OS_ANDROID)
// Limits the number of FDs used to 32, assuming a 4MB allocation size.
diff --git a/chromium/components/discardable_memory/service/discardable_shared_memory_manager_unittest.cc b/chromium/components/discardable_memory/service/discardable_shared_memory_manager_unittest.cc
index ba0b7aac536..ad9e987fb60 100644
--- a/chromium/components/discardable_memory/service/discardable_shared_memory_manager_unittest.cc
+++ b/chromium/components/discardable_memory/service/discardable_shared_memory_manager_unittest.cc
@@ -7,7 +7,7 @@
#include <stdint.h>
#include <string.h>
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -66,7 +66,7 @@ class DiscardableSharedMemoryManagerTest : public testing::Test {
}
// DiscardableSharedMemoryManager requires a message loop.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<TestDiscardableSharedMemoryManager> manager_;
};
@@ -240,7 +240,7 @@ class DiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest
void SetUp() override { manager_.reset(new DiscardableSharedMemoryManager); }
// DiscardableSharedMemoryManager requires a message loop.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<DiscardableSharedMemoryManager> manager_;
};
diff --git a/chromium/components/dom_distiller/content/browser/distillability_driver.cc b/chromium/components/dom_distiller/content/browser/distillability_driver.cc
index 67147efdab8..42ae0003a78 100644
--- a/chromium/components/dom_distiller/content/browser/distillability_driver.cc
+++ b/chromium/components/dom_distiller/content/browser/distillability_driver.cc
@@ -5,6 +5,7 @@
#include "components/dom_distiller/content/browser/distillability_driver.h"
#include <memory>
+#include <utility>
#include "base/bind.h"
#include "content/public/browser/navigation_handle.h"
@@ -31,8 +32,13 @@ class DistillabilityServiceImpl : public mojom::DistillabilityService {
bool is_mobile_friendly) override {
if (!distillability_driver_)
return;
- distillability_driver_->OnDistillability(is_distillable, is_last_update,
- is_mobile_friendly);
+ DistillabilityResult result;
+ result.is_distillable = is_distillable;
+ result.is_last = is_last_update;
+ result.is_mobile_friendly = is_mobile_friendly;
+ DVLOG(1) << "Notifying observers of distillability service result: "
+ << result;
+ distillability_driver_->OnDistillability(result);
}
private:
@@ -59,18 +65,16 @@ void DistillabilityDriver::CreateDistillabilityService(
std::move(request));
}
-void DistillabilityDriver::SetDelegate(
- const base::RepeatingCallback<void(bool, bool, bool)>& delegate) {
- m_delegate_ = delegate;
+void DistillabilityDriver::AddObserver(DistillabilityObserver* observer) {
+ if (!observers_.HasObserver(observer)) {
+ observers_.AddObserver(observer);
+ }
}
-void DistillabilityDriver::OnDistillability(bool distillable,
- bool is_last,
- bool is_mobile_friendly) {
- if (m_delegate_.is_null())
- return;
-
- m_delegate_.Run(distillable, is_last, is_mobile_friendly);
+void DistillabilityDriver::OnDistillability(
+ const DistillabilityResult& result) {
+ for (auto& observer : observers_)
+ observer.OnResult(result);
}
void DistillabilityDriver::OnInterfaceRequestFromFrame(
diff --git a/chromium/components/dom_distiller/content/browser/distillability_driver.h b/chromium/components/dom_distiller/content/browser/distillability_driver.h
index 8d80f28a403..423c55df7b2 100644
--- a/chromium/components/dom_distiller/content/browser/distillability_driver.h
+++ b/chromium/components/dom_distiller/content/browser/distillability_driver.h
@@ -5,8 +5,11 @@
#ifndef COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLIBILITY_DRIVER_H_
#define COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLIBILITY_DRIVER_H_
+#include <string>
+
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
#include "components/dom_distiller/content/browser/distillable_page_utils.h"
#include "components/dom_distiller/content/common/mojom/distillability_service.mojom.h"
#include "content/public/browser/web_contents_observer.h"
@@ -24,7 +27,7 @@ class DistillabilityDriver
~DistillabilityDriver() override;
void CreateDistillabilityService(mojom::DistillabilityServiceRequest request);
- void SetDelegate(const DistillabilityDelegate& delegate);
+ void AddObserver(DistillabilityObserver* observer);
// content::WebContentsObserver implementation.
void OnInterfaceRequestFromFrame(
@@ -37,11 +40,9 @@ class DistillabilityDriver
friend class content::WebContentsUserData<DistillabilityDriver>;
friend class DistillabilityServiceImpl;
- void OnDistillability(bool distillable,
- bool is_last,
- bool is_mobile_friendly);
+ void OnDistillability(const DistillabilityResult& result);
- DistillabilityDelegate m_delegate_;
+ base::ObserverList<DistillabilityObserver> observers_;
service_manager::BinderRegistry frame_interfaces_;
diff --git a/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc b/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
index e3adeb1ed77..a0a32c11497 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
@@ -50,15 +50,22 @@ void IsDistillablePageForDetector(content::WebContents* web_contents,
base::BindOnce(OnExtractFeaturesJsResult, detector, callback));
}
-void SetDelegate(content::WebContents* web_contents,
- DistillabilityDelegate delegate) {
+std::ostream& operator<<(std::ostream& os, const DistillabilityResult& result) {
+ os << "DistillabilityResult: { is_distillable: " << result.is_distillable
+ << ", is_last: " << result.is_last
+ << ", is_mobile_friendly: " << result.is_mobile_friendly << " }";
+ return os;
+}
+
+void AddObserver(content::WebContents* web_contents,
+ DistillabilityObserver* observer) {
CHECK(web_contents);
DistillabilityDriver::CreateForWebContents(web_contents);
DistillabilityDriver* driver =
DistillabilityDriver::FromWebContents(web_contents);
CHECK(driver);
- driver->SetDelegate(delegate);
+ driver->AddObserver(observer);
}
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/content/browser/distillable_page_utils.h b/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
index 632fff0c578..83cee04efa8 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
@@ -5,7 +5,10 @@
#ifndef COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLABLE_PAGE_UTILS_H_
#define COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLABLE_PAGE_UTILS_H_
+#include <ostream>
+
#include "base/callback.h"
+#include "base/observer_list_types.h"
namespace content {
class WebContents;
@@ -24,15 +27,23 @@ void IsDistillablePageForDetector(content::WebContents* web_contents,
const DistillablePageDetector* detector,
base::Callback<void(bool)> callback);
+struct DistillabilityResult {
+ bool is_distillable;
+ bool is_last;
+ bool is_mobile_friendly;
+};
+std::ostream& operator<<(std::ostream& os, const DistillabilityResult& result);
+
+class DistillabilityObserver : public base::CheckedObserver {
+ public:
+ virtual void OnResult(const DistillabilityResult& result) = 0;
+};
+
// Set the delegate to receive the result of whether the page is distillable.
//
// |web_contents| must be non-null.
-using DistillabilityDelegate =
- base::RepeatingCallback<void(bool /* is_distillable */,
- bool /* is_last */,
- bool /* is_mobile_friendly */)>;
-void SetDelegate(content::WebContents* web_contents,
- DistillabilityDelegate delegate);
+void AddObserver(content::WebContents* web_contents,
+ DistillabilityObserver* observer);
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc b/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc
index 51d246a8e73..38d561d7017 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils_android.cc
@@ -9,6 +9,7 @@
#include "components/dom_distiller/content/browser/android/jni_headers/DistillablePageUtils_jni.h"
#include "components/dom_distiller/content/browser/distillable_page_utils.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_user_data.h"
using base::android::JavaParamRef;
using base::android::JavaRef;
@@ -16,15 +17,33 @@ using base::android::ScopedJavaGlobalRef;
namespace dom_distiller {
namespace android {
+
namespace {
-void OnIsPageDistillableUpdate(const JavaRef<jobject>& callback,
- bool isDistillable,
- bool isLast,
- bool isMobileFriendly) {
- Java_DistillablePageUtils_callOnIsPageDistillableUpdate(
- base::android::AttachCurrentThread(), callback, isDistillable, isLast,
- isMobileFriendly);
-}
+
+class JniDistillabilityObserverWrapper
+ : public DistillabilityObserver,
+ public content::WebContentsUserData<JniDistillabilityObserverWrapper> {
+ public:
+ void SetCallback(JNIEnv* env, const JavaParamRef<jobject>& callback) {
+ callback_ = ScopedJavaGlobalRef<jobject>(env, callback);
+ }
+
+ void OnResult(const DistillabilityResult& result) override {
+ Java_DistillablePageUtils_callOnIsPageDistillableUpdate(
+ base::android::AttachCurrentThread(), callback_, result.is_distillable,
+ result.is_last, result.is_mobile_friendly);
+ }
+
+ private:
+ explicit JniDistillabilityObserverWrapper(content::WebContents* contents) {}
+ friend class content::WebContentsUserData<JniDistillabilityObserverWrapper>;
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+ ScopedJavaGlobalRef<jobject> callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(JniDistillabilityObserverWrapper);
+};
+
} // namespace
static void JNI_DistillablePageUtils_SetDelegate(
@@ -37,10 +56,16 @@ static void JNI_DistillablePageUtils_SetDelegate(
return;
}
- DistillabilityDelegate delegate = base::Bind(
- OnIsPageDistillableUpdate, ScopedJavaGlobalRef<jobject>(env, callback));
- SetDelegate(web_contents, delegate);
+ JniDistillabilityObserverWrapper::CreateForWebContents(web_contents);
+ auto* observer =
+ JniDistillabilityObserverWrapper::FromWebContents(web_contents);
+ DCHECK(observer);
+ observer->SetCallback(env, callback);
+
+ AddObserver(web_contents, observer);
}
+WEB_CONTENTS_USER_DATA_KEY_IMPL(JniDistillabilityObserverWrapper)
+
} // namespace android
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.cc b/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.cc
index 155943de807..054a1107843 100644
--- a/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.cc
+++ b/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.cc
@@ -16,12 +16,12 @@ namespace dom_distiller {
namespace {
// An invalid world ID to check against.
-const int invalid_world_id = -1;
+const int32_t invalid_world_id = -1;
// The ID of the world javascript should execute in; init to invalid ID.
-int distiller_javascript_world_id = invalid_world_id;
+int32_t distiller_javascript_world_id = invalid_world_id;
} // namespace
-void SetDistillerJavaScriptWorldId(const int id) {
+void SetDistillerJavaScriptWorldId(const int32_t id) {
// Never allow running in main world (0).
DCHECK(id > content::ISOLATED_WORLD_ID_GLOBAL);
// Only allow ID to be set once.
diff --git a/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.h b/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.h
index 9a4bb591587..3458f12ce8e 100644
--- a/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.h
+++ b/chromium/components/dom_distiller/content/browser/distiller_javascript_utils.h
@@ -12,7 +12,7 @@
namespace dom_distiller {
// Set the world for JavaScript to execute in. This can only be called once.
-void SetDistillerJavaScriptWorldId(const int id);
+void SetDistillerJavaScriptWorldId(const int32_t id);
bool DistillerJavaScriptWorldIdIsSet();
diff --git a/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.cc b/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.cc
index 27c0ac02e58..21a01789ab1 100644
--- a/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.cc
+++ b/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.cc
@@ -228,7 +228,7 @@ std::string DomDistillerViewerSource::GetSource() {
void DomDistillerViewerSource::StartDataRequest(
const std::string& path,
- const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+ const content::WebContents::Getter& wc_getter,
const content::URLDataSource::GotDataCallback& callback) {
content::WebContents* web_contents = wc_getter.Run();
if (!web_contents)
diff --git a/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.h b/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.h
index 1a285dc545c..1f984bb179d 100644
--- a/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.h
+++ b/chromium/components/dom_distiller/content/browser/dom_distiller_viewer_source.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "components/dom_distiller/content/browser/distiller_ui_handle.h"
#include "content/public/browser/url_data_source.h"
+#include "content/public/browser/web_contents.h"
namespace dom_distiller {
@@ -32,7 +33,7 @@ class DomDistillerViewerSource : public content::URLDataSource {
std::string GetSource() override;
void StartDataRequest(
const std::string& path,
- const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+ const content::WebContents::Getter& wc_getter,
const content::URLDataSource::GotDataCallback& callback) override;
std::string GetMimeType(const std::string& path) override;
bool ShouldServiceRequest(const GURL& url,
diff --git a/chromium/components/dom_distiller/content/renderer/distillability_agent.cc b/chromium/components/dom_distiller/content/renderer/distillability_agent.cc
index 15d0a6fe8cc..a4ded3d57fa 100644
--- a/chromium/components/dom_distiller/content/renderer/distillability_agent.cc
+++ b/chromium/components/dom_distiller/content/renderer/distillability_agent.cc
@@ -4,6 +4,7 @@
#include "components/dom_distiller/content/renderer/distillability_agent.h"
+#include "base/json/json_writer.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -75,11 +76,61 @@ bool IsBlacklisted(const GURL& url) {
return false;
}
+void DumpDistillability(content::RenderFrame* render_frame,
+ const WebDistillabilityFeatures& features,
+ const std::vector<double>& derived,
+ double score,
+ bool distillable,
+ double long_score,
+ bool long_page,
+ bool blacklisted) {
+ base::DictionaryValue dict;
+ std::string msg;
+
+ std::unique_ptr<base::DictionaryValue> raw_features(
+ new base::DictionaryValue);
+ raw_features->SetInteger("is_mobile_friendly", features.is_mobile_friendly);
+ raw_features->SetInteger("open_graph", features.open_graph);
+ raw_features->SetInteger("element_count", features.element_count);
+ raw_features->SetInteger("anchor_count", features.anchor_count);
+ raw_features->SetInteger("form_count", features.form_count);
+ raw_features->SetInteger("text_input_count", features.text_input_count);
+ raw_features->SetInteger("password_input_count",
+ features.password_input_count);
+ raw_features->SetInteger("p_count", features.p_count);
+ raw_features->SetInteger("pre_count", features.pre_count);
+ raw_features->SetDouble("moz_score", features.moz_score);
+ raw_features->SetDouble("moz_score_all_sqrt", features.moz_score_all_sqrt);
+ raw_features->SetDouble("moz_score_all_linear",
+ features.moz_score_all_linear);
+ dict.Set("features", std::move(raw_features));
+
+ std::unique_ptr<base::ListValue> derived_features(new base::ListValue());
+ for (double value : derived) {
+ derived_features->AppendDouble(value);
+ }
+ dict.Set("derived_features", std::move(derived_features));
+
+ dict.SetDouble("score", score);
+ dict.SetInteger("distillable", distillable);
+ dict.SetDouble("long_score", long_score);
+ dict.SetInteger("long_page", long_page);
+ dict.SetInteger("blacklisted", blacklisted);
+ base::JSONWriter::WriteWithOptions(
+ dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &msg);
+ msg = "adaboost_classification = " + msg;
+
+ render_frame->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kVerbose,
+ msg);
+}
+
bool IsDistillablePageAdaboost(WebDocument& doc,
const DistillablePageDetector* detector,
const DistillablePageDetector* long_page,
bool is_last,
- bool& is_mobile_friendly) {
+ bool& is_mobile_friendly,
+ content::RenderFrame* render_frame,
+ bool dump_info) {
GURL parsed_url(doc.Url());
if (!parsed_url.is_valid()) {
return false;
@@ -96,6 +147,11 @@ bool IsDistillablePageAdaboost(WebDocument& doc,
bool long_article = long_score > 0;
bool blacklisted = IsBlacklisted(parsed_url);
+ if (dump_info) {
+ DumpDistillability(render_frame, features, derived, score, distillable,
+ long_score, long_article, blacklisted);
+ }
+
if (!features.is_mobile_friendly) {
int score_int = std::round(score * 100);
if (score > 0) {
@@ -154,7 +210,9 @@ bool IsDistillablePageAdaboost(WebDocument& doc,
bool IsDistillablePage(WebDocument& doc,
bool is_last,
- bool& is_mobile_friendly) {
+ bool& is_mobile_friendly,
+ content::RenderFrame* render_frame,
+ bool dump_info) {
switch (GetDistillerHeuristicsType()) {
case DistillerHeuristicsType::ALWAYS_TRUE:
return true;
@@ -165,7 +223,7 @@ bool IsDistillablePage(WebDocument& doc,
return IsDistillablePageAdaboost(
doc, DistillablePageDetector::GetNewModel(),
DistillablePageDetector::GetLongPageModel(), is_last,
- is_mobile_friendly);
+ is_mobile_friendly, render_frame, dump_info);
case DistillerHeuristicsType::NONE:
default:
return false;
@@ -174,8 +232,9 @@ bool IsDistillablePage(WebDocument& doc,
} // namespace
-DistillabilityAgent::DistillabilityAgent(content::RenderFrame* render_frame)
- : RenderFrameObserver(render_frame) {}
+DistillabilityAgent::DistillabilityAgent(content::RenderFrame* render_frame,
+ bool dump_info)
+ : RenderFrameObserver(render_frame), dump_info_(dump_info) {}
void DistillabilityAgent::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
if (layout_type != WebMeaningfulLayout::kFinishedParsing &&
@@ -205,7 +264,8 @@ void DistillabilityAgent::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
if (!distillability_service.is_bound())
return;
bool is_mobile_friendly = false;
- bool is_distillable = IsDistillablePage(doc, is_last, is_mobile_friendly);
+ bool is_distillable = IsDistillablePage(doc, is_last, is_mobile_friendly,
+ render_frame(), dump_info_);
distillability_service->NotifyIsDistillable(is_distillable, is_last,
is_mobile_friendly);
}
diff --git a/chromium/components/dom_distiller/content/renderer/distillability_agent.h b/chromium/components/dom_distiller/content/renderer/distillability_agent.h
index 68772487006..6756f64402c 100644
--- a/chromium/components/dom_distiller/content/renderer/distillability_agent.h
+++ b/chromium/components/dom_distiller/content/renderer/distillability_agent.h
@@ -12,12 +12,15 @@ namespace dom_distiller {
// DistillabilityAgent returns distillability result to DistillabilityDriver.
class DistillabilityAgent : public content::RenderFrameObserver {
public:
- DistillabilityAgent(content::RenderFrame* render_frame);
+ DistillabilityAgent(content::RenderFrame* render_frame, bool dump_info);
~DistillabilityAgent() override;
// content::RenderFrameObserver:
void DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) override;
void OnDestruct() override;
+
+ private:
+ bool dump_info_;
};
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc b/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc
index d26789409b5..50d728ff148 100644
--- a/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc
+++ b/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc
@@ -19,7 +19,7 @@ namespace dom_distiller {
DistillerJsRenderFrameObserver::DistillerJsRenderFrameObserver(
content::RenderFrame* render_frame,
- const int distiller_isolated_world_id,
+ const int32_t distiller_isolated_world_id,
service_manager::BinderRegistry* registry)
: RenderFrameObserver(render_frame),
distiller_isolated_world_id_(distiller_isolated_world_id),
@@ -46,7 +46,7 @@ void DistillerJsRenderFrameObserver::DidFinishLoad() {
void DistillerJsRenderFrameObserver::DidCreateScriptContext(
v8::Local<v8::Context> context,
- int world_id) {
+ int32_t world_id) {
if (world_id != distiller_isolated_world_id_ || !is_distiller_page_) {
return;
}
diff --git a/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h b/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h
index 5a9d121c053..db12f5a6e0d 100644
--- a/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h
+++ b/chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h
@@ -23,7 +23,7 @@ namespace dom_distiller {
class DistillerJsRenderFrameObserver : public content::RenderFrameObserver {
public:
DistillerJsRenderFrameObserver(content::RenderFrame* render_frame,
- const int distiller_isolated_world_id,
+ const int32_t distiller_isolated_world_id,
service_manager::BinderRegistry* registry);
~DistillerJsRenderFrameObserver() override;
@@ -33,7 +33,7 @@ class DistillerJsRenderFrameObserver : public content::RenderFrameObserver {
base::Optional<blink::WebNavigationType> navigation_type) override;
void DidFinishLoad() override;
void DidCreateScriptContext(v8::Local<v8::Context> context,
- int world_id) override;
+ int32_t world_id) override;
// Flag the current page as a distiller page.
void SetIsDistillerPage();
@@ -46,7 +46,7 @@ class DistillerJsRenderFrameObserver : public content::RenderFrameObserver {
void OnDestruct() override;
// The isolated world that the distiller object should be written to.
- int distiller_isolated_world_id_;
+ int32_t distiller_isolated_world_id_;
// Track if the current page is distilled. This is needed for testing.
bool is_distiller_page_;
diff --git a/chromium/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DistilledPagePrefs.java b/chromium/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DistilledPagePrefs.java
index 9b1951e6387..e42e4783cdd 100644
--- a/chromium/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DistilledPagePrefs.java
+++ b/chromium/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DistilledPagePrefs.java
@@ -5,7 +5,6 @@
package org.chromium.components.dom_distiller.core;
import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JCaller;
import org.chromium.base.annotations.JNINamespace;
import java.util.HashMap;
@@ -57,7 +56,7 @@ public final class DistilledPagePrefs {
}
public void destroy() {
- nativeDestroyObserverAndroid(this, mNativeDistilledPagePrefsObserverAndroidPtr);
+ nativeDestroyObserverAndroid(mNativeDistilledPagePrefsObserverAndroidPtr);
}
public long getNativePtr() {
@@ -65,13 +64,6 @@ public final class DistilledPagePrefs {
}
}
- static private native long nativeInitObserverAndroid(
- @JCaller DistilledPagePrefsObserverWrapper caller);
-
- static private native void nativeDestroyObserverAndroid(
- @JCaller DistilledPagePrefsObserverWrapper caller,
- long nativeDistilledPagePrefsObserverAndroid);
-
DistilledPagePrefs(long distilledPagePrefsPtr) {
mDistilledPagePrefsAndroid = nativeInit(distilledPagePrefsPtr);
mObserverMap = new HashMap<Observer, DistilledPagePrefsObserverWrapper>();
@@ -145,4 +137,9 @@ public final class DistilledPagePrefs {
private native void nativeRemoveObserver(long nativeDistilledPagePrefsAndroid,
long nativeObserverPtr);
+
+ private static native long nativeInitObserverAndroid(DistilledPagePrefsObserverWrapper caller);
+
+ private static native void nativeDestroyObserverAndroid(
+ long nativeDistilledPagePrefsObserverAndroid);
}
diff --git a/chromium/components/dom_distiller/core/distilled_content_store_unittest.cc b/chromium/components/dom_distiller/core/distilled_content_store_unittest.cc
index f223607e0ed..31ca8835449 100644
--- a/chromium/components/dom_distiller/core/distilled_content_store_unittest.cc
+++ b/chromium/components/dom_distiller/core/distilled_content_store_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/proto/distilled_article.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -78,7 +78,7 @@ class InMemoryContentStoreTest : public testing::Test {
// Tests whether saving and then loading a single article works as expected.
TEST_F(InMemoryContentStoreTest, SaveAndLoadSingleArticle) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3");
const DistilledArticleProto stored_proto =
CreateDistilledArticleForEntry(entry);
@@ -101,7 +101,7 @@ TEST_F(InMemoryContentStoreTest, SaveAndLoadSingleArticle) {
// Tests that loading articles which have never been stored, yields a callback
// where success is false.
TEST_F(InMemoryContentStoreTest, LoadNonExistentArticle) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
const ArticleEntry entry = CreateEntry("bogus-id", "url1", "url2", "url3");
store_->LoadContent(entry,
base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
@@ -114,7 +114,7 @@ TEST_F(InMemoryContentStoreTest, LoadNonExistentArticle) {
// of save and store does not matter when the total number of articles does not
// exceed |kDefaultMaxNumCachedEntries|.
TEST_F(InMemoryContentStoreTest, SaveAndLoadMultipleArticles) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
// Store first article.
const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3");
const DistilledArticleProto first_stored_proto =
@@ -162,7 +162,7 @@ TEST_F(InMemoryContentStoreTest, SaveAndLoadMultipleArticles) {
// Verifies that the content store does not store unlimited number of articles,
// but expires the oldest ones when the limit for number of articles is reached.
TEST_F(InMemoryContentStoreTest, SaveAndLoadMoreThanMaxArticles) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
// Create a new store with only |kMaxNumArticles| articles as the limit.
const int kMaxNumArticles = 3;
@@ -239,7 +239,7 @@ TEST_F(InMemoryContentStoreTest, SaveAndLoadMoreThanMaxArticles) {
// Tests whether saving and then loading a single article works as expected.
TEST_F(InMemoryContentStoreTest, LookupArticleByURL) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3");
const DistilledArticleProto stored_proto =
CreateDistilledArticleForEntry(entry);
@@ -275,7 +275,7 @@ TEST_F(InMemoryContentStoreTest, LookupArticleByURL) {
// Verifies that the content store does not store unlimited number of articles,
// but expires the oldest ones when the limit for number of articles is reached.
TEST_F(InMemoryContentStoreTest, LoadArticleByURLAfterExpungedFromCache) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
// Create a new store with only |kMaxNumArticles| articles as the limit.
const int kMaxNumArticles = 1;
diff --git a/chromium/components/dom_distiller/core/distilled_page_prefs_android.cc b/chromium/components/dom_distiller/core/distilled_page_prefs_android.cc
index 22a597a4576..7e8556e0bc3 100644
--- a/chromium/components/dom_distiller/core/distilled_page_prefs_android.cc
+++ b/chromium/components/dom_distiller/core/distilled_page_prefs_android.cc
@@ -93,9 +93,7 @@ DistilledPagePrefsObserverAndroid::DistilledPagePrefsObserverAndroid(
DistilledPagePrefsObserverAndroid::~DistilledPagePrefsObserverAndroid() {}
-void DistilledPagePrefsObserverAndroid::DestroyObserverAndroid(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
+void DistilledPagePrefsObserverAndroid::DestroyObserverAndroid(JNIEnv* env) {
delete this;
}
diff --git a/chromium/components/dom_distiller/core/distilled_page_prefs_android.h b/chromium/components/dom_distiller/core/distilled_page_prefs_android.h
index 22521ed3317..5c1877e8dae 100644
--- a/chromium/components/dom_distiller/core/distilled_page_prefs_android.h
+++ b/chromium/components/dom_distiller/core/distilled_page_prefs_android.h
@@ -59,9 +59,7 @@ class DistilledPagePrefsObserverAndroid : public DistilledPagePrefs::Observer {
void OnChangeTheme(DistilledPagePrefs::Theme new_theme) override;
void OnChangeFontScaling(float scaling) override;
- virtual void DestroyObserverAndroid(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
+ virtual void DestroyObserverAndroid(JNIEnv* env);
private:
base::android::ScopedJavaGlobalRef<jobject> java_ref_;
diff --git a/chromium/components/dom_distiller/core/distilled_page_prefs_unittests.cc b/chromium/components/dom_distiller/core/distilled_page_prefs_unittests.cc
index 5d537adf954..d269da6bfaa 100644
--- a/chromium/components/dom_distiller/core/distilled_page_prefs_unittests.cc
+++ b/chromium/components/dom_distiller/core/distilled_page_prefs_unittests.cc
@@ -4,8 +4,8 @@
#include "components/dom_distiller/core/distilled_page_prefs.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/task_environment.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -58,7 +58,7 @@ class DistilledPagePrefsTest : public testing::Test {
std::unique_ptr<DistilledPagePrefs> distilled_page_prefs_;
private:
- base::MessageLoop message_loop_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(DistilledPagePrefsTest, TestingOnChangeFontIsBeingCalled) {
diff --git a/chromium/components/dom_distiller/core/distiller_unittest.cc b/chromium/components/dom_distiller/core/distiller_unittest.cc
index 48a1ee4db3a..b2c68fa9faf 100644
--- a/chromium/components/dom_distiller/core/distiller_unittest.cc
+++ b/chromium/components/dom_distiller/core/distiller_unittest.cc
@@ -21,7 +21,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "components/dom_distiller/core/article_distillation_update.h"
@@ -308,8 +308,8 @@ class DistillerTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
std::unique_ptr<DistillerImpl> distiller_;
std::unique_ptr<DistilledArticleProto> article_proto_;
std::vector<ArticleDistillationUpdate> in_sequence_updates_;
diff --git a/chromium/components/dom_distiller/core/distiller_url_fetcher_unittest.cc b/chromium/components/dom_distiller/core/distiller_url_fetcher_unittest.cc
index 0d53174090b..fed30b9cca0 100644
--- a/chromium/components/dom_distiller/core/distiller_url_fetcher_unittest.cc
+++ b/chromium/components/dom_distiller/core/distiller_url_fetcher_unittest.cc
@@ -3,10 +3,11 @@
// found in the LICENSE file.
#include "components/dom_distiller/core/distiller_url_fetcher.h"
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
@@ -50,8 +51,8 @@ class DistillerURLFetcherTest : public testing::Test {
CHECK_EQ(expected_response, response_);
}
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
std::unique_ptr<dom_distiller::DistillerURLFetcher> url_fetcher_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/chromium/components/dom_distiller/core/dom_distiller_features.cc b/chromium/components/dom_distiller/core/dom_distiller_features.cc
index 01077037500..d1f0d43c2bb 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_features.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_features.cc
@@ -11,9 +11,14 @@
namespace dom_distiller {
-bool IsEnableDomDistillerSet() {
+bool IsDomDistillerEnabled() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableDomDistiller);
}
+bool ShouldStartDistillabilityService() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDistillabilityService);
+}
+
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/dom_distiller_features.h b/chromium/components/dom_distiller/core/dom_distiller_features.h
index 22ed52f9903..d1e56a3db12 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_features.h
+++ b/chromium/components/dom_distiller/core/dom_distiller_features.h
@@ -8,7 +8,9 @@
namespace dom_distiller {
// Returns true when flag enable-dom-distiller is set or enabled from Finch.
-bool IsEnableDomDistillerSet();
+bool IsDomDistillerEnabled();
+
+bool ShouldStartDistillabilityService();
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/core/dom_distiller_service_android.cc b/chromium/components/dom_distiller/core/dom_distiller_service_android.cc
index f8b1e8a5892..039288accca 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service_android.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_service_android.cc
@@ -48,9 +48,7 @@ ScopedJavaLocalRef<jstring> DomDistillerServiceAndroid::GetUrlForEntry(
return ConvertUTF8ToJavaString(env, service_->GetUrlForEntry(entry_id));
}
-jlong DomDistillerServiceAndroid::GetDistilledPagePrefsPtr(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
+jlong DomDistillerServiceAndroid::GetDistilledPagePrefsPtr(JNIEnv* env) {
return reinterpret_cast<intptr_t>(service_->GetDistilledPagePrefs());
}
diff --git a/chromium/components/dom_distiller/core/dom_distiller_service_android.h b/chromium/components/dom_distiller/core/dom_distiller_service_android.h
index e0e133f179d..57145720df8 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service_android.h
+++ b/chromium/components/dom_distiller/core/dom_distiller_service_android.h
@@ -23,9 +23,7 @@ class DomDistillerServiceAndroid {
virtual ~DomDistillerServiceAndroid();
// Returns native pointer to native DistilledPagePrefs registered with
// DomDistillerService.
- jlong GetDistilledPagePrefsPtr(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
+ jlong GetDistilledPagePrefsPtr(JNIEnv* env);
bool HasEntry(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jstring>& entry_id);
diff --git a/chromium/components/dom_distiller/core/dom_distiller_service_unittest.cc b/chromium/components/dom_distiller/core/dom_distiller_service_unittest.cc
index 5a6c5ac1b61..b595edffb03 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service_unittest.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_service_unittest.cc
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/distilled_page_prefs.h"
#include "components/dom_distiller/core/dom_distiller_model.h"
@@ -103,7 +103,7 @@ class DomDistillerServiceTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
// store is owned by service_.
DomDistillerStoreInterface* store_;
MockDistillerFactory* distiller_factory_;
diff --git a/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc b/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc
index c68f6d388ec..3f4600c10f2 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -14,7 +14,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/dom_distiller_test_util.h"
@@ -159,7 +159,7 @@ class DomDistillerStoreTest : public testing::Test {
return data;
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
EntryMap db_model_;
EntryMap sync_model_;
diff --git a/chromium/components/dom_distiller/core/dom_distiller_switches.cc b/chromium/components/dom_distiller/core/dom_distiller_switches.cc
index 0603cb42199..2cebccabd4a 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_switches.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_switches.cc
@@ -19,9 +19,4 @@ const char kAlwaysTrue[] = "alwaystrue";
const char kNone[] = "none";
} // namespace reader_mode_heuristics
-namespace reader_mode_feedback {
-const char kOn[] = "on";
-const char kOff[] = "off";
-} // namespace reader_mode_feedback
-
} // namespace switches
diff --git a/chromium/components/dom_distiller/core/dom_distiller_switches.h b/chromium/components/dom_distiller/core/dom_distiller_switches.h
index 48e6a030ea2..3cb3aeb28c3 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_switches.h
+++ b/chromium/components/dom_distiller/core/dom_distiller_switches.h
@@ -30,11 +30,6 @@ extern const char kAlwaysTrue[];
extern const char kNone[];
} // namespace reader_mode_heuristics
-namespace reader_mode_feedback {
-extern const char kOn[];
-extern const char kOff[];
-} // namespace reader_mode_feedback
-
} // namespace switches
#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_SWITCHES_H_
diff --git a/chromium/components/dom_distiller/core/task_tracker_unittest.cc b/chromium/components/dom_distiller/core/task_tracker_unittest.cc
index b31e3f57eeb..fbecfb36e05 100644
--- a/chromium/components/dom_distiller/core/task_tracker_unittest.cc
+++ b/chromium/components/dom_distiller/core/task_tracker_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/dom_distiller/core/article_distillation_update.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/distilled_content_store.h"
@@ -78,7 +78,7 @@ class DomDistillerTaskTrackerTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::string entry_id_;
GURL page_0_url_;
GURL page_1_url_;
diff --git a/chromium/components/dom_distiller/ios/distiller_page_ios.mm b/chromium/components/dom_distiller/ios/distiller_page_ios.mm
index 109b93d6596..9f261830dc9 100644
--- a/chromium/components/dom_distiller/ios/distiller_page_ios.mm
+++ b/chromium/components/dom_distiller/ios/distiller_page_ios.mm
@@ -21,7 +21,7 @@
#import "ios/web/public/deprecated/crw_js_injection_receiver.h"
#import "ios/web/public/navigation/navigation_manager.h"
#import "ios/web/public/navigation/web_state_policy_decider.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#include "ios/web/public/web_state/web_state_observer.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc b/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc
index 4c45a46681d..227c8fea5a5 100644
--- a/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc
+++ b/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc
@@ -32,8 +32,6 @@
#include "components/dom_distiller/core/proto/distilled_article.pb.h"
#include "components/dom_distiller/core/proto/distilled_page.pb.h"
#include "components/dom_distiller/core/task_tracker.h"
-#include "components/keyed_service/core/simple_key_map.h"
-#include "components/leveldb_proto/content/proto_database_provider_factory.h"
#include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -132,15 +130,14 @@ std::unique_ptr<DomDistillerService> CreateDomDistillerService(
const base::FilePath& db_path,
const FileToUrlMap& file_to_url_map) {
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
- base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()});
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock()});
// Setting up PrefService for DistilledPagePrefs.
DistilledPagePrefs::RegisterProfilePrefs(pref_service->registry());
- SimpleFactoryKey* key =
- SimpleKeyMap::GetInstance()->GetForBrowserContext(context);
auto* db_provider =
- leveldb_proto::ProtoDatabaseProviderFactory::GetForKey(key);
+ content::BrowserContext::GetDefaultStoragePartition(context)
+ ->GetProtoDatabaseProvider();
// TODO(cjhopman): use an in-memory database instead of an on-disk one with
// temporary directory.
diff --git a/chromium/components/dom_distiller/webui/dom_distiller_ui.cc b/chromium/components/dom_distiller/webui/dom_distiller_ui.cc
index 09701535380..c9c8672fa14 100644
--- a/chromium/components/dom_distiller/webui/dom_distiller_ui.cc
+++ b/chromium/components/dom_distiller/webui/dom_distiller_ui.cc
@@ -50,7 +50,7 @@ DomDistillerUi::DomDistillerUi(content::WebUI* web_ui,
content::BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
content::WebUIDataSource::Add(browser_context, source);
- source->SetJsonPath("strings.js");
+ source->UseStringsJs();
// Add message handler.
web_ui->AddMessageHandler(
diff --git a/chromium/components/domain_reliability/OWNERS b/chromium/components/domain_reliability/OWNERS
index 1cfbdeee008..ca9b3d5e965 100644
--- a/chromium/components/domain_reliability/OWNERS
+++ b/chromium/components/domain_reliability/OWNERS
@@ -4,3 +4,4 @@ per-file quic_error_mapping*=rch@chromium.org
per-file quic_error_mapping*=zhongyi@chromium.org
# COMPONENT: Internals>Network
+# TEAM: net-dev@chromium.org
diff --git a/chromium/components/domain_reliability/quic_error_mapping.cc b/chromium/components/domain_reliability/quic_error_mapping.cc
index 487332b8fbf..521488c07c5 100644
--- a/chromium/components/domain_reliability/quic_error_mapping.cc
+++ b/chromium/components/domain_reliability/quic_error_mapping.cc
@@ -307,6 +307,8 @@ const struct QuicErrorMapping {
{quic::QUIC_IETF_GQUIC_ERROR_MISSING, "quic.ietf.gquic.error_missing"},
{quic::QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM,
"quic.window.update.received.on.read.unidirectional.stream"},
+ {quic::QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
+ "quic.too.many.buffered.control.frames"},
// QUIC_INVALID_APPLICATION_CLOSE_DATA was code 101. The code has been
// deprecated, but to keep the assert below happy, there needs to be
diff --git a/chromium/components/domain_reliability/uploader_unittest.cc b/chromium/components/domain_reliability/uploader_unittest.cc
index 374f2fe3033..ed1dea31619 100644
--- a/chromium/components/domain_reliability/uploader_unittest.cc
+++ b/chromium/components/domain_reliability/uploader_unittest.cc
@@ -12,7 +12,7 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/domain_reliability/test_util.h"
@@ -196,8 +196,8 @@ class DomainReliabilityUploaderTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::IO};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
UploadInterceptor* interceptor_;
MockTime time_;
diff --git a/chromium/components/download/content/factory/BUILD.gn b/chromium/components/download/content/factory/BUILD.gn
index d9eb53fa253..5d754f7bd5f 100644
--- a/chromium/components/download/content/factory/BUILD.gn
+++ b/chromium/components/download/content/factory/BUILD.gn
@@ -22,7 +22,6 @@ source_set("factory") {
"//components/download/network",
"//components/keyed_service/content",
"//components/leveldb_proto",
- "//components/leveldb_proto/content:factory",
"//content/public/browser",
"//net",
"//url",
diff --git a/chromium/components/download/content/factory/download_service_factory_helper.cc b/chromium/components/download/content/factory/download_service_factory_helper.cc
index 3bd089b9563..7be7ce8f4cb 100644
--- a/chromium/components/download/content/factory/download_service_factory_helper.cc
+++ b/chromium/components/download/content/factory/download_service_factory_helper.cc
@@ -25,7 +25,6 @@
#include "components/download/internal/background_service/scheduler/scheduler_impl.h"
#include "components/download/public/common/simple_download_manager_coordinator.h"
#include "components/download/public/task/empty_task_scheduler.h"
-#include "components/leveldb_proto/content/proto_database_provider_factory.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -103,6 +102,7 @@ std::unique_ptr<DownloadService> BuildDownloadService(
network::NetworkConnectionTracker* network_connection_tracker,
const base::FilePath& storage_dir,
SimpleDownloadManagerCoordinator* download_manager_coordinator,
+ leveldb_proto::ProtoDatabaseProvider* proto_db_provider,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
std::unique_ptr<TaskScheduler> task_scheduler) {
auto config = Configuration::CreateFromFinch();
@@ -112,10 +112,7 @@ std::unique_ptr<DownloadService> BuildDownloadService(
auto entry_db_storage_dir = storage_dir.Append(kEntryDBStorageDir);
- leveldb_proto::ProtoDatabaseProvider* db_provider =
- leveldb_proto::ProtoDatabaseProviderFactory::GetForKey(
- simple_factory_key);
- auto entry_db = db_provider->GetDB<protodb::Entry>(
+ auto entry_db = proto_db_provider->GetDB<protodb::Entry>(
leveldb_proto::ProtoDbType::DOWNLOAD_STORE, entry_db_storage_dir,
background_task_runner);
auto store = std::make_unique<DownloadStore>(std::move(entry_db));
diff --git a/chromium/components/download/content/factory/download_service_factory_helper.h b/chromium/components/download/content/factory/download_service_factory_helper.h
index 4d4d4e24f90..d7384dcae2f 100644
--- a/chromium/components/download/content/factory/download_service_factory_helper.h
+++ b/chromium/components/download/content/factory/download_service_factory_helper.h
@@ -21,6 +21,10 @@ class NetworkConnectionTracker;
class SharedURLLoaderFactory;
} // namespace network
+namespace leveldb_proto {
+class ProtoDatabaseProvider;
+} // namespace leveldb_proto
+
namespace download {
class DownloadService;
@@ -43,6 +47,7 @@ std::unique_ptr<DownloadService> BuildDownloadService(
network::NetworkConnectionTracker* network_connection_tracker,
const base::FilePath& storage_dir,
SimpleDownloadManagerCoordinator* download_manager_coordinator,
+ leveldb_proto::ProtoDatabaseProvider* proto_db_provider,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
std::unique_ptr<TaskScheduler> task_scheduler);
diff --git a/chromium/components/download/database/download_db_impl.cc b/chromium/components/download/database/download_db_impl.cc
index b1a5ca60889..2e728e8fe1c 100644
--- a/chromium/components/download/database/download_db_impl.cc
+++ b/chromium/components/download/database/download_db_impl.cc
@@ -20,7 +20,6 @@ namespace {
const int kMaxNumInitializeAttempts = 3;
-const char kDatabaseClientName[] = "DownloadDB";
using ProtoKeyVector = std::vector<std::string>;
using ProtoEntryVector = std::vector<download_pb::DownloadDBEntry>;
using ProtoKeyEntryVector =
@@ -46,30 +45,27 @@ void OnUpdateDone(bool success) {
} // namespace
-DownloadDBImpl::DownloadDBImpl(DownloadNamespace download_namespace,
- const base::FilePath& database_dir)
- : DownloadDBImpl(
- download_namespace,
- database_dir,
- leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB<
- download_pb::DownloadDBEntry>(
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(),
- // USER_VISIBLE because it is required to display
- // chrome://downloads. https://crbug.com/976223
- base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))) {}
-
DownloadDBImpl::DownloadDBImpl(
DownloadNamespace download_namespace,
const base::FilePath& database_dir,
+ leveldb_proto::ProtoDatabaseProvider* db_provider)
+ : download_namespace_(download_namespace) {
+ DCHECK(!database_dir.empty());
+ db_ = db_provider->GetDB<download_pb::DownloadDBEntry>(
+ leveldb_proto::ProtoDbType::DOWNLOAD_DB, database_dir,
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::ThreadPool(), base::MayBlock(),
+ // USER_VISIBLE because it is required to display chrome://downloads.
+ // https://crbug.com/976223
+ base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}));
+}
+
+DownloadDBImpl::DownloadDBImpl(
+ DownloadNamespace download_namespace,
std::unique_ptr<leveldb_proto::ProtoDatabase<download_pb::DownloadDBEntry>>
db)
- : database_dir_(database_dir),
- db_(std::move(db)),
- is_initialized_(false),
- download_namespace_(download_namespace),
- num_initialize_attempts_(0) {}
+ : db_(std::move(db)), download_namespace_(download_namespace) {}
DownloadDBImpl::~DownloadDBImpl() = default;
@@ -84,7 +80,7 @@ void DownloadDBImpl::Initialize(DownloadDBCallback callback) {
leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
options.reuse_logs = false;
options.write_buffer_size = 64 << 10; // 64 KiB
- db_->Init(kDatabaseClientName, database_dir_, options,
+ db_->Init(options,
base::BindOnce(&DownloadDBImpl::OnDatabaseInitialized,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
@@ -153,8 +149,10 @@ void DownloadDBImpl::OnAllEntriesLoaded(
std::move(callback).Run(success, std::move(result));
}
-void DownloadDBImpl::OnDatabaseInitialized(DownloadDBCallback callback,
- bool success) {
+void DownloadDBImpl::OnDatabaseInitialized(
+ DownloadDBCallback callback,
+ leveldb_proto::Enums::InitStatus status) {
+ bool success = status == leveldb_proto::Enums::InitStatus::kOK;
if (!success) {
DestroyAndReinitialize(std::move(callback));
return;
diff --git a/chromium/components/download/database/download_db_impl.h b/chromium/components/download/database/download_db_impl.h
index a1a6b65b781..2a85c7cb564 100644
--- a/chromium/components/download/database/download_db_impl.h
+++ b/chromium/components/download/database/download_db_impl.h
@@ -18,16 +18,20 @@ namespace download_pb {
class DownloadDBEntry;
}
+namespace leveldb_proto {
+class ProtoDatabaseProvider;
+} // namespace leveldb_proto
+
namespace download {
// A protodb Implementation of DownloadDB.
class DownloadDBImpl : public DownloadDB {
public:
DownloadDBImpl(DownloadNamespace download_namespace,
- const base::FilePath& database_dir);
+ const base::FilePath& database_dir,
+ leveldb_proto::ProtoDatabaseProvider* db_provider);
DownloadDBImpl(
DownloadNamespace download_namespace,
- const base::FilePath& database_dir,
std::unique_ptr<
leveldb_proto::ProtoDatabase<download_pb::DownloadDBEntry>> db);
~DownloadDBImpl() override;
@@ -51,7 +55,8 @@ class DownloadDBImpl : public DownloadDB {
std::string GetEntryKey(const std::string& guid) const;
// Called when database is initialized.
- void OnDatabaseInitialized(DownloadDBCallback callback, bool success);
+ void OnDatabaseInitialized(DownloadDBCallback callback,
+ leveldb_proto::Enums::InitStatus status);
// Called when database is destroyed.
void OnDatabaseDestroyed(DownloadDBCallback callback, bool success);
@@ -65,21 +70,18 @@ class DownloadDBImpl : public DownloadDB {
bool success,
std::unique_ptr<std::vector<download_pb::DownloadDBEntry>> entries);
- // Directory to store |db_|.
- base::FilePath database_dir_;
-
// Proto db for storing all the entries.
std::unique_ptr<leveldb_proto::ProtoDatabase<download_pb::DownloadDBEntry>>
db_;
// Whether the object is initialized.
- bool is_initialized_;
+ bool is_initialized_ = false;
// Namespace of this db.
DownloadNamespace download_namespace_;
// Number of initialize attempts.
- int num_initialize_attempts_;
+ int num_initialize_attempts_ = 0;
base::WeakPtrFactory<DownloadDBImpl> weak_factory_{this};
diff --git a/chromium/components/download/database/download_db_impl_unittest.cc b/chromium/components/download/database/download_db_impl_unittest.cc
index cd582a2908f..4df08226694 100644
--- a/chromium/components/download/database/download_db_impl_unittest.cc
+++ b/chromium/components/download/database/download_db_impl_unittest.cc
@@ -50,8 +50,7 @@ class DownloadDBTest : public testing::Test {
&db_entries_);
db_ = db.get();
download_db_.reset(new DownloadDBImpl(
- DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD,
- base::FilePath(FILE_PATH_LITERAL("/test/db/fakepath")), std::move(db)));
+ DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD, std::move(db)));
}
void InitCallback(bool success) { init_success_ = success; }
@@ -99,7 +98,7 @@ TEST_F(DownloadDBTest, InitializeSucceeded) {
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(IsInitialized());
ASSERT_TRUE(init_success_);
@@ -111,7 +110,7 @@ TEST_F(DownloadDBTest, InitializeFailed) {
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(false);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kError);
ASSERT_FALSE(IsInitialized());
ASSERT_FALSE(init_success_);
@@ -122,7 +121,7 @@ TEST_F(DownloadDBTest, LoadEntries) {
CreateDatabase();
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(IsInitialized());
std::vector<DownloadDBEntry> loaded_entries;
@@ -142,7 +141,7 @@ TEST_F(DownloadDBTest, AddEntry) {
CreateDatabase();
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(IsInitialized());
DownloadDBEntry entry = CreateDownloadDBEntry();
@@ -173,7 +172,7 @@ TEST_F(DownloadDBTest, ReplaceEntry) {
CreateDatabase();
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(IsInitialized());
InProgressInfo in_progress_info;
@@ -210,7 +209,7 @@ TEST_F(DownloadDBTest, Remove) {
CreateDatabase();
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(IsInitialized());
download_db_->Remove(first.GetGuid());
@@ -231,7 +230,7 @@ TEST_F(DownloadDBTest, DestroyAndReinitialize) {
CreateDatabase();
download_db_->Initialize(
base::BindOnce(&DownloadDBTest::InitCallback, base::Unretained(this)));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(IsInitialized());
std::vector<DownloadDBEntry> loaded_entries;
diff --git a/chromium/components/download/internal/background_service/blob_task_proxy.h b/chromium/components/download/internal/background_service/blob_task_proxy.h
index 2714fb74b4b..7de3466b4b0 100644
--- a/chromium/components/download/internal/background_service/blob_task_proxy.h
+++ b/chromium/components/download/internal/background_service/blob_task_proxy.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
-#include "storage/common/blob_storage/blob_storage_constants.h"
+#include "storage/browser/blob/blob_storage_constants.h"
namespace storage {
class BlobDataHandle;
diff --git a/chromium/components/download/internal/background_service/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc
index 2469409cbfc..3c02debb23e 100644
--- a/chromium/components/download/internal/background_service/controller_impl.cc
+++ b/chromium/components/download/internal/background_service/controller_impl.cc
@@ -212,6 +212,8 @@ void ControllerImpl::StartDownload(const DownloadParams& params) {
void ControllerImpl::PauseDownload(const std::string& guid) {
DCHECK(controller_state_ == State::READY ||
controller_state_ == State::UNAVAILABLE);
+ stats::LogServiceApiAction(GetOwnerOfDownload(guid),
+ stats::ServiceApiAction::PAUSE_DOWNLOAD);
if (controller_state_ != State::READY)
return;
@@ -234,6 +236,8 @@ void ControllerImpl::PauseDownload(const std::string& guid) {
void ControllerImpl::ResumeDownload(const std::string& guid) {
DCHECK(controller_state_ == State::READY ||
controller_state_ == State::UNAVAILABLE);
+ stats::LogServiceApiAction(GetOwnerOfDownload(guid),
+ stats::ServiceApiAction::RESUME_DOWNLOAD);
if (controller_state_ != State::READY)
return;
@@ -252,6 +256,8 @@ void ControllerImpl::ResumeDownload(const std::string& guid) {
void ControllerImpl::CancelDownload(const std::string& guid) {
DCHECK(controller_state_ == State::READY ||
controller_state_ == State::UNAVAILABLE);
+ stats::LogServiceApiAction(GetOwnerOfDownload(guid),
+ stats::ServiceApiAction::CANCEL_DOWNLOAD);
if (controller_state_ != State::READY)
return;
@@ -274,6 +280,8 @@ void ControllerImpl::ChangeDownloadCriteria(const std::string& guid,
const SchedulingParams& params) {
DCHECK(controller_state_ == State::READY ||
controller_state_ == State::UNAVAILABLE);
+ stats::LogServiceApiAction(GetOwnerOfDownload(guid),
+ stats::ServiceApiAction::CHANGE_CRITERIA);
if (controller_state_ != State::READY)
return;
diff --git a/chromium/components/download/internal/background_service/download_service_impl.cc b/chromium/components/download/internal/background_service/download_service_impl.cc
index 6a30111d255..f41e6d7f9bb 100644
--- a/chromium/components/download/internal/background_service/download_service_impl.cc
+++ b/chromium/components/download/internal/background_service/download_service_impl.cc
@@ -89,8 +89,6 @@ void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) {
}
void DownloadServiceImpl::PauseDownload(const std::string& guid) {
- stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
- stats::ServiceApiAction::PAUSE_DOWNLOAD);
if (startup_completed_) {
controller_->PauseDownload(guid);
} else {
@@ -100,8 +98,6 @@ void DownloadServiceImpl::PauseDownload(const std::string& guid) {
}
void DownloadServiceImpl::ResumeDownload(const std::string& guid) {
- stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
- stats::ServiceApiAction::RESUME_DOWNLOAD);
if (startup_completed_) {
controller_->ResumeDownload(guid);
} else {
@@ -112,8 +108,6 @@ void DownloadServiceImpl::ResumeDownload(const std::string& guid) {
}
void DownloadServiceImpl::CancelDownload(const std::string& guid) {
- stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
- stats::ServiceApiAction::CANCEL_DOWNLOAD);
if (startup_completed_) {
controller_->CancelDownload(guid);
} else {
@@ -126,8 +120,6 @@ void DownloadServiceImpl::CancelDownload(const std::string& guid) {
void DownloadServiceImpl::ChangeDownloadCriteria(
const std::string& guid,
const SchedulingParams& params) {
- stats::LogServiceApiAction(controller_->GetOwnerOfDownload(guid),
- stats::ServiceApiAction::CHANGE_CRITERIA);
if (startup_completed_) {
controller_->ChangeDownloadCriteria(guid, params);
} else {
diff --git a/chromium/components/download/internal/background_service/in_memory_download_unittest.cc b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
index 19a7e6d353f..5c4b9dfffc7 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
@@ -6,10 +6,10 @@
#include "base/bind.h"
#include "base/guid.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "net/base/io_buffer.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -89,7 +89,7 @@ class InMemoryDownloadTest : public testing::Test {
void SetUp() override {
io_thread_.reset(new base::Thread("Network and Blob IO thread"));
- base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
+ base::Thread::Options options(base::MessagePumpType::IO, 0);
io_thread_->StartWithOptions(options);
base::RunLoop loop;
@@ -172,7 +172,7 @@ class InMemoryDownloadTest : public testing::Test {
std::unique_ptr<base::Thread> io_thread_;
// Created before other objects to provide test environment.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<InMemoryDownloadImpl> download_;
std::unique_ptr<NiceMock<MockDelegate>> mock_delegate_;
diff --git a/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
index e3da016383e..d6ad0b4b9a7 100644
--- a/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
+++ b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
@@ -8,7 +8,7 @@
#include "base/run_loop.h"
#include "base/test/power_monitor_test_base.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/download/internal/background_service/scheduler/battery_status_listener_impl.h"
#include "components/download/network/network_status_listener_impl.h"
#include "services/network/test/test_network_connection_tracker.h"
@@ -146,7 +146,7 @@ class DeviceStatusListenerTest : public testing::Test {
MockObserver mock_observer_;
// Needed for network change notifier and power monitor.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::PowerMonitorTestSource* power_source_;
TestBatteryStatusListener* test_battery_listener_;
};
diff --git a/chromium/components/download/internal/background_service/stats.cc b/chromium/components/download/internal/background_service/stats.cc
index 282cf52abfd..ac937aba898 100644
--- a/chromium/components/download/internal/background_service/stats.cc
+++ b/chromium/components/download/internal/background_service/stats.cc
@@ -15,10 +15,6 @@ namespace download {
namespace stats {
namespace {
-// The maximum tracked file size in KB, larger files will fall into overflow
-// bucket.
-const int64_t kMaxFileSizeKB = 4 * 1024 * 1024; /* 4GB */
-
// Enum used by UMA metrics to track various reasons of pausing a download.
enum class PauseReason {
// The download was paused. The reason can be anything.
@@ -104,35 +100,6 @@ std::string ClientToHistogramSuffix(DownloadClient client) {
return std::string();
}
-// Converts CompletionType to histogram suffix.
-// Should maps to suffix string in histograms.xml.
-std::string CompletionTypeToHistogramSuffix(CompletionType type) {
- switch (type) {
- case CompletionType::SUCCEED:
- return "Succeed";
- case CompletionType::FAIL:
- return "Fail";
- case CompletionType::ABORT:
- return "Abort";
- case CompletionType::TIMEOUT:
- return "Timeout";
- case CompletionType::UNKNOWN:
- return "Unknown";
- case CompletionType::CANCEL:
- return "Cancel";
- case CompletionType::OUT_OF_RETRIES:
- return "OutOfRetries";
- case CompletionType::OUT_OF_RESUMPTIONS:
- return "OutOfResumptions";
- case CompletionType::UPLOAD_TIMEOUT:
- return "UploadTimeout";
- case CompletionType::COUNT:
- NOTREACHED();
- }
- NOTREACHED();
- return std::string();
-}
-
// Converts FileCleanupReason to histogram suffix.
// Should maps to suffix string in histograms.xml.
std::string FileCleanupReasonToHistogramSuffix(FileCleanupReason reason) {
@@ -234,14 +201,6 @@ void LogDownloadCompletion(CompletionType type, uint64_t file_size_bytes) {
// TODO(xingliu): Use DownloadItem::GetStartTime and DownloadItem::GetEndTime
// to record the completion time to histogram "Download.Service.Finish.Time".
// Also propagates and records the mime type here.
-
- // Records the file size.
- std::string name("Download.Service.Finish.FileSize");
- uint64_t file_size_kb = file_size_bytes / 1024;
- base::UmaHistogramCustomCounts(name, file_size_kb, 1, kMaxFileSizeKB, 50);
-
- name.append(".").append(CompletionTypeToHistogramSuffix(type));
- base::UmaHistogramCustomCounts(name, file_size_kb, 1, kMaxFileSizeKB, 50);
}
void LogDownloadPauseReason(const DownloadBlockageStatus& blockage_status,
diff --git a/chromium/components/download/internal/common/BUILD.gn b/chromium/components/download/internal/common/BUILD.gn
index 63db61acc4b..4959f0a026c 100644
--- a/chromium/components/download/internal/common/BUILD.gn
+++ b/chromium/components/download/internal/common/BUILD.gn
@@ -39,8 +39,6 @@ source_set("internal") {
"download_stats.cc",
"download_task_runner.cc",
"download_ukm_helper.cc",
- "download_url_loader_factory_getter.cc",
- "download_url_loader_factory_getter_impl.cc",
"download_utils.cc",
"download_worker.cc",
"download_worker.h",
@@ -59,9 +57,12 @@ source_set("internal") {
"stream_handle_input_stream.cc",
"url_download_handler_factory.cc",
"url_download_request_handle.cc",
+ "url_loader_factory_provider.cc",
]
public_deps = [
+ "//components/services/quarantine/public/mojom",
+ "//mojo/public/cpp/bindings",
"//services/network/public/mojom",
]
diff --git a/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java b/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
index cdf3e44e5bc..e710401f2f1 100644
--- a/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
+++ b/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
@@ -73,7 +73,7 @@ public class DownloadCollectionBridge {
* @param filePath File path of the download.
* @return True if the download needs to be published, or false otherwise.
*/
- protected boolean needToPublishDownload(final String filePath) {
+ public boolean needToPublishDownload(final String filePath) {
return false;
}
@@ -116,10 +116,12 @@ public class DownloadCollectionBridge {
}
/**
- * @return whether a download with the file name exists.
+ * Gets the content URI of the download that has the given file name.
+ * @param pendingUri name of the file.
+ * @return Uri of the download with the given display name.
*/
- protected boolean checkFileNameExists(final String fileName) {
- return false;
+ public Uri getDownloadUriForFileName(final String fileName) {
+ return null;
}
/**
@@ -251,7 +253,8 @@ public class DownloadCollectionBridge {
*/
@CalledByNative
private static boolean fileNameExists(final String fileName) {
- return getDownloadCollectionBridge().checkFileNameExists(fileName);
+ Uri uri = getDownloadCollectionBridge().getDownloadUriForFileName(fileName);
+ return uri != null;
}
/**
diff --git a/chromium/components/download/internal/common/base_file.cc b/chromium/components/download/internal/common/base_file.cc
index 9497a10ae44..5f955ab6340 100644
--- a/chromium/components/download/internal/common/base_file.cc
+++ b/chromium/components/download/internal/common/base_file.cc
@@ -25,7 +25,6 @@
#include "components/download/public/common/download_stats.h"
#include "components/download/quarantine/quarantine.h"
#include "crypto/secure_hash.h"
-#include "services/service_manager/public/cpp/connector.h"
#if defined(OS_WIN)
#include "components/services/quarantine/public/cpp/quarantine_features_win.h"
@@ -651,10 +650,10 @@ void BaseFile::AnnotateWithSourceInformation(
const std::string& client_guid,
const GURL& source_url,
const GURL& referrer_url,
- std::unique_ptr<service_manager::Connector> connector,
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
OnAnnotationDoneCallback on_annotation_done_callback) {
GURL authority_url = GetEffectiveAuthorityURL(source_url, referrer_url);
- if (!connector) {
+ if (!remote_quarantine) {
#if defined(OS_WIN)
QuarantineFileResult result = quarantine::SetInternetZoneIdentifierDirectly(
full_path_, authority_url, referrer_url);
@@ -664,12 +663,11 @@ void BaseFile::AnnotateWithSourceInformation(
std::move(on_annotation_done_callback)
.Run(QuarantineFileResultToReason(result));
} else {
- connector->BindInterface(quarantine::mojom::kServiceName,
- mojo::MakeRequest(&quarantine_service_));
+ quarantine_service_.Bind(std::move(remote_quarantine));
on_annotation_done_callback_ = std::move(on_annotation_done_callback);
- quarantine_service_.set_connection_error_handler(base::BindOnce(
+ quarantine_service_.set_disconnect_handler(base::BindOnce(
&BaseFile::OnQuarantineServiceError, weak_factory_.GetWeakPtr(),
authority_url, referrer_url));
diff --git a/chromium/components/download/internal/common/download_db_cache.cc b/chromium/components/download/internal/common/download_db_cache.cc
index e9f8afffb41..fc6c029813d 100644
--- a/chromium/components/download/internal/common/download_db_cache.cc
+++ b/chromium/components/download/internal/common/download_db_cache.cc
@@ -73,6 +73,9 @@ void CleanUpInProgressEntry(DownloadDBEntry* entry) {
in_progress_info->state = DownloadItem::DownloadState::INTERRUPTED;
in_progress_info->interrupt_reason =
download::DOWNLOAD_INTERRUPT_REASON_CRASH;
+ // We should not trust the hash value for crashed in-progress download, as
+ // hash is not calculated for when download is in progress.
+ in_progress_info->hash = std::string();
}
}
diff --git a/chromium/components/download/internal/common/download_db_cache_unittest.cc b/chromium/components/download/internal/common/download_db_cache_unittest.cc
index e39763bc48b..02c322875ae 100644
--- a/chromium/components/download/internal/common/download_db_cache_unittest.cc
+++ b/chromium/components/download/internal/common/download_db_cache_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/guid.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "components/download/database/download_db_conversions.h"
#include "components/download/database/download_db_entry.h"
@@ -37,6 +37,7 @@ DownloadDBEntry CreateDownloadDBEntry() {
download_info.guid = base::GenerateGUID();
static int id = 0;
download_info.id = ++id;
+ download_info.in_progress_info->hash = "abc";
entry.download_info = download_info;
return entry;
}
@@ -53,6 +54,7 @@ void CleanUpInProgressEntry(DownloadDBEntry* entry) {
entry->download_info->in_progress_info->state = DownloadItem::INTERRUPTED;
entry->download_info->in_progress_info->interrupt_reason =
DOWNLOAD_INTERRUPT_REASON_CRASH;
+ entry->download_info->in_progress_info->hash = std::string();
}
} // namespace
@@ -70,8 +72,7 @@ class DownloadDBCacheTest : public testing::Test {
&db_entries_);
db_ = db.get();
auto download_db = std::make_unique<DownloadDBImpl>(
- DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD,
- base::FilePath(FILE_PATH_LITERAL("/test/db/fakepath")), std::move(db));
+ DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD, std::move(db));
db_cache_ = std::make_unique<DownloadDBCache>(std::move(download_db));
db_cache_->SetTimerTaskRunnerForTesting(task_runner_);
}
@@ -108,7 +109,7 @@ class DownloadDBCacheTest : public testing::Test {
leveldb_proto::test::FakeDB<download_pb::DownloadDBEntry>* db_;
std::unique_ptr<DownloadDBCache> db_cache_;
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(DownloadDBCacheTest);
};
@@ -119,7 +120,7 @@ TEST_F(DownloadDBCacheTest, InitializeAndRetrieve) {
db_cache_->Initialize(
base::BindOnce(&DownloadDBCacheTest::InitCallback, base::Unretained(this),
&loaded_entries));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
db_->LoadCallback(true);
ASSERT_EQ(loaded_entries.size(), 2u);
@@ -141,7 +142,7 @@ TEST_F(DownloadDBCacheTest, AddNewEntry) {
db_cache_->Initialize(
base::BindOnce(&DownloadDBCacheTest::InitCallback, base::Unretained(this),
&loaded_entries));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
db_->LoadCallback(true);
ASSERT_EQ(loaded_entries.size(), 2u);
@@ -166,7 +167,7 @@ TEST_F(DownloadDBCacheTest, ModifyExistingEntry) {
db_cache_->Initialize(
base::BindOnce(&DownloadDBCacheTest::InitCallback, base::Unretained(this),
&loaded_entries));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
db_->LoadCallback(true);
ASSERT_EQ(loaded_entries.size(), 2u);
@@ -216,7 +217,7 @@ TEST_F(DownloadDBCacheTest, FilePathChange) {
db_cache_->Initialize(
base::BindOnce(&DownloadDBCacheTest::InitCallback, base::Unretained(this),
&loaded_entries));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
db_->LoadCallback(true);
ASSERT_EQ(loaded_entries.size(), 1u);
ASSERT_EQ(loaded_entries[0].download_info->in_progress_info->current_path,
@@ -245,7 +246,7 @@ TEST_F(DownloadDBCacheTest, RemoveEntry) {
db_cache_->Initialize(
base::BindOnce(&DownloadDBCacheTest::InitCallback, base::Unretained(this),
&loaded_entries));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
db_->LoadCallback(true);
ASSERT_EQ(loaded_entries.size(), 2u);
@@ -272,7 +273,7 @@ TEST_F(DownloadDBCacheTest, RemoveWhileModifyExistingEntry) {
db_cache_->Initialize(
base::BindOnce(&DownloadDBCacheTest::InitCallback, base::Unretained(this),
&loaded_entries));
- db_->InitCallback(true);
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
db_->LoadCallback(true);
ASSERT_EQ(loaded_entries.size(), 2u);
// Let the DBCache to cache the entry first.
diff --git a/chromium/components/download/internal/common/download_file_impl.cc b/chromium/components/download/internal/common/download_file_impl.cc
index f0ebeb52667..ce58672bd20 100644
--- a/chromium/components/download/internal/common/download_file_impl.cc
+++ b/chromium/components/download/internal/common/download_file_impl.cc
@@ -27,8 +27,6 @@
#include "crypto/sha2.h"
#include "mojo/public/c/system/types.h"
#include "net/base/io_buffer.h"
-#include "services/network/public/cpp/features.h"
-#include "services/service_manager/public/cpp/connector.h"
#if defined(OS_ANDROID)
#include "base/android/content_uri_utils.h"
@@ -357,14 +355,14 @@ void DownloadFileImpl::RenameAndAnnotate(
const std::string& client_guid,
const GURL& source_url,
const GURL& referrer_url,
- std::unique_ptr<service_manager::Connector> connector,
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
const RenameCompletionCallback& callback) {
std::unique_ptr<RenameParameters> parameters(new RenameParameters(
ANNOTATE_WITH_SOURCE_INFORMATION, full_path, callback));
parameters->client_guid = client_guid;
parameters->source_url = source_url;
parameters->referrer_url = referrer_url;
- parameters->connector = std::move(connector);
+ parameters->remote_quarantine = std::move(remote_quarantine);
RenameWithRetryInternal(std::move(parameters));
}
@@ -484,7 +482,7 @@ void DownloadFileImpl::RenameWithRetryInternal(
download::features::kPreventDownloadsWithSamePath)) {
file_.AnnotateWithSourceInformation(
parameters->client_guid, parameters->source_url,
- parameters->referrer_url, std::move(parameters->connector),
+ parameters->referrer_url, std::move(parameters->remote_quarantine),
base::BindOnce(&DownloadFileImpl::OnRenameComplete,
weak_factory_.GetWeakPtr(), new_path,
parameters->completion_callback));
@@ -557,6 +555,8 @@ void DownloadFileImpl::Pause() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
is_paused_ = true;
record_stream_bandwidth_ = false;
+ for (auto& stream : source_streams_)
+ stream.second->ClearDataReadyCallback();
}
void DownloadFileImpl::Resume() {
@@ -564,13 +564,10 @@ void DownloadFileImpl::Resume() {
DCHECK(is_paused_);
is_paused_ = false;
- if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
- return;
-
for (auto& stream : source_streams_) {
SourceStream* source_stream = stream.second.get();
if (!source_stream->is_finished()) {
- StreamActive(source_stream, MOJO_RESULT_OK);
+ ActivateStream(source_stream);
}
}
}
@@ -578,8 +575,7 @@ void DownloadFileImpl::Resume() {
void DownloadFileImpl::StreamActive(SourceStream* source_stream,
MojoResult result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
- is_paused_)
+ if (is_paused_)
return;
base::TimeTicks start(base::TimeTicks::Now());
@@ -728,15 +724,19 @@ void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
source_stream->Initialize();
- source_stream->RegisterDataReadyCallback(
- base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(),
- source_stream));
// Truncate |source_stream|'s length if necessary.
for (const auto& received_slice : received_slices_) {
source_stream->TruncateLengthWithWrittenDataBlock(
received_slice.offset, received_slice.received_bytes);
}
num_active_streams_++;
+ ActivateStream(source_stream);
+}
+
+void DownloadFileImpl::ActivateStream(SourceStream* source_stream) {
+ source_stream->RegisterDataReadyCallback(
+ base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(),
+ source_stream));
StreamActive(source_stream, MOJO_RESULT_OK);
}
diff --git a/chromium/components/download/internal/common/download_file_unittest.cc b/chromium/components/download/internal/common/download_file_unittest.cc
index 41fd65fe478..e36751b69f4 100644
--- a/chromium/components/download/internal/common/download_file_unittest.cc
+++ b/chromium/components/download/internal/common/download_file_unittest.cc
@@ -16,7 +16,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -26,7 +26,6 @@
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/mock_input_stream.h"
#include "net/base/net_errors.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -397,7 +396,7 @@ class DownloadFileTest : public testing::Test {
case RENAME_AND_ANNOTATE:
download_file_->RenameAndAnnotate(
full_path, "12345678-ABCD-1234-DCBA-123456789ABC", GURL(), GURL(),
- nullptr, completion_callback);
+ mojo::NullRemote(), completion_callback);
break;
}
}
@@ -501,7 +500,7 @@ class DownloadFileTest : public testing::Test {
closure.Run();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
// DownloadFile::RenameAndAnnotate and DownloadFile::RenameAndUniquify have a
diff --git a/chromium/components/download/internal/common/download_item_impl.cc b/chromium/components/download/internal/common/download_item_impl.cc
index 386660c5ee9..f24ef713bf7 100644
--- a/chromium/components/download/internal/common/download_item_impl.cc
+++ b/chromium/components/download/internal/common/download_item_impl.cc
@@ -412,7 +412,7 @@ DownloadItemImpl::DownloadItemImpl(
const base::FilePath& path,
const GURL& url,
const std::string& mime_type,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle)
+ DownloadJob::CancelRequestCallback cancel_request_callback)
: request_info_(url),
guid_(base::GenerateGUID()),
download_id_(download_id),
@@ -423,9 +423,9 @@ DownloadItemImpl::DownloadItemImpl(
delegate_(delegate),
destination_info_(path, path, 0, false, std::string(), base::Time()),
is_updating_observers_(false) {
- job_ = DownloadJobFactory::CreateJob(this, std::move(request_handle),
- DownloadCreateInfo(), true, nullptr,
- nullptr, nullptr);
+ job_ = DownloadJobFactory::CreateJob(
+ this, std::move(cancel_request_callback), DownloadCreateInfo(), true,
+ URLLoaderFactoryProvider::GetNullPtr(), nullptr);
delegate_->Attach();
Init(true /* actively downloading */, TYPE_SAVE_PAGE_AS);
}
@@ -1415,11 +1415,10 @@ void DownloadItemImpl::Init(bool active,
// We're starting the download.
void DownloadItemImpl::Start(
std::unique_ptr<DownloadFile> file,
- std::unique_ptr<DownloadRequestHandleInterface> req_handle,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadCreateInfo& new_create_info,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter) {
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!download_file_);
DVLOG(20) << __func__ << "() this=" << DebugString(true);
@@ -1427,8 +1426,8 @@ void DownloadItemImpl::Start(
download_file_ = std::move(file);
job_ = DownloadJobFactory::CreateJob(
- this, std::move(req_handle), new_create_info, false,
- std::move(url_loader_factory_getter), url_request_context_getter,
+ this, std::move(cancel_request_callback), new_create_info, false,
+ std::move(url_loader_factory_provider),
delegate_ ? delegate_->GetServiceManagerConnector() : nullptr);
if (job_->IsParallelizable()) {
RecordParallelizableDownloadCount(START_COUNT, IsParallelDownloadEnabled());
@@ -1788,12 +1787,10 @@ void DownloadItemImpl::OnDownloadCompleting() {
}
#endif // defined(OS_ANDROID)
- std::unique_ptr<service_manager::Connector> new_connector;
- service_manager::Connector* connector =
- delegate_->GetServiceManagerConnector();
- if (connector)
- new_connector = connector->Clone();
-
+ mojo::PendingRemote<quarantine::mojom::Quarantine> quarantine;
+ auto quarantine_callback = delegate_->GetQuarantineConnectionCallback();
+ if (quarantine_callback)
+ quarantine_callback.Run(quarantine.InitWithNewPipeAndPassReceiver());
GetDownloadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&DownloadFile::RenameAndAnnotate,
@@ -1802,7 +1799,7 @@ void DownloadItemImpl::OnDownloadCompleting() {
delegate_->GetApplicationClientIdForFileScanning(),
delegate_->IsOffTheRecord() ? GURL() : GetURL(),
delegate_->IsOffTheRecord() ? GURL() : GetReferrerUrl(),
- std::move(new_connector), std::move(callback)));
+ std::move(quarantine), std::move(callback)));
}
void DownloadItemImpl::OnDownloadRenamedToFinalName(
@@ -2036,14 +2033,6 @@ void DownloadItemImpl::InterruptWithPartialState(
job_->Cancel(false);
if (IsCancellation(reason)) {
- if (IsDangerous()) {
- RecordDangerousDownloadDiscard(
- reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
- ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
- : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
- GetDangerType(), GetTargetFilePath());
- }
-
RecordDownloadCountWithSource(CANCELLED_COUNT, download_source_);
if (job_ && job_->IsParallelizable()) {
RecordParallelizableDownloadCount(CANCELLED_COUNT,
@@ -2056,8 +2045,7 @@ void DownloadItemImpl::InterruptWithPartialState(
RecordDownloadInterrupted(reason, GetReceivedBytes(), total_bytes_,
job_ && job_->IsParallelizable(),
- IsParallelDownloadEnabled(), download_source_,
- received_bytes_at_length_mismatch_ > 0);
+ IsParallelDownloadEnabled(), download_source_);
base::TimeDelta time_since_start = base::Time::Now() - GetStartTime();
int resulting_file_size = GetReceivedBytes();
@@ -2300,19 +2288,6 @@ void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
TRACE_EVENT_SCOPE_THREAD, "danger_type",
GetDownloadDangerNames(danger_type).c_str());
}
- // Only record the Malicious UMA stat if it's going from {not malicious} ->
- // {malicious}.
- if ((danger_type_ == DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
- danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
- danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
- danger_type_ == DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT ||
- danger_type_ == DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY) &&
- (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
- danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
- danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
- danger_type == DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED)) {
- RecordMaliciousDownloadClassified(danger_type);
- }
danger_type_ = danger_type;
}
@@ -2420,16 +2395,23 @@ void DownloadItemImpl::ResumeInterruptedDownload(
download_params->set_hash_of_partial_file(GetHash());
download_params->set_hash_state(std::move(hash_state_));
download_params->set_guid(guid_);
- if (!HasStrongValidators() && download_params->offset() > 0 &&
+ if (!HasStrongValidators() &&
base::FeatureList::IsEnabled(
features::kAllowDownloadResumptionWithoutStrongValidators)) {
- download_params->set_use_if_range(false);
- download_params->set_file_offset(download_params->offset());
int64_t validation_length = GetDownloadValidationLengthConfig();
- download_params->set_offset(download_params->offset() > validation_length
- ? download_params->offset() -
- validation_length
- : 0);
+ if (download_params->offset() > validation_length) {
+ // There is enough data for validation, set the file_offset so
+ // DownloadFileImpl will validate the data between offset to
+ // file_offset.
+ download_params->set_use_if_range(false);
+ download_params->set_file_offset(download_params->offset());
+ download_params->set_offset(download_params->offset() -
+ validation_length);
+ } else {
+ // There is not enough data for validation, simply overwrites the
+ // existing data from the beginning.
+ download_params->set_offset(0);
+ }
}
// TODO(xingliu): Read |fetch_error_body| and |request_headers_| from the
@@ -2449,13 +2431,6 @@ void DownloadItemImpl::ResumeInterruptedDownload(
download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER);
download_params->set_follow_cross_origin_redirects(false);
- // If the interruption was caused by content length mismatch, ignore it during
- // resumption.
- if (last_reason_ ==
- DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH) {
- download_params->set_ignore_content_length_mismatch(true);
- }
-
TransitionTo(RESUMING_INTERNAL);
RecordDownloadCountWithSource(source == ResumptionRequestSource::USER
? MANUAL_RESUMPTION_COUNT
diff --git a/chromium/components/download/internal/common/download_item_impl_delegate.cc b/chromium/components/download/internal/common/download_item_impl_delegate.cc
index f5dff20abdc..11a8f2691cc 100644
--- a/chromium/components/download/internal/common/download_item_impl_delegate.cc
+++ b/chromium/components/download/internal/common/download_item_impl_delegate.cc
@@ -108,4 +108,9 @@ DownloadItemImplDelegate::GetServiceManagerConnector() {
return nullptr;
}
+QuarantineConnectionCallback
+DownloadItemImplDelegate::GetQuarantineConnectionCallback() {
+ return base::NullCallback();
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/common/download_item_impl_unittest.cc b/chromium/components/download/internal/common/download_item_impl_unittest.cc
index 93a09d6a13e..7bb6147522d 100644
--- a/chromium/components/download/internal/common/download_item_impl_unittest.cc
+++ b/chromium/components/download/internal/common/download_item_impl_unittest.cc
@@ -19,14 +19,13 @@
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_destination_observer.h"
#include "components/download/public/common/download_file_factory.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item_impl_delegate.h"
-#include "components/download/public/common/download_request_handle_interface.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/mock_download_file.h"
#include "components/download/public/common/mock_download_item.h"
@@ -102,13 +101,6 @@ class MockDelegate : public DownloadItemImplDelegate {
}
};
-class MockRequestHandle : public DownloadRequestHandleInterface {
- public:
- MOCK_METHOD0(PauseRequest, void());
- MOCK_METHOD0(ResumeRequest, void());
- MOCK_METHOD1(CancelRequest, void(bool));
-};
-
class TestDownloadItemObserver : public DownloadItem::Observer {
public:
explicit TestDownloadItemObserver(DownloadItem* item)
@@ -240,8 +232,8 @@ class DownloadItemTest : public testing::Test {
public:
DownloadItemTest()
: task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
+ base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED),
next_download_id_(DownloadItem::kInvalidId + 1) {
create_info_.reset(new DownloadCreateInfo());
create_info_->save_info =
@@ -297,10 +289,8 @@ class DownloadItemTest : public testing::Test {
.WillRepeatedly(ReturnRefOfCopy(base::FilePath()));
}
- std::unique_ptr<MockRequestHandle> request_handle =
- std::make_unique<NiceMock<MockRequestHandle>>();
- item->Start(std::move(download_file), std::move(request_handle),
- *create_info_, nullptr, nullptr);
+ item->Start(std::move(download_file), base::DoNothing(), *create_info_,
+ URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
// So that we don't have a function writing to a stack variable
@@ -383,13 +373,18 @@ class DownloadItemTest : public testing::Test {
DownloadCreateInfo* create_info() { return create_info_.get(); }
- base::test::ScopedTaskEnvironment task_environment_;
+ void CancelRequest(bool user_cancel) { canceled_ = true; }
+
+ bool canceled() { return canceled_; }
+
+ base::test::TaskEnvironment task_environment_;
private:
StrictMock<MockDelegate> mock_delegate_;
std::map<DownloadItem*, std::unique_ptr<DownloadItem>> allocated_downloads_;
std::unique_ptr<DownloadCreateInfo> create_info_;
uint32_t next_download_id_ = DownloadItem::kInvalidId + 1;
+ bool canceled_ = false;
};
// Tests to ensure calls that change a DownloadItem generate an update
@@ -577,13 +572,11 @@ TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
TestDownloadItemObserver observer(item);
MockDownloadFile* mock_download_file(new MockDownloadFile);
std::unique_ptr<DownloadFile> download_file(mock_download_file);
- std::unique_ptr<DownloadRequestHandleInterface> request_handle(
- new NiceMock<MockRequestHandle>);
EXPECT_CALL(*mock_download_file, Initialize(_, _, _, _));
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
- item->Start(std::move(download_file), std::move(request_handle),
- *create_info(), nullptr, nullptr);
+ item->Start(std::move(download_file), base::DoNothing(), *create_info(),
+ URLLoaderFactoryProvider::GetNullPtr());
item->Pause();
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
@@ -804,7 +797,6 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
TestDownloadItemObserver observer(item);
MockDownloadFile* mock_download_file_ref = nullptr;
std::unique_ptr<MockDownloadFile> mock_download_file;
- std::unique_ptr<MockRequestHandle> mock_request_handle;
DownloadItemImplDelegate::DownloadTargetCallback callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
@@ -823,15 +815,14 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
mock_download_file = std::make_unique<NiceMock<MockDownloadFile>>();
mock_download_file_ref = mock_download_file.get();
- mock_request_handle = std::make_unique<NiceMock<MockRequestHandle>>();
ON_CALL(*mock_download_file_ref, FullPath())
.WillByDefault(ReturnRefOfCopy(base::FilePath()));
// Copied key parts of DoIntermediateRename & CallDownloadItemStart
// to allow for holding onto the request handle.
- item->Start(std::move(mock_download_file), std::move(mock_request_handle),
- *create_info(), nullptr, nullptr);
+ item->Start(std::move(mock_download_file), base::DoNothing(),
+ *create_info(), URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
base::FilePath target_path(kDummyTargetPath);
@@ -1161,11 +1152,9 @@ TEST_F(DownloadItemTest, Start) {
std::unique_ptr<DownloadFile> download_file(mock_download_file);
DownloadItemImpl* item = CreateDownloadItem();
EXPECT_CALL(*mock_download_file, Initialize(_, _, _, _));
- std::unique_ptr<DownloadRequestHandleInterface> request_handle(
- new NiceMock<MockRequestHandle>);
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
- item->Start(std::move(download_file), std::move(request_handle),
- *create_info(), nullptr, nullptr);
+ item->Start(std::move(download_file), base::DoNothing(), *create_info(),
+ URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
@@ -1176,12 +1165,9 @@ TEST_F(DownloadItemTest, Start) {
TEST_F(DownloadItemTest, InitDownloadFileFails) {
DownloadItemImpl* item = CreateDownloadItem();
std::unique_ptr<MockDownloadFile> file = std::make_unique<MockDownloadFile>();
- std::unique_ptr<MockRequestHandle> request_handle =
- std::make_unique<MockRequestHandle>();
base::HistogramTester histogram_tester;
EXPECT_CALL(*file, Cancel());
- EXPECT_CALL(*request_handle, CancelRequest(_));
EXPECT_CALL(*file, Initialize(_, _, _, _))
.WillOnce(ScheduleCallbackWithParams(
DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED, 0,
@@ -1191,8 +1177,10 @@ TEST_F(DownloadItemTest, InitDownloadFileFails) {
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
.WillOnce(SaveArg<1>(&download_target_callback));
- item->Start(std::move(file), std::move(request_handle), *create_info(),
- nullptr, nullptr);
+ item->Start(
+ std::move(file),
+ base::Bind(&DownloadItemTest::CancelRequest, base::Unretained(this)),
+ *create_info(), URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
download_target_callback.Run(base::FilePath(kDummyTargetPath),
@@ -1207,6 +1195,7 @@ TEST_F(DownloadItemTest, InitDownloadFileFails) {
item->GetLastReason());
EXPECT_FALSE(item->GetTargetFilePath().empty());
EXPECT_TRUE(item->GetFullPath().empty());
+ EXPECT_TRUE(canceled());
histogram_tester.ExpectBucketCount(
"Download.InterruptedReason",
ToHistogramSample<DownloadInterruptReason>(
@@ -1224,12 +1213,11 @@ TEST_F(DownloadItemTest, StartFailedDownload) {
// DownloadFile and DownloadRequestHandleInterface objects aren't created for
// failed downloads.
std::unique_ptr<DownloadFile> null_download_file;
- std::unique_ptr<DownloadRequestHandleInterface> null_request_handle;
DownloadItemImplDelegate::DownloadTargetCallback download_target_callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
.WillOnce(SaveArg<1>(&download_target_callback));
- item->Start(std::move(null_download_file), std::move(null_request_handle),
- *create_info(), nullptr, nullptr);
+ item->Start(std::move(null_download_file), base::DoNothing(), *create_info(),
+ URLLoaderFactoryProvider::GetNullPtr());
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
task_environment_.RunUntilIdle();
@@ -2266,8 +2254,7 @@ class DownloadItemDestinationUpdateRaceTest
public:
DownloadItemDestinationUpdateRaceTest()
: item_(CreateDownloadItem()),
- file_(new ::testing::StrictMock<MockDownloadFile>()),
- request_handle_(new ::testing::StrictMock<MockRequestHandle>()) {
+ file_(new ::testing::StrictMock<MockDownloadFile>()) {
DCHECK_EQ(GetParam().size(), static_cast<unsigned>(kEventCount));
}
@@ -2298,7 +2285,6 @@ class DownloadItemDestinationUpdateRaceTest
DownloadItemImpl* item_;
std::unique_ptr<MockDownloadFile> file_;
- std::unique_ptr<MockRequestHandle> request_handle_;
base::queue<base::Closure> successful_update_events_;
base::queue<base::Closure> failing_update_events_;
@@ -2320,13 +2306,14 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, DownloadCancelledByUser) {
// Expect that the download file and the request will be cancelled as a
// result.
EXPECT_CALL(*file_, Cancel());
- EXPECT_CALL(*request_handle_, CancelRequest(_));
DownloadFile::InitializeCallback initialize_callback;
EXPECT_CALL(*file_, Initialize(_, _, _, _))
.WillOnce(SaveArg<0>(&initialize_callback));
- item_->Start(std::move(file_), std::move(request_handle_), *create_info(),
- nullptr, nullptr);
+ item_->Start(
+ std::move(file_),
+ base::Bind(&DownloadItemTest::CancelRequest, base::Unretained(this)),
+ *create_info(), URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
base::WeakPtr<DownloadDestinationObserver> destination_observer =
@@ -2351,6 +2338,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, DownloadCancelledByUser) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, base::FilePath(),
DOWNLOAD_INTERRUPT_REASON_NONE);
EXPECT_EQ(DownloadItem::CANCELLED, item_->GetState());
+ EXPECT_TRUE(canceled());
task_environment_.RunUntilIdle();
}
@@ -2359,7 +2347,6 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
// Expect that the download file and the request will be cancelled as a
// result.
EXPECT_CALL(*file_, Cancel());
- EXPECT_CALL(*request_handle_, CancelRequest(_));
// Intermediate rename loop is not used immediately, but let's set up the
// DownloadFile expectations since we are about to transfer its ownership to
@@ -2372,8 +2359,10 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
EXPECT_CALL(*file_, Initialize(_, _, _, _))
.WillOnce(SaveArg<0>(&initialize_callback));
- item_->Start(std::move(file_), std::move(request_handle_), *create_info(),
- nullptr, nullptr);
+ item_->Start(
+ std::move(file_),
+ base::Bind(&DownloadItemTest::CancelRequest, base::Unretained(this)),
+ *create_info(), URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
base::WeakPtr<DownloadDestinationObserver> destination_observer =
@@ -2409,6 +2398,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::INTERRUPTED, item_->GetState());
+ EXPECT_TRUE(canceled());
}
// Run through the DII workflow. Download file initialization, target
@@ -2419,7 +2409,6 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
// DownloadFile will Detach()). It depends on the list of observations that
// are given to us.
EXPECT_CALL(*file_, Cancel()).Times(::testing::AnyNumber());
- EXPECT_CALL(*request_handle_, CancelRequest(_)).Times(::testing::AnyNumber());
EXPECT_CALL(*file_, Detach()).Times(::testing::AnyNumber());
EXPECT_CALL(*file_, FullPath())
@@ -2436,8 +2425,8 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
EXPECT_CALL(*file_, Initialize(_, _, _, _))
.WillOnce(SaveArg<0>(&initialize_callback));
- item_->Start(std::move(file_), std::move(request_handle_), *create_info(),
- nullptr, nullptr);
+ item_->Start(std::move(file_), base::DoNothing(), *create_info(),
+ URLLoaderFactoryProvider::GetNullPtr());
task_environment_.RunUntilIdle();
base::WeakPtr<DownloadDestinationObserver> destination_observer =
diff --git a/chromium/components/download/internal/common/download_job.cc b/chromium/components/download/internal/common/download_job.cc
index f69b10805a7..04861abe4a3 100644
--- a/chromium/components/download/internal/common/download_job.cc
+++ b/chromium/components/download/internal/common/download_job.cc
@@ -11,18 +11,17 @@
namespace download {
-DownloadJob::DownloadJob(
- DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle)
+DownloadJob::DownloadJob(DownloadItem* download_item,
+ CancelRequestCallback cancel_request_callback)
: download_item_(download_item),
- request_handle_(std::move(request_handle)),
+ cancel_request_callback_(std::move(cancel_request_callback)),
is_paused_(false) {}
DownloadJob::~DownloadJob() = default;
void DownloadJob::Cancel(bool user_cancel) {
- if (request_handle_)
- request_handle_->CancelRequest(user_cancel);
+ if (cancel_request_callback_)
+ std::move(cancel_request_callback_).Run(user_cancel);
}
void DownloadJob::Pause() {
@@ -36,8 +35,6 @@ void DownloadJob::Pause() {
// Safe because we control download file lifetime.
base::Unretained(download_file)));
}
- if (request_handle_)
- request_handle_->PauseRequest();
}
void DownloadJob::Resume(bool resume_request) {
@@ -53,9 +50,6 @@ void DownloadJob::Resume(bool resume_request) {
// Safe because we control download file lifetime.
base::Unretained(download_file)));
}
-
- if (request_handle_)
- request_handle_->ResumeRequest();
}
void DownloadJob::Start(DownloadFile* download_file_,
diff --git a/chromium/components/download/internal/common/download_job_factory.cc b/chromium/components/download/internal/common/download_job_factory.cc
index db41162941f..cd6274cac86 100644
--- a/chromium/components/download/internal/common/download_job_factory.cc
+++ b/chromium/components/download/internal/common/download_job_factory.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/memory/weak_ptr.h"
#include "components/download/internal/common/download_job_impl.h"
#include "components/download/internal/common/parallel_download_job.h"
#include "components/download/internal/common/parallel_download_utils.h"
@@ -13,7 +14,6 @@
#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_stats.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "net/url_request/url_request_context_getter.h"
namespace download {
@@ -160,30 +160,28 @@ bool IsParallelizableDownload(const DownloadCreateInfo& create_info,
// static
std::unique_ptr<DownloadJob> DownloadJobFactory::CreateJob(
DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> req_handle,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadCreateInfo& create_info,
bool is_save_package_download,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
service_manager::Connector* connector) {
if (is_save_package_download) {
- return std::make_unique<SavePackageDownloadJob>(download_item,
- std::move(req_handle));
+ return std::make_unique<SavePackageDownloadJob>(
+ download_item, std::move(cancel_request_callback));
}
bool is_parallelizable = IsParallelizableDownload(create_info, download_item);
// Build parallel download job.
if (IsParallelDownloadEnabled() && is_parallelizable) {
return std::make_unique<ParallelDownloadJob>(
- download_item, std::move(req_handle), create_info,
- std::move(url_loader_factory_getter), url_request_context_getter,
- connector);
+ download_item, std::move(cancel_request_callback), create_info,
+ std::move(url_loader_factory_provider), connector);
}
// An ordinary download job.
- return std::make_unique<DownloadJobImpl>(download_item, std::move(req_handle),
- is_parallelizable);
+ return std::make_unique<DownloadJobImpl>(
+ download_item, std::move(cancel_request_callback), is_parallelizable);
}
} // namespace download
diff --git a/chromium/components/download/internal/common/download_job_impl.cc b/chromium/components/download/internal/common/download_job_impl.cc
index e653a87c652..cf53b0c9428 100644
--- a/chromium/components/download/internal/common/download_job_impl.cc
+++ b/chromium/components/download/internal/common/download_job_impl.cc
@@ -6,11 +6,10 @@
namespace download {
-DownloadJobImpl::DownloadJobImpl(
- DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle,
- bool is_parallizable)
- : DownloadJob(download_item, std::move(request_handle)),
+DownloadJobImpl::DownloadJobImpl(DownloadItem* download_item,
+ CancelRequestCallback cancel_request_callback,
+ bool is_parallizable)
+ : DownloadJob(download_item, std::move(cancel_request_callback)),
is_parallizable_(is_parallizable) {}
DownloadJobImpl::~DownloadJobImpl() = default;
diff --git a/chromium/components/download/internal/common/download_job_impl.h b/chromium/components/download/internal/common/download_job_impl.h
index 5be902d2755..a78ead6b538 100644
--- a/chromium/components/download/internal/common/download_job_impl.h
+++ b/chromium/components/download/internal/common/download_job_impl.h
@@ -14,10 +14,9 @@ class DownloadItem;
class COMPONENTS_DOWNLOAD_EXPORT DownloadJobImpl : public DownloadJob {
public:
- DownloadJobImpl(
- DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle,
- bool is_parallizable);
+ DownloadJobImpl(DownloadItem* download_item,
+ CancelRequestCallback cancel_request_callback,
+ bool is_parallizable);
~DownloadJobImpl() override;
// DownloadJob implementation.
diff --git a/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc b/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc
index 1b6ccde7434..5c4e3e169aa 100644
--- a/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc
+++ b/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc
@@ -16,7 +16,7 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -75,7 +75,7 @@ class DownloadPathReservationTrackerTest : public testing::Test {
base::ScopedTempDir test_download_dir_;
base::FilePath default_download_path_;
base::FilePath fallback_directory_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
private:
void TestReservedPathCallback(base::FilePath* return_path,
@@ -138,7 +138,7 @@ bool DownloadPathReservationTrackerTest::IsPathInUse(
}
void DownloadPathReservationTrackerTest::RunUntilIdle() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void DownloadPathReservationTrackerTest::CallGetReservedPath(
@@ -157,7 +157,7 @@ void DownloadPathReservationTrackerTest::CallGetReservedPath(
create_directory, conflict_action,
base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback,
weak_ptr_factory.GetWeakPtr(), return_path, return_result));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void DownloadPathReservationTrackerTest::TestReservedPathCallback(
diff --git a/chromium/components/download/internal/common/download_response_handler.cc b/chromium/components/download/internal/common/download_response_handler.cc
index 1d5e3942653..e2e30819117 100644
--- a/chromium/components/download/internal/common/download_response_handler.cc
+++ b/chromium/components/download/internal/common/download_response_handler.cc
@@ -58,7 +58,6 @@ DownloadResponseHandler::DownloadResponseHandler(
const DownloadUrlParameters::RequestHeadersType& request_headers,
const std::string& request_origin,
DownloadSource download_source,
- bool ignore_content_length_mismatch,
std::vector<GURL> url_chain,
bool is_background_mode)
: delegate_(delegate),
@@ -75,7 +74,7 @@ DownloadResponseHandler::DownloadResponseHandler(
request_headers_(request_headers),
request_origin_(request_origin),
download_source_(download_source),
- ignore_content_length_mismatch_(ignore_content_length_mismatch),
+ has_strong_validators_(false),
is_partial_request_(save_info_->offset > 0),
completed_(false),
abort_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
@@ -90,24 +89,16 @@ DownloadResponseHandler::DownloadResponseHandler(
DownloadResponseHandler::~DownloadResponseHandler() = default;
void DownloadResponseHandler::OnReceiveResponse(
- const network::ResourceResponseHead& head) {
+ network::mojom::URLResponseHeadPtr head) {
create_info_ = CreateDownloadCreateInfo(head);
- cert_status_ = head.cert_status;
+ cert_status_ = head->cert_status;
// TODO(xingliu): Do not use http cache.
// Sets page transition type correctly and call
// |RecordDownloadSourcePageTransitionType| here.
- if (head.headers) {
- // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons:
- // 1. Server or proxy closes the connection too early.
- // 2. The content-length header is wrong.
- // If the download has strong validators, we can interrupt the download
- // and let it resume automatically. Otherwise, resuming the download will
- // cause it to restart and the download may never complete if the error was
- // caused by reason 2. As a result, downloads without strong validators are
- // treated as completed here.
- ignore_content_length_mismatch_ |= !head.headers->HasStrongValidators();
- RecordDownloadHttpResponseCode(head.headers->response_code(),
+ if (head->headers) {
+ has_strong_validators_ = head->headers->HasStrongValidators();
+ RecordDownloadHttpResponseCode(head->headers->response_code(),
is_background_mode_);
RecordDownloadContentDisposition(create_info_->content_disposition);
}
@@ -166,7 +157,7 @@ DownloadResponseHandler::CreateDownloadCreateInfo(
void DownloadResponseHandler::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& head) {
+ network::mojom::URLResponseHeadPtr head) {
if (!follow_cross_origin_redirects_ &&
!first_origin_.IsSameOriginWith(
url::Origin::Create(redirect_info.new_url))) {
@@ -234,9 +225,8 @@ void DownloadResponseHandler::OnComplete(
completed_ = true;
DownloadInterruptReason reason = HandleRequestCompletionStatus(
- static_cast<net::Error>(status.error_code),
- ignore_content_length_mismatch_, cert_status_, is_partial_request_,
- abort_reason_);
+ static_cast<net::Error>(status.error_code), has_strong_validators_,
+ cert_status_, is_partial_request_, abort_reason_);
if (client_ptr_) {
client_ptr_->OnStreamCompleted(
diff --git a/chromium/components/download/internal/common/download_stats.cc b/chromium/components/download/internal/common/download_stats.cc
index 1060096e1d8..d12e8625626 100644
--- a/chromium/components/download/internal/common/download_stats.cc
+++ b/chromium/components/download/internal/common/download_stats.cc
@@ -613,19 +613,13 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason,
int64_t total,
bool is_parallelizable,
bool is_parallel_download_enabled,
- DownloadSource download_source,
- bool post_content_length_mismatch) {
+ DownloadSource download_source) {
RecordDownloadCountWithSource(INTERRUPTED_COUNT, download_source);
if (is_parallelizable) {
RecordParallelizableDownloadCount(INTERRUPTED_COUNT,
is_parallel_download_enabled);
}
- if (post_content_length_mismatch) {
- base::UmaHistogramSparse(
- "Download.ResumptionAfterContentLengthMismatch.Reason", reason);
- }
-
std::vector<base::HistogramBase::Sample> samples =
base::CustomHistogram::ArrayToCustomEnumRanges(kAllInterruptReasonCodes);
UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedReason", reason,
@@ -674,11 +668,6 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason,
}
}
-void RecordMaliciousDownloadClassified(DownloadDangerType danger_type) {
- UMA_HISTOGRAM_ENUMERATION("Download.MaliciousDownloadClassified", danger_type,
- DOWNLOAD_DANGER_TYPE_MAX);
-}
-
void RecordDangerousDownloadAccept(DownloadDangerType danger_type,
const base::FilePath& file_path) {
UMA_HISTOGRAM_ENUMERATION("Download.DangerousDownloadValidated", danger_type,
@@ -690,31 +679,6 @@ void RecordDangerousDownloadAccept(DownloadDangerType danger_type,
}
}
-void RecordDangerousDownloadDiscard(DownloadDiscardReason reason,
- DownloadDangerType danger_type,
- const base::FilePath& file_path) {
- switch (reason) {
- case DOWNLOAD_DISCARD_DUE_TO_USER_ACTION:
- UMA_HISTOGRAM_ENUMERATION("Download.UserDiscard", danger_type,
- DOWNLOAD_DANGER_TYPE_MAX);
- if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
- base::UmaHistogramSparse("Download.DangerousFile.UserDiscard",
- GetDangerousFileType(file_path));
- }
- break;
- case DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN:
- UMA_HISTOGRAM_ENUMERATION("Download.Discard", danger_type,
- DOWNLOAD_DANGER_TYPE_MAX);
- if (danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) {
- base::UmaHistogramSparse("Download.DangerousFile.Discard",
- GetDangerousFileType(file_path));
- }
- break;
- default:
- NOTREACHED();
- }
-}
-
namespace {
int GetMimeTypeMatch(const std::string& mime_type_string,
@@ -1235,14 +1199,6 @@ void RecordDownloadValidationMetrics(DownloadMetricsCallsite callsite,
DownloadContent::MAX);
}
-void RecordDownloadConnectionSecurity(const GURL& download_url,
- const std::vector<GURL>& url_chain) {
- UMA_HISTOGRAM_ENUMERATION(
- "Download.TargetConnectionSecurity",
- CheckDownloadConnectionSecurity(download_url, url_chain),
- DOWNLOAD_CONNECTION_SECURITY_MAX);
-}
-
void RecordDownloadContentTypeSecurity(
const GURL& download_url,
const std::vector<GURL>& url_chain,
diff --git a/chromium/components/download/internal/common/download_ukm_helper_unittest.cc b/chromium/components/download/internal/common/download_ukm_helper_unittest.cc
index a3c3fed2de8..a2f75e7f13a 100644
--- a/chromium/components/download/internal/common/download_ukm_helper_unittest.cc
+++ b/chromium/components/download/internal/common/download_ukm_helper_unittest.cc
@@ -5,7 +5,7 @@
#include "components/download/public/common/download_ukm_helper.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -45,7 +45,7 @@ class DownloadUkmHelperTest : public testing::Test {
protected:
int download_id_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_recorder_;
DISALLOW_COPY_AND_ASSIGN(DownloadUkmHelperTest);
diff --git a/chromium/components/download/internal/common/download_url_loader_factory_getter.cc b/chromium/components/download/internal/common/download_url_loader_factory_getter.cc
deleted file mode 100644
index 4f3b2823b7d..00000000000
--- a/chromium/components/download/internal/common/download_url_loader_factory_getter.cc
+++ /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.
-
-#include "components/download/public/common/download_url_loader_factory_getter.h"
-
-#include "components/download/public/common/download_task_runner.h"
-
-namespace download {
-
-DownloadURLLoaderFactoryGetter::DownloadURLLoaderFactoryGetter() = default;
-
-DownloadURLLoaderFactoryGetter::~DownloadURLLoaderFactoryGetter() = default;
-
-void DownloadURLLoaderFactoryGetter::DeleteOnCorrectThread() const {
- if (GetIOTaskRunner() && !GetIOTaskRunner()->BelongsToCurrentThread()) {
- GetIOTaskRunner()->DeleteSoon(FROM_HERE, this);
- return;
- }
- delete this;
-}
-
-} // namespace download
diff --git a/chromium/components/download/internal/common/download_url_loader_factory_getter_impl.cc b/chromium/components/download/internal/common/download_url_loader_factory_getter_impl.cc
deleted file mode 100644
index 83c5b9390d2..00000000000
--- a/chromium/components/download/internal/common/download_url_loader_factory_getter_impl.cc
+++ /dev/null
@@ -1,25 +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 "components/download/public/common/download_url_loader_factory_getter_impl.h"
-
-namespace download {
-
-DownloadURLLoaderFactoryGetterImpl::DownloadURLLoaderFactoryGetterImpl(
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory)
- : url_loader_factory_info_(std::move(url_loader_factory)) {}
-
-DownloadURLLoaderFactoryGetterImpl::~DownloadURLLoaderFactoryGetterImpl() =
- default;
-
-scoped_refptr<network::SharedURLLoaderFactory>
-DownloadURLLoaderFactoryGetterImpl::GetURLLoaderFactory() {
- if (!url_loader_factory_) {
- url_loader_factory_ = network::SharedURLLoaderFactory::Create(
- std::move(url_loader_factory_info_));
- }
- return url_loader_factory_;
-}
-
-} // namespace download
diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc
index b1c816f2dee..d9bcc7b5ba0 100644
--- a/chromium/components/download/internal/common/download_utils.cc
+++ b/chromium/components/download/internal/common/download_utils.cc
@@ -53,12 +53,23 @@ const uint32_t DownloadItem::kInvalidId = 0;
DownloadInterruptReason HandleRequestCompletionStatus(
net::Error error_code,
- bool ignore_content_length_mismatch,
+ bool has_strong_validators,
net::CertStatus cert_status,
bool is_partial_request,
DownloadInterruptReason abort_reason) {
+ // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons:
+ // 1. Server or proxy closes the connection too early.
+ // 2. The content-length header is wrong.
+ // If the download has strong validators, we can interrupt the download
+ // and let it resume automatically. Otherwise, resuming the download will
+ // cause it to restart and the download may never complete if the error was
+ // caused by reason 2. As a result, downloads without strong validators are
+ // treated as completed here.
+ // TODO(qinmin): check the metrics from downloads with strong validators,
+ // and decide whether we should interrupt downloads without strong validators
+ // rather than complete them.
if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH &&
- ignore_content_length_mismatch) {
+ !has_strong_validators) {
error_code = net::OK;
RecordDownloadCount(COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT);
}
@@ -253,7 +264,6 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
request->site_for_cookies = params->url();
request->referrer = params->referrer();
request->referrer_policy = params->referrer_policy();
- request->allow_download = true;
request->is_main_frame = true;
// Downloads should be treated as navigations from Fetch spec perspective.
diff --git a/chromium/components/download/internal/common/download_worker.cc b/chromium/components/download/internal/common/download_worker.cc
index cd55965b6a7..b1e9792c36c 100644
--- a/chromium/components/download/internal/common/download_worker.cc
+++ b/chromium/components/download/internal/common/download_worker.cc
@@ -9,12 +9,9 @@
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_task_runner.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/input_stream.h"
#include "components/download/public/common/url_download_handler_factory.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -52,16 +49,16 @@ class CompletedInputStream : public InputStream {
void CreateUrlDownloadHandler(
std::unique_ptr<DownloadUrlParameters> params,
base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ URLLoaderFactoryProvider* url_loader_factory_provider,
const URLSecurityPolicy& url_security_policy,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
auto downloader = UrlDownloadHandlerFactory::Create(
- std::move(params), delegate, std::move(url_loader_factory_getter),
- url_security_policy, std::move(url_request_context_getter),
- std::move(connector), task_runner);
+ std::move(params), delegate,
+ url_loader_factory_provider
+ ? url_loader_factory_provider->GetURLLoaderFactory()
+ : nullptr,
+ url_security_policy, std::move(connector), task_runner);
task_runner->PostTask(
FROM_HERE,
base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
@@ -78,7 +75,6 @@ DownloadWorker::DownloadWorker(DownloadWorker::Delegate* delegate,
length_(length),
is_paused_(false),
is_canceled_(false),
- is_user_cancel_(false),
url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)) {
DCHECK(delegate_);
}
@@ -87,44 +83,38 @@ DownloadWorker::~DownloadWorker() = default;
void DownloadWorker::SendRequest(
std::unique_ptr<DownloadUrlParameters> params,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ URLLoaderFactoryProvider* url_loader_factory_provider,
service_manager::Connector* connector) {
GetIOTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
weak_factory_.GetWeakPtr(),
- std::move(url_loader_factory_getter),
+ // This is safe because URLLoaderFactoryProvider
+ // deleter is called on the same task sequence.
+ base::Unretained(url_loader_factory_provider),
base::BindRepeating(&IsURLSafe),
- std::move(url_request_context_getter),
connector ? connector->Clone() : nullptr,
base::ThreadTaskRunnerHandle::Get()));
}
void DownloadWorker::Pause() {
is_paused_ = true;
- if (request_handle_)
- request_handle_->PauseRequest();
}
void DownloadWorker::Resume() {
is_paused_ = false;
- if (request_handle_)
- request_handle_->ResumeRequest();
}
void DownloadWorker::Cancel(bool user_cancel) {
is_canceled_ = true;
- is_user_cancel_ = user_cancel;
- if (request_handle_)
- request_handle_->CancelRequest(user_cancel);
+ url_download_handler_.reset();
}
void DownloadWorker::OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ UrlDownloadHandler* downloader,
const DownloadUrlParameters::OnStartedCallback& callback) {
// |callback| is not used in subsequent requests.
DCHECK(callback.is_null());
@@ -133,7 +123,7 @@ void DownloadWorker::OnUrlDownloadStarted(
if (is_canceled_) {
VLOG(kWorkerVerboseLevel)
<< "Byte stream arrived after user cancel the request.";
- create_info->request_handle->CancelRequest(is_user_cancel_);
+ url_download_handler_.reset();
return;
}
@@ -145,8 +135,6 @@ void DownloadWorker::OnUrlDownloadStarted(
input_stream.reset(new CompletedInputStream(create_info->result));
}
- request_handle_ = std::move(create_info->request_handle);
-
// Pause the stream if user paused, still push the stream reader to the sink.
if (is_paused_) {
VLOG(kWorkerVerboseLevel)
diff --git a/chromium/components/download/internal/common/download_worker.h b/chromium/components/download/internal/common/download_worker.h
index 26b57219725..d560f0da584 100644
--- a/chromium/components/download/internal/common/download_worker.h
+++ b/chromium/components/download/internal/common/download_worker.h
@@ -11,20 +11,14 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "components/download/public/common/download_export.h"
-#include "components/download/public/common/download_request_handle_interface.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/url_download_handler.h"
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
-
namespace service_manager {
class Connector;
} // namespace service_manager
namespace download {
-class DownloadURLLoaderFactoryGetter;
// Helper class used to send subsequent range requests to fetch slices of the
// file after handling response of the original non-range request.
@@ -53,12 +47,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
int64_t length() const { return length_; }
// Send network request to ask for a download.
- void SendRequest(
- std::unique_ptr<DownloadUrlParameters> params,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
- service_manager::Connector* connector);
+ void SendRequest(std::unique_ptr<DownloadUrlParameters> params,
+ URLLoaderFactoryProvider* url_loader_factory_provider,
+ service_manager::Connector* connector);
// Download operations.
void Pause();
@@ -70,8 +61,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
void OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ UrlDownloadHandler* downloader,
const DownloadUrlParameters::OnStartedCallback& callback) override;
void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
void OnUrlDownloadHandlerCreated(
@@ -88,10 +80,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
// States of the worker.
bool is_paused_;
bool is_canceled_;
- bool is_user_cancel_;
-
- // Used to control the network request. Live on UI thread.
- std::unique_ptr<DownloadRequestHandleInterface> request_handle_;
// Used to handle the url request. Live and die on IO thread.
UrlDownloadHandler::UniqueUrlDownloadHandlerPtr url_download_handler_;
diff --git a/chromium/components/download/internal/common/in_progress_download_manager.cc b/chromium/components/download/internal/common/in_progress_download_manager.cc
index de9122bcedc..694651a8ee3 100644
--- a/chromium/components/download/internal/common/in_progress_download_manager.cc
+++ b/chromium/components/download/internal/common/in_progress_download_manager.cc
@@ -20,11 +20,10 @@
#include "components/download/public/common/download_start_observer.h"
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_task_runner.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/input_stream.h"
-#include "services/network/public/cpp/features.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -82,7 +81,8 @@ void OnUrlDownloadHandlerCreated(
void BeginResourceDownload(
std::unique_ptr<DownloadUrlParameters> params,
std::unique_ptr<network::ResourceRequest> request,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_info,
const URLSecurityPolicy& url_security_policy,
bool is_new_download,
base::WeakPtr<InProgressDownloadManager> download_manager,
@@ -96,9 +96,11 @@ void BeginResourceDownload(
UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
ResourceDownloader::BeginDownload(
download_manager, std::move(params), std::move(request),
- std::move(url_loader_factory_getter), url_security_policy, site_url,
- tab_url, tab_referrer_url, is_new_download, false,
- std::move(connector), is_background_mode, main_task_runner)
+ network::SharedURLLoaderFactory::Create(
+ std::move(url_loader_factory_info)),
+ url_security_policy, site_url, tab_url, tab_referrer_url,
+ is_new_download, false, std::move(connector), is_background_mode,
+ main_task_runner)
.release(),
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
@@ -119,7 +121,8 @@ void CreateDownloadHandlerForNavigation(
scoped_refptr<network::ResourceResponse> response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_info,
const URLSecurityPolicy& url_security_policy,
std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) {
@@ -131,8 +134,9 @@ void CreateDownloadHandlerForNavigation(
std::move(url_chain), std::move(cert_status),
std::move(response_head), std::move(response_body),
std::move(url_loader_client_endpoints),
- std::move(url_loader_factory_getter), url_security_policy,
- std::move(connector), main_task_runner)
+ network::SharedURLLoaderFactory::Create(
+ std::move(url_loader_factory_info)),
+ url_security_policy, std::move(connector), main_task_runner)
.release(),
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
@@ -193,15 +197,10 @@ InProgressDownloadManager::Delegate::GetDefaultDownloadDirectory() {
return base::FilePath();
}
-net::URLRequestContextGetter*
-InProgressDownloadManager::Delegate::GetURLRequestContextGetter(
- const DownloadCreateInfo& download_create_info) {
- return nullptr;
-}
-
InProgressDownloadManager::InProgressDownloadManager(
Delegate* delegate,
const base::FilePath& in_progress_db_dir,
+ leveldb_proto::ProtoDatabaseProvider* db_provider,
const IsOriginSecureCallback& is_origin_secure_cb,
const URLSecurityPolicy& url_security_policy,
service_manager::Connector* connector)
@@ -212,7 +211,7 @@ InProgressDownloadManager::InProgressDownloadManager(
url_security_policy_(url_security_policy),
use_empty_db_(in_progress_db_dir.empty()),
connector_(connector) {
- Initialize(in_progress_db_dir);
+ Initialize(in_progress_db_dir, db_provider);
}
InProgressDownloadManager::~InProgressDownloadManager() = default;
@@ -220,10 +219,15 @@ InProgressDownloadManager::~InProgressDownloadManager() = default;
void InProgressDownloadManager::OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> download_create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ UrlDownloadHandler* downloader,
const DownloadUrlParameters::OnStartedCallback& callback) {
StartDownload(std::move(download_create_info), std::move(input_stream),
- std::move(url_loader_factory_getter), callback);
+ std::move(url_loader_factory_provider),
+ base::BindOnce(&InProgressDownloadManager::CancelUrlDownload,
+ weak_factory_.GetWeakPtr(), downloader),
+ callback);
}
void InProgressDownloadManager::OnUrlDownloadStopped(
@@ -250,7 +254,7 @@ void InProgressDownloadManager::DownloadUrl(
// Start the new download, the download should be saved to the file path
// specifcied in the |params|.
- BeginDownload(std::move(params), url_loader_factory_getter_,
+ BeginDownload(std::move(params), url_loader_factory_->Clone(),
true /* is_new_download */, GURL() /* site_url */,
GURL() /* tab_url */, GURL() /* tab_referral_url */);
}
@@ -259,7 +263,7 @@ bool InProgressDownloadManager::CanDownload(DownloadUrlParameters* params) {
if (!params->is_transient())
return false;
- if (!url_loader_factory_getter_)
+ if (!url_loader_factory_)
return false;
if (params->require_safety_checks())
@@ -288,7 +292,8 @@ DownloadItem* InProgressDownloadManager::GetDownloadByGuid(
void InProgressDownloadManager::BeginDownload(
std::unique_ptr<DownloadUrlParameters> params,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_info,
bool is_new_download,
const GURL& site_url,
const GURL& tab_url,
@@ -299,7 +304,7 @@ void InProgressDownloadManager::BeginDownload(
FROM_HERE,
base::BindOnce(
&BeginResourceDownload, std::move(params), std::move(request),
- std::move(url_loader_factory_getter), url_security_policy_,
+ std::move(url_loader_factory_info), url_security_policy_,
is_new_download, weak_factory_.GetWeakPtr(), site_url, tab_url,
tab_referrer_url, connector_ ? connector_->Clone() : nullptr,
!delegate_ /* is_background_mode */,
@@ -318,7 +323,8 @@ void InProgressDownloadManager::InterceptDownloadFromNavigation(
scoped_refptr<network::ResourceResponse> response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter) {
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_info) {
GetIOTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
@@ -327,19 +333,26 @@ void InProgressDownloadManager::InterceptDownloadFromNavigation(
site_url, tab_url, tab_referrer_url, std::move(url_chain),
std::move(cert_status), std::move(response_head),
std::move(response_body), std::move(url_loader_client_endpoints),
- std::move(url_loader_factory_getter), url_security_policy_,
+ std::move(url_loader_factory_info), url_security_policy_,
connector_ ? connector_->Clone() : nullptr,
base::ThreadTaskRunnerHandle::Get()));
}
void InProgressDownloadManager::Initialize(
- const base::FilePath& in_progress_db_dir) {
- download_db_cache_ = std::make_unique<DownloadDBCache>(
- in_progress_db_dir.empty()
- ? std::make_unique<DownloadDB>()
- : std::make_unique<DownloadDBImpl>(
- DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD,
- in_progress_db_dir));
+ const base::FilePath& in_progress_db_dir,
+ leveldb_proto::ProtoDatabaseProvider* db_provider) {
+ std::unique_ptr<DownloadDB> download_db;
+
+ if (use_empty_db_) {
+ download_db = std::make_unique<DownloadDB>();
+ } else {
+ download_db = std::make_unique<DownloadDBImpl>(
+ DownloadNamespace::NAMESPACE_BROWSER_DOWNLOAD, in_progress_db_dir,
+ db_provider);
+ }
+
+ download_db_cache_ =
+ std::make_unique<DownloadDBCache>(std::move(download_db));
download_db_cache_->Initialize(base::BindOnce(
&InProgressDownloadManager::OnDBInitialized, weak_factory_.GetWeakPtr()));
}
@@ -390,11 +403,11 @@ void InProgressDownloadManager::DetermineDownloadTarget(
void InProgressDownloadManager::ResumeInterruptedDownload(
std::unique_ptr<DownloadUrlParameters> params,
const GURL& site_url) {
- if (!url_loader_factory_getter_)
+ if (!url_loader_factory_)
return;
- BeginDownload(std::move(params), url_loader_factory_getter_, false, site_url,
- GURL(), GURL());
+ BeginDownload(std::move(params), url_loader_factory_->Clone(), false,
+ site_url, GURL(), GURL());
}
bool InProgressDownloadManager::ShouldOpenDownload(
@@ -425,7 +438,9 @@ void InProgressDownloadManager::RemoveInProgressDownload(
void InProgressDownloadManager::StartDownload(
std::unique_ptr<DownloadCreateInfo> info,
std::unique_ptr<InputStream> stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadUrlParameters::OnStartedCallback& on_started) {
DCHECK(info);
@@ -434,6 +449,8 @@ void InProgressDownloadManager::StartDownload(
info->result ==
DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT)) {
if (delegate_ && delegate_->InterceptDownload(*info)) {
+ if (cancel_request_callback)
+ std::move(cancel_request_callback).Run(false);
GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
return;
}
@@ -451,7 +468,6 @@ void InProgressDownloadManager::StartDownload(
std::string mime_type = info->mime_type;
if (info->is_new_download) {
- RecordDownloadConnectionSecurity(info->url(), info->url_chain);
RecordDownloadContentTypeSecurity(info->url(), info->url_chain,
info->mime_type, is_origin_secure_cb_);
}
@@ -463,7 +479,8 @@ void InProgressDownloadManager::StartDownload(
std::move(info), on_started,
base::BindOnce(&InProgressDownloadManager::StartDownloadWithItem,
weak_factory_.GetWeakPtr(), std::move(stream),
- std::move(url_loader_factory_getter)));
+ std::move(url_loader_factory_provider),
+ std::move(cancel_request_callback)));
} else {
std::string guid = info->guid;
if (info->is_new_download) {
@@ -473,15 +490,17 @@ void InProgressDownloadManager::StartDownload(
in_progress_downloads_.push_back(std::move(download));
}
StartDownloadWithItem(
- std::move(stream), std::move(url_loader_factory_getter),
- std::move(info),
+ std::move(stream), std::move(url_loader_factory_provider),
+ std::move(cancel_request_callback), std::move(info),
static_cast<DownloadItemImpl*>(GetDownloadByGuid(guid)), false);
}
}
void InProgressDownloadManager::StartDownloadWithItem(
std::unique_ptr<InputStream> stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
std::unique_ptr<DownloadCreateInfo> info,
DownloadItemImpl* download,
bool should_persist_new_download) {
@@ -489,8 +508,8 @@ void InProgressDownloadManager::StartDownloadWithItem(
// If the download is no longer known to the DownloadManager, then it was
// removed after it was resumed. Ignore. If the download is cancelled
// while resuming, then also ignore the request.
- if (info->request_handle)
- info->request_handle->CancelRequest(true);
+ if (cancel_request_callback)
+ std::move(cancel_request_callback).Run(false);
// The ByteStreamReader lives and dies on the download sequence.
if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE)
GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
@@ -523,15 +542,8 @@ void InProgressDownloadManager::StartDownloadWithItem(
// so that the DownloadItem can salvage what it can out of a failed
// resumption attempt.
- net::URLRequestContextGetter* url_request_context_getter = nullptr;
- if (delegate_ &&
- !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- url_request_context_getter = delegate_->GetURLRequestContextGetter(*info);
- }
-
- download->Start(std::move(download_file), std::move(info->request_handle),
- *info, std::move(url_loader_factory_getter),
- url_request_context_getter);
+ download->Start(std::move(download_file), std::move(cancel_request_callback),
+ *info, std::move(url_loader_factory_provider));
if (download_start_observer_)
download_start_observer_->OnDownloadStarted(download);
@@ -653,4 +665,10 @@ void InProgressDownloadManager::AddInProgressDownloadForTest(
in_progress_downloads_.push_back(std::move(download));
}
+void InProgressDownloadManager::CancelUrlDownload(
+ UrlDownloadHandler* downloader,
+ bool user_cancel) {
+ OnUrlDownloadStopped(downloader);
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/common/parallel_download_job.cc b/chromium/components/download/internal/common/parallel_download_job.cc
index 45600c7054f..a2e1e42495d 100644
--- a/chromium/components/download/internal/common/parallel_download_job.cc
+++ b/chromium/components/download/internal/common/parallel_download_job.cc
@@ -12,9 +12,7 @@
#include "components/download/internal/common/parallel_download_utils.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_stats.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_context_getter.h"
namespace download {
namespace {
@@ -23,21 +21,19 @@ const int kDownloadJobVerboseLevel = 1;
ParallelDownloadJob::ParallelDownloadJob(
DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle,
+ CancelRequestCallback cancel_request_callback,
const DownloadCreateInfo& create_info,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
service_manager::Connector* connector)
- : DownloadJobImpl(download_item, std::move(request_handle), true),
+ : DownloadJobImpl(download_item, std::move(cancel_request_callback), true),
initial_request_offset_(create_info.offset),
initial_received_slices_(download_item->GetReceivedSlices()),
content_length_(create_info.total_bytes),
requests_sent_(false),
is_canceled_(false),
range_support_(create_info.accept_range),
- url_loader_factory_getter_(std::move(url_loader_factory_getter)),
- url_request_context_getter_(url_request_context_getter),
+ url_loader_factory_provider_(std::move(url_loader_factory_provider)),
connector_(connector) {}
ParallelDownloadJob::~ParallelDownloadJob() = default;
@@ -298,8 +294,8 @@ void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) {
download_params->set_follow_cross_origin_redirects(false);
// Send the request.
- worker->SendRequest(std::move(download_params), url_loader_factory_getter_,
- url_request_context_getter_, connector_);
+ worker->SendRequest(std::move(download_params),
+ url_loader_factory_provider_.get(), connector_);
DCHECK(workers_.find(offset) == workers_.end());
workers_[offset] = std::move(worker);
}
diff --git a/chromium/components/download/internal/common/parallel_download_job.h b/chromium/components/download/internal/common/parallel_download_job.h
index ca410838e13..e502805555b 100644
--- a/chromium/components/download/internal/common/parallel_download_job.h
+++ b/chromium/components/download/internal/common/parallel_download_job.h
@@ -10,17 +10,14 @@
#include <vector>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "components/download/internal/common/download_job_impl.h"
#include "components/download/internal/common/download_worker.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/parallel_download_configs.h"
-
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
+#include "components/download/public/common/url_loader_factory_provider.h"
namespace service_manager {
class Connector;
@@ -37,14 +34,12 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
public:
// TODO(qinmin): Remove |url_request_context_getter| once network service is
// enabled.
- ParallelDownloadJob(
- DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle,
- const DownloadCreateInfo& create_info,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter,
- service_manager::Connector* connector);
+ ParallelDownloadJob(DownloadItem* download_item,
+ CancelRequestCallback cancel_request_callback,
+ const DownloadCreateInfo& create_info,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ service_manager::Connector* connector);
~ParallelDownloadJob() override;
// DownloadJobImpl implementation.
@@ -123,13 +118,10 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
// Whether the server accepts range requests.
RangeRequestSupportType range_support_;
- // URLLoaderFactory getter to issue network requests with network service
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter_;
-
- // URLRequestContextGetter for issueing network requests when network service
- // is disabled.
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+ // URLLoaderFactoryProvider to retrieve the URLLoaderFactory and issue
+ // parallel requests.
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider_;
// Connector used for establishing the connection to the ServiceManager.
service_manager::Connector* connector_;
diff --git a/chromium/components/download/internal/common/parallel_download_job_unittest.cc b/chromium/components/download/internal/common/parallel_download_job_unittest.cc
index d227cf4232e..7909c2ee000 100644
--- a/chromium/components/download/internal/common/parallel_download_job_unittest.cc
+++ b/chromium/components/download/internal/common/parallel_download_job_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/download/internal/common/parallel_download_utils.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_destination_observer.h"
@@ -31,13 +31,6 @@ namespace download {
namespace {
-class MockDownloadRequestHandle : public DownloadRequestHandleInterface {
- public:
- MOCK_METHOD0(PauseRequest, void());
- MOCK_METHOD0(ResumeRequest, void());
- MOCK_METHOD1(CancelRequest, void(bool));
-};
-
class MockDownloadDestinationObserver : public DownloadDestinationObserver {
public:
MOCK_METHOD3(DestinationUpdate,
@@ -60,16 +53,15 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
public:
ParallelDownloadJobForTest(
DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadCreateInfo& create_info,
int request_count,
int64_t min_slice_size,
int min_remaining_time)
: ParallelDownloadJob(download_item,
- std::move(request_handle),
+ std::move(cancel_request_callback),
create_info,
- nullptr,
- nullptr,
+ URLLoaderFactoryProvider::GetNullPtr(),
nullptr),
request_count_(request_count),
min_slice_size_(min_slice_size),
@@ -115,9 +107,9 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
class ParallelDownloadJobTest : public testing::Test {
public:
ParallelDownloadJobTest()
- : task_environment_(base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::
- ThreadPoolExecutionMode::QUEUED) {}
+ : task_environment_(
+ base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
void CreateParallelJob(int64_t initial_request_offset,
int64_t content_length,
@@ -137,19 +129,17 @@ class ParallelDownloadJobTest : public testing::Test {
DownloadCreateInfo info;
info.offset = initial_request_offset;
info.total_bytes = content_length;
- std::unique_ptr<MockDownloadRequestHandle> request_handle =
- std::make_unique<MockDownloadRequestHandle>();
- mock_request_handle_ = request_handle.get();
job_ = std::make_unique<ParallelDownloadJobForTest>(
- download_item_.get(), std::move(request_handle), info, request_count,
- min_slice_size, min_remaining_time);
+ download_item_.get(),
+ base::Bind(&ParallelDownloadJobTest::CancelRequest,
+ base::Unretained(this)),
+ info, request_count, min_slice_size, min_remaining_time);
file_initialized_ = false;
}
void DestroyParallelJob() {
job_.reset();
download_item_.reset();
- mock_request_handle_ = nullptr;
}
void BuildParallelRequests() { job_->BuildParallelRequests(); }
@@ -160,18 +150,7 @@ class ParallelDownloadJobTest : public testing::Test {
bool IsJobCanceled() const { return job_->is_canceled_; }
- void MakeWorkerReady(
- DownloadWorker* worker,
- std::unique_ptr<MockDownloadRequestHandle> request_handle) {
- UrlDownloadHandler::Delegate* delegate =
- static_cast<UrlDownloadHandler::Delegate*>(worker);
- std::unique_ptr<DownloadCreateInfo> create_info =
- std::make_unique<DownloadCreateInfo>();
- create_info->request_handle = std::move(request_handle);
- delegate->OnUrlDownloadStarted(std::move(create_info),
- std::make_unique<MockInputStream>(), nullptr,
- DownloadUrlParameters::OnStartedCallback());
- }
+ void CancelRequest(bool user_cancel) { canceled_ = true; }
void VerifyWorker(int64_t offset, int64_t length) const {
EXPECT_TRUE(job_->workers_.find(offset) != job_->workers_.end());
@@ -183,12 +162,11 @@ class ParallelDownloadJobTest : public testing::Test {
file_initialized_ = true;
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<MockDownloadItem> download_item_;
std::unique_ptr<ParallelDownloadJobForTest> job_;
bool file_initialized_;
- // Request handle for the original request.
- MockDownloadRequestHandle* mock_request_handle_;
+ bool canceled_ = false;
// The received slices used to return in
// |MockDownloadItemImpl::GetReceivedSlices| mock function.
@@ -404,11 +382,11 @@ TEST_F(ParallelDownloadJobTest, LastReceivedSliceFinished) {
// built.
TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) {
CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
- EXPECT_CALL(*mock_request_handle_, CancelRequest(_));
// Job is canceled before building parallel requests.
job_->Cancel(true);
EXPECT_TRUE(IsJobCanceled());
+ EXPECT_TRUE(canceled_);
BuildParallelRequests();
EXPECT_TRUE(job_->workers().empty());
@@ -416,55 +394,6 @@ TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) {
DestroyParallelJob();
}
-// Ensure cancel before adding the byte stream will result in workers being
-// canceled.
-TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) {
- CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
- EXPECT_CALL(*mock_request_handle_, CancelRequest(_));
-
- BuildParallelRequests();
- VerifyWorker(50, 0);
-
- // Job is canceled after building parallel requests and before byte streams
- // are added to the file sink.
- job_->Cancel(true);
- EXPECT_TRUE(IsJobCanceled());
-
- for (auto& worker : job_->workers()) {
- std::unique_ptr<MockDownloadRequestHandle> mock_handle =
- std::make_unique<MockDownloadRequestHandle>();
- EXPECT_CALL(*mock_handle, CancelRequest(_));
- MakeWorkerReady(worker.second.get(), std::move(mock_handle));
- }
-
- DestroyParallelJob();
-}
-
-// Ensure pause before adding the byte stream will result in workers being
-// paused.
-TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) {
- CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
- EXPECT_CALL(*mock_request_handle_, PauseRequest());
-
- BuildParallelRequests();
- VerifyWorker(50, 0);
-
- // Job is paused after building parallel requests and before adding the byte
- // stream to the file sink.
- job_->Pause();
- EXPECT_TRUE(job_->is_paused());
-
- for (auto& worker : job_->workers()) {
- EXPECT_CALL(*job_, CountOnInputStreamReady());
- std::unique_ptr<MockDownloadRequestHandle> mock_handle =
- std::make_unique<MockDownloadRequestHandle>();
- EXPECT_CALL(*mock_handle, PauseRequest());
- MakeWorkerReady(worker.second.get(), std::move(mock_handle));
- }
-
- DestroyParallelJob();
-}
-
// Test that parallel request is not created if the remaining content can be
// finish downloading soon.
TEST_F(ParallelDownloadJobTest, RemainingContentWillFinishSoon) {
diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc
index 15de44ecd42..cf8829ee8d4 100644
--- a/chromium/components/download/internal/common/resource_downloader.cc
+++ b/chromium/components/download/internal/common/resource_downloader.cc
@@ -7,9 +7,9 @@
#include <memory>
#include "base/bind.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/stream_handle_input_stream.h"
-#include "components/download/public/common/url_download_request_handle.h"
+#include "components/download/public/common/url_loader_factory_provider.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -31,9 +31,9 @@ class URLLoaderStatusMonitor : public network::mojom::URLLoaderClient {
~URLLoaderStatusMonitor() override = default;
// network::mojom::URLLoaderClient
- void OnReceiveResponse(const network::ResourceResponseHead& head) override {}
+ void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override {}
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& head) override {}
+ network::mojom::URLResponseHeadPtr head) override {}
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override {}
@@ -62,8 +62,7 @@ std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
std::unique_ptr<DownloadUrlParameters> params,
std::unique_ptr<network::ResourceRequest> request,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
const GURL& site_url,
const GURL& tab_url,
@@ -77,8 +76,7 @@ std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
delegate, std::move(request), params->render_process_host_id(),
params->render_frame_host_routing_id(), site_url, tab_url,
tab_referrer_url, is_new_download, task_runner,
- std::move(url_loader_factory_getter), url_security_policy,
- std::move(connector));
+ std::move(url_loader_factory), url_security_policy, std::move(connector));
downloader->Start(std::move(params), is_parallel_request, is_background_mode);
return downloader;
@@ -99,16 +97,14 @@ ResourceDownloader::InterceptNavigationResponse(
const scoped_refptr<network::ResourceResponse>& response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
auto downloader = std::make_unique<ResourceDownloader>(
delegate, std::move(resource_request), render_process_id, render_frame_id,
site_url, tab_url, tab_referrer_url, true, task_runner,
- std::move(url_loader_factory_getter), url_security_policy,
- std::move(connector));
+ std::move(url_loader_factory), url_security_policy, std::move(connector));
downloader->InterceptResponse(
std::move(url_chain), cert_status, std::move(response_head),
std::move(response_body), std::move(url_loader_client_endpoints));
@@ -125,8 +121,7 @@ ResourceDownloader::ResourceDownloader(
const GURL& tab_referrer_url,
bool is_new_download,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
std::unique_ptr<service_manager::Connector> connector)
: delegate_(delegate),
@@ -138,7 +133,7 @@ ResourceDownloader::ResourceDownloader(
tab_url_(tab_url),
tab_referrer_url_(tab_referrer_url),
delegate_task_runner_(task_runner),
- url_loader_factory_getter_(std::move(url_loader_factory_getter)),
+ url_loader_factory_(url_loader_factory),
url_security_policy_(url_security_policy),
is_content_initiated_(false) {
RequestWakeLock(connector.get());
@@ -166,8 +161,8 @@ void ResourceDownloader::Start(
download_url_parameters->request_headers(),
download_url_parameters->request_origin(),
download_url_parameters->download_source(),
- download_url_parameters->ignore_content_length_mismatch(),
std::vector<GURL>(1, resource_request_->url), is_background_mode);
+
network::mojom::URLLoaderClientPtr url_loader_client_ptr;
url_loader_client_binding_ =
std::make_unique<mojo::Binding<network::mojom::URLLoaderClient>>(
@@ -176,7 +171,7 @@ void ResourceDownloader::Start(
// Set up the URLLoader
network::mojom::URLLoaderRequest url_loader_request =
mojo::MakeRequest(&url_loader_);
- url_loader_factory_getter_->GetURLLoaderFactory()->CreateLoaderAndStart(
+ url_loader_factory_->CreateLoaderAndStart(
std::move(url_loader_request),
0, // routing_id
0, // request_id
@@ -206,8 +201,7 @@ void ResourceDownloader::InterceptResponse(
true, /* follow_cross_origin_redirects */
download::DownloadUrlParameters::RequestHeadersType(),
std::string(), /* request_origin */
- download::DownloadSource::NAVIGATION,
- false /* ignore_content_length_mismatch */, std::move(url_chain),
+ download::DownloadSource::NAVIGATION, std::move(url_chain),
false /* is_background_mode */);
// Simulate on the new URLLoaderClient calls that happened on the old client.
@@ -227,8 +221,6 @@ void ResourceDownloader::InterceptResponse(
void ResourceDownloader::OnResponseStarted(
std::unique_ptr<DownloadCreateInfo> download_create_info,
mojom::DownloadStreamHandlePtr stream_handle) {
- download_create_info->request_handle.reset(new UrlDownloadRequestHandle(
- weak_ptr_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get()));
download_create_info->is_new_download = is_new_download_;
download_create_info->guid = guid_;
download_create_info->site_url = site_url_;
@@ -245,7 +237,10 @@ void ResourceDownloader::OnResponseStarted(
&UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
std::move(download_create_info),
std::make_unique<StreamHandleInputStream>(std::move(stream_handle)),
- std::move(url_loader_factory_getter_), callback_));
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr(
+ new URLLoaderFactoryProvider(url_loader_factory_),
+ base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())),
+ this, callback_));
}
void ResourceDownloader::OnReceiveRedirect() {
@@ -289,13 +284,13 @@ void ResourceDownloader::RequestWakeLock(
service_manager::Connector* connector) {
if (!connector)
return;
- device::mojom::WakeLockProviderPtr wake_lock_provider;
- connector->BindInterface(device::mojom::kServiceName,
- mojo::MakeRequest(&wake_lock_provider));
+ mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider;
+ connector->Connect(device::mojom::kServiceName,
+ wake_lock_provider.BindNewPipeAndPassReceiver());
wake_lock_provider->GetWakeLockWithoutContext(
device::mojom::WakeLockType::kPreventAppSuspension,
device::mojom::WakeLockReason::kOther, "Download in progress",
- mojo::MakeRequest(&wake_lock_));
+ wake_lock_.BindNewPipeAndPassReceiver());
wake_lock_->RequestWakeLock();
}
diff --git a/chromium/components/download/internal/common/resource_downloader.h b/chromium/components/download/internal/common/resource_downloader.h
index 230269b856d..fe7cb243a75 100644
--- a/chromium/components/download/internal/common/resource_downloader.h
+++ b/chromium/components/download/internal/common/resource_downloader.h
@@ -11,6 +11,7 @@
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/url_download_handler.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "net/cert/cert_status_flags.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/network/public/cpp/resource_request.h"
@@ -21,20 +22,17 @@ class Connector;
} // namespace service_manager
namespace download {
-class DownloadURLLoaderFactoryGetter;
-
// Class for handing the download of a url. Lives on IO thread.
class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
- : public download::UrlDownloadHandler,
- public download::DownloadResponseHandler::Delegate {
+ : public UrlDownloadHandler,
+ public DownloadResponseHandler::Delegate {
public:
// Called to start a download, must be called on IO thread.
static std::unique_ptr<ResourceDownloader> BeginDownload(
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
std::unique_ptr<download::DownloadUrlParameters> download_url_parameters,
std::unique_ptr<network::ResourceRequest> request,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
const GURL& site_url,
const GURL& tab_url,
@@ -61,8 +59,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
const scoped_refptr<network::ResourceResponse>& response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
@@ -77,16 +74,15 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
const GURL& tab_referrer_url,
bool is_new_download,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
std::unique_ptr<service_manager::Connector> connector);
~ResourceDownloader() override;
- // download::DownloadResponseHandler::Delegate
+ // DownloadResponseHandler::Delegate
void OnResponseStarted(
std::unique_ptr<download::DownloadCreateInfo> download_create_info,
- download::mojom::DownloadStreamHandlePtr stream_handle) override;
+ mojom::DownloadStreamHandlePtr stream_handle) override;
void OnReceiveRedirect() override;
void OnResponseCompleted() override;
bool CanRequestURL(const GURL& url) override;
@@ -162,9 +158,8 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
// TaskRunner to post callbacks to the |delegate_|
scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
- // URLLoaderFactory getter for issueing network requests.
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter_;
+ // URLLoaderFactory for issuing network requests.
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Used to check if the URL is safe to request.
URLSecurityPolicy url_security_policy_;
@@ -175,7 +170,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
// Used to keep the system from sleeping while a download is ongoing. If the
// system enters power saving mode while a download is alive, it can cause
// download to be interrupted.
- device::mojom::WakeLockPtr wake_lock_;
+ mojo::Remote<device::mojom::WakeLock> wake_lock_;
base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_{this};
diff --git a/chromium/components/download/internal/common/save_package_download_job.cc b/chromium/components/download/internal/common/save_package_download_job.cc
index ae0c9277798..bd6734e652f 100644
--- a/chromium/components/download/internal/common/save_package_download_job.cc
+++ b/chromium/components/download/internal/common/save_package_download_job.cc
@@ -8,8 +8,8 @@ namespace download {
SavePackageDownloadJob::SavePackageDownloadJob(
DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle)
- : DownloadJob(download_item, std::move(request_handle)) {}
+ DownloadJob::CancelRequestCallback cancel_request_callback)
+ : DownloadJob(download_item, std::move(cancel_request_callback)) {}
SavePackageDownloadJob::~SavePackageDownloadJob() = default;
diff --git a/chromium/components/download/internal/common/save_package_download_job.h b/chromium/components/download/internal/common/save_package_download_job.h
index fea7fb1bbb5..fdcffcabc2c 100644
--- a/chromium/components/download/internal/common/save_package_download_job.h
+++ b/chromium/components/download/internal/common/save_package_download_job.h
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_job.h"
-#include "components/download/public/common/download_request_handle_interface.h"
namespace download {
@@ -16,7 +15,7 @@ class SavePackageDownloadJob : public DownloadJob {
public:
SavePackageDownloadJob(
DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle);
+ DownloadJob::CancelRequestCallback cancel_request_callback);
~SavePackageDownloadJob() override;
// DownloadJob implementation.
diff --git a/chromium/components/download/internal/common/url_download_handler_factory.cc b/chromium/components/download/internal/common/url_download_handler_factory.cc
index d0634a03292..056a9f562fa 100644
--- a/chromium/components/download/internal/common/url_download_handler_factory.cc
+++ b/chromium/components/download/internal/common/url_download_handler_factory.cc
@@ -8,89 +8,31 @@
#include "base/synchronization/lock.h"
#include "components/download/internal/common/resource_downloader.h"
#include "components/download/public/common/download_item.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_utils.h"
-#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/connector.h"
namespace download {
-namespace {
-
-// Factory for creating URLDownloadHandler used by network service.
-class DefaultUrlDownloadHandlerFactory : public UrlDownloadHandlerFactory {
- public:
- DefaultUrlDownloadHandlerFactory() = default;
- ~DefaultUrlDownloadHandlerFactory() override = default;
-
- protected:
- UrlDownloadHandler::UniqueUrlDownloadHandlerPtr CreateUrlDownloadHandler(
- std::unique_ptr<download::DownloadUrlParameters> params,
- base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- const URLSecurityPolicy& url_security_policy,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
- std::unique_ptr<service_manager::Connector> connector,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override {
- std::unique_ptr<network::ResourceRequest> request =
- CreateResourceRequest(params.get());
- return UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
- download::ResourceDownloader::BeginDownload(
- delegate, std::move(params), std::move(request),
- std::move(url_loader_factory_getter), url_security_policy, GURL(),
- GURL(), GURL(), true, true, std::move(connector),
- false /* is_background_mode */, task_runner)
- .release(),
- base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DefaultUrlDownloadHandlerFactory);
-};
-
-UrlDownloadHandlerFactory* g_url_download_handler_factory;
-
-// Lock to protect |g_url_download_handler_factory|
-base::Lock& GetURLDownloadHandlerFactoryLock() {
- static base::NoDestructor<base::Lock> instance;
- return *instance;
-}
-
-} // namespace
-
// static
UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
UrlDownloadHandlerFactory::Create(
std::unique_ptr<download::DownloadUrlParameters> params,
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
- base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
- if (!g_url_download_handler_factory)
- g_url_download_handler_factory = new DefaultUrlDownloadHandlerFactory();
- return g_url_download_handler_factory->CreateUrlDownloadHandler(
- std::move(params), delegate, std::move(url_loader_factory_getter),
- std::move(url_security_policy), std::move(url_request_context_getter),
- std::move(connector), task_runner);
-}
-
-// static
-void UrlDownloadHandlerFactory::Install(UrlDownloadHandlerFactory* factory) {
- base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
- if (factory == g_url_download_handler_factory)
- return;
- delete g_url_download_handler_factory;
- g_url_download_handler_factory = factory;
+ std::unique_ptr<network::ResourceRequest> request =
+ CreateResourceRequest(params.get());
+ return UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
+ download::ResourceDownloader::BeginDownload(
+ delegate, std::move(params), std::move(request),
+ std::move(url_loader_factory), url_security_policy, GURL(), GURL(),
+ GURL(), true, true, std::move(connector),
+ false /* is_background_mode */, task_runner)
+ .release(),
+ base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
}
-UrlDownloadHandlerFactory::UrlDownloadHandlerFactory() = default;
-
-UrlDownloadHandlerFactory::~UrlDownloadHandlerFactory() = default;
-
} // namespace download
diff --git a/chromium/components/download/internal/common/url_download_request_handle.cc b/chromium/components/download/internal/common/url_download_request_handle.cc
index 9faf499f03d..186adf819e1 100644
--- a/chromium/components/download/internal/common/url_download_request_handle.cc
+++ b/chromium/components/download/internal/common/url_download_request_handle.cc
@@ -27,22 +27,4 @@ UrlDownloadRequestHandle& UrlDownloadRequestHandle::operator=(
UrlDownloadRequestHandle::~UrlDownloadRequestHandle() = default;
-void UrlDownloadRequestHandle::PauseRequest() {
- downloader_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&UrlDownloadHandler::PauseRequest, downloader_));
-}
-
-void UrlDownloadRequestHandle::ResumeRequest() {
- downloader_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&UrlDownloadHandler::ResumeRequest, downloader_));
-}
-
-void UrlDownloadRequestHandle::CancelRequest(bool user_cancel) {
- downloader_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&UrlDownloadHandler::CancelRequest, downloader_));
-}
-
} // namespace download
diff --git a/chromium/components/download/internal/common/url_loader_factory_provider.cc b/chromium/components/download/internal/common/url_loader_factory_provider.cc
new file mode 100644
index 00000000000..d4c26271a59
--- /dev/null
+++ b/chromium/components/download/internal/common/url_loader_factory_provider.cc
@@ -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.
+
+#include "components/download/public/common/url_loader_factory_provider.h"
+
+#include "components/download/public/common/download_task_runner.h"
+
+namespace download {
+
+URLLoaderFactoryProvider::URLLoaderFactoryProvider(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : url_loader_factory_(std::move(url_loader_factory)) {}
+
+URLLoaderFactoryProvider::~URLLoaderFactoryProvider() = default;
+
+scoped_refptr<network::SharedURLLoaderFactory>
+URLLoaderFactoryProvider::GetURLLoaderFactory() {
+ return url_loader_factory_;
+}
+
+// static
+URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+URLLoaderFactoryProvider::GetNullPtr() {
+ return URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr(
+ nullptr, base::OnTaskRunnerDeleter(nullptr));
+}
+
+} // namespace download
diff --git a/chromium/components/download/public/common/BUILD.gn b/chromium/components/download/public/common/BUILD.gn
index 5883cbbcb11..3febd81f0b4 100644
--- a/chromium/components/download/public/common/BUILD.gn
+++ b/chromium/components/download/public/common/BUILD.gn
@@ -40,7 +40,6 @@ component("public") {
"download_job.h",
"download_job_factory.h",
"download_path_reservation_tracker.h",
- "download_request_handle_interface.h",
"download_response_handler.h",
"download_save_info.cc",
"download_save_info.h",
@@ -49,8 +48,6 @@ component("public") {
"download_stats.h",
"download_task_runner.h",
"download_ukm_helper.h",
- "download_url_loader_factory_getter.h",
- "download_url_loader_factory_getter_impl.h",
"download_url_parameters.cc",
"download_url_parameters.h",
"download_utils.h",
@@ -58,6 +55,7 @@ component("public") {
"input_stream.cc",
"input_stream.h",
"parallel_download_configs.h",
+ "quarantine_connection.h",
"rate_estimator.h",
"resume_mode.h",
"simple_download_manager.h",
@@ -65,19 +63,22 @@ component("public") {
"stream_handle_input_stream.h",
"url_download_handler_factory.h",
"url_download_request_handle.h",
+ "url_loader_factory_provider.h",
]
configs += [ ":components_download_implementation" ]
public_deps = [
":interfaces",
+ "//base",
"//components/download/network",
"//components/download/public/background_service:public",
+ "//components/services/quarantine/public/mojom",
+ "//mojo/public/cpp/bindings",
"//services/network/public/cpp",
]
deps = [
- "//base",
"//components/download/database",
"//components/download/internal/common:internal",
"//components/services/quarantine:quarantine",
diff --git a/chromium/components/download/public/common/base_file.h b/chromium/components/download/public/common/base_file.h
index 4a01d7b7d0e..5a80471d12d 100644
--- a/chromium/components/download/public/common/base_file.h
+++ b/chromium/components/download/public/common/base_file.h
@@ -27,13 +27,11 @@
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
#include "crypto/secure_hash.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/net_errors.h"
#include "url/gurl.h"
-namespace service_manager {
-class Connector;
-}
-
namespace download {
// File being downloaded and saved to disk. This is a base class
@@ -169,8 +167,7 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile {
using OnAnnotationDoneCallback =
base::OnceCallback<void(DownloadInterruptReason)>;
- // Called when a quarantine service is used,
- // connector is used to populate a quarantine::mojom::QuarantinePtr,
+ // Called when a quarantine service is used.
// and the callback will be called from the service.
// TODO (crbug.com/973497): Remove non-service version when
// kPreventDownloadsWithSamePath feature is removed.
@@ -178,7 +175,7 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile {
const std::string& client_guid,
const GURL& source_url,
const GURL& referrer_url,
- std::unique_ptr<service_manager::Connector> connector,
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
OnAnnotationDoneCallback on_annotation_done_callback);
#if defined(OS_ANDROID)
@@ -304,8 +301,8 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile {
// ID of the download, used for trace events.
uint32_t download_id_;
- // Mojo pointer for quarantine service.
- quarantine::mojom::QuarantinePtr quarantine_service_;
+ // Mojo remote for quarantine service.
+ mojo::Remote<quarantine::mojom::Quarantine> quarantine_service_;
// Callback invoked after quarantine service finishes.
OnAnnotationDoneCallback on_annotation_done_callback_;
diff --git a/chromium/components/download/public/common/download_create_info.h b/chromium/components/download/public/common/download_create_info.h
index 84553dc1b97..d1699c66c7b 100644
--- a/chromium/components/download/public/common/download_create_info.h
+++ b/chromium/components/download/public/common/download_create_info.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -18,7 +19,6 @@
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
-#include "components/download/public/common/download_request_handle_interface.h"
#include "components/download/public/common/download_save_info.h"
#include "components/download/public/common/download_source.h"
#include "components/download/public/common/download_url_parameters.h"
@@ -34,7 +34,6 @@ class HttpResponseHeaders;
}
namespace download {
-
// Server support for range request inferred from the response headers.
// |kSupport| value means the server supports range requests. |kNoSupport|
// means no range request is accepted by server. and |kUnknown| is used if
@@ -124,10 +123,6 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo {
// The render frame id that initiates this download.
int render_frame_id;
- // The handle to the URLRequest sourcing this download.
- // TODO(qinmin): remove this when network service is fully enabled.
- std::unique_ptr<DownloadRequestHandleInterface> request_handle;
-
// ---------------------------------------------------------------------------
// The remaining fields are Entity-body properties. These are only set if
// |result| is DOWNLOAD_INTERRUPT_REASON_NONE.
diff --git a/chromium/components/download/public/common/download_features.cc b/chromium/components/download/public/common/download_features.cc
index 3d27465f635..3411080f7eb 100644
--- a/chromium/components/download/public/common/download_features.cc
+++ b/chromium/components/download/public/common/download_features.cc
@@ -54,10 +54,10 @@ const base::Feature kUseParallelRequestsForUnknwonRangeSupport{
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kUseParallelRequestsForHTTP2{
- "kUseParallelRequestsForHTTP2", base::FEATURE_DISABLED_BY_DEFAULT};
+ "UseParallelRequestsForHTTP2", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kUseParallelRequestsForQUIC{
- "kUseParallelRequestsForQUIC", base::FEATURE_DISABLED_BY_DEFAULT};
+ "UseParallelRequestsForQUIC", base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
} // namespace download
diff --git a/chromium/components/download/public/common/download_file.h b/chromium/components/download/public/common/download_file.h
index 6cfd902a6d4..7f81cfbebc1 100644
--- a/chromium/components/download/public/common/download_file.h
+++ b/chromium/components/download/public/common/download_file.h
@@ -18,14 +18,12 @@
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/input_stream.h"
+#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
class GURL;
-namespace service_manager {
-class Connector;
-}
-
namespace download {
// These objects live exclusively on the download sequence and handle the
@@ -86,16 +84,15 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFile {
// Rename the download file to |full_path| and annotate it with
// "Mark of the Web" information about its source. No uniquification
// will be performed.
- // connector is a clone of the service manager connector from
- // DownloadItemImpl's delegate. It used to create the quarantine service.
- // In the unexpected case that connector is null, or the service otherwise
- // fails, mark-of-the-web is manually applied as a fallback.
+ // |remote_quarantine| must be connected to an instance of the Quarantine
+ // service. In the unexpected case that |remote_quarantine| is invalid, or the
+ // service otherwise fails, mark-of-the-web is manually applied as a fallback.
virtual void RenameAndAnnotate(
const base::FilePath& full_path,
const std::string& client_guid,
const GURL& source_url,
const GURL& referrer_url,
- std::unique_ptr<service_manager::Connector> connector,
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
const RenameCompletionCallback& callback) = 0;
// Detach the file so it is not deleted on destruction.
diff --git a/chromium/components/download/public/common/download_file_impl.h b/chromium/components/download/public/common/download_file_impl.h
index 1b33f39da91..59ef5d5ee4a 100644
--- a/chromium/components/download/public/common/download_file_impl.h
+++ b/chromium/components/download/public/common/download_file_impl.h
@@ -32,10 +32,6 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/simple_watcher.h"
-namespace service_manager {
-class Connector;
-}
-
namespace download {
class DownloadDestinationObserver;
@@ -68,12 +64,13 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
int64_t length) override;
void RenameAndUniquify(const base::FilePath& full_path,
const RenameCompletionCallback& callback) override;
- void RenameAndAnnotate(const base::FilePath& full_path,
- const std::string& client_guid,
- const GURL& source_url,
- const GURL& referrer_url,
- std::unique_ptr<service_manager::Connector> connector,
- const RenameCompletionCallback& callback) override;
+ void RenameAndAnnotate(
+ const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
+ const RenameCompletionCallback& callback) override;
void Detach() override;
void Cancel() override;
void SetPotentialFileLength(int64_t length) override;
@@ -234,7 +231,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
std::string client_guid; // See BaseFile::AnnotateWithSourceInformation()
GURL source_url; // See BaseFile::AnnotateWithSourceInformation()
GURL referrer_url; // See BaseFile::AnnotateWithSourceInformation()
- std::unique_ptr<service_manager::Connector> connector;
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine;
int retries_left; // RenameWithRetryInternal() will
// automatically retry until this
// count reaches 0. Each attempt
@@ -280,6 +277,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
// Register callback and start to read data from the stream.
void RegisterAndActivateStream(SourceStream* source_stream);
+ // Helper method to activate a stream and start reading from it.
+ void ActivateStream(SourceStream* source_stream);
+
// Called when a stream completes.
void OnStreamCompleted(SourceStream* source_stream);
diff --git a/chromium/components/download/public/common/download_item_factory.h b/chromium/components/download/public/common/download_item_factory.h
index 8453cd85349..f89fb11f0fc 100644
--- a/chromium/components/download/public/common/download_item_factory.h
+++ b/chromium/components/download/public/common/download_item_factory.h
@@ -18,6 +18,7 @@
#include "base/optional.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_item.h"
+#include "components/download/public/common/download_job.h"
#include "url/origin.h"
class GURL;
@@ -31,7 +32,6 @@ namespace download {
struct DownloadCreateInfo;
class DownloadItemImpl;
class DownloadItemImplDelegate;
-class DownloadRequestHandleInterface;
class COMPONENTS_DOWNLOAD_EXPORT DownloadItemFactory {
public:
@@ -77,7 +77,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemFactory {
const base::FilePath& path,
const GURL& url,
const std::string& mime_type,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle) = 0;
+ download::DownloadJob::CancelRequestCallback cancel_request_callback) = 0;
};
} // namespace download
diff --git a/chromium/components/download/public/common/download_item_impl.h b/chromium/components/download/public/common/download_item_impl.h
index 72e52e201a7..9df918424e7 100644
--- a/chromium/components/download/public/common/download_item_impl.h
+++ b/chromium/components/download/public/common/download_item_impl.h
@@ -23,21 +23,16 @@
#include "components/download/public/common/download_destination_observer.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
-#include "components/download/public/common/download_request_handle_interface.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "components/download/public/common/download_job.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/resume_mode.h"
+#include "components/download/public/common/url_loader_factory_provider.h"
#include "url/gurl.h"
#include "url/origin.h"
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace download {
class DownloadFile;
class DownloadItemImplDelegate;
-class DownloadJob;
// See download_item.h for usage.
class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
@@ -206,13 +201,12 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// Constructing for the "Save Page As..." feature:
// |net_log| is constructed externally for our use.
- DownloadItemImpl(
- DownloadItemImplDelegate* delegate,
- uint32_t id,
- const base::FilePath& path,
- const GURL& url,
- const std::string& mime_type,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle);
+ DownloadItemImpl(DownloadItemImplDelegate* delegate,
+ uint32_t id,
+ const base::FilePath& path,
+ const GURL& url,
+ const std::string& mime_type,
+ DownloadJob::CancelRequestCallback cancel_request_callback);
~DownloadItemImpl() override;
@@ -310,17 +304,16 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// Start the download.
// |download_file| is the associated file on the storage medium.
- // |req_handle| is the new request handle associated with the download.
+ // |cancel_request_callback| is the callback to cancel the download.
// |new_create_info| is a DownloadCreateInfo containing the new response
// parameters. It may be different from the DownloadCreateInfo used to create
// the DownloadItem if Start() is being called in response for a
// download resumption request.
virtual void Start(std::unique_ptr<DownloadFile> download_file,
- std::unique_ptr<DownloadRequestHandleInterface> req_handle,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadCreateInfo& new_create_info,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter);
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider);
// Needed because of intertwining with DownloadManagerImpl -------------------
diff --git a/chromium/components/download/public/common/download_item_impl_delegate.h b/chromium/components/download/public/common/download_item_impl_delegate.h
index e67be44238b..975357cffac 100644
--- a/chromium/components/download/public/common/download_item_impl_delegate.h
+++ b/chromium/components/download/public/common/download_item_impl_delegate.h
@@ -14,6 +14,9 @@
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/quarantine_connection.h"
+#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
namespace service_manager {
class Connector;
@@ -120,6 +123,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImplDelegate {
// Gets the ServiceManager connector that can be used on UI thread.
virtual service_manager::Connector* GetServiceManagerConnector();
+ // Gets a callback that can connect to the Quarantine Service if available.
+ virtual QuarantineConnectionCallback GetQuarantineConnectionCallback();
+
private:
// For "Outlives attached DownloadItemImpl" invariant assertion.
int count_;
diff --git a/chromium/components/download/public/common/download_job.h b/chromium/components/download/public/common/download_job.h
index 0831b93fc4f..a4348310bf3 100644
--- a/chromium/components/download/public/common/download_job.h
+++ b/chromium/components/download/public/common/download_job.h
@@ -11,7 +11,6 @@
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_interrupt_reasons.h"
-#include "components/download/public/common/download_request_handle_interface.h"
namespace download {
@@ -22,8 +21,13 @@ class DownloadItem;
// The base class is a friend class of DownloadItem.
class COMPONENTS_DOWNLOAD_EXPORT DownloadJob {
public:
+ // Callback to cancel the download request.
+ using CancelRequestCallback =
+ base::OnceCallback<void(bool /* user_cancel */)>;
+ CancelRequestCallback cancel_request_callback;
+
DownloadJob(DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> request_handle);
+ CancelRequestCallback cancel_request_callback);
virtual ~DownloadJob();
// Download operations.
@@ -66,9 +70,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadJob {
DownloadItem* download_item_;
- // Used to perform operations on network request.
- // Can be null on interrupted download.
- std::unique_ptr<DownloadRequestHandleInterface> request_handle_;
+ // Callback to cancel the download, can be null.
+ CancelRequestCallback cancel_request_callback_;
private:
// If the download progress is paused by the user.
diff --git a/chromium/components/download/public/common/download_job_factory.h b/chromium/components/download/public/common/download_job_factory.h
index d6660c1073c..0d51cdaf3c8 100644
--- a/chromium/components/download/public/common/download_job_factory.h
+++ b/chromium/components/download/public/common/download_job_factory.h
@@ -8,35 +8,29 @@
#include <memory>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_export.h"
-
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
+#include "components/download/public/common/download_job.h"
+#include "components/download/public/common/url_loader_factory_provider.h"
namespace service_manager {
class Connector;
} // namespace service_manager
namespace download {
-
class DownloadItem;
-class DownloadJob;
-class DownloadRequestHandleInterface;
-class DownloadURLLoaderFactoryGetter;
// Factory class to create different kinds of DownloadJob.
class COMPONENTS_DOWNLOAD_EXPORT DownloadJobFactory {
public:
static std::unique_ptr<DownloadJob> CreateJob(
DownloadItem* download_item,
- std::unique_ptr<DownloadRequestHandleInterface> req_handle,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadCreateInfo& create_info,
bool is_save_package_download,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
service_manager::Connector* connector);
private:
diff --git a/chromium/components/download/public/common/download_request_handle_interface.h b/chromium/components/download/public/common/download_request_handle_interface.h
deleted file mode 100644
index 31678df4a4d..00000000000
--- a/chromium/components/download/public/common/download_request_handle_interface.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_REQUEST_HANDLE_INTERFACE_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_REQUEST_HANDLE_INTERFACE_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "components/download/public/common/download_export.h"
-
-namespace download {
-
-// A handle used by the download system for operations on the network request.
-class COMPONENTS_DOWNLOAD_EXPORT DownloadRequestHandleInterface {
- public:
- virtual ~DownloadRequestHandleInterface() = default;
-
- // Pauses or resumes the network request.
- virtual void PauseRequest() = 0;
- virtual void ResumeRequest() = 0;
-
- // Cancels the request.
- virtual void CancelRequest(bool user_cancel) = 0;
-};
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_REQUEST_HANDLE_INTERFACE_H_
diff --git a/chromium/components/download/public/common/download_response_handler.h b/chromium/components/download/public/common/download_response_handler.h
index 9b67e71af4b..08d93025b27 100644
--- a/chromium/components/download/public/common/download_response_handler.h
+++ b/chromium/components/download/public/common/download_response_handler.h
@@ -52,15 +52,14 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler
const DownloadUrlParameters::RequestHeadersType& request_headers,
const std::string& request_origin,
DownloadSource download_source,
- bool ignore_content_length_mismatch,
std::vector<GURL> url_chain,
bool is_background_mode);
~DownloadResponseHandler() override;
// network::mojom::URLLoaderClient
- void OnReceiveResponse(const network::ResourceResponseHead& head) override;
+ void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- const network::ResourceResponseHead& head) override;
+ network::mojom::URLResponseHeadPtr head) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
@@ -97,7 +96,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler
std::string request_origin_;
DownloadSource download_source_;
net::CertStatus cert_status_;
- bool ignore_content_length_mismatch_;
+ bool has_strong_validators_;
base::Optional<url::Origin> request_initiator_;
bool is_partial_request_;
bool completed_;
diff --git a/chromium/components/download/public/common/download_stats.h b/chromium/components/download/public/common/download_stats.h
index 9e72887e191..ffafffa18b8 100644
--- a/chromium/components/download/public/common/download_stats.h
+++ b/chromium/components/download/public/common/download_stats.h
@@ -267,24 +267,13 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadInterrupted(
int64_t total,
bool is_parallelizable,
bool is_parallel_download_enabled,
- DownloadSource download_source,
- bool post_content_length_mismatch);
-
-// Record that a download has been classified as malicious.
-COMPONENTS_DOWNLOAD_EXPORT void RecordMaliciousDownloadClassified(
- DownloadDangerType danger_type);
+ DownloadSource download_source);
// Record a dangerous download accept event.
COMPONENTS_DOWNLOAD_EXPORT void RecordDangerousDownloadAccept(
DownloadDangerType danger_type,
const base::FilePath& file_path);
-// Record a dangerous download discard event.
-COMPONENTS_DOWNLOAD_EXPORT void RecordDangerousDownloadDiscard(
- DownloadDiscardReason reason,
- DownloadDangerType danger_type,
- const base::FilePath& file_path);
-
// Returns the type of download.
COMPONENTS_DOWNLOAD_EXPORT DownloadContent
DownloadContentFromMimeType(const std::string& mime_type_string,
diff --git a/chromium/components/download/public/common/download_url_loader_factory_getter.h b/chromium/components/download/public/common/download_url_loader_factory_getter.h
deleted file mode 100644
index c9aef992c76..00000000000
--- a/chromium/components/download/public/common/download_url_loader_factory_getter.h
+++ /dev/null
@@ -1,57 +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 COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner_helpers.h"
-#include "components/download/public/common/download_export.h"
-
-namespace network {
-class SharedURLLoaderFactory;
-} // namespace network
-
-namespace download {
-
-struct DownloadURLLoaderFactoryGetterDeleter;
-
-// Class for retrieving a URLLoaderFactory on IO thread. This class can be
-// created on any thread and will be destroyed on the IO thread.
-// GetURLLoaderFactory() has to be called on the IO thread.
-class COMPONENTS_DOWNLOAD_EXPORT DownloadURLLoaderFactoryGetter
- : public base::RefCountedThreadSafe<DownloadURLLoaderFactoryGetter,
- DownloadURLLoaderFactoryGetterDeleter> {
- public:
- DownloadURLLoaderFactoryGetter();
-
- // Called on the IO thread to get a URLLoaderFactory.
- virtual scoped_refptr<network::SharedURLLoaderFactory>
- GetURLLoaderFactory() = 0;
-
- protected:
- virtual ~DownloadURLLoaderFactoryGetter();
-
- private:
- friend class base::DeleteHelper<DownloadURLLoaderFactoryGetter>;
- friend class base::RefCountedThreadSafe<
- DownloadURLLoaderFactoryGetter,
- DownloadURLLoaderFactoryGetterDeleter>;
- friend struct DownloadURLLoaderFactoryGetterDeleter;
-
- void DeleteOnCorrectThread() const;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadURLLoaderFactoryGetter);
-};
-
-struct DownloadURLLoaderFactoryGetterDeleter {
- static void Destruct(const DownloadURLLoaderFactoryGetter* factory_getter) {
- factory_getter->DeleteOnCorrectThread();
- }
-};
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_
diff --git a/chromium/components/download/public/common/download_url_loader_factory_getter_impl.h b/chromium/components/download/public/common/download_url_loader_factory_getter_impl.h
deleted file mode 100644
index dcfb250636c..00000000000
--- a/chromium/components/download/public/common/download_url_loader_factory_getter_impl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
-#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
-
-#include "components/download/public/common/download_url_loader_factory_getter.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-namespace download {
-
-// Class for retrieving a fixed SharedURLLoaderFactory.
-class COMPONENTS_DOWNLOAD_EXPORT DownloadURLLoaderFactoryGetterImpl
- : public DownloadURLLoaderFactoryGetter {
- public:
- explicit DownloadURLLoaderFactoryGetterImpl(
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory);
-
- // download::DownloadURLLoaderFactoryGetter implementation.
- scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
-
- protected:
- ~DownloadURLLoaderFactoryGetterImpl() override;
-
- private:
- // Only one of the following two members is ever set. Initially that would be
- // |url_loader_factory_info_|, but after GetURLLoaderFactory is called for the
- // first time instead |url_loader_factory_| will be set. This is safe because
- // GetURLLoaderFactory is always called from the same thread.
- std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_;
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DownloadURLLoaderFactoryGetterImpl);
-};
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_URL_LOADER_FACTORY_GETTER_IMPL_H_
diff --git a/chromium/components/download/public/common/download_url_parameters.cc b/chromium/components/download/public/common/download_url_parameters.cc
index 0c85c8f6a9a..fd465914dc1 100644
--- a/chromium/components/download/public/common/download_url_parameters.cc
+++ b/chromium/components/download/public/common/download_url_parameters.cc
@@ -40,8 +40,7 @@ DownloadUrlParameters::DownloadUrlParameters(
transient_(false),
traffic_annotation_(traffic_annotation),
download_source_(DownloadSource::UNKNOWN),
- require_safety_checks_(true),
- ignore_content_length_mismatch_(false) {}
+ require_safety_checks_(true) {}
DownloadUrlParameters::~DownloadUrlParameters() = default;
diff --git a/chromium/components/download/public/common/download_url_parameters.h b/chromium/components/download/public/common/download_url_parameters.h
index ecbc0aff525..f276eddce7a 100644
--- a/chromium/components/download/public/common/download_url_parameters.h
+++ b/chromium/components/download/public/common/download_url_parameters.h
@@ -257,11 +257,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
require_safety_checks_ = require_safety_checks;
}
- // Sets whether to ignore content length mismatch errors.
- void set_ignore_content_length_mismatch(bool ignore_content_length_mismatch) {
- ignore_content_length_mismatch_ = ignore_content_length_mismatch;
- }
-
const OnStartedCallback& callback() const { return callback_; }
bool content_initiated() const { return content_initiated_; }
const std::string& last_modified() const { return last_modified_; }
@@ -315,9 +310,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
bool is_transient() const { return transient_; }
std::string guid() const { return guid_; }
bool require_safety_checks() const { return require_safety_checks_; }
- bool ignore_content_length_mismatch() const {
- return ignore_content_length_mismatch_;
- }
// STATE CHANGING: All save_info_ sub-objects will be in an indeterminate
// state following this call.
@@ -365,7 +357,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
DownloadSource download_source_;
UploadProgressCallback upload_callback_;
bool require_safety_checks_;
- bool ignore_content_length_mismatch_;
DISALLOW_COPY_AND_ASSIGN(DownloadUrlParameters);
};
diff --git a/chromium/components/download/public/common/download_utils.h b/chromium/components/download/public/common/download_utils.h
index 69f4824e5f7..d48f61ae8ed 100644
--- a/chromium/components/download/public/common/download_utils.h
+++ b/chromium/components/download/public/common/download_utils.h
@@ -39,7 +39,7 @@ using URLSecurityPolicy =
// |cert_status| is ignored if error_code is not net::ERR_ABORTED.
COMPONENTS_DOWNLOAD_EXPORT DownloadInterruptReason
HandleRequestCompletionStatus(net::Error error_code,
- bool ignore_content_length_mismatch,
+ bool has_strong_validators,
net::CertStatus cert_status,
bool is_partial_request,
DownloadInterruptReason abort_reason);
diff --git a/chromium/components/download/public/common/in_progress_download_manager.h b/chromium/components/download/public/common/in_progress_download_manager.h
index 4feb5060ceb..25d2058628b 100644
--- a/chromium/components/download/public/common/in_progress_download_manager.h
+++ b/chromium/components/download/public/common/in_progress_download_manager.h
@@ -14,33 +14,33 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
-#include "build/build_config.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_file_factory.h"
#include "components/download/public/common/download_item_impl_delegate.h"
+#include "components/download/public/common/download_job.h"
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/simple_download_manager.h"
#include "components/download/public/common/url_download_handler.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "url/gurl.h"
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
-
namespace network {
struct ResourceResponse;
+class SharedURLLoaderFactory;
} // namespace network
namespace service_manager {
class Connector;
} // namespace service_manager
+namespace leveldb_proto {
+class ProtoDatabaseProvider;
+} // namespace leveldb_proto
+
namespace download {
class DownloadDBCache;
class DownloadStartObserver;
-class DownloadURLLoaderFactoryGetter;
class DownloadUrlParameters;
struct DownloadDBEntry;
@@ -78,16 +78,15 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
std::unique_ptr<DownloadCreateInfo> info,
const DownloadUrlParameters::OnStartedCallback& on_started,
StartDownloadItemCallback callback) {}
-
- // Gets the URLRequestContextGetter for sending requests.
- // TODO(qinmin): remove this once network service is fully enabled.
- virtual net::URLRequestContextGetter* GetURLRequestContextGetter(
- const DownloadCreateInfo& download_create_info);
};
using IsOriginSecureCallback = base::RepeatingCallback<bool(const GURL&)>;
+ // Creates a new InProgressDownloadManager instance. If |in_progress_db_dir|
+ // is empty then it will use an empty database and no history will be saved.
+ // |db_provider| can be nullptr if |in_progress_db_dir| is empty.
InProgressDownloadManager(Delegate* delegate,
const base::FilePath& in_progress_db_dir,
+ leveldb_proto::ProtoDatabaseProvider* db_provider,
const IsOriginSecureCallback& is_origin_secure_cb,
const URLSecurityPolicy& url_security_policy,
service_manager::Connector* connector);
@@ -101,13 +100,13 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
DownloadItem* GetDownloadByGuid(const std::string& guid) override;
// Called to start a download.
- void BeginDownload(
- std::unique_ptr<DownloadUrlParameters> params,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
- bool is_new_download,
- const GURL& site_url,
- const GURL& tab_url,
- const GURL& tab_referrer_url);
+ void BeginDownload(std::unique_ptr<DownloadUrlParameters> params,
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_info,
+ bool is_new_download,
+ const GURL& site_url,
+ const GURL& tab_url,
+ const GURL& tab_referrer_url);
// Intercepts a download from navigation.
void InterceptDownloadFromNavigation(
@@ -122,12 +121,15 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
scoped_refptr<network::ResourceResponse> response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter);
+ std::unique_ptr<network::SharedURLLoaderFactoryInfo>
+ url_loader_factory_info);
void StartDownload(
std::unique_ptr<DownloadCreateInfo> info,
std::unique_ptr<InputStream> stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
const DownloadUrlParameters::OnStartedCallback& on_started);
// Shutting down the manager and stop all downloads.
@@ -186,9 +188,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
}
DownloadFileFactory* file_factory() { return file_factory_.get(); }
- void set_url_loader_factory_getter(
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter) {
- url_loader_factory_getter_ = std::move(url_loader_factory_getter);
+ void set_url_loader_factory(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+ url_loader_factory_ = url_loader_factory;
}
void SetDelegate(Delegate* delegate);
@@ -203,13 +205,16 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
std::unique_ptr<download::DownloadItemImpl> download);
private:
- void Initialize(const base::FilePath& in_progress_db_dir);
+ void Initialize(const base::FilePath& in_progress_db_dir,
+ leveldb_proto::ProtoDatabaseProvider* db_provider);
// UrlDownloadHandler::Delegate implementations.
void OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> download_create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> shared_url_loader_factory,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ UrlDownloadHandler* downloader,
const DownloadUrlParameters::OnStartedCallback& callback) override;
void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
void OnUrlDownloadHandlerCreated(
@@ -227,7 +232,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// Start a DownloadItemImpl.
void StartDownloadWithItem(
std::unique_ptr<InputStream> stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
std::unique_ptr<DownloadCreateInfo> info,
DownloadItemImpl* download,
bool should_persist_new_download);
@@ -238,6 +245,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// Called to notify |delegate_| that downloads are initialized.
void NotifyDownloadsInitialized();
+ // Cancels the given UrlDownloadHandler.
+ void CancelUrlDownload(UrlDownloadHandler* downloader, bool user_cancel);
+
// Active download handlers.
std::vector<UrlDownloadHandler::UniqueUrlDownloadHandlerPtr>
url_download_handlers_;
@@ -282,9 +292,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// A list of download GUIDs that should not be persisted.
std::set<std::string> non_persistent_download_guids_;
- // URLLoaderFactoryGetter for issuing network request when DownloadMangerImpl
+ // URLLoaderFactory for issuing network request when DownloadManagerImpl
// is not available.
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter_;
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Mapping between download URIs and display names.
// TODO(qinmin): move display name to history and in-progress DB.
diff --git a/chromium/components/download/public/common/input_stream.cc b/chromium/components/download/public/common/input_stream.cc
index 83558fa72fb..33390e7a479 100644
--- a/chromium/components/download/public/common/input_stream.cc
+++ b/chromium/components/download/public/common/input_stream.cc
@@ -10,6 +10,10 @@ InputStream::~InputStream() = default;
void InputStream::Initialize() {}
+bool InputStream::IsEmpty() {
+ return true;
+}
+
void InputStream::RegisterDataReadyCallback(
const mojo::SimpleWatcher::ReadyCallback& callback) {}
@@ -17,4 +21,13 @@ void InputStream::ClearDataReadyCallback() {}
void InputStream::RegisterCompletionCallback(base::OnceClosure callback) {}
+InputStream::StreamState InputStream::Read(scoped_refptr<net::IOBuffer>* data,
+ size_t* length) {
+ return StreamState::EMPTY;
+}
+
+DownloadInterruptReason InputStream::GetCompletionStatus() {
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+}
+
} // namespace download
diff --git a/chromium/components/download/public/common/input_stream.h b/chromium/components/download/public/common/input_stream.h
index 938daba2eb4..87871ea8979 100644
--- a/chromium/components/download/public/common/input_stream.h
+++ b/chromium/components/download/public/common/input_stream.h
@@ -30,7 +30,7 @@ class COMPONENTS_DOWNLOAD_EXPORT InputStream {
virtual void Initialize();
// Returns true if the input stream contains no data, or false otherwise.
- virtual bool IsEmpty() = 0;
+ virtual bool IsEmpty();
// Register/clear callbacks when data become available.
virtual void RegisterDataReadyCallback(
@@ -42,11 +42,10 @@ class COMPONENTS_DOWNLOAD_EXPORT InputStream {
// Reads data from the stream into |data|, |length| is the number of bytes
// returned.
- virtual StreamState Read(scoped_refptr<net::IOBuffer>* data,
- size_t* length) = 0;
+ virtual StreamState Read(scoped_refptr<net::IOBuffer>* data, size_t* length);
// Returns the completion status.
- virtual DownloadInterruptReason GetCompletionStatus() = 0;
+ virtual DownloadInterruptReason GetCompletionStatus();
};
} // namespace download
diff --git a/chromium/components/download/public/common/mock_download_file.h b/chromium/components/download/public/common/mock_download_file.h
index b0a7d25a3aa..585223e493a 100644
--- a/chromium/components/download/public/common/mock_download_file.h
+++ b/chromium/components/download/public/common/mock_download_file.h
@@ -48,13 +48,14 @@ class MockDownloadFile : public DownloadFile {
MOCK_METHOD2(RenameAndUniquify,
void(const base::FilePath& full_path,
const RenameCompletionCallback& callback));
- MOCK_METHOD6(RenameAndAnnotate,
- void(const base::FilePath& full_path,
- const std::string& client_guid,
- const GURL& source_url,
- const GURL& referrer_url,
- std::unique_ptr<service_manager::Connector> connector,
- const RenameCompletionCallback& callback));
+ MOCK_METHOD6(
+ RenameAndAnnotate,
+ void(const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
+ const RenameCompletionCallback& callback));
MOCK_METHOD0(Detach, void());
MOCK_METHOD0(Cancel, void());
MOCK_METHOD1(SetPotentialFileLength, void(int64_t length));
diff --git a/chromium/components/download/public/common/mock_download_item_impl.h b/chromium/components/download/public/common/mock_download_item_impl.h
index 612485d1f7b..8da0c0f6f5b 100644
--- a/chromium/components/download/public/common/mock_download_item_impl.h
+++ b/chromium/components/download/public/common/mock_download_item_impl.h
@@ -14,7 +14,6 @@
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_item_impl.h"
-#include "components/download/public/common/download_request_handle_interface.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/origin.h"
@@ -51,17 +50,15 @@ class MockDownloadItemImpl : public DownloadItemImpl {
NOTREACHED();
}
MOCK_METHOD0(OnDownloadedFileRemoved, void());
- void Start(
- std::unique_ptr<DownloadFile> download_file,
- std::unique_ptr<DownloadRequestHandleInterface> req_handle,
- const DownloadCreateInfo& create_info,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter) override {
- MockStart(download_file.get(), req_handle.get());
+ void Start(std::unique_ptr<DownloadFile> download_file,
+ DownloadJob::CancelRequestCallback cancel_request_callback,
+ const DownloadCreateInfo& create_info,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider) override {
+ MockStart(download_file.get());
}
- MOCK_METHOD2(MockStart, void(DownloadFile*, DownloadRequestHandleInterface*));
+ MOCK_METHOD1(MockStart, void(DownloadFile*));
MOCK_METHOD0(Remove, void());
MOCK_CONST_METHOD1(TimeRemaining, bool(base::TimeDelta*));
diff --git a/chromium/components/download/public/common/quarantine_connection.h b/chromium/components/download/public/common/quarantine_connection.h
new file mode 100644
index 00000000000..f646b29aa0c
--- /dev/null
+++ b/chromium/components/download/public/common/quarantine_connection.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 COMPONENTS_DOWNLOAD_PUBLIC_COMMON_QUARANTINE_CONNECTION_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_QUARANTINE_CONNECTION_H_
+
+#include "base/callback.h"
+#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+
+namespace download {
+
+// A callback which can be used to acquire a connection to a Quarantine
+// Service instance if available.
+using QuarantineConnectionCallback = base::RepeatingCallback<void(
+ mojo::PendingReceiver<quarantine::mojom::Quarantine>)>;
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_QUARANTINE_CONNECTION_H_
diff --git a/chromium/components/download/public/common/url_download_handler.h b/chromium/components/download/public/common/url_download_handler.h
index 79725204200..c2d514914bd 100644
--- a/chromium/components/download/public/common/url_download_handler.h
+++ b/chromium/components/download/public/common/url_download_handler.h
@@ -5,14 +5,13 @@
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_H_
+#include "base/memory/weak_ptr.h"
#include "components/download/public/common/download_export.h"
-#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_url_parameters.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "components/download/public/common/url_loader_factory_provider.h"
namespace download {
struct DownloadCreateInfo;
-class DownloadURLLoaderFactoryGetter;
class InputStream;
// Class for handling the download of a url. Implemented by child classes.
@@ -26,7 +25,9 @@ class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandler {
virtual void OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> download_create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
+ url_loader_factory_provider,
+ UrlDownloadHandler* downloader,
const DownloadUrlParameters::OnStartedCallback& callback) = 0;
// Called after the connection is cancelled or finished.
diff --git a/chromium/components/download/public/common/url_download_handler_factory.h b/chromium/components/download/public/common/url_download_handler_factory.h
index 8b30691e11d..b20def2782e 100644
--- a/chromium/components/download/public/common/url_download_handler_factory.h
+++ b/chromium/components/download/public/common/url_download_handler_factory.h
@@ -9,16 +9,11 @@
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/url_download_handler.h"
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
-
namespace service_manager {
class Connector;
} // namespace service_manager
namespace download {
-class DownloadURLLoaderFactoryGetter;
class DownloadUrlParameters;
// Class for handling the creation of a URLDownloadHandler. This is used to
@@ -26,39 +21,15 @@ class DownloadUrlParameters;
// TODO(qinmin): remove this factory once network service is fully enabled.
class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandlerFactory {
public:
- // Installs a new factory for creating the URLDownloadHandler. Can be called
- // on any thread.
- static void Install(UrlDownloadHandlerFactory* factory);
-
// Creates a URLDownloadHandler. By default the handler is used for network
// service. Must be called on the IO thread.
static UrlDownloadHandler::UniqueUrlDownloadHandlerPtr Create(
std::unique_ptr<download::DownloadUrlParameters> params,
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const URLSecurityPolicy& url_security_policy,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
-
- virtual ~UrlDownloadHandlerFactory();
-
- protected:
- UrlDownloadHandlerFactory();
-
- // To be implemented by child classes to provide their own URLDownloadHandler
- // instances.
- virtual UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
- CreateUrlDownloadHandler(
- std::unique_ptr<download::DownloadUrlParameters> params,
- base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<download::DownloadURLLoaderFactoryGetter>
- url_loader_factory_getter,
- const URLSecurityPolicy& url_security_policy,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
- std::unique_ptr<service_manager::Connector> connector,
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) = 0;
};
} // namespace download
diff --git a/chromium/components/download/public/common/url_download_request_handle.h b/chromium/components/download/public/common/url_download_request_handle.h
index 46c77564efa..6d10c614a93 100644
--- a/chromium/components/download/public/common/url_download_request_handle.h
+++ b/chromium/components/download/public/common/url_download_request_handle.h
@@ -7,26 +7,19 @@
#include "base/memory/weak_ptr.h"
#include "components/download/public/common/download_export.h"
-#include "components/download/public/common/download_request_handle_interface.h"
#include "components/download/public/common/url_download_handler.h"
namespace download {
// Implementation of the DownloadRequestHandleInterface to handle url download.
-class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadRequestHandle
- : public DownloadRequestHandleInterface {
+class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadRequestHandle {
public:
UrlDownloadRequestHandle(
base::WeakPtr<UrlDownloadHandler> downloader,
scoped_refptr<base::SequencedTaskRunner> downloader_task_runner);
UrlDownloadRequestHandle(UrlDownloadRequestHandle&& other);
UrlDownloadRequestHandle& operator=(UrlDownloadRequestHandle&& other);
- ~UrlDownloadRequestHandle() override;
-
- // DownloadRequestHandleInterface
- void PauseRequest() override;
- void ResumeRequest() override;
- void CancelRequest(bool user_cancel) override;
+ ~UrlDownloadRequestHandle();
private:
base::WeakPtr<UrlDownloadHandler> downloader_;
diff --git a/chromium/components/download/public/common/url_loader_factory_provider.h b/chromium/components/download/public/common/url_loader_factory_provider.h
new file mode 100644
index 00000000000..ae04d8f4f8f
--- /dev/null
+++ b/chromium/components/download/public/common/url_loader_factory_provider.h
@@ -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.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_LOADER_FACTORY_PROVIDER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_LOADER_FACTORY_PROVIDER_H_
+
+#include "base/sequenced_task_runner.h"
+#include "components/download/public/common/download_export.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace download {
+
+// Class for wrapping a SharedURLLoaderFactory that can be passed across thread
+// so that it can be used later on IO thread to retrieve the factory to create
+// parallel download requests.
+class COMPONENTS_DOWNLOAD_EXPORT URLLoaderFactoryProvider {
+ public:
+ using URLLoaderFactoryProviderPtr =
+ std::unique_ptr<URLLoaderFactoryProvider, base::OnTaskRunnerDeleter>;
+
+ explicit URLLoaderFactoryProvider(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+ virtual ~URLLoaderFactoryProvider();
+
+ // Called on the io thread to get the URL loader.
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory();
+
+ // Helper method to get an null ptr.
+ static URLLoaderFactoryProviderPtr GetNullPtr();
+
+ private:
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryProvider);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_LOADER_FACTORY_PROVIDER_H_
diff --git a/chromium/components/error_page/common/localized_error.cc b/chromium/components/error_page/common/localized_error.cc
index ea9bf73be71..ec5ca757995 100644
--- a/chromium/components/error_page/common/localized_error.cc
+++ b/chromium/components/error_page/common/localized_error.cc
@@ -283,12 +283,6 @@ const LocalizedErrorMap net_error_options[] = {
SUGGEST_DISABLE_EXTENSION,
SHOW_BUTTON_RELOAD,
},
- {net::ERR_BLOCKED_BY_XSS_AUDITOR,
- IDS_ERRORPAGES_HEADING_PAGE_NOT_WORKING,
- IDS_ERRORPAGES_SUMMARY_BLOCKED_BY_XSS_AUDITOR,
- SUGGEST_NAVIGATE_TO_ORIGIN,
- SHOW_NO_BUTTONS,
- },
{net::ERR_NETWORK_CHANGED,
IDS_ERRORPAGES_HEADING_CONNECTION_INTERRUPTED,
IDS_ERRORPAGES_SUMMARY_NETWORK_CHANGED,
diff --git a/chromium/components/error_page_strings.grdp b/chromium/components/error_page_strings.grdp
index a67082d8a8d..335968db758 100644
--- a/chromium/components/error_page_strings.grdp
+++ b/chromium/components/error_page_strings.grdp
@@ -250,9 +250,6 @@
<message name="IDS_ERRORPAGES_SUMMARY_BLOCKED_BY_EXTENSION" desc="Summary in the error page when an extension blocks a request.">
Requests to the server have been blocked by an extension.
</message>
- <message name="IDS_ERRORPAGES_SUMMARY_BLOCKED_BY_XSS_AUDITOR" desc="Summary in the error page when the XSS Auditor blocks a response.">
- Chrome detected unusual code on this page and blocked it to protect your personal information (for example, passwords, phone numbers, and credit cards).
- </message>
<message name="IDS_ERRORPAGES_SUMMARY_BLOCKED_BY_ADMINISTRATOR" desc="Summary in the error page when an administrator policy blocks a request.">
The person who set up this computer has chosen to block this site.
</message>
diff --git a/chromium/components/exo/BUILD.gn b/chromium/components/exo/BUILD.gn
index e7c77996fbd..e10c21c574a 100644
--- a/chromium/components/exo/BUILD.gn
+++ b/chromium/components/exo/BUILD.gn
@@ -23,6 +23,8 @@ source_set("exo") {
"data_source_observer.h",
"display.cc",
"display.h",
+ "drag_drop_operation.cc",
+ "drag_drop_operation.h",
"frame_sink_resource_manager.cc",
"frame_sink_resource_manager.h",
"input_trace.h",
@@ -71,7 +73,7 @@ source_set("exo") {
"//gpu/command_buffer/client:raster_interface",
"//net",
"//services/data_decoder/public/cpp",
- "//services/viz/privileged/interfaces/compositing",
+ "//services/viz/privileged/mojom/compositing",
"//skia",
"//third_party/blink/public/common",
"//ui/aura",
@@ -126,6 +128,7 @@ source_set("exo") {
}
if (is_chromecast) {
+ deps += [ "//ui/accessibility:accessibility" ]
sources += [
"fullscreen_shell_surface.cc",
"fullscreen_shell_surface.h",
@@ -247,6 +250,7 @@ source_set("unit_tests") {
}
if (is_chromecast) {
+ deps += [ "//ui/accessibility:accessibility" ]
sources += [ "fullscreen_shell_surface_unittest.cc" ]
}
}
diff --git a/chromium/components/exo/DEPS b/chromium/components/exo/DEPS
index d6f0e640c75..3b43545fd6f 100644
--- a/chromium/components/exo/DEPS
+++ b/chromium/components/exo/DEPS
@@ -11,7 +11,7 @@ include_rules = [
"+mojo/public/cpp",
"+net/base",
"+services/data_decoder/public/cpp",
- "+services/viz/privileged/interfaces/compositing/vsync_parameter_observer.mojom.h",
+ "+services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom.h",
"+third_party/blink/public/common",
"+third_party/khronos",
"+third_party/skia",
diff --git a/chromium/components/exo/OWNERS b/chromium/components/exo/OWNERS
index a2f4fac66dd..f21cfe95c4e 100644
--- a/chromium/components/exo/OWNERS
+++ b/chromium/components/exo/OWNERS
@@ -1,3 +1,4 @@
reveman@chromium.org
oshima@chromium.org
dcastagna@chromium.org
+# COMPONENT: Internals>Exosphere
diff --git a/chromium/components/exo/buffer.cc b/chromium/components/exo/buffer.cc
index ff8c613b40f..e13ae845ee5 100644
--- a/chromium/components/exo/buffer.cc
+++ b/chromium/components/exo/buffer.cc
@@ -115,7 +115,7 @@ class Buffer::Texture : public viz::ContextLostObserver {
const base::TimeDelta wait_for_release_delay_;
base::TimeTicks wait_for_release_time_;
bool wait_for_release_pending_ = false;
- base::WeakPtrFactory<Texture> weak_ptr_factory_;
+ base::WeakPtrFactory<Texture> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Texture);
};
@@ -127,8 +127,7 @@ Buffer::Texture::Texture(
size_(size),
context_provider_(std::move(context_provider)),
texture_target_(GL_TEXTURE_2D),
- query_type_(GL_COMMANDS_COMPLETED_CHROMIUM),
- weak_ptr_factory_(this) {
+ query_type_(GL_COMMANDS_COMPLETED_CHROMIUM) {
gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
const uint32_t usage =
gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_DISPLAY;
@@ -155,8 +154,7 @@ Buffer::Texture::Texture(
context_provider_(std::move(context_provider)),
texture_target_(texture_target),
query_type_(query_type),
- wait_for_release_delay_(wait_for_release_delay),
- weak_ptr_factory_(this) {
+ wait_for_release_delay_(wait_for_release_delay) {
gpu::SharedImageInterface* sii = context_provider_->SharedImageInterface();
const uint32_t usage = gpu::SHARED_IMAGE_USAGE_RASTER |
gpu::SHARED_IMAGE_USAGE_DISPLAY |
diff --git a/chromium/components/exo/client_controlled_shell_surface.cc b/chromium/components/exo/client_controlled_shell_surface.cc
index 77a07221861..11873626d61 100644
--- a/chromium/components/exo/client_controlled_shell_surface.cc
+++ b/chromium/components/exo/client_controlled_shell_surface.cc
@@ -92,17 +92,9 @@ class ClientControlledStateDelegate
ash::WindowStateType requested_state,
const gfx::Rect& bounds_in_display,
int64_t display_id) override {
- const display::Screen* screen = display::Screen::GetScreen();
- display::Display target_display;
- if (!screen->GetDisplayWithDisplayId(display_id, &target_display))
- return;
-
- gfx::Rect bounds_in_screen(bounds_in_display);
- bounds_in_screen.Offset(target_display.bounds().OffsetFromOrigin());
-
shell_surface_->OnBoundsChangeEvent(
window_state->GetStateType(), requested_state, display_id,
- bounds_in_screen,
+ bounds_in_display,
window_state->drag_details() && shell_surface_->IsDragging()
? window_state->drag_details()->bounds_change
: 0);
@@ -396,14 +388,7 @@ void ClientControlledShellSurface::SetSystemUiVisibility(bool autohide) {
void ClientControlledShellSurface::SetAlwaysOnTop(bool always_on_top) {
TRACE_EVENT1("exo", "ClientControlledShellSurface::SetAlwaysOnTop",
"always_on_top", always_on_top);
-
- if (!widget_)
- CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL);
-
- widget_->GetNativeWindow()->SetProperty(aura::client::kZOrderingKey,
- always_on_top
- ? ui::ZOrderLevel::kFloatingWindow
- : ui::ZOrderLevel::kNormal);
+ pending_always_on_top_ = always_on_top;
}
void ClientControlledShellSurface::SetImeBlocked(bool ime_blocked) {
@@ -693,8 +678,14 @@ void ClientControlledShellSurface::OnSetFrameColors(SkColor active_color,
void ClientControlledShellSurface::OnWindowAddedToRootWindow(
aura::Window* window) {
- if (client_controlled_state_->set_bounds_locally())
+ // Window dragging across display moves the window to target display when
+ // dropped, but the actual window bounds comes later from android. Update the
+ // window bounds now so that the window stays where it is expected to be. (it
+ // may still move if the android sends different bounds).
+ if (client_controlled_state_->set_bounds_locally() ||
+ !GetWindowState()->is_dragged()) {
return;
+ }
ScopedLockedToRoot scoped_locked_to_root(widget_);
UpdateWidgetBounds();
@@ -811,8 +802,6 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
display::Display display;
if (screen->GetDisplayWithDisplayId(display_id_, &display)) {
bool is_display_stale = display_id_ != current_display.id();
- LOG(ERROR) << "DisplayId:" << display_id_
- << ", current:" << current_display.id();
// Preserve widget bounds until client acknowledges display move.
if (preserve_widget_bounds_ && is_display_stale)
@@ -846,7 +835,6 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
bool set_bounds_locally =
GetWindowState()->is_dragged() && !is_display_move_pending;
- LOG(ERROR) << "Updating Locally";
if (set_bounds_locally || client_controlled_state_->set_bounds_locally()) {
// Convert from screen to display coordinates.
@@ -861,7 +849,6 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
UpdateSurfaceBounds();
return;
}
- LOG(ERROR) << "Updating Remotely";
{
ScopedSetBoundsLocally scoped_set_bounds(this);
@@ -869,12 +856,15 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
}
if (bounds != adjusted_bounds || is_display_move_pending) {
- LOG(ERROR) << "Sending Bounds:" << bounds.ToString()
- << ", adjusted=" << adjusted_bounds.ToString();
// Notify client that bounds were adjusted or window moved across displays.
auto state_type = GetWindowState()->GetStateType();
+ gfx::Rect adjusted_bounds_in_display(adjusted_bounds);
+
+ adjusted_bounds_in_display.Offset(
+ -target_display.bounds().OffsetFromOrigin());
+
OnBoundsChangeEvent(state_type, state_type, target_display.id(),
- adjusted_bounds, 0);
+ adjusted_bounds_in_display, 0);
}
UpdateSurfaceBounds();
@@ -902,8 +892,10 @@ void ClientControlledShellSurface::InitializeWindowState(
// when maximized, or the entire display when fullscreen.
window_state->set_allow_set_bounds_direct(true);
window_state->set_ignore_keyboard_bounds_change(true);
- if (container_ == ash::kShellWindowId_SystemModalContainer)
+ if (container_ == ash::kShellWindowId_SystemModalContainer ||
+ container_ == ash::kShellWindowId_ArcVirtualKeyboardContainer) {
DisableMovement();
+ }
ash::NonClientFrameViewAsh* frame_view = GetFrameView();
frame_view->SetCaptionButtonModel(std::make_unique<CaptionButtonModel>(
frame_visible_button_mask_, frame_enabled_button_mask_));
@@ -1032,6 +1024,12 @@ void ClientControlledShellSurface::OnPostWidgetCommit() {
orientation_ = pending_orientation_;
if (expected_orientation_ == orientation_)
orientation_compositor_lock_.reset();
+
+ widget_->GetNativeWindow()->SetProperty(aura::client::kZOrderingKey,
+ pending_always_on_top_
+ ? ui::ZOrderLevel::kFloatingWindow
+ : ui::ZOrderLevel::kNormal);
+
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/components/exo/client_controlled_shell_surface.h b/chromium/components/exo/client_controlled_shell_surface.h
index 3fccb24a28c..749d6549bd1 100644
--- a/chromium/components/exo/client_controlled_shell_surface.h
+++ b/chromium/components/exo/client_controlled_shell_surface.h
@@ -95,7 +95,7 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
base::RepeatingCallback<void(ash::WindowStateType current_state,
ash::WindowStateType requested_state,
int64_t display_id,
- const gfx::Rect& bounds,
+ const gfx::Rect& bounds_in_display,
bool is_resize,
int bounds_change)>;
void set_bounds_changed_callback(
@@ -302,6 +302,8 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
ash::WindowStateType pending_window_state_ = ash::WindowStateType::kNormal;
+ bool pending_always_on_top_ = false;
+
ash::WindowPinType current_pin_;
bool can_maximize_ = true;
diff --git a/chromium/components/exo/client_controlled_shell_surface_unittest.cc b/chromium/components/exo/client_controlled_shell_surface_unittest.cc
index 4749a904dce..9dbfb03933a 100644
--- a/chromium/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/chromium/components/exo/client_controlled_shell_surface_unittest.cc
@@ -1280,18 +1280,10 @@ class ClientControlledShellSurfaceDisplayTest : public test::ExoTestBase {
ash::WindowStateType current_state,
ash::WindowStateType requested_state,
int64_t display_id,
- const gfx::Rect& bounds_in_screen,
+ const gfx::Rect& bounds_in_display,
bool is_resize,
int bounds_change) {
bounds_change_count_++;
-
- display::Display target_display;
- const display::Screen* screen = display::Screen::GetScreen();
-
- ASSERT_TRUE(screen->GetDisplayWithDisplayId(display_id, &target_display));
- gfx::Rect bounds_in_display(bounds_in_screen);
- bounds_in_display.Offset(-target_display.bounds().OffsetFromOrigin());
-
requested_bounds_.push_back(bounds_in_display);
requested_display_ids_.push_back(display_id);
}
@@ -1351,6 +1343,11 @@ TEST_F(ClientControlledShellSurfaceDisplayTest, MoveToAnotherDisplayByDrag) {
// Drag the pointer to the right. Once it reaches the right edge of the
// primary display, it warps to the secondary.
+ display::Display secondary_display =
+ display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]);
+ // TODO(crbug.com/990589): Unit tests should be able to simulate mouse input
+ // without having to call |CursorManager::SetDisplay|.
+ ash::Shell::Get()->cursor_manager()->SetDisplay(secondary_display);
resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0);
shell_surface->set_bounds_changed_callback(base::BindRepeating(
@@ -1367,8 +1364,6 @@ TEST_F(ClientControlledShellSurfaceDisplayTest, MoveToAnotherDisplayByDrag) {
EXPECT_EQ(gfx::Rect(-150, 10, 200, 200), requested_bounds()[0]);
EXPECT_EQ(gfx::Rect(-150, 10, 200, 200), requested_bounds()[1]);
- display::Display secondary_display =
- display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]);
EXPECT_EQ(secondary_display.id(), requested_display_ids()[0]);
EXPECT_EQ(secondary_display.id(), requested_display_ids()[1]);
}
diff --git a/chromium/components/exo/data_device.cc b/chromium/components/exo/data_device.cc
index 980dc5e079c..e93d7352196 100644
--- a/chromium/components/exo/data_device.cc
+++ b/chromium/components/exo/data_device.cc
@@ -4,9 +4,9 @@
#include "components/exo/data_device.h"
-#include "base/logging.h"
#include "components/exo/data_device_delegate.h"
#include "components/exo/data_offer.h"
+#include "components/exo/data_source.h"
#include "components/exo/seat.h"
#include "components/exo/surface.h"
#include "ui/base/clipboard/clipboard.h"
@@ -16,38 +16,6 @@
namespace exo {
-class ScopedDataOffer {
- public:
- ScopedDataOffer(DataOffer* data_offer, DataOfferObserver* observer)
- : data_offer_(data_offer), observer_(observer) {
- data_offer_->AddObserver(observer_);
- }
- ~ScopedDataOffer() { data_offer_->RemoveObserver(observer_); }
- DataOffer* get() { return data_offer_; }
-
- private:
- DataOffer* const data_offer_;
- DataOfferObserver* const observer_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedDataOffer);
-};
-
-class ScopedSurface {
- public:
- ScopedSurface(Surface* surface, SurfaceObserver* observer)
- : surface_(surface), observer_(observer) {
- surface_->AddSurfaceObserver(observer_);
- }
- ~ScopedSurface() { surface_->RemoveSurfaceObserver(observer_); }
- Surface* get() { return surface_; }
-
- private:
- Surface* const surface_;
- SurfaceObserver* const observer_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedSurface);
-};
-
DataDevice::DataDevice(DataDeviceDelegate* delegate,
Seat* seat,
FileHelper* file_helper)
@@ -69,12 +37,11 @@ DataDevice::~DataDevice() {
seat_->RemoveObserver(this);
}
-void DataDevice::StartDrag(const DataSource* source_resource,
- Surface* origin_resource,
- Surface* icon_resource,
- uint32_t serial) {
- // TODO(hirono): Check if serial is valid. crbug.com/746111
- NOTIMPLEMENTED();
+void DataDevice::StartDrag(DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source) {
+ seat_->StartDrag(source, origin, icon, event_source);
}
void DataDevice::SetSelection(DataSource* source, uint32_t serial) {
diff --git a/chromium/components/exo/data_device.h b/chromium/components/exo/data_device.h
index 66ecaa63e1f..7993f812e89 100644
--- a/chromium/components/exo/data_device.h
+++ b/chromium/components/exo/data_device.h
@@ -12,8 +12,8 @@
#include "components/exo/seat_observer.h"
#include "components/exo/surface.h"
#include "components/exo/surface_observer.h"
-#include "components/exo/wm_helper.h"
#include "ui/base/clipboard/clipboard_observer.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
namespace ui {
class DropTargetEvent;
@@ -23,15 +23,14 @@ namespace exo {
class DataDeviceDelegate;
class DataOffer;
+class ScopedDataOffer;
class DataSource;
class FileHelper;
class Seat;
+class ScopedSurface;
enum class DndAction { kNone, kCopy, kMove, kAsk };
-class ScopedDataOffer;
-class ScopedSurface;
-
// DataDevice to start drag and drop and copy and paste oprations.
class DataDevice : public WMHelper::DragDropObserver,
public DataOfferObserver,
@@ -51,10 +50,10 @@ class DataDevice : public WMHelper::DragDropObserver,
// nullable image which is rendered at the next to cursor while drag
// operation. |serial| is the unique number comes from input events which
// triggers the drag and drop operation.
- void StartDrag(const DataSource* source,
+ void StartDrag(DataSource* source,
Surface* origin,
Surface* icon,
- uint32_t serial);
+ ui::DragDropTypes::DragEventSource event_source);
// Sets selection data to the clipboard.
// |source| represents data comes from the client. |serial| is the unique
@@ -80,6 +79,8 @@ class DataDevice : public WMHelper::DragDropObserver,
// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
+ DataDeviceDelegate* get_delegate() { return delegate_; }
+
private:
Surface* GetEffectiveTargetForEvent(const ui::DropTargetEvent& event) const;
void SetSelectionToCurrentClipboardData();
diff --git a/chromium/components/exo/data_offer.cc b/chromium/components/exo/data_offer.cc
index f288f40c570..eff37d390dc 100644
--- a/chromium/components/exo/data_offer.cc
+++ b/chromium/components/exo/data_offer.cc
@@ -8,6 +8,7 @@
#include "base/files/file_util.h"
#include "base/i18n/icu_string_conversions.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
@@ -19,8 +20,8 @@
#include "third_party/skia/include/core/SkImageEncoder.h"
#include "third_party/skia/include/core/SkStream.h"
#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/clipboard/clipboard_buffer.h"
#include "ui/base/clipboard/clipboard_constants.h"
-#include "ui/base/clipboard/clipboard_types.h"
#include "ui/base/dragdrop/file_info.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "url/gurl.h"
@@ -73,8 +74,9 @@ void WriteFileDescriptorOnWorkerThread(
void WriteFileDescriptor(base::ScopedFD fd,
scoped_refptr<base::RefCountedMemory> memory) {
- base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&WriteFileDescriptorOnWorkerThread, std::move(fd),
std::move(memory)));
}
@@ -107,35 +109,35 @@ ui::ClipboardFormatType GetClipboardFormatType() {
return *format_type;
}
-void ReadTextFromClipboard(const std::string& charset, base::ScopedFD fd) {
- base::string16 text;
+scoped_refptr<base::RefCountedString> EncodeAsRefCountedString(
+ const base::string16& text,
+ const std::string& charset) {
std::string encoded_text;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
- &text);
base::UTF16ToCodepage(text, charset.c_str(),
base::OnStringConversionError::SUBSTITUTE,
&encoded_text);
- WriteFileDescriptor(std::move(fd),
- base::RefCountedString::TakeString(&encoded_text));
+ return base::RefCountedString::TakeString(&encoded_text);
+}
+
+void ReadTextFromClipboard(const std::string& charset, base::ScopedFD fd) {
+ base::string16 text;
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &text);
+ WriteFileDescriptor(std::move(fd), EncodeAsRefCountedString(text, charset));
}
void ReadHTMLFromClipboard(const std::string& charset, base::ScopedFD fd) {
base::string16 text;
std::string url;
uint32_t start, end;
- std::string encoded_text;
- ui::Clipboard::GetForCurrentThread()->ReadHTML(ui::ClipboardType::kCopyPaste,
- &text, &url, &start, &end);
- base::UTF16ToCodepage(text, charset.c_str(),
- base::OnStringConversionError::SUBSTITUTE,
- &encoded_text);
- WriteFileDescriptor(std::move(fd),
- base::RefCountedString::TakeString(&encoded_text));
+ ui::Clipboard::GetForCurrentThread()->ReadHTML(
+ ui::ClipboardBuffer::kCopyPaste, &text, &url, &start, &end);
+ WriteFileDescriptor(std::move(fd), EncodeAsRefCountedString(text, charset));
}
void ReadRTFFromClipboard(base::ScopedFD fd) {
std::string text;
- ui::Clipboard::GetForCurrentThread()->ReadRTF(ui::ClipboardType::kCopyPaste,
+ ui::Clipboard::GetForCurrentThread()->ReadRTF(ui::ClipboardBuffer::kCopyPaste,
&text);
WriteFileDescriptor(std::move(fd), base::RefCountedString::TakeString(&text));
}
@@ -155,17 +157,28 @@ void SendAsPNGOnWorkerThread(base::ScopedFD fd, const SkBitmap sk_bitmap) {
void ReadPNGFromClipboard(base::ScopedFD fd) {
const SkBitmap sk_bitmap = ui::Clipboard::GetForCurrentThread()->ReadImage(
- ui::ClipboardType::kCopyPaste);
- base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ ui::ClipboardBuffer::kCopyPaste);
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&SendAsPNGOnWorkerThread, std::move(fd),
std::move(sk_bitmap)));
}
} // namespace
+ScopedDataOffer::ScopedDataOffer(DataOffer* data_offer,
+ DataOfferObserver* observer)
+ : data_offer_(data_offer), observer_(observer) {
+ data_offer_->AddObserver(observer_);
+}
+
+ScopedDataOffer::~ScopedDataOffer() {
+ data_offer_->RemoveObserver(observer_);
+}
+
DataOffer::DataOffer(DataOfferDelegate* delegate, Purpose purpose)
- : delegate_(delegate), purpose_(purpose), weak_ptr_factory_(this) {}
+ : delegate_(delegate), purpose_(purpose) {}
DataOffer::~DataOffer() {
delegate_->OnDataOfferDestroying(this);
@@ -254,11 +267,37 @@ void DataOffer::SetDropData(FileHelper* file_helper,
base::string16 string_content;
if (data.HasString() && data.GetString(&string_content)) {
- const std::string text_mime_type = std::string(ui::kMimeTypeText);
- data_.emplace(text_mime_type,
- RefCountedString16::TakeString(std::move(string_content)));
- delegate_->OnOffer(text_mime_type);
- return;
+ const std::string utf8_mime_type = std::string(kTextMimeTypeUtf8);
+ data_.emplace(utf8_mime_type,
+ EncodeAsRefCountedString(string_content, kUTF8));
+ delegate_->OnOffer(utf8_mime_type);
+ const std::string utf16_mime_type = std::string(kTextMimeTypeUtf16);
+ data_.emplace(utf16_mime_type,
+ EncodeAsRefCountedString(string_content, kUTF16));
+ delegate_->OnOffer(utf16_mime_type);
+ const std::string text_plain_mime_type = std::string(ui::kMimeTypeText);
+ // The MIME type standard says that new text/ subtypes should default to a
+ // UTF-8 encoding, but that old ones, including text/plain, keep ASCII as
+ // the default. Nonetheless, we use UTF8 here because it is a superset of
+ // ASCII and the defacto standard text encoding.
+ data_.emplace(text_plain_mime_type,
+ EncodeAsRefCountedString(string_content, kUTF8));
+ delegate_->OnOffer(text_plain_mime_type);
+ }
+
+ base::string16 html_content;
+ GURL url_content;
+ if (data.HasHtml() && data.GetHtml(&html_content, &url_content)) {
+ const std::string utf8_html_mime_type = std::string(kTextHtmlMimeTypeUtf8);
+ data_.emplace(utf8_html_mime_type,
+ EncodeAsRefCountedString(html_content, kUTF8));
+ delegate_->OnOffer(utf8_html_mime_type);
+
+ const std::string utf16_html_mime_type =
+ std::string(kTextHtmlMimeTypeUtf16);
+ data_.emplace(utf16_html_mime_type,
+ EncodeAsRefCountedString(html_content, kUTF16));
+ delegate_->OnOffer(utf16_html_mime_type);
}
}
@@ -266,7 +305,7 @@ void DataOffer::SetClipboardData(FileHelper* file_helper,
const ui::Clipboard& data) {
DCHECK_EQ(0u, data_.size());
if (data.IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextWType(),
- ui::ClipboardType::kCopyPaste)) {
+ ui::ClipboardBuffer::kCopyPaste)) {
auto utf8_callback =
base::BindRepeating(&ReadTextFromClipboard, std::string(kUTF8));
delegate_->OnOffer(std::string(kTextMimeTypeUtf8));
@@ -279,7 +318,7 @@ void DataOffer::SetClipboardData(FileHelper* file_helper,
base::BindRepeating(&ReadTextFromClipboard, std::string(kUTF16)));
}
if (data.IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(),
- ui::ClipboardType::kCopyPaste)) {
+ ui::ClipboardBuffer::kCopyPaste)) {
delegate_->OnOffer(std::string(kTextHtmlMimeTypeUtf8));
data_callbacks_.emplace(
std::string(kTextHtmlMimeTypeUtf8),
@@ -290,13 +329,13 @@ void DataOffer::SetClipboardData(FileHelper* file_helper,
base::BindRepeating(&ReadHTMLFromClipboard, std::string(kUTF16)));
}
if (data.IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(),
- ui::ClipboardType::kCopyPaste)) {
+ ui::ClipboardBuffer::kCopyPaste)) {
delegate_->OnOffer(std::string(kTextRtfMimeType));
data_callbacks_.emplace(std::string(kTextRtfMimeType),
base::BindRepeating(&ReadRTFFromClipboard));
}
if (data.IsFormatAvailable(ui::ClipboardFormatType::GetBitmapType(),
- ui::ClipboardType::kCopyPaste)) {
+ ui::ClipboardBuffer::kCopyPaste)) {
delegate_->OnOffer(std::string(kImagePngMimeType));
data_callbacks_.emplace(std::string(kImagePngMimeType),
base::BindRepeating(&ReadPNGFromClipboard));
diff --git a/chromium/components/exo/data_offer.h b/chromium/components/exo/data_offer.h
index 25b7c3098df..1086d53158c 100644
--- a/chromium/components/exo/data_offer.h
+++ b/chromium/components/exo/data_offer.h
@@ -42,7 +42,7 @@ class DataOffer final : public ui::PropertyHandler {
};
DataOffer(DataOfferDelegate* delegate, Purpose purpose);
- ~DataOffer();
+ ~DataOffer() override;
void AddObserver(DataOfferObserver* observer);
void RemoveObserver(DataOfferObserver* observer);
@@ -105,11 +105,24 @@ class DataOffer final : public ui::PropertyHandler {
base::ObserverList<DataOfferObserver>::Unchecked observers_;
Purpose purpose_;
- base::WeakPtrFactory<DataOffer> weak_ptr_factory_;
+ base::WeakPtrFactory<DataOffer> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DataOffer);
};
+class ScopedDataOffer {
+ public:
+ ScopedDataOffer(DataOffer* data_offer, DataOfferObserver* observer);
+ ~ScopedDataOffer();
+ DataOffer* get() { return data_offer_; }
+
+ private:
+ DataOffer* const data_offer_;
+ DataOfferObserver* const observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDataOffer);
+};
+
} // namespace exo
#endif // COMPONENTS_EXO_DATA_OFFER_H_
diff --git a/chromium/components/exo/data_offer_unittest.cc b/chromium/components/exo/data_offer_unittest.cc
index 3b815ac8efc..162d36aa3f3 100644
--- a/chromium/components/exo/data_offer_unittest.cc
+++ b/chromium/components/exo/data_offer_unittest.cc
@@ -144,14 +144,57 @@ TEST_F(DataOfferTest, SetTextDropData) {
data_offer.SetSourceActions(source_actions);
data_offer.SetActions(base::flat_set<DndAction>(), DndAction::kMove);
- EXPECT_EQ(1u, delegate.mime_types().size());
- EXPECT_EQ(1u, delegate.mime_types().count("text/plain"));
+ EXPECT_EQ(1u, delegate.mime_types().count("text/plain;charset=utf-8"));
+ EXPECT_EQ(1u, delegate.mime_types().count("text/plain;charset=utf-16"));
EXPECT_EQ(2u, delegate.source_actions().size());
EXPECT_EQ(1u, delegate.source_actions().count(DndAction::kCopy));
EXPECT_EQ(1u, delegate.source_actions().count(DndAction::kMove));
EXPECT_EQ(DndAction::kMove, delegate.dnd_action());
}
+TEST_F(DataOfferTest, SetHTMLDropData) {
+ const std::string html_data = "Test HTML data 🔥 ❄";
+
+ base::flat_set<DndAction> source_actions;
+ source_actions.insert(DndAction::kCopy);
+ source_actions.insert(DndAction::kMove);
+
+ ui::OSExchangeData data;
+ data.SetHtml(base::UTF8ToUTF16(html_data), GURL());
+
+ TestDataOfferDelegate delegate;
+ DataOffer data_offer(&delegate, DataOffer::Purpose::DRAG_DROP);
+
+ EXPECT_EQ(0u, delegate.mime_types().size());
+ EXPECT_EQ(0u, delegate.source_actions().size());
+ EXPECT_EQ(DndAction::kNone, delegate.dnd_action());
+
+ TestFileHelper file_helper;
+ data_offer.SetDropData(&file_helper, data);
+ data_offer.SetSourceActions(source_actions);
+ data_offer.SetActions(base::flat_set<DndAction>(), DndAction::kMove);
+
+ EXPECT_EQ(1u, delegate.mime_types().count("text/html;charset=utf-8"));
+ EXPECT_EQ(1u, delegate.mime_types().count("text/html;charset=utf-16"));
+ EXPECT_EQ(2u, delegate.source_actions().size());
+ EXPECT_EQ(1u, delegate.source_actions().count(DndAction::kCopy));
+ EXPECT_EQ(1u, delegate.source_actions().count(DndAction::kMove));
+ EXPECT_EQ(DndAction::kMove, delegate.dnd_action());
+
+ base::ScopedFD read, write;
+ std::string result;
+ EXPECT_TRUE(base::CreatePipe(&read, &write));
+ data_offer.Receive("text/html;charset=utf-8", std::move(write));
+ ReadString(std::move(read), &result);
+ EXPECT_EQ(result, html_data);
+
+ base::string16 result16;
+ EXPECT_TRUE(base::CreatePipe(&read, &write));
+ data_offer.Receive("text/html;charset=utf-16", std::move(write));
+ ReadString16(std::move(read), &result16);
+ EXPECT_EQ(result16, base::UTF8ToUTF16(html_data));
+}
+
TEST_F(DataOfferTest, SetFileDropData) {
TestDataOfferDelegate delegate;
DataOffer data_offer(&delegate, DataOffer::Purpose::DRAG_DROP);
@@ -199,9 +242,51 @@ TEST_F(DataOfferTest, ReceiveString) {
ASSERT_TRUE(base::CreatePipe(&read_pipe, &write_pipe));
data_offer.Receive("text/plain", std::move(write_pipe));
- base::string16 result;
- ASSERT_TRUE(ReadString16(std::move(read_pipe), &result));
- EXPECT_EQ(base::ASCIIToUTF16("Test data"), result);
+ std::string result;
+ ASSERT_TRUE(ReadString(std::move(read_pipe), &result));
+ EXPECT_EQ("Test data", result);
+
+ base::ScopedFD read_pipe_16;
+ base::ScopedFD write_pipe_16;
+ ASSERT_TRUE(base::CreatePipe(&read_pipe_16, &write_pipe_16));
+ data_offer.Receive("text/plain;charset=utf-16", std::move(write_pipe_16));
+ base::string16 result_16;
+ ASSERT_TRUE(ReadString16(std::move(read_pipe_16), &result_16));
+ EXPECT_EQ(base::ASCIIToUTF16("Test data"), result_16);
+
+ base::ScopedFD read_pipe_8;
+ base::ScopedFD write_pipe_8;
+ ASSERT_TRUE(base::CreatePipe(&read_pipe_8, &write_pipe_8));
+ data_offer.Receive("text/plain;charset=utf-8", std::move(write_pipe_8));
+ std::string result_8;
+ ASSERT_TRUE(ReadString(std::move(read_pipe_8), &result_8));
+ EXPECT_EQ("Test data", result_8);
+}
+
+TEST_F(DataOfferTest, ReceiveHTML) {
+ TestDataOfferDelegate delegate;
+ DataOffer data_offer(&delegate, DataOffer::Purpose::DRAG_DROP);
+
+ TestFileHelper file_helper;
+ ui::OSExchangeData data;
+ data.SetHtml(base::ASCIIToUTF16("Test HTML data"), GURL());
+ data_offer.SetDropData(&file_helper, data);
+
+ base::ScopedFD read_pipe_16;
+ base::ScopedFD write_pipe_16;
+ ASSERT_TRUE(base::CreatePipe(&read_pipe_16, &write_pipe_16));
+ data_offer.Receive("text/html;charset=utf-16", std::move(write_pipe_16));
+ base::string16 result_16;
+ ASSERT_TRUE(ReadString16(std::move(read_pipe_16), &result_16));
+ EXPECT_EQ(base::ASCIIToUTF16("Test HTML data"), result_16);
+
+ base::ScopedFD read_pipe_8;
+ base::ScopedFD write_pipe_8;
+ ASSERT_TRUE(base::CreatePipe(&read_pipe_8, &write_pipe_8));
+ data_offer.Receive("text/html;charset=utf-8", std::move(write_pipe_8));
+ std::string result_8;
+ ASSERT_TRUE(ReadString(std::move(read_pipe_8), &result_8));
+ EXPECT_EQ("Test HTML data", result_8);
}
TEST_F(DataOfferTest, ReceiveUriList) {
@@ -346,7 +431,7 @@ TEST_F(DataOfferTest, SetClipboardDataPlainText) {
TestFileHelper file_helper;
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteText(base::UTF8ToUTF16("Test data"));
}
data_offer.SetClipboardData(&file_helper,
@@ -379,7 +464,7 @@ TEST_F(DataOfferTest, SetClipboardDataHTML) {
TestFileHelper file_helper;
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteHTML(base::UTF8ToUTF16("Test data"), "");
}
data_offer.SetClipboardData(&file_helper,
@@ -411,7 +496,7 @@ TEST_F(DataOfferTest, SetClipboardDataRTF) {
TestFileHelper file_helper;
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteRTF("Test data");
}
data_offer.SetClipboardData(&file_helper,
diff --git a/chromium/components/exo/data_source.cc b/chromium/components/exo/data_source.cc
index f4390c6234f..e25c6df5fc3 100644
--- a/chromium/components/exo/data_source.cc
+++ b/chromium/components/exo/data_source.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/i18n/character_encoding.h"
+#include "base/i18n/icu_string_conversions.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
@@ -18,6 +19,7 @@
#include "components/exo/mime_utils.h"
#include "net/base/mime_util.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/icu/source/common/unicode/ucnv.h"
namespace exo {
@@ -30,8 +32,12 @@ constexpr char kTextHTML[] = "text/html";
constexpr char kUtfPrefix[] = "UTF";
constexpr char kEncoding16[] = "16";
constexpr char kEncodingASCII[] = "ASCII";
-constexpr char kEncodingUTF8Legacy[] = "UTF8_STRING";
-constexpr char kEncodingUTF8Charset[] = "UTF-8";
+
+constexpr char kUTF16Unspecified[] = "UTF-16";
+constexpr char kUTF16LittleEndian[] = "UTF-16LE";
+constexpr char kUTF16BigEndian[] = "UTF-16BE";
+constexpr uint8_t kByteOrderMark[] = {0xFE, 0xFF};
+constexpr int kByteOrderMarkSize = sizeof(kByteOrderMark);
constexpr char kImageBitmap[] = "image/bmp";
constexpr char kImagePNG[] = "image/png";
@@ -92,6 +98,38 @@ int GetImageTypeRank(const std::string& mime_type) {
return 2;
}
+base::string16 CodepageToUTF16(const std::vector<uint8_t>& data,
+ const std::string& charset_input) {
+ base::string16 output;
+ base::StringPiece piece(reinterpret_cast<const char*>(data.data()),
+ data.size());
+ const char* charset = charset_input.c_str();
+
+ // Despite claims in the documentation to the contrary, the ICU UTF-16
+ // converter does not automatically detect and interpret the byte order
+ // mark. Therefore, we must do this ourselves.
+ if (!ucnv_compareNames(charset, kUTF16Unspecified) &&
+ data.size() >= kByteOrderMarkSize) {
+ if (static_cast<uint8_t>(piece.data()[0]) == kByteOrderMark[0] &&
+ static_cast<uint8_t>(piece.data()[1]) == kByteOrderMark[1]) {
+ // BOM is in big endian format. Consume the BOM so it doesn't get
+ // interpreted as a character.
+ piece.remove_prefix(2);
+ charset = kUTF16BigEndian;
+ } else if (static_cast<uint8_t>(piece.data()[0]) == kByteOrderMark[1] &&
+ static_cast<uint8_t>(piece.data()[1]) == kByteOrderMark[0]) {
+ // BOM is in little endian format. Consume the BOM so it doesn't get
+ // interpreted as a character.
+ piece.remove_prefix(2);
+ charset = kUTF16LittleEndian;
+ }
+ }
+
+ base::CodepageToUTF16(
+ piece, charset, base::OnStringConversionError::Type::SUBSTITUTE, &output);
+ return output;
+}
+
} // namespace
ScopedDataSource::ScopedDataSource(DataSource* data_source,
@@ -105,9 +143,7 @@ ScopedDataSource::~ScopedDataSource() {
}
DataSource::DataSource(DataSourceDelegate* delegate)
- : delegate_(delegate),
- cancelled_(false),
- read_data_weak_ptr_factory_(this) {}
+ : delegate_(delegate), finished_(false) {}
DataSource::~DataSource() {
delegate_->OnDataSourceDestroying(this);
@@ -129,15 +165,33 @@ void DataSource::Offer(const std::string& mime_type) {
}
void DataSource::SetActions(const base::flat_set<DndAction>& dnd_actions) {
- NOTIMPLEMENTED();
+ dnd_actions_ = dnd_actions;
+}
+
+void DataSource::Target(const base::Optional<std::string>& mime_type) {
+ delegate_->OnTarget(mime_type);
+}
+
+void DataSource::Action(DndAction action) {
+ delegate_->OnAction(action);
+}
+
+void DataSource::DndDropPerformed() {
+ delegate_->OnDndDropPerformed();
}
void DataSource::Cancelled() {
- cancelled_ = true;
+ finished_ = true;
read_data_weak_ptr_factory_.InvalidateWeakPtrs();
delegate_->OnCancelled();
}
+void DataSource::DndFinished() {
+ finished_ = true;
+ read_data_weak_ptr_factory_.InvalidateWeakPtrs();
+ delegate_->OnDndFinished();
+}
+
void DataSource::ReadDataForTesting(const std::string& mime_type,
ReadDataCallback callback) {
ReadData(mime_type, std::move(callback), base::DoNothing());
@@ -147,7 +201,7 @@ void DataSource::ReadData(const std::string& mime_type,
ReadDataCallback callback,
base::OnceClosure failure_callback) {
// This DataSource does not contain the requested MIME type.
- if (!mime_types_.count(mime_type) || cancelled_) {
+ if (mime_type.empty() || !mime_types_.count(mime_type) || finished_) {
std::move(failure_callback).Run();
return;
}
@@ -157,9 +211,9 @@ void DataSource::ReadData(const std::string& mime_type,
PCHECK(base::CreatePipe(&read_fd, &write_fd));
delegate_->OnSend(mime_type, std::move(write_fd));
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&ReadDataOnWorkerThread, std::move(read_fd)),
base::BindOnce(&DataSource::OnDataRead,
@@ -174,9 +228,9 @@ void DataSource::OnDataRead(ReadDataCallback callback,
}
void DataSource::GetDataForPreferredMimeTypes(
- ReadDataCallback text_reader,
+ ReadTextDataCallback text_reader,
ReadDataCallback rtf_reader,
- ReadDataCallback html_reader,
+ ReadTextDataCallback html_reader,
ReadDataCallback image_reader,
base::RepeatingClosure failure_callback) {
std::string text_mime, rtf_mime, html_mime, image_mime;
@@ -188,22 +242,27 @@ void DataSource::GetDataForPreferredMimeTypes(
for (auto mime_type : mime_types_) {
if (net::MatchesMimeType(std::string(kTextPlain), mime_type) ||
mime_type == kEncodingUTF8Legacy) {
+ if (text_reader.is_null())
+ continue;
+
std::string charset;
- // We special case UTF8_STRING to provide minimal handling of X11 apps.
- if (mime_type == kEncodingUTF8Legacy)
- charset = kEncodingUTF8Charset;
- else
- charset = GetCharset(mime_type);
+ charset = GetCharset(mime_type);
int new_rank = GetCharsetRank(charset);
if (new_rank < text_rank) {
text_mime = mime_type;
text_rank = new_rank;
}
} else if (net::MatchesMimeType(std::string(kTextRTF), mime_type)) {
+ if (rtf_reader.is_null())
+ continue;
+
// The RTF MIME type will never have a character set because it only uses
// 7-bit bytes and stores character set information internally.
rtf_mime = mime_type;
} else if (net::MatchesMimeType(std::string(kTextHTML), mime_type)) {
+ if (html_reader.is_null())
+ continue;
+
auto charset = GetCharset(mime_type);
int new_rank = GetCharsetRank(charset);
if (new_rank < html_rank) {
@@ -211,6 +270,9 @@ void DataSource::GetDataForPreferredMimeTypes(
html_rank = new_rank;
}
} else if (blink::IsSupportedImageMimeType(mime_type)) {
+ if (image_reader.is_null())
+ continue;
+
int new_rank = GetImageTypeRank(mime_type);
if (new_rank < image_rank) {
image_mime = mime_type;
@@ -219,10 +281,25 @@ void DataSource::GetDataForPreferredMimeTypes(
}
}
- ReadData(text_mime, std::move(text_reader), failure_callback);
+ ReadData(text_mime,
+ base::BindOnce(&DataSource::OnTextRead,
+ read_data_weak_ptr_factory_.GetWeakPtr(),
+ std::move(text_reader)),
+ failure_callback);
ReadData(rtf_mime, std::move(rtf_reader), failure_callback);
- ReadData(html_mime, std::move(html_reader), failure_callback);
+ ReadData(html_mime,
+ base::BindOnce(&DataSource::OnTextRead,
+ read_data_weak_ptr_factory_.GetWeakPtr(),
+ std::move(html_reader)),
+ failure_callback);
ReadData(image_mime, std::move(image_reader), failure_callback);
}
+void DataSource::OnTextRead(ReadTextDataCallback callback,
+ const std::string& mime_type,
+ const std::vector<uint8_t>& data) {
+ base::string16 output = CodepageToUTF16(data, GetCharset(mime_type));
+ std::move(callback).Run(mime_type, std::move(output));
+}
+
} // namespace exo
diff --git a/chromium/components/exo/data_source.h b/chromium/components/exo/data_source.h
index 2e36dadb0d9..fb555edfe12 100644
--- a/chromium/components/exo/data_source.h
+++ b/chromium/components/exo/data_source.h
@@ -34,10 +34,30 @@ class DataSource {
// DataSource.
void SetActions(const base::flat_set<DndAction>& dnd_actions);
+ const base::flat_set<DndAction>& GetActions() const { return dnd_actions_; }
+
// Notifies the data source is cancelled. e.g. Replaced with another data
// source.
void Cancelled();
+ // Notifies the client of the mime type that will be used by the
+ // recipient. Only used during drag drop operations.
+ void Target(const base::Optional<std::string>& mime_type);
+
+ // Notifies the client of the dnd action that will be performed if the
+ // currently running drag operation ends now. Only used during drag drop
+ // operations.
+ void Action(DndAction action);
+
+ // Notifies the client that the user has released the current drag. At this
+ // point the target and action are considered final, but it is still possible
+ // for the recipient to reject the transfer.
+ void DndDropPerformed();
+
+ // Notifies the client that the drag was completed successfully. The data
+ // source must not be used by the client after this point except to delete it.
+ void DndFinished();
+
// Search the set of offered MIME types for the most preferred of each of the
// following categories: text/plain*, text/rtf, text/html*, image/*. If any
// usable MIME types in a given category are available, the corresponding
@@ -47,9 +67,11 @@ class DataSource {
// as four times.
using ReadDataCallback =
base::OnceCallback<void(const std::string&, const std::vector<uint8_t>&)>;
- void GetDataForPreferredMimeTypes(ReadDataCallback text_reader,
+ using ReadTextDataCallback =
+ base::OnceCallback<void(const std::string&, base::string16)>;
+ void GetDataForPreferredMimeTypes(ReadTextDataCallback text_reader,
ReadDataCallback rtf_reader,
- ReadDataCallback html_reader,
+ ReadTextDataCallback html_reader,
ReadDataCallback image_reader,
base::RepeatingClosure failure_callback);
@@ -68,14 +90,20 @@ class DataSource {
const std::string& mime_type,
const std::vector<uint8_t>&);
+ void OnTextRead(ReadTextDataCallback callback,
+ const std::string& mime_type,
+ const std::vector<uint8_t>& data);
+
DataSourceDelegate* const delegate_;
base::ObserverList<DataSourceObserver>::Unchecked observers_;
// Mime types which has been offered.
std::set<std::string> mime_types_;
- bool cancelled_;
+ bool finished_;
+
+ base::flat_set<DndAction> dnd_actions_;
- base::WeakPtrFactory<DataSource> read_data_weak_ptr_factory_;
+ base::WeakPtrFactory<DataSource> read_data_weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DataSource);
};
diff --git a/chromium/components/exo/data_source_delegate.h b/chromium/components/exo/data_source_delegate.h
index 6c2dc945295..59614445af6 100644
--- a/chromium/components/exo/data_source_delegate.h
+++ b/chromium/components/exo/data_source_delegate.h
@@ -21,7 +21,7 @@ class DataSourceDelegate {
virtual void OnDataSourceDestroying(DataSource* source) = 0;
// Called when a client accepts a |mime_type|.
- virtual void OnTarget(const std::string& mime_type) = 0;
+ virtual void OnTarget(const base::Optional<std::string>& mime_type) = 0;
// Called when the data is requested.
virtual void OnSend(const std::string& mime_type, base::ScopedFD fd) = 0;
diff --git a/chromium/components/exo/data_source_unittest.cc b/chromium/components/exo/data_source_unittest.cc
index f1d1872b30e..44d52bba3ed 100644
--- a/chromium/components/exo/data_source_unittest.cc
+++ b/chromium/components/exo/data_source_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/exo/data_source_delegate.h"
#include "components/exo/test/exo_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,9 +20,9 @@ constexpr char kTestData[] = "Test Data";
class DataSourceTest : public testing::Test {
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_ = {
- base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::DEFAULT,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC};
};
class TestDataSourceDelegate : public DataSourceDelegate {
@@ -32,7 +32,7 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* source) override {}
- void OnTarget(const std::string& mime_type) override {}
+ void OnTarget(const base::Optional<std::string>& mime_type) override {}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
ASSERT_TRUE(
base::WriteFileDescriptor(fd.get(), kTestData, strlen(kTestData)));
@@ -52,6 +52,15 @@ void CheckMimeType(const std::string& expected,
std::move(counter).Run();
}
+void CheckTextMimeType(const std::string& expected,
+ base::OnceClosure counter,
+ const std::string& mime_type,
+ base::string16 data) {
+ EXPECT_FALSE(expected.empty());
+ EXPECT_EQ(mime_type, expected);
+ std::move(counter).Run();
+}
+
void IncrementCounter(base::RepeatingClosure counter) {
std::move(counter).Run();
}
@@ -65,9 +74,9 @@ void CheckMimeTypesRecieved(DataSource* data_source,
base::RepeatingClosure counter =
base::BarrierClosure(4, run_loop.QuitClosure());
data_source->GetDataForPreferredMimeTypes(
- base::BindOnce(&CheckMimeType, text_mime, counter),
+ base::BindOnce(&CheckTextMimeType, text_mime, counter),
base::BindOnce(&CheckMimeType, rtf_mime, counter),
- base::BindOnce(&CheckMimeType, html_mime, counter),
+ base::BindOnce(&CheckTextMimeType, html_mime, counter),
base::BindOnce(&CheckMimeType, image_mime, counter),
base::BindRepeating(&IncrementCounter, counter));
run_loop.Run();
@@ -85,7 +94,7 @@ TEST_F(DataSourceTest, ReadData) {
std::string string_data(data.begin(), data.end());
EXPECT_EQ(std::string(kTestData), string_data);
}));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(DataSourceTest, ReadDataArbitraryMimeType) {
@@ -100,7 +109,7 @@ TEST_F(DataSourceTest, ReadDataArbitraryMimeType) {
std::string string_data(data.begin(), data.end());
EXPECT_EQ(std::string(kTestData), string_data);
}));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(DataSourceTest, ReadData_UnknownMimeType) {
@@ -115,7 +124,7 @@ TEST_F(DataSourceTest, ReadData_UnknownMimeType) {
FAIL() << "Callback should not be invoked when known "
"mimetype is not offerred";
}));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(DataSourceTest, ReadData_Destroyed) {
@@ -132,7 +141,7 @@ TEST_F(DataSourceTest, ReadData_Destroyed) {
"data source is destroyed";
}));
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(DataSourceTest, ReadData_Cancelled) {
@@ -147,7 +156,7 @@ TEST_F(DataSourceTest, ReadData_Cancelled) {
FAIL() << "Callback should not be invoked after cancelled";
}));
data_source.Cancelled();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(DataSourceTest, PreferredMimeTypeUTF16) {
diff --git a/chromium/components/exo/display.cc b/chromium/components/exo/display.cc
index aad19dd93a9..6d547ef44ef 100644
--- a/chromium/components/exo/display.cc
+++ b/chromium/components/exo/display.cc
@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
+#include "build/build_config.h"
#include "components/exo/data_device.h"
#include "components/exo/file_helper.h"
#include "components/exo/input_method_surface_manager.h"
@@ -110,9 +111,13 @@ std::unique_ptr<Buffer> Display::CreateLinuxDMABufBuffer(
// Using zero-copy for optimal performance.
bool use_zero_copy = true;
+#if defined(ARCH_CPU_X86_FAMILY)
// TODO(dcastagna): Re-enable NV12 format as HW overlay once b/113362843
// is addressed.
bool is_overlay_candidate = format != gfx::BufferFormat::YUV_420_BIPLANAR;
+#else
+ bool is_overlay_candidate = true;
+#endif
return std::make_unique<Buffer>(
std::move(gpu_memory_buffer),
diff --git a/chromium/components/exo/drag_drop_operation.cc b/chromium/components/exo/drag_drop_operation.cc
new file mode 100644
index 00000000000..44c633f0e17
--- /dev/null
+++ b/chromium/components/exo/drag_drop_operation.cc
@@ -0,0 +1,306 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/drag_drop_operation.h"
+
+#include "ash/drag_drop/drag_drop_controller.h"
+#include "base/barrier_closure.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/exo/data_offer.h"
+#include "components/exo/data_source.h"
+#include "components/exo/seat.h"
+#include "components/exo/surface.h"
+#include "components/viz/common/frame_sinks/copy_output_request.h"
+#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "ui/aura/client/drag_drop_client.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/gfx/transform_util.h"
+
+namespace exo {
+
+namespace {
+
+uint32_t DndActionsToDragOperations(const base::flat_set<DndAction>& actions) {
+ uint32_t dnd_operations = 0;
+ for (const DndAction action : actions) {
+ switch (action) {
+ case DndAction::kNone:
+ FALLTHROUGH;
+ // We don't support the ask action
+ case DndAction::kAsk:
+ break;
+ case DndAction::kCopy:
+ dnd_operations |= ui::DragDropTypes::DragOperation::DRAG_COPY;
+ break;
+ case DndAction::kMove:
+ dnd_operations |= ui::DragDropTypes::DragOperation::DRAG_MOVE;
+ break;
+ }
+ }
+ return dnd_operations;
+}
+
+#if defined(OS_CHROMEOS)
+DndAction DragOperationsToPreferredDndAction(int op) {
+ if (op & ui::DragDropTypes::DragOperation::DRAG_COPY)
+ return DndAction::kCopy;
+
+ if (op & ui::DragDropTypes::DragOperation::DRAG_MOVE)
+ return DndAction::kMove;
+
+ return DndAction::kNone;
+}
+#endif
+
+DndAction DragOperationToDndAction(int op) {
+ switch (op) {
+ case ui::DragDropTypes::DragOperation::DRAG_NONE:
+ return DndAction::kNone;
+ case ui::DragDropTypes::DragOperation::DRAG_MOVE:
+ return DndAction::kMove;
+ case ui::DragDropTypes::DragOperation::DRAG_COPY:
+ return DndAction::kCopy;
+ default:
+ NOTREACHED();
+ return DndAction::kNone;
+ }
+}
+
+} // namespace
+
+base::WeakPtr<DragDropOperation> DragDropOperation::Create(
+ DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source) {
+ auto* dnd_op = new DragDropOperation(source, origin, icon, event_source);
+ return dnd_op->weak_ptr_factory_.GetWeakPtr();
+}
+
+DragDropOperation::DragDropOperation(
+ DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source)
+ : SurfaceTreeHost("ExoDragDropOperation"),
+ source_(std::make_unique<ScopedDataSource>(source, this)),
+ origin_(std::make_unique<ScopedSurface>(origin, this)),
+ drag_start_point_(display::Screen::GetScreen()->GetCursorScreenPoint()),
+ os_exchange_data_(std::make_unique<ui::OSExchangeData>()),
+ event_source_(event_source),
+ weak_ptr_factory_(this) {
+ aura::Window* root_window = origin_->get()->window()->GetRootWindow();
+ DCHECK(root_window);
+#if defined(OS_CHROMEOS)
+ drag_drop_controller_ = static_cast<ash::DragDropController*>(
+ aura::client::GetDragDropClient(root_window));
+#else
+ drag_drop_controller_ = aura::client::GetDragDropClient(root_window);
+#endif
+ DCHECK(drag_drop_controller_);
+
+ if (drag_drop_controller_->IsDragDropInProgress())
+ drag_drop_controller_->DragCancel();
+
+ drag_drop_controller_->AddObserver(this);
+
+ if (icon)
+ icon_ = std::make_unique<ScopedSurface>(icon, this);
+
+ auto start_op_callback =
+ base::BindOnce(&DragDropOperation::ScheduleStartDragDropOperation,
+ weak_ptr_factory_.GetWeakPtr());
+
+ // Make the count kMaxClipboardDataTypes + 1 so we can wait for the icon to be
+ // captured as well.
+ counter_ = base::BarrierClosure(kMaxClipboardDataTypes + 1,
+ std::move(start_op_callback));
+
+ source->GetDataForPreferredMimeTypes(
+ base::BindOnce(&DragDropOperation::OnTextRead,
+ weak_ptr_factory_.GetWeakPtr()),
+ DataSource::ReadDataCallback(),
+ base::BindOnce(&DragDropOperation::OnHTMLRead,
+ weak_ptr_factory_.GetWeakPtr()),
+ DataSource::ReadDataCallback(), counter_);
+
+ if (icon) {
+ origin_->get()->window()->AddChild(host_window());
+ SetRootSurface(icon);
+ }
+}
+
+DragDropOperation::~DragDropOperation() {
+ drag_drop_controller_->RemoveObserver(this);
+
+ if (source_)
+ source_->get()->Cancelled();
+
+ if (drag_drop_controller_->IsDragDropInProgress() && started_by_this_object_)
+ drag_drop_controller_->DragCancel();
+}
+
+void DragDropOperation::AbortIfPending() {
+ if (!started_by_this_object_)
+ delete this;
+}
+
+void DragDropOperation::OnTextRead(const std::string& mime_type,
+ base::string16 data) {
+ DCHECK(os_exchange_data_);
+ os_exchange_data_->SetString(std::move(data));
+
+ // Prefer to use the HTML MIME type if possible
+ if (mime_type_.empty())
+ mime_type_ = mime_type;
+ counter_.Run();
+}
+
+void DragDropOperation::OnHTMLRead(const std::string& mime_type,
+ base::string16 data) {
+ DCHECK(os_exchange_data_);
+ os_exchange_data_->SetHtml(std::move(data), GURL());
+ mime_type_ = mime_type;
+ counter_.Run();
+}
+
+void DragDropOperation::OnSurfaceCommit() {
+ SurfaceTreeHost::OnSurfaceCommit();
+
+ if (icon_)
+ CaptureDragIcon();
+}
+
+void DragDropOperation::CaptureDragIcon() {
+ SubmitCompositorFrame();
+
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ std::make_unique<viz::CopyOutputRequest>(
+ viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
+ base::BindOnce(&DragDropOperation::OnDragIconCaptured,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ host_window()->layer()->RequestCopyOfOutput(std::move(request));
+}
+
+void DragDropOperation::OnDragIconCaptured(
+ std::unique_ptr<viz::CopyOutputResult> icon_result) {
+ gfx::ImageSkia icon_skia;
+
+ // An empty response means the request was deleted before it was completed. If
+ // this happens, and no operation has yet finished, restart the capture.
+ if (icon_result->IsEmpty()) {
+ CaptureDragIcon();
+ return;
+ }
+
+ float scale_factor = origin_->get()->window()->layer()->device_scale_factor();
+ icon_skia = gfx::ImageSkia(
+ gfx::ImageSkiaRep(icon_result->AsSkBitmap(), scale_factor));
+
+ if (os_exchange_data_) {
+ os_exchange_data_->provider().SetDragImage(
+ icon_skia, -icon_->get()->GetBufferOffset());
+ } else {
+#if defined(OS_CHROMEOS)
+ drag_drop_controller_->SetDragImage(icon_skia,
+ -icon_->get()->GetBufferOffset());
+#endif
+ }
+
+ if (!captured_icon_) {
+ captured_icon_ = true;
+ counter_.Run();
+ }
+}
+
+void DragDropOperation::ScheduleStartDragDropOperation() {
+ // StartDragAndDrop uses a nested run loop. When restarting, we a) don't want
+ // to interrupt the callers task for an arbitrary period of time and b) want
+ // to let any nested run loops that are currently running to have a chance to
+ // exit to avoid arbitrarily deep nesting. We can accomplish both of those
+ // things by posting a new task to actually start the drag and drop operation.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&DragDropOperation::StartDragDropOperation,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DragDropOperation::StartDragDropOperation() {
+ uint32_t dnd_operations =
+ DndActionsToDragOperations(source_->get()->GetActions());
+
+ started_by_this_object_ = true;
+ // This triggers a nested run loop that terminates when the drag and drop
+ // operation is completed.
+ int op = drag_drop_controller_->StartDragAndDrop(
+ std::move(os_exchange_data_), origin_->get()->window()->GetRootWindow(),
+ origin_->get()->window(), drag_start_point_, dnd_operations,
+ event_source_);
+
+ if (op) {
+ // Success
+
+ // TODO(crbug.com/994065) This is currently not the actual mime type used by
+ // the recipient, just an arbitrary one we pick out of the offered types so
+ // we can report back whether or not the drop can succeed. This may need to
+ // change in the future.
+ source_->get()->Target(mime_type_);
+
+ source_->get()->Action(DragOperationToDndAction(op));
+ source_->get()->DndDropPerformed();
+ source_->get()->DndFinished();
+
+ // Reset |source_| so it the destructor doesn't try to cancel it.
+ source_.reset();
+ }
+
+ // On failure the destructor will handle canceling the data source.
+ delete this;
+}
+
+void DragDropOperation::OnDragStarted() {
+ if (!started_by_this_object_)
+ delete this;
+}
+
+void DragDropOperation::OnDragEnded() {}
+
+#if defined(OS_CHROMEOS)
+void DragDropOperation::OnDragActionsChanged(int actions) {
+ if (!started_by_this_object_)
+ return;
+
+ DndAction dnd_action = DragOperationsToPreferredDndAction(actions);
+ // We send a mime type along with the action to indicate to the application
+ // that dropping is/is not currently possible. We do not currently know of
+ // any applications that care about the specific mime type until the drop is
+ // actually performed.
+ if (dnd_action != DndAction::kNone)
+ source_->get()->Target(mime_type_);
+ else
+ source_->get()->Target(base::nullopt);
+
+ source_->get()->Action(dnd_action);
+}
+#endif
+
+void DragDropOperation::OnSurfaceDestroying(Surface* surface) {
+ if (surface == origin_->get() || surface == icon_->get()) {
+ delete this;
+ } else {
+ NOTREACHED();
+ }
+}
+
+void DragDropOperation::OnDataSourceDestroying(DataSource* source) {
+ if (source == source_->get()) {
+ source_.reset();
+ delete this;
+ } else {
+ NOTREACHED();
+ }
+}
+} // namespace exo
diff --git a/chromium/components/exo/drag_drop_operation.h b/chromium/components/exo/drag_drop_operation.h
new file mode 100644
index 00000000000..ae02f4494bb
--- /dev/null
+++ b/chromium/components/exo/drag_drop_operation.h
@@ -0,0 +1,129 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_DRAG_DROP_OPERATION_H_
+#define COMPONENTS_EXO_DRAG_DROP_OPERATION_H_
+
+#include "components/exo/data_device.h"
+#include "components/exo/data_offer_observer.h"
+#include "components/exo/data_source_observer.h"
+#include "components/exo/surface_observer.h"
+#include "components/exo/surface_tree_host.h"
+#include "components/exo/wm_helper.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+
+namespace ash {
+class DragDropController;
+} // namespace ash
+
+namespace aura {
+namespace client {
+class DragDropClient;
+} // namespace client
+} // namespace aura
+
+namespace ui {
+class OSExchangeData;
+}
+
+namespace viz {
+class CopyOutputResult;
+}
+
+namespace exo {
+class ScopedDataSource;
+
+// This class represents an ongoing drag-drop operation started by an exo
+// client. It manages its own lifetime. It will delete itself when the drag
+// operation completes, is cancelled, or some vital resource is destroyed
+// (e.g. the client deletes the data source used to start the drag operation),
+// or if another drag operation races with this one to start and wins.
+class DragDropOperation : public DataSourceObserver,
+ public SurfaceTreeHost,
+ public SurfaceObserver,
+ public aura::client::DragDropClientObserver {
+ public:
+ // Create an operation for a drag-drop originating from a wayland app.
+ static base::WeakPtr<DragDropOperation> Create(
+ DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source);
+
+ // Abort the operation if it hasn't been started yet, otherwise do nothing.
+ void AbortIfPending();
+
+ // DataSourceObserver:
+ void OnDataSourceDestroying(DataSource* source) override;
+
+ // SurfaceDelegate:
+ void OnSurfaceCommit() override;
+
+ // SurfaceObserver:
+ void OnSurfaceDestroying(Surface* surface) override;
+
+ // aura::client::DragDropClientObserver:
+ void OnDragStarted() override;
+ void OnDragEnded() override;
+#if defined(OS_CHROMEOS)
+ void OnDragActionsChanged(int actions) override;
+#endif
+
+ private:
+ // A private constructor and destructor are used to prevent anyone else from
+ // attempting to manage the lifetime of a DragDropOperation.
+ DragDropOperation(DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source);
+ ~DragDropOperation() override;
+
+ void CaptureDragIcon();
+ void OnDragIconCaptured(std::unique_ptr<viz::CopyOutputResult> icon_result);
+
+ void OnTextRead(const std::string& mime_type, base::string16 data);
+ void OnHTMLRead(const std::string& mime_type, base::string16 data);
+
+ void ScheduleStartDragDropOperation();
+
+ // This operation triggers a nested RunLoop, and should not be called
+ // directly. Use ScheduleStartDragDropOperation instead.
+ void StartDragDropOperation();
+
+ std::unique_ptr<ScopedDataSource> source_;
+ std::unique_ptr<ScopedSurface> icon_;
+ std::unique_ptr<ScopedSurface> origin_;
+ gfx::Point drag_start_point_;
+ std::unique_ptr<ui::OSExchangeData> os_exchange_data_;
+#if defined(OS_CHROMEOS)
+ ash::DragDropController* drag_drop_controller_;
+#else
+ aura::client::DragDropClient* drag_drop_controller_;
+#endif // defined(OS_CHROMEOS)
+
+ base::RepeatingClosure counter_;
+
+ // Stores whether this object has just started a drag operation. If so, we
+ // want to ignore the OnDragStarted event.
+ bool started_by_this_object_ = false;
+
+ bool captured_icon_ = false;
+
+ // TODO(crbug.com/994065) This is currently not the actual mime type used by
+ // the recipient, just an arbitrary one we pick out of the offered types so we
+ // can report back whether or not the drop can succeed. This may need to
+ // change in the future.
+ std::string mime_type_;
+
+ ui::DragDropTypes::DragEventSource event_source_;
+
+ base::WeakPtrFactory<DragDropOperation> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(DragDropOperation);
+};
+
+} // namespace exo
+
+#endif // COMPONENTS_EXO_DRAG_DROP_OPERATION_H_
diff --git a/chromium/components/exo/fullscreen_shell_surface.cc b/chromium/components/exo/fullscreen_shell_surface.cc
index 236da687b3f..99343e366c5 100644
--- a/chromium/components/exo/fullscreen_shell_surface.cc
+++ b/chromium/components/exo/fullscreen_shell_surface.cc
@@ -18,11 +18,8 @@
namespace exo {
-FullscreenShellSurface::FullscreenShellSurface(Surface* surface)
+FullscreenShellSurface::FullscreenShellSurface()
: SurfaceTreeHost("FullscreenShellSurfaceHost") {
- surface->AddSurfaceObserver(this);
- SetRootSurface(surface);
- host_window()->Show();
set_owned_by_client();
CreateFullscreenShellSurfaceWidget(ui::SHOW_STATE_FULLSCREEN);
widget_->SetFullscreen(true);
@@ -66,6 +63,22 @@ void FullscreenShellSurface::SetStartupId(const char* startup_id) {
SetShellStartupId(widget_->GetNativeWindow(), startup_id_);
}
+void FullscreenShellSurface::SetSurface(Surface* surface) {
+ if (root_surface())
+ root_surface()->RemoveSurfaceObserver(this);
+ SetRootSurface(surface);
+ set_owned_by_client();
+ SetShellMainSurface(widget_->GetNativeWindow(), root_surface());
+ if (surface) {
+ surface->AddSurfaceObserver(this);
+ host_window()->Show();
+ widget_->Show();
+ } else {
+ host_window()->Hide();
+ widget_->Hide();
+ }
+}
+
void FullscreenShellSurface::Maximize() {
if (!widget_)
return;
@@ -212,7 +225,7 @@ void FullscreenShellSurface::CreateFullscreenShellSurfaceWidget(
params.bounds = gfx::Rect(params.parent->bounds().size());
widget_ = new views::Widget();
- widget_->Init(params);
+ widget_->Init(std::move(params));
aura::Window* window = widget_->GetNativeWindow();
window->SetName("FullscreenShellSurface");
@@ -243,4 +256,18 @@ bool FullscreenShellSurface::OnPreWidgetCommit() {
return true;
}
+void FullscreenShellSurface::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+ node_data->role = ax::mojom::Role::kClient;
+
+ if (child_ax_tree_id_ == ui::AXTreeIDUnknown())
+ return;
+
+ node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId,
+ child_ax_tree_id_.ToString());
+}
+
+void FullscreenShellSurface::SetChildAxTreeId(ui::AXTreeID child_ax_tree_id) {
+ child_ax_tree_id_ = child_ax_tree_id;
+}
+
} // namespace exo
diff --git a/chromium/components/exo/fullscreen_shell_surface.h b/chromium/components/exo/fullscreen_shell_surface.h
index e9175142948..f9928970ab6 100644
--- a/chromium/components/exo/fullscreen_shell_surface.h
+++ b/chromium/components/exo/fullscreen_shell_surface.h
@@ -7,6 +7,8 @@
#include "components/exo/surface_observer.h"
#include "components/exo/surface_tree_host.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/aura/window_observer.h"
#include "ui/views/widget/widget_delegate.h"
@@ -21,7 +23,7 @@ class FullscreenShellSurface : public SurfaceTreeHost,
public views::WidgetDelegate,
public views::View {
public:
- explicit FullscreenShellSurface(Surface* surface);
+ FullscreenShellSurface();
~FullscreenShellSurface() override;
// Set the callback to run when the user wants the shell surface to be closed.
@@ -42,6 +44,10 @@ class FullscreenShellSurface : public SurfaceTreeHost,
// Set the startup ID for the surface.
void SetStartupId(const char* startup_id);
+ // Set the Surface in use. Will replace root_surface_ if a surface is
+ // currently set. Will remove root_surface_ if |surface| is nullptr.
+ void SetSurface(Surface* surface);
+
void Maximize();
void Minimize();
@@ -74,6 +80,11 @@ class FullscreenShellSurface : public SurfaceTreeHost,
// Overridden from aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
+ // Overridden from ui::View
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+
+ void SetChildAxTreeId(ui::AXTreeID child_ax_tree_id);
+
private:
void CreateFullscreenShellSurfaceWidget(ui::WindowShowState show_state);
void CommitWidget();
@@ -85,6 +96,7 @@ class FullscreenShellSurface : public SurfaceTreeHost,
base::Optional<std::string> startup_id_;
base::RepeatingClosure close_callback_;
base::OnceClosure surface_destroyed_callback_;
+ ui::AXTreeID child_ax_tree_id_ = ui::AXTreeIDUnknown();
DISALLOW_COPY_AND_ASSIGN(FullscreenShellSurface);
};
diff --git a/chromium/components/exo/fullscreen_shell_surface_unittest.cc b/chromium/components/exo/fullscreen_shell_surface_unittest.cc
index b340598c870..c15185edb87 100644
--- a/chromium/components/exo/fullscreen_shell_surface_unittest.cc
+++ b/chromium/components/exo/fullscreen_shell_surface_unittest.cc
@@ -12,6 +12,8 @@
#include "components/exo/wm_helper.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/compositor/compositor.h"
@@ -45,7 +47,8 @@ void Close(int* close_call_count) {
TEST_F(FullscreenShellSurfaceTest, SurfaceDestroyedCallback) {
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
fullscreen_surface->set_surface_destroyed_callback(base::BindOnce(
&DestroyFullscreenShellSurface, base::Unretained(&fullscreen_surface)));
@@ -66,7 +69,8 @@ TEST_F(FullscreenShellSurfaceTest, CloseCallback) {
CreateGpuMemoryBuffer(buffer_size, gfx::BufferFormat::RGBA_8888)));
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
int close_call_count = 0;
fullscreen_surface->set_close_callback(
@@ -83,7 +87,8 @@ TEST_F(FullscreenShellSurfaceTest, CloseCallback) {
TEST_F(FullscreenShellSurfaceTest, ShouldShowWindowTitle) {
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
EXPECT_FALSE(fullscreen_surface->ShouldShowWindowTitle());
}
@@ -94,7 +99,8 @@ TEST_F(FullscreenShellSurfaceTest, SetApplicationId) {
CreateGpuMemoryBuffer(buffer_size, gfx::BufferFormat::RGBA_8888)));
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
EXPECT_TRUE(fullscreen_surface->GetWidget());
fullscreen_surface->SetApplicationId("test-id");
@@ -116,7 +122,8 @@ TEST_F(FullscreenShellSurfaceTest, SetStartupId) {
CreateGpuMemoryBuffer(buffer_size, gfx::BufferFormat::RGBA_8888)));
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
EXPECT_TRUE(fullscreen_surface->GetWidget());
fullscreen_surface->SetStartupId("test-id");
@@ -138,7 +145,8 @@ TEST_F(FullscreenShellSurfaceTest, Maximize) {
CreateGpuMemoryBuffer(buffer_size, gfx::BufferFormat::RGBA_8888)));
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
surface->Attach(buffer.get());
surface->Commit();
@@ -152,7 +160,8 @@ TEST_F(FullscreenShellSurfaceTest, Minimize) {
CreateGpuMemoryBuffer(buffer_size, gfx::BufferFormat::RGBA_8888)));
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
surface->Attach(buffer.get());
surface->Commit();
@@ -171,7 +180,8 @@ TEST_F(FullscreenShellSurfaceTest, Bounds) {
CreateGpuMemoryBuffer(buffer_size, gfx::BufferFormat::RGBA_8888)));
std::unique_ptr<Surface> surface(new Surface);
std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
- new FullscreenShellSurface(surface.get()));
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
surface->Attach(buffer.get());
surface->Commit();
@@ -181,5 +191,64 @@ TEST_F(FullscreenShellSurfaceTest, Bounds) {
EXPECT_EQ(fullscreen_bounds, expected_bounds);
}
+TEST_F(FullscreenShellSurfaceTest, SetAXChildTree) {
+ std::unique_ptr<Surface> surface(new Surface);
+ std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
+ ui::AXNodeData node_data;
+ fullscreen_surface->GetAccessibleNodeData(&node_data);
+ EXPECT_FALSE(
+ node_data.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
+
+ ui::AXTreeID tree_id = ui::AXTreeID::CreateNewAXTreeID();
+ fullscreen_surface->SetChildAxTreeId(tree_id);
+ fullscreen_surface->GetAccessibleNodeData(&node_data);
+ EXPECT_TRUE(
+ node_data.HasStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
+}
+
+TEST_F(FullscreenShellSurfaceTest, SwapSurface) {
+ std::unique_ptr<Surface> surface(new Surface);
+ std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
+ fullscreen_surface->SetEnabled(true);
+ fullscreen_surface->set_surface_destroyed_callback(base::BindOnce(
+ &DestroyFullscreenShellSurface, base::Unretained(&fullscreen_surface)));
+ EXPECT_EQ(surface.get(), fullscreen_surface->root_surface());
+ std::unique_ptr<Surface> surface2(new Surface);
+ fullscreen_surface->SetSurface(surface2.get());
+ EXPECT_EQ(surface2.get(), fullscreen_surface->root_surface());
+ EXPECT_NE(surface.get(), fullscreen_surface->root_surface());
+ // RootWindow->FullscreenShellSurface->FullscreenShellSurfaceHost->ExoSurface
+ EXPECT_EQ(1ul, WMHelper::GetInstance()
+ ->GetRootWindowForNewWindows()
+ ->children()[0]
+ ->children()[0]
+ ->children()
+ .size());
+}
+
+TEST_F(FullscreenShellSurfaceTest, RemoveSurface) {
+ std::unique_ptr<Surface> surface(new Surface);
+ std::unique_ptr<FullscreenShellSurface> fullscreen_surface(
+ new FullscreenShellSurface());
+ fullscreen_surface->SetSurface(surface.get());
+ fullscreen_surface->SetEnabled(true);
+ fullscreen_surface->set_surface_destroyed_callback(base::BindOnce(
+ &DestroyFullscreenShellSurface, base::Unretained(&fullscreen_surface)));
+ EXPECT_EQ(surface.get(), fullscreen_surface->root_surface());
+ fullscreen_surface->SetSurface(nullptr);
+ EXPECT_FALSE(fullscreen_surface->root_surface());
+ // RootWindow->FullscreenShellSurface->FullscreenShellSurfaceHost->null
+ EXPECT_EQ(0ul, WMHelper::GetInstance()
+ ->GetRootWindowForNewWindows()
+ ->children()[0]
+ ->children()[0]
+ ->children()
+ .size());
+}
+
} // namespace
} // namespace exo
diff --git a/chromium/components/exo/gamepad_delegate.h b/chromium/components/exo/gamepad_delegate.h
index fc8c5b07de9..8ca47f8c625 100644
--- a/chromium/components/exo/gamepad_delegate.h
+++ b/chromium/components/exo/gamepad_delegate.h
@@ -13,16 +13,11 @@ class GamepadDelegate {
// Called when the gamepad has been removed.
virtual void OnRemoved() = 0;
- // Called when the user moved an axis of the gamepad. Valid axes are defined
- // by the W3C 'standard gamepad' specification.
- virtual void OnAxis(int axis, int raw_axis, double value) = 0;
+ // Called when the user moved an axis of the gamepad.
+ virtual void OnAxis(int axis, double value) = 0;
// Called when the user pressed or moved a button of the gamepad.
- // Valid buttons are defined by the W3C 'standard gamepad' specification.
- virtual void OnButton(int button,
- int raw_button,
- bool pressed,
- double value) = 0;
+ virtual void OnButton(int button, bool pressed) = 0;
// Called after all gamepad information of this frame has been set and the
// client should evaluate the updated state.
diff --git a/chromium/components/exo/gaming_seat.cc b/chromium/components/exo/gaming_seat.cc
index 8a8a3dbdf86..c578348c3d1 100644
--- a/chromium/components/exo/gaming_seat.cc
+++ b/chromium/components/exo/gaming_seat.cc
@@ -97,11 +97,10 @@ void GamingSeat::OnGamepadEvent(const ui::GamepadEvent& event) {
switch (event.type()) {
case ui::GamepadEventType::BUTTON:
- it->second->OnButton(event.code(), event.raw_code(), event.value(),
- event.value());
+ it->second->OnButton(event.code(), event.value());
break;
case ui::GamepadEventType::AXIS:
- it->second->OnAxis(event.code(), event.raw_code(), event.value());
+ it->second->OnAxis(event.code(), event.value());
break;
case ui::GamepadEventType::FRAME:
it->second->OnFrame();
diff --git a/chromium/components/exo/gaming_seat_unittest.cc b/chromium/components/exo/gaming_seat_unittest.cc
index dd153f398e1..6a04350f0de 100644
--- a/chromium/components/exo/gaming_seat_unittest.cc
+++ b/chromium/components/exo/gaming_seat_unittest.cc
@@ -37,8 +37,8 @@ class MockGamepadDelegate : public GamepadDelegate {
// Overridden from GamepadDelegate:
MOCK_METHOD0(OnRemoved, void());
- MOCK_METHOD3(OnAxis, void(int, int, double));
- MOCK_METHOD4(OnButton, void(int, int, bool, double));
+ MOCK_METHOD2(OnAxis, void(int, double));
+ MOCK_METHOD2(OnButton, void(int, bool));
MOCK_METHOD0(OnFrame, void());
};
@@ -67,7 +67,7 @@ class GamingSeatTest : public test::ExoTestBase {
void SendFrameToGamepads(const std::vector<int>& gamepad_device_ids) {
for (auto& id : gamepad_device_ids) {
- ui::GamepadEvent event(id, ui::GamepadEventType::FRAME, 0, 0, 0,
+ ui::GamepadEvent event(id, ui::GamepadEventType::FRAME, 0, 0,
base::TimeTicks());
ui::GamepadProviderOzone::GetInstance()->DispatchGamepadEvent(event);
}
diff --git a/chromium/components/exo/keyboard.cc b/chromium/components/exo/keyboard.cc
index 7b1368c091e..fa16e2dc4d0 100644
--- a/chromium/components/exo/keyboard.cc
+++ b/chromium/components/exo/keyboard.cc
@@ -166,8 +166,7 @@ Keyboard::Keyboard(KeyboardDelegate* delegate, Seat* seat)
: delegate_(delegate),
seat_(seat),
expiration_delay_for_pending_key_acks_(base::TimeDelta::FromMilliseconds(
- kExpirationDelayForPendingKeyAcksMs)),
- weak_ptr_factory_(this) {
+ kExpirationDelayForPendingKeyAcksMs)) {
AddEventHandler();
seat_->AddObserver(this);
keyboard::KeyboardUIController::Get()->AddObserver(this);
diff --git a/chromium/components/exo/keyboard.h b/chromium/components/exo/keyboard.h
index c371a97dfbb..08ec4e079ec 100644
--- a/chromium/components/exo/keyboard.h
+++ b/chromium/components/exo/keyboard.h
@@ -129,7 +129,7 @@ class Keyboard : public ui::EventHandler,
base::ObserverList<KeyboardObserver>::Unchecked observer_list_;
- base::WeakPtrFactory<Keyboard> weak_ptr_factory_;
+ base::WeakPtrFactory<Keyboard> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Keyboard);
};
diff --git a/chromium/components/exo/mime_utils.cc b/chromium/components/exo/mime_utils.cc
index 26103a9c6cc..b9886077739 100644
--- a/chromium/components/exo/mime_utils.cc
+++ b/chromium/components/exo/mime_utils.cc
@@ -8,12 +8,17 @@ namespace {
constexpr char kCharset[] = ";charset=";
constexpr char kDefaultCharset[] = "US-ASCII";
+constexpr char kEncodingUTF8Charset[] = "UTF-8";
} // namespace
namespace exo {
std::string GetCharset(const std::string& mime_type) {
+ // We special case UTF8_STRING to provide minimal handling of X11 apps.
+ if (mime_type == kEncodingUTF8Legacy)
+ return std::string(kEncodingUTF8Charset);
+
auto pos = mime_type.find(kCharset);
if (pos == std::string::npos)
return std::string(kDefaultCharset);
diff --git a/chromium/components/exo/mime_utils.h b/chromium/components/exo/mime_utils.h
index 5905e17d089..8e2b4b5647f 100644
--- a/chromium/components/exo/mime_utils.h
+++ b/chromium/components/exo/mime_utils.h
@@ -9,6 +9,8 @@
namespace exo {
+constexpr char kEncodingUTF8Legacy[] = "UTF8_STRING";
+
// Takes a text/* mime type and returns the name of the character set specified
// in the type. If no character set is specified, defaults to US-ASCII.
std::string GetCharset(const std::string& mime_type);
diff --git a/chromium/components/exo/mime_utils_unittest.cc b/chromium/components/exo/mime_utils_unittest.cc
index c58ee520d7b..81f12945b5d 100644
--- a/chromium/components/exo/mime_utils_unittest.cc
+++ b/chromium/components/exo/mime_utils_unittest.cc
@@ -10,6 +10,12 @@ namespace exo {
namespace {
using MimeUtilsTest = testing::Test;
+TEST_F(MimeUtilsTest, LegacyString) {
+ std::string mime_type("UTF8_STRING");
+ std::string expected("UTF-8");
+ EXPECT_EQ(GetCharset(mime_type), expected);
+}
+
TEST_F(MimeUtilsTest, CharsetNotPresent) {
std::string mime_type("text/plain");
std::string expected("US-ASCII");
diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc
index 9e0bbedb8d1..0d23cdfadb2 100644
--- a/chromium/components/exo/pointer.cc
+++ b/chromium/components/exo/pointer.cc
@@ -12,6 +12,7 @@
#include "components/exo/pointer_delegate.h"
#include "components/exo/pointer_gesture_pinch_delegate.h"
#include "components/exo/relative_pointer_delegate.h"
+#include "components/exo/seat.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "components/exo/wm_helper.h"
@@ -95,14 +96,14 @@ int GetContainerIdForMouseCursor() {
////////////////////////////////////////////////////////////////////////////////
// Pointer, public:
-Pointer::Pointer(PointerDelegate* delegate)
+Pointer::Pointer(PointerDelegate* delegate, Seat* seat)
: SurfaceTreeHost("ExoPointer"),
delegate_(delegate),
+ seat_(seat),
cursor_(ui::CursorType::kNull),
capture_scale_(GetCaptureDisplayInfo().device_scale_factor()),
capture_ratio_(GetCaptureDisplayInfo().GetDensityRatio()),
- cursor_capture_source_id_(base::UnguessableToken::Create()),
- cursor_capture_weak_ptr_factory_(this) {
+ cursor_capture_source_id_(base::UnguessableToken::Create()) {
WMHelper* helper = WMHelper::GetInstance();
helper->AddPreTargetHandler(this);
// TODO(sky): CursorClient does not exist in mash
@@ -365,10 +366,11 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) {
delegate_->OnPointerFrame();
}
}
-
switch (event->type()) {
- case ui::ET_MOUSE_PRESSED:
- case ui::ET_MOUSE_RELEASED: {
+ case ui::ET_MOUSE_RELEASED:
+ seat_->AbortPendingDragOperation();
+ FALLTHROUGH;
+ case ui::ET_MOUSE_PRESSED: {
delegate_->OnPointerButton(event->time_stamp(),
event->changed_button_flags(),
event->type() == ui::ET_MOUSE_PRESSED);
diff --git a/chromium/components/exo/pointer.h b/chromium/components/exo/pointer.h
index 823adc5b9fe..5dff92aa2d6 100644
--- a/chromium/components/exo/pointer.h
+++ b/chromium/components/exo/pointer.h
@@ -38,6 +38,7 @@ namespace exo {
class PointerDelegate;
class PointerGesturePinchDelegate;
class RelativePointerDelegate;
+class Seat;
class Surface;
class SurfaceTreeHost;
@@ -50,7 +51,7 @@ class Pointer : public SurfaceTreeHost,
public aura::client::CursorClientObserver,
public aura::client::FocusChangeObserver {
public:
- explicit Pointer(PointerDelegate* delegate);
+ Pointer(PointerDelegate* delegate, Seat* seat);
~Pointer() override;
PointerDelegate* delegate() const { return delegate_; }
@@ -142,6 +143,8 @@ class Pointer : public SurfaceTreeHost,
// The delegate instance that all events are dispatched to.
PointerDelegate* const delegate_;
+ Seat* const seat_;
+
// The delegate instance that all pinch related events are dispatched to.
PointerGesturePinchDelegate* pinch_delegate_ = nullptr;
@@ -191,7 +194,7 @@ class Pointer : public SurfaceTreeHost,
ui::EventType last_event_type_ = ui::ET_UNKNOWN;
// Weak pointer factory used for cursor capture callbacks.
- base::WeakPtrFactory<Pointer> cursor_capture_weak_ptr_factory_;
+ base::WeakPtrFactory<Pointer> cursor_capture_weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Pointer);
};
diff --git a/chromium/components/exo/pointer_unittest.cc b/chromium/components/exo/pointer_unittest.cc
index 0674da9d531..4415897a2df 100644
--- a/chromium/components/exo/pointer_unittest.cc
+++ b/chromium/components/exo/pointer_unittest.cc
@@ -11,7 +11,10 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "components/exo/buffer.h"
+#include "components/exo/data_source.h"
+#include "components/exo/data_source_delegate.h"
#include "components/exo/pointer_delegate.h"
+#include "components/exo/seat.h"
#include "components/exo/shell_surface.h"
#include "components/exo/sub_surface.h"
#include "components/exo/surface.h"
@@ -46,6 +49,22 @@ class MockPointerDelegate : public PointerDelegate {
MOCK_METHOD0(OnPointerFrame, void());
};
+class TestDataSourceDelegate : public DataSourceDelegate {
+ public:
+ TestDataSourceDelegate() {}
+
+ // Overridden from DataSourceDelegate:
+ void OnDataSourceDestroying(DataSource* device) override {}
+ void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnSend(const std::string& mime_type, base::ScopedFD fd) override {}
+ void OnCancelled() override {}
+ void OnDndDropPerformed() override {}
+ void OnDndFinished() override {}
+ void OnAction(DndAction dnd_action) override {}
+
+ DISALLOW_COPY_AND_ASSIGN(TestDataSourceDelegate);
+};
+
class PointerTest : public test::ExoTestBase {
public:
PointerTest() = default;
@@ -72,7 +91,8 @@ TEST_F(PointerTest, SetCursor) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -134,7 +154,8 @@ TEST_F(PointerTest, SetCursorNull) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -165,7 +186,8 @@ TEST_F(PointerTest, SetCursorType) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -223,7 +245,8 @@ TEST_F(PointerTest, SetCursorTypeOutsideOfSurface) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -255,7 +278,8 @@ TEST_F(PointerTest, SetCursorAndSetCursorType) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -328,7 +352,8 @@ TEST_F(PointerTest, SetCursorNullAndSetCursorType) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -372,7 +397,8 @@ TEST_F(PointerTest, OnPointerEnter) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -395,7 +421,8 @@ TEST_F(PointerTest, OnPointerLeave) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -428,7 +455,8 @@ TEST_F(PointerTest, OnPointerMotion) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -501,7 +529,8 @@ TEST_F(PointerTest, OnPointerButton) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -531,7 +560,8 @@ TEST_F(PointerTest, OnPointerScroll) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
gfx::Point location = surface->window()->GetBoundsInScreen().origin();
@@ -566,7 +596,8 @@ TEST_F(PointerTest, OnPointerScrollWithThreeFinger) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
gfx::Point location = surface->window()->GetBoundsInScreen().origin();
@@ -601,7 +632,8 @@ TEST_F(PointerTest, OnPointerScrollDiscrete) {
surface->Commit();
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
@@ -636,7 +668,8 @@ TEST_F(PointerTest, RegisterPointerEventsOnModal) {
EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen());
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -694,7 +727,8 @@ TEST_F(PointerTest, IgnorePointerEventsOnNonModalWhenModalIsOpen) {
EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen());
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -755,7 +789,8 @@ TEST_F(PointerTest, IgnorePointerLeaveOnModal) {
EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen());
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -802,7 +837,8 @@ TEST_F(PointerTest, RegisterPointerEventsOnNonModal) {
ash::CenterWindow(shell_surface2->GetWidget()->GetNativeWindow());
MockPointerDelegate delegate;
- std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+ Seat seat;
+ std::unique_ptr<Pointer> pointer(new Pointer(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber());
@@ -846,5 +882,41 @@ TEST_F(PointerTest, RegisterPointerEventsOnNonModal) {
pointer.reset();
}
+TEST_F(PointerTest, DragDropAbort) {
+ Seat seat;
+ MockPointerDelegate pointer_delegate;
+ std::unique_ptr<Pointer> pointer(new Pointer(&pointer_delegate, &seat));
+ TestDataSourceDelegate data_source_delegate;
+ DataSource source(&data_source_delegate);
+ Surface origin, icon;
+
+ // Make origin into a real window so the pointer can click it
+ ShellSurface shell_surface(&origin);
+ Buffer buffer(exo_test_helper()->CreateGpuMemoryBuffer(gfx::Size(10, 10)));
+ origin.Attach(&buffer);
+ origin.Commit();
+
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+ EXPECT_CALL(pointer_delegate, CanAcceptPointerEventsForSurface(&origin))
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(pointer_delegate, OnPointerFrame()).Times(3);
+ EXPECT_CALL(pointer_delegate, OnPointerEnter(&origin, gfx::PointF(), 0));
+ generator.MoveMouseTo(origin.window()->GetBoundsInScreen().origin());
+
+ seat.StartDrag(&source, &origin, &icon,
+ ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_MOUSE);
+ EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
+
+ EXPECT_CALL(pointer_delegate, OnPointerButton).Times(2);
+ generator.PressLeftButton();
+ EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
+ generator.ReleaseLeftButton();
+ EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
+
+ EXPECT_CALL(pointer_delegate, OnPointerDestroying(pointer.get()));
+ pointer.reset();
+}
+
} // namespace
} // namespace exo
diff --git a/chromium/components/exo/seat.cc b/chromium/components/exo/seat.cc
index 770ab199ba0..9a3896fe276 100644
--- a/chromium/components/exo/seat.cc
+++ b/chromium/components/exo/seat.cc
@@ -12,18 +12,17 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/i18n/icu_string_conversions.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "components/exo/data_source.h"
+#include "components/exo/drag_drop_operation.h"
#include "components/exo/mime_utils.h"
#include "components/exo/seat_observer.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "components/exo/wm_helper.h"
#include "services/data_decoder/public/cpp/decode_image.h"
-#include "third_party/icu/source/common/unicode/ucnv.h"
#include "ui/aura/client/focus_client.h"
#include "ui/base/clipboard/clipboard_monitor.h"
#include "ui/events/event_utils.h"
@@ -36,16 +35,6 @@ class Connector;
namespace exo {
namespace {
-// The maximum number of different data types that we will write to the
-// clipboard (plain text, RTF, HTML, image)
-constexpr int kMaxClipboardDataTypes = 4;
-
-constexpr char kUTF16Unspecified[] = "UTF-16";
-constexpr char kUTF16LittleEndian[] = "UTF-16LE";
-constexpr char kUTF16BigEndian[] = "UTF-16BE";
-constexpr uint8_t kByteOrderMark[] = {0xFE, 0xFF};
-constexpr int kByteOrderMarkSize = sizeof(kByteOrderMark);
-
Surface* GetEffectiveFocus(aura::Window* window) {
if (!window)
return nullptr;
@@ -59,43 +48,9 @@ Surface* GetEffectiveFocus(aura::Window* window) {
return GetShellMainSurface(top_level_window);
}
-base::string16 CodepageToUTF16(const std::vector<uint8_t>& data,
- const std::string& charset_input) {
- base::string16 output;
- base::StringPiece piece(reinterpret_cast<const char*>(data.data()),
- data.size());
- const char* charset = charset_input.c_str();
-
- // Despite claims in the documentation to the contrary, the ICU UTF-16
- // converter does not automatically detect and interpret the byte order
- // mark. Therefore, we must do this ourselves.
- if (!ucnv_compareNames(charset, kUTF16Unspecified) &&
- data.size() >= kByteOrderMarkSize) {
- if (static_cast<uint8_t>(piece.data()[0]) == kByteOrderMark[0] &&
- static_cast<uint8_t>(piece.data()[1]) == kByteOrderMark[1]) {
- // BOM is in big endian format. Consume the BOM so it doesn't get
- // interpreted as a character.
- piece.remove_prefix(2);
- charset = kUTF16BigEndian;
- } else if (static_cast<uint8_t>(piece.data()[0]) == kByteOrderMark[1] &&
- static_cast<uint8_t>(piece.data()[1]) == kByteOrderMark[0]) {
- // BOM is in little endian format. Consume the BOM so it doesn't get
- // interpreted as a character.
- piece.remove_prefix(2);
- charset = kUTF16LittleEndian;
- }
- }
-
- base::CodepageToUTF16(
- piece, charset, base::OnStringConversionError::Type::SUBSTITUTE, &output);
- return output;
-}
-
} // namespace
-Seat::Seat()
- : changing_clipboard_data_to_selection_source_(false),
- weak_ptr_factory_(this) {
+Seat::Seat() : changing_clipboard_data_to_selection_source_(false) {
WMHelper::GetInstance()->AddFocusObserver(this);
// Prepend handler as it's critical that we see all events.
WMHelper::GetInstance()->PrependPreTargetHandler(this);
@@ -127,9 +82,24 @@ Surface* Seat::GetFocusedSurface() {
return GetEffectiveFocus(WMHelper::GetInstance()->GetFocusedWindow());
}
+void Seat::StartDrag(DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source) {
+ // DragDropOperation manages its own lifetime.
+ drag_drop_operation_ =
+ DragDropOperation::Create(source, origin, icon, event_source);
+}
+
+void Seat::AbortPendingDragOperation() {
+ if (drag_drop_operation_)
+ drag_drop_operation_->AbortIfPending();
+}
+
void Seat::SetSelection(DataSource* source) {
if (!source) {
- ui::Clipboard::GetForCurrentThread()->Clear(ui::ClipboardType::kCopyPaste);
+ ui::Clipboard::GetForCurrentThread()->Clear(
+ ui::ClipboardBuffer::kCopyPaste);
// selection_source_ is Cancelled() and reset() in OnClipboardDataChanged().
return;
}
@@ -142,7 +112,7 @@ void Seat::SetSelection(DataSource* source) {
selection_source_ = std::make_unique<ScopedDataSource>(source, this);
scoped_refptr<RefCountedScopedClipboardWriter> writer =
base::MakeRefCounted<RefCountedScopedClipboardWriter>(
- ui::ClipboardType::kCopyPaste);
+ ui::ClipboardBuffer::kCopyPaste);
base::RepeatingClosure data_read_callback = base::BarrierClosure(
kMaxClipboardDataTypes,
@@ -164,9 +134,8 @@ void Seat::SetSelection(DataSource* source) {
void Seat::OnTextRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
base::OnceClosure callback,
const std::string& mime_type,
- const std::vector<uint8_t>& data) {
- base::string16 output = CodepageToUTF16(data, GetCharset(mime_type));
- writer->WriteText(output);
+ base::string16 data) {
+ writer->WriteText(std::move(data));
std::move(callback).Run();
}
@@ -182,9 +151,8 @@ void Seat::OnRTFRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
void Seat::OnHTMLRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
base::OnceClosure callback,
const std::string& mime_type,
- const std::vector<uint8_t>& data) {
- base::string16 output = CodepageToUTF16(data, GetCharset(mime_type));
- writer->WriteHTML(output, std::string());
+ base::string16 data) {
+ writer->WriteHTML(std::move(data), std::string());
std::move(callback).Run();
}
diff --git a/chromium/components/exo/seat.h b/chromium/components/exo/seat.h
index 79207064b76..e114c1eac77 100644
--- a/chromium/components/exo/seat.h
+++ b/chromium/components/exo/seat.h
@@ -13,6 +13,7 @@
#include "ui/aura/client/focus_change_observer.h"
#include "ui/base/clipboard/clipboard_observer.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/events/event_handler.h"
#include "ui/events/keycodes/dom/dom_codes.h"
#include "ui/events/platform/platform_event_observer.h"
@@ -23,10 +24,15 @@ class KeyEvent;
} // namespace ui
namespace exo {
+class DragDropOperation;
class ScopedDataSource;
class SeatObserver;
class Surface;
+// The maximum number of different data types that we will write to the
+// clipboard (plain text, RTF, HTML, image)
+constexpr int kMaxClipboardDataTypes = 4;
+
// Seat object represent a group of input devices such as keyboard, pointer and
// touch devices and keeps track of input focus.
class Seat : public aura::client::FocusChangeObserver,
@@ -61,6 +67,14 @@ class Seat : public aura::client::FocusChangeObserver,
// Sets clipboard data from |source|.
void SetSelection(DataSource* source);
+ void StartDrag(DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ ui::DragDropTypes::DragEventSource event_source);
+
+ // Abort any drag operations that haven't been started yet.
+ void AbortPendingDragOperation();
+
// Overridden from aura::client::FocusChangeObserver:
void OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) override;
@@ -84,13 +98,17 @@ class Seat : public aura::client::FocusChangeObserver,
physical_code_for_currently_processing_event;
}
+ base::WeakPtr<DragDropOperation> get_drag_drop_operation_for_testing() {
+ return drag_drop_operation_;
+ }
+
private:
class RefCountedScopedClipboardWriter
: public ui::ScopedClipboardWriter,
public base::RefCounted<RefCountedScopedClipboardWriter> {
public:
- RefCountedScopedClipboardWriter(ui::ClipboardType type)
- : ScopedClipboardWriter(type) {}
+ RefCountedScopedClipboardWriter(ui::ClipboardBuffer buffer)
+ : ScopedClipboardWriter(buffer) {}
private:
friend class base::RefCounted<RefCountedScopedClipboardWriter>;
@@ -103,7 +121,7 @@ class Seat : public aura::client::FocusChangeObserver,
void OnTextRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
base::OnceClosure callback,
const std::string& mime_type,
- const std::vector<uint8_t>& data);
+ base::string16 data);
void OnRTFRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
base::OnceClosure callback,
const std::string& mime_type,
@@ -111,7 +129,7 @@ class Seat : public aura::client::FocusChangeObserver,
void OnHTMLRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
base::OnceClosure callback,
const std::string& mime_type,
- const std::vector<uint8_t>& data);
+ base::string16 data);
void OnImageRead(scoped_refptr<RefCountedScopedClipboardWriter> writer,
base::OnceClosure callback,
const std::string& mime_type,
@@ -136,10 +154,12 @@ class Seat : public aura::client::FocusChangeObserver,
// Data source being used as a clipboard content.
std::unique_ptr<ScopedDataSource> selection_source_;
+ base::WeakPtr<DragDropOperation> drag_drop_operation_;
+
// True while Seat is updating clipboard data to selection source.
bool changing_clipboard_data_to_selection_source_;
- base::WeakPtrFactory<Seat> weak_ptr_factory_;
+ base::WeakPtrFactory<Seat> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Seat);
};
diff --git a/chromium/components/exo/seat_unittest.cc b/chromium/components/exo/seat_unittest.cc
index e5959687e60..8ff4fa0432a 100644
--- a/chromium/components/exo/seat_unittest.cc
+++ b/chromium/components/exo/seat_unittest.cc
@@ -7,10 +7,11 @@
#include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/thread_pool/thread_pool.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
#include "components/exo/data_source.h"
#include "components/exo/data_source_delegate.h"
#include "components/exo/seat_observer.h"
+#include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
@@ -49,7 +50,7 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* device) override {}
- void OnTarget(const std::string& mime_type) override {}
+ void OnTarget(const base::Optional<std::string>& mime_type) override {}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
if (!data_.has_value()) {
std::string test_data = "TestData";
@@ -105,7 +106,7 @@ TEST_F(SeatTest, SetSelection) {
std::string clipboard;
ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardType::kCopyPaste, &clipboard);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, std::string("TestData"));
}
@@ -132,14 +133,40 @@ TEST_F(SeatTest, SetSelectionTextUTF8) {
RunReadingTask();
base::string16 clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
- &clipboard);
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, converted_data);
std::string url;
uint32_t start, end;
ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardType::kCopyPaste, &clipboard, &url, &start, &end);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
+ EXPECT_EQ(clipboard, converted_data);
+}
+
+TEST_F(SeatTest, SetSelectionTextUTF8Legacy) {
+ Seat seat;
+
+ // UTF8 encoded data
+ const uint8_t data[] = {
+ 0xe2, 0x9d, 0x84, // SNOWFLAKE
+ 0xf0, 0x9f, 0x94, 0xa5 // FIRE
+ };
+ base::string16 converted_data;
+ EXPECT_TRUE(base::UTF8ToUTF16(reinterpret_cast<const char*>(data),
+ sizeof(data), &converted_data));
+
+ TestDataSourceDelegate delegate;
+ DataSource source(&delegate);
+ source.Offer("UTF8_STRING");
+ delegate.SetData(std::vector<uint8_t>(data, data + sizeof(data)));
+ seat.SetSelection(&source);
+
+ RunReadingTask();
+
+ base::string16 clipboard;
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, converted_data);
}
@@ -167,14 +194,14 @@ TEST_F(SeatTest, SetSelectionTextUTF16LE) {
RunReadingTask();
base::string16 clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
- &clipboard);
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, converted_data);
std::string url;
uint32_t start, end;
ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardType::kCopyPaste, &clipboard, &url, &start, &end);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
EXPECT_EQ(clipboard, converted_data);
}
@@ -202,14 +229,14 @@ TEST_F(SeatTest, SetSelectionTextUTF16BE) {
RunReadingTask();
base::string16 clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
- &clipboard);
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, converted_data);
std::string url;
uint32_t start, end;
ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardType::kCopyPaste, &clipboard, &url, &start, &end);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
EXPECT_EQ(clipboard, converted_data);
}
@@ -228,14 +255,14 @@ TEST_F(SeatTest, SetSelectionTextEmptyString) {
RunReadingTask();
base::string16 clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
- &clipboard);
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard.size(), 0u);
std::string url;
uint32_t start, end;
ui::Clipboard::GetForCurrentThread()->ReadHTML(
- ui::ClipboardType::kCopyPaste, &clipboard, &url, &start, &end);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
EXPECT_EQ(clipboard.size(), 0u);
}
@@ -250,7 +277,7 @@ TEST_F(SeatTest, SetSelectionRTF) {
RunReadingTask();
std::string clipboard;
- ui::Clipboard::GetForCurrentThread()->ReadRTF(ui::ClipboardType::kCopyPaste,
+ ui::Clipboard::GetForCurrentThread()->ReadRTF(ui::ClipboardBuffer::kCopyPaste,
&clipboard);
EXPECT_EQ(clipboard, std::string("TestData"));
@@ -296,7 +323,7 @@ TEST_F(SeatTest, SetSelection_ClipboardChangedDuringSetSelection) {
seat.SetSelection(&source);
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteText(base::UTF8ToUTF16("New data"));
}
@@ -307,7 +334,7 @@ TEST_F(SeatTest, SetSelection_ClipboardChangedDuringSetSelection) {
std::string clipboard;
ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardType::kCopyPaste, &clipboard);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, "New data");
}
@@ -320,7 +347,7 @@ TEST_F(SeatTest, SetSelection_ClipboardChangedAfterSetSelection) {
RunReadingTask();
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteText(base::UTF8ToUTF16("New data"));
}
@@ -329,7 +356,7 @@ TEST_F(SeatTest, SetSelection_ClipboardChangedAfterSetSelection) {
std::string clipboard;
ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardType::kCopyPaste, &clipboard);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, "New data");
}
@@ -337,7 +364,7 @@ TEST_F(SeatTest, SetSelection_SourceDestroyedDuringSetSelection) {
Seat seat;
{
- ui::ScopedClipboardWriter writer(ui::ClipboardType::kCopyPaste);
+ ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
writer.WriteText(base::UTF8ToUTF16("Original data"));
}
@@ -352,7 +379,7 @@ TEST_F(SeatTest, SetSelection_SourceDestroyedDuringSetSelection) {
std::string clipboard;
ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardType::kCopyPaste, &clipboard);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, "Original data");
}
@@ -401,7 +428,7 @@ TEST_F(SeatTest, SetSelection_NullSource) {
std::string clipboard;
ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
- ui::ClipboardType::kCopyPaste, &clipboard);
+ ui::ClipboardBuffer::kCopyPaste, &clipboard);
EXPECT_EQ(clipboard, "");
}
@@ -443,5 +470,21 @@ TEST_F(SeatTest, PressedKeys) {
EXPECT_TRUE(seat.pressed_keys().empty());
}
+TEST_F(SeatTest, DragDropAbort) {
+ Seat seat;
+ TestDataSourceDelegate delegate;
+ DataSource source(&delegate);
+ Surface origin, icon;
+
+ // Give origin a root window for DragDropOperation.
+ CurrentContext()->AddChild(origin.window());
+
+ seat.StartDrag(&source, &origin, &icon,
+ ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_MOUSE);
+ EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
+ seat.AbortPendingDragOperation();
+ EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
+}
+
} // namespace
} // namespace exo
diff --git a/chromium/components/exo/shell_surface_base.cc b/chromium/components/exo/shell_surface_base.cc
index 9d4bc44b1f2..092eff724ce 100644
--- a/chromium/components/exo/shell_surface_base.cc
+++ b/chromium/components/exo/shell_surface_base.cc
@@ -36,6 +36,7 @@
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
+#include "ui/aura/window_occlusion_tracker.h"
#include "ui/aura/window_targeter.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/accelerators/accelerator.h"
@@ -526,6 +527,9 @@ ShellSurfaceBase::AsTracedValue() const {
// SurfaceDelegate overrides:
void ShellSurfaceBase::OnSurfaceCommit() {
+ // Pause occlusion tracking since we will update a bunch of window properties.
+ aura::WindowOcclusionTracker::ScopedPause pause_occlusion;
+
// SetShadowBounds requires synchronizing shadow bounds with the next frame,
// so submit the next frame to a new surface and let the host window use the
// new surface.
@@ -556,6 +560,7 @@ void ShellSurfaceBase::OnSetFrame(SurfaceFrameType frame_type) {
}
bool frame_was_disabled = !frame_enabled();
+ // TODO(b/141151475): Make frame_type a committable property.
frame_type_ = frame_type;
switch (frame_type) {
case SurfaceFrameType::NONE:
@@ -564,9 +569,11 @@ void ShellSurfaceBase::OnSetFrame(SurfaceFrameType frame_type) {
case SurfaceFrameType::NORMAL:
case SurfaceFrameType::AUTOHIDE:
case SurfaceFrameType::OVERLAY:
- // Initialize the shadow if it didn't exist. Do not reset if
- // the frame type just switched from another enabled type.
- if (!shadow_bounds_ || frame_was_disabled)
+ // Initialize the shadow if it didn't exist. Do not reset if
+ // the frame type just switched from another enabled type or
+ // there is a pending shadow_bounds_ change to avoid overriding
+ // a shadow bounds which have been changed and not yet committed.
+ if (!shadow_bounds_ || (frame_was_disabled && !shadow_bounds_changed_))
shadow_bounds_ = gfx::Rect();
break;
case SurfaceFrameType::SHADOW:
@@ -889,7 +896,7 @@ void ShellSurfaceBase::CreateShellSurfaceWidget(
: views::Widget::InitParams::ACTIVATABLE_NO;
// Note: NativeWidget owns this widget.
widget_ = new ShellSurfaceWidget;
- widget_->Init(params);
+ widget_->Init(std::move(params));
aura::Window* window = widget_->GetNativeWindow();
window->SetName("ExoShellSurface");
diff --git a/chromium/components/exo/surface.cc b/chromium/components/exo/surface.cc
index 832ae9ba999..64dfc22c19e 100644
--- a/chromium/components/exo/surface.cc
+++ b/chromium/components/exo/surface.cc
@@ -92,7 +92,6 @@ bool FormatHasAlpha(gfx::BufferFormat format) {
case gfx::BufferFormat::BGRX_8888:
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
- case gfx::BufferFormat::UYVY_422:
return false;
default:
return true;
@@ -225,6 +224,15 @@ const std::string& GetApplicationId(aura::Window* window) {
DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kClientSurfaceIdKey, 0)
+ScopedSurface::ScopedSurface(Surface* surface, SurfaceObserver* observer)
+ : surface_(surface), observer_(observer) {
+ surface_->AddSurfaceObserver(observer_);
+}
+
+ScopedSurface::~ScopedSurface() {
+ surface_->RemoveSurfaceObserver(observer_);
+}
+
////////////////////////////////////////////////////////////////////////////////
// Surface, public:
@@ -265,11 +273,20 @@ Surface* Surface::AsSurface(const aura::Window* window) {
}
void Surface::Attach(Buffer* buffer) {
+ Attach(buffer, gfx::Vector2d());
+}
+
+void Surface::Attach(Buffer* buffer, gfx::Vector2d offset) {
TRACE_EVENT2("exo", "Surface::Attach", "buffer_id",
buffer ? buffer->gfx_buffer() : nullptr, "app_id",
GetApplicationId(window_.get()));
has_pending_contents_ = true;
pending_buffer_.Reset(buffer ? buffer->AsWeakPtr() : base::WeakPtr<Buffer>());
+ pending_state_.offset = offset;
+}
+
+gfx::Vector2d Surface::GetBufferOffset() {
+ return state_.offset;
}
bool Surface::HasPendingAttachedBuffer() const {
@@ -351,9 +368,9 @@ void Surface::RemoveSubSurface(Surface* sub_surface) {
TRACE_EVENT1("exo", "Surface::RemoveSubSurface", "sub_surface",
sub_surface->AsTracedValue());
- window_->RemoveChild(sub_surface->window());
if (sub_surface->window()->IsVisible())
sub_surface->window()->Hide();
+ window_->RemoveChild(sub_surface->window());
DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
pending_sub_surfaces_.erase(
diff --git a/chromium/components/exo/surface.h b/chromium/components/exo/surface.h
index bbe21ecd39e..2feb1f3bc87 100644
--- a/chromium/components/exo/surface.h
+++ b/chromium/components/exo/surface.h
@@ -67,7 +67,7 @@ class Surface final : public ui::PropertyHandler {
using PropertyDeallocator = void (*)(int64_t value);
Surface();
- ~Surface();
+ ~Surface() override;
// Type-checking downcast routine.
static Surface* AsSurface(const aura::Window* window);
@@ -77,6 +77,10 @@ class Surface final : public ui::PropertyHandler {
// Set a buffer as the content of this surface. A buffer can only be attached
// to one surface at a time.
void Attach(Buffer* buffer);
+ void Attach(Buffer* buffer, gfx::Vector2d offset);
+
+ gfx::Vector2d GetBufferOffset();
+
// Returns whether the surface has an uncommitted attached buffer.
bool HasPendingAttachedBuffer() const;
@@ -286,6 +290,7 @@ class Surface final : public ui::PropertyHandler {
bool only_visible_on_secure_output = false;
SkBlendMode blend_mode = SkBlendMode::kSrcOver;
float alpha = 1.0f;
+ gfx::Vector2d offset;
};
class BufferAttachment {
public:
@@ -438,6 +443,19 @@ class Surface final : public ui::PropertyHandler {
DISALLOW_COPY_AND_ASSIGN(Surface);
};
+class ScopedSurface {
+ public:
+ ScopedSurface(Surface* surface, SurfaceObserver* observer);
+ ~ScopedSurface();
+ Surface* get() { return surface_; }
+
+ private:
+ Surface* const surface_;
+ SurfaceObserver* const observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSurface);
+};
+
} // namespace exo
#endif // COMPONENTS_EXO_SURFACE_H_
diff --git a/chromium/components/exo/surface_unittest.cc b/chromium/components/exo/surface_unittest.cc
index 871ddef8de9..331b89a5682 100644
--- a/chromium/components/exo/surface_unittest.cc
+++ b/chromium/components/exo/surface_unittest.cc
@@ -42,6 +42,24 @@ std::unique_ptr<std::vector<gfx::Rect>> GetHitTestShapeRects(Surface* surface) {
return rects;
}
+class SurfaceObserverForTest : public SurfaceObserver {
+ public:
+ SurfaceObserverForTest() = default;
+
+ void OnSurfaceDestroying(Surface* surface) override {}
+
+ void OnWindowOcclusionChanged(Surface* surface) override {
+ num_occlusion_changes_++;
+ }
+
+ int num_occlusion_changes() const { return num_occlusion_changes_; }
+
+ private:
+ int num_occlusion_changes_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(SurfaceObserverForTest);
+};
+
class SurfaceTest : public test::ExoTestBase,
public ::testing::WithParamInterface<float> {
public:
@@ -945,5 +963,36 @@ TEST_P(SurfaceTest, AcquireFence) {
EXPECT_FALSE(surface->HasPendingAcquireFence());
}
+TEST_P(SurfaceTest, UpdatesOcclusionOnDestroyingSubsurface) {
+ gfx::Size buffer_size(256, 512);
+ auto buffer = std::make_unique<Buffer>(
+ exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+ auto surface = std::make_unique<Surface>();
+ auto shell_surface = std::make_unique<ShellSurface>(surface.get());
+ surface->Attach(buffer.get());
+ surface->Commit();
+
+ gfx::Size child_buffer_size(64, 128);
+ auto child_buffer = std::make_unique<Buffer>(
+ exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
+ auto child_surface = std::make_unique<Surface>();
+ auto sub_surface =
+ std::make_unique<SubSurface>(child_surface.get(), surface.get());
+ child_surface->Attach(child_buffer.get());
+ child_surface->Commit();
+ surface->Commit();
+
+ // Turn on occlusion tracking.
+ child_surface->SetOcclusionTracking(true);
+ SurfaceObserverForTest observer;
+ ScopedSurface scoped_child_surface(child_surface.get(), &observer);
+
+ // Destroy the subsurface and expect to get an occlusion update.
+ sub_surface.reset();
+ EXPECT_EQ(1, observer.num_occlusion_changes());
+ EXPECT_EQ(aura::Window::OcclusionState::HIDDEN,
+ child_surface->window()->occlusion_state());
+}
+
} // namespace
} // namespace exo
diff --git a/chromium/components/exo/touch.cc b/chromium/components/exo/touch.cc
index a7b27e1bd48..f68b336f0ad 100644
--- a/chromium/components/exo/touch.cc
+++ b/chromium/components/exo/touch.cc
@@ -5,6 +5,7 @@
#include "components/exo/touch.h"
#include "components/exo/input_trace.h"
+#include "components/exo/seat.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "components/exo/touch_delegate.h"
@@ -47,7 +48,8 @@ gfx::PointF EventLocationInWindow(ui::TouchEvent* event, aura::Window* window) {
////////////////////////////////////////////////////////////////////////////////
// Touch, public:
-Touch::Touch(TouchDelegate* delegate) : delegate_(delegate) {
+Touch::Touch(TouchDelegate* delegate, Seat* seat)
+ : delegate_(delegate), seat_(seat) {
WMHelper::GetInstance()->AddPreTargetHandler(this);
}
@@ -127,6 +129,7 @@ void Touch::OnTouchEvent(ui::TouchEvent* event) {
}
delegate_->OnTouchUp(event->time_stamp(), touch_pointer_id);
+ seat_->AbortPendingDragOperation();
} break;
case ui::ET_TOUCH_MOVED: {
auto it = FindVectorItem(touch_points_, touch_pointer_id);
@@ -155,6 +158,7 @@ void Touch::OnTouchEvent(ui::TouchEvent* event) {
// Cancel the full set of touch sequences as soon as one is canceled.
touch_points_.clear();
delegate_->OnTouchCancel();
+ seat_->AbortPendingDragOperation();
} break;
default:
NOTREACHED();
diff --git a/chromium/components/exo/touch.h b/chromium/components/exo/touch.h
index bfe7878494d..41773052469 100644
--- a/chromium/components/exo/touch.h
+++ b/chromium/components/exo/touch.h
@@ -18,6 +18,7 @@ class TouchEvent;
}
namespace exo {
+class Seat;
class TouchDelegate;
class TouchStylusDelegate;
@@ -25,7 +26,7 @@ class TouchStylusDelegate;
// touch devices.
class Touch : public ui::EventHandler, public SurfaceObserver {
public:
- explicit Touch(TouchDelegate* delegate);
+ Touch(TouchDelegate* delegate, Seat* seat);
~Touch() override;
TouchDelegate* delegate() const { return delegate_; }
@@ -47,6 +48,8 @@ class Touch : public ui::EventHandler, public SurfaceObserver {
// The delegate instance that all events are dispatched to.
TouchDelegate* const delegate_;
+ Seat* const seat_;
+
// The delegate instance that all stylus related events are dispatched to.
TouchStylusDelegate* stylus_delegate_ = nullptr;
diff --git a/chromium/components/exo/touch_unittest.cc b/chromium/components/exo/touch_unittest.cc
index f9737e1264e..96a96cb0ea9 100644
--- a/chromium/components/exo/touch_unittest.cc
+++ b/chromium/components/exo/touch_unittest.cc
@@ -9,6 +9,9 @@
#include "ash/wm/window_positioner.h"
#include "ash/wm/window_positioning_utils.h"
#include "components/exo/buffer.h"
+#include "components/exo/data_source.h"
+#include "components/exo/data_source_delegate.h"
+#include "components/exo/seat.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h"
@@ -52,9 +55,26 @@ class MockTouchStylusDelegate : public TouchStylusDelegate {
MOCK_METHOD3(OnTouchTilt, void(base::TimeTicks, int, const gfx::Vector2dF&));
};
+class TestDataSourceDelegate : public DataSourceDelegate {
+ public:
+ TestDataSourceDelegate() {}
+
+ // Overridden from DataSourceDelegate:
+ void OnDataSourceDestroying(DataSource* device) override {}
+ void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnSend(const std::string& mime_type, base::ScopedFD fd) override {}
+ void OnCancelled() override {}
+ void OnDndDropPerformed() override {}
+ void OnDndFinished() override {}
+ void OnAction(DndAction dnd_action) override {}
+
+ DISALLOW_COPY_AND_ASSIGN(TestDataSourceDelegate);
+};
+
TEST_F(TouchTest, OnTouchDown) {
MockTouchDelegate delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
auto bottom_window = exo_test_helper()->CreateWindow(10, 10, false);
@@ -89,7 +109,8 @@ TEST_F(TouchTest, OnTouchUp) {
auto window = exo_test_helper()->CreateWindow(10, 10, false);
MockTouchDelegate delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_))
@@ -119,7 +140,8 @@ TEST_F(TouchTest, OnTouchMotion) {
auto window = exo_test_helper()->CreateWindow(10, 10, false);
MockTouchDelegate delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_))
@@ -154,7 +176,8 @@ TEST_F(TouchTest, OnTouchShape) {
auto window = exo_test_helper()->CreateWindow(10, 10, false);
MockTouchDelegate delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(window.surface()))
@@ -191,7 +214,8 @@ TEST_F(TouchTest, OnTouchCancel) {
auto window = exo_test_helper()->CreateWindow(10, 10, false);
MockTouchDelegate delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_))
@@ -223,7 +247,8 @@ TEST_F(TouchTest, IgnoreTouchEventDuringModal) {
auto modal = exo_test_helper()->CreateWindow(5, 5, true);
MockTouchDelegate delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
// Make the window modal.
@@ -295,7 +320,8 @@ TEST_F(TouchTest, OnTouchTool) {
MockTouchDelegate delegate;
MockTouchStylusDelegate stylus_delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
touch->SetStylusDelegate(&stylus_delegate);
@@ -329,7 +355,8 @@ TEST_F(TouchTest, OnTouchForce) {
MockTouchDelegate delegate;
MockTouchStylusDelegate stylus_delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
touch->SetStylusDelegate(&stylus_delegate);
@@ -365,7 +392,8 @@ TEST_F(TouchTest, OnTouchTilt) {
MockTouchDelegate delegate;
MockTouchStylusDelegate stylus_delegate;
- std::unique_ptr<Touch> touch(new Touch(&delegate));
+ Seat seat;
+ std::unique_ptr<Touch> touch(new Touch(&delegate, &seat));
ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
touch->SetStylusDelegate(&stylus_delegate);
@@ -397,5 +425,42 @@ TEST_F(TouchTest, OnTouchTilt) {
touch.reset();
}
+TEST_F(TouchTest, DragDropAbort) {
+ Seat seat;
+ MockTouchDelegate touch_delegate;
+ std::unique_ptr<Touch> touch(new Touch(&touch_delegate, &seat));
+ TestDataSourceDelegate data_source_delegate;
+ DataSource source(&data_source_delegate);
+ Surface origin, icon;
+
+ // Make origin into a real window so the touch can click it
+ ShellSurface shell_surface(&origin);
+ Buffer buffer(exo_test_helper()->CreateGpuMemoryBuffer(gfx::Size(10, 10)));
+ origin.Attach(&buffer);
+ origin.Commit();
+
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+ EXPECT_CALL(touch_delegate, CanAcceptTouchEventsForSurface(&origin))
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(touch_delegate, OnTouchFrame()).Times(2);
+ generator.MoveTouch(origin.window()->GetBoundsInScreen().origin());
+
+ seat.StartDrag(&source, &origin, &icon,
+ ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_MOUSE);
+ EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
+
+ EXPECT_CALL(touch_delegate, OnTouchDown).Times(1);
+ EXPECT_CALL(touch_delegate, OnTouchUp).Times(1);
+ EXPECT_CALL(touch_delegate, OnTouchShape).Times(1);
+ generator.PressTouch();
+ EXPECT_TRUE(seat.get_drag_drop_operation_for_testing());
+ generator.ReleaseTouch();
+ EXPECT_FALSE(seat.get_drag_drop_operation_for_testing());
+
+ EXPECT_CALL(touch_delegate, OnTouchDestroying(touch.get()));
+ touch.reset();
+}
+
} // namespace
} // namespace exo
diff --git a/chromium/components/exo/vsync_timing_manager.h b/chromium/components/exo/vsync_timing_manager.h
index 9153dd957d1..ae3e8b0bc63 100644
--- a/chromium/components/exo/vsync_timing_manager.h
+++ b/chromium/components/exo/vsync_timing_manager.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/vsync_parameter_observer.mojom.h"
+#include "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom.h"
namespace exo {
diff --git a/chromium/components/exo/wayland/BUILD.gn b/chromium/components/exo/wayland/BUILD.gn
index fcf347f8cf4..5cc4e341208 100644
--- a/chromium/components/exo/wayland/BUILD.gn
+++ b/chromium/components/exo/wayland/BUILD.gn
@@ -19,6 +19,8 @@ source_set("wayland") {
sources = [
"scoped_wl.cc",
"scoped_wl.h",
+ "serial_tracker.cc",
+ "serial_tracker.h",
"server.cc",
"server.h",
"server_util.cc",
@@ -107,8 +109,8 @@ source_set("wayland") {
"//components/exo",
"//components/exo/wayland/protocol:aura_shell_protocol",
"//device/gamepad",
- "//services/viz/privileged/interfaces/compositing",
- "//services/viz/public/interfaces",
+ "//services/viz/privileged/mojom/compositing",
+ "//services/viz/public/mojom",
"//skia",
"//third_party/libsync",
"//third_party/wayland:wayland_server",
diff --git a/chromium/components/exo/wayland/DEPS b/chromium/components/exo/wayland/DEPS
index a15815d30ee..33a9ebc4583 100644
--- a/chromium/components/exo/wayland/DEPS
+++ b/chromium/components/exo/wayland/DEPS
@@ -1,4 +1,4 @@
include_rules = [
- "+services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h",
+ "+services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h",
"+third_party/wayland/include",
]
diff --git a/chromium/components/exo/wayland/clients/blur_main.cc b/chromium/components/exo/wayland/clients/blur_main.cc
index c6de1318d63..477041346cd 100644
--- a/chromium/components/exo/wayland/clients/blur_main.cc
+++ b/chromium/components/exo/wayland/clients/blur_main.cc
@@ -8,6 +8,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/single_thread_task_executor.h"
#include "components/exo/wayland/clients/blur.h"
@@ -33,8 +34,7 @@ int main(int argc, char* argv[]) {
if (!params.FromCommandLine(*command_line))
return 1;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::Blur client;
if (!client.Init(params))
return 1;
diff --git a/chromium/components/exo/wayland/clients/client_base.cc b/chromium/components/exo/wayland/clients/client_base.cc
index e3086fb742f..03b5407003e 100644
--- a/chromium/components/exo/wayland/clients/client_base.cc
+++ b/chromium/components/exo/wayland/clients/client_base.cc
@@ -322,6 +322,8 @@ ClientBase::InitParams::InitParams() {
ClientBase::InitParams::~InitParams() {}
+ClientBase::InitParams::InitParams(const InitParams& params) = default;
+
bool ClientBase::InitParams::FromCommandLine(
const base::CommandLine& command_line) {
if (command_line.HasSwitch(switches::kSize)) {
@@ -477,9 +479,9 @@ bool ClientBase::Init(const InitParams& params) {
LOG(ERROR) << "Can't create gbm device";
return false;
}
- ui::OzonePlatform::InitParams params;
- params.single_process = true;
- ui::OzonePlatform::InitializeForGPU(params);
+ ui::OzonePlatform::InitParams ozone_params;
+ ozone_params.single_process = true;
+ ui::OzonePlatform::InitializeForGPU(ozone_params);
bool gl_initialized = gl::init::InitializeGLOneOff();
DCHECK(gl_initialized);
gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
@@ -504,21 +506,23 @@ bool ClientBase::Init(const InitParams& params) {
DCHECK(gr_context_);
#if defined(USE_VULKAN)
- vk_implementation_ = gpu::CreateVulkanImplementation();
- CHECK(vk_implementation_) << "Can't create VulkanImplementation";
- bool ret = vk_implementation_->InitializeVulkanInstance(false);
- CHECK(ret) << "Failed to initialize VulkanImplementation";
- vk_instance_ = CreateVkInstance();
- uint32_t queue_family_index = UINT32_MAX;
- vk_device_ = CreateVkDevice(vk_instance_->get(), &queue_family_index);
- CHECK(gpu::GetVulkanFunctionPointers()->BindDeviceFunctionPointers(
- vk_device_->get(), VK_VERSION_1_0, gfx::ExtensionSet()));
- vk_render_pass_ = CreateVkRenderPass(vk_device_->get());
-
- vkGetDeviceQueue(vk_device_->get(), queue_family_index, 0, &vk_queue_);
-
- vk_command_pool_ =
- CreateVkCommandPool(vk_device_->get(), queue_family_index);
+ if (params.use_vulkan) {
+ vk_implementation_ = gpu::CreateVulkanImplementation();
+ CHECK(vk_implementation_) << "Can't create VulkanImplementation";
+ bool ret = vk_implementation_->InitializeVulkanInstance(false);
+ CHECK(ret) << "Failed to initialize VulkanImplementation";
+ vk_instance_ = CreateVkInstance();
+ uint32_t queue_family_index = UINT32_MAX;
+ vk_device_ = CreateVkDevice(vk_instance_->get(), &queue_family_index);
+ CHECK(gpu::GetVulkanFunctionPointers()->BindDeviceFunctionPointers(
+ vk_device_->get(), VK_VERSION_1_0, gfx::ExtensionSet()));
+ vk_render_pass_ = CreateVkRenderPass(vk_device_->get());
+
+ vkGetDeviceQueue(vk_device_->get(), queue_family_index, 0, &vk_queue_);
+
+ vk_command_pool_ =
+ CreateVkCommandPool(vk_device_->get(), queue_family_index);
+ }
#endif // defined(USE_VULKAN)
}
#endif // defined(USE_GBM)
@@ -862,6 +866,8 @@ std::unique_ptr<ClientBase::Buffer> ClientBase::CreateDrmBuffer(
DCHECK(buffer->sk_surface);
#if defined(USE_VULKAN)
+ if (!vk_implementation_)
+ return buffer;
// TODO(dcastagna): remove this hack as soon as the extension
// "VK_EXT_external_memory_dma_buf" is available.
#define VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL 1024
diff --git a/chromium/components/exo/wayland/clients/client_base.h b/chromium/components/exo/wayland/clients/client_base.h
index e948fc55ac6..fca064839c0 100644
--- a/chromium/components/exo/wayland/clients/client_base.h
+++ b/chromium/components/exo/wayland/clients/client_base.h
@@ -38,6 +38,7 @@ class ClientBase {
struct InitParams {
InitParams();
~InitParams();
+ InitParams(const InitParams& params);
bool FromCommandLine(const base::CommandLine& command_line);
@@ -57,6 +58,7 @@ class ClientBase {
bool allocate_buffers_with_output_mode = false;
bool use_fullscreen_shell = false;
bool use_touch = false;
+ bool use_vulkan = false;
};
struct Globals {
diff --git a/chromium/components/exo/wayland/clients/explicit_synchronization.cc b/chromium/components/exo/wayland/clients/explicit_synchronization.cc
index 13bcaccd7cc..cc346d2c231 100644
--- a/chromium/components/exo/wayland/clients/explicit_synchronization.cc
+++ b/chromium/components/exo/wayland/clients/explicit_synchronization.cc
@@ -9,6 +9,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/scoped_file.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/task/single_thread_task_executor.h"
#include "components/exo/wayland/clients/client_helper.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -130,8 +131,7 @@ int main(int argc, char* argv[]) {
if (!params.FromCommandLine(*command_line))
return 1;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::ExplicitSynchronizationClient client;
if (!client.Init(params))
return 1;
diff --git a/chromium/components/exo/wayland/clients/fullscreen_shell_main.cc b/chromium/components/exo/wayland/clients/fullscreen_shell_main.cc
index 5b36cbce1eb..855fa682329 100644
--- a/chromium/components/exo/wayland/clients/fullscreen_shell_main.cc
+++ b/chromium/components/exo/wayland/clients/fullscreen_shell_main.cc
@@ -6,6 +6,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/task/single_thread_task_executor.h"
int main(int argc, char* argv[]) {
@@ -21,8 +22,7 @@ int main(int argc, char* argv[]) {
if (!params.FromCommandLine(*command_line))
return 1;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::FullscreenClient client;
if (!client.Init(params))
diff --git a/chromium/components/exo/wayland/clients/rects.cc b/chromium/components/exo/wayland/clients/rects.cc
index 34c0d3699bd..8205cc37fa6 100644
--- a/chromium/components/exo/wayland/clients/rects.cc
+++ b/chromium/components/exo/wayland/clients/rects.cc
@@ -21,6 +21,7 @@
#include "base/containers/circular_deque.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/scoped_generic.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -572,8 +573,7 @@ int main(int argc, char* argv[]) {
return 1;
}
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::RectsClient client;
return client.Run(params, max_frames_pending, num_rects, num_benchmark_runs,
base::TimeDelta::FromMilliseconds(benchmark_interval_ms),
diff --git a/chromium/components/exo/wayland/clients/simple_main.cc b/chromium/components/exo/wayland/clients/simple_main.cc
index 5e4367b0be2..7e71d8518c4 100644
--- a/chromium/components/exo/wayland/clients/simple_main.cc
+++ b/chromium/components/exo/wayland/clients/simple_main.cc
@@ -8,6 +8,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/task/single_thread_task_executor.h"
#include "components/exo/wayland/clients/simple.h"
@@ -24,8 +25,7 @@ int main(int argc, char* argv[]) {
if (!params.FromCommandLine(*command_line))
return 1;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::Simple client;
if (!client.Init(params))
return 1;
diff --git a/chromium/components/exo/wayland/clients/subsurface.cc b/chromium/components/exo/wayland/clients/subsurface.cc
index e3ed80c49d8..0ef02b65bc0 100644
--- a/chromium/components/exo/wayland/clients/subsurface.cc
+++ b/chromium/components/exo/wayland/clients/subsurface.cc
@@ -4,6 +4,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/stl_util.h"
#include "base/task/single_thread_task_executor.h"
#include "components/exo/wayland/clients/client_base.h"
@@ -154,8 +155,7 @@ int main(int argc, char* argv[]) {
if (!params.FromCommandLine(*command_line))
return 1;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::SubSurfaceClient client;
client.Run(params);
return 1;
diff --git a/chromium/components/exo/wayland/clients/vulkan.cc b/chromium/components/exo/wayland/clients/vulkan.cc
index d39f889fc23..9e91e965360 100644
--- a/chromium/components/exo/wayland/clients/vulkan.cc
+++ b/chromium/components/exo/wayland/clients/vulkan.cc
@@ -4,6 +4,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/stl_util.h"
#include "base/task/single_thread_task_executor.h"
#include "components/exo/wayland/clients/client_base.h"
@@ -175,8 +176,8 @@ int main(int argc, char* argv[]) {
if (!params.FromCommandLine(*command_line))
return 1;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ params.use_vulkan = true;
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::VulkanClient client;
client.Run(params);
return 1;
diff --git a/chromium/components/exo/wayland/clients/yuv.cc b/chromium/components/exo/wayland/clients/yuv.cc
index 7b9cba13e63..32d91e23cc5 100644
--- a/chromium/components/exo/wayland/clients/yuv.cc
+++ b/chromium/components/exo/wayland/clients/yuv.cc
@@ -9,6 +9,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/task/single_thread_task_executor.h"
#include "components/exo/wayland/clients/client_base.h"
#include "components/exo/wayland/clients/client_helper.h"
@@ -136,8 +137,7 @@ int main(int argc, char* argv[]) {
params.bo_usage =
GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR | GBM_BO_USE_TEXTURING;
- base::SingleThreadTaskExecutor main_task_executor(
- base::MessagePump::Type::UI);
+ base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
exo::wayland::clients::YuvClient client;
client.Run(params);
return 1;
diff --git a/chromium/components/exo/wayland/serial_tracker.cc b/chromium/components/exo/wayland/serial_tracker.cc
new file mode 100644
index 00000000000..80f32170bae
--- /dev/null
+++ b/chromium/components/exo/wayland/serial_tracker.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 "components/exo/wayland/serial_tracker.h"
+
+#include <wayland-server-core.h>
+
+namespace exo {
+namespace wayland {
+
+namespace {
+
+// Number of previous events to retain information about.
+constexpr uint32_t kMaxEventsTracked = 1024;
+
+} // namespace
+
+SerialTracker::SerialTracker(struct wl_display* display)
+ : display_(display), events_(kMaxEventsTracked) {}
+
+SerialTracker::~SerialTracker() {}
+
+uint32_t SerialTracker::GetNextSerial(EventType type) {
+ uint32_t serial = wl_display_next_serial(display_);
+ events_[serial % kMaxEventsTracked] = type;
+ max_event_ = serial + 1;
+ if ((max_event_ - min_event_) > kMaxEventsTracked)
+ min_event_ = max_event_ - kMaxEventsTracked;
+
+ switch (type) {
+ case EventType::POINTER_BUTTON_DOWN:
+ pointer_down_serial_ = serial;
+ break;
+ case EventType::POINTER_BUTTON_UP:
+ pointer_down_serial_ = base::nullopt;
+ break;
+ case EventType::TOUCH_DOWN:
+ touch_down_serial_ = serial;
+ break;
+ case EventType::TOUCH_UP:
+ touch_down_serial_ = base::nullopt;
+ break;
+ default:
+ break;
+ }
+
+ return serial;
+}
+
+base::Optional<SerialTracker::EventType> SerialTracker::GetEventType(
+ uint32_t serial) const {
+ if (max_event_ < min_event_) {
+ // The valid range has partially overflowed the 32 bit space, so we should
+ // only reject if the serial number is in neither the upper nor lower parts
+ // of the space.
+ if (!((serial < max_event_) || (serial >= min_event_)))
+ return base::nullopt;
+ } else {
+ // Normal, non-overflowed case. Reject the serial number if it isn't in the
+ // interval.
+ if (!((serial < max_event_) && (serial >= min_event_)))
+ return base::nullopt;
+ }
+
+ return events_[serial % kMaxEventsTracked];
+}
+
+base::Optional<uint32_t> SerialTracker::GetPointerDownSerial() {
+ return pointer_down_serial_;
+}
+
+base::Optional<uint32_t> SerialTracker::GetTouchDownSerial() {
+ return touch_down_serial_;
+}
+
+void SerialTracker::ResetTouchDownSerial() {
+ touch_down_serial_ = base::nullopt;
+}
+
+} // namespace wayland
+} // namespace exo
diff --git a/chromium/components/exo/wayland/serial_tracker.h b/chromium/components/exo/wayland/serial_tracker.h
new file mode 100644
index 00000000000..81d11266b4f
--- /dev/null
+++ b/chromium/components/exo/wayland/serial_tracker.h
@@ -0,0 +1,76 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_WAYLAND_SERIAL_TRACKER_H_
+#define COMPONENTS_EXO_WAYLAND_SERIAL_TRACKER_H_
+
+#include <map>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/optional.h"
+
+struct wl_display;
+
+namespace exo {
+namespace wayland {
+
+class SerialTracker {
+ public:
+ enum EventType {
+ POINTER_ENTER,
+ POINTER_LEAVE,
+ POINTER_BUTTON_DOWN,
+ POINTER_BUTTON_UP,
+
+ TOUCH_DOWN,
+ TOUCH_UP,
+
+ OTHER_EVENT,
+ };
+
+ explicit SerialTracker(struct wl_display* display);
+ ~SerialTracker();
+
+ uint32_t GetNextSerial(EventType type);
+
+ // Get the serial number of the last {pointer,touch} pressed event, or nullopt
+ // if the press has since been released.
+ base::Optional<uint32_t> GetPointerDownSerial();
+ base::Optional<uint32_t> GetTouchDownSerial();
+
+ // Needed because wl_touch::cancel doesn't send a serial number, so we can't
+ // test for it in GetNextSerial.
+ void ResetTouchDownSerial();
+
+ // Get the EventType for a serial number, or nullopt if the serial number was
+ // never sent or is too old.
+ base::Optional<EventType> GetEventType(uint32_t serial) const;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SerialTrackerTest, WrapAroundWholeRange);
+
+ struct wl_display* const display_;
+
+ // EventTypes are stored in a circular buffer, because serial numbers are
+ // issued sequentially and we only want to store the most recent events.
+ std::vector<EventType> events_;
+
+ // [min_event_, max_event) is a half-open interval containing the range of
+ // valid serial numbers. Note that as serial numbers are allowed to wrap
+ // around the 32 bit space, we cannot assume that max_event_ >= min_event_.
+ uint32_t min_event_ = 1;
+ uint32_t max_event_ = 1;
+
+ base::Optional<uint32_t> pointer_down_serial_;
+ base::Optional<uint32_t> touch_down_serial_;
+
+ DISALLOW_COPY_AND_ASSIGN(SerialTracker);
+};
+
+} // namespace wayland
+} // namespace exo
+
+#endif // COMPONENTS_EXO_WAYLAND_SERIAL_TRACKER_H_
diff --git a/chromium/components/exo/wayland/server.cc b/chromium/components/exo/wayland/server.cc
index c2baa3eb9ca..a3471c59711 100644
--- a/chromium/components/exo/wayland/server.cc
+++ b/chromium/components/exo/wayland/server.cc
@@ -35,6 +35,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "components/exo/display.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/wayland_display_output.h"
#include "components/exo/wayland/wl_compositor.h"
#include "components/exo/wayland/wl_data_device_manager.h"
@@ -103,7 +104,9 @@ const char kWaylandSocketGroup[] = "wayland";
// Server, public:
Server::Server(Display* display)
- : display_(display), wl_display_(wl_display_create()) {
+ : display_(display),
+ wl_display_(wl_display_create()),
+ serial_tracker_(std::make_unique<SerialTracker>(wl_display_.get())) {
wl_global_create(wl_display_.get(), &wl_compositor_interface,
kWlCompositorVersion, display_, bind_compositor);
wl_global_create(wl_display_.get(), &wl_shm_interface, 1, display_, bind_shm);
@@ -118,9 +121,13 @@ Server::Server(Display* display)
OnDisplayAdded(display);
wl_global_create(wl_display_.get(), &zcr_vsync_feedback_v1_interface, 1,
display_, bind_vsync_feedback);
+
+ data_device_manager_data_ = std::make_unique<WaylandDataDeviceManager>(
+ display_, serial_tracker_.get());
wl_global_create(wl_display_.get(), &wl_data_device_manager_interface,
- kWlDataDeviceManagerVersion, display_,
+ kWlDataDeviceManagerVersion, data_device_manager_data_.get(),
bind_data_device_manager);
+
wl_global_create(wl_display_.get(), &wp_viewporter_interface, 1, display_,
bind_viewporter);
wl_global_create(wl_display_.get(), &wp_presentation_interface, 1, display_,
@@ -131,8 +138,12 @@ Server::Server(Display* display)
display_, bind_alpha_compositing);
wl_global_create(wl_display_.get(), &zcr_stylus_v2_interface, 1, display_,
bind_stylus_v2);
+
+ seat_data_ =
+ std::make_unique<WaylandSeat>(display_->seat(), serial_tracker_.get());
wl_global_create(wl_display_.get(), &wl_seat_interface, kWlSeatVersion,
- display_->seat(), bind_seat);
+ seat_data_.get(), bind_seat);
+
wl_global_create(wl_display_.get(),
&zwp_linux_explicit_synchronization_v1_interface, 1,
display_, bind_linux_explicit_synchronization);
@@ -164,10 +175,16 @@ Server::Server(Display* display)
wl_global_create(wl_display_.get(),
&zwp_relative_pointer_manager_v1_interface, 1, display_,
bind_relative_pointer_manager);
+
+ zwp_text_manager_data_ =
+ std::make_unique<WaylandTextInputManager>(serial_tracker_.get());
wl_global_create(wl_display_.get(), &zwp_text_input_manager_v1_interface, 1,
- display_, bind_text_input_manager);
- wl_global_create(wl_display_.get(), &zxdg_shell_v6_interface, 1, display_,
- bind_xdg_shell_v6);
+ zwp_text_manager_data_.get(), bind_text_input_manager);
+
+ xdg_shell_data_ =
+ std::make_unique<WaylandXdgShell>(display_, serial_tracker_.get());
+ wl_global_create(wl_display_.get(), &zxdg_shell_v6_interface, 1,
+ xdg_shell_data_.get(), bind_xdg_shell_v6);
#endif
#if defined(USE_FULLSCREEN_SHELL)
diff --git a/chromium/components/exo/wayland/server.h b/chromium/components/exo/wayland/server.h
index 2344d50d468..3f36907b9af 100644
--- a/chromium/components/exo/wayland/server.h
+++ b/chromium/components/exo/wayland/server.h
@@ -19,7 +19,12 @@ class Display;
namespace wayland {
+class SerialTracker;
+struct WaylandDataDeviceManager;
class WaylandDisplayOutput;
+struct WaylandSeat;
+struct WaylandTextInputManager;
+struct WaylandXdgShell;
// This class is a thin wrapper around a Wayland display server. All Wayland
// requests are dispatched into the given Exosphere display.
@@ -55,7 +60,15 @@ class Server : public display::DisplayObserver {
private:
Display* const display_;
std::unique_ptr<wl_display, WlDisplayDeleter> wl_display_;
+ std::unique_ptr<SerialTracker> serial_tracker_;
base::flat_map<int64_t, std::unique_ptr<WaylandDisplayOutput>> outputs_;
+ std::unique_ptr<WaylandDataDeviceManager> data_device_manager_data_;
+ std::unique_ptr<WaylandSeat> seat_data_;
+
+#if defined(OS_CHROMEOS)
+ std::unique_ptr<WaylandTextInputManager> zwp_text_manager_data_;
+ std::unique_ptr<WaylandXdgShell> xdg_shell_data_;
+#endif
DISALLOW_COPY_AND_ASSIGN(Server);
};
diff --git a/chromium/components/exo/wayland/wayland_keyboard_delegate.cc b/chromium/components/exo/wayland/wayland_keyboard_delegate.cc
index 1023f8086a0..64cf8e31794 100644
--- a/chromium/components/exo/wayland/wayland_keyboard_delegate.cc
+++ b/chromium/components/exo/wayland/wayland_keyboard_delegate.cc
@@ -8,6 +8,7 @@
#include <wayland-server-protocol-core.h>
#include "base/containers/flat_map.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "ui/events/keycodes/dom/dom_code.h"
namespace exo {
@@ -15,9 +16,11 @@ namespace wayland {
#if BUILDFLAG(USE_XKBCOMMON)
-WaylandKeyboardDelegate::WaylandKeyboardDelegate(wl_resource* keyboard_resource)
+WaylandKeyboardDelegate::WaylandKeyboardDelegate(wl_resource* keyboard_resource,
+ SerialTracker* serial_tracker)
: keyboard_resource_(keyboard_resource),
- xkb_context_(xkb_context_new(XKB_CONTEXT_NO_FLAGS)) {
+ xkb_context_(xkb_context_new(XKB_CONTEXT_NO_FLAGS)),
+ serial_tracker_(serial_tracker) {
#if defined(OS_CHROMEOS)
ash::ImeController* ime_controller = ash::Shell::Get()->ime_controller();
ime_controller->AddObserver(this);
@@ -59,8 +62,10 @@ void WaylandKeyboardDelegate::OnKeyboardEnter(
DCHECK(value);
*value = DomCodeToKey(entry.second);
}
- wl_keyboard_send_enter(keyboard_resource_, next_serial(), surface_resource,
- &keys);
+ wl_keyboard_send_enter(
+ keyboard_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
+ surface_resource, &keys);
wl_array_release(&keys);
wl_client_flush(client());
}
@@ -68,14 +73,18 @@ void WaylandKeyboardDelegate::OnKeyboardEnter(
void WaylandKeyboardDelegate::OnKeyboardLeave(Surface* surface) {
wl_resource* surface_resource = GetSurfaceResource(surface);
DCHECK(surface_resource);
- wl_keyboard_send_leave(keyboard_resource_, next_serial(), surface_resource);
+ wl_keyboard_send_leave(
+ keyboard_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
+ surface_resource);
wl_client_flush(client());
}
uint32_t WaylandKeyboardDelegate::OnKeyboardKey(base::TimeTicks time_stamp,
ui::DomCode key,
bool pressed) {
- uint32_t serial = next_serial();
+ uint32_t serial =
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT);
SendTimestamp(time_stamp);
wl_keyboard_send_key(
keyboard_resource_, serial, TimeTicksToMilliseconds(time_stamp),
@@ -147,7 +156,8 @@ void WaylandKeyboardDelegate::SendKeyboardModifiers() {
xkb_state_update_mask(xkb_state_.get(), ModifierFlagsToXkbModifiers(), 0, 0,
0, 0, 0);
wl_keyboard_send_modifiers(
- keyboard_resource_, next_serial(),
+ keyboard_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LOCKED),
xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LATCHED),
@@ -197,10 +207,6 @@ wl_client* WaylandKeyboardDelegate::client() const {
return wl_resource_get_client(keyboard_resource_);
}
-uint32_t WaylandKeyboardDelegate::next_serial() const {
- return wl_display_next_serial(wl_client_get_display(client()));
-}
-
#endif
} // namespace wayland
diff --git a/chromium/components/exo/wayland/wayland_keyboard_delegate.h b/chromium/components/exo/wayland/wayland_keyboard_delegate.h
index ee5d4476f42..fab13750971 100644
--- a/chromium/components/exo/wayland/wayland_keyboard_delegate.h
+++ b/chromium/components/exo/wayland/wayland_keyboard_delegate.h
@@ -31,6 +31,7 @@ struct wl_resource;
namespace exo {
namespace wayland {
+class SerialTracker;
// Keyboard delegate class that accepts events for surfaces owned by the same
// client as a keyboard resource.
@@ -44,7 +45,8 @@ class WaylandKeyboardDelegate : public WaylandInputDelegate,
{
#if BUILDFLAG(USE_XKBCOMMON)
public:
- explicit WaylandKeyboardDelegate(wl_resource* keyboard_resource);
+ explicit WaylandKeyboardDelegate(wl_resource* keyboard_resource,
+ SerialTracker* serial_tracker);
#if defined(OS_CHROMEOS)
~WaylandKeyboardDelegate() override;
@@ -89,9 +91,6 @@ class WaylandKeyboardDelegate : public WaylandInputDelegate,
// The client who own this keyboard instance.
wl_client* client() const;
- // Returns the next serial to use for keyboard events.
- uint32_t next_serial() const;
-
// The keyboard resource associated with the keyboard.
wl_resource* const keyboard_resource_;
@@ -104,6 +103,9 @@ class WaylandKeyboardDelegate : public WaylandInputDelegate,
// we treat numlock as always on.
int modifier_flags_ = ui::EF_NUM_LOCK_ON;
+ // Owned by Server, which always outlives this delegate.
+ SerialTracker* const serial_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandKeyboardDelegate);
#endif
};
diff --git a/chromium/components/exo/wayland/wayland_pointer_delegate.cc b/chromium/components/exo/wayland/wayland_pointer_delegate.cc
index 20784f5b727..0dff8a6208e 100644
--- a/chromium/components/exo/wayland/wayland_pointer_delegate.cc
+++ b/chromium/components/exo/wayland/wayland_pointer_delegate.cc
@@ -9,6 +9,7 @@
#include <wayland-server-protocol-core.h>
#include "components/exo/pointer.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
@@ -16,8 +17,9 @@
namespace exo {
namespace wayland {
-WaylandPointerDelegate::WaylandPointerDelegate(wl_resource* pointer_resource)
- : pointer_resource_(pointer_resource) {}
+WaylandPointerDelegate::WaylandPointerDelegate(wl_resource* pointer_resource,
+ SerialTracker* serial_tracker)
+ : pointer_resource_(pointer_resource), serial_tracker_(serial_tracker) {}
void WaylandPointerDelegate::OnPointerDestroying(Pointer* pointer) {
delete this;
@@ -39,15 +41,20 @@ void WaylandPointerDelegate::OnPointerEnter(Surface* surface,
DCHECK(surface_resource);
// Should we be sending button events to the client before the enter event
// if client's pressed button state is different from |button_flags|?
- wl_pointer_send_enter(pointer_resource_, next_serial(), surface_resource,
- wl_fixed_from_double(location.x()),
- wl_fixed_from_double(location.y()));
+ wl_pointer_send_enter(
+ pointer_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::POINTER_ENTER),
+ surface_resource, wl_fixed_from_double(location.x()),
+ wl_fixed_from_double(location.y()));
}
void WaylandPointerDelegate::OnPointerLeave(Surface* surface) {
wl_resource* surface_resource = GetSurfaceResource(surface);
DCHECK(surface_resource);
- wl_pointer_send_leave(pointer_resource_, next_serial(), surface_resource);
+ wl_pointer_send_leave(
+ pointer_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::POINTER_LEAVE),
+ surface_resource);
}
void WaylandPointerDelegate::OnPointerMotion(base::TimeTicks time_stamp,
@@ -71,11 +78,14 @@ void WaylandPointerDelegate::OnPointerButton(base::TimeTicks time_stamp,
{ui::EF_FORWARD_MOUSE_BUTTON, BTN_FORWARD},
{ui::EF_BACK_MOUSE_BUTTON, BTN_BACK},
};
- uint32_t serial = next_serial();
for (auto button : buttons) {
if (button_flags & button.flag) {
SendTimestamp(time_stamp);
- wl_pointer_send_button(pointer_resource_, serial,
+ SerialTracker::EventType event_type =
+ pressed ? SerialTracker::EventType::POINTER_BUTTON_DOWN
+ : SerialTracker::EventType::POINTER_BUTTON_UP;
+ wl_pointer_send_button(pointer_resource_,
+ serial_tracker_->GetNextSerial(event_type),
TimeTicksToMilliseconds(time_stamp), button.value,
pressed ? WL_POINTER_BUTTON_STATE_PRESSED
: WL_POINTER_BUTTON_STATE_RELEASED);
@@ -135,9 +145,5 @@ wl_client* WaylandPointerDelegate::client() const {
return wl_resource_get_client(pointer_resource_);
}
-uint32_t WaylandPointerDelegate::next_serial() const {
- return wl_display_next_serial(wl_client_get_display(client()));
-}
-
} // namespace wayland
} // namespace exo
diff --git a/chromium/components/exo/wayland/wayland_pointer_delegate.h b/chromium/components/exo/wayland/wayland_pointer_delegate.h
index 07d53a9794b..55b6578c13f 100644
--- a/chromium/components/exo/wayland/wayland_pointer_delegate.h
+++ b/chromium/components/exo/wayland/wayland_pointer_delegate.h
@@ -13,13 +13,15 @@ struct wl_resource;
namespace exo {
namespace wayland {
+class SerialTracker;
// Pointer delegate class that accepts events for surfaces owned by the same
// client as a pointer resource.
class WaylandPointerDelegate : public WaylandInputDelegate,
public PointerDelegate {
public:
- explicit WaylandPointerDelegate(wl_resource* pointer_resource);
+ explicit WaylandPointerDelegate(wl_resource* pointer_resource,
+ SerialTracker* serial_tracker);
// Overridden from PointerDelegate:
void OnPointerDestroying(Pointer* pointer) override;
@@ -43,12 +45,12 @@ class WaylandPointerDelegate : public WaylandInputDelegate,
// The client who own this pointer instance.
wl_client* client() const;
- // Returns the next serial to use for pointer events.
- uint32_t next_serial() const;
-
// The pointer resource associated with the pointer.
wl_resource* const pointer_resource_;
+ // Owned by Server, which always outlives this delegate.
+ SerialTracker* const serial_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandPointerDelegate);
};
diff --git a/chromium/components/exo/wayland/wayland_touch_delegate.cc b/chromium/components/exo/wayland/wayland_touch_delegate.cc
index af0087e653d..040e8efddef 100644
--- a/chromium/components/exo/wayland/wayland_touch_delegate.cc
+++ b/chromium/components/exo/wayland/wayland_touch_delegate.cc
@@ -8,13 +8,15 @@
#include <wayland-server-protocol-core.h>
#include "components/exo/touch.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
namespace exo {
namespace wayland {
-WaylandTouchDelegate::WaylandTouchDelegate(wl_resource* touch_resource)
- : touch_resource_(touch_resource) {}
+WaylandTouchDelegate::WaylandTouchDelegate(wl_resource* touch_resource,
+ SerialTracker* serial_tracker)
+ : touch_resource_(touch_resource), serial_tracker_(serial_tracker) {}
void WaylandTouchDelegate::OnTouchDestroying(Touch* touch) {
delete this;
@@ -35,15 +37,18 @@ void WaylandTouchDelegate::OnTouchDown(Surface* surface,
wl_resource* surface_resource = GetSurfaceResource(surface);
DCHECK(surface_resource);
SendTimestamp(time_stamp);
- wl_touch_send_down(touch_resource_, next_serial(),
- TimeTicksToMilliseconds(time_stamp), surface_resource, id,
- wl_fixed_from_double(location.x()),
- wl_fixed_from_double(location.y()));
+ wl_touch_send_down(
+ touch_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::TOUCH_DOWN),
+ TimeTicksToMilliseconds(time_stamp), surface_resource, id,
+ wl_fixed_from_double(location.x()), wl_fixed_from_double(location.y()));
}
void WaylandTouchDelegate::OnTouchUp(base::TimeTicks time_stamp, int id) {
SendTimestamp(time_stamp);
- wl_touch_send_up(touch_resource_, next_serial(),
- TimeTicksToMilliseconds(time_stamp), id);
+ wl_touch_send_up(
+ touch_resource_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::TOUCH_UP),
+ TimeTicksToMilliseconds(time_stamp), id);
}
void WaylandTouchDelegate::OnTouchMotion(base::TimeTicks time_stamp,
int id,
@@ -69,15 +74,12 @@ void WaylandTouchDelegate::OnTouchFrame() {
}
void WaylandTouchDelegate::OnTouchCancel() {
wl_touch_send_cancel(touch_resource_);
+ serial_tracker_->ResetTouchDownSerial();
}
wl_client* WaylandTouchDelegate::client() const {
return wl_resource_get_client(touch_resource_);
}
-uint32_t WaylandTouchDelegate::next_serial() const {
- return wl_display_next_serial(wl_client_get_display(client()));
-}
-
} // namespace wayland
} // namespace exo
diff --git a/chromium/components/exo/wayland/wayland_touch_delegate.h b/chromium/components/exo/wayland/wayland_touch_delegate.h
index c6b4298da1c..bb2912c3a87 100644
--- a/chromium/components/exo/wayland/wayland_touch_delegate.h
+++ b/chromium/components/exo/wayland/wayland_touch_delegate.h
@@ -13,12 +13,14 @@ struct wl_resource;
namespace exo {
namespace wayland {
+class SerialTracker;
// Touch delegate class that accepts events for surfaces owned by the same
// client as a touch resource.
class WaylandTouchDelegate : public WaylandInputDelegate, public TouchDelegate {
public:
- explicit WaylandTouchDelegate(wl_resource* touch_resource);
+ explicit WaylandTouchDelegate(wl_resource* touch_resource,
+ SerialTracker* serial_tracker);
// Overridden from TouchDelegate:
void OnTouchDestroying(Touch* touch) override;
@@ -39,12 +41,12 @@ class WaylandTouchDelegate : public WaylandInputDelegate, public TouchDelegate {
// The client who own this touch instance.
wl_client* client() const;
- // Returns the next serial to use for keyboard events.
- uint32_t next_serial() const;
-
// The touch resource associated with the touch.
wl_resource* const touch_resource_;
+ // Owned by Server, which always outlives this delegate.
+ SerialTracker* const serial_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandTouchDelegate);
};
diff --git a/chromium/components/exo/wayland/wayland_watcher.cc b/chromium/components/exo/wayland/wayland_watcher.cc
index f2dad436d7b..bc2d4b96d4a 100644
--- a/chromium/components/exo/wayland/wayland_watcher.cc
+++ b/chromium/components/exo/wayland/wayland_watcher.cc
@@ -15,7 +15,7 @@ WaylandWatcher::WaylandWatcher(wayland::Server* server)
base::MessageLoopCurrentForUI::Get()->WatchFileDescriptor(
server_->GetFileDescriptor(),
true, // persistent
- base::MessagePumpLibevent::WATCH_READ, &controller_, this);
+ base::MessagePumpForUI::WATCH_READ, &controller_, this);
}
WaylandWatcher::~WaylandWatcher() {}
diff --git a/chromium/components/exo/wayland/wayland_watcher.h b/chromium/components/exo/wayland/wayland_watcher.h
index fae62e63da7..ea1677465b8 100644
--- a/chromium/components/exo/wayland/wayland_watcher.h
+++ b/chromium/components/exo/wayland/wayland_watcher.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_EXO_WAYLAND_WAYLAND_WATCHER_H_
#define COMPONENTS_EXO_WAYLAND_WAYLAND_WATCHER_H_
-#include "base/message_loop/message_pump_libevent.h"
+#include "base/message_loop/message_pump_for_ui.h"
#include "base/message_loop/watchable_io_message_pump_posix.h"
namespace exo {
@@ -13,18 +13,18 @@ namespace wayland {
class Server;
-class WaylandWatcher : public base::MessagePumpLibevent::FdWatcher {
+class WaylandWatcher : public base::MessagePumpForUI::FdWatcher {
public:
explicit WaylandWatcher(wayland::Server* server);
~WaylandWatcher() override;
private:
- // base::MessagePumpLibevent::FdWatcher:
+ // base::MessagePumpForUI::FdWatcher:
void OnFileCanReadWithoutBlocking(int fd) override;
void OnFileCanWriteWithoutBlocking(int fd) override;
- base::MessagePumpLibevent::FdWatchController controller_;
+ base::MessagePumpForUI::FdWatchController controller_;
wayland::Server* const server_;
DISALLOW_COPY_AND_ASSIGN(WaylandWatcher);
diff --git a/chromium/components/exo/wayland/wl_compositor.cc b/chromium/components/exo/wayland/wl_compositor.cc
index 1c7d1633e50..f05ee416626 100644
--- a/chromium/components/exo/wayland/wl_compositor.cc
+++ b/chromium/components/exo/wayland/wl_compositor.cc
@@ -63,12 +63,8 @@ void surface_attach(wl_client* client,
wl_resource* buffer,
int32_t x,
int32_t y) {
- // TODO(reveman): Implement buffer offset support.
- DLOG_IF(WARNING, x || y) << "Unsupported buffer offset: "
- << gfx::Point(x, y).ToString();
-
GetUserDataAs<Surface>(resource)->Attach(
- buffer ? GetUserDataAs<Buffer>(buffer) : nullptr);
+ buffer ? GetUserDataAs<Buffer>(buffer) : nullptr, gfx::Vector2d(x, y));
}
void surface_damage(wl_client* client,
diff --git a/chromium/components/exo/wayland/wl_data_device_manager.cc b/chromium/components/exo/wayland/wl_data_device_manager.cc
index 37e5a16bbc1..846d79447c7 100644
--- a/chromium/components/exo/wayland/wl_data_device_manager.cc
+++ b/chromium/components/exo/wayland/wl_data_device_manager.cc
@@ -18,6 +18,7 @@
#include "components/exo/data_source.h"
#include "components/exo/data_source_delegate.h"
#include "components/exo/display.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
namespace exo {
@@ -83,8 +84,9 @@ class WaylandDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* device) override { delete this; }
- void OnTarget(const std::string& mime_type) override {
- wl_data_source_send_target(data_source_resource_, mime_type.c_str());
+ void OnTarget(const base::Optional<std::string>& mime_type) override {
+ wl_data_source_send_target(data_source_resource_,
+ mime_type ? mime_type->c_str() : nullptr);
wl_client_flush(wl_resource_get_client(data_source_resource_));
}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
@@ -221,16 +223,20 @@ void data_offer_set_actions(wl_client* client,
}
const struct wl_data_offer_interface data_offer_implementation = {
- data_offer_accept, data_offer_receive, data_offer_finish,
- data_offer_destroy, data_offer_set_actions};
+ data_offer_accept, data_offer_receive, data_offer_destroy,
+ data_offer_finish, data_offer_set_actions};
////////////////////////////////////////////////////////////////////////////////
// wl_data_device_interface:
class WaylandDataDeviceDelegate : public DataDeviceDelegate {
public:
- WaylandDataDeviceDelegate(wl_client* client, wl_resource* device_resource)
- : client_(client), data_device_resource_(device_resource) {}
+ WaylandDataDeviceDelegate(wl_client* client,
+ wl_resource* device_resource,
+ SerialTracker* serial_tracker)
+ : client_(client),
+ data_device_resource_(device_resource),
+ serial_tracker_(serial_tracker) {}
// Overridden from DataDeviceDelegate:
void OnDataDeviceDestroying(DataDevice* device) override { delete this; }
@@ -258,7 +264,7 @@ class WaylandDataDeviceDelegate : public DataDeviceDelegate {
const DataOffer& data_offer) override {
wl_data_device_send_enter(
data_device_resource_,
- wl_display_next_serial(wl_client_get_display(client_)),
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
GetSurfaceResource(surface), wl_fixed_from_double(point.x()),
wl_fixed_from_double(point.y()), GetDataOfferResource(&data_offer));
wl_client_flush(client_);
@@ -283,10 +289,35 @@ class WaylandDataDeviceDelegate : public DataDeviceDelegate {
wl_client_flush(client_);
}
+ void StartDrag(DataDevice* data_device,
+ DataSource* source,
+ Surface* origin,
+ Surface* icon,
+ uint32_t serial) {
+ base::Optional<wayland::SerialTracker::EventType> event_type =
+ serial_tracker_->GetEventType(serial);
+ if (event_type == wayland::SerialTracker::EventType::POINTER_BUTTON_DOWN &&
+ serial_tracker_->GetPointerDownSerial() == serial) {
+ data_device->StartDrag(
+ source, origin, icon,
+ ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_MOUSE);
+ } else if (event_type == wayland::SerialTracker::EventType::TOUCH_DOWN &&
+ serial_tracker_->GetTouchDownSerial() == serial) {
+ data_device->StartDrag(
+ source, origin, icon,
+ ui::DragDropTypes::DragEventSource::DRAG_EVENT_SOURCE_TOUCH);
+ } else {
+ source->Cancelled();
+ }
+ }
+
private:
wl_client* const client_;
wl_resource* const data_device_resource_;
+ // Owned by Server, which always outlives this delegate.
+ SerialTracker* const serial_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandDataDeviceDelegate);
};
@@ -296,10 +327,15 @@ void data_device_start_drag(wl_client* client,
wl_resource* origin_resource,
wl_resource* icon_resource,
uint32_t serial) {
- GetUserDataAs<DataDevice>(resource)->StartDrag(
- source_resource ? GetUserDataAs<DataSource>(source_resource) : nullptr,
- GetUserDataAs<Surface>(origin_resource),
- icon_resource ? GetUserDataAs<Surface>(icon_resource) : nullptr, serial);
+ DataDevice* data_device = GetUserDataAs<DataDevice>(resource);
+ static_cast<WaylandDataDeviceDelegate*>(data_device->get_delegate())
+ ->StartDrag(
+ data_device,
+ source_resource ? GetUserDataAs<DataSource>(source_resource)
+ : nullptr,
+ GetUserDataAs<Surface>(origin_resource),
+ icon_resource ? GetUserDataAs<Surface>(icon_resource) : nullptr,
+ serial);
}
void data_device_set_selection(wl_client* client,
@@ -334,12 +370,13 @@ void data_device_manager_get_data_device(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* seat_resource) {
- Display* display = GetUserDataAs<Display>(resource);
+ auto* data = GetUserDataAs<WaylandDataDeviceManager>(resource);
wl_resource* data_device_resource = wl_resource_create(
client, &wl_data_device_interface, wl_resource_get_version(resource), id);
- SetImplementation(data_device_resource, &data_device_implementation,
- display->CreateDataDevice(new WaylandDataDeviceDelegate(
- client, data_device_resource)));
+ SetImplementation(
+ data_device_resource, &data_device_implementation,
+ data->display->CreateDataDevice(new WaylandDataDeviceDelegate(
+ client, data_device_resource, data->serial_tracker)));
}
const struct wl_data_device_manager_interface
diff --git a/chromium/components/exo/wayland/wl_data_device_manager.h b/chromium/components/exo/wayland/wl_data_device_manager.h
index 33b39ff1118..ea4dabe376b 100644
--- a/chromium/components/exo/wayland/wl_data_device_manager.h
+++ b/chromium/components/exo/wayland/wl_data_device_manager.h
@@ -7,13 +7,32 @@
#include <stdint.h>
+#include "base/macros.h"
+
struct wl_client;
namespace exo {
+class Display;
+
namespace wayland {
+class SerialTracker;
constexpr uint32_t kWlDataDeviceManagerVersion = 3;
+struct WaylandDataDeviceManager {
+ WaylandDataDeviceManager(Display* display, SerialTracker* serial_tracker)
+ : display(display), serial_tracker(serial_tracker) {}
+
+ // Owned by WaylandServerController, which always outlives
+ // wl_data_device_manager.
+ Display* const display;
+
+ // Owned by Server, which always outlives wl_data_device_manager.
+ SerialTracker* const serial_tracker;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandDataDeviceManager);
+};
+
void bind_data_device_manager(wl_client* client,
void* data,
uint32_t version,
diff --git a/chromium/components/exo/wayland/wl_seat.cc b/chromium/components/exo/wayland/wl_seat.cc
index 25178180b40..80c2f2bfc01 100644
--- a/chromium/components/exo/wayland/wl_seat.cc
+++ b/chromium/components/exo/wayland/wl_seat.cc
@@ -9,6 +9,7 @@
#include "components/exo/pointer.h"
#include "components/exo/touch.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
#include "components/exo/wayland/wayland_pointer_delegate.h"
#include "components/exo/wayland/wayland_touch_delegate.h"
@@ -72,25 +73,31 @@ const struct wl_touch_interface touch_implementation = {touch_release};
// wl_seat_interface:
void seat_get_pointer(wl_client* client, wl_resource* resource, uint32_t id) {
+ auto* data = GetUserDataAs<WaylandSeat>(resource);
+
wl_resource* pointer_resource = wl_resource_create(
client, &wl_pointer_interface, wl_resource_get_version(resource), id);
SetImplementation(
pointer_resource, &pointer_implementation,
- std::make_unique<Pointer>(new WaylandPointerDelegate(pointer_resource)));
+ std::make_unique<Pointer>(
+ new WaylandPointerDelegate(pointer_resource, data->serial_tracker),
+ data->seat));
}
void seat_get_keyboard(wl_client* client, wl_resource* resource, uint32_t id) {
#if defined(OS_CHROMEOS)
#if BUILDFLAG(USE_XKBCOMMON)
+ auto* data = GetUserDataAs<WaylandSeat>(resource);
+
uint32_t version = wl_resource_get_version(resource);
wl_resource* keyboard_resource =
wl_resource_create(client, &wl_keyboard_interface, version, id);
WaylandKeyboardDelegate* delegate =
- new WaylandKeyboardDelegate(keyboard_resource);
+ new WaylandKeyboardDelegate(keyboard_resource, data->serial_tracker);
std::unique_ptr<Keyboard> keyboard =
- std::make_unique<Keyboard>(delegate, GetUserDataAs<Seat>(resource));
+ std::make_unique<Keyboard>(delegate, data->seat);
keyboard->AddObserver(delegate);
SetImplementation(keyboard_resource, &keyboard_implementation,
std::move(keyboard));
@@ -107,12 +114,16 @@ void seat_get_keyboard(wl_client* client, wl_resource* resource, uint32_t id) {
}
void seat_get_touch(wl_client* client, wl_resource* resource, uint32_t id) {
+ auto* data = GetUserDataAs<WaylandSeat>(resource);
+
wl_resource* touch_resource = wl_resource_create(
client, &wl_touch_interface, wl_resource_get_version(resource), id);
SetImplementation(
touch_resource, &touch_implementation,
- std::make_unique<Touch>(new WaylandTouchDelegate(touch_resource)));
+ std::make_unique<Touch>(
+ new WaylandTouchDelegate(touch_resource, data->serial_tracker),
+ data->seat));
}
void seat_release(wl_client* client, wl_resource* resource) {
diff --git a/chromium/components/exo/wayland/wl_seat.h b/chromium/components/exo/wayland/wl_seat.h
index 2d10ca33180..84e2b981ce5 100644
--- a/chromium/components/exo/wayland/wl_seat.h
+++ b/chromium/components/exo/wayland/wl_seat.h
@@ -7,13 +7,31 @@
#include <stdint.h>
+#include "base/macros.h"
+
struct wl_client;
namespace exo {
+class Seat;
+
namespace wayland {
+class SerialTracker;
constexpr uint32_t kWlSeatVersion = 6;
+struct WaylandSeat {
+ WaylandSeat(Seat* seat, SerialTracker* serial_tracker)
+ : seat(seat), serial_tracker(serial_tracker) {}
+
+ // Owned by Display, which always outlives wl_seat.
+ Seat* const seat;
+
+ // Owned by Server, which always outlives wl_seat.
+ SerialTracker* const serial_tracker;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandSeat);
+};
+
void bind_seat(wl_client* client, void* data, uint32_t version, uint32_t id);
} // namespace wayland
diff --git a/chromium/components/exo/wayland/zaura_shell.cc b/chromium/components/exo/wayland/zaura_shell.cc
index a912432892f..dca7d48ad27 100644
--- a/chromium/components/exo/wayland/zaura_shell.cc
+++ b/chromium/components/exo/wayland/zaura_shell.cc
@@ -21,6 +21,7 @@
#include "ui/aura/window_occlusion_tracker.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/display_util.h"
+#include "ui/display/screen.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/public/activation_client.h"
@@ -201,7 +202,7 @@ void AuraSurface::OnSurfaceDestroying(Surface* surface) {
}
void AuraSurface::OnWindowOcclusionChanged(Surface* surface) {
- if (!surface_)
+ if (!surface_ || !surface_->is_tracking_occlusion())
return;
auto* window = surface_->window();
ComputeAndSendOcclusionFraction(window->occlusion_state(),
@@ -279,19 +280,31 @@ void AuraSurface::ComputeAndSendOcclusionFraction(
float fraction_occluded = 0.0f;
switch (occlusion_state) {
case aura::Window::OcclusionState::VISIBLE: {
+ const gfx::Rect display_bounds_in_screen =
+ display::Screen::GetScreen()
+ ->GetDisplayNearestWindow(window)
+ .bounds();
const gfx::Rect bounds_in_screen = GetTransformedBoundsInScreen(window);
const int tracked_area =
bounds_in_screen.width() * bounds_in_screen.height();
- int occluded_area = 0;
SkRegion tracked_and_occluded_region = occluded_region;
tracked_and_occluded_region.op(gfx::RectToSkIRect(bounds_in_screen),
SkRegion::Op::kIntersect_Op);
+
+ // Clip the area outside of the display.
+ gfx::Rect area_inside_display = bounds_in_screen;
+ area_inside_display.Intersect(display_bounds_in_screen);
+ int occluded_area = tracked_area - area_inside_display.width() *
+ area_inside_display.height();
+
for (SkRegion::Iterator i(tracked_and_occluded_region); !i.done();
i.next()) {
occluded_area += i.rect().width() * i.rect().height();
}
- fraction_occluded =
- static_cast<float>(occluded_area) / static_cast<float>(tracked_area);
+ if (tracked_area) {
+ fraction_occluded = static_cast<float>(occluded_area) /
+ static_cast<float>(tracked_area);
+ }
break;
}
case aura::Window::OcclusionState::OCCLUDED:
@@ -302,7 +315,6 @@ void AuraSurface::ComputeAndSendOcclusionFraction(
case aura::Window::OcclusionState::UNKNOWN:
return; // Window is not tracked.
}
-
SendOcclusionFraction(fraction_occluded);
}
diff --git a/chromium/components/exo/wayland/zaura_shell_unittest.cc b/chromium/components/exo/wayland/zaura_shell_unittest.cc
index 8b08f93d507..0ee896e301f 100644
--- a/chromium/components/exo/wayland/zaura_shell_unittest.cc
+++ b/chromium/components/exo/wayland/zaura_shell_unittest.cc
@@ -13,6 +13,7 @@
#include "base/time/time.h"
#include "components/exo/test/exo_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/window_occlusion_tracker.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
@@ -203,7 +204,7 @@ TEST_F(ZAuraSurfaceTest,
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.context = CurrentContext();
params.bounds = gfx::Rect(0, 0, 100, 100);
- lock_widget->Init(params);
+ lock_widget->Init(std::move(params));
ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(),
ash::kShellWindowId_LockScreenContainer)
->AddChild(lock_widget->GetNativeView());
@@ -224,5 +225,22 @@ TEST_F(ZAuraSurfaceTest,
EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
}
+TEST_F(ZAuraSurfaceTest, OcclusionIncludesOffScreenArea) {
+ UpdateDisplay("150x150");
+ // This is scaled by 1.5 - set the bounds to (-60, 75, 120, 150) in screen
+ // coordinates so 75% of it is outside of the 100x100 screen.
+ surface().window()->SetBounds(gfx::Rect(-40, 50, 80, 100));
+ surface().OnWindowOcclusionChanged();
+
+ EXPECT_EQ(0.75f, aura_surface().last_sent_occlusion_fraction());
+}
+
+TEST_F(ZAuraSurfaceTest, ZeroSizeWindowSendsZeroOcclusionFraction) {
+ // Zero sized window should not be occluded.
+ surface().window()->SetBounds(gfx::Rect(0, 0, 0, 0));
+ surface().OnWindowOcclusionChanged();
+ EXPECT_EQ(0.0f, aura_surface().last_sent_occlusion_fraction());
+}
+
} // namespace wayland
} // namespace exo
diff --git a/chromium/components/exo/wayland/zcr_gaming_input.cc b/chromium/components/exo/wayland/zcr_gaming_input.cc
index 515b2059f99..ad9a7464fad 100644
--- a/chromium/components/exo/wayland/zcr_gaming_input.cc
+++ b/chromium/components/exo/wayland/zcr_gaming_input.cc
@@ -21,11 +21,6 @@ namespace wayland {
namespace {
-// Expose raw gamepad device information to the client.
-// TODO(tetsui): Remove when the change becomes default.
-const base::Feature kRawGamepadInfoFeature{"ExoRawGamepadInfo",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
unsigned int GetGamepadBusType(ui::InputDeviceType type) {
switch (type) {
case ui::INPUT_DEVICE_BLUETOOTH:
@@ -69,37 +64,21 @@ class WaylandGamepadDelegate : public GamepadDelegate {
wl_resource_set_user_data(gamepad_resource_, nullptr);
delete this;
}
- void OnAxis(int axis, int raw_axis, double value) override {
+ void OnAxis(int axis, double value) override {
if (!gamepad_resource_) {
return;
}
- // There are two types of axis events: Web Gamepad remapped and raw. When
- // |axis| is not WG_ABS_COUNT, it's Web Gamepad remapped. ExoRawGamepadInfo
- // expects raw events to be forawrded, so we should discard remapped ones.
- // TODO(tetsui): Remove this when Web Gamepad mapping in Ozone is removed.
- if (base::FeatureList::IsEnabled(kRawGamepadInfoFeature) &&
- axis != ui::WG_ABS_COUNT) {
- return;
- }
- zcr_gamepad_v2_send_axis(
- gamepad_resource_, NowInMilliseconds(),
- base::FeatureList::IsEnabled(kRawGamepadInfoFeature) ? raw_axis : axis,
- wl_fixed_from_double(value));
+ zcr_gamepad_v2_send_axis(gamepad_resource_, NowInMilliseconds(), axis,
+ wl_fixed_from_double(value));
}
- void OnButton(int button,
- int raw_button,
- bool pressed,
- double value) override {
+ void OnButton(int button, bool pressed) override {
if (!gamepad_resource_) {
return;
}
uint32_t state = pressed ? ZCR_GAMEPAD_V2_BUTTON_STATE_PRESSED
: ZCR_GAMEPAD_V2_BUTTON_STATE_RELEASED;
- zcr_gamepad_v2_send_button(
- gamepad_resource_, NowInMilliseconds(),
- base::FeatureList::IsEnabled(kRawGamepadInfoFeature) ? raw_button
- : button,
- state, wl_fixed_from_double(value));
+ zcr_gamepad_v2_send_button(gamepad_resource_, NowInMilliseconds(), button,
+ state, wl_fixed_from_double(0));
}
void OnFrame() override {
if (!gamepad_resource_) {
@@ -158,22 +137,17 @@ class WaylandGamingSeatDelegate : public GamingSeatDelegate {
gamepad_resource, &gamepad_implementation, gamepad_delegate,
&WaylandGamepadDelegate::ResetGamepadResource);
- if (base::FeatureList::IsEnabled(kRawGamepadInfoFeature)) {
- zcr_gaming_seat_v2_send_gamepad_added_with_device_info(
- gaming_seat_resource_, gamepad_resource, device.name.c_str(),
- GetGamepadBusType(device.type), device.vendor_id, device.product_id,
- device.version);
-
- for (const auto& axis : device.axes) {
- zcr_gamepad_v2_send_axis_added(gamepad_resource, axis.code,
- axis.min_value, axis.max_value,
- axis.flat, axis.fuzz, axis.resolution);
- }
- zcr_gamepad_v2_send_activated(gamepad_resource);
- } else {
- zcr_gaming_seat_v2_send_gamepad_added(gaming_seat_resource_,
- gamepad_resource);
+ zcr_gaming_seat_v2_send_gamepad_added_with_device_info(
+ gaming_seat_resource_, gamepad_resource, device.name.c_str(),
+ GetGamepadBusType(device.type), device.vendor_id, device.product_id,
+ device.version);
+
+ for (const auto& axis : device.axes) {
+ zcr_gamepad_v2_send_axis_added(gamepad_resource, axis.code,
+ axis.min_value, axis.max_value, axis.flat,
+ axis.fuzz, axis.resolution);
}
+ zcr_gamepad_v2_send_activated(gamepad_resource);
wl_client_flush(wl_resource_get_client(gaming_seat_resource_));
return gamepad_delegate;
diff --git a/chromium/components/exo/wayland/zcr_notification_shell.cc b/chromium/components/exo/wayland/zcr_notification_shell.cc
index e7470d038f4..5b7eb80fa9f 100644
--- a/chromium/components/exo/wayland/zcr_notification_shell.cc
+++ b/chromium/components/exo/wayland/zcr_notification_shell.cc
@@ -43,7 +43,7 @@ class WaylandNotificationShellNotification {
const std::string& notification_id,
const std::vector<std::string>& buttons,
wl_resource* resource)
- : resource_(resource), weak_ptr_factory_(this) {
+ : resource_(resource) {
notification_ = std::make_unique<Notification>(
title, message, display_source, notification_id,
kNotificationShellNotifierId, buttons,
@@ -70,7 +70,8 @@ class WaylandNotificationShellNotification {
wl_resource* const resource_;
std::unique_ptr<Notification> notification_;
- base::WeakPtrFactory<WaylandNotificationShellNotification> weak_ptr_factory_;
+ base::WeakPtrFactory<WaylandNotificationShellNotification> weak_ptr_factory_{
+ this};
DISALLOW_COPY_AND_ASSIGN(WaylandNotificationShellNotification);
};
diff --git a/chromium/components/exo/wayland/zcr_remote_shell.cc b/chromium/components/exo/wayland/zcr_remote_shell.cc
index 0ab01749301..dfaba70ceb8 100644
--- a/chromium/components/exo/wayland/zcr_remote_shell.cc
+++ b/chromium/components/exo/wayland/zcr_remote_shell.cc
@@ -37,6 +37,7 @@
#include "ui/display/screen.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/caption_button_types.h"
+#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/window_animations.h"
#include "ui/wm/public/activation_change_observer.h"
@@ -631,9 +632,7 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
public display::DisplayObserver {
public:
WaylandRemoteShell(Display* display, wl_resource* remote_shell_resource)
- : display_(display),
- remote_shell_resource_(remote_shell_resource),
- weak_ptr_factory_(this) {
+ : display_(display), remote_shell_resource_(remote_shell_resource) {
WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
helper->AddTabletModeObserver(this);
helper->AddActivationObserver(this);
@@ -681,6 +680,29 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
default_device_scale_factor);
}
+ // TODO(mukai, oshima): rewrite this through delegate-style instead of
+ // creating callbacks.
+ ClientControlledShellSurface::BoundsChangedCallback
+ CreateBoundsChangedCallback(wl_resource* resource) {
+ return base::BindRepeating(
+ &WaylandRemoteShell::HandleRemoteSurfaceBoundsChangedCallback,
+ weak_ptr_factory_.GetWeakPtr(), base::Unretained(resource));
+ }
+
+ ClientControlledShellSurface::StateChangedCallback CreateStateChangedCallback(
+ wl_resource* resource) {
+ return base::BindRepeating(
+ &WaylandRemoteShell::HandleRemoteSurfaceStateChangedCallback,
+ weak_ptr_factory_.GetWeakPtr(), base::Unretained(resource));
+ }
+
+ ClientControlledShellSurface::GeometryChangedCallback
+ CreateGeometryChangedCallback(wl_resource* resource) {
+ return base::BindRepeating(
+ &WaylandRemoteShell::HandleRemoteSurfaceGeometryChangedCallback,
+ weak_ptr_factory_.GetWeakPtr(), base::Unretained(resource));
+ }
+
// Overridden from display::DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override {
ScheduleSendDisplayMetrics(0);
@@ -835,7 +857,20 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
}
zcr_remote_shell_v1_send_configure(remote_shell_resource_, layout_mode_);
- wl_client_flush(wl_resource_get_client(remote_shell_resource_));
+
+ base::flat_set<wl_client*> clients;
+ clients.insert(wl_resource_get_client(remote_shell_resource_));
+
+ for (const auto& bounds_change : pending_bounds_changes_) {
+ SendBoundsChanged(bounds_change.first, bounds_change.second.display_id,
+ bounds_change.second.bounds_in_display,
+ bounds_change.second.reason);
+ clients.insert(wl_resource_get_client(bounds_change.first));
+ }
+ pending_bounds_changes_.clear();
+
+ for (auto* client : clients)
+ wl_client_flush(client);
}
void SendActivated(aura::Window* gained_active, aura::Window* lost_active) {
@@ -871,6 +906,140 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
wl_client_flush(client);
}
+ void HandleRemoteSurfaceBoundsChangedCallback(
+ wl_resource* resource,
+ ash::WindowStateType current_state,
+ ash::WindowStateType requested_state,
+ int64_t display_id,
+ const gfx::Rect& bounds_in_display,
+ bool resize,
+ int bounds_change) {
+ zcr_remote_surface_v1_bounds_change_reason reason =
+ ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE;
+ if (!resize) {
+ reason = current_state == ash::WindowStateType::kPip
+ ? ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE_PIP
+ : ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE;
+ }
+ if (bounds_change & ash::WindowResizer::kBoundsChange_Resizes) {
+ reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE;
+ } else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) {
+ reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE;
+ }
+ // Override the reason only if the window enters snapped mode. If the window
+ // resizes by dragging in snapped mode, we need to keep the original reason.
+ if (requested_state != current_state) {
+ if (requested_state == ash::WindowStateType::kLeftSnapped) {
+ reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT;
+ } else if (requested_state == ash::WindowStateType::kRightSnapped) {
+ reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT;
+ }
+ }
+ if (wl_resource_get_version(resource) >= 22) {
+ if (needs_send_display_metrics_) {
+ pending_bounds_changes_.emplace(
+ std::make_pair<wl_resource*, BoundsChangeData>(
+ std::move(resource),
+ BoundsChangeData(display_id, bounds_in_display, reason)));
+ return;
+ }
+ SendBoundsChanged(resource, display_id, bounds_in_display, reason);
+ } else {
+ gfx::Rect bounds_in_screen = gfx::Rect(bounds_in_display);
+ display::Display display;
+ display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id,
+ &display);
+ // The display ID should be valid.
+ DCHECK(display.is_valid());
+ if (display.is_valid())
+ bounds_in_screen.Offset(display.bounds().OffsetFromOrigin());
+ else
+ LOG(ERROR) << "Invalid Display in send_bounds_changed:" << display_id;
+
+ zcr_remote_surface_v1_send_bounds_changed(
+ resource, static_cast<uint32_t>(display_id >> 32),
+ static_cast<uint32_t>(display_id), bounds_in_screen.x(),
+ bounds_in_screen.y(), bounds_in_screen.width(),
+ bounds_in_screen.height(), reason);
+ }
+ wl_client_flush(wl_resource_get_client(resource));
+ }
+
+ void SendBoundsChanged(wl_resource* resource,
+ int64_t display_id,
+ const gfx::Rect& bounds_in_display,
+ zcr_remote_surface_v1_bounds_change_reason reason) {
+ zcr_remote_surface_v1_send_bounds_changed(
+ resource, static_cast<uint32_t>(display_id >> 32),
+ static_cast<uint32_t>(display_id), bounds_in_display.x(),
+ bounds_in_display.y(), bounds_in_display.width(),
+ bounds_in_display.height(), reason);
+ }
+
+ void HandleRemoteSurfaceStateChangedCallback(
+ wl_resource* resource,
+ ash::WindowStateType old_state_type,
+ ash::WindowStateType new_state_type) {
+ DCHECK_NE(old_state_type, new_state_type);
+ LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0)
+ << "Sending window state while there is a pending bounds change. This "
+ "should not happen.";
+
+ uint32_t state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL;
+ switch (new_state_type) {
+ case ash::WindowStateType::kMinimized:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED;
+ break;
+ case ash::WindowStateType::kMaximized:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED;
+ break;
+ case ash::WindowStateType::kFullscreen:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN;
+ break;
+ case ash::WindowStateType::kPinned:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED;
+ break;
+ case ash::WindowStateType::kTrustedPinned:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED;
+ break;
+ case ash::WindowStateType::kLeftSnapped:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED;
+ break;
+ case ash::WindowStateType::kRightSnapped:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED;
+ break;
+ case ash::WindowStateType::kPip:
+ state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP;
+ break;
+ default:
+ break;
+ }
+
+ zcr_remote_surface_v1_send_state_type_changed(resource, state_type);
+ wl_client_flush(wl_resource_get_client(resource));
+ }
+
+ void HandleRemoteSurfaceGeometryChangedCallback(wl_resource* resource,
+ const gfx::Rect& geometry) {
+ LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0)
+ << "Sending the new window geometry while there is a pending bounds "
+ "change. This should not happen.";
+ zcr_remote_surface_v1_send_window_geometry_changed(
+ resource, geometry.x(), geometry.y(), geometry.width(),
+ geometry.height());
+ wl_client_flush(wl_resource_get_client(resource));
+ }
+
+ struct BoundsChangeData {
+ int64_t display_id;
+ gfx::Rect bounds_in_display;
+ zcr_remote_surface_v1_bounds_change_reason reason;
+ BoundsChangeData(int64_t display_id,
+ const gfx::Rect& bounds,
+ zcr_remote_surface_v1_bounds_change_reason reason)
+ : display_id(display_id), bounds_in_display(bounds), reason(reason) {}
+ };
+
// The exo display instance. Not owned.
Display* const display_;
@@ -881,7 +1050,9 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
int layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
- base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_;
+ base::flat_map<wl_resource*, BoundsChangeData> pending_bounds_changes_;
+
+ base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WaylandRemoteShell);
};
@@ -907,82 +1078,6 @@ void HandleRemoteSurfaceCloseCallback(wl_resource* resource) {
wl_client_flush(wl_resource_get_client(resource));
}
-void HandleRemoteSurfaceStateChangedCallback(
- wl_resource* resource,
- ash::WindowStateType old_state_type,
- ash::WindowStateType new_state_type) {
- DCHECK_NE(old_state_type, new_state_type);
-
- uint32_t state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL;
- switch (new_state_type) {
- case ash::WindowStateType::kMinimized:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED;
- break;
- case ash::WindowStateType::kMaximized:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED;
- break;
- case ash::WindowStateType::kFullscreen:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN;
- break;
- case ash::WindowStateType::kPinned:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED;
- break;
- case ash::WindowStateType::kTrustedPinned:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED;
- break;
- case ash::WindowStateType::kLeftSnapped:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED;
- break;
- case ash::WindowStateType::kRightSnapped:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED;
- break;
- case ash::WindowStateType::kPip:
- state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP;
- break;
- default:
- break;
- }
-
- zcr_remote_surface_v1_send_state_type_changed(resource, state_type);
- wl_client_flush(wl_resource_get_client(resource));
-}
-
-void HandleRemoteSurfaceBoundsChangedCallback(
- wl_resource* resource,
- ash::WindowStateType current_state,
- ash::WindowStateType requested_state,
- int64_t display_id,
- const gfx::Rect& bounds,
- bool resize,
- int bounds_change) {
- zcr_remote_surface_v1_bounds_change_reason reason =
- ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE;
- if (!resize) {
- reason = current_state == ash::WindowStateType::kPip
- ? ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE_PIP
- : ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE;
- }
- if (bounds_change & ash::WindowResizer::kBoundsChange_Resizes) {
- reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE;
- } else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) {
- reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE;
- }
- // Override the reason only if the window enters snapped mode. If the window
- // resizes by dragging in snapped mode, we need to keep the original reason.
- if (requested_state != current_state) {
- if (requested_state == ash::WindowStateType::kLeftSnapped) {
- reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT;
- } else if (requested_state == ash::WindowStateType::kRightSnapped) {
- reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT;
- }
- }
- zcr_remote_surface_v1_send_bounds_changed(
- resource, static_cast<uint32_t>(display_id >> 32),
- static_cast<uint32_t>(display_id), bounds.x(), bounds.y(), bounds.width(),
- bounds.height(), reason);
- wl_client_flush(wl_resource_get_client(resource));
-}
-
void HandleRemoteSurfaceDragStartedCallback(wl_resource* resource,
int component) {
zcr_remote_surface_v1_send_drag_started(resource, ResizeDirection(component));
@@ -997,14 +1092,6 @@ void HandleRemoteSurfaceDragFinishedCallback(wl_resource* resource,
wl_client_flush(wl_resource_get_client(resource));
}
-void HandleRemoteSurfaceGeometryChangedCallback(wl_resource* resource,
- const gfx::Rect& geometry) {
- zcr_remote_surface_v1_send_window_geometry_changed(
- resource, geometry.x(), geometry.y(), geometry.width(),
- geometry.height());
- wl_client_flush(wl_resource_get_client(resource));
-}
-
void remote_shell_get_remote_surface(wl_client* client,
wl_resource* resource,
uint32_t id,
@@ -1036,18 +1123,15 @@ void remote_shell_get_remote_surface(wl_client* client,
base::Bind(&HandleRemoteSurfaceCloseCallback,
base::Unretained(remote_surface_resource)));
shell_surface->set_state_changed_callback(
- base::Bind(&HandleRemoteSurfaceStateChangedCallback,
- base::Unretained(remote_surface_resource)));
+ shell->CreateStateChangedCallback(remote_surface_resource));
shell_surface->set_geometry_changed_callback(
- base::BindRepeating(&HandleRemoteSurfaceGeometryChangedCallback,
- base::Unretained(remote_surface_resource)));
+ shell->CreateGeometryChangedCallback(remote_surface_resource));
shell_surface->set_surface_destroyed_callback(base::BindOnce(
&wl_resource_destroy, base::Unretained(remote_surface_resource)));
DCHECK(wl_resource_get_version(remote_surface_resource) >= 10);
shell_surface->set_bounds_changed_callback(
- base::BindRepeating(&HandleRemoteSurfaceBoundsChangedCallback,
- base::Unretained(remote_surface_resource)));
+ shell->CreateBoundsChangedCallback(remote_surface_resource));
shell_surface->set_drag_started_callback(
base::BindRepeating(&HandleRemoteSurfaceDragStartedCallback,
base::Unretained(remote_surface_resource)));
@@ -1140,8 +1224,6 @@ gfx::Insets GetWorkAreaInsetsInClientPixel(
float default_dsf,
const gfx::Size& size_in_client_pixel,
const gfx::Rect& work_area_in_dp) {
- gfx::Rect work_area_in_display = display.work_area();
- work_area_in_display.Offset(-display.bounds().x(), -display.bounds().y());
gfx::Rect local_work_area_in_dp = work_area_in_dp;
local_work_area_in_dp.Offset(-display.bounds().x(), -display.bounds().y());
gfx::Rect work_area_in_client_pixel = ScaleBoundsToPixelSnappedToParent(
diff --git a/chromium/components/exo/wayland/zcr_remote_shell.h b/chromium/components/exo/wayland/zcr_remote_shell.h
index 3d55ad71892..4b9112d4ed5 100644
--- a/chromium/components/exo/wayland/zcr_remote_shell.h
+++ b/chromium/components/exo/wayland/zcr_remote_shell.h
@@ -22,7 +22,7 @@ class Display;
namespace exo {
namespace wayland {
-constexpr uint32_t kZcrRemoteShellVersion = 21;
+constexpr uint32_t kZcrRemoteShellVersion = 22;
void bind_remote_shell(wl_client* client,
void* data,
diff --git a/chromium/components/exo/wayland/zcr_remote_shell_unittest.cc b/chromium/components/exo/wayland/zcr_remote_shell_unittest.cc
index 66d89954f6c..d16e88d22ab 100644
--- a/chromium/components/exo/wayland/zcr_remote_shell_unittest.cc
+++ b/chromium/components/exo/wayland/zcr_remote_shell_unittest.cc
@@ -16,17 +16,21 @@ using ZcrRemoteShellTest = test::ExoTestBase;
TEST_F(ZcrRemoteShellTest, GetWorkAreaInsetsInClientPixel) {
UpdateDisplay("3000x2000*2.25,1920x1080");
+
auto display = display::Screen::GetScreen()->GetPrimaryDisplay();
+ const float device_scale_factor = display.device_scale_factor();
+ EXPECT_EQ(2.25f, device_scale_factor);
gfx::Insets insets = wayland::GetWorkAreaInsetsInClientPixel(
- display, 2.25f, gfx::Size(3000, 2000), display.work_area());
- EXPECT_EQ(gfx::Insets(0, 0, 128, 0), insets);
+ display, device_scale_factor, display.GetSizeInPixel(),
+ display.work_area());
+ EXPECT_EQ(gfx::Insets(0, 0, 128, 0).ToString(), insets.ToString());
auto secondary_display = GetSecondaryDisplay();
- gfx::Size secondary_size(1920, 1080);
+ gfx::Size secondary_size(secondary_display.size());
gfx::Size secondary_size_in_client_pixel =
- gfx::ScaleToRoundedSize(secondary_size, 2.25f);
+ gfx::ScaleToRoundedSize(secondary_size, device_scale_factor);
gfx::Insets secondary_insets = wayland::GetWorkAreaInsetsInClientPixel(
- secondary_display, 2.25f, secondary_size_in_client_pixel,
+ secondary_display, device_scale_factor, secondary_size_in_client_pixel,
secondary_display.work_area());
EXPECT_EQ(gfx::Insets(0, 0, 126, 0).ToString(), secondary_insets.ToString());
@@ -36,11 +40,11 @@ TEST_F(ZcrRemoteShellTest, GetWorkAreaInsetsInClientPixel) {
display = display::Screen::GetScreen()->GetPrimaryDisplay();
ASSERT_EQ(display.bounds(), display.work_area());
gfx::Insets stable_insets = wayland::GetWorkAreaInsetsInClientPixel(
- display, 2.25f, gfx::Size(3000, 2000),
+ display, device_scale_factor, display.GetSizeInPixel(),
wayland::GetStableWorkArea(display));
EXPECT_EQ(gfx::Insets(0, 0, 128, 0).ToString(), stable_insets.ToString());
gfx::Insets secondary_stable_insets = wayland::GetWorkAreaInsetsInClientPixel(
- secondary_display, 2.25f, secondary_size_in_client_pixel,
+ secondary_display, device_scale_factor, secondary_size_in_client_pixel,
wayland::GetStableWorkArea(secondary_display));
EXPECT_EQ(gfx::Insets(0, 0, 126, 0).ToString(),
secondary_stable_insets.ToString());
diff --git a/chromium/components/exo/wayland/zwp_fullscreen_shell.cc b/chromium/components/exo/wayland/zwp_fullscreen_shell.cc
index d58ffae1bd3..2e73a9731c5 100644
--- a/chromium/components/exo/wayland/zwp_fullscreen_shell.cc
+++ b/chromium/components/exo/wayland/zwp_fullscreen_shell.cc
@@ -27,16 +27,10 @@ void fullscreen_shell_present_surface(wl_client* client,
wl_resource* surface,
uint32_t method,
wl_resource* output) {
- std::unique_ptr<FullscreenShellSurface> fullscreen_shell_surface =
- std::make_unique<FullscreenShellSurface>(GetUserDataAs<Surface>(surface));
- fullscreen_shell_surface->SetEnabled(true);
- wl_resource* fullscreen_shell_surface_resource =
- wl_resource_create(client, &zwp_fullscreen_shell_v1_interface, 1, 0);
- fullscreen_shell_surface->set_surface_destroyed_callback(
- base::BindOnce(&wl_resource_destroy,
- base::Unretained(fullscreen_shell_surface_resource)));
- SetImplementation(fullscreen_shell_surface_resource, nullptr,
- std::move(fullscreen_shell_surface));
+ FullscreenShellSurface* fullscreen_shell_surface =
+ GetUserDataAs<FullscreenShellSurface>(resource);
+ fullscreen_shell_surface->SetSurface(surface ? GetUserDataAs<Surface>(surface)
+ : nullptr);
}
void fullscreen_shell_present_surface_for_mode(wl_client* client,
@@ -58,11 +52,15 @@ void bind_fullscreen_shell(wl_client* client,
void* data,
uint32_t version,
uint32_t id) {
+ std::unique_ptr<FullscreenShellSurface> fullscreen_shell_surface =
+ std::make_unique<FullscreenShellSurface>();
+ fullscreen_shell_surface->SetEnabled(true);
wl_resource* resource =
wl_resource_create(client, &zwp_fullscreen_shell_v1_interface, 1, id);
-
- wl_resource_set_implementation(resource, &fullscreen_shell_implementation,
- data, nullptr);
+ fullscreen_shell_surface->set_surface_destroyed_callback(
+ base::BindOnce(&wl_resource_destroy, base::Unretained(resource)));
+ SetImplementation(resource, &fullscreen_shell_implementation,
+ std::move(fullscreen_shell_surface));
}
} // namespace wayland
diff --git a/chromium/components/exo/wayland/zwp_text_input_manager.cc b/chromium/components/exo/wayland/zwp_text_input_manager.cc
index 38bd505c7c1..dfdfa952416 100644
--- a/chromium/components/exo/wayland/zwp_text_input_manager.cc
+++ b/chromium/components/exo/wayland/zwp_text_input_manager.cc
@@ -9,7 +9,9 @@
#include <wayland-server-protocol-core.h>
#include "base/strings/utf_string_conversions.h"
+#include "components/exo/display.h"
#include "components/exo/text_input.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -28,7 +30,9 @@ namespace {
class WaylandTextInputDelegate : public TextInput::Delegate {
public:
- WaylandTextInputDelegate(wl_resource* text_input) : text_input_(text_input) {}
+ WaylandTextInputDelegate(wl_resource* text_input,
+ SerialTracker* serial_tracker)
+ : text_input_(text_input), serial_tracker_(serial_tracker) {}
~WaylandTextInputDelegate() override = default;
void set_surface(wl_resource* surface) { surface_ = surface; }
@@ -36,10 +40,6 @@ class WaylandTextInputDelegate : public TextInput::Delegate {
private:
wl_client* client() { return wl_resource_get_client(text_input_); }
- uint32_t next_serial() {
- return wl_display_next_serial(wl_client_get_display(client()));
- }
-
// TextInput::Delegate:
void Activated() override {
zwp_text_input_v1_send_enter(text_input_, surface_);
@@ -87,15 +87,19 @@ class WaylandTextInputDelegate : public TextInput::Delegate {
zwp_text_input_v1_send_preedit_cursor(text_input_, pos);
const std::string utf8 = base::UTF16ToUTF8(composition.text);
- zwp_text_input_v1_send_preedit_string(text_input_, next_serial(),
- utf8.c_str(), utf8.c_str());
+ zwp_text_input_v1_send_preedit_string(
+ text_input_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
+ utf8.c_str(), utf8.c_str());
wl_client_flush(client());
}
void Commit(const base::string16& text) override {
- zwp_text_input_v1_send_commit_string(text_input_, next_serial(),
- base::UTF16ToUTF8(text).c_str());
+ zwp_text_input_v1_send_commit_string(
+ text_input_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
+ base::UTF16ToUTF8(text).c_str());
wl_client_flush(client());
}
@@ -120,12 +124,14 @@ class WaylandTextInputDelegate : public TextInput::Delegate {
// 1-bit shifts to adjust the bitpattern for the modifiers; see also
// WaylandTextInputDelegate::SendModifiers().
uint32_t modifiers = (event.flags() & modifiers_mask) >> 1;
- zwp_text_input_v1_send_keysym(text_input_,
- TimeTicksToMilliseconds(event.time_stamp()),
- next_serial(), code,
- pressed ? WL_KEYBOARD_KEY_STATE_PRESSED
- : WL_KEYBOARD_KEY_STATE_RELEASED,
- modifiers);
+
+ zwp_text_input_v1_send_keysym(
+ text_input_, TimeTicksToMilliseconds(event.time_stamp()),
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
+ code,
+ pressed ? WL_KEYBOARD_KEY_STATE_PRESSED
+ : WL_KEYBOARD_KEY_STATE_RELEASED,
+ modifiers);
wl_client_flush(client());
}
@@ -141,13 +147,19 @@ class WaylandTextInputDelegate : public TextInput::Delegate {
case base::i18n::UNKNOWN_DIRECTION:
LOG(ERROR) << "Unrecognized direction: " << direction;
}
- zwp_text_input_v1_send_text_direction(text_input_, next_serial(),
- wayland_direction);
+
+ zwp_text_input_v1_send_text_direction(
+ text_input_,
+ serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
+ wayland_direction);
}
wl_resource* text_input_;
wl_resource* surface_ = nullptr;
+ // Owned by Server, which always outlives this delegate.
+ SerialTracker* const serial_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandTextInputDelegate);
};
@@ -334,13 +346,15 @@ const struct zwp_text_input_v1_interface text_input_v1_implementation = {
void text_input_manager_create_text_input(wl_client* client,
wl_resource* resource,
uint32_t id) {
+ auto* data = GetUserDataAs<WaylandTextInputManager>(resource);
+
wl_resource* text_input_resource =
wl_resource_create(client, &zwp_text_input_v1_interface, 1, id);
SetImplementation(
text_input_resource, &text_input_v1_implementation,
- std::make_unique<TextInput>(
- std::make_unique<WaylandTextInputDelegate>(text_input_resource)));
+ std::make_unique<TextInput>(std::make_unique<WaylandTextInputDelegate>(
+ text_input_resource, data->serial_tracker)));
}
const struct zwp_text_input_manager_v1_interface
diff --git a/chromium/components/exo/wayland/zwp_text_input_manager.h b/chromium/components/exo/wayland/zwp_text_input_manager.h
index 4d17ca98161..1cfd9948783 100644
--- a/chromium/components/exo/wayland/zwp_text_input_manager.h
+++ b/chromium/components/exo/wayland/zwp_text_input_manager.h
@@ -7,10 +7,23 @@
#include <stdint.h>
+#include "base/macros.h"
+
struct wl_client;
namespace exo {
namespace wayland {
+class SerialTracker;
+
+struct WaylandTextInputManager {
+ WaylandTextInputManager(SerialTracker* serial_tracker)
+ : serial_tracker(serial_tracker) {}
+
+ // Owned by Server, which always outlives zwp_text_input_manager.
+ SerialTracker* const serial_tracker;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandTextInputManager);
+};
void bind_text_input_manager(wl_client* client,
void* data,
diff --git a/chromium/components/exo/wayland/zxdg_shell.cc b/chromium/components/exo/wayland/zxdg_shell.cc
index d0e02ee1ab2..bf796d7168b 100644
--- a/chromium/components/exo/wayland/zxdg_shell.cc
+++ b/chromium/components/exo/wayland/zxdg_shell.cc
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/exo/display.h"
+#include "components/exo/wayland/serial_tracker.h"
#include "components/exo/wayland/server_util.h"
#include "components/exo/wayland/wayland_positioner.h"
#include "components/exo/xdg_shell_surface.h"
@@ -149,111 +150,129 @@ using XdgSurfaceConfigureCallback =
uint32_t HandleXdgSurfaceV6ConfigureCallback(
wl_resource* resource,
+ SerialTracker* serial_tracker,
const XdgSurfaceConfigureCallback& callback,
const gfx::Size& size,
ash::WindowStateType state_type,
bool resizing,
bool activated,
const gfx::Vector2d& origin_offset) {
- uint32_t serial = wl_display_next_serial(
- wl_client_get_display(wl_resource_get_client(resource)));
+ uint32_t serial =
+ serial_tracker->GetNextSerial(SerialTracker::EventType::OTHER_EVENT);
callback.Run(size, state_type, resizing, activated);
zxdg_surface_v6_send_configure(resource, serial);
wl_client_flush(wl_resource_get_client(resource));
return serial;
}
+struct WaylandXdgSurface {
+ WaylandXdgSurface(std::unique_ptr<XdgShellSurface> shell_surface,
+ SerialTracker* const serial_tracker)
+ : shell_surface(std::move(shell_surface)),
+ serial_tracker(serial_tracker) {}
+
+ std::unique_ptr<XdgShellSurface> shell_surface;
+
+ // Owned by Server, which always outlives this surface.
+ SerialTracker* const serial_tracker;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandXdgSurface);
+};
+
// Wrapper around shell surface that allows us to handle the case where the
// xdg surface resource is destroyed before the toplevel resource.
class WaylandToplevel : public aura::WindowObserver {
public:
WaylandToplevel(wl_resource* resource, wl_resource* surface_resource)
: resource_(resource),
- shell_surface_(GetUserDataAs<XdgShellSurface>(surface_resource)),
- weak_ptr_factory_(this) {
- shell_surface_->host_window()->AddObserver(this);
- shell_surface_->set_close_callback(
+ shell_surface_data_(
+ GetUserDataAs<WaylandXdgSurface>(surface_resource)) {
+ shell_surface_data_->shell_surface->host_window()->AddObserver(this);
+ shell_surface_data_->shell_surface->set_close_callback(
base::Bind(&WaylandToplevel::OnClose, weak_ptr_factory_.GetWeakPtr()));
- shell_surface_->set_configure_callback(
+ shell_surface_data_->shell_surface->set_configure_callback(
base::Bind(&HandleXdgSurfaceV6ConfigureCallback, surface_resource,
+ shell_surface_data_->serial_tracker,
base::Bind(&WaylandToplevel::OnConfigure,
weak_ptr_factory_.GetWeakPtr())));
}
~WaylandToplevel() override {
- if (shell_surface_)
- shell_surface_->host_window()->RemoveObserver(this);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->host_window()->RemoveObserver(this);
}
// Overridden from aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override {
- shell_surface_ = nullptr;
+ shell_surface_data_ = nullptr;
}
void SetParent(WaylandToplevel* parent) {
- if (!shell_surface_)
+ if (!shell_surface_data_)
return;
if (!parent) {
- shell_surface_->SetParent(nullptr);
+ shell_surface_data_->shell_surface->SetParent(nullptr);
return;
}
// This is a no-op if parent is not mapped.
- if (parent->shell_surface_ && parent->shell_surface_->GetWidget())
- shell_surface_->SetParent(parent->shell_surface_);
+ if (parent->shell_surface_data_ &&
+ parent->shell_surface_data_->shell_surface->GetWidget())
+ shell_surface_data_->shell_surface->SetParent(
+ parent->shell_surface_data_->shell_surface.get());
}
void SetTitle(const base::string16& title) {
- if (shell_surface_)
- shell_surface_->SetTitle(title);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->SetTitle(title);
}
void SetApplicationId(const char* application_id) {
- if (shell_surface_)
- shell_surface_->SetApplicationId(application_id);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->SetApplicationId(application_id);
}
void Move() {
- if (shell_surface_)
- shell_surface_->StartMove();
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->StartMove();
}
void Resize(int component) {
- if (!shell_surface_)
+ if (!shell_surface_data_)
return;
if (component != HTNOWHERE)
- shell_surface_->StartResize(component);
+ shell_surface_data_->shell_surface->StartResize(component);
}
void SetMaximumSize(const gfx::Size& size) {
- if (shell_surface_)
- shell_surface_->SetMaximumSize(size);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->SetMaximumSize(size);
}
void SetMinimumSize(const gfx::Size& size) {
- if (shell_surface_)
- shell_surface_->SetMinimumSize(size);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->SetMinimumSize(size);
}
void Maximize() {
- if (shell_surface_)
- shell_surface_->Maximize();
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->Maximize();
}
void Restore() {
- if (shell_surface_)
- shell_surface_->Restore();
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->Restore();
}
void SetFullscreen(bool fullscreen) {
- if (shell_surface_)
- shell_surface_->SetFullscreen(fullscreen);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->SetFullscreen(fullscreen);
}
void Minimize() {
- if (shell_surface_)
- shell_surface_->Minimize();
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->Minimize();
}
private:
@@ -289,8 +308,8 @@ class WaylandToplevel : public aura::WindowObserver {
}
wl_resource* const resource_;
- XdgShellSurface* shell_surface_;
- base::WeakPtrFactory<WaylandToplevel> weak_ptr_factory_;
+ WaylandXdgSurface* shell_surface_data_;
+ base::WeakPtrFactory<WaylandToplevel> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WaylandToplevel);
};
@@ -404,38 +423,39 @@ class WaylandPopup : aura::WindowObserver {
public:
WaylandPopup(wl_resource* resource, wl_resource* surface_resource)
: resource_(resource),
- shell_surface_(GetUserDataAs<ShellSurface>(surface_resource)),
- weak_ptr_factory_(this) {
- shell_surface_->host_window()->AddObserver(this);
- shell_surface_->set_close_callback(
+ shell_surface_data_(
+ GetUserDataAs<WaylandXdgSurface>(surface_resource)) {
+ shell_surface_data_->shell_surface->host_window()->AddObserver(this);
+ shell_surface_data_->shell_surface->set_close_callback(
base::Bind(&WaylandPopup::OnClose, weak_ptr_factory_.GetWeakPtr()));
- shell_surface_->set_configure_callback(
+ shell_surface_data_->shell_surface->set_configure_callback(
base::Bind(&HandleXdgSurfaceV6ConfigureCallback, surface_resource,
+ shell_surface_data_->serial_tracker,
base::Bind(&WaylandPopup::OnConfigure,
weak_ptr_factory_.GetWeakPtr())));
}
~WaylandPopup() override {
- if (shell_surface_)
- shell_surface_->host_window()->RemoveObserver(this);
+ if (shell_surface_data_)
+ shell_surface_data_->shell_surface->host_window()->RemoveObserver(this);
}
void Grab() {
- if (!shell_surface_) {
+ if (!shell_surface_data_) {
wl_resource_post_error(resource_, ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
"the surface has already been destroyed");
return;
}
- if (shell_surface_->GetWidget()) {
+ if (shell_surface_data_->shell_surface->GetWidget()) {
wl_resource_post_error(resource_, ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
"grab must be called before construction");
return;
}
- shell_surface_->Grab();
+ shell_surface_data_->shell_surface->Grab();
}
// Overridden from aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override {
- shell_surface_ = nullptr;
+ shell_surface_data_ = nullptr;
}
private:
@@ -452,8 +472,8 @@ class WaylandPopup : aura::WindowObserver {
}
wl_resource* const resource_;
- ShellSurface* shell_surface_;
- base::WeakPtrFactory<WaylandPopup> weak_ptr_factory_;
+ WaylandXdgSurface* shell_surface_data_;
+ base::WeakPtrFactory<WaylandPopup> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WaylandPopup);
};
@@ -482,15 +502,15 @@ void xdg_surface_v6_destroy(wl_client* client, wl_resource* resource) {
void xdg_surface_v6_get_toplevel(wl_client* client,
wl_resource* resource,
uint32_t id) {
- ShellSurface* shell_surface = GetUserDataAs<ShellSurface>(resource);
- if (shell_surface->GetEnabled()) {
+ auto* shell_surface_data = GetUserDataAs<WaylandXdgSurface>(resource);
+ if (shell_surface_data->shell_surface->GetEnabled()) {
wl_resource_post_error(resource, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED,
"surface has already been constructed");
return;
}
- shell_surface->SetCanMinimize(true);
- shell_surface->SetEnabled(true);
+ shell_surface_data->shell_surface->SetCanMinimize(true);
+ shell_surface_data->shell_surface->SetEnabled(true);
wl_resource* xdg_toplevel_resource =
wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id);
@@ -505,21 +525,21 @@ void xdg_surface_v6_get_popup(wl_client* client,
uint32_t id,
wl_resource* parent_resource,
wl_resource* positioner_resource) {
- XdgShellSurface* shell_surface = GetUserDataAs<XdgShellSurface>(resource);
- if (shell_surface->GetEnabled()) {
+ auto* shell_surface_data = GetUserDataAs<WaylandXdgSurface>(resource);
+ if (shell_surface_data->shell_surface->GetEnabled()) {
wl_resource_post_error(resource, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED,
"surface has already been constructed");
return;
}
- XdgShellSurface* parent = GetUserDataAs<XdgShellSurface>(parent_resource);
- if (!parent->GetWidget()) {
+ auto* parent_data = GetUserDataAs<WaylandXdgSurface>(parent_resource);
+ if (!parent_data->shell_surface->GetWidget()) {
wl_resource_post_error(resource, ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
"popup parent not constructed");
return;
}
- if (shell_surface->GetWidget()) {
+ if (shell_surface_data->shell_surface->GetWidget()) {
wl_resource_post_error(resource, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED,
"get_popup is called after constructed");
return;
@@ -527,33 +547,38 @@ void xdg_surface_v6_get_popup(wl_client* client,
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestWindow(
- parent->GetWidget()->GetNativeWindow());
+ parent_data->shell_surface->GetWidget()->GetNativeWindow());
gfx::Rect work_area = display.work_area();
- wm::ConvertRectFromScreen(parent->GetWidget()->GetNativeWindow(), &work_area);
+ wm::ConvertRectFromScreen(
+ parent_data->shell_surface->GetWidget()->GetNativeWindow(), &work_area);
// Try layout using parent's flip state.
WaylandPositioner* positioner =
GetUserDataAs<WaylandPositioner>(positioner_resource);
WaylandPositioner::Result position = positioner->CalculatePosition(
- work_area, parent->x_flipped(), parent->y_flipped());
+ work_area, parent_data->shell_surface->x_flipped(),
+ parent_data->shell_surface->y_flipped());
// Remember the new flip state for its child popups.
- shell_surface->set_x_flipped(position.x_flipped);
- shell_surface->set_y_flipped(position.y_flipped);
+ shell_surface_data->shell_surface->set_x_flipped(position.x_flipped);
+ shell_surface_data->shell_surface->set_y_flipped(position.y_flipped);
// |position| is relative to the parent's contents view origin, and |origin|
// is in screen coordinates.
gfx::Point origin = position.origin;
- views::View::ConvertPointToScreen(
- parent->GetWidget()->widget_delegate()->GetContentsView(), &origin);
- shell_surface->SetOrigin(origin);
- shell_surface->SetSize(position.size);
- shell_surface->DisableMovement();
- shell_surface->SetActivatable(false);
- shell_surface->SetCanMinimize(false);
- shell_surface->SetParent(parent);
- shell_surface->SetPopup();
- shell_surface->SetEnabled(true);
+ views::View::ConvertPointToScreen(parent_data->shell_surface->GetWidget()
+ ->widget_delegate()
+ ->GetContentsView(),
+ &origin);
+ shell_surface_data->shell_surface->SetOrigin(origin);
+ shell_surface_data->shell_surface->SetSize(position.size);
+ shell_surface_data->shell_surface->DisableMovement();
+ shell_surface_data->shell_surface->SetActivatable(false);
+ shell_surface_data->shell_surface->SetCanMinimize(false);
+ shell_surface_data->shell_surface->SetParent(
+ parent_data->shell_surface.get());
+ shell_surface_data->shell_surface->SetPopup();
+ shell_surface_data->shell_surface->SetEnabled(true);
wl_resource* xdg_popup_resource =
wl_resource_create(client, &zxdg_popup_v6_interface, 1, id);
@@ -575,14 +600,15 @@ void xdg_surface_v6_set_window_geometry(wl_client* client,
int32_t y,
int32_t width,
int32_t height) {
- GetUserDataAs<ShellSurface>(resource)->SetGeometry(
+ GetUserDataAs<WaylandXdgSurface>(resource)->shell_surface->SetGeometry(
gfx::Rect(x, y, width, height));
}
void xdg_surface_v6_ack_configure(wl_client* client,
wl_resource* resource,
uint32_t serial) {
- GetUserDataAs<ShellSurface>(resource)->AcknowledgeConfigure(serial);
+ GetUserDataAs<WaylandXdgSurface>(resource)
+ ->shell_surface->AcknowledgeConfigure(serial);
}
const struct zxdg_surface_v6_interface xdg_surface_v6_implementation = {
@@ -611,9 +637,9 @@ void xdg_shell_v6_get_xdg_surface(wl_client* client,
wl_resource* resource,
uint32_t id,
wl_resource* surface) {
- std::unique_ptr<ShellSurface> shell_surface =
- GetUserDataAs<Display>(resource)->CreateXdgShellSurface(
- GetUserDataAs<Surface>(surface));
+ auto* data = GetUserDataAs<WaylandXdgShell>(resource);
+ std::unique_ptr<XdgShellSurface> shell_surface =
+ data->display->CreateXdgShellSurface(GetUserDataAs<Surface>(surface));
if (!shell_surface) {
wl_resource_post_error(resource, ZXDG_SHELL_V6_ERROR_ROLE,
"surface has already been assigned a role");
@@ -624,11 +650,15 @@ void xdg_shell_v6_get_xdg_surface(wl_client* client,
// mapped before they are enabled and can become visible.
shell_surface->SetEnabled(false);
+ std::unique_ptr<WaylandXdgSurface> wayland_shell_surface =
+ std::make_unique<WaylandXdgSurface>(std::move(shell_surface),
+ data->serial_tracker);
+
wl_resource* xdg_surface_resource =
wl_resource_create(client, &zxdg_surface_v6_interface, 1, id);
SetImplementation(xdg_surface_resource, &xdg_surface_v6_implementation,
- std::move(shell_surface));
+ std::move(wayland_shell_surface));
}
void xdg_shell_v6_pong(wl_client* client,
diff --git a/chromium/components/exo/wayland/zxdg_shell.h b/chromium/components/exo/wayland/zxdg_shell.h
index d5c0e6b51c7..f5112d36170 100644
--- a/chromium/components/exo/wayland/zxdg_shell.h
+++ b/chromium/components/exo/wayland/zxdg_shell.h
@@ -7,10 +7,28 @@
#include <stdint.h>
+#include "base/macros.h"
+
struct wl_client;
namespace exo {
+class Display;
+
namespace wayland {
+class SerialTracker;
+
+struct WaylandXdgShell {
+ WaylandXdgShell(Display* display, SerialTracker* serial_tracker)
+ : display(display), serial_tracker(serial_tracker) {}
+
+ // Owned by WaylandServerController, which always outlives zxdg_shell.
+ Display* const display;
+
+ // Owned by Server, which always outlives zxdg_shell.
+ SerialTracker* const serial_tracker;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandXdgShell);
+};
void bind_xdg_shell_v6(wl_client* client,
void* data,
diff --git a/chromium/components/favicon/core/BUILD.gn b/chromium/components/favicon/core/BUILD.gn
index f052f32c4e4..3b9c192ed68 100644
--- a/chromium/components/favicon/core/BUILD.gn
+++ b/chromium/components/favicon/core/BUILD.gn
@@ -14,8 +14,6 @@ static_library("core") {
"favicon_driver_observer.h",
"favicon_handler.cc",
"favicon_handler.h",
- "favicon_server_fetcher_params.cc",
- "favicon_server_fetcher_params.h",
"favicon_service.h",
"favicon_service_impl.cc",
"favicon_service_impl.h",
diff --git a/chromium/components/favicon/core/favicon_handler_unittest.cc b/chromium/components/favicon/core/favicon_handler_unittest.cc
index 24d21567729..d3e0a8ea53f 100644
--- a/chromium/components/favicon/core/favicon_handler_unittest.cc
+++ b/chromium/components/favicon/core/favicon_handler_unittest.cc
@@ -18,7 +18,7 @@
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "components/favicon/core/favicon_driver.h"
#include "components/favicon/core/features.h"
@@ -492,8 +492,7 @@ class FaviconHandlerTest : public testing::Test {
const GURL kIconURL64x64 = GURL("http://www.google.com/favicon64x64");
FaviconHandlerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {
// Register various known icon URLs.
delegate_.fake_image_downloader().Add(kIconURL10x10, IntVector{10});
delegate_.fake_image_downloader().Add(kIconURL12x12, IntVector{12});
@@ -547,7 +546,7 @@ class FaviconHandlerTest : public testing::Test {
candidates, manifest_url);
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<ui::test::ScopedSetSupportedScaleFactors>
scoped_set_supported_scale_factors_;
testing::NiceMock<MockFaviconServiceWithFake> favicon_service_;
diff --git a/chromium/components/favicon/core/favicon_server_fetcher_params.cc b/chromium/components/favicon/core/favicon_server_fetcher_params.cc
deleted file mode 100644
index ae70cd4d804..00000000000
--- a/chromium/components/favicon/core/favicon_server_fetcher_params.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/favicon/core/favicon_server_fetcher_params.h"
-
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "build/build_config.h"
-#include "components/favicon_base/favicon_util.h"
-#include "ui/gfx/favicon_size.h"
-
-namespace favicon {
-namespace {
-
-const char kClientParamDesktop[] = "client=chrome_desktop";
-const char kClientParamMobile[] = "client=chrome";
-// TODO(https://crbug.com/982810): Refactor to remove ios specific code from
-// here.
-#if defined(OS_IOS)
-const int kMobileSizeInDip = 32;
-#else
-const int kMobileSizeInDip = 24;
-#endif
-
-float GetMaxDeviceScaleFactor() {
- std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
- DCHECK(!favicon_scales.empty());
- return favicon_scales.back();
-}
-
-} // namespace
-
-std::unique_ptr<FaviconServerFetcherParams>
-FaviconServerFetcherParams::CreateForDesktop(const GURL& page_url) {
- return base::WrapUnique(new FaviconServerFetcherParams(
- page_url, favicon_base::IconType::kFavicon,
- std::ceil(gfx::kFaviconSize * GetMaxDeviceScaleFactor()),
- kClientParamDesktop));
-}
-
-std::unique_ptr<FaviconServerFetcherParams>
-FaviconServerFetcherParams::CreateForMobile(const GURL& page_url) {
- return base::WrapUnique(new FaviconServerFetcherParams(
- page_url, favicon_base::IconType::kTouchIcon,
- std::ceil(kMobileSizeInDip * GetMaxDeviceScaleFactor()),
- kClientParamMobile));
-}
-
-FaviconServerFetcherParams::FaviconServerFetcherParams(
- const GURL& page_url,
- favicon_base::IconType icon_type,
- int desired_size_in_pixel,
- const std::string& google_server_client_param)
- : page_url_(page_url),
- icon_type_(icon_type),
- desired_size_in_pixel_(desired_size_in_pixel),
- google_server_client_param_(google_server_client_param) {}
-
-FaviconServerFetcherParams::~FaviconServerFetcherParams() = default;
-
-} // namespace favicon
diff --git a/chromium/components/favicon/core/favicon_server_fetcher_params.h b/chromium/components/favicon/core/favicon_server_fetcher_params.h
deleted file mode 100644
index 69a91946eac..00000000000
--- a/chromium/components/favicon/core/favicon_server_fetcher_params.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_FAVICON_CORE_FAVICON_SERVER_FETCHER_PARAMS_H_
-#define COMPONENTS_FAVICON_CORE_FAVICON_SERVER_FETCHER_PARAMS_H_
-
-#include "components/favicon_base/favicon_util.h"
-
-class GURL;
-
-namespace favicon {
-
-class FaviconServerFetcherParams {
- public:
- // Platform specific constructors that set default fetch parameters. Any
- // platform not Android nor iOS is considered desktop.
- static std::unique_ptr<FaviconServerFetcherParams> CreateForDesktop(
- const GURL& page_url);
- static std::unique_ptr<FaviconServerFetcherParams> CreateForMobile(
- const GURL& page_url);
-
- ~FaviconServerFetcherParams();
-
- const GURL& page_url() const { return page_url_; }
- favicon_base::IconType icon_type() const { return icon_type_; }
- int desired_size_in_pixel() const { return desired_size_in_pixel_; }
- const std::string& google_server_client_param() const {
- return google_server_client_param_;
- }
-
- private:
- FaviconServerFetcherParams(const GURL& page_url,
- favicon_base::IconType icon_type,
- int desired_size_in_pixel,
- const std::string& google_server_client_param);
-
- const GURL& page_url_;
- favicon_base::IconType icon_type_;
- int desired_size_in_pixel_;
- std::string google_server_client_param_;
-
- DISALLOW_COPY_AND_ASSIGN(FaviconServerFetcherParams);
-};
-
-} // namespace favicon
-
-#endif // COMPONENTS_FAVICON_CORE_FAVICON_SERVER_FETCHER_PARAMS_H_
diff --git a/chromium/components/favicon/core/favicon_service_impl_unittest.cc b/chromium/components/favicon/core/favicon_service_impl_unittest.cc
index 65709ea397a..f04a8dc51ae 100644
--- a/chromium/components/favicon/core/favicon_service_impl_unittest.cc
+++ b/chromium/components/favicon/core/favicon_service_impl_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/files/scoped_temp_dir.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/favicon/core/favicon_client.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/test/history_service_test_util.h"
@@ -17,7 +17,7 @@ namespace favicon {
namespace {
TEST(FaviconServiceImplTest, ShouldCacheUnableToDownloadFavicons) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
base::ScopedTempDir history_dir;
CHECK(history_dir.CreateUniqueTempDir());
std::unique_ptr<history::HistoryService> history_service =
diff --git a/chromium/components/favicon/core/history_ui_favicon_request_handler.h b/chromium/components/favicon/core/history_ui_favicon_request_handler.h
index 8d49514fe0a..6654c5d1f04 100644
--- a/chromium/components/favicon/core/history_ui_favicon_request_handler.h
+++ b/chromium/components/favicon/core/history_ui_favicon_request_handler.h
@@ -44,6 +44,7 @@ class HistoryUiFaviconRequestHandler : public KeyedService {
// is enabled. If a non-empty |icon_url_for_uma| (optional) is passed, it will
// be used to record UMA about the grouping of requests to the favicon server.
// |request_platform| specifies whether the caller is mobile or desktop code.
+ // TODO(victorvianna): Remove platform parameter since it's no longer needed.
virtual void GetRawFaviconForPageURL(
const GURL& page_url,
int desired_size_in_pixel,
diff --git a/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.cc b/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.cc
index 9dbdcca802d..c065351c5c4 100644
--- a/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.cc
+++ b/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.cc
@@ -12,7 +12,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/cancelable_task_tracker.h"
-#include "components/favicon/core/favicon_server_fetcher_params.h"
#include "components/favicon/core/favicon_service.h"
#include "components/favicon/core/features.h"
#include "components/favicon/core/large_icon_service.h"
@@ -26,22 +25,29 @@ namespace favicon {
namespace {
-void RecordFaviconAvailabilityMetric(
+void RecordFaviconAvailabilityAndLatencyMetric(
HistoryUiFaviconRequestOrigin origin_for_uma,
+ base::Time request_start_time_for_uma,
FaviconAvailability availability) {
+ base::TimeDelta latency = base::Time::Now() - request_start_time_for_uma;
switch (origin_for_uma) {
case HistoryUiFaviconRequestOrigin::kHistory:
UMA_HISTOGRAM_ENUMERATION("Sync.SyncedHistoryFaviconAvailability.HISTORY",
availability);
+ UMA_HISTOGRAM_TIMES("Sync.SyncedHistoryFaviconLatency.HISTORY", latency);
break;
case HistoryUiFaviconRequestOrigin::kHistorySyncedTabs:
UMA_HISTOGRAM_ENUMERATION(
"Sync.SyncedHistoryFaviconAvailability.SYNCED_TABS", availability);
+ UMA_HISTOGRAM_TIMES("Sync.SyncedHistoryFaviconLatency.SYNCED_TABS",
+ latency);
break;
case HistoryUiFaviconRequestOrigin::kRecentTabs:
UMA_HISTOGRAM_ENUMERATION(
"Sync.SyncedHistoryFaviconAvailability.RECENTLY_CLOSED_TABS",
availability);
+ UMA_HISTOGRAM_TIMES(
+ "Sync.SyncedHistoryFaviconLatency.RECENTLY_CLOSED_TABS", latency);
break;
}
}
@@ -125,7 +131,7 @@ void HistoryUiFaviconRequestHandlerImpl::GetRawFaviconForPageURL(
weak_ptr_factory_.GetWeakPtr(), CanQueryGoogleServer(), page_url,
desired_size_in_pixel,
/*response_callback=*/std::move(callback), request_platform,
- request_origin_for_uma, icon_url_for_uma, tracker),
+ request_origin_for_uma, icon_url_for_uma, base::Time::Now(), tracker),
tracker);
}
@@ -142,7 +148,7 @@ void HistoryUiFaviconRequestHandlerImpl::GetFaviconImageForPageURL(
&HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable,
weak_ptr_factory_.GetWeakPtr(), CanQueryGoogleServer(), page_url,
/*response_callback=*/std::move(callback), request_origin_for_uma,
- icon_url_for_uma, tracker),
+ icon_url_for_uma, base::Time::Now(), tracker),
tracker);
}
@@ -154,13 +160,15 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
FaviconRequestPlatform platform,
HistoryUiFaviconRequestOrigin origin_for_uma,
const GURL& icon_url_for_uma,
+ base::Time request_start_time_for_uma,
base::CancelableTaskTracker* tracker,
const favicon_base::FaviconRawBitmapResult& bitmap_result) {
if (bitmap_result.is_valid()) {
// The icon comes from local storage now even though it may have been
// originally retrieved from Google server.
- RecordFaviconAvailabilityMetric(origin_for_uma,
- FaviconAvailability::kLocal);
+ RecordFaviconAvailabilityAndLatencyMetric(origin_for_uma,
+ request_start_time_for_uma,
+ FaviconAvailability::kLocal);
large_icon_service_->TouchIconFromGoogleServer(bitmap_result.icon_url);
std::move(response_callback).Run(bitmap_result);
return;
@@ -171,12 +179,8 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
base::RepeatingCallback<void(const favicon_base::FaviconRawBitmapResult&)>
repeating_response_callback =
base::AdaptCallbackForRepeating(std::move(response_callback));
- std::unique_ptr<FaviconServerFetcherParams> server_parameters =
- platform == FaviconRequestPlatform::kMobile
- ? FaviconServerFetcherParams::CreateForMobile(page_url)
- : FaviconServerFetcherParams::CreateForDesktop(page_url);
RequestFromGoogleServer(
- page_url, std::move(server_parameters),
+ page_url,
/*empty_response_callback=*/
base::BindOnce(repeating_response_callback,
favicon_base::FaviconRawBitmapResult()),
@@ -186,7 +190,7 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
base::Unretained(favicon_service_), page_url,
GetIconTypesForLocalQuery(), desired_size_in_pixel, kFallbackToHost,
repeating_response_callback, tracker),
- origin_for_uma, icon_url_for_uma);
+ origin_for_uma, icon_url_for_uma, request_start_time_for_uma);
return;
}
@@ -194,7 +198,8 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
synced_favicon_getter_.Run(page_url);
if (sync_bitmap_result.is_valid()) {
// If request to sync succeeds, resize bitmap to desired size and send.
- RecordFaviconAvailabilityMetric(origin_for_uma, FaviconAvailability::kSync);
+ RecordFaviconAvailabilityAndLatencyMetric(
+ origin_for_uma, request_start_time_for_uma, FaviconAvailability::kSync);
std::move(response_callback)
.Run(favicon_base::ResizeFaviconBitmapResult({sync_bitmap_result},
desired_size_in_pixel));
@@ -202,8 +207,9 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
}
// If sync does not have the favicon, send empty response.
- RecordFaviconAvailabilityMetric(origin_for_uma,
- FaviconAvailability::kNotAvailable);
+ RecordFaviconAvailabilityAndLatencyMetric(origin_for_uma,
+ request_start_time_for_uma,
+ FaviconAvailability::kNotAvailable);
std::move(response_callback).Run(favicon_base::FaviconRawBitmapResult());
}
@@ -213,13 +219,15 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
favicon_base::FaviconImageCallback response_callback,
HistoryUiFaviconRequestOrigin origin_for_uma,
const GURL& icon_url_for_uma,
+ base::Time request_start_time_for_uma,
base::CancelableTaskTracker* tracker,
const favicon_base::FaviconImageResult& image_result) {
if (!image_result.image.IsEmpty()) {
// The icon comes from local storage now even though it may have been
// originally retrieved from Google server.
- RecordFaviconAvailabilityMetric(origin_for_uma,
- FaviconAvailability::kLocal);
+ RecordFaviconAvailabilityAndLatencyMetric(origin_for_uma,
+ request_start_time_for_uma,
+ FaviconAvailability::kLocal);
large_icon_service_->TouchIconFromGoogleServer(image_result.icon_url);
std::move(response_callback).Run(image_result);
return;
@@ -233,7 +241,7 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
// We use CreateForDesktop because GetFaviconImageForPageURL is only called
// by desktop.
RequestFromGoogleServer(
- page_url, FaviconServerFetcherParams::CreateForDesktop(page_url),
+ page_url,
/*empty_response_callback=*/
base::BindOnce(repeating_response_callback,
favicon_base::FaviconImageResult()),
@@ -242,7 +250,7 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
base::IgnoreResult(&FaviconService::GetFaviconImageForPageURL),
base::Unretained(favicon_service_), page_url,
repeating_response_callback, tracker),
- origin_for_uma, icon_url_for_uma);
+ origin_for_uma, icon_url_for_uma, request_start_time_for_uma);
return;
}
@@ -251,7 +259,8 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
if (sync_bitmap_result.is_valid()) {
// If request to sync succeeds, convert the retrieved bitmap to image and
// send.
- RecordFaviconAvailabilityMetric(origin_for_uma, FaviconAvailability::kSync);
+ RecordFaviconAvailabilityAndLatencyMetric(
+ origin_for_uma, request_start_time_for_uma, FaviconAvailability::kSync);
favicon_base::FaviconImageResult sync_image_result;
sync_image_result.image =
gfx::Image::CreateFrom1xPNGBytes(sync_bitmap_result.bitmap_data.get());
@@ -260,18 +269,19 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
}
// If sync does not have the favicon, send empty response.
- RecordFaviconAvailabilityMetric(origin_for_uma,
- FaviconAvailability::kNotAvailable);
+ RecordFaviconAvailabilityAndLatencyMetric(origin_for_uma,
+ request_start_time_for_uma,
+ FaviconAvailability::kNotAvailable);
std::move(response_callback).Run(favicon_base::FaviconImageResult());
}
void HistoryUiFaviconRequestHandlerImpl::RequestFromGoogleServer(
const GURL& page_url,
- std::unique_ptr<FaviconServerFetcherParams> server_parameters,
base::OnceClosure empty_response_callback,
base::OnceClosure local_lookup_callback,
HistoryUiFaviconRequestOrigin origin_for_uma,
- const GURL& icon_url_for_uma) {
+ const GURL& icon_url_for_uma,
+ base::Time request_start_time_for_uma) {
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation(
"history_ui_favicon_request_handler_get_favicon",
@@ -317,15 +327,15 @@ void HistoryUiFaviconRequestHandlerImpl::RequestFromGoogleServer(
/* default_value= */ false);
large_icon_service_
->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- std::move(server_parameters),
+ page_url,
/*may_page_url_be_private=*/true, should_trim_url_path,
traffic_annotation,
base::BindOnce(
&HistoryUiFaviconRequestHandlerImpl::OnGoogleServerDataAvailable,
weak_ptr_factory_.GetWeakPtr(),
std::move(empty_response_callback),
- std::move(local_lookup_callback), origin_for_uma,
- group_to_clear));
+ std::move(local_lookup_callback), origin_for_uma, group_to_clear,
+ request_start_time_for_uma));
}
void HistoryUiFaviconRequestHandlerImpl::OnGoogleServerDataAvailable(
@@ -333,6 +343,7 @@ void HistoryUiFaviconRequestHandlerImpl::OnGoogleServerDataAvailable(
base::OnceClosure local_lookup_callback,
HistoryUiFaviconRequestOrigin origin_for_uma,
const GURL& group_to_clear,
+ base::Time request_start_time_for_uma,
favicon_base::GoogleFaviconServerRequestStatus status) {
if (!group_to_clear.is_empty()) {
auto it = group_callbacks_count_.find(group_to_clear);
@@ -351,12 +362,14 @@ void HistoryUiFaviconRequestHandlerImpl::OnGoogleServerDataAvailable(
FAILURE_ICON_EXISTS_IN_DB) {
// We record the metrics as kLocal since the icon will be subsequently
// retrieved from local storage.
- RecordFaviconAvailabilityMetric(origin_for_uma,
- FaviconAvailability::kLocal);
+ RecordFaviconAvailabilityAndLatencyMetric(origin_for_uma,
+ request_start_time_for_uma,
+ FaviconAvailability::kLocal);
std::move(local_lookup_callback).Run();
} else {
- RecordFaviconAvailabilityMetric(origin_for_uma,
- FaviconAvailability::kNotAvailable);
+ RecordFaviconAvailabilityAndLatencyMetric(
+ origin_for_uma, request_start_time_for_uma,
+ FaviconAvailability::kNotAvailable);
std::move(empty_response_callback).Run();
}
}
diff --git a/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.h b/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.h
index f5e423f52be..710c80774e9 100644
--- a/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.h
+++ b/chromium/components/favicon/core/history_ui_favicon_request_handler_impl.h
@@ -14,7 +14,6 @@
namespace favicon {
-class FaviconServerFetcherParams;
class FaviconService;
class LargeIconService;
@@ -82,6 +81,7 @@ class HistoryUiFaviconRequestHandlerImpl
FaviconRequestPlatform platform,
HistoryUiFaviconRequestOrigin origin_for_uma,
const GURL& icon_url_for_uma,
+ base::Time request_start_time_for_uma,
base::CancelableTaskTracker* tracker,
const favicon_base::FaviconRawBitmapResult& bitmap_result);
@@ -95,19 +95,19 @@ class HistoryUiFaviconRequestHandlerImpl
favicon_base::FaviconImageCallback response_callback,
HistoryUiFaviconRequestOrigin origin_for_uma,
const GURL& icon_url_for_uma,
+ base::Time request_start_time_for_uma,
base::CancelableTaskTracker* tracker,
const favicon_base::FaviconImageResult& image_result);
// Requests an icon from Google favicon server. Since requests work by
// populating local storage, a |local_lookup_callback| will be needed in case
// of success and an |empty_response_callback| in case of failure.
- void RequestFromGoogleServer(
- const GURL& page_url,
- std::unique_ptr<FaviconServerFetcherParams> server_parameters,
- base::OnceClosure empty_response_callback,
- base::OnceClosure local_lookup_callback,
- HistoryUiFaviconRequestOrigin origin_for_uma,
- const GURL& icon_url_for_uma);
+ void RequestFromGoogleServer(const GURL& page_url,
+ base::OnceClosure empty_response_callback,
+ base::OnceClosure local_lookup_callback,
+ HistoryUiFaviconRequestOrigin origin_for_uma,
+ const GURL& icon_url_for_uma,
+ base::Time request_start_time_for_uma);
// Called once the request to the favicon server has finished. If the request
// succeeded, |local_lookup_callback| is called to effectively retrieve the
@@ -119,6 +119,7 @@ class HistoryUiFaviconRequestHandlerImpl
base::OnceClosure local_lookup_callback,
HistoryUiFaviconRequestOrigin origin_for_uma,
const GURL& group_to_clear,
+ base::Time request_start_time_for_uma,
favicon_base::GoogleFaviconServerRequestStatus status);
bool CanQueryGoogleServer() const;
diff --git a/chromium/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc b/chromium/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
index 93fc740459b..2653e765c0d 100644
--- a/chromium/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
+++ b/chromium/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
@@ -11,7 +11,6 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
-#include "components/favicon/core/favicon_server_fetcher_params.h"
#include "components/favicon/core/features.h"
#include "components/favicon/core/large_icon_service.h"
#include "components/favicon/core/test/mock_favicon_service.h"
@@ -40,17 +39,13 @@ const FaviconRequestPlatform kDummyPlatform = FaviconRequestPlatform::kDesktop;
base::CancelableTaskTracker::TaskId kDummyTaskId = 1;
const char kAvailabilityHistogramName[] =
"Sync.SyncedHistoryFaviconAvailability";
+const char kLatencyHistogramName[] = "Sync.SyncedHistoryFaviconLatency";
const char kGroupingHistogramName[] =
"Sync.RequestGroupSizeForSyncedHistoryFavicons";
const int kDefaultDesiredSizeInPixel = 16;
// TODO(victorvianna): Add unit tests specific for mobile.
const SkColor kTestColor = SK_ColorRED;
-// Custom matcher for FaviconServerFetcherParams.
-MATCHER_P(FetcherParamsPageUrlEq, url, "") {
- return arg->page_url() == GURL(url);
-}
-
SkBitmap CreateTestSkBitmap(int desired_size_in_pixel) {
SkBitmap bitmap;
bitmap.allocN32Pixels(desired_size_in_pixel, desired_size_in_pixel);
@@ -92,13 +87,71 @@ void StoreImage(favicon_base::FaviconImageResult* destination,
*destination = result;
}
-class MockLargeIconService : public LargeIconService {
+class MockFaviconServiceWithFake : public MockFaviconService {
+ public:
+ MockFaviconServiceWithFake() {
+ // Fake won't respond with any icons at first.
+ ON_CALL(*this, GetRawFaviconForPageURL(_, _, _, _, _, _))
+ .WillByDefault([](auto, auto, auto, auto,
+ favicon_base::FaviconRawBitmapCallback callback,
+ auto) {
+ std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
+ return kDummyTaskId;
+ });
+ ON_CALL(*this, GetFaviconImageForPageURL(_, _, _))
+ .WillByDefault(
+ [](auto, favicon_base::FaviconImageCallback callback, auto) {
+ std::move(callback).Run(favicon_base::FaviconImageResult());
+ return kDummyTaskId;
+ });
+ }
+
+ ~MockFaviconServiceWithFake() override = default;
+
+ // Will make the object start responding with a valid favicon for |page_url|.
+ void StoreMockLocalFavicon(const GURL& page_url) {
+ ON_CALL(*this, GetRawFaviconForPageURL(GURL(page_url), _,
+ kDefaultDesiredSizeInPixel, _, _, _))
+ .WillByDefault([](auto, auto, auto, auto,
+ favicon_base::FaviconRawBitmapCallback callback,
+ auto) {
+ std::move(callback).Run(CreateTestBitmapResult());
+ return kDummyTaskId;
+ });
+ ON_CALL(*this, GetFaviconImageForPageURL(GURL(page_url), _, _))
+ .WillByDefault(
+ [](auto, favicon_base::FaviconImageCallback callback, auto) {
+ std::move(callback).Run(CreateTestImageResult());
+ return kDummyTaskId;
+ });
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockFaviconServiceWithFake);
+};
+
+class MockLargeIconServiceWithFake : public LargeIconService {
public:
- MockLargeIconService() = default;
- ~MockLargeIconService() override = default;
+ explicit MockLargeIconServiceWithFake(
+ MockFaviconServiceWithFake* mock_favicon_service_with_fake)
+ : mock_favicon_service_with_fake_(mock_favicon_service_with_fake) {
+ // Fake won't respond with any icons at first.
+ ON_CALL(*this,
+ GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
+ _, _, _, _, _))
+ .WillByDefault(
+ [](auto, auto, auto, auto,
+ favicon_base::GoogleFaviconServerCallback server_callback) {
+ std::move(server_callback)
+ .Run(favicon_base::GoogleFaviconServerRequestStatus::
+ FAILURE_HTTP_ERROR);
+ });
+ }
+
+ ~MockLargeIconServiceWithFake() override = default;
MOCK_METHOD5(GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache,
- void(std::unique_ptr<FaviconServerFetcherParams> params,
+ void(const GURL& page_url,
bool may_page_url_be_private,
bool should_trim_page_url_path,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
@@ -129,21 +182,49 @@ class MockLargeIconService : public LargeIconService {
base::CancelableTaskTracker* tracker));
MOCK_METHOD1(TouchIconFromGoogleServer, void(const GURL& icon_url));
+
+ // Will make the object respond by storing a valid local favicon for
+ // |page_url| in |mock_favicon_server_with_fake_|.
+ void StoreMockGoogleServerFavicon(const GURL& page_url) {
+ ON_CALL(*this,
+ GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
+ _, _, _, _, _))
+ .WillByDefault(
+ [=](auto, auto, auto, auto,
+ favicon_base::GoogleFaviconServerCallback server_callback) {
+ mock_favicon_service_with_fake_->StoreMockLocalFavicon(page_url);
+ std::move(server_callback)
+ .Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS);
+ });
+ }
+
+ private:
+ MockFaviconServiceWithFake* const mock_favicon_service_with_fake_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockLargeIconServiceWithFake);
};
class HistoryUiFaviconRequestHandlerImplTest : public ::testing::Test {
public:
HistoryUiFaviconRequestHandlerImplTest()
- : history_ui_favicon_request_handler_(synced_favicon_getter_.Get(),
+ : mock_large_icon_service_(&mock_favicon_service_),
+ history_ui_favicon_request_handler_(synced_favicon_getter_.Get(),
can_send_history_data_getter_.Get(),
&mock_favicon_service_,
&mock_large_icon_service_) {
+ // Allow sending history data by default.
ON_CALL(can_send_history_data_getter_, Run()).WillByDefault(Return(true));
+
+ // Sync will by default respond it does not contain any icon. Same is done
+ // for the FaviconService and LargeIconService fakes in their constructors.
+ ON_CALL(synced_favicon_getter_, Run(_)).WillByDefault([](auto) {
+ return favicon_base::FaviconRawBitmapResult();
+ });
}
protected:
- testing::NiceMock<MockFaviconService> mock_favicon_service_;
- testing::NiceMock<MockLargeIconService> mock_large_icon_service_;
+ testing::NiceMock<MockFaviconServiceWithFake> mock_favicon_service_;
+ testing::NiceMock<MockLargeIconServiceWithFake> mock_large_icon_service_;
testing::NiceMock<base::MockCallback<
HistoryUiFaviconRequestHandlerImpl::SyncedFaviconGetter>>
synced_favicon_getter_;
@@ -154,6 +235,9 @@ class HistoryUiFaviconRequestHandlerImplTest : public ::testing::Test {
base::HistogramTester histogram_tester_;
base::test::ScopedFeatureList scoped_feature_list_;
HistoryUiFaviconRequestHandlerImpl history_ui_favicon_request_handler_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HistoryUiFaviconRequestHandlerImplTest);
};
TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetEmptyBitmap) {
@@ -162,12 +246,7 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetEmptyBitmap) {
EXPECT_CALL(
mock_favicon_service_,
GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
- kDefaultDesiredSizeInPixel, _, _, &tracker_))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
- return kDummyTaskId;
- });
+ kDefaultDesiredSizeInPixel, _, _, &tracker_));
EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
.WillOnce([](auto) { return favicon_base::FaviconRawBitmapResult(); });
favicon_base::FaviconRawBitmapResult result;
@@ -179,6 +258,8 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetEmptyBitmap) {
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kNotAvailable, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
}
TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetSyncBitmap) {
@@ -187,12 +268,7 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetSyncBitmap) {
EXPECT_CALL(
mock_favicon_service_,
GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
- kDefaultDesiredSizeInPixel, _, _, &tracker_))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
- return kDummyTaskId;
- });
+ kDefaultDesiredSizeInPixel, _, _, &tracker_));
EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
.WillOnce([](auto) { return CreateTestBitmapResult(); });
favicon_base::FaviconRawBitmapResult result;
@@ -204,20 +280,18 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetSyncBitmap) {
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kSync, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
}
TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetLocalBitmap) {
scoped_feature_list_.InitAndDisableFeature(
kEnableHistoryFaviconsGoogleServerQuery);
+ mock_favicon_service_.StoreMockLocalFavicon(GURL(kDummyPageUrl));
EXPECT_CALL(
mock_favicon_service_,
GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
- kDefaultDesiredSizeInPixel, _, _, &tracker_))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(CreateTestBitmapResult());
- return kDummyTaskId;
- });
+ kDefaultDesiredSizeInPixel, _, _, &tracker_));
EXPECT_CALL(mock_large_icon_service_,
TouchIconFromGoogleServer(GURL(kDummyIconUrl)));
EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
@@ -230,37 +304,25 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetLocalBitmap) {
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kLocal, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
}
TEST_F(HistoryUiFaviconRequestHandlerImplTest,
ShouldGetGoogleServerBitmapForFullUrl) {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
kEnableHistoryFaviconsGoogleServerQuery, {{"trim_url_path", "false"}});
+ mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
EXPECT_CALL(can_send_history_data_getter_, Run());
EXPECT_CALL(
mock_favicon_service_,
GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
kDefaultDesiredSizeInPixel, _, _, &tracker_))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
- return kDummyTaskId;
- })
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(CreateTestBitmapResult());
- return kDummyTaskId;
- });
+ .Times(2);
EXPECT_CALL(mock_large_icon_service_,
GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- FetcherParamsPageUrlEq(kDummyPageUrl), _,
- /*should_trim_url_path=*/false, _, _))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::GoogleFaviconServerCallback server_callback) {
- std::move(server_callback)
- .Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS);
- });
- EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
+ GURL(kDummyPageUrl), _,
+ /*should_trim_url_path=*/false, _, _));
favicon_base::FaviconRawBitmapResult result;
history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
GURL(kDummyPageUrl), kDefaultDesiredSizeInPixel,
@@ -270,6 +332,8 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest,
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kLocal, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
histogram_tester_.ExpectUniqueSample(
std::string(kGroupingHistogramName) + kDummyOriginHistogramSuffix, 1, 1);
}
@@ -278,30 +342,17 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest,
ShouldGetGoogleServerBitmapForTrimmedUrl) {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
kEnableHistoryFaviconsGoogleServerQuery, {{"trim_url_path", "true"}});
+ mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
EXPECT_CALL(can_send_history_data_getter_, Run());
EXPECT_CALL(
mock_favicon_service_,
GetRawFaviconForPageURL(GURL(kDummyPageUrl), _,
kDefaultDesiredSizeInPixel, _, _, &tracker_))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
- return kDummyTaskId;
- })
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::FaviconRawBitmapCallback callback, auto) {
- std::move(callback).Run(CreateTestBitmapResult());
- return kDummyTaskId;
- });
+ .Times(2);
EXPECT_CALL(mock_large_icon_service_,
GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- FetcherParamsPageUrlEq(kDummyPageUrl), _,
- /*should_trim_url_path=*/true, _, _))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::GoogleFaviconServerCallback server_callback) {
- std::move(server_callback)
- .Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS);
- });
+ GURL(kDummyPageUrl), _,
+ /*should_trim_url_path=*/true, _, _));
EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
favicon_base::FaviconRawBitmapResult result;
history_ui_favicon_request_handler_.GetRawFaviconForPageURL(
@@ -312,6 +363,8 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest,
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kLocal, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
histogram_tester_.ExpectUniqueSample(
std::string(kGroupingHistogramName) + kDummyOriginHistogramSuffix, 1, 1);
}
@@ -320,11 +373,7 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetEmptyImage) {
scoped_feature_list_.InitAndDisableFeature(
kEnableHistoryFaviconsGoogleServerQuery);
EXPECT_CALL(mock_favicon_service_,
- GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconImageResult());
- return kDummyTaskId;
- });
+ GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_));
EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
.WillOnce([](auto) { return favicon_base::FaviconRawBitmapResult(); });
favicon_base::FaviconImageResult result;
@@ -335,17 +384,15 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetEmptyImage) {
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kNotAvailable, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
}
TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetSyncImage) {
scoped_feature_list_.InitAndDisableFeature(
kEnableHistoryFaviconsGoogleServerQuery);
EXPECT_CALL(mock_favicon_service_,
- GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconImageResult());
- return kDummyTaskId;
- });
+ GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_));
EXPECT_CALL(synced_favicon_getter_, Run(GURL(kDummyPageUrl)))
.WillOnce([](auto) { return CreateTestBitmapResult(); });
favicon_base::FaviconImageResult result;
@@ -356,17 +403,16 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetSyncImage) {
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kSync, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
}
TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetLocalImage) {
scoped_feature_list_.InitAndDisableFeature(
kEnableHistoryFaviconsGoogleServerQuery);
+ mock_favicon_service_.StoreMockLocalFavicon(GURL(kDummyPageUrl));
EXPECT_CALL(mock_favicon_service_,
- GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(CreateTestImageResult());
- return kDummyTaskId;
- });
+ GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_));
EXPECT_CALL(mock_large_icon_service_,
TouchIconFromGoogleServer(GURL(kDummyIconUrl)));
EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
@@ -378,32 +424,23 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest, ShouldGetLocalImage) {
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kLocal, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
}
TEST_F(HistoryUiFaviconRequestHandlerImplTest,
ShouldGetGoogleServerImageForFullUrl) {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
kEnableHistoryFaviconsGoogleServerQuery, {{"trim_url_path", "false"}});
+ mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
EXPECT_CALL(can_send_history_data_getter_, Run());
EXPECT_CALL(mock_favicon_service_,
GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconImageResult());
- return kDummyTaskId;
- })
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(CreateTestImageResult());
- return kDummyTaskId;
- });
+ .Times(2);
EXPECT_CALL(mock_large_icon_service_,
GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- FetcherParamsPageUrlEq(kDummyPageUrl), _,
- /*should_trim_url_path=*/false, _, _))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::GoogleFaviconServerCallback server_callback) {
- std::move(server_callback)
- .Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS);
- });
+ GURL(kDummyPageUrl), _,
+ /*should_trim_url_path=*/false, _, _));
EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
favicon_base::FaviconImageResult result;
history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
@@ -413,6 +450,8 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest,
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kLocal, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
histogram_tester_.ExpectUniqueSample(
std::string(kGroupingHistogramName) + kDummyOriginHistogramSuffix, 1, 1);
}
@@ -421,26 +460,15 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest,
ShouldGetGoogleServerImageForTrimmedUrl) {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
kEnableHistoryFaviconsGoogleServerQuery, {{"trim_url_path", "true"}});
+ mock_large_icon_service_.StoreMockGoogleServerFavicon(GURL(kDummyPageUrl));
EXPECT_CALL(can_send_history_data_getter_, Run());
EXPECT_CALL(mock_favicon_service_,
GetFaviconImageForPageURL(GURL(kDummyPageUrl), _, &tracker_))
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(favicon_base::FaviconImageResult());
- return kDummyTaskId;
- })
- .WillOnce([](auto, favicon_base::FaviconImageCallback callback, auto) {
- std::move(callback).Run(CreateTestImageResult());
- return kDummyTaskId;
- });
+ .Times(2);
EXPECT_CALL(mock_large_icon_service_,
GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- FetcherParamsPageUrlEq(kDummyPageUrl), _,
- /*should_trim_url_path=*/true, _, _))
- .WillOnce([](auto, auto, auto, auto,
- favicon_base::GoogleFaviconServerCallback server_callback) {
- std::move(server_callback)
- .Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS);
- });
+ GURL(kDummyPageUrl), _,
+ /*should_trim_url_path=*/true, _, _));
EXPECT_CALL(synced_favicon_getter_, Run(_)).Times(0);
favicon_base::FaviconImageResult result;
history_ui_favicon_request_handler_.GetFaviconImageForPageURL(
@@ -450,6 +478,8 @@ TEST_F(HistoryUiFaviconRequestHandlerImplTest,
histogram_tester_.ExpectUniqueSample(
std::string(kAvailabilityHistogramName) + kDummyOriginHistogramSuffix,
FaviconAvailability::kLocal, 1);
+ histogram_tester_.ExpectTotalCount(
+ std::string(kLatencyHistogramName) + kDummyOriginHistogramSuffix, 1);
histogram_tester_.ExpectUniqueSample(
std::string(kGroupingHistogramName) + kDummyOriginHistogramSuffix, 1, 1);
}
diff --git a/chromium/components/favicon/core/large_icon_service.h b/chromium/components/favicon/core/large_icon_service.h
index 8eab8b80e3b..4cfb343f012 100644
--- a/chromium/components/favicon/core/large_icon_service.h
+++ b/chromium/components/favicon/core/large_icon_service.h
@@ -20,8 +20,6 @@ class GURL;
namespace favicon {
-class FaviconServerFetcherParams;
-
// The large icon service provides methods to access large icons.
class LargeIconService : public KeyedService {
public:
@@ -101,7 +99,7 @@ class LargeIconService : public KeyedService {
// TODO(victorvianna): Consider moving |may_page_url_be_private| and/or
// |should_trim_page_url_path| inside the parameters struct.
virtual void GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- std::unique_ptr<FaviconServerFetcherParams> params,
+ const GURL& page_url,
bool may_page_url_be_private,
bool should_trim_page_url_path,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
diff --git a/chromium/components/favicon/core/large_icon_service_impl.cc b/chromium/components/favicon/core/large_icon_service_impl.cc
index 98af6535601..bec5144031c 100644
--- a/chromium/components/favicon/core/large_icon_service_impl.cc
+++ b/chromium/components/favicon/core/large_icon_service_impl.cc
@@ -19,7 +19,6 @@
#include "base/task/post_task.h"
#include "base/task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/favicon/core/favicon_server_fetcher_params.h"
#include "components/favicon/core/favicon_service.h"
#include "components/favicon_base/fallback_icon_style.h"
#include "components/favicon_base/favicon_util.h"
@@ -88,7 +87,8 @@ GURL GetRequestUrlForGoogleServerV2(
kGoogleServerV2EnforcedMinSizeInPixel, max_size_in_pixel,
page_url.spec().c_str());
base::ReplaceFirstSubstringAfterOffset(
- &request_url, 0, std::string(kClientParam), google_server_client_param);
+ &request_url, 0, std::string(kClientParam),
+ "client=" + google_server_client_param);
return GURL(request_url);
}
@@ -308,8 +308,9 @@ LargeIconWorker::LargeIconWorker(
desired_size_in_pixel_(desired_size_in_pixel),
raw_bitmap_callback_(std::move(raw_bitmap_callback)),
image_callback_(std::move(image_callback)),
- background_task_runner_(base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ background_task_runner_(base::CreateTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
tracker_(tracker),
fallback_icon_style_(
@@ -427,13 +428,26 @@ void OnFetchIconFromGoogleServerComplete(
base::BindOnce(&OnSetOnDemandFaviconComplete, std::move(callback)));
}
+float GetMaxDeviceScale() {
+ std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
+ DCHECK(!favicon_scales.empty());
+ return favicon_scales.back();
+}
+
} // namespace
LargeIconServiceImpl::LargeIconServiceImpl(
FaviconService* favicon_service,
- std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher)
+ std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher,
+ int desired_size_in_dip_for_server_requests,
+ favicon_base::IconType icon_type_for_server_requests,
+ const std::string& google_server_client_param)
: favicon_service_(favicon_service),
- image_fetcher_(std::move(image_fetcher)) {
+ image_fetcher_(std::move(image_fetcher)),
+ desired_size_in_pixel_for_server_requests_(std::ceil(
+ desired_size_in_dip_for_server_requests * GetMaxDeviceScale())),
+ icon_type_for_server_requests_(icon_type_for_server_requests),
+ google_server_client_param_(google_server_client_param) {
large_icon_types_.push_back({favicon_base::IconType::kWebManifestIcon});
large_icon_types_.push_back({favicon_base::IconType::kFavicon});
large_icon_types_.push_back({favicon_base::IconType::kTouchIcon});
@@ -495,7 +509,7 @@ LargeIconServiceImpl::GetLargeIconRawBitmapOrFallbackStyleForIconUrl(
void LargeIconServiceImpl::
GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- std::unique_ptr<FaviconServerFetcherParams> params,
+ const GURL& page_url,
bool may_page_url_be_private,
bool should_trim_page_url_path,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
@@ -509,7 +523,7 @@ void LargeIconServiceImpl::
return;
}
- if (!params->page_url().is_valid()) {
+ if (!page_url.is_valid()) {
FinishServerRequestAsynchronously(
std::move(callback),
GoogleFaviconServerRequestStatus::FAILURE_TARGET_URL_INVALID);
@@ -517,7 +531,7 @@ void LargeIconServiceImpl::
}
const GURL trimmed_page_url =
- TrimPageUrlForGoogleServer(params->page_url(), should_trim_page_url_path);
+ TrimPageUrlForGoogleServer(page_url, should_trim_page_url_path);
if (!trimmed_page_url.is_valid()) {
FinishServerRequestAsynchronously(
std::move(callback),
@@ -526,8 +540,8 @@ void LargeIconServiceImpl::
}
const GURL server_request_url = GetRequestUrlForGoogleServerV2(
- trimmed_page_url, params->google_server_client_param(),
- params->desired_size_in_pixel(), may_page_url_be_private);
+ trimmed_page_url, google_server_client_param_,
+ desired_size_in_pixel_for_server_requests_, may_page_url_be_private);
if (!server_request_url.is_valid()) {
FinishServerRequestAsynchronously(
std::move(callback),
@@ -545,11 +559,10 @@ void LargeIconServiceImpl::
}
favicon_service_->CanSetOnDemandFavicons(
- params->page_url(), params->icon_type(),
+ page_url, icon_type_for_server_requests_,
base::BindOnce(&LargeIconServiceImpl::OnCanSetOnDemandFaviconComplete,
weak_ptr_factory_.GetWeakPtr(), server_request_url,
- params->page_url(), params->icon_type(),
- traffic_annotation, std::move(callback)));
+ page_url, traffic_annotation, std::move(callback)));
}
void LargeIconServiceImpl::TouchIconFromGoogleServer(const GURL& icon_url) {
@@ -605,7 +618,6 @@ LargeIconServiceImpl::GetLargeIconOrFallbackStyleImpl(
void LargeIconServiceImpl::OnCanSetOnDemandFaviconComplete(
const GURL& server_request_url,
const GURL& page_url,
- favicon_base::IconType icon_type,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
favicon_base::GoogleFaviconServerCallback callback,
bool can_set_on_demand_favicon) {
@@ -620,8 +632,8 @@ void LargeIconServiceImpl::OnCanSetOnDemandFaviconComplete(
image_fetcher_->FetchImage(
server_request_url,
base::BindOnce(&OnFetchIconFromGoogleServerComplete, favicon_service_,
- page_url, server_request_url, icon_type,
- std::move(callback)),
+ page_url, server_request_url,
+ icon_type_for_server_requests_, std::move(callback)),
std::move(params));
}
diff --git a/chromium/components/favicon/core/large_icon_service_impl.h b/chromium/components/favicon/core/large_icon_service_impl.h
index c27e427aa8d..7116aeafb9c 100644
--- a/chromium/components/favicon/core/large_icon_service_impl.h
+++ b/chromium/components/favicon/core/large_icon_service_impl.h
@@ -26,7 +26,6 @@ struct NetworkTrafficAnnotationTag;
namespace favicon {
class FaviconService;
-class FaviconServerFetcherParams;
extern const base::Feature kLargeIconServiceFetchingFeature;
@@ -35,7 +34,10 @@ class LargeIconServiceImpl : public LargeIconService {
public:
LargeIconServiceImpl(
FaviconService* favicon_service,
- std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher);
+ std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher,
+ int desired_size_in_dip_for_server_requests,
+ favicon_base::IconType icon_type_for_server_requests,
+ const std::string& google_server_client_param);
~LargeIconServiceImpl() override;
// LargeIconService Implementation.
@@ -61,7 +63,7 @@ class LargeIconServiceImpl : public LargeIconService {
favicon_base::LargeIconCallback callback,
base::CancelableTaskTracker* tracker) override;
void GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- std::unique_ptr<FaviconServerFetcherParams> params,
+ const GURL& page_url,
bool may_page_url_be_private,
bool should_trim_page_url_path,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
@@ -84,20 +86,25 @@ class LargeIconServiceImpl : public LargeIconService {
void OnCanSetOnDemandFaviconComplete(
const GURL& server_request_url,
const GURL& page_url,
- favicon_base::IconType icon_type,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
favicon_base::GoogleFaviconServerCallback callback,
bool can_set_on_demand_favicon);
- FaviconService* favicon_service_;
+ FaviconService* const favicon_service_;
+
+ const std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher_;
+
+ const int desired_size_in_pixel_for_server_requests_;
+
+ const favicon_base::IconType icon_type_for_server_requests_;
+
+ const std::string google_server_client_param_;
// A pre-populated list of icon types to consider when looking for large
// icons. This is an optimization over populating an icon type vector on each
// request.
std::vector<favicon_base::IconTypeSet> large_icon_types_;
- std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher_;
-
base::WeakPtrFactory<LargeIconServiceImpl> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(LargeIconServiceImpl);
diff --git a/chromium/components/favicon/core/large_icon_service_impl_unittest.cc b/chromium/components/favicon/core/large_icon_service_impl_unittest.cc
index 06c85989058..0c97b0291d2 100644
--- a/chromium/components/favicon/core/large_icon_service_impl_unittest.cc
+++ b/chromium/components/favicon/core/large_icon_service_impl_unittest.cc
@@ -11,16 +11,14 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/strings/stringprintf.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/favicon/core/favicon_client.h"
-#include "components/favicon/core/favicon_server_fetcher_params.h"
#include "components/favicon/core/test/mock_favicon_service.h"
#include "components/favicon_base/fallback_icon_style.h"
#include "components/favicon_base/favicon_types.h"
@@ -58,11 +56,6 @@ using testing::SaveArg;
const char kDummyUrl[] = "http://www.example.com";
const char kDummyIconUrl[] = "http://www.example.com/touch_icon.png";
const SkColor kTestColor = SK_ColorRED;
-#if defined(OS_IOS)
-const int kMobileSizeInDip = 32;
-#else
-const int kMobileSizeInDip = 24;
-#endif
ACTION_P(PostFetchReply, p0) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -122,34 +115,34 @@ bool HasBackgroundColor(
class LargeIconServiceTest : public testing::Test {
public:
LargeIconServiceTest()
- : mock_image_fetcher_(new NiceMock<MockImageFetcher>()),
+ : scoped_set_supported_scale_factors_({ui::SCALE_FACTOR_200P}),
+ mock_image_fetcher_(new NiceMock<MockImageFetcher>()),
large_icon_service_(&mock_favicon_service_,
- base::WrapUnique(mock_image_fetcher_)) {
- scoped_set_supported_scale_factors_.reset(
- new ui::test::ScopedSetSupportedScaleFactors({ui::SCALE_FACTOR_200P}));
- }
+ base::WrapUnique(mock_image_fetcher_),
+ /*desired_size_in_dip_for_server_requests=*/24,
+ /*icon_type_for_server_requests=*/
+ favicon_base::IconType::kTouchIcon,
+ /*google_server_client_param=*/"test_chrome") {}
~LargeIconServiceTest() override {}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
+ ui::test::ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_;
NiceMock<MockImageFetcher>* mock_image_fetcher_;
testing::NiceMock<MockFaviconService> mock_favicon_service_;
LargeIconServiceImpl large_icon_service_;
base::HistogramTester histogram_tester_;
- std::unique_ptr<ui::test::ScopedSetSupportedScaleFactors>
- scoped_set_supported_scale_factors_;
private:
DISALLOW_COPY_AND_ASSIGN(LargeIconServiceTest);
};
TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServer) {
- const GURL kExpectedServerUrl(base::StringPrintf(
- "https://t0.gstatic.com/faviconV2?client=chrome&nfrp=2"
- "&check_seen=true&size=%d&min_size=16&max_size=256"
- "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/",
- kMobileSizeInDip * 2));
+ const GURL kExpectedServerUrl(
+ "https://t0.gstatic.com/faviconV2?client=test_chrome&nfrp=2"
+ "&check_seen=true&size=48&min_size=16&max_size=256"
+ "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/");
EXPECT_CALL(mock_favicon_service_, UnableToDownloadFavicon(_)).Times(0);
EXPECT_CALL(mock_favicon_service_,
@@ -176,66 +169,22 @@ TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServer) {
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(GURL(kDummyUrl)),
+ GURL(kDummyUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback,
Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
histogram_tester_.ExpectUniqueSample(
"Favicons.LargeIconService.DownloadedSize", 64, /*expected_count=*/1);
}
-TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerForDesktop) {
+TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerWithOriginalUrl) {
const GURL kExpectedServerUrl(
- "https://t0.gstatic.com/faviconV2?client=chrome_desktop"
- "&nfrp=2&check_seen=true&size=32&min_size=16&max_size=256"
+ "https://t0.gstatic.com/faviconV2?client=test_chrome&nfrp=2"
+ "&check_seen=true&size=48&min_size=16&max_size=256"
"&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/");
-
- EXPECT_CALL(mock_favicon_service_, UnableToDownloadFavicon(_)).Times(0);
- EXPECT_CALL(mock_favicon_service_,
- CanSetOnDemandFavicons(GURL(kDummyUrl),
- favicon_base::IconType::kFavicon, _))
- .WillOnce([](auto, auto, base::OnceCallback<void(bool)> callback) {
- return base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), true));
- });
-
- base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback;
- EXPECT_CALL(*mock_image_fetcher_,
- FetchImageAndData_(kExpectedServerUrl, _, _, _))
- .WillOnce(PostFetchReply(gfx::Image::CreateFrom1xBitmap(
- CreateTestSkBitmap(32, 32, kTestColor))));
- EXPECT_CALL(mock_favicon_service_,
- SetOnDemandFavicons(GURL(kDummyUrl), kExpectedServerUrl,
- favicon_base::IconType::kFavicon, _, _))
- .WillOnce(
- [](auto, auto, auto, auto, base::OnceCallback<void(bool)> callback) {
- return base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), true));
- });
-
- large_icon_service_
- .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForDesktop(
- GURL(kDummyUrl)),
- /*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
- TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
-
- EXPECT_CALL(callback,
- Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS));
- scoped_task_environment_.RunUntilIdle();
- histogram_tester_.ExpectUniqueSample(
- "Favicons.LargeIconService.DownloadedSize", 32, /*expected_count=*/1);
-}
-
-TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerWithOriginalUrl) {
- const GURL kExpectedServerUrl(base::StringPrintf(
- "https://t0.gstatic.com/faviconV2?client=chrome&nfrp=2"
- "&check_seen=true&size=%d&min_size=16&max_size=256"
- "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/",
- kMobileSizeInDip * 2));
const GURL kExpectedOriginalUrl("http://www.example.com/favicon.png");
EXPECT_CALL(mock_favicon_service_,
@@ -266,22 +215,21 @@ TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerWithOriginalUrl) {
base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback;
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(GURL(kDummyUrl)),
+ GURL(kDummyUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback,
Run(favicon_base::GoogleFaviconServerRequestStatus::SUCCESS));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(LargeIconServiceTest, ShouldTrimQueryParametersForGoogleServer) {
const GURL kDummyUrlWithQuery("http://www.example.com?foo=1");
- const GURL kExpectedServerUrl(base::StringPrintf(
- "https://t0.gstatic.com/faviconV2?client=chrome&nfrp=2"
- "&check_seen=true&size=%d&min_size=16&max_size=256"
- "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/",
- kMobileSizeInDip * 2));
+ const GURL kExpectedServerUrl(
+ "https://t0.gstatic.com/faviconV2?client=test_chrome&nfrp=2"
+ "&check_seen=true&size=48&min_size=16&max_size=256"
+ "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/");
EXPECT_CALL(mock_favicon_service_,
CanSetOnDemandFavicons(GURL(kDummyUrlWithQuery),
@@ -301,13 +249,12 @@ TEST_F(LargeIconServiceTest, ShouldTrimQueryParametersForGoogleServer) {
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(
- GURL(kDummyUrlWithQuery)),
+ GURL(kDummyUrlWithQuery),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS,
favicon_base::GoogleFaviconServerCallback());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(LargeIconServiceTest, ShouldNotCheckOnPublicUrls) {
@@ -330,14 +277,14 @@ TEST_F(LargeIconServiceTest, ShouldNotCheckOnPublicUrls) {
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(GURL(kDummyUrl)),
+ GURL(kDummyUrl),
/*may_page_url_be_private=*/false,
/*should_trim_page_url_path=*/false, TRAFFIC_ANNOTATION_FOR_TESTS,
callback.Get());
EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::
FAILURE_CONNECTION_ERROR));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(LargeIconServiceTest, ShouldNotQueryGoogleServerIfInvalidScheme) {
@@ -349,14 +296,13 @@ TEST_F(LargeIconServiceTest, ShouldNotQueryGoogleServerIfInvalidScheme) {
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(
- GURL(kDummyFtpUrl)),
+ GURL(kDummyFtpUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::
FAILURE_TARGET_URL_SKIPPED));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_THAT(histogram_tester_.GetAllSamples(
"Favicons.LargeIconService.DownloadedSize"),
IsEmpty());
@@ -371,25 +317,23 @@ TEST_F(LargeIconServiceTest, ShouldNotQueryGoogleServerIfInvalidURL) {
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(
- GURL(kDummyInvalidUrl)),
+ GURL(kDummyInvalidUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::
FAILURE_TARGET_URL_INVALID));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_THAT(histogram_tester_.GetAllSamples(
"Favicons.LargeIconService.DownloadedSize"),
IsEmpty());
}
TEST_F(LargeIconServiceTest, ShouldReportUnavailableIfFetchFromServerFails) {
- const GURL kExpectedServerUrl(base::StringPrintf(
- "https://t0.gstatic.com/faviconV2?client=chrome&nfrp=2"
- "&check_seen=true&size=%d&min_size=16&max_size=256"
- "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/",
- kMobileSizeInDip * 2));
+ const GURL kExpectedServerUrl(
+ "https://t0.gstatic.com/faviconV2?client=test_chrome&nfrp=2"
+ "&check_seen=true&size=48&min_size=16&max_size=256"
+ "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/");
EXPECT_CALL(mock_favicon_service_,
CanSetOnDemandFavicons(GURL(kDummyUrl),
@@ -410,13 +354,13 @@ TEST_F(LargeIconServiceTest, ShouldReportUnavailableIfFetchFromServerFails) {
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(GURL(kDummyUrl)),
+ GURL(kDummyUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::
FAILURE_CONNECTION_ERROR));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Verify that download failure gets recorded.
histogram_tester_.ExpectUniqueSample(
"Favicons.LargeIconService.DownloadedSize", 0, /*expected_count=*/1);
@@ -424,11 +368,10 @@ TEST_F(LargeIconServiceTest, ShouldReportUnavailableIfFetchFromServerFails) {
TEST_F(LargeIconServiceTest, ShouldNotGetFromGoogleServerIfUnavailable) {
ON_CALL(mock_favicon_service_,
- WasUnableToDownloadFavicon(GURL(base::StringPrintf(
- "https://t0.gstatic.com/faviconV2?client=chrome&nfrp=2"
- "&check_seen=true&size=%d&min_size=16&max_size=256"
- "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/",
- kMobileSizeInDip * 2))))
+ WasUnableToDownloadFavicon(
+ GURL("https://t0.gstatic.com/faviconV2?client=test_chrome&nfrp=2"
+ "&check_seen=true&size=48&min_size=16&max_size=256"
+ "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/")))
.WillByDefault(Return(true));
EXPECT_CALL(mock_favicon_service_, UnableToDownloadFavicon(_)).Times(0);
@@ -439,13 +382,13 @@ TEST_F(LargeIconServiceTest, ShouldNotGetFromGoogleServerIfUnavailable) {
base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback;
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(GURL(kDummyUrl)),
+ GURL(kDummyUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::
FAILURE_HTTP_ERROR_CACHED));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_THAT(histogram_tester_.GetAllSamples(
"Favicons.LargeIconService.DownloadedSize"),
IsEmpty());
@@ -468,13 +411,13 @@ TEST_F(LargeIconServiceTest, ShouldNotGetFromGoogleServerIfCannotSet) {
base::MockCallback<favicon_base::GoogleFaviconServerCallback> callback;
large_icon_service_
.GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(GURL(kDummyUrl)),
+ GURL(kDummyUrl),
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
TRAFFIC_ANNOTATION_FOR_TESTS, callback.Get());
EXPECT_CALL(callback, Run(favicon_base::GoogleFaviconServerRequestStatus::
FAILURE_ICON_EXISTS_IN_DB));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_THAT(histogram_tester_.GetAllSamples(
"Favicons.LargeIconService.DownloadedSize"),
IsEmpty());
@@ -505,7 +448,7 @@ class LargeIconServiceGetterTest : public LargeIconServiceTest,
base::Unretained(this)),
&cancelable_task_tracker_);
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void RawBitmapResultCallback(const favicon_base::LargeIconResult& result) {
diff --git a/chromium/components/favicon/ios/web_favicon_driver.mm b/chromium/components/favicon/ios/web_favicon_driver.mm
index 024d66a8b6b..37bc123b07f 100644
--- a/chromium/components/favicon/ios/web_favicon_driver.mm
+++ b/chromium/components/favicon/ios/web_favicon_driver.mm
@@ -13,7 +13,7 @@
#include "ios/web/public/navigation/navigation_context.h"
#include "ios/web/public/navigation/navigation_item.h"
#include "ios/web/public/navigation/navigation_manager.h"
-#include "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "skia/ext/skia_utils_ios.h"
#include "third_party/skia/include/core/SkBitmap.h"
diff --git a/chromium/components/favicon_base/favicon_url_parser.cc b/chromium/components/favicon_base/favicon_url_parser.cc
index 2d75cd973cb..e9050c02b94 100644
--- a/chromium/components/favicon_base/favicon_url_parser.cc
+++ b/chromium/components/favicon_base/favicon_url_parser.cc
@@ -23,20 +23,6 @@ bool HasSubstringAt(const std::string& path,
return path.compare(start_index, search.length(), search) == 0;
}
-bool ParseIsIconUrl(const std::string& url_type, bool* is_icon_url) {
- if (url_type == "page_url") {
- *is_icon_url = false;
- return true;
- }
-
- if (url_type == "icon_url") {
- *is_icon_url = true;
- return true;
- }
-
- return false;
-}
-
// Parse with legacy FaviconUrlFormat::kFavicon format.
bool ParseFaviconPathWithLegacyFormat(const std::string& path,
chrome::ParsedFaviconPath* parsed) {
@@ -45,14 +31,7 @@ bool ParseFaviconPathWithLegacyFormat(const std::string& path,
const char kIconURLParameter[] = "iconurl/";
const char kSizeParameter[] = "size/";
- parsed->is_icon_url = false;
- parsed->url = "";
- parsed->size_in_dip = gfx::kFaviconSize;
- parsed->device_scale_factor = 1.0f;
- parsed->path_index = std::string::npos;
- // Use of the favicon server is never exposed for the legacy format (only used
- // by extensions).
- parsed->allow_favicon_server_fallback = false;
+ *parsed = chrome::ParsedFaviconPath();
if (path.empty())
return false;
@@ -89,10 +68,9 @@ bool ParseFaviconPathWithLegacyFormat(const std::string& path,
if (HasSubstringAt(path, parsed_index, kIconURLParameter)) {
parsed_index += strlen(kIconURLParameter);
- parsed->is_icon_url = true;
- parsed->url = path.substr(parsed_index);
+ parsed->icon_url = path.substr(parsed_index);
} else {
- parsed->url = path.substr(parsed_index);
+ parsed->page_url = path.substr(parsed_index);
}
// The parsed index needs to be returned in order to allow Instant Extended
@@ -108,56 +86,43 @@ bool ParseFaviconPathWithLegacyFormat(const std::string& path,
// Parse with FaviconUrlFormat::kFavicon2 format.
bool ParseFaviconPathWithFavicon2Format(const std::string& path,
chrome::ParsedFaviconPath* parsed) {
- // Parameters which can be used in chrome://favicon2 path. See file
- // "favicon_url_parser.h" for a description of what each one does.
- const std::string kSizeParameter = "size";
- const std::string kScaleParameter = "scale_factor";
- const std::string kUrlTypeParameter = "url_type";
- const std::string kUrlParameter = "url";
- const std::string kAllowFallbackParameter = "allow_google_server_fallback";
-
if (path.empty())
return false;
- GURL query_url("chrome://favicon2/" + path);
-
- std::string size_str;
- if (!net::GetValueForKeyInQuery(query_url, kSizeParameter, &size_str))
- parsed->size_in_dip = gfx::kFaviconSize;
- else if (!base::StringToInt(size_str, &parsed->size_in_dip))
- return false;
-
- std::string scale_str;
- if (!net::GetValueForKeyInQuery(query_url, kScaleParameter, &scale_str))
- parsed->device_scale_factor = 1.0f;
- else if (!webui::ParseScaleFactor(scale_str, &parsed->device_scale_factor))
- return false;
-
- std::string url_type;
- if (!net::GetValueForKeyInQuery(query_url, kUrlTypeParameter, &url_type))
- parsed->is_icon_url = false;
- else if (!ParseIsIconUrl(url_type, &parsed->is_icon_url))
- return false;
+ GURL query_url = GURL("chrome://favicon2/").Resolve(path);
+
+ *parsed = chrome::ParsedFaviconPath();
+
+ for (net::QueryIterator it(query_url); !it.IsAtEnd(); it.Advance()) {
+ const std::string key = it.GetKey();
+ // Note: each of these keys can be used in chrome://favicon2 path. See file
+ // "favicon_url_parser.h" for a description of what each one does.
+ if (key == "allow_google_server_fallback") {
+ const std::string val = it.GetUnescapedValue();
+ if (!(val == "0" || val == "1"))
+ return false;
+ parsed->allow_favicon_server_fallback = val == "1";
+ } else if (key == "icon_url") {
+ parsed->icon_url = it.GetUnescapedValue();
+ } else if (key == "page_url") {
+ parsed->page_url = it.GetUnescapedValue();
+ } else if (key == "scale_factor" &&
+ !webui::ParseScaleFactor(it.GetUnescapedValue(),
+ &parsed->device_scale_factor)) {
+ return false;
+ } else if (key == "size" && !base::StringToInt(it.GetUnescapedValue(),
+ &parsed->size_in_dip)) {
+ return false;
+ }
+ }
- std::string url;
- if (!net::GetValueForKeyInQuery(query_url, kUrlParameter, &url))
+ if (parsed->page_url.empty() && parsed->icon_url.empty())
return false;
- parsed->url = url;
- if (parsed->is_icon_url) {
- // Fallback is never allowed for icon urls, since the server is queried by
- // page url.
- parsed->allow_favicon_server_fallback = false;
- return true;
- }
-
- // Check optional |kAllowFallbackParameter|.
- std::string allow_favicon_server_fallback;
- if (!net::GetValueForKeyInQuery(query_url, kAllowFallbackParameter,
- &allow_favicon_server_fallback)) {
- parsed->allow_favicon_server_fallback = false;
- } else if (!base::StringToInt(allow_favicon_server_fallback,
- (int*)&parsed->allow_favicon_server_fallback)) {
+ if (parsed->allow_favicon_server_fallback && parsed->page_url.empty()) {
+ // Since the server is queried by page url, we'll fail if no non-empty page
+ // url is provided and the fallback parameter is still set to true.
+ NOTIMPLEMENTED();
return false;
}
@@ -166,6 +131,8 @@ bool ParseFaviconPathWithFavicon2Format(const std::string& path,
} // namespace
+ParsedFaviconPath::ParsedFaviconPath() = default;
+
bool ParseFaviconPath(const std::string& path,
FaviconUrlFormat format,
ParsedFaviconPath* parsed) {
diff --git a/chromium/components/favicon_base/favicon_url_parser.h b/chromium/components/favicon_base/favicon_url_parser.h
index 16e0684d87a..aade7461e35 100644
--- a/chromium/components/favicon_base/favicon_url_parser.h
+++ b/chromium/components/favicon_base/favicon_url_parser.h
@@ -9,28 +9,34 @@
#include <string>
+#include "ui/gfx/favicon_size.h"
+
namespace chrome {
struct ParsedFaviconPath {
- // Whether the URL has the "iconurl" parameter.
- bool is_icon_url;
+ ParsedFaviconPath();
+
+ // URL pointing to the page whose favicon we want.
+ std::string page_url;
- // The URL from which the favicon is being requested.
- std::string url;
+ // URL pointing directly to favicon image. If both |page_url| and |icon_url|
+ // are specified, |page_url| will have precedence. At least one between
+ // |page_url| and |icon_url| must be non-empty.
+ std::string icon_url;
// The size of the requested favicon in dip.
- int size_in_dip;
+ int size_in_dip = gfx::kFaviconSize;
// The device scale factor of the requested favicon.
- float device_scale_factor;
+ float device_scale_factor = 1.0f;
// TODO(victorvianna): Remove this parameter.
// The index of the first character (relative to the path) where the the URL
// from which the favicon is being requested is located.
- size_t path_index;
+ size_t path_index = std::string::npos;
// Whether we should allow making a request to the favicon server as fallback.
- bool allow_favicon_server_fallback;
+ bool allow_favicon_server_fallback = false;
};
// Enum describing the two possible url formats: the legacy chrome://favicon
@@ -64,14 +70,18 @@ struct ParsedFaviconPath {
// chrome://favicon2/?query_parameters
// Standard URL query parameters are used as described below.
//
-// Parameter:
-// 'url' Required
-// The url whose favicon we want.
-// 'url_type' Optional
-// Values: ['icon_url', 'page_url']
-// Specifies whether the |url| parameter refers to the URL of the favicon
-// image directly or to the page whose favicon we want (respectively). If
-// unspecified, defaults to 'page_url'.
+// URL Parameters:
+// 'page_url'
+// URL pointing to the page whose favicon we want.
+// 'icon_url'
+// URL pointing directly to favicon image associated with |page_url|.
+// Pointed image will not necessarily have the most appropriate resolution
+// to the user's device.
+//
+// At least one of the two must be provided and non-empty. If both |page_url|
+// and |icon_url| are passed, |page_url| will have precedence.
+//
+// Other parameters:
// 'size' Optional
// Specifies the requested favicon's size in DIP. If unspecified, defaults
// to 16.
@@ -83,11 +93,12 @@ struct ParsedFaviconPath {
// to 1x.
// Example: chrome://favicon2/?scale_factor=1.2x
//
-// In case |url_type| == 'page_url', we can specify an additional parameter:
// 'allow_google_server_fallback' Optional
// Values: ['1', '0']
// Specifies whether we are allowed to fall back to an external server
-// request in case the icon is not found locally.
+// request (by page url) in case the icon is not found locally.
+// Setting this to 1 while not providing a non-empty page url will cause
+// parsing to fail.
enum class FaviconUrlFormat {
// Legacy chrome://favicon format.
kFaviconLegacy,
diff --git a/chromium/components/favicon_base/favicon_url_parser_unittest.cc b/chromium/components/favicon_base/favicon_url_parser_unittest.cc
index cdb75b43611..685f9c05dce 100644
--- a/chromium/components/favicon_base/favicon_url_parser_unittest.cc
+++ b/chromium/components/favicon_base/favicon_url_parser_unittest.cc
@@ -41,8 +41,8 @@ TEST_F(FaviconUrlParserTest, LegacyParsingNoExtraParams) {
const std::string path1 = url;
EXPECT_TRUE(chrome::ParseFaviconPath(
path1, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_FALSE(parsed.is_icon_url);
- EXPECT_EQ(url, parsed.url);
+ EXPECT_EQ(parsed.icon_url, "");
+ EXPECT_EQ(url, parsed.page_url);
EXPECT_EQ(16, parsed.size_in_dip);
EXPECT_EQ(1.0f, parsed.device_scale_factor);
}
@@ -56,8 +56,8 @@ TEST_F(FaviconUrlParserTest, LegacyParsingSizeParam) {
const std::string path2 = "size/32/" + url;
EXPECT_TRUE(chrome::ParseFaviconPath(
path2, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_FALSE(parsed.is_icon_url);
- EXPECT_EQ(url, parsed.url);
+ EXPECT_EQ(parsed.icon_url, "");
+ EXPECT_EQ(url, parsed.page_url);
EXPECT_EQ(32, parsed.size_in_dip);
EXPECT_EQ(1.0f, parsed.device_scale_factor);
@@ -65,8 +65,8 @@ TEST_F(FaviconUrlParserTest, LegacyParsingSizeParam) {
const std::string path3 = "size/32@1.4x/" + url;
EXPECT_TRUE(chrome::ParseFaviconPath(
path3, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_FALSE(parsed.is_icon_url);
- EXPECT_EQ(url, parsed.url);
+ EXPECT_EQ(parsed.icon_url, "");
+ EXPECT_EQ(url, parsed.page_url);
EXPECT_EQ(32, parsed.size_in_dip);
EXPECT_EQ(1.4f, parsed.device_scale_factor);
@@ -75,8 +75,8 @@ TEST_F(FaviconUrlParserTest, LegacyParsingSizeParam) {
const std::string path4 = "size/16@1.41x/" + url;
EXPECT_TRUE(chrome::ParseFaviconPath(
path4, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_FALSE(parsed.is_icon_url);
- EXPECT_EQ(url, parsed.url);
+ EXPECT_EQ(parsed.icon_url, "");
+ EXPECT_EQ(url, parsed.page_url);
EXPECT_EQ(16, parsed.size_in_dip);
EXPECT_EQ(1.41f, parsed.device_scale_factor);
@@ -95,8 +95,8 @@ TEST_F(FaviconUrlParserTest, LegacyParsingSizeParam) {
const std::string path8 = "http://www.google.com/size/32@1.4x";
EXPECT_TRUE(chrome::ParseFaviconPath(
path8, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_FALSE(parsed.is_icon_url);
- EXPECT_EQ(path8, parsed.url);
+ EXPECT_EQ(parsed.icon_url, "");
+ EXPECT_EQ(path8, parsed.page_url);
EXPECT_EQ(16, parsed.size_in_dip);
EXPECT_EQ(1.0f, parsed.device_scale_factor);
}
@@ -109,8 +109,8 @@ TEST_F(FaviconUrlParserTest, LegacyParsingIconUrlParam) {
const std::string path10 = "iconurl/http://www.google.com/favicon.ico";
EXPECT_TRUE(chrome::ParseFaviconPath(
path10, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_TRUE(parsed.is_icon_url);
- EXPECT_EQ("http://www.google.com/favicon.ico", parsed.url);
+ EXPECT_EQ("http://www.google.com/favicon.ico", parsed.icon_url);
+ EXPECT_EQ("", parsed.page_url);
EXPECT_EQ(16, parsed.size_in_dip);
EXPECT_EQ(1.0f, parsed.device_scale_factor);
}
@@ -125,93 +125,69 @@ TEST_F(FaviconUrlParserTest, LegacyParsingSizeParamAndUrlModifier) {
"size/32/iconurl/http://www.google.com/favicon.ico";
EXPECT_TRUE(chrome::ParseFaviconPath(
path14, chrome::FaviconUrlFormat::kFaviconLegacy, &parsed));
- EXPECT_TRUE(parsed.is_icon_url);
- EXPECT_EQ("http://www.google.com/favicon.ico", parsed.url);
+ EXPECT_EQ("http://www.google.com/favicon.ico", parsed.icon_url);
+ EXPECT_EQ("", parsed.page_url);
EXPECT_EQ(32, parsed.size_in_dip);
}
TEST_F(FaviconUrlParserTest, Favicon2ParsingSizeParam) {
chrome::ParsedFaviconPath parsed;
- EXPECT_TRUE(chrome::ParseFaviconPath("?size=32&url=https%3A%2F%2Fg.com",
+ EXPECT_TRUE(chrome::ParseFaviconPath("?size=32&page_url=https%3A%2F%2Fg.com",
chrome::FaviconUrlFormat::kFavicon2,
&parsed));
- EXPECT_FALSE(parsed.is_icon_url);
EXPECT_EQ(32, parsed.size_in_dip);
- EXPECT_FALSE(chrome::ParseFaviconPath("?size=abc&url=https%3A%2F%2Fg.com",
- chrome::FaviconUrlFormat::kFavicon2,
- &parsed));
+ EXPECT_FALSE(
+ chrome::ParseFaviconPath("?size=abc&page_url=https%3A%2F%2Fg.com",
+ chrome::FaviconUrlFormat::kFavicon2, &parsed));
}
TEST_F(FaviconUrlParserTest, Favicon2ParsingScaleFactorParam) {
chrome::ParsedFaviconPath parsed;
- EXPECT_TRUE(
- chrome::ParseFaviconPath("?scale_factor=2.1x&url=https%3A%2F%2Fg.com",
- chrome::FaviconUrlFormat::kFavicon2, &parsed));
+ EXPECT_TRUE(chrome::ParseFaviconPath(
+ "?scale_factor=2.1x&page_url=https%3A%2F%2Fg.com",
+ chrome::FaviconUrlFormat::kFavicon2, &parsed));
EXPECT_EQ(2.1f, parsed.device_scale_factor);
EXPECT_FALSE(
- chrome::ParseFaviconPath("?scale_factor=-1&url=https%3A%2F%2Fg.com",
+ chrome::ParseFaviconPath("?scale_factor=-1&page_url=https%3A%2F%2Fg.com",
chrome::FaviconUrlFormat::kFavicon2, &parsed));
}
-TEST_F(FaviconUrlParserTest, Favicon2ParsingIconUrlParam) {
+TEST_F(FaviconUrlParserTest, Favicon2ParsingUrlParams) {
chrome::ParsedFaviconPath parsed;
EXPECT_TRUE(
- chrome::ParseFaviconPath("?url_type=icon_url&url=https%3A%2F%2Fg.com",
- chrome::FaviconUrlFormat::kFavicon2, &parsed));
- EXPECT_TRUE(parsed.is_icon_url);
-
- EXPECT_TRUE(
- chrome::ParseFaviconPath("?url_type=page_url&url=https%3A%2F%2Fg.com",
- chrome::FaviconUrlFormat::kFavicon2, &parsed));
- EXPECT_FALSE(parsed.is_icon_url);
-
- EXPECT_FALSE(
- chrome::ParseFaviconPath("?url_type=invalid&url=https%3A%2F%2Fg.com",
+ chrome::ParseFaviconPath("?icon_url=https%3A%2F%2Fg.com%2Ffavicon.ico",
chrome::FaviconUrlFormat::kFavicon2, &parsed));
-}
-
-TEST_F(FaviconUrlParserTest, Favicon2ParsingUrlParam) {
- chrome::ParsedFaviconPath parsed;
-
- // Url parameter is mandatory.
- EXPECT_FALSE(chrome::ParseFaviconPath(
- "?", chrome::FaviconUrlFormat::kFavicon2, &parsed));
+ EXPECT_EQ(parsed.icon_url, "https://g.com/favicon.ico");
+ EXPECT_EQ(parsed.page_url, "");
- // Url parameter is mandatory.
- EXPECT_TRUE(chrome::ParseFaviconPath("?url=https%3A%2F%2Fg.com",
+ EXPECT_TRUE(chrome::ParseFaviconPath("?page_url=https%3A%2F%2Fg.com",
chrome::FaviconUrlFormat::kFavicon2,
&parsed));
- EXPECT_EQ(parsed.url, "https://g.com");
+ EXPECT_EQ(parsed.icon_url, "");
+ EXPECT_EQ(parsed.page_url, "https://g.com");
}
TEST_F(FaviconUrlParserTest, Favicon2ParsingAllowFallbackParam) {
chrome::ParsedFaviconPath parsed;
- // If request is by icon url, fallback parameter should have no effect.
- EXPECT_TRUE(chrome::ParseFaviconPath(
- "?url_type=icon_url&allow_google_server_fallback=1&url=https%3A%"
- "2F%2Fg.com",
- chrome::FaviconUrlFormat::kFavicon2, &parsed));
- EXPECT_FALSE(parsed.allow_favicon_server_fallback);
-
EXPECT_FALSE(chrome::ParseFaviconPath(
- "?url_type=page_url&allow_google_server_fallback=invalid&url=https%"
+ "?allow_google_server_fallback=invalid&page_url=https%"
"3A%2F%2Fg.com",
chrome::FaviconUrlFormat::kFavicon2, &parsed));
EXPECT_TRUE(chrome::ParseFaviconPath(
- "?url_type=page_url&allow_google_server_fallback=0&url=https%3A%"
+ "?allow_google_server_fallback=0&page_url=https%3A%"
"2F%2Fg.com",
chrome::FaviconUrlFormat::kFavicon2, &parsed));
EXPECT_FALSE(parsed.allow_favicon_server_fallback);
EXPECT_TRUE(chrome::ParseFaviconPath(
- "?url_type=page_url&allow_google_server_fallback=1&url=https%3A%"
+ "?allow_google_server_fallback=1&page_url=https%3A%"
"2F%2Fg.com",
chrome::FaviconUrlFormat::kFavicon2, &parsed));
EXPECT_TRUE(parsed.allow_favicon_server_fallback);
diff --git a/chromium/components/feature_engagement/README.md b/chromium/components/feature_engagement/README.md
index ea4a571140b..e9909078f61 100644
--- a/chromium/components/feature_engagement/README.md
+++ b/chromium/components/feature_engagement/README.md
@@ -589,13 +589,14 @@ that you can start Chrome and verify that it behaves correctly.
python ./tools/variations/fieldtrial_util.py DownloadStudy.json android shell_cmd
```
-1. Pass the command line along to the binary you are planning on running or the
- command line utility for the Android platform.
+1. Pass the command line along to the binary you are planning on running.
- For the target `chrome_public_apk` it would be:
+ Note: For Android you need to ensure that all arguments are are within one
+ set of double quotes. In particular, for the Android target
+ `chrome_public_apk` it would be:
```bash
- ./build/android/adb_chrome_public_command_line "--force-fieldtrials=DownloadStudy/DownloadExperiment" "--force-fieldtrial-params=DownloadStudy.DownloadExperiment:availability/>=30/event_1/name%3Adownload_completed;comparator%3A>=1;window%3A120;storage%3A180/event_trigger/name%3Adownload_home_iph_trigger;comparator%3Aany;window%3A90;storage%3A360/event_used/name%3Adownload_home_opened;comparator%3Aany;window%3A90;storage%3A360/session_rate/<1" "--enable-features=IPH_DownloadHome<DownloadStudy"
+ ./out/Debug/bin/chrome_public_apk run --args "--force-fieldtrials=DownloadStudy/DownloadExperiment --force-fieldtrial-params=DownloadStudy.DownloadExperiment:availability/>=30/event_1/name%3Adownload_completed;comparator%3A>=1;window%3A120;storage%3A180/event_trigger/name%3Adownload_home_iph_trigger;comparator%3Aany;window%3A90;storage%3A360/event_used/name%3Adownload_home_opened;comparator%3Aany;window%3A90;storage%3A360/session_rate/<1 --enable-features=IPH_DownloadHome<DownloadStudy"
```
### Printf debugging
diff --git a/chromium/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java b/chromium/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java
index 1fc32c7ec1a..7eeb984951f 100644
--- a/chromium/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java
+++ b/chromium/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java
@@ -10,7 +10,6 @@ import android.support.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.base.CommandLine;
import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JCaller;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.components.feature_engagement.TriggerState;
@@ -46,14 +45,11 @@ public class TrackerImpl implements Tracker {
@Override
public void release() {
assert mNativePtr != 0;
- nativeRelease(this, mNativePtr);
+ nativeRelease(mNativePtr);
assert mNativePtr == 0;
}
}
- private static native void nativeRelease(
- @JCaller DisplayLockHandleAndroid caller, long nativeDisplayLockHandleAndroid);
-
/**
* The pointer to the feature_engagement::TrackerImplAndroid JNI bridge.
*/
@@ -145,4 +141,5 @@ public class TrackerImpl implements Tracker {
private native boolean nativeIsInitialized(long nativeTrackerImplAndroid);
private native void nativeAddOnInitializedCallback(
long nativeTrackerImplAndroid, Callback<Boolean> callback);
+ private static native void nativeRelease(long nativeDisplayLockHandleAndroid);
}
diff --git a/chromium/components/feature_engagement/internal/android/tracker_impl_android.cc b/chromium/components/feature_engagement/internal/android/tracker_impl_android.cc
index f44a5ac8e55..81e968196bf 100644
--- a/chromium/components/feature_engagement/internal/android/tracker_impl_android.cc
+++ b/chromium/components/feature_engagement/internal/android/tracker_impl_android.cc
@@ -184,9 +184,7 @@ DisplayLockHandleAndroid::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
}
-void DisplayLockHandleAndroid::Release(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jobj) {
+void DisplayLockHandleAndroid::Release(JNIEnv* env) {
delete this;
}
} // namespace feature_engagement
diff --git a/chromium/components/feature_engagement/internal/android/tracker_impl_android.h b/chromium/components/feature_engagement/internal/android/tracker_impl_android.h
index 894604b06fe..675c02cec89 100644
--- a/chromium/components/feature_engagement/internal/android/tracker_impl_android.h
+++ b/chromium/components/feature_engagement/internal/android/tracker_impl_android.h
@@ -40,7 +40,7 @@ class DisplayLockHandleAndroid {
base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
// Deletes |this|.
- void Release(JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj);
+ void Release(JNIEnv* env);
private:
// The DisplayLockHandle that this JNI bridge owns.
diff --git a/chromium/components/feature_engagement/internal/in_memory_event_store_unittest.cc b/chromium/components/feature_engagement/internal/in_memory_event_store_unittest.cc
index 73bf2b4b16e..b4c302192f7 100644
--- a/chromium/components/feature_engagement/internal/in_memory_event_store_unittest.cc
+++ b/chromium/components/feature_engagement/internal/in_memory_event_store_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace feature_engagement {
@@ -33,7 +33,7 @@ class InMemoryEventStoreTest : public ::testing::Test {
bool load_callback_has_been_invoked_;
bool last_result_;
std::unique_ptr<std::vector<Event>> loaded_events_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
};
} // namespace
diff --git a/chromium/components/feature_engagement/internal/never_availability_model_unittest.cc b/chromium/components/feature_engagement/internal/never_availability_model_unittest.cc
index a8d5421096f..e2941404fc6 100644
--- a/chromium/components/feature_engagement/internal/never_availability_model_unittest.cc
+++ b/chromium/components/feature_engagement/internal/never_availability_model_unittest.cc
@@ -8,7 +8,7 @@
#include "base/feature_list.h"
#include "base/optional.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace feature_engagement {
@@ -31,7 +31,7 @@ class NeverAvailabilityModelTest : public ::testing::Test {
base::Optional<bool> success_;
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(NeverAvailabilityModelTest);
};
diff --git a/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc b/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
index 6c422e66289..2317ff4a17c 100644
--- a/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
+++ b/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -16,7 +16,7 @@
#include "base/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/feature_engagement/internal/availability_model_impl.h"
#include "components/feature_engagement/internal/display_lock_controller.h"
@@ -415,7 +415,7 @@ class TrackerImplTest : public ::testing::Test {
virtual bool ShouldAvailabilityStoreBeReady() { return true; }
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<TrackerImpl> tracker_;
TestTrackerInMemoryEventStore* event_store_;
TestTrackerAvailabilityModel* availability_model_;
diff --git a/chromium/components/feature_engagement/public/event_constants.cc b/chromium/components/feature_engagement/public/event_constants.cc
index f43a1f873f8..b00db8ed977 100644
--- a/chromium/components/feature_engagement/public/event_constants.cc
+++ b/chromium/components/feature_engagement/public/event_constants.cc
@@ -22,6 +22,9 @@ const char kNewTabOpened[] = "new_tab_opened";
const char kReopenTabConditionsMet[] = "reopen_tab_conditions_met";
const char kTabReopened[] = "tab_reopened";
+const char kMediaBackgrounded[] = "media_backgrounded";
+const char kGlobalMediaControlsOpened[] = "global_media_controls_opened";
+
const char kFocusModeOpened[] = "focus_mode_opened";
const char kFocusModeConditionsMet[] = "focus_mode_conditions_met";
diff --git a/chromium/components/feature_engagement/public/event_constants.h b/chromium/components/feature_engagement/public/event_constants.h
index 559369911d1..a473aa0afa6 100644
--- a/chromium/components/feature_engagement/public/event_constants.h
+++ b/chromium/components/feature_engagement/public/event_constants.h
@@ -31,6 +31,12 @@ extern const char kReopenTabConditionsMet[];
// The user reopened a previously closed tab.
extern const char kTabReopened[];
+// A tab with playing media was sent to the background.
+extern const char kMediaBackgrounded[];
+
+// The user opened the Global Media Controls dialog.
+extern const char kGlobalMediaControlsOpened[];
+
// All the events declared below are the string names of deferred onboarding
// events for the Focus Mode feature.
diff --git a/chromium/components/feature_engagement/public/feature_constants.cc b/chromium/components/feature_engagement/public/feature_constants.cc
index de320468eb0..e93077ad0a1 100644
--- a/chromium/components/feature_engagement/public/feature_constants.cc
+++ b/chromium/components/feature_engagement/public/feature_constants.cc
@@ -16,10 +16,12 @@ const base::Feature kIPHDummyFeature{"IPH_Dummy",
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
-const base::Feature kIPHReopenTabFeature{"IPH_ReopenTab",
- base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHFocusModeFeature{"IPH_FocusMode",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHGlobalMediaControlsFeature{
+ "IPH_GlobalMediaControls", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHReopenTabFeature{"IPH_ReopenTab",
+ base::FEATURE_DISABLED_BY_DEFAULT};
#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
const base::Feature kIPHBookmarkFeature{"IPH_Bookmark",
@@ -107,7 +109,7 @@ const base::Feature kIPHNewTabTipFeature{"IPH_NewTabTip",
const base::Feature kIPHNewIncognitoTabTipFeature{
"IPH_NewIncognitoTabTip", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHBadgedReadingListFeature{
- "IPH_BadgedReadingList", base::FEATURE_ENABLED_BY_DEFAULT};
+ "IPH_BadgedReadingList", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHBadgedTranslateManualTriggerFeature{
"IPH_BadgedTranslateManualTrigger", base::FEATURE_DISABLED_BY_DEFAULT};
#endif // defined(OS_IOS)
diff --git a/chromium/components/feature_engagement/public/feature_constants.h b/chromium/components/feature_engagement/public/feature_constants.h
index 192f40ee8fa..fba9baeb0ef 100644
--- a/chromium/components/feature_engagement/public/feature_constants.h
+++ b/chromium/components/feature_engagement/public/feature_constants.h
@@ -19,8 +19,9 @@ extern const base::Feature kIPHDummyFeature;
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
-extern const base::Feature kIPHReopenTabFeature;
extern const base::Feature kIPHFocusModeFeature;
+extern const base::Feature kIPHGlobalMediaControlsFeature;
+extern const base::Feature kIPHReopenTabFeature;
#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
extern const base::Feature kIPHBookmarkFeature;
diff --git a/chromium/components/feature_engagement/public/feature_list.cc b/chromium/components/feature_engagement/public/feature_list.cc
index d66dfd4cb0a..581dbd73ddc 100644
--- a/chromium/components/feature_engagement/public/feature_list.cc
+++ b/chromium/components/feature_engagement/public/feature_list.cc
@@ -59,8 +59,9 @@ const base::Feature* const kAllFeatures[] = {
#endif // defined(OS_IOS)
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
- &kIPHReopenTabFeature,
&kIPHFocusModeFeature,
+ &kIPHGlobalMediaControlsFeature,
+ &kIPHReopenTabFeature,
#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
&kIPHBookmarkFeature,
&kIPHIncognitoWindowFeature,
diff --git a/chromium/components/feature_engagement/public/feature_list.h b/chromium/components/feature_engagement/public/feature_list.h
index ba31a779b49..88281a10879 100644
--- a/chromium/components/feature_engagement/public/feature_list.h
+++ b/chromium/components/feature_engagement/public/feature_list.h
@@ -109,8 +109,9 @@ DEFINE_VARIATION_PARAM(kIPHBadgedTranslateManualTriggerFeature,
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
-DEFINE_VARIATION_PARAM(kIPHReopenTabFeature, "IPH_ReopenTab");
DEFINE_VARIATION_PARAM(kIPHFocusModeFeature, "IPH_FocusMode");
+DEFINE_VARIATION_PARAM(kIPHGlobalMediaControls, "IPH_GlobalMediaControls");
+DEFINE_VARIATION_PARAM(kIPHReopenTabFeature, "IPH_ReopenTab");
#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
DEFINE_VARIATION_PARAM(kIPHBookmarkFeature, "IPH_Bookmark");
DEFINE_VARIATION_PARAM(kIPHIncognitoWindowFeature, "IPH_IncognitoWindow");
@@ -167,8 +168,9 @@ constexpr flags_ui::FeatureEntry::FeatureVariation
VARIATION_ENTRY(kIPHBadgedTranslateManualTriggerFeature),
#elif defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
- VARIATION_ENTRY(kIPHReopenTabFeature),
VARIATION_ENTRY(kIPHFocusModeFeature),
+ VARIATION_ENTRY(kIPHGlobalMediaControls),
+ VARIATION_ENTRY(kIPHReopenTabFeature),
#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
VARIATION_ENTRY(kIPHBookmarkFeature),
VARIATION_ENTRY(kIPHIncognitoWindowFeature),
diff --git a/chromium/components/feed/content/feed_offline_host_unittest.cc b/chromium/components/feed/content/feed_offline_host_unittest.cc
index e27102bfcdb..3589d95a2af 100644
--- a/chromium/components/feed/content/feed_offline_host_unittest.cc
+++ b/chromium/components/feed/content/feed_offline_host_unittest.cc
@@ -12,7 +12,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/feed/core/content_metadata.h"
#include "components/offline_pages/core/client_namespace_constants.h"
@@ -130,7 +130,7 @@ class FeedOfflineHostTest : public ::testing::Test {
return status_notifications_;
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
void SetupHost() {
EXPECT_CALL(*offline_page_model(), AddObserver(testing::_))
@@ -172,7 +172,7 @@ class FeedOfflineHostTest : public ::testing::Test {
status_notifications_.emplace_back(url, available_offline);
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestOfflinePageModel offline_page_model_;
TestPrefetchService prefetch_service_;
std::unique_ptr<FeedOfflineHost> host_;
diff --git a/chromium/components/feed/core/feed_content_database.cc b/chromium/components/feed/core/feed_content_database.cc
index 359ebbbac0d..4ea33bd29b1 100644
--- a/chromium/components/feed/core/feed_content_database.cc
+++ b/chromium/components/feed/core/feed_content_database.cc
@@ -22,13 +22,14 @@ namespace feed {
namespace {
-using StorageEntryVector =
- leveldb_proto::ProtoDatabase<ContentStorageProto>::KeyEntryVector;
-
const char kContentDatabaseFolder[] = "content";
-const size_t kDatabaseWriteBufferSizeBytes = 64 * 1024; // 64KB
-const size_t kDatabaseWriteBufferSizeBytesForLowEndDevice = 32 * 1024; // 32KB
+// Content writes vary a lot in size, loading full page will will have a couple
+// dozen writes totaling a couple dozen KB, but there's a lot of variability.
+// This should result in some batching while also keeping the memory impact very
+// small.
+const size_t kDatabaseWriteBufferSizeBytes = 8 * 1024; // 8KB
+const size_t kDatabaseWriteBufferSizeBytesForLowEndDevice = 4 * 1024; // 4KB
leveldb::ReadOptions CreateReadOptions() {
leveldb::ReadOptions opts;
@@ -51,18 +52,39 @@ bool DatabasePrefixFilter(const std::string& key_prefix,
FeedContentDatabase::FeedContentDatabase(
leveldb_proto::ProtoDatabaseProvider* proto_database_provider,
const base::FilePath& database_folder)
- : FeedContentDatabase(proto_database_provider->GetDB<ContentStorageProto>(
+ : database_status_(InitStatus::kNotInitialized),
+ task_runner_(
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE})),
+ storage_database_(proto_database_provider->GetDB<ContentStorageProto>(
leveldb_proto::ProtoDbType::FEED_CONTENT_DATABASE,
database_folder.AppendASCII(kContentDatabaseFolder),
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))) {}
+ task_runner_)) {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&FeedContentDatabase::InitInternal,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+// Used for testing.
FeedContentDatabase::FeedContentDatabase(
std::unique_ptr<leveldb_proto::ProtoDatabase<ContentStorageProto>>
- storage_database)
+ storage_database,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
: database_status_(InitStatus::kNotInitialized),
+ task_runner_(task_runner),
storage_database_(std::move(storage_database)) {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&FeedContentDatabase::InitInternal,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+FeedContentDatabase::~FeedContentDatabase() = default;
+
+bool FeedContentDatabase::IsInitialized() const {
+ return database_status_ == InitStatus::kOK;
+}
+
+void FeedContentDatabase::InitInternal() {
leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
options.write_buffer_size = base::SysInfo::IsLowEndDevice()
? kDatabaseWriteBufferSizeBytesForLowEndDevice
@@ -73,41 +95,48 @@ FeedContentDatabase::FeedContentDatabase(
weak_ptr_factory_.GetWeakPtr()));
}
-FeedContentDatabase::~FeedContentDatabase() = default;
-
-bool FeedContentDatabase::IsInitialized() const {
- return database_status_ == InitStatus::kOK;
-}
-
void FeedContentDatabase::LoadContent(const std::vector<std::string>& keys,
ContentLoadCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
std::unordered_set<std::string> key_set(keys.begin(), keys.end());
- storage_database_->LoadEntriesWithFilter(
- base::BindRepeating(&DatabaseKeyFilter, std::move(key_set)),
- CreateReadOptions(), /* target_prefix */ "",
- base::BindOnce(&FeedContentDatabase::OnLoadEntriesForLoadContent,
- weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
- std::move(callback)));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedContentDatabase::LoadEntriesWithFilterInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::BindRepeating(&DatabaseKeyFilter, std::move(key_set)),
+ std::move(callback)));
}
void FeedContentDatabase::LoadContentByPrefix(const std::string& prefix,
ContentLoadCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedContentDatabase::LoadEntriesWithFilterInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::BindRepeating(&DatabasePrefixFilter, std::move(prefix)),
+ std::move(callback)));
+}
+void FeedContentDatabase::LoadEntriesWithFilterInternal(
+ const leveldb_proto::KeyFilter& key_filter,
+ ContentLoadCallback callback) {
storage_database_->LoadEntriesWithFilter(
- base::BindRepeating(&DatabasePrefixFilter, std::move(prefix)),
- CreateReadOptions(), /* target_prefix */ "",
+ std::move(key_filter), CreateReadOptions(), /* target_prefix */ "",
base::BindOnce(&FeedContentDatabase::OnLoadEntriesForLoadContent,
weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
std::move(callback)));
}
void FeedContentDatabase::LoadAllContentKeys(ContentKeyCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FeedContentDatabase::LoadKeysInternal,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+void FeedContentDatabase::LoadKeysInternal(ContentKeyCallback callback) {
storage_database_->LoadKeys(
base::BindOnce(&FeedContentDatabase::OnLoadKeysForLoadAllContentKeys,
weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
@@ -117,7 +146,6 @@ void FeedContentDatabase::LoadAllContentKeys(ContentKeyCallback callback) {
void FeedContentDatabase::CommitContentMutation(
std::unique_ptr<ContentMutation> content_mutation,
ConfirmationCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(content_mutation);
UMA_HISTOGRAM_COUNTS_100(
@@ -125,8 +153,8 @@ void FeedContentDatabase::CommitContentMutation(
content_mutation->Size());
if (content_mutation->Empty()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), true));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(callback), true));
return;
}
@@ -138,7 +166,7 @@ void FeedContentDatabase::PerformNextOperation(
ConfirmationCallback callback) {
DCHECK(!content_mutation->Empty());
- ContentOperation operation = content_mutation->TakeFristOperation();
+ ContentOperation operation = content_mutation->TakeFirstOperation();
switch (operation.type()) {
case ContentOperation::CONTENT_DELETE:
@@ -163,8 +191,8 @@ void FeedContentDatabase::PerformNextOperation(
break;
default:
// Operation type is not supported, therefore failing immediately.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), false));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(callback), false));
}
}
@@ -180,10 +208,12 @@ void FeedContentDatabase::UpsertContent(
proto.set_content_data(operation.value());
contents_to_save->emplace_back(proto.key(), std::move(proto));
- storage_database_->UpdateEntries(
- std::move(contents_to_save), std::make_unique<std::vector<std::string>>(),
- base::BindOnce(&FeedContentDatabase::OnOperationCommitted,
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FeedContentDatabase::UpdateEntriesInternal,
weak_ptr_factory_.GetWeakPtr(),
+ std::move(contents_to_save),
+ std::make_unique<std::vector<std::string>>(),
std::move(content_mutation), std::move(callback)));
}
@@ -196,8 +226,22 @@ void FeedContentDatabase::DeleteContent(
auto content_to_delete = std::make_unique<std::vector<std::string>>(
std::initializer_list<std::string>({operation.key()}));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FeedContentDatabase::UpdateEntriesInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::make_unique<StorageEntryVector>(),
+ std::move(content_to_delete), std::move(content_mutation),
+ std::move(callback)));
+}
+
+void FeedContentDatabase::UpdateEntriesInternal(
+ std::unique_ptr<StorageEntryVector> entries_to_save,
+ std::unique_ptr<std::vector<std::string>> keys_to_remove,
+ std::unique_ptr<ContentMutation> content_mutation,
+ ConfirmationCallback callback) {
storage_database_->UpdateEntries(
- std::make_unique<StorageEntryVector>(), std::move(content_to_delete),
+ std::move(entries_to_save), std::move(keys_to_remove),
base::BindOnce(&FeedContentDatabase::OnOperationCommitted,
weak_ptr_factory_.GetWeakPtr(),
std::move(content_mutation), std::move(callback)));
@@ -209,12 +253,13 @@ void FeedContentDatabase::DeleteContentByPrefix(
ConfirmationCallback callback) {
DCHECK_EQ(operation.type(), ContentOperation::CONTENT_DELETE_BY_PREFIX);
- storage_database_->UpdateEntriesWithRemoveFilter(
- std::make_unique<StorageEntryVector>(),
- base::BindRepeating(&DatabasePrefixFilter, operation.prefix()),
- base::BindOnce(&FeedContentDatabase::OnOperationCommitted,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(content_mutation), std::move(callback)));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedContentDatabase::UpdateEntriesWithRemoveFilterInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::BindRepeating(&DatabasePrefixFilter, operation.prefix()),
+ std::move(content_mutation), std::move(callback)));
}
void FeedContentDatabase::DeleteAllContent(
@@ -224,9 +269,21 @@ void FeedContentDatabase::DeleteAllContent(
DCHECK_EQ(operation.type(), ContentOperation::CONTENT_DELETE_ALL);
std::string key_prefix = "";
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedContentDatabase::UpdateEntriesWithRemoveFilterInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::BindRepeating(&DatabasePrefixFilter, std::move(key_prefix)),
+ std::move(content_mutation), std::move(callback)));
+}
+
+void FeedContentDatabase::UpdateEntriesWithRemoveFilterInternal(
+ const leveldb_proto::KeyFilter& key_filter,
+ std::unique_ptr<ContentMutation> content_mutation,
+ ConfirmationCallback callback) {
storage_database_->UpdateEntriesWithRemoveFilter(
- std::make_unique<StorageEntryVector>(),
- base::BindRepeating(&DatabasePrefixFilter, std::move(key_prefix)),
+ std::make_unique<StorageEntryVector>(), std::move(key_filter),
base::BindOnce(&FeedContentDatabase::OnOperationCommitted,
weak_ptr_factory_.GetWeakPtr(),
std::move(content_mutation), std::move(callback)));
diff --git a/chromium/components/feed/core/feed_content_database.h b/chromium/components/feed/core/feed_content_database.h
index 6223adf23e1..0d951f31ff1 100644
--- a/chromium/components/feed/core/feed_content_database.h
+++ b/chromium/components/feed/core/feed_content_database.h
@@ -27,7 +27,9 @@ class ContentStorageProto;
using InitStatus = leveldb_proto::Enums::InitStatus;
// FeedContentDatabase is leveldb backend store for Feed's content storage data.
-// Feed's content data are key-value pairs.
+// Feed's content data are key-value pairs. In order to support callers from
+// different threads, this class posts all database operations to an owned
+// sequenced task runner.
class FeedContentDatabase {
public:
using KeyAndData = std::pair<std::string, std::string>;
@@ -46,6 +48,9 @@ class FeedContentDatabase {
// the entry's existence.
using ConfirmationCallback = base::OnceCallback<void(bool)>;
+ using StorageEntryVector =
+ leveldb_proto::ProtoDatabase<ContentStorageProto>::KeyEntryVector;
+
// Initializes the database with |proto_database_provider| and
// |database_folder|.
FeedContentDatabase(
@@ -56,7 +61,8 @@ class FeedContentDatabase {
// Useful for testing.
explicit FeedContentDatabase(
std::unique_ptr<leveldb_proto::ProtoDatabase<ContentStorageProto>>
- storage_database);
+ storage_database,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
~FeedContentDatabase();
@@ -102,6 +108,21 @@ class FeedContentDatabase {
std::unique_ptr<ContentMutation> content_mutation,
ConfirmationCallback callback);
+ // The following *Internal methods must be executed from |task_runner_|.
+ void InitInternal();
+ void LoadEntriesWithFilterInternal(const leveldb_proto::KeyFilter& key_filter,
+ ContentLoadCallback callback);
+ void LoadKeysInternal(ContentKeyCallback callback);
+ void UpdateEntriesInternal(
+ std::unique_ptr<StorageEntryVector> entries_to_save,
+ std::unique_ptr<std::vector<std::string>> keys_to_remove,
+ std::unique_ptr<ContentMutation> content_mutation,
+ ConfirmationCallback callback);
+ void UpdateEntriesWithRemoveFilterInternal(
+ const leveldb_proto::KeyFilter& key_filter,
+ std::unique_ptr<ContentMutation> content_mutation,
+ ConfirmationCallback callback);
+
// Callback methods given to |storage_database_| for async responses.
void OnDatabaseInitialized(InitStatus status);
void OnLoadEntriesForLoadContent(
@@ -121,12 +142,13 @@ class FeedContentDatabase {
// Status of the database initialization.
InitStatus database_status_;
+ // Task runner on which to execute database calls.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
// The database for storing content storage information.
std::unique_ptr<leveldb_proto::ProtoDatabase<ContentStorageProto>>
storage_database_;
- SEQUENCE_CHECKER(sequence_checker_);
-
base::WeakPtrFactory<FeedContentDatabase> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(FeedContentDatabase);
diff --git a/chromium/components/feed/core/feed_content_database_unittest.cc b/chromium/components/feed/core/feed_content_database_unittest.cc
index a739f003bce..2fef55d70ea 100644
--- a/chromium/components/feed/core/feed_content_database_unittest.cc
+++ b/chromium/components/feed/core/feed_content_database_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/feed/core/feed_content_mutation.h"
#include "components/feed/core/proto/content_storage.pb.h"
#include "components/leveldb_proto/testing/fake_db.h"
@@ -57,10 +57,15 @@ class FeedContentDatabaseTest : public testing::Test {
auto storage_db =
std::make_unique<FakeDB<ContentStorageProto>>(&content_db_storage_);
+ task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE});
+
content_db_ = storage_db.get();
- feed_db_ = std::make_unique<FeedContentDatabase>(std::move(storage_db));
+ feed_db_ = std::make_unique<FeedContentDatabase>(std::move(storage_db),
+ task_runner_);
if (init_database) {
- content_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ InitStatusCallback(content_db_, leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(db()->IsInitialized());
}
}
@@ -73,7 +78,54 @@ class FeedContentDatabaseTest : public testing::Test {
content_db_storage_[key] = storage_proto;
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ // Since the FakeDB implementation doesn't run callbacks on the same task
+ // runner as the original request was made (like the real ProtoDatabase impl
+ // does), we explicitly post all callbacks onto the DB task runner here.
+ void InitStatusCallback(FakeDB<ContentStorageProto>* storage_db,
+ leveldb_proto::Enums::InitStatus status) {
+ task_runner()->PostTask(FROM_HERE,
+ base::BindOnce(
+ [](FakeDB<ContentStorageProto>* storage_db,
+ leveldb_proto::Enums::InitStatus status) {
+ storage_db->InitStatusCallback(status);
+ },
+ storage_db, status));
+ RunUntilIdle();
+ }
+ void LoadCallback(FakeDB<ContentStorageProto>* storage_db, bool success) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce([](FakeDB<ContentStorageProto>* storage_db,
+ bool success) { storage_db->LoadCallback(success); },
+ storage_db, success));
+ RunUntilIdle();
+ }
+ void LoadKeysCallback(FakeDB<ContentStorageProto>* storage_db, bool success) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](FakeDB<ContentStorageProto>* storage_db, bool success) {
+ storage_db->LoadKeysCallback(success);
+ },
+ storage_db, success));
+ RunUntilIdle();
+ }
+ void UpdateCallback(FakeDB<ContentStorageProto>* storage_db, bool success) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](FakeDB<ContentStorageProto>* storage_db, bool success) {
+ storage_db->UpdateCallback(success);
+ },
+ storage_db, success));
+ RunUntilIdle();
+ }
+
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner() {
+ return task_runner_;
+ }
FakeDB<ContentStorageProto>* storage_db() { return content_db_; }
@@ -87,10 +139,12 @@ class FeedContentDatabaseTest : public testing::Test {
MOCK_METHOD1(OnStorageCommitted, void(bool));
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::map<std::string, ContentStorageProto> content_db_storage_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
// Owned by |feed_db_|.
FakeDB<ContentStorageProto>* content_db_;
@@ -106,7 +160,8 @@ TEST_F(FeedContentDatabaseTest, Init) {
CreateDatabase(/*init_database=*/false);
- storage_db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ InitStatusCallback(storage_db(), leveldb_proto::Enums::InitStatus::kOK);
+
EXPECT_TRUE(db()->IsInitialized());
}
@@ -118,7 +173,7 @@ TEST_F(FeedContentDatabaseTest, LoadContentAfterInitSuccess) {
{kContentKey1},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -144,7 +199,7 @@ TEST_F(FeedContentDatabaseTest, LoadContentsEntries) {
{kContentKey2, kContentKey3},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -172,7 +227,7 @@ TEST_F(FeedContentDatabaseTest, LoadContentsEntriesByPrefix) {
kContentKeyPrefix,
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -193,7 +248,7 @@ TEST_F(FeedContentDatabaseTest, LoadAllContentKeys) {
});
db()->LoadAllContentKeys(base::BindOnce(
&FeedContentDatabaseTest::OnContentKeyReceived, base::Unretained(this)));
- storage_db()->LoadKeysCallback(true);
+ LoadKeysCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaSizeHistogramName,
/*size=*/2, 1);
@@ -213,8 +268,8 @@ TEST_F(FeedContentDatabaseTest, SaveContent) {
std::move(content_mutation),
base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->UpdateCallback(true);
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
// Make sure they're there.
EXPECT_CALL(*this, OnContentEntriesReceived(_, _))
@@ -231,7 +286,7 @@ TEST_F(FeedContentDatabaseTest, SaveContent) {
{kContentKey1, kContentKey2},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/2, 1);
@@ -255,8 +310,8 @@ TEST_F(FeedContentDatabaseTest, DeleteContent) {
std::move(content_mutation),
base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->UpdateCallback(true);
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
// Make sure only |kContentKey2| got deleted.
EXPECT_CALL(*this, OnContentEntriesReceived(_, _))
@@ -271,7 +326,7 @@ TEST_F(FeedContentDatabaseTest, DeleteContent) {
{kContentKey1, kContentKey2},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/2, 1);
@@ -294,7 +349,7 @@ TEST_F(FeedContentDatabaseTest, DeleteContentByPrefix) {
std::move(content_mutation),
base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
// Make sure |kContentKey1| and |kContentKey2| got deleted.
EXPECT_CALL(*this, OnContentEntriesReceived(_, _))
@@ -307,7 +362,7 @@ TEST_F(FeedContentDatabaseTest, DeleteContentByPrefix) {
{kContentKey1, kContentKey2},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/1, 1);
@@ -331,7 +386,7 @@ TEST_F(FeedContentDatabaseTest, DeleteAllContent) {
std::move(content_mutation),
base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
// Make sure |kContentKey1| and |kContentKey2| got deleted.
EXPECT_CALL(*this, OnContentEntriesReceived(_, _))
@@ -344,7 +399,7 @@ TEST_F(FeedContentDatabaseTest, DeleteAllContent) {
{kContentKey1, kContentKey2},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/1, 1);
@@ -366,10 +421,10 @@ TEST_F(FeedContentDatabaseTest, SaveAndDeleteContent) {
std::move(content_mutation),
base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->UpdateCallback(true);
- storage_db()->UpdateCallback(true);
- storage_db()->UpdateCallback(true);
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
// Make sure only |kContentKey2| got deleted.
EXPECT_CALL(*this, OnContentEntriesReceived(_, _))
@@ -384,7 +439,7 @@ TEST_F(FeedContentDatabaseTest, SaveAndDeleteContent) {
{kContentKey1, kContentKey2},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(true);
+ LoadCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/4, 1);
@@ -408,7 +463,7 @@ TEST_F(FeedContentDatabaseTest, LoadContentsFail) {
{kContentKey2, kContentKey3},
base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived,
base::Unretained(this)));
- storage_db()->LoadCallback(false);
+ LoadCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -426,7 +481,7 @@ TEST_F(FeedContentDatabaseTest, LoadAllContentKeysFail) {
});
db()->LoadAllContentKeys(base::BindOnce(
&FeedContentDatabaseTest::OnContentKeyReceived, base::Unretained(this)));
- storage_db()->LoadKeysCallback(false);
+ LoadKeysCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaSizeHistogramName, 0);
histogram().ExpectTotalCount(kUmaLoadKeysTimeHistogramName, 1);
diff --git a/chromium/components/feed/core/feed_content_mutation.cc b/chromium/components/feed/core/feed_content_mutation.cc
index 0290ee0622b..9d3d88cd395 100644
--- a/chromium/components/feed/core/feed_content_mutation.cc
+++ b/chromium/components/feed/core/feed_content_mutation.cc
@@ -47,7 +47,7 @@ base::TimeTicks ContentMutation::GetStartTime() const {
return start_time_;
}
-ContentOperation ContentMutation::TakeFristOperation() {
+ContentOperation ContentMutation::TakeFirstOperation() {
ContentOperation operation = std::move(operations_list_.front());
operations_list_.pop_front();
return operation;
diff --git a/chromium/components/feed/core/feed_content_mutation.h b/chromium/components/feed/core/feed_content_mutation.h
index 7c48fde0ad7..61e9f98ae91 100644
--- a/chromium/components/feed/core/feed_content_mutation.h
+++ b/chromium/components/feed/core/feed_content_mutation.h
@@ -40,7 +40,7 @@ class ContentMutation {
// This will remove the first ContentOperation in |operations_list_| and
// return it to caller.
- ContentOperation TakeFristOperation();
+ ContentOperation TakeFirstOperation();
private:
std::list<ContentOperation> operations_list_;
diff --git a/chromium/components/feed/core/feed_content_mutation_unittest.cc b/chromium/components/feed/core/feed_content_mutation_unittest.cc
index 89a88789284..3a56c2f93cf 100644
--- a/chromium/components/feed/core/feed_content_mutation_unittest.cc
+++ b/chromium/components/feed/core/feed_content_mutation_unittest.cc
@@ -32,7 +32,7 @@ TEST_F(FeedContentMutationTest, AppendDeleteOperation) {
mutation.AppendDeleteOperation(kContentkey);
EXPECT_FALSE(mutation.Empty());
- ContentOperation operation = mutation.TakeFristOperation();
+ ContentOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), ContentOperation::CONTENT_DELETE);
EXPECT_EQ(operation.key(), kContentkey);
@@ -45,7 +45,7 @@ TEST_F(FeedContentMutationTest, AppendDeleteAllOperation) {
mutation.AppendDeleteAllOperation();
EXPECT_FALSE(mutation.Empty());
- ContentOperation operation = mutation.TakeFristOperation();
+ ContentOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), ContentOperation::CONTENT_DELETE_ALL);
}
@@ -57,7 +57,7 @@ TEST_F(FeedContentMutationTest, AppendDeleteByPrefixOperation) {
mutation.AppendDeleteByPrefixOperation(kContentPrefix);
EXPECT_FALSE(mutation.Empty());
- ContentOperation operation = mutation.TakeFristOperation();
+ ContentOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), ContentOperation::CONTENT_DELETE_BY_PREFIX);
EXPECT_EQ(operation.prefix(), kContentPrefix);
@@ -70,7 +70,7 @@ TEST_F(FeedContentMutationTest, AppendUpsertOperation) {
mutation.AppendUpsertOperation(kContentkey, kContentValue);
EXPECT_FALSE(mutation.Empty());
- ContentOperation operation = mutation.TakeFristOperation();
+ ContentOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), ContentOperation::CONTENT_UPSERT);
EXPECT_EQ(operation.key(), kContentkey);
diff --git a/chromium/components/feed/core/feed_image_manager_unittest.cc b/chromium/components/feed/core/feed_image_manager_unittest.cc
index 418724a2dae..fc0ae55e616 100644
--- a/chromium/components/feed/core/feed_image_manager_unittest.cc
+++ b/chromium/components/feed/core/feed_image_manager_unittest.cc
@@ -13,7 +13,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/timer/timer.h"
#include "components/image_fetcher/core/image_decoder.h"
@@ -111,7 +111,7 @@ class FeedImageManagerTest : public testing::Test {
ASSERT_TRUE(image_database_->IsInitialized());
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
FeedImageDatabase* image_database() { return image_database_; }
@@ -144,7 +144,7 @@ class FeedImageManagerTest : public testing::Test {
FeedImageDatabase* image_database_;
base::ScopedTempDir database_dir_;
FakeImageDecoder* fake_image_decoder_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
HistogramTester histogram_;
DISALLOW_COPY_AND_ASSIGN(FeedImageManagerTest);
diff --git a/chromium/components/feed/core/feed_journal_database.cc b/chromium/components/feed/core/feed_journal_database.cc
index c0f81056e00..64539b6d404 100644
--- a/chromium/components/feed/core/feed_journal_database.cc
+++ b/chromium/components/feed/core/feed_journal_database.cc
@@ -20,13 +20,11 @@ namespace feed {
namespace {
-using StorageEntryVector =
- leveldb_proto::ProtoDatabase<JournalStorageProto>::KeyEntryVector;
-
const char kJournalDatabaseFolder[] = "journal";
-const size_t kDatabaseWriteBufferSizeBytes = 64 * 1024; // 64KB
-const size_t kDatabaseWriteBufferSizeBytesForLowEndDevice = 32 * 1024; // 32KB
+// Journal updates happen infrequently and are typically ~8KB. However there's
+// also one tiny write during startup before more writes that 1KB should handle.
+const size_t kDatabaseWriteBufferSizeBytes = 1 * 1024; // 1KB
void ReportLoadTimeHistogram(bool success, base::TimeTicks start_time) {
base::TimeDelta load_time = base::TimeTicks::Now() - start_time;
@@ -39,26 +37,30 @@ void ReportLoadTimeHistogram(bool success, base::TimeTicks start_time) {
FeedJournalDatabase::FeedJournalDatabase(
leveldb_proto::ProtoDatabaseProvider* proto_database_provider,
const base::FilePath& database_folder)
- : FeedJournalDatabase(proto_database_provider->GetDB<JournalStorageProto>(
+ : database_status_(InitStatus::kNotInitialized),
+ task_runner_(
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE})),
+ storage_database_(proto_database_provider->GetDB<JournalStorageProto>(
leveldb_proto::ProtoDbType::FEED_JOURNAL_DATABASE,
database_folder.AppendASCII(kJournalDatabaseFolder),
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))) {}
+ task_runner_)) {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&FeedJournalDatabase::InitInternal,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+// Used for testing.
FeedJournalDatabase::FeedJournalDatabase(
std::unique_ptr<leveldb_proto::ProtoDatabase<JournalStorageProto>>
- storage_database)
+ storage_database,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
: database_status_(InitStatus::kNotInitialized),
+ task_runner_(task_runner),
storage_database_(std::move(storage_database)) {
- leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
- options.write_buffer_size = base::SysInfo::IsLowEndDevice()
- ? kDatabaseWriteBufferSizeBytesForLowEndDevice
- : kDatabaseWriteBufferSizeBytes;
-
- storage_database_->Init(
- options, base::BindOnce(&FeedJournalDatabase::OnDatabaseInitialized,
- weak_ptr_factory_.GetWeakPtr()));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&FeedJournalDatabase::InitInternal,
+ weak_ptr_factory_.GetWeakPtr()));
}
FeedJournalDatabase::~FeedJournalDatabase() = default;
@@ -67,30 +69,42 @@ bool FeedJournalDatabase::IsInitialized() const {
return database_status_ == InitStatus::kOK;
}
+void FeedJournalDatabase::InitInternal() {
+ leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
+ options.write_buffer_size = kDatabaseWriteBufferSizeBytes;
+
+ storage_database_->Init(
+ options, base::BindOnce(&FeedJournalDatabase::OnDatabaseInitialized,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
void FeedJournalDatabase::LoadJournal(const std::string& key,
JournalLoadCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- storage_database_->GetEntry(
- key, base::BindOnce(&FeedJournalDatabase::OnGetEntryForLoadJournal,
- weak_ptr_factory_.GetWeakPtr(),
- base::TimeTicks::Now(), std::move(callback)));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedJournalDatabase::GetEntryInternal,
+ weak_ptr_factory_.GetWeakPtr(), std::move(key),
+ base::BindOnce(&FeedJournalDatabase::OnGetEntryForLoadJournal,
+ weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
+ std::move(callback))));
}
void FeedJournalDatabase::DoesJournalExist(const std::string& key,
CheckExistingCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- storage_database_->GetEntry(
- key, base::BindOnce(&FeedJournalDatabase::OnGetEntryForDoesJournalExist,
- weak_ptr_factory_.GetWeakPtr(),
- base::TimeTicks::Now(), std::move(callback)));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedJournalDatabase::GetEntryInternal,
+ weak_ptr_factory_.GetWeakPtr(), std::move(key),
+ base::BindOnce(&FeedJournalDatabase::OnGetEntryForDoesJournalExist,
+ weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
+ std::move(callback))));
}
void FeedJournalDatabase::CommitJournalMutation(
std::unique_ptr<JournalMutation> journal_mutation,
ConfirmationCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(journal_mutation);
UMA_HISTOGRAM_COUNTS_100(
@@ -98,15 +112,15 @@ void FeedJournalDatabase::CommitJournalMutation(
journal_mutation->Size());
if (journal_mutation->Empty()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), true));
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(callback), true));
return;
}
// Skip loading journal if the first operation is JOURNAL_DELETE.
if (journal_mutation->FirstOperationType() ==
JournalOperation::JOURNAL_DELETE) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
+ task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&FeedJournalDatabase::PerformOperations,
weak_ptr_factory_.GetWeakPtr(), nullptr,
@@ -115,16 +129,32 @@ void FeedJournalDatabase::CommitJournalMutation(
}
std::string journal_name = journal_mutation->journal_name();
- storage_database_->GetEntry(
- journal_name,
- base::BindOnce(&FeedJournalDatabase::OnGetEntryForCommitJournalMutation,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(journal_mutation), std::move(callback)));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &FeedJournalDatabase::GetEntryInternal,
+ weak_ptr_factory_.GetWeakPtr(), std::move(journal_name),
+ base::BindOnce(
+ &FeedJournalDatabase::OnGetEntryForCommitJournalMutation,
+ weak_ptr_factory_.GetWeakPtr(), std::move(journal_mutation),
+ std::move(callback))));
+}
+
+void FeedJournalDatabase::GetEntryInternal(
+ const std::string& key,
+ leveldb_proto::Callbacks::Internal<JournalStorageProto>::GetCallback
+ callback) {
+ storage_database_->GetEntry(key, std::move(callback));
}
void FeedJournalDatabase::LoadAllJournalKeys(JournalLoadCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FeedJournalDatabase::LoadKeysInternal,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+void FeedJournalDatabase::LoadKeysInternal(JournalLoadCallback callback) {
storage_database_->LoadKeys(
base::BindOnce(&FeedJournalDatabase::OnLoadKeysForLoadAllJournalKeys,
weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
@@ -132,8 +162,14 @@ void FeedJournalDatabase::LoadAllJournalKeys(JournalLoadCallback callback) {
}
void FeedJournalDatabase::DeleteAllJournals(ConfirmationCallback callback) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FeedJournalDatabase::DeleteAllEntriesInternal,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+void FeedJournalDatabase::DeleteAllEntriesInternal(
+ ConfirmationCallback callback) {
// For deleting all, filter method always return true.
storage_database_->UpdateEntriesWithRemoveFilter(
std::make_unique<StorageEntryVector>(),
@@ -158,14 +194,14 @@ void FeedJournalDatabase::PerformOperations(
JournalMap copy_to_journal;
while (!journal_mutation->Empty()) {
- JournalOperation operation = journal_mutation->TakeFristOperation();
+ JournalOperation operation = journal_mutation->TakeFirstOperation();
switch (operation.type()) {
case JournalOperation::JOURNAL_APPEND:
journal->add_journal_data(operation.value());
break;
case JournalOperation::JOURNAL_COPY:
copy_to_journal[operation.to_journal_name()] =
- CopyJouarnal(operation.to_journal_name(), *journal);
+ CopyJournal(operation.to_journal_name(), *journal);
break;
case JournalOperation::JOURNAL_DELETE:
journal->clear_journal_data();
@@ -197,8 +233,21 @@ void FeedJournalDatabase::CommitOperations(
journals_to_save->emplace_back(it->first, std::move(it->second));
}
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FeedJournalDatabase::UpdateEntriesInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(journals_to_save), std::move(journals_to_delete),
+ std::move(start_time), std::move(callback)));
+}
+
+void FeedJournalDatabase::UpdateEntriesInternal(
+ std::unique_ptr<StorageEntryVector> entries_to_save,
+ std::unique_ptr<std::vector<std::string>> keys_to_remove,
+ base::TimeTicks start_time,
+ ConfirmationCallback callback) {
storage_database_->UpdateEntries(
- std::move(journals_to_save), std::move(journals_to_delete),
+ std::move(entries_to_save), std::move(keys_to_remove),
base::BindOnce(&FeedJournalDatabase::OnOperationCommitted,
weak_ptr_factory_.GetWeakPtr(), std::move(start_time),
std::move(callback)));
@@ -285,7 +334,7 @@ void FeedJournalDatabase::OnOperationCommitted(base::TimeTicks start_time,
std::move(callback).Run(success);
}
-JournalStorageProto FeedJournalDatabase::CopyJouarnal(
+JournalStorageProto FeedJournalDatabase::CopyJournal(
const std::string& new_journal_name,
const JournalStorageProto& source_journal) {
JournalStorageProto new_journal;
diff --git a/chromium/components/feed/core/feed_journal_database.h b/chromium/components/feed/core/feed_journal_database.h
index 4ded3675e36..eda0e7458fb 100644
--- a/chromium/components/feed/core/feed_journal_database.h
+++ b/chromium/components/feed/core/feed_journal_database.h
@@ -29,7 +29,9 @@ class JournalStorageProto;
using InitStatus = leveldb_proto::Enums::InitStatus;
// FeedJournalDatabase is leveldb backend store for Feed's journal storage data.
-// Feed's journal data are key-value pairs.
+// Feed's journal data are key-value pairs. In order to support callers from
+// different threads, this class posts all database operations to an owned
+// sequenced task runner.
class FeedJournalDatabase {
public:
// Returns the journal data as a vector of strings when calling loading data
@@ -47,6 +49,9 @@ class FeedJournalDatabase {
using JournalMap = base::flat_map<std::string, JournalStorageProto>;
+ using StorageEntryVector =
+ leveldb_proto::ProtoDatabase<JournalStorageProto>::KeyEntryVector;
+
// Initializes the database with |proto_database_provider| and
// |database_folder|.
FeedJournalDatabase(
@@ -57,7 +62,8 @@ class FeedJournalDatabase {
// Useful for testing.
explicit FeedJournalDatabase(
std::unique_ptr<leveldb_proto::ProtoDatabase<JournalStorageProto>>
- storage_database);
+ storage_database,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
~FeedJournalDatabase();
@@ -88,9 +94,9 @@ class FeedJournalDatabase {
private:
// This method performs JournalOperation in the |journal_mutation|.
- // If the first operation in |journal_mutation| is JOURNAL_DELETE, journal can
- // be empty, otherwise we need to load |journal| from database and then pass
- // to this method.
+ // If the first operation in |journal_mutation| is JOURNAL_DELETE, journal
+ // can be empty, otherwise we need to load |journal| from database and
+ // then pass to this method.
void PerformOperations(std::unique_ptr<JournalStorageProto> journal,
std::unique_ptr<JournalMutation> journal_mutation,
ConfirmationCallback callback);
@@ -99,6 +105,20 @@ class FeedJournalDatabase {
JournalMap copy_to_journal,
ConfirmationCallback callback);
+ // The following *Internal methods must be executed from |task_runner_|.
+ void InitInternal();
+ void GetEntryInternal(
+ const std::string& key,
+ leveldb_proto::Callbacks::Internal<JournalStorageProto>::GetCallback
+ callback);
+ void LoadKeysInternal(JournalLoadCallback callback);
+ void DeleteAllEntriesInternal(ConfirmationCallback callback);
+ void UpdateEntriesInternal(
+ std::unique_ptr<StorageEntryVector> entries_to_save,
+ std::unique_ptr<std::vector<std::string>> keys_to_remove,
+ base::TimeTicks start_time,
+ ConfirmationCallback callback);
+
// Callback methods given to |storage_database_| for async responses.
void OnDatabaseInitialized(InitStatus status);
void OnGetEntryForLoadJournal(base::TimeTicks start_time,
@@ -124,18 +144,19 @@ class FeedJournalDatabase {
ConfirmationCallback callback,
bool success);
- JournalStorageProto CopyJouarnal(const std::string& new_journal_name,
- const JournalStorageProto& source_journal);
+ JournalStorageProto CopyJournal(const std::string& new_journal_name,
+ const JournalStorageProto& source_journal);
// Status of the database initialization.
InitStatus database_status_;
+ // Task runner on which to execute database calls.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
// The database for storing journal storage information.
std::unique_ptr<leveldb_proto::ProtoDatabase<JournalStorageProto>>
storage_database_;
- SEQUENCE_CHECKER(sequence_checker_);
-
base::WeakPtrFactory<FeedJournalDatabase> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(FeedJournalDatabase);
diff --git a/chromium/components/feed/core/feed_journal_database_unittest.cc b/chromium/components/feed/core/feed_journal_database_unittest.cc
index 172d2d16d68..272661e459c 100644
--- a/chromium/components/feed/core/feed_journal_database_unittest.cc
+++ b/chromium/components/feed/core/feed_journal_database_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/feed/core/feed_journal_mutation.h"
#include "components/feed/core/proto/journal_storage.pb.h"
#include "components/leveldb_proto/testing/fake_db.h"
@@ -63,10 +63,15 @@ class FeedJournalDatabaseTest : public testing::Test {
auto storage_db =
std::make_unique<FakeDB<JournalStorageProto>>(&journal_db_storage_);
+ task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE});
+
journal_db_ = storage_db.get();
- feed_db_ = std::make_unique<FeedJournalDatabase>(std::move(storage_db));
+ feed_db_ = std::make_unique<FeedJournalDatabase>(std::move(storage_db),
+ task_runner_);
if (init_database) {
- journal_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ InitStatusCallback(journal_db_, leveldb_proto::Enums::InitStatus::kOK);
ASSERT_TRUE(db()->IsInitialized());
}
}
@@ -81,7 +86,54 @@ class FeedJournalDatabaseTest : public testing::Test {
journal_db_storage_[key] = storage_proto;
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ // Since the FakeDB implementation doesn't run callbacks on the same task
+ // runner as the original request was made (like the real ProtoDatabase impl
+ // does), we explicitly post all callbacks onto the DB task runner here.
+ void InitStatusCallback(FakeDB<JournalStorageProto>* storage_db,
+ leveldb_proto::Enums::InitStatus status) {
+ task_runner()->PostTask(FROM_HERE,
+ base::BindOnce(
+ [](FakeDB<JournalStorageProto>* storage_db,
+ leveldb_proto::Enums::InitStatus status) {
+ storage_db->InitStatusCallback(status);
+ },
+ storage_db, status));
+ RunUntilIdle();
+ }
+ void GetCallback(FakeDB<JournalStorageProto>* storage_db, bool success) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce([](FakeDB<JournalStorageProto>* storage_db,
+ bool success) { storage_db->GetCallback(success); },
+ storage_db, success));
+ RunUntilIdle();
+ }
+ void LoadKeysCallback(FakeDB<JournalStorageProto>* storage_db, bool success) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](FakeDB<JournalStorageProto>* storage_db, bool success) {
+ storage_db->LoadKeysCallback(success);
+ },
+ storage_db, success));
+ RunUntilIdle();
+ }
+ void UpdateCallback(FakeDB<JournalStorageProto>* storage_db, bool success) {
+ task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](FakeDB<JournalStorageProto>* storage_db, bool success) {
+ storage_db->UpdateCallback(success);
+ },
+ storage_db, success));
+ RunUntilIdle();
+ }
+
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner() {
+ return task_runner_;
+ }
FakeDB<JournalStorageProto>* storage_db() { return journal_db_; }
@@ -94,10 +146,12 @@ class FeedJournalDatabaseTest : public testing::Test {
MOCK_METHOD2(OnCheckJournalExistReceived, void(bool, bool));
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::map<std::string, JournalStorageProto> journal_db_storage_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
// Owned by |feed_db_|.
FakeDB<JournalStorageProto>* journal_db_;
@@ -114,7 +168,7 @@ TEST_F(FeedJournalDatabaseTest, Init) {
CreateDatabase(/*init_database=*/false);
EXPECT_FALSE(db()->IsInitialized());
- storage_db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ InitStatusCallback(storage_db(), leveldb_proto::Enums::InitStatus::kOK);
EXPECT_TRUE(db()->IsInitialized());
}
@@ -140,7 +194,7 @@ TEST_F(FeedJournalDatabaseTest, LoadJournalEntry) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -159,7 +213,7 @@ TEST_F(FeedJournalDatabaseTest, LoadNonExistingJournalEntry) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -176,8 +230,8 @@ TEST_F(FeedJournalDatabaseTest, AppendJournal) {
std::move(journal_mutation),
base::BindOnce(&FeedJournalDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->GetCallback(true);
- storage_db()->UpdateCallback(true);
+ GetCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
// Make sure they're there.
EXPECT_CALL(*this, OnJournalEntryReceived(_, _))
@@ -191,7 +245,7 @@ TEST_F(FeedJournalDatabaseTest, AppendJournal) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/2, 1);
@@ -209,8 +263,8 @@ TEST_F(FeedJournalDatabaseTest, AppendJournal) {
std::move(journal_mutation),
base::BindOnce(&FeedJournalDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->GetCallback(true);
- storage_db()->UpdateCallback(true);
+ GetCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
// Check new instances are there.
EXPECT_CALL(*this, OnJournalEntryReceived(_, _))
@@ -227,7 +281,7 @@ TEST_F(FeedJournalDatabaseTest, AppendJournal) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/3, 1);
@@ -251,8 +305,8 @@ TEST_F(FeedJournalDatabaseTest, CopyJournal) {
std::move(journal_mutation),
base::BindOnce(&FeedJournalDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
- storage_db()->GetCallback(true);
- storage_db()->UpdateCallback(true);
+ GetCallback(storage_db(), true);
+ UpdateCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/4, 1);
@@ -270,7 +324,7 @@ TEST_F(FeedJournalDatabaseTest, CopyJournal) {
kJournalKey2,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
@@ -290,7 +344,7 @@ TEST_F(FeedJournalDatabaseTest, CopyJournal) {
kJournalKey3,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 2);
@@ -310,7 +364,7 @@ TEST_F(FeedJournalDatabaseTest, CopyJournal) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 3);
}
@@ -332,7 +386,7 @@ TEST_F(FeedJournalDatabaseTest, DeleteJournal) {
base::BindOnce(&FeedJournalDatabaseTest::OnStorageCommitted,
base::Unretained(this)));
RunUntilIdle();
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaCommitMutationSizeHistogramName,
/*operations=*/1, 1);
@@ -348,7 +402,7 @@ TEST_F(FeedJournalDatabaseTest, DeleteJournal) {
kJournalKey2,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
@@ -367,7 +421,7 @@ TEST_F(FeedJournalDatabaseTest, DeleteJournal) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 2);
}
@@ -388,7 +442,7 @@ TEST_F(FeedJournalDatabaseTest, ChecExistingJournal) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnCheckJournalExistReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -403,7 +457,7 @@ TEST_F(FeedJournalDatabaseTest, CheckNonExistingJournal) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnCheckJournalExistReceived,
base::Unretained(this)));
- storage_db()->GetCallback(true);
+ GetCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -428,7 +482,7 @@ TEST_F(FeedJournalDatabaseTest, LoadAllJournalKeys) {
db()->LoadAllJournalKeys(
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->LoadKeysCallback(true);
+ LoadKeysCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaSizeHistogramName,
/*size=*/3, 1);
@@ -449,7 +503,7 @@ TEST_F(FeedJournalDatabaseTest, DeleteAllJournals) {
EXPECT_CALL(*this, OnStorageCommitted(true));
db()->DeleteAllJournals(base::BindOnce(
&FeedJournalDatabaseTest::OnStorageCommitted, base::Unretained(this)));
- storage_db()->UpdateCallback(true);
+ UpdateCallback(storage_db(), true);
histogram().ExpectTotalCount(kUmaOperationCommitTimeHistogramName, 1);
@@ -462,7 +516,7 @@ TEST_F(FeedJournalDatabaseTest, DeleteAllJournals) {
db()->LoadAllJournalKeys(
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->LoadKeysCallback(true);
+ LoadKeysCallback(storage_db(), true);
histogram().ExpectBucketCount(kUmaSizeHistogramName,
/*size=*/0, 1);
@@ -487,7 +541,7 @@ TEST_F(FeedJournalDatabaseTest, LoadJournalEntryFail) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(false);
+ GetCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -505,7 +559,7 @@ TEST_F(FeedJournalDatabaseTest, LoadNonExistingJournalEntryFail) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->GetCallback(false);
+ GetCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -526,7 +580,7 @@ TEST_F(FeedJournalDatabaseTest, LoadAllJournalKeysFail) {
db()->LoadAllJournalKeys(
base::BindOnce(&FeedJournalDatabaseTest::OnJournalEntryReceived,
base::Unretained(this)));
- storage_db()->LoadKeysCallback(false);
+ LoadKeysCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaSizeHistogramName, 0);
histogram().ExpectTotalCount(kUmaLoadKeysTimeHistogramName, 1);
@@ -548,7 +602,7 @@ TEST_F(FeedJournalDatabaseTest, ChecExistingJournalFail) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnCheckJournalExistReceived,
base::Unretained(this)));
- storage_db()->GetCallback(false);
+ GetCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
@@ -563,7 +617,7 @@ TEST_F(FeedJournalDatabaseTest, CheckNonExistingJournalFail) {
kJournalKey1,
base::BindOnce(&FeedJournalDatabaseTest::OnCheckJournalExistReceived,
base::Unretained(this)));
- storage_db()->GetCallback(false);
+ GetCallback(storage_db(), false);
histogram().ExpectTotalCount(kUmaLoadTimeHistogramName, 1);
}
diff --git a/chromium/components/feed/core/feed_journal_mutation.cc b/chromium/components/feed/core/feed_journal_mutation.cc
index 22575250a02..d20c2b20e33 100644
--- a/chromium/components/feed/core/feed_journal_mutation.cc
+++ b/chromium/components/feed/core/feed_journal_mutation.cc
@@ -46,7 +46,7 @@ base::TimeTicks JournalMutation::GetStartTime() const {
return start_time_;
}
-JournalOperation JournalMutation::TakeFristOperation() {
+JournalOperation JournalMutation::TakeFirstOperation() {
JournalOperation operation = std::move(operations_list_.front());
operations_list_.pop_front();
return operation;
diff --git a/chromium/components/feed/core/feed_journal_mutation.h b/chromium/components/feed/core/feed_journal_mutation.h
index aa473c34a50..bdbf598b83c 100644
--- a/chromium/components/feed/core/feed_journal_mutation.h
+++ b/chromium/components/feed/core/feed_journal_mutation.h
@@ -40,7 +40,7 @@ class JournalMutation {
// This will remove the first JournalOperation in |operations_list_| and
// return it to caller.
- JournalOperation TakeFristOperation();
+ JournalOperation TakeFirstOperation();
JournalOperation::Type FirstOperationType();
diff --git a/chromium/components/feed/core/feed_journal_mutation_unittest.cc b/chromium/components/feed/core/feed_journal_mutation_unittest.cc
index b220a5d6635..63ba4d51a56 100644
--- a/chromium/components/feed/core/feed_journal_mutation_unittest.cc
+++ b/chromium/components/feed/core/feed_journal_mutation_unittest.cc
@@ -42,7 +42,7 @@ TEST_F(FeedJournalMutationTest, AddAppendOperation) {
std::string(bytes_vector.begin(), bytes_vector.end()));
EXPECT_FALSE(mutation.Empty());
- JournalOperation operation = mutation.TakeFristOperation();
+ JournalOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), JournalOperation::JOURNAL_APPEND);
EXPECT_EQ(operation.value(),
@@ -57,7 +57,7 @@ TEST_F(FeedJournalMutationTest, AddCopyOperation) {
mutation.AddCopyOperation(kJournalName2);
EXPECT_FALSE(mutation.Empty());
- JournalOperation operation = mutation.TakeFristOperation();
+ JournalOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), JournalOperation::JOURNAL_COPY);
EXPECT_EQ(operation.to_journal_name(), kJournalName2);
@@ -71,7 +71,7 @@ TEST_F(FeedJournalMutationTest, AddDeleteOperation) {
mutation.AddDeleteOperation();
EXPECT_FALSE(mutation.Empty());
- JournalOperation operation = mutation.TakeFristOperation();
+ JournalOperation operation = mutation.TakeFirstOperation();
EXPECT_TRUE(mutation.Empty());
EXPECT_EQ(operation.type(), JournalOperation::JOURNAL_DELETE);
}
diff --git a/chromium/components/feed/core/feed_networking_host.cc b/chromium/components/feed/core/feed_networking_host.cc
index bfc314f4bf1..3fd9a1db591 100644
--- a/chromium/components/feed/core/feed_networking_host.cc
+++ b/chromium/components/feed/core/feed_networking_host.cc
@@ -195,7 +195,7 @@ std::unique_ptr<network::SimpleURLLoader> NetworkFetch::MakeLoader() {
resource_request->url = url;
resource_request->load_flags = net::LOAD_BYPASS_CACHE;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = request_type_;
SetRequestHeaders(resource_request.get());
diff --git a/chromium/components/feed/core/feed_networking_host_unittest.cc b/chromium/components/feed/core/feed_networking_host_unittest.cc
index 57c9db4d720..d29f177e0de 100644
--- a/chromium/components/feed/core/feed_networking_host_unittest.cc
+++ b/chromium/components/feed/core/feed_networking_host_unittest.cc
@@ -12,8 +12,8 @@
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_tick_clock.h"
+#include "base/test/task_environment.h"
#include "components/feed/feed_feature_list.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "net/http/http_response_headers.h"
@@ -72,8 +72,7 @@ class FeedNetworkingHostTest : public testing::Test {
&test_factory_);
net_service_ = std::make_unique<FeedNetworkingHost>(
identity_test_env_.identity_manager(), "dummy_api_key",
- shared_url_loader_factory_,
- scoped_task_environment_.GetMockTickClock());
+ shared_url_loader_factory_, task_environment_.GetMockTickClock());
}
FeedNetworkingHost* service() { return net_service_.get(); }
@@ -96,7 +95,7 @@ class FeedNetworkingHostTest : public testing::Test {
test_factory_.AddResponse(url, head, response_string, status);
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
}
void SendRequestAndRespond(const std::string& url_string,
@@ -136,8 +135,8 @@ class FeedNetworkingHostTest : public testing::Test {
network::TestURLLoaderFactory* test_factory() { return &test_factory_; }
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private:
signin::IdentityTestEnvironment identity_test_env_;
@@ -172,7 +171,7 @@ TEST_F(FeedNetworkingHostTest, ShouldSendSuccessfullyMultipleInflight) {
&done_callback2);
SendRequestAndRespond("http://foobar.com/other", "POST", "", "", net::HTTP_OK,
network::URLLoaderCompletionStatus(), &done_callback3);
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_TRUE(done_callback1.has_run);
EXPECT_TRUE(done_callback2.has_run);
@@ -192,7 +191,7 @@ TEST_F(FeedNetworkingHostTest, ShouldSendSuccessfullyDifferentRequestMethods) {
net::HTTP_OK, network::URLLoaderCompletionStatus(),
&done_callback);
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_TRUE(done_callback.has_run);
EXPECT_EQ(done_callback.code, 200);
}
@@ -291,7 +290,7 @@ TEST_F(FeedNetworkingHostTest, CancellationIsSafe) {
service()->Send(GURL("http://foobar.com/feed2"), "POST", request_body,
base::BindOnce(&MockResponseDoneCallback::Done,
base::Unretained(&done_callback2)));
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
service()->CancelRequests();
}
@@ -346,7 +345,7 @@ TEST_F(FeedNetworkingHostTest, TestDurationHistogram) {
service()->Send(url, "POST", request_body,
base::BindOnce(&MockResponseDoneCallback::Done,
base::Unretained(&done_callback)));
- scoped_task_environment_.FastForwardBy(duration);
+ task_environment_.FastForwardBy(duration);
Respond(url, "", net::HTTP_OK, network::URLLoaderCompletionStatus());
EXPECT_TRUE(done_callback.has_run);
@@ -363,10 +362,10 @@ TEST_F(FeedNetworkingHostTest, TestDefaultTimeout) {
service()->Send(url, "POST", request_body,
base::BindOnce(&MockResponseDoneCallback::Done,
base::Unretained(&done_callback)));
- scoped_task_environment_.FastForwardBy(TimeDelta::FromSeconds(29));
+ task_environment_.FastForwardBy(TimeDelta::FromSeconds(29));
EXPECT_FALSE(done_callback.has_run);
- scoped_task_environment_.FastForwardBy(TimeDelta::FromSeconds(29));
+ task_environment_.FastForwardBy(TimeDelta::FromSeconds(29));
EXPECT_TRUE(done_callback.has_run);
histogram_tester.ExpectTimeBucketCount(
"ContentSuggestions.Feed.Network.Duration", TimeDelta::FromSeconds(30),
@@ -384,10 +383,10 @@ TEST_F(FeedNetworkingHostTest, TestParamTimeout) {
service()->Send(url, "POST", request_body,
base::BindOnce(&MockResponseDoneCallback::Done,
base::Unretained(&done_callback)));
- scoped_task_environment_.FastForwardBy(TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(TimeDelta::FromSeconds(1));
EXPECT_FALSE(done_callback.has_run);
- scoped_task_environment_.FastForwardBy(TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(TimeDelta::FromSeconds(1));
EXPECT_TRUE(done_callback.has_run);
}
diff --git a/chromium/components/feedback/anonymizer_tool.cc b/chromium/components/feedback/anonymizer_tool.cc
index 4f77281552d..ed0974bb782 100644
--- a/chromium/components/feedback/anonymizer_tool.cc
+++ b/chromium/components/feedback/anonymizer_tool.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/files/file_path.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -43,24 +44,31 @@ namespace {
// (?i) turns on case insensitivity for the remainder of the regex.
// (?-s) turns off "dot matches newline" for the remainder of the regex.
// (?:regex) denotes non-capturing parentheses group.
-constexpr const char* kCustomPatternsWithContext[] = {
+CustomPatternWithAlias kCustomPatternsWithContext[] = {
// ModemManager
- "(\\bCell ID: ')([0-9a-fA-F]+)(')",
- "(\\bLocation area code: ')([0-9a-fA-F]+)(')",
+ {"CellID", "(\\bCell ID: ')([0-9a-fA-F]+)(')"},
+ {"LocAC", "(\\bLocation area code: ')([0-9a-fA-F]+)(')"},
// wpa_supplicant
- "(?i-s)(\\bssid[= ]')(.+)(')",
- "(?-s)(\\bSSID - hexdump\\(len=[0-9]+\\): )(.+)()",
+ {"SSID", "(?i-s)(\\bssid[= ]')(.+)(')"},
+ {"SSIDHex", "(?-s)(\\bSSID - hexdump\\(len=[0-9]+\\): )(.+)()"},
// shill
- "(?-s)(\\[SSID=)(.+?)(\\])",
-
- // Serial numbers
- "(?i-s)(serial\\s*(?:number)?\\s*[:=]\\s*)([0-9a-zA-Z\\-\"]+)()",
+ {"SSID", "(?-s)(\\[SSID=)(.+?)(\\])"},
+
+ // Serial numbers. The actual serial number itself can include any alphanum
+ // char as well as dashes, periods, colons, slashes and unprintable ASCII
+ // chars (except newline). The second one is for a special case in
+ // edid-decode, where if we genericized it further then we would catch too
+ // many other cases that we don't want to anonymize.
+ {"Serial",
+ "(?i-s)(\\bserial\\s*_?(?:number)?['\"]?\\s*[:=]\\s*['\"]?)"
+ "([0-9a-zA-Z\\-.:\\/\\\\\\x00-\\x09\\x0B-\\x1F]+)(\\b)"},
+ {"Serial", "( Serial Number )(\\d+)(\\b)"},
// GAIA IDs
- R"xxx((\"?\bgaia_id\"?[=:]['\"])(\d+)(\b['\"]))xxx",
- R"xxx((\{id: )(\d+)(, email:))xxx",
+ {"GAIA", R"xxx((\"?\bgaia_id\"?[=:]['\"])(\d+)(\b['\"]))xxx"},
+ {"GAIA", R"xxx((\{id: )(\d+)(, email:))xxx"},
};
bool MaybeUnmapAddress(net::IPAddress* addr) {
@@ -291,7 +299,7 @@ std::string MaybeScrubIPAddress(const std::string& addr) {
// The |kCustomPatternWithoutContext| array defines further patterns to match
// and anonymize. Each pattern consists of a single capturing group.
-CustomPatternWithoutContext kCustomPatternsWithoutContext[] = {
+CustomPatternWithAlias kCustomPatternsWithoutContext[] = {
{"URL", "(?i)(" IRI ")"},
// Email Addresses need to come after URLs because they can be part
// of a query parameter.
@@ -351,14 +359,22 @@ bool FindAndConsumeAndGetSkipped(re2::StringPiece* input,
base::size(args));
}
+// The following MAC addresses will not be anonymized as they are not specific
+// to a device but have general meanings.
+const char* const kNonAnonymizedMacAddresses[] = {
+ "00:00:00:00:00:00", // ARP failure result MAC.
+ "ff:ff:ff:ff:ff:ff", // Broadcast MAC.
+};
+constexpr size_t kNumNonAnonymizedMacs = base::size(kNonAnonymizedMacAddresses);
+
} // namespace
AnonymizerTool::AnonymizerTool(const char* const* first_party_extension_ids)
- : first_party_extension_ids_(first_party_extension_ids),
- custom_patterns_with_context_(base::size(kCustomPatternsWithContext)),
- custom_patterns_without_context_(
- base::size(kCustomPatternsWithoutContext)) {
+ : first_party_extension_ids_(first_party_extension_ids) {
DETACH_FROM_SEQUENCE(sequence_checker_);
+ // Identity-map these, so we don't mangle them.
+ for (const char* mac : kNonAnonymizedMacAddresses)
+ mac_addresses_[mac] = mac;
}
AnonymizerTool::~AnonymizerTool() {
@@ -371,7 +387,11 @@ std::string AnonymizerTool::Anonymize(const std::string& input) {
<< "This is an expensive operation. Do not execute this on the UI "
"thread.";
std::string anonymized = AnonymizeMACAddresses(input);
+ anonymized = AnonymizeAndroidAppStoragePaths(std::move(anonymized));
anonymized = AnonymizeCustomPatterns(std::move(anonymized));
+ // Do hashes last since they may appear in URLs and they also prevent us from
+ // properly recognizing the Android storage paths.
+ anonymized = AnonymizeHashes(std::move(anonymized));
return anonymized;
}
@@ -391,14 +411,15 @@ RE2* AnonymizerTool::GetRegExp(const std::string& pattern) {
std::string AnonymizerTool::AnonymizeMACAddresses(const std::string& input) {
// This regular expression finds the next MAC address. It splits the data into
// an OUI (Organizationally Unique Identifier) part and a NIC (Network
- // Interface Controller) specific part.
+ // Interface Controller) specific part. We also match on dash and underscore
+ // because we have seen instances of both of those occurring.
RE2* mac_re = GetRegExp(
- "([0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]):("
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]:"
+ "([0-9a-fA-F][0-9a-fA-F][:\\-_]"
+ "[0-9a-fA-F][0-9a-fA-F][:\\-_]"
+ "[0-9a-fA-F][0-9a-fA-F])[:\\-_]("
+ "[0-9a-fA-F][0-9a-fA-F][:\\-_]"
+ "[0-9a-fA-F][0-9a-fA-F][:\\-_]"
"[0-9a-fA-F][0-9a-fA-F])");
std::string result;
@@ -406,21 +427,23 @@ std::string AnonymizerTool::AnonymizeMACAddresses(const std::string& input) {
// Keep consuming, building up a result string as we go.
re2::StringPiece text(input);
- re2::StringPiece skipped;
- re2::StringPiece pre_mac, oui, nic;
+ re2::StringPiece skipped, oui, nic;
+ static const char kMacSeparatorChars[] = "-_";
while (FindAndConsumeAndGetSkipped(&text, *mac_re, &skipped, &oui, &nic)) {
- // Look up the MAC address in the hash.
+ // Look up the MAC address in the hash. Force the separator to be a colon
+ // so that the same MAC with a different format will match in all cases.
std::string oui_string = base::ToLowerASCII(oui.as_string());
+ base::ReplaceChars(oui_string, kMacSeparatorChars, ":", &oui_string);
std::string nic_string = base::ToLowerASCII(nic.as_string());
+ base::ReplaceChars(nic_string, kMacSeparatorChars, ":", &nic_string);
std::string mac = oui_string + ":" + nic_string;
std::string replacement_mac = mac_addresses_[mac];
if (replacement_mac.empty()) {
// If not found, build up a replacement MAC address by generating a new
// NIC part.
- int mac_id = mac_addresses_.size();
- replacement_mac = base::StringPrintf(
- "%s:%02x:%02x:%02x", oui_string.c_str(), (mac_id & 0x00ff0000) >> 16,
- (mac_id & 0x0000ff00) >> 8, (mac_id & 0x000000ff));
+ int mac_id = mac_addresses_.size() - kNumNonAnonymizedMacs;
+ replacement_mac = base::StringPrintf("[MAC OUI=%s IFACE=%d]",
+ oui_string.c_str(), mac_id);
mac_addresses_[mac] = replacement_mac;
}
@@ -432,26 +455,133 @@ std::string AnonymizerTool::AnonymizeMACAddresses(const std::string& input) {
return result;
}
+std::string AnonymizerTool::AnonymizeHashes(const std::string& input) {
+ // This will match hexadecimal strings from length 32 to 64 that have a word
+ // boundary at each end. We then check to make sure they are one of our valid
+ // hash lengths before replacing.
+ // NOTE: There are some occurrences in the dump data (specifically modetest)
+ // where relevant data is formatted with 32 hex chars on a line. In this case,
+ // it is preceded by at least 3 whitespace chars, so check for that and in
+ // that case do not redact.
+ RE2* hash_re = GetRegExp(R"((\s*)\b([0-9a-fA-F]{4})([0-9a-fA-F]{28,60})\b)");
+
+ std::string result;
+ result.reserve(input.size());
+
+ // Keep consuming, building up a result string as we go.
+ re2::StringPiece text(input);
+ re2::StringPiece skipped, pre_whitespace, hash_prefix, hash_suffix;
+ while (FindAndConsumeAndGetSkipped(&text, *hash_re, &skipped, &pre_whitespace,
+ &hash_prefix, &hash_suffix)) {
+ skipped.AppendToString(&result);
+ pre_whitespace.AppendToString(&result);
+
+ // Check if it's a valid length for our hashes or if we need to skip due to
+ // the whitespace check.
+ size_t hash_length = 4 + hash_suffix.length();
+ if ((hash_length != 32 && hash_length != 40 && hash_length != 64) ||
+ (hash_length == 32 && pre_whitespace.length() >= 3)) {
+ // This is not a hash string, skip it.
+ hash_prefix.AppendToString(&result);
+ hash_suffix.AppendToString(&result);
+ continue;
+ }
+
+ // Look up the hash value address in the map of replacements.
+ std::string hash_prefix_string =
+ base::ToLowerASCII(hash_prefix.as_string());
+ std::string hash =
+ hash_prefix_string + base::ToLowerASCII(hash_suffix.as_string());
+ std::string replacement_hash = hashes_[hash];
+ if (replacement_hash.empty()) {
+ // If not found, build up a replacement value.
+ replacement_hash = base::StringPrintf(
+ "<HASH:%s %zd>", hash_prefix_string.c_str(), hashes_.size());
+ hashes_[hash] = replacement_hash;
+ }
+
+ result += replacement_hash;
+ }
+
+ text.AppendToString(&result);
+ return result;
+}
+
+std::string AnonymizerTool::AnonymizeAndroidAppStoragePaths(
+ const std::string& input) {
+ // We only use this on Chrome OS and there's differences in the API for
+ // FilePath on Windows which prevents this from compiling, so only enable this
+ // code for Chrome OS.
+#if defined(OS_CHROMEOS)
+ std::string result;
+ result.reserve(input.size());
+
+ // This is for anonymizing 'android_app_storage' output. When the path starts
+ // either /home/root/<hash>/data/data/<package_name>/ or
+ // /home/root/<hash>/data/user_de/<number>/<package_name>/, this function will
+ // anonymize path components following <package_name>/.
+ RE2* path_re = GetRegExp(
+ "(?m)(\\t/home/root/[\\da-f]+/android-data/data/"
+ "(data|user_de/\\d+)/[^/\\n]+)("
+ "/[^\\n]+)");
+
+ // Keep consuming, building up a result string as we go.
+ re2::StringPiece text(input);
+ re2::StringPiece skipped, path_prefix, ignored, app_specific;
+ while (FindAndConsumeAndGetSkipped(&text, *path_re, &skipped, &path_prefix,
+ &ignored, &app_specific)) {
+ // We can record these parts as-is.
+ skipped.AppendToString(&result);
+ path_prefix.AppendToString(&result);
+
+ // |app_specific| has to be anonymized. First, convert it into components,
+ // and then anonymize each component as follows:
+ // - If the component has a non-ASCII character, change it to '*'.
+ // - Otherwise, remove all the characters in the component but the first
+ // one.
+ // - If the original component has 2 or more bytes, add '_'.
+ const base::FilePath path(app_specific.as_string());
+ std::vector<std::string> components;
+ path.GetComponents(&components);
+ DCHECK(!components.empty());
+
+ auto it = components.begin() + 1; // ignore the leading slash
+ for (; it != components.end(); ++it) {
+ const auto& component = *it;
+ DCHECK(!component.empty());
+ result += '/';
+ result += (base::IsStringASCII(component) ? component[0] : '*');
+ if (component.length() > 1)
+ result += '_';
+ }
+ }
+
+ text.AppendToString(&result);
+ return result;
+#else
+ return input;
+#endif // defined(OS_CHROMEOS)
+}
+
std::string AnonymizerTool::AnonymizeCustomPatterns(std::string input) {
for (size_t i = 0; i < base::size(kCustomPatternsWithContext); i++) {
input =
- AnonymizeCustomPatternWithContext(input, kCustomPatternsWithContext[i],
- &custom_patterns_with_context_[i]);
+ AnonymizeCustomPatternWithContext(input, kCustomPatternsWithContext[i]);
}
for (size_t i = 0; i < base::size(kCustomPatternsWithoutContext); i++) {
input = AnonymizeCustomPatternWithoutContext(
- input, kCustomPatternsWithoutContext[i],
- &custom_patterns_without_context_[i]);
+ input, kCustomPatternsWithoutContext[i]);
}
return input;
}
std::string AnonymizerTool::AnonymizeCustomPatternWithContext(
const std::string& input,
- const std::string& pattern,
- std::map<std::string, std::string>* identifier_space) {
- RE2* re = GetRegExp(pattern);
+ const CustomPatternWithAlias& pattern) {
+ RE2* re = GetRegExp(pattern.pattern);
DCHECK_EQ(3, re->NumberOfCapturingGroups());
+ std::map<std::string, std::string>* identifier_space =
+ &custom_patterns_with_context_[pattern.alias];
std::string result;
result.reserve(input.size());
@@ -465,7 +595,11 @@ std::string AnonymizerTool::AnonymizeCustomPatternWithContext(
std::string matched_id_as_string = matched_id.as_string();
std::string replacement_id = (*identifier_space)[matched_id_as_string];
if (replacement_id.empty()) {
- replacement_id = base::NumberToString(identifier_space->size());
+ // The weird NumberToString trick is because Windows does not like
+ // to deal with %zu and a size_t in printf, nor does it support %llu.
+ replacement_id = base::StringPrintf(
+ "<%s: %s>", pattern.alias,
+ base::NumberToString(identifier_space->size()).c_str());
(*identifier_space)[matched_id_as_string] = replacement_id;
}
@@ -525,11 +659,13 @@ bool IsUrlWhitelisted(re2::StringPiece url,
std::string AnonymizerTool::AnonymizeCustomPatternWithoutContext(
const std::string& input,
- const CustomPatternWithoutContext& pattern,
- std::map<std::string, std::string>* identifier_space) {
+ const CustomPatternWithAlias& pattern) {
RE2* re = GetRegExp(pattern.pattern);
DCHECK_EQ(1, re->NumberOfCapturingGroups());
+ std::map<std::string, std::string>* identifier_space =
+ &custom_patterns_without_context_[pattern.alias];
+
std::string result;
result.reserve(input.size());
@@ -548,7 +684,7 @@ std::string AnonymizerTool::AnonymizeCustomPatternWithoutContext(
if (replacement_id.empty()) {
replacement_id = MaybeScrubIPAddress(matched_id_as_string);
if (replacement_id != matched_id_as_string) {
- // The weird Uint64toString trick is because Windows does not like
+ // The weird NumberToString trick is because Windows does not like
// to deal with %zu and a size_t in printf, nor does it support %llu.
replacement_id = base::StringPrintf(
"<%s: %s>",
diff --git a/chromium/components/feedback/anonymizer_tool.h b/chromium/components/feedback/anonymizer_tool.h
index 9aea4bab5e8..44bfcf46df0 100644
--- a/chromium/components/feedback/anonymizer_tool.h
+++ b/chromium/components/feedback/anonymizer_tool.h
@@ -21,12 +21,12 @@ class RE2;
namespace feedback {
-struct CustomPatternWithoutContext {
+struct CustomPatternWithAlias {
// A string literal used in anonymized tests. Matches to the |pattern| are
// replaced with <|alias|: 1>, <|alias|: 2>, ...
const char* alias;
- // A RE2 regexp with exactly one capture group. Matches will be replaced by
- // the alias reference described above.
+ // A RE2 regexp used in the replacing logic. Matches will be replaced by the
+ // alias reference described above.
const char* pattern;
};
@@ -50,32 +50,42 @@ class AnonymizerTool {
re2::RE2* GetRegExp(const std::string& pattern);
std::string AnonymizeMACAddresses(const std::string& input);
+ std::string AnonymizeAndroidAppStoragePaths(const std::string& input);
+ std::string AnonymizeHashes(const std::string& input);
std::string AnonymizeCustomPatterns(std::string input);
std::string AnonymizeCustomPatternWithContext(
const std::string& input,
- const std::string& pattern,
- std::map<std::string, std::string>* identifier_space);
+ const CustomPatternWithAlias& pattern);
std::string AnonymizeCustomPatternWithoutContext(
const std::string& input,
- const CustomPatternWithoutContext& pattern,
- std::map<std::string, std::string>* identifier_space);
+ const CustomPatternWithAlias& pattern);
// Null-terminated list of first party extension IDs. We need to have this
// passed into us because we can't refer to the code where these are defined.
const char* const* first_party_extension_ids_; // Not owned.
// Map of MAC addresses discovered in anonymized strings to anonymized
- // representations. 11:22:33:44:55:66 gets anonymized to 11:22:33:00:00:01,
- // where the first three bytes represent the manufacturer. The last three
- // bytes are used to distinguish different MAC addresses and are incremented
- // for each newly discovered MAC address.
+ // representations. 11:22:33:44:55:66 gets anonymized to
+ // [MAC OUI=11:22:33 IFACE=1], where the first three bytes (OUI) represent the
+ // manufacturer. The IFACE value is incremented for each newly discovered MAC
+ // address.
std::map<std::string, std::string> mac_addresses_;
+ // Map of hashes discovered in anonymized strings to anonymized
+ // representations. Hexadecimal strings of length 32, 40 and 64 are considered
+ // to be hashes. 11223344556677889900aabbccddeeff gets anonymized to
+ // <HASH:1122 1> where the first 2 bytes of the hash are retained as-is and
+ // the value after that is incremented for each newly discovered hash.
+ std::map<std::string, std::string> hashes_;
+
// Like mac addresses, identifiers in custom patterns are anonymized.
- // custom_patterns_with_context_[i] contains a map of original identifier to
- // anonymized identifier for custom pattern number i.
- std::vector<std::map<std::string, std::string>> custom_patterns_with_context_;
- std::vector<std::map<std::string, std::string>>
+ // custom_patterns_with_context_["alias"] contains a map of original
+ // identifier to anonymized identifier for custom pattern with the given
+ // "alias". We key on alias to allow different patterns to use the same
+ // replacement maps.
+ std::map<std::string, std::map<std::string, std::string>>
+ custom_patterns_with_context_;
+ std::map<std::string, std::map<std::string, std::string>>
custom_patterns_without_context_;
// Cache to prevent the repeated compilation of the same regular expression
diff --git a/chromium/components/feedback/anonymizer_tool_unittest.cc b/chromium/components/feedback/anonymizer_tool_unittest.cc
index 7a8faecb918..853338ddfe3 100644
--- a/chromium/components/feedback/anonymizer_tool_unittest.cc
+++ b/chromium/components/feedback/anonymizer_tool_unittest.cc
@@ -19,23 +19,28 @@ class AnonymizerToolTest : public testing::Test {
return anonymizer_.AnonymizeMACAddresses(input);
}
+ std::string AnonymizeHashes(const std::string& input) {
+ return anonymizer_.AnonymizeHashes(input);
+ }
+
+ std::string AnonymizeAndroidAppStoragePaths(const std::string& input) {
+ return anonymizer_.AnonymizeAndroidAppStoragePaths(input);
+ }
+
std::string AnonymizeCustomPatterns(const std::string& input) {
return anonymizer_.AnonymizeCustomPatterns(input);
}
std::string AnonymizeCustomPatternWithContext(
const std::string& input,
- const std::string& pattern,
- std::map<std::string, std::string>* space) {
- return anonymizer_.AnonymizeCustomPatternWithContext(input, pattern, space);
+ const CustomPatternWithAlias& pattern) {
+ return anonymizer_.AnonymizeCustomPatternWithContext(input, pattern);
}
std::string AnonymizeCustomPatternWithoutContext(
const std::string& input,
- const CustomPatternWithoutContext& pattern,
- std::map<std::string, std::string>* space) {
- return anonymizer_.AnonymizeCustomPatternWithoutContext(input, pattern,
- space);
+ const CustomPatternWithAlias& pattern) {
+ return anonymizer_.AnonymizeCustomPatternWithoutContext(input, pattern);
}
AnonymizerTool anonymizer_{kFakeFirstPartyExtensionIDs};
@@ -46,10 +51,16 @@ TEST_F(AnonymizerToolTest, Anonymize) {
EXPECT_EQ("foo\nbar\n", anonymizer_.Anonymize("foo\nbar\n"));
// Make sure MAC address anonymization is invoked.
- EXPECT_EQ("02:46:8a:00:00:01", anonymizer_.Anonymize("02:46:8a:ce:13:57"));
+ EXPECT_EQ("[MAC OUI=02:46:8a IFACE=1]",
+ anonymizer_.Anonymize("02:46:8a:ce:13:57"));
+
+ // Make sure hash anonymization is invoked.
+ EXPECT_EQ("<HASH:1122 1>",
+ anonymizer_.Anonymize("11223344556677889900AABBCCDDEEFF"));
// Make sure custom pattern anonymization is invoked.
- EXPECT_EQ("Cell ID: '1'", AnonymizeCustomPatterns("Cell ID: 'A1B2'"));
+ EXPECT_EQ("Cell ID: '<CellID: 1>'",
+ AnonymizeCustomPatterns("Cell ID: 'A1B2'"));
// Make sure UUIDs are anonymized.
EXPECT_EQ(
@@ -72,61 +83,129 @@ TEST_F(AnonymizerToolTest, AnonymizeMACAddresses) {
EXPECT_EQ("", AnonymizeMACAddresses(""));
EXPECT_EQ("foo\nbar\n", AnonymizeMACAddresses("foo\nbar\n"));
EXPECT_EQ("11:22:33:44:55", AnonymizeMACAddresses("11:22:33:44:55"));
- EXPECT_EQ("aa:bb:cc:00:00:01", AnonymizeMACAddresses("aa:bb:cc:dd:ee:ff"));
+ EXPECT_EQ("[MAC OUI=aa:bb:cc IFACE=1]",
+ AnonymizeMACAddresses("aa:bb:cc:dd:ee:ff"));
+ EXPECT_EQ("[MAC OUI=aa:bb:cc IFACE=1]",
+ AnonymizeMACAddresses("aa_bb_cc_dd_ee_ff"));
+ EXPECT_EQ("[MAC OUI=aa:bb:cc IFACE=1]",
+ AnonymizeMACAddresses("aa-bb-cc-dd-ee-ff"));
+ EXPECT_EQ("00:00:00:00:00:00", AnonymizeMACAddresses("00:00:00:00:00:00"));
+ EXPECT_EQ("ff:ff:ff:ff:ff:ff", AnonymizeMACAddresses("ff:ff:ff:ff:ff:ff"));
EXPECT_EQ(
- "BSSID: aa:bb:cc:00:00:01 in the middle\n"
- "bb:cc:dd:00:00:02 start of line\n"
- "end of line aa:bb:cc:00:00:01\n"
+ "BSSID: [MAC OUI=aa:bb:cc IFACE=1] in the middle\n"
+ "[MAC OUI=bb:cc:dd IFACE=2] start of line\n"
+ "end of line [MAC OUI=aa:bb:cc IFACE=1]\n"
"no match across lines aa:bb:cc:\n"
"dd:ee:ff two on the same line:\n"
- "x bb:cc:dd:00:00:02 cc:dd:ee:00:00:03 x\n",
+ "x [MAC OUI=bb:cc:dd IFACE=2] [MAC OUI=cc:dd:ee IFACE=3] x\n",
AnonymizeMACAddresses("BSSID: aa:bb:cc:dd:ee:ff in the middle\n"
"bb:cc:dd:ee:ff:00 start of line\n"
"end of line aa:bb:cc:dd:ee:ff\n"
"no match across lines aa:bb:cc:\n"
"dd:ee:ff two on the same line:\n"
"x bb:cc:dd:ee:ff:00 cc:dd:ee:ff:00:11 x\n"));
- EXPECT_EQ("Remember bb:cc:dd:00:00:02?",
+ EXPECT_EQ("Remember [MAC OUI=bb:cc:dd IFACE=2]?",
AnonymizeMACAddresses("Remember bB:Cc:DD:ee:ff:00?"));
}
+TEST_F(AnonymizerToolTest, AnonymizeHashes) {
+ EXPECT_EQ("", AnonymizeHashes(""));
+ EXPECT_EQ("foo\nbar\n", AnonymizeHashes("foo\nbar\n"));
+ // Too short.
+ EXPECT_EQ("11223344556677889900aabbccddee",
+ AnonymizeHashes("11223344556677889900aabbccddee"));
+ // Not the right length.
+ EXPECT_EQ("11223344556677889900aabbccddeeff1122",
+ AnonymizeHashes("11223344556677889900aabbccddeeff1122"));
+ // Too long.
+ EXPECT_EQ(
+ "11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff11",
+ AnonymizeHashes("11223344556677889900aabbccddeeff11223344556677889900aabb"
+ "ccddeeff11"));
+ // Test all 3 valid lengths.
+ EXPECT_EQ("<HASH:aabb 1>",
+ AnonymizeHashes("aabbccddeeff00112233445566778899"));
+ EXPECT_EQ("<HASH:aabb 2>",
+ AnonymizeHashes("aabbccddeeff00112233445566778899aabbccdd"));
+ EXPECT_EQ(
+ "<HASH:9988 3>",
+ AnonymizeHashes(
+ "99887766554433221100ffeeddccbbaaaabbccddeeff00112233445566778899"));
+ // Skip 32 byte hashes that have a at least 3 whitespace chars before it.
+ EXPECT_EQ(" <HASH:aabb 1>",
+ AnonymizeHashes(" aabbccddeeff00112233445566778899"));
+ EXPECT_EQ(" aabbccddeeff00112233445566778899",
+ AnonymizeHashes(" aabbccddeeff00112233445566778899"));
+ // Multiline test.
+ EXPECT_EQ(
+ "Hash value=<HASH:aabb 1>, should be replaced as\n"
+ "well as /<HASH:aabb 1>/ and mixed case of\n"
+ "<HASH:aabb 1> but we don't go across lines\n"
+ "aabbccddeeff\n00112233445566778899 but allow multiple on a line "
+ "<HASH:aabb 4>-"
+ "<HASH:0011 5>\n",
+ AnonymizeHashes(
+ "Hash value=aabbccddeeff00112233445566778899, should be replaced as\n"
+ "well as /aabbccddeeff00112233445566778899/ and mixed case of\n"
+ "AaBbCCddEeFf00112233445566778899 but we don't go across lines\n"
+ "aabbccddeeff\n00112233445566778899 but allow multiple on a line "
+ "aabbccddeeffaabbccddeeffaabbccddeeffaabb-"
+ "00112233445566778899aabbccddeeff\n"));
+}
+
TEST_F(AnonymizerToolTest, AnonymizeCustomPatterns) {
EXPECT_EQ("", AnonymizeCustomPatterns(""));
- EXPECT_EQ("Cell ID: '1'", AnonymizeCustomPatterns("Cell ID: 'A1B2'"));
- EXPECT_EQ("Cell ID: '2'", AnonymizeCustomPatterns("Cell ID: 'C1D2'"));
- EXPECT_EQ("foo Cell ID: '1' bar",
+ EXPECT_EQ("Cell ID: '<CellID: 1>'",
+ AnonymizeCustomPatterns("Cell ID: 'A1B2'"));
+ EXPECT_EQ("Cell ID: '<CellID: 2>'",
+ AnonymizeCustomPatterns("Cell ID: 'C1D2'"));
+ EXPECT_EQ("foo Cell ID: '<CellID: 1>' bar",
AnonymizeCustomPatterns("foo Cell ID: 'A1B2' bar"));
- EXPECT_EQ("foo Location area code: '1' bar",
+ EXPECT_EQ("foo Location area code: '<LocAC: 1>' bar",
AnonymizeCustomPatterns("foo Location area code: 'A1B2' bar"));
- EXPECT_EQ("foo\na SSID='1' b\n'",
+ EXPECT_EQ("foo\na SSID='<SSID: 1>' b\n'",
AnonymizeCustomPatterns("foo\na SSID='Joe's' b\n'"));
- EXPECT_EQ("ssid '2'", AnonymizeCustomPatterns("ssid 'My AP'"));
+ EXPECT_EQ("ssid '<SSID: 2>'", AnonymizeCustomPatterns("ssid 'My AP'"));
EXPECT_EQ("bssid 'aa:bb'", AnonymizeCustomPatterns("bssid 'aa:bb'"));
- EXPECT_EQ("Scan SSID - hexdump(len=6): 1\nfoo",
+ EXPECT_EQ("Scan SSID - hexdump(len=6): <SSIDHex: 1>\nfoo",
AnonymizeCustomPatterns(
"Scan SSID - hexdump(len=6): 47 6f 6f 67 6c 65\nfoo"));
- EXPECT_EQ(
- "a\nb [SSID=1] [SSID=2] [SSID=foo\nbar] b",
- AnonymizeCustomPatterns("a\nb [SSID=foo] [SSID=bar] [SSID=foo\nbar] b"));
+ EXPECT_EQ("a\nb [SSID=<SSID: 3>] [SSID=<SSID: 1>] [SSID=foo\nbar] b",
+ AnonymizeCustomPatterns(
+ "a\nb [SSID=foo] [SSID=Joe's] [SSID=foo\nbar] b"));
- EXPECT_EQ("SerialNumber: 1",
+ EXPECT_EQ("SerialNumber: <Serial: 1>",
AnonymizeCustomPatterns("SerialNumber: 1217D7EF"));
- EXPECT_EQ("serial number: 2",
+ EXPECT_EQ("serial number: <Serial: 2>",
AnonymizeCustomPatterns("serial number: 50C971FEE7F3x010900"));
- EXPECT_EQ("SerialNumber: 3",
+ EXPECT_EQ("SerialNumber: <Serial: 3>",
AnonymizeCustomPatterns("SerialNumber: EVT23-17BA01-004"));
- EXPECT_EQ("serial=4", AnonymizeCustomPatterns("serial=\"1234AA5678\""));
+ EXPECT_EQ("serial=\"<Serial: 4>\"",
+ AnonymizeCustomPatterns("serial=\"1234AA5678\""));
+ EXPECT_EQ("\"serial_number\"=\"<Serial: 1>\"",
+ AnonymizeCustomPatterns("\"serial_number\"=\"1217D7EF\""));
+ EXPECT_EQ("SerialNumber: <Serial: 5>",
+ AnonymizeCustomPatterns("SerialNumber: 5:00:14.0"));
+ EXPECT_EQ("Serial: <Serial: 6>",
+ AnonymizeCustomPatterns("Serial: ABCEFG\x01kjmn-as:342/234\\432"));
+ // Don't overly anonymize serial numbers, we only do this for a specific
+ // formatting case for edid-decode.
+ EXPECT_EQ("Foo serial number 123",
+ AnonymizeCustomPatterns("Foo serial number 123"));
+ EXPECT_EQ("Foo Serial Number <Serial: 7>",
+ AnonymizeCustomPatterns("Foo Serial Number 123"));
- EXPECT_EQ("\"gaia_id\":\"1\"",
+ EXPECT_EQ("\"gaia_id\":\"<GAIA: 1>\"",
AnonymizeCustomPatterns("\"gaia_id\":\"1234567890\""));
- EXPECT_EQ("gaia_id='2'", AnonymizeCustomPatterns("gaia_id='987654321'"));
- EXPECT_EQ("{id: 1, email:",
- AnonymizeCustomPatterns("{id: 123454321, email:"));
+ EXPECT_EQ("gaia_id='<GAIA: 2>'",
+ AnonymizeCustomPatterns("gaia_id='987654321'"));
+ EXPECT_EQ("{id: <GAIA: 1>, email:",
+ AnonymizeCustomPatterns("{id: 1234567890, email:"));
EXPECT_EQ("<email: 1>",
AnonymizeCustomPatterns("foo@bar.com"));
@@ -145,8 +224,9 @@ TEST_F(AnonymizerToolTest, AnonymizeCustomPatterns) {
EXPECT_EQ("<URL: 1>",
AnonymizeCustomPatterns("http://example.com/foo?test=1"));
- EXPECT_EQ("Foo <URL: 2> Bar",
- AnonymizeCustomPatterns("Foo http://192.168.0.1/foo?test=1#123 Bar"));
+ EXPECT_EQ(
+ "Foo <URL: 2> Bar",
+ AnonymizeCustomPatterns("Foo http://192.168.0.1/foo?test=1#123 Bar"));
const char* kURLs[] = {
"http://example.com/foo?test=1",
"http://userid:password@example.com:8080",
@@ -177,38 +257,38 @@ TEST_F(AnonymizerToolTest, AnonymizeCustomPatterns) {
}
TEST_F(AnonymizerToolTest, AnonymizeCustomPatternWithContext) {
- const char kPattern[] = "(\\b(?i)id:? ')(\\d+)(')";
- std::map<std::string, std::string> space;
- EXPECT_EQ("", AnonymizeCustomPatternWithContext("", kPattern, &space));
+ const CustomPatternWithAlias kPattern1 = {"ID", "(\\b(?i)id:? ')(\\d+)(')"};
+ const CustomPatternWithAlias kPattern2 = {"ID", "(\\b(?i)id=')(\\d+)(')"};
+ const CustomPatternWithAlias kPattern3 = {"IDG", "(\\b(?i)idg=')(\\d+)(')"};
+ EXPECT_EQ("", AnonymizeCustomPatternWithContext("", kPattern1));
EXPECT_EQ("foo\nbar\n",
- AnonymizeCustomPatternWithContext("foo\nbar\n", kPattern, &space));
- EXPECT_EQ("id '1'",
- AnonymizeCustomPatternWithContext("id '2345'", kPattern, &space));
- EXPECT_EQ("id '2'",
- AnonymizeCustomPatternWithContext("id '1234'", kPattern, &space));
- EXPECT_EQ("id: '2'",
- AnonymizeCustomPatternWithContext("id: '1234'", kPattern, &space));
- EXPECT_EQ("ID: '1'",
- AnonymizeCustomPatternWithContext("ID: '2345'", kPattern, &space));
- EXPECT_EQ("x1 id '1' 1x id '2'\nid '1'\n",
+ AnonymizeCustomPatternWithContext("foo\nbar\n", kPattern1));
+ EXPECT_EQ("id '<ID: 1>'",
+ AnonymizeCustomPatternWithContext("id '2345'", kPattern1));
+ EXPECT_EQ("id '<ID: 2>'",
+ AnonymizeCustomPatternWithContext("id '1234'", kPattern1));
+ EXPECT_EQ("id: '<ID: 2>'",
+ AnonymizeCustomPatternWithContext("id: '1234'", kPattern1));
+ EXPECT_EQ("ID: '<ID: 1>'",
+ AnonymizeCustomPatternWithContext("ID: '2345'", kPattern1));
+ EXPECT_EQ("x1 id '<ID: 1>' 1x id '<ID: 2>'\nid '<ID: 1>'\n",
AnonymizeCustomPatternWithContext(
- "x1 id '2345' 1x id '1234'\nid '2345'\n", kPattern, &space));
- space.clear();
- EXPECT_EQ("id '1'",
- AnonymizeCustomPatternWithContext("id '1234'", kPattern, &space));
-
- space.clear();
- EXPECT_EQ("x1z",
- AnonymizeCustomPatternWithContext("xyz", "()(y+)()", &space));
+ "x1 id '2345' 1x id '1234'\nid '2345'\n", kPattern1));
+ // Different pattern with same alias should reuse the replacements.
+ EXPECT_EQ("id='<ID: 2>'",
+ AnonymizeCustomPatternWithContext("id='1234'", kPattern2));
+ // Different alias should not reuse replacement from another pattern.
+ EXPECT_EQ("idg='<IDG: 1>'",
+ AnonymizeCustomPatternWithContext("idg='1234'", kPattern3));
+ EXPECT_EQ("x<FOO: 1>z",
+ AnonymizeCustomPatternWithContext("xyz", {"FOO", "()(y+)()"}));
}
TEST_F(AnonymizerToolTest, AnonymizeCustomPatternWithoutContext) {
- CustomPatternWithoutContext kPattern = {"pattern", "(o+)"};
- std::map<std::string, std::string> space;
- EXPECT_EQ("", AnonymizeCustomPatternWithoutContext("", kPattern, &space));
+ CustomPatternWithAlias kPattern = {"pattern", "(o+)"};
+ EXPECT_EQ("", AnonymizeCustomPatternWithoutContext("", kPattern));
EXPECT_EQ("f<pattern: 1>\nf<pattern: 2>z\nf<pattern: 1>l\n",
- AnonymizeCustomPatternWithoutContext("fo\nfooz\nfol\n", kPattern,
- &space));
+ AnonymizeCustomPatternWithoutContext("fo\nfooz\nfol\n", kPattern));
}
TEST_F(AnonymizerToolTest, AnonymizeChunk) {
@@ -216,149 +296,159 @@ TEST_F(AnonymizerToolTest, AnonymizeChunk) {
// of pairs, and then convert that to two strings which become the input and
// output of the anonymizer.
std::pair<std::string, std::string> data[] = {
- {"aaaaaaaa [SSID=123aaaaaa]aaaaa", // SSID.
- "aaaaaaaa [SSID=1]aaaaa"},
- {"aaaaaaaahttp://tets.comaaaaaaa", // URL.
- "aaaaaaaa<URL: 1>"},
- {"aaaaaemail@example.comaaa", // Email address.
- "<email: 1>"},
- {"example@@1234", // No PII, it is not invalid email address.
- "example@@1234"},
- {"255.255.155.2", // IP address.
- "<IPv4: 1>"},
- {"255.255.155.255", // IP address.
- "<IPv4: 2>"},
- {"127.0.0.1", // IPv4 loopback.
- "<127.0.0.0/8: 3>"},
- {"127.255.0.1", // IPv4 loopback.
- "<127.0.0.0/8: 4>"},
- {"0.0.0.0", // Any IPv4.
- "<0.0.0.0/8: 5>"},
- {"0.255.255.255", // Any IPv4.
- "<0.0.0.0/8: 6>"},
- {"10.10.10.100", // IPv4 private class A.
- "<10.0.0.0/8: 7>"},
- {"10.10.10.100", // Intentional duplicate.
- "<10.0.0.0/8: 7>"},
- {"10.10.10.101", // IPv4 private class A.
- "<10.0.0.0/8: 8>"},
- {"10.255.255.255", // IPv4 private class A.
- "<10.0.0.0/8: 9>"},
- {"172.16.0.0", // IPv4 private class B.
- "<172.16.0.0/12: 10>"},
- {"172.31.255.255", // IPv4 private class B.
- "<172.16.0.0/12: 11>"},
- {"172.11.5.5", // IP address.
- "<IPv4: 12>"},
- {"172.111.5.5", // IP address.
- "<IPv4: 13>"},
- {"192.168.0.0", // IPv4 private class C.
- "<192.168.0.0/16: 14>"},
- {"192.168.255.255", // IPv4 private class C.
- "<192.168.0.0/16: 15>"},
- {"192.169.2.120", // IP address.
- "<IPv4: 16>"},
- {"169.254.0.1", // Link local.
- "<169.254.0.0/16: 17>"},
- {"169.200.0.1", // IP address.
- "<IPv4: 18>"},
- {"fe80::", // Link local.
- "<fe80::/10: 1>"},
- {"fe80::ffff", // Link local.
- "<fe80::/10: 2>"},
- {"febf:ffff::ffff", // Link local.
- "<fe80::/10: 3>"},
- {"fecc::1111", // IP address.
- "<IPv6: 4>"},
- {"224.0.0.24", // Multicast.
- "<224.0.0.0/4: 19>"},
- {"240.0.0.0", // IP address.
- "<IPv4: 20>"},
- {"255.255.255.255", // Broadcast.
- "255.255.255.255"},
- {"100.115.92.92", // ChromeOS.
- "100.115.92.92"},
- {"100.115.91.92", // IP address.
- "<IPv4: 23>"},
- {"1.1.1.1", // DNS
- "1.1.1.1"},
- {"8.8.8.8", // DNS
- "8.8.8.8"},
- {"8.8.4.4", // DNS
- "8.8.4.4"},
- {"8.8.8.4", // IP address.
- "<IPv4: 27>"},
- {"255.255.259.255", // Not an IP address.
- "255.255.259.255"},
- {"255.300.255.255", // Not an IP address.
- "255.300.255.255"},
- {"aaaa123.123.45.4aaa", // IP address.
- "aaaa<IPv4: 28>aaa"},
- {"11:11;11::11", // IP address.
- "11:11;<IPv6: 5>"},
- {"11::11", // IP address.
- "<IPv6: 5>"},
- {"11:11:abcdef:0:0:0:0:0", // No PII.
- "11:11:abcdef:0:0:0:0:0"},
- {"::", // Unspecified.
- "::"},
- {"::1", // Local host.
- "::1"},
- {"Instance::Set", // Ignore match, no PII.
- "Instance::Set"},
- {"Instant::ff", // Ignore match, no PII.
- "Instant::ff"},
- {"net::ERR_CONN_TIMEOUT", // Ignore match, no PII.
- "net::ERR_CONN_TIMEOUT"},
- {"ff01::1", // All nodes address (interface local).
- "ff01::1"},
- {"ff01::2", // All routers (interface local).
- "ff01::2"},
- {"ff01::3", // Multicast (interface local).
- "<ff01::/16: 13>"},
- {"ff02::1", // All nodes address (link local).
- "ff02::1"},
- {"ff02::2", // All routers (link local).
- "ff02::2"},
- {"ff02::3", // Multicast (link local).
- "<ff02::/16: 16>"},
- {"ff02::fb", // mDNSv6 (link local).
- "<ff02::/16: 17>"},
- {"ff08::fb", // mDNSv6.
- "<IPv6: 18>"},
- {"ff0f::101", // All NTP servers.
- "<IPv6: 19>"},
- {"::ffff:cb0c:10ea", // IPv4-mapped IPV6 (IP address).
- "<IPv6: 20>"},
- {"::ffff:a0a:a0a", // IPv4-mapped IPV6 (private class A).
- "<M 10.0.0.0/8: 21>"},
- {"::ffff:a0a:a0a", // Intentional duplicate.
- "<M 10.0.0.0/8: 21>"},
- {"::ffff:ac1e:1e1e", // IPv4-mapped IPV6 (private class B).
- "<M 172.16.0.0/12: 22>"},
- {"::ffff:c0a8:640a", // IPv4-mapped IPV6 (private class C).
- "<M 192.168.0.0/16: 23>"},
- {"::ffff:6473:5c01", // IPv4-mapped IPV6 (Chrome).
- "<M 100.115.92.1: 24>"},
- {"64:ff9b::a0a:a0a", // IPv4-translated 6to4 IPV6 (private class A).
- "<T 10.0.0.0/8: 25>"},
- {"64:ff9b::6473:5c01", // IPv4-translated 6to4 IPV6 (Chrome).
- "<T 100.115.92.1: 26>"},
- {"::0101:ffff:c0a8:640a", // IP address.
- "<IPv6: 27>"},
- {"aa:aa:aa:aa:aa:aa", // MAC address (BSSID).
- "aa:aa:aa:00:00:01"},
- {"chrome://resources/foo", // Secure chrome resource, whitelisted.
- "chrome://resources/foo"},
- {"chrome://settings/crisper.js", // Whitelisted settings URLs.
- "chrome://settings/crisper.js"},
- // Whitelisted first party extension.
- {"chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/foobar.js",
- "chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/foobar.js"},
- {"chrome://resources/f?user=bar", // Potentially PII in parameter.
- "<URL: 2>"},
- {"chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/foobar.js?bar=x",
- "<URL: 3>"}, // Potentially PII in parameter.
+ {"aaaaaaaa [SSID=123aaaaaa]aaaaa", // SSID.
+ "aaaaaaaa [SSID=<SSID: 1>]aaaaa"},
+ {"aaaaaaaahttp://tets.comaaaaaaa", // URL.
+ "aaaaaaaa<URL: 1>"},
+ {"aaaaaemail@example.comaaa", // Email address.
+ "<email: 1>"},
+ {"example@@1234", // No PII, it is not invalid email address.
+ "example@@1234"},
+ {"255.255.155.2", // IP address.
+ "<IPv4: 1>"},
+ {"255.255.155.255", // IP address.
+ "<IPv4: 2>"},
+ {"127.0.0.1", // IPv4 loopback.
+ "<127.0.0.0/8: 3>"},
+ {"127.255.0.1", // IPv4 loopback.
+ "<127.0.0.0/8: 4>"},
+ {"0.0.0.0", // Any IPv4.
+ "<0.0.0.0/8: 5>"},
+ {"0.255.255.255", // Any IPv4.
+ "<0.0.0.0/8: 6>"},
+ {"10.10.10.100", // IPv4 private class A.
+ "<10.0.0.0/8: 7>"},
+ {"10.10.10.100", // Intentional duplicate.
+ "<10.0.0.0/8: 7>"},
+ {"10.10.10.101", // IPv4 private class A.
+ "<10.0.0.0/8: 8>"},
+ {"10.255.255.255", // IPv4 private class A.
+ "<10.0.0.0/8: 9>"},
+ {"172.16.0.0", // IPv4 private class B.
+ "<172.16.0.0/12: 10>"},
+ {"172.31.255.255", // IPv4 private class B.
+ "<172.16.0.0/12: 11>"},
+ {"172.11.5.5", // IP address.
+ "<IPv4: 12>"},
+ {"172.111.5.5", // IP address.
+ "<IPv4: 13>"},
+ {"192.168.0.0", // IPv4 private class C.
+ "<192.168.0.0/16: 14>"},
+ {"192.168.255.255", // IPv4 private class C.
+ "<192.168.0.0/16: 15>"},
+ {"192.169.2.120", // IP address.
+ "<IPv4: 16>"},
+ {"169.254.0.1", // Link local.
+ "<169.254.0.0/16: 17>"},
+ {"169.200.0.1", // IP address.
+ "<IPv4: 18>"},
+ {"fe80::", // Link local.
+ "<fe80::/10: 1>"},
+ {"fe80::ffff", // Link local.
+ "<fe80::/10: 2>"},
+ {"febf:ffff::ffff", // Link local.
+ "<fe80::/10: 3>"},
+ {"fecc::1111", // IP address.
+ "<IPv6: 4>"},
+ {"224.0.0.24", // Multicast.
+ "<224.0.0.0/4: 19>"},
+ {"240.0.0.0", // IP address.
+ "<IPv4: 20>"},
+ {"255.255.255.255", // Broadcast.
+ "255.255.255.255"},
+ {"100.115.92.92", // ChromeOS.
+ "100.115.92.92"},
+ {"100.115.91.92", // IP address.
+ "<IPv4: 23>"},
+ {"1.1.1.1", // DNS
+ "1.1.1.1"},
+ {"8.8.8.8", // DNS
+ "8.8.8.8"},
+ {"8.8.4.4", // DNS
+ "8.8.4.4"},
+ {"8.8.8.4", // IP address.
+ "<IPv4: 27>"},
+ {"255.255.259.255", // Not an IP address.
+ "255.255.259.255"},
+ {"255.300.255.255", // Not an IP address.
+ "255.300.255.255"},
+ {"aaaa123.123.45.4aaa", // IP address.
+ "aaaa<IPv4: 28>aaa"},
+ {"11:11;11::11", // IP address.
+ "11:11;<IPv6: 5>"},
+ {"11::11", // IP address.
+ "<IPv6: 5>"},
+ {"11:11:abcdef:0:0:0:0:0", // No PII.
+ "11:11:abcdef:0:0:0:0:0"},
+ {"::", // Unspecified.
+ "::"},
+ {"::1", // Local host.
+ "::1"},
+ {"Instance::Set", // Ignore match, no PII.
+ "Instance::Set"},
+ {"Instant::ff", // Ignore match, no PII.
+ "Instant::ff"},
+ {"net::ERR_CONN_TIMEOUT", // Ignore match, no PII.
+ "net::ERR_CONN_TIMEOUT"},
+ {"ff01::1", // All nodes address (interface local).
+ "ff01::1"},
+ {"ff01::2", // All routers (interface local).
+ "ff01::2"},
+ {"ff01::3", // Multicast (interface local).
+ "<ff01::/16: 13>"},
+ {"ff02::1", // All nodes address (link local).
+ "ff02::1"},
+ {"ff02::2", // All routers (link local).
+ "ff02::2"},
+ {"ff02::3", // Multicast (link local).
+ "<ff02::/16: 16>"},
+ {"ff02::fb", // mDNSv6 (link local).
+ "<ff02::/16: 17>"},
+ {"ff08::fb", // mDNSv6.
+ "<IPv6: 18>"},
+ {"ff0f::101", // All NTP servers.
+ "<IPv6: 19>"},
+ {"::ffff:cb0c:10ea", // IPv4-mapped IPV6 (IP address).
+ "<IPv6: 20>"},
+ {"::ffff:a0a:a0a", // IPv4-mapped IPV6 (private class A).
+ "<M 10.0.0.0/8: 21>"},
+ {"::ffff:a0a:a0a", // Intentional duplicate.
+ "<M 10.0.0.0/8: 21>"},
+ {"::ffff:ac1e:1e1e", // IPv4-mapped IPV6 (private class B).
+ "<M 172.16.0.0/12: 22>"},
+ {"::ffff:c0a8:640a", // IPv4-mapped IPV6 (private class C).
+ "<M 192.168.0.0/16: 23>"},
+ {"::ffff:6473:5c01", // IPv4-mapped IPV6 (Chrome).
+ "<M 100.115.92.1: 24>"},
+ {"64:ff9b::a0a:a0a", // IPv4-translated 6to4 IPV6 (private class A).
+ "<T 10.0.0.0/8: 25>"},
+ {"64:ff9b::6473:5c01", // IPv4-translated 6to4 IPV6 (Chrome).
+ "<T 100.115.92.1: 26>"},
+ {"::0101:ffff:c0a8:640a", // IP address.
+ "<IPv6: 27>"},
+ {"aa:aa:aa:aa:aa:aa", // MAC address (BSSID).
+ "[MAC OUI=aa:aa:aa IFACE=1]"},
+ {"chrome://resources/foo", // Secure chrome resource, whitelisted.
+ "chrome://resources/foo"},
+ {"chrome://settings/crisper.js", // Whitelisted settings URLs.
+ "chrome://settings/crisper.js"},
+ // Whitelisted first party extension.
+ {"chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/foobar.js",
+ "chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/foobar.js"},
+ {"chrome://resources/f?user=bar", // Potentially PII in parameter.
+ "<URL: 2>"},
+ {"chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/foobar.js?bar=x",
+ "<URL: 3>"}, // Potentially PII in parameter.
+ {"/root/27540283740a0897ab7c8de0f809add2bacde78f/foo",
+ "/root/<HASH:2754 1>/foo"}, // Hash string.
+#if defined(OS_CHROMEOS) // We only anonymize Android paths on Chrome OS.
+ // Allowed android storage path.
+ {"112K\t/home/root/deadbeef1234/android-data/data/system_de",
+ "112K\t/home/root/deadbeef1234/android-data/data/system_de"},
+ // Anonymized app-specific storage path.
+ {"8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/de",
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/d_"},
+#endif // defined(OS_CHROMEOS)
};
std::string anon_input;
std::string anon_output;
@@ -369,4 +459,53 @@ TEST_F(AnonymizerToolTest, AnonymizeChunk) {
EXPECT_EQ(anon_output, anonymizer_.Anonymize(anon_input));
}
+#if defined(OS_CHROMEOS) // We only anonymize Android paths on Chrome OS.
+TEST_F(AnonymizerToolTest, AnonymizeAndroidAppStoragePaths) {
+ EXPECT_EQ("", AnonymizeAndroidAppStoragePaths(""));
+ EXPECT_EQ("foo\nbar\n", AnonymizeAndroidAppStoragePaths("foo\nbar\n"));
+
+ constexpr char kDuOutput[] =
+ "112K\t/home/root/deadbeef1234/android-data/data/system_de\n"
+ // /data/data will be modified by the anonymizer.
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pack.age1/a\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pack.age1/bc\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/data/pack.age1\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/de\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/de/"
+ "\xe3\x81\x82\n"
+ "8.1K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/de/"
+ "\xe3\x81\x82\xe3\x81\x83\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/ef\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2\n"
+ // /data/app won't.
+ "8.0K\t/home/root/deadbeef1234/android-data/data/app/pack.age1/a\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/app/pack.age1/bc\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/app/pack.age1\n"
+ // /data/user_de will.
+ "8.0K\t/home/root/deadbeef1234/android-data/data/user_de/0/pack.age1/a\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/user_de/0/pack.age1/bc\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/user_de/0/pack.age1\n"
+ "78M\t/home/root/deadbeef1234/android-data/data/data\n";
+ constexpr char kDuOutputRedacted[] =
+ "112K\t/home/root/deadbeef1234/android-data/data/system_de\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pack.age1/a\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pack.age1/b_\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/data/pack.age1\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/d_\n"
+ // The non-ASCII directory names will become '*_'.
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/d_/*_\n"
+ "8.1K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/d_/*_\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2/e_\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/data/pa.ckage2\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/app/pack.age1/a\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/app/pack.age1/bc\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/app/pack.age1\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/user_de/0/pack.age1/a\n"
+ "8.0K\t/home/root/deadbeef1234/android-data/data/user_de/0/pack.age1/b_\n"
+ "24K\t/home/root/deadbeef1234/android-data/data/user_de/0/pack.age1\n"
+ "78M\t/home/root/deadbeef1234/android-data/data/data\n";
+ EXPECT_EQ(kDuOutputRedacted, AnonymizeAndroidAppStoragePaths(kDuOutput));
+}
+#endif // defined(OS_CHROMEOS)
+
} // namespace feedback
diff --git a/chromium/components/feedback/feedback_data.cc b/chromium/components/feedback/feedback_data.cc
index 91cc10ebc6d..0264e5a69fe 100644
--- a/chromium/components/feedback/feedback_data.cc
+++ b/chromium/components/feedback/feedback_data.cc
@@ -69,8 +69,9 @@ void FeedbackData::CompressSystemInfo() {
}
++pending_op_count_;
- base::PostTaskWithTraitsAndReply(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReply(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&FeedbackData::CompressLogs, this),
base::BindOnce(&FeedbackData::OnCompressComplete, this));
}
@@ -79,8 +80,9 @@ void FeedbackData::SetAndCompressHistograms(std::string histograms) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
++pending_op_count_;
- base::PostTaskWithTraitsAndReply(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReply(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&FeedbackData::CompressFile, this,
base::FilePath(kHistogramsFilename),
kHistogramsAttachmentName, std::move(histograms)),
@@ -95,8 +97,9 @@ void FeedbackData::AttachAndCompressFileData(std::string attached_filedata) {
++pending_op_count_;
base::FilePath attached_file =
base::FilePath::FromUTF8Unsafe(attached_filename_);
- base::PostTaskWithTraitsAndReply(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReply(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&FeedbackData::CompressFile, this, attached_file,
std::string(), std::move(attached_filedata)),
base::BindOnce(&FeedbackData::OnCompressComplete, this));
diff --git a/chromium/components/feedback/feedback_data_unittest.cc b/chromium/components/feedback/feedback_data_unittest.cc
index b93bc26bc61..e588bfbb6da 100644
--- a/chromium/components/feedback/feedback_data_unittest.cc
+++ b/chromium/components/feedback/feedback_data_unittest.cc
@@ -13,8 +13,8 @@
#include "components/feedback/feedback_uploader.h"
#include "components/feedback/feedback_uploader_factory.h"
#include "components/prefs/testing_pref_service.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -85,7 +85,7 @@ class FeedbackDataTest : public testing::Test {
base::Closure quit_closure_;
std::unique_ptr<base::RunLoop> run_loop_;
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
content::TestBrowserContext context_;
diff --git a/chromium/components/feedback/feedback_report.cc b/chromium/components/feedback/feedback_report.cc
index c1f362fe7f7..bcac13be667 100644
--- a/chromium/components/feedback/feedback_report.cc
+++ b/chromium/components/feedback/feedback_report.cc
@@ -12,6 +12,7 @@
#include "base/guid.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
namespace feedback {
@@ -57,6 +58,12 @@ FeedbackReport::FeedbackReport(
base::WrapRefCounted<FeedbackReport>(this)));
}
+FeedbackReport::FeedbackReport(
+ base::FilePath path,
+ std::unique_ptr<std::string> data,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : file_(path), data_(std::move(data)), reports_task_runner_(task_runner) {}
+
// static
const char FeedbackReport::kCrashReportIdsKey[] = "crash_report_ids";
@@ -77,9 +84,11 @@ void FeedbackReport::LoadReportsAndQueue(const base::FilePath& user_dir,
!name.empty();
name = enumerator.Next()) {
auto data = std::make_unique<std::string>();
- if (ReadFileToString(name, data.get()))
- callback.Run(std::move(data));
- base::DeleteFile(name, false);
+ if (ReadFileToString(name, data.get())) {
+ callback.Run(base::MakeRefCounted<FeedbackReport>(
+ std::move(name), std::move(data),
+ base::ThreadTaskRunnerHandle::Get()));
+ }
}
}
diff --git a/chromium/components/feedback/feedback_report.h b/chromium/components/feedback/feedback_report.h
index 413e03ba65e..a71e32d91d7 100644
--- a/chromium/components/feedback/feedback_report.h
+++ b/chromium/components/feedback/feedback_report.h
@@ -11,29 +11,35 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
-namespace base {
-class SequencedTaskRunner;
-}
-
namespace feedback {
+class FeedbackReport;
+
// Repeating since for every feedback report file on disk, the callback to
// queue it in the uploader needs to be invoked.
using QueueCallback =
- base::RepeatingCallback<void(std::unique_ptr<std::string>)>;
+ base::RepeatingCallback<void(scoped_refptr<FeedbackReport>)>;
// This class holds a feedback report. Once a report is created, a disk backup
// for it is created automatically. This backup needs to explicitly be
// deleted by calling DeleteReportOnDisk.
class FeedbackReport : public base::RefCountedThreadSafe<FeedbackReport> {
public:
+ // Creates a new feedback report with the contents of |data|.
FeedbackReport(const base::FilePath& path,
const base::Time& upload_at,
std::unique_ptr<std::string> data,
scoped_refptr<base::SequencedTaskRunner> task_runner);
+ // Creates a feedback report from an existing one on-disk at |path|, the
+ // |upload_at| time should be set after construction.
+ FeedbackReport(base::FilePath path,
+ std::unique_ptr<std::string> data,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+
// The ID of the product specific data for the crash report IDs as stored by
// the feedback server.
static const char kCrashReportIdsKey[];
@@ -54,6 +60,9 @@ class FeedbackReport : public base::RefCountedThreadSafe<FeedbackReport> {
const base::Time& upload_at() const { return upload_at_; }
void set_upload_at(const base::Time& time) { upload_at_ = time; }
const std::string& data() const { return *data_; }
+ scoped_refptr<base::SequencedTaskRunner> reports_task_runner() const {
+ return reports_task_runner_;
+ }
private:
friend class base::RefCountedThreadSafe<FeedbackReport>;
diff --git a/chromium/components/feedback/feedback_uploader.cc b/chromium/components/feedback/feedback_uploader.cc
index 43ac0af9cb2..80e737ead7f 100644
--- a/chromium/components/feedback/feedback_uploader.cc
+++ b/chromium/components/feedback/feedback_uploader.cc
@@ -82,7 +82,17 @@ void FeedbackUploader::SetMinimumRetryDelayForTesting(base::TimeDelta delay) {
}
void FeedbackUploader::QueueReport(std::unique_ptr<std::string> data) {
- QueueReportWithDelay(std::move(data), base::TimeDelta());
+ reports_queue_.emplace(base::MakeRefCounted<FeedbackReport>(
+ feedback_reports_path_, base::Time::Now(), std::move(data),
+ task_runner_));
+ UpdateUploadTimer();
+}
+
+void FeedbackUploader::RequeueReport(scoped_refptr<FeedbackReport> report) {
+ DCHECK_EQ(task_runner_, report->reports_task_runner());
+ report->set_upload_at(base::Time::Now());
+ reports_queue_.emplace(std::move(report));
+ UpdateUploadTimer();
}
void FeedbackUploader::StartDispatchingReport() {
@@ -159,7 +169,7 @@ void FeedbackUploader::DispatchReport() {
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = feedback_post_url_;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
// Tell feedback server about the variation state of this install.
@@ -249,12 +259,4 @@ void FeedbackUploader::UpdateUploadTimer() {
}
}
-void FeedbackUploader::QueueReportWithDelay(std::unique_ptr<std::string> data,
- base::TimeDelta delay) {
- reports_queue_.emplace(base::MakeRefCounted<FeedbackReport>(
- feedback_reports_path_, base::Time::Now() + delay, std::move(data),
- task_runner_));
- UpdateUploadTimer();
-}
-
} // namespace feedback
diff --git a/chromium/components/feedback/feedback_uploader.h b/chromium/components/feedback/feedback_uploader.h
index 816fa256d9e..9dec3f6fb56 100644
--- a/chromium/components/feedback/feedback_uploader.h
+++ b/chromium/components/feedback/feedback_uploader.h
@@ -50,6 +50,9 @@ class FeedbackUploader : public KeyedService,
// Queues a report for uploading.
void QueueReport(std::unique_ptr<std::string> data);
+ // Re-queues an existing report from disk for uploading.
+ void RequeueReport(scoped_refptr<FeedbackReport> report);
+
bool QueueEmpty() const { return reports_queue_.empty(); }
content::BrowserContext* context() { return context_; }
@@ -113,9 +116,6 @@ class FeedbackUploader : public KeyedService,
// Update our timer for uploading the next report.
void UpdateUploadTimer();
- void QueueReportWithDelay(std::unique_ptr<std::string> data,
- base::TimeDelta delay);
-
// URLLoaderFactory used for network requests.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
diff --git a/chromium/components/feedback/feedback_uploader_dispatch_unittest.cc b/chromium/components/feedback/feedback_uploader_dispatch_unittest.cc
index ab1a8b0ed33..8830c7c44e8 100644
--- a/chromium/components/feedback/feedback_uploader_dispatch_unittest.cc
+++ b/chromium/components/feedback/feedback_uploader_dispatch_unittest.cc
@@ -16,8 +16,8 @@
#include "components/variations/net/variations_http_headers.h"
#include "components/variations/variations_associated_data.h"
#include "components/variations/variations_http_header_provider.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -43,7 +43,7 @@ void QueueReport(FeedbackUploader* uploader, const std::string& report_data) {
class FeedbackUploaderDispatchTest : public ::testing::Test {
protected:
FeedbackUploaderDispatchTest()
- : browser_thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
shared_url_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {}
@@ -75,7 +75,7 @@ class FeedbackUploaderDispatchTest : public ::testing::Test {
content::BrowserContext* context() { return &context_; }
private:
- content::TestBrowserThreadBundle browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext context_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
diff --git a/chromium/components/feedback/feedback_uploader_factory.cc b/chromium/components/feedback/feedback_uploader_factory.cc
index 187880744b1..b8f034b00e4 100644
--- a/chromium/components/feedback/feedback_uploader_factory.cc
+++ b/chromium/components/feedback/feedback_uploader_factory.cc
@@ -32,8 +32,8 @@ scoped_refptr<base::SingleThreadTaskRunner>
FeedbackUploaderFactory::CreateUploaderTaskRunner() {
// Uses a BLOCK_SHUTDOWN file task runner because we really don't want to
// lose reports or corrupt their files.
- return base::CreateSingleThreadTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ return base::CreateSingleThreadTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
}
diff --git a/chromium/components/feedback/feedback_uploader_unittest.cc b/chromium/components/feedback/feedback_uploader_unittest.cc
index 8fc865f0841..659f674edbc 100644
--- a/chromium/components/feedback/feedback_uploader_unittest.cc
+++ b/chromium/components/feedback/feedback_uploader_unittest.cc
@@ -16,8 +16,8 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/feedback/feedback_report.h"
#include "components/feedback/feedback_uploader_factory.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -59,7 +59,8 @@ class MockFeedbackUploader : public FeedbackUploader {
base::BindOnce(
&FeedbackReport::LoadReportsAndQueue, feedback_reports_path(),
base::BindRepeating(&MockFeedbackUploader::QueueSingleReport,
- base::SequencedTaskRunnerHandle::Get(), this)));
+ base::SequencedTaskRunnerHandle::Get(),
+ AsWeakPtr())));
}
const std::map<std::string, unsigned int>& dispatched_reports() const {
@@ -71,11 +72,11 @@ class MockFeedbackUploader : public FeedbackUploader {
private:
static void QueueSingleReport(
scoped_refptr<base::SequencedTaskRunner> main_task_runner,
- MockFeedbackUploader* uploader,
- std::unique_ptr<std::string> data) {
+ base::WeakPtr<FeedbackUploader> uploader,
+ scoped_refptr<FeedbackReport> report) {
main_task_runner->PostTask(
- FROM_HERE, base::BindOnce(&MockFeedbackUploader::QueueReport,
- uploader->AsWeakPtr(), std::move(data)));
+ FROM_HERE, base::BindOnce(&MockFeedbackUploader::RequeueReport,
+ std::move(uploader), std::move(report)));
}
// FeedbackUploaderChrome:
@@ -139,7 +140,7 @@ class FeedbackUploaderTest : public testing::Test {
private:
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext context_;
std::unique_ptr<MockFeedbackUploader> uploader_;
diff --git a/chromium/components/feedback/system_logs/system_logs_fetcher.cc b/chromium/components/feedback/system_logs/system_logs_fetcher.cc
index 62ed817c0dc..6b061a58842 100644
--- a/chromium/components/feedback/system_logs/system_logs_fetcher.cc
+++ b/chromium/components/feedback/system_logs/system_logs_fetcher.cc
@@ -51,9 +51,10 @@ SystemLogsFetcher::SystemLogsFetcher(
const char* const first_party_extension_ids[])
: response_(std::make_unique<SystemLogsResponse>()),
num_pending_requests_(0),
- task_runner_for_anonymizer_(base::CreateSequencedTaskRunnerWithTraits(
- {// User visible because this is called when the user is looking at
- // the send feedback dialog, watching a spinner.
+ task_runner_for_anonymizer_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), // User visible because this is called when the
+ // user is looking at the send feedback dialog,
+ // watching a spinner.
base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})) {
if (scrub_data)
diff --git a/chromium/components/flags_strings.grdp b/chromium/components/flags_strings.grdp
new file mode 100644
index 00000000000..d79dbc07f40
--- /dev/null
+++ b/chromium/components/flags_strings.grdp
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <!-- about:flags
+ Not translated. See discussion at: https://crbug.com/587272
+ New entries here should also be added for About:flags/enterprise below -->
+ <message name="IDS_FLAGS_UI_SEARCH_PLACEHOLDER" translateable="false" desc="The placeholder for the search box on the about:flags page.">
+ Search flags
+ </message>
+ <message name="IDS_FLAGS_UI_TITLE" translateable="false" desc="The page title for the about:flags page.">
+ Experiments
+ </message>
+ <message name="IDS_FLAGS_UI_PAGE_RESET" translateable="false" desc="Label for button that resets the flags to their default value.">
+ Reset all to default
+ </message>
+ <message name="IDS_FLAGS_UI_PAGE_WARNING" desc="A warning stating that the features of the page are experimental.">
+ Warning: Experimental features ahead!
+ </message>
+ <message name="IDS_FLAGS_UI_PAGE_WARNING_EXPLANATION" desc="A warning stating what the user gets exposed to by enabling one the features.">
+ By enabling these features, you could lose browser data or
+ compromise your security or privacy. Enabled features apply to all
+ users of this browser.
+ </message>
+ <message name="IDS_FLAGS_UI_OWNER_WARNING" translateable="false" desc="A warning stating what system-wide features can only be set by the owner.">
+ Flags that apply system-wide can only be set by the owner: <ph name="OWNER_EMAIL">$1<ex>owner@email.com</ex></ph>
+ </message>
+ <message name="IDS_FLAGS_UI_AVAILABLE_FEATURE" translateable="false" desc="Label for button that shows available features.">
+ Available
+ </message>
+ <message name="IDS_FLAGS_UI_UNAVAILABLE_FEATURE" translateable="false" desc="Label for button that shows unavailable features.">
+ Unavailable
+ </message>
+ <message name="IDS_FLAGS_UI_ENABLED_FEATURE" translateable="false" desc="This is the 'Enabled' option, not the label for the menu.">
+ Enabled
+ </message>
+ <message name="IDS_FLAGS_UI_DISABLED_FEATURE" translateable="false" desc="This is the 'Disabled' option, not the label for the menu.">
+ Disabled
+ </message>
+ <message name="IDS_FLAGS_UI_NO_RESULTS" translateable="false" desc="Message stating that there are no experiments matching the search criterias.">
+ No matching experiments
+ </message>
+ <message name="IDS_FLAGS_UI_NOT_AVAILABLE_ON_PLATFORM" translateable="false" desc="Message stating that an experiment is not available for the current platform.">
+ Not available on your platform.
+ </message>
+ <if expr="chromeos">
+ <message name="IDS_FLAGS_UI_RELAUNCH" translateable="false" desc="Label for button that restarts chrome os.">
+ Restart
+ </message>
+ </if>
+ <if expr="not chromeos">
+ <message name="IDS_FLAGS_UI_RELAUNCH" translateable="false" desc="Label for button that relaunches chrome.">
+ Relaunch
+ </message>
+ </if>
+ <message name="IDS_FLAGS_UI_CLEAR_SEARCH" translateable="false" desc="Tooltip for icon button that clears the searchbar on the chrome://flags page.">
+ Clear search
+ </message>
+ <message name="IDS_FLAGS_UI_RESET_ACKNOWLEDGED" translateable="false" desc="Screen reader text stating that the reset action was acknowledged.">
+ Reset acknowledged.
+ </message>
+ <message name="IDS_FLAGS_UI_EXPERIMENT_ENABLED" translateable="false" desc="Screen reader text stating that an experiment is enabled.">
+ Experiment enabled
+ </message>
+ <!-- about:flags/deprecated
+ New entries here should also be added for about:flags above -->
+ <message name="IDS_DEPRECATED_FEATURES_PAGE_RESET" desc="Label for button that resets the features to their default value.">
+ Reset all to default
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_OWNER_WARNING" desc="A warning stating what system-wide features can only be set by the owner.">
+ Features that apply system-wide can only be set by the owner: <ph name="OWNER_EMAIL">$1<ex>owner@email.com</ex></ph>
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_AVAILABLE_FEATURE" desc="Label for button that shows available features.">
+ Available
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_UNAVAILABLE_FEATURE" desc="Label for button that shows unavailable features.">
+ Unavailable
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_ENABLED_FEATURE" desc="This is the 'Enabled' option, not the label for the menu.">
+ Enabled
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_DISABLED_FEATURE" desc="This is the 'Disabled' option, not the label for the menu">
+ Disabled
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_NOT_AVAILABLE_ON_PLATFORM" desc="Message stating that an experiment is not available for the current platform.">
+ Not available on your platform.
+ </message>
+ <if expr="chromeos">
+ <message name="IDS_DEPRECATED_FEATURES_RELAUNCH" desc="Label for button that restarts chrome os.">
+ Restart
+ </message>
+ </if>
+ <if expr="not chromeos">
+ <message name="IDS_DEPRECATED_FEATURES_RELAUNCH" desc="Label for button that relaunches chrome.">
+ Relaunch
+ </message>
+ </if>
+ <message name="IDS_DEPRECATED_FEATURES_SEARCH_PLACEHOLDER" desc="The placeholder for the search box on the about:enterprise-settings page.">
+ Search features
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_TITLE" desc="The page title for the about:enterprise-settings page.">
+ Deprecated Features
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_PAGE_WARNING" desc="A warning stating that the features of the page are experimental.">
+ Warning: Deprecated features ahead!
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_PAGE_WARNING_EXPLANATION" desc="Warning to users that features are deprecated. Shown prominently at the top of the page.">
+ By enabling these features, you will be using deprecated features
+ that will disappear in future versions.
+ </message>
+ <message name="IDS_DEPRECATED_FEATURES_NO_RESULTS" desc="Message shown when searching and no results were found.">
+ No matching features
+ </message>
+ <message name="IDS_DEPRECATED_UI_CLEAR_SEARCH" desc="Tooltip for icon button that clears the searchbar on the chrome://flags/enterprise page.">
+ Clear search
+ </message>
+ <message name="IDS_DEPRECATED_UI_RESET_ACKNOWLEDGED" desc="Screen reader text stating that the reset action was acknowledged.">
+ Reset acknowledged.
+ </message>
+ <message name="IDS_DEPRECATED_UI_EXPERIMENT_ENABLED" desc="Screen reader text stating that an experiment is enabled.">
+ Experiment enabled
+ </message>
+</grit-part>
diff --git a/chromium/components/flags_ui/feature_entry.h b/chromium/components/flags_ui/feature_entry.h
index b93f1fb3b4a..3e0cfc383bd 100644
--- a/chromium/components/flags_ui/feature_entry.h
+++ b/chromium/components/flags_ui/feature_entry.h
@@ -72,6 +72,8 @@ struct FeatureEntry {
// passed from the server in a trial config). When set to Enabled, the
// feature is overriden to be enabled and empty set of parameters is used
// boiling down to the default behavior in the code.
+ // TODO(crbug.com/805766): The resulting chrome://flags entries will not work on Chrome OS
+ // devices (but will work in the CrOS-emulated build on Linux).
FEATURE_WITH_PARAMS_VALUE,
// Corresponds to a command line switch where the value is treatead as a
diff --git a/chromium/components/flags_ui/flags_state.cc b/chromium/components/flags_ui/flags_state.cc
index dfde63a2e4a..564df9e8036 100644
--- a/chromium/components/flags_ui/flags_state.cc
+++ b/chromium/components/flags_ui/flags_state.cc
@@ -672,6 +672,7 @@ void FlagsState::GetFlagFeatureEntries(
supported = true;
}
#endif
+
if (supported)
supported_entries->Append(std::move(data));
else
diff --git a/chromium/components/flags_ui/flags_state.h b/chromium/components/flags_ui/flags_state.h
index c3997ff0b5a..1a8db5fcb0d 100644
--- a/chromium/components/flags_ui/flags_state.h
+++ b/chromium/components/flags_ui/flags_state.h
@@ -14,10 +14,10 @@
#include "base/callback_forward.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/macros.h"
namespace base {
-class FeatureList;
class ListValue;
}
@@ -34,7 +34,7 @@ struct FeatureEntry;
class FlagsStorage;
struct SwitchEntry;
-// Enumeration of OSs.
+// Enumeration of flag filters.
enum {
kOsMac = 1 << 0,
kOsWin = 1 << 1,
@@ -43,6 +43,7 @@ enum {
kOsAndroid = 1 << 4,
kOsCrOSOwnerOnly = 1 << 5,
kOsIos = 1 << 6,
+ kDeprecated = 1 << 7,
};
// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
diff --git a/chromium/components/flags_ui/flags_ui_constants.cc b/chromium/components/flags_ui/flags_ui_constants.cc
index a3e2b1c9313..d4d3f3227ac 100644
--- a/chromium/components/flags_ui/flags_ui_constants.cc
+++ b/chromium/components/flags_ui/flags_ui_constants.cc
@@ -20,7 +20,6 @@ const char kRestartBrowser[] = "restartBrowser";
const char kFlagsRestartButton[] = "flagsRestartButton";
const char kFlagsRestartNotice[] = "flagsRestartNotice";
const char kNeedsRestart[] = "needsRestart";
-const char kOwnerEmail[] = "ownerEmail";
const char kReturnExperimentalFeatures[] = "returnExperimentalFeatures";
const char kShowBetaChannelPromotion[] = "showBetaChannelPromotion";
const char kShowDevChannelPromotion[] = "showDevChannelPromotion";
diff --git a/chromium/components/flags_ui/flags_ui_constants.h b/chromium/components/flags_ui/flags_ui_constants.h
index 5a3300ae68b..859e5e5af0b 100644
--- a/chromium/components/flags_ui/flags_ui_constants.h
+++ b/chromium/components/flags_ui/flags_ui_constants.h
@@ -24,7 +24,6 @@ extern const char kRestartBrowser[];
extern const char kFlagsRestartButton[];
extern const char kFlagsRestartNotice[];
extern const char kNeedsRestart[];
-extern const char kOwnerEmail[];
extern const char kReturnExperimentalFeatures[];
extern const char kShowBetaChannelPromotion[];
extern const char kShowDevChannelPromotion[];
diff --git a/chromium/components/flags_ui/resources/flags.css b/chromium/components/flags_ui/resources/flags.css
index 98d2eeb8cdb..58482c950cd 100644
--- a/chromium/components/flags_ui/resources/flags.css
+++ b/chromium/components/flags_ui/resources/flags.css
@@ -229,6 +229,12 @@ button {
text-transform: uppercase;
}
+.screen-reader-only {
+ clip: rect(0,0,0,0);
+ display: inline-block;
+ position: fixed;
+}
+
#promos {
color: var(--secondary-color);
font-size: .875rem;
diff --git a/chromium/components/flags_ui/resources/flags.html b/chromium/components/flags_ui/resources/flags.html
index 4777e01c36a..82295b2520b 100644
--- a/chromium/components/flags_ui/resources/flags.html
+++ b/chromium/components/flags_ui/resources/flags.html
@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
</if>
-<title>Flags</title>
+<title>$i18n{title}</title>
<link rel="stylesheet" href="flags.css">
@@ -26,41 +26,38 @@
<div class="flex-container">
<div class="flex">
<div class="search-container">
- <input type="text" id="search" placeholder="Search flags" tabindex="1"
+ <input type="text" id="search" placeholder="$i18n{search-placeholder}" tabindex="1"
autocomplete="off" spellcheck="false">
- <input type="button" class="clear-search" title="Clear search"
+ <input type="button" class="clear-search" title="$i18n{clear-search}"
tabindex="2">
</div>
</div>
<div class="flex">
<button id="experiment-reset-all" type="button" tabindex="3">
- Reset all to default
+ $i18n{reset}
</button>
+ <div class="screen-reader-only" id="reset-all-success-message" role="status" aria-disabled="true">
+ $i18n{reset-acknowledged}
+ </div>
</div>
</div>
</div>
<div id="body-container" style="visibility:hidden">
<div id="flagsTemplate">
<div class="flex-container">
- <div class="flex"><h1 class="section-header-title">Experiments</h1></div>
+ <div class="flex"><h1 class="section-header-title">$i18n{title}</h1></div>
<span id="version" class="flex">$i18n{version}</span>
</div>
<div class="blurb-container">
- <span class="blurb-warning">
- Warning: Experimental features ahead!
- </span>
- <span>
- By enabling these features, you could lose browser data or
- compromise your security or privacy. Enabled features apply to all
- users of this browser.
- </span>
+ <span class="blurb-warning">$i18n{page-warning}</span>
+ <span>$i18n{page-warning-explanation}</span>
<if expr="chromeos">
- <p id="owner-warning">
- <span>Flags that apply system-wide can only be set by the owner: $i18n{ownerEmail}</span>
- </p>
+ <p id="owner-warning">$i18n{owner-warning}</p>
</if>
</div>
<p id="promos" hidden>
+ <!-- Those strings are not localized because they only appear in
+ chrome://flags, which is not localized. -->
<span id="channel-promo-beta" hidden>
Interested in cool new Chrome features? Try our
<a href="https://chrome.com/beta">beta channel</a>.
@@ -75,7 +72,7 @@
<a href="#tab-content-available" id="tab-available" class="tab" role="tab"
aria-selected="true"
aria-controls="panel1"
- tabindex="4">Available</a>
+ tabindex="4">$i18n{available}</a>
<div id="tab-content-available" class="tab-content"
role="tabpanel" aria-labelledby="tab-available" aria-hidden="false">
</div>
@@ -89,7 +86,7 @@
: 'experiment-switched flex-container'">
<div class="flex">
<h3 class="experiment-name" jscontent="name"
- jsvalues="title: is_default ? '' : 'Experiment enabled';
+ jsvalues="title: is_default ? '' : $i18n{experiment-enabled};
id:internal_name + '_name'"></h3>
<p>
<span jsvalues=".innerHTML:description"></span> –
@@ -120,9 +117,9 @@
jsvalues=".internal_name:internal_name;
aria-labelledby:internal_name + '_name'">
<option jsvalues=".selected:!enabled; data-default: enabled ? 1 : 0"
- value="disabled">Disabled</option>
+ value="disabled">$i18n{disabled}</option>
<option jsvalues=".selected:enabled; data-default: !enabled ? 1 : 0"
- value="enabled">Enabled</option>
+ value="enabled">$i18n{enabled}</option>
</select>
</div>
</div>
@@ -136,7 +133,7 @@
: 'experiment-switched flex-container'">
<div class="flex">
<h3 class="experiment-name" jscontent="name"
- jsvalues="title: is_default ? '' : 'Experiment enabled';
+ jsvalues="title: is_default ? '' : $i18n{experiment-enabled};
id:internal_name + '_name'"></h3>
<p>
<span jsvalues=".innerHTML:description"></span> –
@@ -168,14 +165,14 @@
jsvalues=".internal_name:internal_name;
aria-labelledby:internal_name + '_name'">
<option jsvalues=".selected:!enabled; data-default:!enabled ? 1 : 0"
- value="disabled">Disabled</option>
+ value="disabled">$i18n{disabled}</option>
<option jsvalues=".selected:enabled; data-default: enabled ? 1 : 0"
- value="enabled">Enabled</option>
+ value="enabled">$i18n{enabled}</option>
</select>
</div>
</div>
</div>
- <div class="no-match hidden" role="alert">No matching experiments</div>
+ <div class="no-match hidden" role="alert">$i18n{no-results}</div>
</div>
</li>
<!-- Unsupported experiments are not shown on iOS -->
@@ -183,7 +180,7 @@
<li>
<a href="#tab-content-unavailable" id="tab-unavailable" class="tab" role="tab"
aria-selected="false" aria-controls="panel2"
- tabindex="5">Unavailable</a>
+ tabindex="5">$i18n{unavailable}</a>
<div id="tab-content-unavailable" class="tab-content"
role="tabpanel" aria-labelledby="tab-unavailable" aria-hidden="false">
<div class="experiment"
@@ -194,7 +191,7 @@
: 'experiment-switched flex-container'">
<div class="flex">
<h3 class="experiment-name"
- jscontent="name">Name</h3>
+ jscontent="name"></h3>
<p>
<span jsvalues=".innerHTML:description"></span>
<span class="platforms" jscontent="supported_platforms.join(', ')"></span>
@@ -203,11 +200,11 @@
jsvalues="href: '#' + internal_name"
jscontent="'#' + internal_name" tabindex="8"></a>
</div>
- <div class="flex experiment-actions">Not available on your platform.</div>
+ <div class="flex experiment-actions">$i18n{not-available-platform}</div>
</div>
</div>
<div class="no-match hidden" role="alert">
- No matching experiments
+ $i18n{no-results}
</div>
</div>
</li>
@@ -219,12 +216,7 @@
<div class="flex">
<if expr="not is_ios">
<button id="experiment-restart-button" class="primary" tabindex="9">
-<if expr="not chromeos">
- Relaunch Now
-</if>
-<if expr="chromeos">
- Restart Now
-</if>
+ $i18n{relaunch}
</button>
</if>
</div>
diff --git a/chromium/components/flags_ui/resources/flags.js b/chromium/components/flags_ui/resources/flags.js
index e44879ff495..b6e491cbab3 100644
--- a/chromium/components/flags_ui/resources/flags.js
+++ b/chromium/components/flags_ui/resources/flags.js
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+var lastChanged = null;
+var lastFocused = null;
+var restartButton = $('experiment-restart-button');
+
/**
* This variable structure is here to document the structure that the template
* expects to correctly populate the page.
@@ -41,8 +45,10 @@ function renderTemplate(experimentalFeaturesData) {
for (var i = 0; i < elements.length; ++i) {
elements[i].onchange = function() {
handleSelectExperimentalFeatureChoice(this, this.selectedIndex);
+ lastChanged = this;
return false;
};
+ registerFocusEvents(elements[i]);
}
elements = document.getElementsByClassName('experiment-enable-disable');
@@ -50,8 +56,10 @@ function renderTemplate(experimentalFeaturesData) {
elements[i].onchange = function() {
handleEnableExperimentalFeature(this,
this.options[this.selectedIndex].value == 'enabled');
+ lastChanged = this;
return false;
};
+ registerFocusEvents(elements[i]);
}
elements = document.getElementsByClassName('experiment-origin-list-value');
@@ -62,10 +70,9 @@ function renderTemplate(experimentalFeaturesData) {
};
}
- var element = $('experiment-restart-button');
- assert(element || cr.isIOS);
- if (element) {
- element.onclick = restartBrowser;
+ assert(restartButton || cr.isIOS);
+ if (restartButton) {
+ restartButton.onclick = restartBrowser;
}
// Tab panel selection.
@@ -99,6 +106,25 @@ function renderTemplate(experimentalFeaturesData) {
}
/**
+ * Add events to an element in order to keep track of the last focused element.
+ * Focus restart button if a previous focus target has been set and tab key
+ * pressed.
+ * @param {Element} el Element to bind events to.
+ */
+function registerFocusEvents(el) {
+ el.addEventListener('keydown', function(e) {
+ if (lastChanged && e.key == 'Tab' && !e.shiftKey) {
+ lastFocused = lastChanged;
+ e.preventDefault();
+ restartButton.focus();
+ }
+ });
+ el.addEventListener('blur', function() {
+ lastChanged = null;
+ });
+}
+
+/**
* Highlight an element associated with the page's location's hash. We need to
* fake fragment navigation with '.scrollIntoView()', since the fragment IDs
* don't actually exist until after the template code runs; normal navigation
@@ -143,6 +169,9 @@ function restartBrowser() {
/** Reset all flags to their default values and refresh the UI. */
function resetAllFlags() {
chrome.send('resetAllFlags');
+ $('reset-all-success-message').setAttribute("aria-disabled", "false");
+ // Updating the message in order for it to get announced by screen readers.
+ $('reset-all-success-message').innerHTML += "!";
showRestartToast(true);
requestExperimentalFeaturesData();
}
@@ -495,10 +524,26 @@ FlagSearch.prototype = {
}
};
+/**
+ * Allows the restart button to jump back to the previously focused experiment
+ * in the list instead of going to the top of the page.
+ */
+function setupRestartButton() {
+ restartButton.addEventListener('keydown', function(e) {
+ if (e.shiftKey && e.key == 'Tab' && lastFocused) {
+ e.preventDefault();
+ lastFocused.focus();
+ }
+ });
+ restartButton.addEventListener('blur', () => {
+ lastFocused = null;
+ });
+}
+
document.addEventListener('DOMContentLoaded', function() {
// Get and display the data upon loading.
requestExperimentalFeaturesData();
-
+ setupRestartButton();
cr.ui.FocusOutlineManager.forDocument(document);
});
diff --git a/chromium/components/gcm_driver/BUILD.gn b/chromium/components/gcm_driver/BUILD.gn
index 7fe0e26c3e3..dc03d2a4b45 100644
--- a/chromium/components/gcm_driver/BUILD.gn
+++ b/chromium/components/gcm_driver/BUILD.gn
@@ -40,8 +40,8 @@ static_library("gcm_driver") {
"registration_info.h",
"system_encryptor.cc",
"system_encryptor.h",
- "web_push_metrics.cc",
- "web_push_metrics.h",
+ "web_push_common.cc",
+ "web_push_common.h",
"web_push_sender.cc",
"web_push_sender.h",
]
diff --git a/chromium/components/gcm_driver/android/BUILD.gn b/chromium/components/gcm_driver/android/BUILD.gn
index 81aa2f8a7c4..ec731b371d3 100644
--- a/chromium/components/gcm_driver/android/BUILD.gn
+++ b/chromium/components/gcm_driver/android/BUILD.gn
@@ -24,6 +24,7 @@ android_library("gcm_driver_java") {
"java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingSubscriber.java",
"java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingV2.java",
"java/src/org/chromium/components/gcm_driver/LazySubscriptionsManager.java",
+ "java/src/org/chromium/components/gcm_driver/SubscriptionFlagManager.java",
]
}
diff --git a/chromium/components/gcm_driver/instance_id/BUILD.gn b/chromium/components/gcm_driver/instance_id/BUILD.gn
index 5a3161558ce..b3a28a69869 100644
--- a/chromium/components/gcm_driver/instance_id/BUILD.gn
+++ b/chromium/components/gcm_driver/instance_id/BUILD.gn
@@ -4,6 +4,10 @@
import("//components/gcm_driver/config.gni")
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+
static_library("instance_id") {
sources = [
"instance_id.cc",
@@ -77,3 +81,11 @@ source_set("unit_tests") {
"//testing/gtest",
]
}
+
+if (is_android) {
+ java_cpp_enum("instance_id_java_enums_srcjar") {
+ sources = [
+ "instance_id.h",
+ ]
+ }
+}
diff --git a/chromium/components/gcm_driver/instance_id/android/BUILD.gn b/chromium/components/gcm_driver/instance_id/android/BUILD.gn
index e5b2483fa3b..a0e07754555 100644
--- a/chromium/components/gcm_driver/instance_id/android/BUILD.gn
+++ b/chromium/components/gcm_driver/instance_id/android/BUILD.gn
@@ -23,6 +23,9 @@ android_library("instance_id_driver_java") {
"//components/gcm_driver/android:gcm_driver_java",
]
+ srcjar_deps =
+ [ "//components/gcm_driver/instance_id:instance_id_java_enums_srcjar" ]
+
java_files = [
"java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDBridge.java",
"java/src/org/chromium/components/gcm_driver/instance_id/InstanceIDWithSubtype.java",
diff --git a/chromium/components/google/OWNERS b/chromium/components/google/OWNERS
index 558e5509926..1461f9d3e65 100644
--- a/chromium/components/google/OWNERS
+++ b/chromium/components/google/OWNERS
@@ -2,3 +2,4 @@ isherman@chromium.org
pkasting@chromium.org
# COMPONENT: Internals
+# TEAM: chromium-dev@chromium.org
diff --git a/chromium/components/google/core/browser/BUILD.gn b/chromium/components/google/core/browser/BUILD.gn
deleted file mode 100644
index 22f7273ce4e..00000000000
--- a/chromium/components/google/core/browser/BUILD.gn
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-static_library("browser") {
- sources = [
- "google_pref_names.cc",
- "google_pref_names.h",
- "google_url_tracker.cc",
- "google_url_tracker.h",
- "google_url_tracker_client.cc",
- "google_url_tracker_client.h",
- ]
-
- public_deps = [
- "//base",
- "//components/google/core/common",
- "//components/keyed_service/core",
- "//url",
- ]
-
- deps = [
- "//components/pref_registry",
- "//components/prefs",
- "//components/strings",
- "//services/network/public/cpp",
- "//services/network/public/mojom",
- ]
-}
-
-source_set("unit_tests") {
- testonly = true
-
- sources = [
- "google_url_tracker_unittest.cc",
- "google_util_unittest.cc",
- ]
-
- deps = [
- ":browser",
- "//base",
- "//components/prefs:test_support",
- "//net:test_support",
- "//services/network:test_support",
- "//services/network/public/cpp",
- "//services/network/public/mojom",
- "//testing/gtest",
- ]
-}
diff --git a/chromium/components/google/core/browser/DEPS b/chromium/components/google/core/browser/DEPS
deleted file mode 100644
index 5f1bc003279..00000000000
--- a/chromium/components/google/core/browser/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
- "+components/keyed_service/core",
- "+components/prefs",
- "+components/pref_registry",
- "+services/network/public",
- "+services/network/test",
-]
diff --git a/chromium/components/google/core/browser/OWNERS b/chromium/components/google/core/browser/OWNERS
deleted file mode 100644
index 991eb9d1e22..00000000000
--- a/chromium/components/google/core/browser/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file google_tld_list.h=msramek@chromium.org
-
diff --git a/chromium/components/google/core/browser/google_pref_names.cc b/chromium/components/google/core/browser/google_pref_names.cc
deleted file mode 100644
index 92787d0c6d6..00000000000
--- a/chromium/components/google/core/browser/google_pref_names.cc
+++ /dev/null
@@ -1,17 +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 "components/google/core/browser/google_pref_names.h"
-
-namespace prefs {
-
-// String containing the last known Google URL. We re-detect this on startup in
-// most cases, and use it to send traffic to the correct Google host or with the
-// correct Google domain/country code for whatever location the user is in.
-const char kLastKnownGoogleURL[] = "browser.last_known_google_url";
-
-// String containing the last prompted Google URL.
-const char kLastPromptedGoogleURL[] = "browser.last_prompted_google_url";
-
-} // namespace prefs
diff --git a/chromium/components/google/core/browser/google_pref_names.h b/chromium/components/google/core/browser/google_pref_names.h
deleted file mode 100644
index 2c58dd29187..00000000000
--- a/chromium/components/google/core/browser/google_pref_names.h
+++ /dev/null
@@ -1,17 +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 COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_PREF_NAMES_H_
-#define COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_PREF_NAMES_H_
-
-namespace prefs {
-
-// Alphabetical list of preference names specific to the Google
-// component. Keep alphabetized, and document each in the .cc file.
-extern const char kLastKnownGoogleURL[];
-extern const char kLastPromptedGoogleURL[];
-
-} // namespace prefs
-
-#endif // COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_PREF_NAMES_H_
diff --git a/chromium/components/google/core/browser/google_url_tracker.cc b/chromium/components/google/core/browser/google_url_tracker.cc
deleted file mode 100644
index cbc66dacbec..00000000000
--- a/chromium/components/google/core/browser/google_url_tracker.cc
+++ /dev/null
@@ -1,226 +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 "components/google/core/browser/google_url_tracker.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/google/core/browser/google_pref_names.h"
-#include "components/google/core/common/google_switches.h"
-#include "components/google/core/common/google_util.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
-#include "net/base/load_flags.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/simple_url_loader.h"
-
-const char GoogleURLTracker::kDefaultGoogleHomepage[] =
- "https://www.google.com/";
-const char GoogleURLTracker::kSearchDomainCheckURL[] =
- "https://www.google.com/searchdomaincheck?format=domain&type=chrome";
-
-GoogleURLTracker::GoogleURLTracker(
- std::unique_ptr<GoogleURLTrackerClient> client,
- Mode mode,
- network::NetworkConnectionTracker* network_connection_tracker)
- : client_(std::move(client)),
- network_connection_tracker_(network_connection_tracker),
- google_url_(
- mode == ALWAYS_DOT_COM_MODE
- ? kDefaultGoogleHomepage
- : client_->GetPrefs()->GetString(prefs::kLastKnownGoogleURL)),
- in_startup_sleep_(true),
- already_loaded_(false),
- need_to_load_(false) {
- network_connection_tracker_->AddNetworkConnectionObserver(this);
- client_->set_google_url_tracker(this);
-
- // Because this function can be called during startup, when kicking off a URL
- // load can eat up 20 ms of time, we delay five seconds, which is hopefully
- // long enough to be after startup, but still get results back quickly.
- // Ideally, instead of this timer, we'd do something like "check if the
- // browser is starting up, and if so, come back later", but there is currently
- // no function to do this.
- //
- // In ALWAYS_DOT_COM_MODE we do not nothing at all (but in unit tests
- // /searchdomaincheck lookups might still be issued by calling FinishSleep
- // manually).
- if (mode == NORMAL_MODE) {
- static const int kStartLoadDelayMS = 5000;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&GoogleURLTracker::FinishSleep,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kStartLoadDelayMS));
- }
-}
-
-GoogleURLTracker::~GoogleURLTracker() {
-}
-
-// static
-void GoogleURLTracker::RegisterProfilePrefs(
- user_prefs::PrefRegistrySyncable* registry) {
- registry->RegisterStringPref(prefs::kLastKnownGoogleURL,
- GoogleURLTracker::kDefaultGoogleHomepage);
- registry->RegisterStringPref(prefs::kLastPromptedGoogleURL, std::string());
-}
-
-void GoogleURLTracker::RequestServerCheck() {
- if (!simple_loader_)
- SetNeedToLoad();
-}
-
-std::unique_ptr<GoogleURLTracker::Subscription>
-GoogleURLTracker::RegisterCallback(const OnGoogleURLUpdatedCallback& cb) {
- return callback_list_.Add(cb);
-}
-
-void GoogleURLTracker::OnURLLoaderComplete(
- std::unique_ptr<std::string> response_body) {
- // Delete the loader.
- simple_loader_.reset();
-
- // Don't update the URL if the request didn't succeed.
- if (!response_body) {
- already_loaded_ = false;
- return;
- }
-
- // See if the response data was valid. It should be ".google.<TLD>".
- base::TrimWhitespaceASCII(*response_body, base::TRIM_ALL,
- response_body.get());
- if (!base::StartsWith(*response_body, ".google.",
- base::CompareCase::INSENSITIVE_ASCII))
- return;
- GURL url("https://www" + *response_body);
- if (!url.is_valid() || (url.path().length() > 1) || url.has_query() ||
- url.has_ref() ||
- !google_util::IsGoogleDomainUrl(url, google_util::DISALLOW_SUBDOMAIN,
- google_util::DISALLOW_NON_STANDARD_PORTS))
- return;
-
- if (url != google_url_) {
- google_url_ = url;
- client_->GetPrefs()->SetString(prefs::kLastKnownGoogleURL,
- google_url_.spec());
- callback_list_.Notify();
- }
-}
-
-void GoogleURLTracker::OnConnectionChanged(
- network::mojom::ConnectionType type) {
- // Ignore destructive signals.
- if (type == network::mojom::ConnectionType::CONNECTION_NONE)
- return;
- already_loaded_ = false;
- StartLoadIfDesirable();
-}
-
-void GoogleURLTracker::Shutdown() {
- client_.reset();
- simple_loader_.reset();
- weak_ptr_factory_.InvalidateWeakPtrs();
- network_connection_tracker_->RemoveNetworkConnectionObserver(this);
-}
-
-void GoogleURLTracker::SetNeedToLoad() {
- need_to_load_ = true;
- StartLoadIfDesirable();
-}
-
-void GoogleURLTracker::FinishSleep() {
- in_startup_sleep_ = false;
- StartLoadIfDesirable();
-}
-
-void GoogleURLTracker::StartLoadIfDesirable() {
- // Bail if a load isn't appropriate right now. This function will be called
- // again each time one of the preconditions changes, so we'll load
- // immediately once all of them are met.
- //
- // See comments in header on the class, on RequestServerCheck(), and on the
- // various members here for more detail on exactly what the conditions are.
- if (in_startup_sleep_ || already_loaded_ || !need_to_load_)
- return;
-
- // Some switches should disable the Google URL tracker entirely. If we can't
- // do background networking, we can't do the necessary load, and if the user
- // specified a Google base URL manually, we shouldn't bother to look up any
- // alternatives or offer to switch to them.
- if (!client_->IsBackgroundNetworkingEnabled() ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kGoogleBaseURL))
- return;
-
- already_loaded_ = true;
- net::NetworkTrafficAnnotationTag traffic_annotation =
- net::DefineNetworkTrafficAnnotation("google_url_tracker", R"(
- semantics {
- sender: "Google URL Tracker"
- description:
- "When the user's default search engine is Google, or Google "
- "services are used to resolve navigation errors, the browser needs "
- "to know the ideal origin for requests to Google services. In "
- "these cases the browser makes a request to a global Google "
- "service that returns this origin, potentially taking into account "
- "the user's cookies or IP address."
- trigger: "Browser startup or network change."
- data: "None."
- destination: GOOGLE_OWNED_SERVICE
- }
- policy {
- cookies_allowed: YES
- cookies_store: "user"
- setting:
- "To disable this check, users can change the default search engine "
- "to something other than Google, and disable 'Use a web service to "
- "help resolve navigation errors' in Chromium's settings under "
- "Privacy.\nAlternately, running Chromium with "
- "--google-base-url=\"https://www.google.com/\" will disable this, "
- "and force Chromium to use the specified URL for Google service "
- "requests.\nFinally, running Chromium with "
- "--disable-background-networking will disable this, as well as "
- "various other features that make network requests automatically."
- policy_exception_justification:
- "Setting DefaultSearchProviderEnabled Chrome settings policy to "
- "false suffices as a way of setting the default search engine to "
- "not be Google. But there is no policy that controls navigation "
- "error resolution."
- })");
- auto resource_request = std::make_unique<network::ResourceRequest>();
- resource_request->url = GURL(kSearchDomainCheckURL);
- // We don't want this load to set new entries in the cache or cookies, lest
- // we alarm the user.
- resource_request->load_flags =
- (net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SAVE_COOKIES);
- simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
- traffic_annotation);
- // Configure to retry at most kMaxRetries times for 5xx errors and network
- // changes.
- // A network change can propagate through Chrome in various stages, so it's
- // possible for this code to be reached via OnNetworkChanged(), and then have
- // the load we kick off be canceled due to e.g. the DNS server changing at a
- // later time. In general it's not possible to ensure that by the time we
- // reach here any requests we start won't be canceled in this fashion, so
- // retrying is the best we can do.
- static const int kMaxRetries = 5;
- simple_loader_->SetRetryOptions(
- kMaxRetries,
- network::SimpleURLLoader::RetryMode::RETRY_ON_5XX |
- network::SimpleURLLoader::RetryMode::RETRY_ON_NETWORK_CHANGE);
- simple_loader_->DownloadToString(
- client_->GetURLLoaderFactory(),
- base::BindOnce(&GoogleURLTracker::OnURLLoaderComplete,
- base::Unretained(this)),
- 2 * 1024 /* max_body_size */);
-}
diff --git a/chromium/components/google/core/browser/google_url_tracker.h b/chromium/components/google/core/browser/google_url_tracker.h
deleted file mode 100644
index f8d731f4388..00000000000
--- a/chromium/components/google/core/browser/google_url_tracker.h
+++ /dev/null
@@ -1,137 +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 COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_URL_TRACKER_H_
-#define COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_URL_TRACKER_H_
-
-#include <memory>
-
-#include "base/callback_forward.h"
-#include "base/callback_list.h"
-#include "base/feature_list.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/google/core/browser/google_url_tracker_client.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "services/network/public/cpp/network_connection_tracker.h"
-#include "url/gurl.h"
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-namespace network {
-class SimpleURLLoader;
-} // namespace network
-
-// This object is responsible for checking the Google URL once per network
-// change. The current value is saved to prefs.
-//
-// Most consumers should only call google_url(). Consumers who need to be
-// notified when things change should use RegisterCallback().
-//
-// To protect users' privacy and reduce server load, no updates will be
-// performed (ever) unless at least one consumer registers interest by calling
-// RequestServerCheck().
-class GoogleURLTracker
- : public network::NetworkConnectionTracker::NetworkConnectionObserver,
- public KeyedService {
- public:
- // Callback that is called when the Google URL is updated.
- typedef base::Callback<void()> OnGoogleURLUpdatedCallback;
- typedef base::CallbackList<void()> CallbackList;
- typedef CallbackList::Subscription Subscription;
-
- // The mode of the tracker that controls how the tracker behaves and that must
- // be passed to its constructor.
- enum Mode {
- // Use current local Google TLD.
- // Defer network requests to update TLD until 5 seconds after
- // creation, to avoid an expensive load during Chrome startup.
- //
- // TODO(https://crbug.com/973591): This is unused now. Remove it.
- NORMAL_MODE,
-
- // Always use www.google.com.
- ALWAYS_DOT_COM_MODE,
- };
-
- static const char kDefaultGoogleHomepage[];
-
- // Only the GoogleURLTrackerFactory and tests should call this.
- // |network_connection_tracker| should be the global singleton instance and
- // should outlive the GoogleURLTracker object.
- // Note: you *must* manually call Shutdown() before this instance gets
- // destroyed if you want to create another instance in the same binary
- // (e.g. in unit tests).
- GoogleURLTracker(
- std::unique_ptr<GoogleURLTrackerClient> client,
- Mode mode,
- network::NetworkConnectionTracker* network_connection_tracker);
-
- ~GoogleURLTracker() override;
-
- // Register user preferences for GoogleURLTracker.
- static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
- // Returns the current Google homepage URL.
- const GURL& google_url() const { return google_url_; }
-
- // Requests that the tracker perform a server check to update the Google URL
- // as necessary. This will happen at most once per network change, not sooner
- // than five seconds after startup (checks requested before that time will
- // occur then; checks requested afterwards will occur immediately, if no other
- // checks have been made during this run).
- void RequestServerCheck();
-
- std::unique_ptr<Subscription> RegisterCallback(
- const OnGoogleURLUpdatedCallback& cb);
-
- private:
- friend class GoogleURLTrackerTest;
- friend class SyncTest;
-
- static const char kSearchDomainCheckURL[];
-
- void OnURLLoaderComplete(std::unique_ptr<std::string> response_body);
-
- // NetworkConnectionTracker::NetworkConnectionObserver:
- void OnConnectionChanged(network::mojom::ConnectionType type) override;
-
- // KeyedService:
- void Shutdown() override;
-
- // Sets |need_to_load_| and attempts to start a load.
- void SetNeedToLoad();
-
- // Called when the five second startup sleep has finished. Runs any pending
- // load.
- void FinishSleep();
-
- // Starts the load of the up-to-date Google URL if we actually want to load
- // it and can currently do so.
- void StartLoadIfDesirable();
-
- CallbackList callback_list_;
-
- std::unique_ptr<GoogleURLTrackerClient> client_;
- network::NetworkConnectionTracker* network_connection_tracker_;
-
- GURL google_url_;
- std::unique_ptr<network::SimpleURLLoader> simple_loader_;
- bool in_startup_sleep_; // True if we're in the five-second "no loading"
- // period that begins at browser start.
- bool already_loaded_; // True if we've already loaded a URL once this run;
- // we won't load again until after a restart.
- bool need_to_load_; // True if a consumer actually wants us to load an
- // updated URL. If this is never set, we won't
- // bother to load anything.
- // Consumers should register a callback via
- // RegisterCallback().
- base::WeakPtrFactory<GoogleURLTracker> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(GoogleURLTracker);
-};
-
-#endif // COMPONENTS_GOOGLE_CORE_BROWSER_GOOGLE_URL_TRACKER_H_
diff --git a/chromium/components/google/core/browser/google_url_tracker_client.cc b/chromium/components/google/core/browser/google_url_tracker_client.cc
deleted file mode 100644
index 5091fd6d0d5..00000000000
--- a/chromium/components/google/core/browser/google_url_tracker_client.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/google/core/browser/google_url_tracker_client.h"
-
-GoogleURLTrackerClient::GoogleURLTrackerClient()
- : google_url_tracker_(nullptr) {}
-
-GoogleURLTrackerClient::~GoogleURLTrackerClient() {
-}
diff --git a/chromium/components/google/core/browser/google_url_tracker_client.h b/chromium/components/google/core/browser/google_url_tracker_client.h
deleted file mode 100644
index 0ab7028ac6d..00000000000
--- a/chromium/components/google/core/browser/google_url_tracker_client.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_GOOGLE_GOOGLE_URL_TRACKER_CLIENT_H_
-#define COMPONENTS_GOOGLE_GOOGLE_URL_TRACKER_CLIENT_H_
-
-#include "base/macros.h"
-#include "url/gurl.h"
-
-class GoogleURLTracker;
-class PrefService;
-
-namespace network {
-namespace mojom {
-class URLLoaderFactory;
-}
-}
-
-// Interface by which GoogleURLTracker communicates with its embedder.
-class GoogleURLTrackerClient {
- public:
- GoogleURLTrackerClient();
- virtual ~GoogleURLTrackerClient();
-
- // Sets the GoogleURLTracker that is associated with this client.
- void set_google_url_tracker(GoogleURLTracker* google_url_tracker) {
- google_url_tracker_ = google_url_tracker;
- }
-
- // Returns whether background networking is enabled.
- virtual bool IsBackgroundNetworkingEnabled() = 0;
-
- // Returns the PrefService that the GoogleURLTracker should use.
- virtual PrefService* GetPrefs() = 0;
-
- // Returns the URL loader factory that the GoogleURLTracker should use.
- virtual network::mojom::URLLoaderFactory* GetURLLoaderFactory() = 0;
-
- protected:
- GoogleURLTracker* google_url_tracker() { return google_url_tracker_; }
-
- private:
- GoogleURLTracker* google_url_tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(GoogleURLTrackerClient);
-};
-
-#endif // COMPONENTS_GOOGLE_GOOGLE_URL_TRACKER_CLIENT_H_
diff --git a/chromium/components/google/core/browser/google_url_tracker_unittest.cc b/chromium/components/google/core/browser/google_url_tracker_unittest.cc
deleted file mode 100644
index 12586c2c3e2..00000000000
--- a/chromium/components/google/core/browser/google_url_tracker_unittest.cc
+++ /dev/null
@@ -1,360 +0,0 @@
-// Copyright 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 "components/google/core/browser/google_url_tracker.h"
-
-#include <memory>
-#include <string>
-#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/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/google/core/browser/google_pref_names.h"
-#include "components/google/core/browser/google_url_tracker_client.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/testing_pref_service.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "services/network/test/test_network_connection_tracker.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// TestCallbackListener ---------------------------------------------------
-
-class TestCallbackListener {
- public:
- TestCallbackListener();
- virtual ~TestCallbackListener();
-
- bool HasRegisteredCallback();
- void RegisterCallback(GoogleURLTracker* google_url_tracker);
-
- bool notified() const { return notified_; }
- void clear_notified() { notified_ = false; }
-
- private:
- void OnGoogleURLUpdated();
-
- bool notified_;
- std::unique_ptr<GoogleURLTracker::Subscription>
- google_url_updated_subscription_;
-};
-
-TestCallbackListener::TestCallbackListener() : notified_(false) {
-}
-
-TestCallbackListener::~TestCallbackListener() {
-}
-
-void TestCallbackListener::OnGoogleURLUpdated() {
- notified_ = true;
-}
-
-bool TestCallbackListener::HasRegisteredCallback() {
- return google_url_updated_subscription_.get();
-}
-
-void TestCallbackListener::RegisterCallback(
- GoogleURLTracker* google_url_tracker) {
- google_url_updated_subscription_ =
- google_url_tracker->RegisterCallback(base::Bind(
- &TestCallbackListener::OnGoogleURLUpdated, base::Unretained(this)));
-}
-
-
-// TestGoogleURLTrackerClient -------------------------------------------------
-
-class TestGoogleURLTrackerClient : public GoogleURLTrackerClient {
- public:
- TestGoogleURLTrackerClient(
- PrefService* prefs_,
- network::TestURLLoaderFactory* test_url_loader_factory);
- ~TestGoogleURLTrackerClient() override;
-
- bool IsBackgroundNetworkingEnabled() override;
- PrefService* GetPrefs() override;
- network::mojom::URLLoaderFactory* GetURLLoaderFactory() override;
-
- private:
- PrefService* prefs_;
- scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TestGoogleURLTrackerClient);
-};
-
-TestGoogleURLTrackerClient::TestGoogleURLTrackerClient(
- PrefService* prefs,
- network::TestURLLoaderFactory* test_url_loader_factory)
- : prefs_(prefs),
- test_shared_loader_factory_(
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- test_url_loader_factory)) {}
-
-TestGoogleURLTrackerClient::~TestGoogleURLTrackerClient() {
-}
-
-bool TestGoogleURLTrackerClient::IsBackgroundNetworkingEnabled() {
- return true;
-}
-
-PrefService* TestGoogleURLTrackerClient::GetPrefs() {
- return prefs_;
-}
-
-network::mojom::URLLoaderFactory*
-TestGoogleURLTrackerClient::GetURLLoaderFactory() {
- return test_shared_loader_factory_.get();
-}
-
-} // namespace
-
-// GoogleURLTrackerTest -------------------------------------------------------
-
-class GoogleURLTrackerTest : public testing::Test {
- protected:
- GoogleURLTrackerTest();
- ~GoogleURLTrackerTest() override;
-
- // testing::Test
- void SetUp() override;
- void TearDown() override;
-
- void MockSearchDomainCheckResponse(const std::string& domain);
- void RequestServerCheck();
- void FinishSleep();
- void NotifyNetworkChanged();
- void set_google_url(const GURL& url) {
- google_url_tracker_->google_url_ = url;
- }
- GURL google_url() const { return google_url_tracker_->google_url(); }
- bool listener_notified() const { return listener_.notified(); }
- void clear_listener_notified() { listener_.clear_notified(); }
- bool handled_request() const { return handled_request_; }
-
- GoogleURLTrackerClient* client() const { return client_; }
-
- private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- TestingPrefServiceSimple prefs_;
- network::TestURLLoaderFactory test_url_loader_factory_;
-
- GoogleURLTrackerClient* client_;
-
- std::unique_ptr<GoogleURLTracker> google_url_tracker_;
- TestCallbackListener listener_;
-
- bool handled_request_ = false;
-};
-
-GoogleURLTrackerTest::GoogleURLTrackerTest() {
- prefs_.registry()->RegisterStringPref(
- prefs::kLastKnownGoogleURL,
- GoogleURLTracker::kDefaultGoogleHomepage);
-}
-
-GoogleURLTrackerTest::~GoogleURLTrackerTest() {
-}
-
-void GoogleURLTrackerTest::SetUp() {
- // Ownership is passed to google_url_tracker_, but a weak pointer is kept;
- // this is safe since GoogleURLTracker keeps the client for its lifetime.
- client_ = new TestGoogleURLTrackerClient(&prefs_, &test_url_loader_factory_);
- std::unique_ptr<GoogleURLTrackerClient> client(client_);
- google_url_tracker_.reset(new GoogleURLTracker(
- std::move(client), GoogleURLTracker::ALWAYS_DOT_COM_MODE,
- network::TestNetworkConnectionTracker::GetInstance()));
-}
-
-void GoogleURLTrackerTest::TearDown() {
- google_url_tracker_->Shutdown();
-}
-
-void GoogleURLTrackerTest::MockSearchDomainCheckResponse(
- const std::string& domain) {
- handled_request_ = false;
- test_url_loader_factory_.SetInterceptor(
- base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
- handled_request_ = true;
- }));
- test_url_loader_factory_.AddResponse(GoogleURLTracker::kSearchDomainCheckURL,
- domain);
-}
-
-void GoogleURLTrackerTest::RequestServerCheck() {
- if (!listener_.HasRegisteredCallback())
- listener_.RegisterCallback(google_url_tracker_.get());
- google_url_tracker_->SetNeedToLoad();
- base::RunLoop().RunUntilIdle();
-}
-
-void GoogleURLTrackerTest::FinishSleep() {
- google_url_tracker_->FinishSleep();
- base::RunLoop().RunUntilIdle();
-}
-
-void GoogleURLTrackerTest::NotifyNetworkChanged() {
- network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
- network::mojom::ConnectionType::CONNECTION_UNKNOWN);
- base::RunLoop().RunUntilIdle();
-}
-
-// Tests ----------------------------------------------------------------------
-
-TEST_F(GoogleURLTrackerTest, DontFetchWhenNoOneRequestsCheck) {
- EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), google_url());
- FinishSleep();
- // No one called RequestServerCheck() so nothing should have happened.
- EXPECT_FALSE(handled_request());
- MockSearchDomainCheckResponse(".google.co.uk");
- EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), google_url());
- EXPECT_FALSE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, Update) {
- MockSearchDomainCheckResponse(".google.co.uk");
-
- RequestServerCheck();
- EXPECT_FALSE(handled_request());
- EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), google_url());
- EXPECT_FALSE(listener_notified());
-
- FinishSleep();
- EXPECT_EQ(GURL("https://www.google.co.uk/"), google_url());
- EXPECT_TRUE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, DontUpdateWhenUnchanged) {
- MockSearchDomainCheckResponse(".google.co.uk");
-
- GURL original_google_url("https://www.google.co.uk/");
- set_google_url(original_google_url);
-
- RequestServerCheck();
- EXPECT_FALSE(handled_request());
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- FinishSleep();
- EXPECT_EQ(original_google_url, google_url());
- // No one should be notified, because the new URL matches the old.
- EXPECT_FALSE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, DontUpdateOnBadReplies) {
- GURL original_google_url("https://www.google.co.uk/");
- set_google_url(original_google_url);
-
- RequestServerCheck();
- EXPECT_FALSE(handled_request());
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Old-style URL string.
- MockSearchDomainCheckResponse("https://www.google.com/");
- FinishSleep();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Not a Google domain.
- MockSearchDomainCheckResponse(".google.evil.com");
- FinishSleep();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Doesn't start with .google.
- MockSearchDomainCheckResponse(".mail.google.com");
- NotifyNetworkChanged();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Non-empty path.
- MockSearchDomainCheckResponse(".google.com/search");
- NotifyNetworkChanged();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Non-empty query.
- MockSearchDomainCheckResponse(".google.com/?q=foo");
- NotifyNetworkChanged();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Non-empty ref.
- MockSearchDomainCheckResponse(".google.com/#anchor");
- NotifyNetworkChanged();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-
- // Complete garbage.
- MockSearchDomainCheckResponse("HJ)*qF)_*&@f1");
- NotifyNetworkChanged();
- EXPECT_EQ(original_google_url, google_url());
- EXPECT_FALSE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, RefetchOnNetworkChange) {
- MockSearchDomainCheckResponse(".google.co.uk");
- RequestServerCheck();
- FinishSleep();
- EXPECT_EQ(GURL("https://www.google.co.uk/"), google_url());
- EXPECT_TRUE(listener_notified());
- clear_listener_notified();
-
- MockSearchDomainCheckResponse(".google.co.in");
- NotifyNetworkChanged();
- EXPECT_EQ(GURL("https://www.google.co.in/"), google_url());
- EXPECT_TRUE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, DontRefetchWhenNoOneRequestsCheck) {
- MockSearchDomainCheckResponse(".google.co.uk");
- FinishSleep();
- NotifyNetworkChanged();
- // No one called RequestServerCheck() so nothing should have happened.
- EXPECT_FALSE(handled_request());
- EXPECT_EQ(GURL(GoogleURLTracker::kDefaultGoogleHomepage), google_url());
- EXPECT_FALSE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, FetchOnLateRequest) {
- MockSearchDomainCheckResponse(".google.co.jp");
- FinishSleep();
- NotifyNetworkChanged();
-
- MockSearchDomainCheckResponse(".google.co.uk");
- RequestServerCheck();
- // The first request for a check should trigger a fetch if it hasn't happened
- // already.
- EXPECT_EQ(GURL("https://www.google.co.uk/"), google_url());
- EXPECT_TRUE(listener_notified());
-}
-
-TEST_F(GoogleURLTrackerTest, DontFetchTwiceOnLateRequests) {
- MockSearchDomainCheckResponse(".google.co.jp");
- FinishSleep();
- NotifyNetworkChanged();
-
- MockSearchDomainCheckResponse(".google.co.uk");
- RequestServerCheck();
- // The first request for a check should trigger a fetch if it hasn't happened
- // already.
- EXPECT_EQ(GURL("https://www.google.co.uk/"), google_url());
- EXPECT_TRUE(listener_notified());
- clear_listener_notified();
-
- MockSearchDomainCheckResponse(".google.co.in");
- RequestServerCheck();
- // The second request should be ignored.
- EXPECT_FALSE(handled_request());
- EXPECT_EQ(GURL("https://www.google.co.uk/"), google_url());
- EXPECT_FALSE(listener_notified());
-}
diff --git a/chromium/components/google/core/common/BUILD.gn b/chromium/components/google/core/common/BUILD.gn
index d558cb15fe5..1f7b4cb2f87 100644
--- a/chromium/components/google/core/common/BUILD.gn
+++ b/chromium/components/google/core/common/BUILD.gn
@@ -17,6 +17,21 @@ static_library("common") {
]
deps = [
+ "//build:branding_buildflags",
"//components/url_formatter",
]
}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "google_util_unittest.cc",
+ ]
+
+ deps = [
+ ":common",
+ "//base",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/google/core/common/google_util.cc b/chromium/components/google/core/common/google_util.cc
index 491ec0d65a9..08c89f41c38 100644
--- a/chromium/components/google/core/common/google_util.cc
+++ b/chromium/components/google/core/common/google_util.cc
@@ -19,6 +19,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/branding_buildflags.h"
#include "components/google/core/common/google_switches.h"
#include "components/google/core/common/google_tld_list.h"
#include "components/url_formatter/url_fixer.h"
@@ -29,7 +30,7 @@
// Only use Link Doctor on official builds. It uses an API key, too, but
// seems best to just disable it, for more responsive error pages and to reduce
// server load.
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#define LINKDOCTOR_SERVER_REQUEST_URL "https://www.googleapis.com/rpc"
#else
#define LINKDOCTOR_SERVER_REQUEST_URL ""
@@ -145,6 +146,8 @@ bool IsGoogleSearchSubdomainUrl(const GURL& url) {
// Global functions -----------------------------------------------------------
+const char kGoogleHomepageURL[] = "https://www.google.com/";
+
bool HasGoogleSearchQueryParam(base::StringPiece str) {
url::Component query(0, static_cast<int>(str.length())), key, value;
while (url::ExtractQueryKeyValue(str.data(), &query, &key, &value)) {
diff --git a/chromium/components/google/core/common/google_util.h b/chromium/components/google/core/common/google_util.h
index 70957e16170..cda6b868cba 100644
--- a/chromium/components/google/core/common/google_util.h
+++ b/chromium/components/google/core/common/google_util.h
@@ -17,6 +17,8 @@ class GURL;
// This namespace provides various helpers around handling Google-related URLs.
namespace google_util {
+extern const char kGoogleHomepageURL[];
+
// True iff |str| contains a "q=" or "as_q=" query parameter with a non-empty
// value. |str| should be a query or a hash fragment, without the ? or # (as
// returned by GURL::query() or GURL::ref().
diff --git a/chromium/components/google/core/browser/google_util_unittest.cc b/chromium/components/google/core/common/google_util_unittest.cc
index a51544a2a0a..b975048964f 100644
--- a/chromium/components/google/core/browser/google_util_unittest.cc
+++ b/chromium/components/google/core/common/google_util_unittest.cc
@@ -7,9 +7,9 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
-#include "components/google/core/browser/google_url_tracker.h"
#include "components/google/core/common/google_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
using google_util::IsGoogleDomainUrl;
@@ -44,7 +44,7 @@ bool StartsWithBaseURL(const std::string& url) {
TEST(GoogleUtilTest, GoodHomePagesNonSecure) {
// Valid home page hosts.
- EXPECT_TRUE(IsHomePage(GoogleURLTracker::kDefaultGoogleHomepage));
+ EXPECT_TRUE(IsHomePage(google_util::kGoogleHomepageURL));
EXPECT_TRUE(IsHomePage("http://google.com"));
EXPECT_TRUE(IsHomePage("http://www.google.com"));
EXPECT_TRUE(IsHomePage("http://www.google.ca"));
@@ -188,7 +188,7 @@ TEST(GoogleUtilTest, GoodSearches) {
TEST(GoogleUtilTest, BadSearches) {
// A home page URL should not be identified as a search URL.
- EXPECT_FALSE(IsSearch(GoogleURLTracker::kDefaultGoogleHomepage));
+ EXPECT_FALSE(IsSearch(google_util::kGoogleHomepageURL));
// Must be http or https.
EXPECT_FALSE(IsSearch("ftp://www.google.com/search?q=something"));
diff --git a/chromium/components/guest_os/BUILD.gn b/chromium/components/guest_os/BUILD.gn
new file mode 100644
index 00000000000..48af535158f
--- /dev/null
+++ b/chromium/components/guest_os/BUILD.gn
@@ -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.
+
+import("//testing/test.gni")
+
+static_library("guest_os") {
+ deps = [
+ ":prefs",
+ "//ash/public/cpp",
+ "//chromeos/dbus/power",
+ "//chromeos/dbus/power:power_manager_proto",
+ "//chromeos/dbus/session_manager",
+ "//components/exo",
+ "//components/prefs",
+ "//components/session_manager/core",
+ "//ui/wm/public:public",
+ ]
+ sources = [
+ "guest_os_engagement_metrics.cc",
+ "guest_os_engagement_metrics.h",
+ ]
+}
+
+static_library("prefs") {
+ sources = [
+ "guest_os_prefs.cc",
+ "guest_os_prefs.h",
+ ]
+
+ deps = [
+ "//components/prefs",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ deps = [
+ ":guest_os",
+ ":prefs",
+ "//ash:ash",
+ "//base/test:test_support",
+ "//chromeos/dbus/power:power",
+ "//chromeos/dbus/power:power_manager_proto",
+ "//chromeos/dbus/session_manager",
+ "//components/prefs:test_support",
+ "//components/session_manager/core",
+ "//content/test:test_support",
+ "//testing/gtest",
+ "//ui/aura:test_support",
+ ]
+ sources = [
+ "guest_os_engagement_metrics_unittest.cc",
+ ]
+}
diff --git a/chromium/components/guest_os/DEPS b/chromium/components/guest_os/DEPS
new file mode 100644
index 00000000000..1970e9ddc57
--- /dev/null
+++ b/chromium/components/guest_os/DEPS
@@ -0,0 +1,9 @@
+include_rules = [
+ "+chromeos/dbus",
+ "+components/exo",
+ "+components/prefs",
+ "+components/session_manager/core",
+ "+content/public",
+ "+ui/aura",
+ "+ui/wm/public",
+]
diff --git a/chromium/components/guest_os/OWNERS b/chromium/components/guest_os/OWNERS
new file mode 100644
index 00000000000..dc48383c44d
--- /dev/null
+++ b/chromium/components/guest_os/OWNERS
@@ -0,0 +1 @@
+file://chrome/browser/chromeos/guest_os/OWNERS
diff --git a/chromium/components/guest_os/README.md b/chromium/components/guest_os/README.md
new file mode 100644
index 00000000000..22ec68c51e6
--- /dev/null
+++ b/chromium/components/guest_os/README.md
@@ -0,0 +1,2 @@
+The Guest OS component is for code that is shared between multiple Guest OSes
+(Crostini, Plugin VM, ARC++), but doesn't fit in c/b/chromeos/guest\_os.
diff --git a/chromium/components/guest_os/guest_os_engagement_metrics.cc b/chromium/components/guest_os/guest_os_engagement_metrics.cc
new file mode 100644
index 00000000000..df67b3519f5
--- /dev/null
+++ b/chromium/components/guest_os/guest_os_engagement_metrics.cc
@@ -0,0 +1,227 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/guest_os/guest_os_engagement_metrics.h"
+
+#include <string>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/system/sys_info.h"
+#include "base/time/default_clock.h"
+#include "base/time/default_tick_clock.h"
+#include "chromeos/dbus/power_manager/idle.pb.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
+#include "components/exo/wm_helper.h"
+#include "components/guest_os/guest_os_prefs.h"
+#include "components/prefs/pref_service.h"
+#include "components/session_manager/core/session_manager.h"
+
+namespace guest_os {
+
+namespace {
+
+constexpr base::TimeDelta kUpdateEngagementTimePeriod =
+ base::TimeDelta::FromMinutes(1);
+constexpr base::TimeDelta kSaveEngagementTimeToPrefsPeriod =
+ base::TimeDelta::FromMinutes(30);
+
+int GetDayId(const base::Clock* clock) {
+ return clock->Now().LocalMidnight().since_origin().InDays();
+}
+
+} // namespace
+
+GuestOsEngagementMetrics::GuestOsEngagementMetrics(
+ PrefService* pref_service,
+ WindowMatcher window_matcher,
+ const std::string& pref_prefix,
+ const std::string& uma_name)
+ : pref_service_(pref_service),
+ window_matcher_(window_matcher),
+ pref_prefix_(pref_prefix),
+ uma_name_(uma_name),
+ clock_(base::DefaultClock::GetInstance()),
+ tick_clock_(base::DefaultTickClock::GetInstance()),
+ last_update_ticks_(tick_clock_->NowTicks()) {
+ // If WMHelper doesn't exist, do nothing. This occurs in tests.
+ if (exo::WMHelper::HasInstance())
+ exo::WMHelper::GetInstance()->AddActivationObserver(this);
+
+ session_manager::SessionManager::Get()->AddObserver(this);
+ chromeos::PowerManagerClient::Get()->AddObserver(this);
+
+ DCHECK(pref_service_);
+ RestoreEngagementTimeFromPrefs();
+ update_engagement_time_timer_.Start(
+ FROM_HERE, kUpdateEngagementTimePeriod, this,
+ &GuestOsEngagementMetrics::UpdateEngagementTime);
+ save_engagement_time_to_prefs_timer_.Start(
+ FROM_HERE, kSaveEngagementTimeToPrefsPeriod, this,
+ &GuestOsEngagementMetrics::SaveEngagementTimeToPrefs);
+}
+
+GuestOsEngagementMetrics::~GuestOsEngagementMetrics() {
+ save_engagement_time_to_prefs_timer_.Stop();
+ update_engagement_time_timer_.Stop();
+ UpdateEngagementTime();
+ SaveEngagementTimeToPrefs();
+
+ chromeos::PowerManagerClient::Get()->RemoveObserver(this);
+ session_manager::SessionManager::Get()->RemoveObserver(this);
+
+ // If WMHelper is already destroyed, do nothing.
+ // TODO(crbug.com/748380): Fix shutdown order.
+ if (exo::WMHelper::HasInstance())
+ exo::WMHelper::GetInstance()->RemoveActivationObserver(this);
+}
+
+void GuestOsEngagementMetrics::SetBackgroundActive(bool background_active) {
+ if (background_active_ == background_active)
+ return;
+ UpdateEngagementTime();
+ background_active_ = background_active;
+}
+
+void GuestOsEngagementMetrics::SetClocksForTesting(
+ base::Clock* clock,
+ base::TickClock* tick_clock) {
+ clock_ = clock;
+ tick_clock_ = tick_clock;
+ ResetEngagementTimePrefs();
+}
+
+void GuestOsEngagementMetrics::OnWindowActivated(
+ wm::ActivationChangeObserver::ActivationReason reason,
+ aura::Window* gained_active,
+ aura::Window* lost_active) {
+ UpdateEngagementTime();
+ matched_window_active_ = window_matcher_.Run(gained_active);
+}
+
+void GuestOsEngagementMetrics::OnSessionStateChanged() {
+ UpdateEngagementTime();
+ session_active_ = session_manager::SessionManager::Get()->session_state() ==
+ session_manager::SessionState::ACTIVE;
+}
+
+void GuestOsEngagementMetrics::ScreenIdleStateChanged(
+ const power_manager::ScreenIdleState& proto) {
+ UpdateEngagementTime();
+ screen_dimmed_ = proto.dimmed();
+}
+
+void GuestOsEngagementMetrics::RestoreEngagementTimeFromPrefs() {
+ // Restore accumulated results only if they were recorded on the same OS
+ // version.
+ if (pref_service_->GetString(pref_prefix_ +
+ prefs::kEngagementTimeOsVersion) ==
+ base::SysInfo::OperatingSystemVersion()) {
+ day_id_ =
+ pref_service_->GetInteger(pref_prefix_ + prefs::kEngagementTimeDayId);
+ engagement_time_total_ =
+ pref_service_->GetTimeDelta(pref_prefix_ + prefs::kEngagementTimeTotal);
+ engagement_time_foreground_ = pref_service_->GetTimeDelta(
+ pref_prefix_ + prefs::kEngagementTimeForeground);
+ engagement_time_background_ = pref_service_->GetTimeDelta(
+ pref_prefix_ + prefs::kEngagementTimeBackground);
+ } else {
+ ResetEngagementTimePrefs();
+ }
+
+ RecordEngagementTimeToUmaIfNeeded();
+}
+
+void GuestOsEngagementMetrics::SaveEngagementTimeToPrefs() {
+ DCHECK(pref_service_);
+
+ pref_service_->SetString(pref_prefix_ + prefs::kEngagementTimeOsVersion,
+ base::SysInfo::OperatingSystemVersion());
+ pref_service_->SetInteger(pref_prefix_ + prefs::kEngagementTimeDayId,
+ day_id_);
+ pref_service_->SetTimeDelta(pref_prefix_ + prefs::kEngagementTimeTotal,
+ engagement_time_total_);
+ pref_service_->SetTimeDelta(pref_prefix_ + prefs::kEngagementTimeForeground,
+ engagement_time_foreground_);
+ pref_service_->SetTimeDelta(pref_prefix_ + prefs::kEngagementTimeBackground,
+ engagement_time_background_);
+}
+
+void GuestOsEngagementMetrics::UpdateEngagementTime() {
+ VLOG(2) << "last state: screen_dimmed=" << screen_dimmed_
+ << " session_active=" << session_active_
+ << " background_active=" << background_active_
+ << " matched_window_active=" << matched_window_active_;
+
+ base::TimeTicks now = tick_clock_->NowTicks();
+ base::TimeDelta elapsed = now - last_update_ticks_;
+
+ if (ShouldAccumulateEngagementTotalTime()) {
+ VLOG(2) << "accumulate to total time " << elapsed;
+ engagement_time_total_ += elapsed;
+ if (ShouldAccumulateEngagementForegroundTime()) {
+ VLOG(2) << "accumulate to foreground time " << elapsed;
+ engagement_time_foreground_ += elapsed;
+ } else if (ShouldAccumulateEngagementBackgroundTime()) {
+ VLOG(2) << "accumulate to background time " << elapsed;
+ engagement_time_background_ += elapsed;
+ }
+ }
+
+ last_update_ticks_ = now;
+ RecordEngagementTimeToUmaIfNeeded();
+}
+
+void GuestOsEngagementMetrics::RecordEngagementTimeToUmaIfNeeded() {
+ if (!ShouldRecordEngagementTimeToUma())
+ return;
+ VLOG(2) << "day changed, recording engagement time to UMA";
+ UmaHistogramCustomTimes(
+ uma_name_ + ".EngagementTime.Total", engagement_time_total_,
+ base::TimeDelta::FromSeconds(1),
+ base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
+ UmaHistogramCustomTimes(
+ uma_name_ + ".EngagementTime." + uma_name_ + "Total",
+ engagement_time_foreground_ + engagement_time_background_,
+ base::TimeDelta::FromSeconds(1),
+ base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
+ UmaHistogramCustomTimes(
+ uma_name_ + ".EngagementTime.Foreground", engagement_time_foreground_,
+ base::TimeDelta::FromSeconds(1),
+ base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
+ UmaHistogramCustomTimes(
+ uma_name_ + ".EngagementTime.Background", engagement_time_background_,
+ base::TimeDelta::FromSeconds(1),
+ base::TimeDelta::FromDays(1) + kUpdateEngagementTimePeriod, 50);
+ ResetEngagementTimePrefs();
+}
+
+void GuestOsEngagementMetrics::ResetEngagementTimePrefs() {
+ day_id_ = GetDayId(clock_);
+ engagement_time_total_ = base::TimeDelta();
+ engagement_time_foreground_ = base::TimeDelta();
+ engagement_time_background_ = base::TimeDelta();
+ SaveEngagementTimeToPrefs();
+}
+
+bool GuestOsEngagementMetrics::ShouldAccumulateEngagementTotalTime() const {
+ return session_active_ && !screen_dimmed_;
+}
+
+bool GuestOsEngagementMetrics::ShouldAccumulateEngagementForegroundTime()
+ const {
+ return matched_window_active_;
+}
+
+bool GuestOsEngagementMetrics::ShouldAccumulateEngagementBackgroundTime()
+ const {
+ return background_active_;
+}
+
+bool GuestOsEngagementMetrics::ShouldRecordEngagementTimeToUma() const {
+ return day_id_ != GetDayId(clock_);
+}
+
+} // namespace guest_os
diff --git a/chromium/components/guest_os/guest_os_engagement_metrics.h b/chromium/components/guest_os/guest_os_engagement_metrics.h
new file mode 100644
index 00000000000..0b74315953a
--- /dev/null
+++ b/chromium/components/guest_os/guest_os_engagement_metrics.h
@@ -0,0 +1,131 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_GUEST_OS_GUEST_OS_ENGAGEMENT_METRICS_H_
+#define COMPONENTS_GUEST_OS_GUEST_OS_ENGAGEMENT_METRICS_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "chromeos/dbus/power/power_manager_client.h"
+#include "components/session_manager/core/session_manager_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
+
+class PrefService;
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace base {
+class Clock;
+class TickClock;
+} // namespace base
+
+namespace guest_os {
+
+// A class for recording engagement metrics. Calculates and reports daily
+// totals for the following metrics:
+// - Foo.EngagementTime.Total: Engaged session time, i.e. excluding when the
+// screen is locked or dim due to user idle. To allow comparisons with the
+// other metrics, this class should only be instantiated when the relevant
+// Guest OS is supported.
+// - Foo.EngagementTime.Foreground: Time when the user is engaged and focused
+// on a matching window.
+// - Foo.EngagementTime.Background: Time when the user is engaged and not
+// focused on a matching window, but the Guest OS is otherwise active in the
+// background.
+// - Foo.Engagement.FooTotal: Total of Foreground and Background.
+class GuestOsEngagementMetrics : public wm::ActivationChangeObserver,
+ public session_manager::SessionManagerObserver,
+ public chromeos::PowerManagerClient::Observer {
+ public:
+ using WindowMatcher = base::RepeatingCallback<bool(const aura::Window*)>;
+
+ GuestOsEngagementMetrics(PrefService* pref_service,
+ WindowMatcher window_matcher,
+ const std::string& pref_prefix,
+ const std::string& uma_name);
+ ~GuestOsEngagementMetrics() override;
+
+ // Instead of using |window_matcher_|, we let consumers define when the Guest
+ // OS is active in the background. This function should be called whenever
+ // changes.
+ void SetBackgroundActive(bool background_active);
+
+ void SetClocksForTesting(base::Clock* clock, base::TickClock* tick_clock);
+
+ // wm::ActivationChangeObserver:
+ void OnWindowActivated(wm::ActivationChangeObserver::ActivationReason reason,
+ aura::Window* gained_active,
+ aura::Window* lost_active) override;
+
+ // session_manager::SessionManagerObserver:
+ void OnSessionStateChanged() override;
+
+ // chromeos::PowerManagerClient::Observer:
+ void ScreenIdleStateChanged(
+ const power_manager::ScreenIdleState& proto) override;
+
+ private:
+ // Restores accumulated engagement time in previous sessions from profile
+ // preferences.
+ void RestoreEngagementTimeFromPrefs();
+
+ // Called periodically to save accumulated results to profile preferences.
+ void SaveEngagementTimeToPrefs();
+
+ // Called whenever engagement state is changed. Time spent in last state is
+ // accumulated to corresponding metrics.
+ void UpdateEngagementTime();
+
+ // Records accumulated engagement time metrics to UMA if necessary (i.e. day
+ // has changed).
+ void RecordEngagementTimeToUmaIfNeeded();
+
+ // Resets accumulated engagement times to zero, and updates both OS version
+ // and day ID.
+ void ResetEngagementTimePrefs();
+
+ bool ShouldAccumulateEngagementTotalTime() const;
+ bool ShouldAccumulateEngagementForegroundTime() const;
+ bool ShouldAccumulateEngagementBackgroundTime() const;
+
+ bool ShouldRecordEngagementTimeToUma() const;
+
+ PrefService* const pref_service_;
+
+ WindowMatcher window_matcher_;
+ std::string pref_prefix_;
+ std::string uma_name_;
+
+ // |clock_| is used for determining when to log to UMA, while |tick_clock_|
+ // is used to calculate elapsed time.
+ const base::Clock* clock_;
+ const base::TickClock* tick_clock_;
+ base::RepeatingTimer update_engagement_time_timer_;
+ base::RepeatingTimer save_engagement_time_to_prefs_timer_;
+ base::TimeTicks last_update_ticks_;
+
+ // States for determining which engagement metrics should we accumulate to.
+ bool session_active_ = false;
+ bool screen_dimmed_ = false;
+ bool background_active_ = false;
+ bool matched_window_active_ = false;
+
+ // Accumulated results and associated state which are saved to profile
+ // preferences at fixed interval.
+ int day_id_ = 0;
+ base::TimeDelta engagement_time_total_;
+ base::TimeDelta engagement_time_foreground_;
+ base::TimeDelta engagement_time_background_;
+
+ DISALLOW_COPY_AND_ASSIGN(GuestOsEngagementMetrics);
+};
+
+} // namespace guest_os
+
+#endif // COMPONENTS_GUEST_OS_GUEST_OS_ENGAGEMENT_METRICS_H_
diff --git a/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc b/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc
new file mode 100644
index 00000000000..cb44d320ec5
--- /dev/null
+++ b/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc
@@ -0,0 +1,220 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/guest_os/guest_os_engagement_metrics.h"
+
+#include <algorithm>
+#include <string>
+#include <utility>
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/idle.pb.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
+#include "components/guest_os/guest_os_prefs.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/test/test_windows.h"
+
+namespace guest_os {
+namespace {
+
+constexpr char kUmaName[] = "Foo";
+constexpr char kPrefPrefix[] = "Bar";
+
+constexpr char kHistogramTotal[] = "Total";
+constexpr char kHistogramForeground[] = "Foreground";
+constexpr char kHistogramBackground[] = "Background";
+constexpr char kHistogramActiveTotal[] = "FooTotal";
+
+class GuestOsEngagementMetricsTest : public testing::Test {
+ protected:
+ GuestOsEngagementMetricsTest() = default;
+
+ void SetUp() override {
+ chromeos::PowerManagerClient::InitializeFake();
+ chromeos::SessionManagerClient::InitializeFakeInMemory();
+ pref_service_ = std::make_unique<TestingPrefServiceSimple>();
+
+ matched_window_.reset(aura::test::CreateTestWindowWithId(0, nullptr));
+ non_matched_window_.reset(aura::test::CreateTestWindowWithId(0, nullptr));
+
+ prefs::RegisterEngagementProfilePrefs(pref_service_->registry(),
+ kPrefPrefix);
+ engagement_metrics_ = std::make_unique<GuestOsEngagementMetrics>(
+ pref_service_.get(),
+ base::BindRepeating(&GuestOsEngagementMetricsTest::MatchWindow,
+ base::Unretained(this)),
+ kPrefPrefix, kUmaName);
+
+ // The code doesn't work for correctly for a clock just at the epoch so
+ // advance by a day first.
+ test_clock_.Advance(base::TimeDelta::FromDays(1));
+ engagement_metrics_->SetClocksForTesting(&test_clock_, &test_tick_clock_);
+ SetSessionState(session_manager::SessionState::ACTIVE);
+ }
+
+ void TearDown() override {
+ engagement_metrics_.reset();
+ non_matched_window_.reset();
+ matched_window_.reset();
+ pref_service_.reset();
+ chromeos::SessionManagerClient::Shutdown();
+ chromeos::PowerManagerClient::Shutdown();
+ }
+
+ GuestOsEngagementMetrics* engagement_metrics() {
+ return engagement_metrics_.get();
+ }
+
+ void SetSessionState(session_manager::SessionState state) {
+ session_manager_.SetSessionState(state);
+ }
+
+ void SetScreenDimmed(bool is_screen_dimmed) {
+ power_manager::ScreenIdleState screen_idle_state;
+ screen_idle_state.set_dimmed(is_screen_dimmed);
+ static_cast<chromeos::FakePowerManagerClient*>(
+ chromeos::PowerManagerClient::Get())
+ ->SendScreenIdleStateChanged(screen_idle_state);
+ }
+
+ void AdvanceSeconds(int seconds) {
+ test_tick_clock_.Advance(base::TimeDelta::FromSeconds(seconds));
+ }
+
+ void FocusMatchedWindow() {
+ engagement_metrics()->OnWindowActivated(
+ wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
+ matched_window_.get(), nullptr);
+ }
+
+ void FocusNonMatchedWindow() {
+ engagement_metrics()->OnWindowActivated(
+ wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
+ non_matched_window_.get(), nullptr);
+ }
+
+ void TriggerRecordEngagementTimeToUma() {
+ // Trigger UMA record by changing to next day.
+ test_clock_.Advance(base::TimeDelta::FromDays(1));
+ engagement_metrics_->OnSessionStateChanged();
+ }
+
+ void ExpectTime(const std::string& histogram, int seconds) {
+ tester_.ExpectTimeBucketCount("Foo.EngagementTime." + histogram,
+ base::TimeDelta::FromSeconds(seconds), 1);
+ }
+
+ private:
+ bool MatchWindow(const aura::Window* window) {
+ return window == matched_window_.get();
+ }
+
+ content::BrowserTaskEnvironment task_environment_;
+ session_manager::SessionManager session_manager_;
+
+ base::SimpleTestTickClock test_tick_clock_;
+ base::SimpleTestClock test_clock_;
+
+ base::HistogramTester tester_;
+
+ std::unique_ptr<TestingPrefServiceSimple> pref_service_;
+
+ std::unique_ptr<aura::Window> matched_window_;
+ std::unique_ptr<aura::Window> non_matched_window_;
+
+ std::unique_ptr<GuestOsEngagementMetrics> engagement_metrics_;
+
+ DISALLOW_COPY_AND_ASSIGN(GuestOsEngagementMetricsTest);
+};
+
+TEST_F(GuestOsEngagementMetricsTest, RecordEngagementTimeSessionLocked) {
+ SetSessionState(session_manager::SessionState::LOCKED);
+ AdvanceSeconds(1);
+ SetSessionState(session_manager::SessionState::ACTIVE);
+ AdvanceSeconds(5);
+ SetSessionState(session_manager::SessionState::LOCKED);
+ AdvanceSeconds(10);
+
+ TriggerRecordEngagementTimeToUma();
+ ExpectTime(kHistogramTotal, 5);
+ ExpectTime(kHistogramForeground, 0);
+ ExpectTime(kHistogramBackground, 0);
+ ExpectTime(kHistogramActiveTotal, 0);
+}
+
+TEST_F(GuestOsEngagementMetricsTest, RecordEngagementTimeScreenDimmed) {
+ SetScreenDimmed(true);
+ AdvanceSeconds(1);
+ SetScreenDimmed(false);
+ AdvanceSeconds(5);
+ SetScreenDimmed(true);
+ AdvanceSeconds(10);
+
+ TriggerRecordEngagementTimeToUma();
+ ExpectTime(kHistogramTotal, 5);
+ ExpectTime(kHistogramForeground, 0);
+ ExpectTime(kHistogramBackground, 0);
+ ExpectTime(kHistogramActiveTotal, 0);
+}
+
+TEST_F(GuestOsEngagementMetricsTest, RecordEngagementTimeChangeFocus) {
+ FocusMatchedWindow();
+ AdvanceSeconds(2);
+ FocusNonMatchedWindow();
+ AdvanceSeconds(4);
+ FocusMatchedWindow();
+ AdvanceSeconds(10);
+ FocusNonMatchedWindow();
+ AdvanceSeconds(20);
+
+ // No background time is recorded as background activity is based on calls to
+ // SetBackgroundActive and not background windows.
+ TriggerRecordEngagementTimeToUma();
+ ExpectTime(kHistogramTotal, 36);
+ ExpectTime(kHistogramForeground, 12);
+ ExpectTime(kHistogramBackground, 0);
+ ExpectTime(kHistogramActiveTotal, 12);
+}
+
+TEST_F(GuestOsEngagementMetricsTest, RecordEngagementTimeBackgroundActive) {
+ AdvanceSeconds(10);
+ engagement_metrics()->SetBackgroundActive(true);
+ AdvanceSeconds(5);
+ engagement_metrics()->SetBackgroundActive(false);
+ AdvanceSeconds(1);
+
+ TriggerRecordEngagementTimeToUma();
+ ExpectTime(kHistogramTotal, 16);
+ ExpectTime(kHistogramForeground, 0);
+ ExpectTime(kHistogramBackground, 5);
+ ExpectTime(kHistogramActiveTotal, 5);
+}
+
+TEST_F(GuestOsEngagementMetricsTest,
+ RecordEngagementTimeBackgroundAndForeground) {
+ AdvanceSeconds(1);
+ engagement_metrics()->SetBackgroundActive(true);
+ AdvanceSeconds(2);
+ FocusMatchedWindow();
+ AdvanceSeconds(4);
+ FocusNonMatchedWindow();
+ AdvanceSeconds(10);
+ engagement_metrics()->SetBackgroundActive(false);
+ AdvanceSeconds(20);
+
+ TriggerRecordEngagementTimeToUma();
+ ExpectTime(kHistogramTotal, 37);
+ ExpectTime(kHistogramForeground, 4);
+ ExpectTime(kHistogramBackground, 12);
+ ExpectTime(kHistogramActiveTotal, 16);
+}
+
+} // namespace
+} // namespace guest_os
diff --git a/chromium/components/guest_os/guest_os_prefs.cc b/chromium/components/guest_os/guest_os_prefs.cc
new file mode 100644
index 00000000000..4211807387e
--- /dev/null
+++ b/chromium/components/guest_os/guest_os_prefs.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 "components/guest_os/guest_os_prefs.h"
+
+#include "components/prefs/pref_registry_simple.h"
+
+namespace guest_os {
+namespace prefs {
+
+// The following prefs (nested under a provided location, e.g. arc.metrics)
+// persist engagement time across sessions, to be accumulated and sent to UMA
+// once a day.
+
+// Total engagement time of the device.
+const char kEngagementTimeTotal[] = ".engagement_time.total";
+// Time spent with a matched window in the foreground.
+const char kEngagementTimeForeground[] = ".engagement_time.foreground";
+// Time spent without a matched window in the foreground but the guest OS
+// otherwise running in the background.
+const char kEngagementTimeBackground[] = ".engagement_time.background";
+// The OS version when engagement prefs were recorded. Old results will be
+// discarded if a version change is detected.
+const char kEngagementTimeOsVersion[] = ".engagement_time.os_version";
+// The day ID (number of days since origin of Time) when engagement time was
+// last recorded.
+const char kEngagementTimeDayId[] = ".engagement_time.day_id";
+
+void RegisterEngagementProfilePrefs(PrefRegistrySimple* registry,
+ const std::string& pref_prefix) {
+ registry->RegisterTimeDeltaPref(pref_prefix + kEngagementTimeBackground,
+ base::TimeDelta());
+ registry->RegisterIntegerPref(pref_prefix + kEngagementTimeDayId, 0);
+ registry->RegisterTimeDeltaPref(pref_prefix + kEngagementTimeForeground,
+ base::TimeDelta());
+ registry->RegisterStringPref(pref_prefix + kEngagementTimeOsVersion, "");
+ registry->RegisterTimeDeltaPref(pref_prefix + kEngagementTimeTotal,
+ base::TimeDelta());
+}
+
+} // namespace prefs
+} // namespace guest_os
diff --git a/chromium/components/guest_os/guest_os_prefs.h b/chromium/components/guest_os/guest_os_prefs.h
new file mode 100644
index 00000000000..9c43041449d
--- /dev/null
+++ b/chromium/components/guest_os/guest_os_prefs.h
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_GUEST_OS_GUEST_OS_PREFS_H_
+#define COMPONENTS_GUEST_OS_GUEST_OS_PREFS_H_
+
+#include <string>
+
+class PrefRegistrySimple;
+
+namespace guest_os {
+namespace prefs {
+
+extern const char kEngagementTimeTotal[];
+extern const char kEngagementTimeForeground[];
+extern const char kEngagementTimeBackground[];
+extern const char kEngagementTimeOsVersion[];
+extern const char kEngagementTimeDayId[];
+
+// Registers prefs used by GuestOsEngagementMetrics.
+void RegisterEngagementProfilePrefs(PrefRegistrySimple* registry,
+ const std::string& pref_prefix);
+
+} // namespace prefs
+} // namespace guest_os
+
+#endif // COMPONENTS_GUEST_OS_GUEST_OS_PREFS_H_
diff --git a/chromium/components/gwp_asan/BUILD.gn b/chromium/components/gwp_asan/BUILD.gn
index 5176c8cef6e..47299f882a6 100644
--- a/chromium/components/gwp_asan/BUILD.gn
+++ b/chromium/components/gwp_asan/BUILD.gn
@@ -2,12 +2,19 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("unit_tests") {
+import("//testing/test.gni")
+
+# Defined as a separate target so that on Android tests can be launched in a
+# sub-thread instead of on the main thread to support multi-process tests.
+# Can be removed after minSdkVersion >= Q
+test("gwp_asan_unittests") {
testonly = true
deps = [
+ "//base/test:run_all_unittests",
"//components/gwp_asan/common:unit_tests",
+ "//testing/gtest",
]
- if (is_win || is_mac) {
+ if (is_win || is_mac || is_linux || is_android) {
deps += [
"//components/gwp_asan/client:unit_tests",
"//components/gwp_asan/crash_handler:unit_tests",
diff --git a/chromium/components/gwp_asan/OWNERS b/chromium/components/gwp_asan/OWNERS
index 57999e8662d..26e52daa09b 100644
--- a/chromium/components/gwp_asan/OWNERS
+++ b/chromium/components/gwp_asan/OWNERS
@@ -1,2 +1,3 @@
vitalybuka@chromium.org
vtsyrklevich@chromium.org
+# COMPONENT: Internals>Instrumentation
diff --git a/chromium/components/gwp_asan/buildflags/buildflags.gni b/chromium/components/gwp_asan/buildflags/buildflags.gni
index c6ad77df6bd..08ed1d4dbe3 100644
--- a/chromium/components/gwp_asan/buildflags/buildflags.gni
+++ b/chromium/components/gwp_asan/buildflags/buildflags.gni
@@ -2,10 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//base/allocator/allocator.gni")
import("//build/config/allocator.gni")
# Windows/x86 is disabled due to https://crbug.com/969146
-supported_platform = is_mac || (is_win && current_cpu == "x64")
+# Android component builds are disabled due to https://crbug.com/976399
+supported_platform = is_mac || (is_win && current_cpu == "x64") ||
+ (is_android && !is_component_build)
declare_args() {
# Is GWP-ASan malloc/PartitionAlloc hooking enabled for chrome/ on a given
diff --git a/chromium/components/gwp_asan/client/BUILD.gn b/chromium/components/gwp_asan/client/BUILD.gn
index 6769a8e3485..8145cf741fa 100644
--- a/chromium/components/gwp_asan/client/BUILD.gn
+++ b/chromium/components/gwp_asan/client/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//base/allocator/allocator.gni")
import("//build/config/allocator.gni")
component("client") {
@@ -44,6 +45,10 @@ component("client") {
"//components/crash/core/common:crash_key",
"//components/gwp_asan/common",
]
+
+ if (is_android) {
+ deps += [ "//components/crash/content/app" ]
+ }
}
source_set("unit_tests") {
diff --git a/chromium/components/gwp_asan/client/DEPS b/chromium/components/gwp_asan/client/DEPS
index 90e574cf755..24a317705f7 100644
--- a/chromium/components/gwp_asan/client/DEPS
+++ b/chromium/components/gwp_asan/client/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+components/crash/core/common/crash_key.h",
+ "+components/crash/content/app/crashpad.h",
]
diff --git a/chromium/components/gwp_asan/client/guarded_page_allocator.cc b/chromium/components/gwp_asan/client/guarded_page_allocator.cc
index 2a9cdb56d12..ee8d512c004 100644
--- a/chromium/components/gwp_asan/client/guarded_page_allocator.cc
+++ b/chromium/components/gwp_asan/client/guarded_page_allocator.cc
@@ -21,6 +21,10 @@
#include "components/gwp_asan/common/crash_key_name.h"
#include "components/gwp_asan/common/pack_stack_trace.h"
+#if defined(OS_ANDROID)
+#include "components/crash/content/app/crashpad.h" // nogncheck
+#endif
+
#if defined(OS_MACOSX)
#include <pthread.h>
#endif
@@ -166,6 +170,27 @@ void GuardedPageAllocator::Init(size_t max_alloced_pages,
metadata_ =
std::make_unique<AllocatorState::SlotMetadata[]>(state_.num_metadata);
state_.metadata_addr = reinterpret_cast<uintptr_t>(metadata_.get());
+
+#if defined(OS_ANDROID)
+ // Explicitly whitelist memory ranges the crash_handler needs to reads. This
+ // is required for WebView because it has a stricter set of privacy
+ // constraints on what it reads from the crashing process.
+ for (auto& region : GetInternalMemoryRegions())
+ crash_reporter::WhitelistMemoryRange(region.first, region.second);
+#endif
+}
+
+std::vector<std::pair<void*, size_t>>
+GuardedPageAllocator::GetInternalMemoryRegions() {
+ std::vector<std::pair<void*, size_t>> regions;
+ regions.push_back(std::make_pair(&state_, sizeof(state_)));
+ regions.push_back(std::make_pair(
+ metadata_.get(),
+ sizeof(AllocatorState::SlotMetadata) * state_.num_metadata));
+ regions.push_back(
+ std::make_pair(slot_to_metadata_idx_.data(),
+ sizeof(AllocatorState::MetadataIdx) * state_.total_pages));
+ return regions;
}
GuardedPageAllocator::~GuardedPageAllocator() {
diff --git a/chromium/components/gwp_asan/client/guarded_page_allocator.h b/chromium/components/gwp_asan/client/guarded_page_allocator.h
index 6292e59b5b2..2709754dfa0 100644
--- a/chromium/components/gwp_asan/client/guarded_page_allocator.h
+++ b/chromium/components/gwp_asan/client/guarded_page_allocator.h
@@ -84,6 +84,10 @@ class GWP_ASAN_EXPORT GuardedPageAllocator {
// crash handler.
std::string GetCrashKey() const;
+ // Returns internal memory used by the allocator (required for sanitization
+ // on supported platforms.)
+ std::vector<std::pair<void*, size_t>> GetInternalMemoryRegions();
+
// Returns true if ptr points to memory managed by this class.
inline bool PointerIsMine(const void* ptr) const {
return state_.PointerIsMine(reinterpret_cast<uintptr_t>(ptr));
diff --git a/chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc b/chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc
index 5633ffd3278..dfdfc8c48ab 100644
--- a/chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc
+++ b/chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc
@@ -289,7 +289,11 @@ class ThreadedHighContentionDelegate
// Test that allocator remains in consistent state under high contention and
// doesn't double-allocate pages or fail to deallocate pages.
TEST_P(GuardedPageAllocatorTest, ThreadedHighContention) {
+#if defined(OS_ANDROID)
+ constexpr size_t num_threads = 200;
+#else
constexpr size_t num_threads = 1000;
+#endif
{
base::DelegateSimpleThreadPool threads("page_writers", num_threads);
threads.Start();
diff --git a/chromium/components/gwp_asan/client/sampling_state.h b/chromium/components/gwp_asan/client/sampling_state.h
index 1728a7a6397..48e698491f0 100644
--- a/chromium/components/gwp_asan/client/sampling_state.h
+++ b/chromium/components/gwp_asan/client/sampling_state.h
@@ -6,6 +6,8 @@
#define COMPONENTS_GWP_ASAN_CLIENT_SAMPLING_STATE_H_
#include <stddef.h> // for size_t
+#include <limits>
+#include <random>
#include "base/compiler_specific.h"
#include "base/rand_util.h"
@@ -36,7 +38,7 @@ class SamplingState {
void Init(size_t sampling_frequency) {
DCHECK_GT(sampling_frequency, 0U);
- sampling_frequency_ = sampling_frequency;
+ sampling_probability_ = 1.0 / sampling_frequency;
#if defined(USE_PTHREAD_TLS)
pthread_key_create(&tls_key_, nullptr);
@@ -60,16 +62,12 @@ class SamplingState {
}
private:
- // Sample a single allocations in every chunk of |sampling_frequency_|
- // allocations.
- //
- // TODO(https://crbug.com/919207): Replace with std::geometric_distribution
- // once the LLVM floating point codegen issue in the linked bug is fixed.
+ // Sample an allocation on every average one out of every
+ // |sampling_frequency_| allocations.
size_t NextSample() {
- size_t random = base::RandInt(1, sampling_frequency_ + 1);
- size_t next_sample = increment_ + random;
- increment_ = sampling_frequency_ + 1 - random;
- return next_sample;
+ base::RandomBitGenerator generator;
+ std::geometric_distribution<size_t> distribution(sampling_probability_);
+ return distribution(generator) + 1;
}
#if !defined(USE_PTHREAD_TLS)
@@ -96,11 +94,7 @@ class SamplingState {
pthread_key_t tls_key_ = 0;
#endif
- size_t sampling_frequency_ = 0;
-
- // Stores the number of allocations we need to skip to reach the end of the
- // current chunk of |sampling_frequency_| allocations.
- size_t increment_ = 0;
+ double sampling_probability_ = 0;
};
#if !defined(USE_PTHREAD_TLS)
diff --git a/chromium/components/gwp_asan/common/allocator_state.h b/chromium/components/gwp_asan/common/allocator_state.h
index f9b79e610f6..a04d8796c09 100644
--- a/chromium/components/gwp_asan/common/allocator_state.h
+++ b/chromium/components/gwp_asan/common/allocator_state.h
@@ -39,14 +39,14 @@ class GuardedPageAllocator;
class AllocatorState {
public:
- using MetadataIdx = uint8_t;
+ using MetadataIdx = uint16_t;
using SlotIdx = uint16_t;
// Maximum number of virtual memory slots (guard-page buffered pages) this
// class can allocate.
static constexpr size_t kMaxSlots = 4096;
// Maximum number of concurrent allocations/metadata this class can allocate.
- static constexpr size_t kMaxMetadata = 255;
+ static constexpr size_t kMaxMetadata = 2048;
// Invalid metadata index.
static constexpr MetadataIdx kInvalidMetadataIdx = kMaxMetadata;
diff --git a/chromium/components/gwp_asan/common/crash_key_name.h b/chromium/components/gwp_asan/common/crash_key_name.h
index bbd76279161..7fe5fc5c7bf 100644
--- a/chromium/components/gwp_asan/common/crash_key_name.h
+++ b/chromium/components/gwp_asan/common/crash_key_name.h
@@ -6,14 +6,12 @@
#define COMPONENTS_GWP_ASAN_COMMON_CRASH_KEY_NAME_H_
namespace gwp_asan {
-namespace internal {
// The name of the crash key used to convey the address of the AllocatorState
// for the malloc/PartitionAlloc hooks to the crash handler.
const char kMallocCrashKey[] = "gwp-asan-malloc";
const char kPartitionAllocCrashKey[] = "gwp-asan-partitionalloc";
-} // namespace internal
} // namespace gwp_asan
#endif // COMPONENTS_GWP_ASAN_COMMON_CRASH_KEY_NAME_H_
diff --git a/chromium/components/gwp_asan/crash_handler/BUILD.gn b/chromium/components/gwp_asan/crash_handler/BUILD.gn
index 466c06ffd48..c9aa26ffd9d 100644
--- a/chromium/components/gwp_asan/crash_handler/BUILD.gn
+++ b/chromium/components/gwp_asan/crash_handler/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//components/gwp_asan/buildflags/buildflags.gni")
import("//third_party/protobuf/proto_library.gni")
static_library("crash_handler") {
@@ -35,8 +36,8 @@ source_set("unit_tests") {
testonly = true
sources = [
"crash_analyzer_unittest.cc",
- "crash_handler_unittest.cc",
]
+
deps = [
":crash_handler",
":crash_proto",
@@ -46,13 +47,28 @@ source_set("unit_tests") {
"//testing/gmock",
"//testing/gtest",
"//third_party/crashpad/crashpad/client",
- "//third_party/crashpad/crashpad/handler",
- "//third_party/crashpad/crashpad/minidump",
"//third_party/crashpad/crashpad/snapshot",
"//third_party/crashpad/crashpad/snapshot:test_support",
"//third_party/crashpad/crashpad/test",
- "//third_party/crashpad/crashpad/tools:tool_support",
"//third_party/crashpad/crashpad/util",
"//third_party/protobuf:protobuf_lite",
]
+
+ if (!is_android || enable_gwp_asan) {
+ sources += [ "crash_handler_unittest.cc" ]
+ deps += [
+ "//third_party/crashpad/crashpad/handler",
+ "//third_party/crashpad/crashpad/minidump",
+ "//third_party/crashpad/crashpad/tools:tool_support",
+ ]
+
+ if (is_android) {
+ metadata = {
+ shared_libraries = [ "$root_out_dir/libchrome_crashpad_handler.so" ]
+ }
+ deps += [
+ "//components/crash/content/app:chrome_crashpad_handler_named_as_so",
+ ]
+ }
+ }
}
diff --git a/chromium/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc b/chromium/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc
index 2e8da2dbcf5..6fe4900c0bb 100644
--- a/chromium/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc
+++ b/chromium/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc
@@ -137,12 +137,6 @@ TEST_F(CrashAnalyzerTest, StackTraceCollection) {
proto.deallocation().stack_trace_size() - i),
reinterpret_cast<uintptr_t>(trace[trace_len - i]));
}
-
- // Allocate() and Deallocate() were called from different points in this test.
- ASSERT_NE(proto.allocation().stack_trace(
- proto.allocation().stack_trace_size() - (trace_len + 1)),
- proto.deallocation().stack_trace(
- proto.deallocation().stack_trace_size() - (trace_len + 1)));
}
TEST_F(CrashAnalyzerTest, InternalError) {
diff --git a/chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc b/chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc
index f658bc58ccb..f22e5e6dd8f 100644
--- a/chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc
+++ b/chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc
@@ -14,6 +14,7 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/no_destructor.h"
+#include "base/path_service.h"
#include "base/process/process_metrics.h"
#include "base/strings/stringprintf.h"
#include "base/test/gtest_util.h"
@@ -33,6 +34,10 @@
#include "third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump.h"
#include "third_party/crashpad/crashpad/tools/tool_support.h"
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+#include "third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information.h"
+#endif
+
namespace gwp_asan {
namespace internal {
@@ -42,6 +47,7 @@ constexpr size_t kAllocationSize = 902;
constexpr int kSuccess = 0;
constexpr size_t kTotalPages = AllocatorState::kMaxSlots;
+#if !defined(OS_ANDROID)
int HandlerMainAdaptor(int argc, char* argv[]) {
crashpad::UserStreamDataSources user_stream_data_sources;
user_stream_data_sources.push_back(
@@ -74,6 +80,7 @@ MULTIPROCESS_TEST_MAIN(CrashpadHandler) {
return 0;
}
+#endif // !defined(OS_ANDROID)
// Child process that launches the crashpad handler and then crashes.
MULTIPROCESS_TEST_MAIN(CrashingProcess) {
@@ -114,9 +121,64 @@ MULTIPROCESS_TEST_MAIN(CrashingProcess) {
base::FilePath metrics_dir(FILE_PATH_LITERAL(""));
std::map<std::string, std::string> annotations;
std::vector<std::string> arguments;
+
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+ static crashpad::SanitizationInformation sanitization_info = {};
+ static crashpad::SanitizationMemoryRangeWhitelist memory_whitelist;
+ if (cmd_line->HasSwitch("sanitize")) {
+ auto memory_ranges = gpa->GetInternalMemoryRegions();
+ auto* range_array =
+ new crashpad::SanitizationMemoryRangeWhitelist::Range[memory_ranges
+ .size()];
+ for (size_t i = 0; i < memory_ranges.size(); i++) {
+ range_array[i].base =
+ reinterpret_cast<crashpad::VMAddress>(memory_ranges[i].first);
+ range_array[i].length = memory_ranges[i].second;
+ }
+ memory_whitelist.size = memory_ranges.size();
+ memory_whitelist.entries =
+ reinterpret_cast<crashpad::VMAddress>(range_array);
+ sanitization_info.memory_range_whitelist_address =
+ reinterpret_cast<crashpad::VMAddress>(&memory_whitelist);
+ arguments.push_back(base::StringPrintf("--sanitization-information=%p",
+ &sanitization_info));
+ }
+#endif
+
+#if !defined(OS_ANDROID)
arguments.push_back("--test-child-process=CrashpadHandler");
+#endif
crashpad::CrashpadClient* client = new crashpad::CrashpadClient();
+#if defined(OS_LINUX)
+ bool handler =
+ client->StartHandlerAtCrash(/* handler */ cmd_line->GetProgram(),
+ /* database */ directory,
+ /* metrics_dir */ metrics_dir,
+ /* url */ "",
+ /* annotations */ annotations,
+ /* arguments */ arguments);
+#elif defined(OS_ANDROID)
+ // TODO: Once the minSdkVersion is >= Q define a CrashpadHandlerMain() and
+ // use the /system/bin/linker approach instead of using
+ // libchrome_crashpad_handler.so
+ base::FilePath modules;
+ if (!base::PathService::Get(base::DIR_MODULE, &modules)) {
+ LOG(ERROR) << "Failed to read DIR_MODULE";
+ return kSuccess;
+ }
+
+ base::FilePath executable_path =
+ modules.AppendASCII("libchrome_crashpad_handler.so");
+
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ std::string library_path;
+ env->GetVar("LD_LIBRARY_PATH", &library_path);
+ env->SetVar("LD_LIBRARY_PATH", library_path + ":" + modules.value());
+
+ bool handler = client->StartHandlerAtCrash(
+ executable_path, directory, metrics_dir, "", annotations, arguments);
+#else
bool handler = client->StartHandler(/* handler */ cmd_line->GetProgram(),
/* database */ directory,
/* metrics_dir */ metrics_dir,
@@ -125,6 +187,8 @@ MULTIPROCESS_TEST_MAIN(CrashingProcess) {
/* arguments */ arguments,
/* restartable */ false,
/* asynchronous_start */ false);
+#endif
+
if (!handler) {
LOG(ERROR) << "Crash handler failed to launch";
return kSuccess;
@@ -179,10 +243,18 @@ MULTIPROCESS_TEST_MAIN(CrashingProcess) {
return kSuccess;
}
+struct TestParams {
+ TestParams(const char* allocator, bool sanitize)
+ : allocator(allocator), sanitize(sanitize) {}
+
+ const char* allocator;
+ bool sanitize;
+};
+
class CrashHandlerTest : public base::MultiProcessTest,
- public testing::WithParamInterface<const char*> {
+ public testing::WithParamInterface<TestParams> {
protected:
- CrashHandlerTest() : allocator_(GetParam()) {}
+ CrashHandlerTest() : params_(GetParam()) {}
// Launch a child process and wait for it to crash. Set |gwp_asan_found_| if a
// GWP-ASan data was found and if so, read it into |proto_|.
@@ -214,7 +286,10 @@ class CrashHandlerTest : public base::MultiProcessTest,
base::GetMultiProcessTestChildBaseCommandLine();
cmd_line.AppendSwitchPath("directory", database_dir);
cmd_line.AppendSwitchASCII("test-name", test_name);
- cmd_line.AppendSwitchASCII("allocator", allocator_);
+ cmd_line.AppendSwitchASCII("allocator", params_.allocator);
+
+ if (params_.sanitize)
+ cmd_line.AppendSwitch("sanitize");
base::LaunchOptions options;
#if defined(OS_WIN)
@@ -223,12 +298,23 @@ class CrashHandlerTest : public base::MultiProcessTest,
base::Process process =
base::SpawnMultiProcessTestChild("CrashingProcess", cmd_line, options);
+#if !defined(OS_ANDROID)
int exit_code = -1;
EXPECT_TRUE(WaitForMultiprocessTestChildExit(
process, TestTimeouts::action_max_timeout(), &exit_code));
EXPECT_NE(exit_code, kSuccess);
-
return (exit_code != kSuccess);
+#else
+ // TODO(https://crbug.com/976063): Android's implementation of
+ // WaitForMultiprocessTestChildExit can't detect child process crashes, this
+ // can be fixed after minSdkVersion >= Q.
+ for (int i = 0; i < TestTimeouts::action_max_timeout().InSeconds(); i++) {
+ if (kill(process.Pid(), 0) && errno == ESRCH)
+ return true;
+ sleep(1);
+ }
+ return false;
+#endif
}
// Given a directory with a single crashpad exception, read and parse the
@@ -303,25 +389,25 @@ class CrashHandlerTest : public base::MultiProcessTest,
EXPECT_FALSE(proto_.missing_metadata());
EXPECT_TRUE(proto_.has_allocator());
- if (allocator_ == "malloc")
+ if (!strcmp(params_.allocator, "malloc"))
EXPECT_EQ(proto_.allocator(), Crash_Allocator_MALLOC);
- else if (allocator_ == "partitionalloc")
+ else if (!strcmp(params_.allocator, "partitionalloc"))
EXPECT_EQ(proto_.allocator(), Crash_Allocator_PARTITIONALLOC);
else
ASSERT_TRUE(false) << "Unknown allocator name";
}
gwp_asan::Crash proto_;
- std::string allocator_;
+ TestParams params_;
bool gwp_asan_found_;
};
-#if defined(ADDRESS_SANITIZER) && defined(OS_WIN)
+#if defined(ADDRESS_SANITIZER) && (defined(OS_WIN) || defined(OS_ANDROID))
// ASan intercepts crashes and crashpad doesn't have a chance to see them.
#define MAYBE_DISABLED(name) DISABLED_ ##name
#else
#define MAYBE_DISABLED(name) name
-#endif // defined(ADDRESS_SANITIZER) && defined(OS_WIN)
+#endif
TEST_P(CrashHandlerTest, MAYBE_DISABLED(UseAfterFree)) {
ASSERT_TRUE(gwp_asan_found_);
@@ -371,7 +457,12 @@ TEST_P(CrashHandlerTest, MAYBE_DISABLED(UnrelatedException)) {
INSTANTIATE_TEST_SUITE_P(VaryAllocator,
CrashHandlerTest,
- testing::Values("malloc", "partitionalloc"));
+ testing::Values(
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+ TestParams("malloc", true),
+#endif
+ TestParams("malloc", false),
+ TestParams("partitionalloc", false)));
} // namespace
diff --git a/chromium/components/handoff/OWNERS b/chromium/components/handoff/OWNERS
index 987c0c88a4a..7f61da0991c 100644
--- a/chromium/components/handoff/OWNERS
+++ b/chromium/components/handoff/OWNERS
@@ -1 +1,3 @@
erikchen@chromium.org
+ellyjones@chromium.org
+# COMPONENT: UI>Browser
diff --git a/chromium/components/heap_profiling/BUILD.gn b/chromium/components/heap_profiling/BUILD.gn
index 7650cc81d12..19cada146a8 100644
--- a/chromium/components/heap_profiling/BUILD.gn
+++ b/chromium/components/heap_profiling/BUILD.gn
@@ -16,6 +16,7 @@ static_library("heap_profiling") {
deps = [
"//base",
+ "//components/services/heap_profiling",
"//components/services/heap_profiling/public/cpp",
"//content/public/browser",
"//content/public/common",
diff --git a/chromium/components/heap_profiling/DEPS b/chromium/components/heap_profiling/DEPS
index 8d9b92bc977..06e4ca6fa06 100644
--- a/chromium/components/heap_profiling/DEPS
+++ b/chromium/components/heap_profiling/DEPS
@@ -1,6 +1,8 @@
include_rules = [
+ "+components/services/heap_profiling/heap_profiling_service.h",
"+components/services/heap_profiling/public",
"+content/public",
- "+services/resource_coordinator/public/cpp",
+ "+mojo/public",
+ "+services/resource_coordinator/public",
"+services/service_manager/public/cpp",
]
diff --git a/chromium/components/heap_profiling/OWNERS b/chromium/components/heap_profiling/OWNERS
index 9cc3a5e9cd2..58b20431b03 100644
--- a/chromium/components/heap_profiling/OWNERS
+++ b/chromium/components/heap_profiling/OWNERS
@@ -1,2 +1,3 @@
alph@chromium.org
erikchen@chromium.org
+# COMPONENT: Internals>Instrumentation>Memory
diff --git a/chromium/components/heap_profiling/client_connection_manager.cc b/chromium/components/heap_profiling/client_connection_manager.cc
index 1c5d77ab450..5f51d9e985c 100644
--- a/chromium/components/heap_profiling/client_connection_manager.cc
+++ b/chromium/components/heap_profiling/client_connection_manager.cc
@@ -24,39 +24,13 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/process_type.h"
#include "content/public/common/service_names.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/service_manager/public/cpp/connector.h"
namespace heap_profiling {
namespace {
-// This helper class cleans up initialization boilerplate for the callers who
-// need to create ProfilingClients bound to various different things.
-class ProfilingClientBinder {
- public:
- // Binds to a non-renderer-child-process' ProfilingClient.
- explicit ProfilingClientBinder(content::BrowserChildProcessHost* host)
- : ProfilingClientBinder() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- content::BindInterface(host->GetHost(), std::move(request_));
- }
-
- // Binds to a renderer's ProfilingClient.
- explicit ProfilingClientBinder(content::RenderProcessHost* host)
- : ProfilingClientBinder() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- content::BindInterface(host, std::move(request_));
- }
-
- mojom::ProfilingClientPtr take() { return std::move(memlog_client_); }
-
- private:
- ProfilingClientBinder() : request_(mojo::MakeRequest(&memlog_client_)) {}
-
- mojom::ProfilingClientPtr memlog_client_;
- mojom::ProfilingClientRequest request_;
-};
-
bool ShouldProfileNonRendererProcessType(Mode mode, int process_type) {
switch (mode) {
case Mode::kAll:
@@ -124,21 +98,23 @@ void StartProfilingNonRendererChildOnIOThread(
: mojom::ProcessType::OTHER;
// Tell the child process to start profiling.
- ProfilingClientBinder client(host);
- controller->StartProfilingClient(client.take(), data.GetProcess().Pid(),
+ mojo::PendingRemote<mojom::ProfilingClient> client;
+ host->GetHost()->BindReceiver(client.InitWithNewPipeAndPassReceiver());
+ controller->StartProfilingClient(std::move(client), data.GetProcess().Pid(),
process_type);
}
-void StartProfilingClientOnIOThread(base::WeakPtr<Controller> controller,
- ProfilingClientBinder client,
- base::ProcessId pid,
- mojom::ProcessType process_type) {
+void StartProfilingClientOnIOThread(
+ base::WeakPtr<Controller> controller,
+ mojo::PendingRemote<mojom::ProfilingClient> client,
+ base::ProcessId pid,
+ mojom::ProcessType process_type) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
if (!controller)
return;
- controller->StartProfilingClient(client.take(), pid, process_type);
+ controller->StartProfilingClient(std::move(client), pid, process_type);
}
void StartProfilingBrowserProcessOnIOThread(
@@ -149,9 +125,9 @@ void StartProfilingBrowserProcessOnIOThread(
return;
static base::NoDestructor<ProfilingClient> client;
- mojom::ProfilingClientPtr proxy;
- client->BindToInterface(mojo::MakeRequest(&proxy));
- controller->StartProfilingClient(std::move(proxy), base::GetCurrentProcId(),
+ mojo::PendingRemote<mojom::ProfilingClient> remote;
+ client->BindToInterface(remote.InitWithNewPipeAndPassReceiver());
+ controller->StartProfilingClient(std::move(remote), base::GetCurrentProcId(),
mojom::ProcessType::BROWSER);
}
@@ -244,7 +220,7 @@ void ClientConnectionManager::StartProfilingProcess(base::ProcessId pid) {
}
// The BrowserChildProcessHostIterator iterator must be used on the IO thread.
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(FROM_HERE, base::BindOnce(&StartProfilingPidOnIOThread,
controller_, pid));
}
@@ -265,7 +241,7 @@ void ClientConnectionManager::StartProfilingExistingProcessesIfNecessary() {
// Start profiling the current process.
if (ShouldProfileNonRendererProcessType(
mode_, content::ProcessType::PROCESS_TYPE_BROWSER)) {
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(&StartProfilingBrowserProcessOnIOThread,
controller_));
@@ -281,7 +257,7 @@ void ClientConnectionManager::StartProfilingExistingProcessesIfNecessary() {
}
}
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(
FROM_HERE,
base::BindOnce(&StartProfilingNonRenderersIfNecessaryOnIOThread,
@@ -305,7 +281,7 @@ void ClientConnectionManager::BrowserChildProcessLaunchedAndConnected(
void ClientConnectionManager::StartProfilingNonRendererChild(
const content::ChildProcessData& data) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(&StartProfilingNonRendererChildOnIOThread,
controller_, data.Duplicate()));
@@ -360,10 +336,9 @@ void ClientConnectionManager::StartProfilingRenderer(
profiled_renderers_.insert(host);
- // Tell the child process to start profiling.
- ProfilingClientBinder client(host);
-
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ mojo::PendingRemote<mojom::ProfilingClient> client;
+ host->BindReceiver(client.InitWithNewPipeAndPassReceiver());
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(&StartProfilingClientOnIOThread, controller_,
std::move(client), host->GetProcess().Pid(),
diff --git a/chromium/components/heap_profiling/supervisor.cc b/chromium/components/heap_profiling/supervisor.cc
index 712ba9bbb28..fecdbf45c60 100644
--- a/chromium/components/heap_profiling/supervisor.cc
+++ b/chromium/components/heap_profiling/supervisor.cc
@@ -9,12 +9,15 @@
#include "base/no_destructor.h"
#include "base/task/post_task.h"
#include "components/heap_profiling/client_connection_manager.h"
+#include "components/services/heap_profiling/heap_profiling_service.h"
#include "components/services/heap_profiling/public/cpp/controller.h"
#include "components/services/heap_profiling/public/cpp/settings.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
+#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace heap_profiling {
@@ -71,7 +74,7 @@ void Supervisor::Start(service_manager::Connector* connector,
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(!started_);
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(FROM_HERE, base::BindOnce(&Supervisor::StartServiceOnIOThread,
base::Unretained(this),
connector->Clone(), mode, stack_mode,
@@ -93,7 +96,7 @@ void Supervisor::GetProfiledPids(GetProfiledPidsCallback callback) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(HasStarted());
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
->PostTask(FROM_HERE,
base::BindOnce(&Supervisor::GetProfiledPidsOnIOThread,
base::Unretained(this), std::move(callback)));
@@ -127,8 +130,7 @@ void Supervisor::RequestTraceWithHeapDump(TraceFinishedCallback callback,
base::RefCountedString* in) {
std::string result;
result.swap(in->data());
- base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), true,
std::move(result)));
@@ -171,11 +173,27 @@ void Supervisor::StartServiceOnIOThread(
base::OnceClosure closure) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- controller_.reset(
- new Controller(std::move(connector), stack_mode, sampling_rate));
+ // The heap profiling service requires the injection of a few Resource
+ // Coordinator dependencies.
+ mojo::Remote<memory_instrumentation::mojom::Coordinator> coordinator;
+ connector->Connect(resource_coordinator::mojom::kServiceName,
+ coordinator.BindNewPipeAndPassReceiver());
+ mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper> helper;
+ connector->Connect(resource_coordinator::mojom::kServiceName,
+ helper.InitWithNewPipeAndPassReceiver());
+
+ memory_instrumentation::mojom::HeapProfilerPtr heap_profiler;
+ auto profiler_request = mojo::MakeRequest(&heap_profiler);
+ coordinator->RegisterHeapProfiler(std::move(heap_profiler));
+
+ mojo::PendingRemote<mojom::ProfilingService> service =
+ LaunchService(std::move(profiler_request), std::move(helper));
+
+ controller_ = std::make_unique<Controller>(std::move(service), stack_mode,
+ sampling_rate);
base::WeakPtr<Controller> controller_weak_ptr = controller_->GetWeakPtr();
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
->PostTask(FROM_HERE,
base::BindOnce(&Supervisor::FinishInitializationOnUIhread,
base::Unretained(this), mode,
@@ -208,8 +226,7 @@ void Supervisor::GetProfiledPidsOnIOThread(GetProfiledPidsCallback callback) {
auto post_result_to_ui_thread = base::BindOnce(
[](GetProfiledPidsCallback callback,
const std::vector<base::ProcessId>& result) {
- base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI})
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
->PostTask(FROM_HERE, base::BindOnce(std::move(callback), result));
},
std::move(callback));
diff --git a/chromium/components/heap_profiling/test_driver.cc b/chromium/components/heap_profiling/test_driver.cc
index a8e5ee0f192..3c73d6efbe1 100644
--- a/chromium/components/heap_profiling/test_driver.cc
+++ b/chromium/components/heap_profiling/test_driver.cc
@@ -575,10 +575,9 @@ bool TestDriver::RunTest(const Options& options) {
if (running_on_ui_thread_) {
has_started_ = Supervisor::GetInstance()->HasStarted();
} else {
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&TestDriver::GetHasStartedOnUIThread,
- base::Unretained(this)));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&TestDriver::GetHasStartedOnUIThread,
+ base::Unretained(this)));
wait_for_ui_thread_.Wait();
}
if (has_started_) {
@@ -597,7 +596,7 @@ bool TestDriver::RunTest(const Options& options) {
MakeTestAllocations();
CollectResults(true);
} else {
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&TestDriver::CheckOrStartProfilingOnUIThreadAndSignal,
base::Unretained(this)));
@@ -605,7 +604,7 @@ bool TestDriver::RunTest(const Options& options) {
if (!initialization_success_)
return false;
if (ShouldProfileRenderer()) {
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
&TestDriver::
@@ -614,13 +613,13 @@ bool TestDriver::RunTest(const Options& options) {
wait_for_ui_thread_.Wait();
}
if (ShouldProfileBrowser()) {
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&TestDriver::MakeTestAllocations,
- base::Unretained(this)));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&TestDriver::MakeTestAllocations,
+ base::Unretained(this)));
}
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&TestDriver::CollectResults,
- base::Unretained(this), false));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&TestDriver::CollectResults,
+ base::Unretained(this), false));
wait_for_ui_thread_.Wait();
}
diff --git a/chromium/components/history/core/browser/BUILD.gn b/chromium/components/history/core/browser/BUILD.gn
index 3137667d781..a9e0f520d4e 100644
--- a/chromium/components/history/core/browser/BUILD.gn
+++ b/chromium/components/history/core/browser/BUILD.gn
@@ -52,8 +52,6 @@ static_library("browser") {
"sync/delete_directive_handler.h",
"sync/history_delete_directives_model_type_controller.cc",
"sync/history_delete_directives_model_type_controller.h",
- "sync/history_model_worker.cc",
- "sync/history_model_worker.h",
"sync/typed_url_model_type_controller.cc",
"sync/typed_url_model_type_controller.h",
"sync/typed_url_sync_bridge.cc",
@@ -66,8 +64,6 @@ static_library("browser") {
"top_sites.h",
"top_sites_backend.cc",
"top_sites_backend.h",
- "top_sites_cache.cc",
- "top_sites_cache.h",
"top_sites_database.cc",
"top_sites_database.h",
"top_sites_impl.cc",
@@ -204,11 +200,9 @@ source_set("unit_tests") {
"history_service_unittest.cc",
"history_types_unittest.cc",
"sync/delete_directive_handler_unittest.cc",
- "sync/history_model_worker_unittest.cc",
"sync/typed_url_sync_bridge_unittest.cc",
"sync/typed_url_sync_metadata_database_unittest.cc",
"thumbnail_database_unittest.cc",
- "top_sites_cache_unittest.cc",
"top_sites_database_unittest.cc",
"top_sites_impl_unittest.cc",
"url_database_unittest.cc",
diff --git a/chromium/components/history/core/browser/browsing_history_service.cc b/chromium/components/history/core/browser/browsing_history_service.cc
index d745c3b2daa..781c5f4e373 100644
--- a/chromium/components/history/core/browser/browsing_history_service.cc
+++ b/chromium/components/history/core/browser/browsing_history_service.cc
@@ -122,16 +122,18 @@ BrowsingHistoryService::HistoryEntry::HistoryEntry(
const std::string& client_id,
bool is_search_result,
const base::string16& snippet,
- bool blocked_visit) {
- this->entry_type = entry_type;
- this->url = url;
- this->title = title;
- this->time = time;
- this->client_id = client_id;
+ bool blocked_visit,
+ const GURL& remote_icon_url_for_uma)
+ : entry_type(entry_type),
+ url(url),
+ title(title),
+ time(time),
+ client_id(client_id),
+ is_search_result(is_search_result),
+ snippet(snippet),
+ blocked_visit(blocked_visit),
+ remote_icon_url_for_uma(remote_icon_url_for_uma) {
all_timestamps.insert(time.ToInternalValue());
- this->is_search_result = is_search_result;
- this->snippet = snippet;
- this->blocked_visit = blocked_visit;
}
BrowsingHistoryService::HistoryEntry::HistoryEntry()
@@ -486,6 +488,12 @@ void BrowsingHistoryService::MergeDuplicateResults(
if (matching_entry->entry_type != entry.entry_type) {
matching_entry->entry_type = HistoryEntry::COMBINED_ENTRY;
}
+
+ // Get first non-empty remote icon url.
+ if (matching_entry->remote_icon_url_for_uma.is_empty() &&
+ !entry.remote_icon_url_for_uma.is_empty()) {
+ matching_entry->remote_icon_url_for_uma = entry.remote_icon_url_for_uma;
+ }
}
}
@@ -545,7 +553,7 @@ void BrowsingHistoryService::QueryComplete(
output.emplace_back(HistoryEntry(
HistoryEntry::LOCAL_ENTRY, page.url(), page.title(), page.visit_time(),
std::string(), !state->search_text.empty(), page.snippet().text(),
- page.blocked_visit()));
+ page.blocked_visit(), GURL()));
}
state->local_status =
@@ -643,6 +651,7 @@ void BrowsingHistoryService::WebHistoryQueryComplete(
const base::ListValue* ids = nullptr;
base::string16 url;
base::string16 title;
+ base::string16 favicon_url;
if (!(events->GetDictionary(i, &event) &&
event->GetList("result", &results) &&
@@ -660,6 +669,8 @@ void BrowsingHistoryService::WebHistoryQueryComplete(
// Title is optional, so the return value is ignored here.
result->GetString("title", &title);
+ result->GetString("favicon_url", &favicon_url);
+
// Extract the timestamps of all the visits to this URL.
// They are referred to as "IDs" by the server.
for (int j = 0; j < static_cast<int>(ids->GetSize()); ++j) {
@@ -684,7 +695,7 @@ void BrowsingHistoryService::WebHistoryQueryComplete(
state->remote_results.emplace_back(HistoryEntry(
HistoryEntry::REMOTE_ENTRY, gurl, title, time, client_id,
!state->search_text.empty(), base::string16(),
- /* blocked_visit */ false));
+ /* blocked_visit */ false, GURL(favicon_url)));
}
}
}
diff --git a/chromium/components/history/core/browser/browsing_history_service.h b/chromium/components/history/core/browser/browsing_history_service.h
index b747cc67062..868efb6ba46 100644
--- a/chromium/components/history/core/browser/browsing_history_service.h
+++ b/chromium/components/history/core/browser/browsing_history_service.h
@@ -70,7 +70,8 @@ class BrowsingHistoryService : public HistoryServiceObserver,
const std::string& client_id,
bool is_search_result,
const base::string16& snippet,
- bool blocked_visit);
+ bool blocked_visit,
+ const GURL& remote_icon_url_for_uma);
HistoryEntry();
HistoryEntry(const HistoryEntry& other);
virtual ~HistoryEntry();
@@ -105,6 +106,9 @@ class BrowsingHistoryService : public HistoryServiceObserver,
// Whether this entry was blocked when it was attempted.
bool blocked_visit;
+
+ // Optional parameter used to plumb footprints associated icon url.
+ GURL remote_icon_url_for_uma;
};
// Contains information about a completed history query.
diff --git a/chromium/components/history/core/browser/browsing_history_service_unittest.cc b/chromium/components/history/core/browser/browsing_history_service_unittest.cc
index 11f02f97dea..1b7116eed12 100644
--- a/chromium/components/history/core/browser/browsing_history_service_unittest.cc
+++ b/chromium/components/history/core/browser/browsing_history_service_unittest.cc
@@ -13,7 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/task/cancelable_task_tracker.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/timer/mock_timer.h"
#include "base/values.h"
#include "components/history/core/browser/browsing_history_driver.h"
@@ -43,6 +43,7 @@ const char kUrl4[] = "http://www.four.com";
const char kUrl5[] = "http://www.five.com";
const char kUrl6[] = "http://www.six.com";
const char kUrl7[] = "http://www.seven.com";
+const char kIconUrl1[] = "http://www.one.com/favicon.ico";
const HistoryEntry::EntryType kLocal = HistoryEntry::LOCAL_ENTRY;
const HistoryEntry::EntryType kRemote = HistoryEntry::REMOTE_ENTRY;
@@ -52,6 +53,7 @@ struct TestResult {
std::string url;
int64_t hour_offset; // Visit time in hours past the baseline time.
HistoryEntry::EntryType type;
+ std::string remote_icon_url_for_uma;
};
class TestSyncService : public syncer::FakeSyncService {
@@ -224,7 +226,8 @@ class BrowsingHistoryServiceTest : public ::testing::Test {
OffsetToTime(entry.hour_offset),
VisitSource::SOURCE_BROWSED);
} else if (entry.type == kRemote) {
- web_history->AddSyncedVisit(entry.url, OffsetToTime(entry.hour_offset));
+ web_history->AddSyncedVisit(entry.url, OffsetToTime(entry.hour_offset),
+ entry.remote_icon_url_for_uma);
} else {
NOTREACHED();
}
@@ -240,6 +243,8 @@ class BrowsingHistoryServiceTest : public ::testing::Test {
EXPECT_EQ(OffsetToTime(expected.hour_offset), actual.time);
EXPECT_EQ(static_cast<int>(expected.type),
static_cast<int>(actual.entry_type));
+ EXPECT_EQ(GURL(expected.remote_icon_url_for_uma),
+ actual.remote_icon_url_for_uma);
}
TestBrowsingHistoryDriver::QueryResult QueryHistory(size_t max_count = 0) {
@@ -292,7 +297,7 @@ class BrowsingHistoryServiceTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
// Duplicates on the same day in the local timezone are removed, so set a
// baseline time in local time.
@@ -490,6 +495,18 @@ TEST_F(BrowsingHistoryServiceTest, MergeDuplicatesVerifyTimestamps) {
EXPECT_EQ(1U, results.first[1].all_timestamps.size());
}
+TEST_F(BrowsingHistoryServiceTest, MergeDuplicatesKeepNonEmptyIconUrl) {
+ AddHistory({{kUrl1, 0, kRemote, kIconUrl1}, {kUrl1, 1, kLocal}});
+ auto results = QueryHistory();
+ VerifyQueryResult(/*reached_beginning*/ true, /*has_synced_results*/ true,
+ {{kUrl1, 1, kBoth, kIconUrl1}}, results);
+
+ AddHistory({{kUrl1, 0, kLocal}, {kUrl1, 1, kRemote, kIconUrl1}});
+ results = QueryHistory();
+ VerifyQueryResult(/*reached_beginning*/ true, /*has_synced_results*/ true,
+ {{kUrl1, 1, kBoth, kIconUrl1}}, results);
+}
+
TEST_F(BrowsingHistoryServiceTest, QueryHistoryMerge) {
AddHistory({{kUrl1, 1, kRemote},
{kUrl2, 2, kRemote},
diff --git a/chromium/components/history/core/browser/expire_history_backend_unittest.cc b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
index 2d0770e9435..42fac51f93b 100644
--- a/chromium/components/history/core/browser/expire_history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
@@ -23,7 +23,7 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/history/core/browser/history_backend_client.h"
#include "components/history/core/browser/history_backend_notifier.h"
#include "components/history/core/browser/history_constants.h"
@@ -84,7 +84,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
: backend_client_(history_client_.CreateBackendClient()),
expirer_(this,
backend_client_.get(),
- scoped_task_environment_.GetMainThreadTaskRunner()),
+ task_environment_.GetMainThreadTaskRunner()),
now_(PretendNow()) {}
protected:
@@ -131,7 +131,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
// This must be destroyed last.
base::ScopedTempDir tmp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
HistoryClientFakeBookmarks history_client_;
std::unique_ptr<HistoryBackendClient> backend_client_;
diff --git a/chromium/components/history/core/browser/history_backend.h b/chromium/components/history/core/browser/history_backend.h
index 65256eec515..a1301c84497 100644
--- a/chromium/components/history/core/browser/history_backend.h
+++ b/chromium/components/history/core/browser/history_backend.h
@@ -60,6 +60,7 @@ struct HistoryDatabaseParams;
class HistoryDBTask;
class InMemoryHistoryBackend;
class HistoryBackendHelper;
+class TypedURLSyncBridge;
class URLDatabase;
// The maximum number of bitmaps for a single icon URL which can be stored in
diff --git a/chromium/components/history/core/browser/history_backend_unittest.cc b/chromium/components/history/core/browser/history_backend_unittest.cc
index 89e723b3ad9..34bf13be3fd 100644
--- a/chromium/components/history/core/browser/history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_unittest.cc
@@ -30,7 +30,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/favicon_base/favicon_usage_data.h"
@@ -282,7 +282,7 @@ class HistoryBackendTestBase : public testing::Test {
URLsModifiedList urls_modified_notifications_;
URLsDeletedList urls_deleted_notifications_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::FilePath test_dir_;
DISALLOW_COPY_AND_ASSIGN(HistoryBackendTestBase);
diff --git a/chromium/components/history/core/browser/history_querying_unittest.cc b/chromium/components/history/core/browser/history_querying_unittest.cc
index b51d9e94e58..8ab0e539340 100644
--- a/chromium/components/history/core/browser/history_querying_unittest.cc
+++ b/chromium/components/history/core/browser/history_querying_unittest.cc
@@ -14,7 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/history/core/browser/history_database_params.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/test/test_history_database.h"
@@ -194,7 +194,7 @@ class HistoryQueryTest : public testing::Test {
base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::FilePath history_dir_;
diff --git a/chromium/components/history/core/browser/history_service.cc b/chromium/components/history/core/browser/history_service.cc
index 58a42bcf2b9..c0a0a67c53a 100644
--- a/chromium/components/history/core/browser/history_service.cc
+++ b/chromium/components/history/core/browser/history_service.cc
@@ -905,8 +905,8 @@ bool HistoryService::Init(
}
backend_task_runner_ = thread_->task_runner();
} else {
- backend_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::WithBaseSyncPrimitives(),
+ backend_task_runner_ = base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(),
base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
}
diff --git a/chromium/components/history/core/browser/history_service_unittest.cc b/chromium/components/history/core/browser/history_service_unittest.cc
index 1d865576e80..1baac2af671 100644
--- a/chromium/components/history/core/browser/history_service_unittest.cc
+++ b/chromium/components/history/core/browser/history_service_unittest.cc
@@ -36,7 +36,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/history/core/browser/history_database_params.h"
#include "components/history/core/browser/history_db_task.h"
@@ -58,8 +58,8 @@ namespace history {
class HistoryServiceTest : public testing::Test {
public:
HistoryServiceTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
~HistoryServiceTest() override {}
@@ -155,7 +155,7 @@ class HistoryServiceTest : public testing::Test {
base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
MostVisitedURLList most_visited_urls_;
diff --git a/chromium/components/history/core/browser/in_memory_database.cc b/chromium/components/history/core/browser/in_memory_database.cc
index f8d2dcd2ef0..fe130332a8f 100644
--- a/chromium/components/history/core/browser/in_memory_database.cc
+++ b/chromium/components/history/core/browser/in_memory_database.cc
@@ -101,17 +101,6 @@ bool InMemoryDatabase::InitFromDisk(const base::FilePath& history_name) {
UMA_HISTOGRAM_COUNTS_1M("History.InMemoryDBItemCount",
db_.GetLastChangeCount());
- {
- // This calculation should be fast (since it's on an in-memory DB with
- // an average of only 35 rows).
- sql::Statement visit_count(db_.GetUniqueStatement(
- "SELECT sum(visit_count) FROM urls"));
- if (visit_count.Step()) {
- UMA_HISTOGRAM_COUNTS_1M("History.InMemoryTypedUrlVisitCount",
- visit_count.ColumnInt(0));
- }
- }
-
// Insert keyword search related URLs.
begin_load = base::TimeTicks::Now();
if (!db_.Execute("INSERT OR IGNORE INTO urls SELECT u.id, u.url, u.title, "
diff --git a/chromium/components/history/core/browser/in_memory_history_backend.cc b/chromium/components/history/core/browser/in_memory_history_backend.cc
index 8384e6b5671..f31784866a6 100644
--- a/chromium/components/history/core/browser/in_memory_history_backend.cc
+++ b/chromium/components/history/core/browser/in_memory_history_backend.cc
@@ -10,18 +10,13 @@
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/in_memory_database.h"
#include "components/history/core/browser/url_database.h"
namespace history {
-InMemoryHistoryBackend::InMemoryHistoryBackend()
- : history_service_observer_(this) {
-}
-
-InMemoryHistoryBackend::~InMemoryHistoryBackend() {
-}
+InMemoryHistoryBackend::InMemoryHistoryBackend() = default;
+InMemoryHistoryBackend::~InMemoryHistoryBackend() = default;
bool InMemoryHistoryBackend::Init(const base::FilePath& history_filename) {
db_.reset(new InMemoryDatabase);
diff --git a/chromium/components/history/core/browser/in_memory_history_backend.h b/chromium/components/history/core/browser/in_memory_history_backend.h
index 557467dc99c..fc42b7e01c3 100644
--- a/chromium/components/history/core/browser/in_memory_history_backend.h
+++ b/chromium/components/history/core/browser/in_memory_history_backend.h
@@ -26,6 +26,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
+#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/history/core/browser/keyword_id.h"
@@ -36,7 +37,6 @@ class FilePath;
namespace history {
class HistoryBackendTestBase;
-class HistoryService;
class InMemoryDatabase;
class InMemoryHistoryBackendTest;
class URLRow;
@@ -92,7 +92,7 @@ class InMemoryHistoryBackend : public HistoryServiceObserver {
std::unique_ptr<InMemoryDatabase> db_;
ScopedObserver<HistoryService, HistoryServiceObserver>
- history_service_observer_;
+ history_service_observer_{this};
DISALLOW_COPY_AND_ASSIGN(InMemoryHistoryBackend);
};
diff --git a/chromium/components/history/core/browser/sync/delete_directive_handler_unittest.cc b/chromium/components/history/core/browser/sync/delete_directive_handler_unittest.cc
index a7155d8421f..853b35b38b8 100644
--- a/chromium/components/history/core/browser/sync/delete_directive_handler_unittest.cc
+++ b/chromium/components/history/core/browser/sync/delete_directive_handler_unittest.cc
@@ -9,7 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/history/core/browser/history_backend.h"
@@ -122,7 +122,7 @@ class HistoryDeleteDirectiveHandlerTest : public testing::Test {
DeleteDirectiveHandler* handler() { return delete_directive_handler_.get(); }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir test_dir_;
scoped_refptr<HistoryBackend> history_backend_;
std::unique_ptr<DeleteDirectiveHandler> delete_directive_handler_;
diff --git a/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc b/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
index 8955d0f2e03..eed221869ac 100644
--- a/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
+++ b/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
@@ -31,9 +31,12 @@ HistoryDeleteDirectivesModelTypeController::
HistoryDeleteDirectivesModelTypeController::
~HistoryDeleteDirectivesModelTypeController() {}
-bool HistoryDeleteDirectivesModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+HistoryDeleteDirectivesModelTypeController::GetPreconditionState() const {
DCHECK(CalledOnValidThread());
- return !sync_service_->GetUserSettings()->IsEncryptEverythingEnabled();
+ return sync_service_->GetUserSettings()->IsEncryptEverythingEnabled()
+ ? PreconditionState::kMustStopAndClearData
+ : PreconditionState::kPreconditionsMet;
}
void HistoryDeleteDirectivesModelTypeController::LoadModels(
@@ -62,7 +65,7 @@ void HistoryDeleteDirectivesModelTypeController::OnStateChanged(
syncer::SyncService* sync) {
DCHECK(CalledOnValidThread());
// Most of these calls will be no-ops but SyncService handles that just fine.
- sync_service_->ReadyForStartChanged(type());
+ sync_service_->DataTypePreconditionChanged(type());
}
} // namespace browser_sync
diff --git a/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.h b/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
index 93cb9d33661..8141c718cc1 100644
--- a/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
+++ b/chromium/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
@@ -34,7 +34,7 @@ class HistoryDeleteDirectivesModelTypeController
~HistoryDeleteDirectivesModelTypeController() override;
// DataTypeController overrides.
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
void LoadModels(const syncer::ConfigureContext& configure_context,
const ModelLoadCallback& model_load_callback) override;
void Stop(syncer::ShutdownReason shutdown_reason,
diff --git a/chromium/components/history/core/browser/sync/history_model_worker.cc b/chromium/components/history/core/browser/sync/history_model_worker.cc
deleted file mode 100644
index 6ad79312f04..00000000000
--- a/chromium/components/history/core/browser/sync/history_model_worker.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 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 "components/history/core/browser/sync/history_model_worker.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "components/history/core/browser/history_db_task.h"
-#include "components/history/core/browser/history_service.h"
-
-namespace browser_sync {
-
-class WorkerTask : public history::HistoryDBTask {
- public:
- explicit WorkerTask(base::OnceClosure work) : work_(std::move(work)) {}
-
- bool RunOnDBThread(history::HistoryBackend* backend,
- history::HistoryDatabase* db) override {
- std::move(work_).Run();
- return true;
- }
-
- // Since the DoWorkAndWaitUntilDone() is synchronous, we don't need to run
- // any code asynchronously on the main thread after completion.
- void DoneRunOnMainThread() override {}
-
- private:
- // A OnceClosure is deleted right after it runs. This is important to unblock
- // DoWorkAndWaitUntilDone() right after the task runs.
- base::OnceClosure work_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerTask);
-};
-
-namespace {
-
-// Post the work task on |history_service|'s DB thread from the UI
-// thread.
-void PostWorkerTask(
- const base::WeakPtr<history::HistoryService>& history_service,
- base::OnceClosure work,
- base::CancelableTaskTracker* cancelable_tracker) {
- if (history_service) {
- history_service->ScheduleDBTask(
- FROM_HERE, std::make_unique<WorkerTask>(std::move(work)),
- cancelable_tracker);
- }
-}
-
-} // namespace
-
-HistoryModelWorker::HistoryModelWorker(
- const base::WeakPtr<history::HistoryService>& history_service,
- scoped_refptr<base::SingleThreadTaskRunner> ui_thread)
- : history_service_(history_service),
- ui_thread_(std::move(ui_thread)),
- // base::OnTaskRunnerDeleter ensures that |cancelable_tracker_| is
- // destroyed on the UI thread, even if |this| is deleted on a different
- // thread. It is a requirement of base::CancelableTaskTracker to be
- // constructed and deleted on the same sequence.
- cancelable_tracker_(new base::CancelableTaskTracker,
- base::OnTaskRunnerDeleter(ui_thread_)) {
- CHECK(history_service);
- DCHECK(ui_thread_->BelongsToCurrentThread());
-}
-
-syncer::ModelSafeGroup HistoryModelWorker::GetModelSafeGroup() {
- return syncer::GROUP_HISTORY;
-}
-
-bool HistoryModelWorker::IsOnModelSequence() {
- // Ideally HistoryService would expose a way to check whether this is the
- // history DB thread. Since it doesn't, just return true to bypass a CHECK in
- // the sync code.
- return true;
-}
-
-HistoryModelWorker::~HistoryModelWorker() = default;
-
-void HistoryModelWorker::ScheduleWork(base::OnceClosure work) {
- ui_thread_->PostTask(
- FROM_HERE, base::BindOnce(&PostWorkerTask, history_service_,
- std::move(work), cancelable_tracker_.get()));
-}
-
-} // namespace browser_sync
diff --git a/chromium/components/history/core/browser/sync/history_model_worker.h b/chromium/components/history/core/browser/sync/history_model_worker.h
deleted file mode 100644
index 4bcacaff63e..00000000000
--- a/chromium/components/history/core/browser/sync/history_model_worker.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 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 COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_MODEL_WORKER_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_MODEL_WORKER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task/cancelable_task_tracker.h"
-#include "components/sync/engine/model_safe_worker.h"
-
-namespace history {
-class HistoryService;
-}
-
-namespace browser_sync {
-
-// A syncer::ModelSafeWorker for history models that accepts requests
-// from the syncapi that need to be fulfilled on the history thread.
-class HistoryModelWorker : public syncer::ModelSafeWorker {
- public:
- explicit HistoryModelWorker(
- const base::WeakPtr<history::HistoryService>& history_service,
- scoped_refptr<base::SingleThreadTaskRunner> ui_thread);
-
- // syncer::ModelSafeWorker implementation.
- syncer::ModelSafeGroup GetModelSafeGroup() override;
- bool IsOnModelSequence() override;
-
- private:
- ~HistoryModelWorker() override;
-
- void ScheduleWork(base::OnceClosure work) override;
-
- const base::WeakPtr<history::HistoryService> history_service_;
-
- // A reference to the UI thread's task runner.
- const scoped_refptr<base::SingleThreadTaskRunner> ui_thread_;
-
- // Helper object to make sure we don't leave tasks running on the history
- // thread.
- const std::unique_ptr<base::CancelableTaskTracker, base::OnTaskRunnerDeleter>
- cancelable_tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(HistoryModelWorker);
-};
-
-} // namespace browser_sync
-
-#endif // COMPONENTS_HISTORY_CORE_BROWSER_SYNC_HISTORY_MODEL_WORKER_H_
diff --git a/chromium/components/history/core/browser/sync/history_model_worker_unittest.cc b/chromium/components/history/core/browser/sync/history_model_worker_unittest.cc
deleted file mode 100644
index 8d37a73ef76..00000000000
--- a/chromium/components/history/core/browser/sync/history_model_worker_unittest.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history/core/browser/sync/history_model_worker.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "components/history/core/browser/history_db_task.h"
-#include "components/history/core/browser/history_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace browser_sync {
-namespace {
-
-class HistoryServiceMock : public history::HistoryService {
- public:
- explicit HistoryServiceMock(
- scoped_refptr<base::SingleThreadTaskRunner> history_thread)
- : history_thread_(std::move(history_thread)) {}
-
- base::CancelableTaskTracker::TaskId ScheduleDBTask(
- const base::Location& from_here,
- std::unique_ptr<history::HistoryDBTask> task,
- base::CancelableTaskTracker* tracker) override {
- history::HistoryDBTask* task_raw = task.get();
- history_thread_->PostTaskAndReply(
- from_here,
- base::BindOnce(
- base::IgnoreResult(&history::HistoryDBTask::RunOnDBThread),
- base::Unretained(task_raw), nullptr, nullptr),
- base::BindOnce(&history::HistoryDBTask::DoneRunOnMainThread,
- std::move(task)));
- return base::CancelableTaskTracker::kBadTaskId; // Unused.
- }
-
- private:
- const scoped_refptr<base::SingleThreadTaskRunner> history_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(HistoryServiceMock);
-};
-
-syncer::WorkCallback ClosureToWorkCallback(base::Closure work) {
- return base::BindOnce(
- [](base::Closure work) {
- work.Run();
- return syncer::SyncerError(syncer::SyncerError::SYNCER_OK);
- },
- std::move(work));
-}
-
-class HistoryModelWorkerTest : public testing::Test {
- public:
- HistoryModelWorkerTest()
- : sync_thread_("SyncThreadForTest"),
- history_service_(history_thread_),
- history_service_factory_(&history_service_) {
- sync_thread_.Start();
- worker_ = new HistoryModelWorker(history_service_factory_.GetWeakPtr(),
- ui_thread_);
- }
-
- ~HistoryModelWorkerTest() override {
- // Run tasks that might still have a reference to |worker_|.
- ui_thread_->RunUntilIdle();
- history_thread_->RunUntilIdle();
-
- // Release the last reference to |worker_|.
- EXPECT_TRUE(worker_->HasOneRef());
- worker_ = nullptr;
-
- // Run the DeleteSoon() task posted from ~HistoryModelWorker. This prevents
- // a leak.
- ui_thread_->RunUntilIdle();
- }
-
- protected:
- void DoWorkAndWaitUntilDoneOnSyncThread(base::Closure work) {
- sync_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(
- base::IgnoreResult(&HistoryModelWorker::DoWorkAndWaitUntilDone),
- worker_, ClosureToWorkCallback(work)));
- sync_thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&base::AtomicFlag::Set,
- base::Unretained(&sync_thread_unblocked_)));
- }
-
- const scoped_refptr<base::TestSimpleTaskRunner> ui_thread_ =
- new base::TestSimpleTaskRunner();
- scoped_refptr<base::TestSimpleTaskRunner> history_thread_ =
- new base::TestSimpleTaskRunner();
- base::AtomicFlag sync_thread_unblocked_;
- base::Thread sync_thread_;
- HistoryServiceMock history_service_;
- scoped_refptr<HistoryModelWorker> worker_;
-
- private:
- base::WeakPtrFactory<HistoryServiceMock> history_service_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(HistoryModelWorkerTest);
-};
-
-} // namespace
-
-TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDone) {
- bool did_work = false;
- DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
- [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
-
- EXPECT_FALSE(did_work);
- EXPECT_FALSE(sync_thread_unblocked_.IsSet());
-
- // Wait for a task to be posted to the UI thread and run it. Expect this task
- // to post another task to the history DB thread and run it.
- while (!ui_thread_->HasPendingTask())
- base::PlatformThread::YieldCurrentThread();
- ui_thread_->RunUntilIdle();
- EXPECT_TRUE(history_thread_->HasPendingTask());
- history_thread_->RunUntilIdle();
-
- EXPECT_TRUE(did_work);
-
- sync_thread_.Stop();
- EXPECT_TRUE(sync_thread_unblocked_.IsSet());
-}
-
-TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneRequestStopBeforeRunWork) {
- bool did_work = false;
- DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
- [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
-
- EXPECT_FALSE(did_work);
- EXPECT_FALSE(sync_thread_unblocked_.IsSet());
-
- // Wait for a task to be posted to the UI thread and run it.
- while (!ui_thread_->HasPendingTask())
- base::PlatformThread::YieldCurrentThread();
- ui_thread_->RunUntilIdle();
-
- // Stop the worker.
- worker_->RequestStop();
-
- // The WorkCallback should not run on the history DB thread.
- EXPECT_TRUE(history_thread_->HasPendingTask());
- history_thread_->RunUntilIdle();
- EXPECT_FALSE(did_work);
-
- sync_thread_.Stop();
- EXPECT_TRUE(sync_thread_unblocked_.IsSet());
-}
-
-TEST_F(HistoryModelWorkerTest,
- DoWorkAndWaitUntilDoneRequestStopBeforeUITaskRun) {
- bool did_work = false;
- DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
- [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
-
- EXPECT_FALSE(did_work);
- EXPECT_FALSE(sync_thread_unblocked_.IsSet());
-
- // Wait for a task to be posted to the UI thread.
- while (!ui_thread_->HasPendingTask())
- base::PlatformThread::YieldCurrentThread();
-
- // Stop the worker.
- worker_->RequestStop();
-
- // Stopping the worker should unblock the sync thread.
- sync_thread_.Stop();
- EXPECT_TRUE(sync_thread_unblocked_.IsSet());
-}
-
-TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneDeleteWorkBeforeRun) {
- bool did_work = false;
- DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
- [](bool* did_work) { *did_work = true; }, base::Unretained(&did_work)));
-
- EXPECT_FALSE(did_work);
- EXPECT_FALSE(sync_thread_unblocked_.IsSet());
-
- // Wait for a task to be posted to the UI thread. Delete it before it can run.
- while (!ui_thread_->HasPendingTask())
- base::PlatformThread::YieldCurrentThread();
- ui_thread_->ClearPendingTasks();
-
- EXPECT_FALSE(did_work);
-
- // Deleting the task should have unblocked the sync thread.
- sync_thread_.Stop();
- EXPECT_TRUE(sync_thread_unblocked_.IsSet());
-}
-
-TEST_F(HistoryModelWorkerTest, DoWorkAndWaitUntilDoneRequestStopDuringRunWork) {
- bool did_work = false;
- DoWorkAndWaitUntilDoneOnSyncThread(base::Bind(
- [](scoped_refptr<HistoryModelWorker> worker,
- base::AtomicFlag* sync_thread_unblocked, bool* did_work) {
- worker->RequestStop();
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- // The sync thread should not be unblocked while a WorkCallback is
- // running.
- EXPECT_FALSE(sync_thread_unblocked->IsSet());
-
- *did_work = true;
- },
- worker_, base::Unretained(&sync_thread_unblocked_),
- base::Unretained(&did_work)));
- EXPECT_FALSE(did_work);
- EXPECT_FALSE(sync_thread_unblocked_.IsSet());
-
- // Wait for a task to be posted to the UI thread and run it.
- while (!ui_thread_->HasPendingTask())
- base::PlatformThread::YieldCurrentThread();
- ui_thread_->RunUntilIdle();
-
- // Expect a task to be posted to the history DB thread. Run it.
- EXPECT_TRUE(history_thread_->HasPendingTask());
- history_thread_->RunUntilIdle();
- EXPECT_TRUE(did_work);
-
- sync_thread_.Stop();
- EXPECT_TRUE(sync_thread_unblocked_.IsSet());
-}
-
-} // namespace browser_sync
diff --git a/chromium/components/history/core/browser/sync/typed_url_model_type_controller.cc b/chromium/components/history/core/browser/sync/typed_url_model_type_controller.cc
index 2b1dc8beff9..33104eac9eb 100644
--- a/chromium/components/history/core/browser/sync/typed_url_model_type_controller.cc
+++ b/chromium/components/history/core/browser/sync/typed_url_model_type_controller.cc
@@ -47,9 +47,12 @@ TypedURLModelTypeController::TypedURLModelTypeController(
TypedURLModelTypeController::~TypedURLModelTypeController() {}
-bool TypedURLModelTypeController::ReadyForStart() const {
- return history_service_ &&
- !pref_service_->GetBoolean(history_disabled_pref_name_);
+syncer::DataTypeController::PreconditionState
+TypedURLModelTypeController::GetPreconditionState() const {
+ return (history_service_ &&
+ !pref_service_->GetBoolean(history_disabled_pref_name_))
+ ? PreconditionState::kPreconditionsMet
+ : PreconditionState::kMustStopAndClearData;
}
void TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged() {
@@ -57,6 +60,7 @@ void TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged() {
// We've turned off history persistence, so if we are running,
// generate an unrecoverable error. This can be fixed by restarting
// Chrome (on restart, typed urls will not be a registered type).
+ // TODO(crbug.com/990802): Adopt DataTypePreconditionChanged().
if (state() != NOT_RUNNING && state() != STOPPING) {
ReportModelError(
syncer::SyncError::DATATYPE_POLICY_ERROR,
diff --git a/chromium/components/history/core/browser/sync/typed_url_model_type_controller.h b/chromium/components/history/core/browser/sync/typed_url_model_type_controller.h
index 51280ad71a3..07187ccd9de 100644
--- a/chromium/components/history/core/browser/sync/typed_url_model_type_controller.h
+++ b/chromium/components/history/core/browser/sync/typed_url_model_type_controller.h
@@ -22,7 +22,7 @@ class TypedURLModelTypeController : public syncer::ModelTypeController {
~TypedURLModelTypeController() override;
// syncer::DataTypeController implementation.
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
private:
void OnSavingBrowserHistoryDisabledChanged();
diff --git a/chromium/components/history/core/browser/sync/typed_url_sync_bridge.cc b/chromium/components/history/core/browser/sync/typed_url_sync_bridge.cc
index 04a55021e29..305b8c57247 100644
--- a/chromium/components/history/core/browser/sync/typed_url_sync_bridge.cc
+++ b/chromium/components/history/core/browser/sync/typed_url_sync_bridge.cc
@@ -10,7 +10,6 @@
#include "base/big_endian.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/history/core/browser/history_backend.h"
#include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model_impl/sync_metadata_store_change_list.h"
#include "net/base/url_util.h"
@@ -87,8 +86,7 @@ TypedURLSyncBridge::TypedURLSyncBridge(
processing_syncer_changes_(false),
sync_metadata_database_(sync_metadata_database),
num_db_accesses_(0),
- num_db_errors_(0),
- history_backend_observer_(this) {
+ num_db_errors_(0) {
DCHECK(history_backend_);
DCHECK(sequence_checker_.CalledOnValidSequence());
}
diff --git a/chromium/components/history/core/browser/sync/typed_url_sync_bridge.h b/chromium/components/history/core/browser/sync/typed_url_sync_bridge.h
index f2fdf520562..6980cbc7ba4 100644
--- a/chromium/components/history/core/browser/sync/typed_url_sync_bridge.h
+++ b/chromium/components/history/core/browser/sync/typed_url_sync_bridge.h
@@ -13,6 +13,7 @@
#include <vector>
#include "base/scoped_observer.h"
+#include "components/history/core/browser/history_backend.h"
#include "components/history/core/browser/history_backend_observer.h"
#include "components/history/core/browser/sync/typed_url_sync_metadata_database.h"
#include "components/sync/model/metadata_change_list.h"
@@ -259,7 +260,7 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
// Tracks observed history backend, for receiving updates from history
// backend.
ScopedObserver<HistoryBackend, HistoryBackendObserver>
- history_backend_observer_;
+ history_backend_observer_{this};
DISALLOW_COPY_AND_ASSIGN(TypedURLSyncBridge);
};
diff --git a/chromium/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc b/chromium/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc
index 81d39d18d21..8254afca43c 100644
--- a/chromium/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc
+++ b/chromium/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc
@@ -12,7 +12,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/history/core/browser/history_backend.h"
#include "components/history/core/browser/history_backend_client.h"
@@ -512,7 +512,7 @@ class TypedURLSyncBridgeTest : public testing::Test {
RecordingModelTypeChangeProcessor& processor() { return *processor_; }
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::ScopedTempDir test_dir_;
scoped_refptr<TestHistoryBackend> fake_history_backend_;
TypedURLSyncBridge* typed_url_sync_bridge_;
diff --git a/chromium/components/history/core/browser/thumbnail_database.cc b/chromium/components/history/core/browser/thumbnail_database.cc
index cfc3a9c51b3..05d43e78971 100644
--- a/chromium/components/history/core/browser/thumbnail_database.cc
+++ b/chromium/components/history/core/browser/thumbnail_database.cc
@@ -1047,6 +1047,7 @@ sql::InitStatus ThumbnailDatabase::OpenDatabase(sql::Database* db,
if (!db->Open(db_name))
return sql::INIT_FAILURE;
+ db->Preload();
return sql::INIT_OK;
}
diff --git a/chromium/components/history/core/browser/top_sites.h b/chromium/components/history/core/browser/top_sites.h
index 33d7c98d60c..4f4ece9a16c 100644
--- a/chromium/components/history/core/browser/top_sites.h
+++ b/chromium/components/history/core/browser/top_sites.h
@@ -77,10 +77,6 @@ class TopSites : public RefcountedKeyedService {
// Clear the blacklist. Should be called from the UI thread.
virtual void ClearBlacklistedURLs() = 0;
- // Returns true if the given URL is known to the top sites service.
- // This function also returns false if TopSites isn't loaded yet.
- virtual bool IsKnownURL(const GURL& url) = 0;
-
// Returns true if the top sites list is full (i.e. we already have the
// maximum number of top sites). This function also returns false if TopSites
// isn't loaded yet.
diff --git a/chromium/components/history/core/browser/top_sites_backend.cc b/chromium/components/history/core/browser/top_sites_backend.cc
index 25e2be47043..f1494701aa0 100644
--- a/chromium/components/history/core/browser/top_sites_backend.cc
+++ b/chromium/components/history/core/browser/top_sites_backend.cc
@@ -25,8 +25,8 @@ namespace history {
TopSitesBackend::TopSitesBackend()
: db_(new TopSitesDatabase()),
- db_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::TaskPriority::USER_VISIBLE,
+ db_task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()})) {
DCHECK(db_task_runner_);
}
diff --git a/chromium/components/history/core/browser/top_sites_cache.cc b/chromium/components/history/core/browser/top_sites_cache.cc
deleted file mode 100644
index 38198db5ec3..00000000000
--- a/chromium/components/history/core/browser/top_sites_cache.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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 "base/logging.h"
-#include "components/history/core/browser/top_sites_cache.h"
-
-namespace history {
-
-TopSitesCache::CanonicalURLQuery::CanonicalURLQuery(const GURL& url) {
- most_visited_url_.redirects.push_back(url);
- entry_.first = &most_visited_url_;
- entry_.second = 0u;
-}
-
-TopSitesCache::CanonicalURLQuery::~CanonicalURLQuery() {
-}
-
-TopSitesCache::TopSitesCache() {
-}
-
-TopSitesCache::~TopSitesCache() {
-}
-
-void TopSitesCache::SetTopSites(const MostVisitedURLList& top_sites) {
- top_sites_ = top_sites;
- GenerateCanonicalURLs();
-}
-
-const GURL& TopSitesCache::GetCanonicalURL(const GURL& url) const {
- auto it = GetCanonicalURLsIterator(url);
- return it == canonical_urls_.end() ? url : it->first.first->url;
-}
-
-bool TopSitesCache::IsKnownURL(const GURL& url) const {
- return GetCanonicalURLsIterator(url) != canonical_urls_.end();
-}
-
-size_t TopSitesCache::GetURLIndex(const GURL& url) const {
- DCHECK(IsKnownURL(url));
- return GetCanonicalURLsIterator(url)->second;
-}
-
-size_t TopSitesCache::GetNumURLs() const {
- return top_sites_.size();
-}
-
-void TopSitesCache::GenerateCanonicalURLs() {
- canonical_urls_.clear();
- for (size_t i = 0; i < top_sites_.size(); i++)
- StoreRedirectChain(top_sites_[i].redirects, i);
-}
-
-void TopSitesCache::StoreRedirectChain(const RedirectList& redirects,
- size_t destination) {
- // |redirects| is empty if the user pinned a site and there are not enough top
- // sites before the pinned site.
-
- // Map all the redirected URLs to the destination.
- for (size_t i = 0; i < redirects.size(); i++) {
- // If this redirect is already known, don't replace it with a new one.
- if (!IsKnownURL(redirects[i])) {
- CanonicalURLEntry entry;
- entry.first = &(top_sites_[destination]);
- entry.second = i;
- canonical_urls_[entry] = destination;
- }
- }
-}
-
-TopSitesCache::CanonicalURLs::const_iterator
- TopSitesCache::GetCanonicalURLsIterator(const GURL& url) const {
- return canonical_urls_.find(CanonicalURLQuery(url).entry());
-}
-
-const GURL& TopSitesCache::GetURLFromIterator(
- CanonicalURLs::const_iterator it) const {
- DCHECK(it != canonical_urls_.end());
- return it->first.first->redirects[it->first.second];
-}
-
-} // namespace history
diff --git a/chromium/components/history/core/browser/top_sites_cache.h b/chromium/components/history/core/browser/top_sites_cache.h
deleted file mode 100644
index aee043670e7..00000000000
--- a/chromium/components/history/core/browser/top_sites_cache.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// 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 COMPONENTS_HISTORY_CORE_BROWSER_TOP_SITES_CACHE_H_
-#define COMPONENTS_HISTORY_CORE_BROWSER_TOP_SITES_CACHE_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <utility>
-
-#include "base/macros.h"
-#include "components/history/core/browser/history_types.h"
-#include "components/history/core/browser/url_utils.h"
-#include "url/gurl.h"
-
-namespace history {
-
-// TopSitesCache caches the list of top sites for TopSites.
-class TopSitesCache {
- public:
- TopSitesCache();
- ~TopSitesCache();
-
- // Set the top sites.
- void SetTopSites(const MostVisitedURLList& top_sites);
- const MostVisitedURLList& top_sites() const { return top_sites_; }
-
- // Returns the canonical URL for |url|. If not found, returns |url|.
- const GURL& GetCanonicalURL(const GURL& url) const;
-
- // Returns true if |url| is known.
- bool IsKnownURL(const GURL& url) const;
-
- // Returns the index into |top_sites_| for |url|.
- size_t GetURLIndex(const GURL& url) const;
-
- // Returns the number of URLs in the cache.
- size_t GetNumURLs() const;
-
- private:
- // The entries in CanonicalURLs, see CanonicalURLs for details. The second
- // argument gives the index of the URL into MostVisitedURLs redirects.
- typedef std::pair<MostVisitedURL*, size_t> CanonicalURLEntry;
-
- // Comparator used for CanonicalURLs.
- class CanonicalURLComparator {
- public:
- bool operator()(const CanonicalURLEntry& e1,
- const CanonicalURLEntry& e2) const {
- return CanonicalURLStringCompare(e1.first->redirects[e1.second].spec(),
- e2.first->redirects[e2.second].spec());
- }
- };
-
- // Creates the object needed to form std::map queries into |canonical_urls_|,
- // wrapping all required temporary data to allow inlining.
- class CanonicalURLQuery {
- public:
- explicit CanonicalURLQuery(const GURL& url);
- ~CanonicalURLQuery();
- const CanonicalURLEntry& entry() { return entry_; }
-
- private:
- MostVisitedURL most_visited_url_;
- CanonicalURLEntry entry_;
- };
-
- // This is used to map from redirect url to the MostVisitedURL the redirect is
- // from. Ideally this would be map<GURL, size_t> (second param indexing into
- // top_sites_), but this results in duplicating all redirect urls. As some
- // sites have a lot of redirects, we instead use the MostVisitedURL* and the
- // index of the redirect as the key, and the index into top_sites_ as the
- // value. This way we aren't duplicating GURLs. CanonicalURLComparator
- // enforces the ordering as if we were using GURLs.
- typedef std::map<CanonicalURLEntry, size_t,
- CanonicalURLComparator> CanonicalURLs;
-
- // Generates the set of canonical urls from |top_sites_|.
- void GenerateCanonicalURLs();
-
- // Stores a set of redirects. This is used by GenerateCanonicalURLs.
- void StoreRedirectChain(const RedirectList& redirects, size_t destination);
-
- // Returns the iterator into |canonical_urls_| for the |url|.
- CanonicalURLs::const_iterator GetCanonicalURLsIterator(const GURL& url) const;
-
- // Returns the GURL corresponding to an iterator in |canonical_urls_|.
- const GURL& GetURLFromIterator(CanonicalURLs::const_iterator it) const;
-
- // The list of top sites.
- MostVisitedURLList top_sites_;
-
- // Generated from the redirects to and from the most visited pages. See
- // description above typedef for details.
- CanonicalURLs canonical_urls_;
-
- DISALLOW_COPY_AND_ASSIGN(TopSitesCache);
-};
-
-} // namespace history
-
-#endif // COMPONENTS_HISTORY_CORE_BROWSER_TOP_SITES_CACHE_H_
diff --git a/chromium/components/history/core/browser/top_sites_cache_unittest.cc b/chromium/components/history/core/browser/top_sites_cache_unittest.cc
deleted file mode 100644
index c4510c7b61c..00000000000
--- a/chromium/components/history/core/browser/top_sites_cache_unittest.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history/core/browser/top_sites_cache.h"
-
-#include <stddef.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace history {
-
-namespace {
-
-class TopSitesCacheTest : public testing::Test {
- public:
- TopSitesCacheTest() {
- }
-
- protected:
- // Initializes |top_sites_| on |spec|, which is a list of URL strings with
- // optional indents: indentated URLs redirect to the last non-indented URL.
- // Titles are assigned as "Title 1", "Title 2", etc., in the order of
- // appearance. See |kTopSitesSpecBasic| for an example. This function does not
- // update |cache_| so you can manipulate |top_sites_| before you update it.
- void BuildTopSites(const char** spec, size_t size);
-
- // Initializes |top_sites_| and |cache_| based on |spec|.
- void InitTopSiteCache(const char** spec, size_t size);
-
- MostVisitedURLList top_sites_;
- TopSitesCache cache_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TopSitesCacheTest);
-};
-
-void TopSitesCacheTest::BuildTopSites(const char** spec, size_t size) {
- std::set<std::string> urls_seen;
- for (size_t i = 0; i < size; ++i) {
- const char* spec_item = spec[i];
- while (*spec_item && *spec_item == ' ') // Eat indent.
- ++spec_item;
- if (urls_seen.find(spec_item) != urls_seen.end())
- NOTREACHED() << "Duplicate URL found: " << spec_item;
- urls_seen.insert(spec_item);
- if (spec_item == spec[i]) { // No indent: add new MostVisitedURL.
- base::string16 title(base::ASCIIToUTF16("Title ") +
- base::NumberToString16(top_sites_.size() + 1));
- top_sites_.push_back(MostVisitedURL(GURL(spec_item), title));
- }
- ASSERT_TRUE(!top_sites_.empty());
- // Set up redirect to canonical URL. Canonical URL redirects to itself, too.
- top_sites_.back().redirects.push_back(GURL(spec_item));
- }
-}
-
-void TopSitesCacheTest::InitTopSiteCache(const char** spec, size_t size) {
- BuildTopSites(spec, size);
- cache_.SetTopSites(top_sites_);
-}
-
-const char* kTopSitesSpecBasic[] = {
- "http://www.google.com",
- " http://www.gogle.com", // Redirects.
- " http://www.gooogle.com", // Redirects.
- "http://www.youtube.com/a/b",
- " http://www.youtube.com/a/b?test=1", // Redirects.
- "https://www.google.com/",
- " https://www.gogle.com", // Redirects.
- "http://www.example.com:3141/",
-};
-
-TEST_F(TopSitesCacheTest, GetCanonicalURL) {
- InitTopSiteCache(kTopSitesSpecBasic, base::size(kTopSitesSpecBasic));
- struct {
- const char* expected;
- const char* query;
- } test_cases[] = {
- // Already is canonical: redirects.
- {"http://www.google.com/", "http://www.google.com"},
- // Exact match with stored URL: redirects.
- {"http://www.google.com/", "http://www.gooogle.com"},
- // Recognizes despite trailing "/": redirects
- {"http://www.google.com/", "http://www.gooogle.com/"},
- // Exact match with URL with query: redirects.
- {"http://www.youtube.com/a/b", "http://www.youtube.com/a/b?test=1"},
- // No match with URL with query: as-is.
- {"http://www.youtube.com/a/b?test", "http://www.youtube.com/a/b?test"},
- // Never-seen-before URL: as-is.
- {"http://maps.google.com/", "http://maps.google.com/"},
- // Changing port number, does not match: as-is.
- {"http://www.example.com:1234/", "http://www.example.com:1234"},
- // Smart enough to know that port 80 is HTTP: redirects.
- {"http://www.google.com/", "http://www.gooogle.com:80"},
- // Prefix should not work: as-is.
- {"http://www.youtube.com/a", "http://www.youtube.com/a"},
- };
- for (size_t i = 0; i < base::size(test_cases); ++i) {
- std::string expected(test_cases[i].expected);
- std::string query(test_cases[i].query);
- EXPECT_EQ(expected, cache_.GetCanonicalURL(GURL(query)).spec())
- << " for test_case[" << i << "]";
- }
-}
-
-TEST_F(TopSitesCacheTest, IsKnownUrl) {
- InitTopSiteCache(kTopSitesSpecBasic, base::size(kTopSitesSpecBasic));
- // Matches.
- EXPECT_TRUE(cache_.IsKnownURL(GURL("http://www.google.com")));
- EXPECT_TRUE(cache_.IsKnownURL(GURL("http://www.gooogle.com")));
- EXPECT_TRUE(cache_.IsKnownURL(GURL("http://www.google.com/")));
-
- // Non-matches.
- EXPECT_FALSE(cache_.IsKnownURL(GURL("http://www.google.com?")));
- EXPECT_FALSE(cache_.IsKnownURL(GURL("http://www.google.net")));
- EXPECT_FALSE(cache_.IsKnownURL(GURL("http://www.google.com/stuff")));
- EXPECT_FALSE(cache_.IsKnownURL(GURL("https://www.gooogle.com")));
- EXPECT_FALSE(cache_.IsKnownURL(GURL("http://www.youtube.com/a")));
-}
-
-} // namespace
-
-} // namespace history
diff --git a/chromium/components/history/core/browser/top_sites_impl.cc b/chromium/components/history/core/browser/top_sites_impl.cc
index aadfb560f30..29e814e4cbd 100644
--- a/chromium/components/history/core/browser/top_sites_impl.cc
+++ b/chromium/components/history/core/browser/top_sites_impl.cc
@@ -7,7 +7,6 @@
#include <stdint.h>
#include <algorithm>
#include <memory>
-#include <set>
#include <utility>
#include "base/bind.h"
@@ -26,14 +25,13 @@
#include "components/history/core/browser/history_backend.h"
#include "components/history/core/browser/history_constants.h"
#include "components/history/core/browser/history_db_task.h"
-#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/page_usage_data.h"
-#include "components/history/core/browser/top_sites_cache.h"
#include "components/history/core/browser/top_sites_observer.h"
#include "components/history/core/browser/url_utils.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
+#include "url/gurl.h"
namespace history {
namespace {
@@ -91,14 +89,11 @@ TopSitesImpl::TopSitesImpl(PrefService* pref_service,
const PrepopulatedPageList& prepopulated_pages,
const CanAddURLToHistoryFn& can_add_url_to_history)
: backend_(nullptr),
- cache_(std::make_unique<TopSitesCache>()),
- thread_safe_cache_(std::make_unique<TopSitesCache>()),
prepopulated_pages_(prepopulated_pages),
pref_service_(pref_service),
history_service_(history_service),
can_add_url_to_history_(can_add_url_to_history),
- loaded_(false),
- history_service_observer_(this) {
+ loaded_(false) {
DCHECK(pref_service_);
DCHECK(!can_add_url_to_history_.is_null());
}
@@ -128,7 +123,7 @@ void TopSitesImpl::GetMostVisitedURLs(
base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), callback));
return;
}
- filtered_urls = thread_safe_cache_->top_sites();
+ filtered_urls = thread_safe_cache_;
}
callback.Run(filtered_urls);
}
@@ -197,12 +192,8 @@ void TopSitesImpl::ClearBlacklistedURLs() {
NotifyTopSitesChanged(TopSitesObserver::ChangeReason::BLACKLIST);
}
-bool TopSitesImpl::IsKnownURL(const GURL& url) {
- return loaded_ && cache_->IsKnownURL(url);
-}
-
bool TopSitesImpl::IsFull() {
- return loaded_ && cache_->GetNumURLs() >= kTopSitesNumber;
+ return loaded_ && top_sites_.size() >= kTopSitesNumber;
}
PrepopulatedPageList TopSitesImpl::GetPrepopulatedPages() {
@@ -302,17 +293,6 @@ void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list,
}
}
-// static
-int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
- const GURL& url) {
- for (size_t i = 0; i < most_visited.redirects.size(); i++) {
- if (most_visited.redirects[i] == url)
- return static_cast<int>(most_visited.redirects.size() - i - 1);
- }
- NOTREACHED() << "URL should always be found.";
- return 0;
-}
-
bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) const {
bool added = false;
for (const auto& prepopulated_page : prepopulated_pages_) {
@@ -360,7 +340,7 @@ void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites,
AddPrepopulatedPages(&top_sites);
TopSitesDelta delta;
- DiffMostVisited(cache_->top_sites(), top_sites, &delta);
+ DiffMostVisited(top_sites_, top_sites, &delta);
TopSitesBackend::RecordHistogram record_or_not =
TopSitesBackend::RECORD_HISTOGRAM_NO;
@@ -388,12 +368,12 @@ void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites,
// If there is no url change in top sites, check if the titles have changes.
// Notify observers if there's a change in titles.
if (!should_notify_observers)
- should_notify_observers = DoTitlesDiffer(cache_->top_sites(), top_sites);
+ should_notify_observers = DoTitlesDiffer(top_sites_, top_sites);
// We always do the following steps (setting top sites in cache, and resetting
// thread safe cache ...) as this method is invoked during startup at which
// point the caches haven't been updated yet.
- cache_->SetTopSites(top_sites);
+ top_sites_ = top_sites;
ResetThreadSafeCache();
@@ -424,7 +404,7 @@ void TopSitesImpl::MoveStateToLoaded() {
// Now that we're loaded we can service the queued up callbacks. Copy them
// here and service them outside the lock.
if (!pending_callbacks_.empty()) {
- urls = thread_safe_cache_->top_sites();
+ urls = thread_safe_cache_;
pending_callbacks.swap(pending_callbacks_);
}
}
@@ -440,9 +420,9 @@ void TopSitesImpl::MoveStateToLoaded() {
void TopSitesImpl::ResetThreadSafeCache() {
base::AutoLock lock(lock_);
- MostVisitedURLList cached;
- ApplyBlacklist(cache_->top_sites(), &cached);
- thread_safe_cache_->SetTopSites(cached);
+ MostVisitedURLList filtered;
+ ApplyBlacklist(top_sites_, &filtered);
+ thread_safe_cache_ = filtered;
}
void TopSitesImpl::ScheduleUpdateTimer() {
@@ -457,9 +437,8 @@ void TopSitesImpl::OnGotMostVisitedURLs(
const scoped_refptr<MostVisitedThreadSafe>& sites) {
DCHECK(thread_checker_.CalledOnValidThread());
- // Set the top sites directly in the cache so that SetTopSites diffs
- // correctly.
- cache_->SetTopSites(sites->data);
+ // Set |top_sites_| directly so that SetTopSites() diffs correctly.
+ top_sites_ = sites->data;
SetTopSites(sites->data, CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_URLS);
MoveStateToLoaded();
@@ -481,22 +460,6 @@ void TopSitesImpl::OnURLsDeleted(HistoryService* history_service,
if (deletion_info.IsAllHistory()) {
SetTopSites(MostVisitedURLList(), CALL_LOCATION_FROM_OTHER_PLACES);
backend_->ResetDatabase();
- } else {
- std::set<size_t> indices_to_delete; // Indices into top_sites_.
- for (const auto& row : deletion_info.deleted_rows()) {
- if (cache_->IsKnownURL(row.url()))
- indices_to_delete.insert(cache_->GetURLIndex(row.url()));
- }
-
- if (indices_to_delete.empty())
- return;
-
- MostVisitedURLList new_top_sites(cache_->top_sites());
- for (auto i = indices_to_delete.rbegin(); i != indices_to_delete.rend();
- i++) {
- new_top_sites.erase(new_top_sites.begin() + *i);
- }
- SetTopSites(new_top_sites, CALL_LOCATION_FROM_OTHER_PLACES);
}
StartQueryForMostVisited();
}
diff --git a/chromium/components/history/core/browser/top_sites_impl.h b/chromium/components/history/core/browser/top_sites_impl.h
index 9c85817fbe3..1405246bf0d 100644
--- a/chromium/components/history/core/browser/top_sites_impl.h
+++ b/chromium/components/history/core/browser/top_sites_impl.h
@@ -7,9 +7,6 @@
#include <stddef.h>
-#include <list>
-#include <memory>
-#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -23,12 +20,11 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/top_sites.h"
#include "components/history/core/browser/top_sites_backend.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "url/gurl.h"
class PrefRegistrySimple;
class PrefService;
@@ -39,8 +35,6 @@ class FilePath;
namespace history {
-class HistoryService;
-class TopSitesCache;
class TopSitesImplTest;
// This class allows requests for most visited urls on any thread. All other
@@ -72,7 +66,6 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
void RemoveBlacklistedURL(const GURL& url) override;
bool IsBlacklisted(const GURL& url) override;
void ClearBlacklistedURLs() override;
- bool IsKnownURL(const GURL& url) override;
bool IsFull() override;
PrepopulatedPageList GetPrepopulatedPages() override;
bool loaded() const override;
@@ -127,12 +120,6 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
const MostVisitedURLList& new_list,
TopSitesDelta* delta);
- // Finds the given URL in the redirect chain for the given TopSite, and
- // returns the distance from the destination in hops that the given URL is.
- // The URL is assumed to be in the list. The destination is 0.
- static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited,
- const GURL& url);
-
// Adds prepopulated pages to TopSites. Returns true if any pages were added.
bool AddPrepopulatedPages(MostVisitedURLList* urls) const;
@@ -180,16 +167,16 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
scoped_refptr<TopSitesBackend> backend_;
+ // Lock used to access |thread_safe_cache_|.
+ mutable base::Lock lock_;
+
// The top sites data.
- std::unique_ptr<TopSitesCache> cache_;
+ MostVisitedURLList top_sites_;
// Copy of the top sites data that may be accessed on any thread (assuming
// you hold |lock_|). The data in |thread_safe_cache_| has blacklisted urls
- // applied (|cache_| does not).
- std::unique_ptr<TopSitesCache> thread_safe_cache_;
-
- // Lock used to access |thread_safe_cache_|.
- mutable base::Lock lock_;
+ // applied (|top_sites_| does not).
+ MostVisitedURLList thread_safe_cache_ GUARDED_BY(lock_);
// Task tracker for history and backend requests.
base::CancelableTaskTracker cancelable_task_tracker_;
@@ -225,7 +212,7 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
static bool histogram_recorded_;
ScopedObserver<HistoryService, HistoryServiceObserver>
- history_service_observer_;
+ history_service_observer_{this};
DISALLOW_COPY_AND_ASSIGN(TopSitesImpl);
};
diff --git a/chromium/components/history/core/browser/top_sites_impl_unittest.cc b/chromium/components/history/core/browser/top_sites_impl_unittest.cc
index a4acc3125e0..66ab67a3777 100644
--- a/chromium/components/history/core/browser/top_sites_impl_unittest.cc
+++ b/chromium/components/history/core/browser/top_sites_impl_unittest.cc
@@ -14,7 +14,7 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/history/core/browser/history_client.h"
#include "components/history/core/browser/history_constants.h"
@@ -23,7 +23,6 @@
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/top_sites.h"
-#include "components/history/core/browser/top_sites_cache.h"
#include "components/history/core/browser/top_sites_observer.h"
#include "components/history/core/browser/visit_delegate.h"
#include "components/history/core/test/history_service_test_util.h"
@@ -203,10 +202,6 @@ class TopSitesImplTest : public HistoryUnitTestBase {
// Wrappers that allow private TopSites functions to be called from the
// individual tests without making them all be friends.
- GURL GetCanonicalURL(const GURL& url) {
- return top_sites()->cache_->GetCanonicalURL(url);
- }
-
void SetTopSites(const MostVisitedURLList& new_top_sites) {
top_sites()->SetTopSites(new_top_sites,
TopSitesImpl::CALL_LOCATION_FROM_OTHER_PLACES);
@@ -222,8 +217,7 @@ class TopSitesImplTest : public HistoryUnitTestBase {
void EmptyThreadSafeCache() {
base::AutoLock lock(top_sites()->lock_);
- MostVisitedURLList empty;
- top_sites()->thread_safe_cache_->SetTopSites(empty);
+ top_sites()->thread_safe_cache_.clear();
}
void ResetTopSites() {
@@ -247,7 +241,7 @@ class TopSitesImplTest : public HistoryUnitTestBase {
top_sites_impl_->ShutdownOnUIThread();
top_sites_impl_ = nullptr;
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
}
@@ -258,7 +252,7 @@ class TopSitesImplTest : public HistoryUnitTestBase {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir scoped_temp_dir_;
@@ -308,37 +302,6 @@ void AppendMostVisitedURLwithTitle(const GURL& url,
list->push_back(mv);
}
-// Tests GetCanonicalURL.
-TEST_F(TopSitesImplTest, GetCanonicalURL) {
- // Have two chains:
- // google.com -> www.google.com
- // news.google.com (no redirects)
- GURL news("http://news.google.com/");
- GURL source("http://google.com/");
- GURL dest("http://www.google.com/");
-
- std::vector<MostVisitedURL> most_visited;
- AppendMostVisitedURLWithRedirect(source, dest, &most_visited);
- AppendMostVisitedURL(news, &most_visited);
- SetTopSites(most_visited);
-
- // Random URLs not in the database are returned unchanged.
- GURL result = GetCanonicalURL(GURL("http://fark.com/"));
- EXPECT_EQ(GURL("http://fark.com/"), result);
-
- // Easy case, there are no redirects and the exact URL is stored.
- result = GetCanonicalURL(news);
- EXPECT_EQ(news, result);
-
- // The URL in question is the source URL in a redirect list.
- result = GetCanonicalURL(source);
- EXPECT_EQ(dest, result);
-
- // The URL in question is the destination of a redirect.
- result = GetCanonicalURL(dest);
- EXPECT_EQ(dest, result);
-}
-
class MockTopSitesObserver : public TopSitesObserver {
public:
MockTopSitesObserver() {}
@@ -634,6 +597,9 @@ TEST_F(TopSitesImplTest, DeleteNotifications) {
// Wait for history to process the deletion.
WaitForHistory();
+ // The deletion called back to TopSitesImpl (on the main thread), which
+ // triggers a history query. Wait for that to complete.
+ WaitForHistory();
{
TopSitesQuerier querier;
@@ -660,6 +626,9 @@ TEST_F(TopSitesImplTest, DeleteNotifications) {
// Wait for history to process the deletion.
WaitForHistory();
+ // The deletion called back to TopSitesImpl (on the main thread), which
+ // triggers a history query. Wait for that to complete.
+ WaitForHistory();
{
TopSitesQuerier querier;
diff --git a/chromium/components/history/core/browser/web_history_service.cc b/chromium/components/history/core/browser/web_history_service.cc
index 2013cef4ba2..4c05f9a2368 100644
--- a/chromium/components/history/core/browser/web_history_service.cc
+++ b/chromium/components/history/core/browser/web_history_service.cc
@@ -138,7 +138,7 @@ class RequestImpl : public WebHistoryService::Request {
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url_;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = post_data_ ? "POST" : "GET";
resource_request->headers.SetHeader(net::HttpRequestHeaders::kAuthorization,
"Bearer " + access_token_info.token);
diff --git a/chromium/components/history/core/browser/web_history_service_unittest.cc b/chromium/components/history/core/browser/web_history_service_unittest.cc
index 07e3f844bc1..eaf5febf9b8 100644
--- a/chromium/components/history/core/browser/web_history_service_unittest.cc
+++ b/chromium/components/history/core/browser/web_history_service_unittest.cc
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/http/http_status_code.h"
@@ -237,7 +237,7 @@ class WebHistoryServiceTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
TestingWebHistoryService web_history_service_;
diff --git a/chromium/components/image_fetcher/core/cache/image_cache.cc b/chromium/components/image_fetcher/core/cache/image_cache.cc
index 69bd29e48ca..a69cecc9858 100644
--- a/chromium/components/image_fetcher/core/cache/image_cache.cc
+++ b/chromium/components/image_fetcher/core/cache/image_cache.cc
@@ -143,11 +143,11 @@ void ImageCache::OnDependencyInitialized() {
ImageFetcherEvent::kCacheStartupEvictionStarted);
// Once all the queued requests are taken care of, run eviction.
- base::PostTaskWithTraitsAndReply(
- FROM_HERE, {base::TaskPriority::BEST_EFFORT},
- base::BindOnce(OnStartupEvictionQueued),
- base::BindOnce(&ImageCache::RunEvictionOnStartup,
- weak_ptr_factory_.GetWeakPtr()));
+ base::PostTaskAndReply(FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(OnStartupEvictionQueued),
+ base::BindOnce(&ImageCache::RunEvictionOnStartup,
+ weak_ptr_factory_.GetWeakPtr()));
}
void ImageCache::SaveImageImpl(const std::string& url,
diff --git a/chromium/components/image_fetcher/core/cache/image_cache_unittest.cc b/chromium/components/image_fetcher/core/cache/image_cache_unittest.cc
index 19347e26473..b65fedf28fe 100644
--- a/chromium/components/image_fetcher/core/cache/image_cache_unittest.cc
+++ b/chromium/components/image_fetcher/core/cache/image_cache_unittest.cc
@@ -11,8 +11,8 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/image_fetcher/core/cache/image_data_store_disk.h"
#include "components/image_fetcher/core/cache/image_metadata_store_leveldb.h"
@@ -171,7 +171,7 @@ class CachedImageFetcherImageCacheTest : public testing::Test {
FakeDB<CachedImageMetadataProto>* db_;
std::map<std::string, CachedImageMetadataProto> db_store_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(CachedImageFetcherImageCacheTest);
diff --git a/chromium/components/image_fetcher/core/cache/image_data_store_disk_unittest.cc b/chromium/components/image_fetcher/core/cache/image_data_store_disk_unittest.cc
index fecf8bb18ca..2c97e4eed5e 100644
--- a/chromium/components/image_fetcher/core/cache/image_data_store_disk_unittest.cc
+++ b/chromium/components/image_fetcher/core/cache/image_data_store_disk_unittest.cc
@@ -11,7 +11,7 @@
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -92,7 +92,7 @@ class CachedImageFetcherImageDataStoreDiskTest : public testing::Test {
ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(CachedImageFetcherImageDataStoreDiskTest);
};
diff --git a/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc b/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
index 863c8f5f684..94ec75e656b 100644
--- a/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
+++ b/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
@@ -36,10 +36,10 @@ int64_t ToDatabaseTime(base::Time time) {
// The folder where the data will be stored on disk.
const char kImageDatabaseFolder[] = "cached_image_fetcher_images";
-// The amount of data to build up in memory before converting to a sorted on-
-// disk file.
-const size_t kDatabaseWriteBufferSizeBytes = 64 * 1024; // 64KB
-const size_t kDatabaseWriteBufferSizeBytesForLowEndDevice = 32 * 1024; // 32KB
+// Most writes are very small, <100 bytes. This should buffer a handful of them
+// together, but not much more. This should allow a handful of them to be
+// buffered together without causing a significant impact to memory.
+const size_t kDatabaseWriteBufferSizeBytes = 1 * 1024; // 1KB
bool KeyMatcherFilter(std::string key, const std::string& other_key) {
return key.compare(other_key) == 0;
@@ -80,11 +80,7 @@ ImageMetadataStoreLevelDB::~ImageMetadataStoreLevelDB() = default;
void ImageMetadataStoreLevelDB::Initialize(base::OnceClosure callback) {
leveldb_env::Options options = leveldb_proto::CreateSimpleOptions();
- if (base::SysInfo::IsLowEndDevice()) {
- options.write_buffer_size = kDatabaseWriteBufferSizeBytesForLowEndDevice;
- } else {
- options.write_buffer_size = kDatabaseWriteBufferSizeBytes;
- }
+ options.write_buffer_size = kDatabaseWriteBufferSizeBytes;
database_->Init(
options,
diff --git a/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc b/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
index 402bb75cd55..e4415a11d75 100644
--- a/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
+++ b/chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
@@ -8,8 +8,8 @@
#include <utility>
#include "base/bind.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/image_fetcher/core/cache/image_store_types.h"
#include "components/image_fetcher/core/cache/proto/cached_image_metadata.pb.h"
#include "components/leveldb_proto/testing/fake_db.h"
@@ -119,7 +119,7 @@ class CachedImageFetcherImageMetadataStoreLevelDBTest : public testing::Test {
ASSERT_EQ(entry.needs_transcoding(), needs_transcoding);
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
base::SimpleTestClock* clock() { return clock_.get(); }
ImageMetadataStore* metadata_store() { return metadata_store_.get(); }
FakeDB<CachedImageMetadataProto>* db() { return db_; }
@@ -136,7 +136,7 @@ class CachedImageFetcherImageMetadataStoreLevelDBTest : public testing::Test {
std::map<std::string, CachedImageMetadataProto> db_store_;
std::unique_ptr<ImageMetadataStoreLevelDB> metadata_store_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(CachedImageFetcherImageMetadataStoreLevelDBTest);
};
diff --git a/chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc b/chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc
index 2323f8bd51d..d319b181fd5 100644
--- a/chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc
+++ b/chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -15,8 +15,8 @@
#include "base/memory/ref_counted.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/image_fetcher/core/cache/image_cache.h"
#include "components/image_fetcher/core/cache/image_data_store_disk.h"
@@ -113,7 +113,7 @@ class CachedImageFetcherTest : public testing::Test {
RunUntilIdle();
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
CachedImageFetcher* cached_image_fetcher() {
return cached_image_fetcher_.get();
@@ -142,7 +142,7 @@ class CachedImageFetcherTest : public testing::Test {
FakeDB<CachedImageMetadataProto>* db_;
std::map<std::string, CachedImageMetadataProto> metadata_store_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(CachedImageFetcherTest);
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher.cc b/chromium/components/image_fetcher/core/image_data_fetcher.cc
index 0894fc6a3d9..9720fdc2774 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher.cc
+++ b/chromium/components/image_fetcher/core/image_data_fetcher.cc
@@ -81,7 +81,9 @@ void ImageDataFetcher::FetchImageData(
request->url = image_url;
request->referrer_policy = referrer_policy;
request->referrer = GURL(referrer);
- request->allow_credentials = send_cookies;
+ request->credentials_mode = send_cookies
+ ? network::mojom::CredentialsMode::kInclude
+ : network::mojom::CredentialsMode::kOmit;
std::unique_ptr<network::SimpleURLLoader> loader =
network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc b/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc
index 26581aecaf2..c658f782826 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc
+++ b/chromium/components/image_fetcher/core/image_data_fetcher_unittest.cc
@@ -12,7 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -53,7 +53,7 @@ class ImageDataFetcherTest : public testing::Test {
void(const std::string&, const RequestMetadata&));
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
@@ -82,7 +82,8 @@ TEST_F(ImageDataFetcherTest, FetchImageData) {
// provide a response.
const network::ResourceRequest* pending_request;
EXPECT_TRUE(test_url_loader_factory_.IsPending(kImageURL, &pending_request));
- EXPECT_FALSE(pending_request->allow_credentials);
+ EXPECT_EQ(pending_request->credentials_mode,
+ network::mojom::CredentialsMode::kOmit);
network::ResourceResponseHead head;
std::string raw_header =
@@ -115,7 +116,8 @@ TEST_F(ImageDataFetcherTest, FetchImageDataWithCookies) {
// provide a response.
const network::ResourceRequest* pending_request;
EXPECT_TRUE(test_url_loader_factory_.IsPending(kImageURL, &pending_request));
- EXPECT_TRUE(pending_request->allow_credentials);
+ EXPECT_EQ(pending_request->credentials_mode,
+ network::mojom::CredentialsMode::kInclude);
network::ResourceResponseHead head;
std::string raw_header =
diff --git a/chromium/components/image_fetcher/core/image_fetcher_impl_unittest.cc b/chromium/components/image_fetcher/core/image_fetcher_impl_unittest.cc
index 61ad10cc020..6ddd9b77c6c 100644
--- a/chromium/components/image_fetcher/core/image_fetcher_impl_unittest.cc
+++ b/chromium/components/image_fetcher/core/image_fetcher_impl_unittest.cc
@@ -11,7 +11,7 @@
#include "base/files/file_path.h"
#include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
#include "components/image_fetcher/core/image_fetcher.h"
#include "net/http/http_util.h"
@@ -48,7 +48,7 @@ class ImageFetcherImplTest : public testing::Test {
std::move(decoder), shared_factory_);
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
FakeImageDecoder* image_decoder() { return fake_image_decoder_; }
network::TestURLLoaderFactory* test_url_loader_factory() {
@@ -61,7 +61,7 @@ class ImageFetcherImplTest : public testing::Test {
FakeImageDecoder* fake_image_decoder_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(ImageFetcherImplTest);
};
diff --git a/chromium/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc b/chromium/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc
index ba0242b65bb..ad193d34dc7 100644
--- a/chromium/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc
+++ b/chromium/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc
@@ -15,8 +15,8 @@
#include "base/memory/ref_counted.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/image_fetcher/core/cache/image_cache.h"
#include "components/image_fetcher/core/cache/image_data_store_disk.h"
@@ -106,7 +106,7 @@ class ReducedModeImageFetcherTest : public testing::Test {
RunUntilIdle();
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
void VerifyCacheHit() {
RunUntilIdle();
@@ -152,7 +152,7 @@ class ReducedModeImageFetcherTest : public testing::Test {
FakeDB<CachedImageMetadataProto>* db_;
std::map<std::string, CachedImageMetadataProto> metadata_store_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(ReducedModeImageFetcherTest);
diff --git a/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper.mm b/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper.mm
index b56c03ab137..6c113fd821e 100644
--- a/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper.mm
+++ b/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper.mm
@@ -66,9 +66,10 @@ IOSImageDataFetcherWrapper::CallbackForImageDataFetcher(
// The image is a webp image.
RequestMetadata webp_metadata = metadata;
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
{
+ base::ThreadPool(),
base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
},
diff --git a/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm b/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
index 1f8bcb2038b..7787624251f 100644
--- a/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
+++ b/chromium/components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm
@@ -11,7 +11,7 @@
#include "base/mac/scoped_block.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -125,7 +125,7 @@ class IOSImageDataFetcherWrapperTest : public PlatformTest {
}
// Message loop for the main test thread.
- base::test::ScopedTaskEnvironment environment_;
+ base::test::TaskEnvironment environment_;
base::mac::ScopedBlock<ImageDataFetcherBlock> callback_;
network::TestURLLoaderFactory factory_;
diff --git a/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm b/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm
index aca5ea33923..cab9ce3200c 100644
--- a/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm
+++ b/chromium/components/image_fetcher/ios/ios_image_decoder_impl.mm
@@ -41,8 +41,9 @@ class IOSImageDecoderImpl : public ImageDecoder {
// The task runner used to decode images if necessary.
const scoped_refptr<base::TaskRunner> task_runner_ =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
// The WeakPtrFactory is used to cancel callbacks if ImageFetcher is
diff --git a/chromium/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm b/chromium/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm
index 278e1bbf712..78b70d46c40 100644
--- a/chromium/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm
+++ b/chromium/components/image_fetcher/ios/ios_image_decoder_impl_unittest.mm
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "ui/gfx/geometry/size.h"
@@ -65,7 +65,7 @@ class IOSImageDecoderImplTest : public PlatformTest {
~IOSImageDecoderImplTest() override {}
- base::test::ScopedTaskEnvironment scoped_task_evironment_;
+ base::test::TaskEnvironment scoped_task_evironment_;
std::unique_ptr<ImageDecoder> ios_image_decoder_impl_;
gfx::Image decoded_image_;
diff --git a/chromium/components/infobars/core/infobar_delegate.cc b/chromium/components/infobars/core/infobar_delegate.cc
index 59ae71e4343..52e5e428cd9 100644
--- a/chromium/components/infobars/core/infobar_delegate.cc
+++ b/chromium/components/infobars/core/infobar_delegate.cc
@@ -84,38 +84,15 @@ HungRendererInfoBarDelegate* InfoBarDelegate::AsHungRendererInfoBarDelegate() {
return nullptr;
}
-InsecureContentInfoBarDelegate*
- InfoBarDelegate::AsInsecureContentInfoBarDelegate() {
- return nullptr;
-}
-
-NativeAppInfoBarDelegate* InfoBarDelegate::AsNativeAppInfoBarDelegate() {
- return nullptr;
-}
-
PopupBlockedInfoBarDelegate* InfoBarDelegate::AsPopupBlockedInfoBarDelegate() {
return nullptr;
}
-RegisterProtocolHandlerInfoBarDelegate*
- InfoBarDelegate::AsRegisterProtocolHandlerInfoBarDelegate() {
- return nullptr;
-}
-
-ScreenCaptureInfoBarDelegate*
- InfoBarDelegate::AsScreenCaptureInfoBarDelegate() {
- return nullptr;
-}
-
ThemeInstalledInfoBarDelegate*
InfoBarDelegate::AsThemePreviewInfobarDelegate() {
return nullptr;
}
-ThreeDAPIInfoBarDelegate* InfoBarDelegate::AsThreeDAPIInfoBarDelegate() {
- return nullptr;
-}
-
translate::TranslateInfoBarDelegate*
InfoBarDelegate::AsTranslateInfoBarDelegate() {
return nullptr;
diff --git a/chromium/components/infobars/core/infobar_delegate.h b/chromium/components/infobars/core/infobar_delegate.h
index 91cc4bf7d68..1157bbc5acb 100644
--- a/chromium/components/infobars/core/infobar_delegate.h
+++ b/chromium/components/infobars/core/infobar_delegate.h
@@ -12,13 +12,8 @@
class ConfirmInfoBarDelegate;
class HungRendererInfoBarDelegate;
-class InsecureContentInfoBarDelegate;
-class NativeAppInfoBarDelegate;
class PopupBlockedInfoBarDelegate;
-class RegisterProtocolHandlerInfoBarDelegate;
-class ScreenCaptureInfoBarDelegate;
class ThemeInstalledInfoBarDelegate;
-class ThreeDAPIInfoBarDelegate;
#if defined(OS_ANDROID)
namespace offline_pages {
@@ -153,7 +148,7 @@ class InfoBarDelegate {
DOWNLOAD_PROGRESS_INFOBAR_ANDROID = 82,
AR_CORE_UPGRADE_ANDROID = 83,
BLOATED_RENDERER_INFOBAR_DELEGATE = 84,
- SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE = 85,
+ // Removed: SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE = 85,
NEAR_OOM_REDUCTION_INFOBAR_ANDROID = 86,
LITE_PAGE_PREVIEWS_INFOBAR = 87,
MODULE_INSTALL_FAILURE_INFOBAR_ANDROID = 88,
@@ -162,6 +157,8 @@ class InfoBarDelegate {
FLASH_DEPRECATION_INFOBAR_DELEGATE = 91,
SEND_TAB_TO_SELF_INFOBAR_DELEGATE = 92,
TAB_SHARING_INFOBAR_DELEGATE = 93,
+ SAFETY_TIP_INFOBAR_DELEGATE = 94,
+ SMS_RECEIVER_INFOBAR_DELEGATE = 95,
};
// Describes navigation events, used to decide whether infobars should be
@@ -231,14 +228,8 @@ class InfoBarDelegate {
// Type-checking downcast routines:
virtual ConfirmInfoBarDelegate* AsConfirmInfoBarDelegate();
virtual HungRendererInfoBarDelegate* AsHungRendererInfoBarDelegate();
- virtual InsecureContentInfoBarDelegate* AsInsecureContentInfoBarDelegate();
- virtual NativeAppInfoBarDelegate* AsNativeAppInfoBarDelegate();
virtual PopupBlockedInfoBarDelegate* AsPopupBlockedInfoBarDelegate();
- virtual RegisterProtocolHandlerInfoBarDelegate*
- AsRegisterProtocolHandlerInfoBarDelegate();
- virtual ScreenCaptureInfoBarDelegate* AsScreenCaptureInfoBarDelegate();
virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
- virtual ThreeDAPIInfoBarDelegate* AsThreeDAPIInfoBarDelegate();
virtual translate::TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
#if defined(OS_ANDROID)
virtual offline_pages::OfflinePageInfoBarDelegate*
diff --git a/chromium/components/keyed_service/OWNERS b/chromium/components/keyed_service/OWNERS
index 39557cd3030..88763f945b9 100644
--- a/chromium/components/keyed_service/OWNERS
+++ b/chromium/components/keyed_service/OWNERS
@@ -1 +1,3 @@
blundell@chromium.org
+hnakashima@chromium.org
+# COMPONENT: Internals
diff --git a/chromium/components/keyed_service/content/browser_context_keyed_service_factory.h b/chromium/components/keyed_service/content/browser_context_keyed_service_factory.h
index 1df7c6844ab..5a3b2ccfa7b 100644
--- a/chromium/components/keyed_service/content/browser_context_keyed_service_factory.h
+++ b/chromium/components/keyed_service/content/browser_context_keyed_service_factory.h
@@ -110,7 +110,7 @@ class KEYED_SERVICE_EXPORT BrowserContextKeyedServiceFactory
// and the default implementation removes it from |mapping_| and deletes
// the pointer.
virtual void BrowserContextShutdown(content::BrowserContext* context);
- virtual void BrowserContextDestroyed(content::BrowserContext* context);
+ void BrowserContextDestroyed(content::BrowserContext* context);
private:
friend class BrowserContextDependencyManagerUnittests;
diff --git a/chromium/components/keyed_service/core/refcounted_keyed_service.h b/chromium/components/keyed_service/core/refcounted_keyed_service.h
index 24f7d9ebfd8..043b52a341a 100644
--- a/chromium/components/keyed_service/core/refcounted_keyed_service.h
+++ b/chromium/components/keyed_service/core/refcounted_keyed_service.h
@@ -52,7 +52,7 @@ class KEYED_SERVICE_EXPORT RefcountedKeyedService
// If you need your service to be deleted on a specific sequence (for example,
// you're converting a service that used content::DeleteOnThread<IO>), then
// use this constructor with a reference to the SequencedTaskRunner (e.g., you
- // can get it from base::CreateSequencedTaskRunnerWithTraits).
+ // can get it from base::CreateSequencedTaskRunner).
explicit RefcountedKeyedService(
scoped_refptr<base::SequencedTaskRunner> task_runner);
diff --git a/chromium/components/language/content/browser/geo_language_model_unittest.cc b/chromium/components/language/content/browser/geo_language_model_unittest.cc
index 36230f85134..9d45c4a2495 100644
--- a/chromium/components/language/content/browser/geo_language_model_unittest.cc
+++ b/chromium/components/language/content/browser/geo_language_model_unittest.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/timer/timer.h"
#include "components/language/content/browser/geo_language_provider.h"
#include "components/language/content/browser/test_utils.h"
@@ -30,8 +30,7 @@ MATCHER_P(EqualsLd, lang_details, "") {
class GeoLanguageModelTest : public testing::Test {
public:
GeoLanguageModelTest()
- : geo_language_provider_(
- scoped_task_environment_.GetMainThreadTaskRunner()),
+ : geo_language_provider_(task_environment_.GetMainThreadTaskRunner()),
geo_language_model_(&geo_language_provider_),
mock_ip_geo_location_provider_(&mock_geo_location_) {
service_manager::mojom::ConnectorRequest request;
@@ -58,8 +57,8 @@ class GeoLanguageModelTest : public testing::Test {
GeoLanguageModel* language_model() { return &geo_language_model_; }
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private:
GeoLanguageProvider geo_language_provider_;
@@ -75,7 +74,7 @@ TEST_F(GeoLanguageModelTest, InsideIndia) {
// Setup a random place in Madhya Pradesh, India.
MoveToLocation(23.0, 80.0);
StartGeoLanguageProvider();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_THAT(language_model()->GetLanguages(),
testing::ElementsAre(
@@ -87,7 +86,7 @@ TEST_F(GeoLanguageModelTest, OutsideIndia) {
// Setup a random place outside of India.
MoveToLocation(45.5, 73.5);
StartGeoLanguageProvider();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(0UL, language_model()->GetLanguages().size());
}
diff --git a/chromium/components/language/content/browser/geo_language_provider.cc b/chromium/components/language/content/browser/geo_language_provider.cc
index a2cde93e15f..f0d3fb99920 100644
--- a/chromium/components/language/content/browser/geo_language_provider.cc
+++ b/chromium/components/language/content/browser/geo_language_provider.cc
@@ -32,8 +32,9 @@ const char GeoLanguageProvider::kCachedGeoLanguagesPref[] =
GeoLanguageProvider::GeoLanguageProvider()
: creation_task_runner_(base::SequencedTaskRunnerHandle::Get()),
- background_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ background_task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
prefs_(nullptr) {
// Constructor is not required to run on |background_task_runner_|:
diff --git a/chromium/components/language/content/browser/geo_language_provider_unittest.cc b/chromium/components/language/content/browser/geo_language_provider_unittest.cc
index a00653258ce..54129fc2072 100644
--- a/chromium/components/language/content/browser/geo_language_provider_unittest.cc
+++ b/chromium/components/language/content/browser/geo_language_provider_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/timer/timer.h"
#include "components/language/content/browser/test_utils.h"
@@ -25,8 +25,7 @@ namespace language {
class GeoLanguageProviderTest : public testing::Test {
public:
GeoLanguageProviderTest()
- : geo_language_provider_(
- scoped_task_environment_.GetMainThreadTaskRunner()),
+ : geo_language_provider_(task_environment_.GetMainThreadTaskRunner()),
mock_ip_geo_location_provider_(&mock_geo_location_) {
service_manager::mojom::ConnectorRequest request;
connector_ = service_manager::Connector::Create(&request);
@@ -81,8 +80,8 @@ class GeoLanguageProviderTest : public testing::Test {
}
base::test::ScopedFeatureList scoped_feature_list_;
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private:
// Object under test.
@@ -97,7 +96,7 @@ TEST_F(GeoLanguageProviderTest, GetCurrentGeoLanguages_India) {
// Setup a random place in West Bengal, India.
MoveToLocation(23.0, 85.7);
StartGeoLanguageProvider();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
std::vector<std::string> expected_langs = {"hi", "bn", "en"};
EXPECT_EQ(expected_langs, GetCurrentGeoLanguages());
@@ -107,7 +106,7 @@ TEST_F(GeoLanguageProviderTest, GetCurrentGeoLanguages_OutsideIndia) {
// Setup a random place in Montreal, Canada.
MoveToLocation(45.5, 73.5);
StartGeoLanguageProvider();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
std::vector<std::string> expected_langs = {};
EXPECT_EQ(expected_langs, GetCurrentGeoLanguages());
@@ -117,13 +116,13 @@ TEST_F(GeoLanguageProviderTest, NoFrequentCalls) {
// Setup a random place in Madhya Pradesh, India.
MoveToLocation(23.0, 80.0);
StartGeoLanguageProvider();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
const std::vector<std::string>& result = GetCurrentGeoLanguages();
std::vector<std::string> expected_langs = {"hi", "en"};
EXPECT_EQ(expected_langs, result);
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromHours(12));
+ task_environment_.FastForwardBy(base::TimeDelta::FromHours(12));
EXPECT_EQ(1, GetQueryNextPositionCalledTimes());
EXPECT_EQ(expected_langs, GetCachedLanguages());
}
@@ -132,7 +131,7 @@ TEST_F(GeoLanguageProviderTest, ButDoCallInTheNextDay) {
// Setup a random place in Madhya Pradesh, India.
MoveToLocation(23.0, 80.0);
StartGeoLanguageProvider();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
std::vector<std::string> result = GetCurrentGeoLanguages();
std::vector<std::string> expected_langs = {"hi", "en"};
@@ -141,7 +140,7 @@ TEST_F(GeoLanguageProviderTest, ButDoCallInTheNextDay) {
// Move to another random place in Karnataka, India.
MoveToLocation(23.0, 85.7);
- scoped_task_environment_.FastForwardBy(base::TimeDelta::FromHours(25));
+ task_environment_.FastForwardBy(base::TimeDelta::FromHours(25));
EXPECT_EQ(2, GetQueryNextPositionCalledTimes());
result = GetCurrentGeoLanguages();
@@ -158,7 +157,7 @@ TEST_F(GeoLanguageProviderTest, CachedLanguagesPresent) {
std::vector<std::string> expected_langs = {"en", "fr"};
EXPECT_EQ(expected_langs, GetCurrentGeoLanguages());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
expected_langs = {"hi", "en"};
EXPECT_EQ(expected_langs, GetCurrentGeoLanguages());
diff --git a/chromium/components/language/content/browser/test_utils.cc b/chromium/components/language/content/browser/test_utils.cc
index ca19235cb4d..4d904d5f73f 100644
--- a/chromium/components/language/content/browser/test_utils.cc
+++ b/chromium/components/language/content/browser/test_utils.cc
@@ -6,7 +6,7 @@
namespace language {
-MockGeoLocation::MockGeoLocation() : binding_(this) {}
+MockGeoLocation::MockGeoLocation() {}
MockGeoLocation::~MockGeoLocation() {}
void MockGeoLocation::SetHighAccuracy(bool high_accuracy) {}
@@ -17,8 +17,8 @@ void MockGeoLocation::QueryNextPosition(QueryNextPositionCallback callback) {
}
void MockGeoLocation::BindGeoLocation(
- device::mojom::GeolocationRequest request) {
- binding_.Bind(std::move(request));
+ mojo::PendingReceiver<device::mojom::Geolocation> receiver) {
+ receiver_.Bind(std::move(receiver));
}
void MockGeoLocation::MoveToLocation(float latitude, float longitude) {
@@ -28,19 +28,20 @@ void MockGeoLocation::MoveToLocation(float latitude, float longitude) {
MockIpGeoLocationProvider::MockIpGeoLocationProvider(
MockGeoLocation* mock_geo_location)
- : mock_geo_location_(mock_geo_location), binding_(this) {}
+ : mock_geo_location_(mock_geo_location) {}
MockIpGeoLocationProvider::~MockIpGeoLocationProvider() {}
void MockIpGeoLocationProvider::Bind(mojo::ScopedMessagePipeHandle handle) {
- binding_.Bind(device::mojom::PublicIpAddressGeolocationProviderRequest(
- std::move(handle)));
+ receiver_.Bind(
+ mojo::PendingReceiver<device::mojom::PublicIpAddressGeolocationProvider>(
+ std::move(handle)));
}
void MockIpGeoLocationProvider::CreateGeolocation(
const net::MutablePartialNetworkTrafficAnnotationTag& /* unused */,
- device::mojom::GeolocationRequest request) {
- mock_geo_location_->BindGeoLocation(std::move(request));
+ mojo::PendingReceiver<device::mojom::Geolocation> receiver) {
+ mock_geo_location_->BindGeoLocation(std::move(receiver));
}
} // namespace language
diff --git a/chromium/components/language/content/browser/test_utils.h b/chromium/components/language/content/browser/test_utils.h
index 74310cabe27..74233110b22 100644
--- a/chromium/components/language/content/browser/test_utils.h
+++ b/chromium/components/language/content/browser/test_utils.h
@@ -5,7 +5,8 @@
#ifndef COMPONENTS_LANGUAGE_CONTENT_BROWSER_TEST_UTILS_H_
#define COMPONENTS_LANGUAGE_CONTENT_BROWSER_TEST_UTILS_H_
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/geolocation.mojom.h"
#include "services/device/public/mojom/geoposition.mojom.h"
@@ -26,7 +27,8 @@ class MockGeoLocation : public device::mojom::Geolocation {
void SetHighAccuracy(bool high_accuracy) override;
void QueryNextPosition(QueryNextPositionCallback callback) override;
- void BindGeoLocation(device::mojom::GeolocationRequest request);
+ void BindGeoLocation(
+ mojo::PendingReceiver<device::mojom::Geolocation> receiver);
void MoveToLocation(float latitude, float longitude);
int query_next_position_called_times() const {
@@ -36,7 +38,7 @@ class MockGeoLocation : public device::mojom::Geolocation {
private:
int query_next_position_called_times_ = 0;
device::mojom::Geoposition position_;
- mojo::Binding<device::mojom::Geolocation> binding_;
+ mojo::Receiver<device::mojom::Geolocation> receiver_{this};
};
// Mock impl of mojom::PublicIpAddressGeolocationProvider that binds Geolocation
@@ -51,11 +53,12 @@ class MockIpGeoLocationProvider
void CreateGeolocation(
const net::MutablePartialNetworkTrafficAnnotationTag& /* unused */,
- device::mojom::GeolocationRequest request) override;
+ mojo::PendingReceiver<device::mojom::Geolocation> receiver) override;
private:
MockGeoLocation* mock_geo_location_;
- mojo::Binding<device::mojom::PublicIpAddressGeolocationProvider> binding_;
+ mojo::Receiver<device::mojom::PublicIpAddressGeolocationProvider> receiver_{
+ this};
};
} // namespace language
diff --git a/chromium/components/language/core/common/language_experiments.cc b/chromium/components/language/core/common/language_experiments.cc
index e7cec355796..df4c1f77551 100644
--- a/chromium/components/language/core/common/language_experiments.cc
+++ b/chromium/components/language/core/common/language_experiments.cc
@@ -24,7 +24,7 @@ const base::Feature kImprovedGeoLanguageData{"ImprovedGeoLanguageData",
const base::Feature kUseFluentLanguageModel{"UseFluentLanguageModel",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kNotifySyncOnLanguageDetermined{
- "NotifySyncOnLanguageDetermined", base::FEATURE_DISABLED_BY_DEFAULT};
+ "NotifySyncOnLanguageDetermined", base::FEATURE_ENABLED_BY_DEFAULT};
// Base feature for Translate desktop UI experiment
const base::Feature kUseButtonTranslateBubbleUi{
diff --git a/chromium/components/language_usage_metrics/OWNERS b/chromium/components/language_usage_metrics/OWNERS
index bb5c3afcabc..29abffbbee9 100644
--- a/chromium/components/language_usage_metrics/OWNERS
+++ b/chromium/components/language_usage_metrics/OWNERS
@@ -1 +1,2 @@
file://components/translate/OWNERS
+# COMPONENT: UI>Browser>Language
diff --git a/chromium/components/leveldb_proto/BUILD.gn b/chromium/components/leveldb_proto/BUILD.gn
index fb521c3c645..6dae43b59ca 100644
--- a/chromium/components/leveldb_proto/BUILD.gn
+++ b/chromium/components/leveldb_proto/BUILD.gn
@@ -10,7 +10,7 @@ proto_library("proto") {
]
}
-static_library("leveldb_proto") {
+component("leveldb_proto") {
sources = [
"internal/leveldb_database.cc",
"internal/leveldb_database.h",
@@ -41,6 +41,7 @@ static_library("leveldb_proto") {
"public/shared_proto_database_client_list.cc",
"public/shared_proto_database_client_list.h",
]
+ defines = [ "IS_LEVELDB_PROTO_IMPL" ]
deps = [
":proto",
]
@@ -76,6 +77,7 @@ source_set("unit_tests") {
"internal/unique_proto_database_unittest.cc",
]
deps = [
+ ":proto",
":test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/leveldb_proto/OWNERS b/chromium/components/leveldb_proto/OWNERS
index 3bf6060c1ae..6774f0e0a72 100644
--- a/chromium/components/leveldb_proto/OWNERS
+++ b/chromium/components/leveldb_proto/OWNERS
@@ -2,3 +2,4 @@ nyquist@chromium.org
ssid@chromium.org
# COMPONENT: Internals
+# TEAM: chromium-reviews@chromium.org
diff --git a/chromium/components/leveldb_proto/content/BUILD.gn b/chromium/components/leveldb_proto/content/BUILD.gn
deleted file mode 100644
index 7915c4963e0..00000000000
--- a/chromium/components/leveldb_proto/content/BUILD.gn
+++ /dev/null
@@ -1,21 +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.
-
-assert(!is_ios)
-
-source_set("factory") {
- sources = [
- "proto_database_provider_factory.cc",
- "proto_database_provider_factory.h",
- ]
-
- public_deps = [
- "//base",
- "//components/keyed_service/content",
- ]
-
- deps = [
- "//content/public/browser",
- ]
-}
diff --git a/chromium/components/leveldb_proto/content/proto_database_provider_factory.cc b/chromium/components/leveldb_proto/content/proto_database_provider_factory.cc
deleted file mode 100644
index ce86c510a7c..00000000000
--- a/chromium/components/leveldb_proto/content/proto_database_provider_factory.cc
+++ /dev/null
@@ -1,45 +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 "components/leveldb_proto/content/proto_database_provider_factory.h"
-
-#include "base/memory/singleton.h"
-#include "base/no_destructor.h"
-#include "components/keyed_service/core/simple_dependency_manager.h"
-#include "components/keyed_service/core/simple_factory_key.h"
-#include "components/leveldb_proto/public/proto_database_provider.h"
-
-namespace leveldb_proto {
-
-// static
-ProtoDatabaseProviderFactory* ProtoDatabaseProviderFactory::GetInstance() {
- static base::NoDestructor<ProtoDatabaseProviderFactory> instance;
- return instance.get();
-}
-
-// static
-ProtoDatabaseProvider* ProtoDatabaseProviderFactory::GetForKey(
- SimpleFactoryKey* key) {
- return static_cast<ProtoDatabaseProvider*>(
- GetInstance()->GetServiceForKey(key, true));
-}
-
-// static
-void ProtoDatabaseProviderFactory::RemoveKeyForTesting(SimpleFactoryKey* key) {
- GetInstance()->SimpleContextDestroyed(key);
-}
-
-ProtoDatabaseProviderFactory::ProtoDatabaseProviderFactory()
- : SimpleKeyedServiceFactory("leveldb_proto::ProtoDatabaseProvider",
- SimpleDependencyManager::GetInstance()) {}
-
-ProtoDatabaseProviderFactory::~ProtoDatabaseProviderFactory() = default;
-
-std::unique_ptr<KeyedService>
-ProtoDatabaseProviderFactory::BuildServiceInstanceFor(
- SimpleFactoryKey* key) const {
- return std::make_unique<ProtoDatabaseProvider>(key->GetPath());
-}
-
-} // namespace leveldb_proto
diff --git a/chromium/components/leveldb_proto/content/proto_database_provider_factory.h b/chromium/components/leveldb_proto/content/proto_database_provider_factory.h
deleted file mode 100644
index ceba819e67f..00000000000
--- a/chromium/components/leveldb_proto/content/proto_database_provider_factory.h
+++ /dev/null
@@ -1,55 +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 COMPONENTS_LEVELDB_PROTO_CONTENT_PROTO_DATABASE_PROVIDER_FACTORY_H_
-#define COMPONENTS_LEVELDB_PROTO_CONTENT_PROTO_DATABASE_PROVIDER_FACTORY_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/keyed_service/core/simple_keyed_service_factory.h"
-
-class KeyedService;
-class SimpleFactoryKey;
-
-namespace base {
-template <typename T>
-class NoDestructor;
-} // namespace base
-
-namespace leveldb_proto {
-class ProtoDatabaseProvider;
-
-// A factory for ProtoDatabaseProvider, a class that provides proto databases
-// stored in the appropriate directory for the current profile.
-class ProtoDatabaseProviderFactory : public SimpleKeyedServiceFactory {
- public:
- // Returns singleton instance of ProtoDatabaseProviderFactory.
- static ProtoDatabaseProviderFactory* GetInstance();
-
- // Returns ProtoDatabaseProvider associated with |key|, so we can
- // instantiate ProtoDatabases that use the appropriate profile directory.
- static ProtoDatabaseProvider* GetForKey(SimpleFactoryKey* key);
-
- // Some tests may get databases with manually created keys, this method
- // removes a key from the mapping to avoid reusing a database from a past
- // test.
- static void RemoveKeyForTesting(SimpleFactoryKey* key);
-
- private:
- friend class base::NoDestructor<ProtoDatabaseProviderFactory>;
-
- ProtoDatabaseProviderFactory();
- ~ProtoDatabaseProviderFactory() override;
-
- // SimpleKeyedServiceFactory overrides:
- std::unique_ptr<KeyedService> BuildServiceInstanceFor(
- SimpleFactoryKey* key) const override;
-
- DISALLOW_COPY_AND_ASSIGN(ProtoDatabaseProviderFactory);
-};
-
-} // namespace leveldb_proto
-
-#endif // COMPONENTS_LEVELDB_PROTO_CONTENT_PROTO_DATABASE_PROVIDER_FACTORY_H_
diff --git a/chromium/components/leveldb_proto/internal/leveldb_database.h b/chromium/components/leveldb_proto/internal/leveldb_database.h
index 049f255a1f9..4aff9b23ea4 100644
--- a/chromium/components/leveldb_proto/internal/leveldb_database.h
+++ b/chromium/components/leveldb_proto/internal/leveldb_database.h
@@ -10,6 +10,7 @@
#include <string>
#include <vector>
+#include "base/component_export.h"
#include "base/strings/string_split.h"
#include "components/leveldb_proto/public/proto_database.h"
#include "third_party/leveldatabase/env_chromium.h"
@@ -29,7 +30,7 @@ namespace leveldb_proto {
// Interacts with the LevelDB third party module.
// Once constructed, function calls and destruction should all occur on the
// same thread (not necessarily the same as the constructor).
-class LevelDB {
+class COMPONENT_EXPORT(LEVELDB_PROTO) LevelDB {
public:
// Constructor. Does *not* open a leveldb - only initialize this class.
// |client_name| is the name of the "client" that owns this instance. Used
diff --git a/chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h b/chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h
index f87217ded92..a4711650e83 100644
--- a/chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h
+++ b/chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h
@@ -5,11 +5,13 @@
#ifndef COMPONENTS_LEVELDB_PROTO_INTERNAL_LEVELDB_PROTO_FEATURE_LIST_H_
#define COMPONENTS_LEVELDB_PROTO_INTERNAL_LEVELDB_PROTO_FEATURE_LIST_H_
+#include "base/component_export.h"
#include "base/feature_list.h"
namespace leveldb_proto {
-extern const base::Feature kProtoDBSharedMigration;
+extern const COMPONENT_EXPORT(LEVELDB_PROTO) base::Feature
+ kProtoDBSharedMigration;
} // namespace leveldb_proto
diff --git a/chromium/components/leveldb_proto/internal/proto_database_impl.h b/chromium/components/leveldb_proto/internal/proto_database_impl.h
index d80bd8ca3cd..2125bef8a45 100644
--- a/chromium/components/leveldb_proto/internal/proto_database_impl.h
+++ b/chromium/components/leveldb_proto/internal/proto_database_impl.h
@@ -41,21 +41,21 @@ void GetSharedDBInstance(
// Update transactions happen on background task runner and callback runs on the
// client task runner.
-void RunUpdateCallback(
+void COMPONENT_EXPORT(LEVELDB_PROTO) RunUpdateCallback(
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
Callbacks::UpdateCallback callback,
bool success);
// Load transactions happen on background task runner. The loaded keys need to
// be given to clients on client task runner.
-void RunLoadKeysCallback(
+void COMPONENT_EXPORT(LEVELDB_PROTO) RunLoadKeysCallback(
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
Callbacks::LoadKeysCallback callback,
bool success,
std::unique_ptr<KeyVector> keys);
// Helper to run destroy callback on the client task runner.
-void RunDestroyCallback(
+void COMPONENT_EXPORT(LEVELDB_PROTO) RunDestroyCallback(
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
Callbacks::DestroyCallback callback,
bool success);
diff --git a/chromium/components/leveldb_proto/internal/proto_database_impl_unittest.cc b/chromium/components/leveldb_proto/internal/proto_database_impl_unittest.cc
index 98ce3eab752..af0c96481c5 100644
--- a/chromium/components/leveldb_proto/internal/proto_database_impl_unittest.cc
+++ b/chromium/components/leveldb_proto/internal/proto_database_impl_unittest.cc
@@ -7,9 +7,9 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/task/thread_pool/thread_pool.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "components/leveldb_proto/internal/leveldb_proto_feature_list.h"
#include "components/leveldb_proto/internal/shared_proto_database_provider.h"
@@ -394,7 +394,7 @@ class ProtoDatabaseImplTest : public testing::Test {
private:
std::unique_ptr<base::ScopedTempDir> temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::test::ScopedFeatureList scoped_feature_list_;
// Shared database.
diff --git a/chromium/components/leveldb_proto/internal/proto_database_selector.cc b/chromium/components/leveldb_proto/internal/proto_database_selector.cc
index 417b23fb5bc..f45386524a4 100644
--- a/chromium/components/leveldb_proto/internal/proto_database_selector.cc
+++ b/chromium/components/leveldb_proto/internal/proto_database_selector.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/metrics/histogram_macros.h"
#include "components/leveldb_proto/internal/migration_delegate.h"
#include "components/leveldb_proto/internal/shared_proto_database.h"
#include "components/leveldb_proto/internal/shared_proto_database_provider.h"
@@ -25,6 +26,12 @@ void RunInitCallbackOnTaskRunner(
} // namespace
+// static
+void ProtoDatabaseSelector::RecordInitState(
+ ProtoDatabaseSelector::ProtoDatabaseInitState state) {
+ UMA_HISTOGRAM_ENUMERATION("ProtoDB.SharedDbInitStatus", state);
+}
+
ProtoDatabaseSelector::ProtoDatabaseSelector(
ProtoDbType db_type,
scoped_refptr<base::SequencedTaskRunner> task_runner,
@@ -57,7 +64,7 @@ void ProtoDatabaseSelector::InitWithDatabase(
database, database_dir, options, false,
base::BindOnce(&RunInitCallbackOnTaskRunner, std::move(callback),
callback_task_runner));
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kLegacyInitCalled);
}
void ProtoDatabaseSelector::InitUniqueOrShared(
@@ -67,6 +74,7 @@ void ProtoDatabaseSelector::InitUniqueOrShared(
bool use_shared_db,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
Callbacks::InitStatusCallback callback) {
+ RecordInitState(ProtoDatabaseInitState::kSharedDbInitAttempted);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
init_status_ = InitStatus::IN_PROGRESS;
unique_database_dir_ = db_dir;
@@ -112,7 +120,7 @@ void ProtoDatabaseSelector::OnInitUniqueDB(
if (status == Enums::InitStatus::kCorrupt) {
db_ = std::move(unique_db);
std::move(callback).Run(Enums::InitStatus::kCorrupt);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kFailureUniqueDbCorrupted);
return;
}
@@ -127,7 +135,7 @@ void ProtoDatabaseSelector::OnInitUniqueDB(
if (!db_provider_ || unique_database_dir_.empty()) {
db_ = std::move(unique_db);
std::move(callback).Run(status);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kFailureNoDatabaseProvider);
return;
}
@@ -175,7 +183,7 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!unique_db && !client) {
std::move(callback).Run(Enums::InitStatus::kError);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kBothUniqueAndSharedFailedOpen);
return;
}
@@ -184,7 +192,7 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
// If there's no shared client and one is requested we return an error,
// because it should be created if missing.
std::move(callback).Run(Enums::InitStatus::kError);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kSharedDbClientMissingInitFailed);
return;
} else {
// ProtoLevelDBWrapper::InitWithDatabase() returns kInvalidOperation when
@@ -194,13 +202,14 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
// return the unique DB.
db_ = std::move(unique_db);
std::move(callback).Run(Enums::InitStatus::kOK);
- OnInitDone();
+ OnInitDone(
+ ProtoDatabaseInitState::kSharedDbClientMissingUniqueReturned);
return;
} else {
// If the shared DB failed to open and a unique DB is requested then we
// throw an error, as the shared DB may contain unmigrated data.
std::move(callback).Run(Enums::InitStatus::kError);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kSharedDbOpenFailed);
return;
}
}
@@ -221,14 +230,14 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL);
db_ = std::move(client);
std::move(callback).Run(Enums::InitStatus::kOK);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kUniqueDbMissingSharedReturned);
return;
} else {
// If the unique DB failed to open and the migration status is not
// attempted then we return an error, as we don't know if the unique
// DB contains any data.
std::move(callback).Run(Enums::InitStatus::kError);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kUniqueDbOpenFailed);
return;
}
break;
@@ -241,7 +250,7 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
// and there's no way to migrate.
db_ = std::move(client);
std::move(callback).Run(Enums::InitStatus::kOK);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kMigratedSharedDbOpened);
return;
break;
case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL:
@@ -250,7 +259,7 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
// we throw an error. We ignore the deletion flag because we want both
// databases to be open before we delete the shared DB.
std::move(callback).Run(Enums::InitStatus::kError);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kUniqueDbOpenFailed);
return;
break;
}
@@ -264,6 +273,7 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
// Migrate from unique to shared.
UniqueProtoDatabase* from = unique_db.get();
UniqueProtoDatabase* to = client.get();
+ RecordInitState(ProtoDatabaseInitState::kMigrateToSharedAttempted);
migration_delegate_->DoMigration(
from, to,
base::BindOnce(&ProtoDatabaseSelector::OnMigrationTransferComplete,
@@ -294,6 +304,7 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
// Migrate from shared to unique.
UniqueProtoDatabase* from = client.get();
UniqueProtoDatabase* to = unique_db.get();
+ RecordInitState(ProtoDatabaseInitState::kMigrateToUniqueAttempted);
migration_delegate_->DoMigration(
from, to,
base::BindOnce(&ProtoDatabaseSelector::OnMigrationTransferComplete,
@@ -358,12 +369,15 @@ void ProtoDatabaseSelector::MaybeDoMigrationOnDeletingOld(
: SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED);
db_ = use_shared_db ? std::move(unique_db) : std::move(client);
std::move(callback).Run(Enums::InitStatus::kOK);
- OnInitDone();
+ OnInitDone(ProtoDatabaseInitState::kDeletionOfOldDataFailed);
return;
}
auto* from = use_shared_db ? unique_db.get() : client.get();
auto* to = use_shared_db ? client.get() : unique_db.get();
+ RecordInitState(use_shared_db
+ ? ProtoDatabaseInitState::kMigrateToSharedAttempted
+ : ProtoDatabaseInitState::kMigrateToUniqueAttempted);
migration_delegate_->DoMigration(
from, to,
base::BindOnce(&ProtoDatabaseSelector::OnMigrationTransferComplete, this,
@@ -397,7 +411,8 @@ void ProtoDatabaseSelector::OnMigrationTransferComplete(
: SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED);
db_ = use_shared_db ? std::move(unique_db) : std::move(client);
std::move(callback).Run(Enums::InitStatus::kOK);
- OnInitDone();
+ OnInitDone(use_shared_db ? ProtoDatabaseInitState::kMigrateToSharedFailed
+ : ProtoDatabaseInitState::kMigrateToUniqueFailed);
}
void ProtoDatabaseSelector::OnMigrationCleanupComplete(
@@ -410,20 +425,27 @@ void ProtoDatabaseSelector::OnMigrationCleanupComplete(
// We still return true in our callback below because we do have a database as
// far as the original caller is concerned. As long as |db_| is assigned, we
// return true.
+ ProtoDatabaseInitState state;
if (success) {
client->UpdateClientInitMetadata(
use_shared_db ? SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL
: SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL);
+ state = use_shared_db ? ProtoDatabaseInitState::kMigrateToSharedSuccess
+ : ProtoDatabaseInitState::kMigrateToUniqueSuccess;
} else {
client->UpdateClientInitMetadata(
use_shared_db
? SharedDBMetadataProto::MIGRATE_TO_SHARED_UNIQUE_TO_BE_DELETED
: SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED);
+ state =
+ use_shared_db
+ ? ProtoDatabaseInitState::kMigrateToUniqueCompleteDeletionFailed
+ : ProtoDatabaseInitState::kMigrateToSharedCompleteDeletionFailed;
}
// Migration transfer was complete. So, we should use the requested database.
db_ = use_shared_db ? std::move(client) : std::move(unique_db);
std::move(callback).Run(Enums::InitStatus::kOK);
- OnInitDone();
+ OnInitDone(state);
}
void ProtoDatabaseSelector::AddTransaction(base::OnceClosure task) {
@@ -579,7 +601,10 @@ void ProtoDatabaseSelector::RemoveKeysForTesting(
db_->RemoveKeysForTesting(key_filter, target_prefix, std::move(callback));
}
-void ProtoDatabaseSelector::OnInitDone() {
+void ProtoDatabaseSelector::OnInitDone(
+ ProtoDatabaseSelector::ProtoDatabaseInitState state) {
+ RecordInitState(state);
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
init_status_ = InitStatus::DONE;
while (!pending_tasks_.empty()) {
diff --git a/chromium/components/leveldb_proto/internal/proto_database_selector.h b/chromium/components/leveldb_proto/internal/proto_database_selector.h
index 48cab0c47d1..3d158882d4d 100644
--- a/chromium/components/leveldb_proto/internal/proto_database_selector.h
+++ b/chromium/components/leveldb_proto/internal/proto_database_selector.h
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include "base/component_export.h"
#include "base/containers/queue.h"
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
@@ -25,9 +26,44 @@ class UniqueProtoDatabase;
// A wrapper around unique and shared database client. Handles initialization of
// underlying database as unique or shared as requested.
// TODO: Discuss the init flow/migration path for unique/shared DB here.
-class ProtoDatabaseSelector
+class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector
: public base::RefCountedThreadSafe<ProtoDatabaseSelector> {
public:
+ // These values are logged to UMA. Entries should not be renumbered and
+ // numeric values should never be reused. Please keep in sync with
+ // "ProtoDatabaseInitState" in src/tools/metrics/histograms/enums.xml.
+ enum class ProtoDatabaseInitState {
+ kSharedDbInitAttempted = 0,
+ kFailureUniqueDbCorrupted = 1,
+ kFailureNoDatabaseProvider = 2,
+ kBothUniqueAndSharedFailedOpen = 3,
+ kSharedDbClientMissingInitFailed = 4,
+ kSharedDbClientMissingUniqueReturned = 5,
+ kSharedDbOpenFailed = 6,
+ kUniqueDbMissingSharedReturned = 7,
+ kUniqueDbOpenFailed = 8,
+ kMigrateToSharedAttempted = 9,
+ kMigrateToUniqueAttempted = 10,
+ kMigratedSharedDbOpened = 11,
+ kDeletionOfOldDataFailed = 12,
+ kMigrateToSharedFailed = 13,
+ kMigrateToUniqueFailed = 14,
+ kMigrateToSharedCompleteDeletionFailed = 15,
+ kMigrateToUniqueCompleteDeletionFailed = 16,
+ kMigrateToSharedSuccess = 17,
+ kMigrateToUniqueSuccess = 18,
+ kLegacyInitCalled = 19,
+ kSharedDbMetadataLoadFailed = 20,
+ kSharedDbMetadataWriteFailed = 21,
+ kSharedDbClientCorrupt = 22,
+ kSharedDbClientSuccess = 23,
+ kSharedLevelDbInitFailure = 24,
+ kSharedDbClientMissing = 25,
+ kMaxValue = kSharedDbClientMissing
+ };
+
+ static void RecordInitState(ProtoDatabaseInitState state);
+
ProtoDatabaseSelector(
ProtoDbType db_type,
scoped_refptr<base::SequencedTaskRunner> task_runner,
@@ -146,7 +182,7 @@ class ProtoDatabaseSelector
bool use_shared_db,
Callbacks::InitStatusCallback callback,
bool success);
- void OnInitDone();
+ void OnInitDone(ProtoDatabaseInitState state);
ProtoDbType db_type_;
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/chromium/components/leveldb_proto/internal/proto_leveldb_wrapper.h b/chromium/components/leveldb_proto/internal/proto_leveldb_wrapper.h
index 7f4dfc4ebba..0ed2d84342b 100644
--- a/chromium/components/leveldb_proto/internal/proto_leveldb_wrapper.h
+++ b/chromium/components/leveldb_proto/internal/proto_leveldb_wrapper.h
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/component_export.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
@@ -38,7 +39,7 @@ using ValueVector = std::vector<std::string>;
// When the ProtoDatabase instance is deleted, in-progress asynchronous
// operations will be completed and the corresponding callbacks will be called.
// Construction/calls/destruction should all happen on the same thread.
-class ProtoLevelDBWrapper {
+class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoLevelDBWrapper {
public:
// Used to destroy database when initialization fails.
static void Destroy(
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database.cc b/chromium/components/leveldb_proto/internal/shared_proto_database.cc
index 6c897a905b0..a95aeaa9a2c 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database.cc
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database.cc
@@ -11,6 +11,7 @@
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "components/leveldb_proto/internal/leveldb_database.h"
+#include "components/leveldb_proto/internal/proto_database_selector.h"
#include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
@@ -37,7 +38,9 @@ inline void RunInitStatusCallbackOnCallingSequence(
SharedProtoDatabase::SharedClientInitCallback callback,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
Enums::InitStatus status,
- SharedDBMetadataProto::MigrationStatus migration_status) {
+ SharedDBMetadataProto::MigrationStatus migration_status,
+ ProtoDatabaseSelector::ProtoDatabaseInitState metric) {
+ ProtoDatabaseSelector::RecordInitState(metric);
callback_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), status, migration_status));
}
@@ -54,8 +57,13 @@ SharedProtoDatabase::InitRequest::~InitRequest() = default;
SharedProtoDatabase::SharedProtoDatabase(const std::string& client_db_id,
const base::FilePath& db_dir)
- : task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ : task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ // crbug/1006954 and crbug/976223 explain why one of the clients
+ // needs run in visible priority. Download DB is always loaded to
+ // check for in progress downloads at startup. So, always load shared
+ // db in USER_VISIBLE priority.
+ base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
db_dir_(db_dir),
db_(std::make_unique<LevelDB>(client_db_id.c_str())),
@@ -139,7 +147,9 @@ void SharedProtoDatabase::OnGetClientMetadata(
if (!success) {
RunInitStatusCallbackOnCallingSequence(
std::move(callback), std::move(callback_task_runner),
- Enums::InitStatus::kOK, SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED);
+ Enums::InitStatus::kOK, SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED,
+ ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kSharedDbMetadataLoadFailed);
return;
}
if (!proto || !proto->has_migration_status()) {
@@ -154,19 +164,24 @@ void SharedProtoDatabase::OnGetClientMetadata(
RunInitStatusCallbackOnCallingSequence(
std::move(callback), std::move(callback_task_runner),
Enums::InitStatus::kOK,
- SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED);
+ SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED,
+ ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kSharedDbMetadataWriteFailed);
},
std::move(callback), std::move(callback_task_runner)));
return;
}
// If we've made it here, we know that the current status of our database is
// OK. Make it return corrupt if the metadata disagrees.
+ bool is_corrupt = metadata_->corruptions() != proto->corruptions();
RunInitStatusCallbackOnCallingSequence(
std::move(callback), std::move(callback_task_runner),
- metadata_->corruptions() != proto->corruptions()
- ? Enums::InitStatus::kCorrupt
- : Enums::InitStatus::kOK,
- proto->migration_status());
+ is_corrupt ? Enums::InitStatus::kCorrupt : Enums::InitStatus::kOK,
+ proto->migration_status(),
+ is_corrupt ? ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kSharedDbClientCorrupt
+ : ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kSharedDbClientSuccess);
}
void SharedProtoDatabase::CheckCorruptionAndRunInitCallback(
@@ -181,7 +196,8 @@ void SharedProtoDatabase::CheckCorruptionAndRunInitCallback(
}
RunInitStatusCallbackOnCallingSequence(
std::move(callback), std::move(callback_task_runner), init_status_,
- SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED);
+ SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED,
+ ProtoDatabaseSelector::ProtoDatabaseInitState::kSharedLevelDbInitFailure);
}
// Setting |create_if_missing| to false allows us to test whether or not the
@@ -225,7 +241,9 @@ void SharedProtoDatabase::Init(
RunInitStatusCallbackOnCallingSequence(
std::move(callback), std::move(callback_task_runner),
Enums::InitStatus::kError,
- SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED);
+ SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED,
+ ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kSharedLevelDbInitFailure);
break;
case InitState::kNotFound:
@@ -244,7 +262,9 @@ void SharedProtoDatabase::Init(
RunInitStatusCallbackOnCallingSequence(
std::move(callback), std::move(callback_task_runner),
Enums::InitStatus::kInvalidOperation,
- SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED);
+ SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED,
+ ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kSharedDbClientMissing);
}
break;
}
@@ -412,7 +432,8 @@ void SharedProtoDatabase::OnDatabaseInit(Enums::InitStatus status) {
Callbacks::UpdateCallback obsolete_cleared_callback = base::DoNothing();
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&DestroyObsoleteSharedProtoDatabaseClients,
+ base::BindOnce(&SharedProtoDatabaseClient::
+ DestroyObsoleteSharedProtoDatabaseClients,
std::move(db_wrapper),
std::move(obsolete_cleared_callback)),
kDelayToClearObsoleteDatabase);
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database.h b/chromium/components/leveldb_proto/internal/shared_proto_database.h
index f2e15090319..025af89adb5 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database.h
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database.h
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/component_export.h"
#include "base/containers/queue.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
@@ -22,7 +23,7 @@ namespace leveldb_proto {
// Controls a single LevelDB database to be used by many clients, and provides
// a way to get SharedProtoDatabaseClients that allow shared access to the
// underlying single database.
-class SharedProtoDatabase
+class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabase
: public base::RefCountedThreadSafe<SharedProtoDatabase> {
public:
using SharedClientInitCallback =
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database_client.cc b/chromium/components/leveldb_proto/internal/shared_proto_database_client.cc
index cee0dcc4725..631194ce614 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database_client.cc
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database_client.cc
@@ -42,35 +42,43 @@ class ObsoleteClientsDbHolder
} // namespace
-std::string StripPrefix(const std::string& key, const std::string& prefix) {
+// static
+std::string SharedProtoDatabaseClient::StripPrefix(const std::string& key,
+ const std::string& prefix) {
return base::StartsWith(key, prefix, base::CompareCase::SENSITIVE)
? key.substr(prefix.length())
: key;
}
-std::unique_ptr<KeyVector> PrefixStrings(std::unique_ptr<KeyVector> strings,
- const std::string& prefix) {
+// static
+std::unique_ptr<KeyVector> SharedProtoDatabaseClient::PrefixStrings(
+ std::unique_ptr<KeyVector> strings,
+ const std::string& prefix) {
for (auto& str : *strings)
str.assign(base::StrCat({prefix, str}));
return strings;
}
-bool KeyFilterStripPrefix(const KeyFilter& key_filter,
- const std::string& prefix,
- const std::string& key) {
+// static
+bool SharedProtoDatabaseClient::KeyFilterStripPrefix(
+ const KeyFilter& key_filter,
+ const std::string& prefix,
+ const std::string& key) {
if (key_filter.is_null())
return true;
return key_filter.Run(StripPrefix(key, prefix));
}
-void GetSharedDatabaseInitStatusAsync(
+// static
+void SharedProtoDatabaseClient::GetSharedDatabaseInitStatusAsync(
const std::string& client_db_id,
const scoped_refptr<SharedProtoDatabase>& shared_db,
Callbacks::InitStatusCallback callback) {
shared_db->GetDatabaseInitStatusAsync(client_db_id, std::move(callback));
}
-void UpdateClientMetadataAsync(
+// static
+void SharedProtoDatabaseClient::UpdateClientMetadataAsync(
const scoped_refptr<SharedProtoDatabase>& shared_db,
const std::string& client_db_id,
SharedDBMetadataProto::MigrationStatus migration_status,
@@ -79,7 +87,8 @@ void UpdateClientMetadataAsync(
std::move(callback));
}
-void DestroyObsoleteSharedProtoDatabaseClients(
+// static
+void SharedProtoDatabaseClient::DestroyObsoleteSharedProtoDatabaseClients(
std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
Callbacks::UpdateCallback callback) {
ProtoLevelDBWrapper* db_wrapper_ptr = db_wrapper.get();
@@ -107,7 +116,9 @@ void DestroyObsoleteSharedProtoDatabaseClients(
}
}
-void SetObsoleteClientListForTesting(const ProtoDbType* list) {
+// static
+void SharedProtoDatabaseClient::SetObsoleteClientListForTesting(
+ const ProtoDbType* list) {
g_obsolete_client_list_for_testing = list;
}
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database_client.h b/chromium/components/leveldb_proto/internal/shared_proto_database_client.h
index 2bbc1f7e96a..e1c3960f411 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database_client.h
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database_client.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/bind.h"
+#include "base/component_export.h"
#include "base/sequence_checker.h"
#include "components/leveldb_proto/internal/leveldb_database.h"
#include "components/leveldb_proto/internal/proto/shared_db_metadata.pb.h"
@@ -25,45 +26,48 @@ using SharedClientInitCallback =
base::OnceCallback<void(Enums::InitStatus,
SharedDBMetadataProto::MigrationStatus)>;
-std::string StripPrefix(const std::string& key, const std::string& prefix);
-
-std::unique_ptr<KeyVector> PrefixStrings(std::unique_ptr<KeyVector> strings,
- const std::string& prefix);
-
-bool KeyFilterStripPrefix(const KeyFilter& key_filter,
- const std::string& prefix,
- const std::string& key);
-
-void GetSharedDatabaseInitStatusAsync(
- const std::string& client_db_id,
- const scoped_refptr<SharedProtoDatabase>& db,
- Callbacks::InitStatusCallback callback);
-
-void UpdateClientMetadataAsync(
- const scoped_refptr<SharedProtoDatabase>& db,
- const std::string& client_db_id,
- SharedDBMetadataProto::MigrationStatus migration_status,
- ClientCorruptCallback callback);
-
-// Destroys all the data from obsolete clients, for the given |db_wrapper|
-// instance. |callback| is called once all the obsolete clients data are
-// removed, with failure status if one or more of the update fails.
-void DestroyObsoleteSharedProtoDatabaseClients(
- std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
- Callbacks::UpdateCallback callback);
-
-// Sets list of client names that are obsolete and will be cleared by next call
-// to DestroyObsoleteSharedProtoDatabaseClients(). |list| is list of dbs
-// with a |LAST| to mark the end of list.
-void SetObsoleteClientListForTesting(const ProtoDbType* list);
-
// An implementation of ProtoDatabase<T> that uses a shared LevelDB and task
// runner.
// Should be created, destroyed, and used on the same sequenced task runner.
-class SharedProtoDatabaseClient : public UniqueProtoDatabase {
+class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabaseClient
+ : public UniqueProtoDatabase {
public:
static std::string PrefixForDatabase(ProtoDbType db_type);
+ static std::string StripPrefix(const std::string& key,
+ const std::string& prefix);
+
+ static std::unique_ptr<KeyVector> PrefixStrings(
+ std::unique_ptr<KeyVector> strings,
+ const std::string& prefix);
+
+ static bool KeyFilterStripPrefix(const KeyFilter& key_filter,
+ const std::string& prefix,
+ const std::string& key);
+
+ static void GetSharedDatabaseInitStatusAsync(
+ const std::string& client_db_id,
+ const scoped_refptr<SharedProtoDatabase>& db,
+ Callbacks::InitStatusCallback callback);
+
+ static void UpdateClientMetadataAsync(
+ const scoped_refptr<SharedProtoDatabase>& db,
+ const std::string& client_db_id,
+ SharedDBMetadataProto::MigrationStatus migration_status,
+ ClientCorruptCallback callback);
+
+ // Destroys all the data from obsolete clients, for the given |db_wrapper|
+ // instance. |callback| is called once all the obsolete clients data are
+ // removed, with failure status if one or more of the update fails.
+ static void DestroyObsoleteSharedProtoDatabaseClients(
+ std::unique_ptr<ProtoLevelDBWrapper> db_wrapper,
+ Callbacks::UpdateCallback callback);
+
+ // Sets list of client names that are obsolete and will be cleared by next
+ // call to DestroyObsoleteSharedProtoDatabaseClients(). |list| is list of dbs
+ // with a |LAST| to mark the end of list.
+ static void SetObsoleteClientListForTesting(const ProtoDbType* list);
+
~SharedProtoDatabaseClient() override;
void Init(const std::string& client_uma_name,
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc b/chromium/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc
index e64ba45db0f..5c527216974 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database_client_unittest.cc
@@ -12,7 +12,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
#include "components/leveldb_proto/internal/shared_proto_database.h"
#include "components/leveldb_proto/public/shared_proto_database_client_list.h"
@@ -254,7 +254,7 @@ class SharedProtoDatabaseClientTest : public testing::Test {
// Sets the obsolete client list to given list, runs clean up tasks and waits
// for them to complete.
void DestroyObsoleteClientsAndWait(const ProtoDbType* client_list) {
- SetObsoleteClientListForTesting(client_list);
+ SharedProtoDatabaseClient::SetObsoleteClientListForTesting(client_list);
base::RunLoop wait_loop;
Callbacks::UpdateCallback wait_callback = base::BindOnce(
[](base::OnceClosure closure, bool success) {
@@ -263,12 +263,12 @@ class SharedProtoDatabaseClientTest : public testing::Test {
},
wait_loop.QuitClosure());
- DestroyObsoleteSharedProtoDatabaseClients(
+ SharedProtoDatabaseClient::DestroyObsoleteSharedProtoDatabaseClients(
std::make_unique<ProtoLevelDBWrapper>(
db_->database_task_runner_for_testing(), GetLevelDB()),
std::move(wait_callback));
wait_loop.Run();
- SetObsoleteClientListForTesting(nullptr);
+ SharedProtoDatabaseClient::SetObsoleteClientListForTesting(nullptr);
}
void UpdateMetadataAsync(
@@ -282,13 +282,14 @@ class SharedProtoDatabaseClientTest : public testing::Test {
},
wait_loop.QuitClosure());
client->set_migration_status(migration_status);
- UpdateClientMetadataAsync(client->parent_db_, client->prefix_,
- migration_status, std::move(wait_callback));
+ SharedProtoDatabaseClient::UpdateClientMetadataAsync(
+ client->parent_db_, client->prefix_, migration_status,
+ std::move(wait_callback));
wait_loop.Run();
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<SharedProtoDatabase> db_;
std::unique_ptr<base::ScopedTempDir> temp_dir_;
@@ -669,4 +670,4 @@ TEST_F(SharedProtoDatabaseClientTest, UpdateClientMetadataAsync) {
SharedDBMetadataProto::MIGRATION_NOT_ATTEMPTED);
}
-} // namespace leveldb_proto \ No newline at end of file
+} // namespace leveldb_proto
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database_provider.h b/chromium/components/leveldb_proto/internal/shared_proto_database_provider.h
index 62b6188435c..a5e9ebac306 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database_provider.h
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database_provider.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_PROVIDER_H_
#define COMPONENTS_LEVELDB_PROTO_INTERNAL_SHARED_PROTO_DATABASE_PROVIDER_H_
+#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
@@ -17,7 +18,7 @@ class ProtoDatabaseProvider;
// provider to be used in the wrapper. |client_task_runner| is the
// SequencedTaskRunner provided by the main provider so its WeakPtrs are
// always checked on the right sequence.
-class SharedProtoDatabaseProvider {
+class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabaseProvider {
public:
using GetSharedDBInstanceCallback =
base::OnceCallback<void(scoped_refptr<SharedProtoDatabase>)>;
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database_unittest.cc b/chromium/components/leveldb_proto/internal/shared_proto_database_unittest.cc
index e2a596498b5..736d01dcd32 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database_unittest.cc
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
@@ -53,7 +53,7 @@ class SharedProtoDatabaseTest : public testing::Test {
FROM_HERE,
base::BindOnce(&SharedProtoDatabase::Init, db_, create_if_missing,
client_name, std::move(callback),
- scoped_task_environment_.GetMainThreadTaskRunner()));
+ task_environment_.GetMainThreadTaskRunner()));
}
void KillDB() { db_.reset(); }
@@ -85,14 +85,14 @@ class SharedProtoDatabaseTest : public testing::Test {
}
scoped_refptr<base::SequencedTaskRunner> GetMainThreadTaskRunner() {
- return scoped_task_environment_.GetMainThreadTaskRunner();
+ return task_environment_.GetMainThreadTaskRunner();
}
SharedProtoDatabase* db() { return db_.get(); }
ProtoLevelDBWrapper* wrapper() { return db_->db_wrapper_.get(); }
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<base::ScopedTempDir> temp_dir_;
scoped_refptr<SharedProtoDatabase> db_;
diff --git a/chromium/components/leveldb_proto/internal/unique_proto_database.h b/chromium/components/leveldb_proto/internal/unique_proto_database.h
index 8b113361ffd..c093069982b 100644
--- a/chromium/components/leveldb_proto/internal/unique_proto_database.h
+++ b/chromium/components/leveldb_proto/internal/unique_proto_database.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/bind.h"
+#include "base/component_export.h"
#include "base/sequence_checker.h"
#include "components/leveldb_proto/internal/proto_leveldb_wrapper.h"
#include "components/leveldb_proto/public/proto_database.h"
@@ -17,7 +18,7 @@ namespace leveldb_proto {
// An implementation of ProtoDatabase<std::string> that manages the lifecycle of
// a unique LevelDB instance.
-class UniqueProtoDatabase {
+class COMPONENT_EXPORT(LEVELDB_PROTO) UniqueProtoDatabase {
public:
explicit UniqueProtoDatabase(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
diff --git a/chromium/components/leveldb_proto/internal/unique_proto_database_unittest.cc b/chromium/components/leveldb_proto/internal/unique_proto_database_unittest.cc
index 71dcb9c7b16..33e3943ec0b 100644
--- a/chromium/components/leveldb_proto/internal/unique_proto_database_unittest.cc
+++ b/chromium/components/leveldb_proto/internal/unique_proto_database_unittest.cc
@@ -17,7 +17,7 @@
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/leveldb_proto/internal/leveldb_database.h"
@@ -30,7 +30,7 @@
#include "third_party/leveldatabase/leveldb_chrome.h"
using base::ScopedTempDir;
-using base::test::ScopedTaskEnvironment;
+using base::test::TaskEnvironment;
using leveldb_env::Options;
using testing::_;
using testing::Invoke;
@@ -231,7 +231,7 @@ class UniqueProtoDatabaseTest : public testing::Test {
}
const Matcher<const Options&> options_;
- ScopedTaskEnvironment task_environment_;
+ TaskEnvironment task_environment_;
std::unique_ptr<ProtoDatabaseImpl<TestProto>> db_;
};
@@ -561,7 +561,7 @@ class UniqueProtoDatabaseLevelDBTest : public testing::Test {
void TearDown() override { base::RunLoop().RunUntilIdle(); }
private:
- ScopedTaskEnvironment scoped_task_environment_;
+ TaskEnvironment task_environment_;
};
TEST_F(UniqueProtoDatabaseLevelDBTest, TestDBSaveAndLoadKeys) {
@@ -793,7 +793,7 @@ TEST_F(UniqueProtoDatabaseTest, TestDBRemoveFailure) {
// This tests that normal usage of the real database does not cause any
// threading violations.
TEST(UniqueProtoDatabaseThreadingTest, TestDBDestruction) {
- ScopedTaskEnvironment scoped_task_environment;
+ TaskEnvironment task_environment;
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
@@ -827,7 +827,7 @@ TEST(UniqueProtoDatabaseThreadingTest, TestDBDestruction) {
// This tests that normal usage of the real database does not cause any
// threading violations.
TEST(UniqueProtoDatabaseThreadingTest, TestDBDestroy) {
- ScopedTaskEnvironment scoped_task_environment;
+ TaskEnvironment task_environment;
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/chromium/components/leveldb_proto/public/proto_database.h b/chromium/components/leveldb_proto/public/proto_database.h
index e2fcba1b26d..65994524367 100644
--- a/chromium/components/leveldb_proto/public/proto_database.h
+++ b/chromium/components/leveldb_proto/public/proto_database.h
@@ -8,6 +8,7 @@
#include <map>
#include <vector>
+#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
@@ -216,7 +217,7 @@ class ProtoDatabase {
// Return a new instance of Options, but with two additions:
// 1) create_if_missing = true
// 2) max_open_files = 0
-leveldb_env::Options CreateSimpleOptions();
+leveldb_env::Options COMPONENT_EXPORT(LEVELDB_PROTO) CreateSimpleOptions();
} // namespace leveldb_proto
diff --git a/chromium/components/leveldb_proto/public/proto_database_provider.h b/chromium/components/leveldb_proto/public/proto_database_provider.h
index f29e5f6f88a..a33452cd5cd 100644
--- a/chromium/components/leveldb_proto/public/proto_database_provider.h
+++ b/chromium/components/leveldb_proto/public/proto_database_provider.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/sequenced_task_runner.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -19,9 +20,9 @@ namespace leveldb_proto {
class SharedProtoDatabase;
-// A KeyedService that provides instances of ProtoDatabase tied to the current
+// Class that provides instances of ProtoDatabase tied to the current
// profile directory.
-class ProtoDatabaseProvider : public KeyedService {
+class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseProvider {
public:
using GetSharedDBInstanceCallback =
base::OnceCallback<void(scoped_refptr<SharedProtoDatabase>)>;
@@ -52,7 +53,7 @@ class ProtoDatabaseProvider : public KeyedService {
GetSharedDBInstanceCallback callback,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner);
- ~ProtoDatabaseProvider() override;
+ virtual ~ProtoDatabaseProvider();
private:
friend class TestProtoDatabaseProvider;
diff --git a/chromium/components/leveldb_proto/public/shared_proto_database_client_list.cc b/chromium/components/leveldb_proto/public/shared_proto_database_client_list.cc
index 09df6061ddb..4b05fa898aa 100644
--- a/chromium/components/leveldb_proto/public/shared_proto_database_client_list.cc
+++ b/chromium/components/leveldb_proto/public/shared_proto_database_client_list.cc
@@ -67,6 +67,10 @@ std::string SharedProtoDatabaseClientList::ProtoDbTypeToString(
return "StrikeService";
case ProtoDbType::HINT_CACHE_STORE:
return "PreviewsHintCacheStore";
+ case ProtoDbType::DOWNLOAD_DB:
+ return "DownloadDB";
+ case ProtoDbType::VIDEO_DECODE_STATS_DB:
+ return "VideoDecodeStatsDB";
case ProtoDbType::LAST:
NOTREACHED();
return std::string();
diff --git a/chromium/components/leveldb_proto/public/shared_proto_database_client_list.h b/chromium/components/leveldb_proto/public/shared_proto_database_client_list.h
index e46ecef0372..548018d19a8 100644
--- a/chromium/components/leveldb_proto/public/shared_proto_database_client_list.h
+++ b/chromium/components/leveldb_proto/public/shared_proto_database_client_list.h
@@ -9,6 +9,8 @@
#include <string>
+#include "base/component_export.h"
+
namespace leveldb_proto {
const char* const kFeatureEngagementName = "FeatureEngagement";
@@ -38,6 +40,8 @@ enum class ProtoDbType {
BUDGET_DATABASE = 18,
STRIKE_DATABASE = 19,
HINT_CACHE_STORE = 20,
+ DOWNLOAD_DB = 21,
+ VIDEO_DECODE_STATS_DB = 22,
LAST,
};
@@ -57,7 +61,7 @@ constexpr ProtoDbType kObsoleteSharedProtoDbTypeClients[] = {
ProtoDbType::LAST, // Marks the end of list.
};
-class SharedProtoDatabaseClientList {
+class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabaseClientList {
public:
// Determines if the given |db_type| should use a unique or shared DB.
static bool ShouldUseSharedDB(ProtoDbType db_type);
diff --git a/chromium/components/link_header_util/BUILD.gn b/chromium/components/link_header_util/BUILD.gn
index 6faef62389c..c7042bfa3fe 100644
--- a/chromium/components/link_header_util/BUILD.gn
+++ b/chromium/components/link_header_util/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//testing/libfuzzer/fuzzer_test.gni")
+
static_library("link_header_util") {
sources = [
"link_header_util.cc",
@@ -27,3 +29,14 @@ source_set("unit_tests") {
"//testing/gtest",
]
}
+
+fuzzer_test("link_header_util_fuzzer") {
+ sources = [
+ "link_header_util_fuzzer.cc",
+ ]
+ deps = [
+ ":link_header_util",
+ "//base",
+ ]
+ libfuzzer_options = [ "max_len=65535" ]
+}
diff --git a/chromium/components/link_header_util/OWNERS b/chromium/components/link_header_util/OWNERS
index d5c009c4f1d..5b898582486 100644
--- a/chromium/components/link_header_util/OWNERS
+++ b/chromium/components/link_header_util/OWNERS
@@ -1,5 +1,9 @@
mek@chromium.org
yoavweiss@chromium.org
+# The Link: header can be parsed at high privilege, so please include a security
+# reviewer as well:
+file://base/SECURITY_OWNERS
+
# TEAM: loading-dev@chromium.org
# COMPONENT: Blink>Loader
diff --git a/chromium/components/link_header_util/link_header_util_fuzzer.cc b/chromium/components/link_header_util/link_header_util_fuzzer.cc
new file mode 100644
index 00000000000..42f2b7f6495
--- /dev/null
+++ b/chromium/components/link_header_util/link_header_util_fuzzer.cc
@@ -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.
+
+#include <assert.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "base/optional.h"
+#include "components/link_header_util/link_header_util.h"
+
+namespace link_header_util {
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ const std::string input(reinterpret_cast<const char*>(data), size);
+ const auto result = SplitLinkHeader(input);
+
+ for (const auto& pair : result) {
+ assert(pair.first < pair.second);
+ std::string url;
+ std::unordered_map<std::string, base::Optional<std::string>> params;
+ (void)ParseLinkHeaderValue(pair.first, pair.second, &url, &params);
+ }
+
+ return 0;
+}
+
+} // namespace link_header_util
diff --git a/chromium/components/location/android/java/src/org/chromium/components/location/LocationUtils.java b/chromium/components/location/android/java/src/org/chromium/components/location/LocationUtils.java
index 857f2bbb254..9213e013f42 100644
--- a/chromium/components/location/android/java/src/org/chromium/components/location/LocationUtils.java
+++ b/chromium/components/location/android/java/src/org/chromium/components/location/LocationUtils.java
@@ -5,7 +5,6 @@
package org.chromium.components.location;
import android.Manifest;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -20,6 +19,7 @@ import org.chromium.base.Callback;
import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
+import org.chromium.base.compat.ApiHelperForP;
import org.chromium.ui.base.WindowAndroid;
/**
@@ -72,14 +72,13 @@ public class LocationUtils {
* Returns whether location services are enabled system-wide, i.e. whether any application is
* able to access location.
*/
- @SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public boolean isSystemLocationSettingEnabled() {
Context context = ContextUtils.getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
- return locationManager != null && locationManager.isLocationEnabled();
+ return locationManager != null && ApiHelperForP.isLocationEnabled(locationManager);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
@@ -94,14 +93,13 @@ public class LocationUtils {
* Returns whether location services are enabled in sensors-only mode, i.e. when network
* location services are disabled but GPS and other sensors are enabled.
*/
- @SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public boolean isSystemLocationSettingSensorsOnly() {
Context context = ContextUtils.getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
LocationManager locationManager =
(LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
- return locationManager != null && locationManager.isLocationEnabled()
+ return locationManager != null && ApiHelperForP.isLocationEnabled(locationManager)
&& locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
&& !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
diff --git a/chromium/components/login/OWNERS b/chromium/components/login/OWNERS
index 5539f89a17c..f9350fc0704 100644
--- a/chromium/components/login/OWNERS
+++ b/chromium/components/login/OWNERS
@@ -1,4 +1,4 @@
achuith@chromium.org
alemate@chromium.org
-piman@chromium.org
xiyuan@chromium.org
+# COMPONENT: UI>Shell>OOBE
diff --git a/chromium/components/login/localized_values_builder.cc b/chromium/components/login/localized_values_builder.cc
index 2107b10ecfb..82f560201f0 100644
--- a/chromium/components/login/localized_values_builder.cc
+++ b/chromium/components/login/localized_values_builder.cc
@@ -47,6 +47,15 @@ void LocalizedValuesBuilder::AddF(const std::string& key,
void LocalizedValuesBuilder::AddF(const std::string& key,
int message_id,
+ const base::string16& a,
+ const base::string16& b,
+ const base::string16& c) {
+ dict_->SetString(prefix_ + key,
+ l10n_util::GetStringFUTF16(message_id, a, b, c));
+}
+
+void LocalizedValuesBuilder::AddF(const std::string& key,
+ int message_id,
int message_id_a) {
AddF(key, message_id, l10n_util::GetStringUTF16(message_id_a));
}
@@ -59,4 +68,14 @@ void LocalizedValuesBuilder::AddF(const std::string& key,
l10n_util::GetStringUTF16(message_id_b));
}
+void LocalizedValuesBuilder::AddF(const std::string& key,
+ int message_id,
+ int message_id_a,
+ int message_id_b,
+ int message_id_c) {
+ AddF(key, message_id, l10n_util::GetStringUTF16(message_id_a),
+ l10n_util::GetStringUTF16(message_id_b),
+ l10n_util::GetStringUTF16(message_id_c));
+}
+
} // namespace login
diff --git a/chromium/components/login/localized_values_builder.h b/chromium/components/login/localized_values_builder.h
index 8c1731c87d1..a0b6392ea47 100644
--- a/chromium/components/login/localized_values_builder.h
+++ b/chromium/components/login/localized_values_builder.h
@@ -51,6 +51,15 @@ class LOGIN_EXPORT LocalizedValuesBuilder {
// Method to declare localized value. |key| is the i18n key used in html.
// |message_id| is a resource id of message. Message is expected to have
+ // two format parameters subsituted by |a|, |b| and |c| respectively.
+ void AddF(const std::string& key,
+ int message_id,
+ const base::string16& a,
+ const base::string16& b,
+ const base::string16& c);
+
+ // Method to declare localized value. |key| is the i18n key used in html.
+ // |message_id| is a resource id of message. Message is expected to have
// one format parameter subsituted by resource identified by |message_id_a|.
void AddF(const std::string& key, int message_id, int message_id_a);
@@ -63,6 +72,16 @@ class LOGIN_EXPORT LocalizedValuesBuilder {
int message_id_a,
int message_id_b);
+ // Method to declare localized value. |key| is the i18n key used in html.
+ // |message_id| is a resource id of message. Message is expected to have
+ // three format parameters subsituted by resource identified by
+ // |message_id_a|, |message_id_b| and |message_id_c| respectively.
+ void AddF(const std::string& key,
+ int message_id,
+ int message_id_a,
+ int message_id_b,
+ int message_id_c);
+
private:
std::string prefix_;
diff --git a/chromium/components/login/secure_module_util_chromeos.cc b/chromium/components/login/secure_module_util_chromeos.cc
index 25fc3eb7c89..695a7e9b673 100644
--- a/chromium/components/login/secure_module_util_chromeos.cc
+++ b/chromium/components/login/secure_module_util_chromeos.cc
@@ -38,8 +38,9 @@ void GetSecureModuleUsed(GetSecureModuleUsedCallback callback) {
return;
}
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&GetSecureModuleInfoFromFilesAndCacheIt),
std::move(callback));
}
diff --git a/chromium/components/management_strings.grdp b/chromium/components/management_strings.grdp
index 9cebc28ac80..b18bb77755b 100644
--- a/chromium/components/management_strings.grdp
+++ b/chromium/components/management_strings.grdp
@@ -140,7 +140,7 @@
Your device name and network address
</message>
<message name="IDS_MANAGEMENT_EXTENSION_REPORT_USERNAME" desc="Message explaining that an extension currently reports the user's username">
- Usernames for your device and browser
+ Your device username and Chrome username
</message>
<message name="IDS_MANAGEMENT_EXTENSION_REPORT_VERSION" desc="Message explaining that an extension currently reports the user's browser and machine version">
Version information about your device and browser
@@ -157,4 +157,33 @@
<message name="IDS_MANAGEMENT_EXTENSION_REPORT_PERF_CRASH" desc="Message explaining that an extension currently reports the user's performance data and crash report">
Performance data and crash reports
</message>
+
+ <!-- Strings related to Chrome Enterprise Threat Protection -->
+ <message name="IDS_MANAGEMENT_THREAT_PROTECTION" desc="Title of the Chrome Enterprise Threat Protection section of the page">
+ Chrome Enterprise Threat Protection
+ </message>
+ <message name="IDS_MANAGEMENT_THREAT_PROTECTION_DESCRIPTION" desc="Description of the Chrome Enterprise Threat Protection section of the page">
+ Your administrator has enabled Chrome Enterprise Threat Protection on your browser. Chrome Enterprise Threat Protection has access to some of your data.
+ </message>
+ <message name="IDS_MANAGEMENT_THREAT_PROTECTION_DESCRIPTION_BY" desc="Description of the Chrome Enterprise Threat Protection section of the page">
+ <ph name="ENROLLMENT_DOMAIN">$1<ex>example.com</ex></ph> has enabled Chrome Enterprise Threat Protection on your browser. Chrome Enterprise Threat Protection has access to some of your data.
+ </message>
+ <message name="IDS_MANAGEMENT_DATA_LOSS_PREVENTION_NAME" desc="Name for the data loss prevention feature">
+ Data Loss Prevention
+ </message>
+ <message name="IDS_MANAGEMENT_DATA_LOSS_PREVENTION_PERMISSIONS" desc="Permissions description for the data loss prevention feature">
+ Scan the contents of the cache and files that you download or upload in Chrome.
+ </message>
+ <message name="IDS_MANAGEMENT_MALWARE_SCANNING_NAME" desc="Name for the malware scanning feature">
+ Malware Scanning
+ </message>
+ <message name="IDS_MANAGEMENT_MALWARE_SCANNING_PERMISSIONS" desc="Permissions description for the malware scanning feature">
+ Scan files that you download or upload in Chrome.
+ </message>
+ <message name="IDS_MANAGEMENT_ENTERPRISE_REPORTING_NAME" desc="Name for the enterprise reporting feature">
+ Enterprise Reporting
+ </message>
+ <message name="IDS_MANAGEMENT_ENTERPRISE_REPORTING_PERMISSIONS" desc="Permissions description for the enterprise reporting feature">
+ Share data about security events that have been flagged by Chrome Enterprise Threat Protection with your Administrator. These may include page urls, file name and file metadata, your device username and Chrome username.
+ </message>
</grit-part>
diff --git a/chromium/components/media_message_center/BUILD.gn b/chromium/components/media_message_center/BUILD.gn
index cd232b64c94..20ae4865287 100644
--- a/chromium/components/media_message_center/BUILD.gn
+++ b/chromium/components/media_message_center/BUILD.gn
@@ -4,6 +4,8 @@
component("media_message_center") {
sources = [
+ "media_controls_progress_view.cc",
+ "media_controls_progress_view.h",
"media_notification_background.cc",
"media_notification_background.h",
"media_notification_constants.cc",
@@ -29,6 +31,7 @@ component("media_message_center") {
"//skia",
"//ui/accessibility",
"//ui/message_center",
+ "//ui/native_theme",
"//ui/views",
]
}
@@ -37,6 +40,7 @@ source_set("unit_tests") {
testonly = true
sources = [
+ "media_controls_progress_view_unittest.cc",
"media_notification_background_unittest.cc",
"media_notification_view_unittest.cc",
]
@@ -52,6 +56,7 @@ source_set("unit_tests") {
"//testing/gtest",
"//ui/accessibility",
"//ui/message_center",
+ "//ui/native_theme:test_support",
"//ui/views",
"//ui/views:test_support",
]
diff --git a/chromium/components/media_message_center/media_controls_progress_view.cc b/chromium/components/media_message_center/media_controls_progress_view.cc
new file mode 100644
index 00000000000..af87e06f8f3
--- /dev/null
+++ b/chromium/components/media_message_center/media_controls_progress_view.cc
@@ -0,0 +1,188 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/media_message_center/media_controls_progress_view.h"
+
+#include "base/i18n/time_formatting.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "ui/gfx/font_list.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/progress_bar.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/view_class_properties.h"
+
+namespace media_message_center {
+
+namespace {
+
+constexpr int kProgressBarAndTimeSpacing = 3;
+constexpr int kProgressTimeFontSize = 11;
+constexpr int kProgressBarHeight = 4;
+constexpr int kMinClickHeight = 14;
+constexpr int kMaxClickHeight = 24;
+constexpr gfx::Size kTimeSpacingSize = gfx::Size(150, 10);
+constexpr gfx::Insets kProgressViewInsets = gfx::Insets(15, 0, 0, 0);
+
+} // namespace
+
+MediaControlsProgressView::MediaControlsProgressView(
+ base::RepeatingCallback<void(double)> seek_callback)
+ : seek_callback_(std::move(seek_callback)) {
+ SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kVertical, kProgressViewInsets,
+ kProgressBarAndTimeSpacing));
+
+ progress_bar_ = AddChildView(
+ std::make_unique<views::ProgressBar>(kProgressBarHeight, false));
+
+ // Font list for text views.
+ gfx::Font default_font;
+ int font_size_delta = kProgressTimeFontSize - default_font.GetFontSize();
+ gfx::Font font = default_font.Derive(font_size_delta, gfx::Font::NORMAL,
+ gfx::Font::Weight::NORMAL);
+ gfx::FontList font_list(font);
+
+ auto time_view = std::make_unique<views::View>();
+ auto* time_view_layout =
+ time_view->SetLayoutManager(std::make_unique<views::FlexLayout>());
+ time_view_layout->SetOrientation(views::LayoutOrientation::kHorizontal)
+ .SetMainAxisAlignment(views::LayoutAlignment::kCenter)
+ .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
+ .SetCollapseMargins(true);
+
+ auto progress_time = std::make_unique<views::Label>();
+ progress_time->SetFontList(font_list);
+ progress_time->SetEnabledColor(SK_ColorWHITE);
+ progress_time->SetAutoColorReadabilityEnabled(false);
+ progress_time_ = time_view->AddChildView(std::move(progress_time));
+
+ auto time_spacing = std::make_unique<views::View>();
+ time_spacing->SetPreferredSize(kTimeSpacingSize);
+ time_spacing->SetProperty(views::kFlexBehaviorKey,
+ views::FlexSpecification::ForSizeRule(
+ views::MinimumFlexSizeRule::kPreferred,
+ views::MaximumFlexSizeRule::kUnbounded));
+ time_view->AddChildView(std::move(time_spacing));
+
+ auto duration = std::make_unique<views::Label>();
+ duration->SetFontList(font_list);
+ duration->SetEnabledColor(SK_ColorWHITE);
+ duration->SetAutoColorReadabilityEnabled(false);
+ duration_ = time_view->AddChildView(std::move(duration));
+
+ AddChildView(std::move(time_view));
+}
+
+MediaControlsProgressView::~MediaControlsProgressView() = default;
+
+void MediaControlsProgressView::UpdateProgress(
+ const media_session::MediaPosition& media_position) {
+ // If the media is paused and |update_progress_timer_| is still running, stop
+ // the timer.
+ if (media_position.playback_rate() == 0 && update_progress_timer_.IsRunning())
+ update_progress_timer_.Stop();
+
+ base::TimeDelta current_position = media_position.GetPosition();
+ base::TimeDelta duration = media_position.duration();
+
+ double progress = current_position.InSecondsF() / duration.InSecondsF();
+ SetBarProgress(progress);
+
+ // Time formatting can't yet represent durations greater than 24 hours in
+ // base::DURATION_WIDTH_NUMERIC format.
+ base::DurationFormatWidth time_format =
+ duration >= base::TimeDelta::FromDays(1) ? base::DURATION_WIDTH_NARROW
+ : base::DURATION_WIDTH_NUMERIC;
+
+ base::string16 elapsed_time;
+ bool elapsed_time_received = base::TimeDurationFormatWithSeconds(
+ current_position, time_format, &elapsed_time);
+
+ base::string16 total_time;
+ bool total_time_received =
+ base::TimeDurationFormatWithSeconds(duration, time_format, &total_time);
+
+ if (elapsed_time_received && total_time_received) {
+ // If |duration| is less than an hour, we don't want to show "0:" hours on
+ // the progress times.
+ if (duration < base::TimeDelta::FromHours(1)) {
+ base::ReplaceFirstSubstringAfterOffset(
+ &elapsed_time, 0, base::ASCIIToUTF16("0:"), base::ASCIIToUTF16(""));
+ base::ReplaceFirstSubstringAfterOffset(
+ &total_time, 0, base::ASCIIToUTF16("0:"), base::ASCIIToUTF16(""));
+ }
+
+ SetProgressTime(elapsed_time);
+ SetDuration(total_time);
+ }
+
+ if (media_position.playback_rate() != 0) {
+ base::TimeDelta update_frequency = base::TimeDelta::FromSecondsD(
+ std::abs(1 / media_position.playback_rate()));
+ update_progress_timer_.Start(
+ FROM_HERE, update_frequency,
+ base::Bind(&MediaControlsProgressView::UpdateProgress,
+ base::Unretained(this), media_position));
+ }
+}
+
+bool MediaControlsProgressView::OnMousePressed(const ui::MouseEvent& event) {
+ if (!event.IsOnlyLeftMouseButton() || event.y() < kMinClickHeight ||
+ event.y() > kMaxClickHeight) {
+ return false;
+ }
+
+ HandleSeeking(event.location());
+ return true;
+}
+
+void MediaControlsProgressView::OnGestureEvent(ui::GestureEvent* event) {
+ if (event->type() != ui::ET_GESTURE_TAP || event->y() < kMinClickHeight ||
+ event->y() > kMaxClickHeight) {
+ return;
+ }
+
+ HandleSeeking(event->location());
+ event->SetHandled();
+}
+
+const views::ProgressBar* MediaControlsProgressView::progress_bar_for_testing()
+ const {
+ return progress_bar_;
+}
+
+const base::string16& MediaControlsProgressView::progress_time_for_testing()
+ const {
+ return progress_time_->GetText();
+}
+
+const base::string16& MediaControlsProgressView::duration_for_testing() const {
+ return duration_->GetText();
+}
+
+void MediaControlsProgressView::SetBarProgress(double progress) {
+ progress_bar_->SetValue(progress);
+}
+
+void MediaControlsProgressView::SetProgressTime(const base::string16& time) {
+ progress_time_->SetText(time);
+}
+
+void MediaControlsProgressView::SetDuration(const base::string16& duration) {
+ duration_->SetText(duration);
+}
+
+void MediaControlsProgressView::HandleSeeking(const gfx::Point& location) {
+ gfx::Point location_in_bar(location);
+ ConvertPointToTarget(this, progress_bar_, &location_in_bar);
+
+ double seek_to_progress =
+ static_cast<double>(location_in_bar.x()) / progress_bar_->width();
+ seek_callback_.Run(seek_to_progress);
+}
+
+} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_controls_progress_view.h b/chromium/components/media_message_center/media_controls_progress_view.h
new file mode 100644
index 00000000000..8f5ac64c5a1
--- /dev/null
+++ b/chromium/components/media_message_center/media_controls_progress_view.h
@@ -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.
+
+#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_CONTROLS_PROGRESS_VIEW_H_
+#define COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_CONTROLS_PROGRESS_VIEW_H_
+
+#include "base/timer/timer.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "ui/views/view.h"
+
+namespace views {
+class ProgressBar;
+class Label;
+} // namespace views
+
+namespace media_message_center {
+
+class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaControlsProgressView
+ : public views::View {
+ public:
+ explicit MediaControlsProgressView(
+ base::RepeatingCallback<void(double)> seek_callback);
+ ~MediaControlsProgressView() override;
+
+ void UpdateProgress(const media_session::MediaPosition& media_position);
+
+ // views::View:
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
+
+ const views::ProgressBar* progress_bar_for_testing() const;
+ const base::string16& progress_time_for_testing() const;
+ const base::string16& duration_for_testing() const;
+
+ private:
+ void SetBarProgress(double progress);
+ void SetProgressTime(const base::string16& time);
+ void SetDuration(const base::string16& duration);
+
+ void HandleSeeking(const gfx::Point& location);
+
+ views::ProgressBar* progress_bar_;
+ views::Label* progress_time_;
+ views::Label* duration_;
+
+ // Timer to continually update the progress.
+ base::RepeatingTimer update_progress_timer_;
+
+ const base::RepeatingCallback<void(double)> seek_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaControlsProgressView);
+};
+
+} // namespace media_message_center
+
+#endif // COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_CONTROLS_PROGRESS_VIEW_H_
diff --git a/chromium/components/media_message_center/media_controls_progress_view_unittest.cc b/chromium/components/media_message_center/media_controls_progress_view_unittest.cc
new file mode 100644
index 00000000000..5d5e89e1343
--- /dev/null
+++ b/chromium/components/media_message_center/media_controls_progress_view_unittest.cc
@@ -0,0 +1,295 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/media_message_center/media_controls_progress_view.h"
+
+#include "base/bind_helpers.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/progress_bar.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace media_message_center {
+
+class MediaControlsProgressViewTest : public views::ViewsTestBase {
+ public:
+ MediaControlsProgressViewTest()
+ : views::ViewsTestBase(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+ ~MediaControlsProgressViewTest() override = default;
+
+ // ViewsTestBase:
+ void SetUp() override {
+ ViewsTestBase::SetUp();
+
+ views::Widget::InitParams params =
+ CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.bounds = gfx::Rect(300, 300);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget_.Init(std::move(params));
+ views::View* container = new views::View();
+ widget_.SetContentsView(container);
+
+ progress_view_ = new MediaControlsProgressView(base::DoNothing());
+ container->AddChildView(progress_view_);
+
+ widget_.Show();
+ }
+
+ void TearDown() override {
+ widget_.Close();
+ ViewsTestBase::TearDown();
+ }
+
+ protected:
+ MediaControlsProgressView* progress_view_ = nullptr;
+
+ private:
+ views::Widget widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaControlsProgressViewTest);
+};
+
+TEST_F(MediaControlsProgressViewTest, InitProgress) {
+ media_session::MediaPosition media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+}
+
+TEST_F(MediaControlsProgressViewTest, InitProgressOverHour) {
+ media_session::MediaPosition media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromHours(2) /* duration */,
+ base::TimeDelta::FromMinutes(30) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("2:00:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("0:30:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .25);
+}
+
+TEST_F(MediaControlsProgressViewTest, InitProgressOverDay) {
+ media_session::MediaPosition media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromHours(25) /* duration */,
+ base::TimeDelta::FromHours(5) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ // Verify that base::DURATION_WIDTH_NARROW time format is used here.
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("25h 0m 0s"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("5h 0m 0s"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .2);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgress) {
+ media_session::MediaPosition media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(30));
+ task_environment_->RunUntilIdle();
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:30"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .55);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressFastPlayback) {
+ media_session::MediaPosition media_position(
+ 2 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(15));
+ task_environment_->RunUntilIdle();
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:30"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .55);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressSlowPlayback) {
+ media_session::MediaPosition media_position(
+ .5 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(60));
+ task_environment_->RunUntilIdle();
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:30"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .55);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressNegativePlayback) {
+ media_session::MediaPosition media_position(
+ -1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(30));
+ task_environment_->RunUntilIdle();
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("04:30"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .45);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressPastDuration) {
+ media_session::MediaPosition media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ // Move forward in time past the duration.
+ task_environment_->FastForwardBy(base::TimeDelta::FromMinutes(6));
+ task_environment_->RunUntilIdle();
+
+ // Verify the progress does not go past the duration.
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), 1);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressBeforeStart) {
+ media_session::MediaPosition media_position(
+ -1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ // Move forward in time before the start using negative playback rate.
+ task_environment_->FastForwardBy(base::TimeDelta::FromMinutes(6));
+ task_environment_->RunUntilIdle();
+
+ // Verify the progress does not go below 0.
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("00:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), 0);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressPaused) {
+ media_session::MediaPosition media_position(
+ 0 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ task_environment_->FastForwardBy(base::TimeDelta::FromMinutes(6));
+ task_environment_->RunUntilIdle();
+
+ // Verify the progress does not change while media is paused.
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+}
+
+TEST_F(MediaControlsProgressViewTest, UpdateProgressTwice) {
+ media_session::MediaPosition media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */,
+ base::TimeDelta::FromSeconds(300) /* position */);
+
+ // Simulate first position change.
+ progress_view_->UpdateProgress(media_position);
+
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("10:00"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("05:00"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5);
+
+ media_session::MediaPosition new_media_position(
+ 1 /* playback_rate */, base::TimeDelta::FromSeconds(200) /* duration */,
+ base::TimeDelta::FromSeconds(50) /* position */);
+
+ // Simulate second position change.
+ progress_view_->UpdateProgress(new_media_position);
+
+ // Verify that the progress reflects the most recent position update.
+ EXPECT_EQ(progress_view_->duration_for_testing(),
+ base::ASCIIToUTF16("03:20"));
+ EXPECT_EQ(progress_view_->progress_time_for_testing(),
+ base::ASCIIToUTF16("00:50"));
+ EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .25);
+}
+
+} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_notification_background.cc b/chromium/components/media_message_center/media_notification_background.cc
index 3d6f49f3383..00127a6cbb2 100644
--- a/chromium/components/media_message_center/media_notification_background.cc
+++ b/chromium/components/media_message_center/media_notification_background.cc
@@ -12,6 +12,7 @@
#include "ui/gfx/color_analysis.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/scoped_canvas.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
@@ -21,8 +22,6 @@ namespace {
constexpr int kMediaImageGradientWidth = 40;
-constexpr SkColor kMediaNotificationDefaultBackgroundColor = SK_ColorWHITE;
-
// The ratio for a background color option to be considered very popular.
constexpr double kMediaNotificationBackgroundColorVeryPopularRatio = 2.5;
@@ -233,16 +232,12 @@ base::Optional<SkColor> GetNotificationForegroundColor(
} // namespace
MediaNotificationBackground::MediaNotificationBackground(
- views::View* owner,
int top_radius,
int bottom_radius,
double artwork_max_width_pct)
- : owner_(owner),
- top_radius_(top_radius),
+ : top_radius_(top_radius),
bottom_radius_(bottom_radius),
- artwork_max_width_pct_(artwork_max_width_pct) {
- DCHECK(owner);
-}
+ artwork_max_width_pct_(artwork_max_width_pct) {}
MediaNotificationBackground::~MediaNotificationBackground() = default;
@@ -274,7 +269,7 @@ void MediaNotificationBackground::Paint(gfx::Canvas* canvas,
// maintaining the aspect ratio.
gfx::Rect source_bounds =
gfx::Rect(0, 0, artwork_.width(), artwork_.height());
- gfx::Rect artwork_bounds = GetArtworkBounds(bounds);
+ gfx::Rect artwork_bounds = GetArtworkBounds(*view);
canvas->DrawImageInt(
artwork_, source_bounds.x(), source_bounds.y(), source_bounds.width(),
@@ -285,12 +280,12 @@ void MediaNotificationBackground::Paint(gfx::Canvas* canvas,
// Draw a filled rectangle which will act as the main background of the
// notification. This may cover up some of the artwork.
const SkColor background_color =
- background_color_.value_or(kMediaNotificationDefaultBackgroundColor);
- canvas->FillRect(GetFilledBackgroundBounds(bounds), background_color);
+ background_color_.value_or(GetDefaultBackgroundColor(*view));
+ canvas->FillRect(GetFilledBackgroundBounds(*view), background_color);
{
// Draw a gradient to fade the color background and the image together.
- gfx::Rect draw_bounds = GetGradientBounds(bounds);
+ gfx::Rect draw_bounds = GetGradientBounds(*view);
const SkColor colors[2] = {
background_color, SkColorSetA(background_color, SK_AlphaTRANSPARENT)};
@@ -315,42 +310,42 @@ void MediaNotificationBackground::UpdateArtwork(const gfx::ImageSkia& image) {
background_color_ = GetNotificationBackgroundColor(artwork_.bitmap());
foreground_color_ =
GetNotificationForegroundColor(background_color_, artwork_.bitmap());
- owner_->SchedulePaint();
}
-void MediaNotificationBackground::UpdateCornerRadius(int top_radius,
+bool MediaNotificationBackground::UpdateCornerRadius(int top_radius,
int bottom_radius) {
if (top_radius_ == top_radius && bottom_radius_ == bottom_radius)
- return;
+ return false;
top_radius_ = top_radius;
bottom_radius_ = bottom_radius;
-
- owner_->SchedulePaint();
+ return true;
}
-void MediaNotificationBackground::UpdateArtworkMaxWidthPct(
+bool MediaNotificationBackground::UpdateArtworkMaxWidthPct(
double max_width_pct) {
if (artwork_max_width_pct_ == max_width_pct)
- return;
+ return false;
artwork_max_width_pct_ = max_width_pct;
- owner_->SchedulePaint();
+ return true;
}
-SkColor MediaNotificationBackground::GetBackgroundColor() const {
+SkColor MediaNotificationBackground::GetBackgroundColor(
+ const views::View& owner) const {
if (background_color_.has_value())
return *background_color_;
- return kMediaNotificationDefaultBackgroundColor;
+ return GetDefaultBackgroundColor(owner);
}
-SkColor MediaNotificationBackground::GetForegroundColor() const {
+SkColor MediaNotificationBackground::GetForegroundColor(
+ const views::View& owner) const {
const SkColor foreground =
foreground_color_.has_value()
? *foreground_color_
- : views::style::GetColor(*owner_, views::style::CONTEXT_LABEL,
+ : views::style::GetColor(owner, views::style::CONTEXT_LABEL,
views::style::STYLE_PRIMARY);
- return color_utils::BlendForMinContrast(foreground, GetBackgroundColor())
+ return color_utils::BlendForMinContrast(foreground, GetBackgroundColor(owner))
.color;
}
@@ -373,31 +368,34 @@ int MediaNotificationBackground::GetArtworkVisibleWidth(
}
gfx::Rect MediaNotificationBackground::GetArtworkBounds(
- const gfx::Rect& view_bounds) const {
+ const views::View& owner) const {
+ const gfx::Rect& view_bounds = owner.GetContentsBounds();
int width = GetArtworkWidth(view_bounds.size());
// The artwork should be positioned on the far right hand side of the
// notification and be the same height.
- return owner_->GetMirroredRect(
+ return owner.GetMirroredRect(
gfx::Rect(view_bounds.right() - width, 0, width, view_bounds.height()));
}
gfx::Rect MediaNotificationBackground::GetFilledBackgroundBounds(
- const gfx::Rect& view_bounds) const {
+ const views::View& owner) const {
// The filled background should take up the full notification except the area
// taken up by the artwork.
+ const gfx::Rect& view_bounds = owner.GetContentsBounds();
gfx::Rect bounds = gfx::Rect(view_bounds);
bounds.Inset(0, 0, GetArtworkVisibleWidth(view_bounds.size()), 0);
- return owner_->GetMirroredRect(bounds);
+ return owner.GetMirroredRect(bounds);
}
gfx::Rect MediaNotificationBackground::GetGradientBounds(
- const gfx::Rect& view_bounds) const {
+ const views::View& owner) const {
if (artwork_.isNull())
return gfx::Rect(0, 0, 0, 0);
// The gradient should appear above the artwork on the left.
- return owner_->GetMirroredRect(gfx::Rect(
+ const gfx::Rect& view_bounds = owner.GetContentsBounds();
+ return owner.GetMirroredRect(gfx::Rect(
view_bounds.width() - GetArtworkVisibleWidth(view_bounds.size()),
view_bounds.y(), kMediaImageGradientWidth, view_bounds.height()));
}
@@ -414,4 +412,10 @@ SkPoint MediaNotificationBackground::GetGradientEndPoint(
: draw_bounds.right_center());
}
+SkColor MediaNotificationBackground::GetDefaultBackgroundColor(
+ const views::View& owner) const {
+ return owner.GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_BubbleBackground);
+}
+
} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_notification_background.h b/chromium/components/media_message_center/media_notification_background.h
index 8953a201586..63254ca567b 100644
--- a/chromium/components/media_message_center/media_notification_background.h
+++ b/chromium/components/media_message_center/media_notification_background.h
@@ -29,8 +29,7 @@ namespace media_message_center {
class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground
: public views::Background {
public:
- MediaNotificationBackground(views::View* owner,
- int top_radius,
+ MediaNotificationBackground(int top_radius,
int bottom_radius,
double artwork_max_width_pct);
~MediaNotificationBackground() override;
@@ -38,12 +37,12 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground
// views::Background
void Paint(gfx::Canvas* canvas, views::View* view) const override;
- void UpdateCornerRadius(int top_radius, int bottom_radius);
void UpdateArtwork(const gfx::ImageSkia& image);
- void UpdateArtworkMaxWidthPct(double max_width_pct);
+ bool UpdateCornerRadius(int top_radius, int bottom_radius);
+ bool UpdateArtworkMaxWidthPct(double max_width_pct);
- SkColor GetBackgroundColor() const;
- SkColor GetForegroundColor() const;
+ SkColor GetBackgroundColor(const views::View& owner) const;
+ SkColor GetForegroundColor(const views::View& owner) const;
private:
friend class MediaNotificationBackgroundTest;
@@ -53,14 +52,12 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackground
int GetArtworkWidth(const gfx::Size& view_size) const;
int GetArtworkVisibleWidth(const gfx::Size& view_size) const;
- gfx::Rect GetArtworkBounds(const gfx::Rect& view_bounds) const;
- gfx::Rect GetFilledBackgroundBounds(const gfx::Rect& view_bounds) const;
- gfx::Rect GetGradientBounds(const gfx::Rect& view_bounds) const;
+ gfx::Rect GetArtworkBounds(const views::View& owner) const;
+ gfx::Rect GetFilledBackgroundBounds(const views::View& owner) const;
+ gfx::Rect GetGradientBounds(const views::View& owner) const;
SkPoint GetGradientStartPoint(const gfx::Rect& draw_bounds) const;
SkPoint GetGradientEndPoint(const gfx::Rect& draw_bounds) const;
-
- // Reference to the owning view that this is a background for.
- views::View* owner_;
+ SkColor GetDefaultBackgroundColor(const views::View& owner) const;
int top_radius_;
int bottom_radius_;
diff --git a/chromium/components/media_message_center/media_notification_background_unittest.cc b/chromium/components/media_message_center/media_notification_background_unittest.cc
index 4b588814533..e9293374110 100644
--- a/chromium/components/media_message_center/media_notification_background_unittest.cc
+++ b/chromium/components/media_message_center/media_notification_background_unittest.cc
@@ -13,6 +13,7 @@
#include "ui/gfx/color_analysis.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/skia_util.h"
+#include "ui/native_theme/test_native_theme.h"
#include "ui/views/test/test_views.h"
namespace media_message_center {
@@ -28,6 +29,22 @@ constexpr double kVibrantSaturation = 0.8;
constexpr int kDefaultForegroundArtworkHeight = 100;
+constexpr SkColor kDarkBackgroundColor = SK_ColorBLACK;
+
+class TestDarkTheme : public ui::TestNativeTheme {
+ public:
+ TestDarkTheme() = default;
+ ~TestDarkTheme() override = default;
+
+ // ui::NativeTheme implementation.
+ SkColor GetSystemColor(ColorId color_id,
+ ColorScheme color_scheme) const override {
+ if (color_id == kColorId_BubbleBackground)
+ return kDarkBackgroundColor;
+ return ui::TestNativeTheme::GetSystemColor(color_id, color_scheme);
+ }
+};
+
SkColor GetColorFromSL(double s, double l) {
return color_utils::HSLToSkColor({0.2, s, l}, SK_AlphaOPAQUE);
}
@@ -73,16 +90,13 @@ class MediaNotificationBackgroundTest : public testing::Test {
~MediaNotificationBackgroundTest() override = default;
void SetUp() override {
- owner_ = std::make_unique<views::StaticSizedView>();
- background_ = std::make_unique<MediaNotificationBackground>(owner_.get(),
- 10, 10, 0.1);
+ background_ = std::make_unique<MediaNotificationBackground>(10, 10, 0.1);
EXPECT_FALSE(GetBackgroundColor().has_value());
}
void TearDown() override {
background_.reset();
- owner_.reset();
}
MediaNotificationBackground* background() const { return background_.get(); }
@@ -96,7 +110,6 @@ class MediaNotificationBackgroundTest : public testing::Test {
}
private:
- std::unique_ptr<views::StaticSizedView> owner_;
std::unique_ptr<MediaNotificationBackground> background_;
DISALLOW_COPY_AND_ASSIGN(MediaNotificationBackgroundTest);
@@ -124,6 +137,13 @@ TEST_F(MediaNotificationBackgroundTest,
EXPECT_EQ(kTestColor, GetBackgroundColor());
}
+TEST_F(MediaNotificationBackgroundTest, GetBackgroundColorRespectsTheme) {
+ TestDarkTheme dark_theme;
+ views::View owner;
+ owner.SetNativeTheme(&dark_theme);
+ EXPECT_EQ(kDarkBackgroundColor, background()->GetBackgroundColor(owner));
+}
+
// MediaNotificationBackgroundBlackWhiteTest will repeat these tests with a
// parameter that is either black or white.
class MediaNotificationBackgroundBlackWhiteTest
@@ -322,6 +342,8 @@ class MediaNotificationBackgroundRTLTest
: switches::kForceDirectionLTR);
MediaNotificationBackgroundTest::SetUp();
+
+ ASSERT_EQ(IsRTL(), base::i18n::IsRTL());
}
bool IsRTL() const { return GetParam(); }
@@ -336,15 +358,19 @@ INSTANTIATE_TEST_SUITE_P(, MediaNotificationBackgroundRTLTest, testing::Bool());
TEST_P(MediaNotificationBackgroundRTLTest, BoundsSanityCheck) {
// The test notification will have a width of 200 and a height of 50.
gfx::Rect bounds(0, 0, 200, 50);
+ auto owner = std::make_unique<views::StaticSizedView>();
+ owner->SetBoundsRect(bounds);
+ ASSERT_EQ(bounds, owner->GetContentsBounds());
// Check the artwork is not visible by default.
EXPECT_EQ(0, background()->GetArtworkWidth(bounds.size()));
EXPECT_EQ(0, background()->GetArtworkVisibleWidth(bounds.size()));
- EXPECT_EQ(gfx::Rect(IsRTL() ? -200 : 200, 0, 0, 50),
- background()->GetArtworkBounds(bounds));
- EXPECT_EQ(gfx::Rect(IsRTL() ? -200 : 0, 0, 200, 50),
- background()->GetFilledBackgroundBounds(bounds));
- EXPECT_EQ(gfx::Rect(0, 0, 0, 0), background()->GetGradientBounds(bounds));
+ EXPECT_EQ(gfx::Rect(IsRTL() ? 0 : 200, 0, 0, 50),
+ background()->GetArtworkBounds(*owner.get()));
+ EXPECT_EQ(gfx::Rect(IsRTL() ? 0 : 0, 0, 200, 50),
+ background()->GetFilledBackgroundBounds(*owner.get()));
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0),
+ background()->GetGradientBounds(*owner.get()));
// The background artwork image will have an aspect ratio of 2:1.
SkBitmap bitmap;
@@ -362,22 +388,22 @@ TEST_P(MediaNotificationBackgroundRTLTest, BoundsSanityCheck) {
EXPECT_EQ(100, background()->GetArtworkVisibleWidth(bounds.size()));
// Check the artwork is positioned to the right.
- EXPECT_EQ(gfx::Rect(IsRTL() ? -200 : 100, 0, 100, 50),
- background()->GetArtworkBounds(bounds));
+ EXPECT_EQ(gfx::Rect(IsRTL() ? 0 : 100, 0, 100, 50),
+ background()->GetArtworkBounds(*owner.get()));
// Check the filled background is to the left of the image.
- EXPECT_EQ(gfx::Rect(IsRTL() ? -100 : 0, 0, 100, 50),
- background()->GetFilledBackgroundBounds(bounds));
+ EXPECT_EQ(gfx::Rect(IsRTL() ? 100 : 0, 0, 100, 50),
+ background()->GetFilledBackgroundBounds(*owner.get()));
// Check the gradient is positioned above the artwork.
- const gfx::Rect gradient_bounds = background()->GetGradientBounds(bounds);
- EXPECT_EQ(gfx::Rect(IsRTL() ? -140 : 100, 0, 40, 50), gradient_bounds);
+ const gfx::Rect gradient_bounds =
+ background()->GetGradientBounds(*owner.get());
+ EXPECT_EQ(gfx::Rect(IsRTL() ? 60 : 100, 0, 40, 50), gradient_bounds);
// Check the gradient point X-values are the start and end of
// |gradient_bounds|.
- EXPECT_EQ(IsRTL() ? -100 : 100,
- background()->GetGradientStartPoint(gradient_bounds).x());
- EXPECT_EQ(IsRTL() ? -140 : 140,
+ EXPECT_EQ(100, background()->GetGradientStartPoint(gradient_bounds).x());
+ EXPECT_EQ(IsRTL() ? 60 : 140,
background()->GetGradientEndPoint(gradient_bounds).x());
// Check both of the gradient point Y-values are half the height.
diff --git a/chromium/components/media_message_center/media_notification_container.h b/chromium/components/media_message_center/media_notification_container.h
index 46c4d2bf2a1..63a5cd32fd4 100644
--- a/chromium/components/media_message_center/media_notification_container.h
+++ b/chromium/components/media_message_center/media_notification_container.h
@@ -5,7 +5,14 @@
#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_CONTAINER_H_
#define COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_CONTAINER_H_
+#include <set>
+
#include "base/component_export.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
+
+namespace gfx {
+class ImageSkia;
+} // namespace gfx
namespace media_message_center {
@@ -16,6 +23,14 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationContainer {
public:
// Called when MediaNotificationView's expanded state changes.
virtual void OnExpanded(bool expanded) = 0;
+
+ // TODO(https://crbug.com/1003847): Use base::flat_set isntead.
+ // Called when the set of visible MediaSessionActions changes.
+ virtual void OnVisibleActionsChanged(
+ const std::set<media_session::mojom::MediaSessionAction>& actions) = 0;
+
+ // Called when the media artwork changes.
+ virtual void OnMediaArtworkChanged(const gfx::ImageSkia& image) = 0;
};
} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_notification_controller.h b/chromium/components/media_message_center/media_notification_controller.h
index ae1ed4f10ad..86467d65a68 100644
--- a/chromium/components/media_message_center/media_notification_controller.h
+++ b/chromium/components/media_message_center/media_notification_controller.h
@@ -9,6 +9,13 @@
#include "base/component_export.h"
+template <typename T>
+class scoped_refptr;
+
+namespace base {
+class SequencedTaskRunner;
+} // namespace base
+
namespace media_message_center {
// MediaNotificationController does the actual hiding and showing of the media
@@ -19,6 +26,18 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationController {
// MediaNotificationItem when the notification should be shown/hidden.
virtual void ShowNotification(const std::string& id) = 0;
virtual void HideNotification(const std::string& id) = 0;
+
+ // Removes a notification item with the given request id. Called by
+ // MediaNotificationItem when it should be destroyed.
+ virtual void RemoveItem(const std::string& id) = 0;
+
+ // Returns a task runner that the MediaNotificationItem should use.
+ // It typically returns null except in tests.
+ virtual scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const = 0;
+
+ // Notifies the MediaNotificationController that a media button was pressed on
+ // the MediaNotificationView.
+ virtual void LogMediaSessionActionButtonPressed(const std::string& id) = 0;
};
} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_notification_item.cc b/chromium/components/media_message_center/media_notification_item.cc
index 00cd2893fa6..0c89f90135a 100644
--- a/chromium/components/media_message_center/media_notification_item.cc
+++ b/chromium/components/media_message_center/media_notification_item.cc
@@ -36,6 +36,10 @@ MediaNotificationItem::Source GetSource(const std::string& name) {
return MediaNotificationItem::Source::kUnknown;
}
+// How long to wait (in milliseconds) for a new media session to begin.
+constexpr base::TimeDelta kFreezeTimerDelay =
+ base::TimeDelta::FromMilliseconds(2500);
+
} // namespace
// static
@@ -50,30 +54,17 @@ MediaNotificationItem::MediaNotificationItem(
MediaNotificationController* notification_controller,
const std::string& request_id,
const std::string& source_name,
- media_session::mojom::MediaControllerPtr controller,
+ mojo::Remote<media_session::mojom::MediaController> controller,
media_session::mojom::MediaSessionInfoPtr session_info)
: controller_(notification_controller),
request_id_(request_id),
- source_(GetSource(source_name)),
- media_controller_ptr_(std::move(controller)),
- session_info_(std::move(session_info)) {
+ source_(GetSource(source_name)) {
DCHECK(controller_);
- if (media_controller_ptr_.is_bound()) {
- // Bind an observer to the associated media controller.
- media_controller_ptr_->AddObserver(
- observer_receiver_.BindNewPipeAndPassRemote());
+ if (auto task_runner = notification_controller->GetTaskRunner())
+ freeze_timer_.SetTaskRunner(task_runner);
- // TODO(https://crbug.com/931397): Use dip to calculate the size.
- // Bind an observer to be notified when the artwork changes.
- media_controller_ptr_->ObserveImages(
- media_session::mojom::MediaSessionImageType::kArtwork,
- kMediaSessionNotificationArtworkMinSize,
- kMediaSessionNotificationArtworkDesiredSize,
- artwork_observer_receiver_.BindNewPipeAndPassRemote());
- }
-
- MaybeHideOrShowNotification();
+ SetController(std::move(controller), std::move(session_info));
}
MediaNotificationItem::~MediaNotificationItem() {
@@ -84,9 +75,10 @@ void MediaNotificationItem::MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) {
session_info_ = std::move(session_info);
+ MaybeUnfreeze();
MaybeHideOrShowNotification();
- if (view_)
+ if (view_ && !frozen_)
view_->UpdateWithMediaSessionInfo(session_info_);
}
@@ -96,14 +88,17 @@ void MediaNotificationItem::MediaSessionMetadataChanged(
view_needs_metadata_update_ = true;
+ MaybeUnfreeze();
MaybeHideOrShowNotification();
// |MaybeHideOrShowNotification()| can synchronously create a
// MediaNotificationView that calls |SetView()|. If that happens, then we
// don't want to call |view_->UpdateWithMediaMetadata()| below since |view_|
// will have already received the metadata when calling |SetView()|.
- // |view_needs_metadata_update_| is set to false in |SetView()|.
- if (view_ && view_needs_metadata_update_)
+ // |view_needs_metadata_update_| is set to false in |SetView()|. The reason we
+ // want to avoid sending the metadata twice is that metrics are recorded when
+ // metadata is set and we don't want to double-count metrics.
+ if (view_ && view_needs_metadata_update_ && !frozen_)
view_->UpdateWithMediaMetadata(session_metadata_);
view_needs_metadata_update_ = false;
@@ -114,8 +109,10 @@ void MediaNotificationItem::MediaSessionActionsChanged(
session_actions_ = std::set<media_session::mojom::MediaSessionAction>(
actions.begin(), actions.end());
- if (view_)
+ if (view_ && !frozen_) {
+ DCHECK(view_);
view_->UpdateWithMediaActions(session_actions_);
+ }
}
void MediaNotificationItem::MediaControllerImageChanged(
@@ -125,7 +122,7 @@ void MediaNotificationItem::MediaControllerImageChanged(
session_artwork_ = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
- if (view_)
+ if (view_ && !frozen_)
view_->UpdateWithMediaArtwork(*session_artwork_);
}
@@ -134,7 +131,7 @@ void MediaNotificationItem::SetView(MediaNotificationView* view) {
view_ = view;
- if (view) {
+ if (view_) {
view_needs_metadata_update_ = false;
view_->UpdateWithMediaSessionInfo(session_info_);
view_->UpdateWithMediaMetadata(session_metadata_);
@@ -146,20 +143,37 @@ void MediaNotificationItem::SetView(MediaNotificationView* view) {
}
void MediaNotificationItem::FlushForTesting() {
- media_controller_ptr_.FlushForTesting();
+ media_controller_remote_.FlushForTesting();
}
-void MediaNotificationItem::MaybeHideOrShowNotification() {
+bool MediaNotificationItem::ShouldShowNotification() const {
// If the |is_controllable| bit is set in MediaSessionInfo then we should show
// a media notification.
- if (!session_info_ || !session_info_->is_controllable) {
+ if (!session_info_ || !session_info_->is_controllable)
+ return false;
+
+ // If we do not have a title then we should hide the notification.
+ if (session_metadata_.title.empty())
+ return false;
+
+ return true;
+}
+
+void MediaNotificationItem::OnFreezeTimerFired() {
+ DCHECK(frozen_);
+
+ if (is_bound_) {
controller_->HideNotification(request_id_);
- return;
+ } else {
+ controller_->RemoveItem(request_id_);
}
+}
- // If we do not have a title and an artist then we should hide the
- // notification.
- if (session_metadata_.title.empty() || session_metadata_.artist.empty()) {
+void MediaNotificationItem::MaybeHideOrShowNotification() {
+ if (frozen_)
+ return;
+
+ if (!ShouldShowNotification()) {
controller_->HideNotification(request_id_);
return;
}
@@ -177,7 +191,73 @@ void MediaNotificationItem::OnMediaSessionActionButtonPressed(
MediaSessionAction action) {
UMA_HISTOGRAM_ENUMERATION(kUserActionHistogramName, action);
- media_session::PerformMediaSessionAction(action, media_controller_ptr_);
+ if (frozen_)
+ return;
+
+ controller_->LogMediaSessionActionButtonPressed(request_id_);
+ media_session::PerformMediaSessionAction(action, media_controller_remote_);
+}
+
+void MediaNotificationItem::SetController(
+ mojo::Remote<media_session::mojom::MediaController> controller,
+ media_session::mojom::MediaSessionInfoPtr session_info) {
+ observer_receiver_.reset();
+ artwork_observer_receiver_.reset();
+
+ is_bound_ = true;
+ media_controller_remote_ = std::move(controller);
+ session_info_ = std::move(session_info);
+
+ if (media_controller_remote_.is_bound()) {
+ // Bind an observer to the associated media controller.
+ media_controller_remote_->AddObserver(
+ observer_receiver_.BindNewPipeAndPassRemote());
+
+ // TODO(https://crbug.com/931397): Use dip to calculate the size.
+ // Bind an observer to be notified when the artwork changes.
+ media_controller_remote_->ObserveImages(
+ media_session::mojom::MediaSessionImageType::kArtwork,
+ kMediaSessionNotificationArtworkMinSize,
+ kMediaSessionNotificationArtworkDesiredSize,
+ artwork_observer_receiver_.BindNewPipeAndPassRemote());
+ }
+
+ MaybeHideOrShowNotification();
+}
+
+void MediaNotificationItem::Freeze() {
+ if (frozen_)
+ return;
+
+ frozen_ = true;
+ is_bound_ = false;
+
+ freeze_timer_.Start(FROM_HERE, kFreezeTimerDelay,
+ base::BindOnce(&MediaNotificationItem::OnFreezeTimerFired,
+ base::Unretained(this)));
+}
+
+void MediaNotificationItem::MaybeUnfreeze() {
+ if (!frozen_)
+ return;
+
+ if (!ShouldShowNotification() || !is_bound_)
+ return;
+
+ frozen_ = false;
+ freeze_timer_.Stop();
+
+ // When we unfreeze, we want to fully update |view_| with any changes that
+ // we've avoided sending during the freeze.
+ if (view_) {
+ view_needs_metadata_update_ = false;
+ view_->UpdateWithMediaSessionInfo(session_info_);
+ view_->UpdateWithMediaMetadata(session_metadata_);
+ view_->UpdateWithMediaActions(session_actions_);
+
+ if (session_artwork_.has_value())
+ view_->UpdateWithMediaArtwork(*session_artwork_);
+ }
}
} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_notification_item.h b/chromium/components/media_message_center/media_notification_item.h
index 08f817e6c8f..63f91cbceb6 100644
--- a/chromium/components/media_message_center/media_notification_item.h
+++ b/chromium/components/media_message_center/media_notification_item.h
@@ -12,8 +12,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/public/mojom/media_controller.mojom.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "ui/gfx/image/image_skia.h"
@@ -45,11 +45,12 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem
kMaxValue = kArc,
};
- MediaNotificationItem(MediaNotificationController* notification_controller,
- const std::string& request_id,
- const std::string& source_name,
- media_session::mojom::MediaControllerPtr controller,
- media_session::mojom::MediaSessionInfoPtr session_info);
+ MediaNotificationItem(
+ MediaNotificationController* notification_controller,
+ const std::string& request_id,
+ const std::string& source_name,
+ mojo::Remote<media_session::mojom::MediaController> controller,
+ media_session::mojom::MediaSessionInfoPtr session_info);
~MediaNotificationItem() override;
// media_session::mojom::MediaControllerObserver:
@@ -83,17 +84,35 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem
void FlushForTesting();
void SetMediaControllerForTesting(
- media_session::mojom::MediaControllerPtr controller) {
- media_controller_ptr_ = std::move(controller);
+ mojo::Remote<media_session::mojom::MediaController> controller) {
+ media_controller_remote_ = std::move(controller);
}
+ void SetController(
+ mojo::Remote<media_session::mojom::MediaController> controller,
+ media_session::mojom::MediaSessionInfoPtr session_info);
+
+ // This will freeze the item and start a timer to destroy the item after
+ // some time has passed.
+ void Freeze();
+
+ bool frozen() const { return frozen_; }
+
private:
+ bool ShouldShowNotification() const;
+
+ void MaybeUnfreeze();
+
+ void OnFreezeTimerFired();
+
void MaybeHideOrShowNotification();
void HideNotification();
MediaNotificationController* controller_;
+ bool is_bound_ = true;
+
// Weak reference to the view of the currently shown media notification.
MediaNotificationView* view_ = nullptr;
@@ -104,7 +123,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem
// The source of the media session (e.g. arc, web).
const Source source_;
- media_session::mojom::MediaControllerPtr media_controller_ptr_;
+ mojo::Remote<media_session::mojom::MediaController> media_controller_remote_;
media_session::mojom::MediaSessionInfoPtr session_info_;
@@ -118,6 +137,14 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem
// updating |view_|'s metadata twice on a single change.
bool view_needs_metadata_update_ = false;
+ // When the item is frozen the |view_| will not receive any updates to the
+ // data and no actions will be executed.
+ bool frozen_ = false;
+
+ // The timer that will notify the controller to destroy this item after it
+ // has been frozen for a certain period of time.
+ base::OneShotTimer freeze_timer_;
+
mojo::Receiver<media_session::mojom::MediaControllerObserver>
observer_receiver_{this};
diff --git a/chromium/components/media_message_center/media_notification_util.cc b/chromium/components/media_message_center/media_notification_util.cc
index cbfe55cdb76..5321672d3b1 100644
--- a/chromium/components/media_message_center/media_notification_util.cc
+++ b/chromium/components/media_message_center/media_notification_util.cc
@@ -4,6 +4,7 @@
#include "components/media_message_center/media_notification_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/button/button.h"
@@ -22,8 +23,15 @@ constexpr MediaSessionAction kPreferredActions[] = {
MediaSessionAction::kSeekBackward, MediaSessionAction::kSeekForward,
};
+// The maximum number of media notifications to count when recording the
+// Media.Notification.Count histogram. 20 was chosen because it would be very
+// unlikely to see a user with 20+ things playing at once.
+const int kMediaNotificationCountHistogramMax = 20;
+
} // namespace
+const char kCountHistogramName[] = "Media.Notification.Count";
+
base::string16 GetAccessibleNameFromMetadata(
media_session::MediaMetadata session_metadata) {
std::vector<base::string16> text;
@@ -73,4 +81,9 @@ MediaSessionAction GetPlayPauseIgnoredAction(
: MediaSessionAction::kPlay;
}
+void RecordConcurrentNotificationCount(size_t count) {
+ UMA_HISTOGRAM_EXACT_LINEAR(kCountHistogramName, count,
+ kMediaNotificationCountHistogramMax);
+}
+
} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_notification_util.h b/chromium/components/media_message_center/media_notification_util.h
index 578490f973f..559dd4c8a38 100644
--- a/chromium/components/media_message_center/media_notification_util.h
+++ b/chromium/components/media_message_center/media_notification_util.h
@@ -14,6 +14,10 @@ class Button;
namespace media_message_center {
+// The name of the histogram used to record the number of concurrent media
+// notifications.
+COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) extern const char kCountHistogramName[];
+
// Creates a string describing media session metadata intended to be read out by
// a screen reader.
COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER)
@@ -42,6 +46,10 @@ COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER)
media_session::mojom::MediaSessionAction GetPlayPauseIgnoredAction(
media_session::mojom::MediaSessionAction current_action);
+// Records the concurrent number of media notifications displayed.
+COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER)
+void RecordConcurrentNotificationCount(size_t count);
+
} // namespace media_message_center
#endif // COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_UTIL_H_
diff --git a/chromium/components/media_message_center/media_notification_view.cc b/chromium/components/media_message_center/media_notification_view.cc
index c645937d917..6ac5e90fb6f 100644
--- a/chromium/components/media_message_center/media_notification_view.cc
+++ b/chromium/components/media_message_center/media_notification_view.cc
@@ -203,7 +203,7 @@ MediaNotificationView::MediaNotificationView(
IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK));
SetBackground(std::make_unique<MediaNotificationBackground>(
- this, message_center::kNotificationCornerRadius,
+ message_center::kNotificationCornerRadius,
message_center::kNotificationCornerRadius, kMediaImageMaxWidthPct));
UpdateForegroundColor();
@@ -235,8 +235,26 @@ void MediaNotificationView::SetExpanded(bool expanded) {
void MediaNotificationView::UpdateCornerRadius(int top_radius,
int bottom_radius) {
- GetMediaNotificationBackground()->UpdateCornerRadius(top_radius,
- bottom_radius);
+ if (GetMediaNotificationBackground()->UpdateCornerRadius(top_radius,
+ bottom_radius)) {
+ SchedulePaint();
+ }
+}
+
+void MediaNotificationView::SetForcedExpandedState(
+ bool* forced_expanded_state) {
+ if (forced_expanded_state) {
+ if (forced_expanded_state_ == *forced_expanded_state)
+ return;
+ forced_expanded_state_ = *forced_expanded_state;
+ } else {
+ if (!forced_expanded_state_.has_value())
+ return;
+ forced_expanded_state_ = base::nullopt;
+ }
+
+ header_row_->SetExpandButtonEnabled(IsExpandable());
+ UpdateViewForExpandedState();
}
void MediaNotificationView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
@@ -335,6 +353,8 @@ void MediaNotificationView::UpdateWithMediaArtwork(
UpdateForegroundColor();
+ container_->OnMediaArtworkChanged(image);
+
PreferredSizeChanged();
Layout();
SchedulePaint();
@@ -359,6 +379,8 @@ void MediaNotificationView::UpdateActionButtonsVisibility() {
if (should_invalidate)
action_button->InvalidateLayout();
}
+
+ container_->OnVisibleActionsChanged(visible_actions);
}
void MediaNotificationView::UpdateViewForExpandedState() {
@@ -394,8 +416,10 @@ void MediaNotificationView::UpdateViewForExpandedState() {
main_row_->Layout();
- GetMediaNotificationBackground()->UpdateArtworkMaxWidthPct(
- expanded ? kMediaImageMaxWidthExpandedPct : kMediaImageMaxWidthPct);
+ if (GetMediaNotificationBackground()->UpdateArtworkMaxWidthPct(
+ expanded ? kMediaImageMaxWidthExpandedPct : kMediaImageMaxWidthPct)) {
+ SchedulePaint();
+ }
header_row_->SetExpanded(expanded);
@@ -421,6 +445,9 @@ MediaNotificationView::GetMediaNotificationBackground() {
}
bool MediaNotificationView::IsExpandable() const {
+ if (forced_expanded_state_.has_value())
+ return false;
+
std::set<MediaSessionAction> ignored_actions = {
GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_))};
@@ -432,14 +459,16 @@ bool MediaNotificationView::IsExpandable() const {
}
bool MediaNotificationView::IsActuallyExpanded() const {
+ if (forced_expanded_state_.has_value())
+ return forced_expanded_state_.value();
return expanded_ && IsExpandable();
}
void MediaNotificationView::UpdateForegroundColor() {
const SkColor background =
- GetMediaNotificationBackground()->GetBackgroundColor();
+ GetMediaNotificationBackground()->GetBackgroundColor(*this);
const SkColor foreground =
- GetMediaNotificationBackground()->GetForegroundColor();
+ GetMediaNotificationBackground()->GetForegroundColor(*this);
title_label_->SetEnabledColor(foreground);
artist_label_->SetEnabledColor(foreground);
diff --git a/chromium/components/media_message_center/media_notification_view.h b/chromium/components/media_message_center/media_notification_view.h
index ddca1d78633..02263b99f14 100644
--- a/chromium/components/media_message_center/media_notification_view.h
+++ b/chromium/components/media_message_center/media_notification_view.h
@@ -7,6 +7,7 @@
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/image_button.h"
@@ -70,6 +71,12 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationView
void SetExpanded(bool expanded);
void UpdateCornerRadius(int top_radius, int bottom_radius);
+ // When |forced_expanded_state| has a value, the notification will be forced
+ // into that expanded state and the user won't be given a button to toggle the
+ // expanded state. Subsequent |SetExpanded()| calls will be ignored until
+ // |SetForcedExpandedState(nullptr)| is called.
+ void SetForcedExpandedState(bool* forced_expanded_state);
+
// views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
@@ -121,6 +128,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationView
// Whether this notification is expanded or not.
bool expanded_ = false;
+ // Used to force the notification to remain in a specific expanded state.
+ base::Optional<bool> forced_expanded_state_;
+
// Set of enabled actions.
std::set<media_session::mojom::MediaSessionAction> enabled_actions_;
diff --git a/chromium/components/media_message_center/media_notification_view_unittest.cc b/chromium/components/media_message_center/media_notification_view_unittest.cc
index e73b7f58b07..78921db25ba 100644
--- a/chromium/components/media_message_center/media_notification_view_unittest.cc
+++ b/chromium/components/media_message_center/media_notification_view_unittest.cc
@@ -67,6 +67,11 @@ class MockMediaNotificationController : public MediaNotificationController {
// MediaNotificationController implementation.
MOCK_METHOD1(ShowNotification, void(const std::string& id));
MOCK_METHOD1(HideNotification, void(const std::string& id));
+ MOCK_METHOD1(RemoveItem, void(const std::string& id));
+ scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override {
+ return nullptr;
+ }
+ MOCK_METHOD1(LogMediaSessionActionButtonPressed, void(const std::string& id));
private:
DISALLOW_COPY_AND_ASSIGN(MockMediaNotificationController);
@@ -79,6 +84,9 @@ class MockMediaNotificationContainer : public MediaNotificationContainer {
// MediaNotificationContainer implementation.
MOCK_METHOD1(OnExpanded, void(bool expanded));
+ MOCK_METHOD1(OnVisibleActionsChanged,
+ void(const std::set<MediaSessionAction>& actions));
+ MOCK_METHOD1(OnMediaArtworkChanged, void(const gfx::ImageSkia& image));
MediaNotificationView* view() const { return view_.get(); }
void SetView(std::unique_ptr<MediaNotificationView> view) {
@@ -116,7 +124,7 @@ class MediaNotificationViewTest : public views::ViewsTestBase {
CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = gfx::Rect(kWidgetSize);
- widget_->Init(params);
+ widget_->Init(std::move(params));
widget_->Show();
CreateViewFromMediaSessionInfo(
@@ -126,7 +134,7 @@ class MediaNotificationViewTest : public views::ViewsTestBase {
void CreateViewFromMediaSessionInfo(
media_session::mojom::MediaSessionInfoPtr session_info) {
session_info->is_controllable = true;
- media_session::mojom::MediaControllerPtr controller;
+ mojo::Remote<media_session::mojom::MediaController> controller;
item_ = std::make_unique<MediaNotificationItem>(
&controller_, request_id_.ToString(), std::string(),
std::move(controller), std::move(session_info));
@@ -140,7 +148,7 @@ class MediaNotificationViewTest : public views::ViewsTestBase {
// Inject the test media controller into the item.
media_controller_ = std::make_unique<TestMediaController>();
item_->SetMediaControllerForTesting(
- media_controller_->CreateMediaControllerPtr());
+ media_controller_->CreateMediaControllerRemote());
}
void TearDown() override {
@@ -175,6 +183,8 @@ class MediaNotificationViewTest : public views::ViewsTestBase {
MockMediaNotificationContainer& container() { return container_; }
+ MockMediaNotificationController& controller() { return controller_; }
+
MediaNotificationView* view() const { return container_.view(); }
TestMediaController* media_controller() const {
@@ -385,6 +395,7 @@ TEST_F(MediaNotificationViewTest, PlayPauseButtonTooltipCheck) {
}
TEST_F(MediaNotificationViewTest, NextTrackButtonClick) {
+ EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_));
EnableAction(MediaSessionAction::kNextTrack);
EXPECT_EQ(0, media_controller()->next_track_count());
@@ -397,6 +408,7 @@ TEST_F(MediaNotificationViewTest, NextTrackButtonClick) {
}
TEST_F(MediaNotificationViewTest, PlayButtonClick) {
+ EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_));
EnableAction(MediaSessionAction::kPlay);
EXPECT_EQ(0, media_controller()->resume_count());
@@ -409,6 +421,7 @@ TEST_F(MediaNotificationViewTest, PlayButtonClick) {
}
TEST_F(MediaNotificationViewTest, PauseButtonClick) {
+ EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_));
EnableAction(MediaSessionAction::kPause);
EXPECT_EQ(0, media_controller()->suspend_count());
@@ -428,6 +441,7 @@ TEST_F(MediaNotificationViewTest, PauseButtonClick) {
}
TEST_F(MediaNotificationViewTest, PreviousTrackButtonClick) {
+ EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_));
EnableAction(MediaSessionAction::kPreviousTrack);
EXPECT_EQ(0, media_controller()->previous_track_count());
@@ -440,6 +454,7 @@ TEST_F(MediaNotificationViewTest, PreviousTrackButtonClick) {
}
TEST_F(MediaNotificationViewTest, SeekBackwardButtonClick) {
+ EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_));
EnableAction(MediaSessionAction::kSeekBackward);
EXPECT_EQ(0, media_controller()->seek_backward_count());
@@ -452,6 +467,7 @@ TEST_F(MediaNotificationViewTest, SeekBackwardButtonClick) {
}
TEST_F(MediaNotificationViewTest, SeekForwardButtonClick) {
+ EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_));
EnableAction(MediaSessionAction::kSeekForward);
EXPECT_EQ(0, media_controller()->seek_forward_count());
@@ -601,9 +617,13 @@ TEST_F(MediaNotificationViewTest, UpdateMetadata_AppName) {
}
TEST_F(MediaNotificationViewTest, Buttons_WhenCollapsed) {
+ EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay,
+ MediaSessionAction::kPreviousTrack,
+ MediaSessionAction::kNextTrack})));
EnableAllActions();
-
view()->SetExpanded(false);
+ testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActuallyExpanded());
@@ -613,23 +633,55 @@ TEST_F(MediaNotificationViewTest, Buttons_WhenCollapsed) {
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekBackward));
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
+ EXPECT_CALL(container(),
+ OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward,
+ MediaSessionAction::kNextTrack})));
DisableAction(MediaSessionAction::kPreviousTrack);
+ testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
+ EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay,
+ MediaSessionAction::kPreviousTrack,
+ MediaSessionAction::kNextTrack})));
EnableAction(MediaSessionAction::kPreviousTrack);
+ testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
+ EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay,
+ MediaSessionAction::kPreviousTrack,
+ MediaSessionAction::kNextTrack})));
DisableAction(MediaSessionAction::kSeekForward);
+ testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
+ EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay,
+ MediaSessionAction::kPreviousTrack,
+ MediaSessionAction::kNextTrack})));
EnableAction(MediaSessionAction::kSeekForward);
+ testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
}
TEST_F(MediaNotificationViewTest, Buttons_WhenExpanded) {
+ EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay,
+ MediaSessionAction::kPreviousTrack,
+ MediaSessionAction::kNextTrack})));
EnableAllActions();
-
+ testing::Mock::VerifyAndClearExpectations(&container());
+
+ EXPECT_CALL(
+ container(),
+ OnVisibleActionsChanged(std::set<MediaSessionAction>(
+ {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
+ MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
+ MediaSessionAction::kSeekForward})));
view()->SetExpanded(true);
+ testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_TRUE(IsActuallyExpanded());
@@ -679,6 +731,7 @@ TEST_F(MediaNotificationViewTest, UpdateArtworkFromItem) {
int title_artist_width = title_artist_row()->width();
const SkColor accent = header_row()->accent_color_for_testing();
gfx::Size size = view()->size();
+ EXPECT_CALL(container(), OnMediaArtworkChanged(_)).Times(2);
SkBitmap image;
image.allocN32Pixels(10, 10);
@@ -870,4 +923,156 @@ TEST_F(MediaNotificationViewTest, AccessibleNodeData) {
EXPECT_EQ(base::ASCIIToUTF16("title - artist"), accessible_name());
}
+TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateMetadata) {
+ media_session::MediaMetadata metadata;
+ metadata.title = base::ASCIIToUTF16("title2");
+ metadata.artist = base::ASCIIToUTF16("artist2");
+ metadata.album = base::ASCIIToUTF16("album");
+
+ GetItem()->Freeze();
+ GetItem()->MediaSessionMetadataChanged(metadata);
+
+ EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText());
+ EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText());
+}
+
+TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateImage) {
+ SkBitmap image;
+ image.allocN32Pixels(10, 10);
+ image.eraseColor(SK_ColorMAGENTA);
+ EXPECT_CALL(container(), OnMediaArtworkChanged(_)).Times(0);
+
+ GetItem()->Freeze();
+ GetItem()->MediaControllerImageChanged(
+ media_session::mojom::MediaSessionImageType::kArtwork, image);
+
+ EXPECT_TRUE(GetArtworkImage().isNull());
+}
+
+TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdatePlaybackState) {
+ EnableAction(MediaSessionAction::kPlay);
+ EnableAction(MediaSessionAction::kPause);
+
+ GetItem()->Freeze();
+
+ EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay));
+ EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause));
+
+ media_session::mojom::MediaSessionInfoPtr session_info(
+ media_session::mojom::MediaSessionInfo::New());
+ session_info->playback_state =
+ media_session::mojom::MediaPlaybackState::kPlaying;
+ GetItem()->MediaSessionInfoChanged(session_info.Clone());
+
+ EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay));
+ EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause));
+}
+
+TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateActions) {
+ EXPECT_FALSE(
+ GetButtonForAction(MediaSessionAction::kSeekForward)->GetVisible());
+
+ GetItem()->Freeze();
+ EnableAction(MediaSessionAction::kSeekForward);
+
+ EXPECT_FALSE(
+ GetButtonForAction(MediaSessionAction::kSeekForward)->GetVisible());
+}
+
+TEST_F(MediaNotificationViewTest, Freezing_DisableInteraction) {
+ EnableAllActions();
+
+ EXPECT_EQ(0, media_controller()->next_track_count());
+
+ GetItem()->Freeze();
+
+ SimulateButtonClick(MediaSessionAction::kNextTrack);
+ GetItem()->FlushForTesting();
+
+ EXPECT_EQ(0, media_controller()->next_track_count());
+}
+
+TEST_F(MediaNotificationViewTest, UnfreezingDoesntMissUpdates) {
+ EnableAction(MediaSessionAction::kPlay);
+ EnableAction(MediaSessionAction::kPause);
+
+ // Freeze the item and clear the metadata.
+ GetItem()->Freeze();
+ GetItem()->MediaSessionInfoChanged(nullptr);
+ GetItem()->MediaSessionMetadataChanged(base::nullopt);
+
+ // The item should be frozen and the view should contain the old data.
+ EXPECT_TRUE(GetItem()->frozen());
+ EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay));
+ EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause));
+ EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText());
+ EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText());
+
+ // Bind the item to a new controller that's playing instead of paused.
+ auto new_media_controller = std::make_unique<TestMediaController>();
+ media_session::mojom::MediaSessionInfoPtr session_info(
+ media_session::mojom::MediaSessionInfo::New());
+ session_info->playback_state =
+ media_session::mojom::MediaPlaybackState::kPlaying;
+ session_info->is_controllable = true;
+ GetItem()->SetController(new_media_controller->CreateMediaControllerRemote(),
+ session_info.Clone());
+
+ // The item will receive a MediaSessionInfoChanged.
+ GetItem()->MediaSessionInfoChanged(session_info.Clone());
+
+ // The item should still be frozen, and the view should contain the old data.
+ EXPECT_TRUE(GetItem()->frozen());
+ EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay));
+ EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause));
+ EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText());
+ EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText());
+
+ // Update the metadata.
+ media_session::MediaMetadata metadata;
+ metadata.title = base::ASCIIToUTF16("title2");
+ metadata.artist = base::ASCIIToUTF16("artist2");
+ GetItem()->MediaSessionMetadataChanged(metadata);
+
+ // The item should no longer be frozen, and we should see the updated data.
+ EXPECT_FALSE(GetItem()->frozen());
+ EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPlay));
+ EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPause));
+ EXPECT_EQ(base::ASCIIToUTF16("title2"), title_label()->GetText());
+ EXPECT_EQ(base::ASCIIToUTF16("artist2"), artist_label()->GetText());
+}
+
+TEST_F(MediaNotificationViewTest, ForcedExpandedState) {
+ // Make the view expandable.
+ EnableAllActions();
+
+ // Force it to be expanded.
+ bool expanded_state = true;
+ view()->SetForcedExpandedState(&expanded_state);
+ EXPECT_TRUE(IsActuallyExpanded());
+
+ // Since it's forced, clicking on the header should not toggle the expanded
+ // state.
+ SimulateHeaderClick();
+ EXPECT_TRUE(IsActuallyExpanded());
+
+ // Force it to be not expanded.
+ expanded_state = false;
+ view()->SetForcedExpandedState(&expanded_state);
+ EXPECT_FALSE(IsActuallyExpanded());
+
+ // Since it's forced, clicking on the header should not toggle the expanded
+ // state.
+ SimulateHeaderClick();
+ EXPECT_FALSE(IsActuallyExpanded());
+
+ // Stop forcing expanded state.
+ view()->SetForcedExpandedState(nullptr);
+ EXPECT_FALSE(IsActuallyExpanded());
+
+ // Clicking on the header should toggle the expanded state.
+ SimulateHeaderClick();
+ EXPECT_TRUE(IsActuallyExpanded());
+}
+
} // namespace media_message_center
diff --git a/chromium/components/metrics/BUILD.gn b/chromium/components/metrics/BUILD.gn
index 614f6deb2ab..2f59db4b501 100644
--- a/chromium/components/metrics/BUILD.gn
+++ b/chromium/components/metrics/BUILD.gn
@@ -131,6 +131,7 @@ jumbo_static_library("metrics") {
deps = [
"//base",
"//base:base_static",
+ "//build:branding_buildflags",
"//components/prefs",
"//components/variations",
"//components/version_info:version_info",
@@ -273,7 +274,7 @@ static_library("single_sample_metrics") {
]
public_deps = [
- "//components/metrics/public/interfaces:single_sample_metrics_mojo_bindings",
+ "//components/metrics/public/mojom:single_sample_metrics_mojo_bindings",
]
}
@@ -307,7 +308,7 @@ source_set("child_call_stack_profile_builder") {
]
deps = [
"//base",
- "//components/metrics/public/interfaces:call_stack_mojo_bindings",
+ "//components/metrics/public/mojom:call_stack_mojo_bindings",
"//third_party/metrics_proto",
]
@@ -336,7 +337,7 @@ source_set("call_stack_profile_collector") {
deps = [
":call_stack_profile_params",
":metrics",
- "//components/metrics/public/interfaces:call_stack_mojo_bindings",
+ "//components/metrics/public/mojom:call_stack_mojo_bindings",
]
}
diff --git a/chromium/components/metrics/call_stack_profile_collector.h b/chromium/components/metrics/call_stack_profile_collector.h
index e4b637148f0..541b5acfaa3 100644
--- a/chromium/components/metrics/call_stack_profile_collector.h
+++ b/chromium/components/metrics/call_stack_profile_collector.h
@@ -6,7 +6,7 @@
#define COMPONENTS_METRICS_CALL_STACK_PROFILE_COLLECTOR_H_
#include "base/macros.h"
-#include "components/metrics/public/interfaces/call_stack_profile_collector.mojom.h"
+#include "components/metrics/public/mojom/call_stack_profile_collector.mojom.h"
namespace metrics {
diff --git a/chromium/components/metrics/child_call_stack_profile_collector.h b/chromium/components/metrics/child_call_stack_profile_collector.h
index eafd9d640c0..ad0bcf56a6e 100644
--- a/chromium/components/metrics/child_call_stack_profile_collector.h
+++ b/chromium/components/metrics/child_call_stack_profile_collector.h
@@ -12,7 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
-#include "components/metrics/public/interfaces/call_stack_profile_collector.mojom.h"
+#include "components/metrics/public/mojom/call_stack_profile_collector.mojom.h"
namespace service_manager {
class InterfaceProvider;
diff --git a/chromium/components/metrics/child_call_stack_profile_collector_unittest.cc b/chromium/components/metrics/child_call_stack_profile_collector_unittest.cc
index 84f33bb39e7..9dea0b6083a 100644
--- a/chromium/components/metrics/child_call_stack_profile_collector_unittest.cc
+++ b/chromium/components/metrics/child_call_stack_profile_collector_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/sampled_profile.pb.h"
@@ -50,7 +50,7 @@ class ChildCallStackProfileCollectorTest : public testing::Test {
return child_collector_.profiles_;
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
mojom::CallStackProfileCollectorPtr receiver_;
std::unique_ptr<Receiver> receiver_impl_;
ChildCallStackProfileCollector child_collector_;
diff --git a/chromium/components/metrics/cloned_install_detector.cc b/chromium/components/metrics/cloned_install_detector.cc
index 4287fdb8788..b940288c547 100644
--- a/chromium/components/metrics/cloned_install_detector.cc
+++ b/chromium/components/metrics/cloned_install_detector.cc
@@ -54,9 +54,9 @@ ClonedInstallDetector::~ClonedInstallDetector() {
}
void ClonedInstallDetector::CheckForClonedInstall(PrefService* local_state) {
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::Bind(&MachineIdProvider::GetMachineId),
base::Bind(&ClonedInstallDetector::SaveMachineId,
diff --git a/chromium/components/metrics/delegating_provider.cc b/chromium/components/metrics/delegating_provider.cc
index 6a06ffa33bc..aeeab06c07c 100644
--- a/chromium/components/metrics/delegating_provider.cc
+++ b/chromium/components/metrics/delegating_provider.cc
@@ -63,8 +63,17 @@ bool DelegatingProvider::HasIndependentMetrics() {
void DelegatingProvider::ProvideSystemProfileMetrics(
SystemProfileProto* system_profile_proto) {
- for (auto& provider : metrics_providers_)
- provider->ProvideSystemProfileMetrics(system_profile_proto);
+ // ProvideSystemProfileMetricsWithLogCreationTime() should be called instead.
+ NOTREACHED();
+}
+
+void DelegatingProvider::ProvideSystemProfileMetricsWithLogCreationTime(
+ base::TimeTicks log_creation_time,
+ SystemProfileProto* system_profile_proto) {
+ for (auto& provider : metrics_providers_) {
+ provider->ProvideSystemProfileMetricsWithLogCreationTime(
+ log_creation_time, system_profile_proto);
+ }
}
bool DelegatingProvider::HasPreviousSessionData() {
diff --git a/chromium/components/metrics/delegating_provider.h b/chromium/components/metrics/delegating_provider.h
index 24fa7c7193b..4e0cd1a5a6d 100644
--- a/chromium/components/metrics/delegating_provider.h
+++ b/chromium/components/metrics/delegating_provider.h
@@ -36,6 +36,9 @@ class DelegatingProvider final : public MetricsProvider {
bool HasIndependentMetrics() override;
void ProvideSystemProfileMetrics(
SystemProfileProto* system_profile_proto) override;
+ void ProvideSystemProfileMetricsWithLogCreationTime(
+ base::TimeTicks log_creation_time,
+ SystemProfileProto* system_profile_proto) override;
bool HasPreviousSessionData() override;
void ProvidePreviousSessionData(
ChromeUserMetricsExtension* uma_proto) override;
diff --git a/chromium/components/metrics/drive_metrics_provider.cc b/chromium/components/metrics/drive_metrics_provider.cc
index 1953bb27cb9..ad9c95add08 100644
--- a/chromium/components/metrics/drive_metrics_provider.cc
+++ b/chromium/components/metrics/drive_metrics_provider.cc
@@ -33,9 +33,9 @@ void DriveMetricsProvider::ProvideSystemProfileMetrics(
}
void DriveMetricsProvider::AsyncInit(const base::Closure& done_callback) {
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::Bind(&DriveMetricsProvider::GetDriveMetricsOnBackgroundThread,
local_state_path_key_),
diff --git a/chromium/components/metrics/field_trials_provider.cc b/chromium/components/metrics/field_trials_provider.cc
index 9e5bbeb248c..bb7c97b7a02 100644
--- a/chromium/components/metrics/field_trials_provider.cc
+++ b/chromium/components/metrics/field_trials_provider.cc
@@ -36,13 +36,14 @@ void FieldTrialsProvider::GetFieldTrialIds(
variations::GetFieldTrialActiveGroupIds(suffix_, field_trial_ids);
}
-void FieldTrialsProvider::OnDidCreateMetricsLog() {
- if (registry_) {
- creation_times_.push_back(base::TimeTicks::Now());
- }
+void FieldTrialsProvider::ProvideSystemProfileMetrics(
+ metrics::SystemProfileProto* system_profile_proto) {
+ // ProvideSystemProfileMetricsWithLogCreationTime() should be called instead.
+ NOTREACHED();
}
-void FieldTrialsProvider::ProvideSystemProfileMetrics(
+void FieldTrialsProvider::ProvideSystemProfileMetricsWithLogCreationTime(
+ base::TimeTicks log_creation_time,
metrics::SystemProfileProto* system_profile_proto) {
std::vector<ActiveGroupId> field_trial_ids;
const std::string& version = variations::GetSeedVersion();
@@ -52,14 +53,8 @@ void FieldTrialsProvider::ProvideSystemProfileMetrics(
WriteFieldTrials(field_trial_ids, system_profile_proto);
if (registry_) {
- base::TimeTicks creation_time;
- // Should always be true, but don't crash even if there is a bug.
- if (!creation_times_.empty()) {
- creation_time = creation_times_.back();
- creation_times_.pop_back();
- }
std::vector<ActiveGroupId> synthetic_trials;
- registry_->GetSyntheticFieldTrialsOlderThan(creation_time,
+ registry_->GetSyntheticFieldTrialsOlderThan(log_creation_time,
&synthetic_trials);
WriteFieldTrials(synthetic_trials, system_profile_proto);
}
diff --git a/chromium/components/metrics/field_trials_provider.h b/chromium/components/metrics/field_trials_provider.h
index d93988edc68..6d115e5e47a 100644
--- a/chromium/components/metrics/field_trials_provider.h
+++ b/chromium/components/metrics/field_trials_provider.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_METRICS_FIELD_TRIALS_PROVIDER_H_
#define COMPONENTS_METRICS_FIELD_TRIALS_PROVIDER_H_
-#include <vector>
-
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "components/metrics/metrics_provider.h"
@@ -27,9 +25,11 @@ class FieldTrialsProvider : public metrics::MetricsProvider {
~FieldTrialsProvider() override;
// metrics::MetricsProvider:
- void OnDidCreateMetricsLog() override;
void ProvideSystemProfileMetrics(
metrics::SystemProfileProto* system_profile_proto) override;
+ void ProvideSystemProfileMetricsWithLogCreationTime(
+ base::TimeTicks log_creation_time,
+ metrics::SystemProfileProto* system_profile_proto) override;
private:
// Overrideable for testing.
@@ -41,13 +41,7 @@ class FieldTrialsProvider : public metrics::MetricsProvider {
// Suffix used for the field trial names before they are hashed for uploads.
std::string suffix_;
- // A stack of log creation times.
- // While the initial metrics log exists, there will be two logs open.
- // Use a stack so that we use the right creation time for the first ongoing
- // log.
- // TODO(crbug/746098): Simplify InitialMetricsLog logic so this is not
- // necessary.
- std::vector<base::TimeTicks> creation_times_;
+ DISALLOW_COPY_AND_ASSIGN(FieldTrialsProvider);
};
} // namespace variations
diff --git a/chromium/components/metrics/field_trials_provider_unittest.cc b/chromium/components/metrics/field_trials_provider_unittest.cc
index d7974c777bb..0190615cda4 100644
--- a/chromium/components/metrics/field_trials_provider_unittest.cc
+++ b/chromium/components/metrics/field_trials_provider_unittest.cc
@@ -96,14 +96,17 @@ TEST_F(FieldTrialsProviderTest, ProvideSyntheticTrials) {
// Make sure these trials are older than the log.
WaitUntilTimeChanges(base::TimeTicks::Now());
- provider.OnDidCreateMetricsLog();
+ // Get the current time and wait for it to change.
+ base::TimeTicks log_creation_time = base::TimeTicks::Now();
+
// Make sure that the log is older than the trials that should be excluded.
- WaitUntilTimeChanges(base::TimeTicks::Now());
+ WaitUntilTimeChanges(log_creation_time);
RegisterExtraSyntheticTrial();
metrics::SystemProfileProto proto;
- provider.ProvideSystemProfileMetrics(&proto);
+ provider.ProvideSystemProfileMetricsWithLogCreationTime(log_creation_time,
+ &proto);
ASSERT_EQ(base::size(kFieldTrialIds) + base::size(kSyntheticTrials),
static_cast<size_t>(proto.field_trial_size()));
@@ -115,7 +118,8 @@ TEST_F(FieldTrialsProviderTest, NoSyntheticTrials) {
TestProvider provider(nullptr, base::StringPiece());
metrics::SystemProfileProto proto;
- provider.ProvideSystemProfileMetrics(&proto);
+ provider.ProvideSystemProfileMetricsWithLogCreationTime(base::TimeTicks(),
+ &proto);
ASSERT_EQ(base::size(kFieldTrialIds),
static_cast<size_t>(proto.field_trial_size()));
diff --git a/chromium/components/metrics/file_metrics_provider.cc b/chromium/components/metrics/file_metrics_provider.cc
index e6d00d56dff..8217c95f7f9 100644
--- a/chromium/components/metrics/file_metrics_provider.cc
+++ b/chromium/components/metrics/file_metrics_provider.cc
@@ -97,9 +97,9 @@ scoped_refptr<base::TaskRunner> CreateBackgroundTaskRunner() {
if (g_task_runner_for_testing)
return scoped_refptr<base::TaskRunner>(g_task_runner_for_testing);
- return base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+ return base::CreateTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}
} // namespace
diff --git a/chromium/components/metrics/gpu/gpu_metrics_provider.cc b/chromium/components/metrics/gpu/gpu_metrics_provider.cc
index 53c15fb7c87..a1b1bba39f5 100644
--- a/chromium/components/metrics/gpu/gpu_metrics_provider.cc
+++ b/chromium/components/metrics/gpu/gpu_metrics_provider.cc
@@ -29,7 +29,6 @@ void GPUMetricsProvider::ProvideSystemProfileMetrics(
gpu->set_vendor_id(active_gpu.vendor_id);
gpu->set_device_id(active_gpu.device_id);
gpu->set_driver_version(active_gpu.driver_version);
- gpu->set_driver_date(active_gpu.driver_date);
gpu->set_gl_vendor(gpu_info.gl_vendor);
gpu->set_gl_renderer(gpu_info.gl_renderer);
}
diff --git a/chromium/components/metrics/metrics_log.cc b/chromium/components/metrics/metrics_log.cc
index 1f3f1ecd4de..f2f8e13c6ab 100644
--- a/chromium/components/metrics/metrics_log.cc
+++ b/chromium/components/metrics/metrics_log.cc
@@ -68,10 +68,6 @@ class IndependentFlattener : public base::HistogramFlattener {
DISALLOW_COPY_AND_ASSIGN(IndependentFlattener);
};
-// Any id less than 16 bytes is considered to be a testing id.
-bool IsTestingID(const std::string& id) {
- return id.size() < 16;
-}
} // namespace
@@ -103,11 +99,7 @@ MetricsLog::MetricsLog(const std::string& client_id,
client_(client),
creation_time_(base::TimeTicks::Now()),
has_environment_(false) {
- if (IsTestingID(client_id))
- uma_proto_.set_client_id(0);
- else
- uma_proto_.set_client_id(Hash(client_id));
-
+ uma_proto_.set_client_id(Hash(client_id));
uma_proto_.set_session_id(session_id);
const int32_t product = client_->GetProduct();
@@ -297,11 +289,25 @@ void MetricsLog::WriteRealtimeStabilityAttributes(
const SystemProfileProto& MetricsLog::RecordEnvironment(
DelegatingProvider* delegating_provider) {
- DCHECK(!has_environment_);
- has_environment_ = true;
+ // If |has_environment_| is true, then the system profile in |uma_proto_| has
+ // previously been fully filled in. We still want to fill it in again with
+ // more up to date information (e.g. current field trials), but in order to
+ // not have duplicate repeated fields, we must first clear it. Clearing it
+ // will reset the information filled in by RecordCoreSystemProfile() that was
+ // previously done in the constructor, so re-add that too.
+ //
+ // The |has_environment| case will happen on the very first log, where we
+ // call RecordEnvironment() in order to persist the system profile in the
+ // persistent hitograms .pma file.
+ if (has_environment_) {
+ uma_proto_.clear_system_profile();
+ MetricsLog::RecordCoreSystemProfile(client_,
+ uma_proto_.mutable_system_profile());
+ }
- SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
+ has_environment_ = true;
+ SystemProfileProto* system_profile = uma_proto_.mutable_system_profile();
WriteMetricsEnableDefault(client_->GetMetricsReportingDefaultState(),
system_profile);
@@ -309,7 +315,8 @@ const SystemProfileProto& MetricsLog::RecordEnvironment(
if (client_->GetBrand(&brand_code))
system_profile->set_brand_code(brand_code);
- delegating_provider->ProvideSystemProfileMetrics(system_profile);
+ delegating_provider->ProvideSystemProfileMetricsWithLogCreationTime(
+ creation_time_, system_profile);
return *system_profile;
}
diff --git a/chromium/components/metrics/metrics_log_unittest.cc b/chromium/components/metrics/metrics_log_unittest.cc
index be27a5ea185..0032e5b7b6b 100644
--- a/chromium/components/metrics/metrics_log_unittest.cc
+++ b/chromium/components/metrics/metrics_log_unittest.cc
@@ -81,15 +81,25 @@ class MetricsLogTest : public testing::Test {
~MetricsLogTest() override {}
protected:
- // Check that the values in |system_values| correspond to the test data
- // defined at the top of this file.
+ // Check that the values in |system_values| are filled in and expected ones
+ // correspond to the test data defined at the top of this file.
void CheckSystemProfile(const SystemProfileProto& system_profile) {
+ // Check for presence of core system profile fields.
+ EXPECT_TRUE(system_profile.has_build_timestamp());
+ EXPECT_TRUE(system_profile.has_app_version());
+ EXPECT_TRUE(system_profile.has_channel());
+ EXPECT_TRUE(system_profile.has_application_locale());
+
+ const SystemProfileProto::OS& os = system_profile.os();
+ EXPECT_TRUE(os.has_name());
+ EXPECT_TRUE(os.has_version());
+
+ // Check matching test brand code.
EXPECT_EQ(TestMetricsServiceClient::kBrandForTesting,
system_profile.brand_code());
- const SystemProfileProto::Hardware& hardware =
- system_profile.hardware();
-
+ // Check for presence of fields set by a metrics provider.
+ const SystemProfileProto::Hardware& hardware = system_profile.hardware();
EXPECT_TRUE(hardware.has_cpu());
EXPECT_TRUE(hardware.cpu().has_vendor_name());
EXPECT_TRUE(hardware.cpu().has_signature());
@@ -245,6 +255,19 @@ TEST_F(MetricsLogTest, RecordEnvironment) {
auto cpu_provider = std::make_unique<metrics::CPUMetricsProvider>();
delegating_provider.RegisterMetricsProvider(std::move(cpu_provider));
log.RecordEnvironment(&delegating_provider);
+
+ // Check non-system profile values.
+ EXPECT_EQ(MetricsLog::Hash(kClientId), log.uma_proto().client_id());
+ EXPECT_EQ(kSessionId, log.uma_proto().session_id());
+ // Check that the system profile on the log has the correct values set.
+ CheckSystemProfile(log.system_profile());
+
+ // Call RecordEnvironment() again and verify things are are still filled in.
+ log.RecordEnvironment(&delegating_provider);
+
+ // Check non-system profile values.
+ EXPECT_EQ(MetricsLog::Hash(kClientId), log.uma_proto().client_id());
+ EXPECT_EQ(kSessionId, log.uma_proto().session_id());
// Check that the system profile on the log has the correct values set.
CheckSystemProfile(log.system_profile());
}
diff --git a/chromium/components/metrics/metrics_provider.cc b/chromium/components/metrics/metrics_provider.cc
index 390f5806816..fb6fd3d2816 100644
--- a/chromium/components/metrics/metrics_provider.cc
+++ b/chromium/components/metrics/metrics_provider.cc
@@ -48,7 +48,12 @@ void MetricsProvider::ProvideIndependentMetrics(
}
void MetricsProvider::ProvideSystemProfileMetrics(
+ SystemProfileProto* system_profile_proto) {}
+
+void MetricsProvider::ProvideSystemProfileMetricsWithLogCreationTime(
+ base::TimeTicks log_creation_time,
SystemProfileProto* system_profile_proto) {
+ ProvideSystemProfileMetrics(system_profile_proto);
}
bool MetricsProvider::HasPreviousSessionData() {
diff --git a/chromium/components/metrics/metrics_provider.h b/chromium/components/metrics/metrics_provider.h
index b1af6620172..9560bcb55b0 100644
--- a/chromium/components/metrics/metrics_provider.h
+++ b/chromium/components/metrics/metrics_provider.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/time/time.h"
namespace base {
class HistogramSnapshotManager;
@@ -64,10 +65,19 @@ class MetricsProvider {
ChromeUserMetricsExtension* uma_proto,
base::HistogramSnapshotManager* snapshot_manager);
- // Provides additional metrics into the system profile.
+ // Provides additional metrics into the system profile. This is a convenience
+ // method over ProvideSystemProfileMetricsWithLogCreationTime() without the
+ // |log_creation_time| param. Should not be called directly by services.
virtual void ProvideSystemProfileMetrics(
SystemProfileProto* system_profile_proto);
+ // Provides additional metrics into the system profile. The log creation
+ // time param provides a timestamp of when the log was opened, which is needed
+ // for some metrics providers.
+ virtual void ProvideSystemProfileMetricsWithLogCreationTime(
+ base::TimeTicks log_creation_time,
+ SystemProfileProto* system_profile_proto);
+
// Called once at startup to see whether this provider has critical data
// to provide about the previous session.
// Returning true will trigger ProvidePreviousSessionData on all other
diff --git a/chromium/components/metrics/metrics_service.cc b/chromium/components/metrics/metrics_service.cc
index 1d7ce1d6457..2f29ae05055 100644
--- a/chromium/components/metrics/metrics_service.cc
+++ b/chromium/components/metrics/metrics_service.cc
@@ -316,16 +316,17 @@ void MetricsService::EnableRecording() {
state_manager_->ForceClientIdCreation();
client_->SetMetricsClientId(state_manager_->client_id());
- SystemProfileProto system_profile;
- MetricsLog::RecordCoreSystemProfile(client_, &system_profile);
- GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
- system_profile, /*complete=*/false);
-
if (!log_manager_.current_log())
OpenNewLog();
delegating_provider_.OnRecordingEnabled();
+ // Fill in the system profile in the log and persist it (to prefs, .pma and
+ // crashpad). This includes running the providers so that information like
+ // field trials and hardware info is provided. If Chrome crashes before this
+ // log is completed, the .pma file will have this system profile.
+ RecordCurrentEnvironment(log_manager_.current_log(), /*complete=*/false);
+
base::RemoveActionCallback(action_callback_);
action_callback_ = base::Bind(&MetricsService::OnUserAction,
base::Unretained(this));
@@ -415,10 +416,18 @@ void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
}
}
-void MetricsService::OnAppEnterForeground() {
+void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
StartSchedulerIfNecessary();
+
+ if (force_open_new_log && recording_active() && state_ >= SENDING_LOGS) {
+ // Because state_ >= SENDING_LOGS, PushPendingLogsToPersistentStorage()
+ // will close the log, allowing a new log to be opened.
+ PushPendingLogsToPersistentStorage();
+ OpenNewLog();
+ }
}
+
#else
void MetricsService::LogNeedForCleanShutdown() {
state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
@@ -620,7 +629,7 @@ void MetricsService::CloseCurrentLog() {
// MetricsLog class.
MetricsLog* current_log = log_manager_.current_log();
DCHECK(current_log);
- RecordCurrentEnvironment(current_log);
+ RecordCurrentEnvironment(current_log, /*complete=*/true);
base::TimeDelta incremental_uptime;
base::TimeDelta uptime;
GetUptimes(local_state_, &incremental_uptime, &uptime);
@@ -752,7 +761,7 @@ bool MetricsService::PrepareInitialStabilityLog(
void MetricsService::PrepareInitialMetricsLog() {
DCHECK_EQ(INIT_TASK_DONE, state_);
- RecordCurrentEnvironment(initial_metrics_log_.get());
+ RecordCurrentEnvironment(initial_metrics_log_.get(), /*complete=*/true);
base::TimeDelta incremental_uptime;
base::TimeDelta uptime;
GetUptimes(local_state_, &incremental_uptime, &uptime);
@@ -806,6 +815,14 @@ std::unique_ptr<MetricsLog> MetricsService::CreateLog(
log_type, client_);
}
+void MetricsService::SetPersistentSystemProfile(
+ const std::string& serialized_proto,
+ bool complete) {
+ GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
+ serialized_proto, complete);
+}
+
+// static
std::string MetricsService::RecordCurrentEnvironmentHelper(
MetricsLog* log,
PrefService* local_state,
@@ -816,12 +833,12 @@ std::string MetricsService::RecordCurrentEnvironmentHelper(
return recorder.SerializeAndRecordEnvironmentToPrefs(system_profile);
}
-void MetricsService::RecordCurrentEnvironment(MetricsLog* log) {
+void MetricsService::RecordCurrentEnvironment(MetricsLog* log, bool complete) {
DCHECK(client_);
std::string serialized_proto =
RecordCurrentEnvironmentHelper(log, local_state_, &delegating_provider_);
- GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile(
- serialized_proto, /*complete=*/true);
+
+ SetPersistentSystemProfile(serialized_proto, complete);
client_->OnEnvironmentUpdate(&serialized_proto);
}
diff --git a/chromium/components/metrics/metrics_service.h b/chromium/components/metrics/metrics_service.h
index 8ca5b75fc5d..7270f834923 100644
--- a/chromium/components/metrics/metrics_service.h
+++ b/chromium/components/metrics/metrics_service.h
@@ -38,6 +38,8 @@ class PrefService;
class PrefRegistrySimple;
FORWARD_DECLARE_TEST(ChromeMetricsServiceClientTest,
TestRegisterMetricsServiceProviders);
+FORWARD_DECLARE_TEST(IOSChromeMetricsServiceClientTest,
+ TestRegisterMetricsServiceProviders);
namespace base {
class HistogramSamples;
@@ -132,7 +134,7 @@ class MetricsService : public base::HistogramFlattener {
void OnAppEnterBackground(bool keep_recording_in_background = false);
// Called when the application is coming out of background mode.
- void OnAppEnterForeground();
+ void OnAppEnterForeground(bool force_open_new_log = false);
#else
// Set the dirty flag, which will require a later call to LogCleanShutdown().
void LogNeedForCleanShutdown();
@@ -180,6 +182,10 @@ class MetricsService : public base::HistogramFlattener {
return reporting_service_.metrics_log_store();
}
+ // Sets the persistent system profile. Virtual for tests.
+ virtual void SetPersistentSystemProfile(const std::string& serialized_proto,
+ bool complete);
+
// Records the current environment (system profile) in |log|, and persists
// the results in prefs.
// Exposed for testing.
@@ -291,8 +297,7 @@ class MetricsService : public base::HistogramFlattener {
// Records the current environment (system profile) in |log|, and persists
// the results in prefs and GlobalPersistentSystemProfile.
- // Exposed for testing.
- void RecordCurrentEnvironment(MetricsLog* log);
+ void RecordCurrentEnvironment(MetricsLog* log, bool complete);
// Record complete list of histograms into the current log.
// Called when we close a log.
@@ -390,6 +395,8 @@ class MetricsService : public base::HistogramFlattener {
FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, IsPluginProcess);
FRIEND_TEST_ALL_PREFIXES(::ChromeMetricsServiceClientTest,
TestRegisterMetricsServiceProviders);
+ FRIEND_TEST_ALL_PREFIXES(::IOSChromeMetricsServiceClientTest,
+ TestRegisterMetricsServiceProviders);
SEQUENCE_CHECKER(sequence_checker_);
// Weak pointers factory used to post task on different threads. All weak
diff --git a/chromium/components/metrics/metrics_service_accessor.cc b/chromium/components/metrics/metrics_service_accessor.cc
index 6cfa202800a..bddf51512c1 100644
--- a/chromium/components/metrics/metrics_service_accessor.cc
+++ b/chromium/components/metrics/metrics_service_accessor.cc
@@ -6,6 +6,7 @@
#include "base/base_switches.h"
#include "base/command_line.h"
+#include "build/branding_buildflags.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/prefs/pref_service.h"
@@ -25,14 +26,14 @@ bool IsMetricsReportingEnabledForOfficialBuild(PrefService* pref_service) {
// static
bool MetricsServiceAccessor::IsMetricsReportingEnabled(
PrefService* pref_service) {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return IsMetricsReportingEnabledForOfficialBuild(pref_service);
#else
// In non-official builds, disable metrics reporting completely.
return g_force_official_enabled_test
? IsMetricsReportingEnabledForOfficialBuild(pref_service)
: false;
-#endif // defined(GOOGLE_CHROME_BUILD)
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}
// static
diff --git a/chromium/components/metrics/metrics_service_unittest.cc b/chromium/components/metrics/metrics_service_unittest.cc
index bf84ff375d3..43d7d304024 100644
--- a/chromium/components/metrics/metrics_service_unittest.cc
+++ b/chromium/components/metrics/metrics_service_unittest.cc
@@ -62,7 +62,24 @@ class TestMetricsService : public MetricsService {
using MetricsService::log_store;
using MetricsService::RecordCurrentEnvironmentHelper;
+ // MetricsService:
+ void SetPersistentSystemProfile(const std::string& serialized_proto,
+ bool complete) override {
+ persistent_system_profile_provided_ = true;
+ persistent_system_profile_complete_ = complete;
+ }
+
+ bool persistent_system_profile_provided() const {
+ return persistent_system_profile_provided_;
+ }
+ bool persistent_system_profile_complete() const {
+ return persistent_system_profile_complete_;
+ }
+
private:
+ bool persistent_system_profile_provided_ = false;
+ bool persistent_system_profile_complete_ = false;
+
DISALLOW_COPY_AND_ASSIGN(TestMetricsService);
};
@@ -345,6 +362,30 @@ TEST_F(MetricsServiceTest, MetricsProvidersInitialized) {
EXPECT_TRUE(test_provider->init_called());
}
+TEST_F(MetricsServiceTest, SystemProfileDataProvidedOnEnableRecording) {
+ EnableMetricsReporting();
+ TestMetricsServiceClient client;
+ TestMetricsService service(GetMetricsStateManager(), &client,
+ GetLocalState());
+
+ TestMetricsProvider* test_provider = new TestMetricsProvider();
+ service.RegisterMetricsProvider(
+ std::unique_ptr<MetricsProvider>(test_provider));
+
+ service.InitializeMetricsRecordingState();
+
+ // ProvideSystemProfileMetrics() shouldn't be called initially.
+ EXPECT_FALSE(test_provider->provide_system_profile_metrics_called());
+ EXPECT_FALSE(service.persistent_system_profile_provided());
+
+ service.Start();
+
+ // Start should call ProvideSystemProfileMetrics().
+ EXPECT_TRUE(test_provider->provide_system_profile_metrics_called());
+ EXPECT_TRUE(service.persistent_system_profile_provided());
+ EXPECT_FALSE(service.persistent_system_profile_complete());
+}
+
TEST_F(MetricsServiceTest, SplitRotation) {
EnableMetricsReporting();
TestMetricsServiceClient client;
diff --git a/chromium/components/metrics/metrics_state_manager.cc b/chromium/components/metrics/metrics_state_manager.cc
index 8a3adc0f8dc..b0010a725c8 100644
--- a/chromium/components/metrics/metrics_state_manager.cc
+++ b/chromium/components/metrics/metrics_state_manager.cc
@@ -159,6 +159,11 @@ MetricsStateManager::MetricsStateManager(
// UMA is not enabled at this point, it's unlikely it will be enabled in
// the same session since that requires the user to manually do that via
// settings page after they unchecked it on the download page.
+ //
+ // Note: Windows first run is covered by browser tests
+ // FirstRunMasterPrefsVariationsSeedTest.PRE_SecondRun and
+ // FirstRunMasterPrefsVariationsSeedTest.SecondRun. If the platform ifdef
+ // for this logic changes, the tests should be updated as well.
if (client_id_.empty())
provisional_client_id_ = base::GenerateGUID();
#endif // !defined(OS_WIN)
diff --git a/chromium/components/metrics/net/DEPS b/chromium/components/metrics/net/DEPS
index 2f5402f3c59..36375496d2d 100644
--- a/chromium/components/metrics/net/DEPS
+++ b/chromium/components/metrics/net/DEPS
@@ -3,8 +3,8 @@ include_rules = [
"+chromeos/network",
"+components/encrypted_messages",
"+components/variations",
- "+content/public/test/test_browser_thread_bundle.h",
- "+ios/web/public/test/test_web_thread_bundle.h",
+ "+content/public/test/browser_task_environment.h",
+ "+ios/web/public/test/web_task_environment.h",
"+net",
"+services/network/public/cpp",
"+services/network/test",
diff --git a/chromium/components/metrics/net/net_metrics_log_uploader.cc b/chromium/components/metrics/net/net_metrics_log_uploader.cc
index 205fd598b81..728c9289469 100644
--- a/chromium/components/metrics/net/net_metrics_log_uploader.cc
+++ b/chromium/components/metrics/net/net_metrics_log_uploader.cc
@@ -254,7 +254,7 @@ void NetMetricsLogUploader::UploadLogToURL(
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
// Drop cookies and auth data.
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
std::string reporting_info_string = SerializeReportingInfo(reporting_info);
diff --git a/chromium/components/metrics/net/net_metrics_log_uploader_unittest.cc b/chromium/components/metrics/net/net_metrics_log_uploader_unittest.cc
index 484f4900206..13bf84364eb 100644
--- a/chromium/components/metrics/net/net_metrics_log_uploader_unittest.cc
+++ b/chromium/components/metrics/net/net_metrics_log_uploader_unittest.cc
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -113,7 +113,7 @@ class NetMetricsLogUploaderTest : public testing::Test {
scoped_refptr<network::SharedURLLoaderFactory>
test_shared_url_loader_factory_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::RunLoop loop_;
std::string upload_data_;
diff --git a/chromium/components/metrics/net/network_metrics_provider.cc b/chromium/components/metrics/net/network_metrics_provider.cc
index a83e1fcddcf..279bb347a07 100644
--- a/chromium/components/metrics/net/network_metrics_provider.cc
+++ b/chromium/components/metrics/net/network_metrics_provider.cc
@@ -300,9 +300,9 @@ NetworkMetricsProvider::GetWifiPHYLayerProtocol() const {
void NetworkMetricsProvider::ProbeWifiPHYLayerProtocol() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&net::GetWifiPHYLayerProtocol),
base::BindOnce(&NetworkMetricsProvider::OnWifiPHYLayerProtocolResult,
diff --git a/chromium/components/metrics/net/network_metrics_provider_unittest.cc b/chromium/components/metrics/net/network_metrics_provider_unittest.cc
index d1296a94f93..a25ed76f62e 100644
--- a/chromium/components/metrics/net/network_metrics_provider_unittest.cc
+++ b/chromium/components/metrics/net/network_metrics_provider_unittest.cc
@@ -22,11 +22,11 @@
#endif // OS_CHROMEOS
#if defined(OS_IOS)
-#include "ios/web/public/test/test_web_thread_bundle.h"
-using TestThreadBundle = web::TestWebThreadBundle;
+#include "ios/web/public/test/web_task_environment.h"
+using MetricsTaskEnvironment = web::WebTaskEnvironment;
#else // !defined(OS_IOS)
-#include "content/public/test/test_browser_thread_bundle.h"
-using TestThreadBundle = content::TestBrowserThreadBundle;
+#include "content/public/test/browser_task_environment.h"
+using MetricsTaskEnvironment = content::BrowserTaskEnvironment;
#endif // defined(OS_IOS)
namespace metrics {
@@ -35,7 +35,7 @@ class NetworkMetricsProviderTest : public testing::Test {
public:
protected:
NetworkMetricsProviderTest()
- : test_thread_bundle_(TestThreadBundle::IO_MAINLOOP) {}
+ : task_environment_(MetricsTaskEnvironment::IO_MAINLOOP) {}
~NetworkMetricsProviderTest() override {}
void SetUp() override {
@@ -53,7 +53,7 @@ class NetworkMetricsProviderTest : public testing::Test {
}
private:
- TestThreadBundle test_thread_bundle_;
+ MetricsTaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(NetworkMetricsProviderTest);
};
diff --git a/chromium/components/metrics/persistent_histograms.cc b/chromium/components/metrics/persistent_histograms.cc
index 29a54f5a908..20d02f3975c 100644
--- a/chromium/components/metrics/persistent_histograms.cc
+++ b/chromium/components/metrics/persistent_histograms.cc
@@ -168,9 +168,9 @@ void InstantiatePersistentHistograms(const base::FilePath& metrics_dir) {
}
}
// Schedule the creation of a "spare" file for use on the next run.
- base::PostDelayedTaskWithTraits(
+ base::PostDelayedTask(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::LOWEST,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::LOWEST,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(base::IgnoreResult(
&base::GlobalHistogramAllocator::CreateSpareFile),
@@ -211,9 +211,9 @@ void InstantiatePersistentHistograms(const base::FilePath& metrics_dir) {
allocator->CreateTrackingHistograms(kBrowserMetricsName);
#if defined(OS_WIN)
- base::PostDelayedTaskWithTraits(
+ base::PostDelayedTask(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::LOWEST,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::LOWEST,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&DeleteOldWindowsTempFiles, std::move(metrics_dir)),
kDeleteOldWindowsTempFilesDelay);
diff --git a/chromium/components/metrics/public/interfaces/BUILD.gn b/chromium/components/metrics/public/mojom/BUILD.gn
index 2a84979353f..2a84979353f 100644
--- a/chromium/components/metrics/public/interfaces/BUILD.gn
+++ b/chromium/components/metrics/public/mojom/BUILD.gn
diff --git a/chromium/components/metrics/public/interfaces/OWNERS b/chromium/components/metrics/public/mojom/OWNERS
index 154435234ea..154435234ea 100644
--- a/chromium/components/metrics/public/interfaces/OWNERS
+++ b/chromium/components/metrics/public/mojom/OWNERS
diff --git a/chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom b/chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom
index 51fcf816bad..51fcf816bad 100644
--- a/chromium/components/metrics/public/interfaces/call_stack_profile_collector.mojom
+++ b/chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom
diff --git a/chromium/components/metrics/public/interfaces/call_stack_profile_collector_test.mojom b/chromium/components/metrics/public/mojom/call_stack_profile_collector_test.mojom
index c7725c67939..ba59bcea518 100644
--- a/chromium/components/metrics/public/interfaces/call_stack_profile_collector_test.mojom
+++ b/chromium/components/metrics/public/mojom/call_stack_profile_collector_test.mojom
@@ -4,7 +4,7 @@
module metrics.mojom;
-import "components/metrics/public/interfaces/call_stack_profile_collector.mojom";
+import "components/metrics/public/mojom/call_stack_profile_collector.mojom";
interface CallStackProfileCollectorTest {
[Sync]
diff --git a/chromium/components/metrics/public/interfaces/single_sample_metrics.mojom b/chromium/components/metrics/public/mojom/single_sample_metrics.mojom
index 788150c0188..788150c0188 100644
--- a/chromium/components/metrics/public/interfaces/single_sample_metrics.mojom
+++ b/chromium/components/metrics/public/mojom/single_sample_metrics.mojom
diff --git a/chromium/components/metrics/single_sample_metrics.h b/chromium/components/metrics/single_sample_metrics.h
index 989f6a29b99..1bf69b81066 100644
--- a/chromium/components/metrics/single_sample_metrics.h
+++ b/chromium/components/metrics/single_sample_metrics.h
@@ -6,7 +6,7 @@
#define COMPONENTS_METRICS_SINGLE_SAMPLE_METRICS_H_
#include "base/callback.h"
-#include "components/metrics/public/interfaces/single_sample_metrics.mojom.h"
+#include "components/metrics/public/mojom/single_sample_metrics.mojom.h"
namespace metrics {
diff --git a/chromium/components/metrics/single_sample_metrics_factory_impl.h b/chromium/components/metrics/single_sample_metrics_factory_impl.h
index 297324f97b7..f00e0ff7e25 100644
--- a/chromium/components/metrics/single_sample_metrics_factory_impl.h
+++ b/chromium/components/metrics/single_sample_metrics_factory_impl.h
@@ -9,7 +9,7 @@
#include "base/metrics/single_sample_metrics.h"
#include "base/threading/thread_local.h"
-#include "components/metrics/public/interfaces/single_sample_metrics.mojom.h"
+#include "components/metrics/public/mojom/single_sample_metrics.mojom.h"
#include "components/metrics/single_sample_metrics.h"
namespace metrics {
diff --git a/chromium/components/metrics/single_sample_metrics_factory_impl_unittest.cc b/chromium/components/metrics/single_sample_metrics_factory_impl_unittest.cc
index a14d23f71df..8308a23bb2d 100644
--- a/chromium/components/metrics/single_sample_metrics_factory_impl_unittest.cc
+++ b/chromium/components/metrics/single_sample_metrics_factory_impl_unittest.cc
@@ -9,7 +9,7 @@
#include "base/run_loop.h"
#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "components/metrics/single_sample_metrics.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -75,7 +75,7 @@ class SingleSampleMetricsFactoryImplTest : public testing::Test {
kBucketCount);
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
SingleSampleMetricsFactoryImpl* factory_;
base::Thread thread_;
size_t provider_count_ = 0;
diff --git a/chromium/components/metrics/ui/screen_info_metrics_provider.cc b/chromium/components/metrics/ui/screen_info_metrics_provider.cc
index f35639affa3..4465d903d70 100644
--- a/chromium/components/metrics/ui/screen_info_metrics_provider.cc
+++ b/chromium/components/metrics/ui/screen_info_metrics_provider.cc
@@ -66,12 +66,17 @@ ScreenInfoMetricsProvider::~ScreenInfoMetricsProvider() {
void ScreenInfoMetricsProvider::ProvideSystemProfileMetrics(
SystemProfileProto* system_profile_proto) {
+ // This may be called before the screen info has been initialized, such as
+ // when the persistent system profile gets filled in initially.
+ const base::Optional<gfx::Size> display_size = GetScreenSize();
+ if (!display_size.has_value())
+ return;
+
SystemProfileProto::Hardware* hardware =
system_profile_proto->mutable_hardware();
- const gfx::Size display_size = GetScreenSize();
- hardware->set_primary_screen_width(display_size.width());
- hardware->set_primary_screen_height(display_size.height());
+ hardware->set_primary_screen_width(display_size->width());
+ hardware->set_primary_screen_height(display_size->height());
hardware->set_primary_screen_scale_factor(GetScreenDeviceScaleFactor());
hardware->set_screen_count(GetScreenCount());
@@ -80,8 +85,11 @@ void ScreenInfoMetricsProvider::ProvideSystemProfileMetrics(
#endif
}
-gfx::Size ScreenInfoMetricsProvider::GetScreenSize() const {
- return display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel();
+base::Optional<gfx::Size> ScreenInfoMetricsProvider::GetScreenSize() const {
+ auto* screen = display::Screen::GetScreen();
+ if (!screen)
+ return base::nullopt;
+ return base::make_optional(screen->GetPrimaryDisplay().GetSizeInPixel());
}
float ScreenInfoMetricsProvider::GetScreenDeviceScaleFactor() const {
diff --git a/chromium/components/metrics/ui/screen_info_metrics_provider.h b/chromium/components/metrics/ui/screen_info_metrics_provider.h
index 51ef2b77ab1..f92caac0b5c 100644
--- a/chromium/components/metrics/ui/screen_info_metrics_provider.h
+++ b/chromium/components/metrics/ui/screen_info_metrics_provider.h
@@ -6,6 +6,7 @@
#define COMPONENTS_METRICS_UI_SCREEN_INFO_METRICS_PROVIDER_H_
#include "base/macros.h"
+#include "base/optional.h"
#include "components/metrics/metrics_provider.h"
#include "ui/gfx/geometry/size.h"
@@ -24,8 +25,8 @@ class ScreenInfoMetricsProvider : public MetricsProvider {
protected:
// Exposed for the sake of mocking in test code.
- // Returns the screen size for the primary monitor.
- virtual gfx::Size GetScreenSize() const;
+ // Returns the screen size for the primary monitor if available.
+ virtual base::Optional<gfx::Size> GetScreenSize() const;
// Returns the device scale factor for the primary monitor.
virtual float GetScreenDeviceScaleFactor() const;
diff --git a/chromium/components/metrics/ui/screen_info_metrics_provider_unittest.cc b/chromium/components/metrics/ui/screen_info_metrics_provider_unittest.cc
index 836e9770014..0c74ac4e003 100644
--- a/chromium/components/metrics/ui/screen_info_metrics_provider_unittest.cc
+++ b/chromium/components/metrics/ui/screen_info_metrics_provider_unittest.cc
@@ -24,8 +24,8 @@ class TestScreenInfoMetricsProvider : public ScreenInfoMetricsProvider {
~TestScreenInfoMetricsProvider() override {}
private:
- gfx::Size GetScreenSize() const override {
- return gfx::Size(kScreenWidth, kScreenHeight);
+ base::Optional<gfx::Size> GetScreenSize() const override {
+ return base::make_optional(gfx::Size(kScreenWidth, kScreenHeight));
}
float GetScreenDeviceScaleFactor() const override {
diff --git a/chromium/components/metrics/version_utils.cc b/chromium/components/metrics/version_utils.cc
index 9aac0c158ee..6d2cad2e87f 100644
--- a/chromium/components/metrics/version_utils.cc
+++ b/chromium/components/metrics/version_utils.cc
@@ -5,6 +5,7 @@
#include "components/metrics/version_utils.h"
#include "base/logging.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/version_info/version_info.h"
@@ -20,7 +21,7 @@ std::string GetVersionString() {
version += "-64";
#endif // defined(ARCH_CPU_64_BITS)
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
bool is_chrome_branded = true;
#else
bool is_chrome_branded = false;
diff --git a/chromium/components/metrics_services_manager/OWNERS b/chromium/components/metrics_services_manager/OWNERS
index c9290272739..3d8c9074387 100644
--- a/chromium/components/metrics_services_manager/OWNERS
+++ b/chromium/components/metrics_services_manager/OWNERS
@@ -1,3 +1,4 @@
file://base/metrics/OWNERS
# COMPONENT: Internals>Metrics
+# TEAM: chromium-dev@chromium.org
diff --git a/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java b/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
index 82b760d4101..8839a51150c 100644
--- a/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
+++ b/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/CrashFileManager.java
@@ -65,16 +65,27 @@ public class CrashFileManager {
// define the id to be a sequence of non separator characters {`-`, `,` or `.`}
private static final Pattern CRASH_LOCAL_ID_PATTERN = Pattern.compile("^[^.]+-([^-,]+?)\\.");
- // Unlike the MINIDUMP_READY_FOR_UPLOAD_PATTERN below, this pattern omits a ".tryN" suffix.
+ // Unlike the MINIDUMP_ALL_READY_FOR_UPLOAD_PATTERN below, this pattern omits a ".tryN" suffix.
private static final Pattern MINIDUMP_SANS_LOGCAT_PATTERN =
Pattern.compile("\\.dmp([0-9]*)\\z");
- private static final Pattern MINIDUMP_READY_FOR_UPLOAD_PATTERN =
+ // Minidumps that are ready for uploading including forced uploads.
+ private static final Pattern MINIDUMP_ALL_READY_FOR_UPLOAD_PATTERN =
Pattern.compile("\\.(dmp|forced)([0-9]*)(\\.try([0-9]+))\\z");
+ // Minidumps that are ready for uploading excluding forced uploads.
+ private static final Pattern MINIDUMP_READY_FOR_UPLOAD_PATTERN =
+ Pattern.compile("\\.(dmp)([0-9]*)(\\.try([0-9]+))\\z");
+
private static final Pattern UPLOADED_MINIDUMP_PATTERN =
Pattern.compile("\\.up([0-9]*)(\\.try([0-9]+))\\z");
+ private static final Pattern MINIDUMP_FORCED_UPLOAD_PATTERN =
+ Pattern.compile("\\.forced([0-9]*)(\\.try([0-9]+))\\z");
+
+ private static final Pattern MINIDUMP_SKIPPED_UPLOAD_PATTERN =
+ Pattern.compile("\\.skipped([0-9]*)(\\.try([0-9]+))\\z");
+
private static final String NOT_YET_UPLOADED_MINIDUMP_SUFFIX = ".dmp";
private static final String UPLOADED_MINIDUMP_SUFFIX = ".up";
@@ -408,7 +419,31 @@ public class CrashFileManager {
* Only returns files that we have tried to upload less than {@param maxTries} number of times.
*/
public File[] getMinidumpsReadyForUpload(int maxTries) {
- return getFilesBelowMaxTries(listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN), maxTries);
+ return getFilesBelowMaxTries(
+ listCrashFiles(MINIDUMP_ALL_READY_FOR_UPLOAD_PATTERN), maxTries);
+ }
+
+ /**
+ * Returns minidump files that could still be uploaded excluding forced uploads,
+ * sorted by modification time stamp.
+ */
+ public File[] getMinidumpsNotForcedReadyForUpload() {
+ return listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN);
+ }
+
+ /**
+ * Returns all minidump files that could still be uploaded, sorted by modification time stamp.
+ */
+ public File[] getMinidumpsSkippedUpload() {
+ return listCrashFiles(MINIDUMP_SKIPPED_UPLOAD_PATTERN);
+ }
+
+ /**
+ * Returns minidump files that are forced to be uploaded by the user, sorted by modification
+ * time stamp.
+ */
+ public File[] getMinidumpsForcedUpload() {
+ return listCrashFiles(MINIDUMP_FORCED_UPLOAD_PATTERN);
}
/**
@@ -596,7 +631,7 @@ public class CrashFileManager {
* @param uid The uid of the app to check the minidump limit for.
*/
private void enforceMinidumpStorageRestrictions(int uid) {
- File[] allMinidumpFiles = listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN);
+ File[] allMinidumpFiles = listCrashFiles(MINIDUMP_ALL_READY_FOR_UPLOAD_PATTERN);
List<File> minidumpFilesWithCurrentUid = filterMinidumpFilesOnUid(allMinidumpFiles, uid);
// If we have exceeded our cap per uid, delete the oldest minidump of the same uid
diff --git a/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java b/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
index 2b43ebfa5a4..db5ed2f8210 100644
--- a/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
+++ b/chromium/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
@@ -4,10 +4,8 @@
package org.chromium.components.minidump_uploader;
-import android.content.SharedPreferences;
import android.support.annotation.IntDef;
-import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.StreamUtil;
import org.chromium.base.VisibleForTesting;
@@ -40,11 +38,9 @@ import java.util.zip.GZIPOutputStream;
public class MinidumpUploadCallable implements Callable<Integer> {
private static final String TAG = "MDUploadCallable";
- // These preferences are obsolete and are kept only for removing from user preferences.
- protected static final String PREF_DAY_UPLOAD_COUNT = "crash_day_dump_upload_count";
- protected static final String PREF_LAST_UPLOAD_DAY = "crash_dump_last_upload_day";
- protected static final String PREF_LAST_UPLOAD_WEEK = "crash_dump_last_upload_week";
- protected static final String PREF_WEEK_UPLOAD_SIZE = "crash_dump_week_upload_size";
+ // "crash_day_dump_upload_count", "crash_dump_last_upload_day", "crash_dump_last_upload_week",
+ // "crash_dump_week_upload_size" - Deprecated prefs used for limiting crash report uploads over
+ // cellular network. Last used in M47, removed in M78.
@VisibleForTesting
protected static final String CRASH_URL_STRING = "https://clients2.google.com/cr/report";
@@ -70,7 +66,6 @@ public class MinidumpUploadCallable implements Callable<Integer> {
public MinidumpUploadCallable(
File fileToUpload, File logfile, CrashReportingPermissionManager permissionManager) {
this(fileToUpload, logfile, new HttpURLConnectionFactoryImpl(), permissionManager);
- removeOutdatedPrefs(ContextUtils.getAppSharedPreferences());
}
public MinidumpUploadCallable(File fileToUpload, File logfile,
@@ -312,14 +307,4 @@ public class MinidumpUploadCallable implements Callable<Integer> {
inStream.close();
outStream.close();
}
-
- // TODO(gayane): Remove this function and unused prefs in M51. crbug.com/555022
- private void removeOutdatedPrefs(SharedPreferences sharedPreferences) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.remove(PREF_DAY_UPLOAD_COUNT)
- .remove(PREF_LAST_UPLOAD_DAY)
- .remove(PREF_LAST_UPLOAD_WEEK)
- .remove(PREF_WEEK_UPLOAD_SIZE)
- .apply();
- }
}
diff --git a/chromium/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java b/chromium/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java
index b67106c72e5..d7d0f71c128 100644
--- a/chromium/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java
+++ b/chromium/components/minidump_uploader/android/javatests/src/org/chromium/components/minidump_uploader/CrashFileManagerTest.java
@@ -328,6 +328,59 @@ public class CrashFileManagerTest {
@Test
@SmallTest
@Feature({"Android-AppBase"})
+ public void testGetMinidumpsNotForcedReadyForUpload() throws IOException {
+ File forcedFile = new File(mTestRule.getCrashDir(), "456_def.forced" + TEST_PID + ".try2");
+ forcedFile.createNewFile();
+ forcedFile.setLastModified(mModificationTimestamp);
+ mModificationTimestamp += 1000;
+
+ CrashFileManager crashFileManager = new CrashFileManager(mTestRule.getCacheDir());
+ File[] expectedFiles = new File[] {mMultiDigitMaxTriesFile, mOneBelowMultiDigitMaxTriesFile,
+ mMaxTriesFile, mOneBelowMaxTriesFile, mDmpFile2, mDmpFile1};
+ File[] actualFiles = crashFileManager.getMinidumpsNotForcedReadyForUpload();
+ Assert.assertNotNull(actualFiles);
+ assertArrayEquals("Failed to get the correct minidump files in directory", expectedFiles,
+ actualFiles);
+ }
+
+ @Test
+ @SmallTest
+ @Feature({"Android-AppBase"})
+ public void testGetMinidumpsSkippedUpload() throws IOException {
+ File skippedFile =
+ new File(mTestRule.getCrashDir(), "456_def.skipped" + TEST_PID + ".try2");
+ skippedFile.createNewFile();
+ skippedFile.setLastModified(mModificationTimestamp);
+ mModificationTimestamp += 1000;
+
+ CrashFileManager crashFileManager = new CrashFileManager(mTestRule.getCacheDir());
+ File[] expectedFiles = new File[] {skippedFile};
+ File[] actualFiles = crashFileManager.getMinidumpsSkippedUpload();
+ Assert.assertNotNull(actualFiles);
+ assertArrayEquals("Failed to get the correct minidump files in directory", expectedFiles,
+ actualFiles);
+ }
+
+ @Test
+ @SmallTest
+ @Feature({"Android-AppBase"})
+ public void testGetMinidumpsForcedUpload() throws IOException {
+ File forcedFile = new File(mTestRule.getCrashDir(), "456_def.forced" + TEST_PID + ".try2");
+ forcedFile.createNewFile();
+ forcedFile.setLastModified(mModificationTimestamp);
+ mModificationTimestamp += 1000;
+
+ CrashFileManager crashFileManager = new CrashFileManager(mTestRule.getCacheDir());
+ File[] expectedFiles = new File[] {forcedFile};
+ File[] actualFiles = crashFileManager.getMinidumpsForcedUpload();
+ Assert.assertNotNull(actualFiles);
+ assertArrayEquals("Failed to get the correct minidump files in directory", expectedFiles,
+ actualFiles);
+ }
+
+ @Test
+ @SmallTest
+ @Feature({"Android-AppBase"})
public void testGetFilesBelowMaxTries() {
// No files in input -> return empty
assertArrayEquals(new File[0],
diff --git a/chromium/components/mirroring/browser/BUILD.gn b/chromium/components/mirroring/browser/BUILD.gn
index f73a468b178..d21847dba43 100644
--- a/chromium/components/mirroring/browser/BUILD.gn
+++ b/chromium/components/mirroring/browser/BUILD.gn
@@ -22,7 +22,7 @@ source_set("browser") {
"//media/cast:common",
"//media/cast:net",
"//media/mojo/common:common",
- "//media/mojo/interfaces:remoting",
+ "//media/mojo/mojom:remoting",
"//mojo/public/cpp/bindings",
]
}
@@ -42,7 +42,7 @@ source_set("unittests") {
"//media/cast:common",
"//media/cast:net",
"//media/cast:test_support",
- "//media/mojo/interfaces:remoting",
+ "//media/mojo/mojom:remoting",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//testing/gmock",
diff --git a/chromium/components/mirroring/browser/cast_remoting_sender.cc b/chromium/components/mirroring/browser/cast_remoting_sender.cc
index 75d56be8407..310f83eacc6 100644
--- a/chromium/components/mirroring/browser/cast_remoting_sender.cc
+++ b/chromium/components/mirroring/browser/cast_remoting_sender.cc
@@ -135,7 +135,7 @@ void CastRemotingSender::FindAndBind(
// CastRemotingSender lives entirely on the IO thread, so trampoline if
// necessary.
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(
&CastRemotingSender::FindAndBind, rtp_stream_id, std::move(pipe),
diff --git a/chromium/components/mirroring/browser/cast_remoting_sender.h b/chromium/components/mirroring/browser/cast_remoting_sender.h
index f4cecc75d9a..fecef9e42b8 100644
--- a/chromium/components/mirroring/browser/cast_remoting_sender.h
+++ b/chromium/components/mirroring/browser/cast_remoting_sender.h
@@ -12,7 +12,7 @@
#include "media/cast/cast_config.h"
#include "media/cast/net/cast_transport.h"
#include "media/cast/net/rtcp/rtcp_defines.h"
-#include "media/mojo/interfaces/remoting.mojom.h"
+#include "media/mojo/mojom/remoting.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace media {
diff --git a/chromium/components/mirroring/browser/cast_remoting_sender_unittest.cc b/chromium/components/mirroring/browser/cast_remoting_sender_unittest.cc
index 5be55054477..bc0995ca9b5 100644
--- a/chromium/components/mirroring/browser/cast_remoting_sender_unittest.cc
+++ b/chromium/components/mirroring/browser/cast_remoting_sender_unittest.cc
@@ -10,11 +10,11 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/time/default_tick_clock.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "media/cast/constants.h"
#include "media/cast/net/cast_transport.h"
#include "media/cast/test/utility/default_config.h"
-#include "media/mojo/interfaces/remoting.mojom.h"
+#include "media/mojo/mojom/remoting.mojom.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -103,7 +103,7 @@ class FakeTransport : public media::cast::CastTransport {
class CastRemotingSenderTest : public ::testing::Test {
protected:
CastRemotingSenderTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP),
expecting_error_callback_run_(false) {
media::cast::FrameSenderConfig video_config =
media::cast::GetDefaultVideoSenderConfig();
@@ -258,7 +258,7 @@ class CastRemotingSenderTest : public ::testing::Test {
private:
void OnError() { CHECK(expecting_error_callback_run_); }
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
media::cast::CastTransportRtpConfig transport_config_;
FakeTransport transport_;
std::unique_ptr<CastRemotingSender> remoting_sender_;
diff --git a/chromium/components/mirroring/browser/single_client_video_capture_host.cc b/chromium/components/mirroring/browser/single_client_video_capture_host.cc
index 601b31a0bc6..8c20ecb72ac 100644
--- a/chromium/components/mirroring/browser/single_client_video_capture_host.cc
+++ b/chromium/components/mirroring/browser/single_client_video_capture_host.cc
@@ -61,12 +61,12 @@ SingleClientVideoCaptureHost::SingleClientVideoCaptureHost(
SingleClientVideoCaptureHost::~SingleClientVideoCaptureHost() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- Stop(0);
+ Stop(base::UnguessableToken());
}
void SingleClientVideoCaptureHost::Start(
- int32_t device_id,
- int32_t session_id,
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
const VideoCaptureParams& params,
media::mojom::VideoCaptureObserverPtr observer) {
DVLOG(1) << __func__;
@@ -98,7 +98,8 @@ void SingleClientVideoCaptureHost::Start(
std::move(device_launcher_callbacks)));
}
-void SingleClientVideoCaptureHost::Stop(int32_t device_id) {
+void SingleClientVideoCaptureHost::Stop(
+ const base::UnguessableToken& device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOG(1) << __func__;
@@ -124,28 +125,31 @@ void SingleClientVideoCaptureHost::Stop(int32_t device_id) {
retired_buffers_.clear();
}
-void SingleClientVideoCaptureHost::Pause(int32_t device_id) {
+void SingleClientVideoCaptureHost::Pause(
+ const base::UnguessableToken& device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (launched_device_)
launched_device_->MaybeSuspendDevice();
}
-void SingleClientVideoCaptureHost::Resume(int32_t device_id,
- int32_t session_id,
- const VideoCaptureParams& params) {
+void SingleClientVideoCaptureHost::Resume(
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
+ const VideoCaptureParams& params) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (launched_device_)
launched_device_->ResumeDevice();
}
-void SingleClientVideoCaptureHost::RequestRefreshFrame(int32_t device_id) {
+void SingleClientVideoCaptureHost::RequestRefreshFrame(
+ const base::UnguessableToken& device_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (launched_device_)
launched_device_->RequestRefreshFrame();
}
void SingleClientVideoCaptureHost::ReleaseBuffer(
- int32_t device_id,
+ const base::UnguessableToken& device_id,
int32_t buffer_id,
double consumer_resource_utilization) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -155,8 +159,8 @@ void SingleClientVideoCaptureHost::ReleaseBuffer(
}
void SingleClientVideoCaptureHost::GetDeviceSupportedFormats(
- int32_t device_id,
- int32_t session_id,
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
GetDeviceSupportedFormatsCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTIMPLEMENTED();
@@ -164,8 +168,8 @@ void SingleClientVideoCaptureHost::GetDeviceSupportedFormats(
}
void SingleClientVideoCaptureHost::GetDeviceFormatsInUse(
- int32_t device_id,
- int32_t session_id,
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
GetDeviceFormatsInUseCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NOTIMPLEMENTED();
@@ -173,14 +177,15 @@ void SingleClientVideoCaptureHost::GetDeviceFormatsInUse(
}
void SingleClientVideoCaptureHost::OnFrameDropped(
- int32_t device_id,
+ const base::UnguessableToken& device_id,
media::VideoCaptureFrameDropReason reason) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Ignore this call.
}
-void SingleClientVideoCaptureHost::OnLog(int32_t device_id,
- const std::string& message) {
+void SingleClientVideoCaptureHost::OnLog(
+ const base::UnguessableToken& device_id,
+ const std::string& message) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Ignore this call.
}
diff --git a/chromium/components/mirroring/browser/single_client_video_capture_host.h b/chromium/components/mirroring/browser/single_client_video_capture_host.h
index 9d6e8731564..7821da906d8 100644
--- a/chromium/components/mirroring/browser/single_client_video_capture_host.h
+++ b/chromium/components/mirroring/browser/single_client_video_capture_host.h
@@ -45,29 +45,30 @@ class SingleClientVideoCaptureHost final
// media::mojom::VideoCaptureHost implementations
// |device_id| and |session_id| are ignored since there will be only one
// device and one client.
- void Start(int32_t device_id,
- int32_t session_id,
+ void Start(const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
const VideoCaptureParams& params,
media::mojom::VideoCaptureObserverPtr observer) override;
- void Stop(int32_t device_id) override;
- void Pause(int32_t device_id) override;
- void Resume(int32_t device_id,
- int32_t session_id,
+ void Stop(const base::UnguessableToken& device_id) override;
+ void Pause(const base::UnguessableToken& device_id) override;
+ void Resume(const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
const VideoCaptureParams& params) override;
- void RequestRefreshFrame(int32_t device_id) override;
- void ReleaseBuffer(int32_t device_id,
+ void RequestRefreshFrame(const base::UnguessableToken& device_id) override;
+ void ReleaseBuffer(const base::UnguessableToken& device_id,
int32_t buffer_id,
double consumer_resource_utilization) override;
void GetDeviceSupportedFormats(
- int32_t device_id,
- int32_t session_id,
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
GetDeviceSupportedFormatsCallback callback) override;
- void GetDeviceFormatsInUse(int32_t device_id,
- int32_t session_id,
+ void GetDeviceFormatsInUse(const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
GetDeviceFormatsInUseCallback callback) override;
- void OnFrameDropped(int32_t device_id,
+ void OnFrameDropped(const base::UnguessableToken& device_id,
media::VideoCaptureFrameDropReason reason) override;
- void OnLog(int32_t device_id, const std::string& message) override;
+ void OnLog(const base::UnguessableToken& device_id,
+ const std::string& message) override;
// media::VideoFrameReceiver implementations
using Buffer = VideoCaptureDevice::Client::Buffer;
diff --git a/chromium/components/mirroring/browser/single_client_video_capture_host_unittest.cc b/chromium/components/mirroring/browser/single_client_video_capture_host_unittest.cc
index da17d96bd4b..36a3576d21b 100644
--- a/chromium/components/mirroring/browser/single_client_video_capture_host_unittest.cc
+++ b/chromium/components/mirroring/browser/single_client_video_capture_host_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -133,7 +133,8 @@ class MockVideoCaptureObserver final
void Start() {
media::mojom::VideoCaptureObserverPtr observer;
binding_.Bind(mojo::MakeRequest(&observer));
- host_->Start(0, 0, VideoCaptureParams(), std::move(observer));
+ host_->Start(device_id_, session_id_, VideoCaptureParams(),
+ std::move(observer));
}
void FinishConsumingBuffer(int32_t buffer_id, double utilization) {
@@ -141,12 +142,14 @@ class MockVideoCaptureObserver final
const auto iter = frame_infos_.find(buffer_id);
EXPECT_TRUE(iter != frame_infos_.end());
frame_infos_.erase(iter);
- host_->ReleaseBuffer(0, buffer_id, utilization);
+ host_->ReleaseBuffer(device_id_, buffer_id, utilization);
}
- void Stop() { host_->Stop(0); }
+ void Stop() { host_->Stop(device_id_); }
private:
+ const base::UnguessableToken device_id_ = base::UnguessableToken::Create();
+ const base::UnguessableToken session_id_ = base::UnguessableToken::Create();
media::mojom::VideoCaptureHostPtr host_;
mojo::Binding<media::mojom::VideoCaptureObserver> binding_;
base::flat_map<int, media::mojom::VideoBufferHandlePtr> buffers_;
@@ -239,7 +242,7 @@ class SingleClientVideoCaptureHostTest : public ::testing::Test {
run_loop.Run();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<MockVideoCaptureObserver> consumer_;
base::WeakPtr<VideoFrameReceiver> frame_receiver_;
MockVideoCaptureDevice* launched_device_ = nullptr;
@@ -277,7 +280,7 @@ TEST_F(SingleClientVideoCaptureHostTest, ReuseBufferId) {
{
EXPECT_CALL(*consumer_, OnBufferDestroyedCall(0)).Times(0);
frame_receiver_->OnBufferRetired(0);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// Re-use buffer 0.
diff --git a/chromium/components/mirroring/mojom/BUILD.gn b/chromium/components/mirroring/mojom/BUILD.gn
index 471ccbaa4ba..b62d28b0e6b 100644
--- a/chromium/components/mirroring/mojom/BUILD.gn
+++ b/chromium/components/mirroring/mojom/BUILD.gn
@@ -4,12 +4,6 @@
import("//mojo/public/tools/bindings/mojom.gni")
-mojom("constants") {
- sources = [
- "constants.mojom",
- ]
-}
-
mojom("common") {
sources = [
"cast_message_channel.mojom",
@@ -42,9 +36,10 @@ mojom("service") {
public_deps = [
":common",
"//media/capture/mojom:video_capture",
- "//media/mojo/interfaces:interfaces",
- "//media/mojo/interfaces:remoting",
+ "//media/mojo/mojom",
+ "//media/mojo/mojom:remoting",
"//services/network/public/mojom",
- "//ui/gfx/geometry/mojo",
+ "//services/viz/public/mojom",
+ "//ui/gfx/geometry/mojom",
]
}
diff --git a/chromium/components/mirroring/mojom/constants.mojom b/chromium/components/mirroring/mojom/constants.mojom
deleted file mode 100644
index ace762ec2e5..00000000000
--- a/chromium/components/mirroring/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module mirroring.mojom;
-
-const string kServiceName = "mirroring";
diff --git a/chromium/components/mirroring/mojom/mirroring_service.mojom b/chromium/components/mirroring/mojom/mirroring_service.mojom
index 09c6762bbf2..c58a02e41a0 100644
--- a/chromium/components/mirroring/mojom/mirroring_service.mojom
+++ b/chromium/components/mirroring/mojom/mirroring_service.mojom
@@ -8,7 +8,7 @@ import "components/mirroring/mojom/cast_message_channel.mojom";
import "components/mirroring/mojom/resource_provider.mojom";
import "components/mirroring/mojom/session_observer.mojom";
import "components/mirroring/mojom/session_parameters.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
// This interface is used to control a mirroring session.
interface MirroringService {
diff --git a/chromium/components/mirroring/mojom/resource_provider.mojom b/chromium/components/mirroring/mojom/resource_provider.mojom
index 7605585ac70..69550089407 100644
--- a/chromium/components/mirroring/mojom/resource_provider.mojom
+++ b/chromium/components/mirroring/mojom/resource_provider.mojom
@@ -6,10 +6,11 @@ module mirroring.mojom;
import "media/capture/mojom/video_capture.mojom";
import "services/network/public/mojom/network_context.mojom";
-import "media/mojo/interfaces/remoting.mojom";
-import "media/mojo/interfaces/audio_data_pipe.mojom";
-import "media/mojo/interfaces/audio_input_stream.mojom";
-import "media/mojo/interfaces/audio_parameters.mojom";
+import "media/mojo/mojom/remoting.mojom";
+import "media/mojo/mojom/audio_data_pipe.mojom";
+import "media/mojo/mojom/audio_input_stream.mojom";
+import "media/mojo/mojom/audio_parameters.mojom";
+import "services/viz/public/mojom/gpu.mojom";
// This interface is used by ResourceProvider to notify that an audio input
// stream is created as requested. The lifetime of the stream is limited by the
@@ -25,8 +26,10 @@ interface AudioStreamCreatorClient {
// This interface is used by the Mirroring Service to ask the browser to provide
// resources.
interface ResourceProvider {
+ // Acquires an interface to the GPU process.
+ BindGpu(pending_receiver<viz.mojom.Gpu> receiver);
GetVideoCaptureHost(media.mojom.VideoCaptureHost& request);
- GetNetworkContext(network.mojom.NetworkContext& request);
+ GetNetworkContext(pending_receiver<network.mojom.NetworkContext> receiver);
CreateAudioStream(AudioStreamCreatorClient client,
media.mojom.AudioParameters param,
uint32 shared_memory_count);
diff --git a/chromium/components/mirroring/mojom/session_observer.mojom b/chromium/components/mirroring/mojom/session_observer.mojom
index e788def9f8a..3445aab9581 100644
--- a/chromium/components/mirroring/mojom/session_observer.mojom
+++ b/chromium/components/mirroring/mojom/session_observer.mojom
@@ -5,6 +5,9 @@
module mirroring.mojom;
// Errors occurred in a mirroring session.
+// These values are persisted to logs and are tied to
+// MirroringServiceErrorType in tools/metrics/histograms/enums.xml. Do not
+// reorder or remove entries.
enum SessionError {
ANSWER_TIME_OUT, // ANSWER timeout.
ANSWER_NOT_OK, // Not OK answer response.
diff --git a/chromium/components/mirroring/service/BUILD.gn b/chromium/components/mirroring/service/BUILD.gn
index 759ef85a464..62b48a82ae0 100644
--- a/chromium/components/mirroring/service/BUILD.gn
+++ b/chromium/components/mirroring/service/BUILD.gn
@@ -56,14 +56,13 @@ component("mirroring_service") {
"//media/gpu",
"//media/mojo/clients",
"//media/mojo/common:common",
- "//media/mojo/interfaces",
- "//media/mojo/interfaces:remoting",
+ "//media/mojo/mojom",
+ "//media/mojo/mojom:remoting",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//net",
"//services/network/public/cpp",
"//services/network/public/mojom",
- "//services/service_manager/public/cpp:cpp",
"//services/viz/public/cpp/gpu",
"//ui/base",
"//ui/gfx",
@@ -103,8 +102,8 @@ source_set("unittests") {
"//media/cast:net",
"//media/cast:sender",
"//media/cast:test_support",
- "//media/mojo/interfaces",
- "//media/mojo/interfaces:remoting",
+ "//media/mojo/mojom",
+ "//media/mojo/mojom:remoting",
"//mojo/public/cpp/bindings",
"//net",
"//services/network:test_support",
@@ -114,17 +113,3 @@ source_set("unittests") {
"//testing/gtest",
]
}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/mirroring/mojom:constants",
- "//components/mirroring/mojom:service",
- "//services/service_manager/public/cpp",
- ]
-}
diff --git a/chromium/components/mirroring/service/DEPS b/chromium/components/mirroring/service/DEPS
index a50f12e1532..07a4900ab64 100644
--- a/chromium/components/mirroring/service/DEPS
+++ b/chromium/components/mirroring/service/DEPS
@@ -9,7 +9,6 @@ include_rules = [
"+net",
"+services/network/public",
"+services/network/test",
- "+services/service_manager",
"+services/viz/public",
"+ui/base",
]
diff --git a/chromium/components/mirroring/service/captured_audio_input.cc b/chromium/components/mirroring/service/captured_audio_input.cc
index c86349925ed..7137fc5fccd 100644
--- a/chromium/components/mirroring/service/captured_audio_input.cc
+++ b/chromium/components/mirroring/service/captured_audio_input.cc
@@ -5,7 +5,7 @@
#include "components/mirroring/service/captured_audio_input.h"
#include "base/logging.h"
-#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
+#include "media/mojo/mojom/audio_data_pipe.mojom.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace mirroring {
diff --git a/chromium/components/mirroring/service/captured_audio_input.h b/chromium/components/mirroring/service/captured_audio_input.h
index cf4441c9140..b0f79aa9b4d 100644
--- a/chromium/components/mirroring/service/captured_audio_input.h
+++ b/chromium/components/mirroring/service/captured_audio_input.h
@@ -11,7 +11,7 @@
#include "base/sequence_checker.h"
#include "components/mirroring/mojom/resource_provider.mojom.h"
#include "media/audio/audio_input_ipc.h"
-#include "media/mojo/interfaces/audio_input_stream.mojom.h"
+#include "media/mojo/mojom/audio_input_stream.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace mirroring {
diff --git a/chromium/components/mirroring/service/captured_audio_input_unittest.cc b/chromium/components/mirroring/service/captured_audio_input_unittest.cc
index 59541baa651..888078e31b2 100644
--- a/chromium/components/mirroring/service/captured_audio_input_unittest.cc
+++ b/chromium/components/mirroring/service/captured_audio_input_unittest.cc
@@ -7,9 +7,9 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "media/base/audio_parameters.h"
-#include "media/mojo/interfaces/audio_data_pipe.mojom.h"
+#include "media/mojo/mojom/audio_data_pipe.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/buffer.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -51,9 +51,7 @@ class CapturedAudioInputTest : public ::testing::Test {
public:
CapturedAudioInputTest() {}
- ~CapturedAudioInputTest() override {
- scoped_task_environment_.RunUntilIdle();
- }
+ ~CapturedAudioInputTest() override { task_environment_.RunUntilIdle(); }
void CreateMockStream(bool initially_muted,
mojom::AudioStreamCreatorClientPtr client,
@@ -91,7 +89,7 @@ class CapturedAudioInputTest : public ::testing::Test {
void CloseStream() {
EXPECT_TRUE(audio_input_);
audio_input_->CloseStream();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
socket_.Close();
audio_input_.reset();
stream_ = nullptr;
@@ -134,7 +132,7 @@ class CapturedAudioInputTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<media::AudioInputIPC> audio_input_;
MockDelegate delegate_;
MockStream* stream_ = nullptr;
diff --git a/chromium/components/mirroring/service/fake_network_service.cc b/chromium/components/mirroring/service/fake_network_service.cc
index 971a350aef8..d6b36d042c0 100644
--- a/chromium/components/mirroring/service/fake_network_service.cc
+++ b/chromium/components/mirroring/service/fake_network_service.cc
@@ -11,8 +11,8 @@
namespace mirroring {
MockUdpSocket::MockUdpSocket(network::mojom::UDPSocketRequest request,
- network::mojom::UDPSocketReceiverPtr receiver)
- : binding_(this, std::move(request)), receiver_(std::move(receiver)) {}
+ network::mojom::UDPSocketListenerPtr listener)
+ : binding_(this, std::move(request)), listener_(std::move(listener)) {}
MockUdpSocket::~MockUdpSocket() {}
@@ -38,7 +38,7 @@ void MockUdpSocket::Send(
void MockUdpSocket::OnReceivedPacket(const media::cast::Packet& packet) {
if (num_ask_for_receive_) {
- receiver_->OnReceived(
+ listener_->OnReceived(
net::OK, base::nullopt,
base::span<const uint8_t>(
reinterpret_cast<const uint8_t*>(packet.data()), packet.size()));
@@ -53,15 +53,15 @@ void MockUdpSocket::VerifySendingPacket(const media::cast::Packet& packet) {
}
MockNetworkContext::MockNetworkContext(
- network::mojom::NetworkContextRequest request)
- : binding_(this, std::move(request)) {}
+ mojo::PendingReceiver<network::mojom::NetworkContext> receiver)
+ : receiver_(this, std::move(receiver)) {}
MockNetworkContext::~MockNetworkContext() {}
void MockNetworkContext::CreateUDPSocket(
network::mojom::UDPSocketRequest request,
- network::mojom::UDPSocketReceiverPtr receiver) {
+ network::mojom::UDPSocketListenerPtr listener) {
udp_socket_ =
- std::make_unique<MockUdpSocket>(std::move(request), std::move(receiver));
+ std::make_unique<MockUdpSocket>(std::move(request), std::move(listener));
OnUDPSocketCreated();
}
diff --git a/chromium/components/mirroring/service/fake_network_service.h b/chromium/components/mirroring/service/fake_network_service.h
index 36bc4d33375..9d999ee6d5d 100644
--- a/chromium/components/mirroring/service/fake_network_service.h
+++ b/chromium/components/mirroring/service/fake_network_service.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "media/cast/net/cast_transport_defines.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/test/test_network_context.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -18,7 +19,7 @@ namespace mirroring {
class MockUdpSocket final : public network::mojom::UDPSocket {
public:
MockUdpSocket(network::mojom::UDPSocketRequest request,
- network::mojom::UDPSocketReceiverPtr receiver);
+ network::mojom::UDPSocketListenerPtr listener);
~MockUdpSocket() override;
MOCK_METHOD0(OnSend, void());
@@ -58,7 +59,7 @@ class MockUdpSocket final : public network::mojom::UDPSocket {
private:
mojo::Binding<network::mojom::UDPSocket> binding_;
- network::mojom::UDPSocketReceiverPtr receiver_;
+ network::mojom::UDPSocketListenerPtr listener_;
std::unique_ptr<media::cast::Packet> sending_packet_;
int num_ask_for_receive_ = 0;
@@ -67,14 +68,15 @@ class MockUdpSocket final : public network::mojom::UDPSocket {
class MockNetworkContext final : public network::TestNetworkContext {
public:
- explicit MockNetworkContext(network::mojom::NetworkContextRequest request);
+ explicit MockNetworkContext(
+ mojo::PendingReceiver<network::mojom::NetworkContext> receiver);
~MockNetworkContext() override;
MOCK_METHOD0(OnUDPSocketCreated, void());
// network::mojom::NetworkContext implementation:
void CreateUDPSocket(network::mojom::UDPSocketRequest request,
- network::mojom::UDPSocketReceiverPtr receiver) override;
+ network::mojom::UDPSocketListenerPtr listener) override;
void CreateURLLoaderFactory(
network::mojom::URLLoaderFactoryRequest request,
network::mojom::URLLoaderFactoryParamsPtr params) override;
@@ -82,7 +84,7 @@ class MockNetworkContext final : public network::TestNetworkContext {
MockUdpSocket* udp_socket() const { return udp_socket_.get(); }
private:
- mojo::Binding<network::mojom::NetworkContext> binding_;
+ mojo::Receiver<network::mojom::NetworkContext> receiver_;
std::unique_ptr<MockUdpSocket> udp_socket_;
DISALLOW_COPY_AND_ASSIGN(MockNetworkContext);
};
diff --git a/chromium/components/mirroring/service/fake_video_capture_host.cc b/chromium/components/mirroring/service/fake_video_capture_host.cc
index afb423d1a74..c1535185e4a 100644
--- a/chromium/components/mirroring/service/fake_video_capture_host.cc
+++ b/chromium/components/mirroring/service/fake_video_capture_host.cc
@@ -17,8 +17,8 @@ FakeVideoCaptureHost::FakeVideoCaptureHost(
FakeVideoCaptureHost::~FakeVideoCaptureHost() {}
void FakeVideoCaptureHost::Start(
- int32_t device_id,
- int32_t session_id,
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
const media::VideoCaptureParams& params,
media::mojom::VideoCaptureObserverPtr observer) {
ASSERT_TRUE(observer);
@@ -26,7 +26,7 @@ void FakeVideoCaptureHost::Start(
observer_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
}
-void FakeVideoCaptureHost::Stop(int32_t device_id) {
+void FakeVideoCaptureHost::Stop(const base::UnguessableToken& device_id) {
if (!observer_)
return;
diff --git a/chromium/components/mirroring/service/fake_video_capture_host.h b/chromium/components/mirroring/service/fake_video_capture_host.h
index 179a30f2e90..b9bba15bb4b 100644
--- a/chromium/components/mirroring/service/fake_video_capture_host.h
+++ b/chromium/components/mirroring/service/fake_video_capture_host.h
@@ -20,28 +20,32 @@ class FakeVideoCaptureHost final : public media::mojom::VideoCaptureHost {
~FakeVideoCaptureHost() override;
// mojom::VideoCaptureHost implementations
- MOCK_METHOD1(RequestRefreshFrame, void(int32_t));
- MOCK_METHOD3(ReleaseBuffer, void(int32_t, int32_t, double));
- MOCK_METHOD1(Pause, void(int32_t));
+ MOCK_METHOD1(RequestRefreshFrame, void(const base::UnguessableToken&));
+ MOCK_METHOD3(ReleaseBuffer,
+ void(const base::UnguessableToken&, int32_t, double));
+ MOCK_METHOD1(Pause, void(const base::UnguessableToken&));
MOCK_METHOD3(Resume,
- void(int32_t, int32_t, const media::VideoCaptureParams&));
+ void(const base::UnguessableToken&,
+ const base::UnguessableToken&,
+ const media::VideoCaptureParams&));
MOCK_METHOD0(OnStopped, void());
- MOCK_METHOD2(OnLog, void(int32_t, const std::string&));
+ MOCK_METHOD2(OnLog, void(const base::UnguessableToken&, const std::string&));
MOCK_METHOD2(OnFrameDropped,
- void(int32_t, media::VideoCaptureFrameDropReason));
+ void(const base::UnguessableToken&,
+ media::VideoCaptureFrameDropReason));
- void Start(int32_t device_id,
- int32_t session_id,
+ void Start(const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
const media::VideoCaptureParams& params,
media::mojom::VideoCaptureObserverPtr observer) override;
- void Stop(int32_t device_id) override;
+ void Stop(const base::UnguessableToken& device_id) override;
void GetDeviceSupportedFormats(
- int32_t device_id,
- int32_t session_id,
+ const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
GetDeviceSupportedFormatsCallback callback) override {}
- void GetDeviceFormatsInUse(int32_t device_id,
- int32_t session_id,
+ void GetDeviceFormatsInUse(const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
GetDeviceFormatsInUseCallback callback) override {}
// Create one video frame and send it to |observer_|.
diff --git a/chromium/components/mirroring/service/manifest.cc b/chromium/components/mirroring/service/manifest.cc
deleted file mode 100644
index 4218df7f487..00000000000
--- a/chromium/components/mirroring/service/manifest.cc
+++ /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.
-
-#include "components/mirroring/service/manifest.h"
-
-#include "base/no_destructor.h"
-#include "components/mirroring/mojom/constants.mojom.h"
-#include "components/mirroring/mojom/mirroring_service.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace mirroring {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName("Mirroring Service")
- .WithOptions(
- service_manager::ManifestOptionsBuilder()
- .WithExecutionMode(service_manager::Manifest::ExecutionMode::
- kOutOfProcessBuiltin)
- .WithSandboxType("utility")
- .Build())
- .ExposeCapability("mirroring",
- service_manager::Manifest::InterfaceList<
- mojom::MirroringService>())
- .RequireCapability("content_system", "gpu_client")
- .RequireCapability("ui", "gpu_client")
-
- .Build()};
- return *manifest;
-}
-
-} // namespace mirroring
diff --git a/chromium/components/mirroring/service/manifest.h b/chromium/components/mirroring/service/manifest.h
deleted file mode 100644
index 26022af19e1..00000000000
--- a/chromium/components/mirroring/service/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_MIRRORING_SERVICE_MANIFEST_H_
-#define COMPONENTS_MIRRORING_SERVICE_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace mirroring {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace mirroring
-
-#endif // COMPONENTS_MIRRORING_SERVICE_MANIFEST_H_
diff --git a/chromium/components/mirroring/service/media_remoter.h b/chromium/components/mirroring/service/media_remoter.h
index 3546a294ada..dbedaa5f39f 100644
--- a/chromium/components/mirroring/service/media_remoter.h
+++ b/chromium/components/mirroring/service/media_remoter.h
@@ -8,8 +8,8 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "media/cast/cast_config.h"
-#include "media/mojo/interfaces/remoting.mojom.h"
-#include "media/mojo/interfaces/remoting_common.mojom.h"
+#include "media/mojo/mojom/remoting.mojom.h"
+#include "media/mojo/mojom/remoting_common.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace media {
diff --git a/chromium/components/mirroring/service/media_remoter_unittest.cc b/chromium/components/mirroring/service/media_remoter_unittest.cc
index 4d58946a388..d6ddf875416 100644
--- a/chromium/components/mirroring/service/media_remoter_unittest.cc
+++ b/chromium/components/mirroring/service/media_remoter_unittest.cc
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_tick_clock.h"
#include "components/mirroring/service/message_dispatcher.h"
#include "components/mirroring/service/mirror_settings.h"
@@ -74,7 +74,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
mojo::MakeRequest(&inbound_channel_),
error_callback_.Get()),
sink_metadata_(DefaultSinkMetadata()) {}
- ~MediaRemoterTest() override { scoped_task_environment_.RunUntilIdle(); }
+ ~MediaRemoterTest() override { task_environment_.RunUntilIdle(); }
protected:
MOCK_METHOD1(Send, void(mojom::CastMessagePtr));
@@ -97,7 +97,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
EXPECT_CALL(remoting_source_, OnSinkAvailable(_)).Times(1);
media_remoter_ = std::make_unique<MediaRemoter>(this, sink_metadata_,
&message_dispatcher_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
}
@@ -107,7 +107,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
ASSERT_TRUE(remoter_);
EXPECT_CALL(*this, RequestRemotingStreaming()).Times(1);
remoter_->Start();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
}
@@ -119,7 +119,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
EXPECT_CALL(remoting_source_, OnSinkGone()).Times(1);
EXPECT_CALL(*this, RestartMirroringStreaming()).Times(1);
remoter_->Stop(media::mojom::RemotingStopReason::USER_DISABLED);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
}
@@ -130,15 +130,15 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
scoped_refptr<media::cast::CastEnvironment> cast_environment =
new media::cast::CastEnvironment(
base::DefaultTickClock::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner());
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner());
EXPECT_CALL(remoting_source_, OnStarted()).Times(1);
media_remoter_->StartRpcMessaging(
cast_environment, nullptr, media::cast::FrameSenderConfig(),
MirrorSettings::GetDefaultVideoConfig(RtpPayloadType::REMOTE_VIDEO,
Codec::CODEC_VIDEO_REMOTE));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(&remoting_source_);
}
@@ -146,7 +146,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
void MirroringResumed() {
EXPECT_CALL(remoting_source_, OnSinkAvailable(_)).Times(1);
media_remoter_->OnMirroringResumed();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(&remoting_source_);
}
@@ -157,7 +157,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
EXPECT_CALL(remoting_source_, OnSinkGone()).Times(1);
EXPECT_CALL(*this, RestartMirroringStreaming()).Times(1);
media_remoter_->OnRemotingFailed();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
}
@@ -169,7 +169,7 @@ class MediaRemoterTest : public mojom::CastMessageChannel,
return outbound_channel_ptr;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
mojo::Binding<mojom::CastMessageChannel> binding_;
base::MockCallback<MessageDispatcher::ErrorCallback> error_callback_;
mojom::CastMessageChannelPtr inbound_channel_;
diff --git a/chromium/components/mirroring/service/message_dispatcher_unittest.cc b/chromium/components/mirroring/service/message_dispatcher_unittest.cc
index 62c19d6ef5c..a4b44447f56 100644
--- a/chromium/components/mirroring/service/message_dispatcher_unittest.cc
+++ b/chromium/components/mirroring/service/message_dispatcher_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -73,7 +73,7 @@ class MessageDispatcherTest : public mojom::CastMessageChannel,
base::BindRepeating(&MessageDispatcherTest::OnStatusResponse,
base::Unretained(this)));
}
- ~MessageDispatcherTest() override { scoped_task_environment_.RunUntilIdle(); }
+ ~MessageDispatcherTest() override { task_environment_.RunUntilIdle(); }
void OnParsingError(const std::string& error_message) {
last_error_message_ = error_message;
@@ -103,7 +103,7 @@ class MessageDispatcherTest : public mojom::CastMessageChannel,
inbound_channel_->Send(message.Clone());
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<MessageDispatcher> message_dispatcher_;
CastMessage last_outbound_message_;
std::string last_error_message_;
@@ -120,14 +120,14 @@ TEST_F(MessageDispatcherTest, SendsOutboundMessage) {
const std::string test1 = "{\"a\": 1, \"b\": 2}";
const CastMessage message1 = CastMessage{mojom::kWebRtcNamespace, test1};
message_dispatcher_->SendOutboundMessage(message1.Clone());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(IsEqual(message1, last_outbound_message_));
EXPECT_TRUE(last_error_message_.empty());
const std::string test2 = "{\"m\": 99, \"i\": 98, \"u\": 97}";
const CastMessage message2 = CastMessage{mojom::kWebRtcNamespace, test2};
message_dispatcher_->SendOutboundMessage(message2.Clone());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(IsEqual(message2, last_outbound_message_));
EXPECT_TRUE(last_error_message_.empty());
}
@@ -141,7 +141,7 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
const CastMessage answer_message =
CastMessage{mojom::kWebRtcNamespace, answer_response};
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_EQ(12345, last_answer_response_->sequence_number);
@@ -160,7 +160,7 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
const CastMessage status_message =
CastMessage{mojom::kWebRtcNamespace, status_response};
SendInboundMessage(status_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
ASSERT_TRUE(last_status_response_);
EXPECT_EQ(12345, last_status_response_->sequence_number);
@@ -174,7 +174,7 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
// nothing should happen.
message_dispatcher_->Unsubscribe(ResponseType::ANSWER);
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_FALSE(last_error_message_.empty()); // Expect an error reported.
@@ -183,7 +183,7 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
// However, STATUS_RESPONSE messages should still be dispatcher to the
// remaining subscriber.
SendInboundMessage(status_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_TRUE(last_status_response_);
last_status_response_.reset();
@@ -193,13 +193,13 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
// either an ANSWER or a STATUS_RESPONSE message, nothing should happen.
message_dispatcher_->Unsubscribe(ResponseType::STATUS_RESPONSE);
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_FALSE(last_error_message_.empty());
last_error_message_.clear();
SendInboundMessage(status_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_FALSE(last_error_message_.empty());
@@ -209,7 +209,7 @@ TEST_F(MessageDispatcherTest, IgnoreMalformedMessage) {
const CastMessage message =
CastMessage{mojom::kWebRtcNamespace, "MUAHAHAHAHAHAHAHA!"};
SendInboundMessage(message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_FALSE(last_error_message_.empty());
@@ -222,7 +222,7 @@ TEST_F(MessageDispatcherTest, IgnoreMessageWithWrongNamespace) {
const CastMessage answer_message =
CastMessage{"Wrong_namespace", answer_response};
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
// Messages with different namespace are ignored with no error reported.
@@ -233,7 +233,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
message_dispatcher_->Unsubscribe(ResponseType::ANSWER);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
const std::string fake_offer = "{\"type\":\"OFFER\",\"seqNum\":45623}";
const CastMessage offer_message =
CastMessage{mojom::kWebRtcNamespace, fake_offer};
@@ -242,7 +242,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
base::TimeDelta::FromMilliseconds(100),
base::BindRepeating(&MessageDispatcherTest::OnAnswerResponse,
base::Unretained(this)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Received the request to send the outbound message.
EXPECT_TRUE(IsEqual(offer_message, last_outbound_message_));
@@ -252,7 +252,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
CastMessage answer_message =
CastMessage{mojom::kWebRtcNamespace, answer_response};
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// The answer message with mismatched sequence number is ignored.
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
@@ -263,7 +263,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
"\"answer\":{\"udpPort\":50691}}";
answer_message = CastMessage{mojom::kWebRtcNamespace, answer_response};
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_TRUE(last_error_message_.empty());
@@ -275,7 +275,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
// Expect that the callback for ANSWER message was already unsubscribed.
SendInboundMessage(answer_message);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
EXPECT_FALSE(last_error_message_.empty());
@@ -288,7 +288,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
base::TimeDelta::FromMilliseconds(100),
base::BindRepeating(&MessageDispatcherTest::OnAnswerResponse,
base::Unretained(this)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Received the request to send the outbound message.
EXPECT_TRUE(IsEqual(fake_message, last_outbound_message_));
EXPECT_FALSE(last_answer_response_);
@@ -296,7 +296,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
// Destroy the dispatcher.
message_dispatcher_.reset();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(last_answer_response_);
EXPECT_FALSE(last_status_response_);
}
diff --git a/chromium/components/mirroring/service/mirror_settings.cc b/chromium/components/mirroring/service/mirror_settings.cc
index 14f337dd974..b0392f8901f 100644
--- a/chromium/components/mirroring/service/mirror_settings.cc
+++ b/chromium/components/mirroring/service/mirror_settings.cc
@@ -8,10 +8,10 @@
#include "media/base/audio_parameters.h"
-using media::cast::FrameSenderConfig;
+using media::ResolutionChangePolicy;
using media::cast::Codec;
+using media::cast::FrameSenderConfig;
using media::cast::RtpPayloadType;
-using media::ResolutionChangePolicy;
namespace mirroring {
@@ -108,8 +108,7 @@ media::VideoCaptureParams MirrorSettings::GetVideoCaptureParams() {
kMaxFrameRate, media::PIXEL_FORMAT_I420);
if (max_height_ == min_height_ && max_width_ == min_width_) {
params.resolution_change_policy = ResolutionChangePolicy::FIXED_RESOLUTION;
- } else if ((100 * min_width_ / min_height_) ==
- (100 * max_width_ / max_height_)) {
+ } else if (enable_sender_side_letterboxing_) {
params.resolution_change_policy =
ResolutionChangePolicy::FIXED_ASPECT_RATIO;
} else {
@@ -133,7 +132,8 @@ base::Value MirrorSettings::ToDictionaryValue() {
settings.SetKey("maxHeight", base::Value(max_height_));
settings.SetKey("minWidth", base::Value(min_width_));
settings.SetKey("minHeight", base::Value(min_height_));
- settings.SetKey("senderSideLetterboxing", base::Value(true));
+ settings.SetKey("senderSideLetterboxing",
+ base::Value(enable_sender_side_letterboxing_));
settings.SetKey("minFrameRate", base::Value(0));
settings.SetKey("maxFrameRate", base::Value(kMaxFrameRate));
settings.SetKey("minVideoBitrate", base::Value(kMinVideoBitrate));
diff --git a/chromium/components/mirroring/service/mirror_settings.h b/chromium/components/mirroring/service/mirror_settings.h
index 11c96c668c1..ea19ec79f32 100644
--- a/chromium/components/mirroring/service/mirror_settings.h
+++ b/chromium/components/mirroring/service/mirror_settings.h
@@ -57,6 +57,10 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) MirrorSettings {
int max_width_;
int max_height_;
+ // TODO(crbug.com/1002603): Disable sender-side letterboxing for Chromecast
+ // devices that support arbitrary aspect ratios.
+ bool enable_sender_side_letterboxing_ = true;
+
DISALLOW_COPY_AND_ASSIGN(MirrorSettings);
};
diff --git a/chromium/components/mirroring/service/mirroring_service.cc b/chromium/components/mirroring/service/mirroring_service.cc
index 168c3fedb3c..110a723d69c 100644
--- a/chromium/components/mirroring/service/mirroring_service.cc
+++ b/chromium/components/mirroring/service/mirroring_service.cc
@@ -12,41 +12,12 @@
namespace mirroring {
MirroringService::MirroringService(
- service_manager::mojom::ServiceRequest request,
+ mojo::PendingReceiver<mojom::MirroringService> receiver,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : service_binding_(this, std::move(request)),
- service_keepalive_(&service_binding_, base::TimeDelta()),
- io_task_runner_(std::move(io_task_runner)) {
- registry_.AddInterface<mojom::MirroringService>(
- base::BindRepeating(&MirroringService::Create, base::Unretained(this)));
-}
-
-MirroringService::~MirroringService() {
- session_.reset();
- registry_.RemoveInterface<mojom::MirroringService>();
-}
-
-void MirroringService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
-}
-
-bool MirroringService::OnServiceManagerConnectionLost() {
- bindings_.CloseAllBindings();
- return true;
-}
+ : receiver_(this, std::move(receiver)),
+ io_task_runner_(std::move(io_task_runner)) {}
-void MirroringService::Create(mojom::MirroringServiceRequest request) {
- bindings_.AddBinding(this, std::move(request));
- bindings_.set_connection_error_handler(base::BindRepeating(
- [](MirroringService* service) {
- service->session_.reset();
- service->bindings_.CloseAllBindings();
- },
- this));
-}
+MirroringService::~MirroringService() = default;
void MirroringService::Start(mojom::SessionParametersPtr params,
const gfx::Size& max_resolution,
@@ -55,15 +26,10 @@ void MirroringService::Start(mojom::SessionParametersPtr params,
mojom::CastMessageChannelPtr outbound_channel,
mojom::CastMessageChannelRequest inbound_channel) {
session_.reset(); // Stops the current session if active.
- std::unique_ptr<viz::Gpu> gpu;
- if (params->type != mojom::SessionType::AUDIO_ONLY) {
- gpu = viz::Gpu::Create(service_binding_.GetConnector(), "content_system",
- io_task_runner_);
- }
session_ = std::make_unique<Session>(
std::move(params), max_resolution, std::move(observer),
std::move(resource_provider), std::move(outbound_channel),
- std::move(inbound_channel), std::move(gpu));
+ std::move(inbound_channel), io_task_runner_);
}
} // namespace mirroring
diff --git a/chromium/components/mirroring/service/mirroring_service.h b/chromium/components/mirroring/service/mirroring_service.h
index aa39f12d825..6a59bcff1c2 100644
--- a/chromium/components/mirroring/service/mirroring_service.h
+++ b/chromium/components/mirroring/service/mirroring_service.h
@@ -8,35 +8,21 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "components/mirroring/mojom/mirroring_service.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
namespace mirroring {
class Session;
class COMPONENT_EXPORT(MIRRORING_SERVICE) MirroringService final
- : public service_manager::Service,
- public mojom::MirroringService {
+ : public mojom::MirroringService {
public:
- MirroringService(service_manager::mojom::ServiceRequest request,
+ MirroringService(mojo::PendingReceiver<mojom::MirroringService> receiver,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~MirroringService() override;
private:
- // service_manager::Service implementation.
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
- bool OnServiceManagerConnectionLost() override;
-
- // Handles the request to connect to this service.
- void Create(mojom::MirroringServiceRequest request);
-
// mojom::MirroringService implementation.
void Start(mojom::SessionParametersPtr params,
const gfx::Size& max_resolution,
@@ -45,12 +31,8 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) MirroringService final
mojom::CastMessageChannelPtr outbound_channel,
mojom::CastMessageChannelRequest inbound_channel) override;
- service_manager::ServiceBinding service_binding_;
- service_manager::ServiceKeepalive service_keepalive_;
-
+ mojo::Receiver<mojom::MirroringService> receiver_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- service_manager::BinderRegistry registry_;
- mojo::BindingSet<mojom::MirroringService> bindings_;
std::unique_ptr<Session> session_; // Current mirroring session.
DISALLOW_COPY_AND_ASSIGN(MirroringService);
diff --git a/chromium/components/mirroring/service/remoting_sender.h b/chromium/components/mirroring/service/remoting_sender.h
index 2912022be64..ec027ed01d4 100644
--- a/chromium/components/mirroring/service/remoting_sender.h
+++ b/chromium/components/mirroring/service/remoting_sender.h
@@ -14,7 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "media/cast/sender/frame_sender.h"
-#include "media/mojo/interfaces/remoting.mojom.h"
+#include "media/mojo/mojom/remoting.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace base {
diff --git a/chromium/components/mirroring/service/remoting_sender_unittest.cc b/chromium/components/mirroring/service/remoting_sender_unittest.cc
index 93d97f08b5a..2c0ab3a678f 100644
--- a/chromium/components/mirroring/service/remoting_sender_unittest.cc
+++ b/chromium/components/mirroring/service/remoting_sender_unittest.cc
@@ -11,12 +11,12 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_tick_clock.h"
#include "media/cast/constants.h"
#include "media/cast/net/cast_transport.h"
#include "media/cast/test/utility/default_config.h"
-#include "media/mojo/interfaces/remoting.mojom.h"
+#include "media/mojo/mojom/remoting.mojom.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -107,9 +107,9 @@ class RemotingSenderTest : public ::testing::Test {
RemotingSenderTest()
: cast_environment_(new media::cast::CastEnvironment(
base::DefaultTickClock::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner())),
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner())),
expecting_error_callback_run_(false),
receiver_ssrc_(-1) {
const MojoCreateDataPipeOptions data_pipe_options{
@@ -150,7 +150,7 @@ class RemotingSenderTest : public ::testing::Test {
}
// Allow pending tasks, such as Mojo method calls, to execute.
- void RunPendingTasks() { scoped_task_environment_.RunUntilIdle(); }
+ void RunPendingTasks() { task_environment_.RunUntilIdle(); }
protected:
media::cast::FrameId latest_acked_frame_id() const {
@@ -250,7 +250,7 @@ class RemotingSenderTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
const scoped_refptr<media::cast::CastEnvironment> cast_environment_;
FakeTransport transport_;
std::unique_ptr<RemotingSender> remoting_sender_;
diff --git a/chromium/components/mirroring/service/rtp_stream_unittest.cc b/chromium/components/mirroring/service/rtp_stream_unittest.cc
index b3b9bbea3d5..d8321aa78d9 100644
--- a/chromium/components/mirroring/service/rtp_stream_unittest.cc
+++ b/chromium/components/mirroring/service/rtp_stream_unittest.cc
@@ -7,8 +7,8 @@
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_tick_clock.h"
+#include "base/test/task_environment.h"
#include "media/base/video_frame.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_environment.h"
@@ -61,16 +61,16 @@ class RtpStreamTest : public ::testing::Test {
RtpStreamTest()
: cast_environment_(new media::cast::CastEnvironment(
&testing_clock_,
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner())) {
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner())) {
testing_clock_.Advance(base::TimeTicks::Now() - base::TimeTicks());
}
- ~RtpStreamTest() override { scoped_task_environment_.RunUntilIdle(); }
+ ~RtpStreamTest() override { task_environment_.RunUntilIdle(); }
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::SimpleTestTickClock testing_clock_;
const scoped_refptr<media::cast::CastEnvironment> cast_environment_;
DummyClient client_;
@@ -105,7 +105,7 @@ TEST_F(RtpStreamTest, VideoStreaming) {
run_loop.Run();
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// Test the audio streaming pipeline.
@@ -131,7 +131,7 @@ TEST_F(RtpStreamTest, AudioStreaming) {
run_loop.Run();
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
} // namespace mirroring
diff --git a/chromium/components/mirroring/service/session.cc b/chromium/components/mirroring/service/session.cc
index 0e7a5147885..3a93e2fef27 100644
--- a/chromium/components/mirroring/service/session.cc
+++ b/chromium/components/mirroring/service/session.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/json/json_writer.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"
@@ -39,6 +40,7 @@
#include "media/gpu/gpu_video_accelerator_util.h"
#include "media/mojo/clients/mojo_video_encode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
+#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "net/base/ip_endpoint.h"
@@ -377,7 +379,7 @@ Session::Session(mojom::SessionParametersPtr session_params,
mojom::ResourceProviderPtr resource_provider,
mojom::CastMessageChannelPtr outbound_channel,
mojom::CastMessageChannelRequest inbound_channel,
- std::unique_ptr<viz::Gpu> gpu)
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: session_params_(*session_params),
state_(MIRRORING),
observer_(std::move(observer)),
@@ -386,13 +388,19 @@ Session::Session(mojom::SessionParametersPtr session_params,
std::move(inbound_channel),
base::BindRepeating(&Session::OnResponseParsingError,
base::Unretained(this))),
- gpu_(std::move(gpu)),
gpu_channel_host_(nullptr) {
DCHECK(resource_provider_);
mirror_settings_.SetResolutionContraints(max_resolution.width(),
max_resolution.height());
resource_provider_->GetNetworkContext(mojo::MakeRequest(&network_context_));
+ if (session_params->type != mojom::SessionType::AUDIO_ONLY &&
+ io_task_runner) {
+ mojo::PendingRemote<viz::mojom::Gpu> remote_gpu;
+ resource_provider_->BindGpu(remote_gpu.InitWithNewPipeAndPassReceiver());
+ gpu_ = viz::Gpu::Create(std::move(remote_gpu), io_task_runner);
+ }
+
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
params->process_id = network::mojom::kBrowserProcessId;
@@ -441,6 +449,7 @@ Session::~Session() {
}
void Session::ReportError(SessionError error) {
+ UMA_HISTOGRAM_ENUMERATION("MediaRouter.MirroringService.SessionError", error);
if (session_monitor_.has_value())
session_monitor_->OnStreamingError(error);
if (state_ == REMOTING) {
@@ -544,7 +553,7 @@ void Session::CreateVideoEncodeAccelerator(
mojo_vea.reset(new media::MojoVideoEncodeAccelerator(std::move(vea),
supported_profiles_));
}
- callback.Run(video_encode_thread_, std::move(mojo_vea));
+ callback.Run(base::ThreadTaskRunnerHandle::Get(), std::move(mojo_vea));
}
void Session::CreateVideoEncodeMemory(
@@ -552,23 +561,13 @@ void Session::CreateVideoEncodeMemory(
const media::cast::ReceiveVideoEncodeMemoryCallback& callback) {
DVLOG(1) << __func__;
- mojo::ScopedSharedBufferHandle mojo_buf =
- mojo::SharedBufferHandle::Create(size);
- if (!mojo_buf->is_valid()) {
- LOG(WARNING) << "Browser failed to allocate shared memory.";
- callback.Run(nullptr);
- return;
- }
+ base::UnsafeSharedMemoryRegion buf =
+ mojo::CreateUnsafeSharedMemoryRegion(size);
- base::SharedMemoryHandle shared_buf;
- if (mojo::UnwrapSharedMemoryHandle(std::move(mojo_buf), &shared_buf, nullptr,
- nullptr) != MOJO_RESULT_OK) {
+ if (!buf.IsValid())
LOG(WARNING) << "Browser failed to allocate shared memory.";
- callback.Run(nullptr);
- return;
- }
- callback.Run(std::make_unique<base::SharedMemory>(shared_buf, false));
+ callback.Run(std::move(buf));
}
void Session::OnTransportStatusChanged(CastTransportStatus status) {
@@ -667,12 +666,12 @@ void Session::OnAnswer(const std::vector<FrameSenderConfig>& audio_configs,
const bool initially_starting_session =
!audio_encode_thread_ && !video_encode_thread_;
if (initially_starting_session) {
- audio_encode_thread_ = base::CreateSingleThreadTaskRunnerWithTraits(
- {base::TaskPriority::USER_BLOCKING,
+ audio_encode_thread_ = base::CreateSingleThreadTaskRunner(
+ {base::ThreadPool(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::SingleThreadTaskRunnerThreadMode::DEDICATED);
- video_encode_thread_ = base::CreateSingleThreadTaskRunnerWithTraits(
- {base::TaskPriority::USER_BLOCKING,
+ video_encode_thread_ = base::CreateSingleThreadTaskRunner(
+ {base::ThreadPool(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::SingleThreadTaskRunnerThreadMode::DEDICATED);
}
diff --git a/chromium/components/mirroring/service/session.h b/chromium/components/mirroring/service/session.h
index a281fb9b77a..b6a6a5585d1 100644
--- a/chromium/components/mirroring/service/session.h
+++ b/chromium/components/mirroring/service/session.h
@@ -22,7 +22,7 @@
#include "gpu/config/gpu_info.h"
#include "media/cast/cast_environment.h"
#include "media/cast/net/cast_transport_defines.h"
-#include "media/mojo/interfaces/video_encode_accelerator.mojom.h"
+#include "media/mojo/mojom/video_encode_accelerator.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace media {
@@ -63,7 +63,7 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) Session final
mojom::ResourceProviderPtr resource_provider,
mojom::CastMessageChannelPtr outbound_channel,
mojom::CastMessageChannelRequest inbound_channel,
- std::unique_ptr<viz::Gpu> gpu);
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~Session() override;
diff --git a/chromium/components/mirroring/service/session_monitor_unittest.cc b/chromium/components/mirroring/service/session_monitor_unittest.cc
index 29fcd700a1f..12487a3c0c4 100644
--- a/chromium/components/mirroring/service/session_monitor_unittest.cc
+++ b/chromium/components/mirroring/service/session_monitor_unittest.cc
@@ -10,7 +10,7 @@
#include "base/json/json_writer.h"
#include "base/macros.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_tick_clock.h"
#include "components/mirroring/service/message_dispatcher.h"
#include "components/mirroring/service/mirror_settings.h"
@@ -142,37 +142,37 @@ class SessionMonitorTest : public mojom::CastMessageChannel,
"\"wifiFcsError\": [12, 13, 12, 12]}" // This will be ignored.
"}";
inbound_channel_->Send(message.Clone());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
}
void StartStreamingSession() {
cast_environment_ = new media::cast::CastEnvironment(
base::DefaultTickClock::GetInstance(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner());
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner());
EXPECT_TRUE(session_monitor_);
auto wifi_status_monitor =
std::make_unique<WifiStatusMonitor>(&message_dispatcher_);
session_monitor_->StartStreamingSession(
cast_environment_, std::move(wifi_status_monitor),
SessionMonitor::AUDIO_AND_VIDEO, false /* is_remoting */);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void StopStreamingSession() {
EXPECT_TRUE(session_monitor_);
session_monitor_->StopStreamingSession();
cast_environment_ = nullptr;
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
std::vector<SessionMonitor::EventsAndStats> AssembleBundleAndVerify(
const std::vector<int32_t>& bundle_sizes) {
std::vector<SessionMonitor::EventsAndStats> bundles =
session_monitor_->AssembleBundlesAndClear(bundle_sizes);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(bundle_sizes.size(), bundles.size());
for (size_t i = 0; i < bundles.size(); ++i) {
EXPECT_FALSE(bundles[i].first.empty());
@@ -197,19 +197,19 @@ class SessionMonitorTest : public mojom::CastMessageChannel,
url_loader_factory_->AddResponse(
"http://" + receiver_address_.ToString() + ":8008/setup/eureka_info",
setup_info);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void TakeSnapshot() {
ASSERT_TRUE(session_monitor_);
session_monitor_->TakeSnapshot();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void ReportError(SessionError error) {
ASSERT_TRUE(session_monitor_);
session_monitor_->OnStreamingError(error);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
private:
@@ -219,7 +219,7 @@ class SessionMonitorTest : public mojom::CastMessageChannel,
return outbound_channel_ptr;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
const net::IPAddress receiver_address_;
mojo::Binding<mojom::CastMessageChannel> binding_;
mojom::CastMessageChannelPtr inbound_channel_;
diff --git a/chromium/components/mirroring/service/session_unittest.cc b/chromium/components/mirroring/service/session_unittest.cc
index b170fea8de0..43680f87483 100644
--- a/chromium/components/mirroring/service/session_unittest.cc
+++ b/chromium/components/mirroring/service/session_unittest.cc
@@ -9,7 +9,7 @@
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/mirroring/service/fake_network_service.h"
@@ -78,7 +78,7 @@ class SessionTest : public mojom::ResourceProvider,
session_observer_binding_(this),
outbound_channel_binding_(this) {}
- ~SessionTest() override { scoped_task_environment_.RunUntilIdle(); }
+ ~SessionTest() override { task_environment_.RunUntilIdle(); }
protected:
// mojom::SessionObserver implemenation.
@@ -112,6 +112,7 @@ class SessionTest : public mojom::ResourceProvider,
}
// mojom::ResourceProvider implemenation.
+ void BindGpu(mojo::PendingReceiver<viz::mojom::Gpu> receiver) override {}
void GetVideoCaptureHost(
media::mojom::VideoCaptureHostRequest request) override {
video_host_ = std::make_unique<FakeVideoCaptureHost>(std::move(request));
@@ -119,8 +120,9 @@ class SessionTest : public mojom::ResourceProvider,
}
void GetNetworkContext(
- network::mojom::NetworkContextRequest request) override {
- network_context_ = std::make_unique<MockNetworkContext>(std::move(request));
+ mojo::PendingReceiver<network::mojom::NetworkContext> receiver) override {
+ network_context_ =
+ std::make_unique<MockNetworkContext>(std::move(receiver));
OnGetNetworkContext();
}
@@ -184,7 +186,7 @@ class SessionTest : public mojom::ResourceProvider,
response.answer = std::move(answer);
session_->OnAnswer(audio_configs, video_configs, response);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// Create a mirroring session. Expect to send OFFER message.
@@ -211,7 +213,7 @@ class SessionTest : public mojom::ResourceProvider,
std::move(session_observer_ptr), std::move(resource_provider_ptr),
std::move(outbound_channel_ptr), mojo::MakeRequest(&inbound_channel_),
nullptr);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
}
@@ -230,7 +232,7 @@ class SessionTest : public mojom::ResourceProvider,
EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(1);
EXPECT_CALL(*this, DidStart()).Times(1);
SendAnswer();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
}
@@ -239,7 +241,7 @@ class SessionTest : public mojom::ResourceProvider,
EXPECT_CALL(*video_host_, OnStopped()).Times(1);
EXPECT_CALL(*this, DidStop()).Times(1);
session_.reset();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
}
@@ -251,7 +253,7 @@ class SessionTest : public mojom::ResourceProvider,
EXPECT_CALL(*video_host_, ReleaseBuffer(_, _, _)).Times(1);
// Send one video frame to the consumer.
video_host_->SendOneFrame(gfx::Size(64, 32), base::TimeTicks::Now());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(network_context_.get());
Mock::VerifyAndClear(video_host_.get());
}
@@ -273,7 +275,7 @@ class SessionTest : public mojom::ResourceProvider,
}
session_->OnAnswer(std::vector<FrameSenderConfig>(),
std::vector<FrameSenderConfig>(), ReceiverResponse());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
cast_mode_ = "mirroring";
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
@@ -290,7 +292,7 @@ class SessionTest : public mojom::ResourceProvider,
response.capabilities->media_caps =
std::vector<std::string>({"video", "audio", "vp8", "opus"});
session_->OnCapabilitiesResponse(response);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
}
@@ -304,7 +306,7 @@ class SessionTest : public mojom::ResourceProvider,
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
remoter_->Start();
run_loop.Run();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
cast_mode_ = "remoting";
Mock::VerifyAndClear(this);
}
@@ -313,7 +315,7 @@ class SessionTest : public mojom::ResourceProvider,
ASSERT_TRUE(cast_mode_ == "remoting");
EXPECT_CALL(remoting_source_, OnStarted()).Times(1);
SendAnswer();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
}
@@ -325,14 +327,14 @@ class SessionTest : public mojom::ResourceProvider,
EXPECT_CALL(*this, OnOutboundMessage("OFFER")).Times(1);
EXPECT_CALL(remoting_source_, OnStopped(reason)).Times(1);
remoter_->Stop(reason);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
cast_mode_ = "mirroring";
Mock::VerifyAndClear(this);
Mock::VerifyAndClear(&remoting_source_);
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
const net::IPEndPoint receiver_endpoint_;
mojo::Binding<mojom::ResourceProvider> resource_provider_binding_;
mojo::Binding<mojom::SessionObserver> session_observer_binding_;
diff --git a/chromium/components/mirroring/service/udp_socket_client.cc b/chromium/components/mirroring/service/udp_socket_client.cc
index 615a57560bb..179d4e0dc3d 100644
--- a/chromium/components/mirroring/service/udp_socket_client.cc
+++ b/chromium/components/mirroring/service/udp_socket_client.cc
@@ -105,10 +105,10 @@ void UdpSocketClient::StartReceiving(
const media::cast::PacketReceiverCallbackWithStatus& packet_receiver) {
DVLOG(1) << __func__;
packet_receiver_callback_ = packet_receiver;
- network::mojom::UDPSocketReceiverPtr udp_socket_receiver;
- binding_.Bind(mojo::MakeRequest(&udp_socket_receiver));
+ network::mojom::UDPSocketListenerPtr udp_socket_listener;
+ binding_.Bind(mojo::MakeRequest(&udp_socket_listener));
network_context_->CreateUDPSocket(mojo::MakeRequest(&udp_socket_),
- std::move(udp_socket_receiver));
+ std::move(udp_socket_listener));
network::mojom::UDPSocketOptionsPtr options;
udp_socket_->Connect(remote_endpoint_, std::move(options),
base::BindOnce(&UdpSocketClient::OnSocketConnected,
diff --git a/chromium/components/mirroring/service/udp_socket_client.h b/chromium/components/mirroring/service/udp_socket_client.h
index c25c01f570b..476253d05f0 100644
--- a/chromium/components/mirroring/service/udp_socket_client.h
+++ b/chromium/components/mirroring/service/udp_socket_client.h
@@ -23,7 +23,7 @@ namespace mirroring {
// will be called if the UDPSocket is failed to be created or connected.
class COMPONENT_EXPORT(MIRRORING_SERVICE) UdpSocketClient final
: public media::cast::PacketTransport,
- public network::mojom::UDPSocketReceiver {
+ public network::mojom::UDPSocketListener {
public:
UdpSocketClient(const net::IPEndPoint& remote_endpoint,
network::mojom::NetworkContext* context,
@@ -39,7 +39,7 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) UdpSocketClient final
packet_receiver) override;
void StopReceiving() override;
- // network::mojom::UDPSocketReceiver implementation.
+ // network::mojom::UDPSocketListener implementation.
void OnReceived(int32_t result,
const base::Optional<net::IPEndPoint>& src_addr,
base::Optional<base::span<const uint8_t>> data) override;
@@ -59,7 +59,7 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) UdpSocketClient final
network::mojom::NetworkContext* const network_context_;
base::OnceClosure error_callback_;
- mojo::Binding<network::mojom::UDPSocketReceiver> binding_;
+ mojo::Binding<network::mojom::UDPSocketListener> binding_;
// The callback to deliver the received packets to the packet parser. Set
// when StartReceiving() is called.
diff --git a/chromium/components/mirroring/service/udp_socket_client_unittest.cc b/chromium/components/mirroring/service/udp_socket_client_unittest.cc
index b88f2c7adfd..623936a930b 100644
--- a/chromium/components/mirroring/service/udp_socket_client_unittest.cc
+++ b/chromium/components/mirroring/service/udp_socket_client_unittest.cc
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/mirroring/service/fake_network_service.h"
#include "media/cast/net/cast_transport_config.h"
@@ -47,7 +47,7 @@ class UdpSocketClientTest : public ::testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::mojom::NetworkContextPtr network_context_ptr_;
std::unique_ptr<MockNetworkContext> network_context_;
std::unique_ptr<UdpSocketClient> udp_transport_client_;
@@ -70,7 +70,7 @@ TEST_F(UdpSocketClientTest, SendAndReceive) {
&UdpSocketClientTest::OnReceivedPacket, base::Unretained(this)));
run_loop.Run();
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
MockUdpSocket* socket = network_context_->udp_socket();
@@ -117,7 +117,7 @@ TEST_F(UdpSocketClientTest, SendBeforeConnected) {
EXPECT_CALL(resume_send_cb, Run()).Times(0);
EXPECT_FALSE(udp_transport_client_->SendPacket(
new base::RefCountedData<Packet>(packet), resume_send_cb.Get()));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
{
// Expect the UDPSocket to be created when calling StartReceiving().
diff --git a/chromium/components/mirroring/service/video_capture_client.cc b/chromium/components/mirroring/service/video_capture_client.cc
index 6d8c8dae9ff..de07a0eba36 100644
--- a/chromium/components/mirroring/service/video_capture_client.cc
+++ b/chromium/components/mirroring/service/video_capture_client.cc
@@ -5,6 +5,7 @@
#include "components/mirroring/service/video_capture_client.h"
#include "base/bind.h"
+#include "base/no_destructor.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
@@ -12,8 +13,21 @@
namespace mirroring {
namespace {
-// Required by mojom::VideoCaptureHost interface. Can be any number.
-constexpr int kDeviceId = 0;
+
+// Required by mojom::VideoCaptureHost interface. Can be any nonzero value.
+const base::UnguessableToken& DeviceId() {
+ static const base::NoDestructor<base::UnguessableToken> device_id(
+ base::UnguessableToken::Deserialize(1, 1));
+ return *device_id;
+}
+
+// Required by mojom::VideoCaptureHost interface. Can be any nonzero value.
+const base::UnguessableToken& SessionId() {
+ static const base::NoDestructor<base::UnguessableToken> session_id(
+ base::UnguessableToken::Deserialize(1, 1));
+ return *session_id;
+}
+
} // namespace
VideoCaptureClient::VideoCaptureClient(const media::VideoCaptureParams& params,
@@ -37,13 +51,14 @@ void VideoCaptureClient::Start(FrameDeliverCallback deliver_callback,
media::mojom::VideoCaptureObserverPtr observer;
binding_.Bind(mojo::MakeRequest(&observer));
- video_capture_host_->Start(kDeviceId, 0, params_, std::move(observer));
+ video_capture_host_->Start(DeviceId(), SessionId(), params_,
+ std::move(observer));
}
void VideoCaptureClient::Stop() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DVLOG(1) << __func__;
- video_capture_host_->Stop(kDeviceId);
+ video_capture_host_->Stop(DeviceId());
}
void VideoCaptureClient::Pause() {
@@ -52,7 +67,7 @@ void VideoCaptureClient::Pause() {
if (frame_deliver_callback_.is_null())
return;
frame_deliver_callback_.Reset();
- video_capture_host_->Pause(kDeviceId);
+ video_capture_host_->Pause(DeviceId());
}
void VideoCaptureClient::Resume(FrameDeliverCallback deliver_callback) {
@@ -63,14 +78,14 @@ void VideoCaptureClient::Resume(FrameDeliverCallback deliver_callback) {
return;
}
frame_deliver_callback_ = std::move(deliver_callback);
- video_capture_host_->Resume(kDeviceId, 0, params_);
+ video_capture_host_->Resume(DeviceId(), SessionId(), params_);
}
void VideoCaptureClient::RequestRefreshFrame() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (frame_deliver_callback_.is_null())
return;
- video_capture_host_->RequestRefreshFrame(kDeviceId);
+ video_capture_host_->RequestRefreshFrame(DeviceId());
}
void VideoCaptureClient::OnStateChanged(media::mojom::VideoCaptureState state) {
@@ -129,7 +144,7 @@ void VideoCaptureClient::OnBufferReady(int32_t buffer_id,
<< VideoPixelFormatToString(info->pixel_format);
}
if (!consume_buffer) {
- video_capture_host_->ReleaseBuffer(kDeviceId, buffer_id, -1.0);
+ video_capture_host_->ReleaseBuffer(DeviceId(), buffer_id, -1.0);
return;
}
@@ -179,7 +194,7 @@ void VideoCaptureClient::OnBufferReady(int32_t buffer_id,
mojo::ScopedSharedBufferMapping mapping =
buffer_iter->second->get_shared_buffer_handle()->Map(buffer_size);
if (!mapping) {
- video_capture_host_->ReleaseBuffer(kDeviceId, buffer_id, -1.0);
+ video_capture_host_->ReleaseBuffer(DeviceId(), buffer_id, -1.0);
return;
}
mapping_iter =
@@ -216,7 +231,7 @@ void VideoCaptureClient::OnBufferReady(int32_t buffer_id,
if (!frame) {
LOG(DFATAL) << "Unable to wrap shared memory mapping.";
- video_capture_host_->ReleaseBuffer(kDeviceId, buffer_id, -1.0);
+ video_capture_host_->ReleaseBuffer(DeviceId(), buffer_id, -1.0);
OnStateChanged(media::mojom::VideoCaptureState::FAILED);
return;
}
@@ -256,7 +271,7 @@ void VideoCaptureClient::OnClientBufferFinished(
return;
}
- video_capture_host_->ReleaseBuffer(kDeviceId, buffer_id,
+ video_capture_host_->ReleaseBuffer(DeviceId(), buffer_id,
consumer_resource_utilization);
}
diff --git a/chromium/components/mirroring/service/video_capture_client_unittest.cc b/chromium/components/mirroring/service/video_capture_client_unittest.cc
index 586e7f6cb58..24a1ea4acf6 100644
--- a/chromium/components/mirroring/service/video_capture_client_unittest.cc
+++ b/chromium/components/mirroring/service/video_capture_client_unittest.cc
@@ -8,7 +8,7 @@
#include "base/memory/read_only_shared_memory_region.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/mirroring/service/fake_video_capture_host.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_metadata.h"
@@ -59,7 +59,7 @@ class VideoCaptureClientTest : public ::testing::Test,
client_->Stop();
run_loop.Run();
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
MOCK_METHOD1(OnFrameReceived, void(const gfx::Size&));
@@ -80,7 +80,7 @@ class VideoCaptureClientTest : public ::testing::Test,
base::Unretained(this)),
error_cb_.Get());
run_loop.Run();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void OnNewBuffer(int buffer_id, int buffer_size) {
@@ -96,7 +96,7 @@ class VideoCaptureClientTest : public ::testing::Test,
media::mojom::VideoBufferHandle::NewReadOnlyShmemRegion(
mojo::CreateReadOnlySharedMemoryRegion(buffer_size).region));
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void OnBufferReady(int buffer_id, const gfx::Size& frame_size) {
@@ -109,11 +109,11 @@ class VideoCaptureClientTest : public ::testing::Test,
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
client_->OnBufferReady(buffer_id, GetVideoFrameInfo(frame_size));
run_loop.Run();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::MockCallback<base::OnceClosure> error_cb_;
std::unique_ptr<FakeVideoCaptureHost> host_impl_;
std::unique_ptr<VideoCaptureClient> client_;
diff --git a/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc b/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc
index 8fd597a6285..185c09dd539 100644
--- a/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc
+++ b/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc
@@ -9,7 +9,7 @@
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/mirroring/service/message_dispatcher.h"
#include "components/mirroring/service/value_util.h"
@@ -97,7 +97,7 @@ class WifiStatusMonitorTest : public mojom::CastMessageChannel,
message.message_namespace = mojom::kWebRtcNamespace;
message.json_format_data = response;
inbound_channel_->Send(message.Clone());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// Creates a WifiStatusMonitor and start monitoring the status.
@@ -106,7 +106,7 @@ class WifiStatusMonitorTest : public mojom::CastMessageChannel,
EXPECT_CALL(error_callback_, Run(_)).Times(0);
auto status_monitor =
std::make_unique<WifiStatusMonitor>(&message_dispatcher_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Expect to receive request to send GET_STATUS message when create a
// WifiStatusMonitor.
EXPECT_EQ(mojom::kWebRtcNamespace,
@@ -119,7 +119,7 @@ class WifiStatusMonitorTest : public mojom::CastMessageChannel,
return status_monitor;
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
private:
mojom::CastMessageChannelPtr CreateInterfacePtrAndBind() {
@@ -128,7 +128,7 @@ class WifiStatusMonitorTest : public mojom::CastMessageChannel,
return outbound_channel_ptr;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
mojo::Binding<mojom::CastMessageChannel> binding_;
mojom::CastMessageChannelPtr inbound_channel_;
base::MockCallback<MessageDispatcher::ErrorCallback> error_callback_;
diff --git a/chromium/components/module_installer/OWNERS b/chromium/components/module_installer/OWNERS
index 9fac46f8fb0..d75ae45de06 100644
--- a/chromium/components/module_installer/OWNERS
+++ b/chromium/components/module_installer/OWNERS
@@ -1,3 +1,4 @@
agrieve@chromium.org
tiborg@chromium.org
+wnwen@chromium.org
# COMPONENT: Mobile>FeatureModules
diff --git a/chromium/components/module_installer/android/BUILD.gn b/chromium/components/module_installer/android/BUILD.gn
index 41d2ab4c02a..a4654a4d1ef 100644
--- a/chromium/components/module_installer/android/BUILD.gn
+++ b/chromium/components/module_installer/android/BUILD.gn
@@ -4,50 +4,33 @@
import("//build/config/android/rules.gni")
-# Contains code necessary to compile the rest of Chrome. Doesn't contain actual
-# implementations. To get implementations either depend on
-# |module_installer_impl_java| or |module_installer_stub_java| depending on your
-# build.
android_library("module_installer_java") {
java_files = [
- "java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java",
- "java/src-common/org/chromium/components/module_installer/ModuleInstaller.java",
- "java/src-common/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java",
- "java/src-common/org/chromium/components/module_installer/Module.java",
+ "java/src/org/chromium/components/module_installer/ModuleInstallerImpl.java",
+ "java/src/org/chromium/components/module_installer/ModuleInstallerBackend.java",
+ "java/src/org/chromium/components/module_installer/FakeModuleInstallerBackend.java",
+ "java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java",
+ "java/src/org/chromium/components/module_installer/ApkModuleInstaller.java",
+ "java/src/org/chromium/components/module_installer/ModuleInstaller.java",
+ "java/src/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java",
+ "java/src/org/chromium/components/module_installer/Module.java",
+ "java/src/org/chromium/components/module_installer/Timer.java",
+ "java/src/org/chromium/components/module_installer/observers/ModuleActivityObserver.java",
+ "java/src/org/chromium/components/module_installer/observers/ObserverStrategy.java",
+ "java/src/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java",
]
- jar_excluded_patterns = [ "*/ModuleInstallerImpl.class" ]
- deps = [
- "//base:base_java",
- ]
- jacoco_never_instrument = true
-}
-
-# Contains stub implementation to be used for builds not supporting modules
-# (e.g. APKs).
-android_library("module_installer_stub_java") {
- java_files = [ "java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java" ]
- deps = [
- ":module_installer_java",
- "//base:base_java",
- ]
- jacoco_never_instrument = true
-}
-# Contains real implementation to be used for builds supporting modules (e.g.
-# bundles).
-android_library("module_installer_impl_java") {
- java_files = [
- "java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java",
- "java/src-impl/org/chromium/components/module_installer/ModuleInstallerBackend.java",
- "java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java",
- "java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java",
- ]
deps = [
- ":module_installer_java",
"//base:base_java",
"//components/crash/android:java",
"//third_party/google_android_play_core:com_google_android_play_core_java",
]
+
+ srcjar_deps = [ ":module_installer_build_config" ]
+
+ jar_excluded_patterns = [ "*/ModuleInstallerConfig.class" ]
+
+ jacoco_never_instrument = true
}
android_library("module_installer_test_java") {
@@ -61,13 +44,24 @@ android_library("module_installer_test_java") {
jacoco_never_instrument = true
}
+junit_binary("module_installer_junit_tests") {
+ java_files = [ "junit/src/org/chromium/components/module_installer/observers/ModuleActivityObserverTest.java" ]
+ deps = [
+ ":module_installer_java",
+ "//base:base_java",
+ "//base:base_junit_test_support",
+ ]
+}
+
java_library("module_interface_java") {
supports_android = true
- java_files = [ "java/src-common/org/chromium/components/module_installer/ModuleInterface.java" ]
+ java_files = [
+ "java/src/org/chromium/components/module_installer/ModuleInterface.java",
+ ]
}
java_annotation_processor("module_interface_processor") {
- java_files = [ "java/src-common/org/chromium/components/module_installer/ModuleInterfaceProcessor.java" ]
+ java_files = [ "java/src/org/chromium/components/module_installer/ModuleInterfaceProcessor.java" ]
main_class =
"org.chromium.components.module_installer.ModuleInterfaceProcessor"
annotation_processor_deps = [ "//third_party/auto:auto_service_processor" ]
@@ -78,3 +72,28 @@ java_annotation_processor("module_interface_processor") {
]
jacoco_never_instrument = true
}
+
+# Use this one if your target needs to depend on ModuleInstallerConfig. The
+# other two targets are automatically added to build targets.
+java_cpp_template("module_installer_build_config") {
+ package_path = "org/chromium/components/module_installer"
+ sources = [
+ "build/ModuleInstallerConfig.template",
+ ]
+}
+
+java_cpp_template("module_installer_bundle_build_config") {
+ package_path = "org/chromium/components/module_installer"
+ sources = [
+ "build/ModuleInstallerConfig.template",
+ ]
+ defines = [ "IS_BUNDLE_BUILD" ]
+}
+
+java_cpp_template("module_installer_apk_build_config") {
+ package_path = "org/chromium/components/module_installer"
+ sources = [
+ "build/ModuleInstallerConfig.template",
+ ]
+ defines = [ "IS_APK_BUILD" ]
+}
diff --git a/chromium/components/module_installer/android/build/ModuleInstallerConfig.template b/chromium/components/module_installer/android/build/ModuleInstallerConfig.template
new file mode 100644
index 00000000000..745e6be4437
--- /dev/null
+++ b/chromium/components/module_installer/android/build/ModuleInstallerConfig.template
@@ -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.
+
+package org.chromium.components.module_installer;
+
+/** Build config for DFMs. */
+public class ModuleInstallerConfig {
+
+#if defined(IS_BUNDLE_BUILD)
+ public static final boolean IS_BUNDLE = true;
+#elif defined(IS_APK_BUILD)
+ public static final boolean IS_BUNDLE = false;
+#else
+ // This needs to not be final in order to avoid being inlined.
+ public static boolean IS_BUNDLE;
+#endif
+
+}
diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java b/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java
deleted file mode 100644
index 7e0b24c10ab..00000000000
--- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java
+++ /dev/null
@@ -1,178 +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.
-
-package org.chromium.components.module_installer;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Build;
-import android.text.TextUtils;
-
-import com.google.android.play.core.splitcompat.SplitCompat;
-import com.google.android.play.core.splitinstall.SplitInstallManagerFactory;
-
-import org.chromium.base.BuildInfo;
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.StrictModeContext;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.components.crash.CrashKeyIndex;
-import org.chromium.components.crash.CrashKeys;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-/** Installs dynamic feature modules (DFMs). */
-@MainDex
-public class ModuleInstallerImpl implements ModuleInstaller {
- /** Command line switch for activating the fake backend. */
- private static final String FAKE_FEATURE_MODULE_INSTALL = "fake-feature-module-install";
- private static ModuleInstaller sInstance = new ModuleInstallerImpl();
- private static boolean sAppContextSplitCompatted;
- private final Map<String, List<OnModuleInstallFinishedListener>> mModuleNameListenerMap =
- new HashMap<>();
- private ModuleInstallerBackend mBackend;
-
- /** Returns the singleton instance. */
- public static ModuleInstaller getInstance() {
- return sInstance;
- }
-
- public static void setInstanceForTesting(ModuleInstaller moduleInstaller) {
- sInstance = moduleInstaller;
- }
-
- @Override
- public void init() {
- if (sAppContextSplitCompatted) return;
- // SplitCompat.install may copy modules into Chrome's internal folder or clean them up.
- try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
- SplitCompat.install(ContextUtils.getApplicationContext());
- sAppContextSplitCompatted = true;
- }
- // SplitCompat.install may add emulated modules. Thus, update crash keys.
- updateCrashKeys();
- }
-
- @Override
- public void initActivity(Context context) {
- SplitCompat.install(context);
- }
-
- @Override
- public void recordModuleAvailability() {
- if (!CommandLine.getInstance().hasSwitch(FAKE_FEATURE_MODULE_INSTALL)) {
- PlayCoreModuleInstallerBackend.recordModuleAvailability();
- }
- }
-
- @Override
- public void updateCrashKeys() {
- Context context = ContextUtils.getApplicationContext();
-
- // Get modules that are fully installed as split APKs (excluding base which is always
- // installed). Tree set to have ordered and, thus, deterministic results.
- Set<String> fullyInstalledModules = new TreeSet<>();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- // Split APKs are only supported on Android L+.
- try {
- PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
- BuildInfo.getInstance().packageName, 0);
- if (packageInfo.splitNames != null) {
- fullyInstalledModules.addAll(Arrays.asList(packageInfo.splitNames));
- }
- } catch (NameNotFoundException e) {
- throw new RuntimeException(e);
- }
- }
-
- // Create temporary split install manager to retrieve both fully installed and emulated
- // modules. Then remove fully installed ones to get emulated ones only. Querying the
- // installed modules can only be done if splitcompat has already been called. Otherwise,
- // emulation of later modules won't work. If splitcompat has not been called no modules are
- // emulated. Therefore, use an empty set in that case.
- Set<String> emulatedModules = new TreeSet<>();
- if (sAppContextSplitCompatted) {
- emulatedModules.addAll(
- SplitInstallManagerFactory.create(context).getInstalledModules());
- emulatedModules.removeAll(fullyInstalledModules);
- }
-
- CrashKeys.getInstance().set(
- CrashKeyIndex.INSTALLED_MODULES, encodeCrashKeyValue(fullyInstalledModules));
- CrashKeys.getInstance().set(
- CrashKeyIndex.EMULATED_MODULES, encodeCrashKeyValue(emulatedModules));
- }
-
- @Override
- public void install(String moduleName, OnModuleInstallFinishedListener onFinishedListener) {
- ThreadUtils.assertOnUiThread();
-
- if (!mModuleNameListenerMap.containsKey(moduleName)) {
- mModuleNameListenerMap.put(moduleName, new LinkedList<>());
- }
- List<OnModuleInstallFinishedListener> onFinishedListeners =
- mModuleNameListenerMap.get(moduleName);
- onFinishedListeners.add(onFinishedListener);
- if (onFinishedListeners.size() > 1) {
- // Request is already running.
- return;
- }
- getBackend().install(moduleName);
- }
-
- @Override
- public void installDeferred(String moduleName) {
- ThreadUtils.assertOnUiThread();
- getBackend().installDeferred(moduleName);
- }
-
- private void onFinished(boolean success, List<String> moduleNames) {
- ThreadUtils.assertOnUiThread();
-
- for (String moduleName : moduleNames) {
- List<OnModuleInstallFinishedListener> onFinishedListeners =
- mModuleNameListenerMap.get(moduleName);
- if (onFinishedListeners == null) continue;
-
- for (OnModuleInstallFinishedListener listener : onFinishedListeners) {
- listener.onFinished(success);
- }
- mModuleNameListenerMap.remove(moduleName);
- }
-
- if (mModuleNameListenerMap.isEmpty()) {
- mBackend.close();
- mBackend = null;
- }
-
- updateCrashKeys();
- }
-
- private ModuleInstallerBackend getBackend() {
- if (mBackend == null) {
- ModuleInstallerBackend.OnFinishedListener listener = this::onFinished;
- mBackend = CommandLine.getInstance().hasSwitch(FAKE_FEATURE_MODULE_INSTALL)
- ? new FakeModuleInstallerBackend(listener)
- : new PlayCoreModuleInstallerBackend(listener);
- }
- return mBackend;
- }
-
- private String encodeCrashKeyValue(Set<String> moduleNames) {
- if (moduleNames.isEmpty()) return "<none>";
- // Values with dots are interpreted as URLs. Some module names have dots in them. Make sure
- // they don't get sanitized.
- return TextUtils.join(",", moduleNames).replace('.', '$');
- }
-
- private ModuleInstallerImpl() {}
-}
diff --git a/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java b/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java
deleted file mode 100644
index 25654c30cba..00000000000
--- a/chromium/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java
+++ /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.
-
-package org.chromium.components.module_installer;
-
-import org.chromium.base.annotations.MainDex;
-
-/** Dummy fallback of ModuleInstaller for APK builds. */
-@MainDex
-public class ModuleInstallerImpl implements ModuleInstaller {
- /** A valid singleton instance is necessary for tests to swap it out. */
- private static ModuleInstaller sInstance = new ModuleInstallerImpl();
-
- /** Returns the singleton instance. */
- public static ModuleInstaller getInstance() {
- return sInstance;
- }
-
- public static void setInstanceForTesting(ModuleInstaller moduleInstaller) {
- sInstance = moduleInstaller;
- }
-
- @Override
- public void install(String moduleName, OnModuleInstallFinishedListener onFinishedListener) {
- throw new UnsupportedOperationException("Cannot install module if APK");
- }
-
- @Override
- public void installDeferred(String moduleName) {
- throw new UnsupportedOperationException("Cannot deferred install module if APK");
- }
-
- private ModuleInstallerImpl() {}
-}
diff --git a/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ApkModuleInstaller.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ApkModuleInstaller.java
new file mode 100644
index 00000000000..bc565d6765d
--- /dev/null
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ApkModuleInstaller.java
@@ -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.
+
+package org.chromium.components.module_installer;
+
+/** Module Installer for Apks. */
+public class ApkModuleInstaller implements ModuleInstaller {
+ /** A valid singleton instance is necessary for tests to swap it out. */
+ private static ModuleInstaller sInstance = new ApkModuleInstaller();
+
+ /** Returns the singleton instance. */
+ public static ModuleInstaller getInstance() {
+ return sInstance;
+ }
+
+ public static void setInstanceForTesting(ModuleInstaller moduleInstaller) {
+ sInstance = moduleInstaller;
+ }
+}
diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/FakeModuleInstallerBackend.java
index 9bc39a7b1bf..e293021bfff 100644
--- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/FakeModuleInstallerBackend.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/FakeModuleInstallerBackend.java
@@ -56,8 +56,7 @@ class FakeModuleInstallerBackend extends ModuleInstallerBackend {
protected void onPostExecute(Boolean success) {
onFinished(success, Arrays.asList(moduleName));
}
- }
- .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@Override
diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Module.java
index ccd6e5ab591..fbe378807cd 100644
--- a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/Module.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Module.java
@@ -51,16 +51,18 @@ public class Module<T> {
/** Returns true if the module is currently installed and can be accessed. */
public boolean isInstalled() {
- if (sModulesUninstalledForTesting.contains(mName)) return false;
- if (mImpl != null) return true;
- // Accessing classes in the module may cause its DEX file to be loaded. And on some devices
- // that causes a read mode violation.
- try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
- ModuleInstaller.getInstance().init();
- Class.forName(mImplClassName);
- return true;
- } catch (ClassNotFoundException e) {
- return false;
+ try (Timer ignored1 = new Timer()) {
+ if (sModulesUninstalledForTesting.contains(mName)) return false;
+ if (mImpl != null) return true;
+ // Accessing classes in the module may cause its DEX file to be loaded. And on some
+ // devices that causes a read mode violation.
+ try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
+ ModuleInstaller.getInstance().init();
+ Class.forName(mImplClassName);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
}
}
@@ -83,18 +85,20 @@ public class Module<T> {
* installed.
*/
public T getImpl() {
- assert isInstalled();
- if (mImpl == null) {
- ModuleInstaller.getInstance().init();
- // Accessing classes in the module may cause its DEX file to be loaded. And on some
- // devices that causes a read mode violation.
- try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
- mImpl = mInterfaceClass.cast(Class.forName(mImplClassName).newInstance());
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
- | IllegalArgumentException e) {
- throw new RuntimeException(e);
+ try (Timer ignored1 = new Timer()) {
+ assert isInstalled();
+ if (mImpl == null) {
+ ModuleInstaller.getInstance().init();
+ // Accessing classes in the module may cause its DEX file to be loaded. And on some
+ // devices that causes a read mode violation.
+ try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
+ mImpl = mInterfaceClass.cast(Class.forName(mImplClassName).newInstance());
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ }
}
+ return mImpl;
}
- return mImpl;
}
}
diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstaller.java
index b5083a5c6ac..1b5e8ed17cf 100644
--- a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstaller.java
@@ -4,9 +4,9 @@
package org.chromium.components.module_installer;
-import android.content.Context;
+import android.app.Activity;
-import org.chromium.base.VisibleForTesting;
+import org.chromium.base.annotations.MainDex;
/**
* This interface contains all the necessary methods to orchestrate the installation of dynamic
@@ -14,13 +14,21 @@ import org.chromium.base.VisibleForTesting;
*/
public interface ModuleInstaller {
/** Returns the singleton instance from the correct implementation. */
+ @MainDex
static ModuleInstaller getInstance() {
- return ModuleInstallerImpl.getInstance();
+ if (ModuleInstallerConfig.IS_BUNDLE) {
+ return ModuleInstallerImpl.getInstance();
+ } else {
+ return ApkModuleInstaller.getInstance();
+ }
}
- @VisibleForTesting
static void setInstanceForTesting(ModuleInstaller moduleInstaller) {
- ModuleInstallerImpl.setInstanceForTesting(moduleInstaller);
+ if (ModuleInstallerConfig.IS_BUNDLE) {
+ ModuleInstallerImpl.setInstanceForTesting(moduleInstaller);
+ } else {
+ ApkModuleInstaller.setInstanceForTesting(moduleInstaller);
+ }
}
/** Needs to be called before trying to access a module. */
@@ -32,8 +40,9 @@ public interface ModuleInstaller {
*
* For details, see:
* https://developer.android.com/reference/com/google/android/play/core/splitcompat/SplitCompat.html#install(android.content.Context)
+ * @param activity The Activity for which SplitCompat will be run.
*/
- default void initActivity(Context context) {}
+ default void initActivity(Activity activity) {}
/**
* Records via UMA all modules that have been requested and are currently installed. The intent
@@ -60,4 +69,7 @@ public interface ModuleInstaller {
* @param moduleName Name of the module.
*/
default void installDeferred(String moduleName) {}
+
+ /** Called when startup completes to record module overhead during startup. */
+ default void recordStartupTime() {}
}
diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerBackend.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerBackend.java
index 3d7a5bf7750..c6e9dc71d4f 100644
--- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerBackend.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerBackend.java
@@ -46,6 +46,10 @@ import java.util.List;
*/
public abstract void close();
+ /* package */ void recordModuleAvailability() {}
+
+ /* package */ void recordStartupTime(long durationMs) {}
+
/** To be called when module install has finished. */
protected void onFinished(boolean success, List<String> moduleNames) {
mListener.onFinished(success, moduleNames);
diff --git a/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerImpl.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerImpl.java
new file mode 100644
index 00000000000..5bd89d2db4d
--- /dev/null
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInstallerImpl.java
@@ -0,0 +1,208 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.module_installer;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
+import android.text.TextUtils;
+
+import com.google.android.play.core.splitcompat.SplitCompat;
+import com.google.android.play.core.splitinstall.SplitInstallManagerFactory;
+
+import org.chromium.base.BuildInfo;
+import org.chromium.base.CommandLine;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.StrictModeContext;
+import org.chromium.base.ThreadUtils;
+import org.chromium.components.crash.CrashKeyIndex;
+import org.chromium.components.crash.CrashKeys;
+import org.chromium.components.module_installer.observers.ModuleActivityObserver;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Installs dynamic feature modules (DFMs).
+ */
+/* package */ class ModuleInstallerImpl implements ModuleInstaller {
+ /**
+ * Command line switch for activating the fake backend.
+ */
+ private static final String FAKE_FEATURE_MODULE_INSTALL = "fake-feature-module-install";
+ private static ModuleInstaller sInstance = new ModuleInstallerImpl();
+ private static boolean sAppContextSplitCompatted;
+ private final Map<String, List<OnModuleInstallFinishedListener>> mModuleNameListenerMap =
+ new HashMap<>();
+ private ModuleInstallerBackend mBackend;
+ private ModuleActivityObserver mActivityObserver = new ModuleActivityObserver();
+
+ /**
+ * Returns the singleton instance.
+ */
+ public static ModuleInstaller getInstance() {
+ return sInstance;
+ }
+
+ public static void setInstanceForTesting(ModuleInstaller moduleInstaller) {
+ sInstance = moduleInstaller;
+ }
+
+ @Override
+ public void init() {
+ try (Timer ignored1 = new Timer()) {
+ if (sAppContextSplitCompatted) return;
+ // SplitCompat.install may copy modules into Chrome's internal folder or clean them up.
+ try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
+ SplitCompat.install(ContextUtils.getApplicationContext());
+ sAppContextSplitCompatted = true;
+ }
+ // SplitCompat.install may add emulated modules. Thus, update crash keys.
+ updateCrashKeys();
+ }
+ }
+
+ @Override
+ public void initActivity(Activity activity) {
+ try (Timer ignored = new Timer()) {
+ // SplitCompat#install should always be run for the application first before it is run
+ // for any activities.
+ init();
+ SplitCompat.installActivity(activity);
+ }
+ }
+
+ @Override
+ public void recordModuleAvailability() {
+ try (Timer ignored = new Timer()) {
+ getBackend().recordModuleAvailability();
+ }
+ }
+
+ @Override
+ public void recordStartupTime() {
+ getBackend().recordStartupTime(Timer.getTotalTime());
+ }
+
+ @Override
+ public void updateCrashKeys() {
+ try (Timer ignored = new Timer()) {
+ Context context = ContextUtils.getApplicationContext();
+
+ // Get modules that are fully installed as split APKs (excluding base which is always
+ // installed). Tree set to have ordered and, thus, deterministic results.
+ Set<String> fullyInstalledModules = new TreeSet<>();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ // Split APKs are only supported on Android L+.
+ try {
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
+ BuildInfo.getInstance().packageName, 0);
+ if (packageInfo.splitNames != null) {
+ fullyInstalledModules.addAll(Arrays.asList(packageInfo.splitNames));
+ }
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Create temporary split install manager to retrieve both fully installed and emulated
+ // modules. Then remove fully installed ones to get emulated ones only. Querying the
+ // installed modules can only be done if splitcompat has already been called. Otherwise,
+ // emulation of later modules won't work. If splitcompat has not been called no modules
+ // are emulated. Therefore, use an empty set in that case.
+ Set<String> emulatedModules = new TreeSet<>();
+ if (sAppContextSplitCompatted) {
+ emulatedModules.addAll(
+ SplitInstallManagerFactory.create(context).getInstalledModules());
+ emulatedModules.removeAll(fullyInstalledModules);
+ }
+
+ CrashKeys.getInstance().set(
+ CrashKeyIndex.INSTALLED_MODULES, encodeCrashKeyValue(fullyInstalledModules));
+ CrashKeys.getInstance().set(
+ CrashKeyIndex.EMULATED_MODULES, encodeCrashKeyValue(emulatedModules));
+ }
+ }
+
+ @Override
+ public void install(String moduleName, OnModuleInstallFinishedListener onFinishedListener) {
+ try (Timer ignored = new Timer()) {
+ ThreadUtils.assertOnUiThread();
+
+ if (!mModuleNameListenerMap.containsKey(moduleName)) {
+ mModuleNameListenerMap.put(moduleName, new LinkedList<>());
+ }
+ List<OnModuleInstallFinishedListener> onFinishedListeners =
+ mModuleNameListenerMap.get(moduleName);
+ onFinishedListeners.add(onFinishedListener);
+ if (onFinishedListeners.size() > 1) {
+ // Request is already running.
+ return;
+ }
+ getBackend().install(moduleName);
+ }
+ }
+
+ @Override
+ public void installDeferred(String moduleName) {
+ try (Timer ignored = new Timer()) {
+ ThreadUtils.assertOnUiThread();
+ getBackend().installDeferred(moduleName);
+ }
+ }
+
+ private void onFinished(boolean success, List<String> moduleNames) {
+ // Add timer to this private method since it is passed as a callback.
+ try (Timer ignored = new Timer()) {
+ ThreadUtils.assertOnUiThread();
+
+ mActivityObserver.onModuleInstalled();
+
+ for (String moduleName : moduleNames) {
+ List<OnModuleInstallFinishedListener> onFinishedListeners =
+ mModuleNameListenerMap.get(moduleName);
+ if (onFinishedListeners == null) continue;
+
+ for (OnModuleInstallFinishedListener listener : onFinishedListeners) {
+ listener.onFinished(success);
+ }
+ mModuleNameListenerMap.remove(moduleName);
+ }
+
+ if (mModuleNameListenerMap.isEmpty()) {
+ mBackend.close();
+ mBackend = null;
+ }
+
+ updateCrashKeys();
+ }
+ }
+
+ private ModuleInstallerBackend getBackend() {
+ if (mBackend == null) {
+ ModuleInstallerBackend.OnFinishedListener listener = this::onFinished;
+ mBackend = CommandLine.getInstance().hasSwitch(FAKE_FEATURE_MODULE_INSTALL)
+ ? new FakeModuleInstallerBackend(listener)
+ : new PlayCoreModuleInstallerBackend(listener);
+ }
+ return mBackend;
+ }
+
+ private String encodeCrashKeyValue(Set<String> moduleNames) {
+ if (moduleNames.isEmpty()) return "<none>";
+ // Values with dots are interpreted as URLs. Some module names have dots in them. Make sure
+ // they don't get sanitized.
+ return TextUtils.join(",", moduleNames).replace('.', '$');
+ }
+
+ private ModuleInstallerImpl() {}
+}
diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInterface.java
index b26e1623bd0..1fc6fd5523d 100644
--- a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInterface.java
@@ -17,7 +17,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
public @interface ModuleInterface {
/** The name of the module. */
- public String module();
+ String module();
/** The fully qualified name of the module's interface implementation. */
- public String impl();
+ String impl();
}
diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterfaceProcessor.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInterfaceProcessor.java
index 4eecb3a014f..4eecb3a014f 100644
--- a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterfaceProcessor.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/ModuleInterfaceProcessor.java
diff --git a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java
index e6d8d0e26a5..e6d8d0e26a5 100644
--- a/chromium/components/module_installer/android/java/src-common/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/OnModuleInstallFinishedListener.java
diff --git a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java
index b64387c4516..b6bf7e2d72b 100644
--- a/chromium/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java
@@ -19,6 +19,7 @@ import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample;
+import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample;
import org.chromium.base.metrics.RecordHistogram;
import java.util.Collections;
@@ -90,18 +91,15 @@ import java.util.Set;
private static final int AVAILABILITY_STATUS_COUNT = 3;
/** Records via UMA all modules that have been requested and are currently installed. */
- public static void recordModuleAvailability() {
- // MUST call init before creating a SplitInstallManager.
- ModuleInstaller.getInstance().init();
+ @Override
+ /* package */ void recordModuleAvailability() {
SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
Set<String> requestedModules = new HashSet<>();
requestedModules.addAll(
prefs.getStringSet(KEY_MODULES_ONDEMAND_REQUESTED_PREVIOUSLY, new HashSet<>()));
requestedModules.addAll(
prefs.getStringSet(KEY_MODULES_DEFERRED_REQUESTED_PREVIOUSLY, new HashSet<>()));
- Set<String> installedModules =
- SplitInstallManagerFactory.create(ContextUtils.getApplicationContext())
- .getInstalledModules();
+ Set<String> installedModules = mManager.getInstalledModules();
for (String name : requestedModules) {
EnumeratedHistogramSample sample = new EnumeratedHistogramSample(
@@ -124,7 +122,14 @@ import java.util.Set;
}
}
- public PlayCoreModuleInstallerBackend(OnFinishedListener listener) {
+ @Override
+ /* package */ void recordStartupTime(long durationMs) {
+ TimesHistogramSample sample =
+ new TimesHistogramSample("Android.FeatureModules.StartupTime");
+ sample.record(durationMs);
+ }
+
+ /* package */ PlayCoreModuleInstallerBackend(OnFinishedListener listener) {
super(listener);
// MUST call init before creating a SplitInstallManager.
ModuleInstaller.getInstance().init();
@@ -271,9 +276,9 @@ import java.util.Set;
* @param prefKey Pref key pointing to a string set to which the requested module will be added.
* @return Whether the module has been requested previously.
*/
- private static boolean storeModuleRequested(String moduleName, String prefKey) {
+ private boolean storeModuleRequested(String moduleName, String prefKey) {
SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
- Set<String> modulesRequestedPreviously = prefs.getStringSet(prefKey, new HashSet<String>());
+ Set<String> modulesRequestedPreviously = prefs.getStringSet(prefKey, new HashSet<>());
Set<String> newModulesRequestedPreviously = new HashSet<>(modulesRequestedPreviously);
newModulesRequestedPreviously.add(moduleName);
SharedPreferences.Editor editor = prefs.edit();
diff --git a/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Timer.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Timer.java
new file mode 100644
index 00000000000..03627f8d07b
--- /dev/null
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/Timer.java
@@ -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.
+
+package org.chromium.components.module_installer;
+
+import android.os.SystemClock;
+
+import java.io.Closeable;
+
+/**
+ * Implements a timer through try-with-resources. New instances will be ignored if an existing
+ * timer is already running, so this is not necessary for private methods.
+ *
+ * This should only be used on the UI thread to avoid race conditions.
+ */
+/* package */ class Timer implements Closeable {
+ private static Timer sCurrentTimer;
+ private static long sTotalTime;
+
+ private final long mStartTime;
+
+ /* package */ Timer() {
+ mStartTime = SystemClock.uptimeMillis();
+ if (sCurrentTimer == null) {
+ sCurrentTimer = this;
+ }
+ }
+
+ @Override
+ public void close() {
+ if (sCurrentTimer == this) {
+ sCurrentTimer = null;
+ sTotalTime += SystemClock.uptimeMillis() - mStartTime;
+ }
+ }
+
+ /* package */ static long getTotalTime() {
+ return sTotalTime;
+ }
+}
diff --git a/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ModuleActivityObserver.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ModuleActivityObserver.java
new file mode 100644
index 00000000000..650fe8f56ef
--- /dev/null
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ModuleActivityObserver.java
@@ -0,0 +1,64 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.module_installer.observers;
+
+import android.app.Activity;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ThreadUtils;
+
+import java.util.HashSet;
+
+/**
+ * Observer for activities so that DFMs can be lazily installed on-demand.
+ * Note that ActivityIds are managed globally and therefore any changes to it are to be made
+ * using a single thread (in this case, the UI thread).
+ */
+public class ModuleActivityObserver implements ApplicationStatus.ActivityStateListener {
+ private static HashSet<Integer> sActivityIds = new HashSet<Integer>();
+ private final ObserverStrategy mStrategy;
+
+ public ModuleActivityObserver() {
+ this(new ObserverStrategyImpl());
+ }
+
+ public ModuleActivityObserver(ObserverStrategy strategy) {
+ mStrategy = strategy;
+ }
+
+ @Override
+ public void onActivityStateChange(Activity activity, @ActivityState int newState) {
+ ThreadUtils.assertOnUiThread();
+
+ if (newState == ActivityState.CREATED || newState == ActivityState.RESUMED) {
+ splitCompatActivity(activity);
+ } else if (newState == ActivityState.DESTROYED) {
+ sActivityIds.remove(activity.hashCode());
+ }
+ }
+
+ /** Makes activities aware of a DFM install and prepare them to be able to use new modules. */
+ public void onModuleInstalled() {
+ ThreadUtils.assertOnUiThread();
+
+ sActivityIds.clear();
+
+ for (Activity activity : mStrategy.getRunningActivities()) {
+ if (mStrategy.getStateForActivity(activity) == ActivityState.RESUMED) {
+ splitCompatActivity(activity);
+ }
+ }
+ }
+
+ /** Split Compats activities that have not yet been split compatted. */
+ private void splitCompatActivity(Activity activity) {
+ Integer key = activity.hashCode();
+ if (!sActivityIds.contains(key)) {
+ sActivityIds.add(key);
+ mStrategy.getModuleInstaller().initActivity(activity);
+ }
+ }
+} \ No newline at end of file
diff --git a/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategy.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategy.java
new file mode 100644
index 00000000000..f50ef963f87
--- /dev/null
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategy.java
@@ -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.
+
+package org.chromium.components.module_installer.observers;
+
+import android.app.Activity;
+
+import org.chromium.components.module_installer.ModuleInstaller;
+
+import java.util.List;
+
+/** Interface outlining the necessary strategy to load activities and install modules. */
+/* package */ interface ObserverStrategy {
+ ModuleInstaller getModuleInstaller();
+ List<Activity> getRunningActivities();
+ int getStateForActivity(Activity activity);
+} \ No newline at end of file
diff --git a/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java
new file mode 100644
index 00000000000..414d9cccf77
--- /dev/null
+++ b/chromium/components/module_installer/android/java/src/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.module_installer.observers;
+
+import android.app.Activity;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.components.module_installer.ModuleInstaller;
+
+import java.util.List;
+
+/** Strategy utilizing ModuleInstaller and ApplicationStatus. */
+/* package */ class ObserverStrategyImpl implements ObserverStrategy {
+ @Override
+ public ModuleInstaller getModuleInstaller() {
+ return ModuleInstaller.getInstance();
+ }
+
+ @Override
+ public List<Activity> getRunningActivities() {
+ return ApplicationStatus.getRunningActivities();
+ }
+
+ @Override
+ public int getStateForActivity(Activity activity) {
+ return ApplicationStatus.getStateForActivity(activity);
+ }
+} \ No newline at end of file
diff --git a/chromium/components/module_installer/android/junit/src/org/chromium/components/module_installer/observers/ModuleActivityObserverTest.java b/chromium/components/module_installer/android/junit/src/org/chromium/components/module_installer/observers/ModuleActivityObserverTest.java
new file mode 100644
index 00000000000..a43fc420e6f
--- /dev/null
+++ b/chromium/components/module_installer/android/junit/src/org/chromium/components/module_installer/observers/ModuleActivityObserverTest.java
@@ -0,0 +1,162 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.module_installer.observers;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.components.module_installer.ModuleInstaller;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test suite for the ModuleActivityObserver class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class ModuleActivityObserverTest {
+ @Mock
+ private ModuleInstaller mModuleInstallerMock;
+
+ @Mock
+ private Activity mActivityMock;
+
+ @Mock
+ private ObserverStrategy mStrategy;
+
+ private ModuleActivityObserver mObserver;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mObserver = new ModuleActivityObserver(mStrategy);
+
+ doReturn(mModuleInstallerMock).when(mStrategy).getModuleInstaller();
+ doReturn(new ArrayList<>()).when(mStrategy).getRunningActivities();
+ doReturn(ActivityState.CREATED).when(mStrategy).getStateForActivity(any(Activity.class));
+ }
+
+ @Test
+ public void whenOnCreate_verifySplitCompatted() {
+ // Arrange.
+ @ActivityState
+ Integer newState = ActivityState.CREATED;
+
+ // Act.
+ mObserver.onActivityStateChange(mActivityMock, newState);
+
+ // Assert.
+ verify(mModuleInstallerMock, times(1)).initActivity(mActivityMock);
+ }
+
+ @Test
+ public void whenOnResume_verifySplitCompatted() {
+ // Arrange.
+ @ActivityState
+ Integer newState = ActivityState.RESUMED;
+
+ // Act.
+ mObserver.onActivityStateChange(mActivityMock, newState);
+
+ // Assert.
+ verify(mModuleInstallerMock, times(1)).initActivity(mActivityMock);
+ }
+
+ @Test
+ public void whenOnResumeTwice_verifySplitCompattedOnlyOnce() {
+ // Arrange.
+ @ActivityState
+ Integer newState = ActivityState.RESUMED;
+
+ // Act.
+ mObserver.onActivityStateChange(mActivityMock, newState);
+ mObserver.onActivityStateChange(mActivityMock, newState);
+
+ // Assert.
+ verify(mModuleInstallerMock, times(1)).initActivity(mActivityMock);
+ }
+
+ @Test
+ public void whenOnResumeAfterModuleInstall_verifySplitCompatted() {
+ // Arrange.
+ @ActivityState
+ Integer newState = ActivityState.RESUMED;
+
+ // Act.
+ mObserver.onActivityStateChange(mActivityMock, newState);
+ mObserver.onModuleInstalled();
+ mObserver.onActivityStateChange(mActivityMock, newState);
+
+ // Assert.
+ verify(mModuleInstallerMock, times(2)).initActivity(mActivityMock);
+ }
+
+ @Test
+ public void whenNotOnResumeOrNotOnCreate_verifyNotSplitCompatted() {
+ // Act.
+ mObserver.onActivityStateChange(mActivityMock, ActivityState.STARTED);
+ mObserver.onActivityStateChange(mActivityMock, ActivityState.PAUSED);
+ mObserver.onActivityStateChange(mActivityMock, ActivityState.STOPPED);
+ mObserver.onActivityStateChange(mActivityMock, ActivityState.DESTROYED);
+
+ // Assert.
+ verify(mModuleInstallerMock, never()).initActivity(mActivityMock);
+ }
+
+ @Test
+ public void whenMultipleInstances_verifySplitCompatCalledOnlyOnce() {
+ // Arrange.
+ @ActivityState
+ Integer newState = ActivityState.RESUMED;
+ ModuleActivityObserver newObserver = new ModuleActivityObserver(mStrategy);
+
+ // Act.
+ mObserver.onActivityStateChange(mActivityMock, newState);
+ newObserver.onActivityStateChange(mActivityMock, newState);
+
+ // Assert.
+ verify(mModuleInstallerMock, times(1)).initActivity(mActivityMock);
+ }
+
+ @Test
+ public void whenOnModuleInstalled_verifyOnlyResumedActivitiesAreSplitCompatted() {
+ // Arrange.
+ List<Activity> activitiesList = new ArrayList<Activity>();
+ Activity activityMock1 = mock(Activity.class);
+ Activity activityMock2 = mock(Activity.class);
+ Activity activityMock3 = mock(Activity.class);
+
+ activitiesList.add(activityMock1);
+ activitiesList.add(activityMock2);
+ activitiesList.add(activityMock3);
+
+ doReturn(activitiesList).when(mStrategy).getRunningActivities();
+
+ doReturn(ActivityState.RESUMED).when(mStrategy).getStateForActivity(activityMock1);
+ doReturn(ActivityState.PAUSED).when(mStrategy).getStateForActivity(activityMock2);
+ doReturn(ActivityState.DESTROYED).when(mStrategy).getStateForActivity(activityMock3);
+
+ // Act.
+ mObserver.onModuleInstalled();
+
+ // Assert.
+ verify(mModuleInstallerMock, times(1)).initActivity(any(Activity.class));
+ }
+}
diff --git a/chromium/components/navigation_interception/OWNERS b/chromium/components/navigation_interception/OWNERS
index d370effd656..4c7b5f57f51 100644
--- a/chromium/components/navigation_interception/OWNERS
+++ b/chromium/components/navigation_interception/OWNERS
@@ -1,2 +1,4 @@
michaelbai@chromium.org
ntfschr@chromium.org
+# COMPONENT: UI>Browser>Navigation
+# TEAM: chromium-reviews@chromium.org
diff --git a/chromium/components/navigation_interception/intercept_navigation_delegate.cc b/chromium/components/navigation_interception/intercept_navigation_delegate.cc
index b5f0536101c..47d802d8fcd 100644
--- a/chromium/components/navigation_interception/intercept_navigation_delegate.cc
+++ b/chromium/components/navigation_interception/intercept_navigation_delegate.cc
@@ -16,7 +16,6 @@
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"
diff --git a/chromium/components/navigation_interception/intercept_navigation_throttle.cc b/chromium/components/navigation_interception/intercept_navigation_throttle.cc
index 75450bb76bd..687c38a72b9 100644
--- a/chromium/components/navigation_interception/intercept_navigation_throttle.cc
+++ b/chromium/components/navigation_interception/intercept_navigation_throttle.cc
@@ -115,13 +115,14 @@ bool InterceptNavigationThrottle::ShouldCheckAsynchronously() const {
NavigationParams InterceptNavigationThrottle::GetNavigationParams(
bool is_redirect) const {
- return NavigationParams(
- navigation_handle()->GetURL(), navigation_handle()->GetReferrer(),
- navigation_handle()->HasUserGesture(), navigation_handle()->IsPost(),
- navigation_handle()->GetPageTransition(), is_redirect,
- navigation_handle()->IsExternalProtocol(), true,
- navigation_handle()->IsRendererInitiated(),
- navigation_handle()->GetBaseURLForDataURL());
+ return NavigationParams(navigation_handle()->GetURL(),
+ content::Referrer(navigation_handle()->GetReferrer()),
+ navigation_handle()->HasUserGesture(),
+ navigation_handle()->IsPost(),
+ navigation_handle()->GetPageTransition(), is_redirect,
+ navigation_handle()->IsExternalProtocol(), true,
+ navigation_handle()->IsRendererInitiated(),
+ navigation_handle()->GetBaseURLForDataURL());
}
} // namespace navigation_interception
diff --git a/chromium/components/navigation_metrics/OWNERS b/chromium/components/navigation_metrics/OWNERS
index db827c88019..b4d90df12b1 100644
--- a/chromium/components/navigation_metrics/OWNERS
+++ b/chromium/components/navigation_metrics/OWNERS
@@ -3,3 +3,4 @@ davidben@chromium.org
estark@chromium.org
# COMPONENT: Internals>Network
+# TEAM: net-dev@chromium.org
diff --git a/chromium/components/net_log/net_export_file_writer.cc b/chromium/components/net_log/net_export_file_writer.cc
index a64a35e259d..4f6fbc3891b 100644
--- a/chromium/components/net_log/net_export_file_writer.cc
+++ b/chromium/components/net_log/net_export_file_writer.cc
@@ -75,8 +75,8 @@ scoped_refptr<base::SequencedTaskRunner> CreateFileTaskRunner() {
//
// These operations can be skipped on shutdown since FileNetLogObserver's API
// doesn't require things to have completed until notified of completion.
- return base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ return base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}
diff --git a/chromium/components/net_log/net_export_file_writer_unittest.cc b/chromium/components/net_log/net_export_file_writer_unittest.cc
index 2d41be3bd39..caaf54a41d6 100644
--- a/chromium/components/net_log/net_export_file_writer_unittest.cc
+++ b/chromium/components/net_log/net_export_file_writer_unittest.cc
@@ -18,7 +18,7 @@
#include "base/json/json_reader.h"
#include "base/json/json_string_value_serializer.h"
#include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/values.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -254,8 +254,7 @@ class TestFilePathCallback {
class NetExportFileWriterTest : public ::testing::Test {
public:
NetExportFileWriterTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
network_change_notifier_(net::NetworkChangeNotifier::CreateMock()),
network_service_(network::NetworkService::CreateForTesting()) {}
@@ -440,7 +439,7 @@ class NetExportFileWriterTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
// Use a mock NetworkChangeNotifier so the real one can't add any logging.
std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
std::unique_ptr<network::NetworkService> network_service_;
diff --git a/chromium/components/neterror/resources/offline.js b/chromium/components/neterror/resources/offline.js
index 504b2a89e0c..3cdea7d275c 100644
--- a/chromium/components/neterror/resources/offline.js
+++ b/chromium/components/neterror/resources/offline.js
@@ -93,7 +93,14 @@ var FPS = 60;
var IS_HIDPI = window.devicePixelRatio > 1;
/** @const */
-var IS_IOS = /iPad|iPhone|iPod/.test(window.navigator.platform);
+// iPads are returning "MacIntel" for iOS 13 (devices & simulators).
+// Chrome on macOS also returns "MacIntel" for navigator.platform,
+// but navigator.userAgent includes /Safari/.
+// TODO(crbug.com/998999): Fix navigator.userAgent such that it reliably
+// returns an agent string containing "CriOS".
+var IS_IOS = /iPad|iPhone|iPod|MacIntel/.test(window.navigator.platform) &&
+ !(/Safari/.test(window.navigator.userAgent));
+
/** @const */
var IS_MOBILE = /Android/.test(window.navigator.userAgent) || IS_IOS;
diff --git a/chromium/components/network_hints/common/OWNERS b/chromium/components/network_hints/common/OWNERS
index 82b9841d19c..f1f3a154d50 100644
--- a/chromium/components/network_hints/common/OWNERS
+++ b/chromium/components/network_hints/common/OWNERS
@@ -1,4 +1,4 @@
-per-file *_messages.h=set noparent
-per-file *_messages.h=file://ipc/SECURITY_OWNERS
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *_messages.cc=set noparent
per-file *_messages.cc=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/network_hints/common/network_hints_messages.h b/chromium/components/network_hints/common/network_hints_messages.h
index 82fce8f0f93..aa365ebbf2f 100644
--- a/chromium/components/network_hints/common/network_hints_messages.h
+++ b/chromium/components/network_hints/common/network_hints_messages.h
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Multiply-included file, no traditional include guard.
+// Silence presubmit and Tricium warnings about include guards
+// no-include-guard-because-multiply-included
+// NOLINT(build/header_guard)
+
#include <string>
#include <vector>
@@ -44,7 +47,8 @@ IPC_MESSAGE_CONTROL1(NetworkHintsMsg_DNSPrefetch,
// Request for preconnect to host providing resource specified by URL
-IPC_MESSAGE_CONTROL3(NetworkHintsMsg_Preconnect,
+IPC_MESSAGE_CONTROL4(NetworkHintsMsg_Preconnect,
+ int /* render_frame_id */,
GURL /* preconnect target url */,
bool /* Does connection have its credentials flag set */,
int /* number of connections */)
diff --git a/chromium/components/network_hints/renderer/prescient_networking_dispatcher.cc b/chromium/components/network_hints/renderer/prescient_networking_dispatcher.cc
index 4ae1e1a943a..5bdd359d6ab 100644
--- a/chromium/components/network_hints/renderer/prescient_networking_dispatcher.cc
+++ b/chromium/components/network_hints/renderer/prescient_networking_dispatcher.cc
@@ -24,10 +24,12 @@ void PrescientNetworkingDispatcher::PrefetchDNS(
dns_prefetch_.Resolve(hostname_utf8.data(), hostname_utf8.length());
}
-void PrescientNetworkingDispatcher::Preconnect(const blink::WebURL& url,
- bool allow_credentials) {
+void PrescientNetworkingDispatcher::Preconnect(
+ blink::WebLocalFrame* web_local_frame,
+ const blink::WebURL& url,
+ bool allow_credentials) {
VLOG(2) << "Preconnect: " << url.GetString().Utf8();
- preconnect_.Preconnect(url, allow_credentials);
+ preconnect_.Preconnect(web_local_frame, url, allow_credentials);
}
} // namespace network_hints
diff --git a/chromium/components/network_hints/renderer/prescient_networking_dispatcher.h b/chromium/components/network_hints/renderer/prescient_networking_dispatcher.h
index 5cd5f466d7f..096e5f7d0c2 100644
--- a/chromium/components/network_hints/renderer/prescient_networking_dispatcher.h
+++ b/chromium/components/network_hints/renderer/prescient_networking_dispatcher.h
@@ -10,6 +10,10 @@
#include "components/network_hints/renderer/renderer_preconnect.h"
#include "third_party/blink/public/platform/web_prescient_networking.h"
+namespace blink {
+class WebLocalFrame;
+}
+
namespace network_hints {
// The main entry point from blink for sending DNS prefetch requests to the
@@ -20,7 +24,8 @@ class PrescientNetworkingDispatcher : public blink::WebPrescientNetworking {
~PrescientNetworkingDispatcher() override;
void PrefetchDNS(const blink::WebString& hostname) override;
- void Preconnect(const blink::WebURL& url,
+ void Preconnect(blink::WebLocalFrame* web_local_frame,
+ const blink::WebURL& url,
const bool allow_credentials) override;
private:
diff --git a/chromium/components/network_hints/renderer/renderer_preconnect.cc b/chromium/components/network_hints/renderer/renderer_preconnect.cc
index b353cb1cb4a..38a5a272869 100644
--- a/chromium/components/network_hints/renderer/renderer_preconnect.cc
+++ b/chromium/components/network_hints/renderer/renderer_preconnect.cc
@@ -8,6 +8,7 @@
#include "components/network_hints/common/network_hints_common.h"
#include "components/network_hints/common/network_hints_messages.h"
+#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
using content::RenderThread;
@@ -20,12 +21,15 @@ RendererPreconnect::RendererPreconnect() {
RendererPreconnect::~RendererPreconnect() {
}
-void RendererPreconnect::Preconnect(const GURL& url, bool allow_credentials) {
- if (!url.is_valid())
+void RendererPreconnect::Preconnect(blink::WebLocalFrame* web_local_frame,
+ const GURL& url,
+ bool allow_credentials) {
+ if (!url.is_valid() || !web_local_frame)
return;
- RenderThread::Get()->Send(
- new NetworkHintsMsg_Preconnect(url, allow_credentials, 1));
+ RenderThread::Get()->Send(new NetworkHintsMsg_Preconnect(
+ content::RenderFrame::FromWebFrame(web_local_frame)->GetRoutingID(), url,
+ allow_credentials, 1));
}
} // namespace network_hints
diff --git a/chromium/components/network_hints/renderer/renderer_preconnect.h b/chromium/components/network_hints/renderer/renderer_preconnect.h
index 39dac9312ba..9282d26ef1a 100644
--- a/chromium/components/network_hints/renderer/renderer_preconnect.h
+++ b/chromium/components/network_hints/renderer/renderer_preconnect.h
@@ -20,6 +20,10 @@
#include "base/macros.h"
#include "url/gurl.h"
+namespace blink {
+class WebLocalFrame;
+}
+
namespace network_hints {
// An internal interface to the network_hints component for efficiently sending
@@ -30,7 +34,9 @@ class RendererPreconnect {
~RendererPreconnect();
// Submit a preconnect request for a single connection.
- void Preconnect(const GURL& url, bool allow_credentials);
+ void Preconnect(blink::WebLocalFrame* web_local_frame,
+ const GURL& url,
+ bool allow_credentials);
private:
diff --git a/chromium/components/network_session_configurator/browser/network_session_configurator.cc b/chromium/components/network_session_configurator/browser/network_session_configurator.cc
index 79794485b35..8bd2b25b313 100644
--- a/chromium/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/chromium/components/network_session_configurator/browser/network_session_configurator.cc
@@ -25,7 +25,9 @@
#include "components/variations/variations_associated_data.h"
#include "net/base/host_mapping_rules.h"
#include "net/http/http_stream_factory.h"
+#include "net/quic/platform/impl/quic_flags_impl.h"
#include "net/quic/quic_utils_chromium.h"
+#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
@@ -107,6 +109,19 @@ bool ConfigureWebsocketOverHttp2(
return websocket_value == "true";
}
+int ConfigureSpdySessionMaxQueuedCappedFrames(
+ const base::CommandLine& /*command_line*/,
+ const VariationParameters& http2_trial_params) {
+ int value;
+ if (base::StringToInt(
+ GetVariationParam(http2_trial_params,
+ "spdy_session_max_queued_capped_frames"),
+ &value)) {
+ return value;
+ }
+ return net::kSpdySessionMaxQueuedCappedFrames;
+}
+
void ConfigureHttp2Params(const base::CommandLine& command_line,
base::StringPiece http2_trial_group,
const VariationParameters& http2_trial_params,
@@ -147,6 +162,10 @@ void ConfigureHttp2Params(const base::CommandLine& command_line,
params->enable_websocket_over_http2 =
ConfigureWebsocketOverHttp2(command_line, http2_trial_params);
+
+ params->spdy_session_max_queued_capped_frames =
+ ConfigureSpdySessionMaxQueuedCappedFrames(command_line,
+ http2_trial_params);
}
bool ShouldEnableQuic(base::StringPiece quic_trial_group,
@@ -411,15 +430,28 @@ int GetQuicInitialRttForHandshakeMilliseconds(
return 0;
}
-base::flat_set<std::string> GetQuicHostWhitelist(
+base::flat_set<std::string> GetQuicHostAllowlist(
const VariationParameters& quic_trial_params) {
- std::string host_whitelist =
+ std::string host_allowlist =
GetVariationParam(quic_trial_params, "host_whitelist");
std::vector<std::string> host_vector = base::SplitString(
- host_whitelist, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ host_allowlist, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
return base::flat_set<std::string>(std::move(host_vector));
}
+void SetQuicFlags(const VariationParameters& quic_trial_params) {
+ std::string flags_list =
+ GetVariationParam(quic_trial_params, "set_quic_flags");
+ for (const auto& flag : base::SplitString(
+ flags_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
+ std::vector<std::string> tokens = base::SplitString(
+ flag, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (tokens.size() != 2)
+ continue;
+ SetQuicFlagByName(tokens[0], tokens[1]);
+ }
+}
+
size_t GetQuicMaxPacketLength(const VariationParameters& quic_trial_params) {
unsigned value;
if (base::StringToUint(
@@ -560,7 +592,9 @@ void ConfigureQuicParams(base::StringPiece quic_trial_group,
}
params->quic_params.allow_server_migration =
ShouldQuicAllowServerMigration(quic_trial_params);
- params->quic_host_whitelist = GetQuicHostWhitelist(quic_trial_params);
+ params->quic_host_allowlist = GetQuicHostAllowlist(quic_trial_params);
+
+ SetQuicFlags(quic_trial_params);
}
size_t max_packet_length = GetQuicMaxPacketLength(quic_trial_params);
@@ -600,6 +634,12 @@ quic::ParsedQuicVersionVector ParseQuicVersions(
}
it++;
}
+ for (const auto& supported_version : quic::AllSupportedVersions()) {
+ if (quic::AlpnForVersion(supported_version) == version) {
+ supported_versions.push_back(supported_version);
+ break;
+ }
+ }
}
return supported_versions;
}
diff --git a/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc
index 4db23a0409c..7c7c9b6c4a4 100644
--- a/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc
+++ b/chromium/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -129,7 +129,7 @@ TEST_F(NetworkSessionConfiguratorTest, EnableQuicFromFieldTrialGroup) {
EXPECT_FALSE(params_.quic_params.go_away_on_path_degrading);
EXPECT_TRUE(params_.quic_params.initial_rtt_for_handshake.is_zero());
EXPECT_FALSE(params_.quic_params.allow_server_migration);
- EXPECT_TRUE(params_.quic_host_whitelist.empty());
+ EXPECT_TRUE(params_.quic_host_allowlist.empty());
EXPECT_TRUE(params_.quic_params.retransmittable_on_wire_timeout.is_zero());
net::HttpNetworkSession::Params default_params;
@@ -508,6 +508,19 @@ TEST_F(NetworkSessionConfiguratorTest, QuicVersionFromFieldTrialParams) {
EXPECT_EQ(supported_versions, params_.quic_params.supported_versions);
}
+TEST_F(NetworkSessionConfiguratorTest, QuicVersionFromFieldTrialParamsAlpn) {
+ std::map<std::string, std::string> field_trial_params;
+ field_trial_params["quic_version"] = "h3-T048";
+ variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+ base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+ ParseFieldTrials();
+
+ quic::ParsedQuicVersionVector supported_versions = {
+ {quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_48}};
+ EXPECT_EQ(supported_versions, params_.quic_params.supported_versions);
+}
+
TEST_F(NetworkSessionConfiguratorTest,
MultipleQuicVersionFromFieldTrialParams) {
std::map<std::string, std::string> field_trial_params;
@@ -580,7 +593,7 @@ TEST_F(NetworkSessionConfiguratorTest,
EXPECT_EQ(options, params_.quic_params.client_connection_options);
}
-TEST_F(NetworkSessionConfiguratorTest, QuicHostWhitelist) {
+TEST_F(NetworkSessionConfiguratorTest, QuicHostAllowlist) {
std::map<std::string, std::string> field_trial_params;
field_trial_params["host_whitelist"] = "www.example.org, www.example.com";
variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
@@ -588,12 +601,12 @@ TEST_F(NetworkSessionConfiguratorTest, QuicHostWhitelist) {
ParseFieldTrials();
- EXPECT_EQ(2u, params_.quic_host_whitelist.size());
- EXPECT_TRUE(base::Contains(params_.quic_host_whitelist, "www.example.com"));
- EXPECT_TRUE(base::Contains(params_.quic_host_whitelist, "www.example.org"));
+ EXPECT_EQ(2u, params_.quic_host_allowlist.size());
+ EXPECT_TRUE(base::Contains(params_.quic_host_allowlist, "www.example.com"));
+ EXPECT_TRUE(base::Contains(params_.quic_host_allowlist, "www.example.org"));
}
-TEST_F(NetworkSessionConfiguratorTest, QuicHostWhitelistEmpty) {
+TEST_F(NetworkSessionConfiguratorTest, QuicHostAllowlistEmpty) {
std::map<std::string, std::string> field_trial_params;
field_trial_params["host_whitelist"] = "";
variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
@@ -601,7 +614,23 @@ TEST_F(NetworkSessionConfiguratorTest, QuicHostWhitelistEmpty) {
ParseFieldTrials();
- EXPECT_TRUE(params_.quic_host_whitelist.empty());
+ EXPECT_TRUE(params_.quic_host_allowlist.empty());
+}
+
+TEST_F(NetworkSessionConfiguratorTest, QuicFlags) {
+ FLAGS_quic_supports_tls_handshake = false;
+ FLAGS_quic_reloadable_flag_quic_enable_version_99 = false;
+ std::map<std::string, std::string> field_trial_params;
+ field_trial_params["set_quic_flags"] =
+ "FLAGS_quic_supports_tls_handshake=true,"
+ "FLAGS_quic_reloadable_flag_quic_enable_version_99=true";
+ variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
+ base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
+
+ ParseFieldTrials();
+
+ EXPECT_TRUE(FLAGS_quic_supports_tls_handshake);
+ EXPECT_TRUE(FLAGS_quic_reloadable_flag_quic_enable_version_99);
}
TEST_F(NetworkSessionConfiguratorTest, Http2SettingsFromFieldTrialParams) {
@@ -687,6 +716,18 @@ TEST_F(NetworkSessionConfiguratorTest, QuicVersion) {
}
}
+TEST_F(NetworkSessionConfiguratorTest, QuicVersionAlpn) {
+ base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+ command_line.AppendSwitch(switches::kEnableQuic);
+ command_line.AppendSwitchASCII(switches::kQuicVersion, "h3-T048");
+
+ ParseCommandLineAndFieldTrials(command_line);
+
+ quic::ParsedQuicVersionVector supported_versions = {
+ {quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_48}};
+ EXPECT_EQ(supported_versions, params_.quic_params.supported_versions);
+}
+
TEST_F(NetworkSessionConfiguratorTest, OriginToForceQuicOn) {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitch(switches::kEnableQuic);
diff --git a/chromium/components/network_session_configurator/common/network_features.cc b/chromium/components/network_session_configurator/common/network_features.cc
index c4dd7346139..a7145d2253a 100644
--- a/chromium/components/network_session_configurator/common/network_features.cc
+++ b/chromium/components/network_session_configurator/common/network_features.cc
@@ -8,7 +8,4 @@
namespace features {
-const base::Feature kDnsOverHttps{"dns-over-https",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
} // namespace features
diff --git a/chromium/components/network_session_configurator/common/network_features.h b/chromium/components/network_session_configurator/common/network_features.h
index 4108b1a633f..753269508c4 100644
--- a/chromium/components/network_session_configurator/common/network_features.h
+++ b/chromium/components/network_session_configurator/common/network_features.h
@@ -10,10 +10,6 @@
namespace features {
-// Enabled DNS over HTTPS
-// (https://tools.ietf.org/id/draft-ietf-doh-dns-over-https-12.txt).
-NETWORK_SESSION_CONFIGURATOR_EXPORT extern const base::Feature kDnsOverHttps;
-
} // namespace features
#endif // COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_FEATURES_H_
diff --git a/chromium/components/network_time/network_time_test_utils.cc b/chromium/components/network_time/network_time_test_utils.cc
index 72611899b60..6ba8a358902 100644
--- a/chromium/components/network_time/network_time_test_utils.cc
+++ b/chromium/components/network_time/network_time_test_utils.cc
@@ -6,12 +6,7 @@
#include <memory>
-#include "base/feature_list.h"
-#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
-#include "base/test/mock_entropy_provider.h"
-#include "base/test/scoped_feature_list.h"
-#include "components/variations/variations_associated_data.h"
#include "net/http/http_response_headers.h"
#include "net/test/embedded_test_server/http_response.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,15 +55,13 @@ void FieldTrialTest::SetNetworkQueriesWithVariationsService(
bool enable,
float query_probability,
NetworkTimeTracker::FetchBehavior fetch_behavior) {
- const std::string kTrialName = "Trial";
- const std::string kGroupName = "group";
- const base::Feature kFeature{"NetworkTimeServiceQuerying",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
- // Clear all the things.
- variations::testing::ClearAllVariationParams();
+ scoped_feature_list_.Reset();
+ if (!enable) {
+ scoped_feature_list_.InitAndDisableFeature(kNetworkTimeServiceQuerying);
+ return;
+ }
- std::map<std::string, std::string> params;
+ base::FieldTrialParams params;
params["RandomQueryProbability"] = base::NumberToString(query_probability);
params["CheckTimeIntervalSeconds"] = base::NumberToString(360);
std::string fetch_behavior_param;
@@ -88,46 +81,8 @@ void FieldTrialTest::SetNetworkQueriesWithVariationsService(
break;
}
params["FetchBehavior"] = fetch_behavior_param;
-
- // There are 3 things here: a FieldTrial, a FieldTrialList, and a
- // FeatureList. Don't get confused! The FieldTrial is reference-counted,
- // and a reference is held by the FieldTrialList. The FieldTrialList and
- // FeatureList are both singletons. The authorized way to reset the former
- // for testing is to destruct it (above). The latter, by contrast, should
- // should already start in a clean state and can be manipulated via the
- // ScopedFeatureList helper class. If this comment was useful to you
- // please send me a postcard.
-
- // SetNetworkQueriesWithVariationsService() is usually called during test
- // fixture setup (to establish a default state) and then again in certain
- // tests that want to set special params. FieldTrialList is meant to be a
- // singleton with only one instance existing at once, and the constructor
- // fails a CHECK if this is violated. To allow these duplicate calls to this
- // method, any existing FieldTrialList must be destroyed before creating a new
- // one. (See https://crbug.com/684216#c5 for more discussion.)
- field_trial_list_.reset();
- field_trial_list_.reset(
- new base::FieldTrialList(std::make_unique<base::MockEntropyProvider>()));
-
- // refcounted, and reference held by the singleton FieldTrialList.
- base::FieldTrial* trial = base::FieldTrialList::FactoryGetFieldTrial(
- kTrialName, 100, kGroupName, base::FieldTrial::SESSION_RANDOMIZED,
- nullptr /* default_group_number */);
- // Disabling the field trial selects the default group, with which we
- // associate the provided params. Disabling the field trial does not disable
- // the feature itself, but just provides a default group to use to set the
- // feature enabled/disabled state below.
- trial->Disable();
- ASSERT_TRUE(
- variations::AssociateVariationParams(kTrialName, kGroupName, params));
-
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->RegisterFieldTrialOverride(
- kFeature.name, enable ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
- : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
- trial);
- scoped_feature_list_.reset(new base::test::ScopedFeatureList);
- scoped_feature_list_->InitWithFeatureList(std::move(feature_list));
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ kNetworkTimeServiceQuerying, params);
}
} // namespace network_time
diff --git a/chromium/components/network_time/network_time_test_utils.h b/chromium/components/network_time/network_time_test_utils.h
index b99cf7a834b..7c797ec574d 100644
--- a/chromium/components/network_time/network_time_test_utils.h
+++ b/chromium/components/network_time/network_time_test_utils.h
@@ -9,16 +9,9 @@
#include <memory>
#include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
#include "components/network_time/network_time_tracker.h"
-namespace base {
-namespace test {
-class ScopedFeatureList;
-} // namespace test
-
-class FieldTrialList;
-} // namespace base
-
namespace net {
namespace test_server {
struct HttpRequest;
@@ -62,8 +55,7 @@ class FieldTrialTest {
NetworkTimeTracker::FetchBehavior fetch_behavior);
private:
- std::unique_ptr<base::FieldTrialList> field_trial_list_;
- std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
+ base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(FieldTrialTest);
};
diff --git a/chromium/components/network_time/network_time_tracker.cc b/chromium/components/network_time/network_time_tracker.cc
index cf0544d15bc..8e0bdfc086b 100644
--- a/chromium/components/network_time/network_time_tracker.cc
+++ b/chromium/components/network_time/network_time_tracker.cc
@@ -472,7 +472,7 @@ void NetworkTimeTracker::CheckTime() {
// Not expecting any cookies, but just in case.
resource_request->load_flags =
net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
// This cancels any outstanding fetch.
time_fetcher_ = network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
diff --git a/chromium/components/network_time/network_time_tracker_unittest.cc b/chromium/components/network_time/network_time_tracker_unittest.cc
index 364efa2d2f6..e1c844e438a 100644
--- a/chromium/components/network_time/network_time_tracker_unittest.cc
+++ b/chromium/components/network_time/network_time_tracker_unittest.cc
@@ -14,9 +14,9 @@
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
+#include "base/test/task_environment.h"
#include "components/client_update_protocol/ecdsa.h"
#include "components/network_time/network_time_pref_names.h"
#include "components/network_time/network_time_test_utils.h"
@@ -48,8 +48,7 @@ class NetworkTimeTrackerTest : public ::testing::Test {
~NetworkTimeTrackerTest() override {}
NetworkTimeTrackerTest()
- : task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
field_trial_test_(new FieldTrialTest()),
clock_(new base::SimpleTestClock),
tick_clock_(new base::SimpleTestTickClock),
@@ -156,7 +155,7 @@ class NetworkTimeTrackerTest : public ::testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<FieldTrialTest> field_trial_test_;
base::TimeDelta resolution_;
base::TimeDelta latency_;
diff --git a/chromium/components/ntp_snippets/content_suggestions_service.cc b/chromium/components/ntp_snippets/content_suggestions_service.cc
index c532fd99cea..6fd14be8427 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service.cc
+++ b/chromium/components/ntp_snippets/content_suggestions_service.cc
@@ -18,7 +18,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/values.h"
-#include "components/favicon/core/favicon_server_fetcher_params.h"
#include "components/favicon/core/large_icon_service.h"
#include "components/favicon_base/fallback_icon_style.h"
#include "components/favicon_base/favicon_types.h"
@@ -292,7 +291,7 @@ void ContentSuggestionsService::OnGetFaviconFromCacheFinished(
})");
large_icon_service_
->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(publisher_url),
+ publisher_url,
/*may_page_url_be_private=*/false,
/*should_trim_page_url_path=*/false, traffic_annotation,
base::Bind(
diff --git a/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc b/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
index 231c09a0014..d9ffc0aee32 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
+++ b/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
@@ -13,7 +13,7 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_clock.h"
#include "components/ntp_snippets/category_info.h"
#include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
@@ -259,7 +259,7 @@ TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) {
TEST_F(ContentSuggestionsServiceTest,
ShouldCallbackEmptyImageForUnavailableProvider) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::TaskEnvironment task_environment;
base::RunLoop run_loop;
// Assuming there will never be a category with the id below.
diff --git a/chromium/components/ntp_snippets/features.cc b/chromium/components/ntp_snippets/features.cc
index 2b7f345cb31..72fca90c425 100644
--- a/chromium/components/ntp_snippets/features.cc
+++ b/chromium/components/ntp_snippets/features.cc
@@ -72,7 +72,7 @@ const base::Feature kKeepPrefetchedContentSuggestions{
"KeepPrefetchedContentSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kOptionalImagesEnabledFeature{
- "NTPRemoteSuggestionsOptionalImages", base::FEATURE_DISABLED_BY_DEFAULT};
+ "NTPRemoteSuggestionsOptionalImages", base::FEATURE_ENABLED_BY_DEFAULT};
std::vector<const base::Feature*> GetAllFeatures() {
// Skip the last feature as it's a nullptr.
diff --git a/chromium/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc b/chromium/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
index 96e3b6dee3c..4518f6ad44f 100644
--- a/chromium/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/cached_image_fetcher_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
#include "components/image_fetcher/core/image_fetcher.h"
#include "components/image_fetcher/core/image_fetcher_impl.h"
@@ -121,7 +121,7 @@ class NtpSnippetsCachedImageFetcherTest
image_db_->GetCallback(true);
} break;
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
RemoteSuggestionsDatabase* database() { return database_.get(); }
@@ -152,7 +152,7 @@ class NtpSnippetsCachedImageFetcherTest
FakeDB<SnippetImageProto>* image_db_;
TestingPrefServiceSimple pref_service_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(NtpSnippetsCachedImageFetcherTest);
};
diff --git a/chromium/components/ntp_snippets/remote/json_request.cc b/chromium/components/ntp_snippets/remote/json_request.cc
index 76b2325e7d6..0dc2ecd5a20 100644
--- a/chromium/components/ntp_snippets/remote/json_request.cc
+++ b/chromium/components/ntp_snippets/remote/json_request.cc
@@ -229,9 +229,7 @@ std::unique_ptr<JsonRequest> JsonRequest::Builder::Build() const {
}
JsonRequest::Builder& JsonRequest::Builder::SetAuthentication(
- const std::string& account_id,
const std::string& auth_header) {
- obfuscated_gaia_id_ = account_id;
auth_header_ = auth_header;
return *this;
}
@@ -290,7 +288,7 @@ std::unique_ptr<network::ResourceRequest>
JsonRequest::Builder::BuildResourceRequest() const {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url_;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
resource_request->headers.SetHeader("Content-Type",
"application/json; charset=UTF-8");
diff --git a/chromium/components/ntp_snippets/remote/json_request.h b/chromium/components/ntp_snippets/remote/json_request.h
index 0b0f85e64a5..3fd6f965d47 100644
--- a/chromium/components/ntp_snippets/remote/json_request.h
+++ b/chromium/components/ntp_snippets/remote/json_request.h
@@ -16,6 +16,7 @@
#include "components/language/core/browser/url_language_histogram.h"
#include "components/ntp_snippets/remote/request_params.h"
#include "components/ntp_snippets/status.h"
+#include "google_apis/gaia/core_account_id.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
@@ -73,8 +74,7 @@ class JsonRequest {
// Builds a Request object that contains all data to fetch new snippets.
std::unique_ptr<JsonRequest> Build() const;
- Builder& SetAuthentication(const std::string& account_id,
- const std::string& auth_header);
+ Builder& SetAuthentication(const std::string& auth_header);
Builder& SetCreationTime(base::TimeTicks creation_time);
// The language_histogram borrowed from the fetcher needs to stay alive
// until the request body is built.
@@ -126,7 +126,6 @@ class JsonRequest {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Optional properties.
- std::string obfuscated_gaia_id_;
std::string user_class_;
std::string display_capability_;
const language::UrlLanguageHistogram* language_histogram_;
diff --git a/chromium/components/ntp_snippets/remote/json_request_unittest.cc b/chromium/components/ntp_snippets/remote/json_request_unittest.cc
index 92642b52862..d6d4b77138a 100644
--- a/chromium/components/ntp_snippets/remote/json_request_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/json_request_unittest.cc
@@ -135,7 +135,7 @@ TEST_F(JsonRequestTest, MAYBE_BuildRequestAuthenticated) {
params.interactive_request = false;
builder.SetParams(params)
.SetUrl(GURL("http://valid-url.test"))
- .SetAuthentication("0BFUSGAIA", "headerstuff")
+ .SetAuthentication("headerstuff")
.SetUserClassForTesting("ACTIVE_NTP_USER")
.Build();
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc
index 6c76b42a3b2..52696e40f66 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_database.cc
@@ -31,8 +31,9 @@ RemoteSuggestionsDatabase::RemoteSuggestionsDatabase(
: RemoteSuggestionsDatabase(
proto_database_provider,
database_dir,
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})) {}
RemoteSuggestionsDatabase::RemoteSuggestionsDatabase(
@@ -94,6 +95,11 @@ void RemoteSuggestionsDatabase::LoadSnippets(SnippetsCallback callback) {
}
void RemoteSuggestionsDatabase::SaveSnippet(const RemoteSuggestion& snippet) {
+ if (IsErrorState()) {
+ DVLOG(0) << "Attempted save snippet but db is in an error state, aborting";
+ return;
+ }
+
std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector());
// OnDatabaseLoaded relies on the detail that the primary snippet id goes
// first in the protocol representation.
@@ -104,6 +110,11 @@ void RemoteSuggestionsDatabase::SaveSnippet(const RemoteSuggestion& snippet) {
void RemoteSuggestionsDatabase::SaveSnippets(
const RemoteSuggestion::PtrVector& snippets) {
+ if (IsErrorState()) {
+ DVLOG(0) << "Attempted save snippets but db is in an error state, aborting";
+ return;
+ }
+
std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector());
for (const std::unique_ptr<RemoteSuggestion>& snippet : snippets) {
// OnDatabaseLoaded relies on the detail that the primary snippet id goes
@@ -120,7 +131,11 @@ void RemoteSuggestionsDatabase::DeleteSnippet(const std::string& snippet_id) {
void RemoteSuggestionsDatabase::DeleteSnippets(
std::unique_ptr<std::vector<std::string>> snippet_ids) {
- DCHECK(IsInitialized());
+ if (IsErrorState()) {
+ DVLOG(0)
+ << "Attempted delete snippets but db is in an error state, aborting";
+ return;
+ }
std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector());
database_->UpdateEntries(
@@ -140,7 +155,10 @@ void RemoteSuggestionsDatabase::LoadImage(const std::string& snippet_id,
void RemoteSuggestionsDatabase::SaveImage(const std::string& snippet_id,
const std::string& image_data) {
- DCHECK(IsInitialized());
+ if (IsErrorState()) {
+ DVLOG(0) << "Attempted save image but db is in an error state, aborting";
+ return;
+ }
SnippetImageProto image_proto;
image_proto.set_data(image_data);
@@ -161,7 +179,10 @@ void RemoteSuggestionsDatabase::DeleteImage(const std::string& snippet_id) {
void RemoteSuggestionsDatabase::DeleteImages(
std::unique_ptr<std::vector<std::string>> snippet_ids) {
- DCHECK(IsInitialized());
+ if (IsErrorState()) {
+ DVLOG(0) << "Attempted delete images but db is in an error state, aborting";
+ return;
+ }
image_database_->UpdateEntries(
std::make_unique<ImageKeyEntryVector>(), std::move(snippet_ids),
base::BindOnce(&RemoteSuggestionsDatabase::OnImageDatabaseSaved,
@@ -170,7 +191,10 @@ void RemoteSuggestionsDatabase::DeleteImages(
void RemoteSuggestionsDatabase::GarbageCollectImages(
std::unique_ptr<std::set<std::string>> alive_snippet_ids) {
- DCHECK(image_database_initialized_);
+ if (IsErrorState()) {
+ DVLOG(0) << "Attempted gc but db is in an error state, aborting";
+ return;
+ }
image_database_->LoadKeys(base::BindOnce(
&RemoteSuggestionsDatabase::DeleteUnreferencedImages,
weak_ptr_factory_.GetWeakPtr(), std::move(alive_snippet_ids)));
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
index ddd82600d7d..dedb1e0f8fe 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_database_unittest.cc
@@ -80,8 +80,16 @@ class RemoteSuggestionsDatabaseTest : public testing::Test {
std::move(image_db));
}
+ void ForceDBError() { db_->OnDatabaseError(); }
+
FakeDB<SnippetProto>* suggestion_db() { return suggestion_db_; }
+ std::map<std::string, SnippetProto>& suggestion_db_storage() {
+ return suggestion_db_storage_;
+ }
FakeDB<SnippetImageProto>* image_db() { return image_db_; }
+ std::map<std::string, SnippetImageProto>& image_db_storage() {
+ return image_db_storage_;
+ }
RemoteSuggestionsDatabase* db() { return db_.get(); }
@@ -431,4 +439,28 @@ TEST_F(RemoteSuggestionsDatabaseTest, ShouldGarbageCollectImages) {
image_db()->GetCallback(true);
}
+TEST_F(RemoteSuggestionsDatabaseTest, TryOperationsAfterError) {
+ CreateDatabase();
+ suggestion_db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ image_db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ ASSERT_TRUE(db()->IsInitialized());
+
+ ForceDBError();
+ ASSERT_TRUE(db()->IsErrorState());
+
+ std::unique_ptr<RemoteSuggestion> snippet = CreateTestSuggestion();
+ std::string image_data("pretty image");
+
+ db()->SaveSnippet(*snippet);
+ db()->SaveImage(snippet->id(), image_data);
+ ASSERT_TRUE(suggestion_db_storage().empty());
+ ASSERT_TRUE(image_db_storage().empty());
+
+ db()->DeleteImage("foo");
+ db()->GarbageCollectImages(
+ std::make_unique<std::set<std::string>>(std::set<std::string>({"foo"})));
+
+ SUCCEED() << "This test passes if it doesn't crash";
+}
+
} // namespace ntp_snippets
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
index c8213f0c7c4..3a3916a3052 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
@@ -257,7 +257,6 @@ void RemoteSuggestionsFetcherImpl::FetchSnippetsAuthenticated(
fetch_url_, builder.is_interactive_request());
builder.SetUrl(url).SetAuthentication(
- identity_manager_->GetPrimaryAccountId(),
base::StringPrintf(kAuthorizationRequestHeaderFormat,
oauth_access_token.c_str()));
StartRequest(std::move(builder), std::move(callback),
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
index 42a29042c96..6c28c7df6f0 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
@@ -16,7 +16,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
@@ -201,7 +201,7 @@ class RemoteSuggestionsFetcherImplTest : public testing::Test {
base::BindRepeating(&ParseJsonDelayed), GetFetchEndpoint(), api_key,
user_classifier_.get());
- fetcher_->SetClockForTesting(scoped_task_environment_.GetMockClock());
+ fetcher_->SetClockForTesting(task_environment_.GetMockClock());
}
void SignIn() { identity_test_env_.MakePrimaryAccountAvailable(kTestEmail); }
@@ -215,7 +215,7 @@ class RemoteSuggestionsFetcherImplTest : public testing::Test {
RemoteSuggestionsFetcherImpl& fetcher() { return *fetcher_; }
MockSnippetsAvailableCallback& mock_callback() { return mock_callback_; }
void FastForwardUntilNoTasksRemain() {
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
}
base::HistogramTester& histogram_tester() { return histogram_tester_; }
@@ -253,8 +253,8 @@ class RemoteSuggestionsFetcherImplTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::map<std::string, std::string> default_variation_params_;
signin::IdentityTestEnvironment identity_test_env_;
network::TestURLLoaderFactory test_url_loader_factory_;
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
index 6648e669783..21a7dbb076a 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -23,8 +23,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/default_clock.h"
#include "base/time/tick_clock.h"
@@ -389,7 +389,7 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
void RunUntilIdle() {
timer_mock_task_runner_->RunUntilIdle();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void SetCategoryRanker(std::unique_ptr<CategoryRanker> category_ranker) {
@@ -595,7 +595,7 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
image_fetcher::FakeImageDecoder image_decoder_;
std::unique_ptr<MockScheduler> scheduler_;
RemoteSuggestionsStatusService* remote_suggestions_status_service_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
RemoteSuggestionsStatusService::StatusChangeCallback status_change_callback_;
diff --git a/chromium/components/ntp_snippets_strings_grdp/OWNERS b/chromium/components/ntp_snippets_strings_grdp/OWNERS
index c7f9cc3fac0..f2768600788 100644
--- a/chromium/components/ntp_snippets_strings_grdp/OWNERS
+++ b/chromium/components/ntp_snippets_strings_grdp/OWNERS
@@ -1 +1,2 @@
file://components/ntp_snippets/OWNERS
+# COMPONENT: UI>Browser>NewTabPage
diff --git a/chromium/components/ntp_tiles/BUILD.gn b/chromium/components/ntp_tiles/BUILD.gn
index 244ad33d493..e96ed7096d5 100644
--- a/chromium/components/ntp_tiles/BUILD.gn
+++ b/chromium/components/ntp_tiles/BUILD.gn
@@ -53,9 +53,10 @@ static_library("ntp_tiles") {
"//components/suggestions",
]
deps = [
+ "//build:branding_buildflags",
"//components/favicon/core",
"//components/favicon_base",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/image_fetcher/core",
"//components/pref_registry",
"//components/prefs",
@@ -85,6 +86,7 @@ source_set("unit_tests") {
deps = [
":ntp_tiles",
"//base/test:test_support",
+ "//build:branding_buildflags",
"//components/favicon/core",
"//components/favicon_base",
"//components/history/core/test",
diff --git a/chromium/components/ntp_tiles/OWNERS b/chromium/components/ntp_tiles/OWNERS
index ec42eefb967..5cd35eb49b4 100644
--- a/chromium/components/ntp_tiles/OWNERS
+++ b/chromium/components/ntp_tiles/OWNERS
@@ -1,6 +1,3 @@
-fhorschig@chromium.org
-jkrcal@chromium.org
+dbeam@chromium.org
kristipark@chromium.org
-mastiz@chromium.org
-treib@chromium.org
# COMPONENT: UI>Browser>ContentSuggestions>History
diff --git a/chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc b/chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc
index 88411c62530..504c018b654 100644
--- a/chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc
@@ -11,7 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/history/core/test/history_service_test_util.h"
#include "components/ntp_tiles/pref_names.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -103,7 +103,7 @@ class CustomLinksManagerImplTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
base::ScopedTempDir scoped_temp_dir_;
std::unique_ptr<history::HistoryService> history_service_;
@@ -469,7 +469,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldDeleteMostVisitedOnHistoryDeletion) {
base::UTF8ToUTF16(kTestCase2[0].title), true}}),
custom_links_->GetLinks());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest,
@@ -494,7 +494,7 @@ TEST_F(CustomLinksManagerImplTest,
/*restrict_urls=*/base::nullopt));
EXPECT_TRUE(custom_links_->GetLinks().empty());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest, ShouldDeleteOnHistoryDeletionAfterShutdown) {
@@ -523,7 +523,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldDeleteOnHistoryDeletionAfterShutdown) {
/*restrict_urls=*/base::nullopt));
EXPECT_TRUE(custom_links_->GetLinks().empty());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest, ShouldNotDeleteCustomLinkOnHistoryDeletion) {
@@ -567,7 +567,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldNotDeleteCustomLinkOnHistoryDeletion) {
{Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}}),
custom_links_->GetLinks());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest, ShouldIgnoreHistoryExpiredDeletions) {
@@ -601,7 +601,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldIgnoreHistoryExpiredDeletions) {
EXPECT_EQ(initial_links, custom_links_->GetLinks());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest, ShouldIgnoreEmptyHistoryDeletions) {
@@ -622,7 +622,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldIgnoreEmptyHistoryDeletions) {
EXPECT_EQ(initial_links, custom_links_->GetLinks());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest, ShouldNotUndoAfterHistoryDeletion) {
@@ -654,7 +654,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldNotUndoAfterHistoryDeletion) {
EXPECT_FALSE(custom_links_->UndoAction());
EXPECT_EQ(links_after_add, custom_links_->GetLinks());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(CustomLinksManagerImplTest, UpdateListAfterRemoteChange) {
diff --git a/chromium/components/ntp_tiles/icon_cacher_impl.cc b/chromium/components/ntp_tiles/icon_cacher_impl.cc
index 5fecbfb5f9a..5549ceb7e53 100644
--- a/chromium/components/ntp_tiles/icon_cacher_impl.cc
+++ b/chromium/components/ntp_tiles/icon_cacher_impl.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
-#include "components/favicon/core/favicon_server_fetcher_params.h"
#include "components/favicon/core/favicon_service.h"
#include "components/favicon/core/favicon_util.h"
#include "components/favicon/core/large_icon_service.h"
@@ -254,7 +253,7 @@ void IconCacherImpl::OnGetLargeIconOrFallbackStyleFinished(
})");
large_icon_service_
->GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache(
- favicon::FaviconServerFetcherParams::CreateForMobile(page_url),
+ page_url,
/*may_page_url_be_private=*/true, /*should_trim_page_url_path=*/false,
traffic_annotation,
base::Bind(&IconCacherImpl::OnMostLikelyFaviconDownloaded,
diff --git a/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc b/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc
index 94e1c2b3265..205d21ed2fe 100644
--- a/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/icon_cacher_impl_unittest.cc
@@ -14,7 +14,7 @@
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/favicon/core/favicon_client.h"
@@ -53,6 +53,11 @@ using ::testing::ReturnArg;
namespace ntp_tiles {
namespace {
+const int kTestDipForServerRequests = 24;
+const favicon_base::IconType kTestIconTypeForServerRequests =
+ favicon_base::IconType::kTouchIcon;
+const char kTestGoogleServerClientParam[] = "test_chrome";
+
ACTION(FailFetch) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(*arg2), gfx::Image(),
@@ -127,7 +132,7 @@ class IconCacherTestBase : public ::testing::Test {
loop.RunUntilIdle();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir history_dir_;
history::HistoryService history_service_;
favicon::FaviconServiceImpl favicon_service_;
@@ -351,14 +356,16 @@ TEST_F(IconCacherTestMostLikely, Cached) {
PreloadIcon(page_url, icon_url, favicon_base::IconType::kTouchIcon, 128, 128);
favicon::LargeIconServiceImpl large_icon_service(
- &favicon_service_, std::move(fetcher_for_large_icon_service_));
+ &favicon_service_, std::move(fetcher_for_large_icon_service_),
+ kTestDipForServerRequests, kTestIconTypeForServerRequests,
+ kTestGoogleServerClientParam);
IconCacherImpl cacher(&favicon_service_, &large_icon_service,
std::move(fetcher_for_icon_cacher_));
base::MockCallback<base::Closure> done;
EXPECT_CALL(done, Run()).Times(0);
cacher.StartFetchMostLikely(page_url, done.Get());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon));
EXPECT_TRUE(IconIsCachedFor(page_url, favicon_base::IconType::kTouchIcon));
@@ -380,7 +387,9 @@ TEST_F(IconCacherTestMostLikely, NotCachedAndFetchSucceeded) {
}
favicon::LargeIconServiceImpl large_icon_service(
- &favicon_service_, std::move(fetcher_for_large_icon_service_));
+ &favicon_service_, std::move(fetcher_for_large_icon_service_),
+ kTestDipForServerRequests, kTestIconTypeForServerRequests,
+ kTestGoogleServerClientParam);
IconCacherImpl cacher(&favicon_service_, &large_icon_service,
std::move(fetcher_for_icon_cacher_));
@@ -388,7 +397,7 @@ TEST_F(IconCacherTestMostLikely, NotCachedAndFetchSucceeded) {
// Both these task runners need to be flushed in order to get |done| called by
// running the main loop.
WaitForHistoryThreadTasksToFinish();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
loop.Run();
EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon));
@@ -410,7 +419,9 @@ TEST_F(IconCacherTestMostLikely, NotCachedAndFetchFailed) {
}
favicon::LargeIconServiceImpl large_icon_service(
- &favicon_service_, std::move(fetcher_for_large_icon_service_));
+ &favicon_service_, std::move(fetcher_for_large_icon_service_),
+ kTestDipForServerRequests, kTestIconTypeForServerRequests,
+ kTestGoogleServerClientParam);
IconCacherImpl cacher(&favicon_service_, &large_icon_service,
std::move(fetcher_for_icon_cacher_));
@@ -418,7 +429,7 @@ TEST_F(IconCacherTestMostLikely, NotCachedAndFetchFailed) {
// Both these task runners need to be flushed before flushing the main thread
// queue in order to finish the work.
WaitForHistoryThreadTasksToFinish();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon));
EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kTouchIcon));
@@ -431,7 +442,9 @@ TEST_F(IconCacherTestMostLikely, HandlesEmptyCallbacksNicely) {
.WillOnce(PassFetch(128, 128));
favicon::LargeIconServiceImpl large_icon_service(
- &favicon_service_, std::move(fetcher_for_large_icon_service_));
+ &favicon_service_, std::move(fetcher_for_large_icon_service_),
+ kTestDipForServerRequests, kTestIconTypeForServerRequests,
+ kTestGoogleServerClientParam);
IconCacherImpl cacher(&favicon_service_, &large_icon_service,
std::move(fetcher_for_icon_cacher_));
@@ -439,14 +452,14 @@ TEST_F(IconCacherTestMostLikely, HandlesEmptyCallbacksNicely) {
// Finish the posted tasks on the main and the history thread to find out if
// we can write the icon.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
WaitForHistoryThreadTasksToFinish();
// Continue with the work in large icon service - fetch and decode the data.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Do the work on the history thread to write down the icon
WaitForHistoryThreadTasksToFinish();
// Finish the tasks on the main thread.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Even though the callbacks are not called, the icon gets written out.
EXPECT_FALSE(IconIsCachedFor(page_url, favicon_base::IconType::kFavicon));
@@ -469,7 +482,9 @@ TEST_F(IconCacherTestMostLikely, NotCachedAndFetchPerformedOnlyOnce) {
}
favicon::LargeIconServiceImpl large_icon_service(
- &favicon_service_, std::move(fetcher_for_large_icon_service_));
+ &favicon_service_, std::move(fetcher_for_large_icon_service_),
+ kTestDipForServerRequests, kTestIconTypeForServerRequests,
+ kTestGoogleServerClientParam);
IconCacherImpl cacher(&favicon_service_, &large_icon_service,
std::move(fetcher_for_icon_cacher_));
@@ -478,10 +493,10 @@ TEST_F(IconCacherTestMostLikely, NotCachedAndFetchPerformedOnlyOnce) {
// Finish the posted tasks on the main and the history thread to find out if
// we can write the icon.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
WaitForHistoryThreadTasksToFinish();
// Continue with the work in large icon service - fetch and decode the data.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Do the work on the history thread to write down the icon
WaitForHistoryThreadTasksToFinish();
// Finish the tasks on the main thread.
diff --git a/chromium/components/ntp_tiles/most_visited_sites.cc b/chromium/components/ntp_tiles/most_visited_sites.cc
index f25abd58c16..b86f6e5845c 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites.cc
@@ -17,7 +17,6 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "components/history/core/browser/top_sites.h"
#include "components/ntp_tiles/constants.h"
#include "components/ntp_tiles/features.h"
#include "components/ntp_tiles/icon_cacher.h"
@@ -136,7 +135,6 @@ MostVisitedSites::MostVisitedSites(
supervisor_(std::move(supervisor)),
observer_(nullptr),
max_num_sites_(0u),
- top_sites_observer_(this),
mv_source_(TileSource::TOP_SITES) {
DCHECK(prefs_);
// top_sites_ can be null in tests.
diff --git a/chromium/components/ntp_tiles/most_visited_sites.h b/chromium/components/ntp_tiles/most_visited_sites.h
index 537213f9adb..5bdf52c1715 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.h
+++ b/chromium/components/ntp_tiles/most_visited_sites.h
@@ -24,6 +24,7 @@
#include "base/scoped_observer.h"
#include "base/strings/string16.h"
#include "components/history/core/browser/history_types.h"
+#include "components/history/core/browser/top_sites.h"
#include "components/history/core/browser/top_sites_observer.h"
#include "components/ntp_tiles/custom_links_manager.h"
#include "components/ntp_tiles/ntp_tile.h"
@@ -34,10 +35,6 @@
#include "components/suggestions/suggestions_service.h"
#include "url/gurl.h"
-namespace history {
-class TopSites;
-}
-
namespace user_prefs {
class PrefRegistrySyncable;
}
@@ -364,7 +361,7 @@ class MostVisitedSites : public history::TopSitesObserver,
suggestions_subscription_;
ScopedObserver<history::TopSites, history::TopSitesObserver>
- top_sites_observer_;
+ top_sites_observer_{this};
std::unique_ptr<base::CallbackList<void()>::Subscription>
custom_links_subscription_;
diff --git a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
index e099000df8b..2c318f50de8 100644
--- a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -22,7 +22,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/history/core/browser/top_sites.h"
@@ -559,7 +559,7 @@ class MostVisitedSitesTest : public ::testing::TestWithParam<bool> {
suggestions_service_callbacks_;
TopSitesCallbackList top_sites_callbacks_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
PopularSitesFactoryForTest popular_sites_factory_;
diff --git a/chromium/components/ntp_tiles/popular_sites_impl.cc b/chromium/components/ntp_tiles/popular_sites_impl.cc
index 8d17dff3969..0e1cc6e429f 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl.cc
@@ -5,6 +5,7 @@
#include "components/ntp_tiles/popular_sites_impl.h"
#include <stddef.h>
+
#include <map>
#include <memory>
#include <utility>
@@ -18,6 +19,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/google/core/common/google_util.h"
#include "components/ntp_tiles/features.h"
@@ -195,7 +197,8 @@ std::map<SectionType, PopularSites::SitesVector> ParseSites(
return ParseVersion5(list);
}
-#if defined(GOOGLE_CHROME_BUILD) && (defined(OS_ANDROID) || defined(OS_IOS))
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && \
+ (defined(OS_ANDROID) || defined(OS_IOS))
void SetDefaultResourceForSite(int index,
int resource_id,
base::ListValue* sites) {
@@ -224,7 +227,7 @@ base::Value DefaultPopularSites() {
base::DictionaryValue& dict = static_cast<base::DictionaryValue&>(site);
dict.SetBoolean("baked_in", true);
}
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
int index = 0;
for (int icon_resource :
{IDR_DEFAULT_POPULAR_SITES_ICON0, IDR_DEFAULT_POPULAR_SITES_ICON1,
@@ -233,7 +236,7 @@ base::Value DefaultPopularSites() {
IDR_DEFAULT_POPULAR_SITES_ICON6, IDR_DEFAULT_POPULAR_SITES_ICON7}) {
SetDefaultResourceForSite(index++, icon_resource, sites.get());
}
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
return base::Value::FromUniquePtrValue(std::move(sites));
#endif // OS_ANDROID || OS_IOS
}
@@ -443,7 +446,7 @@ void PopularSitesImpl::FetchPopularSites() {
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = pending_url_;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
simple_url_loader_->SetRetryOptions(
diff --git a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
index b965d6b611d..ce0748b55e6 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
@@ -18,9 +18,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/ntp_tiles/features.h"
#include "components/ntp_tiles/pref_names.h"
@@ -211,8 +212,8 @@ class PopularSitesTest : public ::testing::Test {
const TestPopularSite kYouTube;
const TestPopularSite kChromium;
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
data_decoder::TestingJsonParser::ScopedFactoryOverride factory_override_;
std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
@@ -308,7 +309,7 @@ TEST_F(PopularSitesTest, AddsIconResourcesToDefaultPages) {
ASSERT_FALSE(sites.empty());
for (const auto& site : sites) {
EXPECT_TRUE(site.baked_in);
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
EXPECT_THAT(site.default_icon_resource, Gt(0));
#endif
}
diff --git a/chromium/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java b/chromium/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
index e3582fff65a..8c88e59575d 100644
--- a/chromium/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
+++ b/chromium/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
@@ -6,6 +6,7 @@ package org.chromium.components.offline_items_collection.bridges;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
+import org.chromium.components.offline_items_collection.FailState;
import org.chromium.components.offline_items_collection.OfflineItem;
import org.chromium.components.offline_items_collection.OfflineItemFilter;
import org.chromium.components.offline_items_collection.OfflineItemProgressUnit;
@@ -50,8 +51,8 @@ public final class OfflineItemBridge {
boolean externallyRemoved, long creationTimeMs, long completionTimeMs,
long lastAccessedTimeMs, boolean isOpenable, String filePath, String mimeType,
String pageUrl, String originalUrl, boolean isOffTheRecord, @OfflineItemState int state,
- @PendingState int pendingState, boolean isResumable, boolean allowMetered,
- long receivedBytes, long progressValue, long progressMax,
+ @FailState int failState, @PendingState int pendingState, boolean isResumable,
+ boolean allowMetered, long receivedBytes, long progressValue, long progressMax,
@OfflineItemProgressUnit int progressUnit, long timeRemainingMs, boolean isDangerous,
boolean canRename) {
OfflineItem item = new OfflineItem();
@@ -76,6 +77,7 @@ public final class OfflineItemBridge {
item.originalUrl = originalUrl;
item.isOffTheRecord = isOffTheRecord;
item.state = state;
+ item.failState = failState;
item.pendingState = pendingState;
item.isResumable = isResumable;
item.allowMetered = allowMetered;
diff --git a/chromium/components/offline_items_collection/core/android/offline_item_bridge.cc b/chromium/components/offline_items_collection/core/android/offline_item_bridge.cc
index b218162245e..df787dc35f8 100644
--- a/chromium/components/offline_items_collection/core/android/offline_item_bridge.cc
+++ b/chromium/components/offline_items_collection/core/android/offline_item_bridge.cc
@@ -41,10 +41,11 @@ JNI_OfflineItemBridge_createOfflineItemAndMaybeAddToList(
ConvertUTF8ToJavaString(env, item.page_url.spec()),
ConvertUTF8ToJavaString(env, item.original_url.spec()),
item.is_off_the_record, static_cast<jint>(item.state),
- static_cast<jint>(item.pending_state), item.is_resumable,
- item.allow_metered, item.received_bytes, item.progress.value,
- item.progress.max.value_or(-1), static_cast<jint>(item.progress.unit),
- item.time_remaining_ms, item.is_dangerous, item.can_rename);
+ static_cast<jint>(item.fail_state), static_cast<jint>(item.pending_state),
+ item.is_resumable, item.allow_metered, item.received_bytes,
+ item.progress.value, item.progress.max.value_or(-1),
+ static_cast<jint>(item.progress.unit), item.time_remaining_ms,
+ item.is_dangerous, item.can_rename);
}
} // namespace
diff --git a/chromium/components/offline_pages/content/renovations/render_frame_script_injector.cc b/chromium/components/offline_pages/content/renovations/render_frame_script_injector.cc
index ee6170b679c..cb4de99a18d 100644
--- a/chromium/components/offline_pages/content/renovations/render_frame_script_injector.cc
+++ b/chromium/components/offline_pages/content/renovations/render_frame_script_injector.cc
@@ -17,7 +17,7 @@ namespace offline_pages {
RenderFrameScriptInjector::RenderFrameScriptInjector(
content::RenderFrameHost* render_frame_host,
- int isolated_world_id)
+ int32_t isolated_world_id)
: render_frame_host_(render_frame_host),
isolated_world_id_(isolated_world_id) {
DCHECK(render_frame_host_);
diff --git a/chromium/components/offline_pages/content/renovations/render_frame_script_injector.h b/chromium/components/offline_pages/content/renovations/render_frame_script_injector.h
index 4417ae309ae..e572ee1c7a6 100644
--- a/chromium/components/offline_pages/content/renovations/render_frame_script_injector.h
+++ b/chromium/components/offline_pages/content/renovations/render_frame_script_injector.h
@@ -22,14 +22,14 @@ class RenderFrameScriptInjector : public ScriptInjector {
// The |render_frame_host| is expected to outlive this
// RenderFrameScriptInjector instance.
RenderFrameScriptInjector(content::RenderFrameHost* render_frame_host,
- int isolated_world_id);
+ int32_t isolated_world_id);
// ScriptInjector implementation.
void Inject(base::string16 script, ResultCallback callback) override;
private:
content::RenderFrameHost* render_frame_host_;
- int isolated_world_id_;
+ int32_t isolated_world_id_;
};
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc b/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc
index e1ecaf0ed8f..bef904d0419 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -230,12 +230,23 @@ void OfflinePageModelTaskified::SavePage(
create_archive_params.use_page_problem_detectors =
save_page_params.use_page_problem_detectors;
+ // Set on-the-fly hashing if enabled.
+ create_archive_params.use_on_the_fly_hash_computation =
+ IsOnTheFlyMhtmlHashComputationEnabled();
+
+ // Save directly to public location if on-the-fly enabled.
+ //
+ // TODO(crbug.com/999247): We would like to skip renaming the file if
+ // streaming the file directly to it's end location. Knowing the file path or
+ // name before calling the archiver would make this possible.
+ base::FilePath save_file_dir =
+ GetArchiveDirectory(save_page_params.client_id.name_space);
+
// Note: the archiver instance must be kept alive until the final callback
// coming from it takes place.
OfflinePageArchiver* raw_archiver = archiver.get();
raw_archiver->CreateArchive(
- GetInternalArchiveDirectory(save_page_params.client_id.name_space),
- create_archive_params, web_contents,
+ save_file_dir, create_archive_params, web_contents,
base::BindOnce(&OfflinePageModelTaskified::OnCreateArchiveDone,
weak_ptr_factory_.GetWeakPtr(), save_page_params,
offline_id, OfflineTimeNow(), std::move(archiver),
@@ -349,10 +360,12 @@ void OfflinePageModelTaskified::GetVisualsAvailability(
store_.get(), offline_id, std::move(callback)));
}
-const base::FilePath& OfflinePageModelTaskified::GetInternalArchiveDirectory(
+const base::FilePath& OfflinePageModelTaskified::GetArchiveDirectory(
const std::string& name_space) const {
if (GetPolicy(name_space).lifetime_type == LifetimeType::TEMPORARY)
return archive_manager_->GetTemporaryArchivesDir();
+ if (IsOnTheFlyMhtmlHashComputationEnabled())
+ return archive_manager_->GetPublicArchivesDir();
return archive_manager_->GetPrivateArchivesDir();
}
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_taskified.h b/chromium/components/offline_pages/core/model/offline_page_model_taskified.h
index ba8b37561e7..dbca3ef3400 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_taskified.h
+++ b/chromium/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -102,7 +102,7 @@ class OfflinePageModelTaskified : public OfflinePageModel,
void GetVisualsAvailability(
int64_t offline_id,
base::OnceCallback<void(VisualsAvailability)> callback) override;
- const base::FilePath& GetInternalArchiveDirectory(
+ const base::FilePath& GetArchiveDirectory(
const std::string& name_space) const override;
bool IsArchiveInInternalDir(const base::FilePath& file_path) const override;
OfflineEventLogger* GetLogger() override;
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc b/chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
index e0b5dc803b9..7989210962b 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
@@ -1240,10 +1240,10 @@ TEST_F(OfflinePageModelTaskifiedTest, ExtraActionTriggeredWhenSaveSuccess) {
TEST_F(OfflinePageModelTaskifiedTest, GetArchiveDirectory) {
base::FilePath temporary_dir =
- model()->GetInternalArchiveDirectory(kDefaultNamespace);
+ model()->GetArchiveDirectory(kDefaultNamespace);
EXPECT_EQ(temporary_dir_path(), temporary_dir);
base::FilePath persistent_dir =
- model()->GetInternalArchiveDirectory(kDownloadNamespace);
+ model()->GetArchiveDirectory(kDownloadNamespace);
EXPECT_EQ(private_archive_dir_path(), persistent_dir);
}
diff --git a/chromium/components/offline_pages/core/model/offline_page_model_utils.cc b/chromium/components/offline_pages/core/model/offline_page_model_utils.cc
index 6785f1a4d55..d0783e529bc 100644
--- a/chromium/components/offline_pages/core/model/offline_page_model_utils.cc
+++ b/chromium/components/offline_pages/core/model/offline_page_model_utils.cc
@@ -74,8 +74,7 @@ base::FilePath GenerateUniqueFilenameForOfflinePage(
title, url, false /* can_save_as_complete */, kMHTMLMimeType));
// Find a unique name based on |suggested_path|.
- int uniquifier =
- base::GetUniquePathNumber(suggested_path, base::FilePath::StringType());
+ int uniquifier = base::GetUniquePathNumber(suggested_path);
base::FilePath::StringType suffix;
if (uniquifier > 0)
#if defined(OS_WIN)
diff --git a/chromium/components/offline_pages/core/offline_page_archiver.h b/chromium/components/offline_pages/core/offline_page_archiver.h
index 4f5e7b237b9..9efe6540697 100644
--- a/chromium/components/offline_pages/core/offline_page_archiver.h
+++ b/chromium/components/offline_pages/core/offline_page_archiver.h
@@ -72,6 +72,9 @@ class OfflinePageArchiver {
// Run page problem detectors while generating MTHML if true.
bool use_page_problem_detectors = false;
+
+ // Whether to enable on-the-fly hash computation.
+ bool use_on_the_fly_hash_computation = false;
};
// Callback for the final result of an attempt to generate of offline page
diff --git a/chromium/components/offline_pages/core/offline_page_model.h b/chromium/components/offline_pages/core/offline_page_model.h
index 86c8e5abb36..b5ab57172c8 100644
--- a/chromium/components/offline_pages/core/offline_page_model.h
+++ b/chromium/components/offline_pages/core/offline_page_model.h
@@ -191,7 +191,7 @@ class OfflinePageModel : public base::SupportsUserData, public KeyedService {
PublishPageCallback publish_done_callback) = 0;
// Get the archive directory based on client policy of the namespace.
- virtual const base::FilePath& GetInternalArchiveDirectory(
+ virtual const base::FilePath& GetArchiveDirectory(
const std::string& name_space) const = 0;
// Returns whether given archive file is in the internal directory.
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
index 3c0c0575131..caf584875a5 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -100,9 +100,8 @@ void PrefetchDispatcherImpl::AddCandidatePrefetchURLs(
const std::string& name_space,
const std::vector<PrefetchURL>& prefetch_urls) {
if (!prefetch_prefs::IsEnabled(pref_service_)) {
- if (prefetch_prefs::IsForbiddenCheckDue(pref_service_)) {
+ if (prefetch_prefs::IsForbiddenCheckDue(pref_service_))
CheckIfEnabledByServer(pref_service_, service_);
- }
return;
}
@@ -134,6 +133,14 @@ void PrefetchDispatcherImpl::AddCandidatePrefetchURLs(
void PrefetchDispatcherImpl::NewSuggestionsAvailable(
SuggestionsProvider* suggestions_provider) {
+ // No need to GetKnownContent if prefetching is disabled (however, we don't
+ // want to prevent the server-forbidden check).
+ if (!prefetch_prefs::IsEnabled(pref_service_)) {
+ if (prefetch_prefs::IsForbiddenCheckDue(pref_service_))
+ CheckIfEnabledByServer(pref_service_, service_);
+ return;
+ }
+
suggestions_provider->GetCurrentArticleSuggestions(
base::BindOnce(&PrefetchDispatcherImpl::AddSuggestions, GetWeakPtr()));
}
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc
index 69bc7ca3471..0fa6de7cf10 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_gcm_app_handler_unittest.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/gcm_driver/instance_id/instance_id.h"
#include "components/offline_pages/core/prefetch/prefetch_service_test_taco.h"
#include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h"
@@ -54,7 +54,7 @@ class PrefetchGCMAppHandlerTest : public testing::Test {
~PrefetchGCMAppHandlerTest() override {
// Ensures that the store is properly disposed off.
prefetch_service_taco_.reset();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TestPrefetchDispatcher* dispatcher() { return test_dispatcher_; }
@@ -62,7 +62,7 @@ class PrefetchGCMAppHandlerTest : public testing::Test {
TestTokenFactory* token_factory() { return token_factory_; }
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<PrefetchServiceTestTaco> prefetch_service_taco_;
// Owned by the taco.
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl.cc b/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl.cc
index 99b6d5750f3..3e5d88620d1 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl.cc
@@ -76,8 +76,7 @@ void PrefetchImporterImpl::ImportArchive(const PrefetchArchiveInfo& archive) {
// The target file name will be auto generated based on GUID to prevent any
// name collision.
base::FilePath archives_dir =
- offline_page_model_->GetInternalArchiveDirectory(
- archive.client_id.name_space);
+ offline_page_model_->GetArchiveDirectory(archive.client_id.name_space);
base::FilePath dest_path = archives_dir.AppendASCII(base::GenerateGUID())
.AddExtension(FILE_PATH_LITERAL("mhtml"));
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
index d683cbe6b1e..b0ea704fdae 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
@@ -50,7 +50,7 @@ class TestOfflinePageModel : public StubOfflinePageModel {
page.offline_id);
}
- const base::FilePath& GetInternalArchiveDirectory(
+ const base::FilePath& GetArchiveDirectory(
const std::string& name_space) const override {
return archive_dir_.GetPath();
}
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc b/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
index 275192043bd..19db6e53043 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher.cc
@@ -86,7 +86,7 @@ PrefetchRequestFetcher::PrefetchRequestFetcher(
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
resource_request->method = message.empty() ? "GET" : "POST";
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
std::string experiment_header = PrefetchExperimentHeader();
if (!experiment_header.empty())
diff --git a/chromium/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc b/chromium/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
index 664ae3d12bb..d589325e21e 100644
--- a/chromium/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
@@ -6,7 +6,7 @@
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/prefetch/prefetch_dispatcher.h"
#include "components/offline_pages/core/prefetch/prefetch_gcm_app_handler.h"
@@ -52,7 +52,7 @@ class OfflinePageSuggestedArticlesObserverTest : public testing::Test {
~OfflinePageSuggestedArticlesObserverTest() override {
// Ensure the store can be properly disposed off.
prefetch_service_test_taco_.reset();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
SuggestedArticlesObserver* observer() {
@@ -69,7 +69,7 @@ class OfflinePageSuggestedArticlesObserverTest : public testing::Test {
Category::FromKnownCategory(ntp_snippets::KnownCategories::ARTICLES);
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<PrefetchServiceTestTaco> prefetch_service_test_taco_;
// Owned by the PrefetchServiceTestTaco.
diff --git a/chromium/components/offline_pages/core/stub_offline_page_model.cc b/chromium/components/offline_pages/core/stub_offline_page_model.cc
index 7163dc28a56..7474de87bde 100644
--- a/chromium/components/offline_pages/core/stub_offline_page_model.cc
+++ b/chromium/components/offline_pages/core/stub_offline_page_model.cc
@@ -55,7 +55,7 @@ void StubOfflinePageModel::GetVisualsAvailability(
void StubOfflinePageModel::PublishInternalArchive(
const OfflinePageItem& offline_page,
PublishPageCallback publish_done_callback) {}
-const base::FilePath& StubOfflinePageModel::GetInternalArchiveDirectory(
+const base::FilePath& StubOfflinePageModel::GetArchiveDirectory(
const std::string& name_space) const {
return archive_directory_;
}
diff --git a/chromium/components/offline_pages/core/stub_offline_page_model.h b/chromium/components/offline_pages/core/stub_offline_page_model.h
index 05e207e8302..91d7caa907c 100644
--- a/chromium/components/offline_pages/core/stub_offline_page_model.h
+++ b/chromium/components/offline_pages/core/stub_offline_page_model.h
@@ -53,7 +53,7 @@ class StubOfflinePageModel : public OfflinePageModel {
void PublishInternalArchive(
const OfflinePageItem& offline_page,
PublishPageCallback publish_done_callback) override;
- const base::FilePath& GetInternalArchiveDirectory(
+ const base::FilePath& GetArchiveDirectory(
const std::string& name_space) const override;
bool IsArchiveInInternalDir(const base::FilePath& file_path) const override;
OfflineEventLogger* GetLogger() override;
diff --git a/chromium/components/onc/OWNERS b/chromium/components/onc/OWNERS
index ae9ccd55c9c..29efca1637d 100644
--- a/chromium/components/onc/OWNERS
+++ b/chromium/components/onc/OWNERS
@@ -2,3 +2,4 @@ armansito@chromium.org
gauravsh@chromium.org
gspencer@chromium.org
stevenjb@chromium.org
+# COMPONENT: UI>Shell>Networking
diff --git a/chromium/components/onc/docs/onc_spec.md b/chromium/components/onc/docs/onc_spec.md
index 5529b7f96ba..fde3afbe8a7 100644
--- a/chromium/components/onc/docs/onc_spec.md
+++ b/chromium/components/onc/docs/onc_spec.md
@@ -194,7 +194,6 @@ warns admins of the implications of mis-using this policy for Chrome OS.
* Cellular
* Ethernet
* WiFi
- * WiMAX
* Tether
* List of strings containing disabled network interfaces.
@@ -278,11 +277,6 @@ Field **NetworkConfigurations** is an array of
* (required if **Type** is *WiFi*, otherwise ignored) - [WiFi](#WiFi-type)
* WiFi settings.
-* **WiMAX**
- * (required if **Type** is *WiMAX*, otherwise ignored) -
- [WiMAX](#WiMAX-type)
- * WiMAX settings.
-
* **Cellular**
* (required if **Type** is *Cellular*, otherwise ignored) -
[Cellular](#Cellular-type)
@@ -299,7 +293,6 @@ Field **NetworkConfigurations** is an array of
* *Cellular*
* *Ethernet*
* *WiFi*
- * *WiMAX*
* *VPN*
* Indicates which kind of connection this is.
@@ -1307,33 +1300,6 @@ type exists to configure the authentication.
can be set.
---
-## WiMAX Networks
-
-For WiMAX connections, **Type** must be set to
-*WiMAX* and the field **WiMAX** must be set to an object of
-type [WiMAX](#WiMAX-type).
-
-Currently only used for representing an existing configuration;
-ONC configuration of of **WiMAX** networks is not yet fully supported.
-
-### WiMAX type
-
-* **AutoConnect**
- * (optional, defaults to *false*) - **boolean**
- * Indicating that the network should be connected to automatically when
- possible.
-
-* **EAP**
- * (required) - [EAP](#EAP-type)
- * EAP settings.
-
-* **SignalStrength**
- * (optional, read-only) - **integer**
- * The current signal strength for this network in the range [0, 100],
- provided by the system. If the network is not in range this field will
- be set to '0' or not present.
-
-
## Cellular Networks
For Cellular connections, **Type** must be set to *Cellular* and the
@@ -1470,10 +1436,6 @@ ONC configuration of of **Cellular** networks is not yet supported.
* Properties describing the online payment portal (OLP) at which a user can
sign up for or modify a mobile data plan.
-* **PRLVersion**
- * (optional, read-only) - **integer**
- * The revision of the Preferred Roaming List that is loaded in the modem.
-
* **RoamingState**
* (optional, read-only) - **string**
* The roaming status of the cellular modem on the current network.
@@ -1685,6 +1647,11 @@ objects of [Certificate](#Certificate-type) type.
* If *true*, remove this certificate (only GUID
should be set).
+* **Scope**
+ * (optional, default Scope if missing) - [Scope](#Scope-type)
+ * If this is given, it specifies the scope in which the certificate should
+ be applied.
+
* **TrustBits**
* (optional if **Type**
is *Server*
@@ -1726,6 +1693,21 @@ objects of [Certificate](#Certificate-type) type.
results are undefined, so this configuration should be prohibited by the
configuration editor.
+### Scope type
+* **Id**
+ * (required if **Type** is *Extension*, otherwise ignored) - **string**
+ * If *Type* is *Extension*, this is the ID of the chrome extension for which
+ the certificate should be applied.
+* **Type**
+ * (required) - **string**
+ * Allowed values are:
+ * *Extension*
+ * *Default*
+ * *Extension* indicates that the certificate should only be applied in the
+ scope of a chrome extension.
+ *Default* indicates that the scope the certificate applies in should not
+ be restricted.
+
## Encrypted Configuration
@@ -1907,8 +1889,7 @@ particular PKCS#11 token, and tying to one OS's connection manager.
In this example, we only allow managed networks to auto connect and
disallow any other networks if a managed network is available. We also blacklist
-the "Guest" network (hex("Guest")=4775657374) and disable Cellular and WiMAX
-services.
+the "Guest" network (hex("Guest")=4775657374) and disable Cellular services.
```
{
"Type": "UnencryptedConfiguration",
@@ -1917,7 +1898,7 @@ services.
“AllowOnlyPolicyNetworksToConnect”: false,
“AllowOnlyPolicyNetworksToConnectIfAvailable”: true,
“BlacklistedHexSSIDs”: [“4775657374”],
- "DisableNetworkTypes": ["Cellular", "WiMAX"]
+ "DisableNetworkTypes": ["Cellular"]
}
}
```
diff --git a/chromium/components/onc/onc_constants.cc b/chromium/components/onc/onc_constants.cc
index 076be5bcf61..38e0e00d4ef 100644
--- a/chromium/components/onc/onc_constants.cc
+++ b/chromium/components/onc/onc_constants.cc
@@ -63,7 +63,7 @@ const char kTether[] = "Tether";
const char kType[] = "Type";
const char kVPN[] = "VPN";
const char kWiFi[] = "WiFi";
-const char kWimax[] = "WiMAX";
+const char kWimaxDeprecated[] = "WiMAX";
std::string CellularProperty(const std::string& property) {
return std::string(kCellular) + "." + property;
@@ -90,7 +90,7 @@ const char kEthernet[] = "Ethernet";
const char kTether[] = "Tether";
const char kVPN[] = "VPN";
const char kWiFi[] = "WiFi";
-const char kWimax[] = "WiMAX";
+const char kWimaxDeprecated[] = "WiMAX";
const char kWireless[] = "Wireless";
} // namespace network_type
@@ -123,7 +123,6 @@ const char kMIN[] = "MIN";
const char kModelID[] = "ModelID";
const char kNetworkTechnology[] = "NetworkTechnology";
const char kPaymentPortal[] = "PaymentPortal";
-const char kPRLVersion[] = "PRLVersion";
const char kRoamingHome[] = "Home";
const char kRoamingRequired[] = "Required";
const char kRoamingRoaming[] = "Roaming";
@@ -240,11 +239,11 @@ const char kWPA_PSK[] = "WPA-PSK";
const char kWPA2_PSK[] = "WPA2-PSK";
} // namespace wifi
-namespace wimax {
+// Deprecated, properties exist for ignoring old ONC config entries.
+namespace wimax_deprecated {
const char kAutoConnect[] = "AutoConnect";
const char kEAP[] = "EAP";
-const char kSignalStrength[] = "SignalStrength";
-} // namespace wimax
+} // namespace wimax_deprecated
namespace client_cert {
const char kClientCertPattern[] = "ClientCertPattern";
@@ -272,6 +271,7 @@ const char kAuthority[] = "Authority";
const char kClient[] = "Client";
const char kGUID[] = "GUID";
const char kPKCS12[] = "PKCS12";
+const char kScope[] = "Scope";
const char kServer[] = "Server";
const char kTrustBits[] = "TrustBits";
const char kType[] = "Type";
@@ -279,6 +279,13 @@ const char kWeb[] = "Web";
const char kX509[] = "X509";
} // namespace certificate
+namespace scope {
+const char kDefault[] = "Default";
+const char kExtension[] = "Extension";
+const char kId[] = "Id";
+const char kType[] = "Type";
+} // namespace scope
+
namespace encrypted {
const char kAES256[] = "AES256";
const char kCipher[] = "Cipher";
diff --git a/chromium/components/onc/onc_constants.h b/chromium/components/onc/onc_constants.h
index f40f13c1fa9..868df30c7f2 100644
--- a/chromium/components/onc/onc_constants.h
+++ b/chromium/components/onc/onc_constants.h
@@ -86,7 +86,7 @@ ONC_EXPORT extern const char kTether[];
ONC_EXPORT extern const char kType[];
ONC_EXPORT extern const char kVPN[];
ONC_EXPORT extern const char kWiFi[];
-ONC_EXPORT extern const char kWimax[];
+ONC_EXPORT extern const char kWimaxDeprecated[];
ONC_EXPORT extern std::string CellularProperty(const std::string& property);
ONC_EXPORT extern std::string TetherProperty(const std::string& property);
@@ -101,7 +101,7 @@ ONC_EXPORT extern const char kEthernet[];
ONC_EXPORT extern const char kTether[];
ONC_EXPORT extern const char kVPN[];
ONC_EXPORT extern const char kWiFi[];
-ONC_EXPORT extern const char kWimax[];
+ONC_EXPORT extern const char kWimaxDeprecated[];
// Patterns matching multiple types, not part of the ONC spec.
ONC_EXPORT extern const char kAllTypes[];
ONC_EXPORT extern const char kWireless[];
@@ -136,7 +136,6 @@ ONC_EXPORT extern const char kMIN[];
ONC_EXPORT extern const char kModelID[];
ONC_EXPORT extern const char kNetworkTechnology[];
ONC_EXPORT extern const char kPaymentPortal[];
-ONC_EXPORT extern const char kPRLVersion[];
ONC_EXPORT extern const char kRoamingHome[];
ONC_EXPORT extern const char kRoamingRequired[];
ONC_EXPORT extern const char kRoamingRoaming[];
@@ -253,11 +252,10 @@ ONC_EXPORT extern const char kWPA2_PSK[];
ONC_EXPORT extern const char kWPA_EAP[];
} // namespace wifi
-namespace wimax {
+namespace wimax_deprecated {
ONC_EXPORT extern const char kAutoConnect[];
ONC_EXPORT extern const char kEAP[];
-ONC_EXPORT extern const char kSignalStrength[];
-} // namespace wimax
+} // namespace wimax_deprecated
namespace client_cert {
ONC_EXPORT extern const char kClientCertPattern[];
@@ -285,6 +283,7 @@ ONC_EXPORT extern const char kAuthority[];
ONC_EXPORT extern const char kClient[];
ONC_EXPORT extern const char kGUID[];
ONC_EXPORT extern const char kPKCS12[];
+ONC_EXPORT extern const char kScope[];
ONC_EXPORT extern const char kServer[];
ONC_EXPORT extern const char kTrustBits[];
ONC_EXPORT extern const char kType[];
@@ -292,6 +291,13 @@ ONC_EXPORT extern const char kWeb[];
ONC_EXPORT extern const char kX509[];
} // namespace certificate
+namespace scope {
+ONC_EXPORT extern const char kDefault[];
+ONC_EXPORT extern const char kExtension[];
+ONC_EXPORT extern const char kId[];
+ONC_EXPORT extern const char kType[];
+} // namespace scope
+
namespace encrypted {
ONC_EXPORT extern const char kAES256[];
ONC_EXPORT extern const char kCipher[];
diff --git a/chromium/components/open_from_clipboard/OWNERS b/chromium/components/open_from_clipboard/OWNERS
index f566e77b29f..730ca68a2cc 100644
--- a/chromium/components/open_from_clipboard/OWNERS
+++ b/chromium/components/open_from_clipboard/OWNERS
@@ -1 +1,3 @@
-olivierrobin@chromium.org \ No newline at end of file
+olivierrobin@chromium.org
+# COMPONENT: UI>Browser>Omnibox>ZeroSuggest
+# TEAM: ios-directory-owners@chromium.org
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc b/chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc
index 5fab0b935e7..97db9cdf3ad 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc
@@ -30,7 +30,7 @@ ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
// Get and clean up the clipboard before processing.
std::string gurl_string;
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- clipboard->ReadAsciiText(ui::ClipboardType::kCopyPaste, &gurl_string);
+ clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, &gurl_string);
base::TrimWhitespaceASCII(gurl_string, base::TrimPositions::TRIM_ALL,
&gurl_string);
@@ -48,7 +48,7 @@ ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
// Fall back to unicode / UTF16, as some URLs may use international domain
// names, not punycode.
base::string16 gurl_string16;
- clipboard->ReadText(ui::ClipboardType::kCopyPaste, &gurl_string16);
+ clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &gurl_string16);
base::TrimWhitespace(gurl_string16, base::TrimPositions::TRIM_ALL,
&gurl_string16);
if (gurl_string16.find_first_of(base::kWhitespaceUTF16) !=
@@ -65,7 +65,19 @@ ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
base::Optional<base::string16>
ClipboardRecentContentGeneric::GetRecentTextFromClipboard() {
- return base::nullopt;
+ if (GetClipboardContentAge() > MaximumAgeOfClipboard())
+ return base::nullopt;
+
+ base::string16 text_from_clipboard;
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::ClipboardBuffer::kCopyPaste, &text_from_clipboard);
+ base::TrimWhitespace(text_from_clipboard, base::TrimPositions::TRIM_ALL,
+ &text_from_clipboard);
+ if (text_from_clipboard.empty()) {
+ return base::nullopt;
+ }
+
+ return text_from_clipboard;
}
base::Optional<gfx::Image>
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc b/chromium/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
index cb2a7d9812d..febd864cfd3 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
@@ -9,6 +9,7 @@
#include "base/stl_util.h"
#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/test/test_clipboard.h"
@@ -118,3 +119,17 @@ TEST_F(ClipboardRecentContentGenericTest, SuppressClipboardContent) {
test_clipboard_->SetLastModifiedTime(now);
EXPECT_TRUE(recent_content.GetRecentURLFromClipboard().has_value());
}
+
+TEST_F(ClipboardRecentContentGenericTest, GetRecentTextFromClipboard) {
+ // Make sure the Text is suggested.
+ ClipboardRecentContentGeneric recent_content;
+ base::Time now = base::Time::Now();
+ std::string text = " Foo Bar ";
+ test_clipboard_->WriteText(text.data(), text.length());
+ test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromSeconds(10));
+ EXPECT_TRUE(recent_content.GetRecentTextFromClipboard().has_value());
+ EXPECT_STREQ(
+ "Foo Bar",
+ base::UTF16ToUTF8(recent_content.GetRecentTextFromClipboard().value())
+ .c_str());
+}
diff --git a/chromium/components/optimization_guide/BUILD.gn b/chromium/components/optimization_guide/BUILD.gn
index a8b92a6d17d..972ec5d8279 100644
--- a/chromium/components/optimization_guide/BUILD.gn
+++ b/chromium/components/optimization_guide/BUILD.gn
@@ -8,6 +8,8 @@ static_library("optimization_guide") {
sources = [
"bloom_filter.cc",
"bloom_filter.h",
+ "command_line_top_host_provider.cc",
+ "command_line_top_host_provider.h",
"hint_cache.cc",
"hint_cache.h",
"hint_cache_store.cc",
@@ -21,10 +23,12 @@ static_library("optimization_guide") {
"hints_fetcher.h",
"hints_processing_util.cc",
"hints_processing_util.h",
- "host_filter.cc",
- "host_filter.h",
+ "optimization_filter.cc",
+ "optimization_filter.h",
"optimization_guide_constants.cc",
"optimization_guide_constants.h",
+ "optimization_guide_decider.h",
+ "optimization_guide_enums.h",
"optimization_guide_features.cc",
"optimization_guide_features.h",
"optimization_guide_prefs.cc",
@@ -39,6 +43,10 @@ static_library("optimization_guide") {
"url_pattern_with_wildcards.h",
]
+ public_deps = [
+ "//third_party/re2",
+ ]
+
deps = [
"//base",
"//components/leveldb_proto",
@@ -74,13 +82,14 @@ source_set("unit_tests") {
testonly = true
sources = [
"bloom_filter_unittest.cc",
+ "command_line_top_host_provider_unittest.cc",
"hint_cache_store_unittest.cc",
"hint_cache_unittest.cc",
"hint_update_data_unittest.cc",
"hints_component_util_unittest.cc",
"hints_fetcher_unittest.cc",
"hints_processing_util_unittest.cc",
- "host_filter_unittest.cc",
+ "optimization_filter_unittest.cc",
"optimization_guide_features_unittest.cc",
"optimization_guide_service_unittest.cc",
"optimization_guide_switches_unittest.cc",
diff --git a/chromium/components/optimization_guide/DEPS b/chromium/components/optimization_guide/DEPS
index 5f16a1568b6..37a9b834f4c 100644
--- a/chromium/components/optimization_guide/DEPS
+++ b/chromium/components/optimization_guide/DEPS
@@ -5,5 +5,6 @@ include_rules = [
"+google_apis",
"+net",
"+services/network",
+ "+third_party/re2",
"+third_party/smhasher",
]
diff --git a/chromium/components/optimization_guide/OWNERS b/chromium/components/optimization_guide/OWNERS
index fd70f95f7d4..5ade4011608 100644
--- a/chromium/components/optimization_guide/OWNERS
+++ b/chromium/components/optimization_guide/OWNERS
@@ -1,3 +1,3 @@
file://components/previews/OWNERS
-# COMPONENT: Blink>Previews
+# COMPONENT: Internals>OptimizationGuide
diff --git a/chromium/components/optimization_guide/command_line_top_host_provider.cc b/chromium/components/optimization_guide/command_line_top_host_provider.cc
new file mode 100644
index 00000000000..7eb324b47e4
--- /dev/null
+++ b/chromium/components/optimization_guide/command_line_top_host_provider.cc
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/optimization_guide/command_line_top_host_provider.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "components/optimization_guide/optimization_guide_switches.h"
+
+namespace optimization_guide {
+
+// static
+std::unique_ptr<CommandLineTopHostProvider>
+CommandLineTopHostProvider::CreateIfEnabled() {
+ base::Optional<std::vector<std::string>> top_hosts =
+ switches::ParseHintsFetchOverrideFromCommandLine();
+ if (top_hosts) {
+ // Note: wrap_unique is used because the constructor is private.
+ return base::WrapUnique(new CommandLineTopHostProvider(*top_hosts));
+ }
+
+ return nullptr;
+}
+
+CommandLineTopHostProvider::CommandLineTopHostProvider(
+ const std::vector<std::string>& top_hosts)
+ : top_hosts_(top_hosts) {}
+
+CommandLineTopHostProvider::~CommandLineTopHostProvider() = default;
+
+std::vector<std::string> CommandLineTopHostProvider::GetTopHosts(
+ size_t max_sites) {
+ if (top_hosts_.size() <= max_sites) {
+ return top_hosts_;
+ }
+
+ std::vector<std::string> top_hosts;
+ top_hosts.reserve(max_sites);
+ for (const auto& top_host : top_hosts_) {
+ if (top_hosts.size() >= max_sites)
+ return top_hosts;
+
+ top_hosts.push_back(top_host);
+ }
+ return top_hosts;
+}
+
+} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/command_line_top_host_provider.h b/chromium/components/optimization_guide/command_line_top_host_provider.h
new file mode 100644
index 00000000000..949be273d13
--- /dev/null
+++ b/chromium/components/optimization_guide/command_line_top_host_provider.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 COMPONENTS_OPTIMIZATION_GUIDE_COMMAND_LINE_TOP_HOST_PROVIDER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_COMMAND_LINE_TOP_HOST_PROVIDER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/optimization_guide/top_host_provider.h"
+
+namespace optimization_guide {
+
+// A TopHostProvider implementation that provides top hosts based on what is fed
+// through the command line. This implementation is intended to be used just for
+// developer and integration testing.
+class CommandLineTopHostProvider : public TopHostProvider {
+ public:
+ // Creates a TopHostProvider if the flag for overriding top hosts has been
+ // enabled.
+ static std::unique_ptr<CommandLineTopHostProvider> CreateIfEnabled();
+ ~CommandLineTopHostProvider() override;
+
+ // TopHostProvider implementation:
+ std::vector<std::string> GetTopHosts(size_t max_sites) override;
+
+ private:
+ explicit CommandLineTopHostProvider(
+ const std::vector<std::string>& top_hosts);
+
+ std::vector<std::string> top_hosts_;
+
+ DISALLOW_COPY_AND_ASSIGN(CommandLineTopHostProvider);
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_COMMAND_LINE_TOP_HOST_PROVIDER_H_
diff --git a/chromium/components/optimization_guide/command_line_top_host_provider_unittest.cc b/chromium/components/optimization_guide/command_line_top_host_provider_unittest.cc
new file mode 100644
index 00000000000..f7edda022fb
--- /dev/null
+++ b/chromium/components/optimization_guide/command_line_top_host_provider_unittest.cc
@@ -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.
+
+#include "components/optimization_guide/command_line_top_host_provider.h"
+
+#include "base/command_line.h"
+#include "components/optimization_guide/optimization_guide_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace optimization_guide {
+
+TEST(CommandLineTopHostProviderTest, DoesNotCreateIfFlagNotEnabled) {
+ ASSERT_FALSE(CommandLineTopHostProvider::CreateIfEnabled());
+}
+
+TEST(CommandLineTopHostProviderTest, DoesNotCreateIfSwitchEnabledButNoHosts) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kFetchHintsOverride);
+
+ ASSERT_FALSE(CommandLineTopHostProvider::CreateIfEnabled());
+}
+
+TEST(CommandLineTopHostProviderTest, CreateIfFlagEnabledAndHasHosts) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kFetchHintsOverride, "whatever.com");
+
+ std::unique_ptr<CommandLineTopHostProvider> top_host_provider =
+ CommandLineTopHostProvider::CreateIfEnabled();
+ ASSERT_TRUE(top_host_provider);
+}
+
+TEST(CommandLineTopHostProviderTest,
+ GetTopHostsMaxLessThanProvidedSizeReturnsEverything) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kFetchHintsOverride, "whatever.com");
+
+ std::unique_ptr<CommandLineTopHostProvider> top_host_provider =
+ CommandLineTopHostProvider::CreateIfEnabled();
+ ASSERT_TRUE(top_host_provider);
+ std::vector<std::string> top_hosts =
+ top_host_provider->GetTopHosts(/*max_size=*/2);
+ EXPECT_EQ(1ul, top_hosts.size());
+ EXPECT_EQ("whatever.com", top_hosts[0]);
+}
+
+TEST(CommandLineTopHostProviderTest,
+ GetTopHostsMaxGreaterThanTotalVectorSizeReturnsFirstN) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kFetchHintsOverride, "whatever.com,awesome.com");
+
+ std::unique_ptr<CommandLineTopHostProvider> top_host_provider =
+ CommandLineTopHostProvider::CreateIfEnabled();
+ ASSERT_TRUE(top_host_provider);
+ std::vector<std::string> top_hosts =
+ top_host_provider->GetTopHosts(/*max_size=*/1);
+ EXPECT_EQ(1ul, top_hosts.size());
+ EXPECT_EQ("whatever.com", top_hosts[0]);
+}
+
+} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/hint_cache_store.cc b/chromium/components/optimization_guide/hint_cache_store.cc
index 9a7a3c9beff..3b1a0078d6b 100644
--- a/chromium/components/optimization_guide/hint_cache_store.cc
+++ b/chromium/components/optimization_guide/hint_cache_store.cc
@@ -15,8 +15,6 @@
#include "components/leveldb_proto/public/shared_proto_database_client_list.h"
#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/optimization_guide/proto/hint_cache.pb.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
namespace optimization_guide {
@@ -44,8 +42,6 @@ constexpr char kKeySectionDelimiter = '_';
// Realistic minimum length of a host suffix.
const int kMinHostSuffix = 6; // eg., abc.tv
-constexpr char kHintLoadedPercentageTotalKey[] = "Total";
-
// Enumerates the possible outcomes of loading metadata. Used in UMA histograms,
// so the order of enumerators should not be changed.
//
@@ -94,44 +90,12 @@ bool DatabasePrefixFilter(const std::string& key_prefix,
return base::StartsWith(key, key_prefix, base::CompareCase::SENSITIVE);
}
-std::string GetStringNameForStoreEntryType(
- HintCacheStore::StoreEntryType store_entry_type) {
- switch (store_entry_type) {
- case HintCacheStore::StoreEntryType::kEmpty:
- return "Empty";
- case HintCacheStore::StoreEntryType::kMetadata:
- return "Metadata";
- case HintCacheStore::StoreEntryType::kComponentHint:
- return "ComponentHint";
- case HintCacheStore::StoreEntryType::kFetchedHint:
- return "FetchedHint";
- }
- NOTREACHED();
- return std::string();
-}
-
-void IncrementHintLoadedCountsPrefForKey(PrefService* pref_service,
- const std::string& key) {
- if (!pref_service)
- return;
-
- DictionaryPrefUpdate pref(pref_service, prefs::kHintLoadedCounts);
- base::Optional<int> maybe_val = pref->FindIntKey(key);
- if (maybe_val.has_value()) {
- pref->SetIntKey(key, maybe_val.value() + 1);
- } else {
- pref->SetIntKey(key, 1);
- }
-}
-
} // namespace
HintCacheStore::HintCacheStore(
leveldb_proto::ProtoDatabaseProvider* database_provider,
const base::FilePath& database_dir,
- PrefService* pref_service,
- scoped_refptr<base::SequencedTaskRunner> store_task_runner)
- : pref_service_(pref_service) {
+ scoped_refptr<base::SequencedTaskRunner> store_task_runner) {
base::FilePath hint_store_dir =
database_dir.AppendASCII(kHintCacheStoreFolder);
database_ = database_provider->GetDB<proto::StoreEntry>(
@@ -142,9 +106,8 @@ HintCacheStore::HintCacheStore(
}
HintCacheStore::HintCacheStore(
- std::unique_ptr<leveldb_proto::ProtoDatabase<proto::StoreEntry>> database,
- PrefService* pref_service)
- : database_(std::move(database)), pref_service_(pref_service) {
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::StoreEntry>> database)
+ : database_(std::move(database)) {
RecordStatusChange(status_);
}
@@ -249,39 +212,6 @@ void HintCacheStore::UpdateComponentHints(
GetComponentHintEntryKeyPrefix(component_version_.value());
EntryKeyPrefix filter_prefix = GetComponentHintEntryKeyPrefixWithoutVersion();
- // Received a new component version, report how many unique hints were used
- // and clear the pref afterwards.
- if (pref_service_) {
- const base::DictionaryValue* hint_loaded_counts =
- pref_service_->GetDictionary(prefs::kHintLoadedCounts);
- if (hint_loaded_counts) {
- base::Optional<int> maybe_total_load_attempts =
- hint_loaded_counts->FindIntKey(kHintLoadedPercentageTotalKey);
- if (maybe_total_load_attempts.has_value() &&
- maybe_total_load_attempts.value() > 0) {
- const int total_load_attempts = maybe_total_load_attempts.value();
- int total_hints_loaded = 0;
- for (const auto& it : hint_loaded_counts->DictItems()) {
- // Skip over the total since we already extracted the value.
- if (it.first == kHintLoadedPercentageTotalKey) {
- continue;
- }
- const int val = it.second.GetInt();
- total_hints_loaded += val;
- base::UmaHistogramPercentage(
- base::StrCat(
- {"OptimizationGuide.HintsLoadedPercentage.", it.first}),
- 100 * val / total_load_attempts);
- }
-
- base::UmaHistogramPercentage(
- "OptimizationGuide.HintsLoadedPercentage",
- 100 * total_hints_loaded / total_load_attempts);
- }
- }
- pref_service_->ClearPref(prefs::kHintLoadedCounts);
- }
-
// Add the new component data and purge any old component hints from the db.
// After processing finishes, OnUpdateHints() is called, which loads
// the updated hint entry keys from the database.
@@ -439,9 +369,6 @@ void HintCacheStore::LoadHint(const EntryKey& hint_entry_key,
return;
}
- IncrementHintLoadedCountsPrefForKey(pref_service_,
- kHintLoadedPercentageTotalKey);
-
database_->GetEntry(hint_entry_key,
base::BindOnce(&HintCacheStore::OnLoadHint,
weak_ptr_factory_.GetWeakPtr(),
@@ -835,9 +762,6 @@ void HintCacheStore::OnLoadHint(const std::string& entry_key,
UMA_HISTOGRAM_ENUMERATION("OptimizationGuide.HintCache.HintType.Loaded",
store_entry_type);
- IncrementHintLoadedCountsPrefForKey(
- pref_service_, GetStringNameForStoreEntryType(store_entry_type));
-
if (store_entry_type == StoreEntryType::kFetchedHint) {
UMA_HISTOGRAM_CUSTOM_TIMES(
"OptimizationGuide.HintCache.FetchedHint.TimeToExpiration",
diff --git a/chromium/components/optimization_guide/hint_cache_store.h b/chromium/components/optimization_guide/hint_cache_store.h
index 7f295059040..6b760c86472 100644
--- a/chromium/components/optimization_guide/hint_cache_store.h
+++ b/chromium/components/optimization_guide/hint_cache_store.h
@@ -19,9 +19,6 @@
#include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "components/optimization_guide/hint_update_data.h"
-#include "components/prefs/pref_service.h"
-
-class PrefService;
namespace base {
class SequencedTaskRunner;
@@ -90,11 +87,9 @@ class HintCacheStore {
HintCacheStore(leveldb_proto::ProtoDatabaseProvider* database_provider,
const base::FilePath& database_dir,
- PrefService* pref_service,
scoped_refptr<base::SequencedTaskRunner> store_task_runner);
// For tests only.
- HintCacheStore(std::unique_ptr<StoreEntryProtoDatabase> database,
- PrefService* pref_service);
+ explicit HintCacheStore(std::unique_ptr<StoreEntryProtoDatabase> database);
~HintCacheStore();
// Initializes the hint cache store. If |purge_existing_data| is set to true,
@@ -306,9 +301,6 @@ class HintCacheStore {
// Proto database used by the store.
std::unique_ptr<StoreEntryProtoDatabase> database_;
- // A reference to the PrefService for this profile. Not owned.
- PrefService* pref_service_;
-
// The current status of the store. It should only be updated through
// UpdateStatus(), which validates status transitions and triggers
// accompanying logic.
diff --git a/chromium/components/optimization_guide/hint_cache_store_unittest.cc b/chromium/components/optimization_guide/hint_cache_store_unittest.cc
index 13b6d1bce9a..2af289e0b49 100644
--- a/chromium/components/optimization_guide/hint_cache_store_unittest.cc
+++ b/chromium/components/optimization_guide/hint_cache_store_unittest.cc
@@ -15,11 +15,7 @@
#include "components/leveldb_proto/testing/fake_db.h"
#include "components/optimization_guide/hint_update_data.h"
#include "components/optimization_guide/optimization_guide_features.h"
-#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/optimization_guide/proto/hint_cache.pb.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -150,9 +146,7 @@ class HintCacheStoreTest : public testing::Test {
auto db = std::make_unique<FakeDB<StoreEntry>>(&db_store_);
db_ = db.get();
- optimization_guide::prefs::RegisterProfilePrefs(pref_service_.registry());
- hint_store_ =
- std::make_unique<HintCacheStore>(std::move(db), &pref_service_);
+ hint_store_ = std::make_unique<HintCacheStore>(std::move(db));
}
void InitializeDatabase(bool success, bool purge_existing_data = false) {
@@ -316,18 +310,12 @@ class HintCacheStoreTest : public testing::Test {
last_loaded_hint_ = std::move(loaded_hint);
}
- const base::DictionaryValue* hint_loaded_counts_pref() {
- return pref_service_.GetDictionary(
- optimization_guide::prefs::kHintLoadedCounts);
- }
-
MOCK_METHOD0(OnInitialized, void());
MOCK_METHOD0(OnUpdateHints, void());
private:
FakeDB<proto::StoreEntry>* db_;
StoreEntryMap db_store_;
- TestingPrefServiceSimple pref_service_;
std::unique_ptr<HintCacheStore> hint_store_;
HintCacheStore::EntryKey last_loaded_hint_entry_key_;
@@ -1479,120 +1467,6 @@ TEST_F(HintCacheStoreTest, FetchHintsPurgeExpiredFetchedHints) {
EXPECT_TRUE(hint_store()->FindHintEntryKey("domain3.org", &hint_entry_key));
}
-TEST_F(HintCacheStoreTest, LoadingHintUpdatesPrefCorrectly) {
- base::HistogramTester histogram_tester;
-
- // Update component with some hints.
- MetadataSchemaState schema_state = MetadataSchemaState::kValid;
- size_t initial_hint_count = 10;
- size_t update_hint_count = 5;
- SeedInitialData(schema_state, initial_hint_count);
- CreateDatabase();
- InitializeStore(schema_state);
-
- std::unique_ptr<HintUpdateData> update_data =
- hint_store()->MaybeCreateUpdateDataForComponentHints(
- base::Version(kUpdateComponentVersion));
- ASSERT_TRUE(update_data);
- SeedComponentUpdateData(update_data.get(), update_hint_count);
- UpdateComponentHints(std::move(update_data));
-
- // Also seed a fetched hint into the store.
- update_data = hint_store()->CreateUpdateDataForFetchedHints(
- base::Time().Now(),
- base::Time().Now() +
- optimization_guide::features::StoredFetchedHintsFreshnessDuration());
- proto::Hint hint;
- hint.set_key("domain2.org");
- hint.set_key_representation(proto::HOST_SUFFIX);
- update_data->MoveHintIntoUpdateData(std::move(hint));
- UpdateFetchedHints(std::move(update_data));
-
- // Load hint for component host suffix.
- std::string host_suffix1 = GetHostSuffix(0);
- HintCacheStore::EntryKey hint_entry_key1;
- if (!hint_store()->FindHintEntryKey(host_suffix1, &hint_entry_key1)) {
- FAIL() << "Hint entry not found for host suffix: " << host_suffix1;
- }
- hint_store()->LoadHint(hint_entry_key1,
- base::BindOnce(&HintCacheStoreTest::OnHintLoaded,
- base::Unretained(this)));
- db()->GetCallback(true);
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("Total"));
- EXPECT_EQ(1, hint_loaded_counts_pref()->FindIntKey("Total").value());
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("ComponentHint"));
- EXPECT_EQ(1, hint_loaded_counts_pref()->FindIntKey("ComponentHint").value());
-
- // Load another component hint.
- std::string host_suffix2 = GetHostSuffix(1);
- HintCacheStore::EntryKey hint_entry_key2;
- if (!hint_store()->FindHintEntryKey(host_suffix2, &hint_entry_key2)) {
- FAIL() << "Hint entry not found for host suffix: " << host_suffix2;
- }
- hint_store()->LoadHint(hint_entry_key2,
- base::BindOnce(&HintCacheStoreTest::OnHintLoaded,
- base::Unretained(this)));
- db()->GetCallback(true);
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("Total"));
- EXPECT_EQ(2, hint_loaded_counts_pref()->FindIntKey("Total").value());
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("ComponentHint"));
- EXPECT_EQ(2, hint_loaded_counts_pref()->FindIntKey("ComponentHint").value());
-
- // Load hint for a fetched hint.
- std::string fetched_host_suffix = "host.domain2.org";
- HintCacheStore::EntryKey fetched_hint_entry_key;
- if (!hint_store()->FindHintEntryKey(fetched_host_suffix,
- &fetched_hint_entry_key)) {
- FAIL() << "Hint entry not found for host suffix: " << fetched_host_suffix;
- }
- hint_store()->LoadHint(fetched_hint_entry_key,
- base::BindOnce(&HintCacheStoreTest::OnHintLoaded,
- base::Unretained(this)));
- db()->GetCallback(true);
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("Total"));
- EXPECT_EQ(3, hint_loaded_counts_pref()->FindIntKey("Total").value());
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("ComponentHint"));
- EXPECT_EQ(2, hint_loaded_counts_pref()->FindIntKey("ComponentHint").value());
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("FetchedHint"));
- EXPECT_EQ(1, hint_loaded_counts_pref()->FindIntKey("FetchedHint").value());
-
- // Load hint for a hint entry we do not have.
- hint_store()->LoadHint("doesnotexist",
- base::BindOnce(&HintCacheStoreTest::OnHintLoaded,
- base::Unretained(this)));
- db()->GetCallback(true);
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("Total"));
- EXPECT_EQ(4, hint_loaded_counts_pref()->FindIntKey("Total").value());
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("ComponentHint"));
- EXPECT_EQ(2, hint_loaded_counts_pref()->FindIntKey("ComponentHint").value());
- EXPECT_TRUE(hint_loaded_counts_pref()->HasKey("FetchedHint"));
- EXPECT_EQ(1, hint_loaded_counts_pref()->FindIntKey("FetchedHint").value());
-
- // Now update the component with a new version.
- std::unique_ptr<HintUpdateData> update_data2 =
- hint_store()->MaybeCreateUpdateDataForComponentHints(
- base::Version("100.0.0"));
- ASSERT_TRUE(update_data2);
- SeedComponentUpdateData(update_data2.get(), update_hint_count);
- UpdateComponentHints(std::move(update_data2));
-
- histogram_tester.ExpectTotalCount("OptimizationGuide.HintsLoadedPercentage",
- 1);
- histogram_tester.ExpectUniqueSample("OptimizationGuide.HintsLoadedPercentage",
- 75, 1);
- histogram_tester.ExpectTotalCount(
- "OptimizationGuide.HintsLoadedPercentage.ComponentHint", 1);
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.HintsLoadedPercentage.ComponentHint", 50, 1);
- histogram_tester.ExpectTotalCount(
- "OptimizationGuide.HintsLoadedPercentage.FetchedHint", 1);
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.HintsLoadedPercentage.FetchedHint", 25, 1);
-
- // Ensure that pref has been cleared.
- EXPECT_TRUE(hint_loaded_counts_pref()->empty());
-}
-
TEST_F(HintCacheStoreTest, FetchedHintsLoadExpiredHint) {
base::HistogramTester histogram_tester;
MetadataSchemaState schema_state = MetadataSchemaState::kValid;
diff --git a/chromium/components/optimization_guide/hint_cache_unittest.cc b/chromium/components/optimization_guide/hint_cache_unittest.cc
index 6d6ebf78769..6dd078d04e0 100644
--- a/chromium/components/optimization_guide/hint_cache_unittest.cc
+++ b/chromium/components/optimization_guide/hint_cache_unittest.cc
@@ -13,7 +13,7 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/optimization_guide/hint_cache_store.h"
#include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/proto_database_provider_test_base.h"
@@ -46,11 +46,9 @@ class HintCacheTest : public ProtoDatabaseProviderTestBase {
void CreateAndInitializeHintCache(int memory_cache_size,
bool purge_existing_data = false) {
auto database_path = temp_dir_.GetPath();
- auto database_task_runner =
- scoped_task_environment_.GetMainThreadTaskRunner();
+ auto database_task_runner = task_environment_.GetMainThreadTaskRunner();
hint_cache_ = std::make_unique<HintCache>(
std::make_unique<HintCacheStore>(db_provider_.get(), database_path,
- nullptr /* pref_service */,
database_task_runner),
memory_cache_size);
is_store_initialized_ = false;
@@ -120,7 +118,7 @@ class HintCacheTest : public ProtoDatabaseProviderTestBase {
private:
void RunUntilIdle() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
@@ -131,7 +129,7 @@ class HintCacheTest : public ProtoDatabaseProviderTestBase {
loaded_hint_ = hint;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<HintCache> hint_cache_;
const proto::Hint* loaded_hint_;
diff --git a/chromium/components/optimization_guide/hints_component_util.cc b/chromium/components/optimization_guide/hints_component_util.cc
index 4e89c40f89a..e409e8457e3 100644
--- a/chromium/components/optimization_guide/hints_component_util.cc
+++ b/chromium/components/optimization_guide/hints_component_util.cc
@@ -5,13 +5,18 @@
#include "components/optimization_guide/hints_component_util.h"
#include <string>
+#include <utility>
#include "base/files/file.h"
#include "base/files/file_util.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
+#include "components/optimization_guide/bloom_filter.h"
#include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/hints_processing_util.h"
+#include "components/optimization_guide/optimization_filter.h"
+#include "components/optimization_guide/optimization_guide_features.h"
namespace optimization_guide {
@@ -20,13 +25,83 @@ namespace {
const char kProcessHintsComponentResultHistogramString[] =
"OptimizationGuide.ProcessHintsResult";
-void MaybePopulateProcessHintsComponentResult(
+// Populates |out_result| with |result| if |out_result| is provided.
+void PopulateProcessHintsComponentResultIfSet(
ProcessHintsComponentResult result,
ProcessHintsComponentResult* out_result) {
if (out_result)
*out_result = result;
}
+// Populates |out_status| with |status| if |out_status| is provided.
+void PopulateOptimizationFilterStatusIfSet(
+ OptimizationFilterStatus status,
+ OptimizationFilterStatus* out_status) {
+ if (out_status)
+ *out_status = status;
+}
+
+// Attempts to construct a valid bloom filter from the given
+// |optimization_filter|. If given, |out_status| will be populated with the
+// status of the operation. If a valid bloom filter cannot be constructed,
+// nullptr is returned.
+std::unique_ptr<BloomFilter> ProcessBloomFilter(
+ const proto::OptimizationFilter& optimization_filter,
+ OptimizationFilterStatus* out_status) {
+ const auto& bloom_filter_proto = optimization_filter.bloom_filter();
+ DCHECK_GT(bloom_filter_proto.num_hash_functions(), 0u);
+ DCHECK_GT(bloom_filter_proto.num_bits(), 0u);
+ DCHECK(bloom_filter_proto.has_data());
+
+ if (!bloom_filter_proto.has_data() || bloom_filter_proto.num_bits() <= 0 ||
+ bloom_filter_proto.num_bits() > bloom_filter_proto.data().size() * 8) {
+ DLOG(ERROR) << "Bloom filter config issue";
+ PopulateOptimizationFilterStatusIfSet(
+ OptimizationFilterStatus::kFailedServerBlacklistBadConfig, out_status);
+ return nullptr;
+ }
+
+ if (static_cast<int>(bloom_filter_proto.num_bits()) >
+ features::MaxServerBloomFilterByteSize() * 8) {
+ DLOG(ERROR) << "Bloom filter data exceeds maximum size of "
+ << optimization_guide::features::MaxServerBloomFilterByteSize()
+ << " bytes";
+ PopulateOptimizationFilterStatusIfSet(
+ OptimizationFilterStatus::kFailedServerBlacklistTooBig, out_status);
+ return nullptr;
+ }
+
+ std::unique_ptr<BloomFilter> bloom_filter = std::make_unique<BloomFilter>(
+ bloom_filter_proto.num_hash_functions(), bloom_filter_proto.num_bits(),
+ bloom_filter_proto.data());
+ PopulateOptimizationFilterStatusIfSet(
+ OptimizationFilterStatus::kCreatedServerBlacklist, out_status);
+ return bloom_filter;
+}
+
+// Attempts to construct a valid RegexpList from the given
+// |optimization_filter|. If given, |out_status| will be populated with the
+// status of the operation. If a valid RegexpList cannot be constructed, nullptr
+// is returned.
+std::unique_ptr<RegexpList> ProcessRegexps(
+ const proto::OptimizationFilter& optimization_filter,
+ OptimizationFilterStatus* out_status) {
+ std::unique_ptr<RegexpList> regexps = std::make_unique<RegexpList>();
+ for (int i = 0; i < optimization_filter.regexps_size(); ++i) {
+ regexps->emplace_back(
+ std::make_unique<re2::RE2>(optimization_filter.regexps(i)));
+ if (!regexps->at(i)->ok()) {
+ PopulateOptimizationFilterStatusIfSet(
+ OptimizationFilterStatus::kInvalidRegexp, out_status);
+ return nullptr;
+ }
+ }
+
+ PopulateOptimizationFilterStatusIfSet(
+ OptimizationFilterStatus::kCreatedServerBlacklist, out_status);
+ return regexps;
+}
+
} // namespace
const char kComponentHintsUpdatedResultHistogramString[] =
@@ -37,26 +112,18 @@ void RecordProcessHintsComponentResult(ProcessHintsComponentResult result) {
result);
}
-void RecordOptimizationFilterStatus(proto::OptimizationType optimization_type,
- OptimizationFilterStatus status) {
- std::string histogram_name = base::StringPrintf(
- "OptimizationGuide.OptimizationFilterStatus.%s",
- GetStringNameForOptimizationType(optimization_type).c_str());
- UMA_HISTOGRAM_ENUMERATION(histogram_name, status);
-}
-
std::unique_ptr<proto::Configuration> ProcessHintsComponent(
const HintsComponentInfo& component_info,
ProcessHintsComponentResult* out_result) {
if (!component_info.version.IsValid() || component_info.path.empty()) {
- MaybePopulateProcessHintsComponentResult(
+ PopulateProcessHintsComponentResultIfSet(
ProcessHintsComponentResult::kFailedInvalidParameters, out_result);
return nullptr;
}
std::string binary_pb;
if (!base::ReadFileToString(component_info.path, &binary_pb)) {
- MaybePopulateProcessHintsComponentResult(
+ PopulateProcessHintsComponentResultIfSet(
ProcessHintsComponentResult::kFailedReadingFile, out_result);
return nullptr;
}
@@ -64,14 +131,45 @@ std::unique_ptr<proto::Configuration> ProcessHintsComponent(
std::unique_ptr<proto::Configuration> proto_configuration =
std::make_unique<proto::Configuration>();
if (!proto_configuration->ParseFromString(binary_pb)) {
- MaybePopulateProcessHintsComponentResult(
+ PopulateProcessHintsComponentResultIfSet(
ProcessHintsComponentResult::kFailedInvalidConfiguration, out_result);
return nullptr;
}
- MaybePopulateProcessHintsComponentResult(
+ PopulateProcessHintsComponentResultIfSet(
ProcessHintsComponentResult::kSuccess, out_result);
return proto_configuration;
}
+void RecordOptimizationFilterStatus(proto::OptimizationType optimization_type,
+ OptimizationFilterStatus status) {
+ base::UmaHistogramExactLinear(
+ base::StringPrintf(
+ "OptimizationGuide.OptimizationFilterStatus.%s",
+ GetStringNameForOptimizationType(optimization_type).c_str()),
+ static_cast<int>(status),
+ static_cast<int>(OptimizationFilterStatus::kMaxValue));
+}
+
+std::unique_ptr<OptimizationFilter> ProcessOptimizationFilter(
+ const proto::OptimizationFilter& optimization_filter,
+ OptimizationFilterStatus* out_status) {
+ std::unique_ptr<BloomFilter> bloom_filter;
+ if (optimization_filter.has_bloom_filter()) {
+ bloom_filter = ProcessBloomFilter(optimization_filter, out_status);
+ if (!bloom_filter)
+ return nullptr;
+ }
+
+ std::unique_ptr<RegexpList> regexps;
+ if (optimization_filter.regexps_size() > 0) {
+ regexps = ProcessRegexps(optimization_filter, out_status);
+ if (!regexps)
+ return nullptr;
+ }
+
+ return std::make_unique<OptimizationFilter>(std::move(bloom_filter),
+ std::move(regexps));
+}
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/hints_component_util.h b/chromium/components/optimization_guide/hints_component_util.h
index 620c936e86b..680d6902bd5 100644
--- a/chromium/components/optimization_guide/hints_component_util.h
+++ b/chromium/components/optimization_guide/hints_component_util.h
@@ -12,6 +12,7 @@
namespace optimization_guide {
struct HintsComponentInfo;
+class OptimizationFilter;
// The local histogram used to record that the component hints are stored in
// the cache and are ready for use.
@@ -38,6 +39,17 @@ enum class ProcessHintsComponentResult {
// Records the ProcessHintsComponentResult to UMA.
void RecordProcessHintsComponentResult(ProcessHintsComponentResult result);
+// Processes the specified hints component.
+//
+// If successful, returns the component's Configuration protobuf. Otherwise,
+// returns a nullptr.
+//
+// If |out_result| provided, it will be populated with the result up to that
+// point.
+std::unique_ptr<proto::Configuration> ProcessHintsComponent(
+ const HintsComponentInfo& info,
+ ProcessHintsComponentResult* out_result);
+
// Enumerates status event of processing optimization filters (such as the
// lite page redirect blacklist). Used in UMA histograms, so the order of
// enumerators should not be changed.
@@ -50,25 +62,22 @@ enum class OptimizationFilterStatus {
kFailedServerBlacklistBadConfig,
kFailedServerBlacklistTooBig,
kFailedServerBlacklistDuplicateConfig,
+ kInvalidRegexp,
// Insert new values before this line.
- kMaxValue = kFailedServerBlacklistDuplicateConfig,
+ kMaxValue = kInvalidRegexp,
};
// Records the OptimizationFilterStatus to UMA.
void RecordOptimizationFilterStatus(proto::OptimizationType optimization_type,
OptimizationFilterStatus status);
-// Processes the specified hints component.
-//
-// If successful, returns the component's Configuration protobuf. Otherwise,
-// returns a nullptr.
-//
-// If |out_result| provided, it will be populated with the result up to that
-// point.
-std::unique_ptr<proto::Configuration> ProcessHintsComponent(
- const HintsComponentInfo& info,
- ProcessHintsComponentResult* out_result);
+// Validates and parses |optimization_filter_proto| and creates one that is
+// intended to be queried to make decisions for whether an optimization type
+// should be applied on a navigation.
+std::unique_ptr<OptimizationFilter> ProcessOptimizationFilter(
+ const proto::OptimizationFilter& optimization_filter_proto,
+ OptimizationFilterStatus* out_status);
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/hints_component_util_unittest.cc b/chromium/components/optimization_guide/hints_component_util_unittest.cc
index ca2819678ca..9cece8d191d 100644
--- a/chromium/components/optimization_guide/hints_component_util_unittest.cc
+++ b/chromium/components/optimization_guide/hints_component_util_unittest.cc
@@ -12,9 +12,12 @@
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/version.h"
+#include "components/optimization_guide/bloom_filter.h"
#include "components/optimization_guide/hints_component_info.h"
-#include "components/optimization_guide/proto/hints.pb.h"
+#include "components/optimization_guide/optimization_filter.h"
+#include "components/optimization_guide/optimization_guide_features.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace optimization_guide {
@@ -52,16 +55,6 @@ TEST_F(HintsComponentUtilTest, RecordProcessHintsComponentResult) {
ProcessHintsComponentResult::kSuccess, 1);
}
-TEST_F(HintsComponentUtilTest, RecordOptimizationFilterStatus) {
- base::HistogramTester histogram_tester;
- RecordOptimizationFilterStatus(
- proto::OptimizationType::NOSCRIPT,
- OptimizationFilterStatus::kFoundServerBlacklistConfig);
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.OptimizationFilterStatus.NoScript",
- OptimizationFilterStatus::kFoundServerBlacklistConfig, 1);
-}
-
TEST_F(HintsComponentUtilTest, ProcessHintsComponentInvalidVersion) {
ProcessHintsComponentResult result;
std::unique_ptr<proto::Configuration> config = ProcessHintsComponent(
@@ -138,4 +131,167 @@ TEST_F(HintsComponentUtilTest,
EXPECT_EQ("google.com", processed_config->hints()[0].key());
}
+TEST_F(HintsComponentUtilTest, RecordOptimizationFilterStatus) {
+ base::HistogramTester histogram_tester;
+ RecordOptimizationFilterStatus(
+ proto::OptimizationType::NOSCRIPT,
+ OptimizationFilterStatus::kFoundServerBlacklistConfig);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.OptimizationFilterStatus.NoScript",
+ OptimizationFilterStatus::kFoundServerBlacklistConfig, 1);
+
+ // Record again with a different suffix to make sure it doesn't choke.
+ RecordOptimizationFilterStatus(
+ proto::OptimizationType::DEFER_ALL_SCRIPT,
+ OptimizationFilterStatus::kFoundServerBlacklistConfig);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.OptimizationFilterStatus.DeferAllScript",
+ OptimizationFilterStatus::kFoundServerBlacklistConfig, 1);
+}
+
+TEST_F(HintsComponentUtilTest, ProcessOptimizationFilter) {
+ int num_hash_functions = 7;
+ int num_bits = 1234;
+
+ proto::OptimizationFilter optimization_filter_proto;
+ BloomFilter bloom_filter(num_hash_functions, num_bits);
+ bloom_filter.Add("black.com");
+ proto::BloomFilter* bloom_filter_proto =
+ optimization_filter_proto.mutable_bloom_filter();
+ bloom_filter_proto->set_num_hash_functions(num_hash_functions);
+ bloom_filter_proto->set_num_bits(num_bits);
+ std::string blacklist_data(
+ reinterpret_cast<const char*>(&bloom_filter.bytes()[0]),
+ bloom_filter.bytes().size());
+ bloom_filter_proto->set_data(blacklist_data);
+
+ OptimizationFilterStatus status;
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto, &status);
+
+ EXPECT_EQ(status, OptimizationFilterStatus::kCreatedServerBlacklist);
+ ASSERT_TRUE(optimization_filter);
+ EXPECT_TRUE(optimization_filter->Matches(GURL("https://m.black.com")));
+}
+
+TEST_F(HintsComponentUtilTest, ProcessOptimizationFilterWithBadNumBits) {
+ proto::OptimizationFilter optimization_filter_proto;
+ BloomFilter bloom_filter(7, 1234);
+ bloom_filter.Add("black.com");
+ proto::BloomFilter* bloom_filter_proto =
+ optimization_filter_proto.mutable_bloom_filter();
+ bloom_filter_proto->set_num_hash_functions(7);
+ bloom_filter_proto->set_num_bits(bloom_filter.bytes().size() * 8 + 1);
+ std::string blacklist_data(
+ reinterpret_cast<const char*>(&bloom_filter.bytes()[0]),
+ bloom_filter.bytes().size());
+ bloom_filter_proto->set_data(blacklist_data);
+
+ OptimizationFilterStatus status;
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto, &status);
+
+ EXPECT_EQ(status, OptimizationFilterStatus::kFailedServerBlacklistBadConfig);
+ EXPECT_EQ(nullptr, optimization_filter);
+}
+
+TEST_F(HintsComponentUtilTest, ProcessOptimizationFilterWithRegexps) {
+ proto::OptimizationFilter optimization_filter_proto;
+ optimization_filter_proto.add_regexps("test");
+
+ OptimizationFilterStatus status;
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto, &status);
+
+ EXPECT_EQ(status, OptimizationFilterStatus::kCreatedServerBlacklist);
+ ASSERT_TRUE(optimization_filter);
+ EXPECT_TRUE(optimization_filter->Matches(GURL("https://test.com")));
+}
+
+TEST_F(HintsComponentUtilTest, ProcessOptimizationFilterWithInvalidRegexps) {
+ proto::OptimizationFilter optimization_filter_proto;
+ optimization_filter_proto.add_regexps("test[");
+
+ OptimizationFilterStatus status;
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto, &status);
+
+ EXPECT_EQ(status, OptimizationFilterStatus::kInvalidRegexp);
+ EXPECT_EQ(nullptr, optimization_filter);
+}
+
+TEST_F(HintsComponentUtilTest,
+ ProcessOptimizationFilterInvalidRegexpsOverridesBloomFilterStatus) {
+ int num_hash_functions = 7;
+ int num_bits = 1234;
+
+ proto::OptimizationFilter optimization_filter_proto;
+ optimization_filter_proto.add_regexps("test[");
+ BloomFilter bloom_filter(num_hash_functions, num_bits);
+ bloom_filter.Add("black.com");
+ proto::BloomFilter* bloom_filter_proto =
+ optimization_filter_proto.mutable_bloom_filter();
+ bloom_filter_proto->set_num_hash_functions(num_hash_functions);
+ bloom_filter_proto->set_num_bits(num_bits);
+ std::string blacklist_data(
+ reinterpret_cast<const char*>(&bloom_filter.bytes()[0]),
+ bloom_filter.bytes().size());
+ bloom_filter_proto->set_data(blacklist_data);
+
+ OptimizationFilterStatus status;
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto, &status);
+
+ EXPECT_EQ(status, OptimizationFilterStatus::kInvalidRegexp);
+ EXPECT_EQ(nullptr, optimization_filter);
+}
+
+TEST_F(HintsComponentUtilTest, ProcessOptimizationFilterWithTooLargeBlacklist) {
+ int too_many_bits = features::MaxServerBloomFilterByteSize() * 8 + 1;
+
+ proto::OptimizationFilter optimization_filter_proto;
+ BloomFilter bloom_filter(7, too_many_bits);
+ bloom_filter.Add("black.com");
+ proto::BloomFilter* bloom_filter_proto =
+ optimization_filter_proto.mutable_bloom_filter();
+ bloom_filter_proto->set_num_hash_functions(7);
+ bloom_filter_proto->set_num_bits(too_many_bits);
+ std::string blacklist_data(
+ reinterpret_cast<const char*>(&bloom_filter.bytes()[0]),
+ bloom_filter.bytes().size());
+ bloom_filter_proto->set_data(blacklist_data);
+
+ OptimizationFilterStatus status;
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto, &status);
+
+ EXPECT_EQ(status, OptimizationFilterStatus::kFailedServerBlacklistTooBig);
+ EXPECT_EQ(nullptr, optimization_filter);
+}
+
+TEST_F(HintsComponentUtilTest,
+ ProcessOptimizationFilterNoResultProvidedDoesntCrash) {
+ int num_hash_functions = 7;
+ int num_bits = 1234;
+
+ proto::OptimizationFilter optimization_filter_proto;
+ BloomFilter bloom_filter(num_hash_functions, num_bits);
+ bloom_filter.Add("black.com");
+ proto::BloomFilter* bloom_filter_proto =
+ optimization_filter_proto.mutable_bloom_filter();
+ bloom_filter_proto->set_num_hash_functions(num_hash_functions);
+ bloom_filter_proto->set_num_bits(num_bits);
+ std::string blacklist_data(
+ reinterpret_cast<const char*>(&bloom_filter.bytes()[0]),
+ bloom_filter.bytes().size());
+ bloom_filter_proto->set_data(blacklist_data);
+
+ std::unique_ptr<OptimizationFilter> optimization_filter =
+ ProcessOptimizationFilter(optimization_filter_proto,
+ /*out_status=*/nullptr);
+
+ ASSERT_TRUE(optimization_filter);
+ EXPECT_TRUE(optimization_filter->Matches(GURL("https://m.black.com")));
+}
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/hints_fetcher.cc b/chromium/components/optimization_guide/hints_fetcher.cc
index a725c94d4c9..c50e7cda02f 100644
--- a/chromium/components/optimization_guide/hints_fetcher.cc
+++ b/chromium/components/optimization_guide/hints_fetcher.cc
@@ -10,8 +10,13 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/time/default_clock.h"
+#include "components/optimization_guide/hints_processing_util.h"
#include "components/optimization_guide/optimization_guide_features.h"
+#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
#include "content/public/browser/network_service_instance.h"
#include "net/base/load_flags.h"
#include "net/base/url_util.h"
@@ -24,13 +29,25 @@
namespace optimization_guide {
+namespace {
+
+// The duration that hosts placed in the HintsFetcherHostsSuccessfullyFetched
+// dictionary pref are considered valid.
+constexpr base::TimeDelta kHintsFetcherHostFetchedValidDuration =
+ base::TimeDelta::FromDays(7);
+
+} // namespace
+
HintsFetcher::HintsFetcher(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- GURL optimization_guide_service_url)
+ GURL optimization_guide_service_url,
+ PrefService* pref_service)
: optimization_guide_service_url_(net::AppendOrReplaceQueryParameter(
optimization_guide_service_url,
"key",
- features::GetOptimizationGuideServiceAPIKey())) {
+ features::GetOptimizationGuideServiceAPIKey())),
+ pref_service_(pref_service),
+ time_clock_(base::DefaultClock::GetInstance()) {
url_loader_factory_ = std::move(url_loader_factory);
CHECK(optimization_guide_service_url_.SchemeIs(url::kHttpsScheme));
CHECK(features::IsHintsFetchingEnabled());
@@ -38,6 +55,36 @@ HintsFetcher::HintsFetcher(
HintsFetcher::~HintsFetcher() {}
+// static
+void HintsFetcher::ClearHostsSuccessfullyFetched(PrefService* pref_service) {
+ DictionaryPrefUpdate hosts_fetched_list(
+ pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched);
+ hosts_fetched_list->Clear();
+}
+
+void HintsFetcher::SetTimeClockForTesting(const base::Clock* time_clock) {
+ time_clock_ = time_clock;
+}
+
+// static
+void HintsFetcher::RecordHintsFetcherCoverage(PrefService* pref_service,
+ const std::string& host) {
+ DictionaryPrefUpdate hosts_fetched(
+ pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched);
+ base::Optional<double> value =
+ hosts_fetched->FindDoubleKey(HashHostForDictionary(host));
+ if (!value) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false);
+ return;
+ }
+
+ base::Time host_valid_time = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSecondsD(*value));
+ UMA_HISTOGRAM_BOOLEAN("OptimizationGuide.HintsFetcher.WasHostCoveredByFetch",
+ host_valid_time > base::Time::Now());
+}
+
bool HintsFetcher::FetchOptimizationGuideServiceHints(
const std::vector<std::string>& hosts,
HintsFetchedCallback hints_fetched_callback) {
@@ -100,7 +147,7 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints(
resource_request->method = "POST";
resource_request->load_flags = net::LOAD_BYPASS_PROXY;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
@@ -123,6 +170,7 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints(
base::BindOnce(&HintsFetcher::OnURLLoadComplete, base::Unretained(this)));
hints_fetched_callback_ = std::move(hints_fetched_callback);
+ hosts_fetched_ = hosts;
return true;
}
@@ -143,12 +191,66 @@ void HintsFetcher::HandleResponse(const std::string& get_hints_response_data,
if (net_status == net::OK && response_code == net::HTTP_OK &&
get_hints_response->ParseFromString(get_hints_response_data)) {
+ UMA_HISTOGRAM_COUNTS_100(
+ "OptimizationGuide.HintsFetcher.GetHintsRequest.HintCount",
+ get_hints_response->hints_size());
+ UpdateHostsSuccessfullyFetched();
std::move(hints_fetched_callback_).Run(std::move(get_hints_response));
} else {
std::move(hints_fetched_callback_).Run(base::nullopt);
}
}
+void HintsFetcher::UpdateHostsSuccessfullyFetched() {
+ DictionaryPrefUpdate hosts_fetched_list(
+ pref_service_, prefs::kHintsFetcherHostsSuccessfullyFetched);
+
+ // Remove any expired hosts.
+ std::vector<std::string> entries_to_remove;
+ for (const auto& it : hosts_fetched_list->DictItems()) {
+ if (base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromSecondsD(
+ it.second.GetDouble())) < time_clock_->Now()) {
+ entries_to_remove.emplace_back(it.first);
+ }
+ }
+ for (const auto& host : entries_to_remove) {
+ hosts_fetched_list->Remove(host, nullptr);
+ }
+
+ if (hosts_fetched_.empty())
+ return;
+
+ // Ensure there is enough space in the dictionary pref for the
+ // most recent set of hosts to be stored.
+ if (hosts_fetched_list->size() + hosts_fetched_.size() >
+ features::MaxHostsForRecordingSuccessfullyCovered()) {
+ entries_to_remove.clear();
+ size_t num_entries_to_remove =
+ hosts_fetched_list->size() + hosts_fetched_.size() -
+ features::MaxHostsForRecordingSuccessfullyCovered();
+ for (const auto& it : hosts_fetched_list->DictItems()) {
+ if (entries_to_remove.size() >= num_entries_to_remove)
+ break;
+ entries_to_remove.emplace_back(it.first);
+ }
+ for (const auto& host : entries_to_remove) {
+ hosts_fetched_list->Remove(host, nullptr);
+ }
+ }
+
+ // Add the covered hosts in |hosts_fetched_| to the dictionary pref.
+ base::Time host_invalid_time =
+ time_clock_->Now() + kHintsFetcherHostFetchedValidDuration;
+ for (const std::string& host : hosts_fetched_) {
+ hosts_fetched_list->SetDoubleKey(
+ HashHostForDictionary(host),
+ host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF());
+ }
+ DCHECK_LE(hosts_fetched_list->size(),
+ features::MaxHostsForRecordingSuccessfullyCovered());
+ hosts_fetched_.clear();
+}
+
void HintsFetcher::OnURLLoadComplete(
std::unique_ptr<std::string> response_body) {
int response_code = -1;
diff --git a/chromium/components/optimization_guide/hints_fetcher.h b/chromium/components/optimization_guide/hints_fetcher.h
index f8bca072c7d..f477d62ae31 100644
--- a/chromium/components/optimization_guide/hints_fetcher.h
+++ b/chromium/components/optimization_guide/hints_fetcher.h
@@ -14,9 +14,12 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
+#include "base/time/clock.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "url/gurl.h"
+class PrefService;
+
namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
@@ -24,6 +27,12 @@ class SimpleURLLoader;
namespace optimization_guide {
+// Callback to inform the caller that the remote hints have been fetched and
+// to pass back the fetched hints response from the remote Optimization Guide
+// Service.
+using HintsFetchedCallback = base::OnceCallback<void(
+ base::Optional<std::unique_ptr<proto::GetHintsResponse>>)>;
+
// A class to handle requests for optimization hints from a remote Optimization
// Guide Service.
//
@@ -31,16 +40,11 @@ namespace optimization_guide {
// Owner must ensure that |hint_cache| remains alive for the lifetime of
// |HintsFetcher|.
class HintsFetcher {
- // Callback to inform the caller that the remote hints have been fetched and
- // to pass back the fetched hints response from the remote Optimization Guide
- // Service.
- using HintsFetchedCallback = base::OnceCallback<void(
- base::Optional<std::unique_ptr<proto::GetHintsResponse>>)>;
-
public:
HintsFetcher(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- GURL optimization_guide_service_url);
+ GURL optimization_guide_service_url,
+ PrefService* pref_service);
virtual ~HintsFetcher();
// Requests hints from the Optimization Guide Service if a request for them is
@@ -52,6 +56,18 @@ class HintsFetcher {
const std::vector<std::string>& hosts,
HintsFetchedCallback hints_fetched_callback);
+ // Set |time_clock_| for testing.
+ void SetTimeClockForTesting(const base::Clock* time_clock);
+
+ // Clear all the hosts and expiration times from the
+ // HintsFetcherHostsSuccessfullyFetched dictionary pref.
+ static void ClearHostsSuccessfullyFetched(PrefService* pref_service);
+
+ // Record whether the host was covered by a hints fetch and any returned
+ // hints would not have expired.
+ static void RecordHintsFetcherCoverage(PrefService* pref_serivce,
+ const std::string& host);
+
private:
// URL loader completion callback.
void OnURLLoadComplete(std::unique_ptr<std::string> response_body);
@@ -64,6 +80,13 @@ class HintsFetcher {
int status,
int response_code);
+ // Stores the hosts in |hosts_in_fetch_| in the
+ // HintsFetcherHostsSuccessfullyFetched dictionary pref. The value stored for
+ // each host is the time that the hints fetched for each host will expire.
+ // |hosts_in_fetch_| is cleared once the hosts are stored
+ // in the pref.
+ void UpdateHostsSuccessfullyFetched();
+
// Used to hold the GetHintsRequest being constructed and sent as a remote
// request.
std::unique_ptr<proto::GetHintsRequest> get_hints_request_;
@@ -78,6 +101,15 @@ class HintsFetcher {
// Holds the |URLLoader| for an active hints request.
std::unique_ptr<network::SimpleURLLoader> url_loader_;
+ // A reference to the PrefService for this profile. Not owned.
+ PrefService* pref_service_ = nullptr;
+
+ // Holds the hosts being requested by the hints fetcher.
+ std::vector<std::string> hosts_fetched_;
+
+ // Clock used for recording time that the hints fetch occurred.
+ const base::Clock* time_clock_;
+
// Used for creating a |url_loader_| when needed for request hints.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
diff --git a/chromium/components/optimization_guide/hints_fetcher_unittest.cc b/chromium/components/optimization_guide/hints_fetcher_unittest.cc
index 429e5632f46..710bb6a3ad5 100644
--- a/chromium/components/optimization_guide/hints_fetcher_unittest.cc
+++ b/chromium/components/optimization_guide/hints_fetcher_unittest.cc
@@ -11,10 +11,18 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/optimization_guide/hint_cache.h"
+#include "components/optimization_guide/hints_processing_util.h"
#include "components/optimization_guide/optimization_guide_features.h"
+#include "components/optimization_guide/optimization_guide_prefs.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/prefs/testing_pref_service.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -28,16 +36,23 @@ constexpr char optimization_guide_service_url[] = "https://hintsserver.com/";
class HintsFetcherTest : public testing::Test {
public:
- explicit HintsFetcherTest()
- : shared_url_loader_factory_(
+ HintsFetcherTest()
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME),
+ shared_url_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeatureWithParameters(
features::kOptimizationHintsFetching, {});
+ pref_service_ = std::make_unique<TestingPrefServiceSimple>();
+ prefs::RegisterProfilePrefs(pref_service_->registry());
+
hints_fetcher_ = std::make_unique<HintsFetcher>(
- shared_url_loader_factory_, GURL(optimization_guide_service_url));
+ shared_url_loader_factory_, GURL(optimization_guide_service_url),
+ pref_service_.get());
+ hints_fetcher_->SetTimeClockForTesting(task_environment_.GetMockClock());
}
~HintsFetcherTest() override {}
@@ -62,6 +77,24 @@ class HintsFetcherTest : public testing::Test {
network::mojom::ConnectionType::CONNECTION_4G);
}
+ void SeedCoveredHosts(const std::vector<std::string>& hosts,
+ base::Time host_invalid_time) {
+ DictionaryPrefUpdate hosts_fetched(
+ pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
+
+ for (const std::string& host : hosts) {
+ hosts_fetched->SetDoubleKey(
+ HashHostForDictionary(host),
+ host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF());
+ }
+ }
+
+ PrefService* pref_service() { return pref_service_.get(); }
+
+ const base::Clock* GetMockClock() const {
+ return task_environment_.GetMockClock();
+ }
+
protected:
bool FetchHints(const std::vector<std::string>& hosts) {
bool status = hints_fetcher_->FetchOptimizationGuideServiceHints(
@@ -90,17 +123,22 @@ class HintsFetcherTest : public testing::Test {
}
}
+ void SimulateNavigation(const std::string& host) {
+ HintsFetcher::RecordHintsFetcherCoverage(pref_service(), host);
+ }
+
private:
void RunUntilIdle() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
bool hints_fetched_ = false;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<HintsFetcher> hints_fetcher_;
+ std::unique_ptr<TestingPrefServiceSimple> pref_service_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
network::TestURLLoaderFactory test_url_loader_factory_;
network::TestNetworkConnectionTracker* network_tracker_;
@@ -162,4 +200,199 @@ TEST_F(HintsFetcherTest, FetchAttemptWhenNetworkOffline) {
EXPECT_TRUE(hints_fetched());
}
+TEST_F(HintsFetcherTest, HintsFetchSuccessfulHostsRecorded) {
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ std::string response_content;
+
+ EXPECT_TRUE(FetchHints(hosts));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
+ EXPECT_TRUE(hints_fetched());
+
+ const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary(
+ prefs::kHintsFetcherHostsSuccessfullyFetched);
+ base::Optional<double> value;
+ for (const std::string& host : hosts) {
+ value = hosts_fetched->FindDoubleKey(HashHostForDictionary(host));
+ EXPECT_EQ(base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSecondsD(*value)),
+ GetMockClock()->Now() + base::TimeDelta::FromDays(7));
+ }
+}
+
+TEST_F(HintsFetcherTest, HintsFetchFailsHostNotRecorded) {
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ std::string response_content;
+
+ EXPECT_TRUE(FetchHints(hosts));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_NOT_FOUND));
+ EXPECT_FALSE(hints_fetched());
+
+ const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary(
+ prefs::kHintsFetcherHostsSuccessfullyFetched);
+ for (const std::string& host : hosts) {
+ EXPECT_FALSE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host)));
+ }
+}
+
+TEST_F(HintsFetcherTest, HintsFetchClearHostsSuccessfullyFetched) {
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ std::string response_content;
+
+ EXPECT_TRUE(FetchHints(hosts));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
+ EXPECT_TRUE(hints_fetched());
+
+ const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary(
+ prefs::kHintsFetcherHostsSuccessfullyFetched);
+ for (const std::string& host : hosts) {
+ EXPECT_TRUE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host)));
+ }
+
+ HintsFetcher::ClearHostsSuccessfullyFetched(pref_service());
+ hosts_fetched = pref_service()->GetDictionary(
+ prefs::kHintsFetcherHostsSuccessfullyFetched);
+ for (const std::string& host : hosts) {
+ EXPECT_FALSE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host)));
+ }
+}
+
+TEST_F(HintsFetcherTest, HintsFetcherHostsCovered) {
+ base::HistogramTester histogram_tester;
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ base::Time host_invalid_time =
+ base::Time::Now() + base::TimeDelta().FromHours(1);
+
+ SeedCoveredHosts(hosts, host_invalid_time);
+
+ SimulateNavigation(hosts[0]);
+ SimulateNavigation(hosts[1]);
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
+}
+
+TEST_F(HintsFetcherTest, HintsFetcherCoveredHostExpired) {
+ base::HistogramTester histogram_tester;
+ std::string response_content;
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ base::Time host_invalid_time =
+ GetMockClock()->Now() - base::TimeDelta().FromHours(1);
+
+ SeedCoveredHosts(hosts, host_invalid_time);
+
+ // Fetch hints for new hosts.
+ std::vector<std::string> hosts_valid{"host3.com", "hosts4.com"};
+ EXPECT_TRUE(FetchHints(hosts_valid));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
+ EXPECT_TRUE(hints_fetched());
+
+ // The first pair of hosts should be recorded as failed to be
+ // covered by a recent hints fetcher as they have expired.
+ SimulateNavigation(hosts[0]);
+ SimulateNavigation(hosts[1]);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 2);
+
+ // The first pair of hosts should be removed from the dictionary
+ // pref as they have expired.
+ DictionaryPrefUpdate hosts_fetched(
+ pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
+ EXPECT_EQ(2u, hosts_fetched->size());
+
+ // Navigations to the valid hosts should be recorded as successfully
+ // covered.
+ SimulateNavigation(hosts_valid[0]);
+ SimulateNavigation(hosts_valid[1]);
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
+}
+
+TEST_F(HintsFetcherTest, HintsFetcherHostNotCovered) {
+ base::HistogramTester histogram_tester;
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ base::Time host_invalid_time =
+ base::Time::Now() + base::TimeDelta().FromHours(1);
+
+ SeedCoveredHosts(hosts, host_invalid_time);
+ DictionaryPrefUpdate hosts_fetched(
+ pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
+ EXPECT_EQ(2u, hosts_fetched->size());
+
+ SimulateNavigation(hosts[0]);
+ SimulateNavigation(hosts[1]);
+ SimulateNavigation("newhost.com");
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 1);
+}
+
+TEST_F(HintsFetcherTest, HintsFetcherRemoveExpiredOnSuccessfullyFetched) {
+ base::HistogramTester histogram_tester;
+ std::string response_content;
+ std::vector<std::string> hosts_expired{"host1.com", "host2.com"};
+ base::Time host_invalid_time =
+ GetMockClock()->Now() - base::TimeDelta().FromHours(1);
+
+ SeedCoveredHosts(hosts_expired, host_invalid_time);
+
+ std::vector<std::string> hosts_valid{"host3.com", "host4.com"};
+
+ EXPECT_TRUE(FetchHints(hosts_valid));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
+ EXPECT_TRUE(hints_fetched());
+
+ // The two expired hosts should be removed from the dictionary pref as they
+ // have expired.
+ DictionaryPrefUpdate hosts_fetched(
+ pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
+ EXPECT_EQ(2u, hosts_fetched->size());
+
+ SimulateNavigation(hosts_expired[0]);
+ SimulateNavigation(hosts_expired[1]);
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", false, 2);
+
+ SimulateNavigation(hosts_valid[0]);
+ SimulateNavigation(hosts_valid[1]);
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
+}
+
+TEST_F(HintsFetcherTest, HintsFetcherSuccessfullyFetchedHostsFull) {
+ base::HistogramTester histogram_tester;
+ std::string response_content;
+ std::vector<std::string> hosts;
+ size_t max_hosts =
+ optimization_guide::features::MaxHostsForRecordingSuccessfullyCovered();
+ for (size_t i = 0; i < max_hosts - 1; i++) {
+ hosts.push_back("host" + base::NumberToString(i) + ".com");
+ }
+ base::Time host_expiry_time =
+ GetMockClock()->Now() + base::TimeDelta().FromHours(1);
+
+ SeedCoveredHosts(hosts, host_expiry_time);
+
+ std::vector<std::string> extra_hosts{"extra1.com", "extra2.com"};
+
+ EXPECT_TRUE(FetchHints(extra_hosts));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
+ EXPECT_TRUE(hints_fetched());
+
+ // Navigations to both the extra hosts should be recorded.
+ DictionaryPrefUpdate hosts_fetched(
+ pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
+ EXPECT_EQ(200u, hosts_fetched->size());
+
+ SimulateNavigation(extra_hosts[0]);
+ SimulateNavigation(extra_hosts[1]);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintsFetcher.WasHostCoveredByFetch", true, 2);
+}
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/hints_processing_util.cc b/chromium/components/optimization_guide/hints_processing_util.cc
index 20427e0ddf0..a46666adb88 100644
--- a/chromium/components/optimization_guide/hints_processing_util.cc
+++ b/chromium/components/optimization_guide/hints_processing_util.cc
@@ -84,9 +84,8 @@ std::string HashHostForDictionary(const std::string& host) {
return base::StringPrintf("%x", base::PersistentHash(host));
}
-bool ProcessHints(
- google::protobuf::RepeatedPtrField<optimization_guide::proto::Hint>* hints,
- optimization_guide::HintUpdateData* hint_update_data) {
+bool ProcessHints(google::protobuf::RepeatedPtrField<proto::Hint>* hints,
+ optimization_guide::HintUpdateData* hint_update_data) {
// If there's no update data, then there's nothing to do.
if (!hint_update_data)
return false;
@@ -101,7 +100,7 @@ bool ProcessHints(
for (auto& hint : *hints) {
// We only support host suffixes at the moment. Skip anything else.
// One |hint| applies to one host URL suffix.
- if (hint.key_representation() != optimization_guide::proto::HOST_SUFFIX) {
+ if (hint.key_representation() != proto::HOST_SUFFIX) {
continue;
}
@@ -134,4 +133,22 @@ bool ProcessHints(
return did_process_hints;
}
+net::EffectiveConnectionType ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType proto_ect) {
+ switch (proto_ect) {
+ case proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
+ return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
+ case proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE:
+ return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE;
+ case proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
+ return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
+ case proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G:
+ return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G;
+ case proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G:
+ return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G;
+ case proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_4G:
+ return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_4G;
+ }
+}
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/hints_processing_util.h b/chromium/components/optimization_guide/hints_processing_util.h
index 459dcbbf9e1..f8aadc70362 100644
--- a/chromium/components/optimization_guide/hints_processing_util.h
+++ b/chromium/components/optimization_guide/hints_processing_util.h
@@ -8,6 +8,7 @@
#include <string>
#include "components/optimization_guide/proto/hints.pb.h"
+#include "net/nqe/effective_connection_type.h"
class GURL;
@@ -47,6 +48,10 @@ std::string HashHostForDictionary(const std::string& host);
bool ProcessHints(google::protobuf::RepeatedPtrField<proto::Hint>* hints,
HintUpdateData* hint_update_data);
+// Converts |proto_ect| into a net::EffectiveConnectionType.
+net::EffectiveConnectionType ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType proto_ect);
+
} // namespace optimization_guide
#endif // COMPONENTS_OPTIMIZATION_GUIDE_HINTS_PROCESSING_UTIL_H_
diff --git a/chromium/components/optimization_guide/hints_processing_util_unittest.cc b/chromium/components/optimization_guide/hints_processing_util_unittest.cc
index 48540517ae3..a1a258a085b 100644
--- a/chromium/components/optimization_guide/hints_processing_util_unittest.cc
+++ b/chromium/components/optimization_guide/hints_processing_util_unittest.cc
@@ -12,13 +12,7 @@
namespace optimization_guide {
-class HintsProcessingUtilTest : public testing::Test {
- public:
- HintsProcessingUtilTest() {}
- ~HintsProcessingUtilTest() override {}
-};
-
-TEST_F(HintsProcessingUtilTest, FindPageHintForSubstringPagePattern) {
+TEST(HintsProcessingUtilTest, FindPageHintForSubstringPagePattern) {
proto::Hint hint1;
// Page hint for "/one/"
@@ -64,7 +58,7 @@ TEST_F(HintsProcessingUtilTest, FindPageHintForSubstringPagePattern) {
GURL("https://www.foo.org/bar/three.jpg"), &hint1));
}
-TEST_F(HintsProcessingUtilTest, ProcessHintsNoUpdateData) {
+TEST(HintsProcessingUtilTest, ProcessHintsNoUpdateData) {
proto::Hint hint;
hint.set_key("whatever.com");
hint.set_key_representation(proto::HOST_SUFFIX);
@@ -77,7 +71,7 @@ TEST_F(HintsProcessingUtilTest, ProcessHintsNoUpdateData) {
EXPECT_FALSE(ProcessHints(&hints, nullptr));
}
-TEST_F(HintsProcessingUtilTest, ProcessHintsWithNoPageHintsAndUpdateData) {
+TEST(HintsProcessingUtilTest, ProcessHintsWithNoPageHintsAndUpdateData) {
proto::Hint hint;
hint.set_key("whatever.com");
hint.set_key_representation(proto::HOST_SUFFIX);
@@ -92,7 +86,7 @@ TEST_F(HintsProcessingUtilTest, ProcessHintsWithNoPageHintsAndUpdateData) {
EXPECT_EQ(1ul, update_data->TakeUpdateEntries()->size());
}
-TEST_F(HintsProcessingUtilTest, ProcessHintsWithPageHintsAndUpdateData) {
+TEST(HintsProcessingUtilTest, ProcessHintsWithPageHintsAndUpdateData) {
google::protobuf::RepeatedPtrField<proto::Hint> hints;
proto::Hint hint;
@@ -121,4 +115,28 @@ TEST_F(HintsProcessingUtilTest, ProcessHintsWithPageHintsAndUpdateData) {
EXPECT_EQ(2ul, update_data->TakeUpdateEntries()->size());
}
+TEST(HintsProcessingUtilTest, ConvertProtoEffectiveConnectionType) {
+ EXPECT_EQ(
+ ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
+ EXPECT_EQ(
+ ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE),
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
+ EXPECT_EQ(
+ ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G),
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+ EXPECT_EQ(ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G),
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G);
+ EXPECT_EQ(ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G),
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G);
+ EXPECT_EQ(ConvertProtoEffectiveConnectionType(
+ proto::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_4G),
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_4G);
+}
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/host_filter_unittest.cc b/chromium/components/optimization_guide/host_filter_unittest.cc
deleted file mode 100644
index 8c49bd1ceba..00000000000
--- a/chromium/components/optimization_guide/host_filter_unittest.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 "components/optimization_guide/host_filter.h"
-
-#include "base/macros.h"
-#include "components/optimization_guide/bloom_filter.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace optimization_guide {
-
-namespace {
-
-std::unique_ptr<BloomFilter> CreateBloomFilter() {
- std::unique_ptr<BloomFilter> filter = std::make_unique<BloomFilter>(
- 7 /* num_hash_functions */, 8191 /* num_bits */);
- return filter;
-}
-
-TEST(HostFilterTest, TestContainsHostSuffix) {
- std::unique_ptr<BloomFilter> bloom_filter(CreateBloomFilter());
- bloom_filter->Add("fooco.co.uk");
- HostFilter host_filter(std::move(bloom_filter));
- EXPECT_TRUE(
- host_filter.ContainsHostSuffix(GURL("http://shopping.fooco.co.uk")));
- EXPECT_TRUE(host_filter.ContainsHostSuffix(
- GURL("https://shopping.fooco.co.uk/somepath")));
- EXPECT_TRUE(host_filter.ContainsHostSuffix(GURL("https://fooco.co.uk")));
- EXPECT_FALSE(host_filter.ContainsHostSuffix(GURL("https://nonfooco.co.uk")));
-}
-
-TEST(HostFilterTest, TestContainsHostSuffixMaxSuffix) {
- std::unique_ptr<BloomFilter> bloom_filter(CreateBloomFilter());
- bloom_filter->Add("one.two.three.four.co.uk");
- bloom_filter->Add("one.two.three.four.five.co.uk");
- HostFilter host_filter(std::move(bloom_filter));
- EXPECT_TRUE(host_filter.ContainsHostSuffix(
- GURL("http://host.one.two.three.four.co.uk")));
- EXPECT_FALSE(host_filter.ContainsHostSuffix(
- GURL("http://host.one.two.three.four.five.co.uk")));
-
- // Note: full host will match even if more than 5 elements.
- EXPECT_TRUE(host_filter.ContainsHostSuffix(
- GURL("http://one.two.three.four.five.co.uk")));
-}
-
-TEST(HostFilterTest, TestContainsHostSuffixMinSuffix) {
- std::unique_ptr<BloomFilter> bloom_filter(CreateBloomFilter());
- bloom_filter->Add("abc.tv");
- bloom_filter->Add("xy.tv");
- HostFilter host_filter(std::move(bloom_filter));
- EXPECT_TRUE(host_filter.ContainsHostSuffix(GURL("https://abc.tv")));
- EXPECT_TRUE(host_filter.ContainsHostSuffix(GURL("https://host.abc.tv")));
- EXPECT_FALSE(host_filter.ContainsHostSuffix(GURL("https://host.xy.tv")));
-
- // Note: full host will match even if less than min size.
- EXPECT_TRUE(host_filter.ContainsHostSuffix(GURL("https://xy.tv")));
-}
-
-} // namespace
-
-} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/host_filter.cc b/chromium/components/optimization_guide/optimization_filter.cc
index 20636e7df11..801e1e2494e 100644
--- a/chromium/components/optimization_guide/host_filter.cc
+++ b/chromium/components/optimization_guide/optimization_filter.cc
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/optimization_guide/host_filter.h"
+#include "components/optimization_guide/optimization_filter.h"
#include <string>
+#include "base/strings/string_util.h"
+
namespace optimization_guide {
// Maximum number of suffixes to check per url.
@@ -14,20 +16,29 @@ const int kMaxSuffixCount = 5;
// Realistic minimum length of a host suffix.
const int kMinHostSuffix = 6; // eg., abc.tv
-HostFilter::HostFilter(std::unique_ptr<BloomFilter> bloom_filter)
- : bloom_filter_(std::move(bloom_filter)) {
+OptimizationFilter::OptimizationFilter(
+ std::unique_ptr<BloomFilter> bloom_filter,
+ std::unique_ptr<RegexpList> regexps)
+ : bloom_filter_(std::move(bloom_filter)), regexps_(std::move(regexps)) {
// May be created on one thread but used on another. The first call to
// CalledOnValidSequence() will re-bind it.
DETACH_FROM_SEQUENCE(sequence_checker_);
}
-HostFilter::~HostFilter() {
+OptimizationFilter::~OptimizationFilter() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
-bool HostFilter::ContainsHostSuffix(const GURL& url) const {
+bool OptimizationFilter::Matches(const GURL& url) const {
+ return ContainsHostSuffix(url) || MatchesRegexp(url);
+}
+
+bool OptimizationFilter::ContainsHostSuffix(const GURL& url) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!bloom_filter_)
+ return false;
+
// First check full host name.
if (bloom_filter_->Contains(url.host()))
return true;
@@ -50,4 +61,26 @@ bool HostFilter::ContainsHostSuffix(const GURL& url) const {
return false;
}
+bool OptimizationFilter::MatchesRegexp(const GURL& url) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!regexps_)
+ return false;
+
+ if (!url.is_valid())
+ return false;
+
+ std::string clean_url = base::ToLowerASCII(url.GetAsReferrer().spec());
+ for (auto& regexp : *regexps_) {
+ if (!regexp->ok()) {
+ continue;
+ }
+
+ if (re2::RE2::PartialMatch(clean_url, *regexp)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/host_filter.h b/chromium/components/optimization_guide/optimization_filter.h
index b74da202d8e..9b93aacbf56 100644
--- a/chromium/components/optimization_guide/host_filter.h
+++ b/chromium/components/optimization_guide/optimization_filter.h
@@ -2,27 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OPTIMIZATION_GUIDE_HOST_FILTER_H_
-#define COMPONENTS_OPTIMIZATION_GUIDE_HOST_FILTER_H_
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_FILTER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_FILTER_H_
+
+#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/bloom_filter.h"
+#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"
namespace optimization_guide {
-// HostFilter is a simple Host filter for keeping track of a set of strings
-// that are represented by a Bloom filter.
+typedef std::vector<std::unique_ptr<re2::RE2>> RegexpList;
+
+// OptimizationFilter represents a filter with two underlying implementations: a
+// Bloom filter and a set of regexps. This class has a 1:1 mapping with an
+// OptimizationFilter protobuf message where this is the logical implementation
+// of the proto data.
//
// TODO(dougarnett): consider moving this and BloomFilter under
// components/blacklist/.
-class HostFilter {
+class OptimizationFilter {
public:
- explicit HostFilter(std::unique_ptr<BloomFilter> bloom_filter);
+ explicit OptimizationFilter(std::unique_ptr<BloomFilter> bloom_filter,
+ std::unique_ptr<RegexpList> regexps);
- virtual ~HostFilter();
+ ~OptimizationFilter();
+ // Returns true if the given url is matched by this filter.
+ bool Matches(const GURL& url) const;
+
+ private:
// Returns whether this filter contains a host suffix for the host part
// of |url|. It will check at most 5 host suffixes and it may ignore simple
// top level domain matches (such as "com" or "co.in").
@@ -34,18 +47,20 @@ class HostFilter {
// "www.company.co.in"
// "company.co.in"
// This method will return true if any of those suffixes are present.
- //
- // Virtual for testing.
- virtual bool ContainsHostSuffix(const GURL& url) const;
+ bool ContainsHostSuffix(const GURL& url) const;
+
+ // Returns whether this filter contains a regexp that matches the given url.
+ bool MatchesRegexp(const GURL& url) const;
- private:
std::unique_ptr<BloomFilter> bloom_filter_;
+ std::unique_ptr<RegexpList> regexps_;
+
SEQUENCE_CHECKER(sequence_checker_);
- DISALLOW_COPY_AND_ASSIGN(HostFilter);
+ DISALLOW_COPY_AND_ASSIGN(OptimizationFilter);
};
} // namespace optimization_guide
-#endif // COMPONENTS_OPTIMIZATION_GUIDE_HOST_FILTER_H_
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_FILTER_H_
diff --git a/chromium/components/optimization_guide/optimization_filter_unittest.cc b/chromium/components/optimization_guide/optimization_filter_unittest.cc
new file mode 100644
index 00000000000..c1e29d95cb0
--- /dev/null
+++ b/chromium/components/optimization_guide/optimization_filter_unittest.cc
@@ -0,0 +1,101 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/optimization_guide/optimization_filter.h"
+
+#include "base/macros.h"
+#include "components/optimization_guide/bloom_filter.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace optimization_guide {
+
+namespace {
+
+std::unique_ptr<BloomFilter> CreateBloomFilter() {
+ std::unique_ptr<BloomFilter> filter = std::make_unique<BloomFilter>(
+ 7 /* num_hash_functions */, 8191 /* num_bits */);
+ return filter;
+}
+
+std::unique_ptr<RegexpList> CreateRegexps(
+ const std::vector<std::string>& regexps) {
+ std::unique_ptr<RegexpList> regexp_list = std::make_unique<RegexpList>();
+ for (const std::string& regexp : regexps) {
+ regexp_list->emplace_back(std::make_unique<re2::RE2>(regexp));
+ }
+ return regexp_list;
+}
+
+TEST(OptimizationFilterTest, TestMatchesBloomFilter) {
+ std::unique_ptr<BloomFilter> bloom_filter(CreateBloomFilter());
+ bloom_filter->Add("fooco.co.uk");
+ OptimizationFilter opt_filter(std::move(bloom_filter), nullptr);
+ EXPECT_TRUE(opt_filter.Matches(GURL("http://shopping.fooco.co.uk")));
+ EXPECT_TRUE(
+ opt_filter.Matches(GURL("https://shopping.fooco.co.uk/somepath")));
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://fooco.co.uk")));
+ EXPECT_FALSE(opt_filter.Matches(GURL("https://nonfooco.co.uk")));
+}
+
+TEST(OptimizationFilterTest, TestMatchesRegexp) {
+ std::unique_ptr<RegexpList> regexps(CreateRegexps({"test"}));
+ OptimizationFilter opt_filter(nullptr, std::move(regexps));
+ EXPECT_TRUE(opt_filter.Matches(GURL("http://test.com")));
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://shopping.com/test")));
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://shopping.com/?query=test")));
+ EXPECT_FALSE(opt_filter.Matches(GURL("https://shopping.com/")));
+}
+
+TEST(OptimizationFilterTest, TestMatchesRegexpFragment) {
+ std::unique_ptr<RegexpList> regexps(CreateRegexps({"test"}));
+ OptimizationFilter opt_filter(nullptr, std::move(regexps));
+ // Fragments are not matched.
+ EXPECT_FALSE(opt_filter.Matches(GURL("https://shopping.com/#test")));
+}
+
+TEST(OptimizationFilterTest, TestMatchesRegexpInvalid) {
+ std::unique_ptr<RegexpList> regexps(CreateRegexps({"test[", "shop"}));
+ OptimizationFilter opt_filter(nullptr, std::move(regexps));
+ // Invalid regexps are not used
+ EXPECT_FALSE(opt_filter.Matches(GURL("https://test.com/")));
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://shopping.com/")));
+}
+
+TEST(OptimizationFilterTest, TestMatchesRegexpInvalidGURL) {
+ std::unique_ptr<RegexpList> regexps(CreateRegexps({"test"}));
+ OptimizationFilter opt_filter(nullptr, std::move(regexps));
+ // Invalid urls are not matched.
+ EXPECT_FALSE(opt_filter.Matches(GURL("test")));
+}
+
+TEST(OptimizationFilterTest, TestMatchesMaxSuffix) {
+ std::unique_ptr<BloomFilter> bloom_filter(CreateBloomFilter());
+ bloom_filter->Add("one.two.three.four.co.uk");
+ bloom_filter->Add("one.two.three.four.five.co.uk");
+ OptimizationFilter opt_filter(std::move(bloom_filter), nullptr);
+ EXPECT_TRUE(opt_filter.Matches(GURL("http://host.one.two.three.four.co.uk")));
+ EXPECT_FALSE(
+ opt_filter.Matches(GURL("http://host.one.two.three.four.five.co.uk")));
+
+ // Note: full host will match even if more than 5 elements.
+ EXPECT_TRUE(opt_filter.Matches(GURL("http://one.two.three.four.five.co.uk")));
+}
+
+TEST(OptimizationFilterTest, TestMatchesMinSuffix) {
+ std::unique_ptr<BloomFilter> bloom_filter(CreateBloomFilter());
+ bloom_filter->Add("abc.tv");
+ bloom_filter->Add("xy.tv");
+ OptimizationFilter opt_filter(std::move(bloom_filter), nullptr);
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://abc.tv")));
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://host.abc.tv")));
+ EXPECT_FALSE(opt_filter.Matches(GURL("https://host.xy.tv")));
+
+ // Note: full host will match even if less than min size.
+ EXPECT_TRUE(opt_filter.Matches(GURL("https://xy.tv")));
+}
+
+} // namespace
+
+} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/optimization_guide_constants.cc b/chromium/components/optimization_guide/optimization_guide_constants.cc
index f54c785d200..573d741f648 100644
--- a/chromium/components/optimization_guide/optimization_guide_constants.cc
+++ b/chromium/components/optimization_guide/optimization_guide_constants.cc
@@ -14,4 +14,7 @@ const char kRulesetFormatVersionString[] = "1.0.0";
const char kOptimizationGuideServiceDefaultURL[] =
"https://optimizationguide-pa.googleapis.com/v1:GetHints";
+const char kLoadedHintLocalHistogramString[] =
+ "OptimizationGuide.LoadedHint.Result";
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/optimization_guide_constants.h b/chromium/components/optimization_guide/optimization_guide_constants.h
index 7639f4501d3..cd81f88a87d 100644
--- a/chromium/components/optimization_guide/optimization_guide_constants.h
+++ b/chromium/components/optimization_guide/optimization_guide_constants.h
@@ -17,6 +17,10 @@ extern const char kRulesetFormatVersionString[];
// The remote Optimization Guide Service production server to fetch hints from.
extern const char kOptimizationGuideServiceDefaultURL[];
+// The local histogram used to record that the component hints are stored in
+// the cache and are ready for use.
+extern const char kLoadedHintLocalHistogramString[];
+
} // namespace optimization_guide
#endif // COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_CONSTANTS_H_
diff --git a/chromium/components/optimization_guide/optimization_guide_decider.h b/chromium/components/optimization_guide/optimization_guide_decider.h
new file mode 100644
index 00000000000..69e4d16b6eb
--- /dev/null
+++ b/chromium/components/optimization_guide/optimization_guide_decider.h
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_DECIDER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_DECIDER_H_
+
+#include <vector>
+
+#include "components/optimization_guide/proto/hints.pb.h"
+
+namespace content {
+class NavigationHandle;
+} // namespace content
+
+namespace optimization_guide {
+
+// Represents the decision made by the optimization guide.
+enum class OptimizationGuideDecision {
+ // The necessary information to make the decision is not yet available.
+ kUnknown,
+ // The necessary information to make the decision is available and the
+ // decision is affirmative.
+ kTrue,
+ // The necessary information to make the decision is available and the
+ // decision is negative.
+ kFalse,
+
+ // New values above this line.
+ kMaxValue = kFalse,
+};
+
+// The types of pages the optimization guide understands how to classify.
+enum class OptimizationTarget {
+ kUnknown,
+ // Should only be applied when the page load is predicted to be painful.
+ kPainfulPageLoad,
+};
+
+// Contains metadata for the optimization.
+struct OptimizationMetadata {
+ // Only applicable for NOSCRIPT and RESOURCE_LOADING optimization types.
+ proto::PreviewsMetadata previews_metadata;
+};
+
+class OptimizationGuideDecider {
+ public:
+ // Registers the optimization types that intend to be queried during the
+ // session.
+ virtual void RegisterOptimizationTypes(
+ std::vector<proto::OptimizationType> optimization_types) = 0;
+
+ // Returns whether the current conditions match |optimization_target| and
+ // |optimization_type| can be applied for the URL associated with
+ // |navigation_handle|.
+ virtual OptimizationGuideDecision CanApplyOptimization(
+ content::NavigationHandle* navigation_handle,
+ OptimizationTarget optimization_target,
+ proto::OptimizationType optimization_type,
+ OptimizationMetadata* optimization_metadata) = 0;
+
+ protected:
+ OptimizationGuideDecider() {}
+ virtual ~OptimizationGuideDecider() {}
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_DECIDER_H_
diff --git a/chromium/components/optimization_guide/optimization_guide_enums.h b/chromium/components/optimization_guide/optimization_guide_enums.h
new file mode 100644
index 00000000000..b00303d44fa
--- /dev/null
+++ b/chromium/components/optimization_guide/optimization_guide_enums.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_ENUMS_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_ENUMS_H_
+
+namespace optimization_guide {
+
+// The types of decisions that can be made for an optimization type.
+//
+// Keep in sync with OptimizationGuideOptimizationTypeDecision in enums.xml.
+enum class OptimizationTypeDecision {
+ kUnknown,
+ // The optimization type was allowed for the page load by an optimization
+ // filter for the type.
+ kAllowedByOptimizationFilter,
+ // The optimization type was not allowed for the page load by an optimization
+ // filter for the type.
+ kNotAllowedByOptimizationFilter,
+ // An optimization filter for that type was on the device but was not loaded
+ // in time to make a decision. There is no guarantee that had the filter been
+ // loaded that the page load would have been allowed for the optimization
+ // type.
+ kHadOptimizationFilterButNotLoadedInTime,
+ // The optimization type was allowed for the page load based on a hint.
+ kAllowedByHint,
+ // A hint that matched the page load was present but the optimization type was
+ // not allowed to be applied.
+ kNotAllowedByHint,
+ // A hint was available but there was not a page hint within that hint that
+ // matched the page load.
+ kNoMatchingPageHint,
+ // A hint that matched the page load was on the device but was not loaded in
+ // time to make a decision. There is no guarantee that had the hint been
+ // loaded that the page load would have been allowed for the optimization
+ // type.
+ kHadHintButNotLoadedInTime,
+ // No hints were available in the cache that matched the page load.
+ kNoHintAvailable,
+
+ // Add new values above this line.
+ kMaxValue = kNoHintAvailable,
+};
+
+// The types of decisions that can be made for an optimization target.
+//
+// Keep in sync with OptimizationGuideOptimizationTargetDecision in enums.xml.
+enum class OptimizationTargetDecision {
+ kUnknown,
+ // The page load does not match the optimization target.
+ kPageLoadDoesNotMatch,
+ // The page load matches the optimization target.
+ kPageLoadMatches,
+
+ // Add new values above this line.
+ kMaxValue = kPageLoadMatches,
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_ENUMS_H_
diff --git a/chromium/components/optimization_guide/optimization_guide_features.cc b/chromium/components/optimization_guide/optimization_guide_features.cc
index 5b51443405b..0ea8f56d173 100644
--- a/chromium/components/optimization_guide/optimization_guide_features.cc
+++ b/chromium/components/optimization_guide/optimization_guide_features.cc
@@ -11,7 +11,6 @@
#include "base/metrics/field_trial_params.h"
#include "build/build_config.h"
#include "components/optimization_guide/optimization_guide_constants.h"
-#include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/optimization_guide_switches.h"
#include "google_apis/google_api_keys.h"
#include "net/base/url_util.h"
@@ -50,13 +49,20 @@ const base::Feature kSlowPageTriggering{"PreviewsSlowPageTriggering",
const base::Feature kOptimizationHintsFetching{
"OptimizationHintsFetching", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables the initialization of the Optimization Guide Keyed Service.
+const base::Feature kOptimizationGuideKeyedService{
+ "OptimizationGuideKeyedService", base::FEATURE_DISABLED_BY_DEFAULT};
+
size_t MaxHintsFetcherTopHostBlacklistSize() {
// The blacklist will be limited to the most engaged hosts and will hold twice
// (2*N) as many hosts that the HintsFetcher request hints for. The extra N
// hosts on the blacklist are meant to cover the case that the engagement
// scores on some of the top N host engagement scores decay and they fall out
// of the top N.
- return 2 * MaxHostsForOptimizationGuideServiceHintsFetch();
+ return GetFieldTrialParamByFeatureAsInt(features::kOptimizationHintsFetching,
+ "top_host_blacklist_size_multiplier",
+ 2) *
+ MaxHostsForOptimizationGuideServiceHintsFetch();
}
size_t MaxHostsForOptimizationGuideServiceHintsFetch() {
@@ -65,12 +71,33 @@ size_t MaxHostsForOptimizationGuideServiceHintsFetch() {
"max_hosts_for_optimization_guide_service_hints_fetch", 30);
}
+size_t MaxHostsForRecordingSuccessfullyCovered() {
+ return GetFieldTrialParamByFeatureAsInt(
+ features::kOptimizationHintsFetching,
+ "max_hosts_for_recording_successfully_covered", 200);
+}
+
+double MinTopHostEngagementScoreThreshold() {
+ // The default initial site engagement score for a navigation is 3.0, 1.5
+ // points for a navigation from the omnibox and 1.5 points for the first
+ // navigation of the day.
+ return GetFieldTrialParamByFeatureAsDouble(
+ features::kOptimizationHintsFetching,
+ "min_top_host_engagement_score_threshold", 3.0);
+}
+
base::TimeDelta StoredFetchedHintsFreshnessDuration() {
return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt(
features::kOptimizationHintsFetching,
"max_store_duration_for_featured_hints_in_days", 7));
}
+base::TimeDelta DurationApplyLowEngagementScoreThreshold() {
+ return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt(
+ features::kOptimizationHintsFetching,
+ "duration_apply_low_engagement_score_threshold_in_days", 30));
+}
+
std::string GetOptimizationGuideServiceAPIKey() {
// Command line override takes priority.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -112,5 +139,15 @@ bool IsHintsFetchingEnabled() {
return base::FeatureList::IsEnabled(features::kOptimizationHintsFetching);
}
+bool IsOptimizationGuideKeyedServiceEnabled() {
+ return base::FeatureList::IsEnabled(features::kOptimizationGuideKeyedService);
+}
+
+int MaxServerBloomFilterByteSize() {
+ return base::GetFieldTrialParamByFeatureAsInt(features::kOptimizationHints,
+ "max_bloom_filter_byte_size",
+ 250 * 1024 /* 250KB */);
+}
+
} // namespace features
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/optimization_guide_features.h b/chromium/components/optimization_guide/optimization_guide_features.h
index 50385e8edcb..b560ea45dc8 100644
--- a/chromium/components/optimization_guide/optimization_guide_features.h
+++ b/chromium/components/optimization_guide/optimization_guide_features.h
@@ -20,6 +20,7 @@ extern const base::Feature kOptimizationHintsExperiments;
constexpr char kOptimizationHintsExperimentNameParam[] = "experiment_name";
extern const base::Feature kSlowPageTriggering;
extern const base::Feature kOptimizationHintsFetching;
+extern const base::Feature kOptimizationGuideKeyedService;
// The maximum number of hosts that can be stored in the
// |kHintsFetcherTopHostBlacklist| dictionary pref when initialized. The top
@@ -32,10 +33,24 @@ size_t MaxHintsFetcherTopHostBlacklistSize();
// remote Optimzation Guide Service.
size_t MaxHostsForOptimizationGuideServiceHintsFetch();
+// The maximum number of hosts allowed to be stored as covered by the hints
+// fetcher.
+size_t MaxHostsForRecordingSuccessfullyCovered();
+
+// The minimum score required to be considered a top host and be included in a
+// hints fetch request.
+double MinTopHostEngagementScoreThreshold();
+
// The amount of time a fetched hint will be considered fresh enough
// to be used and remain in the HintCacheStore.
base::TimeDelta StoredFetchedHintsFreshnessDuration();
+// The duration of time after the blacklist initialization for which the low
+// engagement score threshold needs to be applied. If the blacklist was
+// initialized more than DurationApplyLowEngagementScoreThreshold() ago, then
+// the low engagement score threshold need not be applied.
+base::TimeDelta DurationApplyLowEngagementScoreThreshold();
+
// The API key for the One Platform Optimization Guide Service.
std::string GetOptimizationGuideServiceAPIKey();
@@ -49,6 +64,15 @@ bool IsOptimizationHintsEnabled();
// Service is enabled.
bool IsHintsFetchingEnabled();
+// Returns true if the initialization of the Optimization Guide Keyed Service is
+// enabled.
+bool IsOptimizationGuideKeyedServiceEnabled();
+
+// The maximum data byte size for a server-provided bloom filter. This is
+// a client-side safety limit for RAM use in case server sends too large of
+// a bloom filter.
+int MaxServerBloomFilterByteSize();
+
} // namespace features
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/optimization_guide_prefs.cc b/chromium/components/optimization_guide/optimization_guide_prefs.cc
index 5d1639314cf..0650a0df65b 100644
--- a/chromium/components/optimization_guide/optimization_guide_prefs.cc
+++ b/chromium/components/optimization_guide/optimization_guide_prefs.cc
@@ -4,16 +4,12 @@
#include "components/optimization_guide/optimization_guide_prefs.h"
+#include "components/optimization_guide/optimization_guide_features.h"
#include "components/prefs/pref_registry_simple.h"
namespace optimization_guide {
namespace prefs {
-// A dictionary pref that stores counts for the number of times a hint was
-// attempted to be loaded and counts for the number of times a hint was actually
-// loaded, broken down by hint source.
-const char kHintLoadedCounts[] = "optimization_guide.hint_loaded_counts";
-
// A pref that stores the last time a hints fetch was attempted. This limits the
// frequency that hints are fetched and prevents a crash loop that continually
// fetches hints on startup.
@@ -24,27 +20,67 @@ const char kHintsFetcherLastFetchAttempt[] =
// for until visited again after DataSaver was enabled. If The hash of the host
// is in the dictionary, then it is on the blacklist and should not be used, the
// |value| in the key-value pair is not used.
-const char kHintsFetcherTopHostBlacklist[] =
+const char kHintsFetcherDataSaverTopHostBlacklist[] =
"optimization_guide.hintsfetcher.top_host_blacklist";
// An integer pref that stores the state of the blacklist for the top host
// provider for blacklisting hosts after DataSaver is enabled. The state maps to
// the HintsFetcherTopHostBlacklistState enum.
-const char kHintsFetcherTopHostBlacklistState[] =
+const char kHintsFetcherDataSaverTopHostBlacklistState[] =
"optimization_guide.hintsfetcher.top_host_blacklist_state";
+// Time when the blacklist was last initialized. Recorded as seconds since
+// epoch.
+const char kTimeBlacklistLastInitialized[] =
+ "optimization_guide.hintsfetcher.time_blacklist_last_initialized";
+
+// If a host has site engagement score less than the value stored in this pref,
+// then hints fetcher may not fetch hints for that host.
+const char kHintsFetcherDataSaverTopHostBlacklistMinimumEngagementScore[] =
+ "optimization_guide.hintsfetcher.top_host_blacklist_min_engagement_score";
+
+// A dictionary pref that stores hosts that have had hints successfully fetched
+// from the remote Optimization Guide Server. The entry for each host contains
+// the time that the fetch that covered this host expires, i.e., any hints
+// from the fetch would be considered stale.
+const char kHintsFetcherHostsSuccessfullyFetched[] =
+ "optimization_guide.hintsfetcher.hosts_successfully_fetched";
+
+// A string pref that stores the version of the Optimization Hints component
+// that is currently being processed. This pref is cleared once processing
+// completes. It is used for detecting a potential crash loop on processing a
+// version of hints.
+const char kPendingHintsProcessingVersion[] =
+ "optimization_guide.pending_hints_processing_version";
+
void RegisterProfilePrefs(PrefRegistrySimple* registry) {
- registry->RegisterDictionaryPref(kHintLoadedCounts, PrefRegistry::LOSSY_PREF);
registry->RegisterInt64Pref(
kHintsFetcherLastFetchAttempt,
base::Time().ToDeltaSinceWindowsEpoch().InMicroseconds(),
PrefRegistry::LOSSY_PREF);
- registry->RegisterDictionaryPref(kHintsFetcherTopHostBlacklist,
+ registry->RegisterDictionaryPref(kHintsFetcherDataSaverTopHostBlacklist,
+ PrefRegistry::LOSSY_PREF);
+ registry->RegisterDictionaryPref(kHintsFetcherHostsSuccessfullyFetched,
PrefRegistry::LOSSY_PREF);
registry->RegisterIntegerPref(
- kHintsFetcherTopHostBlacklistState,
+ kHintsFetcherDataSaverTopHostBlacklistState,
static_cast<int>(HintsFetcherTopHostBlacklistState::kNotInitialized),
PrefRegistry::LOSSY_PREF);
+ registry->RegisterDoublePref(kTimeBlacklistLastInitialized, 0,
+ PrefRegistry::LOSSY_PREF);
+
+ // Use a default value of MinTopHostEngagementScoreThreshold() for the
+ // threshold. This ensures that the users for which this pref can't be
+ // computed (possibly because they had the blacklist initialized before this
+ // pref was added to the code) use the default value for the site engagement
+ // threshold.
+ registry->RegisterDoublePref(
+ kHintsFetcherDataSaverTopHostBlacklistMinimumEngagementScore,
+ optimization_guide::features::MinTopHostEngagementScoreThreshold(),
+ PrefRegistry::LOSSY_PREF);
+
+ registry->RegisterStringPref(kPendingHintsProcessingVersion, "",
+ PrefRegistry::LOSSY_PREF);
}
} // namespace prefs
diff --git a/chromium/components/optimization_guide/optimization_guide_prefs.h b/chromium/components/optimization_guide/optimization_guide_prefs.h
index 3c0d9986b89..2a81f6fdf45 100644
--- a/chromium/components/optimization_guide/optimization_guide_prefs.h
+++ b/chromium/components/optimization_guide/optimization_guide_prefs.h
@@ -12,10 +12,14 @@ class PrefRegistrySimple;
namespace optimization_guide {
namespace prefs {
-extern const char kHintLoadedCounts[];
extern const char kHintsFetcherLastFetchAttempt[];
-extern const char kHintsFetcherTopHostBlacklist[];
-extern const char kHintsFetcherTopHostBlacklistState[];
+extern const char kHintsFetcherDataSaverTopHostBlacklist[];
+extern const char kHintsFetcherDataSaverTopHostBlacklistState[];
+extern const char kTimeBlacklistLastInitialized[];
+extern const char
+ kHintsFetcherDataSaverTopHostBlacklistMinimumEngagementScore[];
+extern const char kHintsFetcherHostsSuccessfullyFetched[];
+extern const char kPendingHintsProcessingVersion[];
// State of |HintsFetcherTopHostsBlacklist|. The blacklist begins in
// kNotInitialized and transitions to kInitialized after
diff --git a/chromium/components/optimization_guide/optimization_guide_service_unittest.cc b/chromium/components/optimization_guide/optimization_guide_service_unittest.cc
index 5a768353fa0..6a359b63eb8 100644
--- a/chromium/components/optimization_guide/optimization_guide_service_unittest.cc
+++ b/chromium/components/optimization_guide/optimization_guide_service_unittest.cc
@@ -12,7 +12,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/version.h"
#include "components/optimization_guide/hints_component_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -63,7 +63,7 @@ class OptimizationGuideServiceTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
optimization_guide_service_ = std::make_unique<OptimizationGuideService>(
- scoped_task_environment_.GetMainThreadTaskRunner());
+ task_environment_.GetMainThreadTaskRunner());
observer_ = std::make_unique<TestObserver>();
}
@@ -82,14 +82,14 @@ class OptimizationGuideServiceTest : public testing::Test {
void MaybeUpdateHintsComponent(const HintsComponentInfo& info) {
optimization_guide_service_->MaybeUpdateHintsComponent(info);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
base::FilePath temp_dir() const { return temp_dir_.GetPath(); }
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<OptimizationGuideService> optimization_guide_service_;
diff --git a/chromium/components/optimization_guide/proto/hints.proto b/chromium/components/optimization_guide/proto/hints.proto
index 2f4ea430eb1..8175f42bb4e 100644
--- a/chromium/components/optimization_guide/proto/hints.proto
+++ b/chromium/components/optimization_guide/proto/hints.proto
@@ -243,6 +243,9 @@ message OptimizationFilter {
optional OptimizationType optimization_type = 1;
// The filter data represented as a Bloom filter.
optional BloomFilter bloom_filter = 2;
+ // Additional filters represented as regexps matched against the main page
+ // URL.
+ repeated string regexps = 3;
}
message Configuration {
diff --git a/chromium/components/optimization_guide/test_hints_component_creator.cc b/chromium/components/optimization_guide/test_hints_component_creator.cc
index aef242d3654..6068ac044ab 100644
--- a/chromium/components/optimization_guide/test_hints_component_creator.cc
+++ b/chromium/components/optimization_guide/test_hints_component_creator.cc
@@ -4,12 +4,30 @@
#include "components/optimization_guide/test_hints_component_creator.h"
+#include <memory>
+
+#include "base/base64.h"
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/version.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
+std::string GetDefaultHintVersionString() {
+ optimization_guide::proto::Version hint_version;
+ hint_version.mutable_generation_timestamp()->set_seconds(123);
+ hint_version.set_hint_source(
+ optimization_guide::proto::HINT_SOURCE_OPTIMIZATION_HINTS_COMPONENT);
+ std::string hint_version_string;
+ hint_version.SerializeToString(&hint_version_string);
+ base::Base64Encode(hint_version_string, &hint_version_string);
+ return hint_version_string;
+}
+
+} // namespace
+
namespace optimization_guide {
namespace testing {
@@ -33,23 +51,43 @@ TestHintsComponentCreator::CreateHintsComponentInfoWithPageHints(
optimization_guide::proto::Hint* hint = config.add_hints();
hint->set_key(page_hint_site);
hint->set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+ hint->set_version(GetDefaultHintVersionString());
optimization_guide::proto::PageHint* page_hint = hint->add_page_hints();
page_hint->set_page_pattern(page_pattern);
+ page_hint->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
optimization_guide::proto::Optimization* optimization =
page_hint->add_whitelisted_optimizations();
optimization->set_optimization_type(optimization_type);
+ optimization->mutable_previews_metadata()->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
for (auto resource_blocking_pattern : resource_blocking_patterns) {
optimization_guide::proto::ResourceLoadingHint* resource_loading_hint =
- optimization->add_resource_loading_hints();
+ optimization->mutable_previews_metadata()
+ ->add_resource_loading_hints();
resource_loading_hint->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_loading_hint->set_resource_pattern(resource_blocking_pattern);
}
}
+ // Always stick something with no hint version in here.
+ optimization_guide::proto::Hint* no_version_hint = config.add_hints();
+ no_version_hint->set_key("noversion.com");
+ no_version_hint->set_key_representation(
+ optimization_guide::proto::HOST_SUFFIX);
+ no_version_hint->add_page_hints()->set_page_pattern("*");
+ // Always stick something with a bad hint version in here.
+ optimization_guide::proto::Hint* bad_version_hint = config.add_hints();
+ bad_version_hint->set_key("badversion.com");
+ bad_version_hint->set_key_representation(
+ optimization_guide::proto::HOST_SUFFIX);
+ bad_version_hint->set_version("notaversion");
+ bad_version_hint->add_page_hints()->set_page_pattern("*");
+
return WriteConfigToFileAndReturnHintsComponentInfo(config);
}
@@ -63,23 +101,42 @@ TestHintsComponentCreator::CreateHintsComponentInfoWithExperimentalPageHints(
optimization_guide::proto::Hint* hint = config.add_hints();
hint->set_key(page_hint_site);
hint->set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+ hint->set_version(GetDefaultHintVersionString());
optimization_guide::proto::PageHint* page_hint = hint->add_page_hints();
page_hint->set_page_pattern("*");
+ page_hint->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
optimization_guide::proto::Optimization* optimization =
page_hint->add_whitelisted_optimizations();
optimization->set_optimization_type(optimization_type);
optimization->set_experiment_name(kFooExperimentName);
+ optimization->mutable_previews_metadata()->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
for (auto resource_blocking_pattern : experimental_resource_patterns) {
optimization_guide::proto::ResourceLoadingHint* resource_loading_hint =
- optimization->add_resource_loading_hints();
+ optimization->mutable_previews_metadata()
+ ->add_resource_loading_hints();
resource_loading_hint->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_loading_hint->set_resource_pattern(resource_blocking_pattern);
}
}
+ // Always stick something with no hint version in here.
+ optimization_guide::proto::Hint* no_version_hint = config.add_hints();
+ no_version_hint->set_key("noversion.com");
+ no_version_hint->set_key_representation(
+ optimization_guide::proto::HOST_SUFFIX);
+ no_version_hint->add_page_hints()->set_page_pattern("*");
+ // Always stick something with a bad hint version in here.
+ optimization_guide::proto::Hint* bad_version_hint = config.add_hints();
+ bad_version_hint->set_key("badversion.com");
+ bad_version_hint->set_key_representation(
+ optimization_guide::proto::HOST_SUFFIX);
+ bad_version_hint->set_version("notaversion");
+ bad_version_hint->add_page_hints()->set_page_pattern("*");
return WriteConfigToFileAndReturnHintsComponentInfo(config);
}
@@ -95,9 +152,12 @@ TestHintsComponentCreator::CreateHintsComponentInfoWithMixPageHints(
optimization_guide::proto::Hint* hint = config.add_hints();
hint->set_key(page_hint_site);
hint->set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+ hint->set_version(GetDefaultHintVersionString());
optimization_guide::proto::PageHint* page_hint = hint->add_page_hints();
page_hint->set_page_pattern("*");
+ page_hint->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
// Add experimental patterns first so they get higher priority.
{
@@ -105,10 +165,13 @@ TestHintsComponentCreator::CreateHintsComponentInfoWithMixPageHints(
page_hint->add_whitelisted_optimizations();
optimization->set_optimization_type(optimization_type);
optimization->set_experiment_name(kFooExperimentName);
+ optimization->mutable_previews_metadata()->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
for (auto resource_blocking_pattern : experimental_resource_patterns) {
optimization_guide::proto::ResourceLoadingHint* resource_loading_hint =
- optimization->add_resource_loading_hints();
+ optimization->mutable_previews_metadata()
+ ->add_resource_loading_hints();
resource_loading_hint->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_loading_hint->set_resource_pattern(resource_blocking_pattern);
@@ -119,16 +182,32 @@ TestHintsComponentCreator::CreateHintsComponentInfoWithMixPageHints(
optimization_guide::proto::Optimization* optimization =
page_hint->add_whitelisted_optimizations();
optimization->set_optimization_type(optimization_type);
+ optimization->mutable_previews_metadata()->set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_2G);
for (auto resource_blocking_pattern : default_resource_patterns) {
optimization_guide::proto::ResourceLoadingHint* resource_loading_hint =
- optimization->add_resource_loading_hints();
+ optimization->mutable_previews_metadata()
+ ->add_resource_loading_hints();
resource_loading_hint->set_loading_optimization_type(
optimization_guide::proto::LOADING_BLOCK_RESOURCE);
resource_loading_hint->set_resource_pattern(resource_blocking_pattern);
}
}
}
+ // Always stick something with no hint version in here.
+ optimization_guide::proto::Hint* no_version_hint = config.add_hints();
+ no_version_hint->set_key("noversion.com");
+ no_version_hint->set_key_representation(
+ optimization_guide::proto::HOST_SUFFIX);
+ no_version_hint->add_page_hints()->set_page_pattern("*");
+ // Always stick something with a bad hint version in here.
+ optimization_guide::proto::Hint* bad_version_hint = config.add_hints();
+ bad_version_hint->set_key("badversion.com");
+ bad_version_hint->set_key_representation(
+ optimization_guide::proto::HOST_SUFFIX);
+ bad_version_hint->set_version("notaversion");
+ bad_version_hint->add_page_hints()->set_page_pattern("*");
return WriteConfigToFileAndReturnHintsComponentInfo(config);
}
diff --git a/chromium/components/optimization_guide/top_host_provider.h b/chromium/components/optimization_guide/top_host_provider.h
index 3062173be0f..d7a2b3c546c 100644
--- a/chromium/components/optimization_guide/top_host_provider.h
+++ b/chromium/components/optimization_guide/top_host_provider.h
@@ -13,13 +13,14 @@ namespace optimization_guide {
// A class to handle querying for the top hosts for a user.
class TopHostProvider {
public:
+ virtual ~TopHostProvider() {}
+
// Returns a vector of at most |max_sites| top hosts, the order of hosts is
// not guaranteed.
virtual std::vector<std::string> GetTopHosts(size_t max_sites) = 0;
protected:
TopHostProvider() {}
- virtual ~TopHostProvider() {}
};
} // namespace optimization_guide
diff --git a/chromium/components/os_crypt/BUILD.gn b/chromium/components/os_crypt/BUILD.gn
index e13d2930ec5..0a35a9b670b 100644
--- a/chromium/components/os_crypt/BUILD.gn
+++ b/chromium/components/os_crypt/BUILD.gn
@@ -49,6 +49,7 @@ component("os_crypt") {
deps = [
"//base",
+ "//build:branding_buildflags",
"//components/prefs",
"//crypto",
@@ -167,6 +168,7 @@ source_set("unit_tests") {
":test_support",
"//base",
"//base/test:test_support",
+ "//build:branding_buildflags",
"//components/prefs:test_support",
"//crypto",
"//testing/gmock",
diff --git a/chromium/components/os_crypt/key_storage_keyring.cc b/chromium/components/os_crypt/key_storage_keyring.cc
index af2f64b34dd..a4c5b394a24 100644
--- a/chromium/components/os_crypt/key_storage_keyring.cc
+++ b/chromium/components/os_crypt/key_storage_keyring.cc
@@ -9,11 +9,12 @@
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
+#include "build/branding_buildflags.h"
#include "components/os_crypt/keyring_util_linux.h"
namespace {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const char kApplicationName[] = "chrome";
#else
const char kApplicationName[] = "chromium";
diff --git a/chromium/components/os_crypt/key_storage_keyring_unittest.cc b/chromium/components/os_crypt/key_storage_keyring_unittest.cc
index f7d8067ab47..1a8166eac14 100644
--- a/chromium/components/os_crypt/key_storage_keyring_unittest.cc
+++ b/chromium/components/os_crypt/key_storage_keyring_unittest.cc
@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/os_crypt/key_storage_keyring.h"
+
#include <cstdarg> // Needed to mock ellipsis
#include <string>
#include "base/macros.h"
#include "base/test/test_simple_task_runner.h"
-#include "components/os_crypt/key_storage_keyring.h"
+#include "build/branding_buildflags.h"
#include "components/os_crypt/keyring_util_linux.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const char kApplicationName[] = "chrome";
#else
const char kApplicationName[] = "chromium";
diff --git a/chromium/components/os_crypt/key_storage_kwallet_unittest.cc b/chromium/components/os_crypt/key_storage_kwallet_unittest.cc
index 2525d210adf..18afe6e80b9 100644
--- a/chromium/components/os_crypt/key_storage_kwallet_unittest.cc
+++ b/chromium/components/os_crypt/key_storage_kwallet_unittest.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/nix/xdg_util.h"
+#include "build/branding_buildflags.h"
#include "dbus/message.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
@@ -30,7 +31,7 @@ constexpr KWalletDBus::Error CANNOT_CONTACT =
// These names are not allowed to change in prod, unless we intentionally
// migrate.
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const char kExpectedFolderName[] = "Chrome Keys";
const char kExpectedEntryName[] = "Chrome Safe Storage";
#else
diff --git a/chromium/components/os_crypt/key_storage_libsecret.cc b/chromium/components/os_crypt/key_storage_libsecret.cc
index a1b5b975bc8..b8a3d7c0da2 100644
--- a/chromium/components/os_crypt/key_storage_libsecret.cc
+++ b/chromium/components/os_crypt/key_storage_libsecret.cc
@@ -7,11 +7,12 @@
#include "base/base64.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
+#include "build/branding_buildflags.h"
#include "components/os_crypt/libsecret_util_linux.h"
namespace {
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const char kApplicationName[] = "chrome";
#else
const char kApplicationName[] = "chromium";
diff --git a/chromium/components/os_crypt/key_storage_linux.cc b/chromium/components/os_crypt/key_storage_linux.cc
index 9e6f0f27535..48810de20eb 100644
--- a/chromium/components/os_crypt/key_storage_linux.cc
+++ b/chromium/components/os_crypt/key_storage_linux.cc
@@ -12,6 +12,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_restrictions.h"
+#include "build/branding_buildflags.h"
#include "components/os_crypt/key_storage_config_linux.h"
#include "components/os_crypt/key_storage_util_linux.h"
@@ -25,7 +26,7 @@
#include "components/os_crypt/key_storage_kwallet.h"
#endif
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const char KeyStorageLinux::kFolderName[] = "Chrome Keys";
const char KeyStorageLinux::kKey[] = "Chrome Safe Storage";
#else
diff --git a/chromium/components/os_crypt/keychain_password_mac.mm b/chromium/components/os_crypt/keychain_password_mac.mm
index 73cd3059111..e66a829bceb 100644
--- a/chromium/components/os_crypt/keychain_password_mac.mm
+++ b/chromium/components/os_crypt/keychain_password_mac.mm
@@ -10,6 +10,7 @@
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/rand_util.h"
+#include "build/branding_buildflags.h"
#include "components/os_crypt/encryption_key_creation_util.h"
#include "crypto/apple_keychain.h"
@@ -47,7 +48,7 @@ std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain,
// These two strings ARE indeed user facing. But they are used to access
// the encryption keyword. So as to not lose encrypted data when system
// locale changes we DO NOT LOCALIZE.
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const char KeychainPassword::service_name[] = "Chrome Safe Storage";
const char KeychainPassword::account_name[] = "Chrome";
#else
diff --git a/chromium/components/os_crypt/keychain_password_mac_unittest.mm b/chromium/components/os_crypt/keychain_password_mac_unittest.mm
index 1502ce107be..92d810e2995 100644
--- a/chromium/components/os_crypt/keychain_password_mac_unittest.mm
+++ b/chromium/components/os_crypt/keychain_password_mac_unittest.mm
@@ -12,7 +12,7 @@
#include "components/os_crypt/encryption_key_creation_util_ios.h"
#else
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/os_crypt/encryption_key_creation_util_mac.h"
#include "components/os_crypt/os_crypt_pref_names_mac.h"
@@ -94,7 +94,7 @@ class KeychainPasswordTest : public testing::Test {
#if !defined(OS_IOS)
// Waits until all tasks in the task runner's queue are finished.
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
base::HistogramTester& histogram_tester() { return histogram_tester_; }
@@ -107,7 +107,7 @@ class KeychainPasswordTest : public testing::Test {
private:
#if !defined(OS_IOS)
base::HistogramTester histogram_tester_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
#endif
DISALLOW_COPY_AND_ASSIGN(KeychainPasswordTest);
diff --git a/chromium/components/ownership/owner_settings_service.cc b/chromium/components/ownership/owner_settings_service.cc
index 3402e37d97f..300eca5e90a 100644
--- a/chromium/components/ownership/owner_settings_service.cc
+++ b/chromium/components/ownership/owner_settings_service.cc
@@ -72,8 +72,7 @@ std::unique_ptr<em::PolicyFetchResponse> AssembleAndSignPolicy(
OwnerSettingsService::OwnerSettingsService(
const scoped_refptr<ownership::OwnerKeyUtil>& owner_key_util)
- : owner_key_util_(owner_key_util), weak_factory_(this) {
-}
+ : owner_key_util_(owner_key_util) {}
OwnerSettingsService::~OwnerSettingsService() {
DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/chromium/components/ownership/owner_settings_service.h b/chromium/components/ownership/owner_settings_service.h
index f434e76d7e1..57b34cf6902 100644
--- a/chromium/components/ownership/owner_settings_service.h
+++ b/chromium/components/ownership/owner_settings_service.h
@@ -146,7 +146,7 @@ class OWNERSHIP_EXPORT OwnerSettingsService : public KeyedService {
base::ThreadChecker thread_checker_;
private:
- base::WeakPtrFactory<OwnerSettingsService> weak_factory_;
+ base::WeakPtrFactory<OwnerSettingsService> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(OwnerSettingsService);
};
diff --git a/chromium/components/page_image_annotation/DEPS b/chromium/components/page_image_annotation/DEPS
index 3f62e9fdc91..73bc2d534b3 100644
--- a/chromium/components/page_image_annotation/DEPS
+++ b/chromium/components/page_image_annotation/DEPS
@@ -2,6 +2,7 @@ include_rules = [
# Page image annotation is a layered component; subdirectories must explicitly
# introduce the ability to use the content layer as appropriate.
"-components/page_image_annotation/content",
+ "+mojo/public/cpp/bindings",
"+services/image_annotation/public/mojom",
"+services/image_annotation/public/cpp",
"+services/service_manager/public/cpp",
diff --git a/chromium/components/page_image_annotation/content/renderer/DEPS b/chromium/components/page_image_annotation/content/renderer/DEPS
index 07132f33310..8c0a4298eeb 100644
--- a/chromium/components/page_image_annotation/content/renderer/DEPS
+++ b/chromium/components/page_image_annotation/content/renderer/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+components/page_image_annotation/core",
"+content/public/renderer",
"+crypto",
+ "+third_party/blink/public/common/browser_interface_broker_proxy.h",
"+third_party/blink/public/platform",
"+third_party/blink/public/web",
"+ui/base",
diff --git a/chromium/components/page_image_annotation/content/renderer/content_page_annotator_driver.cc b/chromium/components/page_image_annotation/content/renderer/content_page_annotator_driver.cc
index 098d75744cf..d02e2ecb758 100644
--- a/chromium/components/page_image_annotation/content/renderer/content_page_annotator_driver.cc
+++ b/chromium/components/page_image_annotation/content/renderer/content_page_annotator_driver.cc
@@ -10,7 +10,7 @@
#include "content/public/renderer/render_frame.h"
#include "crypto/sha2.h"
#include "services/image_annotation/public/mojom/image_annotation.mojom.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_string.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -40,11 +40,12 @@ base::Optional<PageAnnotator::ImageMetadata> ProduceMetadata(
return PageAnnotator::ImageMetadata{node_id, source_id};
}
-ia_mojom::AnnotatorPtr RequestAnnotator(
+mojo::PendingRemote<ia_mojom::Annotator> RequestAnnotator(
content::RenderFrame* const render_frame) {
- ia_mojom::AnnotatorPtr ptr;
- render_frame->GetRemoteInterfaces()->GetInterface(mojo::MakeRequest(&ptr));
- return ptr;
+ mojo::PendingRemote<ia_mojom::Annotator> annotator;
+ render_frame->GetBrowserInterfaceBroker()->GetInterface(
+ annotator.InitWithNewPipeAndPassReceiver());
+ return annotator;
}
} // namespace
diff --git a/chromium/components/page_image_annotation/core/page_annotator.cc b/chromium/components/page_image_annotation/core/page_annotator.cc
index 90d148a30cb..45927681fb4 100644
--- a/chromium/components/page_image_annotation/core/page_annotator.cc
+++ b/chromium/components/page_image_annotation/core/page_annotator.cc
@@ -12,8 +12,8 @@ namespace ia_mojom = image_annotation::mojom;
PageAnnotator::Observer::~Observer() {}
-PageAnnotator::PageAnnotator(ia_mojom::AnnotatorPtr annotator_ptr)
- : annotator_ptr_(std::move(annotator_ptr)) {}
+PageAnnotator::PageAnnotator(mojo::PendingRemote<ia_mojom::Annotator> annotator)
+ : annotator_(std::move(annotator)) {}
PageAnnotator::~PageAnnotator() {}
@@ -59,7 +59,7 @@ void PageAnnotator::AnnotateImage(Observer* const observer,
return;
// TODO(crbug.com/916363): get a user's preferred language and pass it here.
- annotator_ptr_->AnnotateImage(
+ annotator_->AnnotateImage(
lookup->second.first.source_id,
std::string() /* description_language_tag */,
lookup->second.second.GetPtr(),
diff --git a/chromium/components/page_image_annotation/core/page_annotator.h b/chromium/components/page_image_annotation/core/page_annotator.h
index e36115ae183..e0854ab191b 100644
--- a/chromium/components/page_image_annotation/core/page_annotator.h
+++ b/chromium/components/page_image_annotation/core/page_annotator.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/image_annotation/public/cpp/image_processor.h"
#include "services/image_annotation/public/mojom/image_annotation.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -66,7 +67,8 @@ class PageAnnotator {
image_annotation::mojom::AnnotateImageResultPtr result) = 0;
};
- explicit PageAnnotator(image_annotation::mojom::AnnotatorPtr annotator_ptr);
+ explicit PageAnnotator(
+ mojo::PendingRemote<image_annotation::mojom::Annotator> annotator);
~PageAnnotator();
// Request annotation of the given image via the image annotation service.
@@ -101,7 +103,7 @@ class PageAnnotator {
uint64_t node_id,
image_annotation::mojom::AnnotateImageResultPtr result);
- image_annotation::mojom::AnnotatorPtr annotator_ptr_;
+ mojo::Remote<image_annotation::mojom::Annotator> annotator_;
base::ObserverList<Observer> observers_;
diff --git a/chromium/components/page_image_annotation/core/page_annotator_unittest.cc b/chromium/components/page_image_annotation/core/page_annotator_unittest.cc
index f56ae3b3b71..0319836203d 100644
--- a/chromium/components/page_image_annotation/core/page_annotator_unittest.cc
+++ b/chromium/components/page_image_annotation/core/page_annotator_unittest.cc
@@ -7,7 +7,8 @@
#include <vector>
#include "base/bind.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -49,10 +50,10 @@ class MockObserver : public PageAnnotator::Observer {
// AnnotateImage method was called.
class TestAnnotator : public ia_mojom::Annotator {
public:
- ia_mojom::AnnotatorPtr GetPtr() {
- ia_mojom::AnnotatorPtr ptr;
- bindings_.AddBinding(this, mojo::MakeRequest(&ptr));
- return ptr;
+ mojo::PendingRemote<ia_mojom::Annotator> GetRemote() {
+ mojo::PendingRemote<ia_mojom::Annotator> remote;
+ receivers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
+ return remote;
}
void AnnotateImage(const std::string& source_id,
@@ -81,16 +82,16 @@ class TestAnnotator : public ia_mojom::Annotator {
image_processors_[index].reset();
}
- mojo::BindingSet<ia_mojom::Annotator> bindings_;
+ mojo::ReceiverSet<ia_mojom::Annotator> receivers_;
};
// Tests that correct image tracking messages are sent to observers.
TEST(PageAnnotatorTest, ImageTracking) {
const auto get_pixels = base::BindRepeating([]() { return SkBitmap(); });
- base::test::ScopedTaskEnvironment test_task_env;
+ base::test::TaskEnvironment test_task_env;
- PageAnnotator page_annotator(ia_mojom::AnnotatorPtr{});
+ PageAnnotator page_annotator((mojo::NullRemote()));
MockObserver o1;
page_annotator.AddObserver(&o1);
@@ -118,10 +119,10 @@ TEST(PageAnnotatorTest, Annotation) {
// the local ImageProcessor.
const auto get_pixels = base::BindRepeating([]() { return SkBitmap(); });
- base::test::ScopedTaskEnvironment test_task_env;
+ base::test::TaskEnvironment test_task_env;
TestAnnotator test_annotator;
- PageAnnotator page_annotator(test_annotator.GetPtr());
+ PageAnnotator page_annotator(test_annotator.GetRemote());
test_task_env.RunUntilIdle();
// We use NiceMocks here since we don't place expectations on image added /
diff --git a/chromium/components/page_info_strings.grdp b/chromium/components/page_info_strings.grdp
index a2cb9e68dfc..8faddca16c9 100644
--- a/chromium/components/page_info_strings.grdp
+++ b/chromium/components/page_info_strings.grdp
@@ -28,20 +28,20 @@
<message name="IDS_PAGE_INFO_VIEW_SOURCE_PAGE" desc="Message to display in the page info bubble when you are viewing page sources by using |View page source| option from the right click menu.">
You're viewing the source of a web page
</message>
+ <message name="IDS_PAGE_INFO_DEVTOOLS_PAGE" desc="Message to display in the page info bubble when the page you are on is a devtools:// page.">
+ You're viewing a developer tools page
+ </message>
<!-- Safety Tip summary strings -->
- <message name="IDS_PAGE_INFO_SAFETY_TIP_NAME" desc="Name of safety tips, displayed in bold as part of the title of the safety tip bubble.">
- Safety tip:
- </message>
- <message name="IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_TITLE" desc="Title of Safety Tip bubble when triggered.">
- <ph name="SAFETY_TIP">$1<ex>Safety tip:</ex></ph> suspicious behavior
- </message>
<message name="IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_DESCRIPTION" desc="Body of message to display in the page info bubble when you are viewing a page that triggered a safety tip.">
- This page might try to trick you, steal personal information, or harm your device. Be cautious when entering personal information or opening downloaded files.
+ This site could be fake or fraudulent. Chrome recommends leaving now.
</message>
<message name="IDS_PAGE_INFO_SAFETY_TIP_LEAVE_BUTTON" desc="Text of button to leave a suspicious page shown on the safety tip page info bubble.">
Leave this site
</message>
+ <message name="IDS_PAGE_INFO_SAFETY_TIP_SUMMARY" desc="Message to display in the page info bubble when the page you are on triggered a safety tip.">
+ Suspicious site
+ </message>
<!-- Viewing file strings -->
<message name="IDS_PAGE_INFO_FILE_PAGE" desc="Message to display in the page info bubble when the page the user has navigated to is a file:// page">
@@ -133,15 +133,9 @@
<message name="IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT" desc="The text of the connection section when the connection is not encrypted.">
Your connection to <ph name="DOMAIN">$1<ex>www.google.com</ex></ph> is not encrypted.
</message>
- <message name="IDS_PAGE_INFO_SECURITY_TAB_NO_REVOCATION_MECHANISM" desc="The text of the identity section when there is no certificate revocation mechanism.">
- The certificate does not specify a mechanism to check whether it has been revoked.
- </message>
<message name="IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION" desc="This message gives the version of the SSL protocol used to protect the HTTPS connection.">
The connection uses <ph name="SSL_VERSION">$1<ex>TLS 1.0</ex></ph>.
</message>
- <message name="IDS_PAGE_INFO_SECURITY_TAB_UNABLE_TO_CHECK_REVOCATION" desc="The text of the identity section when we were unable to check if the certificate has been revoked.">
- Unable to check whether the certificate has been revoked.
- </message>
<message name="IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY" desc="The default name used when we did not find a principal name.">
unknown name
</message>
@@ -267,6 +261,9 @@
<message name="IDS_PAGE_INFO_TYPE_SERIAL" desc="The label used for the serial port permission controls in the Page Info popup.">
Serial ports
</message>
+ <message name="IDS_PAGE_INFO_TYPE_NATIVE_FILE_SYSTEM_WRITE" desc="The label used for the native file system write permission controls in the Page Info popup. The write permission determines whether sites are allowed to save to the original file that was selected by the user through the Native File System API.">
+ File editing
+ </message>
<message name="IDS_PAGE_INFO_TYPE_BLUETOOTH_SCANNING" desc="The label used for the Bluetooth scanning controls in the Page Info popup.">
Bluetooth scanning
</message>
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_DESCRIPTION.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_DESCRIPTION.png.sha1
index db9fb7bc2e7..c3b63e34aae 100644
--- a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_DESCRIPTION.png.sha1
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_DESCRIPTION.png.sha1
@@ -1 +1 @@
-286691c1acd6ead1593fb72f3bc054fb607a67ed \ No newline at end of file
+b34b7304a8ffb374af8016eb3068dbbb88ba4ede \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_TITLE.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_TITLE.png.sha1
index db9fb7bc2e7..c3b63e34aae 100644
--- a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_TITLE.png.sha1
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_BAD_REPUTATION_TITLE.png.sha1
@@ -1 +1 @@
-286691c1acd6ead1593fb72f3bc054fb607a67ed \ No newline at end of file
+b34b7304a8ffb374af8016eb3068dbbb88ba4ede \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_SUMMARY.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_SUMMARY.png.sha1
new file mode 100644
index 00000000000..f5f41079b7e
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SAFETY_TIP_SUMMARY.png.sha1
@@ -0,0 +1 @@
+a529530d0ddcd81921d7f17316a5ddb453b3aef6 \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_NATIVE_FILE_SYSTEM_WRITE.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_NATIVE_FILE_SYSTEM_WRITE.png.sha1
new file mode 100644
index 00000000000..89fb4b2b5bf
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_NATIVE_FILE_SYSTEM_WRITE.png.sha1
@@ -0,0 +1 @@
+38a70bcecbe1c8daeb8341794641d670195ab398 \ No newline at end of file
diff --git a/chromium/components/page_load_metrics/OWNERS b/chromium/components/page_load_metrics/OWNERS
new file mode 100644
index 00000000000..3d182295e99
--- /dev/null
+++ b/chromium/components/page_load_metrics/OWNERS
@@ -0,0 +1,13 @@
+csharrison@chromium.org
+bmcquade@chromium.org
+jkarlin@chromium.org
+ryansturm@chromium.org
+johnidel@chromium.org
+
+# For straightforward addition/removal to existing observers only (for
+# APAC).
+kinuko@chromium.org
+
+# For QUIC version changes in ConnectionInfo switch statmenets.
+per-file protocol_util.cc=file://net/quic/OWNERS
+# COMPONENT: Speed>Metrics
diff --git a/chromium/components/page_load_metrics/common/BUILD.gn b/chromium/components/page_load_metrics/common/BUILD.gn
new file mode 100644
index 00000000000..ba5e00cd0b2
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/BUILD.gn
@@ -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("//mojo/public/tools/bindings/mojom.gni")
+import("//testing/test.gni")
+
+source_set("common") {
+ sources = [
+ "page_end_reason.h",
+ "page_load_metrics_constants.h",
+ "page_load_metrics_util.cc",
+ "page_load_metrics_util.h",
+ "page_load_timing.cc",
+ "page_load_timing.h",
+ ]
+ deps = [
+ ":page_load_metrics_mojom",
+ "//base",
+ "//net",
+ "//third_party/blink/public:blink_headers",
+ "//url",
+ ]
+}
+
+source_set("test_support") {
+ testonly = true
+ sources = [
+ "test/page_load_metrics_test_util.cc",
+ "test/page_load_metrics_test_util.h",
+ "test/weak_mock_timer.cc",
+ "test/weak_mock_timer.h",
+ ]
+ deps = [
+ ":common",
+ ":page_load_metrics_mojom",
+ "//base",
+ "//base/test:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
+
+mojom("page_load_metrics_mojom") {
+ sources = [
+ "page_load_metrics.mojom",
+ ]
+ public_deps = [
+ "//mojo/public/mojom/base",
+ "//third_party/blink/public/mojom:web_feature_mojo_bindings",
+ "//url/mojom:url_mojom_origin",
+ ]
+}
diff --git a/chromium/components/page_load_metrics/common/DEPS b/chromium/components/page_load_metrics/common/DEPS
new file mode 100644
index 00000000000..258a3106b69
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+base",
+ "+net/base",
+ "+third_party/blink/public",
+] \ No newline at end of file
diff --git a/chromium/components/page_load_metrics/common/page_end_reason.h b/chromium/components/page_load_metrics/common/page_end_reason.h
new file mode 100644
index 00000000000..94f3444267d
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_end_reason.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 COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_END_REASON_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_END_REASON_H_
+
+namespace page_load_metrics {
+
+// This enum represents how a page load ends. If the action occurs before the
+// page load finishes (or reaches some point like first paint), then we consider
+// the load to be aborted.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. For any additions, also update the
+// corresponding PageEndReason enum in enums.xml.
+enum PageEndReason {
+ // Page lifetime has not yet ended (page is still active).
+ END_NONE = 0,
+
+ // The page was reloaded, possibly by the user.
+ END_RELOAD = 1,
+
+ // The page was navigated away from, via a back or forward navigation.
+ END_FORWARD_BACK = 2,
+
+ // The navigation is replaced with a navigation with the qualifier
+ // ui::PAGE_TRANSITION_CLIENT_REDIRECT, which is caused by Javascript, or the
+ // meta refresh tag.
+ END_CLIENT_REDIRECT = 3,
+
+ // If the page load is replaced by a new navigation. This includes link
+ // clicks, typing in the omnibox (not a reload), and form submissions.
+ END_NEW_NAVIGATION = 4,
+
+ // The page load was stopped (e.g. the user presses the stop X button).
+ END_STOP = 5,
+
+ // Page load ended due to closing the tab or browser.
+ END_CLOSE = 6,
+
+ // The provisional load for this page load failed before committing.
+ END_PROVISIONAL_LOAD_FAILED = 7,
+
+ // The render process hosting the page terminated unexpectedly.
+ END_RENDER_PROCESS_GONE = 8,
+
+ // We don't know why the page load ended. This is the value we assign to a
+ // terminated provisional load if the only signal we get is the load finished
+ // without committing, either without error or with net::ERR_ABORTED.
+ END_OTHER = 9,
+
+ PAGE_END_REASON_COUNT
+};
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_END_REASON_H_
diff --git a/chromium/components/page_load_metrics/common/page_load_metrics.mojom b/chromium/components/page_load_metrics/common/page_load_metrics.mojom
new file mode 100644
index 00000000000..f0e6dad0852
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_load_metrics.mojom
@@ -0,0 +1,268 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module page_load_metrics.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+import "third_party/blink/public/mojom/web_feature/web_feature.mojom";
+import "third_party/blink/public/mojom/use_counter/css_property_id.mojom";
+import "url/mojom/origin.mojom";
+
+// TimeDeltas below relative to navigation start.
+struct DocumentTiming {
+ // Time immediately before the DOMContentLoaded event is fired.
+ mojo_base.mojom.TimeDelta? dom_content_loaded_event_start;
+
+ // Time immediately before the load event is fired.
+ mojo_base.mojom.TimeDelta? load_event_start;
+
+ // Time when the first layout is completed.
+ mojo_base.mojom.TimeDelta? first_layout;
+};
+
+// TimeDeltas below relative to navigation start.
+struct PaintTiming {
+ // Time when the first paint is performed.
+ mojo_base.mojom.TimeDelta? first_paint;
+
+ // Time when the first image is painted.
+ mojo_base.mojom.TimeDelta? first_image_paint;
+
+ // Time when the first contentful thing (image, text, etc.) is painted.
+ mojo_base.mojom.TimeDelta? first_contentful_paint;
+
+ // (Experimental) Time when the page's primary content is painted.
+ mojo_base.mojom.TimeDelta? first_meaningful_paint;
+
+ // (Experimental) Time when the page's largest image is painted.
+ mojo_base.mojom.TimeDelta? largest_image_paint;
+
+ // (Experimental) Size of the largest image of the largest image paint, by
+ // Size = Height * Width.
+ uint64 largest_image_paint_size;
+
+ // (Experimental) Time when the page's largest text is painted.
+ mojo_base.mojom.TimeDelta? largest_text_paint;
+
+ // (Experimental) Size of the largest text of the largest text paint, by
+ // Size = Height * Width.
+ uint64 largest_text_paint_size;
+};
+
+// TimeDeltas below represent durations of time during the page load.
+struct ParseTiming {
+ // Time that the document's parser started and stopped parsing main resource
+ // content.
+ mojo_base.mojom.TimeDelta? parse_start;
+ mojo_base.mojom.TimeDelta? parse_stop;
+
+ // Sum of times when the parser is blocked waiting on the load of a script.
+ // This duration takes place between parser_start and parser_stop, and thus
+ // must be less than or equal to parser_stop - parser_start. Note that this
+ // value may be updated multiple times during the period between parse_start
+ // and parse_stop.
+ mojo_base.mojom.TimeDelta? parse_blocked_on_script_load_duration;
+
+ // Sum of times when the parser is blocked waiting on the load of a script
+ // that was inserted from document.write. This duration must be less than or
+ // equal to parse_blocked_on_script_load_duration. Note that this value may be
+ // updated multiple times during the period between parse_start and
+ // parse_stop. Note that some uncommon cases where scripts are loaded via
+ // document.write are not currently covered by this field. See crbug/600711
+ // for details.
+ mojo_base.mojom.TimeDelta? parse_blocked_on_script_load_from_document_write_duration;
+
+ // Sum of times when the parser is executing a script. This duration takes
+ // place between parser_start and parser_stop, and thus must be less than or
+ // equal to parser_stop - parser_start. Note that this value may be updated
+ // multiple times during the period between parse_start and parse_stop.
+ mojo_base.mojom.TimeDelta? parse_blocked_on_script_execution_duration;
+
+ // Sum of times when the parser is executing a script that was inserted from
+ // document.write. This duration must be less than or equal to
+ // parse_blocked_on_script_load_duration. Note that this value may be updated
+ // multiple times during the period between parse_start and parse_stop. Note
+ // that some uncommon cases where scripts are loaded via document.write are
+ // not currently covered by this field. See crbug/600711 for details.
+ mojo_base.mojom.TimeDelta? parse_blocked_on_script_execution_from_document_write_duration;
+};
+
+struct InteractiveTiming {
+ // The first time the page is considered 'interactive'. This is determined
+ // using heuristics based on main thread and network activity. Time delta is
+ // relative to navigation_start.
+ mojo_base.mojom.TimeDelta? interactive;
+
+ // The time of when we detect the page is interactive. There is a delay
+ // between when the page was interactive and when we were able to detect it.
+ // Time delta is relative to navigation_start.
+ // This is a page load metrics internal value and not generally intended for
+ // consumption by observers.
+ mojo_base.mojom.TimeDelta? interactive_detection;
+
+
+ // The time of when a significant input event happened that may cause
+ // observers to discard the value of Time to Interactive. Time delta is
+ // relative to navigation start.
+ // This is a page load metrics internal value and not generally intended for
+ // consumption by observers.
+ mojo_base.mojom.TimeDelta? first_invalidating_input;
+
+ // Queueing Time of the first click, tap, key press, cancellable touchstart,
+ // or pointer down followed by a pointer up.
+ mojo_base.mojom.TimeDelta? first_input_delay;
+
+ // The timestamp of the event whose delay is reported by GetFirstInputDelay().
+ mojo_base.mojom.TimeDelta? first_input_timestamp;
+
+ // Queueing Time of the meaningful input event with longest delay. Meaningful
+ // input events are click, tap, key press, cancellable touchstart, or pointer
+ // down followed by a pointer up.
+ mojo_base.mojom.TimeDelta? longest_input_delay;
+
+ // The timestamp of the event whose delay is reported as longest_input_delay.
+ mojo_base.mojom.TimeDelta? longest_input_timestamp;
+};
+
+
+// PageLoadTiming contains timing metrics associated with a page load. Many of
+// the metrics here are based on the Navigation Timing spec:
+// http://www.w3.org/TR/navigation-timing/.
+struct PageLoadTiming {
+ // Time that the navigation for the associated page was initiated. Note that
+ // this field is only used for internal tracking purposes and should not be
+ // used by PageLoadMetricsObservers. This field will likely be removed in the
+ // future.
+ mojo_base.mojom.Time navigation_start;
+
+ // Time relative to navigation_start that the first byte of the response is
+ // received.
+ mojo_base.mojom.TimeDelta? response_start;
+ DocumentTiming document_timing;
+ InteractiveTiming interactive_timing;
+ PaintTiming paint_timing;
+ ParseTiming parse_timing;
+ // Time between user input and navigation start. This is set for navigations
+ // where the input start timing is known; currently when the navigation is
+ // initiated by a link click in the renderer, or from the desktop omnibox.
+ mojo_base.mojom.TimeDelta? input_to_navigation_start;
+
+ // If you add additional members, also be sure to update page_load_timing.h.
+};
+
+struct PageLoadMetadata {
+ // These are packed blink::WebLoadingBehaviorFlag enums.
+ int32 behavior_flags = 0;
+};
+
+// PageLoadFeatures contains a list of features newly observed by use counter.
+// In a given page load, no PageLoadFeatures sent will contain previously seen
+// values.
+struct PageLoadFeatures {
+ // These features are defined as blink::mojom::WebFeature enums.
+ array<blink.mojom.WebFeature> features;
+ // CSS properties are defined as blink::mojom::CSSSampleId enums.
+ array<blink.mojom.CSSSampleId> css_properties;
+ array<blink.mojom.CSSSampleId> animated_css_properties;
+};
+
+// Enumeration of distinct cache types.
+enum CacheType {
+ kNotCached, // Resource came from network.
+ kHttp, // Resource was serviced by the http cache.
+ kMemory, // Resource was serviced by the Renderer's MemoryCache.
+};
+
+struct ResourceDataUpdate {
+ // The id for the resource request.
+ int32 request_id = 0;
+
+ // Network bytes received for the resource since the last timing update
+ // from renderer to browser.
+ int64 delta_bytes = 0;
+
+ // Total network bytes received for the resource across timing updates. This
+ // is the aggregate of the |delta_bytes| from each timing update.
+ int64 received_data_length = 0;
+
+ // The length of the response body for the resource before removing any
+ // content encodings. Only set for complete resources.
+ int64 encoded_body_length = 0;
+
+ // Whether this resource load has completed.
+ bool is_complete;
+
+ // Compression ratio estimated from the response headers if data saver was
+ // used.
+ double data_reduction_proxy_compression_ratio_estimate;
+
+ // Whether this resource was tagged as an ad in the renderer. This flag can
+ // be set to true at any point during a resource load. A more recent
+ // ResourceDataUpdate can have a different flag than the previous update.
+ // Once this is set to true, it will be true for all future updates.
+ bool reported_as_ad_resource;
+
+ // Whether this resource was loaded in the top-level frame.
+ bool is_main_frame_resource;
+
+ // Which cache this resource originated from, if any.
+ CacheType cache_type;
+
+ // Whether this resource is the primary resource for a frame.
+ bool is_primary_frame_resource;
+
+ // Mime type for the resource found in the network response header.
+ string mime_type;
+
+ // Whether the scheme of this resource indicates a secure connection.
+ bool is_secure_scheme;
+
+ // Whether this resource was fetched via proxy.
+ bool proxy_used;
+
+ // The origin of this resource.
+ url.mojom.Origin origin;
+};
+
+// Metrics about how a RenderFrame rendered since the last UpdateTiming call.
+struct FrameRenderDataUpdate {
+ // How much visible elements in the frame shifted (bit.ly/lsm-explainer) since
+ // the last timing update.
+ float layout_shift_delta;
+
+ // How much visible elements in the frame shifted (bit.ly/lsm-explainer),
+ // before a user input or document scroll, since the last timing update.
+ float layout_shift_delta_before_input_or_scroll;
+};
+
+// Metrics about the time spent in tasks (cpu time) by a frame.
+struct CpuTiming {
+ // Time spent in tasks measured in wall time.
+ mojo_base.mojom.TimeDelta task_time;
+};
+
+// Metrics about the count of resources that were lazy loaded in the frame.
+struct DeferredResourceCounts {
+ // The count of frames that were deferred due to lazy load.
+ uint64 deferred_frames = 0;
+ // The count of frames that were loaded after being deferred due to lazy load.
+ uint64 frames_loaded_after_deferral = 0;
+
+ // The count of images that were deferred due to lazy load.
+ uint64 deferred_images = 0;
+ // The count of images that were loaded after being deferred due to lazy load.
+ uint64 images_loaded_after_deferral = 0;
+};
+
+// Sent from renderer to browser process when the PageLoadTiming for the
+// associated frame changed.
+interface PageLoadMetrics {
+ UpdateTiming(PageLoadTiming page_load_timing,
+ PageLoadMetadata page_load_metadata,
+ PageLoadFeatures new_features,
+ array<ResourceDataUpdate> resources,
+ FrameRenderDataUpdate render_data,
+ CpuTiming cpu_load_timing,
+ DeferredResourceCounts new_deferred_resource_data);
+};
diff --git a/chromium/components/page_load_metrics/common/page_load_metrics_constants.h b/chromium/components/page_load_metrics/common/page_load_metrics_constants.h
new file mode 100644
index 00000000000..3b44ddb1b28
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_load_metrics_constants.h
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_METRICS_CONSTANTS_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_METRICS_CONSTANTS_H_
+
+namespace page_load_metrics {
+
+// Amount of time to delay dispatch of metrics. This allows us to batch and send
+// fewer cross-process updates, given that cross-process updates can be
+// expensive.
+const int kBufferTimerDelayMillis = 1000;
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_METRICS_CONSTANTS_H_
diff --git a/chromium/components/page_load_metrics/common/page_load_metrics_util.cc b/chromium/components/page_load_metrics/common/page_load_metrics_util.cc
new file mode 100644
index 00000000000..8768df8c82a
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_load_metrics_util.cc
@@ -0,0 +1,65 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/page_load_metrics/common/page_load_metrics_util.h"
+
+#include <algorithm>
+
+#include "base/strings/string_util.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace page_load_metrics {
+
+base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
+ const size_t registry_length =
+ net::registry_controlled_domains::GetRegistryLength(
+ url,
+
+ // Do not include unknown registries (registries that don't have any
+ // matches in effective TLD names).
+ net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
+
+ // Do not include private registries, such as appspot.com. We don't
+ // want to match URLs like www.google.appspot.com.
+ net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+
+ const base::StringPiece hostname = url.host_piece();
+ if (registry_length == 0 || registry_length == std::string::npos ||
+ registry_length >= hostname.length()) {
+ return base::Optional<std::string>();
+ }
+
+ // Removes the tld and the preceding dot.
+ const base::StringPiece hostname_minus_registry =
+ hostname.substr(0, hostname.length() - (registry_length + 1));
+
+ if (hostname_minus_registry == "google")
+ return std::string("");
+
+ if (!base::EndsWith(hostname_minus_registry, ".google",
+ base::CompareCase::INSENSITIVE_ASCII)) {
+ return base::Optional<std::string>();
+ }
+
+ return std::string(hostname_minus_registry.substr(
+ 0, hostname_minus_registry.length() - strlen(".google")));
+}
+
+bool IsGoogleHostname(const GURL& url) {
+ return GetGoogleHostnamePrefix(url).has_value();
+}
+
+base::Optional<base::TimeDelta> OptionalMin(
+ const base::Optional<base::TimeDelta>& a,
+ const base::Optional<base::TimeDelta>& b) {
+ if (a && !b)
+ return a;
+ if (b && !a)
+ return b;
+ if (!a && !b)
+ return a; // doesn't matter which
+ return base::Optional<base::TimeDelta>(std::min(a.value(), b.value()));
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/common/page_load_metrics_util.h b/chromium/components/page_load_metrics/common/page_load_metrics_util.h
new file mode 100644
index 00000000000..3958bd4118b
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_load_metrics_util.h
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_METRICS_UTIL_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_METRICS_UTIL_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "url/gurl.h"
+
+namespace page_load_metrics {
+
+// Returns the minimum value of the optional TimeDeltas, if both values are
+// set. Otherwise, if one value is set, returns that value. Otherwise, returns
+// an unset value.
+base::Optional<base::TimeDelta> OptionalMin(
+ const base::Optional<base::TimeDelta>& a,
+ const base::Optional<base::TimeDelta>& b);
+
+// Whether the given url has a google hostname.
+bool IsGoogleHostname(const GURL& url);
+
+// If the given hostname is a google hostname, returns the portion of the
+// hostname before the google hostname. Otherwise, returns an unset optional
+// value.
+//
+// For example:
+// https://example.com/foo => returns an unset optional value
+// https://google.com/foo => returns ''
+// https://www.google.com/foo => returns 'www'
+// https://news.google.com/foo => returns 'news'
+// https://a.b.c.google.com/foo => returns 'a.b.c'
+base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url);
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_METRICS_UTIL_H_
diff --git a/chromium/components/page_load_metrics/common/page_load_timing.cc b/chromium/components/page_load_metrics/common/page_load_timing.cc
new file mode 100644
index 00000000000..f221c6b2579
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_load_timing.cc
@@ -0,0 +1,61 @@
+// 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 "components/page_load_metrics/common/page_load_timing.h"
+
+namespace page_load_metrics {
+
+mojom::PageLoadTimingPtr CreatePageLoadTiming() {
+ return mojom::PageLoadTiming::New(
+ base::Time(), base::Optional<base::TimeDelta>(),
+ mojom::DocumentTiming::New(), mojom::InteractiveTiming::New(),
+ mojom::PaintTiming::New(), mojom::ParseTiming::New(),
+ base::Optional<base::TimeDelta>());
+}
+
+bool IsEmpty(const page_load_metrics::mojom::DocumentTiming& timing) {
+ return !timing.dom_content_loaded_event_start && !timing.load_event_start &&
+ !timing.first_layout;
+}
+
+bool IsEmpty(const page_load_metrics::mojom::InteractiveTiming& timing) {
+ return !timing.interactive && !timing.interactive_detection &&
+ !timing.first_invalidating_input && !timing.first_input_delay &&
+ !timing.first_input_timestamp && !timing.longest_input_delay &&
+ !timing.longest_input_timestamp;
+}
+bool IsEmpty(const page_load_metrics::mojom::PaintTiming& timing) {
+ return !timing.first_paint && !timing.first_image_paint &&
+ !timing.first_contentful_paint && !timing.first_meaningful_paint &&
+ !timing.largest_image_paint && !timing.largest_text_paint;
+}
+
+bool IsEmpty(const page_load_metrics::mojom::ParseTiming& timing) {
+ return !timing.parse_start && !timing.parse_stop &&
+ !timing.parse_blocked_on_script_load_duration &&
+ !timing.parse_blocked_on_script_load_from_document_write_duration &&
+ !timing.parse_blocked_on_script_execution_duration &&
+ !timing.parse_blocked_on_script_execution_from_document_write_duration;
+}
+
+bool IsEmpty(const page_load_metrics::mojom::PageLoadTiming& timing) {
+ return timing.navigation_start.is_null() && !timing.response_start &&
+ (!timing.document_timing ||
+ page_load_metrics::IsEmpty(*timing.document_timing)) &&
+ (!timing.interactive_timing ||
+ page_load_metrics::IsEmpty(*timing.interactive_timing)) &&
+ (!timing.paint_timing ||
+ page_load_metrics::IsEmpty(*timing.paint_timing)) &&
+ (!timing.parse_timing ||
+ page_load_metrics::IsEmpty(*timing.parse_timing));
+}
+
+void InitPageLoadTimingForTest(mojom::PageLoadTiming* timing) {
+ timing->document_timing = mojom::DocumentTiming::New();
+ timing->interactive_timing = mojom::InteractiveTiming::New();
+ timing->paint_timing = mojom::PaintTiming::New();
+ timing->parse_timing = mojom::ParseTiming::New();
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/common/page_load_timing.h b/chromium/components/page_load_metrics/common/page_load_timing.h
new file mode 100644
index 00000000000..b7dfc999984
--- /dev/null
+++ b/chromium/components/page_load_metrics/common/page_load_timing.h
@@ -0,0 +1,27 @@
+// 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 COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_TIMING_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_TIMING_H_
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
+#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+
+namespace page_load_metrics {
+
+// Initialize an empty PageLoadTiming with initialized empty sub-members.
+mojom::PageLoadTimingPtr CreatePageLoadTiming();
+
+bool IsEmpty(const mojom::DocumentTiming& timing);
+bool IsEmpty(const mojom::PaintTiming& timing);
+bool IsEmpty(const mojom::ParseTiming& timing);
+bool IsEmpty(const mojom::PageLoadTiming& timing);
+
+void InitPageLoadTimingForTest(mojom::PageLoadTiming* timing);
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_COMMON_PAGE_LOAD_TIMING_H_
diff --git a/chromium/components/page_load_metrics/renderer/BUILD.gn b/chromium/components/page_load_metrics/renderer/BUILD.gn
new file mode 100644
index 00000000000..4db65fc1631
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("renderer") {
+ sources = [
+ "metrics_render_frame_observer.cc",
+ "metrics_render_frame_observer.h",
+ "page_resource_data_use.cc",
+ "page_resource_data_use.h",
+ "page_timing_metrics_sender.cc",
+ "page_timing_metrics_sender.h",
+ "page_timing_sender.h",
+ ]
+ deps = [
+ "//base",
+ "//components/data_reduction_proxy/core/common",
+ "//components/page_load_metrics/common",
+ "//components/page_load_metrics/common:page_load_metrics_mojom",
+ "//components/subresource_filter/content/renderer",
+ "//content/public/common",
+ "//content/public/renderer",
+ "//net",
+ "//services/network/public/cpp",
+ "//third_party/blink/public:blink_headers",
+ "//url",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "fake_page_timing_sender.cc",
+ "fake_page_timing_sender.h",
+ "metrics_render_frame_observer_unittest.cc",
+ "page_timing_metrics_sender_unittest.cc",
+ ]
+
+ deps = [
+ ":renderer",
+ "//base",
+ "//base/test:test_support",
+ "//components/page_load_metrics/common",
+ "//components/page_load_metrics/common:page_load_metrics_mojom",
+ "//components/page_load_metrics/common:test_support",
+ "//testing/gtest",
+ "//third_party/blink/public:blink_headers",
+ "//url",
+ ]
+}
diff --git a/chromium/components/page_load_metrics/renderer/DEPS b/chromium/components/page_load_metrics/renderer/DEPS
new file mode 100644
index 00000000000..d530fbcadeb
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/DEPS
@@ -0,0 +1,16 @@
+include_rules = [
+ "+base",
+ "+content/public/common",
+ "+content/public/renderer",
+ "+components/data_reduction_proxy/core/common",
+ "+components/subresource_filter/content/renderer",
+ "+services/network/public/cpp",
+ "+third_party/blink/public",
+ "+url",
+]
+
+specific_include_rules = {
+ '.*_[a-z]*test\.cc': [
+ "+testing/gtest"
+ ],
+}
diff --git a/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc b/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc
new file mode 100644
index 00000000000..14a4f66d8ff
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc
@@ -0,0 +1,155 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/page_load_metrics/renderer/fake_page_timing_sender.h"
+
+#include <algorithm>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace page_load_metrics {
+
+FakePageTimingSender::FakePageTimingSender(PageTimingValidator* validator)
+ : validator_(validator) {}
+
+FakePageTimingSender::~FakePageTimingSender() {}
+
+void FakePageTimingSender::SendTiming(
+ const mojom::PageLoadTimingPtr& timing,
+ const mojom::PageLoadMetadataPtr& metadata,
+ mojom::PageLoadFeaturesPtr new_features,
+ std::vector<mojom::ResourceDataUpdatePtr> resources,
+ const mojom::FrameRenderDataUpdate& render_data,
+ const mojom::CpuTimingPtr& cpu_timing,
+ mojom::DeferredResourceCountsPtr new_deferred_resource_data) {
+ validator_->UpdateTiming(timing, metadata, new_features, resources,
+ render_data, cpu_timing, new_deferred_resource_data);
+}
+
+FakePageTimingSender::PageTimingValidator::PageTimingValidator() {}
+
+FakePageTimingSender::PageTimingValidator::~PageTimingValidator() {
+ VerifyExpectedTimings();
+}
+
+void FakePageTimingSender::PageTimingValidator::ExpectPageLoadTiming(
+ const mojom::PageLoadTiming& timing) {
+ VerifyExpectedTimings();
+ expected_timings_.push_back(timing.Clone());
+}
+
+void FakePageTimingSender::PageTimingValidator::ExpectCpuTiming(
+ const base::TimeDelta& timing) {
+ VerifyExpectedCpuTimings();
+ expected_cpu_timings_.push_back(mojom::CpuTiming(timing).Clone());
+}
+
+void FakePageTimingSender::PageTimingValidator::VerifyExpectedTimings() const {
+ // Ideally we'd just call ASSERT_EQ(actual_timings_, expected_timings_) here,
+ // but this causes the generated gtest code to fail to build on Windows. See
+ // the comments in the header file for additional details.
+ ASSERT_EQ(actual_timings_.size(), expected_timings_.size());
+ for (size_t i = 0; i < actual_timings_.size(); ++i) {
+ if (actual_timings_.at(i)->Equals(*expected_timings_.at(i)))
+ continue;
+ ADD_FAILURE() << "Actual timing != expected timing at index " << i;
+ }
+}
+
+void FakePageTimingSender::PageTimingValidator::VerifyExpectedCpuTimings()
+ const {
+ ASSERT_EQ(actual_cpu_timings_.size(), expected_cpu_timings_.size());
+ for (size_t i = 0; i < actual_cpu_timings_.size(); ++i) {
+ if (actual_cpu_timings_.at(i)->task_time ==
+ expected_cpu_timings_.at(i)->task_time)
+ continue;
+ ADD_FAILURE() << "Actual cpu timing != expected cpu timing at index " << i;
+ }
+}
+
+void FakePageTimingSender::PageTimingValidator::UpdateExpectPageLoadFeatures(
+ const blink::mojom::WebFeature feature) {
+ expected_features_.insert(feature);
+}
+
+void FakePageTimingSender::PageTimingValidator::
+ UpdateExpectPageLoadCssProperties(
+ blink::mojom::CSSSampleId css_property_id) {
+ expected_css_properties_.insert(css_property_id);
+}
+
+void FakePageTimingSender::PageTimingValidator::VerifyExpectedFeatures() const {
+ ASSERT_EQ(actual_features_.size(), expected_features_.size());
+ std::vector<blink::mojom::WebFeature> diff;
+ std::set_difference(actual_features_.begin(), actual_features_.end(),
+ expected_features_.begin(), expected_features_.end(),
+ diff.begin());
+ EXPECT_TRUE(diff.empty())
+ << "Expected more features than the actual features observed";
+
+ std::set_difference(expected_features_.begin(), expected_features_.end(),
+ actual_features_.begin(), actual_features_.end(),
+ diff.begin());
+ EXPECT_TRUE(diff.empty())
+ << "More features are actually observed than expected";
+}
+
+void FakePageTimingSender::PageTimingValidator::VerifyExpectedCssProperties()
+ const {
+ ASSERT_EQ(actual_css_properties_.size(), expected_css_properties_.size());
+ std::vector<blink::mojom::CSSSampleId> diff;
+ std::set_difference(actual_css_properties_.begin(),
+ actual_css_properties_.end(),
+ expected_css_properties_.begin(),
+ expected_css_properties_.end(), diff.begin());
+ EXPECT_TRUE(diff.empty())
+ << "Expected more CSS properties than the actual features observed";
+
+ std::set_difference(expected_css_properties_.begin(),
+ expected_css_properties_.end(),
+ actual_css_properties_.begin(),
+ actual_css_properties_.end(), diff.begin());
+ EXPECT_TRUE(diff.empty())
+ << "More CSS Properties are actually observed than expected";
+}
+
+void FakePageTimingSender::PageTimingValidator::VerifyExpectedRenderData()
+ const {
+ EXPECT_FLOAT_EQ(expected_render_data_.layout_shift_delta,
+ actual_render_data_.layout_shift_delta);
+}
+
+void FakePageTimingSender::PageTimingValidator::UpdateTiming(
+ const mojom::PageLoadTimingPtr& timing,
+ const mojom::PageLoadMetadataPtr& metadata,
+ const mojom::PageLoadFeaturesPtr& new_features,
+ const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+ const mojom::FrameRenderDataUpdate& render_data,
+ const mojom::CpuTimingPtr& cpu_timing,
+ const mojom::DeferredResourceCountsPtr& new_deferred_resource_data) {
+ actual_timings_.push_back(timing.Clone());
+ if (!cpu_timing->task_time.is_zero()) {
+ actual_cpu_timings_.push_back(cpu_timing.Clone());
+ }
+ for (const auto feature : new_features->features) {
+ EXPECT_EQ(actual_features_.find(feature), actual_features_.end())
+ << "Feature " << feature << "has been sent more than once";
+ actual_features_.insert(feature);
+ }
+ for (const auto css_property_id : new_features->css_properties) {
+ EXPECT_EQ(actual_css_properties_.find(css_property_id),
+ actual_css_properties_.end())
+ << "CSS Property ID " << css_property_id
+ << "has been sent more than once";
+ actual_css_properties_.insert(css_property_id);
+ }
+ actual_render_data_.layout_shift_delta = render_data.layout_shift_delta;
+ VerifyExpectedTimings();
+ VerifyExpectedCpuTimings();
+ VerifyExpectedFeatures();
+ VerifyExpectedCssProperties();
+ VerifyExpectedRenderData();
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h b/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h
new file mode 100644
index 00000000000..0e742803d13
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h
@@ -0,0 +1,127 @@
+// 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 COMPONENTS_PAGE_LOAD_METRICS_RENDERER_FAKE_PAGE_TIMING_SENDER_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_FAKE_PAGE_TIMING_SENDER_H_
+
+#include <set>
+#include <vector>
+
+#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
+#include "components/page_load_metrics/common/page_load_timing.h"
+#include "components/page_load_metrics/renderer/page_timing_sender.h"
+
+namespace page_load_metrics {
+
+// PageTimingSender implementation for use in tests. Allows for setting and
+// verifying basic expectations when sending PageLoadTiming. By default,
+// FakePageTimingSender will verify that expected and actual
+// PageLoadTimings match on each invocation to ExpectPageLoadTiming() and
+// SendTiming(), as well as in the destructor. Tests can force additional
+// validations by calling VerifyExpectedTimings.
+//
+// Expected PageLoadTimings are specified via ExpectPageLoadTiming, and actual
+// PageLoadTimings are dispatched through SendTiming(). When SendTiming() is
+// called, we verify that the actual PageLoadTimings dipatched through
+// SendTiming() match the expected PageLoadTimings provided via
+// ExpectPageLoadTiming.
+//
+// Normally, gmock would be used in place of this class, but gmock is not
+// compatible with structures that use aligned memory, and PageLoadTiming uses
+// base::Optional which uses aligned memory, so we're forced to roll
+// our own implementation here. See
+// https://groups.google.com/forum/#!topic/googletestframework/W-Hud3j_c6I for
+// more details.
+class FakePageTimingSender : public PageTimingSender {
+ public:
+ class PageTimingValidator {
+ public:
+ PageTimingValidator();
+ ~PageTimingValidator();
+ // PageLoadTimings that are expected to be sent through SendTiming() should
+ // be passed to ExpectPageLoadTiming.
+ void ExpectPageLoadTiming(const mojom::PageLoadTiming& timing);
+
+ // CpuTimings that are expected to be sent through SendTiming() should be
+ // passed to ExpectCpuTiming.
+ void ExpectCpuTiming(const base::TimeDelta& timing);
+
+ // Forces verification that actual timings sent through SendTiming() match
+ // expected timings provided via ExpectPageLoadTiming.
+ void VerifyExpectedTimings() const;
+
+ // Forces verification that actual timings sent through SendTiming() match
+ // expected timings provided via ExpectCpuTiming.
+ void VerifyExpectedCpuTimings() const;
+
+ // PageLoad features that are expected to be sent through SendTiming()
+ // should be passed via UpdateExpectedPageLoadFeatures.
+ void UpdateExpectPageLoadFeatures(const blink::mojom::WebFeature feature);
+ // PageLoad CSS properties that are expected to be sent through SendTiming()
+ // should be passed via UpdateExpectedPageLoadCSSProperties.
+ void UpdateExpectPageLoadCssProperties(
+ blink::mojom::CSSSampleId css_property_id);
+
+ void UpdateExpectFrameRenderDataUpdate(
+ const mojom::FrameRenderDataUpdate& render_data) {
+ expected_render_data_ = render_data;
+ }
+
+ // Forces verification that actual features sent through SendTiming match
+ // expected features provided via ExpectPageLoadFeatures.
+ void VerifyExpectedFeatures() const;
+ // Forces verification that actual CSS properties sent through SendTiming
+ // match expected CSS properties provided via ExpectPageLoadCSSProperties.
+ void VerifyExpectedCssProperties() const;
+ void VerifyExpectedRenderData() const;
+
+ const std::vector<mojom::PageLoadTimingPtr>& expected_timings() const {
+ return expected_timings_;
+ }
+ const std::vector<mojom::PageLoadTimingPtr>& actual_timings() const {
+ return actual_timings_;
+ }
+
+ void UpdateTiming(
+ const mojom::PageLoadTimingPtr& timing,
+ const mojom::PageLoadMetadataPtr& metadata,
+ const mojom::PageLoadFeaturesPtr& new_features,
+ const std::vector<mojom::ResourceDataUpdatePtr>& resources,
+ const mojom::FrameRenderDataUpdate& render_data,
+ const mojom::CpuTimingPtr& cpu_timing,
+ const mojom::DeferredResourceCountsPtr& new_deferred_resource_data);
+
+ private:
+ std::vector<mojom::PageLoadTimingPtr> expected_timings_;
+ std::vector<mojom::PageLoadTimingPtr> actual_timings_;
+ std::vector<mojom::CpuTimingPtr> expected_cpu_timings_;
+ std::vector<mojom::CpuTimingPtr> actual_cpu_timings_;
+ std::set<blink::mojom::WebFeature> expected_features_;
+ std::set<blink::mojom::WebFeature> actual_features_;
+ std::set<blink::mojom::CSSSampleId> expected_css_properties_;
+ std::set<blink::mojom::CSSSampleId> actual_css_properties_;
+ mojom::FrameRenderDataUpdate expected_render_data_;
+ mojom::FrameRenderDataUpdate actual_render_data_;
+ DISALLOW_COPY_AND_ASSIGN(PageTimingValidator);
+ };
+
+ explicit FakePageTimingSender(PageTimingValidator* validator);
+ ~FakePageTimingSender() override;
+ void SendTiming(
+ const mojom::PageLoadTimingPtr& timing,
+ const mojom::PageLoadMetadataPtr& metadata,
+ mojom::PageLoadFeaturesPtr new_features,
+ std::vector<mojom::ResourceDataUpdatePtr> resources,
+ const mojom::FrameRenderDataUpdate& render_data,
+ const mojom::CpuTimingPtr& cpu_timing,
+ mojom::DeferredResourceCountsPtr new_deferred_resource_data) override;
+
+ private:
+ PageTimingValidator* const validator_;
+ DISALLOW_COPY_AND_ASSIGN(FakePageTimingSender);
+};
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_RENDERER_FAKE_PAGE_TIMING_SENDER_H_
diff --git a/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
new file mode 100644
index 00000000000..061e29ed58f
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
@@ -0,0 +1,422 @@
+// 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 "components/page_load_metrics/renderer/metrics_render_frame_observer.h"
+
+#include <string>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "components/page_load_metrics/renderer/page_timing_metrics_sender.h"
+#include "components/page_load_metrics/renderer/page_timing_sender.h"
+#include "content/public/renderer/render_frame.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_document_loader.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_performance.h"
+#include "url/gurl.h"
+
+namespace page_load_metrics {
+
+namespace {
+
+base::TimeDelta ClampDelta(double event, double start) {
+ if (event - start < 0)
+ event = start;
+ return base::Time::FromDoubleT(event) - base::Time::FromDoubleT(start);
+}
+
+class MojoPageTimingSender : public PageTimingSender {
+ public:
+ explicit MojoPageTimingSender(content::RenderFrame* render_frame) {
+ DCHECK(render_frame);
+ render_frame->GetRemoteAssociatedInterfaces()->GetInterface(
+ &page_load_metrics_);
+ }
+ ~MojoPageTimingSender() override {}
+ void SendTiming(
+ const mojom::PageLoadTimingPtr& timing,
+ const mojom::PageLoadMetadataPtr& metadata,
+ mojom::PageLoadFeaturesPtr new_features,
+ std::vector<mojom::ResourceDataUpdatePtr> resources,
+ const mojom::FrameRenderDataUpdate& render_data,
+ const mojom::CpuTimingPtr& cpu_timing,
+ mojom::DeferredResourceCountsPtr new_deferred_resource_data) override {
+ DCHECK(page_load_metrics_);
+ page_load_metrics_->UpdateTiming(
+ timing->Clone(), metadata->Clone(), std::move(new_features),
+ std::move(resources), render_data.Clone(), cpu_timing->Clone(),
+ std::move(new_deferred_resource_data));
+ }
+
+ private:
+ // Use associated interface to make sure mojo messages are ordered with regard
+ // to legacy IPC messages.
+ mojom::PageLoadMetricsAssociatedPtr page_load_metrics_;
+};
+
+} // namespace
+
+MetricsRenderFrameObserver::MetricsRenderFrameObserver(
+ content::RenderFrame* render_frame)
+ : content::RenderFrameObserver(render_frame),
+ scoped_ad_resource_observer_(this) {}
+
+MetricsRenderFrameObserver::~MetricsRenderFrameObserver() {}
+
+void MetricsRenderFrameObserver::DidChangePerformanceTiming() {
+ SendMetrics();
+}
+
+void MetricsRenderFrameObserver::DidChangeCpuTiming(base::TimeDelta time) {
+ if (!page_timing_metrics_sender_)
+ return;
+ if (HasNoRenderFrame())
+ return;
+ page_timing_metrics_sender_->UpdateCpuTiming(time);
+}
+
+void MetricsRenderFrameObserver::DidObserveLoadingBehavior(
+ blink::WebLoadingBehaviorFlag behavior) {
+ if (page_timing_metrics_sender_)
+ page_timing_metrics_sender_->DidObserveLoadingBehavior(behavior);
+}
+
+void MetricsRenderFrameObserver::DidObserveNewFeatureUsage(
+ blink::mojom::WebFeature feature) {
+ if (page_timing_metrics_sender_)
+ page_timing_metrics_sender_->DidObserveNewFeatureUsage(feature);
+}
+
+void MetricsRenderFrameObserver::DidObserveNewCssPropertyUsage(
+ blink::mojom::CSSSampleId css_property,
+ bool is_animated) {
+ if (page_timing_metrics_sender_) {
+ page_timing_metrics_sender_->DidObserveNewCssPropertyUsage(css_property,
+ is_animated);
+ }
+}
+
+void MetricsRenderFrameObserver::DidObserveLayoutShift(
+ double score,
+ bool after_input_or_scroll) {
+ if (page_timing_metrics_sender_)
+ page_timing_metrics_sender_->DidObserveLayoutShift(score,
+ after_input_or_scroll);
+}
+
+void MetricsRenderFrameObserver::DidObserveLazyLoadBehavior(
+ blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
+ if (page_timing_metrics_sender_)
+ page_timing_metrics_sender_->DidObserveLazyLoadBehavior(lazy_load_behavior);
+}
+
+void MetricsRenderFrameObserver::DidStartResponse(
+ const GURL& response_url,
+ int request_id,
+ const network::ResourceResponseHead& response_head,
+ content::ResourceType resource_type,
+ content::PreviewsState previews_state) {
+ if (provisional_frame_resource_data_use_ &&
+ content::IsResourceTypeFrame(resource_type)) {
+ // TODO(rajendrant): This frame request might start before the provisional
+ // load starts, and data use of the frame request might be missed in that
+ // case. There should be a guarantee that DidStartProvisionalLoad be called
+ // before DidStartResponse for the frame request.
+ provisional_frame_resource_data_use_->DidStartResponse(
+ response_url, request_id, response_head, resource_type, previews_state);
+ } else if (page_timing_metrics_sender_) {
+ page_timing_metrics_sender_->DidStartResponse(
+ response_url, request_id, response_head, resource_type, previews_state);
+ UpdateResourceMetadata(request_id);
+ }
+}
+
+void MetricsRenderFrameObserver::DidCompleteResponse(
+ int request_id,
+ const network::URLLoaderCompletionStatus& status) {
+ if (provisional_frame_resource_data_use_ &&
+ provisional_frame_resource_data_use_->resource_id() == request_id) {
+ provisional_frame_resource_data_use_->DidCompleteResponse(status);
+ } else if (page_timing_metrics_sender_) {
+ page_timing_metrics_sender_->DidCompleteResponse(request_id, status);
+ // The provisional frame can be flagged as an ad anytime during the load.
+ if (request_id == provisional_frame_resource_id)
+ UpdateResourceMetadata(request_id);
+ }
+}
+
+void MetricsRenderFrameObserver::DidCancelResponse(int request_id) {
+ if (provisional_frame_resource_data_use_ &&
+ provisional_frame_resource_data_use_->resource_id() == request_id) {
+ provisional_frame_resource_data_use_.reset();
+ } else if (page_timing_metrics_sender_) {
+ page_timing_metrics_sender_->DidCancelResponse(request_id);
+ // The provisional frame can be flagged as an ad anytime during the load.
+ if (request_id == provisional_frame_resource_id)
+ UpdateResourceMetadata(request_id);
+ }
+}
+
+void MetricsRenderFrameObserver::DidReceiveTransferSizeUpdate(
+ int request_id,
+ int received_data_length) {
+ if (provisional_frame_resource_data_use_ &&
+ provisional_frame_resource_data_use_->resource_id() == request_id) {
+ provisional_frame_resource_data_use_->DidReceiveTransferSizeUpdate(
+ received_data_length);
+ } else if (page_timing_metrics_sender_) {
+ page_timing_metrics_sender_->DidReceiveTransferSizeUpdate(
+ request_id, received_data_length);
+ // The provisional frame can be flagged as an ad anytime during the load.
+ if (request_id == provisional_frame_resource_id)
+ UpdateResourceMetadata(request_id);
+ }
+}
+
+void MetricsRenderFrameObserver::DidLoadResourceFromMemoryCache(
+ const GURL& response_url,
+ int request_id,
+ int64_t encoded_body_length,
+ const std::string& mime_type,
+ bool from_archive) {
+ // Resources from archives, such as subresources from a MHTML archive, do not
+ // have valid request ids and should not be reported to PLM.
+ if (from_archive)
+ return;
+
+ // A provisional frame resource cannot be serviced from the memory cache, so
+ // we do not need to check |provisional_frame_resource_data_use_|.
+ if (page_timing_metrics_sender_) {
+ page_timing_metrics_sender_->DidLoadResourceFromMemoryCache(
+ response_url, request_id, encoded_body_length, mime_type);
+ }
+}
+
+void MetricsRenderFrameObserver::FrameDetached() {
+ page_timing_metrics_sender_.reset();
+}
+
+void MetricsRenderFrameObserver::ReadyToCommitNavigation(
+ blink::WebDocumentLoader* document_loader) {
+ // Create a new data use tracker for the new document load.
+ provisional_frame_resource_data_use_ =
+ std::make_unique<PageResourceDataUse>();
+ provisional_frame_resource_id = 0;
+}
+
+void MetricsRenderFrameObserver::DidFailProvisionalLoad(
+ const blink::WebURLError& error) {
+ // Clear the data use tracker for the provisional navigation that started.
+ provisional_frame_resource_data_use_.reset();
+}
+
+void MetricsRenderFrameObserver::DidCommitProvisionalLoad(
+ bool is_same_document_navigation,
+ ui::PageTransition transition) {
+ // Same-document navigations (e.g. a navigation from a fragment link) aren't
+ // full page loads, since they don't go to network to load the main HTML
+ // resource. DidStartProvisionalLoad doesn't get invoked for same document
+ // navigations, so we may still have an active page_timing_metrics_sender_ at
+ // this point.
+ if (is_same_document_navigation)
+ return;
+
+ // Make sure to release the sender for a previous navigation, if we have one.
+ page_timing_metrics_sender_.reset();
+
+ if (HasNoRenderFrame())
+ return;
+
+ // Update metadata once the load has been committed. There is no guarantee
+ // that the provisional resource will have been reported as an ad by this
+ // point. Therefore, need to update metadata for the resource after the load.
+ // Consumers may receive the correct ad information late.
+ UpdateResourceMetadata(provisional_frame_resource_data_use_->resource_id());
+
+ provisional_frame_resource_id =
+ provisional_frame_resource_data_use_->resource_id();
+
+ page_timing_metrics_sender_ = std::make_unique<PageTimingMetricsSender>(
+ CreatePageTimingSender(), CreateTimer(), GetTiming(),
+ std::move(provisional_frame_resource_data_use_));
+}
+
+void MetricsRenderFrameObserver::SetAdResourceTracker(
+ subresource_filter::AdResourceTracker* ad_resource_tracker) {
+ // Remove all sources and set a new source for the observer.
+ scoped_ad_resource_observer_.RemoveAll();
+ scoped_ad_resource_observer_.Add(ad_resource_tracker);
+}
+
+void MetricsRenderFrameObserver::OnAdResourceTrackerGoingAway() {
+ scoped_ad_resource_observer_.RemoveAll();
+}
+
+void MetricsRenderFrameObserver::OnAdResourceObserved(int request_id) {
+ ad_request_ids_.insert(request_id);
+}
+
+void MetricsRenderFrameObserver::UpdateResourceMetadata(int request_id) {
+ if (!page_timing_metrics_sender_)
+ return;
+ // If the request is an ad, pop it off the list of known ad requests.
+ auto ad_resource_it = ad_request_ids_.find(request_id);
+ bool reported_as_ad_resource =
+ ad_request_ids_.find(request_id) != ad_request_ids_.end();
+ if (reported_as_ad_resource)
+ ad_request_ids_.erase(ad_resource_it);
+ bool is_main_frame_resource = render_frame()->IsMainFrame();
+ if (provisional_frame_resource_data_use_ &&
+ provisional_frame_resource_data_use_->resource_id() == request_id) {
+ if (reported_as_ad_resource)
+ provisional_frame_resource_data_use_->SetReportedAsAdResource(
+ reported_as_ad_resource);
+ provisional_frame_resource_data_use_->SetIsMainFrameResource(
+ is_main_frame_resource);
+ } else {
+ page_timing_metrics_sender_->UpdateResourceMetadata(
+ request_id, reported_as_ad_resource, is_main_frame_resource);
+ }
+}
+
+void MetricsRenderFrameObserver::SendMetrics() {
+ if (!page_timing_metrics_sender_)
+ return;
+ if (HasNoRenderFrame())
+ return;
+ page_timing_metrics_sender_->Send(GetTiming());
+}
+
+mojom::PageLoadTimingPtr MetricsRenderFrameObserver::GetTiming() const {
+ const blink::WebPerformance& perf =
+ render_frame()->GetWebFrame()->Performance();
+
+ mojom::PageLoadTimingPtr timing(CreatePageLoadTiming());
+ double start = perf.NavigationStart();
+ timing->navigation_start = base::Time::FromDoubleT(start);
+ if (perf.InputForNavigationStart() > 0.0) {
+ timing->input_to_navigation_start =
+ ClampDelta(start, perf.InputForNavigationStart());
+ }
+ if (perf.PageInteractive() > 0.0) {
+ // PageInteractive and PageInteractiveDetection should be available at the
+ // same time. This is a renderer side DCHECK to ensure this.
+ DCHECK(perf.PageInteractiveDetection());
+ timing->interactive_timing->interactive =
+ ClampDelta(perf.PageInteractive(), start);
+ timing->interactive_timing->interactive_detection =
+ ClampDelta(perf.PageInteractiveDetection(), start);
+ }
+ if (perf.FirstInputInvalidatingInteractive() > 0.0) {
+ timing->interactive_timing->first_invalidating_input =
+ ClampDelta(perf.FirstInputInvalidatingInteractive(), start);
+ }
+ if (perf.FirstInputDelay() > 0.0) {
+ timing->interactive_timing->first_input_delay =
+ base::TimeDelta::FromSecondsD(perf.FirstInputDelay());
+ }
+ if (perf.FirstInputTimestamp() > 0.0) {
+ timing->interactive_timing->first_input_timestamp =
+ ClampDelta(perf.FirstInputTimestamp(), start);
+ }
+ if (perf.LongestInputDelay() > 0.0) {
+ timing->interactive_timing->longest_input_delay =
+ base::TimeDelta::FromSecondsD(perf.LongestInputDelay());
+ }
+ if (perf.LongestInputTimestamp() > 0.0) {
+ timing->interactive_timing->longest_input_timestamp =
+ ClampDelta(perf.LongestInputTimestamp(), start);
+ }
+ if (perf.ResponseStart() > 0.0)
+ timing->response_start = ClampDelta(perf.ResponseStart(), start);
+ if (perf.DomContentLoadedEventStart() > 0.0) {
+ timing->document_timing->dom_content_loaded_event_start =
+ ClampDelta(perf.DomContentLoadedEventStart(), start);
+ }
+ if (perf.LoadEventStart() > 0.0) {
+ timing->document_timing->load_event_start =
+ ClampDelta(perf.LoadEventStart(), start);
+ }
+ if (perf.FirstLayout() > 0.0)
+ timing->document_timing->first_layout =
+ ClampDelta(perf.FirstLayout(), start);
+ if (perf.FirstPaint() > 0.0)
+ timing->paint_timing->first_paint = ClampDelta(perf.FirstPaint(), start);
+ if (perf.FirstImagePaint() > 0.0) {
+ timing->paint_timing->first_image_paint =
+ ClampDelta(perf.FirstImagePaint(), start);
+ }
+ if (perf.FirstContentfulPaint() > 0.0) {
+ timing->paint_timing->first_contentful_paint =
+ ClampDelta(perf.FirstContentfulPaint(), start);
+ }
+ if (perf.FirstMeaningfulPaint() > 0.0) {
+ timing->paint_timing->first_meaningful_paint =
+ ClampDelta(perf.FirstMeaningfulPaint(), start);
+ }
+ if (perf.LargestImagePaintSize() > 0) {
+ timing->paint_timing->largest_image_paint =
+ perf.LargestImagePaint() == 0.0
+ ? base::TimeDelta()
+ : ClampDelta(perf.LargestImagePaint(), start);
+ timing->paint_timing->largest_image_paint_size =
+ perf.LargestImagePaintSize();
+ }
+ if (perf.LargestTextPaintSize() > 0) {
+ timing->paint_timing->largest_text_paint =
+ perf.LargestTextPaint() == 0.0
+ ? base::TimeDelta()
+ : ClampDelta(perf.LargestTextPaint(), start);
+ timing->paint_timing->largest_text_paint_size = perf.LargestTextPaintSize();
+ }
+ if (perf.ParseStart() > 0.0)
+ timing->parse_timing->parse_start = ClampDelta(perf.ParseStart(), start);
+ if (perf.ParseStop() > 0.0)
+ timing->parse_timing->parse_stop = ClampDelta(perf.ParseStop(), start);
+ if (timing->parse_timing->parse_start) {
+ // If we started parsing, record all parser durations such as the amount of
+ // time blocked on script load, even if those values are zero.
+ timing->parse_timing->parse_blocked_on_script_load_duration =
+ base::TimeDelta::FromSecondsD(perf.ParseBlockedOnScriptLoadDuration());
+ timing->parse_timing
+ ->parse_blocked_on_script_load_from_document_write_duration =
+ base::TimeDelta::FromSecondsD(
+ perf.ParseBlockedOnScriptLoadFromDocumentWriteDuration());
+ timing->parse_timing->parse_blocked_on_script_execution_duration =
+ base::TimeDelta::FromSecondsD(
+ perf.ParseBlockedOnScriptExecutionDuration());
+ timing->parse_timing
+ ->parse_blocked_on_script_execution_from_document_write_duration =
+ base::TimeDelta::FromSecondsD(
+ perf.ParseBlockedOnScriptExecutionFromDocumentWriteDuration());
+ }
+
+ return timing;
+}
+
+std::unique_ptr<base::OneShotTimer> MetricsRenderFrameObserver::CreateTimer() {
+ return std::make_unique<base::OneShotTimer>();
+}
+
+std::unique_ptr<PageTimingSender>
+MetricsRenderFrameObserver::CreatePageTimingSender() {
+ return base::WrapUnique<PageTimingSender>(
+ new MojoPageTimingSender(render_frame()));
+}
+
+bool MetricsRenderFrameObserver::HasNoRenderFrame() const {
+ bool no_frame = !render_frame() || !render_frame()->GetWebFrame();
+ DCHECK(!no_frame);
+ return no_frame;
+}
+
+void MetricsRenderFrameObserver::OnDestruct() {
+ delete this;
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h
new file mode 100644
index 00000000000..ac56f4fe94d
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h
@@ -0,0 +1,125 @@
+// 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 COMPONENTS_PAGE_LOAD_METRICS_RENDERER_METRICS_RENDER_FRAME_OBSERVER_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_METRICS_RENDER_FRAME_OBSERVER_H_
+
+#include <memory>
+#include <set>
+
+#include "base/macros.h"
+#include "base/scoped_observer.h"
+#include "components/page_load_metrics/common/page_load_timing.h"
+#include "components/page_load_metrics/renderer/page_resource_data_use.h"
+#include "components/subresource_filter/content/renderer/ad_resource_tracker.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+
+class GURL;
+
+namespace base {
+class OneShotTimer;
+} // namespace base
+
+namespace page_load_metrics {
+
+class PageTimingMetricsSender;
+class PageTimingSender;
+
+// MetricsRenderFrameObserver observes RenderFrame notifications, and sends page
+// load timing information to the browser process over IPC. A
+// MetricsRenderFrameObserver is instantiated for each frame (main frames and
+// child frames). MetricsRenderFrameObserver dispatches timing and metadata
+// updates for main frames, but only metadata updates for child frames.
+class MetricsRenderFrameObserver
+ : public content::RenderFrameObserver,
+ public subresource_filter::AdResourceTracker::Observer {
+ public:
+ explicit MetricsRenderFrameObserver(content::RenderFrame* render_frame);
+ ~MetricsRenderFrameObserver() override;
+
+ // RenderFrameObserver implementation
+ void DidChangePerformanceTiming() override;
+ void DidChangeCpuTiming(base::TimeDelta time) override;
+ void DidObserveLoadingBehavior(
+ blink::WebLoadingBehaviorFlag behavior) override;
+ void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature) override;
+ void DidObserveNewCssPropertyUsage(blink::mojom::CSSSampleId css_property,
+ bool is_animated) override;
+ void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
+ void DidObserveLazyLoadBehavior(
+ blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
+ void DidStartResponse(const GURL& response_url,
+ int request_id,
+ const network::ResourceResponseHead& response_head,
+ content::ResourceType resource_type,
+ content::PreviewsState previews_state) override;
+ void DidReceiveTransferSizeUpdate(int request_id,
+ int received_data_length) override;
+ void DidCompleteResponse(
+ int request_id,
+ const network::URLLoaderCompletionStatus& status) override;
+ void DidCancelResponse(int request_id) override;
+ void DidLoadResourceFromMemoryCache(const GURL& response_url,
+ int request_id,
+ int64_t encoded_body_length,
+ const std::string& mime_type,
+ bool from_archive) override;
+ void ReadyToCommitNavigation(
+ blink::WebDocumentLoader* document_loader) override;
+ void DidFailProvisionalLoad(const blink::WebURLError& error) override;
+ void DidCommitProvisionalLoad(bool is_same_document_navigation,
+ ui::PageTransition transition) override;
+ void OnDestruct() override;
+
+ // Invoked when a frame is going away. This is our last chance to send IPCs
+ // before being destroyed.
+ void FrameDetached() override;
+
+ // Set the ad resource tracker that |this| observes.
+ void SetAdResourceTracker(
+ subresource_filter::AdResourceTracker* ad_resource_tracker);
+
+ // AdResourceTracker implementation
+ void OnAdResourceTrackerGoingAway() override;
+ void OnAdResourceObserved(int request_id) override;
+
+ private:
+ // Updates the metadata for the page resource associated with the given
+ // request_id. Removes the request_id from the list of known ads if it is an
+ // ad.
+ void UpdateResourceMetadata(int request_id);
+
+ void SendMetrics();
+ virtual mojom::PageLoadTimingPtr GetTiming() const;
+ virtual std::unique_ptr<base::OneShotTimer> CreateTimer();
+ virtual std::unique_ptr<PageTimingSender> CreatePageTimingSender();
+ virtual bool HasNoRenderFrame() const;
+
+ // Collects the data use of the frame request for a provisional load until the
+ // load is committed. We want to collect data use for completed navigations in
+ // this class, but the various navigation callbacks do not provide enough data
+ // for us to use them for data attribution. Instead, we try to get this
+ // information from ongoing resource requests on the previous page (or right
+ // before this page loads in a new renderer).
+ std::unique_ptr<PageResourceDataUse> provisional_frame_resource_data_use_;
+ int provisional_frame_resource_id = 0;
+
+ ScopedObserver<subresource_filter::AdResourceTracker,
+ subresource_filter::AdResourceTracker::Observer>
+ scoped_ad_resource_observer_;
+
+ // Set containing all request ids that were reported as ads from the renderer.
+ std::set<int> ad_request_ids_;
+
+ // Will be null when we're not actively sending metrics.
+ std::unique_ptr<PageTimingMetricsSender> page_timing_metrics_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(MetricsRenderFrameObserver);
+};
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_RENDERER_METRICS_RENDER_FRAME_OBSERVER_H_
diff --git a/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer_unittest.cc b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer_unittest.cc
new file mode 100644
index 00000000000..748636fd6ca
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer_unittest.cc
@@ -0,0 +1,225 @@
+// 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 "components/page_load_metrics/renderer/metrics_render_frame_observer.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/time/time.h"
+#include "base/timer/mock_timer.h"
+#include "components/page_load_metrics/common/page_load_timing.h"
+#include "components/page_load_metrics/common/test/weak_mock_timer.h"
+#include "components/page_load_metrics/renderer/fake_page_timing_sender.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace page_load_metrics {
+
+// Implementation of the MetricsRenderFrameObserver class we're testing, with
+// the GetTiming() method stubbed out to make the rest of the class more
+// testable.
+class TestMetricsRenderFrameObserver : public MetricsRenderFrameObserver,
+ public test::WeakMockTimerProvider {
+ public:
+ TestMetricsRenderFrameObserver() : MetricsRenderFrameObserver(nullptr) {}
+
+ std::unique_ptr<base::OneShotTimer> CreateTimer() override {
+ auto timer = std::make_unique<test::WeakMockTimer>();
+ SetMockTimer(timer->AsWeakPtr());
+ return std::move(timer);
+ }
+
+ std::unique_ptr<PageTimingSender> CreatePageTimingSender() override {
+ return base::WrapUnique<PageTimingSender>(
+ new FakePageTimingSender(&validator_));
+ }
+
+ void ExpectPageLoadTiming(const mojom::PageLoadTiming& timing) {
+ SetFakePageLoadTiming(timing);
+ validator_.ExpectPageLoadTiming(timing);
+ }
+
+ void ExpectCpuTiming(const base::TimeDelta& timing) {
+ validator_.ExpectCpuTiming(timing);
+ }
+
+ void SetFakePageLoadTiming(const mojom::PageLoadTiming& timing) {
+ EXPECT_EQ(nullptr, fake_timing_.get());
+ fake_timing_ = timing.Clone();
+ }
+
+ mojom::PageLoadTimingPtr GetTiming() const override {
+ EXPECT_NE(nullptr, fake_timing_.get());
+ return std::move(fake_timing_);
+ }
+
+ void VerifyExpectedTimings() const {
+ EXPECT_EQ(nullptr, fake_timing_.get());
+ validator_.VerifyExpectedTimings();
+ }
+
+ bool HasNoRenderFrame() const override { return false; }
+
+ private:
+ FakePageTimingSender::PageTimingValidator validator_;
+ mutable mojom::PageLoadTimingPtr fake_timing_;
+};
+
+typedef testing::Test MetricsRenderFrameObserverTest;
+
+TEST_F(MetricsRenderFrameObserverTest, NoMetrics) {
+ TestMetricsRenderFrameObserver observer;
+ observer.DidChangePerformanceTiming();
+ ASSERT_EQ(nullptr, observer.GetMockTimer());
+}
+
+TEST_F(MetricsRenderFrameObserverTest, SingleMetric) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(10);
+
+ TestMetricsRenderFrameObserver observer;
+
+ mojom::PageLoadTiming timing;
+ page_load_metrics::InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ observer.ExpectPageLoadTiming(timing);
+ observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.ReadyToCommitNavigation(nullptr);
+ observer.DidCommitProvisionalLoad(false, ui::PAGE_TRANSITION_LINK);
+ observer.GetMockTimer()->Fire();
+
+ timing.document_timing->first_layout = first_layout;
+ observer.ExpectPageLoadTiming(timing);
+
+ observer.DidChangePerformanceTiming();
+ observer.GetMockTimer()->Fire();
+}
+
+// Verify that when two CpuTimings come in, they're grouped into a single
+// Message with the total being the sum of the two.
+TEST_F(MetricsRenderFrameObserverTest, SingleCpuMetric) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ TestMetricsRenderFrameObserver observer;
+ mojom::PageLoadTiming timing;
+
+ // Initialize the page and add the initial timing info to the expected.
+ page_load_metrics::InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ observer.ExpectPageLoadTiming(timing);
+ observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.ReadyToCommitNavigation(nullptr);
+ observer.DidCommitProvisionalLoad(false, ui::PAGE_TRANSITION_LINK);
+
+ // Send cpu timing updates and verify the expected result.
+ observer.DidChangeCpuTiming(base::TimeDelta::FromMilliseconds(110));
+ observer.DidChangeCpuTiming(base::TimeDelta::FromMilliseconds(50));
+ observer.ExpectCpuTiming(base::TimeDelta::FromMilliseconds(160));
+ observer.GetMockTimer()->Fire();
+}
+
+TEST_F(MetricsRenderFrameObserverTest, MultipleMetrics) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(2);
+ base::TimeDelta dom_event = base::TimeDelta::FromMillisecondsD(2);
+ base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(2);
+
+ TestMetricsRenderFrameObserver observer;
+
+ mojom::PageLoadTiming timing;
+ page_load_metrics::InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ observer.ExpectPageLoadTiming(timing);
+ observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.ReadyToCommitNavigation(nullptr);
+ observer.DidCommitProvisionalLoad(false, ui::PAGE_TRANSITION_LINK);
+ observer.GetMockTimer()->Fire();
+
+ timing.document_timing->first_layout = first_layout;
+ timing.document_timing->dom_content_loaded_event_start = dom_event;
+ observer.ExpectPageLoadTiming(timing);
+
+ observer.DidChangePerformanceTiming();
+ observer.GetMockTimer()->Fire();
+
+ // At this point, we should have triggered the generation of two metrics.
+ // Verify and reset the observer's expectations before moving on to the next
+ // part of the test.
+ observer.VerifyExpectedTimings();
+
+ timing.document_timing->load_event_start = load_event;
+ observer.ExpectPageLoadTiming(timing);
+
+ observer.DidChangePerformanceTiming();
+ observer.GetMockTimer()->Fire();
+
+ // Verify and reset the observer's expectations before moving on to the next
+ // part of the test.
+ observer.VerifyExpectedTimings();
+
+ // The PageLoadTiming above includes timing information for the first layout,
+ // dom content, and load metrics. However, since we've already generated
+ // timing information for all of these metrics previously, we do not expect
+ // this invocation to generate any additional metrics.
+ observer.SetFakePageLoadTiming(timing);
+ observer.DidChangePerformanceTiming();
+ ASSERT_FALSE(observer.GetMockTimer()->IsRunning());
+}
+
+TEST_F(MetricsRenderFrameObserverTest, MultipleNavigations) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(2);
+ base::TimeDelta dom_event = base::TimeDelta::FromMillisecondsD(2);
+ base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(2);
+
+ TestMetricsRenderFrameObserver observer;
+
+ mojom::PageLoadTiming timing;
+ page_load_metrics::InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ observer.ExpectPageLoadTiming(timing);
+ observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.ReadyToCommitNavigation(nullptr);
+ observer.DidCommitProvisionalLoad(false, ui::PAGE_TRANSITION_LINK);
+ observer.GetMockTimer()->Fire();
+
+ timing.document_timing->first_layout = first_layout;
+ timing.document_timing->dom_content_loaded_event_start = dom_event;
+ timing.document_timing->load_event_start = load_event;
+ observer.ExpectPageLoadTiming(timing);
+ observer.DidChangePerformanceTiming();
+ observer.GetMockTimer()->Fire();
+
+ // At this point, we should have triggered the generation of two metrics.
+ // Verify and reset the observer's expectations before moving on to the next
+ // part of the test.
+ observer.VerifyExpectedTimings();
+
+ base::Time nav_start_2 = base::Time::FromDoubleT(100);
+ base::TimeDelta first_layout_2 = base::TimeDelta::FromMillisecondsD(20);
+ base::TimeDelta dom_event_2 = base::TimeDelta::FromMillisecondsD(20);
+ base::TimeDelta load_event_2 = base::TimeDelta::FromMillisecondsD(20);
+ mojom::PageLoadTiming timing_2;
+ page_load_metrics::InitPageLoadTimingForTest(&timing_2);
+ timing_2.navigation_start = nav_start_2;
+
+ observer.SetMockTimer(nullptr);
+
+ observer.ExpectPageLoadTiming(timing_2);
+ observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.ReadyToCommitNavigation(nullptr);
+ observer.DidCommitProvisionalLoad(false, ui::PAGE_TRANSITION_LINK);
+ observer.GetMockTimer()->Fire();
+
+ timing_2.document_timing->first_layout = first_layout_2;
+ timing_2.document_timing->dom_content_loaded_event_start = dom_event_2;
+ timing_2.document_timing->load_event_start = load_event_2;
+ observer.ExpectPageLoadTiming(timing_2);
+
+ observer.DidChangePerformanceTiming();
+ observer.GetMockTimer()->Fire();
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/renderer/page_resource_data_use.cc b/chromium/components/page_load_metrics/renderer/page_resource_data_use.cc
new file mode 100644
index 00000000000..2d5f6b1ced7
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/page_resource_data_use.cc
@@ -0,0 +1,196 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/page_load_metrics/renderer/page_resource_data_use.h"
+
+#include "base/stl_util.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "url/gurl.h"
+
+namespace page_load_metrics {
+
+namespace {
+
+// Returns true when the image is a placeholder for lazy load.
+bool IsPartialImageRequest(content::ResourceType resource_type,
+ content::PreviewsState previews_state) {
+ if (resource_type != content::ResourceType::kImage)
+ return false;
+ return previews_state & content::PreviewsTypes::LAZY_IMAGE_LOAD_DEFERRED;
+}
+
+// Returns true if this resource was previously fetched as a placeholder.
+bool IsImageAutoReload(content::ResourceType resource_type,
+ content::PreviewsState previews_state) {
+ if (resource_type != content::ResourceType::kImage)
+ return false;
+ return previews_state & content::PreviewsTypes::LAZY_IMAGE_AUTO_RELOAD;
+}
+
+// Returns the ratio of original data size (without applying interventions) to
+// actual data use for a placeholder.
+double EstimatePartialImageRequestSavings(
+ const network::ResourceResponseHead& response_head) {
+ if (!response_head.headers)
+ return 1.0;
+
+ if (response_head.headers->GetContentLength() <= 0)
+ return 1.0;
+
+ int64_t first, last, original_length;
+ if (!response_head.headers->GetContentRangeFor206(&first, &last,
+ &original_length)) {
+ return 1.0;
+ }
+
+ if (original_length < response_head.headers->GetContentLength())
+ return 1.0;
+
+ return original_length / response_head.headers->GetContentLength();
+}
+
+// Returns a ratio of original data use to actual data use while factoring in
+// that this request was previously fetched as a placeholder, and therefore
+// recorded savings earlier.
+double EstimateAutoReloadImageRequestSavings(
+ const network::ResourceResponseHead& response_head) {
+ static const double kPlageholderContentInCache = 2048;
+
+ // Count the new network usage. For a reloaded placeholder image, 2KB will be
+ // in cache.
+ return kPlageholderContentInCache / response_head.headers->GetContentLength();
+}
+
+} // namespace
+
+PageResourceDataUse::PageResourceDataUse()
+ : resource_id_(-1),
+ data_reduction_proxy_compression_ratio_estimate_(1.0),
+ total_received_bytes_(0),
+ last_update_bytes_(0),
+ is_complete_(false),
+ is_canceled_(false),
+ reported_as_ad_resource_(false),
+ is_main_frame_resource_(false),
+ is_secure_scheme_(false),
+ proxy_used_(false),
+ cache_type_(mojom::CacheType::kNotCached) {}
+
+PageResourceDataUse::PageResourceDataUse(const PageResourceDataUse& other) =
+ default;
+PageResourceDataUse::~PageResourceDataUse() = default;
+
+void PageResourceDataUse::DidStartResponse(
+ const GURL& response_url,
+ int resource_id,
+ const network::ResourceResponseHead& response_head,
+ content::ResourceType resource_type,
+ content::PreviewsState previews_state) {
+ resource_id_ = resource_id;
+
+ if (IsPartialImageRequest(resource_type, previews_state)) {
+ data_reduction_proxy_compression_ratio_estimate_ =
+ EstimatePartialImageRequestSavings(response_head);
+ } else if (IsImageAutoReload(resource_type, previews_state)) {
+ data_reduction_proxy_compression_ratio_estimate_ =
+ EstimateAutoReloadImageRequestSavings(response_head);
+ } else {
+ data_reduction_proxy_compression_ratio_estimate_ =
+ data_reduction_proxy::EstimateCompressionRatioFromHeaders(
+ &response_head);
+ }
+
+ proxy_used_ = !response_head.proxy_server.is_direct();
+ mime_type_ = response_head.mime_type;
+ if (response_head.was_fetched_via_cache)
+ cache_type_ = mojom::CacheType::kHttp;
+ is_secure_scheme_ = response_url.SchemeIsCryptographic();
+ is_primary_frame_resource_ =
+ resource_type == content::ResourceType::kMainFrame ||
+ resource_type == content::ResourceType::kSubFrame;
+ origin_ = url::Origin::Create(response_url);
+}
+
+void PageResourceDataUse::DidReceiveTransferSizeUpdate(
+ int received_data_length) {
+ total_received_bytes_ += received_data_length;
+}
+
+void PageResourceDataUse::DidCompleteResponse(
+ const network::URLLoaderCompletionStatus& status) {
+ // Report the difference in received bytes.
+ is_complete_ = true;
+ encoded_body_length_ = status.encoded_body_length;
+ int64_t delta_bytes = status.encoded_data_length - total_received_bytes_;
+ if (delta_bytes > 0) {
+ total_received_bytes_ += delta_bytes;
+ }
+}
+
+void PageResourceDataUse::DidCancelResponse() {
+ is_canceled_ = true;
+}
+
+void PageResourceDataUse::DidLoadFromMemoryCache(const GURL& response_url,
+ int request_id,
+ int64_t encoded_body_length,
+ const std::string& mime_type) {
+ origin_ = url::Origin::Create(response_url);
+ resource_id_ = request_id;
+ mime_type_ = mime_type;
+ is_secure_scheme_ = response_url.SchemeIsCryptographic();
+ cache_type_ = mojom::CacheType::kMemory;
+
+ // Resources from the memory cache cannot be a primary frame resource.
+ is_primary_frame_resource_ = false;
+
+ is_complete_ = true;
+ encoded_body_length_ = encoded_body_length;
+}
+
+bool PageResourceDataUse::IsFinishedLoading() {
+ return is_complete_ || is_canceled_;
+}
+
+void PageResourceDataUse::SetReportedAsAdResource(
+ bool reported_as_ad_resource) {
+ reported_as_ad_resource_ = reported_as_ad_resource;
+}
+
+void PageResourceDataUse::SetIsMainFrameResource(bool is_main_frame_resource) {
+ is_main_frame_resource_ = is_main_frame_resource;
+}
+
+int PageResourceDataUse::CalculateNewlyReceivedBytes() {
+ int newly_received_bytes = total_received_bytes_ - last_update_bytes_;
+ last_update_bytes_ = total_received_bytes_;
+ DCHECK_GE(newly_received_bytes, 0);
+ return newly_received_bytes;
+}
+
+mojom::ResourceDataUpdatePtr PageResourceDataUse::GetResourceDataUpdate() {
+ DCHECK(cache_type_ == mojom::CacheType::kMemory ? is_complete_ : true);
+ mojom::ResourceDataUpdatePtr resource_data_update =
+ mojom::ResourceDataUpdate::New();
+ resource_data_update->request_id = resource_id();
+ resource_data_update->received_data_length = total_received_bytes_;
+ resource_data_update->delta_bytes = CalculateNewlyReceivedBytes();
+ resource_data_update->is_complete = is_complete_;
+ resource_data_update->data_reduction_proxy_compression_ratio_estimate =
+ data_reduction_proxy_compression_ratio_estimate_;
+ resource_data_update->reported_as_ad_resource = reported_as_ad_resource_;
+ resource_data_update->is_main_frame_resource = is_main_frame_resource_;
+ resource_data_update->mime_type = mime_type_;
+ resource_data_update->encoded_body_length = encoded_body_length_;
+ resource_data_update->cache_type = cache_type_;
+ resource_data_update->is_secure_scheme = is_secure_scheme_;
+ resource_data_update->proxy_used = proxy_used_;
+ resource_data_update->is_primary_frame_resource = is_primary_frame_resource_;
+ resource_data_update->origin = origin_;
+ return resource_data_update;
+}
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/renderer/page_resource_data_use.h b/chromium/components/page_load_metrics/renderer/page_resource_data_use.h
new file mode 100644
index 00000000000..c90822ecb8f
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/page_resource_data_use.h
@@ -0,0 +1,101 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_RESOURCE_DATA_USE_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_RESOURCE_DATA_USE_H_
+
+#include "base/macros.h"
+#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
+#include "content/public/common/previews_state.h"
+#include "content/public/common/resource_type.h"
+#include "url/origin.h"
+
+class GURL;
+
+namespace network {
+struct ResourceResponseHead;
+struct URLLoaderCompletionStatus;
+} // namespace network
+
+namespace page_load_metrics {
+
+// PageResourceDataUse contains the data use information of one resource. Data
+// use is updated when resource size updates are called.
+class PageResourceDataUse {
+ public:
+ PageResourceDataUse();
+ PageResourceDataUse(const PageResourceDataUse& other);
+ ~PageResourceDataUse();
+
+ void DidStartResponse(const GURL& response_url,
+ int resource_id,
+ const network::ResourceResponseHead& response_head,
+ content::ResourceType resource_type,
+ content::PreviewsState previews_state);
+
+ // Updates received bytes.
+ void DidReceiveTransferSizeUpdate(int received_data_length);
+
+ // Updates received bytes from encoded length.
+ void DidCompleteResponse(const network::URLLoaderCompletionStatus& status);
+
+ // Flags the resource as canceled.
+ void DidCancelResponse();
+
+ // Called when this resource was loaded from the memory cache. Resources
+ // loaded from the memory cache only receive a single update.
+ void DidLoadFromMemoryCache(const GURL& response_url,
+ int request_id,
+ int64_t encoded_body_length,
+ const std::string& mime_type);
+
+ // Checks if the resource has completed loading or if the response was
+ // cancelled.
+ bool IsFinishedLoading();
+
+ int resource_id() const { return resource_id_; }
+
+ void SetReportedAsAdResource(bool reported_as_ad_resource);
+ void SetIsMainFrameResource(bool is_main_frame_resource);
+
+ // Creates a ResourceDataUpdate mojo for this resource. This page resource
+ // contains information since the last time update. Should be called at most
+ // once once per timing update.
+ mojom::ResourceDataUpdatePtr GetResourceDataUpdate();
+
+ private:
+ // Calculates the difference between |total_received_bytes_| and
+ // |last_update_bytes_|, returns it, and updates |last_update_bytes_|.
+ int CalculateNewlyReceivedBytes();
+
+ int resource_id_;
+
+ // Compression ratio estimated from the response headers if data saver was
+ // used.
+ double data_reduction_proxy_compression_ratio_estimate_;
+
+ uint64_t total_received_bytes_ = 0;
+ uint64_t last_update_bytes_ = 0;
+ uint64_t encoded_body_length_ = 0;
+
+ bool is_complete_;
+ bool is_canceled_;
+ bool reported_as_ad_resource_;
+ bool is_main_frame_resource_;
+ bool is_secure_scheme_;
+ bool proxy_used_;
+ bool is_primary_frame_resource_ = false;
+
+ mojom::CacheType cache_type_;
+
+ url::Origin origin_;
+
+ std::string mime_type_;
+
+ DISALLOW_ASSIGN(PageResourceDataUse);
+};
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_RESOURCE_DATA_USE_H_
diff --git a/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc
new file mode 100644
index 00000000000..04628c0c0e3
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc
@@ -0,0 +1,276 @@
+// 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 "components/page_load_metrics/renderer/page_timing_metrics_sender.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "components/page_load_metrics/common/page_load_metrics_constants.h"
+#include "components/page_load_metrics/renderer/page_timing_sender.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
+
+namespace page_load_metrics {
+
+namespace {
+const int kInitialTimerDelayMillis = 50;
+const base::Feature kPageLoadMetricsTimerDelayFeature{
+ "PageLoadMetricsTimerDelay", base::FEATURE_DISABLED_BY_DEFAULT};
+} // namespace
+
+PageTimingMetricsSender::PageTimingMetricsSender(
+ std::unique_ptr<PageTimingSender> sender,
+ std::unique_ptr<base::OneShotTimer> timer,
+ mojom::PageLoadTimingPtr initial_timing,
+ std::unique_ptr<PageResourceDataUse> initial_request)
+ : sender_(std::move(sender)),
+ timer_(std::move(timer)),
+ last_timing_(std::move(initial_timing)),
+ last_cpu_timing_(mojom::CpuTiming::New()),
+ metadata_(mojom::PageLoadMetadata::New()),
+ new_features_(mojom::PageLoadFeatures::New()),
+ render_data_(),
+ new_deferred_resource_data_(mojom::DeferredResourceCounts::New()),
+ buffer_timer_delay_ms_(kBufferTimerDelayMillis) {
+ page_resource_data_use_.emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(initial_request->resource_id()),
+ std::forward_as_tuple(std::move(initial_request)));
+ buffer_timer_delay_ms_ = base::GetFieldTrialParamByFeatureAsInt(
+ kPageLoadMetricsTimerDelayFeature, "BufferTimerDelayMillis",
+ kBufferTimerDelayMillis /* default value */);
+ if (!IsEmpty(*last_timing_)) {
+ EnsureSendTimer();
+ }
+}
+
+// On destruction, we want to send any data we have if we have a timer
+// currently running (and thus are talking to a browser process)
+PageTimingMetricsSender::~PageTimingMetricsSender() {
+ if (timer_->IsRunning()) {
+ timer_->Stop();
+ SendNow();
+ }
+}
+
+void PageTimingMetricsSender::DidObserveLoadingBehavior(
+ blink::WebLoadingBehaviorFlag behavior) {
+ if (behavior & metadata_->behavior_flags) {
+ return;
+ }
+ metadata_->behavior_flags |= behavior;
+ EnsureSendTimer();
+}
+
+void PageTimingMetricsSender::DidObserveNewFeatureUsage(
+ blink::mojom::WebFeature feature) {
+ size_t feature_id = static_cast<size_t>(feature);
+ if (features_sent_.test(feature_id)) {
+ return;
+ }
+ features_sent_.set(feature_id);
+ new_features_->features.push_back(feature);
+ EnsureSendTimer();
+}
+
+void PageTimingMetricsSender::DidObserveNewCssPropertyUsage(
+ blink::mojom::CSSSampleId css_property,
+ bool is_animated) {
+ size_t css_property_id = static_cast<size_t>(css_property);
+ if (is_animated && !animated_css_properties_sent_.test(css_property_id)) {
+ animated_css_properties_sent_.set(css_property_id);
+ new_features_->animated_css_properties.push_back(css_property);
+ EnsureSendTimer();
+ } else if (!is_animated && !css_properties_sent_.test(css_property_id)) {
+ css_properties_sent_.set(css_property_id);
+ new_features_->css_properties.push_back(css_property);
+ EnsureSendTimer();
+ }
+}
+
+void PageTimingMetricsSender::DidObserveLayoutShift(
+ double score,
+ bool after_input_or_scroll) {
+ DCHECK(score > 0);
+ render_data_.layout_shift_delta += score;
+ if (!after_input_or_scroll)
+ render_data_.layout_shift_delta_before_input_or_scroll += score;
+ EnsureSendTimer();
+}
+
+void PageTimingMetricsSender::DidObserveLazyLoadBehavior(
+ blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) {
+ switch (lazy_load_behavior) {
+ case blink::WebLocalFrameClient::LazyLoadBehavior::kDeferredFrame:
+ ++new_deferred_resource_data_->deferred_frames;
+ break;
+ case blink::WebLocalFrameClient::LazyLoadBehavior::kDeferredImage:
+ ++new_deferred_resource_data_->deferred_images;
+ break;
+ case blink::WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedFrame:
+ ++new_deferred_resource_data_->frames_loaded_after_deferral;
+ break;
+ case blink::WebLocalFrameClient::LazyLoadBehavior::kLazyLoadedImage:
+ ++new_deferred_resource_data_->images_loaded_after_deferral;
+ break;
+ }
+}
+
+void PageTimingMetricsSender::DidStartResponse(
+ const GURL& response_url,
+ int resource_id,
+ const network::ResourceResponseHead& response_head,
+ content::ResourceType resource_type,
+ content::PreviewsState previews_state) {
+ DCHECK(!base::Contains(page_resource_data_use_, resource_id));
+
+ auto resource_it = page_resource_data_use_.emplace(
+ std::piecewise_construct, std::forward_as_tuple(resource_id),
+ std::forward_as_tuple(std::make_unique<PageResourceDataUse>()));
+ resource_it.first->second->DidStartResponse(
+ response_url, resource_id, response_head, resource_type, previews_state);
+}
+
+void PageTimingMetricsSender::DidReceiveTransferSizeUpdate(
+ int resource_id,
+ int received_data_length) {
+ // Transfer size updates are called in a throttled manner.
+ auto resource_it = page_resource_data_use_.find(resource_id);
+
+ // It is possible that resources are not in the map, if response headers were
+ // not received or for failed/cancelled resources.
+ if (resource_it == page_resource_data_use_.end()) {
+ return;
+ }
+
+ resource_it->second->DidReceiveTransferSizeUpdate(received_data_length);
+ modified_resources_.insert(resource_it->second.get());
+ EnsureSendTimer();
+}
+
+void PageTimingMetricsSender::DidCompleteResponse(
+ int resource_id,
+ const network::URLLoaderCompletionStatus& status) {
+ auto resource_it = page_resource_data_use_.find(resource_id);
+
+ // It is possible that resources are not in the map, if response headers were
+ // not received or for failed/cancelled resources. For data reduction proxy
+ // purposes treat these as having no savings.
+ if (resource_it == page_resource_data_use_.end()) {
+ auto new_resource_it = page_resource_data_use_.emplace(
+ std::piecewise_construct, std::forward_as_tuple(resource_id),
+ std::forward_as_tuple(std::make_unique<PageResourceDataUse>()));
+ resource_it = new_resource_it.first;
+ }
+
+ resource_it->second->DidCompleteResponse(status);
+ EnsureSendTimer();
+ modified_resources_.insert(resource_it->second.get());
+}
+
+void PageTimingMetricsSender::DidCancelResponse(int resource_id) {
+ auto resource_it = page_resource_data_use_.find(resource_id);
+ if (resource_it == page_resource_data_use_.end()) {
+ return;
+ }
+ resource_it->second->DidCancelResponse();
+}
+
+void PageTimingMetricsSender::DidLoadResourceFromMemoryCache(
+ const GURL& response_url,
+ int request_id,
+ int64_t encoded_body_length,
+ const std::string& mime_type) {
+ // In general, we should not observe the same resource being loaded twice in
+ // the frame. This is possible due to an existing workaround in
+ // ResourceFetcher::EmulateLoadStartedForInspector(). In this case, ignore
+ // multiple resources being loaded in the document, as memory cache resources
+ // are only reported once per context by design in all other cases.
+ if (base::Contains(page_resource_data_use_, request_id))
+ return;
+
+ auto resource_it = page_resource_data_use_.emplace(
+ std::piecewise_construct, std::forward_as_tuple(request_id),
+ std::forward_as_tuple(std::make_unique<PageResourceDataUse>()));
+ resource_it.first->second->DidLoadFromMemoryCache(
+ response_url, request_id, encoded_body_length, mime_type);
+ modified_resources_.insert(resource_it.first->second.get());
+}
+
+void PageTimingMetricsSender::UpdateResourceMetadata(
+ int resource_id,
+ bool reported_as_ad_resource,
+ bool is_main_frame_resource) {
+ auto it = page_resource_data_use_.find(resource_id);
+ if (it == page_resource_data_use_.end())
+ return;
+ // This can get called multiple times for resources, and this
+ // flag will only be true once.
+ if (reported_as_ad_resource)
+ it->second->SetReportedAsAdResource(reported_as_ad_resource);
+ it->second->SetIsMainFrameResource(is_main_frame_resource);
+}
+
+void PageTimingMetricsSender::Send(mojom::PageLoadTimingPtr timing) {
+ if (last_timing_->Equals(*timing)) {
+ return;
+ }
+
+ // We want to make sure that each PageTimingMetricsSender is associated
+ // with a distinct page navigation. Because we reset the object on commit,
+ // we can trash last_timing_ on a provisional load before SendNow() fires.
+ if (!last_timing_->navigation_start.is_null() &&
+ last_timing_->navigation_start != timing->navigation_start) {
+ return;
+ }
+
+ last_timing_ = std::move(timing);
+ EnsureSendTimer();
+}
+
+void PageTimingMetricsSender::UpdateCpuTiming(base::TimeDelta task_time) {
+ last_cpu_timing_->task_time += task_time;
+ EnsureSendTimer();
+}
+
+void PageTimingMetricsSender::EnsureSendTimer() {
+ if (!timer_->IsRunning()) {
+ // Send the first IPC eagerly to make sure the receiving side knows we're
+ // sending metrics as soon as possible.
+ int delay_ms =
+ have_sent_ipc_ ? buffer_timer_delay_ms_ : kInitialTimerDelayMillis;
+ timer_->Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
+ base::Bind(&PageTimingMetricsSender::SendNow, base::Unretained(this)));
+ }
+}
+
+void PageTimingMetricsSender::SendNow() {
+ have_sent_ipc_ = true;
+ std::vector<mojom::ResourceDataUpdatePtr> resources;
+ for (auto* resource : modified_resources_) {
+ resources.push_back(resource->GetResourceDataUpdate());
+ if (resource->IsFinishedLoading()) {
+ page_resource_data_use_.erase(resource->resource_id());
+ }
+ }
+ sender_->SendTiming(last_timing_, metadata_, std::move(new_features_),
+ std::move(resources), render_data_, last_cpu_timing_,
+ std::move(new_deferred_resource_data_));
+ new_deferred_resource_data_ = mojom::DeferredResourceCounts::New();
+ new_features_ = mojom::PageLoadFeatures::New();
+ last_cpu_timing_->task_time = base::TimeDelta();
+ modified_resources_.clear();
+ render_data_.layout_shift_delta = 0;
+ render_data_.layout_shift_delta_before_input_or_scroll = 0;
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h
new file mode 100644
index 00000000000..65f30097182
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h
@@ -0,0 +1,130 @@
+// 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 COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_METRICS_SENDER_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_METRICS_SENDER_H_
+
+#include <bitset>
+#include <memory>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/small_map.h"
+#include "base/macros.h"
+#include "components/page_load_metrics/common/page_load_timing.h"
+#include "components/page_load_metrics/renderer/page_resource_data_use.h"
+#include "content/public/common/previews_state.h"
+#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-shared.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
+#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+
+class GURL;
+
+namespace base {
+class OneShotTimer;
+} // namespace base
+
+namespace network {
+struct ResourceResponseHead;
+struct URLLoaderCompletionStatus;
+} // namespace network
+
+namespace page_load_metrics {
+
+class PageTimingSender;
+
+// PageTimingMetricsSender is responsible for sending page load timing metrics
+// over IPC. PageTimingMetricsSender may coalesce sent IPCs in order to
+// minimize IPC contention.
+class PageTimingMetricsSender {
+ public:
+ PageTimingMetricsSender(std::unique_ptr<PageTimingSender> sender,
+ std::unique_ptr<base::OneShotTimer> timer,
+ mojom::PageLoadTimingPtr initial_timing,
+ std::unique_ptr<PageResourceDataUse> initial_request);
+ ~PageTimingMetricsSender();
+
+ void DidObserveLoadingBehavior(blink::WebLoadingBehaviorFlag behavior);
+ void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature);
+ void DidObserveNewCssPropertyUsage(blink::mojom::CSSSampleId css_property,
+ bool is_animated);
+ void DidObserveLayoutShift(double score, bool after_input_or_scroll);
+ void DidObserveLazyLoadBehavior(
+ blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior);
+
+ void DidStartResponse(const GURL& response_url,
+ int resource_id,
+ const network::ResourceResponseHead& response_head,
+ content::ResourceType resource_type,
+ content::PreviewsState previews_state);
+ void DidReceiveTransferSizeUpdate(int resource_id, int received_data_length);
+ void DidCompleteResponse(int resource_id,
+ const network::URLLoaderCompletionStatus& status);
+ void DidCancelResponse(int resource_id);
+ void DidLoadResourceFromMemoryCache(const GURL& response_url,
+ int request_id,
+ int64_t encoded_body_length,
+ const std::string& mime_type);
+
+ // TODO(ericrobinson): There should probably be a name change here:
+ // * Send: Sends immediately, functions as SendNow.
+ // * QueueSend: Queues the send by starting the timer, functions as Send.
+ void Send(mojom::PageLoadTimingPtr timing);
+ // Updates the PageLoadMetrics::CpuTiming data and starts the Send timer.
+ void UpdateCpuTiming(base::TimeDelta task_time);
+
+ void UpdateResourceMetadata(int resource_id,
+ bool is_ad_resource,
+ bool is_main_frame_resource);
+
+ protected:
+ base::OneShotTimer* timer() const { return timer_.get(); }
+
+ private:
+ void EnsureSendTimer();
+ void SendNow();
+ void ClearNewFeatures();
+
+ std::unique_ptr<PageTimingSender> sender_;
+ std::unique_ptr<base::OneShotTimer> timer_;
+ mojom::PageLoadTimingPtr last_timing_;
+ mojom::CpuTimingPtr last_cpu_timing_;
+
+ // The the sender keep track of metadata as it comes in, because the sender is
+ // scoped to a single committed load.
+ mojom::PageLoadMetadataPtr metadata_;
+ // A list of newly observed features during page load, to be sent to the
+ // browser.
+ mojom::PageLoadFeaturesPtr new_features_;
+ mojom::FrameRenderDataUpdate render_data_;
+ mojom::DeferredResourceCountsPtr new_deferred_resource_data_;
+
+ std::bitset<static_cast<size_t>(blink::mojom::WebFeature::kNumberOfFeatures)>
+ features_sent_;
+ std::bitset<static_cast<size_t>(blink::mojom::CSSSampleId::kMaxValue) + 1>
+ css_properties_sent_;
+ std::bitset<static_cast<size_t>(blink::mojom::CSSSampleId::kMaxValue) + 1>
+ animated_css_properties_sent_;
+
+ bool have_sent_ipc_ = false;
+
+ // The page's resources that are currently loading, or were completed after
+ // the last timing update.
+ base::small_map<std::map<int, std::unique_ptr<PageResourceDataUse>>, 16>
+ page_resource_data_use_;
+
+ // Set of all resources that have completed or received a transfer
+ // size update since the last timimg update.
+ base::flat_set<PageResourceDataUse*> modified_resources_;
+
+ // Field trial for alternating page timing metrics sender buffer timer delay.
+ // https://crbug.com/847269.
+ int buffer_timer_delay_ms_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageTimingMetricsSender);
+};
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_METRICS_SENDER_H_
diff --git a/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc
new file mode 100644
index 00000000000..224b6ca6d2e
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc
@@ -0,0 +1,378 @@
+// 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 "components/page_load_metrics/renderer/page_timing_metrics_sender.h"
+
+#include "base/time/time.h"
+#include "base/timer/mock_timer.h"
+#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
+#include "components/page_load_metrics/renderer/fake_page_timing_sender.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using CSSSampleId = blink::mojom::CSSSampleId;
+
+namespace page_load_metrics {
+
+// Thin wrapper around PageTimingMetricsSender that provides access to the
+// MockOneShotTimer instance.
+class TestPageTimingMetricsSender : public PageTimingMetricsSender {
+ public:
+ explicit TestPageTimingMetricsSender(
+ std::unique_ptr<PageTimingSender> page_timing_sender,
+ mojom::PageLoadTimingPtr initial_timing)
+ : PageTimingMetricsSender(std::move(page_timing_sender),
+ std::make_unique<base::MockOneShotTimer>(),
+ std::move(initial_timing),
+ std::make_unique<PageResourceDataUse>()) {}
+
+ base::MockOneShotTimer* mock_timer() const {
+ return static_cast<base::MockOneShotTimer*>(timer());
+ }
+};
+
+class PageTimingMetricsSenderTest : public testing::Test {
+ public:
+ PageTimingMetricsSenderTest()
+ : metrics_sender_(new TestPageTimingMetricsSender(
+ std::make_unique<FakePageTimingSender>(&validator_),
+ mojom::PageLoadTiming::New())) {}
+
+ protected:
+ FakePageTimingSender::PageTimingValidator validator_;
+ std::unique_ptr<TestPageTimingMetricsSender> metrics_sender_;
+};
+
+TEST_F(PageTimingMetricsSenderTest, Basic) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(2);
+
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ timing.document_timing->first_layout = first_layout;
+
+ metrics_sender_->Send(timing.Clone());
+
+ // Firing the timer should trigger sending of an SendTiming call.
+ validator_.ExpectPageLoadTiming(timing);
+ ASSERT_TRUE(metrics_sender_->mock_timer()->IsRunning());
+ metrics_sender_->mock_timer()->Fire();
+ EXPECT_FALSE(metrics_sender_->mock_timer()->IsRunning());
+
+ // At this point, we should have triggered the send of the SendTiming call.
+ validator_.VerifyExpectedTimings();
+
+ // Attempt to send the same timing instance again. The send should be
+ // suppressed, since the timing instance hasn't changed since the last send.
+ metrics_sender_->Send(timing.Clone());
+ EXPECT_FALSE(metrics_sender_->mock_timer()->IsRunning());
+}
+
+TEST_F(PageTimingMetricsSenderTest, CoalesceMultipleTimings) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(2);
+ base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(4);
+
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ timing.document_timing->first_layout = first_layout;
+
+ metrics_sender_->Send(timing.Clone());
+ ASSERT_TRUE(metrics_sender_->mock_timer()->IsRunning());
+
+ // Send an updated PageLoadTiming before the timer has fired. When the timer
+ // fires, the updated PageLoadTiming should be sent.
+ timing.document_timing->load_event_start = load_event;
+ metrics_sender_->Send(timing.Clone());
+
+ // Firing the timer should trigger sending of the SendTiming call with
+ // the most recently provided PageLoadTiming instance.
+ validator_.ExpectPageLoadTiming(timing);
+ metrics_sender_->mock_timer()->Fire();
+ EXPECT_FALSE(metrics_sender_->mock_timer()->IsRunning());
+}
+
+TEST_F(PageTimingMetricsSenderTest, MultipleTimings) {
+ base::Time nav_start = base::Time::FromDoubleT(10);
+ base::TimeDelta first_layout = base::TimeDelta::FromMillisecondsD(2);
+ base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(4);
+
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = nav_start;
+ timing.document_timing->first_layout = first_layout;
+
+ metrics_sender_->Send(timing.Clone());
+ ASSERT_TRUE(metrics_sender_->mock_timer()->IsRunning());
+ validator_.ExpectPageLoadTiming(timing);
+ metrics_sender_->mock_timer()->Fire();
+ EXPECT_FALSE(metrics_sender_->mock_timer()->IsRunning());
+ validator_.VerifyExpectedTimings();
+
+ // Send an updated PageLoadTiming after the timer for the first send request
+ // has fired, and verify that a second timing is sent.
+ timing.document_timing->load_event_start = load_event;
+ metrics_sender_->Send(timing.Clone());
+ ASSERT_TRUE(metrics_sender_->mock_timer()->IsRunning());
+ validator_.ExpectPageLoadTiming(timing);
+ metrics_sender_->mock_timer()->Fire();
+ EXPECT_FALSE(metrics_sender_->mock_timer()->IsRunning());
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendTimingOnDestructor) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ timing.navigation_start = base::Time::FromDoubleT(10);
+ timing.document_timing->first_layout = base::TimeDelta::FromMilliseconds(10);
+
+ // This test wants to verify behavior in the PageTimingMetricsSender
+ // destructor. The EXPECT_CALL will be satisfied when the |metrics_sender_|
+ // is destroyed below.
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ ASSERT_TRUE(metrics_sender_->mock_timer()->IsRunning());
+
+ // Destroy |metrics_sender_|, in order to force its destructor to run.
+ metrics_sender_.reset();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendSingleFeature) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ blink::mojom::WebFeature feature = blink::mojom::WebFeature::kFetch;
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe a single feature, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature);
+ validator_.UpdateExpectPageLoadFeatures(feature);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendMultipleFeatures) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ blink::mojom::WebFeature feature_0 = blink::mojom::WebFeature::kFetch;
+ blink::mojom::WebFeature feature_1 =
+ blink::mojom::WebFeature::kFetchBodyStream;
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe the first feature, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_0);
+ validator_.UpdateExpectPageLoadFeatures(feature_0);
+ // Observe the second feature, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_1);
+ validator_.UpdateExpectPageLoadFeatures(feature_1);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendDuplicatedFeatures) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ blink::mojom::WebFeature feature = blink::mojom::WebFeature::kFetch;
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ metrics_sender_->DidObserveNewFeatureUsage(feature);
+ validator_.UpdateExpectPageLoadFeatures(feature);
+ // Observe a duplicated feature usage, without updating expected features sent
+ // across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendMultipleFeaturesTwice) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+ blink::mojom::WebFeature feature_0 = blink::mojom::WebFeature::kFetch;
+ blink::mojom::WebFeature feature_1 =
+ blink::mojom::WebFeature::kFetchBodyStream;
+ blink::mojom::WebFeature feature_2 = blink::mojom::WebFeature::kWindowFind;
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe the first feature, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_0);
+ validator_.UpdateExpectPageLoadFeatures(feature_0);
+ // Observe the second feature, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_1);
+ validator_.UpdateExpectPageLoadFeatures(feature_1);
+ // Observe a duplicated feature usage, without updating expected features sent
+ // across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_0);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+
+ base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(4);
+ // Send an updated PageLoadTiming after the timer for the first send request
+ // has fired, and verify that a second list of features is sent.
+ timing.document_timing->load_event_start = load_event;
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe duplicated feature usage, without updating expected features sent
+ // across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_0);
+ metrics_sender_->DidObserveNewFeatureUsage(feature_1);
+ // Observe an additional feature usage, update expected features sent across
+ // IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_2);
+ validator_.UpdateExpectPageLoadFeatures(feature_2);
+ // Fire the timer to trigger another sending of features via the second
+ // SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendSingleCssProperty) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe a single CSS property, update expected CSS properties sent across
+ // IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kDirection,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kDirection);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedCssProperties();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendCssPropertiesInRange) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe the smallest CSS property ID.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kColor,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kColor);
+ // Observe the largest CSS property ID.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kMaxValue,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kMaxValue);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedCssProperties();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendMultipleCssProperties) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe the first CSS property, update expected CSS properties sent across
+ // IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kDirection,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kDirection);
+ // Observe the second CSS property, update expected CSS properties sent across
+ // IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kBorderLeftWidth,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kBorderLeftWidth);
+ // Fire the timer to trigger sending of CSS properties via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedCssProperties();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendDuplicatedCssProperties) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kDirection,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kDirection);
+ // Observe a duplicated CSS property usage, without updating expected CSS
+ // properties sent across IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kDirection,
+ false /*is_animated*/);
+ // Fire the timer to trigger sending of CSS properties via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedCssProperties();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendMultipleCssPropertiesTwice) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe the first CSS property, update expected CSS properties sent across
+ // IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kColor,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kColor);
+ // Observe the second CSS property, update expected CSS properties sent across
+ // IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kFont,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kFont);
+ // Observe a duplicated usage, without updating expected CSS properties sent
+ // across IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kColor,
+ false /*is_animated*/);
+ // Fire the timer to trigger sending of features via an SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+
+ base::TimeDelta load_event = base::TimeDelta::FromMillisecondsD(4);
+ // Send an updated PageLoadTiming after the timer for the first send request
+ // has fired, and verify that a second list of CSS properties is sent.
+ timing.document_timing->load_event_start = load_event;
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+ // Observe duplicated usage, without updating expected features sent across
+ // IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kDirection,
+ false /*is_animated*/);
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kColor,
+ false /*is_animated*/);
+ // Observe an additional usage, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewCssPropertyUsage(CSSSampleId::kDirection,
+ false /*is_animated*/);
+ validator_.UpdateExpectPageLoadCssProperties(CSSSampleId::kDirection);
+ // Fire the timer to trigger another sending of features via the second
+ // SendTiming call.
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedFeatures();
+}
+
+TEST_F(PageTimingMetricsSenderTest, SendPageRenderData) {
+ mojom::PageLoadTiming timing;
+ InitPageLoadTimingForTest(&timing);
+
+ // We need to send the PageLoadTiming here even though it is not really
+ // related to the PageRenderData. This is because metrics_sender_ sends
+ // its last_timing_ when the mock timer fires, causing the validator to
+ // look for a matching expectation.
+ metrics_sender_->Send(timing.Clone());
+ validator_.ExpectPageLoadTiming(timing);
+
+ metrics_sender_->DidObserveLayoutShift(0.5, false);
+ metrics_sender_->DidObserveLayoutShift(0.5, false);
+ metrics_sender_->DidObserveLayoutShift(0.5, true);
+
+ mojom::FrameRenderDataUpdate render_data(1.5, 1.0);
+ validator_.UpdateExpectFrameRenderDataUpdate(render_data);
+
+ metrics_sender_->mock_timer()->Fire();
+ validator_.VerifyExpectedRenderData();
+}
+
+} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/renderer/page_timing_sender.h b/chromium/components/page_load_metrics/renderer/page_timing_sender.h
new file mode 100644
index 00000000000..597e457f6c2
--- /dev/null
+++ b/chromium/components/page_load_metrics/renderer/page_timing_sender.h
@@ -0,0 +1,29 @@
+// 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 COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_SENDER_H_
+#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_SENDER_H_
+
+#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
+
+namespace page_load_metrics {
+
+// PageTimingSender is an interface that is responsible for sending page load
+// timing through IPC.
+class PageTimingSender {
+ public:
+ virtual ~PageTimingSender() {}
+ virtual void SendTiming(
+ const mojom::PageLoadTimingPtr& timing,
+ const mojom::PageLoadMetadataPtr& metadata,
+ mojom::PageLoadFeaturesPtr new_features,
+ std::vector<mojom::ResourceDataUpdatePtr> resources,
+ const mojom::FrameRenderDataUpdate& render_data,
+ const mojom::CpuTimingPtr& cpu_timing,
+ mojom::DeferredResourceCountsPtr new_deferred_resource_data) = 0;
+};
+
+} // namespace page_load_metrics
+
+#endif // COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_SENDER_H_
diff --git a/chromium/components/password_manager/OWNERS b/chromium/components/password_manager/OWNERS
index 7746c0f4fdf..55e5a0549e5 100644
--- a/chromium/components/password_manager/OWNERS
+++ b/chromium/components/password_manager/OWNERS
@@ -4,3 +4,4 @@ kolos@chromium.org
vasilii@chromium.org
# COMPONENT: UI>Browser>Passwords
+# TEAM: chromium-dev@chromium.org
diff --git a/chromium/components/password_manager/README.md b/chromium/components/password_manager/README.md
index 3bbe4aae119..24a37729c55 100644
--- a/chromium/components/password_manager/README.md
+++ b/chromium/components/password_manager/README.md
@@ -97,9 +97,6 @@ Here is a summary of the core responsibilities of the classes and interfaces:
to offer password saving or updating existing credentials after a successful
form submission.
- Note: At the moment [`NewPasswordFormManager`] is the relevant class to look
- at. This will soon replace the old [`PasswordFormManager`] implementation.
-
* `*::PasswordManagerDriver` (1 per frame)
The `*::PasswordManagerDriver` is the browser-side communication end-point for
@@ -155,7 +152,7 @@ Here is a summary of the core responsibilities of the classes and interfaces:
[`mojom::PasswordAutofillAgent`]: https://cs.chromium.org/search?q=file:autofill_agent.mojom+"interface+PasswordAutofillAgent"
[`mojom::PasswordGenerationAgent`]: https://cs.chromium.org/search?q=file:autofill_agent.mojom+"interface+PasswordGenerationAgent"
[`mojom::PasswordManagerDriver`]: https://cs.chromium.org/search?q=file:autofill_driver.mojom+"interface+PasswordManagerDriver"
-[`NewPasswordFormManager`]: https://cs.chromium.org/search?q=file:/new_password_form_manager.h$
+[`PasswordFormManager`]: https://cs.chromium.org/search?q=file:/password_form_manager.h$
[`password_manager::PasswordManagerDriver`]: https://cs.chromium.org/search?q=file:/password_manager_driver.h$
[`password_manager::PasswordManagerDriver`]: https://cs.chromium.org/search?q=file:/password_manager_driver.h$
[`PasswordAutofillAgent`]: https://cs.chromium.org/search?q=file:/password_autofill_agent.h$
diff --git a/chromium/components/password_manager/content/browser/BUILD.gn b/chromium/components/password_manager/content/browser/BUILD.gn
index 92c8c8b6942..2a6c0ee268b 100644
--- a/chromium/components/password_manager/content/browser/BUILD.gn
+++ b/chromium/components/password_manager/content/browser/BUILD.gn
@@ -50,6 +50,7 @@ source_set("unit_tests") {
"//components/autofill/core/browser:test_support",
"//components/password_manager/core/browser:test_support",
"//components/prefs:test_support",
+ "//components/safe_browsing:buildflags",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/password_manager/content/browser/DEPS b/chromium/components/password_manager/content/browser/DEPS
index 5227e412bdd..47c9c9109ac 100644
--- a/chromium/components/password_manager/content/browser/DEPS
+++ b/chromium/components/password_manager/content/browser/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+components/autofill/content/common",
"+components/keyed_service/content",
"+components/keyed_service/core",
+ "+components/safe_browsing/buildflags.h",
"+content/public/browser",
"+net",
"+services/service_manager/public/cpp",
diff --git a/chromium/components/password_manager/content/browser/content_password_manager_driver.cc b/chromium/components/password_manager/content/browser/content_password_manager_driver.cc
index d4a27653de8..5e2ad8e40c2 100644
--- a/chromium/components/password_manager/content/browser/content_password_manager_driver.cc
+++ b/chromium/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -18,6 +18,7 @@
#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
+#include "components/safe_browsing/buildflags.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
@@ -114,6 +115,8 @@ void ContentPasswordManagerDriver::FormEligibleForGenerationFound(
void ContentPasswordManagerDriver::AutofillDataReceived(
const autofill::FormsPredictionsMap& predictions) {
+ // TODO(https://crbug.com/949519): Remove this method, MOJO calls and
+ // processing server predictions in the renderer.
GetPasswordAutofillAgent()->AutofillUsernameAndPasswordDataReceived(
predictions);
}
@@ -276,16 +279,6 @@ void ContentPasswordManagerDriver::SameDocumentNavigation(
LogSiteIsolationMetricsForSubmittedForm(render_frame_host_);
}
-void ContentPasswordManagerDriver::ShowPasswordSuggestions(
- base::i18n::TextDirection text_direction,
- const base::string16& typed_username,
- int options,
- const gfx::RectF& bounds) {
- GetPasswordAutofillManager()->OnShowPasswordSuggestions(
- text_direction, typed_username, options,
- TransformToRootCoordinates(render_frame_host_, bounds));
-}
-
void ContentPasswordManagerDriver::RecordSavePasswordProgress(
const std::string& log) {
client_->GetLogManager()->LogTextMessage(log);
@@ -303,10 +296,24 @@ void ContentPasswordManagerDriver::UserModifiedNonPasswordField(
value);
}
+void ContentPasswordManagerDriver::ShowPasswordSuggestions(
+ base::i18n::TextDirection text_direction,
+ const base::string16& typed_username,
+ int options,
+ const gfx::RectF& bounds) {
+ GetPasswordAutofillManager()->OnShowPasswordSuggestions(
+ text_direction, typed_username, options,
+ TransformToRootCoordinates(render_frame_host_, bounds));
+}
+
+void ContentPasswordManagerDriver::ShowTouchToFill() {
+ client_->ShowTouchToFill(this);
+}
+
void ContentPasswordManagerDriver::CheckSafeBrowsingReputation(
const GURL& form_action,
const GURL& frame_url) {
-#if defined(FULL_SAFE_BROWSING)
+#if defined(ON_FOCUS_PING_ENABLED)
client_->CheckSafeBrowsingReputation(form_action, frame_url);
#endif
}
diff --git a/chromium/components/password_manager/content/browser/content_password_manager_driver.h b/chromium/components/password_manager/content/browser/content_password_manager_driver.h
index d066de5d616..623ae2e6fe9 100644
--- a/chromium/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/chromium/components/password_manager/content/browser/content_password_manager_driver.h
@@ -107,14 +107,15 @@ class ContentPasswordManagerDriver
void HideManualFallbackForSaving() override;
void SameDocumentNavigation(
const autofill::PasswordForm& password_form) override;
- void ShowPasswordSuggestions(base::i18n::TextDirection text_direction,
- const base::string16& typed_username,
- int options,
- const gfx::RectF& bounds) override;
void RecordSavePasswordProgress(const std::string& log) override;
void UserModifiedPasswordField() override;
void UserModifiedNonPasswordField(uint32_t renderer_id,
const base::string16& value) override;
+ void ShowPasswordSuggestions(base::i18n::TextDirection text_direction,
+ const base::string16& typed_username,
+ int options,
+ const gfx::RectF& bounds) override;
+ void ShowTouchToFill() override;
void CheckSafeBrowsingReputation(const GURL& form_action,
const GURL& frame_url) override;
void FocusedInputChanged(
diff --git a/chromium/components/password_manager/content/browser/content_password_manager_driver_unittest.cc b/chromium/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
index 21088bd2a32..293cdf3bef3 100644
--- a/chromium/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
+++ b/chromium/components/password_manager/content/browser/content_password_manager_driver_unittest.cc
@@ -15,6 +15,7 @@
#include "components/autofill/core/browser/logging/stub_log_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
+#include "components/safe_browsing/buildflags.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.h"
@@ -47,7 +48,7 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
~MockPasswordManagerClient() override = default;
MOCK_CONST_METHOD0(GetLogManager, const autofill::LogManager*());
-#if defined(SAFE_BROWSING_DB_LOCAL)
+#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
MOCK_METHOD2(CheckSafeBrowsingReputation, void(const GURL&, const GURL&));
#endif
diff --git a/chromium/components/password_manager/content/browser/password_manager_log_router_factory_unittest.cc b/chromium/components/password_manager/content/browser/password_manager_log_router_factory_unittest.cc
index 474a136151c..eae9faafab7 100644
--- a/chromium/components/password_manager/content/browser/password_manager_log_router_factory_unittest.cc
+++ b/chromium/components/password_manager/content/browser/password_manager_log_router_factory_unittest.cc
@@ -7,8 +7,8 @@
#include "components/autofill/core/browser/logging/log_receiver.h"
#include "components/autofill/core/browser/logging/log_router.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -30,7 +30,7 @@ class MockLogReceiver : public autofill::LogReceiver {
class PasswordManagerLogRouterFactoryTest : public testing::Test {
public:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
void SetUp() override {
diff --git a/chromium/components/password_manager/content/common/credential_manager.typemap b/chromium/components/password_manager/content/common/credential_manager.typemap
index d0d170a4362..cdd69b24331 100644
--- a/chromium/components/password_manager/content/common/credential_manager.typemap
+++ b/chromium/components/password_manager/content/common/credential_manager.typemap
@@ -15,8 +15,8 @@ deps = [
]
type_mappings = [
- "blink.mojom.CredentialType=password_manager::CredentialType",
- "blink.mojom.CredentialMediationRequirement=password_manager::CredentialMediationRequirement",
- "blink.mojom.CredentialInfo=password_manager::CredentialInfo",
- "blink.mojom.CredentialManagerError=password_manager::CredentialManagerError",
+ "blink.mojom.CredentialType=::password_manager::CredentialType",
+ "blink.mojom.CredentialMediationRequirement=::password_manager::CredentialMediationRequirement",
+ "blink.mojom.CredentialInfo=::password_manager::CredentialInfo",
+ "blink.mojom.CredentialManagerError=::password_manager::CredentialManagerError",
]
diff --git a/chromium/components/password_manager/core/browser/BUILD.gn b/chromium/components/password_manager/core/browser/BUILD.gn
index 1f2697f01ef..fbe421011e6 100644
--- a/chromium/components/password_manager/core/browser/BUILD.gn
+++ b/chromium/components/password_manager/core/browser/BUILD.gn
@@ -12,10 +12,15 @@ if (is_android) {
# TODO(crbug.com/706392): Fix password reuse detection for Android.
password_reuse_detection_support = !is_android && !is_ios
+password_on_focus_ping_support = !is_ios
config("password_reuse_detection_config") {
+ defines = []
if (password_reuse_detection_support) {
- defines = [ "SYNC_PASSWORD_REUSE_DETECTION_ENABLED" ]
+ defines += [ "SYNC_PASSWORD_REUSE_DETECTION_ENABLED" ]
+ }
+ if (password_on_focus_ping_support) {
+ defines += [ "ON_FOCUS_PING_ENABLED" ]
}
}
@@ -98,8 +103,6 @@ jumbo_static_library("browser") {
"login_database_mac.cc",
"login_database_win.cc",
"manage_passwords_referrer.h",
- "new_password_form_manager.cc",
- "new_password_form_manager.h",
"origin_credential_store.cc",
"origin_credential_store.h",
"password_autofill_manager.cc",
@@ -133,6 +136,8 @@ jumbo_static_library("browser") {
"password_manager_metrics_recorder.h",
"password_manager_metrics_util.cc",
"password_manager_metrics_util.h",
+ "password_manager_onboarding.cc",
+ "password_manager_onboarding.h",
"password_manager_util.cc",
"password_manager_util.h",
"password_requirements_service.cc",
@@ -204,6 +209,7 @@ jumbo_static_library("browser") {
public_deps = [
"//base",
+ "//components/safe_browsing:buildflags",
"//components/sync",
]
deps = [
@@ -222,6 +228,7 @@ jumbo_static_library("browser") {
"//components/keyed_service/core",
"//components/os_crypt",
"//components/password_manager/core/browser/form_parsing",
+ "//components/password_manager/core/browser/leak_detection:leak_detection_interface_headers",
"//components/password_manager/core/common",
"//components/pref_registry",
"//components/prefs",
@@ -252,6 +259,12 @@ jumbo_static_library("browser") {
"hsts_query.h",
"http_credentials_cleaner.cc",
"http_credentials_cleaner.h",
+ "leak_detection_delegate.cc",
+ "leak_detection_delegate.h",
+ "leak_detection_delegate_helper.cc",
+ "leak_detection_delegate_helper.h",
+ "leak_detection_dialog_utils.cc",
+ "leak_detection_dialog_utils.h",
]
deps += [
"//components/password_manager/core/browser/leak_detection:leak_detection",
@@ -285,6 +298,8 @@ static_library("csv") {
"import/csv_field_parser.h",
"import/csv_password.cc",
"import/csv_password.h",
+ "import/csv_password_iterator.cc",
+ "import/csv_password_iterator.h",
]
deps = [
":affiliation",
@@ -298,6 +313,7 @@ source_set("csv_unittests") {
testonly = true
sources = [
"import/csv_field_parser_unittest.cc",
+ "import/csv_password_iterator_unittest.cc",
"import/csv_password_unittest.cc",
]
deps = [
@@ -394,6 +410,7 @@ jumbo_static_library("test_support") {
":browser",
":hash_password_manager",
"//components/autofill/core/browser:test_support",
+ "//components/safe_browsing:buildflags",
"//components/ukm",
"//services/network/public/cpp",
"//testing/gmock",
@@ -432,6 +449,8 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/password_manager/login_db_v22.sql",
"//components/test/data/password_manager/login_db_v23.sql",
"//components/test/data/password_manager/login_db_v24.sql",
+ "//components/test/data/password_manager/login_db_v24_broken.sql",
+ "//components/test/data/password_manager/login_db_v25.sql",
"//components/test/data/password_manager/login_db_v2_broken.sql",
"//components/test/data/password_manager/login_db_v3.sql",
"//components/test/data/password_manager/login_db_v3_broken.sql",
@@ -480,7 +499,6 @@ source_set("unit_tests") {
"import/password_csv_reader_unittest.cc",
"import/password_importer_unittest.cc",
"login_database_unittest.cc",
- "new_password_form_manager_unittest.cc",
"origin_credential_store_unittest.cc",
"password_autofill_manager_unittest.cc",
"password_bubble_experiment_unittest.cc",
@@ -492,6 +510,7 @@ source_set("unit_tests") {
"password_hash_data_unittest.cc",
"password_list_sorter_unittest.cc",
"password_manager_metrics_recorder_unittest.cc",
+ "password_manager_onboarding_unittest.cc",
"password_manager_unittest.cc",
"password_manager_util_unittest.cc",
"password_requirements_service_unittest.cc",
@@ -522,6 +541,8 @@ source_set("unit_tests") {
sources += [
"hsts_query_unittest.cc",
"http_credentials_cleaner_unittest.cc",
+ "leak_detection_delegate_helper_unittest.cc",
+ "leak_detection_delegate_unittest.cc",
]
}
if (password_reuse_detection_support) {
@@ -554,6 +575,7 @@ source_set("unit_tests") {
"//components/password_manager/core/browser:proto",
"//components/password_manager/core/browser/form_parsing:unit_tests",
"//components/password_manager/core/browser/form_parsing/fuzzer:unit_tests",
+ "//components/password_manager/core/browser/leak_detection:leak_detection_interface_headers",
"//components/password_manager/core/common",
"//components/prefs:test_support",
"//components/security_state/core",
@@ -584,6 +606,13 @@ source_set("unit_tests") {
"//components/safe_browsing/common:safe_browsing_prefs",
]
}
+
+ if (!is_ios) {
+ deps += [
+ "//components/password_manager/core/browser/leak_detection",
+ "//components/password_manager/core/browser/leak_detection:unit_tests",
+ ]
+ }
}
fuzzer_test("csv_reader_fuzzer") {
diff --git a/chromium/components/password_manager/core/browser/DEPS b/chromium/components/password_manager/core/browser/DEPS
index fa76a0da7f7..af644c229ee 100644
--- a/chromium/components/password_manager/core/browser/DEPS
+++ b/chromium/components/password_manager/core/browser/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+components/keyed_service/core",
"+components/pref_registry",
"+components/security_state",
+ "+components/safe_browsing/buildflags.h",
"+components/safe_browsing/common/safe_browsing_prefs.h",
"+components/safe_browsing/features.h",
"+components/sync/base",
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc
index e1ad3d411f3..aabba05cf71 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc
@@ -15,7 +15,7 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_mock_time_message_loop_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_service.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/test_password_store.h"
@@ -348,7 +348,7 @@ class AffiliatedMatchHelperTest : public testing::Test {
RunUntilIdle();
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedMockTimeMessageLoopTaskRunner mock_time_task_runner_;
std::vector<std::string> last_result_realms_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc
index 44f78d3fb54..339bf8f8540 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_backend_unittest.cc
@@ -12,7 +12,7 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/clock.h"
@@ -363,7 +363,7 @@ class AffiliationBackendTest : public testing::Test {
GetTestEquivalenceClassGamma());
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<base::TestMockTimeTaskRunner> backend_task_runner_;
scoped_refptr<base::TestSimpleTaskRunner> consumer_task_runner_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
index e430ff3f23d..8dba0afeca3 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetch_throttler_unittest.cc
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/numerics/safe_math.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
@@ -82,7 +82,7 @@ class AffiliationFetchThrottlerTest : public testing::Test {
network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
has_connectivity ? network::mojom::ConnectionType::CONNECTION_ETHERNET
: network::mojom::ConnectionType::CONNECTION_NONE);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// Runs the task runner until no tasks remain, and asserts that by this time,
@@ -127,7 +127,7 @@ class AffiliationFetchThrottlerTest : public testing::Test {
private:
// Needed because NetworkConnectionTracker uses base::ObserverList, which
// notifies observers on the sequence from which they have registered.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
MockAffiliationFetchThrottlerDelegate mock_delegate_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc
index c97b19fdf60..404fba42589 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc
@@ -113,7 +113,7 @@ void AffiliationFetcher::StartRequest() {
resource_request->url = BuildQueryURL();
resource_request->load_flags =
net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc
index 1caccd27ced..b86f51fb3ad 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/test/bind_test_util.h"
#include "base/test/null_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_api.pb.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -112,14 +112,14 @@ class AffiliationFetcherTest : public testing::Test {
test_url_loader_factory_.AddResponse(interception_url(), head, "", status);
}
- void WaitForResponse() { scoped_task_environment_.RunUntilIdle(); }
+ void WaitForResponse() { task_environment_.RunUntilIdle(); }
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory() {
return test_shared_loader_factory_;
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
std::string intercepted_body_;
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service_unittest.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service_unittest.cc
index 20f73f28d7e..36c337b3145 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service_unittest.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_service_unittest.cc
@@ -13,7 +13,7 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -70,7 +70,7 @@ class AffiliationServiceTest : public testing::Test {
return &fake_affiliation_api_;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
private:
// testing::Test:
@@ -129,7 +129,7 @@ TEST_F(AffiliationServiceTest, GetAffiliationsAndBranding) {
testing::Contains(testing::Field(
&Facet::uri, FacetURI::FromCanonicalSpec(kTestFacetURIAlpha1))));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_consumer());
// The second request should be (and can be) served from cache.
@@ -141,7 +141,7 @@ TEST_F(AffiliationServiceTest, GetAffiliationsAndBranding) {
ASSERT_FALSE(fake_affiliation_api()->HasPendingRequest());
mock_consumer()->ExpectSuccessWithResult(equivalence_class_alpha);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_consumer());
// The third request is also restricted to the cache, but cannot be served
@@ -154,7 +154,7 @@ TEST_F(AffiliationServiceTest, GetAffiliationsAndBranding) {
ASSERT_FALSE(fake_affiliation_api()->HasPendingRequest());
mock_consumer()->ExpectFailure();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_consumer());
}
@@ -169,7 +169,7 @@ TEST_F(AffiliationServiceTest, ShutdownWhileTasksArePosted) {
background_task_runner()->RunUntilIdle();
mock_consumer()->ExpectFailure();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_consumer());
}
diff --git a/chromium/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc b/chromium/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc
index 2f4a0725553..a94069ebeef 100644
--- a/chromium/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc
+++ b/chromium/components/password_manager/core/browser/blacklisted_credentials_cleaner_unittest.cc
@@ -6,7 +6,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/password_manager/core/browser/test_password_store.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
@@ -71,11 +71,11 @@ class BlacklistedCredentialsCleanerTest : public ::testing::Test {
~BlacklistedCredentialsCleanerTest() override {
store_->ShutdownOnUIThread();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::HistogramTester histogram_tester_;
const scoped_refptr<TestPasswordStore> store_ =
base::MakeRefCounted<TestPasswordStore>();
@@ -98,7 +98,7 @@ TEST_F(BlacklistedCredentialsCleanerTest, CleanerUpdatesPref) {
MockCredentialsCleanerObserver observer;
cleaner_.StartCleaning(&observer);
EXPECT_CALL(observer, CleaningCompleted);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(prefs_.GetBoolean(prefs::kBlacklistedCredentialsNormalized));
}
@@ -111,7 +111,7 @@ TEST_F(BlacklistedCredentialsCleanerTest, CleanerNormalizesData) {
MockCredentialsCleanerObserver observer;
cleaner_.StartCleaning(&observer);
EXPECT_CALL(observer, CleaningCompleted);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
TestPasswordStore::PasswordMap stored_passwords = store_->stored_passwords();
ASSERT_EQ(1u, stored_passwords.size());
@@ -133,7 +133,7 @@ TEST_F(BlacklistedCredentialsCleanerTest,
MockCredentialsCleanerObserver observer;
cleaner_.StartCleaning(&observer);
EXPECT_CALL(observer, CleaningCompleted);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
TestPasswordStore::PasswordMap stored_passwords = store_->stored_passwords();
ASSERT_EQ(1u, stored_passwords.size());
@@ -148,7 +148,7 @@ TEST_F(BlacklistedCredentialsCleanerTest, CleanerDeduplicatesForms) {
// Create a duplicated entry for the same signon realm.
test_credential.username_value = base::ASCIIToUTF16(kTestUsername2);
store_->AddLogin(test_credential);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
const TestPasswordStore::PasswordMap& stored_passwords =
store_->stored_passwords();
@@ -158,7 +158,7 @@ TEST_F(BlacklistedCredentialsCleanerTest, CleanerDeduplicatesForms) {
MockCredentialsCleanerObserver observer;
cleaner_.StartCleaning(&observer);
EXPECT_CALL(observer, CleaningCompleted);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_EQ(1u, stored_passwords.size());
// Only one credential for the signon realm is left.
diff --git a/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.cc
index e52c61199f5..9fcabb61ac2 100644
--- a/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.cc
+++ b/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -4,6 +4,8 @@
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
+#include <utility>
+
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -15,11 +17,14 @@
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/common/password_form.h"
#include "components/autofill/core/common/signatures_util.h"
-#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_form_metrics_recorder.h"
#include "components/password_manager/core/browser/password_manager.h"
using autofill::AutofillUploadContents;
+using autofill::FieldPropertiesFlags;
+using autofill::FormStructure;
+using autofill::PasswordAttribute;
+using autofill::ServerFieldType;
using base::NumberToString;
namespace password_manager {
@@ -98,7 +103,7 @@ BrowserSavePasswordProgressLogger::~BrowserSavePasswordProgressLogger() {}
void BrowserSavePasswordProgressLogger::LogFormSignatures(
SavePasswordProgressLogger::StringID label,
const autofill::PasswordForm& form) {
- autofill::FormStructure form_structure(form.form_data);
+ FormStructure form_structure(form.form_data);
std::string message = GetStringFromID(label) + ": {\n";
message += GetStringFromID(STRING_FORM_SIGNATURE) + ": " +
FormSignatureToDebugString(form_structure.form_signature()) + "\n";
@@ -117,7 +122,7 @@ void BrowserSavePasswordProgressLogger::LogFormSignatures(
void BrowserSavePasswordProgressLogger::LogFormStructure(
StringID label,
- const autofill::FormStructure& form_structure) {
+ const FormStructure& form_structure) {
std::string message = GetStringFromID(label) + ": {\n";
message += GetStringFromID(STRING_FORM_SIGNATURE) + ": " +
FormSignatureToDebugString(form_structure.form_signature()) + "\n";
@@ -126,6 +131,7 @@ void BrowserSavePasswordProgressLogger::LogFormStructure(
message += GetStringFromID(STRING_ACTION) + ": " +
ScrubURL(form_structure.target_url()) + "\n";
message += FormStructureToFieldsLogString(form_structure);
+ message += FormStructurePasswordAttributesLogString(form_structure);
message += "}";
SendLog(message);
}
@@ -143,8 +149,59 @@ void BrowserSavePasswordProgressLogger::LogSuccessiveOrigins(
SendLog(message);
}
+std::string
+BrowserSavePasswordProgressLogger::FormStructurePasswordAttributesLogString(
+ const FormStructure& form) {
+ const base::Optional<std::pair<PasswordAttribute, bool>> attribute_vote =
+ form.get_password_attributes_vote();
+ if (!attribute_vote.has_value())
+ return std::string();
+ std::string message;
+ const PasswordAttribute attribute = std::get<0>(attribute_vote.value());
+ const bool attribute_value = std::get<1>(attribute_vote.value());
+
+ switch (attribute) {
+ case PasswordAttribute::kHasLowercaseLetter:
+ message += BinaryPasswordAttributeLogString(
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE, attribute_value);
+ break;
+
+ case PasswordAttribute::kHasUppercaseLetter:
+ message += BinaryPasswordAttributeLogString(
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE, attribute_value);
+ break;
+
+ case PasswordAttribute::kHasNumeric:
+ message += BinaryPasswordAttributeLogString(
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS, attribute_value);
+ break;
+
+ case PasswordAttribute::kHasSpecialSymbol:
+ message += BinaryPasswordAttributeLogString(
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL,
+ attribute_value);
+ if (attribute_value) {
+ std::string voted_symbol(
+ 1, static_cast<char>(form.get_password_symbol_vote()));
+ message += PasswordAttributeLogString(
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIFIC_SPECIAL_SYMBOL,
+ voted_symbol);
+ }
+ break;
+
+ case PasswordAttribute::kPasswordAttributesCount:
+ break;
+ }
+ std::string password_length =
+ base::NumberToString(form.get_password_length_vote());
+ message += PasswordAttributeLogString(
+ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_PASSWORD_LENGTH, password_length);
+
+ return message;
+}
+
std::string BrowserSavePasswordProgressLogger::FormStructureToFieldsLogString(
- const autofill::FormStructure& form_structure) {
+ const FormStructure& form_structure) {
std::string result;
result += GetStringFromID(STRING_FIELDS) + ": " + "\n";
for (const auto& field : form_structure) {
@@ -166,7 +223,7 @@ std::string BrowserSavePasswordProgressLogger::FormStructureToFieldsLogString(
autofill::AutofillType::ServerFieldTypeToString(field->server_type());
}
- for (autofill::ServerFieldType type : field->possible_types())
+ for (ServerFieldType type : field->possible_types())
field_info +=
", VOTE: " + autofill::AutofillType::ServerFieldTypeToString(type);
@@ -175,32 +232,37 @@ std::string BrowserSavePasswordProgressLogger::FormStructureToFieldsLogString(
if (field->properties_mask) {
field_info += ", properties=";
- field_info +=
- (field->properties_mask & autofill::FieldPropertiesFlags::USER_TYPED)
- ? "T"
- : "_";
+ field_info += (field->properties_mask & FieldPropertiesFlags::USER_TYPED)
+ ? "T"
+ : "_";
field_info += (field->properties_mask &
- autofill::FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD)
+ FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD)
? "Ap"
: "__";
field_info += (field->properties_mask &
- autofill::FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER)
+ FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER)
? "Au"
: "__";
- field_info +=
- (field->properties_mask & autofill::FieldPropertiesFlags::HAD_FOCUS)
- ? "F"
- : "_";
- field_info +=
- (field->properties_mask & autofill::FieldPropertiesFlags::KNOWN_VALUE)
- ? "K"
- : "_";
+ field_info += (field->properties_mask & FieldPropertiesFlags::HAD_FOCUS)
+ ? "F"
+ : "_";
+ field_info += (field->properties_mask & FieldPropertiesFlags::KNOWN_VALUE)
+ ? "K"
+ : "_";
+ }
+
+ if (field->initial_value_hash().has_value()) {
+ field_info += ", initial value hash=";
+ field_info += field->initial_value_hash().value();
}
std::string generation = GenerationTypeToString(field->generation_type());
if (!generation.empty())
field_info += ", GENERATION_EVENT: " + generation;
+ if (field->generated_password_changed())
+ field_info += ", generated password changed";
+
result += field_info + "\n";
}
@@ -271,4 +333,17 @@ void BrowserSavePasswordProgressLogger::SendLog(const std::string& log) {
log_manager_->LogTextMessage(log);
}
+std::string BrowserSavePasswordProgressLogger::PasswordAttributeLogString(
+ StringID string_id,
+ const std::string& attribute_value) {
+ return GetStringFromID(string_id) + ": " + attribute_value + "\n";
+}
+
+std::string BrowserSavePasswordProgressLogger::BinaryPasswordAttributeLogString(
+ StringID string_id,
+ bool attribute_value) {
+ return PasswordAttributeLogString(string_id,
+ (attribute_value ? "yes" : "no"));
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.h b/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.h
index 5152f836a9e..7a072d51d7b 100644
--- a/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.h
+++ b/chromium/components/password_manager/core/browser/browser_save_password_progress_logger.h
@@ -65,10 +65,22 @@ class BrowserSavePasswordProgressLogger
// outlive this logger.
const autofill::LogManager* const log_manager_;
- // Return string representation for FormStructure.
+ // Returns string representation for |FormStructure|.
std::string FormStructureToFieldsLogString(
const autofill::FormStructure& form);
+ // Returns string representation of password attributes for |FormStructure|.
+ std::string FormStructurePasswordAttributesLogString(
+ const autofill::FormStructure& form);
+
+ // Returns the string representation of a password attribute.
+ std::string PasswordAttributeLogString(StringID string_id,
+ const std::string& attribute_value);
+
+ // Returns the string representation of a binary password attribute.
+ std::string BinaryPasswordAttributeLogString(StringID string_id,
+ bool attribute_value);
+
DISALLOW_COPY_AND_ASSIGN(BrowserSavePasswordProgressLogger);
};
diff --git a/chromium/components/password_manager/core/browser/credential_manager_impl.cc b/chromium/components/password_manager/core/browser/credential_manager_impl.cc
index e24acea3f33..9f6c9c331e7 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_impl.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_impl.cc
@@ -3,10 +3,7 @@
// found in the LICENSE file.
#include "components/password_manager/core/browser/credential_manager_impl.h"
-#include <memory>
#include <string>
-#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/metrics/user_metrics.h"
@@ -27,7 +24,12 @@ void RunGetCallback(GetCallback callback, const CredentialInfo& info) {
} // namespace
CredentialManagerImpl::CredentialManagerImpl(PasswordManagerClient* client)
- : client_(client) {
+ : client_(client)
+#if !defined(OS_IOS)
+ ,
+ leak_delegate_(client)
+#endif // !defined(OS_IOS)
+{
auto_signin_enabled_.Init(prefs::kCredentialsEnableAutosignin,
client_->GetPrefs());
}
@@ -56,6 +58,12 @@ void CredentialManagerImpl::Store(const CredentialInfo& credential,
std::unique_ptr<autofill::PasswordForm> form(
CreatePasswordFormFromCredentialInfo(credential, origin));
+ // Check whether a stored password credential was leaked.
+#if !defined(OS_IOS)
+ if (credential.type == CredentialType::CREDENTIAL_TYPE_PASSWORD)
+ leak_delegate_.StartLeakCheck(*form);
+#endif
+
std::string signon_realm = origin.GetOrigin().spec();
PasswordStore::FormDigest observed_digest(
autofill::PasswordForm::Scheme::kHtml, signon_realm, origin);
diff --git a/chromium/components/password_manager/core/browser/credential_manager_impl.h b/chromium/components/password_manager/core/browser/credential_manager_impl.h
index 24b45bdb099..41273ca1281 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_impl.h
+++ b/chromium/components/password_manager/core/browser/credential_manager_impl.h
@@ -4,9 +4,16 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_MANAGER_IMPL_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_MANAGER_IMPL_H_
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "build/build_config.h"
#include "components/password_manager/core/browser/credential_manager_password_form_manager.h"
#include "components/password_manager/core/browser/credential_manager_pending_prevent_silent_access_task.h"
#include "components/password_manager/core/browser/credential_manager_pending_request_task.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
+#include "components/password_manager/core/browser/leak_detection_delegate.h"
#include "components/password_manager/core/common/credential_manager_types.h"
#include "components/prefs/pref_member.h"
@@ -46,6 +53,12 @@ class CredentialManagerImpl
// Exposed publicly for testing.
PasswordStore::FormDigest GetSynthesizedFormForOrigin() const;
+#if defined(UNIT_TEST) && !defined(OS_IOS)
+ void set_leak_factory(std::unique_ptr<LeakDetectionCheckFactory> factory) {
+ leak_delegate_.set_leak_factory(std::move(factory));
+ }
+#endif // defined(UNIT_TEST) && !defined(OS_IOS)
+
private:
// CredentialManagerPendingRequestTaskDelegate:
GURL GetOrigin() const override;
@@ -82,6 +95,11 @@ class CredentialManagerImpl
std::unique_ptr<CredentialManagerPendingPreventSilentAccessTask>
pending_require_user_mediation_;
+#if !defined(OS_IOS)
+ // Helper for making the requests on leak detection.
+ LeakDetectionDelegate leak_delegate_;
+#endif // !defined(OS_IOS)
+
DISALLOW_COPY_AND_ASSIGN(CredentialManagerImpl);
};
diff --git a/chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc b/chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc
index c9a99b92c0d..77dfbaa9824 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc
@@ -6,18 +6,20 @@
#include <stdint.h>
-#include <memory>
+#include <algorithm>
+#include <map>
#include <string>
#include <tuple>
-#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
+#include "build/build_config.h"
#include "components/password_manager/core/browser/android_affiliation/mock_affiliated_match_helper.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "components/password_manager/core/browser/test_password_store.h"
@@ -25,6 +27,7 @@
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -32,6 +35,7 @@
using testing::_;
using testing::ElementsAre;
+using testing::Pair;
using testing::Pointee;
using testing::UnorderedElementsAre;
@@ -43,6 +47,20 @@ const char kTestWebOrigin[] = "https://example.com/";
const char kTestAndroidRealm1[] = "android://hash@com.example.one.android/";
const char kTestAndroidRealm2[] = "android://hash@com.example.two.android/";
+class MockLeakDetectionCheck : public LeakDetectionCheck {
+ public:
+ MOCK_METHOD3(Start, void(const GURL&, base::string16, base::string16));
+};
+
+class MockLeakDetectionCheckFactory : public LeakDetectionCheckFactory {
+ public:
+ MOCK_CONST_METHOD3(TryCreateLeakCheck,
+ std::unique_ptr<LeakDetectionCheck>(
+ LeakDetectionDelegateInterface*,
+ signin::IdentityManager*,
+ scoped_refptr<network::SharedURLLoaderFactory>));
+};
+
class MockPasswordManagerClient : public StubPasswordManagerClient {
public:
MOCK_CONST_METHOD1(IsSavingAndFillingEnabled, bool(const GURL&));
@@ -58,6 +76,11 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
bool(const std::vector<autofill::PasswordForm*>& local_forms,
const GURL& origin,
const CredentialsCallback& callback));
+ MOCK_METHOD3(
+ PasswordWasAutofilled,
+ void(const std::map<base::string16, const autofill::PasswordForm*>&,
+ const GURL&,
+ const std::vector<const autofill::PasswordForm*>*));
explicit MockPasswordManagerClient(PasswordStore* store)
: store_(store), password_manager_(this) {
@@ -66,6 +89,8 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
true);
prefs_->registry()->RegisterBooleanPref(
prefs::kWasAutoSignInFirstRunExperienceShown, true);
+ prefs_->registry()->RegisterBooleanPref(
+ prefs::kPasswordLeakDetectionEnabled, true);
}
~MockPasswordManagerClient() override {}
@@ -327,10 +352,10 @@ class CredentialManagerImplTest : public testing::Test {
std::move(callback));
}
- void RunAllPendingTasks() { scoped_task_environment_.RunUntilIdle(); }
+ void RunAllPendingTasks() { task_environment_.RunUntilIdle(); }
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
autofill::PasswordForm form_;
autofill::PasswordForm affiliated_form1_;
autofill::PasswordForm affiliated_form2_;
@@ -450,6 +475,8 @@ TEST_F(CredentialManagerImplTest, StoreFederatedAfterPassword) {
EXPECT_THAT(passwords["https://example.com/"], ElementsAre(form_));
federated.date_created =
passwords["federation://example.com/google.com"][0].date_created;
+ federated.date_last_used =
+ passwords["federation://example.com/google.com"][0].date_last_used;
EXPECT_THAT(passwords["federation://example.com/google.com"],
ElementsAre(federated));
}
@@ -964,7 +991,6 @@ TEST_F(CredentialManagerImplTest,
std::vector<GURL> federations;
EXPECT_CALL(*client_, NotifyUserCouldBeAutoSignedInPtr(_)).Times(0);
-
ExpectZeroClickSignInFailure(CredentialMediationRequirement::kSilent, false,
federations);
}
@@ -1615,4 +1641,72 @@ TEST_F(CredentialManagerImplTest, RespectBlacklistingFederatedCredential) {
EXPECT_TRUE(client_->pending_manager()->IsBlacklisted());
}
+TEST_F(CredentialManagerImplTest,
+ ManagePasswordsUICredentialsUpdatedUnconditionallyInSilentMediation) {
+ autofill::PasswordForm federated = origin_path_form_;
+ federated.federation_origin =
+ url::Origin::Create(GURL("https://google.com/"));
+ federated.signon_realm =
+ "federation://" + federated.origin.host() + "/google.com";
+ store_->AddLogin(federated);
+
+ form_.username_value = base::ASCIIToUTF16("username_value");
+ store_->AddLogin(form_);
+
+ EXPECT_CALL(*client_,
+ PasswordWasAutofilled(
+ ElementsAre(Pair(form_.username_value, Pointee(form_))), _,
+ Pointee(ElementsAre(Pointee(federated)))));
+
+ bool called = false;
+ CredentialManagerError error;
+ base::Optional<CredentialInfo> credential;
+ std::vector<GURL> federations;
+ federations.push_back(GURL("https://google.com/"));
+
+ CallGet(CredentialMediationRequirement::kSilent, true, federations,
+ base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
+
+ RunAllPendingTasks();
+}
+
+#if !defined(OS_IOS)
+// Check that following a call to store() a federated credential is not checked
+// for leaks.
+TEST_F(CredentialManagerImplTest,
+ StoreFederatedCredentialDoesNotStartLeakDetection) {
+ auto mock_factory =
+ std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>();
+ EXPECT_CALL(*mock_factory, TryCreateLeakCheck).Times(0);
+ cm_service_impl()->set_leak_factory(std::move(mock_factory));
+
+ form_.federation_origin = url::Origin::Create(GURL("https://example.com/"));
+ form_.password_value = base::string16();
+ form_.signon_realm = "federation://example.com/example.com";
+ CallStore({form_, CredentialType::CREDENTIAL_TYPE_FEDERATED},
+ base::DoNothing());
+
+ RunAllPendingTasks();
+}
+
+// Check that following a call to store() a password credential is checked for
+// leaks.
+TEST_F(CredentialManagerImplTest, StorePasswordCredentialStartsLeakDetection) {
+ auto mock_factory =
+ std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>();
+ auto* weak_factory = mock_factory.get();
+ cm_service_impl()->set_leak_factory(std::move(mock_factory));
+
+ auto check_instance = std::make_unique<MockLeakDetectionCheck>();
+ EXPECT_CALL(*check_instance,
+ Start(form_.origin, form_.username_value, form_.password_value));
+ EXPECT_CALL(*weak_factory, TryCreateLeakCheck)
+ .WillOnce(testing::Return(testing::ByMove(std::move(check_instance))));
+ CallStore({form_, CredentialType::CREDENTIAL_TYPE_PASSWORD},
+ base::DoNothing());
+
+ RunAllPendingTasks();
+}
+#endif // !defined(OS_IOS)
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.cc b/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.cc
index 8d620b57f4e..aa5807100a2 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.cc
@@ -26,19 +26,19 @@ CredentialManagerPasswordFormManager::CredentialManagerPasswordFormManager(
CredentialManagerPasswordFormManagerDelegate* delegate,
std::unique_ptr<FormSaver> form_saver,
std::unique_ptr<FormFetcher> form_fetcher)
- : NewPasswordFormManager(client,
- std::move(saved_form),
- std::move(form_fetcher),
- (form_saver ? std::move(form_saver)
- : std::make_unique<FormSaverImpl>(
- client->GetPasswordStore()))),
+ : PasswordFormManager(client,
+ std::move(saved_form),
+ std::move(form_fetcher),
+ (form_saver ? std::move(form_saver)
+ : std::make_unique<FormSaverImpl>(
+ client->GetPasswordStore()))),
delegate_(delegate) {}
CredentialManagerPasswordFormManager::~CredentialManagerPasswordFormManager() =
default;
void CredentialManagerPasswordFormManager::OnFetchCompleted() {
- NewPasswordFormManager::OnFetchCompleted();
+ PasswordFormManager::OnFetchCompleted();
CreatePendingCredentials();
diff --git a/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.h b/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.h
index 5f6648d56b9..6a88aa81205 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.h
+++ b/chromium/components/password_manager/core/browser/credential_manager_password_form_manager.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "components/password_manager/core/browser/new_password_form_manager.h"
+#include "components/password_manager/core/browser/password_form_manager.h"
namespace autofill {
struct PasswordForm;
@@ -27,7 +27,7 @@ class CredentialManagerPasswordFormManagerDelegate {
// A PasswordFormManager built to handle PasswordForm objects synthesized
// by the Credential Manager API.
-class CredentialManagerPasswordFormManager : public NewPasswordFormManager {
+class CredentialManagerPasswordFormManager : public PasswordFormManager {
public:
// Given a |client| and an |observed_form|, kick off the process of fetching
// matching logins from the password store; if |observed_form| doesn't map to
diff --git a/chromium/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc b/chromium/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc
index 25bd8098419..83dd964b7ad 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/fake_form_fetcher.h"
#include "components/password_manager/core/browser/stub_form_saver.h"
@@ -47,7 +47,7 @@ class MockFormSaver : public StubFormSaver {
const base::string16& old_password));
// Convenience downcasting method.
- static MockFormSaver& Get(NewPasswordFormManager* form_manager) {
+ static MockFormSaver& Get(PasswordFormManager* form_manager) {
return *static_cast<MockFormSaver*>(form_manager->form_saver());
}
@@ -97,7 +97,7 @@ class CredentialManagerPasswordFormManagerTest : public testing::Test {
}
// Necessary for callbacks, and for TestAutofillDriver.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
StubPasswordManagerClient client_;
MockDelegate delegate_;
diff --git a/chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc b/chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc
index 689d126cf3a..8c9e65473ee 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc
@@ -196,6 +196,20 @@ void CredentialManagerPendingRequestTask::ProcessForms(
else
get_result = metrics_util::CredentialManagerGetResult::kNoneFirstRun;
+ if (!local_results.empty()) {
+ std::map<base::string16, const autofill::PasswordForm*>
+ non_federated_matches;
+ std::vector<const autofill::PasswordForm*> federated_matches;
+ for (const auto& result : local_results) {
+ if (result->IsFederatedCredential()) {
+ federated_matches.emplace_back(result.get());
+ } else {
+ non_federated_matches.emplace(result->username_value, result.get());
+ }
+ }
+ delegate_->client()->PasswordWasAutofilled(non_federated_matches, origin_,
+ &federated_matches);
+ }
if (can_use_autosignin) {
// The user had credentials, but either chose not to share them with the
// site, or was prevented from doing so by lack of zero-click (or the
@@ -204,7 +218,6 @@ void CredentialManagerPendingRequestTask::ProcessForms(
delegate_->client()->NotifyUserCouldBeAutoSignedIn(
std::move(local_results[0]));
}
-
LogCredentialManagerGetResult(get_result, mediation_);
delegate_->SendCredential(send_callback_, CredentialInfo());
return;
diff --git a/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc b/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc
index 3595289c515..c2f54337a8a 100644
--- a/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc
+++ b/chromium/components/password_manager/core/browser/export/password_manager_exporter_unittest.cc
@@ -12,7 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/export/password_csv_writer.h"
@@ -95,8 +95,7 @@ std::vector<std::unique_ptr<autofill::PasswordForm>> CreatePasswordList() {
class PasswordManagerExporterTest : public testing::Test {
public:
PasswordManagerExporterTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
exporter_(&fake_credential_provider_, mock_on_progress_.Get()),
destination_path_(kNullFileName) {
exporter_.SetWriteForTesting(mock_write_file_.Get());
@@ -110,7 +109,7 @@ class PasswordManagerExporterTest : public testing::Test {
~PasswordManagerExporterTest() override = default;
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::vector<std::unique_ptr<autofill::PasswordForm>> password_list_;
FakeCredentialProvider fake_credential_provider_;
base::MockCallback<base::RepeatingCallback<
@@ -145,7 +144,7 @@ TEST_F(PasswordManagerExporterTest, PasswordExportSetPasswordListFirst) {
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// When writing fails, we should notify the UI of the failure and try to cleanup
@@ -166,7 +165,7 @@ TEST_F(PasswordManagerExporterTest, WriteFileFailed) {
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// A partial write should be considered a failure and be cleaned up.
@@ -189,7 +188,7 @@ TEST_F(PasswordManagerExporterTest, WriteFileFailedHalfway) {
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// Test that GetProgressStatus() returns the last ExportProgressStatus sent
@@ -212,7 +211,7 @@ TEST_F(PasswordManagerExporterTest, GetProgressReturnsLastCallbackStatus) {
exporter_.SetDestination(destination_path_);
ASSERT_EQ(exporter_.GetProgressStatus(), status);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_EQ(exporter_.GetProgressStatus(), status);
}
@@ -224,7 +223,7 @@ TEST_F(PasswordManagerExporterTest, DontExportWithOnlyDestination) {
exporter_.SetDestination(destination_path_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(PasswordManagerExporterTest, CancelAfterPasswords) {
@@ -236,7 +235,7 @@ TEST_F(PasswordManagerExporterTest, CancelAfterPasswords) {
exporter_.PreparePasswordsForExport();
exporter_.Cancel();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(PasswordManagerExporterTest, CancelWhileExporting) {
@@ -253,7 +252,7 @@ TEST_F(PasswordManagerExporterTest, CancelWhileExporting) {
exporter_.SetDestination(destination_path_);
exporter_.Cancel();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
// The "Cancel" button may still be visible on the UI after we've completed
@@ -274,10 +273,10 @@ TEST_F(PasswordManagerExporterTest, CancelAfterExporting) {
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
exporter_.Cancel();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
#if defined(OS_POSIX)
@@ -292,7 +291,7 @@ TEST_F(PasswordManagerExporterTest, OutputHasRestrictedPermissions) {
exporter_.PreparePasswordsForExport();
exporter_.SetDestination(destination_path_);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
#endif
diff --git a/chromium/components/password_manager/core/browser/fake_form_fetcher.cc b/chromium/components/password_manager/core/browser/fake_form_fetcher.cc
index dd68207b0ba..1941c3a7a86 100644
--- a/chromium/components/password_manager/core/browser/fake_form_fetcher.cc
+++ b/chromium/components/password_manager/core/browser/fake_form_fetcher.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/statistics_table.h"
using autofill::PasswordForm;
@@ -48,9 +49,26 @@ std::vector<const PasswordForm*> FakeFormFetcher::GetBlacklistedMatches()
return blacklisted_;
}
+const std::vector<const PasswordForm*>& FakeFormFetcher::GetAllRelevantMatches()
+ const {
+ return non_federated_same_scheme_;
+}
+
+const std::map<base::string16, const PasswordForm*>&
+FakeFormFetcher::GetBestMatches() const {
+ return best_matches_;
+}
+
+const PasswordForm* FakeFormFetcher::GetPreferredMatch() const {
+ return preferred_match_;
+}
+
void FakeFormFetcher::SetNonFederated(
const std::vector<const PasswordForm*>& non_federated) {
non_federated_ = non_federated;
+ password_manager_util::FindBestMatches(non_federated_, scheme_,
+ &non_federated_same_scheme_,
+ &best_matches_, &preferred_match_);
}
void FakeFormFetcher::SetBlacklisted(
diff --git a/chromium/components/password_manager/core/browser/fake_form_fetcher.h b/chromium/components/password_manager/core/browser/fake_form_fetcher.h
index d487c762d88..55b236df44e 100644
--- a/chromium/components/password_manager/core/browser/fake_form_fetcher.h
+++ b/chromium/components/password_manager/core/browser/fake_form_fetcher.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/macros.h"
+#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/form_fetcher.h"
#include "components/password_manager/core/browser/statistics_table.h"
@@ -48,6 +49,8 @@ class FakeFormFetcher : public FormFetcher {
stats_ = stats;
}
+ void set_scheme(autofill::PasswordForm::Scheme scheme) { scheme_ = scheme; }
+
std::vector<const autofill::PasswordForm*> GetNonFederatedMatches()
const override;
@@ -57,6 +60,14 @@ class FakeFormFetcher : public FormFetcher {
std::vector<const autofill::PasswordForm*> GetBlacklistedMatches()
const override;
+ const std::vector<const autofill::PasswordForm*>& GetAllRelevantMatches()
+ const override;
+
+ const std::map<base::string16, const autofill::PasswordForm*>&
+ GetBestMatches() const override;
+
+ const autofill::PasswordForm* GetPreferredMatch() const override;
+
void set_federated(
const std::vector<const autofill::PasswordForm*>& federated) {
state_ = State::NOT_WAITING;
@@ -80,10 +91,15 @@ class FakeFormFetcher : public FormFetcher {
private:
std::set<Consumer*> consumers_;
State state_ = State::NOT_WAITING;
+ autofill::PasswordForm::Scheme scheme_ =
+ autofill::PasswordForm::Scheme::kHtml;
std::vector<InteractionsStats> stats_;
std::vector<const autofill::PasswordForm*> non_federated_;
std::vector<const autofill::PasswordForm*> federated_;
std::vector<const autofill::PasswordForm*> blacklisted_;
+ std::vector<const autofill::PasswordForm*> non_federated_same_scheme_;
+ std::map<base::string16, const autofill::PasswordForm*> best_matches_;
+ const autofill::PasswordForm* preferred_match_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeFormFetcher);
};
diff --git a/chromium/components/password_manager/core/browser/form_fetcher.h b/chromium/components/password_manager/core/browser/form_fetcher.h
index a124269297f..0198c324963 100644
--- a/chromium/components/password_manager/core/browser/form_fetcher.h
+++ b/chromium/components/password_manager/core/browser/form_fetcher.h
@@ -5,10 +5,12 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_FETCHER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_FETCHER_H_
+#include <map>
#include <memory>
#include <vector>
#include "base/macros.h"
+#include "base/strings/string16.h"
namespace autofill {
struct PasswordForm;
@@ -76,6 +78,18 @@ class FormFetcher {
virtual std::vector<const autofill::PasswordForm*> GetBlacklistedMatches()
const = 0;
+ // Non-federated matches obtained from the backend that have the same scheme
+ // of this form.
+ virtual const std::vector<const autofill::PasswordForm*>&
+ GetAllRelevantMatches() const = 0;
+
+ // Nonblacklisted matches obtained from the backend.
+ virtual const std::map<base::string16, const autofill::PasswordForm*>&
+ GetBestMatches() const = 0;
+
+ // Pointer to an preferred entry in the map returned by GetBestMatches().
+ virtual const autofill::PasswordForm* GetPreferredMatch() const = 0;
+
// Fetches stored matching logins. In addition the statistics is fetched on
// platforms with the password bubble. This is called automatically during
// construction and can be called manually later as well to cause an update
diff --git a/chromium/components/password_manager/core/browser/form_fetcher_impl.cc b/chromium/components/password_manager/core/browser/form_fetcher_impl.cc
index 030bbb24671..0d17eaee901 100644
--- a/chromium/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/chromium/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -131,6 +131,20 @@ std::vector<const PasswordForm*> FormFetcherImpl::GetBlacklistedMatches()
return MakeWeakCopies(blacklisted_);
}
+const std::vector<const PasswordForm*>& FormFetcherImpl::GetAllRelevantMatches()
+ const {
+ return non_federated_same_scheme_;
+}
+
+const std::map<base::string16, const PasswordForm*>&
+FormFetcherImpl::GetBestMatches() const {
+ return best_matches_;
+}
+
+const PasswordForm* FormFetcherImpl::GetPreferredMatch() const {
+ return preferred_match_;
+}
+
void FormFetcherImpl::OnGetPasswordStoreResults(
std::vector<std::unique_ptr<PasswordForm>> results) {
DCHECK_EQ(State::WAITING, state_);
@@ -222,6 +236,11 @@ std::unique_ptr<FormFetcher> FormFetcherImpl::Clone() {
result->non_federated_ = MakeCopies(non_federated_);
result->federated_ = MakeCopies(federated_);
result->blacklisted_ = MakeCopies(blacklisted_);
+ password_manager_util::FindBestMatches(
+ MakeWeakCopies(result->non_federated_), form_digest_.scheme,
+ &result->non_federated_same_scheme_, &result->best_matches_,
+ &result->preferred_match_);
+
result->interactions_stats_ = this->interactions_stats_;
result->state_ = this->state_;
result->need_to_refetch_ = this->need_to_refetch_;
@@ -238,6 +257,10 @@ void FormFetcherImpl::ProcessPasswordStoreResults(
non_federated_ = std::move(matches.non_federated);
blacklisted_ = std::move(matches.blacklisted);
+ password_manager_util::FindBestMatches(
+ MakeWeakCopies(non_federated_), form_digest_.scheme,
+ &non_federated_same_scheme_, &best_matches_, &preferred_match_);
+
for (auto* consumer : consumers_)
consumer->OnFetchCompleted();
}
diff --git a/chromium/components/password_manager/core/browser/form_fetcher_impl.h b/chromium/components/password_manager/core/browser/form_fetcher_impl.h
index f5c8de61ba7..96df83afc6e 100644
--- a/chromium/components/password_manager/core/browser/form_fetcher_impl.h
+++ b/chromium/components/password_manager/core/browser/form_fetcher_impl.h
@@ -19,8 +19,9 @@ namespace password_manager {
class PasswordManagerClient;
-// Production implementation of FormFetcher. Fetches credentials associated
-// with a particular origin.
+// Production implementation of FormFetcher. Fetches credentials associated with
+// a particular origin. When adding new member fields to this class, please,
+// update the Clone() method accordingly.
class FormFetcherImpl : public FormFetcher,
public PasswordStoreConsumer,
public HttpPasswordStoreMigrator::Consumer {
@@ -46,6 +47,14 @@ class FormFetcherImpl : public FormFetcher,
std::vector<const autofill::PasswordForm*> GetBlacklistedMatches()
const override;
+ const std::vector<const autofill::PasswordForm*>& GetAllRelevantMatches()
+ const override;
+
+ const std::map<base::string16, const autofill::PasswordForm*>&
+ GetBestMatches() const override;
+
+ const autofill::PasswordForm* GetPreferredMatch() const override;
+
void Fetch() override;
std::unique_ptr<FormFetcher> Clone() override;
@@ -77,6 +86,19 @@ class FormFetcherImpl : public FormFetcher,
// List of blacklisted credentials obtained form the password store.
std::vector<std::unique_ptr<autofill::PasswordForm>> blacklisted_;
+ // Non-federated credentials of the same scheme as the observed form.
+ std::vector<const autofill::PasswordForm*> non_federated_same_scheme_;
+
+ // Set of nonblacklisted PasswordForms from the password store that best match
+ // the form being managed by |this|, indexed by username.
+ std::map<base::string16, const autofill::PasswordForm*> best_matches_;
+
+ // Convenience pointer to entry in |best_matches_| that is marked as
+ // preferred. This is only allowed to be null if there are no best matches at
+ // all, since there will always be one preferred login when there are multiple
+ // matches (when first saved, a login is marked preferred).
+ const autofill::PasswordForm* preferred_match_ = nullptr;
+
// Statistics for the current domain.
std::vector<InteractionsStats> interactions_stats_;
diff --git a/chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index 3f2137fc983..106cb13915a 100644
--- a/chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -14,7 +14,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/mock_password_store.h"
@@ -200,11 +200,11 @@ class FormFetcherImplTest : public testing::Test {
#endif
EXPECT_CALL(*mock_store_, GetLogins(form_digest_, form_fetcher_.get()));
form_fetcher_->Fetch();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_store_.get());
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
PasswordStore::FormDigest form_digest_;
std::unique_ptr<FormFetcherImpl> form_fetcher_;
MockConsumer consumer_;
@@ -422,7 +422,7 @@ TEST_F(FormFetcherImplTest, FetchStatistics) {
EXPECT_CALL(*mock_store_, GetSiteStatsImpl(stats.origin_domain))
.WillOnce(Return(db_stats));
form_fetcher_->Fetch();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_THAT(form_fetcher_->GetInteractionsStats(),
UnorderedElementsAre(stats));
@@ -432,7 +432,7 @@ TEST_F(FormFetcherImplTest, DontFetchStatistics) {
EXPECT_CALL(*mock_store_, GetLogins(form_digest_, form_fetcher_.get()));
EXPECT_CALL(*mock_store_, GetSiteStatsImpl(_)).Times(0);
form_fetcher_->Fetch();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
#endif
diff --git a/chromium/components/password_manager/core/browser/form_parsing/form_parser.cc b/chromium/components/password_manager/core/browser/form_parsing/form_parser.cc
index 83c53df3c9d..0083ec43765 100644
--- a/chromium/components/password_manager/core/browser/form_parsing/form_parser.cc
+++ b/chromium/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -109,6 +109,9 @@ struct ProcessedField {
// True if field->form_control_type == "password".
bool is_password = false;
+ // True if field is predicted to be a password.
+ bool is_predicted_as_password = false;
+
// True if the server predicts that this field is not a password field.
bool server_hints_not_password = false;
@@ -147,6 +150,7 @@ bool IsNotUsernameField(const ProcessedField& field) {
bool IsPasswordPrediction(const CredentialFieldType field_type) {
switch (field_type) {
case CredentialFieldType::kUsername:
+ case CredentialFieldType::kSingleUsername:
case CredentialFieldType::kNone:
return false;
case CredentialFieldType::kCurrentPassword:
@@ -213,6 +217,9 @@ struct SignificantFields {
// attributes.
bool is_new_password_reliable = false;
+ // True if the current form has only username, but no passwords.
+ bool is_single_username = false;
+
// Returns true if some password field is present. This is the minimal
// requirement for a successful creation of a PasswordForm is present.
bool HasPasswords() const {
@@ -220,6 +227,12 @@ struct SignificantFields {
<< "There is no password to confirm if there is no new password field.";
return password || new_password;
}
+
+ void ClearAllPasswordFields() {
+ password = nullptr;
+ new_password = nullptr;
+ confirmation_password = nullptr;
+ }
};
// Returns true if |field| is in |significant_fields|.
@@ -270,6 +283,7 @@ void ParseUsingPredictions(std::vector<ProcessedField>* processed_fields,
bool sign_in_username_first = true;
// First username is stored in |result->username|.
const FormFieldData* second_username = nullptr;
+
for (const PasswordFieldPrediction& prediction : predictions) {
ProcessedField* processed_field = nullptr;
@@ -284,18 +298,25 @@ void ParseUsingPredictions(std::vector<ProcessedField>* processed_fields,
case CredentialFieldType::kUsername:
if (!result->username) {
processed_field = FindField(processed_fields, prediction);
- if (processed_field) {
+ if (processed_field)
result->username = processed_field->field;
- }
} else if (!second_username) {
processed_field = FindField(processed_fields, prediction);
- if (processed_field) {
+ if (processed_field)
second_username = processed_field->field;
- }
} else {
prevent_handling_two_usernames = true;
}
break;
+ case CredentialFieldType::kSingleUsername:
+ processed_field = FindField(processed_fields, prediction);
+ if (processed_field) {
+ result->username = processed_field->field;
+ result->is_single_username = true;
+ result->ClearAllPasswordFields();
+ return;
+ }
+ break;
case CredentialFieldType::kCurrentPassword:
if (result->password) {
prevent_handling_two_usernames = true;
@@ -322,18 +343,16 @@ void ParseUsingPredictions(std::vector<ProcessedField>* processed_fields,
if (!result->new_password) {
processed_field = FindField(processed_fields, prediction);
if (processed_field) {
- if (!processed_field->is_password)
- continue;
result->new_password = processed_field->field;
+ processed_field->is_predicted_as_password = true;
}
}
break;
case CredentialFieldType::kConfirmationPassword:
processed_field = FindField(processed_fields, prediction);
if (processed_field) {
- if (!processed_field->is_password)
- continue;
result->confirmation_password = processed_field->field;
+ processed_field->is_predicted_as_password = true;
}
break;
case CredentialFieldType::kNone:
@@ -478,7 +497,8 @@ std::vector<const FormFieldData*> GetRelevantPasswords(
if (processed_field.is_password)
passwords.push_back(&processed_field);
}
- DCHECK(!passwords.empty());
+ if (passwords.empty())
+ return std::vector<const FormFieldData*>();
// These two counters are used to determine the ReadonlyPasswordFields value
// corresponding to this form.
@@ -621,7 +641,7 @@ const FormFieldData* FindUsernameFieldBaseHeuristics(
// Do reverse search to find the closest candidates preceding the password.
for (auto it = std::make_reverse_iterator(first_relevant_password);
it != processed_fields.rend(); ++it) {
- if (it->is_password)
+ if (it->is_password || it->is_predicted_as_password)
continue;
if (!MatchesInteractability(*it, best_interactability))
continue;
@@ -646,7 +666,8 @@ const FormFieldData* FindUsernameFieldBaseHeuristics(
// A helper to return a |field|'s unique_renderer_id or
// kNotSetFormControlRendererId if |field| is null.
uint32_t ExtractUniqueId(const FormFieldData* field) {
- return field ? field->unique_renderer_id : FormFieldData::kNotSetFormControlRendererId;
+ return field ? field->unique_renderer_id
+ : FormFieldData::kNotSetFormControlRendererId;
}
// Tries to find the username and password fields in |processed_fields| based
@@ -708,7 +729,7 @@ void ParseUsingBaseHeuristics(
ExtractUniqueId(found_fields->confirmation_password)};
for (auto it = processed_fields.begin(); it != processed_fields.end();
++it) {
- if (it->is_password &&
+ if ((it->is_password || it->is_predicted_as_password) &&
base::Contains(password_ids, it->field->unique_renderer_id)) {
first_relevant_password = it;
break;
@@ -803,8 +824,6 @@ std::vector<ProcessedField> ProcessFields(
DCHECK(all_possible_passwords->empty());
std::vector<ProcessedField> result;
- bool password_field_found = false;
-
result.reserve(fields.size());
// |all_possible_passwords| should only contain each value once.
@@ -821,6 +840,7 @@ std::vector<ProcessedField> ProcessFields(
continue;
const bool is_password = field.form_control_type == "password";
+
if (!field.value.empty()) {
std::set<base::StringPiece16>& seen_values =
is_password ? seen_password_values : seen_username_values;
@@ -840,8 +860,6 @@ std::vector<ProcessedField> ProcessFields(
ProcessedField processed_field = {
.field = &field, .autocomplete_flag = flag, .is_password = is_password};
- password_field_found |= is_password;
-
if (field.properties_mask & FieldPropertiesFlags::USER_TYPED)
processed_field.interactability = Interactability::kCertain;
else if (field.is_focusable)
@@ -850,9 +868,6 @@ std::vector<ProcessedField> ProcessFields(
result.push_back(processed_field);
}
- if (!password_field_found)
- result.clear();
-
return result;
}
@@ -908,8 +923,10 @@ std::unique_ptr<PasswordForm> AssemblePasswordForm(
autofill::ValueElementVector all_possible_passwords,
autofill::ValueElementVector all_possible_usernames,
const base::Optional<FormPredictions>& form_predictions) {
- if (!significant_fields.HasPasswords())
+ if (!significant_fields.HasPasswords() &&
+ !significant_fields.is_single_username) {
return nullptr;
+ }
// Create the PasswordForm and set data not related to specific fields.
auto result = std::make_unique<PasswordForm>();
@@ -930,6 +947,13 @@ std::unique_ptr<PasswordForm> AssemblePasswordForm(
result->only_for_fallback = significant_fields.is_fallback;
result->submission_event = form_data.submission_event;
+ for (const FormFieldData& field : form_data.fields) {
+ if (field.form_control_type == "password" &&
+ (field.properties_mask & FieldPropertiesFlags::AUTOFILLED)) {
+ result->form_has_autofilled_value = true;
+ }
+ }
+
// Set data related to specific fields.
SetFields(significant_fields, result.get());
return result;
@@ -970,11 +994,14 @@ std::unique_ptr<PasswordForm> FormDataParser::Parse(const FormData& form_data,
}
// (2) If that failed, try to parse with autocomplete attributes.
- ParseUsingAutocomplete(processed_fields, &significant_fields);
- if (username_detection_method ==
- UsernameDetectionMethod::kNoUsernameDetected &&
- significant_fields.username) {
- username_detection_method = UsernameDetectionMethod::kAutocompleteAttribute;
+ if (!significant_fields.is_single_username) {
+ ParseUsingAutocomplete(processed_fields, &significant_fields);
+ if (username_detection_method ==
+ UsernameDetectionMethod::kNoUsernameDetected &&
+ significant_fields.username) {
+ username_detection_method =
+ UsernameDetectionMethod::kAutocompleteAttribute;
+ }
}
// Pass the "reliability" information to mark the new-password fields as
@@ -989,32 +1016,35 @@ std::unique_ptr<PasswordForm> FormDataParser::Parse(const FormData& form_data,
const bool username_found_before_heuristic = significant_fields.username;
// Try to parse with base heuristic.
- Interactability username_max = Interactability::kUnlikely;
- ParseUsingBaseHeuristics(processed_fields, mode, &significant_fields,
- &username_max, &readonly_status_);
- if (username_detection_method ==
- UsernameDetectionMethod::kNoUsernameDetected &&
- significant_fields.username) {
- username_detection_method = UsernameDetectionMethod::kBaseHeuristic;
- }
+ if (!significant_fields.is_single_username) {
+ Interactability username_max = Interactability::kUnlikely;
+ ParseUsingBaseHeuristics(processed_fields, mode, &significant_fields,
+ &username_max, &readonly_status_);
+ if (username_detection_method ==
+ UsernameDetectionMethod::kNoUsernameDetected &&
+ significant_fields.username) {
+ username_detection_method = UsernameDetectionMethod::kBaseHeuristic;
+ }
- // Additionally, and based on the best interactability computed by base
- // heuristics, try to improve the username based on the context of the
- // fields, unless the username already came from more reliable types of
- // analysis.
- if (!username_found_before_heuristic) {
- const FormFieldData* username_field_by_context = FindUsernameInPredictions(
- form_data.username_predictions, processed_fields, username_max);
- if (username_field_by_context &&
- !(mode == FormDataParser::Mode::kSaving &&
- username_field_by_context->value.empty())) {
- significant_fields.username = username_field_by_context;
- if (username_detection_method ==
- UsernameDetectionMethod::kNoUsernameDetected ||
- username_detection_method ==
- UsernameDetectionMethod::kBaseHeuristic) {
- username_detection_method =
- UsernameDetectionMethod::kHtmlBasedClassifier;
+ // Additionally, and based on the best interactability computed by base
+ // heuristics, try to improve the username based on the context of the
+ // fields, unless the username already came from more reliable types of
+ // analysis.
+ if (!username_found_before_heuristic) {
+ const FormFieldData* username_field_by_context =
+ FindUsernameInPredictions(form_data.username_predictions,
+ processed_fields, username_max);
+ if (username_field_by_context &&
+ !(mode == FormDataParser::Mode::kSaving &&
+ username_field_by_context->value.empty())) {
+ significant_fields.username = username_field_by_context;
+ if (username_detection_method ==
+ UsernameDetectionMethod::kNoUsernameDetected ||
+ username_detection_method ==
+ UsernameDetectionMethod::kBaseHeuristic) {
+ username_detection_method =
+ UsernameDetectionMethod::kHtmlBasedClassifier;
+ }
}
}
}
diff --git a/chromium/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/chromium/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
index 059fbb4f473..447b6f3c18e 100644
--- a/chromium/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
+++ b/chromium/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -97,6 +97,7 @@ struct FormParsingTestCase {
bool fallback_only = false;
SubmissionIndicatorEvent submission_event = SubmissionIndicatorEvent::NONE;
base::Optional<bool> is_new_password_reliable;
+ bool form_has_autofilled_value = false;
};
// Returns numbers which are distinct from each other within the scope of one
@@ -374,6 +375,8 @@ void CheckTestData(const std::vector<FormParsingTestCase>& test_cases) {
EXPECT_EQ(*test_case.is_new_password_reliable,
parsed_form->is_new_password_reliable);
}
+ EXPECT_EQ(test_case.form_has_autofilled_value,
+ parsed_form->form_has_autofilled_value);
CheckPasswordFormFields(*parsed_form, form_data, expected_ids);
CheckAllValuesUnique(parsed_form->all_possible_passwords);
@@ -1024,6 +1027,7 @@ TEST(FormParserTest, ReadonlyFields) {
{.form_control_type = "password", .is_readonly = true},
},
.number_of_all_possible_passwords = 3,
+ .form_has_autofilled_value = true,
},
{
.description_for_logging = "And passwords already filled by user or "
@@ -1044,6 +1048,89 @@ TEST(FormParserTest, ReadonlyFields) {
{.form_control_type = "password", .is_readonly = true},
},
.number_of_all_possible_passwords = 3,
+ .form_has_autofilled_value = true,
+ },
+ });
+}
+
+TEST(FormParserTest, ServerPredictionsForClearTextPasswordFields) {
+ CheckTestData({
+ {
+ "Server prediction for account change password and username field.",
+ {
+ {
+ .role_filling = ElementRole::USERNAME,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS},
+ },
+ {
+ .role_filling = ElementRole::NEW_PASSWORD,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::NEW_PASSWORD},
+ },
+ },
+ },
+ {
+ "Server prediction for account change password field only.",
+ {
+ {.role_filling = ElementRole::USERNAME,
+ .form_control_type = "text"},
+ {
+ .role_filling = ElementRole::NEW_PASSWORD,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::NEW_PASSWORD},
+ },
+ },
+ },
+ {
+ "Server prediction for account password and username field.",
+ {
+ {
+ .form_control_type = "text",
+ .prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS},
+ },
+ {
+ .form_control_type = "text",
+ .prediction = {.type = autofill::PASSWORD},
+ },
+ },
+ },
+ {
+ "Server prediction for account password field only.",
+ {
+ {.form_control_type = "text"},
+ {
+ .form_control_type = "text",
+ .prediction = {.type = autofill::PASSWORD},
+ },
+ },
+ },
+ {
+ "Server prediction for account creation password and username field.",
+ {
+ {
+ .role_filling = ElementRole::USERNAME,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS},
+ },
+ {
+ .role_filling = ElementRole::NEW_PASSWORD,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD},
+ },
+ },
+ },
+ {
+ "Server prediction for account creation password field only.",
+ {
+ {.role_filling = ElementRole::USERNAME,
+ .form_control_type = "text"},
+ {
+ .role_filling = ElementRole::NEW_PASSWORD,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::ACCOUNT_CREATION_PASSWORD},
+ },
+ },
},
});
}
@@ -1179,6 +1266,7 @@ TEST(FormParserTest, Interactability) {
.is_focusable = true},
},
.number_of_all_possible_passwords = 3,
+ .form_has_autofilled_value = true,
},
{
"Interactability for usernames is only considered before the first "
@@ -1197,6 +1285,7 @@ TEST(FormParserTest, Interactability) {
.is_focusable = true},
{.form_control_type = "text", .is_focusable = true, .value = ""},
},
+ .form_has_autofilled_value = true,
},
{
"Interactability also matters for HTML classifier.",
@@ -1667,6 +1756,7 @@ TEST(FormParserTest, ReadonlyStatus) {
},
.readonly_status =
FormDataParser::ReadonlyPasswordFields::kNoneIgnored,
+ .form_has_autofilled_value = true,
},
{
"Some readonly passwords ignored.",
@@ -2096,6 +2186,21 @@ TEST(FormParserTest, ContradictingPasswordPredictionAndAutocomplete) {
.autocomplete_attribute = "new-password"}}}});
}
+TEST(FormParserTest, SingleUsernamePrediction) {
+ CheckTestData({
+ {"1 field",
+ {{.role = ElementRole::USERNAME,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::SINGLE_USERNAME}}}},
+ {"Password field is ignored",
+ {{.role = ElementRole::USERNAME,
+ .form_control_type = "text",
+ .prediction = {.type = autofill::SINGLE_USERNAME}},
+ {.form_control_type = "password",
+ .prediction = {.type = autofill::PASSWORD}}}},
+ });
+}
+
} // namespace
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.cc b/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.cc
index 7f46f57ca83..ffe3ac50368 100644
--- a/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.cc
+++ b/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.cc
@@ -30,6 +30,8 @@ CredentialFieldType DeriveFromServerFieldType(ServerFieldType type) {
case autofill::USERNAME:
case autofill::USERNAME_AND_EMAIL_ADDRESS:
return CredentialFieldType::kUsername;
+ case autofill::SINGLE_USERNAME:
+ return CredentialFieldType::kSingleUsername;
case autofill::PASSWORD:
return CredentialFieldType::kCurrentPassword;
case autofill::ACCOUNT_CREATION_PASSWORD:
diff --git a/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.h b/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.h
index d92f8764745..0c91ee89f6d 100644
--- a/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.h
+++ b/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction.h
@@ -20,6 +20,7 @@ namespace password_manager {
enum class CredentialFieldType {
kNone,
kUsername,
+ kSingleUsername,
kCurrentPassword,
kNewPassword,
kConfirmationPassword
diff --git a/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc b/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc
index a0265ee189a..a9953935211 100644
--- a/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc
+++ b/chromium/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc
@@ -13,8 +13,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using autofill::AutofillField;
using autofill::ACCOUNT_CREATION_PASSWORD;
+using autofill::AutofillField;
using autofill::CONFIRMATION_PASSWORD;
using autofill::EMAIL_ADDRESS;
using autofill::FormData;
@@ -24,6 +24,7 @@ using autofill::NEW_PASSWORD;
using autofill::NO_SERVER_DATA;
using autofill::PASSWORD;
using autofill::ServerFieldType;
+using autofill::SINGLE_USERNAME;
using autofill::UNKNOWN_TYPE;
using autofill::USERNAME;
using autofill::USERNAME_AND_EMAIL_ADDRESS;
@@ -186,6 +187,8 @@ TEST(FormPredictionsTest, DeriveFromServerFieldType) {
{"Username", USERNAME, CredentialFieldType::kUsername},
{"Username/Email", USERNAME_AND_EMAIL_ADDRESS,
CredentialFieldType::kUsername},
+ {"Single Username", SINGLE_USERNAME,
+ CredentialFieldType::kSingleUsername},
{"Password", PASSWORD, CredentialFieldType::kCurrentPassword},
{"New password", NEW_PASSWORD, CredentialFieldType::kNewPassword},
{"Account creation password", ACCOUNT_CREATION_PASSWORD,
diff --git a/chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc b/chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc
index d117476508a..5188fbbae1a 100644
--- a/chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc
+++ b/chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc
@@ -13,7 +13,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/browser/password_manager_util.h"
@@ -77,7 +77,7 @@ class FormSaverImplTest : public testing::Test {
protected:
// For the MockPasswordStore.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<StrictMock<MockPasswordStore>> mock_store_;
FormSaverImpl form_saver_;
diff --git a/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_impl.cc b/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_impl.cc
index d73f6b7133e..b679a0ecff3 100644
--- a/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_impl.cc
+++ b/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_impl.cc
@@ -172,7 +172,7 @@ void PasswordRequirementsSpecFetcherImpl::Fetch(GURL origin,
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = GetUrlForRequirementsSpec(version_, hash_prefix);
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
lookup->url_loader = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
lookup->url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
diff --git a/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc b/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc
index 9ec93ad528f..93da8266961 100644
--- a/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc
+++ b/chromium/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/proto/password_requirements.pb.h"
#include "components/autofill/core/browser/proto/password_requirements_shard.pb.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -207,8 +207,8 @@ TEST(PasswordRequirementsSpecFetcherTest, FetchData) {
SCOPED_TRACE(test.test_name);
base::HistogramTester histogram_tester;
- base::test::ScopedTaskEnvironment environment(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
+ base::test::TaskEnvironment environment(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME);
network::TestURLLoaderFactory loader_factory;
loader_factory.AddResponse(test.requested_url, test.response_content,
test.response_status);
@@ -262,8 +262,8 @@ TEST(PasswordRequirementsSpecFetcherTest, FetchDataInterleaved) {
(*shard.mutable_specs())["b.com"].set_min_length(18);
shard.SerializeToString(&serialized_shard);
- base::test::ScopedTaskEnvironment environment(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
+ base::test::TaskEnvironment environment(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME);
network::TestURLLoaderFactory loader_factory;
// Target into which data will be written by the callback.
@@ -315,7 +315,7 @@ TEST(PasswordRequirementsSpecFetcherTest, FetchDataInterleaved) {
// In case of incognito mode, we won't have a URL loader factory.
// Test that an empty spec is returned by the spec fetcher in this case.
TEST(PasswordRequirementsSpecFetcherTest, FetchDataWithoutURLLoaderFactory) {
- base::test::ScopedTaskEnvironment environment;
+ base::test::TaskEnvironment environment;
// Target into which data will be written by the callback.
PasswordRequirementsSpec received_spec;
diff --git a/chromium/components/password_manager/core/browser/hash_password_manager.cc b/chromium/components/password_manager/core/browser/hash_password_manager.cc
index 2d5fab400cb..9a8ee08c89c 100644
--- a/chromium/components/password_manager/core/browser/hash_password_manager.cc
+++ b/chromium/components/password_manager/core/browser/hash_password_manager.cc
@@ -143,6 +143,8 @@ base::Optional<PasswordHashData> ConvertToPasswordHashData(
} // namespace
HashPasswordManager::HashPasswordManager(PrefService* prefs) : prefs_(prefs) {}
+HashPasswordManager::HashPasswordManager() = default;
+HashPasswordManager::~HashPasswordManager() = default;
bool HashPasswordManager::SavePasswordHash(const std::string username,
const base::string16& password,
@@ -168,9 +170,10 @@ bool HashPasswordManager::SavePasswordHash(const std::string username,
}
}
}
-
- return SavePasswordHash(
+ bool is_saved = SavePasswordHash(
PasswordHashData(username, password, true, is_gaia_password));
+ state_callback_list_.Notify(username);
+ return is_saved;
}
bool HashPasswordManager::SavePasswordHash(
@@ -216,6 +219,23 @@ void HashPasswordManager::ClearAllPasswordHash(bool is_gaia_password) {
}
}
+void HashPasswordManager::ClearAllNonGmailPasswordHash() {
+ if (!prefs_)
+ return;
+
+ ListPrefUpdate update(prefs_, prefs::kPasswordHashDataList);
+
+ base::EraseIf(update->GetList(), [](const base::Value& data) {
+ if (GetAndDecryptField(data, kIsGaiaFieldKey) == "false") {
+ return false;
+ }
+ std::string username = GetAndDecryptField(data, kUsernameFieldKey);
+ std::string email =
+ CanonicalizeUsername(username, /*is_gaia_account=*/true);
+ return email.find("@gmail.com") == std::string::npos;
+ });
+}
+
std::vector<PasswordHashData> HashPasswordManager::RetrieveAllPasswordHashes() {
std::vector<PasswordHashData> result;
if (!prefs_ || !prefs_->HasPrefPath(prefs::kPasswordHashDataList))
@@ -270,6 +290,11 @@ bool HashPasswordManager::HasPasswordHash(const std::string& username,
return false;
}
+std::unique_ptr<StateSubscription> HashPasswordManager::RegisterStateCallback(
+ const base::Callback<void(const std::string& username)>& callback) {
+ return state_callback_list_.Add(callback);
+}
+
bool HashPasswordManager::EncryptAndSaveToPrefs(const std::string& pref_name,
const std::string& s) {
std::string encrypted_base64_text = EncryptString(s);
diff --git a/chromium/components/password_manager/core/browser/hash_password_manager.h b/chromium/components/password_manager/core/browser/hash_password_manager.h
index ff57e5ae214..37c62f712b9 100644
--- a/chromium/components/password_manager/core/browser/hash_password_manager.h
+++ b/chromium/components/password_manager/core/browser/hash_password_manager.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HASH_PASSWORD_MANAGER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_HASH_PASSWORD_MANAGER_H_
+#include "base/callback.h"
+#include "base/callback_list.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
@@ -12,6 +14,9 @@
class PrefService;
+using StateSubscription =
+ base::CallbackList<void(const std::string& username)>::Subscription;
+
namespace password_manager {
// Responsible for saving, clearing, retrieving and encryption of a password
@@ -19,9 +24,9 @@ namespace password_manager {
// All methods should be called on UI thread.
class HashPasswordManager {
public:
- HashPasswordManager() = default;
+ HashPasswordManager();
explicit HashPasswordManager(PrefService* prefs);
- ~HashPasswordManager() = default;
+ ~HashPasswordManager();
bool SavePasswordHash(const std::string username,
const base::string16& password,
@@ -34,6 +39,9 @@ class HashPasswordManager {
// clears all enterprise password hashes.
void ClearAllPasswordHash(bool is_gaia_password);
+ // Clears all non-Gmail Gaia password hashes.
+ void ClearAllNonGmailPasswordHash();
+
// Returns empty array if no hash is available.
std::vector<PasswordHashData> RetrieveAllPasswordHashes();
@@ -48,6 +56,11 @@ class HashPasswordManager {
void set_prefs(PrefService* prefs) { prefs_ = prefs; }
+ // Adds a listener for when |kPasswordHashDataList| list might have changed.
+ // Should only be called on the UI thread.
+ virtual std::unique_ptr<StateSubscription> RegisterStateCallback(
+ const base::Callback<void(const std::string& username)>& callback);
+
private:
// Saves encrypted string |s| in a preference |pref_name|. Returns true on
// success.
@@ -63,6 +76,10 @@ class HashPasswordManager {
PrefService* prefs_ = nullptr;
+ // Callbacks when |kPasswordHashDataList| might have changed.
+ // Should only be accessed on the UI thread.
+ base::CallbackList<void(const std::string& username)> state_callback_list_;
+
DISALLOW_COPY_AND_ASSIGN(HashPasswordManager);
};
diff --git a/chromium/components/password_manager/core/browser/hsts_query_unittest.cc b/chromium/components/password_manager/core/browser/hsts_query_unittest.cc
index ebd21cb406d..3bcbbda601a 100644
--- a/chromium/components/password_manager/core/browser/hsts_query_unittest.cc
+++ b/chromium/components/password_manager/core/browser/hsts_query_unittest.cc
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "net/url_request/url_request_test_util.h"
@@ -71,7 +71,7 @@ class HSTSQueryTest : public testing::Test {
private:
// Used by request_context_.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
network::mojom::NetworkContextPtr network_context_pipe_;
std::unique_ptr<network::NetworkContext> network_context_;
diff --git a/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc b/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc
index 13e66d38e5f..246bdf10f19 100644
--- a/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc
+++ b/chromium/components/password_manager/core/browser/http_auth_manager_impl.cc
@@ -9,7 +9,7 @@
#include "components/autofill/core/common/password_form.h"
#include "components/autofill/core/common/save_password_progress_logger.h"
#include "components/password_manager/core/browser/form_saver_impl.h"
-#include "components/password_manager/core/browser/new_password_form_manager.h"
+#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_util.h"
@@ -59,7 +59,7 @@ void HttpAuthManagerImpl::SetObserverAndDeliverCredentials(
observer_->OnLoginModelDestroying();
observer_ = observer;
// Initialize the form manager.
- form_manager_ = std::make_unique<NewPasswordFormManager>(
+ form_manager_ = std::make_unique<PasswordFormManager>(
client_, PasswordStore::FormDigest(observed_form),
nullptr, /* form_fetcher */
std::make_unique<FormSaverImpl>(client_->GetPasswordStore()));
@@ -128,6 +128,13 @@ void HttpAuthManagerImpl::OnLoginSuccesfull() {
if (!form_manager_->is_submitted())
return;
+ if (form_manager_->GetFormFetcher()->GetState() ==
+ FormFetcher::State::WAITING) {
+ // We have a provisional save manager, but it didn't finish matching yet.
+ // We just give up.
+ return;
+ }
+
// TODO(crbug/831123) Move the logic into the PasswordFormManager.
bool is_update = form_manager_->IsPasswordUpdate();
bool is_new_login = form_manager_->IsNewLogin();
diff --git a/chromium/components/password_manager/core/browser/http_auth_manager_impl.h b/chromium/components/password_manager/core/browser/http_auth_manager_impl.h
index f6fca7c66fe..bd54cf4db1a 100644
--- a/chromium/components/password_manager/core/browser/http_auth_manager_impl.h
+++ b/chromium/components/password_manager/core/browser/http_auth_manager_impl.h
@@ -18,7 +18,7 @@
namespace password_manager {
class PasswordManagerClient;
-class NewPasswordFormManager;
+class PasswordFormManager;
class PasswordFormManagerForUI;
// Implementation of the HttpAuthManager as used by the PasswordManagerClient.
@@ -55,7 +55,7 @@ class HttpAuthManagerImpl : public HttpAuthManager {
// Get a Logger object and write a log message defined by the message id.
void LogMessage(const BrowserSavePasswordProgressLogger::StringID) const;
- // Passes |form| to NewPasswordFormManager that manages it for using it after
+ // Passes |form| to PasswordFormManager that manages it for using it after
// detecting submission success for saving.
void ProvisionallySaveForm(const autofill::PasswordForm& password_form);
@@ -69,7 +69,7 @@ class HttpAuthManagerImpl : public HttpAuthManager {
HttpAuthObserver* observer_;
// Single password form manager to handle the http-auth request form.
- std::unique_ptr<NewPasswordFormManager> form_manager_;
+ std::unique_ptr<PasswordFormManager> form_manager_;
// When set to true, the password form has been dismissed and |form_manager_|
// will be cleared on next navigation.
diff --git a/chromium/components/password_manager/core/browser/http_auth_manager_unittest.cc b/chromium/components/password_manager/core/browser/http_auth_manager_unittest.cc
index 3da807daba1..d70fc51d411 100644
--- a/chromium/components/password_manager/core/browser/http_auth_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/http_auth_manager_unittest.cc
@@ -14,14 +14,14 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "build/build_config.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/password_manager/core/browser/form_fetcher_impl.h"
#include "components/password_manager/core/browser/http_auth_manager_impl.h"
#include "components/password_manager/core/browser/mock_password_store.h"
-#include "components/password_manager/core/browser/new_password_form_manager.h"
+#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
#include "components/password_manager/core/browser/password_store.h"
@@ -122,7 +122,7 @@ class HttpAuthManagerTest : public testing::Test {
HttpAuthManagerImpl* httpauth_manager() { return httpauth_manager_.get(); }
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<MockPasswordStore> store_;
testing::NiceMock<MockPasswordManagerClient> client_;
std::unique_ptr<HttpAuthManagerImpl> httpauth_manager_;
@@ -219,4 +219,30 @@ TEST_F(HttpAuthManagerTest, NavigationWithoutSubmission) {
httpauth_manager()->DetachObserver(&observer);
}
+TEST_F(HttpAuthManagerTest, NavigationWhenMatchingNotReady) {
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled).WillRepeatedly(Return(true));
+ PasswordForm observed_form;
+ observed_form.scheme = PasswordForm::Scheme::kBasic;
+ observed_form.origin = GURL("http://proxy.com/");
+ observed_form.signon_realm = "proxy.com/realm";
+
+ MockHttpAuthObserver observer;
+ // The password store is queried but it's slow and won't respond.
+ EXPECT_CALL(*store_, GetLogins);
+ // Initiate creating a form manager.
+ httpauth_manager()->SetObserverAndDeliverCredentials(&observer,
+ observed_form);
+
+ PasswordForm submitted_form = observed_form;
+ submitted_form.username_value = ASCIIToUTF16("user");
+ submitted_form.password_value = ASCIIToUTF16("1234");
+ httpauth_manager()->OnPasswordFormSubmitted(submitted_form);
+ httpauth_manager()->OnPasswordFormDismissed();
+
+ // Expect no prompt as the password store didn't reply.
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr()).Times(0);
+ httpauth_manager()->OnDidFinishMainFrameNavigation();
+ httpauth_manager()->DetachObserver(&observer);
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc b/chromium/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
index 1e8e20ed89f..94a7cc91872 100644
--- a/chromium/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
+++ b/chromium/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
@@ -10,7 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/test_password_store.h"
@@ -138,7 +138,7 @@ TEST_P(HttpCredentialCleanerTest, ReportHttpMigrationMetrics) {
static const base::string16 password[2] = {base::ASCIIToUTF16("pass0"),
base::ASCIIToUTF16("pass1")};
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::TaskEnvironment task_environment;
ASSERT_TRUE(store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr));
TestCase test = GetParam();
SCOPED_TRACE(testing::Message()
@@ -187,7 +187,7 @@ TEST_P(HttpCredentialCleanerTest, ReportHttpMigrationMetrics) {
run_loop.QuitClosure());
run_loop.Run();
}
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
base::HistogramTester histogram_tester;
const TestPasswordStore::PasswordMap passwords_before_cleaning =
@@ -212,7 +212,7 @@ TEST_P(HttpCredentialCleanerTest, ReportHttpMigrationMetrics) {
&prefs);
EXPECT_CALL(observer, CleaningCompleted);
cleaner.StartCleaning(&observer);
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
histogram_tester.ExpectUniqueSample(
"PasswordManager.HttpCredentials",
@@ -237,7 +237,7 @@ TEST_P(HttpCredentialCleanerTest, ReportHttpMigrationMetrics) {
}
store_->ShutdownOnUIThread();
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
}
INSTANTIATE_TEST_SUITE_P(,
@@ -249,7 +249,7 @@ TEST(HttpCredentialCleaner, StartCleanUpTest) {
SCOPED_TRACE(testing::Message()
<< "should_start_clean_up=" << should_start_clean_up);
- base::test::ScopedTaskEnvironment scoped_task_environment;
+ base::test::TaskEnvironment task_environment;
auto password_store = base::MakeRefCounted<TestPasswordStore>();
ASSERT_TRUE(password_store->Init(syncer::SyncableService::StartSyncFlare(),
nullptr));
@@ -275,7 +275,7 @@ TEST(HttpCredentialCleaner, StartCleanUpTest) {
if (!should_start_clean_up) {
password_store->ShutdownOnUIThread();
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
continue;
}
@@ -304,13 +304,13 @@ TEST(HttpCredentialCleaner, StartCleanUpTest) {
EXPECT_TRUE(cleaner.NeedsCleaning());
EXPECT_CALL(observer, CleaningCompleted);
cleaner.StartCleaning(&observer);
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
EXPECT_NE(prefs.GetDouble(prefs::kLastTimeObsoleteHttpCredentialsRemoved),
last_time);
password_store->ShutdownOnUIThread();
- scoped_task_environment.RunUntilIdle();
+ task_environment.RunUntilIdle();
}
}
diff --git a/chromium/components/password_manager/core/browser/http_password_store_migrator_unittest.cc b/chromium/components/password_manager/core/browser/http_password_store_migrator_unittest.cc
index 45970432574..b15363203a0 100644
--- a/chromium/components/password_manager/core/browser/http_password_store_migrator_unittest.cc
+++ b/chromium/components/password_manager/core/browser/http_password_store_migrator_unittest.cc
@@ -3,10 +3,11 @@
// found in the LICENSE file.
#include "components/password_manager/core/browser/http_password_store_migrator.h"
+
#include <memory>
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -130,7 +131,7 @@ class HttpPasswordStoreMigratorTest : public testing::Test {
MockPasswordStore& store() { return *mock_store_; }
MockPasswordManagerClient& client() { return client_; }
- void WaitForPasswordStore() { scoped_task_environment_.RunUntilIdle(); }
+ void WaitForPasswordStore() { task_environment_.RunUntilIdle(); }
protected:
void TestEmptyStore(bool is_hsts);
@@ -138,7 +139,7 @@ class HttpPasswordStoreMigratorTest : public testing::Test {
void TestMigratorDeletionByConsumer(bool is_hsts);
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockConsumer consumer_;
scoped_refptr<MockPasswordStore> mock_store_;
MockPasswordManagerClient client_;
diff --git a/chromium/components/password_manager/core/browser/import/csv_password.cc b/chromium/components/password_manager/core/browser/import/csv_password.cc
index 4b0cf869210..0a78a69703e 100644
--- a/chromium/components/password_manager/core/browser/import/csv_password.cc
+++ b/chromium/components/password_manager/core/browser/import/csv_password.cc
@@ -17,18 +17,21 @@ namespace password_manager {
using ::autofill::PasswordForm;
-CSVPassword::CSVPassword() = default;
-
-CSVPassword::CSVPassword(ColumnMap map, base::StringPiece csv_row)
- : map_(std::move(map)), row_(csv_row) {}
-
-CSVPassword::CSVPassword(const CSVPassword&) = default;
-
-CSVPassword::CSVPassword(CSVPassword&&) = default;
+namespace {
+
+// Convert() unescapes a CSV field |str| and converts the result to a 16-bit
+// string. |str| is assumed to exclude the outer pair of quotation marks, if
+// originally present.
+base::string16 Convert(base::StringPiece str) {
+ std::string str_copy(str);
+ base::ReplaceSubstringsAfterOffset(&str_copy, 0, "\"\"", "\"");
+ return base::UTF8ToUTF16(str_copy);
+}
-CSVPassword& CSVPassword::operator=(const CSVPassword&) = default;
+} // namespace
-CSVPassword& CSVPassword::operator=(CSVPassword&&) = default;
+CSVPassword::CSVPassword(const ColumnMap& map, base::StringPiece csv_row)
+ : map_(map), row_(csv_row) {}
CSVPassword::~CSVPassword() = default;
@@ -84,8 +87,8 @@ bool CSVPassword::Parse(PasswordForm* form) const {
? origin.spec()
: origin.GetOrigin().spec();
form->origin = std::move(origin);
- form->username_value = base::UTF8ToUTF16(username);
- form->password_value = base::UTF8ToUTF16(password);
+ form->username_value = Convert(username);
+ form->password_value = Convert(password);
return true;
}
diff --git a/chromium/components/password_manager/core/browser/import/csv_password.h b/chromium/components/password_manager/core/browser/import/csv_password.h
index e36162d0cd7..e85ff9719cd 100644
--- a/chromium/components/password_manager/core/browser/import/csv_password.h
+++ b/chromium/components/password_manager/core/browser/import/csv_password.h
@@ -24,12 +24,11 @@ class CSVPassword {
// Number of values in the Label enum.
static constexpr size_t kLabelCount = 3;
- CSVPassword();
- explicit CSVPassword(ColumnMap map, base::StringPiece csv_row);
- CSVPassword(const CSVPassword&);
- CSVPassword(CSVPassword&&);
- CSVPassword& operator=(const CSVPassword&);
- CSVPassword& operator=(CSVPassword&&);
+ explicit CSVPassword(const ColumnMap& map, base::StringPiece csv_row);
+ CSVPassword(const CSVPassword&) = delete;
+ CSVPassword(CSVPassword&&) = delete;
+ CSVPassword& operator=(const CSVPassword&) = delete;
+ CSVPassword& operator=(CSVPassword&&) = delete;
~CSVPassword();
// Returns whether the associated CSV row can be parsed successfully.
@@ -46,7 +45,7 @@ class CSVPassword {
// operator=().
// |map_| stores the meaning of particular columns in the row.
- ColumnMap map_;
+ const ColumnMap& map_;
// |row_| contains the CSV row from which the PasswordForm is parsed.
base::StringPiece row_;
};
diff --git a/chromium/components/password_manager/core/browser/import/csv_password_iterator.cc b/chromium/components/password_manager/core/browser/import/csv_password_iterator.cc
new file mode 100644
index 00000000000..6892ab8e635
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/import/csv_password_iterator.cc
@@ -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.
+
+#include "components/password_manager/core/browser/import/csv_password_iterator.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/template_util.h"
+
+namespace password_manager {
+
+namespace {
+
+// Returns all the characters from the start of |input| until the first '\n',
+// "\r\n" (exclusive) or the end of |input|. Cuts the returned part (inclusive
+// the line breaks) from |input|. Skips blocks of matching quotes. Examples:
+// old input -> returned value, new input
+// "ab\ncd" -> "ab", "cd"
+// "\r\n" -> "", ""
+// "abcd" -> "abcd", ""
+// "\r" -> "\r", ""
+// "a\"\n\"b" -> "a\"\n\"b", ""
+base::StringPiece ConsumeLine(base::StringPiece* input) {
+ DCHECK(input);
+ DCHECK(!input->empty());
+
+ bool inside_quotes = false;
+ bool last_char_was_CR = false;
+ for (size_t current = 0; current < input->size(); ++current) {
+ char c = (*input)[current];
+ switch (c) {
+ case '\n':
+ if (!inside_quotes) {
+ const size_t eol_start = last_char_was_CR ? current - 1 : current;
+ base::StringPiece ret = input->substr(0, eol_start);
+ *input = input->substr(current + 1);
+ return ret;
+ }
+ break;
+ case '"':
+ inside_quotes = !inside_quotes;
+ break;
+ default:
+ break;
+ }
+ last_char_was_CR = (c == '\r');
+ }
+
+ // The whole |*input| is one line.
+ return std::exchange(*input, base::StringPiece());
+}
+
+// Takes the |rest| of the CSV lines, returns the first one and stores the
+// remaining ones back in |rest|.
+base::StringPiece ExtractFirstRow(base::StringPiece* rest) {
+ DCHECK(rest);
+ if (!rest->empty())
+ return ConsumeLine(rest);
+ return base::StringPiece();
+}
+
+} // namespace
+
+CSVPasswordIterator::CSVPasswordIterator() = default;
+
+CSVPasswordIterator::CSVPasswordIterator(const CSVPassword::ColumnMap& map,
+ base::StringPiece csv)
+ : map_(&map),
+ csv_rest_(csv),
+ csv_row_(ExtractFirstRow(&csv_rest_)),
+ password_(base::in_place, map, csv_row_) {}
+
+CSVPasswordIterator::CSVPasswordIterator(const CSVPasswordIterator& other) {
+ *this = other;
+}
+
+CSVPasswordIterator& CSVPasswordIterator::operator=(
+ const CSVPasswordIterator& other) {
+ map_ = other.map_;
+ csv_rest_ = other.csv_rest_;
+ csv_row_ = other.csv_row_;
+ if (map_)
+ password_.emplace(*map_, csv_row_);
+ else
+ password_.reset();
+ return *this;
+}
+
+CSVPasswordIterator::~CSVPasswordIterator() = default;
+
+CSVPasswordIterator& CSVPasswordIterator::operator++() {
+ DCHECK(map_);
+ csv_row_ = ExtractFirstRow(&csv_rest_);
+ password_.emplace(*map_, csv_row_);
+ return *this;
+}
+
+CSVPasswordIterator CSVPasswordIterator::operator++(int) {
+ CSVPasswordIterator old = *this;
+ ++*this;
+ return old;
+}
+
+bool CSVPasswordIterator::operator==(const CSVPasswordIterator& other) const {
+ // There is no need to compare |password_|, because it is determined by |map_|
+ // and |csv_row_|.
+ return
+ // Checking StringPiece::data() equality instead of just StringPiece has
+ // two reasons: (1) flagging the case when, e.g., two identical lines in
+ // one CSV blob would otherwise cause the corresponding iterators look the
+ // same, and (2) efficiency. StringPiece::size() is not checked on the
+ // assumption that always the whole row is contained in |csv_row_|.
+ csv_row_.data() == other.csv_row_.data() &&
+ // The column map should reference the same map if the iterators come from
+ // the same sequence, and iterators from different sequences are not
+ // considered equal. Therefore the maps' addresses are checked instead of
+ // their contents.
+ map_ == other.map_;
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/import/csv_password_iterator.h b/chromium/components/password_manager/core/browser/import/csv_password_iterator.h
new file mode 100644
index 00000000000..65bc400be6f
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/import/csv_password_iterator.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_CSV_PASSWORD_ITERATOR_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_CSV_PASSWORD_ITERATOR_H_
+
+#include <stddef.h>
+
+#include <iterator>
+
+#include "base/optional.h"
+#include "base/strings/string_piece.h"
+#include "components/password_manager/core/browser/import/csv_password.h"
+
+namespace password_manager {
+
+// CSVPasswordIterator abstracts reading a CSV text line by line by creating
+// and providing a CSVPassword for each line. For more details, see
+// https://docs.google.com/document/d/1wsZBl93S_WGaXZqrqq5SP08LVZ0zDKf6e9nlptyl9AY/edit?usp=sharing.
+class CSVPasswordIterator {
+ public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = CSVPassword;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const value_type*;
+ using reference = const value_type&;
+
+ CSVPasswordIterator();
+ explicit CSVPasswordIterator(const CSVPassword::ColumnMap& map,
+ base::StringPiece csv);
+ CSVPasswordIterator(const CSVPasswordIterator&);
+ CSVPasswordIterator& operator=(const CSVPasswordIterator&);
+ ~CSVPasswordIterator();
+
+ reference operator*() const {
+ DCHECK(password_);
+ return *password_;
+ }
+ pointer operator->() const { return &**this; }
+
+ CSVPasswordIterator& operator++();
+ CSVPasswordIterator operator++(int);
+
+ // Defining comparison as methods rather than non-member functions, because
+ // while the latter allows implicit conversions on the lhs argument as well,
+ // there are no implicit conversions available for CSVPasswordIterator, and
+ // the methods avoid having to declare the operators as friends.
+ bool operator==(const CSVPasswordIterator& other) const;
+ bool operator!=(const CSVPasswordIterator& other) const {
+ return !(*this == other);
+ }
+
+ private:
+ // |map_| stores the meaning of particular columns in the row.
+ const CSVPassword::ColumnMap* map_ = nullptr;
+ // |csv_rest_| contains the CSV lines left to be iterated over.
+ base::StringPiece csv_rest_;
+ // |csv_row_| contains the CSV row which the iterator points at.
+ base::StringPiece csv_row_;
+ // Contains a CSVPassword created from |map_| and |csv_row_| if possible.
+ base::Optional<CSVPassword> password_;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_CSV_PASSWORD_ITERATOR_H_
diff --git a/chromium/components/password_manager/core/browser/import/csv_password_iterator_unittest.cc b/chromium/components/password_manager/core/browser/import/csv_password_iterator_unittest.cc
new file mode 100644
index 00000000000..b9e727a575c
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/import/csv_password_iterator_unittest.cc
@@ -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.
+
+#include "components/password_manager/core/browser/import/csv_password_iterator.h"
+
+#include <string>
+#include <utility>
+
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+
+using ::autofill::PasswordForm;
+
+TEST(CSVPasswordIteratorTest, Operations) {
+ // Default.
+ CSVPasswordIterator def;
+ EXPECT_EQ(def, def);
+
+ // From CSV.
+ const CSVPassword::ColumnMap kColMap = {
+ {0, CSVPassword::Label::kOrigin},
+ {1, CSVPassword::Label::kUsername},
+ {2, CSVPassword::Label::kPassword},
+ };
+ constexpr base::StringPiece kCSV = "http://example.com,user,password";
+ CSVPasswordIterator iter(kColMap, kCSV);
+ // Because kCSV is just one row, it can be used to create a CSVPassword
+ // directly.
+ EXPECT_EQ(iter->ParseValid(), CSVPassword(kColMap, kCSV).ParseValid());
+
+ // Copy.
+ CSVPasswordIterator copy = iter;
+ EXPECT_EQ(copy, iter);
+
+ // Assignment.
+ CSVPasswordIterator target;
+ target = iter;
+ EXPECT_EQ(target, iter);
+ copy = def;
+ EXPECT_EQ(copy, def);
+
+ // More of equality and increment.
+ CSVPasswordIterator dummy;
+ EXPECT_NE(dummy, iter);
+ CSVPasswordIterator same_as_iter(kColMap, kCSV);
+ EXPECT_EQ(same_as_iter, iter);
+ const std::string kCSVCopy(kCSV);
+ CSVPasswordIterator same_looking(kColMap, kCSVCopy);
+ EXPECT_NE(same_looking, iter);
+ CSVPasswordIterator old = iter++;
+ EXPECT_NE(old, iter);
+ EXPECT_EQ(++old, iter);
+}
+
+TEST(CSVPasswordIteratorTest, Success) {
+ const CSVPassword::ColumnMap kColMap = {
+ {0, CSVPassword::Label::kOrigin},
+ {1, CSVPassword::Label::kUsername},
+ {2, CSVPassword::Label::kPassword},
+ };
+ constexpr base::StringPiece kCSVBlob =
+ "http://example.com,u1,p1\n"
+ "http://example.com,u2,p2\r\n"
+ "http://example.com,u3,p\r\r\n"
+ "http://example.com,\"u\n4\",\"p\n4\"\n"
+ "http://example.com,u5,p5";
+ constexpr base::StringPiece kExpectedPasswords[] = {"p1", "p2", "p\r", "p\n4",
+ "p5"};
+
+ CSVPasswordIterator iter(kColMap, kCSVBlob);
+
+ CSVPasswordIterator check = iter;
+ for (size_t i = 0; i < base::size(kExpectedPasswords); ++i) {
+ EXPECT_TRUE((check++)->Parse(nullptr)) << "on line " << i;
+ }
+ EXPECT_FALSE(check->Parse(nullptr));
+
+ for (const base::StringPiece& expected_password : kExpectedPasswords) {
+ PasswordForm result = (iter++)->ParseValid();
+ // Detailed checks of the parsed result are made in the test for
+ // CSVPassword. Here only the last field (password) is checked to (1) ensure
+ // that lines are processed in the expected sequence, and (2) line breaks
+ // are handled as expected (in particular, '\r' alone is not a line break).
+ EXPECT_EQ(base::ASCIIToUTF16(expected_password), result.password_value);
+ }
+}
+
+TEST(CSVPasswordIteratorTest, Failure) {
+ const CSVPassword::ColumnMap kColMap = {
+ {0, CSVPassword::Label::kOrigin},
+ {1, CSVPassword::Label::kUsername},
+ {2, CSVPassword::Label::kPassword},
+ };
+ constexpr base::StringPiece kCSVBlob =
+ "too few fields\n"
+ "http://example.com,\"\"trailing,p\n"
+ "http://notascii.ž.com,u,p\n"
+ "http://example.com,empty-password,\n"
+ "http://no-failure.example.com,to check that,operator++ worked";
+ constexpr size_t kLinesInBlob = 5;
+
+ CSVPasswordIterator iter(kColMap, kCSVBlob);
+
+ CSVPasswordIterator check = iter;
+ for (size_t i = 0; i + 1 < kLinesInBlob; ++i) {
+ EXPECT_FALSE((check++)->Parse(nullptr)) << "on line " << i;
+ }
+ // Last line was not a failure.
+ EXPECT_TRUE((check++)->Parse(nullptr));
+ // After iterating over all lines, there is no more data to parse.
+ EXPECT_FALSE(check->Parse(nullptr));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/import/csv_password_unittest.cc b/chromium/components/password_manager/core/browser/import/csv_password_unittest.cc
index df6970bbb1a..03a19ede0db 100644
--- a/chromium/components/password_manager/core/browser/import/csv_password_unittest.cc
+++ b/chromium/components/password_manager/core/browser/import/csv_password_unittest.cc
@@ -15,11 +15,6 @@ namespace password_manager {
using ::autofill::PasswordForm;
TEST(CSVPassword, Construction) {
- // Default.
- CSVPassword empty;
- EXPECT_FALSE(empty.Parse(nullptr));
-
- // From CSV.
CSVPassword::ColumnMap col_map = {
{0, CSVPassword::Label::kOrigin},
{1, CSVPassword::Label::kUsername},
@@ -32,19 +27,6 @@ TEST(CSVPassword, Construction) {
EXPECT_EQ(expected_origin.GetOrigin().spec(), result.signon_realm);
EXPECT_EQ(base::ASCIIToUTF16("user"), result.username_value);
EXPECT_EQ(base::ASCIIToUTF16("password"), result.password_value);
-
- // Copy, move and operator=.
- CSVPassword copy = csv_pwd;
- EXPECT_EQ(copy.ParseValid(), csv_pwd.ParseValid());
-
- CSVPassword moved = std::move(copy);
- EXPECT_EQ(moved.ParseValid(), csv_pwd.ParseValid());
-
- CSVPassword target;
- target = csv_pwd;
- EXPECT_EQ(target.ParseValid(), csv_pwd.ParseValid());
- target = std::move(moved);
- EXPECT_EQ(target.ParseValid(), csv_pwd.ParseValid());
}
struct TestCase {
@@ -165,6 +147,16 @@ INSTANTIATE_TEST_SUITE_P(
.Username("the-user")
.Password("pwd")
.Build(),
+ TestCaseBuilder("Escaped")
+ .Map({{0, CSVPassword::Label::kOrigin},
+ {2, CSVPassword::Label::kUsername},
+ {3, CSVPassword::Label::kPassword}})
+ .CSV(R"(http://example.org,"a""b","u,+,c","p""")")
+ .Origin("http://example.org")
+ .SignonRealm("http://example.org/")
+ .Username("u,+,c")
+ .Password("p\"")
+ .Build(),
TestCaseBuilder("path discarded")
.Map({{2, CSVPassword::Label::kOrigin},
{1, CSVPassword::Label::kUsername},
diff --git a/chromium/components/password_manager/core/browser/import/password_importer.cc b/chromium/components/password_manager/core/browser/import/password_importer.cc
index 9b45e711f9c..dcf08910dc5 100644
--- a/chromium/components/password_manager/core/browser/import/password_importer.cc
+++ b/chromium/components/password_manager/core/browser/import/password_importer.cc
@@ -49,8 +49,9 @@ void PasswordImporter::Import(const base::FilePath& path,
const CompletionCallback& completion) {
// Posting with USER_VISIBLE priority, because the result of the import is
// visible to the user in the password settings page.
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
base::Bind(&ReadFileToString, path),
base::Bind(&ParsePasswords, completion));
}
diff --git a/chromium/components/password_manager/core/browser/import/password_importer_unittest.cc b/chromium/components/password_manager/core/browser/import/password_importer_unittest.cc
index 48a632bd0c0..aaa93eaef08 100644
--- a/chromium/components/password_manager/core/browser/import/password_importer_unittest.cc
+++ b/chromium/components/password_manager/core/browser/import/password_importer_unittest.cc
@@ -9,7 +9,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/password_form.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +36,7 @@ class PasswordImporterTest : public testing::Test {
base::Bind(&PasswordImporterTest::OnImportFinished,
base::Unretained(this)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(callback_called_);
}
@@ -57,7 +57,7 @@ class PasswordImporterTest : public testing::Test {
base::ScopedTempDir temp_directory_;
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool callback_called_;
PasswordImporter::Result result_;
diff --git a/chromium/components/password_manager/core/browser/leak_detection/BUILD.gn b/chromium/components/password_manager/core/browser/leak_detection/BUILD.gn
index f724b334ff5..7c3dc539776 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/BUILD.gn
+++ b/chromium/components/password_manager/core/browser/leak_detection/BUILD.gn
@@ -11,8 +11,93 @@ fuzzable_proto_library("proto") {
]
}
+source_set("leak_detection_interface_headers") {
+ sources = [
+ "leak_detection_check.h",
+ "leak_detection_check_factory.h",
+ "leak_detection_delegate_interface.h",
+ ]
+ deps = [
+ "//base",
+ "//url",
+ ]
+}
+
jumbo_source_set("leak_detection") {
+ sources = [
+ "authenticated_leak_check.cc",
+ "authenticated_leak_check.h",
+ "encryption_utils.cc",
+ "encryption_utils.h",
+ "leak_detection_check.h",
+ "leak_detection_check_factory.h",
+ "leak_detection_check_factory_impl.cc",
+ "leak_detection_check_factory_impl.h",
+ "leak_detection_request.cc",
+ "leak_detection_request.h",
+ "leak_detection_request_factory.cc",
+ "leak_detection_request_factory.h",
+ "leak_detection_request_utils.cc",
+ "leak_detection_request_utils.h",
+ "single_lookup_response.cc",
+ "single_lookup_response.h",
+ ]
+
+ public_deps = [
+ ":leak_detection_interface_headers",
+ "//services/network/public/cpp",
+ ]
+
deps = [
":proto",
+ "//base",
+ "//components/password_manager/core/common",
+ "//components/signin/public/identity_manager",
+ "//third_party/private-join-and-compute/src:ec_commutative_cipher",
+ "//url",
+ ]
+}
+
+jumbo_source_set("test_support") {
+ testonly = true
+ sources = [
+ "mock_leak_detection_delegate.cc",
+ "mock_leak_detection_delegate.h",
+ ]
+ deps = [
+ ":leak_detection",
+ "//base/test:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
+
+jumbo_source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "authenticated_leak_check_unittest.cc",
+ "encryption_utils_unittest.cc",
+ "leak_detection_check_factory_impl_unittest.cc",
+ "leak_detection_request_unittest.cc",
+ "leak_detection_request_utils_unittest.cc",
+ ]
+
+ deps = [
+ ":leak_detection",
+ ":proto",
+ ":test_support",
+ "//base/test:test_support",
+ "//components/password_manager/core/common",
+ "//components/signin/public/identity_manager:test_support",
+ "//services/network:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/private-join-and-compute/src:ec_commutative_cipher",
+ ]
+}
+
+group("fuzzers") {
+ deps = [
+ "//components/password_manager/core/browser/leak_detection/fuzzer",
]
}
diff --git a/chromium/components/password_manager/core/browser/leak_detection/DEPS b/chromium/components/password_manager/core/browser/leak_detection/DEPS
new file mode 100644
index 00000000000..750a2990726
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+components/signin/public",
+ "+third_party/private-join-and-compute/src",
+]
diff --git a/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc b/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc
new file mode 100644
index 00000000000..040f9c895df
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc
@@ -0,0 +1,289 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/authenticated_leak_check.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/timer/elapsed_timer.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace password_manager {
+namespace {
+
+using ::signin::AccessTokenFetcher;
+
+constexpr char kAPIScope[] =
+ "https://www.googleapis.com/auth/identity.passwords.leak.check";
+
+// Returns a Google account that can be used for getting a token.
+CoreAccountId GetAccountForRequest(
+ const signin::IdentityManager* identity_manager) {
+ CoreAccountInfo result = identity_manager->GetUnconsentedPrimaryAccountInfo();
+ if (result.IsEmpty()) {
+ std::vector<CoreAccountInfo> all_accounts =
+ identity_manager->GetAccountsWithRefreshTokens();
+ if (!all_accounts.empty())
+ result = all_accounts.front();
+ }
+ return result.account_id;
+}
+
+// Wraps |callback| into another callback that measures the elapsed time between
+// construction and actual execution of the callback. Records the result to
+// |histogram|, which is expected to be a char literal.
+template <typename R, typename... Args>
+base::OnceCallback<R(Args...)> TimeCallback(
+ base::OnceCallback<R(Args...)> callback,
+ const char* histogram) {
+ return base::BindOnce(
+ [](const char* histogram, const base::ElapsedTimer& timer,
+ base::OnceCallback<R(Args...)> callback, Args... args) {
+ base::UmaHistogramTimes(histogram, timer.Elapsed());
+ return std::move(callback).Run(std::forward<Args>(args)...);
+ },
+ histogram, base::ElapsedTimer(), std::move(callback));
+}
+
+} // namespace
+
+// Incapsulates the token request and payload calculation done in parallel.
+class AuthenticatedLeakCheck::RequestPayloadHelper {
+ public:
+ RequestPayloadHelper(
+ AuthenticatedLeakCheck* leak_check,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+ ~RequestPayloadHelper() = default;
+
+ // Neither copyable nor movable.
+ RequestPayloadHelper(const RequestPayloadHelper&) = delete;
+ RequestPayloadHelper& operator=(const RequestPayloadHelper&) = delete;
+ RequestPayloadHelper(RequestPayloadHelper&&) = delete;
+ RequestPayloadHelper& operator=(RequestPayloadHelper&&) = delete;
+
+ void RequestAccessToken(AccessTokenFetcher::TokenCallback callback);
+ void PreparePayload(const std::string& username,
+ const std::string& password,
+ SingleLeakRequestDataCallback callback);
+
+ // Notifies that the access token was obtained.
+ void OnGotAccessToken(std::string access_token);
+
+ // Notifies that the payload was obtained.
+ void OnGotPayload(LookupSingleLeakData data);
+
+ private:
+ // Describes the steps done in parallel as a bit mask.
+ enum Step {
+ kPayloadData = 1 << 0,
+ kAccessToken = 1 << 1,
+ kAll = kPayloadData | kAccessToken
+ };
+
+ // If both the access token and the payload are ready notify |leak_check_|.
+ void CheckAllStepsDone();
+
+ // Bitmask of steps done.
+ int steps_ = 0;
+ // Owns |this|.
+ AuthenticatedLeakCheck* leak_check_;
+ // Identity manager for the profile.
+ signin::IdentityManager* identity_manager_;
+ // URL loader factory required for the network request to the identity
+ // endpoint.
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+ // Actual request for the needed token.
+ std::unique_ptr<signin::AccessTokenFetcher> token_fetcher_;
+ // The token to be used for request.
+ std::string access_token_;
+ // Payload for the actual request.
+ LookupSingleLeakData payload_;
+};
+
+AuthenticatedLeakCheck::RequestPayloadHelper::RequestPayloadHelper(
+ AuthenticatedLeakCheck* leak_check,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : leak_check_(leak_check),
+ identity_manager_(identity_manager),
+ url_loader_factory_(std::move(url_loader_factory)) {
+ DCHECK(identity_manager_);
+ DCHECK(url_loader_factory_);
+}
+
+void AuthenticatedLeakCheck::RequestPayloadHelper::RequestAccessToken(
+ AccessTokenFetcher::TokenCallback callback) {
+ token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
+ GetAccountForRequest(identity_manager_),
+ /*consumer_name=*/"leak_detection_service", {kAPIScope},
+ std::move(callback), signin::AccessTokenFetcher::Mode::kImmediate);
+}
+
+void AuthenticatedLeakCheck::RequestPayloadHelper::PreparePayload(
+ const std::string& username,
+ const std::string& password,
+ SingleLeakRequestDataCallback callback) {
+ PrepareSingleLeakRequestData(username, password, std::move(callback));
+}
+
+void AuthenticatedLeakCheck::RequestPayloadHelper::OnGotAccessToken(
+ std::string access_token) {
+ access_token_ = std::move(access_token);
+ steps_ |= kAccessToken;
+ token_fetcher_.reset();
+
+ CheckAllStepsDone();
+}
+
+void AuthenticatedLeakCheck::RequestPayloadHelper::OnGotPayload(
+ LookupSingleLeakData data) {
+ payload_ = std::move(data);
+ steps_ |= kPayloadData;
+
+ CheckAllStepsDone();
+}
+
+void AuthenticatedLeakCheck::RequestPayloadHelper::CheckAllStepsDone() {
+ if (steps_ == kAll) {
+ leak_check_->DoLeakRequest(std::move(payload_), std::move(access_token_),
+ std::move(url_loader_factory_));
+ }
+}
+
+AuthenticatedLeakCheck::AuthenticatedLeakCheck(
+ LeakDetectionDelegateInterface* delegate,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : delegate_(delegate),
+ payload_helper_(new RequestPayloadHelper(this,
+ identity_manager,
+ std::move(url_loader_factory))),
+ network_request_factory_(
+ std::make_unique<LeakDetectionRequestFactory>()) {
+ DCHECK(delegate_);
+}
+
+AuthenticatedLeakCheck::~AuthenticatedLeakCheck() = default;
+
+// static
+bool AuthenticatedLeakCheck::HasAccountForRequest(
+ const signin::IdentityManager* identity_manager) {
+ // On desktop HasUnconsentedPrimaryAccount() will always return something if
+ // the user is signed in.
+ // On Android it will be empty if the user isn't syncing. Thus,
+ // GetAccountsWithRefreshTokens() check is necessary.
+ return identity_manager &&
+ (identity_manager->HasUnconsentedPrimaryAccount() ||
+ !identity_manager->GetAccountsWithRefreshTokens().empty());
+}
+
+void AuthenticatedLeakCheck::Start(const GURL& url,
+ base::string16 username,
+ base::string16 password) {
+ DCHECK(payload_helper_);
+ DCHECK(!request_);
+
+ url_ = url;
+ username_ = std::move(username);
+ password_ = std::move(password);
+ payload_helper_->RequestAccessToken(TimeCallback(
+ base::BindOnce(&AuthenticatedLeakCheck::OnAccessTokenRequestCompleted,
+ weak_ptr_factory_.GetWeakPtr()),
+ "PasswordManager.LeakDetection.ObtainAccessTokenTime"));
+ payload_helper_->PreparePayload(
+ base::UTF16ToUTF8(username_), base::UTF16ToUTF8(password_),
+ TimeCallback(
+ base::BindOnce(&AuthenticatedLeakCheck::OnRequestDataReady,
+ weak_ptr_factory_.GetWeakPtr()),
+ "PasswordManager.LeakDetection.PrepareSingleLeakRequestTime"));
+}
+
+void AuthenticatedLeakCheck::OnAccessTokenRequestCompleted(
+ GoogleServiceAuthError error,
+ signin::AccessTokenInfo access_token_info) {
+ base::UmaHistogramEnumeration(
+ "PasswordManager.LeakDetection.AccessTokenFetchStatus", error.state(),
+ GoogleServiceAuthError::NUM_STATES);
+ if (error.state() != GoogleServiceAuthError::NONE) {
+ // Network error codes are negative. See: src/net/base/net_error_list.h.
+ base::UmaHistogramSparse(
+ "PasswordManager.LeakDetection.AccessTokenNetErrorCode",
+ -error.network_error());
+ DLOG(ERROR) << "Token request error: " << error.error_message();
+ delegate_->OnError(LeakDetectionError::kTokenRequestFailure);
+ return;
+ }
+
+ // The fetcher successfully obtained an access token.
+ DVLOG(0) << "Token=" << access_token_info.token;
+ payload_helper_->OnGotAccessToken(std::move(access_token_info.token));
+}
+
+void AuthenticatedLeakCheck::OnRequestDataReady(LookupSingleLeakData data) {
+ if (data.encryption_key.empty()) {
+ DLOG(ERROR) << "Preparing the payload for leak detection failed";
+ delegate_->OnError(LeakDetectionError::kHashingFailure);
+ return;
+ }
+ payload_helper_->OnGotPayload(std::move(data));
+}
+
+void AuthenticatedLeakCheck::DoLeakRequest(
+ LookupSingleLeakData data,
+ std::string access_token,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+ payload_helper_.reset();
+ encryption_key_ = std::move(data.encryption_key);
+ request_ = network_request_factory_->CreateNetworkRequest();
+ request_->LookupSingleLeak(
+ url_loader_factory.get(), access_token,
+ std::move(data.username_hash_prefix), std::move(data.encrypted_payload),
+ TimeCallback(
+ base::BindOnce(&AuthenticatedLeakCheck::OnLookupSingleLeakResponse,
+ weak_ptr_factory_.GetWeakPtr()),
+ "PasswordManager.LeakDetection.ReceiveSingleLeakResponseTime"));
+}
+
+void AuthenticatedLeakCheck::OnLookupSingleLeakResponse(
+ std::unique_ptr<SingleLookupResponse> response) {
+ request_.reset();
+ if (!response) {
+ delegate_->OnError(LeakDetectionError::kInvalidServerResponse);
+ return;
+ }
+
+ DVLOG(0) << "Leak check: number of matching encrypted prefixes="
+ << response->encrypted_leak_match_prefixes.size();
+
+ AnalyzeResponse(
+ std::move(response), encryption_key_,
+ TimeCallback(
+ base::BindOnce(&AuthenticatedLeakCheck::OnAnalyzeSingleLeakResponse,
+ weak_ptr_factory_.GetWeakPtr()),
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseTime"));
+}
+
+void AuthenticatedLeakCheck::OnAnalyzeSingleLeakResponse(
+ AnalyzeResponseResult result) {
+ base::UmaHistogramEnumeration(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseResult", result);
+ const bool is_leaked = result == AnalyzeResponseResult::kLeaked;
+ DVLOG(0) << "Leak check result=" << is_leaked;
+ delegate_->OnLeakDetectionDone(is_leaked, std::move(url_),
+ std::move(username_), std::move(password_));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h b/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h
new file mode 100644
index 00000000000..e29a0a40425
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h
@@ -0,0 +1,110 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_AUTHENTICATED_LEAK_CHECK_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_AUTHENTICATED_LEAK_CHECK_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
+#include "url/gurl.h"
+
+class GoogleServiceAuthError;
+
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+
+namespace signin {
+struct AccessTokenInfo;
+class IdentityManager;
+} // namespace signin
+
+namespace password_manager {
+
+enum class AnalyzeResponseResult;
+class LeakDetectionDelegateInterface;
+struct LookupSingleLeakData;
+struct SingleLookupResponse;
+
+// Performs a leak-check for {username, password} for Chrome signed-in users.
+class AuthenticatedLeakCheck : public LeakDetectionCheck {
+ public:
+ AuthenticatedLeakCheck(
+ LeakDetectionDelegateInterface* delegate,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+ ~AuthenticatedLeakCheck() override;
+
+ // Returns true if there is a Google account to use for the leak detection
+ // check. Otherwise, instantiating the class is pointless.
+ static bool HasAccountForRequest(
+ const signin::IdentityManager* identity_manager);
+
+ // LeakDetectionCheck:
+ void Start(const GURL& url,
+ base::string16 username,
+ base::string16 password) override;
+
+#if defined(UNIT_TEST)
+ void set_network_factory(
+ std::unique_ptr<LeakDetectionRequestFactory> factory) {
+ network_request_factory_ = std::move(factory);
+ }
+#endif // defined(UNIT_TEST)
+
+ private:
+ class RequestPayloadHelper;
+
+ // Called when the token request is done.
+ void OnAccessTokenRequestCompleted(GoogleServiceAuthError error,
+ signin::AccessTokenInfo access_token_info);
+
+ // Called when the payload for the request is precomputed.
+ void OnRequestDataReady(LookupSingleLeakData data);
+
+ // Does the network request to check the credentials.
+ void DoLeakRequest(
+ LookupSingleLeakData data,
+ std::string access_token,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
+ // Called when the single leak lookup request is done. |response| is null in
+ // case of an invalid server response, or contains a valid
+ // SingleLookupResponse instance otherwise.
+ void OnLookupSingleLeakResponse(
+ std::unique_ptr<SingleLookupResponse> response);
+
+ // Called when the network response is analazyed on the background thread. The
+ // method is called on the main thread.
+ void OnAnalyzeSingleLeakResponse(AnalyzeResponseResult result);
+
+ // Delegate for the instance. Should outlive |this|.
+ LeakDetectionDelegateInterface* const delegate_;
+ // Helper class to asynchronously prepare the data for the request.
+ std::unique_ptr<RequestPayloadHelper> payload_helper_;
+ // Class used to initiate a request to the identity leak lookup endpoint. This
+ // is only instantiated if a valid |access_token_| could be obtained.
+ std::unique_ptr<LeakDetectionRequestInterface> request_;
+ // A factory for creating a |request_|.
+ std::unique_ptr<LeakDetectionRequestFactory> network_request_factory_;
+ // |url| passed to Start().
+ GURL url_;
+ // |username| passed to Start().
+ base::string16 username_;
+ // |password| passed to Start().
+ base::string16 password_;
+ // Encryption key used during the request.
+ std::string encryption_key_;
+ // Weak pointers for different callbacks.
+ base::WeakPtrFactory<AuthenticatedLeakCheck> weak_ptr_factory_{this};
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_AUTHENTICATED_LEAK_CHECK_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
new file mode 100644
index 00000000000..c23a406c94f
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
@@ -0,0 +1,369 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/authenticated_leak_check.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/task_environment.h"
+#include "base/timer/elapsed_timer.h"
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "crypto/sha2.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/test/test_shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+namespace {
+
+using ::testing::_;
+using ::testing::ByMove;
+using ::testing::ElementsAre;
+using ::testing::Return;
+using ::testing::StrictMock;
+
+constexpr char kTestEmail[] = "user@gmail.com";
+constexpr char kUsername[] = "USERNAME@gmail.com";
+constexpr char kPassword[] = "password123";
+constexpr char kExampleCom[] = "https://example.com";
+
+const int64_t kMockElapsedTime =
+ base::ScopedMockElapsedTimersForTest::kMockElapsedTime.InMilliseconds();
+
+class MockLeakDetectionRequest : public LeakDetectionRequestInterface {
+ public:
+ // LeakDetectionRequestInterface:
+ MOCK_METHOD5(LookupSingleLeak,
+ void(network::mojom::URLLoaderFactory*,
+ const std::string&,
+ std::string,
+ std::string,
+ LookupSingleLeakCallback));
+};
+
+struct TestLeakDetectionRequest : public LeakDetectionRequestInterface {
+ ~TestLeakDetectionRequest() override = default;
+ // LeakDetectionRequestInterface:
+ void LookupSingleLeak(network::mojom::URLLoaderFactory* url_loader_factory,
+ const std::string& access_token,
+ std::string username_hash_prefix,
+ std::string encrypted_payload,
+ LookupSingleLeakCallback callback) override {
+ encrypted_payload_ = std::move(encrypted_payload);
+ callback_ = std::move(callback);
+ }
+
+ std::string encrypted_payload_;
+ LookupSingleLeakCallback callback_;
+};
+
+class MockLeakDetectionRequestFactory : public LeakDetectionRequestFactory {
+ public:
+ // LeakDetectionRequestFactory:
+ MOCK_CONST_METHOD0(CreateNetworkRequest,
+ std::unique_ptr<LeakDetectionRequestInterface>());
+};
+
+// Helper struct for making a fake network request.
+struct PayloadAndCallback {
+ std::string payload;
+ LeakDetectionRequestInterface::LookupSingleLeakCallback callback;
+};
+
+class AuthenticatedLeakCheckTest : public testing::Test {
+ public:
+ AuthenticatedLeakCheckTest()
+ : leak_check_(
+ &delegate_,
+ identity_test_env_.identity_manager(),
+ base::MakeRefCounted<network::TestSharedURLLoaderFactory>()) {
+ auto mock_request_factory =
+ std::make_unique<StrictMock<MockLeakDetectionRequestFactory>>();
+ request_factory_ = mock_request_factory.get();
+ leak_check_.set_network_factory(std::move(mock_request_factory));
+ }
+ ~AuthenticatedLeakCheckTest() override = default;
+
+ base::test::TaskEnvironment& task_env() { return task_env_; }
+ signin::IdentityTestEnvironment& identity_env() { return identity_test_env_; }
+ MockLeakDetectionDelegateInterface& delegate() { return delegate_; }
+ MockLeakDetectionRequestFactory* request_factory() {
+ return request_factory_;
+ }
+ base::HistogramTester& histogram_tester() { return histogram_tester_; }
+ AuthenticatedLeakCheck& leak_check() { return leak_check_; }
+
+ // Brings |leak_check_| to the state right after the network request.
+ // The check is done for |kUsername|/|kPassword| credential on |kExampleCom|.
+ // Returns |encrypted_payload| and |callback| arguments of LookupSingleLeak().
+ PayloadAndCallback ImitateNetworkRequest();
+
+ private:
+ base::test::TaskEnvironment task_env_;
+ signin::IdentityTestEnvironment identity_test_env_;
+ StrictMock<MockLeakDetectionDelegateInterface> delegate_;
+ MockLeakDetectionRequestFactory* request_factory_;
+ base::HistogramTester histogram_tester_;
+ base::ScopedMockElapsedTimersForTest mock_elapsed_timers_;
+ AuthenticatedLeakCheck leak_check_;
+};
+
+PayloadAndCallback AuthenticatedLeakCheckTest::ImitateNetworkRequest() {
+ AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+ identity_env().SetCookieAccounts({{info.email, info.account_id}});
+ identity_env().SetRefreshTokenForAccount(info.account_id);
+
+ leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword));
+ // Crypto stuff is done here.
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.PrepareSingleLeakRequestTime",
+ kMockElapsedTime, 1);
+
+ static constexpr char access_token[] = "access_token";
+ auto network_request = std::make_unique<TestLeakDetectionRequest>();
+ TestLeakDetectionRequest* raw_request = network_request.get();
+ EXPECT_CALL(*request_factory(), CreateNetworkRequest)
+ .WillOnce(Return(ByMove(std::move(network_request))));
+
+ // Return the access token.
+ identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token, base::Time::Max());
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ObtainAccessTokenTime", kMockElapsedTime,
+ 1);
+
+ return {std::move(raw_request->encrypted_payload_),
+ std::move(raw_request->callback_)};
+}
+
+} // namespace
+
+TEST_F(AuthenticatedLeakCheckTest, Create) {
+ EXPECT_CALL(delegate(), OnLeakDetectionDone).Times(0);
+ EXPECT_CALL(delegate(), OnError).Times(0);
+ // Destroying |leak_check_| doesn't trigger anything.
+}
+
+TEST_F(AuthenticatedLeakCheckTest, HasAccountForRequest_SignedIn) {
+ AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+ identity_env().SetCookieAccounts({{info.email, info.account_id}});
+ identity_env().SetRefreshTokenForAccount(info.account_id);
+ EXPECT_TRUE(AuthenticatedLeakCheck::HasAccountForRequest(
+ identity_env().identity_manager()));
+}
+
+TEST_F(AuthenticatedLeakCheckTest, HasAccountForRequest_Syncing) {
+ identity_env().SetPrimaryAccount(kTestEmail);
+ EXPECT_TRUE(AuthenticatedLeakCheck::HasAccountForRequest(
+ identity_env().identity_manager()));
+}
+
+TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenBeforeEncryption) {
+ AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+ identity_env().SetCookieAccounts({{info.email, info.account_id}});
+ identity_env().SetRefreshTokenForAccount(info.account_id);
+ const std::string access_token = "access_token";
+
+ leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword));
+ // Return the access token before the crypto stuff is done.
+ identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token, base::Time::Max());
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ObtainAccessTokenTime", kMockElapsedTime,
+ 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AccessTokenFetchStatus",
+ GoogleServiceAuthError::NONE, 1);
+
+ auto network_request = std::make_unique<MockLeakDetectionRequest>();
+ EXPECT_CALL(*network_request,
+ LookupSingleLeak(_, access_token, ElementsAre(-67, 116, -87),
+ testing::Ne(""), _));
+ EXPECT_CALL(*request_factory(), CreateNetworkRequest)
+ .WillOnce(Return(ByMove(std::move(network_request))));
+ // Crypto stuff is done here.
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.PrepareSingleLeakRequestTime",
+ kMockElapsedTime, 1);
+}
+
+TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenAfterEncryption) {
+ AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+ identity_env().SetCookieAccounts({{info.email, info.account_id}});
+ identity_env().SetRefreshTokenForAccount(info.account_id);
+
+ leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword));
+ // crypto stuff is done here.
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.PrepareSingleLeakRequestTime",
+ kMockElapsedTime, 1);
+
+ const std::string access_token = "access_token";
+ auto network_request = std::make_unique<MockLeakDetectionRequest>();
+ EXPECT_CALL(*network_request,
+ LookupSingleLeak(_, access_token, ElementsAre(-67, 116, -87),
+ testing::Ne(""), _));
+ EXPECT_CALL(*request_factory(), CreateNetworkRequest)
+ .WillOnce(Return(ByMove(std::move(network_request))));
+
+ // Return the access token.
+ identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ access_token, base::Time::Max());
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ObtainAccessTokenTime", kMockElapsedTime,
+ 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AccessTokenFetchStatus",
+ GoogleServiceAuthError::NONE, 1);
+}
+
+TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenFailure) {
+ AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+ identity_env().SetCookieAccounts({{info.email, info.account_id}});
+ identity_env().SetRefreshTokenForAccount(info.account_id);
+
+ leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword));
+
+ EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure));
+ identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ObtainAccessTokenTime", kMockElapsedTime,
+ 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AccessTokenFetchStatus",
+ GoogleServiceAuthError::CONNECTION_FAILED, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AccessTokenNetErrorCode", -net::ERR_FAILED,
+ 1);
+}
+
+// Perform the whole cycle of a leak check. The server returns data that
+// can't be decrypted.
+TEST_F(AuthenticatedLeakCheckTest, ParseResponse_DecryptionError) {
+ PayloadAndCallback payload_and_callback = ImitateNetworkRequest();
+ ASSERT_TRUE(!payload_and_callback.payload.empty());
+
+ auto response = std::make_unique<SingleLookupResponse>();
+ std::string key_server;
+ // Append trash bytes to force a decryption error.
+ response->reencrypted_lookup_hash =
+ CipherReEncrypt(payload_and_callback.payload, &key_server) +
+ "trash_bytes";
+ response->encrypted_leak_match_prefixes.push_back(
+ crypto::SHA256HashString(CipherEncryptWithKey(
+ ScryptHashUsernameAndPassword("another_username", kPassword),
+ key_server)));
+
+ EXPECT_CALL(delegate(), OnLeakDetectionDone(false, GURL(kExampleCom),
+ base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword)));
+ std::move(payload_and_callback.callback).Run(std::move(response));
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseResult",
+ AnalyzeResponseResult::kDecryptionError, 1);
+ // Expect one sample for each of the response time histograms.
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ReceiveSingleLeakResponseTime",
+ kMockElapsedTime, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseTime",
+ kMockElapsedTime, 1);
+}
+// Perform the whole cycle of a leak check. The server returns data signalling
+// that the password wasn't leaked.
+TEST_F(AuthenticatedLeakCheckTest, ParseResponse_NoLeak) {
+ PayloadAndCallback payload_and_callback = ImitateNetworkRequest();
+ ASSERT_TRUE(!payload_and_callback.payload.empty());
+
+ auto response = std::make_unique<SingleLookupResponse>();
+ std::string key_server;
+ response->reencrypted_lookup_hash =
+ CipherReEncrypt(payload_and_callback.payload, &key_server);
+ response->encrypted_leak_match_prefixes.push_back(
+ crypto::SHA256HashString(CipherEncryptWithKey(
+ ScryptHashUsernameAndPassword("another_username", kPassword),
+ key_server)));
+
+ EXPECT_CALL(delegate(), OnLeakDetectionDone(false, GURL(kExampleCom),
+ base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword)));
+ std::move(payload_and_callback.callback).Run(std::move(response));
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseResult",
+ AnalyzeResponseResult::kNotLeaked, 1);
+ // Expect one sample for each of the response time histograms.
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ReceiveSingleLeakResponseTime",
+ kMockElapsedTime, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseTime",
+ kMockElapsedTime, 1);
+}
+
+// Perform the whole cycle of a leak check. The server returns data signalling
+// that the password was leaked.
+TEST_F(AuthenticatedLeakCheckTest, ParseResponse_Leak) {
+ PayloadAndCallback payload_and_callback = ImitateNetworkRequest();
+ ASSERT_TRUE(!payload_and_callback.payload.empty());
+
+ // |canonicalized_username| is passed to ScryptHashUsernameAndPassword() to
+ // make sure the canonicalization logic works correctly. Assert that
+ // CanonicalizeUsername() was not a no-op.
+ std::string canonicalized_username = CanonicalizeUsername(kUsername);
+ ASSERT_NE(kUsername, canonicalized_username);
+
+ auto response = std::make_unique<SingleLookupResponse>();
+ std::string key_server;
+ response->reencrypted_lookup_hash =
+ CipherReEncrypt(payload_and_callback.payload, &key_server);
+ response->encrypted_leak_match_prefixes.push_back(
+ crypto::SHA256HashString(CipherEncryptWithKey(
+ ScryptHashUsernameAndPassword(canonicalized_username, kPassword),
+ key_server)));
+
+ EXPECT_CALL(delegate(), OnLeakDetectionDone(true, GURL(kExampleCom),
+ base::ASCIIToUTF16(kUsername),
+ base::ASCIIToUTF16(kPassword)));
+ std::move(payload_and_callback.callback).Run(std::move(response));
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseResult",
+ AnalyzeResponseResult::kLeaked, 1);
+ // Expect one sample for each of the response time histograms.
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.ReceiveSingleLeakResponseTime",
+ kMockElapsedTime, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.AnalyzeSingleLeakResponseTime",
+ kMockElapsedTime, 1);
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc
new file mode 100644
index 00000000000..36da42d4db0
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc
@@ -0,0 +1,141 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+
+#include <climits>
+
+#include "base/stl_util.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "crypto/openssl_util.h"
+#include "crypto/sha2.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/nid.h"
+#include "third_party/private-join-and-compute/src/crypto/ec_commutative_cipher.h"
+
+namespace password_manager {
+
+std::string CanonicalizeUsername(base::StringPiece username) {
+ std::string email_lower = base::ToLowerASCII(username);
+ // |email_lower| might be an email address. Strip off the mail-address host,
+ // remove periods from the username and return the result.
+ std::string user_lower = email_lower.substr(0, email_lower.find_last_of('@'));
+ base::RemoveChars(user_lower, ".", &user_lower);
+ return user_lower;
+}
+
+std::string HashUsername(base::StringPiece canonicalized_username) {
+ // Needs to stay in sync with server side constant: go/passwords-leak-salts
+ static constexpr char kUsernameSalt[] = {
+ -60, -108, -93, -107, -8, -64, -30, 62, -87, 35, 4,
+ 120, 112, 44, 114, 24, 86, 84, -103, -77, -23, 33,
+ 24, 108, 33, 26, 1, 34, 60, 69, 74, -6};
+
+ // Check that |canonicalized_username| is actually canonicalized.
+ // Note: We can't use CanonicalizeUsername() again, since it's not idempotent
+ // if multiple '@' signs are present in the initial username.
+ DCHECK_EQ(base::ToLowerASCII(canonicalized_username), canonicalized_username);
+ return crypto::SHA256HashString(base::StrCat(
+ {canonicalized_username,
+ base::StringPiece(kUsernameSalt, base::size(kUsernameSalt))}));
+}
+
+std::string BucketizeUsername(base::StringPiece canonicalized_username) {
+ static_assert(
+ kUsernameHashPrefixLength % CHAR_BIT == 0,
+ "The prefix length must be a multiple of the number of bits in a char.");
+
+ // Check that |canonicalized_username| is actually canonicalized.
+ // Note: We can't use CanonicalizeUsername() again, since it's not idempotent
+ // if multiple '@' signs are present in the initial username.
+ DCHECK_EQ(base::ToLowerASCII(canonicalized_username), canonicalized_username);
+ return HashUsername(canonicalized_username)
+ .substr(0, kUsernameHashPrefixLength / CHAR_BIT);
+}
+
+std::string ScryptHashUsernameAndPassword(
+ base::StringPiece canonicalized_username,
+ base::StringPiece password) {
+ // Constant salt added to the password hash on top of canonicalized_username.
+ // Needs to stay in sync with server side constant: go/passwords-leak-salts
+ static constexpr char kPasswordHashSalt[] = {
+ 48, 118, 42, -46, 63, 123, -95, -101, -8, -29, 66,
+ -4, -95, -89, -115, 6, -26, 107, -28, -37, -72, 79,
+ -127, 83, -59, 3, -56, -37, -67, -34, -91, 32};
+ static constexpr size_t kHashKeyLength = 32;
+ static constexpr uint64_t kScryptCost = 1 << 12; // It must be a power of 2.
+ static constexpr uint64_t kScryptBlockSize = 8;
+ static constexpr uint64_t kScryptParallelization = 1;
+ static constexpr size_t kScryptMaxMemory = 1024 * 1024 * 32;
+
+ // Check that |canonicalized_username| is actually canonicalized.
+ // Note: We can't use CanonicalizeUsername() again, since it's not idempotent
+ // if multiple '@' signs are present in the initial username.
+ DCHECK_EQ(base::ToLowerASCII(canonicalized_username), canonicalized_username);
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ std::string username_password =
+ base::StrCat({canonicalized_username, password});
+ std::string salt = base::StrCat(
+ {canonicalized_username,
+ base::StringPiece(kPasswordHashSalt, base::size(kPasswordHashSalt))});
+
+ std::string result;
+ uint8_t* key_data =
+ reinterpret_cast<uint8_t*>(base::WriteInto(&result, kHashKeyLength + 1));
+
+ int scrypt_ok =
+ EVP_PBE_scrypt(username_password.data(), username_password.size(),
+ reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
+ kScryptCost, kScryptBlockSize, kScryptParallelization,
+ kScryptMaxMemory, key_data, kHashKeyLength);
+ return scrypt_ok == 1 ? std::move(result) : std::string();
+}
+
+std::string CipherEncrypt(const std::string& plaintext, std::string* key) {
+ using ::private_join_and_compute::ECCommutativeCipher;
+ auto cipher = ECCommutativeCipher::CreateWithNewKey(
+ NID_X9_62_prime256v1, ECCommutativeCipher::SHA256);
+ *key = cipher.ValueOrDie()->GetPrivateKeyBytes();
+ auto result = cipher.ValueOrDie()->Encrypt(plaintext);
+ if (result.ok())
+ return result.ValueOrDie();
+ return std::string();
+}
+
+std::string CipherEncryptWithKey(const std::string& plaintext,
+ const std::string& key) {
+ using ::private_join_and_compute::ECCommutativeCipher;
+ auto cipher = ECCommutativeCipher::CreateFromKey(NID_X9_62_prime256v1, key,
+ ECCommutativeCipher::SHA256);
+ auto result = cipher.ValueOrDie()->Encrypt(plaintext);
+ if (result.ok())
+ return result.ValueOrDie();
+ return std::string();
+}
+
+std::string CipherReEncrypt(const std::string& already_encrypted,
+ std::string* key) {
+ using ::private_join_and_compute::ECCommutativeCipher;
+ auto cipher = ECCommutativeCipher::CreateWithNewKey(
+ NID_X9_62_prime256v1, ECCommutativeCipher::SHA256);
+ *key = cipher.ValueOrDie()->GetPrivateKeyBytes();
+ auto result = cipher.ValueOrDie()->ReEncrypt(already_encrypted);
+ return result.ValueOrDie();
+}
+
+std::string CipherDecrypt(const std::string& ciphertext,
+ const std::string& key) {
+ using ::private_join_and_compute::ECCommutativeCipher;
+ auto cipher = ECCommutativeCipher::CreateFromKey(NID_X9_62_prime256v1, key,
+ ECCommutativeCipher::SHA256);
+ auto result = cipher.ValueOrDie()->Decrypt(ciphertext);
+ if (result.ok())
+ return result.ValueOrDie();
+ return std::string();
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.h b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.h
new file mode 100644
index 00000000000..ec6a3bce08f
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_ENCRYPTION_UTILS_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_ENCRYPTION_UTILS_H_
+
+#include <string>
+
+#include "base/strings/string_piece_forward.h"
+
+namespace password_manager {
+
+// Username hash prefix length in bits.
+constexpr size_t kUsernameHashPrefixLength = 24;
+
+// Canonicalizes |username| by lower-casing and and stripping a mail-address
+// host in case the username is a mail address. |username| must be a UTF-8
+// string.
+std::string CanonicalizeUsername(base::StringPiece username);
+
+// Hashes |canonicalized_username| by appending a fixed salt and computing the
+// SHA256 hash.
+std::string HashUsername(base::StringPiece canonicalized_username);
+
+// Bucketizes |canonicalized_username| by hashing it and returning a prefix of
+// |kUsernameHashPrefixLength| bits.
+std::string BucketizeUsername(base::StringPiece canonicalized_username);
+
+// Produces the username/password pair hash using scrypt algorithm.
+// |canonicalized_username| and |password| are UTF-8 strings.
+std::string ScryptHashUsernameAndPassword(
+ base::StringPiece canonicalized_username,
+ base::StringPiece password);
+
+// Encrypt/decrypt routines.
+
+// Encrypts |plaintext| with a new key. The key is returned via |key|.
+// Internally the function does some hashing first and then encrypts the result.
+std::string CipherEncrypt(const std::string& plaintext, std::string* key);
+
+// Encrypts |plaintext| with the existing key.
+std::string CipherEncryptWithKey(const std::string& plaintext,
+ const std::string& key);
+
+// |already_encrypted| is an already encrypted string (output of CipherEncrypt).
+// Encrypts it again with a new key. The key is returned in |key|.
+// The function is different from CipherEncrypt() as it doesn't apply hashing on
+// the input.
+std::string CipherReEncrypt(const std::string& already_encrypted,
+ std::string* key);
+
+// Decrypts |ciphertext| using |key|. The result isn't the original string but a
+// hash of it.
+std::string CipherDecrypt(const std::string& ciphertext,
+ const std::string& key);
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_ENCRYPTION_UTILS_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/encryption_utils_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils_unittest.cc
new file mode 100644
index 00000000000..30613dcc448
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils_unittest.cc
@@ -0,0 +1,139 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+
+#include <vector>
+
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/private-join-and-compute/src/crypto/context.h"
+#include "third_party/private-join-and-compute/src/crypto/ec_commutative_cipher.h"
+#include "third_party/private-join-and-compute/src/crypto/ec_group.h"
+#include "third_party/private-join-and-compute/src/crypto/ec_point.h"
+
+namespace password_manager {
+namespace {
+
+// Returns the hash of |plaintext| used by the encryption algorithm.
+std::string CalculateECCurveHash(const std::string& plaintext) {
+ using ::private_join_and_compute::Context;
+ using ::private_join_and_compute::ECGroup;
+
+ std::unique_ptr<Context> context(new Context);
+ auto group = ECGroup::Create(NID_X9_62_prime256v1, context.get());
+ auto point = group.ValueOrDie().GetPointByHashingToCurveSha256(plaintext);
+ return point.ValueOrDie().ToBytesCompressed().ValueOrDie();
+}
+
+// Converts a string to an array for printing.
+std::vector<int> StringAsArray(const std::string& s) {
+ return std::vector<int>(s.begin(), s.end());
+}
+
+} // namespace
+
+using ::testing::ElementsAreArray;
+
+TEST(EncryptionUtils, CanonicalizeUsername) {
+ // Ignore capitalization and mail hosts.
+ EXPECT_EQ("test", CanonicalizeUsername("test"));
+ EXPECT_EQ("test", CanonicalizeUsername("Test"));
+ EXPECT_EQ("test", CanonicalizeUsername("TEST"));
+ EXPECT_EQ("test", CanonicalizeUsername("test@mail.com"));
+ EXPECT_EQ("test", CanonicalizeUsername("TeSt@MaIl.cOm"));
+ EXPECT_EQ("test", CanonicalizeUsername("TEST@MAIL.COM"));
+
+ // Strip off dots.
+ EXPECT_EQ("foobar", CanonicalizeUsername("foo.bar@COM"));
+
+ // Keep all but the last '@' sign.
+ EXPECT_EQ("te@st", CanonicalizeUsername("te@st@mail.com"));
+}
+
+TEST(EncryptionUtils, HashUsername) {
+ // Same test case as used by the server-side implementation:
+ // go/passwords-leak-test
+ constexpr char kExpected[] = {0x3D, 0x70, 0xD3, 0x7B, 0xFC, 0x1A, 0x3D, 0x81,
+ 0x45, 0xE6, 0xC7, 0xA3, 0xA4, 0xD7, 0x92, 0x76,
+ 0x61, 0xC1, 0xE8, 0xDF, 0x82, 0xBD, 0x0C, 0x9F,
+ 0x61, 0x9A, 0xA3, 0xC9, 0x96, 0xEC, 0x4C, 0xB3};
+ EXPECT_THAT(HashUsername("jonsnow"), ElementsAreArray(kExpected));
+}
+
+TEST(EncryptionUtils, BucketizeUsername) {
+ EXPECT_THAT(BucketizeUsername("jonsnow"),
+ ElementsAreArray({0x3D, 0x70, 0xD3}));
+}
+
+TEST(EncryptionUtils, ScryptHashUsernameAndPassword) {
+ // The expected result was obtained by running the Java implementation of the
+ // hash.
+ // Needs to stay in sync with server side constant: go/passwords-leak-salts.
+ constexpr char kExpected[] = {-103, 126, -10, 118, 7, 76, -51, -76,
+ -56, -82, -38, 31, 114, 61, -7, 103,
+ 76, 91, 52, -52, 47, -22, 107, 77,
+ 118, 123, -14, -125, -123, 85, 115, -3};
+ std::string result = ScryptHashUsernameAndPassword("user", "password123");
+ EXPECT_THAT(result, ElementsAreArray(kExpected));
+}
+
+TEST(EncryptionUtils, EncryptAndDecrypt) {
+ constexpr char kRandomString[] = "very_secret";
+ std::string key;
+ std::string cipher = CipherEncrypt(kRandomString, &key);
+ SCOPED_TRACE(testing::Message()
+ << "key=" << testing::PrintToString(StringAsArray(key)));
+
+ EXPECT_NE(kRandomString, cipher);
+ EXPECT_NE(std::string(), key);
+ EXPECT_THAT(CalculateECCurveHash(kRandomString),
+ ElementsAreArray(CipherDecrypt(cipher, key)));
+}
+
+TEST(EncryptionUtils, EncryptAndDecryptWithPredefinedKey) {
+ constexpr char kRandomString[] = "very_secret";
+ const std::string kKey = {-3, -80, 44, -113, -1, -67, 49, -120,
+ -91, 54, -15, -2, 13, -87, 95, 85,
+ -101, 11, -81, 102, -105, -14, 8, -123,
+ 1, 36, -74, -19, 88, 109, -24, -102};
+ SCOPED_TRACE(testing::Message()
+ << "key=" << testing::PrintToString(StringAsArray(kKey)));
+ // The expected result was obtained by running the Java implementation of the
+ // cipher.
+ const char kEncrypted[] = {2, 69, 19, 106, -38, 4, -21, -57, 110,
+ 95, 110, 111, 51, -100, -56, -10, -24, 71,
+ -112, -64, 58, -64, 76, -35, -117, -23, -100,
+ 25, 63, 37, 114, 74, 88};
+
+ std::string cipher = CipherEncryptWithKey(kRandomString, kKey);
+ EXPECT_THAT(cipher, ElementsAreArray(kEncrypted));
+ EXPECT_THAT(CalculateECCurveHash(kRandomString),
+ ElementsAreArray(CipherDecrypt(cipher, kKey)));
+}
+
+TEST(EncryptionUtils, CipherIsCommutative) {
+ constexpr char kRandomString[] = "very_secret";
+
+ // Client encrypts the string.
+ std::string key_client;
+ std::string cipher = CipherEncrypt(kRandomString, &key_client);
+ SCOPED_TRACE(testing::Message()
+ << "key_client="
+ << testing::PrintToString(StringAsArray(key_client)));
+
+ // Server encrypts the result.
+ std::string key_server;
+ cipher = CipherReEncrypt(cipher, &key_server);
+ SCOPED_TRACE(testing::Message()
+ << "key_server="
+ << testing::PrintToString(StringAsArray(key_server)));
+
+ EXPECT_THAT(CipherEncryptWithKey(kRandomString, key_server),
+ ElementsAreArray(CipherDecrypt(cipher, key_client)));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn b/chromium/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn
new file mode 100644
index 00000000000..323b1dbb0e3
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/fuzzer/BUILD.gn
@@ -0,0 +1,43 @@
+import("//testing/libfuzzer/fuzzer_test.gni")
+
+# Empty group for package discovery.
+group("fuzzer") {
+}
+
+fuzzer_test("cipher_encrypt_fuzzer") {
+ sources = [
+ "cipher_encrypt_fuzzer.cc",
+ ]
+ deps = [
+ "//components/password_manager/core/browser/leak_detection",
+ ]
+}
+
+fuzzer_test("cypher_encrypt_with_key_fuzzer") {
+ sources = [
+ "cypher_encrypt_with_key_fuzzer.cc",
+ ]
+ deps = [
+ "//components/password_manager/core/browser/leak_detection",
+ "//third_party/private-join-and-compute/src:ec_commutative_cipher",
+ ]
+}
+
+fuzzer_test("cypher_reencrypt_fuzzer") {
+ sources = [
+ "cypher_reencrypt_fuzzer.cc",
+ ]
+ deps = [
+ "//components/password_manager/core/browser/leak_detection",
+ ]
+}
+
+fuzzer_test("cypher_decrypt_fuzzer") {
+ sources = [
+ "cypher_decrypt_fuzzer.cc",
+ ]
+ deps = [
+ "//components/password_manager/core/browser/leak_detection",
+ "//third_party/private-join-and-compute/src:ec_commutative_cipher",
+ ]
+}
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_api.proto b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_api.proto
index 8466c06033b..3a0643126c8 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_api.proto
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_api.proto
@@ -1,38 +1,12 @@
syntax = "proto3";
-package leak_detection;
+// See the following for the server side definition:
+// http://google3/google/internal/identity/passwords/leak/check/v1/service.proto
+package google.internal.identity.passwords.leak.check.v1;
option optimize_for = LITE_RUNTIME;
-// See internal/identity/passwords/leak/check/v1/service.proto for the server
-// side definition.
-service PasswordsLeakCheckService {
- // Enables clients to privately check whether given username-password pairs
- // are part of a leak that we collected.
- //
- // The protocol used here requires the client to request buckets of known
- // leaks identified by a username-hash prefix (username_hash_prefix).
- // In response, the server returns all the leaks (hashed username-password
- // pairs) of the requested buckets (leak_match).
- //
- // In order to not leak the database of hashed username-password pairs
- // to the client, we added the blinders protocol (go/blinders) into the mix.
- // This allows the server to only return an encrypted version of the hashes
- // to the clients (encrypted_leak_hash). The clients will not know the key
- // with which the server encrypted the hashes.
- // In order for the client to figure out if their credentials actually got
- // leaked, they need to encrypt their username-password pair hashes with their
- // own secret key and send the encrypted result to the server
- // (encrypted_lookup_hash).
- // The server will then reencrypt encrypted_lookup_hash with their own secret
- // key and return that in the result (reencrypted_lookup_hash).
- // The client will then reverse their own encryption on
- // reencrypted_lookup_hash and look up if the result is in the list of
- // returned leaks (leak_match). If so, the client has identified a leak.
- rpc LookupLeaks(LookupLeaksRequest) returns (LookupLeaksResponse) {}
-}
-
-message LookupLeaksRequest {
+message LookupSingleLeakRequest {
// The prefix of the username hash (algorithm: SHA-256;
// string encoding: UTF8).
//
@@ -44,10 +18,9 @@ message LookupLeaksRequest {
// with 0.
//
// The client can request all known leaks for a given username bucket.
- // This specifies the requested username buckets. All returned
- // `leak_match` values will belong to one of the requested username
- // buckets.
- repeated bytes username_hash_prefix = 1;
+ // This specifies the requested username bucket. All returned
+ // `encrypted_leak_match_prefix` values will belong to that requested bucket.
+ bytes username_hash_prefix = 1;
// The length of the username hash prefix in bits.
// We only allow 24 bits at the moment.
@@ -59,6 +32,10 @@ message LookupLeaksRequest {
// The full hash of username and password which was encrypted using a
// commutative cipher.
+ // The hashing algorithm used is Scrypt.
+ //
+ // Essentially:
+ // cipher_with_client_key(scrypt(username, password))
//
// The underlying username is expected to be canonicalized the same as
// described for username_hash_prefix.
@@ -66,45 +43,32 @@ message LookupLeaksRequest {
// The key should be randomly generated by the client. It can choose a new one
// per request, or even per hash. The server can't decrypt this and
// won't know the difference.
- repeated bytes encrypted_lookup_hash = 3;
+ bytes encrypted_lookup_hash = 3;
}
-message LookupLeaksResponse {
+message LookupSingleLeakResponse {
// The leaks that match the requested `username_hash_prefix`.
- // This list is sorted by `encrypted_leak_hash` in order to enable binary
- // search for matches.
- repeated LeakMatch leak_match = 1;
-
- // The reencrypted `encrypted_lookup_hash` from the request. In order for the
- // clients to check for matches, it needs the server to reencrypt the
- // `encrypted_lookup_hash` that they sent. The client can then reverse their
- // own encryption and check `leak_match` for the resulting values.
- repeated ReencryptedLookupHash reencrypted_lookup_hash = 2;
-
- message LeakMatch {
- // The requested username_hash_prefix that the leak matches belong to.
- bytes username_hash_prefix = 2;
-
- // The full hash of username and password that was discovered in a leak
- // which was encrypted using a commutative cipher with a private key picked
- // by the server.
- // The hashing algorithm and cipher used are the same as defined in the
- // request.
- // Note: There are no guarantees that the server key stays the same between
- // subsequent requests.
- repeated bytes encrypted_leak_hash = 1;
- }
+ // A prefix of the SHA256 hash of the encrypted hashed username and password
+ // pair that was discovered in a leak. It was encrypted using a commutative
+ // cipher with a private key picked by the server.
+ // The prefix length can vary depending on the response size but will be long
+ // enough in order to not cause any false positives. This is a pure bandwidth
+ // optimization measure.
+ //
+ // Essentially:
+ // prefix(sha256(cipher_with_server_key(scrypt(username, password))))
+ //
+ // Note: There are no guarantees that the server key stays the same between
+ // subsequent requests.
+ repeated bytes encrypted_leak_match_prefix = 1;
- message ReencryptedLookupHash {
- // The same as `encrypted_lookup_hash` from the request. This can be used by
- // the client to link the reencrypted hash to the originally requested
- // one.
- bytes encrypted_lookup_hash = 1;
- // The `encrypted_lookup_hash` reencrypted with the server's private key
- // (the same key that is used for encrypting `encrypted_leak_hash`).
- // This enables the client to reverse their own encryption, giving the
- // client a server-side only encrypted leak entry which it can use to check
- // if `leak_match` contains it.
- bytes reencrypted_lookup_hash = 2;
- }
+ // The `encrypted_lookup_hash` reencrypted with the server's private key
+ // (the same key that is used for encrypting `encrypted_leak_match_prefix`).
+ // This enables the client to reverse their own encryption, giving the
+ // client a server-side only encrypted leak entry which it can use to check
+ // if `encrypted_leak_match_prefix` contains it.
+ //
+ // Essentially:
+ // cipher_with_server_key(cipher_with_client_key(scrypt(username, password)))
+ bytes reencrypted_lookup_hash = 2;
}
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check.h
new file mode 100644
index 00000000000..6a3a3cd187e
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_H_
+
+#include "base/strings/string16.h"
+#include "url/gurl.h"
+
+namespace password_manager {
+
+// The base class for requests for checking if {username, password} pair was
+// leaked in the internet.
+class LeakDetectionCheck {
+ public:
+ LeakDetectionCheck() = default;
+ virtual ~LeakDetectionCheck() = default;
+
+ // Not copyable or movable
+ LeakDetectionCheck(const LeakDetectionCheck&) = delete;
+ LeakDetectionCheck& operator=(const LeakDetectionCheck&) = delete;
+ LeakDetectionCheck(LeakDetectionCheck&&) = delete;
+ LeakDetectionCheck& operator=(LeakDetectionCheck&&) = delete;
+
+ // Starts checking |username| and |password| pair asynchronously.
+ // |url| is used later for presentation in the UI but not for actual business
+ // logic. The method should be called only once per lifetime of the object.
+ virtual void Start(const GURL& url,
+ base::string16 username,
+ base::string16 password) = 0;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h
new file mode 100644
index 00000000000..2ff2d38013b
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_FACTORY_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_FACTORY_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+
+namespace signin {
+class IdentityManager;
+} // namespace signin
+
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+
+namespace password_manager {
+
+class LeakDetectionCheck;
+class LeakDetectionDelegateInterface;
+
+// The interface for creating instances of requests for checking if
+// {username, password} pair was leaked in the internet.
+class LeakDetectionCheckFactory {
+ public:
+ LeakDetectionCheckFactory() = default;
+ virtual ~LeakDetectionCheckFactory() = default;
+
+ // Not copyable or movable
+ LeakDetectionCheckFactory(const LeakDetectionCheckFactory&) = delete;
+ LeakDetectionCheckFactory& operator=(const LeakDetectionCheckFactory&) =
+ delete;
+ LeakDetectionCheckFactory(LeakDetectionCheckFactory&&) = delete;
+ LeakDetectionCheckFactory& operator=(LeakDetectionCheckFactory&&) = delete;
+
+ // The leak check is available only for signed-in users and if the feature is
+ // available.
+ // |delegate| gets the results for the fetch.
+ // |identity_manager| is used to obtain the token.
+ // |url_loader_factory| does the actual network request.
+ virtual std::unique_ptr<LeakDetectionCheck> TryCreateLeakCheck(
+ LeakDetectionDelegateInterface* delegate,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ const = 0;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_FACTORY_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc
new file mode 100644
index 00000000000..4327b54a795
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.cc
@@ -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.
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h"
+
+#include <utility>
+
+#include "components/password_manager/core/browser/leak_detection/authenticated_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace password_manager {
+
+LeakDetectionCheckFactoryImpl::LeakDetectionCheckFactoryImpl() = default;
+LeakDetectionCheckFactoryImpl::~LeakDetectionCheckFactoryImpl() = default;
+
+std::unique_ptr<LeakDetectionCheck>
+LeakDetectionCheckFactoryImpl::TryCreateLeakCheck(
+ LeakDetectionDelegateInterface* delegate,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) const {
+ if (!AuthenticatedLeakCheck::HasAccountForRequest(identity_manager)) {
+ delegate->OnError(LeakDetectionError::kNotSignIn);
+ return nullptr;
+ }
+ // Instantiate the field trial right before the feature can be used. Thus,
+ // the experiment groups will only contain the users who can use the feature.
+ if (!base::FeatureList::IsEnabled(features::kLeakDetection))
+ return nullptr;
+ return std::make_unique<AuthenticatedLeakCheck>(
+ delegate, identity_manager, std::move(url_loader_factory));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h
new file mode 100644
index 00000000000..4befcd25d3b
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_FACTORY_IMPL_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_FACTORY_IMPL_H_
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
+#include "url/gurl.h"
+
+namespace password_manager {
+
+// The class creates instances of requests for checking if {username, password}
+// pair was leaked in the internet.
+class LeakDetectionCheckFactoryImpl : public LeakDetectionCheckFactory {
+ public:
+ LeakDetectionCheckFactoryImpl();
+ ~LeakDetectionCheckFactoryImpl() override;
+
+ std::unique_ptr<LeakDetectionCheck> TryCreateLeakCheck(
+ LeakDetectionDelegateInterface* delegate,
+ signin::IdentityManager* identity_manager,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ const override;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_FACTORY_IMPL_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl_unittest.cc
new file mode 100644
index 00000000000..0e5dd00de1b
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl_unittest.cc
@@ -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.
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/test/test_shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+namespace {
+
+using ::testing::StrictMock;
+
+constexpr char kTestAccount[] = "user@gmail.com";
+
+class LeakDetectionCheckFactoryImplTest : public testing::Test {
+ public:
+ LeakDetectionCheckFactoryImplTest() = default;
+ ~LeakDetectionCheckFactoryImplTest() override = default;
+
+ signin::IdentityTestEnvironment& identity_env() { return identity_test_env_; }
+ MockLeakDetectionDelegateInterface& delegate() { return delegate_; }
+ const scoped_refptr<network::SharedURLLoaderFactory>& url_loader_factory() {
+ return url_loader_factory_;
+ }
+ LeakDetectionCheckFactoryImpl& request_factory() { return request_factory_; }
+
+ private:
+ base::test::TaskEnvironment task_env_;
+ signin::IdentityTestEnvironment identity_test_env_;
+ StrictMock<MockLeakDetectionDelegateInterface> delegate_;
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_ =
+ base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
+ LeakDetectionCheckFactoryImpl request_factory_;
+};
+
+} // namespace
+
+TEST_F(LeakDetectionCheckFactoryImplTest, DisabledFeature) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(features::kLeakDetection);
+
+ identity_env().SetPrimaryAccount(kTestAccount);
+ EXPECT_FALSE(request_factory().TryCreateLeakCheck(
+ &delegate(), identity_env().identity_manager(), url_loader_factory()));
+}
+
+TEST_F(LeakDetectionCheckFactoryImplTest, SignedOut) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kLeakDetection);
+
+ EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNotSignIn));
+ EXPECT_FALSE(request_factory().TryCreateLeakCheck(
+ &delegate(), identity_env().identity_manager(), url_loader_factory()));
+}
+
+TEST_F(LeakDetectionCheckFactoryImplTest, SignedIn) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kLeakDetection);
+
+ AccountInfo info = identity_env().MakeAccountAvailable(kTestAccount);
+ identity_env().SetCookieAccounts({{info.email, info.account_id}});
+ identity_env().SetRefreshTokenForAccount(info.account_id);
+ EXPECT_TRUE(request_factory().TryCreateLeakCheck(
+ &delegate(), identity_env().identity_manager(), url_loader_factory()));
+}
+
+TEST_F(LeakDetectionCheckFactoryImplTest, SignedInAndSyncing) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kLeakDetection);
+
+ identity_env().SetPrimaryAccount(kTestAccount);
+ EXPECT_TRUE(request_factory().TryCreateLeakCheck(
+ &delegate(), identity_env().identity_manager(), url_loader_factory()));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h
new file mode 100644
index 00000000000..61760998fd0
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_DELEGATE_INTERFACE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_DELEGATE_INTERFACE_H_
+
+#include "url/gurl.h"
+
+namespace password_manager {
+
+enum class LeakDetectionError {
+ // The user isn't signed-in to Chrome.
+ kNotSignIn = 0,
+ // Error obtaining a token.
+ kTokenRequestFailure = 1,
+ // Error in hashing/encrypting for the request.
+ kHashingFailure = 2,
+ // Error obtaining a valid server response.
+ kInvalidServerResponse = 3,
+ // TODO(crbug.com/986298): add more errors.
+};
+
+// Interface with callbacks for LeakDetectionCheck. Used to get the result of
+// the check.
+class LeakDetectionDelegateInterface {
+ public:
+ LeakDetectionDelegateInterface() = default;
+ virtual ~LeakDetectionDelegateInterface() = default;
+
+ // Not copyable or movable
+ LeakDetectionDelegateInterface(const LeakDetectionDelegateInterface&) =
+ delete;
+ LeakDetectionDelegateInterface& operator=(
+ const LeakDetectionDelegateInterface&) = delete;
+ LeakDetectionDelegateInterface(LeakDetectionDelegateInterface&&) = delete;
+ LeakDetectionDelegateInterface& operator=(LeakDetectionDelegateInterface&&) =
+ delete;
+
+ // Called when the request is finished without error.
+ // |leak| is true iff the checked credential was leaked.
+ // |url| and |username| are taken from Start() for presentation in the UI.
+ // Pass parameters by value because the caller can be destroyed here.
+ virtual void OnLeakDetectionDone(bool is_leaked,
+ GURL url,
+ base::string16 username,
+ base::string16 password) = 0;
+
+ virtual void OnError(LeakDetectionError error) = 0;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_DELEGATE_INTERFACE_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.cc
new file mode 100644
index 00000000000..91efcb1be79
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.cc
@@ -0,0 +1,186 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request.h"
+
+#include <iterator>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_api.pb.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "url/gurl.h"
+
+namespace password_manager {
+
+namespace {
+
+void RecordLookupResponseResult(
+ LeakDetectionRequest::LeakLookupResponseResult result) {
+ base::UmaHistogramEnumeration(
+ "PasswordManager.LeakDetection.LookupSingleLeakResponseResult", result);
+}
+
+constexpr char kAuthHeaderBearer[] = "Bearer ";
+constexpr char kPostMethod[] = "POST";
+constexpr char kProtobufContentType[] = "application/x-protobuf";
+
+google::internal::identity::passwords::leak::check::v1::LookupSingleLeakRequest
+MakeLookupSingleLeakRequest(std::string username_hash_prefix,
+ std::string encrypted_payload) {
+ google::internal::identity::passwords::leak::check::v1::
+ LookupSingleLeakRequest request;
+ request.set_username_hash_prefix(std::move(username_hash_prefix));
+ request.set_username_hash_prefix_length(kUsernameHashPrefixLength);
+ request.set_encrypted_lookup_hash(std::move(encrypted_payload));
+ return request;
+}
+
+} // namespace
+
+constexpr char LeakDetectionRequest::kLookupSingleLeakEndpoint[];
+
+LeakDetectionRequest::LeakDetectionRequest() = default;
+
+LeakDetectionRequest::~LeakDetectionRequest() = default;
+
+void LeakDetectionRequest::LookupSingleLeak(
+ network::mojom::URLLoaderFactory* url_loader_factory,
+ const std::string& access_token,
+ std::string username_hash_prefix,
+ std::string encrypted_payload,
+ LookupSingleLeakCallback callback) {
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("lookup_single_password_leak", R"(
+ semantics {
+ sender: "Leaked Credential Detector"
+ description:
+ "In order to inform signed-in users about leaked credentials this "
+ "service uploads a prefix of the hashed username, as well as the "
+ "encrypted username and password following a successful password "
+ "form submission. The former is a 3 bytes of the hash and doesn't "
+ "reveal the username to the server in any way. The latter is "
+ "completely opaque to the server. The server responds with a list "
+ "of encrypted leaked credentials matching the prefix of the hashed "
+ "username, as well as with a re-encypted version of the uploaded "
+ "username and password. Chrome then reverses its encryption on the "
+ "re-encrypted credential and tries to find it in the list of "
+ "leaked credentials. If a match is found, Chrome notifies the user "
+ "and prompts them to change their credentials. Re-encryption part "
+ "is for the privacy reason. The server can't read the user's "
+ "password. At the same time the client can't read the "
+ "usernames/passwords of other leaked accounts but only can check "
+ "the current one.";
+ trigger:
+ "Following a successful password form submission by a signed-in "
+ "user"
+ data:
+ "A hash prefix of the username and the encrypted username and "
+ "password."
+ destination: GOOGLE_OWNED_SERVICE
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "Users can enable or disable this feature in Chrome's password "
+ "settings. The feature is enabled by default."
+ chrome_policy {
+ PasswordLeakDetectionEnabled {
+ PasswordLeakDetectionEnabled: false
+ }
+ }
+ })");
+
+ auto resource_request = std::make_unique<network::ResourceRequest>();
+ resource_request->url = GURL(kLookupSingleLeakEndpoint);
+ resource_request->load_flags = net::LOAD_DISABLE_CACHE;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+ resource_request->method = kPostMethod;
+ resource_request->headers.SetHeader(
+ net::HttpRequestHeaders::kAuthorization,
+ base::StrCat({kAuthHeaderBearer, access_token}));
+
+ simple_url_loader_ = network::SimpleURLLoader::Create(
+ std::move(resource_request), traffic_annotation);
+ simple_url_loader_->AttachStringForUpload(
+ MakeLookupSingleLeakRequest(std::move(username_hash_prefix),
+ std::move(encrypted_payload))
+ .SerializeAsString(),
+ kProtobufContentType);
+ simple_url_loader_->DownloadToString(
+ url_loader_factory,
+ base::BindOnce(&LeakDetectionRequest::OnLookupSingleLeakResponse,
+ base::Unretained(this), std::move(callback)),
+ network::SimpleURLLoader::kMaxBoundedStringDownloadSize);
+}
+
+void LeakDetectionRequest::OnLookupSingleLeakResponse(
+ LookupSingleLeakCallback callback,
+ std::unique_ptr<std::string> response) {
+ if (!response) {
+ RecordLookupResponseResult(LeakLookupResponseResult::kFetchError);
+ DLOG(ERROR) << "Empty Lookup Single Leak Response";
+ int response_code = -1;
+ if (simple_url_loader_->ResponseInfo() &&
+ simple_url_loader_->ResponseInfo()->headers) {
+ response_code =
+ simple_url_loader_->ResponseInfo()->headers->response_code();
+ DLOG(ERROR) << "HTTP Response Code: " << response_code;
+ }
+
+ base::UmaHistogramSparse("PasswordManager.LeakDetection.HttpResponseCode",
+ response_code);
+
+ int net_error = simple_url_loader_->NetError();
+ DLOG(ERROR) << "Net Error: " << net::ErrorToString(net_error);
+ // Network error codes are negative. See: src/net/base/net_error_list.h.
+ base::UmaHistogramSparse("PasswordManager.LeakDetection.NetErrorCode",
+ -net_error);
+
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ base::UmaHistogramCounts1M(
+ "PasswordManager.LeakDetection.SingleLeakResponseSize", response->size());
+ google::internal::identity::passwords::leak::check::v1::
+ LookupSingleLeakResponse leak_response;
+ if (!leak_response.ParseFromString(*response)) {
+ RecordLookupResponseResult(LeakLookupResponseResult::kParseError);
+ DLOG(ERROR) << "Could not parse response: "
+ << base::HexEncode(response->data(), response->size());
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ RecordLookupResponseResult(LeakLookupResponseResult::kSuccess);
+ auto single_lookup_response = std::make_unique<SingleLookupResponse>();
+ single_lookup_response->encrypted_leak_match_prefixes.assign(
+ std::make_move_iterator(
+ leak_response.mutable_encrypted_leak_match_prefix()->begin()),
+ std::make_move_iterator(
+ leak_response.mutable_encrypted_leak_match_prefix()->end()));
+ single_lookup_response->reencrypted_lookup_hash =
+ std::move(*leak_response.mutable_reencrypted_lookup_hash());
+ base::UmaHistogramCounts100000(
+ "PasswordManager.LeakDetection.SingleLeakResponsePrefixes",
+ single_lookup_response->encrypted_leak_match_prefixes.size());
+ std::move(callback).Run(std::move(single_lookup_response));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.h
new file mode 100644
index 00000000000..87459074b26
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.h
@@ -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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_H_
+
+#include <memory>
+#include <string>
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
+
+namespace network {
+class SimpleURLLoader;
+} // namespace network
+
+namespace password_manager {
+
+// This class encapsulates the logic required to talk to the identity leak check
+// endpoint. Callers are expected to construct an instance for each request they
+// would like to perform. Destruction of the class results in a cancellation of
+// the initiated network request.
+class LeakDetectionRequest : public LeakDetectionRequestInterface {
+ public:
+ // Enum representing different leak lookup response results. Needs to stay in
+ // sync with the PasswordLeakLookupResponseResult enum in enums.xml.
+ //
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class LeakLookupResponseResult {
+ kSuccess = 0,
+ kFetchError = 1,
+ kParseError = 2,
+ kMaxValue = kParseError
+ };
+
+ static constexpr char kLookupSingleLeakEndpoint[] =
+ "https://passwordsleakcheck-pa.googleapis.com/v1/leaks:lookupSingle";
+
+ LeakDetectionRequest();
+ ~LeakDetectionRequest() override;
+
+ // Initiates a leak lookup network request for the credential corresponding to
+ // |username_hash_prefix| and |encrypted_payload|. |access_token| is required
+ // to authenticate the request. Invokes |callback| on completion, unless this
+ // instance is deleted beforehand. If the request failed, |callback| is
+ // invoked with |nullptr|, otherwise a SingleLookupResponse is returned.
+ void LookupSingleLeak(network::mojom::URLLoaderFactory* url_loader_factory,
+ const std::string& access_token,
+ std::string username_hash_prefix,
+ std::string encrypted_payload,
+ LookupSingleLeakCallback callback) override;
+
+ private:
+ void OnLookupSingleLeakResponse(LookupSingleLeakCallback callback,
+ std::unique_ptr<std::string> response);
+
+ // Simple URL loader required for the network request to the identity
+ // endpoint.
+ std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.cc
new file mode 100644
index 00000000000..3263c1f5b8c
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.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 "components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h"
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request.h"
+
+namespace password_manager {
+
+std::unique_ptr<LeakDetectionRequestInterface>
+LeakDetectionRequestFactory::CreateNetworkRequest() const {
+ return std::make_unique<LeakDetectionRequest>();
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h
new file mode 100644
index 00000000000..03305b3e350
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h
@@ -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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_FACTORY_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback_forward.h"
+
+namespace network {
+namespace mojom {
+class URLLoaderFactory;
+} // namespace mojom
+} // namespace network
+
+namespace password_manager {
+
+struct SingleLookupResponse;
+
+// Interface for the class making the network requests for leak detection.
+class LeakDetectionRequestInterface {
+ public:
+ using LookupSingleLeakCallback =
+ base::OnceCallback<void(std::unique_ptr<SingleLookupResponse>)>;
+
+ LeakDetectionRequestInterface() = default;
+ virtual ~LeakDetectionRequestInterface() = default;
+
+ // Neither copyable nor movable.
+ LeakDetectionRequestInterface(const LeakDetectionRequestInterface&) = delete;
+ LeakDetectionRequestInterface& operator=(
+ const LeakDetectionRequestInterface&) = delete;
+ LeakDetectionRequestInterface(LeakDetectionRequestInterface&&) = delete;
+ LeakDetectionRequestInterface& operator=(LeakDetectionRequestInterface&&) =
+ delete;
+
+ // Initiates a leak lookup network request for the credential corresponding to
+ // |username_hash_prefix| and |encrypted_payload|. |access_token| is required
+ // to authenticate the request. Invokes |callback| on completion, unless this
+ // instance is deleted beforehand. If the request failed, |callback| is
+ // invoked with |nullptr|, otherwise a SingleLookupResponse is returned.
+ virtual void LookupSingleLeak(
+ network::mojom::URLLoaderFactory* url_loader_factory,
+ const std::string& access_token,
+ std::string username_hash_prefix,
+ std::string encrypted_payload,
+ LookupSingleLeakCallback callback) = 0;
+};
+
+// The factory for creating instances of network requests for leak detection.
+class LeakDetectionRequestFactory {
+ public:
+ LeakDetectionRequestFactory() = default;
+ virtual ~LeakDetectionRequestFactory() = default;
+
+ // Not copyable or movable
+ LeakDetectionRequestFactory(const LeakDetectionRequestFactory&) = delete;
+ LeakDetectionRequestFactory& operator=(const LeakDetectionRequestFactory&) =
+ delete;
+ LeakDetectionRequestFactory(LeakDetectionRequestFactory&&) = delete;
+ LeakDetectionRequestFactory& operator=(LeakDetectionRequestFactory&&) =
+ delete;
+
+ virtual std::unique_ptr<LeakDetectionRequestInterface> CreateNetworkRequest()
+ const;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_FACTORY_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_unittest.cc
new file mode 100644
index 00000000000..c9436f69987
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_unittest.cc
@@ -0,0 +1,114 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_api.pb.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+
+using ::testing::Eq;
+
+class LeakDetectionRequestTest : public testing::Test {
+ public:
+ static constexpr char kAccessToken[] = "access_token";
+ static constexpr char kUsername[] = "username";
+ static constexpr char kPassword[] = "password123";
+
+ ~LeakDetectionRequestTest() override = default;
+
+ base::test::TaskEnvironment& task_env() { return task_env_; }
+ base::HistogramTester& histogram_tester() { return histogram_tester_; }
+ network::TestURLLoaderFactory* test_url_loader_factory() {
+ return &test_url_loader_factory_;
+ }
+ LeakDetectionRequest& request() { return request_; }
+
+ private:
+ base::test::TaskEnvironment task_env_;
+ base::HistogramTester histogram_tester_;
+ network::TestURLLoaderFactory test_url_loader_factory_;
+ LeakDetectionRequest request_;
+};
+
+// Note: These strings are static member constants rather than namespace scoped
+// constants to avoid compilation errors in Jumbo builds.
+constexpr char LeakDetectionRequestTest::kAccessToken[];
+constexpr char LeakDetectionRequestTest::kUsername[];
+constexpr char LeakDetectionRequestTest::kPassword[];
+
+TEST_F(LeakDetectionRequestTest, ServerError) {
+ test_url_loader_factory()->AddResponse(
+ LeakDetectionRequest::kLookupSingleLeakEndpoint, "",
+ net::HTTP_INTERNAL_SERVER_ERROR);
+
+ base::MockCallback<LeakDetectionRequest::LookupSingleLeakCallback> callback;
+ request().LookupSingleLeak(test_url_loader_factory(), kAccessToken, kUsername,
+ kPassword, callback.Get());
+ EXPECT_CALL(callback, Run(Eq(nullptr)));
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.LookupSingleLeakResponseResult",
+ LeakDetectionRequest::LeakLookupResponseResult::kFetchError, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.HttpResponseCode",
+ net::HTTP_INTERNAL_SERVER_ERROR, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.NetErrorCode",
+ -net::ERR_HTTP_RESPONSE_CODE_FAILURE, 1);
+}
+
+TEST_F(LeakDetectionRequestTest, MalformedServerResponse) {
+ static constexpr base::StringPiece kMalformedResponse = "\x01\x02\x03";
+ test_url_loader_factory()->AddResponse(
+ LeakDetectionRequest::kLookupSingleLeakEndpoint,
+ std::string(kMalformedResponse));
+
+ base::MockCallback<LeakDetectionRequest::LookupSingleLeakCallback> callback;
+ request().LookupSingleLeak(test_url_loader_factory(), kAccessToken, kUsername,
+ kPassword, callback.Get());
+ EXPECT_CALL(callback, Run(Eq(nullptr)));
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.LookupSingleLeakResponseResult",
+ LeakDetectionRequest::LeakLookupResponseResult::kParseError, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.SingleLeakResponseSize",
+ kMalformedResponse.size(), 1);
+}
+
+TEST_F(LeakDetectionRequestTest, WellformedServerResponse) {
+ google::internal::identity::passwords::leak::check::v1::
+ LookupSingleLeakResponse response;
+ std::string response_string = response.SerializeAsString();
+ test_url_loader_factory()->AddResponse(
+ LeakDetectionRequest::kLookupSingleLeakEndpoint, response_string);
+
+ base::MockCallback<LeakDetectionRequest::LookupSingleLeakCallback> callback;
+ request().LookupSingleLeak(test_url_loader_factory(), kAccessToken, kUsername,
+ kPassword, callback.Get());
+ EXPECT_CALL(callback, Run(testing::Pointee(SingleLookupResponse())));
+ task_env().RunUntilIdle();
+
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.LookupSingleLeakResponseResult",
+ LeakDetectionRequest::LeakLookupResponseResult::kSuccess, 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.SingleLeakResponseSize",
+ response_string.size(), 1);
+ histogram_tester().ExpectUniqueSample(
+ "PasswordManager.LeakDetection.SingleLeakResponsePrefixes",
+ response.encrypted_leak_match_prefix().size(), 1);
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc
new file mode 100644
index 00000000000..9d61252f877
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc
@@ -0,0 +1,98 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+
+#include <string>
+
+#include "base/containers/span.h"
+#include "base/debug/dump_without_crashing.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+#include "crypto/sha2.h"
+
+namespace password_manager {
+namespace {
+
+// Despite the function is short, it executes long. That's why it should be done
+// asynchronously.
+LookupSingleLeakData PrepareLookupSingleLeakData(const std::string& username,
+ const std::string& password) {
+ std::string canonicalized_username = CanonicalizeUsername(username);
+ LookupSingleLeakData data;
+ data.username_hash_prefix = BucketizeUsername(canonicalized_username);
+ data.encrypted_payload = CipherEncrypt(
+ ScryptHashUsernameAndPassword(canonicalized_username, password),
+ &data.encryption_key);
+ return data;
+}
+
+// Searches |reencrypted_lookup_hash| in the |encrypted_leak_match_prefixes|
+// array. |encryption_key| is the original client key used to encrypt the
+// payload.
+AnalyzeResponseResult CheckIfCredentialWasLeaked(
+ std::unique_ptr<SingleLookupResponse> response,
+ const std::string& encryption_key) {
+ std::string decrypted_username_password =
+ CipherDecrypt(response->reencrypted_lookup_hash, encryption_key);
+ if (decrypted_username_password.empty()) {
+ DLOG(ERROR) << "Can't decrypt data="
+ << base::HexEncode(base::as_bytes(
+ base::make_span(response->reencrypted_lookup_hash)));
+ return AnalyzeResponseResult::kDecryptionError;
+ }
+
+ std::string hash_username_password =
+ crypto::SHA256HashString(decrypted_username_password);
+
+ const ptrdiff_t matched_prefixes =
+ std::count_if(response->encrypted_leak_match_prefixes.begin(),
+ response->encrypted_leak_match_prefixes.end(),
+ [&hash_username_password](const std::string& prefix) {
+ return base::StartsWith(hash_username_password, prefix,
+ base::CompareCase::SENSITIVE);
+ });
+ switch (matched_prefixes) {
+ case 0:
+ return AnalyzeResponseResult::kNotLeaked;
+ case 1:
+ return AnalyzeResponseResult::kLeaked;
+ default:
+ // In theory this should never happen, due to the API contract the server
+ // provides. Generate a crash dump in case it does, so that we get
+ // notified.
+ base::debug::DumpWithoutCrashing();
+ return AnalyzeResponseResult::kLeaked;
+ };
+}
+
+} // namespace
+
+void PrepareSingleLeakRequestData(const std::string& username,
+ const std::string& password,
+ SingleLeakRequestDataCallback callback) {
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ base::BindOnce(&PrepareLookupSingleLeakData, username, password),
+ std::move(callback));
+}
+
+void AnalyzeResponse(std::unique_ptr<SingleLookupResponse> response,
+ const std::string& encryption_key,
+ SingleLeakResponseAnalysisCallback callback) {
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ base::BindOnce(&CheckIfCredentialWasLeaked, std::move(response),
+ encryption_key),
+ std::move(callback));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h
new file mode 100644
index 00000000000..bf8afea1130
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h
@@ -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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_UTILS_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_UTILS_H_
+
+#include "base/callback.h"
+#include "base/strings/string_piece_forward.h"
+
+namespace password_manager {
+
+struct SingleLookupResponse;
+
+// Stores all the data needed for one credential lookup.
+struct LookupSingleLeakData {
+ LookupSingleLeakData() = default;
+ LookupSingleLeakData(LookupSingleLeakData&& other) = default;
+ LookupSingleLeakData& operator=(LookupSingleLeakData&& other) = default;
+ ~LookupSingleLeakData() = default;
+
+ LookupSingleLeakData(const LookupSingleLeakData&) = delete;
+ LookupSingleLeakData& operator=(const LookupSingleLeakData&) = delete;
+
+ std::string username_hash_prefix;
+ std::string encrypted_payload;
+
+ std::string encryption_key;
+};
+
+using SingleLeakRequestDataCallback =
+ base::OnceCallback<void(LookupSingleLeakData)>;
+
+// Describes possible results of analyzing a leak response from the server.
+// Needs to stay in sync with the PasswordAnalyzeLeakResponseResult enum in
+// enums.xml.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class AnalyzeResponseResult {
+ kDecryptionError = 0,
+ kNotLeaked = 1,
+ kLeaked = 2,
+ kMaxValue = kLeaked,
+};
+
+using SingleLeakResponseAnalysisCallback =
+ base::OnceCallback<void(AnalyzeResponseResult)>;
+
+// Asynchronously creates a data payload for single credential check.
+// Callback is invoked on the calling thread with the protobuf and the
+// encryption key used.
+void PrepareSingleLeakRequestData(const std::string& username,
+ const std::string& password,
+ SingleLeakRequestDataCallback callback);
+
+// Analyses the |response| asynchronously and checks if the credential was
+// leaked. |callback| is invoked on the calling thread.
+void AnalyzeResponse(std::unique_ptr<SingleLookupResponse> response,
+ const std::string& encryption_key,
+ SingleLeakResponseAnalysisCallback callback);
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_REQUEST_UTILS_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc
new file mode 100644
index 00000000000..b4eb5580058
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils_unittest.cc
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
+
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+#include "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+#include "crypto/sha2.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+namespace {
+
+using ::testing::ElementsAre;
+using ::testing::Field;
+
+// Converts a string to an array for printing.
+std::vector<int> StringToArray(const std::string& s) {
+ return std::vector<int>(s.begin(), s.end());
+}
+
+} // namespace
+
+TEST(LeakDetectionRequestUtils, PrepareSingleLeakRequestData) {
+ base::test::TaskEnvironment task_env;
+ base::MockCallback<SingleLeakRequestDataCallback> callback;
+
+ PrepareSingleLeakRequestData("jonsnow", "1234", callback.Get());
+ EXPECT_CALL(
+ callback,
+ Run(AllOf(
+ Field(&LookupSingleLeakData::username_hash_prefix,
+ ElementsAre(61, 112, -45)),
+ Field(&LookupSingleLeakData::encrypted_payload, testing::Ne("")),
+ Field(&LookupSingleLeakData::encryption_key, testing::Ne("")))));
+ task_env.RunUntilIdle();
+}
+
+TEST(LeakDetectionRequestUtils, AnalyzeResponseResult_DecryptionError) {
+ base::test::TaskEnvironment task_env;
+
+ // Force a decryption error by returning trash bytes.
+ auto response = std::make_unique<SingleLookupResponse>();
+ response->reencrypted_lookup_hash = "trash_bytes";
+
+ base::MockCallback<SingleLeakResponseAnalysisCallback> callback;
+ AnalyzeResponse(std::move(response), "random_key", callback.Get());
+ EXPECT_CALL(callback, Run(AnalyzeResponseResult::kDecryptionError));
+ task_env.RunUntilIdle();
+}
+
+TEST(LeakDetectionRequestUtils, AnalyzeResponseResult_NoLeak) {
+ base::test::TaskEnvironment task_env;
+
+ constexpr char kUsernamePasswordHash[] = "abcdefg";
+ auto response = std::make_unique<SingleLookupResponse>();
+ std::string key_client;
+ std::string encrypted_username_password =
+ CipherEncrypt(kUsernamePasswordHash, &key_client);
+ std::string key_server;
+ response->reencrypted_lookup_hash =
+ CipherReEncrypt(encrypted_username_password, &key_server);
+ SCOPED_TRACE(testing::Message()
+ << "key_client="
+ << testing::PrintToString(StringToArray(key_client))
+ << ", key_server="
+ << testing::PrintToString(StringToArray(key_server)));
+
+ response->encrypted_leak_match_prefixes.push_back(crypto::SHA256HashString(
+ CipherEncryptWithKey("unrelated_trash", key_server)));
+
+ base::MockCallback<SingleLeakResponseAnalysisCallback> callback;
+ AnalyzeResponse(std::move(response), key_client, callback.Get());
+ EXPECT_CALL(callback, Run(AnalyzeResponseResult::kNotLeaked));
+ task_env.RunUntilIdle();
+}
+
+TEST(LeakDetectionRequestUtils, AnalyzeResponseResult_Leak) {
+ base::test::TaskEnvironment task_env;
+
+ constexpr char kUsernamePasswordHash[] = "abcdefg";
+ auto response = std::make_unique<SingleLookupResponse>();
+ std::string key_client;
+ std::string encrypted_username_password =
+ CipherEncrypt(kUsernamePasswordHash, &key_client);
+ std::string key_server;
+ response->reencrypted_lookup_hash =
+ CipherReEncrypt(encrypted_username_password, &key_server);
+ SCOPED_TRACE(testing::Message()
+ << "key_client="
+ << testing::PrintToString(StringToArray(key_client))
+ << ", key_server="
+ << testing::PrintToString(StringToArray(key_server)));
+
+ // Random length of the prefix for values in |encrypted_leak_match_prefixes|.
+ // The server can pick any value.
+ constexpr int kPrefixLength = 30;
+ response->encrypted_leak_match_prefixes.push_back(crypto::SHA256HashString(
+ CipherEncryptWithKey("unrelated_trash", key_server)));
+ response->encrypted_leak_match_prefixes.push_back(
+ crypto::SHA256HashString(
+ CipherEncryptWithKey(kUsernamePasswordHash, key_server))
+ .substr(0, kPrefixLength));
+
+ base::MockCallback<SingleLeakResponseAnalysisCallback> callback;
+
+ AnalyzeResponse(std::move(response), key_client, callback.Get());
+ EXPECT_CALL(callback, Run(AnalyzeResponseResult::kLeaked));
+ task_env.RunUntilIdle();
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.cc b/chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.cc
new file mode 100644
index 00000000000..9f7f3b005a6
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.cc
@@ -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.
+
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+
+namespace password_manager {
+
+MockLeakDetectionDelegateInterface::MockLeakDetectionDelegateInterface() =
+ default;
+MockLeakDetectionDelegateInterface::~MockLeakDetectionDelegateInterface() =
+ default;
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h b/chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h
new file mode 100644
index 00000000000..3bd76b8c965
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_DELEGATE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_DELEGATE_H_
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace password_manager {
+
+class MockLeakDetectionDelegateInterface
+ : public LeakDetectionDelegateInterface {
+ public:
+ MockLeakDetectionDelegateInterface();
+ ~MockLeakDetectionDelegateInterface() override;
+
+ // LeakDetectionDelegateInterface:
+ MOCK_METHOD4(OnLeakDetectionDone,
+ void(bool, GURL, base::string16, base::string16));
+ MOCK_METHOD1(OnError, void(LeakDetectionError));
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_DELEGATE_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.cc b/chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.cc
new file mode 100644
index 00000000000..4986958830d
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.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 "components/password_manager/core/browser/leak_detection/single_lookup_response.h"
+
+namespace password_manager {
+
+SingleLookupResponse::SingleLookupResponse() = default;
+
+SingleLookupResponse::SingleLookupResponse(const SingleLookupResponse& other) =
+ default;
+
+SingleLookupResponse& SingleLookupResponse::operator=(
+ const SingleLookupResponse& other) = default;
+
+SingleLookupResponse::SingleLookupResponse(SingleLookupResponse&& other) =
+ default;
+
+SingleLookupResponse& SingleLookupResponse::operator=(
+ SingleLookupResponse&& other) = default;
+
+SingleLookupResponse::~SingleLookupResponse() = default;
+
+bool operator==(const SingleLookupResponse& lhs,
+ const SingleLookupResponse& rhs) {
+ return lhs.encrypted_leak_match_prefixes ==
+ rhs.encrypted_leak_match_prefixes &&
+ lhs.reencrypted_lookup_hash == rhs.reencrypted_lookup_hash;
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.h b/chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.h
new file mode 100644
index 00000000000..8eb5a2a185d
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection/single_lookup_response.h
@@ -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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_SINGLE_LOOKUP_RESPONSE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_SINGLE_LOOKUP_RESPONSE_H_
+
+#include <string>
+#include <vector>
+
+namespace password_manager {
+
+// This class encapsulates the data required to determine whether a given
+// credential was leaked. It is a more convenient data representation of the
+// protobuf used for network communication.
+struct SingleLookupResponse {
+ SingleLookupResponse();
+ SingleLookupResponse(const SingleLookupResponse& other);
+ SingleLookupResponse& operator=(const SingleLookupResponse& other);
+ SingleLookupResponse(SingleLookupResponse&& other);
+ SingleLookupResponse& operator=(SingleLookupResponse&& other);
+ ~SingleLookupResponse();
+
+ std::vector<std::string> encrypted_leak_match_prefixes;
+ std::string reencrypted_lookup_hash;
+};
+
+bool operator==(const SingleLookupResponse& lhs,
+ const SingleLookupResponse& rhs);
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_SINGLE_LOOKUP_RESPONSE_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate.cc b/chromium/components/password_manager/core/browser/leak_detection_delegate.cc
new file mode 100644
index 00000000000..56a9fd808c2
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -0,0 +1,114 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection_delegate.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/save_password_progress_logger.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h"
+#include "components/password_manager/core/browser/leak_detection_delegate_helper.h"
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
+#include "components/password_manager/core/browser/password_manager_client.h"
+#include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace password_manager {
+
+using Logger = autofill::SavePasswordProgressLogger;
+
+LeakDetectionDelegate::LeakDetectionDelegate(PasswordManagerClient* client)
+ : client_(client),
+ leak_factory_(std::make_unique<LeakDetectionCheckFactoryImpl>()) {}
+
+LeakDetectionDelegate::~LeakDetectionDelegate() = default;
+
+void LeakDetectionDelegate::StartLeakCheck(const autofill::PasswordForm& form) {
+ if (client_->IsIncognito())
+ return;
+
+ if (!client_->GetPrefs()->GetBoolean(
+ password_manager::prefs::kPasswordLeakDetectionEnabled)) {
+ return;
+ }
+
+ if (form.username_value.empty())
+ return;
+
+ DCHECK(!form.password_value.empty());
+ leak_check_ = leak_factory_->TryCreateLeakCheck(
+ this, client_->GetIdentityManager(), client_->GetURLLoaderFactory());
+ if (leak_check_) {
+ is_leaked_timer_ = std::make_unique<base::ElapsedTimer>();
+ leak_check_->Start(form.origin, form.username_value, form.password_value);
+ }
+}
+
+void LeakDetectionDelegate::OnLeakDetectionDone(bool is_leaked,
+ GURL url,
+ base::string16 username,
+ base::string16 password) {
+ leak_check_.reset();
+ if (password_manager_util::IsLoggingActive(client_)) {
+ BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
+ logger.LogBoolean(Logger::STRING_LEAK_DETECTION_FINISHED, is_leaked);
+ }
+ if (is_leaked) {
+ if (client_->GetPasswordSyncState() != SYNCING_NORMAL_ENCRYPTION) {
+ // If the credentials are not synced, the |CredentialLeakType| needed to
+ // show the correct notification is already determined.
+ OnShowLeakDetectionNotification(
+ CreateLeakType(IsSaved(false), IsReused(false), IsSyncing(false)),
+ std::move(url), std::move(username));
+ } else {
+ // Otherwise query the helper to asynchronously determine the
+ // |CredentialLeakType|.
+ helper_ = std::make_unique<LeakDetectionDelegateHelper>(base::BindOnce(
+ &LeakDetectionDelegate::OnShowLeakDetectionNotification,
+ base::Unretained(this)));
+ helper_->GetCredentialLeakType(client_->GetPasswordStore(),
+ std::move(url), std::move(username),
+ std::move(password));
+ }
+ }
+}
+
+void LeakDetectionDelegate::OnShowLeakDetectionNotification(
+ CredentialLeakType leak_type,
+ GURL url,
+ base::string16 username) {
+ DCHECK(is_leaked_timer_);
+ base::UmaHistogramTimes("PasswordManager.LeakDetection.NotifyIsLeakedTime",
+ std::exchange(is_leaked_timer_, nullptr)->Elapsed());
+ helper_.reset();
+ client_->NotifyUserCredentialsWereLeaked(leak_type, url);
+}
+
+void LeakDetectionDelegate::OnError(LeakDetectionError error) {
+ leak_check_.reset();
+
+ if (password_manager_util::IsLoggingActive(client_)) {
+ BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
+ switch (error) {
+ case LeakDetectionError::kNotSignIn:
+ logger.LogMessage(Logger::STRING_LEAK_DETECTION_SIGNED_OUT_ERROR);
+ break;
+ case LeakDetectionError::kTokenRequestFailure:
+ logger.LogMessage(Logger::STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR);
+ break;
+ case LeakDetectionError::kHashingFailure:
+ logger.LogMessage(Logger::STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR);
+ break;
+ case LeakDetectionError::kInvalidServerResponse:
+ logger.LogMessage(
+ Logger::STRING_LEAK_DETECTION_INVALID_SERVER_RESPONSE_ERROR);
+ break;
+ }
+ }
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate.h b/chromium/components/password_manager/core/browser/leak_detection_delegate.h
new file mode 100644
index 00000000000..d0528253773
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DELEGATE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DELEGATE_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/timer/elapsed_timer.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
+
+namespace autofill {
+struct PasswordForm;
+} // namespace autofill
+
+namespace password_manager {
+
+class LeakDetectionCheck;
+class LeakDetectionDelegateHelper;
+class PasswordManagerClient;
+
+// The helper class that encapsulates the requests and their processing.
+class LeakDetectionDelegate : public LeakDetectionDelegateInterface {
+ public:
+ explicit LeakDetectionDelegate(PasswordManagerClient* client);
+ ~LeakDetectionDelegate() override;
+
+ // Not copyable or movable
+ LeakDetectionDelegate(const LeakDetectionDelegate&) = delete;
+ LeakDetectionDelegate& operator=(const LeakDetectionDelegate&) = delete;
+ LeakDetectionDelegate(LeakDetectionDelegate&&) = delete;
+ LeakDetectionDelegate& operator=(LeakDetectionDelegate&&) = delete;
+
+#if defined(UNIT_TEST)
+ void set_leak_factory(std::unique_ptr<LeakDetectionCheckFactory> factory) {
+ leak_factory_ = std::move(factory);
+ }
+
+ LeakDetectionCheck* leak_check() const { return leak_check_.get(); }
+#endif // defined(UNIT_TEST)
+
+ void StartLeakCheck(const autofill::PasswordForm& form);
+
+ private:
+ // LeakDetectionDelegateInterface:
+ void OnLeakDetectionDone(bool is_leaked,
+ GURL url,
+ base::string16 username,
+ base::string16 password) override;
+
+ // Initiates the showing of the leak detection notification. If the account is
+ // synced, it is called by |helper_| after the |leak_type| was asynchronously
+ // determined.
+ void OnShowLeakDetectionNotification(CredentialLeakType leak_type,
+ GURL url,
+ base::string16 username);
+
+ void OnError(LeakDetectionError error) override;
+
+ PasswordManagerClient* client_;
+ // The factory that creates objects for performing a leak check up.
+ std::unique_ptr<LeakDetectionCheckFactory> leak_factory_;
+
+ // Current leak check-up being performed in the background.
+ std::unique_ptr<LeakDetectionCheck> leak_check_;
+
+ // Timer measuring the time it takes from StartLeakCheck() until a call to
+ // OnLeakDetectionDone() with is_leaked = true.
+ std::unique_ptr<base::ElapsedTimer> is_leaked_timer_;
+
+ // Helper class to asynchronously determine |CredentialLeakType| for leaked
+ // credentials.
+ std::unique_ptr<LeakDetectionDelegateHelper> helper_;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DELEGATE_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate_helper.cc b/chromium/components/password_manager/core/browser/leak_detection_delegate_helper.cc
new file mode 100644
index 00000000000..7f29fb7bce1
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate_helper.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 "components/password_manager/core/browser/leak_detection_delegate_helper.h"
+
+#include "components/password_manager/core/browser/password_store.h"
+
+namespace password_manager {
+
+LeakDetectionDelegateHelper::LeakDetectionDelegateHelper(LeakTypeReply callback)
+ : callback_(std::move(callback)) {}
+
+LeakDetectionDelegateHelper::~LeakDetectionDelegateHelper() = default;
+
+void LeakDetectionDelegateHelper::GetCredentialLeakType(
+ PasswordStore* store,
+ GURL url,
+ base::string16 username,
+ base::string16 password) {
+ DCHECK(store);
+ url_ = std::move(url);
+ username_ = std::move(username);
+ password_ = std::move(password);
+ store->GetLoginsByPassword(password_, this);
+}
+
+void LeakDetectionDelegateHelper::OnGetPasswordStoreResults(
+ std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
+ IsSaved is_saved(
+ std::any_of(results.begin(), results.end(), [this](const auto& form) {
+ return form->origin == url_ && form->username_value == username_;
+ }));
+
+ IsReused is_reused(results.size() > (is_saved ? 1 : 0));
+ CredentialLeakType leak_type =
+ CreateLeakType(is_saved, is_reused, IsSyncing(true));
+ std::move(callback_).Run(std::move(leak_type), std::move(url_),
+ std::move(username_));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate_helper.h b/chromium/components/password_manager/core/browser/leak_detection_delegate_helper.h
new file mode 100644
index 00000000000..4a800e8e9d0
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate_helper.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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DELEGATE_HELPER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DELEGATE_HELPER_H_
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
+#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "url/gurl.h"
+
+namespace password_manager {
+
+class LeakDetectionCheck;
+class PasswordStore;
+
+// Helper class to asynchronously requests all credentials with
+// a specific password from the |PasswordStore|.
+class LeakDetectionDelegateHelper : public PasswordStoreConsumer {
+ public:
+ // Type alias for |callback_|.
+ using LeakTypeReply =
+ base::OnceCallback<void(CredentialLeakType, GURL, base::string16)>;
+
+ explicit LeakDetectionDelegateHelper(LeakTypeReply callback);
+ ~LeakDetectionDelegateHelper() override;
+
+ // Request all credentials with |password| from |store|.
+ // Results are password to |OnGetPasswordStoreResults|.
+ void GetCredentialLeakType(PasswordStore* store,
+ GURL url,
+ base::string16 username,
+ base::string16 password);
+
+ private:
+ // PasswordStoreConsumer:
+ // Is called by the |PasswordStore| once all credentials with the specific
+ // password are retrieved. Determine the |CredentialLeakType and invokes
+ // |callback_| when done.
+ void OnGetPasswordStoreResults(
+ std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
+
+ LeakTypeReply callback_;
+ GURL url_;
+ base::string16 username_;
+ base::string16 password_;
+
+ // Instances should be neither copyable nor assignable.
+ DISALLOW_COPY_AND_ASSIGN(LeakDetectionDelegateHelper);
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DELEGATE_HELPER_H_
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc
new file mode 100644
index 00000000000..de3ff6d7af6
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc
@@ -0,0 +1,180 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/leak_detection_delegate_helper.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/mock_callback.h"
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
+#include "components/password_manager/core/browser/mock_password_store.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using autofill::PasswordForm;
+using base::ASCIIToUTF16;
+using base::BindOnce;
+using base::MockCallback;
+using base::Unretained;
+using testing::_;
+using testing::StrictMock;
+using testing::WithArg;
+
+namespace password_manager {
+
+namespace {
+constexpr char kLeakedPassword[] = "leaked_password";
+constexpr char kLeakedUsername[] = "leaked_username";
+constexpr char kOtherUsername[] = "other_username";
+constexpr char kLeakedOrigin[] = "https://www.leaked_origin.de/login";
+constexpr char kOtherOrigin[] = "https://www.other_origin.de/login";
+
+// Creates a |PasswordForm| with the supplied |origin| and |username|. The
+// password is always set to |kLeakedPassword|.
+PasswordForm CreateForm(base::StringPiece origin, base::StringPiece username) {
+ PasswordForm form;
+ form.origin = GURL(ASCIIToUTF16(origin));
+ form.username_value = ASCIIToUTF16(username);
+ form.password_value = ASCIIToUTF16(kLeakedPassword);
+ form.signon_realm = form.origin.GetOrigin().spec();
+ return form;
+}
+
+// Used to mimic the callback of the |PasswordStore|. Converts the vector of
+// |PasswordForm|s to a vector of unique pointers to |PasswordForm|s.
+ACTION_P(InvokeConsumerWithPasswordForms, forms) {
+ std::vector<std::unique_ptr<autofill::PasswordForm>> results;
+ for (const auto& form : forms) {
+ results.push_back(std::make_unique<PasswordForm>(form));
+ }
+ arg0->OnGetPasswordStoreResults(std::move(results));
+}
+
+} // namespace
+
+class LeakDetectionDelegateHelperTest : public testing::Test {
+ public:
+ LeakDetectionDelegateHelperTest() = default;
+ ~LeakDetectionDelegateHelperTest() override = default;
+
+ protected:
+ void SetUp() override {
+ store_ = new testing::StrictMock<MockPasswordStore>;
+
+ delegate_helper_ =
+ std::make_unique<LeakDetectionDelegateHelper>(callback_.Get());
+ }
+
+ void TearDown() override {
+ store_->ShutdownOnUIThread();
+ store_ = nullptr;
+ }
+
+ // Initiates determining the credential leak type.
+ void InitiateGetCredentialLeakType() {
+ delegate_helper_->GetCredentialLeakType(store_.get(), GURL(kLeakedOrigin),
+ ASCIIToUTF16(kLeakedUsername),
+ ASCIIToUTF16(kLeakedPassword));
+ }
+
+ // Sets the |PasswordForm|s which are retrieve from the |PasswordStore|.
+ void SetGetLoginByPasswordConsumerInvocation(
+ std::vector<PasswordForm> password_forms) {
+ EXPECT_CALL(*store_.get(), GetLoginsByPassword(_, _))
+ .WillRepeatedly(
+ WithArg<1>(InvokeConsumerWithPasswordForms(password_forms)));
+ }
+
+ // Set the expectation for the |CredentialLeakType| in the callback_.
+ void SetOnShowLeakDetectionNotificationExpectation(IsSaved is_saved,
+ IsReused is_reused) {
+ EXPECT_CALL(callback_,
+ Run(CreateLeakType(is_saved, is_reused, IsSyncing(true)),
+ GURL(kLeakedOrigin), ASCIIToUTF16(kLeakedUsername)))
+ .Times(1);
+ }
+
+ MockCallback<LeakDetectionDelegateHelper::LeakTypeReply> callback_;
+ scoped_refptr<MockPasswordStore> store_;
+ std::unique_ptr<LeakDetectionDelegateHelper> delegate_helper_;
+};
+
+// Credentials are neither saved nor is the password reused.
+TEST_F(LeakDetectionDelegateHelperTest, NeitherSaveNotReused) {
+ std::vector<PasswordForm> password_forms;
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(false),
+ IsReused(false));
+ InitiateGetCredentialLeakType();
+}
+
+// Credentials are saved but the password is not reused.
+TEST_F(LeakDetectionDelegateHelperTest, SavedLeakedCredentials) {
+ std::vector<PasswordForm> password_forms = {
+ CreateForm(kLeakedOrigin, kLeakedUsername)};
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(true), IsReused(false));
+ InitiateGetCredentialLeakType();
+}
+
+// Credentials are saved and the password is reused on a different origin.
+TEST_F(LeakDetectionDelegateHelperTest,
+ SavedCredentialsAndReusedPasswordOnOtherOrigin) {
+ std::vector<PasswordForm> password_forms = {
+ CreateForm(kLeakedOrigin, kLeakedUsername),
+ CreateForm(kOtherOrigin, kLeakedUsername)};
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(true), IsReused(true));
+ InitiateGetCredentialLeakType();
+}
+
+// Credentials are saved and the password is reused on the same origin with
+// a different username.
+TEST_F(LeakDetectionDelegateHelperTest,
+ SavedCredentialsAndReusedPasswordWithOtherUsername) {
+ std::vector<PasswordForm> password_forms = {
+ CreateForm(kLeakedOrigin, kLeakedUsername),
+ CreateForm(kLeakedOrigin, kOtherUsername)};
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(true), IsReused(true));
+ InitiateGetCredentialLeakType();
+}
+
+// Credentials are not saved but the password is reused.
+TEST_F(LeakDetectionDelegateHelperTest, ReusedPasswordWithOtherUsername) {
+ std::vector<PasswordForm> password_forms = {
+ CreateForm(kLeakedOrigin, kOtherUsername)};
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(false), IsReused(true));
+ InitiateGetCredentialLeakType();
+}
+
+// Credentials are not saved but the password is reused on a different origin.
+TEST_F(LeakDetectionDelegateHelperTest, ReusedPasswordOnOtherOrigin) {
+ std::vector<PasswordForm> password_forms = {
+ CreateForm(kOtherOrigin, kLeakedUsername)};
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(false), IsReused(true));
+ InitiateGetCredentialLeakType();
+}
+
+// Credentials are not saved but the password is reused with a different
+// username on a different origin.
+TEST_F(LeakDetectionDelegateHelperTest, ReusedPassword) {
+ std::vector<PasswordForm> password_forms = {
+ CreateForm(kOtherOrigin, kOtherUsername)};
+
+ SetGetLoginByPasswordConsumerInvocation(std::move(password_forms));
+ SetOnShowLeakDetectionNotificationExpectation(IsSaved(false), IsReused(true));
+ InitiateGetCredentialLeakType();
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
new file mode 100644
index 00000000000..274df3d6d43
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright 2019 The Chromium Authors. 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 "components/password_manager/core/browser/leak_detection_delegate.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
+#include "components/password_manager/core/browser/stub_password_manager_client.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace password_manager {
+namespace {
+
+using base::ASCIIToUTF16;
+using testing::_;
+using testing::ByMove;
+using testing::Eq;
+using testing::Return;
+
+autofill::PasswordForm CreateTestForm() {
+ autofill::PasswordForm form;
+ form.origin = GURL("http://www.example.com/a/LoginAuth");
+ form.username_value = ASCIIToUTF16("Adam");
+ form.password_value = ASCIIToUTF16("p4ssword");
+ form.signon_realm = "http://www.example.com/";
+ return form;
+}
+
+class MockPasswordManagerClient : public StubPasswordManagerClient {
+ public:
+ MockPasswordManagerClient() = default;
+ ~MockPasswordManagerClient() override = default;
+
+ MOCK_CONST_METHOD0(IsIncognito, bool());
+ MOCK_CONST_METHOD0(GetPrefs, PrefService*());
+ MOCK_METHOD2(NotifyUserCredentialsWereLeaked,
+ void(password_manager::CredentialLeakType, const GURL&));
+};
+
+class MockLeakDetectionCheck : public LeakDetectionCheck {
+ public:
+ MOCK_METHOD3(Start, void(const GURL&, base::string16, base::string16));
+};
+
+class MockLeakDetectionCheckFactory : public LeakDetectionCheckFactory {
+ public:
+ MOCK_CONST_METHOD3(TryCreateLeakCheck,
+ std::unique_ptr<LeakDetectionCheck>(
+ LeakDetectionDelegateInterface*,
+ signin::IdentityManager*,
+ scoped_refptr<network::SharedURLLoaderFactory>));
+};
+
+} // namespace
+
+class LeakDetectionDelegateTest : public testing::Test {
+ public:
+ LeakDetectionDelegateTest() : delegate_(&client_) {
+ auto mock_factory =
+ std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>();
+ mock_factory_ = mock_factory.get();
+ delegate_.set_leak_factory(std::move(mock_factory));
+ prefs_ = std::make_unique<TestingPrefServiceSimple>();
+ prefs_->registry()->RegisterBooleanPref(
+ password_manager::prefs::kPasswordLeakDetectionEnabled, true);
+ ON_CALL(client_, GetPrefs()).WillByDefault(Return(prefs_.get()));
+ }
+ ~LeakDetectionDelegateTest() override = default;
+
+ MockPasswordManagerClient& client() { return client_; }
+ MockLeakDetectionCheckFactory& factory() { return *mock_factory_; }
+ LeakDetectionDelegate& delegate() { return delegate_; }
+
+ protected:
+ std::unique_ptr<TestingPrefServiceSimple> prefs_;
+
+ private:
+ testing::NiceMock<MockPasswordManagerClient> client_;
+ MockLeakDetectionCheckFactory* mock_factory_ = nullptr;
+ LeakDetectionDelegate delegate_;
+};
+
+TEST_F(LeakDetectionDelegateTest, InIncognito) {
+ const autofill::PasswordForm form = CreateTestForm();
+ EXPECT_CALL(client(), IsIncognito).WillOnce(Return(true));
+ EXPECT_CALL(factory(), TryCreateLeakCheck).Times(0);
+ delegate().StartLeakCheck(form);
+
+ EXPECT_FALSE(delegate().leak_check());
+}
+
+TEST_F(LeakDetectionDelegateTest, PrefIsFalse) {
+ const autofill::PasswordForm form = CreateTestForm();
+ prefs_->SetBoolean(password_manager::prefs::kPasswordLeakDetectionEnabled,
+ false);
+
+ EXPECT_CALL(factory(), TryCreateLeakCheck).Times(0);
+ delegate().StartLeakCheck(form);
+
+ EXPECT_FALSE(delegate().leak_check());
+}
+
+TEST_F(LeakDetectionDelegateTest, UsernameIsEmpty) {
+ autofill::PasswordForm form = CreateTestForm();
+ form.username_value.clear();
+
+ EXPECT_CALL(factory(), TryCreateLeakCheck).Times(0);
+ delegate().StartLeakCheck(form);
+
+ EXPECT_FALSE(delegate().leak_check());
+}
+
+TEST_F(LeakDetectionDelegateTest, StartCheck) {
+ const autofill::PasswordForm form = CreateTestForm();
+ EXPECT_CALL(client(), IsIncognito).WillOnce(Return(false));
+ auto check_instance = std::make_unique<MockLeakDetectionCheck>();
+ EXPECT_CALL(*check_instance,
+ Start(form.origin, form.username_value, form.password_value));
+ EXPECT_CALL(factory(), TryCreateLeakCheck(&delegate(), _, _))
+ .WillOnce(Return(ByMove(std::move(check_instance))));
+ delegate().StartLeakCheck(form);
+
+ EXPECT_TRUE(delegate().leak_check());
+}
+
+TEST_F(LeakDetectionDelegateTest, LeakDetectionDone) {
+ base::HistogramTester histogram_tester;
+ LeakDetectionDelegateInterface* delegate_interface = &delegate();
+ const autofill::PasswordForm form = CreateTestForm();
+
+ EXPECT_CALL(factory(), TryCreateLeakCheck)
+ .WillOnce(Return(ByMove(std::make_unique<MockLeakDetectionCheck>())));
+ delegate().StartLeakCheck(form);
+
+ EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked).Times(0);
+ delegate_interface->OnLeakDetectionDone(
+ false, form.origin, form.username_value, form.password_value);
+ histogram_tester.ExpectTotalCount(
+ "PasswordManager.LeakDetection.NotifyIsLeakedTime", 0);
+
+ EXPECT_CALL(client(),
+ NotifyUserCredentialsWereLeaked(
+ password_manager::CreateLeakType(
+ IsSaved(false), IsReused(false), IsSyncing(false)),
+ form.origin));
+ delegate_interface->OnLeakDetectionDone(
+ true, form.origin, form.username_value, form.password_value);
+ histogram_tester.ExpectTotalCount(
+ "PasswordManager.LeakDetection.NotifyIsLeakedTime", 1);
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc
new file mode 100644
index 00000000000..654f5a5ab83
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc
@@ -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.
+
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
+
+namespace password_manager {
+
+CredentialLeakType CreateLeakType(IsSaved is_saved,
+ IsReused is_reused,
+ IsSyncing is_syncing) {
+ CredentialLeakType leak_type = 0;
+ if (is_saved)
+ leak_type |= kPasswordSaved;
+ if (is_reused)
+ leak_type |= kPasswordUsedOnOtherSites;
+ if (is_syncing)
+ leak_type |= kSyncingPasswordsNormally;
+ return leak_type;
+}
+
+bool IsPasswordSaved(CredentialLeakType leak_type) {
+ return leak_type & CredentialLeakFlags::kPasswordSaved;
+}
+
+bool IsPasswordUsedOnOtherSites(CredentialLeakType leak_type) {
+ return leak_type & CredentialLeakFlags::kPasswordUsedOnOtherSites;
+}
+
+bool IsSyncingPasswordsNormally(CredentialLeakType leak_type) {
+ return leak_type & CredentialLeakFlags::kSyncingPasswordsNormally;
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h
new file mode 100644
index 00000000000..867d864c4c9
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h
@@ -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.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DIALOG_UTILS_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DIALOG_UTILS_H_
+
+#include <type_traits>
+
+#include "base/util/type_safety/strong_alias.h"
+
+namespace password_manager {
+
+// Defines possible scenarios for leaked credentials.
+enum CredentialLeakFlags {
+ // Password is saved for current site.
+ kPasswordSaved = 1 << 0,
+ // Password is reused on other sites.
+ kPasswordUsedOnOtherSites = 1 << 1,
+ // User is syncing passwords with normal encryption.
+ kSyncingPasswordsNormally = 1 << 2,
+};
+
+// Contains combination of CredentialLeakFlags values.
+using CredentialLeakType = std::underlying_type_t<CredentialLeakFlags>;
+
+using IsSaved = util::StrongAlias<class IsSavedTag, bool>;
+using IsReused = util::StrongAlias<class IsReusedTag, bool>;
+using IsSyncing = util::StrongAlias<class IsSyncingTag, bool>;
+
+// Creates CredentialLeakType from strong booleans.
+CredentialLeakType CreateLeakType(IsSaved is_saved,
+ IsReused is_reused,
+ IsSyncing is_syncing);
+
+// Checks whether password is saved in chrome.
+bool IsPasswordSaved(CredentialLeakType leak_type);
+
+// Checks whether password is reused on other sites.
+bool IsPasswordUsedOnOtherSites(CredentialLeakType leak_type);
+
+// Checks whether user is syncing passwords with normal encryption.
+bool IsSyncingPasswordsNormally(CredentialLeakType leak_type);
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_DIALOG_UTILS_H_
diff --git a/chromium/components/password_manager/core/browser/login_database.cc b/chromium/components/password_manager/core/browser/login_database.cc
index 5e3dc0ee71c..136771b0566 100644
--- a/chromium/components/password_manager/core/browser/login_database.cc
+++ b/chromium/components/password_manager/core/browser/login_database.cc
@@ -54,7 +54,7 @@ using autofill::PasswordForm;
namespace password_manager {
// The current version number of the login database schema.
-const int kCurrentVersionNumber = 24;
+const int kCurrentVersionNumber = 25;
// The oldest version of the schema such that a legacy Chrome client using that
// version can still read/write the current database.
const int kCompatibleVersionNumber = 19;
@@ -125,6 +125,7 @@ enum LoginDatabaseTableColumns {
COLUMN_GENERATION_UPLOAD_STATUS,
COLUMN_POSSIBLE_USERNAME_PAIRS,
COLUMN_ID,
+ COLUMN_DATE_LAST_USED,
COLUMN_NUM // Keep this last.
};
@@ -191,6 +192,8 @@ void BindAddStatement(const PasswordForm& form,
SerializeValueElementPairs(form.all_possible_usernames);
s->BindBlob(COLUMN_POSSIBLE_USERNAME_PAIRS, usernames_pickle.data(),
usernames_pickle.size());
+ s->BindInt64(COLUMN_DATE_LAST_USED,
+ form.date_last_used.ToDeltaSinceWindowsEpoch().InMicroseconds());
}
// Output parameter is the first one because of binding order.
@@ -521,6 +524,11 @@ void InitializeBuilders(SQLTableBuilders builders) {
// start clean from scratch.
SealVersion(builders, /*expected_version=*/24u);
+ // Version 25. Introduce date_last_used column to replace the preferred
+ // column. MigrateLogins() will take care of migrating the data.
+ builders.logins->AddColumn("date_last_used", "INTEGER NOT NULL DEFAULT 0");
+ SealVersion(builders, /*expected_version=*/25u);
+
DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builders.logins->NumberOfColumns())
<< "Adjust LoginDatabaseTableColumns if you change column definitions "
"here.";
@@ -567,6 +575,26 @@ bool MigrateLogins(unsigned current_version,
return false;
}
+ // "date_last_used" column has been introduced and we should migrate the data
+ // in "preferred" column. We set the value of "date_last_used"
+ // deterministically such the final output will be consistent across syncing
+ // clients.
+ // TODO(crbug.com/997670): Drop the "preferred" column together with this
+ // migration code in M82.
+ if (current_version < 25) {
+ sql::Statement preferred_stmt;
+ preferred_stmt.Assign(db->GetCachedStatement(
+ SQL_FROM_HERE,
+ "UPDATE logins SET date_last_used = ? WHERE preferred > 0"));
+ // Set the preferred password to be last used one day after the Windows
+ // Epoch to make sure the "preferred" password is used more recently.
+ // Non-preferred passwords carry the default value of 0 (which maps to the
+ // Windows Epoch).
+ preferred_stmt.BindInt64(0, base::TimeDelta::FromDays(1).InMicroseconds());
+ if (!preferred_stmt.Run())
+ return false;
+ }
+
return true;
}
@@ -595,6 +623,13 @@ bool FixVersionIfNeeded(sql::Database* db, int* current_version) {
if (db->DoesColumnExist("logins", "form_data"))
*current_version = 4;
}
+ // "date_last_used" columns has been introduced in version 25. if it exists,
+ // the version should be at least 25. This has been added to address this bug
+ // (crbug.com/1020320).
+ if (*current_version < 25) {
+ if (db->DoesColumnExist("logins", "date_last_used"))
+ *current_version = 25;
+ }
return true;
}
@@ -623,8 +658,9 @@ PasswordForm GetFormForRemoval(const sql::Statement& statement) {
} // namespace
-LoginDatabase::LoginDatabase(const base::FilePath& db_path)
- : db_path_(db_path) {}
+LoginDatabase::LoginDatabase(const base::FilePath& db_path,
+ IsAccountStore is_account_store)
+ : db_path_(db_path), is_account_store_(is_account_store) {}
LoginDatabase::~LoginDatabase() {
}
@@ -708,7 +744,6 @@ bool LoginDatabase::Init() {
int current_version = meta_table_.GetVersionNumber();
bool migration_success = FixVersionIfNeeded(&db_, &current_version);
- DCHECK_LE(current_version, kCurrentVersionNumber);
// If the file on disk is an older database version, bring it up to date.
if (migration_success && current_version < kCurrentVersionNumber) {
@@ -719,8 +754,13 @@ bool LoginDatabase::Init() {
migration_success = stats_table_.MigrateToVersion(16);
}
if (migration_success) {
- meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber);
- meta_table_.SetVersionNumber(kCurrentVersionNumber);
+ // |migration_success| could be true when no logins have been actually
+ // migrated. We should protect against downgrading the database version in
+ // such case. Update the database version only if a migration took place.
+ if (current_version < kCurrentVersionNumber) {
+ meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber);
+ meta_table_.SetVersionNumber(kCurrentVersionNumber);
+ }
} else {
LogDatabaseInitError(MIGRATION_ERROR);
LOG(ERROR) << "Unable to migrate database from "
@@ -979,7 +1019,6 @@ PasswordStoreChangeList LoginDatabase::AddLogin(const PasswordForm& form,
}
return list;
}
-
DCHECK(!add_statement_.empty());
sql::Statement s(
db_.GetCachedStatement(SQL_FROM_HERE, add_statement_.c_str()));
@@ -1079,6 +1118,8 @@ PasswordStoreChangeList LoginDatabase::UpdateLogin(const PasswordForm& form,
base::Pickle username_pickle =
SerializeValueElementPairs(form.all_possible_usernames);
s.BindBlob(next_param++, username_pickle.data(), username_pickle.size());
+ s.BindInt64(next_param++,
+ form.date_last_used.ToDeltaSinceWindowsEpoch().InMicroseconds());
// NOTE: Add new fields here unless the field is a part of the unique key.
// If so, add new field below.
@@ -1306,6 +1347,8 @@ LoginDatabase::EncryptionResult LoginDatabase::InitPasswordFormFromStatement(
form->generation_upload_status =
static_cast<PasswordForm::GenerationUploadStatus>(
generation_upload_status_int);
+ form->date_last_used = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(s.ColumnInt64(COLUMN_DATE_LAST_USED)));
DCHECK(autofill::mojom::IsKnownEnumValue(form->generation_upload_status));
return ENCRYPTION_RESULT_SUCCESS;
}
@@ -1319,8 +1362,7 @@ bool LoginDatabase::GetLogins(
const GURL signon_realm(form.signon_realm);
std::string registered_domain = GetRegistryControlledDomain(signon_realm);
const bool should_PSL_matching_apply =
- form.scheme == PasswordForm::Scheme::kHtml &&
- ShouldPSLDomainMatchingApply(registered_domain);
+ !registered_domain.empty() && form.scheme == PasswordForm::Scheme::kHtml;
const bool should_federated_apply =
form.scheme == PasswordForm::Scheme::kHtml;
DCHECK(!get_statement_.empty());
@@ -1398,6 +1440,35 @@ bool LoginDatabase::GetLogins(
return true;
}
+bool LoginDatabase::GetLoginsByPassword(
+ const base::string16& plain_text_password,
+ std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) {
+ DCHECK(forms);
+ forms->clear();
+
+ // Get all autofillable (not blacklisted) logins.
+ DCHECK(!blacklisted_statement_.empty());
+ sql::Statement s(
+ db_.GetCachedStatement(SQL_FROM_HERE, blacklisted_statement_.c_str()));
+ s.BindInt(0, 0); // blacklisted = false
+
+ // Apply query, check status and copy results if successful.
+ PrimaryKeyToFormMap key_to_form_map;
+ FormRetrievalResult result =
+ StatementToForms(&s, /*matched_form=*/nullptr, &key_to_form_map);
+
+ if (result != FormRetrievalResult::kSuccess) {
+ return false;
+ }
+ for (auto& pair : key_to_form_map) {
+ if (pair.second->password_value == plain_text_password) {
+ // Only add the form the result if the password value matches.
+ forms->push_back(std::move(pair.second));
+ }
+ }
+ return true;
+}
+
bool LoginDatabase::GetLoginsCreatedBetween(
const base::Time begin,
const base::Time end,
diff --git a/chromium/components/password_manager/core/browser/login_database.h b/chromium/components/password_manager/core/browser/login_database.h
index 8934c4670fc..dba2f87f415 100644
--- a/chromium/components/password_manager/core/browser/login_database.h
+++ b/chromium/components/password_manager/core/browser/login_database.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/pickle.h"
#include "base/strings/string16.h"
+#include "base/util/type_safety/strong_alias.h"
#include "build/build_config.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/password_store_change.h"
@@ -40,14 +41,23 @@ class SQLTableBuilder;
extern const int kCurrentVersionNumber;
extern const int kCompatibleVersionNumber;
+using IsAccountStore = util::StrongAlias<class IsAccountStoreTag, bool>;
+
// Interface to the database storage of login information, intended as a helper
// for PasswordStore on platforms that need internal storage of some or all of
// the login information.
class LoginDatabase : public PasswordStoreSync::MetadataStore {
public:
- explicit LoginDatabase(const base::FilePath& db_path);
+ LoginDatabase(const base::FilePath& db_path, IsAccountStore is_account_store);
~LoginDatabase() override;
+ // Returns whether this is the profile-scoped or the account-scoped storage:
+ // true: Gaia-account-scoped store, which is used for signed-in but not
+ // syncing users.
+ // false: Profile-scoped store, which is used for local storage and for
+ // syncing users.
+ bool is_account_store() const { return is_account_store_.value(); }
+
// Actually creates/opens the database. If false is returned, no other method
// should be called.
virtual bool Init();
@@ -119,6 +129,11 @@ class LoginDatabase : public PasswordStoreSync::MetadataStore {
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms)
WARN_UNUSED_RESULT;
+ // Gets a list of credentials with password_value=|plain_text_password|.
+ bool GetLoginsByPassword(const base::string16& plain_text_password,
+ std::vector<std::unique_ptr<autofill::PasswordForm>>*
+ forms) WARN_UNUSED_RESULT;
+
// Gets all logins created from |begin| onwards (inclusive) and before |end|.
// You may use a null Time value to do an unbounded search in either
// direction. |key_to_form_map| must not be null and will be used to return
@@ -191,6 +206,7 @@ class LoginDatabase : public PasswordStoreSync::MetadataStore {
StatisticsTable& stats_table() { return stats_table_; }
#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ void enable_encryption() { use_encryption_ = true; }
// This instance should not encrypt/decrypt password values using OSCrypt.
void disable_encryption() { use_encryption_ = false; }
#endif // defined(OS_POSIX)
@@ -296,7 +312,9 @@ class LoginDatabase : public PasswordStoreSync::MetadataStore {
// enabled, or false otherwise. On all other platforms it returns false.
bool IsUsingCleanupMechanism() const;
- base::FilePath db_path_;
+ const base::FilePath db_path_;
+ const IsAccountStore is_account_store_;
+
mutable sql::Database db_;
sql::MetaTable meta_table_;
StatisticsTable stats_table_;
diff --git a/chromium/components/password_manager/core/browser/login_database_ios_unittest.cc b/chromium/components/password_manager/core/browser/login_database_ios_unittest.cc
index c9cf4b51b75..a59e5b58105 100644
--- a/chromium/components/password_manager/core/browser/login_database_ios_unittest.cc
+++ b/chromium/components/password_manager/core/browser/login_database_ios_unittest.cc
@@ -11,7 +11,7 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/password_form.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -29,7 +29,8 @@ class LoginDatabaseIOSTest : public PlatformTest {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath login_db_path =
temp_dir_.GetPath().AppendASCII("temp_login.db");
- login_db_.reset(new password_manager::LoginDatabase(login_db_path));
+ login_db_.reset(new password_manager::LoginDatabase(
+ login_db_path, password_manager::IsAccountStore(false)));
login_db_->Init();
}
@@ -46,7 +47,7 @@ class LoginDatabaseIOSTest : public PlatformTest {
protected:
base::ScopedTempDir temp_dir_;
std::unique_ptr<LoginDatabase> login_db_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
void LoginDatabaseIOSTest::ClearKeychain() {
diff --git a/chromium/components/password_manager/core/browser/login_database_unittest.cc b/chromium/components/password_manager/core/browser/login_database_unittest.cc
index 58721ec4eff..d83b7f573e9 100644
--- a/chromium/components/password_manager/core/browser/login_database_unittest.cc
+++ b/chromium/components/password_manager/core/browser/login_database_unittest.cc
@@ -18,7 +18,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -81,6 +81,7 @@ void GenerateExamplePasswordForm(PasswordForm* form) {
form->times_used = 1;
form->form_data.name = ASCIIToUTF16("form_name");
form->date_synced = base::Time::Now();
+ form->date_last_used = base::Time::Now();
form->display_name = ASCIIToUTF16("Mr. Smith");
form->icon_url = GURL("https://accounts.google.com/Icon");
form->federation_origin =
@@ -186,7 +187,7 @@ class LoginDatabaseTest : public testing::Test {
file_ = temp_dir_.GetPath().AppendASCII("TestMetadataStoreMacDatabase");
OSCryptMocker::SetUp();
- db_.reset(new LoginDatabase(file_));
+ db_.reset(new LoginDatabase(file_, IsAccountStore(false)));
ASSERT_TRUE(db_->Init());
}
@@ -273,7 +274,7 @@ class LoginDatabaseTest : public testing::Test {
base::ScopedTempDir temp_dir_;
base::FilePath file_;
std::unique_ptr<LoginDatabase> db_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(LoginDatabaseTest, Logins) {
@@ -370,6 +371,8 @@ TEST_F(LoginDatabaseTest, Logins) {
PasswordForm form5(form4);
form5.password_value = ASCIIToUTF16("test6");
form5.preferred = true;
+ const base::Time kNow = base::Time::Now();
+ form5.date_last_used = kNow;
// We update, and check to make sure it matches the
// old form, and there is only one record.
@@ -385,6 +388,8 @@ TEST_F(LoginDatabaseTest, Logins) {
EXPECT_EQ(form5.password_value, result[0]->password_value);
// Preferred login.
EXPECT_TRUE(form5.preferred);
+ // Date last used.
+ EXPECT_EQ(kNow, form5.date_last_used);
result.clear();
// Make sure everything can disappear.
@@ -607,17 +612,12 @@ TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingShouldMatchingApply) {
EXPECT_TRUE(db().GetAutofillableLogins(&result));
EXPECT_EQ(0U, result.size());
- // Example password form.
+ // Saved password form on Google sign-in page.
PasswordForm form;
form.origin = GURL("https://accounts.google.com/");
- form.action = GURL("https://accounts.google.com/login");
- form.username_element = ASCIIToUTF16("username");
form.username_value = ASCIIToUTF16("test@gmail.com");
- form.password_element = ASCIIToUTF16("password");
form.password_value = ASCIIToUTF16("test");
- form.submit_element = ASCIIToUTF16("");
form.signon_realm = "https://accounts.google.com/";
- form.preferred = false;
form.scheme = PasswordForm::Scheme::kHtml;
// Add it and make sure it is there.
@@ -628,20 +628,26 @@ TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingShouldMatchingApply) {
// Match against an exact copy.
EXPECT_TRUE(db().GetLogins(PasswordStore::FormDigest(form), &result));
- EXPECT_EQ(1U, result.size());
+ ASSERT_EQ(1U, result.size());
+ EXPECT_EQ(form.signon_realm, result[0]->signon_realm);
result.clear();
- // We go to a different site on the same domain where feature is not needed.
+ // Google change password should match to the saved sign-in form.
PasswordStore::FormDigest form2 = {PasswordForm::Scheme::kHtml,
+ "https://myaccount.google.com/",
+ GURL("https://myaccount.google.com/")};
+
+ EXPECT_TRUE(db().GetLogins(form2, &result));
+ ASSERT_EQ(1U, result.size());
+ EXPECT_EQ(form.signon_realm, result[0]->signon_realm);
+ EXPECT_TRUE(result[0]->is_public_suffix_match);
+
+ // There should be no PSL match on other subdomains.
+ PasswordStore::FormDigest form3 = {PasswordForm::Scheme::kHtml,
"https://some.other.google.com/",
GURL("https://some.other.google.com/")};
- // Match against the other site. Should not match since feature should not be
- // enabled for this domain.
- ASSERT_FALSE(ShouldPSLDomainMatchingApply(
- GetRegistryControlledDomain(GURL(form2.signon_realm))));
-
- EXPECT_TRUE(db().GetLogins(form2, &result));
+ EXPECT_TRUE(db().GetLogins(form3, &result));
EXPECT_EQ(0U, result.size());
}
@@ -681,8 +687,6 @@ TEST_F(LoginDatabaseTest, TestFederatedMatchingWithoutPSLMatching) {
EXPECT_THAT(result, testing::ElementsAre(Pointee(form)));
// Match against the second one.
- ASSERT_FALSE(ShouldPSLDomainMatchingApply(
- GetRegistryControlledDomain(GURL(form2.signon_realm))));
form_request.origin = form2.origin;
form_request.signon_realm = form2.signon_realm;
EXPECT_TRUE(db().GetLogins(form_request, &result));
@@ -1078,6 +1082,7 @@ TEST_F(LoginDatabaseTest, BlacklistedLogins) {
form.blacklisted_by_user = true;
form.scheme = PasswordForm::Scheme::kHtml;
form.date_synced = base::Time::Now();
+ form.date_last_used = base::Time::Now();
form.display_name = ASCIIToUTF16("Mr. Smith");
form.icon_url = GURL("https://accounts.google.com/Icon");
form.federation_origin =
@@ -1135,6 +1140,7 @@ TEST_F(LoginDatabaseTest, UpdateIncompleteCredentials) {
incomplete_form.username_value = ASCIIToUTF16("my_username");
incomplete_form.password_value = ASCIIToUTF16("my_password");
incomplete_form.preferred = true;
+ incomplete_form.date_last_used = base::Time::Now();
incomplete_form.blacklisted_by_user = false;
incomplete_form.scheme = PasswordForm::Scheme::kHtml;
EXPECT_EQ(AddChangeForForm(incomplete_form), db().AddLogin(incomplete_form));
@@ -1157,6 +1163,7 @@ TEST_F(LoginDatabaseTest, UpdateIncompleteCredentials) {
EXPECT_EQ(incomplete_form.username_value, result[0]->username_value);
EXPECT_EQ(incomplete_form.password_value, result[0]->password_value);
EXPECT_TRUE(result[0]->preferred);
+ EXPECT_EQ(incomplete_form.date_last_used, result[0]->date_last_used);
// We should return empty 'action', 'username_element', 'password_element'
// and 'submit_element' as we can't be sure if the credentials were entered
@@ -1200,6 +1207,7 @@ TEST_F(LoginDatabaseTest, UpdateOverlappingCredentials) {
incomplete_form.username_value = ASCIIToUTF16("my_username");
incomplete_form.password_value = ASCIIToUTF16("my_password");
incomplete_form.preferred = true;
+ incomplete_form.date_last_used = base::Time::Now();
incomplete_form.blacklisted_by_user = false;
incomplete_form.scheme = PasswordForm::Scheme::kHtml;
EXPECT_EQ(AddChangeForForm(incomplete_form), db().AddLogin(incomplete_form));
@@ -1285,6 +1293,7 @@ TEST_F(LoginDatabaseTest, UpdateLogin) {
form.preferred = true;
form.blacklisted_by_user = false;
form.scheme = PasswordForm::Scheme::kHtml;
+ form.date_last_used = base::Time::Now();
EXPECT_EQ(AddChangeForForm(form), db().AddLogin(form));
form.action = GURL("http://accounts.google.com/login");
@@ -1296,6 +1305,7 @@ TEST_F(LoginDatabaseTest, UpdateLogin) {
form.submit_element = ASCIIToUTF16("submit_element");
form.date_synced = base::Time::Now();
form.date_created = base::Time::Now() - base::TimeDelta::FromDays(1);
+ form.date_last_used = base::Time::Now() + base::TimeDelta::FromDays(1);
form.blacklisted_by_user = true;
form.scheme = PasswordForm::Scheme::kBasic;
form.type = PasswordForm::Type::kGenerated;
@@ -1786,7 +1796,7 @@ TEST_F(LoginDatabaseTest, EncryptionEnabled) {
GenerateExamplePasswordForm(&password_form);
base::FilePath file = temp_dir_.GetPath().AppendASCII("TestUnencryptedDB");
{
- LoginDatabase db(file);
+ LoginDatabase db(file, IsAccountStore(false));
ASSERT_TRUE(db.Init());
EXPECT_EQ(AddChangeForForm(password_form), db.AddLogin(password_form));
}
@@ -1807,7 +1817,7 @@ TEST_F(LoginDatabaseTest, EncryptionDisabled) {
GenerateExamplePasswordForm(&password_form);
base::FilePath file = temp_dir_.GetPath().AppendASCII("TestUnencryptedDB");
{
- LoginDatabase db(file);
+ LoginDatabase db(file, IsAccountStore(false));
db.disable_encryption();
ASSERT_TRUE(db.Init());
EXPECT_EQ(AddChangeForForm(password_form), db.AddLogin(password_form));
@@ -1830,7 +1840,7 @@ TEST_F(LoginDatabaseTest, HandleObfuscationMix) {
base::FilePath file = temp_dir_.GetPath().AppendASCII("TestUnencryptedDB");
{
- LoginDatabase db(file);
+ LoginDatabase db(file, IsAccountStore(false));
ASSERT_TRUE(db.Init());
// Add obfuscated (new) entries.
PasswordForm password_form;
@@ -1851,7 +1861,7 @@ TEST_F(LoginDatabaseTest, HandleObfuscationMix) {
std::vector<std::unique_ptr<autofill::PasswordForm>> forms;
{
- LoginDatabase db(file);
+ LoginDatabase db(file, IsAccountStore(false));
ASSERT_TRUE(db.Init());
ASSERT_TRUE(db.GetAutofillableLogins(&forms));
}
@@ -1889,10 +1899,49 @@ TEST(LoginDatabaseFailureTest, Init_NoCrashOnFailedRollback) {
// Now try to init the database with the file. The test succeeds if it does
// not crash.
- LoginDatabase db(database_path);
+ LoginDatabase db(database_path, IsAccountStore(false));
EXPECT_FALSE(db.Init());
}
+// If the database version is from the future, it shouldn't be downgraded.
+TEST(LoginDatabaseFutureLoginDatabase, ShouldNotDowngradeDatabaseVersion) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath database_path = temp_dir.GetPath().AppendASCII("test.db");
+
+ const int kDBFutureVersion = kCurrentVersionNumber + 1000;
+
+ {
+ // Open a database with the current version.
+ LoginDatabase db(database_path, IsAccountStore(false));
+ EXPECT_TRUE(db.Init());
+ }
+ {
+ // Overwrite the current version to be |kDBFutureVersion|
+ sql::Database connection;
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(connection.Open(database_path));
+ // Set the DB version to be coming from the future.
+ ASSERT_TRUE(meta_table.Init(&connection, kDBFutureVersion,
+ kCompatibleVersionNumber));
+ meta_table.SetVersionNumber(kDBFutureVersion);
+ }
+ {
+ // Open the database again.
+ LoginDatabase db(database_path, IsAccountStore(false));
+ EXPECT_TRUE(db.Init());
+ }
+ {
+ // The DB version should remain the same.
+ sql::Database connection;
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(connection.Open(database_path));
+ ASSERT_TRUE(meta_table.Init(&connection, kDBFutureVersion,
+ kCompatibleVersionNumber));
+ EXPECT_EQ(kDBFutureVersion, meta_table.GetVersionNumber());
+ }
+}
+
// Test the migration from GetParam() version to kCurrentVersionNumber.
class LoginDatabaseMigrationTest : public testing::TestWithParam<int> {
protected:
@@ -1934,7 +1983,7 @@ class LoginDatabaseMigrationTest : public testing::TestWithParam<int> {
private:
base::FilePath database_dump_location_;
base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
void LoginDatabaseMigrationTest::MigrationToVCurrent(
@@ -1964,7 +2013,7 @@ void LoginDatabaseMigrationTest::MigrationToVCurrent(
{
// Assert that the database was successfully opened and updated
// to current version.
- LoginDatabase db(database_path_);
+ LoginDatabase db(database_path_, IsAccountStore(false));
ASSERT_TRUE(db.Init());
// Check that the contents was preserved.
@@ -2061,7 +2110,7 @@ INSTANTIATE_TEST_SUITE_P(MigrationToVCurrent,
testing::Values(9));
INSTANTIATE_TEST_SUITE_P(MigrationToVCurrent,
LoginDatabaseMigrationTestBroken,
- testing::Range(1, 4));
+ testing::Values(1, 2, 3, 24));
class LoginDatabaseUndecryptableLoginsTest : public testing::Test {
protected:
@@ -2088,12 +2137,12 @@ class LoginDatabaseUndecryptableLoginsTest : public testing::Test {
return testing_local_state_;
}
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
private:
base::FilePath database_path_;
base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple testing_local_state_;
DISALLOW_COPY_AND_ASSIGN(LoginDatabaseUndecryptableLoginsTest);
@@ -2114,7 +2163,7 @@ PasswordForm LoginDatabaseUndecryptableLoginsTest::AddDummyLogin(
form.signon_realm = origin.GetOrigin().spec();
{
- LoginDatabase db(database_path());
+ LoginDatabase db(database_path(), IsAccountStore(false));
EXPECT_TRUE(db.Init());
EXPECT_EQ(db.AddLogin(form), AddChangeForForm(form));
}
@@ -2151,7 +2200,7 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, DeleteUndecryptableLoginsTest) {
auto form2 = AddDummyLogin("foo2", GURL("https://foo2.com/"), true);
auto form3 = AddDummyLogin("foo3", GURL("https://foo3.com/"), false);
- LoginDatabase db(database_path());
+ LoginDatabase db(database_path(), IsAccountStore(false));
base::HistogramTester histogram_tester;
ASSERT_TRUE(db.Init());
@@ -2204,7 +2253,7 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, PasswordRecoveryEnabledGetLogins) {
auto form2 = AddDummyLogin("foo2", GURL("https://foo2.com/"), true);
auto form3 = AddDummyLogin("foo3", GURL("https://foo3.com/"), false);
- LoginDatabase db(database_path());
+ LoginDatabase db(database_path(), IsAccountStore(false));
ASSERT_TRUE(db.Init());
testing_local_state().registry()->RegisterTimePref(prefs::kPasswordRecovery,
@@ -2237,7 +2286,7 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest,
AddDummyLogin("foo1", GURL("https://foo1.com/"), false);
AddDummyLogin("foo2", GURL("https://foo2.com/"), true);
- LoginDatabase db(database_path());
+ LoginDatabase db(database_path(), IsAccountStore(false));
ASSERT_TRUE(db.Init());
testing_local_state().registry()->RegisterTimePref(prefs::kPasswordRecovery,
@@ -2272,7 +2321,7 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest,
OSCryptMocker::SetBackendLocked(true);
- LoginDatabase db(database_path());
+ LoginDatabase db(database_path(), IsAccountStore(false));
ASSERT_TRUE(db.Init());
testing_local_state().registry()->RegisterTimePref(prefs::kPasswordRecovery,
@@ -2308,7 +2357,7 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, KeychainLockedTest) {
AddDummyLogin("foo2", GURL("https://foo2.com/"), true);
OSCryptMocker::SetBackendLocked(true);
- LoginDatabase db(database_path());
+ LoginDatabase db(database_path(), IsAccountStore(false));
base::HistogramTester histogram_tester;
ASSERT_TRUE(db.Init());
EXPECT_EQ(DatabaseCleanupResult::kEncryptionUnavailable,
@@ -2323,4 +2372,51 @@ TEST_F(LoginDatabaseUndecryptableLoginsTest, KeychainLockedTest) {
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+// Test retrieving password forms by supplied password.
+TEST_F(LoginDatabaseTest, GetLoginsByPassword) {
+ std::vector<std::unique_ptr<PasswordForm>> result;
+ PrimaryKeyToFormMap key_to_form_map;
+
+ const base::string16 duplicated_password =
+ base::ASCIIToUTF16("duplicated_password");
+
+ // Insert first logins.
+ PasswordForm form1;
+ GenerateExamplePasswordForm(&form1);
+ form1.password_value = duplicated_password;
+ PasswordStoreChangeList changes = db().AddLogin(form1);
+ ASSERT_EQ(AddChangeForForm(form1), changes);
+
+ // Check if there is exactly one form with this password.
+ std::vector<std::unique_ptr<PasswordForm>> forms;
+ EXPECT_TRUE(db().GetLoginsByPassword(duplicated_password, &forms));
+ EXPECT_THAT(forms, UnorderedElementsAre(Pointee(form1)));
+
+ // Insert another form with a different password for a different origin.
+ PasswordForm form2;
+ GenerateExamplePasswordForm(&form2);
+ form2.origin = GURL("https://myrandomsite.com/login.php");
+ form2.signon_realm = form2.origin.GetOrigin().spec();
+ form2.password_value = base::ASCIIToUTF16("my-unique-random-password");
+ changes = db().AddLogin(form2);
+ ASSERT_EQ(AddChangeForForm(form2), changes);
+
+ // Check if there is still exactly one form with the duplicated_password.
+ EXPECT_TRUE(db().GetLoginsByPassword(duplicated_password, &forms));
+ EXPECT_THAT(forms, UnorderedElementsAre(Pointee(form1)));
+
+ // Insert another form with the target password for a different origin.
+ PasswordForm form3;
+ GenerateExamplePasswordForm(&form3);
+ form3.origin = GURL("https://myrandomsite1.com/login.php");
+ form3.signon_realm = form3.origin.GetOrigin().spec();
+ form3.password_value = duplicated_password;
+ changes = db().AddLogin(form3);
+ ASSERT_EQ(AddChangeForForm(form3), changes);
+
+ // Check if there are exactly two forms with the duplicated_password.
+ EXPECT_TRUE(db().GetLoginsByPassword(duplicated_password, &forms));
+ EXPECT_THAT(forms, UnorderedElementsAre(Pointee(form1), Pointee(form3)));
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/mock_password_store.h b/chromium/components/password_manager/core/browser/mock_password_store.h
index e2c0921ca2c..e7d690cc915 100644
--- a/chromium/components/password_manager/core/browser/mock_password_store.h
+++ b/chromium/components/password_manager/core/browser/mock_password_store.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_PASSWORD_STORE_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_PASSWORD_STORE_H_
+#include <memory>
#include <string>
#include <vector>
@@ -22,6 +23,8 @@ class MockPasswordStore : public PasswordStore {
MOCK_METHOD1(RemoveLogin, void(const autofill::PasswordForm&));
MOCK_METHOD2(GetLogins,
void(const PasswordStore::FormDigest&, PasswordStoreConsumer*));
+ MOCK_METHOD2(GetLoginsByPassword,
+ void(const base::string16&, PasswordStoreConsumer*));
MOCK_METHOD1(AddLogin, void(const autofill::PasswordForm&));
MOCK_METHOD1(UpdateLogin, void(const autofill::PasswordForm&));
MOCK_METHOD2(UpdateLoginWithPrimaryKey,
@@ -54,6 +57,9 @@ class MockPasswordStore : public PasswordStore {
const PasswordStore::FormDigest& form) override {
return std::vector<std::unique_ptr<autofill::PasswordForm>>();
}
+ MOCK_METHOD1(FillMatchingLoginsByPassword,
+ std::vector<std::unique_ptr<autofill::PasswordForm>>(
+ const base::string16&));
MOCK_METHOD1(FillAutofillableLogins,
bool(std::vector<std::unique_ptr<autofill::PasswordForm>>*));
MOCK_METHOD1(FillBlacklistLogins,
@@ -75,7 +81,7 @@ class MockPasswordStore : public PasswordStore {
MOCK_METHOD3(SaveGaiaPasswordHash,
void(const std::string&,
const base::string16&,
- metrics_util::SyncPasswordHashChange));
+ metrics_util::GaiaPasswordHashChange));
MOCK_METHOD2(SaveEnterprisePasswordHash,
void(const std::string&, const base::string16&));
MOCK_METHOD1(ClearGaiaPasswordHash, void(const std::string&));
@@ -88,6 +94,8 @@ class MockPasswordStore : public PasswordStore {
MOCK_METHOD1(ReadAllLogins, FormRetrievalResult(PrimaryKeyToFormMap*));
MOCK_METHOD1(RemoveLoginByPrimaryKeySync, PasswordStoreChangeList(int));
MOCK_METHOD0(GetMetadataStore, PasswordStoreSync::MetadataStore*());
+ MOCK_CONST_METHOD0(IsAccountStore, bool());
+ MOCK_METHOD0(DeleteAndRecreateDatabaseFile, bool());
PasswordStoreSync* GetSyncInterface() { return this; }
diff --git a/chromium/components/password_manager/core/browser/new_password_form_manager.cc b/chromium/components/password_manager/core/browser/new_password_form_manager.cc
deleted file mode 100644
index 644c3d58c04..00000000000
--- a/chromium/components/password_manager/core/browser/new_password_form_manager.cc
+++ /dev/null
@@ -1,1167 +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 "components/password_manager/core/browser/new_password_form_manager.h"
-
-#include <algorithm>
-#include <memory>
-#include <set>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "base/stl_util.h"
-#include "build/build_config.h"
-#include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/browser/validation.h"
-#include "components/autofill/core/common/password_form_generation_data.h"
-#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
-#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
-#include "components/password_manager/core/browser/form_fetcher_impl.h"
-#include "components/password_manager/core/browser/form_saver.h"
-#include "components/password_manager/core/browser/password_form_filling.h"
-#include "components/password_manager/core/browser/password_generation_state.h"
-#include "components/password_manager/core/browser/password_manager_client.h"
-#include "components/password_manager/core/browser/password_manager_driver.h"
-#include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/statistics_table.h"
-
-using autofill::FormData;
-using autofill::FormFieldData;
-using autofill::FormSignature;
-using autofill::FormStructure;
-using autofill::PasswordForm;
-using autofill::ValueElementPair;
-using base::TimeDelta;
-using base::TimeTicks;
-
-using Logger = autofill::SavePasswordProgressLogger;
-
-namespace password_manager {
-
-bool NewPasswordFormManager::wait_for_server_predictions_for_filling_ = true;
-
-namespace {
-
-constexpr TimeDelta kMaxFillingDelayForServerPredictions =
- TimeDelta::FromMilliseconds(500);
-
-// Helper to get the platform specific identifier by which autofill and password
-// manager refer to a field. See http://crbug.com/896594
-base::string16 GetPlatformSpecificIdentifier(const FormFieldData& field) {
-#if defined(OS_IOS)
- return field.unique_id;
-#else
- return field.name;
-#endif
-}
-
-ValueElementPair PasswordToSave(const PasswordForm& form) {
- if (form.new_password_value.empty()) {
- DCHECK(!form.password_value.empty() || form.IsFederatedCredential());
- return {form.password_value, form.password_element};
- }
- return {form.new_password_value, form.new_password_element};
-}
-
-// Copies field properties masks from the form |from| to the form |to|.
-void CopyFieldPropertiesMasks(const FormData& from, FormData* to) {
- // Skip copying if the number of fields is different.
- if (from.fields.size() != to->fields.size())
- return;
-
- for (size_t i = 0; i < from.fields.size(); ++i) {
- to->fields[i].properties_mask =
- GetPlatformSpecificIdentifier(to->fields[i]) ==
- GetPlatformSpecificIdentifier(from.fields[i])
- ? from.fields[i].properties_mask
- : autofill::FieldPropertiesFlags::ERROR_OCCURRED;
- }
-}
-
-// Filter sensitive information, duplicates and |username_value| out from
-// |form->all_possible_usernames|.
-void SanitizePossibleUsernames(PasswordForm* form) {
- auto& usernames = form->all_possible_usernames;
-
- // Deduplicate.
- std::sort(usernames.begin(), usernames.end());
- usernames.erase(std::unique(usernames.begin(), usernames.end()),
- usernames.end());
-
- // Filter out |form->username_value| and sensitive information.
- const base::string16& username_value = form->username_value;
- base::EraseIf(usernames, [&username_value](const ValueElementPair& pair) {
- return pair.first == username_value ||
- autofill::IsValidCreditCardNumber(pair.first) ||
- autofill::IsSSN(pair.first);
- });
-}
-
-// Returns bit masks with differences in forms attributes which are important
-// for parsing. Bits are set according to enum FormDataDifferences.
-uint32_t FindFormsDifferences(const FormData& lhs, const FormData& rhs) {
- if (lhs.fields.size() != rhs.fields.size())
- return PasswordFormMetricsRecorder::kFieldsNumber;
- size_t differences_bitmask = 0;
- for (size_t i = 0; i < lhs.fields.size(); ++i) {
- const FormFieldData& lhs_field = lhs.fields[i];
- const FormFieldData& rhs_field = rhs.fields[i];
-
- if (lhs_field.unique_renderer_id != rhs_field.unique_renderer_id)
- differences_bitmask |= PasswordFormMetricsRecorder::kRendererFieldIDs;
-
- if (lhs_field.form_control_type != rhs_field.form_control_type)
- differences_bitmask |= PasswordFormMetricsRecorder::kFormControlTypes;
-
- if (lhs_field.autocomplete_attribute != rhs_field.autocomplete_attribute)
- differences_bitmask |=
- PasswordFormMetricsRecorder::kAutocompleteAttributes;
- }
- return differences_bitmask;
-}
-
-} // namespace
-
-NewPasswordFormManager::NewPasswordFormManager(
- PasswordManagerClient* client,
- const base::WeakPtr<PasswordManagerDriver>& driver,
- const FormData& observed_form,
- FormFetcher* form_fetcher,
- std::unique_ptr<FormSaver> form_saver,
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder)
- : NewPasswordFormManager(client,
- form_fetcher,
- std::move(form_saver),
- metrics_recorder,
- PasswordStore::FormDigest(observed_form)) {
- driver_ = driver;
- observed_form_ = observed_form;
- metrics_recorder_->RecordFormSignature(CalculateFormSignature(observed_form));
- form_fetcher_->AddConsumer(this);
- votes_uploader_.StoreInitialFieldValues(observed_form);
-}
-
-NewPasswordFormManager::NewPasswordFormManager(
- PasswordManagerClient* client,
- PasswordStore::FormDigest observed_http_auth_digest,
- FormFetcher* form_fetcher,
- std::unique_ptr<FormSaver> form_saver)
- : NewPasswordFormManager(client,
- form_fetcher,
- std::move(form_saver),
- nullptr /* metrics_recorder */,
- observed_http_auth_digest) {
- observed_not_web_form_digest_ = std::move(observed_http_auth_digest);
- form_fetcher_->AddConsumer(this);
-}
-
-NewPasswordFormManager::~NewPasswordFormManager() = default;
-
-bool NewPasswordFormManager::DoesManage(
- const FormData& form,
- const PasswordManagerDriver* driver) const {
- if (driver != driver_.get())
- return false;
-
- if (observed_form_.is_form_tag != form.is_form_tag)
- return false;
- // All unowned input elements are considered as one synthetic form.
- if (!observed_form_.is_form_tag && !form.is_form_tag)
- return true;
-#if defined(OS_IOS)
- // On iOS form name is used as the form identifier.
- return observed_form_.name == form.name;
-#else
- return observed_form_.unique_renderer_id == form.unique_renderer_id;
-#endif
-}
-
-bool NewPasswordFormManager::DoesManageAccordingToRendererId(
- uint32_t form_renderer_id,
- const PasswordManagerDriver* driver) const {
- if (driver != driver_.get())
- return false;
-#if defined(OS_IOS)
- NOTREACHED();
- // On iOS form name is used as the form identifier.
- return false;
-#else
- return observed_form_.unique_renderer_id == form_renderer_id;
-#endif
-}
-
-bool NewPasswordFormManager::IsEqualToSubmittedForm(
- const autofill::FormData& form) const {
- if (!is_submitted_)
- return false;
- if (IsHttpAuth())
- return false;
- if (form.action == submitted_form_.action)
- return true;
- // TODO(https://crbug.com/831123): Implement other checks from a function
- // IsPasswordFormReappeared from password_manager.cc.
- return false;
-}
-
-const GURL& NewPasswordFormManager::GetOrigin() const {
- return observed_not_web_form_digest_ ? observed_not_web_form_digest_->origin
- : observed_form_.url;
-}
-
-const std::map<base::string16, const PasswordForm*>&
-NewPasswordFormManager::GetBestMatches() const {
- return best_matches_;
-}
-
-std::vector<const autofill::PasswordForm*>
-NewPasswordFormManager::GetFederatedMatches() const {
- return form_fetcher_->GetFederatedMatches();
-}
-
-const PasswordForm& NewPasswordFormManager::GetPendingCredentials() const {
- return pending_credentials_;
-}
-
-metrics_util::CredentialSourceType
-NewPasswordFormManager::GetCredentialSource() {
- return metrics_util::CredentialSourceType::kPasswordManager;
-}
-
-PasswordFormMetricsRecorder* NewPasswordFormManager::GetMetricsRecorder() {
- return metrics_recorder_.get();
-}
-
-base::span<const autofill::PasswordForm* const>
-NewPasswordFormManager::GetBlacklistedMatches() const {
- return base::make_span(blacklisted_matches_);
-}
-
-base::span<const InteractionsStats>
-NewPasswordFormManager::GetInteractionsStats() const {
- return base::make_span(form_fetcher_->GetInteractionsStats());
-}
-
-bool NewPasswordFormManager::IsBlacklisted() const {
- return !blacklisted_matches_.empty();
-}
-
-void NewPasswordFormManager::Save() {
- DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
- DCHECK(!client_->IsIncognito());
-
- for (auto blacklisted_iterator = blacklisted_matches_.begin();
- blacklisted_iterator != blacklisted_matches_.end();) {
- form_saver_->Remove(**blacklisted_iterator);
- blacklisted_iterator = blacklisted_matches_.erase(blacklisted_iterator);
- }
-
- // TODO(https://crbug.com/831123): Implement indicator event metrics.
- if (password_overridden_ &&
- pending_credentials_.type == PasswordForm::Type::kGenerated &&
- !HasGeneratedPassword()) {
- metrics_util::LogPasswordGenerationSubmissionEvent(
- metrics_util::PASSWORD_OVERRIDDEN);
- pending_credentials_.type = PasswordForm::Type::kManual;
- }
-
- if (is_new_login_) {
- metrics_util::LogNewlySavedPasswordIsGenerated(
- pending_credentials_.type == PasswordForm::Type::kGenerated);
- SanitizePossibleUsernames(&pending_credentials_);
- pending_credentials_.date_created = base::Time::Now();
- votes_uploader_.SendVotesOnSave(observed_form_, *parsed_submitted_form_,
- best_matches_, &pending_credentials_);
- SavePendingToStore(false /*update*/);
- } else {
- ProcessUpdate();
- SavePendingToStore(true /*update*/);
- }
-
- if (pending_credentials_.times_used == 1 &&
- pending_credentials_.type == PasswordForm::Type::kGenerated) {
- // This also includes PSL matched credentials.
- metrics_util::LogPasswordGenerationSubmissionEvent(
- metrics_util::PASSWORD_USED);
- }
-
- client_->UpdateFormManagers();
-}
-
-void NewPasswordFormManager::Update(const PasswordForm& credentials_to_update) {
- metrics_util::LogPasswordAcceptedSaveUpdateSubmissionIndicatorEvent(
- parsed_submitted_form_->submission_event);
- metrics_recorder_->SetSubmissionIndicatorEvent(
- parsed_submitted_form_->submission_event);
-
- std::unique_ptr<PasswordForm> parsed_observed_form =
- parser_.Parse(observed_form_, FormDataParser::Mode::kFilling);
-
- base::string16 password_to_save = pending_credentials_.password_value;
- bool skip_zero_click = pending_credentials_.skip_zero_click;
- pending_credentials_ = credentials_to_update;
- pending_credentials_.password_value = password_to_save;
- pending_credentials_.skip_zero_click = skip_zero_click;
- pending_credentials_.preferred = true;
- is_new_login_ = false;
- ProcessUpdate();
- SavePendingToStore(true /*update*/);
-
- client_->UpdateFormManagers();
-}
-
-void NewPasswordFormManager::UpdateUsername(
- const base::string16& new_username) {
- DCHECK(parsed_submitted_form_);
- parsed_submitted_form_->username_value = new_username;
- parsed_submitted_form_->username_element.clear();
-
- // |has_username_edited_vote_| is true iff |new_username| was typed in another
- // field. Otherwise, |has_username_edited_vote_| is false and no vote will be
- // uploaded.
- votes_uploader_.set_has_username_edited_vote(false);
- if (!new_username.empty()) {
- // |all_possible_usernames| has all possible usernames.
- // TODO(crbug.com/831123): rename to |all_possible_usernames| when the old
- // parser is gone.
- for (const auto& possible_username :
- parsed_submitted_form_->all_possible_usernames) {
- if (possible_username.first == new_username) {
- parsed_submitted_form_->username_element = possible_username.second;
- votes_uploader_.set_has_username_edited_vote(true);
- break;
- }
- }
- }
-
- CreatePendingCredentials();
-}
-
-void NewPasswordFormManager::UpdatePasswordValue(
- const base::string16& new_password) {
- DCHECK(parsed_submitted_form_);
- parsed_submitted_form_->password_value = new_password;
- parsed_submitted_form_->password_element.clear();
-
- // The user updated a password from the prompt. It means that heuristics were
- // wrong. So clear new password, since it is likely wrong.
- parsed_submitted_form_->new_password_value.clear();
- parsed_submitted_form_->new_password_element.clear();
-
- for (const ValueElementPair& pair :
- parsed_submitted_form_->all_possible_passwords) {
- if (pair.first == new_password) {
- parsed_submitted_form_->password_element = pair.second;
- break;
- }
- }
-
- CreatePendingCredentials();
-}
-
-void NewPasswordFormManager::OnNopeUpdateClicked() {
- votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
- *parsed_submitted_form_,
- autofill::NOT_NEW_PASSWORD, std::string());
-}
-
-void NewPasswordFormManager::OnNeverClicked() {
- // |UNKNOWN_TYPE| is sent in order to record that a generation popup was
- // shown and ignored.
- votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
- *parsed_submitted_form_,
- autofill::UNKNOWN_TYPE, std::string());
- PermanentlyBlacklist();
-}
-
-void NewPasswordFormManager::OnNoInteraction(bool is_update) {
- // |UNKNOWN_TYPE| is sent in order to record that a generation popup was
- // shown and ignored.
- votes_uploader_.UploadPasswordVote(
- *parsed_submitted_form_, *parsed_submitted_form_,
- is_update ? autofill::PROBABLY_NEW_PASSWORD : autofill::UNKNOWN_TYPE,
- std::string());
-}
-
-void NewPasswordFormManager::PermanentlyBlacklist() {
- DCHECK(!client_->IsIncognito());
-
- if (!new_blacklisted_) {
- new_blacklisted_ = std::make_unique<PasswordForm>();
- if (observed_not_web_form_digest_) {
- new_blacklisted_->origin = observed_not_web_form_digest_->origin;
- // GetSignonRealm is not suitable for http auth credentials.
- new_blacklisted_->signon_realm =
- IsHttpAuth() ? observed_not_web_form_digest_->signon_realm
- : GetSignonRealm(observed_not_web_form_digest_->origin);
- } else {
- new_blacklisted_->origin = observed_form_.url;
- new_blacklisted_->signon_realm = GetSignonRealm(observed_form_.url);
- }
- new_blacklisted_->scheme = GetScheme();
- blacklisted_matches_.push_back(new_blacklisted_.get());
- }
- *new_blacklisted_ = form_saver_->PermanentlyBlacklist(
- PasswordStore::FormDigest(*new_blacklisted_));
-}
-
-void NewPasswordFormManager::OnPasswordsRevealed() {
- votes_uploader_.set_has_passwords_revealed_vote(true);
-}
-
-bool NewPasswordFormManager::IsNewLogin() const {
- return is_new_login_;
-}
-
-FormFetcher* NewPasswordFormManager::GetFormFetcher() {
- return form_fetcher_;
-}
-
-bool NewPasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const {
- return pending_credentials_.is_public_suffix_match;
-}
-
-void NewPasswordFormManager::PresaveGeneratedPassword(
- const PasswordForm& form) {
- // TODO(https://crbug.com/831123): Propagate generated password independently
- // of PasswordForm when PasswordForm goes away from the renderer process.
- PresaveGeneratedPasswordInternal(form.form_data,
- form.password_value /*generated_password*/);
-}
-
-void NewPasswordFormManager::PasswordNoLongerGenerated() {
- if (!HasGeneratedPassword())
- return;
-
- generation_state_->PasswordNoLongerGenerated();
- generation_state_.reset();
- votes_uploader_.set_has_generated_password(false);
- votes_uploader_.set_generated_password_changed(false);
- metrics_recorder_->SetGeneratedPasswordStatus(
- PasswordFormMetricsRecorder::GeneratedPasswordStatus::kPasswordDeleted);
-}
-
-bool NewPasswordFormManager::HasGeneratedPassword() const {
- return generation_state_ && generation_state_->HasGeneratedPassword();
-}
-
-void NewPasswordFormManager::SetGenerationPopupWasShown(
- bool generation_popup_was_shown,
- bool is_manual_generation) {
- votes_uploader_.set_generation_popup_was_shown(generation_popup_was_shown);
- votes_uploader_.set_is_manual_generation(is_manual_generation);
- metrics_recorder_->SetPasswordGenerationPopupShown(generation_popup_was_shown,
- is_manual_generation);
-}
-
-void NewPasswordFormManager::SetGenerationElement(
- const base::string16& generation_element) {
- votes_uploader_.set_generation_element(generation_element);
-}
-
-bool NewPasswordFormManager::IsPossibleChangePasswordFormWithoutUsername()
- const {
- return parsed_submitted_form_ &&
- parsed_submitted_form_->IsPossibleChangePasswordFormWithoutUsername();
-}
-
-bool NewPasswordFormManager::IsPasswordUpdate() const {
- return password_overridden_;
-}
-
-std::vector<base::WeakPtr<PasswordManagerDriver>>
-NewPasswordFormManager::GetDrivers() const {
- return {driver_};
-}
-
-const PasswordForm* NewPasswordFormManager::GetSubmittedForm() const {
- return parsed_submitted_form_.get();
-}
-
-#if defined(OS_IOS)
-void NewPasswordFormManager::PresaveGeneratedPassword(
- PasswordManagerDriver* driver,
- const FormData& form,
- const base::string16& generated_password,
- const base::string16& generation_element) {
- observed_form_ = form;
- PresaveGeneratedPasswordInternal(form, generated_password);
- votes_uploader_.set_generation_element(generation_element);
-}
-
-bool NewPasswordFormManager::UpdateGeneratedPasswordOnUserInput(
- const base::string16& form_identifier,
- const base::string16& field_identifier,
- const base::string16& field_value) {
- if (observed_form_.name != form_identifier || !HasGeneratedPassword()) {
- // *this might not have generated password, because
- // 1.This function is called before PresaveGeneratedPassword, or
- // 2.There are multiple forms with the same |form_identifier|
- return false;
- }
- bool form_data_changed = false;
- for (FormFieldData& field : observed_form_.fields) {
- if (field.unique_id == field_identifier) {
- field.value = field_value;
- form_data_changed = true;
- break;
- }
- }
- base::string16 generated_password = generation_state_->generated_password();
- if (votes_uploader_.get_generation_element() == field_identifier) {
- generated_password = field_value;
- form_data_changed = true;
- }
- if (form_data_changed)
- PresaveGeneratedPasswordInternal(observed_form_, generated_password);
- return true;
-}
-#endif // defined(OS_IOS)
-
-std::unique_ptr<NewPasswordFormManager> NewPasswordFormManager::Clone() {
- // Fetcher is cloned to avoid re-fetching data from PasswordStore.
- std::unique_ptr<FormFetcher> fetcher = form_fetcher_->Clone();
-
- // Some data is filled through the constructor. No PasswordManagerDriver is
- // needed, because the UI does not need any functionality related to the
- // renderer process, to which the driver serves as an interface. The full
- // |observed_form_| needs to be copied, because it is used to create the
- // blacklisting entry if needed.
- auto result = std::make_unique<NewPasswordFormManager>(
- client_, base::WeakPtr<PasswordManagerDriver>(), observed_form_,
- fetcher.get(), form_saver_->Clone(), metrics_recorder_);
-
- // The constructor only can take a weak pointer to the fetcher, so moving the
- // owning one needs to happen explicitly.
- result->owned_form_fetcher_ = std::move(fetcher);
-
- if (generation_state_) {
- result->generation_state_ =
- generation_state_->Clone(result->form_saver_.get());
- }
-
- // These data members all satisfy:
- // (1) They could have been changed by |*this| between its construction and
- // calling Clone().
- // (2) They are potentially used in the clone as the clone is used in the UI
- // code.
- // (3) They are not changed during OnFetchCompleted, triggered at some point
- // by the
- // cloned FormFetcher.
- result->votes_uploader_ = votes_uploader_;
- if (parser_.predictions())
- result->parser_.set_predictions(*parser_.predictions());
-
- result->pending_credentials_ = pending_credentials_;
- if (parsed_submitted_form_) {
- result->parsed_submitted_form_.reset(
- new PasswordForm(*parsed_submitted_form_));
- }
- result->is_new_login_ = is_new_login_;
- result->password_overridden_ = password_overridden_;
- result->is_submitted_ = is_submitted_;
-
- return result;
-}
-
-NewPasswordFormManager::NewPasswordFormManager(
- PasswordManagerClient* client,
- std::unique_ptr<PasswordForm> saved_form,
- std::unique_ptr<FormFetcher> form_fetcher,
- std::unique_ptr<FormSaver> form_saver)
- : NewPasswordFormManager(client,
- form_fetcher.get(),
- std::move(form_saver),
- nullptr /* metrics_recorder */,
- PasswordStore::FormDigest(*saved_form)) {
- observed_not_web_form_digest_ = PasswordStore::FormDigest(*saved_form);
- parsed_submitted_form_ = std::move(saved_form);
- is_submitted_ = true;
- owned_form_fetcher_ = std::move(form_fetcher),
- form_fetcher_->AddConsumer(this);
- if (form_fetcher_)
- form_fetcher_->Fetch();
-}
-
-void NewPasswordFormManager::OnFetchCompleted() {
- received_stored_credentials_time_ = TimeTicks::Now();
- std::vector<const PasswordForm*> matches;
- PasswordForm::Scheme observed_form_scheme = GetScheme();
- for (const auto* match : form_fetcher_->GetNonFederatedMatches()) {
- if (match->scheme == observed_form_scheme)
- matches.push_back(match);
- }
-
- password_manager_util::FindBestMatches(matches, &best_matches_,
- &not_best_matches_, &preferred_match_);
-
- // Copy out blacklisted matches.
- new_blacklisted_.reset();
- blacklisted_matches_ = form_fetcher_->GetBlacklistedMatches();
-
- autofills_left_ = kMaxTimesAutofill;
-
- if (IsCredentialAPISave()) {
- // This is saving with credential API, there is no form to fill, so no
- // filling required.
- return;
- }
-
- if (IsHttpAuth()) {
- // No server prediction for http auth, so no need to wait.
- FillHttpAuth();
- } else if (parser_.predictions() ||
- !wait_for_server_predictions_for_filling_) {
- ReportTimeBetweenStoreAndServerUMA();
- Fill();
- } else if (!waiting_for_server_predictions_) {
- waiting_for_server_predictions_ = true;
- base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&NewPasswordFormManager::Fill,
- weak_ptr_factory_.GetWeakPtr()),
- kMaxFillingDelayForServerPredictions);
- }
-}
-
-bool NewPasswordFormManager::ProvisionallySave(
- const FormData& submitted_form,
- const PasswordManagerDriver* driver,
- bool is_gaia_with_skip_save_password_form) {
- DCHECK(DoesManage(submitted_form, driver));
-
- std::unique_ptr<PasswordForm> parsed_submitted_form =
- ParseFormAndMakeLogging(submitted_form, FormDataParser::Mode::kSaving);
-
- RecordMetricOnReadonly(parser_.readonly_status(), !!parsed_submitted_form,
- FormDataParser::Mode::kSaving);
-
- // This function might be called multiple times. Consider as success if the
- // submitted form was successfully parsed on a previous call.
- if (!parsed_submitted_form)
- return is_submitted_;
-
- parsed_submitted_form_ = std::move(parsed_submitted_form);
- parsed_submitted_form_->form_data.is_gaia_with_skip_save_password_form =
- is_gaia_with_skip_save_password_form;
- submitted_form_ = submitted_form;
- is_submitted_ = true;
- CalculateFillingAssistanceMetric(submitted_form);
-
- CreatePendingCredentials();
- return true;
-}
-
-bool NewPasswordFormManager::ProvisionallySaveHttpAuthForm(
- const PasswordForm& submitted_form) {
- if (!IsHttpAuth())
- return false;
- if (!(*observed_not_web_form_digest_ ==
- PasswordStore::FormDigest(submitted_form)))
- return false;
-
- parsed_submitted_form_.reset(new PasswordForm(submitted_form));
- is_submitted_ = true;
- CreatePendingCredentials();
- return true;
-}
-
-bool NewPasswordFormManager::IsHttpAuth() const {
- return GetScheme() != PasswordForm::Scheme::kHtml;
-}
-
-bool NewPasswordFormManager::IsCredentialAPISave() const {
- return observed_not_web_form_digest_ && !IsHttpAuth();
-}
-
-PasswordForm::Scheme NewPasswordFormManager::GetScheme() const {
- return observed_not_web_form_digest_ ? observed_not_web_form_digest_->scheme
- : PasswordForm::Scheme::kHtml;
-}
-
-void NewPasswordFormManager::ProcessServerPredictions(
- const std::map<FormSignature, FormPredictions>& predictions) {
- if (parser_.predictions()) {
- // This method might be called multiple times. No need to process
- // predictions again.
- return;
- }
- FormSignature observed_form_signature =
- CalculateFormSignature(observed_form_);
- auto it = predictions.find(observed_form_signature);
- if (it == predictions.end())
- return;
-
- ReportTimeBetweenStoreAndServerUMA();
- parser_.set_predictions(it->second);
- Fill();
-}
-
-void NewPasswordFormManager::Fill() {
- if (!driver_)
- return;
-
- waiting_for_server_predictions_ = false;
-
- if (form_fetcher_->GetState() == FormFetcher::State::WAITING)
- return;
-
- if (autofills_left_ <= 0)
- return;
- autofills_left_--;
-
- // There are additional signals (server-side data) and parse results in
- // filling and saving mode might be different so it is better not to cache
- // parse result, but to parse each time again.
- std::unique_ptr<PasswordForm> observed_password_form =
- ParseFormAndMakeLogging(observed_form_, FormDataParser::Mode::kFilling);
- RecordMetricOnReadonly(parser_.readonly_status(), !!observed_password_form,
- FormDataParser::Mode::kFilling);
- if (!observed_password_form)
- return;
-
- RecordMetricOnCompareParsingResult(*observed_password_form);
-
- if (observed_password_form->is_new_password_reliable && !IsBlacklisted()) {
-#if defined(OS_IOS)
- driver_->FormEligibleForGenerationFound(
- {/*form_name*/ observed_password_form->form_data.name,
- /*new_password_element*/ observed_password_form->new_password_element,
- /*confirmation_password_element*/
- observed_password_form->confirmation_password_element});
-#else
- driver_->FormEligibleForGenerationFound(
- {/*new_password_renderer_id*/
- observed_password_form->new_password_element_renderer_id,
- /*confirmation_password_renderer_id*/
- observed_password_form->confirmation_password_element_renderer_id});
-#endif
- }
-
- // TODO(https://crbug.com/831123): Implement correct treating of federated
- // matches.
- std::vector<const PasswordForm*> federated_matches;
- SendFillInformationToRenderer(client_, driver_.get(), IsBlacklisted(),
- *observed_password_form.get(), best_matches_,
- federated_matches, preferred_match_,
- metrics_recorder_.get());
-}
-
-void NewPasswordFormManager::FillForm(const FormData& observed_form) {
- uint32_t differences_bitmask =
- FindFormsDifferences(observed_form_, observed_form);
- metrics_recorder_->RecordFormChangeBitmask(differences_bitmask);
-
- if (differences_bitmask)
- observed_form_ = observed_form;
-
- if (!waiting_for_server_predictions_)
- Fill();
-}
-
-void NewPasswordFormManager::OnGeneratedPasswordAccepted(
- FormData form_data,
- uint32_t generation_element_id,
- const base::string16& password) {
- // Find the generating element to update its value. The parser needs a non
- // empty value.
- auto it = std::find_if(form_data.fields.begin(), form_data.fields.end(),
- [generation_element_id](const auto& field_data) {
- return generation_element_id ==
- field_data.unique_renderer_id;
- });
- DCHECK(it != form_data.fields.end());
- it->value = password;
- std::unique_ptr<PasswordForm> parsed_form =
- ParseFormAndMakeLogging(form_data, FormDataParser::Mode::kSaving);
- if (!parsed_form) {
- // Create a password form with a minimum data.
- parsed_form.reset(new PasswordForm);
- parsed_form->origin = form_data.url;
- parsed_form->signon_realm = GetSignonRealm(form_data.url);
- }
- parsed_form->password_value = password;
- generation_state_ =
- std::make_unique<PasswordGenerationState>(form_saver_.get(), client_);
- generation_state_->GeneratedPasswordAccepted(*parsed_form, *form_fetcher_,
- driver_);
-}
-
-NewPasswordFormManager::NewPasswordFormManager(
- PasswordManagerClient* client,
- FormFetcher* form_fetcher,
- std::unique_ptr<FormSaver> form_saver,
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder,
- PasswordStore::FormDigest form_digest)
- : client_(client),
- metrics_recorder_(metrics_recorder),
- owned_form_fetcher_(form_fetcher
- ? nullptr
- : std::make_unique<FormFetcherImpl>(
- std::move(form_digest),
- client_,
- true /* should_migrate_http_passwords */)),
- form_fetcher_(form_fetcher ? form_fetcher : owned_form_fetcher_.get()),
- form_saver_(std::move(form_saver)),
- // TODO(https://crbug.com/831123): set correctly
- // |is_possible_change_password_form| in |votes_uploader_| constructor
- votes_uploader_(client, false /* is_possible_change_password_form */) {
- if (!metrics_recorder_) {
- metrics_recorder_ = base::MakeRefCounted<PasswordFormMetricsRecorder>(
- client_->IsMainFrameSecure(), client_->GetUkmSourceId());
- }
-
- if (owned_form_fetcher_)
- owned_form_fetcher_->Fetch();
-}
-
-void NewPasswordFormManager::RecordMetricOnCompareParsingResult(
- const PasswordForm& parsed_form) {
- bool same =
- parsed_form.username_element == old_parsing_result_.username_element &&
- parsed_form.password_element == old_parsing_result_.password_element &&
- parsed_form.new_password_element ==
- old_parsing_result_.new_password_element &&
- parsed_form.confirmation_password_element ==
- old_parsing_result_.confirmation_password_element;
- if (same) {
- metrics_recorder_->RecordParsingsComparisonResult(
- PasswordFormMetricsRecorder::ParsingComparisonResult::kSame);
- return;
- }
-
- // In the old parsing for fields with empty name, placeholders are used. The
- // reason for this is that an empty "..._element" attribute in a PasswordForm
- // means that no corresponding input element exists. The new form parsing sets
- // empty string in that case because renderer ids are used instead of element
- // names for fields identification. Hence in case of anonymous fields, the
- // results will be different for sure. Compare to placeholders and record this
- // case.
- if (old_parsing_result_.username_element ==
- base::ASCIIToUTF16("anonymous_username") ||
- old_parsing_result_.password_element ==
- base::ASCIIToUTF16("anonymous_password") ||
- old_parsing_result_.new_password_element ==
- base::ASCIIToUTF16("anonymous_new_password") ||
- old_parsing_result_.confirmation_password_element ==
- base::ASCIIToUTF16("anonymous_confirmation_password")) {
- metrics_recorder_->RecordParsingsComparisonResult(
- PasswordFormMetricsRecorder::ParsingComparisonResult::kAnonymousFields);
- } else {
- metrics_recorder_->RecordParsingsComparisonResult(
- PasswordFormMetricsRecorder::ParsingComparisonResult::kDifferent);
- }
-}
-
-void NewPasswordFormManager::RecordMetricOnReadonly(
- FormDataParser::ReadonlyPasswordFields readonly_status,
- bool parsing_successful,
- FormDataParser::Mode mode) {
- // The reported value is combined of the |readonly_status| shifted by one bit
- // to the left, and the success bit put in the least significant bit. Note:
- // C++ guarantees that bool->int conversions map false to 0 and true to 1.
- uint64_t value = static_cast<uint64_t>(parsing_successful) +
- (static_cast<uint64_t>(readonly_status) << 1);
- switch (mode) {
- case FormDataParser::Mode::kSaving:
- metrics_recorder_->RecordReadonlyWhenSaving(value);
- break;
- case FormDataParser::Mode::kFilling:
- metrics_recorder_->RecordReadonlyWhenFilling(value);
- break;
- }
-}
-
-void NewPasswordFormManager::ReportTimeBetweenStoreAndServerUMA() {
- if (!received_stored_credentials_time_.is_null()) {
- UMA_HISTOGRAM_TIMES("PasswordManager.TimeBetweenStoreAndServer",
- TimeTicks::Now() - received_stored_credentials_time_);
- }
-}
-
-// TODO(https://crbug.com/831123): move this function to the proper place
-// corresponding to its place in the header.
-void NewPasswordFormManager::CreatePendingCredentials() {
- DCHECK(is_submitted_);
- // TODO(https://crbug.com/831123): Process correctly the case when saved
- // credentials are not received from the store yet.
- if (!parsed_submitted_form_)
- return;
-
- // Calculate the user's action based on existing matches and the submitted
- // form.
- metrics_recorder_->CalculateUserAction(best_matches_,
- *parsed_submitted_form_);
-
- // This function might be called multiple times so set variables that are
- // changed in this function to initial states.
- is_new_login_ = true;
- SetPasswordOverridden(false);
-
- ValueElementPair password_to_save(PasswordToSave(*parsed_submitted_form_));
- // Look for the actually submitted credentials in the list of previously saved
- // credentials that were available to autofilling.
- const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating(
- *parsed_submitted_form_, best_matches_);
- if (saved_form) {
- // A similar credential exists in the store already.
- pending_credentials_ = *saved_form;
- SetPasswordOverridden(pending_credentials_.password_value !=
- password_to_save.first);
- // If the autofilled credentials were a PSL match, store a copy with the
- // current origin and signon realm. This ensures that on the next visit, a
- // precise match is found.
- is_new_login_ = pending_credentials_.is_public_suffix_match;
-
- if (is_new_login_) {
- // Update credential to reflect that it has been used for submission.
- // If this isn't updated, then password generation uploads are off for
- // sites where PSL matching is required to fill the login form, as two
- // PASSWORD votes are uploaded per saved password instead of one.
- password_manager_util::UpdateMetadataForUsage(&pending_credentials_);
-
- // Update |pending_credentials_| in order to be able correctly save it.
- pending_credentials_.origin = parsed_submitted_form_->origin;
- pending_credentials_.signon_realm = parsed_submitted_form_->signon_realm;
- pending_credentials_.action = parsed_submitted_form_->action;
- }
- } else {
- is_new_login_ = true;
- // No stored credentials can be matched to the submitted form. Offer to
- // save new credentials.
- CreatePendingCredentialsForNewCredentials(*parsed_submitted_form_,
- password_to_save.second);
- // Generate username correction votes.
- bool username_correction_found =
- votes_uploader_.FindCorrectedUsernameElement(
- best_matches_, not_best_matches_,
- parsed_submitted_form_->username_value,
- parsed_submitted_form_->password_value);
- UMA_HISTOGRAM_BOOLEAN("PasswordManager.UsernameCorrectionFound",
- username_correction_found);
- if (username_correction_found) {
- metrics_recorder_->RecordDetailedUserAction(
- password_manager::PasswordFormMetricsRecorder::DetailedUserAction::
- kCorrectedUsernameInForm);
- }
- }
- pending_credentials_.password_value =
- HasGeneratedPassword() ? generation_state_->generated_password()
- : password_to_save.first;
- pending_credentials_.preferred = true;
- pending_credentials_.form_has_autofilled_value =
- parsed_submitted_form_->form_has_autofilled_value;
- pending_credentials_.all_possible_passwords =
- parsed_submitted_form_->all_possible_passwords;
- CopyFieldPropertiesMasks(submitted_form_, &pending_credentials_.form_data);
-
- // If we're dealing with an API-driven provisionally saved form, then take
- // the server provided values. We don't do this for non-API forms, as
- // those will never have those members set.
- if (parsed_submitted_form_->type == PasswordForm::Type::kApi) {
- pending_credentials_.skip_zero_click =
- parsed_submitted_form_->skip_zero_click;
- pending_credentials_.display_name = parsed_submitted_form_->display_name;
- pending_credentials_.federation_origin =
- parsed_submitted_form_->federation_origin;
- pending_credentials_.icon_url = parsed_submitted_form_->icon_url;
- // It's important to override |signon_realm| for federated credentials
- // because it has format "federation://" + origin_host + "/" +
- // federation_host
- pending_credentials_.signon_realm = parsed_submitted_form_->signon_realm;
- }
-
- if (HasGeneratedPassword())
- pending_credentials_.type = PasswordForm::Type::kGenerated;
-}
-
-void NewPasswordFormManager::CreatePendingCredentialsForNewCredentials(
- const PasswordForm& submitted_password_form,
- const base::string16& password_element) {
- if (IsHttpAuth() || IsCredentialAPISave()) {
- pending_credentials_ = submitted_password_form;
- return;
- }
-
- // TODO(https://crbug.com/831123): Replace parsing of the observed form with
- // usage of already parsed submitted form.
- std::unique_ptr<PasswordForm> parsed_observed_form =
- ParseFormAndMakeLogging(observed_form_, FormDataParser::Mode::kFilling);
- if (!parsed_observed_form)
- return;
- pending_credentials_ = *parsed_observed_form;
- pending_credentials_.username_element =
- submitted_password_form.username_element;
- pending_credentials_.username_value = submitted_password_form.username_value;
- pending_credentials_.all_possible_usernames =
- submitted_password_form.all_possible_usernames;
- pending_credentials_.all_possible_passwords =
- submitted_password_form.all_possible_passwords;
-
- // The password value will be filled in later, remove any garbage for now.
- pending_credentials_.password_value.clear();
- // The password element should be determined earlier in |PasswordToSave|.
- pending_credentials_.password_element = password_element;
- // The new password's value and element name should be empty.
- pending_credentials_.new_password_value.clear();
- pending_credentials_.new_password_element.clear();
-}
-
-void NewPasswordFormManager::ProcessUpdate() {
- DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
- DCHECK(preferred_match_ || pending_credentials_.IsFederatedCredential());
- // If we're doing an Update, we either autofilled correctly and need to
- // update the stats, or the user typed in a new password for autofilled
- // username, or the user selected one of the non-preferred matches,
- // thus requiring a swap of preferred bits.
- DCHECK(pending_credentials_.preferred);
- DCHECK(!client_->IsIncognito());
- DCHECK(parsed_submitted_form_);
-
- password_manager_util::UpdateMetadataForUsage(&pending_credentials_);
-
- base::RecordAction(
- base::UserMetricsAction("PasswordManager_LoginFollowingAutofill"));
-
- // Check to see if this form is a candidate for password generation.
- // Do not send votes on change password forms, since they were already sent in
- // Update() method.
- if (!parsed_submitted_form_->IsPossibleChangePasswordForm()) {
- votes_uploader_.SendVoteOnCredentialsReuse(
- observed_form_, *parsed_submitted_form_, &pending_credentials_);
- }
- if (IsPasswordUpdate()) {
- votes_uploader_.UploadPasswordVote(
- *parsed_submitted_form_, *parsed_submitted_form_,
- autofill::NEW_PASSWORD,
- autofill::FormStructure(pending_credentials_.form_data)
- .FormSignatureAsStr());
- }
-
- if (pending_credentials_.times_used == 1) {
- votes_uploader_.UploadFirstLoginVotes(best_matches_, pending_credentials_,
- *parsed_submitted_form_);
- }
-}
-
-void NewPasswordFormManager::FillHttpAuth() {
- DCHECK(IsHttpAuth());
- if (!preferred_match_)
- return;
- client_->AutofillHttpAuth(*preferred_match_, this);
-}
-
-std::unique_ptr<PasswordForm> NewPasswordFormManager::ParseFormAndMakeLogging(
- const FormData& form,
- FormDataParser::Mode mode) {
- std::unique_ptr<PasswordForm> password_form = parser_.Parse(form, mode);
-
- if (password_manager_util::IsLoggingActive(client_)) {
- BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
- logger.LogFormData(Logger::STRING_FORM_PARSING_INPUT, form);
- if (password_form)
- logger.LogPasswordForm(Logger::STRING_FORM_PARSING_OUTPUT,
- *password_form);
- }
- return password_form;
-}
-
-void NewPasswordFormManager::PresaveGeneratedPasswordInternal(
- const FormData& form,
- const base::string16& generated_password) {
- std::unique_ptr<PasswordForm> parsed_form =
- ParseFormAndMakeLogging(form, FormDataParser::Mode::kSaving);
-
- if (!parsed_form) {
- // Create a password form with a minimum data.
- parsed_form.reset(new PasswordForm());
- parsed_form->origin = form.url;
- parsed_form->signon_realm = GetSignonRealm(form.url);
- }
-
- if (!HasGeneratedPassword()) {
- generation_state_ =
- std::make_unique<PasswordGenerationState>(form_saver_.get(), client_);
- votes_uploader_.set_generated_password_changed(false);
- metrics_recorder_->SetGeneratedPasswordStatus(
- PasswordFormMetricsRecorder::GeneratedPasswordStatus::
- kPasswordAccepted);
- } else {
- // If the password is already generated and a new value to presave differs
- // from the presaved one, then mark that the generated password was changed.
- // If a user recovers the original generated password, it will be recorded
- // as a password change.
- if (generation_state_->generated_password() != generated_password) {
- votes_uploader_.set_generated_password_changed(true);
- metrics_recorder_->SetGeneratedPasswordStatus(
- PasswordFormMetricsRecorder::GeneratedPasswordStatus::
- kPasswordEdited);
- }
- }
- votes_uploader_.set_has_generated_password(true);
-
- // Set |password_value| to the generated password in order to ensure that the
- // generated password is saved.
- parsed_form->password_value = generated_password;
-
- generation_state_->PresaveGeneratedPassword(std::move(*parsed_form),
- GetAllMatches());
-}
-
-void NewPasswordFormManager::CalculateFillingAssistanceMetric(
- const FormData& submitted_form) {
- // TODO(https://crbug.com/918846): implement collecting all necessary data on
- // iOS.
-#if not defined(OS_IOS)
- std::set<base::string16> saved_usernames;
- std::set<base::string16> saved_passwords;
-
- for (auto* saved_form : form_fetcher_->GetNonFederatedMatches()) {
- saved_usernames.insert(saved_form->username_value);
- saved_passwords.insert(saved_form->password_value);
- }
-
- // Saved credentials might have empty usernames which are not interesting for
- // filling assistance metric.
- saved_usernames.erase(base::string16());
-
- metrics_recorder_->CalculateFillingAssistanceMetric(
- submitted_form, saved_usernames, saved_passwords, IsBlacklisted(),
- form_fetcher_->GetInteractionsStats());
-#endif
-}
-
-std::vector<const PasswordForm*> NewPasswordFormManager::GetAllMatches() const {
- std::vector<const autofill::PasswordForm*> result =
- form_fetcher_->GetNonFederatedMatches();
- PasswordForm::Scheme observed_form_scheme = GetScheme();
- base::EraseIf(result, [observed_form_scheme](const auto* form) {
- return form->scheme != observed_form_scheme;
- });
- return result;
-}
-
-void NewPasswordFormManager::SavePendingToStore(bool update) {
- const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating(
- *parsed_submitted_form_, best_matches_);
- if ((update || password_overridden_) &&
- !pending_credentials_.IsFederatedCredential()) {
- DCHECK(saved_form);
- }
- base::string16 old_password =
- saved_form ? saved_form->password_value : base::string16();
- if (HasGeneratedPassword()) {
- generation_state_->CommitGeneratedPassword(pending_credentials_,
- GetAllMatches(), old_password);
- } else if (update) {
- form_saver_->Update(pending_credentials_, GetAllMatches(), old_password);
- } else {
- form_saver_->Save(pending_credentials_, GetAllMatches(), old_password);
- }
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/new_password_form_manager.h b/chromium/components/password_manager/core/browser/new_password_form_manager.h
deleted file mode 100644
index d65d30d10fd..00000000000
--- a/chromium/components/password_manager/core/browser/new_password_form_manager.h
+++ /dev/null
@@ -1,414 +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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_NEW_PASSWORD_FORM_MANAGER_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_NEW_PASSWORD_FORM_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/signatures_util.h"
-#include "components/password_manager/core/browser/form_fetcher.h"
-#include "components/password_manager/core/browser/form_parsing/form_parser.h"
-#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
-#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
-#include "components/password_manager/core/browser/password_form_metrics_recorder.h"
-#include "components/password_manager/core/browser/password_form_user_action.h"
-#include "components/password_manager/core/browser/password_store.h"
-#include "components/password_manager/core/browser/votes_uploader.h"
-
-namespace password_manager {
-
-class FormSaver;
-class PasswordFormMetricsRecorder;
-class PasswordGenerationState;
-class PasswordManagerClient;
-class PasswordManagerDriver;
-
-// This class helps with filling the observed form and with saving/updating the
-// stored information about it. It is aimed to replace PasswordFormManager and
-// to be renamed in new Password Manager design. Details
-// go/new-cpm-design-refactoring.
-class NewPasswordFormManager : public PasswordFormManagerInterface,
- public FormFetcher::Consumer {
- public:
- // TODO(crbug.com/621355): So far, |form_fetcher| can be null. In that case
- // |this| creates an instance of it itself (meant for production code). Once
- // the fetcher is shared between PasswordFormManager instances, it will be
- // required that |form_fetcher| is not null. |form_saver| is used to
- // save/update the form. |metrics_recorder| records metrics for |*this|. If
- // null a new instance will be created.
- NewPasswordFormManager(
- PasswordManagerClient* client,
- const base::WeakPtr<PasswordManagerDriver>& driver,
- const autofill::FormData& observed_form,
- FormFetcher* form_fetcher,
- std::unique_ptr<FormSaver> form_saver,
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder);
-
- // Constructor for http authentication (aka basic authentication).
- NewPasswordFormManager(PasswordManagerClient* client,
- PasswordStore::FormDigest observed_http_auth_digest,
- FormFetcher* form_fetcher,
- std::unique_ptr<FormSaver> form_saver);
-
- ~NewPasswordFormManager() override;
-
- // The upper limit on how many times Chrome will try to autofill the same
- // form.
- static constexpr int kMaxTimesAutofill = 5;
-
- // Compares |observed_form_| with |form| and returns true if they are the
- // same and if |driver| is the same as |driver_|.
- bool DoesManage(const autofill::FormData& form,
- const PasswordManagerDriver* driver) const;
-
- // Returns whether the form identified by |form_renderer_id| and |driver|
- // is managed by this password form manager. Don't call this on iOS.
- bool DoesManageAccordingToRendererId(
- uint32_t form_renderer_id,
- const PasswordManagerDriver* driver) const;
-
- // Check that |submitted_form_| is equal to |form| from the user point of
- // view. It is used for detecting that a form is reappeared after navigation
- // for success detection.
- bool IsEqualToSubmittedForm(const autofill::FormData& form) const;
-
- // If |submitted_form| is managed by *this (i.e. DoesManage returns true for
- // |submitted_form| and |driver|) then saves |submitted_form| to
- // |submitted_form_| field, sets |is_submitted| = true and returns true.
- // Otherwise returns false.
- // |is_gaia_with_skip_save_password_form| is true iff this is Gaia form which
- // should be skipped on saving.
- bool ProvisionallySave(const autofill::FormData& submitted_form,
- const PasswordManagerDriver* driver,
- bool is_gaia_with_skip_save_password_form);
-
- // If |submitted_form| is managed by *this then saves |submitted_form| to
- // |submitted_form_| field, sets |is_submitted| = true and returns true.
- // Otherwise returns false.
- bool ProvisionallySaveHttpAuthForm(
- const autofill::PasswordForm& submitted_form);
-
- bool is_submitted() { return is_submitted_; }
- void set_not_submitted() { is_submitted_ = false; }
-
- void set_old_parsing_result(const autofill::PasswordForm& form) {
- old_parsing_result_ = form;
- }
-
- // Returns true if |*this| manages http authentication.
- bool IsHttpAuth() const;
-
- // Returns true if |*this| manages saving with Credentials API. This class is
- // not used for filling with Credentials API.
- bool IsCredentialAPISave() const;
-
- // Returns scheme of the observed form or http authentication.
- autofill::PasswordForm::Scheme GetScheme() const;
-
- // Selects from |predictions| predictions that corresponds to
- // |observed_form_|, initiates filling and stores predictions in
- // |predictions_|.
- void ProcessServerPredictions(
- const std::map<autofill::FormSignature, FormPredictions>& predictions);
-
- // Sends fill data to the renderer.
- void Fill();
-
- // Sends fill data to the renderer to fill |observed_form|.
- void FillForm(const autofill::FormData& observed_form);
-
- // Sends the request to prefill the generated password or pops up an
- // additional UI in case of possible override.
- void OnGeneratedPasswordAccepted(autofill::FormData form_data,
- uint32_t generation_element_id,
- const base::string16& password);
-
- // PasswordFormManagerForUI:
- const GURL& GetOrigin() const override;
- const std::map<base::string16, const autofill::PasswordForm*>&
- GetBestMatches() const override;
- std::vector<const autofill::PasswordForm*> GetFederatedMatches()
- const override;
- const autofill::PasswordForm& GetPendingCredentials() const override;
- metrics_util::CredentialSourceType GetCredentialSource() override;
- PasswordFormMetricsRecorder* GetMetricsRecorder() override;
- base::span<const autofill::PasswordForm* const> GetBlacklistedMatches()
- const override;
- base::span<const InteractionsStats> GetInteractionsStats() const override;
- bool IsBlacklisted() const override;
-
- void Save() override;
- void Update(const autofill::PasswordForm& credentials_to_update) override;
- void UpdateUsername(const base::string16& new_username) override;
- void UpdatePasswordValue(const base::string16& new_password) override;
-
- void OnNopeUpdateClicked() override;
- void OnNeverClicked() override;
- void OnNoInteraction(bool is_update) override;
- void PermanentlyBlacklist() override;
- void OnPasswordsRevealed() override;
-
- // PasswordFormManagerInterface:
- bool IsNewLogin() const override;
- FormFetcher* GetFormFetcher() override;
- bool IsPendingCredentialsPublicSuffixMatch() const override;
- void PresaveGeneratedPassword(const autofill::PasswordForm& form) override;
- void PasswordNoLongerGenerated() override;
- bool HasGeneratedPassword() const override;
- void SetGenerationPopupWasShown(bool generation_popup_was_shown,
- bool is_manual_generation) override;
- void SetGenerationElement(const base::string16& generation_element) override;
- bool IsPossibleChangePasswordFormWithoutUsername() const override;
- bool IsPasswordUpdate() const override;
- std::vector<base::WeakPtr<PasswordManagerDriver>> GetDrivers() const override;
- const autofill::PasswordForm* GetSubmittedForm() const override;
-
-#if defined(OS_IOS)
- // Presaves the form with |generated_password|. This function is called once
- // when the user accepts the generated password. The password was generated in
- // the field with identifier |generation_element|. |driver| corresponds to the
- // |form| parent frame.
- void PresaveGeneratedPassword(PasswordManagerDriver* driver,
- const autofill::FormData& form,
- const base::string16& generated_password,
- const base::string16& generation_element);
-
- // Updates the presaved credential with the generated password when the user
- // types in field with |field_identifier|, which is in form with
- // |form_identifier| and the field value is |field_value|. Return true if
- // |*this| manages a form with name |form_identifier|.
- bool UpdateGeneratedPasswordOnUserInput(
- const base::string16& form_identifier,
- const base::string16& field_identifier,
- const base::string16& field_value);
-#endif // defined(OS_IOS)
-
- // Create a copy of |*this| which can be passed to the code handling
- // save-password related UI. This omits some parts of the internal data, so
- // the result is not identical to the original.
- // TODO(crbug.com/739366): Replace with translating one appropriate class into
- // another one.
- std::unique_ptr<NewPasswordFormManager> Clone();
-
-#if defined(UNIT_TEST)
- static void set_wait_for_server_predictions_for_filling(bool value) {
- wait_for_server_predictions_for_filling_ = value;
- }
-
- FormSaver* form_saver() { return form_saver_.get(); }
-#endif
-
- // TODO(https://crbug.com/831123): Remove it when the old form parsing is
- // removed.
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder() {
- return metrics_recorder_;
- }
-
- protected:
- // Constructor for Credentials API.
- NewPasswordFormManager(PasswordManagerClient* client,
- std::unique_ptr<autofill::PasswordForm> saved_form,
- std::unique_ptr<FormFetcher> form_fetcher,
- std::unique_ptr<FormSaver> form_saver);
-
- // FormFetcher::Consumer:
- void OnFetchCompleted() override;
-
- // Create pending credentials from |parsed_submitted_form_| and forms received
- // from the password store.
- void CreatePendingCredentials();
-
- private:
- // Delegating constructor.
- NewPasswordFormManager(
- PasswordManagerClient* client,
- FormFetcher* form_fetcher,
- std::unique_ptr<FormSaver> form_saver,
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder,
- PasswordStore::FormDigest form_digest);
-
- // Compares |parsed_form| with |old_parsing_result_| and records UKM metric.
- // TODO(https://crbug.com/831123): Remove it when the old form parsing is
- // removed.
- void RecordMetricOnCompareParsingResult(
- const autofill::PasswordForm& parsed_form);
-
- // Records the status of readonly fields during parsing, combined with the
- // overall success of the parsing. It reports through two different metrics,
- // depending on whether |mode| indicates parsing for saving or filling.
- void RecordMetricOnReadonly(
- FormDataParser::ReadonlyPasswordFields readonly_status,
- bool parsing_successful,
- FormDataParser::Mode mode);
-
- // Report the time between receiving credentials from the password store and
- // the autofill server responding to the lookup request.
- void ReportTimeBetweenStoreAndServerUMA();
-
- // Create pending credentials from provisionally saved form when this form
- // represents credentials that were not previosly saved.
- void CreatePendingCredentialsForNewCredentials(
- const autofill::PasswordForm& submitted_password_form,
- const base::string16& password_element);
-
- void SetPasswordOverridden(bool password_overridden) {
- password_overridden_ = password_overridden;
- votes_uploader_.set_password_overridden(password_overridden);
- }
-
- // Helper for Save in the case there is at least one match for the pending
- // credentials. This sends needed signals to the autofill server, and also
- // triggers some UMA reporting.
- void ProcessUpdate();
-
- // Sends fill data to the http auth popup.
- void FillHttpAuth();
-
- // Helper function for calling form parsing and logging results if logging is
- // active.
- std::unique_ptr<autofill::PasswordForm> ParseFormAndMakeLogging(
- const autofill::FormData& form,
- FormDataParser::Mode mode);
-
- void PresaveGeneratedPasswordInternal(
- const autofill::FormData& form,
- const base::string16& generated_password);
-
- // Calculates FillingAssistance metric for |submitted_form|. The metric is
- // recorded in case when the successful submission is detected.
- void CalculateFillingAssistanceMetric(
- const autofill::FormData& submitted_form);
-
- // Returns all the credentials for the origin (essentially, |best_matches_|
- // and |not_best_matches_|).
- std::vector<const autofill::PasswordForm*> GetAllMatches() const;
-
- // Save/update |pending_credentials_| to the password store.
- void SavePendingToStore(bool update);
-
- // The client which implements embedder-specific PasswordManager operations.
- PasswordManagerClient* client_;
-
- base::WeakPtr<PasswordManagerDriver> driver_;
-
- // TODO(https://crbug.com/943045): use std::variant for keeping
- // |observed_form_| and |observed_not_web_form_digest_|.
- autofill::FormData observed_form_;
-
- // Used for retrieving credentials in case http authentication or Credentials
- // API.
- base::Optional<PasswordStore::FormDigest> observed_not_web_form_digest_;
-
- // Set of nonblacklisted PasswordForms from the DB that best match the form
- // being managed by |this|, indexed by username. The PasswordForms are owned
- // by |form_fetcher_|.
- std::map<base::string16, const autofill::PasswordForm*> best_matches_;
-
- // Set of forms from PasswordStore that correspond to the current site and
- // that are not in |best_matches_|. They are owned by |form_fetcher_|.
- // It is leftover from the old PasswordFormManager.
- // TODO(https://crbug.com/831123): update all places where it is used with
- // saved credentials from |form_fetcher_|.
- std::vector<const autofill::PasswordForm*> not_best_matches_;
-
- // Set of blacklisted forms from the PasswordStore that best match the current
- // form. They are owned by |form_fetcher_|.
- std::vector<const autofill::PasswordForm*> blacklisted_matches_;
-
- // If the observed form gets blacklisted through |this|, the blacklist entry
- // gets stored in |new_blacklisted_| until data is potentially refreshed by
- // reading from PasswordStore again. |blacklisted_matches_| will contain
- // |new_blacklisted_.get()| in that case. The PasswordForm will usually get
- // accessed via |blacklisted_matches_|, this unique_ptr is only used to store
- // it (unlike the rest of forms being pointed to in |blacklisted_matches_|,
- // which are owned by |form_fetcher_|).
- std::unique_ptr<autofill::PasswordForm> new_blacklisted_;
-
- // Convenience pointer to entry in best_matches_ that is marked
- // as preferred. This is only allowed to be null if there are no best matches
- // at all, since there will always be one preferred login when there are
- // multiple matches (when first saved, a login is marked preferred).
- const autofill::PasswordForm* preferred_match_ = nullptr;
-
- // Takes care of recording metrics and events for |*this|.
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder_;
-
- // When not null, then this is the object which |form_fetcher_| points to.
- std::unique_ptr<FormFetcher> owned_form_fetcher_;
-
- // FormFetcher instance which owns the login data from PasswordStore.
- FormFetcher* form_fetcher_;
-
- // FormSaver instance used by |this| to all tasks related to storing
- // credentials.
- const std::unique_ptr<FormSaver> form_saver_;
-
- VotesUploader votes_uploader_;
-
- // |is_submitted_| = true means that a submission of the managed form was seen
- // and then |submitted_form_| contains the submitted form.
- bool is_submitted_ = false;
- autofill::FormData submitted_form_;
- std::unique_ptr<autofill::PasswordForm> parsed_submitted_form_;
-
- // Stores updated credentials when the form was submitted but success is still
- // unknown. This variable contains credentials that are ready to be written
- // (saved or updated) to a password store. It is calculated based on
- // |submitted_form_| and |best_matches_|.
- autofill::PasswordForm pending_credentials_;
-
- // Whether |pending_credentials_| stores a credential that should be added
- // to the password store. False means it's a pure update to the existing ones.
- // TODO(crbug/831123): this value only makes sense internally. Remove public
- // dependencies on it.
- bool is_new_login_ = true;
-
- // Handles the user flows related to the generation.
- std::unique_ptr<PasswordGenerationState> generation_state_;
-
- // Whether a saved password was overridden. The flag is true when there is a
- // credential in the store that will get a new password value.
- bool password_overridden_ = false;
-
- // If Chrome has already autofilled a few times, it is probable that autofill
- // is triggered by programmatic changes in the page. We set a maximum number
- // of times that Chrome will autofill to avoid being stuck in an infinite
- // loop.
- int autofills_left_ = kMaxTimesAutofill;
-
- // True until server predictions received or waiting for them timed out.
- bool waiting_for_server_predictions_ = false;
-
- // Controls whether to wait or not server before filling. It is used in tests.
- static bool wait_for_server_predictions_for_filling_;
-
- // Used for comparison metrics.
- // TODO(https://crbug.com/831123): Remove it when the old form parsing is
- // removed.
- autofill::PasswordForm old_parsing_result_;
-
- // Time when stored credentials are received from the store. Used for metrics.
- base::TimeTicks received_stored_credentials_time_;
-
- // Used to transform FormData into PasswordForms.
- FormDataParser parser_;
-
- base::WeakPtrFactory<NewPasswordFormManager> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(NewPasswordFormManager);
-};
-
-} // namespace password_manager
-
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_NEW_PASSWORD_FORM_MANAGER_H_
diff --git a/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc b/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc
deleted file mode 100644
index 30b4ad36f59..00000000000
--- a/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc
+++ /dev/null
@@ -1,2041 +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 "components/password_manager/core/browser/new_password_form_manager.h"
-
-#include <string>
-#include <utility>
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_download_manager.h"
-#include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/password_form.h"
-#include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/core/common/password_form_generation_data.h"
-#include "components/autofill/core/common/password_generation_util.h"
-#include "components/password_manager/core/browser/fake_form_fetcher.h"
-#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
-#include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store.h"
-#include "components/password_manager/core/browser/stub_form_saver.h"
-#include "components/password_manager/core/browser/stub_password_manager_client.h"
-#include "components/password_manager/core/browser/stub_password_manager_driver.h"
-#include "components/password_manager/core/browser/vote_uploads_test_matchers.h"
-#include "components/ukm/test_ukm_recorder.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using autofill::AutofillUploadContents;
-using autofill::FieldPropertiesFlags;
-using autofill::FormData;
-using autofill::FormFieldData;
-using autofill::FormSignature;
-using autofill::FormStructure;
-using autofill::PasswordForm;
-using autofill::PasswordFormFillData;
-using autofill::PasswordFormGenerationData;
-using autofill::ServerFieldType;
-using base::ASCIIToUTF16;
-using base::TestMockTimeTaskRunner;
-using testing::_;
-using testing::AllOf;
-using testing::Contains;
-using testing::ElementsAre;
-using testing::IsEmpty;
-using testing::Mock;
-using testing::NiceMock;
-using testing::Pointee;
-using testing::Return;
-using testing::SaveArg;
-using testing::SaveArgPointee;
-using testing::UnorderedElementsAre;
-
-namespace password_manager {
-
-namespace {
-
-// Indices of username and password fields in the observed form.
-const int kUsernameFieldIndex = 1;
-const int kPasswordFieldIndex = 2;
-
-MATCHER_P(FormHasUniqueKey, key, "") {
- return ArePasswordFormUniqueKeysEqual(arg, key);
-}
-
-class MockPasswordManagerDriver : public StubPasswordManagerDriver {
- public:
- MockPasswordManagerDriver() {}
-
- ~MockPasswordManagerDriver() override {}
-
- MOCK_METHOD1(FillPasswordForm, void(const PasswordFormFillData&));
- MOCK_METHOD1(AllowPasswordGenerationForForm, void(const PasswordForm&));
- MOCK_METHOD1(FormEligibleForGenerationFound,
- void(const autofill::PasswordFormGenerationData&));
-};
-
-class MockAutofillDownloadManager : public autofill::AutofillDownloadManager {
- public:
- MockAutofillDownloadManager()
- : AutofillDownloadManager(nullptr, &fake_observer) {}
-
- MOCK_METHOD6(StartUploadRequest,
- bool(const FormStructure&,
- bool,
- const autofill::ServerFieldTypeSet&,
- const std::string&,
- bool,
- PrefService*));
-
- private:
- class StubObserver : public AutofillDownloadManager::Observer {
- void OnLoadedServerPredictions(
- std::string response,
- const std::vector<std::string>& form_signatures) override {}
- };
-
- StubObserver fake_observer;
- DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager);
-};
-
-class MockPasswordManagerClient : public StubPasswordManagerClient {
- public:
- MockPasswordManagerClient() = default;
- ~MockPasswordManagerClient() override = default;
-
- MOCK_CONST_METHOD0(IsIncognito, bool());
-
- MOCK_METHOD0(GetAutofillDownloadManager,
- autofill::AutofillDownloadManager*());
-
- MOCK_METHOD0(UpdateFormManagers, void());
-
- MOCK_METHOD2(AutofillHttpAuth,
- void(const PasswordForm&, const PasswordFormManagerForUI*));
-};
-
-void CheckPendingCredentials(const PasswordForm& expected,
- const PasswordForm& actual) {
- EXPECT_EQ(expected.signon_realm, actual.signon_realm);
- EXPECT_EQ(expected.origin, actual.origin);
- EXPECT_EQ(expected.action, actual.action);
- EXPECT_EQ(expected.username_value, actual.username_value);
- EXPECT_EQ(expected.password_value, actual.password_value);
- EXPECT_EQ(expected.username_element, actual.username_element);
- EXPECT_EQ(expected.password_element, actual.password_element);
- EXPECT_EQ(expected.blacklisted_by_user, actual.blacklisted_by_user);
- EXPECT_EQ(expected.form_data, actual.form_data);
-}
-
-struct ExpectedGenerationUKM {
- base::Optional<int64_t> generation_popup_shown;
- int64_t has_generated_password;
- base::Optional<int64_t> generated_password_modified;
-};
-
-// Check that UKM |metric_name| in |entry| is equal to |expected|. |expected| ==
-// null means that no metric recording is expected.
-void CheckMetric(const int64_t* expected,
- const ukm::mojom::UkmEntry* entry,
- const char* metric_name) {
- SCOPED_TRACE(testing::Message("Checking UKM metric ") << metric_name);
-
- const int64_t* actual =
- ukm::TestUkmRecorder::GetEntryMetric(entry, metric_name);
-
- ASSERT_EQ(!!expected, !!actual);
- if (expected)
- EXPECT_EQ(*expected, *actual);
-}
-
-// Check that |recorder| records metrics |expected_metrics|.
-void CheckPasswordGenerationUKM(const ukm::TestAutoSetUkmRecorder& recorder,
- const ExpectedGenerationUKM& expected_metrics) {
- auto entries =
- recorder.GetEntriesByName(ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(1u, entries.size());
- const int64_t* expected_popup_shown = nullptr;
- if (expected_metrics.generation_popup_shown)
- expected_popup_shown = &expected_metrics.generation_popup_shown.value();
- CheckMetric(expected_popup_shown, entries[0],
- ukm::builders::PasswordForm::kGeneration_PopupShownName);
-
- CheckMetric(&expected_metrics.has_generated_password, entries[0],
- ukm::builders::PasswordForm::kGeneration_GeneratedPasswordName);
-
- const int64_t* expected_password_modified = nullptr;
- if (expected_metrics.generated_password_modified)
- expected_password_modified =
- &expected_metrics.generated_password_modified.value();
- CheckMetric(
- expected_password_modified, entries[0],
- ukm::builders::PasswordForm::kGeneration_GeneratedPasswordModifiedName);
-}
-
-// Create predictions for |form| using field predictions |field_predictions|.
-std::map<FormSignature, FormPredictions> CreatePredictions(
- const FormData& form,
- std::vector<std::pair<int, ServerFieldType>> field_predictions) {
- FormPredictions predictions;
- for (const auto& index_prediction : field_predictions) {
- uint32_t renderer_id =
- form.fields[index_prediction.first].unique_renderer_id;
- ServerFieldType server_type = index_prediction.second;
- predictions.push_back({.renderer_id = renderer_id, .type = server_type});
- }
- FormSignature form_signature = CalculateFormSignature(form);
- return {{form_signature, predictions}};
-}
-
-class MockFormSaver : public StubFormSaver {
- public:
- MockFormSaver() = default;
-
- ~MockFormSaver() override = default;
-
- // FormSaver:
- MOCK_METHOD1(PermanentlyBlacklist, PasswordForm(PasswordStore::FormDigest));
- MOCK_METHOD3(Save,
- void(PasswordForm pending,
- const std::vector<const PasswordForm*>& matches,
- const base::string16& old_password));
- MOCK_METHOD3(Update,
- void(PasswordForm pending,
- const std::vector<const PasswordForm*>& matches,
- const base::string16& old_password));
- MOCK_METHOD4(UpdateReplace,
- void(PasswordForm pending,
- const std::vector<const PasswordForm*>& matches,
- const base::string16& old_password,
- const PasswordForm& old_unique_key));
- MOCK_METHOD1(Remove, void(const PasswordForm&));
-
- std::unique_ptr<FormSaver> Clone() override {
- return std::make_unique<MockFormSaver>();
- }
-
- // Convenience downcasting method.
- static MockFormSaver& Get(NewPasswordFormManager* form_manager) {
- return *static_cast<MockFormSaver*>(form_manager->form_saver());
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockFormSaver);
-};
-
-// TODO(https://crbug.com/831123): Test sending metrics.
-// TODO(https://crbug.com/831123): Test create pending credentials when
-// generation happened.
-// TODO(https://crbug.com/831123): Test create pending credentials with
-// Credential API.
-class NewPasswordFormManagerTest : public testing::Test {
- public:
- NewPasswordFormManagerTest() : task_runner_(new TestMockTimeTaskRunner) {
- GURL origin = GURL("https://accounts.google.com/a/ServiceLoginAuth");
- GURL action = GURL("https://accounts.google.com/a/ServiceLogin");
- GURL psl_origin = GURL("https://myaccounts.google.com/a/ServiceLoginAuth");
- GURL psl_action = GURL("https://myaccounts.google.com/a/ServiceLogin");
-
- observed_form_.url = origin;
- observed_form_.action = action;
- observed_form_.name = ASCIIToUTF16("sign-in");
- observed_form_.unique_renderer_id = 1;
- observed_form_.is_form_tag = true;
-
- observed_form_only_password_fields_ = observed_form_;
-
- FormFieldData field;
- field.name = ASCIIToUTF16("firstname");
- field.id_attribute = field.name;
- field.name_attribute = field.name;
- field.form_control_type = "text";
- field.unique_renderer_id = 1;
- observed_form_.fields.push_back(field);
-
- field.name = ASCIIToUTF16("username");
- field.id_attribute = field.name;
- field.name_attribute = field.name;
- field.form_control_type = "text";
- field.unique_renderer_id = 2;
- observed_form_.fields.push_back(field);
-
- field.name = ASCIIToUTF16("password");
- field.id_attribute = field.name;
- field.name_attribute = field.name;
- field.form_control_type = "password";
- field.unique_renderer_id = 3;
- observed_form_.fields.push_back(field);
- observed_form_only_password_fields_.fields.push_back(field);
-
- field.name = ASCIIToUTF16("password2");
- field.id_attribute = field.name;
- field.name_attribute = field.name;
- field.form_control_type = "password";
- field.unique_renderer_id = 5;
- observed_form_only_password_fields_.fields.push_back(field);
-
-// On iOS the unique_id member uniquely addresses this field in the DOM.
-// This is an ephemeral value which is not guaranteed to be stable across
-// page loads. It serves to allow a given field to be found during the
-// current navigation.
-// TODO(crbug.com/896689): Expand the logic/application of this to other
-// platforms and/or merge this concept with |unique_renderer_id|.
-#if defined(OS_IOS)
- for (auto& f : observed_form_.fields) {
- f.unique_id = f.id_attribute;
- }
- for (auto& f : observed_form_only_password_fields_.fields) {
- f.unique_id = f.id_attribute;
- }
-#endif
-
- submitted_form_ = observed_form_;
- submitted_form_.fields[kUsernameFieldIndex].value = ASCIIToUTF16("user1");
- submitted_form_.fields[kPasswordFieldIndex].value = ASCIIToUTF16("secret1");
-
- saved_match_.origin = origin;
- saved_match_.action = action;
- saved_match_.signon_realm = "https://accounts.google.com/";
- saved_match_.preferred = true;
- saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
- saved_match_.username_element = ASCIIToUTF16("field1");
- saved_match_.password_value = ASCIIToUTF16("test1");
- saved_match_.password_element = ASCIIToUTF16("field2");
- saved_match_.is_public_suffix_match = false;
- saved_match_.scheme = PasswordForm::Scheme::kHtml;
-
- psl_saved_match_ = saved_match_;
- psl_saved_match_.origin = psl_origin;
- psl_saved_match_.action = psl_action;
- psl_saved_match_.signon_realm = "https://myaccounts.google.com/";
- psl_saved_match_.is_public_suffix_match = true;
-
- parsed_observed_form_ = saved_match_;
- parsed_observed_form_.form_data = observed_form_;
- parsed_observed_form_.username_element =
- observed_form_.fields[kUsernameFieldIndex].name;
- parsed_observed_form_.password_element =
- observed_form_.fields[kPasswordFieldIndex].name;
-
- parsed_submitted_form_ = parsed_observed_form_;
- parsed_submitted_form_.form_data = submitted_form_;
- parsed_submitted_form_.username_value =
- submitted_form_.fields[kUsernameFieldIndex].value;
- parsed_submitted_form_.password_value =
- submitted_form_.fields[kPasswordFieldIndex].value;
-
- blacklisted_match_ = saved_match_;
- blacklisted_match_.blacklisted_by_user = true;
-
- EXPECT_CALL(client_, GetAutofillDownloadManager())
- .WillRepeatedly(testing::Return(&mock_autofill_download_manager_));
- ON_CALL(mock_autofill_download_manager_,
- StartUploadRequest(_, _, _, _, _, _))
- .WillByDefault(testing::Return(true));
-
- CreateFormManager(observed_form_);
- }
-
- protected:
- MockAutofillDownloadManager mock_autofill_download_manager_;
- FormData observed_form_;
- FormData submitted_form_;
- FormData observed_form_only_password_fields_;
- PasswordForm saved_match_;
- PasswordForm psl_saved_match_;
- PasswordForm blacklisted_match_;
- PasswordForm parsed_observed_form_;
- PasswordForm parsed_submitted_form_;
- MockPasswordManagerClient client_;
- MockPasswordManagerDriver driver_;
- scoped_refptr<TestMockTimeTaskRunner> task_runner_;
-
- // Define |fetcher_| before |form_manager_|, because the former needs to
- // outlive the latter.
- std::unique_ptr<FakeFormFetcher> fetcher_;
- std::unique_ptr<NewPasswordFormManager> form_manager_;
-
- // Creates NewPasswordFormManager and sets it to |form_manager_|. Along the
- // way a new |fetcher_| is created.
- void CreateFormManager(const FormData& observed_form) {
- fetcher_.reset(new FakeFormFetcher());
- fetcher_->Fetch();
- form_manager_.reset(new NewPasswordFormManager(
- &client_, driver_.AsWeakPtr(), observed_form, fetcher_.get(),
- std::make_unique<NiceMock<MockFormSaver>>(), nullptr));
- }
-
- // Creates NewPasswordFormManager and sets it to |form_manager_| for
- // |base_auth_observed_form|. Along the way a new |fetcher_| is created.
- void CreateFormManagerForNonWebForm(
- const PasswordForm& base_auth_observed_form) {
- fetcher_.reset(new FakeFormFetcher());
- fetcher_->Fetch();
- form_manager_.reset(new NewPasswordFormManager(
- &client_, PasswordStore::FormDigest(base_auth_observed_form),
- fetcher_.get(), std::make_unique<NiceMock<MockFormSaver>>()));
- }
-
- void SetNonFederatedAndNotifyFetchCompleted(
- const std::vector<const autofill::PasswordForm*>& non_federated) {
- fetcher_->SetNonFederated(non_federated);
- fetcher_->NotifyFetchCompleted();
- }
-};
-
-TEST_F(NewPasswordFormManagerTest, DoesManage) {
- EXPECT_TRUE(form_manager_->DoesManage(observed_form_, &driver_));
- // Forms on other drivers are not considered managed.
- EXPECT_FALSE(form_manager_->DoesManage(observed_form_, nullptr));
- FormData another_form = observed_form_;
- another_form.is_form_tag = false;
- EXPECT_FALSE(form_manager_->DoesManage(another_form, &driver_));
-
- // On non-iOS platforms unique_renderer_id is the form identifier.
- another_form = observed_form_;
- another_form.unique_renderer_id = observed_form_.unique_renderer_id + 1;
-#if defined(OS_IOS)
- EXPECT_TRUE(form_manager_->DoesManage(another_form, &driver_));
-#else
- EXPECT_FALSE(form_manager_->DoesManage(another_form, &driver_));
-#endif
-
- // On iOS platforms form name is the form identifier.
- another_form = observed_form_;
- another_form.name = observed_form_.name + ASCIIToUTF16("1");
-#if defined(OS_IOS)
- EXPECT_FALSE(form_manager_->DoesManage(another_form, &driver_));
-#else
- EXPECT_TRUE(form_manager_->DoesManage(another_form, &driver_));
-#endif
-}
-
-TEST_F(NewPasswordFormManagerTest, DoesManageNoFormTag) {
- observed_form_.is_form_tag = false;
- CreateFormManager(observed_form_);
-
- FormData another_form = observed_form_;
- // Simulate that new input was added by JavaScript.
- another_form.fields.push_back(FormFieldData());
- EXPECT_TRUE(form_manager_->DoesManage(another_form, &driver_));
- // Forms on other drivers are not considered managed.
- EXPECT_FALSE(form_manager_->DoesManage(another_form, nullptr));
-}
-
-TEST_F(NewPasswordFormManagerTest, Autofill) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- CreateFormManager(observed_form_);
- EXPECT_CALL(driver_, FormEligibleForGenerationFound(_)).Times(0);
- PasswordFormFillData fill_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
- CreateFormManager(observed_form_);
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_EQ(observed_form_.url, fill_data.origin);
- EXPECT_FALSE(fill_data.wait_for_username);
- EXPECT_EQ(observed_form_.fields[1].name, fill_data.username_field.name);
- EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
- EXPECT_EQ(observed_form_.fields[2].name, fill_data.password_field.name);
- EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
-}
-
-TEST_F(NewPasswordFormManagerTest, AutofillNotMoreThan5Times) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- EXPECT_CALL(driver_, FillPasswordForm(_));
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- task_runner_->FastForwardUntilNoTasksRemain();
- Mock::VerifyAndClearExpectations(&driver_);
-
- for (size_t i = 0; i < NewPasswordFormManager::kMaxTimesAutofill - 1; ++i) {
- EXPECT_CALL(driver_, FillPasswordForm(_));
- form_manager_->Fill();
- Mock::VerifyAndClearExpectations(&driver_);
- }
-
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- form_manager_->Fill();
-}
-
-// NewPasswordFormManager should always send fill data to renderer, even for
-// sign-up forms (no "current-password" field, i.e., no password field to fill
-// into). However, for sign-up forms, no particular password field should be
-// identified for filling. That way, Chrome won't disturb the user by filling
-// the sign-up form, but will be able to offer a manual fallback for filling if
-// the form was misclassified.
-TEST_F(NewPasswordFormManagerTest, AutofillSignUpForm) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- // Make |observed_form_| to be sign-up form.
- observed_form_.fields.back().autocomplete_attribute = "new-password";
-
- PasswordFormFillData fill_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
-
- PasswordFormGenerationData generation_data;
- EXPECT_CALL(driver_, FormEligibleForGenerationFound(_))
- .WillOnce(SaveArg<0>(&generation_data));
-
- CreateFormManager(observed_form_);
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- task_runner_->FastForwardUntilNoTasksRemain();
- constexpr uint32_t kNoID = FormFieldData::kNotSetFormControlRendererId;
- EXPECT_EQ(kNoID, fill_data.password_field.unique_renderer_id);
- EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
-#if defined(OS_IOS)
- EXPECT_EQ(ASCIIToUTF16("sign-in"), generation_data.form_name);
- EXPECT_EQ(ASCIIToUTF16("password"), generation_data.new_password_element);
- EXPECT_EQ(base::string16(), generation_data.confirmation_password_element);
-#else
- EXPECT_EQ(observed_form_.fields.back().unique_renderer_id,
- generation_data.new_password_renderer_id);
- EXPECT_EQ(kNoID, generation_data.confirmation_password_renderer_id);
-#endif
-}
-
-// Check that generation signal is sent the the renderer when new password
-// fields are marked with autocomplete attribute.
-TEST_F(NewPasswordFormManagerTest, GenerationOnNewAndConfirmPasswordFields) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- // Make |observed_form_| to be sign-up form.
- observed_form_.fields.back().autocomplete_attribute = "new-password";
- const uint32_t new_password_render_id =
- observed_form_.fields.back().unique_renderer_id;
- // Add a confirmation field.
- FormFieldData field;
- const uint32_t confirm_password_render_id = new_password_render_id + 1;
- field.unique_renderer_id = confirm_password_render_id;
- field.form_control_type = "password";
- field.autocomplete_attribute = "new-password";
- observed_form_.fields.push_back(field);
-
- PasswordFormGenerationData generation_data;
- EXPECT_CALL(driver_, FormEligibleForGenerationFound(_))
- .WillOnce(SaveArg<0>(&generation_data));
-
- CreateFormManager(observed_form_);
- fetcher_->NotifyFetchCompleted();
-
- task_runner_->FastForwardUntilNoTasksRemain();
-#if defined(OS_IOS)
- EXPECT_EQ(ASCIIToUTF16("sign-in"), generation_data.form_name);
- EXPECT_EQ(ASCIIToUTF16("password"), generation_data.new_password_element);
- EXPECT_EQ(base::string16(), generation_data.confirmation_password_element);
-#else
- EXPECT_EQ(new_password_render_id, generation_data.new_password_renderer_id);
- EXPECT_EQ(confirm_password_render_id,
- generation_data.confirmation_password_renderer_id);
-#endif
-}
-
-TEST_F(NewPasswordFormManagerTest, AutofillWithBlacklistedMatch) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordFormFillData fill_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
- fetcher_->SetNonFederated({&saved_match_});
- fetcher_->SetBlacklisted({&blacklisted_match_});
- fetcher_->NotifyFetchCompleted();
-
- task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_EQ(observed_form_.url, fill_data.origin);
- EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
- EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
-}
-
-TEST_F(NewPasswordFormManagerTest, SetSubmitted) {
- EXPECT_FALSE(form_manager_->is_submitted());
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- EXPECT_TRUE(form_manager_->is_submitted());
-
- FormData another_form = submitted_form_;
- another_form.name += ASCIIToUTF16("1");
-#if !defined(OS_IOS)
- // |another_form| is managed because the same |unique_renderer_id| as
- // |observed_form_|.
- EXPECT_TRUE(form_manager_->ProvisionallySave(another_form, &driver_, false));
- EXPECT_TRUE(form_manager_->is_submitted());
-#endif
-}
-
-TEST_F(NewPasswordFormManagerTest, SetSubmittedMultipleTimes) {
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- EXPECT_TRUE(form_manager_->is_submitted());
-
- // Make the submitted form to be invalid password form.
- submitted_form_.fields.clear();
-
- // Expect that |form_manager_| is still in submitted state because the first
- // time the submited form was valid.
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- EXPECT_TRUE(form_manager_->is_submitted());
- EXPECT_TRUE(form_manager_->GetSubmittedForm());
-}
-
-// Tests that when NewPasswordFormManager receives saved matches it waits for
-// server predictions and fills on receving them.
-TEST_F(NewPasswordFormManagerTest, ServerPredictionsWithinDelay) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- // Expects no filling on save matches receiving.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- Mock::VerifyAndClearExpectations(&driver_);
-
- std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
- observed_form_, {std::make_pair(2, autofill::PASSWORD)});
-
- // Expect filling without delay on receiving server predictions.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
- form_manager_->ProcessServerPredictions(predictions);
- Mock::VerifyAndClearExpectations(&driver_);
-
- // Expect no filling on receving predictions again.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- form_manager_->ProcessServerPredictions(predictions);
-}
-
-// Tests that NewPasswordFormManager fills after some delay even without
-// server predictions.
-TEST_F(NewPasswordFormManagerTest, ServerPredictionsAfterDelay) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- // Expect filling after passing filling delay.
-
- // Simulate passing filling delay.
- task_runner_->FastForwardUntilNoTasksRemain();
- Mock::VerifyAndClearExpectations(&driver_);
-
- std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
- observed_form_, {std::make_pair(2, autofill::PASSWORD)});
-
- // Expect filling on receiving server predictions because it was less than
- // kMaxTimesAutofill attempts to fill.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
- form_manager_->ProcessServerPredictions(predictions);
- task_runner_->FastForwardUntilNoTasksRemain();
-}
-
-// Tests that filling happens immediately if server predictions are received
-// before saved matches.
-TEST_F(NewPasswordFormManagerTest, ServerPredictionsBeforeFetcher) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- // Expect no filling after receiving saved matches from |fetcher_|, since
- // |form_manager| is waiting for server-side predictions.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- CreateFormManager(observed_form_);
-
- std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
- observed_form_, {std::make_pair(2, autofill::PASSWORD)});
- form_manager_->ProcessServerPredictions(predictions);
- Mock::VerifyAndClearExpectations(&driver_);
-
- // Expect filling without delay on receiving server predictions.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-}
-
-// Tests creating pending credentials when the password store is empty.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsEmptyStore) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- CheckPendingCredentials(parsed_submitted_form_,
- form_manager_->GetPendingCredentials());
- EXPECT_EQ(UserAction::kOverrideUsernameAndPassword,
- form_manager_->GetMetricsRecorder()->GetUserAction());
-}
-
-// Tests creating pending credentials when new credentials are submitted and the
-// store has another credentials saved.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsNewCredentials) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- CheckPendingCredentials(parsed_submitted_form_,
- form_manager_->GetPendingCredentials());
- EXPECT_EQ(UserAction::kOverrideUsernameAndPassword,
- form_manager_->GetMetricsRecorder()->GetUserAction());
-}
-
-// Tests that when submitted credentials are equal to already saved one then
-// pending credentials equal to saved match.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsAlreadySaved) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- submitted_form_.fields[kUsernameFieldIndex].value =
- saved_match_.username_value;
- submitted_form_.fields[kPasswordFieldIndex].value =
- saved_match_.password_value;
-
- // Tests that depending on whether we fill on page load or account select that
- // correct user action is recorded. Fill on account select is simulated by
- // pretending we are in incognito mode.
- for (bool is_incognito : {false, true}) {
- EXPECT_CALL(client_, IsIncognito).WillOnce(Return(is_incognito));
- form_manager_->Fill();
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- CheckPendingCredentials(/* expected */ saved_match_,
- form_manager_->GetPendingCredentials());
- EXPECT_EQ(is_incognito ? UserAction::kChoose : UserAction::kNone,
- form_manager_->GetMetricsRecorder()->GetUserAction());
- }
-}
-
-// Tests that when submitted credentials are equal to already saved PSL
-// credentials.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsPSLMatchSaved) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordForm expected = saved_match_;
-
- saved_match_.origin = GURL("https://m.accounts.google.com/auth");
- saved_match_.signon_realm = "https://m.accounts.google.com/";
- saved_match_.is_public_suffix_match = true;
-
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- submitted_form_.fields[kUsernameFieldIndex].value =
- saved_match_.username_value;
- submitted_form_.fields[kPasswordFieldIndex].value =
- saved_match_.password_value;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_EQ(UserAction::kChoosePslMatch,
- form_manager_->GetMetricsRecorder()->GetUserAction());
-}
-
-// Tests creating pending credentials when new credentials are different only in
-// password with already saved one.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsPasswordOverriden) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- PasswordForm expected = saved_match_;
- expected.password_value += ASCIIToUTF16("1");
-
- submitted_form_.fields[kUsernameFieldIndex].value =
- saved_match_.username_value;
- submitted_form_.fields[kPasswordFieldIndex].value = expected.password_value;
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_EQ(UserAction::kOverridePassword,
- form_manager_->GetMetricsRecorder()->GetUserAction());
-}
-
-// Tests that when submitted credentials are equal to already saved one then
-// pending credentials equal to saved match.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsUpdate) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- FormData submitted_form = observed_form_only_password_fields_;
- submitted_form.fields[0].value = ASCIIToUTF16("strongpassword");
- submitted_form.fields[1].value = ASCIIToUTF16("verystrongpassword");
-
- PasswordForm expected = saved_match_;
- expected.password_value = ASCIIToUTF16("verystrongpassword");
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_EQ(UserAction::kOverridePassword,
- form_manager_->GetMetricsRecorder()->GetUserAction());
-}
-
-// Tests creating pending credentials when a change password form is submitted
-// and there are multipe saved forms.
-TEST_F(NewPasswordFormManagerTest,
- CreatePendingCredentialsUpdateMultipleSaved) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordForm another_saved_match = saved_match_;
- another_saved_match.username_value += ASCIIToUTF16("1");
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_, &another_saved_match});
-
- FormData submitted_form = observed_form_only_password_fields_;
- submitted_form.fields[0].value = ASCIIToUTF16("strongpassword");
- submitted_form.fields[1].value = ASCIIToUTF16("verystrongpassword");
-
- PasswordForm expected = saved_match_;
- expected.password_value = ASCIIToUTF16("verystrongpassword");
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
-}
-
-// Tests creating pending credentials when the password field has an empty name.
-TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsEmptyName) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- FormData anonymous_signup = observed_form_;
- // There is an anonymous password field.
- anonymous_signup.fields[2].name.clear();
- anonymous_signup.fields[2].value = ASCIIToUTF16("a password");
- // Mark the password field as new-password.
- std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
- observed_form_, {std::make_pair(2, autofill::ACCOUNT_CREATION_PASSWORD)});
-
- form_manager_->ProcessServerPredictions(predictions);
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(anonymous_signup, &driver_, false));
- EXPECT_EQ(ASCIIToUTF16("a password"),
- form_manager_->GetPendingCredentials().password_value);
-}
-
-// Tests that there is no crash even when the observed form is a not password
-// form and the submitted form is password form.
-TEST_F(NewPasswordFormManagerTest, NoCrashOnNonPasswordForm) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- FormData form_without_password_fields = observed_form_;
- // Remove the password field.
- form_without_password_fields.fields.resize(kPasswordFieldIndex);
- CreateFormManager(form_without_password_fields);
- fetcher_->NotifyFetchCompleted();
-
- FormData submitted_form = observed_form_;
- submitted_form.fields[kUsernameFieldIndex].value = ASCIIToUTF16("username");
- submitted_form.fields[kPasswordFieldIndex].value = ASCIIToUTF16("password");
-
- // Expect no crash.
- form_manager_->ProvisionallySave(submitted_form, &driver_, false);
-}
-
-TEST_F(NewPasswordFormManagerTest, IsEqualToSubmittedForm) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- FormData submitted_form = observed_form_;
- submitted_form.fields[kUsernameFieldIndex].value =
- saved_match_.username_value;
- submitted_form.fields[kPasswordFieldIndex].value =
- saved_match_.password_value;
-
- // No submitted form yet.
- EXPECT_FALSE(form_manager_->IsEqualToSubmittedForm(submitted_form));
-
- ASSERT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
-
- observed_form_.unique_renderer_id += 10;
- observed_form_.fields.clear();
-
- EXPECT_TRUE(form_manager_->IsEqualToSubmittedForm(observed_form_));
-
- observed_form_.action = GURL("https://example.com");
- EXPECT_FALSE(form_manager_->IsEqualToSubmittedForm(observed_form_));
-}
-
-// Tests that when credentials with a new username (i.e. not saved yet) is
-// successfully submitted, then they are saved correctly.
-TEST_F(NewPasswordFormManagerTest, SaveNewCredentials) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- FormData submitted_form = observed_form_;
- base::string16 new_username = saved_match_.username_value + ASCIIToUTF16("1");
- base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
- submitted_form.fields[kUsernameFieldIndex].value = new_username;
- submitted_form.fields[kPasswordFieldIndex].value = new_password;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
- EXPECT_TRUE(form_manager_->IsNewLogin());
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm saved_form;
- std::vector<const PasswordForm*> best_matches;
- EXPECT_CALL(form_saver, Save(_, _, _))
- .WillOnce(DoAll(SaveArg<0>(&saved_form), SaveArg<1>(&best_matches)));
- EXPECT_CALL(client_, UpdateFormManagers());
-
- form_manager_->Save();
-
- std::string expected_signon_realm = submitted_form.url.GetOrigin().spec();
- EXPECT_EQ(submitted_form.url, saved_form.origin);
- EXPECT_EQ(expected_signon_realm, saved_form.signon_realm);
- EXPECT_EQ(new_username, saved_form.username_value);
- EXPECT_EQ(new_password, saved_form.password_value);
- EXPECT_TRUE(saved_form.preferred);
-
- EXPECT_EQ(submitted_form.fields[kUsernameFieldIndex].name,
- saved_form.username_element);
- EXPECT_EQ(submitted_form.fields[kPasswordFieldIndex].name,
- saved_form.password_element);
- EXPECT_EQ(std::vector<const PasswordForm*>{&saved_match_}, best_matches);
-
- // Check UKM metrics.
- form_manager_.reset();
- ExpectedGenerationUKM expected_metrics = {
- {} /* shown manually */,
- 0 /* password generated */,
- {} /* generated password is not modified */};
-
- CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
-}
-
-// Check that if there is saved PSL matched credentials with the same
-// username/password as in submitted form, then the saved form is the same
-// already saved only with origin and signon_realm from the submitted form.
-TEST_F(NewPasswordFormManagerTest, SavePSLToAlreadySaved) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&psl_saved_match_});
-
- FormData submitted_form = observed_form_;
- // Change
- submitted_form.fields[kUsernameFieldIndex].value =
- psl_saved_match_.username_value;
- submitted_form.fields[kPasswordFieldIndex].value =
- psl_saved_match_.password_value;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
- EXPECT_TRUE(form_manager_->IsNewLogin());
- EXPECT_TRUE(form_manager_->IsPendingCredentialsPublicSuffixMatch());
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm saved_form;
- std::vector<const PasswordForm*> best_matches;
- EXPECT_CALL(form_saver, Save(_, _, _))
- .WillOnce(DoAll(SaveArg<0>(&saved_form), SaveArg<1>(&best_matches)));
-
- form_manager_->Save();
-
- EXPECT_EQ(submitted_form.url, saved_form.origin);
- EXPECT_EQ(GetSignonRealm(submitted_form.url), saved_form.signon_realm);
- EXPECT_EQ(saved_form.username_value, psl_saved_match_.username_value);
- EXPECT_EQ(saved_form.password_value, psl_saved_match_.password_value);
- EXPECT_EQ(saved_form.username_element, psl_saved_match_.username_element);
- EXPECT_EQ(saved_form.password_element, psl_saved_match_.password_element);
-
- EXPECT_TRUE(saved_form.preferred);
-
- EXPECT_EQ(std::vector<const PasswordForm*>{&psl_saved_match_}, best_matches);
-}
-
-// Tests that when credentials with already saved username but with a new
-// password are submitted, then the saved password is updated.
-TEST_F(NewPasswordFormManagerTest, OverridePassword) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- FormData submitted_form = observed_form_;
- base::string16 username = saved_match_.username_value;
- base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
- submitted_form.fields[kUsernameFieldIndex].value = username;
- submitted_form.fields[kPasswordFieldIndex].value = new_password;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
- EXPECT_FALSE(form_manager_->IsNewLogin());
- EXPECT_TRUE(form_manager_->IsPasswordUpdate());
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm updated_form;
- EXPECT_CALL(form_saver, Update(_, ElementsAre(Pointee(saved_match_)),
- saved_match_.password_value))
- .WillOnce(SaveArg<0>(&updated_form));
-
- form_manager_->Save();
-
- EXPECT_TRUE(ArePasswordFormUniqueKeysEqual(saved_match_, updated_form));
- EXPECT_TRUE(updated_form.preferred);
- EXPECT_EQ(new_password, updated_form.password_value);
-}
-
-// Tests that when the user changes password on a change password form then the
-// saved password is updated.
-TEST_F(NewPasswordFormManagerTest, UpdatePasswordOnChangePasswordForm) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- CreateFormManager(observed_form_only_password_fields_);
- PasswordForm not_best_saved_match = saved_match_;
- not_best_saved_match.preferred = false;
- PasswordForm saved_match_another_username = saved_match_;
- saved_match_another_username.username_value += ASCIIToUTF16("1");
-
- SetNonFederatedAndNotifyFetchCompleted(
- {&saved_match_, &not_best_saved_match, &saved_match_another_username});
-
- FormData submitted_form = observed_form_only_password_fields_;
- submitted_form.fields[0].value = saved_match_.password_value;
- base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
- submitted_form.fields[1].value = new_password;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
- EXPECT_FALSE(form_manager_->IsNewLogin());
- EXPECT_TRUE(form_manager_->IsPasswordUpdate());
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm updated_form;
- EXPECT_CALL(form_saver,
- Update(_,
- UnorderedElementsAre(
- Pointee(saved_match_), Pointee(not_best_saved_match),
- Pointee(saved_match_another_username)),
- saved_match_.password_value))
- .WillOnce(SaveArg<0>(&updated_form));
-
- form_manager_->Save();
-
- EXPECT_TRUE(ArePasswordFormUniqueKeysEqual(saved_match_, updated_form));
- EXPECT_TRUE(updated_form.preferred);
- EXPECT_EQ(new_password, updated_form.password_value);
-}
-
-TEST_F(NewPasswordFormManagerTest, VotesUploadingOnPasswordUpdate) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- for (auto expected_vote :
- {autofill::NEW_PASSWORD, autofill::PROBABLY_NEW_PASSWORD,
- autofill::NOT_NEW_PASSWORD}) {
- SCOPED_TRACE(testing::Message("expected_vote=") << expected_vote);
- CreateFormManager(observed_form_only_password_fields_);
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- FormData submitted_form = observed_form_only_password_fields_;
- submitted_form.fields[0].value = saved_match_.password_value;
- auto new_password = saved_match_.password_value + ASCIIToUTF16("1");
- submitted_form.fields[1].value = new_password;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
-
- std::map<base::string16, autofill::ServerFieldType> expected_types;
- expected_types[ASCIIToUTF16("password")] = autofill::PASSWORD;
- expected_types[ASCIIToUTF16("password2")] = expected_vote;
-
- testing::InSequence in_sequence;
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(UploadedAutofillTypesAre(expected_types),
- false, _, _, true, nullptr));
- if (expected_vote == autofill::NEW_PASSWORD) {
- // An unrelated |FIRST_USE| vote.
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(_, _, _, _, _, _));
- }
-
- if (expected_vote == autofill::NEW_PASSWORD)
- form_manager_->Save();
- else if (expected_vote == autofill::PROBABLY_NEW_PASSWORD)
- form_manager_->OnNoInteraction(true /* is_update */);
- else
- form_manager_->OnNopeUpdateClicked();
- Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdateUsernameEmptyStore) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false);
-
- base::string16 new_username =
- parsed_submitted_form_.username_value + ASCIIToUTF16("1");
- PasswordForm expected = parsed_submitted_form_;
- expected.username_value = new_username;
- expected.username_element.clear();
-
- form_manager_->UpdateUsername(new_username);
-
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_TRUE(form_manager_->IsNewLogin());
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdateUsernameToAnotherFieldValue) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- base::string16 user_chosen_username = ASCIIToUTF16("user_chosen_username");
- base::string16 automatically_chosen_username =
- ASCIIToUTF16("automatically_chosen_username");
- submitted_form_.fields[0].value = user_chosen_username;
- submitted_form_.fields[1].value = automatically_chosen_username;
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false);
-
- EXPECT_EQ(automatically_chosen_username,
- form_manager_->GetPendingCredentials().username_value);
-
- form_manager_->UpdateUsername(user_chosen_username);
-
- EXPECT_EQ(user_chosen_username,
- form_manager_->GetPendingCredentials().username_value);
-
- FieldTypeMap expected_types = {
- {ASCIIToUTF16("firstname"), autofill::USERNAME},
- {ASCIIToUTF16("password"), autofill::PASSWORD}};
- VoteTypeMap expected_vote_types = {
- {ASCIIToUTF16("firstname"),
- AutofillUploadContents::Field::USERNAME_EDITED}};
- EXPECT_CALL(
- mock_autofill_download_manager_,
- StartUploadRequest(
- AllOf(UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
- _, Contains(autofill::USERNAME), _, _, nullptr));
- form_manager_->Save();
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdateUsernameToAlreadyExisting) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false);
-
- base::string16 new_username = saved_match_.username_value;
- base::string16 expected_password = parsed_submitted_form_.password_value;
- PasswordForm expected = saved_match_;
- expected.password_value = expected_password;
-
- form_manager_->UpdateUsername(new_username);
-
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_FALSE(form_manager_->IsNewLogin());
- EXPECT_TRUE(form_manager_->IsPasswordUpdate());
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdatePasswordValueEmptyStore) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false);
-
- base::string16 new_password =
- parsed_submitted_form_.password_value + ASCIIToUTF16("1");
- PasswordForm expected = parsed_submitted_form_;
- expected.password_value = new_password;
- expected.password_element.clear();
-
- form_manager_->UpdatePasswordValue(new_password);
-
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_TRUE(form_manager_->IsNewLogin());
-
- // TODO(https://crbug.com/928690): implement not sending incorrect votes and
- // check that StartUploadRequest is not called.
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(_, _, _, _, _, _))
- .Times(1);
- form_manager_->Save();
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdatePasswordValueToAlreadyExisting) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- // Emulate submitting form with known username and different password.
- submitted_form_.fields[kUsernameFieldIndex].value =
- saved_match_.username_value;
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false);
-
- // The user changes password to already saved one.
- base::string16 password = saved_match_.password_value;
- form_manager_->UpdatePasswordValue(password);
-
- CheckPendingCredentials(saved_match_, form_manager_->GetPendingCredentials());
- EXPECT_FALSE(form_manager_->IsNewLogin());
- EXPECT_FALSE(form_manager_->IsPasswordUpdate());
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdatePasswordValueMultiplePasswordFields) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- FormData form = observed_form_only_password_fields_;
-
- CreateFormManager(form);
- fetcher_->NotifyFetchCompleted();
- base::string16 password = ASCIIToUTF16("password1");
- base::string16 pin = ASCIIToUTF16("pin");
- form.fields[0].value = password;
- form.fields[1].value = pin;
- form_manager_->ProvisionallySave(form, &driver_, false);
-
- // Check that a second password field is chosen for saving.
- EXPECT_EQ(pin, form_manager_->GetPendingCredentials().password_value);
-
- PasswordForm expected = form_manager_->GetPendingCredentials();
- expected.password_value = password;
- expected.password_element = form.fields[0].name;
-
- // Simulate that the user updates value to save for the first password field.
- form_manager_->UpdatePasswordValue(password);
-
- // Check that newly created pending credentials are correct.
- CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
- EXPECT_TRUE(form_manager_->IsNewLogin());
-
- // Check that a vote is sent for the field with the value which is chosen by
- // the user.
- std::map<base::string16, ServerFieldType> expected_types;
- expected_types[expected.password_element] = autofill::PASSWORD;
-
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(UploadedAutofillTypesAre(expected_types),
- false, _, _, true, nullptr));
-
- // Check that the password which was chosen by the user is saved.
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
-
- form_manager_->Save();
- CheckPendingCredentials(expected, saved_form);
-}
-
-TEST_F(NewPasswordFormManagerTest, PermanentlyBlacklist) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- PasswordForm actual_blacklisted_form =
- password_manager_util::MakeNormalizedBlacklistedForm(
- PasswordStore::FormDigest(observed_form_));
- EXPECT_CALL(form_saver,
- PermanentlyBlacklist(PasswordStore::FormDigest(observed_form_)))
- .WillOnce(Return(actual_blacklisted_form));
-
- form_manager_->PermanentlyBlacklist();
- EXPECT_THAT(form_manager_->GetBlacklistedMatches(),
- ElementsAre(Pointee(actual_blacklisted_form)));
-}
-
-TEST_F(NewPasswordFormManagerTest, Clone) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
-
- // Provisionally save in order to create pending credentials.
- ASSERT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
-
- std::unique_ptr<NewPasswordFormManager> cloned_manager =
- form_manager_->Clone();
-
- EXPECT_TRUE(cloned_manager->DoesManage(observed_form_, nullptr));
- EXPECT_TRUE(cloned_manager->GetFormFetcher());
- // Check that |form_fetcher| was cloned.
- EXPECT_NE(form_manager_->GetFormFetcher(), cloned_manager->GetFormFetcher());
-
- EXPECT_EQ(form_manager_->metrics_recorder(),
- cloned_manager->metrics_recorder());
-
- EXPECT_EQ(form_manager_->GetPendingCredentials(),
- cloned_manager->GetPendingCredentials());
- ASSERT_TRUE(cloned_manager->GetSubmittedForm());
- EXPECT_EQ(*form_manager_->GetSubmittedForm(),
- *cloned_manager->GetSubmittedForm());
- EXPECT_TRUE(cloned_manager->is_submitted());
-}
-
-// Extracts the information whether parsing was successful from a metric
-// specified by |metric_name| stored in |entry|. The metric name should be one
-// of ukm::builders::PasswordForm::kReadonlyWhenSavingName and
-// ukm::builders::PasswordForm::kReadonlyWhenFillingName.
-bool ParsingSuccessReported(const ukm::mojom::UkmEntry* entry,
- base::StringPiece metric_name) {
- const int64_t* value =
- ukm::TestUkmRecorder::GetEntryMetric(entry, metric_name);
- EXPECT_TRUE(value);
- // Ideally, an ASSERT_TRUE above would prevent the test suite from crashing on
- // dereferencing |value| below. But ASSERT_* is not available in non-void
- // returning functions, so the null value is handled explicitly.
- if (!value)
- return false; // Value does not matter, the test already failed.
- return 1 == (1 & *value);
-}
-
-// Test that an attempt to log to ReadonlyWhenFilling UKM is made when filling.
-TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenFilling) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- EXPECT_CALL(driver_, FillPasswordForm(_));
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- task_runner_->FastForwardUntilNoTasksRemain();
-
- // Destroy the form manager to destroy the UKM recorder it owns. The recorder
- // only records metrics in its destructor.
- form_manager_.reset();
-
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(1u, entries.size());
-
- EXPECT_TRUE(ParsingSuccessReported(
- entries[0], ukm::builders::PasswordForm::kReadonlyWhenFillingName));
-}
-
-// Test that an attempt to log to ReadonlyWhenFilling UKM is made when filling,
-// even when the parsing itself is unsuccessful.
-TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenFilling_ParsingFailed) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- FormData malformed_form = observed_form_;
- malformed_form.fields.clear();
- CreateFormManager(malformed_form);
- // Only create the recorder after the current form manager is created,
- // otherwise the destruction of the previous one will add unwanted UKM entries
- // in it.
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- task_runner_->FastForwardUntilNoTasksRemain();
-
- // Destroy the form manager to destroy the UKM recorder it owns. The recorder
- // only records metrics in its destructor.
- form_manager_.reset();
-
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(1u, entries.size());
-
- EXPECT_FALSE(ParsingSuccessReported(
- entries[0], ukm::builders::PasswordForm::kReadonlyWhenFillingName));
-}
-
-// Test that an attempt to log to ReadonlyWhenSaving UKM is made when creating
-// pending credentials.
-TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenSaving) {
- // The scoped context is needed for the UKM recorder.
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
-
- // Destroy the form manager to destroy the UKM recorder it owns. The recorder
- // only records metrics in its destructor.
- form_manager_.reset();
-
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(1u, entries.size());
-
- EXPECT_TRUE(ParsingSuccessReported(
- entries[0], ukm::builders::PasswordForm::kReadonlyWhenSavingName));
-}
-
-// Test that an attempt to log to ReadonlyWhenSaving UKM is made when creating
-// pending credentials, even when their parsing itself is unsuccessful.
-TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenSaving_ParsingFailed) {
- // The scoped context is needed for the UKM recorder.
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- FormData malformed_form = submitted_form_;
- malformed_form.fields.clear();
- EXPECT_FALSE(
- form_manager_->ProvisionallySave(malformed_form, &driver_, false));
-
- // Destroy the form manager to destroy the UKM recorder it owns. The recorder
- // only records metrics in its destructor.
- form_manager_.reset();
-
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(1u, entries.size());
-
- EXPECT_FALSE(ParsingSuccessReported(
- entries[0], ukm::builders::PasswordForm::kReadonlyWhenSavingName));
-}
-
-TEST_F(NewPasswordFormManagerTest, PresaveGeneratedPasswordEmptyStore) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- fetcher_->NotifyFetchCompleted();
-
- EXPECT_FALSE(form_manager_->HasGeneratedPassword());
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- form_manager_->SetGenerationPopupWasShown(
- true /* generation_popup_was_shown */, false /* is_manual_generation */);
-
- // Check that the generated password is presaved.
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, IsEmpty(), base::string16()))
- .WillOnce(SaveArg<0>(&saved_form));
-
- PasswordForm form_with_generated_password = parsed_submitted_form_;
- FormData& form_data = form_with_generated_password.form_data;
- form_manager_->PresaveGeneratedPassword(form_with_generated_password);
-
- EXPECT_TRUE(form_manager_->HasGeneratedPassword());
- EXPECT_EQ(saved_form.username_value,
- form_data.fields[kUsernameFieldIndex].value);
- EXPECT_EQ(saved_form.password_value,
- form_data.fields[kPasswordFieldIndex].value);
-
- Mock::VerifyAndClearExpectations(&form_saver);
-
- // Check that when the generated password is edited, then it's presaved.
- form_with_generated_password.password_value += ASCIIToUTF16("1");
- form_data.fields[kPasswordFieldIndex].value =
- form_with_generated_password.password_value;
- EXPECT_CALL(form_saver,
- UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
- FormHasUniqueKey(form_with_generated_password)))
- .WillOnce(SaveArg<0>(&saved_form));
-
- form_manager_->PresaveGeneratedPassword(form_with_generated_password);
-
- EXPECT_TRUE(form_manager_->HasGeneratedPassword());
- EXPECT_EQ(saved_form.username_value,
- form_data.fields[kUsernameFieldIndex].value);
- EXPECT_EQ(saved_form.password_value,
- form_with_generated_password.password_value);
-
- Mock::VerifyAndClearExpectations(&form_saver);
-
- // Check UKM metrics.
- form_manager_.reset();
- ExpectedGenerationUKM expected_metrics = {
- base::make_optional(1u) /* shown automatically */,
- 1 /* password generated */,
- base::make_optional(1u) /* password modified */};
-
- CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
-}
-
-TEST_F(NewPasswordFormManagerTest, PresaveGenerated_ModifiedUsername) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- fetcher_->NotifyFetchCompleted();
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- form_manager_->SetGenerationPopupWasShown(
- true /* generation_popup_was_shown */, false /* is_manual_generation */);
-
- // Check that the generated password is presaved.
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
- PasswordForm form_with_generated_password = parsed_submitted_form_;
- FormData& form_data = form_with_generated_password.form_data;
- form_manager_->PresaveGeneratedPassword(form_with_generated_password);
- Mock::VerifyAndClearExpectations(&form_saver);
-
- // Check that when the username is edited, then it's presaved.
- form_with_generated_password.username_value += ASCIIToUTF16("1");
- form_data.fields[kUsernameFieldIndex].value =
- form_with_generated_password.username_value;
-
- EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
- FormHasUniqueKey(saved_form)))
- .WillOnce(SaveArg<0>(&saved_form));
- form_manager_->PresaveGeneratedPassword(form_with_generated_password);
-
- EXPECT_TRUE(form_manager_->HasGeneratedPassword());
- EXPECT_EQ(saved_form.username_value,
- form_with_generated_password.username_value);
- EXPECT_EQ(saved_form.password_value,
- form_with_generated_password.password_value);
-
- // Check UKM metrics.
- form_manager_.reset();
- ExpectedGenerationUKM expected_metrics = {
- base::make_optional(1u) /* shown automatically */,
- 1 /* password generated */,
- base::make_optional(0u) /* password modified */};
-
- CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
-}
-
-TEST_F(NewPasswordFormManagerTest, GeneratedPasswordWhichIsNotInFormData) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- // Create a password form such that |form_data| do not contain the generated
- // password.
- PasswordForm form_with_generated_password;
- form_with_generated_password.form_data = submitted_form_;
- const base::string16 generated_password = ASCIIToUTF16("gen_pw");
- // |password_value| should contain the generated password.
- form_with_generated_password.password_value = generated_password;
-
- // Check that the generated password is presaved.
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
-
- form_manager_->PresaveGeneratedPassword(form_with_generated_password);
- EXPECT_EQ(submitted_form_.fields[kUsernameFieldIndex].value,
- saved_form.username_value);
- EXPECT_EQ(generated_password, saved_form.password_value);
- EXPECT_TRUE(form_manager_->HasGeneratedPassword());
-
- // Check that the generated password is saved.
- EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
- FormHasUniqueKey(saved_form)))
- .WillOnce(SaveArg<0>(&saved_form));
- EXPECT_CALL(client_, UpdateFormManagers());
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
- form_manager_->Save();
-
- EXPECT_EQ(submitted_form_.fields[kUsernameFieldIndex].value,
- saved_form.username_value);
- EXPECT_EQ(generated_password, saved_form.password_value);
-}
-
-TEST_F(NewPasswordFormManagerTest, PresaveGenerationWhenParsingFails) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- // Create a password form with empty |form_data|. On this form the form parser
- // should fail.
- PasswordForm form_with_empty_form_data;
- const base::string16 generated_password = ASCIIToUTF16("gen_pw");
- form_with_empty_form_data.password_value = generated_password;
-
- // Check that nevertheless the generated password is presaved.
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, IsEmpty(), base::string16()))
- .WillOnce(SaveArg<0>(&saved_form));
- form_manager_->PresaveGeneratedPassword(form_with_empty_form_data);
- EXPECT_EQ(generated_password, saved_form.password_value);
-}
-
-TEST_F(NewPasswordFormManagerTest, PasswordNoLongerGenerated) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- fetcher_->NotifyFetchCompleted();
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- form_manager_->SetGenerationPopupWasShown(
- true /* generation_popup_was_shown */, true /* is_manual_generation */);
-
- EXPECT_CALL(form_saver, Save(_, _, _));
-
- PasswordForm form = parsed_submitted_form_;
- form_manager_->PresaveGeneratedPassword(form);
- Mock::VerifyAndClearExpectations(&form_saver);
-
- EXPECT_TRUE(form_manager_->HasGeneratedPassword());
-
- // Check when the user removes the generated password on the page, it is
- // removed from the store.
- EXPECT_CALL(form_saver, Remove(_));
- form_manager_->PasswordNoLongerGenerated();
-
- EXPECT_FALSE(form_manager_->HasGeneratedPassword());
-
- // Check UKM metrics.
- form_manager_.reset();
- ExpectedGenerationUKM expected_metrics = {
- base::make_optional(2u) /* shown manually */,
- 0 /* password generated */,
- {} /* generated password is not modified */};
-
- CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
-}
-
-TEST_F(NewPasswordFormManagerTest, PresaveGeneratedPasswordExistingCredential) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- form_manager_->SetGenerationPopupWasShown(
- true /* generation_popup_was_shown */, false /* is_manual_generation */);
-
- // Check that the generated password is presaved.
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
-
- PasswordForm form_with_generated_password = parsed_submitted_form_;
- FormData& form_data = form_with_generated_password.form_data;
-
- // Check that the generated password is saved with the empty username when
- // there is already a saved credetial with the same username.
- form_data.fields[kUsernameFieldIndex].value = saved_match_.username_value;
- form_manager_->PresaveGeneratedPassword(form_with_generated_password);
-
- EXPECT_TRUE(form_manager_->HasGeneratedPassword());
- EXPECT_TRUE(saved_form.username_value.empty());
- EXPECT_EQ(form_with_generated_password.password_value,
- saved_form.password_value);
-}
-
-TEST_F(NewPasswordFormManagerTest, UserEventsForGeneration) {
- using GeneratedPasswordStatus =
- PasswordFormMetricsRecorder::GeneratedPasswordStatus;
-
- PasswordForm submitted_form(parsed_observed_form_);
- submitted_form.form_data = submitted_form_;
- FormData& form_data = submitted_form.form_data;
-
- { // User accepts a generated password.
- base::HistogramTester histogram_tester;
- CreateFormManager(observed_form_);
- form_manager_->PresaveGeneratedPassword(submitted_form);
- form_manager_.reset();
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.UserDecision",
- GeneratedPasswordStatus::kPasswordAccepted, 1);
- }
-
- { // User edits the generated password.
- base::HistogramTester histogram_tester;
- CreateFormManager(observed_form_);
- form_manager_->PresaveGeneratedPassword(submitted_form);
- form_data.fields[kPasswordFieldIndex].value += ASCIIToUTF16("1");
- submitted_form.password_value = form_data.fields[kPasswordFieldIndex].value;
- form_manager_->PresaveGeneratedPassword(submitted_form);
- form_manager_.reset();
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.UserDecision",
- GeneratedPasswordStatus::kPasswordEdited, 1);
- }
-
- { // User clears the generated password.
- base::HistogramTester histogram_tester;
- CreateFormManager(observed_form_);
- form_manager_->PresaveGeneratedPassword(submitted_form);
- form_data.fields[kPasswordFieldIndex].value += ASCIIToUTF16("2");
- submitted_form.password_value = form_data.fields[kPasswordFieldIndex].value;
- form_manager_->PresaveGeneratedPassword(submitted_form);
- form_manager_->PasswordNoLongerGenerated();
- form_manager_.reset();
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.UserDecision",
- GeneratedPasswordStatus::kPasswordDeleted, 1);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, FillForm) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- for (bool observed_form_changed : {false, true}) {
- SCOPED_TRACE(testing::Message("observed_form_changed=")
- << observed_form_changed);
- CreateFormManager(observed_form_);
- EXPECT_CALL(driver_, FillPasswordForm(_));
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- task_runner_->FastForwardUntilNoTasksRemain();
- Mock::VerifyAndClearExpectations(&driver_);
-
- FormData form = observed_form_;
-
- if (observed_form_changed) {
- form.fields[kUsernameFieldIndex].unique_renderer_id += 1000;
- form.fields[kUsernameFieldIndex].name += ASCIIToUTF16("1");
- form.fields[kUsernameFieldIndex].id_attribute += ASCIIToUTF16("1");
-#if defined(OS_IOS)
- form.fields[kUsernameFieldIndex].unique_id += ASCIIToUTF16("1");
-#endif
- form.fields[kPasswordFieldIndex].unique_renderer_id += 1000;
- }
-
- PasswordFormFillData fill_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
- form_manager_->FillForm(form);
-
- EXPECT_EQ(form.fields[kUsernameFieldIndex].name,
- fill_data.username_field.name);
- EXPECT_EQ(form.fields[kUsernameFieldIndex].unique_renderer_id,
- fill_data.username_field.unique_renderer_id);
- EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
- EXPECT_EQ(form.fields[kPasswordFieldIndex].name,
- fill_data.password_field.name);
- EXPECT_EQ(form.fields[kPasswordFieldIndex].unique_renderer_id,
- fill_data.password_field.unique_renderer_id);
- EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
-
- base::HistogramTester histogram_tester;
- form_manager_.reset();
- uint32_t expected_differences_mask = 0;
- if (observed_form_changed)
- expected_differences_mask = 2; // renderer_id changes.
- histogram_tester.ExpectUniqueSample("PasswordManager.DynamicFormChanges",
- expected_differences_mask, 1);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, FillFormWaitForServerPredictions) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- FormData changed_form = observed_form_;
-
- changed_form.fields[kUsernameFieldIndex].unique_renderer_id += 1000;
- changed_form.fields[kPasswordFieldIndex].unique_renderer_id += 1000;
-
- // Check that no filling until server predicions or filling timeout
- // expiration.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- form_manager_->FillForm(changed_form);
- Mock::VerifyAndClearExpectations(&driver_);
-
- // Check that the changed form is filled after the filling timeout expires.
-
- PasswordFormFillData fill_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
-
- task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_EQ(changed_form.fields[kUsernameFieldIndex].unique_renderer_id,
- fill_data.username_field.unique_renderer_id);
- EXPECT_EQ(changed_form.fields[kPasswordFieldIndex].unique_renderer_id,
- fill_data.password_field.unique_renderer_id);
-
- base::HistogramTester histogram_tester;
- form_manager_.reset();
- uint32_t expected_differences_mask = 2; // renderer_id changes.
- histogram_tester.ExpectUniqueSample("PasswordManager.DynamicFormChanges",
- expected_differences_mask, 1);
-}
-
-TEST_F(NewPasswordFormManagerTest, Update) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- PasswordForm not_best_saved_match = saved_match_;
- not_best_saved_match.preferred = false;
- PasswordForm saved_match_another_username = saved_match_;
- saved_match_another_username.username_value += ASCIIToUTF16("1");
- SetNonFederatedAndNotifyFetchCompleted(
- {&saved_match_, &saved_match_another_username});
-
- FormData submitted_form = observed_form_;
- base::string16 username = saved_match_.username_value;
- base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
- submitted_form.fields[kUsernameFieldIndex].value = username;
- submitted_form.fields[kPasswordFieldIndex].value = new_password;
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form, &driver_, false));
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm updated_form;
- EXPECT_CALL(form_saver, Update(_,
- UnorderedElementsAre(
- Pointee(saved_match_),
- Pointee(saved_match_another_username)),
- saved_match_.password_value))
- .WillOnce(SaveArg<0>(&updated_form));
- EXPECT_CALL(client_, UpdateFormManagers());
-
- form_manager_->Update(saved_match_);
-
- EXPECT_TRUE(ArePasswordFormUniqueKeysEqual(saved_match_, updated_form));
- EXPECT_TRUE(updated_form.preferred);
- EXPECT_EQ(new_password, updated_form.password_value);
-}
-
-// TODO(https://crbug.com/918846): implement FillingAssistance metric on iOS.
-#if defined(OS_IOS)
-#define MAYBE_FillingAssistanceMetric DISABLED_FillingAssistanceMetric
-#else
-#define MAYBE_FillingAssistanceMetric FillingAssistanceMetric
-#endif
-TEST_F(NewPasswordFormManagerTest, MAYBE_FillingAssistanceMetric) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-
- // Simulate that the user fills the saved credentials manually.
- submitted_form_.fields[kUsernameFieldIndex].value =
- saved_match_.username_value;
- submitted_form_.fields[kUsernameFieldIndex].properties_mask =
- FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER;
- submitted_form_.fields[kPasswordFieldIndex].value =
- saved_match_.password_value;
- submitted_form_.fields[kPasswordFieldIndex].properties_mask =
- FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER;
-
- base::HistogramTester histogram_tester;
- // Simulate successful submission.
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false);
- form_manager_->GetMetricsRecorder()->LogSubmitPassed();
-
- form_manager_.reset();
- histogram_tester.ExpectUniqueSample(
- "PasswordManager.FillingAssistance",
- PasswordFormMetricsRecorder::FillingAssistance::kManual, 1);
-}
-
-TEST_F(NewPasswordFormManagerTest, PasswordRevealedVote) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- for (bool password_revealed : {false, true}) {
- SCOPED_TRACE(testing::Message("password_revealed=") << password_revealed);
- CreateFormManager(observed_form_);
- fetcher_->NotifyFetchCompleted();
-
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
-
- if (password_revealed)
- form_manager_->OnPasswordsRevealed();
-
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(PasswordsWereRevealed(password_revealed),
- false, _, _, true, nullptr));
- form_manager_->Save();
- Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, GenerationUploadOnNoInteraction) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- for (bool generation_popup_shown : {false, true}) {
- SCOPED_TRACE(testing::Message("generation_popup_shown=")
- << generation_popup_shown);
- CreateFormManager(observed_form_);
- fetcher_->NotifyFetchCompleted();
-
- if (generation_popup_shown) {
- form_manager_->SetGenerationElement(ASCIIToUTF16("password"));
- form_manager_->SetGenerationPopupWasShown(
- true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
- }
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
-
- EXPECT_CALL(
- mock_autofill_download_manager_,
- StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr))
- .Times(generation_popup_shown ? 1 : 0);
- form_manager_->OnNoInteraction(false /*is_update */);
- Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, GenerationUploadOnNeverClicked) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- for (bool generation_popup_shown : {false, true}) {
- SCOPED_TRACE(testing::Message("generation_popup_shown=")
- << generation_popup_shown);
- CreateFormManager(observed_form_);
- fetcher_->NotifyFetchCompleted();
-
- if (generation_popup_shown) {
- form_manager_->SetGenerationElement(ASCIIToUTF16("password"));
- form_manager_->SetGenerationPopupWasShown(
- true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
- }
- EXPECT_TRUE(
- form_manager_->ProvisionallySave(submitted_form_, &driver_, false));
-
- EXPECT_CALL(
- mock_autofill_download_manager_,
- StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr))
- .Times(generation_popup_shown ? 1 : 0);
- form_manager_->OnNeverClicked();
- Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, SaveHttpAuthNoHttpAuthStored) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-
- for (bool html_credentials_saved : {false, true}) {
- SCOPED_TRACE(testing::Message("html_credentials_saved=")
- << html_credentials_saved);
- PasswordForm http_auth_form = parsed_observed_form_;
- http_auth_form.scheme = PasswordForm::Scheme::kBasic;
-
- // Check that no filling because no http auth credentials are stored.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- EXPECT_CALL(client_, AutofillHttpAuth(_, _)).Times(0);
-
- CreateFormManagerForNonWebForm(http_auth_form);
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- std::vector<const PasswordForm*> saved_matches;
- if (html_credentials_saved)
- saved_matches.push_back(&saved_match_);
- SetNonFederatedAndNotifyFetchCompleted(saved_matches);
-
- base::string16 username = ASCIIToUTF16("user1");
- base::string16 password = ASCIIToUTF16("pass1");
- http_auth_form.username_value = username;
- http_auth_form.password_value = password;
-
- // Check that submitted credentials are saved.
- ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthForm(http_auth_form));
- EXPECT_TRUE(form_manager_->IsNewLogin());
-
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
- form_manager_->Save();
-
- EXPECT_EQ(http_auth_form.signon_realm, saved_form.signon_realm);
- EXPECT_EQ(username, saved_form.username_value);
- EXPECT_EQ(password, saved_form.password_value);
- }
-}
-
-TEST_F(NewPasswordFormManagerTest, HTTPAuthAlreadySaved) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordForm http_auth_form = parsed_observed_form_;
- http_auth_form.scheme = PasswordForm::Scheme::kBasic;
-
- CreateFormManagerForNonWebForm(http_auth_form);
-
- const base::string16 username = ASCIIToUTF16("user1");
- const base::string16 password = ASCIIToUTF16("pass1");
- http_auth_form.username_value = username;
- http_auth_form.password_value = password;
- EXPECT_CALL(client_, AutofillHttpAuth(http_auth_form, _)).Times(1);
- SetNonFederatedAndNotifyFetchCompleted({&http_auth_form});
-
- // Check that if known credentials are submitted, then |form_manager_| is not
- // in state new login nor password overridden.
- ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthForm(http_auth_form));
- EXPECT_FALSE(form_manager_->IsNewLogin());
- EXPECT_FALSE(form_manager_->IsPasswordUpdate());
-}
-
-TEST_F(NewPasswordFormManagerTest, HTTPAuthPasswordOverridden) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordForm http_auth_form = parsed_observed_form_;
- http_auth_form.scheme = PasswordForm::Scheme::kBasic;
-
- CreateFormManagerForNonWebForm(http_auth_form);
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- PasswordForm saved_http_auth_form = http_auth_form;
- const base::string16 username = ASCIIToUTF16("user1");
- const base::string16 password = ASCIIToUTF16("pass1");
- saved_http_auth_form.username_value = username;
- saved_http_auth_form.password_value = password;
- EXPECT_CALL(client_, AutofillHttpAuth(saved_http_auth_form, _)).Times(1);
- SetNonFederatedAndNotifyFetchCompleted({&saved_http_auth_form});
-
- // Check that if new password is submitted, then |form_manager_| is in state
- // password overridden.
- PasswordForm submitted_http_auth_form = saved_http_auth_form;
- base::string16 new_password = password + ASCIIToUTF16("1");
- submitted_http_auth_form.password_value = new_password;
- ASSERT_TRUE(
- form_manager_->ProvisionallySaveHttpAuthForm(submitted_http_auth_form));
- EXPECT_FALSE(form_manager_->IsNewLogin());
- EXPECT_TRUE(form_manager_->IsPasswordUpdate());
-
- // Check that the password is updated in the stored credential.
- PasswordForm updated_form;
- EXPECT_CALL(form_saver,
- Update(_, ElementsAre(Pointee(saved_http_auth_form)), password))
- .WillOnce(SaveArg<0>(&updated_form));
-
- form_manager_->Save();
-
- EXPECT_TRUE(
- ArePasswordFormUniqueKeysEqual(saved_http_auth_form, updated_form));
- EXPECT_EQ(new_password, updated_form.password_value);
-}
-
-TEST_F(NewPasswordFormManagerTest, BlacklistHttpAuthCredentials) {
- PasswordForm http_auth_form = parsed_observed_form_;
- http_auth_form.signon_realm += "my-auth-realm";
- http_auth_form.scheme = PasswordForm::Scheme::kBasic;
-
- CreateFormManagerForNonWebForm(http_auth_form);
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- // Simulate that the user submits http auth credentials.
- http_auth_form.username_value = ASCIIToUTF16("user1");
- http_auth_form.password_value = ASCIIToUTF16("pass1");
- ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthForm(http_auth_form));
-
- // Simulate that the user clicks never.
- PasswordForm blacklisted_form;
- EXPECT_CALL(form_saver,
- PermanentlyBlacklist(PasswordStore::FormDigest(http_auth_form)));
- form_manager_->OnNeverClicked();
-}
-
-#if defined(OS_IOS)
-TEST_F(NewPasswordFormManagerTest, iOSPresavedGeneratedPassword) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- FormData form_to_presave = observed_form_;
- const base::string16 typed_username = ASCIIToUTF16("user1");
- FormFieldData& username_field = form_to_presave.fields[kUsernameFieldIndex];
- FormFieldData& password_field = form_to_presave.fields[kPasswordFieldIndex];
- username_field.value = typed_username;
- password_field.value = ASCIIToUTF16("not_password");
- // Use |generated_password| different from value in field to test that the
- // generated password is saved.
- const base::string16 generated_password = ASCIIToUTF16("gen_pw");
- // Use different |unique_id| and |name| to test that |unique_id| is taken.
- password_field.unique_id = password_field.name + ASCIIToUTF16("1");
- const base::string16 generation_element = password_field.unique_id;
-
- PasswordForm saved_form;
- EXPECT_CALL(form_saver, Save(_, IsEmpty(), base::string16()))
- .WillOnce(SaveArg<0>(&saved_form));
- form_manager_->PresaveGeneratedPassword(
- &driver_, form_to_presave, generated_password, generation_element);
- EXPECT_EQ(generated_password, saved_form.password_value);
-
- Mock::VerifyAndClearExpectations(&form_saver);
-
- const base::string16 changed_password =
- generated_password + ASCIIToUTF16("1");
- EXPECT_CALL(form_saver, UpdateReplace(_, _, base::string16(), _))
- .WillOnce(SaveArg<0>(&saved_form));
-
- form_manager_->UpdateGeneratedPasswordOnUserInput(
- form_to_presave.name, generation_element, changed_password);
- EXPECT_EQ(username_field.value, saved_form.username_value);
- EXPECT_EQ(changed_password, saved_form.password_value);
-}
-
-TEST_F(NewPasswordFormManagerTest, UpdateGeneratedPasswordBeforePresaving) {
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- fetcher_->NotifyFetchCompleted();
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-
- FormData form_to_presave = observed_form_;
- const base::string16 generation_element =
- form_to_presave.fields[kPasswordFieldIndex].unique_id;
- const base::string16 generation_field_value = ASCIIToUTF16("some_password");
-
- // Check that nothing is saved on changing password, in case when there was no
- // pre-saving.
- EXPECT_CALL(form_saver, Save(_, _, _)).Times(0);
- form_manager_->UpdateGeneratedPasswordOnUserInput(
- form_to_presave.name, generation_element, generation_field_value);
-}
-
-#endif // defined(OS_IOS)
-
-} // namespace
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc
index 67362c008c5..b3a76599b7c 100644
--- a/chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -14,7 +14,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
@@ -194,7 +194,7 @@ class PasswordAutofillManagerTest : public testing::Test {
// The TestAutofillDriver uses a SequencedWorkerPool which expects the
// existence of a MessageLoop.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(PasswordAutofillManagerTest, FillSuggestion) {
diff --git a/chromium/components/password_manager/core/browser/password_form_filling.cc b/chromium/components/password_manager/core/browser/password_form_filling.cc
index 02531a90082..9652bf00fd4 100644
--- a/chromium/components/password_manager/core/browser/password_form_filling.cc
+++ b/chromium/components/password_manager/core/browser/password_form_filling.cc
@@ -105,7 +105,6 @@ void ShowInitialPasswordAccountSuggestions(
LikelyFormFilling SendFillInformationToRenderer(
PasswordManagerClient* client,
PasswordManagerDriver* driver,
- bool is_blacklisted,
const PasswordForm& observed_form,
const std::map<base::string16, const PasswordForm*>& best_matches,
const std::vector<const PasswordForm*>& federated_matches,
@@ -114,9 +113,6 @@ LikelyFormFilling SendFillInformationToRenderer(
DCHECK(driver);
DCHECK_EQ(PasswordForm::Scheme::kHtml, observed_form.scheme);
- const bool new_parsing_enabled =
- base::FeatureList::IsEnabled(features::kNewPasswordFormParsing);
-
if (best_matches.empty()) {
driver->InformNoSavedCredentials();
metrics_recorder->RecordFillEvent(
@@ -125,23 +121,12 @@ LikelyFormFilling SendFillInformationToRenderer(
}
DCHECK(preferred_match);
- // Chrome tries to avoid filling into fields where the user is asked to enter
- // a fresh password. The old condition for filling on load was: "does the
- // form lack a new-password field?" The new one is: "does the form have a
- // current-password field?" because the current-password field is what should
- // be filled. The old condition is used with the old parser, and the new
- // condition with the new one. The new one is not explicitly checked here,
- // because it is implicit in the way filling is done: if there is no current
- // password field ID, then PasswordAutofillAgent has no way to fill the
- // password anywhere.
- const bool form_good_for_filling =
- new_parsing_enabled || !observed_form.IsPossibleChangePasswordForm();
-
- // If the parser of the NewPasswordFormManager decides that there is no
+ // If the parser of the PasswordFormManager decides that there is no
// current password field, no filling attempt will be made. In this case the
// renderer won't treat this as the "first filling" and won't record metrics
// accordingly. The browser should not do that either.
- const bool no_sign_in_form = !observed_form.HasPasswordElement();
+ const bool no_sign_in_form =
+ !observed_form.HasPasswordElement() && !observed_form.IsSingleUsername();
// Wait for the username before filling passwords in case the
// FillOnAccountSelectHttp feature is active and the main frame is
@@ -166,8 +151,6 @@ LikelyFormFilling SendFillInformationToRenderer(
wait_for_username_reason = WaitForUsernameReason::kIncognitoMode;
} else if (preferred_match->is_public_suffix_match) {
wait_for_username_reason = WaitForUsernameReason::kPublicSuffixMatch;
- } else if (!form_good_for_filling) {
- wait_for_username_reason = WaitForUsernameReason::kFormNotGoodForFilling;
} else if (no_sign_in_form) {
// If the parser did not find a current password element, don't fill.
wait_for_username_reason = WaitForUsernameReason::kFormNotGoodForFilling;
diff --git a/chromium/components/password_manager/core/browser/password_form_filling.h b/chromium/components/password_manager/core/browser/password_form_filling.h
index 87647ebd1f7..6a1eaae0886 100644
--- a/chromium/components/password_manager/core/browser/password_form_filling.h
+++ b/chromium/components/password_manager/core/browser/password_form_filling.h
@@ -42,7 +42,6 @@ enum class LikelyFormFilling {
LikelyFormFilling SendFillInformationToRenderer(
PasswordManagerClient* client,
PasswordManagerDriver* driver,
- bool is_blacklisted,
const autofill::PasswordForm& observed_form,
const std::map<base::string16, const autofill::PasswordForm*>& best_matches,
const std::vector<const autofill::PasswordForm*>& federated_matches,
diff --git a/chromium/components/password_manager/core/browser/password_form_filling_unittest.cc b/chromium/components/password_manager/core/browser/password_form_filling_unittest.cc
index f13c77781aa..ad42e2ce703 100644
--- a/chromium/components/password_manager/core/browser/password_form_filling_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -63,7 +63,9 @@ class PasswordFormFillingTest : public testing::Test {
observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
observed_form_.action = GURL("http://accounts.google.com/a/Login");
observed_form_.username_element = ASCIIToUTF16("Email");
+ observed_form_.username_element_renderer_id = 100;
observed_form_.password_element = ASCIIToUTF16("Passwd");
+ observed_form_.password_element_renderer_id = 101;
observed_form_.submit_element = ASCIIToUTF16("signIn");
observed_form_.signon_realm = "http://accounts.google.com";
observed_form_.form_data.name = ASCIIToUTF16("the-form-name");
@@ -104,49 +106,47 @@ TEST_F(PasswordFormFillingTest, NoSavedCredentials) {
EXPECT_CALL(driver_, ShowInitialPasswordAccountSuggestions(_)).Times(0);
LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
- &client_, &driver_, false /* is_blacklisted */, observed_form_,
- best_matches, federated_matches_, nullptr, metrics_recorder_.get());
+ &client_, &driver_, observed_form_, best_matches, federated_matches_,
+ nullptr, metrics_recorder_.get());
EXPECT_EQ(LikelyFormFilling::kNoFilling, likely_form_filling);
}
TEST_F(PasswordFormFillingTest, Autofill) {
- for (bool is_blacklisted : {false, true}) {
- std::map<base::string16, const autofill::PasswordForm*> best_matches;
- best_matches[saved_match_.username_value] = &saved_match_;
- PasswordForm another_saved_match = saved_match_;
- another_saved_match.username_value += ASCIIToUTF16("1");
- another_saved_match.password_value += ASCIIToUTF16("1");
- best_matches[another_saved_match.username_value] = &another_saved_match;
+ std::map<base::string16, const autofill::PasswordForm*> best_matches;
+ best_matches[saved_match_.username_value] = &saved_match_;
+ PasswordForm another_saved_match = saved_match_;
+ another_saved_match.username_value += ASCIIToUTF16("1");
+ another_saved_match.password_value += ASCIIToUTF16("1");
+ best_matches[another_saved_match.username_value] = &another_saved_match;
- EXPECT_CALL(driver_, InformNoSavedCredentials()).Times(0);
- PasswordFormFillData fill_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
- EXPECT_CALL(driver_, ShowInitialPasswordAccountSuggestions(_)).Times(0);
- EXPECT_CALL(client_, PasswordWasAutofilled(_, _, _));
+ EXPECT_CALL(driver_, InformNoSavedCredentials()).Times(0);
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
+ EXPECT_CALL(driver_, ShowInitialPasswordAccountSuggestions(_)).Times(0);
+ EXPECT_CALL(client_, PasswordWasAutofilled(_, _, _));
- LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
- &client_, &driver_, is_blacklisted, observed_form_, best_matches,
- federated_matches_, &saved_match_, metrics_recorder_.get());
- EXPECT_EQ(LikelyFormFilling::kFillOnPageLoad, likely_form_filling);
-
- // Check that the message to the renderer (i.e. |fill_data|) is filled
- // correctly.
- EXPECT_EQ(observed_form_.origin, fill_data.origin);
- EXPECT_FALSE(fill_data.wait_for_username);
- EXPECT_EQ(observed_form_.username_element, fill_data.username_field.name);
- EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
- EXPECT_EQ(observed_form_.password_element, fill_data.password_field.name);
- EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
-
- // Check that information about non-preferred best matches is filled.
- ASSERT_EQ(1u, fill_data.additional_logins.size());
- EXPECT_EQ(another_saved_match.username_value,
- fill_data.additional_logins.begin()->first);
- EXPECT_EQ(another_saved_match.password_value,
- fill_data.additional_logins.begin()->second.password);
- // Realm is empty for non-psl match.
- EXPECT_TRUE(fill_data.additional_logins.begin()->second.realm.empty());
- }
+ LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
+ &client_, &driver_, observed_form_, best_matches, federated_matches_,
+ &saved_match_, metrics_recorder_.get());
+ EXPECT_EQ(LikelyFormFilling::kFillOnPageLoad, likely_form_filling);
+
+ // Check that the message to the renderer (i.e. |fill_data|) is filled
+ // correctly.
+ EXPECT_EQ(observed_form_.origin, fill_data.origin);
+ EXPECT_FALSE(fill_data.wait_for_username);
+ EXPECT_EQ(observed_form_.username_element, fill_data.username_field.name);
+ EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
+ EXPECT_EQ(observed_form_.password_element, fill_data.password_field.name);
+ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
+
+ // Check that information about non-preferred best matches is filled.
+ ASSERT_EQ(1u, fill_data.additional_logins.size());
+ EXPECT_EQ(another_saved_match.username_value,
+ fill_data.additional_logins.begin()->first);
+ EXPECT_EQ(another_saved_match.password_value,
+ fill_data.additional_logins.begin()->second.password);
+ // Realm is empty for non-psl match.
+ EXPECT_TRUE(fill_data.additional_logins.begin()->second.realm.empty());
}
TEST_F(PasswordFormFillingTest, TestFillOnLoadSuggestion) {
@@ -171,18 +171,16 @@ TEST_F(PasswordFormFillingTest, TestFillOnLoadSuggestion) {
.current_password_present = true,
},
};
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kNewPasswordFormParsing);
-
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.description);
std::map<base::string16, const PasswordForm*> best_matches;
best_matches[saved_match_.username_value] = &saved_match_;
PasswordForm observed_form = observed_form_;
- observed_form.password_element_renderer_id = 123;
- if (!test_case.new_password_present)
+ if (test_case.new_password_present) {
observed_form.new_password_element = ASCIIToUTF16("New Passwd");
+ observed_form.new_password_element_renderer_id = 125;
+ }
if (!test_case.current_password_present) {
observed_form.password_element.clear();
observed_form.password_element_renderer_id =
@@ -194,8 +192,8 @@ TEST_F(PasswordFormFillingTest, TestFillOnLoadSuggestion) {
EXPECT_CALL(client_, PasswordWasAutofilled(_, _, _));
LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
- &client_, &driver_, false, observed_form, best_matches,
- federated_matches_, &saved_match_, metrics_recorder_.get());
+ &client_, &driver_, observed_form, best_matches, federated_matches_,
+ &saved_match_, metrics_recorder_.get());
// In all cases where a current password exists, fill on load should be
// permitted. Otherwise, the renderer will not fill anyway and return
@@ -218,9 +216,8 @@ TEST_F(PasswordFormFillingTest, AutofillPSLMatch) {
EXPECT_CALL(client_, PasswordWasAutofilled(_, _, _));
LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
- &client_, &driver_, false /* is_blacklisted */, observed_form_,
- best_matches, federated_matches_, &psl_saved_match_,
- metrics_recorder_.get());
+ &client_, &driver_, observed_form_, best_matches, federated_matches_,
+ &psl_saved_match_, metrics_recorder_.get());
EXPECT_EQ(LikelyFormFilling::kFillOnAccountSelect, likely_form_filling);
// Check that the message to the renderer (i.e. |fill_data|) is filled
@@ -247,9 +244,8 @@ TEST_F(PasswordFormFillingTest, FillingOnHttp) {
enable_foas_http);
LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
- &client_, &driver_, false /* is_blacklisted */, observed_form_,
- best_matches, federated_matches_, &saved_match_,
- metrics_recorder_.get());
+ &client_, &driver_, observed_form_, best_matches, federated_matches_,
+ &saved_match_, metrics_recorder_.get());
EXPECT_EQ(enable_foas_http ? LikelyFormFilling::kFillOnAccountSelect
: LikelyFormFilling::kFillOnPageLoad,
likely_form_filling);
@@ -269,9 +265,8 @@ TEST_F(PasswordFormFillingTest, TouchToFill) {
enable_touch_to_fill);
LikelyFormFilling likely_form_filling = SendFillInformationToRenderer(
- &client_, &driver_, false /* is_blacklisted */, observed_form_,
- best_matches, federated_matches_, &saved_match_,
- metrics_recorder_.get());
+ &client_, &driver_, observed_form_, best_matches, federated_matches_,
+ &saved_match_, metrics_recorder_.get());
EXPECT_EQ(enable_touch_to_fill ? LikelyFormFilling::kFillOnAccountSelect
: LikelyFormFilling::kFillOnPageLoad,
likely_form_filling);
diff --git a/chromium/components/password_manager/core/browser/password_form_manager.cc b/chromium/components/password_manager/core/browser/password_form_manager.cc
index 00294b09e1a..3f19991cc58 100644
--- a/chromium/components/password_manager/core/browser/password_form_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_form_manager.cc
@@ -1,59 +1,87 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/password_manager/core/browser/password_form_manager.h"
-#include <stddef.h>
-
#include <algorithm>
-#include <iterator>
-#include <map>
#include <memory>
+#include <set>
+#include <string>
#include <utility>
-#include "base/logging.h"
+#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
#include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/time/time.h"
-#include "components/autofill/core/browser/logging/log_manager.h"
+#include "build/build_config.h"
+#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/validation.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
#include "components/password_manager/core/browser/form_fetcher_impl.h"
#include "components/password_manager/core/browser/form_saver.h"
#include "components/password_manager/core/browser/password_form_filling.h"
#include "components/password_manager/core/browser/password_generation_state.h"
-#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/statistics_table.h"
-#include "components/password_manager/core/common/password_manager_features.h"
+using autofill::FormData;
+using autofill::FormFieldData;
+using autofill::FormSignature;
using autofill::FormStructure;
using autofill::PasswordForm;
using autofill::ValueElementPair;
-using base::Time;
+using base::TimeDelta;
+using base::TimeTicks;
-// Shorten the name to spare line breaks. The code provides enough context
-// already.
-typedef autofill::SavePasswordProgressLogger Logger;
+using Logger = autofill::SavePasswordProgressLogger;
namespace password_manager {
+bool PasswordFormManager::wait_for_server_predictions_for_filling_ = true;
+
namespace {
-// This namespace is for fixing Jumbo builds, because the same functions are
-// defined in new_password_form_manager.cc.
-namespace password_form_manager_helpers {
+constexpr TimeDelta kMaxFillingDelayForServerPredictions =
+ TimeDelta::FromMilliseconds(500);
+
+// Helper to get the platform specific identifier by which autofill and password
+// manager refer to a field. See http://crbug.com/896594
+base::string16 GetPlatformSpecificIdentifier(const FormFieldData& field) {
+#if defined(OS_IOS)
+ return field.unique_id;
+#else
+ return field.name;
+#endif
+}
+
+ValueElementPair PasswordToSave(const PasswordForm& form) {
+ if (form.new_password_value.empty()) {
+ DCHECK(!form.password_value.empty() || form.IsFederatedCredential());
+ return {form.password_value, form.password_element};
+ }
+ return {form.new_password_value, form.new_password_element};
+}
+
+// Copies field properties masks from the form |from| to the form |to|.
+void CopyFieldPropertiesMasks(const FormData& from, FormData* to) {
+ // Skip copying if the number of fields is different.
+ if (from.fields.size() != to->fields.size())
+ return;
+
+ for (size_t i = 0; i < from.fields.size(); ++i) {
+ to->fields[i].properties_mask =
+ GetPlatformSpecificIdentifier(to->fields[i]) ==
+ GetPlatformSpecificIdentifier(from.fields[i])
+ ? from.fields[i].properties_mask
+ : autofill::FieldPropertiesFlags::ERROR_OCCURRED;
+ }
+}
// Filter sensitive information, duplicates and |username_value| out from
// |form->all_possible_usernames|.
@@ -74,209 +102,161 @@ void SanitizePossibleUsernames(PasswordForm* form) {
});
}
-} // namespace password_form_manager_helpers
-
-bool DoesStringContainOnlyDigits(const base::string16& s) {
- for (auto c : s) {
- if (!base::IsAsciiDigit(c))
- return false;
- }
- return true;
-}
-
-// Heuristics to determine that a string is very unlikely to be a username.
-bool IsProbablyNotUsername(const base::string16& s) {
- return !s.empty() && DoesStringContainOnlyDigits(s) && s.size() < 3;
-}
-
-// Copies field properties masks from the form |from| to the form |to|.
-void CopyFieldPropertiesMasks(const PasswordForm& from, PasswordForm* to) {
- // Skip copying if the number of fields is different.
- if (from.form_data.fields.size() != to->form_data.fields.size())
- return;
-
- for (size_t i = 0; i < from.form_data.fields.size(); ++i) {
- to->form_data.fields[i].properties_mask =
- to->form_data.fields[i].name == from.form_data.fields[i].name
- ? from.form_data.fields[i].properties_mask
- : autofill::FieldPropertiesFlags::ERROR_OCCURRED;
+// Returns bit masks with differences in forms attributes which are important
+// for parsing. Bits are set according to enum FormDataDifferences.
+uint32_t FindFormsDifferences(const FormData& lhs, const FormData& rhs) {
+ if (lhs.fields.size() != rhs.fields.size())
+ return PasswordFormMetricsRecorder::kFieldsNumber;
+ size_t differences_bitmask = 0;
+ for (size_t i = 0; i < lhs.fields.size(); ++i) {
+ const FormFieldData& lhs_field = lhs.fields[i];
+ const FormFieldData& rhs_field = rhs.fields[i];
+
+ if (lhs_field.unique_renderer_id != rhs_field.unique_renderer_id)
+ differences_bitmask |= PasswordFormMetricsRecorder::kRendererFieldIDs;
+
+ if (lhs_field.form_control_type != rhs_field.form_control_type)
+ differences_bitmask |= PasswordFormMetricsRecorder::kFormControlTypes;
+
+ if (lhs_field.autocomplete_attribute != rhs_field.autocomplete_attribute)
+ differences_bitmask |=
+ PasswordFormMetricsRecorder::kAutocompleteAttributes;
}
+ return differences_bitmask;
}
} // namespace
PasswordFormManager::PasswordFormManager(
- PasswordManager* password_manager,
PasswordManagerClient* client,
const base::WeakPtr<PasswordManagerDriver>& driver,
- const PasswordForm& observed_form,
+ const FormData& observed_form,
+ FormFetcher* form_fetcher,
std::unique_ptr<FormSaver> form_saver,
- FormFetcher* form_fetcher)
- : observed_form_(observed_form),
- observed_form_signature_(CalculateFormSignature(observed_form.form_data)),
- is_new_login_(true),
- password_overridden_(false),
- retry_password_form_password_update_(false),
- password_manager_(password_manager),
- preferred_match_(nullptr),
- is_possible_change_password_form_without_username_(
- observed_form.IsPossibleChangePasswordFormWithoutUsername()),
- client_(client),
- form_saver_(std::move(form_saver)),
- owned_form_fetcher_(form_fetcher
- ? nullptr
- : std::make_unique<FormFetcherImpl>(
- PasswordStore::FormDigest(observed_form),
- client,
- true /* should_migrate_http_passwords */)),
- form_fetcher_(form_fetcher ? form_fetcher : owned_form_fetcher_.get()),
- votes_uploader_(client, observed_form.IsPossibleChangePasswordForm()) {
- // Non-HTML forms should not need any interaction with the renderer, and hence
- // no driver. Note that cloned PasswordFormManager instances can have HTML
- // forms without drivers as well.
- DCHECK((observed_form.scheme == PasswordForm::Scheme::kHtml) ||
- (driver == nullptr))
- << observed_form.scheme;
- if (driver)
- drivers_.push_back(driver);
-}
-
-void PasswordFormManager::Init(
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder) {
- DCHECK(!metrics_recorder_) << "Do not call Init twice.";
- metrics_recorder_ = std::move(metrics_recorder);
- if (!metrics_recorder_) {
- metrics_recorder_ = base::MakeRefCounted<PasswordFormMetricsRecorder>(
- client_->IsMainFrameSecure(), client_->GetUkmSourceId());
- }
-
- metrics_recorder_->RecordFormSignature(observed_form_signature_);
-
+ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder)
+ : PasswordFormManager(client,
+ form_fetcher,
+ std::move(form_saver),
+ metrics_recorder,
+ PasswordStore::FormDigest(observed_form)) {
+ driver_ = driver;
+ observed_form_ = observed_form;
+ metrics_recorder_->RecordFormSignature(CalculateFormSignature(observed_form));
+ // Do not fetch saved credentials for Chrome sync form, since nor filling nor
+ // saving are supported.
if (owned_form_fetcher_ &&
- !observed_form_.form_data.is_gaia_with_skip_save_password_form) {
+ !observed_form_.is_gaia_with_skip_save_password_form) {
owned_form_fetcher_->Fetch();
}
form_fetcher_->AddConsumer(this);
+ votes_uploader_.StoreInitialFieldValues(observed_form);
+}
+
+PasswordFormManager::PasswordFormManager(
+ PasswordManagerClient* client,
+ PasswordStore::FormDigest observed_http_auth_digest,
+ FormFetcher* form_fetcher,
+ std::unique_ptr<FormSaver> form_saver)
+ : PasswordFormManager(client,
+ form_fetcher,
+ std::move(form_saver),
+ nullptr /* metrics_recorder */,
+ observed_http_auth_digest) {
+ observed_not_web_form_digest_ = std::move(observed_http_auth_digest);
+ if (owned_form_fetcher_)
+ owned_form_fetcher_->Fetch();
+ form_fetcher_->AddConsumer(this);
}
PasswordFormManager::~PasswordFormManager() {
form_fetcher_->RemoveConsumer(this);
}
-// static
-ValueElementPair PasswordFormManager::PasswordToSave(const PasswordForm& form) {
- if (form.new_password_element.empty() || form.new_password_value.empty())
- return {form.password_value, form.password_element};
- return {form.new_password_value, form.new_password_element};
+bool PasswordFormManager::DoesManage(
+ const FormData& form,
+ const PasswordManagerDriver* driver) const {
+ if (driver != driver_.get())
+ return false;
+
+ if (observed_form_.is_form_tag != form.is_form_tag)
+ return false;
+ // All unowned input elements are considered as one synthetic form.
+ if (!observed_form_.is_form_tag && !form.is_form_tag)
+ return true;
+#if defined(OS_IOS)
+ // On iOS form name is used as the form identifier.
+ return observed_form_.name == form.name;
+#else
+ return observed_form_.unique_renderer_id == form.unique_renderer_id;
+#endif
}
-// TODO(crbug.com/700420): Refactor this function, to make comparison more
-// reliable.
-PasswordFormManager::MatchResultMask PasswordFormManager::DoesManage(
- const PasswordForm& form,
- const password_manager::PasswordManagerDriver* driver) const {
- // Non-HTML form case.
- if (observed_form_.scheme != PasswordForm::Scheme::kHtml ||
- form.scheme != PasswordForm::Scheme::kHtml) {
- const bool forms_match = observed_form_.signon_realm == form.signon_realm &&
- observed_form_.scheme == form.scheme;
- return forms_match ? RESULT_COMPLETE_MATCH : RESULT_NO_MATCH;
- }
-
- // HTML form case.
- MatchResultMask result = RESULT_NO_MATCH;
-
- if (observed_form_.signon_realm != form.signon_realm)
- return result;
-
- // Easiest case of matching origins.
- bool origins_match = form.origin == observed_form_.origin;
- // If this is a replay of the same form in the case a user entered an invalid
- // password, the origin of the new form may equal the action of the "first"
- // form instead.
- origins_match = origins_match || (form.origin == observed_form_.action);
- // Otherwise, if action hosts are the same, the old URL scheme is HTTP while
- // the new one is HTTPS, and the new path equals to or extends the old path,
- // we also consider the actions a match. This is to accommodate cases where
- // the original login form is on an HTTP page, but a failed login attempt
- // redirects to HTTPS (as in http://example.org -> https://example.org/auth).
- if (!origins_match && !observed_form_.origin.SchemeIsCryptographic() &&
- form.origin.SchemeIsCryptographic()) {
- const base::StringPiece& old_path = observed_form_.origin.path_piece();
- const base::StringPiece& new_path = form.origin.path_piece();
- origins_match =
- observed_form_.origin.host_piece() == form.origin.host_piece() &&
- observed_form_.origin.port() == form.origin.port() &&
- base::StartsWith(new_path, old_path, base::CompareCase::SENSITIVE);
- }
-
- if (driver) {
- origins_match =
- origins_match ||
- std::any_of(drivers_.begin(), drivers_.end(),
- [driver](const base::WeakPtr<PasswordManagerDriver>& d) {
- return d.get() == driver;
- });
- }
- if (!origins_match)
- return result;
-
- result |= RESULT_ORIGINS_OR_FRAMES_MATCH;
-
- if (CalculateFormSignature(form.form_data) == observed_form_signature_)
- result |= RESULT_SIGNATURE_MATCH;
+bool PasswordFormManager::DoesManageAccordingToRendererId(
+ uint32_t form_renderer_id,
+ const PasswordManagerDriver* driver) const {
+ if (driver != driver_.get())
+ return false;
+#if defined(OS_IOS)
+ NOTREACHED();
+ // On iOS form name is used as the form identifier.
+ return false;
+#else
+ return observed_form_.unique_renderer_id == form_renderer_id;
+#endif
+}
- if (form.form_data.name == observed_form_.form_data.name)
- result |= RESULT_FORM_NAME_MATCH;
+bool PasswordFormManager::IsEqualToSubmittedForm(
+ const autofill::FormData& form) const {
+ if (!is_submitted_)
+ return false;
+ if (IsHttpAuth())
+ return false;
+ if (form.action == submitted_form_.action)
+ return true;
+ // TODO(https://crbug.com/831123): Implement other checks from a function
+ // IsPasswordFormReappeared from password_manager.cc.
+ return false;
+}
- // Note: although saved password forms might actually have an empty action
- // URL if they were imported (see bug 1107719), the |form| we see here comes
- // never from the password store, and should have an exactly matching action.
- if (form.action == observed_form_.action)
- result |= RESULT_ACTION_MATCH;
+const GURL& PasswordFormManager::GetOrigin() const {
+ return observed_not_web_form_digest_ ? observed_not_web_form_digest_->origin
+ : observed_form_.url;
+}
- return result;
+const std::map<base::string16, const PasswordForm*>&
+PasswordFormManager::GetBestMatches() const {
+ return best_matches_;
}
-void PasswordFormManager::PermanentlyBlacklist() {
- DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
- DCHECK(!client_->IsIncognito());
+std::vector<const autofill::PasswordForm*>
+PasswordFormManager::GetFederatedMatches() const {
+ return form_fetcher_->GetFederatedMatches();
+}
- if (!new_blacklisted_) {
- new_blacklisted_ = std::make_unique<PasswordForm>();
- blacklisted_matches_.push_back(new_blacklisted_.get());
- }
- *new_blacklisted_ = form_saver_->PermanentlyBlacklist(
- PasswordStore::FormDigest(observed_form_));
+const PasswordForm& PasswordFormManager::GetPendingCredentials() const {
+ return pending_credentials_;
}
-bool PasswordFormManager::IsNewLogin() const {
- DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
- return is_new_login_;
+metrics_util::CredentialSourceType PasswordFormManager::GetCredentialSource() {
+ return metrics_util::CredentialSourceType::kPasswordManager;
}
-FormFetcher* PasswordFormManager::GetFormFetcher() {
- return form_fetcher_;
+PasswordFormMetricsRecorder* PasswordFormManager::GetMetricsRecorder() {
+ return metrics_recorder_.get();
}
-bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const {
- return pending_credentials_.is_public_suffix_match;
+base::span<const autofill::PasswordForm* const>
+PasswordFormManager::GetBlacklistedMatches() const {
+ return base::make_span(blacklisted_matches_);
}
-void PasswordFormManager::ProvisionallySave(const PasswordForm& credentials) {
- std::unique_ptr<autofill::PasswordForm> mutable_submitted_form(
- new PasswordForm(credentials));
- if (credentials.IsPossibleChangePasswordForm() &&
- !credentials.username_value.empty() &&
- IsProbablyNotUsername(credentials.username_value)) {
- mutable_submitted_form->username_value.clear();
- mutable_submitted_form->username_element.clear();
- is_possible_change_password_form_without_username_ = true;
- }
- submitted_form_ = std::move(mutable_submitted_form);
+base::span<const InteractionsStats> PasswordFormManager::GetInteractionsStats()
+ const {
+ return base::make_span(form_fetcher_->GetInteractionsStats());
+}
- if (form_fetcher_->GetState() == FormFetcher::State::NOT_WAITING)
- CreatePendingCredentials();
+bool PasswordFormManager::IsBlacklisted() const {
+ return !blacklisted_matches_.empty();
}
void PasswordFormManager::Save() {
@@ -289,11 +269,7 @@ void PasswordFormManager::Save() {
blacklisted_iterator = blacklisted_matches_.erase(blacklisted_iterator);
}
- metrics_util::LogPasswordAcceptedSaveUpdateSubmissionIndicatorEvent(
- submitted_form_->submission_event);
- metrics_recorder_->SetSubmissionIndicatorEvent(
- submitted_form_->submission_event);
-
+ // TODO(https://crbug.com/831123): Implement indicator event metrics.
if (password_overridden_ &&
pending_credentials_.type == PasswordForm::Type::kGenerated &&
!HasGeneratedPassword()) {
@@ -305,15 +281,14 @@ void PasswordFormManager::Save() {
if (is_new_login_) {
metrics_util::LogNewlySavedPasswordIsGenerated(
pending_credentials_.type == PasswordForm::Type::kGenerated);
- password_form_manager_helpers::SanitizePossibleUsernames(
- &pending_credentials_);
+ SanitizePossibleUsernames(&pending_credentials_);
pending_credentials_.date_created = base::Time::Now();
- votes_uploader_.SendVotesOnSave(observed_form_.form_data, *submitted_form_,
+ votes_uploader_.SendVotesOnSave(observed_form_, *parsed_submitted_form_,
best_matches_, &pending_credentials_);
- SavePendingToStore(false);
+ SavePendingToStore(false /*update*/);
} else {
ProcessUpdate();
- SavePendingToStore(true);
+ SavePendingToStore(true /*update*/);
}
if (pending_credentials_.times_used == 1 &&
@@ -323,136 +298,153 @@ void PasswordFormManager::Save() {
metrics_util::PASSWORD_USED);
}
- password_manager_->UpdateFormManagers();
+ client_->UpdateFormManagers();
}
-void PasswordFormManager::Update(
- const autofill::PasswordForm& credentials_to_update) {
+void PasswordFormManager::Update(const PasswordForm& credentials_to_update) {
metrics_util::LogPasswordAcceptedSaveUpdateSubmissionIndicatorEvent(
- submitted_form_->submission_event);
+ parsed_submitted_form_->submission_event);
metrics_recorder_->SetSubmissionIndicatorEvent(
- submitted_form_->submission_event);
+ parsed_submitted_form_->submission_event);
+
+ std::unique_ptr<PasswordForm> parsed_observed_form =
+ parser_.Parse(observed_form_, FormDataParser::Mode::kFilling);
+
base::string16 password_to_save = pending_credentials_.password_value;
bool skip_zero_click = pending_credentials_.skip_zero_click;
pending_credentials_ = credentials_to_update;
pending_credentials_.password_value = password_to_save;
pending_credentials_.skip_zero_click = skip_zero_click;
pending_credentials_.preferred = true;
+ pending_credentials_.date_last_used = base::Time::Now();
is_new_login_ = false;
ProcessUpdate();
- SavePendingToStore(true);
+ SavePendingToStore(true /*update*/);
- password_manager_->UpdateFormManagers();
+ client_->UpdateFormManagers();
}
void PasswordFormManager::UpdateUsername(const base::string16& new_username) {
- PasswordForm credential(*submitted_form_);
- credential.username_value = new_username;
- // If |new_username| is not found in |all_possible_usernames|, store empty
- // |username_element|.
- credential.username_element.clear();
+ DCHECK(parsed_submitted_form_);
+ parsed_submitted_form_->username_value = new_username;
+ parsed_submitted_form_->username_element.clear();
// |has_username_edited_vote_| is true iff |new_username| was typed in another
// field. Otherwise, |has_username_edited_vote_| is false and no vote will be
// uploaded.
votes_uploader_.set_has_username_edited_vote(false);
if (!new_username.empty()) {
- for (size_t i = 0; i < credential.all_possible_usernames.size(); ++i) {
- if (credential.all_possible_usernames[i].first == new_username) {
- credential.username_element =
- credential.all_possible_usernames[i].second;
-
- credential.all_possible_usernames.erase(
- credential.all_possible_usernames.begin() + i);
-
- // Set |corrected_username_element_| to upload a username vote.
+ // |all_possible_usernames| has all possible usernames.
+ // TODO(crbug.com/831123): rename to |all_possible_usernames| when the old
+ // parser is gone.
+ for (const auto& possible_username :
+ parsed_submitted_form_->all_possible_usernames) {
+ if (possible_username.first == new_username) {
+ parsed_submitted_form_->username_element = possible_username.second;
votes_uploader_.set_has_username_edited_vote(true);
break;
}
}
}
- // A user may make a mistake and remove the correct username. So, save
- // |username_value| and |username_element| of the submitted form. When the
- // user has to override the username, Chrome will send a username vote.
- if (!submitted_form_->username_value.empty()) {
- credential.all_possible_usernames.push_back(ValueElementPair(
- submitted_form_->username_value, submitted_form_->username_element));
- }
- ProvisionallySave(credential);
+ CreatePendingCredentials();
}
void PasswordFormManager::UpdatePasswordValue(
const base::string16& new_password) {
- DCHECK(!new_password.empty());
-
- PasswordForm credential(*submitted_form_);
- // Select whether to update |password_value| or |new_password_value|.
- base::string16* password_value_ptr;
- base::string16* password_element_ptr;
- if (credential.new_password_value.empty()) {
- DCHECK(!credential.password_value.empty());
- password_value_ptr = &credential.password_value;
- password_element_ptr = &credential.password_element;
- } else {
- password_value_ptr = &credential.new_password_value;
- password_element_ptr = &credential.new_password_element;
- }
+ DCHECK(parsed_submitted_form_);
+ parsed_submitted_form_->password_value = new_password;
+ parsed_submitted_form_->password_element.clear();
+
+ // The user updated a password from the prompt. It means that heuristics were
+ // wrong. So clear new password, since it is likely wrong.
+ parsed_submitted_form_->new_password_value.clear();
+ parsed_submitted_form_->new_password_element.clear();
- *password_value_ptr = new_password;
- // If |new_password| is not found among the known password fields, store an
- // empty field name.
- password_element_ptr->clear();
- for (const ValueElementPair& pair : credential.all_possible_passwords) {
- DCHECK(!pair.second.empty());
+ for (const ValueElementPair& pair :
+ parsed_submitted_form_->all_possible_passwords) {
if (pair.first == new_password) {
- *password_element_ptr = pair.second;
+ parsed_submitted_form_->password_element = pair.second;
break;
}
}
- ProvisionallySave(credential);
+ CreatePendingCredentials();
}
-void PasswordFormManager::PresaveGeneratedPassword(
- const autofill::PasswordForm& form) {
- if (!HasGeneratedPassword()) {
- votes_uploader_.set_generated_password_changed(false);
- metrics_recorder_->SetGeneratedPasswordStatus(
- PasswordFormMetricsRecorder::GeneratedPasswordStatus::
- kPasswordAccepted);
- } else {
- // If the password is already generated and the new value to presave differs
- // from the presaved one, then mark that the generated password was changed.
- // If a user recovers the original generated password, it will be recorded
- // as a password change.
- if (generation_state_->generated_password() != form.password_value) {
- votes_uploader_.set_generated_password_changed(true);
- metrics_recorder_->SetGeneratedPasswordStatus(
- PasswordFormMetricsRecorder::GeneratedPasswordStatus::
- kPasswordEdited);
+void PasswordFormManager::OnNopeUpdateClicked() {
+ votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
+ *parsed_submitted_form_,
+ autofill::NOT_NEW_PASSWORD, std::string());
+}
+
+void PasswordFormManager::OnNeverClicked() {
+ // |UNKNOWN_TYPE| is sent in order to record that a generation popup was
+ // shown and ignored.
+ votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
+ *parsed_submitted_form_,
+ autofill::UNKNOWN_TYPE, std::string());
+ PermanentlyBlacklist();
+}
+
+void PasswordFormManager::OnNoInteraction(bool is_update) {
+ // |UNKNOWN_TYPE| is sent in order to record that a generation popup was
+ // shown and ignored.
+ votes_uploader_.UploadPasswordVote(
+ *parsed_submitted_form_, *parsed_submitted_form_,
+ is_update ? autofill::PROBABLY_NEW_PASSWORD : autofill::UNKNOWN_TYPE,
+ std::string());
+}
+
+void PasswordFormManager::PermanentlyBlacklist() {
+ DCHECK(!client_->IsIncognito());
+
+ if (!new_blacklisted_) {
+ new_blacklisted_ = std::make_unique<PasswordForm>();
+ if (observed_not_web_form_digest_) {
+ new_blacklisted_->origin = observed_not_web_form_digest_->origin;
+ // GetSignonRealm is not suitable for http auth credentials.
+ new_blacklisted_->signon_realm =
+ IsHttpAuth() ? observed_not_web_form_digest_->signon_realm
+ : GetSignonRealm(observed_not_web_form_digest_->origin);
+ } else {
+ new_blacklisted_->origin = observed_form_.url;
+ new_blacklisted_->signon_realm = GetSignonRealm(observed_form_.url);
}
+ new_blacklisted_->scheme = GetScheme();
+ blacklisted_matches_.push_back(new_blacklisted_.get());
}
+ *new_blacklisted_ = form_saver_->PermanentlyBlacklist(
+ PasswordStore::FormDigest(*new_blacklisted_));
+}
- if (!generation_state_) {
- generation_state_ =
- std::make_unique<PasswordGenerationState>(form_saver_.get(), client_);
- }
- if (!base::Contains(best_matches_, form.username_value) ||
- form.username_value.empty()) {
- generation_state_->PresaveGeneratedPassword(form, {});
- } else {
- autofill::PasswordForm form_without_username(form);
- form_without_username.username_value.clear();
- generation_state_->PresaveGeneratedPassword(
- std::move(form_without_username), {});
- }
+void PasswordFormManager::OnPasswordsRevealed() {
+ votes_uploader_.set_has_passwords_revealed_vote(true);
+}
- votes_uploader_.set_has_generated_password(true);
+bool PasswordFormManager::IsNewLogin() const {
+ return is_new_login_;
+}
+
+FormFetcher* PasswordFormManager::GetFormFetcher() {
+ return form_fetcher_;
+}
+
+bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const {
+ return pending_credentials_.is_public_suffix_match;
+}
+
+void PasswordFormManager::PresaveGeneratedPassword(const PasswordForm& form) {
+ // TODO(https://crbug.com/831123): Propagate generated password independently
+ // of PasswordForm when PasswordForm goes away from the renderer process.
+ PresaveGeneratedPasswordInternal(form.form_data,
+ form.password_value /*generated_password*/);
}
void PasswordFormManager::PasswordNoLongerGenerated() {
- DCHECK(HasGeneratedPassword());
+ if (!HasGeneratedPassword())
+ return;
+
generation_state_->PasswordNoLongerGenerated();
generation_state_.reset();
votes_uploader_.set_has_generated_password(false);
@@ -461,180 +453,468 @@ void PasswordFormManager::PasswordNoLongerGenerated() {
PasswordFormMetricsRecorder::GeneratedPasswordStatus::kPasswordDeleted);
}
-void PasswordFormManager::SaveSubmittedFormTypeForMetrics(
- const autofill::PasswordForm& form) {
- bool is_change_password_form =
- !form.new_password_value.empty() && !form.password_value.empty();
- bool is_signup_form =
- !form.new_password_value.empty() && form.password_value.empty();
- bool no_username = form.username_value.empty();
-
- PasswordFormMetricsRecorder::SubmittedFormType type =
- PasswordFormMetricsRecorder::kSubmittedFormTypeUnspecified;
- if (is_change_password_form) {
- type = PasswordFormMetricsRecorder::kSubmittedFormTypeChangePasswordEnabled;
- } else if (is_signup_form) {
- if (no_username)
- type = PasswordFormMetricsRecorder::kSubmittedFormTypeSignupNoUsername;
- else
- type = PasswordFormMetricsRecorder::kSubmittedFormTypeSignup;
- } else if (no_username) {
- type = PasswordFormMetricsRecorder::kSubmittedFormTypeLoginNoUsername;
- } else {
- type = PasswordFormMetricsRecorder::kSubmittedFormTypeLogin;
+bool PasswordFormManager::HasGeneratedPassword() const {
+ return generation_state_ && generation_state_->HasGeneratedPassword();
+}
+
+void PasswordFormManager::SetGenerationPopupWasShown(
+ bool generation_popup_was_shown,
+ bool is_manual_generation) {
+ votes_uploader_.set_generation_popup_was_shown(generation_popup_was_shown);
+ votes_uploader_.set_is_manual_generation(is_manual_generation);
+ metrics_recorder_->SetPasswordGenerationPopupShown(generation_popup_was_shown,
+ is_manual_generation);
+}
+
+void PasswordFormManager::SetGenerationElement(
+ const base::string16& generation_element) {
+ votes_uploader_.set_generation_element(generation_element);
+}
+
+bool PasswordFormManager::IsPossibleChangePasswordFormWithoutUsername() const {
+ return parsed_submitted_form_ &&
+ parsed_submitted_form_->IsPossibleChangePasswordFormWithoutUsername();
+}
+
+bool PasswordFormManager::IsPasswordUpdate() const {
+ return password_overridden_;
+}
+
+std::vector<base::WeakPtr<PasswordManagerDriver>>
+PasswordFormManager::GetDrivers() const {
+ return {driver_};
+}
+
+const PasswordForm* PasswordFormManager::GetSubmittedForm() const {
+ return parsed_submitted_form_.get();
+}
+
+#if defined(OS_IOS)
+void PasswordFormManager::PresaveGeneratedPassword(
+ PasswordManagerDriver* driver,
+ const FormData& form,
+ const base::string16& generated_password,
+ const base::string16& generation_element) {
+ observed_form_ = form;
+ PresaveGeneratedPasswordInternal(form, generated_password);
+ votes_uploader_.set_generation_element(generation_element);
+}
+
+bool PasswordFormManager::UpdateGeneratedPasswordOnUserInput(
+ const base::string16& form_identifier,
+ const base::string16& field_identifier,
+ const base::string16& field_value) {
+ if (observed_form_.name != form_identifier || !HasGeneratedPassword()) {
+ // *this might not have generated password, because
+ // 1.This function is called before PresaveGeneratedPassword, or
+ // 2.There are multiple forms with the same |form_identifier|
+ return false;
+ }
+ bool form_data_changed = false;
+ for (FormFieldData& field : observed_form_.fields) {
+ if (field.unique_id == field_identifier) {
+ field.value = field_value;
+ form_data_changed = true;
+ break;
+ }
}
- metrics_recorder_->SetSubmittedFormType(type);
+ base::string16 generated_password = generation_state_->generated_password();
+ if (votes_uploader_.get_generation_element() == field_identifier) {
+ generated_password = field_value;
+ form_data_changed = true;
+ }
+ if (form_data_changed)
+ PresaveGeneratedPasswordInternal(observed_form_, generated_password);
+ return true;
}
+#endif // defined(OS_IOS)
-void PasswordFormManager::OnFetchCompleted() {
- blacklisted_matches_.clear();
- new_blacklisted_.reset();
+std::unique_ptr<PasswordFormManager> PasswordFormManager::Clone() {
+ // Fetcher is cloned to avoid re-fetching data from PasswordStore.
+ std::unique_ptr<FormFetcher> fetcher = form_fetcher_->Clone();
- std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
- if (password_manager_util::IsLoggingActive(client_)) {
- logger.reset(
- new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
- logger->LogMessage(Logger::STRING_ON_FETCH_COMPLETED_METHOD);
+ // Some data is filled through the constructor. No PasswordManagerDriver is
+ // needed, because the UI does not need any functionality related to the
+ // renderer process, to which the driver serves as an interface. The full
+ // |observed_form_| needs to be copied, because it is used to create the
+ // blacklisting entry if needed.
+ auto result = std::make_unique<PasswordFormManager>(
+ client_, base::WeakPtr<PasswordManagerDriver>(), observed_form_,
+ fetcher.get(), form_saver_->Clone(), metrics_recorder_);
+
+ // The constructor only can take a weak pointer to the fetcher, so moving the
+ // owning one needs to happen explicitly.
+ result->owned_form_fetcher_ = std::move(fetcher);
+
+ if (generation_state_) {
+ result->generation_state_ =
+ generation_state_->Clone(result->form_saver_.get());
}
- // Copy out and score non-blacklisted matches.
- std::vector<const PasswordForm*> matches;
- for (const auto* match : form_fetcher_->GetNonFederatedMatches()) {
- if (match->scheme == observed_form_.scheme)
- matches.push_back(match);
+ // These data members all satisfy:
+ // (1) They could have been changed by |*this| between its construction and
+ // calling Clone().
+ // (2) They are potentially used in the clone as the clone is used in the UI
+ // code.
+ // (3) They are not changed during OnFetchCompleted, triggered at some point
+ // by the
+ // cloned FormFetcher.
+ result->votes_uploader_ = votes_uploader_;
+ if (parser_.predictions())
+ result->parser_.set_predictions(*parser_.predictions());
+
+ result->pending_credentials_ = pending_credentials_;
+ if (parsed_submitted_form_) {
+ result->parsed_submitted_form_.reset(
+ new PasswordForm(*parsed_submitted_form_));
}
+ result->is_new_login_ = is_new_login_;
+ result->password_overridden_ = password_overridden_;
+ result->is_submitted_ = is_submitted_;
+
+ return result;
+}
+
+PasswordFormManager::PasswordFormManager(
+ PasswordManagerClient* client,
+ std::unique_ptr<PasswordForm> saved_form,
+ std::unique_ptr<FormFetcher> form_fetcher,
+ std::unique_ptr<FormSaver> form_saver)
+ : PasswordFormManager(client,
+ form_fetcher.get(),
+ std::move(form_saver),
+ nullptr /* metrics_recorder */,
+ PasswordStore::FormDigest(*saved_form)) {
+ observed_not_web_form_digest_ = PasswordStore::FormDigest(*saved_form);
+ parsed_submitted_form_ = std::move(saved_form);
+ is_submitted_ = true;
+ owned_form_fetcher_ = std::move(form_fetcher),
+ form_fetcher_->AddConsumer(this);
+ if (form_fetcher_)
+ form_fetcher_->Fetch();
+}
- password_manager_util::FindBestMatches(std::move(matches), &best_matches_,
- &not_best_matches_, &preferred_match_);
+void PasswordFormManager::OnFetchCompleted() {
+ received_stored_credentials_time_ = TimeTicks::Now();
+ best_matches_ = form_fetcher_->GetBestMatches();
+ preferred_match_ = form_fetcher_->GetPreferredMatch();
// Copy out blacklisted matches.
+ new_blacklisted_.reset();
blacklisted_matches_ = form_fetcher_->GetBlacklistedMatches();
- UMA_HISTOGRAM_COUNTS_1M("PasswordManager.NumPasswordsNotShown",
- form_fetcher_->GetNonFederatedMatches().size() +
- form_fetcher_->GetFederatedMatches().size() +
- form_fetcher_->GetBlacklistedMatches().size() -
- best_matches_.size());
+ autofills_left_ = kMaxTimesAutofill;
- // If password store was slow and provisionally saved form is already here
- // then create pending credentials (see http://crbug.com/470322).
- if (submitted_form_)
- CreatePendingCredentials();
+ if (IsCredentialAPISave()) {
+ // This is saving with credential API, there is no form to fill, so no
+ // filling required.
+ return;
+ }
- for (auto const& driver : drivers_)
- ProcessFrameInternal(driver);
- if (observed_form_.scheme != PasswordForm::Scheme::kHtml)
- ProcessLoginPrompt();
+ if (IsHttpAuth()) {
+ // No server prediction for http auth, so no need to wait.
+ FillHttpAuth();
+ } else if (parser_.predictions() ||
+ !wait_for_server_predictions_for_filling_) {
+ ReportTimeBetweenStoreAndServerUMA();
+ Fill();
+ } else if (!waiting_for_server_predictions_) {
+ waiting_for_server_predictions_ = true;
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&PasswordFormManager::Fill,
+ weak_ptr_factory_.GetWeakPtr()),
+ kMaxFillingDelayForServerPredictions);
+ }
}
-void PasswordFormManager::ProcessFrame(
- const base::WeakPtr<PasswordManagerDriver>& driver) {
- DCHECK_EQ(PasswordForm::Scheme::kHtml, observed_form_.scheme);
+bool PasswordFormManager::ProvisionallySave(
+ const FormData& submitted_form,
+ const PasswordManagerDriver* driver) {
+ DCHECK(DoesManage(submitted_form, driver));
- // Don't keep processing the same form.
- if (autofills_left_ <= 0)
- return;
- autofills_left_--;
+ std::unique_ptr<PasswordForm> parsed_submitted_form =
+ ParseFormAndMakeLogging(submitted_form, FormDataParser::Mode::kSaving);
- if (form_fetcher_->GetState() == FormFetcher::State::NOT_WAITING)
- ProcessFrameInternal(driver);
+ RecordMetricOnReadonly(parser_.readonly_status(), !!parsed_submitted_form,
+ FormDataParser::Mode::kSaving);
- for (auto const& old_driver : drivers_) {
- // |drivers_| is not a set because WeakPtr has no good candidate for a key
- // (the address may change to null). So let's weed out duplicates in O(N).
- if (old_driver.get() == driver.get())
- return;
- }
+ // This function might be called multiple times. Consider as success if the
+ // submitted form was successfully parsed on a previous call.
+ if (!parsed_submitted_form)
+ return is_submitted_;
+
+ parsed_submitted_form_ = std::move(parsed_submitted_form);
+ submitted_form_ = submitted_form;
+ is_submitted_ = true;
+ CalculateFillingAssistanceMetric(submitted_form);
+
+ CreatePendingCredentials();
+ return true;
+}
+
+bool PasswordFormManager::ProvisionallySaveHttpAuthForm(
+ const PasswordForm& submitted_form) {
+ if (!IsHttpAuth())
+ return false;
+ if (!(*observed_not_web_form_digest_ ==
+ PasswordStore::FormDigest(submitted_form)))
+ return false;
+
+ parsed_submitted_form_.reset(new PasswordForm(submitted_form));
+ is_submitted_ = true;
+ CreatePendingCredentials();
+ return true;
+}
- drivers_.push_back(driver);
+bool PasswordFormManager::IsHttpAuth() const {
+ return GetScheme() != PasswordForm::Scheme::kHtml;
}
-void PasswordFormManager::ProcessFrameInternal(
- const base::WeakPtr<PasswordManagerDriver>& driver) {
- if (base::FeatureList::IsEnabled(
- password_manager::features::kNewPasswordFormParsing))
+bool PasswordFormManager::IsCredentialAPISave() const {
+ return observed_not_web_form_digest_ && !IsHttpAuth();
+}
+
+PasswordForm::Scheme PasswordFormManager::GetScheme() const {
+ return observed_not_web_form_digest_ ? observed_not_web_form_digest_->scheme
+ : PasswordForm::Scheme::kHtml;
+}
+
+void PasswordFormManager::ProcessServerPredictions(
+ const std::map<FormSignature, FormPredictions>& predictions) {
+ if (parser_.predictions()) {
+ // This method might be called multiple times. No need to process
+ // predictions again.
return;
- if (!driver)
+ }
+ FormSignature observed_form_signature =
+ CalculateFormSignature(observed_form_);
+ auto it = predictions.find(observed_form_signature);
+ if (it == predictions.end())
return;
- SendFillInformationToRenderer(client_, driver.get(), IsBlacklisted(),
- observed_form_, best_matches_,
- form_fetcher_->GetFederatedMatches(),
- preferred_match_, GetMetricsRecorder());
+
+ ReportTimeBetweenStoreAndServerUMA();
+ parser_.set_predictions(it->second);
+ Fill();
}
-void PasswordFormManager::ProcessLoginPrompt() {
- DCHECK_NE(PasswordForm::Scheme::kHtml, observed_form_.scheme);
- if (!preferred_match_) {
- DCHECK(best_matches_.empty());
- metrics_recorder_->RecordFillEvent(
- PasswordFormMetricsRecorder::kManagerFillEventNoCredential);
+void PasswordFormManager::Fill() {
+ if (!driver_)
return;
+
+ waiting_for_server_predictions_ = false;
+
+ if (form_fetcher_->GetState() == FormFetcher::State::WAITING)
+ return;
+
+ if (autofills_left_ <= 0)
+ return;
+ autofills_left_--;
+
+ // There are additional signals (server-side data) and parse results in
+ // filling and saving mode might be different so it is better not to cache
+ // parse result, but to parse each time again.
+ std::unique_ptr<PasswordForm> observed_password_form =
+ ParseFormAndMakeLogging(observed_form_, FormDataParser::Mode::kFilling);
+ RecordMetricOnReadonly(parser_.readonly_status(), !!observed_password_form,
+ FormDataParser::Mode::kFilling);
+ if (!observed_password_form)
+ return;
+
+ RecordMetricOnCompareParsingResult(*observed_password_form);
+
+ if (observed_password_form->is_new_password_reliable && !IsBlacklisted()) {
+#if defined(OS_IOS)
+ driver_->FormEligibleForGenerationFound(
+ {/*form_name*/ observed_password_form->form_data.name,
+ /*new_password_element*/ observed_password_form->new_password_element,
+ /*confirmation_password_element*/
+ observed_password_form->confirmation_password_element});
+#else
+ driver_->FormEligibleForGenerationFound(
+ {/*new_password_renderer_id*/
+ observed_password_form->new_password_element_renderer_id,
+ /*confirmation_password_renderer_id*/
+ observed_password_form->confirmation_password_element_renderer_id});
+#endif
}
- metrics_recorder_->SetManagerAction(
- PasswordFormMetricsRecorder::kManagerActionAutofilled);
- metrics_recorder_->RecordFillEvent(
- PasswordFormMetricsRecorder::kManagerFillEventAutofilled);
+#if defined(OS_IOS)
+ // Filling on username first flow is not supported on iOS.
+ if (observed_password_form->IsSingleUsername())
+ return;
+#endif
+
+ SendFillInformationToRenderer(client_, driver_.get(),
+ *observed_password_form.get(), best_matches_,
+ form_fetcher_->GetFederatedMatches(),
+ preferred_match_, metrics_recorder_.get());
}
-void PasswordFormManager::ProcessUpdate() {
- DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
- DCHECK(preferred_match_ || !pending_credentials_.federation_origin.opaque());
- // If we're doing an Update, we either autofilled correctly and need to
- // update the stats, or the user typed in a new password for autofilled
- // username, or the user selected one of the non-preferred matches,
- // thus requiring a swap of preferred bits.
- DCHECK(!IsNewLogin() && pending_credentials_.preferred);
- DCHECK(!client_->IsIncognito());
+void PasswordFormManager::FillForm(const FormData& observed_form) {
+ uint32_t differences_bitmask =
+ FindFormsDifferences(observed_form_, observed_form);
+ metrics_recorder_->RecordFormChangeBitmask(differences_bitmask);
- password_manager_util::UpdateMetadataForUsage(&pending_credentials_);
+ if (differences_bitmask)
+ observed_form_ = observed_form;
- base::RecordAction(
- base::UserMetricsAction("PasswordManager_LoginFollowingAutofill"));
+ if (!waiting_for_server_predictions_)
+ Fill();
+}
- // Check to see if this form is a candidate for password generation.
- // Do not send votes on change password forms, since they were already sent in
- // Update() method.
- if (!observed_form_.IsPossibleChangePasswordForm()) {
- votes_uploader_.SendVoteOnCredentialsReuse(
- observed_form_.form_data, *submitted_form_, &pending_credentials_);
+void PasswordFormManager::OnGeneratedPasswordAccepted(
+ FormData form_data,
+ uint32_t generation_element_id,
+ const base::string16& password) {
+ // Find the generating element to update its value. The parser needs a non
+ // empty value.
+ auto it = std::find_if(form_data.fields.begin(), form_data.fields.end(),
+ [generation_element_id](const auto& field_data) {
+ return generation_element_id ==
+ field_data.unique_renderer_id;
+ });
+ DCHECK(it != form_data.fields.end());
+ it->value = password;
+ std::unique_ptr<PasswordForm> parsed_form =
+ ParseFormAndMakeLogging(form_data, FormDataParser::Mode::kSaving);
+ if (!parsed_form) {
+ // Create a password form with a minimum data.
+ parsed_form.reset(new PasswordForm);
+ parsed_form->origin = form_data.url;
+ parsed_form->signon_realm = GetSignonRealm(form_data.url);
}
- if (IsPasswordUpdate()) {
- votes_uploader_.UploadPasswordVote(
- *submitted_form_, *submitted_form_, autofill::NEW_PASSWORD,
- autofill::FormStructure(pending_credentials_.form_data)
- .FormSignatureAsStr());
+ parsed_form->password_value = password;
+ generation_state_ =
+ std::make_unique<PasswordGenerationState>(form_saver_.get(), client_);
+ generation_state_->GeneratedPasswordAccepted(*parsed_form, *form_fetcher_,
+ driver_);
+}
+
+PasswordFormManager::PasswordFormManager(
+ PasswordManagerClient* client,
+ FormFetcher* form_fetcher,
+ std::unique_ptr<FormSaver> form_saver,
+ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder,
+ PasswordStore::FormDigest form_digest)
+ : client_(client),
+ metrics_recorder_(metrics_recorder),
+ owned_form_fetcher_(form_fetcher
+ ? nullptr
+ : std::make_unique<FormFetcherImpl>(
+ std::move(form_digest),
+ client_,
+ true /* should_migrate_http_passwords */)),
+ form_fetcher_(form_fetcher ? form_fetcher : owned_form_fetcher_.get()),
+ form_saver_(std::move(form_saver)),
+ // TODO(https://crbug.com/831123): set correctly
+ // |is_possible_change_password_form| in |votes_uploader_| constructor
+ votes_uploader_(client, false /* is_possible_change_password_form */) {
+ if (!metrics_recorder_) {
+ metrics_recorder_ = base::MakeRefCounted<PasswordFormMetricsRecorder>(
+ client_->IsMainFrameSecure(), client_->GetUkmSourceId());
}
+}
- if (pending_credentials_.times_used == 1) {
- votes_uploader_.UploadFirstLoginVotes(best_matches_, pending_credentials_,
- *submitted_form_);
+void PasswordFormManager::RecordMetricOnCompareParsingResult(
+ const PasswordForm& parsed_form) {
+ bool same =
+ parsed_form.username_element == old_parsing_result_.username_element &&
+ parsed_form.password_element == old_parsing_result_.password_element &&
+ parsed_form.new_password_element ==
+ old_parsing_result_.new_password_element &&
+ parsed_form.confirmation_password_element ==
+ old_parsing_result_.confirmation_password_element;
+ if (same) {
+ metrics_recorder_->RecordParsingsComparisonResult(
+ PasswordFormMetricsRecorder::ParsingComparisonResult::kSame);
+ return;
+ }
+
+ // In the old parsing for fields with empty name, placeholders are used. The
+ // reason for this is that an empty "..._element" attribute in a PasswordForm
+ // means that no corresponding input element exists. The new form parsing sets
+ // empty string in that case because renderer ids are used instead of element
+ // names for fields identification. Hence in case of anonymous fields, the
+ // results will be different for sure. Compare to placeholders and record this
+ // case.
+ if (old_parsing_result_.username_element ==
+ base::ASCIIToUTF16("anonymous_username") ||
+ old_parsing_result_.password_element ==
+ base::ASCIIToUTF16("anonymous_password") ||
+ old_parsing_result_.new_password_element ==
+ base::ASCIIToUTF16("anonymous_new_password") ||
+ old_parsing_result_.confirmation_password_element ==
+ base::ASCIIToUTF16("anonymous_confirmation_password")) {
+ metrics_recorder_->RecordParsingsComparisonResult(
+ PasswordFormMetricsRecorder::ParsingComparisonResult::kAnonymousFields);
+ } else {
+ metrics_recorder_->RecordParsingsComparisonResult(
+ PasswordFormMetricsRecorder::ParsingComparisonResult::kDifferent);
}
}
+void PasswordFormManager::RecordMetricOnReadonly(
+ FormDataParser::ReadonlyPasswordFields readonly_status,
+ bool parsing_successful,
+ FormDataParser::Mode mode) {
+ // The reported value is combined of the |readonly_status| shifted by one bit
+ // to the left, and the success bit put in the least significant bit. Note:
+ // C++ guarantees that bool->int conversions map false to 0 and true to 1.
+ uint64_t value = static_cast<uint64_t>(parsing_successful) +
+ (static_cast<uint64_t>(readonly_status) << 1);
+ switch (mode) {
+ case FormDataParser::Mode::kSaving:
+ metrics_recorder_->RecordReadonlyWhenSaving(value);
+ break;
+ case FormDataParser::Mode::kFilling:
+ metrics_recorder_->RecordReadonlyWhenFilling(value);
+ break;
+ }
+}
+
+void PasswordFormManager::ReportTimeBetweenStoreAndServerUMA() {
+ if (!received_stored_credentials_time_.is_null()) {
+ UMA_HISTOGRAM_TIMES("PasswordManager.TimeBetweenStoreAndServer",
+ TimeTicks::Now() - received_stored_credentials_time_);
+ }
+}
+
+// TODO(https://crbug.com/831123): move this function to the proper place
+// corresponding to its place in the header.
void PasswordFormManager::CreatePendingCredentials() {
- DCHECK(submitted_form_);
- ValueElementPair password_to_save(PasswordToSave(*submitted_form_));
+ DCHECK(is_submitted_);
+ // TODO(https://crbug.com/831123): Process correctly the case when saved
+ // credentials are not received from the store yet.
+ if (!parsed_submitted_form_)
+ return;
// Calculate the user's action based on existing matches and the submitted
// form.
- metrics_recorder_->CalculateUserAction(best_matches_, *submitted_form_);
+ metrics_recorder_->CalculateUserAction(best_matches_,
+ *parsed_submitted_form_);
+ // This function might be called multiple times so set variables that are
+ // changed in this function to initial states.
+ is_new_login_ = true;
+ SetPasswordOverridden(false);
+
+ ValueElementPair password_to_save(PasswordToSave(*parsed_submitted_form_));
// Look for the actually submitted credentials in the list of previously saved
// credentials that were available to autofilling.
- const PasswordForm* saved_form = FindBestSavedMatch(submitted_form_.get());
+ const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating(
+ *parsed_submitted_form_, best_matches_);
if (saved_form) {
- // The user signed in with a login we autofilled.
+ // A similar credential exists in the store already.
pending_credentials_ = *saved_form;
SetPasswordOverridden(pending_credentials_.password_value !=
password_to_save.first);
+ // If the autofilled credentials were a PSL match, store a copy with the
+ // current origin and signon realm. This ensures that on the next visit, a
+ // precise match is found.
+ is_new_login_ = pending_credentials_.is_public_suffix_match;
- if (pending_credentials_.is_public_suffix_match) {
- // If the autofilled credentials were a PSL match or credentials stored
- // from Android apps, store a copy with the current origin and signon
- // realm. This ensures that on the next visit, a precise match is found.
- is_new_login_ = true;
-
+ if (is_new_login_) {
// Update credential to reflect that it has been used for submission.
// If this isn't updated, then password generation uploads are off for
// sites where PSL matching is required to fill the login form, as two
@@ -642,83 +922,22 @@ void PasswordFormManager::CreatePendingCredentials() {
password_manager_util::UpdateMetadataForUsage(&pending_credentials_);
// Update |pending_credentials_| in order to be able correctly save it.
- pending_credentials_.origin = submitted_form_->origin;
- pending_credentials_.signon_realm = submitted_form_->signon_realm;
-
- // Normally, the copy of the PSL matched credentials, adapted for the
- // current domain, is saved automatically without asking the user, because
- // the copy likely represents the same account, i.e., the one for which
- // the user already agreed to store a password.
- //
- // However, if the user changes the suggested password, it might indicate
- // that the autofilled credentials and |submitted_form_|
- // actually correspond to two different accounts (see
- // http://crbug.com/385619). In that case the user should be asked again
- // before saving the password. This is ensured by setting
- // |password_overriden_| on |pending_credentials_| to false.
- //
- // There is still the edge case when the autofilled credentials represent
- // the same account as |submitted_form_| but the stored password
- // was out of date. In that case, the user just had to manually enter the
- // new password, which is now in |submitted_form_|. The best
- // thing would be to save automatically, and also update the original
- // credentials. However, we have no way to tell if this is the case.
- // This will likely happen infrequently, and the inconvenience put on the
- // user by asking them is not significant, so we are fine with asking
- // here again.
- if (password_overridden_) {
- pending_credentials_.is_public_suffix_match = false;
- SetPasswordOverridden(false);
- }
- } else { // Not a PSL match but a match of an already stored credential.
- is_new_login_ = false;
- }
- } else if (!best_matches_.empty() &&
- submitted_form_->type != autofill::PasswordForm::Type::kApi &&
- submitted_form_->username_value.empty()) {
- // This branch deals with the case that the submitted form has no username
- // element and needs to decide whether to offer to update any credentials.
- // In that case, the user can select any previously stored credential as
- // the one to update, but we still try to find the best candidate.
-
- // Find the best candidate to select by default in the password update
- // bubble. If no best candidate is found, any one can be offered.
- const PasswordForm* best_update_match =
- FindBestMatchForUpdatePassword(submitted_form_->password_value);
-
- // A retry password form is one that consists of only an "old password"
- // field, i.e. one that is not a "new password".
- retry_password_form_password_update_ =
- submitted_form_->username_value.empty() &&
- submitted_form_->new_password_value.empty();
-
- is_new_login_ = false;
- if (best_update_match) {
- // Chose |best_update_match| to be updated.
- pending_credentials_ = *best_update_match;
- } else if (HasGeneratedPassword()) {
- // If a password was generated and we didn't find a match, we have to save
- // it in a separate entry since we have to store it but we don't know
- // where.
- CreatePendingCredentialsForNewCredentials(password_to_save.second);
- is_new_login_ = true;
- } else {
- // We don't have a good candidate to choose as the default credential for
- // the update bubble and the user has to pick one.
- // We set |pending_credentials_| to the bare minimum, which is the correct
- // origin.
- pending_credentials_.origin = submitted_form_->origin;
+ pending_credentials_.origin = parsed_submitted_form_->origin;
+ pending_credentials_.signon_realm = parsed_submitted_form_->signon_realm;
+ pending_credentials_.action = parsed_submitted_form_->action;
}
} else {
is_new_login_ = true;
// No stored credentials can be matched to the submitted form. Offer to
// save new credentials.
- CreatePendingCredentialsForNewCredentials(password_to_save.second);
+ CreatePendingCredentialsForNewCredentials(*parsed_submitted_form_,
+ password_to_save.second);
// Generate username correction votes.
bool username_correction_found =
votes_uploader_.FindCorrectedUsernameElement(
- best_matches_, not_best_matches_, submitted_form_->username_value,
- submitted_form_->password_value);
+ form_fetcher_->GetAllRelevantMatches(),
+ parsed_submitted_form_->username_value,
+ parsed_submitted_form_->password_value);
UMA_HISTOGRAM_BOOLEAN("PasswordManager.UsernameCorrectionFound",
username_correction_found);
if (username_correction_found) {
@@ -727,100 +946,59 @@ void PasswordFormManager::CreatePendingCredentials() {
kCorrectedUsernameInForm);
}
}
-
- if (!IsValidAndroidFacetURI(pending_credentials_.signon_realm))
- pending_credentials_.action = submitted_form_->action;
-
- pending_credentials_.password_value = password_to_save.first;
- pending_credentials_.preferred = submitted_form_->preferred;
+ pending_credentials_.password_value =
+ HasGeneratedPassword() ? generation_state_->generated_password()
+ : password_to_save.first;
+ pending_credentials_.preferred = true;
+ pending_credentials_.date_last_used = base::Time::Now();
pending_credentials_.form_has_autofilled_value =
- submitted_form_->form_has_autofilled_value;
+ parsed_submitted_form_->form_has_autofilled_value;
pending_credentials_.all_possible_passwords =
- submitted_form_->all_possible_passwords;
- CopyFieldPropertiesMasks(*submitted_form_, &pending_credentials_);
+ parsed_submitted_form_->all_possible_passwords;
+ CopyFieldPropertiesMasks(submitted_form_, &pending_credentials_.form_data);
// If we're dealing with an API-driven provisionally saved form, then take
// the server provided values. We don't do this for non-API forms, as
// those will never have those members set.
- if (submitted_form_->type == autofill::PasswordForm::Type::kApi) {
- pending_credentials_.skip_zero_click = submitted_form_->skip_zero_click;
- pending_credentials_.display_name = submitted_form_->display_name;
- pending_credentials_.federation_origin = submitted_form_->federation_origin;
- pending_credentials_.icon_url = submitted_form_->icon_url;
+ if (parsed_submitted_form_->type == PasswordForm::Type::kApi) {
+ pending_credentials_.skip_zero_click =
+ parsed_submitted_form_->skip_zero_click;
+ pending_credentials_.display_name = parsed_submitted_form_->display_name;
+ pending_credentials_.federation_origin =
+ parsed_submitted_form_->federation_origin;
+ pending_credentials_.icon_url = parsed_submitted_form_->icon_url;
// It's important to override |signon_realm| for federated credentials
// because it has format "federation://" + origin_host + "/" +
// federation_host
- pending_credentials_.signon_realm = submitted_form_->signon_realm;
+ pending_credentials_.signon_realm = parsed_submitted_form_->signon_realm;
}
if (HasGeneratedPassword())
pending_credentials_.type = PasswordForm::Type::kGenerated;
}
-const PasswordForm* PasswordFormManager::FindBestMatchForUpdatePassword(
- const base::string16& password) const {
- // This function is called for forms that do not contain a username field.
- // This means that we cannot update credentials based on a matching username
- // and that we may need to show an update prompt.
- if (best_matches_.size() == 1 && !HasGeneratedPassword()) {
- // In case the submitted form contained no username but a password, and if
- // the user has only one credential stored, return it as the one that should
- // be updated.
- return best_matches_.begin()->second;
- }
- if (password.empty())
- return nullptr;
-
- // Return any existing credential that has the same |password| saved already.
- for (const auto& key_value : best_matches_) {
- if (key_value.second->password_value == password)
- return key_value.second;
- }
- return nullptr;
-}
-
-const PasswordForm* PasswordFormManager::FindBestSavedMatch(
- const PasswordForm* submitted_form) const {
- if (!submitted_form->federation_origin.opaque())
- return nullptr;
-
- // Return form with matching |username_value|.
- auto it = best_matches_.find(submitted_form->username_value);
- if (it != best_matches_.end())
- return it->second;
-
- // Match Credential API forms only by username. Stop here if nothing was found
- // above.
- if (submitted_form->type == autofill::PasswordForm::Type::kApi)
- return nullptr;
-
- // Verify that the submitted form has no username and no "new password"
- // and bail out with a nullptr otherwise.
- bool submitted_form_has_username = !submitted_form->username_value.empty();
- bool submitted_form_has_new_password_element =
- !submitted_form->new_password_value.empty();
- if (submitted_form_has_username || submitted_form_has_new_password_element)
- return nullptr;
-
- // At this line we are certain that the submitted form contains only a
- // password field that is not a "new password". Now we can check whether we
- // have a match by password of an already saved credential.
- for (const auto& stored_match : best_matches_) {
- if (stored_match.second->password_value == submitted_form->password_value)
- return stored_match.second;
- }
- return nullptr;
-}
-
void PasswordFormManager::CreatePendingCredentialsForNewCredentials(
+ const PasswordForm& submitted_password_form,
const base::string16& password_element) {
- pending_credentials_ = observed_form_;
- pending_credentials_.username_element = submitted_form_->username_element;
- pending_credentials_.username_value = submitted_form_->username_value;
+ if (IsHttpAuth() || IsCredentialAPISave()) {
+ pending_credentials_ = submitted_password_form;
+ return;
+ }
+
+ // TODO(https://crbug.com/831123): Replace parsing of the observed form with
+ // usage of already parsed submitted form.
+ std::unique_ptr<PasswordForm> parsed_observed_form =
+ ParseFormAndMakeLogging(observed_form_, FormDataParser::Mode::kFilling);
+ if (!parsed_observed_form)
+ return;
+ pending_credentials_ = *parsed_observed_form;
+ pending_credentials_.username_element =
+ submitted_password_form.username_element;
+ pending_credentials_.username_value = submitted_password_form.username_value;
pending_credentials_.all_possible_usernames =
- submitted_form_->all_possible_usernames;
+ submitted_password_form.all_possible_usernames;
pending_credentials_.all_possible_passwords =
- submitted_form_->all_possible_passwords;
+ submitted_password_form.all_possible_passwords;
// The password value will be filled in later, remove any garbage for now.
pending_credentials_.password_value.clear();
@@ -831,235 +1009,149 @@ void PasswordFormManager::CreatePendingCredentialsForNewCredentials(
pending_credentials_.new_password_element.clear();
}
-void PasswordFormManager::OnNopeUpdateClicked() {
- votes_uploader_.UploadPasswordVote(observed_form_, *submitted_form_,
- autofill::NOT_NEW_PASSWORD, std::string());
-}
-
-void PasswordFormManager::OnNeverClicked() {
- votes_uploader_.UploadPasswordVote(pending_credentials_, *submitted_form_,
- autofill::UNKNOWN_TYPE, std::string());
- PermanentlyBlacklist();
-}
-
-void PasswordFormManager::OnNoInteraction(bool is_update) {
- if (is_update) {
- votes_uploader_.UploadPasswordVote(observed_form_, *submitted_form_,
- autofill::PROBABLY_NEW_PASSWORD,
- std::string());
- } else {
- votes_uploader_.UploadPasswordVote(pending_credentials_, *submitted_form_,
- autofill::UNKNOWN_TYPE, std::string());
- }
-}
-
-void PasswordFormManager::OnPasswordsRevealed() {
- votes_uploader_.set_has_passwords_revealed_vote(true);
-}
-
-bool PasswordFormManager::HasGeneratedPassword() const {
- return generation_state_ && generation_state_->HasGeneratedPassword();
-}
-
-void PasswordFormManager::SetGenerationElement(
- const base::string16& generation_element) {
- votes_uploader_.set_generation_element(generation_element);
-}
-
-void PasswordFormManager::SetGenerationPopupWasShown(
- bool generation_popup_was_shown,
- bool is_manual_generation) {
- votes_uploader_.set_generation_popup_was_shown(generation_popup_was_shown);
- votes_uploader_.set_is_manual_generation(is_manual_generation);
- metrics_recorder_->SetPasswordGenerationPopupShown(generation_popup_was_shown,
- is_manual_generation);
-}
-
-bool PasswordFormManager::IsPasswordUpdate() const {
- return (!GetBestMatches().empty() &&
- IsPossibleChangePasswordFormWithoutUsername()) ||
- password_overridden_ || retry_password_form_password_update_;
-}
-
-void PasswordFormManager::LogSubmitPassed() {
- metrics_recorder_->LogSubmitPassed();
-}
-
-void PasswordFormManager::LogSubmitFailed() {
- metrics_recorder_->LogSubmitFailed();
-}
-
-void PasswordFormManager::MarkGenerationAvailable() {
- metrics_recorder_->MarkGenerationAvailable();
-}
-
-bool PasswordFormManager::IsPossibleChangePasswordFormWithoutUsername() const {
- return is_possible_change_password_form_without_username_;
-}
-
-std::vector<base::WeakPtr<PasswordManagerDriver>>
-PasswordFormManager::GetDrivers() const {
- return drivers_;
-}
-
-const PasswordForm* PasswordFormManager::GetSubmittedForm() const {
- return submitted_form_.get();
-}
-
-const std::map<base::string16, const autofill::PasswordForm*>&
-PasswordFormManager::GetBestMatches() const {
- return best_matches_;
-}
-
-std::vector<const autofill::PasswordForm*>
-PasswordFormManager::GetFederatedMatches() const {
- return form_fetcher_->GetFederatedMatches();
-}
-
-const GURL& PasswordFormManager::GetOrigin() const {
- return observed_form_.origin;
-}
-
-const autofill::PasswordForm& PasswordFormManager::GetPendingCredentials()
- const {
- return pending_credentials_;
-}
-
-metrics_util::CredentialSourceType PasswordFormManager::GetCredentialSource() {
- return metrics_util::CredentialSourceType::kPasswordManager;
-}
-
-PasswordFormMetricsRecorder* PasswordFormManager::GetMetricsRecorder() {
- return metrics_recorder_.get();
-}
+void PasswordFormManager::ProcessUpdate() {
+ DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
+ DCHECK(preferred_match_ || pending_credentials_.IsFederatedCredential());
+ // If we're doing an Update, we either autofilled correctly and need to
+ // update the stats, or the user typed in a new password for autofilled
+ // username, or the user selected one of the non-preferred matches,
+ // thus requiring a swap of preferred bits.
+ DCHECK(pending_credentials_.preferred);
+ DCHECK(!client_->IsIncognito());
+ DCHECK(parsed_submitted_form_);
-base::span<const autofill::PasswordForm* const>
-PasswordFormManager::GetBlacklistedMatches() const {
- return base::make_span(blacklisted_matches_);
-}
+ password_manager_util::UpdateMetadataForUsage(&pending_credentials_);
-base::span<const InteractionsStats> PasswordFormManager::GetInteractionsStats()
- const {
- return base::make_span(form_fetcher_->GetInteractionsStats());
-}
+ base::RecordAction(
+ base::UserMetricsAction("PasswordManager_LoginFollowingAutofill"));
-bool PasswordFormManager::IsBlacklisted() const {
- DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
- return !blacklisted_matches_.empty();
-}
+ // Check to see if this form is a candidate for password generation.
+ // Do not send votes on change password forms, since they were already sent in
+ // Update() method.
+ if (!parsed_submitted_form_->IsPossibleChangePasswordForm()) {
+ votes_uploader_.SendVoteOnCredentialsReuse(
+ observed_form_, *parsed_submitted_form_, &pending_credentials_);
+ }
+ if (IsPasswordUpdate()) {
+ votes_uploader_.UploadPasswordVote(
+ *parsed_submitted_form_, *parsed_submitted_form_,
+ autofill::NEW_PASSWORD,
+ autofill::FormStructure(pending_credentials_.form_data)
+ .FormSignatureAsStr());
+ }
-void PasswordFormManager::ResetStoredMatches() {
- preferred_match_ = nullptr;
- best_matches_.clear();
- not_best_matches_.clear();
- blacklisted_matches_.clear();
- new_blacklisted_.reset();
+ if (pending_credentials_.times_used == 1) {
+ votes_uploader_.UploadFirstLoginVotes(best_matches_, pending_credentials_,
+ *parsed_submitted_form_);
+ }
}
-void PasswordFormManager::GrabFetcher(std::unique_ptr<FormFetcher> fetcher) {
- DCHECK(!owned_form_fetcher_);
- owned_form_fetcher_ = std::move(fetcher);
- if (owned_form_fetcher_.get() == form_fetcher_)
+void PasswordFormManager::FillHttpAuth() {
+ DCHECK(IsHttpAuth());
+ if (!preferred_match_)
return;
- ResetStoredMatches();
- form_fetcher_->RemoveConsumer(this);
- form_fetcher_ = owned_form_fetcher_.get();
- form_fetcher_->AddConsumer(this);
+ client_->AutofillHttpAuth(*preferred_match_, this);
}
-std::unique_ptr<PasswordFormManager> PasswordFormManager::Clone() {
- // Fetcher is cloned to avoid re-fetching data from PasswordStore.
- std::unique_ptr<FormFetcher> fetcher = form_fetcher_->Clone();
-
- // Some data is filled through the constructor. No PasswordManagerDriver is
- // needed, because the UI does not need any functionality related to the
- // renderer process, to which the driver serves as an interface. The full
- // |observed_form_| needs to be copied, because it is used to created the
- // blacklisting entry if needed.
- auto result = std::make_unique<PasswordFormManager>(
- password_manager_, client_, base::WeakPtr<PasswordManagerDriver>(),
- observed_form_, form_saver_->Clone(), fetcher.get());
- result->Init(metrics_recorder_);
-
- // The constructor only can take a weak pointer to the fetcher, so moving the
- // owning one needs to happen explicitly.
- result->GrabFetcher(std::move(fetcher));
+std::unique_ptr<PasswordForm> PasswordFormManager::ParseFormAndMakeLogging(
+ const FormData& form,
+ FormDataParser::Mode mode) {
+ std::unique_ptr<PasswordForm> password_form = parser_.Parse(form, mode);
- // |best_matches_| are skipped, because those are regenerated from the new
- // fetcher automatically.
+ if (password_manager_util::IsLoggingActive(client_)) {
+ BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
+ logger.LogFormData(Logger::STRING_FORM_PARSING_INPUT, form);
+ if (password_form)
+ logger.LogPasswordForm(Logger::STRING_FORM_PARSING_OUTPUT,
+ *password_form);
+ }
+ return password_form;
+}
- // These data members all satisfy:
- // (1) They could have been changed by |*this| between its construction and
- // calling Clone().
- // (2) They are potentially used in the clone as the clone is used in the UI
- // code.
- // (3) They are not changed during OnFetchCompleted, triggered at some
- // point
- // by the cloned FormFetcher.
- if (submitted_form_)
- result->submitted_form_ = std::make_unique<PasswordForm>(*submitted_form_);
+void PasswordFormManager::PresaveGeneratedPasswordInternal(
+ const FormData& form,
+ const base::string16& generated_password) {
+ std::unique_ptr<PasswordForm> parsed_form =
+ ParseFormAndMakeLogging(form, FormDataParser::Mode::kSaving);
+
+ if (!parsed_form) {
+ // Create a password form with a minimum data.
+ parsed_form.reset(new PasswordForm());
+ parsed_form->origin = form.url;
+ parsed_form->signon_realm = GetSignonRealm(form.url);
+ }
- if (generation_state_) {
- result->generation_state_ =
- generation_state_->Clone(result->form_saver_.get());
+ if (!HasGeneratedPassword()) {
+ generation_state_ =
+ std::make_unique<PasswordGenerationState>(form_saver_.get(), client_);
+ votes_uploader_.set_generated_password_changed(false);
+ metrics_recorder_->SetGeneratedPasswordStatus(
+ PasswordFormMetricsRecorder::GeneratedPasswordStatus::
+ kPasswordAccepted);
+ } else {
+ // If the password is already generated and a new value to presave differs
+ // from the presaved one, then mark that the generated password was changed.
+ // If a user recovers the original generated password, it will be recorded
+ // as a password change.
+ if (generation_state_->generated_password() != generated_password) {
+ votes_uploader_.set_generated_password_changed(true);
+ metrics_recorder_->SetGeneratedPasswordStatus(
+ PasswordFormMetricsRecorder::GeneratedPasswordStatus::
+ kPasswordEdited);
+ }
}
+ votes_uploader_.set_has_generated_password(true);
- result->pending_credentials_ = pending_credentials_;
- result->is_new_login_ = is_new_login_;
- result->password_overridden_ = password_overridden_;
- result->retry_password_form_password_update_ =
- retry_password_form_password_update_;
- result->is_possible_change_password_form_without_username_ =
- is_possible_change_password_form_without_username_;
- result->votes_uploader_ = votes_uploader_;
+ // Set |password_value| to the generated password in order to ensure that the
+ // generated password is saved.
+ parsed_form->password_value = generated_password;
- return result;
+ generation_state_->PresaveGeneratedPassword(
+ std::move(*parsed_form), form_fetcher_->GetAllRelevantMatches());
}
-std::vector<PasswordForm> PasswordFormManager::FindOtherCredentialsToUpdate()
- const {
- std::vector<autofill::PasswordForm> credentials_to_update;
- if (!pending_credentials_.federation_origin.opaque())
- return credentials_to_update;
-
- auto updated_password_it =
- best_matches_.find(pending_credentials_.username_value);
- DCHECK(best_matches_.end() != updated_password_it);
- const base::string16& old_password =
- updated_password_it->second->password_value;
- for (auto* not_best_match : not_best_matches_) {
- if (not_best_match->username_value == pending_credentials_.username_value &&
- not_best_match->password_value == old_password) {
- credentials_to_update.push_back(*not_best_match);
- credentials_to_update.back().password_value =
- pending_credentials_.password_value;
- }
+void PasswordFormManager::CalculateFillingAssistanceMetric(
+ const FormData& submitted_form) {
+ // TODO(https://crbug.com/918846): implement collecting all necessary data on
+ // iOS.
+#if not defined(OS_IOS)
+ std::set<base::string16> saved_usernames;
+ std::set<base::string16> saved_passwords;
+
+ for (auto* saved_form : form_fetcher_->GetNonFederatedMatches()) {
+ saved_usernames.insert(saved_form->username_value);
+ saved_passwords.insert(saved_form->password_value);
}
- return credentials_to_update;
+ // Saved credentials might have empty usernames which are not interesting for
+ // filling assistance metric.
+ saved_usernames.erase(base::string16());
+
+ metrics_recorder_->CalculateFillingAssistanceMetric(
+ submitted_form, saved_usernames, saved_passwords, IsBlacklisted(),
+ form_fetcher_->GetInteractionsStats());
+#endif
}
void PasswordFormManager::SavePendingToStore(bool update) {
- std::vector<const autofill::PasswordForm*> matches;
- for (const auto& match : best_matches_)
- matches.push_back(match.second);
- matches.insert(matches.end(), not_best_matches_.begin(),
- not_best_matches_.end());
+ const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating(
+ *parsed_submitted_form_, best_matches_);
+ if ((update || password_overridden_) &&
+ !pending_credentials_.IsFederatedCredential()) {
+ DCHECK(saved_form);
+ }
+ base::string16 old_password =
+ saved_form ? saved_form->password_value : base::string16();
if (HasGeneratedPassword()) {
- generation_state_->CommitGeneratedPassword(pending_credentials_, matches,
- base::string16());
+ generation_state_->CommitGeneratedPassword(
+ pending_credentials_, form_fetcher_->GetAllRelevantMatches(),
+ old_password);
} else if (update) {
- base::string16 old_password;
- if (!pending_credentials_.IsFederatedCredential()) {
- auto updated_password_it =
- best_matches_.find(pending_credentials_.username_value);
- if (updated_password_it != best_matches_.end())
- old_password = updated_password_it->second->password_value;
- }
-
- form_saver_->Update(pending_credentials_, matches, old_password);
+ form_saver_->Update(pending_credentials_,
+ form_fetcher_->GetAllRelevantMatches(), old_password);
} else {
- form_saver_->Save(pending_credentials_, matches, base::string16());
+ form_saver_->Save(pending_credentials_,
+ form_fetcher_->GetAllRelevantMatches(), old_password);
}
}
diff --git a/chromium/components/password_manager/core/browser/password_form_manager.h b/chromium/components/password_manager/core/browser/password_form_manager.h
index 8f31381d110..dc792f895a9 100644
--- a/chromium/components/password_manager/core/browser/password_form_manager.h
+++ b/chromium/components/password_manager/core/browser/password_form_manager.h
@@ -1,199 +1,135 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_MANAGER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_MANAGER_H_
-#include <stdint.h>
-
#include <map>
#include <memory>
-#include <string>
#include <vector>
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "build/build_config.h"
-#include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/form_structure.h"
-#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/signatures_util.h"
#include "components/password_manager/core/browser/form_fetcher.h"
+#include "components/password_manager/core/browser/form_parsing/form_parser.h"
+#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_form_metrics_recorder.h"
#include "components/password_manager/core/browser/password_form_user_action.h"
-#include "components/password_manager/core/browser/password_manager_driver.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/votes_uploader.h"
-using autofill::FormData;
-using autofill::FormStructure;
-
namespace password_manager {
class FormSaver;
+class PasswordFormMetricsRecorder;
class PasswordGenerationState;
-class PasswordManager;
class PasswordManagerClient;
+class PasswordManagerDriver;
-// This class helps with filling the observed form (both HTML and from HTTP
-// auth) and with saving/updating the stored information about it.
+// This class helps with filling the observed form and with saving/updating the
+// stored information about it. It is aimed to replace PasswordFormManager and
+// to be renamed in new Password Manager design. Details
+// go/new-cpm-design-refactoring.
class PasswordFormManager : public PasswordFormManagerInterface,
public FormFetcher::Consumer {
public:
- // |password_manager| owns |this|, |client| and |driver| serve to
- // communicate with embedder, |observed_form| is the associated form |this|
- // is managing, |form_saver| is used to save/update the form and
- // |form_fetcher| to get saved data about the form. |form_fetcher| must not be
- // destroyed before |this|.
- //
- // Make sure to also call Init before using |*this|.
- //
// TODO(crbug.com/621355): So far, |form_fetcher| can be null. In that case
// |this| creates an instance of it itself (meant for production code). Once
// the fetcher is shared between PasswordFormManager instances, it will be
- // required that |form_fetcher| is not null.
- PasswordFormManager(PasswordManager* password_manager,
- PasswordManagerClient* client,
- const base::WeakPtr<PasswordManagerDriver>& driver,
- const autofill::PasswordForm& observed_form,
- std::unique_ptr<FormSaver> form_saver,
- FormFetcher* form_fetcher);
- ~PasswordFormManager() override;
+ // required that |form_fetcher| is not null. |form_saver| is used to
+ // save/update the form. |metrics_recorder| records metrics for |*this|. If
+ // null a new instance will be created.
+ PasswordFormManager(
+ PasswordManagerClient* client,
+ const base::WeakPtr<PasswordManagerDriver>& driver,
+ const autofill::FormData& observed_form,
+ FormFetcher* form_fetcher,
+ std::unique_ptr<FormSaver> form_saver,
+ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder);
+
+ // Constructor for http authentication (aka basic authentication).
+ PasswordFormManager(PasswordManagerClient* client,
+ PasswordStore::FormDigest observed_http_auth_digest,
+ FormFetcher* form_fetcher,
+ std::unique_ptr<FormSaver> form_saver);
- // Call this after construction to complete initialization. If
- // |metrics_recorder| is null, a fresh one is created.
- void Init(scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder);
-
- // Flags describing the result of comparing two forms as performed by
- // DoesMatch. Individual flags are only relevant for HTML forms, but
- // RESULT_COMPLETE_MATCH will also be returned to indicate non-HTML forms
- // completely matching.
- // The ordering of these flags is important. Larger matches are more
- // preferred than lower matches. That is, since RESULT_FORM_NAME_MATCH
- // is greater than RESULT_ACTION_MATCH, a match of only names and not
- // actions will be preferred to one of actions and not names.
- enum MatchResultFlags {
- RESULT_NO_MATCH = 0,
- RESULT_ACTION_MATCH = 1 << 0,
- RESULT_FORM_NAME_MATCH = 1 << 1,
- RESULT_SIGNATURE_MATCH = 1 << 2,
- RESULT_ORIGINS_OR_FRAMES_MATCH = 1 << 3,
- RESULT_COMPLETE_MATCH = RESULT_ACTION_MATCH | RESULT_FORM_NAME_MATCH |
- RESULT_SIGNATURE_MATCH |
- RESULT_ORIGINS_OR_FRAMES_MATCH
- };
- // Use MatchResultMask to contain combinations of MatchResultFlags values.
- // It's a signed int rather than unsigned to avoid signed/unsigned mismatch
- // caused by the enum values implicitly converting to signed int.
- typedef int MatchResultMask;
+ ~PasswordFormManager() override;
// The upper limit on how many times Chrome will try to autofill the same
// form.
static constexpr int kMaxTimesAutofill = 5;
- // Chooses between the current and new password value which one to save. This
- // is whichever is non-empty, with the preference being given to the new one.
- static autofill::ValueElementPair PasswordToSave(
- const autofill::PasswordForm& form);
-
- // Compares basic data of |observed_form_| with |form| and returns how much
- // they match. The return value is a MatchResultMask bitmask.
- // |driver| is optional and if it's given it should be a driver that
- // corresponds to a frame from which |form| comes from.
- MatchResultMask DoesManage(
- const autofill::PasswordForm& form,
- const password_manager::PasswordManagerDriver* driver) const;
-
- // Used to determine what type the submitted form is for UMA stats.
- void SaveSubmittedFormTypeForMetrics(const autofill::PasswordForm& form);
-
- // PasswordFormManagerInterface:
- bool IsNewLogin() const override;
- FormFetcher* GetFormFetcher() override;
- bool IsPendingCredentialsPublicSuffixMatch() const override;
- bool IsPossibleChangePasswordFormWithoutUsername() const override;
- bool IsPasswordUpdate() const override;
- std::vector<base::WeakPtr<PasswordManagerDriver>> GetDrivers() const override;
- const autofill::PasswordForm* GetSubmittedForm() const override;
-
- // Through |driver|, supply the associated frame with appropriate information
- // (fill data, whether to allow password generation, etc.). If this is called
- // before |this| has data from the PasswordStore, the execution will be
- // delayed until the data arrives.
- void ProcessFrame(const base::WeakPtr<PasswordManagerDriver>& driver);
-
- // If the user has submitted observed_form_, provisionally hold on to
- // the submitted credentials until we are told by PasswordManager whether
- // or not the login was successful.
- void ProvisionallySave(const autofill::PasswordForm& credentials);
-
- // Call these if/when we know the form submission worked or failed.
- // These routines are used to update internal statistics ("ActionsTaken").
- void LogSubmitPassed();
- void LogSubmitFailed();
-
- // Called when generated password is accepted or changed by user.
- void PresaveGeneratedPassword(const autofill::PasswordForm& form) override;
-
- // Called when user removed a generated password.
- void PasswordNoLongerGenerated() override;
-
- // These functions are used to determine if this form has had it's password
- // auto generated by the browser.
- bool HasGeneratedPassword() const override;
-
- // These functions are used to determine if this form has generated password
- // changed by user.
- bool generated_password_changed() const {
- return votes_uploader_.generated_password_changed();
+ // Compares |observed_form_| with |form| and returns true if they are the
+ // same and if |driver| is the same as |driver_|.
+ bool DoesManage(const autofill::FormData& form,
+ const PasswordManagerDriver* driver) const;
+
+ // Returns whether the form identified by |form_renderer_id| and |driver|
+ // is managed by this password form manager. Don't call this on iOS.
+ bool DoesManageAccordingToRendererId(
+ uint32_t form_renderer_id,
+ const PasswordManagerDriver* driver) const;
+
+ // Check that |submitted_form_| is equal to |form| from the user point of
+ // view. It is used for detecting that a form is reappeared after navigation
+ // for success detection.
+ bool IsEqualToSubmittedForm(const autofill::FormData& form) const;
+
+ // If |submitted_form| is managed by *this (i.e. DoesManage returns true for
+ // |submitted_form| and |driver|) then saves |submitted_form| to
+ // |submitted_form_| field, sets |is_submitted| = true and returns true.
+ // Otherwise returns false.
+ bool ProvisionallySave(const autofill::FormData& submitted_form,
+ const PasswordManagerDriver* driver);
+
+ // If |submitted_form| is managed by *this then saves |submitted_form| to
+ // |submitted_form_| field, sets |is_submitted| = true and returns true.
+ // Otherwise returns false.
+ bool ProvisionallySaveHttpAuthForm(
+ const autofill::PasswordForm& submitted_form);
+
+ bool is_submitted() { return is_submitted_; }
+ void set_not_submitted() { is_submitted_ = false; }
+
+ void set_old_parsing_result(const autofill::PasswordForm& form) {
+ old_parsing_result_ = form;
}
- bool is_manual_generation() const {
- return votes_uploader_.is_manual_generation();
- }
- const base::string16& generation_element() const {
- return votes_uploader_.get_generation_element();
- }
- void SetGenerationElement(const base::string16& generation_element) override;
+ // Returns true if |*this| manages http authentication.
+ bool IsHttpAuth() const;
- bool get_generation_popup_was_shown() const {
- return votes_uploader_.get_generation_popup_was_shown();
- }
- void SetGenerationPopupWasShown(bool generation_popup_was_shown,
- bool is_manual_generation) override;
+ // Returns true if |*this| manages saving with Credentials API. This class is
+ // not used for filling with Credentials API.
+ bool IsCredentialAPISave() const;
- // Called if the user could generate a password for this form.
- void MarkGenerationAvailable();
+ // Returns scheme of the observed form or http authentication.
+ autofill::PasswordForm::Scheme GetScheme() const;
- const autofill::PasswordForm& observed_form() const { return observed_form_; }
- const autofill::PasswordForm* preferred_match() const {
- return preferred_match_;
- }
+ // Selects from |predictions| predictions that corresponds to
+ // |observed_form_|, initiates filling and stores predictions in
+ // |predictions_|.
+ void ProcessServerPredictions(
+ const std::map<autofill::FormSignature, FormPredictions>& predictions);
- FormSaver* form_saver() { return form_saver_.get(); }
+ // Sends fill data to the renderer.
+ void Fill();
- // Clears references to matches derived from the associated FormFetcher data.
- // After calling this, the PasswordFormManager holds no references to objects
- // owned by the associated FormFetcher. This does not cause removing |this| as
- // a consumer of |form_fetcher_|.
- void ResetStoredMatches();
+ // Sends fill data to the renderer to fill |observed_form|.
+ void FillForm(const autofill::FormData& observed_form);
- // Takes ownership of |fetcher|. If |fetcher| is different from the current
- // |form_fetcher_| then also resets matches stored from the old fetcher and
- // adds itself as a consumer of the new one.
- void GrabFetcher(std::unique_ptr<FormFetcher> fetcher);
-
- // Create a copy of |*this| which can be passed to the code handling
- // save-password related UI. This omits some parts of the internal data, so
- // the result is not identical to the original.
- // TODO(crbug.com/739366): Replace with translating one appropriate class into
- // another one.
- std::unique_ptr<PasswordFormManager> Clone();
+ // Sends the request to prefill the generated password or pops up an
+ // additional UI in case of possible override.
+ void OnGeneratedPasswordAccepted(autofill::FormData form_data,
+ uint32_t generation_element_id,
+ const base::string16& password);
// PasswordFormManagerForUI:
const GURL& GetOrigin() const override;
@@ -220,102 +156,160 @@ class PasswordFormManager : public PasswordFormManagerInterface,
void PermanentlyBlacklist() override;
void OnPasswordsRevealed() override;
+ // PasswordFormManagerInterface:
+ bool IsNewLogin() const override;
+ FormFetcher* GetFormFetcher() override;
+ bool IsPendingCredentialsPublicSuffixMatch() const override;
+ void PresaveGeneratedPassword(const autofill::PasswordForm& form) override;
+ void PasswordNoLongerGenerated() override;
+ bool HasGeneratedPassword() const override;
+ void SetGenerationPopupWasShown(bool generation_popup_was_shown,
+ bool is_manual_generation) override;
+ void SetGenerationElement(const base::string16& generation_element) override;
+ bool IsPossibleChangePasswordFormWithoutUsername() const override;
+ bool IsPasswordUpdate() const override;
+ std::vector<base::WeakPtr<PasswordManagerDriver>> GetDrivers() const override;
+ const autofill::PasswordForm* GetSubmittedForm() const override;
+
+#if defined(OS_IOS)
+ // Presaves the form with |generated_password|. This function is called once
+ // when the user accepts the generated password. The password was generated in
+ // the field with identifier |generation_element|. |driver| corresponds to the
+ // |form| parent frame.
+ void PresaveGeneratedPassword(PasswordManagerDriver* driver,
+ const autofill::FormData& form,
+ const base::string16& generated_password,
+ const base::string16& generation_element);
+
+ // Updates the presaved credential with the generated password when the user
+ // types in field with |field_identifier|, which is in form with
+ // |form_identifier| and the field value is |field_value|. Return true if
+ // |*this| manages a form with name |form_identifier|.
+ bool UpdateGeneratedPasswordOnUserInput(
+ const base::string16& form_identifier,
+ const base::string16& field_identifier,
+ const base::string16& field_value);
+#endif // defined(OS_IOS)
+
+ // Create a copy of |*this| which can be passed to the code handling
+ // save-password related UI. This omits some parts of the internal data, so
+ // the result is not identical to the original.
+ // TODO(crbug.com/739366): Replace with translating one appropriate class into
+ // another one.
+ std::unique_ptr<PasswordFormManager> Clone();
+
+#if defined(UNIT_TEST)
+ static void set_wait_for_server_predictions_for_filling(bool value) {
+ wait_for_server_predictions_for_filling_ = value;
+ }
+
+ FormSaver* form_saver() { return form_saver_.get(); }
+#endif
+
+ // TODO(https://crbug.com/831123): Remove it when the old form parsing is
+ // removed.
+ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder() {
+ return metrics_recorder_;
+ }
+
protected:
+ // Constructor for Credentials API.
+ PasswordFormManager(PasswordManagerClient* client,
+ std::unique_ptr<autofill::PasswordForm> saved_form,
+ std::unique_ptr<FormFetcher> form_fetcher,
+ std::unique_ptr<FormSaver> form_saver);
+
// FormFetcher::Consumer:
void OnFetchCompleted() override;
+ // Create pending credentials from |parsed_submitted_form_| and forms received
+ // from the password store.
+ void CreatePendingCredentials();
+
private:
- // Through |driver|, supply the associated frame with appropriate information
- // (fill data, whether to allow password generation, etc.).
- void ProcessFrameInternal(const base::WeakPtr<PasswordManagerDriver>& driver);
+ // Delegating constructor.
+ PasswordFormManager(
+ PasswordManagerClient* client,
+ FormFetcher* form_fetcher,
+ std::unique_ptr<FormSaver> form_saver,
+ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder,
+ PasswordStore::FormDigest form_digest);
+
+ // Compares |parsed_form| with |old_parsing_result_| and records UKM metric.
+ // TODO(https://crbug.com/831123): Remove it when the old form parsing is
+ // removed.
+ void RecordMetricOnCompareParsingResult(
+ const autofill::PasswordForm& parsed_form);
+
+ // Records the status of readonly fields during parsing, combined with the
+ // overall success of the parsing. It reports through two different metrics,
+ // depending on whether |mode| indicates parsing for saving or filling.
+ void RecordMetricOnReadonly(
+ FormDataParser::ReadonlyPasswordFields readonly_status,
+ bool parsing_successful,
+ FormDataParser::Mode mode);
+
+ // Report the time between receiving credentials from the password store and
+ // the autofill server responding to the lookup request.
+ void ReportTimeBetweenStoreAndServerUMA();
- // Trigger filling of HTTP auth dialog and update |manager_action_|.
- void ProcessLoginPrompt();
+ // Create pending credentials from provisionally saved form when this form
+ // represents credentials that were not previosly saved.
+ void CreatePendingCredentialsForNewCredentials(
+ const autofill::PasswordForm& submitted_password_form,
+ const base::string16& password_element);
- // Helper for Save in the case that best_matches.size() == 0, meaning
- // we have no prior record of this form/username/password and the user
- // has opted to 'Save Password'. The previously preferred login from
- // |best_matches_| will be reset.
- void SaveAsNewLogin();
+ void SetPasswordOverridden(bool password_overridden) {
+ password_overridden_ = password_overridden;
+ votes_uploader_.set_password_overridden(password_overridden);
+ }
// Helper for Save in the case there is at least one match for the pending
// credentials. This sends needed signals to the autofill server, and also
// triggers some UMA reporting.
void ProcessUpdate();
- // Update all login matches to reflect new preferred state - preferred flag
- // will be reset on all matched logins that different than the current
- // |pending_credentials_|.
- void UpdatePreferredLoginState(PasswordStore* password_store);
-
- // Returns true if |username| is one of the other possible usernames for a
- // password form in |best_matches_| and sets |pending_credentials_| to the
- // match which had this username.
- bool UpdatePendingCredentialsIfOtherPossibleUsername(
- const base::string16& username);
-
- // Returns true if |form| is a username update of a credential already in
- // |best_matches_|. Sets |pending_credentials_| to the appropriate
- // PasswordForm if it returns true.
- bool UpdatePendingCredentialsIfUsernameChanged(
- const autofill::PasswordForm& form);
-
- // Create pending credentials from |submitted_form_| and forms received from
- // the password store.
- void CreatePendingCredentials();
+ // Sends fill data to the http auth popup.
+ void FillHttpAuth();
- // Create pending credentials from provisionally saved form when this form
- // represents credentials that were not previosly saved.
- void CreatePendingCredentialsForNewCredentials(
- const base::string16& password_element);
+ // Helper function for calling form parsing and logging results if logging is
+ // active.
+ std::unique_ptr<autofill::PasswordForm> ParseFormAndMakeLogging(
+ const autofill::FormData& form,
+ FormDataParser::Mode mode);
- // If |best_matches_| contains only one entry, then return this entry.
- // Otherwise for empty |password| return nullptr and for non-empty |password|
- // returns the any entry in |best_matches_| with the same password, if it
- // exists, and nullptr otherwise.
- const autofill::PasswordForm* FindBestMatchForUpdatePassword(
- const base::string16& password) const;
-
- // Try to find best matched to |form| from |best_matches_| by the rules:
- // 1. If there is an element in |best_matches_| with the same username then
- // return it;
- // 2. If |form| is created with Credential API return nullptr, i.e. we match
- // Credentials API forms only by username;
- // 3. If |form| has no |username_element| and no |new_password_element| (i.e.
- // a form contains only one field which is a password) and there is an element
- // from |best_matches_| with the same password as in |form| then return it;
- // 4. Otherwise return nullptr.
- const autofill::PasswordForm* FindBestSavedMatch(
- const autofill::PasswordForm* form) const;
-
- // Goes through |not_best_matches_|, updates the password of those which share
- // the old password and username with |pending_credentials_| to the new
- // password of |pending_credentials_|, and returns copies of all such modified
- // credentials.
- std::vector<autofill::PasswordForm> FindOtherCredentialsToUpdate() const;
+ void PresaveGeneratedPasswordInternal(
+ const autofill::FormData& form,
+ const base::string16& generated_password);
+
+ // Calculates FillingAssistance metric for |submitted_form|. The metric is
+ // recorded in case when the successful submission is detected.
+ void CalculateFillingAssistanceMetric(
+ const autofill::FormData& submitted_form);
// Save/update |pending_credentials_| to the password store.
void SavePendingToStore(bool update);
- void SetPasswordOverridden(bool password_overridden) {
- password_overridden_ = password_overridden;
- votes_uploader_.set_password_overridden(password_overridden);
- }
+ // The client which implements embedder-specific PasswordManager operations.
+ PasswordManagerClient* client_;
+
+ base::WeakPtr<PasswordManagerDriver> driver_;
+
+ // TODO(https://crbug.com/943045): use std::variant for keeping
+ // |observed_form_| and |observed_not_web_form_digest_|.
+ autofill::FormData observed_form_;
+
+ // Used for retrieving credentials in case http authentication or Credentials
+ // API.
+ base::Optional<PasswordStore::FormDigest> observed_not_web_form_digest_;
// Set of nonblacklisted PasswordForms from the DB that best match the form
- // being managed by |this|, indexed by username. This means the best
- // PasswordForm for each username is stored in this map. The PasswordForms are
- // owned by |form_fetcher_|.
+ // being managed by |this|, indexed by username. The PasswordForms are owned
+ // by |form_fetcher_|.
std::map<base::string16, const autofill::PasswordForm*> best_matches_;
- // Set of forms from PasswordStore that correspond to the current site and
- // that are not in |best_matches_|. They are owned by |form_fetcher_|.
- std::vector<const autofill::PasswordForm*> not_best_matches_;
-
// Set of blacklisted forms from the PasswordStore that best match the current
- // form. They are owned by |form_fetcher_|, with the exception that if
- // |new_blacklisted_| is not null, the address of that form is also inside
- // |blacklisted_matches_|.
+ // form. They are owned by |form_fetcher_|.
std::vector<const autofill::PasswordForm*> blacklisted_matches_;
// If the observed form gets blacklisted through |this|, the blacklist entry
@@ -327,66 +321,14 @@ class PasswordFormManager : public PasswordFormManagerInterface,
// which are owned by |form_fetcher_|).
std::unique_ptr<autofill::PasswordForm> new_blacklisted_;
- // The PasswordForm from the page or dialog managed by |this|.
- const autofill::PasswordForm observed_form_;
-
- // The form signature of |observed_form_|
- const autofill::FormSignature observed_form_signature_;
-
- // Stores a submitted form.
- std::unique_ptr<const autofill::PasswordForm> submitted_form_;
-
- // Stores updated credentials when the form was submitted but success is still
- // unknown. This variable contains credentials that are ready to be written
- // (saved or updated) to a password store. It is calculated based on
- // |submitted_form_| and |best_matches_|.
- autofill::PasswordForm pending_credentials_;
-
- // Whether pending_credentials_ stores a new login or is an update
- // to an existing one.
- bool is_new_login_;
-
- // Handles the user flows related to the generation.
- std::unique_ptr<PasswordGenerationState> generation_state_;
-
- // Whether the saved password was overridden.
- bool password_overridden_;
-
- // A form is considered to be "retry" password if it has only one field which
- // is a current password field.
- // This variable is true if the password passed through ProvisionallySave() is
- // a password that is not part of any password form stored for this origin
- // and it was entered on a retry password form.
- bool retry_password_form_password_update_;
-
- // PasswordManager owning this.
- PasswordManager* const password_manager_;
-
// Convenience pointer to entry in best_matches_ that is marked
// as preferred. This is only allowed to be null if there are no best matches
// at all, since there will always be one preferred login when there are
// multiple matches (when first saved, a login is marked preferred).
- const autofill::PasswordForm* preferred_match_;
-
- // True if we consider this form to be a change password form without username
- // field. We use only client heuristics, so it could include signup forms.
- // The value of this variable is calculated based not only on information from
- // |observed_form_| but also on the credentials that the user submitted.
- bool is_possible_change_password_form_without_username_;
-
- // The client which implements embedder-specific PasswordManager operations.
- PasswordManagerClient* client_;
-
- // |this| is created for a form in some frame, which is represented by a
- // driver. Similar form can appear in more frames, represented with more
- // drivers. The drivers are needed to perform frame-specific operations
- // (filling etc.). These drivers are kept in |drivers_| to allow updating of
- // the filling information when needed.
- std::vector<base::WeakPtr<PasswordManagerDriver>> drivers_;
+ const autofill::PasswordForm* preferred_match_ = nullptr;
- // FormSaver instance used by |this| to all tasks related to storing
- // credentials.
- std::unique_ptr<FormSaver> form_saver_;
+ // Takes care of recording metrics and events for |*this|.
+ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder_;
// When not null, then this is the object which |form_fetcher_| points to.
std::unique_ptr<FormFetcher> owned_form_fetcher_;
@@ -394,11 +336,36 @@ class PasswordFormManager : public PasswordFormManagerInterface,
// FormFetcher instance which owns the login data from PasswordStore.
FormFetcher* form_fetcher_;
+ // FormSaver instance used by |this| to all tasks related to storing
+ // credentials.
+ const std::unique_ptr<FormSaver> form_saver_;
+
VotesUploader votes_uploader_;
- // Takes care of recording metrics and events for this PasswordFormManager.
- // Make sure to call Init before using |*this|, to ensure it is not null.
- scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder_;
+ // |is_submitted_| = true means that a submission of the managed form was seen
+ // and then |submitted_form_| contains the submitted form.
+ bool is_submitted_ = false;
+ autofill::FormData submitted_form_;
+ std::unique_ptr<autofill::PasswordForm> parsed_submitted_form_;
+
+ // Stores updated credentials when the form was submitted but success is still
+ // unknown. This variable contains credentials that are ready to be written
+ // (saved or updated) to a password store. It is calculated based on
+ // |submitted_form_| and |best_matches_|.
+ autofill::PasswordForm pending_credentials_;
+
+ // Whether |pending_credentials_| stores a credential that should be added
+ // to the password store. False means it's a pure update to the existing ones.
+ // TODO(crbug/831123): this value only makes sense internally. Remove public
+ // dependencies on it.
+ bool is_new_login_ = true;
+
+ // Handles the user flows related to the generation.
+ std::unique_ptr<PasswordGenerationState> generation_state_;
+
+ // Whether a saved password was overridden. The flag is true when there is a
+ // credential in the store that will get a new password value.
+ bool password_overridden_ = false;
// If Chrome has already autofilled a few times, it is probable that autofill
// is triggered by programmatic changes in the page. We set a maximum number
@@ -406,6 +373,25 @@ class PasswordFormManager : public PasswordFormManagerInterface,
// loop.
int autofills_left_ = kMaxTimesAutofill;
+ // True until server predictions received or waiting for them timed out.
+ bool waiting_for_server_predictions_ = false;
+
+ // Controls whether to wait or not server before filling. It is used in tests.
+ static bool wait_for_server_predictions_for_filling_;
+
+ // Used for comparison metrics.
+ // TODO(https://crbug.com/831123): Remove it when the old form parsing is
+ // removed.
+ autofill::PasswordForm old_parsing_result_;
+
+ // Time when stored credentials are received from the store. Used for metrics.
+ base::TimeTicks received_stored_credentials_time_;
+
+ // Used to transform FormData into PasswordForms.
+ FormDataParser parser_;
+
+ base::WeakPtrFactory<PasswordFormManager> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(PasswordFormManager);
};
diff --git a/chromium/components/password_manager/core/browser/password_form_manager_unittest.cc b/chromium/components/password_manager/core/browser/password_form_manager_unittest.cc
index 26d3af01985..8ba9a4dbd89 100644
--- a/chromium/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -1,230 +1,93 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/password_manager/core/browser/password_form_manager.h"
-#include <map>
-#include <memory>
-#include <set>
+#include <string>
#include <utility>
-#include "base/feature_list.h"
-#include "base/macros.h"
-#include "base/metrics/metrics_hashes.h"
-#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/metrics/user_action_tester.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
-#include "components/autofill/core/browser/autofill_manager.h"
-#include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
-#include "components/autofill/core/browser/proto/server.pb.h"
-#include "components/autofill/core/browser/test_autofill_client.h"
-#include "components/autofill/core/browser/test_autofill_driver.h"
-#include "components/autofill/core/browser/test_personal_data_manager.h"
-#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "build/build_config.h"
+#include "components/autofill/core/browser/autofill_download_manager.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
#include "components/autofill/core/common/password_generation_util.h"
#include "components/password_manager/core/browser/fake_form_fetcher.h"
-#include "components/password_manager/core/browser/password_manager.h"
-#include "components/password_manager/core/browser/password_manager_driver.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_manager_util.h"
-#include "components/password_manager/core/browser/statistics_table.h"
-#include "components/password_manager/core/browser/stub_credentials_filter.h"
+#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/stub_form_saver.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "components/password_manager/core/browser/stub_password_manager_driver.h"
#include "components/password_manager/core/browser/vote_uploads_test_matchers.h"
-#include "components/password_manager/core/common/password_manager_features.h"
-#include "components/password_manager/core/common/password_manager_pref_names.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/testing_pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "url/origin.h"
+using autofill::AutofillUploadContents;
using autofill::FieldPropertiesFlags;
-using autofill::FieldPropertiesMask;
+using autofill::FormData;
+using autofill::FormFieldData;
+using autofill::FormSignature;
+using autofill::FormStructure;
using autofill::PasswordForm;
-using autofill::ValueElementPair;
-using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics;
-using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery;
-using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload;
+using autofill::PasswordFormFillData;
+using autofill::PasswordFormGenerationData;
+using autofill::ServerFieldType;
using base::ASCIIToUTF16;
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::AtMost;
-using ::testing::Contains;
-using ::testing::ElementsAre;
-using ::testing::InSequence;
-using ::testing::IsEmpty;
-using ::testing::Mock;
-using ::testing::NiceMock;
-using ::testing::Not;
-using ::testing::Pair;
-using ::testing::Pointee;
-using ::testing::Return;
-using ::testing::SaveArg;
-using ::testing::SaveArgPointee;
-using ::testing::StrictMock;
-using ::testing::UnorderedElementsAre;
-using ::testing::WithArg;
+using base::TestMockTimeTaskRunner;
+using testing::_;
+using testing::AllOf;
+using testing::Contains;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::Mock;
+using testing::NiceMock;
+using testing::Pointee;
+using testing::Return;
+using testing::SaveArg;
+using testing::SaveArgPointee;
+using testing::UnorderedElementsAre;
namespace password_manager {
namespace {
-// Enum that describes what button the user pressed on the save prompt.
-enum SavePromptInteraction { SAVE, NEVER, NO_INTERACTION };
-
-// Creates a form with 2 text fields and 1 password field. The first and second
-// fields are username and password respectively. |observed_form| is used for
-// default values.
-// TODO(crbug.com/824834): The minimal case should be a smaller form.
-PasswordForm CreateMinimalCrowdsourcableForm(
- const PasswordForm& observed_form) {
- PasswordForm form = observed_form;
- form.origin = GURL("https://www.foo.com/login");
- form.form_data.url = form.origin;
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("email");
- field.form_control_type = "text";
- form.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("password");
- field.form_control_type = "password";
- form.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("petname");
- field.form_control_type = "text";
- form.form_data.fields.push_back(field);
- form.username_element = ASCIIToUTF16("email");
- form.password_element = ASCIIToUTF16("password");
- return form;
+// Indices of username and password fields in the observed form.
+const int kUsernameFieldIndex = 1;
+const int kPasswordFieldIndex = 2;
+
+MATCHER_P(FormHasUniqueKey, key, "") {
+ return ArePasswordFormUniqueKeysEqual(arg, key);
}
-class MockFormSaver : public StubFormSaver {
+class MockPasswordManagerDriver : public StubPasswordManagerDriver {
public:
- MockFormSaver() = default;
-
- ~MockFormSaver() override = default;
+ MockPasswordManagerDriver() {}
- // FormSaver:
- MOCK_METHOD1(PermanentlyBlacklist, PasswordForm(PasswordStore::FormDigest));
- MOCK_METHOD3(Save,
- void(PasswordForm pending,
- const std::vector<const PasswordForm*>& matches,
- const base::string16& old_password));
- MOCK_METHOD3(Update,
- void(PasswordForm pending,
- const std::vector<const PasswordForm*>& matches,
- const base::string16& old_password));
- MOCK_METHOD4(UpdateReplace,
- void(PasswordForm pending,
- const std::vector<const PasswordForm*>& matches,
- const base::string16& old_password,
- const PasswordForm& old_unique_key));
- MOCK_METHOD1(Remove, void(const PasswordForm&));
-
- std::unique_ptr<FormSaver> Clone() override {
- return std::make_unique<MockFormSaver>();
- }
-
- // Convenience downcasting method.
- static MockFormSaver& Get(PasswordFormManager* form_manager) {
- return *static_cast<MockFormSaver*>(form_manager->form_saver());
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockFormSaver);
-};
+ ~MockPasswordManagerDriver() override {}
-class MockFormFetcher : public FakeFormFetcher {
- public:
- MOCK_METHOD1(AddConsumer, void(Consumer*));
- MOCK_METHOD1(RemoveConsumer, void(Consumer*));
- MOCK_METHOD0(Clone, std::unique_ptr<FormFetcher>());
+ MOCK_METHOD1(FillPasswordForm, void(const PasswordFormFillData&));
+ MOCK_METHOD1(AllowPasswordGenerationForForm, void(const PasswordForm&));
+ MOCK_METHOD1(FormEligibleForGenerationFound,
+ void(const autofill::PasswordFormGenerationData&));
};
-MATCHER_P(UsernamePtrIs, username_value, "") {
- if (!arg)
- return false;
- if (arg->username_value != username_value) {
- *result_listener << "has username: " << arg->username_value;
- return false;
- }
- return true;
-}
-
-MATCHER_P(PasswordsWereRevealed, revealed, "") {
- return arg.passwords_were_revealed() == revealed;
-}
-
-MATCHER_P(HasPasswordAttributesVote, is_vote_expected, "") {
- base::Optional<std::pair<autofill::PasswordAttribute, bool>> vote =
- arg.get_password_attributes_vote_for_testing();
- EXPECT_EQ(is_vote_expected, vote.has_value());
- if (vote.has_value()) {
- size_t reported_length = arg.get_password_length_vote_for_testing();
- EXPECT_LT(0u, reported_length);
- EXPECT_LE(reported_length, 5u /* actual password length */);
- }
- return true;
-}
-
-// Matches iff the masks in |expected_field_properties| match the mask in the
-// uploaded form exactly.
-MATCHER_P(UploadedFieldPropertiesMasksAre, expected_field_properties, "") {
- size_t matched_count = 0;
- bool conflict_found = false;
- for (const auto& field : arg) {
- auto expectation = expected_field_properties.find(field->name);
- if (expectation == expected_field_properties.end())
- continue;
-
- matched_count++;
- autofill::FieldPropertiesMask expected_mask = expectation->second;
-
- if (field->properties_mask != expected_mask) {
- *result_listener << (conflict_found ? ", " : "") << field->name
- << " field: expected mask " << expected_mask
- << ", but found " << field->properties_mask;
- conflict_found = true;
- }
- }
-
- if (matched_count != expected_field_properties.size()) {
- *result_listener
- << (conflict_found ? ", " : "")
- << "some expectations did not correspond to an uploaded field";
- conflict_found = true;
- }
-
- return !conflict_found;
-}
-
-MATCHER_P(FormIgnoreDate, expected, "") {
- PasswordForm expected_with_date = expected;
- expected_with_date.date_created = arg.date_created;
- return arg == expected_with_date;
-}
-
class MockAutofillDownloadManager : public autofill::AutofillDownloadManager {
public:
- MockAutofillDownloadManager(
- autofill::AutofillDriver* driver,
- autofill::AutofillDownloadManager::Observer* observer)
- : AutofillDownloadManager(driver, observer) {}
+ MockAutofillDownloadManager()
+ : AutofillDownloadManager(nullptr, &fake_observer) {}
MOCK_METHOD6(StartUploadRequest,
- bool(const autofill::FormStructure&,
+ bool(const FormStructure&,
bool,
const autofill::ServerFieldTypeSet&,
const std::string&,
@@ -232,4438 +95,1928 @@ class MockAutofillDownloadManager : public autofill::AutofillDownloadManager {
PrefService*));
private:
+ class StubObserver : public AutofillDownloadManager::Observer {
+ void OnLoadedServerPredictions(
+ std::string response,
+ const std::vector<std::string>& form_signatures) override {}
+ };
+
+ StubObserver fake_observer;
DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager);
};
-class MockAutofillManager : public autofill::AutofillManager {
+class MockPasswordManagerClient : public StubPasswordManagerClient {
public:
- MockAutofillManager(
- autofill::AutofillDriver* driver,
- autofill::AutofillClient* client,
- autofill::PersonalDataManager* data_manager,
- autofill::MockAutocompleteHistoryManager* autocomplete_manager)
- : AutofillManager(driver, client, data_manager, autocomplete_manager) {
- // This function will be called in the destructor of AutofillManager.
- EXPECT_CALL(*autocomplete_manager, CancelPendingQueries(this));
- }
+ MockPasswordManagerClient() = default;
+ ~MockPasswordManagerClient() override = default;
- void SetDownloadManager(autofill::AutofillDownloadManager* manager) {
- set_download_manager(manager);
- }
+ MOCK_CONST_METHOD0(IsIncognito, bool());
- // Workaround for std::unique_ptr<> lacking a copy constructor.
- bool MaybeStartVoteUploadProcess(
- std::unique_ptr<FormStructure> form_structure,
- bool observed_submission) override {
- MaybeStartVoteUploadProcessPtr(form_structure.release(),
- observed_submission);
- return true;
- }
+ MOCK_METHOD0(GetAutofillDownloadManager,
+ autofill::AutofillDownloadManager*());
- MOCK_METHOD2(MaybeStartVoteUploadProcessPtr, void(FormStructure*, bool));
+ MOCK_METHOD0(UpdateFormManagers, void());
- private:
- DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
+ MOCK_METHOD2(AutofillHttpAuth,
+ void(const PasswordForm&, const PasswordFormManagerForUI*));
};
-class MockPasswordManagerDriver : public StubPasswordManagerDriver {
- public:
- MockPasswordManagerDriver()
- : mock_autofill_manager_(&test_autofill_driver_,
- &test_autofill_client_,
- &test_personal_data_manager_,
- &mock_autocomplete_history_manager_) {
- std::unique_ptr<TestingPrefServiceSimple> prefs(
- new TestingPrefServiceSimple());
- prefs->registry()->RegisterBooleanPref(
- autofill::prefs::kAutofillCreditCardEnabled, true);
- prefs->registry()->RegisterBooleanPref(
- autofill::prefs::kAutofillProfileEnabled, true);
- prefs->registry()->RegisterStringPref(
- autofill::prefs::kAutofillUploadEncodingSeed, "");
- test_autofill_client_.SetPrefs(std::move(prefs));
- mock_autofill_download_manager_ = new MockAutofillDownloadManager(
- &test_autofill_driver_, &mock_autofill_manager_);
- // AutofillManager takes ownership of |mock_autofill_download_manager_|.
- mock_autofill_manager_.SetDownloadManager(mock_autofill_download_manager_);
- }
-
- ~MockPasswordManagerDriver() override {}
-
- MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
- MOCK_METHOD0(InformNoSavedCredentials, void());
- MOCK_METHOD1(ShowInitialPasswordAccountSuggestions,
- void(const autofill::PasswordFormFillData&));
-
- MockAutofillManager* mock_autofill_manager() {
- return &mock_autofill_manager_;
- }
-
- MockAutofillDownloadManager* mock_autofill_download_manager() {
- return mock_autofill_download_manager_;
- }
-
- private:
- StrictMock<autofill::MockAutocompleteHistoryManager>
- mock_autocomplete_history_manager_;
- autofill::TestAutofillDriver test_autofill_driver_;
- autofill::TestAutofillClient test_autofill_client_;
- autofill::TestPersonalDataManager test_personal_data_manager_;
- MockAutofillDownloadManager* mock_autofill_download_manager_;
-
- NiceMock<MockAutofillManager> mock_autofill_manager_;
+void CheckPendingCredentials(const PasswordForm& expected,
+ const PasswordForm& actual) {
+ EXPECT_EQ(expected.signon_realm, actual.signon_realm);
+ EXPECT_EQ(expected.origin, actual.origin);
+ EXPECT_EQ(expected.action, actual.action);
+ EXPECT_EQ(expected.username_value, actual.username_value);
+ EXPECT_EQ(expected.password_value, actual.password_value);
+ EXPECT_EQ(expected.username_element, actual.username_element);
+ EXPECT_EQ(expected.password_element, actual.password_element);
+ EXPECT_EQ(expected.blacklisted_by_user, actual.blacklisted_by_user);
+ EXPECT_EQ(expected.form_data, actual.form_data);
+}
+
+struct ExpectedGenerationUKM {
+ base::Optional<int64_t> generation_popup_shown;
+ int64_t has_generated_password;
+ base::Optional<int64_t> generated_password_modified;
};
-class TestPasswordManagerClient : public StubPasswordManagerClient {
- public:
- TestPasswordManagerClient()
- : driver_(new NiceMock<MockPasswordManagerDriver>) {
- prefs_ = std::make_unique<TestingPrefServiceSimple>();
- prefs_->registry()->RegisterBooleanPref(prefs::kCredentialsEnableService,
- true);
- prefs_->registry()->RegisterStringPref(
- autofill::prefs::kAutofillUploadEncodingSeed, "");
+// Check that UKM |metric_name| in |entry| is equal to |expected|. |expected| ==
+// null means that no metric recording is expected.
+void CheckMetric(const int64_t* expected,
+ const ukm::mojom::UkmEntry* entry,
+ const char* metric_name) {
+ SCOPED_TRACE(testing::Message("Checking UKM metric ") << metric_name);
+
+ const int64_t* actual =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, metric_name);
+
+ ASSERT_EQ(!!expected, !!actual);
+ if (expected)
+ EXPECT_EQ(*expected, *actual);
+}
+
+// Check that |recorder| records metrics |expected_metrics|.
+void CheckPasswordGenerationUKM(const ukm::TestAutoSetUkmRecorder& recorder,
+ const ExpectedGenerationUKM& expected_metrics) {
+ auto entries =
+ recorder.GetEntriesByName(ukm::builders::PasswordForm::kEntryName);
+ ASSERT_EQ(1u, entries.size());
+ const int64_t* expected_popup_shown = nullptr;
+ if (expected_metrics.generation_popup_shown)
+ expected_popup_shown = &expected_metrics.generation_popup_shown.value();
+ CheckMetric(expected_popup_shown, entries[0],
+ ukm::builders::PasswordForm::kGeneration_PopupShownName);
+
+ CheckMetric(&expected_metrics.has_generated_password, entries[0],
+ ukm::builders::PasswordForm::kGeneration_GeneratedPasswordName);
+
+ const int64_t* expected_password_modified = nullptr;
+ if (expected_metrics.generated_password_modified)
+ expected_password_modified =
+ &expected_metrics.generated_password_modified.value();
+ CheckMetric(
+ expected_password_modified, entries[0],
+ ukm::builders::PasswordForm::kGeneration_GeneratedPasswordModifiedName);
+}
+
+// Create predictions for |form| using field predictions |field_predictions|.
+std::map<FormSignature, FormPredictions> CreatePredictions(
+ const FormData& form,
+ std::vector<std::pair<int, ServerFieldType>> field_predictions) {
+ FormPredictions predictions;
+ for (const auto& index_prediction : field_predictions) {
+ uint32_t renderer_id =
+ form.fields[index_prediction.first].unique_renderer_id;
+ ServerFieldType server_type = index_prediction.second;
+ predictions.push_back({.renderer_id = renderer_id, .type = server_type});
}
+ FormSignature form_signature = CalculateFormSignature(form);
+ return {{form_signature, predictions}};
+}
- MOCK_CONST_METHOD0(IsIncognito, bool());
-
- PrefService* GetPrefs() const override { return prefs_.get(); }
+class MockFormSaver : public StubFormSaver {
+ public:
+ MockFormSaver() = default;
- MockPasswordManagerDriver* mock_driver() { return driver_.get(); }
+ ~MockFormSaver() override = default;
- base::WeakPtr<PasswordManagerDriver> driver() { return driver_->AsWeakPtr(); }
+ // FormSaver:
+ MOCK_METHOD1(PermanentlyBlacklist, PasswordForm(PasswordStore::FormDigest));
+ MOCK_METHOD3(Save,
+ void(PasswordForm pending,
+ const std::vector<const PasswordForm*>& matches,
+ const base::string16& old_password));
+ MOCK_METHOD3(Update,
+ void(PasswordForm pending,
+ const std::vector<const PasswordForm*>& matches,
+ const base::string16& old_password));
+ MOCK_METHOD4(UpdateReplace,
+ void(PasswordForm pending,
+ const std::vector<const PasswordForm*>& matches,
+ const base::string16& old_password,
+ const PasswordForm& old_unique_key));
+ MOCK_METHOD1(Remove, void(const PasswordForm&));
- autofill::AutofillDownloadManager* GetAutofillDownloadManager() override {
- return mock_driver()->mock_autofill_download_manager();
+ std::unique_ptr<FormSaver> Clone() override {
+ return std::make_unique<MockFormSaver>();
}
- void KillDriver() { driver_.reset(); }
-
- const GURL& GetMainFrameURL() const override {
- static GURL url("https://www.example.com");
- return url;
+ // Convenience downcasting method.
+ static MockFormSaver& Get(PasswordFormManager* form_manager) {
+ return *static_cast<MockFormSaver*>(form_manager->form_saver());
}
private:
- std::unique_ptr<TestingPrefServiceSimple> prefs_;
- std::unique_ptr<MockPasswordManagerDriver> driver_;
+ DISALLOW_COPY_AND_ASSIGN(MockFormSaver);
};
-ACTION_P(SaveToUniquePtr, scoped) {
- scoped->reset(arg0);
-}
-
-} // namespace
-
+// TODO(https://crbug.com/831123): Test sending metrics.
+// TODO(https://crbug.com/831123): Test create pending credentials when
+// generation happened.
+// TODO(https://crbug.com/831123): Test create pending credentials with
+// Credential API.
class PasswordFormManagerTest : public testing::Test {
public:
- PasswordFormManagerTest() { fake_form_fetcher_.Fetch(); }
-
- void SetUp() override {
- observed_form_.origin = GURL("http://accounts.google.com/a/LoginAuth");
- observed_form_.action = GURL("http://accounts.google.com/a/Login");
- observed_form_.username_element = ASCIIToUTF16("Email");
- observed_form_.password_element = ASCIIToUTF16("Passwd");
- observed_form_.submit_element = ASCIIToUTF16("signIn");
- observed_form_.signon_realm = "http://accounts.google.com";
- observed_form_.form_data.name = ASCIIToUTF16("the-form-name");
-
- saved_match_ = observed_form_;
- saved_match_.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
- saved_match_.action = GURL("http://accounts.google.com/a/ServiceLogin");
- saved_match_.preferred = true;
- saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
- saved_match_.password_value = ASCIIToUTF16("test1");
- saved_match_.all_possible_usernames.push_back(ValueElementPair(
- ASCIIToUTF16("test2@gmail.com"), ASCIIToUTF16("full_name")));
- saved_match_.all_possible_passwords = {
- {ASCIIToUTF16("password"), base::string16()},
- {ASCIIToUTF16("password"), ASCIIToUTF16("Passwd")}};
-
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("Full name");
- field.name = ASCIIToUTF16("full_name");
+ PasswordFormManagerTest() : task_runner_(new TestMockTimeTaskRunner) {
+ GURL origin = GURL("https://accounts.google.com/a/ServiceLoginAuth");
+ GURL action = GURL("https://accounts.google.com/a/ServiceLogin");
+ GURL psl_origin = GURL("https://myaccounts.google.com/a/ServiceLoginAuth");
+ GURL psl_action = GURL("https://myaccounts.google.com/a/ServiceLogin");
+
+ observed_form_.url = origin;
+ observed_form_.action = action;
+ observed_form_.name = ASCIIToUTF16("sign-in");
+ observed_form_.unique_renderer_id = 1;
+ observed_form_.is_form_tag = true;
+
+ observed_form_only_password_fields_ = observed_form_;
+
+ FormFieldData field;
+ field.name = ASCIIToUTF16("firstname");
+ field.id_attribute = field.name;
+ field.name_attribute = field.name;
field.form_control_type = "text";
- saved_match_.form_data.fields.push_back(field);
+ field.unique_renderer_id = 1;
+ observed_form_.fields.push_back(field);
- field.label = ASCIIToUTF16("Email");
- field.name = ASCIIToUTF16("Email");
+ field.name = ASCIIToUTF16("username");
+ field.id_attribute = field.name;
+ field.name_attribute = field.name;
field.form_control_type = "text";
- saved_match_.form_data.fields.push_back(field);
+ field.unique_renderer_id = 2;
+ observed_form_.fields.push_back(field);
- field.label = ASCIIToUTF16("password");
- field.name = ASCIIToUTF16("Passwd");
+ field.name = ASCIIToUTF16("password");
+ field.id_attribute = field.name;
+ field.name_attribute = field.name;
field.form_control_type = "password";
- saved_match_.form_data.fields.push_back(field);
+ field.unique_renderer_id = 3;
+ observed_form_.fields.push_back(field);
+ observed_form_only_password_fields_.fields.push_back(field);
- psl_saved_match_ = saved_match_;
- psl_saved_match_.is_public_suffix_match = true;
- psl_saved_match_.origin =
- GURL("http://m.accounts.google.com/a/ServiceLoginAuth");
- psl_saved_match_.action = GURL("http://m.accounts.google.com/a/Login");
- psl_saved_match_.signon_realm = "http://m.accounts.google.com";
-
- scoped_feature_list_.InitWithFeatures(
- /* enabled_features */ {},
- /* disabled_features*/ {features::kNewPasswordFormParsing,
- features::kNewPasswordFormParsingForSaving,
- features::kOnlyNewParser});
- password_manager_.reset(new PasswordManager(&client_));
- form_manager_.reset(new PasswordFormManager(
- password_manager_.get(), &client_, client_.driver(), observed_form_,
- std::make_unique<NiceMock<MockFormSaver>>(), &fake_form_fetcher_));
- form_manager_->Init(nullptr);
- }
-
- // Save saved_match() for observed_form() where |observed_form_data|,
- // |times_used|, and |status| are used to overwrite the default values for
- // observed_form(). |field_type| is the upload that we expect from saving,
- // with nullptr meaning no upload expected.
- void AccountCreationUploadTest(const autofill::FormData& observed_form_data,
- int times_used,
- PasswordForm::GenerationUploadStatus status,
- const autofill::ServerFieldType* field_type) {
- PasswordForm form(*observed_form());
-
- form.form_data = observed_form_data;
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), form,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- PasswordForm match = CreateSavedMatch(false);
- match.generation_upload_status = status;
- match.times_used = times_used;
-
- PasswordForm form_to_save(form);
- form_to_save.preferred = true;
- form_to_save.username_element = ASCIIToUTF16("observed-username-field");
- form_to_save.password_element = ASCIIToUTF16("observed-password-field");
- form_to_save.username_value = match.username_value;
- form_to_save.password_value = match.password_value;
-
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {&match});
- std::string expected_login_signature;
- autofill::FormStructure observed_structure(observed_form_data);
- autofill::FormStructure pending_structure(saved_match()->form_data);
- if (observed_structure.FormSignatureAsStr() !=
- pending_structure.FormSignatureAsStr() &&
- times_used == 0) {
- expected_login_signature = observed_structure.FormSignatureAsStr();
- }
- autofill::ServerFieldTypeSet expected_available_field_types;
- FieldTypeMap expected_types;
- expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
-
- // When we're voting for an account creation form, we should also vote
- // for its username field.
- bool expect_username_vote = false;
- if (field_type && *field_type == autofill::ACCOUNT_CREATION_PASSWORD) {
- expected_types[match.username_element] = autofill::USERNAME;
- expected_available_field_types.insert(autofill::USERNAME);
- expect_username_vote = true;
- } else {
- expected_types[match.username_element] = autofill::UNKNOWN_TYPE;
- }
-
- bool expect_generation_vote = false;
- if (field_type) {
- // Show the password generation popup to check that the generation vote
- // would be ignored.
- form_manager.SetGenerationElement(saved_match()->password_element);
- form_manager.SetGenerationPopupWasShown(/*shown=*/true,
- /*manually_triggered*/ true);
- expect_generation_vote =
- *field_type != autofill::ACCOUNT_CREATION_PASSWORD;
-
- expected_available_field_types.insert(*field_type);
- expected_types[saved_match()->password_element] = *field_type;
- }
-
- if (field_type) {
- if (expect_username_vote) {
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(AllOf(SignatureIsSameAs(*saved_match()),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(expect_generation_vote),
- VoteTypesAre(VoteTypeMap(
- {{match.username_element,
- autofill::AutofillUploadContents::
- Field::CREDENTIALS_REUSED}})),
- HasPasswordAttributesVote(false)),
- false, expected_available_field_types,
- expected_login_signature, true, nullptr));
- } else {
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(AllOf(SignatureIsSameAs(*saved_match()),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(expect_generation_vote),
- HasPasswordAttributesVote(false)),
- false, expected_available_field_types,
- expected_login_signature, true, nullptr));
- }
- } else {
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, _, _, _, _))
- .Times(0);
- }
- if (times_used == 0) {
- // First login vote.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(form_to_save), _, _, _,
- _, nullptr));
- }
- form_manager.ProvisionallySave(form_to_save);
- form_manager.Save();
- Mock::VerifyAndClearExpectations(
- client()->mock_driver()->mock_autofill_download_manager());
- }
-
- // Test upload votes on change password forms. |field_type| is a vote that we
- // expect to be uploaded.
- void ChangePasswordUploadTest(autofill::ServerFieldType field_type,
- bool has_confirmation_field) {
- SCOPED_TRACE(testing::Message()
- << "field_type=" << field_type
- << " has_confirmation_field=" << has_confirmation_field);
-
- // |observed_form_| should have |form_data| in order to be uploaded.
- observed_form()->form_data = saved_match()->form_data;
- // Turn |observed_form_| and into change password form.
- observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("NewPasswd");
- field.name = ASCIIToUTF16("NewPasswd");
+ field.name = ASCIIToUTF16("password2");
+ field.id_attribute = field.name;
+ field.name_attribute = field.name;
field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
- autofill::FormFieldData empty_field;
- observed_form()->form_data.fields.push_back(empty_field);
- if (has_confirmation_field) {
- field.label = ASCIIToUTF16("ConfPwd");
- field.name = ASCIIToUTF16("ConfPwd");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
- }
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {saved_match()});
-
- // User submits current and new credentials to the observed form.
- PasswordForm submitted_form(*observed_form());
- // credentials.username_element.clear();
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.new_password_value = ASCIIToUTF16("test2");
- if (has_confirmation_field)
- submitted_form.confirmation_password_element = ASCIIToUTF16("ConfPwd");
- submitted_form.preferred = true;
- form_manager.ProvisionallySave(submitted_form);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to update.
- EXPECT_FALSE(form_manager.IsNewLogin());
- EXPECT_FALSE(form_manager.IsPossibleChangePasswordFormWithoutUsername());
-
- // By now, the PasswordFormManager should have promoted the new password
- // value already to be the current password, and should no longer maintain
- // any info about the new password value.
- EXPECT_EQ(submitted_form.new_password_value,
- form_manager.GetPendingCredentials().password_value);
- EXPECT_TRUE(
- form_manager.GetPendingCredentials().new_password_value.empty());
-
- std::map<base::string16, autofill::ServerFieldType> expected_types;
- expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
- expected_types[observed_form_.username_element] = autofill::UNKNOWN_TYPE;
- expected_types[observed_form_.password_element] = autofill::PASSWORD;
- expected_types[observed_form_.new_password_element] = field_type;
- expected_types[base::string16()] = autofill::UNKNOWN_TYPE;
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- expected_available_field_types.insert(autofill::PASSWORD);
- expected_available_field_types.insert(field_type);
- if (has_confirmation_field) {
- expected_types[submitted_form.confirmation_password_element] =
- autofill::CONFIRMATION_PASSWORD;
- expected_available_field_types.insert(autofill::CONFIRMATION_PASSWORD);
- }
-
- InSequence in_sequence;
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(*observed_form()),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false), HasPasswordAttributesVote(false)),
- false, expected_available_field_types, _, true, nullptr));
- if (field_type == autofill::NEW_PASSWORD) {
- // An unrelated vote that the credentials were used for the first time.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _, _));
- }
- switch (field_type) {
- case autofill::NEW_PASSWORD:
- form_manager.Save();
- break;
- case autofill::PROBABLY_NEW_PASSWORD:
- form_manager.OnNoInteraction(true /* it is an update */);
- break;
- case autofill::NOT_NEW_PASSWORD:
- form_manager.OnNopeUpdateClicked();
- break;
- default:
- NOTREACHED();
- }
- Mock::VerifyAndClearExpectations(
- client()->mock_driver()->mock_autofill_download_manager());
- }
-
- autofill::AutofillUploadContents::Field::PasswordGenerationType
- GetExpectedPasswordGenerationType(bool is_manual_generation,
- bool is_change_password_form,
- bool has_generated_password) {
- if (!has_generated_password)
- return autofill::AutofillUploadContents::Field::IGNORED_GENERATION_POPUP;
-
- if (is_manual_generation) {
- if (is_change_password_form) {
- return autofill::AutofillUploadContents::Field::
- MANUALLY_TRIGGERED_GENERATION_ON_CHANGE_PASSWORD_FORM;
- } else {
- return autofill::AutofillUploadContents::Field::
- MANUALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM;
- }
- } else {
- if (is_change_password_form) {
- return autofill::AutofillUploadContents::Field::
- AUTOMATICALLY_TRIGGERED_GENERATION_ON_CHANGE_PASSWORD_FORM;
- } else {
- return autofill::AutofillUploadContents::Field::
- AUTOMATICALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM;
- }
- }
- }
-
- // The user types username and generates password on SignUp or change password
- // form. The password generation might be triggered automatically or manually.
- // This function checks that correct vote is uploaded on server. The vote must
- // be uploaded regardless of the user's interaction with the prompt.
- void GeneratedVoteUploadTest(bool is_manual_generation,
- bool is_change_password_form,
- bool has_generated_password,
- bool generated_password_changed,
- SavePromptInteraction interaction) {
- SCOPED_TRACE(testing::Message()
- << "is_manual_generation=" << is_manual_generation
- << " is_change_password_form=" << is_change_password_form
- << " has_generated_password=" << has_generated_password
- << " generated_password_changed=" << generated_password_changed
- << " interaction=" << interaction);
- PasswordForm form(*observed_form());
- form.form_data = saved_match()->form_data;
-
- if (is_change_password_form) {
- // Turn |form| to a change password form.
- form.new_password_element = ASCIIToUTF16("NewPasswd");
-
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("password");
- field.name = ASCIIToUTF16("NewPasswd");
- field.form_control_type = "password";
- form.form_data.fields.push_back(field);
+ field.unique_renderer_id = 5;
+ observed_form_only_password_fields_.fields.push_back(field);
+
+// On iOS the unique_id member uniquely addresses this field in the DOM.
+// This is an ephemeral value which is not guaranteed to be stable across
+// page loads. It serves to allow a given field to be found during the
+// current navigation.
+// TODO(crbug.com/896689): Expand the logic/application of this to other
+// platforms and/or merge this concept with |unique_renderer_id|.
+#if defined(OS_IOS)
+ for (auto& f : observed_form_.fields) {
+ f.unique_id = f.id_attribute;
}
-
- // Create submitted form.
- PasswordForm submitted_form(form);
- submitted_form.preferred = true;
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
-
- if (is_change_password_form) {
- submitted_form.new_password_value =
- saved_match()->password_value + ASCIIToUTF16("1");
- submitted_form.password_value = submitted_form.new_password_value;
- }
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), form,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- // Don't send autofill votes if the user didn't press "Save" button.
- if (interaction == SAVE)
- expected_available_field_types.insert(autofill::PASSWORD);
-
- base::string16 generation_element = is_change_password_form
- ? form.new_password_element
- : form.password_element;
- form_manager.SetGenerationElement(generation_element);
- form_manager.SetGenerationPopupWasShown(true, is_manual_generation);
- if (has_generated_password) {
- form_manager.PresaveGeneratedPassword(submitted_form);
- if (generated_password_changed) {
- submitted_form.password_value += ASCIIToUTF16("2");
- form_manager.PresaveGeneratedPassword(submitted_form);
- }
- }
-
- // Figure out expected generation event type.
- autofill::AutofillUploadContents::Field::PasswordGenerationType
- expected_generation_type = GetExpectedPasswordGenerationType(
- is_manual_generation, is_change_password_form,
- has_generated_password);
- std::map<base::string16,
- autofill::AutofillUploadContents::Field::PasswordGenerationType>
- expected_generation_types;
- expected_generation_types[generation_element] = expected_generation_type;
-
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(AllOf(SignatureIsSameAs(submitted_form),
- UploadedGenerationTypesAre(
- expected_generation_types,
- generated_password_changed)),
- false, expected_available_field_types,
- std::string(), true, nullptr));
- base::HistogramTester histogram_tester;
-
- form_manager.ProvisionallySave(submitted_form);
- switch (interaction) {
- case SAVE:
- form_manager.Save();
- break;
- case NEVER:
- form_manager.OnNeverClicked();
- break;
- case NO_INTERACTION:
- form_manager.OnNoInteraction(false /* not an update prompt*/);
- break;
- }
- if (has_generated_password) {
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.GeneratedPasswordWasEdited",
- generated_password_changed /* sample */, 1);
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.IsTriggeredManually",
- is_manual_generation /* sample */, 1);
- }
- Mock::VerifyAndClearExpectations(
- client()->mock_driver()->mock_autofill_download_manager());
- }
-
- void GeneratedPasswordUkmTest(bool is_manual_generation,
- bool is_change_password_form,
- bool has_generated_password,
- bool generated_password_changed,
- SavePromptInteraction interaction) {
- SCOPED_TRACE(testing::Message()
- << "is_manual_generation=" << is_manual_generation
- << " is_change_password_form=" << is_change_password_form
- << " has_generated_password=" << has_generated_password
- << " generated_password_changed=" << generated_password_changed
- << " interaction=" << interaction);
-
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- test_ukm_recorder.UpdateSourceURL(client()->GetUkmSourceId(),
- client()->GetMainFrameURL());
-
- PasswordForm form(*observed_form());
- form.form_data = saved_match()->form_data;
-
- if (is_change_password_form) {
- // Turn |form| to a change password form.
- form.new_password_element = ASCIIToUTF16("NewPasswd");
-
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("password");
- field.name = ASCIIToUTF16("NewPasswd");
- field.form_control_type = "password";
- form.form_data.fields.push_back(field);
+ for (auto& f : observed_form_only_password_fields_.fields) {
+ f.unique_id = f.id_attribute;
}
+#endif
- // Create submitted form.
- PasswordForm submitted_form(form);
- submitted_form.preferred = true;
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
-
- if (is_change_password_form) {
- submitted_form.new_password_value =
- saved_match()->password_value + ASCIIToUTF16("1");
- submitted_form.password_value = submitted_form.new_password_value;
- }
+ submitted_form_ = observed_form_;
+ submitted_form_.fields[kUsernameFieldIndex].value = ASCIIToUTF16("user1");
+ submitted_form_.fields[kPasswordFieldIndex].value = ASCIIToUTF16("secret1");
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- auto metrics_recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
- form.origin.SchemeIsCryptographic(), client()->GetUkmSourceId());
- auto form_manager = std::make_unique<PasswordFormManager>(
- password_manager(), client(), client()->driver(), form,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- // *Move* the metrics recorder to not hold on to a reference.
- form_manager->Init(std::move(metrics_recorder));
- fetcher.NotifyFetchCompleted();
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- // Don't send autofill votes if the user didn't press "Save" button.
- if (interaction == SAVE)
- expected_available_field_types.insert(autofill::PASSWORD);
-
- base::string16 generation_element = is_change_password_form
- ? form.new_password_element
- : form.password_element;
- form_manager->SetGenerationElement(generation_element);
- form_manager->SetGenerationPopupWasShown(true, is_manual_generation);
- if (has_generated_password) {
- form_manager->PresaveGeneratedPassword(submitted_form);
- if (generated_password_changed) {
- submitted_form.password_value += ASCIIToUTF16("2");
- form_manager->PresaveGeneratedPassword(submitted_form);
- }
- }
+ saved_match_.origin = origin;
+ saved_match_.action = action;
+ saved_match_.signon_realm = "https://accounts.google.com/";
+ saved_match_.preferred = true;
+ saved_match_.username_value = ASCIIToUTF16("test@gmail.com");
+ saved_match_.username_element = ASCIIToUTF16("field1");
+ saved_match_.password_value = ASCIIToUTF16("test1");
+ saved_match_.password_element = ASCIIToUTF16("field2");
+ saved_match_.is_public_suffix_match = false;
+ saved_match_.scheme = PasswordForm::Scheme::kHtml;
- // Figure out expected generation event type.
- autofill::AutofillUploadContents::Field::PasswordGenerationType
- expected_generation_type = GetExpectedPasswordGenerationType(
- is_manual_generation, is_change_password_form,
- has_generated_password);
- std::map<base::string16,
- autofill::AutofillUploadContents::Field::PasswordGenerationType>
- expected_generation_types;
- expected_generation_types[generation_element] = expected_generation_type;
-
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(AllOf(SignatureIsSameAs(submitted_form),
- UploadedGenerationTypesAre(
- expected_generation_types,
- generated_password_changed)),
- false, expected_available_field_types,
- std::string(), true, nullptr));
- form_manager->ProvisionallySave(submitted_form);
- switch (interaction) {
- case SAVE:
- form_manager->Save();
- break;
- case NEVER:
- form_manager->OnNeverClicked();
- break;
- case NO_INTERACTION:
- form_manager->OnNoInteraction(false /* not an update prompt*/);
- break;
- }
- // Reset form manager to flush UKM metrics.
- form_manager.reset();
-
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(1u, entries.size());
-
- ukm::TestUkmRecorder::ExpectEntryMetric(
- entries[0], ukm::builders::PasswordForm::kGeneration_PopupShownName,
- is_manual_generation
- ? static_cast<int64_t>(
- password_manager::PasswordFormMetricsRecorder::
- PasswordGenerationPopupShown::kShownManually)
- : static_cast<int64_t>(
- password_manager::PasswordFormMetricsRecorder::
- PasswordGenerationPopupShown::kShownAutomatically));
-
- ukm::TestUkmRecorder::ExpectEntryMetric(
- entries[0],
- ukm::builders::PasswordForm::kGeneration_GeneratedPasswordName,
- has_generated_password ? 1 : 0);
-
- if (has_generated_password) {
- ukm::TestUkmRecorder::ExpectEntryMetric(
- entries[0],
- ukm::builders::PasswordForm::
- kGeneration_GeneratedPasswordModifiedName,
- generated_password_changed ? 1 : 0);
- }
- Mock::VerifyAndClearExpectations(
- client()->mock_driver()->mock_autofill_download_manager());
- }
+ psl_saved_match_ = saved_match_;
+ psl_saved_match_.origin = psl_origin;
+ psl_saved_match_.action = psl_action;
+ psl_saved_match_.signon_realm = "https://myaccounts.google.com/";
+ psl_saved_match_.is_public_suffix_match = true;
- PasswordForm* observed_form() { return &observed_form_; }
- PasswordForm* saved_match() { return &saved_match_; }
- PasswordForm* psl_saved_match() { return &psl_saved_match_; }
- PasswordForm CreateSavedMatch(bool blacklisted) {
- PasswordForm match = saved_match_;
- match.blacklisted_by_user = blacklisted;
- return match;
+ parsed_observed_form_ = saved_match_;
+ parsed_observed_form_.form_data = observed_form_;
+ parsed_observed_form_.username_element =
+ observed_form_.fields[kUsernameFieldIndex].name;
+ parsed_observed_form_.password_element =
+ observed_form_.fields[kPasswordFieldIndex].name;
+
+ parsed_submitted_form_ = parsed_observed_form_;
+ parsed_submitted_form_.form_data = submitted_form_;
+ parsed_submitted_form_.username_value =
+ submitted_form_.fields[kUsernameFieldIndex].value;
+ parsed_submitted_form_.password_value =
+ submitted_form_.fields[kPasswordFieldIndex].value;
+
+ blacklisted_match_ = saved_match_;
+ blacklisted_match_.blacklisted_by_user = true;
+
+ EXPECT_CALL(client_, GetAutofillDownloadManager())
+ .WillRepeatedly(testing::Return(&mock_autofill_download_manager_));
+ ON_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(_, _, _, _, _, _))
+ .WillByDefault(testing::Return(true));
+
+ fetcher_.reset(new FakeFormFetcher());
+ fetcher_->Fetch();
+
+ CreateFormManager(observed_form_);
}
- TestPasswordManagerClient* client() { return &client_; }
-
- PasswordManager* password_manager() { return password_manager_.get(); }
-
- PasswordFormManager* form_manager() { return form_manager_.get(); }
-
- FakeFormFetcher* fake_form_fetcher() { return &fake_form_fetcher_; }
-
- // To spare typing for PasswordFormManager instances which need no driver.
- const base::WeakPtr<PasswordManagerDriver> kNoDriver;
-
protected:
- enum class SimulatedManagerAction { NONE, AUTOFILLED, OFFERED, OFFERED_PSL };
- enum class SimulatedSubmitResult { NONE, PASSED, FAILED };
- enum class SuppressedFormType { HTTPS, PSL_MATCH, SAME_ORGANIZATION_NAME };
-
- PasswordForm CreateSuppressedForm(SuppressedFormType suppression_type,
- const char* username,
- const char* password,
- PasswordForm::Type manual_or_generated) {
- PasswordForm form = *saved_match();
- switch (suppression_type) {
- case SuppressedFormType::HTTPS:
- form.origin = GURL("https://accounts.google.com/a/LoginAuth");
- form.signon_realm = "https://accounts.google.com/";
- break;
- case SuppressedFormType::PSL_MATCH:
- form.origin = GURL("http://other.google.com/");
- form.signon_realm = "http://other.google.com/";
- break;
- case SuppressedFormType::SAME_ORGANIZATION_NAME:
- form.origin = GURL("https://may-or-may-not-be.google.appspot.com/");
- form.signon_realm = "https://may-or-may-not-be.google.appspot.com/";
- break;
- }
- form.type = manual_or_generated;
- form.username_value = ASCIIToUTF16(username);
- form.password_value = ASCIIToUTF16(password);
- return form;
+ MockAutofillDownloadManager mock_autofill_download_manager_;
+ FormData observed_form_;
+ FormData submitted_form_;
+ FormData observed_form_only_password_fields_;
+ PasswordForm saved_match_;
+ PasswordForm psl_saved_match_;
+ PasswordForm blacklisted_match_;
+ PasswordForm parsed_observed_form_;
+ PasswordForm parsed_submitted_form_;
+ MockPasswordManagerClient client_;
+ MockPasswordManagerDriver driver_;
+ scoped_refptr<TestMockTimeTaskRunner> task_runner_;
+
+ // Define |fetcher_| before |form_manager_|, because the former needs to
+ // outlive the latter.
+ std::unique_ptr<FakeFormFetcher> fetcher_;
+ std::unique_ptr<PasswordFormManager> form_manager_;
+
+ // Creates PasswordFormManager and sets it to |form_manager_|. Along the
+ // way a new |fetcher_| is created.
+ void CreateFormManager(const FormData& observed_form) {
+ form_manager_.reset(new PasswordFormManager(
+ &client_, driver_.AsWeakPtr(), observed_form, fetcher_.get(),
+ std::make_unique<NiceMock<MockFormSaver>>(), nullptr));
}
- void SetNonFederatedAndNotifyFetchCompleted(
- const std::vector<const autofill::PasswordForm*>& non_federated) {
- SetNonFederatedAndNotifyFetchCompleted(fake_form_fetcher(), non_federated);
+ // Creates PasswordFormManager and sets it to |form_manager_| for
+ // |base_auth_observed_form|. Along the way a new |fetcher_| is created.
+ void CreateFormManagerForNonWebForm(
+ const PasswordForm& base_auth_observed_form) {
+ fetcher_->set_scheme(
+ PasswordStore::FormDigest(base_auth_observed_form).scheme);
+ form_manager_.reset(new PasswordFormManager(
+ &client_, PasswordStore::FormDigest(base_auth_observed_form),
+ fetcher_.get(), std::make_unique<NiceMock<MockFormSaver>>()));
}
void SetNonFederatedAndNotifyFetchCompleted(
- FakeFormFetcher* fetcher,
const std::vector<const autofill::PasswordForm*>& non_federated) {
- fetcher->SetNonFederated(non_federated);
- fetcher->NotifyFetchCompleted();
+ fetcher_->SetNonFederated(non_federated);
+ fetcher_->NotifyFetchCompleted();
}
+};
- void SimulateActionsOnHTTPObservedForm(
- FakeFormFetcher* fetcher,
- SimulatedManagerAction manager_action,
- SimulatedSubmitResult submit_result,
- const char* filled_username,
- const char* filled_password,
- const char* submitted_password = nullptr) {
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<NiceMock<MockFormSaver>>(), fetcher);
- form_manager.Init(nullptr);
-
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, _, _, _, _))
- .Times(::testing::AnyNumber());
-
- PasswordForm http_stored_form = *saved_match();
- http_stored_form.username_value = base::ASCIIToUTF16(filled_username);
- http_stored_form.password_value = base::ASCIIToUTF16(filled_password);
- if (manager_action == SimulatedManagerAction::OFFERED_PSL)
- http_stored_form.is_public_suffix_match = true;
-
- std::vector<const PasswordForm*> matches;
- if (manager_action != SimulatedManagerAction::NONE)
- matches.push_back(&http_stored_form);
-
- // Extra mile: kChoose is only recorded if there were multiple
- // logins available and the preferred one was changed.
- PasswordForm http_stored_form2 = http_stored_form;
- if (manager_action == SimulatedManagerAction::OFFERED) {
- http_stored_form.preferred = false;
- http_stored_form2.username_value = ASCIIToUTF16("user-other@gmail.com");
- matches.push_back(&http_stored_form2);
- }
+TEST_F(PasswordFormManagerTest, DoesManage) {
+ EXPECT_TRUE(form_manager_->DoesManage(observed_form_, &driver_));
+ // Forms on other drivers are not considered managed.
+ EXPECT_FALSE(form_manager_->DoesManage(observed_form_, nullptr));
+ FormData another_form = observed_form_;
+ another_form.is_form_tag = false;
+ EXPECT_FALSE(form_manager_->DoesManage(another_form, &driver_));
+
+ // On non-iOS platforms unique_renderer_id is the form identifier.
+ another_form = observed_form_;
+ another_form.unique_renderer_id = observed_form_.unique_renderer_id + 1;
+#if defined(OS_IOS)
+ EXPECT_TRUE(form_manager_->DoesManage(another_form, &driver_));
+#else
+ EXPECT_FALSE(form_manager_->DoesManage(another_form, &driver_));
+#endif
+
+ // On iOS platforms form name is the form identifier.
+ another_form = observed_form_;
+ another_form.name = observed_form_.name + ASCIIToUTF16("1");
+#if defined(OS_IOS)
+ EXPECT_FALSE(form_manager_->DoesManage(another_form, &driver_));
+#else
+ EXPECT_TRUE(form_manager_->DoesManage(another_form, &driver_));
+#endif
+}
+
+TEST_F(PasswordFormManagerTest, DoesManageNoFormTag) {
+ observed_form_.is_form_tag = false;
+ CreateFormManager(observed_form_);
+
+ FormData another_form = observed_form_;
+ // Simulate that new input was added by JavaScript.
+ another_form.fields.push_back(FormFieldData());
+ EXPECT_TRUE(form_manager_->DoesManage(another_form, &driver_));
+ // Forms on other drivers are not considered managed.
+ EXPECT_FALSE(form_manager_->DoesManage(another_form, nullptr));
+}
+
+TEST_F(PasswordFormManagerTest, Autofill) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ CreateFormManager(observed_form_);
+ EXPECT_CALL(driver_, FormEligibleForGenerationFound(_)).Times(0);
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
+ CreateFormManager(observed_form_);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+
+ task_runner_->FastForwardUntilNoTasksRemain();
+
+ EXPECT_EQ(observed_form_.url, fill_data.origin);
+ EXPECT_FALSE(fill_data.wait_for_username);
+ EXPECT_EQ(observed_form_.fields[1].name, fill_data.username_field.name);
+ EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
+ EXPECT_EQ(observed_form_.fields[2].name, fill_data.password_field.name);
+ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
+}
- fetcher->Fetch();
- SetNonFederatedAndNotifyFetchCompleted(fetcher, matches);
-
- if (submit_result != SimulatedSubmitResult::NONE) {
- PasswordForm submitted_form(*observed_form());
- submitted_form.preferred = true;
- submitted_form.username_value = base::ASCIIToUTF16(filled_username);
- submitted_form.password_value =
- submitted_password ? base::ASCIIToUTF16(submitted_password)
- : base::ASCIIToUTF16(filled_password);
-
- form_manager.ProvisionallySave(submitted_form);
- if (submit_result == SimulatedSubmitResult::PASSED) {
- form_manager.LogSubmitPassed();
- form_manager.Save();
- } else {
- form_manager.LogSubmitFailed();
- }
- }
- }
+TEST_F(PasswordFormManagerTest, AutofillNotMoreThan5Times) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- private:
- // Necessary for callbacks, and for TestAutofillDriver.
- base::test::ScopedTaskEnvironment task_environment_;
+ EXPECT_CALL(driver_, FillPasswordForm(_));
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- PasswordForm observed_form_;
- PasswordForm saved_match_;
- PasswordForm psl_saved_match_;
- NiceMock<TestPasswordManagerClient> client_;
- std::unique_ptr<PasswordManager> password_manager_;
- // Define |fake_form_fetcher_| before |form_manager_|, because the former
- // needs to outlive the latter.
- FakeFormFetcher fake_form_fetcher_;
- std::unique_ptr<PasswordFormManager> form_manager_;
- base::test::ScopedFeatureList scoped_feature_list_;
-};
+ task_runner_->FastForwardUntilNoTasksRemain();
+ Mock::VerifyAndClearExpectations(&driver_);
-class PasswordFormManagerFillOnAccountSelectTest
- : public PasswordFormManagerTest {
- public:
- void SetUp() override {
- PasswordFormManagerTest::SetUp();
- scoped_feature_list_.InitAndEnableFeature(features::kFillOnAccountSelect);
+ for (size_t i = 0; i < PasswordFormManager::kMaxTimesAutofill - 1; ++i) {
+ EXPECT_CALL(driver_, FillPasswordForm(_));
+ form_manager_->Fill();
+ Mock::VerifyAndClearExpectations(&driver_);
}
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-// Test provisionally saving a new login.
-TEST_F(PasswordFormManagerTest, TestNewLogin) {
- fake_form_fetcher()->NotifyFetchCompleted();
-
- // User submits credentials for the observed form.
- PasswordForm credentials = *observed_form();
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = saved_match()->password_value;
- credentials.preferred = true;
- form_manager()->ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, which should know this is a new login.
- EXPECT_TRUE(form_manager()->IsNewLogin());
- // Make sure the credentials that would be submitted on successful login
- // are going to match the stored entry in the db.
- EXPECT_EQ(observed_form()->origin.spec(),
- form_manager()->GetPendingCredentials().origin.spec());
- EXPECT_EQ(observed_form()->signon_realm,
- form_manager()->GetPendingCredentials().signon_realm);
- EXPECT_EQ(observed_form()->action,
- form_manager()->GetPendingCredentials().action);
- EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
- EXPECT_EQ(saved_match()->password_value,
- form_manager()->GetPendingCredentials().password_value);
- EXPECT_EQ(saved_match()->username_value,
- form_manager()->GetPendingCredentials().username_value);
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_element.empty());
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_value.empty());
-}
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ form_manager_->Fill();
+}
+
+// PasswordFormManager should always send fill data to renderer, even for
+// sign-up forms (no "current-password" field, i.e., no password field to fill
+// into). However, for sign-up forms, no particular password field should be
+// identified for filling. That way, Chrome won't disturb the user by filling
+// the sign-up form, but will be able to offer a manual fallback for filling if
+// the form was misclassified.
+TEST_F(PasswordFormManagerTest, AutofillSignUpForm) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ // Make |observed_form_| to be sign-up form.
+ observed_form_.fields.back().autocomplete_attribute = "new-password";
+
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
+
+ PasswordFormGenerationData generation_data;
+ EXPECT_CALL(driver_, FormEligibleForGenerationFound(_))
+ .WillOnce(SaveArg<0>(&generation_data));
+
+ CreateFormManager(observed_form_);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+
+ task_runner_->FastForwardUntilNoTasksRemain();
+ constexpr uint32_t kNoID = FormFieldData::kNotSetFormControlRendererId;
+ EXPECT_EQ(kNoID, fill_data.password_field.unique_renderer_id);
+ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
+#if defined(OS_IOS)
+ EXPECT_EQ(ASCIIToUTF16("sign-in"), generation_data.form_name);
+ EXPECT_EQ(ASCIIToUTF16("password"), generation_data.new_password_element);
+ EXPECT_EQ(base::string16(), generation_data.confirmation_password_element);
+#else
+ EXPECT_EQ(observed_form_.fields.back().unique_renderer_id,
+ generation_data.new_password_renderer_id);
+ EXPECT_EQ(kNoID, generation_data.confirmation_password_renderer_id);
+#endif
+}
+
+// Check that generation signal is sent the the renderer when new password
+// fields are marked with autocomplete attribute.
+TEST_F(PasswordFormManagerTest, GenerationOnNewAndConfirmPasswordFields) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ // Make |observed_form_| to be sign-up form.
+ observed_form_.fields.back().autocomplete_attribute = "new-password";
+ const uint32_t new_password_render_id =
+ observed_form_.fields.back().unique_renderer_id;
+ // Add a confirmation field.
+ FormFieldData field;
+ const uint32_t confirm_password_render_id = new_password_render_id + 1;
+ field.unique_renderer_id = confirm_password_render_id;
+ field.form_control_type = "password";
+ field.autocomplete_attribute = "new-password";
+ observed_form_.fields.push_back(field);
-// Test provisionally saving a new login in presence of other saved logins.
-TEST_F(PasswordFormManagerTest, TestAdditionalLogin) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
+ PasswordFormGenerationData generation_data;
+ EXPECT_CALL(driver_, FormEligibleForGenerationFound(_))
+ .WillOnce(SaveArg<0>(&generation_data));
- base::string16 new_user = ASCIIToUTF16("newuser");
- base::string16 new_pass = ASCIIToUTF16("newpass");
- ASSERT_NE(new_user, saved_match()->username_value);
+ CreateFormManager(observed_form_);
+ fetcher_->NotifyFetchCompleted();
+
+ task_runner_->FastForwardUntilNoTasksRemain();
+#if defined(OS_IOS)
+ EXPECT_EQ(ASCIIToUTF16("sign-in"), generation_data.form_name);
+ EXPECT_EQ(ASCIIToUTF16("password"), generation_data.new_password_element);
+ EXPECT_EQ(base::string16(), generation_data.confirmation_password_element);
+#else
+ EXPECT_EQ(new_password_render_id, generation_data.new_password_renderer_id);
+ EXPECT_EQ(confirm_password_render_id,
+ generation_data.confirmation_password_renderer_id);
+#endif
+}
+
+TEST_F(PasswordFormManagerTest, AutofillWithBlacklistedMatch) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
+ fetcher_->SetNonFederated({&saved_match_});
+ fetcher_->SetBlacklisted({&blacklisted_match_});
+ fetcher_->NotifyFetchCompleted();
+
+ task_runner_->FastForwardUntilNoTasksRemain();
+
+ EXPECT_EQ(observed_form_.url, fill_data.origin);
+ EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
+ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
+}
+
+TEST_F(PasswordFormManagerTest, SetSubmitted) {
+ EXPECT_FALSE(form_manager_->is_submitted());
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ EXPECT_TRUE(form_manager_->is_submitted());
- PasswordForm new_login = *observed_form();
- new_login.username_value = new_user;
- new_login.password_value = new_pass;
- new_login.preferred = true;
+ FormData another_form = submitted_form_;
+ another_form.name += ASCIIToUTF16("1");
+#if !defined(OS_IOS)
+ // |another_form| is managed because the same |unique_renderer_id| as
+ // |observed_form_|.
+ EXPECT_TRUE(form_manager_->ProvisionallySave(another_form, &driver_));
+ EXPECT_TRUE(form_manager_->is_submitted());
+#endif
+}
+
+TEST_F(PasswordFormManagerTest, SetSubmittedMultipleTimes) {
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ EXPECT_TRUE(form_manager_->is_submitted());
+
+ // Make the submitted form to be invalid password form.
+ submitted_form_.fields.clear();
+
+ // Expect that |form_manager_| is still in submitted state because the first
+ // time the submited form was valid.
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ EXPECT_TRUE(form_manager_->is_submitted());
+ EXPECT_TRUE(form_manager_->GetSubmittedForm());
+}
+
+// Tests that when PasswordFormManager receives saved matches it waits for
+// server predictions and fills on receving them.
+TEST_F(PasswordFormManagerTest, ServerPredictionsWithinDelay) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ // Expects no filling on save matches receiving.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+ Mock::VerifyAndClearExpectations(&driver_);
+
+ std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
+ observed_form_, {std::make_pair(2, autofill::PASSWORD)});
+
+ // Expect filling without delay on receiving server predictions.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
+ form_manager_->ProcessServerPredictions(predictions);
+ Mock::VerifyAndClearExpectations(&driver_);
+
+ // Expect no filling on receving predictions again.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ form_manager_->ProcessServerPredictions(predictions);
+}
+
+// Tests that PasswordFormManager fills after some delay even without
+// server predictions.
+TEST_F(PasswordFormManagerTest, ServerPredictionsAfterDelay) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+ // Expect filling after passing filling delay.
+
+ // Simulate passing filling delay.
+ task_runner_->FastForwardUntilNoTasksRemain();
+ Mock::VerifyAndClearExpectations(&driver_);
- form_manager()->ProvisionallySave(new_login);
+ std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
+ observed_form_, {std::make_pair(2, autofill::PASSWORD)});
+
+ // Expect filling on receiving server predictions because it was less than
+ // kMaxTimesAutofill attempts to fill.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
+ form_manager_->ProcessServerPredictions(predictions);
+ task_runner_->FastForwardUntilNoTasksRemain();
+}
+
+// Tests that filling happens immediately if server predictions are received
+// before saved matches.
+TEST_F(PasswordFormManagerTest, ServerPredictionsBeforeFetcher) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ // Expect no filling after receiving saved matches from |fetcher_|, since
+ // |form_manager| is waiting for server-side predictions.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ CreateFormManager(observed_form_);
- // The username value differs from the saved match, so this is a new login.
- EXPECT_TRUE(form_manager()->IsNewLogin());
+ std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
+ observed_form_, {std::make_pair(2, autofill::PASSWORD)});
+ form_manager_->ProcessServerPredictions(predictions);
+ Mock::VerifyAndClearExpectations(&driver_);
- EXPECT_EQ(observed_form()->origin.spec(),
- form_manager()->GetPendingCredentials().origin.spec());
- EXPECT_EQ(observed_form()->signon_realm,
- form_manager()->GetPendingCredentials().signon_realm);
- EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
- EXPECT_EQ(new_pass, form_manager()->GetPendingCredentials().password_value);
- EXPECT_EQ(new_user, form_manager()->GetPendingCredentials().username_value);
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_element.empty());
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_value.empty());
+ // Expect filling without delay on receiving server predictions.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
}
-// Test blacklisting in the presence of saved results.
-TEST_F(PasswordFormManagerTest, TestBlacklist) {
- saved_match()->origin = observed_form()->origin;
- saved_match()->action = observed_form()->action;
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- PasswordForm new_login = *observed_form();
- new_login.username_value = ASCIIToUTF16("newuser");
- new_login.password_value = ASCIIToUTF16("newpass");
- // Pretend Chrome detected a form submission with |new_login|.
- form_manager()->ProvisionallySave(new_login);
-
- EXPECT_TRUE(form_manager()->IsNewLogin());
- EXPECT_EQ(observed_form()->origin.spec(),
- form_manager()->GetPendingCredentials().origin.spec());
- EXPECT_EQ(observed_form()->signon_realm,
- form_manager()->GetPendingCredentials().signon_realm);
-
- const PasswordForm pending_form = form_manager()->GetPendingCredentials();
- PasswordForm actual_blacklisted_form =
- password_manager_util::MakeNormalizedBlacklistedForm(
- PasswordStore::FormDigest(*observed_form()));
- // Now pretend the user wants to never save passwords on this origin. Chrome
- // is supposed to only request blacklisting of a single form.
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- PermanentlyBlacklist(PasswordStore::FormDigest(*observed_form())))
- .WillOnce(Return(actual_blacklisted_form));
- form_manager()->PermanentlyBlacklist();
- EXPECT_EQ(pending_form, form_manager()->GetPendingCredentials());
- // The PasswordFormManager should have updated its knowledge of blacklisting
- // without waiting for PasswordStore updates.
- EXPECT_TRUE(form_manager()->IsBlacklisted());
- EXPECT_THAT(form_manager()->GetBlacklistedMatches(),
- ElementsAre(Pointee(actual_blacklisted_form)));
-}
+// Tests creating pending credentials when the password store is empty.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsEmptyStore) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
-// Test that stored blacklisted forms are correctly evaluated for whether they
-// apply to the observed form.
-TEST_F(PasswordFormManagerTest, TestBlacklistMatching) {
- // Applies despite different element names and path.
- PasswordForm blacklisted_match = *observed_form();
- blacklisted_match.origin = GURL("http://accounts.google.com/a/LoginAuth1234");
- blacklisted_match.username_element = ASCIIToUTF16("Element1");
- blacklisted_match.password_element = ASCIIToUTF16("Element2");
- blacklisted_match.submit_element = ASCIIToUTF16("Element3");
- blacklisted_match.blacklisted_by_user = true;
-
- fake_form_fetcher()->SetNonFederated({saved_match()});
- fake_form_fetcher()->SetBlacklisted({&blacklisted_match});
- fake_form_fetcher()->NotifyFetchCompleted();
- EXPECT_TRUE(form_manager()->IsBlacklisted());
- EXPECT_THAT(form_manager()->GetBlacklistedMatches(),
- ElementsAre(Pointee(blacklisted_match)));
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
- EXPECT_EQ(*saved_match(), *form_manager()->preferred_match());
-}
+ const base::Time kNow = base::Time::Now();
-// Test that even in the presence of blacklisted matches, the non-blacklisted
-// ones are still autofilled.
-TEST_F(PasswordFormManagerTest, AutofillBlacklisted) {
- PasswordForm saved_form = *observed_form();
- saved_form.username_value = ASCIIToUTF16("user");
- saved_form.password_value = ASCIIToUTF16("pass");
-
- PasswordForm blacklisted = *observed_form();
- blacklisted.blacklisted_by_user = true;
- blacklisted.username_value.clear();
-
- autofill::PasswordFormFillData fill_data;
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .WillOnce(SaveArg<0>(&fill_data));
-
- fake_form_fetcher()->SetNonFederated({&saved_form});
- fake_form_fetcher()->SetBlacklisted({&blacklisted});
- fake_form_fetcher()->NotifyFetchCompleted();
- EXPECT_EQ(1u, form_manager()->GetBlacklistedMatches().size());
- EXPECT_TRUE(form_manager()->IsBlacklisted());
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
- EXPECT_TRUE(fill_data.additional_logins.empty());
-}
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
-// If PSL-matched credentials had been suggested, but the user has overwritten
-// the password, the provisionally saved credentials should no longer be
-// considered as PSL-matched, so that the exception for not prompting before
-// saving PSL-matched credentials should no longer apply.
-TEST_F(PasswordFormManagerTest,
- OverriddenPSLMatchedCredentialsNotMarkedAsPSLMatched) {
- // The suggestion needs to be PSL-matched.
- SetNonFederatedAndNotifyFetchCompleted({psl_saved_match()});
-
- // User modifies the suggested password and submits the form.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value =
- saved_match()->password_value + ASCIIToUTF16("modify");
- form_manager()->ProvisionallySave(credentials);
-
- EXPECT_TRUE(form_manager()->IsNewLogin());
- EXPECT_FALSE(form_manager()->IsPendingCredentialsPublicSuffixMatch());
+ const PasswordForm& pending_credentials =
+ form_manager_->GetPendingCredentials();
+ CheckPendingCredentials(parsed_submitted_form_, pending_credentials);
+ EXPECT_GE(pending_credentials.date_last_used, kNow);
+ EXPECT_EQ(UserAction::kOverrideUsernameAndPassword,
+ form_manager_->GetMetricsRecorder()->GetUserAction());
}
-// Test that if a PSL-matched suggestion is saved on a new origin, its metadata
-// are correctly updated.
-TEST_F(PasswordFormManagerTest, PSLMatchedCredentialsMetadataUpdated) {
- PasswordForm psl_suggestion = *saved_match();
- psl_suggestion.is_public_suffix_match = true;
- SetNonFederatedAndNotifyFetchCompleted({&psl_suggestion});
-
- PasswordForm submitted_form(*observed_form());
- submitted_form.preferred = true;
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- form_manager()->ProvisionallySave(submitted_form);
-
- PasswordForm expected_saved_form(submitted_form);
- expected_saved_form.times_used = 1;
- expected_saved_form.all_possible_usernames.clear();
- expected_saved_form.form_data = saved_match()->form_data;
- expected_saved_form.origin = observed_form()->origin;
- expected_saved_form.is_public_suffix_match = true;
- PasswordForm actual_saved_form;
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- expected_available_field_types.insert(autofill::ACCOUNT_CREATION_PASSWORD);
- expected_available_field_types.insert(autofill::USERNAME);
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, expected_available_field_types, _,
- true, nullptr));
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _, _))
- .WillOnce(SaveArg<0>(&actual_saved_form));
- form_manager()->Save();
-
- // Can't verify time, so ignore it.
- actual_saved_form.date_created = base::Time();
- EXPECT_EQ(expected_saved_form, actual_saved_form);
-}
+// Tests creating pending credentials when new credentials are submitted and the
+// store has another credentials saved.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsNewCredentials) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-// Test that when the submitted form contains a "new-password" field, then the
-// password value is taken from there.
-TEST_F(PasswordFormManagerTest, TestNewLoginFromNewPasswordElement) {
- observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
- observed_form()->username_marked_by_site = true;
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- // User enters current and new credentials to the observed form.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("oldpassword");
- credentials.new_password_value = ASCIIToUTF16("newpassword");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, which should know this is a new login.
- EXPECT_TRUE(form_manager.IsNewLogin());
- EXPECT_EQ(credentials.origin, form_manager.GetPendingCredentials().origin);
- EXPECT_EQ(credentials.signon_realm,
- form_manager.GetPendingCredentials().signon_realm);
- EXPECT_EQ(credentials.action, form_manager.GetPendingCredentials().action);
- EXPECT_TRUE(form_manager.GetPendingCredentials().preferred);
- EXPECT_EQ(credentials.username_value,
- form_manager.GetPendingCredentials().username_value);
-
- // By this point, the PasswordFormManager should have promoted the new
- // password value to be the current password.
- EXPECT_EQ(credentials.new_password_value,
- form_manager.GetPendingCredentials().password_value);
- EXPECT_EQ(credentials.new_password_element,
- form_manager.GetPendingCredentials().password_element);
- EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());
- EXPECT_TRUE(
- form_manager.GetPendingCredentials().new_password_element.empty());
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ CheckPendingCredentials(parsed_submitted_form_,
+ form_manager_->GetPendingCredentials());
+ EXPECT_EQ(UserAction::kOverrideUsernameAndPassword,
+ form_manager_->GetMetricsRecorder()->GetUserAction());
+}
+
+// Tests that when submitted credentials are equal to already saved one then
+// pending credentials equal to saved match.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsAlreadySaved) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+
+ submitted_form_.fields[kUsernameFieldIndex].value =
+ saved_match_.username_value;
+ submitted_form_.fields[kPasswordFieldIndex].value =
+ saved_match_.password_value;
+
+ // Tests that depending on whether we fill on page load or account select that
+ // correct user action is recorded. Fill on account select is simulated by
+ // pretending we are in incognito mode.
+ for (bool is_incognito : {false, true}) {
+ EXPECT_CALL(client_, IsIncognito).WillOnce(Return(is_incognito));
+ form_manager_->Fill();
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ CheckPendingCredentials(/* expected */ saved_match_,
+ form_manager_->GetPendingCredentials());
+ EXPECT_EQ(is_incognito ? UserAction::kChoose : UserAction::kNone,
+ form_manager_->GetMetricsRecorder()->GetUserAction());
+ }
}
-TEST_F(PasswordFormManagerTest, TestUpdatePassword) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User submits credentials for the observed form using a username previously
- // stored, but a new password. Note that the observed form may have different
- // origin URL (as it does in this case) than the saved_match, but we want to
- // make sure the updated password is reflected in saved_match, because that is
- // what we autofilled.
- base::string16 new_pass = ASCIIToUTF16("test2");
- PasswordForm credentials = *observed_form();
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = new_pass;
- credentials.preferred = true;
- form_manager()->ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager()->IsNewLogin());
-
- // Make sure the credentials that would be submitted on successful login
- // are going to match the stored entry in the db. (This verifies correct
- // behaviour for bug 1074420).
- EXPECT_EQ(form_manager()->GetPendingCredentials().origin.spec(),
- saved_match()->origin.spec());
- EXPECT_EQ(form_manager()->GetPendingCredentials().signon_realm,
- saved_match()->signon_realm);
- EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
- EXPECT_EQ(new_pass, form_manager()->GetPendingCredentials().password_value);
-}
+// Tests that when submitted credentials are equal to already saved PSL
+// credentials.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsPSLMatchSaved) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ PasswordForm expected = saved_match_;
-TEST_F(PasswordFormManagerTest, TestUpdatePasswordFromNewPasswordElement) {
- // Add a new password field to the test form. The PasswordFormManager should
- // save the password from this field, instead of the current password field.
- observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {saved_match()});
-
- // User submits current and new credentials to the observed form.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = saved_match()->password_value;
- credentials.new_password_value = ASCIIToUTF16("test2");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager.IsNewLogin());
-
- // By now, the PasswordFormManager should have promoted the new password value
- // already to be the current password, and should no longer maintain any info
- // about the new password.
- EXPECT_EQ(credentials.new_password_value,
- form_manager.GetPendingCredentials().password_value);
- EXPECT_TRUE(
- form_manager.GetPendingCredentials().new_password_element.empty());
- EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());
+ saved_match_.origin = GURL("https://m.accounts.google.com/auth");
+ saved_match_.signon_realm = "https://m.accounts.google.com/";
+ saved_match_.is_public_suffix_match = true;
- // Trigger saving to exercise some special case handling for updating.
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- form_manager.Save();
+ submitted_form_.fields[kUsernameFieldIndex].value =
+ saved_match_.username_value;
+ submitted_form_.fields[kPasswordFieldIndex].value =
+ saved_match_.password_value;
- // The password should be updated.
- EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
- EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
- EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
- EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_EQ(UserAction::kChoosePslMatch,
+ form_manager_->GetMetricsRecorder()->GetUserAction());
}
-// Test that saved results are not ignored if they differ in paths for action or
-// origin.
-TEST_F(PasswordFormManagerTest, TestIgnoreResult_Paths) {
- PasswordForm observed(*observed_form());
- observed.origin = GURL("https://accounts.google.com/a/LoginAuth");
- observed.action = GURL("https://accounts.google.com/a/Login");
- observed.signon_realm = "https://accounts.google.com";
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), observed,
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
-
- PasswordForm saved_form = observed;
- saved_form.origin = GURL("https://accounts.google.com/a/OtherLoginAuth");
- saved_form.action = GURL("https://accounts.google.com/a/OtherLogin");
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {&saved_form});
-
- // Different paths for action / origin are okay.
- EXPECT_EQ(1u, form_manager.GetBestMatches().size());
- EXPECT_EQ(*form_manager.GetBestMatches().begin()->second, saved_form);
-}
+// Tests creating pending credentials when new credentials are different only in
+// password with already saved one.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsPasswordOverriden) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-// Test that saved empty action URL is updated with the submitted action URL.
-TEST_F(PasswordFormManagerTest, TestEmptyAction) {
- saved_match()->action = GURL();
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User logs in with the autofilled username / password from saved_match.
- PasswordForm login = *observed_form();
- login.username_value = saved_match()->username_value;
- login.password_value = saved_match()->password_value;
- form_manager()->ProvisionallySave(login);
- EXPECT_FALSE(form_manager()->IsNewLogin());
- // Chrome updates the saved PasswordForm entry with the action URL of the
- // observed form.
- EXPECT_EQ(observed_form()->action,
- form_manager()->GetPendingCredentials().action);
-}
+ PasswordForm expected = saved_match_;
+ expected.password_value += ASCIIToUTF16("1");
-TEST_F(PasswordFormManagerTest, TestUpdateAction) {
- saved_match()->action = GURL("http://accounts.google.com/a/ServiceLogin");
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User logs in with the autofilled username / password from saved_match.
- observed_form()->action = GURL("http://accounts.google.com/a/Login");
- PasswordForm login = *observed_form();
- login.username_value = saved_match()->username_value;
- login.password_value = saved_match()->password_value;
-
- form_manager()->ProvisionallySave(login);
- EXPECT_FALSE(form_manager()->IsNewLogin());
- // The observed action URL is different from the previously saved one. Chrome
- // should update the store by setting the pending credential's action URL to
- // be that of the currently observed form.
- EXPECT_EQ(observed_form()->action,
- form_manager()->GetPendingCredentials().action);
+ submitted_form_.fields[kUsernameFieldIndex].value =
+ saved_match_.username_value;
+ submitted_form_.fields[kPasswordFieldIndex].value = expected.password_value;
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_EQ(UserAction::kOverridePassword,
+ form_manager_->GetMetricsRecorder()->GetUserAction());
}
-TEST_F(PasswordFormManagerTest, TestDynamicAction) {
- fake_form_fetcher()->NotifyFetchCompleted();
+// Tests that when submitted credentials are equal to already saved one then
+// pending credentials equal to saved match.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsUpdate) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- observed_form()->action = GURL("http://accounts.google.com/a/Login");
- PasswordForm login(*observed_form());
- // The submitted action URL is different from the one observed on page load.
- login.action = GURL("http://www.google.com/new_action");
+ FormData submitted_form = observed_form_only_password_fields_;
+ submitted_form.fields[0].value = ASCIIToUTF16("strongpassword");
+ submitted_form.fields[1].value = ASCIIToUTF16("verystrongpassword");
- form_manager()->ProvisionallySave(login);
- EXPECT_TRUE(form_manager()->IsNewLogin());
- // Check that the provisionally saved action URL is the same as the submitted
- // action URL, not the one observed on page load.
- EXPECT_EQ(login.action, form_manager()->GetPendingCredentials().action);
-}
+ PasswordForm expected = saved_match_;
+ expected.password_value = ASCIIToUTF16("verystrongpassword");
-// Test that if the saved match has other possible usernames stored, and the
-// user chooses the main one, then the other possible usernames are dropped on
-// update.
-TEST_F(PasswordFormManagerTest, TestAlternateUsername_NoChange) {
- PasswordForm saved_form = *saved_match();
- saved_form.all_possible_usernames.push_back(
- ValueElementPair(ASCIIToUTF16("other_possible@gmail.com"),
- ASCIIToUTF16("other_username")));
-
- SetNonFederatedAndNotifyFetchCompleted({&saved_form});
-
- // The saved match has the right username already.
- PasswordForm login(*observed_form());
- login.preferred = true;
- login.username_value = saved_match()->username_value;
- login.password_value = saved_match()->password_value;
-
- form_manager()->ProvisionallySave(login);
-
- EXPECT_FALSE(form_manager()->IsNewLogin());
-
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _))
- .WillOnce(SaveArg<0>(&saved_result));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
-
- form_manager()->Save();
- // Should be only one password stored, and should not have
- // |all_possible_usernames| set anymore.
- EXPECT_EQ(saved_match()->username_value, saved_result.username_value);
- EXPECT_TRUE(saved_result.all_possible_usernames.empty());
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_EQ(UserAction::kOverridePassword,
+ form_manager_->GetMetricsRecorder()->GetUserAction());
}
+// Tests creating pending credentials when a change password form is submitted
+// and there are multipe saved forms.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsUpdateMultipleSaved) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ PasswordForm another_saved_match = saved_match_;
+ another_saved_match.username_value += ASCIIToUTF16("1");
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_, &another_saved_match});
-TEST_F(PasswordFormManagerTest,
- TestSendNotBlacklistedMessage_DroppedCredentials) {
- // There are cases, such as when a form is made explicitly for creating a new
- // password, where we may ignore saved credentials. Make sure that we still
- // allow generation in that case.
- PasswordForm signup_form(*observed_form());
- signup_form.new_password_element = base::ASCIIToUTF16("new_password_field");
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), signup_form,
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- PasswordForm simulated_result = CreateSavedMatch(false);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {&simulated_result});
-}
+ FormData submitted_form = observed_form_only_password_fields_;
+ submitted_form.fields[0].value = ASCIIToUTF16("strongpassword");
+ submitted_form.fields[1].value = ASCIIToUTF16("verystrongpassword");
-// Test that exactly one match for each username is chosen as a best match, even
-// though it is a PSL match.
-TEST_F(PasswordFormManagerTest, TestBestCredentialsForEachUsernameAreIncluded) {
- // Add a best scoring match. It should be in |best_matches| and chosen as a
- // prefferred match.
- PasswordForm best_scoring = *saved_match();
-
- // Add a match saved on another form, it has lower score. It should not be in
- // |best_matches|.
- PasswordForm other_form = *saved_match();
- other_form.password_element = ASCIIToUTF16("signup_password");
- other_form.username_element = ASCIIToUTF16("signup_username");
-
- // Add a match saved on another form with a different username. It should be
- // in |best_matches|.
- PasswordForm other_username = other_form;
- const base::string16 kUsername1 =
- other_username.username_value + ASCIIToUTF16("1");
- other_username.username_value = kUsername1;
-
- // Add a PSL match, it should not be in |best_matches|.
- PasswordForm psl_match = *psl_saved_match();
-
- // Add a PSL match with a different username. It should be in |best_matches|.
- PasswordForm psl_match_other = psl_match;
- const base::string16 kUsername2 =
- psl_match_other.username_value + ASCIIToUTF16("2");
- psl_match_other.username_value = kUsername2;
-
- autofill::PasswordFormFillData fill_data;
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .WillOnce(SaveArg<0>(&fill_data));
-
- SetNonFederatedAndNotifyFetchCompleted({&best_scoring, &other_form,
- &other_username, &psl_match,
- &psl_match_other});
-
- const std::map<base::string16, const PasswordForm*>& best_matches =
- form_manager()->GetBestMatches();
- EXPECT_EQ(3u, best_matches.size());
- EXPECT_NE(best_matches.end(),
- best_matches.find(saved_match()->username_value));
- EXPECT_EQ(*saved_match(),
- *best_matches.find(saved_match()->username_value)->second);
- EXPECT_NE(best_matches.end(), best_matches.find(kUsername1));
- EXPECT_NE(best_matches.end(), best_matches.find(kUsername2));
-
- EXPECT_EQ(*saved_match(), *form_manager()->preferred_match());
- EXPECT_EQ(2u, fill_data.additional_logins.size());
+ PasswordForm expected = saved_match_;
+ expected.password_value = ASCIIToUTF16("verystrongpassword");
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
}
-TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernames) {
- const ValueElementPair kUsernameOther(ASCIIToUTF16("other username"),
- ASCIIToUTF16("other_username_id"));
+// Tests creating pending credentials when the password field has an empty name.
+TEST_F(PasswordFormManagerTest, CreatePendingCredentialsEmptyName) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
- fake_form_fetcher()->NotifyFetchCompleted();
+ FormData anonymous_signup = observed_form_;
+ // There is an anonymous password field.
+ anonymous_signup.fields[2].name.clear();
+ anonymous_signup.fields[2].value = ASCIIToUTF16("a password");
+ // Mark the password field as new-password.
+ std::map<FormSignature, FormPredictions> predictions = CreatePredictions(
+ observed_form_, {std::make_pair(2, autofill::ACCOUNT_CREATION_PASSWORD)});
- PasswordForm credentials(*observed_form());
- credentials.all_possible_usernames.push_back(
- ValueElementPair(ASCIIToUTF16("543-43-1234"), ASCIIToUTF16("id1")));
- credentials.all_possible_usernames.push_back(
- ValueElementPair(ASCIIToUTF16("378282246310005"), ASCIIToUTF16("id2")));
- credentials.all_possible_usernames.push_back(kUsernameOther);
- credentials.username_value = ASCIIToUTF16("test@gmail.com");
- credentials.preferred = true;
+ form_manager_->ProcessServerPredictions(predictions);
- form_manager()->ProvisionallySave(credentials);
+ EXPECT_TRUE(form_manager_->ProvisionallySave(anonymous_signup, &driver_));
+ EXPECT_EQ(ASCIIToUTF16("a password"),
+ form_manager_->GetPendingCredentials().password_value);
+}
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _, _))
- .WillOnce(SaveArg<0>(&saved_result));
- form_manager()->Save();
+// Tests that there is no crash even when the observed form is a not password
+// form and the submitted form is password form.
+TEST_F(PasswordFormManagerTest, NoCrashOnNonPasswordForm) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ FormData form_without_password_fields = observed_form_;
+ // Remove the password field.
+ form_without_password_fields.fields.resize(kPasswordFieldIndex);
+ CreateFormManager(form_without_password_fields);
+ fetcher_->NotifyFetchCompleted();
- // Possible credit card number and SSN are stripped.
- EXPECT_THAT(saved_result.all_possible_usernames,
- UnorderedElementsAre(kUsernameOther));
-}
+ FormData submitted_form = observed_form_;
+ submitted_form.fields[kUsernameFieldIndex].value = ASCIIToUTF16("username");
+ submitted_form.fields[kPasswordFieldIndex].value = ASCIIToUTF16("password");
-TEST_F(PasswordFormManagerTest, TestSanitizePossibleUsernamesDuplicates) {
- const ValueElementPair kUsernameSsn(ASCIIToUTF16("511-32-9830"),
- ASCIIToUTF16("ssn_id"));
- const ValueElementPair kUsernameEmail(ASCIIToUTF16("test@gmail.com"),
- ASCIIToUTF16("email_id"));
- const ValueElementPair kUsernameDuplicate(ASCIIToUTF16("duplicate"),
- ASCIIToUTF16("duplicate_id"));
- const ValueElementPair kUsernameRandom(ASCIIToUTF16("random"),
- ASCIIToUTF16("random_id"));
-
- fake_form_fetcher()->NotifyFetchCompleted();
-
- PasswordForm credentials(*observed_form());
- credentials.all_possible_usernames.push_back(kUsernameSsn);
- credentials.all_possible_usernames.push_back(kUsernameDuplicate);
- credentials.all_possible_usernames.push_back(kUsernameDuplicate);
- credentials.all_possible_usernames.push_back(kUsernameRandom);
- credentials.all_possible_usernames.push_back(kUsernameEmail);
- credentials.username_value = kUsernameEmail.first;
- credentials.preferred = true;
-
- form_manager()->ProvisionallySave(credentials);
-
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _, _))
- .WillOnce(SaveArg<0>(&saved_result));
- form_manager()->Save();
-
- // SSN, duplicate in |all_possible_usernames| and duplicate of
- // |username_value| all removed.
- EXPECT_THAT(saved_result.all_possible_usernames,
- UnorderedElementsAre(kUsernameDuplicate, kUsernameRandom));
+ // Expect no crash.
+ form_manager_->ProvisionallySave(submitted_form, &driver_);
}
-TEST_F(PasswordFormManagerTest, TestAllPossiblePasswords) {
- fake_form_fetcher()->NotifyFetchCompleted();
+TEST_F(PasswordFormManagerTest, IsEqualToSubmittedForm) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
- ValueElementPair pair1 = {ASCIIToUTF16("pass1"), ASCIIToUTF16("el1")};
- ValueElementPair pair2 = {ASCIIToUTF16("pass2"), ASCIIToUTF16("el2")};
- ValueElementPair pair3 = {ASCIIToUTF16("pass3"), ASCIIToUTF16("el3")};
+ FormData submitted_form = observed_form_;
+ submitted_form.fields[kUsernameFieldIndex].value =
+ saved_match_.username_value;
+ submitted_form.fields[kPasswordFieldIndex].value =
+ saved_match_.password_value;
- PasswordForm credentials(*observed_form());
- credentials.all_possible_passwords.push_back(pair1);
- credentials.all_possible_passwords.push_back(pair2);
- credentials.all_possible_passwords.push_back(pair3);
+ // No submitted form yet.
+ EXPECT_FALSE(form_manager_->IsEqualToSubmittedForm(submitted_form));
- form_manager()->ProvisionallySave(credentials);
+ ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
- EXPECT_THAT(form_manager()->GetPendingCredentials().all_possible_passwords,
- UnorderedElementsAre(pair1, pair2, pair3));
-}
+ observed_form_.unique_renderer_id += 10;
+ observed_form_.fields.clear();
-// Test that public-suffix-matched credentials score lower than same-origin
-// ones.
-TEST_F(PasswordFormManagerTest, TestScoringPublicSuffixMatch) {
- PasswordForm base_match = CreateSavedMatch(false);
- base_match.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth");
- base_match.action = GURL("http://accounts.google.com/a/ServiceLogin");
-
- PasswordForm psl_match = base_match;
- psl_match.is_public_suffix_match = true;
-
- // Change origin and action URLs to decrease the score.
- PasswordForm same_origin_match = base_match;
- psl_match.origin = GURL("http://accounts.google.com/a/ServiceLoginAuth2");
- psl_match.action = GURL("http://accounts.google.com/a/ServiceLogin2");
-
- autofill::PasswordFormFillData fill_data;
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .WillOnce(SaveArg<0>(&fill_data));
-
- SetNonFederatedAndNotifyFetchCompleted({&psl_match, &same_origin_match});
- EXPECT_TRUE(fill_data.additional_logins.empty());
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
- EXPECT_FALSE(
- form_manager()->GetBestMatches().begin()->second->is_public_suffix_match);
-}
+ EXPECT_TRUE(form_manager_->IsEqualToSubmittedForm(observed_form_));
-TEST_F(PasswordFormManagerTest, AndroidCredentialsAreAutofilled) {
- // Although Android-based credentials are treated similarly to PSL-matched
- // credentials in some respects, they should be autofilled as opposed to be
- // filled on username-select.
- PasswordForm android_login;
- android_login.signon_realm = "android://hash@com.google.android";
- android_login.origin = GURL("android://hash@com.google.android/");
- android_login.is_affiliation_based_match = true;
- android_login.username_value = saved_match()->username_value;
- android_login.password_value = saved_match()->password_value;
- android_login.preferred = false;
- android_login.times_used = 42;
-
- autofill::PasswordFormFillData fill_data;
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .WillOnce(SaveArg<0>(&fill_data));
-
- SetNonFederatedAndNotifyFetchCompleted({&android_login});
- EXPECT_TRUE(fill_data.additional_logins.empty());
- EXPECT_FALSE(fill_data.wait_for_username);
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
-
- // When the user submits the filled form, no copy of the credential should be
- // created, instead the usage counter of the original credential should be
- // incremented in-place, as if it were a regular credential for that website.
- PasswordForm credential(*observed_form());
- credential.username_value = android_login.username_value;
- credential.password_value = android_login.password_value;
- credential.preferred = true;
- form_manager()->ProvisionallySave(credential);
- EXPECT_FALSE(form_manager()->IsNewLogin());
-
- PasswordForm updated_credential;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _))
- .WillOnce(testing::SaveArg<0>(&updated_credential));
- form_manager()->Save();
-
- EXPECT_EQ(android_login.username_value, updated_credential.username_value);
- EXPECT_EQ(android_login.password_value, updated_credential.password_value);
- EXPECT_EQ(android_login.times_used + 1, updated_credential.times_used);
- EXPECT_TRUE(updated_credential.preferred);
- EXPECT_EQ(GURL(), updated_credential.action);
- EXPECT_EQ(base::string16(), updated_credential.username_element);
- EXPECT_EQ(base::string16(), updated_credential.password_element);
- EXPECT_EQ(base::string16(), updated_credential.submit_element);
+ observed_form_.action = GURL("https://example.com");
+ EXPECT_FALSE(form_manager_->IsEqualToSubmittedForm(observed_form_));
}
-// Credentials saved through Android apps should always be shown in the drop-
-// down menu, unless there is a better-scoring match with the same username.
-TEST_F(PasswordFormManagerTest, AndroidCredentialsAreProtected) {
- const char kTestUsername1[] = "test-user@gmail.com";
- const char kTestUsername2[] = "test-other-user@gmail.com";
- const char kTestWebPassword[] = "web-password";
- const char kTestAndroidPassword1[] = "android-password-alpha";
- const char kTestAndroidPassword2[] = "android-password-beta";
-
- // Suppose there is one login saved through the website, and two other coming
- // from Android: the first has the same username as the web-based credential,
- // so it should be suppressed, but the second has a different username, so it
- // should be shown.
- PasswordForm website_login = CreateSavedMatch(false);
- website_login.username_value = ASCIIToUTF16(kTestUsername1);
- website_login.password_value = ASCIIToUTF16(kTestWebPassword);
-
- PasswordForm android_same;
- android_same.signon_realm = "android://hash@com.google.android";
- android_same.origin = GURL("android://hash@com.google.android/");
- android_same.username_value = ASCIIToUTF16(kTestUsername1);
- android_same.password_value = ASCIIToUTF16(kTestAndroidPassword1);
-
- PasswordForm android_other = android_same;
- android_other.username_value = ASCIIToUTF16(kTestUsername2);
- android_other.password_value = ASCIIToUTF16(kTestAndroidPassword2);
-
- std::vector<std::unique_ptr<PasswordForm>> expected_matches;
- expected_matches.push_back(std::make_unique<PasswordForm>(website_login));
- expected_matches.push_back(std::make_unique<PasswordForm>(android_other));
-
- autofill::PasswordFormFillData fill_data;
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .WillOnce(SaveArg<0>(&fill_data));
- SetNonFederatedAndNotifyFetchCompleted(
- {&website_login, &android_same, &android_other});
-
- EXPECT_FALSE(fill_data.wait_for_username);
- EXPECT_EQ(1u, fill_data.additional_logins.size());
-
- std::vector<std::unique_ptr<PasswordForm>> actual_matches;
- for (const auto& username_match_pair : form_manager()->GetBestMatches())
- actual_matches.push_back(
- std::make_unique<PasswordForm>(*username_match_pair.second));
- EXPECT_THAT(actual_matches,
- UnorderedPasswordFormElementsAre(&expected_matches));
-}
+// Tests that when credentials with a new username (i.e. not saved yet) is
+// successfully submitted, then they are saved correctly.
+TEST_F(PasswordFormManagerTest, SaveNewCredentials) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+
+ FormData submitted_form = observed_form_;
+ base::string16 new_username = saved_match_.username_value + ASCIIToUTF16("1");
+ base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
+ submitted_form.fields[kUsernameFieldIndex].value = new_username;
+ submitted_form.fields[kPasswordFieldIndex].value = new_password;
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+ EXPECT_TRUE(form_manager_->IsNewLogin());
+
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ PasswordForm saved_form;
+ std::vector<const PasswordForm*> best_matches;
+ EXPECT_CALL(form_saver, Save(_, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_form), SaveArg<1>(&best_matches)));
+ EXPECT_CALL(client_, UpdateFormManagers());
+
+ form_manager_->Save();
+
+ std::string expected_signon_realm = submitted_form.url.GetOrigin().spec();
+ EXPECT_EQ(submitted_form.url, saved_form.origin);
+ EXPECT_EQ(expected_signon_realm, saved_form.signon_realm);
+ EXPECT_EQ(new_username, saved_form.username_value);
+ EXPECT_EQ(new_password, saved_form.password_value);
+ EXPECT_TRUE(saved_form.preferred);
+
+ EXPECT_EQ(submitted_form.fields[kUsernameFieldIndex].name,
+ saved_form.username_element);
+ EXPECT_EQ(submitted_form.fields[kPasswordFieldIndex].name,
+ saved_form.password_element);
+ EXPECT_EQ(std::vector<const PasswordForm*>{&saved_match_}, best_matches);
+
+ // Check UKM metrics.
+ form_manager_.reset();
+ ExpectedGenerationUKM expected_metrics = {
+ {} /* shown manually */,
+ 0 /* password generated */,
+ {} /* generated password is not modified */};
+
+ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
+}
+
+// Check that if there is saved PSL matched credentials with the same
+// username/password as in submitted form, then the saved form is the same
+// already saved only with origin and signon_realm from the submitted form.
+TEST_F(PasswordFormManagerTest, SavePSLToAlreadySaved) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&psl_saved_match_});
+
+ FormData submitted_form = observed_form_;
+ // Change
+ submitted_form.fields[kUsernameFieldIndex].value =
+ psl_saved_match_.username_value;
+ submitted_form.fields[kPasswordFieldIndex].value =
+ psl_saved_match_.password_value;
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+ EXPECT_TRUE(form_manager_->IsNewLogin());
+ EXPECT_TRUE(form_manager_->IsPendingCredentialsPublicSuffixMatch());
+
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ PasswordForm saved_form;
+ std::vector<const PasswordForm*> best_matches;
+ EXPECT_CALL(form_saver, Save(_, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&saved_form), SaveArg<1>(&best_matches)));
+
+ form_manager_->Save();
+
+ EXPECT_EQ(submitted_form.url, saved_form.origin);
+ EXPECT_EQ(GetSignonRealm(submitted_form.url), saved_form.signon_realm);
+ EXPECT_EQ(saved_form.username_value, psl_saved_match_.username_value);
+ EXPECT_EQ(saved_form.password_value, psl_saved_match_.password_value);
+ EXPECT_EQ(saved_form.username_element, psl_saved_match_.username_element);
+ EXPECT_EQ(saved_form.password_element, psl_saved_match_.password_element);
+
+ EXPECT_TRUE(saved_form.preferred);
+
+ EXPECT_EQ(std::vector<const PasswordForm*>{&psl_saved_match_}, best_matches);
+}
+
+// Tests that when credentials with already saved username but with a new
+// password are submitted, then the saved password is updated.
+TEST_F(PasswordFormManagerTest, OverridePassword) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+
+ FormData submitted_form = observed_form_;
+ base::string16 username = saved_match_.username_value;
+ base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
+ submitted_form.fields[kUsernameFieldIndex].value = username;
+ submitted_form.fields[kPasswordFieldIndex].value = new_password;
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+ EXPECT_FALSE(form_manager_->IsNewLogin());
+ EXPECT_TRUE(form_manager_->IsPasswordUpdate());
+
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ PasswordForm updated_form;
+ EXPECT_CALL(form_saver, Update(_, ElementsAre(Pointee(saved_match_)),
+ saved_match_.password_value))
+ .WillOnce(SaveArg<0>(&updated_form));
+
+ form_manager_->Save();
+
+ EXPECT_TRUE(ArePasswordFormUniqueKeysEqual(saved_match_, updated_form));
+ EXPECT_TRUE(updated_form.preferred);
+ EXPECT_EQ(new_password, updated_form.password_value);
+}
+
+// Tests that when the user changes password on a change password form then the
+// saved password is updated.
+TEST_F(PasswordFormManagerTest, UpdatePasswordOnChangePasswordForm) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ CreateFormManager(observed_form_only_password_fields_);
+ PasswordForm not_best_saved_match = saved_match_;
+ not_best_saved_match.preferred = false;
+ PasswordForm saved_match_another_username = saved_match_;
+ saved_match_another_username.username_value += ASCIIToUTF16("1");
-TEST_F(PasswordFormManagerTest, InvalidActionURLsDoNotMatch) {
- PasswordForm invalid_action_form(*observed_form());
- invalid_action_form.action = GURL("http://");
- ASSERT_FALSE(invalid_action_form.action.is_valid());
- ASSERT_FALSE(invalid_action_form.action.is_empty());
- // Non-empty invalid action URLs should not match other actions.
- // First when the compared form has an invalid URL:
- EXPECT_EQ(0, form_manager()->DoesManage(invalid_action_form, nullptr) &
- PasswordFormManager::RESULT_ACTION_MATCH);
- // Then when the observed form has an invalid URL:
- PasswordForm valid_action_form(*observed_form());
- PasswordFormManager invalid_manager(
- password_manager(), client(), client()->driver(), invalid_action_form,
- std::make_unique<MockFormSaver>(), fake_form_fetcher());
- invalid_manager.Init(nullptr);
- EXPECT_EQ(0, invalid_manager.DoesManage(valid_action_form, nullptr) &
- PasswordFormManager::RESULT_ACTION_MATCH);
-}
+ SetNonFederatedAndNotifyFetchCompleted(
+ {&saved_match_, &not_best_saved_match, &saved_match_another_username});
-TEST_F(PasswordFormManagerTest, EmptyActionURLsDoNotMatchNonEmpty) {
- PasswordForm empty_action_form(*observed_form());
- empty_action_form.action = GURL();
- ASSERT_FALSE(empty_action_form.action.is_valid());
- ASSERT_TRUE(empty_action_form.action.is_empty());
- // First when the compared form has an empty URL:
- EXPECT_EQ(0, form_manager()->DoesManage(empty_action_form, nullptr) &
- PasswordFormManager::RESULT_ACTION_MATCH);
- // Then when the observed form has an empty URL:
- PasswordForm valid_action_form(*observed_form());
- PasswordFormManager empty_action_manager(
- password_manager(), client(), client()->driver(), empty_action_form,
- std::make_unique<MockFormSaver>(), fake_form_fetcher());
- empty_action_manager.Init(nullptr);
- EXPECT_EQ(0, empty_action_manager.DoesManage(valid_action_form, nullptr) &
- PasswordFormManager::RESULT_ACTION_MATCH);
-}
+ FormData submitted_form = observed_form_only_password_fields_;
+ submitted_form.fields[0].value = saved_match_.password_value;
+ base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
+ submitted_form.fields[1].value = new_password;
-TEST_F(PasswordFormManagerTest, NonHTMLFormsDoNotMatchHTMLForms) {
- ASSERT_EQ(PasswordForm::Scheme::kHtml, observed_form()->scheme);
- PasswordForm non_html_form(*observed_form());
- non_html_form.scheme = PasswordForm::Scheme::kDigest;
- EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
- form_manager()->DoesManage(non_html_form, nullptr));
-
- // The other way round: observing a non-HTML form, don't match a HTML form.
- PasswordForm html_form(*observed_form());
- PasswordFormManager non_html_manager(
- password_manager(), client(), kNoDriver, non_html_form,
- std::make_unique<MockFormSaver>(), fake_form_fetcher());
- non_html_manager.Init(nullptr);
- EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
- non_html_manager.DoesManage(html_form, nullptr));
-}
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+ EXPECT_FALSE(form_manager_->IsNewLogin());
+ EXPECT_TRUE(form_manager_->IsPasswordUpdate());
-TEST_F(PasswordFormManagerTest, OriginCheck_HostsMatchExactly) {
- // Host part of origins must match exactly, not just by prefix.
- PasswordForm form_longer_host(*observed_form());
- form_longer_host.origin = GURL("http://accounts.google.com.au/a/LoginAuth");
- // Check that accounts.google.com does not match accounts.google.com.au.
- EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
- form_manager()->DoesManage(form_longer_host, nullptr));
-}
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ PasswordForm updated_form;
+ EXPECT_CALL(form_saver,
+ Update(_,
+ UnorderedElementsAre(
+ Pointee(saved_match_), Pointee(not_best_saved_match),
+ Pointee(saved_match_another_username)),
+ saved_match_.password_value))
+ .WillOnce(SaveArg<0>(&updated_form));
-TEST_F(PasswordFormManagerTest, OriginCheck_MoreSecureSchemePathsMatchPrefix) {
- // If the URL scheme of the observed form is HTTP, and the compared form is
- // HTTPS, then the compared form can extend the path.
- PasswordForm form_longer_path(*observed_form());
- form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
- EXPECT_NE(0, form_manager()->DoesManage(form_longer_path, nullptr) &
- PasswordFormManager::RESULT_ORIGINS_OR_FRAMES_MATCH);
-}
+ form_manager_->Save();
-TEST_F(PasswordFormManagerTest,
- OriginCheck_NotMoreSecureSchemePathsMatchExactly) {
- // If the origin URL scheme of the compared form is not more secure than that
- // of the observed form, then the paths must match exactly.
- PasswordForm form_longer_path(*observed_form());
- form_longer_path.origin = GURL("http://accounts.google.com/a/LoginAuth/sec");
- // Check that /a/LoginAuth does not match /a/LoginAuth/more.
- EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
- form_manager()->DoesManage(form_longer_path, nullptr));
-
- PasswordForm secure_observed_form(*observed_form());
- secure_observed_form.origin = GURL("https://accounts.google.com/a/LoginAuth");
- PasswordFormManager secure_manager(
- password_manager(), client(), client()->driver(), secure_observed_form,
- std::make_unique<MockFormSaver>(), fake_form_fetcher());
- secure_manager.Init(nullptr);
- // Also for HTTPS in the observed form, and HTTP in the compared form, an
- // exact path match is expected.
- EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
- secure_manager.DoesManage(form_longer_path, nullptr));
- // Not even upgrade to HTTPS in the compared form should help.
- form_longer_path.origin = GURL("https://accounts.google.com/a/LoginAuth/sec");
- EXPECT_EQ(PasswordFormManager::RESULT_NO_MATCH,
- secure_manager.DoesManage(form_longer_path, nullptr));
+ EXPECT_TRUE(ArePasswordFormUniqueKeysEqual(saved_match_, updated_form));
+ EXPECT_TRUE(updated_form.preferred);
+ EXPECT_EQ(new_password, updated_form.password_value);
}
-TEST_F(PasswordFormManagerTest, OriginCheck_OnlyOriginsMatch) {
- // Make sure DoesManage() can distinguish when only origins match.
+TEST_F(PasswordFormManagerTest, VotesUploadingOnPasswordUpdate) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordForm same_origin_only(*observed_form());
- same_origin_only.form_data.name = ASCIIToUTF16("other_name");
- same_origin_only.action = GURL("https://somewhere/else");
+ for (auto expected_vote :
+ {autofill::NEW_PASSWORD, autofill::PROBABLY_NEW_PASSWORD,
+ autofill::NOT_NEW_PASSWORD}) {
+ SCOPED_TRACE(testing::Message("expected_vote=") << expected_vote);
+ CreateFormManager(observed_form_only_password_fields_);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- EXPECT_EQ(PasswordFormManager::RESULT_ORIGINS_OR_FRAMES_MATCH,
- form_manager()->DoesManage(same_origin_only, nullptr));
-}
+ FormData submitted_form = observed_form_only_password_fields_;
+ submitted_form.fields[0].value = saved_match_.password_value;
+ auto new_password = saved_match_.password_value + ASCIIToUTF16("1");
+ submitted_form.fields[1].value = new_password;
-TEST_F(PasswordFormManagerTest, FormsMatchIfNamesMatch) {
- PasswordForm other_form(*observed_form());
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("another-field-name");
- other_form.form_data.fields.push_back(field);
- other_form.action = GURL("https://somewhere/else");
- // Names should match, other things may not.
- EXPECT_EQ(PasswordFormManager::RESULT_FORM_NAME_MATCH,
- form_manager()->DoesManage(other_form, nullptr) &
- PasswordFormManager::RESULT_FORM_NAME_MATCH);
-}
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
-TEST_F(PasswordFormManagerTest, FormsMatchIfSignaturesMatch) {
- PasswordForm other_form(*observed_form());
- other_form.action = GURL("https://somewhere/else");
- // Signatures should match, other things may not.
- EXPECT_EQ(PasswordFormManager::RESULT_SIGNATURE_MATCH,
- form_manager()->DoesManage(other_form, nullptr) &
- PasswordFormManager::RESULT_SIGNATURE_MATCH);
-}
+ std::map<base::string16, autofill::ServerFieldType> expected_types;
+ expected_types[ASCIIToUTF16("password")] = autofill::PASSWORD;
+ expected_types[ASCIIToUTF16("password2")] = expected_vote;
+
+ testing::InSequence in_sequence;
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(UploadedAutofillTypesAre(expected_types),
+ false, _, _, true, nullptr));
+ if (expected_vote == autofill::NEW_PASSWORD) {
+ // An unrelated |FIRST_USE| vote.
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(_, _, _, _, _, _));
+ }
-TEST_F(PasswordFormManagerTest, FormWithEmptyActionAndNameMatchesItself) {
- observed_form()->form_data.name.clear();
- observed_form()->action = GURL::EmptyGURL();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
- form_manager.Init(nullptr);
- // Any form should match itself regardless of missing properties. Otherwise,
- // a PasswordFormManager instance is created for the same form multiple times.
- PasswordForm other_form(*observed_form());
- EXPECT_EQ(PasswordFormManager::RESULT_COMPLETE_MATCH,
- form_manager.DoesManage(other_form, nullptr));
+ if (expected_vote == autofill::NEW_PASSWORD)
+ form_manager_->Save();
+ else if (expected_vote == autofill::PROBABLY_NEW_PASSWORD)
+ form_manager_->OnNoInteraction(true /* is_update */);
+ else
+ form_manager_->OnNopeUpdateClicked();
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
+ }
}
-// Test that if multiple credentials with the same username are stored, and the
-// user updates the password, then all of the stored passwords get updated as
-// long as they have the same password value.
-TEST_F(PasswordFormManagerTest, CorrectlyUpdatePasswordsWithSameUsername) {
- PasswordForm first(*saved_match());
- first.action = observed_form()->action;
- first.password_value = ASCIIToUTF16("first");
- first.preferred = true;
-
- // The second credential has the same password value, but it has a different
- // |username_element| to make a different unique key for the database
- // (otherwise the two credentials could not be stored at the same time). The
- // different unique key results in a slightly lower score than for |first|.
- PasswordForm second(first);
- second.username_element.clear();
- second.preferred = false;
-
- // The third credential has a different password value. It also has a
- // different |password_element| to make a different unique key for the
- // database again.
- PasswordForm third(first);
- third.password_element.clear();
- third.password_value = ASCIIToUTF16("second");
- third.preferred = false;
-
- SetNonFederatedAndNotifyFetchCompleted({&first, &second, &third});
-
- // |first| scored slightly higher.
- EXPECT_EQ(ASCIIToUTF16("first"),
- form_manager()->preferred_match()->password_value);
-
- PasswordForm login(*observed_form());
- login.username_value = saved_match()->username_value;
- login.password_value = ASCIIToUTF16("third");
- login.preferred = true;
- form_manager()->ProvisionallySave(login);
-
- EXPECT_FALSE(form_manager()->IsNewLogin());
-
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Update(_, UnorderedElementsAre(&first, &second, &third),
- first.password_value))
- .WillOnce(SaveArg<0>(&saved_result));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
-
- form_manager()->Save();
-
- // What was |first| above should be the main credential updated.
- EXPECT_EQ(ASCIIToUTF16("third"), saved_result.password_value);
- EXPECT_FALSE(saved_result.password_element.empty());
- EXPECT_FALSE(saved_result.username_element.empty());
-}
+TEST_F(PasswordFormManagerTest, UpdateUsernameEmptyStore) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
-TEST_F(PasswordFormManagerTest, UploadFormData_NewPassword) {
- // For newly saved passwords, upload a password vote for autofill::PASSWORD.
- // Don't vote for the username field yet.
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *saved_match(),
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- PasswordForm form_to_save(*saved_match());
- form_to_save.preferred = true;
- form_to_save.username_value = ASCIIToUTF16("username");
- form_to_save.password_value = ASCIIToUTF16("1234");
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- expected_available_field_types.insert(autofill::PASSWORD);
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, expected_available_field_types, _,
- true, nullptr));
- form_manager.ProvisionallySave(form_to_save);
- form_manager.Save();
-}
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
-TEST_F(PasswordFormManagerTest, UploadFormData_NewPassword_Blacklist) {
- // Do not upload a vote if the user is blacklisting the form.
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager blacklist_form_manager(
- password_manager(), client(), client()->driver(), *saved_match(),
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- blacklist_form_manager.Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- expected_available_field_types.insert(autofill::USERNAME);
- expected_available_field_types.insert(autofill::PASSWORD);
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, expected_available_field_types, _, true, _))
- .Times(0);
- blacklist_form_manager.PermanentlyBlacklist();
-}
+ base::string16 new_username =
+ parsed_submitted_form_.username_value + ASCIIToUTF16("1");
+ PasswordForm expected = parsed_submitted_form_;
+ expected.username_value = new_username;
+ expected.username_element.clear();
-TEST_F(PasswordFormManagerTest, UploadPasswordForm) {
- autofill::FormData observed_form_data;
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("Email:");
- field.name = ASCIIToUTF16("observed-username-field");
- field.form_control_type = "text";
- observed_form_data.fields.push_back(field);
+ form_manager_->UpdateUsername(new_username);
- field.label = ASCIIToUTF16("Password:");
- field.name = ASCIIToUTF16("observed-password-field");
- field.form_control_type = "password";
- observed_form_data.fields.push_back(field);
-
- // Form data is different than saved form data, account creation signal should
- // be sent.
- autofill::ServerFieldType field_type = autofill::ACCOUNT_CREATION_PASSWORD;
- AccountCreationUploadTest(observed_form_data, 0,
- PasswordForm::GenerationUploadStatus::kNoSignalSent,
- &field_type);
-
- // Non-zero times used will not upload since we only upload a positive signal
- // at most once.
- AccountCreationUploadTest(observed_form_data, 1,
- PasswordForm::GenerationUploadStatus::kNoSignalSent,
- nullptr);
-
- // Same form data as saved match and POSITIVE_SIGNAL_SENT means there should
- // be a negative autofill ping sent.
- field_type = autofill::NOT_ACCOUNT_CREATION_PASSWORD;
- AccountCreationUploadTest(
- saved_match()->form_data, 2,
- PasswordForm::GenerationUploadStatus::kPositiveSignalSent, &field_type);
-
- // For any other GenerationUploadStatus, no autofill upload should occur
- // if the observed form data matches the saved form data.
- AccountCreationUploadTest(saved_match()->form_data, 3,
- PasswordForm::GenerationUploadStatus::kNoSignalSent,
- nullptr);
- AccountCreationUploadTest(
- saved_match()->form_data, 3,
- PasswordForm::GenerationUploadStatus::kNegativeSignalSent, nullptr);
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_TRUE(form_manager_->IsNewLogin());
}
-TEST_F(PasswordFormManagerTest, CorrectlySavePasswordWithoutUsernameFields) {
- fake_form_fetcher()->NotifyFetchCompleted();
-
- PasswordForm login(*observed_form());
- login.username_element.clear();
- login.password_value = ASCIIToUTF16("password");
- login.preferred = true;
+TEST_F(PasswordFormManagerTest, UpdateUsernameToAnotherFieldValue) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
- form_manager()->ProvisionallySave(login);
+ base::string16 user_chosen_username = ASCIIToUTF16("user_chosen_username");
+ base::string16 automatically_chosen_username =
+ ASCIIToUTF16("automatically_chosen_username");
+ submitted_form_.fields[0].value = user_chosen_username;
+ submitted_form_.fields[1].value = automatically_chosen_username;
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
- EXPECT_TRUE(form_manager()->IsNewLogin());
+ EXPECT_EQ(automatically_chosen_username,
+ form_manager_->GetPendingCredentials().username_value);
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Save(_, _, _))
- .WillOnce(SaveArg<0>(&saved_result));
+ form_manager_->UpdateUsername(user_chosen_username);
- form_manager()->Save();
+ EXPECT_EQ(user_chosen_username,
+ form_manager_->GetPendingCredentials().username_value);
- // Make sure that the password is updated appropriately.
- EXPECT_EQ(ASCIIToUTF16("password"), saved_result.password_value);
+ FieldTypeMap expected_types = {
+ {ASCIIToUTF16("firstname"), autofill::USERNAME},
+ {ASCIIToUTF16("password"), autofill::PASSWORD}};
+ VoteTypeMap expected_vote_types = {
+ {ASCIIToUTF16("firstname"),
+ AutofillUploadContents::Field::USERNAME_EDITED}};
+ EXPECT_CALL(
+ mock_autofill_download_manager_,
+ StartUploadRequest(
+ AllOf(UploadedAutofillTypesAre(expected_types),
+ HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
+ _, Contains(autofill::USERNAME), _, _, nullptr));
+ form_manager_->Save();
}
-TEST_F(PasswordFormManagerTest, DriverDeletedBeforeStoreDone) {
- // Test graceful handling of the following situation:
- // 1. A form appears in a frame, a PFM is created for that form.
- // 2. The PFM asks the store for credentials for this form.
- // 3. The frame (and associated driver) gets deleted.
- // 4. The PFM returns the callback with credentials.
- // This test checks implicitly that after step 4 the PFM does not attempt
- // use-after-free of the deleted driver.
- std::string example_url("http://example.com");
- PasswordForm form;
- form.origin = GURL(example_url);
- form.signon_realm = example_url;
- form.action = GURL(example_url);
- form.username_element = ASCIIToUTF16("u");
- form.password_element = ASCIIToUTF16("p");
- form.submit_element = ASCIIToUTF16("s");
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), form,
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
-
- // Suddenly, the frame and its driver disappear.
- client()->KillDriver();
-
- SetNonFederatedAndNotifyFetchCompleted({&form});
-}
+TEST_F(PasswordFormManagerTest, UpdateUsernameToAlreadyExisting) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-TEST_F(PasswordFormManagerTest, PreferredMatchIsUpToDate) {
- // Check that preferred_match() is always a member of GetBestMatches().
- PasswordForm form = *observed_form();
- form.username_value = ASCIIToUTF16("username");
- form.password_value = ASCIIToUTF16("password1");
- form.preferred = false;
-
- PasswordForm generated_form = form;
- generated_form.type = PasswordForm::Type::kGenerated;
- generated_form.password_value = ASCIIToUTF16("password2");
- generated_form.preferred = true;
-
- SetNonFederatedAndNotifyFetchCompleted({&form, &generated_form});
-
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
- EXPECT_EQ(form_manager()->preferred_match(),
- form_manager()->GetBestMatches().begin()->second);
- // Make sure to access all fields of preferred_match; this way if it was
- // deleted, ASAN might notice it.
- PasswordForm dummy(*form_manager()->preferred_match());
-}
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
-TEST_F(PasswordFormManagerTest, PasswordToSave_NoElements) {
- PasswordForm form;
- EXPECT_TRUE(PasswordFormManager::PasswordToSave(form).first.empty());
-}
+ base::string16 new_username = saved_match_.username_value;
+ base::string16 expected_password = parsed_submitted_form_.password_value;
+ PasswordForm expected = saved_match_;
+ expected.password_value = expected_password;
-TEST_F(PasswordFormManagerTest, PasswordToSave_NoNewElement) {
- PasswordForm form;
- form.password_element = base::ASCIIToUTF16("pwd");
- base::string16 kValue = base::ASCIIToUTF16("val");
- form.password_value = kValue;
- EXPECT_EQ(kValue, PasswordFormManager::PasswordToSave(form).first);
-}
+ form_manager_->UpdateUsername(new_username);
-TEST_F(PasswordFormManagerTest, PasswordToSave_NoOldElement) {
- PasswordForm form;
- form.new_password_element = base::ASCIIToUTF16("new_pwd");
- base::string16 kNewValue = base::ASCIIToUTF16("new_val");
- form.new_password_value = kNewValue;
- EXPECT_EQ(kNewValue, PasswordFormManager::PasswordToSave(form).first);
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_FALSE(form_manager_->IsNewLogin());
+ EXPECT_TRUE(form_manager_->IsPasswordUpdate());
}
-TEST_F(PasswordFormManagerTest, PasswordToSave_BothButNoNewValue) {
- PasswordForm form;
- form.password_element = base::ASCIIToUTF16("pwd");
- form.new_password_element = base::ASCIIToUTF16("new_pwd");
- base::string16 kValue = base::ASCIIToUTF16("val");
- form.password_value = kValue;
- EXPECT_EQ(kValue, PasswordFormManager::PasswordToSave(form).first);
-}
+TEST_F(PasswordFormManagerTest, UpdatePasswordValueEmptyStore) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
-TEST_F(PasswordFormManagerTest, PasswordToSave_NewValue) {
- PasswordForm form;
- form.password_element = base::ASCIIToUTF16("pwd");
- form.new_password_element = base::ASCIIToUTF16("new_pwd");
- form.password_value = base::ASCIIToUTF16("val");
- base::string16 kNewValue = base::ASCIIToUTF16("new_val");
- form.new_password_value = kNewValue;
- EXPECT_EQ(kNewValue, PasswordFormManager::PasswordToSave(form).first);
-}
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
-TEST_F(PasswordFormManagerTest, TestSuggestingPasswordChangeForms) {
- // Suggesting password on the password change form on the previously visited
- // site. Credentials are found in the password store, and are not blacklisted.
- PasswordForm observed_change_password_form = *observed_form();
- observed_change_password_form.new_password_element =
- base::ASCIIToUTF16("new_pwd");
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager manager_creds(
- password_manager(), client(), client()->driver(),
- observed_change_password_form, std::make_unique<MockFormSaver>(),
- &fetcher);
- manager_creds.Init(nullptr);
-
- autofill::PasswordFormFillData fill_data;
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .WillOnce(SaveArg<0>(&fill_data));
-
- PasswordForm result = CreateSavedMatch(false);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {&result});
- EXPECT_EQ(1u, manager_creds.GetBestMatches().size());
- EXPECT_EQ(0u, fill_data.additional_logins.size());
- EXPECT_TRUE(fill_data.wait_for_username);
-}
+ base::string16 new_password =
+ parsed_submitted_form_.password_value + ASCIIToUTF16("1");
+ PasswordForm expected = parsed_submitted_form_;
+ expected.password_value = new_password;
+ expected.password_element.clear();
-TEST_F(PasswordFormManagerTest, TestUpdateMethod) {
- // Add a new password field to the test form. The PasswordFormManager should
- // save the password from this field, instead of the current password field.
- observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("NewPasswd");
- field.name = ASCIIToUTF16("NewPasswd");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {saved_match()});
-
- // User submits current and new credentials to the observed form.
- PasswordForm credentials(*observed_form());
- credentials.username_element.clear();
- credentials.password_value = saved_match()->password_value;
- credentials.new_password_value = ASCIIToUTF16("test2");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager.IsNewLogin());
- EXPECT_FALSE(form_manager.IsPossibleChangePasswordFormWithoutUsername());
-
- // By now, the PasswordFormManager should have promoted the new password value
- // already to be the current password, and should no longer maintain any info
- // about the new password value.
- EXPECT_EQ(credentials.new_password_value,
- form_manager.GetPendingCredentials().password_value);
- EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());
-
- // Trigger saving to exercise some special case handling during updating.
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _))
- .WillOnce(SaveArg<0>(&new_credentials));
-
- form_manager.Update(*saved_match());
-
- // The password is updated.
- EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
- EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
- EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
- EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
-}
+ form_manager_->UpdatePasswordValue(new_password);
-TEST_F(PasswordFormManagerTest, TestUpdateNoUsernameTextfieldPresent) {
- // Add a new password field to the test form and insert a |username_value|
- // unlikely to be a real username. The PasswordFormManager should still save
- // the password from this field, instead of the current password field.
- observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("NewPasswd");
- field.name = ASCIIToUTF16("NewPasswd");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {saved_match()});
-
- // User submits current and new credentials to the observed form.
- PasswordForm credentials(*observed_form());
- // The |username_value| contains a text that's unlikely to be real username.
- credentials.username_value = ASCIIToUTF16("3");
- credentials.password_value = saved_match()->password_value;
- credentials.new_password_value = ASCIIToUTF16("test2");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager.IsNewLogin());
- EXPECT_TRUE(form_manager.IsPossibleChangePasswordFormWithoutUsername());
-
- // By now, the PasswordFormManager should have promoted the new password value
- // already to be the current password, and should no longer maintain any info
- // about the new password value.
- EXPECT_EQ(saved_match()->username_value,
- form_manager.GetPendingCredentials().username_value);
- EXPECT_EQ(credentials.new_password_value,
- form_manager.GetPendingCredentials().password_value);
- EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());
-
- // Trigger saving to exercise some special case handling during updating.
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _))
- .WillOnce(SaveArg<0>(&new_credentials));
-
- form_manager.Update(form_manager.GetPendingCredentials());
-
- // The password should be updated, but the username should not.
- EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
- EXPECT_EQ(credentials.new_password_value, new_credentials.password_value);
- EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
- EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
- EXPECT_TRUE(new_credentials.new_password_value.empty());
- EXPECT_TRUE(new_credentials.new_password_element.empty());
- EXPECT_EQ(saved_match()->submit_element, new_credentials.submit_element);
-}
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_TRUE(form_manager_->IsNewLogin());
-// Test the case when a user changes the username to the value of another field
-// from the form.
-TEST_F(PasswordFormManagerTest, UpdateUsername_ValueOfAnotherField) {
- for (bool captured_username_is_empty : {false, true}) {
- SCOPED_TRACE(testing::Message() << "captured_username_is_empty="
- << captured_username_is_empty);
- PasswordForm observed(*observed_form());
- // Set |FormData| to upload a username vote.
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("full_name");
- field.form_control_type = "text";
- observed.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("correct_username_element");
- field.form_control_type = "text";
- observed.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("Passwd");
- field.form_control_type = "password";
- observed.form_data.fields.push_back(field);
-
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), observed,
- std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
- form_manager.Init(nullptr);
- fake_form_fetcher()->NotifyFetchCompleted();
-
- // User enters credential in the form.
- PasswordForm credential(observed);
- credential.username_value = captured_username_is_empty
- ? base::string16()
- : ASCIIToUTF16("typed_username");
- credential.password_value = ASCIIToUTF16("password");
- credential.all_possible_usernames.push_back(
- ValueElementPair(ASCIIToUTF16("edited_username"),
- ASCIIToUTF16("correct_username_element")));
- form_manager.ProvisionallySave(credential);
-
- // User edits username in a prompt.
- form_manager.UpdateUsername(ASCIIToUTF16("edited_username"));
- EXPECT_EQ(form_manager.GetPendingCredentials().username_value,
- ASCIIToUTF16("edited_username"));
- EXPECT_EQ(form_manager.GetPendingCredentials().username_element,
- ASCIIToUTF16("correct_username_element"));
- EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
- ASCIIToUTF16("password"));
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- // User clicks save, the edited username is saved.
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(&form_manager),
- Save(_, IsEmpty(), base::string16()))
- .WillOnce(SaveArg<0>(&saved_result));
- // Expect a username edited vote.
- FieldTypeMap expected_types;
- expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
- expected_types[ASCIIToUTF16("correct_username_element")] =
- autofill::USERNAME;
- expected_types[ASCIIToUTF16("Passwd")] = autofill::PASSWORD;
- VoteTypeMap expected_vote_types = {
- {ASCIIToUTF16("correct_username_element"),
- autofill::AutofillUploadContents::Field::USERNAME_EDITED}};
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(observed),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
- _, Contains(autofill::USERNAME), _, _, nullptr));
- form_manager.Save();
-
- // Check what is saved.
- EXPECT_EQ(ASCIIToUTF16("edited_username"), saved_result.username_value);
- EXPECT_EQ(ASCIIToUTF16("correct_username_element"),
- saved_result.username_element);
- EXPECT_EQ(ASCIIToUTF16("password"), saved_result.password_value);
- if (captured_username_is_empty) {
- EXPECT_TRUE(saved_result.all_possible_usernames.empty());
- } else {
- EXPECT_THAT(
- saved_result.all_possible_usernames,
- ElementsAre(ValueElementPair(ASCIIToUTF16("typed_username"),
- observed_form()->username_element)));
- }
- }
+ // TODO(https://crbug.com/928690): implement not sending incorrect votes and
+ // check that StartUploadRequest is not called.
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(_, _, _, _, _, _))
+ .Times(1);
+ form_manager_->Save();
}
-// Test the case when a user updates the username to an already existing one.
-TEST_F(PasswordFormManagerTest, UpdateUsername_ValueSavedInStore) {
- for (bool captured_username_is_empty : {false, true}) {
- SCOPED_TRACE(testing::Message() << "captured_username_is_empty="
- << captured_username_is_empty);
- // We have an already existing credential.
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User enters credential in the form.
- PasswordForm credential(*observed_form());
- credential.username_value = captured_username_is_empty
- ? base::string16()
- : ASCIIToUTF16("different_username");
- credential.password_value = ASCIIToUTF16("different_pass");
- credential.preferred = true;
- form_manager()->ProvisionallySave(credential);
-
- // User edits username in a prompt to one already existing.
- form_manager()->UpdateUsername(saved_match()->username_value);
-
- // The username in credentials is expected to be updated.
- EXPECT_EQ(saved_match()->username_value,
- form_manager()->GetPendingCredentials().username_value);
- EXPECT_EQ(saved_match()->username_element,
- form_manager()->GetPendingCredentials().username_element);
- EXPECT_EQ(ASCIIToUTF16("different_pass"),
- form_manager()->GetPendingCredentials().password_value);
- EXPECT_FALSE(form_manager()->IsNewLogin());
-
- // Create the expected credential to be saved.
- PasswordForm expected_pending(credential);
- expected_pending.origin = saved_match()->origin;
- expected_pending.form_data = saved_match()->form_data;
- expected_pending.times_used = 1;
- expected_pending.username_value = saved_match()->username_value;
-
- // User clicks save, edited username is saved, password updated.
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Update(expected_pending, ElementsAre(Pointee(*saved_match())),
- saved_match()->password_value));
- // Expect a username reusing vote.
- FieldTypeMap expected_types;
- expected_types[ASCIIToUTF16("full_name")] = autofill::UNKNOWN_TYPE;
- expected_types[expected_pending.username_element] = autofill::USERNAME;
- expected_types[expected_pending.password_element] =
- autofill::ACCOUNT_CREATION_PASSWORD;
- VoteTypeMap expected_vote_types = {
- {expected_pending.username_element,
- autofill::AutofillUploadContents::Field::CREDENTIALS_REUSED}};
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(expected_pending),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
- _, Contains(autofill::USERNAME), _, _, nullptr));
- form_manager()->Save();
- }
-}
+TEST_F(PasswordFormManagerTest, UpdatePasswordValueToAlreadyExisting) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-// Tests the case when the username value edited in prompt doesn't coincides
-// neither with other values on the form nor with saved usernames.
-TEST_F(PasswordFormManagerTest, UpdateUsername_NoMatchNeitherOnFormNorInStore) {
- for (bool captured_username_is_empty : {false, true}) {
- SCOPED_TRACE(testing::Message() << "captured_username_is_empty="
- << captured_username_is_empty);
- PasswordForm observed(*observed_form());
- // Assign any |FormData| to allow crowdsourcing of this form.
- observed.form_data = saved_match()->form_data;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), observed,
- std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
- form_manager.Init(nullptr);
- // We have an already existing credential.
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // A user enters a credential in the form.
- PasswordForm credential(observed);
- credential.username_value = captured_username_is_empty
- ? base::string16()
- : ASCIIToUTF16("captured_username");
- credential.password_value = ASCIIToUTF16("different_pass");
- credential.preferred = true;
- form_manager.ProvisionallySave(credential);
-
- // User edits username. The username doesn't exist neither in the store nor
- // on the form.
- form_manager.UpdateUsername(ASCIIToUTF16("new_username"));
-
- // As there is no match on the form, |username_element| is empty.
- EXPECT_TRUE(form_manager.GetPendingCredentials().username_element.empty());
- EXPECT_EQ(ASCIIToUTF16("new_username"),
- form_manager.GetPendingCredentials().username_value);
- EXPECT_EQ(ASCIIToUTF16("different_pass"),
- form_manager.GetPendingCredentials().password_value);
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- PasswordForm expected_pending(credential);
- expected_pending.username_value = ASCIIToUTF16("new_username");
- expected_pending.username_element = base::string16();
- if (!captured_username_is_empty) {
- // A non-empty captured username value should be saved to recover later if
- // a user makes a mistake in username editing.
- expected_pending.all_possible_usernames.push_back(ValueElementPair(
- ASCIIToUTF16("captured_username"), ASCIIToUTF16("Email")));
- }
+ // Emulate submitting form with known username and different password.
+ submitted_form_.fields[kUsernameFieldIndex].value =
+ saved_match_.username_value;
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
- // User clicks save, the edited username is saved, the password is updated,
- // no username vote is uploaded.
- PasswordForm actual_saved_form;
- EXPECT_CALL(MockFormSaver::Get(&form_manager),
- Save(_, ElementsAre(Pointee(*saved_match())), _))
- .WillOnce(SaveArg<0>(&actual_saved_form));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _,
- _, nullptr));
- form_manager.Save();
-
- // Can't verify |date_created |, so ignore it in form comparison.
- actual_saved_form.date_created = expected_pending.date_created;
- EXPECT_EQ(expected_pending, actual_saved_form);
- }
-}
+ // The user changes password to already saved one.
+ base::string16 password = saved_match_.password_value;
+ form_manager_->UpdatePasswordValue(password);
-// Tests the case when a user clears the username value in a prompt.
-TEST_F(PasswordFormManagerTest, UpdateUsername_UserRemovedUsername) {
- PasswordForm observed(*observed_form());
- // Assign any |FormData| to allow crowdsourcing of this form.
- observed.form_data = saved_match()->form_data;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), observed,
- std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
- form_manager.Init(nullptr);
- fake_form_fetcher()->NotifyFetchCompleted();
-
- // The user enters credential in the form.
- PasswordForm credential(observed);
- credential.username_value = ASCIIToUTF16("pin_code");
- credential.password_value = ASCIIToUTF16("password");
- credential.all_possible_usernames.push_back(
- ValueElementPair(base::string16(), ASCIIToUTF16("empty_field")));
- form_manager.ProvisionallySave(credential);
-
- // The user clears the username value in the prompt.
- form_manager.UpdateUsername(base::string16());
- EXPECT_TRUE(form_manager.GetPendingCredentials().username_value.empty());
- EXPECT_TRUE(form_manager.GetPendingCredentials().username_element.empty());
- EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
- ASCIIToUTF16("password"));
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- // The user clicks save, empty username is saved.
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, IsEmpty(), _))
- .WillOnce(SaveArg<0>(&saved_result));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _, _,
- nullptr));
- form_manager.Save();
-
- EXPECT_TRUE(saved_result.username_value.empty());
- EXPECT_TRUE(saved_result.username_element.empty());
- EXPECT_EQ(ASCIIToUTF16("password"), saved_result.password_value);
- EXPECT_THAT(saved_result.all_possible_usernames,
- ElementsAre(ValueElementPair(ASCIIToUTF16("pin_code"),
- observed_form()->username_element)));
+ CheckPendingCredentials(saved_match_, form_manager_->GetPendingCredentials());
+ EXPECT_FALSE(form_manager_->IsNewLogin());
+ EXPECT_FALSE(form_manager_->IsPasswordUpdate());
}
-// Test that when user updates username to a PSL matching credential, we should
-// handle it as a new login.
-TEST_F(PasswordFormManagerTest, UpdateUsername_PslMatch) {
- SetNonFederatedAndNotifyFetchCompleted({psl_saved_match()});
- // The user submits a credential of the observed form.
- PasswordForm credential(*observed_form());
- credential.username_value = ASCIIToUTF16("some_username");
- credential.password_value = ASCIIToUTF16("some_pass");
- form_manager()->ProvisionallySave(credential);
-
- // The user edits the username to match the PSL entry.
- form_manager()->UpdateUsername(psl_saved_match()->username_value);
- EXPECT_EQ(psl_saved_match()->username_value,
- form_manager()->GetPendingCredentials().username_value);
- EXPECT_TRUE(form_manager()->IsNewLogin());
- EXPECT_EQ(ASCIIToUTF16("some_pass"),
- form_manager()->GetPendingCredentials().password_value);
-
- // The user clicks save, the edited username is saved.
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Save(_, ElementsAre(Pointee(*psl_saved_match())), _))
- .WillOnce(SaveArg<0>(&saved_result));
- // As the credential is re-used successfully, expect a username vote.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _, nullptr));
- form_manager()->Save();
+TEST_F(PasswordFormManagerTest, UpdatePasswordValueMultiplePasswordFields) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ FormData form = observed_form_only_password_fields_;
- // Check what is saved.
- EXPECT_EQ(psl_saved_match()->username_value, saved_result.username_value);
- EXPECT_EQ(ASCIIToUTF16("some_pass"), saved_result.password_value);
-}
+ CreateFormManager(form);
+ fetcher_->NotifyFetchCompleted();
+ base::string16 password = ASCIIToUTF16("password1");
+ base::string16 pin = ASCIIToUTF16("pin");
+ form.fields[0].value = password;
+ form.fields[1].value = pin;
+ form_manager_->ProvisionallySave(form, &driver_);
-// Test that when user selects a password in the bubble, the pending credentials
-// are updated accordingly.
-TEST_F(PasswordFormManagerTest, TestSelectPasswordMethod) {
- for (bool has_password : {true, false}) {
- for (bool has_new_password : {true, false}) {
- for (bool has_passwords_revealed : {true, false}) {
- if (!has_password && !has_new_password)
- continue;
- SCOPED_TRACE(testing::Message() << "has_password=" << has_password);
- SCOPED_TRACE(testing::Message()
- << "has_new_password=" << has_new_password);
- SCOPED_TRACE(testing::Message()
- << "has_passwords_revealed=" << has_passwords_revealed);
-
- PasswordForm observed(*observed_form());
- // Observe two password fields, between which we must select.
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("correct_password_element");
- field.form_control_type = "password";
- observed.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("other_password_element");
- field.form_control_type = "password";
- observed.form_data.fields.push_back(field);
-
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), observed,
- std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
- form_manager.Init(nullptr);
- fake_form_fetcher()->NotifyFetchCompleted();
-
- // User enters credential in the form. We autodetect the wrong password
- // field.
- PasswordForm credential(observed);
- if (has_password) {
- credential.password_value = ASCIIToUTF16("not-a-password");
- credential.password_element = ASCIIToUTF16("other_password_element");
- }
- if (has_new_password) {
- credential.new_password_value = ASCIIToUTF16("not-a-password");
- credential.new_password_element =
- ASCIIToUTF16("other_password_element");
- }
- credential.all_possible_passwords = {
- {ASCIIToUTF16("p4ssword"),
- ASCIIToUTF16("correct_password_element")},
- {ASCIIToUTF16("not-a-password"),
- ASCIIToUTF16("other_password_element")}};
- form_manager.ProvisionallySave(credential);
-
- // Pending credentials have the wrong values.
- EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
- ASCIIToUTF16("not-a-password"));
- EXPECT_EQ(form_manager.GetPendingCredentials().password_element,
- ASCIIToUTF16("other_password_element"));
- // User selects another password in a prompt.
- if (has_passwords_revealed)
- form_manager.OnPasswordsRevealed();
- form_manager.UpdatePasswordValue(ASCIIToUTF16("p4ssword"));
- // Pending credentials are also corrected.
- EXPECT_EQ(form_manager.GetPendingCredentials().password_value,
- ASCIIToUTF16("p4ssword"));
- EXPECT_EQ(form_manager.GetPendingCredentials().password_element,
- ASCIIToUTF16("correct_password_element"));
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- // User clicks save, selected password is saved.
- PasswordForm saved_result;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, IsEmpty(), _))
- .WillOnce(SaveArg<0>(&saved_result));
- // Expect a password edited vote.
- FieldTypeMap expected_types;
- expected_types[ASCIIToUTF16("correct_password_element")] =
- autofill::PASSWORD;
- expected_types[ASCIIToUTF16("other_password_element")] =
- autofill::UNKNOWN_TYPE;
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(observed),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false),
- PasswordsWereRevealed(has_passwords_revealed)),
- _, Contains(autofill::PASSWORD), _, _, nullptr));
- form_manager.Save();
-
- EXPECT_EQ(ASCIIToUTF16("p4ssword"), saved_result.password_value);
- EXPECT_EQ(ASCIIToUTF16("correct_password_element"),
- saved_result.password_element);
- EXPECT_EQ(base::string16(), saved_result.new_password_value);
- EXPECT_EQ(base::string16(), saved_result.new_password_element);
- }
- }
- }
-}
+ // Check that a second password field is chosen for saving.
+ EXPECT_EQ(pin, form_manager_->GetPendingCredentials().password_value);
+
+ PasswordForm expected = form_manager_->GetPendingCredentials();
+ expected.password_value = password;
+ expected.password_element = form.fields[0].name;
-TEST_F(PasswordFormManagerTest, GenerationStatusChangedWithPassword) {
- PasswordForm generated_form = *observed_form();
- generated_form.type = PasswordForm::Type::kGenerated;
- generated_form.username_value = ASCIIToUTF16("username");
- generated_form.password_value = ASCIIToUTF16("password2");
- generated_form.preferred = true;
+ // Simulate that the user updates value to save for the first password field.
+ form_manager_->UpdatePasswordValue(password);
- PasswordForm submitted_form(generated_form);
- submitted_form.password_value = ASCIIToUTF16("password3");
+ // Check that newly created pending credentials are correct.
+ CheckPendingCredentials(expected, form_manager_->GetPendingCredentials());
+ EXPECT_TRUE(form_manager_->IsNewLogin());
- SetNonFederatedAndNotifyFetchCompleted({&generated_form});
+ // Check that a vote is sent for the field with the value which is chosen by
+ // the user.
+ std::map<base::string16, ServerFieldType> expected_types;
+ expected_types[expected.password_element] = autofill::PASSWORD;
- form_manager()->ProvisionallySave(submitted_form);
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(UploadedAutofillTypesAre(expected_types),
+ false, _, _, true, nullptr));
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
- form_manager()->Save();
+ // Check that the password which was chosen by the user is saved.
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
- EXPECT_EQ(PasswordForm::Type::kManual, new_credentials.type);
+ form_manager_->Save();
+ CheckPendingCredentials(expected, saved_form);
}
-TEST_F(PasswordFormManagerTest, GenerationStatusNotUpdatedIfPasswordUnchanged) {
- base::HistogramTester histogram_tester;
+TEST_F(PasswordFormManagerTest, PermanentlyBlacklist) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
- PasswordForm generated_form = *observed_form();
- generated_form.type = PasswordForm::Type::kGenerated;
- generated_form.username_value = ASCIIToUTF16("username");
- generated_form.password_value = ASCIIToUTF16("password2");
- generated_form.preferred = true;
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm submitted_form(generated_form);
+ PasswordForm actual_blacklisted_form =
+ password_manager_util::MakeNormalizedBlacklistedForm(
+ PasswordStore::FormDigest(observed_form_));
+ EXPECT_CALL(form_saver,
+ PermanentlyBlacklist(PasswordStore::FormDigest(observed_form_)))
+ .WillOnce(Return(actual_blacklisted_form));
- SetNonFederatedAndNotifyFetchCompleted({&generated_form});
+ form_manager_->PermanentlyBlacklist();
+ EXPECT_THAT(form_manager_->GetBlacklistedMatches(),
+ ElementsAre(Pointee(actual_blacklisted_form)));
+}
- form_manager()->ProvisionallySave(submitted_form);
+TEST_F(PasswordFormManagerTest, Clone) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
- form_manager()->Save();
+ // Provisionally save in order to create pending credentials.
+ ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
- EXPECT_EQ(PasswordForm::Type::kGenerated, new_credentials.type);
- histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
- metrics_util::PASSWORD_USED, 1);
+ std::unique_ptr<PasswordFormManager> cloned_manager = form_manager_->Clone();
- // On the second reuse, the metric is not reported.
- generated_form.times_used = 1;
- SetNonFederatedAndNotifyFetchCompleted({&generated_form});
- form_manager()->ProvisionallySave(submitted_form);
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _));
- form_manager()->Save();
- histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
- metrics_util::PASSWORD_USED, 1);
-}
+ EXPECT_TRUE(cloned_manager->DoesManage(observed_form_, nullptr));
+ EXPECT_TRUE(cloned_manager->GetFormFetcher());
+ // Check that |form_fetcher| was cloned.
+ EXPECT_NE(form_manager_->GetFormFetcher(), cloned_manager->GetFormFetcher());
-TEST_F(PasswordFormManagerTest, GeneratedPasswordIsOverridden) {
- base::HistogramTester histogram_tester;
+ EXPECT_EQ(form_manager_->metrics_recorder(),
+ cloned_manager->metrics_recorder());
- PasswordForm generated_form = *observed_form();
- generated_form.type = PasswordForm::Type::kGenerated;
- generated_form.username_value = ASCIIToUTF16("username");
- generated_form.password_value = ASCIIToUTF16("password2");
- generated_form.preferred = true;
-
- PasswordForm submitted_form(generated_form);
- submitted_form.password_value = ASCIIToUTF16("another_password");
-
- SetNonFederatedAndNotifyFetchCompleted({&generated_form});
-
- form_manager()->ProvisionallySave(submitted_form);
-
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
- form_manager()->Save();
-
- EXPECT_EQ(PasswordForm::Type::kManual, new_credentials.type);
- EXPECT_EQ(ASCIIToUTF16("another_password"), new_credentials.password_value);
- histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
- metrics_util::PASSWORD_OVERRIDDEN, 1);
-
- // On the reuse of the overriden password, the metric is not reported.
- SetNonFederatedAndNotifyFetchCompleted({&new_credentials});
- form_manager()->ProvisionallySave(new_credentials);
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _));
- form_manager()->Save();
- histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
- metrics_util::PASSWORD_OVERRIDDEN, 1);
- histogram_tester.ExpectBucketCount("PasswordGeneration.SubmissionEvent",
- metrics_util::PASSWORD_USED, 0);
+ EXPECT_EQ(form_manager_->GetPendingCredentials(),
+ cloned_manager->GetPendingCredentials());
+ ASSERT_TRUE(cloned_manager->GetSubmittedForm());
+ EXPECT_EQ(*form_manager_->GetSubmittedForm(),
+ *cloned_manager->GetSubmittedForm());
+ EXPECT_TRUE(cloned_manager->is_submitted());
}
-// Test that ProcessFrame is called on receiving matches from the fetcher,
-// resulting in a FillPasswordForm call.
-TEST_F(PasswordFormManagerTest, ProcessFrame) {
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
+// Extracts the information whether parsing was successful from a metric
+// specified by |metric_name| stored in |entry|. The metric name should be one
+// of ukm::builders::PasswordForm::kReadonlyWhenSavingName and
+// ukm::builders::PasswordForm::kReadonlyWhenFillingName.
+bool ParsingSuccessReported(const ukm::mojom::UkmEntry* entry,
+ base::StringPiece metric_name) {
+ const int64_t* value =
+ ukm::TestUkmRecorder::GetEntryMetric(entry, metric_name);
+ EXPECT_TRUE(value);
+ // Ideally, an ASSERT_TRUE above would prevent the test suite from crashing on
+ // dereferencing |value| below. But ASSERT_* is not available in non-void
+ // returning functions, so the null value is handled explicitly.
+ if (!value)
+ return false; // Value does not matter, the test already failed.
+ return 1 == (1 & *value);
}
-// Test that driver is informed when there are not saved credentials.
-TEST_F(PasswordFormManagerTest, InformNoSavedCredentials) {
- EXPECT_CALL(*client()->mock_driver(), InformNoSavedCredentials());
- SetNonFederatedAndNotifyFetchCompleted({});
-}
+// Test that an attempt to log to ReadonlyWhenFilling UKM is made when filling.
+TEST_F(PasswordFormManagerTest, RecordReadonlyWhenFilling) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ EXPECT_CALL(driver_, FillPasswordForm(_));
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-// Test that ProcessFrame can also be called directly, resulting in an
-// additional FillPasswordForm call.
-TEST_F(PasswordFormManagerTest, ProcessFrame_MoreProcessFrameMoreFill) {
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)).Times(2);
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
- form_manager()->ProcessFrame(client()->mock_driver()->AsWeakPtr());
-}
+ task_runner_->FastForwardUntilNoTasksRemain();
-// Test that Chrome stops autofilling if triggered too many times.
-TEST_F(PasswordFormManagerTest, ProcessFrame_MaxTimes) {
- constexpr int kMaxAutofills = PasswordFormManager::kMaxTimesAutofill;
- constexpr int kExtraProcessRequests = 3;
- // Expect one call for each ProcessFrame() and one for SetNonFederated().
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_))
- .Times(kMaxAutofills + 1);
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
- // Process more times to exceed the limit.
- for (int i = 0; i < kMaxAutofills + kExtraProcessRequests; i++) {
- form_manager()->ProcessFrame(client()->mock_driver()->AsWeakPtr());
- }
-}
+ // Destroy the form manager to destroy the UKM recorder it owns. The recorder
+ // only records metrics in its destructor.
+ form_manager_.reset();
-// Test that when ProcessFrame is called on a driver added after receiving
-// matches, such driver is still told to call FillPasswordForm.
-TEST_F(PasswordFormManagerTest, ProcessFrame_TwoDrivers) {
- NiceMock<MockPasswordManagerDriver> second_driver;
+ auto entries = test_ukm_recorder.GetEntriesByName(
+ ukm::builders::PasswordForm::kEntryName);
+ ASSERT_EQ(1u, entries.size());
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
- EXPECT_CALL(second_driver, FillPasswordForm(_));
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
- form_manager()->ProcessFrame(second_driver.AsWeakPtr());
+ EXPECT_TRUE(ParsingSuccessReported(
+ entries[0], ukm::builders::PasswordForm::kReadonlyWhenFillingName));
}
-// Test that a second driver is added before receiving matches, such driver is
-// also told to call FillPasswordForm once the matches arrive.
-TEST_F(PasswordFormManagerTest, ProcessFrame_DriverBeforeMatching) {
- NiceMock<MockPasswordManagerDriver> second_driver;
- form_manager()->ProcessFrame(second_driver.AsWeakPtr());
+// Test that an attempt to log to ReadonlyWhenFilling UKM is made when filling,
+// even when the parsing itself is unsuccessful.
+TEST_F(PasswordFormManagerTest, RecordReadonlyWhenFilling_ParsingFailed) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_));
- EXPECT_CALL(second_driver, FillPasswordForm(_));
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-}
+ FormData malformed_form = observed_form_;
+ malformed_form.fields.clear();
+ CreateFormManager(malformed_form);
+ // Only create the recorder after the current form manager is created,
+ // otherwise the destruction of the previous one will add unwanted UKM entries
+ // in it.
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-// Test that if the fetcher updates the information about stored matches,
-// autofill is re-triggered.
-TEST_F(PasswordFormManagerTest, ProcessFrame_StoreUpdatesCausesAutofill) {
- EXPECT_CALL(*client()->mock_driver(), FillPasswordForm(_)).Times(2);
- std::vector<const PasswordForm*> matches = {saved_match()};
- SetNonFederatedAndNotifyFetchCompleted(matches);
- fake_form_fetcher()->Fetch();
- SetNonFederatedAndNotifyFetchCompleted(matches);
-}
+ task_runner_->FastForwardUntilNoTasksRemain();
-// TODO(crbug.com/639786): Restore the following test:
-// when PasswordFormManager::Save or PasswordFormManager::Update is called, then
-// PasswordFormManager also calls PasswordManager::UpdateFormManagers.
-
-TEST_F(PasswordFormManagerTest, UploadChangePasswordForm) {
- autofill::ServerFieldType kChangePasswordVotes[] = {
- autofill::NEW_PASSWORD, autofill::PROBABLY_NEW_PASSWORD,
- autofill::NOT_NEW_PASSWORD};
- bool kFalseTrue[] = {false, true};
- for (autofill::ServerFieldType vote : kChangePasswordVotes) {
- for (bool has_confirmation_field : kFalseTrue)
- ChangePasswordUploadTest(vote, has_confirmation_field);
- }
-}
+ // Destroy the form manager to destroy the UKM recorder it owns. The recorder
+ // only records metrics in its destructor.
+ form_manager_.reset();
-TEST_F(PasswordFormManagerTest, TestUpdatePSLMatchedCredentials) {
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher,
- {saved_match(), psl_saved_match()});
-
- // User submits a credentials with an old username and a new password.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager.IsNewLogin());
-
- // Trigger saving to exercise some special case handling during updating.
- PasswordForm new_credentials;
- std::vector<const autofill::PasswordForm*> matches;
- EXPECT_CALL(MockFormSaver::Get(&form_manager),
- Update(_, _, saved_match()->password_value))
- .WillOnce(
- testing::DoAll(SaveArg<0>(&new_credentials), SaveArg<1>(&matches)));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
-
- form_manager.Save();
-
- // No meta-information should be updated, only the password.
- EXPECT_EQ(credentials.password_value, new_credentials.password_value);
- EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
- EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
- EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
- EXPECT_EQ(saved_match()->origin, new_credentials.origin);
-
- EXPECT_THAT(matches, UnorderedElementsAre(Pointee(*saved_match()),
- Pointee(*psl_saved_match())));
-}
+ auto entries = test_ukm_recorder.GetEntriesByName(
+ ukm::builders::PasswordForm::kEntryName);
+ ASSERT_EQ(1u, entries.size());
-TEST_F(PasswordFormManagerTest,
- TestNotUpdatePSLMatchedCredentialsWithAnotherUsername) {
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- psl_saved_match()->username_value += ASCIIToUTF16("1");
- SetNonFederatedAndNotifyFetchCompleted(&fetcher,
- {saved_match(), psl_saved_match()});
-
- // User submits a credentials with an old username and a new password.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager.IsNewLogin());
-
- // Trigger saving to exercise some special case handling during updating.
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager),
- Update(_,
- UnorderedElementsAre(Pointee(*saved_match()),
- Pointee(*psl_saved_match())),
- saved_match()->password_value))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
-
- form_manager.Save();
-
- // No meta-information should be updated, only the password.
- EXPECT_EQ(credentials.password_value, new_credentials.password_value);
- EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
- EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
- EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
- EXPECT_EQ(saved_match()->origin, new_credentials.origin);
+ EXPECT_FALSE(ParsingSuccessReported(
+ entries[0], ukm::builders::PasswordForm::kReadonlyWhenFillingName));
}
-TEST_F(PasswordFormManagerTest,
- TestNotUpdatePSLMatchedCredentialsWithAnotherPassword) {
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- psl_saved_match()->password_value += ASCIIToUTF16("1");
- SetNonFederatedAndNotifyFetchCompleted(&fetcher,
- {saved_match(), psl_saved_match()});
-
- // User submits a credentials with an old username and a new password.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, and since this is an update, it should know not to save as a new
- // login.
- EXPECT_FALSE(form_manager.IsNewLogin());
-
- // Trigger saving to exercise some special case handling during updating.
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager),
- Update(_,
- UnorderedElementsAre(Pointee(*saved_match()),
- Pointee(*psl_saved_match())),
- saved_match()->password_value))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
-
- form_manager.Save();
-
- // No meta-information should be updated, only the password.
- EXPECT_EQ(credentials.password_value, new_credentials.password_value);
- EXPECT_EQ(saved_match()->username_value, new_credentials.username_value);
- EXPECT_EQ(saved_match()->password_element, new_credentials.password_element);
- EXPECT_EQ(saved_match()->username_element, new_credentials.username_element);
- EXPECT_EQ(saved_match()->origin, new_credentials.origin);
-}
+// Test that an attempt to log to ReadonlyWhenSaving UKM is made when creating
+// pending credentials.
+TEST_F(PasswordFormManagerTest, RecordReadonlyWhenSaving) {
+ // The scoped context is needed for the UKM recorder.
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-TEST_F(PasswordFormManagerTest, TestNotUpdateWhenOnlyPslMatched) {
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {psl_saved_match()});
-
- // User submits a credentials with an old username and a new password.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager.ProvisionallySave(credentials);
-
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- // PSL matched credential should not be updated, since we are not sure that
- // this is the same credential as submitted one.
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, _, _))
- .WillOnce(testing::SaveArg<0>(&new_credentials));
- // As the username is re-used, expect a username vote.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, Contains(autofill::USERNAME), _, _, nullptr));
- form_manager.Save();
-
- EXPECT_EQ(credentials.password_value, new_credentials.password_value);
- EXPECT_EQ(credentials.username_value, new_credentials.username_value);
- EXPECT_EQ(credentials.password_element, new_credentials.password_element);
- EXPECT_EQ(credentials.username_element, new_credentials.username_element);
- EXPECT_EQ(credentials.origin, new_credentials.origin);
-}
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
-TEST_F(PasswordFormManagerTest,
- TestSavingOnChangePasswordFormGenerationNoStoredForms) {
- fake_form_fetcher()->NotifyFetchCompleted();
-
- // User submits change password form and there is no stored credentials.
- PasswordForm credentials = *observed_form();
- credentials.username_element.clear();
- credentials.password_value = saved_match()->password_value;
- credentials.new_password_element = ASCIIToUTF16("NewPasswd");
- credentials.new_password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager()->PresaveGeneratedPassword(credentials);
- form_manager()->ProvisionallySave(credentials);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to save, which should know this is a new login.
- EXPECT_TRUE(form_manager()->IsNewLogin());
- // Make sure the credentials that would be submitted on successful login
- // are going to match submitted form.
- EXPECT_EQ(observed_form()->origin.spec(),
- form_manager()->GetPendingCredentials().origin.spec());
- EXPECT_EQ(observed_form()->signon_realm,
- form_manager()->GetPendingCredentials().signon_realm);
- EXPECT_EQ(observed_form()->action,
- form_manager()->GetPendingCredentials().action);
- EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
- EXPECT_EQ(ASCIIToUTF16("new_password"),
- form_manager()->GetPendingCredentials().password_value);
- EXPECT_EQ(base::string16(),
- form_manager()->GetPendingCredentials().username_value);
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_element.empty());
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_value.empty());
-}
+ // Destroy the form manager to destroy the UKM recorder it owns. The recorder
+ // only records metrics in its destructor.
+ form_manager_.reset();
-TEST_F(PasswordFormManagerTest, TestUpdatingOnChangePasswordFormGeneration) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User submits credentials for the change password form, and old password is
- // coincide with password from an existing credentials, so stored credentials
- // should be updated.
- PasswordForm credentials = *observed_form();
- credentials.username_element.clear();
- credentials.password_value = saved_match()->password_value;
- credentials.new_password_element = ASCIIToUTF16("NewPasswd");
- credentials.new_password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager()->PresaveGeneratedPassword(credentials);
- form_manager()->ProvisionallySave(credentials);
-
- EXPECT_FALSE(form_manager()->IsNewLogin());
- // Make sure the credentials that would be submitted on successful login
- // are going to match the stored entry in the db.
- EXPECT_EQ(saved_match()->origin.spec(),
- form_manager()->GetPendingCredentials().origin.spec());
- EXPECT_EQ(saved_match()->signon_realm,
- form_manager()->GetPendingCredentials().signon_realm);
- EXPECT_EQ(observed_form()->action,
- form_manager()->GetPendingCredentials().action);
- EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
- EXPECT_EQ(ASCIIToUTF16("new_password"),
- form_manager()->GetPendingCredentials().password_value);
- EXPECT_EQ(saved_match()->username_value,
- form_manager()->GetPendingCredentials().username_value);
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_element.empty());
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_value.empty());
-}
+ auto entries = test_ukm_recorder.GetEntriesByName(
+ ukm::builders::PasswordForm::kEntryName);
+ ASSERT_EQ(1u, entries.size());
-TEST_F(PasswordFormManagerTest,
- TestSavingOnChangePasswordFormGenerationNoMatchedForms) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User submits credentials for the change password form, and old password is
- // not coincide with password from existing credentials, so new credentials
- // should be saved.
- PasswordForm credentials = *observed_form();
- credentials.username_element.clear();
- credentials.password_value =
- saved_match()->password_value + ASCIIToUTF16("1");
- credentials.new_password_element = ASCIIToUTF16("NewPasswd");
- credentials.new_password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager()->PresaveGeneratedPassword(credentials);
- form_manager()->ProvisionallySave(credentials);
-
- EXPECT_TRUE(form_manager()->IsNewLogin());
- // Make sure the credentials that would be submitted on successful login
- // are going to match submitted form.
- EXPECT_EQ(observed_form()->origin.spec(),
- form_manager()->GetPendingCredentials().origin.spec());
- EXPECT_EQ(observed_form()->signon_realm,
- form_manager()->GetPendingCredentials().signon_realm);
- EXPECT_EQ(observed_form()->action,
- form_manager()->GetPendingCredentials().action);
- EXPECT_TRUE(form_manager()->GetPendingCredentials().preferred);
- EXPECT_EQ(ASCIIToUTF16("new_password"),
- form_manager()->GetPendingCredentials().password_value);
- EXPECT_EQ(base::string16(),
- form_manager()->GetPendingCredentials().username_value);
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_element.empty());
- EXPECT_TRUE(
- form_manager()->GetPendingCredentials().new_password_value.empty());
+ EXPECT_TRUE(ParsingSuccessReported(
+ entries[0], ukm::builders::PasswordForm::kReadonlyWhenSavingName));
}
-TEST_F(PasswordFormManagerTest,
- TestUploadVotesForPasswordChangeFormsWithTwoFields) {
- // Turn |observed_form_| into change password form with only 2 fields: an old
- // password and a new password.
- observed_form()->username_element.clear();
- observed_form()->new_password_element = ASCIIToUTF16("NewPasswd");
- autofill::FormFieldData field;
- field.label = ASCIIToUTF16("password");
- field.name = ASCIIToUTF16("Passwd");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
-
- field.label = ASCIIToUTF16("new password");
- field.name = ASCIIToUTF16("NewPasswd");
- observed_form()->form_data.fields.push_back(field);
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {saved_match()});
-
- // User submits current and new credentials to the observed form.
- PasswordForm submitted_form(*observed_form());
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.new_password_value = ASCIIToUTF16("test2");
- submitted_form.preferred = true;
- form_manager.ProvisionallySave(submitted_form);
-
- // Successful login. The PasswordManager would instruct PasswordFormManager
- // to update.
- EXPECT_FALSE(form_manager.IsNewLogin());
- EXPECT_TRUE(form_manager.IsPossibleChangePasswordFormWithoutUsername());
-
- // By now, the PasswordFormManager should have promoted the new password
- // value already to be the current password, and should no longer maintain
- // any info about the new password value.
- EXPECT_EQ(submitted_form.new_password_value,
- form_manager.GetPendingCredentials().password_value);
- EXPECT_TRUE(form_manager.GetPendingCredentials().new_password_value.empty());
-
- std::map<base::string16, autofill::ServerFieldType> expected_types;
- expected_types[observed_form()->password_element] = autofill::PASSWORD;
- expected_types[observed_form()->new_password_element] =
- autofill::NEW_PASSWORD;
-
- autofill::ServerFieldTypeSet expected_available_field_types;
- expected_available_field_types.insert(autofill::PASSWORD);
- expected_available_field_types.insert(autofill::NEW_PASSWORD);
-
- InSequence in_sequence;
- // Password change vote.
- std::string expected_login_signature =
- autofill::FormStructure(saved_match()->form_data).FormSignatureAsStr();
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(AllOf(UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false),
- SignatureIsSameAs(*observed_form())),
- false, expected_available_field_types,
- expected_login_signature, true, nullptr));
- // First login vote.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(submitted_form), _, _, _, _,
- nullptr));
-
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Update(_, _, _));
- form_manager.Save();
-}
+// Test that an attempt to log to ReadonlyWhenSaving UKM is made when creating
+// pending credentials, even when their parsing itself is unsuccessful.
+TEST_F(PasswordFormManagerTest, RecordReadonlyWhenSaving_ParsingFailed) {
+ // The scoped context is needed for the UKM recorder.
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
-// Checks uploading a vote about the usage of the password generation popup.
-TEST_F(PasswordFormManagerTest, GeneratedVoteUpload) {
- bool kFalseTrue[] = {false, true};
- SavePromptInteraction kSavePromptInterations[] = {SAVE, NEVER,
- NO_INTERACTION};
- for (bool is_manual_generation : kFalseTrue) {
- for (bool is_change_password_form : kFalseTrue) {
- for (bool has_generated_password : kFalseTrue) {
- for (bool generated_password_changed : kFalseTrue) {
- for (SavePromptInteraction interaction : kSavePromptInterations) {
- GeneratedVoteUploadTest(is_manual_generation,
- is_change_password_form,
- has_generated_password,
- generated_password_changed, interaction);
- }
- }
- }
- }
- }
-}
+ FormData malformed_form = submitted_form_;
+ malformed_form.fields.clear();
+ EXPECT_FALSE(form_manager_->ProvisionallySave(malformed_form, &driver_));
-TEST_F(PasswordFormManagerTest, GeneratedPasswordUkm) {
- bool kFalseTrue[] = {false, true};
- SavePromptInteraction kSavePromptInterations[] = {SAVE, NEVER,
- NO_INTERACTION};
- for (bool is_manual_generation : kFalseTrue) {
- for (bool is_change_password_form : kFalseTrue) {
- for (bool has_generated_password : kFalseTrue) {
- for (bool generated_password_changed : kFalseTrue) {
- for (SavePromptInteraction interaction : kSavePromptInterations) {
- GeneratedPasswordUkmTest(is_manual_generation,
- is_change_password_form,
- has_generated_password,
- generated_password_changed, interaction);
- }
- }
- }
- }
- }
-}
+ // Destroy the form manager to destroy the UKM recorder it owns. The recorder
+ // only records metrics in its destructor.
+ form_manager_.reset();
-TEST_F(PasswordFormManagerTest, PresaveGeneratedPasswordAndRemoveIt) {
- PasswordForm credentials = *observed_form();
- credentials.username_value = ASCIIToUTF16("username");
- credentials.password_value = ASCIIToUTF16("password");
-
- // Simulate the user accepted a generated password.
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Save(FormIgnoreDate(credentials), _, _));
- form_manager()->PresaveGeneratedPassword(credentials);
- EXPECT_TRUE(form_manager()->HasGeneratedPassword());
- EXPECT_FALSE(form_manager()->generated_password_changed());
-
- // Simulate the user changed the presaved username.
- PasswordForm saved_form = credentials;
- credentials.username_value = ASCIIToUTF16("new_username");
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- UpdateReplace(FormIgnoreDate(credentials), _, _,
- FormIgnoreDate(saved_form)));
- form_manager()->PresaveGeneratedPassword(credentials);
- EXPECT_TRUE(form_manager()->HasGeneratedPassword());
- EXPECT_FALSE(form_manager()->generated_password_changed());
-
- // Simulate the user changed the presaved password.
- saved_form = credentials;
- credentials.password_value = ASCIIToUTF16("changed_password");
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- UpdateReplace(FormIgnoreDate(credentials), _, _,
- FormIgnoreDate(saved_form)));
- form_manager()->PresaveGeneratedPassword(credentials);
- EXPECT_TRUE(form_manager()->HasGeneratedPassword());
- EXPECT_TRUE(form_manager()->generated_password_changed());
-
- // Simulate the user removed the presaved password.
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Remove(FormIgnoreDate(credentials)));
- form_manager()->PasswordNoLongerGenerated();
-}
+ auto entries = test_ukm_recorder.GetEntriesByName(
+ ukm::builders::PasswordForm::kEntryName);
+ ASSERT_EQ(1u, entries.size());
-TEST_F(PasswordFormManagerTest, FieldPropertiesMasksUpload) {
- PasswordForm form(*observed_form());
- form.form_data = saved_match()->form_data;
-
- // Create submitted form.
- PasswordForm submitted_form(form);
- submitted_form.preferred = true;
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), form,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- DCHECK_EQ(3U, form.form_data.fields.size());
- submitted_form.form_data.fields[1].properties_mask =
- FieldPropertiesFlags::USER_TYPED;
- submitted_form.form_data.fields[2].properties_mask =
- FieldPropertiesFlags::USER_TYPED;
-
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties;
- for (const autofill::FormFieldData& field : submitted_form.form_data.fields)
- if (field.properties_mask)
- expected_field_properties[field.name] = field.properties_mask;
-
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- false, _, _, true, nullptr));
- form_manager.ProvisionallySave(submitted_form);
- form_manager.Save();
+ EXPECT_FALSE(ParsingSuccessReported(
+ entries[0], ukm::builders::PasswordForm::kReadonlyWhenSavingName));
}
-TEST_F(PasswordFormManagerTest, TestSavingAPIFormsWithSamePassword) {
- // Turn |observed_form| and |saved_match| to API created forms.
- observed_form()->username_element.clear();
- observed_form()->type = autofill::PasswordForm::Type::kApi;
- saved_match()->username_element.clear();
- saved_match()->type = autofill::PasswordForm::Type::kApi;
-
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(password_manager(), client(),
- client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager.Init(nullptr);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {saved_match()});
-
- // User submits new credentials with the same password as in already saved
- // one.
- PasswordForm credentials(*observed_form());
- credentials.username_value =
- saved_match()->username_value + ASCIIToUTF16("1");
- credentials.password_value = saved_match()->password_value;
- credentials.preferred = true;
-
- form_manager.ProvisionallySave(credentials);
-
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- PasswordForm new_credentials;
- EXPECT_CALL(MockFormSaver::Get(&form_manager), Save(_, _, _))
- .WillOnce(SaveArg<0>(&new_credentials));
-
- form_manager.Save();
-
- EXPECT_EQ(saved_match()->username_value + ASCIIToUTF16("1"),
- new_credentials.username_value);
- EXPECT_EQ(saved_match()->password_value, new_credentials.password_value);
- EXPECT_EQ(base::string16(), new_credentials.username_element);
- EXPECT_EQ(autofill::PasswordForm::Type::kApi, new_credentials.type);
-}
+TEST_F(PasswordFormManagerTest, PresaveGeneratedPasswordEmptyStore) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ fetcher_->NotifyFetchCompleted();
-TEST_F(PasswordFormManagerTest, SkipZeroClickIntact) {
- saved_match()->skip_zero_click = true;
- psl_saved_match()->skip_zero_click = true;
- SetNonFederatedAndNotifyFetchCompleted({saved_match(), psl_saved_match()});
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
-
- // User submits a credentials with an old username and a new password.
- PasswordForm credentials(*observed_form());
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("new_password");
- credentials.preferred = true;
- form_manager()->ProvisionallySave(credentials);
-
- // Trigger saving to exercise some special case handling during updating.
- PasswordForm new_credentials;
- std::vector<const autofill::PasswordForm*> matches;
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _))
- .WillOnce(
- testing::DoAll(SaveArg<0>(&new_credentials), SaveArg<1>(&matches)));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
- form_manager()->Save();
-
- EXPECT_TRUE(new_credentials.skip_zero_click);
- ASSERT_EQ(2u, matches.size());
- EXPECT_TRUE(matches[0]->skip_zero_click);
- EXPECT_TRUE(matches[1]->skip_zero_click);
-}
+ EXPECT_FALSE(form_manager_->HasGeneratedPassword());
-TEST_F(PasswordFormManagerFillOnAccountSelectTest, ProcessFrame) {
- EXPECT_CALL(*client()->mock_driver(),
- ShowInitialPasswordAccountSuggestions(_));
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-}
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
-// Check that PasswordFormManager records
-// PasswordManager_LoginFollowingAutofill as part of processing a credential
-// update.
-TEST_F(PasswordFormManagerTest, ReportProcessingUpdate) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
- PasswordForm pending = *observed_form();
- pending.username_value = saved_match()->username_value;
- pending.password_value = saved_match()->password_value;
- form_manager()->ProvisionallySave(pending);
-
- EXPECT_FALSE(form_manager()->IsNewLogin());
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, _, _, true, nullptr));
-
- base::UserActionTester tester;
- EXPECT_EQ(0, tester.GetActionCount("PasswordManager_LoginFollowingAutofill"));
- form_manager()->Update(*saved_match());
- EXPECT_EQ(1, tester.GetActionCount("PasswordManager_LoginFollowingAutofill"));
-}
+ form_manager_->SetGenerationPopupWasShown(
+ true /* generation_popup_was_shown */, false /* is_manual_generation */);
-// Sanity check for calling OnFetchCompleted with empty vector. Should not
-// crash or make sanitizers scream.
-TEST_F(PasswordFormManagerTest, ProcessMatches_Empty) {
- fake_form_fetcher()->NotifyFetchCompleted();
-}
+ // Check that the generated password is presaved.
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, IsEmpty(), base::string16()))
+ .WillOnce(SaveArg<0>(&saved_form));
-// For all combinations of PasswordForm schemes, test that OnFetchCompleted
-// filters out forms with schemes not matching the observed form.
-TEST_F(PasswordFormManagerTest, RemoveResultsWithWrongScheme_ObservingHTML) {
- constexpr int kMaxValue = static_cast<int>(PasswordForm::Scheme::kMaxValue);
- for (int correct = 0; correct <= kMaxValue; ++correct) {
- for (int wrong = 0; wrong <= kMaxValue; ++wrong) {
- if (correct == wrong)
- continue;
-
- const PasswordForm::Scheme kCorrectScheme =
- static_cast<PasswordForm::Scheme>(correct);
- const PasswordForm::Scheme kWrongScheme =
- static_cast<PasswordForm::Scheme>(wrong);
- SCOPED_TRACE(testing::Message() << "Correct scheme = " << kCorrectScheme
- << ", wrong scheme = " << kWrongScheme);
-
- PasswordForm observed = *observed_form();
- observed.scheme = kCorrectScheme;
- FakeFormFetcher fetcher;
- fetcher.Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(),
- (kCorrectScheme == PasswordForm::Scheme::kHtml ? client()->driver()
- : nullptr),
- observed, std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
-
- PasswordForm match = *saved_match();
- match.scheme = kCorrectScheme;
-
- PasswordForm non_match = match;
- non_match.scheme = kWrongScheme;
-
- // First try putting the correct scheme first in returned matches.
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {&match, &non_match});
-
- EXPECT_EQ(1u, form_manager.GetBestMatches().size());
- EXPECT_EQ(kCorrectScheme,
- form_manager.GetBestMatches().begin()->second->scheme);
-
- // Now try putting the correct scheme last in returned matches.
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, {&non_match, &match});
-
- EXPECT_EQ(1u, form_manager.GetBestMatches().size());
- EXPECT_EQ(kCorrectScheme,
- form_manager.GetBestMatches().begin()->second->scheme);
- }
- }
-}
+ PasswordForm form_with_generated_password = parsed_submitted_form_;
+ FormData& form_data = form_with_generated_password.form_data;
+ form_manager_->PresaveGeneratedPassword(form_with_generated_password);
-// Ensure that DoesManage takes into consideration drivers when origins are
-// different.
-TEST_F(PasswordFormManagerTest, DoesManageDifferentOrigins) {
- for (bool same_drivers : {false, true}) {
- PasswordForm submitted_form(*observed_form());
- observed_form()->origin = GURL("http://accounts.google.com/a/Login");
- submitted_form.origin = GURL("http://accounts.google.com/signin");
-
- EXPECT_NE(observed_form()->origin, submitted_form.origin);
-
- NiceMock<MockPasswordManagerDriver> driver;
- EXPECT_EQ(
- same_drivers ? PasswordFormManager::RESULT_COMPLETE_MATCH
- : PasswordFormManager::RESULT_NO_MATCH,
- form_manager()->DoesManage(
- submitted_form, same_drivers ? client()->driver().get() : &driver));
- }
-}
+ EXPECT_TRUE(form_manager_->HasGeneratedPassword());
+ EXPECT_EQ(saved_form.username_value,
+ form_data.fields[kUsernameFieldIndex].value);
+ EXPECT_EQ(saved_form.password_value,
+ form_data.fields[kPasswordFieldIndex].value);
-// Ensure that DoesManage returns No match when signon realms are different.
-TEST_F(PasswordFormManagerTest, DoesManageDifferentSignonRealmSameDrivers) {
- PasswordForm submitted_form(*observed_form());
- observed_form()->signon_realm = "http://accounts.google.com";
- submitted_form.signon_realm = "http://facebook.com";
+ Mock::VerifyAndClearExpectations(&form_saver);
- EXPECT_EQ(
- PasswordFormManager::RESULT_NO_MATCH,
- form_manager()->DoesManage(submitted_form, client()->driver().get()));
-}
+ // Check that when the generated password is edited, then it's presaved.
+ form_with_generated_password.password_value += ASCIIToUTF16("1");
+ form_data.fields[kPasswordFieldIndex].value =
+ form_with_generated_password.password_value;
+ EXPECT_CALL(form_saver,
+ UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ FormHasUniqueKey(form_with_generated_password)))
+ .WillOnce(SaveArg<0>(&saved_form));
-TEST_F(PasswordFormManagerTest, UploadUsernameCorrectionVote) {
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
- for (bool is_pending_credential_psl_match : {false, true}) {
- // Observed and saved forms have the same password, but different
- // usernames.
- PasswordForm new_login(*observed_form());
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("full_name");
- field.form_control_type = "text";
- new_login.form_data.fields.push_back(field);
-
- field.name = ASCIIToUTF16("observed-username-field");
- field.form_control_type = "text";
- new_login.form_data.fields.push_back(field);
-
- field.name = ASCIIToUTF16("Passwd");
- field.form_control_type = "password";
- new_login.form_data.fields.push_back(field);
-
- const PasswordForm* saved_credential =
- is_pending_credential_psl_match ? psl_saved_match() : saved_match();
-
- new_login.username_value =
- saved_credential->all_possible_usernames[0].first;
- new_login.password_value = saved_credential->password_value;
-
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), new_login,
- std::make_unique<NiceMock<MockFormSaver>>(), fake_form_fetcher());
- form_manager.Init(nullptr);
-
- base::HistogramTester histogram_tester;
- SetNonFederatedAndNotifyFetchCompleted({saved_credential});
- form_manager.ProvisionallySave(new_login);
- histogram_tester.ExpectUniqueSample(
- "PasswordManager.UsernameCorrectionFound", 1, 1);
- // No match found (because usernames are different).
- EXPECT_TRUE(form_manager.IsNewLogin());
-
- // Checks the username correction vote is saved.
- PasswordForm expected_username_vote(*saved_credential);
- expected_username_vote.username_element =
- saved_credential->all_possible_usernames[0].second;
-
- // Checks the upload.
- autofill::ServerFieldTypeSet expected_available_field_types;
- expected_available_field_types.insert(autofill::USERNAME);
- expected_available_field_types.insert(
- autofill::ACCOUNT_CREATION_PASSWORD);
-
- std::string expected_login_signature =
- FormStructure(form_manager.observed_form().form_data)
- .FormSignatureAsStr();
-
- std::map<base::string16, autofill::ServerFieldType> expected_types;
- expected_types[expected_username_vote.username_element] =
- autofill::USERNAME;
- expected_types[expected_username_vote.password_element] =
- autofill::ACCOUNT_CREATION_PASSWORD;
- expected_types[ASCIIToUTF16("Email")] = autofill::UNKNOWN_TYPE;
-
- // Checks the type of the username vote is saved.
- VoteTypeMap expected_vote_types = {
- {expected_username_vote.username_element,
- autofill::AutofillUploadContents::Field::USERNAME_OVERWRITTEN}};
-
- InSequence s;
- autofill::ServerFieldTypeSet field_types;
- field_types.insert(autofill::PASSWORD);
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, false, field_types, std::string(), true,
- nullptr));
-
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(AllOf(SignatureIsSameAs(expected_username_vote),
- UploadedAutofillTypesAre(expected_types),
- HasGenerationVote(false),
- VoteTypesAre(expected_vote_types)),
- false, expected_available_field_types,
- expected_login_signature, true, nullptr));
- form_manager.Save();
- }
-}
+ form_manager_->PresaveGeneratedPassword(form_with_generated_password);
-TEST_F(PasswordFormManagerTest, NoUsernameCorrectionVote) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
- PasswordForm new_login = *observed_form();
- // The username is from |saved_match_.all_possible_usernames|, but the
- // password is different. So, no username correction found.
- new_login.username_value = ASCIIToUTF16("test2@gmail.com");
- new_login.password_value = ASCIIToUTF16("newpass");
+ EXPECT_TRUE(form_manager_->HasGeneratedPassword());
+ EXPECT_EQ(saved_form.username_value,
+ form_data.fields[kUsernameFieldIndex].value);
+ EXPECT_EQ(saved_form.password_value,
+ form_with_generated_password.password_value);
- base::HistogramTester histogram_tester;
- form_manager()->ProvisionallySave(new_login);
- histogram_tester.ExpectUniqueSample("PasswordManager.UsernameCorrectionFound",
- 0, 1);
+ Mock::VerifyAndClearExpectations(&form_saver);
- // Don't expect any vote uploads.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, _, _, _, _))
- .Times(0);
+ // Check UKM metrics.
+ form_manager_.reset();
+ ExpectedGenerationUKM expected_metrics = {
+ base::make_optional(1u) /* shown automatically */,
+ 1 /* password generated */,
+ base::make_optional(1u) /* password modified */};
- form_manager()->Save();
+ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
}
-TEST_F(PasswordFormManagerTest,
- UsernameCorrectionVote_PasswordReusedWithoutUsername) {
- for (bool saved_username_is_empty : {false, true}) {
- SCOPED_TRACE(testing::Message()
- << "saved_username_is_empty=" << saved_username_is_empty);
-
- if (saved_username_is_empty) {
- saved_match()->username_value.clear();
- // |username_element| must be empty as well, but it may be non-empty in
- // credentials saved in past versions. Let's test there will be not vote
- // for this element even if |username_element| has a non-empty value.
- }
+TEST_F(PasswordFormManagerTest, PresaveGenerated_ModifiedUsername) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ fetcher_->NotifyFetchCompleted();
+
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ form_manager_->SetGenerationPopupWasShown(
+ true /* generation_popup_was_shown */, false /* is_manual_generation */);
+
+ // Check that the generated password is presaved.
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
+ PasswordForm form_with_generated_password = parsed_submitted_form_;
+ FormData& form_data = form_with_generated_password.form_data;
+ form_manager_->PresaveGeneratedPassword(form_with_generated_password);
+ Mock::VerifyAndClearExpectations(&form_saver);
+
+ // Check that when the username is edited, then it's presaved.
+ form_with_generated_password.username_value += ASCIIToUTF16("1");
+ form_data.fields[kUsernameFieldIndex].value =
+ form_with_generated_password.username_value;
+
+ EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ FormHasUniqueKey(saved_form)))
+ .WillOnce(SaveArg<0>(&saved_form));
+ form_manager_->PresaveGeneratedPassword(form_with_generated_password);
+
+ EXPECT_TRUE(form_manager_->HasGeneratedPassword());
+ EXPECT_EQ(saved_form.username_value,
+ form_with_generated_password.username_value);
+ EXPECT_EQ(saved_form.password_value,
+ form_with_generated_password.password_value);
+
+ // Check UKM metrics.
+ form_manager_.reset();
+ ExpectedGenerationUKM expected_metrics = {
+ base::make_optional(1u) /* shown automatically */,
+ 1 /* password generated */,
+ base::make_optional(0u) /* password modified */};
+
+ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
+}
+
+TEST_F(PasswordFormManagerTest, GeneratedPasswordWhichIsNotInFormData) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ // Create a password form such that |form_data| do not contain the generated
+ // password.
+ PasswordForm form_with_generated_password;
+ form_with_generated_password.form_data = submitted_form_;
+ const base::string16 generated_password = ASCIIToUTF16("gen_pw");
+ // |password_value| should contain the generated password.
+ form_with_generated_password.password_value = generated_password;
+
+ // Check that the generated password is presaved.
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
+
+ form_manager_->PresaveGeneratedPassword(form_with_generated_password);
+ EXPECT_EQ(submitted_form_.fields[kUsernameFieldIndex].value,
+ saved_form.username_value);
+ EXPECT_EQ(generated_password, saved_form.password_value);
+ EXPECT_TRUE(form_manager_->HasGeneratedPassword());
+
+ // Check that the generated password is saved.
+ EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ FormHasUniqueKey(saved_form)))
+ .WillOnce(SaveArg<0>(&saved_form));
+ EXPECT_CALL(client_, UpdateFormManagers());
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+ form_manager_->Save();
+
+ EXPECT_EQ(submitted_form_.fields[kUsernameFieldIndex].value,
+ saved_form.username_value);
+ EXPECT_EQ(generated_password, saved_form.password_value);
+}
+
+TEST_F(PasswordFormManagerTest, PresaveGenerationWhenParsingFails) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ // Create a password form with empty |form_data|. On this form the form parser
+ // should fail.
+ PasswordForm form_with_empty_form_data;
+ const base::string16 generated_password = ASCIIToUTF16("gen_pw");
+ form_with_empty_form_data.password_value = generated_password;
+
+ // Check that nevertheless the generated password is presaved.
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, IsEmpty(), base::string16()))
+ .WillOnce(SaveArg<0>(&saved_form));
+ form_manager_->PresaveGeneratedPassword(form_with_empty_form_data);
+ EXPECT_EQ(generated_password, saved_form.password_value);
+}
+
+TEST_F(PasswordFormManagerTest, PasswordNoLongerGenerated) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ fetcher_->NotifyFetchCompleted();
- saved_match()->all_possible_usernames.push_back(
- ValueElementPair(base::string16(), ASCIIToUTF16("empty_field")));
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // A user enters the password in the form. The username is absent or not
- // captured, but the user doesn't enter the username in a prompt.
- PasswordForm credential(*saved_match());
- credential.username_value.clear();
- credential.preferred = true;
- form_manager()->ProvisionallySave(credential);
- EXPECT_FALSE(form_manager()->IsNewLogin());
-
- // Create the expected credential to be saved.
- PasswordForm expected_pending(*saved_match());
- expected_pending.times_used = 1;
- // As a credential is reused, |all_possible_usernames| will be cleared.
- // In fact, the username wasn't reused, only password, but for the sake of
- // simplicity |all_possible_usernames| is cleared even in this case.
- expected_pending.all_possible_usernames.clear();
-
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Update(expected_pending, ElementsAre(Pointee(*saved_match())),
- saved_match()->password_value));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, _, _, _, nullptr));
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, Not(Contains(autofill::USERNAME)), _,
- _, nullptr));
- form_manager()->Save();
- }
-}
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ form_manager_->SetGenerationPopupWasShown(
+ true /* generation_popup_was_shown */, true /* is_manual_generation */);
-// Test that ResetStoredMatches removes references to previously fetched store
-// results.
-TEST_F(PasswordFormManagerTest, ResetStoredMatches) {
- PasswordForm best_match1 = *observed_form();
- best_match1.username_value = ASCIIToUTF16("user1");
- best_match1.password_value = ASCIIToUTF16("pass");
- best_match1.preferred = true;
-
- PasswordForm best_match2 = best_match1;
- best_match2.username_value = ASCIIToUTF16("user2");
- best_match2.preferred = false;
-
- PasswordForm non_best_match = best_match1;
- non_best_match.action = GURL();
-
- PasswordForm blacklisted = *observed_form();
- blacklisted.blacklisted_by_user = true;
- blacklisted.username_value.clear();
-
- fake_form_fetcher()->SetNonFederated(
- {&best_match1, &best_match2, &non_best_match});
- fake_form_fetcher()->SetBlacklisted({&blacklisted});
- fake_form_fetcher()->NotifyFetchCompleted();
-
- EXPECT_EQ(2u, form_manager()->GetBestMatches().size());
- EXPECT_TRUE(form_manager()->preferred_match());
- EXPECT_EQ(1u, form_manager()->GetBlacklistedMatches().size());
-
- // Trigger Update to verify that there is a non-best match.
- PasswordForm updated(best_match1);
- updated.password_value = ASCIIToUTF16("updated password");
- form_manager()->ProvisionallySave(updated);
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _));
- form_manager()->Save();
-
- form_manager()->ResetStoredMatches();
-
- EXPECT_THAT(form_manager()->GetBestMatches(), IsEmpty());
- EXPECT_FALSE(form_manager()->preferred_match());
- EXPECT_THAT(form_manager()->GetBlacklistedMatches(), IsEmpty());
-
- // Simulate updating a saved credential again, but this time without non-best
- // matches. Verify that the old non-best matches are no longer present.
- fake_form_fetcher()->Fetch();
- SetNonFederatedAndNotifyFetchCompleted({&best_match1});
-
- form_manager()->ProvisionallySave(updated);
- EXPECT_CALL(MockFormSaver::Get(form_manager()), Update(_, _, _));
- form_manager()->Save();
-}
+ EXPECT_CALL(form_saver, Save(_, _, _));
-// Check that on changing FormFetcher, the PasswordFormManager removes itself
-// from consuming the old one.
-TEST_F(PasswordFormManagerTest, DropFetcherOnDestruction) {
- MockFormFetcher fetcher;
- FormFetcher::Consumer* added_consumer = nullptr;
- EXPECT_CALL(fetcher, AddConsumer(_)).WillOnce(SaveArg<0>(&added_consumer));
- auto form_manager = std::make_unique<PasswordFormManager>(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager->Init(nullptr);
- EXPECT_EQ(form_manager.get(), added_consumer);
-
- EXPECT_CALL(fetcher, RemoveConsumer(form_manager.get()));
- form_manager.reset();
-}
+ PasswordForm form = parsed_submitted_form_;
+ form_manager_->PresaveGeneratedPassword(form);
+ Mock::VerifyAndClearExpectations(&form_saver);
-// Check that if asked to take ownership of the same FormFetcher which it had
-// consumed before, the PasswordFormManager does not add itself as a consumer
-// again.
-TEST_F(PasswordFormManagerTest, GrabFetcher_Same) {
- auto fetcher = std::make_unique<MockFormFetcher>();
- fetcher->Fetch();
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), fetcher.get());
- form_manager.Init(nullptr);
-
- EXPECT_CALL(*fetcher, AddConsumer(_)).Times(0);
- EXPECT_CALL(*fetcher, RemoveConsumer(_)).Times(0);
- form_manager.GrabFetcher(std::move(fetcher));
- // There will be a RemoveConsumer call as soon as form_manager goes out of
- // scope, but the test needs to ensure that there is none as a result of
- // GrabFetcher.
- Mock::VerifyAndClearExpectations(form_manager.GetFormFetcher());
-}
+ EXPECT_TRUE(form_manager_->HasGeneratedPassword());
-// Check that if asked to take ownership of a different FormFetcher than which
-// it had consumed before, the PasswordFormManager adds itself as a consumer
-// and replaces the references to the old results.
-TEST_F(PasswordFormManagerTest, GrabFetcher_Different) {
- PasswordForm old_match = *observed_form();
- old_match.username_value = ASCIIToUTF16("user1");
- old_match.password_value = ASCIIToUTF16("pass");
- SetNonFederatedAndNotifyFetchCompleted({&old_match});
- EXPECT_EQ(1u, form_manager()->GetBestMatches().size());
- EXPECT_EQ(&old_match, form_manager()->GetBestMatches().begin()->second);
-
- // |form_manager()| uses |fake_form_fetcher()|, which is an instance
- // different from |fetcher| below.
- auto fetcher = std::make_unique<MockFormFetcher>();
- fetcher->Fetch();
- fetcher->NotifyFetchCompleted();
- EXPECT_CALL(*fetcher, AddConsumer(form_manager()));
- form_manager()->GrabFetcher(std::move(fetcher));
-
- EXPECT_EQ(0u, form_manager()->GetBestMatches().size());
-}
+ // Check when the user removes the generated password on the page, it is
+ // removed from the store.
+ EXPECT_CALL(form_saver, Remove(_));
+ form_manager_->PasswordNoLongerGenerated();
-// Check that on changing FormFetcher, the PasswordFormManager removes itself
-// from consuming the old one.
-TEST_F(PasswordFormManagerTest, GrabFetcher_Remove) {
- MockFormFetcher old_fetcher;
- FormFetcher::Consumer* added_consumer = nullptr;
- EXPECT_CALL(old_fetcher, AddConsumer(_))
- .WillOnce(SaveArg<0>(&added_consumer));
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &old_fetcher);
- form_manager.Init(nullptr);
- EXPECT_EQ(&form_manager, added_consumer);
-
- auto new_fetcher = std::make_unique<MockFormFetcher>();
- EXPECT_CALL(*new_fetcher, AddConsumer(&form_manager));
- EXPECT_CALL(old_fetcher, RemoveConsumer(&form_manager));
- form_manager.GrabFetcher(std::move(new_fetcher));
-}
+ EXPECT_FALSE(form_manager_->HasGeneratedPassword());
-// Check that a cloned PasswordFormManager reacts correctly to Save.
-TEST_F(PasswordFormManagerTest, Clone_OnSave) {
- FakeFormFetcher fetcher;
- auto form_manager = std::make_unique<PasswordFormManager>(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager->Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- PasswordForm saved_login = *observed_form();
- saved_login.username_value = ASCIIToUTF16("newuser");
- saved_login.password_value = ASCIIToUTF16("newpass");
- form_manager->ProvisionallySave(saved_login);
-
- const PasswordForm pending = form_manager->GetPendingCredentials();
-
- std::unique_ptr<PasswordFormManager> clone = form_manager->Clone();
-
- PasswordForm passed;
- EXPECT_CALL(MockFormSaver::Get(clone.get()), Save(_, IsEmpty(), _))
- .WillOnce(SaveArg<0>(&passed));
- clone->Save();
- // The date is expected to be different. Reset it so that we can easily
- // compare the rest with operator==.
- passed.date_created = pending.date_created;
- EXPECT_EQ(pending, passed);
+ // Check UKM metrics.
+ form_manager_.reset();
+ ExpectedGenerationUKM expected_metrics = {
+ base::make_optional(2u) /* shown manually */,
+ 0 /* password generated */,
+ {} /* generated password is not modified */};
+
+ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
}
-// Check that a cloned PasswordFormManager reacts correctly to OnNeverClicked.
-TEST_F(PasswordFormManagerTest, Clone_OnNeverClicked) {
- FakeFormFetcher fetcher;
- auto form_manager = std::make_unique<PasswordFormManager>(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- form_manager->Init(nullptr);
- fetcher.NotifyFetchCompleted();
+TEST_F(PasswordFormManagerTest, PresaveGeneratedPasswordExistingCredential) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- PasswordForm saved_login = *observed_form();
- saved_login.username_value = ASCIIToUTF16("newuser");
- saved_login.password_value = ASCIIToUTF16("newpass");
- form_manager->ProvisionallySave(saved_login);
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- std::unique_ptr<PasswordFormManager> clone = form_manager->Clone();
+ form_manager_->SetGenerationPopupWasShown(
+ true /* generation_popup_was_shown */, false /* is_manual_generation */);
- EXPECT_CALL(
- MockFormSaver::Get(clone.get()),
- PermanentlyBlacklist(PasswordStore::FormDigest(*observed_form())));
- clone->OnNeverClicked();
-}
-
-// Check that a cloned PasswordFormManager works even after the original is
-// gone.
-TEST_F(PasswordFormManagerTest, Clone_SurvivesOriginal) {
- FakeFormFetcher fetcher;
- auto form_manager = std::make_unique<PasswordFormManager>(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<MockFormSaver>(), &fetcher);
- fetcher.NotifyFetchCompleted();
- form_manager->Init(nullptr);
-
- PasswordForm saved_login = *observed_form();
- saved_login.username_value = ASCIIToUTF16("newuser");
- saved_login.password_value = ASCIIToUTF16("newpass");
- form_manager->ProvisionallySave(saved_login);
-
- const PasswordForm pending = form_manager->GetPendingCredentials();
-
- std::unique_ptr<PasswordFormManager> clone = form_manager->Clone();
- form_manager.reset();
-
- PasswordForm passed;
- EXPECT_CALL(MockFormSaver::Get(clone.get()), Save(_, IsEmpty(), _))
- .WillOnce(SaveArg<0>(&passed));
- clone->Save();
- // The date is expected to be different. Reset it so that we can easily
- // compare the rest with operator==.
- passed.date_created = pending.date_created;
- EXPECT_EQ(pending, passed);
-}
+ // Check that the generated password is presaved.
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
-// Verifies that URL keyed metrics are recorded for the filling of passwords
-// into forms and HTTP Basic auth.
-TEST_F(PasswordFormManagerTest, TestUkmForFilling) {
- PasswordForm scheme_basic_form = *observed_form();
- scheme_basic_form.scheme = PasswordForm::Scheme::kBasic;
-
- const struct {
- // Whether the login is doing HTTP Basic Auth instead of form based login.
- bool is_http_basic_auth;
- // The matching stored credentials, or nullptr if none.
- PasswordForm* fetched_form;
- PasswordFormMetricsRecorder::ManagerAutofillEvent expected_event;
- } kTestCases[] = {
- {false, saved_match(),
- PasswordFormMetricsRecorder::kManagerFillEventAutofilled},
- {false, psl_saved_match(),
- PasswordFormMetricsRecorder::kManagerFillEventBlockedOnInteraction},
- {false, nullptr,
- PasswordFormMetricsRecorder::kManagerFillEventNoCredential},
- {true, &scheme_basic_form,
- PasswordFormMetricsRecorder::kManagerFillEventAutofilled},
- {true, nullptr,
- PasswordFormMetricsRecorder::kManagerFillEventNoCredential},
- };
+ PasswordForm form_with_generated_password = parsed_submitted_form_;
+ FormData& form_data = form_with_generated_password.form_data;
- for (const auto& test : kTestCases) {
- const PasswordForm& form_to_fill =
- test.is_http_basic_auth ? scheme_basic_form : *observed_form();
-
- std::vector<const autofill::PasswordForm*> fetched_forms;
- if (test.fetched_form)
- fetched_forms.push_back(test.fetched_form);
-
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- {
- auto metrics_recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
- form_to_fill.origin.SchemeIsCryptographic(),
- client()->GetUkmSourceId());
- FakeFormFetcher fetcher;
- PasswordFormManager form_manager(
- password_manager(), client(),
- test.is_http_basic_auth ? nullptr : client()->driver(), form_to_fill,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(metrics_recorder);
- SetNonFederatedAndNotifyFetchCompleted(&fetcher, fetched_forms);
- }
+ // Check that the generated password is saved with the empty username when
+ // there is already a saved credetial with the same username.
+ form_data.fields[kUsernameFieldIndex].value = saved_match_.username_value;
+ form_manager_->PresaveGeneratedPassword(form_with_generated_password);
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- EXPECT_EQ(1u, entries.size());
- for (const auto* const entry : entries) {
- EXPECT_EQ(client()->GetUkmSourceId(), entry->source_id);
- test_ukm_recorder.ExpectEntryMetric(
- entry, ukm::builders::PasswordForm::kManagerFill_ActionName,
- test.expected_event);
- }
- }
+ EXPECT_TRUE(form_manager_->HasGeneratedPassword());
+ EXPECT_TRUE(saved_form.username_value.empty());
+ EXPECT_EQ(form_with_generated_password.password_value,
+ saved_form.password_value);
}
-// Verifies that the form signature of forms is recorded in UKMs.
-TEST_F(PasswordFormManagerTest, TestUkmContextMetrics) {
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- test_ukm_recorder.UpdateSourceURL(client()->GetUkmSourceId(),
- client()->GetMainFrameURL());
-
- // Register two forms on one page.
- PasswordForm second_observed_form = *observed_form();
- second_observed_form.form_data.action = GURL("https://somewhere-else.com");
- for (PasswordForm* form : {observed_form(), &second_observed_form}) {
- auto metrics_recorder = base::MakeRefCounted<PasswordFormMetricsRecorder>(
- form->origin.SchemeIsCryptographic(), client()->GetUkmSourceId());
- FakeFormFetcher fetcher;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *form,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(metrics_recorder);
- }
-
- // Verify that a form signatures have been recorded in UKM.
- int64_t form_signature_1 = PasswordFormMetricsRecorder::HashFormSignature(
- CalculateFormSignature(observed_form()->form_data));
- int64_t form_signature_2 = PasswordFormMetricsRecorder::HashFormSignature(
- CalculateFormSignature(second_observed_form.form_data));
-
- EXPECT_GE(form_signature_1, 0);
- EXPECT_GE(form_signature_2, 0);
+TEST_F(PasswordFormManagerTest, UserEventsForGeneration) {
+ using GeneratedPasswordStatus =
+ PasswordFormMetricsRecorder::GeneratedPasswordStatus;
- auto entries = test_ukm_recorder.GetEntriesByName(
- ukm::builders::PasswordForm::kEntryName);
- ASSERT_EQ(2u, entries.size());
+ PasswordForm submitted_form(parsed_observed_form_);
+ submitted_form.form_data = submitted_form_;
+ FormData& form_data = submitted_form.form_data;
- const int64_t* metric1 = test_ukm_recorder.GetEntryMetric(
- entries[0], ukm::builders::PasswordForm::kContext_FormSignatureName);
- const int64_t* metric2 = test_ukm_recorder.GetEntryMetric(
- entries[1], ukm::builders::PasswordForm::kContext_FormSignatureName);
+ { // User accepts a generated password.
+ base::HistogramTester histogram_tester;
+ CreateFormManager(observed_form_);
+ form_manager_->PresaveGeneratedPassword(submitted_form);
+ form_manager_.reset();
+ histogram_tester.ExpectUniqueSample(
+ "PasswordGeneration.UserDecision",
+ GeneratedPasswordStatus::kPasswordAccepted, 1);
+ }
- ASSERT_TRUE(metric1);
- ASSERT_TRUE(metric2);
+ { // User edits the generated password.
+ base::HistogramTester histogram_tester;
+ CreateFormManager(observed_form_);
+ form_manager_->PresaveGeneratedPassword(submitted_form);
+ form_data.fields[kPasswordFieldIndex].value += ASCIIToUTF16("1");
+ submitted_form.password_value = form_data.fields[kPasswordFieldIndex].value;
+ form_manager_->PresaveGeneratedPassword(submitted_form);
+ form_manager_.reset();
+ histogram_tester.ExpectUniqueSample(
+ "PasswordGeneration.UserDecision",
+ GeneratedPasswordStatus::kPasswordEdited, 1);
+ }
- EXPECT_THAT(
- std::vector<int64_t>({*metric1, *metric2}),
- ::testing::UnorderedElementsAre(form_signature_1, form_signature_2));
+ { // User clears the generated password.
+ base::HistogramTester histogram_tester;
+ CreateFormManager(observed_form_);
+ form_manager_->PresaveGeneratedPassword(submitted_form);
+ form_data.fields[kPasswordFieldIndex].value += ASCIIToUTF16("2");
+ submitted_form.password_value = form_data.fields[kPasswordFieldIndex].value;
+ form_manager_->PresaveGeneratedPassword(submitted_form);
+ form_manager_->PasswordNoLongerGenerated();
+ form_manager_.reset();
+ histogram_tester.ExpectUniqueSample(
+ "PasswordGeneration.UserDecision",
+ GeneratedPasswordStatus::kPasswordDeleted, 1);
+ }
}
-TEST_F(PasswordFormManagerTest, FirstLoginVote) {
- PasswordForm old_without_username = *saved_match();
- old_without_username.username_value.clear();
- old_without_username.username_element.clear();
- old_without_username.times_used = 2;
- struct {
- std::vector<const autofill::PasswordForm*> stored_creds;
- std::string description;
- } test_cases[] = {
- {{saved_match()}, "Credential reused"},
- {{psl_saved_match()}, "PSL credential reused"},
- {{&old_without_username},
- "Submitted credential adds a username to a stored credential without "
- "one"},
- };
+TEST_F(PasswordFormManagerTest, FillForm) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ for (bool observed_form_changed : {false, true}) {
+ SCOPED_TRACE(testing::Message("observed_form_changed=")
+ << observed_form_changed);
+ CreateFormManager(observed_form_);
+ EXPECT_CALL(driver_, FillPasswordForm(_));
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+ task_runner_->FastForwardUntilNoTasksRemain();
+ Mock::VerifyAndClearExpectations(&driver_);
+
+ FormData form = observed_form_;
+
+ if (observed_form_changed) {
+ form.fields[kUsernameFieldIndex].unique_renderer_id += 1000;
+ form.fields[kUsernameFieldIndex].name += ASCIIToUTF16("1");
+ form.fields[kUsernameFieldIndex].id_attribute += ASCIIToUTF16("1");
+#if defined(OS_IOS)
+ form.fields[kUsernameFieldIndex].unique_id += ASCIIToUTF16("1");
+#endif
+ form.fields[kPasswordFieldIndex].unique_renderer_id += 1000;
+ }
- for (auto test_case : test_cases) {
- SCOPED_TRACE(testing::Message()
- << "Stored credentials: " << test_case.description);
-
- SetNonFederatedAndNotifyFetchCompleted(test_case.stored_creds);
-
- PasswordForm submitted_form =
- CreateMinimalCrowdsourcableForm(*observed_form());
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.form_data.fields[0].value = submitted_form.username_value;
- submitted_form.form_data.fields[1].value = submitted_form.password_value;
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
-
- form_manager()->ProvisionallySave(submitted_form);
-
- // The username and password fields contain stored values. This should be
- // signaled in the vote.
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties = {{submitted_form.username_element,
- FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.password_element,
- FieldPropertiesFlags::KNOWN_VALUE}};
-
- // All votes should be FIRST_USE.
- std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
- expected_vote_types = {
- {submitted_form.username_element,
- autofill::AutofillUploadContents::Field::FIRST_USE},
- {submitted_form.password_element,
- autofill::AutofillUploadContents::Field::FIRST_USE}};
-
- // Unrelated vote
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(*test_case.stored_creds.front()),
- _, _, _, _, _))
- .Times(AtMost(1));
- // First login vote
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(submitted_form),
- UploadedAutofillTypesAre(FieldTypeMap(
- {{submitted_form.username_element, autofill::USERNAME},
- {submitted_form.password_element, autofill::PASSWORD},
- {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- VoteTypesAre(expected_vote_types)),
- _,
- autofill::ServerFieldTypeSet(
- {autofill::USERNAME, autofill::PASSWORD}),
- _, true, nullptr));
-
- form_manager()->Save();
-
- Mock::VerifyAndClearExpectations(
- client()->mock_driver()->mock_autofill_download_manager());
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
+ form_manager_->FillForm(form);
+
+ EXPECT_EQ(form.fields[kUsernameFieldIndex].name,
+ fill_data.username_field.name);
+ EXPECT_EQ(form.fields[kUsernameFieldIndex].unique_renderer_id,
+ fill_data.username_field.unique_renderer_id);
+ EXPECT_EQ(saved_match_.username_value, fill_data.username_field.value);
+ EXPECT_EQ(form.fields[kPasswordFieldIndex].name,
+ fill_data.password_field.name);
+ EXPECT_EQ(form.fields[kPasswordFieldIndex].unique_renderer_id,
+ fill_data.password_field.unique_renderer_id);
+ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value);
+
+ base::HistogramTester histogram_tester;
+ form_manager_.reset();
+ uint32_t expected_differences_mask = 0;
+ if (observed_form_changed)
+ expected_differences_mask = 2; // renderer_id changes.
+ histogram_tester.ExpectUniqueSample("PasswordManager.DynamicFormChanges",
+ expected_differences_mask, 1);
}
}
-// Tests scenarios where no vote should be uploaded.
-TEST_F(PasswordFormManagerTest, FirstLoginVote_NoVote) {
- PasswordForm old_credential(*saved_match());
- old_credential.times_used = 1;
-
- // A new username means a new credential. We will vote on it the next time it
- // is used, not now.
- PasswordForm different_username(*saved_match());
- different_username.username_value = ASCIIToUTF16("DifferentUsername");
-
- struct {
- std::vector<const autofill::PasswordForm*> stored_creds;
- std::string description;
- } test_cases[] = {
- {{}, "No credentials stored"},
- {{&old_credential}, "Not first use"},
- {{&different_username}, "Different username"},
- };
+TEST_F(PasswordFormManagerTest, FillFormWaitForServerPredictions) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
- for (auto test_case : test_cases) {
- SCOPED_TRACE(testing::Message()
- << "Stored credentials: " << test_case.description);
+ FormData changed_form = observed_form_;
- SetNonFederatedAndNotifyFetchCompleted(test_case.stored_creds);
+ changed_form.fields[kUsernameFieldIndex].unique_renderer_id += 1000;
+ changed_form.fields[kPasswordFieldIndex].unique_renderer_id += 1000;
- // User submits credentials for the observed form.
- PasswordForm submitted_form =
- CreateMinimalCrowdsourcableForm(*observed_form());
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.form_data.fields[0].value = submitted_form.username_value;
- submitted_form.form_data.fields[1].value = submitted_form.password_value;
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
+ // Check that no filling until server predicions or filling timeout
+ // expiration.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ form_manager_->FillForm(changed_form);
+ Mock::VerifyAndClearExpectations(&driver_);
- form_manager()->ProvisionallySave(submitted_form);
+ // Check that the changed form is filled after the filling timeout expires.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(_, _, _, _, _, _))
- .Times(0);
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
- form_manager()->Save();
+ task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(changed_form.fields[kUsernameFieldIndex].unique_renderer_id,
+ fill_data.username_field.unique_renderer_id);
+ EXPECT_EQ(changed_form.fields[kPasswordFieldIndex].unique_renderer_id,
+ fill_data.password_field.unique_renderer_id);
- Mock::VerifyAndClearExpectations(
- client()->mock_driver()->mock_autofill_download_manager());
- }
+ base::HistogramTester histogram_tester;
+ form_manager_.reset();
+ uint32_t expected_differences_mask = 2; // renderer_id changes.
+ histogram_tester.ExpectUniqueSample("PasswordManager.DynamicFormChanges",
+ expected_differences_mask, 1);
}
-// If we update an existing credential with a new password, only the username is
-// a known value.
-TEST_F(PasswordFormManagerTest,
- FirstLoginVote_UpdatePasswordVotesOnlyForUsername) {
- PasswordForm different_password(*saved_match());
- different_password.password_value = ASCIIToUTF16("DifferentPassword");
- SetNonFederatedAndNotifyFetchCompleted({&different_password});
-
- PasswordForm submitted_form =
- CreateMinimalCrowdsourcableForm(*observed_form());
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.form_data.fields[0].value = submitted_form.username_value;
- submitted_form.form_data.fields[1].value = submitted_form.password_value;
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
-
- form_manager()->ProvisionallySave(submitted_form);
-
- // The username and password fields contain stored values. This should be
- // signaled in the vote.
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties = {
- {submitted_form.username_element, FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.password_element, 0}};
-
- // All votes should be FIRST_USE.
- std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
- expected_vote_types = {
- {submitted_form.username_element,
- autofill::AutofillUploadContents::Field::FIRST_USE}};
-
- // Unrelated vote
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(different_password), _, _, _, _, _))
- .Times(AtMost(1));
- // First login vote
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(submitted_form),
- UploadedAutofillTypesAre(FieldTypeMap(
- {{submitted_form.username_element, autofill::USERNAME},
- {submitted_form.password_element, autofill::UNKNOWN_TYPE},
- {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- VoteTypesAre(expected_vote_types)),
- _, autofill::ServerFieldTypeSet({autofill::USERNAME}), _, true,
- nullptr));
-
- form_manager()->Save();
-}
+TEST_F(PasswordFormManagerTest, Update) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-// Values on a submitted form should be marked as KNOWN_VALUE only if they match
-// values from the credential which was used to log in. Other stored credentials
-// are ignored.
-TEST_F(PasswordFormManagerTest, FirstLoginVote_MatchOnlySubmittedCredentials) {
- PasswordForm alternative_credential = *saved_match();
- alternative_credential.username_value = ASCIIToUTF16("flatmate");
- alternative_credential.password_value = ASCIIToUTF16("p@ssword");
+ PasswordForm not_best_saved_match = saved_match_;
+ not_best_saved_match.preferred = false;
+ PasswordForm saved_match_another_username = saved_match_;
+ saved_match_another_username.username_value += ASCIIToUTF16("1");
SetNonFederatedAndNotifyFetchCompleted(
- {&alternative_credential, saved_match()});
-
- // User submits credentials for the observed form.
- PasswordForm submitted_form =
- CreateMinimalCrowdsourcableForm(*observed_form());
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.form_data.fields[0].value = submitted_form.username_value;
- submitted_form.form_data.fields[1].value = submitted_form.password_value;
- // Use a value from an alternative credential. It should not be voted as a
- // known value.
- submitted_form.form_data.fields[2].value =
- alternative_credential.username_value;
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
-
- form_manager()->ProvisionallySave(submitted_form);
-
- // The username and password fields contain stored values. This should be
- // signaled in the vote.
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties = {
- {submitted_form.username_element, FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.password_element, FieldPropertiesFlags::KNOWN_VALUE},
- {ASCIIToUTF16("petname"), 0}};
-
- // All votes should be FIRST_USE.
- std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
- expected_vote_types = {
- {submitted_form.username_element,
- autofill::AutofillUploadContents::Field::FIRST_USE},
- {submitted_form.password_element,
- autofill::AutofillUploadContents::Field::FIRST_USE}};
-
- // Unrelated vote.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _,
- nullptr))
- .Times(1);
- // First login vote.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(submitted_form),
- UploadedAutofillTypesAre(FieldTypeMap(
- {{submitted_form.username_element, autofill::USERNAME},
- {submitted_form.password_element, autofill::PASSWORD},
- {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- VoteTypesAre(expected_vote_types)),
- _,
- autofill::ServerFieldTypeSet(
- {autofill::USERNAME, autofill::PASSWORD}),
- _, true, nullptr));
-
- form_manager()->Save();
-}
+ {&saved_match_, &saved_match_another_username});
+
+ FormData submitted_form = observed_form_;
+ base::string16 username = saved_match_.username_value;
+ base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
+ submitted_form.fields[kUsernameFieldIndex].value = username;
+ submitted_form.fields[kPasswordFieldIndex].value = new_password;
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+ PasswordForm updated_form;
+ EXPECT_CALL(form_saver, Update(_,
+ UnorderedElementsAre(
+ Pointee(saved_match_),
+ Pointee(saved_match_another_username)),
+ saved_match_.password_value))
+ .WillOnce(SaveArg<0>(&updated_form));
+ EXPECT_CALL(client_, UpdateFormManagers());
+
+ const base::Time kNow = base::Time::Now();
+ form_manager_->Update(saved_match_);
+
+ EXPECT_TRUE(ArePasswordFormUniqueKeysEqual(saved_match_, updated_form));
+ EXPECT_TRUE(updated_form.preferred);
+ EXPECT_EQ(new_password, updated_form.password_value);
+ EXPECT_GE(updated_form.date_last_used, kNow);
+}
+
+// TODO(https://crbug.com/918846): implement FillingAssistance metric on iOS.
+#if defined(OS_IOS)
+#define MAYBE_FillingAssistanceMetric DISABLED_FillingAssistanceMetric
+#else
+#define MAYBE_FillingAssistanceMetric FillingAssistanceMetric
+#endif
+TEST_F(PasswordFormManagerTest, MAYBE_FillingAssistanceMetric) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
+
+ // Simulate that the user fills the saved credentials manually.
+ submitted_form_.fields[kUsernameFieldIndex].value =
+ saved_match_.username_value;
+ submitted_form_.fields[kUsernameFieldIndex].properties_mask =
+ FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER;
+ submitted_form_.fields[kPasswordFieldIndex].value =
+ saved_match_.password_value;
+ submitted_form_.fields[kPasswordFieldIndex].properties_mask =
+ FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER;
-TEST_F(PasswordFormManagerTest, FirstLoginVote_NoUsernameSaved) {
- // We have a credential without a username saved.
- saved_match()->username_element.clear();
- saved_match()->username_value.clear();
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User submits credentials for the observed form.
- PasswordForm submitted_form =
- CreateMinimalCrowdsourcableForm(*observed_form());
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.form_data.fields[0].value = submitted_form.username_value;
- submitted_form.form_data.fields[1].value = submitted_form.password_value;
- // An empty field should not be a known username, even if we have no username.
- submitted_form.form_data.fields[2].value.clear();
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
-
- form_manager()->ProvisionallySave(submitted_form);
-
- // The password field contains stored values. This should be signaled in the
- // vote.
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties = {
- {submitted_form.username_element, 0}, // Don't match empty values.
- {submitted_form.password_element, FieldPropertiesFlags::KNOWN_VALUE}};
-
- // All votes should be FIRST_USE.
- std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
- expected_vote_types = {
- {submitted_form.username_element,
- autofill::AutofillUploadContents::Field::FIRST_USE},
- {submitted_form.password_element,
- autofill::AutofillUploadContents::Field::FIRST_USE},
- {ASCIIToUTF16("petname"),
- autofill::AutofillUploadContents::Field::NO_INFORMATION}};
-
- // Unrelated vote.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _,
- nullptr))
- .Times(1);
- // First login vote.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(submitted_form),
- UploadedAutofillTypesAre(FieldTypeMap(
- {{submitted_form.username_element, autofill::USERNAME},
- {submitted_form.password_element, autofill::PASSWORD},
- {ASCIIToUTF16("petname"), autofill::UNKNOWN_TYPE}})),
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- VoteTypesAre(expected_vote_types)),
- _,
- autofill::ServerFieldTypeSet(
- {autofill::USERNAME, autofill::PASSWORD}),
- _, true, nullptr));
-
- form_manager()->Save();
-}
-
-// Upload a first login (i.e. first use) vote when the form has no username
-// field.
-TEST_F(PasswordFormManagerTest, FirstLoginVote_NoUsernameSubmitted) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- // User submits credentials for the observed form.
- PasswordForm submitted_form = *observed_form();
- submitted_form.origin = GURL("https://www.foo.com/login");
- submitted_form.form_data.url = submitted_form.origin;
+ base::HistogramTester histogram_tester;
+ // Simulate successful submission.
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
+ form_manager_->GetMetricsRecorder()->LogSubmitPassed();
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("password1");
- field.form_control_type = "password";
- submitted_form.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("password2");
- field.form_control_type = "new-password";
- submitted_form.form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("password3");
- field.form_control_type = "new-password";
- submitted_form.form_data.fields.push_back(field);
-
- submitted_form.username_value.clear();
- submitted_form.username_element.clear();
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.password_element = ASCIIToUTF16("password1");
- submitted_form.form_data.fields[0].value = saved_match()->password_value;
- submitted_form.form_data.fields[1].value = ASCIIToUTF16("newpassword");
- submitted_form.form_data.fields[2].value = ASCIIToUTF16("newpassword");
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
-
- form_manager()->ProvisionallySave(submitted_form);
-
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties = {
- {submitted_form.password_element, FieldPropertiesFlags::KNOWN_VALUE}};
-
- std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
- expected_vote_types = {
- {submitted_form.password_element,
- autofill::AutofillUploadContents::Field::FIRST_USE}};
-
- FieldTypeMap expected_votes = {
- {submitted_form.form_data.fields[0].name, autofill::PASSWORD},
- {submitted_form.form_data.fields[1].name, autofill::UNKNOWN_TYPE},
- {submitted_form.form_data.fields[2].name, autofill::UNKNOWN_TYPE}};
-
- // Unrelated vote.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _,
- nullptr))
- .Times(1);
- // First login vote.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(submitted_form),
- UploadedAutofillTypesAre(expected_votes),
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- VoteTypesAre(expected_vote_types)),
- _, autofill::ServerFieldTypeSet({autofill::PASSWORD}), _, true,
- nullptr));
-
- form_manager()->Save();
+ form_manager_.reset();
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.FillingAssistance",
+ PasswordFormMetricsRecorder::FillingAssistance::kManual, 1);
}
-// All fields with a known value should have the KNOWN_VALUE flag.
-TEST_F(PasswordFormManagerTest, FirstLoginVote_KnownValue) {
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
-
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("email");
- field.form_control_type = "text";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("petname");
- field.form_control_type = "text";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("pin");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("password");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("repeat password");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("repeat email");
- field.form_control_type = "text";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("empty password");
- field.form_control_type = "password";
- observed_form()->form_data.fields.push_back(field);
- field.name = ASCIIToUTF16("empty text");
- field.form_control_type = "text";
- observed_form()->form_data.fields.push_back(field);
- observed_form()->username_element = ASCIIToUTF16("email");
- observed_form()->password_element = ASCIIToUTF16("password");
- // User submits credentials for the observed form.
- PasswordForm submitted_form = *observed_form();
- submitted_form.origin = GURL("https://www.foo.com/login");
- submitted_form.form_data.url = submitted_form.origin;
- submitted_form.username_value = saved_match()->username_value;
- submitted_form.password_value = saved_match()->password_value;
- submitted_form.form_data.fields[0].value = submitted_form.username_value;
- submitted_form.form_data.fields[1].value = ASCIIToUTF16("Snoop");
- submitted_form.form_data.fields[2].value = ASCIIToUTF16("1234");
- submitted_form.form_data.fields[3].value = submitted_form.password_value;
- submitted_form.form_data.fields[4].value = submitted_form.password_value;
- submitted_form.form_data.fields[5].value = submitted_form.username_value;
- submitted_form.form_data.fields[6].value.clear();
- submitted_form.form_data.fields[7].value.clear();
- submitted_form.preferred = true;
- EXPECT_TRUE(FormStructure(submitted_form.form_data).ShouldBeUploaded());
-
- form_manager()->ProvisionallySave(submitted_form);
-
- std::map<base::string16, autofill::FieldPropertiesMask>
- expected_field_properties = {
- {submitted_form.form_data.fields[0].name,
- FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.form_data.fields[1].name, 0},
- {submitted_form.form_data.fields[2].name, 0},
- {submitted_form.form_data.fields[3].name,
- FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.form_data.fields[4].name,
- FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.form_data.fields[5].name,
- FieldPropertiesFlags::KNOWN_VALUE},
- {submitted_form.form_data.fields[6].name, 0},
- {submitted_form.form_data.fields[7].name, 0}};
-
- // Only the detected username_element and password_element fields should have
- // a USERNAME and PASSWORD vote.
- std::map<base::string16, autofill::AutofillUploadContents::Field::VoteType>
- expected_vote_types = {
- {submitted_form.form_data.fields[0].name,
- autofill::AutofillUploadContents::Field::FIRST_USE},
- {submitted_form.form_data.fields[1].name,
- autofill::AutofillUploadContents::Field::NO_INFORMATION},
- {submitted_form.form_data.fields[2].name,
- autofill::AutofillUploadContents::Field::NO_INFORMATION},
- {submitted_form.form_data.fields[3].name,
- autofill::AutofillUploadContents::Field::FIRST_USE},
- {submitted_form.form_data.fields[4].name,
- autofill::AutofillUploadContents::Field::NO_INFORMATION},
- {submitted_form.form_data.fields[5].name,
- autofill::AutofillUploadContents::Field::NO_INFORMATION},
- {submitted_form.form_data.fields[6].name,
- autofill::AutofillUploadContents::Field::NO_INFORMATION},
- {submitted_form.form_data.fields[7].name,
- autofill::AutofillUploadContents::Field::NO_INFORMATION}};
-
- FieldTypeMap expected_votes = {
- {submitted_form.username_element, autofill::USERNAME},
- {submitted_form.form_data.fields[1].name, autofill::UNKNOWN_TYPE},
- {submitted_form.form_data.fields[2].name, autofill::UNKNOWN_TYPE},
- {submitted_form.password_element, autofill::PASSWORD},
- {submitted_form.form_data.fields[4].name, autofill::UNKNOWN_TYPE},
- {submitted_form.form_data.fields[5].name, autofill::UNKNOWN_TYPE},
- {submitted_form.form_data.fields[6].name, autofill::UNKNOWN_TYPE},
- {submitted_form.form_data.fields[7].name, autofill::UNKNOWN_TYPE}};
-
- // Unrelated vote.
- EXPECT_CALL(*client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(SignatureIsSameAs(*saved_match()), _, _, _, _,
- nullptr))
- .Times(1);
- // First login vote.
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(
- AllOf(SignatureIsSameAs(submitted_form),
- UploadedAutofillTypesAre(expected_votes),
- UploadedFieldPropertiesMasksAre(expected_field_properties),
- VoteTypesAre(expected_vote_types)),
- _,
- autofill::ServerFieldTypeSet(
- {autofill::USERNAME, autofill::PASSWORD}),
- _, true, nullptr));
-
- form_manager()->Save();
-}
+TEST_F(PasswordFormManagerTest, PasswordRevealedVote) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-TEST_F(PasswordFormManagerTest, UploadPasswordAttributesVote) {
- PasswordForm credentials = *observed_form();
- // Set FormData to enable crowdsourcing.
- credentials.form_data = saved_match()->form_data;
- FakeFormFetcher fetcher;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), credentials,
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- fetcher.NotifyFetchCompleted();
-
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("12345");
- form_manager.ProvisionallySave(credentials);
+ for (bool password_revealed : {false, true}) {
+ SCOPED_TRACE(testing::Message("password_revealed=") << password_revealed);
+ CreateFormManager(observed_form_);
+ fetcher_->NotifyFetchCompleted();
- EXPECT_CALL(
- *client()->mock_driver()->mock_autofill_download_manager(),
- StartUploadRequest(HasPasswordAttributesVote(true /* is_vote_expected */),
- _, _, _, _, nullptr));
- form_manager.Save();
-}
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
-TEST_F(PasswordFormManagerTest, PresaveGeneratedPassword_UnknownUsername) {
- // Checks whether the generated password is presaved with the captured
- // username. The username is new, so there will be no credentail override.
- SetNonFederatedAndNotifyFetchCompleted({saved_match()});
- PasswordForm credentials = *observed_form();
- credentials.username_value = ASCIIToUTF16("new_user");
- credentials.password_value = ASCIIToUTF16("generatated_password");
-
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Save(FormIgnoreDate(credentials), _, _));
- form_manager()->PresaveGeneratedPassword(credentials);
-}
+ if (password_revealed)
+ form_manager_->OnPasswordsRevealed();
-TEST_F(PasswordFormManagerTest, PresaveGeneratedPassword_KnownUsername) {
- // Checks whether the generated password is presaved with empty username if
- // there is already an entry with the captured username in the store.
- PasswordForm saved_form_without_username(*saved_match());
- saved_form_without_username.username_value.clear();
- SetNonFederatedAndNotifyFetchCompleted(
- {saved_match(), &saved_form_without_username});
- PasswordForm credentials = *observed_form();
- credentials.username_value = saved_match()->username_value;
- credentials.password_value = ASCIIToUTF16("generatated_password");
-
- PasswordForm credentials_without_username(credentials);
- credentials_without_username.username_value.clear();
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Save(FormIgnoreDate(credentials_without_username), _, _));
- form_manager()->PresaveGeneratedPassword(credentials);
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(PasswordsWereRevealed(password_revealed),
+ false, _, _, true, nullptr));
+ form_manager_->Save();
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
+ }
}
-TEST_F(PasswordFormManagerTest, PresaveGeneratedPassword_EmptyUsername) {
- // Checks whether the generated password is presaved even if the captured
- // username is empty.
- PasswordForm saved_form_without_username(*saved_match());
- saved_form_without_username.username_value.clear();
- SetNonFederatedAndNotifyFetchCompleted(
- {saved_match(), &saved_form_without_username});
- PasswordForm credentials = *observed_form();
- credentials.username_value.clear();
- credentials.password_value = ASCIIToUTF16("generatated_password");
-
- EXPECT_CALL(MockFormSaver::Get(form_manager()),
- Save(FormIgnoreDate(credentials), _, _));
- form_manager()->PresaveGeneratedPassword(credentials);
-}
+TEST_F(PasswordFormManagerTest, GenerationUploadOnNoInteraction) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
-TEST_F(PasswordFormManagerTest, MetricForManuallyTypedAndGeneratedPasswords) {
- for (bool is_generated_password : {false, true}) {
- SCOPED_TRACE(testing::Message("is_generated_password = ")
- << is_generated_password);
- fake_form_fetcher()->NotifyFetchCompleted();
-
- PasswordForm credentials(*observed_form());
- credentials.username_value = ASCIIToUTF16("test@gmail.com");
- credentials.preferred = true;
- if (is_generated_password) {
- credentials.password_value = ASCIIToUTF16("12345");
- form_manager()->PresaveGeneratedPassword(credentials);
+ for (bool generation_popup_shown : {false, true}) {
+ SCOPED_TRACE(testing::Message("generation_popup_shown=")
+ << generation_popup_shown);
+ CreateFormManager(observed_form_);
+ fetcher_->NotifyFetchCompleted();
+
+ if (generation_popup_shown) {
+ form_manager_->SetGenerationElement(ASCIIToUTF16("password"));
+ form_manager_->SetGenerationPopupWasShown(
+ true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
}
- form_manager()->ProvisionallySave(credentials);
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
- PasswordForm saved_result;
- base::HistogramTester histogram_tester;
- form_manager()->Save();
- histogram_tester.ExpectUniqueSample(
- "PasswordManager.NewlySavedPasswordIsGenerated", is_generated_password,
- 1);
+ EXPECT_CALL(
+ mock_autofill_download_manager_,
+ StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr))
+ .Times(generation_popup_shown ? 1 : 0);
+ form_manager_->OnNoInteraction(false /*is_update */);
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
}
}
-TEST_F(PasswordFormManagerTest, UserEventsForGeneration) {
- using GeneratedPasswordStatus =
- PasswordFormMetricsRecorder::GeneratedPasswordStatus;
-
- PasswordForm submitted_form(*observed_form());
- submitted_form.username_value = ASCIIToUTF16("username");
- submitted_form.password_value = ASCIIToUTF16("123456");
+TEST_F(PasswordFormManagerTest, GenerationUploadOnNeverClicked) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- { // User accepts a generated password.
- base::HistogramTester histogram_tester;
- {
- FakeFormFetcher fetcher;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- form_manager.PresaveGeneratedPassword(submitted_form);
- }
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.UserDecision",
- GeneratedPasswordStatus::kPasswordAccepted, 1);
- }
+ for (bool generation_popup_shown : {false, true}) {
+ SCOPED_TRACE(testing::Message("generation_popup_shown=")
+ << generation_popup_shown);
+ CreateFormManager(observed_form_);
+ fetcher_->NotifyFetchCompleted();
- { // User edits the generated password.
- base::HistogramTester histogram_tester;
- {
- FakeFormFetcher fetcher;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- form_manager.PresaveGeneratedPassword(submitted_form);
- submitted_form.password_value = ASCIIToUTF16("password123456");
- form_manager.PresaveGeneratedPassword(submitted_form);
+ if (generation_popup_shown) {
+ form_manager_->SetGenerationElement(ASCIIToUTF16("password"));
+ form_manager_->SetGenerationPopupWasShown(
+ true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
}
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.UserDecision",
- GeneratedPasswordStatus::kPasswordEdited, 1);
- }
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
- { // User clears the generated password.
- base::HistogramTester histogram_tester;
- {
- FakeFormFetcher fetcher;
- PasswordFormManager form_manager(
- password_manager(), client(), client()->driver(), *observed_form(),
- std::make_unique<NiceMock<MockFormSaver>>(), &fetcher);
- form_manager.Init(nullptr);
- form_manager.PresaveGeneratedPassword(submitted_form);
- submitted_form.password_value = ASCIIToUTF16("password123");
- form_manager.PresaveGeneratedPassword(submitted_form);
- form_manager.PasswordNoLongerGenerated();
- }
- histogram_tester.ExpectUniqueSample(
- "PasswordGeneration.UserDecision",
- GeneratedPasswordStatus::kPasswordDeleted, 1);
+ EXPECT_CALL(
+ mock_autofill_download_manager_,
+ StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr))
+ .Times(generation_popup_shown ? 1 : 0);
+ form_manager_->OnNeverClicked();
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
}
}
-TEST_F(PasswordFormManagerTest, ProvisionallySaveUpdatesUserAction) {
- // Setup existing matches.
- PasswordForm preferred_match = *saved_match();
+TEST_F(PasswordFormManagerTest, SaveHttpAuthNoHttpAuthStored) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- PasswordForm other_match = *saved_match();
- other_match.username_value = ASCIIToUTF16("other_username");
- other_match.password_value = ASCIIToUTF16("other_password");
- other_match.preferred = false;
+ for (bool html_credentials_saved : {false, true}) {
+ SCOPED_TRACE(testing::Message("html_credentials_saved=")
+ << html_credentials_saved);
+ PasswordForm http_auth_form = parsed_observed_form_;
+ http_auth_form.scheme = PasswordForm::Scheme::kBasic;
- PasswordForm psl_match = *psl_saved_match();
- psl_match.username_value = ASCIIToUTF16("psl_match_username");
+ // Check that no filling because no http auth credentials are stored.
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ EXPECT_CALL(client_, AutofillHttpAuth(_, _)).Times(0);
- SetNonFederatedAndNotifyFetchCompleted(
- {&preferred_match, &other_match, &psl_match});
-
- // Verify that provisionally saving the |preferred_match| results in the
- // correct user action.
- form_manager()->ProvisionallySave(preferred_match);
- EXPECT_EQ(UserAction::kNone,
- form_manager()->GetMetricsRecorder()->GetUserAction());
-
- // Verify that provisionally saving an |other_match| results in the
- // correct user action.
- form_manager()->ProvisionallySave(other_match);
- EXPECT_EQ(UserAction::kChoose,
- form_manager()->GetMetricsRecorder()->GetUserAction());
-
- // Verify that provisionally saving a |psl_match| results in the correct user
- // action.
- form_manager()->ProvisionallySave(psl_match);
- EXPECT_EQ(UserAction::kChoosePslMatch,
- form_manager()->GetMetricsRecorder()->GetUserAction());
-
- // Verify that provisionally saving a credential with a |new_password| results
- // in the correct user action.
- PasswordForm new_password;
- new_password.username_value = preferred_match.username_value;
- new_password.password_value = ASCIIToUTF16("new_password");
- form_manager()->ProvisionallySave(new_password);
- EXPECT_EQ(UserAction::kOverridePassword,
- form_manager()->GetMetricsRecorder()->GetUserAction());
-
- // Verify that provisionally saving a |new_credential| results in the correct
- // user action.
- PasswordForm new_credential;
- new_credential.username_value = ASCIIToUTF16("new_username");
- new_credential.password_value = ASCIIToUTF16("new_password");
- form_manager()->ProvisionallySave(new_credential);
- EXPECT_EQ(UserAction::kOverrideUsernameAndPassword,
- form_manager()->GetMetricsRecorder()->GetUserAction());
-
- // Verify that provisionally saving the |preferred_match| results in resetting
- // the user action.
- form_manager()->ProvisionallySave(preferred_match);
- EXPECT_EQ(UserAction::kNone,
- form_manager()->GetMetricsRecorder()->GetUserAction());
-
- // Verify that provisionally saving the |preferred_match| with filling on
- // account select results in the corresponding user action. Fill on account
- // select is simulated by pretending we are in incognito mode.
- EXPECT_CALL(*client(), IsIncognito).WillOnce(Return(true));
- SetNonFederatedAndNotifyFetchCompleted(
- {&preferred_match, &other_match, &psl_match});
+ CreateFormManagerForNonWebForm(http_auth_form);
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ std::vector<const PasswordForm*> saved_matches;
+ if (html_credentials_saved)
+ saved_matches.push_back(&saved_match_);
+ SetNonFederatedAndNotifyFetchCompleted(saved_matches);
+
+ base::string16 username = ASCIIToUTF16("user1");
+ base::string16 password = ASCIIToUTF16("pass1");
+ http_auth_form.username_value = username;
+ http_auth_form.password_value = password;
+
+ // Check that submitted credentials are saved.
+ ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthForm(http_auth_form));
+ EXPECT_TRUE(form_manager_->IsNewLogin());
- form_manager()->ProvisionallySave(preferred_match);
- EXPECT_EQ(UserAction::kChoose,
- form_manager()->GetMetricsRecorder()->GetUserAction());
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, _, _)).WillOnce(SaveArg<0>(&saved_form));
+ form_manager_->Save();
+
+ EXPECT_EQ(http_auth_form.signon_realm, saved_form.signon_realm);
+ EXPECT_EQ(username, saved_form.username_value);
+ EXPECT_EQ(password, saved_form.password_value);
+ }
}
+TEST_F(PasswordFormManagerTest, HTTPAuthAlreadySaved) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ PasswordForm http_auth_form = parsed_observed_form_;
+ http_auth_form.scheme = PasswordForm::Scheme::kBasic;
+
+ CreateFormManagerForNonWebForm(http_auth_form);
+
+ const base::string16 username = ASCIIToUTF16("user1");
+ const base::string16 password = ASCIIToUTF16("pass1");
+ http_auth_form.username_value = username;
+ http_auth_form.password_value = password;
+ EXPECT_CALL(client_, AutofillHttpAuth(http_auth_form, _)).Times(1);
+ SetNonFederatedAndNotifyFetchCompleted({&http_auth_form});
+
+ // Check that if known credentials are submitted, then |form_manager_| is not
+ // in state new login nor password overridden.
+ ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthForm(http_auth_form));
+ EXPECT_FALSE(form_manager_->IsNewLogin());
+ EXPECT_FALSE(form_manager_->IsPasswordUpdate());
+}
+
+TEST_F(PasswordFormManagerTest, HTTPAuthPasswordOverridden) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ PasswordForm http_auth_form = parsed_observed_form_;
+ http_auth_form.scheme = PasswordForm::Scheme::kBasic;
+
+ CreateFormManagerForNonWebForm(http_auth_form);
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ PasswordForm saved_http_auth_form = http_auth_form;
+ const base::string16 username = ASCIIToUTF16("user1");
+ const base::string16 password = ASCIIToUTF16("pass1");
+ saved_http_auth_form.username_value = username;
+ saved_http_auth_form.password_value = password;
+ EXPECT_CALL(client_, AutofillHttpAuth(saved_http_auth_form, _)).Times(1);
+ SetNonFederatedAndNotifyFetchCompleted({&saved_http_auth_form});
+
+ // Check that if new password is submitted, then |form_manager_| is in state
+ // password overridden.
+ PasswordForm submitted_http_auth_form = saved_http_auth_form;
+ base::string16 new_password = password + ASCIIToUTF16("1");
+ submitted_http_auth_form.password_value = new_password;
+ ASSERT_TRUE(
+ form_manager_->ProvisionallySaveHttpAuthForm(submitted_http_auth_form));
+ EXPECT_FALSE(form_manager_->IsNewLogin());
+ EXPECT_TRUE(form_manager_->IsPasswordUpdate());
+
+ // Check that the password is updated in the stored credential.
+ PasswordForm updated_form;
+ EXPECT_CALL(form_saver,
+ Update(_, ElementsAre(Pointee(saved_http_auth_form)), password))
+ .WillOnce(SaveArg<0>(&updated_form));
+
+ form_manager_->Save();
+
+ EXPECT_TRUE(
+ ArePasswordFormUniqueKeysEqual(saved_http_auth_form, updated_form));
+ EXPECT_EQ(new_password, updated_form.password_value);
+}
+
+TEST_F(PasswordFormManagerTest, BlacklistHttpAuthCredentials) {
+ PasswordForm http_auth_form = parsed_observed_form_;
+ http_auth_form.signon_realm += "my-auth-realm";
+ http_auth_form.scheme = PasswordForm::Scheme::kBasic;
+
+ CreateFormManagerForNonWebForm(http_auth_form);
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ // Simulate that the user submits http auth credentials.
+ http_auth_form.username_value = ASCIIToUTF16("user1");
+ http_auth_form.password_value = ASCIIToUTF16("pass1");
+ ASSERT_TRUE(form_manager_->ProvisionallySaveHttpAuthForm(http_auth_form));
+
+ // Simulate that the user clicks never.
+ PasswordForm blacklisted_form;
+ EXPECT_CALL(form_saver,
+ PermanentlyBlacklist(PasswordStore::FormDigest(http_auth_form)));
+ form_manager_->OnNeverClicked();
+}
+
+#if defined(OS_IOS)
+TEST_F(PasswordFormManagerTest, iOSPresavedGeneratedPassword) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ FormData form_to_presave = observed_form_;
+ const base::string16 typed_username = ASCIIToUTF16("user1");
+ FormFieldData& username_field = form_to_presave.fields[kUsernameFieldIndex];
+ FormFieldData& password_field = form_to_presave.fields[kPasswordFieldIndex];
+ username_field.value = typed_username;
+ password_field.value = ASCIIToUTF16("not_password");
+ // Use |generated_password| different from value in field to test that the
+ // generated password is saved.
+ const base::string16 generated_password = ASCIIToUTF16("gen_pw");
+ // Use different |unique_id| and |name| to test that |unique_id| is taken.
+ password_field.unique_id = password_field.name + ASCIIToUTF16("1");
+ const base::string16 generation_element = password_field.unique_id;
+
+ PasswordForm saved_form;
+ EXPECT_CALL(form_saver, Save(_, IsEmpty(), base::string16()))
+ .WillOnce(SaveArg<0>(&saved_form));
+ form_manager_->PresaveGeneratedPassword(
+ &driver_, form_to_presave, generated_password, generation_element);
+ EXPECT_EQ(generated_password, saved_form.password_value);
+
+ Mock::VerifyAndClearExpectations(&form_saver);
+
+ const base::string16 changed_password =
+ generated_password + ASCIIToUTF16("1");
+ EXPECT_CALL(form_saver, UpdateReplace(_, _, base::string16(), _))
+ .WillOnce(SaveArg<0>(&saved_form));
+
+ form_manager_->UpdateGeneratedPasswordOnUserInput(
+ form_to_presave.name, generation_element, changed_password);
+ EXPECT_EQ(username_field.value, saved_form.username_value);
+ EXPECT_EQ(changed_password, saved_form.password_value);
+}
+
+TEST_F(PasswordFormManagerTest, UpdateGeneratedPasswordBeforePresaving) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->NotifyFetchCompleted();
+ MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
+
+ FormData form_to_presave = observed_form_;
+ const base::string16 generation_element =
+ form_to_presave.fields[kPasswordFieldIndex].unique_id;
+ const base::string16 generation_field_value = ASCIIToUTF16("some_password");
+
+ // Check that nothing is saved on changing password, in case when there was no
+ // pre-saving.
+ EXPECT_CALL(form_saver, Save(_, _, _)).Times(0);
+ form_manager_->UpdateGeneratedPasswordOnUserInput(
+ form_to_presave.name, generation_element, generation_field_value);
+}
+
+#endif // defined(OS_IOS)
+
+} // namespace
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_form_metrics_recorder.cc b/chromium/components/password_manager/core/browser/password_form_metrics_recorder.cc
index ac2513429f0..a40e214b825 100644
--- a/chromium/components/password_manager/core/browser/password_form_metrics_recorder.cc
+++ b/chromium/components/password_manager/core/browser/password_form_metrics_recorder.cc
@@ -267,6 +267,15 @@ PasswordFormMetricsRecorder::~PasswordFormMetricsRecorder() {
}
}
+ if (user_typed_password_on_chrome_sign_in_page_ ||
+ password_hash_saved_on_chrome_sing_in_page_) {
+ auto value = password_hash_saved_on_chrome_sing_in_page_
+ ? ChromeSignInPageHashSaved::kHashSaved
+ : ChromeSignInPageHashSaved::kPasswordTypedHashNotSaved;
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.ChromeSignInPageHashSaved",
+ value);
+ }
+
ukm_entry_builder_.Record(ukm::UkmRecorder::Get());
}
diff --git a/chromium/components/password_manager/core/browser/password_form_metrics_recorder.h b/chromium/components/password_manager/core/browser/password_form_metrics_recorder.h
index 1bb1c461e59..4608e74731f 100644
--- a/chromium/components/password_manager/core/browser/password_form_metrics_recorder.h
+++ b/chromium/components/password_manager/core/browser/password_form_metrics_recorder.h
@@ -260,6 +260,13 @@ class PasswordFormMetricsRecorder
kMaxValue = kNoSavedCredentialsAndBlacklistedBySmartBubble,
};
+ // Records whether a password hash was saved or not on Chrome sign-in page.
+ enum class ChromeSignInPageHashSaved {
+ kPasswordTypedHashNotSaved = 0,
+ kHashSaved = 1,
+ kMaxValue = kHashSaved,
+ };
+
// The maximum number of combinations of the ManagerAction, UserAction and
// SubmitResult enums.
// This is used when recording the actions taken by the form in UMA.
@@ -386,6 +393,14 @@ class PasswordFormMetricsRecorder
bool is_blacklisted,
const std::vector<InteractionsStats>& interactions_stats);
+ void set_user_typed_password_on_chrome_sign_in_page() {
+ user_typed_password_on_chrome_sign_in_page_ = true;
+ }
+
+ void set_password_hash_saved_on_chrome_sing_in_page() {
+ password_hash_saved_on_chrome_sing_in_page_ = true;
+ }
+
private:
friend class base::RefCounted<PasswordFormMetricsRecorder>;
@@ -469,6 +484,9 @@ class PasswordFormMetricsRecorder
bool recorded_wait_for_username_reason_ = false;
+ bool user_typed_password_on_chrome_sign_in_page_ = false;
+ bool password_hash_saved_on_chrome_sing_in_page_ = false;
+
base::Optional<FillingAssistance> filling_assistance_;
DISALLOW_COPY_AND_ASSIGN(PasswordFormMetricsRecorder);
diff --git a/chromium/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc b/chromium/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
index ce979a3aeec..295037e4ee1 100644
--- a/chromium/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc
@@ -10,7 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
@@ -69,7 +69,7 @@ void ExpectUkmValueCount(ukm::TestUkmRecorder* test_ukm_recorder,
// Test the metrics recorded around password generation and the user's
// interaction with the offer to generate passwords.
TEST(PasswordFormMetricsRecorder, Generation) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
static constexpr struct {
bool generation_available;
bool has_generated_password;
@@ -200,7 +200,7 @@ TEST(PasswordFormMetricsRecorder, Generation) {
// Test the recording of metrics around manager_action, user_action, and
// submit_result.
TEST(PasswordFormMetricsRecorder, Actions) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
static constexpr struct {
// Stimuli:
bool is_main_frame_secure;
@@ -297,7 +297,7 @@ TEST(PasswordFormMetricsRecorder, Actions) {
}
TEST(PasswordFormMetricsRecorder, SubmittedFormType) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
static constexpr struct {
// Stimuli:
bool is_main_frame_secure;
@@ -356,7 +356,7 @@ TEST(PasswordFormMetricsRecorder, SubmittedFormType) {
}
TEST(PasswordFormMetricsRecorder, RecordPasswordBubbleShown) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
using Trigger = PasswordFormMetricsRecorder::BubbleTrigger;
static constexpr struct {
// Stimuli:
@@ -451,7 +451,7 @@ TEST(PasswordFormMetricsRecorder, RecordPasswordBubbleShown) {
}
TEST(PasswordFormMetricsRecorder, RecordUIDismissalReason) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
static constexpr struct {
// Stimuli:
metrics_util::UIDisplayDisposition display_disposition;
@@ -503,7 +503,7 @@ TEST(PasswordFormMetricsRecorder, RecordUIDismissalReason) {
// Verify that it is ok to open and close the password bubble more than once
// and still get accurate metrics.
TEST(PasswordFormMetricsRecorder, SequencesOfBubbles) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
using BubbleDismissalReason =
PasswordFormMetricsRecorder::BubbleDismissalReason;
using BubbleTrigger = PasswordFormMetricsRecorder::BubbleTrigger;
@@ -550,7 +550,7 @@ TEST(PasswordFormMetricsRecorder, SequencesOfBubbles) {
// Verify that one-time actions are only recorded once per life-cycle of a
// PasswordFormMetricsRecorder.
TEST(PasswordFormMetricsRecorder, RecordDetailedUserAction) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
using Action = PasswordFormMetricsRecorder::DetailedUserAction;
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
{
@@ -576,7 +576,7 @@ TEST(PasswordFormMetricsRecorder, RecordDetailedUserAction) {
// Verify that the the mapping is correct and that metrics are actually
// recorded.
TEST(PasswordFormMetricsRecorder, RecordShowManualFallbackForSaving) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
struct {
bool has_generated_password;
bool is_update;
@@ -606,7 +606,7 @@ TEST(PasswordFormMetricsRecorder, RecordShowManualFallbackForSaving) {
// Verify that no 0 is recorded if now fallback icon is shown.
TEST(PasswordFormMetricsRecorder, NoRecordShowManualFallbackForSaving) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
{
auto recorder = CreatePasswordFormMetricsRecorder(
@@ -621,7 +621,7 @@ TEST(PasswordFormMetricsRecorder, NoRecordShowManualFallbackForSaving) {
// Verify that only the latest value is recorded
TEST(PasswordFormMetricsRecorder, RecordShowManualFallbackForSavingLatestOnly) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
{
auto recorder = CreatePasswordFormMetricsRecorder(
@@ -736,7 +736,7 @@ void CheckFillingAssistanceTestCase(
<< ", is_main_frame_secure: " << std::boolalpha
<< is_main_frame_secure);
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::HistogramTester histogram_tester;
FormData form_data = ConvertToFormData(test_case.fields);
diff --git a/chromium/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc b/chromium/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc
index f2bf07aa6ef..b7851c0477e 100644
--- a/chromium/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc
@@ -12,7 +12,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/form_structure.h"
@@ -182,7 +182,7 @@ class PasswordGenerationFrameHelperTest : public testing::Test {
return GetGenerationHelper()->IsGenerationEnabled(true);
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<MockPasswordManagerClient> client_;
};
diff --git a/chromium/components/password_manager/core/browser/password_generation_state.cc b/chromium/components/password_manager/core/browser/password_generation_state.cc
index cfedfda3c77..23d927f5e9f 100644
--- a/chromium/components/password_manager/core/browser/password_generation_state.cc
+++ b/chromium/components/password_manager/core/browser/password_generation_state.cc
@@ -271,6 +271,7 @@ void PasswordGenerationState::CommitGeneratedPassword(
const base::string16& old_password) {
DCHECK(presaved_);
generated.preferred = true;
+ generated.date_last_used = clock_->Now();
generated.date_created = clock_->Now();
form_saver_->UpdateReplace(generated, matches, old_password,
presaved_.value() /* old_primary_key */);
diff --git a/chromium/components/password_manager/core/browser/password_generation_state_unittest.cc b/chromium/components/password_manager/core/browser/password_generation_state_unittest.cc
index dd47e53216c..68d0a153256 100644
--- a/chromium/components/password_manager/core/browser/password_generation_state_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_generation_state_unittest.cc
@@ -8,8 +8,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/fake_form_fetcher.h"
#include "components/password_manager/core/browser/form_saver_impl.h"
#include "components/password_manager/core/browser/mock_password_store.h"
@@ -133,7 +133,7 @@ class PasswordGenerationStateTest : public testing::Test {
private:
// For the MockPasswordStore.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<MockPasswordStore> mock_store_;
// Test with the real form saver for better robustness.
FormSaverImpl form_saver_;
@@ -387,6 +387,7 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenSaveAsNew) {
pending.username_value = ASCIIToUTF16("edited_username");
PasswordForm generated_with_date = pending;
generated_with_date.date_created = base::Time::FromTimeT(kTime);
+ generated_with_date.date_last_used = base::Time::FromTimeT(kTime);
EXPECT_CALL(store(), UpdateLoginWithPrimaryKey(generated_with_date,
FormHasUniqueKey(generated)));
state().CommitGeneratedPassword(pending, {} /* matches */,
@@ -428,6 +429,7 @@ TEST_F(PasswordGenerationStateTest, PresaveGeneratedPassword_ThenUpdate) {
generated.username_value = ASCIIToUTF16("username");
PasswordForm generated_with_date = generated;
generated_with_date.date_created = base::Time::FromTimeT(kTime);
+ generated_with_date.date_last_used = base::Time::FromTimeT(kTime);
EXPECT_CALL(store(),
UpdateLoginWithPrimaryKey(generated_with_date,
diff --git a/chromium/components/password_manager/core/browser/password_manager.cc b/chromium/components/password_manager/core/browser/password_manager.cc
index 253c2015bf0..0e1463bc156 100644
--- a/chromium/components/password_manager/core/browser/password_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_manager.cc
@@ -25,13 +25,13 @@
#include "components/autofill/core/common/save_password_progress_logger.h"
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
#include "components/password_manager/core/browser/form_saver_impl.h"
-#include "components/password_manager/core/browser/new_password_form_manager.h"
#include "components/password_manager/core/browser/password_autofill_manager.h"
#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_generation_frame_helper.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
@@ -45,18 +45,17 @@
#endif
using autofill::FormData;
+using autofill::FormStructure;
using autofill::PasswordForm;
using autofill::mojom::PasswordFormFieldPredictionType;
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
-using password_manager::metrics_util::SyncPasswordHashChange;
+using password_manager::metrics_util::GaiaPasswordHashChange;
#endif // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
namespace password_manager {
namespace {
-const char kSpdyProxyRealm[] = "/SpdyProxy";
-
// Shorten the name to spare line breaks. The code provides enough context
// already.
using Logger = autofill::SavePasswordProgressLogger;
@@ -113,123 +112,11 @@ bool IsPasswordFormReappeared(const PasswordForm& observed_form,
return false;
}
-bool IsSignupForm(const PasswordForm& form) {
- return !form.new_password_element.empty() && form.password_element.empty();
-}
-
-// Tries to find if at least one of the values from |server_field_predictions|
-// can be converted from AutofillQueryResponseContents::Field::FieldPrediction
-// to a PasswordFormFieldPredictionType stored in |type|. Returns true if the
-// conversion was made.
-bool ServerPredictionsToPasswordFormPrediction(
- std::vector<autofill::AutofillQueryResponseContents::Field::FieldPrediction>
- server_field_predictions,
- PasswordFormFieldPredictionType* type) {
- for (auto const& server_field_prediction : server_field_predictions) {
- switch (server_field_prediction.type()) {
- case autofill::USERNAME:
- case autofill::USERNAME_AND_EMAIL_ADDRESS:
- *type = PasswordFormFieldPredictionType::kUsername;
- return true;
-
- case autofill::PASSWORD:
- *type = PasswordFormFieldPredictionType::kCurrentPassword;
- return true;
-
- case autofill::ACCOUNT_CREATION_PASSWORD:
- *type = PasswordFormFieldPredictionType::kNewPassword;
- return true;
-
- default:
- break;
- }
- }
- return false;
-}
-
-// Returns true if the |field_type| is known to be possibly
-// misinterpreted as a password by the Password Manager.
-bool IsPredictedTypeNotPasswordPrediction(
- autofill::ServerFieldType field_type) {
- return field_type == autofill::CREDIT_CARD_NUMBER ||
- field_type == autofill::CREDIT_CARD_VERIFICATION_CODE ||
- field_type == autofill::NOT_PASSWORD;
-}
-
bool AreAllFieldsEmpty(const PasswordForm& form) {
return form.username_value.empty() && form.password_value.empty() &&
form.new_password_value.empty();
}
-// Finds the matched form manager for |form| in |pending_login_managers|.
-PasswordFormManager* FindMatchedManager(
- const PasswordForm& form,
- const std::vector<std::unique_ptr<PasswordFormManager>>&
- pending_login_managers,
- const password_manager::PasswordManagerDriver* driver,
- BrowserSavePasswordProgressLogger* logger) {
- auto matched_manager_it = pending_login_managers.end();
- PasswordFormManager::MatchResultMask current_match_result =
- PasswordFormManager::RESULT_NO_MATCH;
- // Below, "matching" is in DoesManage-sense and "not ready" in the sense of
- // FormFetcher being ready. We keep track of such PasswordFormManager
- // instances for UMA.
- for (auto iter = pending_login_managers.begin();
- iter != pending_login_managers.end(); ++iter) {
- PasswordFormManager::MatchResultMask result =
- (*iter)->DoesManage(form, driver);
-
- if (result == PasswordFormManager::RESULT_COMPLETE_MATCH) {
- // If we find a manager that exactly matches the submitted form including
- // the action URL, exit the loop.
- if (logger)
- logger->LogMessage(Logger::STRING_EXACT_MATCH);
- matched_manager_it = iter;
- break;
- }
-
- if (result > current_match_result) {
- current_match_result = result;
- matched_manager_it = iter;
-
- if (logger) {
- if (result == (PasswordFormManager::RESULT_COMPLETE_MATCH &
- ~PasswordFormManager::RESULT_ACTION_MATCH))
- logger->LogMessage(Logger::STRING_MATCH_WITHOUT_ACTION);
- if (IsSignupForm(form))
- logger->LogMessage(Logger::STRING_ORIGINS_MATCH);
- }
- }
- }
-
- return matched_manager_it == pending_login_managers.end()
- ? nullptr
- : matched_manager_it->get();
-}
-
-std::unique_ptr<PasswordFormManager> FindAndCloneMatchedPasswordFormManager(
- const PasswordForm& password_form,
- const std::vector<std::unique_ptr<PasswordFormManager>>&
- pending_login_managers,
- const password_manager::PasswordManagerDriver* driver) {
- PasswordFormManager* matched_manager = FindMatchedManager(
- password_form, pending_login_managers, driver, nullptr);
- if (!matched_manager)
- return nullptr;
- // TODO(crbug.com/741537): Process manual saving request even if there is
- // still no response from the store.
- if (matched_manager->GetFormFetcher()->GetState() ==
- FormFetcher::State::WAITING) {
- return nullptr;
- }
-
- std::unique_ptr<PasswordFormManager> manager = matched_manager->Clone();
- PasswordForm form(password_form);
- form.preferred = true;
- manager->ProvisionallySave(form);
- return manager;
-}
-
// Returns true if the user needs to be prompted before a password can be
// saved (instead of automatically saving the password), based on inspecting
// the state of |manager|.
@@ -263,9 +150,9 @@ bool IsThereVisiblePasswordField(const FormData& form) {
}
// Finds the matched form manager for |form| in |form_managers|.
-NewPasswordFormManager* FindMatchedManager(
+PasswordFormManager* FindMatchedManager(
const FormData& form,
- const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers,
+ const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers,
const PasswordManagerDriver* driver) {
for (const auto& form_manager : form_managers) {
if (form_manager->DoesManage(form, driver))
@@ -275,9 +162,9 @@ NewPasswordFormManager* FindMatchedManager(
}
// Finds the matched form manager with id |form_renderer_id| in |form_managers|.
-NewPasswordFormManager* FindMatchedManagerByRendererId(
+PasswordFormManager* FindMatchedManagerByRendererId(
uint32_t form_renderer_id,
- const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers,
+ const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers,
const PasswordManagerDriver* driver) {
for (const auto& form_manager : form_managers) {
if (form_manager->DoesManageAccordingToRendererId(form_renderer_id, driver))
@@ -286,69 +173,25 @@ NewPasswordFormManager* FindMatchedManagerByRendererId(
return nullptr;
}
-// Records the difference between how |old_manager| and |new_manager| understood
-// the pending credentials.
-void RecordParsingOnSavingDifference(
- const PasswordFormManagerInterface& old_manager,
- const PasswordFormManagerInterface& new_manager,
- PasswordFormMetricsRecorder* metrics_recorder) {
- const PasswordForm& old_form = old_manager.GetPendingCredentials();
- const PasswordForm& new_form = new_manager.GetPendingCredentials();
- uint64_t result = 0;
-
- if (old_form.username_element != new_form.username_element ||
- old_form.username_value != new_form.username_value ||
- old_form.password_element != new_form.password_element ||
- old_form.password_value != new_form.password_value) {
- result |= static_cast<int>(
- PasswordFormMetricsRecorder::ParsingOnSavingDifference::kFields);
- }
- if (old_form.signon_realm != new_form.signon_realm) {
- result |= static_cast<int>(
- PasswordFormMetricsRecorder::ParsingOnSavingDifference::kSignonRealm);
- }
- if (old_manager.IsNewLogin() != new_manager.IsNewLogin()) {
- result |= static_cast<int>(PasswordFormMetricsRecorder::
- ParsingOnSavingDifference::kNewLoginStatus);
- }
- if (old_manager.HasGeneratedPassword() !=
- new_manager.HasGeneratedPassword()) {
- result |= static_cast<int>(
- PasswordFormMetricsRecorder::ParsingOnSavingDifference::kGenerated);
+bool HasSingleUsernameVote(const FormStructure& form) {
+ for (const auto& field : form) {
+ if (field->server_type() == autofill::SINGLE_USERNAME)
+ return true;
}
-
- metrics_recorder->RecordParsingOnSavingDifference(result);
-}
-
-bool IsNewFormParsingForFillingEnabled() {
-#if defined(OS_IOS)
- return true;
-#else
- return base::FeatureList::IsEnabled(features::kNewPasswordFormParsing);
-#endif
-}
-
-bool IsNewFormParsingForSavingEnabled() {
-#if defined(OS_IOS)
- return true;
-#else
- return base::FeatureList::IsEnabled(
- features::kNewPasswordFormParsingForSaving) &&
- base::FeatureList::IsEnabled(features::kNewPasswordFormParsing);
-#endif
+ return false;
}
-// Returns true if it is turned off using PasswordFormManager in
-// PasswordManager.
-bool IsOnlyNewParserEnabled() {
-#if defined(OS_IOS)
- return true;
-#else
- return base::FeatureList::IsEnabled(
- features::kNewPasswordFormParsingForSaving) &&
- base::FeatureList::IsEnabled(features::kNewPasswordFormParsing) &&
- base::FeatureList::IsEnabled(features::kOnlyNewParser);
-#endif
+// Returns true if at least one of the fields in |form| has a prediction to be a
+// new-password related field.
+// corresponds to a field for creating or changing a password.
+bool HasNewPasswordVote(const FormStructure& form) {
+ for (const auto& field : form) {
+ if (field->server_type() == autofill::ACCOUNT_CREATION_PASSWORD ||
+ field->server_type() == autofill::NEW_PASSWORD) {
+ return true;
+ }
+ }
+ return false;
}
} // namespace
@@ -374,6 +217,9 @@ void PasswordManager::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
registry->RegisterDoublePref(prefs::kLastTimeObsoleteHttpCredentialsRemoved,
0.0);
+ registry->RegisterIntegerPref(
+ prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(metrics_util::OnboardingState::kDoNotShow));
#if defined(OS_MACOSX)
registry->RegisterIntegerPref(prefs::kKeychainMigrationStatus,
@@ -381,6 +227,9 @@ void PasswordManager::RegisterProfilePrefs(
#endif
registry->RegisterListPref(prefs::kPasswordHashDataList,
PrefRegistry::NO_REGISTRATION_FLAGS);
+ registry->RegisterBooleanPref(
+ prefs::kPasswordLeakDetectionEnabled, true,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
}
// static
@@ -396,39 +245,30 @@ void PasswordManager::RegisterLocalPrefs(PrefRegistrySimple* registry) {
}
PasswordManager::PasswordManager(PasswordManagerClient* client)
- : client_(client) {
+ : client_(client)
+#if !defined(OS_IOS)
+ ,
+ leak_delegate_(client)
+#endif // !defined(OS_IOS)
+{
DCHECK(client_);
}
PasswordManager::~PasswordManager() = default;
-void PasswordManager::GenerationAvailableForForm(const PasswordForm& form) {
- DCHECK(client_->IsSavingAndFillingEnabled(form.origin));
-
- PasswordFormManager* form_manager = GetMatchingPendingManager(form);
- if (form_manager) {
- form_manager->MarkGenerationAvailable();
- return;
- }
-}
-
void PasswordManager::OnGeneratedPasswordAccepted(
PasswordManagerDriver* driver,
- const autofill::FormData& form_data,
+ const FormData& form_data,
uint32_t generation_element_id,
const base::string16& password) {
- if (IsNewFormParsingForSavingEnabled()) {
- NewPasswordFormManager* manager = GetMatchedManager(driver, form_data);
- if (manager) {
- manager->OnGeneratedPasswordAccepted(form_data, generation_element_id,
- password);
- } else {
- // OnPresaveGeneratedPassword records the histogram in all other cases.
- UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager",
- true);
- }
+ PasswordFormManager* manager = GetMatchedManager(driver, form_data);
+ if (manager) {
+ manager->OnGeneratedPasswordAccepted(form_data, generation_element_id,
+ password);
} else {
- driver->GeneratedPasswordAccepted(password);
+ // OnPresaveGeneratedPassword records the histogram in all other cases.
+ UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager",
+ true);
}
}
@@ -462,97 +302,21 @@ void PasswordManager::SetGenerationElementAndReasonForForm(
if (form_manager) {
form_manager->SetGenerationElement(generation_element);
form_manager->SetGenerationPopupWasShown(true, is_manually_triggered);
- return;
- }
-
- // If there is no corresponding PasswordFormManager, we create one. This is
- // not the common case, and should only happen when there is a bug in our
- // ability to detect forms. No matched |NewPasswordFormManager| is unlikely.
- if (!IsNewFormParsingForSavingEnabled()) {
- auto manager = std::make_unique<PasswordFormManager>(
- this, client_, driver->AsWeakPtr(), form,
- std::make_unique<FormSaverImpl>(client_->GetPasswordStore()), nullptr);
- manager->Init(nullptr);
- pending_login_managers_.push_back(std::move(manager));
}
}
-void PasswordManager::ProvisionallySavePassword(
- const PasswordForm& form,
- const PasswordManagerDriver* driver) {
- if (IsOnlyNewParserEnabled())
- return;
-
- // If the form was declined by some heuristics, don't show automatic bubble
- // for it, only fallback saving should be available.
- if (form.only_for_fallback)
- return;
-
+void PasswordManager::DidNavigateMainFrame(bool form_may_be_submitted) {
std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
if (password_manager_util::IsLoggingActive(client_)) {
logger.reset(
new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
- logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD);
- logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM,
- form);
- }
-
- if (!client_->IsSavingAndFillingEnabled(form.origin)) {
- RecordProvisionalSaveFailure(
- PasswordManagerMetricsRecorder::SAVING_DISABLED, form.origin,
- logger.get());
- return;
- }
-
- // No password value to save? Then don't.
- if (PasswordFormManager::PasswordToSave(form).first.empty()) {
- RecordProvisionalSaveFailure(PasswordManagerMetricsRecorder::EMPTY_PASSWORD,
- form.origin, logger.get());
- return;
- }
-
- if (ShouldBlockPasswordForSameOriginButDifferentScheme(form.origin)) {
- RecordProvisionalSaveFailure(
- PasswordManagerMetricsRecorder::SAVING_ON_HTTP_AFTER_HTTPS, form.origin,
- logger.get());
- return;
+ logger->LogBoolean(Logger::STRING_DID_NAVIGATE_MAIN_FRAME,
+ form_may_be_submitted);
}
- PasswordFormManager* matched_manager =
- FindMatchedManager(form, pending_login_managers_, driver, logger.get());
-
- // If we didn't find a manager, this means a form was submitted without
- // first loading the page containing the form. Don't offer to save
- // passwords in this case.
- auto availability =
- matched_manager
- ? PasswordManagerMetricsRecorder::FormManagerAvailable::kSuccess
- : PasswordManagerMetricsRecorder::FormManagerAvailable::
- kMissingProvisionallySave;
- if (client_ && client_->GetMetricsRecorder())
- client_->GetMetricsRecorder()->RecordFormManagerAvailable(availability);
- if (!matched_manager) {
- RecordProvisionalSaveFailure(
- PasswordManagerMetricsRecorder::NO_MATCHING_FORM, form.origin,
- logger.get());
- return;
- }
- matched_manager->SaveSubmittedFormTypeForMetrics(form);
-
- ProvisionallySaveManager(form, matched_manager, logger.get());
-
- // Cache the user-visible URL (i.e., the one seen in the omnibox). Once the
- // post-submit navigation concludes, we compare the landing URL against the
- // cached and report the difference through UMA.
- main_frame_url_ = client_->GetMainFrameURL();
-
- ReportSubmittedFormFrameMetric(driver, form);
-}
-
-void PasswordManager::DidNavigateMainFrame(bool form_may_be_submitted) {
- pending_login_managers_.clear();
-
if (client_->IsNewTabPage()) {
+ if (logger)
+ logger->LogMessage(Logger::STRING_NAVIGATION_NTP);
// On a successful Chrome sign-in the page navigates to the new tab page
// (ntp). OnPasswordFormsRendered is not called on ntp. That is why the
// standard flow for saving hash does not work. Save a password hash now
@@ -560,11 +324,11 @@ void PasswordManager::DidNavigateMainFrame(bool form_may_be_submitted) {
PasswordFormManagerInterface* manager = GetSubmittedManager();
if (manager && manager->GetSubmittedForm()
->form_data.is_gaia_with_skip_save_password_form) {
- MaybeSavePasswordHash(*manager);
+ MaybeSavePasswordHash(manager);
}
}
- for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) {
+ for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) {
if (form_may_be_submitted && manager->is_submitted()) {
owned_submitted_form_manager_ = std::move(manager);
break;
@@ -580,9 +344,6 @@ void PasswordManager::UpdateFormManagers() {
for (const auto& form_manager : form_managers_)
form_managers.push_back(form_manager.get());
- for (const auto& form_manager : pending_login_managers_)
- form_managers.push_back(form_manager.get());
-
// Get the fetchers and all the drivers.
std::vector<FormFetcher*> fetchers;
std::vector<PasswordManagerDriver*> drivers;
@@ -616,25 +377,20 @@ void PasswordManager::UpdateFormManagers() {
}
void PasswordManager::DropFormManagers() {
- pending_login_managers_.clear();
form_managers_.clear();
owned_submitted_form_manager_.reset();
- provisional_save_manager_.reset();
all_visible_forms_.clear();
predictions_.clear();
}
bool PasswordManager::IsPasswordFieldDetectedOnPage() {
- return !pending_login_managers_.empty() || !form_managers_.empty();
+ return !form_managers_.empty();
}
void PasswordManager::OnPasswordFormSubmitted(
password_manager::PasswordManagerDriver* driver,
const PasswordForm& password_form) {
- if (IsNewFormParsingForSavingEnabled())
- ProvisionallySaveForm(password_form.form_data, driver, false);
-
- ProvisionallySavePassword(password_form, driver);
+ ProvisionallySaveForm(password_form.form_data, driver, false);
}
@@ -656,11 +412,7 @@ void PasswordManager::OnPasswordFormSubmittedNoChecks(
return;
}
- if (IsNewFormParsingForSavingEnabled()) {
- ProvisionallySaveForm(password_form.form_data, driver, false);
- }
-
- ProvisionallySavePassword(password_form, driver);
+ ProvisionallySaveForm(password_form.form_data, driver, false);
if (IsAutomaticSavePromptAvailable())
OnLoginSuccessful();
@@ -677,22 +429,22 @@ void PasswordManager::OnUserModifiedNonPasswordField(
void PasswordManager::ShowManualFallbackForSaving(
password_manager::PasswordManagerDriver* driver,
const PasswordForm& password_form) {
+ PasswordFormManager* manager =
+ ProvisionallySaveForm(password_form.form_data, driver, true);
+
+ if (manager && password_form.form_data.is_gaia_with_skip_save_password_form) {
+ manager->GetMetricsRecorder()
+ ->set_user_typed_password_on_chrome_sign_in_page();
+ }
+
if (!client_->GetPasswordStore()->IsAbleToSavePasswords() ||
!client_->IsSavingAndFillingEnabled(password_form.origin) ||
ShouldBlockPasswordForSameOriginButDifferentScheme(
password_form.origin) ||
- !client_->GetStoreResultFilter()->ShouldSave(password_form))
+ !client_->GetStoreResultFilter()->ShouldSave(password_form)) {
return;
-
- std::unique_ptr<PasswordFormManagerInterface> manager;
- if (IsNewFormParsingForSavingEnabled()) {
- NewPasswordFormManager* matched_manager =
- ProvisionallySaveForm(password_form.form_data, driver, true);
- manager = matched_manager ? matched_manager->Clone() : nullptr;
- } else {
- manager = FindAndCloneMatchedPasswordFormManager(
- password_form, pending_login_managers_, driver);
}
+
auto availability =
manager ? PasswordManagerMetricsRecorder::FormManagerAvailable::kSuccess
: PasswordManagerMetricsRecorder::FormManagerAvailable::
@@ -708,7 +460,7 @@ void PasswordManager::ShowManualFallbackForSaving(
bool is_update = manager->IsPasswordUpdate();
manager->GetMetricsRecorder()->RecordShowManualFallbackForSaving(
has_generated_password, is_update);
- client_->ShowManualFallbackForSaving(std::move(manager),
+ client_->ShowManualFallbackForSaving(manager->Clone(),
has_generated_password, is_update);
} else {
HideManualFallbackForSaving();
@@ -742,8 +494,7 @@ void PasswordManager::CreatePendingLoginManagers(
logger->LogMessage(Logger::STRING_CREATE_LOGIN_MANAGERS_METHOD);
}
- if (IsNewFormParsingForFillingEnabled())
- CreateFormManagers(driver, forms);
+ CreateFormManagers(driver, forms);
// Record whether or not this top-level URL has at least one password field.
client_->AnnotateNavigationEntry(!forms.empty());
@@ -771,54 +522,6 @@ void PasswordManager::CreatePendingLoginManagers(
"PasswordManager.CertificateErrorsWhileSeeingForms", cert_error,
metrics_util::CertificateError::COUNT);
}
-
- if (logger) {
- logger->LogNumber(Logger::STRING_OLD_NUMBER_LOGIN_MANAGERS,
- pending_login_managers_.size());
- }
-
- if (IsOnlyNewParserEnabled())
- return;
-
- for (const PasswordForm& form : forms) {
- // Don't involve the password manager if this form corresponds to
- // SpdyProxy authentication, as indicated by the realm.
- if (base::EndsWith(form.signon_realm, kSpdyProxyRealm,
- base::CompareCase::SENSITIVE))
- continue;
- if (!client_->IsFillingEnabled(form.origin))
- continue;
-
- bool old_manager_found = false;
- for (const auto& old_manager : pending_login_managers_) {
- if (old_manager->DoesManage(form, driver) !=
- PasswordFormManager::RESULT_COMPLETE_MATCH) {
- continue;
- }
- old_manager_found = true;
- if (driver)
- old_manager->ProcessFrame(driver->AsWeakPtr());
- break;
- }
- if (old_manager_found)
- continue; // The current form is already managed.
-
- if (logger)
- logger->LogFormSignatures(Logger::STRING_ADDING_SIGNATURE, form);
- auto manager = std::make_unique<PasswordFormManager>(
- this, client_,
- (driver ? driver->AsWeakPtr() : base::WeakPtr<PasswordManagerDriver>()),
- form, std::make_unique<FormSaverImpl>(client_->GetPasswordStore()),
- nullptr);
- manager->Init(
- GetMetricRecorderFromNewPasswordFormManager(form.form_data, driver));
- pending_login_managers_.push_back(std::move(manager));
- }
-
- if (logger) {
- logger->LogNumber(Logger::STRING_NEW_NUMBER_LOGIN_MANAGERS,
- pending_login_managers_.size());
- }
}
void PasswordManager::CreateFormManagers(
@@ -827,15 +530,10 @@ void PasswordManager::CreateFormManagers(
// Find new forms.
std::vector<const PasswordForm*> new_forms;
for (const PasswordForm& form : forms) {
- // TODO(https://crbug.com/831123): Implement inside NewPasswordFormManger
- // not-filling Gaia forms that should be ignored instead of non-creating
- // NewPasswordFormManger instance.
- if (form.form_data.is_gaia_with_skip_save_password_form)
- continue;
if (!client_->IsFillingEnabled(form.origin))
continue;
- NewPasswordFormManager* manager =
+ PasswordFormManager* manager =
FindMatchedManager(form.form_data, form_managers_, driver);
if (manager) {
@@ -857,10 +555,10 @@ void PasswordManager::CreateFormManagers(
}
}
-NewPasswordFormManager* PasswordManager::CreateFormManager(
+PasswordFormManager* PasswordManager::CreateFormManager(
PasswordManagerDriver* driver,
const autofill::FormData& form) {
- form_managers_.push_back(std::make_unique<NewPasswordFormManager>(
+ form_managers_.push_back(std::make_unique<PasswordFormManager>(
client_,
driver ? driver->AsWeakPtr() : base::WeakPtr<PasswordManagerDriver>(),
form, nullptr,
@@ -869,7 +567,7 @@ NewPasswordFormManager* PasswordManager::CreateFormManager(
return form_managers_.back().get();
}
-NewPasswordFormManager* PasswordManager::ProvisionallySaveForm(
+PasswordFormManager* PasswordManager::ProvisionallySaveForm(
const FormData& submitted_form,
PasswordManagerDriver* driver,
bool is_manual_fallback) {
@@ -890,7 +588,7 @@ NewPasswordFormManager* PasswordManager::ProvisionallySaveForm(
return nullptr;
// No need to report PasswordManagerMetricsRecorder::EMPTY_PASSWORD, because
- // PasswordToSave in NewPasswordFormManager DCHECKs that the password is never
+ // PasswordToSave in PasswordFormManager DCHECKs that the password is never
// empty.
const GURL& origin = submitted_form.url;
@@ -901,7 +599,7 @@ NewPasswordFormManager* PasswordManager::ProvisionallySaveForm(
return nullptr;
}
- NewPasswordFormManager* matched_manager =
+ PasswordFormManager* matched_manager =
GetMatchedManager(driver, submitted_form);
auto availability =
@@ -925,9 +623,7 @@ NewPasswordFormManager* PasswordManager::ProvisionallySaveForm(
return nullptr;
}
- if (!matched_manager->ProvisionallySave(
- submitted_form, driver,
- submitted_form.is_gaia_with_skip_save_password_form))
+ if (!matched_manager->ProvisionallySave(submitted_form, driver))
return nullptr;
// Set all other form managers to no submission state.
@@ -949,17 +645,13 @@ NewPasswordFormManager* PasswordManager::ProvisionallySaveForm(
void PasswordManager::ReportSpecPriorityForGeneratedPassword(
const PasswordForm& password_form,
uint32_t spec_priority) {
- PasswordFormManager* form_manager = GetMatchingPendingManager(password_form);
- if (form_manager && form_manager->GetMetricsRecorder()) {
- form_manager->GetMetricsRecorder()->ReportSpecPriorityForGeneratedPassword(
- spec_priority);
- }
+ // TODO(https://crbug.com/949519): remove Generation.SpecPriority metric.
}
void PasswordManager::LogFirstFillingResult(PasswordManagerDriver* driver,
uint32_t form_renderer_id,
int32_t result) {
- NewPasswordFormManager* matching_manager =
+ PasswordFormManager* matching_manager =
FindMatchedManagerByRendererId(form_renderer_id, form_managers_, driver);
if (!matching_manager)
return;
@@ -977,7 +669,7 @@ void PasswordManager::PresaveGeneratedPassword(
const FormData& form,
const base::string16& generated_password,
const base::string16& generation_element) {
- NewPasswordFormManager* form_manager =
+ PasswordFormManager* form_manager =
FindMatchedManager(form, form_managers_, driver);
UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager",
!form_manager);
@@ -993,7 +685,7 @@ void PasswordManager::UpdateGeneratedPasswordOnUserInput(
const base::string16& form_identifier,
const base::string16& field_identifier,
const base::string16& field_value) {
- for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) {
+ for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) {
if (manager->UpdateGeneratedPasswordOnUserInput(
form_identifier, field_identifier, field_value)) {
break;
@@ -1003,28 +695,11 @@ void PasswordManager::UpdateGeneratedPasswordOnUserInput(
void PasswordManager::OnPasswordNoLongerGenerated(
PasswordManagerDriver* driver) {
- for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_)
+ for (std::unique_ptr<PasswordFormManager>& manager : form_managers_)
manager->PasswordNoLongerGenerated();
}
#endif
-void PasswordManager::ProvisionallySaveManager(
- const PasswordForm& form,
- PasswordFormManager* matched_manager,
- BrowserSavePasswordProgressLogger* logger) {
- DCHECK(matched_manager);
- std::unique_ptr<PasswordFormManager> manager = matched_manager->Clone();
-
- PasswordForm submitted_form(form);
- submitted_form.preferred = true;
- if (logger) {
- logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVED_FORM,
- submitted_form);
- }
- manager->ProvisionallySave(submitted_form);
- provisional_save_manager_.swap(manager);
-}
-
bool PasswordManager::IsAutomaticSavePromptAvailable() {
std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
if (password_manager_util::IsLoggingActive(client_)) {
@@ -1085,7 +760,6 @@ void PasswordManager::OnPasswordFormsRendered(
if (logger)
logger->LogMessage(Logger::STRING_DECISION_DROP);
submitted_manager->GetMetricsRecorder()->LogSubmitFailed();
- provisional_save_manager_.reset();
owned_submitted_form_manager_.reset();
return;
}
@@ -1126,7 +800,6 @@ void PasswordManager::OnPasswordFormsRendered(
form);
logger->LogMessage(Logger::STRING_DECISION_DROP);
}
- provisional_save_manager_.reset();
owned_submitted_form_manager_.reset();
// Clear all_visible_forms_ once we found the match.
all_visible_forms_.clear();
@@ -1161,6 +834,9 @@ void PasswordManager::OnLoginSuccessful() {
DCHECK(submitted_manager->GetSubmittedForm());
client_->GetStoreResultFilter()->ReportFormLoginSuccess(*submitted_manager);
+#if !defined(OS_IOS)
+ leak_delegate_.StartLeakCheck(submitted_manager->GetPendingCredentials());
+#endif
auto submission_event =
submitted_manager->GetSubmittedForm()->submission_event;
@@ -1175,16 +851,15 @@ void PasswordManager::OnLoginSuccessful() {
if (!able_to_save_passwords)
return;
- MaybeSavePasswordHash(*submitted_manager);
+ MaybeSavePasswordHash(submitted_manager);
// TODO(https://crbug.com/831123): Implement checking whether to save with
- // NewPasswordFormManager.
+ // PasswordFormManager.
if (!client_->GetStoreResultFilter()->ShouldSave(
*submitted_manager->GetSubmittedForm())) {
RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::SYNC_CREDENTIAL,
submitted_manager->GetOrigin(), logger.get());
- provisional_save_manager_.reset();
owned_submitted_form_manager_.reset();
return;
}
@@ -1198,26 +873,21 @@ void PasswordManager::OnLoginSuccessful() {
// If the form is eligible only for saving fallback, it shouldn't go here.
DCHECK(!submitted_manager->GetPendingCredentials().only_for_fallback);
- // TODO(https://crbug.com/831123): Remove logging when the old form parsing is
- // removed.
- if (IsNewFormParsingForSavingEnabled()) {
- // In this case, |submitted_manager| points to a NewPasswordFormManager and
- // |provisional_save_manager_| to a PasswordFormManager. They use the new
- // and the old FormData parser, respectively. Log the differences using UKM
- // to be alerted of regressions early.
- if (provisional_save_manager_) {
- RecordParsingOnSavingDifference(*provisional_save_manager_,
- *submitted_manager,
- submitted_manager->GetMetricsRecorder());
- }
- }
-
if (ShouldPromptUserToSavePassword(*submitted_manager)) {
if (logger)
logger->LogMessage(Logger::STRING_DECISION_ASK);
bool update_password = submitted_manager->IsPasswordUpdate();
- if (client_->PromptUserToSaveOrUpdatePassword(MoveOwnedSubmittedManager(),
- update_password)) {
+ bool is_blacklisted = submitted_manager->IsBlacklisted();
+ SyncState password_sync_state = client_->GetPasswordSyncState();
+ if (ShouldShowOnboarding(
+ client_->GetPrefs(), PasswordUpdateBool(update_password),
+ BlacklistedBool(is_blacklisted), password_sync_state)) {
+ if (client_->ShowOnboarding(MoveOwnedSubmittedManager())) {
+ if (logger)
+ logger->LogMessage(Logger::STRING_SHOW_ONBOARDING);
+ }
+ } else if (client_->PromptUserToSaveOrUpdatePassword(
+ MoveOwnedSubmittedManager(), update_password)) {
if (logger)
logger->LogMessage(Logger::STRING_SHOW_PASSWORD_PROMPT);
}
@@ -1234,18 +904,17 @@ void PasswordManager::OnLoginSuccessful() {
if (submitted_manager->HasGeneratedPassword())
client_->AutomaticPasswordSave(MoveOwnedSubmittedManager());
}
- provisional_save_manager_.reset();
owned_submitted_form_manager_.reset();
}
void PasswordManager::MaybeSavePasswordHash(
- const PasswordFormManagerInterface& submitted_manager) {
+ PasswordFormManagerInterface* submitted_manager) {
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+ const PasswordForm* submitted_form = submitted_manager->GetSubmittedForm();
// When |username_value| is empty, it's not clear whether the submitted
// credentials are really Gaia or enterprise credentials. Don't save
// password hash in that case.
- std::string username =
- base::UTF16ToUTF8(submitted_manager.GetSubmittedForm()->username_value);
+ std::string username = base::UTF16ToUTF8(submitted_form->username_value);
if (username.empty())
return;
@@ -1254,25 +923,33 @@ void PasswordManager::MaybeSavePasswordHash(
if (!store)
return;
- const PasswordForm* password_form = submitted_manager.GetSubmittedForm();
-
bool should_save_enterprise_pw =
client_->GetStoreResultFilter()->ShouldSaveEnterprisePasswordHash(
- *password_form);
+ *submitted_form);
bool should_save_gaia_pw =
client_->GetStoreResultFilter()->ShouldSaveGaiaPasswordHash(
- *password_form);
+ *submitted_form);
if (!should_save_enterprise_pw && !should_save_gaia_pw)
return;
+ if (submitted_form->form_data.is_gaia_with_skip_save_password_form) {
+ submitted_manager->GetMetricsRecorder()
+ ->set_password_hash_saved_on_chrome_sing_in_page();
+ }
+
+ if (password_manager_util::IsLoggingActive(client_)) {
+ BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
+ logger.LogMessage(Logger::STRING_SAVE_PASSWORD_HASH);
+ }
+
// Canonicalizes username if it is an email.
if (username.find('@') != std::string::npos)
username = gaia::CanonicalizeEmail(username);
- bool is_password_change = !password_form->new_password_element.empty();
+ bool is_password_change = !submitted_form->new_password_element.empty();
const base::string16 password = is_password_change
- ? password_form->new_password_value
- : password_form->password_value;
+ ? submitted_form->new_password_value
+ : submitted_form->password_value;
if (should_save_enterprise_pw) {
store->SaveEnterprisePasswordHash(username, password);
@@ -1280,107 +957,59 @@ void PasswordManager::MaybeSavePasswordHash(
}
DCHECK(should_save_gaia_pw);
- SyncPasswordHashChange event =
+ GaiaPasswordHashChange event =
client_->GetStoreResultFilter()->IsSyncAccountEmail(username)
? (is_password_change
- ? SyncPasswordHashChange::CHANGED_IN_CONTENT_AREA
- : SyncPasswordHashChange::SAVED_IN_CONTENT_AREA)
- : SyncPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE;
+ ? GaiaPasswordHashChange::CHANGED_IN_CONTENT_AREA
+ : GaiaPasswordHashChange::SAVED_IN_CONTENT_AREA)
+ : GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE;
store->SaveGaiaPasswordHash(username, password, event);
#endif
}
void PasswordManager::ProcessAutofillPredictions(
- password_manager::PasswordManagerDriver* driver,
- const std::vector<autofill::FormStructure*>& forms) {
+ PasswordManagerDriver* driver,
+ const std::vector<FormStructure*>& forms) {
std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
- if (password_manager_util::IsLoggingActive(client_))
+ if (password_manager_util::IsLoggingActive(client_)) {
logger.reset(
new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
-
- if (IsNewFormParsingForFillingEnabled()) {
- for (const autofill::FormStructure* form : forms)
- predictions_[form->form_signature()] = ConvertToFormPredictions(*form);
- for (auto& manager : form_managers_)
- manager->ProcessServerPredictions(predictions_);
}
- // Leave only forms that contain fields that are useful for password manager.
- autofill::FormsPredictionsMap predictions;
- for (const autofill::FormStructure* form : forms) {
+ for (const FormStructure* form : forms)
+ predictions_[form->form_signature()] = ConvertToFormPredictions(*form);
+ for (auto& manager : form_managers_)
+ manager->ProcessServerPredictions(predictions_);
+
+ // Create form managers for non-password forms with single usernames.
+ for (const FormStructure* form : forms) {
if (logger)
logger->LogFormStructure(Logger::STRING_SERVER_PREDICTIONS, *form);
- for (const auto& field : *form) {
- PasswordFormFieldPredictionType prediction_type;
- if (ServerPredictionsToPasswordFormPrediction(field->server_predictions(),
- &prediction_type)) {
- predictions[form->ToFormData()][*field] = prediction_type;
- }
- // Certain fields are annotated by the browsers as "not passwords" i.e.
- // they should not be treated as passwords by the Password Manager.
- if (field->form_control_type == "password" &&
- IsPredictedTypeNotPasswordPrediction(
- field->Type().GetStorableType())) {
- predictions[form->ToFormData()][*field] =
- PasswordFormFieldPredictionType::kNotPassword;
- }
- }
- }
- if (predictions.empty())
- return;
-
- if (driver) {
- // |driver_| is nullptr on iOS.
- // TODO(https://crbug.com/831123): Remove propagating predictions to the
- // renderer when the old parser is gone.
- driver->AutofillDataReceived(predictions);
- }
-}
-
-PasswordFormManager* PasswordManager::GetMatchingPendingManager(
- const PasswordForm& form) {
- PasswordFormManager* matched_manager = nullptr;
- PasswordFormManager::MatchResultMask current_match_result =
- PasswordFormManager::RESULT_NO_MATCH;
-
- for (auto& login_manager : pending_login_managers_) {
- PasswordFormManager::MatchResultMask result =
- login_manager->DoesManage(form, nullptr);
+ if (form->has_password_field())
+ continue;
- if (result == PasswordFormManager::RESULT_NO_MATCH)
+ // Do not skip the form if it either contains a field for the Username
+ // first flow or a clear-text password field.
+ if (!(HasSingleUsernameVote(*form) || HasNewPasswordVote(*form)))
continue;
- if (result == PasswordFormManager::RESULT_COMPLETE_MATCH) {
- // If we find a manager that exactly matches the submitted form including
- // the action URL, exit the loop.
- matched_manager = login_manager.get();
- break;
- } else if (result == (PasswordFormManager::RESULT_COMPLETE_MATCH &
- ~PasswordFormManager::RESULT_ACTION_MATCH) &&
- result > current_match_result) {
- // If the current manager matches the submitted form excluding the action
- // URL, remember it as a candidate and continue searching for an exact
- // match. See http://crbug.com/27246 for an example where actions can
- // change.
- matched_manager = login_manager.get();
- current_match_result = result;
- } else if (result > current_match_result) {
- matched_manager = login_manager.get();
- current_match_result = result;
+ if (FindMatchedManagerByRendererId(form->unique_renderer_id(),
+ form_managers_, driver)) {
+ // The form manager is already created.
+ continue;
}
+
+ FormData form_data = form->ToFormData();
+ auto* manager = CreateFormManager(driver, form_data);
+ manager->ProcessServerPredictions(predictions_);
}
- return matched_manager;
}
PasswordFormManagerInterface* PasswordManager::GetSubmittedManager() const {
- if (!IsNewFormParsingForSavingEnabled())
- return provisional_save_manager_.get();
-
if (owned_submitted_form_manager_)
return owned_submitted_form_manager_.get();
- for (const std::unique_ptr<NewPasswordFormManager>& manager :
- form_managers_) {
+ for (const std::unique_ptr<PasswordFormManager>& manager : form_managers_) {
if (manager->is_submitted())
return manager.get();
}
@@ -1390,17 +1019,13 @@ PasswordFormManagerInterface* PasswordManager::GetSubmittedManager() const {
std::unique_ptr<PasswordFormManagerForUI>
PasswordManager::MoveOwnedSubmittedManager() {
- if (!IsNewFormParsingForSavingEnabled())
- return std::move(provisional_save_manager_);
-
if (owned_submitted_form_manager_)
return std::move(owned_submitted_form_manager_);
for (auto iter = form_managers_.begin(); iter != form_managers_.end();
++iter) {
if ((*iter)->is_submitted()) {
- std::unique_ptr<NewPasswordFormManager> submitted_manager =
- std::move(*iter);
+ std::unique_ptr<PasswordFormManager> submitted_manager = std::move(*iter);
form_managers_.erase(iter);
return std::move(submitted_manager);
}
@@ -1421,25 +1046,22 @@ void PasswordManager::RecordProvisionalSaveFailure(
}
scoped_refptr<PasswordFormMetricsRecorder>
-PasswordManager::GetMetricRecorderFromNewPasswordFormManager(
+PasswordManager::GetMetricRecorderFromPasswordFormManager(
const FormData& form,
const PasswordManagerDriver* driver) {
- NewPasswordFormManager* matched_manager = GetMatchedManager(driver, form);
+ PasswordFormManager* matched_manager = GetMatchedManager(driver, form);
return matched_manager ? matched_manager->metrics_recorder() : nullptr;
}
// TODO(https://crbug.com/831123): Implement creating missing
-// NewPasswordFormManager when PasswordFormManager is gone.
+// PasswordFormManager when PasswordFormManager is gone.
PasswordFormManagerInterface* PasswordManager::GetMatchedManager(
const PasswordManagerDriver* driver,
const PasswordForm& form) {
- if (!IsNewFormParsingForSavingEnabled())
- return GetMatchingPendingManager(form);
-
return GetMatchedManager(driver, form.form_data);
}
-NewPasswordFormManager* PasswordManager::GetMatchedManager(
+PasswordFormManager* PasswordManager::GetMatchedManager(
const PasswordManagerDriver* driver,
const FormData& form) {
for (auto& form_manager : form_managers_) {
diff --git a/chromium/components/password_manager/core/browser/password_manager.h b/chromium/components/password_manager/core/browser/password_manager.h
index ca02bb30738..882d9c65d76 100644
--- a/chromium/components/password_manager/core/browser/password_manager.h
+++ b/chromium/components/password_manager/core/browser/password_manager.h
@@ -21,7 +21,8 @@
#include "components/autofill/core/common/signatures_util.h"
#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
#include "components/password_manager/core/browser/form_submission_observer.h"
-#include "components/password_manager/core/browser/password_form_manager.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
+#include "components/password_manager/core/browser/leak_detection_delegate.h"
#include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
class PrefRegistrySimple;
@@ -40,8 +41,11 @@ namespace password_manager {
class BrowserSavePasswordProgressLogger;
class PasswordManagerClient;
class PasswordManagerDriver;
+class PasswordFormManagerForUI;
+class PasswordFormManagerInterface;
+class PasswordFormMetricsRecorder;
+class PasswordManagerMetricsRecorder;
class PasswordFormManager;
-class NewPasswordFormManager;
// Per-tab password manager. Handles creation and management of UI elements,
// receiving password form data from the renderer and managing the password
@@ -153,18 +157,7 @@ class PasswordManager : public FormSubmissionObserver {
PasswordManagerClient* client() { return client_; }
#if defined(UNIT_TEST)
- // TODO(crbug.com/639786): Replace using this by quering the factory for
- // mocked PasswordFormManagers.
- const std::vector<std::unique_ptr<PasswordFormManager>>&
- pending_login_managers() const {
- return pending_login_managers_;
- }
-
- const PasswordFormManager* provisional_save_manager() const {
- return provisional_save_manager_.get();
- }
-
- const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers()
+ const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers()
const {
return form_managers_;
}
@@ -172,8 +165,13 @@ class PasswordManager : public FormSubmissionObserver {
PasswordFormManagerInterface* GetSubmittedManagerForTest() const {
return GetSubmittedManager();
}
+#if !defined(OS_IOS)
+ void set_leak_factory(std::unique_ptr<LeakDetectionCheckFactory> factory) {
+ leak_delegate_.set_leak_factory(std::move(factory));
+ }
+#endif // !defined(OS_IOS)
-#endif
+#endif // defined(UNIT_TEST)
// Reports the priority of a PasswordGenerationRequirementsSpec for a
// generated password. See
@@ -225,12 +223,6 @@ class PasswordManager : public FormSubmissionObserver {
PasswordManagerTest,
ShouldBlockPasswordForSameOriginButDifferentSchemeTest);
- // Clones |matched_manager| and keeps it as |provisional_save_manager_|.
- // |form| is saved provisionally to |provisional_save_manager_|.
- void ProvisionallySaveManager(const autofill::PasswordForm& form,
- PasswordFormManager* matched_manager,
- BrowserSavePasswordProgressLogger* logger);
-
// Returns true if there is a form manager for a submitted form and this form
// manager contains the submitted credentials suitable for automatic save
// prompt, not for manual fallback only.
@@ -253,8 +245,7 @@ class PasswordManager : public FormSubmissionObserver {
// Helper function called inside OnLoginSuccessful() to save password hash
// data from |submitted_manager| for password reuse detection purpose.
- void MaybeSavePasswordHash(
- const PasswordFormManagerInterface& submitted_manager);
+ void MaybeSavePasswordHash(PasswordFormManagerInterface* submitted_manager);
// Checks for every form in |forms| whether |pending_login_managers_| already
// contain a manager for that form. If not, adds a manager for each such form.
@@ -267,16 +258,16 @@ class PasswordManager : public FormSubmissionObserver {
void CreateFormManagers(PasswordManagerDriver* driver,
const std::vector<autofill::PasswordForm>& forms);
- // Create NewPasswordFormManager for |form|, adds the newly created one to
+ // Create PasswordFormManager for |form|, adds the newly created one to
// |form_managers_| and returns it.
- NewPasswordFormManager* CreateFormManager(PasswordManagerDriver* driver,
- const autofill::FormData& forms);
+ PasswordFormManager* CreateFormManager(PasswordManagerDriver* driver,
+ const autofill::FormData& form);
- // Passes |form| to NewPasswordFormManager that manages it for using it after
+ // Passes |form| to PasswordFormManager that manages it for using it after
// detecting submission success for saving. |driver| is needed to determine
// the match. If the function is called multiple times, only the form from the
// last call is provisionally saved. Multiple calls is possible because it is
- // called on any user keystroke. If there is no NewPasswordFormManager that
+ // called on any user keystroke. If there is no PasswordFormManager that
// manages |form|, the new one is created. If |is_manual_fallback| is true
// and the matched form manager has not recieved yet response from the
// password store, then nullptr is returned. Returns manager which manages
@@ -285,14 +276,9 @@ class PasswordManager : public FormSubmissionObserver {
// should be skipped on saving.
// TODO(https://crbug.com/949519): move |is_gaia_with_skip_save_password_form|
// from PasswordForm to FormData, and remove it from arguments.
- NewPasswordFormManager* ProvisionallySaveForm(const autofill::FormData& form,
- PasswordManagerDriver* driver,
- bool is_manual_fallback);
-
- // Returns the best match in |pending_login_managers_| for |form|. May return
- // nullptr if no match exists.
- PasswordFormManager* GetMatchingPendingManager(
- const autofill::PasswordForm& form);
+ PasswordFormManager* ProvisionallySaveForm(const autofill::FormData& form,
+ PasswordManagerDriver* driver,
+ bool is_manual_fallback);
// Returns the form manager that corresponds to the submitted form. It might
// be nullptr if there is no submitted form.
@@ -314,9 +300,8 @@ class PasswordManager : public FormSubmissionObserver {
BrowserSavePasswordProgressLogger* logger);
scoped_refptr<PasswordFormMetricsRecorder>
- GetMetricRecorderFromNewPasswordFormManager(
- const autofill::FormData& form,
- const PasswordManagerDriver* driver);
+ GetMetricRecorderFromPasswordFormManager(const autofill::FormData& form,
+ const PasswordManagerDriver* driver);
// Returns the manager which manages |form|. |driver| is needed to determine
// the match. Returns nullptr when no matched manager is found.
@@ -326,38 +311,14 @@ class PasswordManager : public FormSubmissionObserver {
// Returns the manager which manages |form|. |driver| is needed to determine
// the match. Returns nullptr when no matched manager is found.
- NewPasswordFormManager* GetMatchedManager(const PasswordManagerDriver* driver,
- const autofill::FormData& form);
+ PasswordFormManager* GetMatchedManager(const PasswordManagerDriver* driver,
+ const autofill::FormData& form);
// Log a frame (main frame, iframe) of a submitted password form.
void ReportSubmittedFormFrameMetric(const PasswordManagerDriver* driver,
const autofill::PasswordForm& form);
- // Note about how a PasswordFormManager can transition from
- // pending_login_managers_ to provisional_save_manager_ and the infobar.
- //
- // 1. form "seen"
- // | new
- // | ___ Infobar
- // pending_login -- form submit --> provisional_save ___/
- // ^ | \___ (update DB)
- // | fail
- // |-----------<------<---------| !new
- //
- // When a form is "seen" on a page, a PasswordFormManager is created
- // and stored in this collection until user navigates away from page.
-
- std::vector<std::unique_ptr<PasswordFormManager>> pending_login_managers_;
-
- // When the user submits a password/credential, this contains the
- // PasswordFormManager for the form in question until we deem the login
- // attempt to have succeeded (as in valid credentials). If it fails, we
- // send the PasswordFormManager back to the pending_login_managers_ set.
- // Scoped in case PasswordManager gets deleted (e.g tab closes) between the
- // time a user submits a login form and gets to the next page.
- std::unique_ptr<PasswordFormManager> provisional_save_manager_;
-
- // NewPasswordFormManager transition schemes:
+ // PasswordFormManager transition schemes:
// 1. HTML submission with navigation afterwads.
// form "seen"
// |
@@ -374,14 +335,14 @@ class PasswordManager : public FormSubmissionObserver {
// ____ Prompt.
// --> (is_submitted = true) ---- Automatic save.
- // Contains one NewPasswordFormManager per each form on the page.
- // When a form is "seen" on a page, a NewPasswordFormManager is created
+ // Contains one PasswordFormManager per each form on the page.
+ // When a form is "seen" on a page, a PasswordFormManager is created
// and stored in this collection until user navigates away from page.
- std::vector<std::unique_ptr<NewPasswordFormManager>> form_managers_;
+ std::vector<std::unique_ptr<PasswordFormManager>> form_managers_;
// Corresponds to the submitted form, after navigion away before submission
// success detection is finished.
- std::unique_ptr<NewPasswordFormManager> owned_submitted_form_manager_;
+ std::unique_ptr<PasswordFormManager> owned_submitted_form_manager_;
// The embedder-level client. Must outlive this class.
PasswordManagerClient* const client_;
@@ -403,6 +364,11 @@ class PasswordManager : public FormSubmissionObserver {
// CredentialManagerImpl takes care of it.
bool store_password_called_ = false;
+#if !defined(OS_IOS)
+ // Helper for making the requests on leak detection.
+ LeakDetectionDelegate leak_delegate_;
+#endif // !defined(OS_IOS)
+
DISALLOW_COPY_AND_ASSIGN(PasswordManager);
};
diff --git a/chromium/components/password_manager/core/browser/password_manager_client.cc b/chromium/components/password_manager/core/browser/password_manager_client.cc
index 2a7afaa50b1..2ef9f9ec4d8 100644
--- a/chromium/components/password_manager/core/browser/password_manager_client.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_client.cc
@@ -32,6 +32,8 @@ bool PasswordManagerClient::OnCredentialManagerUsed() {
return true;
}
+void PasswordManagerClient::ShowTouchToFill(PasswordManagerDriver* driver) {}
+
void PasswordManagerClient::GeneratePassword() {}
void PasswordManagerClient::PasswordWasAutofilled(
@@ -43,6 +45,10 @@ void PasswordManagerClient::AutofillHttpAuth(
const autofill::PasswordForm& preferred_match,
const PasswordFormManagerForUI* form_manager) {}
+void PasswordManagerClient::NotifyUserCredentialsWereLeaked(
+ password_manager::CredentialLeakType leak_type,
+ const GURL& origin) {}
+
SyncState PasswordManagerClient::GetPasswordSyncState() const {
return NOT_SYNCING;
}
diff --git a/chromium/components/password_manager/core/browser/password_manager_client.h b/chromium/components/password_manager/core/browser/password_manager_client.h
index ec283b37108..105815e0602 100644
--- a/chromium/components/password_manager/core/browser/password_manager_client.h
+++ b/chromium/components/password_manager/core/browser/password_manager_client.h
@@ -12,14 +12,17 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/credentials_filter.h"
#include "components/password_manager/core/browser/hsts_query.h"
#include "components/password_manager/core/browser/http_auth_manager.h"
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
#include "components/password_manager/core/browser/manage_passwords_referrer.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_store.h"
+#include "components/safe_browsing/buildflags.h"
#include "net/cert/cert_status_flags.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
@@ -34,9 +37,17 @@ namespace favicon {
class FaviconService;
}
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+
+namespace signin {
+class IdentityManager;
+} // namespace signin
+
class GURL;
-#if defined(FULL_SAFE_BROWSING)
+#if defined(ON_FOCUS_PING_ENABLED)
namespace safe_browsing {
class PasswordProtectionService;
}
@@ -119,6 +130,12 @@ class PasswordManagerClient {
std::unique_ptr<PasswordFormManagerForUI> form_to_save,
bool is_update) = 0;
+ // Informs the embedder that the onboarding experience should be shown.
+ // This will also offer the ability to actually save the password.
+ // Returns true if both the onboarding and the saving prompt were displayed.
+ virtual bool ShowOnboarding(
+ std::unique_ptr<PasswordFormManagerForUI> form_to_save) = 0;
+
// Informs the embedder that the user started typing a password and a password
// prompt should be available on click on the omnibox icon.
virtual void ShowManualFallbackForSaving(
@@ -133,7 +150,7 @@ class PasswordManagerClient {
// Informs the embedder that the focus changed to a different input in the
// same frame (e.g. tabbed from email to password field).
virtual void FocusedInputChanged(
- password_manager::PasswordManagerDriver* driver,
+ PasswordManagerDriver* driver,
autofill::mojom::FocusedFieldType focused_field_type) = 0;
// Informs the embedder of a password forms that the user should choose from.
@@ -145,6 +162,9 @@ class PasswordManagerClient {
const GURL& origin,
const CredentialsCallback& callback) = 0;
+ // Instructs the client to show the Touch To Fill UI.
+ virtual void ShowTouchToFill(PasswordManagerDriver* driver);
+
// Informs the embedder that the user has manually requested to generate a
// password in the focused password field.
virtual void GeneratePassword();
@@ -194,6 +214,11 @@ class PasswordManagerClient {
virtual void AutofillHttpAuth(const autofill::PasswordForm& preferred_match,
const PasswordFormManagerForUI* form_manager);
+ // Informs the embedder that user credentials were leaked.
+ virtual void NotifyUserCredentialsWereLeaked(
+ password_manager::CredentialLeakType leak_type,
+ const GURL& origin);
+
// Gets prefs associated with this embedder.
virtual PrefService* GetPrefs() const = 0;
@@ -244,7 +269,7 @@ class PasswordManagerClient {
// Returns the current best guess as to the page's display language.
virtual std::string GetPageLanguage() const;
-#if defined(FULL_SAFE_BROWSING)
+#if defined(ON_FOCUS_PING_ENABLED)
// Return the PasswordProtectionService associated with this instance.
virtual safe_browsing::PasswordProtectionService*
GetPasswordProtectionService() const = 0;
@@ -254,7 +279,9 @@ class PasswordManagerClient {
// only, and won't trigger a warning.
virtual void CheckSafeBrowsingReputation(const GURL& form_action,
const GURL& frame_url) = 0;
+#endif
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// Checks the safe browsing reputation of the webpage where password reuse
// happens. This is called by the PasswordReuseDetectionManager when a
// protected password is typed on the wrong domain. This may trigger a
@@ -268,7 +295,7 @@ class PasswordManagerClient {
const std::vector<std::string>& matching_domains,
bool password_field_exists) = 0;
- // Records a Chrome Sync event that sync password reuse was detected.
+ // Records a Chrome Sync event that GAIA password reuse was detected.
virtual void LogPasswordReuseDetectedEvent() = 0;
#endif
@@ -292,6 +319,14 @@ class PasswordManagerClient {
// Returns the favicon service used to retrieve icons for an origin.
virtual favicon::FaviconService* GetFaviconService();
+ // Returns the identity manager for profile.
+ virtual signin::IdentityManager* GetIdentityManager() = 0;
+
+ // Returns a pointer to the URLLoaderFactory owned by the storage partition of
+ // the current profile.
+ virtual scoped_refptr<network::SharedURLLoaderFactory>
+ GetURLLoaderFactory() = 0;
+
// Whether the primary account of the current profile is under Advanced
// Protection - a type of Google Account that helps protect our most at-risk
// users.
diff --git a/chromium/components/password_manager/core/browser/password_manager_constants.cc b/chromium/components/password_manager/core/browser/password_manager_constants.cc
index 33e45e58e15..b7f898de714 100644
--- a/chromium/components/password_manager/core/browser/password_manager_constants.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_constants.cc
@@ -8,12 +8,10 @@ namespace password_manager {
const base::FilePath::CharType kAffiliationDatabaseFileName[] =
FILE_PATH_LITERAL("Affiliation Database");
-const base::FilePath::CharType kLoginDataFileName[] =
+const base::FilePath::CharType kLoginDataForProfileFileName[] =
FILE_PATH_LITERAL("Login Data");
-#if defined(USE_X11)
-const base::FilePath::CharType kSecondLoginDataFileName[] =
- FILE_PATH_LITERAL("Login Data 2");
-#endif // defined(USE_X11)
+const base::FilePath::CharType kLoginDataForAccountFileName[] =
+ FILE_PATH_LITERAL("Login Data For Account");
const char kPasswordManagerAccountDashboardURL[] =
"https://passwords.google.com";
diff --git a/chromium/components/password_manager/core/browser/password_manager_constants.h b/chromium/components/password_manager/core/browser/password_manager_constants.h
index 86a4bc149a4..249ee57afde 100644
--- a/chromium/components/password_manager/core/browser/password_manager_constants.h
+++ b/chromium/components/password_manager/core/browser/password_manager_constants.h
@@ -10,10 +10,8 @@
namespace password_manager {
extern const base::FilePath::CharType kAffiliationDatabaseFileName[];
-extern const base::FilePath::CharType kLoginDataFileName[];
-#if defined(USE_X11)
-extern const base::FilePath::CharType kSecondLoginDataFileName[];
-#endif // defined(USE_X11)
+extern const base::FilePath::CharType kLoginDataForProfileFileName[];
+extern const base::FilePath::CharType kLoginDataForAccountFileName[];
// URL to the password manager account dashboard.
extern const char kPasswordManagerAccountDashboardURL[];
diff --git a/chromium/components/password_manager/core/browser/password_manager_metrics_recorder_unittest.cc b/chromium/components/password_manager/core/browser/password_manager_metrics_recorder_unittest.cc
index b48005f8af7..f542d97ded7 100644
--- a/chromium/components/password_manager/core/browser/password_manager_metrics_recorder_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_metrics_recorder_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/metrics/metrics_hashes.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
@@ -34,7 +34,7 @@ PasswordManagerMetricsRecorder CreateMetricsRecorder() {
} // namespace
TEST(PasswordManagerMetricsRecorder, UserModifiedPasswordField) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
{
PasswordManagerMetricsRecorder recorder(CreateMetricsRecorder());
@@ -52,7 +52,7 @@ TEST(PasswordManagerMetricsRecorder, UserModifiedPasswordField) {
}
TEST(PasswordManagerMetricsRecorder, UserModifiedPasswordFieldMultipleTimes) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
{
PasswordManagerMetricsRecorder recorder(CreateMetricsRecorder());
@@ -71,7 +71,7 @@ TEST(PasswordManagerMetricsRecorder, UserModifiedPasswordFieldMultipleTimes) {
}
TEST(PasswordManagerMetricsRecorder, UserModifiedPasswordFieldNotCalled) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder;
{ PasswordManagerMetricsRecorder recorder(CreateMetricsRecorder()); }
const auto& entries =
diff --git a/chromium/components/password_manager/core/browser/password_manager_metrics_util.cc b/chromium/components/password_manager/core/browser/password_manager_metrics_util.cc
index b734b5f2810..1725ba6d775 100644
--- a/chromium/components/password_manager/core/browser/password_manager_metrics_util.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -9,6 +9,7 @@
#include "base/metrics/user_metrics.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
@@ -55,6 +56,45 @@ void LogPresavedUpdateUIDismissalReason(UIDismissalReason reason) {
NUM_UI_RESPONSES);
}
+void LogLeakDialogTypeAndDismissalReason(LeakDialogType type,
+ LeakDialogDismissalReason reason) {
+ static constexpr char kHistogram[] =
+ "PasswordManager.LeakDetection.DialogDismissalReason";
+ auto GetSuffix = [type] {
+ switch (type) {
+ case LeakDialogType::kCheckup:
+ return "Checkup";
+ case LeakDialogType::kChange:
+ return "Change";
+ case LeakDialogType::kCheckupAndChange:
+ return "CheckupAndChange";
+ }
+ };
+
+ base::UmaHistogramEnumeration(kHistogram, reason);
+ base::UmaHistogramEnumeration(base::StrCat({kHistogram, ".", GetSuffix()}),
+ reason);
+}
+
+void LogOnboardingState(OnboardingState state) {
+ base::UmaHistogramEnumeration("PasswordManager.Onboarding.State", state);
+}
+
+void LogOnboardingUIDismissalReason(OnboardingUIDismissalReason reason) {
+ base::UmaHistogramEnumeration("PasswordManager.Onboarding.UIDismissalReason",
+ reason);
+}
+
+void LogResultOfSavingFlow(OnboardingResultOfSavingFlow result) {
+ base::UmaHistogramEnumeration("PasswordManager.Onboarding.ResultOfSavingFlow",
+ result);
+}
+
+void LogResultOfOnboardingSavingFlow(OnboardingResultOfSavingFlow result) {
+ base::UmaHistogramEnumeration(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", result);
+}
+
void LogUIDisplayDisposition(UIDisplayDisposition disposition) {
base::UmaHistogramEnumeration("PasswordBubble.DisplayDisposition",
disposition, NUM_DISPLAY_DISPOSITIONS);
@@ -236,21 +276,25 @@ void LogGenerationDialogChoice(GenerationDialogChoice choice,
} // namespace metrics_util
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
-void LogSyncPasswordHashChange(SyncPasswordHashChange event) {
- base::UmaHistogramEnumeration(
- "PasswordManager.SyncPasswordHashChange", event,
- SyncPasswordHashChange::SAVED_SYNC_PASSWORD_CHANGE_COUNT);
+void LogGaiaPasswordHashChange(GaiaPasswordHashChange event,
+ bool is_sync_password) {
+ if (is_sync_password) {
+ base::UmaHistogramEnumeration("PasswordManager.SyncPasswordHashChange",
+ event);
+ } else {
+ base::UmaHistogramEnumeration("PasswordManager.NonSyncPasswordHashChange",
+ event);
+ }
}
void LogIsSyncPasswordHashSaved(IsSyncPasswordHashSaved state,
bool is_under_advanced_protection) {
- base::UmaHistogramEnumeration(
- "PasswordManager.IsSyncPasswordHashSaved", state,
- IsSyncPasswordHashSaved::IS_SYNC_PASSWORD_HASH_SAVED_COUNT);
+ base::UmaHistogramEnumeration("PasswordManager.IsSyncPasswordHashSaved",
+ state);
if (is_under_advanced_protection) {
base::UmaHistogramEnumeration(
"PasswordManager.IsSyncPasswordHashSavedForAdvancedProtectionUser",
- state, IsSyncPasswordHashSaved::IS_SYNC_PASSWORD_HASH_SAVED_COUNT);
+ state);
}
}
diff --git a/chromium/components/password_manager/core/browser/password_manager_metrics_util.h b/chromium/components/password_manager/core/browser/password_manager_metrics_util.h
index 75b6759d55a..3e17bbe049c 100644
--- a/chromium/components/password_manager/core/browser/password_manager_metrics_util.h
+++ b/chromium/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -18,15 +18,6 @@ namespace password_manager {
namespace metrics_util {
-// Metrics: "PasswordManager.InfoBarResponse"
-enum ResponseType {
- NO_RESPONSE = 0,
- REMEMBER_PASSWORD,
- NEVER_REMEMBER_PASSWORD,
- INFOBAR_DISMISSED,
- NUM_RESPONSE_TYPES,
-};
-
// Metrics: "PasswordBubble.DisplayDisposition"
enum UIDisplayDisposition {
AUTOMATIC_WITH_PASSWORD_PENDING = 0,
@@ -62,6 +53,93 @@ enum UIDismissalReason {
NUM_UI_RESPONSES,
};
+// Enum representing the different leak detection dialogs shown to the user.
+// Corresponds to LeakDetectionDialogType suffix in histograms.xml.
+enum class LeakDialogType {
+ // The user is asked to visit the Password Checkup.
+ kCheckup = 0,
+ // The user is asked to change the password for the current site.
+ kChange = 1,
+ // The user is asked to visit the Password Checkup and change the password for
+ // the current site.
+ kCheckupAndChange = 2,
+ kMaxValue = kCheckupAndChange,
+};
+
+// Enum recording the dismissal reason of the data breach dialog which is shown
+// in case a credential is reported as leaked. Needs to stay in sync with the
+// PasswordLeakDetectionDialogDismissalReason enum in enums.xml.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class LeakDialogDismissalReason {
+ kNoDirectInteraction = 0,
+ kClickedClose = 1,
+ kClickedCheckPasswords = 2,
+ kClickedOk = 3,
+ kMaxValue = kClickedOk,
+};
+
+// Metrics: "PasswordManager.Onboarding.State"
+// Enum recording the state of showing the onboarding to the user. This
+// will be recorded on startup. Needs to stay in sync with the
+// PasswordManagerOnboardingState enum in enums.xml.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class OnboardingState {
+ // The onboarding wasn't shown to the user.
+ kDoNotShow = 0,
+ // The onboarding wasn't shown to the user,
+ // but it should be shown the next time they are prompted to save a password.
+ kShouldShow = 1,
+ // The onboarding was shown to the user.
+ kShown = 2,
+ kMaxValue = kShown,
+};
+
+// Metrics: "PasswordManager.Onboarding.UIDismissalReason"
+// Enum recording the dismissal reason of the onboarding dialog which is shown
+// when the user is offered to save their password for the first time.
+// Needs to stay in sync with the PasswordManagerOnboardingUIDismissalReason
+// enum in enums.xml.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class OnboardingUIDismissalReason {
+ // The accepting button was pressed, e.g. "Continue" or "Got it".
+ kAccepted = 0,
+ // The rejecting button was pressed, e.g. "Cancel".
+ kRejected = 1,
+ // The dialog was dismissed, e.g. by pressing the back button, or
+ // opening a new tab.
+ kDismissed = 2,
+ kMaxValue = kDismissed,
+};
+
+// Metrics: "PasswordManager.Onboarding.ResultOfSavingFlow"
+// Metrics: "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding"
+// Enum recording the result of the combined saving flow consisting of the
+// potentially shown onboarding dialog and the save infobar.
+// Needs to stay in sync with the PasswordManagerOnboardingResultOfSavingFlow
+// enum in enums.xml.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class OnboardingResultOfSavingFlow {
+ // Possible infobar responses from the |UIDismissalReason| enum.
+ kInfobarNoDirectInteraction = 0,
+ kInfobarClickedSave = 1,
+ kInfobarClickedCancel = 2,
+ kInfobarClickedNever = 3,
+ // The rejecting button on the onboarding dialog was pressed, e.g. "Cancel".
+ kOnboardingRejected = 4,
+ // The onboarding dialog was dismissed, e.g. by pressing the back button, or
+ // opening a new tab.
+ kOnboardingDismissed = 5,
+ kMaxValue = kOnboardingDismissed,
+};
+
enum FormDeserializationStatus {
LOGIN_DATABASE_SUCCESS,
LOGIN_DATABASE_FAILURE,
@@ -212,20 +290,38 @@ enum class DeleteCorruptedPasswordsResult {
};
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
-enum class SyncPasswordHashChange {
- SAVED_ON_CHROME_SIGNIN,
- SAVED_IN_CONTENT_AREA,
- CLEARED_ON_CHROME_SIGNOUT,
- CHANGED_IN_CONTENT_AREA,
- NOT_SYNC_PASSWORD_CHANGE,
- SAVED_SYNC_PASSWORD_CHANGE_COUNT
+enum class GaiaPasswordHashChange {
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+
+ // Password hash saved event where the account is used to sign in to Chrome
+ // (syncing).
+ SAVED_ON_CHROME_SIGNIN = 0,
+ // Syncing account password hash saved in content area (syncing).
+ SAVED_IN_CONTENT_AREA = 1,
+ // Clear syncing password hash when the account is signed out of Chrome
+ // (syncing).
+ CLEARED_ON_CHROME_SIGNOUT = 2,
+ // Password hash changed event where the account is used to sign in to Chrome
+ // (syncing).
+ CHANGED_IN_CONTENT_AREA = 3,
+ // Password hash change event where the account is not syncing.
+ NOT_SYNC_PASSWORD_CHANGE = 4,
+ // Password hash change event for non-GAIA enterprise accounts.
+ NON_GAIA_ENTERPRISE_PASSWORD_CHANGE = 5,
+ SAVED_SYNC_PASSWORD_CHANGE_COUNT = 6,
+ kMaxValue = SAVED_SYNC_PASSWORD_CHANGE_COUNT,
};
enum class IsSyncPasswordHashSaved {
- NOT_SAVED,
- SAVED_VIA_STRING_PREF,
- SAVED_VIA_LIST_PREF,
- IS_SYNC_PASSWORD_HASH_SAVED_COUNT
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+
+ NOT_SAVED = 0,
+ SAVED_VIA_STRING_PREF = 1,
+ SAVED_VIA_LIST_PREF = 2,
+ IS_SYNC_PASSWORD_HASH_SAVED_COUNT = 3,
+ kMaxValue = IS_SYNC_PASSWORD_HASH_SAVED_COUNT,
};
#endif
@@ -283,7 +379,7 @@ enum class LinuxBackendMigrationStatus {
// The last attempt was not completed.
kDeprecatedFailed = 1,
// All the data is in the encrypted loginDB.
- kCopiedAll = 2,
+ kDeprecatedCopiedAll = 2,
// The standard login database is encrypted.
kLoginDBReplaced = 3,
// The migration is about to be attempted.
@@ -294,13 +390,13 @@ enum class LinuxBackendMigrationStatus {
// by more precise errors.
kDeprecatedFailedCreatedEncrypted = 6,
// Could not read from the native backend.
- kFailedAccessNative = 7,
+ kDeprecatedFailedAccessNative = 7,
// Could not replace old database.
kFailedReplace = 8,
// Could not initialise the temporary encrypted database.
kFailedInitEncrypted,
// Could not reset th temporary encrypted database.
- kFailedRecreateEncrypted,
+ kDeprecatedFailedRecreateEncrypted,
// Could not add entries into the temporary encrypted database.
kFailedWriteToEncrypted,
kMaxValue = kFailedWriteToEncrypted
@@ -366,6 +462,24 @@ void LogUpdateUIDismissalReason(UIDismissalReason reason);
// conflict during generation.
void LogPresavedUpdateUIDismissalReason(UIDismissalReason reason);
+// Log the |type| of a leak dialog shown to the user and the |reason| why it was
+// dismissed.
+void LogLeakDialogTypeAndDismissalReason(LeakDialogType type,
+ LeakDialogDismissalReason reason);
+
+// Log the current onboarding |state| of the user.
+void LogOnboardingState(OnboardingState state);
+
+// Log the |reason| a user dismissed the onboarding UI.
+void LogOnboardingUIDismissalReason(OnboardingUIDismissalReason reason);
+
+// Log the |result| of the password saving flow.
+void LogResultOfSavingFlow(OnboardingResultOfSavingFlow result);
+
+// Log the |result| of the password saving flow if the onboarding was shown in
+// the process.
+void LogResultOfOnboardingSavingFlow(OnboardingResultOfSavingFlow result);
+
// Log the appropriate display disposition.
void LogUIDisplayDisposition(UIDisplayDisposition disposition);
@@ -462,8 +576,9 @@ void LogGenerationDialogChoice(
void LogGenerationPresaveConflict(GenerationPresaveConflict value);
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
-// Log a save sync password change event.
-void LogSyncPasswordHashChange(SyncPasswordHashChange event);
+// Log a save gaia password change event.
+void LogGaiaPasswordHashChange(GaiaPasswordHashChange event,
+ bool is_sync_password);
// Log whether a sync password hash saved.
void LogIsSyncPasswordHashSaved(IsSyncPasswordHashSaved state,
diff --git a/chromium/components/password_manager/core/browser/password_manager_onboarding.cc b/chromium/components/password_manager/core/browser/password_manager_onboarding.cc
new file mode 100644
index 00000000000..21b383ba62b
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/password_manager_onboarding.cc
@@ -0,0 +1,170 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
+
+#include "base/feature_list.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
+
+namespace password_manager {
+
+namespace {
+// Functions converting UIDismissalReasons for the save password
+// infobar and the onboarding dialog into values of the
+// |OnboardingResultOfSavingFlow| enum.
+metrics_util::OnboardingResultOfSavingFlow FlowResultFromInfobarDismissalReason(
+ const metrics_util::UIDismissalReason reason) {
+ switch (reason) {
+ case metrics_util::UIDismissalReason::NO_DIRECT_INTERACTION:
+ return metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarNoDirectInteraction;
+ case metrics_util::UIDismissalReason::CLICKED_SAVE:
+ return metrics_util::OnboardingResultOfSavingFlow::kInfobarClickedSave;
+ case metrics_util::UIDismissalReason::CLICKED_CANCEL:
+ return metrics_util::OnboardingResultOfSavingFlow::kInfobarClickedCancel;
+ case metrics_util::UIDismissalReason::CLICKED_NEVER:
+ return metrics_util::OnboardingResultOfSavingFlow::kInfobarClickedNever;
+ default:
+ NOTREACHED();
+ return metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarNoDirectInteraction;
+ }
+}
+
+metrics_util::OnboardingResultOfSavingFlow
+FlowResultFromOnboardingDismissalReason(
+ const metrics_util::OnboardingUIDismissalReason reason) {
+ switch (reason) {
+ case metrics_util::OnboardingUIDismissalReason::kRejected:
+ return metrics_util::OnboardingResultOfSavingFlow::kOnboardingRejected;
+ case metrics_util::OnboardingUIDismissalReason::kDismissed:
+ return metrics_util::OnboardingResultOfSavingFlow::kOnboardingDismissed;
+ default:
+ NOTREACHED();
+ return metrics_util::OnboardingResultOfSavingFlow::kOnboardingRejected;
+ }
+}
+} // namespace
+
+using OnboardingState = password_manager::metrics_util::OnboardingState;
+
+OnboardingStateUpdate::OnboardingStateUpdate(
+ scoped_refptr<password_manager::PasswordStore> store,
+ PrefService* prefs)
+ : store_(std::move(store)), prefs_(prefs) {}
+
+void OnboardingStateUpdate::Start() {
+ store_->GetAutofillableLogins(this);
+}
+
+OnboardingStateUpdate::~OnboardingStateUpdate() = default;
+
+void OnboardingStateUpdate::UpdateState(
+ std::vector<std::unique_ptr<autofill::PasswordForm>> credentials) {
+ if (credentials.size() >= kOnboardingCredentialsThreshold) {
+ if (prefs_->GetInteger(prefs::kPasswordManagerOnboardingState) ==
+ static_cast<int>(OnboardingState::kShouldShow)) {
+ prefs_->SetInteger(prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kDoNotShow));
+ }
+ return;
+ }
+ if (prefs_->GetInteger(
+ password_manager::prefs::kPasswordManagerOnboardingState) ==
+ static_cast<int>(OnboardingState::kDoNotShow)) {
+ prefs_->SetInteger(prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShouldShow));
+ }
+}
+
+void OnboardingStateUpdate::OnGetPasswordStoreResults(
+ std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
+ UpdateState(std::move(results));
+ delete this;
+}
+
+// Initializes and runs the OnboardingStateUpdate class, which is
+// used to update the |kPasswordManagerOnboardingState| pref.
+void StartOnboardingStateUpdate(
+ scoped_refptr<password_manager::PasswordStore> store,
+ PrefService* prefs) {
+ (new OnboardingStateUpdate(store, prefs))->Start();
+}
+
+void UpdateOnboardingState(scoped_refptr<password_manager::PasswordStore> store,
+ PrefService* prefs,
+ base::TimeDelta delay) {
+ if (prefs->GetInteger(prefs::kPasswordManagerOnboardingState) ==
+ static_cast<int>(OnboardingState::kShown)) {
+ return;
+ }
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&StartOnboardingStateUpdate, store, prefs),
+ delay);
+}
+
+bool ShouldShowOnboarding(PrefService* prefs,
+ PasswordUpdateBool is_password_update,
+ BlacklistedBool is_blacklisted,
+ SyncState sync_state) {
+ if (sync_state == NOT_SYNCING) {
+ return false;
+ }
+ if (is_blacklisted) {
+ return false;
+ }
+ if (is_password_update) {
+ return false;
+ }
+
+ int pref_value = prefs->GetInteger(
+ password_manager::prefs::kPasswordManagerOnboardingState);
+
+ bool should_show =
+ (pref_value == static_cast<int>(OnboardingState::kShouldShow));
+ bool already_shown =
+ (pref_value == static_cast<int>(OnboardingState::kShown));
+ bool is_eligible = should_show || already_shown;
+
+ if (!is_eligible) {
+ return false;
+ }
+
+ // It is very important that the feature is checked only for eligible users.
+ // otherwise the data will be diluted. It's also important that the feature is
+ // checked in all eligible cases, even if the onboarding prompt was shown,
+ // otherwise the data will be incomplete.
+ if (!base::FeatureList::IsEnabled(
+ password_manager::features::kPasswordManagerOnboardingAndroid)) {
+ return false;
+ }
+ return should_show;
+}
+
+SavingFlowMetricsRecorder::SavingFlowMetricsRecorder() = default;
+
+SavingFlowMetricsRecorder::~SavingFlowMetricsRecorder() {
+ metrics_util::LogResultOfSavingFlow(flow_result_);
+ if (onboarding_shown_) {
+ metrics_util::LogResultOfOnboardingSavingFlow(flow_result_);
+ }
+}
+
+void SavingFlowMetricsRecorder::SetOnboardingShown() {
+ onboarding_shown_ = true;
+}
+
+void SavingFlowMetricsRecorder::SetFlowResult(
+ metrics_util::UIDismissalReason reason) {
+ flow_result_ = FlowResultFromInfobarDismissalReason(reason);
+}
+
+void SavingFlowMetricsRecorder::SetFlowResult(
+ metrics_util::OnboardingUIDismissalReason reason) {
+ flow_result_ = FlowResultFromOnboardingDismissalReason(reason);
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_manager_onboarding.h b/chromium/components/password_manager/core/browser/password_manager_onboarding.h
new file mode 100644
index 00000000000..1e2ad43677a
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/password_manager_onboarding.h
@@ -0,0 +1,122 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_ONBOARDING_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_ONBOARDING_H_
+
+#include "base/util/type_safety/strong_alias.h"
+#include "components/password_manager/core/browser/password_manager_client.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/password_store_consumer.h"
+
+class PrefService;
+
+namespace password_manager {
+
+using PasswordUpdateBool = util::StrongAlias<class PasswordUpdateBoolTag, bool>;
+using BlacklistedBool = util::StrongAlias<class BlacklistedBoolTag, bool>;
+
+// The onboarding won't be shown if there are this many
+// saved credentials or more.
+constexpr int kOnboardingCredentialsThreshold = 3;
+
+// This utility class is responsible for updating the
+// |kPasswordManagerOnboardingState| pref, for later use in the triggering logic
+// for the onboarding.
+// Important note: The object will delete itself once it
+// receives the results from the password store, thus it should not be allocated
+// on the stack. Having a non-public destructor enforces this.
+class OnboardingStateUpdate : public password_manager::PasswordStoreConsumer {
+ public:
+ OnboardingStateUpdate(scoped_refptr<password_manager::PasswordStore> store,
+ PrefService* prefs);
+
+ // Requests all autofillable credentials from PasswordStore.
+ void Start();
+
+ private:
+ ~OnboardingStateUpdate() override;
+
+ // Update the |kPasswordManagerOnboardingState| pref to represent the right
+ // state.
+ // - |kDoNotShow| -> |kShouldShow| (if credentials count < threshold)
+ // - |kShouldShow| -> |kDoNotShow| (if credentials count >= threshold)
+ void UpdateState(
+ std::vector<std::unique_ptr<autofill::PasswordForm>> credentials);
+
+ // PasswordStoreConsumer:
+ // When the results are obtained updates the pref and deletes
+ // itself.
+ void OnGetPasswordStoreResults(
+ std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
+
+ scoped_refptr<password_manager::PasswordStore> store_;
+
+ // |prefs_| is not an owning pointer.
+ // It is used to update the |kPasswordManagerOnboardingState| pref.
+ PrefService* prefs_;
+
+ DISALLOW_COPY_AND_ASSIGN(OnboardingStateUpdate);
+};
+
+// This function updates the |kPasswordManagerOnboardingState| pref on
+// a separate thread after a given time delay.
+// Runs if the state is not |kShown|.
+void UpdateOnboardingState(scoped_refptr<password_manager::PasswordStore> store,
+ PrefService* prefs,
+ base::TimeDelta delay);
+
+// Return true if the password manager onboarding experience should be shown to
+// the user. Conditions (all must apply):
+// 1. The user is syncing passwords. This is a temporary cutoff to allow
+// us to experiment with different strings talking about features
+// available when syncing.
+// 2. The set of credentials is not blacklisted.
+// 3. We are dealing with a new set of credentials.
+// 4. |kPasswordManagerOnboardingState| is |kShouldShow|.
+// 5. The PasswordManagerOnboardingAndroid feature is enabled.
+bool ShouldShowOnboarding(PrefService* prefs,
+ PasswordUpdateBool is_password_update,
+ BlacklistedBool is_blacklisted,
+ SyncState sync_state);
+
+// This utility class is responsible for recording the result of the
+// saving flow into the following metrics:
+// - "PasswordManager.Onboarding.ResultOfSavingFlow"
+// - "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding"
+// They are recorded upon deletion of this class.
+// The second metric is only recorded if the onboarding was shown
+// during the flow, which is indicated by |onboarding_shown_|.
+class SavingFlowMetricsRecorder {
+ public:
+ SavingFlowMetricsRecorder();
+
+ // Records the metrics before destruction.
+ ~SavingFlowMetricsRecorder();
+
+ // This is called to indicate that the onboarding was shown.
+ void SetOnboardingShown();
+
+ // Functions called to store the outcome of the saving flow.
+ // Accepts the following reasons for dismissing the infobar:
+ // NO_DIRECT_INTERACTION, CLICKED_SAVE, CLICKED_CANCEL and CLICKED_NEVER.
+ void SetFlowResult(metrics_util::UIDismissalReason reason);
+ // Accepts the following reasons for dismissing the onboarding dialog:
+ // kRejected and kDismissed.
+ void SetFlowResult(metrics_util::OnboardingUIDismissalReason reason);
+
+ private:
+ // Boolean indicating if the onboarding was shown in the flow.
+ bool onboarding_shown_ = false;
+ // Enum indicating the outcome of the password saving flow.
+ metrics_util::OnboardingResultOfSavingFlow flow_result_ =
+ metrics_util::OnboardingResultOfSavingFlow::kInfobarNoDirectInteraction;
+
+ DISALLOW_COPY_AND_ASSIGN(SavingFlowMetricsRecorder);
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_ONBOARDING_H_
diff --git a/chromium/components/password_manager/core/browser/password_manager_onboarding_unittest.cc b/chromium/components/password_manager/core/browser/password_manager_onboarding_unittest.cc
new file mode 100644
index 00000000000..4341da3323e
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/password_manager_onboarding_unittest.cc
@@ -0,0 +1,389 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using autofill::PasswordForm;
+using base::ASCIIToUTF16;
+
+namespace password_manager {
+
+using OnboardingState = metrics_util::OnboardingState;
+
+class PasswordManagerOnboardingTest : public testing::Test {
+ public:
+ PasswordManagerOnboardingTest() = default;
+
+ void SetUp() override {
+ store_ = new TestPasswordStore;
+ store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
+
+ prefs_.reset(new TestingPrefServiceSimple());
+ prefs_->registry()->RegisterIntegerPref(
+ prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kDoNotShow));
+ }
+
+ void TearDown() override {
+ store_->ShutdownOnUIThread();
+
+ // It's needed to cleanup the password store asynchronously.
+ RunAllPendingTasks();
+ }
+
+ PrefService* GetPrefs() { return prefs_.get(); }
+
+ void RunAllPendingTasks() { task_environment_.RunUntilIdle(); }
+
+ PasswordForm MakeSimpleForm(int id) {
+ PasswordForm form;
+ form.origin = GURL("https://example.org/");
+ form.signon_realm = "https://example.org/";
+ form.username_value = ASCIIToUTF16("username") + base::NumberToString16(id);
+ form.password_value = ASCIIToUTF16("p4ssword") + base::NumberToString16(id);
+ return form;
+ }
+
+ PasswordForm MakeSimpleBlacklistedForm(int id) {
+ PasswordForm form;
+ std::string link = "https://example" + base::NumberToString(id) + ".org/";
+ form.origin = GURL(link);
+ form.signon_realm = link;
+ form.blacklisted_by_user = true;
+ return form;
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ scoped_refptr<TestPasswordStore> store_;
+ std::unique_ptr<TestingPrefServiceSimple> prefs_;
+};
+
+TEST_F(PasswordManagerOnboardingTest, CredentialsCountUnderThreshold) {
+ // Check that the count of credentials is handled correctly.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ for (int id = 0; id < kOnboardingCredentialsThreshold - 1; ++id) {
+ store_->AddLogin(MakeSimpleForm(id));
+ }
+ constexpr int kNumberOfBlacklistedLogins = 5;
+ for (int id = 0; id < kNumberOfBlacklistedLogins; ++id) {
+ store_->AddLogin(MakeSimpleBlacklistedForm(id));
+ }
+ RunAllPendingTasks();
+ UpdateOnboardingState(store_, GetPrefs(), base::TimeDelta::FromSeconds(0));
+ RunAllPendingTasks();
+ EXPECT_EQ(prefs_->GetInteger(prefs::kPasswordManagerOnboardingState),
+ static_cast<int>(OnboardingState::kShouldShow));
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ CredentialsCountThresholdHitAfterDoNotShow) {
+ // Check that the threshold is handled correctly.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ for (int id = 0; id < kOnboardingCredentialsThreshold; ++id) {
+ store_->AddLogin(MakeSimpleForm(id));
+ }
+ RunAllPendingTasks();
+ UpdateOnboardingState(store_, GetPrefs(), base::TimeDelta::FromSeconds(0));
+ RunAllPendingTasks();
+ EXPECT_EQ(prefs_->GetInteger(prefs::kPasswordManagerOnboardingState),
+ static_cast<int>(OnboardingState::kDoNotShow));
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ CredentialsCountThresholdHitAfterShouldShow) {
+ // Check that the threshold is handled correctly
+ // in case the current state is |kShouldShow|.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShouldShow));
+ for (int id = 0; id < kOnboardingCredentialsThreshold; ++id) {
+ store_->AddLogin(MakeSimpleForm(id));
+ }
+ RunAllPendingTasks();
+ UpdateOnboardingState(store_, GetPrefs(), base::TimeDelta::FromSeconds(0));
+ RunAllPendingTasks();
+ EXPECT_EQ(prefs_->GetInteger(prefs::kPasswordManagerOnboardingState),
+ static_cast<int>(OnboardingState::kDoNotShow));
+}
+
+TEST_F(PasswordManagerOnboardingTest, CredentialsCountThresholdHitAfterShown) {
+ // Check that the threshold is handled correctly
+ // in case the current state is |kShown|.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShown));
+ for (int id = 0; id < kOnboardingCredentialsThreshold; ++id) {
+ store_->AddLogin(MakeSimpleForm(id));
+ }
+ RunAllPendingTasks();
+ UpdateOnboardingState(store_, GetPrefs(), base::TimeDelta::FromSeconds(0));
+ RunAllPendingTasks();
+ EXPECT_EQ(prefs_->GetInteger(prefs::kPasswordManagerOnboardingState),
+ static_cast<int>(OnboardingState::kShown));
+}
+
+TEST_F(PasswordManagerOnboardingTest, DoNotShowAfterShown) {
+ // If the current state is |kShown| it should stay this way,
+ // so that the onboarding won't be shown twice.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShown));
+ UpdateOnboardingState(store_, GetPrefs(), base::TimeDelta::FromSeconds(0));
+ RunAllPendingTasks();
+ EXPECT_EQ(prefs_->GetInteger(prefs::kPasswordManagerOnboardingState),
+ static_cast<int>(OnboardingState::kShown));
+}
+
+TEST_F(PasswordManagerOnboardingTest, FeatureDisabledAfterShowing) {
+ prefs_->SetInteger(prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShown));
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ UpdateOnboardingState(store_, GetPrefs(), base::TimeDelta::FromSeconds(0));
+ RunAllPendingTasks();
+ EXPECT_EQ(prefs_->GetInteger(prefs::kPasswordManagerOnboardingState),
+ static_cast<int>(OnboardingState::kShown));
+}
+
+TEST_F(PasswordManagerOnboardingTest, ShouldShowOnboardingState) {
+ // Check that the |kPasswordManagerOnboardingState| pref is handled correctly.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ password_manager::features::kPasswordManagerOnboardingAndroid);
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(false),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+
+ prefs_->SetInteger(password_manager::prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShouldShow));
+ EXPECT_TRUE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(false),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+
+ prefs_->SetInteger(password_manager::prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kDoNotShow));
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(false),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+
+ prefs_->SetInteger(password_manager::prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShown));
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(false),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+}
+
+TEST_F(PasswordManagerOnboardingTest, ShouldShowOnboardingFeatureDisabled) {
+ // Feature disabled ==> don't show.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(password_manager::prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(OnboardingState::kShouldShow));
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(false),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+}
+
+TEST_F(PasswordManagerOnboardingTest, ShouldShowOnboardingPasswordUpdate) {
+ // Password update ==> don't show.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ password_manager::features::kPasswordManagerOnboardingAndroid);
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(true),
+ BlacklistedBool(false),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ ShouldShowOnboardingBlacklistedCredentials) {
+ // Blacklisted credentials ==> don't show.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ password_manager::features::kPasswordManagerOnboardingAndroid);
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(true),
+ SyncState::SYNCING_NORMAL_ENCRYPTION));
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ ShouldShowOnboardingPasswordSyncDisabled) {
+ // Password sync disabled ==> don't show.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ password_manager::features::kPasswordManagerOnboardingAndroid);
+ EXPECT_FALSE(ShouldShowOnboarding(GetPrefs(), PasswordUpdateBool(false),
+ BlacklistedBool(false),
+ SyncState::NOT_SYNCING));
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderInfobarNoDirectInteraction) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetFlowResult(password_manager::metrics_util::UIDismissalReason::
+ NO_DIRECT_INTERACTION);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarNoDirectInteraction,
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderInfobarClickedSave) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetFlowResult(
+ password_manager::metrics_util::UIDismissalReason::CLICKED_SAVE);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarClickedSave,
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderInfobarClickedCancel) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetFlowResult(
+ password_manager::metrics_util::UIDismissalReason::CLICKED_CANCEL);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarClickedCancel,
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderInfobarClickedNever) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetFlowResult(
+ password_manager::metrics_util::UIDismissalReason::CLICKED_NEVER);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarClickedNever,
+ 1);
+ histogram_tester.ExpectTotalCount(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderOnboardingRejected) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetOnboardingShown();
+ recorder.SetFlowResult(
+ password_manager::metrics_util::OnboardingUIDismissalReason::kRejected);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kOnboardingRejected,
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kOnboardingRejected,
+ 1);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderOnboardingDismissed) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetOnboardingShown();
+ recorder.SetFlowResult(password_manager::metrics_util::
+ OnboardingUIDismissalReason::kDismissed);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kOnboardingDismissed,
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kOnboardingDismissed,
+ 1);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+ SavingFlowMetricsRecorderAfterOnboarding) {
+ base::HistogramTester histogram_tester;
+ {
+ SavingFlowMetricsRecorder recorder;
+ recorder.SetOnboardingShown();
+ recorder.SetFlowResult(
+ password_manager::metrics_util::UIDismissalReason::CLICKED_SAVE);
+ }
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlow",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarClickedSave,
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding",
+ password_manager::metrics_util::OnboardingResultOfSavingFlow::
+ kInfobarClickedSave,
+ 1);
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_manager_test_utils.cc b/chromium/components/password_manager/core/browser/password_manager_test_utils.cc
index 20ee9ab4008..bd5df04fee0 100644
--- a/chromium/components/password_manager/core/browser/password_manager_test_utils.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_test_utils.cc
@@ -24,6 +24,7 @@ std::unique_ptr<PasswordForm> PasswordFormFromData(
auto form = std::make_unique<PasswordForm>();
form->scheme = form_data.scheme;
form->preferred = form_data.preferred;
+ form->date_last_used = base::Time::FromDoubleT(form_data.last_usage_time);
form->date_created = base::Time::FromDoubleT(form_data.creation_time);
if (form_data.signon_realm)
form->signon_realm = std::string(form_data.signon_realm);
diff --git a/chromium/components/password_manager/core/browser/password_manager_test_utils.h b/chromium/components/password_manager/core/browser/password_manager_test_utils.h
index 6f40e9f92d3..aefa8aa3445 100644
--- a/chromium/components/password_manager/core/browser/password_manager_test_utils.h
+++ b/chromium/components/password_manager/core/browser/password_manager_test_utils.h
@@ -48,6 +48,7 @@ struct PasswordFormData {
const wchar_t* username_value; // Set to NULL for a blacklist entry.
const wchar_t* password_value;
const bool preferred;
+ const double last_usage_time;
const double creation_time;
};
diff --git a/chromium/components/password_manager/core/browser/password_manager_unittest.cc b/chromium/components/password_manager/core/browser/password_manager_unittest.cc
index 9ecc16785b5..e098b9a4790 100644
--- a/chromium/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_unittest.cc
@@ -4,6 +4,7 @@
#include "components/password_manager/core/browser/password_manager.h"
+#include <limits>
#include <memory>
#include <string>
#include <utility>
@@ -12,22 +13,28 @@
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/optional.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/password_manager/core/browser/form_fetcher_impl.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
#include "components/password_manager/core/browser/mock_password_store.h"
-#include "components/password_manager/core/browser/new_password_form_manager.h"
#include "components/password_manager/core/browser/password_autofill_manager.h"
+#include "components/password_manager/core/browser/password_bubble_experiment.h"
+#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/statistics_table.h"
#include "components/password_manager/core/browser/stub_credentials_filter.h"
@@ -35,15 +42,21 @@
#include "components/password_manager/core/browser/stub_password_manager_driver.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_registry.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "net/cert/cert_status_flags.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using autofill::FormData;
using autofill::FormFieldData;
+using autofill::FormStructure;
using autofill::PasswordForm;
using autofill::PasswordFormFillData;
using autofill::mojom::PasswordFormFieldPredictionType;
@@ -52,6 +65,7 @@ using base::Feature;
using base::TestMockTimeTaskRunner;
using testing::_;
using testing::AnyNumber;
+using testing::ByMove;
using testing::Invoke;
using testing::IsNull;
using testing::Mock;
@@ -78,6 +92,20 @@ MATCHER_P(FormIgnoreDate, expected, "") {
return arg == expected_with_date;
}
+class MockLeakDetectionCheck : public LeakDetectionCheck {
+ public:
+ MOCK_METHOD3(Start, void(const GURL&, base::string16, base::string16));
+};
+
+class MockLeakDetectionCheckFactory : public LeakDetectionCheckFactory {
+ public:
+ MOCK_CONST_METHOD3(TryCreateLeakCheck,
+ std::unique_ptr<LeakDetectionCheck>(
+ LeakDetectionDelegateInterface*,
+ signin::IdentityManager*,
+ scoped_refptr<network::SharedURLLoaderFactory>));
+};
+
class MockStoreResultFilter : public StubCredentialsFilter {
public:
MOCK_CONST_METHOD1(ShouldSave, bool(const autofill::PasswordForm& form));
@@ -113,6 +141,7 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
// ShowManualFallbackForSavingPtr owns the PasswordFormManager* argument.
MOCK_METHOD1(PromptUserToSaveOrUpdatePasswordPtr,
void(PasswordFormManagerForUI*));
+ MOCK_METHOD1(ShowOnboarding, bool(std::unique_ptr<PasswordFormManagerForUI>));
MOCK_METHOD3(ShowManualFallbackForSavingPtr,
void(PasswordFormManagerForUI*, bool, bool));
MOCK_METHOD0(HideManualFallbackForSaving, void());
@@ -125,6 +154,7 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
MOCK_CONST_METHOD0(GetStoreResultFilter, const MockStoreResultFilter*());
MOCK_METHOD0(GetMetricsRecorder, PasswordManagerMetricsRecorder*());
MOCK_CONST_METHOD0(IsNewTabPage, bool());
+ MOCK_CONST_METHOD0(GetPasswordSyncState, SyncState());
// Workaround for std::unique_ptr<> lacking a copy constructor.
bool PromptUserToSaveOrUpdatePassword(
@@ -133,6 +163,7 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
PromptUserToSaveOrUpdatePasswordPtr(manager.release());
return false;
}
+
void ShowManualFallbackForSaving(
std::unique_ptr<PasswordFormManagerForUI> manager,
bool has_generated_password,
@@ -155,6 +186,8 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
class MockPasswordManagerDriver : public StubPasswordManagerDriver {
public:
+ MOCK_METHOD1(FormEligibleForGenerationFound,
+ void(const autofill::PasswordFormGenerationData&));
MOCK_METHOD1(FillPasswordForm, void(const autofill::PasswordFormFillData&));
MOCK_METHOD1(AutofillDataReceived,
void(const autofill::FormsPredictionsMap&));
@@ -278,11 +311,19 @@ class PasswordManagerTest : public testing::Test {
ON_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _))
.WillByDefault(WithArg<0>(DeletePtr()));
+ prefs_.reset(new TestingPrefServiceSimple());
+ prefs_->registry()->RegisterIntegerPref(
+ prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(metrics_util::OnboardingState::kDoNotShow));
+ prefs_->registry()->RegisterBooleanPref(
+ prefs::kPasswordLeakDetectionEnabled, true);
+ ON_CALL(client_, GetPrefs()).WillByDefault(Return(prefs_.get()));
+
// When waiting for predictions is on, it makes tests more complicated.
// Disable waiting, since most tests have nothing to do with predictions.
// All tests that test working with prediction should explicitly turn
// predictions on.
- NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false);
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(false);
}
void TearDown() override {
@@ -290,7 +331,7 @@ class PasswordManagerTest : public testing::Test {
store_ = nullptr;
}
- PasswordForm MakeSimpleForm() {
+ PasswordForm MakeSavedForm() {
PasswordForm form;
form.origin = GURL("http://www.google.com/a/LoginAuth");
form.action = GURL("http://www.google.com/a/Login");
@@ -300,6 +341,11 @@ class PasswordManagerTest : public testing::Test {
form.password_value = ASCIIToUTF16("p4ssword");
form.submit_element = ASCIIToUTF16("signIn");
form.signon_realm = "http://www.google.com/";
+ return form;
+ }
+
+ PasswordForm MakeSimpleForm() {
+ auto form = MakeSavedForm();
// Fill |form.form_data|.
form.form_data.url = form.origin;
@@ -441,49 +487,15 @@ class PasswordManagerTest : public testing::Test {
manager()->OnPasswordFormSubmitted(&driver_, form);
}
- void TurnOnNewParsingForFilling(
- base::test::ScopedFeatureList* scoped_feature_list,
- bool enabled) {
- std::vector<Feature> enabled_features;
- std::vector<Feature> disabled_features;
- (enabled ? enabled_features : disabled_features) =
- std::vector<Feature>({features::kNewPasswordFormParsing});
-
- disabled_features.push_back(features::kNewPasswordFormParsingForSaving);
- disabled_features.push_back(features::kOnlyNewParser);
- scoped_feature_list->InitWithFeatures(enabled_features, disabled_features);
- manager_.reset(new PasswordManager(&client_));
- }
-
- void TurnOnNewParsingForSaving(
- base::test::ScopedFeatureList* scoped_feature_list,
- bool enabled) {
- std::vector<Feature> enabled_features;
- std::vector<Feature> disabled_features;
- (enabled ? enabled_features : disabled_features) =
- std::vector<Feature>({features::kNewPasswordFormParsing,
- features::kNewPasswordFormParsingForSaving});
- scoped_feature_list->InitWithFeatures(enabled_features, disabled_features);
-
- manager_.reset(new PasswordManager(&client_));
- }
-
- void TurnOnOnlyNewParser(base::test::ScopedFeatureList* scoped_feature_list) {
- scoped_feature_list->InitWithFeatures(
- {features::kNewPasswordFormParsing,
- features::kNewPasswordFormParsingForSaving, features::kOnlyNewParser},
- {});
- manager_.reset(new PasswordManager(&client_));
- }
-
const GURL test_url_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<MockPasswordStore> store_;
testing::NiceMock<MockPasswordManagerClient> client_;
MockPasswordManagerDriver driver_;
std::unique_ptr<PasswordAutofillManager> password_autofill_manager_;
std::unique_ptr<PasswordManager> manager_;
scoped_refptr<TestMockTimeTaskRunner> task_runner_;
+ std::unique_ptr<TestingPrefServiceSimple> prefs_;
};
MATCHER_P(FormMatches, form, "") {
@@ -536,11 +548,6 @@ TEST_F(PasswordManagerTest, FormSubmitWithOnlyNewPasswordField) {
}
TEST_F(PasswordManagerTest, GeneratedPasswordFormSubmitEmptyStore) {
- for (bool new_parsing_for_saving : {false, true}) {
- SCOPED_TRACE(testing::Message()
- << "new_parsing_for_saving = " << new_parsing_for_saving);
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving);
// Test that generated passwords are stored without asking the user.
std::vector<PasswordForm> observed;
PasswordForm form(MakeFormWithOnlyNewPasswordField());
@@ -576,13 +583,10 @@ TEST_F(PasswordManagerTest, GeneratedPasswordFormSubmitEmptyStore) {
// What was "new password" field in the submitted form, becomes the current
// password field in the form to save.
EXPECT_EQ(form.new_password_value, form_to_save.password_value);
- }
}
#if defined(OS_IOS)
TEST_F(PasswordManagerTest, EditingGeneratedPasswordOnIOS) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -632,8 +636,6 @@ TEST_F(PasswordManagerTest, EditingGeneratedPasswordOnIOS) {
}
TEST_F(PasswordManagerTest, SavingGeneratedPasswordOnIOS) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -676,8 +678,6 @@ TEST_F(PasswordManagerTest, SavingGeneratedPasswordOnIOS) {
}
TEST_F(PasswordManagerTest, PasswordNoLongerGeneratedOnIOS) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -739,127 +739,6 @@ TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) {
form_manager_to_save->Save();
}
-#if !defined(OS_IOS)
-TEST_F(PasswordManagerTest, BestMatchFormToManager) {
- base::test::ScopedFeatureList scoped_feature_list;
- // This test does not make sense for NewPasswordFormManager:
- // 1.Only renderer ids are used for matching.
- // 2.If no matched form manager is found, then new one is created.
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
-
- std::vector<PasswordForm> observed;
- // Observe the form that will be submitted.
- PasswordForm form(MakeSimpleForm());
-
- // This form is different from the on that will be submitted.
- PasswordForm no_match_form(MakeSimpleForm());
- no_match_form.form_data.name = ASCIIToUTF16("another-name");
- no_match_form.action = GURL("http://www.google.com/somethingelse");
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("another-field-name");
- no_match_form.form_data.fields.push_back(field);
-
- observed.push_back(no_match_form);
- observed.push_back(form);
-
- // Simulate observing forms after navigation the page.
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- // The form is modified before being submitted and does not match perfectly.
- // Out of the criteria {name, action, signature}, we keep the signature the
- // same and change the rest.
- PasswordForm changed_form(form);
- changed_form.username_element = ASCIIToUTF16("changed-name");
- changed_form.action = GURL("http://www.google.com/changed-action");
- OnPasswordFormSubmitted(changed_form);
- EXPECT_EQ(CalculateFormSignature(form.form_data),
- CalculateFormSignature(changed_form.form_data));
-
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-
- // Now the password manager waits for the navigation to complete.
- observed.clear();
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Verify that PasswordFormManager to be save owns the correct pair of
- // observed and submitted forms.
- // TODO(https://crbug.com/831123): Implement subsequent expectation with
- // PasswordFormManagerInterface and avoid casting to PasswordFormManager*.
- PasswordFormManager* form_manager =
- static_cast<PasswordFormManager*>(form_manager_to_save.get());
- EXPECT_EQ(form.action, form_manager->observed_form().action);
- EXPECT_EQ(form.form_data.name, form_manager->observed_form().form_data.name);
- EXPECT_EQ(changed_form.action, form_manager->GetSubmittedForm()->action);
- EXPECT_EQ(changed_form.form_data.name,
- form_manager->GetSubmittedForm()->form_data.name);
-}
-
-// As long as the is a PasswordFormManager that matches the origin, we should
-// not fail to match a submitted PasswordForm to a PasswordFormManager.
-TEST_F(PasswordManagerTest, AnyMatchFormToManager) {
- // This test does not make sense for NewPasswordFormManager, because it has a
- // different behaviour, instead of taken any form manager new one is created.
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
-
- // Observe the form that will be submitted.
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
-
- // Simulate observing forms after navigation the page.
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- // The form is modified before being submitted and does not match perfectly.
- // We change all of the criteria: {name, action, signature}.
- PasswordForm changed_form(form);
- autofill::FormFieldData field;
- field.name = ASCIIToUTF16("another-field-name");
- changed_form.form_data.fields.push_back(field);
- changed_form.username_element = ASCIIToUTF16("changed-name");
- changed_form.action = GURL("http://www.google.com/changed-action");
- OnPasswordFormSubmitted(changed_form);
- EXPECT_NE(CalculateFormSignature(form.form_data),
- CalculateFormSignature(changed_form.form_data));
-
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-
- // Now the password manager waits for the navigation to complete.
- observed.clear();
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Verify that we matched the form to a PasswordFormManager, although with the
- // worst possible match.
- // TODO(https://crbug.com/831123): Implement subsequent expectation with
- // PasswordFormManagerInterface and avoid casting to PasswordFormManager*.
- PasswordFormManager* form_manager =
- static_cast<PasswordFormManager*>(form_manager_to_save.get());
- EXPECT_EQ(form.action, form_manager->observed_form().action);
- EXPECT_EQ(form.form_data.name, form_manager->observed_form().form_data.name);
- EXPECT_EQ(changed_form.action, form_manager->GetSubmittedForm()->action);
- EXPECT_EQ(changed_form.form_data.name,
- form_manager->GetSubmittedForm()->form_data.name);
-}
-#endif
-
// Tests that a credential wouldn't be saved if it is already in the store.
TEST_F(PasswordManagerTest, DontSaveAlreadySavedCredential) {
PasswordForm form(MakeSimpleForm());
@@ -1021,9 +900,113 @@ TEST_F(PasswordManagerTest, FormSubmit) {
form_manager_to_save->Save();
}
+TEST_F(PasswordManagerTest, OnboardingSimple) {
+ // Test that a plain form submit results in showing the onboarding
+ // if the |kShouldShow| state is set.
+ ON_CALL(client_, GetPasswordSyncState())
+ .WillByDefault(Return(SyncState::SYNCING_NORMAL_ENCRYPTION));
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(
+ prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(metrics_util::OnboardingState::kShouldShow));
+
+ PasswordForm form(MakeSimpleForm());
+ std::vector<PasswordForm> observed = {form};
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
+ .WillRepeatedly(Return(true));
+ OnPasswordFormSubmitted(form);
+
+ EXPECT_CALL(client_, ShowOnboarding(_));
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+
+ observed.clear();
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+}
+
+TEST_F(PasswordManagerTest, OnboardingPasswordSyncDisabled) {
+ // Tests that the onboarding is not shown when password sync is disabled.
+ ON_CALL(client_, GetPasswordSyncState()).WillByDefault(Return(NOT_SYNCING));
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(
+ prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(metrics_util::OnboardingState::kShouldShow));
+
+ PasswordForm form(MakeSimpleForm());
+ std::vector<PasswordForm> observed = {form};
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
+ .WillRepeatedly(Return(true));
+ OnPasswordFormSubmitted(form);
+
+ EXPECT_CALL(client_, ShowOnboarding(_)).Times(0);
+ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+
+ observed.clear();
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+}
+
+TEST_F(PasswordManagerTest, OnboardingPasswordUpdate) {
+ // Tests that the onboarding is not shown on password update.
+ ON_CALL(client_, GetPasswordSyncState())
+ .WillByDefault(Return(SYNCING_NORMAL_ENCRYPTION));
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kPasswordManagerOnboardingAndroid);
+ prefs_->SetInteger(
+ prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(metrics_util::OnboardingState::kShouldShow));
+
+ PasswordForm observed_form(MakeSimpleForm());
+ std::vector<PasswordForm> observed_forms = {observed_form};
+
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2);
+ // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when
+ // the old parser is gone.
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeConsumer(MakeSavedForm())));
+ manager()->OnPasswordFormsParsed(&driver_, observed_forms);
+ manager()->OnPasswordFormsRendered(&driver_, observed_forms, true);
+
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(observed_form.origin))
+ .WillRepeatedly(Return(true));
+
+ PasswordForm filled_form(observed_form);
+ filled_form.form_data.fields[0].value = filled_form.username_value;
+ filled_form.password_value = ASCIIToUTF16("new_password");
+ filled_form.form_data.fields[1].value = filled_form.password_value;
+ OnPasswordFormSubmitted(filled_form);
+
+ EXPECT_CALL(client_, ShowOnboarding(_)).Times(0);
+ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+
+ observed_forms.clear();
+ manager()->DidNavigateMainFrame(true);
+ manager()->OnPasswordFormsParsed(&driver_, observed_forms);
+ manager()->OnPasswordFormsRendered(&driver_, observed_forms, true);
+}
+
TEST_F(PasswordManagerTest, IsPasswordFieldDetectedOnPage) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnOnlyNewParser(&scoped_feature_list);
PasswordForm form(MakeSimpleForm());
EXPECT_CALL(*store_, GetLogins(_, _))
.WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
@@ -1231,10 +1214,8 @@ TEST_F(PasswordManagerTest, SyncCredentialsNotSaved) {
EXPECT_CALL(*store_,
SaveGaiaPasswordHash(
"googleuser", form.password_value,
- metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA));
+ metrics_util::GaiaPasswordHashChange::SAVED_IN_CONTENT_AREA));
#endif
- // Prefs are needed for failure logging about sync credentials.
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
@@ -1249,69 +1230,51 @@ TEST_F(PasswordManagerTest, SyncCredentialsNotSaved) {
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
TEST_F(PasswordManagerTest, HashSavedOnGaiaFormWithSkipSavePassword) {
for (bool did_stop_loading : {false, true}) {
- for (bool only_new_parser : {false, true}) {
- SCOPED_TRACE(testing::Message("did_stop_loading = ")
- << did_stop_loading
- << testing::Message(" only_new_parser = ")
- << only_new_parser);
- base::test::ScopedFeatureList scoped_feature_list;
- if (only_new_parser) {
- TurnOnOnlyNewParser(&scoped_feature_list);
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- } else {
- TurnOnNewParsingForFilling(&scoped_feature_list, true);
- }
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleGAIAForm());
- // Simulate that this is Gaia form that should be ignored for
- // saving/filling.
- form.form_data.is_gaia_with_skip_save_password_form = true;
- observed.push_back(form);
-
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
-
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
- .WillByDefault(Return(true));
- ON_CALL(*client_.GetStoreResultFilter(), ShouldSave(_))
- .WillByDefault(Return(false));
- ON_CALL(*client_.GetStoreResultFilter(), IsSyncAccountEmail(_))
- .WillByDefault(Return(true));
+ SCOPED_TRACE(testing::Message("did_stop_loading = ") << did_stop_loading);
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+ std::vector<PasswordForm> observed;
+ PasswordForm form(MakeSimpleGAIAForm());
+ // Simulate that this is Gaia form that should be ignored for
+ // saving/filling.
+ form.form_data.is_gaia_with_skip_save_password_form = true;
+ observed.push_back(form);
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
+ .WillRepeatedly(Return(true));
- EXPECT_CALL(
- *store_,
- SaveGaiaPasswordHash(
- "googleuser", form.password_value,
- metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA));
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
- OnPasswordFormSubmitted(form);
- observed.clear();
- manager()->OnPasswordFormsRendered(&driver_, observed, did_stop_loading);
- testing::Mock::VerifyAndClearExpectations(&client_);
- testing::Mock::VerifyAndClearExpectations(&store_);
- }
+ ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
+ .WillByDefault(Return(true));
+ ON_CALL(*client_.GetStoreResultFilter(), ShouldSave(_))
+ .WillByDefault(Return(false));
+ ON_CALL(*client_.GetStoreResultFilter(), IsSyncAccountEmail(_))
+ .WillByDefault(Return(true));
+
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+
+ EXPECT_CALL(
+ *store_,
+ SaveGaiaPasswordHash(
+ "googleuser", form.password_value,
+ metrics_util::GaiaPasswordHashChange::SAVED_IN_CONTENT_AREA));
+
+ OnPasswordFormSubmitted(form);
+ observed.clear();
+ manager()->OnPasswordFormsRendered(&driver_, observed, did_stop_loading);
+ testing::Mock::VerifyAndClearExpectations(&client_);
+ testing::Mock::VerifyAndClearExpectations(&store_);
}
}
TEST_F(PasswordManagerTest,
HashSavedOnGaiaFormWithSkipSavePasswordAndToNTPNavigation) {
- for (bool only_new_parser : {false, true}) {
- SCOPED_TRACE(testing::Message("only_new_parser = ") << only_new_parser);
- base::test::ScopedFeatureList scoped_feature_list;
- if (only_new_parser) {
- TurnOnOnlyNewParser(&scoped_feature_list);
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- } else {
- TurnOnNewParsingForFilling(&scoped_feature_list, true);
- }
-
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
PasswordForm form(MakeSimpleGAIAForm());
// Simulate that this is Gaia form that should be ignored for
// saving/filling.
@@ -1331,20 +1294,17 @@ TEST_F(PasswordManagerTest,
*store_,
SaveGaiaPasswordHash(
"googleuser", form.password_value,
- metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA));
+ metrics_util::GaiaPasswordHashChange::SAVED_IN_CONTENT_AREA));
EXPECT_CALL(client_, IsNewTabPage()).WillRepeatedly(Return(true));
OnPasswordFormSubmitted(form);
manager()->DidNavigateMainFrame(false);
- testing::Mock::VerifyAndClearExpectations(&client_);
- testing::Mock::VerifyAndClearExpectations(&store_);
- }
}
#endif
// On a successful login with an updated password,
// CredentialsFilter::ReportFormLoginSuccess and CredentialsFilter::ShouldSave
-// should be called. The argument of ShouldSave shold be the submitted form.
+// should be called. The argument of ShouldSave should be the submitted form.
TEST_F(PasswordManagerTest, ReportFormLoginSuccessAndShouldSaveCalled) {
PasswordForm stored_form(MakeSimpleForm());
@@ -1367,7 +1327,6 @@ TEST_F(PasswordManagerTest, ReportFormLoginSuccessAndShouldSaveCalled) {
// Submit form and finish navigation.
EXPECT_CALL(client_, IsSavingAndFillingEnabled(observed_form.origin))
.WillRepeatedly(Return(true));
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
OnPasswordFormSubmitted(observed_form);
@@ -1377,6 +1336,7 @@ TEST_F(PasswordManagerTest, ReportFormLoginSuccessAndShouldSaveCalled) {
PasswordForm submitted_form = observed_form;
submitted_form.preferred = true;
+ submitted_form.date_last_used = base::Time::Now();
EXPECT_CALL(*client_.GetStoreResultFilter(),
ShouldSave(FormMatches(submitted_form)));
EXPECT_CALL(*store_, UpdateLogin(_));
@@ -1403,7 +1363,7 @@ TEST_F(PasswordManagerTest, SyncCredentialsNotDroppedIfUpToDate) {
// Submit form and finish navigation.
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
+
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
.WillByDefault(Return(true));
@@ -1412,7 +1372,7 @@ TEST_F(PasswordManagerTest, SyncCredentialsNotDroppedIfUpToDate) {
EXPECT_CALL(*store_,
SaveGaiaPasswordHash(
"googleuser", form.password_value,
- metrics_util::SyncPasswordHashChange::SAVED_IN_CONTENT_AREA));
+ metrics_util::GaiaPasswordHashChange::SAVED_IN_CONTENT_AREA));
#endif
manager()->OnPasswordFormSubmitted(&driver_, form);
@@ -1619,9 +1579,7 @@ TEST_F(PasswordManagerTest, DoNotSaveWithEmptyNewPasswordAndNonemptyPassword) {
manager()->OnPasswordFormsRendered(&driver_, observed, true);
ASSERT_TRUE(form_manager_to_save);
EXPECT_EQ(form.password_value,
- PasswordFormManager::PasswordToSave(
- form_manager_to_save->GetPendingCredentials())
- .first);
+ form_manager_to_save->GetPendingCredentials().password_value);
}
TEST_F(PasswordManagerTest, FormSubmitWithOnlyPasswordField) {
@@ -1667,16 +1625,16 @@ TEST_F(PasswordManagerTest, FormSubmitWithOnlyPasswordField) {
// tests below.
// If kNewPasswordFormParsing is enabled, then "similar" is governed by
-// NewPasswordFormManager::DoesManage, which in turn delegates to the unique
+// PasswordFormManager::DoesManage, which in turn delegates to the unique
// renderer ID of the forms being the same. Note, however, that such ID is only
// unique within one renderer process. If different frames on the page are
// rendered by different processes, two unrelated forms can end up with the same
// ID. The test checks that nevertheless each of them gets assigned its own
-// NewPasswordFormManager and filled as expected.
+// PasswordFormManager and filled as expected.
TEST_F(PasswordManagerTest, FillPasswordOnManyFrames_SameId) {
- // Setting task runner is required since NewPasswordFormManager uses
+ // Setting task runner is required since PasswordFormManager uses
// PostDelayTask for making filling.
- NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true);
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(true);
TestMockTimeTaskRunner::ScopedContext scoped_context_(task_runner_.get());
// Two unrelated forms...
@@ -1727,36 +1685,6 @@ TEST_F(PasswordManagerTest, FillPasswordOnManyFrames_SameId) {
task_runner_->FastForwardUntilNoTasksRemain();
}
-#if !defined(OS_IOS)
-// If kNewPasswordFormParsing is disabled, "similar" is governed by
-// PasswordFormManager::DoesManage and is related to actual similarity of the
-// forms, including having the same signon realm (and hence origin). Should a
-// page have two frames with the same origin and a form, and those two forms be
-// similar, then it is important to ensure that the single governing
-// PasswordFormManager knows about both PasswordManagerDriver instances and
-// instructs them to fill.
-// TODO(https://crbug.com/949519): Remove this test when the old parser is gone.
-TEST_F(PasswordManagerTest, FillPasswordOnManyFrames_SameForm) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForFilling(&scoped_feature_list, false);
- PasswordForm same_form = MakeSimpleForm();
-
- // Observe the form in the first frame.
- EXPECT_CALL(driver_, FillPasswordForm(_));
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillOnce(WithArg<1>(InvokeConsumer(same_form)));
- manager()->OnPasswordFormsParsed(&driver_, {same_form});
-
- // Now the form will be seen the second time, in a different frame. The driver
- // for that frame should be told to fill it, but the store should not be asked
- // for it again.
- MockPasswordManagerDriver driver_b;
- EXPECT_CALL(driver_b, FillPasswordForm(_));
- EXPECT_CALL(*store_, GetLogins(_, _)).Times(0);
- manager()->OnPasswordFormsParsed(&driver_b, {same_form});
-}
-#endif
-
TEST_F(PasswordManagerTest, SameDocumentNavigation) {
// Test that observing a newly submitted form shows the save password bar on
// call in page navigation.
@@ -1802,8 +1730,6 @@ TEST_F(PasswordManagerTest, SameDocumentBlacklistedSite) {
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
- // Prefs are needed for failure logging about blacklisting.
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
@@ -1813,168 +1739,6 @@ TEST_F(PasswordManagerTest, SameDocumentBlacklistedSite) {
EXPECT_TRUE(form_manager_to_save->IsBlacklisted());
}
-#if !defined(OS_IOS)
-TEST_F(PasswordManagerTest, SavingSignupForms_NoHTMLMatch) {
- base::test::ScopedFeatureList scoped_feature_list;
- // This test does not make sense for NewPasswordFormManager:
- // 1.Renderer ids are used for matching.
- // 2.HTML attributes are not used.
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- // Signup forms don't require HTML attributes match in order to save.
- // Verify that we prefer a better match (action + origin vs. origin).
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
- PasswordForm wrong_action_form(form);
- wrong_action_form.action = GURL("http://www.google.com/other/action");
- observed.push_back(wrong_action_form);
-
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Simulate either form changing or heuristics choosing other fields
- // after the user has entered their information.
- PasswordForm submitted_form(form);
- submitted_form.new_password_element = ASCIIToUTF16("new_password");
- submitted_form.new_password_value = form.password_value;
- submitted_form.password_element.clear();
- submitted_form.password_value.clear();
-
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- OnPasswordFormSubmitted(submitted_form);
-
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-
- // Now the password manager waits for the navigation to complete.
- observed.clear();
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Simulate saving the form, as if the info bar was accepted.
- PasswordForm form_to_save;
- EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&form_to_save));
- ASSERT_TRUE(form_manager_to_save);
- form_manager_to_save->Save();
-
- // PasswordManager observed two forms, and should have associate the saved one
- // with the observed form with a matching action.
- EXPECT_EQ(form.action, form_to_save.action);
- // Password values are always saved as the current password value.
- EXPECT_EQ(submitted_form.new_password_value, form_to_save.password_value);
- EXPECT_EQ(submitted_form.new_password_element, form_to_save.password_element);
-}
-
-TEST_F(PasswordManagerTest, SavingSignupForms_NoActionMatch) {
- base::test::ScopedFeatureList scoped_feature_list;
- // This test does not make sense for NewPasswordFormManager:
- // 1.Only renderer ids are used for matching.
- // 2.HTML attributes are not used.
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- // Signup forms don't require HTML attributes match in order to save.
- // Verify that we prefer a better match (HTML attributes + origin vs. origin).
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
- // Change the submit element so we can track which of the two forms is
- // chosen as a better match.
- PasswordForm wrong_submit_form(form);
- wrong_submit_form.submit_element = ASCIIToUTF16("different_signin");
- wrong_submit_form.new_password_element = ASCIIToUTF16("new_password");
- wrong_submit_form.new_password_value = form.password_value;
- wrong_submit_form.password_element.clear();
- wrong_submit_form.password_value.clear();
- observed.push_back(wrong_submit_form);
-
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- PasswordForm submitted_form(form);
- submitted_form.action = GURL("http://www.google.com/other/action");
-
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- OnPasswordFormSubmitted(submitted_form);
-
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-
- // Now the password manager waits for the navigation to complete.
- observed.clear();
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Simulate saving the form, as if the info bar was accepted.
- PasswordForm form_to_save;
- EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&form_to_save));
- ASSERT_TRUE(form_manager_to_save);
- form_manager_to_save->Save();
-
- // PasswordManager observed two forms, and should have associate the saved one
- // with the observed form with a matching action.
- EXPECT_EQ(form.submit_element, form_to_save.submit_element);
-
- EXPECT_EQ(submitted_form.password_value, form_to_save.password_value);
- EXPECT_EQ(submitted_form.password_element, form_to_save.password_element);
- EXPECT_EQ(submitted_form.username_value, form_to_save.username_value);
- EXPECT_EQ(submitted_form.username_element, form_to_save.username_element);
- EXPECT_TRUE(form_to_save.new_password_element.empty());
- EXPECT_TRUE(form_to_save.new_password_value.empty());
-}
-
-TEST_F(PasswordManagerTest, FormSubmittedChangedWithAutofillResponse) {
- base::test::ScopedFeatureList scoped_feature_list;
- // This test does not make sense for NewPasswordFormManager, because all
- // parsing is in the browser process and
- // |was_parsed_using_autofill_predictions| is not used anymore.
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- // This tests verifies that if the observed forms and provisionally saved
- // differ in the choice of the username, the saving still succeeds, as long as
- // the changed form is marked "parsed using autofill predictions".
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Simulate that based on autofill server username prediction, the username
- // of the form changed from the default candidate("Email") to something else.
- // Set the parsed_using_autofill_predictions bit to true to make sure that
- // choice of username is accepted by PasswordManager, otherwise the the form
- // will be rejected as not equal to the observed one. Note that during
- // initial parsing we don't have autofill server predictions yet, that's why
- // observed form and submitted form may be different.
- form.username_element = ASCIIToUTF16("Username");
- form.was_parsed_using_autofill_predictions = true;
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- OnPasswordFormSubmitted(form);
-
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
-
- // Now the password manager waits for the navigation to complete.
- observed.clear();
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Simulate saving the form, as if the info bar was accepted.
- EXPECT_CALL(*store_, AddLogin(FormMatches(form)));
- ASSERT_TRUE(form_manager_to_save);
- form_manager_to_save->Save();
-}
-#endif
-
TEST_F(PasswordManagerTest, FormSubmittedUnchangedNotifiesClient) {
// This tests verifies that if the observed forms and provisionally saved
// forms are the same, then successful submission notifies the client.
@@ -2361,78 +2125,18 @@ TEST_F(PasswordManagerTest, SetGenerationElementAndReasonForForm) {
EXPECT_TRUE(form_manager->HasGeneratedPassword());
}
-#if !defined(OS_IOS)
-TEST_F(PasswordManagerTest,
- PasswordGenerationNoCorrespondingPasswordFormManager) {
- base::test::ScopedFeatureList scoped_feature_list;
- // This test does not make sense for NewPasswordFormManager: there is much
- // more robust mechanism for matching them, so no new NewPasswordFormManager
- // is created when no matched one is found.
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
- // Verifies that if there is no corresponding password form manager for the
- // given form, new password form manager should fetch data from the password
- // store. Also verifies that |SetGenerationElementAndReasonForForm| doesn't
- // change |has_generated_password_| of new password form manager.
- PasswordForm form(MakeFormWithOnlyNewPasswordField());
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- std::vector<PasswordForm> observed;
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- EXPECT_CALL(*store_, GetLogins(PasswordStore::FormDigest(form), _));
- manager()->SetGenerationElementAndReasonForForm(&driver_, form,
- base::string16(), false);
- ASSERT_EQ(1u, manager()->pending_login_managers().size());
- PasswordFormManager* form_manager =
- manager()->pending_login_managers().front().get();
-
- EXPECT_FALSE(form_manager->HasGeneratedPassword());
-}
-#endif
-
TEST_F(PasswordManagerTest, UpdateFormManagers) {
- // Seeing a form should result in creating PasswordFormManager and
- // NewPasswordFormManager and querying PasswordStore. Calling
- // UpdateFormManagers should result in querying the store again.
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
-
- manager()->OnPasswordFormsParsed(&driver_, {PasswordForm()});
-
- EXPECT_CALL(*store_, GetLogins(_, _));
- manager()->UpdateFormManagers();
-}
-
-#if !defined(OS_IOS)
-TEST_F(PasswordManagerTest, DropFormManagers) {
- // This test doesn't make sense for the new parser, because
- // NewPasswordFormManager is created on submission if it is missing.
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- // Interrupt the normal submit flow by DropFormManagers().
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
- // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when
- // the old parser is gone.
+ // Seeing a form should result in creating PasswordFormManager and
+ // PasswordFormManager and querying PasswordStore. Calling
+ // UpdateFormManagers should result in querying the store again.
EXPECT_CALL(*store_, GetLogins(_, _))
.WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
- manager()->DropFormManagers();
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- OnPasswordFormSubmitted(form);
+ manager()->OnPasswordFormsParsed(&driver_, {PasswordForm()});
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
- observed.clear();
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
+ EXPECT_CALL(*store_, GetLogins(_, _));
+ manager()->UpdateFormManagers();
}
-#endif
TEST_F(PasswordManagerTest, AutofillingOfAffiliatedCredentials) {
PasswordForm android_form(MakeAndroidCredential());
@@ -2577,7 +2281,6 @@ TEST_F(PasswordManagerTest, NotSavingSyncPasswordHash_NoUsername) {
.WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
manager()->OnPasswordFormsRendered(&driver_, observed, true);
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
@@ -2601,7 +2304,6 @@ TEST_F(PasswordManagerTest, NotSavingSyncPasswordHash_NotSyncCredentials) {
.WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
manager()->OnPasswordFormsRendered(&driver_, observed, true);
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
@@ -2676,38 +2378,31 @@ TEST_F(PasswordManagerTest, ManualFallbackForSaving) {
// Tests that the manual fallback for saving isn't shown if there is no response
// from the password storage. When crbug.com/741537 is fixed, change this test.
TEST_F(PasswordManagerTest, ManualFallbackForSaving_SlowBackend) {
- for (bool only_new_parser_enabled : {false, true}) {
- base::test::ScopedFeatureList scoped_feature_list;
- if (only_new_parser_enabled)
- TurnOnOnlyNewParser(&scoped_feature_list);
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
- PasswordStoreConsumer* store_consumer = nullptr;
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when
- // the old parser is gone.
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(SaveArg<1>(&store_consumer));
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
+ std::vector<PasswordForm> observed;
+ PasswordForm form(MakeSimpleForm());
+ observed.push_back(form);
+ PasswordStoreConsumer* store_consumer = nullptr;
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
+ .WillRepeatedly(Return(true));
+ // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when
+ // the old parser is gone.
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(SaveArg<1>(&store_consumer));
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
- // There is no response from the store. Don't show the fallback.
- EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)).Times(0);
- manager()->ShowManualFallbackForSaving(&driver_, form);
+ // There is no response from the store. Don't show the fallback.
+ EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)).Times(0);
+ manager()->ShowManualFallbackForSaving(&driver_, form);
- // The storage responded. The fallback can be shown.
- ASSERT_TRUE(store_consumer);
- store_consumer->OnGetPasswordStoreResults(
- std::vector<std::unique_ptr<PasswordForm>>());
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
- manager()->ShowManualFallbackForSaving(&driver_, form);
- Mock::VerifyAndClearExpectations(&client_);
- Mock::VerifyAndClearExpectations(&store_);
- }
+ // The storage responded. The fallback can be shown.
+ ASSERT_TRUE(store_consumer);
+ store_consumer->OnGetPasswordStoreResults(
+ std::vector<std::unique_ptr<PasswordForm>>());
+ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+ EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+ manager()->ShowManualFallbackForSaving(&driver_, form);
}
TEST_F(PasswordManagerTest, ManualFallbackForSaving_GeneratedPassword) {
@@ -2750,67 +2445,6 @@ TEST_F(PasswordManagerTest, ManualFallbackForSaving_GeneratedPassword) {
manager()->HideManualFallbackForSaving();
}
-// Tests that Autofill predictions are processed correctly. If at least one of
-// these predictions can be converted to a |PasswordFormFieldPredictionMap|, the
-// predictions map is updated accordingly.
-TEST_F(PasswordManagerTest, ProcessAutofillPredictions) {
- // Create FormData form with two fields.
- autofill::FormData form;
- form.url = GURL("http://foo.com");
- autofill::FormFieldData field;
- field.form_control_type = "text";
-
- field.label = ASCIIToUTF16("username");
- field.name = ASCIIToUTF16("username");
- form.fields.push_back(field);
-
- field.label = ASCIIToUTF16("password");
- field.name = ASCIIToUTF16("password");
- form.fields.push_back(field);
-
- FormStructure form_structure(form);
- std::vector<FormStructure*> forms;
- forms.push_back(&form_structure);
-
- autofill::AutofillQueryResponseContents response;
- // If there are multiple predictions for the field,
- // |AutofillField::overall_server_type_| will store only autofill vote, but
- // not password vote. |AutofillField::server_predictions_| should store all
- // predictions.
- autofill::AutofillQueryResponseContents_Field* field0 = response.add_field();
- field0->set_overall_type_prediction(autofill::PHONE_HOME_NUMBER);
- autofill::AutofillQueryResponseContents_Field_FieldPrediction*
- field_prediction0 = field0->add_predictions();
- field_prediction0->set_type(autofill::PHONE_HOME_NUMBER);
- autofill::AutofillQueryResponseContents_Field_FieldPrediction*
- field_prediction1 = field0->add_predictions();
- field_prediction1->set_type(autofill::USERNAME);
-
- autofill::AutofillQueryResponseContents_Field* field1 = response.add_field();
- field1->set_overall_type_prediction(autofill::PASSWORD);
- autofill::AutofillQueryResponseContents_Field_FieldPrediction*
- field_prediction2 = field1->add_predictions();
- field_prediction2->set_type(autofill::PASSWORD);
- autofill::AutofillQueryResponseContents_Field_FieldPrediction*
- field_prediction3 = field1->add_predictions();
- field_prediction3->set_type(autofill::PROBABLY_NEW_PASSWORD);
-
- std::string response_string;
- ASSERT_TRUE(response.SerializeToString(&response_string));
- FormStructure::ParseQueryResponse(response_string, forms, nullptr);
-
- // Check that Autofill predictions are converted to password related
- // predictions.
- autofill::FormsPredictionsMap predictions;
- predictions[form][form.fields[0]] =
- PasswordFormFieldPredictionType::kUsername;
- predictions[form][form.fields[1]] =
- PasswordFormFieldPredictionType::kCurrentPassword;
- EXPECT_CALL(driver_, AutofillDataReceived(predictions));
-
- manager()->ProcessAutofillPredictions(&driver_, forms);
-}
-
// Sync password hash should be updated upon submission of change password page.
TEST_F(PasswordManagerTest, SaveSyncPasswordHashOnChangePasswordPage) {
PasswordForm form(MakeGAIAChangePasswordForm());
@@ -2825,7 +2459,7 @@ TEST_F(PasswordManagerTest, SaveSyncPasswordHashOnChangePasswordPage) {
// Submit form and finish navigation.
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
+
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
.WillByDefault(Return(true));
@@ -2835,7 +2469,7 @@ TEST_F(PasswordManagerTest, SaveSyncPasswordHashOnChangePasswordPage) {
*store_,
SaveGaiaPasswordHash(
"googleuser", form.new_password_value,
- metrics_util::SyncPasswordHashChange::CHANGED_IN_CONTENT_AREA));
+ metrics_util::GaiaPasswordHashChange::CHANGED_IN_CONTENT_AREA));
#endif
client_.FilterAllResultsForSaving();
OnPasswordFormSubmitted(form);
@@ -2860,7 +2494,6 @@ TEST_F(PasswordManagerTest, SaveOtherGaiaPasswordHash) {
// Submit form and finish navigation.
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveGaiaPasswordHash(_))
.WillByDefault(Return(true));
@@ -2868,7 +2501,7 @@ TEST_F(PasswordManagerTest, SaveOtherGaiaPasswordHash) {
*store_,
SaveGaiaPasswordHash(
"googleuser", form.password_value,
- metrics_util::SyncPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE));
+ metrics_util::GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE));
client_.FilterAllResultsForSaving();
OnPasswordFormSubmitted(form);
@@ -2892,7 +2525,7 @@ TEST_F(PasswordManagerTest, SaveEnterprisePasswordHash) {
// Submit form and finish navigation.
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
- EXPECT_CALL(client_, GetPrefs()).WillRepeatedly(Return(nullptr));
+
ON_CALL(*client_.GetStoreResultFilter(), ShouldSaveEnterprisePasswordHash(_))
.WillByDefault(Return(true));
ON_CALL(*client_.GetStoreResultFilter(), IsSyncAccountEmail(_))
@@ -2964,10 +2597,6 @@ TEST_F(PasswordManagerTest, CertErrorReported) {
}
TEST_F(PasswordManagerTest, CreatingFormManagers) {
- // Add the NewPasswordFormParsing feature.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kNewPasswordFormParsing);
-
PasswordForm form(MakeSimpleForm());
std::vector<PasswordForm> observed;
observed.push_back(form);
@@ -2985,114 +2614,13 @@ TEST_F(PasswordManagerTest, CreatingFormManagers) {
EXPECT_EQ(1u, manager()->form_managers().size());
}
-#if !defined(OS_IOS)
-TEST_F(PasswordManagerTest,
- ShowManualFallbacksDontChangeProvisionalSaveManager) {
- base::test::ScopedFeatureList scoped_feature_list;
- // This test does not make sense for NewPasswordFormManager because
- // provisional_save_manager() is OldPasswordFormManager.
- TurnOnNewParsingForSaving(&scoped_feature_list, false);
- std::vector<PasswordForm> observed;
- PasswordForm form(MakeSimpleForm());
- observed.push_back(form);
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeConsumer(form)));
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2);
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- EXPECT_THAT(manager()->provisional_save_manager(), IsNull());
- manager()->ShowManualFallbackForSaving(&driver_, form);
- EXPECT_THAT(manager()->provisional_save_manager(), IsNull());
-
- // The user submits the form and a provisional save manager is set.
- OnPasswordFormSubmitted(form);
-
- EXPECT_THAT(manager()->provisional_save_manager(), NotNull());
- const PasswordFormManager* last_provisional_save_manager =
- manager()->provisional_save_manager();
-
- EXPECT_CALL(client_, HideManualFallbackForSaving());
- // The call to manual fallback with |form| equal to already saved should close
- // the fallback.
- manager()->ShowManualFallbackForSaving(&driver_, form);
-
- EXPECT_THAT(manager()->provisional_save_manager(), NotNull());
- EXPECT_EQ(last_provisional_save_manager,
- manager()->provisional_save_manager());
-}
-#endif
-
// Tests that processing normal HTML form submissions works properly with the
// new parsing. For details see scheme 1 in comments before
// |form_managers_| in password_manager.h.
TEST_F(PasswordManagerTest, ProcessingNormalFormSubmission) {
- for (bool only_new_parser : {false, true}) {
- for (bool successful_submission : {false, true}) {
- SCOPED_TRACE(testing::Message("only_new_parser = ")
- << only_new_parser
- << " successful_submission = " << successful_submission);
- base::test::ScopedFeatureList scoped_feature_list;
- if (only_new_parser)
- TurnOnOnlyNewParser(&scoped_feature_list);
- else
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
-
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
- .WillRepeatedly(Return(true));
-
- PasswordForm form(MakeSimpleForm());
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
-
- std::vector<PasswordForm> observed;
- observed.push_back(form);
- manager()->OnPasswordFormsParsed(&driver_, observed);
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- if (only_new_parser)
- EXPECT_TRUE(manager()->pending_login_managers().empty());
-
- auto submitted_form = form;
- submitted_form.form_data.fields[0].value = ASCIIToUTF16("username");
- submitted_form.form_data.fields[1].value = ASCIIToUTF16("password1");
-
- OnPasswordFormSubmitted(submitted_form);
- EXPECT_TRUE(manager()->GetSubmittedManagerForTest());
-
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
-
- // Simulate submission.
- if (successful_submission) {
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
- // The form disappeared, so the submission is condered to be successful.
- observed.clear();
- } else {
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
- }
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
-
- // Multiple calls of OnPasswordFormsRendered should be handled gracefully.
- manager()->OnPasswordFormsRendered(&driver_, observed, true);
- testing::Mock::VerifyAndClearExpectations(&client_);
- }
- }
-}
-
-// Tests that processing form submissions without navigations works properly
-// with the new parsing. For details see scheme 2 in comments before
-// |form_managers_| in password_manager.h.
-TEST_F(PasswordManagerTest, ProcessingOtherSubmissionTypes) {
- for (bool only_new_parser : {false, true}) {
- SCOPED_TRACE(testing::Message("only_new_parser = ") << only_new_parser);
- base::test::ScopedFeatureList scoped_feature_list;
- if (only_new_parser)
- TurnOnOnlyNewParser(&scoped_feature_list);
- else
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
+ for (bool successful_submission : {false, true}) {
+ SCOPED_TRACE(testing::Message("successful_submission = ")
+ << successful_submission);
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -3108,17 +2636,57 @@ TEST_F(PasswordManagerTest, ProcessingOtherSubmissionTypes) {
auto submitted_form = form;
submitted_form.form_data.fields[0].value = ASCIIToUTF16("username");
- submitted_form.form_data.fields[1].value = ASCIIToUTF16("strong_password");
+ submitted_form.form_data.fields[1].value = ASCIIToUTF16("password1");
+
+ OnPasswordFormSubmitted(submitted_form);
+ EXPECT_TRUE(manager()->GetSubmittedManagerForTest());
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
- manager()->OnPasswordFormSubmittedNoChecks(&driver_, submitted_form);
- EXPECT_TRUE(manager()->form_managers().empty());
+
+ // Simulate submission.
+ if (successful_submission) {
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+ // The form disappeared, so the submission is condered to be successful.
+ observed.clear();
+ } else {
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+ }
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ // Multiple calls of OnPasswordFormsRendered should be handled gracefully.
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
testing::Mock::VerifyAndClearExpectations(&client_);
}
}
+// Tests that processing form submissions without navigations works properly
+// with the new parsing. For details see scheme 2 in comments before
+// |form_managers_| in password_manager.h.
+TEST_F(PasswordManagerTest, ProcessingOtherSubmissionTypes) {
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
+ .WillRepeatedly(Return(true));
+
+ PasswordForm form(MakeSimpleForm());
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+
+ std::vector<PasswordForm> observed;
+ observed.push_back(form);
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ auto submitted_form = form;
+ submitted_form.form_data.fields[0].value = ASCIIToUTF16("username");
+ submitted_form.form_data.fields[1].value = ASCIIToUTF16("strong_password");
+
+ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+ manager()->OnPasswordFormSubmittedNoChecks(&driver_, submitted_form);
+ EXPECT_TRUE(manager()->form_managers().empty());
+}
+
TEST_F(PasswordManagerTest, SubmittedGaiaFormWithoutVisiblePasswordField) {
// Tests that a submitted GAIA sign-in form which does not contain a visible
// password field is skipped.
@@ -3141,40 +2709,6 @@ TEST_F(PasswordManagerTest, SubmittedGaiaFormWithoutVisiblePasswordField) {
manager()->OnPasswordFormSubmittedNoChecks(&driver_, form);
}
-#if !defined(OS_IOS)
-// Tests that PasswordFormManager and NewPasswordFormManager for the same form
-// have the same metrics recorder.
-TEST_F(PasswordManagerTest, CheckMetricsRecorder) {
- // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when
- // the old parser is gone.
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForFilling(&scoped_feature_list, true);
-
- PasswordForm form(MakeSimpleForm());
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
-
- std::vector<PasswordForm> observed;
- observed.push_back(form);
- manager()->OnPasswordFormsParsed(&driver_, observed);
-
- const std::vector<std::unique_ptr<PasswordFormManager>>&
- password_form_managers = manager()->pending_login_managers();
-
- const std::vector<std::unique_ptr<NewPasswordFormManager>>&
- new_password_form_managers = manager()->form_managers();
-
- ASSERT_EQ(1u, password_form_managers.size());
- ASSERT_EQ(1u, new_password_form_managers.size());
-
- EXPECT_TRUE(password_form_managers[0]->GetMetricsRecorder());
- EXPECT_EQ(password_form_managers[0]->GetMetricsRecorder(),
- new_password_form_managers[0]->GetMetricsRecorder());
-}
-#endif
-
TEST_F(PasswordManagerTest, MetricForSchemeOfSuccessfulLogins) {
for (bool origin_is_secure : {false, true}) {
SCOPED_TRACE(testing::Message("origin_is_secure = ") << origin_is_secure);
@@ -3206,9 +2740,7 @@ TEST_F(PasswordManagerTest, MetricForSchemeOfSuccessfulLogins) {
}
TEST_F(PasswordManagerTest, ManualFallbackForSavingNewParser) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
- NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false);
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(false);
std::vector<PasswordForm> observed;
PasswordForm form(MakeSimpleForm());
@@ -3247,47 +2779,7 @@ TEST_F(PasswordManagerTest, ManualFallbackForSavingNewParser) {
manager()->HideManualFallbackForSaving();
}
-#if !defined(OS_IOS)
-// Check that some value for the ParsingOnSavingDifference UKM metric is emitted
-// on a successful login.
-TEST_F(PasswordManagerTest, ParsingOnSavingMetricRecorded) {
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- base::test::ScopedFeatureList scoped_feature_list;
- std::vector<Feature> enabled_features;
- std::vector<Feature> disabled_features = {features::kOnlyNewParser};
- // This test does not make sense the old parser is off, since it checks
- // metrics for comparison the old and the new one.
- scoped_feature_list.InitWithFeatures(enabled_features, disabled_features);
- manager_.reset(new PasswordManager(&client_));
-
- PasswordForm form = MakeSimpleForm();
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
-
- std::vector<PasswordForm> observed = {form};
- manager()->OnPasswordFormsParsed(nullptr, observed);
-
- // Provisionally save and simulate a successful landing page load to make
- // manager() believe this password should be saved.
- manager()->OnPasswordFormSubmitted(nullptr, form);
- manager()->OnPasswordFormsRendered(nullptr, {}, true);
-
- // Destroy |manager_| to send off UKM metrics.
- manager_.reset();
-
- EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(
- GetMetricEntry(test_ukm_recorder,
- ukm::builders::PasswordForm::kEntryName),
- ukm::builders::PasswordForm::kParsingOnSavingDifferenceName));
-}
-#endif
-
TEST_F(PasswordManagerTest, NoSavePromptWhenPasswordManagerDisabled) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
-
PasswordForm form(MakeSimpleForm());
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(false));
@@ -3305,9 +2797,6 @@ TEST_F(PasswordManagerTest, NoSavePromptWhenPasswordManagerDisabled) {
}
TEST_F(PasswordManagerTest, NoSavePromptForNotPasswordForm) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
-
PasswordForm form(MakeSimpleForm());
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
@@ -3329,11 +2818,7 @@ TEST_F(PasswordManagerTest, NoSavePromptForNotPasswordForm) {
// Check that when autofill predictions are received before a form is found then
// server predictions are not ignored and used for filling.
TEST_F(PasswordManagerTest, AutofillPredictionBeforeFormParsed) {
- NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true);
- TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(features::kNewPasswordFormParsing);
-
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(true);
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -3350,11 +2835,7 @@ TEST_F(PasswordManagerTest, AutofillPredictionBeforeFormParsed) {
EXPECT_CALL(*store_, GetLogins(_, _))
.WillRepeatedly(WithArg<1>(InvokeConsumer(form)));
- // There are 2 fills, the first when the server predictions are received, the
- // second when the filling delayed task is executed. In production code a
- // delayed task is not posted since receiving results from the store is
- // asynchronous in contrast to test code.
- EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2);
+ EXPECT_CALL(driver_, FillPasswordForm(_));
manager()->OnPasswordFormsParsed(&driver_, {form});
task_runner_->FastForwardUntilNoTasksRemain();
@@ -3369,9 +2850,6 @@ TEST_F(PasswordManagerTest, SavingAfterUserTypingAndNavigation) {
for (bool form_may_be_submitted : {false, true}) {
SCOPED_TRACE(testing::Message()
<< "form_may_be_submitted = " << form_may_be_submitted);
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
-
PasswordForm form(MakeSimpleForm());
EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin))
.WillRepeatedly(Return(true));
@@ -3406,19 +2884,13 @@ TEST_F(PasswordManagerTest, SavingAfterUserTypingAndNavigation) {
}
}
-// Check that when a form is submitted and a NewPasswordFormManager not present,
+// Check that when a form is submitted and a PasswordFormManager not present,
// this ends up reported in ProvisionallySaveFailure UMA and UKM.
TEST_F(PasswordManagerTest, ProvisionallySaveFailure) {
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
EXPECT_CALL(*store_, GetLogins(_, _))
.WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
- for (bool new_parsing_for_saving : {false, true}) {
- SCOPED_TRACE(testing::Message()
- << "new_parsing_for_saving = " << new_parsing_for_saving);
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving);
-
manager()->OnPasswordFormsParsed(nullptr, {});
base::HistogramTester histogram_tester;
@@ -3441,7 +2913,6 @@ TEST_F(PasswordManagerTest, ProvisionallySaveFailure) {
test_ukm_recorder, ukm::builders::PageWithPassword::kEntryName,
ukm::builders::PageWithPassword::kProvisionalSaveFailureName,
PasswordManagerMetricsRecorder::NO_MATCHING_FORM);
- }
}
namespace {
@@ -3466,9 +2937,6 @@ struct MissingFormManagerTestCase {
// The expected value of the PageWithPassword::kFormManagerAvailableName
// metric, or base::nullopt if no value should be logged.
base::Optional<int64_t> expected_metric_value;
-
- bool run_for_old_parser = true;
- bool run_for_new_parser = true;
};
} // namespace
@@ -3484,7 +2952,7 @@ TEST_F(PasswordManagerTest, ReportMissingFormManager) {
const MissingFormManagerTestCase kTestCases[] = {
{
.description =
- "A form is submitted and a NewPasswordFormManager not present.",
+ "A form is submitted and a PasswordFormManager not present.",
.parsed_forms = {},
.save_signal = MissingFormManagerTestCase::Signal::Automatic,
// .parsed_forms is empty, so the processed form below was not
@@ -3496,20 +2964,7 @@ TEST_F(PasswordManagerTest, ReportMissingFormManager) {
},
{
.description = "Manual saving is requested and a "
- "NewPasswordFormManager not present.",
- .parsed_forms = {},
- .save_signal = MissingFormManagerTestCase::Signal::Manual,
- // .parsed_forms is empty, so the processed form below was not
- // observed and has no form manager associated.
- .processed_forms = {form},
- .expected_metric_value =
- MetricValue(PasswordManagerMetricsRecorder::FormManagerAvailable::
- kMissingManual),
- .run_for_new_parser = false,
- },
- {
- .description = "Manual saving is requested and a "
- "NewPasswordFormManager is created.",
+ "PasswordFormManager is created.",
.parsed_forms = {},
.save_signal = MissingFormManagerTestCase::Signal::Manual,
// .parsed_forms is empty, so the processed form below was not
@@ -3517,7 +2972,6 @@ TEST_F(PasswordManagerTest, ReportMissingFormManager) {
.processed_forms = {form},
.expected_metric_value = MetricValue(
PasswordManagerMetricsRecorder::FormManagerAvailable::kSuccess),
- .run_for_old_parser = false,
},
{
.description = "Manual saving is successfully requested.",
@@ -3529,7 +2983,7 @@ TEST_F(PasswordManagerTest, ReportMissingFormManager) {
},
{
.description =
- "A form is submitted and a NewPasswordFormManager present.",
+ "A form is submitted and a PasswordFormManager present.",
.parsed_forms = {form},
.save_signal = MissingFormManagerTestCase::Signal::Automatic,
.processed_forms = {form},
@@ -3570,72 +3024,50 @@ TEST_F(PasswordManagerTest, ReportMissingFormManager) {
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(test_case.saving ==
MissingFormManagerTestCase::Saving::Enabled));
- std::vector<bool> only_new_parser_options(1, true);
-#if !defined(OS_IOS)
- // The old parser is not present on iOS anymore.
- only_new_parser_options.push_back(false);
-#endif
- for (bool only_new_parser : only_new_parser_options) {
- if ((only_new_parser && !test_case.run_for_new_parser) ||
- (!only_new_parser && !test_case.run_for_old_parser)) {
- continue;
- }
- SCOPED_TRACE(testing::Message()
- << "test case = " << test_case.description
- << ", only_new_parser = " << only_new_parser);
- base::test::ScopedFeatureList scoped_feature_list;
- if (only_new_parser)
- TurnOnOnlyNewParser(&scoped_feature_list);
- else
- TurnOnNewParsingForFilling(&scoped_feature_list, true);
-
- manager()->OnPasswordFormsParsed(nullptr, test_case.parsed_forms);
-
- ukm::TestAutoSetUkmRecorder test_ukm_recorder;
- auto metrics_recorder = std::make_unique<PasswordManagerMetricsRecorder>(
- 1234, GURL("http://example.com"));
- EXPECT_CALL(client_, GetMetricsRecorder())
- .WillRepeatedly(Return(metrics_recorder.get()));
-
- for (const PasswordForm& processed_form : test_case.processed_forms) {
- switch (test_case.save_signal) {
- case MissingFormManagerTestCase::Signal::Automatic:
- manager()->OnPasswordFormSubmitted(nullptr, processed_form);
- break;
- case MissingFormManagerTestCase::Signal::Manual:
- manager()->ShowManualFallbackForSaving(nullptr, processed_form);
- break;
- case MissingFormManagerTestCase::Signal::None:
- break;
- }
- }
+ SCOPED_TRACE(testing::Message() << "test case = " << test_case.description);
- // Flush the UKM reports.
- EXPECT_CALL(client_, GetMetricsRecorder())
- .WillRepeatedly(Return(nullptr));
- metrics_recorder.reset();
- if (test_case.expected_metric_value) {
- CheckMetricHasValue(
- test_ukm_recorder, ukm::builders::PageWithPassword::kEntryName,
- ukm::builders::PageWithPassword::kFormManagerAvailableName,
- test_case.expected_metric_value.value());
- } else {
- EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(
- GetMetricEntry(test_ukm_recorder,
- ukm::builders::PageWithPassword::kEntryName),
- ukm::builders::PageWithPassword::kFormManagerAvailableName));
+ manager()->OnPasswordFormsParsed(nullptr, test_case.parsed_forms);
+
+ ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+ auto metrics_recorder = std::make_unique<PasswordManagerMetricsRecorder>(
+ 1234, GURL("http://example.com"));
+ EXPECT_CALL(client_, GetMetricsRecorder())
+ .WillRepeatedly(Return(metrics_recorder.get()));
+
+ for (const PasswordForm& processed_form : test_case.processed_forms) {
+ switch (test_case.save_signal) {
+ case MissingFormManagerTestCase::Signal::Automatic:
+ manager()->OnPasswordFormSubmitted(nullptr, processed_form);
+ break;
+ case MissingFormManagerTestCase::Signal::Manual:
+ manager()->ShowManualFallbackForSaving(nullptr, processed_form);
+ break;
+ case MissingFormManagerTestCase::Signal::None:
+ break;
}
}
+
+ // Flush the UKM reports.
+ EXPECT_CALL(client_, GetMetricsRecorder()).WillRepeatedly(Return(nullptr));
+ metrics_recorder.reset();
+ if (test_case.expected_metric_value) {
+ CheckMetricHasValue(
+ test_ukm_recorder, ukm::builders::PageWithPassword::kEntryName,
+ ukm::builders::PageWithPassword::kFormManagerAvailableName,
+ test_case.expected_metric_value.value());
+ } else {
+ EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(
+ GetMetricEntry(test_ukm_recorder,
+ ukm::builders::PageWithPassword::kEntryName),
+ ukm::builders::PageWithPassword::kFormManagerAvailableName));
+ }
}
}
// Tests that despite there a form was not seen on a page load, new
-// |NewPasswordFormManager| is created in process of saving.
-TEST_F(PasswordManagerTest, CreateNewPasswordFormManagerOnSaving) {
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, true);
-
+// |PasswordFormManager| is created in process of saving.
+TEST_F(PasswordManagerTest, CreatePasswordFormManagerOnSaving) {
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -3671,12 +3103,6 @@ TEST_F(PasswordManagerTest, CreateNewPasswordFormManagerOnSaving) {
// Tests that no save prompt from form manager is shown when Credentials
// Management API function store is called.
TEST_F(PasswordManagerTest, NoSavePromptAfterStoreCalled) {
- for (bool new_parsing_for_saving : {false, true}) {
- SCOPED_TRACE(testing::Message()
- << "new_parsing_for_saving = " << new_parsing_for_saving);
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving);
-
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
@@ -3694,59 +3120,162 @@ TEST_F(PasswordManagerTest, NoSavePromptAfterStoreCalled) {
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
manager()->OnPasswordFormsRendered(&driver_, {}, true);
- testing::Mock::VerifyAndClearExpectations(&client_);
- }
}
// Check that on non-password form, saving and filling fallbacks are available
// but no automatic filling and saving are available.
TEST_F(PasswordManagerTest, FillingAndSavingFallbacksOnNonPasswordForm) {
- NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false);
- for (bool new_parsing_for_saving : {false, true}) {
- SCOPED_TRACE(testing::Message()
- << "is_new_parsing_on = " << new_parsing_for_saving);
- base::test::ScopedFeatureList scoped_feature_list;
- TurnOnNewParsingForSaving(&scoped_feature_list, new_parsing_for_saving);
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(false);
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
+ .WillRepeatedly(Return(true));
- EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
- .WillRepeatedly(Return(true));
+ PasswordForm saved_match(MakeSimpleForm());
+ PasswordForm credit_card_form(MakeSimpleCreditCardForm());
+ credit_card_form.only_for_fallback = true;
- PasswordForm saved_match(MakeSimpleForm());
- PasswordForm credit_card_form(MakeSimpleCreditCardForm());
- credit_card_form.only_for_fallback = true;
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match)));
- EXPECT_CALL(*store_, GetLogins(_, _))
- .WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match)));
+ PasswordFormFillData form_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data));
- PasswordFormFillData form_data;
- EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data));
+ manager()->OnPasswordFormsParsed(&driver_, {credit_card_form});
+ // Check that manual filling fallback available.
+ EXPECT_EQ(saved_match.username_value, form_data.username_field.value);
+ EXPECT_EQ(saved_match.password_value, form_data.password_field.value);
+ // Check that no automatic filling available.
+ uint32_t renderer_id_not_set = FormFieldData::kNotSetFormControlRendererId;
+ EXPECT_EQ(renderer_id_not_set, form_data.username_field.unique_renderer_id);
+ EXPECT_EQ(renderer_id_not_set, form_data.password_field.unique_renderer_id);
- manager()->OnPasswordFormsParsed(&driver_, {credit_card_form});
- // Check that manual filling fallback available.
- EXPECT_EQ(saved_match.username_value, form_data.username_field.value);
- EXPECT_EQ(saved_match.password_value, form_data.password_field.value);
- // Check that no automatic filling available.
- uint32_t renderer_id_not_set = FormFieldData::kNotSetFormControlRendererId;
- EXPECT_EQ(renderer_id_not_set, form_data.username_field.unique_renderer_id);
- EXPECT_EQ(renderer_id_not_set, form_data.password_field.unique_renderer_id);
+ // Check that saving fallback is available.
+ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+ EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+ manager()->ShowManualFallbackForSaving(&driver_, credit_card_form);
+ ASSERT_TRUE(form_manager_to_save);
+ EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
+ FormMatches(credit_card_form));
- // Check that saving fallback is available.
- std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
- EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
- .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
- manager()->ShowManualFallbackForSaving(&driver_, credit_card_form);
- ASSERT_TRUE(form_manager_to_save);
- EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
- FormMatches(credit_card_form));
+ // Check that no automatic save prompt is shown.
+ OnPasswordFormSubmitted(credit_card_form);
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
+ manager()->DidNavigateMainFrame(true);
+ manager()->OnPasswordFormsRendered(&driver_, {}, true);
+}
- // Check that no automatic save prompt is shown.
- OnPasswordFormSubmitted(credit_card_form);
- EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
- manager()->DidNavigateMainFrame(true);
- manager()->OnPasswordFormsRendered(&driver_, {}, true);
+#if !defined(OS_IOS)
+// Check that on successful login the credentials are checked for leak.
+TEST_F(PasswordManagerTest, StartLeakDetection) {
+ auto mock_factory =
+ std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>();
+ MockLeakDetectionCheckFactory* weak_factory = mock_factory.get();
+ manager()->set_leak_factory(std::move(mock_factory));
- testing::Mock::VerifyAndClearExpectations(&client_);
- }
+ const PasswordForm form = MakeSimpleForm();
+ std::vector<PasswordForm> observed = {form};
+ EXPECT_CALL(*store_, GetLogins)
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms()));
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled).WillRepeatedly(Return(true));
+ OnPasswordFormSubmitted(form);
+
+ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
+ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr)
+ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
+ auto check_instance = std::make_unique<MockLeakDetectionCheck>();
+ EXPECT_CALL(*check_instance,
+ Start(form.origin, form.username_value, form.password_value));
+ EXPECT_CALL(*weak_factory, TryCreateLeakCheck)
+ .WillOnce(Return(ByMove(std::move(check_instance))));
+
+ // Now the password manager waits for the navigation to complete.
+ observed.clear();
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
}
+#endif // !defined(OS_IOS)
+// Check that a non-password form with SINGLE_USERNAME prediction is filled.
+TEST_F(PasswordManagerTest, FillSingleUsername) {
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(true);
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
+ .WillRepeatedly(Return(true));
+ PasswordForm saved_match(MakeSavedForm());
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match)));
+
+ // Create FormdData for a form with 1 text field.
+ FormData form_data;
+ const uint32_t form_id = 1001;
+ form_data.unique_renderer_id = form_id;
+ form_data.url = GURL("example.com");
+ FormFieldData field;
+ field.form_control_type = "text";
+ const uint32_t field_id = 10;
+ field.unique_renderer_id = field_id;
+ form_data.fields.push_back(field);
+
+ // Set SINGLE_USERNAME predictions for the field.
+ FormStructure form_structure(form_data);
+ form_structure.field(0)->set_server_type(autofill::SINGLE_USERNAME);
+
+#if !defined(OS_IOS)
+ PasswordFormFillData fill_data;
+ EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
+ manager()->ProcessAutofillPredictions(&driver_, {&form_structure});
+ EXPECT_EQ(form_id, fill_data.form_renderer_id);
+ EXPECT_EQ(saved_match.username_value, fill_data.username_field.value);
+ EXPECT_EQ(field_id, fill_data.username_field.unique_renderer_id);
+ EXPECT_EQ(saved_match.password_value, fill_data.password_field.value);
+ EXPECT_EQ(std::numeric_limits<uint32_t>::max(),
+ fill_data.password_field.unique_renderer_id);
+#else // defined(OS_IOS)
+ EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0);
+#endif // !defined(OS_IOS)
+}
+
+// Checks that a password form with a clear-text account creation field results
+// in marking the password field as eligible for password generation.
+TEST_F(PasswordManagerTest,
+ MarkServerPredictedClearTextPasswordFieldEligibleForGeneration) {
+ PasswordFormManager::set_wait_for_server_predictions_for_filling(true);
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
+ .WillRepeatedly(Return(true));
+ PasswordForm saved_match(MakeSavedForm());
+ EXPECT_CALL(*store_, GetLogins(_, _))
+ .WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match)));
+
+ // Create FormdData for a form with 1 text field.
+ FormData form_data;
+ const uint32_t form_id = 1001;
+ form_data.unique_renderer_id = form_id;
+ form_data.url = GURL("example.com");
+
+ FormFieldData username_field;
+ username_field.form_control_type = "text";
+ const uint32_t username_field_id = 10;
+ username_field.unique_renderer_id = username_field_id;
+ form_data.fields.push_back(username_field);
+
+ FormFieldData password_field;
+ password_field.form_control_type = "text";
+ const uint32_t password_field_id = 11;
+ password_field.unique_renderer_id = password_field_id;
+ form_data.fields.push_back(password_field);
+
+ // Set ACCOUNT_CREATION_PASSWORD predictions for the field.
+ FormStructure form_structure(form_data);
+ form_structure.field(1)->set_server_type(autofill::ACCOUNT_CREATION_PASSWORD);
+
+ autofill::PasswordFormGenerationData form_generation_data;
+ EXPECT_CALL(driver_, FormEligibleForGenerationFound(_))
+ .WillOnce(SaveArg<0>(&form_generation_data));
+ manager()->ProcessAutofillPredictions(&driver_, {&form_structure});
+#if !defined(OS_IOS)
+ EXPECT_EQ(password_field_id, form_generation_data.new_password_renderer_id);
+#endif
+}
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_manager_util.cc b/chromium/components/password_manager/core/browser/password_manager_util.cc
index 1637ad7eede..0be0134aac3 100644
--- a/chromium/components/password_manager/core/browser/password_manager_util.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_util.cc
@@ -226,36 +226,41 @@ base::StringPiece GetSignonRealmWithProtocolExcluded(const PasswordForm& form) {
}
void FindBestMatches(
- std::vector<const PasswordForm*> matches,
+ const std::vector<const PasswordForm*>& non_federated_matches,
+ PasswordForm::Scheme scheme,
+ std::vector<const autofill::PasswordForm*>* non_federated_same_scheme,
std::map<base::string16, const PasswordForm*>* best_matches,
- std::vector<const PasswordForm*>* not_best_matches,
const PasswordForm** preferred_match) {
DCHECK(std::all_of(
- matches.begin(), matches.end(),
+ non_federated_matches.begin(), non_federated_matches.end(),
[](const PasswordForm* match) { return !match->blacklisted_by_user; }));
+ DCHECK(non_federated_same_scheme);
DCHECK(best_matches);
- DCHECK(not_best_matches);
DCHECK(preferred_match);
*preferred_match = nullptr;
best_matches->clear();
- not_best_matches->clear();
+ non_federated_same_scheme->clear();
- if (matches.empty())
+ for (auto* match : non_federated_matches) {
+ if (match->scheme == scheme)
+ non_federated_same_scheme->push_back(match);
+ }
+
+ if (non_federated_same_scheme->empty())
return;
// Sort matches using IsBetterMatch predicate.
- std::sort(matches.begin(), matches.end(), IsBetterMatch);
- for (const auto* match : matches) {
+ std::sort(non_federated_same_scheme->begin(),
+ non_federated_same_scheme->end(), IsBetterMatch);
+ for (const auto* match : *non_federated_same_scheme) {
const base::string16& username = match->username_value;
// The first match for |username| in the sorted array is best match.
if (best_matches->find(username) == best_matches->end())
best_matches->insert(std::make_pair(username, match));
- else
- not_best_matches->push_back(match);
}
- *preferred_match = *matches.begin();
+ *preferred_match = *non_federated_same_scheme->begin();
}
const PasswordForm* GetMatchForUpdating(
diff --git a/chromium/components/password_manager/core/browser/password_manager_util.h b/chromium/components/password_manager/core/browser/password_manager_util.h
index 6e90fd0515f..62b32629b77 100644
--- a/chromium/components/password_manager/core/browser/password_manager_util.h
+++ b/chromium/components/password_manager/core/browser/password_manager_util.h
@@ -23,12 +23,12 @@ namespace network {
namespace mojom {
class NetworkContext;
}
-}
+} // namespace network
namespace password_manager {
class PasswordManagerDriver;
class PasswordManagerClient;
-}
+} // namespace password_manager
namespace syncer {
class SyncService;
@@ -113,16 +113,17 @@ void RemoveUselessCredentials(
base::StringPiece GetSignonRealmWithProtocolExcluded(
const autofill::PasswordForm& form);
-// Given all non-blacklisted |matches|, finds and populates
-// |best_matches_|, |preferred_match_| and |non_best_matches_| accordingly.
-// For comparing credentials the following rule is used: non-psl match is better
-// than psl match, preferred match is better than non-preferred match. In case
-// of tie, an arbitrary credential from the tied ones is chosen for
-// |best_matches| and preferred_match.
+// Given all non-blacklisted |non_federated_matches|, finds and populates
+// |best_matches| and |preferred_match_| accordingly. For comparing credentials
+// the following rule is used: non-psl match is better than psl match, preferred
+// match is better than non-preferred match. In case of tie, an arbitrary
+// credential from the tied ones is chosen for |best_matches| and
+// preferred_match.
void FindBestMatches(
- std::vector<const autofill::PasswordForm*> matches,
+ const std::vector<const autofill::PasswordForm*>& non_federated_matches,
+ autofill::PasswordForm::Scheme scheme,
+ std::vector<const autofill::PasswordForm*>* non_federated_same_scheme,
std::map<base::string16, const autofill::PasswordForm*>* best_matches,
- std::vector<const autofill::PasswordForm*>* not_best_matches,
const autofill::PasswordForm** preferred_match);
// If the user submits a form, they may have used existing credentials, new
diff --git a/chromium/components/password_manager/core/browser/password_manager_util_unittest.cc b/chromium/components/password_manager/core/browser/password_manager_util_unittest.cc
index ecb6a4464a9..b842f017595 100644
--- a/chromium/components/password_manager/core/browser/password_manager_util_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/test_password_store.h"
@@ -198,17 +198,16 @@ TEST(PasswordManagerUtil, FindBestMatches) {
matches.push_back(&match);
std::map<base::string16, const PasswordForm*> best_matches;
- std::vector<const PasswordForm*> not_best_matches;
const PasswordForm* preferred_match = nullptr;
- FindBestMatches(matches, &best_matches, &not_best_matches,
- &preferred_match);
+ std::vector<const PasswordForm*> same_scheme_matches;
+ FindBestMatches(matches, PasswordForm::Scheme::kHtml, &same_scheme_matches,
+ &best_matches, &preferred_match);
if (test_case.expected_preferred_match_index == kNotFound) {
// Case of empty |matches|.
EXPECT_FALSE(preferred_match);
EXPECT_TRUE(best_matches.empty());
- EXPECT_TRUE(not_best_matches.empty());
} else {
// Check |preferred_match|.
EXPECT_EQ(matches[test_case.expected_preferred_match_index],
@@ -228,18 +227,6 @@ TEST(PasswordManagerUtil, FindBestMatches) {
std::find(matches.begin(), matches.end(), username_match.second));
EXPECT_EQ(expected_index, actual_index);
}
-
- // Check non-best matches.
- ASSERT_EQ(matches.size(), best_matches.size() + not_best_matches.size());
- for (const PasswordForm* form : not_best_matches) {
- // A non-best match form must not be in |best_matches|.
- EXPECT_NE(best_matches[form->username_value], form);
-
- base::Erase(matches, form);
- }
- // Expect that all non-best matches were found in |matches| and only best
- // matches left.
- EXPECT_EQ(best_matches.size(), matches.size());
}
}
}
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc b/chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc
index 28c43c68215..bac595510bf 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc
@@ -9,6 +9,7 @@
#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/safe_browsing/buildflags.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
using base::Time;
@@ -123,9 +124,7 @@ void PasswordReuseDetectionManager::OnReuseFound(
metrics_util::LogPasswordReuse(password_length, saved_passwords,
matching_domains.size(),
password_field_detected, reused_password_type);
-#if defined(FULL_SAFE_BROWSING)
- // TODO(crbug/1673863): Log password reuse event for signed in non sync
- // account.
+#if BUILDFLAG(FULL_SAFE_BROWSING)
if (reused_password_type ==
metrics_util::PasswordType::PRIMARY_ACCOUNT_PASSWORD)
client_->LogPasswordReuseDetectedEvent();
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detection_manager_unittest.cc b/chromium/components/password_manager/core/browser/password_reuse_detection_manager_unittest.cc
index d46fbe5ca38..fdd5b86fe90 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detection_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_reuse_detection_manager_unittest.cc
@@ -7,8 +7,8 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -52,7 +52,7 @@ class PasswordReuseDetectionManagerTest : public ::testing::Test {
protected:
// It's needed for an initialisation of thread runners that are used in
// MockPasswordStore.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockPasswordManagerClient client_;
scoped_refptr<MockPasswordStore> store_;
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detector.cc b/chromium/components/password_manager/core/browser/password_reuse_detector.cc
index 1fbd85ddf8d..9877c4b313d 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detector.cc
+++ b/chromium/components/password_manager/core/browser/password_reuse_detector.cc
@@ -260,6 +260,18 @@ void PasswordReuseDetector::ClearAllEnterprisePasswordHash() {
enterprise_password_hash_data_list_.reset();
}
+void PasswordReuseDetector::ClearAllNonGmailPasswordHash() {
+ if (!gaia_password_hash_data_list_)
+ return;
+
+ base::EraseIf(
+ *gaia_password_hash_data_list_, [](const PasswordHashData& data) {
+ std::string email =
+ CanonicalizeUsername(data.username, data.is_gaia_password);
+ return email.find("@gmail.com") == std::string::npos;
+ });
+}
+
void PasswordReuseDetector::AddPassword(const autofill::PasswordForm& form) {
if (form.password_value.size() < kMinPasswordLengthToCheck)
return;
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detector.h b/chromium/components/password_manager/core/browser/password_reuse_detector.h
index e244bdde509..c3da09ce246 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detector.h
+++ b/chromium/components/password_manager/core/browser/password_reuse_detector.h
@@ -77,6 +77,8 @@ class PasswordReuseDetector : public PasswordStoreConsumer {
void ClearAllEnterprisePasswordHash();
+ void ClearAllNonGmailPasswordHash();
+
private:
using passwords_iterator = std::map<base::string16,
std::set<std::string>,
diff --git a/chromium/components/password_manager/core/browser/password_store.cc b/chromium/components/password_manager/core/browser/password_store.cc
index a4ebcbccc56..b0b44e893b2 100644
--- a/chromium/components/password_manager/core/browser/password_store.cc
+++ b/chromium/components/password_manager/core/browser/password_store.cc
@@ -240,15 +240,22 @@ void PasswordStore::GetLogins(const FormDigest& form,
form, base::BindOnce(
&PasswordStore::ScheduleGetFilteredLoginsWithAffiliations,
this, consumer->GetWeakPtr(), form, cutoff));
- }
-
- else {
+ } else {
PostLoginsTaskAndReplyToConsumerWithProcessedResult(
consumer, base::BindOnce(&PasswordStore::GetLoginsImpl, this, form),
base::BindOnce(FilterLogins, cutoff));
}
}
+void PasswordStore::GetLoginsByPassword(
+ const base::string16& plain_text_password,
+ PasswordStoreConsumer* consumer) {
+ DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+ PostLoginsTaskAndReplyToConsumerWithResult(
+ consumer, base::BindOnce(&PasswordStore::GetLoginsByPasswordImpl, this,
+ plain_text_password));
+}
+
void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
PostLoginsTaskAndReplyToConsumerWithResult(
@@ -400,10 +407,9 @@ void PasswordStore::PreparePasswordHashData(const std::string& sync_username) {
ScheduleEnterprisePasswordURLUpdate();
}
-void PasswordStore::SaveGaiaPasswordHash(
- const std::string& username,
- const base::string16& password,
- metrics_util::SyncPasswordHashChange event) {
+void PasswordStore::SaveGaiaPasswordHash(const std::string& username,
+ const base::string16& password,
+ GaiaPasswordHashChange event) {
SaveProtectedPasswordHash(username, password, /*is_gaia_password=*/true,
event);
}
@@ -412,20 +418,20 @@ void PasswordStore::SaveEnterprisePasswordHash(const std::string& username,
const base::string16& password) {
SaveProtectedPasswordHash(
username, password, /*is_gaia_password=*/false,
- metrics_util::SyncPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
+ GaiaPasswordHashChange::NON_GAIA_ENTERPRISE_PASSWORD_CHANGE);
}
-void PasswordStore::SaveProtectedPasswordHash(
- const std::string& username,
- const base::string16& password,
- bool is_gaia_password,
- metrics_util::SyncPasswordHashChange event) {
+void PasswordStore::SaveProtectedPasswordHash(const std::string& username,
+ const base::string16& password,
+ bool is_gaia_password,
+ GaiaPasswordHashChange event) {
if (hash_password_manager_.SavePasswordHash(username, password,
is_gaia_password)) {
- if (is_gaia_password &&
- event !=
- metrics_util::SyncPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE) {
- metrics_util::LogSyncPasswordHashChange(event);
+ bool is_syncing =
+ event != GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE &&
+ event != GaiaPasswordHashChange::NON_GAIA_ENTERPRISE_PASSWORD_CHANGE;
+ if (is_gaia_password) {
+ metrics_util::LogGaiaPasswordHashChange(event, is_syncing);
}
SchedulePasswordHashUpdate(/*should_log_metrics=*/false);
}
@@ -433,9 +439,10 @@ void PasswordStore::SaveProtectedPasswordHash(
void PasswordStore::SaveSyncPasswordHash(
const PasswordHashData& sync_password_data,
- metrics_util::SyncPasswordHashChange event) {
+ GaiaPasswordHashChange event) {
if (hash_password_manager_.SavePasswordHash(sync_password_data)) {
- metrics_util::LogSyncPasswordHashChange(event);
+ metrics_util::LogGaiaPasswordHashChange(event,
+ /*is_sync_password=*/true);
SchedulePasswordHashUpdate(/*should_log_metrics=*/false);
}
}
@@ -459,6 +466,18 @@ void PasswordStore::ClearAllEnterprisePasswordHash() {
&PasswordStore::ClearAllEnterprisePasswordHashImpl, this));
}
+void PasswordStore::ClearAllNonGmailPasswordHash() {
+ hash_password_manager_.ClearAllNonGmailPasswordHash();
+ ScheduleTask(base::BindRepeating(
+ &PasswordStore::ClearAllNonGmailPasswordHashImpl, this));
+}
+
+std::unique_ptr<StateSubscription>
+PasswordStore::RegisterStateCallbackOnHashPasswordManager(
+ const base::Callback<void(const std::string& username)>& callback) {
+ return hash_password_manager_.RegisterStateCallback(callback);
+}
+
void PasswordStore::SetPasswordStoreSigninNotifier(
std::unique_ptr<PasswordStoreSigninNotifier> notifier) {
DCHECK(!notifier_);
@@ -494,8 +513,8 @@ PasswordStore::~PasswordStore() {
scoped_refptr<base::SequencedTaskRunner>
PasswordStore::CreateBackgroundTaskRunner() const {
- return base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ return base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}
bool PasswordStore::InitOnBackgroundSequence(
@@ -632,6 +651,12 @@ void PasswordStore::ClearAllEnterprisePasswordHashImpl() {
if (reuse_detector_)
reuse_detector_->ClearAllEnterprisePasswordHash();
}
+
+void PasswordStore::ClearAllNonGmailPasswordHashImpl() {
+ if (reuse_detector_)
+ reuse_detector_->ClearAllNonGmailPasswordHash();
+}
+
#endif
void PasswordStore::OnInitCompleted(bool success) {
@@ -791,6 +816,13 @@ PasswordStore::GetLoginsImpl(const FormDigest& form) {
}
std::vector<std::unique_ptr<PasswordForm>>
+PasswordStore::GetLoginsByPasswordImpl(
+ const base::string16& plain_text_password) {
+ DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+ return FillMatchingLoginsByPassword(plain_text_password);
+}
+
+std::vector<std::unique_ptr<PasswordForm>>
PasswordStore::GetAutofillableLoginsImpl() {
DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<PasswordForm>> obtained_forms;
diff --git a/chromium/components/password_manager/core/browser/password_store.h b/chromium/components/password_manager/core/browser/password_store.h
index 7898994f298..5a6a5873ca4 100644
--- a/chromium/components/password_manager/core/browser/password_store.h
+++ b/chromium/components/password_manager/core/browser/password_store.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/callback_list.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/observer_list_threadsafe.h"
@@ -43,8 +44,15 @@ class ProxyModelTypeControllerDelegate;
class SyncableService;
}
+using StateSubscription =
+ base::CallbackList<void(const std::string& username)>::Subscription;
+
namespace password_manager {
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+using metrics_util::GaiaPasswordHashChange;
+#endif
+
class AffiliatedMatchHelper;
class PasswordStoreConsumer;
class PasswordStoreSigninNotifier;
@@ -180,6 +188,12 @@ class PasswordStore : protected PasswordStoreSync,
virtual void GetLogins(const FormDigest& form,
PasswordStoreConsumer* consumer);
+ // Searches for credentials with the specified |plain_text_password|, and
+ // notifies |consumer| on completion. The request will be cancelled if the
+ // consumer is destroyed.
+ virtual void GetLoginsByPassword(const base::string16& plain_text_password,
+ PasswordStoreConsumer* consumer);
+
// Gets the complete list of PasswordForms that are not blacklist entries--and
// are thus auto-fillable. |consumer| will be notified on completion.
// The request will be cancelled if the consumer is destroyed.
@@ -258,12 +272,12 @@ class PasswordStore : protected PasswordStoreSync,
const std::string& domain,
PasswordReuseDetectorConsumer* consumer);
- // Saves |username| and a hash of |password| for Gaia password reuse checking.
+ // Saves |username| and a hash of |password| for GAIA password reuse checking.
// |event| is used for metric logging and for distinguishing sync password
- // hash change event and other non-sync Gaia password change event.
+ // hash change event and other non-sync GAIA password change event.
virtual void SaveGaiaPasswordHash(const std::string& username,
const base::string16& password,
- metrics_util::SyncPasswordHashChange event);
+ GaiaPasswordHashChange event);
// Saves |username| and a hash of |password| for enterprise password reuse
// checking.
@@ -273,17 +287,26 @@ class PasswordStore : protected PasswordStoreSync,
// Saves |sync_password_data| for sync password reuse checking.
// |event| is used for metric logging.
virtual void SaveSyncPasswordHash(const PasswordHashData& sync_password_data,
- metrics_util::SyncPasswordHashChange event);
+ GaiaPasswordHashChange event);
- // Clears the saved Gaia password hash for |username|.
+ // Clears the saved GAIA password hash for |username|.
virtual void ClearGaiaPasswordHash(const std::string& username);
- // Clears all the Gaia password hash.
+ // Clears all the GAIA password hash.
virtual void ClearAllGaiaPasswordHash();
- // Clears all (non-Gaia) enterprise password hash.
+ // Clears all (non-GAIA) enterprise password hash.
virtual void ClearAllEnterprisePasswordHash();
+ // Clear all GAIA password hash that is not associated with a Gmail account.
+ virtual void ClearAllNonGmailPasswordHash();
+
+ // Adds a listener on |hash_password_manager_| for when |kHashPasswordData|
+ // list might have changed. Should only be called on the UI thread.
+ virtual std::unique_ptr<StateSubscription>
+ RegisterStateCallbackOnHashPasswordManager(
+ const base::Callback<void(const std::string& username)>& callback);
+
// Shouldn't be called more than once, |notifier| must be not nullptr.
void SetPasswordStoreSigninNotifier(
std::unique_ptr<PasswordStoreSigninNotifier> notifier);
@@ -398,6 +421,11 @@ class PasswordStore : protected PasswordStoreSync,
virtual std::vector<std::unique_ptr<autofill::PasswordForm>>
FillMatchingLogins(const FormDigest& form) = 0;
+ // Finds and returns all not-blacklisted PasswordForms with the specified
+ // |plain_text_password| stored in the credential database.
+ virtual std::vector<std::unique_ptr<autofill::PasswordForm>>
+ FillMatchingLoginsByPassword(const base::string16& plain_text_password) = 0;
+
// Synchronous implementation for manipulating with statistics.
virtual void AddSiteStatsImpl(const InteractionsStats& stats) = 0;
virtual void RemoveSiteStatsImpl(const GURL& origin_domain) = 0;
@@ -426,7 +454,7 @@ class PasswordStore : protected PasswordStoreSync,
void SaveProtectedPasswordHash(const std::string& username,
const base::string16& password,
bool is_gaia_password,
- metrics_util::SyncPasswordHashChange event);
+ GaiaPasswordHashChange event);
// Synchronous implementation of CheckReuse().
void CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,
@@ -449,11 +477,14 @@ class PasswordStore : protected PasswordStoreSync,
// Synchronous implementation of ClearGaiaPasswordHash(...).
void ClearGaiaPasswordHashImpl(const std::string& username);
- // Synchronous implementation of ClearAllGaiaPasswordHashImpl().
+ // Synchronous implementation of ClearAllGaiaPasswordHash().
void ClearAllGaiaPasswordHashImpl();
- // Synchronous implementation of ClearAllEnterprisePasswordHashImpl().
+ // Synchronous implementation of ClearAllEnterprisePasswordHash().
void ClearAllEnterprisePasswordHashImpl();
+
+ // Synchronous implementation of ClearAllNonGmailPasswordHash().
+ void ClearAllNonGmailPasswordHashImpl();
#endif
scoped_refptr<base::SequencedTaskRunner> main_task_runner() const {
@@ -537,6 +568,11 @@ class PasswordStore : protected PasswordStoreSync,
std::vector<std::unique_ptr<autofill::PasswordForm>> GetLoginsImpl(
const FormDigest& form);
+ // Finds all credentials with the specified |plain_text_password|.
+ // Note: subclasses should implement FillMatchingLoginsByPassword() instead.
+ std::vector<std::unique_ptr<autofill::PasswordForm>> GetLoginsByPasswordImpl(
+ const base::string16& plain_text_password);
+
// Finds all non-blacklist PasswordForms and returns the result.
std::vector<std::unique_ptr<autofill::PasswordForm>>
GetAutofillableLoginsImpl();
diff --git a/chromium/components/password_manager/core/browser/password_store_change.h b/chromium/components/password_manager/core/browser/password_store_change.h
index 5b6c2bc26e9..83d7f8f94ea 100644
--- a/chromium/components/password_manager/core/browser/password_store_change.h
+++ b/chromium/components/password_manager/core/browser/password_store_change.h
@@ -51,6 +51,7 @@ class PasswordStoreChange {
form().new_password_element == other.form().new_password_element &&
form().new_password_value == other.form().new_password_value &&
form().preferred == other.form().preferred &&
+ form().date_last_used == other.form().date_last_used &&
form().date_created == other.form().date_created &&
form().blacklisted_by_user == other.form().blacklisted_by_user;
}
diff --git a/chromium/components/password_manager/core/browser/password_store_default.cc b/chromium/components/password_manager/core/browser/password_store_default.cc
index b34eff756b1..8189a1e8549 100644
--- a/chromium/components/password_manager/core/browser/password_store_default.cc
+++ b/chromium/components/password_manager/core/browser/password_store_default.cc
@@ -168,6 +168,16 @@ PasswordStoreDefault::FillMatchingLogins(const FormDigest& form) {
return matched_forms;
}
+std::vector<std::unique_ptr<PasswordForm>>
+PasswordStoreDefault::FillMatchingLoginsByPassword(
+ const base::string16& plain_text_password) {
+ std::vector<std::unique_ptr<PasswordForm>> matched_forms;
+ if (login_db_ &&
+ !login_db_->GetLoginsByPassword(plain_text_password, &matched_forms))
+ return std::vector<std::unique_ptr<PasswordForm>>();
+ return matched_forms;
+}
+
bool PasswordStoreDefault::FillAutofillableLogins(
std::vector<std::unique_ptr<PasswordForm>>* forms) {
DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
@@ -251,6 +261,14 @@ PasswordStoreSync::MetadataStore* PasswordStoreDefault::GetMetadataStore() {
return login_db_.get();
}
+bool PasswordStoreDefault::IsAccountStore() const {
+ return login_db_->is_account_store();
+}
+
+bool PasswordStoreDefault::DeleteAndRecreateDatabaseFile() {
+ return login_db_->DeleteAndRecreateDatabaseFile();
+}
+
void PasswordStoreDefault::ResetLoginDB() {
DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
login_db_.reset();
diff --git a/chromium/components/password_manager/core/browser/password_store_default.h b/chromium/components/password_manager/core/browser/password_store_default.h
index efc82d5164e..7d9a0200d33 100644
--- a/chromium/components/password_manager/core/browser/password_store_default.h
+++ b/chromium/components/password_manager/core/browser/password_store_default.h
@@ -68,6 +68,9 @@ class PasswordStoreDefault : public PasswordStore {
base::Time delete_end) override;
std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
const FormDigest& form) override;
+ std::vector<std::unique_ptr<autofill::PasswordForm>>
+ FillMatchingLoginsByPassword(
+ const base::string16& plain_text_password) override;
bool FillAutofillableLogins(
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
bool FillBlacklistLogins(
@@ -87,10 +90,8 @@ class PasswordStoreDefault : public PasswordStore {
PrimaryKeyToFormMap* key_to_form_map) override;
PasswordStoreChangeList RemoveLoginByPrimaryKeySync(int primary_key) override;
PasswordStoreSync::MetadataStore* GetMetadataStore() override;
-
- inline bool DeleteAndRecreateDatabaseFile() {
- return login_db_->DeleteAndRecreateDatabaseFile();
- }
+ bool IsAccountStore() const override;
+ bool DeleteAndRecreateDatabaseFile() override;
private:
// Resets |login_db_| on the background sequence.
diff --git a/chromium/components/password_manager/core/browser/password_store_default_unittest.cc b/chromium/components/password_manager/core/browser/password_store_default_unittest.cc
index 88e8a5f439b..040adb4e347 100644
--- a/chromium/components/password_manager/core/browser/password_store_default_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_store_default_unittest.cc
@@ -14,7 +14,7 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/password_manager/core/browser/login_database.h"
@@ -51,7 +51,7 @@ class MockPasswordStoreConsumer : public PasswordStoreConsumer {
// A mock LoginDatabase that simulates a failing Init() method.
class BadLoginDatabase : public LoginDatabase {
public:
- BadLoginDatabase() : LoginDatabase(base::FilePath()) {}
+ BadLoginDatabase() : LoginDatabase(base::FilePath(), IsAccountStore(false)) {}
~BadLoginDatabase() override {}
// LoginDatabase:
@@ -97,7 +97,7 @@ class PasswordStoreDefaultTestDelegate {
base::FilePath test_login_db_file_path() const;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
scoped_refptr<PasswordStoreDefault> store_;
@@ -105,18 +105,16 @@ class PasswordStoreDefaultTestDelegate {
};
PasswordStoreDefaultTestDelegate::PasswordStoreDefaultTestDelegate()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {
OSCryptMocker::SetUp();
SetupTempDir();
- store_ = CreateInitializedStore(
- std::make_unique<LoginDatabase>(test_login_db_file_path()));
+ store_ = CreateInitializedStore(std::make_unique<LoginDatabase>(
+ test_login_db_file_path(), IsAccountStore(false)));
}
PasswordStoreDefaultTestDelegate::PasswordStoreDefaultTestDelegate(
std::unique_ptr<LoginDatabase> database)
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {
OSCryptMocker::SetUp();
SetupTempDir();
store_ = CreateInitializedStore(std::move(database));
@@ -128,7 +126,7 @@ PasswordStoreDefaultTestDelegate::~PasswordStoreDefaultTestDelegate() {
}
void PasswordStoreDefaultTestDelegate::FinishAsyncProcessing() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void PasswordStoreDefaultTestDelegate::SetupTempDir() {
diff --git a/chromium/components/password_manager/core/browser/password_store_factory_util.cc b/chromium/components/password_manager/core/browser/password_store_factory_util.cc
index 38b009d8459..76ab0744c51 100644
--- a/chromium/components/password_manager/core/browser/password_store_factory_util.cc
+++ b/chromium/components/password_manager/core/browser/password_store_factory_util.cc
@@ -40,8 +40,8 @@ void ActivateAffiliationBasedMatching(
//
// Task priority is USER_VISIBLE, because AffiliationService-related tasks
// block obtaining credentials from PasswordStore, hence password autofill.
- static auto backend_task_runner = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ static auto backend_task_runner = base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
// The PasswordStore is so far the only consumer of the AffiliationService,
// therefore the service is owned by the AffiliatedMatchHelper, which in turn
@@ -85,10 +85,20 @@ void ToggleAffiliationBasedMatchingBasedOnPasswordSyncedState(
}
}
-std::unique_ptr<LoginDatabase> CreateLoginDatabase(
+std::unique_ptr<LoginDatabase> CreateLoginDatabaseForProfileStorage(
const base::FilePath& profile_path) {
- base::FilePath login_db_file_path = profile_path.Append(kLoginDataFileName);
- return std::make_unique<LoginDatabase>(login_db_file_path);
+ base::FilePath login_db_file_path =
+ profile_path.Append(kLoginDataForProfileFileName);
+ return std::make_unique<LoginDatabase>(login_db_file_path,
+ IsAccountStore(false));
+}
+
+std::unique_ptr<LoginDatabase> CreateLoginDatabaseForAccountStorage(
+ const base::FilePath& profile_path) {
+ base::FilePath login_db_file_path =
+ profile_path.Append(kLoginDataForAccountFileName);
+ return std::make_unique<LoginDatabase>(login_db_file_path,
+ IsAccountStore(true));
}
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_store_factory_util.h b/chromium/components/password_manager/core/browser/password_store_factory_util.h
index 58e05f5799b..eaef85ac49e 100644
--- a/chromium/components/password_manager/core/browser/password_store_factory_util.h
+++ b/chromium/components/password_manager/core/browser/password_store_factory_util.h
@@ -38,7 +38,9 @@ void ToggleAffiliationBasedMatchingBasedOnPasswordSyncedState(
// Creates a LoginDatabase. Looks in |profile_path| for the database file.
// Does not call LoginDatabase::Init() -- to avoid UI jank, that needs to be
// called by PasswordStore::Init() on the background thread.
-std::unique_ptr<LoginDatabase> CreateLoginDatabase(
+std::unique_ptr<LoginDatabase> CreateLoginDatabaseForProfileStorage(
+ const base::FilePath& profile_path);
+std::unique_ptr<LoginDatabase> CreateLoginDatabaseForAccountStorage(
const base::FilePath& profile_path);
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc b/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc
index 217c067056a..c17f214ef14 100644
--- a/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc
+++ b/chromium/components/password_manager/core/browser/password_store_signin_notifier.cc
@@ -19,8 +19,9 @@ void PasswordStoreSigninNotifier::NotifySignedOut(const std::string& username,
return;
if (primary_account) {
- metrics_util::LogSyncPasswordHashChange(
- metrics_util::SyncPasswordHashChange::CLEARED_ON_CHROME_SIGNOUT);
+ metrics_util::LogGaiaPasswordHashChange(
+ metrics_util::GaiaPasswordHashChange::CLEARED_ON_CHROME_SIGNOUT,
+ /*is_sync_password=*/true);
store_->ClearAllGaiaPasswordHash();
} else {
store_->ClearGaiaPasswordHash(username);
diff --git a/chromium/components/password_manager/core/browser/password_store_sync.h b/chromium/components/password_manager/core/browser/password_store_sync.h
index 0640c1c3929..b03d106207a 100644
--- a/chromium/components/password_manager/core/browser/password_store_sync.h
+++ b/chromium/components/password_manager/core/browser/password_store_sync.h
@@ -163,6 +163,15 @@ class PasswordStoreSync {
// sync metadata.
virtual MetadataStore* GetMetadataStore() = 0;
+ // Returns whether this is the profile-scoped or the account-scoped storage:
+ // true: Gaia-account-scoped store, which is used for signed-in but not
+ // syncing users.
+ // false: Profile-scoped store, which is used for local storage and for
+ // syncing users.
+ virtual bool IsAccountStore() const = 0;
+
+ virtual bool DeleteAndRecreateDatabaseFile() = 0;
+
protected:
virtual ~PasswordStoreSync();
diff --git a/chromium/components/password_manager/core/browser/password_store_unittest.cc b/chromium/components/password_manager/core/browser/password_store_unittest.cc
index b7f291e9e16..f8f5f3ee154 100644
--- a/chromium/components/password_manager/core/browser/password_store_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_store_unittest.cc
@@ -15,7 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/os_crypt/os_crypt_mocker.h"
#include "components/password_manager/core/browser/android_affiliation/affiliated_match_helper.h"
@@ -109,8 +109,7 @@ class StartSyncFlareMock {
class PasswordStoreTest : public testing::Test {
protected:
PasswordStoreTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
@@ -123,15 +122,20 @@ class PasswordStoreTest : public testing::Test {
OSCryptMocker::TearDown();
}
- void WaitForPasswordStore() { scoped_task_environment_.RunUntilIdle(); }
+ void WaitForPasswordStore() { task_environment_.RunUntilIdle(); }
base::FilePath test_login_db_file_path() const {
return temp_dir_.GetPath().Append(FILE_PATH_LITERAL("login_test"));
}
+ scoped_refptr<PasswordStoreDefault> CreatePasswordStore() {
+ return new PasswordStoreDefault(std::make_unique<LoginDatabase>(
+ test_login_db_file_path(), password_manager::IsAccountStore(false)));
+ }
+
private:
base::ScopedTempDir temp_dir_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(PasswordStoreTest);
};
@@ -147,40 +151,40 @@ base::Optional<PasswordHashData> GetPasswordFromPref(
}
TEST_F(PasswordStoreTest, IgnoreOldWwwGoogleLogins) {
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
const time_t cutoff = 1325376000; // 00:00 Jan 1 2012 UTC
+ const time_t last_usage_time = 1546300800; // 00:00 Jan 1 2019 UTC
static const PasswordFormData form_data[] = {
// A form on https://www.google.com/ older than the cutoff. Will be
// ignored.
{PasswordForm::Scheme::kHtml, "https://www.google.com",
"https://www.google.com/origin", "https://www.google.com/action",
L"submit_element", L"username_element", L"password_element",
- L"username_value_1", L"", true, cutoff - 1},
+ L"username_value_1", L"", true, last_usage_time, cutoff - 1},
// A form on https://www.google.com/ older than the cutoff. Will be
// ignored.
{PasswordForm::Scheme::kHtml, "https://www.google.com",
"https://www.google.com/origin", "https://www.google.com/action",
L"submit_element", L"username_element", L"password_element",
- L"username_value_2", L"", true, cutoff - 1},
+ L"username_value_2", L"", true, last_usage_time, cutoff - 1},
// A form on https://www.google.com/ newer than the cutoff.
{PasswordForm::Scheme::kHtml, "https://www.google.com",
"https://www.google.com/origin", "https://www.google.com/action",
L"submit_element", L"username_element", L"password_element",
- L"username_value_3", L"", true, cutoff + 1},
+ L"username_value_3", L"", true, last_usage_time, cutoff + 1},
// A form on https://accounts.google.com/ older than the cutoff.
{PasswordForm::Scheme::kHtml, "https://accounts.google.com",
"https://accounts.google.com/origin",
"https://accounts.google.com/action", L"submit_element",
L"username_element", L"password_element", L"username_value", L"", true,
- cutoff - 1},
+ last_usage_time, cutoff - 1},
// A form on http://bar.example.com/ older than the cutoff.
{PasswordForm::Scheme::kHtml, "http://bar.example.com",
"http://bar.example.com/origin", "http://bar.example.com/action",
L"submit_element", L"username_element", L"password_element",
- L"username_value", L"", true, cutoff - 1},
+ L"username_value", L"", true, last_usage_time, cutoff - 1},
};
// Build the forms vector and add the forms to the store.
@@ -241,8 +245,7 @@ TEST_F(PasswordStoreTest, StartSyncFlare) {
// This test isn't relevant for USS code path.
if (base::FeatureList::IsEnabled(switches::kSyncUSSPasswords))
return;
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
StartSyncFlareMock mock;
store->Init(
base::Bind(&StartSyncFlareMock::StartSyncFlare, base::Unretained(&mock)),
@@ -277,8 +280,7 @@ TEST_F(PasswordStoreTest, UpdateLoginPrimaryKeyFields) {
L"", true, 1}};
/* clang-format on */
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
std::unique_ptr<PasswordForm> old_form(
@@ -329,8 +331,7 @@ TEST_F(PasswordStoreTest, RemoveLoginsCreatedBetweenCallbackIsCalled) {
L"", true, 1};
/* clang-format on */
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
std::unique_ptr<PasswordForm> test_form(
@@ -381,8 +382,7 @@ TEST_F(PasswordStoreTest, GetLoginsWithoutAffiliations) {
L"", true, 1}};
/* clang-format on */
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
std::vector<std::unique_ptr<PasswordForm>> all_credentials;
@@ -481,8 +481,7 @@ TEST_F(PasswordStoreTest, GetLoginsWithAffiliations) {
false,
}};
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
std::vector<std::unique_ptr<PasswordForm>> all_credentials;
@@ -546,6 +545,7 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
const wchar_t kTestOldPassword[] = L"old_password_value";
const wchar_t kTestNewPassword[] = L"new_password_value";
const wchar_t kTestOtherPassword[] = L"other_password_value";
+ const time_t last_usage_time = 1546300800; // 00:00 Jan 1 2019 UTC
/* clang-format off */
static const PasswordFormData kTestCredentials[] = {
@@ -556,7 +556,7 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
kTestAndroidRealm1,
"", "", L"", L"", L"",
kTestUsername,
- kTestOldPassword, true, 2},
+ kTestOldPassword, true, last_usage_time, 2},
// --- Positive samples --- Credentials that the password update should be
// automatically propagated to.
@@ -567,7 +567,7 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
kTestWebOrigin1,
"", L"", L"", L"",
kTestUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true, last_usage_time, 1},
// Credential for another affiliated web site with the same username.
// Although the password is different than the current/old password for
// the Android application, it should be updated regardless.
@@ -576,7 +576,7 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
kTestWebOrigin2,
"", L"", L"", L"",
kTestUsername,
- kTestOtherPassword, true, 1},
+ kTestOtherPassword, true,last_usage_time, 1},
// --- Negative samples --- Credentials that the password update should
// not be propagated to.
@@ -588,21 +588,21 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
kTestWebOrigin3,
"", L"", L"", L"",
kTestUsername,
- kTestNewPassword, true, 1},
+ kTestNewPassword, true, last_usage_time, 1},
// Credential for the HTTP version of an affiliated web site.
{PasswordForm::Scheme::kHtml,
kTestInsecureWebRealm,
kTestInsecureWebOrigin,
"", L"", L"", L"",
kTestUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true, last_usage_time, 1},
// Credential for an affiliated web site, but with a different username.
{PasswordForm::Scheme::kHtml,
kTestWebRealm1,
kTestWebOrigin1,
"", L"", L"", L"",
kTestOtherUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true,last_usage_time, 1},
// Credential for a web site that is a PSL match to a web sites affiliated
// with the Android application.
{PasswordForm::Scheme::kHtml,
@@ -610,26 +610,26 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
kTestPSLMatchingWebOrigin,
"poisoned", L"poisoned", L"", L"",
kTestUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true,last_usage_time, 1},
// Credential for an unrelated web site.
{PasswordForm::Scheme::kHtml,
kTestUnrelatedWebRealm,
kTestUnrelatedWebOrigin,
"", L"", L"", L"",
kTestUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true,last_usage_time, 1},
// Credential for an affiliated Android application.
{PasswordForm::Scheme::kHtml,
kTestAndroidRealm2,
"", "", L"", L"", L"",
kTestUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true,last_usage_time, 1},
// Credential for an unrelated Android application.
{PasswordForm::Scheme::kHtml,
kTestUnrelatedAndroidRealm,
"", "", L"", L"", L"",
kTestUsername,
- kTestOldPassword, true, 1},
+ kTestOldPassword, true,last_usage_time, 1},
// Credential for an affiliated web site with the same username, but one
// that was updated at the same time via Sync as the Android credential.
{PasswordForm::Scheme::kHtml,
@@ -637,7 +637,7 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
kTestWebOrigin5,
"", L"", L"", L"",
kTestUsername,
- kTestOtherPassword, true, 2}};
+ kTestOtherPassword, true, last_usage_time, 2}};
/* clang-format on */
// The number of positive samples in |kTestCredentials|.
@@ -648,8 +648,7 @@ TEST_F(PasswordStoreTest, UpdatePasswordsStoredForAffiliatedWebsites) {
SCOPED_TRACE(testing::Message("test_remove_and_add_login: ")
<< test_remove_and_add_login);
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max(),
base::Closure());
@@ -746,8 +745,7 @@ TEST_F(PasswordStoreTest, GetAllLogins) {
{PasswordForm::Scheme::kHtml, kTestWebRealm3, kTestWebOrigin3, "", L"",
L"", L"", nullptr, L"", true, 1}};
- auto store = base::MakeRefCounted<PasswordStoreDefault>(
- std::make_unique<LoginDatabase>(test_login_db_file_path()));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
std::vector<std::unique_ptr<PasswordForm>> all_credentials;
@@ -769,6 +767,72 @@ TEST_F(PasswordStoreTest, GetAllLogins) {
store->ShutdownOnUIThread();
}
+// Tests if all credentials in the store with a specific password are
+// successfully transferred to the consumer.
+TEST_F(PasswordStoreTest, GetLogisByPassword) {
+ static constexpr wchar_t tested_password[] = L"duplicated_password";
+ static constexpr wchar_t another_tested_password[] = L"some_other_password";
+ static constexpr wchar_t untested_password[] = L"and_another_password";
+
+ // The first, third and forth credentials use the same password, but the forth
+ // is blacklisted.
+ static constexpr PasswordFormData kTestCredentials[] = {
+ // Has the specified password:
+ {PasswordForm::Scheme::kHtml, kTestAndroidRealm1, "", "", L"", L"", L"",
+ L"username_value_1", tested_password, true, 1},
+ // Has another password:
+ {PasswordForm::Scheme::kHtml, kTestAndroidRealm2, "", "", L"", L"", L"",
+ L"username_value_2", another_tested_password, true, 1},
+ // Has the specified password:
+ {PasswordForm::Scheme::kHtml, kTestAndroidRealm3, "", "", L"", L"", L"",
+ L"username_value_3", tested_password, true, 1},
+ // Has a third password:
+ {PasswordForm::Scheme::kHtml, kTestWebRealm1, kTestWebOrigin1, "", L"",
+ L"", L"", L"username_value_4", untested_password, true, 1},
+ // A PasswordFormData with nullptr as the username_value will be converted
+ // in a blacklisted PasswordForm in FillPasswordFormWithData().
+ // Has the specified password, but is blacklisted.
+ {PasswordForm::Scheme::kHtml, kTestWebRealm3, kTestWebOrigin3, "", L"",
+ L"", L"", nullptr, tested_password, true, 1}};
+
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
+ store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
+
+ std::vector<std::unique_ptr<PasswordForm>> all_credentials;
+ for (const auto& test_credential : kTestCredentials) {
+ all_credentials.push_back(FillPasswordFormWithData(test_credential));
+ store->AddLogin(*all_credentials.back());
+ }
+
+ MockPasswordStoreConsumer mock_consumer;
+ std::vector<std::unique_ptr<PasswordForm>> expected_results;
+ expected_results.push_back(
+ std::make_unique<PasswordForm>(*all_credentials[0]));
+ expected_results.push_back(
+ std::make_unique<PasswordForm>(*all_credentials[2]));
+
+ EXPECT_CALL(mock_consumer,
+ OnGetPasswordStoreResultsConstRef(
+ UnorderedPasswordFormElementsAre(&expected_results)));
+ store->GetLoginsByPassword(base::WideToUTF16(tested_password),
+ &mock_consumer);
+ WaitForPasswordStore();
+
+ // Tries to find all credentials with |another_tested_password|.
+ expected_results.clear();
+ expected_results.push_back(
+ std::make_unique<PasswordForm>(*all_credentials[1]));
+
+ EXPECT_CALL(mock_consumer,
+ OnGetPasswordStoreResultsConstRef(
+ UnorderedPasswordFormElementsAre(&expected_results)));
+ store->GetLoginsByPassword(base::WideToUTF16(another_tested_password),
+ &mock_consumer);
+ WaitForPasswordStore();
+
+ store->ShutdownOnUIThread();
+}
+
TEST_F(PasswordStoreTest, GetAllLoginsWithAffiliationAndBrandingInformation) {
static constexpr PasswordFormData kTestCredentials[] = {
{PasswordForm::Scheme::kHtml, kTestAndroidRealm1, "", "", L"", L"", L"",
@@ -786,8 +850,7 @@ TEST_F(PasswordStoreTest, GetAllLoginsWithAffiliationAndBrandingInformation) {
{PasswordForm::Scheme::kHtml, kTestWebRealm3, kTestWebOrigin3, "", L"",
L"", L"", nullptr, L"", true, 1}};
- auto store = base::MakeRefCounted<PasswordStoreDefault>(
- std::make_unique<LoginDatabase>(test_login_db_file_path()));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
std::vector<std::unique_ptr<PasswordForm>> all_credentials;
@@ -843,8 +906,7 @@ TEST_F(PasswordStoreTest, CheckPasswordReuse) {
{PasswordForm::Scheme::kHtml, "https://facebook.com",
"https://facebook.com", "", L"", L"", L"", L"", L"topsecret", true, 1}};
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
for (const auto& test_credentials : kTestCredentials) {
@@ -883,8 +945,7 @@ TEST_F(PasswordStoreTest, CheckPasswordReuse) {
}
TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
TestingPrefServiceSimple prefs;
prefs.registry()->RegisterListPref(prefs::kPasswordHashDataList,
@@ -896,7 +957,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
const base::string16 input = base::ASCIIToUTF16("123password");
store->SaveGaiaPasswordHash(
"sync_username", sync_password,
- metrics_util::SyncPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
+ metrics_util::GaiaPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
WaitForPasswordStore();
EXPECT_TRUE(prefs.HasPrefPath(prefs::kPasswordHashDataList));
base::Optional<PasswordHashData> sync_password_hash =
@@ -914,9 +975,8 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
// Save a non-sync Gaia password this time.
const base::string16 gaia_password = base::ASCIIToUTF16("3password");
- store->SaveGaiaPasswordHash(
- "other_gaia_username", gaia_password,
- metrics_util::SyncPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
+ store->SaveGaiaPasswordHash("other_gaia_username", gaia_password,
+ GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
base::Optional<PasswordHashData> gaia_password_hash = GetPasswordFromPref(
"other_gaia_username", /*is_gaia_password=*/true, &prefs);
ASSERT_TRUE(gaia_password_hash.has_value());
@@ -943,7 +1003,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
store->ClearAllGaiaPasswordHash();
EXPECT_EQ(0u, prefs.GetList(prefs::kPasswordHashDataList)->GetList().size());
EXPECT_CALL(mock_consumer, OnReuseFound(_, _, _, _)).Times(0);
- store->CheckReuse(input, "https://facebook.com", &mock_consumer);
+ store->CheckReuse(input, "https://example.com", &mock_consumer);
WaitForPasswordStore();
testing::Mock::VerifyAndClearExpectations(&mock_consumer);
@@ -972,12 +1032,57 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
WaitForPasswordStore();
testing::Mock::VerifyAndClearExpectations(&mock_consumer);
+ // Save a Gmail password this time.
+ const base::string16 gmail_password = base::ASCIIToUTF16("gmailpass");
+ store->SaveGaiaPasswordHash("username@gmail.com", gmail_password,
+ GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
+ WaitForPasswordStore();
+ EXPECT_TRUE(prefs.HasPrefPath(prefs::kPasswordHashDataList));
+ base::Optional<PasswordHashData> gmail_password_hash = GetPasswordFromPref(
+ "username@gmail.com", /*is_gaia_password=*/true, &prefs);
+ ASSERT_TRUE(gmail_password_hash.has_value());
+
+ // Check that gmail password reuse is found.
+ EXPECT_CALL(mock_consumer,
+ OnReuseFound(gmail_password.size(), Matches(gmail_password_hash),
+ std::vector<std::string>(), 0));
+ store->CheckReuse(gmail_password, "https://example.com", &mock_consumer);
+ WaitForPasswordStore();
+ testing::Mock::VerifyAndClearExpectations(&mock_consumer);
+
+ // Also save another non-sync Gaia password this time.
+ const base::string16 non_sync_gaia_password = base::ASCIIToUTF16("3password");
+ store->SaveGaiaPasswordHash("non_sync_gaia_password@gsuite.com",
+ non_sync_gaia_password,
+ GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
+ base::Optional<PasswordHashData> non_sync_gaia_password_hash =
+ GetPasswordFromPref("non_sync_gaia_password@gsuite.com",
+ /*is_gaia_password=*/true, &prefs);
+ ASSERT_TRUE(non_sync_gaia_password_hash.has_value());
+ EXPECT_EQ(2u, prefs.GetList(prefs::kPasswordHashDataList)->GetList().size());
+
+ // Check that no non-gmail password reuse is found after clearing the
+ // password hash.
+ store->ClearAllNonGmailPasswordHash();
+ EXPECT_EQ(1u, prefs.GetList(prefs::kPasswordHashDataList)->GetList().size());
+ EXPECT_CALL(mock_consumer, OnReuseFound(_, _, _, _)).Times(0);
+ store->CheckReuse(non_sync_gaia_password, "https://example.com",
+ &mock_consumer);
+ WaitForPasswordStore();
+ testing::Mock::VerifyAndClearExpectations(&mock_consumer);
+ EXPECT_CALL(mock_consumer,
+ OnReuseFound(gmail_password.size(), Matches(gmail_password_hash),
+ std::vector<std::string>(), 0))
+ .Times(1);
+ store->CheckReuse(gmail_password, "https://example.com", &mock_consumer);
+ WaitForPasswordStore();
+ testing::Mock::VerifyAndClearExpectations(&mock_consumer);
+
store->ShutdownOnUIThread();
}
TEST_F(PasswordStoreTest, SubscriptionAndUnsubscriptionFromSignInEvents) {
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
std::unique_ptr<MockPasswordStoreSigninNotifier> notifier =
std::make_unique<MockPasswordStoreSigninNotifier>();
@@ -994,8 +1099,7 @@ TEST_F(PasswordStoreTest, SubscriptionAndUnsubscriptionFromSignInEvents) {
}
TEST_F(PasswordStoreTest, ReportMetricsForAdvancedProtection) {
- scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
- std::make_unique<LoginDatabase>(test_login_db_file_path())));
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
TestingPrefServiceSimple prefs;
prefs.registry()->RegisterListPref(prefs::kPasswordHashDataList,
@@ -1003,6 +1107,7 @@ TEST_F(PasswordStoreTest, ReportMetricsForAdvancedProtection) {
ASSERT_FALSE(prefs.HasPrefPath(prefs::kSyncPasswordHash));
store->Init(syncer::SyncableService::StartSyncFlare(), &prefs);
+ // Hash does not exist yet.
base::HistogramTester histogram_tester;
store->ReportMetrics("sync_username", false, true);
std::string name =
@@ -1013,15 +1118,54 @@ TEST_F(PasswordStoreTest, ReportMetricsForAdvancedProtection) {
// Save password.
const base::string16 sync_password = base::ASCIIToUTF16("password");
const base::string16 input = base::ASCIIToUTF16("123password");
- store->SaveGaiaPasswordHash(
- "sync_username", sync_password,
- metrics_util::SyncPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
+ store->SaveGaiaPasswordHash("sync_username", sync_password,
+ GaiaPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
WaitForPasswordStore();
store->ReportMetrics("sync_username", false, true);
histogram_tester.ExpectBucketCount(
name, metrics_util::IsSyncPasswordHashSaved::SAVED_VIA_LIST_PREF, 1);
+ histogram_tester.ExpectBucketCount(
+ "PasswordManager.SyncPasswordHashChange",
+ GaiaPasswordHashChange::SAVED_ON_CHROME_SIGNIN, 1);
+ store->ShutdownOnUIThread();
+}
+
+TEST_F(PasswordStoreTest, ReportMetricsForNonSyncPassword) {
+ scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore();
+
+ TestingPrefServiceSimple prefs;
+ prefs.registry()->RegisterListPref(prefs::kPasswordHashDataList,
+ PrefRegistry::NO_REGISTRATION_FLAGS);
+ ASSERT_FALSE(prefs.HasPrefPath(prefs::kSyncPasswordHash));
+ store->Init(syncer::SyncableService::StartSyncFlare(), &prefs);
+
+ // Hash does not exist yet.
+ base::HistogramTester histogram_tester;
+ store->ReportMetrics("not_sync_username",
+ /*custom_passphrase_sync_enabled=*/false,
+ /*is_under_advanced_protection=*/true);
+ std::string name =
+ "PasswordManager.IsSyncPasswordHashSavedForAdvancedProtectionUser";
+ histogram_tester.ExpectBucketCount(
+ name, metrics_util::IsSyncPasswordHashSaved::NOT_SAVED, 1);
+ // Save password.
+ const base::string16 not_sync_password = base::ASCIIToUTF16("password");
+ const base::string16 input = base::ASCIIToUTF16("123password");
+ store->SaveGaiaPasswordHash("not_sync_username", not_sync_password,
+ GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
+ WaitForPasswordStore();
+
+ store->ReportMetrics("not_sync_username",
+ /*custom_passphrase_sync_enabled=*/false,
+ /*is_under_advanced_protection=*/true);
+ // Check that the non sync hash password was saved.
+ histogram_tester.ExpectBucketCount(
+ name, metrics_util::IsSyncPasswordHashSaved::SAVED_VIA_LIST_PREF, 1);
+ histogram_tester.ExpectBucketCount(
+ "PasswordManager.NonSyncPasswordHashChange",
+ GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE, 1);
store->ShutdownOnUIThread();
}
diff --git a/chromium/components/password_manager/core/browser/password_sync_util.cc b/chromium/components/password_manager/core/browser/password_sync_util.cc
index 7d43c6e7a3e..18279789c92 100644
--- a/chromium/components/password_manager/core/browser/password_sync_util.cc
+++ b/chromium/components/password_manager/core/browser/password_sync_util.cc
@@ -50,7 +50,7 @@ std::string GetSyncUsernameIfSyncingPasswords(
bool IsSyncAccountCredential(const autofill::PasswordForm& form,
const syncer::SyncService* sync_service,
const signin::IdentityManager* identity_manager) {
- if (!IsGaiaCredentialPage(form.signon_realm))
+ if (!GURL(form.signon_realm).DomainIs("google.com"))
return false;
// The empty username can mean that Chrome did not detect it correctly. For
diff --git a/chromium/components/password_manager/core/browser/password_sync_util_unittest.cc b/chromium/components/password_manager/core/browser/password_sync_util_unittest.cc
index af916006ec6..9a02d6a9fe3 100644
--- a/chromium/components/password_manager/core/browser/password_sync_util_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_sync_util_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/sync_username_test_base.h"
@@ -19,6 +20,7 @@
#endif // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
using autofill::PasswordForm;
+using base::ASCIIToUTF16;
namespace password_manager {
namespace sync_util {
@@ -31,6 +33,13 @@ PasswordForm SimpleGAIAChangePasswordForm() {
return form;
}
+PasswordForm SimpleForm(const char* signon_realm, const char* username) {
+ PasswordForm form;
+ form.signon_realm = signon_realm;
+ form.username_value = ASCIIToUTF16(username);
+ return form;
+}
+
TEST_F(PasswordSyncUtilTest, GetSyncUsernameIfSyncingPasswords) {
const struct TestCase {
enum { SYNCING_PASSWORDS, NOT_SYNCING_PASSWORDS } password_sync;
@@ -82,6 +91,10 @@ TEST_F(PasswordSyncUtilTest, IsSyncAccountCredential) {
{SimpleGaiaForm(""), "sync_user@example.org", true},
{SimpleNonGaiaForm(""), "sync_user@example.org", false},
{SimpleGAIAChangePasswordForm(), "sync_user@example.org", true},
+ {SimpleForm("https://subdomain.google.com/", "sync_user@example.org"),
+ "sync_user@example.org", true},
+ {SimpleForm("https://subdomain.google.com/", ""), "sync_user@example.org",
+ true},
};
for (size_t i = 0; i < base::size(kTestCases); ++i) {
diff --git a/chromium/components/password_manager/core/browser/psl_matching_helper.cc b/chromium/components/password_manager/core/browser/psl_matching_helper.cc
index 3ac27eb8a56..567a6e18152 100644
--- a/chromium/components/password_manager/core/browser/psl_matching_helper.cc
+++ b/chromium/components/password_manager/core/browser/psl_matching_helper.cc
@@ -18,6 +18,14 @@ using autofill::PasswordForm;
namespace password_manager {
+namespace {
+bool IsAllowedForPSLMatchedGoogleDomain(const GURL& url) {
+ return url.DomainIs("myaccount.google.com") ||
+ url.DomainIs("accounts.google.com");
+}
+
+} // namespace
+
std::ostream& operator<<(std::ostream& out, MatchResult result) {
switch (result) {
case MatchResult::NO_MATCH:
@@ -61,35 +69,28 @@ MatchResult GetMatchResult(const PasswordForm& form,
// PSL and federated matches only apply to HTML forms.
if (form_digest.scheme != PasswordForm::Scheme::kHtml ||
- form.scheme != PasswordForm::Scheme::kHtml)
+ form.scheme != PasswordForm::Scheme::kHtml) {
return MatchResult::NO_MATCH;
+ }
- const bool allow_psl_match = ShouldPSLDomainMatchingApply(
- GetRegistryControlledDomain(GURL(form_digest.signon_realm)));
- const bool allow_federated_match = !form.federation_origin.opaque();
-
- if (allow_psl_match &&
- IsPublicSuffixDomainMatch(form.signon_realm, form_digest.signon_realm))
+ if (IsPublicSuffixDomainMatch(form.signon_realm, form_digest.signon_realm))
return MatchResult::PSL_MATCH;
+ const bool allow_federated_match = !form.federation_origin.opaque();
if (allow_federated_match &&
IsFederatedRealm(form.signon_realm, form_digest.origin) &&
- form.origin.GetOrigin() == form_digest.origin.GetOrigin())
+ form.origin.GetOrigin() == form_digest.origin.GetOrigin()) {
return MatchResult::FEDERATED_MATCH;
+ }
- if (allow_psl_match && allow_federated_match &&
- IsFederatedPSLMatch(form.signon_realm, form.origin, form_digest.origin))
+ if (allow_federated_match &&
+ IsFederatedPSLMatch(form.signon_realm, form.origin, form_digest.origin)) {
return MatchResult::FEDERATED_PSL_MATCH;
+ }
return MatchResult::NO_MATCH;
}
-bool ShouldPSLDomainMatchingApply(
- const std::string& registry_controlled_domain) {
- return !registry_controlled_domain.empty() &&
- registry_controlled_domain != "google.com";
-}
-
bool IsPublicSuffixDomainMatch(const std::string& url1,
const std::string& url2) {
GURL gurl1(url1);
@@ -101,6 +102,12 @@ bool IsPublicSuffixDomainMatch(const std::string& url1,
if (gurl1 == gurl2)
return true;
+ if (gurl1.DomainIs("google.com") && gurl2.DomainIs("google.com")) {
+ return gurl1.scheme() == gurl2.scheme() && gurl1.port() == gurl2.port() &&
+ IsAllowedForPSLMatchedGoogleDomain(gurl1) &&
+ IsAllowedForPSLMatchedGoogleDomain(gurl2);
+ }
+
std::string domain1(GetRegistryControlledDomain(gurl1));
std::string domain2(GetRegistryControlledDomain(gurl2));
diff --git a/chromium/components/password_manager/core/browser/psl_matching_helper.h b/chromium/components/password_manager/core/browser/psl_matching_helper.h
index 1d0e6596927..15d565a29d6 100644
--- a/chromium/components/password_manager/core/browser/psl_matching_helper.h
+++ b/chromium/components/password_manager/core/browser/psl_matching_helper.h
@@ -54,18 +54,6 @@ bool IsFederatedPSLMatch(const std::string& form_signon_realm,
MatchResult GetMatchResult(const autofill::PasswordForm& form,
const PasswordStore::FormDigest& form_digest);
-// Using the public suffix list for matching the origin is only needed for
-// websites that do not have a single hostname for entering credentials. It
-// would be better for their users if they did, but until then we help them find
-// credentials across different hostnames. We know that accounts.google.com is
-// the only hostname we should be accepting credentials on for any domain under
-// google.com, so we can apply a tighter policy for that domain. For owners of
-// domains where a single hostname is always used when your users are entering
-// their credentials, please contact palmer@chromium.org, nyquist@chromium.org
-// or file a bug at http://crbug.com/ to be added here.
-bool ShouldPSLDomainMatchingApply(
- const std::string& registry_controlled_domain);
-
// Two URLs are considered a Public Suffix Domain match if they have the same
// scheme, ports, and their registry controlled domains are equal. If one or
// both arguments do not describe valid URLs, returns false.
diff --git a/chromium/components/password_manager/core/browser/psl_matching_helper_unittest.cc b/chromium/components/password_manager/core/browser/psl_matching_helper_unittest.cc
index a9fa650e0c9..5b068ed6c72 100644
--- a/chromium/components/password_manager/core/browser/psl_matching_helper_unittest.cc
+++ b/chromium/components/password_manager/core/browser/psl_matching_helper_unittest.cc
@@ -91,8 +91,14 @@ TEST(PSLMatchingUtilsTest, GetMatchResultPSL) {
{"https://www.facebook.com/", "https://m.facebook.com",
MatchResult::PSL_MATCH},
- // Don't apply PSL matching to Google domains.
- {"https://google.com/", "https://maps.google.com/",
+ // Google sign-in and change password pages are PSL matched.
+ {"https://accounts.google.com/", "https://myaccount.google.com/",
+ MatchResult::PSL_MATCH},
+
+ // Don't apply PSL matching to other Google domains.
+ {"https://accounts.google.com/", "https://maps.google.com/",
+ MatchResult::NO_MATCH},
+ {"https://subdomain1.google.com/", "https://maps.google.com/",
MatchResult::NO_MATCH},
// Scheme mismatch.
diff --git a/chromium/components/password_manager/core/browser/store_metrics_reporter.cc b/chromium/components/password_manager/core/browser/store_metrics_reporter.cc
index a96721240a5..34eca4d3256 100644
--- a/chromium/components/password_manager/core/browser/store_metrics_reporter.cc
+++ b/chromium/components/password_manager/core/browser/store_metrics_reporter.cc
@@ -4,23 +4,22 @@
#include "components/password_manager/core/browser/store_metrics_reporter.h"
-#include "base/metrics/histogram_macros.h"
-#include "components/password_manager/core/browser/password_bubble_experiment.h"
+#include "base/metrics/histogram_functions.h"
#include "components/password_manager/core/browser/password_manager_client.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/password_sync_util.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
namespace password_manager {
StoreMetricsReporter::StoreMetricsReporter(
- bool password_manager_enabled,
PasswordManagerClient* client,
const syncer::SyncService* sync_service,
const signin::IdentityManager* identity_manager,
PrefService* prefs) {
- password_manager::PasswordStore* store = client->GetPasswordStore();
// May be null in tests.
- if (store) {
+ if (PasswordStore* store = client->GetPasswordStore()) {
store->ReportMetrics(
password_manager::sync_util::GetSyncUsernameIfSyncingPasswords(
sync_service, identity_manager),
@@ -28,7 +27,17 @@ StoreMetricsReporter::StoreMetricsReporter(
password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE,
client->IsUnderAdvancedProtection());
}
- UMA_HISTOGRAM_BOOLEAN("PasswordManager.Enabled", password_manager_enabled);
+ base::UmaHistogramBoolean(
+ "PasswordManager.Enabled",
+ prefs->GetBoolean(password_manager::prefs::kCredentialsEnableService));
+ base::UmaHistogramBoolean(
+ "PasswordManager.LeakDetection.Enabled",
+ prefs->GetBoolean(
+ password_manager::prefs::kPasswordLeakDetectionEnabled));
+ password_manager::metrics_util::LogOnboardingState(
+ static_cast<password_manager::metrics_util::OnboardingState>(
+ prefs->GetInteger(
+ password_manager::prefs::kPasswordManagerOnboardingState)));
}
StoreMetricsReporter::~StoreMetricsReporter() = default;
diff --git a/chromium/components/password_manager/core/browser/store_metrics_reporter.h b/chromium/components/password_manager/core/browser/store_metrics_reporter.h
index 2d61d8243dd..21d0ed2831b 100644
--- a/chromium/components/password_manager/core/browser/store_metrics_reporter.h
+++ b/chromium/components/password_manager/core/browser/store_metrics_reporter.h
@@ -33,10 +33,10 @@ class StoreMetricsReporter {
// Reports various metrics based on whether password manager is enabled. Uses
// |client| to obtain the password store and password syncing state. Uses
// |sync_service| and |identity_manager| to obtain the sync username to report
- // about its presence among saved credentials. Uses the |prefs| to obtain the
- // state of the first-run-experience bubble.
- StoreMetricsReporter(bool password_manager_enabled,
- PasswordManagerClient* client,
+ // about its presence among saved credentials. Uses the |prefs| to obtain
+ // information wither the password manager and the leak detection feature is
+ // enabled.
+ StoreMetricsReporter(PasswordManagerClient* client,
const syncer::SyncService* sync_service,
const signin::IdentityManager* identity_manager,
PrefService* prefs);
diff --git a/chromium/components/password_manager/core/browser/store_metrics_reporter_unittest.cc b/chromium/components/password_manager/core/browser/store_metrics_reporter_unittest.cc
index 908365161be..4a151bd40ae 100644
--- a/chromium/components/password_manager/core/browser/store_metrics_reporter_unittest.cc
+++ b/chromium/components/password_manager/core/browser/store_metrics_reporter_unittest.cc
@@ -8,6 +8,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "components/password_manager/core/browser/mock_password_store.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "components/password_manager/core/browser/sync_username_test_base.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
@@ -16,6 +17,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::Bool;
+using ::testing::Range;
using ::testing::Return;
namespace password_manager {
@@ -28,12 +31,25 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
MOCK_CONST_METHOD0(IsUnderAdvancedProtection, bool());
};
-class StoreMetricsReporterTest : public SyncUsernameTestBase {
+// The test fixture defines two tests, one that doesn't require a password store
+// and one that does. Each of these tests depend on two boolean parameters,
+// which are declared here. Each test then assigns the desired semantics to
+// them.
+class StoreMetricsReporterTest
+ : public SyncUsernameTestBase,
+ public ::testing::WithParamInterface<std::tuple<bool, bool, int>> {
public:
StoreMetricsReporterTest() {
+ prefs_.registry()->RegisterBooleanPref(prefs::kCredentialsEnableService,
+ false);
+ prefs_.registry()->RegisterBooleanPref(prefs::kPasswordLeakDetectionEnabled,
+ false);
prefs_.registry()->RegisterBooleanPref(
- password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, false,
- PrefRegistry::NO_REGISTRATION_FLAGS);
+ password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, false);
+ prefs_.registry()->RegisterIntegerPref(
+ password_manager::prefs::kPasswordManagerOnboardingState,
+ static_cast<int>(
+ password_manager::metrics_util::OnboardingState::kDoNotShow));
}
~StoreMetricsReporterTest() override = default;
@@ -45,77 +61,64 @@ class StoreMetricsReporterTest : public SyncUsernameTestBase {
};
// Test that store-independent metrics are reported correctly.
-TEST_F(StoreMetricsReporterTest, StoreIndependentMetrics) {
- for (const bool password_manager_enabled : {true, false}) {
- for (const bool first_run_ui_shown : {true, false}) {
- SCOPED_TRACE(testing::Message()
- << "password_manager_enabled=" << password_manager_enabled
- << ", first_run_ui_shown=" << first_run_ui_shown);
-
- prefs_.SetBoolean(
- password_manager::prefs::kWasAutoSignInFirstRunExperienceShown,
- first_run_ui_shown);
- base::HistogramTester histogram_tester;
- EXPECT_CALL(client_, GetPasswordStore()).WillOnce(Return(nullptr));
- StoreMetricsReporter reporter(password_manager_enabled, &client_,
- sync_service(), identity_manager(),
- &prefs_);
-
- histogram_tester.ExpectBucketCount("PasswordManager.Enabled",
- password_manager_enabled, 1);
- }
- }
+TEST_P(StoreMetricsReporterTest, StoreIndependentMetrics) {
+ const bool password_manager_enabled = std::get<0>(GetParam());
+ const bool leak_detection_enabled = std::get<1>(GetParam());
+ const int onboarding_state = std::get<2>(GetParam());
+
+ prefs_.SetBoolean(password_manager::prefs::kCredentialsEnableService,
+ password_manager_enabled);
+ prefs_.SetBoolean(password_manager::prefs::kPasswordLeakDetectionEnabled,
+ leak_detection_enabled);
+ prefs_.SetInteger(password_manager::prefs::kPasswordManagerOnboardingState,
+ onboarding_state);
+ base::HistogramTester histogram_tester;
+ EXPECT_CALL(client_, GetPasswordStore()).WillOnce(Return(nullptr));
+ StoreMetricsReporter reporter(&client_, sync_service(), identity_manager(),
+ &prefs_);
+
+ histogram_tester.ExpectUniqueSample("PasswordManager.Enabled",
+ password_manager_enabled, 1);
+ histogram_tester.ExpectUniqueSample("PasswordManager.LeakDetection.Enabled",
+ leak_detection_enabled, 1);
+ histogram_tester.ExpectUniqueSample("PasswordManager.Onboarding.State",
+ onboarding_state, 1);
}
// Test that sync username and syncing state are passed correctly to the
-// PasswordStore when not under advanced protection.
-TEST_F(StoreMetricsReporterTest, PasswordStore) {
- for (const bool syncing_with_passphrase : {true, false}) {
- SCOPED_TRACE(testing::Message()
- << "syncing_with_passphrase=" << syncing_with_passphrase);
-
- auto store = base::MakeRefCounted<MockPasswordStore>();
- const auto sync_state =
- syncing_with_passphrase
- ? password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE
- : password_manager::SYNCING_NORMAL_ENCRYPTION;
- EXPECT_CALL(client_, GetPasswordSyncState()).WillOnce(Return(sync_state));
- EXPECT_CALL(client_, GetPasswordStore()).WillOnce(Return(store.get()));
- EXPECT_CALL(client_, IsUnderAdvancedProtection()).WillOnce(Return(false));
- EXPECT_CALL(*store, ReportMetrics("some.user@gmail.com",
- syncing_with_passphrase, false));
- FakeSigninAs("some.user@gmail.com");
-
- StoreMetricsReporter reporter(true, &client_, sync_service(),
- identity_manager(), &prefs_);
- store->ShutdownOnUIThread();
- }
+// PasswordStore.
+TEST_P(StoreMetricsReporterTest, StoreDependentMetrics) {
+ const bool syncing_with_passphrase = std::get<0>(GetParam());
+ const bool is_under_advanced_protection = std::get<1>(GetParam());
+
+ auto store = base::MakeRefCounted<MockPasswordStore>();
+ const auto sync_state = syncing_with_passphrase
+ ? password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE
+ : password_manager::SYNCING_NORMAL_ENCRYPTION;
+ EXPECT_CALL(client_, GetPasswordSyncState()).WillOnce(Return(sync_state));
+ EXPECT_CALL(client_, GetPasswordStore()).WillOnce(Return(store.get()));
+ EXPECT_CALL(client_, IsUnderAdvancedProtection())
+ .WillOnce(Return(is_under_advanced_protection));
+ EXPECT_CALL(*store,
+ ReportMetrics("some.user@gmail.com", syncing_with_passphrase,
+ is_under_advanced_protection));
+ FakeSigninAs("some.user@gmail.com");
+
+ StoreMetricsReporter reporter(&client_, sync_service(), identity_manager(),
+ &prefs_);
+ store->ShutdownOnUIThread();
}
-// Test that sync username and syncing state are passed correctly to the
-// PasswordStore when under advanced protection.
-TEST_F(StoreMetricsReporterTest, PasswordStoreForUnderAdvancedProtection) {
- for (const bool syncing_with_passphrase : {true, false}) {
- SCOPED_TRACE(testing::Message()
- << "syncing_with_passphrase=" << syncing_with_passphrase);
-
- auto store = base::MakeRefCounted<MockPasswordStore>();
- const auto sync_state =
- syncing_with_passphrase
- ? password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE
- : password_manager::SYNCING_NORMAL_ENCRYPTION;
- EXPECT_CALL(client_, GetPasswordSyncState()).WillOnce(Return(sync_state));
- EXPECT_CALL(client_, GetPasswordStore()).WillOnce(Return(store.get()));
- EXPECT_CALL(client_, IsUnderAdvancedProtection()).WillOnce(Return(true));
- EXPECT_CALL(*store, ReportMetrics("some.user@gmail.com",
- syncing_with_passphrase, true));
- FakeSigninAs("some.user@gmail.com");
-
- StoreMetricsReporter reporter(true, &client_, sync_service(),
- identity_manager(), &prefs_);
- store->ShutdownOnUIThread();
- }
-}
+INSTANTIATE_TEST_SUITE_P(
+ /*InstantiationName*/,
+ StoreMetricsReporterTest,
+ testing::Combine(
+ Bool(),
+ Bool(),
+ Range(0,
+ static_cast<int>(
+ password_manager::metrics_util::OnboardingState::kMaxValue) +
+ 1)));
} // namespace
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/stub_password_manager_client.cc b/chromium/components/password_manager/core/browser/stub_password_manager_client.cc
index 16c569924ca..fbb40c4d23e 100644
--- a/chromium/components/password_manager/core/browser/stub_password_manager_client.cc
+++ b/chromium/components/password_manager/core/browser/stub_password_manager_client.cc
@@ -8,6 +8,7 @@
#include "components/password_manager/core/browser/credentials_filter.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace password_manager {
@@ -22,6 +23,11 @@ bool StubPasswordManagerClient::PromptUserToSaveOrUpdatePassword(
return false;
}
+bool StubPasswordManagerClient::ShowOnboarding(
+ std::unique_ptr<PasswordFormManagerForUI> form_to_save) {
+ return false;
+}
+
void StubPasswordManagerClient::ShowManualFallbackForSaving(
std::unique_ptr<PasswordFormManagerForUI> form_to_save,
bool has_generated_password,
@@ -76,16 +82,21 @@ const autofill::LogManager* StubPasswordManagerClient::GetLogManager() const {
return &log_manager_;
}
-#if defined(FULL_SAFE_BROWSING)
+#if defined(ON_FOCUS_PING_ENABLED) || \
+ defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
safe_browsing::PasswordProtectionService*
StubPasswordManagerClient::GetPasswordProtectionService() const {
return nullptr;
}
+#endif
+#if defined(ON_FOCUS_PING_ENABLED)
void StubPasswordManagerClient::CheckSafeBrowsingReputation(
const GURL& form_action,
const GURL& frame_url) {}
+#endif
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
void StubPasswordManagerClient::CheckProtectedPasswordEntry(
metrics_util::PasswordType reused_password_type,
const std::string& username,
@@ -107,6 +118,15 @@ StubPasswordManagerClient::GetMetricsRecorder() {
return base::OptionalOrNullptr(metrics_recorder_);
}
+signin::IdentityManager* StubPasswordManagerClient::GetIdentityManager() {
+ return nullptr;
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+StubPasswordManagerClient::GetURLLoaderFactory() {
+ return nullptr;
+}
+
bool StubPasswordManagerClient::IsIsolationForPasswordSitesEnabled() const {
return false;
}
diff --git a/chromium/components/password_manager/core/browser/stub_password_manager_client.h b/chromium/components/password_manager/core/browser/stub_password_manager_client.h
index f7da6af8f4f..440f1d13d78 100644
--- a/chromium/components/password_manager/core/browser/stub_password_manager_client.h
+++ b/chromium/components/password_manager/core/browser/stub_password_manager_client.h
@@ -27,6 +27,8 @@ class StubPasswordManagerClient : public PasswordManagerClient {
bool PromptUserToSaveOrUpdatePassword(
std::unique_ptr<PasswordFormManagerForUI> form_to_save,
bool update_password) override;
+ bool ShowOnboarding(
+ std::unique_ptr<PasswordFormManagerForUI> form_to_save) override;
void ShowManualFallbackForSaving(
std::unique_ptr<PasswordFormManagerForUI> form_to_save,
bool has_generated_password,
@@ -54,11 +56,19 @@ class StubPasswordManagerClient : public PasswordManagerClient {
const GURL& GetLastCommittedEntryURL() const override;
const CredentialsFilter* GetStoreResultFilter() const override;
const autofill::LogManager* GetLogManager() const override;
-#if defined(FULL_SAFE_BROWSING)
+
+#if defined(ON_FOCUS_PING_ENABLED) || \
+ defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
safe_browsing::PasswordProtectionService* GetPasswordProtectionService()
const override;
+#endif
+
+#if defined(ON_FOCUS_PING_ENABLED)
void CheckSafeBrowsingReputation(const GURL& form_action,
const GURL& frame_url) override;
+#endif
+
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
void CheckProtectedPasswordEntry(
metrics_util::PasswordType reused_password_type,
const std::string& username,
@@ -66,8 +76,11 @@ class StubPasswordManagerClient : public PasswordManagerClient {
bool password_field_exists) override;
void LogPasswordReuseDetectedEvent() override;
#endif
+
ukm::SourceId GetUkmSourceId() override;
PasswordManagerMetricsRecorder* GetMetricsRecorder() override;
+ signin::IdentityManager* GetIdentityManager() override;
+ scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
bool IsIsolationForPasswordSitesEnabled() const override;
bool IsNewTabPage() const override;
diff --git a/chromium/components/password_manager/core/browser/sync/password_model_type_controller.cc b/chromium/components/password_manager/core/browser/sync/password_model_type_controller.cc
index db4dab36c56..b65603a31ba 100644
--- a/chromium/components/password_manager/core/browser/sync/password_model_type_controller.cc
+++ b/chromium/components/password_manager/core/browser/sync/password_model_type_controller.cc
@@ -15,9 +15,12 @@ namespace password_manager {
PasswordModelTypeController::PasswordModelTypeController(
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
syncer::SyncService* sync_service,
const base::RepeatingClosure& state_changed_callback)
- : ModelTypeController(syncer::PASSWORDS, std::move(delegate_on_disk)),
+ : ModelTypeController(syncer::PASSWORDS,
+ std::move(delegate_on_disk),
+ std::move(delegate_in_memory)),
sync_service_(sync_service),
state_changed_callback_(state_changed_callback) {}
diff --git a/chromium/components/password_manager/core/browser/sync/password_model_type_controller.h b/chromium/components/password_manager/core/browser/sync/password_model_type_controller.h
index 2593dab2ae9..3745f88a5ff 100644
--- a/chromium/components/password_manager/core/browser/sync/password_model_type_controller.h
+++ b/chromium/components/password_manager/core/browser/sync/password_model_type_controller.h
@@ -25,6 +25,7 @@ class PasswordModelTypeController : public syncer::ModelTypeController,
public:
PasswordModelTypeController(
std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+ std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
syncer::SyncService* sync_service,
const base::RepeatingClosure& state_changed_callback);
~PasswordModelTypeController() override;
diff --git a/chromium/components/password_manager/core/browser/sync/password_sync_bridge.cc b/chromium/components/password_manager/core/browser/sync/password_sync_bridge.cc
index 9098ec27b1b..3740209a782 100644
--- a/chromium/components/password_manager/core/browser/sync/password_sync_bridge.cc
+++ b/chromium/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -45,6 +45,8 @@ sync_pb::PasswordSpecifics SpecificsFromPassword(
password_data->set_password_value(
base::UTF16ToUTF8(password_form.password_value));
password_data->set_preferred(password_form.preferred);
+ password_data->set_date_last_used(
+ password_form.date_last_used.ToDeltaSinceWindowsEpoch().InMicroseconds());
password_data->set_date_created(
password_form.date_created.ToDeltaSinceWindowsEpoch().InMicroseconds());
password_data->set_blacklisted(password_form.blacklisted_by_user);
@@ -80,6 +82,15 @@ autofill::PasswordForm PasswordFromEntityChange(
password.username_value = base::UTF8ToUTF16(password_data.username_value());
password.password_value = base::UTF8ToUTF16(password_data.password_value());
password.preferred = password_data.preferred();
+ if (password_data.has_date_last_used()) {
+ password.date_last_used = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(password_data.date_last_used()));
+ } else if (password_data.preferred()) {
+ // For legacy passwords that don't have the |date_last_used| field set, we
+ // should it similar to the logic in login database migration.
+ password.date_last_used =
+ base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(1));
+ }
password.date_created = base::Time::FromDeltaSinceWindowsEpoch(
// Use FromDeltaSinceWindowsEpoch because create_time_us has
// always used the Windows epoch.
@@ -133,6 +144,10 @@ bool AreLocalAndRemotePasswordsEqual(
base::UTF16ToUTF8(password_form.password_value) ==
password_specifics.password_value() &&
password_form.preferred == password_specifics.preferred() &&
+ password_form.date_last_used ==
+ base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(
+ password_specifics.date_last_used())) &&
password_form.date_created ==
base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMicroseconds(
@@ -734,6 +749,25 @@ void PasswordSyncBridge::ApplyStopSyncChanges(
std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) {
if (delete_metadata_change_list) {
password_store_sync_->GetMetadataStore()->DeleteAllSyncMetadata();
+
+ // If this is the account store, also delete the actual data.
+ if (password_store_sync_->IsAccountStore()) {
+ base::AutoReset<bool> processing_changes(
+ &is_processing_remote_sync_changes_, true);
+
+ PasswordStoreChangeList password_store_changes;
+ PrimaryKeyToFormMap logins;
+ FormRetrievalResult result = password_store_sync_->ReadAllLogins(&logins);
+ if (result == FormRetrievalResult::kSuccess) {
+ for (const auto& primary_key_and_form : logins) {
+ password_store_changes.emplace_back(PasswordStoreChange::REMOVE,
+ *primary_key_and_form.second,
+ primary_key_and_form.first);
+ }
+ }
+ password_store_sync_->DeleteAndRecreateDatabaseFile();
+ password_store_sync_->NotifyLoginsChanged(password_store_changes);
+ }
}
}
diff --git a/chromium/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/chromium/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
index fb2b72b63a3..4d60261468f 100644
--- a/chromium/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
+++ b/chromium/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -212,6 +212,8 @@ class MockPasswordStoreSync : public PasswordStoreSync {
MOCK_METHOD0(CommitTransaction, bool());
MOCK_METHOD0(RollbackTransaction, void());
MOCK_METHOD0(GetMetadataStore, PasswordStoreSync::MetadataStore*());
+ MOCK_CONST_METHOD0(IsAccountStore, bool());
+ MOCK_METHOD0(DeleteAndRecreateDatabaseFile, bool());
};
} // namespace
diff --git a/chromium/components/password_manager/core/browser/sync/password_syncable_service.cc b/chromium/components/password_manager/core/browser/sync/password_syncable_service.cc
index e60f079427a..62a0f67f5fc 100644
--- a/chromium/components/password_manager/core/browser/sync/password_syncable_service.cc
+++ b/chromium/components/password_manager/core/browser/sync/password_syncable_service.cc
@@ -57,6 +57,8 @@ bool AreLocalAndSyncPasswordsEqual(
base::UTF16ToUTF8(password_form.password_value) ==
password_specifics.password_value() &&
password_form.preferred == password_specifics.preferred() &&
+ password_form.date_last_used.ToDeltaSinceWindowsEpoch()
+ .InMicroseconds() == password_specifics.date_last_used() &&
password_form.date_created.ToInternalValue() ==
password_specifics.date_created() &&
password_form.blacklisted_by_user == password_specifics.blacklisted() &&
@@ -480,6 +482,8 @@ syncer::SyncData SyncDataFromPassword(
CopyStringField(username_value);
CopyStringField(password_value);
CopyField(preferred);
+ password_specifics->set_date_last_used(
+ password_form.date_last_used.ToDeltaSinceWindowsEpoch().InMicroseconds());
password_specifics->set_date_created(
password_form.date_created.ToInternalValue());
password_specifics->set_blacklisted(password_form.blacklisted_by_user);
@@ -514,6 +518,15 @@ autofill::PasswordForm PasswordFromSpecifics(
new_password.username_value = base::UTF8ToUTF16(password.username_value());
new_password.password_value = base::UTF8ToUTF16(password.password_value());
new_password.preferred = password.preferred();
+ if (password.has_date_last_used()) {
+ new_password.date_last_used = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(password.date_last_used()));
+ } else if (password.preferred()) {
+ // For legacy passwords that don't have the |date_last_used| field set, we
+ // should set it similar to the logic in login database migration.
+ new_password.date_last_used =
+ base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(1));
+ }
new_password.date_created =
base::Time::FromInternalValue(password.date_created());
new_password.blacklisted_by_user = password.blacklisted();
diff --git a/chromium/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc b/chromium/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc
index 0b0abb5a658..4b9310b3848 100644
--- a/chromium/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc
+++ b/chromium/components/password_manager/core/browser/sync/password_syncable_service_unittest.cc
@@ -16,7 +16,7 @@
#include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/sync/model/sync_change_processor.h"
@@ -93,6 +93,7 @@ MATCHER_P(PasswordIs, form, "") {
expected_password.username_value() == actual_password.username_value() &&
expected_password.password_value() == actual_password.password_value() &&
expected_password.preferred() == actual_password.preferred() &&
+ expected_password.date_last_used() == actual_password.date_last_used() &&
expected_password.date_created() == actual_password.date_created() &&
expected_password.blacklisted() == actual_password.blacklisted() &&
expected_password.type() == actual_password.type() &&
@@ -230,7 +231,7 @@ class PasswordSyncableServiceTest : public testing::Test {
private:
// Used by the password store.
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
PasswordSyncableServiceWrapper wrapper_;
};
@@ -328,11 +329,13 @@ TEST_F(PasswordSyncableServiceTest, Merge) {
form1.action = GURL("http://pie.com");
form1.date_created = base::Time::Now();
form1.preferred = true;
+ form1.date_last_used = form1.date_created;
form1.username_value = base::ASCIIToUTF16(kUsername);
form1.password_value = base::ASCIIToUTF16(kPassword);
autofill::PasswordForm form2(form1);
form2.preferred = false;
+ form2.date_created = form1.date_created + base::TimeDelta::FromDays(1);
EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
.WillOnce(AppendForm(form1));
EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));
@@ -711,6 +714,8 @@ TEST_F(PasswordSyncableServiceTest, SerializeEmptyPasswordForm) {
EXPECT_EQ("", specifics.password_value());
EXPECT_TRUE(specifics.has_preferred());
EXPECT_FALSE(specifics.preferred());
+ EXPECT_TRUE(specifics.has_date_last_used());
+ EXPECT_EQ(0, specifics.date_last_used());
EXPECT_TRUE(specifics.has_date_created());
EXPECT_EQ(0, specifics.date_created());
EXPECT_TRUE(specifics.has_blacklisted());
@@ -740,6 +745,8 @@ TEST_F(PasswordSyncableServiceTest, SerializeNonEmptyPasswordForm) {
form.password_element = base::ASCIIToUTF16("password_element");
form.password_value = base::ASCIIToUTF16("!@#$%^&*()");
form.preferred = true;
+ form.date_last_used = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(100));
form.date_created = base::Time::FromInternalValue(100);
form.blacklisted_by_user = true;
form.type = autofill::PasswordForm::Type::kMaxValue;
@@ -769,6 +776,8 @@ TEST_F(PasswordSyncableServiceTest, SerializeNonEmptyPasswordForm) {
EXPECT_EQ("!@#$%^&*()", specifics.password_value());
EXPECT_TRUE(specifics.has_preferred());
EXPECT_TRUE(specifics.preferred());
+ EXPECT_TRUE(specifics.has_date_last_used());
+ EXPECT_EQ(100, specifics.date_last_used());
EXPECT_TRUE(specifics.has_date_created());
EXPECT_EQ(100, specifics.date_created());
EXPECT_TRUE(specifics.has_blacklisted());
diff --git a/chromium/components/password_manager/core/browser/sync_credentials_filter.cc b/chromium/components/password_manager/core/browser/sync_credentials_filter.cc
index a3d88e3560b..7b8155a9854 100644
--- a/chromium/components/password_manager/core/browser/sync_credentials_filter.cc
+++ b/chromium/components/password_manager/core/browser/sync_credentials_filter.cc
@@ -22,12 +22,11 @@ using autofill::PasswordForm;
namespace password_manager {
SyncCredentialsFilter::SyncCredentialsFilter(
- const PasswordManagerClient* client,
- SyncServiceFactoryFunction sync_service_factory_function,
- IdentityManagerFactoryFunction identity_manager_factory_function)
+ PasswordManagerClient* client,
+ SyncServiceFactoryFunction sync_service_factory_function)
: client_(client),
- sync_service_factory_function_(sync_service_factory_function),
- identity_manager_factory_function_(identity_manager_factory_function) {}
+ sync_service_factory_function_(std::move(sync_service_factory_function)) {
+}
SyncCredentialsFilter::~SyncCredentialsFilter() {}
@@ -37,7 +36,7 @@ bool SyncCredentialsFilter::ShouldSave(
!form.form_data.is_gaia_with_skip_save_password_form &&
!sync_util::IsSyncAccountCredential(
form, sync_service_factory_function_.Run(),
- identity_manager_factory_function_.Run());
+ client_->GetIdentityManager());
}
bool SyncCredentialsFilter::ShouldSaveGaiaPasswordHash(
@@ -58,17 +57,15 @@ bool SyncCredentialsFilter::ShouldSaveEnterprisePasswordHash(
bool SyncCredentialsFilter::IsSyncAccountEmail(
const std::string& username) const {
- return sync_util::IsSyncAccountEmail(
- username, identity_manager_factory_function_.Run());
+ return sync_util::IsSyncAccountEmail(username, client_->GetIdentityManager());
}
void SyncCredentialsFilter::ReportFormLoginSuccess(
const PasswordFormManagerInterface& form_manager) const {
if (!form_manager.IsNewLogin() &&
- sync_util::IsSyncAccountCredential(
- form_manager.GetPendingCredentials(),
- sync_service_factory_function_.Run(),
- identity_manager_factory_function_.Run())) {
+ sync_util::IsSyncAccountCredential(form_manager.GetPendingCredentials(),
+ sync_service_factory_function_.Run(),
+ client_->GetIdentityManager())) {
base::RecordAction(base::UserMetricsAction(
"PasswordManager_SyncCredentialFilledAndLoginSuccessfull"));
}
diff --git a/chromium/components/password_manager/core/browser/sync_credentials_filter.h b/chromium/components/password_manager/core/browser/sync_credentials_filter.h
index dbcac09066a..ba17e1277ef 100644
--- a/chromium/components/password_manager/core/browser/sync_credentials_filter.h
+++ b/chromium/components/password_manager/core/browser/sync_credentials_filter.h
@@ -16,10 +16,6 @@
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/sync/driver/sync_service.h"
-namespace signin {
-class IdentityManager;
-}
-
namespace password_manager {
// The sync- and GAIA- aware implementation of the filter.
@@ -27,17 +23,13 @@ class SyncCredentialsFilter : public CredentialsFilter {
public:
using SyncServiceFactoryFunction =
base::RepeatingCallback<const syncer::SyncService*(void)>;
- using IdentityManagerFactoryFunction =
- base::RepeatingCallback<const signin::IdentityManager*(void)>;
// Implements protection of sync credentials. Uses |client| to get the last
// commited entry URL for a check against GAIA reauth site. Uses the factory
- // functions repeatedly to get the sync service and identity manager to pass
- // them to sync_util methods.
+ // function repeatedly to get the sync service to pass to sync_util methods.
SyncCredentialsFilter(
- const PasswordManagerClient* client,
- SyncServiceFactoryFunction sync_service_factory_function,
- IdentityManagerFactoryFunction identity_manager_factory_function);
+ PasswordManagerClient* client,
+ SyncServiceFactoryFunction sync_service_factory_function);
~SyncCredentialsFilter() override;
// CredentialsFilter
@@ -51,14 +43,10 @@ class SyncCredentialsFilter : public CredentialsFilter {
bool IsSyncAccountEmail(const std::string& username) const override;
private:
- const PasswordManagerClient* const client_;
+ PasswordManagerClient* const client_;
const SyncServiceFactoryFunction sync_service_factory_function_;
- // For incognito profile, |identity_manager_factory_function_| returns the
- // sign in manager of its original profile.
- const IdentityManagerFactoryFunction identity_manager_factory_function_;
-
DISALLOW_COPY_AND_ASSIGN(SyncCredentialsFilter);
};
diff --git a/chromium/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/chromium/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
index 3d690061b09..9603ef70457 100644
--- a/chromium/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
+++ b/chromium/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -19,7 +19,7 @@
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/fake_form_fetcher.h"
#include "components/password_manager/core/browser/mock_password_store.h"
-#include "components/password_manager/core/browser/password_manager.h"
+#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
#include "components/password_manager/core/browser/stub_form_saver.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
@@ -49,9 +49,8 @@ const char kEnterpriseURL[] = "https://enterprise.test/";
class FakePasswordManagerClient : public StubPasswordManagerClient {
public:
- FakePasswordManagerClient()
- : password_store_(new testing::NiceMock<MockPasswordStore>),
- is_incognito_(false) {
+ explicit FakePasswordManagerClient(signin::IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// Initializes and configures prefs.
prefs_ = std::make_unique<TestingPrefServiceSimple>();
@@ -74,6 +73,9 @@ class FakePasswordManagerClient : public StubPasswordManagerClient {
MockPasswordStore* GetPasswordStore() const override {
return password_store_.get();
}
+ signin::IdentityManager* GetIdentityManager() override {
+ return identity_manager_;
+ }
void set_last_committed_entry_url(const char* url_spec) {
last_committed_entry_url_ = GURL(url_spec);
@@ -89,8 +91,10 @@ class FakePasswordManagerClient : public StubPasswordManagerClient {
private:
GURL last_committed_entry_url_;
- scoped_refptr<testing::NiceMock<MockPasswordStore>> password_store_;
- bool is_incognito_;
+ scoped_refptr<testing::NiceMock<MockPasswordStore>> password_store_ =
+ new testing::NiceMock<MockPasswordStore>;
+ bool is_incognito_ = false;
+ signin::IdentityManager* identity_manager_;
#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
std::unique_ptr<TestingPrefServiceSimple> prefs_;
#endif // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
@@ -106,20 +110,17 @@ class CredentialsFilterTest : public SyncUsernameTestBase {
enum class LoginState { NEW, EXISTING };
CredentialsFilterTest()
- : password_manager_(&client_),
+ : client_(identity_manager()),
pending_(SimpleGaiaForm("user@gmail.com")),
- form_manager_(&password_manager_,
- &client_,
+ form_manager_(&client_,
driver_.AsWeakPtr(),
- pending_,
+ pending_.form_data,
+ &fetcher_,
std::make_unique<StubFormSaver>(),
- &fetcher_),
+ nullptr /* metrics_recorder */),
filter_(&client_,
base::BindRepeating(&SyncUsernameTestBase::sync_service,
- base::Unretained(this)),
- base::BindRepeating(&SyncUsernameTestBase::identity_manager,
base::Unretained(this))) {
- form_manager_.Init(nullptr);
fetcher_.Fetch();
}
@@ -134,12 +135,11 @@ class CredentialsFilterTest : public SyncUsernameTestBase {
fetcher_.SetNonFederated(matches);
fetcher_.NotifyFetchCompleted();
- form_manager_.ProvisionallySave(pending_);
+ form_manager_.ProvisionallySave(pending_.form_data, &driver_);
}
protected:
FakePasswordManagerClient client_;
- PasswordManager password_manager_;
StubPasswordManagerDriver driver_;
PasswordForm pending_;
FakeFormFetcher fetcher_;
diff --git a/chromium/components/password_manager/core/browser/sync_username_test_base.cc b/chromium/components/password_manager/core/browser/sync_username_test_base.cc
index bf541ac1016..d23c5dafa7e 100644
--- a/chromium/components/password_manager/core/browser/sync_username_test_base.cc
+++ b/chromium/components/password_manager/core/browser/sync_username_test_base.cc
@@ -5,11 +5,35 @@
#include "components/password_manager/core/browser/sync_username_test_base.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/common/form_data.h"
+using autofill::FormData;
+using autofill::FormFieldData;
using autofill::PasswordForm;
+using base::ASCIIToUTF16;
namespace password_manager {
+namespace {
+
+FormData CreateSigninFormData(const GURL& url, const char* username) {
+ FormData form;
+ form.url = url;
+ FormFieldData field;
+ field.name = ASCIIToUTF16("username_element");
+ field.form_control_type = "text";
+ field.value = ASCIIToUTF16(username);
+ form.fields.push_back(field);
+
+ field.name = ASCIIToUTF16("password_element");
+ field.form_control_type = "password";
+ field.value = ASCIIToUTF16("strong_pw");
+ form.fields.push_back(field);
+ return form;
+}
+
+} // namespace
+
SyncUsernameTestBase::SyncUsernameTestBase() = default;
SyncUsernameTestBase::~SyncUsernameTestBase() = default;
@@ -32,7 +56,8 @@ void SyncUsernameTestBase::FakeSigninAs(const std::string& email) {
PasswordForm SyncUsernameTestBase::SimpleGaiaForm(const char* username) {
PasswordForm form;
form.signon_realm = "https://accounts.google.com";
- form.username_value = base::ASCIIToUTF16(username);
+ form.username_value = ASCIIToUTF16(username);
+ form.form_data = CreateSigninFormData(GURL(form.signon_realm), username);
return form;
}
@@ -40,7 +65,8 @@ PasswordForm SyncUsernameTestBase::SimpleGaiaForm(const char* username) {
PasswordForm SyncUsernameTestBase::SimpleNonGaiaForm(const char* username) {
PasswordForm form;
form.signon_realm = "https://site.com";
- form.username_value = base::ASCIIToUTF16(username);
+ form.username_value = ASCIIToUTF16(username);
+ form.form_data = CreateSigninFormData(GURL(form.signon_realm), username);
return form;
}
@@ -49,8 +75,9 @@ PasswordForm SyncUsernameTestBase::SimpleNonGaiaForm(const char* username,
const char* origin) {
PasswordForm form;
form.signon_realm = "https://site.com";
- form.username_value = base::ASCIIToUTF16(username);
+ form.username_value = ASCIIToUTF16(username);
form.origin = GURL(origin);
+ form.form_data = CreateSigninFormData(GURL(form.signon_realm), username);
return form;
}
diff --git a/chromium/components/password_manager/core/browser/sync_username_test_base.h b/chromium/components/password_manager/core/browser/sync_username_test_base.h
index 330953dd941..9f70d48fb86 100644
--- a/chromium/components/password_manager/core/browser/sync_username_test_base.h
+++ b/chromium/components/password_manager/core/browser/sync_username_test_base.h
@@ -10,7 +10,7 @@
#include <string>
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/common/password_form.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync/driver/test_sync_service.h"
@@ -38,12 +38,12 @@ class SyncUsernameTestBase : public testing::Test {
const syncer::SyncService* sync_service() const { return &sync_service_; }
- const signin::IdentityManager* identity_manager() {
+ signin::IdentityManager* identity_manager() {
return identity_test_env_.identity_manager();
}
private:
- base::test::ScopedTaskEnvironment scoped_task_env_;
+ base::test::TaskEnvironment scoped_task_env_;
signin::IdentityTestEnvironment identity_test_env_;
syncer::TestSyncService sync_service_;
};
diff --git a/chromium/components/password_manager/core/browser/test_password_store.cc b/chromium/components/password_manager/core/browser/test_password_store.cc
index f07d05af430..a9fae60c429 100644
--- a/chromium/components/password_manager/core/browser/test_password_store.cc
+++ b/chromium/components/password_manager/core/browser/test_password_store.cc
@@ -133,6 +133,20 @@ TestPasswordStore::FillMatchingLogins(const FormDigest& form) {
return matched_forms;
}
+std::vector<std::unique_ptr<autofill::PasswordForm>>
+TestPasswordStore::FillMatchingLoginsByPassword(
+ const base::string16& plain_text_password) {
+ std::vector<std::unique_ptr<autofill::PasswordForm>> matched_forms;
+ for (const auto& elements : stored_passwords_) {
+ for (const auto& password_form : elements.second) {
+ if (password_form.password_value == plain_text_password)
+ matched_forms.push_back(
+ std::make_unique<autofill::PasswordForm>(password_form));
+ }
+ }
+ return matched_forms;
+}
+
bool TestPasswordStore::FillAutofillableLogins(
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) {
for (const auto& forms_for_realm : stored_passwords_) {
@@ -238,4 +252,13 @@ PasswordStoreSync::MetadataStore* TestPasswordStore::GetMetadataStore() {
return nullptr;
}
+bool TestPasswordStore::IsAccountStore() const {
+ return false;
+}
+
+bool TestPasswordStore::DeleteAndRecreateDatabaseFile() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/test_password_store.h b/chromium/components/password_manager/core/browser/test_password_store.h
index 0544f6cda39..541f70cf5b3 100644
--- a/chromium/components/password_manager/core/browser/test_password_store.h
+++ b/chromium/components/password_manager/core/browser/test_password_store.h
@@ -7,6 +7,7 @@
#include <functional>
#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -54,6 +55,9 @@ class TestPasswordStore : public PasswordStore {
const autofill::PasswordForm& form) override;
std::vector<std::unique_ptr<autofill::PasswordForm>> FillMatchingLogins(
const FormDigest& form) override;
+ std::vector<std::unique_ptr<autofill::PasswordForm>>
+ FillMatchingLoginsByPassword(
+ const base::string16& plain_text_password) override;
bool FillAutofillableLogins(
std::vector<std::unique_ptr<autofill::PasswordForm>>* forms) override;
bool FillBlacklistLogins(
@@ -90,6 +94,8 @@ class TestPasswordStore : public PasswordStore {
PrimaryKeyToFormMap* key_to_form_map) override;
PasswordStoreChangeList RemoveLoginByPrimaryKeySync(int primary_key) override;
PasswordStoreSync::MetadataStore* GetMetadataStore() override;
+ bool IsAccountStore() const override;
+ bool DeleteAndRecreateDatabaseFile() override;
private:
PasswordMap stored_passwords_;
diff --git a/chromium/components/password_manager/core/browser/votes_uploader.cc b/chromium/components/password_manager/core/browser/votes_uploader.cc
index 97b30d3b6c1..dbc89a64534 100644
--- a/chromium/components/password_manager/core/browser/votes_uploader.cc
+++ b/chromium/components/password_manager/core/browser/votes_uploader.cc
@@ -5,8 +5,8 @@
#include "components/password_manager/core/browser/votes_uploader.h"
#include <ctype.h>
-
#include <algorithm>
+#include <iostream>
#include <utility>
#include "base/hash/hash.h"
#include "base/logging.h"
@@ -36,6 +36,7 @@ using autofill::ServerFieldTypeSet;
using autofill::ValueElementPair;
using Logger = autofill::SavePasswordProgressLogger;
+using StringID = autofill::SavePasswordProgressLogger::StringID;
namespace password_manager {
@@ -342,7 +343,7 @@ bool VotesUploader::UploadPasswordVote(
if (password_manager_util::IsLoggingActive(client_)) {
BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
- logger.LogFormStructure(Logger::STRING_FORM_VOTES, form_structure);
+ logger.LogFormStructure(Logger::STRING_PASSWORD_FORM_VOTE, form_structure);
}
// Annotate the form with the source language of the page.
@@ -397,11 +398,6 @@ void VotesUploader::UploadFirstLoginVotes(
// sure to receive them.
form_structure.set_upload_required(UPLOAD_REQUIRED);
- if (password_manager_util::IsLoggingActive(client_)) {
- BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
- logger.LogFormStructure(Logger::STRING_FORM_VOTES, form_structure);
- }
-
// Annotate the form with the source language of the page.
form_structure.set_page_language(client_->GetPageLanguage());
@@ -412,6 +408,11 @@ void VotesUploader::UploadFirstLoginVotes(
SetInitialHashValueOfUsernameField(
form_to_upload.username_element_renderer_id, &form_structure);
+ if (password_manager_util::IsLoggingActive(client_)) {
+ BrowserSavePasswordProgressLogger logger(client_->GetLogManager());
+ logger.LogFormStructure(Logger::STRING_FIRSTUSE_FORM_VOTE, form_structure);
+ }
+
download_manager->StartUploadRequest(
form_structure, false /* was_autofilled */, available_field_types,
std::string(), true /* observed_submission */, nullptr /* prefs */);
@@ -526,19 +527,12 @@ bool VotesUploader::FindUsernameInOtherPossibleUsernames(
}
bool VotesUploader::FindCorrectedUsernameElement(
- const std::map<base::string16, const PasswordForm*>& best_matches,
- const std::vector<const PasswordForm*>& not_best_matches,
+ const std::vector<const PasswordForm*>& matches,
const base::string16& username,
const base::string16& password) {
if (username.empty())
return false;
- for (const auto& key_value : best_matches) {
- const PasswordForm* match = key_value.second;
- if ((match->password_value == password) &&
- FindUsernameInOtherPossibleUsernames(*match, username))
- return true;
- }
- for (const PasswordForm* match : not_best_matches) {
+ for (const PasswordForm* match : matches) {
if ((match->password_value == password) &&
FindUsernameInOtherPossibleUsernames(*match, username))
return true;
diff --git a/chromium/components/password_manager/core/browser/votes_uploader.h b/chromium/components/password_manager/core/browser/votes_uploader.h
index abe6879aecb..acf0fc13638 100644
--- a/chromium/components/password_manager/core/browser/votes_uploader.h
+++ b/chromium/components/password_manager/core/browser/votes_uploader.h
@@ -70,15 +70,12 @@ class VotesUploader {
const autofill::PasswordForm& pending_credentials,
const autofill::PasswordForm& form_to_upload);
- // Searches for |username| in |all_possible_usernames| of |best_matches|
- // and |not_best_matches|. If the username value is found in
- // |all_possible_usernames| and the password value of the match is equal to
- // |password|, the match is saved to |username_correction_vote_| and the
- // method returns true.
+ // Searches for |username| in |all_possible_usernames| of |matches|. If the
+ // username value is found in |all_possible_usernames| and the password value
+ // of the match is equal to |password|, the match is saved to
+ // |username_correction_vote_| and the method returns true.
bool FindCorrectedUsernameElement(
- const std::map<base::string16, const autofill::PasswordForm*>&
- best_matches,
- const std::vector<const autofill::PasswordForm*>& not_best_matches,
+ const std::vector<const autofill::PasswordForm*>& matches,
const base::string16& username,
const base::string16& password);
diff --git a/chromium/components/password_manager/core/browser/votes_uploader_unittest.cc b/chromium/components/password_manager/core/browser/votes_uploader_unittest.cc
index a72bbf42cee..ed3742dbafe 100644
--- a/chromium/components/password_manager/core/browser/votes_uploader_unittest.cc
+++ b/chromium/components/password_manager/core/browser/votes_uploader_unittest.cc
@@ -13,7 +13,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/autofill/core/browser/autofill_download_manager.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/form_data.h"
@@ -107,7 +107,7 @@ class VotesUploaderTest : public testing::Test {
return ASCIIToUTF16("field") + base::NumberToString16(index);
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
MockAutofillDownloadManager mock_autofill_download_manager_;
MockPasswordManagerClient client_;
@@ -248,14 +248,13 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote) {
votes_uploader.GeneratePasswordAttributesVote(password_value,
&form_structure);
base::Optional<std::pair<PasswordAttribute, bool>> vote =
- form_structure.get_password_attributes_vote_for_testing();
+ form_structure.get_password_attributes_vote();
int attribute_index = static_cast<int>(vote->first);
if (vote->second)
reported_true[attribute_index]++;
else
reported_false[attribute_index]++;
- size_t reported_length =
- form_structure.get_password_length_vote_for_testing();
+ size_t reported_length = form_structure.get_password_length_vote();
if (reported_length == password_value.size()) {
reported_actual_length++;
} else {
@@ -305,19 +304,19 @@ TEST_F(VotesUploaderTest, GeneratePasswordSpecialSymbolVote) {
votes_uploader.GeneratePasswordAttributesVote(password_value,
&form_structure);
base::Optional<std::pair<PasswordAttribute, bool>> vote =
- form_structure.get_password_attributes_vote_for_testing();
+ form_structure.get_password_attributes_vote();
// Continue if the vote is not about special symbols or implies that no
// special symbols are used.
if (static_cast<int>(vote->first) != kSpecialSymbolsAttribute ||
!vote->second) {
- EXPECT_EQ(form_structure.get_password_symbol_vote_for_testing(), 0);
+ EXPECT_EQ(form_structure.get_password_symbol_vote(), 0);
continue;
}
number_of_symbol_votes += 1;
- int symbol = form_structure.get_password_symbol_vote_for_testing();
+ int symbol = form_structure.get_password_symbol_vote();
if (symbol == '-' || symbol == '!')
correct_symbol_reported += 1;
else
@@ -336,10 +335,9 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote_OneCharacterPassword) {
votes_uploader.GeneratePasswordAttributesVote(ASCIIToUTF16("1"),
&form_structure);
base::Optional<std::pair<PasswordAttribute, bool>> vote =
- form_structure.get_password_attributes_vote_for_testing();
+ form_structure.get_password_attributes_vote();
EXPECT_TRUE(vote.has_value());
- size_t reported_length =
- form_structure.get_password_length_vote_for_testing();
+ size_t reported_length = form_structure.get_password_length_vote();
EXPECT_EQ(1u, reported_length);
}
@@ -352,7 +350,7 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote_AllAsciiCharacters) {
"stuvwxyz!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"),
&form_structure);
base::Optional<std::pair<PasswordAttribute, bool>> vote =
- form_structure.get_password_attributes_vote_for_testing();
+ form_structure.get_password_attributes_vote();
EXPECT_TRUE(vote.has_value());
}
@@ -369,7 +367,7 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote_NonAsciiPassword) {
votes_uploader.GeneratePasswordAttributesVote(base::UTF8ToUTF16(password),
&form_structure);
base::Optional<std::pair<PasswordAttribute, bool>> vote =
- form_structure.get_password_attributes_vote_for_testing();
+ form_structure.get_password_attributes_vote();
EXPECT_FALSE(vote.has_value()) << password;
}
diff --git a/chromium/components/password_manager/core/common/password_manager_features.cc b/chromium/components/password_manager/core/common/password_manager_features.cc
index 3a8e5f0e961..89fa83caf6a 100644
--- a/chromium/components/password_manager/core/common/password_manager_features.cc
+++ b/chromium/components/password_manager/core/common/password_manager_features.cc
@@ -20,6 +20,11 @@ const base::Feature kEditPasswordsInDesktopSettings = {
const base::Feature kDeleteCorruptedPasswords = {
"DeleteCorruptedPasswords", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables a second, Gaia-account-scoped password store for users who are signed
+// in but not syncing.
+const base::Feature kEnablePasswordsAccountStorage = {
+ "EnablePasswordsAccountStorage", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables the experiment for the password manager to only fill on account
// selection, rather than autofilling on page load, with highlighting of fields.
const base::Feature kFillOnAccountSelect = {"fill-on-account-select",
@@ -48,26 +53,6 @@ const base::Feature kLeakDetection = {"PasswordLeakDetection",
const base::Feature kManualPasswordGenerationAndroid{
"ManualPasswordGenerationAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
-// Performs a one-off migration (with retries) from a native backend into
-// logindb. Passwords are served from the new location.
-const base::Feature kMigrateLinuxToLoginDB = {"migrate-linux-to-logindb",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Enables new password form parsing mechanism for filling passwords, details in
-// https://goo.gl/QodPH1
-const base::Feature kNewPasswordFormParsing = {
- "new-password-form-parsing", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Enables new password form parsing mechanism for saving passwords, details in
-// https://goo.gl/QodPH1
-const base::Feature kNewPasswordFormParsingForSaving = {
- "new-password-form-parsing-for-saving", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Enables new password form parsing mechanism for saving passwords and disables
-// the old parser, details in https://goo.gl/QodPH1
-const base::Feature kOnlyNewParser = {"only-new-password-form-parsing",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables editing saved passwords for Android.
const base::Feature kPasswordEditingAndroid = {
"PasswordEditingAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -94,6 +79,10 @@ const base::Feature kTouchToFillAndroid = {"TouchToFillAndroid",
const base::Feature kUsernameFirstFlow = {"UsernameFirstFlow",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Makes the password managaer save/update bubble sticky.
+const base::Feature kStickyBubble{"PasswordManagerStickyBubble",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Field trial identifier for password generation requirements.
const char* kGenerationRequirementsFieldTrial =
"PasswordGenerationRequirements";
diff --git a/chromium/components/password_manager/core/common/password_manager_features.h b/chromium/components/password_manager/core/common/password_manager_features.h
index a4f9b59647f..9742fafce03 100644
--- a/chromium/components/password_manager/core/common/password_manager_features.h
+++ b/chromium/components/password_manager/core/common/password_manager_features.h
@@ -19,22 +19,20 @@ namespace features {
extern const base::Feature kEditPasswordsInDesktopSettings;
extern const base::Feature kDeleteCorruptedPasswords;
+extern const base::Feature kEnablePasswordsAccountStorage;
extern const base::Feature kFillOnAccountSelect;
extern const base::Feature kFillOnAccountSelectHttp;
extern const base::Feature kGenerationNoOverwrites;
extern const base::Feature kGooglePasswordManager;
extern const base::Feature kLeakDetection;
extern const base::Feature kManualPasswordGenerationAndroid;
-extern const base::Feature kMigrateLinuxToLoginDB;
-extern const base::Feature kNewPasswordFormParsing;
-extern const base::Feature kNewPasswordFormParsingForSaving;
-extern const base::Feature kOnlyNewParser;
extern const base::Feature kPasswordEditingAndroid;
extern const base::Feature kPasswordImport;
extern const base::Feature kPasswordManagerOnboardingAndroid;
extern const base::Feature kRecoverPasswordsForSyncUsers;
extern const base::Feature kTouchToFillAndroid;
extern const base::Feature kUsernameFirstFlow;
+extern const base::Feature kStickyBubble;
// Field trial and corresponding parameters.
// To manually override this, start Chrome with the following parameters:
diff --git a/chromium/components/password_manager/core/common/password_manager_pref_names.cc b/chromium/components/password_manager/core/common/password_manager_pref_names.cc
index 36fcccaf4c9..0d3ea4f5255 100644
--- a/chromium/components/password_manager/core/common/password_manager_pref_names.cc
+++ b/chromium/components/password_manager/core/common/password_manager_pref_names.cc
@@ -15,7 +15,6 @@ const char kCredentialsEnableAutosignin[] = "credentials_enable_autosignin";
const char kCredentialsEnableService[] = "credentials_enable_service";
#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
-const char kLocalProfileId[] = "profile.local_profile_id";
const char kMigrationToLoginDBStep[] = "profile.migration_to_logindb_step";
#endif
@@ -49,5 +48,11 @@ const char kLastTimeObsoleteHttpCredentialsRemoved[] =
const char kPasswordHashDataList[] = "profile.password_hash_data_list";
+const char kPasswordManagerOnboardingState[] =
+ "profile.password_manager_onboarding_state";
+
+const char kPasswordLeakDetectionEnabled[] =
+ "profile.password_manager_leak_detection";
+
} // namespace prefs
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/common/password_manager_pref_names.h b/chromium/components/password_manager/core/common/password_manager_pref_names.h
index 0eb4a653905..f360324f6d2 100644
--- a/chromium/components/password_manager/core/common/password_manager_pref_names.h
+++ b/chromium/components/password_manager/core/common/password_manager_pref_names.h
@@ -29,9 +29,6 @@ extern const char kCredentialsEnableAutosignin[];
extern const char kCredentialsEnableService[];
#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
-// The local profile id for this profile.
-extern const char kLocalProfileId[];
-
// The current state of the migration to LoginDB from Keyring/Kwallet on Linux.
extern const char kMigrationToLoginDBStep[];
#endif
@@ -81,6 +78,13 @@ extern const char kLastTimeObsoleteHttpCredentialsRemoved[];
// List that contains captured password hashes.
extern const char kPasswordHashDataList[];
+// Integer indicating the state of the password manager onboarding experience.
+extern const char kPasswordManagerOnboardingState[];
+
+// Boolean indicating whether Chrome should check whether the credentials
+// submitted by the user were part of a leak.
+extern const char kPasswordLeakDetectionEnabled[];
+
} // namespace prefs
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/common/passwords_directory_util_ios.cc b/chromium/components/password_manager/core/common/passwords_directory_util_ios.cc
index c27880de5fe..b9e30587475 100644
--- a/chromium/components/password_manager/core/common/passwords_directory_util_ios.cc
+++ b/chromium/components/password_manager/core/common/passwords_directory_util_ios.cc
@@ -35,10 +35,11 @@ bool GetPasswordsDirectory(base::FilePath* directory_path) {
}
void DeletePasswordsDirectory() {
- base::PostTaskWithTraits(FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
- base::BindOnce(&DeletePasswordsDirectorySync));
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+ base::BindOnce(&DeletePasswordsDirectorySync));
}
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/common/passwords_directory_util_ios_unittest.cc b/chromium/components/password_manager/core/common/passwords_directory_util_ios_unittest.cc
index e4d9945e56c..cb9d3644c0a 100644
--- a/chromium/components/password_manager/core/common/passwords_directory_util_ios_unittest.cc
+++ b/chromium/components/password_manager/core/common/passwords_directory_util_ios_unittest.cc
@@ -7,12 +7,12 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
// Tests that DeletePasswordsDirectory() actually deletes the directory.
TEST(PasswordsDirectoryUtilTest, Deletion) {
- base::test::ScopedTaskEnvironment environment;
+ base::test::TaskEnvironment environment;
base::FilePath dir;
ASSERT_TRUE(password_manager::GetPasswordsDirectory(&dir));
ASSERT_TRUE(CreateDirectory(dir));
diff --git a/chromium/components/password_manager/ios/password_form_helper.mm b/chromium/components/password_manager/ios/password_form_helper.mm
index 29f6900ca75..e9bb2a73a95 100644
--- a/chromium/components/password_manager/ios/password_form_helper.mm
+++ b/chromium/components/password_manager/ios/password_form_helper.mm
@@ -16,7 +16,7 @@
#include "components/password_manager/ios/account_select_fill_data.h"
#include "components/password_manager/ios/js_password_manager.h"
#import "ios/web/public/js_messaging/web_frame.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
diff --git a/chromium/components/password_manager/ios/password_form_helper_unittest.mm b/chromium/components/password_manager/ios/password_form_helper_unittest.mm
index b50b6d170e8..c4c5b399ee3 100644
--- a/chromium/components/password_manager/ios/password_form_helper_unittest.mm
+++ b/chromium/components/password_manager/ios/password_form_helper_unittest.mm
@@ -21,7 +21,7 @@
#include "components/password_manager/ios/test_helpers.h"
#include "ios/web/public/test/fakes/test_web_client.h"
#import "ios/web/public/test/web_test_with_web_state.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
diff --git a/chromium/components/password_manager/ios/password_suggestion_helper.mm b/chromium/components/password_manager/ios/password_suggestion_helper.mm
index 3a313fa461d..42491ca5a74 100644
--- a/chromium/components/password_manager/ios/password_suggestion_helper.mm
+++ b/chromium/components/password_manager/ios/password_suggestion_helper.mm
@@ -10,7 +10,7 @@
#include "components/password_manager/ios/account_select_fill_data.h"
#include "ios/web/public/js_messaging/web_frame.h"
#include "ios/web/public/js_messaging/web_frame_util.h"
-#import "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
diff --git a/chromium/components/payments/content/BUILD.gn b/chromium/components/payments/content/BUILD.gn
index dec5545dcfc..25df858745b 100644
--- a/chromium/components/payments/content/BUILD.gn
+++ b/chromium/components/payments/content/BUILD.gn
@@ -115,6 +115,8 @@ jumbo_static_library("utils") {
jumbo_source_set("unit_tests") {
testonly = true
sources = [
+ "mock_identity_observer.cc",
+ "mock_identity_observer.h",
"payment_method_manifest_table_unittest.cc",
"service_worker_payment_app_factory_unittest.cc",
"test_content_payment_request_delegate.cc",
diff --git a/chromium/components/payments/content/android/java/src/org/chromium/components/payments/PaymentHandlerHost.java b/chromium/components/payments/content/android/java/src/org/chromium/components/payments/PaymentHandlerHost.java
index 62b3e27fe5a..da9478cc895 100644
--- a/chromium/components/payments/content/android/java/src/org/chromium/components/payments/PaymentHandlerHost.java
+++ b/chromium/components/payments/content/android/java/src/org/chromium/components/payments/PaymentHandlerHost.java
@@ -7,6 +7,7 @@ package org.chromium.components.payments;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
+import org.chromium.content_public.browser.WebContents;
import org.chromium.payments.mojom.PaymentMethodChangeResponse;
import java.nio.ByteBuffer;
@@ -39,10 +40,12 @@ public class PaymentHandlerHost {
/**
* Instantiates the native bridge to the payment handler host. This Java object owns the native
* bridge. The caller must call destroy() when finished using this Java object.
- * @param delegate The object that can communicate to the merchant renderer process.
+ * @param webContents The web contents in the same browser context as the payment handler. Used
+ * for logging in developer tools.
+ * @param delegate The object that can communicate to the merchant renderer process.
*/
- public PaymentHandlerHost(PaymentHandlerHostDelegate delegate) {
- mNativePointer = PaymentHandlerHostJni.get().init(delegate);
+ public PaymentHandlerHost(WebContents webContents, PaymentHandlerHostDelegate delegate) {
+ mNativePointer = PaymentHandlerHostJni.get().init(webContents, delegate);
}
/**
@@ -96,10 +99,12 @@ public class PaymentHandlerHost {
/**
* Initializes the native object. The Java caller owns the returned native object and must
* call destroy(nativePaymentHandlerHost) when done.
- * @param delegate The object that can communicate to the merchant renderer process.
+ * @param webContents The web contents in the same browser context as the payment handler.
+ * Used for logging in developer tools.
+ * @param delegate The object that can communicate to the merchant renderer process.
* @return The pointer to the native payment handler host bridge.
*/
- long init(PaymentHandlerHostDelegate delegate);
+ long init(WebContents webContents, PaymentHandlerHostDelegate delegate);
/**
* Checks whether the payment method change is currently in progress.
diff --git a/chromium/components/payments/content/android/payment_handler_host.cc b/chromium/components/payments/content/android/payment_handler_host.cc
index 155ee6114ae..55591beb2ad 100644
--- a/chromium/components/payments/content/android/payment_handler_host.cc
+++ b/chromium/components/payments/content/android/payment_handler_host.cc
@@ -8,6 +8,7 @@
#include "base/android/jni_string.h"
#include "components/payments/content/android/byte_buffer_helper.h"
#include "components/payments/content/android/jni_headers/PaymentHandlerHost_jni.h"
+#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/payments/payment_handler_host.mojom.h"
namespace payments {
@@ -16,37 +17,36 @@ namespace android {
// static
jlong JNI_PaymentHandlerHost_Init(
JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& web_contents,
const base::android::JavaParamRef<jobject>& delegate) {
- return reinterpret_cast<intptr_t>(new PaymentHandlerHost(delegate));
+ return reinterpret_cast<intptr_t>(
+ new PaymentHandlerHost(web_contents, delegate));
}
PaymentHandlerHost::PaymentHandlerHost(
+ const base::android::JavaParamRef<jobject>& web_contents,
const base::android::JavaParamRef<jobject>& delegate)
- : delegate_(delegate), payment_handler_host_(this) {}
+ : delegate_(delegate),
+ payment_handler_host_(
+ content::WebContents::FromJavaWebContents(web_contents),
+ /*delegate=*/this) {}
PaymentHandlerHost::~PaymentHandlerHost() {}
-jboolean PaymentHandlerHost::IsChangingPaymentMethod(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& j_caller) const {
+jboolean PaymentHandlerHost::IsChangingPaymentMethod(JNIEnv* env) const {
return payment_handler_host_.is_changing_payment_method();
}
-jlong PaymentHandlerHost::GetNativePaymentHandlerHost(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller) {
+jlong PaymentHandlerHost::GetNativePaymentHandlerHost(JNIEnv* env) {
return reinterpret_cast<intptr_t>(&payment_handler_host_);
}
-void PaymentHandlerHost::Destroy(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller) {
+void PaymentHandlerHost::Destroy(JNIEnv* env) {
delete this;
}
void PaymentHandlerHost::UpdateWith(
JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller,
const base::android::JavaParamRef<jobject>& response_buffer) {
mojom::PaymentMethodChangeResponsePtr response;
bool success = mojom::PaymentMethodChangeResponse::Deserialize(
@@ -56,9 +56,7 @@ void PaymentHandlerHost::UpdateWith(
payment_handler_host_.UpdateWith(std::move(response));
}
-void PaymentHandlerHost::NoUpdatedPaymentDetails(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller) {
+void PaymentHandlerHost::NoUpdatedPaymentDetails(JNIEnv* env) {
payment_handler_host_.NoUpdatedPaymentDetails();
}
diff --git a/chromium/components/payments/content/android/payment_handler_host.h b/chromium/components/payments/content/android/payment_handler_host.h
index a95762298b3..4643ccdaf67 100644
--- a/chromium/components/payments/content/android/payment_handler_host.h
+++ b/chromium/components/payments/content/android/payment_handler_host.h
@@ -36,37 +36,31 @@ namespace android {
class PaymentHandlerHost : public payments::PaymentHandlerHost::Delegate {
public:
// The |delegate| must implement PaymentHandlerHostDelegate from
- // PaymentHandlerHost.java.
- explicit PaymentHandlerHost(
- const base::android::JavaParamRef<jobject>& delegate);
+ // PaymentHandlerHost.java. The |web_contents| should be from the same browser
+ // context as the payment handler and are used for logging in developr tools.
+ PaymentHandlerHost(const base::android::JavaParamRef<jobject>& web_contents,
+ const base::android::JavaParamRef<jobject>& delegate);
~PaymentHandlerHost() override;
// Checks whether the payment method change is currently in progress.
- jboolean IsChangingPaymentMethod(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller) const;
+ jboolean IsChangingPaymentMethod(JNIEnv* env) const;
// Returns the pointer to the payments::PaymentHandlerHost for binding to its
// IPC endpoint in service_worker_payment_app_bridge.cc.
- jlong GetNativePaymentHandlerHost(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller);
+ jlong GetNativePaymentHandlerHost(JNIEnv* env);
// Destroys this object.
- void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& caller);
+ void Destroy(JNIEnv* env);
// Notifies the payment handler that the merchant has updated the payment
// details. The |response_buffer| should be a serialization of a valid
// PaymentMethodChangeResponse.java object.
void UpdateWith(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller,
const base::android::JavaParamRef<jobject>& response_buffer);
// Notifies the payment handler that the merchant ignored the payment
// method change event.
- void NoUpdatedPaymentDetails(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& caller);
+ void NoUpdatedPaymentDetails(JNIEnv* env);
private:
// PaymentHandlerHost::Delegate implementation:
diff --git a/chromium/components/payments/content/android/payment_manifest_parser_android.cc b/chromium/components/payments/content/android/payment_manifest_parser_android.cc
index 63f7f935206..98abacdb4a3 100644
--- a/chromium/components/payments/content/android/payment_manifest_parser_android.cc
+++ b/chromium/components/payments/content/android/payment_manifest_parser_android.cc
@@ -131,7 +131,6 @@ PaymentManifestParserAndroid::~PaymentManifestParserAndroid() {}
void PaymentManifestParserAndroid::ParsePaymentMethodManifest(
JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jcontent,
const base::android::JavaParamRef<jobject>& jcallback) {
parser_.ParsePaymentMethodManifest(
@@ -142,7 +141,6 @@ void PaymentManifestParserAndroid::ParsePaymentMethodManifest(
void PaymentManifestParserAndroid::ParseWebAppManifest(
JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jcontent,
const base::android::JavaParamRef<jobject>& jcallback) {
parser_.ParseWebAppManifest(
@@ -152,8 +150,7 @@ void PaymentManifestParserAndroid::ParseWebAppManifest(
}
void PaymentManifestParserAndroid::DestroyPaymentManifestParserAndroid(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller) {
+ JNIEnv* env) {
delete this;
}
diff --git a/chromium/components/payments/content/android/payment_manifest_parser_android.h b/chromium/components/payments/content/android/payment_manifest_parser_android.h
index e763e549de3..c201077a9cf 100644
--- a/chromium/components/payments/content/android/payment_manifest_parser_android.h
+++ b/chromium/components/payments/content/android/payment_manifest_parser_android.h
@@ -25,19 +25,15 @@ class PaymentManifestParserAndroid {
void ParsePaymentMethodManifest(
JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jcontent,
const base::android::JavaParamRef<jobject>& jcallback);
void ParseWebAppManifest(
JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller,
const base::android::JavaParamRef<jstring>& jcontent,
const base::android::JavaParamRef<jobject>& jcallback);
- void DestroyPaymentManifestParserAndroid(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller);
+ void DestroyPaymentManifestParserAndroid(JNIEnv* env);
private:
PaymentManifestParser parser_;
diff --git a/chromium/components/payments/content/installable_payment_app_crawler.cc b/chromium/components/payments/content/installable_payment_app_crawler.cc
index e5a0a6bdd76..76c20508ad7 100644
--- a/chromium/components/payments/content/installable_payment_app_crawler.cc
+++ b/chromium/components/payments/content/installable_payment_app_crawler.cc
@@ -68,7 +68,7 @@ void InstallablePaymentAppCrawler::Start(
if (manifests_to_download.empty()) {
// Post the result back asynchronously.
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
&InstallablePaymentAppCrawler::FinishCrawlingPaymentAppsIfReady,
diff --git a/chromium/components/payments/content/mock_identity_observer.cc b/chromium/components/payments/content/mock_identity_observer.cc
new file mode 100644
index 00000000000..c580003cd97
--- /dev/null
+++ b/chromium/components/payments/content/mock_identity_observer.cc
@@ -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.
+
+#include "components/payments/content/mock_identity_observer.h"
+
+namespace payments {
+
+MockIdentityObserver::MockIdentityObserver() = default;
+
+MockIdentityObserver::~MockIdentityObserver() = default;
+
+base::WeakPtr<ServiceWorkerPaymentInstrument::IdentityObserver>
+MockIdentityObserver::AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+} // namespace payments
diff --git a/chromium/components/payments/content/mock_identity_observer.h b/chromium/components/payments/content/mock_identity_observer.h
new file mode 100644
index 00000000000..b6886335079
--- /dev/null
+++ b/chromium/components/payments/content/mock_identity_observer.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 COMPONENTS_PAYMENTS_CONTENT_MOCK_IDENTITY_OBSERVER_H_
+#define COMPONENTS_PAYMENTS_CONTENT_MOCK_IDENTITY_OBSERVER_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/payments/content/service_worker_payment_instrument.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "url/origin.h"
+
+namespace payments {
+
+class MockIdentityObserver
+ : public ServiceWorkerPaymentInstrument::IdentityObserver {
+ public:
+ MockIdentityObserver();
+ ~MockIdentityObserver() override;
+ MOCK_METHOD2(SetInvokedServiceWorkerIdentity,
+ void(const url::Origin& origin, int64_t registration_id));
+
+ base::WeakPtr<ServiceWorkerPaymentInstrument::IdentityObserver> AsWeakPtr();
+
+ private:
+ base::WeakPtrFactory<MockIdentityObserver> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(MockIdentityObserver);
+};
+
+} // namespace payments
+
+#endif // COMPONENTS_PAYMENTS_CONTENT_MOCK_IDENTITY_OBSERVER_H_
diff --git a/chromium/components/payments/content/payment_handler_host.cc b/chromium/components/payments/content/payment_handler_host.cc
index 0c78c635a30..fdb0a82ccc6 100644
--- a/chromium/components/payments/content/payment_handler_host.cc
+++ b/chromium/components/payments/content/payment_handler_host.cc
@@ -7,29 +7,56 @@
#include <utility>
#include "base/callback.h"
+#include "base/strings/string_number_conversions.h"
#include "components/payments/core/error_strings.h"
#include "components/payments/core/native_error_strings.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/devtools_background_services_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
+#include "url/origin.h"
namespace payments {
+namespace {
-PaymentHandlerHost::PaymentHandlerHost(Delegate* delegate)
- : binding_(this), delegate_(delegate) {
+content::DevToolsBackgroundServicesContext* GetDevTools(
+ content::BrowserContext* browser_context,
+ const url::Origin& sw_origin) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ auto* storage_partition = content::BrowserContext::GetStoragePartitionForSite(
+ browser_context, sw_origin.GetURL(), /*can_create=*/true);
+ if (!storage_partition)
+ return nullptr;
+
+ auto* dev_tools = storage_partition->GetDevToolsBackgroundServicesContext();
+ return dev_tools && dev_tools->IsRecording(
+ content::DevToolsBackgroundService::kPaymentHandler)
+ ? dev_tools
+ : nullptr;
+}
+
+} // namespace
+
+PaymentHandlerHost::PaymentHandlerHost(content::WebContents* web_contents,
+ Delegate* delegate)
+ : web_contents_(web_contents), delegate_(delegate) {
+ DCHECK(web_contents_);
DCHECK(delegate_);
}
PaymentHandlerHost::~PaymentHandlerHost() {}
-mojom::PaymentHandlerHostPtrInfo PaymentHandlerHost::Bind() {
- mojom::PaymentHandlerHostPtrInfo host_ptr_info;
- binding_.Close();
- binding_.Bind(mojo::MakeRequest(&host_ptr_info));
+mojo::PendingRemote<mojom::PaymentHandlerHost> PaymentHandlerHost::Bind() {
+ receiver_.reset();
+ mojo::PendingRemote<mojom::PaymentHandlerHost> host =
+ receiver_.BindNewPipeAndPassRemote();
// Connection error handler can be set only after the Bind() call.
- binding_.set_connection_error_handler(base::BindOnce(
+ receiver_.set_disconnect_handler(base::BindOnce(
&PaymentHandlerHost::Disconnect, weak_ptr_factory_.GetWeakPtr()));
- return host_ptr_info;
+ return host;
}
void PaymentHandlerHost::UpdateWith(
@@ -37,6 +64,45 @@ void PaymentHandlerHost::UpdateWith(
if (!change_payment_method_callback_)
return;
+ auto* dev_tools =
+ GetDevTools(web_contents_->GetBrowserContext(), sw_origin_for_logs_);
+ if (dev_tools) {
+ std::map<std::string, std::string> data = {{"Error", response->error}};
+
+ if (response->total) {
+ data["Total Currency"] = response->total->currency;
+ data["Total Value"] = response->total->value;
+ }
+
+ if (response->stringified_payment_method_errors) {
+ data["Payment Method Errors"] =
+ *response->stringified_payment_method_errors;
+ }
+
+ if (response->modifiers) {
+ for (size_t i = 0; i < response->modifiers->size(); ++i) {
+ std::string prefix =
+ "Modifier" + (response->modifiers->size() == 1
+ ? ""
+ : " #" + base::NumberToString(i));
+ const auto& modifier = response->modifiers->at(i);
+ data.emplace(prefix + " Method Name",
+ modifier->method_data->method_name);
+ data.emplace(prefix + " Method Data",
+ modifier->method_data->stringified_data);
+ if (!modifier->total)
+ continue;
+ data.emplace(prefix + " Total Currency", modifier->total->currency);
+ data.emplace(prefix + " Total Value", modifier->total->value);
+ }
+ }
+
+ dev_tools->LogBackgroundServiceEvent(
+ registration_id_for_logs_, sw_origin_for_logs_,
+ content::DevToolsBackgroundService::kPaymentHandler, "Update with",
+ /*instance_id=*/payment_request_id_for_logs_, data);
+ }
+
std::move(change_payment_method_callback_).Run(std::move(response));
}
@@ -49,7 +115,7 @@ void PaymentHandlerHost::NoUpdatedPaymentDetails() {
}
void PaymentHandlerHost::Disconnect() {
- binding_.Close();
+ receiver_.reset();
}
base::WeakPtr<PaymentHandlerHost> PaymentHandlerHost::AsWeakPtr() {
@@ -86,6 +152,18 @@ void PaymentHandlerHost::ChangePaymentMethod(
return;
}
+ auto* dev_tools =
+ GetDevTools(web_contents_->GetBrowserContext(), sw_origin_for_logs_);
+ if (dev_tools) {
+ dev_tools->LogBackgroundServiceEvent(
+ registration_id_for_logs_, sw_origin_for_logs_,
+ content::DevToolsBackgroundService::kPaymentHandler,
+ "Change payment method",
+ /*instance_id=*/payment_request_id_for_logs_,
+ {{"Method Name", method_data->method_name},
+ {"Method Data", method_data->stringified_data}});
+ }
+
change_payment_method_callback_ = std::move(callback);
}
diff --git a/chromium/components/payments/content/payment_handler_host.h b/chromium/components/payments/content/payment_handler_host.h
index d2046ce9b4b..427a18b033d 100644
--- a/chromium/components/payments/content/payment_handler_host.h
+++ b/chromium/components/payments/content/payment_handler_host.h
@@ -5,13 +5,20 @@
#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_HANDLER_HOST_H_
#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_HANDLER_HOST_H_
+#include <stdint.h>
#include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/mojom/payments/payment_handler_host.mojom.h"
+#include "url/origin.h"
+
+namespace content {
+class WebContents;
+} // namespace content
namespace payments {
@@ -19,7 +26,7 @@ namespace payments {
// merchant renderer process.
class PaymentHandlerHost : public mojom::PaymentHandlerHost {
public:
- // The interfce to be implemented by the object that can communicate to the
+ // The interface to be implemented by the object that can communicate to the
// merchant's renderer process.
class Delegate {
public:
@@ -32,10 +39,30 @@ class PaymentHandlerHost : public mojom::PaymentHandlerHost {
};
// The |delegate| cannot be null and must outlive this object. Typically this
- // is accomplished by the |delegate| owning this object.
- explicit PaymentHandlerHost(Delegate* delegate);
+ // is accomplished by the |delegate| owning this object. The |web_contents| is
+ // used for developer tools logging and should be from the same browser
+ // context as the payment handler.
+ PaymentHandlerHost(content::WebContents* web_contents, Delegate* delegate);
~PaymentHandlerHost() override;
+ // Sets the origin of the payment handler / service worker registration scope.
+ // Used for developer tools logging.
+ void set_sw_origin_for_logs(const url::Origin& origin) {
+ sw_origin_for_logs_ = origin;
+ }
+
+ // Sets the registration identifier of the payment handler / service worker.
+ // Used for developer tools logging.
+ void set_registration_id_for_logs(int64_t id) {
+ registration_id_for_logs_ = id;
+ }
+
+ // Sets the identifier for the Payment Request object. Used for developer
+ // tools logging.
+ void set_payment_request_id_for_logs(const std::string& id) {
+ payment_request_id_for_logs_ = id;
+ }
+
// Returns "true" when the payment handler has changed the payment method, but
// has not received the response from the merchant yet.
bool is_changing_payment_method() const {
@@ -43,7 +70,7 @@ class PaymentHandlerHost : public mojom::PaymentHandlerHost {
}
// Binds to an IPC endpoint and returns it.
- mojom::PaymentHandlerHostPtrInfo Bind();
+ mojo::PendingRemote<mojom::PaymentHandlerHost> Bind();
// Notifies the payment handler of the updated details, such as updated total,
// in response to the change of the payment method.
@@ -71,11 +98,26 @@ class PaymentHandlerHost : public mojom::PaymentHandlerHost {
// The end-point for the payment handler renderer process to call into the
// browser process.
- mojo::Binding<mojom::PaymentHandlerHost> binding_;
+ mojo::Receiver<mojom::PaymentHandlerHost> receiver_{this};
+
+ // The merchant page that invoked the Payment Request API.
+ content::WebContents* web_contents_;
// Not null and outlives this object. Owns this object.
Delegate* delegate_;
+ // The origin of the payment handler / service worker registration scope. Used
+ // for developer tools logging.
+ url::Origin sw_origin_for_logs_;
+
+ // The registration identifier for the payment handler / service worker. Used
+ // for developer tools logging.
+ int64_t registration_id_for_logs_ = -1;
+
+ // The identifier for the Payment Request object. Used for developer tools
+ // logging.
+ std::string payment_request_id_for_logs_;
+
base::WeakPtrFactory<PaymentHandlerHost> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PaymentHandlerHost);
diff --git a/chromium/components/payments/content/payment_instrument_unittest.cc b/chromium/components/payments/content/payment_instrument_unittest.cc
index a80151369e1..85d341903e7 100644
--- a/chromium/components/payments/content/payment_instrument_unittest.cc
+++ b/chromium/components/payments/content/payment_instrument_unittest.cc
@@ -10,12 +10,13 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/payments/content/mock_identity_observer.h"
#include "components/payments/content/service_worker_payment_instrument.h"
#include "components/payments/core/autofill_payment_instrument.h"
#include "components/payments/core/mock_payment_request_delegate.h"
#include "content/public/browser/stored_payment_app.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
@@ -49,7 +50,7 @@ class PaymentInstrumentTest : public testing::Test,
return std::make_unique<ServiceWorkerPaymentInstrument>(
&browser_context_, GURL("https://testmerchant.com"),
GURL("https://testmerchant.com/bobpay"), spec_.get(),
- std::move(stored_app), &delegate_);
+ std::move(stored_app), &delegate_, identity_observer_.AsWeakPtr());
}
autofill::CreditCard& local_credit_card() { return local_card_; }
@@ -68,12 +69,13 @@ class PaymentInstrumentTest : public testing::Test,
std::move(method_data), this, "en-US");
}
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
autofill::AutofillProfile address_;
autofill::CreditCard local_card_;
std::vector<autofill::AutofillProfile*> billing_profiles_;
MockPaymentRequestDelegate delegate_;
+ MockIdentityObserver identity_observer_;
std::unique_ptr<PaymentRequestSpec> spec_;
DISALLOW_COPY_AND_ASSIGN(PaymentInstrumentTest);
diff --git a/chromium/components/payments/content/payment_request.cc b/chromium/components/payments/content/payment_request.cc
index 7b8f92ff96d..331be864c7a 100644
--- a/chromium/components/payments/content/payment_request.cc
+++ b/chromium/components/payments/content/payment_request.cc
@@ -78,7 +78,7 @@ PaymentRequest::PaymentRequest(
std::unique_ptr<ContentPaymentRequestDelegate> delegate,
PaymentRequestWebContentsManager* manager,
PaymentRequestDisplayManager* display_manager,
- mojo::InterfaceRequest<mojom::PaymentRequest> request,
+ mojo::PendingReceiver<mojom::PaymentRequest> receiver,
ObserverForTest* observer_for_testing)
: web_contents_(web_contents),
log_(web_contents_),
@@ -86,8 +86,7 @@ PaymentRequest::PaymentRequest(
manager_(manager),
display_manager_(display_manager),
display_handle_(nullptr),
- binding_(this, std::move(request)),
- payment_handler_host_(this),
+ payment_handler_host_(web_contents_, this),
top_level_origin_(url_formatter::FormatUrlForSecurityDisplay(
web_contents_->GetLastCommittedURL())),
frame_origin_(url_formatter::FormatUrlForSecurityDisplay(
@@ -95,21 +94,23 @@ PaymentRequest::PaymentRequest(
observer_for_testing_(observer_for_testing),
journey_logger_(delegate_->IsIncognito(),
ukm::GetSourceIdForWebContentsDocument(web_contents)) {
+ receiver_.Bind(std::move(receiver));
// OnConnectionTerminated will be called when the Mojo pipe is closed. This
// will happen as a result of many renderer-side events (both successful and
// erroneous in nature).
// TODO(crbug.com/683636): Investigate using
// set_connection_error_with_reason_handler with Binding::CloseWithReason.
- binding_.set_connection_error_handler(base::BindOnce(
+ receiver_.set_disconnect_handler(base::BindOnce(
&PaymentRequest::OnConnectionTerminated, weak_ptr_factory_.GetWeakPtr()));
}
PaymentRequest::~PaymentRequest() {}
-void PaymentRequest::Init(mojom::PaymentRequestClientPtr client,
- std::vector<mojom::PaymentMethodDataPtr> method_data,
- mojom::PaymentDetailsPtr details,
- mojom::PaymentOptionsPtr options) {
+void PaymentRequest::Init(
+ mojo::PendingRemote<mojom::PaymentRequestClient> client,
+ std::vector<mojom::PaymentMethodDataPtr> method_data,
+ mojom::PaymentDetailsPtr details,
+ mojom::PaymentOptionsPtr options) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (is_initialized_) {
@@ -119,7 +120,7 @@ void PaymentRequest::Init(mojom::PaymentRequestClientPtr client,
}
is_initialized_ = true;
- client_ = std::move(client);
+ client_.Bind(std::move(client));
const GURL last_committed_url = delegate_->GetLastCommittedURL();
if (!content::IsOriginSecure(last_committed_url)) {
@@ -165,12 +166,14 @@ void PaymentRequest::Init(mojom::PaymentRequestClientPtr client,
}
spec_ = std::make_unique<PaymentRequestSpec>(
- std::move(options), std::move(details), std::move(method_data), this,
- delegate_->GetApplicationLocale());
+ std::move(options), std::move(details), std::move(method_data),
+ /*observer=*/this, delegate_->GetApplicationLocale());
state_ = std::make_unique<PaymentRequestState>(
- web_contents_, top_level_origin_, frame_origin_, spec_.get(), this,
- delegate_->GetApplicationLocale(), delegate_->GetPersonalDataManager(),
- delegate_.get(), &journey_logger_);
+ web_contents_, top_level_origin_, frame_origin_, spec_.get(),
+ /*delegate=*/this, delegate_->GetApplicationLocale(),
+ delegate_->GetPersonalDataManager(), delegate_.get(),
+ /*sw_identity_observer=*/weak_ptr_factory_.GetWeakPtr(),
+ &journey_logger_);
journey_logger_.SetRequestedInformation(
spec_->request_shipping(), spec_->request_payer_email(),
@@ -194,6 +197,8 @@ void PaymentRequest::Init(mojom::PaymentRequestClientPtr client,
android_pay_url),
/*requested_method_other=*/non_google_it !=
spec_->url_payment_method_identifiers().end());
+
+ payment_handler_host_.set_payment_request_id_for_logs(*spec_->details().id);
}
void PaymentRequest::Show(bool is_user_gesture, bool wait_for_updated_details) {
@@ -210,6 +215,7 @@ void PaymentRequest::Show(bool is_user_gesture, bool wait_for_updated_details) {
}
is_show_called_ = true;
+ journey_logger_.SetTriggerTime();
// A tab can display only one PaymentRequest UI at a time.
display_handle_ = display_manager_->TryShow(delegate_.get());
@@ -433,7 +439,7 @@ void PaymentRequest::Complete(mojom::PaymentComplete result) {
}
}
-void PaymentRequest::CanMakePayment(bool legacy_mode) {
+void PaymentRequest::CanMakePayment() {
if (!IsInitialized()) {
log_.Error(errors::kCannotCallCanMakePaymentWithoutInit);
OnConnectionTerminated();
@@ -447,12 +453,11 @@ void PaymentRequest::CanMakePayment(bool legacy_mode) {
if (!delegate_->GetPrefService()->GetBoolean(kCanMakePaymentEnabled) ||
!state_) {
- CanMakePaymentCallback(legacy_mode, /*can_make_payment=*/false);
+ CanMakePaymentCallback(/*can_make_payment=*/false);
} else {
state_->CanMakePayment(
- legacy_mode,
base::BindOnce(&PaymentRequest::CanMakePaymentCallback,
- weak_ptr_factory_.GetWeakPtr(), legacy_mode));
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -513,7 +518,7 @@ void PaymentRequest::AreRequestedMethodsSupportedCallback(
bool PaymentRequest::IsInitialized() const {
return is_initialized_ && client_ && client_.is_bound() &&
- binding_.is_bound();
+ receiver_.is_bound();
}
bool PaymentRequest::IsThisPaymentRequestShowing() const {
@@ -616,6 +621,12 @@ void PaymentRequest::OnPayerInfoSelected(mojom::PayerDetailPtr payer_info) {
client_->OnPayerDetailChange(std::move(payer_info));
}
+void PaymentRequest::SetInvokedServiceWorkerIdentity(const url::Origin& origin,
+ int64_t registration_id) {
+ payment_handler_host_.set_sw_origin_for_logs(origin);
+ payment_handler_host_.set_registration_id_for_logs(registration_id);
+}
+
void PaymentRequest::UserCancelled() {
// If |client_| is not bound, then the object is already being destroyed as
// a result of a renderer event.
@@ -632,7 +643,7 @@ void PaymentRequest::UserCancelled() {
// We close all bindings and ask to be destroyed.
client_.reset();
- binding_.Close();
+ receiver_.reset();
payment_handler_host_.Disconnect();
if (observer_for_testing_)
observer_for_testing_->OnConnectionTerminated();
@@ -648,12 +659,12 @@ void PaymentRequest::DidStartMainFrameNavigationToDifferentDocument(
void PaymentRequest::OnConnectionTerminated() {
// We are here because of a browser-side error, or likely as a result of the
- // connection_error_handler on |binding_|, which can mean that the renderer
+ // disconnect_handler on |receiver_|, which can mean that the renderer
// has decided to close the pipe for various reasons (see all uses of
// PaymentRequest::clearResolversAndCloseMojoConnection() in Blink). We close
// the binding and the dialog, and ask to be deleted.
client_.reset();
- binding_.Close();
+ receiver_.reset();
payment_handler_host_.Disconnect();
delegate_->CloseDialog();
if (observer_for_testing_)
@@ -690,31 +701,10 @@ void PaymentRequest::RecordFirstAbortReason(
}
}
-void PaymentRequest::CanMakePaymentCallback(bool legacy_mode,
- bool can_make_payment) {
- // Only need to enforce query quota in legacy mode. Per-method quota not
- // supported.
- if (legacy_mode && spec_ &&
- !CanMakePaymentQueryFactory::GetInstance()
- ->GetForContext(web_contents_->GetBrowserContext())
- ->CanQuery(top_level_origin_, frame_origin_,
- spec_->stringified_method_data(),
- /*per_method_quota=*/false)) {
- if (UrlUtil::IsLocalDevelopmentUrl(frame_origin_)) {
- client_->OnCanMakePayment(
- can_make_payment
- ? CanMakePaymentQueryResult::WARNING_CAN_MAKE_PAYMENT
- : CanMakePaymentQueryResult::WARNING_CANNOT_MAKE_PAYMENT);
- } else {
- client_->OnCanMakePayment(
- CanMakePaymentQueryResult::QUERY_QUOTA_EXCEEDED);
- }
- } else {
- client_->OnCanMakePayment(
- can_make_payment
- ? mojom::CanMakePaymentQueryResult::CAN_MAKE_PAYMENT
- : mojom::CanMakePaymentQueryResult::CANNOT_MAKE_PAYMENT);
- }
+void PaymentRequest::CanMakePaymentCallback(bool can_make_payment) {
+ client_->OnCanMakePayment(
+ can_make_payment ? mojom::CanMakePaymentQueryResult::CAN_MAKE_PAYMENT
+ : mojom::CanMakePaymentQueryResult::CANNOT_MAKE_PAYMENT);
journey_logger_.SetCanMakePaymentValue(can_make_payment);
@@ -725,11 +715,10 @@ void PaymentRequest::CanMakePaymentCallback(bool legacy_mode,
void PaymentRequest::HasEnrolledInstrumentCallback(
bool per_method_quota,
bool has_enrolled_instrument) {
- if (!spec_ ||
- CanMakePaymentQueryFactory::GetInstance()
- ->GetForContext(web_contents_->GetBrowserContext())
- ->CanQuery(top_level_origin_, frame_origin_,
- spec_->stringified_method_data(), per_method_quota)) {
+ if (!spec_ || CanMakePaymentQueryFactory::GetInstance()
+ ->GetForContext(web_contents_->GetBrowserContext())
+ ->CanQuery(top_level_origin_, frame_origin_,
+ spec_->query_for_quota(), per_method_quota)) {
RespondToHasEnrolledInstrumentQuery(has_enrolled_instrument,
/*warn_local_development=*/false);
} else if (UrlUtil::IsLocalDevelopmentUrl(frame_origin_)) {
diff --git a/chromium/components/payments/content/payment_request.h b/chromium/components/payments/content/payment_request.h
index 4b4f766fd61..c59f187df3e 100644
--- a/chromium/components/payments/content/payment_request.h
+++ b/chromium/components/payments/content/payment_request.h
@@ -15,9 +15,10 @@
#include "components/payments/content/payment_request_display_manager.h"
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/content/payment_request_state.h"
+#include "components/payments/content/service_worker_payment_instrument.h"
#include "components/payments/core/journey_logger.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/interface_request.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.h"
#include "url/gurl.h"
@@ -40,7 +41,8 @@ class PaymentRequestWebContentsManager;
class PaymentRequest : public mojom::PaymentRequest,
public PaymentHandlerHost::Delegate,
public PaymentRequestSpec::Observer,
- public PaymentRequestState::Delegate {
+ public PaymentRequestState::Delegate,
+ public ServiceWorkerPaymentInstrument::IdentityObserver {
public:
class ObserverForTest {
public:
@@ -61,12 +63,12 @@ class PaymentRequest : public mojom::PaymentRequest,
std::unique_ptr<ContentPaymentRequestDelegate> delegate,
PaymentRequestWebContentsManager* manager,
PaymentRequestDisplayManager* display_manager,
- mojo::InterfaceRequest<mojom::PaymentRequest> request,
+ mojo::PendingReceiver<mojom::PaymentRequest> receiver,
ObserverForTest* observer_for_testing);
~PaymentRequest() override;
// mojom::PaymentRequest
- void Init(mojom::PaymentRequestClientPtr client,
+ void Init(mojo::PendingRemote<mojom::PaymentRequestClient> client,
std::vector<mojom::PaymentMethodDataPtr> method_data,
mojom::PaymentDetailsPtr details,
mojom::PaymentOptionsPtr options) override;
@@ -76,7 +78,7 @@ class PaymentRequest : public mojom::PaymentRequest,
void NoUpdatedPaymentDetails() override;
void Abort() override;
void Complete(mojom::PaymentComplete result) override;
- void CanMakePayment(bool legacy_mode) override;
+ void CanMakePayment() override;
void HasEnrolledInstrument(bool per_method_quota) override;
// PaymentHandlerHost::Delegate
@@ -93,6 +95,10 @@ class PaymentRequest : public mojom::PaymentRequest,
void OnShippingAddressSelected(mojom::PaymentAddressPtr address) override;
void OnPayerInfoSelected(mojom::PayerDetailPtr payer_info) override;
+ // ServiceWorkerPaymentInstrument::IdentityObserver:
+ void SetInvokedServiceWorkerIdentity(const url::Origin& origin,
+ int64_t registration_id) override;
+
// Called when the user explicitly cancelled the flow. Will send a message
// to the renderer which will indirectly destroy this object (through
// OnConnectionTerminated).
@@ -146,9 +152,8 @@ class PaymentRequest : public mojom::PaymentRequest,
// the first one being the most precise.
void RecordFirstAbortReason(JourneyLogger::AbortReason completion_status);
- // The callback for PaymentRequestState::CanMakePayment. Checks for query
- // quota and may send QUERY_QUOTA_EXCEEDED.
- void CanMakePaymentCallback(bool legacy_mode, bool can_make_payment);
+ // The callback for PaymentRequestState::CanMakePayment.
+ void CanMakePaymentCallback(bool can_make_payment);
// The callback for PaymentRequestState::HasEnrolledInstrument. Checks for
// query quota and may send QUERY_QUOTA_EXCEEDED.
@@ -175,8 +180,8 @@ class PaymentRequest : public mojom::PaymentRequest,
PaymentRequestWebContentsManager* manager_;
PaymentRequestDisplayManager* display_manager_;
std::unique_ptr<PaymentRequestDisplayManager::DisplayHandle> display_handle_;
- mojo::Binding<mojom::PaymentRequest> binding_;
- mojom::PaymentRequestClientPtr client_;
+ mojo::Receiver<mojom::PaymentRequest> receiver_{this};
+ mojo::Remote<mojom::PaymentRequestClient> client_;
std::unique_ptr<PaymentRequestSpec> spec_;
std::unique_ptr<PaymentRequestState> state_;
diff --git a/chromium/components/payments/content/payment_request_spec.cc b/chromium/components/payments/content/payment_request_spec.cc
index 792689bf665..c8b7c31eb3b 100644
--- a/chromium/components/payments/content/payment_request_spec.cc
+++ b/chromium/components/payments/content/payment_request_spec.cc
@@ -8,12 +8,15 @@
#include "base/feature_list.h"
#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/payments/content/payment_request_converter.h"
#include "components/payments/core/features.h"
#include "components/payments/core/payment_instrument.h"
#include "components/payments/core/payment_method_data.h"
#include "components/payments/core/payment_request_data_util.h"
+#include "components/payments/core/payments_experimental_features.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
@@ -68,6 +71,10 @@ void PopulateValidatedMethodData(
payment_method_identifiers_set, stringified_method_data);
}
+std::string ToString(bool value) {
+ return value ? "true" : "false";
+}
+
} // namespace
const char kBasicCardMethodName[] = "basic-card";
@@ -100,6 +107,18 @@ PaymentRequestSpec::PaymentRequestSpec(
&supported_card_networks_set_, &supported_card_types_set_,
&url_payment_method_identifiers_, &payment_method_identifiers_set_,
&stringified_method_data_);
+
+ query_for_quota_ = stringified_method_data_;
+ if (base::Contains(payment_method_identifiers_set_, "basic-card") &&
+ PaymentsExperimentalFeatures::IsEnabled(
+ features::kStrictHasEnrolledAutofillInstrument)) {
+ query_for_quota_["basic-card-payment-options"] = {
+ base::ReplaceStringPlaceholders(
+ "{payerEmail:$1,payerName:$2,payerPhone:$3,shipping:$4}",
+ {ToString(request_payer_email()), ToString(request_payer_name()),
+ ToString(request_payer_phone()), ToString(request_shipping())},
+ nullptr)};
+ }
}
PaymentRequestSpec::~PaymentRequestSpec() {}
diff --git a/chromium/components/payments/content/payment_request_spec.h b/chromium/components/payments/content/payment_request_spec.h
index 693de31e55f..80735b71bde 100644
--- a/chromium/components/payments/content/payment_request_spec.h
+++ b/chromium/components/payments/content/payment_request_spec.h
@@ -125,6 +125,19 @@ class PaymentRequestSpec : public PaymentOptionsProvider,
bool request_payer_email() const override;
PaymentShippingType shipping_type() const override;
+ // Returns the query to be used for the quota on hasEnrolledInstrument()
+ // calls. Generally this returns the payment method identifiers and their
+ // corresponding data. However, in the case of basic-card with
+ // kStrictHasEnrolledAutofillInstrument feature enabled, this method also
+ // returns the following payment options:
+ // - requestPayerEmail
+ // - requestPayerName
+ // - requestPayerPhone
+ // - requestShipping
+ const std::map<std::string, std::set<std::string>>& query_for_quota() const {
+ return query_for_quota_;
+ }
+
bool supports_basic_card() const { return !supported_card_networks_.empty(); }
const std::vector<std::string>& supported_card_networks() const {
@@ -260,6 +273,16 @@ class PaymentRequestSpec : public PaymentOptionsProvider,
// payment method specific data.
std::map<std::string, std::set<std::string>> stringified_method_data_;
+ // A mapping of the payment method names to the corresponding JSON-stringified
+ // payment method specific data. If kStrictHasEnrolledAutofillInstrument is
+ // enabled, then the key "basic-card-payment-options" also maps to the
+ // following payment options:
+ // - requestPayerEmail
+ // - requestPayerName
+ // - requestPayerPhone
+ // - requestShipping
+ std::map<std::string, std::set<std::string>> query_for_quota_;
+
// The reason why this payment request is waiting for updateWith.
UpdateReason current_update_reason_;
diff --git a/chromium/components/payments/content/payment_request_state.cc b/chromium/components/payments/content/payment_request_state.cc
index 31e6c300da4..c12071df6bb 100644
--- a/chromium/components/payments/content/payment_request_state.cc
+++ b/chromium/components/payments/content/payment_request_state.cc
@@ -41,6 +41,8 @@ PaymentRequestState::PaymentRequestState(
const std::string& app_locale,
autofill::PersonalDataManager* personal_data_manager,
ContentPaymentRequestDelegate* payment_request_delegate,
+ base::WeakPtr<ServiceWorkerPaymentInstrument::IdentityObserver>
+ sw_identity_observer,
JourneyLogger* journey_logger)
: is_ready_to_pay_(false),
get_all_instruments_finished_(true),
@@ -60,7 +62,9 @@ PaymentRequestState::PaymentRequestState(
selected_instrument_(nullptr),
number_of_pending_sw_payment_instruments_(0),
payment_request_delegate_(payment_request_delegate),
+ sw_identity_observer_(sw_identity_observer),
profile_comparator_(app_locale, *spec) {
+ DCHECK(sw_identity_observer_);
if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
DCHECK(web_contents);
get_all_instruments_finished_ = false;
@@ -108,7 +112,8 @@ void PaymentRequestState::GetAllPaymentAppsCallback(
std::unique_ptr<ServiceWorkerPaymentInstrument> instrument =
std::make_unique<ServiceWorkerPaymentInstrument>(
web_contents->GetBrowserContext(), top_level_origin, frame_origin,
- spec_, std::move(app.second), payment_request_delegate_);
+ spec_, std::move(app.second), payment_request_delegate_,
+ sw_identity_observer_);
instrument->ValidateCanMakePayment(
base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
weak_ptr_factory_.GetWeakPtr()));
@@ -120,7 +125,7 @@ void PaymentRequestState::GetAllPaymentAppsCallback(
std::make_unique<ServiceWorkerPaymentInstrument>(
web_contents, top_level_origin, frame_origin, spec_,
std::move(installable_app.second), installable_app.first.spec(),
- payment_request_delegate_);
+ payment_request_delegate_, sw_identity_observer_);
instrument->ValidateCanMakePayment(
base::BindOnce(&PaymentRequestState::OnSWPaymentInstrumentValidated,
weak_ptr_factory_.GetWeakPtr()));
@@ -158,8 +163,7 @@ void PaymentRequestState::FinishedGetAllSWPaymentInstruments() {
// Fulfill the pending CanMakePayment call.
if (can_make_payment_callback_) {
- CheckCanMakePayment(can_make_payment_legacy_mode_,
- std::move(can_make_payment_callback_));
+ CheckCanMakePayment(std::move(can_make_payment_callback_));
}
// Fulfill the pending HasEnrolledInstrument call.
@@ -215,38 +219,22 @@ void PaymentRequestState::OnSpecUpdated() {
UpdateIsReadyToPayAndNotifyObservers();
}
-void PaymentRequestState::CanMakePayment(bool legacy_mode,
- StatusCallback callback) {
+void PaymentRequestState::CanMakePayment(StatusCallback callback) {
if (!get_all_instruments_finished_) {
DCHECK(!can_make_payment_callback_);
can_make_payment_callback_ = std::move(callback);
- can_make_payment_legacy_mode_ = legacy_mode;
return;
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&PaymentRequestState::CheckCanMakePayment,
- weak_ptr_factory_.GetWeakPtr(), legacy_mode,
- std::move(callback)));
+ FROM_HERE,
+ base::BindOnce(&PaymentRequestState::CheckCanMakePayment,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
-void PaymentRequestState::CheckCanMakePayment(bool legacy_mode,
- StatusCallback callback) {
+void PaymentRequestState::CheckCanMakePayment(StatusCallback callback) {
DCHECK(get_all_instruments_finished_);
- if (!legacy_mode) {
- std::move(callback).Run(are_requested_methods_supported_);
- return;
- }
-
- // Legacy mode: fall back to also checking if an instrument is enrolled.
- bool can_make_payment_value = false;
- for (const auto& instrument : available_instruments_) {
- if (instrument->IsValidForCanMakePayment()) {
- can_make_payment_value = true;
- break;
- }
- }
- std::move(callback).Run(can_make_payment_value);
+ std::move(callback).Run(are_requested_methods_supported_);
}
void PaymentRequestState::HasEnrolledInstrument(StatusCallback callback) {
@@ -370,6 +358,8 @@ void PaymentRequestState::AddAutofillPaymentInstrument(
auto instrument = std::make_unique<AutofillPaymentInstrument>(
basic_card_network, card, matches_merchant_card_type_exactly,
shipping_profiles_, app_locale_, payment_request_delegate_);
+ instrument->set_is_requested_autofill_data_available(
+ is_requested_autofill_data_available_);
available_instruments_.push_back(std::move(instrument));
if (selected) {
@@ -559,6 +549,7 @@ void PaymentRequestState::PopulateProfileCache() {
contact_profiles_.empty()
? false
: profile_comparator()->IsContactInfoComplete(contact_profiles_[0]);
+ is_requested_autofill_data_available_ &= has_complete_contact;
journey_logger_->SetNumberOfSuggestionsShown(
JourneyLogger::Section::SECTION_CONTACT_INFO, contact_profiles_.size(),
has_complete_contact);
@@ -568,6 +559,7 @@ void PaymentRequestState::PopulateProfileCache() {
shipping_profiles_.empty()
? false
: profile_comparator()->IsShippingComplete(shipping_profiles_[0]);
+ is_requested_autofill_data_available_ &= has_complete_shipping;
journey_logger_->SetNumberOfSuggestionsShown(
JourneyLogger::Section::SECTION_SHIPPING_ADDRESS,
shipping_profiles_.size(), has_complete_shipping);
diff --git a/chromium/components/payments/content/payment_request_state.h b/chromium/components/payments/content/payment_request_state.h
index 921fff640e9..e176d35f1c7 100644
--- a/chromium/components/payments/content/payment_request_state.h
+++ b/chromium/components/payments/content/payment_request_state.h
@@ -17,6 +17,7 @@
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/content/payment_response_helper.h"
#include "components/payments/content/service_worker_payment_app_factory.h"
+#include "components/payments/content/service_worker_payment_instrument.h"
#include "components/payments/core/journey_logger.h"
#include "components/payments/core/payments_profile_comparator.h"
#include "content/public/browser/payment_app_provider.h"
@@ -34,7 +35,6 @@ namespace payments {
class ContentPaymentRequestDelegate;
class PaymentInstrument;
-class ServiceWorkerPaymentInstrument;
// Keeps track of the information currently selected by the user and whether the
// user is ready to pay. Uses information from the PaymentRequestSpec, which is
@@ -107,15 +107,18 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
base::OnceCallback<void(bool methods_supported,
const std::string& error_message)>;
- PaymentRequestState(content::WebContents* web_contents,
- const GURL& top_level_origin,
- const GURL& frame_origin,
- PaymentRequestSpec* spec,
- Delegate* delegate,
- const std::string& app_locale,
- autofill::PersonalDataManager* personal_data_manager,
- ContentPaymentRequestDelegate* payment_request_delegate,
- JourneyLogger* journey_logger);
+ PaymentRequestState(
+ content::WebContents* web_contents,
+ const GURL& top_level_origin,
+ const GURL& frame_origin,
+ PaymentRequestSpec* spec,
+ Delegate* delegate,
+ const std::string& app_locale,
+ autofill::PersonalDataManager* personal_data_manager,
+ ContentPaymentRequestDelegate* payment_request_delegate,
+ base::WeakPtr<ServiceWorkerPaymentInstrument::IdentityObserver>
+ sw_identity_observer,
+ JourneyLogger* journey_logger);
~PaymentRequestState() override;
// PaymentResponseHelper::Delegate
@@ -130,8 +133,7 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
// Checks whether support for the specified payment methods exist, either
// because the user has a registered payment handler or because the browser
// can do just-in-time registration for a suitable payment handler.
- // If |legacy_mode| is true, then also checks that an instrument is enrolled.
- void CanMakePayment(bool legacy_mode, StatusCallback callback);
+ void CanMakePayment(StatusCallback callback);
// Checks whether the user has at least one instrument that satisfies the
// specified supported payment methods asynchronously.
@@ -310,7 +312,7 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
// Checks whether support for the specified payment methods exists and call
// the |callback| to return the result.
- void CheckCanMakePayment(bool legacy_mode, StatusCallback callback);
+ void CheckCanMakePayment(StatusCallback callback);
// Checks whether the user has at least one instrument that satisfies the
// specified supported payment methods and call the |callback| to return the
@@ -327,8 +329,16 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
void IncrementSelectionStatus(JourneyLogger::Section section,
SectionSelectionStatus selection_status);
+ // True when the requested autofill data (shipping address and/or contact
+ // information) and payment data (either autofill or service worker) are
+ // complete, valid, and selected.
bool is_ready_to_pay_;
+ // True when the requested autofill data (shipping address and/or contact
+ // information) is complete and valid, even if not selected. This variable is
+ // not affected by payment instruments.
+ bool is_requested_autofill_data_available_ = true;
+
bool get_all_instruments_finished_;
// Whether the data is currently being validated by the merchant.
@@ -342,10 +352,6 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
autofill::PersonalDataManager* personal_data_manager_;
JourneyLogger* journey_logger_;
- // Whether |can_make_payment_callback_| expects the legacy canMakePayment
- // semantic. Only meaningful when |can_make_payment_callback_| is present.
- bool can_make_payment_legacy_mode_ = false;
-
StatusCallback can_make_payment_callback_;
StatusCallback has_enrolled_instrument_callback_;
MethodsSupportedCallback are_requested_methods_supported_callback_;
@@ -374,6 +380,8 @@ class PaymentRequestState : public PaymentResponseHelper::Delegate,
std::vector<std::unique_ptr<PaymentInstrument>> available_instruments_;
ContentPaymentRequestDelegate* payment_request_delegate_;
+ base::WeakPtr<ServiceWorkerPaymentInstrument::IdentityObserver>
+ sw_identity_observer_;
std::unique_ptr<PaymentResponseHelper> response_helper_;
diff --git a/chromium/components/payments/content/payment_request_state_unittest.cc b/chromium/components/payments/content/payment_request_state_unittest.cc
index 866bb9a3b98..567145417c4 100644
--- a/chromium/components/payments/content/payment_request_state_unittest.cc
+++ b/chromium/components/payments/content/payment_request_state_unittest.cc
@@ -15,6 +15,7 @@
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/payments/content/mock_identity_observer.h"
#include "components/payments/content/payment_request_spec.h"
#include "components/payments/content/test_content_payment_request_delegate.h"
#include "components/payments/core/journey_logger.h"
@@ -79,7 +80,7 @@ class PaymentRequestStateTest : public testing::Test,
nullptr /* context */, GURL("https://example.com"),
GURL("https://example.com/pay"), spec_.get(), this, "en-US",
&test_personal_data_manager_, &test_payment_request_delegate_,
- &journey_logger_);
+ identity_observer_.AsWeakPtr(), &journey_logger_);
state_->AddObserver(this);
}
@@ -137,6 +138,7 @@ class PaymentRequestStateTest : public testing::Test,
mojom::PaymentAddressPtr selected_shipping_address_;
autofill::TestPersonalDataManager test_personal_data_manager_;
TestContentPaymentRequestDelegate test_payment_request_delegate_;
+ MockIdentityObserver identity_observer_;
JourneyLogger journey_logger_;
// Test data.
@@ -148,22 +150,14 @@ TEST_F(PaymentRequestStateTest, CanMakePayment) {
// Default options.
RecreateStateWithOptions(mojom::PaymentOptions::New());
- // Legacy CanMakePayment returns true because the method data requires Visa,
- // and the user has a Visa card on file.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_TRUE(has_enrolled_instrument);
}));
// CanMakePayment returns true because the requested method is supported.
- state()->CanMakePayment(/*legacy_mode=*/false,
- base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_TRUE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest, CanMakePayment_NoEnrolledInstrument) {
@@ -177,12 +171,6 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_NoEnrolledInstrument) {
mojom::PaymentDetails::New(),
std::move(method_data));
- // Legacy CanMakePayment returns false because the method data requires
- // MasterCard, and the user doesn't have such an instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_FALSE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_FALSE(has_enrolled_instrument);
@@ -190,10 +178,8 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_NoEnrolledInstrument) {
// CanMakePayment returns true because the requested method is supported, even
// though the payment instrument is not ready to pay.
- state()->CanMakePayment(/*legacy_mode=*/false,
- base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_TRUE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest, CanMakePayment_UnsupportedPaymentMethod) {
@@ -205,12 +191,6 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_UnsupportedPaymentMethod) {
mojom::PaymentDetails::New(),
std::move(method_data));
- // Legacy CanMakePayment returns false because the method data requires
- // MasterCard, and the user doesn't have such an instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_FALSE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_FALSE(has_enrolled_instrument);
@@ -218,10 +198,8 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_UnsupportedPaymentMethod) {
// CanMakePayment returns true because the requested method is supported, even
// though the payment instrument is not ready to pay.
- state()->CanMakePayment(/*legacy_mode=*/false,
- base::BindOnce([](bool can_make_payment) {
- EXPECT_FALSE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_FALSE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest, CanMakePayment_OnlyBasicCard) {
@@ -234,22 +212,14 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_OnlyBasicCard) {
mojom::PaymentDetails::New(),
std::move(method_data));
- // Legacy CanMakePayment returns true because the method data supports
- // everything, and the user has at least one instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_TRUE(has_enrolled_instrument);
}));
// CanMakePayment returns true because the requested method is supported.
- state()->CanMakePayment(
- /*legacy_mode=*/false, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_TRUE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest, CanMakePayment_BasicCard_SpecificAvailable) {
@@ -263,22 +233,14 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_BasicCard_SpecificAvailable) {
mojom::PaymentDetails::New(),
std::move(method_data));
- // Legacy CanMakePayment returns true because the method data supports visa,
- // and the user has a Visa instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_TRUE(has_enrolled_instrument);
}));
// CanMakePayment returns true because the requested method is supported.
- state()->CanMakePayment(
- /*legacy_mode=*/false, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_TRUE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest,
@@ -293,12 +255,6 @@ TEST_F(PaymentRequestStateTest,
mojom::PaymentDetails::New(),
std::move(method_data));
- // Legacy CanMakePayment returns false because the method data supports jcb,
- // and the user has a JCB instrument, but it's invalid.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_FALSE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_FALSE(has_enrolled_instrument);
@@ -306,10 +262,8 @@ TEST_F(PaymentRequestStateTest,
// CanMakePayment returns true because the requested method is supported, even
// though there is no enrolled instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/false, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_TRUE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest, CanMakePayment_BasicCard_SpecificUnavailable) {
@@ -323,12 +277,6 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_BasicCard_SpecificUnavailable) {
mojom::PaymentDetails::New(),
std::move(method_data));
- // Legacy CanMakePayment returns false because the method data supports
- // mastercard, and the user doesn't have such an instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/true, base::BindOnce([](bool can_make_payment) {
- EXPECT_FALSE(can_make_payment);
- }));
state()->HasEnrolledInstrument(
base::BindOnce([](bool has_enrolled_instrument) {
EXPECT_FALSE(has_enrolled_instrument);
@@ -336,10 +284,8 @@ TEST_F(PaymentRequestStateTest, CanMakePayment_BasicCard_SpecificUnavailable) {
// CanMakePayment returns true because the requested method is supported, even
// though there is no enrolled instrument.
- state()->CanMakePayment(
- /*legacy_mode=*/false, base::BindOnce([](bool can_make_payment) {
- EXPECT_TRUE(can_make_payment);
- }));
+ state()->CanMakePayment(base::BindOnce(
+ [](bool can_make_payment) { EXPECT_TRUE(can_make_payment); }));
}
TEST_F(PaymentRequestStateTest, ReadyToPay_DefaultSelections) {
diff --git a/chromium/components/payments/content/service_worker_payment_instrument.cc b/chromium/components/payments/content/service_worker_payment_instrument.cc
index 6ac9b623739..c1256666b32 100644
--- a/chromium/components/payments/content/service_worker_payment_instrument.cc
+++ b/chromium/components/payments/content/service_worker_payment_instrument.cc
@@ -31,7 +31,8 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
const GURL& frame_origin,
const PaymentRequestSpec* spec,
std::unique_ptr<content::StoredPaymentApp> stored_payment_app_info,
- PaymentRequestDelegate* payment_request_delegate)
+ PaymentRequestDelegate* payment_request_delegate,
+ base::WeakPtr<IdentityObserver> identity_observer)
: PaymentInstrument(0, PaymentInstrument::Type::SERVICE_WORKER_APP),
browser_context_(browser_context),
top_origin_(top_origin),
@@ -40,6 +41,7 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
stored_payment_app_info_(std::move(stored_payment_app_info)),
delegate_(nullptr),
payment_request_delegate_(payment_request_delegate),
+ identity_observer_(identity_observer),
can_make_payment_result_(false),
has_enrolled_instrument_result_(false),
needs_installation_(false) {
@@ -47,6 +49,7 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
DCHECK(top_origin_.is_valid());
DCHECK(frame_origin_.is_valid());
DCHECK(spec_);
+ DCHECK(identity_observer_);
if (stored_payment_app_info_->icon) {
icon_image_ =
@@ -67,13 +70,15 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
const PaymentRequestSpec* spec,
std::unique_ptr<WebAppInstallationInfo> installable_payment_app_info,
const std::string& enabled_method,
- PaymentRequestDelegate* payment_request_delegate)
+ PaymentRequestDelegate* payment_request_delegate,
+ base::WeakPtr<IdentityObserver> identity_observer)
: PaymentInstrument(0, PaymentInstrument::Type::SERVICE_WORKER_APP),
top_origin_(top_origin),
frame_origin_(frame_origin),
spec_(spec),
delegate_(nullptr),
payment_request_delegate_(payment_request_delegate),
+ identity_observer_(identity_observer),
can_make_payment_result_(false),
has_enrolled_instrument_result_(false),
needs_installation_(true),
@@ -84,6 +89,7 @@ ServiceWorkerPaymentInstrument::ServiceWorkerPaymentInstrument(
DCHECK(top_origin_.is_valid());
DCHECK(frame_origin_.is_valid());
DCHECK(spec_);
+ DCHECK(identity_observer_);
if (installable_web_app_info_->icon) {
icon_image_ =
@@ -193,6 +199,7 @@ ServiceWorkerPaymentInstrument::CreateCanMakePaymentEventData() {
void ServiceWorkerPaymentInstrument::OnCanMakePaymentEventSkipped(
ValidateCanMakePaymentCallback callback) {
+ // |can_make_payment| is true as long as there is a matching payment handler.
can_make_payment_result_ = true;
has_enrolled_instrument_result_ = false;
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -203,16 +210,9 @@ void ServiceWorkerPaymentInstrument::OnCanMakePaymentEventSkipped(
void ServiceWorkerPaymentInstrument::OnCanMakePaymentEventResponded(
ValidateCanMakePaymentCallback callback,
bool result) {
- // If hasEnrolledInstrument is supported, always return true for
- // canMakePayment for any matching payment handler.
- if (base::FeatureList::IsEnabled(
- ::features::kPaymentRequestHasEnrolledInstrument)) {
- can_make_payment_result_ = true;
- has_enrolled_instrument_result_ = result;
- } else {
- can_make_payment_result_ = result;
- has_enrolled_instrument_result_ = result;
- }
+ // |can_make_payment| is true as long as there is a matching payment handler.
+ can_make_payment_result_ = true;
+ has_enrolled_instrument_result_ = result;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), this, can_make_payment_result_));
@@ -231,12 +231,19 @@ void ServiceWorkerPaymentInstrument::InvokePaymentApp(Delegate* delegate) {
installable_web_app_info_->sw_js_url,
installable_web_app_info_->sw_scope,
installable_web_app_info_->sw_use_cache, installable_enabled_method_,
+ base::BindOnce(
+ &IdentityObserver::SetInvokedServiceWorkerIdentity,
+ identity_observer_,
+ url::Origin::Create(GURL(installable_web_app_info_->sw_scope))),
base::BindOnce(&ServiceWorkerPaymentInstrument::OnPaymentAppInvoked,
weak_ptr_factory_.GetWeakPtr()));
} else {
+ url::Origin sw_origin =
+ url::Origin::Create(stored_payment_app_info_->scope);
+ identity_observer_->SetInvokedServiceWorkerIdentity(
+ sw_origin, stored_payment_app_info_->registration_id);
content::PaymentAppProvider::GetInstance()->InvokePaymentApp(
- browser_context_, stored_payment_app_info_->registration_id,
- url::Origin::Create(stored_payment_app_info_->scope),
+ browser_context_, stored_payment_app_info_->registration_id, sw_origin,
CreatePaymentRequestEventData(),
base::BindOnce(&ServiceWorkerPaymentInstrument::OnPaymentAppInvoked,
weak_ptr_factory_.GetWeakPtr()));
@@ -341,11 +348,7 @@ bool ServiceWorkerPaymentInstrument::IsValidForCanMakePayment() const {
// This instrument should not be used when can_make_payment_result_ is false,
// so this interface should not be invoked.
DCHECK(can_make_payment_result_);
- if (base::FeatureList::IsEnabled(
- ::features::kPaymentRequestHasEnrolledInstrument)) {
- return has_enrolled_instrument_result_;
- }
- return true;
+ return has_enrolled_instrument_result_;
}
void ServiceWorkerPaymentInstrument::RecordUse() {
diff --git a/chromium/components/payments/content/service_worker_payment_instrument.h b/chromium/components/payments/content/service_worker_payment_instrument.h
index 31adfcff1ff..d288913ac5d 100644
--- a/chromium/components/payments/content/service_worker_payment_instrument.h
+++ b/chromium/components/payments/content/service_worker_payment_instrument.h
@@ -12,6 +12,7 @@
#include "components/payments/content/web_app_manifest.h"
#include "components/payments/core/payment_instrument.h"
#include "content/public/browser/stored_payment_app.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/payments/payment_app.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_handler_host.mojom.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
@@ -21,6 +22,10 @@ class BrowserContext;
class WebContents;
} // namespace content
+namespace url {
+class Origin;
+} // namespace url
+
namespace payments {
class PaymentRequestDelegate;
@@ -28,6 +33,21 @@ class PaymentRequestDelegate;
// Represents a service worker based payment app.
class ServiceWorkerPaymentInstrument : public PaymentInstrument {
public:
+ // Observer for identity of the service worker, which is known ahead of time
+ // when already installed, but may be unknown at first when using just-in-time
+ // installation.
+ class IdentityObserver {
+ public:
+ virtual ~IdentityObserver() {}
+
+ // Notifies the observer that the service worker registration has the
+ // |registration_id| and its scope has |origin|. Called exactly once after
+ // InvokePaymentApp(). Called before the service worker actually receives
+ // the 'paymentrequest' event.
+ virtual void SetInvokedServiceWorkerIdentity(const url::Origin& origin,
+ int64_t registration_id) = 0;
+ };
+
// This constructor is used for a payment app that has been installed in
// Chrome.
ServiceWorkerPaymentInstrument(
@@ -36,9 +56,10 @@ class ServiceWorkerPaymentInstrument : public PaymentInstrument {
const GURL& frame_origin,
const PaymentRequestSpec* spec,
std::unique_ptr<content::StoredPaymentApp> stored_payment_app_info,
- PaymentRequestDelegate* payment_request_delegate);
+ PaymentRequestDelegate* payment_request_delegate,
+ base::WeakPtr<IdentityObserver> identity_observer);
- // This contructor is used for a payment app that has not been installed in
+ // This constructor is used for a payment app that has not been installed in
// Chrome but can be installed when paying with it.
ServiceWorkerPaymentInstrument(
content::WebContents* web_contents,
@@ -47,7 +68,8 @@ class ServiceWorkerPaymentInstrument : public PaymentInstrument {
const PaymentRequestSpec* spec,
std::unique_ptr<WebAppInstallationInfo> installable_payment_app_info,
const std::string& enabled_methods,
- PaymentRequestDelegate* payment_request_delegate);
+ PaymentRequestDelegate* payment_request_delegate,
+ base::WeakPtr<IdentityObserver> identity_observer);
~ServiceWorkerPaymentInstrument() override;
// The callback for ValidateCanMakePayment.
@@ -89,7 +111,7 @@ class ServiceWorkerPaymentInstrument : public PaymentInstrument {
gfx::ImageSkia icon_image_skia() const override;
void set_payment_handler_host(
- mojom::PaymentHandlerHostPtrInfo payment_handler_host) {
+ mojo::PendingRemote<mojom::PaymentHandlerHost> payment_handler_host) {
payment_handler_host_ = std::move(payment_handler_host);
}
@@ -118,7 +140,11 @@ class ServiceWorkerPaymentInstrument : public PaymentInstrument {
// Weak pointer that must outlive this object.
PaymentRequestDelegate* payment_request_delegate_;
- mojom::PaymentHandlerHostPtrInfo payment_handler_host_;
+ // The object that is notified of service worker registration identifier after
+ // the service worker is installed.
+ base::WeakPtr<IdentityObserver> identity_observer_;
+
+ mojo::PendingRemote<mojom::PaymentHandlerHost> payment_handler_host_;
// PaymentAppProvider::CanMakePayment result of this payment instrument.
bool can_make_payment_result_;
diff --git a/chromium/components/payments/content/service_worker_payment_instrument_unittest.cc b/chromium/components/payments/content/service_worker_payment_instrument_unittest.cc
index 36fe9710764..17d0f2c5077 100644
--- a/chromium/components/payments/content/service_worker_payment_instrument_unittest.cc
+++ b/chromium/components/payments/content/service_worker_payment_instrument_unittest.cc
@@ -8,12 +8,11 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
+#include "components/payments/content/mock_identity_observer.h"
#include "components/payments/core/mock_payment_request_delegate.h"
#include "content/public/browser/stored_payment_app.h"
-#include "content/public/common/content_features.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
@@ -120,7 +119,7 @@ class ServiceWorkerPaymentInstrumentTest : public testing::Test,
instrument_ = std::make_unique<ServiceWorkerPaymentInstrument>(
&browser_context_, GURL("https://testmerchant.com"),
GURL("https://testmerchant.com/bobpay"), spec_.get(),
- std::move(stored_app), &delegate_);
+ std::move(stored_app), &delegate_, identity_observer_.AsWeakPtr());
}
ServiceWorkerPaymentInstrument* GetInstrument() { return instrument_.get(); }
@@ -135,7 +134,8 @@ class ServiceWorkerPaymentInstrumentTest : public testing::Test,
private:
MockPaymentRequestDelegate delegate_;
- content::TestBrowserThreadBundle thread_bundle_;
+ MockIdentityObserver identity_observer_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
std::unique_ptr<PaymentRequestSpec> spec_;
@@ -222,10 +222,6 @@ TEST_F(ServiceWorkerPaymentInstrumentTest, CreateCanMakePaymentEvent) {
// Test the case when CanMakePaymentEvent cannot be fired. The instrument should
// be considered valid, but not ready for payment.
TEST_F(ServiceWorkerPaymentInstrumentTest, ValidateCanMakePayment) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(
- features::kPaymentRequestHasEnrolledInstrument);
-
// CanMakePaymentEvent is not fired because this test instrument does not have
// any explicitly verified methods.
CreateServiceWorkerPaymentInstrument(/*with_url_method=*/true);
diff --git a/chromium/components/payments/core/autofill_payment_instrument.cc b/chromium/components/payments/core/autofill_payment_instrument.cc
index 67265732722..8d94ac39330 100644
--- a/chromium/components/payments/core/autofill_payment_instrument.cc
+++ b/chromium/components/payments/core/autofill_payment_instrument.cc
@@ -22,8 +22,10 @@
#include "components/autofill/core/common/autofill_clock.h"
#include "components/payments/core/autofill_card_validation.h"
#include "components/payments/core/basic_card_response.h"
+#include "components/payments/core/features.h"
#include "components/payments/core/payment_request_base_delegate.h"
#include "components/payments/core/payment_request_data_util.h"
+#include "components/payments/core/payments_experimental_features.h"
namespace payments {
@@ -123,6 +125,12 @@ base::string16 AutofillPaymentInstrument::GetMissingInfoLabel() const {
bool AutofillPaymentInstrument::IsValidForCanMakePayment() const {
CreditCardCompletionStatus status =
GetCompletionStatusForCard(credit_card_, app_locale_, billing_profiles_);
+ if (PaymentsExperimentalFeatures::IsEnabled(
+ features::kStrictHasEnrolledAutofillInstrument)) {
+ return status == CREDIT_CARD_COMPLETE &&
+ is_requested_autofill_data_available_;
+ }
+
// Card has to have a cardholder name and number for the purposes of
// CanMakePayment. An expired card is still valid at this stage.
return !(status & CREDIT_CARD_NO_CARDHOLDER ||
diff --git a/chromium/components/payments/core/autofill_payment_instrument.h b/chromium/components/payments/core/autofill_payment_instrument.h
index ec123d11b8b..3c78957f116 100644
--- a/chromium/components/payments/core/autofill_payment_instrument.h
+++ b/chromium/components/payments/core/autofill_payment_instrument.h
@@ -70,6 +70,11 @@ class AutofillPaymentInstrument
void RecordMissingFieldsForInstrument() const;
+ // Sets whether the complete and valid autofill data for merchant's request is
+ // available.
+ void set_is_requested_autofill_data_available(bool available) {
+ is_requested_autofill_data_available_ = available;
+ }
autofill::CreditCard* credit_card() { return &credit_card_; }
const autofill::CreditCard* credit_card() const { return &credit_card_; }
@@ -108,6 +113,11 @@ class AutofillPaymentInstrument
bool is_waiting_for_card_unmask_;
bool is_waiting_for_billing_address_normalization_;
+ // True when complete and valid autofill data for merchant's request is
+ // available, e.g., if merchant specifies `requestPayerEmail: true`, then this
+ // variable is true only if the autofill data contains a valid email address.
+ bool is_requested_autofill_data_available_ = false;
+
base::WeakPtrFactory<AutofillPaymentInstrument> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(AutofillPaymentInstrument);
diff --git a/chromium/components/payments/core/can_make_payment_query_unittest.cc b/chromium/components/payments/core/can_make_payment_query_unittest.cc
index c7be1ff9780..4b00986ac3b 100644
--- a/chromium/components/payments/core/can_make_payment_query_unittest.cc
+++ b/chromium/components/payments/core/can_make_payment_query_unittest.cc
@@ -4,7 +4,7 @@
#include "components/payments/core/can_make_payment_query.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -16,7 +16,7 @@ class CanMakePaymentQueryTest : public ::testing::Test {
CanMakePaymentQuery guard_;
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
// An HTTPS website is not allowed to query all of the networks of the cards in
diff --git a/chromium/components/payments/core/features.cc b/chromium/components/payments/core/features.cc
index e5c53900459..d5ef9aaa9ae 100644
--- a/chromium/components/payments/core/features.cc
+++ b/chromium/components/payments/core/features.cc
@@ -42,7 +42,10 @@ const base::Feature kWebPaymentsPerMethodCanMakePaymentQuota{
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kWebPaymentsRedactShippingAddress{
- "WebPaymentsRedactShippingAddress", base::FEATURE_DISABLED_BY_DEFAULT};
+ "WebPaymentsRedactShippingAddress", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kStrictHasEnrolledAutofillInstrument{
+ "StrictHasEnrolledAutofillInstrument", base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
} // namespace payments
diff --git a/chromium/components/payments/core/features.h b/chromium/components/payments/core/features.h
index f760f10956b..e8aa5c2ec7e 100644
--- a/chromium/components/payments/core/features.h
+++ b/chromium/components/payments/core/features.h
@@ -49,6 +49,10 @@ extern const base::Feature kWebPaymentsPerMethodCanMakePaymentQuota;
// ShippingAddressChangeEvent is redacted of fine-grained details.
extern const base::Feature kWebPaymentsRedactShippingAddress;
+// Used to make autofill instrument more restrictive when responding to
+// hasEnrolledInstrument() queries.
+extern const base::Feature kStrictHasEnrolledAutofillInstrument;
+
} // namespace features
} // namespace payments
diff --git a/chromium/components/payments/core/journey_logger.cc b/chromium/components/payments/core/journey_logger.cc
index 048f263041e..c886758679c 100644
--- a/chromium/components/payments/core/journey_logger.cc
+++ b/chromium/components/payments/core/journey_logger.cc
@@ -73,6 +73,15 @@ bool ValidateExclusiveBitVector(const std::vector<bool>& bit_vector) {
return seen_true_bit;
}
+// Records time to checkout for payment requests. The 5-minute max is chosen
+// since the payment handler window times out after 5 minutes.
+void RecordTimeToCheckoutUmaHistograms(const std::string name,
+ const base::TimeDelta time_to_checkout) {
+ UmaHistogramCustomTimes(
+ name, time_to_checkout, base::TimeDelta::FromMilliseconds(1) /* min */,
+ base::TimeDelta::FromMinutes(5) /* max */, 100 /*bucket count*/);
+}
+
enum class TransactionSize {
kZeroTransaction = 0,
kMicroTransaction = 1,
@@ -269,6 +278,7 @@ void JourneyLogger::RecordJourneyStatsHistograms(
has_recorded_ = true;
RecordEventsMetric(completion_status);
+ RecordTimeToCheckout(completion_status);
// These following metrics only make sense if the Payment Request was
// triggered.
@@ -359,6 +369,72 @@ void JourneyLogger::RecordEventsMetric(CompletionStatus completion_status) {
.Record(ukm::UkmRecorder::Get());
}
+void JourneyLogger::RecordTimeToCheckout(
+ CompletionStatus completion_status) const {
+ const base::TimeDelta time_to_checkout =
+ base::TimeTicks::Now() - trigger_time_;
+ const std::string histogram_name = "PaymentRequest.TimeToCheckout";
+
+ // Whether or not the payment sheet was shown shown.
+ std::string ui_show_suffix;
+ if (events_ & EVENT_SHOWN)
+ ui_show_suffix = ".Shown";
+ else if (events_ & EVENT_SKIPPED_SHOW)
+ ui_show_suffix = ".SkippedShow";
+ else // User aborted before request.show()
+ ui_show_suffix = ".BeforeShow";
+
+ std::string completion_suffix;
+ switch (completion_status) {
+ case COMPLETION_STATUS_COMPLETED: {
+ completion_suffix = ".Completed";
+ // Record time to checkout for completed requests separated by payment
+ // sheet shown status. Requests can complete only after request.show()
+ // call.
+ DCHECK_NE(".BeforeShow", ui_show_suffix);
+ RecordTimeToCheckoutUmaHistograms(
+ histogram_name + ".Completed" + ui_show_suffix, time_to_checkout);
+
+ // Record time to checkout for completed requests separated by payment
+ // sheet shown status and selected method.
+ std::string selected_method_suffix;
+ if (events_ & EVENT_SELECTED_CREDIT_CARD) {
+ selected_method_suffix = ".BasicCard";
+ } else if (events_ & EVENT_SELECTED_GOOGLE) {
+ selected_method_suffix = ".Google";
+ } else {
+ DCHECK(events_ & EVENT_SELECTED_OTHER);
+ selected_method_suffix = ".Other";
+ }
+ RecordTimeToCheckoutUmaHistograms(histogram_name + ".Completed" +
+ ui_show_suffix +
+ selected_method_suffix,
+ time_to_checkout);
+ break;
+ }
+ case COMPLETION_STATUS_USER_ABORTED: {
+ completion_suffix = ".UserAborted";
+ // Record time to checkout for requests aborted by user separated by
+ // payment sheet shown status.
+ RecordTimeToCheckoutUmaHistograms(
+ histogram_name + ".UserAborted" + ui_show_suffix, time_to_checkout);
+ break;
+ }
+ case COMPLETION_STATUS_OTHER_ABORTED:
+ completion_suffix = ".OtherAborted";
+ break;
+ case COMPLETION_STATUS_COULD_NOT_SHOW:
+ // Do not record checkout duration when payment sheet could not shown.
+ return;
+ default:
+ NOTREACHED();
+ }
+ // Record time to checkout for payment reuqests separated by completion
+ // status.
+ RecordTimeToCheckoutUmaHistograms(histogram_name + completion_suffix,
+ time_to_checkout);
+}
+
void JourneyLogger::ValidateEventBits() const {
std::vector<bool> bit_vector;
@@ -422,4 +498,8 @@ bool JourneyLogger::WasPaymentRequestTriggered() {
return (events_ & EVENT_SHOWN) > 0 || (events_ & EVENT_SKIPPED_SHOW) > 0;
}
+void JourneyLogger::SetTriggerTime() {
+ trigger_time_ = base::TimeTicks::Now();
+}
+
} // namespace payments
diff --git a/chromium/components/payments/core/journey_logger.h b/chromium/components/payments/core/journey_logger.h
index 6fce1435156..9939b139c8a 100644
--- a/chromium/components/payments/core/journey_logger.h
+++ b/chromium/components/payments/core/journey_logger.h
@@ -9,6 +9,7 @@
#include <unordered_map>
#include "base/macros.h"
+#include "base/time/time.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
namespace payments {
@@ -189,12 +190,15 @@ class JourneyLogger {
// reason.
void SetNotShown(NotShownReason reason);
- // Records the transcation amount separated by currency and completion status
- // (complete vs triggered).
+ // Records the transcation amount after converting to USD separated by
+ // completion status (complete vs triggered).
void RecordTransactionAmount(std::string currency,
const std::string& value,
bool completed);
+ // Records when Payment Request .show is called.
+ void SetTriggerTime();
+
private:
static const int NUMBER_OF_SECTIONS = 3;
@@ -238,6 +242,9 @@ class JourneyLogger {
// Payment Request.
void RecordEventsMetric(CompletionStatus completion_status);
+ // Records the time between request.show() and request completion/abort.
+ void RecordTimeToCheckout(CompletionStatus completion_status) const;
+
// Validates the recorded event sequence during the Payment Request.
void ValidateEventBits() const;
@@ -258,6 +265,10 @@ class JourneyLogger {
// multiple recording. Triggered is the first index and Completed the second.
bool has_recorded_transaction_amount_[2] = {false};
+ // Stores the time that request.show() is called. This is used to record
+ // checkout duration.
+ base::TimeTicks trigger_time_;
+
ukm::SourceId source_id_;
DISALLOW_COPY_AND_ASSIGN(JourneyLogger);
diff --git a/chromium/components/payments/core/journey_logger_unittest.cc b/chromium/components/payments/core/journey_logger_unittest.cc
index 348f582be81..c430e07138c 100644
--- a/chromium/components/payments/core/journey_logger_unittest.cc
+++ b/chromium/components/payments/core/journey_logger_unittest.cc
@@ -7,7 +7,7 @@
#include "base/metrics/metrics_hashes.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
@@ -931,7 +931,7 @@ TEST(JourneyLoggerTest, RecordJourneyStatsHistograms_TwoPaymentRequests) {
// the Payment Request.
TEST(JourneyLoggerTest,
RecordJourneyStatsHistograms_CheckoutFunnelUkm_UserAborted) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
using UkmEntry = ukm::builders::PaymentRequest_CheckoutEvents;
ukm::TestAutoSetUkmRecorder ukm_recorder;
char test_url[] = "http://www.google.com/";
@@ -982,7 +982,7 @@ TEST(JourneyLoggerTest,
// completes the Payment Request.
TEST(JourneyLoggerTest,
RecordJourneyStatsHistograms_CheckoutFunnelUkm_Completed) {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
using UkmEntry = ukm::builders::PaymentRequest_CheckoutEvents;
ukm::TestAutoSetUkmRecorder ukm_recorder;
char test_url[] = "http://www.google.com/";
diff --git a/chromium/components/payments/core/payment_manifest_downloader.cc b/chromium/components/payments/core/payment_manifest_downloader.cc
index a0544b7796d..edc6776a767 100644
--- a/chromium/components/payments/core/payment_manifest_downloader.cc
+++ b/chromium/components/payments/core/payment_manifest_downloader.cc
@@ -320,7 +320,7 @@ void PaymentManifestDownloader::InitiateDownload(
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
resource_request->method = method;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
std::unique_ptr<network::SimpleURLLoader> loader =
network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation);
diff --git a/chromium/components/payments/core/payment_manifest_downloader_unittest.cc b/chromium/components/payments/core/payment_manifest_downloader_unittest.cc
index b460cb79d5b..c6edd1507b5 100644
--- a/chromium/components/payments/core/payment_manifest_downloader_unittest.cc
+++ b/chromium/components/payments/core/payment_manifest_downloader_unittest.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/payments/core/error_logger.h"
#include "net/http/http_response_headers.h"
@@ -84,7 +84,7 @@ class PaymentMethodManifestDownloaderTest : public testing::Test {
private:
GURL test_url_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
PaymentManifestDownloader downloader_;
@@ -381,7 +381,7 @@ class WebAppManifestDownloaderTest : public testing::Test {
private:
GURL test_url_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
PaymentManifestDownloader downloader_;
diff --git a/chromium/components/pdf/OWNERS b/chromium/components/pdf/OWNERS
index 59c3f69f09b..e209556882a 100644
--- a/chromium/components/pdf/OWNERS
+++ b/chromium/components/pdf/OWNERS
@@ -1 +1,2 @@
file://pdf/OWNERS
+# COMPONENT: Internals>Plugins>PDF
diff --git a/chromium/components/pdf/common/BUILD.gn b/chromium/components/pdf/common/BUILD.gn
index affc4455ba7..a35b6727f89 100644
--- a/chromium/components/pdf/common/BUILD.gn
+++ b/chromium/components/pdf/common/BUILD.gn
@@ -12,7 +12,7 @@ mojom("interfaces") {
public_deps = [
"//third_party/blink/public/mojom:mojom_platform",
- "//ui/gfx/geometry/mojo",
+ "//ui/gfx/geometry/mojom",
"//url/mojom:url_mojom_gurl",
]
diff --git a/chromium/components/pdf/common/pdf.mojom b/chromium/components/pdf/common/pdf.mojom
index 45ae635d3f2..c660dd40701 100644
--- a/chromium/components/pdf/common/pdf.mojom
+++ b/chromium/components/pdf/common/pdf.mojom
@@ -5,7 +5,7 @@
module pdf.mojom;
import "third_party/blink/public/mojom/referrer.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
import "url/mojom/url.mojom";
interface PdfListener {
diff --git a/chromium/components/pdf/renderer/BUILD.gn b/chromium/components/pdf/renderer/BUILD.gn
index fc847d5ba06..fcd72f981f9 100644
--- a/chromium/components/pdf/renderer/BUILD.gn
+++ b/chromium/components/pdf/renderer/BUILD.gn
@@ -9,6 +9,8 @@ jumbo_static_library("renderer") {
sources = [
"pdf_accessibility_tree.cc",
"pdf_accessibility_tree.h",
+ "pdf_ax_action_target.cc",
+ "pdf_ax_action_target.h",
"pepper_pdf_host.cc",
"pepper_pdf_host.h",
]
@@ -32,3 +34,16 @@ jumbo_static_library("renderer") {
"//v8",
]
}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "pdf_accessibility_tree_unittest.cc",
+ ]
+
+ deps = [
+ ":renderer",
+ "//components/pdf/common:interfaces",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree.cc b/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
index 43a47cd48cf..4e26a89bcd3 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -9,11 +9,14 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "components/pdf/renderer/pdf_accessibility_tree.h"
+#include "components/pdf/renderer/pdf_ax_action_target.h"
#include "components/strings/grit/components_strings.h"
+#include "content/public/renderer/pepper_plugin_instance.h"
#include "content/public/renderer/render_accessibility.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ui/accessibility/null_ax_action_target.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/transform.h"
@@ -26,8 +29,8 @@ namespace {
// if the median font size is not at least this many points.
const double kMinimumFontSize = 5;
-// Don't try to apply line break thresholds to automatically identify
-// line breaks if the median line break is not at least this many points.
+// Don't try to apply paragraph break thresholds to automatically identify
+// paragraph breaks if the median line break is not at least this many points.
const double kMinimumLineSpacing = 5;
// Ratio between the font size of one text run and the median on the page
@@ -42,8 +45,161 @@ gfx::RectF ToGfxRectF(const PP_FloatRect& r) {
return gfx::RectF(r.point.x, r.point.y, r.size.width, r.size.height);
}
+// This class is used as part of our heuristic to determine which text runs live
+// on the same "line". As we process runs, we keep a weighted average of the
+// top and bottom coordinates of the line, and if a new run falls within that
+// range (within a threshold) it is considered part of the line.
+class LineHelper {
+ public:
+ explicit LineHelper(
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs)
+ : text_runs_(text_runs) {
+ StartNewLine(0);
+ }
+
+ void StartNewLine(size_t current_index) {
+ DCHECK(current_index == 0 || current_index < text_runs_.size());
+ start_index_ = current_index;
+ accumulated_weight_top_ = 0.0f;
+ accumulated_weight_bottom_ = 0.0f;
+ accumulated_width_ = 0.0f;
+ }
+
+ void ProcessNextRun(size_t run_index) {
+ DCHECK_LT(run_index, text_runs_.size());
+ RemoveOldRunsUpTo(run_index);
+ AddRun(text_runs_[run_index].bounds);
+ }
+
+ bool IsRunOnSameLine(size_t run_index) const {
+ DCHECK_LT(run_index, text_runs_.size());
+
+ // Calculate new top/bottom bounds for our line.
+ if (accumulated_width_ == 0.0f)
+ return false;
+
+ float line_top = accumulated_weight_top_ / accumulated_width_;
+ float line_bottom = accumulated_weight_bottom_ / accumulated_width_;
+
+ // Look at the next run, and determine how much it overlaps the line.
+ const auto& run_bounds = text_runs_[run_index].bounds;
+ if (run_bounds.size.height == 0.0f)
+ return false;
+
+ float clamped_top = std::max(line_top, run_bounds.point.y);
+ float clamped_bottom =
+ std::min(line_bottom, run_bounds.point.y + run_bounds.size.height);
+ if (clamped_bottom < clamped_top)
+ return false;
+
+ float coverage = (clamped_bottom - clamped_top) / (run_bounds.size.height);
+
+ // See if it falls within the line (within our threshold).
+ constexpr float kLineCoverageThreshold = 0.25f;
+ return coverage > kLineCoverageThreshold;
+ }
+
+ private:
+ void AddRun(const PP_FloatRect& run_bounds) {
+ float run_width = fabs(run_bounds.size.width);
+ accumulated_width_ += run_width;
+ accumulated_weight_top_ += run_bounds.point.y * run_width;
+ accumulated_weight_bottom_ +=
+ (run_bounds.point.y + run_bounds.size.height) * run_width;
+ }
+
+ void RemoveRun(const PP_FloatRect& run_bounds) {
+ float run_width = fabs(run_bounds.size.width);
+ accumulated_width_ -= run_width;
+ accumulated_weight_top_ -= run_bounds.point.y * run_width;
+ accumulated_weight_bottom_ -=
+ (run_bounds.point.y + run_bounds.size.height) * run_width;
+ }
+
+ void RemoveOldRunsUpTo(size_t stop_index) {
+ // Remove older runs from the weighted average if we've exceeded the
+ // threshold distance from them. We remove them to prevent e.g. drop-caps
+ // from unduly influencing future lines.
+ constexpr float kBoxRemoveWidthThreshold = 3.0f;
+ while (start_index_ < stop_index &&
+ accumulated_width_ > text_runs_[start_index_].bounds.size.width *
+ kBoxRemoveWidthThreshold) {
+ const auto& old_bounds = text_runs_[start_index_].bounds;
+ RemoveRun(old_bounds);
+ start_index_++;
+ }
+ }
+
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs_;
+ size_t start_index_;
+ float accumulated_weight_top_;
+ float accumulated_weight_bottom_;
+ float accumulated_width_;
+
+ DISALLOW_COPY_AND_ASSIGN(LineHelper);
+};
+
+void FinishStaticNode(ui::AXNodeData** static_text_node,
+ std::string* static_text,
+ ui::AXNodeData** previous_on_line_node) {
+ // If we're in the middle of building a static text node, finish it before
+ // moving on to the next object.
+ if (*static_text_node) {
+ (*static_text_node)
+ ->AddStringAttribute(ax::mojom::StringAttribute::kName, (*static_text));
+ static_text->clear();
+ }
+ *static_text_node = nullptr;
+ *previous_on_line_node = nullptr;
+}
+
+bool BreakParagraph(
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ uint32_t text_run_index,
+ double paragraph_spacing_threshold) {
+ // Check to see if its also a new paragraph, i.e., if the distance between
+ // lines is greater than the threshold. If there's no threshold, that
+ // means there weren't enough lines to compute an accurate median, so
+ // we compare against the line size instead.
+ double line_spacing = fabs(text_runs[text_run_index + 1].bounds.point.y -
+ text_runs[text_run_index].bounds.point.y);
+ return ((paragraph_spacing_threshold > 0 &&
+ line_spacing > paragraph_spacing_threshold) ||
+ (paragraph_spacing_threshold == 0 &&
+ line_spacing > kParagraphLineSpacingRatio *
+ text_runs[text_run_index].bounds.size.height));
+}
+
+ui::AXNode* GetStaticTextNodeFromNode(ui::AXNode* node) {
+ // Returns the appropriate static text node given |node|'s type.
+ // Returns nullptr if there is no appropriate static text node.
+ ui::AXNode* static_node = node;
+ // Get the static text from the link node.
+ if (node && node->data().role == ax::mojom::Role::kLink &&
+ node->children().size() == 1) {
+ static_node = node->children()[0];
+ }
+ // If it's static text node, then it holds text.
+ if (static_node && static_node->data().role == ax::mojom::Role::kStaticText)
+ return static_node;
+ return nullptr;
}
+template <typename T>
+bool CompareTextRuns(const T& a, const T& b) {
+ return a.text_run_index < b.text_run_index;
+}
+
+template <typename T>
+bool IsObjectInTextRun(const std::vector<T>& objects,
+ uint32_t object_index,
+ size_t text_run_index) {
+ return (object_index < objects.size() &&
+ objects[object_index].text_run_index <= text_run_index);
+}
+
+} // namespace
+
PdfAccessibilityTree::PdfAccessibilityTree(
content::RendererPpapiHost* host,
PP_Instance instance)
@@ -58,6 +214,47 @@ PdfAccessibilityTree::~PdfAccessibilityTree() {
render_accessibility->SetPluginTreeSource(nullptr);
}
+// static
+bool PdfAccessibilityTree::IsDataFromPluginValid(
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images) {
+ base::CheckedNumeric<uint32_t> char_length = 0;
+ for (const PP_PrivateAccessibilityTextRunInfo& text_run : text_runs)
+ char_length += text_run.len;
+ if (!char_length.IsValid() || char_length.ValueOrDie() != chars.size())
+ return false;
+
+ if (!std::is_sorted(links.begin(), links.end(),
+ CompareTextRuns<ppapi::PdfAccessibilityLinkInfo>)) {
+ return false;
+ }
+ // Text run index of a |link| is out of bounds if it exceeds the size of
+ // |text_runs|. The index denotes the position of the link relative to the
+ // text runs. The index value equal to the size of |text_runs| indicates that
+ // the link should be after the last text run.
+ for (const ppapi::PdfAccessibilityLinkInfo& link : links) {
+ base::CheckedNumeric<uint32_t> index = link.text_run_index;
+ index += link.text_run_count;
+ if (!index.IsValid() || index.ValueOrDie() > text_runs.size())
+ return false;
+ }
+
+ if (!std::is_sorted(images.begin(), images.end(),
+ CompareTextRuns<ppapi::PdfAccessibilityImageInfo>)) {
+ return false;
+ }
+ // Text run index of an |image| works on the same logic as the text run index
+ // of a |link| as mentioned above.
+ for (const ppapi::PdfAccessibilityImageInfo& image : images) {
+ if (image.text_run_index > text_runs.size())
+ return false;
+ }
+
+ return true;
+}
+
void PdfAccessibilityTree::SetAccessibilityViewportInfo(
const PP_PrivateAccessibilityViewportInfo& viewport_info) {
zoom_ = viewport_info.zoom;
@@ -90,7 +287,7 @@ void PdfAccessibilityTree::SetAccessibilityDocInfo(
return;
doc_info_ = doc_info;
- doc_node_ = CreateNode(ax::mojom::Role::kGroup);
+ doc_node_ = CreateNode(ax::mojom::Role::kDocument);
// Because all of the coordinates are expressed relative to the
// doc's coordinates, the origin of the doc must be (0, 0). Its
@@ -102,11 +299,22 @@ void PdfAccessibilityTree::SetAccessibilityDocInfo(
void PdfAccessibilityTree::SetAccessibilityPageInfo(
const PP_PrivateAccessibilityPageInfo& page_info,
const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
- const std::vector<PP_PrivateAccessibilityCharInfo>& chars) {
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images) {
content::RenderAccessibility* render_accessibility = GetRenderAccessibility();
if (!render_accessibility)
return;
+ // If unsanitized data is found, don't trust the PPAPI process sending it and
+ // stop creation of the accessibility tree.
+ if (!invalid_plugin_message_received_) {
+ invalid_plugin_message_received_ =
+ !IsDataFromPluginValid(text_runs, chars, links, images);
+ }
+ if (invalid_plugin_message_received_)
+ return;
+
uint32_t page_index = page_info.page_index;
CHECK_GE(page_index, 0U);
CHECK_LT(page_index, doc_info_.page_count);
@@ -115,93 +323,191 @@ void PdfAccessibilityTree::SetAccessibilityPageInfo(
page_node->AddStringAttribute(
ax::mojom::StringAttribute::kName,
l10n_util::GetPluralStringFUTF8(IDS_PDF_PAGE_INDEX, page_index + 1));
+ page_node->AddBoolAttribute(ax::mojom::BoolAttribute::kIsPageBreakingObject,
+ true);
gfx::RectF page_bounds = ToRectF(page_info.bounds);
page_node->relative_bounds.bounds = page_bounds;
doc_node_->relative_bounds.bounds.Union(page_node->relative_bounds.bounds);
doc_node_->child_ids.push_back(page_node->id);
+ AddPageContent(page_node, page_bounds, page_index, text_runs, chars, links,
+ images);
+
+ if (page_index == doc_info_.page_count - 1)
+ Finish();
+}
+
+void PdfAccessibilityTree::AddPageContent(
+ ui::AXNodeData* page_node,
+ const gfx::RectF& page_bounds,
+ uint32_t page_index,
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images) {
+ DCHECK(page_node);
double heading_font_size_threshold = 0;
- double line_spacing_threshold = 0;
- ComputeParagraphAndHeadingThresholds(text_runs,
- &heading_font_size_threshold,
- &line_spacing_threshold);
+ double paragraph_spacing_threshold = 0;
+ ComputeParagraphAndHeadingThresholds(text_runs, &heading_font_size_threshold,
+ &paragraph_spacing_threshold);
ui::AXNodeData* para_node = nullptr;
ui::AXNodeData* static_text_node = nullptr;
+ ui::AXNodeData* previous_on_line_node = nullptr;
std::string static_text;
uint32_t char_index = 0;
- for (size_t i = 0; i < text_runs.size(); ++i) {
- // Get the text of the next text run
- const auto& text_run = text_runs[i];
- std::string chars_utf8 = GetTextRunCharsAsUTF8(text_run, chars, char_index);
- std::vector<int32_t> char_offsets = GetTextRunCharOffsets(
- text_run, chars, char_index);
- static_text += chars_utf8;
- uint32_t initial_char_index = char_index;
- char_index += text_run.len;
+ uint32_t current_link_index = 0;
+ uint32_t current_image_index = 0;
+ bool is_run_on_same_line = false;
+ LineHelper line_helper(text_runs);
+ for (size_t text_run_index = 0; text_run_index < text_runs.size();
+ ++text_run_index) {
// If we don't have a paragraph, create one.
if (!para_node) {
- para_node = CreateNode(ax::mojom::Role::kParagraph);
+ para_node = CreateParagraphNode(text_runs[text_run_index].font_size,
+ heading_font_size_threshold);
page_node->child_ids.push_back(para_node->id);
+ }
- if (heading_font_size_threshold > 0 &&
- text_run.font_size > heading_font_size_threshold) {
- para_node->role = ax::mojom::Role::kHeading;
- para_node->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel,
- 2);
- para_node->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag,
- "h2");
+ // If the |text_run_index| is less than or equal to the link's
+ // text_run_index, then push the link node in the paragraph.
+ if (IsObjectInTextRun(links, current_link_index, text_run_index)) {
+ FinishStaticNode(&static_text_node, &static_text, &previous_on_line_node);
+ is_run_on_same_line = false;
+ const ppapi::PdfAccessibilityLinkInfo& link = links[current_link_index++];
+ ui::AXNodeData* link_node = CreateLinkNode(link, page_bounds);
+ para_node->child_ids.push_back(link_node->id);
+
+ // If |link.text_run_count| == 0, then the link is not part of the page
+ // text. Push it ahead of the current text run.
+ if (link.text_run_count == 0) {
+ --text_run_index;
+ continue;
}
-
+ // If |link.text_run_count| > 0, then the link is part of the page text.
+ // Make the text runs contained by the link children of the link node.
+ uint32_t link_end_text_run_index =
+ std::min(text_run_index + link.text_run_count, text_runs.size()) - 1;
+
+ AddTextToLinkNode(text_run_index, link_end_text_run_index, text_runs,
+ chars, page_bounds, &char_index, link_node);
+
+ para_node->relative_bounds.bounds.Union(
+ link_node->relative_bounds.bounds);
+
+ text_run_index = link_end_text_run_index;
+ } else if (IsObjectInTextRun(images, current_image_index, text_run_index)) {
+ FinishStaticNode(&static_text_node, &static_text, &previous_on_line_node);
+ is_run_on_same_line = false;
+ // If the |text_run_index| is less than or equal to the image's text run
+ // index, then push the image ahead of the current text run.
+ ui::AXNodeData* image_node =
+ CreateImageNode(images[current_image_index], page_bounds);
+ para_node->child_ids.push_back(image_node->id);
+ ++current_image_index;
+ --text_run_index;
+ continue;
+ } else {
// This node is for the text inside the paragraph, it includes
// the text of all of the text runs.
- static_text_node = CreateNode(ax::mojom::Role::kStaticText);
- para_node->child_ids.push_back(static_text_node->id);
- node_id_to_char_index_in_page_[static_text_node->id] = initial_char_index;
- }
+ if (!static_text_node) {
+ static_text_node = CreateStaticTextNode(char_index);
+ para_node->child_ids.push_back(static_text_node->id);
+ }
- // Add this text run to the current static text node.
- ui::AXNodeData* inline_text_box_node =
- CreateNode(ax::mojom::Role::kInlineTextBox);
- static_text_node->child_ids.push_back(inline_text_box_node->id);
-
- inline_text_box_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
- chars_utf8);
- gfx::RectF text_run_bounds = ToGfxRectF(text_run.bounds);
- text_run_bounds += page_bounds.OffsetFromOrigin();
- inline_text_box_node->relative_bounds.bounds = text_run_bounds;
- inline_text_box_node->AddIntListAttribute(
- ax::mojom::IntListAttribute::kCharacterOffsets, char_offsets);
- AddWordStartsAndEnds(inline_text_box_node);
-
- para_node->relative_bounds.bounds.Union(
- inline_text_box_node->relative_bounds.bounds);
- static_text_node->relative_bounds.bounds.Union(
- inline_text_box_node->relative_bounds.bounds);
+ const PP_PrivateAccessibilityTextRunInfo& text_run =
+ text_runs[text_run_index];
+ // Add this text run to the current static text node.
+ ui::AXNodeData* inline_text_box_node =
+ CreateInlineTextBoxNode(text_run, chars, char_index, page_bounds);
+ static_text_node->child_ids.push_back(inline_text_box_node->id);
+
+ static_text += inline_text_box_node->GetStringAttribute(
+ ax::mojom::StringAttribute::kName);
+ char_index += text_run.len;
+
+ para_node->relative_bounds.bounds.Union(
+ inline_text_box_node->relative_bounds.bounds);
+ static_text_node->relative_bounds.bounds.Union(
+ inline_text_box_node->relative_bounds.bounds);
+
+ if (previous_on_line_node) {
+ previous_on_line_node->AddIntAttribute(
+ ax::mojom::IntAttribute::kNextOnLineId, inline_text_box_node->id);
+ inline_text_box_node->AddIntAttribute(
+ ax::mojom::IntAttribute::kPreviousOnLineId,
+ previous_on_line_node->id);
+ }
- if (i == text_runs.size() - 1) {
- static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
- static_text);
+ if (!previous_on_line_node)
+ line_helper.StartNewLine(text_run_index);
+ line_helper.ProcessNextRun(text_run_index);
+
+ if (text_run_index < text_runs.size() - 1)
+ is_run_on_same_line = line_helper.IsRunOnSameLine(text_run_index + 1);
+ if (is_run_on_same_line) {
+ // The next run is on the same line.
+ previous_on_line_node = inline_text_box_node;
+ }
+ }
+
+ if (text_run_index == text_runs.size() - 1) {
+ if (static_text_node) {
+ static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ static_text);
+ }
break;
}
- double line_spacing =
- text_runs[i + 1].bounds.point.y - text_run.bounds.point.y;
- if (text_run.font_size != text_runs[i + 1].font_size ||
- (line_spacing_threshold > 0 &&
- line_spacing > line_spacing_threshold)) {
- static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
- static_text);
- para_node = nullptr;
- static_text_node = nullptr;
- static_text.clear();
+ if (!is_run_on_same_line) {
+ // The next run is on a new line.
+ previous_on_line_node = nullptr;
+
+ if (BreakParagraph(text_runs, text_run_index,
+ paragraph_spacing_threshold)) {
+ if (static_text_node) {
+ static_text_node->AddStringAttribute(
+ ax::mojom::StringAttribute::kName, static_text);
+ }
+ para_node = nullptr;
+ static_text_node = nullptr;
+ static_text.clear();
+ }
}
}
- if (page_index == doc_info_.page_count - 1)
- Finish();
+ base::span<const ppapi::PdfAccessibilityLinkInfo> remaining_links =
+ base::make_span(links).subspan(current_link_index);
+ base::span<const ppapi::PdfAccessibilityImageInfo> remaining_images =
+ base::make_span(images).subspan(current_image_index);
+ AddRemainingAnnotations(page_node, page_bounds, remaining_links,
+ remaining_images, para_node);
+}
+
+void PdfAccessibilityTree::AddRemainingAnnotations(
+ ui::AXNodeData* page_node,
+ const gfx::RectF& page_bounds,
+ base::span<const ppapi::PdfAccessibilityLinkInfo> links,
+ base::span<const ppapi::PdfAccessibilityImageInfo> images,
+ ui::AXNodeData* para_node) {
+ // If we have additional links or images to insert in the tree, and we don't
+ // have a paragraph node, create a new one.
+ if (!para_node && (!links.empty() || !images.empty())) {
+ para_node = CreateNode(ax::mojom::Role::kParagraph);
+ page_node->child_ids.push_back(para_node->id);
+ }
+ // Push all the links not anchored to any text run to the last paragraph.
+ for (const ppapi::PdfAccessibilityLinkInfo& link : links) {
+ ui::AXNodeData* link_node = CreateLinkNode(link, page_bounds);
+ para_node->child_ids.push_back(link_node->id);
+ }
+ // Push all the images not anchored to any text run to the last paragraph.
+ for (const ppapi::PdfAccessibilityImageInfo& image : images) {
+ ui::AXNodeData* image_node = CreateImageNode(image, page_bounds);
+ para_node->child_ids.push_back(image_node->id);
+ }
}
void PdfAccessibilityTree::Finish() {
@@ -253,8 +559,11 @@ void PdfAccessibilityTree::FindNodeOffset(uint32_t page_index,
// Iterate over all paragraphs within this given page, and static text nodes
// within each paragraph.
for (ui::AXNode* para : page->children()) {
- for (ui::AXNode* static_text : para->children()) {
- // Look up the page-relative character index for this node from a map
+ for (ui::AXNode* child_node : para->children()) {
+ ui::AXNode* static_text = GetStaticTextNodeFromNode(child_node);
+ if (!static_text)
+ continue;
+ // Look up the page-relative character index for static nodes from a map
// we built while the document was initially built.
DCHECK(base::Contains(node_id_to_char_index_in_page_, static_text->id()));
uint32_t char_index = node_id_to_char_index_in_page_[static_text->id()];
@@ -276,7 +585,7 @@ void PdfAccessibilityTree::FindNodeOffset(uint32_t page_index,
void PdfAccessibilityTree::ComputeParagraphAndHeadingThresholds(
const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
double* out_heading_font_size_threshold,
- double* out_line_spacing_threshold) {
+ double* out_paragraph_spacing_threshold) {
// Scan over the font sizes and line spacing within this page and
// set heuristic thresholds so that text larger than the median font
// size can be marked as a heading, and spacing larger than the median
@@ -304,7 +613,7 @@ void PdfAccessibilityTree::ComputeParagraphAndHeadingThresholds(
std::sort(line_spacings.begin(), line_spacings.end());
double median_line_spacing = line_spacings[line_spacings.size() / 2];
if (median_line_spacing > kMinimumLineSpacing) {
- *out_line_spacing_threshold =
+ *out_paragraph_spacing_threshold =
median_line_spacing * kParagraphLineSpacingRatio;
}
}
@@ -362,6 +671,132 @@ ui::AXNodeData* PdfAccessibilityTree::CreateNode(ax::mojom::Role role) {
return node;
}
+ui::AXNodeData* PdfAccessibilityTree::CreateParagraphNode(
+ double font_size,
+ double heading_font_size_threshold) {
+ ui::AXNodeData* para_node = CreateNode(ax::mojom::Role::kParagraph);
+
+ // If font size exceeds the |heading_font_size_threshold|, then classify
+ // it as a Heading.
+ if (heading_font_size_threshold > 0 &&
+ font_size > heading_font_size_threshold) {
+ para_node->role = ax::mojom::Role::kHeading;
+ para_node->AddIntAttribute(ax::mojom::IntAttribute::kHierarchicalLevel, 2);
+ para_node->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, "h2");
+ }
+
+ return para_node;
+}
+
+ui::AXNodeData* PdfAccessibilityTree::CreateStaticTextNode(
+ uint32_t char_index) {
+ ui::AXNodeData* static_text_node = CreateNode(ax::mojom::Role::kStaticText);
+ node_id_to_char_index_in_page_[static_text_node->id] = char_index;
+ return static_text_node;
+}
+
+ui::AXNodeData* PdfAccessibilityTree::CreateInlineTextBoxNode(
+ const PP_PrivateAccessibilityTextRunInfo& text_run,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ uint32_t char_index,
+ const gfx::RectF& page_bounds) {
+ ui::AXNodeData* inline_text_box_node =
+ CreateNode(ax::mojom::Role::kInlineTextBox);
+
+ std::string chars_utf8 = GetTextRunCharsAsUTF8(text_run, chars, char_index);
+ inline_text_box_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ chars_utf8);
+ inline_text_box_node->AddIntAttribute(ax::mojom::IntAttribute::kTextDirection,
+ text_run.direction);
+ inline_text_box_node->relative_bounds.bounds =
+ ToGfxRectF(text_run.bounds) + page_bounds.OffsetFromOrigin();
+ std::vector<int32_t> char_offsets =
+ GetTextRunCharOffsets(text_run, chars, char_index);
+ inline_text_box_node->AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, char_offsets);
+ AddWordStartsAndEnds(inline_text_box_node);
+ return inline_text_box_node;
+}
+
+ui::AXNodeData* PdfAccessibilityTree::CreateLinkNode(
+ const ppapi::PdfAccessibilityLinkInfo& link,
+ const gfx::RectF& page_bounds) {
+ ui::AXNodeData* link_node = CreateNode(ax::mojom::Role::kLink);
+
+ link_node->AddStringAttribute(ax::mojom::StringAttribute::kUrl, link.url);
+ link_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ std::string());
+ link_node->relative_bounds.bounds =
+ ToGfxRectF(link.bounds) + page_bounds.OffsetFromOrigin();
+ return link_node;
+}
+
+ui::AXNodeData* PdfAccessibilityTree::CreateImageNode(
+ const ppapi::PdfAccessibilityImageInfo& image,
+ const gfx::RectF& page_bounds) {
+ ui::AXNodeData* image_node = CreateNode(ax::mojom::Role::kImage);
+
+ image_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ image.alt_text);
+ image_node->relative_bounds.bounds =
+ ToGfxRectF(image.bounds) + page_bounds.OffsetFromOrigin();
+ return image_node;
+}
+
+void PdfAccessibilityTree::AddTextToLinkNode(
+ uint32_t start_text_run_index,
+ uint32_t end_text_run_index,
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const gfx::RectF& page_bounds,
+ uint32_t* char_index,
+ ui::AXNodeData* link_node) {
+ ui::AXNodeData* link_static_text_node = CreateStaticTextNode(*char_index);
+ link_node->child_ids.push_back(link_static_text_node->id);
+ // Accumulate the text of the link.
+ std::string link_name;
+ ui::AXNodeData* previous_on_line_node = nullptr;
+ LineHelper line_helper(text_runs);
+
+ for (size_t text_run_index = start_text_run_index;
+ text_run_index <= end_text_run_index; ++text_run_index) {
+ const PP_PrivateAccessibilityTextRunInfo& text_run =
+ text_runs[text_run_index];
+ // Add this text run to the current static text node.
+ ui::AXNodeData* inline_text_box_node =
+ CreateInlineTextBoxNode(text_run, chars, *char_index, page_bounds);
+ link_static_text_node->child_ids.push_back(inline_text_box_node->id);
+
+ link_static_text_node->relative_bounds.bounds.Union(
+ inline_text_box_node->relative_bounds.bounds);
+ link_name += inline_text_box_node->GetStringAttribute(
+ ax::mojom::StringAttribute::kName);
+
+ *char_index += text_run.len;
+
+ if (previous_on_line_node) {
+ previous_on_line_node->AddIntAttribute(
+ ax::mojom::IntAttribute::kNextOnLineId, inline_text_box_node->id);
+ inline_text_box_node->AddIntAttribute(
+ ax::mojom::IntAttribute::kPreviousOnLineId,
+ previous_on_line_node->id);
+ }
+ if (!previous_on_line_node)
+ line_helper.StartNewLine(text_run_index);
+ line_helper.ProcessNextRun(text_run_index);
+
+ if (text_run_index < text_runs.size() - 1 &&
+ line_helper.IsRunOnSameLine(text_run_index + 1)) {
+ // The next run is on the same line.
+ previous_on_line_node = inline_text_box_node;
+ }
+ }
+
+ link_node->AddStringAttribute(ax::mojom::StringAttribute::kName, link_name);
+ link_static_text_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
+ link_name);
+}
+
float PdfAccessibilityTree::GetDeviceScaleFactor() const {
content::RenderFrame* render_frame =
host_->GetRenderFrameForInstance(instance_);
@@ -456,7 +891,7 @@ ui::AXNode* PdfAccessibilityTree::GetParent(const ui::AXNode* node) const {
}
bool PdfAccessibilityTree::IsIgnored(const ui::AXNode* node) const {
- return node->data().HasState(ax::mojom::State::kIgnored);
+ return node->IsIgnored();
}
bool PdfAccessibilityTree::IsValid(const ui::AXNode* node) const {
@@ -477,4 +912,18 @@ void PdfAccessibilityTree::SerializeNode(
*out_data = node->data();
}
+std::unique_ptr<ui::AXActionTarget> PdfAccessibilityTree::CreateActionTarget(
+ const ui::AXNode& target_node) {
+ return std::make_unique<pdf::PdfAXActionTarget>(target_node, this);
+}
+
+void PdfAccessibilityTree::HandleAction(
+ const PP_PdfAccessibilityActionData& action_data) {
+ content::PepperPluginInstance* plugin_instance =
+ host_->GetPluginInstance(instance_);
+ if (plugin_instance) {
+ plugin_instance->HandleAccessibilityAction(action_data);
+ }
+}
+
} // namespace pdf
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree.h b/chromium/components/pdf/renderer/pdf_accessibility_tree.h
index 4c468e68867..c91d16b2794 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree.h
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree.h
@@ -8,8 +8,11 @@
#include <memory>
#include <vector>
+#include "content/public/renderer/plugin_ax_tree_source.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/private/ppb_pdf.h"
+#include "ppapi/c/private/ppp_pdf.h"
+#include "ppapi/shared_impl/pdf_accessibility_shared.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_source.h"
@@ -27,15 +30,18 @@ class Transform;
namespace pdf {
-class PdfAccessibilityTree
- : public ui::AXTreeSource<const ui::AXNode*,
- ui::AXNodeData,
- ui::AXTreeData> {
+class PdfAccessibilityTree : public content::PluginAXTreeSource {
public:
PdfAccessibilityTree(content::RendererPpapiHost* host,
PP_Instance instance);
~PdfAccessibilityTree() override;
+ static bool IsDataFromPluginValid(
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images);
+
void SetAccessibilityViewportInfo(
const PP_PrivateAccessibilityViewportInfo& viewport_info);
void SetAccessibilityDocInfo(
@@ -43,9 +49,12 @@ class PdfAccessibilityTree
void SetAccessibilityPageInfo(
const PP_PrivateAccessibilityPageInfo& page_info,
const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
- const std::vector<PP_PrivateAccessibilityCharInfo>& chars);
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images);
+ void HandleAction(const PP_PdfAccessibilityActionData& action_data);
- // AXTreeSource implementation.
+ // PluginAXTreeSource implementation.
bool GetTreeData(ui::AXTreeData* tree_data) const override;
ui::AXNode* GetRoot() const override;
ui::AXNode* GetFromId(int32_t id) const override;
@@ -59,6 +68,8 @@ class PdfAccessibilityTree
const ui::AXNode* GetNull() const override;
void SerializeNode(const ui::AXNode* node, ui::AXNodeData* out_data)
const override;
+ std::unique_ptr<ui::AXActionTarget> CreateActionTarget(
+ const ui::AXNode& target_node) override;
private:
// Update the AXTreeData when the selected range changed.
@@ -78,10 +89,25 @@ class PdfAccessibilityTree
// onto the host tree.
void Finish();
+ void AddPageContent(
+ ui::AXNodeData* page_node,
+ const gfx::RectF& page_bounds,
+ uint32_t page_index,
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images);
+ void AddRemainingAnnotations(
+ ui::AXNodeData* page_node,
+ const gfx::RectF& page_bounds,
+ base::span<const ppapi::PdfAccessibilityLinkInfo> links,
+ base::span<const ppapi::PdfAccessibilityImageInfo> images,
+ ui::AXNodeData* para_node);
+
void ComputeParagraphAndHeadingThresholds(
const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
double* out_heading_font_size_threshold,
- double* out_line_spacing_threshold);
+ double* out_paragraph_spacing_threshold);
std::string GetTextRunCharsAsUTF8(
const PP_PrivateAccessibilityTextRunInfo& text_run,
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
@@ -93,6 +119,26 @@ class PdfAccessibilityTree
gfx::Vector2dF ToVector2dF(const PP_Point& p);
gfx::RectF ToRectF(const PP_Rect& r);
ui::AXNodeData* CreateNode(ax::mojom::Role role);
+ ui::AXNodeData* CreateParagraphNode(double font_size,
+ double heading_font_size_threshold);
+ ui::AXNodeData* CreateStaticTextNode(uint32_t char_index);
+ ui::AXNodeData* CreateInlineTextBoxNode(
+ const PP_PrivateAccessibilityTextRunInfo& text_run,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ uint32_t char_index,
+ const gfx::RectF& page_bounds);
+ ui::AXNodeData* CreateLinkNode(const ppapi::PdfAccessibilityLinkInfo& link,
+ const gfx::RectF& page_bounds);
+ ui::AXNodeData* CreateImageNode(const ppapi::PdfAccessibilityImageInfo& image,
+ const gfx::RectF& page_bounds);
+ void AddTextToLinkNode(
+ uint32_t start_text_run_index,
+ uint32_t end_text_run_index,
+ const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const gfx::RectF& page_bounds,
+ uint32_t* char_index,
+ ui::AXNodeData* link_node);
float GetDeviceScaleFactor() const;
content::RenderAccessibility* GetRenderAccessibility();
gfx::Transform* MakeTransformFromViewInfo();
@@ -116,6 +162,7 @@ class PdfAccessibilityTree
// character within its page. Used to find the node associated with
// the start or end of a selection.
std::map<int32_t, uint32_t> node_id_to_char_index_in_page_;
+ bool invalid_plugin_message_received_ = false;
};
} // namespace pdf;
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc b/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
index e2629626f74..496132a5148 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
@@ -10,6 +10,7 @@
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/public/test/fake_pepper_plugin_instance.h"
#include "content/public/test/render_view_test.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_settings.h"
@@ -19,17 +20,71 @@
namespace pdf {
namespace {
+const PP_PrivateAccessibilityTextRunInfo kFirstTextRun = {
+ 15, 12, PP_MakeFloatRectFromXYWH(26.0f, 189.0f, 84.0f, 13.0f)};
+const PP_PrivateAccessibilityTextRunInfo kSecondTextRun = {
+ 15, 16, PP_MakeFloatRectFromXYWH(28.0f, 117.0f, 152.0f, 19.0f)};
+const PP_PrivateAccessibilityCharInfo kDummyCharsData[] = {
+ {'H', 12}, {'e', 6}, {'l', 5}, {'l', 4}, {'o', 8}, {',', 4},
+ {' ', 4}, {'w', 12}, {'o', 6}, {'r', 6}, {'l', 4}, {'d', 9},
+ {'!', 4}, {' ', 0}, {' ', 0}, {'G', 16}, {'o', 12}, {'o', 12},
+ {'d', 12}, {'b', 10}, {'y', 12}, {'e', 12}, {',', 4}, {' ', 6},
+ {'w', 16}, {'o', 12}, {'r', 8}, {'l', 4}, {'d', 12}, {'!', 2},
+};
+const PP_PrivateAccessibilityTextRunInfo kFirstRunMultiLine = {
+ 7, 12, PP_MakeFloatRectFromXYWH(26.0f, 189.0f, 84.0f, 13.0f)};
+const PP_PrivateAccessibilityTextRunInfo kSecondRunMultiLine = {
+ 8, 12, PP_MakeFloatRectFromXYWH(26.0f, 189.0f, 84.0f, 13.0f)};
+const PP_PrivateAccessibilityTextRunInfo kThirdRunMultiLine = {
+ 9, 12, PP_MakeFloatRectFromXYWH(26.0f, 189.0f, 84.0f, 13.0f)};
+const PP_PrivateAccessibilityTextRunInfo kFourthRunMultiLine = {
+ 6, 12, PP_MakeFloatRectFromXYWH(26.0f, 189.0f, 84.0f, 13.0f)};
+
+void CompareRect(PP_Rect expected_rect, PP_Rect actual_rect) {
+ EXPECT_EQ(expected_rect.point.x, actual_rect.point.x);
+ EXPECT_EQ(expected_rect.point.y, actual_rect.point.y);
+ EXPECT_EQ(expected_rect.size.height, actual_rect.size.height);
+ EXPECT_EQ(expected_rect.size.width, actual_rect.size.width);
+}
+
+// This class overrides content::FakePepperPluginInstance to record received
+// action data when tests make an accessibility action call.
+class ActionHandlingFakePepperPluginInstance
+ : public content::FakePepperPluginInstance {
+ public:
+ ActionHandlingFakePepperPluginInstance() = default;
+ ~ActionHandlingFakePepperPluginInstance() override = default;
+
+ // content::FakePepperPluginInstance:
+ void HandleAccessibilityAction(
+ const PP_PdfAccessibilityActionData& action_data) override {
+ received_action_data_ = action_data;
+ }
+
+ PP_PdfAccessibilityActionData GetReceivedActionData() {
+ return received_action_data_;
+ }
+
+ private:
+ PP_PdfAccessibilityActionData received_action_data_;
+};
+
class FakeRendererPpapiHost : public content::RendererPpapiHost {
public:
explicit FakeRendererPpapiHost(content::RenderFrame* render_frame)
- : render_frame_(render_frame) {}
- ~FakeRendererPpapiHost() override {}
+ : FakeRendererPpapiHost(render_frame, nullptr) {}
+ FakeRendererPpapiHost(
+ content::RenderFrame* render_frame,
+ ActionHandlingFakePepperPluginInstance* fake_pepper_plugin_instance)
+ : render_frame_(render_frame),
+ fake_pepper_plugin_instance_(fake_pepper_plugin_instance) {}
+ ~FakeRendererPpapiHost() override = default;
ppapi::host::PpapiHost* GetPpapiHost() override { return nullptr; }
bool IsValidInstance(PP_Instance instance) override { return true; }
content::PepperPluginInstance* GetPluginInstance(
PP_Instance instance) override {
- return nullptr;
+ return fake_pepper_plugin_instance_;
}
content::RenderFrame* GetRenderFrameForInstance(
PP_Instance instance) override {
@@ -76,6 +131,7 @@ class FakeRendererPpapiHost : public content::RendererPpapiHost {
private:
content::RenderFrame* render_frame_;
+ ActionHandlingFakePepperPluginInstance* fake_pepper_plugin_instance_;
};
} // namespace
@@ -83,7 +139,7 @@ class FakeRendererPpapiHost : public content::RendererPpapiHost {
class PdfAccessibilityTreeTest : public content::RenderViewTest {
public:
PdfAccessibilityTreeTest() {}
- ~PdfAccessibilityTreeTest() override {}
+ ~PdfAccessibilityTreeTest() override = default;
void SetUp() override {
content::RenderViewTest::SetUp();
@@ -106,6 +162,8 @@ class PdfAccessibilityTreeTest : public content::RenderViewTest {
page_info_.page_index = 0;
page_info_.text_run_count = 0;
page_info_.char_count = 0;
+ page_info_.link_count = 0;
+ page_info_.image_count = 0;
page_info_.bounds = PP_MakeRectFromXYWH(0, 0, 1, 1);
}
@@ -115,6 +173,8 @@ class PdfAccessibilityTreeTest : public content::RenderViewTest {
PP_PrivateAccessibilityPageInfo page_info_;
std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs_;
std::vector<PP_PrivateAccessibilityCharInfo> chars_;
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links_;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images_;
};
TEST_F(PdfAccessibilityTreeTest, TestEmptyPDFPage) {
@@ -129,16 +189,16 @@ TEST_F(PdfAccessibilityTreeTest, TestEmptyPDFPage) {
pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
- chars_);
+ chars_, links_, images_);
- EXPECT_EQ(ax::mojom::Role::kGroup,
+ EXPECT_EQ(ax::mojom::Role::kDocument,
pdf_accessibility_tree.GetRoot()->data().role);
}
TEST_F(PdfAccessibilityTreeTest, TestAccessibilityDisabledDuringPDFLoad) {
content::RenderFrame* render_frame = view_->GetMainRenderFrame();
render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
- ASSERT_TRUE(render_frame->GetRenderAccessibility() != nullptr);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
FakeRendererPpapiHost host(view_->GetMainRenderFrame());
PP_Instance instance = 0;
@@ -152,7 +212,501 @@ TEST_F(PdfAccessibilityTreeTest, TestAccessibilityDisabledDuringPDFLoad) {
render_frame->SetAccessibilityModeForTest(ui::AXMode());
pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
- chars_);
+ chars_, links_, images_);
+}
+
+TEST_F(PdfAccessibilityTreeTest, TestPdfAccessibilityTreeCreation) {
+ text_runs_.emplace_back(kFirstTextRun);
+ text_runs_.emplace_back(kSecondTextRun);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ ppapi::PdfAccessibilityLinkInfo link;
+ link.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ link.url = "www.cs.chromium.org";
+ link.text_run_index = 0;
+ link.text_run_count = 1;
+ links_.push_back(link);
+
+ ppapi::PdfAccessibilityImageInfo image;
+ image.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ image.alt_text = "Alternate text for image";
+ image.text_run_index = 2;
+ images_.push_back(image);
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+ page_info_.link_count = links_.size();
+ page_info_.image_count = images_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+
+ /*
+ * Expected tree structure
+ * Document
+ * ++ Region
+ * ++++ Paragraph
+ * ++++++ Link
+ * ++++ Paragraph
+ * ++++++ Static Text
+ * ++++++ Image
+ */
+
+ ui::AXNode* root_node = pdf_accessibility_tree.GetRoot();
+ ASSERT_TRUE(root_node);
+ EXPECT_EQ(ax::mojom::Role::kDocument, root_node->data().role);
+ ASSERT_EQ(1u, root_node->children().size());
+
+ ui::AXNode* page_node = root_node->children()[0];
+ ASSERT_TRUE(page_node);
+ EXPECT_EQ(ax::mojom::Role::kRegion, page_node->data().role);
+ ASSERT_EQ(2u, page_node->children().size());
+
+ ui::AXNode* paragraph_node = page_node->children()[0];
+ ASSERT_TRUE(paragraph_node);
+ EXPECT_EQ(ax::mojom::Role::kParagraph, paragraph_node->data().role);
+ ASSERT_EQ(1u, paragraph_node->children().size());
+
+ ui::AXNode* link_node = paragraph_node->children()[0];
+ ASSERT_TRUE(link_node);
+ EXPECT_EQ(link.url,
+ link_node->GetStringAttribute(ax::mojom::StringAttribute::kUrl));
+ EXPECT_EQ(ax::mojom::Role::kLink, link_node->data().role);
+ ASSERT_EQ(1u, link_node->children().size());
+
+ paragraph_node = page_node->children()[1];
+ ASSERT_TRUE(paragraph_node);
+ EXPECT_EQ(ax::mojom::Role::kParagraph, paragraph_node->data().role);
+ ASSERT_EQ(2u, paragraph_node->children().size());
+
+ ui::AXNode* static_text_node = paragraph_node->children()[0];
+ ASSERT_TRUE(static_text_node);
+ EXPECT_EQ(ax::mojom::Role::kStaticText, static_text_node->data().role);
+ ASSERT_EQ(1u, static_text_node->children().size());
+
+ ui::AXNode* image_node = paragraph_node->children()[1];
+ ASSERT_TRUE(image_node);
+ EXPECT_EQ(ax::mojom::Role::kImage, image_node->data().role);
+ EXPECT_EQ(image.alt_text,
+ image_node->GetStringAttribute(ax::mojom::StringAttribute::kName));
+}
+
+TEST_F(PdfAccessibilityTreeTest, TestPreviousNextOnLine) {
+ text_runs_.emplace_back(kFirstRunMultiLine);
+ text_runs_.emplace_back(kSecondRunMultiLine);
+ text_runs_.emplace_back(kThirdRunMultiLine);
+ text_runs_.emplace_back(kFourthRunMultiLine);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ ppapi::PdfAccessibilityLinkInfo link;
+ link.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ link.url = "www.cs.chromium.org";
+ link.text_run_index = 2;
+ link.text_run_count = 2;
+ links_.push_back(link);
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+ page_info_.link_count = links_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+
+ /*
+ * Expected tree structure
+ * Document
+ * ++ Region
+ * ++++ Paragraph
+ * ++++++ Static Text
+ * ++++++++ Inline Text Box
+ * ++++++++ Inline Text Box
+ * ++++++ Link
+ * ++++++++ Static Text
+ * ++++++++++ Inline Text Box
+ * ++++++++++ Inline Text Box
+ */
+
+ ui::AXNode* root_node = pdf_accessibility_tree.GetRoot();
+ ASSERT_TRUE(root_node);
+ EXPECT_EQ(ax::mojom::Role::kDocument, root_node->data().role);
+ ASSERT_EQ(1u, root_node->children().size());
+
+ ui::AXNode* page_node = root_node->children()[0];
+ ASSERT_TRUE(page_node);
+ EXPECT_EQ(ax::mojom::Role::kRegion, page_node->data().role);
+ ASSERT_EQ(1u, page_node->children().size());
+
+ ui::AXNode* paragraph_node = page_node->children()[0];
+ ASSERT_TRUE(paragraph_node);
+ EXPECT_EQ(ax::mojom::Role::kParagraph, paragraph_node->data().role);
+ ASSERT_EQ(2u, paragraph_node->children().size());
+
+ ui::AXNode* static_text_node = paragraph_node->children()[0];
+ ASSERT_TRUE(static_text_node);
+ EXPECT_EQ(ax::mojom::Role::kStaticText, static_text_node->data().role);
+ ASSERT_EQ(2u, static_text_node->children().size());
+
+ ui::AXNode* previous_inline_node = static_text_node->children()[0];
+ ASSERT_TRUE(previous_inline_node);
+ EXPECT_EQ(ax::mojom::Role::kInlineTextBox, previous_inline_node->data().role);
+
+ ui::AXNode* next_inline_node = static_text_node->children()[1];
+ ASSERT_TRUE(next_inline_node);
+ EXPECT_EQ(ax::mojom::Role::kInlineTextBox, next_inline_node->data().role);
+
+ ASSERT_EQ(next_inline_node->data().id,
+ previous_inline_node->GetIntAttribute(
+ ax::mojom::IntAttribute::kNextOnLineId));
+ ASSERT_EQ(previous_inline_node->data().id,
+ next_inline_node->GetIntAttribute(
+ ax::mojom::IntAttribute::kPreviousOnLineId));
+ ASSERT_FALSE(next_inline_node->HasIntAttribute(
+ ax::mojom::IntAttribute::kNextOnLineId));
+ ASSERT_FALSE(previous_inline_node->HasIntAttribute(
+ ax::mojom::IntAttribute::kPreviousOnLineId));
+
+ ui::AXNode* link_node = paragraph_node->children()[1];
+ ASSERT_TRUE(link_node);
+ EXPECT_EQ(link.url,
+ link_node->GetStringAttribute(ax::mojom::StringAttribute::kUrl));
+ EXPECT_EQ(ax::mojom::Role::kLink, link_node->data().role);
+ ASSERT_EQ(1u, link_node->children().size());
+
+ static_text_node = link_node->children()[0];
+ ASSERT_TRUE(static_text_node);
+ EXPECT_EQ(ax::mojom::Role::kStaticText, static_text_node->data().role);
+ ASSERT_EQ(2u, static_text_node->children().size());
+
+ previous_inline_node = static_text_node->children()[0];
+ ASSERT_TRUE(previous_inline_node);
+ EXPECT_EQ(ax::mojom::Role::kInlineTextBox, previous_inline_node->data().role);
+
+ next_inline_node = static_text_node->children()[1];
+ ASSERT_TRUE(next_inline_node);
+ EXPECT_EQ(ax::mojom::Role::kInlineTextBox, next_inline_node->data().role);
+
+ ASSERT_EQ(next_inline_node->data().id,
+ previous_inline_node->GetIntAttribute(
+ ax::mojom::IntAttribute::kNextOnLineId));
+ ASSERT_EQ(previous_inline_node->data().id,
+ next_inline_node->GetIntAttribute(
+ ax::mojom::IntAttribute::kPreviousOnLineId));
+ ASSERT_FALSE(next_inline_node->HasIntAttribute(
+ ax::mojom::IntAttribute::kNextOnLineId));
+ ASSERT_FALSE(previous_inline_node->HasIntAttribute(
+ ax::mojom::IntAttribute::kPreviousOnLineId));
+}
+
+TEST_F(PdfAccessibilityTreeTest, TextRunsAndCharsMismatch) {
+ // |chars_| and |text_runs_| span over the same page text. They should denote
+ // the same page text size, but |text_runs_| is incorrect and only denotes 1
+ // of 2 text runs.
+ text_runs_.emplace_back(kFirstTextRun);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+ // In case of invalid data, only the initialized data should be in the tree.
+ ASSERT_EQ(ax::mojom::Role::kUnknown,
+ pdf_accessibility_tree.GetRoot()->data().role);
+ ASSERT_EQ(0u, pdf_accessibility_tree.GetRoot()->children().size());
+}
+
+TEST_F(PdfAccessibilityTreeTest, UnsortedLinkVector) {
+ text_runs_.emplace_back(kFirstTextRun);
+ text_runs_.emplace_back(kSecondTextRun);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ ppapi::PdfAccessibilityLinkInfo link;
+ link.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ // Add first link in the vector.
+ link.text_run_index = 2;
+ link.text_run_count = 0;
+ links_.push_back(link);
+
+ // Add second link in the vector.
+ link.text_run_index = 0;
+ link.text_run_count = 1;
+ links_.push_back(link);
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+ page_info_.link_count = links_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+ // In case of invalid data, only the initialized data should be in the tree.
+ ASSERT_EQ(ax::mojom::Role::kUnknown,
+ pdf_accessibility_tree.GetRoot()->data().role);
+ ASSERT_EQ(0u, pdf_accessibility_tree.GetRoot()->children().size());
+}
+
+TEST_F(PdfAccessibilityTreeTest, OutOfBoundLink) {
+ text_runs_.emplace_back(kFirstTextRun);
+ text_runs_.emplace_back(kSecondTextRun);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ ppapi::PdfAccessibilityLinkInfo link;
+ link.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ link.text_run_index = 3;
+ link.text_run_count = 0;
+ links_.push_back(link);
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+ page_info_.link_count = links_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+ // In case of invalid data, only the initialized data should be in the tree.
+ ASSERT_EQ(ax::mojom::Role::kUnknown,
+ pdf_accessibility_tree.GetRoot()->data().role);
+ ASSERT_EQ(0u, pdf_accessibility_tree.GetRoot()->children().size());
+}
+
+TEST_F(PdfAccessibilityTreeTest, UnsortedImageVector) {
+ text_runs_.emplace_back(kFirstTextRun);
+ text_runs_.emplace_back(kSecondTextRun);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ ppapi::PdfAccessibilityImageInfo image;
+ image.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ // Add first image to the vector.
+ image.text_run_index = 1;
+ images_.push_back(image);
+
+ // Add second image to the vector.
+ image.text_run_index = 0;
+ images_.push_back(image);
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+ page_info_.image_count = images_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+ // In case of invalid data, only the initialized data should be in the tree.
+ ASSERT_EQ(ax::mojom::Role::kUnknown,
+ pdf_accessibility_tree.GetRoot()->data().role);
+ ASSERT_EQ(0u, pdf_accessibility_tree.GetRoot()->children().size());
+}
+
+TEST_F(PdfAccessibilityTreeTest, OutOfBoundImage) {
+ text_runs_.emplace_back(kFirstTextRun);
+ text_runs_.emplace_back(kSecondTextRun);
+ chars_.insert(chars_.end(), std::begin(kDummyCharsData),
+ std::end(kDummyCharsData));
+
+ ppapi::PdfAccessibilityImageInfo image;
+ image.bounds = PP_MakeFloatRectFromXYWH(0.0f, 0.0f, 0.0f, 0.0f);
+ image.text_run_index = 3;
+ images_.push_back(image);
+
+ page_info_.text_run_count = text_runs_.size();
+ page_info_.char_count = chars_.size();
+ page_info_.image_count = images_.size();
+
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame());
+ PP_Instance instance = 0;
+ pdf::PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+ // In case of invalid data, only the initialized data should be in the tree.
+ ASSERT_EQ(ax::mojom::Role::kUnknown,
+ pdf_accessibility_tree.GetRoot()->data().role);
+ ASSERT_EQ(0u, pdf_accessibility_tree.GetRoot()->children().size());
+}
+
+TEST_F(PdfAccessibilityTreeTest, TestActionDataConversion) {
+ // This test verifies the AXActionData conversion to
+ // PP_AccessibilityActionData.
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ ActionHandlingFakePepperPluginInstance fake_pepper_instance;
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame(),
+ &fake_pepper_instance);
+ PP_Instance instance = 0;
+ PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+
+ ui::AXNode* root_node = pdf_accessibility_tree.GetRoot();
+ std::unique_ptr<ui::AXActionTarget> pdf_action_target =
+ pdf_accessibility_tree.CreateActionTarget(*root_node);
+ ASSERT_TRUE(pdf_action_target);
+ EXPECT_EQ(ui::AXActionTarget::Type::kPdf, pdf_action_target->GetType());
+ EXPECT_TRUE(pdf_action_target->ScrollToMakeVisibleWithSubFocus(
+ gfx::Rect(0, 0, 50, 50), ax::mojom::ScrollAlignment::kScrollAlignmentLeft,
+ ax::mojom::ScrollAlignment::kScrollAlignmentTop));
+ PP_PdfAccessibilityActionData action_data =
+ fake_pepper_instance.GetReceivedActionData();
+ EXPECT_EQ(PP_PdfAccessibilityAction::PP_PDF_SCROLL_TO_MAKE_VISIBLE,
+ action_data.action);
+ EXPECT_EQ(PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_LEFT,
+ action_data.horizontal_scroll_alignment);
+ EXPECT_EQ(PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_TOP,
+ action_data.vertical_scroll_alignment);
+
+ EXPECT_TRUE(pdf_action_target->ScrollToMakeVisibleWithSubFocus(
+ gfx::Rect(0, 0, 50, 50),
+ ax::mojom::ScrollAlignment::kScrollAlignmentRight,
+ ax::mojom::ScrollAlignment::kScrollAlignmentTop));
+ action_data = fake_pepper_instance.GetReceivedActionData();
+ EXPECT_EQ(PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_RIGHT,
+ action_data.horizontal_scroll_alignment);
+
+ EXPECT_TRUE(pdf_action_target->ScrollToMakeVisibleWithSubFocus(
+ gfx::Rect(0, 0, 50, 50),
+ ax::mojom::ScrollAlignment::kScrollAlignmentBottom,
+ ax::mojom::ScrollAlignment::kScrollAlignmentBottom));
+ action_data = fake_pepper_instance.GetReceivedActionData();
+ EXPECT_EQ(PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_BOTTOM,
+ action_data.horizontal_scroll_alignment);
+
+ EXPECT_TRUE(pdf_action_target->ScrollToMakeVisibleWithSubFocus(
+ gfx::Rect(0, 0, 50, 50),
+ ax::mojom::ScrollAlignment::kScrollAlignmentCenter,
+ ax::mojom::ScrollAlignment::kScrollAlignmentClosestEdge));
+ action_data = fake_pepper_instance.GetReceivedActionData();
+ EXPECT_EQ(PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_CENTER,
+ action_data.horizontal_scroll_alignment);
+ EXPECT_EQ(
+ PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_CLOSEST_EDGE,
+ action_data.vertical_scroll_alignment);
+ CompareRect({{0, 0}, {1, 1}}, action_data.target_rect);
+}
+
+TEST_F(PdfAccessibilityTreeTest, TestEmptyPdfAxActions) {
+ content::RenderFrame* render_frame = view_->GetMainRenderFrame();
+ render_frame->SetAccessibilityModeForTest(ui::AXMode::kWebContents);
+ ASSERT_TRUE(render_frame->GetRenderAccessibility());
+
+ ActionHandlingFakePepperPluginInstance fake_pepper_instance;
+ FakeRendererPpapiHost host(view_->GetMainRenderFrame(),
+ &fake_pepper_instance);
+ PP_Instance instance = 0;
+ PdfAccessibilityTree pdf_accessibility_tree(&host, instance);
+
+ pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_);
+ pdf_accessibility_tree.SetAccessibilityDocInfo(doc_info_);
+ pdf_accessibility_tree.SetAccessibilityPageInfo(page_info_, text_runs_,
+ chars_, links_, images_);
+
+ ui::AXNode* root_node = pdf_accessibility_tree.GetRoot();
+ std::unique_ptr<ui::AXActionTarget> pdf_action_target =
+ pdf_accessibility_tree.CreateActionTarget(*root_node);
+ ASSERT_TRUE(pdf_action_target);
+ EXPECT_FALSE(pdf_action_target->ClearAccessibilityFocus());
+ EXPECT_FALSE(pdf_action_target->Click());
+ EXPECT_FALSE(pdf_action_target->Decrement());
+ EXPECT_FALSE(pdf_action_target->Increment());
+ EXPECT_FALSE(pdf_action_target->Focus());
+ gfx::Rect rect = pdf_action_target->GetRelativeBounds();
+ EXPECT_TRUE(rect.origin().IsOrigin());
+ EXPECT_TRUE(rect.IsEmpty());
+
+ gfx::Point point = pdf_action_target->GetScrollOffset();
+ EXPECT_EQ(point.x(), 0);
+ EXPECT_EQ(point.y(), 0);
+
+ point = pdf_action_target->MinimumScrollOffset();
+ EXPECT_EQ(point.x(), 0);
+ EXPECT_EQ(point.y(), 0);
+
+ point = pdf_action_target->MaximumScrollOffset();
+ EXPECT_EQ(point.x(), 0);
+ EXPECT_EQ(point.y(), 0);
+
+ EXPECT_FALSE(pdf_action_target->SetAccessibilityFocus());
+ EXPECT_FALSE(pdf_action_target->SetSelected(true));
+ EXPECT_FALSE(pdf_action_target->SetSelected(false));
+ EXPECT_FALSE(pdf_action_target->SetSelection(nullptr, 0, nullptr, 0));
+ EXPECT_FALSE(pdf_action_target->SetSequentialFocusNavigationStartingPoint());
+ EXPECT_FALSE(pdf_action_target->SetValue("test"));
+ EXPECT_FALSE(pdf_action_target->ShowContextMenu());
+ EXPECT_FALSE(pdf_action_target->ScrollToMakeVisible());
+ EXPECT_FALSE(pdf_action_target->ScrollToGlobalPoint(gfx::Point()));
}
} // namespace pdf
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree_unittest.cc b/chromium/components/pdf/renderer/pdf_accessibility_tree_unittest.cc
new file mode 100644
index 00000000000..ccaa9fad183
--- /dev/null
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/pdf/renderer/pdf_accessibility_tree.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace pdf {
+
+const PP_PrivateAccessibilityTextRunInfo kFirstTextRun = {
+ 15, 12, PP_MakeFloatRectFromXYWH(26.0f, 189.0f, 84.0f, 13.0f)};
+const PP_PrivateAccessibilityTextRunInfo kSecondTextRun = {
+ 15, 16, PP_MakeFloatRectFromXYWH(28.0f, 117.0f, 152.0f, 19.0f)};
+const PP_PrivateAccessibilityCharInfo kDummyCharsData[] = {
+ {'H', 12}, {'e', 6}, {'l', 5}, {'l', 4}, {'o', 8}, {',', 4},
+ {' ', 4}, {'w', 12}, {'o', 6}, {'r', 6}, {'l', 4}, {'d', 9},
+ {'!', 4}, {'\r', 0}, {'\n', 0}, {'G', 16}, {'o', 12}, {'o', 12},
+ {'d', 12}, {'b', 10}, {'y', 12}, {'e', 12}, {',', 4}, {' ', 6},
+ {'w', 16}, {'o', 12}, {'r', 8}, {'l', 4}, {'d', 12}, {'!', 2},
+};
+
+TEST(PdfAccessibilityTreeUnitTest, TextRunsAndCharsMismatch) {
+ // |chars| and |text_runs| span over the same page text. They should denote
+ // the same page text size, but |text_runs_| is incorrect and only denotes 1
+ // of 2 text runs.
+ std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
+ text_runs.emplace_back(kFirstTextRun);
+
+ std::vector<PP_PrivateAccessibilityCharInfo> chars(
+ std::begin(kDummyCharsData), std::end(kDummyCharsData));
+
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images;
+
+ ASSERT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
+ links, images));
+}
+
+TEST(PdfAccessibilityTreeUnitTest, TextRunsAndCharsMatch) {
+ // |chars| and |text_runs| span over the same page text. They should denote
+ // the same page text size.
+ std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
+ text_runs.emplace_back(kFirstTextRun);
+ text_runs.emplace_back(kSecondTextRun);
+
+ std::vector<PP_PrivateAccessibilityCharInfo> chars(
+ std::begin(kDummyCharsData), std::end(kDummyCharsData));
+
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images;
+
+ ASSERT_TRUE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
+ links, images));
+}
+
+TEST(PdfAccessibilityTreeUnitTest, UnsortedLinkVector) {
+ std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
+ text_runs.emplace_back(kFirstTextRun);
+ text_runs.emplace_back(kSecondTextRun);
+
+ std::vector<PP_PrivateAccessibilityCharInfo> chars(
+ std::begin(kDummyCharsData), std::end(kDummyCharsData));
+
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images;
+
+ ppapi::PdfAccessibilityLinkInfo link;
+ // Add first link in the vector.
+ link.text_run_index = 2;
+ link.text_run_count = 0;
+ links.push_back(link);
+
+ // Add second link in the vector.
+ link.text_run_index = 0;
+ link.text_run_count = 1;
+ links.push_back(link);
+
+ ASSERT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
+ links, images));
+}
+
+TEST(PdfAccessibilityTreeUnitTest, OutOfBoundLink) {
+ std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
+ text_runs.emplace_back(kFirstTextRun);
+ text_runs.emplace_back(kSecondTextRun);
+
+ std::vector<PP_PrivateAccessibilityCharInfo> chars(
+ std::begin(kDummyCharsData), std::end(kDummyCharsData));
+
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images;
+
+ ppapi::PdfAccessibilityLinkInfo link;
+ link.text_run_index = 3;
+ link.text_run_count = 0;
+ links.push_back(link);
+
+ ASSERT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
+ links, images));
+}
+
+TEST(PdfAccessibilityTreeUnitTest, UnsortedImageVector) {
+ std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
+ text_runs.emplace_back(kFirstTextRun);
+ text_runs.emplace_back(kSecondTextRun);
+
+ std::vector<PP_PrivateAccessibilityCharInfo> chars(
+ std::begin(kDummyCharsData), std::end(kDummyCharsData));
+
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images;
+
+ ppapi::PdfAccessibilityImageInfo image;
+ // Add first image to the vector.
+ image.text_run_index = 1;
+ images.push_back(image);
+
+ // Add second image to the vector.
+ image.text_run_index = 0;
+ images.push_back(image);
+
+ ASSERT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
+ links, images));
+}
+
+TEST(PdfAccessibilityTreeUnitTest, OutOfBoundImage) {
+ std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
+ text_runs.emplace_back(kFirstTextRun);
+ text_runs.emplace_back(kSecondTextRun);
+
+ std::vector<PP_PrivateAccessibilityCharInfo> chars(
+ std::begin(kDummyCharsData), std::end(kDummyCharsData));
+
+ std::vector<ppapi::PdfAccessibilityLinkInfo> links;
+ std::vector<ppapi::PdfAccessibilityImageInfo> images;
+
+ ppapi::PdfAccessibilityImageInfo image;
+ image.text_run_index = 3;
+ images.push_back(image);
+
+ ASSERT_FALSE(PdfAccessibilityTree::IsDataFromPluginValid(text_runs, chars,
+ links, images));
+}
+
+} // namespace pdf \ No newline at end of file
diff --git a/chromium/components/pdf/renderer/pdf_ax_action_target.cc b/chromium/components/pdf/renderer/pdf_ax_action_target.cc
new file mode 100644
index 00000000000..b3fd80b30c4
--- /dev/null
+++ b/chromium/components/pdf/renderer/pdf_ax_action_target.cc
@@ -0,0 +1,143 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/pdf/renderer/pdf_ax_action_target.h"
+
+#include "components/pdf/renderer/pdf_accessibility_tree.h"
+
+namespace pdf {
+
+namespace {
+
+PP_PdfAccessibilityScrollAlignment ConvertAXScrollToPdfScrollAlignment(
+ ax::mojom::ScrollAlignment scroll_alignment) {
+ switch (scroll_alignment) {
+ case ax::mojom::ScrollAlignment::kScrollAlignmentCenter:
+ return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_CENTER;
+ case ax::mojom::ScrollAlignment::kScrollAlignmentTop:
+ return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_TOP;
+ case ax::mojom::ScrollAlignment::kScrollAlignmentBottom:
+ return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_BOTTOM;
+ case ax::mojom::ScrollAlignment::kScrollAlignmentLeft:
+ return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_LEFT;
+ case ax::mojom::ScrollAlignment::kScrollAlignmentRight:
+ return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_ALIGNMENT_RIGHT;
+ case ax::mojom::ScrollAlignment::kScrollAlignmentClosestEdge:
+ return PP_PdfAccessibilityScrollAlignment::
+ PP_PDF_SCROLL_ALIGNMENT_CLOSEST_EDGE;
+ case ax::mojom::ScrollAlignment::kNone:
+ default:
+ return PP_PdfAccessibilityScrollAlignment::PP_PDF_SCROLL_NONE;
+ }
+}
+
+} // namespace
+
+PdfAXActionTarget::PdfAXActionTarget(const ui::AXNode& plugin_node,
+ pdf::PdfAccessibilityTree* pdf_tree_source)
+ : target_plugin_node_(plugin_node),
+ pdf_accessibility_tree_source_(pdf_tree_source) {
+ DCHECK(pdf_accessibility_tree_source_);
+}
+
+PdfAXActionTarget::~PdfAXActionTarget() = default;
+
+ui::AXActionTarget::Type PdfAXActionTarget::GetType() const {
+ return ui::AXActionTarget::Type::kPdf;
+}
+
+bool PdfAXActionTarget::ClearAccessibilityFocus() const {
+ return false;
+}
+
+bool PdfAXActionTarget::Click() const {
+ return false;
+}
+
+bool PdfAXActionTarget::Decrement() const {
+ return false;
+}
+
+bool PdfAXActionTarget::Increment() const {
+ return false;
+}
+
+bool PdfAXActionTarget::Focus() const {
+ return false;
+}
+
+gfx::Rect PdfAXActionTarget::GetRelativeBounds() const {
+ return gfx::Rect();
+}
+
+gfx::Point PdfAXActionTarget::GetScrollOffset() const {
+ return gfx::Point();
+}
+
+gfx::Point PdfAXActionTarget::MinimumScrollOffset() const {
+ return gfx::Point();
+}
+
+gfx::Point PdfAXActionTarget::MaximumScrollOffset() const {
+ return gfx::Point();
+}
+
+bool PdfAXActionTarget::SetAccessibilityFocus() const {
+ return false;
+}
+
+void PdfAXActionTarget::SetScrollOffset(const gfx::Point& point) const {}
+
+bool PdfAXActionTarget::SetSelected(bool selected) const {
+ return false;
+}
+
+bool PdfAXActionTarget::SetSelection(const ui::AXActionTarget* anchor_object,
+ int anchor_offset,
+ const ui::AXActionTarget* focus_object,
+ int focus_offset) const {
+ return false;
+}
+
+bool PdfAXActionTarget::SetSequentialFocusNavigationStartingPoint() const {
+ return false;
+}
+
+bool PdfAXActionTarget::SetValue(const std::string& value) const {
+ return false;
+}
+
+bool PdfAXActionTarget::ShowContextMenu() const {
+ return false;
+}
+
+bool PdfAXActionTarget::ScrollToMakeVisible() const {
+ return false;
+}
+
+bool PdfAXActionTarget::ScrollToMakeVisibleWithSubFocus(
+ const gfx::Rect& rect,
+ ax::mojom::ScrollAlignment horizontal_scroll_alignment,
+ ax::mojom::ScrollAlignment vertical_scroll_alignment) const {
+ PP_PdfAccessibilityActionData pdf_action_data;
+ pdf_action_data.action =
+ PP_PdfAccessibilityAction::PP_PDF_SCROLL_TO_MAKE_VISIBLE;
+ pdf_action_data.horizontal_scroll_alignment =
+ ConvertAXScrollToPdfScrollAlignment(horizontal_scroll_alignment);
+ pdf_action_data.vertical_scroll_alignment =
+ ConvertAXScrollToPdfScrollAlignment(vertical_scroll_alignment);
+ pdf_action_data.target_rect = {
+ {target_plugin_node_.data().relative_bounds.bounds.x(),
+ target_plugin_node_.data().relative_bounds.bounds.y()},
+ {target_plugin_node_.data().relative_bounds.bounds.width(),
+ target_plugin_node_.data().relative_bounds.bounds.height()}};
+ pdf_accessibility_tree_source_->HandleAction(pdf_action_data);
+ return true;
+}
+
+bool PdfAXActionTarget::ScrollToGlobalPoint(const gfx::Point& point) const {
+ return false;
+}
+
+} // namespace pdf
diff --git a/chromium/components/pdf/renderer/pdf_ax_action_target.h b/chromium/components/pdf/renderer/pdf_ax_action_target.h
new file mode 100644
index 00000000000..ddd784d20e2
--- /dev/null
+++ b/chromium/components/pdf/renderer/pdf_ax_action_target.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PDF_RENDERER_PDF_AX_ACTION_TARGET_H_
+#define COMPONENTS_PDF_RENDERER_PDF_AX_ACTION_TARGET_H_
+
+#include "ui/accessibility/ax_action_target.h"
+
+namespace ui {
+class AXNode;
+}
+
+namespace pdf {
+
+class PdfAccessibilityTree;
+
+// Abstracts an AXNode, representing a PDF node, for dispatching
+// accessibility actions.
+class PdfAXActionTarget : public ui::AXActionTarget {
+ public:
+ PdfAXActionTarget(const ui::AXNode& plugin_node,
+ pdf::PdfAccessibilityTree* tree);
+ ~PdfAXActionTarget() override;
+
+ protected:
+ // AXActionTarget overrides.
+ Type GetType() const override;
+ bool ClearAccessibilityFocus() const override;
+ bool Click() const override;
+ bool Decrement() const override;
+ bool Increment() const override;
+ bool Focus() const override;
+ gfx::Rect GetRelativeBounds() const override;
+ gfx::Point GetScrollOffset() const override;
+ gfx::Point MinimumScrollOffset() const override;
+ gfx::Point MaximumScrollOffset() const override;
+ bool SetAccessibilityFocus() const override;
+ void SetScrollOffset(const gfx::Point& point) const override;
+ bool SetSelected(bool selected) const override;
+ bool SetSelection(const ui::AXActionTarget* anchor_object,
+ int anchor_offset,
+ const ui::AXActionTarget* focus_object,
+ int focus_offset) const override;
+ bool SetSequentialFocusNavigationStartingPoint() const override;
+ bool SetValue(const std::string& value) const override;
+ bool ShowContextMenu() const override;
+ bool ScrollToMakeVisible() const override;
+ bool ScrollToMakeVisibleWithSubFocus(
+ const gfx::Rect& rect,
+ ax::mojom::ScrollAlignment horizontal_scroll_alignment,
+ ax::mojom::ScrollAlignment vertical_scroll_alignment) const override;
+ bool ScrollToGlobalPoint(const gfx::Point& point) const override;
+
+ private:
+ const ui::AXNode& target_plugin_node_;
+ pdf::PdfAccessibilityTree* pdf_accessibility_tree_source_;
+};
+
+} // namespace pdf
+
+#endif // COMPONENTS_PDF_RENDERER_PDF_AX_ACTION_TARGET_H_
diff --git a/chromium/components/pdf/renderer/pepper_pdf_host.cc b/chromium/components/pdf/renderer/pepper_pdf_host.cc
index d24105340e7..a8d74a48db9 100644
--- a/chromium/components/pdf/renderer/pepper_pdf_host.cc
+++ b/chromium/components/pdf/renderer/pepper_pdf_host.cc
@@ -278,12 +278,14 @@ int32_t PepperPDFHost::OnHostMsgSetAccessibilityPageInfo(
ppapi::host::HostMessageContext* context,
const PP_PrivateAccessibilityPageInfo& page_info,
const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_run_info,
- const std::vector<PP_PrivateAccessibilityCharInfo>& chars) {
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images) {
if (!host_->GetPluginInstance(pp_instance()))
return PP_ERROR_FAILED;
CreatePdfAccessibilityTreeIfNeeded();
- pdf_accessibility_tree_->SetAccessibilityPageInfo(
- page_info, text_run_info, chars);
+ pdf_accessibility_tree_->SetAccessibilityPageInfo(page_info, text_run_info,
+ chars, links, images);
return PP_OK;
}
diff --git a/chromium/components/pdf/renderer/pepper_pdf_host.h b/chromium/components/pdf/renderer/pepper_pdf_host.h
index 0bfc7397b8d..a501a89c74d 100644
--- a/chromium/components/pdf/renderer/pepper_pdf_host.h
+++ b/chromium/components/pdf/renderer/pepper_pdf_host.h
@@ -21,6 +21,7 @@
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/serialized_structs.h"
+#include "ppapi/shared_impl/pdf_accessibility_shared.h"
namespace blink {
class WebLocalFrame;
@@ -117,7 +118,9 @@ class PepperPDFHost : public ppapi::host::ResourceHost,
ppapi::host::HostMessageContext* context,
const PP_PrivateAccessibilityPageInfo& page_info,
const std::vector<PP_PrivateAccessibilityTextRunInfo>& text_runs,
- const std::vector<PP_PrivateAccessibilityCharInfo>& chars);
+ const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
+ const std::vector<ppapi::PdfAccessibilityLinkInfo>& links,
+ const std::vector<ppapi::PdfAccessibilityImageInfo>& images);
int32_t OnHostMsgSelectionChanged(ppapi::host::HostMessageContext* context,
const PP_FloatPoint& left,
int32_t left_height,
diff --git a/chromium/components/pdf_strings_grdp/OWNERS b/chromium/components/pdf_strings_grdp/OWNERS
index db781ac5adc..4e342a12dae 100644
--- a/chromium/components/pdf_strings_grdp/OWNERS
+++ b/chromium/components/pdf_strings_grdp/OWNERS
@@ -1 +1,2 @@
raymes@chromium.org
+# COMPONENT: Internals>Plugins>PDF
diff --git a/chromium/components/plugins/OWNERS b/chromium/components/plugins/OWNERS
index 94de159b9e4..f8cf45de415 100644
--- a/chromium/components/plugins/OWNERS
+++ b/chromium/components/plugins/OWNERS
@@ -1 +1,2 @@
tommycli@chromium.org
+# COMPONENT: Internals>Plugins
diff --git a/chromium/components/plugins/renderer/DEPS b/chromium/components/plugins/renderer/DEPS
index 9e68e68f34e..5ee90b78ce7 100644
--- a/chromium/components/plugins/renderer/DEPS
+++ b/chromium/components/plugins/renderer/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+content/public/renderer",
"+content/public/common",
"+content/public/test",
+ "+mojo/public/cpp/bindings",
"+services/service_manager/public/cpp",
"+third_party/blink/public",
"+third_party/re2",
diff --git a/chromium/components/plugins/renderer/webview_plugin.cc b/chromium/components/plugins/renderer/webview_plugin.cc
index 956fc1f5f39..b632d299000 100644
--- a/chromium/components/plugins/renderer/webview_plugin.cc
+++ b/chromium/components/plugins/renderer/webview_plugin.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <string>
+
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/location.h"
@@ -16,6 +18,7 @@
#include "content/public/common/web_preferences.h"
#include "content/public/renderer/render_view.h"
#include "gin/converter.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
@@ -146,6 +149,7 @@ v8::Local<v8::Object> WebViewPlugin::V8ScriptableObject(v8::Isolate* isolate) {
void WebViewPlugin::UpdateAllLifecyclePhases(
blink::WebWidget::LifecycleUpdateReason reason) {
+ DCHECK(web_view()->MainFrameWidget());
web_view()->MainFrameWidget()->UpdateAllLifecyclePhases(reason);
}
@@ -182,6 +186,7 @@ void WebViewPlugin::UpdateGeometry(const WebRect& window_rect,
if (static_cast<gfx::Rect>(window_rect) != rect_) {
rect_ = window_rect;
+ DCHECK(web_view()->MainFrameWidget());
web_view()->MainFrameWidget()->Resize(rect_.size());
}
@@ -220,6 +225,7 @@ blink::WebInputEventResult WebViewPlugin::HandleInputEvent(
return blink::WebInputEventResult::kHandledSuppressed;
}
current_cursor_ = cursor;
+ DCHECK(web_view()->MainFrameWidget());
blink::WebInputEventResult handled =
web_view()->MainFrameWidget()->HandleInputEvent(
blink::WebCoalescedInputEvent(event));
@@ -257,21 +263,23 @@ WebViewPlugin::WebViewHelper::WebViewHelper(WebViewPlugin* plugin,
// ApplyWebPreferences before making a WebLocalFrame so that the frame sees a
// consistent view of our preferences.
content::RenderView::ApplyWebPreferences(preferences, web_view_);
- blink::mojom::DocumentInterfaceBrokerPtrInfo document_interface_broker;
+ mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
+ document_interface_broker;
WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
web_view_, this, nullptr,
- mojo::MakeRequest(&document_interface_broker).PassMessagePipe(), nullptr);
+ document_interface_broker.InitWithNewPipeAndPassReceiver().PassPipe(),
+ nullptr);
// The created WebFrameWidget is owned by the |web_frame|.
WebFrameWidget::CreateForMainFrame(this, web_frame);
// The WebFrame created here was already attached to the Page as its
// main frame, and the WebFrameWidget has been initialized, so we can call
// WebViewImpl's DidAttachLocalMainFrame().
- web_view_->DidAttachLocalMainFrame(this);
+ web_view_->DidAttachLocalMainFrame();
}
WebViewPlugin::WebViewHelper::~WebViewHelper() {
- web_view_->MainFrameWidget()->Close();
+ web_view_->Close();
}
bool WebViewPlugin::WebViewHelper::AcceptsLoadDrops() {
@@ -383,7 +391,8 @@ void WebViewPlugin::OnZoomLevelChanged() {
void WebViewPlugin::LoadHTML(const std::string& html_data, const GURL& url) {
web_view_helper_.main_frame()->CommitNavigation(
blink::WebNavigationParams::CreateWithHTMLString(html_data, url),
- nullptr /* extra_data */);
+ nullptr /* extra_data */,
+ base::DoNothing::Once() /* call_before_attaching_new_document */);
}
void WebViewPlugin::UpdatePluginForNewGeometry(
@@ -398,6 +407,7 @@ void WebViewPlugin::UpdatePluginForNewGeometry(
// The delegate may have dirtied style and layout of the WebView.
// See for example the resizePoster function in plugin_poster.html.
// Run the lifecycle now so that it is clean.
+ DCHECK(web_view()->MainFrameWidget());
web_view()->MainFrameWidget()->UpdateAllLifecyclePhases(
blink::WebWidget::LifecycleUpdateReason::kOther);
}
diff --git a/chromium/components/plugins/renderer/webview_plugin.h b/chromium/components/plugins/renderer/webview_plugin.h
index ffd59c4ac34..0e1d05d8750 100644
--- a/chromium/components/plugins/renderer/webview_plugin.h
+++ b/chromium/components/plugins/renderer/webview_plugin.h
@@ -180,13 +180,13 @@ class WebViewPlugin : public blink::WebPlugin,
const gfx::Point&) override;
void DidChangeCursor(const blink::WebCursorInfo& cursor) override;
void ScheduleAnimation() override;
- std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory()
- override;
// WebLocalFrameClient methods:
void BindToFrame(blink::WebNavigationControl* frame) override;
void DidClearWindowObject() override;
void FrameDetached(DetachType) override;
+ std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory()
+ override;
private:
WebViewPlugin* plugin_;
diff --git a/chromium/components/policy/BUILD.gn b/chromium/components/policy/BUILD.gn
index e094f46881f..353e8e409ed 100644
--- a/chromium/components/policy/BUILD.gn
+++ b/chromium/components/policy/BUILD.gn
@@ -91,12 +91,6 @@ action("cloud_policy_code_generate") {
chrome_version_abspath = "//chrome/VERSION"
chrome_version_path = rebase_path(chrome_version_abspath, root_build_dir)
- if (is_chromeos) {
- chromeos_flag = "1"
- } else {
- chromeos_flag = "0"
- }
-
inputs = [
chrome_version_abspath,
"resources/policy_templates.json",
@@ -115,6 +109,13 @@ action("cloud_policy_code_generate") {
}
args = [
+ # Input information
+ "--chrome-version-file=" + chrome_version_path,
+ "--target-platform=" + target_os,
+ "--policy-templates-file=" +
+ rebase_path("resources/policy_templates.json", root_build_dir),
+
+ # Output files to be generated
"--policy-constants-header=" +
rebase_path(constants_header_path, root_build_dir),
"--policy-constants-source=" +
@@ -126,10 +127,6 @@ action("cloud_policy_code_generate") {
"--app-restrictions-definition=" +
rebase_path(app_restrictions_path, root_build_dir),
"--risk-tag-header=" + rebase_path(risk_tag_header_path, root_build_dir),
- chrome_version_path,
- target_os,
- chromeos_flag,
- rebase_path("resources/policy_templates.json", root_build_dir),
]
}
@@ -138,12 +135,6 @@ action("full_runtime_code_generate") {
chrome_version_abspath = "//chrome/VERSION"
chrome_version_path = rebase_path(chrome_version_abspath, root_build_dir)
- if (is_chromeos) {
- chromeos_flag = "1"
- } else {
- chromeos_flag = "0"
- }
-
inputs = [
chrome_version_abspath,
"resources/policy_templates.json",
@@ -154,14 +145,17 @@ action("full_runtime_code_generate") {
]
args = [
+ # Input information
+ "--chrome-version-file=" + chrome_version_path,
+ "--target-platform=" + target_os,
+ "--policy-templates-file=" +
+ rebase_path("resources/policy_templates.json", root_build_dir),
+
+ # Output files to be generated
"--cloud-policy-full-runtime-protobuf=" +
rebase_path(cloud_policy_full_runtime_proto_path, root_build_dir),
"--chrome-settings-full-runtime-protobuf=" +
rebase_path(chrome_settings_full_runtime_proto_path, root_build_dir),
- chrome_version_path,
- target_os,
- chromeos_flag,
- rebase_path("resources/policy_templates.json", root_build_dir),
]
}
@@ -348,6 +342,9 @@ static_library("generated") {
"//components/policy/core/common:common_constants",
"//third_party/protobuf:protobuf_lite",
]
+ deps = [
+ "//build:branding_buildflags",
+ ]
}
if (gen_policy_templates_android && is_android) {
diff --git a/chromium/components/policy/core/browser/BUILD.gn b/chromium/components/policy/core/browser/BUILD.gn
index a2fc5fe7545..bf4ee73af84 100644
--- a/chromium/components/policy/core/browser/BUILD.gn
+++ b/chromium/components/policy/core/browser/BUILD.gn
@@ -56,7 +56,7 @@ jumbo_source_set("internal") {
deps = [
"//base/third_party/dynamic_annotations",
"//components/bookmarks/managed",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/keyed_service/core",
"//components/pref_registry",
"//components/prefs",
diff --git a/chromium/components/policy/core/common/BUILD.gn b/chromium/components/policy/core/common/BUILD.gn
index cf05ae4fee8..fce00064b0f 100644
--- a/chromium/components/policy/core/common/BUILD.gn
+++ b/chromium/components/policy/core/common/BUILD.gn
@@ -241,7 +241,10 @@ jumbo_source_set("internal") {
]
}
if (is_mac) {
- libs = [ "CoreFoundation.framework" ]
+ libs = [
+ "CoreFoundation.framework",
+ "SystemConfiguration.framework",
+ ]
}
if (is_ios || is_mac) {
sources += [
@@ -409,6 +412,7 @@ source_set("unit_tests") {
"//components/account_id",
"//components/policy:generated",
"//components/prefs:test_support",
+ "//components/version_info:version_info",
"//extensions/buildflags",
"//google_apis",
"//net:test_support",
diff --git a/chromium/components/policy_strings.grdp b/chromium/components/policy_strings.grdp
index 619ce16f1fe..0551e44698b 100644
--- a/chromium/components/policy_strings.grdp
+++ b/chromium/components/policy_strings.grdp
@@ -160,6 +160,9 @@
<message name="IDS_POLICY_NOT_SPECIFIED_ERROR" desc="The text displayed in the status column when a policy value should have been specified but wasn't.">
Must be specified.
</message>
+ <message name="IDS_POLICY_EXTENSION_SETTINGS_ORIGIN_LIMIT_WARNING" desc="The text displayed in the status column of the 'Extension Settings' policy when more than 100 origins are specified.">
+ This field should not have more than <ph name="MAX_ITEMS_LIMIT">$1<ex>100</ex></ph> entries. All further entries will be discarded.
+ </message>
<message name="IDS_POLICY_SUBKEY_ERROR" desc="The text displayed in the status column for errors in a subkey of a policy.">
Key "<ph name="SUBKEY">$1<ex>ProxyMode</ex></ph>": <ph name="ERROR">$2<ex>Must be specified.</ex></ph>
</message>
@@ -175,6 +178,12 @@
<message name="IDS_POLICY_INVALID_SEARCH_URL_ERROR" desc="The text displayed in the status column when a the URL given for DefaultSearchProviderSearchURL is invalid.">
Invalid search URL.
</message>
+ <message name="IDS_POLICY_INVALID_SECURE_DNS_MODE_ERROR" desc="The text displayed in the status column when the value for DnsOverHttpsMode is invalid.">
+ Invalid DnsOverHttps mode.
+ </message>
+ <message name="IDS_POLICY_SECURE_DNS_MODE_NOT_SUPPORTED_ERROR" desc="The text displayed in the status column when the value for DnsOverHttpsMode is secure, which is not supported yet.">
+ The DnsOverHttps mode <ph name="SECURE_DNS_MODE_SECURE">'secure'</ph> is not yet supported, the mode has been set to <ph name="SECURE_DNS_MODE_OFF">'off'</ph>.
+ </message>
<message name="IDS_POLICY_INVALID_PROXY_MODE_ERROR" desc="The text displayed in the status column when the value for ProxyMode is invalid.">
Invalid proxy mode.
</message>
@@ -407,7 +416,7 @@ Additional details:
Cloud
</message>
<message name="IDS_POLICY_SOURCE_MERGED" desc="Indicates that the policy is a merged values from multiple sources.">
- Platform and Cloud
+ Merged
</message>
<message name="IDS_POLICY_SOURCE_ACTIVE_DIRECTORY" desc="Indicates that the policy originates from a local server, e.g. Samba or Active Directory.">
<ph name="MICROSOFT_ACTIVE_DIRECTORY">Local Server</ph>
diff --git a/chromium/components/policy_strings_grdp/OWNERS b/chromium/components/policy_strings_grdp/OWNERS
index f22fa361bed..08e0a7137f9 100644
--- a/chromium/components/policy_strings_grdp/OWNERS
+++ b/chromium/components/policy_strings_grdp/OWNERS
@@ -1 +1,3 @@
file://components/policy/OWNERS
+# COMPONENT: Enterprise>CloudPolicy
+# TEAM: chromium-reviews@chromium.org
diff --git a/chromium/components/prefs/in_memory_pref_store_unittest.cc b/chromium/components/prefs/in_memory_pref_store_unittest.cc
index b2b6780a108..dffe5fa454d 100644
--- a/chromium/components/prefs/in_memory_pref_store_unittest.cc
+++ b/chromium/components/prefs/in_memory_pref_store_unittest.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/prefs/persistent_pref_store_unittest.h"
#include "components/prefs/pref_store_observer_mock.h"
@@ -22,7 +22,7 @@ class InMemoryPrefStoreTest : public testing::Test {
void SetUp() override { store_ = new InMemoryPrefStore(); }
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<InMemoryPrefStore> store_;
PrefStoreObserverMock observer_;
};
@@ -107,7 +107,7 @@ TEST_F(InMemoryPrefStoreTest, ReadPrefs) {
}
TEST_F(InMemoryPrefStoreTest, CommitPendingWriteWithCallback) {
- TestCommitPendingWriteWithCallback(store_.get(), &scoped_task_environment_);
+ TestCommitPendingWriteWithCallback(store_.get(), &task_environment_);
}
} // namespace
diff --git a/chromium/components/prefs/json_pref_store.h b/chromium/components/prefs/json_pref_store.h
index e29e3b59fad..089ce0b6853 100644
--- a/chromium/components/prefs/json_pref_store.h
+++ b/chromium/components/prefs/json_pref_store.h
@@ -67,8 +67,9 @@ class COMPONENTS_PREFS_EXPORT JsonPrefStore
JsonPrefStore(const base::FilePath& pref_filename,
std::unique_ptr<PrefFilter> pref_filter = nullptr,
scoped_refptr<base::SequencedTaskRunner> file_task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
// PrefStore overrides:
diff --git a/chromium/components/prefs/json_pref_store_unittest.cc b/chromium/components/prefs/json_pref_store_unittest.cc
index 8ba14d1601a..c747c368715 100644
--- a/chromium/components/prefs/json_pref_store_unittest.cc
+++ b/chromium/components/prefs/json_pref_store_unittest.cc
@@ -25,7 +25,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread.h"
#include "base/values.h"
@@ -134,31 +134,30 @@ enum class CommitPendingWriteMode {
WITH_SYNCHRONOUS_CALLBACK,
};
-base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode GetExecutionMode(
+base::test::TaskEnvironment::ThreadPoolExecutionMode GetExecutionMode(
CommitPendingWriteMode commit_mode) {
switch (commit_mode) {
case CommitPendingWriteMode::WITHOUT_CALLBACK:
FALLTHROUGH;
case CommitPendingWriteMode::WITH_CALLBACK:
- return base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED;
+ return base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED;
case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK:
// Synchronous callbacks require async tasks to run on their own.
- return base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC;
+ return base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC;
}
}
-void CommitPendingWrite(
- JsonPrefStore* pref_store,
- CommitPendingWriteMode commit_pending_write_mode,
- base::test::ScopedTaskEnvironment* scoped_task_environment) {
+void CommitPendingWrite(JsonPrefStore* pref_store,
+ CommitPendingWriteMode commit_pending_write_mode,
+ base::test::TaskEnvironment* task_environment) {
switch (commit_pending_write_mode) {
case CommitPendingWriteMode::WITHOUT_CALLBACK: {
pref_store->CommitPendingWrite();
- scoped_task_environment->RunUntilIdle();
+ task_environment->RunUntilIdle();
break;
}
case CommitPendingWriteMode::WITH_CALLBACK: {
- TestCommitPendingWriteWithCallback(pref_store, scoped_task_environment);
+ TestCommitPendingWriteWithCallback(pref_store, task_environment);
break;
}
case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK: {
@@ -176,16 +175,15 @@ class JsonPrefStoreTest
: public testing::TestWithParam<CommitPendingWriteMode> {
public:
JsonPrefStoreTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT,
- GetExecutionMode(GetParam())) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::DEFAULT,
+ GetExecutionMode(GetParam())) {}
protected:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
// The path to temporary directory used to contain the test operations.
base::ScopedTempDir temp_dir_;
@@ -229,11 +227,10 @@ TEST_P(JsonPrefStoreTest, InvalidFile) {
// This function is used to avoid code duplication while testing synchronous
// and asynchronous version of the JsonPrefStore loading. It validates that the
// given output file's contents matches kWriteGolden.
-void RunBasicJsonPrefStoreTest(
- JsonPrefStore* pref_store,
- const base::FilePath& output_file,
- CommitPendingWriteMode commit_pending_write_mode,
- base::test::ScopedTaskEnvironment* scoped_task_environment) {
+void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
+ const base::FilePath& output_file,
+ CommitPendingWriteMode commit_pending_write_mode,
+ base::test::TaskEnvironment* task_environment) {
const char kNewWindowsInTabs[] = "tabs.new_windows_in_tabs";
const char kMaxTabs[] = "tabs.max_tabs";
const char kLongIntPref[] = "long_int.pref";
@@ -294,8 +291,7 @@ void RunBasicJsonPrefStoreTest(
EXPECT_EQ(214748364842LL, value);
// Serialize and compare to expected output.
- CommitPendingWrite(pref_store, commit_pending_write_mode,
- scoped_task_environment);
+ CommitPendingWrite(pref_store, commit_pending_write_mode, task_environment);
std::string output_contents;
ASSERT_TRUE(base::ReadFileToString(output_file, &output_contents));
@@ -326,7 +322,7 @@ TEST_P(JsonPrefStoreTest, Basic) {
// }
RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
- &scoped_task_environment_);
+ &task_environment_);
}
TEST_P(JsonPrefStoreTest, BasicAsync) {
@@ -347,7 +343,7 @@ TEST_P(JsonPrefStoreTest, BasicAsync) {
EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
EXPECT_CALL(*mock_error_delegate,
OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
pref_store->RemoveObserver(&mock_observer);
EXPECT_FALSE(pref_store->ReadOnly());
@@ -365,7 +361,7 @@ TEST_P(JsonPrefStoreTest, BasicAsync) {
// }
RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
- &scoped_task_environment_);
+ &task_environment_);
}
TEST_P(JsonPrefStoreTest, PreserveEmptyValues) {
@@ -380,7 +376,7 @@ TEST_P(JsonPrefStoreTest, PreserveEmptyValues) {
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
// Write to file.
- CommitPendingWrite(pref_store.get(), GetParam(), &scoped_task_environment_);
+ CommitPendingWrite(pref_store.get(), GetParam(), &task_environment_);
// Reload.
pref_store = base::MakeRefCounted<JsonPrefStore>(pref_file);
@@ -429,7 +425,7 @@ TEST_P(JsonPrefStoreTest, AsyncNonExistingFile) {
EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1);
EXPECT_CALL(*mock_error_delegate,
OnError(PersistentPrefStore::PREF_READ_ERROR_NO_FILE)).Times(1);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
pref_store->RemoveObserver(&mock_observer);
EXPECT_FALSE(pref_store->ReadOnly());
@@ -474,7 +470,7 @@ TEST_P(JsonPrefStoreTest, ReadWithInterceptor) {
// }
RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
- &scoped_task_environment_);
+ &task_environment_);
}
TEST_P(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
@@ -501,7 +497,7 @@ TEST_P(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0);
// EXPECT_CALL(*mock_error_delegate,
// OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(pref_store->ReadOnly());
EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs());
@@ -535,7 +531,7 @@ TEST_P(JsonPrefStoreTest, ReadAsyncWithInterceptor) {
// }
RunBasicJsonPrefStoreTest(pref_store.get(), input_file, GetParam(),
- &scoped_task_environment_);
+ &task_environment_);
}
INSTANTIATE_TEST_SUITE_P(
@@ -573,7 +569,7 @@ class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest {
// Get the contents of kTestFile. Pumps the message loop before returning the
// result.
std::string GetTestFileContents() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
std::string file_contents;
ReadFileToString(test_file_, &file_contents);
return file_contents;
@@ -836,9 +832,9 @@ class JsonPrefStoreCallbackTest : public testing::Test {
WriteCallbacksObserver write_callback_observer_;
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::DEFAULT,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED};
base::ScopedTempDir temp_dir_;
@@ -870,7 +866,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestSerializeDataCallbacks) {
EXPECT_EQ(NOT_CALLED,
write_callback_observer_.GetAndResetPostWriteObservationState());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -886,7 +882,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacks) {
successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
file_writer->WriteNow(std::make_unique<std::string>("foo"));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -897,7 +893,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacks) {
successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
file_writer->WriteNow(std::make_unique<std::string>("foo"));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -906,7 +902,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacks) {
// Test RegisterOnNextSuccessfulWriteReply only.
successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
file_writer->WriteNow(std::make_unique<std::string>("foo"));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_FALSE(write_callback_observer_.GetAndResetPreWriteObservationState());
EXPECT_EQ(NOT_CALLED,
@@ -915,7 +911,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacks) {
// Test RegisterOnNextWriteSynchronousCallbacks only.
write_callback_observer_.ObserveNextWriteCallback(pref_store.get());
file_writer->WriteNow(std::make_unique<std::string>("foo"));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
@@ -928,7 +924,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksWithFakeFailure) {
// Confirm that the observers are invoked.
successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
TriggerFakeWriteForCallback(pref_store.get(), true);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -941,7 +937,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksWithFakeFailure) {
// Confirm that re-installing the observers works for another write.
successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
TriggerFakeWriteForCallback(pref_store.get(), true);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -950,7 +946,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksWithFakeFailure) {
// write, and that the synchronous observer is invoked.
successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get());
TriggerFakeWriteForCallback(pref_store.get(), false);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_EQ(CALLED_WITH_ERROR,
write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -959,7 +955,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksWithFakeFailure) {
// being set by |PostWriteCallback| by the last TriggerFakeWriteCallback.
ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get());
file_writer->WriteNow(std::make_unique<std::string>("foo"));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_EQ(NOT_CALLED,
write_callback_observer_.GetAndResetPostWriteObservationState());
@@ -979,7 +975,7 @@ TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbacksDuringProfileDeath) {
soon_out_of_scope_pref_store.get());
file_writer->WriteNow(std::make_unique<std::string>("foo"));
}
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
EXPECT_TRUE(write_callback_observer_.GetAndResetPreWriteObservationState());
EXPECT_EQ(CALLED_WITH_SUCCESS,
diff --git a/chromium/components/prefs/overlay_user_pref_store_unittest.cc b/chromium/components/prefs/overlay_user_pref_store_unittest.cc
index 5f0d7258198..1c0c855b93c 100644
--- a/chromium/components/prefs/overlay_user_pref_store_unittest.cc
+++ b/chromium/components/prefs/overlay_user_pref_store_unittest.cc
@@ -3,9 +3,10 @@
// found in the LICENSE file.
#include "components/prefs/overlay_user_pref_store.h"
+
#include <memory>
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/prefs/persistent_pref_store_unittest.h"
#include "components/prefs/pref_store_observer_mock.h"
@@ -40,7 +41,7 @@ class OverlayUserPrefStoreTest : public testing::Test {
~OverlayUserPrefStoreTest() override {}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<TestingPrefStore> underlay_;
scoped_refptr<OverlayUserPrefStore> overlay_;
};
@@ -275,7 +276,7 @@ TEST_F(OverlayUserPrefStoreTest, GetValues) {
}
TEST_F(OverlayUserPrefStoreTest, CommitPendingWriteWithCallback) {
- TestCommitPendingWriteWithCallback(overlay_.get(), &scoped_task_environment_);
+ TestCommitPendingWriteWithCallback(overlay_.get(), &task_environment_);
}
} // namespace base
diff --git a/chromium/components/prefs/persistent_pref_store_unittest.cc b/chromium/components/prefs/persistent_pref_store_unittest.cc
index d297858b812..9ea3f988c5b 100644
--- a/chromium/components/prefs/persistent_pref_store_unittest.cc
+++ b/chromium/components/prefs/persistent_pref_store_unittest.cc
@@ -7,12 +7,12 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/sequence_checker_impl.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
void TestCommitPendingWriteWithCallback(
PersistentPrefStore* store,
- base::test::ScopedTaskEnvironment* scoped_task_environment) {
+ base::test::TaskEnvironment* task_environment) {
base::RunLoop run_loop;
base::SequenceCheckerImpl sequence_checker;
store->CommitPendingWrite(base::BindOnce(
@@ -21,6 +21,6 @@ void TestCommitPendingWriteWithCallback(
run_loop->Quit();
},
base::Unretained(&sequence_checker), base::Unretained(&run_loop)));
- scoped_task_environment->RunUntilIdle();
+ task_environment->RunUntilIdle();
run_loop.Run();
}
diff --git a/chromium/components/prefs/persistent_pref_store_unittest.h b/chromium/components/prefs/persistent_pref_store_unittest.h
index ea658e1c7c7..121f942b1af 100644
--- a/chromium/components/prefs/persistent_pref_store_unittest.h
+++ b/chromium/components/prefs/persistent_pref_store_unittest.h
@@ -7,18 +7,18 @@
namespace base {
namespace test {
-class ScopedTaskEnvironment;
+class TaskEnvironment;
}
} // namespace base
class PersistentPrefStore;
// Calls CommitPendingWrite() on |store| with a callback. Verifies that the
-// callback runs on the appropriate sequence. |scoped_task_environment| is the
-// test's ScopedTaskEnvironment. This function is meant to be reused in the
+// callback runs on the appropriate sequence. |task_environment| is the
+// test's TaskEnvironment. This function is meant to be reused in the
// tests of various PersistentPrefStore implementations.
void TestCommitPendingWriteWithCallback(
PersistentPrefStore* store,
- base::test::ScopedTaskEnvironment* scoped_task_environment);
+ base::test::TaskEnvironment* task_environment);
#endif // COMPONENTS_PREFS_PERSISTENT_PREF_STORE_UNITTEST_H_
diff --git a/chromium/components/prefs/pref_member_unittest.cc b/chromium/components/prefs/pref_member_unittest.cc
index eced7b50f4c..126b18fc296 100644
--- a/chromium/components/prefs/pref_member_unittest.cc
+++ b/chromium/components/prefs/pref_member_unittest.cc
@@ -11,7 +11,7 @@
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,7 +36,8 @@ class GetPrefValueHelper
: public base::RefCountedThreadSafe<GetPrefValueHelper> {
public:
GetPrefValueHelper()
- : value_(false), task_runner_(base::CreateSequencedTaskRunner({})) {}
+ : value_(false),
+ task_runner_(base::CreateSequencedTaskRunner({base::ThreadPool()})) {}
void Init(const std::string& pref_name, PrefService* prefs) {
pref_.Init(pref_name, prefs);
@@ -99,7 +100,7 @@ class PrefMemberTestClass {
} // anonymous namespace
class PrefMemberTest : public testing::Test {
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
TEST_F(PrefMemberTest, BasicGetAndSet) {
diff --git a/chromium/components/prefs/pref_notifier_impl.cc b/chromium/components/prefs/pref_notifier_impl.cc
index 0291e04b1cf..9c753e71be7 100644
--- a/chromium/components/prefs/pref_notifier_impl.cc
+++ b/chromium/components/prefs/pref_notifier_impl.cc
@@ -4,9 +4,11 @@
#include "components/prefs/pref_notifier_impl.h"
+#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/strcat.h"
#include "components/prefs/pref_service.h"
PrefNotifierImpl::PrefNotifierImpl() : pref_service_(nullptr) {}
@@ -33,8 +35,10 @@ PrefNotifierImpl::~PrefNotifierImpl() {
// leaked on termination, it is guaranteed that they don't attempt to
// unsubscribe.
const auto& pref_name = observer_list.first;
- LOG(WARNING) << "Pref observer for " << pref_name
- << " found at shutdown.";
+ std::string message = base::StrCat(
+ {"Pref observer for ", pref_name, " found at shutdown."});
+ LOG(WARNING) << message;
+ DEBUG_ALIAS_FOR_CSTR(aliased_message, message.c_str(), 128);
// TODO(crbug.com/942491, 946668, 945772) The following code collects
// stacktraces that show how the profile is destroyed that owns
diff --git a/chromium/components/previews/DEPS b/chromium/components/previews/DEPS
index ba62364303c..03135a11a14 100644
--- a/chromium/components/previews/DEPS
+++ b/chromium/components/previews/DEPS
@@ -3,5 +3,6 @@ include_rules = [
# allowances of //content dependencies as appropriate.
"-components",
"-components/data_reduction_proxy/",
+ "+components/data_reduction_proxy/core/browser/",
"-components/previews/content",
] \ No newline at end of file
diff --git a/chromium/components/previews/content/BUILD.gn b/chromium/components/previews/content/BUILD.gn
index 4e6d9992fec..461aae9fbf2 100644
--- a/chromium/components/previews/content/BUILD.gn
+++ b/chromium/components/previews/content/BUILD.gn
@@ -4,12 +4,16 @@
static_library("content") {
sources = [
+ "previews_decider.h",
"previews_decider_impl.cc",
"previews_decider_impl.h",
"previews_hints.cc",
"previews_hints.h",
- "previews_optimization_guide.cc",
"previews_optimization_guide.h",
+ "previews_optimization_guide_decider.cc",
+ "previews_optimization_guide_decider.h",
+ "previews_optimization_guide_impl.cc",
+ "previews_optimization_guide_impl.h",
"previews_ui_service.cc",
"previews_ui_service.h",
"previews_user_data.cc",
@@ -26,6 +30,7 @@ static_library("content") {
"//components/previews/core",
"//components/url_matcher",
"//components/variations",
+ "//content/public/browser",
"//content/public/common",
"//net",
"//services/network:network_service",
@@ -37,7 +42,8 @@ source_set("unit_tests") {
sources = [
"previews_decider_impl_unittest.cc",
"previews_hints_unittest.cc",
- "previews_optimization_guide_unittest.cc",
+ "previews_optimization_guide_decider_unittest.cc",
+ "previews_optimization_guide_impl_unittest.cc",
"previews_ui_service_unittest.cc",
"previews_user_data_unittest.cc",
]
@@ -54,7 +60,9 @@ source_set("unit_tests") {
"//components/prefs:test_support",
"//components/previews/core",
"//components/variations",
+ "//content/public/browser",
"//content/public/common",
+ "//content/test:test_support",
"//net:test_support",
"//services/network:network_service",
"//services/network:test_support",
diff --git a/chromium/components/previews/content/DEPS b/chromium/components/previews/content/DEPS
index b525d9da6c9..ce31fe01b24 100644
--- a/chromium/components/previews/content/DEPS
+++ b/chromium/components/previews/content/DEPS
@@ -8,7 +8,9 @@ include_rules = [
"+components/previews/core",
"+components/url_matcher",
"+components/variations",
+ "+content/public/browser",
"+content/public/common",
+ "+content/public/test",
"+net",
"+services/network",
]
diff --git a/chromium/components/previews/core/previews_decider.h b/chromium/components/previews/content/previews_decider.h
index 7d1b7c0b6c5..886492ad336 100644
--- a/chromium/components/previews/core/previews_decider.h
+++ b/chromium/components/previews/content/previews_decider.h
@@ -2,14 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_PREVIEWS_CORE_PREVIEWS_DECIDER_H_
-#define COMPONENTS_PREVIEWS_CORE_PREVIEWS_DECIDER_H_
+#ifndef COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_DECIDER_H_
+#define COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_DECIDER_H_
+
#include <string>
#include <vector>
-#include "base/strings/string_piece.h"
#include "components/previews/core/previews_experiments.h"
-#include "net/nqe/effective_connection_type.h"
+
+namespace content {
+class NavigationHandle;
+} // namespace content
class GURL;
@@ -18,30 +21,31 @@ class PreviewsUserData;
class PreviewsDecider {
public:
- // Whether |url| is allowed to show a preview of |type| as can be determined
- // at the start of a navigation (or start of a redirection). This can be
- // further checked at navigation commit time via |ShouldCommitPreview|.
- // Some types of previews will be checked for an applicable network quality
- // threshold - these are client previews that do not have optimization hint
- // support. Previews with optimization hint support can have variable
- // network quality thresholds based on the committed URL. Data Reduction
- // Proxy previews (i.e., LITE_PAGE) perform a network quality check on the
- // server.
+ // Whether the URL for |navigation_handle| is allowed to show a preview of
+ // |type| as can be determined at the start of a navigation (or start of a
+ // redirection). This can be further checked at navigation commit time via
+ // |ShouldCommitPreview|. Some types of previews will be checked for an
+ // applicable network quality threshold - these are client previews that do
+ // not have optimization hint support. Previews with optimization hint support
+ // can have variable network quality thresholds based on the committed URL.
+ // Data Reduction Proxy previews (i.e., LITE_PAGE) perform a network quality
+ // check on the server.
virtual bool ShouldAllowPreviewAtNavigationStart(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
bool is_reload,
PreviewsType type) const = 0;
- // Whether the |committed_url| is allowed to show a preview of |type|.
+ // Whether the URL for |navigation_handle| is allowed to show a preview of
+ // |type|.
virtual bool ShouldCommitPreview(PreviewsUserData* previews_data,
- const GURL& committed_url,
+ content::NavigationHandle* navigation_handle,
PreviewsType type) const = 0;
// Requests that any applicable detailed page hints be loaded. Returns
- // whether client knows that it has hints for the host of |url| (that may
- // need to be loaded from persistent storage).
- virtual bool LoadPageHints(const GURL& url) = 0;
+ // whether client knows that it has hints for the host of the URL for
+ // |navigation_handle| (that may need to be loaded from persistent storage).
+ virtual bool LoadPageHints(content::NavigationHandle* navigation_handle) = 0;
// Whether |url| has loaded resource loading hints and, if it does, populates
// |out_resource_patterns_to_block| with the resource patterns to block.
@@ -61,4 +65,4 @@ class PreviewsDecider {
} // namespace previews
-#endif // COMPONENTS_PREVIEWS_CORE_PREVIEWS_DECIDER_H_
+#endif // COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_DECIDER_H_
diff --git a/chromium/components/previews/content/previews_decider_impl.cc b/chromium/components/previews/content/previews_decider_impl.cc
index 04c52a6ff69..68c8e42f939 100644
--- a/chromium/components/previews/content/previews_decider_impl.cc
+++ b/chromium/components/previews/content/previews_decider_impl.cc
@@ -26,6 +26,7 @@
#include "components/previews/core/previews_experiments.h"
#include "components/previews/core/previews_features.h"
#include "components/previews/core/previews_switches.h"
+#include "content/public/browser/navigation_handle.h"
#include "net/nqe/network_quality_estimator.h"
namespace previews {
@@ -204,9 +205,11 @@ void PreviewsDeciderImpl::SetIgnorePreviewsBlacklistDecision(bool ignored) {
bool PreviewsDeciderImpl::ShouldAllowPreviewAtNavigationStart(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
bool is_reload,
PreviewsType type) const {
+ const GURL url = navigation_handle->GetURL();
+
if (!ShouldConsiderPreview(type, url, previews_data)) {
// Don't capture metrics since preview is either disabled or url is local.
return false;
@@ -215,8 +218,8 @@ bool PreviewsDeciderImpl::ShouldAllowPreviewAtNavigationStart(
bool is_drp_server_preview = (type == PreviewsType::LITE_PAGE);
std::vector<PreviewsEligibilityReason> passed_reasons;
PreviewsEligibilityReason eligibility =
- DeterminePreviewEligibility(previews_data, url, is_reload, type,
- is_drp_server_preview, &passed_reasons);
+ DeterminePreviewEligibility(previews_data, navigation_handle, is_reload,
+ type, is_drp_server_preview, &passed_reasons);
LogPreviewDecisionMade(eligibility, url, clock_->Now(), type,
std::move(passed_reasons), previews_data);
return eligibility == PreviewsEligibilityReason::ALLOWED;
@@ -233,13 +236,14 @@ bool PreviewsDeciderImpl::ShouldConsiderPreview(
PreviewsEligibilityReason PreviewsDeciderImpl::DeterminePreviewEligibility(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
bool is_reload,
PreviewsType type,
bool is_drp_server_preview,
std::vector<PreviewsEligibilityReason>* passed_reasons) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(previews::params::ArePreviewsAllowed());
+ const GURL url = navigation_handle->GetURL();
DCHECK(url.has_host());
DCHECK(previews_data);
@@ -312,39 +316,49 @@ PreviewsEligibilityReason PreviewsDeciderImpl::DeterminePreviewEligibility(
}
passed_reasons->push_back(PreviewsEligibilityReason::DEVICE_OFFLINE);
- if (effective_connection_type_ >
- previews::params::GetECTThresholdForPreview(type)) {
- return PreviewsEligibilityReason::NETWORK_NOT_SLOW;
+ // If the optimization type is not a commit-time preview, determine
+ // the ECT network triggering condition here.
+ if (!CheckECTOnlyAtCommitTime(type)) {
+ if (effective_connection_type_ >
+ previews::params::GetECTThresholdForPreview(type)) {
+ return PreviewsEligibilityReason::NETWORK_NOT_SLOW;
+ }
+ passed_reasons->push_back(PreviewsEligibilityReason::NETWORK_NOT_SLOW);
+
+ if (effective_connection_type_ > params::GetSessionMaxECTThreshold()) {
+ return PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION;
+ }
+ passed_reasons->push_back(
+ PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION);
}
- passed_reasons->push_back(PreviewsEligibilityReason::NETWORK_NOT_SLOW);
}
if (is_reload) {
return PreviewsEligibilityReason::RELOAD_DISALLOWED;
}
-
passed_reasons->push_back(PreviewsEligibilityReason::RELOAD_DISALLOWED);
- // Check server whitelist/blacklist, if provided.
+ // Check optimization hints, if provided.
if (ShouldCheckOptimizationHints(type)) {
if (optimization_guide::features::IsOptimizationHintsEnabled()) {
// Optimization hints are configured, so determine if those hints
// allow the optimization type (as of start-of-navigation time anyway).
- return ShouldAllowPreviewPerOptimizationHints(previews_data, url, type,
- passed_reasons);
+ return ShouldAllowPreviewPerOptimizationHints(
+ previews_data, navigation_handle, type, passed_reasons);
} else if (type == PreviewsType::RESOURCE_LOADING_HINTS ||
type == PreviewsType::NOSCRIPT ||
type == PreviewsType::DEFER_ALL_SCRIPT) {
- return PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER;
+ return PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE;
}
}
return PreviewsEligibilityReason::ALLOWED;
}
-bool PreviewsDeciderImpl::LoadPageHints(const GURL& url) {
+bool PreviewsDeciderImpl::LoadPageHints(
+ content::NavigationHandle* navigation_handle) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return previews_opt_guide_->MaybeLoadOptimizationHints(url,
+ return previews_opt_guide_->MaybeLoadOptimizationHints(navigation_handle,
base::DoNothing());
}
@@ -365,17 +379,20 @@ void PreviewsDeciderImpl::LogHintCacheMatch(const GURL& url,
if (!previews_opt_guide_)
return;
- previews_opt_guide_->LogHintCacheMatch(url, is_committed,
- effective_connection_type_);
+ previews_opt_guide_->LogHintCacheMatch(url, is_committed);
}
-bool PreviewsDeciderImpl::ShouldCommitPreview(PreviewsUserData* previews_data,
- const GURL& committed_url,
- PreviewsType type) const {
+bool PreviewsDeciderImpl::ShouldCommitPreview(
+ PreviewsUserData* previews_data,
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(PreviewsType::NOSCRIPT == type ||
PreviewsType::RESOURCE_LOADING_HINTS == type ||
PreviewsType::DEFER_ALL_SCRIPT == type);
+
+ const GURL committed_url = navigation_handle->GetURL();
+
if (previews_black_list_ && !blacklist_ignored_) {
std::vector<PreviewsEligibilityReason> passed_reasons;
// The blacklist will disallow certain hosts for periods of time based on
@@ -394,7 +411,7 @@ bool PreviewsDeciderImpl::ShouldCommitPreview(PreviewsUserData* previews_data,
optimization_guide::features::IsOptimizationHintsEnabled()) {
std::vector<PreviewsEligibilityReason> passed_reasons;
PreviewsEligibilityReason status = ShouldCommitPreviewPerOptimizationHints(
- previews_data, committed_url, type, &passed_reasons);
+ previews_data, navigation_handle, type, &passed_reasons);
if (status != PreviewsEligibilityReason::ALLOWED) {
LogPreviewDecisionMade(status, committed_url, clock_->Now(), type,
std::move(passed_reasons), previews_data);
@@ -408,7 +425,7 @@ bool PreviewsDeciderImpl::ShouldCommitPreview(PreviewsUserData* previews_data,
PreviewsEligibilityReason
PreviewsDeciderImpl::ShouldAllowPreviewPerOptimizationHints(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
PreviewsType type,
std::vector<PreviewsEligibilityReason>* passed_reasons) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -424,18 +441,26 @@ PreviewsDeciderImpl::ShouldAllowPreviewPerOptimizationHints(
if (type == PreviewsType::LITE_PAGE_REDIRECT) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kIgnoreLitePageRedirectOptimizationBlacklist)) {
+ // Make sure to also check the ECT threshold for the Preview if we are
+ // bypassing the optimization guide.
+ if (effective_connection_type_ >
+ params::GetECTThresholdForPreview(type)) {
+ return PreviewsEligibilityReason::NETWORK_NOT_SLOW;
+ }
return PreviewsEligibilityReason::ALLOWED;
}
- if (!previews_opt_guide_ || !previews_opt_guide_->has_hints())
+ if (!previews_opt_guide_ || !previews_opt_guide_->IsReady())
return PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE;
passed_reasons->push_back(
PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE);
- if (previews_opt_guide_->IsBlacklisted(url, type))
- return PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER;
+ if (!previews_opt_guide_->CanApplyPreview(previews_data, navigation_handle,
+ type)) {
+ return PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE;
+ }
passed_reasons->push_back(
- PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER);
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE);
}
return PreviewsEligibilityReason::ALLOWED;
@@ -444,7 +469,7 @@ PreviewsDeciderImpl::ShouldAllowPreviewPerOptimizationHints(
PreviewsEligibilityReason
PreviewsDeciderImpl::ShouldCommitPreviewPerOptimizationHints(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
PreviewsType type,
std::vector<PreviewsEligibilityReason>* passed_reasons) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -461,22 +486,22 @@ PreviewsDeciderImpl::ShouldCommitPreviewPerOptimizationHints(
return PreviewsEligibilityReason::ALLOWED;
}
- if (!previews_opt_guide_ || !previews_opt_guide_->has_hints())
+ if (!previews_opt_guide_ || !previews_opt_guide_->IsReady())
return PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE;
passed_reasons->push_back(
PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE);
// Check if request URL is whitelisted by the optimization guide.
- net::EffectiveConnectionType ect_threshold =
- net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
- if (!previews_opt_guide_->IsWhitelisted(previews_data, url, type,
- &ect_threshold)) {
- return PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER;
+ if (!previews_opt_guide_->CanApplyPreview(previews_data, navigation_handle,
+ type)) {
+ return PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE;
}
passed_reasons->push_back(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER);
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE);
+
+ // The url is whitelisted, now check some additional cases of the effective
+ // network condition.
- // The url is whitelisted, now check the ECT threshold for it.
// Note: the network quality estimator may sometimes return effective
// connection type as offline when the Android APIs incorrectly return device
// connectivity as null. See https://crbug.com/838969. So, we do not trigger
@@ -500,11 +525,6 @@ PreviewsDeciderImpl::ShouldCommitPreviewPerOptimizationHints(
}
passed_reasons->push_back(PreviewsEligibilityReason::DEVICE_OFFLINE);
- if (ect > ect_threshold) {
- return PreviewsEligibilityReason::NETWORK_NOT_SLOW;
- }
- passed_reasons->push_back(PreviewsEligibilityReason::NETWORK_NOT_SLOW);
-
if (ect > params::GetSessionMaxECTThreshold()) {
return PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION;
}
diff --git a/chromium/components/previews/content/previews_decider_impl.h b/chromium/components/previews/content/previews_decider_impl.h
index f99311fe1ab..c2b073f82e6 100644
--- a/chromium/components/previews/content/previews_decider_impl.h
+++ b/chromium/components/previews/content/previews_decider_impl.h
@@ -20,9 +20,9 @@
#include "base/time/time.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h"
+#include "components/previews/content/previews_decider.h"
#include "components/previews/content/previews_optimization_guide.h"
#include "components/previews/core/previews_black_list.h"
-#include "components/previews/core/previews_decider.h"
#include "components/previews/core/previews_experiments.h"
#include "components/previews/core/previews_logger.h"
#include "net/nqe/effective_connection_type.h"
@@ -36,6 +36,10 @@ namespace blacklist {
class OptOutStore;
}
+namespace content {
+class NavigationHandle;
+}
+
namespace previews {
class PreviewsUIService;
@@ -106,19 +110,20 @@ class PreviewsDeciderImpl : public PreviewsDecider,
PreviewsBlackList* black_list() const { return previews_black_list_.get(); }
// PreviewsDecider implementation:
- bool ShouldAllowPreviewAtNavigationStart(PreviewsUserData* previews_data,
- const GURL& url,
- bool is_reload,
- PreviewsType type) const override;
+ bool ShouldAllowPreviewAtNavigationStart(
+ PreviewsUserData* previews_data,
+ content::NavigationHandle* navigation_handle,
+ bool is_reload,
+ PreviewsType type) const override;
bool ShouldCommitPreview(PreviewsUserData* previews_data,
- const GURL& committed_url,
+ content::NavigationHandle* navigation_handle,
PreviewsType type) const override;
// Set whether to ignore the long term blacklist rules for server previews.
void SetIgnoreLongTermBlackListForServerPreviews(
bool ignore_long_term_blacklist_for_server_previews);
- bool LoadPageHints(const GURL& url) override;
+ bool LoadPageHints(content::NavigationHandle* navigation_handle) override;
bool GetResourceLoadingHints(
const GURL& url,
@@ -157,7 +162,7 @@ class PreviewsDeciderImpl : public PreviewsDecider,
// Determines the eligibility of the preview |type| for |url|.
PreviewsEligibilityReason DeterminePreviewEligibility(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
bool is_reload,
PreviewsType type,
bool is_drp_server_preview,
@@ -169,7 +174,7 @@ class PreviewsDeciderImpl : public PreviewsDecider,
// to deny the preview for consideration.
PreviewsEligibilityReason ShouldAllowPreviewPerOptimizationHints(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
PreviewsType type,
std::vector<PreviewsEligibilityReason>* passed_reasons) const;
@@ -178,7 +183,7 @@ class PreviewsDeciderImpl : public PreviewsDecider,
// navigation URL against any specific hint details.
PreviewsEligibilityReason ShouldCommitPreviewPerOptimizationHints(
PreviewsUserData* previews_data,
- const GURL& url,
+ content::NavigationHandle* navigation_handle,
PreviewsType type,
std::vector<PreviewsEligibilityReason>* passed_reasons) const;
diff --git a/chromium/components/previews/content/previews_decider_impl_unittest.cc b/chromium/components/previews/content/previews_decider_impl_unittest.cc
index c1651508faf..38ae4312742 100644
--- a/chromium/components/previews/content/previews_decider_impl_unittest.cc
+++ b/chromium/components/previews/content/previews_decider_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <map>
#include <memory>
#include <string>
+#include <unordered_set>
#include <utility>
#include <vector>
@@ -26,8 +27,8 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
@@ -39,6 +40,7 @@
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/optimization_guide/hint_cache_store.h"
#include "components/optimization_guide/optimization_guide_features.h"
+#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/optimization_guide/optimization_guide_service.h"
#include "components/optimization_guide/proto_database_provider_test_base.h"
#include "components/optimization_guide/top_host_provider.h"
@@ -52,6 +54,7 @@
#include "components/previews/core/previews_logger.h"
#include "components/previews/core/previews_switches.h"
#include "components/variations/variations_associated_data.h"
+#include "content/public/test/mock_navigation_handle.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -165,38 +168,46 @@ class TestTopHostProvider : public optimization_guide::TopHostProvider {
// Stub class of PreviewsOptimizationGuide to control IsWhitelisted and
// IsBlacklisted outcomes when testing PreviewsDeciderImpl.
-class TestPreviewsOptimizationGuide : public PreviewsOptimizationGuide {
+class TestPreviewsOptimizationGuide
+ : public PreviewsOptimizationGuide,
+ public network::NetworkQualityTracker::EffectiveConnectionTypeObserver {
public:
TestPreviewsOptimizationGuide(
- optimization_guide::OptimizationGuideService* optimization_guide_service,
- const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
- const base::FilePath& test_path,
- PrefService* pref_service,
- leveldb_proto::ProtoDatabaseProvider* database_provider,
- optimization_guide::TopHostProvider* optimization_guide_top_host_provider,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
- : PreviewsOptimizationGuide(optimization_guide_service,
- ui_task_runner,
- background_task_runner,
- test_path,
- pref_service,
- database_provider,
- optimization_guide_top_host_provider,
- url_loader_factory) {}
- ~TestPreviewsOptimizationGuide() override {}
+ network::NetworkQualityTracker* network_quality_tracker)
+ : network_quality_tracker_(network_quality_tracker) {
+ network_quality_tracker_->AddEffectiveConnectionTypeObserver(this);
+ }
+
+ ~TestPreviewsOptimizationGuide() override {
+ network_quality_tracker_->RemoveEffectiveConnectionTypeObserver(this);
+ }
+
+ bool IsReady() const override { return is_ready_; }
+
+ void SetIsReady(bool is_ready) { is_ready_ = is_ready; }
+
+ void OnEffectiveConnectionTypeChanged(
+ net::EffectiveConnectionType ect) override {
+ current_ect_ = ect;
+ }
// PreviewsOptimizationGuide:
- bool IsWhitelisted(
- PreviewsUserData* previews_user_data,
- const GURL& url,
- PreviewsType type,
- net::EffectiveConnectionType* ect_threshold) const override {
+ bool CanApplyPreview(PreviewsUserData* previews_user_data,
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) override {
EXPECT_TRUE(type == PreviewsType::NOSCRIPT ||
type == PreviewsType::RESOURCE_LOADING_HINTS ||
- type == PreviewsType::DEFER_ALL_SCRIPT);
+ type == PreviewsType::DEFER_ALL_SCRIPT ||
+ type == PreviewsType::LITE_PAGE_REDIRECT);
+
// Use default ect trigger threshold for the preview type.
- *ect_threshold = previews::params::GetECTThresholdForPreview(type);
+ if (current_ect_ > previews::params::GetECTThresholdForPreview(type))
+ return false;
+
+ if (type == PreviewsType::LITE_PAGE_REDIRECT)
+ return !IsBlacklisted(navigation_handle, type);
+
+ const GURL url = navigation_handle->GetURL();
if (type == PreviewsType::NOSCRIPT) {
return url.host().compare("whitelisted.example.com") == 0 ||
url.host().compare("noscript_only_whitelisted.example.com") == 0;
@@ -208,14 +219,42 @@ class TestPreviewsOptimizationGuide : public PreviewsOptimizationGuide {
return false;
}
- // PreviewsOptimizationGuide:
- bool IsBlacklisted(const GURL& url, PreviewsType type) const override {
+ // Returns whether the URL associated with |navigation_handle| should be
+ // blacklisted from |type|.
+ bool IsBlacklisted(content::NavigationHandle* navigation_handle,
+ PreviewsType type) const {
EXPECT_TRUE(type == PreviewsType::LITE_PAGE_REDIRECT);
+ const GURL url = navigation_handle->GetURL();
if (type == PreviewsType::LITE_PAGE_REDIRECT) {
return url.host().compare("blacklisted.example.com") == 0;
}
return false;
}
+
+ // PreviewsOptimizationGuide:
+ bool MaybeLoadOptimizationHints(content::NavigationHandle* navigation_handle,
+ base::OnceClosure callback) override {
+ return false;
+ }
+
+ // PreviewsOptimizationGuide:
+ bool GetResourceLoadingHints(
+ const GURL& url,
+ std::vector<std::string>* out_resource_patterns_to_block) override {
+ return false;
+ }
+
+ // PreviewsOptimizationGuide:
+ void LogHintCacheMatch(const GURL& url, bool is_committed) const override {}
+
+ // PreviewsOptimizationGuide:
+ void ClearFetchedHints() override {}
+
+ private:
+ network::NetworkQualityTracker* network_quality_tracker_;
+ bool is_ready_ = false;
+ net::EffectiveConnectionType current_ect_ =
+ net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
};
// Stub class of PreviewsUIService to test logging functionalities in
@@ -352,7 +391,8 @@ class TestPreviewsUIService : public PreviewsUIService {
class TestPreviewsDeciderImpl : public PreviewsDeciderImpl {
public:
- TestPreviewsDeciderImpl(base::Clock* clock) : PreviewsDeciderImpl(clock) {}
+ explicit TestPreviewsDeciderImpl(base::Clock* clock)
+ : PreviewsDeciderImpl(clock) {}
~TestPreviewsDeciderImpl() override {}
// Expose the injecting blacklist method from PreviewsDeciderImpl, and inject
@@ -396,7 +436,7 @@ class PreviewsDeciderImplTest
: field_trial_list_(nullptr),
previews_decider_impl_(nullptr),
optimization_guide_service_(
- scoped_task_environment_.GetMainThreadTaskRunner()) {
+ task_environment_.GetMainThreadTaskRunner()) {
clock_.SetNow(base::Time::Now());
network_quality_tracker_.ReportEffectiveConnectionTypeForTesting(
@@ -434,15 +474,14 @@ class PreviewsDeciderImplTest
std::make_unique<TestPreviewsDeciderImpl>(&clock_);
previews_decider_impl_ = previews_decider_impl.get();
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
+ optimization_guide::prefs::RegisterProfilePrefs(pref_service_->registry());
+ std::unique_ptr<TestPreviewsOptimizationGuide> previews_opt_guide =
+ std::make_unique<TestPreviewsOptimizationGuide>(
+ &network_quality_tracker_);
+ previews_opt_guide_ = previews_opt_guide.get();
ui_service_.reset(new TestPreviewsUIService(
std::move(previews_decider_impl), std::make_unique<TestOptOutStore>(),
- std::make_unique<TestPreviewsOptimizationGuide>(
- &optimization_guide_service_,
- scoped_task_environment_.GetMainThreadTaskRunner(),
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
- temp_dir_.GetPath(), pref_service_.get(), db_provider_.get(),
- &optimization_guide_top_host_provider_, url_loader_factory_),
+ std::move(previews_opt_guide),
base::BindRepeating(&IsPreviewFieldTrialEnabled),
std::make_unique<PreviewsLogger>(), std::move(allowed_types),
&network_quality_tracker_));
@@ -450,17 +489,12 @@ class PreviewsDeciderImplTest
void InitializeUIService() {
InitializeUIServiceWithoutWaitingForBlackList();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
void InitializeOptimizationGuideHints() {
- std::unique_ptr<optimization_guide::proto::Configuration> config =
- std::make_unique<optimization_guide::proto::Configuration>();
- std::unique_ptr<PreviewsHints> hints =
- PreviewsHints::CreateFromHintsConfiguration(std::move(config), nullptr);
- previews_decider_impl()->previews_opt_guide()->UpdateHints(
- base::DoNothing(), std::move(hints));
+ previews_opt_guide_->SetIsReady(true);
}
TestPreviewsDeciderImpl* previews_decider_impl() {
@@ -479,10 +513,11 @@ class PreviewsDeciderImplTest
base::SimpleTestClock clock_;
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::FieldTrialList field_trial_list_;
TestPreviewsDeciderImpl* previews_decider_impl_;
optimization_guide::OptimizationGuideService optimization_guide_service_;
+ TestPreviewsOptimizationGuide* previews_opt_guide_;
TestTopHostProvider optimization_guide_top_host_provider_;
std::unique_ptr<TestPreviewsUIService> ui_service_;
network::TestNetworkQualityTracker network_quality_tracker_;
@@ -500,9 +535,10 @@ TEST_F(PreviewsDeciderImplTest, AllPreviewsDisabledByFeature) {
PreviewsUserData user_data(kDefaultPageId);
PreviewsUserData user_data2(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data2, GURL("https://www.google.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data2, &navigation_handle, false, PreviewsType::NOSCRIPT));
}
TEST_F(PreviewsDeciderImplTest, TestDisallowBasicAuthentication) {
@@ -514,9 +550,10 @@ TEST_F(PreviewsDeciderImplTest, TestDisallowBasicAuthentication) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://user:pass@www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://user:pass@www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason",
static_cast<int>(PreviewsEligibilityReason::URL_HAS_BASIC_AUTH), 1);
@@ -535,13 +572,14 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
InitializeUIServiceWithoutWaitingForBlackList();
// The blacklist is not loaded yet.
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason",
static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
@@ -561,8 +599,7 @@ TEST_F(PreviewsDeciderImplTest,
previews_decider_impl()->ClearBlackList(now, now);
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
@@ -581,6 +618,8 @@ TEST_F(PreviewsDeciderImplTest, MAYBE_TestSetBlacklistBoolDueToBlackListState) {
scoped_feature_list.InitAndEnableFeature(features::kPreviews);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
InitializeUIServiceWithoutWaitingForBlackList();
@@ -590,8 +629,7 @@ TEST_F(PreviewsDeciderImplTest, MAYBE_TestSetBlacklistBoolDueToBlackListState) {
EXPECT_FALSE(user_data.black_listed_for_lite_page());
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
EXPECT_TRUE(user_data.black_listed_for_lite_page());
}
@@ -602,13 +640,14 @@ TEST_F(PreviewsDeciderImplTest,
InitializeUIService();
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE),
@@ -625,13 +664,15 @@ TEST_F(PreviewsDeciderImplTest, TestAllowLitePageWhenNetworkQualityFast) {
InitializeUIService();
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
+
// LitePage check NQE on its own.
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
base::HistogramTester histogram_tester;
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LitePage",
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
@@ -643,12 +684,13 @@ TEST_F(PreviewsDeciderImplTest, TestDisallowOfflineWhenNetworkQualityFast) {
InitializeUIService();
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_3G);
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
@@ -660,12 +702,13 @@ TEST_F(PreviewsDeciderImplTest, TestDisallowOfflineWhenNetworkOffline) {
InitializeUIService();
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::DEVICE_OFFLINE), 1);
@@ -679,10 +722,12 @@ TEST_F(PreviewsDeciderImplTest, TestDisallowOfflineOnReload) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), true, PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, true, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason",
static_cast<int>(PreviewsEligibilityReason::RELOAD_DISALLOWED), 1);
@@ -700,10 +745,12 @@ TEST_F(PreviewsDeciderImplTest, TestDisallowOfflineOnReloadWithExperiment) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), true, PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, true, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason",
static_cast<int>(PreviewsEligibilityReason::RELOAD_DISALLOWED), 1);
@@ -731,11 +778,12 @@ TEST_F(PreviewsDeciderImplTest, TestAllowOffline) {
ReportEffectiveConnectionType(test.effective_connection_type);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
EXPECT_EQ(test.expected_offline_allowed,
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE))
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE))
<< " effective_connection_type=" << test.effective_connection_type;
if (test.expected_offline_allowed) {
histogram_tester.ExpectUniqueSample(
@@ -760,10 +808,11 @@ TEST_F(PreviewsDeciderImplTest, OfflineDisallowedWhenFeatureDisabled) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.Offline", 0);
}
@@ -777,10 +826,11 @@ TEST_F(PreviewsDeciderImplTest,
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE),
@@ -799,9 +849,10 @@ TEST_F(PreviewsDeciderImplTest, OfflineDisallowedWhenNetworkFast) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
@@ -818,8 +869,10 @@ TEST_F(PreviewsDeciderImplTest, MissingHostDisallowed) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("file:///sdcard"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("file:///sdcard"), false, PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
}
TEST_F(PreviewsDeciderImplTest, OfflineDisallowedOnReload) {
@@ -833,10 +886,12 @@ TEST_F(PreviewsDeciderImplTest, OfflineDisallowedOnReload) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), true, PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, true, PreviewsType::OFFLINE));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.Offline",
static_cast<int>(PreviewsEligibilityReason::RELOAD_DISALLOWED), 1);
@@ -849,13 +904,14 @@ TEST_F(PreviewsDeciderImplTest, NoScriptFeatureDefaultBehavior) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
#if defined(OS_ANDROID)
// Enabled by default on Android. NOSCRIPT always allowed at navigation start
// to handle asynchronous loading of page hints; non-whitelisted ones are
// later blocked on commit.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 1);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.NoScript",
@@ -863,8 +919,7 @@ TEST_F(PreviewsDeciderImplTest, NoScriptFeatureDefaultBehavior) {
#else // !defined(OS_ANDROID)
// Disabled by default on non-Android.
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
#endif // defined(OS_ANDROID)
}
@@ -883,14 +938,15 @@ TEST_F(PreviewsDeciderImplTest, NoScriptNotAllowedWithoutOptimizationHints) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
EXPECT_EQ(test_ect, user_data.navigation_ect());
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE),
1);
}
}
@@ -907,16 +963,18 @@ TEST_F(PreviewsDeciderImplTest, NoScriptAllowedByFeatureWithWhitelist) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
// First verify preview allowed for non-whitelisted url; they're always
// allowed at navigation start to enable asynchronous loading of page hints.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
// Now verify preview allowed for whitelisted url.
+ content::MockNavigationHandle whitelisted_navigation_handle;
+ whitelisted_navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.NoScript",
@@ -934,27 +992,30 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
// First verify not allowed for non-whitelisted url.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://www.google.com"), PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
}
// Now verify preview for whitelisted url.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
// Expect no eligibility logging.
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
@@ -962,16 +1023,19 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
// Verify preview not allowed for whitelisted url when network is not slow.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_3G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_3G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
- static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
+ static_cast<int>(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
+ 1);
}
// Verify preview not allowed for whitelisted url for unknown network quality.
@@ -979,10 +1043,11 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
@@ -993,16 +1058,17 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
// Verify preview not allowed for session limited ECT threshold.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::test::ScopedFeatureList nested_scoped_list;
nested_scoped_list.InitAndEnableFeatureWithParameters(
features::kSlowPageTriggering,
{{"session_max_ect_trigger", "Slow-2G"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
@@ -1021,10 +1087,11 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
{{"session_max_ect_trigger", "Slow-2G"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
@@ -1043,10 +1110,11 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
{{"session_max_ect_trigger", "Slow-2G"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
}
@@ -1061,14 +1129,17 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
{{"session_max_ect_trigger", "Slow-2G"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.NoScript",
- static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
+ static_cast<int>(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
+ 1);
}
// Verify preview allowed for session when navigation ECT is unknown but max
@@ -1080,10 +1151,11 @@ TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
features::kSlowPageTriggering, {{"session_max_ect_trigger", "4G"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
}
@@ -1099,9 +1171,10 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE_REDIRECT));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE_REDIRECT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason",
@@ -1123,27 +1196,33 @@ TEST_F(PreviewsDeciderImplTest, LitePageRedirectDisallowedByServerBlacklist) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
// First verify preview allowed for non-whitelisted url.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE_REDIRECT));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE_REDIRECT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LitePageRedirect",
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
// Now verify no preview for blacklisted url.
+ content::MockNavigationHandle blacklisted_navigation_handle;
+ blacklisted_navigation_handle.set_url(
+ GURL("https://blacklisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://blacklisted.example.com"), false,
+ &user_data, &blacklisted_navigation_handle, false,
PreviewsType::LITE_PAGE_REDIRECT));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason",
- static_cast<int>(PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER),
+ static_cast<int>(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.LitePageRedirect",
- static_cast<int>(PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER),
+ static_cast<int>(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
}
@@ -1167,18 +1246,21 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
// First verify preview allowed for non-whitelisted url.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE_REDIRECT));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE_REDIRECT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LitePageRedirect",
static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
+ content::MockNavigationHandle blacklisted_navigation_handle;
+ blacklisted_navigation_handle.set_url(
+ GURL("https://blacklisted.example.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://blacklisted.example.com"), false,
- PreviewsType::LITE_PAGE_REDIRECT));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE_REDIRECT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.LitePageRedirect",
@@ -1197,26 +1279,25 @@ TEST_F(PreviewsDeciderImplTest, OptimizationGuidePreviewsAllowedWithoutHints) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
// NoScript is allowed before commit without hints.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
// ResourceLoading is allowed before commit without hints.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
+ &user_data, &navigation_handle, false,
PreviewsType::RESOURCE_LOADING_HINTS));
// DeferAllScript is allowed before commit without hints.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
// LitePageRedirect is not allowed before commit without hints.
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::LITE_PAGE_REDIRECT));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE_REDIRECT));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.LitePageRedirect",
static_cast<int>(
@@ -1226,17 +1307,14 @@ TEST_F(PreviewsDeciderImplTest, OptimizationGuidePreviewsAllowedWithoutHints) {
// Load hints and make sure everything is allowed.
InitializeOptimizationGuideHints();
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::NOSCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
+ &user_data, &navigation_handle, false,
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::LITE_PAGE_REDIRECT));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE_REDIRECT));
}
TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsAllowedByDefault) {
@@ -1249,6 +1327,8 @@ TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsAllowedByDefault) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
#if defined(OS_ANDROID)
bool expected = true;
@@ -1257,7 +1337,7 @@ TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsAllowedByDefault) {
#endif // defined(OS_ANDROID)
EXPECT_EQ(expected,
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
+ &user_data, &navigation_handle, false,
PreviewsType::RESOURCE_LOADING_HINTS));
}
@@ -1271,18 +1351,20 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
+ &user_data, &navigation_handle, false,
PreviewsType::RESOURCE_LOADING_HINTS));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE),
1);
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE),
1);
}
@@ -1303,10 +1385,12 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
// Check whitelisted URL.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
+ &user_data, &navigation_handle, false,
PreviewsType::RESOURCE_LOADING_HINTS));
EXPECT_EQ(test_ect, user_data.navigation_ect());
histogram_tester.ExpectUniqueSample(
@@ -1327,10 +1411,12 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
// Verify preview allowed initially for url without known hints.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
+ &user_data, &navigation_handle, false,
PreviewsType::RESOURCE_LOADING_HINTS));
histogram_tester.ExpectBucketCount(
@@ -1349,28 +1435,30 @@ TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsCommitTimeWhitelistCheck) {
// First verify not allowed for non-whitelisted url.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://www.google.com"),
- PreviewsType::RESOURCE_LOADING_HINTS));
+ &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.ResourceLoadingHints",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
}
// Now verify preview for whitelisted url.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::RESOURCE_LOADING_HINTS));
+ &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
// Expect no eligibility logging.
histogram_tester.ExpectTotalCount(
@@ -1379,26 +1467,30 @@ TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsCommitTimeWhitelistCheck) {
// Verify preview not allowed for whitelisted url when network is not slow.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_4G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::RESOURCE_LOADING_HINTS));
+ &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.ResourceLoadingHints",
- static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
+ static_cast<int>(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
+ 1);
}
// Verify preview not allowed for whitelisted url for offline network quality.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::RESOURCE_LOADING_HINTS));
+ &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.ResourceLoadingHints",
@@ -1407,16 +1499,17 @@ TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsCommitTimeWhitelistCheck) {
// Verify preview not allowed for session limited ECT threshold.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::test::ScopedFeatureList nested_scoped_list;
nested_scoped_list.InitAndEnableFeatureWithParameters(
features::kSlowPageTriggering,
{{"session_max_ect_trigger", "Offline"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::RESOURCE_LOADING_HINTS));
+ &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.ResourceLoadingHints",
@@ -1436,10 +1529,11 @@ TEST_F(PreviewsDeciderImplTest, DeferAllScriptNotAllowedByDefault) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
}
TEST_F(PreviewsDeciderImplTest,
@@ -1452,18 +1546,19 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE),
1);
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.DeferAllScript",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::OPTIMIZATION_HINTS_NOT_AVAILABLE),
1);
}
@@ -1483,11 +1578,12 @@ TEST_F(PreviewsDeciderImplTest, DeferAllScriptAllowedByFeatureAndWhitelist) {
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
// Check whitelisted URL.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://whitelisted.example.com"), false,
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
EXPECT_EQ(test_ect, user_data.navigation_ect());
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.DeferAllScript",
@@ -1507,11 +1603,12 @@ TEST_F(PreviewsDeciderImplTest,
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
// Verify preview allowed initially for url without known hints.
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
histogram_tester.ExpectBucketCount(
"Previews.EligibilityReason.DeferAllScript",
@@ -1529,28 +1626,30 @@ TEST_F(PreviewsDeciderImplTest, DeferAllScriptCommitTimeWhitelistCheck) {
// First verify not allowed for non-whitelisted url.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://www.google.com"),
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.DeferAllScript",
static_cast<int>(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER),
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
1);
}
// Now verify preview for whitelisted url.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
// Expect no eligibility logging.
histogram_tester.ExpectTotalCount(
@@ -1559,26 +1658,30 @@ TEST_F(PreviewsDeciderImplTest, DeferAllScriptCommitTimeWhitelistCheck) {
// Verify preview not allowed for whitelisted url when network is not slow.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_4G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.DeferAllScript",
- static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
+ static_cast<int>(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE),
+ 1);
}
// Verify preview not allowed for whitelisted url for offline network quality.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.DeferAllScript",
@@ -1587,16 +1690,17 @@ TEST_F(PreviewsDeciderImplTest, DeferAllScriptCommitTimeWhitelistCheck) {
// Verify preview not allowed for session limited ECT threshold.
{
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
base::test::ScopedFeatureList nested_scoped_list;
nested_scoped_list.InitAndEnableFeatureWithParameters(
features::kSlowPageTriggering,
{{"session_max_ect_trigger", "Offline"}});
base::HistogramTester histogram_tester;
PreviewsUserData user_data(kDefaultPageId);
- user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("https://whitelisted.example.com"),
- PreviewsType::DEFER_ALL_SCRIPT));
+ &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
histogram_tester.ExpectUniqueSample(
"Previews.EligibilityReason.DeferAllScript",
@@ -1678,8 +1782,10 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlacklistNotAvailable) {
previews_decider_impl()->InjectTestBlacklist(nullptr /* blacklist */);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), false, expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
EXPECT_THAT(ui_service()->decision_reasons(),
@@ -1713,8 +1819,10 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlacklistStatusesDefault) {
previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), false, expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
// Check for all decision upto current decision is logged.
@@ -1735,9 +1843,11 @@ TEST_F(PreviewsDeciderImplTest, ShouldCommitPreviewBlacklistStatuses) {
InitializeUIService();
auto expected_type = PreviewsType::NOSCRIPT;
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
// First verify URL is allowed for no blacklist status.
EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("http://www.google.com"), expected_type));
+ &user_data, &navigation_handle, expected_type));
PreviewsEligibilityReason expected_reasons[] = {
PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
@@ -1756,8 +1866,10 @@ TEST_F(PreviewsDeciderImplTest, ShouldCommitPreviewBlacklistStatuses) {
previews_decider_impl());
previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
- &user_data, GURL("http://www.google.com"), expected_type));
+ &user_data, &navigation_handle, expected_type));
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
// Check for all decision upto current decision is logged.
@@ -1794,8 +1906,10 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlacklistStatusesIgnore) {
previews_decider_impl());
previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), false, expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
@@ -1826,9 +1940,10 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeMediaSuffixesAreExcluded) {
previews_decider_impl());
previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com/video.mp4"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com/video.mp4"), false,
- expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
@@ -1849,15 +1964,15 @@ TEST_F(PreviewsDeciderImplTest, IgnoreFlagDoesNotCheckBlacklist) {
previews_decider_impl()->SetIgnorePreviewsBlacklistDecision(
true /* ignored */);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
previews_decider_impl()->AddPreviewReload();
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
}
TEST_F(PreviewsDeciderImplTest, ReloadsTriggerFiveMinuteRule) {
@@ -1868,9 +1983,10 @@ TEST_F(PreviewsDeciderImplTest, ReloadsTriggerFiveMinuteRule) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
previews_decider_impl()->AddPreviewNavigation(
GURL("http://wwww.somedomain.com"), false, PreviewsType::OFFLINE, 1);
@@ -1878,16 +1994,14 @@ TEST_F(PreviewsDeciderImplTest, ReloadsTriggerFiveMinuteRule) {
previews_decider_impl()->AddPreviewReload();
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
ui_service()->decision_reasons().back());
clock_.Advance(base::TimeDelta::FromMinutes(6));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
EXPECT_THAT(
ui_service()->decision_passed_reasons().back(),
::testing::Contains(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT));
@@ -1901,7 +2015,6 @@ TEST_F(PreviewsDeciderImplTest,
optimization_guide::features::kOptimizationHints},
{});
InitializeUIService();
- InitializeOptimizationGuideHints();
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
@@ -1924,8 +2037,10 @@ TEST_F(PreviewsDeciderImplTest,
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), false, expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
@@ -1970,8 +2085,10 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeNetworkNotSlow) {
PreviewsEligibilityReason::DEVICE_OFFLINE,
};
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), false, expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
EXPECT_THAT(ui_service()->decision_reasons(),
@@ -1998,6 +2115,8 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeReloadDisallowed) {
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
auto expected_reason = PreviewsEligibilityReason::RELOAD_DISALLOWED;
auto expected_type = PreviewsType::OFFLINE;
@@ -2013,10 +2132,11 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeReloadDisallowed) {
PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE,
PreviewsEligibilityReason::DEVICE_OFFLINE,
PreviewsEligibilityReason::NETWORK_NOT_SLOW,
+ PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION,
};
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), true, expected_type);
+ &user_data, &navigation_handle, true, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
@@ -2050,10 +2170,11 @@ TEST_F(PreviewsDeciderImplTest, IgnoreBlacklistEnabledViaFlag) {
previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
auto expected_reason = PreviewsEligibilityReason::ALLOWED;
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::OFFLINE));
+ &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
base::RunLoop().RunUntilIdle();
EXPECT_THAT(ui_service()->decision_reasons(),
@@ -2088,11 +2209,14 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeAllowClientPreviewsWithECT) {
PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE,
PreviewsEligibilityReason::DEVICE_OFFLINE,
PreviewsEligibilityReason::NETWORK_NOT_SLOW,
+ PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION,
PreviewsEligibilityReason::RELOAD_DISALLOWED,
};
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://www.google.com"), false, expected_type);
+ &user_data, &navigation_handle, false, expected_type);
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
@@ -2116,7 +2240,6 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeAllowHintPreviewWithoutECT) {
optimization_guide::features::kOptimizationHints},
{});
InitializeUIService();
- InitializeOptimizationGuideHints();
std::unique_ptr<TestPreviewsBlackList> blacklist =
std::make_unique<TestPreviewsBlackList>(
@@ -2140,9 +2263,10 @@ TEST_F(PreviewsDeciderImplTest, LogDecisionMadeAllowHintPreviewWithoutECT) {
PreviewsEligibilityReason::RELOAD_DISALLOWED,
};
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whitelisted.example.com"));
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("http://whitelisted.example.com"), false,
- expected_type));
+ &user_data, &navigation_handle, false, expected_type));
base::RunLoop().RunUntilIdle();
// Testing correct log method is called.
@@ -2234,16 +2358,16 @@ TEST_F(PreviewsDeciderImplTest, TestIgnoreLongTermRule) {
// DataReductionProxy LitePage checks NQE on their own.
ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_3G);
PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://www.google.com"));
base::HistogramTester histogram_tester;
previews_decider_impl()->SetIgnoreLongTermBlackListForServerPreviews(false);
EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
previews_decider_impl()->SetIgnoreLongTermBlackListForServerPreviews(true);
EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
- &user_data, GURL("https://www.google.com"), false,
- PreviewsType::LITE_PAGE));
+ &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
}
} // namespace
diff --git a/chromium/components/previews/content/previews_hints.cc b/chromium/components/previews/content/previews_hints.cc
index 6b72e76037c..21612a21f18 100644
--- a/chromium/components/previews/content/previews_hints.cc
+++ b/chromium/components/previews/content/previews_hints.cc
@@ -5,6 +5,7 @@
#include "components/previews/content/previews_hints.h"
#include <unordered_set>
+#include <utility>
#include "base/files/file.h"
#include "base/files/file_util.h"
@@ -122,30 +123,6 @@ bool IsEnabledOptimizationType(
}
}
-net::EffectiveConnectionType ConvertProtoEffectiveConnectionType(
- optimization_guide::proto::EffectiveConnectionType proto_ect) {
- switch (proto_ect) {
- case optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_UNKNOWN:
- return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
- case optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_OFFLINE:
- return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE;
- case optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_SLOW_2G:
- return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
- case optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_2G:
- return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G;
- case optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_3G:
- return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G;
- case optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_4G:
- return net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_4G;
- }
-}
-
} // namespace
PreviewsHints::PreviewsHints(
@@ -241,8 +218,7 @@ void PreviewsHints::ParseOptimizationFilters(
ConvertProtoOptimizationTypeToPreviewsType(
blacklist.optimization_type());
if (previews_type == PreviewsType::LITE_PAGE_REDIRECT &&
- previews::params::IsLitePageServerPreviewsEnabled() &&
- blacklist.has_bloom_filter()) {
+ previews::params::IsLitePageServerPreviewsEnabled()) {
RecordOptimizationFilterStatus(
blacklist.optimization_type(),
optimization_guide::OptimizationFilterStatus::
@@ -256,46 +232,11 @@ void PreviewsHints::ParseOptimizationFilters(
kFailedServerBlacklistDuplicateConfig);
continue;
}
- const auto& bloom_filter_proto = blacklist.bloom_filter();
- DCHECK_GT(bloom_filter_proto.num_hash_functions(), 0u);
- DCHECK_GT(bloom_filter_proto.num_bits(), 0u);
- DCHECK(bloom_filter_proto.has_data());
- if (!bloom_filter_proto.has_data() ||
- bloom_filter_proto.num_bits() <= 0 ||
- bloom_filter_proto.num_bits() >
- bloom_filter_proto.data().size() * 8) {
- DLOG(ERROR) << "Bloom filter config issue";
- RecordOptimizationFilterStatus(
- blacklist.optimization_type(),
- optimization_guide::OptimizationFilterStatus::
- kFailedServerBlacklistBadConfig);
- continue;
- }
- if (static_cast<int>(bloom_filter_proto.num_bits()) >
- previews::params::
- LitePageRedirectPreviewMaxServerBlacklistByteSize() *
- 8) {
- DLOG(ERROR) << "Bloom filter data exceeds maximum size of "
- << previews::params::
- LitePageRedirectPreviewMaxServerBlacklistByteSize()
- << " bytes";
- RecordOptimizationFilterStatus(
- blacklist.optimization_type(),
- optimization_guide::OptimizationFilterStatus::
- kFailedServerBlacklistTooBig);
- continue;
- }
- std::unique_ptr<optimization_guide::BloomFilter> bloom_filter =
- std::make_unique<optimization_guide::BloomFilter>(
- bloom_filter_proto.num_hash_functions(),
- bloom_filter_proto.num_bits(), bloom_filter_proto.data());
+
+ optimization_guide::OptimizationFilterStatus status;
lite_page_redirect_blacklist_ =
- std::make_unique<optimization_guide::HostFilter>(
- std::move(bloom_filter));
- RecordOptimizationFilterStatus(
- blacklist.optimization_type(),
- optimization_guide::OptimizationFilterStatus::
- kCreatedServerBlacklist);
+ optimization_guide::ProcessOptimizationFilter(blacklist, &status);
+ RecordOptimizationFilterStatus(blacklist.optimization_type(), status);
}
}
}
@@ -353,13 +294,17 @@ bool PreviewsHints::IsWhitelisted(
if (optimization.has_previews_metadata()) {
*out_inflation_percent =
optimization.previews_metadata().inflation_percent();
- *out_ect_threshold = ConvertProtoEffectiveConnectionType(
- optimization.previews_metadata().max_ect_trigger());
+ if (out_ect_threshold) {
+ *out_ect_threshold =
+ optimization_guide::ConvertProtoEffectiveConnectionType(
+ optimization.previews_metadata().max_ect_trigger());
+ }
} else {
*out_inflation_percent = optimization.inflation_percent();
- if (matched_page_hint->has_max_ect_trigger()) {
- *out_ect_threshold = ConvertProtoEffectiveConnectionType(
- matched_page_hint->max_ect_trigger());
+ if (out_ect_threshold && matched_page_hint->has_max_ect_trigger()) {
+ *out_ect_threshold =
+ optimization_guide::ConvertProtoEffectiveConnectionType(
+ matched_page_hint->max_ect_trigger());
}
}
@@ -387,7 +332,7 @@ bool PreviewsHints::IsBlacklisted(const GURL& url, PreviewsType type) const {
return true;
}
- return lite_page_redirect_blacklist_->ContainsHostSuffix(url);
+ return lite_page_redirect_blacklist_->Matches(url);
}
return false;
@@ -460,31 +405,26 @@ bool PreviewsHints::GetResourceLoadingHints(
}
void PreviewsHints::LogHintCacheMatch(const GURL& url,
- bool is_committed,
- net::EffectiveConnectionType ect) const {
+ bool is_committed) const {
DCHECK(hint_cache_);
- if (hint_cache_->HasHint(url.host())) {
- if (!is_committed) {
- UMA_HISTOGRAM_ENUMERATION(
- "Previews.OptimizationGuide.HintCache.HasHint.BeforeCommit", ect,
- net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST);
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- "Previews.OptimizationGuide.HintCache.HasHint.AtCommit", ect,
- net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST);
- const optimization_guide::proto::Hint* hint =
- hint_cache_->GetHintIfLoaded(url.host());
- if (hint) {
- UMA_HISTOGRAM_ENUMERATION(
- "Previews.OptimizationGuide.HintCache.HostMatch.AtCommit", ect,
- net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST);
- if (optimization_guide::FindPageHintForURL(url, hint)) {
- UMA_HISTOGRAM_ENUMERATION(
- "Previews.OptimizationGuide.HintCache.PageMatch.AtCommit", ect,
- net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST);
- }
- }
+ bool has_hint = hint_cache_->HasHint(url.host());
+ if (!is_committed) {
+ UMA_HISTOGRAM_BOOLEAN("OptimizationGuide.HintCache.HasHint.BeforeCommit",
+ has_hint);
+ return;
+ }
+
+ UMA_HISTOGRAM_BOOLEAN("OptimizationGuide.HintCache.HasHint.AtCommit",
+ has_hint);
+ if (has_hint) {
+ const optimization_guide::proto::Hint* hint =
+ hint_cache_->GetHintIfLoaded(url.host());
+ UMA_HISTOGRAM_BOOLEAN("OptimizationGuide.HintCache.HostMatch.AtCommit",
+ hint);
+ if (hint) {
+ UMA_HISTOGRAM_BOOLEAN("OptimizationGuide.HintCache.PageMatch.AtCommit",
+ optimization_guide::FindPageHintForURL(url, hint));
}
}
}
diff --git a/chromium/components/previews/content/previews_hints.h b/chromium/components/previews/content/previews_hints.h
index aa01f64a046..997a40732ab 100644
--- a/chromium/components/previews/content/previews_hints.h
+++ b/chromium/components/previews/content/previews_hints.h
@@ -13,7 +13,7 @@
#include "base/sequence_checker.h"
#include "components/optimization_guide/hint_cache.h"
#include "components/optimization_guide/hints_processing_util.h"
-#include "components/optimization_guide/host_filter.h"
+#include "components/optimization_guide/optimization_filter.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/previews/content/previews_user_data.h"
#include "net/nqe/effective_connection_type.h"
@@ -85,11 +85,9 @@ class PreviewsHints {
std::vector<std::string>* out_resource_patterns_to_block) const;
// Logs UMA for whether the HintCache has a matching Hint and also a matching
- // PageHint for |url|. Records the client's current |ect| as well. This is
- // useful for measuring the effectiveness of the page hints provided by Cacao.
- void LogHintCacheMatch(const GURL& url,
- bool is_committed,
- net::EffectiveConnectionType ect) const;
+ // PageHint for |url|. This is useful for measuring the effectiveness of the
+ // page hints provided by Cacao.
+ void LogHintCacheMatch(const GURL& url, bool is_committed) const;
private:
friend class PreviewsHintsTest;
@@ -114,7 +112,8 @@ class PreviewsHints {
std::unique_ptr<optimization_guide::HintUpdateData> component_update_data_;
// Blacklist of host suffixes for LITE_PAGE_REDIRECT Previews.
- std::unique_ptr<optimization_guide::HostFilter> lite_page_redirect_blacklist_;
+ std::unique_ptr<optimization_guide::OptimizationFilter>
+ lite_page_redirect_blacklist_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/components/previews/content/previews_hints_unittest.cc b/chromium/components/previews/content/previews_hints_unittest.cc
index 06bce379df6..91fecdf1841 100644
--- a/chromium/components/previews/content/previews_hints_unittest.cc
+++ b/chromium/components/previews/content/previews_hints_unittest.cc
@@ -5,6 +5,7 @@
#include "components/previews/content/previews_hints.h"
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -13,14 +14,13 @@
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/optimization_guide/bloom_filter.h"
#include "components/optimization_guide/hint_cache.h"
#include "components/optimization_guide/hint_cache_store.h"
#include "components/optimization_guide/hint_update_data.h"
#include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/hints_component_util.h"
-#include "components/optimization_guide/host_filter.h"
#include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/optimization_guide/proto_database_provider_test_base.h"
@@ -59,20 +59,23 @@ void AddBlacklistBloomFilterToConfig(
blacklist_proto->set_allocated_bloom_filter(bloom_filter_proto.release());
}
-} // namespace
-
-class TestHostFilter : public optimization_guide::HostFilter {
- public:
- explicit TestHostFilter(std::string single_host_match)
- : HostFilter(nullptr), single_host_match_(single_host_match) {}
+void AddRegexpsFilterToConfig(optimization_guide::proto::Configuration* config,
+ const std::vector<std::string>& regexps) {
+ optimization_guide::proto::OptimizationFilter* blacklist_proto;
+ if (config->optimization_blacklists_size() > 0) {
+ blacklist_proto = config->mutable_optimization_blacklists(0);
+ } else {
+ blacklist_proto = config->add_optimization_blacklists();
+ blacklist_proto->set_optimization_type(
+ optimization_guide::proto::LITE_PAGE_REDIRECT);
+ }
- bool ContainsHostSuffix(const GURL& url) const override {
- return single_host_match_ == url.host();
+ for (const std::string& regexp : regexps) {
+ blacklist_proto->add_regexps(regexp);
}
+}
- private:
- std::string single_host_match_;
-};
+} // namespace
class PreviewsHintsTest
: public optimization_guide::ProtoDatabaseProviderTestBase {
@@ -85,8 +88,8 @@ class PreviewsHintsTest
ProtoDatabaseProviderTestBase::SetUp();
hint_cache_ = std::make_unique<optimization_guide::HintCache>(
std::make_unique<optimization_guide::HintCacheStore>(
- db_provider_.get(), temp_dir_.GetPath(), nullptr /* pref_service */,
- scoped_task_environment_.GetMainThreadTaskRunner()));
+ db_provider_.get(), temp_dir_.GetPath(),
+ task_environment_.GetMainThreadTaskRunner()));
is_store_initialized_ = false;
hint_cache_->Initialize(
@@ -141,12 +144,10 @@ class PreviewsHintsTest
net::EffectiveConnectionType* out_ect_threshold,
std::string* serialized_hint_version_string);
- void MaybeLoadHintAndLogHintCacheMatch(const GURL& url,
- bool is_committed,
- net::EffectiveConnectionType ect);
+ void MaybeLoadHintAndLogHintCacheMatch(const GURL& url, bool is_committed);
void RunUntilIdle() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
@@ -168,7 +169,7 @@ class PreviewsHintsTest
void MaybeLoadHint(const GURL& url);
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool is_store_initialized_;
bool are_previews_hints_initialized_;
@@ -190,12 +191,10 @@ bool PreviewsHintsTest::MaybeLoadHintAndCheckIsWhitelisted(
out_serialized_hint_version_string);
}
-void PreviewsHintsTest::MaybeLoadHintAndLogHintCacheMatch(
- const GURL& url,
- bool is_committed,
- net::EffectiveConnectionType ect) {
+void PreviewsHintsTest::MaybeLoadHintAndLogHintCacheMatch(const GURL& url,
+ bool is_committed) {
MaybeLoadHint(url);
- previews_hints_->LogHintCacheMatch(url, is_committed, ect);
+ previews_hints_->LogHintCacheMatch(url, is_committed);
}
void PreviewsHintsTest::MaybeLoadHint(const GURL& url) {
@@ -233,43 +232,99 @@ TEST_F(PreviewsHintsTest, LogHintCacheMatch) {
resource_loading_hint1->set_resource_pattern("news_cruft.js");
ParseConfig(config);
- base::HistogramTester histogram_tester;
+ // Verify histogram counts for non-matching URL host prior to commit.
+ {
+ base::HistogramTester histogram_tester;
- // First verify no histogram counts for non-matching URL host.
- MaybeLoadHintAndLogHintCacheMatch(
- GURL("https://someotherdomain.com/news/story.html"),
- false /* is_committed */, net::EFFECTIVE_CONNECTION_TYPE_3G);
- MaybeLoadHintAndLogHintCacheMatch(
- GURL("https://someotherdomain.com/news/story2.html"),
- true /* is_committed */, net::EFFECTIVE_CONNECTION_TYPE_4G);
- histogram_tester.ExpectTotalCount(
- "Previews.OptimizationGuide.HintCache.HasHint.BeforeCommit", 0);
- histogram_tester.ExpectTotalCount(
- "Previews.OptimizationGuide.HintCache.HasHint.AtCommit", 0);
- histogram_tester.ExpectTotalCount(
- "Previews.OptimizationGuide.HintCache.HintLoaded.AtCommit", 0);
- histogram_tester.ExpectTotalCount(
- "Previews.OptimizationGuide.HintCache.PageMatch.AtCommit", 0);
-
- // Now verify do have histogram counts for matching URL host.
- MaybeLoadHintAndLogHintCacheMatch(
- GURL("https://somedomain.org/news/story.html"), false /* is_committed */,
- net::EFFECTIVE_CONNECTION_TYPE_3G);
- MaybeLoadHintAndLogHintCacheMatch(
- GURL("https://somedomain.org/news/story2.html"), true /* is_committed */,
- net::EFFECTIVE_CONNECTION_TYPE_4G);
- histogram_tester.ExpectBucketCount(
- "Previews.OptimizationGuide.HintCache.HasHint.BeforeCommit",
- 4 /* EFFECTIVE_CONNECTION_TYPE_3G */, 1);
- histogram_tester.ExpectBucketCount(
- "Previews.OptimizationGuide.HintCache.HasHint.AtCommit",
- 5 /* EFFECTIVE_CONNECTION_TYPE_4G */, 1);
- histogram_tester.ExpectBucketCount(
- "Previews.OptimizationGuide.HintCache.HostMatch.AtCommit",
- 5 /* EFFECTIVE_CONNECTION_TYPE_4G */, 1);
- histogram_tester.ExpectBucketCount(
- "Previews.OptimizationGuide.HintCache.PageMatch.AtCommit",
- 5 /* EFFECTIVE_CONNECTION_TYPE_4G */, 1);
+ MaybeLoadHintAndLogHintCacheMatch(
+ GURL("https://someotherdomain.com/news/story.html"),
+ false /* is_committed */);
+
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HasHint.BeforeCommit", false, 1);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HasHint.AtCommit", 0);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HintLoaded.AtCommit", 0);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.PageMatch.AtCommit", 0);
+ }
+
+ // Verify histogram counts for non-matching URL host after commit.
+ {
+ base::HistogramTester histogram_tester;
+
+ MaybeLoadHintAndLogHintCacheMatch(
+ GURL("https://someotherdomain.com/news/story2.html"),
+ true /* is_committed */);
+
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HasHint.BeforeCommit", 0);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HasHint.AtCommit", false, 1);
+ // We don't have a hint for this host so we do not expect to check if the
+ // hint is loaded and we have a page hint.
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HintLoaded.AtCommit", 0);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.PageMatch.AtCommit", 0);
+ }
+
+ // Verify do have histogram counts for matching URL host before commit.
+ {
+ base::HistogramTester histogram_tester;
+
+ MaybeLoadHintAndLogHintCacheMatch(
+ GURL("https://somedomain.org/news/story.html"),
+ false /* is_committed */);
+
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HasHint.BeforeCommit", true, 1);
+ // None of the AfterCommit histograms should be recorded.
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HasHint.AtCommit", 0);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HostMatch.AtCommit", 0);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.PageMatch.AtCommit", 0);
+ }
+
+ // Verify do have histogram counts for matching URL host after commit.
+ {
+ base::HistogramTester histogram_tester;
+
+ MaybeLoadHintAndLogHintCacheMatch(
+ GURL("https://somedomain.org/news/story2.html"),
+ true /* is_committed */);
+
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HasHint.BeforeCommit", 0);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HasHint.AtCommit", true, 1);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HostMatch.AtCommit", true, 1);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.PageMatch.AtCommit", true, 1);
+ }
+
+ // Verify do have histogram counts for matching URL host but no matching page
+ // hint after commit.
+ {
+ base::HistogramTester histogram_tester;
+
+ MaybeLoadHintAndLogHintCacheMatch(
+ GURL("https://somedomain.org/nopagehint/story2.html"),
+ true /* is_committed */);
+
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.HintCache.HasHint.BeforeCommit", 0);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HasHint.AtCommit", true, 1);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.HostMatch.AtCommit", true, 1);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.HintCache.PageMatch.AtCommit", false, 1);
+ }
}
TEST_F(PreviewsHintsTest, IsBlacklistedReturnsTrueIfNoBloomFilter) {
@@ -292,7 +347,36 @@ TEST_F(PreviewsHintsTest, IsBlacklistedReturnsTrueIfNoBloomFilter) {
GURL("https://nonblack.com"), PreviewsType::LITE_PAGE_REDIRECT));
}
-TEST_F(PreviewsHintsTest, IsBlacklisted) {
+TEST_F(PreviewsHintsTest, IsBlacklisted_BloomFilterAndRegexps) {
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
+
+ optimization_guide::BloomFilter blacklist_bloom_filter(
+ kBlackBlacklistBloomFilterNumHashFunctions,
+ kBlackBlacklistBloomFilterNumBits);
+ PopulateBlackBlacklistBloomFilter(&blacklist_bloom_filter);
+
+ optimization_guide::proto::Configuration config;
+ AddBlacklistBloomFilterToConfig(blacklist_bloom_filter,
+ kBlackBlacklistBloomFilterNumHashFunctions,
+ kBlackBlacklistBloomFilterNumBits, &config);
+ AddRegexpsFilterToConfig(&config, {"blackpath"});
+ ParseConfig(config);
+
+ EXPECT_TRUE(HasLitePageRedirectBlacklist());
+ EXPECT_FALSE(previews_hints()->IsBlacklisted(GURL("https://black.com/path"),
+ PreviewsType::OFFLINE));
+ EXPECT_TRUE(previews_hints()->IsBlacklisted(
+ GURL("https://black.com/path"), PreviewsType::LITE_PAGE_REDIRECT));
+ EXPECT_TRUE(previews_hints()->IsBlacklisted(
+ GURL("https://joe.black.com/path"), PreviewsType::LITE_PAGE_REDIRECT));
+ EXPECT_FALSE(previews_hints()->IsBlacklisted(
+ GURL("https://ok-host.com/"), PreviewsType::LITE_PAGE_REDIRECT));
+ EXPECT_TRUE(previews_hints()->IsBlacklisted(
+ GURL("https://ok-host.com/blackpath"), PreviewsType::LITE_PAGE_REDIRECT));
+}
+
+TEST_F(PreviewsHintsTest, IsBlacklisted_BloomFilter) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
@@ -318,6 +402,47 @@ TEST_F(PreviewsHintsTest, IsBlacklisted) {
GURL("https://nonblack.com"), PreviewsType::LITE_PAGE_REDIRECT));
}
+TEST_F(PreviewsHintsTest, IsBlacklisted_Regexps) {
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
+
+ optimization_guide::proto::Configuration config;
+ AddRegexpsFilterToConfig(&config, {"black\\.com"});
+ ParseConfig(config);
+
+ EXPECT_TRUE(HasLitePageRedirectBlacklist());
+ EXPECT_FALSE(previews_hints()->IsBlacklisted(GURL("https://black.com/path"),
+ PreviewsType::OFFLINE));
+ EXPECT_TRUE(previews_hints()->IsBlacklisted(
+ GURL("https://black.com/path"), PreviewsType::LITE_PAGE_REDIRECT));
+ EXPECT_TRUE(previews_hints()->IsBlacklisted(
+ GURL("https://joe.black.com/path"), PreviewsType::LITE_PAGE_REDIRECT));
+ EXPECT_FALSE(previews_hints()->IsBlacklisted(
+ GURL("https://blackish.com"), PreviewsType::LITE_PAGE_REDIRECT));
+}
+
+TEST_F(PreviewsHintsTest, ParseConfigWithBadRegexp) {
+ base::HistogramTester histogram_tester;
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
+
+ optimization_guide::proto::Configuration config;
+ AddRegexpsFilterToConfig(&config, {"["});
+ ParseConfig(config);
+
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.OptimizationFilterStatus.LitePageRedirect",
+ optimization_guide::OptimizationFilterStatus::kFoundServerBlacklistConfig,
+ 1);
+ histogram_tester.ExpectBucketCount(
+ "OptimizationGuide.OptimizationFilterStatus.LitePageRedirect",
+ optimization_guide::OptimizationFilterStatus::kInvalidRegexp, 1);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.OptimizationFilterStatus.LitePageRedirect", 2);
+
+ EXPECT_FALSE(HasLitePageRedirectBlacklist());
+}
+
TEST_F(PreviewsHintsTest, ParseConfigWithInsufficientConfigDetails) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
@@ -358,9 +483,7 @@ TEST_F(PreviewsHintsTest, ParseConfigWithTooLargeBlacklist) {
scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
int too_many_bits =
- previews::params::LitePageRedirectPreviewMaxServerBlacklistByteSize() *
- 8 +
- 1;
+ optimization_guide::features::MaxServerBloomFilterByteSize() * 8 + 1;
optimization_guide::BloomFilter blacklist_bloom_filter(
kBlackBlacklistBloomFilterNumHashFunctions, too_many_bits);
diff --git a/chromium/components/previews/content/previews_optimization_guide.h b/chromium/components/previews/content/previews_optimization_guide.h
index 403f94be302..40c138cf24a 100644
--- a/chromium/components/previews/content/previews_optimization_guide.h
+++ b/chromium/components/previews/content/previews_optimization_guide.h
@@ -5,222 +5,62 @@
#ifndef COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_H_
#define COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_H_
-#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/time/clock.h"
-#include "base/timer/timer.h"
-#include "components/optimization_guide/hint_cache.h"
-#include "components/optimization_guide/optimization_guide_service_observer.h"
#include "components/previews/core/previews_experiments.h"
-#include "url/gurl.h"
-class PrefService;
+namespace content {
+class NavigationHandle;
+} // namespace content
-namespace base {
-class FilePath;
-} // namespace base
-namespace network {
-class SharedURLLoaderFactory;
-} // namespace network
-namespace optimization_guide {
-struct HintsComponentInfo;
-class HintsFetcher;
-class OptimizationGuideService;
-class TopHostProvider;
-namespace proto {
-class Hint;
-} // namespace proto
-} // namespace optimization_guide
+class GURL;
namespace previews {
-
-class PreviewsHints;
class PreviewsUserData;
// A Previews optimization guide that makes decisions guided by hints received
// from the OptimizationGuideService.
-class PreviewsOptimizationGuide
- : public optimization_guide::OptimizationGuideServiceObserver {
+class PreviewsOptimizationGuide {
public:
- // The embedder guarantees |optimization_guide_service| outlives |this|.
- // The embedder guarantees that |previews_top_host_provider_| outlives |this|.
- PreviewsOptimizationGuide(
- optimization_guide::OptimizationGuideService* optimization_guide_service,
- const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
- const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
- const base::FilePath& profile_path,
- PrefService* pref_service,
- leveldb_proto::ProtoDatabaseProvider* database_provider,
- optimization_guide::TopHostProvider* top_host_provider,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
-
- ~PreviewsOptimizationGuide() override;
-
- // Returns whether |type| is whitelisted for |url|. If so |out_ect_threshold|
- // provides the maximum effective connection type to trigger the preview for.
- // |previews_data| can be modified (for further details provided by hints).
- // Virtual so it can be mocked in tests.
- virtual bool IsWhitelisted(
- PreviewsUserData* previews_data,
- const GURL& url,
- PreviewsType type,
- net::EffectiveConnectionType* out_ect_threshold) const;
-
- // Returns whether |type| is blacklisted for |url|.
- // Virtual so it can be mocked in tests.
- virtual bool IsBlacklisted(const GURL& url, PreviewsType type) const;
-
- // Returns whether |request| may have associated optimization hints
+ PreviewsOptimizationGuide() {}
+ virtual ~PreviewsOptimizationGuide() {}
+
+ // Returns whether the optimization guide is ready to receive requests.
+ virtual bool IsReady() const = 0;
+
+ // Returns whether |type| is allowed for the URL associated with
+ // |navigation_handle| and the current conditions. |previews_data| can be
+ // modified (for further details provided by hints). Note that this will
+ // return false if a hint is needed to determine if the preview is allowed but
+ // we do not have everything we need to make that determination in memory.
+ virtual bool CanApplyPreview(PreviewsUserData* previews_data,
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) = 0;
+
+ // Returns whether |navigation_handle| may have associated optimization hints
// (specifically, PageHints). If so, but the hints are not available
// synchronously, this method will request that they be loaded (from disk or
// network). The callback is run after the hint is loaded and can be used as
// a signal during tests.
- bool MaybeLoadOptimizationHints(const GURL& url, base::OnceClosure callback);
+ virtual bool MaybeLoadOptimizationHints(
+ content::NavigationHandle* navigation_handle,
+ base::OnceClosure callback) = 0;
// Whether |url| has loaded resource loading hints and, if it does, populates
// |out_resource_patterns_to_block| with the resource patterns to block.
- bool GetResourceLoadingHints(
+ virtual bool GetResourceLoadingHints(
const GURL& url,
- std::vector<std::string>* out_resource_patterns_to_block) const;
+ std::vector<std::string>* out_resource_patterns_to_block) = 0;
// Logs UMA for whether the OptimizationGuide HintCache has a matching Hint
// guidance for |url|. This is useful for measuring the effectiveness of the
// page hints provided by Cacao.
- void LogHintCacheMatch(const GURL& url,
- bool is_committed,
- net::EffectiveConnectionType ect) const;
-
- // optimization_guide::OptimizationGuideServiceObserver implementation:
- // Called by OptimizationGuideService when a new component is available for
- // processing.
- void OnHintsComponentAvailable(
- const optimization_guide::HintsComponentInfo& info) override;
-
- PreviewsHints* GetHintsForTesting() { return hints_.get(); }
-
- // |next_update_closure| is called the next time OnHintsComponentAvailable is
- // called and the corresponding hints have been updated.
- void ListenForNextUpdateForTesting(base::OnceClosure next_update_closure);
-
- // Updates the hints to the latest hints sent by the Component Updater.
- // |update_closure| is called once the hints are updated. Public for testing.
- void UpdateHints(base::OnceClosure update_closure,
- std::unique_ptr<PreviewsHints> hints);
-
- // Clear all fetched hints known to |this|, including those persisted on disk.
- void ClearFetchedHints();
-
- bool has_hints() const { return !!hints_; }
-
- // Set |time_clock_| for testing.
- void SetTimeClockForTesting(const base::Clock* time_clock);
-
- // Set |hints_fetcher_| for testing.
- void SetHintsFetcherForTesting(
- std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher);
-
- optimization_guide::HintsFetcher* GetHintsFetcherForTesting();
-
- // Called when the hints store is initialized to determine when hints
- // should be fetched and schedules the |hints_fetch_timer_| to fire based on:
- // 1. The update time for the fetched hints in the store and
- // 2. The last time a fetch attempt was made, |last_fetch_attempt_|.
- void ScheduleHintsFetch();
-
- protected:
- // Callback executed after remote hints have been fetched and returned from
- // the remote Optimization Guide Service. At this point, the hints response
- // is ready to be processed and stored for use. Virtual to be mocked in
- // testing.
- virtual void OnHintsFetched(
- base::Optional<
- std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
- get_hints_response);
-
- // Callback executed after the Hints have been successfully stored in the
- // store. Virtual to be mocked in tests.
- virtual void OnFetchedHintsStored();
-
- private:
- // Callback run after the hint cache is fully initialized. At this point, the
- // PreviewsOptimizationGuide is ready to process components from the
- // OptimizationGuideService and registers as an observer with it.
- void OnHintCacheInitialized();
-
- // Called when the hints have been fully updated with the latest hints from
- // the Component Updater. This is used as a signal during tests.
- // |update_closure| is called immediately if not null.
- void OnHintsUpdated(base::OnceClosure update_closure);
-
- // Callback when a hint is loaded.
- void OnLoadedHint(base::OnceClosure callback,
- const GURL& document_url,
- const optimization_guide::proto::Hint* loaded_hint) const;
-
- // Method to request new hints for user's sites based on
- // engagement scores using |hints_fetcher_|.
- void FetchHints();
-
- // Return the time when a hints fetch request was last attempted.
- base::Time GetLastHintsFetchAttemptTime() const;
-
- // Set the time when a hints fetch was last attempted to |last_attempt_time|.
- void SetLastHintsFetchAttemptTime(base::Time last_attempt_time);
-
- // The OptimizationGuideService that this guide is listening to. Not owned.
- optimization_guide::OptimizationGuideService* optimization_guide_service_;
-
- // Runner for UI thread tasks.
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
-
- // Background thread where hints processing should be performed.
- scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
-
- // The hint cache used by PreviewsHints. It is owned by
- // PreviewsOptimizationGuide so that the existing hint cache can be reused on
- // component updates. Otherwise, a new cache and store would need to be
- // created during each component update.
- std::unique_ptr<optimization_guide::HintCache> hint_cache_;
-
- // The current hints used for this optimization guide.
- std::unique_ptr<PreviewsHints> hints_;
-
- // Used in testing to subscribe to an update event in this class.
- base::OnceClosure next_update_closure_;
-
- // HintsFetcher handles making the request for updated hints from the remote
- // Optimization Guide Service.
- std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher_;
-
- // Timer to schedule when to fetch hints from the remote Optimization Guide
- // Service.
- base::OneShotTimer hints_fetch_timer_;
-
- // TopHostProvider that this guide can query. Not owned.
- optimization_guide::TopHostProvider* top_host_provider_ = nullptr;
-
- // Clock used for scheduling the |hints_fetch_timer_|.
- const base::Clock* time_clock_;
-
- // A reference to the PrefService for this profile. Not owned.
- PrefService* pref_service_ = nullptr;
-
- // Used for fetching Hints by the Hints Fetcher.
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
- // Used to get |weak_ptr_| to self on the UI thread.
- base::WeakPtrFactory<PreviewsOptimizationGuide> ui_weak_ptr_factory_{this};
+ virtual void LogHintCacheMatch(const GURL& url, bool is_committed) const = 0;
- DISALLOW_COPY_AND_ASSIGN(PreviewsOptimizationGuide);
+ // Clears all fetched hints from its store.
+ virtual void ClearFetchedHints() = 0;
};
} // namespace previews
diff --git a/chromium/components/previews/content/previews_optimization_guide_decider.cc b/chromium/components/previews/content/previews_optimization_guide_decider.cc
new file mode 100644
index 00000000000..fc446b83540
--- /dev/null
+++ b/chromium/components/previews/content/previews_optimization_guide_decider.cc
@@ -0,0 +1,211 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/previews/content/previews_optimization_guide_decider.h"
+
+#include <utility>
+
+#include "components/optimization_guide/hints_processing_util.h"
+#include "components/optimization_guide/optimization_guide_decider.h"
+#include "components/optimization_guide/proto/hints.pb.h"
+#include "components/previews/content/previews_user_data.h"
+#include "components/previews/core/previews_experiments.h"
+#include "components/previews/core/previews_switches.h"
+#include "content/public/browser/navigation_handle.h"
+
+namespace previews {
+
+namespace {
+
+// The default max size of the cache holding resource loading hints by URL.
+size_t kDefaultMaxResourceLoadingHintsCacheSize = 10;
+
+// Returns base::nullopt if |previews_type| can't be converted.
+base::Optional<optimization_guide::proto::OptimizationType>
+ConvertPreviewsTypeToOptimizationType(PreviewsType previews_type) {
+ switch (previews_type) {
+ case PreviewsType::NONE:
+ return optimization_guide::proto::OPTIMIZATION_NONE;
+ case PreviewsType::NOSCRIPT:
+ return optimization_guide::proto::NOSCRIPT;
+ case PreviewsType::UNSPECIFIED:
+ return optimization_guide::proto::TYPE_UNSPECIFIED;
+ case PreviewsType::RESOURCE_LOADING_HINTS:
+ return optimization_guide::proto::RESOURCE_LOADING;
+ case PreviewsType::LITE_PAGE_REDIRECT:
+ return optimization_guide::proto::LITE_PAGE_REDIRECT;
+ case PreviewsType::DEFER_ALL_SCRIPT:
+ return optimization_guide::proto::DEFER_ALL_SCRIPT;
+ default:
+ return base::nullopt;
+ }
+}
+
+// Returns the optimization types to register with the Optimization Guide
+// Decider based on which Previews are enabled for the session.
+std::unordered_set<optimization_guide::proto::OptimizationType>
+GetOptimizationTypesToRegister() {
+ std::unordered_set<optimization_guide::proto::OptimizationType>
+ optimization_types;
+
+ if (params::IsNoScriptPreviewsEnabled())
+ optimization_types.insert(optimization_guide::proto::NOSCRIPT);
+ if (params::IsResourceLoadingHintsEnabled())
+ optimization_types.insert(optimization_guide::proto::RESOURCE_LOADING);
+ if (params::IsLitePageServerPreviewsEnabled())
+ optimization_types.insert(optimization_guide::proto::LITE_PAGE_REDIRECT);
+ if (params::IsDeferAllScriptPreviewsEnabled())
+ optimization_types.insert(optimization_guide::proto::DEFER_ALL_SCRIPT);
+
+ return optimization_types;
+}
+
+// Parses |resource_loading_hints| and returns a vector of resource patterns
+// that can be blocked.
+std::vector<std::string> GetResourcePatternsToBlock(
+ const google::protobuf::RepeatedPtrField<
+ optimization_guide::proto::ResourceLoadingHint>&
+ resource_loading_hints) {
+ std::vector<std::string> resource_patterns_to_block;
+ for (const auto& resource_loading_hint : resource_loading_hints) {
+ if (!resource_loading_hint.resource_pattern().empty() &&
+ resource_loading_hint.loading_optimization_type() ==
+ optimization_guide::proto::LOADING_BLOCK_RESOURCE) {
+ resource_patterns_to_block.push_back(
+ resource_loading_hint.resource_pattern());
+ }
+ }
+ return resource_patterns_to_block;
+}
+
+} // namespace
+
+PreviewsOptimizationGuideDecider::PreviewsOptimizationGuideDecider(
+ optimization_guide::OptimizationGuideDecider* optimization_guide_decider)
+ : optimization_guide_decider_(optimization_guide_decider),
+ resource_loading_hints_cache_(kDefaultMaxResourceLoadingHintsCacheSize),
+ registered_optimization_types_(GetOptimizationTypesToRegister()) {
+ DCHECK(optimization_guide_decider_);
+
+ optimization_guide_decider_->RegisterOptimizationTypes(
+ std::vector<optimization_guide::proto::OptimizationType>(
+ registered_optimization_types_.begin(),
+ registered_optimization_types_.end()));
+}
+
+PreviewsOptimizationGuideDecider::~PreviewsOptimizationGuideDecider() = default;
+
+bool PreviewsOptimizationGuideDecider::IsReady() const {
+ // TODO(crbug/969558): Figure out what to do here. The behavior in the old
+ // version was to check if the hints were initialized, but that detail is
+ // opaque to us at this level.
+ return true;
+}
+
+bool PreviewsOptimizationGuideDecider::CanApplyPreview(
+ PreviewsUserData* previews_data,
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) {
+ // See if we need to bypass the lite page redirect blacklist.
+ if (type == PreviewsType::LITE_PAGE_REDIRECT &&
+ params::LitePageRedirectPreviewIgnoresOptimizationGuideFilter()) {
+ return true;
+ }
+
+ base::Optional<optimization_guide::proto::OptimizationType>
+ optimization_type = ConvertPreviewsTypeToOptimizationType(type);
+ if (!optimization_type.has_value())
+ return false;
+
+ // See if we can apply the optimization. Note that
+ // |optimization_guide_decider_| also ensures that the current browser
+ // conditions match a painful page load as a prerequisite for returning true.
+ optimization_guide::OptimizationMetadata optimization_metadata;
+ optimization_guide::OptimizationGuideDecision decision =
+ optimization_guide_decider_->CanApplyOptimization(
+ navigation_handle,
+ optimization_guide::OptimizationTarget::kPainfulPageLoad,
+ *optimization_type, &optimization_metadata);
+
+ // Return false if we are even unsure if we can apply the optimization (i.e.
+ // hint not loaded yet or just not applicable).
+ if (decision != optimization_guide::OptimizationGuideDecision::kTrue)
+ return false;
+
+ // If we can apply it, populate information from metadata.
+ if (previews_data &&
+ optimization_metadata.previews_metadata.has_inflation_percent()) {
+ previews_data->set_data_savings_inflation_percent(
+ optimization_metadata.previews_metadata.inflation_percent());
+ }
+ if (optimization_metadata.previews_metadata.resource_loading_hints_size() >
+ 0) {
+ resource_loading_hints_cache_.Put(
+ navigation_handle->GetURL(),
+ GetResourcePatternsToBlock(
+ optimization_metadata.previews_metadata.resource_loading_hints()));
+ }
+
+ return true;
+}
+
+bool PreviewsOptimizationGuideDecider::MaybeLoadOptimizationHints(
+ content::NavigationHandle* navigation_handle,
+ base::OnceClosure callback) {
+ // We use this method as a way of enforcing some sort of preview ordering.
+ // Thus, we check if we can potentially apply any of the client-side previews,
+ // and if any of them potentially can be applied, then we return true.
+ const std::vector<optimization_guide::proto::OptimizationType>
+ optimization_types_to_check = {
+ optimization_guide::proto::DEFER_ALL_SCRIPT,
+ optimization_guide::proto::RESOURCE_LOADING,
+ optimization_guide::proto::NOSCRIPT};
+
+ bool might_have_hint = false;
+ for (const auto optimization_type : optimization_types_to_check) {
+ // Don't check for the hint if the optimization type is not enabled.
+ if (registered_optimization_types_.find(optimization_type) ==
+ registered_optimization_types_.end()) {
+ continue;
+ }
+
+ if (optimization_guide_decider_->CanApplyOptimization(
+ navigation_handle,
+ optimization_guide::OptimizationTarget::kPainfulPageLoad,
+ optimization_type,
+ /*optimization_metadata=*/nullptr) !=
+ optimization_guide::OptimizationGuideDecision::kFalse) {
+ might_have_hint = true;
+ break;
+ }
+ }
+
+ std::move(callback).Run();
+ return might_have_hint;
+}
+
+bool PreviewsOptimizationGuideDecider::GetResourceLoadingHints(
+ const GURL& url,
+ std::vector<std::string>* out_resource_patterns_to_block) {
+ auto rlh_it = resource_loading_hints_cache_.Get(url);
+ if (rlh_it == resource_loading_hints_cache_.end())
+ return false;
+
+ *out_resource_patterns_to_block = rlh_it->second;
+ return true;
+}
+
+void PreviewsOptimizationGuideDecider::LogHintCacheMatch(
+ const GURL& url,
+ bool is_committed) const {
+ // Intentionally unimplemented: This is handled directly by the
+ // OptimizationGuideDecider.
+}
+
+void PreviewsOptimizationGuideDecider::ClearFetchedHints() {
+ // Intentionally unimplemented: This is handled directly by the
+ // OptimizationGuideDecider.
+}
+
+} // namespace previews
diff --git a/chromium/components/previews/content/previews_optimization_guide_decider.h b/chromium/components/previews/content/previews_optimization_guide_decider.h
new file mode 100644
index 00000000000..4fccbbd39ff
--- /dev/null
+++ b/chromium/components/previews/content/previews_optimization_guide_decider.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_DECIDER_H_
+#define COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_DECIDER_H_
+
+#include "components/previews/content/previews_optimization_guide.h"
+
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include "base/containers/mru_cache.h"
+#include "components/optimization_guide/proto/hints.pb.h"
+
+namespace optimization_guide {
+class OptimizationGuideDecider;
+} // namespace optimization_guide
+
+namespace previews {
+
+// An |optimization_guide::OptimizationDecider| backed implementation of
+// |PreviewsOptimizationGuide|.
+class PreviewsOptimizationGuideDecider : public PreviewsOptimizationGuide {
+ public:
+ explicit PreviewsOptimizationGuideDecider(
+ optimization_guide::OptimizationGuideDecider* optimization_guide_decider);
+ ~PreviewsOptimizationGuideDecider() override;
+
+ // PreviewsOptimizationGuide implementation:
+ bool IsReady() const override;
+ bool CanApplyPreview(PreviewsUserData* previews_data,
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) override;
+ bool MaybeLoadOptimizationHints(content::NavigationHandle* navigation_handle,
+ base::OnceClosure callback) override;
+ bool GetResourceLoadingHints(
+ const GURL& url,
+ std::vector<std::string>* out_resource_patterns_to_block) override;
+ void LogHintCacheMatch(const GURL& url, bool is_committed) const override;
+ void ClearFetchedHints() override;
+
+ private:
+ // The Optimization Guide Decider to consult for whether an optimization can
+ // be applied. Not owned.
+ optimization_guide::OptimizationGuideDecider* optimization_guide_decider_;
+
+ // An in-memory cache of resource loading hints keyed by the URL. This allows
+ // us to avoid making too many calls to |optimization_guide_decider_|.
+ base::MRUCache<GURL, std::vector<std::string>> resource_loading_hints_cache_;
+
+ // The optimization types registered with |optimization_guide_decider_|.
+ const std::unordered_set<optimization_guide::proto::OptimizationType>
+ registered_optimization_types_;
+
+ DISALLOW_COPY_AND_ASSIGN(PreviewsOptimizationGuideDecider);
+};
+
+} // namespace previews
+
+#endif // COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_DECIDER_H_
diff --git a/chromium/components/previews/content/previews_optimization_guide_decider_unittest.cc b/chromium/components/previews/content/previews_optimization_guide_decider_unittest.cc
new file mode 100644
index 00000000000..2dc85bcb282
--- /dev/null
+++ b/chromium/components/previews/content/previews_optimization_guide_decider_unittest.cc
@@ -0,0 +1,355 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/previews/content/previews_optimization_guide_decider.h"
+
+#include <map>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <unordered_set>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/optimization_guide/optimization_guide_decider.h"
+#include "components/previews/content/previews_user_data.h"
+#include "components/previews/core/previews_features.h"
+#include "components/previews/core/previews_switches.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/test/mock_navigation_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace previews {
+
+class TestOptimizationGuideDecider
+ : public optimization_guide::OptimizationGuideDecider {
+ public:
+ TestOptimizationGuideDecider() = default;
+ ~TestOptimizationGuideDecider() override = default;
+
+ void RegisterOptimizationTypes(
+ std::vector<optimization_guide::proto::OptimizationType>
+ optimization_types) override {
+ registered_optimization_types_ =
+ std::unordered_set<optimization_guide::proto::OptimizationType>(
+ optimization_types.begin(), optimization_types.end());
+ }
+
+ // Returns the optimization types registered with the Optimization Guide
+ // Decider.
+ std::unordered_set<optimization_guide::proto::OptimizationType>
+ registered_optimization_types() {
+ return registered_optimization_types_;
+ }
+
+ optimization_guide::OptimizationGuideDecision CanApplyOptimization(
+ content::NavigationHandle* navigation_handle,
+ optimization_guide::OptimizationTarget optimization_target,
+ optimization_guide::proto::OptimizationType optimization_type,
+ optimization_guide::OptimizationMetadata* optimization_metadata)
+ override {
+ // Previews should always call this method with painful page load as the
+ // target.
+ DCHECK(optimization_target ==
+ optimization_guide::OptimizationTarget::kPainfulPageLoad);
+
+ auto response_iter = responses_.find(
+ std::make_tuple(navigation_handle->GetURL(), optimization_type));
+ if (response_iter == responses_.end())
+ return optimization_guide::OptimizationGuideDecision::kFalse;
+
+ auto response = response_iter->second;
+ if (optimization_metadata)
+ *optimization_metadata = std::get<1>(response);
+
+ return std::get<0>(response);
+ }
+
+ void SetResponses(
+ std::map<std::tuple<GURL, optimization_guide::proto::OptimizationType>,
+ std::tuple<optimization_guide::OptimizationGuideDecision,
+ optimization_guide::OptimizationMetadata>>
+ responses) {
+ responses_ = responses;
+ }
+
+ private:
+ // The optimization types that were registered with the Optimization Guide
+ // Decider.
+ std::unordered_set<optimization_guide::proto::OptimizationType>
+ registered_optimization_types_;
+
+ std::map<std::tuple<GURL, optimization_guide::proto::OptimizationType>,
+ std::tuple<optimization_guide::OptimizationGuideDecision,
+ optimization_guide::OptimizationMetadata>>
+ responses_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestOptimizationGuideDecider);
+};
+
+class PreviewsOptimizationGuideDeciderTest : public testing::Test {
+ public:
+ void SetUp() override {
+ optimization_guide_decider_.reset(new TestOptimizationGuideDecider);
+ }
+
+ TestOptimizationGuideDecider* optimization_guide_decider() {
+ return optimization_guide_decider_.get();
+ }
+
+ void SeedOptimizationGuideDeciderWithDefaultResponses() {
+ optimization_guide::OptimizationMetadata default_metadata;
+
+ optimization_guide::OptimizationMetadata rlh_metadata;
+ rlh_metadata.previews_metadata.set_inflation_percent(123);
+ rlh_metadata.previews_metadata.set_max_ect_trigger(
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_3G);
+ auto* rlh1 = rlh_metadata.previews_metadata.add_resource_loading_hints();
+ rlh1->set_resource_pattern("resource1");
+ rlh1->set_loading_optimization_type(
+ optimization_guide::proto::LOADING_BLOCK_RESOURCE);
+ auto* rlh2 = rlh_metadata.previews_metadata.add_resource_loading_hints();
+ rlh2->set_resource_pattern("resource2");
+ rlh2->set_loading_optimization_type(
+ optimization_guide::proto::LOADING_BLOCK_RESOURCE);
+ rlh_metadata.previews_metadata.add_resource_loading_hints()
+ ->set_resource_pattern("shouldbeskipped");
+ // Should also be skipped since the resource pattern is empty.
+ rlh_metadata.previews_metadata.add_resource_loading_hints()
+ ->set_loading_optimization_type(
+ optimization_guide::proto::LOADING_BLOCK_RESOURCE);
+
+ std::map<std::tuple<GURL, optimization_guide::proto::OptimizationType>,
+ std::tuple<optimization_guide::OptimizationGuideDecision,
+ optimization_guide::OptimizationMetadata>>
+ responses = {
+ {std::make_tuple(blacklisted_lpr_url(),
+ optimization_guide::proto::LITE_PAGE_REDIRECT),
+ std::make_tuple(
+ optimization_guide::OptimizationGuideDecision::kFalse,
+ default_metadata)},
+ {std::make_tuple(hint_not_loaded_url(),
+ optimization_guide::proto::NOSCRIPT),
+ std::make_tuple(
+ optimization_guide::OptimizationGuideDecision::kUnknown,
+ default_metadata)},
+ {std::make_tuple(resource_loading_hints_url(),
+ optimization_guide::proto::RESOURCE_LOADING),
+ std::make_tuple(
+ optimization_guide::OptimizationGuideDecision::kTrue,
+ rlh_metadata)},
+ };
+
+ optimization_guide_decider()->SetResponses(responses);
+ }
+
+ GURL blacklisted_lpr_url() { return GURL("https://blacklistedlpr.com/123"); }
+
+ GURL hint_not_loaded_url() { return GURL("https://hintnotloaded.com/123"); }
+
+ GURL resource_loading_hints_url() {
+ return GURL("https://hasresourceloadinghints.com/123");
+ }
+
+ private:
+ std::unique_ptr<TestOptimizationGuideDecider> optimization_guide_decider_;
+};
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ InitializationRegistersCorrectOptimizationTypes) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {previews::features::kLitePageServerPreviews,
+ previews::features::kDeferAllScriptPreviews,
+ previews::features::kNoScriptPreviews,
+ previews::features::kResourceLoadingHints},
+ {});
+
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+
+ std::unordered_set<optimization_guide::proto::OptimizationType>
+ registered_optimization_types =
+ optimization_guide_decider()->registered_optimization_types();
+ EXPECT_EQ(4u, registered_optimization_types.size());
+ // We expect for LITE_PAGE_REDIRECT, DEFER_ALL_SCRIPT, NOSCRIPT, and
+ // RESOURCE_LOADING to be registered.
+ EXPECT_TRUE(registered_optimization_types.find(
+ optimization_guide::proto::LITE_PAGE_REDIRECT) !=
+ registered_optimization_types.end());
+ EXPECT_TRUE(registered_optimization_types.find(
+ optimization_guide::proto::DEFER_ALL_SCRIPT) !=
+ registered_optimization_types.end());
+ EXPECT_TRUE(
+ registered_optimization_types.find(optimization_guide::proto::NOSCRIPT) !=
+ registered_optimization_types.end());
+ EXPECT_TRUE(registered_optimization_types.find(
+ optimization_guide::proto::RESOURCE_LOADING) !=
+ registered_optimization_types.end());
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ InitializationRegistersOnlyEnabledTypes) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {previews::features::kLitePageServerPreviews},
+ {previews::features::kDeferAllScriptPreviews,
+ previews::features::kNoScriptPreviews,
+ previews::features::kResourceLoadingHints});
+
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+
+ std::unordered_set<optimization_guide::proto::OptimizationType>
+ registered_optimization_types =
+ optimization_guide_decider()->registered_optimization_types();
+ EXPECT_EQ(1u, registered_optimization_types.size());
+ // We only expect for LITE_PAGE_REDIRECT to be registered, as it's the only
+ // type that is enabled.
+ EXPECT_TRUE(registered_optimization_types.find(
+ optimization_guide::proto::LITE_PAGE_REDIRECT) !=
+ registered_optimization_types.end());
+ EXPECT_EQ(registered_optimization_types.find(
+ optimization_guide::proto::DEFER_ALL_SCRIPT),
+ registered_optimization_types.end());
+ EXPECT_EQ(
+ registered_optimization_types.find(optimization_guide::proto::NOSCRIPT),
+ registered_optimization_types.end());
+ EXPECT_EQ(registered_optimization_types.find(
+ optimization_guide::proto::RESOURCE_LOADING),
+ registered_optimization_types.end());
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ PreviewsTypeWithoutCorrespondingOptimizationTypeReturnsFalse) {
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://whatever.com/"));
+
+ EXPECT_FALSE(decider.CanApplyPreview(
+ /*previews_data=*/nullptr, &navigation_handle,
+ PreviewsType::DEPRECATED_LOFI));
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ LitePageRedirectConvertsToOptimizationTypeCorrectly) {
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(blacklisted_lpr_url());
+
+ EXPECT_FALSE(decider.CanApplyPreview(
+ /*previews_data=*/nullptr, &navigation_handle,
+ PreviewsType::LITE_PAGE_REDIRECT));
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ LitePageRedirectSwitchOverridesDecisionForCanApplyPreview) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kIgnoreLitePageRedirectOptimizationBlacklist);
+
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(blacklisted_lpr_url());
+
+ EXPECT_TRUE(decider.CanApplyPreview(
+ /*previews_data=*/nullptr, &navigation_handle,
+ PreviewsType::LITE_PAGE_REDIRECT));
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ CanApplyPreviewPopulatesResourceLoadingHintsCache) {
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ // Make sure resource loading hints not cached.
+ std::vector<std::string> resource_loading_hints;
+ EXPECT_FALSE(decider.GetResourceLoadingHints(resource_loading_hints_url(),
+ &resource_loading_hints));
+ EXPECT_TRUE(resource_loading_hints.empty());
+
+ // Check if we can apply it and metadata is properly applied.
+ PreviewsUserData data(/*page_id=*/1);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(resource_loading_hints_url());
+ EXPECT_TRUE(decider.CanApplyPreview(&data, &navigation_handle,
+ PreviewsType::RESOURCE_LOADING_HINTS));
+ EXPECT_EQ(123, data.data_savings_inflation_percent());
+
+ // Make sure resource loading hints are validated and cached.
+ EXPECT_TRUE(decider.GetResourceLoadingHints(resource_loading_hints_url(),
+ &resource_loading_hints));
+ EXPECT_EQ(2u, resource_loading_hints.size());
+ EXPECT_EQ("resource1", resource_loading_hints[0]);
+ EXPECT_EQ("resource2", resource_loading_hints[1]);
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ CanApplyPreviewWithUnknownDecisionReturnsFalse) {
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(hint_not_loaded_url());
+
+ EXPECT_FALSE(decider.CanApplyPreview(
+ /*previews_data=*/nullptr, &navigation_handle, PreviewsType::NOSCRIPT));
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ MaybeLoadOptimizationHintsWithAtLeastOneNonFalseDecisionReturnsTrue) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {previews::features::kLitePageServerPreviews,
+ previews::features::kDeferAllScriptPreviews,
+ previews::features::kNoScriptPreviews,
+ previews::features::kResourceLoadingHints},
+ {});
+
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(hint_not_loaded_url());
+
+ EXPECT_TRUE(decider.MaybeLoadOptimizationHints(&navigation_handle,
+ base::DoNothing()));
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ MaybeLoadOptimizationHintsReturnsFalseIfNoClientSidePreviewsEnabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {previews::features::kLitePageServerPreviews},
+ {previews::features::kDeferAllScriptPreviews,
+ previews::features::kNoScriptPreviews,
+ previews::features::kResourceLoadingHints});
+
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(hint_not_loaded_url());
+
+ EXPECT_FALSE(decider.MaybeLoadOptimizationHints(&navigation_handle,
+ base::DoNothing()));
+}
+
+TEST_F(PreviewsOptimizationGuideDeciderTest,
+ MaybeLoadOptimizationHintsWithAllFalseDecisionsReturnsFalse) {
+ PreviewsOptimizationGuideDecider decider(optimization_guide_decider());
+ SeedOptimizationGuideDeciderWithDefaultResponses();
+
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://nohints.com"));
+
+ EXPECT_FALSE(decider.MaybeLoadOptimizationHints(&navigation_handle,
+ base::DoNothing()));
+}
+
+} // namespace previews
diff --git a/chromium/components/previews/content/previews_optimization_guide.cc b/chromium/components/previews/content/previews_optimization_guide_impl.cc
index 49a8a9edbc2..49e7cd1eaab 100644
--- a/chromium/components/previews/content/previews_optimization_guide.cc
+++ b/chromium/components/previews/content/previews_optimization_guide_impl.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 "components/previews/content/previews_optimization_guide.h"
+#include "components/previews/content/previews_optimization_guide_impl.h"
+
+#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
@@ -18,6 +20,7 @@
#include "components/optimization_guide/hints_component_info.h"
#include "components/optimization_guide/hints_component_util.h"
#include "components/optimization_guide/hints_fetcher.h"
+#include "components/optimization_guide/optimization_guide_constants.h"
#include "components/optimization_guide/optimization_guide_features.h"
#include "components/optimization_guide/optimization_guide_prefs.h"
#include "components/optimization_guide/optimization_guide_service.h"
@@ -27,8 +30,8 @@
#include "components/prefs/pref_service.h"
#include "components/previews/content/previews_hints.h"
#include "components/previews/content/previews_user_data.h"
-#include "components/previews/core/previews_constants.h"
#include "components/previews/core/previews_switches.h"
+#include "content/public/browser/navigation_handle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"
@@ -61,7 +64,7 @@ base::TimeDelta RandomFetchDelay() {
} // namespace
-PreviewsOptimizationGuide::PreviewsOptimizationGuide(
+PreviewsOptimizationGuideImpl::PreviewsOptimizationGuideImpl(
optimization_guide::OptimizationGuideService* optimization_guide_service,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
@@ -69,7 +72,8 @@ PreviewsOptimizationGuide::PreviewsOptimizationGuide(
PrefService* pref_service,
leveldb_proto::ProtoDatabaseProvider* database_provider,
optimization_guide::TopHostProvider* top_host_provider,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ network::NetworkQualityTracker* network_quality_tracker)
: optimization_guide_service_(optimization_guide_service),
ui_task_runner_(ui_task_runner),
background_task_runner_(background_task_runner),
@@ -77,41 +81,69 @@ PreviewsOptimizationGuide::PreviewsOptimizationGuide(
std::make_unique<optimization_guide::HintCacheStore>(
database_provider,
profile_path,
- pref_service,
background_task_runner_))),
top_host_provider_(top_host_provider),
time_clock_(base::DefaultClock::GetInstance()),
pref_service_(pref_service),
- url_loader_factory_(url_loader_factory) {
+ url_loader_factory_(url_loader_factory),
+ network_quality_tracker_(network_quality_tracker) {
DCHECK(optimization_guide_service_);
+ network_quality_tracker_->AddEffectiveConnectionTypeObserver(this);
hint_cache_->Initialize(
optimization_guide::switches::ShouldPurgeHintCacheStoreOnStartup(),
- base::BindOnce(&PreviewsOptimizationGuide::OnHintCacheInitialized,
+ base::BindOnce(&PreviewsOptimizationGuideImpl::OnHintCacheInitialized,
ui_weak_ptr_factory_.GetWeakPtr()));
}
-PreviewsOptimizationGuide::~PreviewsOptimizationGuide() {
+PreviewsOptimizationGuideImpl::~PreviewsOptimizationGuideImpl() {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
optimization_guide_service_->RemoveObserver(this);
+ network_quality_tracker_->RemoveEffectiveConnectionTypeObserver(this);
+}
+
+bool PreviewsOptimizationGuideImpl::IsReady() const {
+ return !!hints_;
}
-bool PreviewsOptimizationGuide::IsWhitelisted(
+bool PreviewsOptimizationGuideImpl::CanApplyPreview(
PreviewsUserData* previews_data,
- const GURL& url,
- PreviewsType type,
- net::EffectiveConnectionType* out_ect_threshold) const {
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
if (!hints_) {
return false;
}
- *out_ect_threshold = params::GetECTThresholdForPreview(type);
+ // Check if LITE_PAGE_REDIRECT is blacklisted or not.
+ if (type == PreviewsType::LITE_PAGE_REDIRECT) {
+ if (current_effective_connection_type_ >
+ params::GetECTThresholdForPreview(type)) {
+ return false;
+ }
+
+ if (params::LitePageRedirectPreviewIgnoresOptimizationGuideFilter()) {
+ return true;
+ }
+
+ return !hints_->IsBlacklisted(navigation_handle->GetURL(),
+ PreviewsType::LITE_PAGE_REDIRECT);
+ }
+
+ // Check other previews.
int inflation_percent = 0;
+ net::EffectiveConnectionType out_ect_threshold =
+ params::GetECTThresholdForPreview(type);
std::string serialized_hint_version_string;
- if (!hints_->IsWhitelisted(url, type, &inflation_percent, out_ect_threshold,
+ if (!hints_->IsWhitelisted(navigation_handle->GetURL(), type,
+ &inflation_percent, &out_ect_threshold,
&serialized_hint_version_string)) {
return false;
}
+ // Also check the hint's ECT threshold against the current ECT if the type
+ // can be applied.
+ if (current_effective_connection_type_ > out_ect_threshold) {
+ return false;
+ }
if (inflation_percent != 0 && previews_data) {
previews_data->set_data_savings_inflation_percent(inflation_percent);
@@ -125,28 +157,7 @@ bool PreviewsOptimizationGuide::IsWhitelisted(
return true;
}
-bool PreviewsOptimizationGuide::IsBlacklisted(const GURL& url,
- PreviewsType type) const {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
-
- if (type == PreviewsType::LITE_PAGE_REDIRECT) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kIgnoreLitePageRedirectOptimizationBlacklist)) {
- return false;
- }
-
- if (!hints_)
- return true;
-
- return hints_->IsBlacklisted(url, PreviewsType::LITE_PAGE_REDIRECT);
- }
-
- // This function is only used by lite page redirect.
- NOTREACHED();
- return false;
-}
-
-void PreviewsOptimizationGuide::OnLoadedHint(
+void PreviewsOptimizationGuideImpl::OnLoadedHint(
base::OnceClosure callback,
const GURL& document_url,
const optimization_guide::proto::Hint* loaded_hint) const {
@@ -154,16 +165,16 @@ void PreviewsOptimizationGuide::OnLoadedHint(
// Record that the hint finished loading. This is used as a signal during
// tests.
- LOCAL_HISTOGRAM_BOOLEAN(
- kPreviewsOptimizationGuideOnLoadedHintResultHistogramString, loaded_hint);
+ LOCAL_HISTOGRAM_BOOLEAN(optimization_guide::kLoadedHintLocalHistogramString,
+ loaded_hint);
// Run the callback now that the hint is loaded. This is used as a signal by
// tests.
std::move(callback).Run();
}
-bool PreviewsOptimizationGuide::MaybeLoadOptimizationHints(
- const GURL& url,
+bool PreviewsOptimizationGuideImpl::MaybeLoadOptimizationHints(
+ content::NavigationHandle* navigation_handle,
base::OnceClosure callback) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
@@ -171,15 +182,16 @@ bool PreviewsOptimizationGuide::MaybeLoadOptimizationHints(
return false;
}
+ const GURL& url = navigation_handle->GetURL();
return hints_->MaybeLoadOptimizationHints(
- url, base::BindOnce(&PreviewsOptimizationGuide::OnLoadedHint,
+ url, base::BindOnce(&PreviewsOptimizationGuideImpl::OnLoadedHint,
ui_weak_ptr_factory_.GetWeakPtr(),
std::move(callback), url));
}
-bool PreviewsOptimizationGuide::GetResourceLoadingHints(
+bool PreviewsOptimizationGuideImpl::GetResourceLoadingHints(
const GURL& url,
- std::vector<std::string>* out_resource_patterns_to_block) const {
+ std::vector<std::string>* out_resource_patterns_to_block) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
if (!hints_)
@@ -188,18 +200,16 @@ bool PreviewsOptimizationGuide::GetResourceLoadingHints(
return hints_->GetResourceLoadingHints(url, out_resource_patterns_to_block);
}
-void PreviewsOptimizationGuide::LogHintCacheMatch(
- const GURL& url,
- bool is_committed,
- net::EffectiveConnectionType ect) const {
+void PreviewsOptimizationGuideImpl::LogHintCacheMatch(const GURL& url,
+ bool is_committed) const {
if (!hints_) {
return;
}
- hints_->LogHintCacheMatch(url, is_committed, ect);
+ hints_->LogHintCacheMatch(url, is_committed);
}
-void PreviewsOptimizationGuide::OnHintCacheInitialized() {
+void PreviewsOptimizationGuideImpl::OnHintCacheInitialized() {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
// Check if there is a valid hint proto given on the command line first. We
// don't normally expect one, but if one is provided then use that and do not
@@ -216,14 +226,12 @@ void PreviewsOptimizationGuide::OnHintCacheInitialized() {
base::Version(kManualConfigComponentVersion))));
}
-
-
// Register as an observer regardless of hint proto override usage. This is
// needed as a signal during testing.
optimization_guide_service_->AddObserver(this);
}
-void PreviewsOptimizationGuide::OnHintsComponentAvailable(
+void PreviewsOptimizationGuideImpl::OnHintsComponentAvailable(
const optimization_guide::HintsComponentInfo& info) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
@@ -246,12 +254,12 @@ void PreviewsOptimizationGuide::OnHintsComponentAvailable(
base::BindOnce(
&PreviewsHints::CreateFromHintsComponent, info,
hint_cache_->MaybeCreateUpdateDataForComponentHints(info.version)),
- base::BindOnce(&PreviewsOptimizationGuide::UpdateHints,
+ base::BindOnce(&PreviewsOptimizationGuideImpl::UpdateHints,
ui_weak_ptr_factory_.GetWeakPtr(),
std::move(next_update_closure_)));
}
-void PreviewsOptimizationGuide::FetchHints() {
+void PreviewsOptimizationGuideImpl::FetchHints() {
base::Optional<std::vector<std::string>> top_hosts =
optimization_guide::switches::ParseHintsFetchOverrideFromCommandLine();
if (!top_hosts) {
@@ -266,17 +274,19 @@ void PreviewsOptimizationGuide::FetchHints() {
if (!hints_fetcher_) {
hints_fetcher_ = std::make_unique<optimization_guide::HintsFetcher>(
url_loader_factory_,
- optimization_guide::features::GetOptimizationGuideServiceURL());
+ optimization_guide::features::GetOptimizationGuideServiceURL(),
+ pref_service_);
}
if (top_hosts->size() > 0) {
hints_fetcher_->FetchOptimizationGuideServiceHints(
- *top_hosts, base::BindOnce(&PreviewsOptimizationGuide::OnHintsFetched,
- ui_weak_ptr_factory_.GetWeakPtr()));
+ *top_hosts,
+ base::BindOnce(&PreviewsOptimizationGuideImpl::OnHintsFetched,
+ ui_weak_ptr_factory_.GetWeakPtr()));
}
}
-void PreviewsOptimizationGuide::OnHintsFetched(
+void PreviewsOptimizationGuideImpl::OnHintsFetched(
base::Optional<std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response) {
// TODO(mcrouse): this will be dropped into a backgroundtask as it will likely
@@ -285,27 +295,28 @@ void PreviewsOptimizationGuide::OnHintsFetched(
hint_cache_->UpdateFetchedHints(
std::move(*get_hints_response),
time_clock_->Now() + kUpdateFetchedHintsDelay,
- base::BindOnce(&PreviewsOptimizationGuide::OnFetchedHintsStored,
+ base::BindOnce(&PreviewsOptimizationGuideImpl::OnFetchedHintsStored,
ui_weak_ptr_factory_.GetWeakPtr()));
} else {
// The fetch did not succeed so we will schedule to retry the fetch in
// after delaying for |kFetchRetryDelay|
// TODO(mcrouse): When the store is refactored from closures, the timer will
// be scheduled on failure of the store instead.
- hints_fetch_timer_.Start(FROM_HERE, kFetchRetryDelay, this,
- &PreviewsOptimizationGuide::ScheduleHintsFetch);
+ hints_fetch_timer_.Start(
+ FROM_HERE, kFetchRetryDelay, this,
+ &PreviewsOptimizationGuideImpl::ScheduleHintsFetch);
}
}
-void PreviewsOptimizationGuide::OnFetchedHintsStored() {
+void PreviewsOptimizationGuideImpl::OnFetchedHintsStored() {
hints_fetch_timer_.Stop();
hints_fetch_timer_.Start(
FROM_HERE, hint_cache_->FetchedHintsUpdateTime() - time_clock_->Now(),
- this, &PreviewsOptimizationGuide::ScheduleHintsFetch);
+ this, &PreviewsOptimizationGuideImpl::ScheduleHintsFetch);
// TODO(mcrouse): Purge hints now that new fetched hints have been stored.
}
-void PreviewsOptimizationGuide::UpdateHints(
+void PreviewsOptimizationGuideImpl::UpdateHints(
base::OnceClosure update_closure,
std::unique_ptr<PreviewsHints> hints) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
@@ -313,7 +324,7 @@ void PreviewsOptimizationGuide::UpdateHints(
if (hints_) {
hints_->Initialize(
hint_cache_.get(),
- base::BindOnce(&PreviewsOptimizationGuide::OnHintsUpdated,
+ base::BindOnce(&PreviewsOptimizationGuideImpl::OnHintsUpdated,
ui_weak_ptr_factory_.GetWeakPtr(),
std::move(update_closure)));
} else {
@@ -321,12 +332,14 @@ void PreviewsOptimizationGuide::UpdateHints(
}
}
-void PreviewsOptimizationGuide::ClearFetchedHints() {
+void PreviewsOptimizationGuideImpl::ClearFetchedHints() {
DCHECK(hint_cache_);
hint_cache_->ClearFetchedHints();
+ optimization_guide::HintsFetcher::ClearHostsSuccessfullyFetched(
+ pref_service_);
}
-void PreviewsOptimizationGuide::OnHintsUpdated(
+void PreviewsOptimizationGuideImpl::OnHintsUpdated(
base::OnceClosure update_closure) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
DCHECK(pref_service_);
@@ -343,9 +356,6 @@ void PreviewsOptimizationGuide::OnHintsUpdated(
// If the client is eligible to fetch hints, currently controlled by a feature
// flag |kOptimizationHintsFetching|, fetch hints from the remote Optimization
// Guide Service.
- //
- // TODO(mcrouse): Add a check if Infobar notification needs to be shown to the
- // user.
if (!data_reduction_proxy::DataReductionProxySettings::
IsDataSaverEnabledByUser(pref_service_)) {
return;
@@ -365,7 +375,7 @@ void PreviewsOptimizationGuide::OnHintsUpdated(
}
}
-void PreviewsOptimizationGuide::SetLastHintsFetchAttemptTime(
+void PreviewsOptimizationGuideImpl::SetLastHintsFetchAttemptTime(
base::Time last_attempt_time) {
DCHECK(pref_service_);
pref_service_->SetInt64(
@@ -373,14 +383,14 @@ void PreviewsOptimizationGuide::SetLastHintsFetchAttemptTime(
last_attempt_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
}
-base::Time PreviewsOptimizationGuide::GetLastHintsFetchAttemptTime() const {
+base::Time PreviewsOptimizationGuideImpl::GetLastHintsFetchAttemptTime() const {
DCHECK(pref_service_);
return base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMicroseconds(pref_service_->GetInt64(
optimization_guide::prefs::kHintsFetcherLastFetchAttempt)));
}
-void PreviewsOptimizationGuide::ScheduleHintsFetch() {
+void PreviewsOptimizationGuideImpl::ScheduleHintsFetch() {
DCHECK(!hints_fetch_timer_.IsRunning());
DCHECK(pref_service_);
@@ -399,7 +409,7 @@ void PreviewsOptimizationGuide::ScheduleHintsFetch() {
// been made in last |kFetchRetryDelay|.
SetLastHintsFetchAttemptTime(time_clock_->Now());
hints_fetch_timer_.Start(FROM_HERE, RandomFetchDelay(), this,
- &PreviewsOptimizationGuide::FetchHints);
+ &PreviewsOptimizationGuideImpl::FetchHints);
} else {
if (time_until_update_time >= base::TimeDelta()) {
// If the fetched hints in the store are still up-to-date, set a timer
@@ -411,31 +421,37 @@ void PreviewsOptimizationGuide::ScheduleHintsFetch() {
// delay.
fetcher_delay = time_until_retry;
}
- hints_fetch_timer_.Start(FROM_HERE, fetcher_delay, this,
- &PreviewsOptimizationGuide::ScheduleHintsFetch);
+ hints_fetch_timer_.Start(
+ FROM_HERE, fetcher_delay, this,
+ &PreviewsOptimizationGuideImpl::ScheduleHintsFetch);
}
}
-void PreviewsOptimizationGuide::SetTimeClockForTesting(
+void PreviewsOptimizationGuideImpl::SetTimeClockForTesting(
const base::Clock* time_clock) {
time_clock_ = time_clock;
}
-void PreviewsOptimizationGuide::SetHintsFetcherForTesting(
+void PreviewsOptimizationGuideImpl::SetHintsFetcherForTesting(
std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher) {
hints_fetcher_ = std::move(hints_fetcher);
}
optimization_guide::HintsFetcher*
-PreviewsOptimizationGuide::GetHintsFetcherForTesting() {
+PreviewsOptimizationGuideImpl::GetHintsFetcherForTesting() {
return hints_fetcher_.get();
}
-void PreviewsOptimizationGuide::ListenForNextUpdateForTesting(
+void PreviewsOptimizationGuideImpl::ListenForNextUpdateForTesting(
base::OnceClosure next_update_closure) {
DCHECK(next_update_closure_.is_null())
<< "Only one update closure is supported at a time";
next_update_closure_ = std::move(next_update_closure);
}
+void PreviewsOptimizationGuideImpl::OnEffectiveConnectionTypeChanged(
+ net::EffectiveConnectionType effective_connection_type) {
+ current_effective_connection_type_ = effective_connection_type;
+}
+
} // namespace previews
diff --git a/chromium/components/previews/content/previews_optimization_guide_impl.h b/chromium/components/previews/content/previews_optimization_guide_impl.h
new file mode 100644
index 00000000000..b36b65bd3cc
--- /dev/null
+++ b/chromium/components/previews/content/previews_optimization_guide_impl.h
@@ -0,0 +1,223 @@
+// 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 COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_IMPL_H_
+#define COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/clock.h"
+#include "base/timer/timer.h"
+#include "components/optimization_guide/hint_cache.h"
+#include "components/optimization_guide/optimization_guide_service_observer.h"
+#include "components/previews/content/previews_optimization_guide.h"
+#include "components/previews/core/previews_experiments.h"
+#include "services/network/public/cpp/network_quality_tracker.h"
+#include "url/gurl.h"
+
+class PrefService;
+
+namespace base {
+class FilePath;
+} // namespace base
+namespace content {
+class NavigationHandle;
+} // namespace content
+namespace network {
+class SharedURLLoaderFactory;
+} // namespace network
+namespace optimization_guide {
+struct HintsComponentInfo;
+class HintsFetcher;
+class OptimizationGuideService;
+class TopHostProvider;
+namespace proto {
+class Hint;
+} // namespace proto
+} // namespace optimization_guide
+
+namespace previews {
+
+class PreviewsHints;
+class PreviewsUserData;
+
+// A Previews optimization guide that makes decisions guided by hints received
+// from the OptimizationGuideService.
+class PreviewsOptimizationGuideImpl
+ : public PreviewsOptimizationGuide,
+ public optimization_guide::OptimizationGuideServiceObserver,
+ public network::NetworkQualityTracker::EffectiveConnectionTypeObserver {
+ public:
+ // The embedder guarantees |optimization_guide_service| outlives |this|.
+ // The embedder guarantees that |previews_top_host_provider_| outlives |this|.
+ PreviewsOptimizationGuideImpl(
+ optimization_guide::OptimizationGuideService* optimization_guide_service,
+ const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+ const base::FilePath& profile_path,
+ PrefService* pref_service,
+ leveldb_proto::ProtoDatabaseProvider* database_provider,
+ optimization_guide::TopHostProvider* top_host_provider,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ network::NetworkQualityTracker* network_quality_tracker);
+
+ ~PreviewsOptimizationGuideImpl() override;
+
+ // PreviewsOptimizationGuide implementation:
+ bool IsReady() const override;
+ bool CanApplyPreview(PreviewsUserData* previews_data,
+ content::NavigationHandle* navigation_handle,
+ PreviewsType type) override;
+ bool MaybeLoadOptimizationHints(content::NavigationHandle* navigation_handle,
+ base::OnceClosure callback) override;
+ bool GetResourceLoadingHints(
+ const GURL& url,
+ std::vector<std::string>* out_resource_patterns_to_block) override;
+ void LogHintCacheMatch(const GURL& url, bool is_committed) const override;
+ void ClearFetchedHints() override;
+
+ // optimization_guide::OptimizationGuideServiceObserver implementation:
+ // Called by OptimizationGuideService when a new component is available for
+ // processing.
+ void OnHintsComponentAvailable(
+ const optimization_guide::HintsComponentInfo& info) override;
+
+ // network::NetworkQualityTracker::EffectiveConnectionTypeObserver
+ // implementation:
+ void OnEffectiveConnectionTypeChanged(
+ net::EffectiveConnectionType effective_connection_type) override;
+
+ PreviewsHints* GetHintsForTesting() { return hints_.get(); }
+
+ // |next_update_closure| is called the next time OnHintsComponentAvailable is
+ // called and the corresponding hints have been updated.
+ void ListenForNextUpdateForTesting(base::OnceClosure next_update_closure);
+
+ // Set |time_clock_| for testing.
+ void SetTimeClockForTesting(const base::Clock* time_clock);
+
+ // Set |hints_fetcher_| for testing.
+ void SetHintsFetcherForTesting(
+ std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher);
+
+ optimization_guide::HintsFetcher* GetHintsFetcherForTesting();
+
+ // Called when the hints store is initialized to determine when hints
+ // should be fetched and schedules the |hints_fetch_timer_| to fire based on:
+ // 1. The update time for the fetched hints in the store and
+ // 2. The last time a fetch attempt was made, |last_fetch_attempt_|.
+ void ScheduleHintsFetch();
+
+ protected:
+ // Callback executed after remote hints have been fetched and returned from
+ // the remote Optimization Guide Service. At this point, the hints response
+ // is ready to be processed and stored for use. Virtual to be mocked in
+ // testing.
+ virtual void OnHintsFetched(
+ base::Optional<
+ std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
+ get_hints_response);
+
+ // Callback executed after the Hints have been successfully stored in the
+ // store. Virtual to be mocked in tests.
+ virtual void OnFetchedHintsStored();
+
+ private:
+ // Callback run after the hint cache is fully initialized. At this point, the
+ // PreviewsOptimizationGuide is ready to process components from the
+ // OptimizationGuideService and registers as an observer with it.
+ void OnHintCacheInitialized();
+
+ // Updates the hints to the latest hints sent by the Component Updater.
+ // |update_closure| is called once the hints are updated.
+ void UpdateHints(base::OnceClosure update_closure,
+ std::unique_ptr<PreviewsHints> hints);
+
+ // Called when the hints have been fully updated with the latest hints from
+ // the Component Updater. This is used as a signal during tests.
+ // |update_closure| is called immediately if not null.
+ void OnHintsUpdated(base::OnceClosure update_closure);
+
+ // Callback when a hint is loaded.
+ void OnLoadedHint(base::OnceClosure callback,
+ const GURL& document_url,
+ const optimization_guide::proto::Hint* loaded_hint) const;
+
+ // Method to request new hints for user's sites based on
+ // engagement scores using |hints_fetcher_|.
+ void FetchHints();
+
+ // Return the time when a hints fetch request was last attempted.
+ base::Time GetLastHintsFetchAttemptTime() const;
+
+ // Set the time when a hints fetch was last attempted to |last_attempt_time|.
+ void SetLastHintsFetchAttemptTime(base::Time last_attempt_time);
+
+ // The OptimizationGuideService that this guide is listening to. Not owned.
+ optimization_guide::OptimizationGuideService* optimization_guide_service_;
+
+ // Runner for UI thread tasks.
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
+ // Background thread where hints processing should be performed.
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
+ // The hint cache used by PreviewsHints. It is owned by
+ // PreviewsOptimizationGuide so that the existing hint cache can be reused on
+ // component updates. Otherwise, a new cache and store would need to be
+ // created during each component update.
+ std::unique_ptr<optimization_guide::HintCache> hint_cache_;
+
+ // The current hints used for this optimization guide.
+ std::unique_ptr<PreviewsHints> hints_;
+
+ // Used in testing to subscribe to an update event in this class.
+ base::OnceClosure next_update_closure_;
+
+ // HintsFetcher handles making the request for updated hints from the remote
+ // Optimization Guide Service.
+ std::unique_ptr<optimization_guide::HintsFetcher> hints_fetcher_;
+
+ // Timer to schedule when to fetch hints from the remote Optimization Guide
+ // Service.
+ base::OneShotTimer hints_fetch_timer_;
+
+ // TopHostProvider that this guide can query. Not owned.
+ optimization_guide::TopHostProvider* top_host_provider_ = nullptr;
+
+ // Clock used for scheduling the |hints_fetch_timer_|.
+ const base::Clock* time_clock_;
+
+ // A reference to the PrefService for this profile. Not owned.
+ PrefService* pref_service_ = nullptr;
+
+ // Used for fetching Hints by the Hints Fetcher.
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+ // The network quality tracker that this guide is listening to. Not owned.
+ network::NetworkQualityTracker* network_quality_tracker_;
+
+ // The current estimate of the effective connection type.
+ net::EffectiveConnectionType current_effective_connection_type_ =
+ net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
+
+ // Used to get |weak_ptr_| to self on the UI thread.
+ base::WeakPtrFactory<PreviewsOptimizationGuideImpl> ui_weak_ptr_factory_{
+ this};
+
+ DISALLOW_COPY_AND_ASSIGN(PreviewsOptimizationGuideImpl);
+};
+
+} // namespace previews
+
+#endif // COMPONENTS_PREVIEWS_CONTENT_PREVIEWS_OPTIMIZATION_GUIDE_IMPL_H_
diff --git a/chromium/components/previews/content/previews_optimization_guide_unittest.cc b/chromium/components/previews/content/previews_optimization_guide_impl_unittest.cc
index 6f7a58c498c..22188299815 100644
--- a/chromium/components/previews/content/previews_optimization_guide_unittest.cc
+++ b/chromium/components/previews/content/previews_optimization_guide_impl_unittest.cc
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/previews/content/previews_optimization_guide.h"
+#include "components/previews/content/previews_optimization_guide_impl.h"
#include <memory>
+#include <utility>
#include "base/base64.h"
#include "base/bind.h"
@@ -20,8 +21,8 @@
#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/optimization_guide/bloom_filter.h"
@@ -41,8 +42,10 @@
#include "components/previews/content/previews_user_data.h"
#include "components/previews/core/previews_experiments.h"
#include "components/previews/core/previews_features.h"
+#include "content/public/test/mock_navigation_handle.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_network_quality_tracker.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -120,22 +123,21 @@ std::unique_ptr<optimization_guide::proto::GetHintsResponse> BuildHintsResponse(
// A mock class implementation of HintsFetcher for unittesting
// previews_optimization_guide.
class TestHintsFetcher : public optimization_guide::HintsFetcher {
- using HintsFetchedCallback = base::OnceCallback<void(
- base::Optional<
- std::unique_ptr<optimization_guide::proto::GetHintsResponse>>)>;
- using HintsFetcher::FetchOptimizationGuideServiceHints;
-
public:
TestHintsFetcher(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
GURL optimization_guide_service_url,
- HintsFetcherEndState fetch_state)
- : HintsFetcher(url_loader_factory, optimization_guide_service_url),
+ HintsFetcherEndState fetch_state,
+ PrefService* pref_service)
+ : HintsFetcher(url_loader_factory,
+ optimization_guide_service_url,
+ pref_service),
fetch_state_(fetch_state) {}
bool FetchOptimizationGuideServiceHints(
const std::vector<std::string>& hosts,
- HintsFetchedCallback hints_fetched_callback) override {
+ optimization_guide::HintsFetchedCallback hints_fetched_callback)
+ override {
switch (fetch_state_) {
case HintsFetcherEndState::kFetchFailed:
std::move(hints_fetched_callback).Run(base::nullopt);
@@ -161,7 +163,7 @@ class TestHintsFetcher : public optimization_guide::HintsFetcher {
// A Test PreviewsOptimizationGuide to observe and record when callbacks
// from hints fetching and storing occur.
-class TestPreviewsOptimizationGuide : public PreviewsOptimizationGuide {
+class TestPreviewsOptimizationGuide : public PreviewsOptimizationGuideImpl {
public:
TestPreviewsOptimizationGuide(
optimization_guide::OptimizationGuideService* optimization_guide_service,
@@ -171,15 +173,17 @@ class TestPreviewsOptimizationGuide : public PreviewsOptimizationGuide {
PrefService* pref_service,
leveldb_proto::ProtoDatabaseProvider* database_provider,
optimization_guide::TopHostProvider* optimization_guide_top_host_provider,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
- : PreviewsOptimizationGuide(optimization_guide_service,
- ui_task_runner,
- background_task_runner,
- profile_path,
- pref_service,
- database_provider,
- optimization_guide_top_host_provider,
- url_loader_factory) {}
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ network::TestNetworkQualityTracker* network_quality_tracker)
+ : PreviewsOptimizationGuideImpl(optimization_guide_service,
+ ui_task_runner,
+ background_task_runner,
+ profile_path,
+ pref_service,
+ database_provider,
+ optimization_guide_top_host_provider,
+ url_loader_factory,
+ network_quality_tracker) {}
bool fetched_hints_stored() { return fetched_hints_stored_; }
@@ -189,26 +193,26 @@ class TestPreviewsOptimizationGuide : public PreviewsOptimizationGuide {
std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response) override {
fetched_hints_stored_ = false;
- PreviewsOptimizationGuide::OnHintsFetched(std::move(get_hints_response));
+ PreviewsOptimizationGuideImpl::OnHintsFetched(
+ std::move(get_hints_response));
}
void OnFetchedHintsStored() override {
fetched_hints_stored_ = true;
- PreviewsOptimizationGuide::OnFetchedHintsStored();
+ PreviewsOptimizationGuideImpl::OnFetchedHintsStored();
}
bool fetched_hints_stored_ = false;
};
-class PreviewsOptimizationGuideTest
+class PreviewsOptimizationGuideImplTest
: public optimization_guide::ProtoDatabaseProviderTestBase {
public:
- PreviewsOptimizationGuideTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
+ PreviewsOptimizationGuideImplTest()
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- ~PreviewsOptimizationGuideTest() override {}
+ ~PreviewsOptimizationGuideImplTest() override {}
void SetUp() override {
ProtoDatabaseProviderTestBase::SetUp();
@@ -222,7 +226,7 @@ class PreviewsOptimizationGuideTest
ResetGuide();
}
- PreviewsOptimizationGuide* guide() { return guide_.get(); }
+ PreviewsOptimizationGuideImpl* guide() { return guide_.get(); }
MockTopHostProvider* top_host_provider() {
return optimization_guide_top_host_provider_.get();
@@ -242,6 +246,10 @@ class PreviewsOptimizationGuideTest
return static_cast<TestHintsFetcher*>(guide_->GetHintsFetcherForTesting());
}
+ network::TestNetworkQualityTracker* network_quality_tracker() {
+ return network_quality_tracker_.get();
+ }
+
void ProcessHints(const optimization_guide::proto::Configuration& config,
const std::string& version) {
base::HistogramTester histogram_tester;
@@ -284,7 +292,7 @@ class PreviewsOptimizationGuideTest
}
optimization_guide_service_ =
std::make_unique<TestOptimizationGuideService>(
- scoped_task_environment_.GetMainThreadTaskRunner());
+ task_environment_.GetMainThreadTaskRunner());
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
// Registry pref for DataSaver with default off.
@@ -292,14 +300,18 @@ class PreviewsOptimizationGuideTest
data_reduction_proxy::prefs::kDataSaverEnabled, false);
optimization_guide::prefs::RegisterProfilePrefs(pref_service_->registry());
+ network_quality_tracker_ =
+ std::make_unique<network::TestNetworkQualityTracker>();
+
guide_ = std::make_unique<TestPreviewsOptimizationGuide>(
optimization_guide_service_.get(),
- scoped_task_environment_.GetMainThreadTaskRunner(),
- scoped_task_environment_.GetMainThreadTaskRunner(), temp_dir(),
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMainThreadTaskRunner(), temp_dir(),
pref_service_.get(), db_provider_.get(),
- optimization_guide_top_host_provider_.get(), url_loader_factory_);
+ optimization_guide_top_host_provider_.get(), url_loader_factory_,
+ network_quality_tracker_.get());
- guide_->SetTimeClockForTesting(scoped_task_environment_.GetMockClock());
+ guide_->SetTimeClockForTesting(task_environment_.GetMockClock());
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -313,7 +325,7 @@ class PreviewsOptimizationGuideTest
}
const base::Clock* GetMockClock() const {
- return scoped_task_environment_.GetMockClock();
+ return task_environment_.GetMockClock();
}
void ResetGuide() {
@@ -324,23 +336,24 @@ class PreviewsOptimizationGuideTest
std::unique_ptr<TestHintsFetcher> BuildTestHintsFetcher(
HintsFetcherEndState end_state) {
std::unique_ptr<TestHintsFetcher> hints_fetcher =
- std::make_unique<TestHintsFetcher>(
- url_loader_factory_, GURL("https://hintsserver.com"), end_state);
+ std::make_unique<TestHintsFetcher>(url_loader_factory_,
+ GURL("https://hintsserver.com"),
+ end_state, pref_service());
return hints_fetcher;
}
base::FilePath temp_dir() const { return temp_dir_.GetPath(); }
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
void MoveClockForwardBy(base::TimeDelta time_delta) {
- scoped_task_environment_.FastForwardBy(time_delta);
+ task_environment_.FastForwardBy(time_delta);
base::RunLoop().RunUntilIdle();
}
void RunUntilIdle() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
@@ -366,15 +379,20 @@ class PreviewsOptimizationGuideTest
// server blacklist.
void InitializeWithLitePageRedirectBlacklist();
+ // This is a wrapper around MaybeLoadOptimizationHints that wraps |url| in a
+ // navigation handle to call the method.
+ bool CallMaybeLoadOptimizationHints(const GURL& url);
+
// This function guarantees that all of the asynchronous processing required
- // to load the specified hint has occurred prior to calling IsWhitelisted.
- // It accomplishes this by calling MaybeLoadOptimizationHints() and waiting
- // until OnLoadOptimizationHints runs before calling IsWhitelisted().
- bool MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ // to load the specified hint has occurred prior to calling
+ // CanApplyPreview. It accomplishes this by calling
+ // MaybeLoadOptimizationHints() and waiting until OnLoadOptimizationHints runs
+ // before calling CanApplyPreview().
+ bool MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
PreviewsUserData* previews_data,
const GURL& url,
PreviewsType type,
- net::EffectiveConnectionType* out_ect_threshold);
+ net::EffectiveConnectionType ect);
void RunUntilFetchedHintsStored() {
while (!guide_->fetched_hints_stored()) {
@@ -408,18 +426,19 @@ class PreviewsOptimizationGuideTest
std::unique_ptr<TestOptimizationGuideService> optimization_guide_service_;
std::unique_ptr<MockTopHostProvider> optimization_guide_top_host_provider_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
+ std::unique_ptr<network::TestNetworkQualityTracker> network_quality_tracker_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
network::TestURLLoaderFactory test_url_loader_factory_;
-
GURL loaded_hints_document_gurl_;
std::vector<std::string> loaded_hints_resource_patterns_;
- DISALLOW_COPY_AND_ASSIGN(PreviewsOptimizationGuideTest);
+ DISALLOW_COPY_AND_ASSIGN(PreviewsOptimizationGuideImplTest);
};
-void PreviewsOptimizationGuideTest::InitializeFixedCountResourceLoadingHints() {
+void PreviewsOptimizationGuideImplTest::
+ InitializeFixedCountResourceLoadingHints() {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint1 = config.add_hints();
hint1->set_key("somedomain.org");
@@ -461,7 +480,7 @@ void PreviewsOptimizationGuideTest::InitializeFixedCountResourceLoadingHints() {
ProcessHints(config, "2.0.0");
}
-void PreviewsOptimizationGuideTest::
+void PreviewsOptimizationGuideImplTest::
InitializeFixedCountResourceLoadingHintsWithTwoExperiments() {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint1 = config.add_hints();
@@ -497,7 +516,7 @@ void PreviewsOptimizationGuideTest::
ProcessHints(config, "2.0.0");
}
-void PreviewsOptimizationGuideTest::InitializeMultipleResourceLoadingHints(
+void PreviewsOptimizationGuideImplTest::InitializeMultipleResourceLoadingHints(
size_t key_count,
size_t page_patterns_per_key) {
optimization_guide::proto::Configuration config;
@@ -535,7 +554,8 @@ void PreviewsOptimizationGuideTest::InitializeMultipleResourceLoadingHints(
ProcessHints(config, "2.0.0");
}
-void PreviewsOptimizationGuideTest::InitializeWithLitePageRedirectBlacklist() {
+void PreviewsOptimizationGuideImplTest::
+ InitializeWithLitePageRedirectBlacklist() {
optimization_guide::BloomFilter blacklist_bloom_filter(7, 511);
blacklist_bloom_filter.Add("blacklisteddomain.com");
blacklist_bloom_filter.Add("blacklistedsubdomain.maindomain.co.in");
@@ -555,42 +575,54 @@ void PreviewsOptimizationGuideTest::InitializeWithLitePageRedirectBlacklist() {
ProcessHints(config, "2.0.0");
}
-bool PreviewsOptimizationGuideTest::
- MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+bool PreviewsOptimizationGuideImplTest::CallMaybeLoadOptimizationHints(
+ const GURL& url) {
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(url);
+ return guide()->MaybeLoadOptimizationHints(&navigation_handle,
+ base::DoNothing());
+}
+
+bool PreviewsOptimizationGuideImplTest::
+ MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
PreviewsUserData* previews_data,
const GURL& url,
PreviewsType type,
- net::EffectiveConnectionType* out_ect_threshold) {
+ net::EffectiveConnectionType ect) {
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(url);
+
// Ensure that all asynchronous MaybeLoadOptimizationHints processing
- // finishes prior to calling IsWhitelisted. This is accomplished by waiting
- // for the OnLoadOptimizationHints callback to set |requested_hints_loaded_|
- // to true.
+ // finishes prior to calling CanApplyPreview. This is accomplished by
+ // waiting for the OnLoadOptimizationHints callback to set
+ // |requested_hints_loaded_| to true.
requested_hints_loaded_ = false;
if (guide()->MaybeLoadOptimizationHints(
- url, base::BindOnce(
- &PreviewsOptimizationGuideTest::OnLoadOptimizationHints,
- base::Unretained(this)))) {
+ &navigation_handle,
+ base::BindOnce(
+ &PreviewsOptimizationGuideImplTest::OnLoadOptimizationHints,
+ base::Unretained(this)))) {
while (!requested_hints_loaded_) {
RunUntilIdle();
}
}
- return guide()->IsWhitelisted(previews_data, url, type, out_ect_threshold);
+ network_quality_tracker()->ReportEffectiveConnectionTypeForTesting(ect);
+ return guide()->CanApplyPreview(previews_data, &navigation_handle, type);
}
-void PreviewsOptimizationGuideTest::OnLoadOptimizationHints() {
+void PreviewsOptimizationGuideImplTest::OnLoadOptimizationHints() {
requested_hints_loaded_ = true;
}
-TEST_F(PreviewsOptimizationGuideTest, IsWhitelistedWithoutHints) {
+TEST_F(PreviewsOptimizationGuideImplTest, CanApplyPreviewWithoutHints) {
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsForNoScriptPageHintsPopulatedCorrectly) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
@@ -609,8 +641,7 @@ TEST_F(PreviewsOptimizationGuideTest,
optimization_guide::proto::PageHint* page_hint2 = hint1->add_page_hints();
page_hint2->set_page_pattern("noscript_3g");
page_hint2->set_max_ect_trigger(
- optimization_guide::proto::EffectiveConnectionType::
- EFFECTIVE_CONNECTION_TYPE_3G);
+ optimization_guide::proto::EFFECTIVE_CONNECTION_TYPE_3G);
optimization_guide::proto::Optimization* optimization2 =
page_hint2->add_whitelisted_optimizations();
optimization2->set_optimization_type(optimization_guide::proto::NOSCRIPT);
@@ -627,34 +658,31 @@ TEST_F(PreviewsOptimizationGuideTest,
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify page matches and ECT thresholds.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://somedomain.org/noscript_default_2g"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://somedomain.org/noscript_3g"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G, ect_threshold);
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_3G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://somedomain.org/no_pattern_match"),
- PreviewsType::NOSCRIPT, &ect_threshold));
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
// Verify * matches any page.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://anypage.com/noscript_for_all"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://anypage.com/"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://anypage.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsWithValidCommandLineOverride) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
@@ -680,16 +708,14 @@ TEST_F(PreviewsOptimizationGuideTest,
// Verify page matches and ECT thresholds.
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
EXPECT_TRUE(guide()->GetHintsForTesting());
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://somedomain.org/noscript_default_2g"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsWithValidCommandLineOverrideForDeferAllScript) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures({features::kDeferAllScriptPreviews}, {});
@@ -715,16 +741,14 @@ TEST_F(PreviewsOptimizationGuideTest,
// Verify page matches and ECT thresholds.
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
EXPECT_TRUE(guide()->GetHintsForTesting());
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://somedomain.org/defer_default_2g"),
- PreviewsType::DEFER_ALL_SCRIPT, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ PreviewsType::DEFER_ALL_SCRIPT, net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsWithValidCommandLineOverrideAndPreexistingData) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
@@ -732,8 +756,8 @@ TEST_F(PreviewsOptimizationGuideTest,
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint = config.add_hints();
@@ -755,19 +779,17 @@ TEST_F(PreviewsOptimizationGuideTest,
// Verify page matches and ECT thresholds.
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
EXPECT_TRUE(guide()->GetHintsForTesting());
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://otherdomain.org/noscript_default_2g"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsWithInvalidCommandLineOverride) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
optimization_guide::switches::kHintsProtoOverride, "this-is-not-a-proto");
@@ -776,53 +798,48 @@ TEST_F(PreviewsOptimizationGuideTest,
EXPECT_FALSE(guide()->GetHintsForTesting());
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsWithPurgeHintCacheStoreCommandLineAndNoPreexistingData) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
optimization_guide::switches::kPurgeHintCacheStore);
CreateServiceAndGuide();
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsWithPurgeHintCacheStoreCommandLineAndPreexistingData) {
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
base::CommandLine::ForCurrentProcess()->AppendSwitch(
optimization_guide::switches::kPurgeHintCacheStore);
CreateServiceAndGuide();
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
}
// Test when resource loading hints are enabled.
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsForResourceLoadingHintsPopulatedCorrectly) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
@@ -871,23 +888,24 @@ TEST_F(PreviewsOptimizationGuideTest,
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Twitter and Facebook should be whitelisted but not Google.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.twitter.com/example"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://google.com"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
// Test when both NoScript and resource loading hints are enabled.
TEST_F(
- PreviewsOptimizationGuideTest,
+ PreviewsOptimizationGuideImplTest,
ProcessHintsWhitelistForNoScriptAndResourceLoadingHintsPopulatedCorrectly) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
@@ -935,23 +953,24 @@ TEST_F(
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Twitter and Facebook should be whitelisted but not Google.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com/example.html"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::NOSCRIPT, net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.twitter.com/example"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://google.com"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsForResourceLoadingHintsWithSlowPageTriggering) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
@@ -999,19 +1018,16 @@ TEST_F(PreviewsOptimizationGuideTest,
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://3g.com"), PreviewsType::RESOURCE_LOADING_HINTS,
- &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G, ect_threshold);
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_3G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://4g.com/example"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_4G, ect_threshold);
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS, net::EFFECTIVE_CONNECTION_TYPE_4G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://default2g.com"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
// This is a helper function for testing the experiment flags on the config for
@@ -1019,7 +1035,7 @@ TEST_F(PreviewsOptimizationGuideTest,
// multiple optimizations. The optimization under test will be marked with an
// experiment name if one is provided in |experiment_name|. It will then be
// tested to see if it's enabled, the expectation found in |expect_enabled|.
-void PreviewsOptimizationGuideTest::DoExperimentFlagTest(
+void PreviewsOptimizationGuideImplTest::DoExperimentFlagTest(
base::Optional<std::string> experiment_name,
bool expect_enabled) {
base::test::ScopedFeatureList scoped_list;
@@ -1065,36 +1081,32 @@ void PreviewsOptimizationGuideTest::DoExperimentFlagTest(
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Check to ensure the optimization under test (facebook noscript) is either
// enabled or disabled, depending on what the caller told us to expect.
- EXPECT_EQ(expect_enabled, MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_EQ(expect_enabled, MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"),
- PreviewsType::NOSCRIPT, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ PreviewsType::NOSCRIPT,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
// RESOURCE_LOADING_HINTS for facebook should always be enabled.
- ect_threshold = net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
EXPECT_EQ(!expect_enabled,
- MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
// Twitter's NOSCRIPT should always be enabled; RESOURCE_LOADING_HINTS is not
// configured and should be disabled.
- ect_threshold = net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.twitter.com/example"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
// Google (which is not configured at all) should always have both NOSCRIPT
// and RESOURCE_LOADING_HINTS disabled.
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
HandlesExperimentalFlagWithNoExperimentFlaggedOrEnabled) {
// With the optimization NOT flagged as experimental and no experiment
// enabled, the optimization should be enabled.
@@ -1104,7 +1116,7 @@ TEST_F(PreviewsOptimizationGuideTest,
DoExperimentFlagTest(base::nullopt, true);
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
HandlesExperimentalFlagWithEmptyExperimentName) {
// Empty experiment names should be equivalent to no experiment flag set.
base::test::ScopedFeatureList scoped_list;
@@ -1113,7 +1125,7 @@ TEST_F(PreviewsOptimizationGuideTest,
DoExperimentFlagTest("", true);
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
HandlesExperimentalFlagWithExperimentConfiguredAndNotRunning) {
// With the optimization flagged as experimental and no experiment
// enabled, the optimization should be disabled.
@@ -1123,7 +1135,7 @@ TEST_F(PreviewsOptimizationGuideTest,
DoExperimentFlagTest("foo_experiment", false);
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
HandlesExperimentalFlagWithExperimentConfiguredAndSameOneRunning) {
// With the optimization flagged as experimental and an experiment with that
// name running, the optimization should be enabled.
@@ -1134,7 +1146,7 @@ TEST_F(PreviewsOptimizationGuideTest,
DoExperimentFlagTest("foo_experiment", true);
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
HandlesExperimentalFlagWithExperimentConfiguredAndDifferentOneRunning) {
// With the optimization flagged as experimental and a *different* experiment
// enabled, the optimization should be disabled.
@@ -1145,14 +1157,15 @@ TEST_F(PreviewsOptimizationGuideTest,
DoExperimentFlagTest("foo_experiment", false);
}
-TEST_F(PreviewsOptimizationGuideTest, EnsureExperimentsDisabledByDefault) {
+TEST_F(PreviewsOptimizationGuideImplTest, EnsureExperimentsDisabledByDefault) {
// Mark an optimization as experiment, and ensure it's disabled even though we
// don't explicitly enable or disable the feature as part of the test. This
// ensures the experiments feature is disabled by default.
DoExperimentFlagTest("foo_experiment", false);
}
-TEST_F(PreviewsOptimizationGuideTest, ProcessHintsUnsupportedKeyRepIsIgnored) {
+TEST_F(PreviewsOptimizationGuideImplTest,
+ ProcessHintsUnsupportedKeyRepIsIgnored) {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint = config.add_hints();
hint->set_key("facebook.com");
@@ -1166,13 +1179,12 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsUnsupportedKeyRepIsIgnored) {
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsUnsupportedOptimizationIsIgnored) {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint = config.add_hints();
@@ -1188,13 +1200,12 @@ TEST_F(PreviewsOptimizationGuideTest,
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithExistingSentinel) {
+TEST_F(PreviewsOptimizationGuideImplTest, ProcessHintsWithExistingSentinel) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
{features::kNoScriptPreviews, features::kResourceLoadingHints}, {});
@@ -1220,10 +1231,9 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithExistingSentinel) {
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
EXPECT_TRUE(base::PathExists(sentinel_path));
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.ProcessHintsResult",
@@ -1234,10 +1244,9 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithExistingSentinel) {
// Now verify config is processed for different version and sentinel cleared.
ProcessHints(config, "3.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, ect_threshold);
+ net::EFFECTIVE_CONNECTION_TYPE_2G));
EXPECT_FALSE(base::PathExists(sentinel_path));
histogram_tester.ExpectBucketCount(
"OptimizationGuide.ProcessHintsResult",
@@ -1246,7 +1255,7 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithExistingSentinel) {
1);
}
-TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithInvalidSentinelFile) {
+TEST_F(PreviewsOptimizationGuideImplTest, ProcessHintsWithInvalidSentinelFile) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
{features::kNoScriptPreviews, features::kResourceLoadingHints}, {});
@@ -1273,10 +1282,9 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithInvalidSentinelFile) {
ProcessHints(config, "2.0.0");
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
EXPECT_FALSE(base::PathExists(sentinel_path));
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.ProcessHintsResult",
@@ -1287,9 +1295,9 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithInvalidSentinelFile) {
// Now verify config is processed with sentinel cleared.
ProcessHints(config, "2.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
EXPECT_FALSE(base::PathExists(sentinel_path));
histogram_tester.ExpectBucketCount(
"OptimizationGuide.ProcessHintsResult",
@@ -1298,7 +1306,8 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintsWithInvalidSentinelFile) {
1);
}
-TEST_F(PreviewsOptimizationGuideTest, SkipHintProcessingForSameConfigVersion) {
+TEST_F(PreviewsOptimizationGuideImplTest,
+ SkipHintProcessingForSameConfigVersion) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
{features::kNoScriptPreviews, features::kResourceLoadingHints}, {});
@@ -1325,17 +1334,16 @@ TEST_F(PreviewsOptimizationGuideTest, SkipHintProcessingForSameConfigVersion) {
optimization2->set_optimization_type(optimization_guide::proto::NOSCRIPT);
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Process the new hints config and verify that they are available.
ProcessHints(config1, "2.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.ProcessHintsResult",
static_cast<int>(
@@ -1346,12 +1354,12 @@ TEST_F(PreviewsOptimizationGuideTest, SkipHintProcessingForSameConfigVersion) {
// is skipped.
ProcessHints(config2, "2.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
histogram_tester.ExpectBucketCount(
"OptimizationGuide.ProcessHintsResult",
static_cast<int>(optimization_guide::ProcessHintsComponentResult::
@@ -1359,7 +1367,7 @@ TEST_F(PreviewsOptimizationGuideTest, SkipHintProcessingForSameConfigVersion) {
1);
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
SkipHintProcessingForEarlierConfigVersion) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
@@ -1387,17 +1395,16 @@ TEST_F(PreviewsOptimizationGuideTest,
optimization2->set_optimization_type(optimization_guide::proto::NOSCRIPT);
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Process the new hints config and verify that they are available.
ProcessHints(config1, "2.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.ProcessHintsResult",
static_cast<int>(
@@ -1408,12 +1415,12 @@ TEST_F(PreviewsOptimizationGuideTest,
// one is skipped.
ProcessHints(config2, "1.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
histogram_tester.ExpectBucketCount(
"OptimizationGuide.ProcessHintsResult",
static_cast<int>(optimization_guide::ProcessHintsComponentResult::
@@ -1421,7 +1428,7 @@ TEST_F(PreviewsOptimizationGuideTest,
1);
}
-TEST_F(PreviewsOptimizationGuideTest, ProcessMultipleNewConfigs) {
+TEST_F(PreviewsOptimizationGuideImplTest, ProcessMultipleNewConfigs) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitWithFeatures(
@@ -1448,17 +1455,16 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessMultipleNewConfigs) {
optimization2->set_optimization_type(optimization_guide::proto::NOSCRIPT);
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Process the new hints config and verify that they are available.
ProcessHints(config1, "2.0.0");
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
histogram_tester.ExpectUniqueSample(
"OptimizationGuide.ProcessHintsResult",
static_cast<int>(
@@ -1469,12 +1475,12 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessMultipleNewConfigs) {
// is processed.
ProcessHints(config2, "3.0.0");
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.facebook.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://m.google.com"), PreviewsType::NOSCRIPT,
- &ect_threshold));
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
histogram_tester.ExpectBucketCount(
"OptimizationGuide.ProcessHintsResult",
static_cast<int>(
@@ -1482,7 +1488,8 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessMultipleNewConfigs) {
2);
}
-TEST_F(PreviewsOptimizationGuideTest, ProcessHintConfigWithNoKeyFailsDcheck) {
+TEST_F(PreviewsOptimizationGuideImplTest,
+ ProcessHintConfigWithNoKeyFailsDcheck) {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint = config.add_hints();
hint->set_key_representation(optimization_guide::proto::HOST_SUFFIX);
@@ -1492,12 +1499,10 @@ TEST_F(PreviewsOptimizationGuideTest, ProcessHintConfigWithNoKeyFailsDcheck) {
page_hint1->add_whitelisted_optimizations();
optimization1->set_optimization_type(optimization_guide::proto::NOSCRIPT);
- EXPECT_DCHECK_DEATH({
- ProcessHints(config, "2.0.0");
- });
+ EXPECT_DCHECK_DEATH({ ProcessHints(config, "2.0.0"); });
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
ProcessHintsConfigWithDuplicateKeysFailsDcheck) {
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint1 = config.add_hints();
@@ -1517,75 +1522,73 @@ TEST_F(PreviewsOptimizationGuideTest,
page_hint2->add_whitelisted_optimizations();
optimization2->set_optimization_type(optimization_guide::proto::NOSCRIPT);
- EXPECT_DCHECK_DEATH({
- ProcessHints(config, "2.0.0");
- });
+ EXPECT_DCHECK_DEATH({ ProcessHints(config, "2.0.0"); });
}
-TEST_F(PreviewsOptimizationGuideTest, MaybeLoadOptimizationHints) {
+TEST_F(PreviewsOptimizationGuideImplTest, MaybeLoadOptimizationHints) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify whitelisting from loaded page hints.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain.org/unhinted"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
MaybeLoadPageHintsWithTwoExperimentsDisabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify whitelisting from loaded page hints.
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain.org/unhinted"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
MaybeLoadPageHintsWithFirstExperimentEnabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
@@ -1597,32 +1600,32 @@ TEST_F(PreviewsOptimizationGuideTest,
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify whitelisting from loaded page hints.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain.org/unhinted"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
MaybeLoadPageHintsWithSecondExperimentEnabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
@@ -1634,32 +1637,32 @@ TEST_F(PreviewsOptimizationGuideTest,
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify whitelisting from loaded page hints.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain.org/unhinted"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
MaybeLoadPageHintsWithBothExperimentEnabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
@@ -1672,34 +1675,34 @@ TEST_F(PreviewsOptimizationGuideTest,
InitializeFixedCountResourceLoadingHintsWithTwoExperiments();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify whitelisting from loaded page hints.
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/football/seahawksrebuildingyear"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain.org/unhinted"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
// Test that optimization hints with multiple page patterns is processed
// correctly.
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
LoadManyResourceLoadingOptimizationHints) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
@@ -1708,61 +1711,66 @@ TEST_F(PreviewsOptimizationGuideTest,
const size_t page_patterns_per_key = 25;
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
InitializeMultipleResourceLoadingHints(key_count, page_patterns_per_key);
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain0.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain0.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain0.org/news0/football"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain49.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain49.org/news0/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain50.org/"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain50.org/news0/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
-
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain0.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain0.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://somedomain0.org/news0/football")));
+ EXPECT_TRUE(
+ CallMaybeLoadOptimizationHints(GURL("https://somedomain49.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://somedomain49.org/news0/football")));
+ EXPECT_FALSE(
+ CallMaybeLoadOptimizationHints(GURL("https://somedomain50.org/")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(
+ GURL("https://somedomain50.org/news0/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
+
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain0.org/news0/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain0.org/news24/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain0.org/news25/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain49.org/news0/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain49.org/news24/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain49.org/news25/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain50.org/news0/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain50.org/news24/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain50.org/news25/football"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
RunUntilIdle();
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
MaybeLoadOptimizationHintsWithoutEnabledPageHintsFeature) {
// Without PageHints-oriented feature enabled, never see
// enabled, the optimization should be disabled.
@@ -1771,85 +1779,96 @@ TEST_F(PreviewsOptimizationGuideTest,
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org"), base::DoNothing()));
+ EXPECT_TRUE(
+ CallMaybeLoadOptimizationHints(GURL("https://www.somedomain.org")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
}
-TEST_F(PreviewsOptimizationGuideTest, PreviewsUserDataPopulatedCorrectly) {
+TEST_F(PreviewsOptimizationGuideImplTest, PreviewsUserDataPopulatedCorrectly) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kResourceLoadingHints);
InitializeFixedCountResourceLoadingHints();
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://somedomain.org/"), base::DoNothing()));
- EXPECT_TRUE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.somedomain.org/news/football"), base::DoNothing()));
- EXPECT_FALSE(guide()->MaybeLoadOptimizationHints(
- GURL("https://www.unknown.com"), base::DoNothing()));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(GURL("https://somedomain.org/")));
+ EXPECT_TRUE(CallMaybeLoadOptimizationHints(
+ GURL("https://www.somedomain.org/news/football")));
+ EXPECT_FALSE(CallMaybeLoadOptimizationHints(GURL("https://www.unknown.com")));
RunUntilIdle();
PreviewsUserData user_data(kDefaultPageId);
- net::EffectiveConnectionType ect_threshold;
// Verify whitelisting from loaded page hints.
- EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_FALSE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data, GURL("https://www.somedomain.org/unhinted"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
EXPECT_EQ(base::nullopt, user_data.serialized_hint_version_string());
- EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIsWhitelisted(
+ EXPECT_TRUE(MaybeLoadOptimizationHintsAndCheckIfCanApplyPreview(
&user_data,
GURL("https://www.somedomain.org/news/weather/raininginseattle"),
- PreviewsType::RESOURCE_LOADING_HINTS, &ect_threshold));
+ PreviewsType::RESOURCE_LOADING_HINTS,
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G));
EXPECT_EQ("someversion", user_data.serialized_hint_version_string());
}
-TEST_F(PreviewsOptimizationGuideTest, IsBlacklisted) {
+TEST_F(PreviewsOptimizationGuideImplTest,
+ CanApplyPreviewWithLitePageServerPreviewsEnabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
+ network_quality_tracker()->ReportEffectiveConnectionTypeForTesting(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
- EXPECT_TRUE(
- guide()->IsBlacklisted(GURL("https://m.blacklisteddomain.com/path"),
- PreviewsType::LITE_PAGE_REDIRECT));
+ PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://m.blacklisteddomain.com/path"));
+ EXPECT_FALSE(guide()->CanApplyPreview(&user_data, &navigation_handle,
+ PreviewsType::LITE_PAGE_REDIRECT));
InitializeWithLitePageRedirectBlacklist();
- EXPECT_TRUE(
- guide()->IsBlacklisted(GURL("https://m.blacklisteddomain.com/path"),
- PreviewsType::LITE_PAGE_REDIRECT));
- EXPECT_DCHECK_DEATH(guide()->IsBlacklisted(
- GURL("https://m.blacklisteddomain.com/path"), PreviewsType::NOSCRIPT));
+ EXPECT_FALSE(guide()->CanApplyPreview(&user_data, &navigation_handle,
+ PreviewsType::LITE_PAGE_REDIRECT));
- EXPECT_TRUE(guide()->IsBlacklisted(
- GURL("https://blacklistedsubdomain.maindomain.co.in"),
+ content::MockNavigationHandle blacklisted_subdomain_navigation_handle;
+ blacklisted_subdomain_navigation_handle.set_url(
+ GURL("https://blacklistedsubdomain.maindomain.co.in"));
+ EXPECT_FALSE(guide()->CanApplyPreview(
+ &user_data, &blacklisted_subdomain_navigation_handle,
PreviewsType::LITE_PAGE_REDIRECT));
- EXPECT_FALSE(guide()->IsBlacklisted(GURL("https://maindomain.co.in"),
- PreviewsType::LITE_PAGE_REDIRECT));
+ content::MockNavigationHandle main_domain_navigation_handle;
+ main_domain_navigation_handle.set_url(GURL("https://maindomain.co.in"));
+ EXPECT_TRUE(guide()->CanApplyPreview(&user_data,
+ &main_domain_navigation_handle,
+ PreviewsType::LITE_PAGE_REDIRECT));
}
-TEST_F(PreviewsOptimizationGuideTest,
- IsBlacklistedWithLitePageServerPreviewsDisabled) {
+TEST_F(PreviewsOptimizationGuideImplTest,
+ CanApplyPreviewWithLitePageServerPreviewsDisabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndDisableFeature(features::kLitePageServerPreviews);
+ network_quality_tracker()->ReportEffectiveConnectionTypeForTesting(
+ net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
InitializeWithLitePageRedirectBlacklist();
- EXPECT_TRUE(
- guide()->IsBlacklisted(GURL("https://m.blacklisteddomain.com/path"),
- PreviewsType::LITE_PAGE_REDIRECT));
+ PreviewsUserData user_data(kDefaultPageId);
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_url(GURL("https://m.blacklisteddomain.com/path"));
+ EXPECT_FALSE(guide()->CanApplyPreview(&user_data, &navigation_handle,
+ PreviewsType::LITE_PAGE_REDIRECT));
}
-TEST_F(PreviewsOptimizationGuideTest, RemoveObserverCalledAtDestruction) {
+TEST_F(PreviewsOptimizationGuideImplTest, RemoveObserverCalledAtDestruction) {
EXPECT_FALSE(optimization_guide_service()->RemoveObserverCalled());
ResetGuide();
@@ -1857,7 +1876,7 @@ TEST_F(PreviewsOptimizationGuideTest, RemoveObserverCalledAtDestruction) {
EXPECT_TRUE(optimization_guide_service()->RemoveObserverCalled());
}
-TEST_F(PreviewsOptimizationGuideTest, HintsFetcherEnabledNoHosts) {
+TEST_F(PreviewsOptimizationGuideImplTest, HintsFetcherEnabledNoHosts) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -1876,7 +1895,7 @@ TEST_F(PreviewsOptimizationGuideTest, HintsFetcherEnabledNoHosts) {
EXPECT_FALSE(hints_fetcher()->hints_fetched());
}
-TEST_F(PreviewsOptimizationGuideTest,
+TEST_F(PreviewsOptimizationGuideImplTest,
HintsFetcherEnabledWithHostsNoHintsInResponse) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -1906,7 +1925,7 @@ TEST_F(PreviewsOptimizationGuideTest,
EXPECT_CALL(*top_host_provider(), GetTopHosts(testing::_)).Times(0);
}
-TEST_F(PreviewsOptimizationGuideTest, HintsFetcherEnabledWithHosts) {
+TEST_F(PreviewsOptimizationGuideImplTest, HintsFetcherEnabledWithHosts) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -1929,7 +1948,7 @@ TEST_F(PreviewsOptimizationGuideTest, HintsFetcherEnabledWithHosts) {
EXPECT_TRUE(hints_fetcher()->hints_fetched());
}
-TEST_F(PreviewsOptimizationGuideTest, HintsFetcherTimerRetryDelay) {
+TEST_F(PreviewsOptimizationGuideImplTest, HintsFetcherTimerRetryDelay) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -1959,7 +1978,7 @@ TEST_F(PreviewsOptimizationGuideTest, HintsFetcherTimerRetryDelay) {
EXPECT_TRUE(hints_fetcher()->hints_fetched());
}
-TEST_F(PreviewsOptimizationGuideTest, HintsFetcherTimerFetchSucceeds) {
+TEST_F(PreviewsOptimizationGuideImplTest, HintsFetcherTimerFetchSucceeds) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -1993,7 +2012,7 @@ TEST_F(PreviewsOptimizationGuideTest, HintsFetcherTimerFetchSucceeds) {
EXPECT_TRUE(hints_fetcher()->hints_fetched());
}
-TEST_F(PreviewsOptimizationGuideTest, HintsFetcherDisabled) {
+TEST_F(PreviewsOptimizationGuideImplTest, HintsFetcherDisabled) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndDisableFeature(
optimization_guide::features::kOptimizationHintsFetching);
@@ -2006,7 +2025,7 @@ TEST_F(PreviewsOptimizationGuideTest, HintsFetcherDisabled) {
InitializeFixedCountResourceLoadingHints();
}
-TEST_F(PreviewsOptimizationGuideTest, HintsFetcherLastFetchAtttempt) {
+TEST_F(PreviewsOptimizationGuideImplTest, HintsFetcherLastFetchAtttempt) {
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeature(
@@ -2045,14 +2064,14 @@ TEST_F(PreviewsOptimizationGuideTest, HintsFetcherLastFetchAtttempt) {
}
class PreviewsOptimizationGuideDataSaverOffTest
- : public PreviewsOptimizationGuideTest {
+ : public PreviewsOptimizationGuideImplTest {
public:
PreviewsOptimizationGuideDataSaverOffTest() {}
~PreviewsOptimizationGuideDataSaverOffTest() override {}
void SetUp() override {
- PreviewsOptimizationGuideTest::SetUp();
+ PreviewsOptimizationGuideImplTest::SetUp();
DisableDataSaver();
}
diff --git a/chromium/components/previews/content/previews_ui_service_unittest.cc b/chromium/components/previews/content/previews_ui_service_unittest.cc
index eede77b0d6b..a5ae8be8ea4 100644
--- a/chromium/components/previews/content/previews_ui_service_unittest.cc
+++ b/chromium/components/previews/content/previews_ui_service_unittest.cc
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/default_clock.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h"
#include "components/previews/content/previews_decider_impl.h"
@@ -214,7 +214,7 @@ class PreviewsUIServiceTest : public testing::Test {
protected:
// Run this test on a single thread.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestPreviewsLogger* logger_ptr_;
network::TestNetworkQualityTracker test_network_quality_tracker_;
@@ -300,7 +300,7 @@ TEST_F(PreviewsUIServiceTest, TestLogPreviewDecisionMadePassesCorrectParams) {
const base::Time time_b = base::Time::Now();
PreviewsType type_b = PreviewsType::OFFLINE;
std::vector<PreviewsEligibilityReason> passed_reasons_b = {
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER,
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE,
PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE,
};
const std::vector<PreviewsEligibilityReason> expected_passed_reasons_b(
diff --git a/chromium/components/previews/core/BUILD.gn b/chromium/components/previews/core/BUILD.gn
index 886262afa0b..28540a569d3 100644
--- a/chromium/components/previews/core/BUILD.gn
+++ b/chromium/components/previews/core/BUILD.gn
@@ -6,9 +6,6 @@ static_library("core") {
sources = [
"previews_black_list.cc",
"previews_black_list.h",
- "previews_constants.cc",
- "previews_constants.h",
- "previews_decider.h",
"previews_experiments.cc",
"previews_experiments.h",
"previews_features.cc",
@@ -32,24 +29,6 @@ static_library("core") {
]
}
-static_library("test_support") {
- testonly = true
- sources = [
- "test_previews_decider.cc",
- "test_previews_decider.h",
- ]
-
- deps = [
- ":core",
- "//base",
- "//base/test:test_support",
- "//net",
- "//net:test_support",
- "//testing/gmock",
- "//testing/gtest",
- ]
-}
-
source_set("unit_tests") {
testonly = true
sources = [
@@ -61,7 +40,6 @@ source_set("unit_tests") {
deps = [
":core",
- ":test_support",
"//base",
"//base/test:test_support",
"//components/blacklist/opt_out_blacklist",
diff --git a/chromium/components/previews/core/previews_black_list.h b/chromium/components/previews/core/previews_black_list.h
index 50d2e56b615..115548ebedb 100644
--- a/chromium/components/previews/core/previews_black_list.h
+++ b/chromium/components/previews/core/previews_black_list.h
@@ -52,12 +52,16 @@ enum class PreviewsEligibilityReason {
NETWORK_NOT_SLOW = 7,
// If the page was reloaded, the user should not be shown a stale preview.
RELOAD_DISALLOWED = 8,
- // The host is explicitly blacklisted by the server, so the user was not shown
+ // DEPRECATED: The host is explicitly blacklisted by the server, so the user
+ // was not shown
// a preview.
- HOST_BLACKLISTED_BY_SERVER = 9,
- // The host is not whitelisted by the server for a preview decision that uses
+ // Replaced by NOT_ALLOWED_BY_OPTIMIZATION_HINTS.
+ DEPRECATED_HOST_BLACKLISTED_BY_SERVER = 9,
+ // DEPRECATED: The host is not whitelisted by the server for a preview
+ // decision that uses
// server optimization hints.
- HOST_NOT_WHITELISTED_BY_SERVER = 10,
+ // Replaced by NOT_ALLOWED_BY_OPTIMIZATION_HINTS.
+ DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER = 10,
// The preview is allowed but without an expected check of server optimization
// hints because they are not enabled (features::kOptimizationHints).
ALLOWED_WITHOUT_OPTIMIZATION_HINTS = 11,
@@ -77,6 +81,12 @@ enum class PreviewsEligibilityReason {
OPTIMIZATION_HINTS_NOT_AVAILABLE = 17,
// The navigation URL has a media suffix which is excluded from previews.
EXCLUDED_BY_MEDIA_SUFFIX = 18,
+ // The Optimization Guide was checked for this preview type and the
+ // optimization guide did not allow this preview type in the current browser
+ // conditions.
+ NOT_ALLOWED_BY_OPTIMIZATION_GUIDE = 19,
+ // The preview was not performed due to a coinflip experiment holdback.
+ COINFLIP_HOLDBACK = 20,
LAST,
};
diff --git a/chromium/components/previews/core/previews_black_list_unittest.cc b/chromium/components/previews/core/previews_black_list_unittest.cc
index 5db93c2a27f..63f451eedb1 100644
--- a/chromium/components/previews/core/previews_black_list_unittest.cc
+++ b/chromium/components/previews/core/previews_black_list_unittest.cc
@@ -18,8 +18,8 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h"
@@ -152,7 +152,7 @@ class PreviewsBlackListTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
// Observer to |black_list_|.
TestOptOutBlacklistDelegate blacklist_delegate_;
diff --git a/chromium/components/previews/core/previews_constants.cc b/chromium/components/previews/core/previews_constants.cc
deleted file mode 100644
index 68263516701..00000000000
--- a/chromium/components/previews/core/previews_constants.cc
+++ /dev/null
@@ -1,12 +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 "components/previews/core/previews_constants.h"
-
-namespace previews {
-
-const char kPreviewsOptimizationGuideOnLoadedHintResultHistogramString[] =
- "PreviewsOptimizationGuide.OnLoadedHint.Result";
-
-} // namespace previews
diff --git a/chromium/components/previews/core/previews_constants.h b/chromium/components/previews/core/previews_constants.h
deleted file mode 100644
index 7c90a473449..00000000000
--- a/chromium/components/previews/core/previews_constants.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PREVIEWS_CORE_PREVIEWS_CONSTANTS_H_
-#define COMPONENTS_PREVIEWS_CORE_PREVIEWS_CONSTANTS_H_
-
-namespace previews {
-
-// The local histogram used by PreviewsOptimizationGuide to record that a hint
-// finished loading.
-extern const char kPreviewsOptimizationGuideOnLoadedHintResultHistogramString[];
-
-} // namespace previews
-
-#endif // COMPONENTS_PREVIEWS_CORE_PREVIEWS_CONSTANTS_H_
diff --git a/chromium/components/previews/core/previews_experiments.cc b/chromium/components/previews/core/previews_experiments.cc
index 82e1272397e..8f649df295e 100644
--- a/chromium/components/previews/core/previews_experiments.cc
+++ b/chromium/components/previews/core/previews_experiments.cc
@@ -13,7 +13,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "components/previews/core/previews_constants.h"
#include "components/previews/core/previews_features.h"
#include "components/previews/core/previews_switches.h"
#include "net/base/url_util.h"
@@ -48,7 +47,6 @@ const char kSessionMaxECTTrigger[] = "session_max_ect_trigger";
const char kNoScriptInflationPercent[] = "NoScriptInflationPercent";
const char kNoScriptInflationBytes[] = "NoScriptInflationBytes";
-
// Inflation parameters for estimating ResourceLoadingHints data savings.
const char kResourceLoadingHintsInflationPercent[] =
"ResourceLoadingHintsInflationPercent";
@@ -161,12 +159,6 @@ base::TimeDelta LitePagePreviewsNavigationTimeoutDuration() {
30 * 1000));
}
-int LitePageRedirectPreviewMaxServerBlacklistByteSize() {
- return base::GetFieldTrialParamByFeatureAsInt(
- features::kLitePageServerPreviews, "max_blacklist_byte_size",
- 250 * 1024 /* 250KB */);
-}
-
size_t LitePageRedirectPreviewMaxNavigationRestarts() {
return base::GetFieldTrialParamByFeatureAsInt(
features::kLitePageServerPreviews, "max_navigation_restart", 5);
@@ -222,15 +214,68 @@ bool IsInLitePageRedirectControl() {
features::kLitePageServerPreviews, "control_group", false);
}
+bool LitePageRedirectPreviewShouldPreconnect() {
+ return base::GetFieldTrialParamByFeatureAsBool(
+ features::kLitePageServerPreviews, "preconnect_on_slow_connections",
+ false);
+}
+
bool LitePageRedirectPreviewShouldPresolve() {
return base::GetFieldTrialParamByFeatureAsBool(
features::kLitePageServerPreviews, "preresolve_on_slow_connections",
true);
}
-base::TimeDelta LitePageRedirectPreviewPresolveInterval() {
+bool LitePageRedirectPreviewIgnoresOptimizationGuideFilter() {
+ return base::GetFieldTrialParamByFeatureAsBool(
+ features::kLitePageServerPreviews,
+ "ignore_optimization_guide_filtering", false) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kIgnoreLitePageRedirectOptimizationBlacklist);
+}
+
+bool LitePageRedirectOnlyTriggerOnSuccessfulProbe() {
+ return base::GetFieldTrialParamByFeatureAsBool(
+ features::kLitePageServerPreviews, "only_trigger_after_probe_success",
+ true);
+}
+
+GURL LitePageRedirectProbeURL() {
+ GURL url(GetFieldTrialParamValueByFeature(features::kLitePageServerPreviews,
+ "full_probe_url"));
+ if (url.is_valid())
+ return url;
+ return GURL("https://litepages.googlezip.net/e2e_probe");
+}
+
+base::TimeDelta LitePageRedirectPreviewPreresolvePreconnectInterval() {
return base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
- features::kLitePageServerPreviews, "preresolve_interval_in_seconds", 60));
+ features::kLitePageServerPreviews,
+ "preresolveconnect_interval_in_seconds", 60));
+}
+
+net::EffectiveConnectionType
+LitePageRedirectPreviewPreresolvePreconnectECTThreshold() {
+ return GetParamValueAsECTByFeature(features::kLitePageServerPreviews,
+ "preresolveconnect_ect_threshold",
+ net::EFFECTIVE_CONNECTION_TYPE_2G);
+}
+
+base::TimeDelta LitePageRedirectPreviewProbeInterval() {
+ return base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
+ features::kLitePageServerPreviews, "probe_interval_in_seconds", 30));
+}
+
+bool LitePageRedirectShouldProbeOrigin() {
+ return base::GetFieldTrialParamByFeatureAsBool(
+ features::kLitePageServerPreviews, "should_probe_origin", false);
+}
+
+base::TimeDelta LitePageRedirectPreviewOriginProbeTimeout() {
+ return base::TimeDelta::FromMilliseconds(
+ base::GetFieldTrialParamByFeatureAsInt(features::kLitePageServerPreviews,
+ "origin_probe_timeout_ms",
+ 30 * 1000));
}
net::EffectiveConnectionType GetECTThresholdForPreview(
diff --git a/chromium/components/previews/core/previews_experiments.h b/chromium/components/previews/core/previews_experiments.h
index 464d011feed..6a1f7694441 100644
--- a/chromium/components/previews/core/previews_experiments.h
+++ b/chromium/components/previews/core/previews_experiments.h
@@ -126,20 +126,46 @@ bool LitePagePreviewsTriggerOnLocalhost();
// page hints for the host.
bool LitePagePreviewsOverridePageHints();
-// The maximum data byte size for the server-provided blacklist. This is
-// a client-side safety limit for RAM use in case server sends too large of
-// a blacklist.
-int LitePageRedirectPreviewMaxServerBlacklistByteSize();
-
// The maximum number of times that a Lite Page Redirect preview should restart
// a navigation.
size_t LitePageRedirectPreviewMaxNavigationRestarts();
-// Whether we should preresolve the lite page redirect server.
+// Whether we should preconnect to the lite page redirect server or the origin.
+bool LitePageRedirectPreviewShouldPreconnect();
+
+// Whether we should preresolve the lite page redirect server or the origin.
bool LitePageRedirectPreviewShouldPresolve();
-// The duration in between preresolving the lite page redirect server.
-base::TimeDelta LitePageRedirectPreviewPresolveInterval();
+// Whether the Optimization Guide logic should be ignored for lite page redirect
+// previews.
+bool LitePageRedirectPreviewIgnoresOptimizationGuideFilter();
+
+// Whether to only trigger a lite page preview if there has been a successful
+// probe to the server. This is returns true, lite page redirect previews should
+// only been attempted when a probe to the previews server has completed
+// successfully.
+bool LitePageRedirectOnlyTriggerOnSuccessfulProbe();
+
+// The URL to probe on the lite pages server.
+GURL LitePageRedirectProbeURL();
+
+// The duration in between preresolving or preconnecting the lite page redirect
+// server or the origin.
+base::TimeDelta LitePageRedirectPreviewPreresolvePreconnectInterval();
+
+// The ect threshold at which, or below, we should preresolve or preconnect for
+// lite page redirect previews.
+net::EffectiveConnectionType
+LitePageRedirectPreviewPreresolvePreconnectECTThreshold();
+
+// The duration in between probes to the lite page redirect server.
+base::TimeDelta LitePageRedirectPreviewProbeInterval();
+
+// Whether the origin should be successfully probed before showing a preview.
+bool LitePageRedirectShouldProbeOrigin();
+
+// The timeout for the origin probe on lite page redirect previews.
+base::TimeDelta LitePageRedirectPreviewOriginProbeTimeout();
// The maximum number of seconds to loadshed the Previews server for.
int PreviewServerLoadshedMaxSeconds();
diff --git a/chromium/components/previews/core/previews_experiments_unittest.cc b/chromium/components/previews/core/previews_experiments_unittest.cc
index 01c3f9b0844..32efbca21db 100644
--- a/chromium/components/previews/core/previews_experiments_unittest.cc
+++ b/chromium/components/previews/core/previews_experiments_unittest.cc
@@ -15,7 +15,6 @@
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
-#include "components/previews/core/previews_constants.h"
#include "components/previews/core/previews_features.h"
#include "components/variations/variations_associated_data.h"
diff --git a/chromium/components/previews/core/previews_logger.cc b/chromium/components/previews/core/previews_logger.cc
index a28a1e1d973..d305a26548d 100644
--- a/chromium/components/previews/core/previews_logger.cc
+++ b/chromium/components/previews/core/previews_logger.cc
@@ -61,10 +61,10 @@ std::string GetReasonDescription(PreviewsEligibilityReason reason,
return want_inverse_description
? "Page reloads allowed"
: "Page reloads do not show previews for this preview type";
- case PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER:
+ case PreviewsEligibilityReason::DEPRECATED_HOST_BLACKLISTED_BY_SERVER:
return want_inverse_description ? "Host not blacklisted by server rules"
: "Host blacklisted by server rules";
- case PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER:
+ case PreviewsEligibilityReason::DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER:
return want_inverse_description ? "Host whitelisted by server rules"
: "Host not whitelisted by server rules";
case PreviewsEligibilityReason::ALLOWED_WITHOUT_OPTIMIZATION_HINTS:
@@ -95,6 +95,12 @@ std::string GetReasonDescription(PreviewsEligibilityReason reason,
return want_inverse_description
? "URL suffix is not an excluded media suffix previews"
: "URL suffix is an excluded media suffix";
+ case PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE:
+ return want_inverse_description ? "Allowed by server rules"
+ : "Not allowed by server rules";
+ case PreviewsEligibilityReason::COINFLIP_HOLDBACK:
+ DCHECK(!want_inverse_description);
+ return "Coin flip holdback encountered";
case PreviewsEligibilityReason::LAST:
break;
}
diff --git a/chromium/components/previews/core/previews_logger_unittest.cc b/chromium/components/previews/core/previews_logger_unittest.cc
index aa31811322e..84ec94e40f7 100644
--- a/chromium/components/previews/core/previews_logger_unittest.cc
+++ b/chromium/components/previews/core/previews_logger_unittest.cc
@@ -539,7 +539,7 @@ TEST_F(PreviewsLoggerTest,
TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionServerRulesFailed) {
std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
- PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER,
+ PreviewsEligibilityReason::DEPRECATED_HOST_BLACKLISTED_BY_SERVER,
true /* final_reason */);
std::string expected_description = "Host blacklisted by server rules";
EXPECT_EQ(expected_description, actual_description);
@@ -547,7 +547,7 @@ TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionServerRulesFailed) {
TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionServerRulesChecked) {
std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
- PreviewsEligibilityReason::HOST_BLACKLISTED_BY_SERVER,
+ PreviewsEligibilityReason::DEPRECATED_HOST_BLACKLISTED_BY_SERVER,
false /* final_reason */);
std::string expected_description = "Host not blacklisted by server rules";
EXPECT_EQ(expected_description, actual_description);
@@ -556,7 +556,7 @@ TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionServerRulesChecked) {
TEST_F(PreviewsLoggerTest,
LogPreviewDecisionDescriptionNotWhitelisedByServerFailed) {
std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER,
+ PreviewsEligibilityReason::DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER,
true /* final_reason */);
std::string expected_description = "Host not whitelisted by server rules";
EXPECT_EQ(expected_description, actual_description);
@@ -565,7 +565,7 @@ TEST_F(PreviewsLoggerTest,
TEST_F(PreviewsLoggerTest,
LogPreviewDecisionDescriptionNotWhitelisedByServerChecked) {
std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
- PreviewsEligibilityReason::HOST_NOT_WHITELISTED_BY_SERVER,
+ PreviewsEligibilityReason::DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER,
false /* final_reason */);
std::string expected_description = "Host whitelisted by server rules";
EXPECT_EQ(expected_description, actual_description);
@@ -607,6 +607,24 @@ TEST_F(PreviewsLoggerTest,
EXPECT_EQ(expected_description, actual_description);
}
+TEST_F(PreviewsLoggerTest,
+ LogPreviewDecisionDescriptionNotAllowedByOptimizationGuide) {
+ std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE,
+ true /*final_reason */);
+ std::string expected_description = "Not allowed by server rules";
+ EXPECT_EQ(expected_description, actual_description);
+}
+
+TEST_F(PreviewsLoggerTest,
+ LogPreviewDecisionDescriptionAllowedByOptimizationGuide) {
+ std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
+ PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE,
+ false /*final_reason */);
+ std::string expected_description = "Allowed by server rules";
+ EXPECT_EQ(expected_description, actual_description);
+}
+
TEST_F(PreviewsLoggerTest, NotifyObserversOfNewBlacklistedHost) {
TestPreviewsLoggerObserver observers[3];
diff --git a/chromium/components/previews/core/test_previews_decider.cc b/chromium/components/previews/core/test_previews_decider.cc
deleted file mode 100644
index 93fba96ccdc..00000000000
--- a/chromium/components/previews/core/test_previews_decider.cc
+++ /dev/null
@@ -1,41 +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 "components/previews/core/test_previews_decider.h"
-
-namespace previews {
-
-TestPreviewsDecider::TestPreviewsDecider(bool allow_previews)
- : allow_previews_(allow_previews) {}
-
-TestPreviewsDecider::~TestPreviewsDecider() {}
-
-bool TestPreviewsDecider::ShouldAllowPreviewAtNavigationStart(
- PreviewsUserData* previews_data,
- const GURL& url,
- bool is_reload,
- PreviewsType type) const {
- return allow_previews_;
-}
-
-bool TestPreviewsDecider::ShouldCommitPreview(PreviewsUserData* previews_data,
- const GURL& url,
- PreviewsType type) const {
- return allow_previews_;
-}
-
-bool TestPreviewsDecider::LoadPageHints(const GURL& url) {
- return true;
-}
-
-bool TestPreviewsDecider::GetResourceLoadingHints(
- const GURL& url,
- std::vector<std::string>* out_resource_patterns_to_block) const {
- return false;
-}
-
-void TestPreviewsDecider::LogHintCacheMatch(const GURL& url,
- bool is_committed) const {}
-
-} // namespace previews
diff --git a/chromium/components/previews/core/test_previews_decider.h b/chromium/components/previews/core/test_previews_decider.h
deleted file mode 100644
index a9f8905d893..00000000000
--- a/chromium/components/previews/core/test_previews_decider.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PREVIEWS_CORE_TEST_PREVIEWS_DECIDER_H_
-#define COMPONENTS_PREVIEWS_CORE_TEST_PREVIEWS_DECIDER_H_
-
-#include "components/previews/core/previews_decider.h"
-
-namespace previews {
-
-// Simple test implementation of PreviewsDecider interface.
-class TestPreviewsDecider : public previews::PreviewsDecider {
- public:
- TestPreviewsDecider(bool allow_previews);
- ~TestPreviewsDecider() override;
-
- // previews::PreviewsDecider:
- bool ShouldAllowPreviewAtNavigationStart(PreviewsUserData* previews_data,
- const GURL& url,
- bool is_reload,
- PreviewsType type) const override;
- bool ShouldCommitPreview(PreviewsUserData* previews_data,
- const GURL& url,
- PreviewsType type) const override;
- bool LoadPageHints(const GURL& url) override;
- bool GetResourceLoadingHints(
- const GURL& url,
- std::vector<std::string>* out_resource_patterns_to_block) const override;
- void LogHintCacheMatch(const GURL& url, bool is_committed) const override;
-
- private:
- bool allow_previews_;
-};
-
-} // namespace previews
-
-#endif // COMPONENTS_PREVIEWS_CORE_TEST_PREVIEWS_DECIDER_H_
diff --git a/chromium/components/printing/browser/BUILD.gn b/chromium/components/printing/browser/BUILD.gn
index b1151c06115..fffc1354617 100644
--- a/chromium/components/printing/browser/BUILD.gn
+++ b/chromium/components/printing/browser/BUILD.gn
@@ -37,12 +37,13 @@ static_library("browser") {
deps = [
"//base",
"//components/crash/core/common",
+ "//components/discardable_memory/service",
"//components/printing/common",
+ "//components/services/pdf_compositor/public/cpp",
"//components/services/pdf_compositor/public/mojom",
"//components/strings:components_strings_grit",
"//printing",
"//printing/common:common",
- "//services/service_manager/public/cpp",
"//ui/base",
"//ui/gfx/geometry",
]
diff --git a/chromium/components/printing/browser/DEPS b/chromium/components/printing/browser/DEPS
index 7e4576e9016..e2f3e327b45 100644
--- a/chromium/components/printing/browser/DEPS
+++ b/chromium/components/printing/browser/DEPS
@@ -1,11 +1,10 @@
include_rules = [
"+components/crash/core/common",
- "+components/services/pdf_compositor/public/cpp",
- "+components/services/pdf_compositor/public/mojom",
+ "+components/discardable_memory/service",
+ "+components/services/pdf_compositor/public",
"+components/strings/grit",
"+content/public/browser",
- "+mojo/public/cpp/system",
- "+services/service_manager/public/cpp",
+ "+mojo/public",
"+ui/base/l10n",
]
diff --git a/chromium/components/printing/browser/print_composite_client.cc b/chromium/components/printing/browser/print_composite_client.cc
index 36cbc913fb7..941c8fb674c 100644
--- a/chromium/components/printing/browser/print_composite_client.cc
+++ b/chromium/components/printing/browser/print_composite_client.cc
@@ -9,14 +9,18 @@
#include "base/bind.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/stl_util.h"
+#include "base/task/post_task.h"
+#include "build/build_config.h"
+#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
#include "components/printing/common/print_messages.h"
#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/system_connector.h"
+#include "content/public/browser/service_process_host.h"
#include "printing/printing_utils.h"
-#include "services/service_manager/public/cpp/connector.h"
namespace printing {
@@ -56,6 +60,14 @@ ContentToFrameMap ConvertContentInfoMap(
return content_frame_map;
}
+void BindDiscardableSharedMemoryManagerOnIOThread(
+ mojo::PendingReceiver<
+ discardable_memory::mojom::DiscardableSharedMemoryManager> receiver) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ discardable_memory::DiscardableSharedMemoryManager::Get()->Bind(
+ std::move(receiver), {});
+}
+
} // namespace
PrintCompositeClient::PrintCompositeClient(content::WebContents* web_contents)
@@ -84,7 +96,7 @@ void PrintCompositeClient::RenderFrameDeleted(
// When a subframe we are expecting is deleted, we should notify pdf
// compositor service.
for (int doc_cookie : iter->second) {
- auto& compositor = GetCompositeRequest(doc_cookie);
+ auto* compositor = GetCompositeRequest(doc_cookie);
compositor->NotifyUnavailableSubframe(frame_guid);
}
pending_subframe_cookies_.erase(iter);
@@ -113,7 +125,7 @@ void PrintCompositeClient::OnDidPrintFrameContent(
// Content in |params| is sent from untrusted source; only minimal processing
// is done here. Most of it will be directly forwarded to pdf compositor
// service.
- auto& compositor = GetCompositeRequest(document_cookie);
+ auto* compositor = GetCompositeRequest(document_cookie);
auto region = params.metafile_data_region.Duplicate();
uint64_t frame_guid = GenerateFrameGuid(render_frame_host);
compositor->AddSubframeContent(
@@ -138,7 +150,7 @@ void PrintCompositeClient::PrintCrossProcessSubframe(
if (!subframe_host->IsRenderFrameLive()) {
// When the subframe is dead, no need to send message,
// just notify the service.
- auto& compositor = GetCompositeRequest(document_cookie);
+ auto* compositor = GetCompositeRequest(document_cookie);
compositor->NotifyUnavailableSubframe(frame_guid);
return;
}
@@ -170,7 +182,7 @@ void PrintCompositeClient::DoCompositePageToPdf(
mojom::PdfCompositor::CompositePageToPdfCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- auto& compositor = GetCompositeRequest(document_cookie);
+ auto* compositor = GetCompositeRequest(document_cookie);
auto region = content.metafile_data_region.Duplicate();
compositor->CompositePageToPdf(
GenerateFrameGuid(render_frame_host), std::move(region),
@@ -186,7 +198,7 @@ void PrintCompositeClient::DoCompositeDocumentToPdf(
mojom::PdfCompositor::CompositeDocumentToPdfCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- auto& compositor = GetCompositeRequest(document_cookie);
+ auto* compositor = GetCompositeRequest(document_cookie);
auto region = content.metafile_data_region.Duplicate();
// Since this class owns compositor, compositor will be gone when this class
@@ -220,15 +232,15 @@ void PrintCompositeClient::OnDidCompositeDocumentToPdf(
std::move(callback).Run(status, std::move(region));
}
-mojom::PdfCompositorPtr& PrintCompositeClient::GetCompositeRequest(int cookie) {
+mojom::PdfCompositor* PrintCompositeClient::GetCompositeRequest(int cookie) {
auto iter = compositor_map_.find(cookie);
if (iter != compositor_map_.end()) {
DCHECK(iter->second.is_bound());
- return iter->second;
+ return iter->second.get();
}
iter = compositor_map_.emplace(cookie, CreateCompositeRequest()).first;
- return iter->second;
+ return iter->second.get();
}
void PrintCompositeClient::RemoveCompositeRequest(int cookie) {
@@ -236,11 +248,23 @@ void PrintCompositeClient::RemoveCompositeRequest(int cookie) {
DCHECK_EQ(erased, 1u);
}
-mojom::PdfCompositorPtr PrintCompositeClient::CreateCompositeRequest() {
- if (!connector_)
- connector_ = content::GetSystemConnector()->Clone();
- mojom::PdfCompositorPtr compositor;
- connector_->BindInterface(mojom::kServiceName, &compositor);
+mojo::Remote<mojom::PdfCompositor>
+PrintCompositeClient::CreateCompositeRequest() {
+ auto compositor = content::ServiceProcessHost::Launch<mojom::PdfCompositor>(
+ content::ServiceProcessHost::Options()
+ .WithDisplayName(IDS_PDF_COMPOSITOR_SERVICE_DISPLAY_NAME)
+ .WithSandboxType(service_manager::SANDBOX_TYPE_PDF_COMPOSITOR)
+ .Pass());
+
+ mojo::PendingRemote<discardable_memory::mojom::DiscardableSharedMemoryManager>
+ discardable_memory_manager;
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(
+ &BindDiscardableSharedMemoryManagerOnIOThread,
+ discardable_memory_manager.InitWithNewPipeAndPassReceiver()));
+ compositor->SetDiscardableSharedMemoryManager(
+ std::move(discardable_memory_manager));
compositor->SetWebContentsURL(web_contents()->GetLastCommittedURL());
compositor->SetUserAgent(user_agent_);
return compositor;
diff --git a/chromium/components/printing/browser/print_composite_client.h b/chromium/components/printing/browser/print_composite_client.h
index 14756fbaf4a..c8102b7c20a 100644
--- a/chromium/components/printing/browser/print_composite_client.h
+++ b/chromium/components/printing/browser/print_composite_client.h
@@ -12,13 +12,10 @@
#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "mojo/public/cpp/bindings/remote.h"
struct PrintHostMsg_DidPrintContent_Params;
-namespace service_manager {
-class Connector;
-}
-
namespace printing {
// Class to manage print requests and their communication with pdf
@@ -86,18 +83,16 @@ class PrintCompositeClient
// Get the request or create a new one if none exists.
// Since printed pages always share content with its document, they share the
// same composite request.
- mojom::PdfCompositorPtr& GetCompositeRequest(int cookie);
+ mojom::PdfCompositor* GetCompositeRequest(int cookie);
// Remove an existing request from |compositor_map_|.
void RemoveCompositeRequest(int cookie);
- mojom::PdfCompositorPtr CreateCompositeRequest();
-
- std::unique_ptr<service_manager::Connector> connector_;
+ mojo::Remote<mojom::PdfCompositor> CreateCompositeRequest();
// Stores the mapping between document cookies and their corresponding
// requests.
- std::map<int, mojom::PdfCompositorPtr> compositor_map_;
+ std::map<int, mojo::Remote<mojom::PdfCompositor>> compositor_map_;
// Stores the mapping between render frame's global unique id and document
// cookies that requested such frame.
diff --git a/chromium/components/printing/browser/print_manager.cc b/chromium/components/printing/browser/print_manager.cc
index 3aa50285691..8579ed8a446 100644
--- a/chromium/components/printing/browser/print_manager.cc
+++ b/chromium/components/printing/browser/print_manager.cc
@@ -6,9 +6,60 @@
#include "build/build_config.h"
#include "components/printing/common/print_messages.h"
+#include "content/public/browser/render_frame_host.h"
namespace printing {
+struct PrintManager::FrameDispatchHelper {
+ PrintManager* manager;
+ content::RenderFrameHost* render_frame_host;
+
+ bool Send(IPC::Message* msg) { return render_frame_host->Send(msg); }
+
+ void OnGetDefaultPrintSettings(IPC::Message* reply_msg) {
+ manager->OnGetDefaultPrintSettings(render_frame_host, reply_msg);
+ }
+
+ void OnScriptedPrint(const PrintHostMsg_ScriptedPrint_Params& scripted_params,
+ IPC::Message* reply_msg) {
+ manager->OnScriptedPrint(render_frame_host, scripted_params, reply_msg);
+ }
+
+ void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params,
+ IPC::Message* reply_msg) {
+ // If DidPrintDocument message was received then need to transition from
+ // a variable allocated on stack (which has efficient memory management
+ // when dealing with any other incoming message) to a persistent variable
+ // on the heap that can be referenced by the asynchronous processing which
+ // occurs beyond the scope of PrintViewManagerBase::OnMessageReceived().
+ manager->OnDidPrintDocument(render_frame_host, params,
+ std::make_unique<DelayedFrameDispatchHelper>(
+ render_frame_host, reply_msg));
+ }
+};
+
+PrintManager::DelayedFrameDispatchHelper::DelayedFrameDispatchHelper(
+ content::RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg)
+ : render_frame_host_(render_frame_host), reply_msg_(reply_msg) {}
+
+PrintManager::DelayedFrameDispatchHelper::~DelayedFrameDispatchHelper() {
+ if (reply_msg_) {
+ PrintHostMsg_DidPrintDocument::WriteReplyParams(reply_msg_, false);
+ render_frame_host_->Send(reply_msg_);
+ }
+}
+
+void PrintManager::DelayedFrameDispatchHelper::SendCompleted() {
+ DCHECK(reply_msg_);
+
+ PrintHostMsg_DidPrintDocument::WriteReplyParams(reply_msg_, true);
+ render_frame_host_->Send(reply_msg_);
+
+ // This wraps up the one allowed reply for the message.
+ reply_msg_ = nullptr;
+}
+
PrintManager::PrintManager(content::WebContents* contents)
: content::WebContentsObserver(contents) {}
@@ -17,12 +68,21 @@ PrintManager::~PrintManager() = default;
bool PrintManager::OnMessageReceived(
const IPC::Message& message,
content::RenderFrameHost* render_frame_host) {
+ FrameDispatchHelper helper = {this, render_frame_host};
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintManager, message)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPrintedPagesCount,
OnDidGetPrintedPagesCount)
IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDocumentCookie,
OnDidGetDocumentCookie)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(
+ PrintHostMsg_GetDefaultPrintSettings, &helper,
+ FrameDispatchHelper::OnGetDefaultPrintSettings)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(PrintHostMsg_ScriptedPrint, &helper,
+ FrameDispatchHelper::OnScriptedPrint)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(PrintHostMsg_DidPrintDocument, &helper,
+ FrameDispatchHelper::OnDidPrintDocument);
+
IPC_MESSAGE_HANDLER(PrintHostMsg_PrintingFailed, OnPrintingFailed)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
diff --git a/chromium/components/printing/browser/print_manager.h b/chromium/components/printing/browser/print_manager.h
index c8e6fdc4283..37da50f5890 100644
--- a/chromium/components/printing/browser/print_manager.h
+++ b/chromium/components/printing/browser/print_manager.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_PRINTING_BROWSER_PRINT_MANAGER_H_
#define COMPONENTS_PRINTING_BROWSER_PRINT_MANAGER_H_
+#include <memory>
+
#include "base/macros.h"
#include "build/build_config.h"
#include "content/public/browser/web_contents_observer.h"
@@ -13,6 +15,13 @@
#include "base/callback.h"
#endif
+namespace IPC {
+class Message;
+}
+
+struct PrintHostMsg_DidPrintDocument_Params;
+struct PrintHostMsg_ScriptedPrint_Params;
+
namespace printing {
class PrintManager : public content::WebContentsObserver {
@@ -21,7 +30,8 @@ class PrintManager : public content::WebContentsObserver {
#if defined(OS_ANDROID)
// TODO(timvolodine): consider introducing PrintManagerAndroid (crbug/500960)
- using PdfWritingDoneCallback = base::Callback<void(int /* page count */)>;
+ using PdfWritingDoneCallback =
+ base::RepeatingCallback<void(int /* page count */)>;
virtual void PdfWritingDone(int page_count) = 0;
#endif
@@ -36,9 +46,44 @@ class PrintManager : public content::WebContentsObserver {
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* render_frame_host) override;
+ // IPC handling support
+ struct FrameDispatchHelper;
+
+ // IPC message PrintHostMsg_DidPrintDocument can require handling in other
+ // processes beyond the rendering process running OnMessageReceived(),
+ // requiring that the renderer needs to wait.
+ class DelayedFrameDispatchHelper {
+ public:
+ DelayedFrameDispatchHelper(content::RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg);
+ DelayedFrameDispatchHelper(const DelayedFrameDispatchHelper&) = delete;
+ ~DelayedFrameDispatchHelper();
+ DelayedFrameDispatchHelper& operator=(const DelayedFrameDispatchHelper&) =
+ delete;
+
+ // SendCompleted() can be called at most once, since it provides the success
+ // reply for a message. A failure reply for the message is automatically
+ // sent if this is never called.
+ void SendCompleted();
+
+ private:
+ content::RenderFrameHost* const render_frame_host_;
+ IPC::Message* reply_msg_;
+ };
+
// IPC handlers
virtual void OnDidGetPrintedPagesCount(int cookie, int number_pages);
+ virtual void OnDidPrintDocument(
+ content::RenderFrameHost* render_frame_host,
+ const PrintHostMsg_DidPrintDocument_Params& params,
+ std::unique_ptr<DelayedFrameDispatchHelper> helper) = 0;
+ virtual void OnGetDefaultPrintSettings(
+ content::RenderFrameHost* render_frame_host,
+ IPC::Message* reply_msg) = 0;
virtual void OnPrintingFailed(int cookie);
+ virtual void OnScriptedPrint(content::RenderFrameHost* render_frame_host,
+ const PrintHostMsg_ScriptedPrint_Params& params,
+ IPC::Message* reply_msg) = 0;
int number_pages_ = 0; // Number of pages to print in the print job.
int cookie_ = 0; // The current document cookie.
diff --git a/chromium/components/printing/browser/print_media_l10n.cc b/chromium/components/printing/browser/print_media_l10n.cc
index ca19d2631a8..e9ffc3fbd31 100644
--- a/chromium/components/printing/browser/print_media_l10n.cc
+++ b/chromium/components/printing/browser/print_media_l10n.cc
@@ -5,13 +5,8 @@
#include "components/printing/browser/print_media_l10n.h"
#include <map>
-#include <vector>
-#include "base/logging.h"
#include "base/no_destructor.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
@@ -162,45 +157,17 @@ int VendorIdToTranslatedId(const std::string& vendor_id) {
return it != media_map->end() ? it->second : -1;
}
-std::string SplitMediaName(const base::StringPiece& vendor_id) {
- // <name>_<width>x<height>{in,mm}
- // e.g. na_letter_8.5x11in, iso_a4_210x297mm
- std::vector<base::StringPiece> pieces = base::SplitStringPiece(
- vendor_id, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (pieces.size() < 2)
- return std::string();
-
- // Append all tokens split out of the vendor ID. The last token is
- // usually the <width>x<height> token, so skip it.
- pieces.pop_back();
- return base::JoinString(pieces, " ");
-}
-
} // namespace
std::string LocalizePaperDisplayName(const std::string& vendor_id) {
- std::string localized;
// We can't do anything without a vendor ID.
if (vendor_id.empty()) {
- return localized;
+ return std::string();
}
int translation_id = VendorIdToTranslatedId(vendor_id);
- // If we can't get a localized media name, we do our best to parse it
- // on our own.
- if (translation_id < 0) {
- localized = SplitMediaName(base::StringPiece(vendor_id));
- } else {
- localized = l10n_util::GetStringUTF8(translation_id);
- }
-
- // If we still don't have a sane display name, fall back on showing
- // the vendor ID.
- if (localized.empty()) {
- VLOG(1) << "No display name for " << vendor_id;
- localized = vendor_id;
- }
- return localized;
+ return translation_id < 0 ? std::string()
+ : l10n_util::GetStringUTF8(translation_id);
}
} // namespace printing
diff --git a/chromium/components/printing/browser/print_media_l10n.h b/chromium/components/printing/browser/print_media_l10n.h
index e012b990709..2d3d507f035 100644
--- a/chromium/components/printing/browser/print_media_l10n.h
+++ b/chromium/components/printing/browser/print_media_l10n.h
@@ -9,7 +9,8 @@
namespace printing {
-// Map a paper vendor ID to a localized name.
+// Maps a paper vendor ID to a localized name; returns the localized
+// name if any is found, else returns an empty string.
std::string LocalizePaperDisplayName(const std::string& vendor_id);
} // namespace printing
diff --git a/chromium/components/printing/browser/print_media_l10n_unittest.cc b/chromium/components/printing/browser/print_media_l10n_unittest.cc
index 226d365b818..9ae4682de68 100644
--- a/chromium/components/printing/browser/print_media_l10n_unittest.cc
+++ b/chromium/components/printing/browser/print_media_l10n_unittest.cc
@@ -13,7 +13,7 @@
namespace printing {
-// Verify that we localize some common names.
+// Verifies that we localize some common names.
TEST(PrintMediaL10N, LocalizeSomeCommonNames) {
const struct {
const char* vendor_id;
@@ -31,15 +31,16 @@ TEST(PrintMediaL10N, LocalizeSomeCommonNames) {
}
}
-// Verify that we attempt to split and prettify a vendor ID for which
-// we don't have a localization.
+// Verifies that we return the empty string when no localization is
+// found for a given media name.
TEST(PrintMediaL10N, DoWithoutCommonName) {
const struct {
const char* vendor_id;
const char* expected_localized_name;
} kTestCases[] = {
- {"lorem_ipsum_8x10in", "lorem ipsum"},
- {"q_e_d_130x200mm", "q e d"},
+ {"lorem_ipsum_8x10in", ""},
+ {"q_e_d_130x200mm", ""},
+ {"not at all a valid vendor ID", ""},
};
for (const auto& test_case : kTestCases) {
@@ -48,13 +49,4 @@ TEST(PrintMediaL10N, DoWithoutCommonName) {
}
}
-// Verify that we return the vendor ID itself
-// 1. when we don't have a localization and
-// 2. when we don't see it split into at least 2 tokens (for name and
-// dimensions).
-TEST(PrintMediaL10N, FallbackToVendorId) {
- const std::string no_dim = "I-BE-NAME-SANS-DIMENSIONS";
- EXPECT_EQ(LocalizePaperDisplayName(no_dim), no_dim);
-}
-
} // namespace printing
diff --git a/chromium/components/printing/browser/printer_capabilities.cc b/chromium/components/printing/browser/printer_capabilities.cc
index 8e3a517c80d..9011989c38f 100644
--- a/chromium/components/printing/browser/printer_capabilities.cc
+++ b/chromium/components/printing/browser/printer_capabilities.cc
@@ -43,12 +43,21 @@ namespace {
#if BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)
// Iterate on the Papers of a given printer |info| and set the
-// display_name members, localizing where possible.
+// display_name members, localizing where possible. We expect the
+// backend to have populated non-empty display names already, so we
+// don't touch media display names that we can't localize.
void PopulateAllPaperDisplayNames(PrinterSemanticCapsAndDefaults* info) {
- info->default_paper.display_name =
+ std::string default_paper_display =
LocalizePaperDisplayName(info->default_paper.vendor_id);
+ if (!default_paper_display.empty()) {
+ info->default_paper.display_name = default_paper_display;
+ }
+
for (PrinterSemanticCapsAndDefaults::Paper& paper : info->papers) {
- paper.display_name = LocalizePaperDisplayName(paper.vendor_id);
+ std::string display = LocalizePaperDisplayName(paper.vendor_id);
+ if (!display.empty()) {
+ paper.display_name = display;
+ }
}
}
#endif // BUILDFLAG(PRINT_MEDIA_L10N_ENABLED)
@@ -71,11 +80,6 @@ base::Value GetPrinterCapabilitiesOnBlockingPoolThread(
crash_keys::ScopedPrinterInfo crash_key(
backend->GetPrinterDriverInfo(device_name));
- if (!backend->IsValidPrinter(device_name)) {
- LOG(WARNING) << "Invalid printer " << device_name;
- return base::Value(base::Value::Type::DICTIONARY);
- }
-
PrinterSemanticCapsAndDefaults info;
if (!backend->GetPrinterSemanticCapsAndDefaults(device_name, &info)) {
LOG(WARNING) << "Failed to get capabilities for " << device_name;
diff --git a/chromium/components/printing/browser/printer_capabilities_unittest.cc b/chromium/components/printing/browser/printer_capabilities_unittest.cc
index 2755dc8fd78..64cf25f7c34 100644
--- a/chromium/components/printing/browser/printer_capabilities_unittest.cc
+++ b/chromium/components/printing/browser/printer_capabilities_unittest.cc
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
#include "base/values.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "printing/backend/test_print_backend.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
@@ -41,7 +41,7 @@ class PrinterCapabilitiesTest : public testing::Test {
TestPrintBackend* print_backend() { return test_backend_.get(); }
private:
- content::TestBrowserThreadBundle test_browser_threads_;
+ content::BrowserTaskEnvironment task_environment_;
scoped_refptr<TestPrintBackend> test_backend_;
};
diff --git a/chromium/components/printing/common/BUILD.gn b/chromium/components/printing/common/BUILD.gn
index 40da0372461..a6698e1327b 100644
--- a/chromium/components/printing/common/BUILD.gn
+++ b/chromium/components/printing/common/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//mojo/public/tools/bindings/mojom.gni")
+
static_library("common") {
sources = [
"cloud_print_cdd_conversion.cc",
@@ -24,3 +26,13 @@ static_library("common") {
"//ui/gfx/ipc/skia",
]
}
+
+mojom("mojo_interfaces") {
+ sources = [
+ "print.mojom",
+ ]
+
+ public_deps = [
+ "//mojo/public/mojom/base",
+ ]
+}
diff --git a/chromium/components/printing/common/OWNERS b/chromium/components/printing/common/OWNERS
index c894089bc76..e8407344e00 100644
--- a/chromium/components/printing/common/OWNERS
+++ b/chromium/components/printing/common/OWNERS
@@ -4,6 +4,9 @@ per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *_messages.cc=set noparent
per-file *_messages.cc=file://ipc/SECURITY_OWNERS
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+
per-file *_param_traits*.*=set noparent
per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
# COMPONENT: Internals>Printing
diff --git a/chromium/components/printing/common/print.mojom b/chromium/components/printing/common/print.mojom
new file mode 100644
index 00000000000..e977a3be969
--- /dev/null
+++ b/chromium/components/printing/common/print.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 printing.mojom;
+
+// Interface implemented by a class that desires to render print documents for
+// Chrome print preview.
+interface PrintRenderer {
+ // TODO(jschettler): Add methods to render a print document and signal the
+ // close of Chrome print preview.
+};
diff --git a/chromium/components/printing/common/print_messages.h b/chromium/components/printing/common/print_messages.h
index 1802034a6e1..a134a000bd3 100644
--- a/chromium/components/printing/common/print_messages.h
+++ b/chromium/components/printing/common/print_messages.h
@@ -412,9 +412,12 @@ IPC_MESSAGE_ROUTED0(PrintHostMsg_DidShowPrintDialog)
// Sends back to the browser the rendered document that was requested by a
// PrintMsg_PrintPages message or from scripted printing. The memory handle in
-// this message is already valid in the browser process.
-IPC_MESSAGE_ROUTED1(PrintHostMsg_DidPrintDocument,
- PrintHostMsg_DidPrintDocument_Params /* page content */)
+// this message is already valid in the browser process. Waits until the
+// document is complete ready before replying.
+IPC_SYNC_MESSAGE_ROUTED1_1(PrintHostMsg_DidPrintDocument,
+ PrintHostMsg_DidPrintDocument_Params
+ /* page content */,
+ bool /* completed */)
// Sends back to the browser the rendered subframe content that was
// requested by a PrintMsg_PrintFrameContent message.
diff --git a/chromium/components/printing/renderer/DEPS b/chromium/components/printing/renderer/DEPS
index d195afd698a..7e4dbdc7070 100644
--- a/chromium/components/printing/renderer/DEPS
+++ b/chromium/components/printing/renderer/DEPS
@@ -4,7 +4,6 @@ include_rules = [
"+content/public/renderer",
"+mojo/public",
"+net/base",
- "+services/service_manager/public/cpp",
"+third_party/skia",
"+ui/base",
]
diff --git a/chromium/components/printing/renderer/print_render_frame_helper.cc b/chromium/components/printing/renderer/print_render_frame_helper.cc
index 84c11dcdb4f..86f8ab33563 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper.cc
+++ b/chromium/components/printing/renderer/print_render_frame_helper.cc
@@ -33,6 +33,7 @@
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "mojo/public/cpp/base/shared_memory_utils.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/escape.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "printing/buildflags/buildflags.h"
@@ -691,10 +692,12 @@ void PrintRenderFrameHelper::PrintHeaderAndFooter(
};
HeaderAndFooterClient frame_client;
- blink::mojom::DocumentInterfaceBrokerPtrInfo document_interface_broker;
+ mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
+ document_interface_broker;
blink::WebLocalFrame* frame = blink::WebLocalFrame::CreateMainFrame(
web_view, &frame_client, nullptr,
- mojo::MakeRequest(&document_interface_broker).PassMessagePipe(), nullptr);
+ document_interface_broker.InitWithNewPipeAndPassReceiver().PassPipe(),
+ nullptr);
blink::WebWidgetClient web_widget_client;
blink::WebFrameWidget::CreateForMainFrame(&web_widget_client, frame);
@@ -730,7 +733,7 @@ void PrintRenderFrameHelper::PrintHeaderAndFooter(
frame->PrintPage(0, canvas);
frame->PrintEnd();
- web_view->MainFrameWidget()->Close();
+ web_view->Close();
}
// static - Not anonymous so that platform implementations can use it.
@@ -882,8 +885,9 @@ void PrepareFrameAndViewForPrint::ResizeForPrinting() {
if (web_frame->IsWebLocalFrame())
prev_scroll_offset_ = web_frame->ToWebLocalFrame()->GetScrollOffset();
}
- prev_view_size_ = web_view->MainFrameWidget()->Size();
- web_view->MainFrameWidget()->Resize(print_layout_size);
+
+ prev_view_size_ = frame()->LocalRoot()->FrameWidget()->Size();
+ frame()->LocalRoot()->FrameWidget()->Resize(print_layout_size);
}
void PrepareFrameAndViewForPrint::StartPrinting() {
@@ -927,10 +931,12 @@ void PrepareFrameAndViewForPrint::CopySelection(
/*compositing_enabled=*/false,
/*opener=*/nullptr);
content::RenderView::ApplyWebPreferences(prefs, web_view);
- blink::mojom::DocumentInterfaceBrokerPtrInfo document_interface_broker;
+ mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
+ document_interface_broker;
blink::WebLocalFrame* main_frame = blink::WebLocalFrame::CreateMainFrame(
web_view, this, nullptr,
- mojo::MakeRequest(&document_interface_broker).PassMessagePipe(), nullptr);
+ document_interface_broker.InitWithNewPipeAndPassReceiver().PassPipe(),
+ nullptr);
frame_.Reset(main_frame);
blink::WebFrameWidget::CreateForMainFrame(this, main_frame);
node_to_print_.Reset();
@@ -942,7 +948,8 @@ void PrepareFrameAndViewForPrint::CopySelection(
navigation_control_->CommitNavigation(
blink::WebNavigationParams::CreateWithHTMLString(
html, GURL(url::kAboutBlankURL)),
- nullptr /* extra_data */);
+ nullptr /* extra_data */,
+ base::DoNothing::Once() /* call_before_attaching_new_document */);
}
blink::WebScreenInfo PrepareFrameAndViewForPrint::GetScreenInfo() {
@@ -1007,8 +1014,8 @@ void PrepareFrameAndViewForPrint::RestoreSize() {
if (IsPrintingNodeOrPdfFrame(frame(), node_to_print_))
return;
+ frame()->LocalRoot()->FrameWidget()->Resize(prev_view_size_);
blink::WebView* web_view = frame_.GetFrame()->View();
- web_view->MainFrameWidget()->Resize(prev_view_size_);
if (blink::WebFrame* web_frame = web_view->MainFrame()) {
// TODO(lukasza, weili): Support restoring scroll offset of a remote main
// frame - https://crbug.com/734815.
@@ -1032,7 +1039,7 @@ void PrepareFrameAndViewForPrint::FinishPrinting() {
if (owns_web_view_) {
DCHECK(!frame->IsLoading());
owns_web_view_ = false;
- web_view->MainFrameWidget()->Close();
+ web_view->Close();
}
}
navigation_control_ = nullptr;
@@ -1826,8 +1833,10 @@ bool PrintRenderFrameHelper::PrintPagesNative(blink::WebLocalFrame* frame,
#if defined(OS_WIN)
page_params.physical_offsets = printer_printable_area_.origin();
#endif
- Send(new PrintHostMsg_DidPrintDocument(routing_id(), page_params));
- return true;
+ bool completed = false;
+ Send(
+ new PrintHostMsg_DidPrintDocument(routing_id(), page_params, &completed));
+ return completed;
}
void PrintRenderFrameHelper::FinishFramePrinting() {
diff --git a/chromium/components/proxy_config/OWNERS b/chromium/components/proxy_config/OWNERS
index aa215c7d505..de8464c0981 100644
--- a/chromium/components/proxy_config/OWNERS
+++ b/chromium/components/proxy_config/OWNERS
@@ -1 +1,2 @@
stevenjb@chromium.org
+# COMPONENT: UI>Shell>Networking
diff --git a/chromium/components/proxy_config/ios/proxy_service_factory.cc b/chromium/components/proxy_config/ios/proxy_service_factory.cc
index c5fc61d11d0..d1f0ca9c044 100644
--- a/chromium/components/proxy_config/ios/proxy_service_factory.cc
+++ b/chromium/components/proxy_config/ios/proxy_service_factory.cc
@@ -20,7 +20,7 @@ std::unique_ptr<net::ProxyConfigService>
ProxyServiceFactory::CreateProxyConfigService(PrefProxyConfigTracker* tracker) {
std::unique_ptr<net::ProxyConfigService> base_service(
net::ProxyResolutionService::CreateSystemProxyConfigService(
- base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO})));
+ base::CreateSingleThreadTaskRunner({web::WebThread::IO})));
return tracker->CreateTrackingProxyConfigService(std::move(base_service));
}
@@ -31,7 +31,7 @@ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
PrefService* local_state_prefs) {
return std::make_unique<PrefProxyConfigTrackerImpl>(
browser_state_prefs,
- base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}));
+ base::CreateSingleThreadTaskRunner({web::WebThread::IO}));
}
// static
@@ -40,7 +40,7 @@ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
PrefService* local_state_prefs) {
return std::make_unique<PrefProxyConfigTrackerImpl>(
local_state_prefs,
- base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}));
+ base::CreateSingleThreadTaskRunner({web::WebThread::IO}));
}
// static
diff --git a/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc b/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
index 735464d87e4..b4bc739a8b7 100644
--- a/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
+++ b/chromium/components/proxy_config/pref_proxy_config_tracker_impl_unittest.cc
@@ -9,7 +9,7 @@
#include "base/files/file_path.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
@@ -104,7 +104,7 @@ class PrefProxyConfigTrackerImplTest : public testing::Test {
proxy_config_service_.reset();
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
TestProxyConfigService* delegate_service_; // weak
std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
diff --git a/chromium/components/quirks/OWNERS b/chromium/components/quirks/OWNERS
index 469ca5f13cc..cb2d3b56ef4 100644
--- a/chromium/components/quirks/OWNERS
+++ b/chromium/components/quirks/OWNERS
@@ -1,2 +1,3 @@
glevin@chromium.org
oshima@chromium.org
+# COMPONENT: UI>Shell>Display
diff --git a/chromium/components/quirks/quirks_client.cc b/chromium/components/quirks/quirks_client.cc
index c202a8eca8c..6978eaa16c1 100644
--- a/chromium/components/quirks/quirks_client.cc
+++ b/chromium/components/quirks/quirks_client.cc
@@ -63,8 +63,7 @@ QuirksClient::QuirksClient(int64_t product_id,
manager_(manager),
icc_path_(manager->delegate()->GetDisplayProfileDirectory().Append(
IdToFileName(product_id))),
- backoff_entry_(&kDefaultBackoffPolicy),
- weak_ptr_factory_(this) {}
+ backoff_entry_(&kDefaultBackoffPolicy) {}
QuirksClient::~QuirksClient() {}
@@ -90,7 +89,7 @@ void QuirksClient::StartDownload() {
resource_request->url = GURL(url);
resource_request->load_flags =
net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("quirks_display_fetcher", R"(
diff --git a/chromium/components/quirks/quirks_client.h b/chromium/components/quirks/quirks_client.h
index bc36efb2b9e..0b15c88ffb4 100644
--- a/chromium/components/quirks/quirks_client.h
+++ b/chromium/components/quirks/quirks_client.h
@@ -78,7 +78,7 @@ class QuirksClient {
net::BackoffEntry backoff_entry_;
// Factory for callbacks.
- base::WeakPtrFactory<QuirksClient> weak_ptr_factory_;
+ base::WeakPtrFactory<QuirksClient> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(QuirksClient);
};
diff --git a/chromium/components/quirks/quirks_manager.cc b/chromium/components/quirks/quirks_manager.cc
index e013ce80f2c..afd756c1269 100644
--- a/chromium/components/quirks/quirks_manager.cc
+++ b/chromium/components/quirks/quirks_manager.cc
@@ -62,10 +62,10 @@ QuirksManager::QuirksManager(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
: waiting_for_login_(true),
delegate_(std::move(delegate)),
- task_runner_(base::CreateTaskRunnerWithTraits({base::MayBlock()})),
+ task_runner_(
+ base::CreateTaskRunner({base::ThreadPool(), base::MayBlock()})),
local_state_(local_state),
- url_loader_factory_(std::move(url_loader_factory)),
- weak_ptr_factory_(this) {}
+ url_loader_factory_(std::move(url_loader_factory)) {}
QuirksManager::~QuirksManager() {
clients_.clear();
@@ -93,6 +93,11 @@ QuirksManager* QuirksManager::Get() {
}
// static
+bool QuirksManager::HasInstance() {
+ return !!manager_;
+}
+
+// static
void QuirksManager::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kQuirksClientLastServerCheck);
}
diff --git a/chromium/components/quirks/quirks_manager.h b/chromium/components/quirks/quirks_manager.h
index 551888bef24..5cd96eddb07 100644
--- a/chromium/components/quirks/quirks_manager.h
+++ b/chromium/components/quirks/quirks_manager.h
@@ -72,6 +72,7 @@ class QUIRKS_EXPORT QuirksManager {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
static void Shutdown();
static QuirksManager* Get();
+ static bool HasInstance();
static void RegisterPrefs(PrefRegistrySimple* registry);
@@ -136,7 +137,7 @@ class QUIRKS_EXPORT QuirksManager {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Factory for callbacks.
- base::WeakPtrFactory<QuirksManager> weak_ptr_factory_;
+ base::WeakPtrFactory<QuirksManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(QuirksManager);
};
diff --git a/chromium/components/rappor/log_uploader.cc b/chromium/components/rappor/log_uploader.cc
index 4c42c52880a..20f5d86a800 100644
--- a/chromium/components/rappor/log_uploader.cc
+++ b/chromium/components/rappor/log_uploader.cc
@@ -147,7 +147,7 @@ void LogUploader::StartScheduledUpload() {
resource_request->url = server_url_;
// We already drop cookies server-side, but we might as well strip them out
// client-side as well.
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
diff --git a/chromium/components/rappor/log_uploader_unittest.cc b/chromium/components/rappor/log_uploader_unittest.cc
index f8a53754ae7..2819ed5289e 100644
--- a/chromium/components/rappor/log_uploader_unittest.cc
+++ b/chromium/components/rappor/log_uploader_unittest.cc
@@ -7,7 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -65,12 +65,11 @@ class TestLogUploader : public LogUploader {
class LogUploaderTest : public testing::Test {
public:
LogUploaderTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
protected:
// Required for base::ThreadTaskRunnerHandle::Get().
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
private:
diff --git a/chromium/components/reading_list/core/reading_list_store_unittest.cc b/chromium/components/reading_list/core/reading_list_store_unittest.cc
index 9dfcbc508d4..89e581dded1 100644
--- a/chromium/components/reading_list/core/reading_list_store_unittest.cc
+++ b/chromium/components/reading_list/core/reading_list_store_unittest.cc
@@ -10,8 +10,8 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/reading_list/core/reading_list_model_impl.h"
#include "components/sync/model/mock_model_type_change_processor.h"
#include "components/sync/model/model_type_store_test_util.h"
@@ -143,7 +143,7 @@ class ReadingListStoreTest : public testing::Test,
}
// In memory model type store needs to be able to post tasks.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
testing::NiceMock<syncer::MockModelTypeChangeProcessor> processor_;
std::unique_ptr<syncer::ModelTypeStore> store_;
diff --git a/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 235b4d50dce..bf4cd6d2463 100644
--- a/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -58,7 +58,8 @@
@implementation NativeWidgetMacNSWindowTitledFrame
- (void)mouseDown:(NSEvent*)event {
- [self cr_mouseDownOnFrameView:event];
+ if (self.window.isMovable)
+ [self cr_mouseDownOnFrameView:event];
[super mouseDown:event];
}
- (BOOL)usesCustomDrawing {
@@ -229,17 +230,34 @@
return;
NSEventType type = [event type];
- if ((type != NSKeyDown && type != NSKeyUp) || ![self hasViewsMenuActive]) {
- [super sendEvent:event];
- return;
+
+ // Draggable regions only respond to left-click dragging, but the system will
+ // still suppress right-clicks in a draggable region. Forwarding right-clicks
+ // allows the underlying views to respond to right-click to potentially bring
+ // up a frame context menu.
+ if (type == NSRightMouseDown) {
+ if ([[self contentView] hitTest:event.locationInWindow] == nil) {
+ [[self contentView] rightMouseDown:event];
+ return;
+ }
+ } else if (type == NSRightMouseUp) {
+ if ([[self contentView] hitTest:event.locationInWindow] == nil) {
+ [[self contentView] rightMouseUp:event];
+ return;
+ }
+ } else if ([self hasViewsMenuActive]) {
+ // Send to the menu, after converting the event into an action message using
+ // the content view.
+ if (type == NSKeyDown) {
+ [[self contentView] keyDown:event];
+ return;
+ } else if (type == NSKeyUp) {
+ [[self contentView] keyUp:event];
+ return;
+ }
}
- // Send to the menu, after converting the event into an action message using
- // the content view.
- if (type == NSKeyDown)
- [[self contentView] keyDown:event];
- else
- [[self contentView] keyUp:event];
+ [super sendEvent:event];
}
// Override window order functions to intercept other visibility changes. This
diff --git a/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h b/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
index 98a123e452e..9aa27456516 100644
--- a/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
+++ b/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
@@ -232,6 +232,7 @@ class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowBridge
void SetContentAspectRatio(const gfx::SizeF& aspect_ratio) override;
void SetCALayerParams(const gfx::CALayerParams& ca_layer_params) override;
void SetWindowTitle(const base::string16& title) override;
+ void SetIgnoresMouseEvents(bool ignores_mouse_events) override;
void MakeFirstResponder() override;
void ClearTouchBar() override;
void UpdateTooltip() override;
@@ -254,6 +255,9 @@ class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowBridge
private:
friend class views::test::BridgedNativeWidgetTestApi;
+ // Attach child windows, if the window is visible (see comment inline).
+ void OrderChildren();
+
// Closes all child windows. NativeWidgetNSWindowBridge children will be
// destroyed.
void RemoveOrDestroyChildren();
diff --git a/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index d1b8eefbfac..6fc74421017 100644
--- a/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -383,15 +383,8 @@ void NativeWidgetNSWindowBridge::SetParent(uint64_t new_parent_id) {
[window_ setCollectionBehavior:[window_ collectionBehavior] |
NSWindowCollectionBehaviorTransient];
- // If |window_| was already visible then add it as a child window immediately.
- // As in OnVisibilityChanged, do not set a parent for sheets.
- if (window_visible_ && ![window_ isSheet]) {
- // Attaching a window to be a child window resets the window level, so
- // restore the window level afterwards.
- NSInteger window_level = [window_ level];
- [parent_->ns_window() addChildWindow:window_ ordered:NSWindowAbove];
- [window_ setLevel:window_level];
- }
+ if (wants_to_be_visible_)
+ parent_->OrderChildren();
}
void NativeWidgetNSWindowBridge::CreateSelectFileDialog(
@@ -462,6 +455,9 @@ void NativeWidgetNSWindowBridge::InitWindow(
}
[window_ setHasShadow:params->has_window_server_shadow];
+ // Don't allow dragging sheets.
+ if (params->modal_type == ui::MODAL_TYPE_WINDOW)
+ [window_ setMovable:NO];
}
void NativeWidgetNSWindowBridge::SetInitialBounds(
@@ -614,6 +610,10 @@ void NativeWidgetNSWindowBridge::CloseWindow() {
// being torn down.
DestroyContentView();
+ // If the window wants to be visible and has a parent, then the parent may
+ // order it back in (in the period between orderOut: and close).
+ wants_to_be_visible_ = false;
+
// Widget::Close() ensures [Non]ClientView::CanClose() returns true, so there
// is no need to call the NSWindow or its delegate's -windowShouldClose:
// implementation in the manner of -[NSWindow performClose:]. But,
@@ -694,34 +694,15 @@ void NativeWidgetNSWindowBridge::SetVisibilityState(
return;
}
+ if (parent_)
+ parent_->OrderChildren();
+
if (new_state == WindowVisibilityState::kShowAndActivateWindow) {
[window_ makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
- } else {
- // ui::SHOW_STATE_INACTIVE is typically used to avoid stealing focus from a
- // parent window. So, if there's a parent, order above that. Otherwise, this
- // will order above all windows at the same level.
- NSInteger parent_window_number = 0;
- if (parent_) {
- // When there's a parent, check if the window is already visible. If
- // ShowInactive() is called on an already-visible window, there should be
- // no effect: the macOS childWindow mechanism should have already raised
- // the window to the right stacking order. More importantly, invoking
- // -[NSWindow orderWindow:] could cause a Space switch, which defeats the
- // point of ShowInactive(), so avoid it. See https://crbug.com/866760.
-
- // Sanity check: if the window is visible, the prior Show should have
- // hooked it up as a native child window already.
- DCHECK_EQ(window_visible_, !![window_ parentWindow]);
- if (window_visible_)
- return; // Avoid a Spaces transition.
-
- parent_window_number = [parent_->ns_window() windowNumber];
- }
-
- [window_ orderWindow:NSWindowAbove relativeTo:parent_window_number];
+ } else if (!parent_) {
+ [window_ orderFront:nil];
}
- DCHECK(window_visible_);
// For non-sheet modal types, use the constrained window animations to make
// the window appear.
@@ -872,6 +853,9 @@ void NativeWidgetNSWindowBridge::OnFullscreenTransitionComplete(
bool actual_fullscreen_state) {
in_fullscreen_transition_ = false;
+ // Add any children that were skipped during the fullscreen transition.
+ OrderChildren();
+
if (has_deferred_window_close_) {
[ns_window() close];
return;
@@ -960,16 +944,8 @@ void NativeWidgetNSWindowBridge::OnVisibilityChanged() {
// window - we might not need that.
if (window_visible_) {
wants_to_be_visible_ = true;
-
- // Sheets don't need a parentWindow set, and setting one causes graphical
- // glitches (http://crbug.com/605098).
- if (parent_ && ![window_ isSheet]) {
- // Attaching a window to be a child window resets the window level, so
- // restore the window level afterwards.
- NSInteger window_level = [window_ level];
- [parent_->ns_window() addChildWindow:window_ ordered:NSWindowAbove];
- [window_ setLevel:window_level];
- }
+ if (parent_ && !window_visible_)
+ parent_->OrderChildren();
} else {
ReleaseCapture(); // Capture on hidden windows is not permitted.
@@ -1007,6 +983,10 @@ void NativeWidgetNSWindowBridge::OnWindowKeyStatusChangedTo(bool is_key) {
host_->OnWindowKeyStatusChanged(
is_key, [window_ contentView] == [window_ firstResponder],
[NSApp isFullKeyboardAccessEnabled]);
+ // If the window just became key, this is a good chance to add child windows
+ // from when the window wasn't on the current space.
+ if (is_key)
+ OrderChildren();
}
void NativeWidgetNSWindowBridge::SetSizeConstraints(const gfx::Size& min_size,
@@ -1229,6 +1209,11 @@ void NativeWidgetNSWindowBridge::SetCALayerParams(
}
}
+void NativeWidgetNSWindowBridge::SetIgnoresMouseEvents(
+ bool ignores_mouse_events) {
+ [window_ setIgnoresMouseEvents:ignores_mouse_events];
+}
+
void NativeWidgetNSWindowBridge::MakeFirstResponder() {
[window_ makeFirstResponder:bridged_view_];
}
@@ -1285,6 +1270,35 @@ void NativeWidgetNSWindowBridge::RemoveChildWindow(
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetNSWindowBridge, private:
+void NativeWidgetNSWindowBridge::OrderChildren() {
+ // Adding a child to a window that isn't visible on the active space will
+ // switch to that space (https://crbug.com/783521, https://crbug.com/798792).
+ // Bail here (and call OrderChildren() in a few places) to defer adding
+ // children until the window is visible.
+ NSWindow* window = window_.get();
+ if (!window.isVisible || !window.isOnActiveSpace)
+ return;
+ for (auto* child : child_windows_) {
+ if (!child->wants_to_be_visible())
+ continue;
+ NSWindow* child_window = child->window_.get();
+ if (child->IsWindowModalSheet()) {
+ if (!child->window_visible_)
+ child->ShowAsModalSheet();
+ // Sheets don't need a parentWindow set, and setting one causes graphical
+ // glitches (http://crbug.com/605098).
+ } else {
+ if (child_window.parentWindow == window)
+ continue;
+ // Attaching a window to be a child window resets the window level, so
+ // restore the window level afterwards.
+ NSInteger level = child_window.level;
+ [window addChildWindow:child_window ordered:NSWindowAbove];
+ child_window.level = level;
+ }
+ }
+}
+
void NativeWidgetNSWindowBridge::RemoveOrDestroyChildren() {
// TODO(tapted): Implement unowned child windows if required.
while (!child_windows_.empty()) {
@@ -1320,38 +1334,7 @@ void NativeWidgetNSWindowBridge::NotifyVisibilityChangeDown() {
return;
}
- NSUInteger visible_bridged_children = 0; // For a DCHECK below.
- NSInteger parent_window_number = [window_ windowNumber];
- for (NativeWidgetNSWindowBridge* child : child_windows_) {
- // Note: order the child windows on top, regardless of whether or not they
- // are currently visible. They probably aren't, since the parent was hidden
- // prior to this, but they could have been made visible in other ways.
- if (child->wants_to_be_visible_) {
- if ([child->ns_window() isSheet]) {
- // Sheets should not be counted as children since their NSWindows are
- // not children of this NSWindow, and they should not be directly
- // ordered back in - that causes them to lose their sheet-ness.
- child->ShowAsModalSheet();
- } else {
- ++visible_bridged_children;
-
- // Here -[NSWindow orderWindow:relativeTo:] is used to put the window on
- // screen. However, that by itself is insufficient to guarantee a
- // correct z-order relationship. If this function is being called from a
- // z-order change in the parent, orderWindow turns out to be unreliable
- // (i.e. the ordering doesn't always take effect). What this actually
- // relies on is the resulting call to OnVisibilityChanged() in the
- // child, which will then insert itself into -[NSWindow childWindows] to
- // let Cocoa do its internal layering magic.
- [child->ns_window() orderWindow:NSWindowAbove
- relativeTo:parent_window_number];
- DCHECK(child->window_visible_);
- }
- }
- CHECK_EQ(child_count, child_windows_.size());
- }
- DCHECK_EQ(visible_bridged_children,
- CountBridgedWindows([window_ childWindows]));
+ OrderChildren();
}
void NativeWidgetNSWindowBridge::UpdateWindowGeometry() {
diff --git a/chromium/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm b/chromium/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm
index 17683b7464b..8c6527ab834 100644
--- a/chromium/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm
+++ b/chromium/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm
@@ -234,7 +234,9 @@ void SelectFileDialogBridge::Show(
[dialog setCanSelectHiddenExtension:YES];
}
} else {
- NSOpenPanel* open_dialog = base::mac::ObjCCastStrict<NSOpenPanel>(dialog);
+ // This does not use ObjCCast because the underlying object could be a
+ // non-exported AppKit type (https://crbug.com/995476).
+ NSOpenPanel* open_dialog = static_cast<NSOpenPanel*>(dialog);
if (type_ == SelectFileDialogType::kOpenMultiFile)
[open_dialog setAllowsMultipleSelection:YES];
@@ -394,7 +396,6 @@ void SelectFileDialogBridge::OnPanelEnded(bool did_cancel) {
index = 1;
}
} else {
- CHECK([panel_ isKindOfClass:[NSOpenPanel class]]);
NSArray* urls = [static_cast<NSOpenPanel*>(panel_) URLs];
for (NSURL* url in urls)
if ([url isFileURL])
diff --git a/chromium/components/remote_cocoa/common/BUILD.gn b/chromium/components/remote_cocoa/common/BUILD.gn
index f0a7ba3251e..bce2462f10c 100644
--- a/chromium/components/remote_cocoa/common/BUILD.gn
+++ b/chromium/components/remote_cocoa/common/BUILD.gn
@@ -19,12 +19,12 @@ mojom("mojo") {
public_deps = [
"//mojo/public/mojom/base",
- "//ui/base/accelerators/mojo:interfaces",
+ "//ui/base/accelerators/mojom",
"//ui/base/mojom",
"//ui/display/mojom",
- "//ui/events/mojo:interfaces",
- "//ui/gfx/geometry/mojo",
- "//ui/gfx/mojo",
- "//ui/gfx/range/mojo",
+ "//ui/events/mojom",
+ "//ui/gfx/geometry/mojom",
+ "//ui/gfx/mojom",
+ "//ui/gfx/range/mojom",
]
}
diff --git a/chromium/components/remote_cocoa/common/native_widget_ns_window.mojom b/chromium/components/remote_cocoa/common/native_widget_ns_window.mojom
index cc878f3c95e..b8dc3bebdd1 100644
--- a/chromium/components/remote_cocoa/common/native_widget_ns_window.mojom
+++ b/chromium/components/remote_cocoa/common/native_widget_ns_window.mojom
@@ -7,8 +7,8 @@ module remote_cocoa.mojom;
import "components/remote_cocoa/common/select_file_dialog.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "ui/base/mojom/ui_base_types.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
-import "ui/gfx/mojo/ca_layer_params.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
+import "ui/gfx/mojom/ca_layer_params.mojom";
// The window class (subclass of kNativeWidgetMacNSWindow) to use for a given
// window.
@@ -189,6 +189,9 @@ interface NativeWidgetNSWindow {
// Set the NSWindow's title text.
SetWindowTitle(mojo_base.mojom.String16 title);
+ // Ignore or accept mouse events on the NSWindow.
+ SetIgnoresMouseEvents(bool ignores_mouse_events);
+
// Make the content view be the first responder for the NSWindow.
MakeFirstResponder();
diff --git a/chromium/components/remote_cocoa/common/native_widget_ns_window_host.mojom b/chromium/components/remote_cocoa/common/native_widget_ns_window_host.mojom
index f9925fc10f7..a374235ed0d 100644
--- a/chromium/components/remote_cocoa/common/native_widget_ns_window_host.mojom
+++ b/chromium/components/remote_cocoa/common/native_widget_ns_window_host.mojom
@@ -5,13 +5,13 @@
module remote_cocoa.mojom;
import "mojo/public/mojom/base/string16.mojom";
-import "ui/base/accelerators/mojo/accelerator.mojom";
+import "ui/base/accelerators/mojom/accelerator.mojom";
import "ui/base/mojom/ui_base_types.mojom";
import "ui/base/mojom/window_open_disposition.mojom";
import "ui/display/mojom/display.mojom";
-import "ui/events/mojo/event.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
-import "ui/gfx/mojo/ca_layer_params.mojom";
+import "ui/events/mojom/event.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
+import "ui/gfx/mojom/ca_layer_params.mojom";
struct ValidateUserInterfaceItemResult {
// Whether or not the specified sender should be enabled.
diff --git a/chromium/components/remote_cocoa/common/text_input_host.mojom b/chromium/components/remote_cocoa/common/text_input_host.mojom
index 20e00112dd4..7528982d799 100644
--- a/chromium/components/remote_cocoa/common/text_input_host.mojom
+++ b/chromium/components/remote_cocoa/common/text_input_host.mojom
@@ -5,8 +5,8 @@
module remote_cocoa.mojom;
import "mojo/public/mojom/base/string16.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
-import "ui/gfx/range/mojo/range.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
+import "ui/gfx/range/mojom/range.mojom";
// Interface exposing a views::Widget's currently-focused views::View's
// ui::TextInputClient to the NSView corresponding to that views::Widget.
diff --git a/chromium/components/renderer_context_menu/render_view_context_menu_base.cc b/chromium/components/renderer_context_menu/render_view_context_menu_base.cc
index 7dc7465ebc8..5d5a8232394 100644
--- a/chromium/components/renderer_context_menu/render_view_context_menu_base.cc
+++ b/chromium/components/renderer_context_menu/render_view_context_menu_base.cc
@@ -211,6 +211,13 @@ void RenderViewContextMenuBase::AddMenuItemWithIcon(
menu_model_.AddItemWithIcon(command_id, title, image);
}
+void RenderViewContextMenuBase::AddMenuItemWithIcon(
+ int command_id,
+ const base::string16& title,
+ const gfx::VectorIcon& icon) {
+ menu_model_.AddItemWithIcon(command_id, title, icon);
+}
+
void RenderViewContextMenuBase::AddCheckItem(int command_id,
const base::string16& title) {
menu_model_.AddCheckItem(command_id, title);
@@ -235,6 +242,15 @@ void RenderViewContextMenuBase::AddSubMenuWithStringIdAndIcon(
image);
}
+void RenderViewContextMenuBase::AddSubMenuWithStringIdAndIcon(
+ int command_id,
+ int message_id,
+ ui::MenuModel* model,
+ const gfx::VectorIcon& icon) {
+ menu_model_.AddSubMenuWithStringIdAndIcon(command_id, message_id, model,
+ icon);
+}
+
void RenderViewContextMenuBase::UpdateMenuItem(int command_id,
bool enabled,
bool hidden,
diff --git a/chromium/components/renderer_context_menu/render_view_context_menu_base.h b/chromium/components/renderer_context_menu/render_view_context_menu_base.h
index 7abdb0340fc..baaa73aad07 100644
--- a/chromium/components/renderer_context_menu/render_view_context_menu_base.h
+++ b/chromium/components/renderer_context_menu/render_view_context_menu_base.h
@@ -98,6 +98,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
void AddMenuItemWithIcon(int command_id,
const base::string16& title,
const gfx::ImageSkia& image) override;
+ void AddMenuItemWithIcon(int command_id,
+ const base::string16& title,
+ const gfx::VectorIcon& icon) override;
void AddCheckItem(int command_id, const base::string16& title) override;
void AddSeparator() override;
void AddSubMenu(int command_id,
@@ -107,6 +110,10 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
int message_id,
ui::MenuModel* model,
const gfx::ImageSkia& image) override;
+ void AddSubMenuWithStringIdAndIcon(int command_id,
+ int message_id,
+ ui::MenuModel* model,
+ const gfx::VectorIcon& icon) override;
void UpdateMenuItem(int command_id,
bool enabled,
bool hidden,
diff --git a/chromium/components/renderer_context_menu/render_view_context_menu_proxy.h b/chromium/components/renderer_context_menu/render_view_context_menu_proxy.h
index 2f3d25b0f19..33b343871c9 100644
--- a/chromium/components/renderer_context_menu/render_view_context_menu_proxy.h
+++ b/chromium/components/renderer_context_menu/render_view_context_menu_proxy.h
@@ -16,6 +16,7 @@ class WebContents;
namespace gfx {
class Image;
class ImageSkia;
+struct VectorIcon;
}
namespace ui {
@@ -84,6 +85,9 @@ class RenderViewContextMenuProxy {
virtual void AddMenuItemWithIcon(int command_id,
const base::string16& title,
const gfx::ImageSkia& image) = 0;
+ virtual void AddMenuItemWithIcon(int command_id,
+ const base::string16& title,
+ const gfx::VectorIcon& image) = 0;
virtual void AddCheckItem(int command_id, const base::string16& title) = 0;
virtual void AddSeparator() = 0;
@@ -95,6 +99,10 @@ class RenderViewContextMenuProxy {
int message_id,
ui::MenuModel* model,
const gfx::ImageSkia& image) = 0;
+ virtual void AddSubMenuWithStringIdAndIcon(int command_id,
+ int message_id,
+ ui::MenuModel* model,
+ const gfx::VectorIcon& image) = 0;
// Update the status and text of the specified context-menu item.
virtual void UpdateMenuItem(int command_id,
diff --git a/chromium/components/reset_password_strings_grdp/OWNERS b/chromium/components/reset_password_strings_grdp/OWNERS
index 5225674f443..2045ecdb69c 100644
--- a/chromium/components/reset_password_strings_grdp/OWNERS
+++ b/chromium/components/reset_password_strings_grdp/OWNERS
@@ -1 +1,3 @@
file://components/safe_browsing/OWNERS
+# COMPONENT: Services>Safebrowsing
+# TEAM: safebrowsing@chromium.org
diff --git a/chromium/components/resources/BUILD.gn b/chromium/components/resources/BUILD.gn
index 209ff73247f..e608270d64d 100644
--- a/chromium/components/resources/BUILD.gn
+++ b/chromium/components/resources/BUILD.gn
@@ -28,6 +28,8 @@ grit("components_resources") {
]
output_dir = "$root_gen_dir/components"
+ use_brotli = true
+
grit_flags = [
"-E",
"about_credits_file=" + rebase_path(about_credits_file, root_build_dir),
diff --git a/chromium/components/resources/OWNERS b/chromium/components/resources/OWNERS
index 704da9fbde1..697f2052545 100644
--- a/chromium/components/resources/OWNERS
+++ b/chromium/components/resources/OWNERS
@@ -18,11 +18,10 @@ per-file gcm_driver_resources.grdp=zea@chromium.org
per-file neterror*=mmenke@chromium.org
per-file neterror*=file://net/OWNERS
per-file ntp_tiles_resources.grdp=file://components/ntp_tiles/OWNERS
-per-file onboarding_welcome_scaled_resources.grdp=file://ui/webui/PLATFORM_OWNERS
+per-file welcome_scaled_resources.grdp=file://ui/webui/PLATFORM_OWNERS
per-file offline_pages_resources.grdp=file://components/offline_pages/OWNERS
per-file proximity_auth*=tengs@chromium.org
per-file printing_resources.grdp=file://printing/OWNERS
per-file security_interstitials_resources.grdp=file://components/security_interstitials/OWNERS
-per-file supervised_user_error_page_resources.grdp=file://components/supervised_user_error_page/OWNERS
per-file sync_driver_resources.grdp=file://components/sync/OWNERS
per-file version_ui*=file://ui/webui/PLATFORM_OWNERS
diff --git a/chromium/components/resources/components_resources.grd b/chromium/components/resources/components_resources.grd
index d56d3767a97..adff92489bb 100644
--- a/chromium/components/resources/components_resources.grd
+++ b/chromium/components/resources/components_resources.grd
@@ -22,7 +22,6 @@
<part file="safe_browsing_resources.grdp" />
<part file="security_interstitials_resources.grdp" />
<part file="signin_resources.grdp" />
- <part file="supervised_user_error_page_resources.grdp" />
<part file="sync_driver_resources.grdp" />
<part file="translate_resources.grdp" />
<part file="user_actions_ui_resources.grdp" />
diff --git a/chromium/components/resources/components_scaled_resources.grd b/chromium/components/resources/components_scaled_resources.grd
index 379fb2f9351..a58807f06fd 100644
--- a/chromium/components/resources/components_scaled_resources.grd
+++ b/chromium/components/resources/components_scaled_resources.grd
@@ -16,7 +16,7 @@
<part file="crash_scaled_resources.grdp" />
<part file="flags_ui_scaled_resources.grdp" />
<part file="neterror_scaled_resources.grdp" />
- <part file="onboarding_welcome_scaled_resources.grdp" />
+ <part file="welcome_scaled_resources.grdp" />
<part file="version_ui_scaled_resources.grdp" />
<!-- Generic resources -->
diff --git a/chromium/components/resources/onboarding_welcome_scaled_resources.grdp b/chromium/components/resources/onboarding_welcome_scaled_resources.grdp
deleted file mode 100644
index c5a5f73807d..00000000000
--- a/chromium/components/resources/onboarding_welcome_scaled_resources.grdp
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit-part>
- <if expr="not is_android and not is_ios and _google_chrome">
- <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_GMAIL" file="google_chrome/welcome/gmail.png" />
- <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_MAPS" file="google_chrome/welcome/maps.png" />
- <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_NEWS" file="google_chrome/welcome/news.png" />
- <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_SEARCH" file="google_chrome/welcome/search.png" />
- <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_TRANSLATE" file="google_chrome/welcome/translate.png" />
- <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_YOUTUBE" file="google_chrome/welcome/youtube.png" />
- </if>
-</grit-part>
diff --git a/chromium/components/resources/supervised_user_error_page_resources.grdp b/chromium/components/resources/supervised_user_error_page_resources.grdp
deleted file mode 100644
index b9c9577b2cc..00000000000
--- a/chromium/components/resources/supervised_user_error_page_resources.grdp
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<grit-part>
- <include name="IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_HTML" file="../supervised_user_error_page/resources/supervised_user_block_interstitial.html" flattenhtml="true" type="BINDATA" />
-</grit-part>
diff --git a/chromium/components/resources/welcome_scaled_resources.grdp b/chromium/components/resources/welcome_scaled_resources.grdp
new file mode 100644
index 00000000000..b6c82bdb041
--- /dev/null
+++ b/chromium/components/resources/welcome_scaled_resources.grdp
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit-part>
+ <if expr="not is_android and not is_ios and _google_chrome">
+ <structure type="chrome_scaled_image" name="IDS_WELCOME_GMAIL" file="google_chrome/welcome/gmail.png" />
+ <structure type="chrome_scaled_image" name="IDS_WELCOME_MAPS" file="google_chrome/welcome/maps.png" />
+ <structure type="chrome_scaled_image" name="IDS_WELCOME_NEWS" file="google_chrome/welcome/news.png" />
+ <structure type="chrome_scaled_image" name="IDS_WELCOME_SEARCH" file="google_chrome/welcome/search.png" />
+ <structure type="chrome_scaled_image" name="IDS_WELCOME_TRANSLATE" file="google_chrome/welcome/translate.png" />
+ <structure type="chrome_scaled_image" name="IDS_WELCOME_YOUTUBE" file="google_chrome/welcome/youtube.png" />
+ </if>
+</grit-part>
diff --git a/chromium/components/rlz/BUILD.gn b/chromium/components/rlz/BUILD.gn
index c5d7a9dad93..3676c968ad0 100644
--- a/chromium/components/rlz/BUILD.gn
+++ b/chromium/components/rlz/BUILD.gn
@@ -15,7 +15,7 @@ static_library("rlz") {
deps = [
"//base",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//net",
"//rlz:rlz_lib",
"//services/network/public/cpp:cpp",
diff --git a/chromium/components/safe_browsing/BUILD.gn b/chromium/components/safe_browsing/BUILD.gn
index c8a6f37a7a0..28598087db3 100644
--- a/chromium/components/safe_browsing/BUILD.gn
+++ b/chromium/components/safe_browsing/BUILD.gn
@@ -2,152 +2,191 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/buildflag_header.gni")
+import("//components/safe_browsing/buildflags.gni")
import("//third_party/protobuf/proto_library.gni")
-proto_library("csd_proto") {
- sources = [
- "proto/csd.proto",
- ]
+buildflag_header("buildflags") {
+ header = "buildflags.h"
+
+ flags = []
+ if (safe_browsing_mode == 0) {
+ flags += [ "FULL_SAFE_BROWSING=0" ]
+ flags += [ "SAFE_BROWSING_CSD=0" ]
+ flags += [ "SAFE_BROWSING_DB_LOCAL=0" ]
+ flags += [ "SAFE_BROWSING_DB_REMOTE=0" ]
+ } else if (safe_browsing_mode == 1) {
+ flags += [ "FULL_SAFE_BROWSING=1" ]
+ flags += [ "SAFE_BROWSING_CSD=1" ]
+ flags += [ "SAFE_BROWSING_DB_LOCAL=1" ]
+ flags += [ "SAFE_BROWSING_DB_REMOTE=0" ]
+ } else if (safe_browsing_mode == 2) {
+ flags += [ "FULL_SAFE_BROWSING=0" ]
+ flags += [ "SAFE_BROWSING_CSD=0" ]
+ flags += [ "SAFE_BROWSING_DB_LOCAL=0" ]
+ flags += [ "SAFE_BROWSING_DB_REMOTE=1" ]
+ } else if (safe_browsing_mode == 3) {
+ flags += [ "FULL_SAFE_BROWSING=0" ]
+ flags += [ "SAFE_BROWSING_CSD=0" ]
+ flags += [ "SAFE_BROWSING_DB_LOCAL=1" ]
+ flags += [ "SAFE_BROWSING_DB_REMOTE=0" ]
+ }
}
-proto_library("webui_proto") {
- sources = [
- "proto/webui.proto",
- ]
-}
-
-proto_library("realtimeapi_proto") {
- sources = [
- "proto/realtimeapi.proto",
- ]
-
- deps = [
- ":csd_proto",
- ]
-}
-
-proto_library("webprotect_proto") {
- sources = [
- "proto/webprotect.proto",
- ]
-}
-
-source_set("safe_browsing") {
- sources = [
- "base_blocking_page.cc",
- "base_blocking_page.h",
- "base_ui_manager.cc",
- "base_ui_manager.h",
- ]
- public_deps = [
- "//components/security_interstitials/content:security_interstitial_page",
- ]
- deps = [
- ":features",
- ":ping_manager",
- ":verdict_cache_manager",
- "//base:base",
- "//base:i18n",
- "//components/safe_browsing/common:common",
- "//components/safe_browsing/common:safe_browsing_prefs",
- "//components/safe_browsing/db:database_manager",
- "//components/safe_browsing/web_ui:constants",
- "//components/security_interstitials/core:core",
- "//content/public/browser:browser",
- "//content/public/common:common",
- "//net:net",
- ]
-}
-
-static_library("ping_manager") {
- sources = [
- "ping_manager.cc",
- "ping_manager.h",
- ]
-
- public_deps = [
- "//google_apis:google_apis",
- ]
-
- deps = [
- "//base:base",
- "//components/safe_browsing/db:hit_report",
- "//components/safe_browsing/db:util",
- "//content/public/browser:browser",
- "//net:net",
- ]
-}
-
-source_set("ping_manager_unittest") {
- testonly = true
- sources = [
- "ping_manager_unittest.cc",
- ]
-
- deps = [
- ":ping_manager",
- "//base:base",
- "//components/safe_browsing/db:v4_test_util",
- "//net:net",
- "//net:test_support",
- "//testing/gtest",
- ]
-}
-
-static_library("features") {
- sources = [
- "features.cc",
- "features.h",
- ]
-
- deps = [
- "//base:base",
- ]
-}
-
-source_set("public") {
- sources = [
- "safe_browsing_service_interface.cc",
- "safe_browsing_service_interface.h",
- ]
-
- deps = [
- "//base:base",
- "//content/public/browser",
- ]
-}
-
-source_set("verdict_cache_manager") {
- sources = [
- "verdict_cache_manager.cc",
- "verdict_cache_manager.h",
- ]
-
- deps = [
- ":csd_proto",
- "//base",
- "//components/content_settings/core/browser",
- "//components/history/core/browser",
- "//components/password_manager/core/browser:browser",
- "//components/safe_browsing/db:v4_protocol_manager_util",
- "//content/public/browser",
- "//url",
- ]
-}
-
-source_set("verdict_cache_manager_unittest") {
- testonly = true
- sources = [
- "verdict_cache_manager_unittest.cc",
- ]
-
- deps = [
- ":csd_proto",
- ":verdict_cache_manager",
- "//base",
- "//components/content_settings/core/browser",
- "//components/sync_preferences:test_support",
- "//content/test:test_support",
- "//testing/gtest",
- ]
+# safe_browsing/ pulls in content/, which doesn't work on iOS.
+# TODO(thakis): This should be `safe_browsing_mode != 0`, but chromecast builds
+# set safe_browsing_mode to 0 and build chrome/, and chrome/ currently
+# unconditionally depends on things in this build file. Make these dependencies
+# conditional on safe_browsing_mode != 0 and then change the conditional here.
+if (!is_ios) {
+ assert(!is_ios, "safe_browsing/ pulls in content/ which doesn't work on iOS")
+
+ proto_library("csd_proto") {
+ sources = [
+ "proto/csd.proto",
+ ]
+ }
+
+ proto_library("webui_proto") {
+ sources = [
+ "proto/webui.proto",
+ ]
+ }
+
+ proto_library("realtimeapi_proto") {
+ sources = [
+ "proto/realtimeapi.proto",
+ ]
+
+ deps = [
+ ":csd_proto",
+ ]
+ }
+
+ proto_library("webprotect_proto") {
+ sources = [
+ "proto/webprotect.proto",
+ ]
+ }
+
+ source_set("safe_browsing") {
+ sources = [
+ "base_blocking_page.cc",
+ "base_blocking_page.h",
+ "base_ui_manager.cc",
+ "base_ui_manager.h",
+ ]
+ public_deps = [
+ "//components/security_interstitials/content:security_interstitial_page",
+ ]
+ deps = [
+ ":features",
+ ":ping_manager",
+ ":verdict_cache_manager",
+ "//base:base",
+ "//base:i18n",
+ "//components/safe_browsing/common:common",
+ "//components/safe_browsing/common:safe_browsing_prefs",
+ "//components/safe_browsing/db:database_manager",
+ "//components/safe_browsing/web_ui:constants",
+ "//components/security_interstitials/core:core",
+ "//content/public/browser:browser",
+ "//content/public/common:common",
+ "//net:net",
+ ]
+ }
+
+ static_library("ping_manager") {
+ sources = [
+ "ping_manager.cc",
+ "ping_manager.h",
+ ]
+
+ public_deps = [
+ "//google_apis:google_apis",
+ ]
+
+ deps = [
+ "//base:base",
+ "//components/safe_browsing/db:hit_report",
+ "//components/safe_browsing/db:util",
+ "//content/public/browser:browser",
+ "//net:net",
+ ]
+ }
+
+ source_set("ping_manager_unittest") {
+ testonly = true
+ sources = [
+ "ping_manager_unittest.cc",
+ ]
+
+ deps = [
+ ":ping_manager",
+ "//base:base",
+ "//components/safe_browsing/db:v4_test_util",
+ "//net:net",
+ "//net:test_support",
+ "//testing/gtest",
+ ]
+ }
+
+ static_library("features") {
+ sources = [
+ "features.cc",
+ "features.h",
+ ]
+
+ deps = [
+ "//base:base",
+ "//components/safe_browsing:buildflags",
+ ]
+ }
+
+ source_set("public") {
+ sources = [
+ "safe_browsing_service_interface.cc",
+ "safe_browsing_service_interface.h",
+ ]
+
+ deps = [
+ "//base:base",
+ "//content/public/browser",
+ ]
+ }
+
+ source_set("verdict_cache_manager") {
+ sources = [
+ "verdict_cache_manager.cc",
+ "verdict_cache_manager.h",
+ ]
+
+ deps = [
+ ":csd_proto",
+ "//base",
+ "//components/content_settings/core/browser",
+ "//components/history/core/browser",
+ "//components/password_manager/core/browser:browser",
+ "//components/safe_browsing/db:v4_protocol_manager_util",
+ "//content/public/browser",
+ "//url",
+ ]
+ }
+
+ source_set("verdict_cache_manager_unittest") {
+ testonly = true
+ sources = [
+ "verdict_cache_manager_unittest.cc",
+ ]
+
+ deps = [
+ ":csd_proto",
+ ":verdict_cache_manager",
+ "//base",
+ "//components/content_settings/core/browser",
+ "//components/sync_preferences:test_support",
+ "//content/test:test_support",
+ "//testing/gtest",
+ ]
+ }
}
diff --git a/chromium/components/safe_browsing/DEPS b/chromium/components/safe_browsing/DEPS
index 04e04b00141..74f5a3b63c5 100644
--- a/chromium/components/safe_browsing/DEPS
+++ b/chromium/components/safe_browsing/DEPS
@@ -19,7 +19,9 @@ include_rules = [
"+net/traffic_annotation",
"+net/url_request",
"+services/network/public",
+ "+services/network/test",
"+services/service_manager/public",
"+testing/gtest",
+ "+third_party/blink/public/common/loader/url_loader_throttle.h",
"+third_party/protobuf",
]
diff --git a/chromium/components/safe_browsing/OWNERS b/chromium/components/safe_browsing/OWNERS
index 695d379be87..9659c18616c 100644
--- a/chromium/components/safe_browsing/OWNERS
+++ b/chromium/components/safe_browsing/OWNERS
@@ -1,7 +1,6 @@
+drubery@chromium.org
nparker@chromium.org
vakh@chromium.org
-# For componentization
-timvolodine@chromium.org
-
# COMPONENT: Services>Safebrowsing
+# TEAM: safebrowsing@chromium.org
diff --git a/chromium/components/safe_browsing/android/remote_database_manager.cc b/chromium/components/safe_browsing/android/remote_database_manager.cc
index 9976bfad856..055ed6c621c 100644
--- a/chromium/components/safe_browsing/android/remote_database_manager.cc
+++ b/chromium/components/safe_browsing/android/remote_database_manager.cc
@@ -22,10 +22,6 @@
using content::BrowserThread;
-namespace net {
-class URLRequestContextGetter;
-} // namespace net
-
namespace safe_browsing {
namespace {
@@ -63,17 +59,14 @@ class RemoteSafeBrowsingDatabaseManager::ClientRequest {
RemoteSafeBrowsingDatabaseManager* db_manager_;
GURL url_;
base::ElapsedTimer timer_;
- base::WeakPtrFactory<ClientRequest> weak_factory_;
+ base::WeakPtrFactory<ClientRequest> weak_factory_{this};
};
RemoteSafeBrowsingDatabaseManager::ClientRequest::ClientRequest(
Client* client,
RemoteSafeBrowsingDatabaseManager* db_manager,
const GURL& url)
- : client_(client),
- db_manager_(db_manager),
- url_(url),
- weak_factory_(this) {}
+ : client_(client), db_manager_(db_manager), url_(url) {}
// Static
void RemoteSafeBrowsingDatabaseManager::ClientRequest::OnRequestDoneWeak(
@@ -278,8 +271,8 @@ bool RemoteSafeBrowsingDatabaseManager::CheckUrlForSubresourceFilter(
AsyncMatch RemoteSafeBrowsingDatabaseManager::CheckCsdWhitelistUrl(
const GURL& url,
Client* client) {
- NOTREACHED();
- return AsyncMatch::MATCH;
+ // TODO(crbug.com/995926): Enable CSD allowlist on Android
+ return AsyncMatch::NO_MATCH;
}
bool RemoteSafeBrowsingDatabaseManager::MatchDownloadWhitelistString(
diff --git a/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc b/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
index 505457e12df..cb07c7082fe 100644
--- a/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
+++ b/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
@@ -14,7 +14,7 @@
#include "base/time/time.h"
#include "components/safe_browsing/android/safe_browsing_api_handler.h"
#include "components/variations/variations_associated_data.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace safe_browsing {
@@ -68,7 +68,7 @@ class RemoteDatabaseManagerTest : public testing::Test {
group_name, params));
}
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<base::FieldTrialList> field_trials_;
TestSafeBrowsingApiHandler api_handler_;
scoped_refptr<RemoteSafeBrowsingDatabaseManager> db_;
diff --git a/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc b/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
index e0c58104c7d..19c2555b37d 100644
--- a/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
+++ b/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
@@ -41,9 +41,8 @@ void RunCallbackOnIOThread(
const ThreatMetadata& metadata) {
CHECK(callback); // Remove after fixing crbug.com/889972
CHECK(!callback->is_null()); // Remove after fixing crbug.com/889972
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(std::move(*callback), threat_type, metadata));
+ base::PostTask(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(std::move(*callback), threat_type, metadata));
}
void ReportUmaResult(safe_browsing::UmaRemoteCallResult result) {
@@ -200,10 +199,9 @@ void JNI_SafeBrowsingApiBridge_OnUrlCheckDone(
<< " with status=" << result_status << " and metadata=["
<< metadata_str << "]";
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&OnUrlCheckDoneOnIOThread, callback_id, result_status,
- metadata_str));
+ base::PostTask(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&OnUrlCheckDoneOnIOThread, callback_id,
+ result_status, metadata_str));
}
//
diff --git a/chromium/components/safe_browsing/base_ui_manager.cc b/chromium/components/safe_browsing/base_ui_manager.cc
index 06c90f9eb8e..41187638be9 100644
--- a/chromium/components/safe_browsing/base_ui_manager.cc
+++ b/chromium/components/safe_browsing/base_ui_manager.cc
@@ -240,9 +240,12 @@ void BaseUIManager::DisplayBlockingPage(
resource.web_contents_getter.Run(),
true /* A decision is now pending */,
resource.threat_type);
- if (SafeBrowsingInterstitialsAreCommittedNavigations() &&
- resource.IsMainPageLoadBlocked()) {
- AddUnsafeResource(resource.url, resource);
+ if (SafeBrowsingInterstitialsAreCommittedNavigations()) {
+ GURL unsafe_url = (resource.IsMainPageLoadBlocked() ||
+ !resource.GetNavigationEntryForResource())
+ ? resource.url
+ : resource.GetNavigationEntryForResource()->GetURL();
+ AddUnsafeResource(unsafe_url, resource);
// With committed interstitials we just cancel the load from here, the
// actual interstitial will be shown from the
// SafeBrowsingNavigationThrottle.
diff --git a/chromium/components/safe_browsing/browser/BUILD.gn b/chromium/components/safe_browsing/browser/BUILD.gn
index 05167fb0f9b..777d390eeaf 100644
--- a/chromium/components/safe_browsing/browser/BUILD.gn
+++ b/chromium/components/safe_browsing/browser/BUILD.gn
@@ -7,16 +7,12 @@ import("//build/config/jumbo.gni")
jumbo_source_set("browser") {
sources = [
- "base_parallel_resource_throttle.cc",
- "base_parallel_resource_throttle.h",
"browser_url_loader_throttle.cc",
"browser_url_loader_throttle.h",
"mojo_safe_browsing_impl.cc",
"mojo_safe_browsing_impl.h",
"safe_browsing_url_checker_impl.cc",
"safe_browsing_url_checker_impl.h",
- "safe_browsing_url_request_context_getter.cc",
- "safe_browsing_url_request_context_getter.h",
"threat_details.cc",
"threat_details.h",
"threat_details_cache.cc",
@@ -29,11 +25,14 @@ jumbo_source_set("browser") {
"//components/history/core/browser:browser",
"//components/safe_browsing:csd_proto",
"//components/safe_browsing:features",
+ "//components/safe_browsing:realtimeapi_proto",
"//components/safe_browsing:safe_browsing",
"//components/safe_browsing/browser:network_context",
"//components/safe_browsing/browser:referrer_chain_provider",
"//components/safe_browsing/common:common",
"//components/safe_browsing/db:database_manager",
+ "//components/safe_browsing/realtime:policy_engine",
+ "//components/safe_browsing/realtime:url_lookup_service",
"//components/safe_browsing/web_ui:constants",
"//components/safe_browsing/web_ui:web_ui",
"//components/security_interstitials/content:security_interstitial_page",
@@ -67,9 +66,7 @@ source_set("referrer_chain_provider") {
source_set("unittests") {
testonly = true
- sources = [
- "base_parallel_resource_throttle_unittest.cc",
- ]
+ sources = []
deps = [
":browser",
diff --git a/chromium/components/safe_browsing/browser/DEPS b/chromium/components/safe_browsing/browser/DEPS
index 5b92a17e869..0bd06341cf9 100644
--- a/chromium/components/safe_browsing/browser/DEPS
+++ b/chromium/components/safe_browsing/browser/DEPS
@@ -16,6 +16,6 @@ include_rules = [
specific_include_rules = {
".*test\.cc": [
- "+content/public/test/test_browser_thread_bundle.h",
+ "+content/public/test/browser_task_environment.h",
],
}
diff --git a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc
deleted file mode 100644
index ddb86f35ee5..00000000000
--- a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/safe_browsing/browser/base_parallel_resource_throttle.h"
-
-#include <utility>
-
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/safe_browsing/browser/browser_url_loader_throttle.h"
-#include "components/safe_browsing/browser/url_checker_delegate.h"
-#include "content/public/browser/resource_request_info.h"
-#include "net/http/http_request_headers.h"
-#include "net/log/net_log_with_source.h"
-#include "net/url_request/url_request.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/resource_response.h"
-
-namespace safe_browsing {
-
-class BaseParallelResourceThrottle::URLLoaderThrottleHolder
- : public content::URLLoaderThrottle::Delegate {
- public:
- URLLoaderThrottleHolder(BaseParallelResourceThrottle* owner,
- std::unique_ptr<BrowserURLLoaderThrottle> throttle)
- : owner_(owner), throttle_(std::move(throttle)) {
- throttle_->set_delegate(this);
- }
- ~URLLoaderThrottleHolder() override = default;
-
- BrowserURLLoaderThrottle* throttle() const { return throttle_.get(); }
- uint32_t inside_delegate_calls() const { return inside_delegate_calls_; }
-
- // content::URLLoaderThrottle::Delegate implementation:
- void CancelWithError(int error_code,
- base::StringPiece custom_reason) override {
- if (!owner_)
- return;
-
- ScopedDelegateCall scoped_delegate_call(this);
- owner_->MayDeferCancelResourceLoad();
- }
-
- void Resume() override {
- if (!owner_)
- return;
-
- ScopedDelegateCall scoped_delegate_call(this);
- owner_->ResumeResourceLoad();
- }
-
- void Detach() {
- owner_ = nullptr;
- }
-
- private:
- class ScopedDelegateCall {
- public:
- explicit ScopedDelegateCall(URLLoaderThrottleHolder* holder)
- : holder_(holder) {
- holder_->inside_delegate_calls_++;
- }
- ~ScopedDelegateCall() { holder_->inside_delegate_calls_--; }
-
- private:
- URLLoaderThrottleHolder* const holder_;
- DISALLOW_COPY_AND_ASSIGN(ScopedDelegateCall);
- };
-
- BaseParallelResourceThrottle* owner_;
- uint32_t inside_delegate_calls_ = 0;
- std::unique_ptr<BrowserURLLoaderThrottle> throttle_;
-
- DISALLOW_COPY_AND_ASSIGN(URLLoaderThrottleHolder);
-};
-
-BaseParallelResourceThrottle::BaseParallelResourceThrottle(
- const net::URLRequest* request,
- content::ResourceType resource_type,
- scoped_refptr<UrlCheckerDelegate> url_checker_delegate)
- : request_(request), resource_type_(resource_type) {
- content::ResourceRequestInfo* info =
- content::ResourceRequestInfo::ForRequest(request_);
- auto throttle = BrowserURLLoaderThrottle::Create(
- base::BindOnce([](scoped_refptr<UrlCheckerDelegate> delegate,
- content::ResourceContext*) { return delegate; },
- url_checker_delegate),
- info->GetWebContentsGetterForRequest(), info->GetFrameTreeNodeId(),
- info->GetContext());
- url_loader_throttle_holder_ =
- std::make_unique<URLLoaderThrottleHolder>(this, std::move(throttle));
-}
-
-BaseParallelResourceThrottle::~BaseParallelResourceThrottle() {
- if (url_loader_throttle_holder_->inside_delegate_calls() > 0) {
- // The BrowserURLLoaderThrottle owned by |url_loader_throttle_holder_| is
- // calling into this object. In this case, delay destruction of
- // |url_loader_throttle_holder_|, so that the BrowserURLLoaderThrottle
- // doesn't need to worry about any delegate calls may destroy it
- // synchronously.
- url_loader_throttle_holder_->Detach();
-
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(
- FROM_HERE, std::move(url_loader_throttle_holder_));
- }
-}
-
-void BaseParallelResourceThrottle::WillStartRequest(bool* defer) {
- throttle_in_band_ = true;
- if (should_cancel_on_notification_) {
- CancelResourceLoad();
- return;
- }
-
- network::ResourceRequest resource_request;
-
- net::HttpRequestHeaders full_headers;
- resource_request.headers = request_->GetFullRequestHeaders(&full_headers)
- ? full_headers
- : request_->extra_request_headers();
-
- resource_request.load_flags = request_->load_flags();
- resource_request.resource_type = static_cast<int>(resource_type_);
-
- content::ResourceRequestInfo* info =
- content::ResourceRequestInfo::ForRequest(request_);
- resource_request.has_user_gesture = info && info->HasUserGesture();
-
- resource_request.url = request_->url();
- resource_request.method = request_->method();
-
- url_loader_throttle_holder_->throttle()->WillStartRequest(&resource_request,
- defer);
- DCHECK(!*defer);
- throttle_in_band_ = false;
-}
-
-void BaseParallelResourceThrottle::WillRedirectRequest(
- const net::RedirectInfo& redirect_info,
- bool* defer) {
- throttle_in_band_ = true;
- if (should_cancel_on_notification_) {
- CancelResourceLoad();
- return;
- }
-
- // The safe browsing URLLoaderThrottle doesn't use the |resource_head|,
- // |to_be_modified_headers|, |modified_headers| or |new_url| parameters, so
- // pass in an empty struct to avoid changing ResourceThrottle signature.
- network::ResourceResponseHead resource_head;
- std::vector<std::string> to_be_removed_headers;
- net::HttpRequestHeaders modified_headers;
- net::RedirectInfo redirect_info_copy = redirect_info;
- url_loader_throttle_holder_->throttle()->WillRedirectRequest(
- &redirect_info_copy, resource_head, defer, &to_be_removed_headers,
- &modified_headers);
- DCHECK(!*defer);
- throttle_in_band_ = false;
-}
-
-void BaseParallelResourceThrottle::WillProcessResponse(bool* defer) {
- throttle_in_band_ = true;
- if (should_cancel_on_notification_) {
- CancelResourceLoad();
- return;
- }
-
- network::ResourceResponseHead response_head;
- url_loader_throttle_holder_->throttle()->WillProcessResponse(
- GURL(), &response_head, defer);
- if (!*defer)
- throttle_in_band_ = false;
-}
-
-const char* BaseParallelResourceThrottle::GetNameForLogging() {
- return "BaseParallelResourceThrottle";
-}
-
-bool BaseParallelResourceThrottle::MustProcessResponseBeforeReadingBody() {
- // The response body should not be cached before SafeBrowsing confirms that it
- // is safe to do so.
- return true;
-}
-
-void BaseParallelResourceThrottle::CancelResourceLoad() {
- DCHECK(throttle_in_band_);
- throttle_in_band_ = false;
- Cancel();
-}
-
-void BaseParallelResourceThrottle::ResumeResourceLoad() {
- DCHECK(throttle_in_band_);
- throttle_in_band_ = false;
- Resume();
-}
-
-void BaseParallelResourceThrottle::MayDeferCancelResourceLoad() {
- if (!throttle_in_band_)
- should_cancel_on_notification_ = true;
- else
- CancelResourceLoad();
-}
-
-} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.h b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.h
deleted file mode 100644
index 91e01c8c81b..00000000000
--- a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle.h
+++ /dev/null
@@ -1,70 +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 COMPONENTS_SAFE_BROWSING_BROWSER_BASE_PARALLEL_RESOURCE_THROTTLE_H_
-#define COMPONENTS_SAFE_BROWSING_BROWSER_BASE_PARALLEL_RESOURCE_THROTTLE_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/public/browser/resource_throttle.h"
-#include "content/public/common/resource_type.h"
-#include "content/public/common/url_loader_throttle.h"
-
-namespace net {
-class URLRequest;
-}
-
-namespace safe_browsing {
-
-class BrowserURLLoaderThrottle;
-class UrlCheckerDelegate;
-
-// A thin wrapper around BrowserURLLoaderThrottle to adapt to the
-// content::ResourceThrottle interface.
-class BaseParallelResourceThrottle : public content::ResourceThrottle {
- protected:
- BaseParallelResourceThrottle(
- const net::URLRequest* request,
- content::ResourceType resource_type,
- scoped_refptr<UrlCheckerDelegate> url_checker_delegate);
-
- ~BaseParallelResourceThrottle() override;
-
- // content::ResourceThrottle implementation:
- void WillStartRequest(bool* defer) override;
- void WillRedirectRequest(const net::RedirectInfo& redirect_info,
- bool* defer) override;
- void WillProcessResponse(bool* defer) override;
- const char* GetNameForLogging() override;
- bool MustProcessResponseBeforeReadingBody() override;
-
- // Cancels the resource load. This calls ResourceThrottle::Cancel() but also
- // maintains internal state. It may be overridden in a subclass. The override
- // in subclass should call this base implementation for cancellation, instead
- // of calling ResourceThrottle::Cancel() directly.
- virtual void CancelResourceLoad();
-
- private:
- class URLLoaderThrottleHolder;
-
- void ResumeResourceLoad();
- void MayDeferCancelResourceLoad();
-
- const net::URLRequest* const request_;
- const content::ResourceType resource_type_;
- // Set to true if the throttle is currently either inside a ResourceThrottle
- // notification call or responsible for deferring the request.
- bool throttle_in_band_ = false;
- // Whether we should directly cancel the request on subsequent
- // ResourceThrottle notification calls.
- bool should_cancel_on_notification_ = false;
-
- std::unique_ptr<URLLoaderThrottleHolder> url_loader_throttle_holder_;
-
- DISALLOW_COPY_AND_ASSIGN(BaseParallelResourceThrottle);
-};
-
-} // namespace safe_browsing
-
-#endif // COMPONENTS_SAFE_BROWSING_BROWSER_BASE_PARALLEL_RESOURCE_THROTTLE_H_
diff --git a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc b/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc
deleted file mode 100644
index 9f245e4945d..00000000000
--- a/chromium/components/safe_browsing/browser/base_parallel_resource_throttle_unittest.cc
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/safe_browsing/browser/base_parallel_resource_throttle.h"
-
-#include "base/memory/ref_counted.h"
-#include "components/safe_browsing/browser/url_checker_delegate.h"
-#include "components/safe_browsing/db/test_database_manager.h"
-#include "components/security_interstitials/content/unsafe_resource.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/browser/resource_throttle.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/redirect_info.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace safe_browsing {
-
-class TestResourceThrottleDelegate
- : public content::ResourceThrottle::Delegate {
- public:
- int cancel_called() const { return cancel_called_; }
- int resume_called() const { return resume_called_; }
-
- void Cancel() override { cancel_called_++; }
- void CancelWithError(int error_code) override { cancel_called_++; }
- void Resume() override { resume_called_++; }
-
- private:
- int cancel_called_ = 0;
- int resume_called_ = 0;
-};
-
-class TestDatabaseManager : public TestSafeBrowsingDatabaseManager {
- public:
- ThreatSource GetThreatSource() const override {
- return ThreatSource::UNKNOWN;
- }
-
- bool IsSupported() const override { return true; }
-
- bool CanCheckResourceType(
- content::ResourceType resource_type) const override {
- return true;
- }
-
- bool ChecksAreAlwaysAsync() const override { return false; }
-
- bool CheckBrowseUrl(const GURL& url,
- const SBThreatTypeSet& threat_types,
- Client* client) override {
- DCHECK(!last_client_);
-
- check_browse_url_called_++;
-
- // Immediately return that the url is safe.
- if (delay_check_browse_url_calls_ == 0)
- return true;
-
- delay_check_browse_url_calls_--;
- last_client_ = client;
- last_url_ = url;
- return false;
- }
-
- void CancelCheck(Client* client) override {}
-
- int check_browse_url_called() const { return check_browse_url_called_; }
-
- void DelayCheckBrowseUrlResult(int num_calls) {
- delay_check_browse_url_calls_ += num_calls;
- }
-
- void CompleteNextCheckBrowseUrl(bool safe) {
- DCHECK(last_client_);
-
- Client* temp = last_client_;
- last_client_ = nullptr;
- temp->OnCheckBrowseUrlResult(
- last_url_, safe ? SB_THREAT_TYPE_SAFE : SB_THREAT_TYPE_URL_MALWARE,
- ThreatMetadata());
- }
-
- private:
- ~TestDatabaseManager() override {}
-
- int check_browse_url_called_ = 0;
- Client* last_client_ = nullptr;
- GURL last_url_;
- int delay_check_browse_url_calls_ = 0;
-};
-
-class TestUrlCheckerDelegate : public UrlCheckerDelegate {
- public:
- explicit TestUrlCheckerDelegate(
- scoped_refptr<TestDatabaseManager> database_manager)
- : threat_types_(CreateSBThreatTypeSet(
- {safe_browsing::SB_THREAT_TYPE_URL_MALWARE,
- safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
- safe_browsing::SB_THREAT_TYPE_URL_UNWANTED})),
- database_manager_(std::move(database_manager)) {}
-
- void MaybeDestroyPrerenderContents(
- const base::Callback<content::WebContents*()>& web_contents_getter)
- override {}
-
- void StartDisplayingBlockingPageHelper(
- const security_interstitials::UnsafeResource& resource,
- const std::string& method,
- const net::HttpRequestHeaders& headers,
- bool is_main_frame,
- bool has_user_gesture) override {
- resource.callback.Run(false);
- }
-
- bool IsUrlWhitelisted(const GURL& url) override { return false; }
-
- bool ShouldSkipRequestCheck(content::ResourceContext* resource_context,
- const GURL& original_url,
- int frame_tree_node_id,
- int render_process_id,
- int render_frame_id,
- bool originated_from_service_worker) override {
- return false;
- }
-
- void NotifySuspiciousSiteDetected(
- const base::RepeatingCallback<content::WebContents*()>&
- web_contents_getter) override {}
- const SBThreatTypeSet& GetThreatTypes() override { return threat_types_; }
- SafeBrowsingDatabaseManager* GetDatabaseManager() override {
- return database_manager_.get();
- }
- BaseUIManager* GetUIManager() override { return nullptr; }
-
- private:
- ~TestUrlCheckerDelegate() override {}
-
- SBThreatTypeSet threat_types_;
- scoped_refptr<TestDatabaseManager> database_manager_;
-};
-
-class TestParallelResourceThrottle : public BaseParallelResourceThrottle {
- public:
- TestParallelResourceThrottle(
- const net::URLRequest* request,
- content::ResourceType resource_type,
- scoped_refptr<UrlCheckerDelegate> url_checker_delegate)
- : BaseParallelResourceThrottle(request,
- resource_type,
- std::move(url_checker_delegate)) {}
-
- // BaseParallelResourceThrottle overrides to expose them as public methods.
- void WillStartRequest(bool* defer) override {
- BaseParallelResourceThrottle::WillStartRequest(defer);
- }
-
- void WillRedirectRequest(const net::RedirectInfo& redirect_info,
- bool* defer) override {
- BaseParallelResourceThrottle::WillRedirectRequest(redirect_info, defer);
- }
-
- void WillProcessResponse(bool* defer) override {
- BaseParallelResourceThrottle::WillProcessResponse(defer);
- }
-};
-
-class BaseParallelResourceThrottleTest : public testing::Test {
- protected:
- BaseParallelResourceThrottleTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
-
- void SetUp() override {
- request_ = request_context_.CreateRequest(GURL("http://example.org"),
- net::MEDIUM, &request_delegate_,
- TRAFFIC_ANNOTATION_FOR_TESTS);
- content::ResourceRequestInfo::AllocateForTesting(
- request_.get(), content::ResourceType::kMainFrame, nullptr, -1, -1, -1,
- true, content::ResourceInterceptPolicy::kAllowAll, true,
- content::PREVIEWS_OFF, nullptr);
-
- database_manager_ = new TestDatabaseManager();
- url_checker_delegate_ = new TestUrlCheckerDelegate(database_manager_);
- throttle_ = std::make_unique<TestParallelResourceThrottle>(
- request_.get(), content::ResourceType::kMainFrame,
- url_checker_delegate_);
- throttle_->set_delegate_for_testing(&resource_throttle_delegate_);
- }
-
- content::TestBrowserThreadBundle thread_bundle_;
- net::TestURLRequestContext request_context_;
- net::TestDelegate request_delegate_;
- std::unique_ptr<net::URLRequest> request_;
- scoped_refptr<TestDatabaseManager> database_manager_;
- scoped_refptr<UrlCheckerDelegate> url_checker_delegate_;
- TestResourceThrottleDelegate resource_throttle_delegate_;
- std::unique_ptr<TestParallelResourceThrottle> throttle_;
-};
-
-TEST_F(BaseParallelResourceThrottleTest, Resume) {
- database_manager_->DelayCheckBrowseUrlResult(2);
- bool defer = false;
- throttle_->WillStartRequest(&defer);
-
- // Although there is a pending URL check, starting request is not deferred.
- EXPECT_FALSE(defer);
- EXPECT_EQ(1, database_manager_->check_browse_url_called());
-
- // Following redirects is also not deferred by pending URL checks.
- throttle_->WillRedirectRequest(net::RedirectInfo(), &defer);
- EXPECT_FALSE(defer);
- // The throttle doesn't initiate a new URL check until the previous one is
- // completed.
- EXPECT_EQ(1, database_manager_->check_browse_url_called());
-
- throttle_->WillProcessResponse(&defer);
- EXPECT_TRUE(defer);
-
- EXPECT_EQ(0, resource_throttle_delegate_.resume_called());
-
- database_manager_->CompleteNextCheckBrowseUrl(true);
- EXPECT_EQ(2, database_manager_->check_browse_url_called());
- database_manager_->CompleteNextCheckBrowseUrl(true);
-
- EXPECT_EQ(1, resource_throttle_delegate_.resume_called());
-}
-
-TEST_F(BaseParallelResourceThrottleTest, CancelWhenDeferred) {
- database_manager_->DelayCheckBrowseUrlResult(1);
- bool defer = false;
- throttle_->WillStartRequest(&defer);
-
- // Although there is a pending URL check, starting request is not deferred.
- EXPECT_FALSE(defer);
- EXPECT_EQ(1, database_manager_->check_browse_url_called());
-
- throttle_->WillProcessResponse(&defer);
- EXPECT_TRUE(defer);
-
- EXPECT_EQ(0, resource_throttle_delegate_.cancel_called());
-
- database_manager_->CompleteNextCheckBrowseUrl(false);
-
- EXPECT_EQ(1, resource_throttle_delegate_.cancel_called());
-}
-
-TEST_F(BaseParallelResourceThrottleTest, CancelBeforeWillRedirectRequest) {
- database_manager_->DelayCheckBrowseUrlResult(1);
- bool defer = false;
- throttle_->WillStartRequest(&defer);
-
- EXPECT_FALSE(defer);
- EXPECT_EQ(1, database_manager_->check_browse_url_called());
- database_manager_->CompleteNextCheckBrowseUrl(false);
-
- // Cancellation is delayed to the next throttle notification event (in order
- // to avoid confusing ResourceLoader).
- EXPECT_EQ(0, resource_throttle_delegate_.cancel_called());
-
- throttle_->WillRedirectRequest(net::RedirectInfo(), &defer);
-
- EXPECT_EQ(1, resource_throttle_delegate_.cancel_called());
-}
-
-TEST_F(BaseParallelResourceThrottleTest, CancelBeforeWillProcessResponse) {
- database_manager_->DelayCheckBrowseUrlResult(1);
- bool defer = false;
- throttle_->WillStartRequest(&defer);
-
- EXPECT_FALSE(defer);
- EXPECT_EQ(1, database_manager_->check_browse_url_called());
- database_manager_->CompleteNextCheckBrowseUrl(false);
-
- // Cancellation is delayed to the next throttle notification event (in order
- // to avoid confusing ResourceLoader).
- EXPECT_EQ(0, resource_throttle_delegate_.cancel_called());
-
- throttle_->WillProcessResponse(&defer);
-
- EXPECT_EQ(1, resource_throttle_delegate_.cancel_called());
-}
-
-} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc b/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc
index cf407713ee8..185cace5da9 100644
--- a/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc
+++ b/chromium/components/safe_browsing/browser/browser_url_loader_throttle.cc
@@ -18,22 +18,6 @@
#include "services/network/public/cpp/resource_response.h"
namespace safe_browsing {
-namespace {
-
-// Runs |task| on the thread specified by |thread_id| if already on that thread,
-// otherwise posts a task to that thread.
-void RunOrPostTaskIfNecessary(const base::Location& from_here,
- content::BrowserThread::ID thread_id,
- base::OnceClosure task) {
- if (content::BrowserThread::CurrentlyOn(thread_id)) {
- std::move(task).Run();
- return;
- }
-
- base::PostTaskWithTraits(from_here, {thread_id}, std::move(task));
-}
-
-} // namespace
// TODO(http://crbug.com/824843): Remove this if safe browsing is moved to the
// UI thread.
@@ -45,13 +29,11 @@ class BrowserURLLoaderThrottle::CheckerOnIO
content::ResourceContext* resource_context,
int frame_tree_node_id,
base::RepeatingCallback<content::WebContents*()> web_contents_getter,
- content::BrowserThread::ID throttle_thread_id,
base::WeakPtr<BrowserURLLoaderThrottle> throttle)
: delegate_getter_(std::move(delegate_getter)),
resource_context_(resource_context),
frame_tree_node_id_(frame_tree_node_id),
web_contents_getter_(web_contents_getter),
- throttle_thread_id_(throttle_thread_id),
throttle_(std::move(throttle)) {}
// Starts the initial safe browsing check. This check and future checks may be
@@ -73,8 +55,8 @@ class BrowserURLLoaderThrottle::CheckerOnIO
-1 /* render_process_id */, -1 /* render_frame_id */,
originated_from_service_worker);
if (skip_checks_) {
- RunOrPostTaskIfNecessary(
- FROM_HERE, throttle_thread_id_,
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&BrowserURLLoaderThrottle::SkipChecks, throttle_));
return;
}
@@ -90,8 +72,8 @@ class BrowserURLLoaderThrottle::CheckerOnIO
void CheckUrl(const GURL& url, const std::string& method) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (skip_checks_) {
- RunOrPostTaskIfNecessary(
- FROM_HERE, throttle_thread_id_,
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&BrowserURLLoaderThrottle::SkipChecks, throttle_));
return;
}
@@ -117,8 +99,8 @@ class BrowserURLLoaderThrottle::CheckerOnIO
return;
}
- RunOrPostTaskIfNecessary(
- FROM_HERE, throttle_thread_id_,
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&BrowserURLLoaderThrottle::NotifySlowCheck, throttle_));
// In this case |proceed| and |showed_interstitial| should be ignored. The
@@ -133,8 +115,8 @@ class BrowserURLLoaderThrottle::CheckerOnIO
void OnCompleteCheck(bool slow_check,
bool proceed,
bool showed_interstitial) {
- RunOrPostTaskIfNecessary(
- FROM_HERE, throttle_thread_id_,
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&BrowserURLLoaderThrottle::OnCompleteCheck, throttle_,
slow_check, proceed, showed_interstitial));
}
@@ -147,7 +129,6 @@ class BrowserURLLoaderThrottle::CheckerOnIO
int frame_tree_node_id_;
base::RepeatingCallback<content::WebContents*()> web_contents_getter_;
bool skip_checks_ = false;
- content::BrowserThread::ID throttle_thread_id_;
base::WeakPtr<BrowserURLLoaderThrottle> throttle_;
};
@@ -168,14 +149,14 @@ BrowserURLLoaderThrottle::BrowserURLLoaderThrottle(
const base::Callback<content::WebContents*()>& web_contents_getter,
int frame_tree_node_id,
content::ResourceContext* resource_context) {
- content::BrowserThread::ID thread_id;
- CHECK(content::BrowserThread::GetCurrentThreadIdentifier(&thread_id));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
io_checker_ = std::make_unique<CheckerOnIO>(
std::move(delegate_getter), resource_context, frame_tree_node_id,
- web_contents_getter, thread_id, weak_factory_.GetWeakPtr());
+ web_contents_getter, weak_factory_.GetWeakPtr());
}
BrowserURLLoaderThrottle::~BrowserURLLoaderThrottle() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (deferred_)
TRACE_EVENT_ASYNC_END0("safe_browsing", "Deferred", this);
@@ -188,13 +169,14 @@ BrowserURLLoaderThrottle::~BrowserURLLoaderThrottle() {
void BrowserURLLoaderThrottle::WillStartRequest(
network::ResourceRequest* request,
bool* defer) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK_EQ(0u, pending_checks_);
DCHECK(!blocked_);
original_url_ = request->url;
pending_checks_++;
- RunOrPostTaskIfNecessary(
- FROM_HERE, content::BrowserThread::IO,
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(
&BrowserURLLoaderThrottle::CheckerOnIO::Start,
io_checker_->AsWeakPtr(), request->headers, request->load_flags,
@@ -209,6 +191,7 @@ void BrowserURLLoaderThrottle::WillRedirectRequest(
bool* defer,
std::vector<std::string>* /* to_be_removed_headers */,
net::HttpRequestHeaders* /* modified_headers */) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (blocked_) {
// OnCheckUrlResult() has set |blocked_| to true and called
// |delegate_->CancelWithError|, but this method is called before the
@@ -221,8 +204,8 @@ void BrowserURLLoaderThrottle::WillRedirectRequest(
return;
pending_checks_++;
- RunOrPostTaskIfNecessary(
- FROM_HERE, content::BrowserThread::IO,
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&BrowserURLLoaderThrottle::CheckerOnIO::CheckUrl,
io_checker_->AsWeakPtr(), redirect_info->new_url,
redirect_info->new_method));
@@ -232,6 +215,7 @@ void BrowserURLLoaderThrottle::WillProcessResponse(
const GURL& response_url,
network::ResourceResponseHead* response_head,
bool* defer) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (blocked_) {
// OnCheckUrlResult() has set |blocked_| to true and called
// |delegate_->CancelWithError|, but this method is called before the
@@ -254,6 +238,7 @@ void BrowserURLLoaderThrottle::WillProcessResponse(
void BrowserURLLoaderThrottle::OnCompleteCheck(bool slow_check,
bool proceed,
bool showed_interstitial) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(!blocked_);
DCHECK_LT(0u, pending_checks_);
@@ -291,6 +276,7 @@ void BrowserURLLoaderThrottle::OnCompleteCheck(bool slow_check,
}
void BrowserURLLoaderThrottle::SkipChecks() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Future checks for redirects will be skipped.
skip_checks_ = true;
@@ -300,6 +286,7 @@ void BrowserURLLoaderThrottle::SkipChecks() {
}
void BrowserURLLoaderThrottle::NotifySlowCheck() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
pending_slow_checks_++;
// Pending slow checks indicate that the resource may be unsafe. In that case,
@@ -312,9 +299,8 @@ void BrowserURLLoaderThrottle::NotifySlowCheck() {
}
void BrowserURLLoaderThrottle::DeleteCheckerOnIO() {
- RunOrPostTaskIfNecessary(FROM_HERE, content::BrowserThread::IO,
- base::BindOnce([](std::unique_ptr<CheckerOnIO>) {},
- std::move(io_checker_)));
+ content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
+ std::move(io_checker_));
}
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/browser/browser_url_loader_throttle.h b/chromium/components/safe_browsing/browser/browser_url_loader_throttle.h
index 33d4dd7f629..96a2c5a2d0f 100644
--- a/chromium/components/safe_browsing/browser/browser_url_loader_throttle.h
+++ b/chromium/components/safe_browsing/browser/browser_url_loader_throttle.h
@@ -13,7 +13,7 @@
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/url_loader_throttle.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "url/gurl.h"
namespace content {
@@ -38,7 +38,7 @@ class UrlCheckerDelegate;
// and redirect chain are not complete by the time the response headers are
// available, the request is deferred until all the checks are done. It cancels
// the load if any URLs turn out to be bad.
-class BrowserURLLoaderThrottle : public content::URLLoaderThrottle {
+class BrowserURLLoaderThrottle : public blink::URLLoaderThrottle {
public:
using GetDelegateCallback =
base::OnceCallback<scoped_refptr<UrlCheckerDelegate>(
@@ -52,7 +52,7 @@ class BrowserURLLoaderThrottle : public content::URLLoaderThrottle {
~BrowserURLLoaderThrottle() override;
- // content::URLLoaderThrottle implementation.
+ // blink::URLLoaderThrottle implementation.
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override;
void WillRedirectRequest(net::RedirectInfo* redirect_info,
diff --git a/chromium/components/safe_browsing/browser/safe_browsing_network_context.cc b/chromium/components/safe_browsing/browser/safe_browsing_network_context.cc
index ddca8cdc9d5..713f202f06f 100644
--- a/chromium/components/safe_browsing/browser/safe_browsing_network_context.cc
+++ b/chromium/components/safe_browsing/browser/safe_browsing_network_context.cc
@@ -13,11 +13,12 @@
#include "components/safe_browsing/common/safebrowsing_constants.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/network_context_client_base.h"
#include "content/public/browser/network_service_instance.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/net_buildflags.h"
-#include "net/url_request/url_request_context_getter.h"
#include "services/network/network_context.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace safe_browsing {
@@ -26,11 +27,9 @@ class SafeBrowsingNetworkContext::SharedURLLoaderFactory
: public network::SharedURLLoaderFactory {
public:
SharedURLLoaderFactory(
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const base::FilePath& user_data_dir,
NetworkContextParamsFactory network_context_params_factory)
- : request_context_getter_(request_context_getter),
- user_data_dir_(user_data_dir),
+ : user_data_dir_(user_data_dir),
network_context_params_factory_(
std::move(network_context_params_factory)) {}
@@ -38,25 +37,19 @@ class SafeBrowsingNetworkContext::SharedURLLoaderFactory
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
url_loader_factory_.reset();
network_context_.reset();
- request_context_getter_ = nullptr;
- if (internal_state_) {
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&InternalState::Reset, internal_state_));
- }
}
network::mojom::NetworkContext* GetNetworkContext() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (!network_context_ || network_context_.encountered_error()) {
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- content::GetNetworkService()->CreateNetworkContext(
- MakeRequest(&network_context_), CreateNetworkContextParams());
- } else {
- internal_state_ = base::MakeRefCounted<InternalState>();
- internal_state_->Initialize(request_context_getter_,
- MakeRequest(&network_context_));
- }
+ content::GetNetworkService()->CreateNetworkContext(
+ MakeRequest(&network_context_), CreateNetworkContextParams());
+
+ mojo::PendingRemote<network::mojom::NetworkContextClient> client_remote;
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<content::NetworkContextClientBase>(),
+ client_remote.InitWithNewPipeAndPassReceiver());
+ network_context_->SetClient(std::move(client_remote));
}
return network_context_.get();
}
@@ -108,46 +101,6 @@ class SafeBrowsingNetworkContext::SharedURLLoaderFactory
}
private:
- // This class holds on to the network::NetworkContext object on the IO thread.
- class InternalState : public base::RefCountedThreadSafe<InternalState> {
- public:
- InternalState() = default;
-
- void Initialize(
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- network::mojom::NetworkContextRequest network_context_request) {
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&InternalState::InitOnIO, this, request_context_getter,
- std::move(network_context_request)));
- }
-
- void Reset() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- network_context_impl_.reset();
- request_context_getter_ = nullptr;
- }
-
- private:
- friend class base::RefCountedThreadSafe<InternalState>;
- virtual ~InternalState() {}
-
- void InitOnIO(
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
- network::mojom::NetworkContextRequest network_context_request) {
- request_context_getter_ = std::move(request_context_getter);
- network_context_impl_ = std::make_unique<network::NetworkContext>(
- content::GetNetworkServiceImpl(), std::move(network_context_request),
- request_context_getter_->GetURLRequestContext(),
- /*cors_exempt_header_list=*/std::vector<std::string>());
- }
-
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
- std::unique_ptr<network::NetworkContext> network_context_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(InternalState);
- };
-
friend class base::RefCounted<SharedURLLoaderFactory>;
~SharedURLLoaderFactory() override = default;
@@ -173,24 +126,20 @@ class SafeBrowsingNetworkContext::SharedURLLoaderFactory
return network_context_params;
}
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
base::FilePath user_data_dir_;
NetworkContextParamsFactory network_context_params_factory_;
network::mojom::NetworkContextPtr network_context_;
network::mojom::URLLoaderFactoryPtr url_loader_factory_;
- scoped_refptr<InternalState> internal_state_;
DISALLOW_COPY_AND_ASSIGN(SharedURLLoaderFactory);
};
SafeBrowsingNetworkContext::SafeBrowsingNetworkContext(
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const base::FilePath& user_data_dir,
NetworkContextParamsFactory network_context_params_factory) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
url_loader_factory_ = base::MakeRefCounted<SharedURLLoaderFactory>(
- request_context_getter, user_data_dir,
- std::move(network_context_params_factory));
+ user_data_dir, std::move(network_context_params_factory));
}
SafeBrowsingNetworkContext::~SafeBrowsingNetworkContext() {
diff --git a/chromium/components/safe_browsing/browser/safe_browsing_network_context.h b/chromium/components/safe_browsing/browser/safe_browsing_network_context.h
index 8d8bbee26e1..5e57a5e67f7 100644
--- a/chromium/components/safe_browsing/browser/safe_browsing_network_context.h
+++ b/chromium/components/safe_browsing/browser/safe_browsing_network_context.h
@@ -11,10 +11,6 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/network_service.mojom.h"
-namespace net {
-class URLRequestContextGetter;
-}
-
namespace network {
namespace mojom {
class NetworkContext;
@@ -26,19 +22,13 @@ namespace safe_browsing {
// This class owns the NetworkContext that is used for requests by Safe
// Browsing.
// All methods are called on the UI thread.
-// Note: temporarily this is wrapping SafeBrowsingURLRequestContextGetter,
-// however once all requests are converted to using the network service mojo
-// APIs we can delete SafeBrowsingURLRequestContextGetter and this object will
-// create the NetworkContext directly. http://crbug.com/825242
class SafeBrowsingNetworkContext {
public:
- // |request_context_getter| is used only if network service is disabled.
- // Otherwise |user_dtaa_dir| and |network_context_params_factory| are used
+ // |user_data_dir| and |network_context_params_factory| are used
// to construct a URLRequestContext through the network service.
using NetworkContextParamsFactory =
base::RepeatingCallback<network::mojom::NetworkContextParamsPtr()>;
SafeBrowsingNetworkContext(
- scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const base::FilePath& user_data_dir,
NetworkContextParamsFactory network_context_params_factory);
~SafeBrowsingNetworkContext();
@@ -52,8 +42,7 @@ class SafeBrowsingNetworkContext {
// Flushes NetworkContext and URLLoaderFactory pipes.
void FlushForTesting();
- // Called at shutdown to ensure that the URLRequestContextGetter reference is
- // destroyed..
+ // Called at shutdown to ensure that the URLLoaderFactory is cleaned up.
void ServiceShuttingDown();
private:
diff --git a/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc b/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc
index 20595fef92d..5f83d51aa69 100644
--- a/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc
+++ b/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc
@@ -9,6 +9,8 @@
#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "components/safe_browsing/browser/url_checker_delegate.h"
+#include "components/safe_browsing/realtime/policy_engine.h"
+#include "components/safe_browsing/realtime/url_lookup_service.h"
#include "components/safe_browsing/web_ui/constants.h"
#include "components/security_interstitials/content/unsafe_resource.h"
#include "content/public/browser/browser_task_traits.h"
@@ -26,6 +28,10 @@ namespace {
// the resource will be treated as if it were safe.
const int kCheckUrlTimeoutMs = 5000;
+void RecordCheckUrlTimeout(bool timed_out) {
+ UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.CheckUrl.Timeout", timed_out);
+}
+
} // namespace
SafeBrowsingUrlCheckerImpl::Notifier::Notifier(CheckUrlCallback callback)
@@ -126,11 +132,18 @@ void SafeBrowsingUrlCheckerImpl::OnCheckBrowseUrlResult(
const GURL& url,
SBThreatType threat_type,
const ThreatMetadata& metadata) {
+ OnUrlResult(url, threat_type, metadata);
+}
+
+void SafeBrowsingUrlCheckerImpl::OnUrlResult(const GURL& url,
+ SBThreatType threat_type,
+ const ThreatMetadata& metadata) {
DCHECK_EQ(STATE_CHECKING_URL, state_);
DCHECK_LT(next_index_, urls_.size());
DCHECK_EQ(urls_[next_index_].url, url);
timer_.Stop();
+ RecordCheckUrlTimeout(/*timed_out=*/false);
TRACE_EVENT_ASYNC_END1(
"safe_browsing", "CheckUrl", this, "result",
@@ -180,8 +193,8 @@ void SafeBrowsingUrlCheckerImpl::OnCheckBrowseUrlResult(
resource.callback =
base::Bind(&SafeBrowsingUrlCheckerImpl::OnBlockingPageComplete,
weak_factory_.GetWeakPtr());
- resource.callback_thread = base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::IO});
+ resource.callback_thread =
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO});
resource.web_contents_getter = web_contents_getter_;
resource.threat_source = database_manager_->GetThreatSource();
@@ -191,11 +204,13 @@ void SafeBrowsingUrlCheckerImpl::OnCheckBrowseUrlResult(
resource_type_ == content::ResourceType::kMainFrame, has_user_gesture_);
}
-void SafeBrowsingUrlCheckerImpl::OnCheckUrlTimeout() {
+void SafeBrowsingUrlCheckerImpl::OnTimeout() {
+ RecordCheckUrlTimeout(/*timed_out=*/true);
+
database_manager_->CancelCheck(this);
- OnCheckBrowseUrlResult(urls_[next_index_].url,
- safe_browsing::SB_THREAT_TYPE_SAFE, ThreatMetadata());
+ OnUrlResult(urls_[next_index_].url, safe_browsing::SB_THREAT_TYPE_SAFE,
+ ThreatMetadata());
}
void SafeBrowsingUrlCheckerImpl::CheckUrlImpl(const GURL& url,
@@ -210,6 +225,7 @@ void SafeBrowsingUrlCheckerImpl::CheckUrlImpl(const GURL& url,
}
void SafeBrowsingUrlCheckerImpl::ProcessUrls() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
DCHECK_NE(STATE_BLOCKED, state_);
if (state_ == STATE_CHECKING_URL ||
@@ -221,7 +237,6 @@ void SafeBrowsingUrlCheckerImpl::ProcessUrls() {
DCHECK_EQ(STATE_NONE, state_);
const GURL& url = urls_[next_index_].url;
-
if (url_checker_delegate_->IsUrlWhitelisted(url)) {
if (!RunNextCallback(true, false))
return;
@@ -254,7 +269,7 @@ void SafeBrowsingUrlCheckerImpl::ProcessUrls() {
TRACE_EVENT_ASYNC_BEGIN1("safe_browsing", "CheckUrl", this, "url",
url.spec());
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&SafeBrowsingUrlCheckerImpl::OnCheckBrowseUrlResult,
weak_factory_.GetWeakPtr(), url, threat_type,
@@ -262,8 +277,62 @@ void SafeBrowsingUrlCheckerImpl::ProcessUrls() {
break;
}
- if (database_manager_->CheckBrowseUrl(
- url, url_checker_delegate_->GetThreatTypes(), this)) {
+ TRACE_EVENT_ASYNC_BEGIN1("safe_browsing", "CheckUrl", this, "url",
+ url.spec());
+
+ // Start a timer to abort the check if it takes too long.
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), this,
+ &SafeBrowsingUrlCheckerImpl::OnTimeout);
+
+ bool safe_synchronously;
+ auto* rt_lookup_service = database_manager_->GetRealTimeUrlLookupService();
+ if (RealTimePolicyEngine::CanPerformFullURLLookupForResourceType(
+ resource_type_) &&
+ rt_lookup_service && rt_lookup_service->CanCheckUrl(url) &&
+ !rt_lookup_service->IsInBackoffMode()) {
+ UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.RT.ResourceTypes.Checked",
+ resource_type_);
+ safe_synchronously = false;
+ AsyncMatch match =
+ database_manager_->CheckUrlForHighConfidenceAllowlist(url, this);
+ switch (match) {
+ case AsyncMatch::ASYNC:
+ // Hash-prefix matched. A call to
+ // |OnCheckUrlForHighConfidenceAllowlist| will follow.
+ break;
+ case AsyncMatch::MATCH:
+ // Full-hash matched locally so queue a call to
+ // |OnCheckUrlForHighConfidenceAllowlist| to trigger the hash-based
+ // checking.
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&SafeBrowsingUrlCheckerImpl::
+ OnCheckUrlForHighConfidenceAllowlist,
+ weak_factory_.GetWeakPtr(),
+ /*did_match_allowlist=*/true));
+ break;
+ case AsyncMatch::NO_MATCH:
+ // No match found locally. Queue the call to
+ // |OnCheckUrlForHighConfidenceAllowlist| to perform the full URL
+ // lookup.
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&SafeBrowsingUrlCheckerImpl::
+ OnCheckUrlForHighConfidenceAllowlist,
+ weak_factory_.GetWeakPtr(),
+ /*did_match_allowlist=*/false));
+ break;
+ }
+ } else {
+ safe_synchronously = database_manager_->CheckBrowseUrl(
+ url, url_checker_delegate_->GetThreatTypes(), this);
+ }
+
+ if (safe_synchronously) {
+ timer_.Stop();
+ RecordCheckUrlTimeout(/*timed_out=*/false);
+
if (!RunNextCallback(true, false))
return;
@@ -280,14 +349,6 @@ void SafeBrowsingUrlCheckerImpl::ProcessUrls() {
if (!database_manager_->ChecksAreAlwaysAsync())
urls_[next_index_].notifier.OnStartSlowCheck();
- TRACE_EVENT_ASYNC_BEGIN1("safe_browsing", "CheckUrl", this, "url",
- url.spec());
-
- // Start a timer to abort the check if it takes too long.
- timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), this,
- &SafeBrowsingUrlCheckerImpl::OnCheckUrlTimeout);
-
break;
}
}
@@ -340,4 +401,46 @@ bool SafeBrowsingUrlCheckerImpl::RunNextCallback(bool proceed,
return !!weak_self;
}
+void SafeBrowsingUrlCheckerImpl::OnCheckUrlForHighConfidenceAllowlist(
+ bool did_match_allowlist) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_EQ(content::ResourceType::kMainFrame, resource_type_);
+
+ const GURL& url = urls_[next_index_].url;
+ if (did_match_allowlist) {
+ // If the URL matches the high-confidence allowlist, still do the hash based
+ // checks.
+ if (database_manager_->CheckBrowseUrl(
+ url, url_checker_delegate_->GetThreatTypes(), this)) {
+ // No match found in the local database. Safe to call |OnUrlResult| here
+ // directly.
+ OnUrlResult(url, SB_THREAT_TYPE_SAFE, ThreatMetadata());
+ }
+ return;
+ }
+
+ RTLookupResponseCallback result_callback =
+ base::Bind(&SafeBrowsingUrlCheckerImpl::OnRTLookupResponse,
+ weak_factory_.GetWeakPtr());
+ auto* rt_lookup_service = database_manager_->GetRealTimeUrlLookupService();
+ rt_lookup_service->StartLookup(url, std::move(result_callback));
+}
+
+void SafeBrowsingUrlCheckerImpl::OnRTLookupResponse(
+ std::unique_ptr<RTLookupResponse> response) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK_EQ(content::ResourceType::kMainFrame, resource_type_);
+
+ const GURL& url = urls_[next_index_].url;
+ if (response && (response->threat_info_size() > 0) &&
+ (response->threat_info(0).verdict_type() ==
+ RTLookupResponse::ThreatInfo::DANGEROUS)) {
+ OnUrlResult(url, SB_THREAT_TYPE_URL_PHISHING, ThreatMetadata());
+ } else {
+ OnUrlResult(url, SB_THREAT_TYPE_SAFE, ThreatMetadata());
+ }
+
+ // TODO(vakh): Log |response| to chrome://safe-browsing
+}
+
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.h b/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.h
index 88eb597d6d7..7947abf910f 100644
--- a/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.h
+++ b/chromium/components/safe_browsing/browser/safe_browsing_url_checker_impl.h
@@ -13,6 +13,7 @@
#include "base/timer/timer.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "components/safe_browsing/db/database_manager.h"
+#include "components/safe_browsing/proto/realtimeapi.pb.h"
#include "content/public/common/resource_type.h"
#include "net/http/http_request_headers.h"
#include "url/gurl.h"
@@ -108,7 +109,13 @@ class SafeBrowsingUrlCheckerImpl : public mojom::SafeBrowsingUrlChecker,
SBThreatType threat_type,
const ThreatMetadata& metadata) override;
- void OnCheckUrlTimeout();
+ void OnCheckUrlForHighConfidenceAllowlist(bool did_match_allowlist) override;
+
+ void OnTimeout();
+
+ void OnUrlResult(const GURL& url,
+ SBThreatType threat_type,
+ const ThreatMetadata& metadata);
void CheckUrlImpl(const GURL& url,
const std::string& method,
@@ -128,6 +135,9 @@ class SafeBrowsingUrlCheckerImpl : public mojom::SafeBrowsingUrlChecker,
// case none of the members of this object should be touched again.
bool RunNextCallback(bool proceed, bool showed_interstitial);
+ // Called when the |response| from the real-time lookup service is received.
+ void OnRTLookupResponse(std::unique_ptr<RTLookupResponse> response);
+
enum State {
// Haven't started checking or checking is complete.
STATE_NONE,
diff --git a/chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc b/chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc
deleted file mode 100644
index e8f85713e45..00000000000
--- a/chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/safe_browsing/browser/safe_browsing_url_request_context_getter.h"
-
-#include "base/single_thread_task_runner.h"
-#include "base/task/post_task.h"
-#include "components/safe_browsing/common/safebrowsing_constants.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/cookie_store_factory.h"
-#include "net/cookies/cookie_store.h"
-#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
-#include "net/http/http_network_layer.h"
-#include "net/http/http_transaction_factory.h"
-#include "net/url_request/url_request_context.h"
-
-using content::BrowserThread;
-
-namespace safe_browsing {
-
-SafeBrowsingURLRequestContextGetter::SafeBrowsingURLRequestContextGetter(
- scoped_refptr<net::URLRequestContextGetter> system_context_getter,
- const base::FilePath& user_data_dir)
- : shut_down_(false),
- user_data_dir_(user_data_dir),
- system_context_getter_(system_context_getter),
- network_task_runner_(
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})) {
- DCHECK(!user_data_dir.empty());
- DCHECK(system_context_getter_);
-}
-
-net::URLRequestContext*
-SafeBrowsingURLRequestContextGetter::GetURLRequestContext() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Check if the service has been shut down.
- if (shut_down_)
- return nullptr;
-
- if (!safe_browsing_request_context_) {
- safe_browsing_request_context_.reset(new net::URLRequestContext());
- safe_browsing_request_context_->CopyFrom(
- system_context_getter_->GetURLRequestContext());
- scoped_refptr<base::SequencedTaskRunner> background_task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), net::GetCookieStoreBackgroundSequencePriority(),
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-
- // Set up the CookieStore
- content::CookieStoreConfig cookie_config(CookieFilePath(), false, false,
- nullptr);
- cookie_config.background_task_runner = background_task_runner;
- safe_browsing_cookie_store_ =
- content::CreateCookieStore(cookie_config, nullptr /* netlog */);
- safe_browsing_request_context_->set_cookie_store(
- safe_browsing_cookie_store_.get());
-
- safe_browsing_request_context_->set_name("safe_browsing");
- }
-
- return safe_browsing_request_context_.get();
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-SafeBrowsingURLRequestContextGetter::GetNetworkTaskRunner() const {
- return network_task_runner_;
-}
-
-void SafeBrowsingURLRequestContextGetter::ServiceShuttingDown() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- shut_down_ = true;
- URLRequestContextGetter::NotifyContextShuttingDown();
- safe_browsing_request_context_.reset();
-}
-
-void SafeBrowsingURLRequestContextGetter::DisableQuicOnIOThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // |http_network_session_| is only initialized once GetURLRequestContext() is
- // (lazily) called. With most consumers shifting to use
- // SafeBrowsingNetworkContext instead of this class directly, now on startup
- // GetURLRequestContext() might not have been called yet. So expliclity call
- // it to make sure http_network_session_ is initialized. Don't call it though
- // if shutdown has already started.
- if (!http_network_session_ && !shut_down_)
- GetURLRequestContext();
-
- if (http_network_session_)
- http_network_session_->DisableQuic();
-}
-
-base::FilePath SafeBrowsingURLRequestContextGetter::GetBaseFilename() {
- base::FilePath path(user_data_dir_);
- return path.Append(kSafeBrowsingBaseFilename);
-}
-
-base::FilePath SafeBrowsingURLRequestContextGetter::CookieFilePath() {
- return base::FilePath(GetBaseFilename().value() + kCookiesFile);
-}
-
-SafeBrowsingURLRequestContextGetter::~SafeBrowsingURLRequestContextGetter() {}
-
-} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.h b/chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.h
deleted file mode 100644
index 9cc6a5076bc..00000000000
--- a/chromium/components/safe_browsing/browser/safe_browsing_url_request_context_getter.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SAFE_BROWSING_BROWSER_SAFE_BROWSING_URL_REQUEST_CONTEXT_GETTER_H_
-#define COMPONENTS_SAFE_BROWSING_BROWSER_SAFE_BROWSING_URL_REQUEST_CONTEXT_GETTER_H_
-
-#include "base/files/file_path.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace net {
-class CookieStore;
-class HttpNetworkSession;
-class HttpTransactionFactory;
-class URLRequestContext;
-}
-
-namespace safe_browsing {
-
-class SafeBrowsingURLRequestContextGetter
- : public net::URLRequestContextGetter {
- public:
- explicit SafeBrowsingURLRequestContextGetter(
- scoped_refptr<net::URLRequestContextGetter> system_context_getter,
- const base::FilePath& user_data_dir);
-
- // Implementation for net::UrlRequestContextGetter.
- net::URLRequestContext* GetURLRequestContext() override;
- scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
- const override;
-
- // Shuts down any pending requests using the getter, and sets |shut_down_| to
- // true.
- void ServiceShuttingDown();
-
- // Disables QUIC. This should not be necessary anymore when
- // http://crbug.com/678653 is implemented.
- void DisableQuicOnIOThread();
-
- protected:
- ~SafeBrowsingURLRequestContextGetter() override;
-
- private:
- base::FilePath GetBaseFilename();
- base::FilePath CookieFilePath();
-
- bool shut_down_;
- base::FilePath user_data_dir_;
-
- scoped_refptr<net::URLRequestContextGetter> system_context_getter_;
- scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
- std::unique_ptr<net::URLRequestContext> safe_browsing_request_context_;
- std::unique_ptr<net::CookieStore> safe_browsing_cookie_store_;
- std::unique_ptr<net::HttpNetworkSession> http_network_session_;
- std::unique_ptr<net::HttpTransactionFactory> http_transaction_factory_;
-};
-
-} // namespace safe_browsing
-
-#endif // COMPONENTS_SAFE_BROWSING_BROWSER_SAFE_BROWSING_URL_REQUEST_CONTEXT_GETTER_H_
diff --git a/chromium/components/safe_browsing/browser/threat_details.cc b/chromium/components/safe_browsing/browser/threat_details.cc
index 1c85e99bcb5..1d71139c461 100644
--- a/chromium/components/safe_browsing/browser/threat_details.cc
+++ b/chromium/components/safe_browsing/browser/threat_details.cc
@@ -99,7 +99,8 @@ ClientSafeBrowsingReportRequest::ReportType GetReportTypeFromSBThreatType(
return ClientSafeBrowsingReportRequest::AD_SAMPLE;
case SB_THREAT_TYPE_BLOCKED_AD_REDIRECT:
return ClientSafeBrowsingReportRequest::BLOCKED_AD_REDIRECT;
- case SB_THREAT_TYPE_SIGN_IN_PASSWORD_REUSE:
+ case SB_THREAT_TYPE_SIGNED_IN_SYNC_PASSWORD_REUSE:
+ case SB_THREAT_TYPE_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
case SB_THREAT_TYPE_ENTERPRISE_PASSWORD_REUSE:
return ClientSafeBrowsingReportRequest::URL_PASSWORD_PROTECTION_PHISHING;
case SB_THREAT_TYPE_SUSPICIOUS_SITE:
@@ -381,7 +382,6 @@ ThreatDetails::ThreatDetails(
cache_result_(false),
did_proceed_(false),
num_visits_(0),
- ambiguous_dom_(false),
trim_to_ad_tags_(trim_to_ad_tags),
cache_collector_(new ThreatDetailsCacheCollector),
done_callback_(done_callback),
@@ -398,7 +398,6 @@ ThreatDetails::ThreatDetails()
: cache_result_(false),
did_proceed_(false),
num_visits_(0),
- ambiguous_dom_(false),
trim_to_ad_tags_(false),
all_done_expected_(false),
is_all_done_(false) {}
@@ -676,10 +675,8 @@ void ThreatDetails::OnReceivedThreatDOMDetails(
int child_frame_tree_node_id =
content::RenderFrameHost::GetFrameTreeNodeIdForRoutingId(
sender_process_id, node->child_frame_routing_id);
- if (child_frame_tree_node_id ==
+ if (child_frame_tree_node_id !=
content::RenderFrameHost::kNoFrameTreeNodeId) {
- ambiguous_dom_ = true;
- } else {
child_frame_tree_map[cur_element_key] = child_frame_tree_node_id;
}
}
@@ -822,12 +819,6 @@ void ThreatDetails::OnCacheCollectionReady() {
for (auto& element_pair : elements_) {
report_->add_dom()->Swap(element_pair.second.get());
}
- if (!elements_.empty()) {
- // TODO(lpz): Consider including the ambiguous_dom_ bit in the report
- // itself.
- UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.ThreatReport.DomIsAmbiguous",
- ambiguous_dom_);
- }
report_->set_did_proceed(did_proceed_);
// Only sets repeat_visit if num_visits_ >= 0.
@@ -850,7 +841,7 @@ void ThreatDetails::OnCacheCollectionReady() {
return;
}
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&WebUIInfoSingleton::AddToCSBRRsSent,
base::Unretained(WebUIInfoSingleton::GetInstance()),
@@ -878,7 +869,7 @@ void ThreatDetails::MaybeFillReferrerChain() {
void ThreatDetails::AllDone() {
is_all_done_ = true;
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(done_callback_, base::Unretained(web_contents())));
}
diff --git a/chromium/components/safe_browsing/browser/threat_details.h b/chromium/components/safe_browsing/browser/threat_details.h
index 76ae1c01b18..0a77f7630cd 100644
--- a/chromium/components/safe_browsing/browser/threat_details.h
+++ b/chromium/components/safe_browsing/browser/threat_details.h
@@ -233,11 +233,6 @@ class ThreatDetails : public content::WebContentsObserver {
// How many times this user has visited this page before.
int num_visits_;
- // Keeps track of whether we have an ambiguous DOM in this report. This can
- // happen when the HTML Elements returned by a renderer can't be
- // associated with a parent Element in the parent frame.
- bool ambiguous_dom_;
-
// Whether this report should be trimmed down to only ad tags, not the entire
// page contents. Used for sampling ads.
bool trim_to_ad_tags_;
diff --git a/chromium/components/safe_browsing/browser/threat_details_cache.cc b/chromium/components/safe_browsing/browser/threat_details_cache.cc
index cdd908494c5..0abc641a88f 100644
--- a/chromium/components/safe_browsing/browser/threat_details_cache.cc
+++ b/chromium/components/safe_browsing/browser/threat_details_cache.cc
@@ -52,9 +52,8 @@ void ThreatDetailsCacheCollector::StartCacheCollection(
// Post a task in the message loop, so the callers don't need to
// check if we call their callback immediately.
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&ThreatDetailsCacheCollector::OpenEntry, this));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&ThreatDetailsCacheCollector::OpenEntry, this));
}
bool ThreatDetailsCacheCollector::HasStarted() {
@@ -228,16 +227,15 @@ void ThreatDetailsCacheCollector::AdvanceEntry() {
current_load_.reset();
// Create a task so we don't take over the UI thread for too long.
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&ThreatDetailsCacheCollector::OpenEntry, this));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&ThreatDetailsCacheCollector::OpenEntry, this));
}
void ThreatDetailsCacheCollector::AllDone(bool success) {
DVLOG(1) << "AllDone";
DCHECK_CURRENTLY_ON(BrowserThread::UI);
*result_ = success;
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback_);
+ base::PostTask(FROM_HERE, {BrowserThread::UI}, callback_);
callback_.Reset();
}
diff --git a/chromium/components/safe_browsing/browser/threat_details_history.cc b/chromium/components/safe_browsing/browser/threat_details_history.cc
index 1381c2a0c0d..3ea0e17e568 100644
--- a/chromium/components/safe_browsing/browser/threat_details_history.cc
+++ b/chromium/components/safe_browsing/browser/threat_details_history.cc
@@ -46,7 +46,7 @@ void ThreatDetailsRedirectsCollector::StartHistoryCollection(
return;
}
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&ThreatDetailsRedirectsCollector::StartGetRedirects, this,
urls));
@@ -112,7 +112,7 @@ void ThreatDetailsRedirectsCollector::OnGotQueryRedirectsTo(
void ThreatDetailsRedirectsCollector::AllDone() {
DVLOG(1) << "AllDone";
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback_);
+ base::PostTask(FROM_HERE, {BrowserThread::UI}, callback_);
callback_.Reset();
}
diff --git a/chromium/components/safe_browsing/buildflags.gni b/chromium/components/safe_browsing/buildflags.gni
new file mode 100644
index 00000000000..fba0e03cd92
--- /dev/null
+++ b/chromium/components/safe_browsing/buildflags.gni
@@ -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.
+
+import("//build/config/chromecast_build.gni")
+if (is_android) {
+ import("//build/config/android/config.gni")
+}
+
+declare_args() {
+ # Variable safe_browsing is used to control the build time configuration for
+ # safe browsing feature. Safe browsing can be compiled in 3 different levels:
+ # 0 disables it, 1 enables it fully, 2 enables mobile protection via an
+ # external API, and 3 enables mobile protection via internal API.
+ if (is_ios || is_chromecast) {
+ safe_browsing_mode = 0
+ } else if (is_android) {
+ if (notouch_build) {
+ safe_browsing_mode = 3
+ } else {
+ safe_browsing_mode = 2
+ }
+ } else {
+ safe_browsing_mode = 1
+ }
+}
diff --git a/chromium/components/safe_browsing/common/BUILD.gn b/chromium/components/safe_browsing/common/BUILD.gn
index 21079fab0d9..6ebbdd1b422 100644
--- a/chromium/components/safe_browsing/common/BUILD.gn
+++ b/chromium/components/safe_browsing/common/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/features.gni")
+import("//components/safe_browsing/buildflags.gni")
import("//mojo/public/tools/bindings/mojom.gni")
source_set("common") {
diff --git a/chromium/components/safe_browsing/common/safe_browsing_prefs.cc b/chromium/components/safe_browsing/common/safe_browsing_prefs.cc
index a3607c3b7cf..01c693b71c9 100644
--- a/chromium/components/safe_browsing/common/safe_browsing_prefs.cc
+++ b/chromium/components/safe_browsing/common/safe_browsing_prefs.cc
@@ -92,7 +92,7 @@ const char kSafeBrowsingScoutReportingEnabled[] =
"safebrowsing.scout_reporting_enabled";
const char kSafeBrowsingTriggerEventTimestamps[] =
"safebrowsing.trigger_event_timestamps";
-const char kSafeBrowsingUnhandledSyncPasswordReuses[] =
+const char kSafeBrowsingUnhandledGaiaPasswordReuses[] =
"safebrowsing.unhandled_sync_password_reuses";
const char kSafeBrowsingNextPasswordCaptureEventLogTime[] =
"safebrowsing.next_password_capture_event_log_time";
@@ -106,10 +106,24 @@ const char kPasswordProtectionWarningTrigger[] =
"safebrowsing.password_protection_warning_trigger";
const char kAdvancedProtectionLastRefreshInUs[] =
"safebrowsing.advanced_protection_last_refresh";
-const char kPasswordProtectedAllowed[] =
- "safebrowsing.password_protected_allowed";
const char kSafeBrowsingRealTimeLookupEnabled[] =
"safebrowsing.real_time_lookup_enabled";
+const char kSafeBrowsingSendFilesForMalwareCheck[] =
+ "safebrowsing.send_files_for_malware_check";
+const char kUnsafeEventsReportingEnabled[] =
+ "safebrowsing.unsafe_events_reporting";
+const char kBlockLargeFileTransfer[] =
+ "safebrowsing.block_large_file_transfers";
+const char kDelayDeliveryUntilVerdict[] =
+ "safebrowsing.delay_delivery_until_verdict";
+const char kAllowPasswordProtectedFiles[] =
+ "safebrowsing.allow_password_protected_files";
+const char kCheckContentCompliance[] = "safebrowsing.check_content_compliance";
+const char kDomainsToCheckComplianceOfDownloadedContent[] =
+ "safebrowsing.domains_to_check_compliance_of_downloaded_content";
+const char kDomainsToCheckForMalwareOfUploadedContent[] =
+ "safebrowsing.domains_to_check_for_malware_of_uploaded_content";
+
} // namespace prefs
namespace safe_browsing {
@@ -161,7 +175,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
false);
registry->RegisterDictionaryPref(prefs::kSafeBrowsingIncidentsSent);
registry->RegisterDictionaryPref(
- prefs::kSafeBrowsingUnhandledSyncPasswordReuses);
+ prefs::kSafeBrowsingUnhandledGaiaPasswordReuses);
registry->RegisterStringPref(
prefs::kSafeBrowsingNextPasswordCaptureEventLogTime,
"0"); // int64 as string
@@ -171,13 +185,23 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(prefs::kPasswordProtectionWarningTrigger,
PASSWORD_PROTECTION_OFF);
registry->RegisterInt64Pref(prefs::kAdvancedProtectionLastRefreshInUs, 0);
- registry->RegisterBooleanPref(prefs::kPasswordProtectedAllowed, true);
registry->RegisterBooleanPref(prefs::kSafeBrowsingRealTimeLookupEnabled,
false);
+ registry->RegisterIntegerPref(prefs::kSafeBrowsingSendFilesForMalwareCheck,
+ 0);
}
void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kSafeBrowsingTriggerEventTimestamps);
+ registry->RegisterBooleanPref(prefs::kUnsafeEventsReportingEnabled, false);
+ registry->RegisterIntegerPref(prefs::kBlockLargeFileTransfer, 0);
+ registry->RegisterIntegerPref(prefs::kDelayDeliveryUntilVerdict, 0);
+ registry->RegisterIntegerPref(
+ prefs::kAllowPasswordProtectedFiles,
+ AllowPasswordProtectedFilesValues::ALLOW_UPLOADS_AND_DOWNLOADS);
+ registry->RegisterIntegerPref(prefs::kCheckContentCompliance, 0);
+ registry->RegisterListPref(
+ prefs::kDomainsToCheckComplianceOfDownloadedContent);
}
void SetExtendedReportingPrefAndMetric(
diff --git a/chromium/components/safe_browsing/common/safe_browsing_prefs.h b/chromium/components/safe_browsing/common/safe_browsing_prefs.h
index c1b5d512fa0..4b27073286c 100644
--- a/chromium/components/safe_browsing/common/safe_browsing_prefs.h
+++ b/chromium/components/safe_browsing/common/safe_browsing_prefs.h
@@ -46,11 +46,11 @@ extern const char kSafeBrowsingScoutReportingEnabled[];
// lists of doubles.
extern const char kSafeBrowsingTriggerEventTimestamps[];
-// Dictionary that records the origin and navigation ID pairs of unhandled sync
+// Dictionary that records the origin and navigation ID pairs of unhandled gaia
// password reuses. The keys are origin strings and the ID values are 8-byte
-// ints. Only set/update if a Chrome Sync user reuses their Gaia password on
+// ints. Only set/update if a Chrome user reuses their Gaia password on a
// phishing site.
-extern const char kSafeBrowsingUnhandledSyncPasswordReuses[];
+extern const char kSafeBrowsingUnhandledGaiaPasswordReuses[];
// Integer timestamp of next time the PasswordCaptured event should be logged.
extern const char kSafeBrowsingNextPasswordCaptureEventLogTime[];
@@ -81,13 +81,39 @@ extern const char kPasswordProtectionWarningTrigger[];
// microseconds);
extern const char kAdvancedProtectionLastRefreshInUs[];
-// Whether or not to allow downloads of password-protected files.
-extern const char kPasswordProtectedAllowed[];
-
// Whether or not to check URLs in real time. This is configured by enterprise
// policy. For consumers, this pref is irrelevant.
extern const char kSafeBrowsingRealTimeLookupEnabled[];
-}
+
+// Whether or not to send downloads to Safe Browsing for deep scanning. This
+// is configured by enterprise policy.
+extern const char kSafeBrowsingSendFilesForMalwareCheck[];
+
+// Boolean that indidicates if Chrome reports unsafe events to Google.
+extern const char kUnsafeEventsReportingEnabled[];
+
+// Integer that specifies if large files are blocked form either uploads or
+// downloads or both.
+extern const char kBlockLargeFileTransfer[];
+
+// Integer that specifies if delivery to the user of potentially unsafe data
+// is delayed until a verdict about the data is known.
+extern const char kDelayDeliveryUntilVerdict[];
+
+// Integer that specifies if password protected files can be either uploaded
+// or downloaded or both.
+extern const char kAllowPasswordProtectedFiles[];
+
+// Integer that indidicates if Chrome checks data for content compliance.
+extern const char kCheckContentCompliance[];
+
+// List of domains where Chrome should check compliance of downloaded files.
+extern const char kDomainsToCheckComplianceOfDownloadedContent[];
+
+// List of domains where Chrome should check for malware of uploaded files.
+extern const char kDomainsToCheckForMalwareOfUploadedContent[];
+
+} // namespace prefs
namespace safe_browsing {
@@ -134,6 +160,47 @@ enum PasswordProtectionTrigger {
PASSWORD_PROTECTION_TRIGGER_MAX,
};
+// Enum representing possible values of the SendFilesForMalwareCheck policy.
+// This must be kept in sync with policy_templates.json
+enum SendFilesForMalwareCheckValues {
+ DO_NOT_SCAN = 0,
+ SEND_FILES_DISABLED = 1,
+ SEND_DOWNLOADS = 2,
+ SEND_UPLOADS = 3,
+ SEND_UPLOADS_AND_DOWNLOADS = 4,
+ // New options must be added before SEND_FILES_FOR_MALWARE_CHECK_MAX.
+ SEND_FILES_FOR_MALWARE_CHECK_MAX = SEND_UPLOADS_AND_DOWNLOADS,
+};
+
+// Enum representing possible values of the CheckContentCompliance policy. This
+// must be kept in sync with policy_templates.json
+enum CheckContentComplianceValues {
+ CHECK_NONE = 0,
+ CHECK_DOWNLOADS = 1,
+ CHECK_UPLOADS = 2,
+ CHECK_UPLOADS_AND_DOWNLOADS = 3,
+ // New options must be added before CHECK_CONTENT_COMPLIANCE_MAX.
+ CHECK_CONTENT_COMPLIANCE_MAX = CHECK_UPLOADS_AND_DOWNLOADS,
+};
+
+// Enum representing possible values of the AllowPasswordProtectedFiles policy.
+// This must be kept in sync with policy_templates.json
+enum AllowPasswordProtectedFilesValues {
+ ALLOW_NONE = 0,
+ ALLOW_DOWNLOADS = 1,
+ ALLOW_UPLOADS = 2,
+ ALLOW_UPLOADS_AND_DOWNLOADS = 3,
+};
+
+// Enum representing possible values of the BlockLargeFileTransfer policy. This
+// must be kept in sync with policy_templates.json
+enum BlockLargeFileTransferValues {
+ BLOCK_NONE = 0,
+ BLOCK_LARGE_DOWNLOADS = 1,
+ BLOCK_LARGE_UPLOADS = 2,
+ BLOCK_LARGE_UPLOADS_AND_DOWNLOADS = 3,
+};
+
// Returns whether the currently active Safe Browsing Extended Reporting
// preference exists (eg: has been set before).
bool ExtendedReportingPrefExists(const PrefService& prefs);
diff --git a/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc b/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc
index 0e00ab16548..760d640bd08 100644
--- a/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc
+++ b/chromium/components/safe_browsing/common/safe_browsing_prefs_unittest.cc
@@ -14,7 +14,7 @@
#include "components/prefs/testing_pref_service.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/features.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -54,7 +54,7 @@ class SafeBrowsingPrefsTest : public ::testing::Test {
TestingPrefServiceSimple prefs_;
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
};
// TODO(crbug.com/881476) disabled for flaky crashes.
diff --git a/chromium/components/safe_browsing/db/BUILD.gn b/chromium/components/safe_browsing/db/BUILD.gn
index 5e5b0eea85e..e634e7215d5 100644
--- a/chromium/components/safe_browsing/db/BUILD.gn
+++ b/chromium/components/safe_browsing/db/BUILD.gn
@@ -167,8 +167,10 @@ static_library("v4_local_database_manager") {
":v4_protocol_manager_util",
":v4_update_protocol_manager",
"//base",
+ "//build:branding_buildflags",
"//components/safe_browsing:webui_proto",
"//components/safe_browsing/realtime:policy_engine",
+ "//components/safe_browsing/realtime:url_lookup_service",
"//content/public/browser",
"//crypto",
"//net",
@@ -273,6 +275,7 @@ static_library("v4_update_protocol_manager") {
":util",
":v4_protocol_manager_util",
"//base",
+ "//components/safe_browsing:buildflags",
"//components/safe_browsing:webui_proto",
"//components/safe_browsing/common:safe_browsing_prefs",
"//net",
@@ -281,84 +284,6 @@ static_library("v4_update_protocol_manager") {
]
}
-source_set("v4_database_unittest") {
- testonly = true
- sources = [
- "v4_database_unittest.cc",
- ]
- deps = [
- ":v4_database",
- ":v4_store",
- "//base",
- "//base/test:test_support",
- "//content/test:test_support",
- "//testing/gtest",
- ]
-}
-
-source_set("v4_get_hash_protocol_manager_unittest") {
- testonly = true
- sources = [
- "v4_get_hash_protocol_manager_unittest.cc",
- ]
- deps = [
- ":safebrowsing_proto",
- ":util",
- ":v4_database",
- ":v4_get_hash_protocol_manager",
- ":v4_local_database_manager",
- ":v4_test_util",
- "//base",
- "//base/test:test_support",
- "//content/test:test_support",
- "//net",
- "//net:test_support",
- "//services/network:test_support",
- "//testing/gtest",
- ]
-}
-
-source_set("v4_local_database_manager_unittest") {
- testonly = true
- sources = [
- "v4_local_database_manager_unittest.cc",
- ]
- deps = [
- ":v4_database",
- ":v4_local_database_manager",
- ":v4_protocol_manager_util",
- ":v4_test_util",
- "//base",
- "//base/test:test_support",
- "//components/safe_browsing:features",
- "//content/test:test_support",
- "//net",
- "//net:test_support",
- "//services/network:test_support",
- "//testing/gtest",
- ]
-}
-
-source_set("v4_update_protocol_manager_unittest") {
- testonly = true
- sources = [
- "v4_update_protocol_manager_unittest.cc",
- ]
- deps = [
- ":safebrowsing_proto",
- ":util",
- ":v4_test_util",
- ":v4_update_protocol_manager",
- "//base",
- "//base/test:test_support",
- "//content/public/common",
- "//net",
- "//net:test_support",
- "//services/network:test_support",
- "//testing/gtest",
- ]
-}
-
source_set("unit_tests_shared") {
testonly = true
sources = [
@@ -413,6 +338,7 @@ source_set("unit_tests_desktop") {
":v4_update_protocol_manager",
"//base",
"//components/prefs:test_support",
+ "//components/safe_browsing:buildflags",
"//components/safe_browsing:features",
"//components/safe_browsing/common:safe_browsing_prefs",
"//content/test:test_support",
@@ -443,24 +369,6 @@ static_library("allowlist_checker_client") {
]
}
-source_set("allowlist_checker_client_unittest") {
- testonly = true
- sources = [
- "allowlist_checker_client_unittest.cc",
- ]
- deps = [
- ":allowlist_checker_client",
- ":database_manager",
- ":test_database_manager",
- "//base:base",
- "//base/test:test_support",
- "//content/public/browser",
- "//content/test:test_support",
- "//testing/gmock:gmock",
- "//testing/gtest:gtest",
- ]
-}
-
fuzzer_test("v4_get_hash_protocol_manager_fuzzer") {
sources = [
"v4_get_hash_protocol_manager_fuzzer.cc",
diff --git a/chromium/components/safe_browsing/db/allowlist_checker_client_unittest.cc b/chromium/components/safe_browsing/db/allowlist_checker_client_unittest.cc
index 37e273713f8..e49c83719f0 100644
--- a/chromium/components/safe_browsing/db/allowlist_checker_client_unittest.cc
+++ b/chromium/components/safe_browsing/db/allowlist_checker_client_unittest.cc
@@ -8,11 +8,11 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/safe_browsing/db/test_database_manager.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -50,8 +50,7 @@ class MockSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager {
class AllowlistCheckerClientTest : public testing::Test {
public:
AllowlistCheckerClientTest()
- : thread_bundle_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
target_url_("https://example.test") {}
void SetUp() override {
@@ -63,11 +62,11 @@ class AllowlistCheckerClientTest : public testing::Test {
base::RunLoop().RunUntilIdle();
// Verify no callback is remaining.
- EXPECT_TRUE(thread_bundle_.MainThreadIsIdle());
+ EXPECT_TRUE(task_environment_.MainThreadIsIdle());
}
protected:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
GURL target_url_;
scoped_refptr<MockSafeBrowsingDatabaseManager> database_manager_;
@@ -76,7 +75,6 @@ class AllowlistCheckerClientTest : public testing::Test {
TEST_F(AllowlistCheckerClientTest, TestCsdListMatch) {
EXPECT_CALL(*database_manager_, CheckCsdWhitelistUrl(target_url_, _))
.WillOnce(Return(AsyncMatch::MATCH));
-
MockBoolCallback callback;
EXPECT_CALL(callback, Run(true /* did_match_allowlist */));
AllowlistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_,
@@ -86,7 +84,6 @@ TEST_F(AllowlistCheckerClientTest, TestCsdListMatch) {
TEST_F(AllowlistCheckerClientTest, TestCsdListNoMatch) {
EXPECT_CALL(*database_manager_, CheckCsdWhitelistUrl(target_url_, _))
.WillOnce(Return(AsyncMatch::NO_MATCH));
-
MockBoolCallback callback;
EXPECT_CALL(callback, Run(false /* did_match_allowlist */));
AllowlistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_,
@@ -117,11 +114,11 @@ TEST_F(AllowlistCheckerClientTest, TestCsdListAsyncTimeout) {
MockBoolCallback callback;
AllowlistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_,
callback.Get());
- thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
// No callback yet.
EXPECT_CALL(callback, Run(true /* did_match_allowlist */));
- thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
}
TEST_F(AllowlistCheckerClientTest, TestHighConfidenceListMatch) {
@@ -172,11 +169,11 @@ TEST_F(AllowlistCheckerClientTest, TestHighConfidenceListAsyncTimeout) {
MockBoolCallback callback;
AllowlistCheckerClient::StartCheckHighConfidenceAllowlist(
database_manager_, target_url_, callback.Get());
- thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
// No callback yet.
EXPECT_CALL(callback, Run(false /* did_match_allowlist */));
- thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
}
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/db/database_manager.cc b/chromium/components/safe_browsing/db/database_manager.cc
index 966ea6c6529..324cc288506 100644
--- a/chromium/components/safe_browsing/db/database_manager.cc
+++ b/chromium/components/safe_browsing/db/database_manager.cc
@@ -23,8 +23,7 @@ namespace safe_browsing {
SafeBrowsingDatabaseManager::SafeBrowsingDatabaseManager()
: base::RefCountedDeleteOnSequence<SafeBrowsingDatabaseManager>(
- base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::IO})),
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})),
enabled_(false) {}
SafeBrowsingDatabaseManager::~SafeBrowsingDatabaseManager() {
@@ -142,6 +141,11 @@ void SafeBrowsingDatabaseManager::StopOnIOThread(bool shutdown) {
v4_get_hash_protocol_manager_.reset();
}
+RealTimeUrlLookupService*
+SafeBrowsingDatabaseManager::GetRealTimeUrlLookupService() {
+ return nullptr;
+}
+
std::unique_ptr<base::CallbackList<void()>::Subscription>
SafeBrowsingDatabaseManager::RegisterDatabaseUpdatedCallback(
const OnDatabaseUpdated& cb) {
diff --git a/chromium/components/safe_browsing/db/database_manager.h b/chromium/components/safe_browsing/db/database_manager.h
index 061e7d69368..7f294698702 100644
--- a/chromium/components/safe_browsing/db/database_manager.h
+++ b/chromium/components/safe_browsing/db/database_manager.h
@@ -30,6 +30,8 @@ class SharedURLLoaderFactory;
namespace safe_browsing {
+class RealTimeUrlLookupService;
+
// Value returned by some functions that check an allowlist and may or may not
// have an immediate answer.
enum class AsyncMatch : int {
@@ -263,6 +265,8 @@ class SafeBrowsingDatabaseManager
// method at the bottom of it.
virtual void StopOnIOThread(bool shutdown);
+ virtual RealTimeUrlLookupService* GetRealTimeUrlLookupService();
+
protected:
// Bundled client info for an API abuse hash prefix check.
class SafeBrowsingApiCheck {
diff --git a/chromium/components/safe_browsing/db/database_manager_unittest.cc b/chromium/components/safe_browsing/db/database_manager_unittest.cc
index 01ef6b0eaaa..a10ba0f4d2c 100644
--- a/chromium/components/safe_browsing/db/database_manager_unittest.cc
+++ b/chromium/components/safe_browsing/db/database_manager_unittest.cc
@@ -23,7 +23,7 @@
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/db/v4_test_util.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "crypto/sha2.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -112,7 +112,7 @@ class SafeBrowsingDatabaseManagerTest : public testing::Test {
scoped_refptr<SafeBrowsingDatabaseManager> db_manager_;
private:
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
};
TEST_F(SafeBrowsingDatabaseManagerTest, CheckApiBlacklistUrlWrongScheme) {
diff --git a/chromium/components/safe_browsing/db/v4_database_unittest.cc b/chromium/components/safe_browsing/db/v4_database_unittest.cc
index 67c7fcaf7e1..821d1b04374 100644
--- a/chromium/components/safe_browsing/db/v4_database_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_database_unittest.cc
@@ -12,7 +12,7 @@
#include "base/test/test_simple_task_runner.h"
#include "components/safe_browsing/db/v4_database.h"
#include "components/safe_browsing/db/v4_store.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/platform_test.h"
namespace safe_browsing {
@@ -201,7 +201,7 @@ class V4DatabaseTest : public PlatformTest {
std::unique_ptr<V4Database> v4_database_;
base::FilePath database_dirname_;
base::ScopedTempDir temp_dir_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
bool created_but_not_called_back_;
bool created_and_called_back_;
bool verify_checksum_called_back_;
diff --git a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc
index e8697a9ee7f..561ac7a39ea 100644
--- a/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_get_hash_protocol_manager_unittest.cc
@@ -18,7 +18,7 @@
#include "components/safe_browsing/db/safebrowsing.pb.h"
#include "components/safe_browsing/db/util.h"
#include "components/safe_browsing/db/v4_test_util.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -188,7 +188,7 @@ class V4GetHashProtocolManagerTest : public PlatformTest {
base::SimpleTestClock clock_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
};
TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingNetwork) {
diff --git a/chromium/components/safe_browsing/db/v4_local_database_manager.cc b/chromium/components/safe_browsing/db/v4_local_database_manager.cc
index 2ac1d8d3087..588ab2cadc7 100644
--- a/chromium/components/safe_browsing/db/v4_local_database_manager.cc
+++ b/chromium/components/safe_browsing/db/v4_local_database_manager.cc
@@ -16,6 +16,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_tokenizer.h"
#include "base/task/post_task.h"
+#include "build/branding_buildflags.h"
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/realtime/policy_engine.h"
#include "content/public/browser/browser_task_traits.h"
@@ -54,7 +55,7 @@ ListInfos GetListInfos() {
// - The list doesn't have hash prefixes to match. All requests lead to full
// hash checks. For instance: GetChromeUrlApiId()
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const bool kSyncOnlyOnChromeBuilds = true;
#else
const bool kSyncOnlyOnChromeBuilds = false;
@@ -62,7 +63,7 @@ ListInfos GetListInfos() {
const bool kSyncAlways = true;
const bool kSyncNever = false;
const bool kSyncRealTimeLookupList =
- RealTimePolicyEngine::CanFetchAllowlist();
+ RealTimePolicyEngine::IsFetchAllowlistEnabled();
return ListInfos({
ListInfo(kSyncAlways, "IpMalware.store", GetIpMalwareId(),
SB_THREAT_TYPE_UNUSED),
@@ -264,8 +265,8 @@ V4LocalDatabaseManager::V4LocalDatabaseManager(
list_infos_(GetListInfos()),
task_runner_(task_runner_for_tests
? task_runner_for_tests
- : base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(),
+ : base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
DCHECK(!base_path_.empty());
DCHECK(!list_infos_.empty());
@@ -402,7 +403,6 @@ AsyncMatch V4LocalDatabaseManager::CheckUrlForHighConfidenceAllowlist(
!AreAllStoresAvailableNow(stores_to_check)) {
// NOTE(vakh): If Safe Browsing isn't enabled yet, or if the URL isn't a
// navigation URL, or if the allowlist isn't ready yet, return NO_MATCH.
- // This will lead to a full URL lookup, if other conditions are met.
return AsyncMatch::NO_MATCH;
}
@@ -519,6 +519,7 @@ void V4LocalDatabaseManager::StartOnIOThread(
db_updated_callback_ = base::Bind(&V4LocalDatabaseManager::DatabaseUpdated,
weak_factory_.GetWeakPtr());
+ SetupRealTimeUrlLookupService(url_loader_factory);
SetupUpdateProtocolManager(url_loader_factory, config);
SetupDatabase();
@@ -543,6 +544,8 @@ void V4LocalDatabaseManager::StopOnIOThread(bool shutdown) {
// and doesn't block the IO thread.
V4Database::Destroy(std::move(v4_database_));
+ rt_url_lookup_service_.reset();
+
// Delete the V4UpdateProtocolManager.
// This cancels any in-flight update request.
v4_update_protocol_manager_.reset();
@@ -603,7 +606,7 @@ void V4LocalDatabaseManager::DatabaseUpdated() {
v4_database_->RecordFileSizeHistograms();
UpdateListClientStates(GetStoreStateMap());
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished, this));
@@ -675,6 +678,11 @@ bool V4LocalDatabaseManager::GetPrefixMatches(
return !check->full_hash_to_store_and_hash_prefixes.empty();
}
+RealTimeUrlLookupService*
+V4LocalDatabaseManager::GetRealTimeUrlLookupService() {
+ return rt_url_lookup_service_.get();
+}
+
void V4LocalDatabaseManager::GetSeverestThreatTypeAndMetadata(
const std::vector<FullHashInfo>& full_hash_infos,
const std::vector<FullHash>& full_hashes,
@@ -743,8 +751,9 @@ AsyncMatch V4LocalDatabaseManager::HandleWhitelistCheck(
// These loops will have exactly 1 entry most of the time.
for (const auto& entry : check->full_hash_to_store_and_hash_prefixes) {
for (const auto& store_and_prefix : entry.second) {
- if (store_and_prefix.hash_prefix.size() == kMaxHashPrefixLength)
+ if (store_and_prefix.hash_prefix.size() == kMaxHashPrefixLength) {
return AsyncMatch::MATCH;
+ }
}
}
@@ -808,14 +817,13 @@ void V4LocalDatabaseManager::ScheduleFullHashCheck(
full_hash_infos.emplace_back(entry.first, list_id, next);
}
}
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&V4LocalDatabaseManager::OnFullHashResponse,
- weak_factory_.GetWeakPtr(), std::move(check),
- full_hash_infos));
+ base::PostTask(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&V4LocalDatabaseManager::OnFullHashResponse,
+ weak_factory_.GetWeakPtr(), std::move(check),
+ full_hash_infos));
} else {
// Post on the IO thread to enforce async behavior.
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&V4LocalDatabaseManager::PerformFullHashCheck,
weak_factory_.GetWeakPtr(), std::move(check)));
@@ -990,6 +998,14 @@ void V4LocalDatabaseManager::SetupDatabase() {
V4Database::Create(task_runner_, base_path_, list_infos_, db_ready_callback);
}
+void V4LocalDatabaseManager::SetupRealTimeUrlLookupService(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ rt_url_lookup_service_ =
+ std::make_unique<RealTimeUrlLookupService>(url_loader_factory);
+}
+
void V4LocalDatabaseManager::SetupUpdateProtocolManager(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const V4ProtocolConfig& config) {
diff --git a/chromium/components/safe_browsing/db/v4_local_database_manager.h b/chromium/components/safe_browsing/db/v4_local_database_manager.h
index 47421f90e56..98c23705d5a 100644
--- a/chromium/components/safe_browsing/db/v4_local_database_manager.h
+++ b/chromium/components/safe_browsing/db/v4_local_database_manager.h
@@ -20,6 +20,7 @@
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/db/v4_update_protocol_manager.h"
#include "components/safe_browsing/proto/webui.pb.h"
+#include "components/safe_browsing/realtime/url_lookup_service.h"
#include "url/gurl.h"
namespace safe_browsing {
@@ -77,6 +78,8 @@ class V4LocalDatabaseManager : public SafeBrowsingDatabaseManager {
bool IsDownloadProtectionEnabled() const override;
bool IsSupported() const override;
+ RealTimeUrlLookupService* GetRealTimeUrlLookupService() override;
+
void StartOnIOThread(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const V4ProtocolConfig& config) override;
@@ -104,7 +107,7 @@ class V4LocalDatabaseManager : public SafeBrowsingDatabaseManager {
~V4LocalDatabaseManager() override;
- enum class ClientCallbackType {
+ enum class ClientCallbackType : int {
// This represents the case when we're trying to determine if a URL is
// unsafe from the following perspectives: Malware, Phishing, UwS.
CHECK_BROWSE_URL,
@@ -309,6 +312,10 @@ class V4LocalDatabaseManager : public SafeBrowsingDatabaseManager {
// callback for |DatabaseReady| when the database is ready for use.
void SetupDatabase();
+ // Instantiates and initializes |rt_url_lookup_service_|.
+ void SetupRealTimeUrlLookupService(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
// Instantiates and initializes |v4_update_protocol_manager_|.
void SetupUpdateProtocolManager(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
@@ -367,6 +374,8 @@ class V4LocalDatabaseManager : public SafeBrowsingDatabaseManager {
// use.
QueuedChecks queued_checks_;
+ std::unique_ptr<RealTimeUrlLookupService> rt_url_lookup_service_;
+
// The sequenced task runner for running safe browsing database operations.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc b/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc
index f8f2ebe33a2..33775bff979 100644
--- a/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_local_database_manager_unittest.cc
@@ -22,7 +22,7 @@
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/db/v4_test_util.h"
#include "components/safe_browsing/features.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "crypto/sha2.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -445,7 +445,7 @@ class V4LocalDatabaseManagerTest : public PlatformTest {
ExtendedReportingLevel extended_reporting_level_;
ExtendedReportingLevelCallback erl_callback_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
scoped_refptr<V4LocalDatabaseManager> v4_local_database_manager_;
};
diff --git a/chromium/components/safe_browsing/db/v4_protocol_manager_util.cc b/chromium/components/safe_browsing/db/v4_protocol_manager_util.cc
index 59736f6db6d..05b79335489 100644
--- a/chromium/components/safe_browsing/db/v4_protocol_manager_util.cc
+++ b/chromium/components/safe_browsing/db/v4_protocol_manager_util.cc
@@ -16,6 +16,7 @@
#include "google_apis/google_api_keys.h"
#include "net/base/escape.h"
#include "net/base/ip_address.h"
+#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "url/url_util.h"
diff --git a/chromium/components/safe_browsing/db/v4_protocol_manager_util.h b/chromium/components/safe_browsing/db/v4_protocol_manager_util.h
index e5b34ad0e03..6838c4e9c56 100644
--- a/chromium/components/safe_browsing/db/v4_protocol_manager_util.h
+++ b/chromium/components/safe_browsing/db/v4_protocol_manager_util.h
@@ -22,7 +22,6 @@
#include "base/strings/string_piece.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/db/safebrowsing.pb.h"
-#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
namespace net {
@@ -143,8 +142,13 @@ enum SBThreatType {
// DEPRECATED. Url detected by password protection service.
DEPRECATED_SB_THREAT_TYPE_URL_PASSWORD_PROTECTION_PHISHING,
- // Chrome sign in password reuse detected on low reputation page,
- SB_THREAT_TYPE_SIGN_IN_PASSWORD_REUSE,
+ // Chrome signed in and syncing gaia password reuse detected on low reputation
+ // page,
+ SB_THREAT_TYPE_SIGNED_IN_SYNC_PASSWORD_REUSE,
+
+ // Chrome signed in non syncing gaia password reuse detected on low reputation
+ // page,
+ SB_THREAT_TYPE_SIGNED_IN_NON_SYNC_PASSWORD_REUSE,
// A Google ad that caused a blocked autoredirect was collected
SB_THREAT_TYPE_BLOCKED_AD_REDIRECT,
diff --git a/chromium/components/safe_browsing/db/v4_store.cc b/chromium/components/safe_browsing/db/v4_store.cc
index 89668bc1fb8..ac3237cab68 100644
--- a/chromium/components/safe_browsing/db/v4_store.cc
+++ b/chromium/components/safe_browsing/db/v4_store.cc
@@ -655,8 +655,6 @@ StoreReadResult V4Store::ReadFromDisk() {
return UNEXPECTED_MAGIC_NUMBER_FAILURE;
}
- base::UmaHistogramSparse("SafeBrowsing.V4StoreVersionRead",
- file_format.version_number());
if (file_format.version_number() != kFileVersion) {
return FILE_VERSION_INCOMPATIBLE_FAILURE;
}
diff --git a/chromium/components/safe_browsing/db/v4_store_unittest.cc b/chromium/components/safe_browsing/db/v4_store_unittest.cc
index 4b0ee43ef8f..56300b372bf 100644
--- a/chromium/components/safe_browsing/db/v4_store_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_store_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "components/safe_browsing/db/v4_store.h"
+
#include "base/base64.h"
#include "base/bind.h"
#include "base/files/file_util.h"
@@ -11,7 +12,7 @@
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "components/safe_browsing/db/v4_store.pb.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "crypto/sha2.h"
#include "testing/platform_test.h"
@@ -75,7 +76,7 @@ class V4StoreTest : public PlatformTest {
base::ScopedTempDir temp_dir_;
base::FilePath store_path_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<V4Store> updated_store_;
};
diff --git a/chromium/components/safe_browsing/db/v4_update_protocol_manager.cc b/chromium/components/safe_browsing/db/v4_update_protocol_manager.cc
index 41b782f1a33..84325c7f432 100644
--- a/chromium/components/safe_browsing/db/v4_update_protocol_manager.cc
+++ b/chromium/components/safe_browsing/db/v4_update_protocol_manager.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/timer/timer.h"
+#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/db/safebrowsing.pb.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
@@ -20,7 +21,7 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
-#if !defined(FULL_SAFE_BROWSING)
+#if !BUILDFLAG(FULL_SAFE_BROWSING)
#include "base/system/sys_info.h"
#endif
@@ -64,10 +65,6 @@ void RecordUpdateResult(safe_browsing::V4OperationResult result) {
safe_browsing::V4OperationResult::OPERATION_RESULT_MAX);
}
-void RecordTimedOut(bool timed_out) {
- UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.V4Update.TimedOut", timed_out);
-}
-
} // namespace
namespace safe_browsing {
@@ -256,7 +253,7 @@ std::string V4UpdateProtocolManager::GetBase64SerializedUpdateRequestProto() {
list_update_request->mutable_constraints()->add_supported_compressions(
RICE);
-#if !defined(FULL_SAFE_BROWSING)
+#if !BUILDFLAG(FULL_SAFE_BROWSING)
if (base::SysInfo::IsLowEndDevice()) {
list_update_request->mutable_constraints()->set_max_database_entries(
GetLowEndDBEntryCount(list_update_request->threat_type()));
@@ -390,7 +387,6 @@ void V4UpdateProtocolManager::IssueUpdateRequest() {
}
void V4UpdateProtocolManager::HandleTimeout() {
- RecordTimedOut(true);
request_.reset();
ScheduleNextUpdateWithBackoff(true);
}
@@ -419,7 +415,6 @@ void V4UpdateProtocolManager::OnURLLoaderCompleteInternal(
last_response_code_ = response_code;
V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode(
"SafeBrowsing.V4Update.Network.Result", net_error, last_response_code_);
- RecordTimedOut(false);
last_response_time_ = Time::Now();
diff --git a/chromium/components/safe_browsing/db/v4_update_protocol_manager_unittest.cc b/chromium/components/safe_browsing/db/v4_update_protocol_manager_unittest.cc
index fa27844e3e4..4fd97a8f4cf 100644
--- a/chromium/components/safe_browsing/db/v4_update_protocol_manager_unittest.cc
+++ b/chromium/components/safe_browsing/db/v4_update_protocol_manager_unittest.cc
@@ -14,6 +14,7 @@
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/db/safebrowsing.pb.h"
#include "components/safe_browsing/db/util.h"
#include "components/safe_browsing/db/v4_test_util.h"
@@ -27,7 +28,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
-#if !defined(FULL_SAFE_BROWSING)
+#if !BUILDFLAG(FULL_SAFE_BROWSING)
#include "base/system/sys_info.h"
#endif
@@ -289,7 +290,7 @@ TEST_F(V4UpdateProtocolManagerTest, TestBase64EncodingUsesUrlEncoding) {
std::string expected =
"Cg8KCHVuaXR0ZXN0EgMxLjAaGAgBEAIaCmg4eGZZcVk-OlIiBCABIAIoASICCAE=";
-#if !defined(FULL_SAFE_BROWSING)
+#if !BUILDFLAG(FULL_SAFE_BROWSING)
if (base::SysInfo::IsLowEndDevice()) {
expected =
"Cg8KCHVuaXR0ZXN0EgMxLjAaGwgBEAIaCmg4eGZZcVk-OlIiBxCAICABIAIoASICCAE=";
@@ -360,7 +361,7 @@ TEST_F(V4UpdateProtocolManagerTest, TestExtendedReportingLevelIncluded) {
(*store_state_map_)[ListIdentifier(LINUX_PLATFORM, URL, MALWARE_THREAT)] =
"state";
std::string base = "Cg8KCHVuaXR0ZXN0EgMxLjAaEwgBEAIaBXN0YXRlIgQgASACKAEiAgg";
-#if !defined(FULL_SAFE_BROWSING)
+#if !BUILDFLAG(FULL_SAFE_BROWSING)
if (base::SysInfo::IsLowEndDevice()) {
base = "Cg8KCHVuaXR0ZXN0EgMxLjAaFggBEAIaBXN0YXRlIgcQgCAgASACKAEiAgg";
}
diff --git a/chromium/components/safe_browsing/features.cc b/chromium/components/safe_browsing/features.cc
index eb9ebc9eee8..8405ba7b2f1 100644
--- a/chromium/components/safe_browsing/features.cc
+++ b/chromium/components/safe_browsing/features.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
+#include "components/safe_browsing/buildflags.h"
#include "base/macros.h"
#include "base/values.h"
@@ -34,16 +35,6 @@ const base::Feature kCaptureInlineJavascriptForGoogleAds{
const base::Feature kCaptureSafetyNetId{"SafeBrowsingCaptureSafetyNetId",
base::FEATURE_DISABLED_BY_DEFAULT};
-// If enabled in pre-network-service world, SafeBrowsing URL checks are done by
-// applying SafeBrowsing's URLLoaderThrottle subclasses to ThrottlingURLLoader.
-//
-// This flag has no effect if network service is enabled. With network service,
-// SafeBrowsing URL checks are always done by SafeBrowsing's URLLoaderThrottle
-// subclasses.
-const base::Feature kCheckByURLLoaderThrottle{
- "S13nSafeBrowsingCheckByURLLoaderThrottle",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
const base::Feature kCommittedSBInterstitials{
"SafeBrowsingCommittedInterstitials", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -61,6 +52,16 @@ const base::Feature kRealTimeUrlLookupFetchAllowlist{
"SafeBrowsingRealTimeUrlLookupFetchAllowlist",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kSendOnFocusPing {
+ "SafeBrowsingSendOnFocusPing",
+#if BUILDFLAG(FULL_SAFE_BROWSING)
+ base::FEATURE_ENABLED_BY_DEFAULT
+};
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+};
+#endif
+
const base::Feature kSuspiciousSiteTriggerQuotaFeature{
"SafeBrowsingSuspiciousSiteTriggerQuota", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -72,11 +73,17 @@ const base::Feature kTriggerThrottlerDailyQuotaFeature{
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kUseAPDownloadProtection{"UseAPDownloadProtection",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kUseLocalBlacklistsV2{"SafeBrowsingUseLocalBlacklistsV2",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kUploadForMalwareCheck{"SafeBrowsingUploadForMalwareCheck",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kDeepScanningOfDownloads{
+ "SafeBrowsingDeepScanningOfDownloads", base::FEATURE_ENABLED_BY_DEFAULT};
+
constexpr base::FeatureParam<bool> kShouldFillOldPhishGuardProto{
&kPasswordProtectionForSignedInUsers, "DeprecateOldProto", false};
@@ -94,12 +101,12 @@ constexpr struct {
{&kAdSamplerTriggerFeature, false},
{&kCaptureInlineJavascriptForGoogleAds, true},
{&kCaptureSafetyNetId, true},
- {&kCheckByURLLoaderThrottle, true},
{&kCommittedSBInterstitials, true},
{&kForceUseAPDownloadProtection, false},
{&kPasswordProtectionForSignedInUsers, true},
{&kRealTimeUrlLookupEnabled, true},
{&kRealTimeUrlLookupFetchAllowlist, true},
+ {&kSendOnFocusPing, true},
{&kSuspiciousSiteTriggerQuotaFeature, true},
{&kThreatDomDetailsTagAndAttributeFeature, false},
{&kTriggerThrottlerDailyQuotaFeature, false},
diff --git a/chromium/components/safe_browsing/features.h b/chromium/components/safe_browsing/features.h
index 7775c5f8ffd..c6260e108f5 100644
--- a/chromium/components/safe_browsing/features.h
+++ b/chromium/components/safe_browsing/features.h
@@ -37,8 +37,6 @@ extern const base::Feature kCaptureInlineJavascriptForGoogleAds;
// a SBER user downloads an APK file.
extern const base::Feature kCaptureSafetyNetId;
-extern const base::Feature kCheckByURLLoaderThrottle;
-
// Controls if safe browsing interstitials are implemented as committed
// navigations instead of overlays.
extern const base::Feature kCommittedSBInterstitials;
@@ -51,6 +49,9 @@ extern const base::Feature kForceUseAPDownloadProtection;
// Enable GAIA password protection for signed-in users.
extern const base::Feature kPasswordProtectionForSignedInUsers;
+// Controls whether Chrome sends on focus ping.
+extern const base::Feature kSendOnFocusPing;
+
// Controls the daily quota for the suspicious site trigger.
extern const base::Feature kSuspiciousSiteTriggerQuotaFeature;
@@ -87,6 +88,15 @@ extern const base::Feature kUseAPDownloadProtection;
// Controls whether Chrome on Android uses locally cached blacklists.
extern const base::Feature kUseLocalBlacklistsV2;
+// Controls whether we are uploading files to Safe Browsing for malware
+// scanning.
+extern const base::Feature kUploadForMalwareCheck;
+
+// Controls whether to do deep scanning of downloads. If both this feature and
+// the enterprise policies are enabled, the downloaded file is sent for
+// scanning.
+extern const base::Feature kDeepScanningOfDownloads;
+
base::ListValue GetFeatureStatusList();
// Returns whether or not to stop filling in the SyncAccountType and
diff --git a/chromium/components/safe_browsing/password_protection/BUILD.gn b/chromium/components/safe_browsing/password_protection/BUILD.gn
index 928a9da5d88..5e014fdd11f 100644
--- a/chromium/components/safe_browsing/password_protection/BUILD.gn
+++ b/chromium/components/safe_browsing/password_protection/BUILD.gn
@@ -2,10 +2,11 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//components/safe_browsing/buildflags.gni")
import("//extensions/buildflags/buildflags.gni")
source_set("password_protection") {
- if (safe_browsing_mode == 1) {
+ if (safe_browsing_mode == 1 || safe_browsing_mode == 2) {
sources = [
"password_protection_navigation_throttle.cc",
"password_protection_navigation_throttle.h",
@@ -39,12 +40,14 @@ source_set("password_protection") {
"//components/sessions",
"//components/signin/public/base",
"//components/signin/public/identity_manager",
- "//components/zoom",
"//content/public/browser:browser",
"//net:net",
"//third_party/protobuf:protobuf_lite",
]
}
+ if (safe_browsing_mode == 1) {
+ deps += [ "//components/zoom" ]
+ }
}
source_set("password_protection_metrics_util") {
diff --git a/chromium/components/safe_browsing/password_protection/metrics_util.cc b/chromium/components/safe_browsing/password_protection/metrics_util.cc
index f9606d05a32..ccce2ecdfee 100644
--- a/chromium/components/safe_browsing/password_protection/metrics_util.cc
+++ b/chromium/components/safe_browsing/password_protection/metrics_util.cc
@@ -26,28 +26,63 @@ const char kEnterprisePasswordInterstitialHistogram[] =
const char kEnterprisePasswordWarningDialogHistogram[] =
"PasswordProtection.ModalWarningDialogAction."
"NonGaiaEnterprisePasswordEntry";
+const char kGmailSyncPasswordEntryRequestOutcomeHistogram[] =
+ "PasswordProtection.RequestOutcome.GmailSyncPasswordEntry";
+const char kGmailNonSyncPasswordEntryRequestOutcomeHistogram[] =
+ "PasswordProtection.RequestOutcome.GmailNonSyncPasswordEntry";
const char kGSuiteSyncPasswordEntryRequestOutcomeHistogram[] =
"PasswordProtection.RequestOutcome.GSuiteSyncPasswordEntry";
+const char kGSuiteNonSyncPasswordEntryRequestOutcomeHistogram[] =
+ "PasswordProtection.RequestOutcome.GSuiteNonSyncPasswordEntry";
const char kGSuiteSyncPasswordEntryVerdictHistogram[] =
"PasswordProtection.Verdict.GSuiteSyncPasswordEntry";
+const char kGSuiteNonSyncPasswordEntryVerdictHistogram[] =
+ "PasswordProtection.Verdict.GSuiteNonSyncPasswordEntry";
+const char kGmailSyncPasswordEntryVerdictHistogram[] =
+ "PasswordProtection.Verdict.GmailSyncPasswordEntry";
+const char kGmailNonSyncPasswordEntryVerdictHistogram[] =
+ "PasswordProtection.Verdict.GmailNonSyncPasswordEntry";
+const char kGmailNonSyncPasswordInterstitialHistogram[] =
+ "PasswordProtection.InterstitialAction.GmailNonSyncPasswordEntry";
+const char kGmailSyncPasswordPageInfoHistogram[] =
+ "PasswordProtection.PageInfoAction.GmailSyncPasswordEntry";
+const char kGmailNonSyncPasswordPageInfoHistogram[] =
+ "PasswordProtection.PageInfoAction.GmailNonSyncPasswordEntry";
+const char kGmailSyncPasswordWarningDialogHistogram[] =
+ "PasswordProtection.ModalWarningDialogAction.GmailSyncPasswordEntry";
+const char kGmailNonSyncPasswordWarningDialogHistogram[] =
+ "PasswordProtection.ModalWarningDialogAction.GmailNonSyncPasswordEntry";
+const char kNonSyncPasswordInterstitialHistogram[] =
+ "PasswordProtection.InterstitialAction.NonSyncPasswordEntry";
+const char kNonSyncPasswordPageInfoHistogram[] =
+ "PasswordProtection.PageInfoAction.NonSyncPasswordEntry";
+
const char kGSuiteSyncPasswordInterstitialHistogram[] =
"PasswordProtection.InterstitialAction.GSuiteSyncPasswordEntry";
+const char kGSuiteNonSyncPasswordInterstitialHistogram[] =
+ "PasswordProtection.InterstitialAction.GSuiteNonSyncPasswordEntry";
const char kGSuiteSyncPasswordPageInfoHistogram[] =
"PasswordProtection.PageInfoAction.GSuiteSyncPasswordEntry";
+const char kGSuiteNonSyncPasswordPageInfoHistogram[] =
+ "PasswordProtection.PageInfoAction.GSuiteNonSyncPasswordEntry";
const char kGSuiteSyncPasswordWarningDialogHistogram[] =
"PasswordProtection.ModalWarningDialogAction.GSuiteSyncPasswordEntry";
+const char kGSuiteNonSyncPasswordWarningDialogHistogram[] =
+ "PasswordProtection.ModalWarningDialogAction.GSuiteNonSyncPasswordEntry";
+const char kNonSyncPasswordWarningDialogHistogram[] =
+ "PasswordProtection.ModalWarningDialogAction.NonSyncPasswordEntry";
const char kPasswordOnFocusRequestOutcomeHistogram[] =
"PasswordProtection.RequestOutcome.PasswordFieldOnFocus";
const char kPasswordOnFocusVerdictHistogram[] =
"PasswordProtection.Verdict.PasswordFieldOnFocus";
-const char kProtectedPasswordEntryRequestOutcomeHistogram[] =
- "PasswordProtection.RequestOutcome.ProtectedPasswordEntry";
-const char kProtectedPasswordEntryVerdictHistogram[] =
- "PasswordProtection.Verdict.ProtectedPasswordEntry";
+const char kNonSyncPasswordEntryRequestOutcomeHistogram[] =
+ "PasswordProtection.RequestOutcome.NonSyncPasswordEntry";
const char kSyncPasswordEntryRequestOutcomeHistogram[] =
"PasswordProtection.RequestOutcome.SyncPasswordEntry";
const char kSyncPasswordEntryVerdictHistogram[] =
"PasswordProtection.Verdict.SyncPasswordEntry";
+const char kNonSyncPasswordEntryVerdictHistogram[] =
+ "PasswordProtection.Verdict.NonSyncPasswordEntry";
const char kSyncPasswordChromeSettingsHistogram[] =
"PasswordProtection.ChromeSettingsAction.SyncPasswordEntry";
const char kSyncPasswordInterstitialHistogram[] =
@@ -56,6 +91,13 @@ const char kSyncPasswordPageInfoHistogram[] =
"PasswordProtection.PageInfoAction.SyncPasswordEntry";
const char kSyncPasswordWarningDialogHistogram[] =
"PasswordProtection.ModalWarningDialogAction.SyncPasswordEntry";
+const char kEnterprisePasswordAlertHistogram[] =
+ "PasswordProtection.PasswordAlertModeOutcome."
+ "NonGaiaEnterprisePasswordEntry";
+const char kGsuiteSyncPasswordAlertHistogram[] =
+ "PasswordProtection.PasswordAlertModeOutcome.GSuiteSyncPasswordEntry";
+const char kGsuiteNonSyncPasswordAlertHistogram[] =
+ "PasswordProtection.PasswordAlertModeOutcome.GSuiteNonSyncPasswordEntry";
void LogPasswordEntryRequestOutcome(
RequestOutcome outcome,
@@ -65,12 +107,13 @@ void LogPasswordEntryRequestOutcome(
bool is_gsuite_user =
password_account_type.account_type() == ReusedPasswordAccountType::GSUITE;
bool is_primary_account_password = password_account_type.is_account_syncing();
- // TODO(crbug/914410): Differentiate between primary and syncing accounts for
- // UMA.
if (is_primary_account_password) {
if (is_gsuite_user) {
UMA_HISTOGRAM_ENUMERATION(kGSuiteSyncPasswordEntryRequestOutcomeHistogram,
outcome);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGmailSyncPasswordEntryRequestOutcomeHistogram,
+ outcome);
}
UMA_HISTOGRAM_ENUMERATION(kSyncPasswordEntryRequestOutcomeHistogram,
outcome);
@@ -79,7 +122,14 @@ void LogPasswordEntryRequestOutcome(
UMA_HISTOGRAM_ENUMERATION(kEnterprisePasswordEntryRequestOutcomeHistogram,
outcome);
} else {
- UMA_HISTOGRAM_ENUMERATION(kProtectedPasswordEntryRequestOutcomeHistogram,
+ if (is_gsuite_user) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGSuiteNonSyncPasswordEntryRequestOutcomeHistogram, outcome);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGmailNonSyncPasswordEntryRequestOutcomeHistogram, outcome);
+ }
+ UMA_HISTOGRAM_ENUMERATION(kNonSyncPasswordEntryRequestOutcomeHistogram,
outcome);
}
}
@@ -91,16 +141,17 @@ void LogPasswordOnFocusRequestOutcome(RequestOutcome outcome) {
void LogPasswordAlertModeOutcome(
RequestOutcome outcome,
ReusedPasswordAccountType password_account_type) {
+ DCHECK_NE(ReusedPasswordAccountType::GMAIL,
+ password_account_type.account_type());
if (password_account_type.account_type() ==
ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
- UMA_HISTOGRAM_ENUMERATION(
- "PasswordProtection.PasswordAlertModeOutcome."
- "NonGaiaEnterprisePasswordEntry",
- outcome);
+ UMA_HISTOGRAM_ENUMERATION(kEnterprisePasswordAlertHistogram, outcome);
} else {
- UMA_HISTOGRAM_ENUMERATION(
- "PasswordProtection.PasswordAlertModeOutcome.GSuiteSyncPasswordEntry",
- outcome);
+ if (password_account_type.is_account_syncing()) {
+ UMA_HISTOGRAM_ENUMERATION(kGsuiteSyncPasswordAlertHistogram, outcome);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGsuiteNonSyncPasswordAlertHistogram, outcome);
+ }
}
}
@@ -121,38 +172,56 @@ void LogPasswordProtectionVerdict(
LoginReputationClientRequest::TriggerType trigger_type,
ReusedPasswordAccountType password_account_type,
VerdictType verdict_type) {
- // TODO(crbug/914410): Account for non sync users.
bool is_gsuite_user =
password_account_type.account_type() == ReusedPasswordAccountType::GSUITE;
- bool is_primary_account_password = password_account_type.is_account_syncing();
+ bool is_gmail_user =
+ password_account_type.account_type() == ReusedPasswordAccountType::GMAIL;
+ bool is_account_syncing = password_account_type.is_account_syncing();
+
switch (trigger_type) {
case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE:
UMA_HISTOGRAM_ENUMERATION(
kPasswordOnFocusVerdictHistogram, verdict_type,
- LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1);
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
break;
case LoginReputationClientRequest::PASSWORD_REUSE_EVENT:
UMA_HISTOGRAM_ENUMERATION(
kAnyPasswordEntryVerdictHistogram, verdict_type,
- LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1);
- if (is_primary_account_password) {
- if (is_gsuite_user) {
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
+ if (is_account_syncing) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kSyncPasswordEntryVerdictHistogram, verdict_type,
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
+ } else if (is_gsuite_user || is_gmail_user) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kNonSyncPasswordEntryVerdictHistogram, verdict_type,
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
+ }
+ if (is_gsuite_user) {
+ if (is_account_syncing) {
UMA_HISTOGRAM_ENUMERATION(
kGSuiteSyncPasswordEntryVerdictHistogram, verdict_type,
- LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1);
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGSuiteNonSyncPasswordEntryVerdictHistogram, verdict_type,
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
+ }
+ } else if (is_gmail_user) {
+ if (is_account_syncing) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGmailSyncPasswordEntryVerdictHistogram, verdict_type,
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGmailNonSyncPasswordEntryVerdictHistogram, verdict_type,
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
}
- UMA_HISTOGRAM_ENUMERATION(
- kSyncPasswordEntryVerdictHistogram, verdict_type,
- LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1);
} else if (password_account_type.account_type() ==
ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
UMA_HISTOGRAM_ENUMERATION(
kEnterprisePasswordEntryVerdictHistogram, verdict_type,
- LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1);
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- kProtectedPasswordEntryVerdictHistogram, verdict_type,
- LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1);
+ (LoginReputationClientResponse_VerdictType_VerdictType_MAX + 1));
}
break;
default:
@@ -190,7 +259,6 @@ void LogWarningAction(WarningUIType ui_type,
return;
}
- // TODO(crbug/914410): Account for non sync users.
bool is_gsuite_user =
password_account_type.account_type() == ReusedPasswordAccountType::GSUITE;
bool is_primary_account_password = password_account_type.is_account_syncing();
@@ -201,9 +269,22 @@ void LogWarningAction(WarningUIType ui_type,
if (is_gsuite_user) {
UMA_HISTOGRAM_ENUMERATION(kGSuiteSyncPasswordPageInfoHistogram,
action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGmailSyncPasswordPageInfoHistogram,
+ action);
}
- } else {
+ } else if (password_account_type.account_type() ==
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
UMA_HISTOGRAM_ENUMERATION(kEnterprisePasswordPageInfoHistogram, action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kNonSyncPasswordPageInfoHistogram, action);
+ if (is_gsuite_user) {
+ UMA_HISTOGRAM_ENUMERATION(kGSuiteNonSyncPasswordPageInfoHistogram,
+ action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGmailNonSyncPasswordPageInfoHistogram,
+ action);
+ }
}
break;
case WarningUIType::MODAL_DIALOG:
@@ -212,10 +293,24 @@ void LogWarningAction(WarningUIType ui_type,
if (is_gsuite_user) {
UMA_HISTOGRAM_ENUMERATION(kGSuiteSyncPasswordWarningDialogHistogram,
action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGmailSyncPasswordWarningDialogHistogram,
+ action);
}
- } else {
+ } else if (password_account_type.account_type() ==
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
UMA_HISTOGRAM_ENUMERATION(kEnterprisePasswordWarningDialogHistogram,
action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kNonSyncPasswordWarningDialogHistogram,
+ action);
+ if (is_gsuite_user) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGSuiteNonSyncPasswordWarningDialogHistogram, action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGmailNonSyncPasswordWarningDialogHistogram,
+ action);
+ }
}
break;
case WarningUIType::CHROME_SETTINGS:
@@ -229,9 +324,20 @@ void LogWarningAction(WarningUIType ui_type,
UMA_HISTOGRAM_ENUMERATION(kGSuiteSyncPasswordInterstitialHistogram,
action);
}
- } else {
+ } else if (password_account_type.account_type() ==
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
UMA_HISTOGRAM_ENUMERATION(kEnterprisePasswordInterstitialHistogram,
action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kNonSyncPasswordInterstitialHistogram,
+ action);
+ if (is_gsuite_user) {
+ UMA_HISTOGRAM_ENUMERATION(kGSuiteNonSyncPasswordInterstitialHistogram,
+ action);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(kGmailNonSyncPasswordInterstitialHistogram,
+ action);
+ }
}
break;
case WarningUIType::NOT_USED:
@@ -246,11 +352,4 @@ void LogNumberOfReuseBeforeSyncPasswordChange(size_t reuse_count) {
reuse_count);
}
-void LogContentsSize(const gfx::Size& size) {
- if (size.width() <= 0 || size.height() <= 0)
- return;
- UMA_HISTOGRAM_COUNTS_10000("SafeBrowsing.ContentsSize.Width", size.width());
- UMA_HISTOGRAM_COUNTS_10000("SafeBrowsing.ContentsSize.Height", size.height());
-}
-
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/password_protection/metrics_util.h b/chromium/components/safe_browsing/password_protection/metrics_util.h
index 197b9d1fbd3..c9a8c4c7f47 100644
--- a/chromium/components/safe_browsing/password_protection/metrics_util.h
+++ b/chromium/components/safe_browsing/password_protection/metrics_util.h
@@ -23,21 +23,42 @@ extern const char kEnterprisePasswordEntryVerdictHistogram[];
extern const char kEnterprisePasswordInterstitialHistogram[];
extern const char kEnterprisePasswordPageInfoHistogram[];
extern const char kEnterprisePasswordWarningDialogHistogram[];
-extern const char kGSuiteSyncPasswordEntryRequestOutcomeHistogram[];
+extern const char kGmailNonSyncPasswordInterstitialHistogram[];
+extern const char kGmailSyncPasswordPageInfoHistogram[];
+extern const char kGmailNonSyncPasswordPageInfoHistogram[];
+extern const char kGmailSyncPasswordWarningDialogHistogram[];
+extern const char kGmailNonSyncPasswordWarningDialogHistogram[];
+extern const char kNonSyncPasswordInterstitialHistogram[];
+extern const char kNonSyncPasswordPageInfoHistogram[];
+extern const char kGmailSyncPasswordEntryRequestOutcomeHistogram[];
+extern const char kGmailNonSyncPasswordEntryRequestOutcomeHistogram[];
+extern const char kGSuiteNonSyncPasswordEntryRequestOutcomeHistogram[];
extern const char kGSuiteSyncPasswordEntryVerdictHistogram[];
+
+extern const char kGSuiteSyncPasswordEntryRequestOutcomeHistogram[];
+extern const char kGSuiteNonSyncPasswordEntryVerdictHistogram[];
+extern const char kGmailSyncPasswordEntryVerdictHistogram[];
+extern const char kGmailNonSyncPasswordEntryVerdictHistogram[];
extern const char kGSuiteSyncPasswordInterstitialHistogram[];
+extern const char kGSuiteNonSyncPasswordInterstitialHistogram[];
extern const char kGSuiteSyncPasswordPageInfoHistogram[];
+extern const char kGSuiteNonSyncPasswordPageInfoHistogram[];
extern const char kGSuiteSyncPasswordWarningDialogHistogram[];
+extern const char kGSuiteNonSyncPasswordWarningDialogHistogram[];
extern const char kPasswordOnFocusRequestOutcomeHistogram[];
extern const char kPasswordOnFocusVerdictHistogram[];
+extern const char kNonSyncPasswordEntryRequestOutcomeHistogram[];
extern const char kProtectedPasswordEntryRequestOutcomeHistogram[];
-extern const char kProtectedPasswordEntryVerdictHistogram[];
+extern const char kNonSyncPasswordEntryVerdictHistogram[];
extern const char kSyncPasswordChromeSettingsHistogram[];
extern const char kSyncPasswordEntryRequestOutcomeHistogram[];
extern const char kSyncPasswordEntryVerdictHistogram[];
extern const char kSyncPasswordInterstitialHistogram[];
extern const char kSyncPasswordPageInfoHistogram[];
extern const char kSyncPasswordWarningDialogHistogram[];
+extern const char kEnterprisePasswordAlertHistogram[];
+extern const char kGsuiteSyncPasswordAlertHistogram[];
+extern const char kGsuiteNonSyncPasswordAlertHistogram[];
using ReusedPasswordAccountType =
LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType;
@@ -180,9 +201,6 @@ void LogReferrerChainSize(
LoginReputationClientResponse::VerdictType verdict_type,
int referrer_chain_size);
-// Logs the content area size in DIPs.
-void LogContentsSize(const gfx::Size& size);
-
} // namespace safe_browsing
#endif // COMPONENTS_SAFE_BROWSING_PASSWORD_PROTECTION_METRICS_UTIL_H_
diff --git a/chromium/components/safe_browsing/password_protection/mock_password_protection_service.h b/chromium/components/safe_browsing/password_protection/mock_password_protection_service.h
index 7d41cb2bfdc..83f5c1bcc0e 100644
--- a/chromium/components/safe_browsing/password_protection/mock_password_protection_service.h
+++ b/chromium/components/safe_browsing/password_protection/mock_password_protection_service.h
@@ -26,14 +26,16 @@ class MockPasswordProtectionService : public PasswordProtectionService {
PasswordReuseEvent::SyncAccountType());
MOCK_CONST_METHOD0(GetBrowserPolicyConnector,
const policy::BrowserPolicyConnector*());
- MOCK_CONST_METHOD0(GetPasswordProtectionWarningTriggerPref,
- PasswordProtectionTrigger());
MOCK_CONST_METHOD0(GetCurrentContentAreaSize, gfx::Size());
MOCK_CONST_METHOD0(GetAccountInfo, AccountInfo());
MOCK_CONST_METHOD0(IsPrimaryAccountSyncing, bool());
MOCK_CONST_METHOD0(IsPrimaryAccountSignedIn, bool());
MOCK_CONST_METHOD0(IsPrimaryAccountGmail, bool());
- MOCK_CONST_METHOD1(IsOtherGaiaAccountSignedIn, bool(const std::string&));
+ MOCK_CONST_METHOD1(GetPasswordProtectionWarningTriggerPref,
+ PasswordProtectionTrigger(ReusedPasswordAccountType));
+ MOCK_CONST_METHOD1(GetSignedInNonSyncAccount,
+ AccountInfo(const std::string&));
+ MOCK_CONST_METHOD1(IsOtherGaiaAccountGmail, bool(const std::string&));
MOCK_CONST_METHOD2(IsURLWhitelistedForPasswordEntry,
bool(const GURL&, RequestOutcome*));
@@ -42,22 +44,26 @@ class MockPasswordProtectionService : public PasswordProtectionService {
MOCK_METHOD0(IsHistorySyncEnabled, bool());
MOCK_METHOD0(IsUnderAdvancedProtection, bool());
MOCK_METHOD0(ReportPasswordChanged, void());
- MOCK_METHOD1(MaybeLogPasswordReuseDetectedEvent, void(content::WebContents*));
MOCK_METHOD1(UserClickedThroughSBInterstitial, bool(content::WebContents*));
- MOCK_METHOD2(ShowInterstitial, void(content::WebContents*, PasswordType));
- MOCK_METHOD4(IsPingingEnabled,
+ MOCK_METHOD1(MaybeLogPasswordReuseDetectedEvent, void(content::WebContents*));
+ MOCK_METHOD2(ShowInterstitial,
+ void(content::WebContents*, ReusedPasswordAccountType));
+ MOCK_METHOD3(IsPingingEnabled,
bool(LoginReputationClientRequest::TriggerType,
- PasswordType,
- const std::string&,
+ ReusedPasswordAccountType,
RequestOutcome*));
- MOCK_METHOD3(ShowModalWarning,
- void(content::WebContents*, const std::string&, PasswordType));
+ MOCK_METHOD5(ShowModalWarning,
+ void(content::WebContents*,
+ RequestOutcome,
+ LoginReputationClientResponse::VerdictType,
+ const std::string&,
+ ReusedPasswordAccountType));
MOCK_METHOD4(
MaybeReportPasswordReuseDetected,
void(content::WebContents*, const std::string&, PasswordType, bool));
MOCK_METHOD3(UpdateSecurityState,
void(safe_browsing::SBThreatType,
- PasswordType,
+ ReusedPasswordAccountType,
content::WebContents*));
MOCK_METHOD2(RemoveUnhandledSyncPasswordReuseOnURLsDeleted,
void(bool, const history::URLRows&));
@@ -65,12 +71,13 @@ class MockPasswordProtectionService : public PasswordProtectionService {
void(const GURL&,
SessionID,
LoginReputationClientRequest::Frame*));
- MOCK_METHOD3(MaybeLogPasswordReuseLookupEvent,
+ MOCK_METHOD4(MaybeLogPasswordReuseLookupEvent,
void(content::WebContents*,
RequestOutcome,
+ PasswordType,
const safe_browsing::LoginReputationClientResponse*));
MOCK_METHOD3(CanShowInterstitial,
- bool(RequestOutcome, PasswordType, const GURL&));
+ bool(RequestOutcome, ReusedPasswordAccountType, const GURL&));
MOCK_METHOD5(MaybeStartPasswordFieldOnFocusRequest,
void(content::WebContents*,
const GURL&,
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_request.cc b/chromium/components/safe_browsing/password_protection/password_protection_request.cc
index 6919f8af1f2..0ef073c8cfe 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_request.cc
+++ b/chromium/components/safe_browsing/password_protection/password_protection_request.cc
@@ -49,6 +49,10 @@ namespace {
// the size of the report. UMA suggests 99.9% will have < 200 domains.
const int kMaxReusedDomains = 200;
+#if BUILDFLAG(FULL_SAFE_BROWSING)
+// The maximum time to wait for DOM features to be collected, in milliseconds.
+const int kDomFeatureTimeoutMs = 3000;
+
// Parameters chosen to ensure privacy is preserved by visual features.
const int kMinWidthForVisualFeatures = 576;
const int kMinHeightForVisualFeatures = 576;
@@ -62,6 +66,7 @@ std::unique_ptr<VisualFeatures> ExtractVisualFeatures(
visual_utils::GetBlurredImage(screenshot, features->mutable_image());
return features;
}
+#endif
} // namespace
@@ -127,8 +132,7 @@ void PasswordProtectionRequest::CheckWhitelist() {
// check is required.
auto result_callback = base::Bind(&OnWhitelistCheckDoneOnIO, GetWeakPtr());
tracker_.PostTask(
- base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}).get(),
- FROM_HERE,
+ base::CreateSingleThreadTaskRunner({BrowserThread::IO}).get(), FROM_HERE,
base::BindOnce(&AllowlistCheckerClient::StartCheckCsdWhitelist,
password_protection_service_->database_manager(),
main_frame_url_, result_callback));
@@ -139,7 +143,7 @@ void PasswordProtectionRequest::OnWhitelistCheckDoneOnIO(
base::WeakPtr<PasswordProtectionRequest> weak_request,
bool match_whitelist) {
// Don't access weak_request on IO thread. Move it back to UI thread first.
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PasswordProtectionRequest::OnWhitelistCheckDone,
weak_request, match_whitelist));
@@ -167,12 +171,19 @@ void PasswordProtectionRequest::CheckCachedVerdicts() {
std::unique_ptr<LoginReputationClientResponse> cached_response =
std::make_unique<LoginReputationClientResponse>();
+ ReusedPasswordAccountType password_account_type =
+ password_protection_service_
+ ->GetPasswordProtectionReusedPasswordAccountType(password_type_,
+ username_);
auto verdict = password_protection_service_->GetCachedVerdict(
- main_frame_url_, trigger_type_, password_type_, cached_response.get());
- if (verdict != LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED)
+ main_frame_url_, trigger_type_, password_account_type,
+ cached_response.get());
+ if (verdict != LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED) {
+ set_request_outcome(RequestOutcome::RESPONSE_ALREADY_CACHED);
Finish(RequestOutcome::RESPONSE_ALREADY_CACHED, std::move(cached_response));
- else
+ } else {
FillRequestProto();
+ }
}
void PasswordProtectionRequest::FillRequestProto() {
@@ -193,6 +204,8 @@ void PasswordProtectionRequest::FillRequestProto() {
request_proto_->set_clicked_through_interstitial(
clicked_through_interstitial);
request_proto_->set_content_type(web_contents_->GetContentsMimeType());
+
+#if BUILDFLAG(FULL_SAFE_BROWSING)
if (password_protection_service_->IsExtendedReporting() &&
!password_protection_service_->IsIncognito()) {
gfx::Size content_area_size =
@@ -200,6 +213,7 @@ void PasswordProtectionRequest::FillRequestProto() {
request_proto_->set_content_area_height(content_area_size.height());
request_proto_->set_content_area_width(content_area_size.width());
}
+#endif
switch (trigger_type_) {
case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE: {
@@ -245,8 +259,8 @@ void PasswordProtectionRequest::FillRequestProto() {
safe_browsing::kPasswordProtectionForSignedInUsers)) {
ReusedPasswordAccountType password_account_type_to_add =
password_protection_service_
- ->GetPasswordProtectionReusedPasswordAccountType(
- password_type_);
+ ->GetPasswordProtectionReusedPasswordAccountType(password_type_,
+ username_);
*reuse_event->mutable_reused_password_account_type() =
password_account_type_to_add;
}
@@ -256,22 +270,36 @@ void PasswordProtectionRequest::FillRequestProto() {
NOTREACHED();
}
+#if BUILDFLAG(FULL_SAFE_BROWSING)
// Get the page DOM features.
content::RenderFrameHost* rfh = web_contents_->GetMainFrame();
password_protection_service_->GetPhishingDetector(rfh->GetRemoteInterfaces(),
&phishing_detector_);
+ dom_features_collection_complete_ = false;
phishing_detector_->StartPhishingDetection(
main_frame_url_,
base::BindRepeating(&PasswordProtectionRequest::OnGetDomFeatures,
GetWeakPtr()));
+ base::PostDelayedTask(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&PasswordProtectionRequest::OnGetDomFeatureTimeout,
+ GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kDomFeatureTimeoutMs));
dom_feature_start_time_ = base::TimeTicks::Now();
+#else
+ SendRequest();
+#endif
}
+#if BUILDFLAG(FULL_SAFE_BROWSING)
void PasswordProtectionRequest::OnGetDomFeatures(const std::string& verdict) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (dom_features_collection_complete_)
+ return;
+
+ dom_features_collection_complete_ = true;
ClientPhishingRequest dom_features_request;
- bool parsed = dom_features_request.ParseFromString(verdict);
- UMA_HISTOGRAM_BOOLEAN("PasswordProtection.DomFeatureParsing", parsed);
- if (parsed) {
+ if (dom_features_request.ParseFromString(verdict)) {
for (const ClientPhishingRequest::Feature& feature :
dom_features_request.feature_map()) {
DomFeatures::Feature* new_feature =
@@ -297,6 +325,18 @@ void PasswordProtectionRequest::OnGetDomFeatures(const std::string& verdict) {
UMA_HISTOGRAM_TIMES("PasswordProtection.DomFeatureExtractionDuration",
base::TimeTicks::Now() - dom_feature_start_time_);
+ MaybeCollectVisualFeatures();
+}
+
+void PasswordProtectionRequest::OnGetDomFeatureTimeout() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!dom_features_collection_complete_) {
+ dom_features_collection_complete_ = true;
+ MaybeCollectVisualFeatures();
+ }
+}
+
+void PasswordProtectionRequest::MaybeCollectVisualFeatures() {
// Once the DOM features are collected, either collect visual features, or go
// straight to sending the ping.
if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE &&
@@ -330,9 +370,9 @@ void PasswordProtectionRequest::CollectVisualFeatures() {
void PasswordProtectionRequest::OnScreenshotTaken(const SkBitmap& screenshot) {
// Do the feature extraction on a worker thread, to avoid blocking the UI.
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&ExtractVisualFeatures, screenshot),
base::BindOnce(&PasswordProtectionRequest::OnVisualFeatureCollectionDone,
@@ -350,6 +390,7 @@ void PasswordProtectionRequest::OnVisualFeatureCollectionDone(
SendRequest();
}
+#endif
void PasswordProtectionRequest::SendRequest() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -418,7 +459,7 @@ void PasswordProtectionRequest::StartTimeout() {
// The weak pointer used for the timeout will be invalidated (and
// hence would prevent the timeout) if the check completes on time and
// execution reaches Finish().
- base::PostDelayedTaskWithTraits(
+ base::PostDelayedTask(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&PasswordProtectionRequest::Cancel, GetWeakPtr(), true),
base::TimeDelta::FromMilliseconds(request_timeout_in_ms_));
@@ -449,6 +490,7 @@ void PasswordProtectionRequest::OnURLLoaderComplete(
if (response_body && response->ParseFromString(*response_body)) {
WebUIInfoSingleton::GetInstance()->AddToPGResponses(web_ui_token_,
*response);
+ set_request_outcome(RequestOutcome::SUCCEEDED);
Finish(RequestOutcome::SUCCEEDED, std::move(response));
} else {
Finish(RequestOutcome::RESPONSE_MALFORMED, nullptr);
@@ -466,16 +508,19 @@ void PasswordProtectionRequest::Finish(
if (outcome != RequestOutcome::CANCELED) {
ReusedPasswordAccountType password_account_type =
password_protection_service_
- ->GetPasswordProtectionReusedPasswordAccountType(password_type_);
+ ->GetPasswordProtectionReusedPasswordAccountType(password_type_,
+ username_);
if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
LogPasswordOnFocusRequestOutcome(outcome);
} else {
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
LogPasswordEntryRequestOutcome(outcome, password_account_type);
- // TODO(crbug/914410): Account for non sync users.
+
if (password_type_ == PasswordType::PRIMARY_ACCOUNT_PASSWORD) {
password_protection_service_->MaybeLogPasswordReuseLookupEvent(
- web_contents_, outcome, response.get());
+ web_contents_, outcome, password_type_, response.get());
}
+#endif
}
if (outcome == RequestOutcome::SUCCEEDED && response) {
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_request.h b/chromium/components/safe_browsing/password_protection/password_protection_request.h
index e823d874532..3a2d6e191a8 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_request.h
+++ b/chromium/components/safe_browsing/password_protection/password_protection_request.h
@@ -12,6 +12,7 @@
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "components/safe_browsing/password_protection/metrics_util.h"
#include "components/safe_browsing/password_protection/password_protection_service.h"
@@ -105,6 +106,12 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
is_modal_warning_showing_ = is_warning_showing;
}
+ RequestOutcome request_outcome() const { return request_outcome_; }
+
+ void set_request_outcome(RequestOutcome request_outcome) {
+ request_outcome_ = request_outcome;
+ }
+
// Keeps track of created navigation throttle.
void AddThrottle(PasswordProtectionNavigationThrottle* throttle) {
throttles_.insert(throttle);
@@ -149,6 +156,7 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
// Fill |request_proto_| with appropriate values.
void FillRequestProto();
+#if BUILDFLAG(FULL_SAFE_BROWSING)
// Collects visual features from the current login page.
void CollectVisualFeatures();
@@ -158,6 +166,7 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
// Called when the visual feature extraction is complete.
void OnVisualFeatureCollectionDone(
std::unique_ptr<VisualFeatures> visual_features);
+#endif
// Initiates network request to Safe Browsing backend.
void SendRequest();
@@ -169,9 +178,18 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
void Finish(RequestOutcome outcome,
std::unique_ptr<LoginReputationClientResponse> response);
+#if BUILDFLAG(FULL_SAFE_BROWSING)
// Called when the DOM feature extraction is complete.
void OnGetDomFeatures(const std::string& verdict);
+ // Called when the DOM feature extraction times out.
+ void OnGetDomFeatureTimeout();
+
+ // If appropriate, collects visual features, otherwise continues on to sending
+ // the request.
+ void MaybeCollectVisualFeatures();
+#endif
+
// WebContents of the password protection event.
content::WebContents* web_contents_;
@@ -213,6 +231,9 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
// Can only be accessed on UI thread.
PasswordProtectionService* password_protection_service_;
+ // The outcome of the password protection request.
+ RequestOutcome request_outcome_;
+
// If we haven't receive response after this period of time, we cancel this
// request.
const int request_timeout_in_ms_;
@@ -233,6 +254,7 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
// If a request is sent, this is the token returned by the WebUI.
int web_ui_token_;
+#if BUILDFLAG(FULL_SAFE_BROWSING)
// When we start extracting visual features.
base::TimeTicks visual_feature_start_time_;
@@ -244,6 +266,11 @@ class PasswordProtectionRequest : public base::RefCountedThreadSafe<
// PasswordProtection.DomFeatureExtractionDuration.
base::TimeTicks dom_feature_start_time_;
+ // Whether the DOM features collection is finished, either by timeout or by
+ // successfully gathering the features.
+ bool dom_features_collection_complete_;
+#endif
+
base::WeakPtrFactory<PasswordProtectionRequest> weakptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PasswordProtectionRequest);
};
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_service.cc b/chromium/components/safe_browsing/password_protection/password_protection_service.cc
index 73167a96bb4..f55e4b2e4c1 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_service.cc
+++ b/chromium/components/safe_browsing/password_protection/password_protection_service.cc
@@ -83,34 +83,27 @@ bool PasswordProtectionService::CanGetReputationOfURL(const GURL& url) {
hostname.find('.') != std::string::npos;
}
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
bool PasswordProtectionService::ShouldShowModalWarning(
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
- const std::string& username,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse::VerdictType verdict_type) {
if (trigger_type != LoginReputationClientRequest::PASSWORD_REUSE_EVENT ||
!IsSupportedPasswordTypeForModalWarning(password_type)) {
return false;
}
- // Accounts are not signed in only in tests.
- if ((password_type == PasswordType::PRIMARY_ACCOUNT_PASSWORD &&
- !IsPrimaryAccountSignedIn()) ||
- (password_type == PasswordType::OTHER_GAIA_PASSWORD &&
- !IsOtherGaiaAccountSignedIn(username))) {
- return false;
- }
-
return (verdict_type == LoginReputationClientResponse::PHISHING ||
verdict_type == LoginReputationClientResponse::LOW_REPUTATION) &&
- IsWarningEnabled();
+ IsWarningEnabled(password_type);
}
+#endif
LoginReputationClientResponse::VerdictType
PasswordProtectionService::GetCachedVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse* out_response) {
return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
}
@@ -118,7 +111,7 @@ PasswordProtectionService::GetCachedVerdict(
void PasswordProtectionService::CacheVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
const LoginReputationClientResponse& verdict,
const base::Time& receive_time) {}
@@ -142,6 +135,7 @@ void PasswordProtectionService::StartRequest(
pending_requests_.insert(std::move(request));
}
+#if defined(ON_FOCUS_PING_ENABLED)
void PasswordProtectionService::MaybeStartPasswordFieldOnFocusRequest(
WebContents* web_contents,
const GURL& main_frame_url,
@@ -150,8 +144,14 @@ void PasswordProtectionService::MaybeStartPasswordFieldOnFocusRequest(
const std::string& hosted_domain) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RequestOutcome reason;
+ if (!base::FeatureList::IsEnabled(safe_browsing::kSendOnFocusPing)) {
+ return;
+ }
if (CanSendPing(LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- main_frame_url, PasswordType::PASSWORD_TYPE_UNKNOWN, "",
+ main_frame_url,
+ GetPasswordProtectionReusedPasswordAccountType(
+ PasswordType::PASSWORD_TYPE_UNKNOWN,
+ /*username=*/""),
&reason)) {
StartRequest(web_contents, main_frame_url, password_form_action,
password_form_frame_url, /* username */ "",
@@ -160,7 +160,9 @@ void PasswordProtectionService::MaybeStartPasswordFieldOnFocusRequest(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
}
}
+#endif
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
void PasswordProtectionService::MaybeStartProtectedPasswordEntryRequest(
WebContents* web_contents,
const GURL& main_frame_url,
@@ -169,44 +171,53 @@ void PasswordProtectionService::MaybeStartProtectedPasswordEntryRequest(
const std::vector<std::string>& matching_domains,
bool password_field_exists) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!IsSupportedPasswordTypeForPinging(password_type))
- return;
-
- // Collect metrics about typical page-zoom on login pages.
- double zoom_level =
- zoom::ZoomController::GetZoomLevelForWebContents(web_contents);
- UMA_HISTOGRAM_COUNTS_1000(
- "PasswordProtection.PageZoomFactor",
- static_cast<int>(100 * content::ZoomLevelToZoomFactor(zoom_level)));
-
+ ReusedPasswordAccountType reused_password_account_type =
+ GetPasswordProtectionReusedPasswordAccountType(password_type, username);
RequestOutcome reason;
- if (CanSendPing(LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- main_frame_url, password_type, username, &reason)) {
- StartRequest(web_contents, main_frame_url, GURL(), GURL(), username,
- password_type, matching_domains,
- LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- password_field_exists);
- } else {
- MaybeLogPasswordReuseLookupEvent(web_contents, reason, nullptr);
+ // Need to populate |reason| to be passed into CanShowInterstitial.
+ bool can_send_ping =
+ CanSendPing(LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ main_frame_url, reused_password_account_type, &reason);
+ if (IsSupportedPasswordTypeForPinging(password_type)) {
+ // Collect metrics about typical page-zoom on login pages.
+ double zoom_level =
+ zoom::ZoomController::GetZoomLevelForWebContents(web_contents);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "PasswordProtection.PageZoomFactor",
+ static_cast<int>(100 * content::ZoomLevelToZoomFactor(zoom_level)));
+ if (can_send_ping) {
+ StartRequest(web_contents, main_frame_url, GURL(), GURL(), username,
+ password_type, matching_domains,
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ password_field_exists);
+ } else {
+ if (reused_password_account_type.is_account_syncing())
+ MaybeLogPasswordReuseLookupEvent(web_contents, reason, password_type,
+ nullptr);
+ }
}
- if (CanShowInterstitial(reason, password_type, main_frame_url)) {
- ShowInterstitial(web_contents, password_type);
+ if (CanShowInterstitial(reason, reused_password_account_type,
+ main_frame_url)) {
+ username_for_last_shown_warning_ = username;
+ reused_password_account_type_for_last_shown_warning_ =
+ reused_password_account_type;
+ ShowInterstitial(web_contents, reused_password_account_type);
}
}
+#endif
bool PasswordProtectionService::CanSendPing(
LoginReputationClientRequest::TriggerType trigger_type,
const GURL& main_frame_url,
- PasswordType password_type,
- const std::string& username,
+ ReusedPasswordAccountType password_type,
RequestOutcome* reason) {
*reason = RequestOutcome::UNKNOWN;
bool is_pinging_enabled =
- IsPingingEnabled(trigger_type, password_type, username, reason);
+ IsPingingEnabled(trigger_type, password_type, reason);
// Pinging is enabled for password_reuse trigger level; however we need to
// make sure *reason is set appropriately.
PasswordProtectionTrigger trigger_level =
- GetPasswordProtectionWarningTriggerPref();
+ GetPasswordProtectionWarningTriggerPref(password_type);
if (trigger_level == PASSWORD_REUSE) {
*reason = RequestOutcome::PASSWORD_ALERT_MODE;
}
@@ -214,9 +225,7 @@ bool PasswordProtectionService::CanSendPing(
!IsURLWhitelistedForPasswordEntry(main_frame_url, reason)) {
return true;
}
- LogNoPingingReason(
- trigger_type, *reason,
- GetPasswordProtectionReusedPasswordAccountType(password_type));
+ LogNoPingingReason(trigger_type, *reason, password_type);
return false;
}
@@ -228,21 +237,45 @@ void PasswordProtectionService::RequestFinished(
DCHECK(request);
if (response) {
+ ReusedPasswordAccountType password_type =
+ GetPasswordProtectionReusedPasswordAccountType(request->password_type(),
+ request->username());
if (outcome != RequestOutcome::RESPONSE_ALREADY_CACHED) {
CacheVerdict(request->main_frame_url(), request->trigger_type(),
- request->password_type(), *response, base::Time::Now());
+ password_type, *response, base::Time::Now());
+ }
+ bool enable_warning_for_non_sync_users = base::FeatureList::IsEnabled(
+ safe_browsing::kPasswordProtectionForSignedInUsers);
+ if (!enable_warning_for_non_sync_users &&
+ request->password_type() == PasswordType::OTHER_GAIA_PASSWORD) {
+ return;
}
- if (ShouldShowModalWarning(request->trigger_type(),
- request->password_type(), request->username(),
+
+ // If it's password alert mode and a Gsuite/enterprise account, we do not
+ // show a modal warning.
+ if (outcome == RequestOutcome::PASSWORD_ALERT_MODE &&
+ (password_type.account_type() == ReusedPasswordAccountType::GSUITE ||
+ password_type.account_type() ==
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE)) {
+ return;
+ }
+
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
+ if (ShouldShowModalWarning(request->trigger_type(), password_type,
response->verdict_type())) {
- ShowModalWarning(request->web_contents(), response->verdict_token(),
- request->password_type());
+ username_for_last_shown_warning_ = request->username();
+ reused_password_account_type_for_last_shown_warning_ = password_type;
+ ShowModalWarning(request->web_contents(), request->request_outcome(),
+ response->verdict_type(), response->verdict_token(),
+ password_type);
request->set_is_modal_warning_showing(true);
}
+#endif
}
request->HandleDeferredNavigations();
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// If the request is canceled, the PasswordProtectionService is already
// partially destroyed, and we won't be able to log accurate metrics.
if (outcome != RequestOutcome::CANCELED) {
@@ -254,6 +287,7 @@ void PasswordProtectionService::RequestFinished(
request->username(),
request->password_type(), is_phishing_url);
}
+#endif
// Remove request from |pending_requests_| list. If it triggers warning, add
// it into the !warning_reqeusts_| list.
@@ -312,15 +346,17 @@ void PasswordProtectionService::FillUserPopulation(
user_population->set_profile_management_status(
GetProfileManagementStatus(GetBrowserPolicyConnector()));
user_population->set_is_history_sync_enabled(IsHistorySyncEnabled());
+#if BUILDFLAG(FULL_SAFE_BROWSING)
user_population->set_is_under_advanced_protection(
IsUnderAdvancedProtection());
+#endif
user_population->set_is_incognito(IsIncognito());
}
void PasswordProtectionService::OnURLsDeleted(
history::HistoryService* history_service,
const history::DeletionInfo& deletion_info) {
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::UI},
base::BindRepeating(&PasswordProtectionService::
RemoveUnhandledSyncPasswordReuseOnURLsDeleted,
@@ -344,7 +380,9 @@ PasswordProtectionService::MaybeCreateNavigationThrottle(
if (request->web_contents() == web_contents &&
request->trigger_type() ==
safe_browsing::LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
- IsSupportedPasswordTypeForModalWarning(request->password_type())) {
+ IsSupportedPasswordTypeForModalWarning(
+ GetPasswordProtectionReusedPasswordAccountType(
+ request->password_type(), username_for_last_shown_warning()))) {
return std::make_unique<PasswordProtectionNavigationThrottle>(
navigation_handle, request, /*is_warning_showing=*/false);
}
@@ -359,6 +397,7 @@ PasswordProtectionService::MaybeCreateNavigationThrottle(
return nullptr;
}
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
void PasswordProtectionService::RemoveWarningRequestsByWebContents(
content::WebContents* web_contents) {
for (auto it = warning_requests_.begin(); it != warning_requests_.end();) {
@@ -377,14 +416,12 @@ bool PasswordProtectionService::IsModalWarningShowingInWebContents(
}
return false;
}
+#endif
-bool PasswordProtectionService::IsWarningEnabled() {
- return GetPasswordProtectionWarningTriggerPref() == PHISHING_REUSE;
-}
-
-bool PasswordProtectionService::IsEventLoggingEnabled() {
- // TODO(bdea): Incorporate non-sync users.
- return !IsIncognito() && IsPrimaryAccountSignedIn();
+bool PasswordProtectionService::IsWarningEnabled(
+ ReusedPasswordAccountType password_type) {
+ return GetPasswordProtectionWarningTriggerPref(password_type) ==
+ PHISHING_REUSE;
}
// static
@@ -409,10 +446,10 @@ PasswordProtectionService::GetPasswordProtectionReusedPasswordType(
return PasswordReuseEvent::REUSED_PASSWORD_TYPE_UNKNOWN;
}
-// static
ReusedPasswordAccountType
PasswordProtectionService::GetPasswordProtectionReusedPasswordAccountType(
- password_manager::metrics_util::PasswordType password_type) const {
+ password_manager::metrics_util::PasswordType password_type,
+ const std::string& username) const {
ReusedPasswordAccountType reused_password_account_type;
switch (password_type) {
case PasswordType::SAVED_PASSWORD:
@@ -423,11 +460,9 @@ PasswordProtectionService::GetPasswordProtectionReusedPasswordAccountType(
reused_password_account_type.set_account_type(
ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
return reused_password_account_type;
- case PasswordType::PRIMARY_ACCOUNT_PASSWORD:
- case PasswordType::OTHER_GAIA_PASSWORD:
- if (password_type == PasswordType::PRIMARY_ACCOUNT_PASSWORD)
- reused_password_account_type.set_is_account_syncing(
- IsPrimaryAccountSyncing());
+ case PasswordType::PRIMARY_ACCOUNT_PASSWORD: {
+ reused_password_account_type.set_is_account_syncing(
+ IsPrimaryAccountSyncing());
if (!IsPrimaryAccountSignedIn()) {
reused_password_account_type.set_account_type(
ReusedPasswordAccountType::UNKNOWN);
@@ -437,6 +472,20 @@ PasswordProtectionService::GetPasswordProtectionReusedPasswordAccountType(
IsPrimaryAccountGmail() ? ReusedPasswordAccountType::GMAIL
: ReusedPasswordAccountType::GSUITE);
return reused_password_account_type;
+ }
+ case PasswordType::OTHER_GAIA_PASSWORD: {
+ AccountInfo account_info = GetSignedInNonSyncAccount(username);
+ if (account_info.account_id.empty()) {
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
+ return reused_password_account_type;
+ }
+ reused_password_account_type.set_account_type(
+ IsOtherGaiaAccountGmail(username)
+ ? ReusedPasswordAccountType::GMAIL
+ : ReusedPasswordAccountType::GSUITE);
+ return reused_password_account_type;
+ }
case PasswordType::PASSWORD_TYPE_UNKNOWN:
case PasswordType::PASSWORD_TYPE_COUNT:
reused_password_account_type.set_account_type(
@@ -447,6 +496,26 @@ PasswordProtectionService::GetPasswordProtectionReusedPasswordAccountType(
return reused_password_account_type;
}
+// static
+PasswordType
+PasswordProtectionService::ConvertReusedPasswordAccountTypeToPasswordType(
+ ReusedPasswordAccountType password_type) {
+ if (password_type.is_account_syncing()) {
+ return PasswordType::PRIMARY_ACCOUNT_PASSWORD;
+ } else if (password_type.account_type() ==
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
+ return PasswordType::ENTERPRISE_PASSWORD;
+ } else if (password_type.account_type() ==
+ ReusedPasswordAccountType::SAVED_PASSWORD) {
+ return PasswordType::SAVED_PASSWORD;
+ } else if (password_type.account_type() ==
+ ReusedPasswordAccountType::UNKNOWN) {
+ return PasswordType::PASSWORD_TYPE_UNKNOWN;
+ } else {
+ return PasswordType::OTHER_GAIA_PASSWORD;
+ }
+}
+
bool PasswordProtectionService::IsSupportedPasswordTypeForPinging(
PasswordType password_type) const {
switch (password_type) {
@@ -468,19 +537,26 @@ bool PasswordProtectionService::IsSupportedPasswordTypeForPinging(
}
bool PasswordProtectionService::IsSupportedPasswordTypeForModalWarning(
- PasswordType password_type) const {
- if (password_type == PasswordType::OTHER_GAIA_PASSWORD) {
- return base::FeatureList::IsEnabled(
- safe_browsing::kPasswordProtectionForSignedInUsers);
- }
- return password_type == PasswordType::PRIMARY_ACCOUNT_PASSWORD ||
- password_type == PasswordType::ENTERPRISE_PASSWORD;
+ ReusedPasswordAccountType password_type) const {
+ if (password_type.account_type() ==
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE)
+ return true;
+
+ if (password_type.account_type() != ReusedPasswordAccountType::GMAIL &&
+ password_type.account_type() != ReusedPasswordAccountType::GSUITE)
+ return false;
+
+ return password_type.is_account_syncing() ||
+ base::FeatureList::IsEnabled(
+ safe_browsing::kPasswordProtectionForSignedInUsers);
}
+#if BUILDFLAG(FULL_SAFE_BROWSING)
void PasswordProtectionService::GetPhishingDetector(
service_manager::InterfaceProvider* provider,
mojom::PhishingDetectorPtr* phishing_detector) {
provider->GetInterface(phishing_detector);
}
+#endif
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_service.h b/chromium/components/safe_browsing/password_protection/password_protection_service.h
index 8e6ba9a8e7c..5a3f8e1ebb7 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_service.h
+++ b/chromium/components/safe_browsing/password_protection/password_protection_service.h
@@ -19,6 +19,7 @@
#include "base/values.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/db/v4_protocol_manager_util.h"
@@ -81,7 +82,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
virtual LoginReputationClientResponse::VerdictType GetCachedVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse* out_response);
// Stores |verdict| in |settings| based on its |trigger_type|, |url|,
@@ -89,7 +90,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
virtual void CacheVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
const LoginReputationClientResponse& verdict,
const base::Time& receive_time);
@@ -106,13 +107,16 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
LoginReputationClientRequest::TriggerType trigger_type,
bool password_field_exists);
+#if defined(ON_FOCUS_PING_ENABLED)
virtual void MaybeStartPasswordFieldOnFocusRequest(
content::WebContents* web_contents,
const GURL& main_frame_url,
const GURL& password_form_action,
const GURL& password_form_frame_url,
const std::string& hosted_domain);
+#endif
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
virtual void MaybeStartProtectedPasswordEntryRequest(
content::WebContents* web_contents,
const GURL& main_frame_url,
@@ -124,6 +128,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
// Records a Chrome Sync event that sync password reuse was detected.
virtual void MaybeLogPasswordReuseDetectedEvent(
content::WebContents* web_contents) = 0;
+#endif
scoped_refptr<SafeBrowsingDatabaseManager> database_manager();
@@ -136,25 +141,29 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
// (6) Its hostname is a dotless domain.
static bool CanGetReputationOfURL(const GURL& url);
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// If we want to show password reuse modal warning.
bool ShouldShowModalWarning(
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
- const std::string& username,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse::VerdictType verdict_type);
// Shows modal warning dialog on the current |web_contents| and pass the
// |verdict_token| to callback of this dialog.
- virtual void ShowModalWarning(content::WebContents* web_contents,
- const std::string& verdict_token,
- PasswordType password_type) = 0;
+ virtual void ShowModalWarning(
+ content::WebContents* web_contents,
+ RequestOutcome outcome,
+ LoginReputationClientResponse::VerdictType verdict_type,
+ const std::string& verdict_token,
+ ReusedPasswordAccountType password_type) = 0;
// Shows chrome://reset-password interstitial.
virtual void ShowInterstitial(content::WebContents* web_contens,
- PasswordType password_type) = 0;
+ ReusedPasswordAccountType password_type) = 0;
+#endif
virtual void UpdateSecurityState(safe_browsing::SBThreatType threat_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
content::WebContents* web_contents) = 0;
// If user has clicked through any Safe Browsing interstitial on this given
@@ -169,14 +178,11 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
MaybeCreateNavigationThrottle(content::NavigationHandle* navigation_handle);
// Returns if the warning UI is enabled.
- bool IsWarningEnabled();
-
- // Returns if the event logging is enabled.
- bool IsEventLoggingEnabled();
+ bool IsWarningEnabled(ReusedPasswordAccountType password_type);
// Returns the pref value of password protection warning trigger.
- virtual PasswordProtectionTrigger GetPasswordProtectionWarningTriggerPref()
- const = 0;
+ virtual PasswordProtectionTrigger GetPasswordProtectionWarningTriggerPref(
+ ReusedPasswordAccountType password_type) const = 0;
// If |url| matches Safe Browsing whitelist domains, password protection
// change password URL, or password protection login URLs in the enterprise
@@ -185,6 +191,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
const GURL& url,
RequestOutcome* reason) const = 0;
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// Triggers the safeBrowsingPrivate.OnPolicySpecifiedPasswordReuseDetected.
virtual void MaybeReportPasswordReuseDetected(
content::WebContents* web_contents,
@@ -195,23 +202,53 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
// Called when a protected password change is detected. Must be called on
// UI thread.
virtual void ReportPasswordChanged() = 0;
-
+#endif
// Converts from password::metrics_util::PasswordType to
// LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordType.
static ReusedPasswordType GetPasswordProtectionReusedPasswordType(
- password_manager::metrics_util::PasswordType password_type);
+ PasswordType password_type);
- // Converts from
- // LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType
- // to LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordType.
+ // Converts from password_manager::metrics_util::PasswordType
+ // to PasswordReuseEvent::ReusedPasswordAccountType. |username| is only
+ // used if |password_type| is OTHER_GAIA_PASSWORD because it needs to be
+ // compared to the list of signed in accounts.
ReusedPasswordAccountType GetPasswordProtectionReusedPasswordAccountType(
- PasswordType password_type) const;
+ PasswordType password_type,
+ const std::string& username) const;
+
+ // Converts from ReusedPasswordAccountType to
+ // password_manager::metrics_util::PasswordType.
+ static PasswordType ConvertReusedPasswordAccountTypeToPasswordType(
+ ReusedPasswordAccountType password_type);
// If we can send ping for this type of reused password.
bool IsSupportedPasswordTypeForPinging(PasswordType password_type) const;
// If we can show modal warning for this type of reused password.
- bool IsSupportedPasswordTypeForModalWarning(PasswordType password_type) const;
+ bool IsSupportedPasswordTypeForModalWarning(
+ ReusedPasswordAccountType password_type) const;
+
+ const ReusedPasswordAccountType&
+ reused_password_account_type_for_last_shown_warning() const {
+ return reused_password_account_type_for_last_shown_warning_;
+ }
+#if defined(UNIT_TEST)
+ void set_reused_password_account_type_for_last_shown_warning(
+ ReusedPasswordAccountType
+ reused_password_account_type_for_last_shown_warning) {
+ reused_password_account_type_for_last_shown_warning_ =
+ reused_password_account_type_for_last_shown_warning;
+ }
+#endif
+
+ const std::string& username_for_last_shown_warning() const {
+ return username_for_last_shown_warning_;
+ }
+#if defined(UNIT_TEST)
+ void set_username_for_last_shown_warning(const std::string& username) {
+ username_for_last_shown_warning_ = username;
+ }
+#endif
virtual AccountInfo GetAccountInfo() const = 0;
@@ -225,8 +262,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
// allowed. |password_type| is used for UMA metric recording.
bool CanSendPing(LoginReputationClientRequest::TriggerType trigger_type,
const GURL& main_frame_url,
- PasswordType password_type,
- const std::string& username,
+ ReusedPasswordAccountType password_type,
RequestOutcome* reason);
// Called by a PasswordProtectionRequest instance when it finishes to remove
@@ -277,44 +313,63 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
virtual bool IsPingingEnabled(
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
- const std::string& username,
+ ReusedPasswordAccountType password_type,
RequestOutcome* reason) = 0;
virtual bool IsHistorySyncEnabled() = 0;
+ // If primary account is syncing.
virtual bool IsPrimaryAccountSyncing() const = 0;
+ // If primary account is signed in.
virtual bool IsPrimaryAccountSignedIn() const = 0;
+ // If a domain is not defined for the primary account. This means the primary
+ // account is a Gmail account.
virtual bool IsPrimaryAccountGmail() const = 0;
- virtual bool IsOtherGaiaAccountSignedIn(
+ // If the domain for the non sync account is equal to |kNoHostedDomainFound|,
+ // this means that the account is a Gmail account.
+ virtual bool IsOtherGaiaAccountGmail(const std::string& username) const = 0;
+
+ // Gets the account based off of the username from a list of signed in
+ // accounts.
+ virtual AccountInfo GetSignedInNonSyncAccount(
const std::string& username) const = 0;
+#if BUILDFLAG(FULL_SAFE_BROWSING)
virtual bool IsUnderAdvancedProtection() = 0;
+#endif
// Gets the type of sync account associated with current profile or
// |NOT_SIGNED_IN|.
virtual LoginReputationClientRequest::PasswordReuseEvent::SyncAccountType
GetSyncAccountType() const = 0;
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
// Records a Chrome Sync event for the result of the URL reputation lookup
// if the user enters their sync password on a website.
virtual void MaybeLogPasswordReuseLookupEvent(
content::WebContents* web_contents,
RequestOutcome,
+ PasswordType password_type,
const LoginReputationClientResponse*) = 0;
+#endif
void CheckCsdWhitelistOnIOThread(const GURL& url, bool* check_result);
+#if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
void RemoveWarningRequestsByWebContents(content::WebContents* web_contents);
bool IsModalWarningShowingInWebContents(content::WebContents* web_contents);
+ // Determines if we should show chrome://reset-password interstitial based on
+ // previous request outcome, the reused |password_type| and the
+ // |main_frame_url|.
virtual bool CanShowInterstitial(RequestOutcome reason,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
const GURL& main_frame_url) = 0;
+#endif
private:
friend class PasswordProtectionServiceTest;
@@ -354,6 +409,7 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
RequestOutcome reason,
PasswordType password_type);
+#if BUILDFLAG(FULL_SAFE_BROWSING)
// Get the content area size of current browsing window.
virtual gfx::Size GetCurrentContentAreaSize() const = 0;
@@ -362,6 +418,16 @@ class PasswordProtectionService : public history::HistoryServiceObserver {
virtual void GetPhishingDetector(
service_manager::InterfaceProvider* provider,
mojom::PhishingDetectorPtr* phishing_detector);
+#endif
+
+ // The username of the account which password has been reused on. It is only
+ // set once a modal warning or interstitial is verified to be shown.
+ std::string username_for_last_shown_warning_ = "";
+
+ // The last ReusedPasswordAccountType that was shown a warning or
+ // interstitial.
+ ReusedPasswordAccountType
+ reused_password_account_type_for_last_shown_warning_;
scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
diff --git a/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc
index 2c6e54609c1..2354a205115 100644
--- a/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc
+++ b/chromium/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -11,12 +11,16 @@
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/null_task_runner.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_reuse_detector.h"
#include "components/safe_browsing/common/safe_browsing.mojom-forward.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "components/safe_browsing/db/test_database_manager.h"
+#include "components/safe_browsing/features.h"
#include "components/safe_browsing/password_protection/metrics_util.h"
#include "components/safe_browsing/password_protection/mock_password_protection_service.h"
#include "components/safe_browsing/password_protection/password_protection_navigation_throttle.h"
@@ -26,8 +30,8 @@
#include "components/signin/public/identity_manager/account_info.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -77,7 +81,7 @@ class MockSafeBrowsingDatabaseManager : public TestSafeBrowsingDatabaseManager {
class TestPhishingDetector : public mojom::PhishingDetector {
public:
- TestPhishingDetector() : binding_(this) {}
+ TestPhishingDetector() : should_timeout_(false), binding_(this) {}
~TestPhishingDetector() override {}
void Bind(mojo::ScopedMessagePipeHandle handle) {
@@ -87,13 +91,25 @@ class TestPhishingDetector : public mojom::PhishingDetector {
void StartPhishingDetection(
const GURL& url,
StartPhishingDetectionCallback callback) override {
+ if (should_timeout_) {
+ deferred_callbacks_.push_back(std::move(callback));
+ } else {
+ ReturnFeatures(url, std::move(callback));
+ }
+ }
+ void ReturnFeatures(const GURL& url,
+ StartPhishingDetectionCallback callback) {
ClientPhishingRequest verdict;
verdict.set_is_phishing(false);
verdict.set_client_score(0.1);
std::move(callback).Run(verdict.SerializeAsString());
}
+ void set_should_timeout(bool timeout) { should_timeout_ = timeout; }
+
private:
+ bool should_timeout_;
+ std::vector<StartPhishingDetectionCallback> deferred_callbacks_;
mojo::Binding<mojom::PhishingDetector> binding_;
DISALLOW_COPY_AND_ASSIGN(TestPhishingDetector);
@@ -149,7 +165,7 @@ class TestPasswordProtectionService : public MockPasswordProtectionService {
void CacheVerdict(const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
const LoginReputationClientResponse& verdict,
const base::Time& receive_time) override {
if (!CanGetReputationOfURL(url) || IsIncognito())
@@ -162,7 +178,7 @@ class TestPasswordProtectionService : public MockPasswordProtectionService {
LoginReputationClientResponse::VerdictType GetCachedVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse* out_response) override {
if (!url.is_valid() || !CanGetReputationOfURL(url))
return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
@@ -176,6 +192,10 @@ class TestPasswordProtectionService : public MockPasswordProtectionService {
return cache_manager_->GetStoredPhishGuardVerdictCount(trigger_type);
}
+ void SetDomFeatureCollectionTimeout(bool should_timeout) {
+ test_phishing_detector_.set_should_timeout(should_timeout);
+ }
+
private:
PasswordProtectionRequest* latest_request_;
base::RunLoop run_loop_;
@@ -206,7 +226,8 @@ class MockPasswordProtectionNavigationThrottle
class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
public:
- PasswordProtectionServiceTest() {}
+ PasswordProtectionServiceTest()
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
LoginReputationClientResponse CreateVerdictProto(
LoginReputationClientResponse::VerdictType verdict,
@@ -236,13 +257,11 @@ class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
.WillRepeatedly(Return(GetParam()));
EXPECT_CALL(*password_protection_service_, IsIncognito())
.WillRepeatedly(Return(false));
- EXPECT_CALL(*password_protection_service_, GetSyncAccountType())
- .WillRepeatedly(Return(PasswordReuseEvent::NOT_SIGNED_IN));
EXPECT_CALL(*password_protection_service_,
IsURLWhitelistedForPasswordEntry(_, _))
.WillRepeatedly(Return(false));
EXPECT_CALL(*password_protection_service_,
- GetPasswordProtectionWarningTriggerPref())
+ GetPasswordProtectionWarningTriggerPref(_))
.WillRepeatedly(Return(PASSWORD_PROTECTION_OFF));
url_ = PasswordProtectionService::GetPasswordProtectionRequestUrl();
}
@@ -290,7 +309,7 @@ class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
void CacheVerdict(const GURL& url,
LoginReputationClientRequest::TriggerType trigger,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse::VerdictType verdict,
int cache_duration_sec,
const std::string& cache_expression,
@@ -302,7 +321,7 @@ class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
response, verdict_received_time);
}
- void CacheInvalidVerdict(PasswordType password_type) {
+ void CacheInvalidVerdict(ReusedPasswordAccountType password_type) {
GURL invalid_hostname("http://invalid.com");
std::unique_ptr<base::DictionaryValue> verdict_dictionary =
base::DictionaryValue::From(content_setting_map_->GetWebsiteSetting(
@@ -321,8 +340,10 @@ class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
invalid_cache_expression_entry->SetWithoutPathExpansion(
"invalid_cache_expression", std::move(invalid_verdict_entry));
verdict_dictionary->SetWithoutPathExpansion(
- base::NumberToString(
- static_cast<std::underlying_type_t<PasswordType>>(password_type)),
+ base::NumberToString(static_cast<std::underlying_type_t<PasswordType>>(
+ password_protection_service_
+ ->ConvertReusedPasswordAccountTypeToPasswordType(
+ password_type))),
std::move(invalid_cache_expression_entry));
content_setting_map_->SetWebsiteSettingDefaultScope(
invalid_hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
@@ -352,9 +373,9 @@ class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
}
protected:
- // |thread_bundle_| is needed here because this test involves both UI and IO
- // threads.
- content::TestBrowserThreadBundle thread_bundle_;
+ // |task_environment_| is needed here because this test involves both UI and
+ // IO threads.
+ content::BrowserTaskEnvironment task_environment_;
scoped_refptr<MockSafeBrowsingDatabaseManager> database_manager_;
sync_preferences::TestingPrefServiceSyncable test_pref_service_;
scoped_refptr<HostContentSettingsMap> content_setting_map_;
@@ -370,12 +391,17 @@ class PasswordProtectionServiceTest : public ::testing::TestWithParam<bool> {
TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
ASSERT_EQ(0U, GetStoredVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-
+ EXPECT_CALL(*password_protection_service_, IsPrimaryAccountSignedIn())
+ .WillRepeatedly(Return(true));
// Assume each verdict has a TTL of 10 minutes.
// Cache a verdict for http://www.test.com/foo/index.html
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
+ reused_password_account_type.set_is_account_syncing(true);
CacheVerdict(GURL("http://www.test.com/foo/index.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foo/", base::Time::Now());
@@ -386,7 +412,7 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
// override the cache.
CacheVerdict(GURL("http://www.test.com/foo/index2.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::PHISHING, 10 * kMinute,
"test.com/foo/", base::Time::Now());
EXPECT_EQ(1U, GetStoredVerdictCount(
@@ -396,13 +422,15 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
password_protection_service_->GetCachedVerdict(
GURL("http://www.test.com/foo/index2.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &out_verdict));
+ reused_password_account_type, &out_verdict));
// Cache a password reuse verdict with a different password type but same
// origin and cache expression should add a new entry.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
CacheVerdict(GURL("http://www.test.com/foo/index2.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::PHISHING, 10 * kMinute,
"test.com/foo/", base::Time::Now());
EXPECT_EQ(2U, GetStoredVerdictCount(
@@ -411,14 +439,14 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
password_protection_service_->GetCachedVerdict(
GURL("http://www.test.com/foo/index2.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD, &out_verdict));
+ reused_password_account_type, &out_verdict));
// Cache another verdict with the same origin but different cache_expression
// will not increase setting count, but will increase the number of verdicts
// in the given origin.
CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/bar/", base::Time::Now());
EXPECT_EQ(3U, GetStoredVerdictCount(
@@ -428,7 +456,7 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
// PASSWORD_REUSE_EVENT should be the same.
CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foobar/", base::Time::Now());
EXPECT_EQ(3U, GetStoredVerdictCount(
@@ -443,10 +471,14 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdictsIncognito) {
ASSERT_EQ(0U, GetStoredVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
+ reused_password_account_type.set_is_account_syncing(true);
// No verdict will be cached for incognito profile.
CacheVerdict(GURL("http://www.test.com/foo/index.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foo/", base::Time::Now());
@@ -457,7 +489,7 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdictsIncognito) {
// Verdict count should not increase.
CacheVerdict(GURL("http://www.test.com/foo/index2.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::PHISHING, 10 * kMinute,
"test.com/foo/", base::Time::Now());
EXPECT_EQ(0U, GetStoredVerdictCount(
@@ -467,7 +499,7 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdictsIncognito) {
// increase.
CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foobar/", base::Time::Now());
EXPECT_EQ(0U, GetStoredVerdictCount(
@@ -479,12 +511,15 @@ TEST_P(PasswordProtectionServiceTest, TestCachePasswordReuseVerdictsIncognito) {
TEST_P(PasswordProtectionServiceTest, TestCacheUnfamiliarLoginVerdicts) {
ASSERT_EQ(0U, GetStoredVerdictCount(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
+ reused_password_account_type.set_is_account_syncing(true);
// Assume each verdict has a TTL of 10 minutes.
// Cache a verdict for http://www.test.com/foo/index.html
CacheVerdict(GURL("http://www.test.com/foo/index.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foo/", base::Time::Now());
@@ -496,7 +531,7 @@ TEST_P(PasswordProtectionServiceTest, TestCacheUnfamiliarLoginVerdicts) {
// in the given origin.
CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/bar/", base::Time::Now());
EXPECT_EQ(2U, GetStoredVerdictCount(
@@ -506,7 +541,7 @@ TEST_P(PasswordProtectionServiceTest, TestCacheUnfamiliarLoginVerdicts) {
// UNFAMILIAR_LOGIN_PAGE should be the same.
CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foobar/", base::Time::Now());
EXPECT_EQ(2U, GetStoredVerdictCount(
@@ -522,10 +557,14 @@ TEST_P(PasswordProtectionServiceTest,
ASSERT_EQ(0U, GetStoredVerdictCount(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
+ reused_password_account_type.set_is_account_syncing(true);
// No verdict will be cached for incognito profile.
CacheVerdict(GURL("http://www.test.com/foo/index.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foo/", base::Time::Now());
@@ -534,7 +573,7 @@ TEST_P(PasswordProtectionServiceTest,
CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/bar/", base::Time::Now());
EXPECT_EQ(0U, GetStoredVerdictCount(
@@ -542,9 +581,12 @@ TEST_P(PasswordProtectionServiceTest,
// Now cache a PASSWORD_REUSE_EVENT verdict. Verdict count should not
// increase.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
+ reused_password_account_type.set_is_account_syncing(true);
CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/foobar/", base::Time::Now());
EXPECT_EQ(0U, GetStoredVerdictCount(
@@ -558,29 +600,37 @@ TEST_P(PasswordProtectionServiceTest, TestGetCachedVerdicts) {
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
ASSERT_EQ(0U, GetStoredVerdictCount(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
+ reused_password_account_type.set_is_account_syncing(true);
// Prepare 4 verdicts of the same origin with different cache expressions,
// or password type, one is expired, one is not, one is of a different
// trigger type, and the other is with a different password type.
base::Time now = base::Time::Now();
CacheVerdict(GURL("http://test.com/login.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute, "test.com/",
now);
CacheVerdict(
GURL("http://test.com/def/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::PHISHING, 10 * kMinute, "test.com/def/",
+ reused_password_account_type, LoginReputationClientResponse::PHISHING,
+ 10 * kMinute, "test.com/def/",
base::Time::FromDoubleT(now.ToDoubleT() - kDay)); // Yesterday, expired.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
CacheVerdict(GURL("http://test.com/bar/login.html"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::PHISHING, 10 * kMinute,
"test.com/bar/", now);
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
CacheVerdict(GURL("http://test.com/login.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute, "test.com/",
now);
@@ -591,48 +641,60 @@ TEST_P(PasswordProtectionServiceTest, TestGetCachedVerdicts) {
// Return VERDICT_TYPE_UNSPECIFIED if look up for a URL with unknown origin.
LoginReputationClientResponse actual_verdict;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
password_protection_service_->GetCachedVerdict(
GURL("http://www.unknown.com/"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
password_protection_service_->GetCachedVerdict(
GURL("http://www.unknown.com/"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
// Return SAFE if look up for a URL that matches "test.com" cache expression.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
EXPECT_EQ(LoginReputationClientResponse::SAFE,
password_protection_service_->GetCachedVerdict(
GURL("http://test.com/xyz/foo.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
EXPECT_EQ(LoginReputationClientResponse::SAFE,
password_protection_service_->GetCachedVerdict(
GURL("http://test.com/xyz/foo.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
// Return VERDICT_TYPE_UNSPECIFIED if look up for a URL whose variants match
// test.com/def, but the corresponding verdict is expired.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
password_protection_service_->GetCachedVerdict(
GURL("http://test.com/def/ghi/index.html"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
// Return PHISHING. Matches "test.com/bar/" cache expression.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
EXPECT_EQ(LoginReputationClientResponse::PHISHING,
password_protection_service_->GetCachedVerdict(
GURL("http://test.com/bar/foo.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
// Now cache SAFE verdict for the full path.
CacheVerdict(GURL("http://test.com/bar/foo.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::SAFE, 10 * kMinute,
"test.com/bar/foo.jsp", now);
@@ -641,18 +703,21 @@ TEST_P(PasswordProtectionServiceTest, TestGetCachedVerdicts) {
password_protection_service_->GetCachedVerdict(
GURL("http://test.com/bar/foo.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN, &actual_verdict));
+ reused_password_account_type, &actual_verdict));
}
TEST_P(PasswordProtectionServiceTest, TestDoesNotCacheAboutBlank) {
ASSERT_EQ(0U, GetStoredVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
// Should not actually cache, since about:blank is not valid for reputation
// computing.
CacheVerdict(
GURL("about:blank"), LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN, LoginReputationClientResponse::SAFE,
+ reused_password_account_type, LoginReputationClientResponse::SAFE,
10 * kMinute, "about:blank", base::Time::Now());
EXPECT_EQ(0U, GetStoredVerdictCount(
@@ -713,9 +778,12 @@ TEST_P(PasswordProtectionServiceTest, TestNoRequestSentForWhitelistedURL) {
TEST_P(PasswordProtectionServiceTest, TestNoRequestSentIfVerdictAlreadyCached) {
histograms_.ExpectTotalCount(kPasswordOnFocusRequestOutcomeHistogram, 0);
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
CacheVerdict(GURL(kTargetUrl),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
+ reused_password_account_type,
LoginReputationClientResponse::LOW_REPUTATION, 10 * kMinute,
GURL(kTargetUrl).host().append("/"), base::Time::Now());
InitializeAndStartPasswordOnFocusRequest(
@@ -801,8 +869,7 @@ TEST_P(PasswordProtectionServiceTest,
TestProtectedPasswordEntryRequestAndResponseSuccessfull) {
histograms_.ExpectTotalCount(kAnyPasswordEntryRequestOutcomeHistogram, 0);
histograms_.ExpectTotalCount(kSyncPasswordEntryRequestOutcomeHistogram, 0);
- histograms_.ExpectTotalCount(kProtectedPasswordEntryRequestOutcomeHistogram,
- 0);
+ histograms_.ExpectTotalCount(kNonSyncPasswordEntryRequestOutcomeHistogram, 0);
// Set up valid response.
LoginReputationClientResponse expected_response =
CreateVerdictProto(LoginReputationClientResponse::PHISHING, 10 * kMinute,
@@ -811,9 +878,17 @@ TEST_P(PasswordProtectionServiceTest,
expected_response.SerializeAsString());
// Initiate a saved password entry request (w/ no sync password).
+ AccountInfo account_info;
+ account_info.account_id = "account_id";
+ account_info.email = "email";
+ account_info.gaia = "gaia";
+ EXPECT_CALL(*password_protection_service_, GetSignedInNonSyncAccount(_))
+ .WillRepeatedly(Return(account_info));
+
InitializeAndStartPasswordEntryRequest(
- PasswordType::SAVED_PASSWORD, {"example.com"},
- false /* match whitelist */, 10000 /* timeout in ms*/, GetWebContents());
+ PasswordType::OTHER_GAIA_PASSWORD, {"gmail.com"},
+ false /* match whitelist */, 10000 /* timeout in ms*/,
+ GetWebContents());
password_protection_service_->WaitForResponse();
// UMA: request outcomes
@@ -822,27 +897,24 @@ TEST_P(PasswordProtectionServiceTest,
ElementsAre(base::Bucket(1 /* SUCCEEDED */, 1)));
histograms_.ExpectTotalCount(kSyncPasswordEntryRequestOutcomeHistogram, 0);
EXPECT_THAT(
- histograms_.GetAllSamples(kProtectedPasswordEntryRequestOutcomeHistogram),
+ histograms_.GetAllSamples(kNonSyncPasswordEntryRequestOutcomeHistogram),
ElementsAre(base::Bucket(1 /* SUCCEEDED */, 1)));
- EXPECT_THAT(
- histograms_.GetAllSamples(kProtectedPasswordEntryVerdictHistogram),
- ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
+ EXPECT_THAT(histograms_.GetAllSamples(kNonSyncPasswordEntryVerdictHistogram),
+ ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
// UMA: verdicts
EXPECT_THAT(histograms_.GetAllSamples(kAnyPasswordEntryVerdictHistogram),
ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
histograms_.ExpectTotalCount(kSyncPasswordEntryVerdictHistogram, 0);
- EXPECT_THAT(
- histograms_.GetAllSamples(kProtectedPasswordEntryVerdictHistogram),
- ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
+ EXPECT_THAT(histograms_.GetAllSamples(kNonSyncPasswordEntryVerdictHistogram),
+ ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
}
TEST_P(PasswordProtectionServiceTest,
TestSyncPasswordEntryRequestAndResponseSuccessfull) {
histograms_.ExpectTotalCount(kAnyPasswordEntryRequestOutcomeHistogram, 0);
histograms_.ExpectTotalCount(kSyncPasswordEntryRequestOutcomeHistogram, 0);
- histograms_.ExpectTotalCount(kProtectedPasswordEntryRequestOutcomeHistogram,
- 0);
+ histograms_.ExpectTotalCount(kNonSyncPasswordEntryRequestOutcomeHistogram, 0);
// Set up valid response.
LoginReputationClientResponse expected_response =
CreateVerdictProto(LoginReputationClientResponse::PHISHING, 10 * kMinute,
@@ -851,6 +923,8 @@ TEST_P(PasswordProtectionServiceTest,
expected_response.SerializeAsString());
EXPECT_CALL(*password_protection_service_, IsPrimaryAccountSyncing())
.WillRepeatedly(Return(true));
+ EXPECT_CALL(*password_protection_service_, IsPrimaryAccountSignedIn())
+ .WillRepeatedly(Return(true));
// Initiate a sync password entry request (w/ no saved password).
InitializeAndStartPasswordEntryRequest(
PasswordType::PRIMARY_ACCOUNT_PASSWORD, {}, false /* match whitelist */,
@@ -864,15 +938,14 @@ TEST_P(PasswordProtectionServiceTest,
EXPECT_THAT(
histograms_.GetAllSamples(kSyncPasswordEntryRequestOutcomeHistogram),
ElementsAre(base::Bucket(1 /* SUCCEEDED */, 1)));
- histograms_.ExpectTotalCount(kProtectedPasswordEntryRequestOutcomeHistogram,
- 0);
+ histograms_.ExpectTotalCount(kNonSyncPasswordEntryRequestOutcomeHistogram, 0);
// UMA: verdicts
EXPECT_THAT(histograms_.GetAllSamples(kAnyPasswordEntryVerdictHistogram),
ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
EXPECT_THAT(histograms_.GetAllSamples(kSyncPasswordEntryVerdictHistogram),
ElementsAre(base::Bucket(3 /* PHISHING */, 1)));
- histograms_.ExpectTotalCount(kProtectedPasswordEntryVerdictHistogram, 0);
+ histograms_.ExpectTotalCount(kNonSyncPasswordEntryVerdictHistogram, 0);
}
TEST_P(PasswordProtectionServiceTest, TestTearDownWithPendingRequests) {
@@ -987,101 +1060,123 @@ TEST_P(PasswordProtectionServiceTest,
TEST_P(PasswordProtectionServiceTest, VerifyShouldShowModalWarning) {
EXPECT_CALL(*password_protection_service_,
- GetPasswordProtectionWarningTriggerPref())
+ GetPasswordProtectionWarningTriggerPref(_))
.WillRepeatedly(Return(PHISHING_REUSE));
EXPECT_CALL(*password_protection_service_, IsPrimaryAccountSignedIn())
.WillRepeatedly(Return(true));
+ AccountInfo account_info;
+ account_info.account_id = "account_id";
+ account_info.email = "email";
+ account_info.gaia = "gaia";
+ EXPECT_CALL(*password_protection_service_, GetSignedInNonSyncAccount(_))
+ .WillRepeatedly(Return(account_info));
// Don't show modal warning if it is not a password reuse ping.
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
+ reused_password_account_type.set_is_account_syncing(true);
EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
// Don't show modal warning if it is a saved password reuse.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::SAVED_PASSWORD);
EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::SAVED_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
-
- // Don't show modal warning if it is a non-sync gaia password reuse.
- EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
- LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::OTHER_GAIA_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
+
+ {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ {}, {safe_browsing::kPasswordProtectionForSignedInUsers});
+
+ // Don't show modal warning if non-sync gaia account experiment is not
+ // on.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GMAIL);
+ reused_password_account_type.set_is_account_syncing(false);
+ EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
+ }
+ {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ safe_browsing::kPasswordProtectionForSignedInUsers);
+ // Show modal warning if non-sync gaia account experiment is on.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GMAIL);
+ reused_password_account_type.set_is_account_syncing(false);
+ EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
+ }
// Don't show modal warning if reused password type unknown.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::UNKNOWN);
EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GMAIL);
+ reused_password_account_type.set_is_account_syncing(true);
EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
// For a GSUITE account, don't show warning if password protection is set to
// off by enterprise policy.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::GSUITE);
EXPECT_CALL(*password_protection_service_,
- GetPasswordProtectionWarningTriggerPref())
+ GetPasswordProtectionWarningTriggerPref(_))
.WillRepeatedly(Return(PASSWORD_PROTECTION_OFF));
- EXPECT_EQ(
- PASSWORD_PROTECTION_OFF,
- password_protection_service_->GetPasswordProtectionWarningTriggerPref());
EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
// For a GSUITE account, show warning if password protection is set to
// PHISHING_REUSE.
EXPECT_CALL(*password_protection_service_,
- GetPasswordProtectionWarningTriggerPref())
+ GetPasswordProtectionWarningTriggerPref(_))
.WillRepeatedly(Return(PHISHING_REUSE));
EXPECT_EQ(
PHISHING_REUSE,
- password_protection_service_->GetPasswordProtectionWarningTriggerPref());
+ password_protection_service_->GetPasswordProtectionWarningTriggerPref(
+ reused_password_account_type));
EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
// Modal dialog warning is also shown on LOW_REPUTATION verdict.
EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::LOW_REPUTATION));
+ reused_password_account_type,
+ LoginReputationClientResponse::LOW_REPUTATION));
// Modal dialog warning should not be shown for enterprise password reuse
// if it is turned off by policy.
EXPECT_CALL(*password_protection_service_,
- GetPasswordProtectionWarningTriggerPref())
+ GetPasswordProtectionWarningTriggerPref(_))
.WillRepeatedly(Return(PASSWORD_PROTECTION_OFF));
EXPECT_FALSE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
// Show modal warning for enterprise password reuse if the trigger is
// configured to PHISHING_REUSE.
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
EXPECT_CALL(*password_protection_service_,
- GetPasswordProtectionWarningTriggerPref())
+ GetPasswordProtectionWarningTriggerPref(_))
.WillRepeatedly(Return(PHISHING_REUSE));
EXPECT_TRUE(password_protection_service_->ShouldShowModalWarning(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD,
- /*username=*/"", LoginReputationClientResponse::PHISHING));
-}
-
-TEST_P(PasswordProtectionServiceTest, VerifyIsEventLoggingEnabled) {
- // For user who is not signed-in, event logging should be disabled.
- EXPECT_FALSE(password_protection_service_->IsEventLoggingEnabled());
-
- // Event logging should be enable for all signed-in users..
- EXPECT_CALL(*password_protection_service_, IsPrimaryAccountSignedIn())
- .WillRepeatedly(Return(true));
- EXPECT_TRUE(password_protection_service_->IsEventLoggingEnabled());
+ reused_password_account_type, LoginReputationClientResponse::PHISHING));
}
TEST_P(PasswordProtectionServiceTest, VerifyContentTypeIsPopulated) {
@@ -1107,6 +1202,15 @@ TEST_P(PasswordProtectionServiceTest, VerifyContentTypeIsPopulated) {
}
TEST_P(PasswordProtectionServiceTest, VerifyIsSupportedPasswordTypeForPinging) {
+ EXPECT_CALL(*password_protection_service_, IsPrimaryAccountSignedIn())
+ .WillRepeatedly(Return(true));
+ AccountInfo account_info;
+ account_info.account_id = "account_id";
+ account_info.email = "email";
+ account_info.gaia = "gaia";
+ EXPECT_CALL(*password_protection_service_, GetSignedInNonSyncAccount(_))
+ .WillRepeatedly(Return(account_info));
+
EXPECT_TRUE(password_protection_service_->IsSupportedPasswordTypeForPinging(
PasswordType::SAVED_PASSWORD));
EXPECT_TRUE(password_protection_service_->IsSupportedPasswordTypeForPinging(
@@ -1118,10 +1222,24 @@ TEST_P(PasswordProtectionServiceTest, VerifyIsSupportedPasswordTypeForPinging) {
EXPECT_TRUE(password_protection_service_->IsSupportedPasswordTypeForPinging(
PasswordType::SAVED_PASSWORD));
- EXPECT_FALSE(password_protection_service_->IsSupportedPasswordTypeForPinging(
- PasswordType::OTHER_GAIA_PASSWORD));
EXPECT_TRUE(password_protection_service_->IsSupportedPasswordTypeForPinging(
PasswordType::ENTERPRISE_PASSWORD));
+ {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ {}, {safe_browsing::kPasswordProtectionForSignedInUsers});
+ // Only ping for signed in, non-syncing users if the experiment is on.
+ EXPECT_FALSE(
+ password_protection_service_->IsSupportedPasswordTypeForPinging(
+ PasswordType::OTHER_GAIA_PASSWORD));
+ }
+ {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ safe_browsing::kPasswordProtectionForSignedInUsers);
+ EXPECT_TRUE(password_protection_service_->IsSupportedPasswordTypeForPinging(
+ PasswordType::OTHER_GAIA_PASSWORD));
+ }
}
TEST_P(PasswordProtectionServiceTest, TestPingsForAboutBlank) {
@@ -1185,6 +1303,28 @@ TEST_P(PasswordProtectionServiceTest, TestDomFeaturesPopulated) {
->has_dom_features());
}
+TEST_P(PasswordProtectionServiceTest, TestDomFeaturesTimeout) {
+ password_protection_service_->SetDomFeatureCollectionTimeout(true);
+ LoginReputationClientResponse expected_response =
+ CreateVerdictProto(LoginReputationClientResponse::PHISHING, 10 * kMinute,
+ GURL("about:blank").host());
+ test_url_loader_factory_.AddResponse(url_.spec(),
+ expected_response.SerializeAsString());
+ EXPECT_CALL(*password_protection_service_, GetCurrentContentAreaSize())
+ .Times(AnyNumber())
+ .WillOnce(Return(gfx::Size(1000, 1000)));
+ password_protection_service_->StartRequest(
+ GetWebContents(), GURL("about:blank"), GURL(), GURL(), kUserName,
+ PasswordType::SAVED_PASSWORD, {"example.com"},
+ LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, true);
+ task_environment_.FastForwardUntilNoTasksRemain();
+
+ password_protection_service_->WaitForResponse();
+ ASSERT_NE(nullptr, password_protection_service_->GetLatestRequestProto());
+ EXPECT_FALSE(password_protection_service_->GetLatestRequestProto()
+ ->has_dom_features());
+}
+
TEST_P(PasswordProtectionServiceTest, TestRequestCancelOnTimeout) {
content::WebContents* web_contents = GetWebContents();
InitializeAndStartPasswordOnFocusRequest(
@@ -1212,7 +1352,7 @@ TEST_P(PasswordProtectionServiceTest, TestWebContentsDestroyed) {
InitializeAndStartPasswordOnFocusRequest(
false /* match whitelist */, 10000 /* timeout in ms */, web_contents);
delete web_contents;
- base::RunLoop().RunUntilIdle();
+ task_environment_.FastForwardUntilNoTasksRemain();
}
INSTANTIATE_TEST_SUITE_P(Regular,
diff --git a/chromium/components/safe_browsing/ping_manager.cc b/chromium/components/safe_browsing/ping_manager.cc
index 4cbb6881857..f578f39e46d 100644
--- a/chromium/components/safe_browsing/ping_manager.cc
+++ b/chromium/components/safe_browsing/ping_manager.cc
@@ -17,10 +17,6 @@
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/url_request/url_request_status.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/gurl.h"
@@ -85,8 +81,6 @@ PingManager::PingManager(
PingManager::~PingManager() {}
-// net::URLFetcherDelegate implementation ----------------------------------
-
// All SafeBrowsing request responses are handled here.
void PingManager::OnURLLoaderComplete(
network::SimpleURLLoader* source,
diff --git a/chromium/components/safe_browsing/proto/webprotect.proto b/chromium/components/safe_browsing/proto/webprotect.proto
index d0c2e6f5db5..9b839cbdb8a 100644
--- a/chromium/components/safe_browsing/proto/webprotect.proto
+++ b/chromium/components/safe_browsing/proto/webprotect.proto
@@ -23,7 +23,16 @@ message MalwareDeepScanningClientRequest {
}
// DLP-specific scanning information.
-message DlpDeepScanningClientRequest {}
+message DlpDeepScanningClientRequest {
+ // Where the content comes from, so that the proper rules can be triggered.
+ enum ContentSource {
+ CONTENT_SOURCE_UNKNOWN = 0;
+ FILE_DOWNLOAD = 1;
+ FILE_UPLOAD = 2;
+ WEB_CONTENT_UPLOAD = 3;
+ }
+ optional ContentSource content_source = 1;
+}
// Scanning configuration sent from Chrome.
message DeepScanningClientRequest {
@@ -38,10 +47,14 @@ message DeepScanningClientRequest {
// DLP scan specific request info.
optional DlpDeepScanningClientRequest dlp_scan_request = 4;
+
+ // Token used to correlate requests and responses. This is different than the
+ // FCM token, in that it is unique for each request.
+ optional string request_token = 5;
}
// Malware-specific response given back for scanned content.
-message MalwareDeepScanningClientResponse {
+message MalwareDeepScanningVerdict {
enum Verdict {
VERDICT_UNSPECIFIED = 0;
CLEAN = 1;
@@ -52,17 +65,39 @@ message MalwareDeepScanningClientResponse {
optional Verdict verdict = 1;
}
-// DLP-specific response given back for scanned content.
-message DlpDeepScanningClientResponse {}
+message DlpDeepScanningVerdict {
+ // The status of the deep scanning verdict. When status is SUCCESS and
+ // triggered_rules below is empty, then the content is clean.
+ enum Status {
+ STATUS_UNKNOWN = 0;
+ SUCCESS = 1;
+ FAILURE = 2;
+ }
+ optional Status status = 1;
-message DeepScanningClientResponse {
- // Malware scan specific response info.
- optional MalwareDeepScanningClientResponse malware_scan_response = 1;
+ message TriggeredRule {
+ enum Action {
+ ACTION_UNKNOWN = 0;
+ REPORT_ONLY = 1;
+ WARN = 2;
+ BLOCK = 3;
+ }
+ optional Action action = 1;
- // DLP scan specific response info.
- optional DlpDeepScanningClientResponse dlp_scan_response = 2;
+ optional string rule_name = 2;
+ optional int64 rule_id = 3;
+ }
+ // Only relevant when status is SUCCESS above.
+ repeated TriggeredRule triggered_rules = 2;
+}
+
+message DeepScanningClientResponse {
// Token used to correlate requests and responses. This is different than the
// FCM token, in that it is unique for each request.
- optional string token = 3;
+ optional string token = 1;
+
+ optional MalwareDeepScanningVerdict malware_scan_verdict = 2;
+
+ optional DlpDeepScanningVerdict dlp_scan_verdict = 3;
}
diff --git a/chromium/components/safe_browsing/realtime/BUILD.gn b/chromium/components/safe_browsing/realtime/BUILD.gn
index 6030b79a60d..2d90ba37298 100644
--- a/chromium/components/safe_browsing/realtime/BUILD.gn
+++ b/chromium/components/safe_browsing/realtime/BUILD.gn
@@ -14,5 +14,40 @@ static_library("policy_engine") {
"//components/safe_browsing:features",
"//components/safe_browsing:realtimeapi_proto",
"//components/safe_browsing/common:safe_browsing_prefs",
+ "//content/public/common:resource_type_header",
+ ]
+}
+
+static_library("url_lookup_service") {
+ sources = [
+ "url_lookup_service.cc",
+ "url_lookup_service.h",
+ ]
+
+ deps = [
+ ":policy_engine",
+ "//base:base",
+ "//components/safe_browsing:realtimeapi_proto",
+ "//components/safe_browsing/db:v4_protocol_manager_util",
+ "//content/public/browser",
+ "//url:url",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "policy_engine_unittest.cc",
+ "url_lookup_service_unittest.cc",
+ ]
+ deps = [
+ ":policy_engine",
+ ":url_lookup_service",
+ "//base/test:test_support",
+ "//components/safe_browsing:features",
+ "//content/test:test_support",
+ "//services/network:test_support",
+ "//services/network/public/cpp:cpp",
+ "//testing/gtest",
]
}
diff --git a/chromium/components/safe_browsing/realtime/policy_engine.cc b/chromium/components/safe_browsing/realtime/policy_engine.cc
index 27fbd0fd35e..be10a363276 100644
--- a/chromium/components/safe_browsing/realtime/policy_engine.cc
+++ b/chromium/components/safe_browsing/realtime/policy_engine.cc
@@ -5,29 +5,59 @@
#include "components/safe_browsing/realtime/policy_engine.h"
#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/features.h"
namespace safe_browsing {
-RealTimePolicyEngine::RealTimePolicyEngine(PrefService* pref_service)
- : pref_service_(pref_service) {}
-
-RealTimePolicyEngine::~RealTimePolicyEngine() {}
+bool RealTimePolicyEngine::is_enabled_by_pref_ = false;
// static
-bool RealTimePolicyEngine::CanFetchAllowlist() {
+bool RealTimePolicyEngine::IsFetchAllowlistEnabled() {
return base::FeatureList::IsEnabled(kRealTimeUrlLookupFetchAllowlist);
}
// static
+bool RealTimePolicyEngine::IsUrlLookupEnabled() {
+ return base::FeatureList::IsEnabled(kRealTimeUrlLookupEnabled);
+}
+
+// static
+bool RealTimePolicyEngine::IsUserOptedIn() {
+ // TODO(crbug.com/991394): Implement this soon. For now, disabled.
+ return false;
+}
+
+// static
bool RealTimePolicyEngine::CanPerformFullURLLookup() {
- // TODO(vakh): This should also take into account whether the user is eligible
- // for this service (see "Target Users" in the design doc).
- return CanFetchAllowlist() &&
- (base::FeatureList::IsEnabled(kRealTimeUrlLookupEnabled) ||
- pref_service_->GetBoolean(prefs::kSafeBrowsingRealTimeLookupEnabled));
+ // TODO(crbug.com/991394): This should take into account whether the user is
+ // eligible for this service (see "Target Users" in the design doc).
+
+ if (!IsFetchAllowlistEnabled())
+ return false;
+
+ if (is_enabled_by_pref())
+ return true;
+
+ return IsUrlLookupEnabled() && IsUserOptedIn();
+}
+
+// static
+bool RealTimePolicyEngine::CanPerformFullURLLookupForResourceType(
+ content::ResourceType resource_type) {
+ if (!CanPerformFullURLLookup())
+ return false;
+
+ UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.RT.ResourceTypes.Requested",
+ resource_type);
+ return resource_type == content::ResourceType::kMainFrame;
+}
+
+// static
+void RealTimePolicyEngine::SetEnabled(bool is_enabled) {
+ is_enabled_by_pref_ = is_enabled;
}
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/realtime/policy_engine.h b/chromium/components/safe_browsing/realtime/policy_engine.h
index 22c9b397f53..4316412c8e7 100644
--- a/chromium/components/safe_browsing/realtime/policy_engine.h
+++ b/chromium/components/safe_browsing/realtime/policy_engine.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_SAFE_BROWSING_REALTIME_POLICY_ENGINE_H_
#define COMPONENTS_SAFE_BROWSING_REALTIME_POLICY_ENGINE_H_
-class PrefService;
+#include "content/public/common/resource_type.h"
namespace safe_browsing {
@@ -13,21 +13,38 @@ namespace safe_browsing {
// feature is enabled for a given user/profile.
class RealTimePolicyEngine {
public:
- explicit RealTimePolicyEngine(PrefService* pref_service);
- ~RealTimePolicyEngine();
+ RealTimePolicyEngine() = delete;
+ ~RealTimePolicyEngine() = delete;
- // Can the high confidence allowlist be sync'd?
- static bool CanFetchAllowlist();
+ // Is the feature to sync high confidence allowlist enabled?
+ static bool IsFetchAllowlistEnabled();
+
+ // Return true if the feature to enable full URL lookups is enabled and the
+ // allowlist fetch is enabled, |resource_type| is kMainFrame.
+ static bool CanPerformFullURLLookupForResourceType(
+ content::ResourceType resource_type);
// Return true if the feature to enable full URL lookups is enabled and the
// allowlist fetch is enabled.
- bool CanPerformFullURLLookup();
+ static bool CanPerformFullURLLookup();
+
+ static bool is_enabled_by_pref() { return is_enabled_by_pref_; }
+ friend class SafeBrowsingService;
private:
- // Does not indicate ownership of |pref_service_|. The owner of the
- // RealTimePolicyEngine is responsible for ensuring |pref_service_| outlasts
- // this.
- PrefService* pref_service_;
+ // Is the feature to perform real-time URL lookup enabled?
+ static bool IsUrlLookupEnabled();
+
+ // Is user opted-in to the feature?
+ static bool IsUserOptedIn();
+
+ // TODO(crbug.com/991394): This is a temporary way of checking whether the
+ // real-time lookup is enabled for any active profile. This must be fixed
+ // before full launch.
+ static bool is_enabled_by_pref_;
+ static void SetEnabled(bool is_enabled);
+
+ friend class RealTimePolicyEngineTest;
}; // class RealTimePolicyEngine
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/realtime/policy_engine_unittest.cc b/chromium/components/safe_browsing/realtime/policy_engine_unittest.cc
new file mode 100644
index 00000000000..55a0329acf2
--- /dev/null
+++ b/chromium/components/safe_browsing/realtime/policy_engine_unittest.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 "components/safe_browsing/realtime/policy_engine.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "components/safe_browsing/features.h"
+#include "testing/platform_test.h"
+
+namespace safe_browsing {
+
+class RealTimePolicyEngineTest : public PlatformTest {
+ public:
+ void ForceSetRealTimeLookupPolicy(bool is_enabled) {
+ RealTimePolicyEngine::SetEnabled(is_enabled);
+ }
+
+ bool IsUserOptedIn() { return RealTimePolicyEngine::IsUserOptedIn(); }
+};
+
+TEST_F(RealTimePolicyEngineTest,
+ TestCanPerformFullURLLookup_DisabledFetchAllowlist) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(kRealTimeUrlLookupFetchAllowlist);
+ EXPECT_FALSE(RealTimePolicyEngine::CanPerformFullURLLookup());
+}
+
+TEST_F(RealTimePolicyEngineTest, TestCanPerformFullURLLookup_EnabledByPolicy) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(kRealTimeUrlLookupFetchAllowlist);
+ ForceSetRealTimeLookupPolicy(/* is_enabled= */ true);
+ ASSERT_TRUE(RealTimePolicyEngine::is_enabled_by_pref());
+ EXPECT_TRUE(RealTimePolicyEngine::CanPerformFullURLLookup());
+}
+
+TEST_F(RealTimePolicyEngineTest,
+ TestCanPerformFullURLLookup_DisabledUrlLookup) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(kRealTimeUrlLookupEnabled);
+ EXPECT_FALSE(RealTimePolicyEngine::CanPerformFullURLLookup());
+}
+
+TEST_F(RealTimePolicyEngineTest,
+ TestCanPerformFullURLLookup_DisabledUserOptin) {
+ // This is hardcoded as false for now so ensure that.
+ ASSERT_FALSE(IsUserOptedIn());
+}
+
+TEST_F(RealTimePolicyEngineTest,
+ TestCanPerformFullURLLookup_EnabledMainFrameOnly) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(kRealTimeUrlLookupFetchAllowlist);
+ ForceSetRealTimeLookupPolicy(/* is_enabled= */ true);
+ ASSERT_TRUE(RealTimePolicyEngine::is_enabled_by_pref());
+
+ for (int i = 0; i <= static_cast<int>(content::ResourceType::kMaxValue);
+ i++) {
+ content::ResourceType resource_type = static_cast<content::ResourceType>(i);
+ bool enabled = RealTimePolicyEngine::CanPerformFullURLLookupForResourceType(
+ resource_type);
+ switch (resource_type) {
+ case content::ResourceType::kMainFrame:
+ EXPECT_TRUE(enabled);
+ break;
+ default:
+ EXPECT_FALSE(enabled);
+ break;
+ }
+ }
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/realtime/url_lookup_service.cc b/chromium/components/safe_browsing/realtime/url_lookup_service.cc
new file mode 100644
index 00000000000..c40f8b3fc22
--- /dev/null
+++ b/chromium/components/safe_browsing/realtime/url_lookup_service.cc
@@ -0,0 +1,180 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/realtime/url_lookup_service.h"
+
+#include "base/base64url.h"
+#include "base/time/time.h"
+#include "components/safe_browsing/db/v4_protocol_manager_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+
+namespace safe_browsing {
+
+namespace {
+
+const char kRealTimeLookupUrlPrefix[] =
+ "https://safebrowsing.google.com/safebrowsing/clientreport/realtime";
+
+const size_t kMaxFailuresToEnforceBackoff = 3;
+
+const size_t kBackOffResetDurationInSeconds = 5 * 60; // 5 minutes.
+
+const size_t kURLLookupTimeoutDurationInSeconds = 1 * 60; // 1 minute.
+
+} // namespace
+
+RealTimeUrlLookupService::RealTimeUrlLookupService(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : url_loader_factory_(url_loader_factory) {}
+
+void RealTimeUrlLookupService::StartLookup(const GURL& url,
+ RTLookupResponseCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(url.is_valid());
+
+ RTLookupRequest request;
+ request.set_url(url.spec());
+ request.set_lookup_type(RTLookupRequest::NAVIGATION);
+ std::string req_data, req_base64;
+ request.SerializeToString(&req_data);
+ base::Base64UrlEncode(req_data, base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &req_base64);
+ // TODO(vakh): Add the correct chrome_policy field below.
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("safe_browsing_realtime_url_lookup",
+ R"(
+ semantics {
+ sender: "Safe Browsing"
+ description:
+ "When Safe Browsing can't detect that a URL is safe based on its "
+ "local database, it sends the top-level URL to Google to verify it "
+ "before showing a warning to the user."
+ trigger:
+ "When a main frame URL fails to match the local hash-prefix "
+ "database of known safe URLs and a valid result from a prior "
+ "lookup is not already cached, this will be sent."
+ data: "The main frame URL that did not match the local safelist."
+ destination: GOOGLE_OWNED_SERVICE
+ }
+ policy {
+ cookies_allowed: YES
+ cookies_store: "Safe Browsing cookie store"
+ setting:
+ "Users can disable Safe Browsing real time URL checks by "
+ "unchecking 'Protect you and your device from dangerous sites' in "
+ "Chromium settings under Privacy, or by unchecking 'Make searches "
+ "and browsing better (Sends URLs of pages you visit to Google)' in "
+ "Chromium settings under Privacy."
+ chrome_policy {
+ SafeBrowsingEnabled {
+ policy_options {mode: MANDATORY}
+ SafeBrowsingEnabled: false
+ }
+ }
+ })");
+
+ auto resource_request = std::make_unique<network::ResourceRequest>();
+ resource_request->url = GURL(kRealTimeLookupUrlPrefix);
+ resource_request->load_flags = net::LOAD_DISABLE_CACHE;
+ resource_request->method = "POST";
+
+ std::unique_ptr<network::SimpleURLLoader> owned_loader =
+ network::SimpleURLLoader::Create(std::move(resource_request),
+ traffic_annotation);
+ network::SimpleURLLoader* loader = owned_loader.get();
+ owned_loader->AttachStringForUpload(req_data, "application/octet-stream");
+ owned_loader->SetTimeoutDuration(
+ base::TimeDelta::FromSeconds(kURLLookupTimeoutDurationInSeconds));
+ owned_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+ url_loader_factory_.get(),
+ base::BindOnce(&RealTimeUrlLookupService::OnURLLoaderComplete,
+ GetWeakPtr(), loader));
+
+ pending_requests_[owned_loader.release()] = std::move(callback);
+}
+
+RealTimeUrlLookupService::~RealTimeUrlLookupService() {
+ for (auto& pending : pending_requests_) {
+ // An empty response is treated as safe.
+ auto response = std::make_unique<RTLookupResponse>();
+ std::move(pending.second).Run(std::move(response));
+ delete pending.first;
+ }
+ pending_requests_.clear();
+}
+
+void RealTimeUrlLookupService::OnURLLoaderComplete(
+ network::SimpleURLLoader* url_loader,
+ std::unique_ptr<std::string> response_body) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ auto it = pending_requests_.find(url_loader);
+ DCHECK(it != pending_requests_.end()) << "Request not found";
+
+ int net_error = url_loader->NetError();
+ int response_code = 0;
+ if (url_loader->ResponseInfo() && url_loader->ResponseInfo()->headers)
+ response_code = url_loader->ResponseInfo()->headers->response_code();
+ V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode(
+ "SafeBrowsing.RT.Network.Result", net_error, response_code);
+
+ auto response = std::make_unique<RTLookupResponse>();
+ bool success = (net_error == net::OK) && (response_code == net::HTTP_OK) &&
+ response->ParseFromString(*response_body);
+ success ? HandleLookupSuccess() : HandleLookupError();
+
+ std::move(it->second).Run(std::move(response));
+ delete it->first;
+ pending_requests_.erase(it);
+}
+
+bool RealTimeUrlLookupService::CanCheckUrl(const GURL& url) const {
+ return url.SchemeIsHTTPOrHTTPS();
+}
+
+void RealTimeUrlLookupService::ExitBackoff() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ ResetFailures();
+}
+
+void RealTimeUrlLookupService::HandleLookupError() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ consecutive_failures_++;
+
+ if (IsInBackoffMode()) {
+ reset_backoff_timer_.Stop();
+ reset_backoff_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(kBackOffResetDurationInSeconds),
+ this, &RealTimeUrlLookupService::ExitBackoff);
+ }
+}
+
+void RealTimeUrlLookupService::HandleLookupSuccess() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ ResetFailures();
+}
+
+bool RealTimeUrlLookupService::IsInBackoffMode() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ return consecutive_failures_ >= kMaxFailuresToEnforceBackoff;
+}
+
+void RealTimeUrlLookupService::ResetFailures() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ consecutive_failures_ = 0;
+ reset_backoff_timer_.Stop();
+}
+
+base::WeakPtr<RealTimeUrlLookupService> RealTimeUrlLookupService::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/realtime/url_lookup_service.h b/chromium/components/safe_browsing/realtime/url_lookup_service.h
new file mode 100644
index 00000000000..7cb6423c5c6
--- /dev/null
+++ b/chromium/components/safe_browsing/realtime/url_lookup_service.h
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SAFE_BROWSING_REALTIME_URL_LOOKUP_SERVICE_H_
+#define COMPONENTS_SAFE_BROWSING_REALTIME_URL_LOOKUP_SERVICE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "components/safe_browsing/proto/realtimeapi.pb.h"
+#include "url/gurl.h"
+
+namespace network {
+class SimpleURLLoader;
+class SharedURLLoaderFactory;
+} // namespace network
+
+namespace safe_browsing {
+
+using RTLookupResponseCallback =
+ base::OnceCallback<void(std::unique_ptr<RTLookupResponse>)>;
+
+// This class implements the logic to decide whether the real time lookup
+// feature is enabled for a given user/profile.
+class RealTimeUrlLookupService {
+ public:
+ explicit RealTimeUrlLookupService(
+ scoped_refptr<network::SharedURLLoaderFactory>);
+ ~RealTimeUrlLookupService();
+
+ // Returns true if |url|'s scheme can be checked.
+ bool CanCheckUrl(const GURL& url) const;
+
+ // Returns true if the real time lookups are currently in backoff mode due to
+ // too many prior errors. If this happens, the checking falls back to
+ // local hash-based method.
+ bool IsInBackoffMode();
+
+ // Start the full URL lookup for |url| and call |callback| on the same thread
+ // when done.
+ void StartLookup(const GURL& url, RTLookupResponseCallback callback);
+
+ private:
+ using PendingRTLookupRequests =
+ base::flat_map<network::SimpleURLLoader*, RTLookupResponseCallback>;
+
+ // Called when the request to remote endpoint fails. May initiate or extend
+ // backoff.
+ void HandleLookupError();
+
+ // Called when the request to remote endpoint succeeds. Resets error count and
+ // ends backoff.
+ void HandleLookupSuccess();
+
+ // Resets the error count and ends backoff mode. Functionally same as
+ // |HandleLookupSuccess| for now.
+ void ResetFailures();
+
+ // Called when the timer to end backoff mode fires. Resets error count.
+ void ExitBackoff();
+
+ // Called when the response from the real-time lookup remote endpoint is
+ // received.
+ void OnURLLoaderComplete(network::SimpleURLLoader* url_loader,
+ std::unique_ptr<std::string> response_body);
+
+ // Helper function to return a weak pointer.
+ base::WeakPtr<RealTimeUrlLookupService> GetWeakPtr();
+
+ PendingRTLookupRequests pending_requests_;
+
+ // Count of consecutive failures to complete URL lookup requests. When it
+ // reaches |kMaxFailuresToEnforceBackoff|, we enter the backoff mode. It gets
+ // reset when we complete a lookup successfully or when the backoff reset
+ // timer fires.
+ size_t consecutive_failures_ = 0;
+
+ // Started when we enter backoff. We exit the backoff mode when this fires.
+ base::OneShotTimer reset_backoff_timer_;
+
+ // The URLLoaderFactory we use to issue network requests.
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+ friend class RealTimeUrlLookupServiceTest;
+
+ base::WeakPtrFactory<RealTimeUrlLookupService> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(RealTimeUrlLookupService);
+
+}; // class RealTimeUrlLookupService
+
+} // namespace safe_browsing
+
+#endif // COMPONENTS_SAFE_BROWSING_REALTIME_URL_LOOKUP_SERVICE_H_
diff --git a/chromium/components/safe_browsing/realtime/url_lookup_service_unittest.cc b/chromium/components/safe_browsing/realtime/url_lookup_service_unittest.cc
new file mode 100644
index 00000000000..155b66ed234
--- /dev/null
+++ b/chromium/components/safe_browsing/realtime/url_lookup_service_unittest.cc
@@ -0,0 +1,111 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/realtime/url_lookup_service.h"
+
+#include "base/test/task_environment.h"
+#include "content/public/test/browser_task_environment.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/platform_test.h"
+
+namespace safe_browsing {
+
+class RealTimeUrlLookupServiceTest : public PlatformTest {
+ public:
+ RealTimeUrlLookupServiceTest()
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+ void SetUp() override {
+ PlatformTest::SetUp();
+
+ test_shared_loader_factory_ =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &test_url_loader_factory_);
+
+ rt_service_ =
+ std::make_unique<RealTimeUrlLookupService>(test_shared_loader_factory_);
+ }
+
+ void HandleLookupError() { rt_service_->HandleLookupError(); }
+ void HandleLookupSuccess() { rt_service_->HandleLookupSuccess(); }
+ bool IsInBackoffMode() { return rt_service_->IsInBackoffMode(); }
+
+ network::TestURLLoaderFactory test_url_loader_factory_;
+ scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
+ std::unique_ptr<RealTimeUrlLookupService> rt_service_;
+ content::BrowserTaskEnvironment task_environment_;
+};
+
+TEST_F(RealTimeUrlLookupServiceTest, TestBackoffAndTimerReset) {
+ // Not in backoff at the beginning.
+ ASSERT_FALSE(IsInBackoffMode());
+
+ // Failure 1: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 2: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 3: Entered backoff.
+ HandleLookupError();
+ EXPECT_TRUE(IsInBackoffMode());
+
+ // Backoff not reset after 1 second.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ EXPECT_TRUE(IsInBackoffMode());
+
+ // Backoff not reset after 299 seconds.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(298));
+ EXPECT_TRUE(IsInBackoffMode());
+
+ // Backoff should have been reset after 300 seconds.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ EXPECT_FALSE(IsInBackoffMode());
+}
+
+TEST_F(RealTimeUrlLookupServiceTest, TestBackoffAndLookupSuccessReset) {
+ // Not in backoff at the beginning.
+ ASSERT_FALSE(IsInBackoffMode());
+
+ // Failure 1: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Lookup success resets the backoff counter.
+ HandleLookupSuccess();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 1: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 2: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Lookup success resets the backoff counter.
+ HandleLookupSuccess();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 1: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 2: No backoff.
+ HandleLookupError();
+ EXPECT_FALSE(IsInBackoffMode());
+
+ // Failure 3: Entered backoff.
+ HandleLookupError();
+ EXPECT_TRUE(IsInBackoffMode());
+
+ // Lookup success resets the backoff counter.
+ HandleLookupSuccess();
+ EXPECT_FALSE(IsInBackoffMode());
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/renderer/BUILD.gn b/chromium/components/safe_browsing/renderer/BUILD.gn
index 33981c7560d..7c600dd0f73 100644
--- a/chromium/components/safe_browsing/renderer/BUILD.gn
+++ b/chromium/components/safe_browsing/renderer/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/features.gni")
+import("//components/safe_browsing/buildflags.gni")
source_set("renderer") {
if (safe_browsing_mode != 0) {
diff --git a/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.h b/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.h
index f63d9480360..89b2f47d262 100644
--- a/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.h
+++ b/chromium/components/safe_browsing/renderer/renderer_url_loader_throttle.h
@@ -9,8 +9,8 @@
#include "base/memory/weak_ptr.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
-#include "content/public/common/url_loader_throttle.h"
#include "mojo/public/cpp/bindings/binding_set.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "url/gurl.h"
namespace safe_browsing {
@@ -19,7 +19,7 @@ namespace safe_browsing {
// SafeBrowsing and determine whether a URL and its redirect URLs are safe to
// load. It defers response processing until all URL checks are completed;
// cancels the load if any URLs turn out to be bad.
-class RendererURLLoaderThrottle : public content::URLLoaderThrottle,
+class RendererURLLoaderThrottle : public blink::URLLoaderThrottle,
public mojom::UrlCheckNotifier {
public:
// |safe_browsing| must stay alive until WillStartRequest() (if it is called)
@@ -30,7 +30,7 @@ class RendererURLLoaderThrottle : public content::URLLoaderThrottle,
~RendererURLLoaderThrottle() override;
private:
- // content::URLLoaderThrottle implementation.
+ // blink::URLLoaderThrottle implementation.
void DetachFromCurrentSequence() override;
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override;
diff --git a/chromium/components/safe_browsing/renderer/threat_dom_details.cc b/chromium/components/safe_browsing/renderer/threat_dom_details.cc
index 428653074b7..b7d971f24f0 100644
--- a/chromium/components/safe_browsing/renderer/threat_dom_details.cc
+++ b/chromium/components/safe_browsing/renderer/threat_dom_details.cc
@@ -327,20 +327,16 @@ void ThreatDOMDetails::ExtractResources(
ElementToNodeMap element_to_node_map;
blink::WebElementCollection elements = document.All();
blink::WebElement element = elements.FirstItem();
- bool max_nodes_exceeded = false;
for (; !element.IsNull(); element = elements.NextItem()) {
if (ShouldHandleElement(element, tag_and_attributes_list_)) {
HandleElement(element, tag_and_attributes_list_, details_node.get(),
resources, &element_to_node_map);
if (resources->size() >= kMaxNodes) {
// We have reached kMaxNodes, exit early.
- max_nodes_exceeded = true;
break;
}
}
}
- UMA_HISTOGRAM_BOOLEAN("SafeBrowsing.ThreatReport.MaxNodesExceededInFrame",
- max_nodes_exceeded);
resources->push_back(std::move(details_node));
}
diff --git a/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc b/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc
index 00d595243c0..8bd3fc96bb3 100644
--- a/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc
+++ b/chromium/components/safe_browsing/renderer/websocket_sb_handshake_throttle_unittest.cc
@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "content/public/common/resource_type.h"
#include "ipc/ipc_message.h"
@@ -109,7 +109,7 @@ class WebSocketSBHandshakeThrottleTest : public ::testing::Test {
safe_browsing_ptr_.get(), MSG_ROUTING_NONE);
}
- base::test::ScopedTaskEnvironment message_loop_;
+ base::test::TaskEnvironment message_loop_;
FakeSafeBrowsing safe_browsing_;
mojo::Binding<mojom::SafeBrowsing> mojo_binding_;
mojom::SafeBrowsingPtr safe_browsing_ptr_;
diff --git a/chromium/components/safe_browsing/triggers/ad_popup_trigger.cc b/chromium/components/safe_browsing/triggers/ad_popup_trigger.cc
index 0aaece8b13e..b4d1f6dcc74 100644
--- a/chromium/components/safe_browsing/triggers/ad_popup_trigger.cc
+++ b/chromium/components/safe_browsing/triggers/ad_popup_trigger.cc
@@ -66,8 +66,8 @@ AdPopupTrigger::AdPopupTrigger(
prefs_(prefs),
url_loader_factory_(url_loader_factory),
history_service_(history_service),
- task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI})) {}
+ task_runner_(
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})) {}
AdPopupTrigger::~AdPopupTrigger() {}
diff --git a/chromium/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc b/chromium/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc
index c6549214e58..53a44968570 100644
--- a/chromium/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc
@@ -13,8 +13,8 @@
#include "components/safe_browsing/triggers/mock_trigger_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock-generated-function-mockers.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/chromium/components/safe_browsing/triggers/ad_redirect_trigger.cc b/chromium/components/safe_browsing/triggers/ad_redirect_trigger.cc
index 140d69d41e5..a70f466e57f 100644
--- a/chromium/components/safe_browsing/triggers/ad_redirect_trigger.cc
+++ b/chromium/components/safe_browsing/triggers/ad_redirect_trigger.cc
@@ -42,6 +42,14 @@ const int64_t kMinAdRedirectCollectionStartDelayMilliseconds = 500;
const char kAdRedirectTriggerActionMetricName[] =
"SafeBrowsing.Triggers.AdRedirect.Action";
+namespace {
+
+void RecordAdRedirectTriggerAction(AdRedirectTriggerAction action) {
+ UMA_HISTOGRAM_ENUMERATION(kAdRedirectTriggerActionMetricName, action);
+}
+
+} // namespace
+
AdRedirectTrigger::AdRedirectTrigger(
content::WebContents* web_contents,
TriggerManager* trigger_manager,
@@ -57,8 +65,8 @@ AdRedirectTrigger::AdRedirectTrigger(
prefs_(prefs),
url_loader_factory_(url_loader_factory),
history_service_(history_service),
- task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI})) {}
+ task_runner_(
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})) {}
AdRedirectTrigger::~AdRedirectTrigger() {}
@@ -92,12 +100,10 @@ void AdRedirectTrigger::CreateAdRedirectReport() {
TriggerType::AD_REDIRECT, web_contents_, resource,
url_loader_factory_, history_service_, error_options, &reason)) {
if (reason == TriggerManagerReason::DAILY_QUOTA_EXCEEDED) {
- UMA_HISTOGRAM_ENUMERATION(
- kAdRedirectTriggerActionMetricName,
+ RecordAdRedirectTriggerAction(
AdRedirectTriggerAction::REDIRECT_DAILY_QUOTA_EXCEEDED);
} else {
- UMA_HISTOGRAM_ENUMERATION(
- kAdRedirectTriggerActionMetricName,
+ RecordAdRedirectTriggerAction(
AdRedirectTriggerAction::REDIRECT_COULD_NOT_START_REPORT);
}
return;
@@ -114,21 +120,19 @@ void AdRedirectTrigger::CreateAdRedirectReport() {
base::Unretained(web_contents_), base::TimeDelta(),
/*did_proceed=*/false, /*num_visits=*/0, error_options),
base::TimeDelta::FromMilliseconds(finish_report_delay_ms_));
- UMA_HISTOGRAM_ENUMERATION(kAdRedirectTriggerActionMetricName,
- AdRedirectTriggerAction::AD_REDIRECT);
+ RecordAdRedirectTriggerAction(AdRedirectTriggerAction::AD_REDIRECT);
}
void AdRedirectTrigger::OnDidBlockNavigation(const GURL& initiator_url) {
- UMA_HISTOGRAM_ENUMERATION(kAdRedirectTriggerActionMetricName,
- AdRedirectTriggerAction::REDIRECT_CHECK);
+ RecordAdRedirectTriggerAction(AdRedirectTriggerAction::REDIRECT_CHECK);
content::RenderFrameHost* initiator_frame =
web_contents_->GetOriginalOpener();
// Use focused frame as proxy if there is no opener.
if (!initiator_frame)
initiator_frame = web_contents_->GetFocusedFrame();
if (!DetectGoogleAd(initiator_frame, initiator_url)) {
- UMA_HISTOGRAM_ENUMERATION(kAdRedirectTriggerActionMetricName,
- AdRedirectTriggerAction::REDIRECT_NO_GOOGLE_AD);
+ RecordAdRedirectTriggerAction(
+ AdRedirectTriggerAction::REDIRECT_NO_GOOGLE_AD);
return;
}
// Create a report after a short delay.
diff --git a/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc b/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc
index 75fa07f66fd..c6c71ffed94 100644
--- a/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc
+++ b/chromium/components/safe_browsing/triggers/ad_sampler_trigger.cc
@@ -92,8 +92,8 @@ AdSamplerTrigger::AdSamplerTrigger(
prefs_(prefs),
url_loader_factory_(url_loader_factory),
history_service_(history_service),
- task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI})) {}
+ task_runner_(
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})) {}
AdSamplerTrigger::~AdSamplerTrigger() {}
diff --git a/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc b/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc
index 90be0b9797d..e88b71b3c83 100644
--- a/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/ad_sampler_trigger_unittest.cc
@@ -12,8 +12,8 @@
#include "components/safe_browsing/triggers/mock_trigger_manager.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gmock/include/gmock/gmock-generated-function-mockers.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -224,7 +224,7 @@ TEST(AdSamplerTriggerTestFinch, FrequencyDenominatorFeature) {
// Make sure that setting the frequency denominator via Finch params works as
// expected, and that the default frequency is used when no Finch config is
// given.
- content::TestBrowserThreadBundle thread_bundle;
+ content::BrowserTaskEnvironment task_environment;
AdSamplerTrigger trigger_default(nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(kAdSamplerDefaultFrequency,
trigger_default.sampler_frequency_denominator_);
diff --git a/chromium/components/safe_browsing/triggers/suspicious_site_trigger.cc b/chromium/components/safe_browsing/triggers/suspicious_site_trigger.cc
index ca66d9f96b3..a0fc823a9e9 100644
--- a/chromium/components/safe_browsing/triggers/suspicious_site_trigger.cc
+++ b/chromium/components/safe_browsing/triggers/suspicious_site_trigger.cc
@@ -66,8 +66,8 @@ SuspiciousSiteTrigger::SuspiciousSiteTrigger(
prefs_(prefs),
url_loader_factory_(url_loader_factory),
history_service_(history_service),
- task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
- {content::BrowserThread::UI})) {}
+ task_runner_(
+ base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})) {}
SuspiciousSiteTrigger::~SuspiciousSiteTrigger() {}
diff --git a/chromium/components/safe_browsing/triggers/suspicious_site_trigger_unittest.cc b/chromium/components/safe_browsing/triggers/suspicious_site_trigger_unittest.cc
index 17f8fdb09fd..445469b6896 100644
--- a/chromium/components/safe_browsing/triggers/suspicious_site_trigger_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/suspicious_site_trigger_unittest.cc
@@ -11,8 +11,8 @@
#include "components/prefs/testing_pref_service.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/triggers/mock_trigger_manager.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -68,6 +68,7 @@ class SuspiciousSiteTriggerTest : public content::RenderViewHostTestHarness {
GURL gurl(url);
auto navigation_simulator =
NavigationSimulator::CreateRendererInitiated(gurl, frame);
+ navigation_simulator->SetKeepLoading(true);
navigation_simulator->Commit();
RenderFrameHost* final_frame_host =
navigation_simulator->GetFinalRenderFrameHost();
diff --git a/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc b/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc
index 359d7454fad..486af5b6121 100644
--- a/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/trigger_manager_unittest.cc
@@ -12,8 +12,8 @@
#include "components/safe_browsing/browser/threat_details.h"
#include "components/safe_browsing/features.h"
#include "components/safe_browsing/triggers/trigger_throttler.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_web_contents_factory.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -151,7 +151,7 @@ class TriggerManagerTest : public ::testing::Test {
private:
TriggerManager trigger_manager_;
MockThreatDetailsFactory mock_threat_details_factory_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
content::TestWebContentsFactory web_contents_factory_;
TestingPrefServiceSimple pref_service_;
diff --git a/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc b/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc
index 1ef5be965f8..39986659cfd 100644
--- a/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc
+++ b/chromium/components/safe_browsing/triggers/trigger_throttler_unittest.cc
@@ -4,7 +4,6 @@
#include "components/safe_browsing/triggers/trigger_throttler.h"
-#include "base/metrics/field_trial_params.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
@@ -206,25 +205,19 @@ TEST_F(TriggerThrottlerTest, TriggerQuotaPersistence) {
class TriggerThrottlerTestFinch : public ::testing::Test {
public:
- std::unique_ptr<base::FeatureList> SetupQuotaInFinch(
- const TriggerType trigger_type,
- const std::string& group_name,
- int quota) {
- std::string feature_name = "";
+ void SetupQuotaParams(const TriggerType trigger_type,
+ const std::string& group_name,
+ int quota,
+ base::test::ScopedFeatureList* scoped_feature_list) {
+ const base::Feature* feature = nullptr;
std::string param_name = "";
- GetFeatureAndParamForTrigger(trigger_type, &feature_name, &param_name);
+ GetFeatureAndParamForTrigger(trigger_type, &feature, &param_name);
- base::FieldTrial* trial =
- base::FieldTrialList::CreateFieldTrial(feature_name, group_name);
- std::map<std::string, std::string> feature_params;
+ base::FieldTrialParams feature_params;
feature_params[param_name] =
GetQuotaParamValueForTrigger(trigger_type, quota);
- base::AssociateFieldTrialParams(feature_name, group_name, feature_params);
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(feature_name, std::string());
- feature_list->AssociateReportingFieldTrial(
- feature_name, base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
- return feature_list;
+ scoped_feature_list->InitAndEnableFeatureWithParameters(*feature,
+ feature_params);
}
size_t GetDailyQuotaForTrigger(const TriggerThrottler& throttler,
@@ -234,16 +227,16 @@ class TriggerThrottlerTestFinch : public ::testing::Test {
private:
void GetFeatureAndParamForTrigger(const TriggerType trigger_type,
- std::string* out_feature,
+ const base::Feature** out_feature,
std::string* out_param) {
switch (trigger_type) {
case TriggerType::AD_SAMPLE:
- *out_feature = safe_browsing::kTriggerThrottlerDailyQuotaFeature.name;
+ *out_feature = &safe_browsing::kTriggerThrottlerDailyQuotaFeature;
*out_param = safe_browsing::kTriggerTypeAndQuotaParam;
break;
case TriggerType::SUSPICIOUS_SITE:
- *out_feature = safe_browsing::kSuspiciousSiteTriggerQuotaFeature.name;
+ *out_feature = &safe_browsing::kSuspiciousSiteTriggerQuotaFeature;
*out_param = safe_browsing::kSuspiciousSiteTriggerQuotaParam;
break;
@@ -263,10 +256,9 @@ class TriggerThrottlerTestFinch : public ::testing::Test {
};
TEST_F(TriggerThrottlerTestFinch, ConfigureQuotaViaFinch) {
- base::FieldTrialList field_trial_list(nullptr);
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatureList(SetupQuotaInFinch(
- TriggerType::AD_SAMPLE, "Group_ConfigureQuotaViaFinch", 3));
+ SetupQuotaParams(TriggerType::AD_SAMPLE, "Group_ConfigureQuotaViaFinch", 3,
+ &scoped_feature_list);
// Make sure that setting the quota param via Finch params works as expected.
// The throttler has been configured (above) to allow ad samples to fire three
@@ -293,10 +285,9 @@ TEST_F(TriggerThrottlerTestFinch, AdSamplerDefaultQuota) {
GetDailyQuotaForTrigger(throttler_default, TriggerType::AD_SAMPLE));
EXPECT_TRUE(throttler_default.TriggerCanFire(TriggerType::AD_SAMPLE));
- base::FieldTrialList field_trial_list(nullptr);
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatureList(SetupQuotaInFinch(
- TriggerType::AD_SAMPLE, "Group_AdSamplerDefaultQuota", 4));
+ SetupQuotaParams(TriggerType::AD_SAMPLE, "Group_AdSamplerDefaultQuota", 4,
+ &scoped_feature_list);
TriggerThrottler throttler_finch(nullptr);
EXPECT_EQ(4u,
GetDailyQuotaForTrigger(throttler_finch, TriggerType::AD_SAMPLE));
@@ -310,11 +301,10 @@ TEST_F(TriggerThrottlerTestFinch, SuspiciousSiteTriggerDefaultQuota) {
GetDailyQuotaForTrigger(throttler_default, TriggerType::SUSPICIOUS_SITE));
EXPECT_TRUE(throttler_default.TriggerCanFire(TriggerType::SUSPICIOUS_SITE));
- base::FieldTrialList field_trial_list(nullptr);
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatureList(
- SetupQuotaInFinch(TriggerType::SUSPICIOUS_SITE,
- "Group_SuspiciousSiteTriggerDefaultQuota", 7));
+ SetupQuotaParams(TriggerType::SUSPICIOUS_SITE,
+ "Group_SuspiciousSiteTriggerDefaultQuota", 7,
+ &scoped_feature_list);
TriggerThrottler throttler_finch(nullptr);
EXPECT_EQ(7u, GetDailyQuotaForTrigger(throttler_finch,
TriggerType::SUSPICIOUS_SITE));
diff --git a/chromium/components/safe_browsing/verdict_cache_manager.cc b/chromium/components/safe_browsing/verdict_cache_manager.cc
index c31a5fd1c4b..fd5ac3dabcf 100644
--- a/chromium/components/safe_browsing/verdict_cache_manager.cc
+++ b/chromium/components/safe_browsing/verdict_cache_manager.cc
@@ -163,7 +163,7 @@ VerdictCacheManager::~VerdictCacheManager() {
void VerdictCacheManager::CachePhishGuardVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
const LoginReputationClientResponse& verdict,
const base::Time& receive_time) {
DCHECK(content_settings_);
@@ -198,7 +198,9 @@ void VerdictCacheManager::CachePhishGuardVerdict(
}
} else {
std::string password_type_key = base::NumberToString(
- static_cast<std::underlying_type_t<PasswordType>>(password_type));
+ static_cast<
+ std::underlying_type_t<ReusedPasswordAccountType::AccountType>>(
+ password_type.account_type()));
verdict_dictionary = cache_dictionary->FindKeyOfType(
password_type_key, base::Value::Type::DICTIONARY);
if (!verdict_dictionary) {
@@ -226,7 +228,7 @@ LoginReputationClientResponse::VerdictType
VerdictCacheManager::GetCachedPhishGuardVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse* out_response) {
DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
@@ -249,7 +251,9 @@ VerdictCacheManager::GetCachedPhishGuardVerdict(
return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
} else {
verdict_dictionary = cache_dictionary->FindKey(base::NumberToString(
- static_cast<std::underlying_type_t<PasswordType>>(password_type)));
+ static_cast<
+ std::underlying_type_t<ReusedPasswordAccountType::AccountType>>(
+ password_type.account_type())));
if (!verdict_dictionary)
return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
}
@@ -385,12 +389,11 @@ void VerdictCacheManager::CleanUpExpiredVerdicts() {
void VerdictCacheManager::OnURLsDeleted(
history::HistoryService* history_service,
const history::DeletionInfo& deletion_info) {
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindRepeating(
- &VerdictCacheManager::RemoveContentSettingsOnURLsDeleted,
- GetWeakPtr(), deletion_info.IsAllHistory(),
- deletion_info.deleted_rows()));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindRepeating(
+ &VerdictCacheManager::RemoveContentSettingsOnURLsDeleted,
+ GetWeakPtr(), deletion_info.IsAllHistory(),
+ deletion_info.deleted_rows()));
}
// Overridden from history::HistoryServiceObserver.
diff --git a/chromium/components/safe_browsing/verdict_cache_manager.h b/chromium/components/safe_browsing/verdict_cache_manager.h
index d45aafda92c..f4ac829be5d 100644
--- a/chromium/components/safe_browsing/verdict_cache_manager.h
+++ b/chromium/components/safe_browsing/verdict_cache_manager.h
@@ -13,7 +13,6 @@
#include "base/values.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/history/core/browser/history_service_observer.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/safe_browsing/proto/csd.pb.h"
#include "url/gurl.h"
@@ -25,7 +24,8 @@ class HostContentSettingsMap;
namespace safe_browsing {
-using password_manager::metrics_util::PasswordType;
+using ReusedPasswordAccountType =
+ LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType;
class VerdictCacheManager : public history::HistoryServiceObserver {
public:
@@ -48,7 +48,7 @@ class VerdictCacheManager : public history::HistoryServiceObserver {
void CachePhishGuardVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
const LoginReputationClientResponse& verdict,
const base::Time& receive_time);
@@ -58,7 +58,7 @@ class VerdictCacheManager : public history::HistoryServiceObserver {
LoginReputationClientResponse::VerdictType GetCachedPhishGuardVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger_type,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse* out_response);
// Gets the total number of verdicts of the specified |trigger_type| we cached
diff --git a/chromium/components/safe_browsing/verdict_cache_manager_unittest.cc b/chromium/components/safe_browsing/verdict_cache_manager_unittest.cc
index 900fbbb09f5..2182da6cf93 100644
--- a/chromium/components/safe_browsing/verdict_cache_manager_unittest.cc
+++ b/chromium/components/safe_browsing/verdict_cache_manager_unittest.cc
@@ -10,7 +10,7 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/safe_browsing/proto/csd.pb.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace safe_browsing {
@@ -37,7 +37,7 @@ class VerdictCacheManagerTest : public ::testing::Test {
void CachePhishGuardVerdict(
const GURL& url,
LoginReputationClientRequest::TriggerType trigger,
- PasswordType password_type,
+ ReusedPasswordAccountType password_type,
LoginReputationClientResponse::VerdictType verdict,
int cache_duration_sec,
const std::string& cache_expression,
@@ -56,73 +56,79 @@ class VerdictCacheManagerTest : public ::testing::Test {
scoped_refptr<HostContentSettingsMap> content_setting_map_;
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable test_pref_service_;
};
TEST_F(VerdictCacheManagerTest, TestCanRetrieveCachedVerdict) {
GURL url("https://www.google.com/");
-
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
+ password_type.set_is_account_syncing(true);
LoginReputationClientResponse cached_verdict;
cached_verdict.set_cache_expression("www.google.com/");
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
+ password_type, &cached_verdict));
CachePhishGuardVerdict(url,
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::SAFE, 60,
+ password_type, LoginReputationClientResponse::SAFE, 60,
"www.google.com/", base::Time::Now());
EXPECT_EQ(LoginReputationClientResponse::SAFE,
cache_manager_->GetCachedPhishGuardVerdict(
url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
+ password_type, &cached_verdict));
}
TEST_F(VerdictCacheManagerTest, TestCacheSplitByTriggerType) {
GURL url("https://www.google.com/");
-
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
+ password_type.set_is_account_syncing(true);
LoginReputationClientResponse cached_verdict;
cached_verdict.set_cache_expression("www.google.com/");
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
+ password_type, &cached_verdict));
CachePhishGuardVerdict(url,
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::SAFE, 60,
+ password_type, LoginReputationClientResponse::SAFE, 60,
"www.google.com/", base::Time::Now());
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
+ password_type, &cached_verdict));
}
TEST_F(VerdictCacheManagerTest, TestCacheSplitByPasswordType) {
GURL url("https://www.google.com/");
-
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
+ password_type.set_is_account_syncing(true);
LoginReputationClientResponse cached_verdict;
cached_verdict.set_cache_expression("www.google.com/");
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
-
- CachePhishGuardVerdict(
- url, LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::ENTERPRISE_PASSWORD, LoginReputationClientResponse::SAFE,
- 60, "www.google.com/", base::Time::Now());
+ password_type, &cached_verdict));
+ password_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
+ CachePhishGuardVerdict(url,
+ LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+ password_type, LoginReputationClientResponse::SAFE, 60,
+ "www.google.com/", base::Time::Now());
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
+ password_type, &cached_verdict));
}
TEST_F(VerdictCacheManagerTest, TestGetStoredPhishGuardVerdictCount) {
@@ -132,27 +138,30 @@ TEST_F(VerdictCacheManagerTest, TestGetStoredPhishGuardVerdictCount) {
cached_verdict.set_cache_expression("www.google.com/");
EXPECT_EQ(0u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-
- CachePhishGuardVerdict(
- url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD, LoginReputationClientResponse::SAFE,
- 60, "www.google.com/", base::Time::Now());
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
+ password_type.set_is_account_syncing(true);
+ CachePhishGuardVerdict(url,
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ password_type, LoginReputationClientResponse::SAFE, 60,
+ "www.google.com/", base::Time::Now());
EXPECT_EQ(1u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
- CachePhishGuardVerdict(
- url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD, LoginReputationClientResponse::SAFE,
- 60, "www.google.com/", base::Time::Now());
+ CachePhishGuardVerdict(url,
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ password_type, LoginReputationClientResponse::SAFE, 60,
+ "www.google.com/", base::Time::Now());
EXPECT_EQ(1u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
- CachePhishGuardVerdict(
- url, LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD, LoginReputationClientResponse::SAFE,
- 60, "www.google.com/path", base::Time::Now());
+ CachePhishGuardVerdict(url,
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ password_type, LoginReputationClientResponse::SAFE, 60,
+ "www.google.com/path", base::Time::Now());
EXPECT_EQ(2u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
@@ -182,12 +191,16 @@ TEST_F(VerdictCacheManagerTest, TestParseInvalidVerdictEntry) {
CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
std::move(cache_dictionary));
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
+ password_type.set_is_account_syncing(true);
+
LoginReputationClientResponse cached_verdict;
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://www.google.com/"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &cached_verdict));
+ password_type, &cached_verdict));
}
TEST_F(VerdictCacheManagerTest, TestRemoveCachedVerdictOnURLsDeleted) {
@@ -198,34 +211,35 @@ TEST_F(VerdictCacheManagerTest, TestRemoveCachedVerdictOnURLsDeleted) {
// Prepare 5 verdicts. Three are for origin "http://foo.com", and the others
// are for "http://bar.com".
base::Time now = base::Time::Now();
- CachePhishGuardVerdict(GURL("http://foo.com/abc/index.jsp"),
- LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::LOW_REPUTATION, 600,
- "foo.com/abc/", now);
- CachePhishGuardVerdict(GURL("http://foo.com/abc/index.jsp"),
- LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::ENTERPRISE_PASSWORD,
- LoginReputationClientResponse::LOW_REPUTATION, 600,
- "foo.com/abc/", now);
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
+ CachePhishGuardVerdict(
+ GURL("http://foo.com/abc/index.jsp"),
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT, password_type,
+ LoginReputationClientResponse::LOW_REPUTATION, 600, "foo.com/abc/", now);
+ password_type.set_account_type(
+ ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
+ CachePhishGuardVerdict(
+ GURL("http://foo.com/abc/index.jsp"),
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT, password_type,
+ LoginReputationClientResponse::LOW_REPUTATION, 600, "foo.com/abc/", now);
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
CachePhishGuardVerdict(GURL("http://bar.com/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::PHISHING, 600,
- "bar.com", now);
+ password_type, LoginReputationClientResponse::PHISHING,
+ 600, "bar.com", now);
ASSERT_EQ(3u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
- CachePhishGuardVerdict(GURL("http://foo.com/abc/index.jsp"),
- LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
- LoginReputationClientResponse::LOW_REPUTATION, 600,
- "foo.com/abc/", now);
+ password_type.set_account_type(ReusedPasswordAccountType::UNKNOWN);
+ CachePhishGuardVerdict(
+ GURL("http://foo.com/abc/index.jsp"),
+ LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE, password_type,
+ LoginReputationClientResponse::LOW_REPUTATION, 600, "foo.com/abc/", now);
CachePhishGuardVerdict(GURL("http://bar.com/index.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
- LoginReputationClientResponse::PHISHING, 600,
- "bar.com", now);
+ password_type, LoginReputationClientResponse::PHISHING,
+ 600, "bar.com", now);
ASSERT_EQ(2u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
@@ -246,16 +260,18 @@ TEST_F(VerdictCacheManagerTest, TestRemoveCachedVerdictOnURLsDeleted) {
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
LoginReputationClientResponse actual_verdict;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("http://bar.com"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ password_type, &actual_verdict));
+ password_type.set_account_type(ReusedPasswordAccountType::UNKNOWN);
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("http://bar.com"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN, &actual_verdict));
+ password_type, &actual_verdict));
// If delete all history. All password protection content settings should be
// gone.
@@ -274,42 +290,39 @@ TEST_F(VerdictCacheManagerTest, TestCleanUpExpiredVerdict) {
// (3) "bar.com/abc/" expired
// (4) "bar.com/def/" expired
base::Time now = base::Time::Now();
- CachePhishGuardVerdict(GURL("https://foo.com/abc/index.jsp"),
- LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::LOW_REPUTATION, 600,
- "foo.com/abc/", now);
- CachePhishGuardVerdict(GURL("https://foo.com/def/index.jsp"),
- LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::LOW_REPUTATION, 0,
- "foo.com/def/", now);
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
+ CachePhishGuardVerdict(
+ GURL("https://foo.com/abc/index.jsp"),
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT, password_type,
+ LoginReputationClientResponse::LOW_REPUTATION, 600, "foo.com/abc/", now);
+ CachePhishGuardVerdict(
+ GURL("https://foo.com/def/index.jsp"),
+ LoginReputationClientRequest::PASSWORD_REUSE_EVENT, password_type,
+ LoginReputationClientResponse::LOW_REPUTATION, 0, "foo.com/def/", now);
CachePhishGuardVerdict(GURL("https://bar.com/abc/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::PHISHING, 0,
- "bar.com/abc/", now);
+ password_type, LoginReputationClientResponse::PHISHING,
+ 0, "bar.com/abc/", now);
CachePhishGuardVerdict(GURL("https://bar.com/def/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::PHISHING, 0,
- "bar.com/def/", now);
+ password_type, LoginReputationClientResponse::PHISHING,
+ 0, "bar.com/def/", now);
ASSERT_EQ(4u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
// Prepare 2 verdicts for UNFAMILIAR_LOGIN_PAGE:
// (1) "bar.com/def/" valid
// (2) "bar.com/xyz/" expired
+ password_type.set_account_type(ReusedPasswordAccountType::UNKNOWN);
CachePhishGuardVerdict(GURL("https://bar.com/def/index.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
- LoginReputationClientResponse::SAFE, 600,
- "bar.com/def/", now);
+ password_type, LoginReputationClientResponse::SAFE,
+ 600, "bar.com/def/", now);
CachePhishGuardVerdict(GURL("https://bar.com/xyz/index.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN,
- LoginReputationClientResponse::PHISHING, 0,
- "bar.com/xyz/", now);
+ password_type, LoginReputationClientResponse::PHISHING,
+ 0, "bar.com/xyz/", now);
ASSERT_EQ(2u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
@@ -320,44 +333,46 @@ TEST_F(VerdictCacheManagerTest, TestCleanUpExpiredVerdict) {
ASSERT_EQ(1u, cache_manager_->GetStoredPhishGuardVerdictCount(
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
LoginReputationClientResponse actual_verdict;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
// Has cached PASSWORD_REUSE_EVENT verdict for foo.com/abc/.
EXPECT_EQ(LoginReputationClientResponse::LOW_REPUTATION,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://foo.com/abc/test.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ password_type, &actual_verdict));
// No cached PASSWORD_REUSE_EVENT verdict for foo.com/def.
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://foo.com/def/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ password_type, &actual_verdict));
// No cached PASSWORD_REUSE_EVENT verdict for bar.com/abc.
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://bar.com/abc/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ password_type, &actual_verdict));
// No cached PASSWORD_REUSE_EVENT verdict for bar.com/def.
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://bar.com/def/index.jsp"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD, &actual_verdict));
+ password_type, &actual_verdict));
// Has cached UNFAMILIAR_LOGIN_PAGE verdict for bar.com/def.
+ password_type.set_account_type(ReusedPasswordAccountType::UNKNOWN);
EXPECT_EQ(LoginReputationClientResponse::SAFE,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://bar.com/def/index.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN, &actual_verdict));
+ password_type, &actual_verdict));
// No cached UNFAMILIAR_LOGIN_PAGE verdict for bar.com/xyz.
EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
cache_manager_->GetCachedPhishGuardVerdict(
GURL("https://bar.com/xyz/index.jsp"),
LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
- PasswordType::PASSWORD_TYPE_UNKNOWN, &actual_verdict));
+ password_type, &actual_verdict));
}
TEST_F(VerdictCacheManagerTest, TestCleanUpExpiredVerdictWithInvalidEntry) {
@@ -384,11 +399,12 @@ TEST_F(VerdictCacheManagerTest, TestCleanUpExpiredVerdictWithInvalidEntry) {
CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
std::move(cache_dictionary));
+ ReusedPasswordAccountType password_type;
+ password_type.set_account_type(ReusedPasswordAccountType::GSUITE);
// Save one valid entry
CachePhishGuardVerdict(GURL("https://www.google.com"),
LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
- PasswordType::PRIMARY_ACCOUNT_PASSWORD,
- LoginReputationClientResponse::SAFE, 60,
+ password_type, LoginReputationClientResponse::SAFE, 60,
"www.google.com/", base::Time::Now());
// Verify we saved two entries under PasswordType PRIMARY_ACCOUNT_PASSWORD
diff --git a/chromium/components/safe_browsing/web_ui/BUILD.gn b/chromium/components/safe_browsing/web_ui/BUILD.gn
index 3221fc3ebaa..1f3de09e864 100644
--- a/chromium/components/safe_browsing/web_ui/BUILD.gn
+++ b/chromium/components/safe_browsing/web_ui/BUILD.gn
@@ -16,6 +16,7 @@ static_library("web_ui") {
"//components/password_manager/core/browser:hash_password_manager",
"//components/resources:components_resources_grit",
"//components/resources:components_scaled_resources_grit",
+ "//components/safe_browsing:buildflags",
"//components/safe_browsing:csd_proto",
"//components/safe_browsing:features",
"//components/safe_browsing/browser:network_context",
diff --git a/chromium/components/safe_browsing/web_ui/resources/safe_browsing.html b/chromium/components/safe_browsing/web_ui/resources/safe_browsing.html
index 023d459966a..89194bbf238 100644
--- a/chromium/components/safe_browsing/web_ui/resources/safe_browsing.html
+++ b/chromium/components/safe_browsing/web_ui/resources/safe_browsing.html
@@ -80,6 +80,10 @@
<div class="content">
<p id="pg-event-log"></p>
</div>
+ <h2>Security Events</h2>
+ <div class="content">
+ <p id="security-event-log"></p>
+ </div>
<h2>Password Protection Pings</h2>
<table id="pg-ping-list" class="request-response"></table>
</tabpanel>
diff --git a/chromium/components/safe_browsing/web_ui/resources/safe_browsing.js b/chromium/components/safe_browsing/web_ui/resources/safe_browsing.js
index 17b86902e50..cab3834b7aa 100644
--- a/chromium/components/safe_browsing/web_ui/resources/safe_browsing.js
+++ b/chromium/components/safe_browsing/web_ui/resources/safe_browsing.js
@@ -64,6 +64,15 @@ cr.define('safe_browsing', function() {
addPGEvent(result);
});
+ cr.sendWithPromise('getSecurityEvents', [])
+ .then((securityEvents) => {securityEvents.forEach(
+ function(securityEvent) {
+ addSecurityEvent(securityEvent);
+ })});
+ cr.addWebUIListener('sent-security-event', function(result) {
+ addSecurityEvent(result);
+ });
+
cr.sendWithPromise('getPGPings', [])
.then((pgPings) => { pgPings.forEach(function (pgPing) {
addPGPing(pgPing);
@@ -187,6 +196,13 @@ cr.define('safe_browsing', function() {
appendChildWithInnerText(logDiv, eventFormatted);
}
+ function addSecurityEvent(result) {
+ var logDiv = $('security-event-log');
+ var eventFormatted = "[" + (new Date(result["time"])).toLocaleString() +
+ "] " + result['message'];
+ appendChildWithInnerText(logDiv, eventFormatted);
+ }
+
function addPGPingRow(token) {
var row = $('pg-ping-list').insertRow();
row.className = 'content';
@@ -256,6 +272,7 @@ cr.define('safe_browsing', function() {
addReceivedClientDownloadResponseInfo:
addReceivedClientDownloadResponseInfo,
addPGEvent: addPGEvent,
+ addSecurityEvent: addSecurityEvent,
addPGPing: addPGPing,
addPGResponse: addPGResponse,
initialize: initialize,
diff --git a/chromium/components/safe_browsing/web_ui/safe_browsing_ui.cc b/chromium/components/safe_browsing/web_ui/safe_browsing_ui.cc
index a5c0babbc65..57a812b505d 100644
--- a/chromium/components/safe_browsing/web_ui/safe_browsing_ui.cc
+++ b/chromium/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -28,6 +28,7 @@
#include "components/grit/components_scaled_resources.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
#include "components/safe_browsing/browser/referrer_chain_provider.h"
+#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/common/safe_browsing_prefs.h"
#include "components/safe_browsing/features.h"
#include "components/safe_browsing/proto/csd.pb.h"
@@ -39,7 +40,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
-#if SAFE_BROWSING_DB_LOCAL
+#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
#include "components/safe_browsing/db/v4_local_database_manager.h"
#endif
@@ -130,6 +131,21 @@ void WebUIInfoSingleton::ClearPGEvents() {
std::vector<sync_pb::UserEventSpecifics>().swap(pg_event_log_);
}
+void WebUIInfoSingleton::AddToSecurityEvents(
+ const sync_pb::GaiaPasswordReuse& event) {
+ if (!HasListener())
+ return;
+
+ for (auto* webui_listener : webui_instances_)
+ webui_listener->NotifySecurityEventJsListener(event);
+
+ security_event_log_.push_back(event);
+}
+
+void WebUIInfoSingleton::ClearSecurityEvents() {
+ std::vector<sync_pb::GaiaPasswordReuse>().swap(security_event_log_);
+}
+
int WebUIInfoSingleton::AddToPGPings(
const LoginReputationClientRequest& request) {
if (!HasListener())
@@ -167,10 +183,9 @@ void WebUIInfoSingleton::LogMessage(const std::string& message) {
base::Time timestamp = base::Time::Now();
log_messages_.push_back(std::make_pair(timestamp, message));
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&WebUIInfoSingleton::NotifyLogMessageListeners, timestamp,
- message));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&WebUIInfoSingleton::NotifyLogMessageListeners,
+ timestamp, message));
}
void WebUIInfoSingleton::ClearLogMessages() {
@@ -203,31 +218,31 @@ void WebUIInfoSingleton::UnregisterWebUIInstance(SafeBrowsingUIHandler* webui) {
}
network::mojom::CookieManager* WebUIInfoSingleton::GetCookieManager() {
- if (!cookie_manager_ptr_)
+ if (!cookie_manager_remote_)
InitializeCookieManager();
- return cookie_manager_ptr_.get();
+ return cookie_manager_remote_.get();
}
void WebUIInfoSingleton::InitializeCookieManager() {
DCHECK(network_context_);
- // Reset |cookie_manager_ptr_|, and only re-initialize it if we have a
+ // Reset |cookie_manager_remote_|, and only re-initialize it if we have a
// listening SafeBrowsingUIHandler.
- cookie_manager_ptr_ = nullptr;
+ cookie_manager_remote_.reset();
if (HasListener()) {
network_context_->GetNetworkContext()->GetCookieManager(
- mojo::MakeRequest(&cookie_manager_ptr_));
+ cookie_manager_remote_.BindNewPipeAndPassReceiver());
- // base::Unretained is safe because |this| owns |cookie_manager_ptr_|.
- cookie_manager_ptr_.set_connection_error_handler(base::BindOnce(
+ // base::Unretained is safe because |this| owns |cookie_manager_remote_|.
+ cookie_manager_remote_.set_disconnect_handler(base::BindOnce(
&WebUIInfoSingleton::InitializeCookieManager, base::Unretained(this)));
}
}
namespace {
-#if SAFE_BROWSING_DB_LOCAL
+#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
base::Value UserReadableTimeFromMillisSinceEpoch(int64_t time_in_milliseconds) {
base::Time time = base::Time::UnixEpoch() +
@@ -624,6 +639,57 @@ std::string SerializeCSBRR(const ClientSafeBrowsingReportRequest& report) {
return report_request_serialized;
}
+base::Value SerializeReuseLookup(
+ const PasswordReuseLookup password_reuse_lookup) {
+ std::string lookup_result;
+ switch (password_reuse_lookup.lookup_result()) {
+ case PasswordReuseLookup::UNSPECIFIED:
+ lookup_result = "UNSPECIFIED";
+ break;
+ case PasswordReuseLookup::WHITELIST_HIT:
+ lookup_result = "WHITELIST_HIT";
+ break;
+ case PasswordReuseLookup::CACHE_HIT:
+ lookup_result = "CACHE_HIT";
+ break;
+ case PasswordReuseLookup::REQUEST_SUCCESS:
+ lookup_result = "REQUEST_SUCCESS";
+ break;
+ case PasswordReuseLookup::REQUEST_FAILURE:
+ lookup_result = "REQUEST_FAILURE";
+ break;
+ case PasswordReuseLookup::URL_UNSUPPORTED:
+ lookup_result = "URL_UNSUPPORTED";
+ break;
+ case PasswordReuseLookup::ENTERPRISE_WHITELIST_HIT:
+ lookup_result = "ENTERPRISE_WHITELIST_HIT";
+ break;
+ case PasswordReuseLookup::TURNED_OFF_BY_POLICY:
+ lookup_result = "TURNED_OFF_BY_POLICY";
+ break;
+ }
+ return base::Value(lookup_result);
+}
+
+base::Value SerializeVerdict(const PasswordReuseLookup password_reuse_lookup) {
+ std::string verdict;
+ switch (password_reuse_lookup.verdict()) {
+ case PasswordReuseLookup::VERDICT_UNSPECIFIED:
+ verdict = "VERDICT_UNSPECIFIED";
+ break;
+ case PasswordReuseLookup::SAFE:
+ verdict = "SAFE";
+ break;
+ case PasswordReuseLookup::LOW_REPUTATION:
+ verdict = "LOW_REPUTATION";
+ break;
+ case PasswordReuseLookup::PHISHING:
+ verdict = "PHISHING";
+ break;
+ }
+ return base::Value(verdict);
+}
+
base::DictionaryValue SerializePGEvent(
const sync_pb::UserEventSpecifics& event) {
base::DictionaryValue result;
@@ -684,52 +750,10 @@ base::DictionaryValue SerializePGEvent(
}
if (reuse.has_reuse_lookup()) {
- std::string lookup_result;
- switch (reuse.reuse_lookup().lookup_result()) {
- case PasswordReuseLookup::UNSPECIFIED:
- lookup_result = "UNSPECIFIED";
- break;
- case PasswordReuseLookup::WHITELIST_HIT:
- lookup_result = "WHITELIST_HIT";
- break;
- case PasswordReuseLookup::CACHE_HIT:
- lookup_result = "CACHE_HIT";
- break;
- case PasswordReuseLookup::REQUEST_SUCCESS:
- lookup_result = "REQUEST_SUCCESS";
- break;
- case PasswordReuseLookup::REQUEST_FAILURE:
- lookup_result = "REQUEST_FAILURE";
- break;
- case PasswordReuseLookup::URL_UNSUPPORTED:
- lookup_result = "URL_UNSUPPORTED";
- break;
- case PasswordReuseLookup::ENTERPRISE_WHITELIST_HIT:
- lookup_result = "ENTERPRISE_WHITELIST_HIT";
- break;
- case PasswordReuseLookup::TURNED_OFF_BY_POLICY:
- lookup_result = "TURNED_OFF_BY_POLICY";
- break;
- }
event_dict.SetPath({"reuse_lookup", "lookup_result"},
- base::Value(lookup_result));
-
- std::string verdict;
- switch (reuse.reuse_lookup().verdict()) {
- case PasswordReuseLookup::VERDICT_UNSPECIFIED:
- verdict = "VERDICT_UNSPECIFIED";
- break;
- case PasswordReuseLookup::SAFE:
- verdict = "SAFE";
- break;
- case PasswordReuseLookup::LOW_REPUTATION:
- verdict = "LOW_REPUTATION";
- break;
- case PasswordReuseLookup::PHISHING:
- verdict = "PHISHING";
- break;
- }
- event_dict.SetPath({"reuse_lookup", "verdict"}, base::Value(verdict));
+ SerializeReuseLookup(reuse.reuse_lookup()));
+ event_dict.SetPath({"reuse_lookup", "verdict"},
+ SerializeVerdict(reuse.reuse_lookup()));
event_dict.SetPath({"reuse_lookup", "verdict_token"},
base::Value(reuse.reuse_lookup().verdict_token()));
}
@@ -765,6 +789,28 @@ base::DictionaryValue SerializePGEvent(
return result;
}
+base::DictionaryValue SerializeSecurityEvent(
+ const sync_pb::GaiaPasswordReuse& event) {
+ base::DictionaryValue result;
+
+ base::DictionaryValue event_dict;
+ if (event.has_reuse_lookup()) {
+ event_dict.SetPath({"reuse_lookup", "lookup_result"},
+ SerializeReuseLookup(event.reuse_lookup()));
+ event_dict.SetPath({"reuse_lookup", "verdict"},
+ SerializeVerdict(event.reuse_lookup()));
+ event_dict.SetPath({"reuse_lookup", "verdict_token"},
+ base::Value(event.reuse_lookup().verdict_token()));
+ }
+
+ std::string event_serialized;
+ JSONStringValueSerializer serializer(&event_serialized);
+ serializer.set_pretty_print(true);
+ serializer.Serialize(event_dict);
+ result.SetString("message", event_serialized);
+ return result;
+}
+
base::Value SerializeFrame(const LoginReputationClientRequest::Frame& frame) {
base::DictionaryValue frame_dict;
frame_dict.SetKey("frame_index", base::Value(frame.frame_index()));
@@ -1136,7 +1182,7 @@ void SafeBrowsingUIHandler::GetDatabaseManagerInfo(
const base::ListValue* args) {
base::ListValue database_manager_info;
-#if SAFE_BROWSING_DB_LOCAL
+#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
const V4LocalDatabaseManager* local_database_manager_instance =
V4LocalDatabaseManager::current_local_database_manager();
if (local_database_manager_instance) {
@@ -1234,6 +1280,21 @@ void SafeBrowsingUIHandler::GetPGEvents(const base::ListValue* args) {
ResolveJavascriptCallback(base::Value(callback_id), events_sent);
}
+void SafeBrowsingUIHandler::GetSecurityEvents(const base::ListValue* args) {
+ const std::vector<sync_pb::GaiaPasswordReuse>& events =
+ WebUIInfoSingleton::GetInstance()->security_event_log();
+
+ base::ListValue events_sent;
+
+ for (const sync_pb::GaiaPasswordReuse& event : events)
+ events_sent.GetList().push_back(SerializeSecurityEvent(event));
+
+ AllowJavascript();
+ std::string callback_id;
+ args->GetString(0, &callback_id);
+ ResolveJavascriptCallback(base::Value(callback_id), events_sent);
+}
+
void SafeBrowsingUIHandler::GetPGPings(const base::ListValue* args) {
const std::vector<LoginReputationClientRequest> requests =
WebUIInfoSingleton::GetInstance()->pg_pings();
@@ -1352,6 +1413,12 @@ void SafeBrowsingUIHandler::NotifyPGEventJsListener(
FireWebUIListener("sent-pg-event", SerializePGEvent(event));
}
+void SafeBrowsingUIHandler::NotifySecurityEventJsListener(
+ const sync_pb::GaiaPasswordReuse& event) {
+ AllowJavascript();
+ FireWebUIListener("sent-security-event", SerializeSecurityEvent(event));
+}
+
void SafeBrowsingUIHandler::NotifyPGPingJsListener(
int token,
const LoginReputationClientRequest& request) {
@@ -1418,6 +1485,10 @@ void SafeBrowsingUIHandler::RegisterMessages() {
"getPGEvents", base::BindRepeating(&SafeBrowsingUIHandler::GetPGEvents,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
+ "getSecurityEvents",
+ base::BindRepeating(&SafeBrowsingUIHandler::GetSecurityEvents,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
"getPGPings", base::BindRepeating(&SafeBrowsingUIHandler::GetPGPings,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
diff --git a/chromium/components/safe_browsing/web_ui/safe_browsing_ui.h b/chromium/components/safe_browsing/web_ui/safe_browsing_ui.h
index 95379fd8565..d854ef94f28 100644
--- a/chromium/components/safe_browsing/web_ui/safe_browsing_ui.h
+++ b/chromium/components/safe_browsing/web_ui/safe_browsing_ui.h
@@ -14,6 +14,7 @@
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
@@ -70,6 +71,10 @@ class SafeBrowsingUIHandler : public content::WebUIMessageHandler {
// currently open chrome://safe-browsing tab was opened.
void GetPGEvents(const base::ListValue* args);
+ // Get the Security events that have been collected since the oldest
+ // currently open chrome://safe-browsing tab was opened.
+ void GetSecurityEvents(const base::ListValue* args);
+
// Get the PhishGuard pings that have been sent since the oldest currently
// open chrome://safe-browsing tab was opened.
void GetPGPings(const base::ListValue* args);
@@ -112,6 +117,10 @@ class SafeBrowsingUIHandler : public content::WebUIMessageHandler {
// are open.
void NotifyPGEventJsListener(const sync_pb::UserEventSpecifics& event);
+ // Called when any new Security events are sent while one or more WebUI tabs
+ // are open.
+ void NotifySecurityEventJsListener(const sync_pb::GaiaPasswordReuse& event);
+
// Called when any new PhishGuard pings are sent while one or more WebUI tabs
// are open.
void NotifyPGPingJsListener(int token,
@@ -189,6 +198,13 @@ class WebUIInfoSingleton {
// Clear the list of sent PhishGuard events.
void ClearPGEvents();
+ // Add the new message in |security_event_log_| and send it to all the open
+ // chrome://safe-browsing tabs.
+ void AddToSecurityEvents(const sync_pb::GaiaPasswordReuse& event);
+
+ // Clear the list of sent Security events.
+ void ClearSecurityEvents();
+
// Add the new ping to |pg_pings_| and send it to all the open
// chrome://safe-browsing tabs. Returns a token that can be used in
// |AddToPGReponses| to correlate a ping and response.
@@ -252,6 +268,12 @@ class WebUIInfoSingleton {
return pg_event_log_;
}
+ // Get the list of Security events since the oldest currently open
+ // chrome://safe-browsing tab was opened.
+ const std::vector<sync_pb::GaiaPasswordReuse>& security_event_log() const {
+ return security_event_log_;
+ }
+
// Get the list of PhishGuard pings since the oldest currently open
// chrome://safe-browsing tab was opened.
const std::vector<LoginReputationClientRequest>& pg_pings() const {
@@ -316,6 +338,10 @@ class WebUIInfoSingleton {
// chrome://safe-browsing tab was opened.
std::vector<sync_pb::UserEventSpecifics> pg_event_log_;
+ // List of Security events sent since the oldest currently open
+ // chrome://safe-browsing tab was opened.
+ std::vector<sync_pb::GaiaPasswordReuse> security_event_log_;
+
// List of PhishGuard pings sent since the oldest currently open
// chrome://safe-browsing tab was opened.
std::vector<LoginReputationClientRequest> pg_pings_;
@@ -340,7 +366,7 @@ class WebUIInfoSingleton {
SafeBrowsingNetworkContext* network_context_ = nullptr;
// The current CookieManager for the Safe Browsing cookie.
- network::mojom::CookieManagerPtr cookie_manager_ptr_ = nullptr;
+ mojo::Remote<network::mojom::CookieManager> cookie_manager_remote_;
// Whether there is a test listener.
bool has_test_listener_ = false;
diff --git a/chromium/components/safe_browsing/web_ui/safe_browsing_ui_unittest.cc b/chromium/components/safe_browsing/web_ui/safe_browsing_ui_unittest.cc
index c2291c7f9ee..87fdd59fd8a 100644
--- a/chromium/components/safe_browsing/web_ui/safe_browsing_ui_unittest.cc
+++ b/chromium/components/safe_browsing/web_ui/safe_browsing_ui_unittest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "components/safe_browsing/web_ui/safe_browsing_ui.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_web_ui.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -40,7 +40,7 @@ class SafeBrowsingUITest : public testing::Test {
protected:
int member_int_;
content::TestWebUI web_ui_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
};
diff --git a/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client.cc b/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client.cc
index 236663ff22b..8b3d5be51d5 100644
--- a/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client.cc
+++ b/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client.cc
@@ -113,7 +113,7 @@ void SafeSearchURLCheckerClient::CheckURL(const GURL& url,
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = GURL(kSafeSearchApiUrl);
resource_request->method = "POST";
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
std::unique_ptr<network::SimpleURLLoader> simple_url_loader =
network::SimpleURLLoader::Create(std::move(resource_request),
traffic_annotation_);
diff --git a/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client_unittest.cc b/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client_unittest.cc
index d42e3f06bec..4261315ed21 100644
--- a/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client_unittest.cc
+++ b/chromium/components/safe_search_api/safe_search/safe_search_url_checker_client_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/json/json_writer.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/http/http_util.h"
@@ -109,7 +109,7 @@ class SafeSearchURLCheckerClientTest : public testing::Test {
}
size_t next_url_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
std::unique_ptr<SafeSearchURLCheckerClient> checker_;
diff --git a/chromium/components/safe_search_api/url_checker_unittest.cc b/chromium/components/safe_search_api/url_checker_unittest.cc
index 362fde4d781..70400aa96b6 100644
--- a/chromium/components/safe_search_api/url_checker_unittest.cc
+++ b/chromium/components/safe_search_api/url_checker_unittest.cc
@@ -15,7 +15,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/safe_search_api/fake_url_checker_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/search/BUILD.gn b/chromium/components/search/BUILD.gn
index b3896ba7d1a..2baff9f8491 100644
--- a/chromium/components/search/BUILD.gn
+++ b/chromium/components/search/BUILD.gn
@@ -10,7 +10,7 @@ static_library("search") {
deps = [
"//base",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/search_engines",
"//url",
]
diff --git a/chromium/components/search/OWNERS b/chromium/components/search/OWNERS
index 36c858c50d2..e5e11337b3b 100644
--- a/chromium/components/search/OWNERS
+++ b/chromium/components/search/OWNERS
@@ -8,3 +8,6 @@ ramyan@chromium.org
# Original implementors of most of the code, but not active in Chromium anymore:
# - jered@chromium.org
# - samarth@chromium.org
+
+# COMPONENT: UI>Browser>NewTabPage
+# TEAM: ntp-dev@chromium.org
diff --git a/chromium/components/search_engines/BUILD.gn b/chromium/components/search_engines/BUILD.gn
index f0e10cf0bac..caf5ebb1eba 100644
--- a/chromium/components/search_engines/BUILD.gn
+++ b/chromium/components/search_engines/BUILD.gn
@@ -49,7 +49,7 @@ static_library("search_engines") {
public_deps = [
":search_engine_type",
"//base",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/keyed_service/core",
"//components/prefs",
"//components/sync",
@@ -144,7 +144,7 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/country_codes",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/pref_registry:pref_registry",
"//components/prefs",
"//components/sync:test_support",
diff --git a/chromium/components/search_engines/android/OWNERS b/chromium/components/search_engines/android/OWNERS
new file mode 100644
index 00000000000..52b99d7e26c
--- /dev/null
+++ b/chromium/components/search_engines/android/OWNERS
@@ -0,0 +1,3 @@
+file://chrome/android/OWNERS
+
+# COMPONENT: UI>Browser>Search
diff --git a/chromium/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrlService.java b/chromium/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrlService.java
index 04bfbf2719e..b00162b85c5 100644
--- a/chromium/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrlService.java
+++ b/chromium/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrlService.java
@@ -289,6 +289,29 @@ public class TemplateUrlService {
return nativeGetSearchEngineTypeFromTemplateUrl(mNativeTemplateUrlServiceAndroid, keyword);
}
+ /**
+ * Adds a search engine, set by Play API.
+ * @param name The name of the search engine to be added.
+ * @param keyword The keyword of the search engine to be added.
+ * @param searchUrl Search url of the search engine to be added.
+ * @param suggestUrl Url for retrieving search suggestions.
+ * @param faviconUrl Favicon url of the search engine to be added.
+ * @return True if search engine was successfully added, false if search engine from Play API
+ * with such keyword already existed (e.g. from previous attempt to set search engine).
+ */
+ public boolean setPlayAPISearchEngine(
+ String name, String keyword, String searchUrl, String suggestUrl, String faviconUrl) {
+ return nativeSetPlayAPISearchEngine(
+ mNativeTemplateUrlServiceAndroid, name, keyword, searchUrl, suggestUrl, faviconUrl);
+ }
+ // TODO(crbug/1002271): This API is called from clank repo. Helper function below will be
+ // removed once clank repo is updated.
+ public boolean setPlayAPISearchEngine(
+ String name, String keyword, String searchUrl, String faviconUrl) {
+ return nativeSetPlayAPISearchEngine(
+ mNativeTemplateUrlServiceAndroid, name, keyword, searchUrl, null, faviconUrl);
+ }
+
@VisibleForTesting
public String addSearchEngineForTesting(String keyword, int ageInDays) {
return nativeAddSearchEngineForTesting(
@@ -321,6 +344,8 @@ public class TemplateUrlService {
long nativeTemplateUrlServiceAndroid, String keyword);
private native String nativeAddSearchEngineForTesting(
long nativeTemplateUrlServiceAndroid, String keyword, int offset);
+ private native boolean nativeSetPlayAPISearchEngine(long nativeTemplateUrlServiceAndroid,
+ String name, String keyword, String searchUrl, String suggestUrl, String faviconUrl);
private native String nativeUpdateLastVisitedForTesting(
long nativeTemplateUrlServiceAndroid, String keyword);
private native void nativeGetTemplateUrls(
diff --git a/chromium/components/search_engines/android/template_url_android.cc b/chromium/components/search_engines/android/template_url_android.cc
index cc424a0650a..e41bc66f6a5 100644
--- a/chromium/components/search_engines/android/template_url_android.cc
+++ b/chromium/components/search_engines/android/template_url_android.cc
@@ -36,7 +36,8 @@ jboolean JNI_TemplateUrl_IsPrepopulatedOrCreatedByPolicy(
jlong template_url_ptr) {
TemplateURL* template_url = ToTemplateURL(template_url_ptr);
return template_url->prepopulate_id() > 0 ||
- template_url->created_by_policy();
+ template_url->created_by_policy() ||
+ template_url->created_from_play_api();
}
jlong JNI_TemplateUrl_GetLastVisitedTime(JNIEnv* env, jlong template_url_ptr) {
diff --git a/chromium/components/search_engines/android/template_url_service_android.cc b/chromium/components/search_engines/android/template_url_service_android.cc
index 0a2517279a9..b9707339fed 100644
--- a/chromium/components/search_engines/android/template_url_service_android.cc
+++ b/chromium/components/search_engines/android/template_url_service_android.cc
@@ -238,6 +238,45 @@ int TemplateUrlServiceAndroid::GetSearchEngineTypeFromTemplateUrl(
return template_url->GetEngineType(search_terms_data);
}
+jboolean TemplateUrlServiceAndroid::SetPlayAPISearchEngine(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jstring>& jname,
+ const base::android::JavaParamRef<jstring>& jkeyword,
+ const base::android::JavaParamRef<jstring>& jsearch_url,
+ const base::android::JavaParamRef<jstring>& jsuggest_url,
+ const base::android::JavaParamRef<jstring>& jfavicon_url) {
+ // Check if there is already a search engine created from Play API.
+ TemplateURLService::TemplateURLVector template_urls =
+ template_url_service_->GetTemplateURLs();
+ auto existing_play_api_turl = std::find_if(
+ template_urls.cbegin(), template_urls.cend(),
+ [](const TemplateURL* turl) { return turl->created_from_play_api(); });
+ if (existing_play_api_turl != template_urls.cend())
+ return false;
+
+ base::string16 keyword =
+ base::android::ConvertJavaStringToUTF16(env, jkeyword);
+ base::string16 name = base::android::ConvertJavaStringToUTF16(env, jname);
+ std::string search_url = base::android::ConvertJavaStringToUTF8(jsearch_url);
+ std::string suggest_url;
+ if (jsuggest_url) {
+ suggest_url = base::android::ConvertJavaStringToUTF8(jsuggest_url);
+ }
+ std::string favicon_url;
+ if (jfavicon_url) {
+ favicon_url = base::android::ConvertJavaStringToUTF8(jfavicon_url);
+ }
+
+ TemplateURL* t_url =
+ template_url_service_->CreateOrUpdateTemplateURLFromPlayAPIData(
+ name, keyword, search_url, suggest_url, favicon_url);
+
+ if (template_url_service_->CanMakeDefault(t_url))
+ template_url_service_->SetUserSelectedDefaultSearchProvider(t_url);
+ return true;
+}
+
base::android::ScopedJavaLocalRef<jstring>
TemplateUrlServiceAndroid::AddSearchEngineForTesting(
JNIEnv* env,
diff --git a/chromium/components/search_engines/android/template_url_service_android.h b/chromium/components/search_engines/android/template_url_service_android.h
index 667abb7fe29..d692ab3de30 100644
--- a/chromium/components/search_engines/android/template_url_service_android.h
+++ b/chromium/components/search_engines/android/template_url_service_android.h
@@ -65,6 +65,19 @@ class TemplateUrlServiceAndroid : public TemplateURLServiceObserver {
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jstring>& jkeyword);
+ // Adds a search engine, set by Play API. Sets it as DSE if possible.
+ // Returns true if search engine was successfully added, false if search
+ // engine from Play API with such keyword already existed (e.g. from previous
+ // attempt to set search engine).
+ jboolean SetPlayAPISearchEngine(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jstring>& jname,
+ const base::android::JavaParamRef<jstring>& jkeyword,
+ const base::android::JavaParamRef<jstring>& jsearch_url,
+ const base::android::JavaParamRef<jstring>& jsuggest_url,
+ const base::android::JavaParamRef<jstring>& jfavicon_url);
+
// Adds a custom search engine, sets |jkeyword| as its short_name and keyword,
// and sets its date_created as |age_in_days| days before the current time.
base::android::ScopedJavaLocalRef<jstring> AddSearchEngineForTesting(
diff --git a/chromium/components/search_engines/default_search_manager.cc b/chromium/components/search_engines/default_search_manager.cc
index ffe8ec2a91f..d1124ba866f 100644
--- a/chromium/components/search_engines/default_search_manager.cc
+++ b/chromium/components/search_engines/default_search_manager.cc
@@ -74,6 +74,8 @@ const char DefaultSearchManager::kUsageCount[] = "usage_count";
const char DefaultSearchManager::kAlternateURLs[] = "alternate_urls";
const char DefaultSearchManager::kCreatedByPolicy[] = "created_by_policy";
const char DefaultSearchManager::kDisabledByPolicy[] = "disabled_by_policy";
+const char DefaultSearchManager::kCreatedFromPlayAPI[] =
+ "created_from_play_api";
DefaultSearchManager::DefaultSearchManager(
PrefService* pref_service,
diff --git a/chromium/components/search_engines/default_search_manager.h b/chromium/components/search_engines/default_search_manager.h
index c6211c58f43..4d9e5450eec 100644
--- a/chromium/components/search_engines/default_search_manager.h
+++ b/chromium/components/search_engines/default_search_manager.h
@@ -60,6 +60,7 @@ class DefaultSearchManager {
static const char kAlternateURLs[];
static const char kCreatedByPolicy[];
static const char kDisabledByPolicy[];
+ static const char kCreatedFromPlayAPI[];
enum Source {
// Default search engine chosen either from prepopulated engines set for
diff --git a/chromium/components/search_engines/default_search_manager_unittest.cc b/chromium/components/search_engines/default_search_manager_unittest.cc
index 1f7a1f9b828..1797642aaf9 100644
--- a/chromium/components/search_engines/default_search_manager_unittest.cc
+++ b/chromium/components/search_engines/default_search_manager_unittest.cc
@@ -115,6 +115,7 @@ TEST_F(DefaultSearchManagerTest, ReadAndWritePref) {
data.date_created = base::Time();
data.last_modified = base::Time();
data.last_modified = base::Time();
+ data.created_from_play_api = true;
manager.SetUserSelectedDefaultSearchEngine(data);
const TemplateURLData* read_data = manager.GetDefaultSearchEngine(nullptr);
diff --git a/chromium/components/search_engines/keyword_table.cc b/chromium/components/search_engines/keyword_table.cc
index 8278864b0f0..3feaad1eac4 100644
--- a/chromium/components/search_engines/keyword_table.cc
+++ b/chromium/components/search_engines/keyword_table.cc
@@ -99,6 +99,10 @@ const std::string ColumnsForVersion(int version, bool concatenated) {
// Column added in version 69.
columns.push_back("last_visited");
}
+ if (version >= 82) {
+ // Column added in version 82.
+ columns.push_back("created_from_play_api");
+ }
return base::JoinString(columns, std::string(concatenated ? " || " : ", "));
}
@@ -151,6 +155,7 @@ void BindURLToStatement(const TemplateURLData& data,
s->BindString(starting_column + 19, data.new_tab_url);
s->BindInt64(starting_column + 20,
data.last_visited.since_origin().InMicroseconds());
+ s->BindBool(starting_column + 21, data.created_from_play_api);
}
WebDatabaseTable::TypeKey GetKey() {
@@ -200,7 +205,8 @@ bool KeywordTable::CreateTablesIfNecessary() {
"suggest_url_post_params VARCHAR,"
"image_url_post_params VARCHAR,"
"new_tab_url VARCHAR,"
- "last_visited INTEGER DEFAULT 0)");
+ "last_visited INTEGER DEFAULT 0, "
+ "created_from_play_api INTEGER DEFAULT 0)");
}
bool KeywordTable::IsSyncable() {
@@ -228,6 +234,8 @@ bool KeywordTable::MigrateToVersion(int version,
case 77:
*update_compatible_version = true;
return MigrateToVersion77IncreaseTimePrecision();
+ case 82:
+ return MigrateToVersion82AddCreatedFromPlayApiColumn();
}
return true;
@@ -436,6 +444,12 @@ bool KeywordTable::MigrateToVersion77IncreaseTimePrecision() {
return transaction.Commit();
}
+bool KeywordTable::MigrateToVersion82AddCreatedFromPlayApiColumn() {
+ return db_->Execute(
+ "ALTER TABLE keywords ADD COLUMN created_from_play_api INTEGER DEFAULT "
+ "0");
+}
+
// static
bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
TemplateURLData* data) {
@@ -467,6 +481,7 @@ bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
data->last_modified =
base::Time() + base::TimeDelta::FromMicroseconds(s.ColumnInt64(13));
data->created_by_policy = s.ColumnBool(12);
+ data->created_from_play_api = s.ColumnBool(22);
data->usage_count = s.ColumnInt(8);
data->prepopulate_id = s.ColumnInt(11);
data->sync_guid = s.ColumnString(14);
@@ -494,7 +509,7 @@ bool KeywordTable::AddKeyword(const TemplateURLData& data) {
DCHECK(data.id);
std::string query("INSERT INTO keywords (" + GetKeywordColumns() +
") "
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE, query.c_str()));
BindURLToStatement(data, &s, 0, 1);
@@ -519,8 +534,9 @@ bool KeywordTable::UpdateKeyword(const TemplateURLData& data) {
"usage_count=?, input_encodings=?, suggest_url=?, prepopulate_id=?, "
"created_by_policy=?, last_modified=?, sync_guid=?, alternate_urls=?, "
"image_url=?, search_url_post_params=?, suggest_url_post_params=?, "
- "image_url_post_params=?, new_tab_url=?, last_visited=? WHERE id=?"));
- BindURLToStatement(data, &s, 21, 0); // "21" binds id() as the last item.
+ "image_url_post_params=?, new_tab_url=?, last_visited=?, "
+ "created_from_play_api=? WHERE id=?"));
+ BindURLToStatement(data, &s, 22, 0); // "22" binds id() as the last item.
return s.Run();
}
diff --git a/chromium/components/search_engines/keyword_table.h b/chromium/components/search_engines/keyword_table.h
index 340d2daa98b..c8f1f19e5ba 100644
--- a/chromium/components/search_engines/keyword_table.h
+++ b/chromium/components/search_engines/keyword_table.h
@@ -65,6 +65,10 @@ class Statement;
// was added in version 52.
// new_tab_url See TemplateURLData::new_tab_url. This was added in
// version 53.
+// last_visited See TemplateURLData::last_visited. This was added in
+// version 69.
+// created_from_play_api See TemplateURLData::created_from_play_api. This was
+// added in version 82.
//
// This class also manages some fields in the |meta| table:
//
@@ -128,6 +132,7 @@ class KeywordTable : public WebDatabaseTable {
bool MigrateToVersion69AddLastVisitedColumn();
bool MigrateToVersion76RemoveInstantColumns();
bool MigrateToVersion77IncreaseTimePrecision();
+ bool MigrateToVersion82AddCreatedFromPlayApiColumn();
private:
friend class KeywordTableTest;
diff --git a/chromium/components/search_engines/keyword_table_unittest.cc b/chromium/components/search_engines/keyword_table_unittest.cc
index 1b552031436..bffdff92130 100644
--- a/chromium/components/search_engines/keyword_table_unittest.cc
+++ b/chromium/components/search_engines/keyword_table_unittest.cc
@@ -133,6 +133,8 @@ TEST_F(KeywordTableTest, Keywords) {
EXPECT_EQ(keyword.last_visited.ToTimeT(),
restored_keyword.last_visited.ToTimeT());
EXPECT_EQ(keyword.created_by_policy, restored_keyword.created_by_policy);
+ EXPECT_EQ(keyword.created_from_play_api,
+ restored_keyword.created_from_play_api);
EXPECT_EQ(keyword.usage_count, restored_keyword.usage_count);
EXPECT_EQ(keyword.prepopulate_id, restored_keyword.prepopulate_id);
@@ -152,6 +154,7 @@ TEST_F(KeywordTableTest, UpdateKeyword) {
keyword.originating_url = GURL("http://originating.url/");
keyword.input_encodings.push_back("Shift_JIS");
keyword.prepopulate_id = 5;
+ keyword.created_from_play_api = true;
UpdateKeyword(keyword);
KeywordTable::Keywords keywords(GetKeywords());
@@ -168,6 +171,8 @@ TEST_F(KeywordTableTest, UpdateKeyword) {
EXPECT_EQ(keyword.input_encodings, restored_keyword.input_encodings);
EXPECT_EQ(keyword.id, restored_keyword.id);
EXPECT_EQ(keyword.prepopulate_id, restored_keyword.prepopulate_id);
+ EXPECT_EQ(keyword.created_from_play_api,
+ restored_keyword.created_from_play_api);
}
TEST_F(KeywordTableTest, KeywordWithNoFavicon) {
diff --git a/chromium/components/search_engines/keyword_web_data_service.cc b/chromium/components/search_engines/keyword_web_data_service.cc
index c1ab4071379..0a5e8035833 100644
--- a/chromium/components/search_engines/keyword_web_data_service.cc
+++ b/chromium/components/search_engines/keyword_web_data_service.cc
@@ -7,21 +7,57 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "build/build_config.h"
#include "components/search_engines/keyword_table.h"
#include "components/search_engines/template_url_data.h"
#include "components/webdata/common/web_data_results.h"
#include "components/webdata/common/web_database_service.h"
-using base::Bind;
+namespace {
-WDKeywordsResult::WDKeywordsResult()
- : default_search_provider_id(0),
- builtin_keyword_version(0) {
+WebDatabase::State PerformKeywordOperationsImpl(
+ const KeywordTable::Operations& operations,
+ WebDatabase* db) {
+ return KeywordTable::FromWebDatabase(db)->PerformOperations(operations)
+ ? WebDatabase::COMMIT_NEEDED
+ : WebDatabase::COMMIT_NOT_NEEDED;
}
-WDKeywordsResult::WDKeywordsResult(const WDKeywordsResult& other) = default;
+std::unique_ptr<WDTypedResult> GetKeywordsImpl(WebDatabase* db) {
+ KeywordTable* const keyword_table = KeywordTable::FromWebDatabase(db);
+ WDKeywordsResult result;
+ if (!keyword_table->GetKeywords(&result.keywords))
+ return nullptr;
+
+ result.default_search_provider_id =
+ keyword_table->GetDefaultSearchProviderID();
+ result.builtin_keyword_version = keyword_table->GetBuiltinKeywordVersion();
+ return std::make_unique<WDResult<WDKeywordsResult>>(KEYWORDS_RESULT, result);
+}
+
+WebDatabase::State SetDefaultSearchProviderIDImpl(TemplateURLID id,
+ WebDatabase* db) {
+ return KeywordTable::FromWebDatabase(db)->SetDefaultSearchProviderID(id)
+ ? WebDatabase::COMMIT_NEEDED
+ : WebDatabase::COMMIT_NOT_NEEDED;
+}
+
+WebDatabase::State SetBuiltinKeywordVersionImpl(int version, WebDatabase* db) {
+ return KeywordTable::FromWebDatabase(db)->SetBuiltinKeywordVersion(version)
+ ? WebDatabase::COMMIT_NEEDED
+ : WebDatabase::COMMIT_NOT_NEEDED;
+}
+
+} // namespace
+
+WDKeywordsResult::WDKeywordsResult() = default;
+
+WDKeywordsResult::WDKeywordsResult(const WDKeywordsResult&) = default;
+
+WDKeywordsResult& WDKeywordsResult::operator=(const WDKeywordsResult&) =
+ default;
-WDKeywordsResult::~WDKeywordsResult() {}
+WDKeywordsResult::~WDKeywordsResult() = default;
KeywordWebDataService::BatchModeScoper::BatchModeScoper(
KeywordWebDataService* service)
@@ -40,7 +76,10 @@ KeywordWebDataService::KeywordWebDataService(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
const ProfileErrorCallback& callback)
: WebDataServiceBase(wdbs, callback, ui_task_runner),
- batch_mode_level_(0) {}
+ timer_(FROM_HERE,
+ base::TimeDelta::FromSeconds(5),
+ base::BindRepeating(&KeywordWebDataService::CommitQueuedOperations,
+ base::Unretained(this))) {}
void KeywordWebDataService::AddKeyword(const TemplateURLData& data) {
if (batch_mode_level_) {
@@ -79,25 +118,27 @@ void KeywordWebDataService::UpdateKeyword(const TemplateURLData& data) {
WebDataServiceBase::Handle KeywordWebDataService::GetKeywords(
WebDataServiceConsumer* consumer) {
+ // Force pending changes to be visible immediately so the results of this call
+ // won't be out of date.
+ CommitQueuedOperations();
+
return wdbs_->ScheduleDBTaskWithResult(
- FROM_HERE, Bind(&KeywordWebDataService::GetKeywordsImpl, this), consumer);
+ FROM_HERE, base::Bind(&GetKeywordsImpl), consumer);
}
void KeywordWebDataService::SetDefaultSearchProviderID(TemplateURLID id) {
- wdbs_->ScheduleDBTask(
- FROM_HERE,
- Bind(&KeywordWebDataService::SetDefaultSearchProviderIDImpl, this, id));
+ wdbs_->ScheduleDBTask(FROM_HERE,
+ base::Bind(&SetDefaultSearchProviderIDImpl, id));
}
void KeywordWebDataService::SetBuiltinKeywordVersion(int version) {
- wdbs_->ScheduleDBTask(
- FROM_HERE,
- Bind(&KeywordWebDataService::SetBuiltinKeywordVersionImpl,
- this, version));
+ wdbs_->ScheduleDBTask(FROM_HERE,
+ base::Bind(&SetBuiltinKeywordVersionImpl, version));
}
KeywordWebDataService::~KeywordWebDataService() {
DCHECK(!batch_mode_level_);
+ CommitQueuedOperations();
}
void KeywordWebDataService::AdjustBatchModeLevel(bool entering_batch_mode) {
@@ -106,47 +147,25 @@ void KeywordWebDataService::AdjustBatchModeLevel(bool entering_batch_mode) {
} else {
DCHECK(batch_mode_level_);
--batch_mode_level_;
- if (!batch_mode_level_ && !queued_keyword_operations_.empty()) {
- wdbs_->ScheduleDBTask(
- FROM_HERE,
- Bind(&KeywordWebDataService::PerformKeywordOperationsImpl, this,
- queued_keyword_operations_));
- queued_keyword_operations_.clear();
+ if (!batch_mode_level_ && !queued_keyword_operations_.empty() &&
+ !timer_.IsRunning()) {
+ // When killing an app on Android/iOS, shutdown isn't guaranteed to be
+ // called. Finishing this task immediately ensures the table is fully
+ // populated even if the app is killed before the timer expires.
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ CommitQueuedOperations();
+#else
+ timer_.Reset();
+#endif
}
}
}
-WebDatabase::State KeywordWebDataService::PerformKeywordOperationsImpl(
- const KeywordTable::Operations& operations,
- WebDatabase* db) {
- return KeywordTable::FromWebDatabase(db)->PerformOperations(operations) ?
- WebDatabase::COMMIT_NEEDED : WebDatabase::COMMIT_NOT_NEEDED;
-}
-
-std::unique_ptr<WDTypedResult> KeywordWebDataService::GetKeywordsImpl(
- WebDatabase* db) {
- std::unique_ptr<WDTypedResult> result_ptr;
- WDKeywordsResult result;
- if (KeywordTable::FromWebDatabase(db)->GetKeywords(&result.keywords)) {
- result.default_search_provider_id =
- KeywordTable::FromWebDatabase(db)->GetDefaultSearchProviderID();
- result.builtin_keyword_version =
- KeywordTable::FromWebDatabase(db)->GetBuiltinKeywordVersion();
- result_ptr.reset(new WDResult<WDKeywordsResult>(KEYWORDS_RESULT, result));
+void KeywordWebDataService::CommitQueuedOperations() {
+ if (!queued_keyword_operations_.empty()) {
+ wdbs_->ScheduleDBTask(FROM_HERE, base::Bind(&PerformKeywordOperationsImpl,
+ queued_keyword_operations_));
+ queued_keyword_operations_.clear();
}
- return result_ptr;
-}
-
-WebDatabase::State KeywordWebDataService::SetDefaultSearchProviderIDImpl(
- TemplateURLID id,
- WebDatabase* db) {
- return KeywordTable::FromWebDatabase(db)->SetDefaultSearchProviderID(id) ?
- WebDatabase::COMMIT_NEEDED : WebDatabase::COMMIT_NOT_NEEDED;
-}
-
-WebDatabase::State KeywordWebDataService::SetBuiltinKeywordVersionImpl(
- int version,
- WebDatabase* db) {
- return KeywordTable::FromWebDatabase(db)->SetBuiltinKeywordVersion(version) ?
- WebDatabase::COMMIT_NEEDED : WebDatabase::COMMIT_NOT_NEEDED;
+ timer_.Stop();
}
diff --git a/chromium/components/search_engines/keyword_web_data_service.h b/chromium/components/search_engines/keyword_web_data_service.h
index f97f03638db..2b4a16cfdbe 100644
--- a/chromium/components/search_engines/keyword_web_data_service.h
+++ b/chromium/components/search_engines/keyword_web_data_service.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/timer/timer.h"
#include "components/search_engines/keyword_table.h"
#include "components/search_engines/template_url_id.h"
#include "components/webdata/common/web_data_service_base.h"
@@ -19,21 +20,21 @@ namespace base {
class SingleThreadTaskRunner;
}
-class WDTypedResult;
class WebDatabaseService;
struct TemplateURLData;
struct WDKeywordsResult {
WDKeywordsResult();
- WDKeywordsResult(const WDKeywordsResult& other);
+ WDKeywordsResult(const WDKeywordsResult&);
+ WDKeywordsResult& operator=(const WDKeywordsResult&);
~WDKeywordsResult();
KeywordTable::Keywords keywords;
// Identifies the ID of the TemplateURL that is the default search. A value of
// 0 indicates there is no default search provider.
- int64_t default_search_provider_id;
+ int64_t default_search_provider_id = 0;
// Version of the built-in keywords. A value of 0 indicates a first run.
- int builtin_keyword_version;
+ int builtin_keyword_version = 0;
};
class WebDataServiceConsumer;
@@ -43,8 +44,8 @@ class KeywordWebDataService : public WebDataServiceBase {
// Instantiate this to turn on batch mode on the provided |service|
// until the scoper is destroyed. When batch mode is on, calls to any of the
// three keyword table modification functions below will result in locally
- // queueing the operation; on setting this back to false, all the
- // modifications will be performed at once. This is a performance
+ // queueing the operation; on setting this back to false, after a short delay,
+ // all the modifications will be performed at once. This is a performance
// optimization; see comments on KeywordTable::PerformOperations().
//
// If multiple scopers are in-scope simultaneously, batch mode will only be
@@ -94,21 +95,13 @@ class KeywordWebDataService : public WebDataServiceBase {
// Called by the BatchModeScoper (see comments there).
void AdjustBatchModeLevel(bool entering_batch_mode);
- //////////////////////////////////////////////////////////////////////////////
- //
- // The following methods are only invoked on the DB sequence.
- //
- //////////////////////////////////////////////////////////////////////////////
- WebDatabase::State PerformKeywordOperationsImpl(
- const KeywordTable::Operations& operations,
- WebDatabase* db);
- std::unique_ptr<WDTypedResult> GetKeywordsImpl(WebDatabase* db);
- WebDatabase::State SetDefaultSearchProviderIDImpl(TemplateURLID id,
- WebDatabase* db);
- WebDatabase::State SetBuiltinKeywordVersionImpl(int version, WebDatabase* db);
-
- size_t batch_mode_level_;
+ // Schedules a task to commit any |queued_keyword_operations_| immediately.
+ void CommitQueuedOperations();
+
+ size_t batch_mode_level_ = 0;
KeywordTable::Operations queued_keyword_operations_;
+ base::RetainingOneShotTimer timer_; // Used to commit updates no more often
+ // than every five seconds.
DISALLOW_COPY_AND_ASSIGN(KeywordWebDataService);
};
diff --git a/chromium/components/search_engines/prepopulated_engines.json b/chromium/components/search_engines/prepopulated_engines.json
index 3dedb8cc630..b0474152926 100644
--- a/chromium/components/search_engines/prepopulated_engines.json
+++ b/chromium/components/search_engines/prepopulated_engines.json
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// This file is used during build to generate prepopulated_engine.h/cc.
+// This file is used during build to generate prepopulated_engines.h/cc.
// For more details see tools/json_to_struct/json_to_struct.py.
// Engine definitions. See prepopulated_engines_schema.json for the field
@@ -28,26 +28,22 @@
// Increment this if you change the data in ways that mean users with
// existing data should get a new version. Otherwise, existing data may
// continue to be used and updates made here will not always appear.
- "kCurrentDataVersion": 115
+ "kCurrentDataVersion": 116
},
// The following engines are included in country lists and are added to the
// list of search engines on the first run depending on user's country.
"elements": {
- // Ask and Ask UK have suggestion URLs reachable over HTTPS, but they
- // throw a certificate error, so those will remain as HTTP for now.
"ask": {
"name": "Ask",
"keyword": "ask.com",
"favicon_url": "https://sp.ask.com/sh/i/a16/favicon/favicon.ico",
"search_url": "https://www.ask.com/web?q={searchTerms}",
- "suggest_url": "http://ss.ask.com/query?q={searchTerms}&li=ff",
+ "suggest_url": "https://lss.sse-iacapps.com/query?q={searchTerms}&li=ff",
"type": "SEARCH_ENGINE_ASK",
"id": 4
},
- // Baidu's suggestion URL is not reachable over HTTPS, so it remains as
- // HTTP for now.
"baidu": {
"name": "\u767e\u5ea6",
"keyword": "baidu.com",
@@ -58,7 +54,7 @@
"https://www.baidu.com/s?ie={inputEncoding}&word={searchTerms}",
"https://www.baidu.com/{google:pathWildcard}/s?ie={inputEncoding}&word={searchTerms}"
],
- "suggest_url": "http://suggestion.baidu.com/su?wd={searchTerms}&action=opensearch&ie={inputEncoding}",
+ "suggest_url": "https://suggestion.baidu.com/su?wd={searchTerms}&action=opensearch&ie={inputEncoding}",
"type": "SEARCH_ENGINE_BAIDU",
"id": 21
},
diff --git a/chromium/components/search_engines/prepopulated_engines_schema.json b/chromium/components/search_engines/prepopulated_engines_schema.json
index 69773603cbf..c46435e37b6 100644
--- a/chromium/components/search_engines/prepopulated_engines_schema.json
+++ b/chromium/components/search_engines/prepopulated_engines_schema.json
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// This file is used by json_to_struct.py to generate prepopulated_engine.h/cc.
+// This file is used by json_to_struct.py to generate prepopulated_engines.h/cc.
// Any time you modify this file regenerate the .h/.cc. See
// prepopulated_engines.json for details.
diff --git a/chromium/components/search_engines/search_engines_test_util.cc b/chromium/components/search_engines/search_engines_test_util.cc
index 4d6239fc60b..c78e7cbbaf7 100644
--- a/chromium/components/search_engines/search_engines_test_util.cc
+++ b/chromium/components/search_engines/search_engines_test_util.cc
@@ -53,6 +53,7 @@ void ExpectSimilar(const TemplateURLData* expected,
EXPECT_EQ(expected->safe_for_autoreplace, actual->safe_for_autoreplace);
EXPECT_EQ(expected->input_encodings, actual->input_encodings);
EXPECT_EQ(expected->alternate_urls, actual->alternate_urls);
+ EXPECT_EQ(expected->created_from_play_api, actual->created_from_play_api);
}
void SetExtensionDefaultSearchInPrefs(
diff --git a/chromium/components/search_engines/search_terms_data.cc b/chromium/components/search_engines/search_terms_data.cc
index 1bd615e5bb4..441fb9e1b04 100644
--- a/chromium/components/search_engines/search_terms_data.cc
+++ b/chromium/components/search_engines/search_terms_data.cc
@@ -5,7 +5,7 @@
#include "components/search_engines/search_terms_data.h"
#include "base/logging.h"
-#include "components/google/core/browser/google_url_tracker.h"
+#include "components/google/core/common/google_util.h"
#include "url/gurl.h"
SearchTermsData::SearchTermsData() {
@@ -15,7 +15,7 @@ SearchTermsData::~SearchTermsData() {
}
std::string SearchTermsData::GoogleBaseURLValue() const {
- return GoogleURLTracker::kDefaultGoogleHomepage;
+ return google_util::kGoogleHomepageURL;
}
std::string SearchTermsData::GoogleBaseSuggestURLValue() const {
diff --git a/chromium/components/search_engines/template_url.cc b/chromium/components/search_engines/template_url.cc
index 15c5ccd1f89..96c96e154c4 100644
--- a/chromium/components/search_engines/template_url.cc
+++ b/chromium/components/search_engines/template_url.cc
@@ -386,6 +386,11 @@ std::string TemplateURLRef::ReplaceSearchTerms(
query_params.push_back(search_terms_args.additional_query_params);
if (!gurl.query().empty())
query_params.push_back(gurl.query());
+ if (owner_->created_from_play_api()) {
+ // Append attribution parameter to query originating from Play API search
+ // engine.
+ query_params.push_back("chrome_dse_attribution=1");
+ }
if (query_params.empty())
return url;
diff --git a/chromium/components/search_engines/template_url.h b/chromium/components/search_engines/template_url.h
index 303720d2105..1cfa0196ed7 100644
--- a/chromium/components/search_engines/template_url.h
+++ b/chromium/components/search_engines/template_url.h
@@ -651,6 +651,7 @@ class TemplateURL {
base::Time last_visited() const { return data_.last_visited; }
bool created_by_policy() const { return data_.created_by_policy; }
+ bool created_from_play_api() const { return data_.created_from_play_api; }
int usage_count() const { return data_.usage_count; }
diff --git a/chromium/components/search_engines/template_url_data.cc b/chromium/components/search_engines/template_url_data.cc
index e7cfd6cc4af..6a9635ec085 100644
--- a/chromium/components/search_engines/template_url_data.cc
+++ b/chromium/components/search_engines/template_url_data.cc
@@ -40,6 +40,7 @@ TemplateURLData::TemplateURLData()
last_modified(base::Time::Now()),
last_visited(base::Time()),
created_by_policy(false),
+ created_from_play_api(false),
usage_count(0),
prepopulate_id(0),
sync_guid(base::GenerateGUID()),
@@ -48,6 +49,9 @@ TemplateURLData::TemplateURLData()
TemplateURLData::TemplateURLData(const TemplateURLData& other) = default;
+TemplateURLData& TemplateURLData::operator=(const TemplateURLData& other) =
+ default;
+
TemplateURLData::TemplateURLData(const base::string16& name,
const base::string16& keyword,
base::StringPiece search_url,
@@ -79,6 +83,7 @@ TemplateURLData::TemplateURLData(const base::string16& name,
date_created(base::Time()),
last_modified(base::Time()),
created_by_policy(false),
+ created_from_play_api(false),
usage_count(0),
prepopulate_id(prepopulate_id),
sync_guid(GenerateGUID(prepopulate_id)) {
@@ -94,8 +99,7 @@ TemplateURLData::TemplateURLData(const base::string16& name,
}
}
-TemplateURLData::~TemplateURLData() {
-}
+TemplateURLData::~TemplateURLData() = default;
void TemplateURLData::SetShortName(const base::string16& short_name) {
// Remove tabs, carriage returns, and the like, as they can corrupt
diff --git a/chromium/components/search_engines/template_url_data.h b/chromium/components/search_engines/template_url_data.h
index 1f7724081ea..6d419921286 100644
--- a/chromium/components/search_engines/template_url_data.h
+++ b/chromium/components/search_engines/template_url_data.h
@@ -23,6 +23,7 @@ class ListValue;
struct TemplateURLData {
TemplateURLData();
TemplateURLData(const TemplateURLData& other);
+ TemplateURLData& operator=(const TemplateURLData& other);
// Creates a TemplateURLData suitable for prepopulated engines.
// Note that unlike in the default constructor, |safe_for_autoreplace| will
@@ -132,6 +133,9 @@ struct TemplateURLData {
// group policy.
bool created_by_policy;
+ // True if this TemplateURL was created from metadata received from Play API.
+ bool created_from_play_api;
+
// Number of times this TemplateURL has been explicitly used to load a URL.
// We don't increment this for uses as the "default search engine" since
// that's not really "explicit" usage and incrementing would result in pinning
diff --git a/chromium/components/search_engines/template_url_data_util.cc b/chromium/components/search_engines/template_url_data_util.cc
index b03157ea349..12bfdf64db7 100644
--- a/chromium/components/search_engines/template_url_data_util.cc
+++ b/chromium/components/search_engines/template_url_data_util.cc
@@ -108,6 +108,8 @@ std::unique_ptr<TemplateURLData> TemplateURLDataFromDictionary(
dict.GetBoolean(DefaultSearchManager::kCreatedByPolicy,
&result->created_by_policy);
+ dict.GetBoolean(DefaultSearchManager::kCreatedFromPlayAPI,
+ &result->created_from_play_api);
return result;
}
@@ -170,6 +172,8 @@ std::unique_ptr<base::DictionaryValue> TemplateURLDataToDictionary(
url_dict->SetBoolean(DefaultSearchManager::kCreatedByPolicy,
data.created_by_policy);
+ url_dict->SetBoolean(DefaultSearchManager::kCreatedFromPlayAPI,
+ data.created_from_play_api);
return url_dict;
}
diff --git a/chromium/components/search_engines/template_url_service.cc b/chromium/components/search_engines/template_url_service.cc
index 3537b677866..fac5d6d2b45 100644
--- a/chromium/components/search_engines/template_url_service.cc
+++ b/chromium/components/search_engines/template_url_service.cc
@@ -282,14 +282,12 @@ TemplateURLService::TemplateURLService(
std::unique_ptr<SearchTermsData> search_terms_data,
const scoped_refptr<KeywordWebDataService>& web_data_service,
std::unique_ptr<TemplateURLServiceClient> client,
- GoogleURLTracker* google_url_tracker,
rappor::RapporServiceImpl* rappor_service,
const base::Closure& dsp_change_callback)
: prefs_(prefs),
search_terms_data_(std::move(search_terms_data)),
web_data_service_(web_data_service),
client_(std::move(client)),
- google_url_tracker_(google_url_tracker),
rappor_service_(rappor_service),
dsp_change_callback_(dsp_change_callback),
default_search_manager_(
@@ -366,8 +364,9 @@ bool TemplateURLService::CanAddAutogeneratedKeyword(
bool TemplateURLService::IsPrepopulatedOrCreatedByPolicy(
const TemplateURL* t_url) const {
- return (t_url->prepopulate_id() > 0 || t_url->created_by_policy()) &&
- t_url->SupportsReplacement(search_terms_data());
+ return (t_url->prepopulate_id() > 0 || t_url->created_by_policy() ||
+ t_url->created_from_play_api()) &&
+ t_url->SupportsReplacement(search_terms_data());
}
bool TemplateURLService::ShowInDefaultList(const TemplateURL* t_url) const {
@@ -618,6 +617,32 @@ void TemplateURLService::ResetTemplateURL(TemplateURL* url,
Update(url, TemplateURL(data));
}
+TemplateURL* TemplateURLService::CreateOrUpdateTemplateURLFromPlayAPIData(
+ const base::string16& title,
+ const base::string16& keyword,
+ const std::string& search_url,
+ const std::string& suggestions_url,
+ const std::string& favicon_url) {
+ TemplateURL* existing_turl = FindNonExtensionTemplateURLForKeyword(keyword);
+ TemplateURLData data;
+ if (existing_turl)
+ data = existing_turl->data();
+ data.SetShortName(title);
+ data.SetKeyword(keyword);
+ data.SetURL(search_url);
+ data.suggestions_url = suggestions_url;
+ data.favicon_url = GURL(favicon_url);
+ data.safe_for_autoreplace = true;
+ data.created_from_play_api = true;
+ if (existing_turl) {
+ Update(existing_turl, TemplateURL(data));
+ } else {
+ existing_turl = Add(std::make_unique<TemplateURL>(data));
+ DCHECK(existing_turl);
+ }
+ return existing_turl;
+}
+
void TemplateURLService::UpdateProviderFavicons(
const GURL& potential_search_url,
const GURL& favicon_url) {
@@ -759,7 +784,6 @@ void TemplateURLService::RepairPrepopulatedSearchEngines() {
prefs_->SetString(prefs::kSyncedDefaultSearchProviderGUID,
fallback_engine->sync_guid());
}
- RequestGoogleURLTrackerServerCheckIfNecessary();
} else {
// If the default search provider came from a user pref we would have been
// notified of the new (fallback-provided) value in
@@ -1386,13 +1410,6 @@ void TemplateURLService::Init(const Initializer* initializers,
if (client_)
client_->SetOwner(this);
- // GoogleURLTracker is not created in tests.
- if (google_url_tracker_) {
- google_url_updated_subscription_ =
- google_url_tracker_->RegisterCallback(base::Bind(
- &TemplateURLService::GoogleBaseURLChanged, base::Unretained(this)));
- }
-
if (prefs_) {
pref_change_registrar_.Init(prefs_);
pref_change_registrar_.Add(
@@ -1434,10 +1451,6 @@ void TemplateURLService::Init(const Initializer* initializers,
default_search_manager_.SetUserSelectedDefaultSearchEngine(data);
}
}
-
- // Request a server check for the correct Google URL if Google is the
- // default search engine.
- RequestGoogleURLTrackerServerCheckIfNecessary();
}
TemplateURL* TemplateURLService::BestEngineForKeyword(TemplateURL* engine1,
@@ -1804,71 +1817,6 @@ void TemplateURLService::AddTabToSearchVisit(const TemplateURL& t_url) {
client_->AddKeywordGeneratedVisit(url);
}
-void TemplateURLService::RequestGoogleURLTrackerServerCheckIfNecessary() {
- if (default_search_provider_ &&
- default_search_provider_->HasGoogleBaseURLs(search_terms_data()) &&
- google_url_tracker_)
- google_url_tracker_->RequestServerCheck();
-}
-
-void TemplateURLService::GoogleBaseURLChanged() {
- if (!loaded_) {
- if (initial_default_search_provider_.get() &&
- initial_default_search_provider_->HasGoogleBaseURLs(
- search_terms_data())) {
- initial_default_search_provider_->InvalidateCachedValues();
- initial_default_search_provider_->ResetKeywordIfNecessary(
- search_terms_data(), false);
- }
- return;
- }
-
- // Prepare the queue of TemplateURLs which must be updated. We cannot directly
- // iterate through template_urls_ while we're updating because sometimes we
- // want to remove TemplateURL.
- std::set<TemplateURL*> turls_to_update;
- for (const auto& turl : template_urls_)
- turls_to_update.insert(turl.get());
-
- Scoper scoper(this);
-
- while (!turls_to_update.empty()) {
- auto it = turls_to_update.begin();
- TemplateURL* turl = *it;
- turls_to_update.erase(it);
- if (turl->HasGoogleBaseURLs(search_terms_data())) {
- TemplateURL updated_turl(turl->data());
- updated_turl.ResetKeywordIfNecessary(search_terms_data(), false);
- KeywordToTURLAndMeaningfulLength::const_iterator existing_entry =
- keyword_to_turl_and_length_.find(updated_turl.keyword());
- if (existing_entry != keyword_to_turl_and_length_.end()) {
- TemplateURL* existing_turl = existing_entry->second.first;
- if (existing_turl != turl) {
- // The new autogenerated keyword conflicts with another TemplateURL.
- // Overwrite it if it's replaceable; otherwise, leave |turl| using its
- // current keyword. (This will not prevent |turl| from auto-updating
- // the keyword in the future if the conflicting TemplateURL
- // disappears.) Note that we must still update |turl| in this case, or
- // the |provider_map_| will not be updated correctly.
- if (CanReplace(existing_turl)) {
- Remove(existing_turl);
- // Remove |existing_url| from the queue we're iterating through.
- // Perhaps there is no |existing_url| in this queue already if this
- // cycle processed |existing_url| before |turl|.
- turls_to_update.erase(existing_turl);
- } else {
- updated_turl.data_.SetKeyword(turl->keyword());
- }
- }
- }
- // This will send the keyword change to sync. Note that other clients
- // need to reset the keyword to an appropriate local value when this
- // change arrives; see CreateTemplateURLFromTemplateURLAndSyncData().
- Update(turl, updated_turl);
- }
- }
-}
-
void TemplateURLService::ApplyDefaultSearchChange(
const TemplateURLData* data,
DefaultSearchManager::Source source) {
@@ -1986,7 +1934,6 @@ bool TemplateURLService::ApplyDefaultSearchChangeNoMetrics(
bool changed = default_search_provider_ != previous_default_search_engine;
if (changed) {
model_mutated_notification_pending_ = true;
- RequestGoogleURLTrackerServerCheckIfNecessary();
}
return changed;
diff --git a/chromium/components/search_engines/template_url_service.h b/chromium/components/search_engines/template_url_service.h
index 8c03c40f839..e77dea75e19 100644
--- a/chromium/components/search_engines/template_url_service.h
+++ b/chromium/components/search_engines/template_url_service.h
@@ -21,7 +21,6 @@
#include "base/observer_list.h"
#include "base/time/default_clock.h"
#include "build/build_config.h"
-#include "components/google/core/browser/google_url_tracker.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/search_engines/default_search_manager.h"
@@ -113,7 +112,6 @@ class TemplateURLService : public WebDataServiceConsumer,
std::unique_ptr<SearchTermsData> search_terms_data,
const scoped_refptr<KeywordWebDataService>& web_data_service,
std::unique_ptr<TemplateURLServiceClient> client,
- GoogleURLTracker* google_url_tracker,
rappor::RapporServiceImpl* rappor_service,
const base::RepeatingClosure& dsp_change_callback);
// The following is for testing.
@@ -256,6 +254,16 @@ class TemplateURLService : public WebDataServiceConsumer,
const base::string16& keyword,
const std::string& search_url);
+ // Creates TemplateURL, populating it with data from Play API. If TemplateURL
+ // with matching keyword already exists then merges Play API data into it.
+ // Sets |created_from_play_api| flag.
+ TemplateURL* CreateOrUpdateTemplateURLFromPlayAPIData(
+ const base::string16& title,
+ const base::string16& keyword,
+ const std::string& search_url,
+ const std::string& suggestions_url,
+ const std::string& favicon_url);
+
// Updates any search providers matching |potential_search_url| with the new
// favicon location |favicon_url|.
void UpdateProviderFavicons(const GURL& potential_search_url,
@@ -605,14 +613,6 @@ class TemplateURLService : public WebDataServiceConsumer,
// If necessary, generates a visit for the site http:// + t_url.keyword().
void AddTabToSearchVisit(const TemplateURL& t_url);
- // Requests the Google URL tracker to check the server if necessary.
- void RequestGoogleURLTrackerServerCheckIfNecessary();
-
- // Invoked when the Google base URL has changed. Updates the mapping for all
- // TemplateURLs that have a replacement term of {google:baseURL} or
- // {google:baseSuggestURL}.
- void GoogleBaseURLChanged();
-
// Adds a new TemplateURL to this model.
//
// If |newly_adding| is false, we assume that this TemplateURL was already
@@ -742,8 +742,6 @@ class TemplateURLService : public WebDataServiceConsumer,
std::unique_ptr<TemplateURLServiceClient> client_;
- GoogleURLTracker* google_url_tracker_ = nullptr;
-
// ---------- Metrics related members ---------------------------------------
rappor::RapporServiceImpl* rappor_service_ = nullptr;
@@ -850,9 +848,6 @@ class TemplateURLService : public WebDataServiceConsumer,
// Helper class to manage the default search engine.
DefaultSearchManager default_search_manager_;
- std::unique_ptr<GoogleURLTracker::Subscription>
- google_url_updated_subscription_;
-
// This tracks how many Scoper handles exist. When the number of handles drops
// to zero, a notification is made to observers if
// |model_mutated_notification_pending_| is true.
diff --git a/chromium/components/search_engines/template_url_service_util_unittest.cc b/chromium/components/search_engines/template_url_service_util_unittest.cc
index 644696f0b41..172662684d5 100644
--- a/chromium/components/search_engines/template_url_service_util_unittest.cc
+++ b/chromium/components/search_engines/template_url_service_util_unittest.cc
@@ -8,6 +8,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
#include "components/search_engines/search_terms_data.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
@@ -18,13 +19,16 @@ namespace {
std::unique_ptr<TemplateURLData> CreatePrepopulateTemplateURLData(
int prepopulate_id,
- const std::string& keyword,
- TemplateURLID id) {
- std::unique_ptr<TemplateURLData> data(new TemplateURLData);
- data->prepopulate_id = prepopulate_id;
- data->SetKeyword(base::ASCIIToUTF16(keyword));
- data->id = id;
- return data;
+ const std::string& keyword) {
+ return std::make_unique<TemplateURLData>(
+ base::ASCIIToUTF16("Search engine name"), base::ASCIIToUTF16(keyword),
+ "https://search.url", nullptr /* suggest_url */, nullptr /* image_url */,
+ nullptr /* new_tab_url */, nullptr /* contextual_search_url */,
+ nullptr /* logo_url */, nullptr /* doodle_url */,
+ nullptr /* search_url_post_params */,
+ nullptr /* suggest_url_post_params */,
+ nullptr /* image_url_post_params */, nullptr /* favicon_url */, "UTF-8",
+ base::ListValue() /* alternate_urls_list */, prepopulate_id);
}
// Creates a TemplateURL with default values except for the prepopulate ID,
@@ -33,9 +37,13 @@ std::unique_ptr<TemplateURLData> CreatePrepopulateTemplateURLData(
std::unique_ptr<TemplateURL> CreatePrepopulateTemplateURL(
int prepopulate_id,
const std::string& keyword,
- TemplateURLID id) {
- return std::make_unique<TemplateURL>(
- *CreatePrepopulateTemplateURLData(prepopulate_id, keyword, id));
+ TemplateURLID id,
+ bool is_play_api_turl = false) {
+ std::unique_ptr<TemplateURLData> data =
+ CreatePrepopulateTemplateURLData(prepopulate_id, keyword);
+ data->id = id;
+ data->created_from_play_api = is_play_api_turl;
+ return std::make_unique<TemplateURL>(*data);
}
} // namespace
@@ -44,10 +52,9 @@ TEST(TemplateURLServiceUtilTest, RemoveDuplicatePrepopulateIDs) {
std::vector<std::unique_ptr<TemplateURLData>> prepopulated_turls;
TemplateURLService::OwnedTemplateURLVector local_turls;
- prepopulated_turls.push_back(
- CreatePrepopulateTemplateURLData(1, "winner4", 1));
- prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(2, "xxx", 2));
- prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(3, "yyy", 3));
+ prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(1, "winner4"));
+ prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(2, "xxx"));
+ prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(3, "yyy"));
// Create a sets of different TURLs grouped by prepopulate ID. Each group
// will test a different heuristic of RemoveDuplicatePrepopulateIDs.
@@ -89,3 +96,46 @@ TEST(TemplateURLServiceUtilTest, RemoveDuplicatePrepopulateIDs) {
base::CompareCase::SENSITIVE));
}
}
+
+// Tests correct interaction of Play API search engine during prepopulated list
+// update.
+TEST(TemplateURLServiceUtilTest, MergeEnginesFromPrepopulateData_PlayAPI) {
+ std::vector<std::unique_ptr<TemplateURLData>> prepopulated_turls;
+ TemplateURLService::OwnedTemplateURLVector local_turls;
+
+ // Start with single search engine created from Play API data.
+ local_turls.push_back(CreatePrepopulateTemplateURL(0, "play", 1, true));
+
+ // Test that prepopulated search engine with matching keyword is merged with
+ // Play API search engine. Search URL should come from Play API search engine.
+ const std::string prepopulated_search_url = "http://prepopulated.url";
+ prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(1, "play"));
+ prepopulated_turls.back()->SetURL(prepopulated_search_url);
+ MergeEnginesFromPrepopulateData(nullptr, &prepopulated_turls, &local_turls,
+ nullptr, nullptr);
+ ASSERT_EQ(local_turls.size(), 1U);
+ // Merged search engine should have both Play API flag and valid
+ // prepopulate_id.
+ EXPECT_TRUE(local_turls[0]->created_from_play_api());
+ EXPECT_EQ(1, local_turls[0]->prepopulate_id());
+ EXPECT_NE(prepopulated_search_url, local_turls[0]->url());
+
+ // Test that merging prepopulated search engine with matching prepopulate_id
+ // preserves keyword of Play API search engine.
+ prepopulated_turls.clear();
+ prepopulated_turls.push_back(CreatePrepopulateTemplateURLData(1, "play2"));
+ MergeEnginesFromPrepopulateData(nullptr, &prepopulated_turls, &local_turls,
+ nullptr, nullptr);
+ ASSERT_EQ(local_turls.size(), 1U);
+ EXPECT_TRUE(local_turls[0]->created_from_play_api());
+ EXPECT_EQ(local_turls[0]->keyword(), base::ASCIIToUTF16("play"));
+
+ // Test that removing search engine from prepopulated list doesn't delete Play
+ // API search engine record.
+ prepopulated_turls.clear();
+ MergeEnginesFromPrepopulateData(nullptr, &prepopulated_turls, &local_turls,
+ nullptr, nullptr);
+ ASSERT_EQ(local_turls.size(), 1U);
+ EXPECT_TRUE(local_turls[0]->created_from_play_api());
+ EXPECT_EQ(local_turls[0]->prepopulate_id(), 0);
+}
diff --git a/chromium/components/search_engines/template_url_unittest.cc b/chromium/components/search_engines/template_url_unittest.cc
index a19a834af10..a96c8a0f415 100644
--- a/chromium/components/search_engines/template_url_unittest.cc
+++ b/chromium/components/search_engines/template_url_unittest.cc
@@ -802,6 +802,33 @@ TEST_F(TemplateURLTest, ReplaceCurrentPageUrl) {
}
}
+// Tests appending attribution parameter to queries originating from Play API
+// search engine.
+TEST_F(TemplateURLTest, PlayAPIAttribution) {
+ const struct TestData {
+ const char* url;
+ base::string16 terms;
+ bool created_from_play_api;
+ const char* output;
+ } test_data[] = {{"http://foo/?q={searchTerms}", ASCIIToUTF16("bar"), false,
+ "http://foo/?q=bar"},
+ {"http://foo/?q={searchTerms}", ASCIIToUTF16("bar"), true,
+ "http://foo/?q=bar&chrome_dse_attribution=1"}};
+ TemplateURLData data;
+ for (size_t i = 0; i < base::size(test_data); ++i) {
+ data.SetURL(test_data[i].url);
+ data.created_from_play_api = test_data[i].created_from_play_api;
+ TemplateURL url(data);
+ EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_));
+ ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_));
+ GURL result(url.url_ref().ReplaceSearchTerms(
+ TemplateURLRef::SearchTermsArgs(test_data[i].terms),
+ search_terms_data_));
+ ASSERT_TRUE(result.is_valid());
+ EXPECT_EQ(test_data[i].output, result.spec());
+ }
+}
+
TEST_F(TemplateURLTest, Suggestions) {
struct TestData {
const int accepted_suggestion;
diff --git a/chromium/components/search_engines/util.cc b/chromium/components/search_engines/util.cc
index d1371e334f8..9f73ffea47d 100644
--- a/chromium/components/search_engines/util.cc
+++ b/chromium/components/search_engines/util.cc
@@ -182,16 +182,31 @@ TemplateURL* FindURLByPrepopulateID(
void MergeIntoPrepopulatedEngineData(const TemplateURL* original_turl,
TemplateURLData* prepopulated_url) {
- DCHECK_EQ(original_turl->prepopulate_id(), prepopulated_url->prepopulate_id);
- if (!original_turl->safe_for_autoreplace()) {
- prepopulated_url->safe_for_autoreplace = false;
- prepopulated_url->SetKeyword(original_turl->keyword());
+ DCHECK(original_turl->prepopulate_id() == 0 ||
+ original_turl->prepopulate_id() == prepopulated_url->prepopulate_id);
+ // When the user modified search engine's properties or search engine is
+ // imported from Play API data we need to preserve certain search engine
+ // properties from overriding with prepopulated data.
+ if (!original_turl->safe_for_autoreplace() ||
+ original_turl->created_from_play_api()) {
+ prepopulated_url->safe_for_autoreplace =
+ original_turl->safe_for_autoreplace();
prepopulated_url->SetShortName(original_turl->short_name());
+ prepopulated_url->SetKeyword(original_turl->keyword());
+ if (original_turl->created_from_play_api()) {
+ // TODO(crbug/1002271): Search url from Play API might contain attribution
+ // info and therefore should be preserved through prepopulated data
+ // update. In the future we might decide to take different approach to
+ // pass attribution info to search providers.
+ prepopulated_url->SetURL(original_turl->url());
+ }
}
prepopulated_url->id = original_turl->id();
prepopulated_url->sync_guid = original_turl->sync_guid();
prepopulated_url->date_created = original_turl->date_created();
prepopulated_url->last_modified = original_turl->last_modified();
+ prepopulated_url->created_from_play_api =
+ original_turl->created_from_play_api();
}
ActionsFromPrepopulateData::ActionsFromPrepopulateData() {}
@@ -201,14 +216,9 @@ ActionsFromPrepopulateData::ActionsFromPrepopulateData(
ActionsFromPrepopulateData::~ActionsFromPrepopulateData() {}
-// This is invoked when the version of the prepopulate data changes.
-// If |removed_keyword_guids| is not NULL, the Sync GUID of each item removed
-// from the DB will be added to it. Note that this function will take
-// ownership of |prepopulated_urls| and will clear the vector.
void MergeEnginesFromPrepopulateData(
KeywordWebDataService* service,
std::vector<std::unique_ptr<TemplateURLData>>* prepopulated_urls,
- size_t default_search_index,
TemplateURLService::OwnedTemplateURLVector* template_urls,
TemplateURL* default_search_provider,
std::set<std::string>* removed_keyword_guids) {
@@ -255,8 +265,13 @@ ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData(
const TemplateURL* default_search_provider) {
// Create a map to hold all provided |template_urls| that originally came from
// prepopulate data (i.e. have a non-zero prepopulate_id()).
+ TemplateURL* play_api_turl = nullptr;
std::map<int, TemplateURL*> id_to_turl;
for (auto& turl : existing_urls) {
+ if (turl->created_from_play_api()) {
+ DCHECK_EQ(nullptr, play_api_turl);
+ play_api_turl = turl.get();
+ }
int prepopulate_id = turl->prepopulate_id();
if (prepopulate_id > 0)
id_to_turl[prepopulate_id] = turl.get();
@@ -272,18 +287,24 @@ ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData(
DCHECK_NE(0, prepopulated_id);
auto existing_url_iter = id_to_turl.find(prepopulated_id);
+ TemplateURL* existing_url = nullptr;
if (existing_url_iter != id_to_turl.end()) {
+ existing_url = existing_url_iter->second;
+ id_to_turl.erase(existing_url_iter);
+ } else if (play_api_turl &&
+ play_api_turl->keyword() == prepopulated_url->keyword()) {
+ existing_url = play_api_turl;
+ }
+
+ if (existing_url != nullptr) {
// Update the data store with the new prepopulated data. Preserve user
// edits to the name and keyword.
- TemplateURL* existing_url(existing_url_iter->second);
- id_to_turl.erase(existing_url_iter);
MergeIntoPrepopulatedEngineData(existing_url, prepopulated_url.get());
// Update last_modified to ensure that if this entry is later merged with
// entries from Sync, the conflict resolution logic knows that this was
// updated and propagates the new values to the server.
prepopulated_url->last_modified = base::Time::Now();
- actions.edited_engines.push_back(
- std::make_pair(existing_url, *prepopulated_url));
+ actions.edited_engines.push_back({existing_url, *prepopulated_url});
} else {
actions.added_engines.push_back(*prepopulated_url);
}
@@ -300,9 +321,18 @@ ActionsFromPrepopulateData CreateActionsFromCurrentPrepopulateData(
if ((template_url->safe_for_autoreplace()) &&
(!default_search_provider ||
(template_url->prepopulate_id() !=
- default_search_provider->prepopulate_id()) ||
- (template_url->keyword() != default_search_provider->keyword())))
- actions.removed_engines.push_back(template_url);
+ default_search_provider->prepopulate_id()) ||
+ (template_url->keyword() != default_search_provider->keyword()))) {
+ if (template_url->created_from_play_api()) {
+ // Don't remove the entry created from Play API. Just reset
+ // prepopulate_id for it.
+ TemplateURLData data = template_url->data();
+ data.prepopulate_id = 0;
+ actions.edited_engines.push_back({template_url, data});
+ } else {
+ actions.removed_engines.push_back(template_url);
+ }
+ }
}
return actions;
@@ -358,10 +388,8 @@ void GetSearchProvidersUsingLoadedEngines(
std::set<std::string>* removed_keyword_guids) {
DCHECK(template_urls);
DCHECK(resource_keyword_version);
- size_t default_search_index;
std::vector<std::unique_ptr<TemplateURLData>> prepopulated_urls =
- TemplateURLPrepopulateData::GetPrepopulatedEngines(prefs,
- &default_search_index);
+ TemplateURLPrepopulateData::GetPrepopulatedEngines(prefs, nullptr);
RemoveDuplicatePrepopulateIDs(service, prepopulated_urls,
default_search_provider, template_urls,
search_terms_data, removed_keyword_guids);
@@ -369,9 +397,9 @@ void GetSearchProvidersUsingLoadedEngines(
const int prepopulate_resource_keyword_version =
TemplateURLPrepopulateData::GetDataVersion(prefs);
if (*resource_keyword_version < prepopulate_resource_keyword_version) {
- MergeEnginesFromPrepopulateData(
- service, &prepopulated_urls, default_search_index, template_urls,
- default_search_provider, removed_keyword_guids);
+ MergeEnginesFromPrepopulateData(service, &prepopulated_urls, template_urls,
+ default_search_provider,
+ removed_keyword_guids);
*resource_keyword_version = prepopulate_resource_keyword_version;
} else {
*resource_keyword_version = 0;
diff --git a/chromium/components/search_engines/util.h b/chromium/components/search_engines/util.h
index d3790c99444..ae10ce2ed12 100644
--- a/chromium/components/search_engines/util.h
+++ b/chromium/components/search_engines/util.h
@@ -68,6 +68,22 @@ struct ActionsFromPrepopulateData {
std::vector<TemplateURLData> added_engines;
};
+// MergeEnginesFromPrepopulateData merges search engines from
+// |prepopulated_urls| into |template_urls|. Calls
+// CreateActionsFromCurrentPrepopulateData() to collect actions and then applies
+// them on |tempate_urls|. MergeEnginesFromPrepopulateData is invoked when the
+// version of the prepopulate data changes. If |removed_keyword_guids| is not
+// nullptr, the Sync GUID of each item removed from the DB will be added to it.
+// Note that this function will take ownership of |prepopulated_urls| and will
+// clear the vector.
+// The function is exposed in header file to provide access from unittests.
+void MergeEnginesFromPrepopulateData(
+ KeywordWebDataService* service,
+ std::vector<std::unique_ptr<TemplateURLData>>* prepopulated_urls,
+ TemplateURLService::OwnedTemplateURLVector* template_urls,
+ TemplateURL* default_search_provider,
+ std::set<std::string>* removed_keyword_guids);
+
// Given the user's current URLs and the current set of prepopulated URLs,
// produces the set of actions (see above) required to make the user's URLs
// reflect the prepopulate data. |default_search_provider| is used to avoid
diff --git a/chromium/components/search_provider_logos/logo_service_impl.cc b/chromium/components/search_provider_logos/logo_service_impl.cc
index b3daa5e366d..2bc599e9fcf 100644
--- a/chromium/components/search_provider_logos/logo_service_impl.cc
+++ b/chromium/components/search_provider_logos/logo_service_impl.cc
@@ -192,8 +192,9 @@ LogoServiceImpl::LogoServiceImpl(
image_decoder_(std::move(image_decoder)),
is_idle_(true),
is_cached_logo_valid_(false),
- cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ cache_task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
logo_cache_(new LogoCache(cache_directory_),
base::OnTaskRunnerDeleter(cache_task_runner_)) {
@@ -719,9 +720,9 @@ void LogoServiceImpl::OnURLLoadComplete(const network::SimpleURLLoader* source,
bool from_http_cache = !source->ResponseInfo()->network_accessed;
bool* parsing_failed = new bool(false);
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(parse_logo_response_func_, std::move(response),
response_time, parsing_failed),
diff --git a/chromium/components/search_provider_logos/logo_service_impl_unittest.cc b/chromium/components/search_provider_logos/logo_service_impl_unittest.cc
index 9e797f333fe..72ce6a3d76b 100644
--- a/chromium/components/search_provider_logos/logo_service_impl_unittest.cc
+++ b/chromium/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -21,8 +21,8 @@
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -418,7 +418,7 @@ class LogoServiceImplTest : public ::testing::Test {
bool use_gray_background() const { return use_gray_background_; }
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
TemplateURLService template_url_service_;
base::SimpleTestClock test_clock_;
NiceMock<MockLogoCache>* logo_cache_;
diff --git a/chromium/components/security_interstitials/OWNERS b/chromium/components/security_interstitials/OWNERS
index e3577f2ce42..0068b8a5a97 100644
--- a/chromium/components/security_interstitials/OWNERS
+++ b/chromium/components/security_interstitials/OWNERS
@@ -1,4 +1,5 @@
carlosil@chromium.org
+drubery@chromium.org
estark@chromium.org
felt@chromium.org
mattm@chromium.org
diff --git a/chromium/components/security_interstitials/content/connection_help_ui.cc b/chromium/components/security_interstitials/content/connection_help_ui.cc
index b48645c8bb8..5b5e77df3a3 100644
--- a/chromium/components/security_interstitials/content/connection_help_ui.cc
+++ b/chromium/components/security_interstitials/content/connection_help_ui.cc
@@ -73,7 +73,7 @@ ConnectionHelpUI::ConnectionHelpUI(content::WebUI* web_ui)
html_source->AddLocalizedString("connectionHelpShowLess",
IDS_CONNECTION_HELP_SHOW_LESS);
- html_source->SetJsonPath("strings.js");
+ html_source->UseStringsJs();
html_source->AddResourcePath("interstitial_core.css",
IDR_SECURITY_INTERSTITIAL_CORE_CSS);
diff --git a/chromium/components/security_interstitials/content/unsafe_resource.cc b/chromium/components/security_interstitials/content/unsafe_resource.cc
index a22e6bef5d1..de6daf0b9b8 100644
--- a/chromium/components/security_interstitials/content/unsafe_resource.cc
+++ b/chromium/components/security_interstitials/content/unsafe_resource.cc
@@ -50,9 +50,12 @@ bool UnsafeResource::IsMainPageLoadBlocked() const {
case safe_browsing::SB_THREAT_TYPE_BLOCKED_AD_REDIRECT:
// Ad sampling happens in the background.
case safe_browsing::SB_THREAT_TYPE_AD_SAMPLE:
- // Sign-in password reuse warning happens after the page is finished
- // loading.
- case safe_browsing::SB_THREAT_TYPE_SIGN_IN_PASSWORD_REUSE:
+ // Chrome GAIA signed in and syncing password reuse warning happens after
+ // the page is finished loading.
+ case safe_browsing::SB_THREAT_TYPE_SIGNED_IN_SYNC_PASSWORD_REUSE:
+ // Chrome GAIA signed in and non-syncing password reuse warning happens
+ // after the page is finished loading.
+ case safe_browsing::SB_THREAT_TYPE_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
// Enterprise password reuse warning happens after the page is finished
// loading.
case safe_browsing::SB_THREAT_TYPE_ENTERPRISE_PASSWORD_REUSE:
diff --git a/chromium/components/security_interstitials/core/BUILD.gn b/chromium/components/security_interstitials/core/BUILD.gn
index 8b0cf365128..7b758549867 100644
--- a/chromium/components/security_interstitials/core/BUILD.gn
+++ b/chromium/components/security_interstitials/core/BUILD.gn
@@ -38,7 +38,7 @@ static_library("core") {
deps = [
"//base",
"//base:i18n",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/history/core/browser",
"//components/metrics",
"//components/prefs",
diff --git a/chromium/components/security_interstitials/core/browser/resources/images/heavy_ad.svg b/chromium/components/security_interstitials/core/browser/resources/images/heavy_ad.svg
new file mode 100644
index 00000000000..7f15c3edc94
--- /dev/null
+++ b/chromium/components/security_interstitials/core/browser/resources/images/heavy_ad.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M-618-440H782v3600H-618zM0 0h24v24H0z"/><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z" fill-opacity=".2"/><path d="M14.392 16.82l1.103-1.102-2.374-2.372 2.379-2.378-1.103-1.102-2.38 2.378L9.632 9.86l-1.103 1.102 2.386 2.384L8.5 15.758l1.103 1.102 2.414-2.413z" fill-opacity=".2"/></svg> \ No newline at end of file
diff --git a/chromium/components/security_interstitials/core/browser/resources/interstitial_large.js b/chromium/components/security_interstitials/core/browser/resources/interstitial_large.js
index 26de41c1b17..d0b2968e700 100644
--- a/chromium/components/security_interstitials/core/browser/resources/interstitial_large.js
+++ b/chromium/components/security_interstitials/core/browser/resources/interstitial_large.js
@@ -186,8 +186,9 @@ function setupEvents() {
});
}
+ var details_id = null;
if (captivePortal || billing || lookalike) {
- // Captive portal, billing and lookalike pages don't have details button.
+ // Captive portal, billing and lookalike pages don't have details buttons.
$('details-button').classList.add('hidden');
} else {
$('details-button').addEventListener('click', function(event) {
diff --git a/chromium/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css b/chromium/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css
index 4dd765d003d..a13e36d2d04 100644
--- a/chromium/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css
+++ b/chromium/components/security_interstitials/core/browser/resources/interstitial_lookalikeurl.css
@@ -2,7 +2,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-.lookalike-url a {
+.lookalike-url #main-content a {
color: var(--google-blue-700);
text-decoration: none;
}
diff --git a/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css b/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css
index 3b379f3f8ee..fa7c0f0d630 100644
--- a/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css
+++ b/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.css
@@ -70,6 +70,10 @@ h1 {
width: 20vh;
}
+.heavy-ad .icon {
+ background-image: url(images/heavy_ad.svg);
+}
+
.interstitial-wrapper {
align-items: center;
box-sizing: border-box;
diff --git a/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.js b/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.js
index 3464121a299..44eff5e2a5c 100644
--- a/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.js
+++ b/chromium/components/security_interstitials/core/browser/resources/interstitial_webview_quiet.js
@@ -21,6 +21,9 @@ function onResize() {
function initPage() {
var isGiantWebView = loadTimeData.getBoolean('is_giant');
var darkModeAvailable = loadTimeData.getBoolean('darkModeAvailable');
+ var interstitialType = loadTimeData.getString('type');
+ var safebrowsing = interstitialType == "SAFEBROWSING";
+ var heavyAd = interstitialType == "HEAVYAD";
document.body.className = isGiantWebView ? 'giant' : '';
@@ -28,6 +31,10 @@ function initPage() {
document.body.classList.add('dark-mode-available');
}
+ if (heavyAd) {
+ document.body.classList.add('heavy-ad');
+ }
+
preventDefaultOnPoundLinkClicks();
$('details-link').addEventListener('click', function(event) {
@@ -35,9 +42,11 @@ function initPage() {
$('main-content').classList.toggle(HIDDEN_CLASS, !hiddenDetails);
});
- $('proceed-link').addEventListener('click', function(event) {
- sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
- });
+ if (safebrowsing) {
+ $('proceed-link').addEventListener('click', function(event) {
+ sendCommand(SecurityInterstitialCommandId.CMD_PROCEED);
+ });
+ }
window.addEventListener('resize', onResize);
}
diff --git a/chromium/components/security_interstitials/core/browser/resources/list_of_interstitials.html b/chromium/components/security_interstitials/core/browser/resources/list_of_interstitials.html
index 950702c32c2..09b37abb202 100644
--- a/chromium/components/security_interstitials/core/browser/resources/list_of_interstitials.html
+++ b/chromium/components/security_interstitials/core/browser/resources/list_of_interstitials.html
@@ -109,14 +109,6 @@
</a>
</li>
</ul>
- <h3>Supervised Users</h3>
- <ul>
- <li>
- <a href="supervised_user">
- Supervised User
- </a>
- </li>
- </ul>
<h3>Origin Policy</h3>
<ul>
<li>
diff --git a/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc b/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
index a5ec63f51f0..49de2ab45ed 100644
--- a/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
+++ b/chromium/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
@@ -314,6 +314,8 @@ void SafeBrowsingLoudErrorUI::PopulateBillingLoadTimeData(
load_time_data->SetBoolean("phishing", false);
load_time_data->SetBoolean("overridable", true);
+ load_time_data->SetString("tabTitle",
+ l10n_util::GetStringUTF16(IDS_BILLING_TITLE));
load_time_data->SetString("heading",
l10n_util::GetStringUTF16(IDS_BILLING_HEADING));
load_time_data->SetString(
diff --git a/chromium/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc b/chromium/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
index 8d6c799fbb3..8099cbe2832 100644
--- a/chromium/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
+++ b/chromium/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
@@ -152,6 +152,8 @@ void SafeBrowsingQuietErrorUI::PopulatePhishingLoadTimeData(
void SafeBrowsingQuietErrorUI::PopulateBillingLoadTimeData(
base::DictionaryValue* load_time_data) {
load_time_data->SetBoolean("phishing", false);
+ load_time_data->SetString("tabTitle",
+ l10n_util::GetStringUTF16(IDS_BILLING_TITLE));
load_time_data->SetString(
"heading", l10n_util::GetStringUTF16(IDS_BILLING_WEBVIEW_HEADING));
load_time_data->SetString(
diff --git a/chromium/components/security_interstitials_strings.grdp b/chromium/components/security_interstitials_strings.grdp
index e9d9f0c04f4..bafe7d716fa 100644
--- a/chromium/components/security_interstitials_strings.grdp
+++ b/chromium/components/security_interstitials_strings.grdp
@@ -65,20 +65,20 @@
</message>
<!-- Lookalike URL warning -->
- <message name="IDS_LOOKALIKE_URL_TITLE" desc="Tab title. Context: the requested URL looks like a more popular URL.">
+ <message name="IDS_LOOKALIKE_URL_TITLE" desc="Tab title. Context: the requested URL might be trying to trick the user since it looks like a more popular URL.">
Continue to <ph name="DOMAIN">$1<ex>example.com</ex></ph>?
</message>
- <message name="IDS_LOOKALIKE_URL_HEADING" desc="Large heading. Context: the error page that's shown when the requested URL looks like a more popular URL.">
+ <message name="IDS_LOOKALIKE_URL_HEADING" desc="Large heading. Context: the error page that's shown when the requested URL might be trying to trick the user since it looks like a more popular URL.">
Continue to &lt;a href="#" id="dont-proceed-link"&gt;<ph name="DOMAIN">$1<ex>example.com</ex></ph>&lt;/a&gt;?
</message>
- <message name="IDS_LOOKALIKE_URL_IGNORE" desc="Button text. Context: the error page that's shown when the requested URL looks like a more popular URL. This button dismisses the interstitial and navigates to the originally-requested URL.">
+ <message name="IDS_LOOKALIKE_URL_IGNORE" desc="Button text. Context: the error page that's shown when the requested URL might be trying to trick the user since it looks like a more popular URL. This button dismisses the interstitial and navigates to the originally-requested URL.">
Ignore
</message>
- <message name="IDS_LOOKALIKE_URL_CONTINUE" desc="Button text. Context: the error page that's shown when the requested URL looks like a more popular URL. This button dismisses the interstitial and navigates to the suggested (safe) URL.">
+ <message name="IDS_LOOKALIKE_URL_CONTINUE" desc="Button text. Context: the error page that's shown when the requested URL might be trying to trick the user since it looks like a more popular URL. This button dismisses the interstitial and navigates to the suggested (safe) URL.">
Continue
</message>
- <message name="IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH" desc="Main paragraph of an error message. Context: the error page that's shown when the requested URL looks like a more popular URL.">
- The link you opened goes to a site you don't usually visit. It might be trying to confuse you.
+ <message name="IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH" desc="Main paragraph of an error message. Context: the error page that's shown when the requested URL might be trying to trick the user since it looks like a more popular URL.">
+ The site you just tried to visit looks fake. Attackers sometimes mimic sites by making small, hard-to-see changes to the URL.
</message>
<!-- Clock errors -->
@@ -228,7 +228,7 @@
Privacy policy
</message>
<message name="IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE" desc="SafeBrowsing Scout label next to checkbox">
- Help improve Safe Browsing by sending some <ph name="BEGIN_WHITEPAPER_LINK">&lt;a href="#" id="whitepaper-link"&gt;</ph>system information and page content<ph name="END_WHITEPAPER_LINK">&lt;/a&gt;</ph> to Google. <ph name="PRIVACY_PAGE_LINK">$1</ph>
+ Help improve Chrome security by sending <ph name="BEGIN_WHITEPAPER_LINK">&lt;a href="#" id="whitepaper-link"&gt;</ph>URLs of some pages you visit, limited system information, and some page content<ph name="END_WHITEPAPER_LINK">&lt;/a&gt;</ph> to Google. <ph name="PRIVACY_PAGE_LINK">$1</ph>
</message>
<!-- Harmful download interstitial -->
@@ -385,6 +385,9 @@
</if>
<!-- Billing interstitial -->
+ <message name="IDS_BILLING_TITLE" desc="The tab title for the Safe Browsing Billing interstitial.">
+ Page may charge money
+ </message>
<message name="IDS_BILLING_HEADING" desc="The large heading at the top of the billing interstitial.">
The page ahead may try to charge you money
</message>
@@ -447,4 +450,21 @@
<message name="IDS_ORIGIN_POLICY_CLOSE" desc="The text of the Origin Policy Error Interstitial that will hide the 'advanced' section again.">
Hide advanced
</message>
+
+ <!-- Safety Tip summary strings for Android (Desktop is in page_info_strings.grdp) -->
+ <message name="IDS_SAFETY_TIP_ANDROID_NAME" desc="Name of safety tips in general, displayed in bold as part of the title of the safety tip infobar.">
+ Safety tip:
+ </message>
+ <message name="IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_TITLE" desc="Title of Safety Tip infobar.">
+ <ph name="SAFETY_TIP">$1<ex>Safety tip:</ex></ph> suspicious site
+ </message>
+ <message name="IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_DESCRIPTION" desc="Body of an infobar warning when the user visits a page that triggered a Safety Tip.">
+ This site could be fake or fraudulent. Chrome recommends leaving now.
+ </message>
+ <message name="IDS_SAFETY_TIP_ANDROID_IGNORE_BUTTON" desc="Text of button to leave a suspicious page. Shown on the safety tip infobar.">
+ IGNORE
+ </message>
+ <message name="IDS_SAFETY_TIP_ANDROID_LEAVE_BUTTON" desc="Text of button to ignore the warning on a suspicious page. Shown on the safety tip infobar.">
+ LEAVE SITE
+ </message>
</grit-part>
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_BILLING_TITLE.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_BILLING_TITLE.png.sha1
new file mode 100644
index 00000000000..ac27e9b9f0f
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_BILLING_TITLE.png.sha1
@@ -0,0 +1 @@
+a8634b9ed4f8e7829c25a89ef83b68217d0c564c \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE.png.sha1
new file mode 100644
index 00000000000..5d0db878405
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE.png.sha1
@@ -0,0 +1 @@
+d61456e2fd82bcad5d327f4e0fbb59bba9126366 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_HEADING_WIFI.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_HEADING_WIFI.png.sha1
new file mode 100644
index 00000000000..5d0db878405
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_HEADING_WIFI.png.sha1
@@ -0,0 +1 @@
+d61456e2fd82bcad5d327f4e0fbb59bba9126366 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI_SSID.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI_SSID.png.sha1
new file mode 100644
index 00000000000..5d0db878405
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI_SSID.png.sha1
@@ -0,0 +1 @@
+d61456e2fd82bcad5d327f4e0fbb59bba9126366 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIRED.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIRED.png.sha1
new file mode 100644
index 00000000000..dfc1e8d9daf
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIRED.png.sha1
@@ -0,0 +1 @@
+378650e81625e476126a1a3d4b6ff559df54ef7c
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1
index 55b5d17dce3..83030021b31 100644
--- a/chromium/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH.png.sha1
@@ -1 +1 @@
-260a7f133f2a8fcec1743f8f2bb7538cc7a2fc50 \ No newline at end of file
+a0e10eb89867355fc98c930e468397e8dadf4f17 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_DESCRIPTION.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_DESCRIPTION.png.sha1
new file mode 100644
index 00000000000..0f238f806a8
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+fb0016e6f1d75b8d7023df83680103ec528713d4 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_TITLE.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_TITLE.png.sha1
new file mode 100644
index 00000000000..0f238f806a8
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_BAD_REPUTATION_TITLE.png.sha1
@@ -0,0 +1 @@
+fb0016e6f1d75b8d7023df83680103ec528713d4 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_IGNORE_BUTTON.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_IGNORE_BUTTON.png.sha1
new file mode 100644
index 00000000000..0f238f806a8
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_IGNORE_BUTTON.png.sha1
@@ -0,0 +1 @@
+fb0016e6f1d75b8d7023df83680103ec528713d4 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_LEAVE_BUTTON.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_LEAVE_BUTTON.png.sha1
new file mode 100644
index 00000000000..0f238f806a8
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_LEAVE_BUTTON.png.sha1
@@ -0,0 +1 @@
+fb0016e6f1d75b8d7023df83680103ec528713d4 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_NAME.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_NAME.png.sha1
new file mode 100644
index 00000000000..0f238f806a8
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_SAFETY_TIP_ANDROID_NAME.png.sha1
@@ -0,0 +1 @@
+fb0016e6f1d75b8d7023df83680103ec528713d4 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE.png.sha1 b/chromium/components/security_interstitials_strings_grdp/IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE.png.sha1
new file mode 100644
index 00000000000..7b0c8836606
--- /dev/null
+++ b/chromium/components/security_interstitials_strings_grdp/IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE.png.sha1
@@ -0,0 +1 @@
+540ac19f59fd8051492e34fb594618d0c368f934 \ No newline at end of file
diff --git a/chromium/components/security_interstitials_strings_grdp/OWNERS b/chromium/components/security_interstitials_strings_grdp/OWNERS
index d94897a8729..5643d3a5345 100644
--- a/chromium/components/security_interstitials_strings_grdp/OWNERS
+++ b/chromium/components/security_interstitials_strings_grdp/OWNERS
@@ -1 +1,2 @@
file://components/security_interstitials/OWNERS
+# COMPONENT: Services>Safebrowsing
diff --git a/chromium/components/security_state/content/content_utils.cc b/chromium/components/security_state/content/content_utils.cc
index 5b57db3782d..8c55c0d9f83 100644
--- a/chromium/components/security_state/content/content_utils.cc
+++ b/chromium/components/security_state/content/content_utils.cc
@@ -127,8 +127,6 @@ void ExplainCertificateSecurity(
bool is_cert_status_error =
net::IsCertStatusError(visible_security_state.cert_status);
- bool is_cert_status_minor_error =
- net::IsCertStatusMinorError(visible_security_state.cert_status);
if (is_cert_status_error) {
base::string16 error_string = base::UTF8ToUTF16(net::ErrorToString(
@@ -142,11 +140,7 @@ void ExplainCertificateSecurity(
visible_security_state.certificate,
blink::WebMixedContentContextType::kNotMixedContent);
- if (is_cert_status_minor_error) {
- security_style_explanations->neutral_explanations.push_back(explanation);
- } else {
- security_style_explanations->insecure_explanations.push_back(explanation);
- }
+ security_style_explanations->insecure_explanations.push_back(explanation);
} else {
// If the certificate does not have errors and is not using SHA1, then add
// an explanation that the certificate is valid.
@@ -321,17 +315,14 @@ void ExplainContentSecurity(
l10n_util::GetStringUTF8(IDS_NON_SECURE_FORM_DESCRIPTION)));
}
- // If the main resource was loaded with no certificate errors or only minor
- // certificate errors, then record the presence of subresources with
- // certificate errors. Subresource certificate errors aren't recorded when the
- // main resource was loaded with major certificate errors because, in the
- // common case, these subresource certificate errors would be duplicative with
- // the main resource's error.
+ // If the main resource was loaded with no certificate errors then record the
+ // presence of subresources with certificate errors. Subresource certificate
+ // errors aren't recorded when the main resource was loaded with major
+ // certificate errors because, in the common case, these subresource
+ // certificate errors would be duplicative with the main resource's error.
bool is_cert_status_error =
net::IsCertStatusError(visible_security_state.cert_status);
- bool is_cert_status_minor_error =
- net::IsCertStatusMinorError(visible_security_state.cert_status);
- if (!is_cert_status_error || is_cert_status_minor_error) {
+ if (!is_cert_status_error) {
if (visible_security_state.ran_content_with_cert_errors) {
add_secure_explanation = false;
security_style_explanations->insecure_explanations.push_back(
@@ -377,6 +368,8 @@ std::unique_ptr<security_state::VisibleSecurityState> GetVisibleSecurityState(
state->is_error_page = entry->GetPageType() == content::PAGE_TYPE_ERROR;
state->is_view_source =
entry->GetVirtualURL().SchemeIs(content::kViewSourceScheme);
+ state->is_devtools =
+ entry->GetVirtualURL().SchemeIs(content::kChromeDevToolsScheme);
state->url = entry->GetURL();
if (!entry->GetSSL().initialized)
@@ -423,9 +416,7 @@ blink::WebSecurityStyle GetSecurityStyle(
ExplainSafeBrowsingSecurity(visible_security_state,
security_style_explanations);
} else if (visible_security_state.is_error_page &&
- (!net::IsCertStatusError(visible_security_state.cert_status) ||
- net::IsCertStatusMinorError(
- visible_security_state.cert_status))) {
+ !net::IsCertStatusError(visible_security_state.cert_status)) {
security_style_explanations->summary =
l10n_util::GetStringUTF8(IDS_ERROR_PAGE_SUMMARY);
// In the case of a non cert error page, we usually don't have a
diff --git a/chromium/components/security_state/content/content_utils_unittest.cc b/chromium/components/security_state/content/content_utils_unittest.cc
index 678561ca158..7935219f256 100644
--- a/chromium/components/security_state/content/content_utils_unittest.cc
+++ b/chromium/components/security_state/content/content_utils_unittest.cc
@@ -467,8 +467,7 @@ TEST(SecurityStateContentUtilsTest, MixedContentExplanations) {
TEST(SecurityStateContentUtilsTest, CertErrorContentExplanations) {
// Test a modern configuration with a key exchange group.
security_state::VisibleSecurityState visible_security_state;
- visible_security_state.cert_status =
- net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
+ visible_security_state.cert_status = 0;
visible_security_state.url = GURL("https://scheme-is-cryptographic.test");
net::SSLConnectionStatusSetCipherSuite(
0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
@@ -545,8 +544,7 @@ TEST(SecurityStateContentUtilsTest, CertErrorContentExplanations) {
TEST(SecurityStateContentUtilsTest, MixedContentAndCertErrorExplanations) {
// Test a modern configuration with a key exchange group.
security_state::VisibleSecurityState visible_security_state;
- visible_security_state.cert_status =
- net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
+ visible_security_state.cert_status = 0;
visible_security_state.url = GURL("https://scheme-is-cryptographic.test");
net::SSLConnectionStatusSetCipherSuite(
0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
diff --git a/chromium/components/security_state/core/security_state.cc b/chromium/components/security_state/core/security_state.cc
index b402dc745d2..3ee6b82abe5 100644
--- a/chromium/components/security_state/core/security_state.cc
+++ b/chromium/components/security_state/core/security_state.cc
@@ -71,6 +71,22 @@ std::string GetHistogramSuffixForSecurityLevel(
}
}
+std::string GetHistogramSuffixForSafetyTipStatus(
+ security_state::SafetyTipStatus safety_tip_status) {
+ switch (safety_tip_status) {
+ case security_state::SafetyTipStatus::kUnknown:
+ return "SafetyTip_Unknown";
+ case security_state::SafetyTipStatus::kNone:
+ return "SafetyTip_None";
+ case security_state::SafetyTipStatus::kBadReputation:
+ return "SafetyTip_BadReputation";
+ case security_state::SafetyTipStatus::kLookalike:
+ return "SafetyTip_Lookalike";
+ };
+ NOTREACHED();
+ return std::string();
+}
+
} // namespace
SecurityLevel GetSecurityLevel(
@@ -92,6 +108,7 @@ SecurityLevel GetSecurityLevel(
if (HasMajorCertificateError(visible_security_state)) {
return DANGEROUS;
}
+ DCHECK(!net::IsCertStatusError(visible_security_state.cert_status));
const GURL& url = visible_security_state.url;
@@ -104,6 +121,12 @@ SecurityLevel GetSecurityLevel(
return HTTP_SHOW_WARNING;
}
+ // Display DevTools pages as neutral since we can't be confident the page
+ // is secure, but also don't want the "Not secure" badge.
+ if (visible_security_state.is_devtools) {
+ return NONE;
+ }
+
// Choose the appropriate security level for requests to HTTP and remaining
// pseudo URLs (blob:, filesystem:). filesystem: is a standard scheme so does
// not need to be explicitly listed here.
@@ -146,12 +169,6 @@ SecurityLevel GetSecurityLevel(
return kDisplayedInsecureContentLevel;
}
- if (net::IsCertStatusError(visible_security_state.cert_status)) {
- // Major cert errors are handled above.
- DCHECK(net::IsCertStatusMinorError(visible_security_state.cert_status));
- return NONE;
- }
-
if (visible_security_state.is_view_source) {
return NONE;
}
@@ -180,14 +197,14 @@ bool HasMajorCertificateError(
visible_security_state.certificate;
const bool is_major_cert_error =
- net::IsCertStatusError(visible_security_state.cert_status) &&
- !net::IsCertStatusMinorError(visible_security_state.cert_status);
+ net::IsCertStatusError(visible_security_state.cert_status);
return is_cryptographic_with_certificate && is_major_cert_error;
}
VisibleSecurityState::VisibleSecurityState()
: malicious_content_status(MALICIOUS_CONTENT_STATUS_NONE),
+ safety_tip_status(security_state::SafetyTipStatus::kUnknown),
connection_info_initialized(false),
cert_status(0),
connection_status(0),
@@ -200,7 +217,8 @@ VisibleSecurityState::VisibleSecurityState()
ran_content_with_cert_errors(false),
pkp_bypassed(false),
is_error_page(false),
- is_view_source(false) {}
+ is_view_source(false),
+ is_devtools(false) {}
VisibleSecurityState::~VisibleSecurityState() {}
@@ -223,6 +241,11 @@ std::string GetSecurityLevelHistogramName(
return prefix + "." + GetHistogramSuffixForSecurityLevel(level);
}
+std::string GetSafetyTipHistogramName(const std::string& prefix,
+ SafetyTipStatus safety_tip_status) {
+ return prefix + "." + GetHistogramSuffixForSafetyTipStatus(safety_tip_status);
+}
+
bool IsSHA1InChain(const VisibleSecurityState& visible_security_state) {
return visible_security_state.certificate &&
(visible_security_state.cert_status &
diff --git a/chromium/components/security_state/core/security_state.h b/chromium/components/security_state/core/security_state.h
index fd69904c2af..b6249339dd6 100644
--- a/chromium/components/security_state/core/security_state.h
+++ b/chromium/components/security_state/core/security_state.h
@@ -91,11 +91,33 @@ enum MaliciousContentStatus {
MALICIOUS_CONTENT_STATUS_MALWARE,
MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE,
MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING,
- MALICIOUS_CONTENT_STATUS_SIGN_IN_PASSWORD_REUSE,
+ MALICIOUS_CONTENT_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE,
+ MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE,
MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE,
MALICIOUS_CONTENT_STATUS_BILLING,
};
+// Describes whether the page triggers any safety tips or reputation
+// warnings.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+//
+// Style note: this differs from other enums in this file to follow new
+// histogram enum naming conventions
+// (https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#usage).
+enum class SafetyTipStatus {
+ // Safety tip status is not applicable, e.g. there is no current navigation.
+ kUnknown = 0,
+ // The current page did not trigger any Safety Tip.
+ kNone = 1,
+ // The current page triggered a Safety Tip because it was bad reputation.
+ kBadReputation = 2,
+ // The current page trigged a Safety Tip because it had a lookalike URL.
+ kLookalike = 3,
+ kMaxValue = kLookalike,
+};
+
// Contains the security state relevant to computing the SecurityLevel
// for a page. This is the input to GetSecurityLevel().
struct VisibleSecurityState {
@@ -105,6 +127,12 @@ struct VisibleSecurityState {
MaliciousContentStatus malicious_content_status;
+ // What type of Safety Tip (if any) triggered on the page. Note that this
+ // field will be set even if the Safety Tip UI was not actually shown due to
+ // the feature being disabled (so that this field can be used to record
+ // metrics independent of whether the UI actually showed).
+ SafetyTipStatus safety_tip_status;
+
// CONNECTION SECURITY FIELDS
// Whether the connection security fields are initialized.
bool connection_info_initialized;
@@ -136,6 +164,8 @@ struct VisibleSecurityState {
bool is_error_page;
// True if the page is a view-source page.
bool is_view_source;
+ // True if the page is a devtools page.
+ bool is_devtools;
// Contains information about input events that may impact the security
// level of the page.
InsecureInputEventData insecure_input_events;
@@ -180,6 +210,10 @@ bool IsSslCertificateValid(security_state::SecurityLevel security_level);
std::string GetSecurityLevelHistogramName(
const std::string& prefix, security_state::SecurityLevel level);
+// Returns the given prefix suffixed with a dot and the given Safety Tip status.
+std::string GetSafetyTipHistogramName(const std::string& prefix,
+ SafetyTipStatus safety_tip_status);
+
bool IsSHA1InChain(const VisibleSecurityState& visible_security_state);
} // namespace security_state
diff --git a/chromium/components/security_state/core/security_state_unittest.cc b/chromium/components/security_state/core/security_state_unittest.cc
index db75e164324..24fa517969a 100644
--- a/chromium/components/security_state/core/security_state_unittest.cc
+++ b/chromium/components/security_state/core/security_state_unittest.cc
@@ -457,21 +457,17 @@ TEST(SecurityStateTest, CryptoWithNoCertificateErrors) {
EXPECT_FALSE(helper.HasMajorCertificateError());
}
-// Tests that minor certificate errors are properly ignored.
-TEST(SecurityStateTest, MinorCertificateErrors) {
+// Tests that major certificate errors are detected.
+TEST(SecurityStateTest, MajorCertificateErrors) {
TestSecurityStateHelper helper;
helper.set_cert_status(net::CERT_STATUS_SHA1_SIGNATURE_PRESENT |
net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION);
- EXPECT_FALSE(helper.HasMajorCertificateError());
+ EXPECT_TRUE(helper.HasMajorCertificateError());
helper.set_cert_status(net::CERT_STATUS_SHA1_SIGNATURE_PRESENT |
net::CERT_STATUS_NO_REVOCATION_MECHANISM);
- EXPECT_FALSE(helper.HasMajorCertificateError());
-}
+ EXPECT_TRUE(helper.HasMajorCertificateError());
-// Tests that major certificate errors are detected.
-TEST(SecurityStateTest, MajorCertificateErrors) {
- TestSecurityStateHelper helper;
helper.set_cert_status(net::CERT_STATUS_SHA1_SIGNATURE_PRESENT |
net::CERT_STATUS_REVOKED);
EXPECT_TRUE(helper.HasMajorCertificateError());
diff --git a/chromium/components/security_state_strings_grdp/OWNERS b/chromium/components/security_state_strings_grdp/OWNERS
index 9e98e488b99..6d3f89e7e07 100644
--- a/chromium/components/security_state_strings_grdp/OWNERS
+++ b/chromium/components/security_state_strings_grdp/OWNERS
@@ -1 +1,2 @@
file://components/security_state/OWNERS
+# COMPONENT: Internals>PageSecurityState
diff --git a/chromium/components/send_tab_to_self/OWNERS b/chromium/components/send_tab_to_self/OWNERS
index a49acc9eff2..37c75ef2f77 100644
--- a/chromium/components/send_tab_to_self/OWNERS
+++ b/chromium/components/send_tab_to_self/OWNERS
@@ -1,5 +1,6 @@
hansberry@chromium.org
jeffreycohen@chromium.org
+ramyan@chromium.org
sebsg@chromium.org
tgupta@chromium.org
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_bridge.cc b/chromium/components/send_tab_to_self/send_tab_to_self_bridge.cc
index e10dfefe82d..4fd9f588d8d 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_bridge.cc
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_bridge.cc
@@ -49,7 +49,7 @@ enum class UMAAddEntryStatus {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class UMANotifyLocalDevice {
- // The addedentry was sent to the local machine.
+ // The added entry was sent to the local machine.
LOCAL = 0,
// The added entry was targeted at a different machine.
REMOTE = 1,
@@ -716,7 +716,7 @@ void SendTabToSelfBridge::SetTargetDeviceInfoList() {
device_info_tracker_->GetAllDeviceInfo();
number_of_devices_ = all_devices.size();
- // Sort the DeviceInfo vector so the most recenly modified devices are first.
+ // Sort the DeviceInfo vector so the most recently modified devices are first.
std::stable_sort(all_devices.begin(), all_devices.end(),
[](const std::unique_ptr<syncer::DeviceInfo>& device1,
const std::unique_ptr<syncer::DeviceInfo>& device2) {
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc b/chromium/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
index 3f3ffee618a..5176d5d08db 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
@@ -12,8 +12,8 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
#include "components/history/core/browser/history_service.h"
#include "components/send_tab_to_self/features.h"
#include "components/send_tab_to_self/proto/send_tab_to_self.pb.h"
@@ -195,7 +195,7 @@ class SendTabToSelfBridgeTest : public testing::Test {
base::SimpleTestClock clock_;
// In memory model type store needs to be able to post tasks.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<syncer::ModelTypeStore> store_;
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc b/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc
index cad730e12b5..550d6ad2919 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc
@@ -27,16 +27,19 @@ SendTabToSelfModelTypeController::~SendTabToSelfModelTypeController() {
sync_service_->RemoveObserver(this);
}
-bool SendTabToSelfModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+SendTabToSelfModelTypeController::GetPreconditionState() const {
DCHECK(CalledOnValidThread());
- return !(syncer::IsWebSignout(sync_service_->GetAuthError()));
+ return syncer::IsWebSignout(sync_service_->GetAuthError())
+ ? PreconditionState::kMustStopAndClearData
+ : PreconditionState::kPreconditionsMet;
}
void SendTabToSelfModelTypeController::OnStateChanged(
syncer::SyncService* sync) {
DCHECK(CalledOnValidThread());
// Most of these calls will be no-ops but SyncService handles that just fine.
- sync_service_->ReadyForStartChanged(type());
+ sync_service_->DataTypePreconditionChanged(type());
}
} // namespace send_tab_to_self
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.h b/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.h
index fe9244b8dd0..b6b3cb308cf 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.h
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_model_type_controller.h
@@ -27,7 +27,7 @@ class SendTabToSelfModelTypeController : public syncer::ModelTypeController,
~SendTabToSelfModelTypeController() override;
// DataTypeController overrides.
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
// syncer::SyncServiceObserver implementation.
void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/chromium/components/services/OWNERS b/chromium/components/services/OWNERS
index e4ca4ab097f..50eca1368b3 100644
--- a/chromium/components/services/OWNERS
+++ b/chromium/components/services/OWNERS
@@ -1 +1,2 @@
file://services/OWNERS
+# COMPONENT: Internal>Services
diff --git a/chromium/components/services/app_service/public/cpp/BUILD.gn b/chromium/components/services/app_service/public/cpp/BUILD.gn
new file mode 100644
index 00000000000..502f85ca84b
--- /dev/null
+++ b/chromium/components/services/app_service/public/cpp/BUILD.gn
@@ -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.
+
+source_set("app_file_handling") {
+ sources = [
+ "file_handler_info.cc",
+ "file_handler_info.h",
+ ]
+}
diff --git a/chromium/components/services/app_service/public/cpp/file_handler_info.cc b/chromium/components/services/app_service/public/cpp/file_handler_info.cc
new file mode 100644
index 00000000000..d073c498af2
--- /dev/null
+++ b/chromium/components/services/app_service/public/cpp/file_handler_info.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 "components/services/app_service/public/cpp/file_handler_info.h"
+
+namespace apps {
+
+namespace file_handler_verbs {
+
+const char kOpenWith[] = "open_with";
+const char kAddTo[] = "add_to";
+const char kPackWith[] = "pack_with";
+const char kShareWith[] = "share_with";
+
+} // namespace file_handler_verbs
+
+FileHandlerInfo::FileHandlerInfo()
+ : include_directories(false), verb(file_handler_verbs::kOpenWith) {}
+
+FileHandlerInfo::FileHandlerInfo(const FileHandlerInfo& other) = default;
+
+FileHandlerInfo::~FileHandlerInfo() {}
+
+} // namespace apps
diff --git a/chromium/components/services/app_service/public/cpp/file_handler_info.h b/chromium/components/services/app_service/public/cpp/file_handler_info.h
new file mode 100644
index 00000000000..c122fc20bf2
--- /dev/null
+++ b/chromium/components/services/app_service/public/cpp/file_handler_info.h
@@ -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.
+
+#ifndef COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_FILE_HANDLER_INFO_H_
+#define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_FILE_HANDLER_INFO_H_
+
+#include <set>
+#include <string>
+
+namespace apps {
+
+namespace file_handler_verbs {
+
+// Supported verbs for file handlers.
+extern const char kOpenWith[];
+extern const char kAddTo[];
+extern const char kPackWith[];
+extern const char kShareWith[];
+
+} // namespace file_handler_verbs
+
+// Contains information about a file handler for an app.
+struct FileHandlerInfo {
+ FileHandlerInfo();
+ FileHandlerInfo(const FileHandlerInfo& other);
+ ~FileHandlerInfo();
+
+ // The id of this handler.
+ std::string id;
+
+ // File extensions associated with this handler.
+ std::set<std::string> extensions;
+
+ // MIME types associated with this handler.
+ std::set<std::string> types;
+
+ // True if the handler can manage directories.
+ bool include_directories;
+
+ // A verb describing the intent of the handler.
+ std::string verb;
+};
+
+} // namespace apps
+
+#endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_FILE_HANDLER_INFO_H_ \ No newline at end of file
diff --git a/chromium/components/services/filesystem/BUILD.gn b/chromium/components/services/filesystem/BUILD.gn
index a9075692ecb..2af927c624a 100644
--- a/chromium/components/services/filesystem/BUILD.gn
+++ b/chromium/components/services/filesystem/BUILD.gn
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//services/service_manager/public/cpp/service_executable.gni")
import("//testing/test.gni")
static_library("lib") {
@@ -11,8 +10,6 @@ static_library("lib") {
"directory_impl.h",
"file_impl.cc",
"file_impl.h",
- "file_system_impl.cc",
- "file_system_impl.h",
"lock_table.cc",
"lock_table.h",
"shared_temp_dir.cc",
@@ -25,28 +22,27 @@ static_library("lib") {
"//base",
"//components/services/filesystem/public/mojom",
"//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/mojom",
"//url",
]
}
if (!is_ios) {
- # service binaries are not supported on iOS.
- service_executable("filesystem") {
+ source_set("test_support") {
+ testonly = true
+
sources = [
- "file_system_app.cc",
- "file_system_app.h",
- "main.cc",
+ "directory_test_helper.cc",
+ "directory_test_helper.h",
]
deps = [
+ "//base/test:test_support",
+ ]
+
+ public_deps = [
":lib",
"//base",
"//components/services/filesystem/public/mojom",
- "//mojo/public/cpp/bindings",
- "//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
]
}
@@ -54,25 +50,18 @@ if (!is_ios) {
sources = [
"directory_impl_unittest.cc",
"file_impl_unittest.cc",
- "files_test_base.cc",
- "files_test_base.h",
]
deps = [
+ ":lib",
+ ":test_support",
"//base",
"//base/test:test_support",
- "//components/services/filesystem/public/cpp:manifest",
"//components/services/filesystem/public/mojom",
"//mojo/core/test:run_all_unittests",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/cpp/test:test_support",
"//testing/gtest",
]
-
- data_deps = [
- ":filesystem",
- ]
}
}
diff --git a/chromium/components/services/filesystem/DEPS b/chromium/components/services/filesystem/DEPS
index 541d16a8a62..f1f2e01caac 100644
--- a/chromium/components/services/filesystem/DEPS
+++ b/chromium/components/services/filesystem/DEPS
@@ -1,6 +1,4 @@
include_rules = [
"+components/prefs",
"+mojo/public",
- "+mojo/util",
- "+services/service_manager",
]
diff --git a/chromium/components/services/filesystem/OWNERS b/chromium/components/services/filesystem/OWNERS
new file mode 100644
index 00000000000..f2c7bf4daef
--- /dev/null
+++ b/chromium/components/services/filesystem/OWNERS
@@ -0,0 +1,2 @@
+# COMPONENT: Internals>Services>File
+# TEAM: storage-dev@chromium.org
diff --git a/chromium/components/services/filesystem/directory_impl_unittest.cc b/chromium/components/services/filesystem/directory_impl_unittest.cc
index 9a6740dbc1a..70f8261a4d5 100644
--- a/chromium/components/services/filesystem/directory_impl_unittest.cc
+++ b/chromium/components/services/filesystem/directory_impl_unittest.cc
@@ -8,22 +8,37 @@
#include <map>
#include <string>
+#include "base/macros.h"
#include "base/stl_util.h"
-#include "components/services/filesystem/files_test_base.h"
+#include "base/test/task_environment.h"
+#include "components/services/filesystem/directory_test_helper.h"
#include "components/services/filesystem/public/mojom/directory.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace filesystem {
namespace {
-using DirectoryImplTest = FilesTestBase;
+class DirectoryImplTest : public testing::Test {
+ public:
+ DirectoryImplTest() = default;
+
+ mojo::Remote<mojom::Directory> CreateTempDir() {
+ return test_helper_.CreateTempDir();
+ }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+ DirectoryTestHelper test_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectoryImplTest);
+};
constexpr char kData[] = "one two three";
TEST_F(DirectoryImplTest, Read) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Make some files.
@@ -79,8 +94,7 @@ TEST_F(DirectoryImplTest, Read) {
// TODO(vtl): Properly test OpenFile() and OpenDirectory() (including flags).
TEST_F(DirectoryImplTest, BasicRenameDelete) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -132,8 +146,7 @@ TEST_F(DirectoryImplTest, BasicRenameDelete) {
}
TEST_F(DirectoryImplTest, CantOpenDirectoriesAsFiles) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
@@ -165,9 +178,7 @@ TEST_F(DirectoryImplTest, Clone) {
base::File::Error error;
{
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
-
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
directory->Clone(clone_one.BindNewPipeAndPassReceiver());
directory->Clone(clone_two.BindNewPipeAndPassReceiver());
@@ -193,8 +204,7 @@ TEST_F(DirectoryImplTest, Clone) {
}
TEST_F(DirectoryImplTest, WriteFileReadFile) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
std::vector<uint8_t> data(kData, kData + strlen(kData));
@@ -215,8 +225,7 @@ TEST_F(DirectoryImplTest, WriteFileReadFile) {
}
TEST_F(DirectoryImplTest, ReadEmptyFileIsNotFoundError) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
@@ -229,8 +238,7 @@ TEST_F(DirectoryImplTest, ReadEmptyFileIsNotFoundError) {
}
TEST_F(DirectoryImplTest, CantReadEntireFileOnADirectory) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create a directory
@@ -254,8 +262,7 @@ TEST_F(DirectoryImplTest, CantReadEntireFileOnADirectory) {
}
TEST_F(DirectoryImplTest, CantWriteFileOnADirectory) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create a directory
@@ -278,8 +285,7 @@ TEST_F(DirectoryImplTest, CantWriteFileOnADirectory) {
}
TEST_F(DirectoryImplTest, Flush) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
@@ -289,7 +295,5 @@ TEST_F(DirectoryImplTest, Flush) {
}
}
-// TODO(vtl): Test delete flags.
-
} // namespace
} // namespace filesystem
diff --git a/chromium/components/services/filesystem/directory_test_helper.cc b/chromium/components/services/filesystem/directory_test_helper.cc
new file mode 100644
index 00000000000..c04f04af829
--- /dev/null
+++ b/chromium/components/services/filesystem/directory_test_helper.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 "components/services/filesystem/directory_test_helper.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
+#include "components/services/filesystem/directory_impl.h"
+#include "components/services/filesystem/lock_table.h"
+#include "components/services/filesystem/public/mojom/directory.mojom.h"
+#include "components/services/filesystem/shared_temp_dir.h"
+#include "mojo/public/cpp/bindings/unique_receiver_set.h"
+
+namespace filesystem {
+
+class DirectoryTestHelper::BlockingState {
+ public:
+ BlockingState() : lock_table_(base::MakeRefCounted<LockTable>()) {}
+ ~BlockingState() = default;
+
+ void BindNewTempDirectory(mojo::PendingReceiver<mojom::Directory> receiver) {
+ auto temp_dir = std::make_unique<base::ScopedTempDir>();
+ CHECK(temp_dir->CreateUniqueTempDir());
+ base::FilePath path = temp_dir->GetPath();
+ directories_.Add(
+ std::make_unique<DirectoryImpl>(
+ path, base::MakeRefCounted<SharedTempDir>(std::move(temp_dir)),
+ lock_table_),
+ std::move(receiver));
+ }
+
+ private:
+ const scoped_refptr<LockTable> lock_table_;
+ mojo::UniqueReceiverSet<mojom::Directory> directories_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlockingState);
+};
+
+DirectoryTestHelper::DirectoryTestHelper()
+ : blocking_state_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock()})) {}
+
+DirectoryTestHelper::~DirectoryTestHelper() = default;
+
+mojo::Remote<mojom::Directory> DirectoryTestHelper::CreateTempDir() {
+ mojo::Remote<mojom::Directory> remote;
+ blocking_state_.Post(FROM_HERE, &BlockingState::BindNewTempDirectory,
+ remote.BindNewPipeAndPassReceiver());
+ return remote;
+}
+
+} // namespace filesystem
diff --git a/chromium/components/services/filesystem/directory_test_helper.h b/chromium/components/services/filesystem/directory_test_helper.h
new file mode 100644
index 00000000000..fe435d0fb14
--- /dev/null
+++ b/chromium/components/services/filesystem/directory_test_helper.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_TEST_HELPER_H_
+#define COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_TEST_HELPER_H_
+
+#include "base/macros.h"
+#include "base/threading/sequence_bound.h"
+#include "components/services/filesystem/public/mojom/directory.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace filesystem {
+
+// Helper class for tests which want to use a remote DirectoryImpl. This binds
+// DirectoryImpl instances for temporary directories on a background thread
+// which supports blocking operations.
+class DirectoryTestHelper {
+ public:
+ DirectoryTestHelper();
+ ~DirectoryTestHelper();
+
+ mojo::Remote<mojom::Directory> CreateTempDir();
+
+ private:
+ class BlockingState;
+
+ base::SequenceBound<BlockingState> blocking_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectoryTestHelper);
+};
+
+} // namespace filesystem
+
+#endif // COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_TEST_HELPER_H_
diff --git a/chromium/components/services/filesystem/file_impl_unittest.cc b/chromium/components/services/filesystem/file_impl_unittest.cc
index ed128c57236..74fcdd8e747 100644
--- a/chromium/components/services/filesystem/file_impl_unittest.cc
+++ b/chromium/components/services/filesystem/file_impl_unittest.cc
@@ -8,18 +8,33 @@
#include <vector>
#include "base/files/file.h"
-#include "components/services/filesystem/files_test_base.h"
+#include "base/macros.h"
+#include "base/test/task_environment.h"
+#include "components/services/filesystem/directory_test_helper.h"
#include "components/services/filesystem/public/mojom/directory.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace filesystem {
namespace {
-using FileImplTest = FilesTestBase;
+class FileImplTest : public testing::Test {
+ public:
+ FileImplTest() = default;
+
+ mojo::Remote<mojom::Directory> CreateTempDir() {
+ return test_helper_.CreateTempDir();
+ }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+ DirectoryTestHelper test_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileImplTest);
+};
TEST_F(FileImplTest, CreateWriteCloseRenameOpenRead) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
bool handled = false;
@@ -88,8 +103,7 @@ TEST_F(FileImplTest, CreateWriteCloseRenameOpenRead) {
}
TEST_F(FileImplTest, CantWriteInReadMode) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
std::vector<uint8_t> bytes_to_write;
@@ -154,8 +168,7 @@ TEST_F(FileImplTest, CantWriteInReadMode) {
}
TEST_F(FileImplTest, OpenInAppendMode) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
@@ -250,8 +263,7 @@ TEST_F(FileImplTest, OpenInAppendMode) {
}
TEST_F(FileImplTest, OpenInTruncateMode) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
@@ -348,8 +360,7 @@ TEST_F(FileImplTest, OpenInTruncateMode) {
// Note: Ignore nanoseconds, since it may not always be supported. We expect at
// least second-resolution support though.
TEST_F(FileImplTest, StatTouch) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -419,8 +430,7 @@ TEST_F(FileImplTest, StatTouch) {
}
TEST_F(FileImplTest, TellSeek) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -505,8 +515,7 @@ TEST_F(FileImplTest, TellSeek) {
}
TEST_F(FileImplTest, Dup) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -599,8 +608,7 @@ TEST_F(FileImplTest, Truncate) {
const uint32_t kInitialSize = 1000;
const uint32_t kTruncatedSize = 654;
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -648,8 +656,7 @@ TEST_F(FileImplTest, Truncate) {
}
TEST_F(FileImplTest, AsHandle) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
@@ -700,8 +707,7 @@ TEST_F(FileImplTest, AsHandle) {
}
TEST_F(FileImplTest, SimpleLockUnlock) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -727,8 +733,7 @@ TEST_F(FileImplTest, SimpleLockUnlock) {
}
TEST_F(FileImplTest, CantDoubleLock) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
// Create my_file.
@@ -754,8 +759,7 @@ TEST_F(FileImplTest, CantDoubleLock) {
}
TEST_F(FileImplTest, ClosingFileClearsLock) {
- mojo::Remote<mojom::Directory> directory;
- GetTemporaryRoot(&directory);
+ mojo::Remote<mojom::Directory> directory = CreateTempDir();
base::File::Error error;
{
diff --git a/chromium/components/services/filesystem/file_system_app.cc b/chromium/components/services/filesystem/file_system_app.cc
deleted file mode 100644
index f5844c579a7..00000000000
--- a/chromium/components/services/filesystem/file_system_app.cc
+++ /dev/null
@@ -1,87 +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 "components/services/filesystem/file_system_app.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-#if defined(OS_WIN)
-#include "base/base_paths_win.h"
-#include "base/path_service.h"
-#include "base/strings/utf_string_conversions.h"
-#elif defined(OS_ANDROID)
-#include "base/base_paths_android.h"
-#include "base/path_service.h"
-#elif defined(OS_LINUX)
-#include "base/environment.h"
-#include "base/nix/xdg_util.h"
-#elif defined(OS_MACOSX)
-#include "base/base_paths_mac.h"
-#include "base/path_service.h"
-#endif
-
-namespace filesystem {
-
-namespace {
-
-const char kUserDataDir[] = "user-data-dir";
-
-} // namespace
-
-FileSystemApp::FileSystemApp(
- mojo::PendingReceiver<service_manager::mojom::Service> receiver)
- : service_binding_(this, std::move(receiver)),
- lock_table_(base::MakeRefCounted<LockTable>()) {}
-
-FileSystemApp::~FileSystemApp() = default;
-
-void FileSystemApp::OnConnect(
- const service_manager::ConnectSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle receiver_pipe) {
- if (interface_name == mojom::FileSystem::Name_) {
- file_systems_.Add(
- std::make_unique<FileSystemImpl>(source_info.identity, GetUserDataDir(),
- lock_table_),
- mojo::PendingReceiver<mojom::FileSystem>(std::move(receiver_pipe)));
- }
-}
-
-// static
-base::FilePath FileSystemApp::GetUserDataDir() {
- base::FilePath path;
-
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(kUserDataDir)) {
- path = command_line->GetSwitchValuePath(kUserDataDir);
- } else {
-#if defined(OS_WIN)
- CHECK(base::PathService::Get(base::DIR_LOCAL_APP_DATA, &path));
-#elif defined(OS_MACOSX)
- CHECK(base::PathService::Get(base::DIR_APP_DATA, &path));
-#elif defined(OS_ANDROID)
- CHECK(base::PathService::Get(base::DIR_ANDROID_APP_DATA, &path));
-#elif defined(OS_LINUX)
- std::unique_ptr<base::Environment> env(base::Environment::Create());
- path = base::nix::GetXDGDirectory(
- env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir);
-#else
- NOTIMPLEMENTED();
-#endif
- path = path.Append(FILE_PATH_LITERAL("filesystem"));
- }
-
- if (!base::PathExists(path))
- base::CreateDirectory(path);
-
- return path;
-}
-
-} // namespace filesystem
diff --git a/chromium/components/services/filesystem/file_system_app.h b/chromium/components/services/filesystem/file_system_app.h
deleted file mode 100644
index 0be9682cda1..00000000000
--- a/chromium/components/services/filesystem/file_system_app.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
-#define COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
-
-#include "base/macros.h"
-#include "components/services/filesystem/directory_impl.h"
-#include "components/services/filesystem/file_system_impl.h"
-#include "components/services/filesystem/lock_table.h"
-#include "components/services/filesystem/public/mojom/file_system.mojom.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/unique_receiver_set.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-
-namespace filesystem {
-
-class FileSystemApp : public service_manager::Service {
- public:
- explicit FileSystemApp(
- mojo::PendingReceiver<service_manager::mojom::Service> receiver);
- ~FileSystemApp() override;
-
- private:
- // Gets the system specific toplevel profile directory.
- static base::FilePath GetUserDataDir();
-
- // |service_manager::Service| override:
- void OnConnect(const service_manager::ConnectSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle receiver_pipe) override;
-
- service_manager::ServiceBinding service_binding_;
- scoped_refptr<LockTable> lock_table_;
- mojo::UniqueReceiverSet<mojom::FileSystem> file_systems_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemApp);
-};
-
-} // namespace filesystem
-
-#endif // COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
diff --git a/chromium/components/services/filesystem/file_system_impl.cc b/chromium/components/services/filesystem/file_system_impl.cc
deleted file mode 100644
index d69a74ad441..00000000000
--- a/chromium/components/services/filesystem/file_system_impl.cc
+++ /dev/null
@@ -1,70 +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 "components/services/filesystem/file_system_impl.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "components/services/filesystem/directory_impl.h"
-#include "components/services/filesystem/lock_table.h"
-#include "mojo/public/cpp/bindings/self_owned_receiver.h"
-#include "services/service_manager/public/cpp/identity.h"
-#include "url/gurl.h"
-
-namespace filesystem {
-
-FileSystemImpl::FileSystemImpl(const service_manager::Identity& remote_identity,
- base::FilePath persistent_dir,
- scoped_refptr<LockTable> lock_table)
- : remote_application_name_(remote_identity.name()),
- lock_table_(std::move(lock_table)),
- persistent_dir_(persistent_dir) {}
-
-FileSystemImpl::~FileSystemImpl() = default;
-
-void FileSystemImpl::OpenTempDirectory(
- mojo::PendingReceiver<mojom::Directory> receiver,
- OpenTempDirectoryCallback callback) {
- // Set only if the |DirectoryImpl| will own a temporary directory.
- std::unique_ptr<base::ScopedTempDir> temp_dir(new base::ScopedTempDir);
- CHECK(temp_dir->CreateUniqueTempDir());
-
- base::FilePath path = temp_dir->GetPath();
- scoped_refptr<SharedTempDir> shared_temp_dir =
- new SharedTempDir(std::move(temp_dir));
- mojo::MakeSelfOwnedReceiver(
- std::make_unique<DirectoryImpl>(path, std::move(shared_temp_dir),
- lock_table_),
- std::move(receiver));
- std::move(callback).Run(base::File::Error::FILE_OK);
-}
-
-void FileSystemImpl::OpenPersistentFileSystem(
- mojo::PendingReceiver<mojom::Directory> receiver,
- OpenPersistentFileSystemCallback callback) {
- std::unique_ptr<base::ScopedTempDir> temp_dir;
- base::FilePath path = persistent_dir_;
- if (!base::PathExists(path))
- base::CreateDirectory(path);
-
- scoped_refptr<SharedTempDir> shared_temp_dir =
- new SharedTempDir(std::move(temp_dir));
-
- mojo::MakeSelfOwnedReceiver(
- std::make_unique<DirectoryImpl>(path, std::move(shared_temp_dir),
- lock_table_),
- std::move(receiver));
- std::move(callback).Run(base::File::Error::FILE_OK);
-}
-
-} // namespace filesystem
diff --git a/chromium/components/services/filesystem/file_system_impl.h b/chromium/components/services/filesystem/file_system_impl.h
deleted file mode 100644
index bbdf14f7a47..00000000000
--- a/chromium/components/services/filesystem/file_system_impl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
-#define COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "components/services/filesystem/public/mojom/file_system.mojom.h"
-#include "components/services/filesystem/shared_temp_dir.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace service_manager {
-class Identity;
-}
-
-namespace filesystem {
-
-class LockTable;
-
-// The base implementation of FileSystemImpl.
-class FileSystemImpl : public mojom::FileSystem {
- public:
- // |persistent_dir| is the directory served to callers of
- // |OpenPersistentFileSystem()|.
- FileSystemImpl(const service_manager::Identity& remote_identity,
- base::FilePath persistent_dir,
- scoped_refptr<LockTable> lock_table);
- ~FileSystemImpl() override;
-
- // mojom::FileSystem:
- void OpenTempDirectory(mojo::PendingReceiver<mojom::Directory> receiver,
- OpenTempDirectoryCallback callback) override;
- void OpenPersistentFileSystem(
- mojo::PendingReceiver<mojom::Directory> receiver,
- OpenPersistentFileSystemCallback callback) override;
-
- private:
- const std::string remote_application_name_;
- scoped_refptr<LockTable> lock_table_;
-
- base::FilePath persistent_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(FileSystemImpl);
-};
-
-} // namespace filesystem
-
-#endif // COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
diff --git a/chromium/components/services/filesystem/files_test_base.cc b/chromium/components/services/filesystem/files_test_base.cc
deleted file mode 100644
index aeb6854fb0f..00000000000
--- a/chromium/components/services/filesystem/files_test_base.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/services/filesystem/files_test_base.h"
-
-#include <utility>
-
-#include "components/services/filesystem/public/cpp/manifest.h"
-#include "components/services/filesystem/public/mojom/directory.mojom.h"
-#include "components/services/filesystem/public/mojom/types.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace filesystem {
-
-const char kTestServiceName[] = "filesystem_service_unittests";
-
-FilesTestBase::FilesTestBase()
- : test_service_manager_(
- {GetManifest(),
- service_manager::ManifestBuilder()
- .WithServiceName(kTestServiceName)
- .RequireCapability("filesystem", "filesystem:filesystem")
- .Build()}),
- test_service_(
- test_service_manager_.RegisterTestInstance(kTestServiceName)) {}
-
-FilesTestBase::~FilesTestBase() = default;
-
-void FilesTestBase::SetUp() {
- connector()->Connect("filesystem", files_.BindNewPipeAndPassReceiver());
-}
-
-void FilesTestBase::GetTemporaryRoot(
- mojo::Remote<mojom::Directory>* directory) {
- base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
- bool handled = files()->OpenTempDirectory(
- directory->BindNewPipeAndPassReceiver(), &error);
- ASSERT_TRUE(handled);
- ASSERT_EQ(base::File::Error::FILE_OK, error);
-}
-
-} // namespace filesystem
diff --git a/chromium/components/services/filesystem/files_test_base.h b/chromium/components/services/filesystem/files_test_base.h
deleted file mode 100644
index 8777d177c16..00000000000
--- a/chromium/components/services/filesystem/files_test_base.h
+++ /dev/null
@@ -1,48 +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 COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
-#define COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/services/filesystem/public/mojom/file_system.mojom.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/service_manager/public/cpp/test/test_service.h"
-#include "services/service_manager/public/cpp/test/test_service_manager.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace filesystem {
-
-class FilesTestBase : public testing::Test {
- public:
- FilesTestBase();
- ~FilesTestBase() override;
-
- // testing::Test:
- void SetUp() override;
-
- protected:
- // Note: This has an out parameter rather than returning the Directory remote,
- // since |ASSERT_...()| doesn't work with return values.
- void GetTemporaryRoot(mojo::Remote<mojom::Directory>* directory);
-
- service_manager::Connector* connector() { return test_service_.connector(); }
- mojo::Remote<mojom::FileSystem>& files() { return files_; }
-
- private:
- base::test::ScopedTaskEnvironment task_environment_;
- service_manager::TestServiceManager test_service_manager_;
- service_manager::TestService test_service_;
- mojo::Remote<mojom::FileSystem> files_;
-
- DISALLOW_COPY_AND_ASSIGN(FilesTestBase);
-};
-
-} // namespace filesystem
-
-#endif // COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
diff --git a/chromium/components/services/filesystem/main.cc b/chromium/components/services/filesystem/main.cc
deleted file mode 100644
index 18921e456a9..00000000000
--- a/chromium/components/services/filesystem/main.cc
+++ /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.
-
-#include "base/task/single_thread_task_executor.h"
-#include "components/services/filesystem/file_system_app.h"
-#include "services/service_manager/public/cpp/service_executable/service_main.h"
-
-void ServiceMain(service_manager::mojom::ServiceRequest request) {
- base::SingleThreadTaskExecutor main_thread_task_executor;
- filesystem::FileSystemApp(std::move(request)).RunUntilTermination();
-}
diff --git a/chromium/components/services/filesystem/public/cpp/BUILD.gn b/chromium/components/services/filesystem/public/cpp/BUILD.gn
deleted file mode 100644
index ae860801190..00000000000
--- a/chromium/components/services/filesystem/public/cpp/BUILD.gn
+++ /dev/null
@@ -1,16 +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.
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/filesystem/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
diff --git a/chromium/components/services/filesystem/public/cpp/OWNERS b/chromium/components/services/filesystem/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/filesystem/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/filesystem/public/cpp/manifest.cc b/chromium/components/services/filesystem/public/cpp/manifest.cc
deleted file mode 100644
index 79e1351a003..00000000000
--- a/chromium/components/services/filesystem/public/cpp/manifest.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/services/filesystem/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "components/services/filesystem/public/mojom/file_system.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace filesystem {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName("filesystem")
- .WithOptions(
- service_manager::ManifestOptionsBuilder()
- .WithSandboxType("none")
- .WithExecutionMode(service_manager::Manifest::ExecutionMode::
- kStandaloneExecutable)
- .Build())
- .ExposeCapability(
- "filesystem:filesystem",
- service_manager::Manifest::InterfaceList<mojom::FileSystem>())
- .Build()};
- return *manifest;
-}
-
-} // namespace filesystem
diff --git a/chromium/components/services/filesystem/public/cpp/manifest.h b/chromium/components/services/filesystem/public/cpp/manifest.h
deleted file mode 100644
index 2009ebf1cc0..00000000000
--- a/chromium/components/services/filesystem/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_FILESYSTEM_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_FILESYSTEM_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace filesystem {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace filesystem
-
-#endif // COMPONENTS_SERVICES_FILESYSTEM_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/filesystem/public/mojom/BUILD.gn b/chromium/components/services/filesystem/public/mojom/BUILD.gn
index 244db145a00..e799e18596e 100644
--- a/chromium/components/services/filesystem/public/mojom/BUILD.gn
+++ b/chromium/components/services/filesystem/public/mojom/BUILD.gn
@@ -8,7 +8,6 @@ mojom("mojom") {
sources = [
"directory.mojom",
"file.mojom",
- "file_system.mojom",
"types.mojom",
]
public_deps = [
diff --git a/chromium/components/services/filesystem/public/mojom/file_system.mojom b/chromium/components/services/filesystem/public/mojom/file_system.mojom
deleted file mode 100644
index d53721ad6bd..00000000000
--- a/chromium/components/services/filesystem/public/mojom/file_system.mojom
+++ /dev/null
@@ -1,21 +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.
-
-module filesystem.mojom;
-
-import "components/services/filesystem/public/mojom/directory.mojom";
-import "mojo/public/mojom/base/file_error.mojom";
-
-interface FileSystem {
- // Opens a temporary filesystem. Will return a different directory each time
- // it is called.
- [Sync]
- OpenTempDirectory(pending_receiver<Directory> directory)
- => (mojo_base.mojom.FileError error);
-
- // Returns a directory which will persist to disk.
- [Sync]
- OpenPersistentFileSystem(pending_receiver<Directory> directory)
- => (mojo_base.mojom.FileError error);
-};
diff --git a/chromium/components/services/font/BUILD.gn b/chromium/components/services/font/BUILD.gn
index 92a4aafb3b3..3fcd92ea18e 100644
--- a/chromium/components/services/font/BUILD.gn
+++ b/chromium/components/services/font/BUILD.gn
@@ -4,7 +4,6 @@
import("//build/config/features.gni")
import("//ppapi/buildflags/buildflags.gni")
-import("//services/service_manager/public/cpp/service_executable.gni")
import("//testing/test.gni")
source_set("lib") {
@@ -21,7 +20,6 @@ source_set("lib") {
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//ppapi/buildflags:buildflags",
- "//services/service_manager/public/cpp",
"//third_party/fontconfig",
"//ui/gfx",
]
@@ -50,37 +48,21 @@ if (is_linux && enable_plugins) {
}
}
-service_executable("font_service") {
- sources = [
- "main.cc",
- ]
-
- deps = [
- ":lib",
- "//base",
- "//mojo/public/c/system",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/mojom",
- ]
-}
-
test("font_service_unittests") {
sources = [
"font_loader_unittest.cc",
]
deps = [
+ ":lib",
"//base",
"//base/test:test_support",
"//components/services/font/public/cpp",
- "//components/services/font/public/cpp:manifest",
"//components/services/font/public/mojom",
"//mojo/core/test:run_all_unittests",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//ppapi/buildflags:buildflags",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/cpp/test:test_support",
"//skia",
"//testing/gtest",
]
@@ -91,8 +73,4 @@ test("font_service_unittests") {
"//third_party:freetype_harfbuzz",
]
}
-
- data_deps = [
- ":font_service",
- ]
}
diff --git a/chromium/components/services/font/DEPS b/chromium/components/services/font/DEPS
index b81f8787fc9..9f6476397f1 100644
--- a/chromium/components/services/font/DEPS
+++ b/chromium/components/services/font/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+services/service_manager",
"+mojo/public",
"+ppapi/buildflags",
"+ppapi/c",
diff --git a/chromium/components/services/font/font_loader_unittest.cc b/chromium/components/services/font/font_loader_unittest.cc
index f837e314ddf..efe3e175f9a 100644
--- a/chromium/components/services/font/font_loader_unittest.cc
+++ b/chromium/components/services/font/font_loader_unittest.cc
@@ -5,17 +5,14 @@
#include <utility>
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/task/post_task.h"
+#include "base/test/task_environment.h"
+#include "components/services/font/font_service_app.h"
#include "components/services/font/public/cpp/font_loader.h"
-#include "components/services/font/public/cpp/manifest.h"
-#include "components/services/font/public/mojom/constants.mojom.h"
#include "components/services/font/public/mojom/font_service.mojom.h"
#include "ppapi/buildflags/buildflags.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-#include "services/service_manager/public/cpp/test/test_service.h"
-#include "services/service_manager/public/cpp/test/test_service_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkFontStyle.h"
@@ -57,30 +54,32 @@ std::string GetPostscriptNameFromFile(base::File& font_file) {
}
#endif
-const char kTestServiceName[] = "font_service_unittests";
+mojo::PendingRemote<mojom::FontService> ConnectToBackgroundFontService() {
+ mojo::PendingRemote<mojom::FontService> remote;
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::WithBaseSyncPrimitives(),
+ base::TaskPriority::USER_BLOCKING})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(
+ [](mojo::PendingReceiver<mojom::FontService> receiver) {
+ static base::NoDestructor<FontServiceApp> service;
+ service->BindReceiver(std::move(receiver));
+ },
+ remote.InitWithNewPipeAndPassReceiver()));
+ return remote;
+}
class FontLoaderTest : public testing::Test {
public:
- FontLoaderTest()
- : test_service_manager_(
- {GetManifest(),
- service_manager::ManifestBuilder()
- .WithServiceName(kTestServiceName)
- .RequireCapability(mojom::kServiceName, "font_service")
- .Build()}),
- test_service_(
- test_service_manager_.RegisterTestInstance(kTestServiceName)),
- font_loader_(test_service_.connector()) {}
+ FontLoaderTest() = default;
~FontLoaderTest() override = default;
protected:
FontLoader* font_loader() { return &font_loader_; }
private:
- base::test::ScopedTaskEnvironment task_environment_;
- service_manager::TestServiceManager test_service_manager_;
- service_manager::TestService test_service_;
- FontLoader font_loader_;
+ base::test::TaskEnvironment task_environment_;
+ FontLoader font_loader_{ConnectToBackgroundFontService()};
DISALLOW_COPY_AND_ASSIGN(FontLoaderTest);
};
diff --git a/chromium/components/services/font/font_service_app.cc b/chromium/components/services/font/font_service_app.cc
index f1bf0e769f1..16c1958793e 100644
--- a/chromium/components/services/font/font_service_app.cc
+++ b/chromium/components/services/font/font_service_app.cc
@@ -79,21 +79,13 @@ font_service::mojom::RenderStyleSwitch ConvertSubpixelRendering(
namespace font_service {
-FontServiceApp::FontServiceApp(service_manager::mojom::ServiceRequest request)
- : service_binding_(this, std::move(request)) {
- registry_.AddInterface(
- base::BindRepeating(&FontServiceApp::CreateSelf, base::Unretained(this)));
-}
-
-FontServiceApp::~FontServiceApp() {}
+FontServiceApp::FontServiceApp() = default;
-void FontServiceApp::OnStart() {}
+FontServiceApp::~FontServiceApp() = default;
-void FontServiceApp::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
+void FontServiceApp::BindReceiver(
+ mojo::PendingReceiver<mojom::FontService> receiver) {
+ receivers_.Add(this, std::move(receiver));
}
void FontServiceApp::MatchFamilyName(const std::string& family_name,
@@ -248,10 +240,6 @@ void FontServiceApp::MatchFontWithFallback(
#endif
}
-void FontServiceApp::CreateSelf(mojom::FontServiceRequest request) {
- bindings_.AddBinding(this, std::move(request));
-}
-
int FontServiceApp::FindOrAddPath(const SkString& path) {
TRACE_EVENT1("fonts", "FontServiceApp::FindOrAddPath", "path",
TRACE_STR_COPY(path.c_str()));
diff --git a/chromium/components/services/font/font_service_app.h b/chromium/components/services/font/font_service_app.h
index 125916496d7..eb920d55798 100644
--- a/chromium/components/services/font/font_service_app.h
+++ b/chromium/components/services/font/font_service_app.h
@@ -10,29 +10,19 @@
#include "base/macros.h"
#include "components/services/font/public/mojom/font_service.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
#include "skia/ext/skia_utils_base.h"
namespace font_service {
-class FontServiceApp : public service_manager::Service,
- public mojom::FontService {
+class FontServiceApp : public mojom::FontService {
public:
- explicit FontServiceApp(service_manager::mojom::ServiceRequest request);
+ FontServiceApp();
~FontServiceApp() override;
- void CreateSelf(mojom::FontServiceRequest request);
+ void BindReceiver(mojo::PendingReceiver<mojom::FontService> receiver);
private:
- // service_manager::Service:
- void OnStart() override;
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
// FontService:
void MatchFamilyName(const std::string& family_name,
mojom::TypefaceStylePtr requested_style,
@@ -60,9 +50,7 @@ class FontServiceApp : public service_manager::Service,
MatchFontWithFallbackCallback callback) override;
int FindOrAddPath(const SkString& path);
- service_manager::ServiceBinding service_binding_;
- service_manager::BinderRegistry registry_;
- mojo::BindingSet<mojom::FontService> bindings_;
+ mojo::ReceiverSet<mojom::FontService> receivers_;
// We don't want to leak paths to our callers; we thus enumerate the paths of
// fonts.
diff --git a/chromium/components/services/font/main.cc b/chromium/components/services/font/main.cc
deleted file mode 100644
index b5e2a098c58..00000000000
--- a/chromium/components/services/font/main.cc
+++ /dev/null
@@ -1,12 +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 "base/task/single_thread_task_executor.h"
-#include "components/services/font/font_service_app.h"
-#include "services/service_manager/public/cpp/service_executable/service_main.h"
-
-void ServiceMain(service_manager::mojom::ServiceRequest request) {
- base::SingleThreadTaskExecutor main_thread_task_executor;
- font_service::FontServiceApp(std::move(request)).RunUntilTermination();
-}
diff --git a/chromium/components/services/font/public/cpp/BUILD.gn b/chromium/components/services/font/public/cpp/BUILD.gn
index 7de60d2150d..259f11696b9 100644
--- a/chromium/components/services/font/public/cpp/BUILD.gn
+++ b/chromium/components/services/font/public/cpp/BUILD.gn
@@ -17,21 +17,6 @@ source_set("cpp") {
"//components/services/font/public/mojom",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/mojom",
"//skia",
]
}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/font/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
diff --git a/chromium/components/services/font/public/cpp/OWNERS b/chromium/components/services/font/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/font/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/font/public/cpp/font_loader.cc b/chromium/components/services/font/public/cpp/font_loader.cc
index 97b162cd8f5..4be7f118f6e 100644
--- a/chromium/components/services/font/public/cpp/font_loader.cc
+++ b/chromium/components/services/font/public/cpp/font_loader.cc
@@ -7,20 +7,19 @@
#include <utility>
#include "base/bind.h"
+#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event.h"
#include "components/services/font/public/cpp/font_service_thread.h"
-#include "components/services/font/public/mojom/constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
namespace font_service {
-FontLoader::FontLoader(service_manager::Connector* connector) {
- mojom::FontServicePtr font_service;
- connector->BindInterface(font_service::mojom::kServiceName, &font_service);
- thread_ = new internal::FontServiceThread(std::move(font_service));
+FontLoader::FontLoader(
+ mojo::PendingRemote<mojom::FontService> pending_font_service)
+ : thread_(base::MakeRefCounted<internal::FontServiceThread>()) {
+ thread_->Init(std::move(pending_font_service));
}
-FontLoader::~FontLoader() {}
+FontLoader::~FontLoader() = default;
bool FontLoader::matchFamilyName(const char family_name[],
SkFontStyle requested,
diff --git a/chromium/components/services/font/public/cpp/font_loader.h b/chromium/components/services/font/public/cpp/font_loader.h
index 6676f80905d..31bc95d4e19 100644
--- a/chromium/components/services/font/public/cpp/font_loader.h
+++ b/chromium/components/services/font/public/cpp/font_loader.h
@@ -12,14 +12,11 @@
#include "base/synchronization/lock.h"
#include "components/services/font/public/cpp/mapped_font_file.h"
#include "components/services/font/public/mojom/font_service.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
-namespace service_manager {
-class Connector;
-}
-
namespace font_service {
namespace internal {
class FontServiceThread;
@@ -34,7 +31,8 @@ class FontServiceThread;
class FontLoader : public SkFontConfigInterface,
public internal::MappedFontFile::Observer {
public:
- explicit FontLoader(service_manager::Connector* connector);
+ explicit FontLoader(
+ mojo::PendingRemote<mojom::FontService> pending_font_service);
~FontLoader() override;
// SkFontConfigInterface:
diff --git a/chromium/components/services/font/public/cpp/font_service_thread.cc b/chromium/components/services/font/public/cpp/font_service_thread.cc
index e93db6ea96a..6e4a2811f3e 100644
--- a/chromium/components/services/font/public/cpp/font_service_thread.cc
+++ b/chromium/components/services/font/public/cpp/font_service_thread.cc
@@ -15,15 +15,24 @@
namespace font_service {
namespace internal {
-FontServiceThread::FontServiceThread(mojom::FontServicePtr font_service)
- : font_service_info_(font_service.PassInterface()),
- task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::TaskPriority::USER_VISIBLE, base::MayBlock()})) {
- task_runner_->PostTask(FROM_HERE, base::BindOnce(&FontServiceThread::Init,
- weak_factory_.GetWeakPtr()));
+FontServiceThread::FontServiceThread()
+ : task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+ base::MayBlock()})) {}
+
+FontServiceThread::~FontServiceThread() {
+ // Ensure the remote is unbound on the appropriate sequence.
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce([](mojo::Remote<mojom::FontService>) {},
+ std::move(font_service_)));
}
-FontServiceThread::~FontServiceThread() {}
+void FontServiceThread::Init(
+ mojo::PendingRemote<mojom::FontService> pending_font_service) {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&FontServiceThread::InitImpl, this,
+ std::move(pending_font_service)));
+}
bool FontServiceThread::MatchFamilyName(
const char family_name[],
@@ -156,7 +165,7 @@ void FontServiceThread::MatchFamilyNameImpl(
SkFontStyle* out_style) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (font_service_.encountered_error()) {
+ if (!font_service_.is_connected()) {
*out_valid = false;
done_event->Signal();
return;
@@ -211,7 +220,7 @@ void FontServiceThread::OpenStreamImpl(base::WaitableEvent* done_event,
const uint32_t id_number) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (font_service_.encountered_error()) {
+ if (!font_service_.is_connected()) {
done_event->Signal();
return;
}
@@ -243,7 +252,7 @@ void FontServiceThread::FallbackFontForCharacterImpl(
bool* out_is_italic) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (font_service_.encountered_error()) {
+ if (!font_service_.is_connected()) {
*out_valid = false;
done_event->Signal();
return;
@@ -293,7 +302,7 @@ void FontServiceThread::FontRenderStyleForStrikeImpl(
mojom::FontRenderStylePtr* out_font_render_style) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (font_service_.encountered_error()) {
+ if (!font_service_.is_connected()) {
*out_valid = false;
done_event->Signal();
return;
@@ -329,7 +338,7 @@ void FontServiceThread::MatchFontByPostscriptNameOrFullFontNameImpl(
mojom::FontIdentityPtr* out_font_identity) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (font_service_.encountered_error()) {
+ if (!font_service_.is_connected()) {
*out_valid = false;
done_event->Signal();
return;
@@ -370,7 +379,7 @@ void FontServiceThread::MatchFontWithFallbackImpl(
DCHECK(task_runner_->RunsTasksInCurrentSequence());
*out_font_file_handle = base::File();
- if (font_service_.encountered_error()) {
+ if (!font_service_.is_connected()) {
done_event->Signal();
return;
}
@@ -393,18 +402,21 @@ void FontServiceThread::OnMatchFontWithFallbackComplete(
done_event->Signal();
}
-void FontServiceThread::OnFontServiceConnectionError() {
+void FontServiceThread::OnFontServiceDisconnected() {
std::set<base::WaitableEvent*> events;
events.swap(pending_waitable_events_);
for (base::WaitableEvent* event : events)
event->Signal();
}
-void FontServiceThread::Init() {
- font_service_.Bind(std::move(font_service_info_));
- font_service_.set_connection_error_handler(
- base::BindOnce(&FontServiceThread::OnFontServiceConnectionError,
- weak_factory_.GetWeakPtr()));
+void FontServiceThread::InitImpl(
+ mojo::PendingRemote<mojom::FontService> pending_font_service) {
+ font_service_.Bind(std::move(pending_font_service));
+
+ // NOTE: Unretained is safe here because the callback can never be invoked
+ // past |font_service_|'s lifetime.
+ font_service_.set_disconnect_handler(base::BindOnce(
+ &FontServiceThread::OnFontServiceDisconnected, base::Unretained(this)));
}
} // namespace internal
diff --git a/chromium/components/services/font/public/cpp/font_service_thread.h b/chromium/components/services/font/public/cpp/font_service_thread.h
index bf800e477fb..5ba397270f1 100644
--- a/chromium/components/services/font/public/cpp/font_service_thread.h
+++ b/chromium/components/services/font/public/cpp/font_service_thread.h
@@ -11,8 +11,9 @@
#include "base/files/file.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "components/services/font/public/mojom/font_service.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
@@ -32,7 +33,11 @@ class MappedFontFile;
// TODO(936569): Rename FontServiceThread since it's no longer a thread.
class FontServiceThread : public base::RefCountedThreadSafe<FontServiceThread> {
public:
- explicit FontServiceThread(mojom::FontServicePtr font_service);
+ FontServiceThread();
+
+ // Initializes the thread, binding to |pending_font_service| in the
+ // background sequence.
+ void Init(mojo::PendingRemote<mojom::FontService> pending_font_service);
// These methods are proxies which run on your thread, post a blocking task
// to the FontServiceThread, and wait on an event signaled from the callback.
@@ -72,7 +77,7 @@ class FontServiceThread : public base::RefCountedThreadSafe<FontServiceThread> {
friend class base::RefCountedThreadSafe<FontServiceThread>;
virtual ~FontServiceThread();
- void Init();
+ void InitImpl(mojo::PendingRemote<mojom::FontService> pending_font_service);
// Methods which run on the FontServiceThread. The public MatchFamilyName
// calls this method, this method calls the mojo interface, and sets up the
@@ -167,15 +172,11 @@ class FontServiceThread : public base::RefCountedThreadSafe<FontServiceThread> {
// Connection to |font_service_| has gone away. Called on the background
// thread.
- void OnFontServiceConnectionError();
-
- // This member is used to safely pass data from one thread to another. It is
- // set in the constructor and is consumed in Init().
- mojom::FontServicePtrInfo font_service_info_;
+ void OnFontServiceDisconnected();
- // This member is set in Init(). It takes |font_service_info_|, which is
- // non-thread bound, and binds it to the newly created thread.
- mojom::FontServicePtr font_service_;
+ // This member is set in InitImpl(), binding to the provided PendingRemote on
+ // the background sequence.
+ mojo::Remote<mojom::FontService> font_service_;
// All WaitableEvents supplied to OpenStreamImpl() and the other *Impl()
// functions are added here while waiting on the response from the
@@ -187,7 +188,6 @@ class FontServiceThread : public base::RefCountedThreadSafe<FontServiceThread> {
std::set<base::WaitableEvent*> pending_waitable_events_;
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
- base::WeakPtrFactory<FontServiceThread> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(FontServiceThread);
};
diff --git a/chromium/components/services/font/public/cpp/manifest.cc b/chromium/components/services/font/public/cpp/manifest.cc
deleted file mode 100644
index 903b9fd81e6..00000000000
--- a/chromium/components/services/font/public/cpp/manifest.cc
+++ /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.
-
-#include "components/services/font/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "components/services/font/public/mojom/constants.mojom.h"
-#include "components/services/font/public/mojom/font_service.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace font_service {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName("Font Service")
- .WithOptions(service_manager::ManifestOptionsBuilder()
- .WithSandboxType("none")
- .WithInstanceSharingPolicy(
- service_manager::Manifest::
- InstanceSharingPolicy::kSharedAcrossGroups)
- .Build())
- .ExposeCapability(
- "font_service",
- service_manager::Manifest::InterfaceList<mojom::FontService>())
- .Build()};
- return *manifest;
-}
-
-} // namespace font_service
diff --git a/chromium/components/services/font/public/cpp/manifest.h b/chromium/components/services/font/public/cpp/manifest.h
deleted file mode 100644
index 1c2c50154ee..00000000000
--- a/chromium/components/services/font/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_FONT_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_FONT_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace font_service {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace font_service
-
-#endif // COMPONENTS_SERVICES_FONT_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/font/public/mojom/BUILD.gn b/chromium/components/services/font/public/mojom/BUILD.gn
index 76441bc5296..1e6edba839d 100644
--- a/chromium/components/services/font/public/mojom/BUILD.gn
+++ b/chromium/components/services/font/public/mojom/BUILD.gn
@@ -6,7 +6,6 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
- "constants.mojom",
"font_service.mojom",
]
diff --git a/chromium/components/services/font/public/mojom/constants.mojom b/chromium/components/services/font/public/mojom/constants.mojom
deleted file mode 100644
index 087574750fb..00000000000
--- a/chromium/components/services/font/public/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +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.
-
-module font_service.mojom;
-
-const string kServiceName = "font_service";
diff --git a/chromium/components/services/heap_profiling/BUILD.gn b/chromium/components/services/heap_profiling/BUILD.gn
index 77cfbdfd585..8dcbe7d8fe7 100644
--- a/chromium/components/services/heap_profiling/BUILD.gn
+++ b/chromium/components/services/heap_profiling/BUILD.gn
@@ -14,8 +14,14 @@ static_library("heap_profiling") {
"json_exporter.h",
]
- deps = [
+ public_deps = [
"//base",
+ "//components/services/heap_profiling/public/mojom",
+ "//mojo/public/cpp/bindings",
+ "//services/resource_coordinator/public/mojom",
+ ]
+
+ deps = [
"//components/services/heap_profiling/public/cpp",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
]
diff --git a/chromium/components/services/heap_profiling/OWNERS b/chromium/components/services/heap_profiling/OWNERS
index 9cc3a5e9cd2..58b20431b03 100644
--- a/chromium/components/services/heap_profiling/OWNERS
+++ b/chromium/components/services/heap_profiling/OWNERS
@@ -1,2 +1,3 @@
alph@chromium.org
erikchen@chromium.org
+# COMPONENT: Internals>Instrumentation>Memory
diff --git a/chromium/components/services/heap_profiling/connection_manager.cc b/chromium/components/services/heap_profiling/connection_manager.cc
index f2af464f9c2..3a0c23cafff 100644
--- a/chromium/components/services/heap_profiling/connection_manager.cc
+++ b/chromium/components/services/heap_profiling/connection_manager.cc
@@ -41,7 +41,7 @@ struct ConnectionManager::DumpProcessesForTracingTracking
struct ConnectionManager::Connection {
Connection(CompleteCallback complete_cb,
- mojom::ProfilingClientPtr client,
+ mojo::PendingRemote<mojom::ProfilingClient> client,
mojom::ProcessType process_type,
uint32_t sampling_rate,
mojom::StackMode stack_mode)
@@ -49,7 +49,7 @@ struct ConnectionManager::Connection {
process_type(process_type),
stack_mode(stack_mode),
sampling_rate(sampling_rate) {
- this->client.set_connection_error_handler(std::move(complete_cb));
+ this->client.set_disconnect_handler(std::move(complete_cb));
}
bool HeapDumpNeedsVmRegions() {
@@ -58,7 +58,7 @@ struct ConnectionManager::Connection {
stack_mode == mojom::StackMode::MIXED;
}
- mojom::ProfilingClientPtr client;
+ mojo::Remote<mojom::ProfilingClient> client;
mojom::ProcessType process_type;
mojom::StackMode stack_mode;
@@ -78,10 +78,11 @@ ConnectionManager::ConnectionManager() {
}
ConnectionManager::~ConnectionManager() = default;
-void ConnectionManager::OnNewConnection(base::ProcessId pid,
- mojom::ProfilingClientPtr client,
- mojom::ProcessType process_type,
- mojom::ProfilingParamsPtr params) {
+void ConnectionManager::OnNewConnection(
+ base::ProcessId pid,
+ mojo::PendingRemote<mojom::ProfilingClient> client,
+ mojom::ProcessType process_type,
+ mojom::ProfilingParamsPtr params) {
base::AutoLock lock(connections_lock_);
// Attempting to start profiling on an already profiled processs should have
diff --git a/chromium/components/services/heap_profiling/connection_manager.h b/chromium/components/services/heap_profiling/connection_manager.h
index cb576e958bf..c8ac48f89d1 100644
--- a/chromium/components/services/heap_profiling/connection_manager.h
+++ b/chromium/components/services/heap_profiling/connection_manager.h
@@ -20,6 +20,7 @@
#include "build/build_config.h"
#include "components/services/heap_profiling/allocation.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
namespace heap_profiling {
@@ -56,7 +57,7 @@ class ConnectionManager {
VmRegions vm_regions);
void OnNewConnection(base::ProcessId pid,
- mojom::ProfilingClientPtr client,
+ mojo::PendingRemote<mojom::ProfilingClient> client,
mojom::ProcessType process_type,
mojom::ProfilingParamsPtr params);
diff --git a/chromium/components/services/heap_profiling/heap_profiling_service.cc b/chromium/components/services/heap_profiling/heap_profiling_service.cc
index 8d86ba7f753..5900052850d 100644
--- a/chromium/components/services/heap_profiling/heap_profiling_service.cc
+++ b/chromium/components/services/heap_profiling/heap_profiling_service.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,116 +9,126 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/no_destructor.h"
#include "base/task/post_task.h"
+#include "components/services/heap_profiling/connection_manager.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/system/platform_handle.h"
-#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
namespace heap_profiling {
-HeapProfilingService::HeapProfilingService(
- service_manager::mojom::ServiceRequest request)
- : service_binding_(this, std::move(request)) {}
-
-HeapProfilingService::~HeapProfilingService() = default;
-
-// static
-base::RepeatingCallback<void(service_manager::mojom::ServiceRequest)>
-HeapProfilingService::GetServiceFactory() {
- return base::BindRepeating(
- [](service_manager::mojom::ServiceRequest request) {
- // base::WithBaseSyncPrimitives() and thus DEDICATED are needed
- // because the thread owned by ConnectionManager::Connection is doing
- // blocking Join during dectruction.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- base::CreateSingleThreadTaskRunnerWithTraits(
- {base::TaskPriority::BEST_EFFORT,
- base::WithBaseSyncPrimitives()},
- base::SingleThreadTaskRunnerThreadMode::DEDICATED);
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(
- [](service_manager::mojom::ServiceRequest request) {
- service_manager::Service::RunAsyncUntilTermination(
- std::make_unique<heap_profiling::HeapProfilingService>(
- std::move(request)));
- },
- std::move(request)));
- });
-}
-
-void HeapProfilingService::OnStart() {
- registry_.AddInterface(
- base::Bind(&HeapProfilingService::OnProfilingServiceRequest,
- base::Unretained(this)));
- registry_.AddInterface(base::Bind(
- &HeapProfilingService::OnHeapProfilerRequest, base::Unretained(this)));
-}
-
-void HeapProfilingService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
-}
-
-void HeapProfilingService::OnProfilingServiceRequest(
- mojom::ProfilingServiceRequest request) {
- binding_.Bind(std::move(request));
-}
-
-void HeapProfilingService::OnHeapProfilerRequest(
- memory_instrumentation::mojom::HeapProfilerRequest request) {
- heap_profiler_binding_.Bind(std::move(request));
-}
-
-void HeapProfilingService::AddProfilingClient(
- base::ProcessId pid,
- mojom::ProfilingClientPtr client,
- mojom::ProcessType process_type,
- mojom::ProfilingParamsPtr params) {
- if (params->sampling_rate == 0)
- params->sampling_rate = 1;
- connection_manager_.OnNewConnection(pid, std::move(client), process_type,
- std::move(params));
-}
+namespace {
+
+class ProfilingServiceImpl;
+
+class ProfilingServiceImpl
+ : public mojom::ProfilingService,
+ public memory_instrumentation::mojom::HeapProfiler {
+ public:
+ ProfilingServiceImpl(
+ mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
+ profiler_receiver,
+ mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
+ helper)
+ : heap_profiler_receiver_(this, std::move(profiler_receiver)),
+ helper_(std::move(helper)) {}
+
+ ~ProfilingServiceImpl() override = default;
+
+ // mojom::ProfilingService implementation:
+ void AddProfilingClient(base::ProcessId pid,
+ mojo::PendingRemote<mojom::ProfilingClient> client,
+ mojom::ProcessType process_type,
+ mojom::ProfilingParamsPtr params) override {
+ if (params->sampling_rate == 0)
+ params->sampling_rate = 1;
+ connection_manager_.OnNewConnection(pid, std::move(client), process_type,
+ std::move(params));
+ }
-void HeapProfilingService::GetProfiledPids(GetProfiledPidsCallback callback) {
- std::move(callback).Run(connection_manager_.GetConnectionPids());
-}
+ void GetProfiledPids(GetProfiledPidsCallback callback) override {
+ std::move(callback).Run(connection_manager_.GetConnectionPids());
+ }
-void HeapProfilingService::DumpProcessesForTracing(
- bool strip_path_from_mapped_files,
- DumpProcessesForTracingCallback callback) {
- std::vector<base::ProcessId> pids =
- connection_manager_.GetConnectionPidsThatNeedVmRegions();
- if (pids.empty()) {
- connection_manager_.DumpProcessesForTracing(
- strip_path_from_mapped_files, std::move(callback), VmRegions());
- return;
+ // memory_instrumentation::mojom::HeapProfiler implementation:
+ void DumpProcessesForTracing(
+ bool strip_path_from_mapped_files,
+ DumpProcessesForTracingCallback callback) override {
+ std::vector<base::ProcessId> pids =
+ connection_manager_.GetConnectionPidsThatNeedVmRegions();
+ if (pids.empty()) {
+ connection_manager_.DumpProcessesForTracing(
+ strip_path_from_mapped_files, std::move(callback), VmRegions());
+ return;
+ }
+
+ // Need a memory map to make sense of the dump. The dump will be triggered
+ // in the memory map global dump callback.
+ helper_->GetVmRegionsForHeapProfiler(
+ pids,
+ base::BindOnce(&ProfilingServiceImpl::
+ OnGetVmRegionsCompleteForDumpProcessesForTracing,
+ weak_factory_.GetWeakPtr(), strip_path_from_mapped_files,
+ std::move(callback)));
}
- // Need a memory map to make sense of the dump. The dump will be triggered
- // in the memory map global dump callback.
- if (!helper_) {
- service_binding_.GetConnector()->BindInterface(
- resource_coordinator::mojom::kServiceName, &helper_);
+ private:
+ void OnGetVmRegionsCompleteForDumpProcessesForTracing(
+ bool strip_path_from_mapped_files,
+ DumpProcessesForTracingCallback callback,
+ VmRegions vm_regions) {
+ connection_manager_.DumpProcessesForTracing(strip_path_from_mapped_files,
+ std::move(callback),
+ std::move(vm_regions));
}
- helper_->GetVmRegionsForHeapProfiler(
- pids, base::BindOnce(&HeapProfilingService::
- OnGetVmRegionsCompleteForDumpProcessesForTracing,
- weak_factory_.GetWeakPtr(),
- strip_path_from_mapped_files, std::move(callback)));
+
+ mojo::Receiver<memory_instrumentation::mojom::HeapProfiler>
+ heap_profiler_receiver_{this};
+ mojo::Remote<memory_instrumentation::mojom::HeapProfilerHelper> helper_;
+ ConnectionManager connection_manager_;
+
+ base::WeakPtrFactory<ProfilingServiceImpl> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(ProfilingServiceImpl);
+};
+
+void RunHeapProfilingService(
+ mojo::PendingReceiver<mojom::ProfilingService> receiver,
+ mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
+ profiler_receiver,
+ mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
+ helper) {
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<ProfilingServiceImpl>(std::move(profiler_receiver),
+ std::move(helper)),
+ std::move(receiver));
}
-void HeapProfilingService::OnGetVmRegionsCompleteForDumpProcessesForTracing(
- bool strip_path_from_mapped_files,
- DumpProcessesForTracingCallback callback,
- VmRegions vm_regions) {
- connection_manager_.DumpProcessesForTracing(
- strip_path_from_mapped_files, std::move(callback), std::move(vm_regions));
+} // namespace
+
+mojo::PendingRemote<mojom::ProfilingService> LaunchService(
+ mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
+ profiler_receiver,
+ mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
+ helper) {
+ mojo::PendingRemote<mojom::ProfilingService> remote;
+ auto task_runner = base::CreateSingleThreadTaskRunner(
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
+ base::WithBaseSyncPrimitives()},
+ base::SingleThreadTaskRunnerThreadMode::DEDICATED);
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunHeapProfilingService,
+ remote.InitWithNewPipeAndPassReceiver(),
+ std::move(profiler_receiver), std::move(helper)));
+ return remote;
}
} // namespace heap_profiling
diff --git a/chromium/components/services/heap_profiling/heap_profiling_service.h b/chromium/components/services/heap_profiling/heap_profiling_service.h
index ea657c02495..4b3e767718c 100644
--- a/chromium/components/services/heap_profiling/heap_profiling_service.h
+++ b/chromium/components/services/heap_profiling/heap_profiling_service.h
@@ -1,82 +1,28 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SERVICES_HEAP_PROFILING_HEAP_PROFILING_SERVICE_H_
#define COMPONENTS_SERVICES_HEAP_PROFILING_HEAP_PROFILING_SERVICE_H_
-#include "base/memory/weak_ptr.h"
-#include "components/services/heap_profiling/connection_manager.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
namespace heap_profiling {
-// Service implementation for Profiling. This will be called in the profiling
-// process (which is a sandboxed utility process created on demand by the
-// ServiceManager) to set manage the global state as well as the bound
-// interface.
+// Returns a PendingRemote which can be bound to control a new ProfilingService
+// instance running on a dedicated thread. The service will run until this
+// remote is disconnected.
//
-// This class lives in the I/O thread of the Utility process.
-class HeapProfilingService
- : public service_manager::Service,
- public mojom::ProfilingService,
- public memory_instrumentation::mojom::HeapProfiler {
- using DumpProcessesForTracingCallback = memory_instrumentation::mojom::
- HeapProfiler::DumpProcessesForTracingCallback;
-
- public:
- explicit HeapProfilingService(service_manager::mojom::ServiceRequest request);
- ~HeapProfilingService() override;
-
- static base::RepeatingCallback<void(service_manager::mojom::ServiceRequest)>
- GetServiceFactory();
-
- // Lifescycle events that occur after the service has started to spinup.
- void OnStart() override;
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- // ProfilingService implementation.
- void AddProfilingClient(base::ProcessId pid,
- mojom::ProfilingClientPtr client,
- mojom::ProcessType process_type,
- mojom::ProfilingParamsPtr params) override;
- void GetProfiledPids(GetProfiledPidsCallback callback) override;
-
- // HeapProfiler implementation.
- void DumpProcessesForTracing(
- bool strip_path_from_mapped_files,
- DumpProcessesForTracingCallback callback) override;
-
- private:
- void OnProfilingServiceRequest(mojom::ProfilingServiceRequest request);
- void OnHeapProfilerRequest(
- memory_instrumentation::mojom::HeapProfilerRequest request);
-
- void OnGetVmRegionsCompleteForDumpProcessesForTracing(
- bool strip_path_from_mapped_files,
- DumpProcessesForTracingCallback callback,
- VmRegions vm_regions);
-
- service_manager::ServiceBinding service_binding_;
- service_manager::BinderRegistry registry_;
- mojo::Binding<mojom::ProfilingService> binding_{this};
-
- mojo::Binding<memory_instrumentation::mojom::HeapProfiler>
- heap_profiler_binding_{this};
-
- memory_instrumentation::mojom::HeapProfilerHelperPtr helper_;
- ConnectionManager connection_manager_;
- // Must be the last.
- base::WeakPtrFactory<HeapProfilingService> weak_factory_{this};
-};
+// |profiler_receiver| must be valid and will receive heap profiling requests.
+// |helper| must be valid and will be used by the service to retrieve memory
+// maps.
+mojo::PendingRemote<mojom::ProfilingService> LaunchService(
+ mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
+ profiler_receiver,
+ mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
+ helper);
} // namespace heap_profiling
diff --git a/chromium/components/services/heap_profiling/public/cpp/BUILD.gn b/chromium/components/services/heap_profiling/public/cpp/BUILD.gn
index 409890369e8..e016a91843f 100644
--- a/chromium/components/services/heap_profiling/public/cpp/BUILD.gn
+++ b/chromium/components/services/heap_profiling/public/cpp/BUILD.gn
@@ -15,15 +15,14 @@ static_library("cpp") {
]
public_deps = [
+ "//base",
"//components/services/heap_profiling/public/mojom",
+ "//mojo/public/cpp/bindings",
]
+
deps = [
- "//base",
"//base:debugging_buildflags",
"//base/allocator:buildflags",
- "//services/resource_coordinator/public/mojom:",
- "//services/service_manager/public/cpp",
- "//services/service_manager/sandbox",
]
}
@@ -40,17 +39,3 @@ source_set("unit_tests") {
"//testing/gtest",
]
}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/heap_profiling/public/mojom",
- "//services/resource_coordinator/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
diff --git a/chromium/components/services/heap_profiling/public/cpp/OWNERS b/chromium/components/services/heap_profiling/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/heap_profiling/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/heap_profiling/public/cpp/controller.cc b/chromium/components/services/heap_profiling/public/cpp/controller.cc
index a0c76f7013f..5bb6676f427 100644
--- a/chromium/components/services/heap_profiling/public/cpp/controller.cc
+++ b/chromium/components/services/heap_profiling/public/cpp/controller.cc
@@ -5,39 +5,24 @@
#include "components/services/heap_profiling/public/cpp/controller.h"
#include "components/services/heap_profiling/public/cpp/settings.h"
-#include "components/services/heap_profiling/public/mojom/constants.mojom.h"
-#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
namespace heap_profiling {
-Controller::Controller(std::unique_ptr<service_manager::Connector> connector,
+Controller::Controller(mojo::PendingRemote<mojom::ProfilingService> service,
mojom::StackMode stack_mode,
uint32_t sampling_rate)
- : connector_(std::move(connector)),
+ : heap_profiling_service_(std::move(service)),
sampling_rate_(sampling_rate),
stack_mode_(stack_mode) {
DCHECK_NE(sampling_rate, 0u);
-
- // Start the Heap Profiling service.
- connector_->BindInterface(mojom::kServiceName, &heap_profiling_service_);
-
- // Grab a HeapProfiler InterfacePtr and pass that to memory instrumentation.
- memory_instrumentation::mojom::HeapProfilerPtr heap_profiler;
- connector_->BindInterface(mojom::kServiceName, &heap_profiler);
-
- memory_instrumentation::mojom::CoordinatorPtr coordinator;
- connector_->BindInterface(resource_coordinator::mojom::kServiceName,
- &coordinator);
- coordinator->RegisterHeapProfiler(std::move(heap_profiler));
}
Controller::~Controller() = default;
-void Controller::StartProfilingClient(mojom::ProfilingClientPtr client,
- base::ProcessId pid,
- mojom::ProcessType process_type) {
+void Controller::StartProfilingClient(
+ mojo::PendingRemote<mojom::ProfilingClient> client,
+ base::ProcessId pid,
+ mojom::ProcessType process_type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
mojom::ProfilingParamsPtr params = mojom::ProfilingParams::New();
@@ -57,9 +42,4 @@ base::WeakPtr<Controller> Controller::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-service_manager::Connector* Controller::GetConnector() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return connector_.get();
-}
-
} // namespace heap_profiling
diff --git a/chromium/components/services/heap_profiling/public/cpp/controller.h b/chromium/components/services/heap_profiling/public/cpp/controller.h
index 02762d501f0..ed19b9a0947 100644
--- a/chromium/components/services/heap_profiling/public/cpp/controller.h
+++ b/chromium/components/services/heap_profiling/public/cpp/controller.h
@@ -10,17 +10,13 @@
#include "base/sequence_checker.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h"
-
-namespace service_manager {
-class Connector;
-}
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
namespace heap_profiling {
-// This class is responsible for
-// * Starting the Heap Profiling Service
-// * Hooking up clients to the service
-// * Getting information about profiled clients
+// This class is responsible for hooking up clients to the heap profiling
+// service and getting information about profiled clients.
//
// This class is sequence-affine. The public non-getter methods must be called
// from a single sequence. Getters return const members set during the
@@ -30,7 +26,8 @@ namespace heap_profiling {
// create OS pipes.
class Controller {
public:
- // |connector| is used to connect to other services.
+ // |service| must be connected to an instance of the Heap Profiling service.
+ //
// |stack_mode| describes the type of metadata to record for each allocation.
// A |sampling_rate| of 1 indicates that all allocations should be recorded.
// A |sampling_rate| greater than 1 describes the Poisson Process sampling
@@ -40,13 +37,13 @@ class Controller {
// Note: The name |sampling_rate| is a bit confusing. A higher sampling rate
// causes there to be fewer samples taken. This probably should have been
// named |sampling_interval|.
- Controller(std::unique_ptr<service_manager::Connector> connector,
+ Controller(mojo::PendingRemote<mojom::ProfilingService> service,
mojom::StackMode stack_mode,
uint32_t sampling_rate);
~Controller();
// Starts Heap Profiling for the client.
- void StartProfilingClient(mojom::ProfilingClientPtr client,
+ void StartProfilingClient(mojo::PendingRemote<mojom::ProfilingClient> client,
base::ProcessId pid,
mojom::ProcessType);
@@ -61,11 +58,8 @@ class Controller {
// This method must be called from the same sequence the instance is bound to.
base::WeakPtr<Controller> GetWeakPtr();
- service_manager::Connector* GetConnector();
-
private:
- std::unique_ptr<service_manager::Connector> connector_;
- mojom::ProfilingServicePtr heap_profiling_service_;
+ mojo::Remote<mojom::ProfilingService> heap_profiling_service_;
// The same sampling rate and stack mode is used for each client.
const uint32_t sampling_rate_ = 1;
diff --git a/chromium/components/services/heap_profiling/public/cpp/manifest.cc b/chromium/components/services/heap_profiling/public/cpp/manifest.cc
deleted file mode 100644
index bd3e16b60ab..00000000000
--- a/chromium/components/services/heap_profiling/public/cpp/manifest.cc
+++ /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.
-
-#include "components/services/heap_profiling/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "components/services/heap_profiling/public/mojom/constants.mojom.h"
-#include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h"
-#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace heap_profiling {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName("Heap Profiling Service")
- .WithOptions(service_manager::ManifestOptionsBuilder()
- .WithSandboxType("profiling")
- .WithInstanceSharingPolicy(
- service_manager::Manifest::
- InstanceSharingPolicy::kSharedAcrossGroups)
- .Build())
- .ExposeCapability("profiling",
- service_manager::Manifest::InterfaceList<
- mojom::ProfilingService>())
- .ExposeCapability("heap_profiler",
- service_manager::Manifest::InterfaceList<
- memory_instrumentation::mojom::HeapProfiler>())
- .RequireCapability(resource_coordinator::mojom::kServiceName,
- "heap_profiler_helper")
- .Build()};
- return *manifest;
-}
-
-} // namespace heap_profiling
diff --git a/chromium/components/services/heap_profiling/public/cpp/manifest.h b/chromium/components/services/heap_profiling/public/cpp/manifest.h
deleted file mode 100644
index 96f7f0c8e3b..00000000000
--- a/chromium/components/services/heap_profiling/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace heap_profiling {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace heap_profiling
-
-#endif // COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/heap_profiling/public/cpp/profiling_client.cc b/chromium/components/services/heap_profiling/public/cpp/profiling_client.cc
index 2f0bf6f1394..abd844b798c 100644
--- a/chromium/components/services/heap_profiling/public/cpp/profiling_client.cc
+++ b/chromium/components/services/heap_profiling/public/cpp/profiling_client.cc
@@ -29,8 +29,9 @@ namespace heap_profiling {
ProfilingClient::ProfilingClient() = default;
ProfilingClient::~ProfilingClient() = default;
-void ProfilingClient::BindToInterface(mojom::ProfilingClientRequest request) {
- bindings_.AddBinding(this, std::move(request));
+void ProfilingClient::BindToInterface(
+ mojo::PendingReceiver<mojom::ProfilingClient> receiver) {
+ receivers_.Add(this, std::move(receiver));
}
void ProfilingClient::StartProfiling(mojom::ProfilingParamsPtr params) {
@@ -50,9 +51,9 @@ void ProfilingClient::StartProfiling(mojom::ProfilingParamsPtr params) {
defined(OFFICIAL_BUILD)
// On Android the unwinder initialization requires file reading before
// initializing shim. So, post task on background thread.
- base::PostTaskWithTraitsAndReply(
+ base::PostTaskAndReply(
FROM_HERE,
- {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce([]() {
bool can_unwind =
diff --git a/chromium/components/services/heap_profiling/public/cpp/profiling_client.h b/chromium/components/services/heap_profiling/public/cpp/profiling_client.h
index f167bac18ac..2ae95050141 100644
--- a/chromium/components/services/heap_profiling/public/cpp/profiling_client.h
+++ b/chromium/components/services/heap_profiling/public/cpp/profiling_client.h
@@ -6,7 +6,8 @@
#define COMPONENTS_SERVICES_HEAP_PROFILING_PUBLIC_CPP_PROFILING_CLIENT_H_
#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
namespace heap_profiling {
@@ -22,20 +23,20 @@ class ProfilingClient : public mojom::ProfilingClient {
void StartProfiling(mojom::ProfilingParamsPtr params) override;
void RetrieveHeapProfile(RetrieveHeapProfileCallback callback) override;
- void BindToInterface(mojom::ProfilingClientRequest request);
+ void BindToInterface(mojo::PendingReceiver<mojom::ProfilingClient> receiver);
private:
~ProfilingClient() override;
void StartProfilingInternal(mojom::ProfilingParamsPtr params);
- // Ideally, this would be a mojo::Binding that would only keep alive one
- // client request. However, the service that makes the client requests
+ // Ideally, this would be a mojo::Receiver that would only keep alive one
+ // client receiver. However, the service that makes the client requests
// [content_browser] is different from the service that dedupes the client
// requests [profiling service]. This means that there may be a brief
// intervals where there are two active bindings, until the profiling service
// has a chance to figure out which one to keep.
- mojo::BindingSet<mojom::ProfilingClient> bindings_;
+ mojo::ReceiverSet<mojom::ProfilingClient> receivers_;
bool started_profiling_{false};
};
diff --git a/chromium/components/services/heap_profiling/public/mojom/BUILD.gn b/chromium/components/services/heap_profiling/public/mojom/BUILD.gn
index fa28fe7f4bf..bc27caa3b3f 100644
--- a/chromium/components/services/heap_profiling/public/mojom/BUILD.gn
+++ b/chromium/components/services/heap_profiling/public/mojom/BUILD.gn
@@ -6,7 +6,6 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
- "constants.mojom",
"heap_profiling_client.mojom",
"heap_profiling_service.mojom",
]
diff --git a/chromium/components/services/heap_profiling/public/mojom/constants.mojom b/chromium/components/services/heap_profiling/public/mojom/constants.mojom
deleted file mode 100644
index 085a130b363..00000000000
--- a/chromium/components/services/heap_profiling/public/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +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.
-
-module heap_profiling.mojom;
-
-const string kServiceName = "heap_profiling";
diff --git a/chromium/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom b/chromium/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom
index e8e0ff60db8..ba5e3367085 100644
--- a/chromium/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom
+++ b/chromium/components/services/heap_profiling/public/mojom/heap_profiling_service.mojom
@@ -24,8 +24,10 @@ interface ProfilingService {
//
// The "client" interface will be for the instrumented process. It allows the
// profiling process to talk to the new process.
- AddProfilingClient(mojo_base.mojom.ProcessId pid, ProfilingClient client,
- ProcessType process_type, ProfilingParams params);
+ AddProfilingClient(mojo_base.mojom.ProcessId pid,
+ pending_remote<ProfilingClient> client,
+ ProcessType process_type,
+ ProfilingParams params);
// Returns the pids of all profiled processes.
GetProfiledPids() => (array<mojo_base.mojom.ProcessId> pids);
diff --git a/chromium/components/services/leveldb/BUILD.gn b/chromium/components/services/leveldb/BUILD.gn
index d78c2b619cd..b4a651097cf 100644
--- a/chromium/components/services/leveldb/BUILD.gn
+++ b/chromium/components/services/leveldb/BUILD.gn
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//services/service_manager/public/cpp/service_executable.gni")
import("//testing/test.gni")
static_library("lib") {
@@ -25,27 +24,10 @@ static_library("lib") {
deps = [
"//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
"//third_party/leveldatabase",
]
}
-service_executable("leveldb") {
- sources = [
- "leveldb_app.cc",
- "leveldb_app.h",
- "main.cc",
- ]
-
- deps = [
- ":lib",
- "//components/services/leveldb/public/mojom",
- "//mojo/public/cpp/bindings",
- "//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
- ]
-}
-
test("leveldb_service_unittests") {
sources = [
"leveldb_mojo_unittest.cc",
@@ -54,24 +36,18 @@ test("leveldb_service_unittests") {
]
deps = [
+ ":lib",
"//base",
"//base/test:test_support",
- "//components/services/filesystem/public/cpp:manifest",
+ "//components/services/filesystem:lib",
+ "//components/services/filesystem:test_support",
"//components/services/filesystem/public/mojom",
"//components/services/leveldb/public/cpp",
- "//components/services/leveldb/public/cpp:manifest",
"//components/services/leveldb/public/mojom",
"//mojo/core/test:run_all_unittests",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/cpp/test:test_support",
"//testing/gtest",
"//third_party/leveldatabase",
]
-
- data_deps = [
- ":leveldb",
- "//components/services/filesystem:filesystem",
- ]
}
diff --git a/chromium/components/services/leveldb/DEPS b/chromium/components/services/leveldb/DEPS
index b8a7f958f32..1debd9d34f1 100644
--- a/chromium/components/services/leveldb/DEPS
+++ b/chromium/components/services/leveldb/DEPS
@@ -1,7 +1,5 @@
include_rules = [
"+components/services/filesystem/public/mojom",
"+mojo/public",
- "+mojo/util",
- "+services/service_manager",
"+third_party/leveldatabase",
]
diff --git a/chromium/components/services/leveldb/OWNERS b/chromium/components/services/leveldb/OWNERS
index ecf8616c2ff..6de0c1dfc69 100644
--- a/chromium/components/services/leveldb/OWNERS
+++ b/chromium/components/services/leveldb/OWNERS
@@ -5,3 +5,5 @@ per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
+# COMPONENT: Internals>Storage
+# TEAM: storage-dev@chromium.org
diff --git a/chromium/components/services/leveldb/env_mojo.cc b/chromium/components/services/leveldb/env_mojo.cc
index 86bbf050ff4..01561482cee 100644
--- a/chromium/components/services/leveldb/env_mojo.cc
+++ b/chromium/components/services/leveldb/env_mojo.cc
@@ -517,10 +517,11 @@ void MojoEnv::SleepForMicroseconds(int micros) {
}
void MojoEnv::Schedule(void (*function)(void* arg), void* arg) {
- base::PostTaskWithTraits(FROM_HERE,
- {base::MayBlock(), base::WithBaseSyncPrimitives(),
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
- base::BindOnce(function, arg));
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+ base::BindOnce(function, arg));
}
void MojoEnv::StartThread(void (*function)(void* arg), void* arg) {
diff --git a/chromium/components/services/leveldb/leveldb_app.cc b/chromium/components/services/leveldb/leveldb_app.cc
deleted file mode 100644
index 5713b75855c..00000000000
--- a/chromium/components/services/leveldb/leveldb_app.cc
+++ /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.
-
-#include "components/services/leveldb/leveldb_app.h"
-
-#include "base/bind.h"
-#include "base/task/post_task.h"
-#include "components/services/leveldb/leveldb_service_impl.h"
-
-namespace leveldb {
-
-LevelDBApp::LevelDBApp(service_manager::mojom::ServiceRequest request)
- : service_binding_(this, std::move(request)),
- file_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {
- registry_.AddInterface<mojom::LevelDBService>(
- base::Bind(&LevelDBApp::Create, base::Unretained(this)));
-}
-
-LevelDBApp::~LevelDBApp() {}
-
-void LevelDBApp::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
-}
-
-void LevelDBApp::Create(leveldb::mojom::LevelDBServiceRequest request) {
- if (!service_)
- service_.reset(new LevelDBServiceImpl(file_task_runner_));
- bindings_.AddBinding(service_.get(), std::move(request));
-}
-
-} // namespace leveldb
diff --git a/chromium/components/services/leveldb/leveldb_app.h b/chromium/components/services/leveldb/leveldb_app.h
deleted file mode 100644
index 53b3854bd81..00000000000
--- a/chromium/components/services/leveldb/leveldb_app.h
+++ /dev/null
@@ -1,47 +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 COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
-#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
-
-#include <memory>
-
-#include "components/services/leveldb/public/mojom/leveldb.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace leveldb {
-
-class LevelDBApp : public service_manager::Service {
- public:
- explicit LevelDBApp(service_manager::mojom::ServiceRequest request);
- ~LevelDBApp() override;
-
- private:
- // |Service| override:
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- void Create(leveldb::mojom::LevelDBServiceRequest request);
-
- service_manager::ServiceBinding service_binding_;
- std::unique_ptr<mojom::LevelDBService> service_;
- service_manager::BinderRegistry registry_;
- mojo::BindingSet<mojom::LevelDBService> bindings_;
-
- scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(LevelDBApp);
-};
-
-} // namespace leveldb
-
-#endif // COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
diff --git a/chromium/components/services/leveldb/leveldb_service_impl.cc b/chromium/components/services/leveldb/leveldb_service_impl.cc
index 757c5d6e826..ca312231e1e 100644
--- a/chromium/components/services/leveldb/leveldb_service_impl.cc
+++ b/chromium/components/services/leveldb/leveldb_service_impl.cc
@@ -12,7 +12,8 @@
#include "components/services/leveldb/env_mojo.h"
#include "components/services/leveldb/leveldb_database_impl.h"
#include "components/services/leveldb/public/cpp/util.h"
-#include "mojo/public/cpp/bindings/strong_associated_binding.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
@@ -21,15 +22,16 @@
namespace leveldb {
namespace {
-void CreateBinding(std::unique_ptr<LevelDBDatabaseImpl> db,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest request) {
+void CreateReceiver(
+ std::unique_ptr<LevelDBDatabaseImpl> db,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> receiver) {
// The database should be able to close the binding if it gets into an
// error condition that can't be recovered.
LevelDBDatabaseImpl* impl = db.get();
- auto binding =
- mojo::MakeStrongAssociatedBinding(std::move(db), std::move(request));
impl->SetCloseBindingClosure(base::BindOnce(
- &mojo::StrongAssociatedBinding<mojom::LevelDBDatabase>::Close, binding));
+ &mojo::StrongAssociatedBinding<mojom::LevelDBDatabase>::Close,
+ mojo::MakeSelfOwnedAssociatedReceiver(std::move(db),
+ std::move(receiver))));
}
} // namespace
@@ -45,7 +47,7 @@ void LevelDBServiceImpl::Open(
const std::string& dbname,
const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
OpenCallback callback) {
leveldb_env::Options options;
// the default here to 80 instead of leveldb's default 1000 because we don't
@@ -64,7 +66,7 @@ void LevelDBServiceImpl::OpenWithOptions(
const std::string& dbname,
const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
OpenCallback callback) {
// Register our directory with the file thread.
LevelDBMojoProxy::OpaqueDir* dir =
@@ -78,10 +80,10 @@ void LevelDBServiceImpl::OpenWithOptions(
leveldb::Status s = leveldb_env::OpenDB(open_options, dbname, &db);
if (s.ok()) {
- CreateBinding(std::make_unique<LevelDBDatabaseImpl>(
- std::move(env_mojo), std::move(db), nullptr, open_options,
- dbname, memory_dump_id),
- std::move(database));
+ CreateReceiver(std::make_unique<LevelDBDatabaseImpl>(
+ std::move(env_mojo), std::move(db), nullptr,
+ open_options, dbname, memory_dump_id),
+ std::move(database));
}
std::move(callback).Run(LeveldbStatusToError(s));
@@ -91,7 +93,7 @@ void LevelDBServiceImpl::OpenInMemory(
const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
const std::string& tracking_name,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
OpenCallback callback) {
leveldb_env::Options options;
options.create_if_missing = true;
@@ -104,10 +106,10 @@ void LevelDBServiceImpl::OpenInMemory(
leveldb::Status s = leveldb_env::OpenDB(options, "", &db);
if (s.ok()) {
- CreateBinding(std::make_unique<LevelDBDatabaseImpl>(
- std::move(env), std::move(db), nullptr, options,
- tracking_name, memory_dump_id),
- std::move(database));
+ CreateReceiver(std::make_unique<LevelDBDatabaseImpl>(
+ std::move(env), std::move(db), nullptr, options,
+ tracking_name, memory_dump_id),
+ std::move(database));
}
std::move(callback).Run(LeveldbStatusToError(s));
diff --git a/chromium/components/services/leveldb/leveldb_service_impl.h b/chromium/components/services/leveldb/leveldb_service_impl.h
index 1755d019fed..0665d5abbf5 100644
--- a/chromium/components/services/leveldb/leveldb_service_impl.h
+++ b/chromium/components/services/leveldb/leveldb_service_impl.h
@@ -8,7 +8,7 @@
#include "base/memory/ref_counted.h"
#include "components/services/leveldb/leveldb_mojo_proxy.h"
#include "components/services/leveldb/public/mojom/leveldb.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
namespace base {
class SequencedTaskRunner;
@@ -22,29 +22,31 @@ class LevelDBServiceImpl : public mojom::LevelDBService {
// The |file_task_runner| is used to run tasks to interact with the
// file_service. Specifically this task runner must NOT be the same as the
// task runner this implementation runs on, or deadlock might occur.
- LevelDBServiceImpl(scoped_refptr<base::SequencedTaskRunner> file_task_runner);
+ explicit LevelDBServiceImpl(
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner);
~LevelDBServiceImpl() override;
// Overridden from LevelDBService:
- void Open(filesystem::mojom::DirectoryPtr directory,
- const std::string& dbname,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
- memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
- OpenCallback callback) override;
+ void Open(
+ filesystem::mojom::DirectoryPtr directory,
+ const std::string& dbname,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
+ OpenCallback callback) override;
void OpenWithOptions(
const leveldb_env::Options& open_options,
filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
OpenCallback callback) override;
void OpenInMemory(
const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
const std::string& tracking_name,
- leveldb::mojom::LevelDBDatabaseAssociatedRequest database,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
OpenInMemoryCallback callback) override;
void Destroy(filesystem::mojom::DirectoryPtr directory,
const std::string& dbname,
diff --git a/chromium/components/services/leveldb/leveldb_service_unittest.cc b/chromium/components/services/leveldb/leveldb_service_unittest.cc
index a719d9979ec..0dc185c481e 100644
--- a/chromium/components/services/leveldb/leveldb_service_unittest.cc
+++ b/chromium/components/services/leveldb/leveldb_service_unittest.cc
@@ -3,21 +3,23 @@
// found in the LICENSE file.
#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/services/filesystem/public/cpp/manifest.h"
+#include "base/test/task_environment.h"
+#include "components/services/filesystem/directory_test_helper.h"
#include "components/services/filesystem/public/mojom/directory.mojom.h"
-#include "components/services/filesystem/public/mojom/file_system.mojom.h"
#include "components/services/filesystem/public/mojom/types.mojom.h"
-#include "components/services/leveldb/public/cpp/manifest.h"
+#include "components/services/leveldb/leveldb_service_impl.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "components/services/leveldb/public/mojom/leveldb.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-#include "services/service_manager/public/cpp/test/test_service.h"
-#include "services/service_manager/public/cpp/test/test_service_manager.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/leveldb_features.h"
@@ -137,9 +139,10 @@ void DatabaseSyncRewrite(mojom::LevelDBDatabase* database,
run_loop.Run();
}
-void LevelDBSyncOpenInMemory(mojom::LevelDBService* leveldb,
- mojom::LevelDBDatabaseAssociatedRequest database,
- mojom::DatabaseError* out_error) {
+void LevelDBSyncOpenInMemory(
+ mojom::LevelDBService* leveldb,
+ mojo::PendingAssociatedReceiver<leveldb::mojom::LevelDBDatabase> database,
+ mojom::DatabaseError* out_error) {
base::RunLoop run_loop;
leveldb->OpenInMemory(base::nullopt, "LevelDBSync", std::move(database),
Capture(out_error, run_loop.QuitClosure()));
@@ -158,62 +161,46 @@ void AddKeyPrefixToGetManyRequest(const std::string& key_prefix,
list->emplace_back(mojom::GetManyRequest::NewKeyPrefix(in_arg));
}
-const char kTestServiceName[] = "leveldb_service_unittests";
-
class LevelDBServiceTest : public testing::Test {
public:
LevelDBServiceTest()
- : test_service_manager_(
- {GetManifest(), filesystem::GetManifest(),
- service_manager::ManifestBuilder()
- .WithServiceName(kTestServiceName)
- .RequireCapability("filesystem", "filesystem:filesystem")
- .RequireCapability("leveldb", "leveldb:leveldb")
- .Build()}),
- test_service_(
- test_service_manager_.RegisterTestInstance(kTestServiceName)) {}
+ : leveldb_service_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+ leveldb_receiver_(&leveldb_service_,
+ leveldb_remote_.BindNewPipeAndPassReceiver()) {}
~LevelDBServiceTest() override = default;
protected:
- service_manager::Connector* connector() { return test_service_.connector(); }
-
void SetUp() override {
// TODO(dullweber): This doesn't seem to work. The reason is probably that
// the LevelDB service is a separate executable here. How should we set
// features that affect a service?
feature_list_.InitAndEnableFeature(leveldb::kLevelDBRewriteFeature);
- connector()->BindInterface("filesystem", &files_);
- connector()->BindInterface("leveldb", &leveldb_);
}
- // Note: This has an out parameter rather than returning the |DirectoryPtr|,
- // since |ASSERT_...()| doesn't work with return values.
- void GetTempDirectory(filesystem::mojom::DirectoryPtr* directory) {
- base::File::Error error = base::File::Error::FILE_ERROR_FAILED;
- bool handled = files()->OpenTempDirectory(MakeRequest(directory), &error);
- ASSERT_TRUE(handled);
- ASSERT_EQ(base::File::Error::FILE_OK, error);
+ mojo::Remote<filesystem::mojom::Directory> CreateTempDir() {
+ return directory_helper_.CreateTempDir();
}
- filesystem::mojom::FileSystemPtr& files() { return files_; }
- mojom::LevelDBServicePtr& leveldb() { return leveldb_; }
+ mojo::Remote<mojom::LevelDBService>& leveldb() { return leveldb_remote_; }
private:
- base::test::ScopedTaskEnvironment task_environment_;
- service_manager::TestServiceManager test_service_manager_;
- service_manager::TestService test_service_;
-
+ base::test::TaskEnvironment task_environment_;
base::test::ScopedFeatureList feature_list_;
- filesystem::mojom::FileSystemPtr files_;
- mojom::LevelDBServicePtr leveldb_;
+ filesystem::DirectoryTestHelper directory_helper_;
+ LevelDBServiceImpl leveldb_service_;
+ mojo::Remote<mojom::LevelDBService> leveldb_remote_;
+ mojo::Receiver<mojom::LevelDBService> leveldb_receiver_;
DISALLOW_COPY_AND_ASSIGN(LevelDBServiceTest);
};
TEST_F(LevelDBServiceTest, Basic) {
mojom::DatabaseError error;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
// Write a key to the database.
@@ -243,8 +230,9 @@ TEST_F(LevelDBServiceTest, Basic) {
TEST_F(LevelDBServiceTest, WriteBatch) {
mojom::DatabaseError error;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
// Write a key to the database.
@@ -334,8 +322,9 @@ TEST_F(LevelDBServiceTest, WriteBatchPrefixesAndDeletes) {
// This test makes sure that prefixes & deletes happen before all other batch
// operations.
mojom::DatabaseError error;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
// Write a key to the database.
@@ -388,20 +377,20 @@ TEST_F(LevelDBServiceTest, WriteBatchPrefixesAndDeletes) {
TEST_F(LevelDBServiceTest, Reconnect) {
mojom::DatabaseError error;
- filesystem::mojom::DirectoryPtr temp_directory;
- GetTempDirectory(&temp_directory);
+ mojo::Remote<filesystem::mojom::Directory> temp_directory = CreateTempDir();
{
filesystem::mojom::DirectoryPtr directory;
temp_directory->Clone(MakeRequest(&directory));
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
leveldb_env::Options options;
options.error_if_exists = true;
options.create_if_missing = true;
base::RunLoop run_loop;
leveldb()->OpenWithOptions(std::move(options), std::move(directory), "test",
- base::nullopt, MakeRequest(&database),
+ base::nullopt,
+ database.BindNewEndpointAndPassReceiver(),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -419,10 +408,10 @@ TEST_F(LevelDBServiceTest, Reconnect) {
temp_directory->Clone(MakeRequest(&directory));
// Reconnect to the database.
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
base::RunLoop run_loop;
leveldb()->Open(std::move(directory), "test", base::nullopt,
- MakeRequest(&database),
+ database.BindNewEndpointAndPassReceiver(),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -439,20 +428,20 @@ TEST_F(LevelDBServiceTest, Reconnect) {
TEST_F(LevelDBServiceTest, Destroy) {
mojom::DatabaseError error;
- filesystem::mojom::DirectoryPtr temp_directory;
- GetTempDirectory(&temp_directory);
+ mojo::Remote<filesystem::mojom::Directory> temp_directory = CreateTempDir();
{
filesystem::mojom::DirectoryPtr directory;
temp_directory->Clone(MakeRequest(&directory));
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
leveldb_env::Options options;
options.error_if_exists = true;
options.create_if_missing = true;
base::RunLoop run_loop;
leveldb()->OpenWithOptions(std::move(options), std::move(directory), "test",
- base::nullopt, MakeRequest(&database),
+ base::nullopt,
+ database.BindNewEndpointAndPassReceiver(),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -482,10 +471,10 @@ TEST_F(LevelDBServiceTest, Destroy) {
temp_directory->Clone(MakeRequest(&directory));
// Reconnect to the database should fail.
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
base::RunLoop run_loop;
leveldb()->Open(std::move(directory), "test", base::nullopt,
- MakeRequest(&database),
+ database.BindNewEndpointAndPassReceiver(),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::INVALID_ARGUMENT, error);
@@ -506,8 +495,9 @@ TEST_F(LevelDBServiceTest, Destroy) {
TEST_F(LevelDBServiceTest, GetSnapshotSimple) {
mojom::DatabaseError error;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
base::UnguessableToken snapshot;
@@ -519,8 +509,9 @@ TEST_F(LevelDBServiceTest, GetSnapshotSimple) {
TEST_F(LevelDBServiceTest, GetFromSnapshots) {
mojom::DatabaseError error;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
// Write a key to the database.
@@ -560,9 +551,10 @@ TEST_F(LevelDBServiceTest, GetFromSnapshots) {
}
TEST_F(LevelDBServiceTest, InvalidArgumentOnInvalidSnapshot) {
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
mojom::DatabaseError error = mojom::DatabaseError::INVALID_ARGUMENT;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
base::UnguessableToken invalid_snapshot = base::UnguessableToken::Create();
@@ -578,9 +570,10 @@ TEST_F(LevelDBServiceTest, InvalidArgumentOnInvalidSnapshot) {
}
TEST_F(LevelDBServiceTest, MemoryDBReadWrite) {
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
mojom::DatabaseError error = mojom::DatabaseError::INVALID_ARGUMENT;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
// Write a key to the database.
@@ -611,8 +604,9 @@ TEST_F(LevelDBServiceTest, MemoryDBReadWrite) {
TEST_F(LevelDBServiceTest, Prefixed) {
// Open an in memory database for speed.
mojom::DatabaseError error = mojom::DatabaseError::INVALID_ARGUMENT;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
const std::string prefix("prefix");
@@ -721,15 +715,15 @@ TEST_F(LevelDBServiceTest, Prefixed) {
TEST_F(LevelDBServiceTest, RewriteDB) {
mojom::DatabaseError error;
- filesystem::mojom::DirectoryPtr directory;
- GetTempDirectory(&directory);
+ filesystem::mojom::DirectoryPtr directory(CreateTempDir().Unbind());
- mojom::LevelDBDatabaseAssociatedPtr database;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
leveldb_env::Options options;
options.create_if_missing = true;
base::RunLoop run_loop;
leveldb()->OpenWithOptions(std::move(options), std::move(directory), "test",
- base::nullopt, MakeRequest(&database),
+ base::nullopt,
+ database.BindNewEndpointAndPassReceiver(),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -759,8 +753,9 @@ TEST_F(LevelDBServiceTest, RewriteDB) {
TEST_F(LevelDBServiceTest, GetMany) {
mojom::DatabaseError error;
- mojom::LevelDBDatabaseAssociatedPtr database;
- LevelDBSyncOpenInMemory(leveldb().get(), MakeRequest(&database), &error);
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database;
+ LevelDBSyncOpenInMemory(leveldb().get(),
+ database.BindNewEndpointAndPassReceiver(), &error);
EXPECT_EQ(mojom::DatabaseError::OK, error);
// Write two keys to the database.
diff --git a/chromium/components/services/leveldb/main.cc b/chromium/components/services/leveldb/main.cc
deleted file mode 100644
index 80899d95a81..00000000000
--- a/chromium/components/services/leveldb/main.cc
+++ /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.
-
-#include "base/task/single_thread_task_executor.h"
-#include "components/services/leveldb/leveldb_app.h"
-#include "services/service_manager/public/cpp/service_executable/service_main.h"
-
-void ServiceMain(service_manager::mojom::ServiceRequest request) {
- base::SingleThreadTaskExecutor main_thread_task_executor;
- leveldb::LevelDBApp(std::move(request)).RunUntilTermination();
-}
diff --git a/chromium/components/services/leveldb/public/cpp/BUILD.gn b/chromium/components/services/leveldb/public/cpp/BUILD.gn
index 86ba2cba959..033466eb05a 100644
--- a/chromium/components/services/leveldb/public/cpp/BUILD.gn
+++ b/chromium/components/services/leveldb/public/cpp/BUILD.gn
@@ -13,20 +13,6 @@ static_library("cpp") {
deps = [
"//base",
"//components/services/leveldb/public/mojom",
- "//services/service_manager/public/cpp",
"//third_party/leveldatabase",
]
}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/leveldb/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
diff --git a/chromium/components/services/leveldb/public/cpp/OWNERS b/chromium/components/services/leveldb/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/leveldb/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/leveldb/public/cpp/manifest.cc b/chromium/components/services/leveldb/public/cpp/manifest.cc
deleted file mode 100644
index 255564cf27c..00000000000
--- a/chromium/components/services/leveldb/public/cpp/manifest.cc
+++ /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.
-
-#include "components/services/leveldb/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "components/services/leveldb/public/mojom/leveldb.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace leveldb {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName("leveldb")
- .WithDisplayName("LevelDB Service")
- .WithOptions(
- service_manager::ManifestOptionsBuilder()
- .WithSandboxType("none")
- .WithExecutionMode(service_manager::Manifest::ExecutionMode ::
- kStandaloneExecutable)
- .Build())
- .ExposeCapability(
- "leveldb:leveldb",
- service_manager::Manifest::InterfaceList<mojom::LevelDBService>())
- .Build()};
- return *manifest;
-}
-
-} // namespace leveldb
diff --git a/chromium/components/services/leveldb/public/cpp/manifest.h b/chromium/components/services/leveldb/public/cpp/manifest.h
deleted file mode 100644
index 09d6c6ae495..00000000000
--- a/chromium/components/services/leveldb/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace leveldb {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace leveldb
-
-#endif // COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/leveldb/public/mojom/leveldb.mojom b/chromium/components/services/leveldb/public/mojom/leveldb.mojom
index c4027284e9f..3de269f8cf5 100644
--- a/chromium/components/services/leveldb/public/mojom/leveldb.mojom
+++ b/chromium/components/services/leveldb/public/mojom/leveldb.mojom
@@ -91,7 +91,8 @@ interface LevelDBService {
Open(filesystem.mojom.Directory directory,
string dbname,
mojo_base.mojom.MemoryAllocatorDumpCrossProcessUid? memory_dump_id,
- associated LevelDBDatabase& database) => (DatabaseError status);
+ pending_associated_receiver<LevelDBDatabase> database)
+ => (DatabaseError status);
// Open the database with the specified "name" in the specified "directory".
OpenWithOptions(OpenOptions options,
@@ -99,14 +100,16 @@ interface LevelDBService {
string dbname,
mojo_base.mojom.MemoryAllocatorDumpCrossProcessUid?
memory_dump_id,
- associated LevelDBDatabase& database) => (DatabaseError status);
+ pending_associated_receiver<LevelDBDatabase> database)
+ => (DatabaseError status);
// Opens a database stored purely in memory.
// "tracking_name" will be used for memory-infra reporting to associate memory
// use with its origin.
OpenInMemory(mojo_base.mojom.MemoryAllocatorDumpCrossProcessUid?
memory_dump_id, string tracking_name,
- associated LevelDBDatabase& database) => (DatabaseError status);
+ pending_associated_receiver<LevelDBDatabase> database)
+ => (DatabaseError status);
// Destroys the contents of the specified database. Returns OK if the database
// already didn't exist.
diff --git a/chromium/components/services/leveldb/remote_iterator_unittest.cc b/chromium/components/services/leveldb/remote_iterator_unittest.cc
index b8077f9419d..a53273331de 100644
--- a/chromium/components/services/leveldb/remote_iterator_unittest.cc
+++ b/chromium/components/services/leveldb/remote_iterator_unittest.cc
@@ -7,14 +7,15 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/services/leveldb/public/cpp/manifest.h"
+#include "base/task/post_task.h"
+#include "base/test/task_environment.h"
+#include "components/services/leveldb/leveldb_service_impl.h"
#include "components/services/leveldb/public/cpp/remote_iterator.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "components/services/leveldb/public/mojom/leveldb.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-#include "services/service_manager/public/cpp/test/test_service.h"
-#include "services/service_manager/public/cpp/test/test_service_manager.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace leveldb {
@@ -43,30 +44,22 @@ base::Callback<void(const base::UnguessableToken&)> CaptureToken(
quit_closure);
}
-const char kTestServiceName[] = "leveldb_service_unittests";
-
class RemoteIteratorTest : public testing::Test {
public:
RemoteIteratorTest()
- : test_service_manager_(
- {GetManifest(), service_manager::ManifestBuilder()
- .WithServiceName(kTestServiceName)
- .RequireCapability("leveldb", "leveldb:leveldb")
- .Build()}),
- test_service_(
- test_service_manager_.RegisterTestInstance(kTestServiceName)) {}
+ : leveldb_service_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+ leveldb_receiver_(&leveldb_service_,
+ leveldb_remote_.BindNewPipeAndPassReceiver()) {}
~RemoteIteratorTest() override = default;
protected:
- service_manager::Connector* connector() { return test_service_.connector(); }
-
void SetUp() override {
- connector()->BindInterface("leveldb", &leveldb_);
-
mojom::DatabaseError error;
base::RunLoop run_loop;
leveldb()->OpenInMemory(base::nullopt, "RemoteIteratorTest",
- MakeRequest(&database_),
+ database_.BindNewEndpointAndPassReceiver(),
Capture(&error, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(mojom::DatabaseError::OK, error);
@@ -86,16 +79,17 @@ class RemoteIteratorTest : public testing::Test {
}
}
- mojom::LevelDBServicePtr& leveldb() { return leveldb_; }
- mojom::LevelDBDatabaseAssociatedPtr& database() { return database_; }
+ mojo::Remote<mojom::LevelDBService>& leveldb() { return leveldb_remote_; }
+ mojo::AssociatedRemote<mojom::LevelDBDatabase>& database() {
+ return database_;
+ }
private:
- base::test::ScopedTaskEnvironment task_environment_;
- service_manager::TestServiceManager test_service_manager_;
- service_manager::TestService test_service_;
-
- mojom::LevelDBServicePtr leveldb_;
- mojom::LevelDBDatabaseAssociatedPtr database_;
+ base::test::TaskEnvironment task_environment_;
+ LevelDBServiceImpl leveldb_service_;
+ mojo::Remote<mojom::LevelDBService> leveldb_remote_;
+ mojo::Receiver<mojom::LevelDBService> leveldb_receiver_;
+ mojo::AssociatedRemote<mojom::LevelDBDatabase> database_;
DISALLOW_COPY_AND_ASSIGN(RemoteIteratorTest);
};
diff --git a/chromium/components/services/patch/BUILD.gn b/chromium/components/services/patch/BUILD.gn
index 68354ae4025..a7b67cf6652 100644
--- a/chromium/components/services/patch/BUILD.gn
+++ b/chromium/components/services/patch/BUILD.gn
@@ -6,8 +6,6 @@ source_set("lib") {
sources = [
"file_patcher_impl.cc",
"file_patcher_impl.h",
- "patch_service.cc",
- "patch_service.h",
]
deps = [
@@ -19,6 +17,25 @@ source_set("lib") {
public_deps = [
"//components/services/patch/public/mojom",
- "//services/service_manager/public/cpp",
+ ]
+}
+
+source_set("in_process") {
+ # NOTE: In-process file patching is unsafe! Unfortunately on iOS we have no
+ # other choice. On all other platforms, this target is restricted to tests.
+ testonly = !is_ios
+
+ sources = [
+ "in_process_file_patcher.cc",
+ "in_process_file_patcher.h",
+ ]
+
+ deps = [
+ ":lib",
+ ]
+
+ public_deps = [
+ "//components/services/patch/public/mojom",
+ "//mojo/public/cpp/bindings",
]
}
diff --git a/chromium/components/services/patch/DEPS b/chromium/components/services/patch/DEPS
index ea7209ad865..5b3aea17b0a 100644
--- a/chromium/components/services/patch/DEPS
+++ b/chromium/components/services/patch/DEPS
@@ -1,6 +1,5 @@
include_rules = [
"+components/update_client",
"+courgette",
- "+mojo", # By definition.
- "+services/service_manager/public", # Every service talks to Service Manager.
+ "+mojo/public",
]
diff --git a/chromium/components/services/patch/OWNERS b/chromium/components/services/patch/OWNERS
index ec81839d0ad..a761ba58ebb 100644
--- a/chromium/components/services/patch/OWNERS
+++ b/chromium/components/services/patch/OWNERS
@@ -1,2 +1,4 @@
sorin@chromium.org
waffles@chromium.org
+# COMPONENT: Internals>Services>ServiceManager
+# TEAM: chrome-updates-dev@chromium.org
diff --git a/chromium/components/services/patch/content/BUILD.gn b/chromium/components/services/patch/content/BUILD.gn
new file mode 100644
index 00000000000..a2331d18ad2
--- /dev/null
+++ b/chromium/components/services/patch/content/BUILD.gn
@@ -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.
+
+source_set("content") {
+ sources = [
+ "patch_service.cc",
+ "patch_service.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/strings",
+ "//content/public/browser",
+ ]
+
+ public_deps = [
+ "//components/services/patch/public/mojom",
+ "//mojo/public/cpp/bindings",
+ ]
+}
diff --git a/chromium/components/leveldb_proto/content/DEPS b/chromium/components/services/patch/content/DEPS
index 33af8ec77cf..1c35d9ca694 100644
--- a/chromium/components/leveldb_proto/content/DEPS
+++ b/chromium/components/services/patch/content/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+components/keyed_service/content",
"+content/public/browser",
-] \ No newline at end of file
+]
diff --git a/chromium/components/services/patch/content/patch_service.cc b/chromium/components/services/patch/content/patch_service.cc
new file mode 100644
index 00000000000..07f367061d7
--- /dev/null
+++ b/chromium/components/services/patch/content/patch_service.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 "components/services/patch/content/patch_service.h"
+
+#include "base/no_destructor.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/service_process_host.h"
+
+namespace patch {
+
+mojo::PendingRemote<mojom::FilePatcher> LaunchFilePatcher() {
+ mojo::PendingRemote<mojom::FilePatcher> remote;
+ content::ServiceProcessHost::Launch<mojom::FilePatcher>(
+ remote.InitWithNewPipeAndPassReceiver(),
+ content::ServiceProcessHost::Options()
+ .WithSandboxType(service_manager::SANDBOX_TYPE_UTILITY)
+ .WithDisplayName(IDS_PATCH_SERVICE_DISPLAY_NAME)
+ .Pass());
+ return remote;
+}
+
+} // namespace patch
diff --git a/chromium/components/services/patch/content/patch_service.h b/chromium/components/services/patch/content/patch_service.h
new file mode 100644
index 00000000000..5710c5622cf
--- /dev/null
+++ b/chromium/components/services/patch/content/patch_service.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 COMPONENTS_SERVICES_PATCH_CONTENT_PATCH_SERVICE_H_
+#define COMPONENTS_SERVICES_PATCH_CONTENT_PATCH_SERVICE_H_
+
+#include "base/callback.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+
+namespace patch {
+
+// Launches a new instance of the FilePatcher service in an isolated, sandboxed
+// process, and returns a remote interface to control the service. The lifetime
+// of the process is tied to that of the Remote. May be called from any thread.
+mojo::PendingRemote<mojom::FilePatcher> LaunchFilePatcher();
+
+} // namespace patch
+
+#endif // COMPONENTS_SERVICES_PATCH_CONTENT_PATCH_SERVICE_H_
diff --git a/chromium/components/services/patch/file_patcher_impl.cc b/chromium/components/services/patch/file_patcher_impl.cc
index 6c4d3dc49c6..1f0febce621 100644
--- a/chromium/components/services/patch/file_patcher_impl.cc
+++ b/chromium/components/services/patch/file_patcher_impl.cc
@@ -9,9 +9,11 @@
namespace patch {
+FilePatcherImpl::FilePatcherImpl() = default;
+
FilePatcherImpl::FilePatcherImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref)
- : service_ref_(std::move(service_ref)) {}
+ mojo::PendingReceiver<mojom::FilePatcher> receiver)
+ : receiver_(this, std::move(receiver)) {}
FilePatcherImpl::~FilePatcherImpl() = default;
diff --git a/chromium/components/services/patch/file_patcher_impl.h b/chromium/components/services/patch/file_patcher_impl.h
index daa49947281..5e4caeb2316 100644
--- a/chromium/components/services/patch/file_patcher_impl.h
+++ b/chromium/components/services/patch/file_patcher_impl.h
@@ -10,14 +10,20 @@
#include "base/files/file.h"
#include "base/macros.h"
#include "components/services/patch/public/mojom/file_patcher.mojom.h"
-#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
namespace patch {
class FilePatcherImpl : public mojom::FilePatcher {
public:
- explicit FilePatcherImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+ // This constructor assumes the FilePatcherImpl will be bound to an externally
+ // owned receiver, such as through |mojo::MakeSelfOwnedReceiver()|.
+ FilePatcherImpl();
+
+ // Constructs a FilePatcherImpl bound to |receiver|.
+ explicit FilePatcherImpl(mojo::PendingReceiver<mojom::FilePatcher> receiver);
+
~FilePatcherImpl() override;
private:
@@ -31,7 +37,7 @@ class FilePatcherImpl : public mojom::FilePatcher {
base::File output_file,
PatchFileCourgetteCallback callback) override;
- const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+ mojo::Receiver<mojom::FilePatcher> receiver_{this};
DISALLOW_COPY_AND_ASSIGN(FilePatcherImpl);
};
diff --git a/chromium/components/services/patch/in_process_file_patcher.cc b/chromium/components/services/patch/in_process_file_patcher.cc
new file mode 100644
index 00000000000..ea9c5c7444e
--- /dev/null
+++ b/chromium/components/services/patch/in_process_file_patcher.cc
@@ -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.
+
+#include "components/services/patch/in_process_file_patcher.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "components/services/patch/file_patcher_impl.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+
+namespace patch {
+
+namespace {
+
+void BindInProcessFilePatcher(
+ mojo::PendingReceiver<mojom::FilePatcher> receiver) {
+ mojo::MakeSelfOwnedReceiver(std::make_unique<FilePatcherImpl>(),
+ std::move(receiver));
+}
+
+} // namespace
+
+mojo::PendingRemote<mojom::FilePatcher> LaunchInProcessFilePatcher() {
+ mojo::PendingRemote<mojom::FilePatcher> remote;
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives()})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(&BindInProcessFilePatcher,
+ remote.InitWithNewPipeAndPassReceiver()));
+ return remote;
+}
+
+} // namespace patch
diff --git a/chromium/components/services/patch/in_process_file_patcher.h b/chromium/components/services/patch/in_process_file_patcher.h
new file mode 100644
index 00000000000..baea5a4f007
--- /dev/null
+++ b/chromium/components/services/patch/in_process_file_patcher.h
@@ -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.
+
+#ifndef COMPONENTS_SERVICES_PATCH_IN_PROCESS_FILE_PATCHER_H_
+#define COMPONENTS_SERVICES_PATCH_IN_PROCESS_FILE_PATCHER_H_
+
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+
+namespace patch {
+
+// Creates an in-process instance of the FilePatcher service on a background
+// sequence and returns a PendingRemote which can be bound to communicate with
+// the service. This should only be used for testing environments or other
+// runtimes where multiprocess is infeasible, such as iOS, or Content
+// dependencies are not allowed.
+mojo::PendingRemote<mojom::FilePatcher> LaunchInProcessFilePatcher();
+
+} // namespace patch
+
+#endif // COMPONENTS_SERVICES_PATCH_IN_PROCESS_FILE_PATCHER_H_
diff --git a/chromium/components/services/patch/patch_service.cc b/chromium/components/services/patch/patch_service.cc
deleted file mode 100644
index c51d70511ba..00000000000
--- a/chromium/components/services/patch/patch_service.cc
+++ /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.
-
-#include "components/services/patch/patch_service.h"
-
-#include "components/services/patch/file_patcher_impl.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace patch {
-
-PatchService::PatchService(service_manager::mojom::ServiceRequest request)
- : binding_(this, std::move(request)),
- keepalive_(&binding_, base::TimeDelta::FromSeconds(0)) {}
-
-PatchService::~PatchService() = default;
-
-void PatchService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- if (interface_name == patch::mojom::FilePatcher::Name_) {
- mojo::MakeStrongBinding(
- std::make_unique<FilePatcherImpl>(keepalive_.CreateRef()),
- patch::mojom::FilePatcherRequest(std::move(interface_pipe)));
- }
-}
-
-} // namespace patch
diff --git a/chromium/components/services/patch/patch_service.h b/chromium/components/services/patch/patch_service.h
deleted file mode 100644
index 00d7a520063..00000000000
--- a/chromium/components/services/patch/patch_service.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_PATCH_PATCH_SERVICE_H_
-#define COMPONENTS_SERVICES_PATCH_PATCH_SERVICE_H_
-
-#include "base/macros.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-
-namespace patch {
-
-class PatchService : public service_manager::Service {
- public:
- explicit PatchService(service_manager::mojom::ServiceRequest request);
- ~PatchService() override;
-
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- private:
- service_manager::ServiceBinding binding_;
- service_manager::ServiceKeepalive keepalive_;
-
- DISALLOW_COPY_AND_ASSIGN(PatchService);
-};
-
-} // namespace patch
-
-#endif // COMPONENTS_SERVICES_PATCH_PATCH_SERVICE_H_
diff --git a/chromium/components/services/patch/public/cpp/BUILD.gn b/chromium/components/services/patch/public/cpp/BUILD.gn
index 3d2081b8084..5dd93bb1b24 100644
--- a/chromium/components/services/patch/public/cpp/BUILD.gn
+++ b/chromium/components/services/patch/public/cpp/BUILD.gn
@@ -2,8 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//mojo/public/tools/bindings/mojom.gni")
-
source_set("cpp") {
sources = [
"patch.cc",
@@ -12,20 +10,6 @@ source_set("cpp") {
public_deps = [
"//components/services/patch/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/patch/public/mojom",
- "//components/strings",
- "//services/service_manager/public/cpp",
+ "//mojo/public/cpp/bindings",
]
}
diff --git a/chromium/components/services/patch/public/cpp/OWNERS b/chromium/components/services/patch/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/patch/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/patch/public/cpp/manifest.cc b/chromium/components/services/patch/public/cpp/manifest.cc
deleted file mode 100644
index dbdc813c66d..00000000000
--- a/chromium/components/services/patch/public/cpp/manifest.cc
+++ /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.
-
-#include "components/services/patch/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
-#include "components/services/patch/public/mojom/file_patcher.mojom.h"
-#include "components/strings/grit/components_strings.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace patch {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName(IDS_PATCH_SERVICE_DISPLAY_NAME)
- .WithOptions(
- service_manager::ManifestOptionsBuilder()
-#if !defined(OS_IOS)
- .WithExecutionMode(service_manager::Manifest::ExecutionMode::
- kOutOfProcessBuiltin)
-#endif // !defined(OS_IOS)
- .WithSandboxType("utility")
- .WithInstanceSharingPolicy(
- service_manager::Manifest::InstanceSharingPolicy::
- kSharedAcrossGroups)
- .Build())
- .ExposeCapability(
- "patch_file",
- service_manager::Manifest::InterfaceList<mojom::FilePatcher>())
-
- .Build()
- };
- return *manifest;
-}
-
-} // namespace patch
diff --git a/chromium/components/services/patch/public/cpp/manifest.h b/chromium/components/services/patch/public/cpp/manifest.h
deleted file mode 100644
index d476dc235c4..00000000000
--- a/chromium/components/services/patch/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_PATCH_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_PATCH_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace patch {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace patch
-
-#endif // COMPONENTS_SERVICES_PATCH_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/patch/public/cpp/patch.cc b/chromium/components/services/patch/public/cpp/patch.cc
index 8eaad8c6e8f..60c3a2f2774 100644
--- a/chromium/components/services/patch/public/cpp/patch.cc
+++ b/chromium/components/services/patch/public/cpp/patch.cc
@@ -15,10 +15,8 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string16.h"
#include "base/threading/sequenced_task_runner_handle.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
-#include "components/services/patch/public/mojom/file_patcher.mojom.h"
#include "components/update_client/component_patcher_operation.h" // nogncheck
-#include "services/service_manager/public/cpp/connector.h"
+#include "mojo/public/cpp/bindings/remote.h"
namespace patch {
@@ -26,11 +24,12 @@ namespace {
class PatchParams : public base::RefCounted<PatchParams> {
public:
- PatchParams(mojom::FilePatcherPtr file_patcher, PatchCallback callback)
+ PatchParams(mojo::PendingRemote<mojom::FilePatcher> file_patcher,
+ PatchCallback callback)
: file_patcher_(std::move(file_patcher)),
callback_(std::move(callback)) {}
- mojom::FilePatcherPtr* file_patcher() { return &file_patcher_; }
+ mojo::Remote<mojom::FilePatcher>& file_patcher() { return file_patcher_; }
PatchCallback TakeCallback() { return std::move(callback_); }
@@ -41,7 +40,7 @@ class PatchParams : public base::RefCounted<PatchParams> {
// The FilePatcherPtr is stored so it does not get deleted before the callback
// runs.
- mojom::FilePatcherPtr file_patcher_;
+ mojo::Remote<mojom::FilePatcher> file_patcher_;
PatchCallback callback_;
@@ -49,7 +48,7 @@ class PatchParams : public base::RefCounted<PatchParams> {
};
void PatchDone(scoped_refptr<PatchParams> params, int result) {
- params->file_patcher()->reset();
+ params->file_patcher().reset();
PatchCallback cb = params->TakeCallback();
if (!cb.is_null())
std::move(cb).Run(result);
@@ -57,7 +56,7 @@ void PatchDone(scoped_refptr<PatchParams> params, int result) {
} // namespace
-void Patch(service_manager::Connector* connector,
+void Patch(mojo::PendingRemote<mojom::FilePatcher> file_patcher,
const std::string& operation,
const base::FilePath& input_path,
const base::FilePath& patch_path,
@@ -80,28 +79,22 @@ void Patch(service_manager::Connector* connector,
return;
}
- mojom::FilePatcherPtr file_patcher;
- connector->BindInterface(mojom::kServiceName,
- mojo::MakeRequest(&file_patcher));
-
// In order to share |callback| between the connection error handler and the
// FilePatcher calls, we have to use a context object.
scoped_refptr<PatchParams> patch_params =
new PatchParams(std::move(file_patcher), std::move(callback));
- patch_params->file_patcher()->set_connection_error_handler(
+ patch_params->file_patcher().set_disconnect_handler(
base::BindOnce(&PatchDone, patch_params, /*result=*/-1));
if (operation == update_client::kBsdiff) {
- (*patch_params->file_patcher())
- ->PatchFileBsdiff(std::move(input_file), std::move(patch_file),
- std::move(output_file),
- base::BindOnce(&PatchDone, patch_params));
+ patch_params->file_patcher()->PatchFileBsdiff(
+ std::move(input_file), std::move(patch_file), std::move(output_file),
+ base::BindOnce(&PatchDone, patch_params));
} else if (operation == update_client::kCourgette) {
- (*patch_params->file_patcher())
- ->PatchFileCourgette(std::move(input_file), std::move(patch_file),
- std::move(output_file),
- base::BindOnce(&PatchDone, patch_params));
+ patch_params->file_patcher()->PatchFileCourgette(
+ std::move(input_file), std::move(patch_file), std::move(output_file),
+ base::BindOnce(&PatchDone, patch_params));
} else {
NOTREACHED();
}
diff --git a/chromium/components/services/patch/public/cpp/patch.h b/chromium/components/services/patch/public/cpp/patch.h
index 01137451262..94c0b1971b1 100644
--- a/chromium/components/services/patch/public/cpp/patch.h
+++ b/chromium/components/services/patch/public/cpp/patch.h
@@ -8,21 +8,19 @@
#include <string>
#include "base/callback_forward.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
namespace base {
class FilePath;
}
-namespace service_manager {
-class Connector;
-}
-
namespace patch {
// Patches |input_abs_path| with |patch_abs_path| using the |operation|
// algorithm and place the output in |output_abs_path|.
using PatchCallback = base::OnceCallback<void(int result)>;
-void Patch(service_manager::Connector* connector,
+void Patch(mojo::PendingRemote<mojom::FilePatcher> file_patcher,
const std::string& operation,
const base::FilePath& input_abs_path,
const base::FilePath& patch_abs_path,
diff --git a/chromium/components/services/patch/public/mojom/BUILD.gn b/chromium/components/services/patch/public/mojom/BUILD.gn
index 6e4f869f7f9..b6b49df46fc 100644
--- a/chromium/components/services/patch/public/mojom/BUILD.gn
+++ b/chromium/components/services/patch/public/mojom/BUILD.gn
@@ -10,13 +10,6 @@ mojom("mojom") {
]
public_deps = [
- ":constants",
"//mojo/public/mojom/base",
]
}
-
-mojom("constants") {
- sources = [
- "constants.mojom",
- ]
-}
diff --git a/chromium/components/services/patch/public/mojom/constants.mojom b/chromium/components/services/patch/public/mojom/constants.mojom
deleted file mode 100644
index fa5ad3c7f5e..00000000000
--- a/chromium/components/services/patch/public/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +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.
-
-module patch.mojom;
-
-const string kServiceName = "patch_service";
diff --git a/chromium/components/services/pdf_compositor/BUILD.gn b/chromium/components/services/pdf_compositor/BUILD.gn
index 55e7b178307..ccc4858e0ef 100644
--- a/chromium/components/services/pdf_compositor/BUILD.gn
+++ b/chromium/components/services/pdf_compositor/BUILD.gn
@@ -8,8 +8,6 @@ static_library("pdf_compositor") {
sources = [
"pdf_compositor_impl.cc",
"pdf_compositor_impl.h",
- "pdf_compositor_service.cc",
- "pdf_compositor_service.h",
]
deps = [
@@ -17,17 +15,19 @@ static_library("pdf_compositor") {
"//components/crash/core/common:crash_key",
"//components/discardable_memory/client",
"//components/discardable_memory/public/mojom",
- "//content/public/child",
- "//content/public/common:service_names",
+ "//components/services/pdf_compositor/public/cpp",
"//content/public/utility",
"//printing/common",
"//skia",
"//third_party/blink/public:blink_headers",
]
+ if (is_win) {
+ deps += [ "//content/public/child" ]
+ }
+
public_deps = [
"//components/services/pdf_compositor/public/mojom",
- "//services/service_manager/public/cpp",
]
}
@@ -36,7 +36,6 @@ if (enable_basic_printing) {
testonly = true
sources = [
"pdf_compositor_impl_unittest.cc",
- "pdf_compositor_service_unittest.cc",
]
include_dirs = [
@@ -51,8 +50,8 @@ if (enable_basic_printing) {
"//base/test:test_support",
"//cc/paint:paint",
"//components/crash/core/common:crash_key",
+ "//components/services/pdf_compositor/public/cpp",
"//components/services/pdf_compositor/public/mojom",
- "//services/service_manager/public/cpp/test:test_support",
"//skia",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/services/pdf_compositor/DEPS b/chromium/components/services/pdf_compositor/DEPS
index 1f84ab9708c..3dec59eb9f2 100644
--- a/chromium/components/services/pdf_compositor/DEPS
+++ b/chromium/components/services/pdf_compositor/DEPS
@@ -7,8 +7,6 @@ include_rules = [
"+content/public/utility",
"+mojo/public/cpp",
"+printing/common",
- "+services/service_manager/public/cpp",
- "+services/service_manager/public/mojom",
"+skia",
"+third_party/skia",
"+third_party/blink/public/platform", # Test web sandbox support.
diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_impl.cc b/chromium/components/services/pdf_compositor/pdf_compositor_impl.cc
index d7ea512ad9f..b4fd83e3e2c 100644
--- a/chromium/components/services/pdf_compositor/pdf_compositor_impl.cc
+++ b/chromium/components/services/pdf_compositor/pdf_compositor_impl.cc
@@ -9,24 +9,90 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/discardable_memory.h"
+#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
+#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
+#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
+#include "content/public/utility/utility_thread.h"
#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "printing/common/metafile_utils.h"
+#include "third_party/blink/public/platform/web_image_generator.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDocument.h"
+#include "third_party/skia/include/core/SkGraphics.h"
#include "third_party/skia/include/core/SkSerialProcs.h"
#include "third_party/skia/src/utils/SkMultiPictureDocument.h"
+#if defined(OS_WIN)
+#include "content/public/child/dwrite_font_proxy_init_win.h"
+#elif defined(OS_MACOSX)
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
+#include "third_party/blink/public/platform/platform.h"
+#endif
+
namespace printing {
PdfCompositorImpl::PdfCompositorImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref)
- : service_ref_(std::move(service_ref)) {}
+ mojo::PendingReceiver<mojom::PdfCompositor> receiver,
+ bool initialize_environment,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+ : io_task_runner_(std::move(io_task_runner)) {
+ if (receiver)
+ receiver_.Bind(std::move(receiver));
+
+#if defined(OS_WIN)
+ // Initialize direct write font proxy so skia can use it.
+ content::InitializeDWriteFontProxy();
+#endif
+
+ // Hook up blink's codecs so skia can call them.
+ SkGraphics::SetImageGeneratorFromEncodedDataFactory(
+ blink::WebImageGenerator::CreateAsSkImageGenerator);
+
+ if (!initialize_environment)
+ return;
+
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+ content::UtilityThread::Get()->EnsureBlinkInitializedWithSandboxSupport();
+ // Check that we have sandbox support on this platform.
+ DCHECK(blink::Platform::Current()->GetSandboxSupport());
+#else
+ content::UtilityThread::Get()->EnsureBlinkInitialized();
+#endif
+
+#if defined(OS_MACOSX)
+ // Check that font access is granted.
+ // This doesn't do comprehensive tests to make sure fonts can work properly.
+ // It is just a quick and simple check to catch things like improper sandbox
+ // policy setup.
+ DCHECK(SkFontMgr::RefDefault()->countFamilies());
+#endif
+}
-PdfCompositorImpl::~PdfCompositorImpl() = default;
+PdfCompositorImpl::~PdfCompositorImpl() {
+#if defined(OS_WIN)
+ content::UninitializeDWriteFontProxy();
+#endif
+}
+
+void PdfCompositorImpl::SetDiscardableSharedMemoryManager(
+ mojo::PendingRemote<
+ discardable_memory::mojom::DiscardableSharedMemoryManager> manager) {
+ // Set up discardable memory manager.
+ discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr(
+ std::move(manager));
+ discardable_shared_memory_manager_ = std::make_unique<
+ discardable_memory::ClientDiscardableSharedMemoryManager>(
+ std::move(manager_ptr), io_task_runner_);
+ base::DiscardableMemoryAllocator::SetInstance(
+ discardable_shared_memory_manager_.get());
+}
void PdfCompositorImpl::NotifyUnavailableSubframe(uint64_t frame_guid) {
// Add this frame into the map.
diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_impl.h b/chromium/components/services/pdf_compositor/pdf_compositor_impl.h
index 3b7aa4b3efa..84f40a751f9 100644
--- a/chromium/components/services/pdf_compositor/pdf_compositor_impl.h
+++ b/chromium/components/services/pdf_compositor/pdf_compositor_impl.h
@@ -15,22 +15,43 @@
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
-#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRefCnt.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace discardable_memory {
+class ClientDiscardableSharedMemoryManager;
+}
+
namespace printing {
class PdfCompositorImpl : public mojom::PdfCompositor {
public:
- explicit PdfCompositorImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+ // Creates an instance with an optional Mojo receiver (may be null) and
+ // optional initialization of the runtime environment necessary for
+ // compositing operations. |io_task_runner| is used for shared memory
+ // management, if and only if |SetDiscardableSharedMemoryManager()| is
+ // eventually called, which may not be the case in unit tests. In practice,
+ // |initialize_environment| is only false in unit tests.
+ PdfCompositorImpl(mojo::PendingReceiver<mojom::PdfCompositor> receiver,
+ bool initialize_environment,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~PdfCompositorImpl() override;
// mojom::PdfCompositor
+ void SetDiscardableSharedMemoryManager(
+ mojo::PendingRemote<
+ discardable_memory::mojom::DiscardableSharedMemoryManager> manager)
+ override;
void NotifyUnavailableSubframe(uint64_t frame_guid) override;
void AddSubframeContent(
uint64_t frame_guid,
@@ -159,9 +180,13 @@ class PdfCompositorImpl : public mojom::PdfCompositor {
DeserializationContext GetDeserializationContext(
const ContentToFrameMap& subframe_content_map);
- const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
- // The creator of this service.
+ mojo::Receiver<mojom::PdfCompositor> receiver_{this};
+ const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
+ discardable_shared_memory_manager_;
+
+ // The creator of this service.
// Currently contains the service creator's user agent string if given,
// otherwise just use string "Chromium".
std::string creator_ = "Chromium";
diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc b/chromium/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc
index 7f52160ac73..e8de49d74f5 100644
--- a/chromium/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc
+++ b/chromium/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/crash/core/common/crash_key.h"
#include "components/services/pdf_compositor/pdf_compositor_impl.h"
#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
@@ -24,8 +24,11 @@ struct TestRequestData {
class MockPdfCompositorImpl : public PdfCompositorImpl {
public:
- MockPdfCompositorImpl() : PdfCompositorImpl(nullptr) {}
- ~MockPdfCompositorImpl() override {}
+ MockPdfCompositorImpl()
+ : PdfCompositorImpl(mojo::NullReceiver(),
+ false /* initialize_environment */,
+ nullptr /* io_task_runner */) {}
+ ~MockPdfCompositorImpl() override = default;
MOCK_METHOD2(OnFulfillRequest, void(uint64_t, int));
@@ -41,8 +44,7 @@ class MockPdfCompositorImpl : public PdfCompositorImpl {
class PdfCompositorImplTest : public testing::Test {
public:
PdfCompositorImplTest()
- : task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
run_loop_(std::make_unique<base::RunLoop>()),
is_ready_(false) {}
@@ -74,7 +76,7 @@ class PdfCompositorImplTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<base::RunLoop> run_loop_;
bool is_ready_;
};
@@ -96,7 +98,9 @@ class PdfCompositorImplCrashKeyTest : public PdfCompositorImplTest {
};
TEST_F(PdfCompositorImplTest, IsReadyToComposite) {
- PdfCompositorImpl impl(nullptr);
+ PdfCompositorImpl impl(mojo::NullReceiver(),
+ false /* initialize_environment */,
+ nullptr /* io_task_runner */);
// Frame 2 and 3 are painted.
impl.AddSubframeContent(2, CreateTestData(2, -1), ContentToFrameMap());
impl.AddSubframeContent(3, CreateTestData(3, -1), ContentToFrameMap());
@@ -132,7 +136,9 @@ TEST_F(PdfCompositorImplTest, IsReadyToComposite) {
}
TEST_F(PdfCompositorImplTest, MultiLayerDependency) {
- PdfCompositorImpl impl(nullptr);
+ PdfCompositorImpl impl(mojo::NullReceiver(),
+ false /* initialize_environment */,
+ nullptr /* io_task_runner */);
// Frame 3 has content 1 which refers to subframe 1.
ContentToFrameMap subframe_content_map = {{1, 1}};
impl.AddSubframeContent(3, CreateTestData(3, -1), subframe_content_map);
@@ -172,7 +178,9 @@ TEST_F(PdfCompositorImplTest, MultiLayerDependency) {
}
TEST_F(PdfCompositorImplTest, DependencyLoop) {
- PdfCompositorImpl impl(nullptr);
+ PdfCompositorImpl impl(mojo::NullReceiver(),
+ false /* initialize_environment */,
+ nullptr /* io_task_runner */);
// Frame 3 has content 1, which refers to frame 1.
// Frame 1 has content 3, which refers to frame 3.
ContentToFrameMap subframe_content_map = {{3, 3}};
@@ -305,7 +313,9 @@ TEST_F(PdfCompositorImplTest, NotifyUnavailableSubframe) {
}
TEST_F(PdfCompositorImplCrashKeyTest, SetCrashKey) {
- PdfCompositorImpl impl(nullptr);
+ PdfCompositorImpl impl(mojo::NullReceiver(),
+ false /* initialize_environment */,
+ nullptr /* io_task_runner */);
std::string url_str("https://www.example.com/");
GURL url(url_str);
impl.SetWebContentsURL(url);
diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_service.cc b/chromium/components/services/pdf_compositor/pdf_compositor_service.cc
deleted file mode 100644
index 96e6202e4a4..00000000000
--- a/chromium/components/services/pdf_compositor/pdf_compositor_service.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/services/pdf_compositor/pdf_compositor_service.h"
-
-#include <utility>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/memory/discardable_memory.h"
-#include "build/build_config.h"
-#include "components/services/pdf_compositor/pdf_compositor_impl.h"
-#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
-#include "content/public/common/service_names.mojom.h"
-#include "content/public/utility/utility_thread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-#if defined(OS_WIN)
-#include "content/public/child/dwrite_font_proxy_init_win.h"
-#elif defined(OS_MACOSX)
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/skia/include/core/SkFontMgr.h"
-#elif defined(OS_POSIX) && !defined(OS_ANDROID)
-#include "third_party/blink/public/platform/platform.h"
-#endif
-
-namespace {
-
-void OnPdfCompositorRequest(service_manager::ServiceKeepalive* keepalive,
- printing::mojom::PdfCompositorRequest request) {
- mojo::MakeStrongBinding(
- std::make_unique<printing::PdfCompositorImpl>(keepalive->CreateRef()),
- std::move(request));
-}
-
-} // namespace
-
-namespace printing {
-
-PdfCompositorService::PdfCompositorService(
- service_manager::mojom::ServiceRequest request)
- : binding_(this, std::move(request)),
- keepalive_(&binding_, base::TimeDelta{}) {}
-
-PdfCompositorService::~PdfCompositorService() {
-#if defined(OS_WIN)
- content::UninitializeDWriteFontProxy();
-#endif
-}
-
-// static
-std::unique_ptr<service_manager::Service> PdfCompositorService::Create(
- service_manager::mojom::ServiceRequest request) {
-#if defined(OS_WIN)
- // Initialize direct write font proxy so skia can use it.
- content::InitializeDWriteFontProxy();
-#endif
- return std::make_unique<printing::PdfCompositorService>(std::move(request));
-}
-
-void PdfCompositorService::OnStart() {
- registry_.AddInterface(
- base::BindRepeating(&OnPdfCompositorRequest, &keepalive_));
-
- if (skip_initialization_for_testing_)
- return;
-
- // Set up discardable memory manager.
- discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr;
- binding_.GetConnector()->BindInterface(content::mojom::kSystemServiceName,
- &manager_ptr);
- discardable_shared_memory_manager_ = std::make_unique<
- discardable_memory::ClientDiscardableSharedMemoryManager>(
- std::move(manager_ptr), content::UtilityThread::Get()->GetIOTaskRunner());
- DCHECK(discardable_shared_memory_manager_);
- base::DiscardableMemoryAllocator::SetInstance(
- discardable_shared_memory_manager_.get());
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
- // Check that we have sandbox support on this platform.
- DCHECK(blink::Platform::Current()->GetSandboxSupport());
-#endif
-
-#if defined(OS_MACOSX)
- // Check that font access is granted.
- // This doesn't do comprehensive tests to make sure fonts can work properly.
- // It is just a quick and simple check to catch things like improper sandbox
- // policy setup.
- DCHECK(SkFontMgr::RefDefault()->countFamilies());
-#endif
-}
-
-void PdfCompositorService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
-}
-
-} // namespace printing
diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_service.h b/chromium/components/services/pdf_compositor/pdf_compositor_service.h
deleted file mode 100644
index 28fda4a0484..00000000000
--- a/chromium/components/services/pdf_compositor/pdf_compositor_service.h
+++ /dev/null
@@ -1,55 +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 COMPONENTS_SERVICES_PDF_COMPOSITOR_PDF_COMPOSITOR_SERVICE_H_
-#define COMPONENTS_SERVICES_PDF_COMPOSITOR_PDF_COMPOSITOR_SERVICE_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
-#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-
-namespace printing {
-
-class PdfCompositorService : public service_manager::Service {
- public:
- explicit PdfCompositorService(service_manager::mojom::ServiceRequest request);
- ~PdfCompositorService() override;
-
- // Factory function for use as an embedded service.
- static std::unique_ptr<service_manager::Service> Create(
- service_manager::mojom::ServiceRequest request);
-
- // service_manager::Service:
- void OnStart() override;
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- void set_skip_initialization_for_testing(bool skip) {
- skip_initialization_for_testing_ = skip;
- }
-
- private:
- service_manager::ServiceBinding binding_;
- service_manager::ServiceKeepalive keepalive_;
- bool skip_initialization_for_testing_ = false;
- std::unique_ptr<discardable_memory::ClientDiscardableSharedMemoryManager>
- discardable_shared_memory_manager_;
- service_manager::BinderRegistry registry_;
- base::WeakPtrFactory<PdfCompositorService> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PdfCompositorService);
-};
-
-} // namespace printing
-
-#endif // COMPONENTS_SERVICES_PDF_COMPOSITOR_PDF_COMPOSITOR_SERVICE_H_
diff --git a/chromium/components/services/pdf_compositor/pdf_compositor_service_unittest.cc b/chromium/components/services/pdf_compositor/pdf_compositor_service_unittest.cc
deleted file mode 100644
index 2e459d56e9b..00000000000
--- a/chromium/components/services/pdf_compositor/pdf_compositor_service_unittest.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/memory/read_only_shared_memory_region.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/test_discardable_memory_allocator.h"
-#include "cc/paint/paint_flags.h"
-#include "cc/paint/skia_paint_canvas.h"
-#include "components/services/pdf_compositor/pdf_compositor_service.h"
-#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
-#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkStream.h"
-#include "third_party/skia/src/utils/SkMultiPictureDocument.h"
-
-namespace printing {
-
-class PdfCompositorServiceTest : public testing::Test {
- public:
- PdfCompositorServiceTest()
- : connector_(test_connector_factory_.CreateConnector()),
- service_(
- test_connector_factory_.RegisterInstance(mojom::kServiceName)) {
- // We don't want the service instance setting up its own discardable memory
- // allocator, which it normally does. Instead it will use the one provided
- // by our fixture in |SetUp()| below.
- service_.set_skip_initialization_for_testing(true);
- }
-
- ~PdfCompositorServiceTest() override = default;
-
- MOCK_METHOD1(CallbackOnCompositeSuccess,
- void(const base::ReadOnlySharedMemoryRegion&));
- MOCK_METHOD1(CallbackOnCompositeStatus, void(mojom::PdfCompositor::Status));
-
- void OnCompositeToPdfCallback(mojom::PdfCompositor::Status status,
- base::ReadOnlySharedMemoryRegion region) {
- if (status == mojom::PdfCompositor::Status::kSuccess)
- CallbackOnCompositeSuccess(region);
- else
- CallbackOnCompositeStatus(status);
- run_loop_->Quit();
- }
-
- MOCK_METHOD0(ConnectionClosed, void());
-
- protected:
- service_manager::Connector* connector() { return connector_.get(); }
-
- void SetUp() override {
- base::DiscardableMemoryAllocator::SetInstance(
- &discardable_memory_allocator_);
-
- ASSERT_FALSE(compositor_);
- connector()->BindInterface(mojom::kServiceName, &compositor_);
- ASSERT_TRUE(compositor_);
-
- run_loop_ = std::make_unique<base::RunLoop>();
- }
-
- void TearDown() override {
- compositor_.reset();
- base::DiscardableMemoryAllocator::SetInstance(nullptr);
- }
-
- base::ReadOnlySharedMemoryRegion CreateMSKP() {
- SkDynamicMemoryWStream stream;
- sk_sp<SkDocument> doc = SkMakeMultiPictureDocument(&stream);
- cc::SkiaPaintCanvas canvas(doc->beginPage(800, 600));
- SkRect rect = SkRect::MakeXYWH(10, 10, 250, 250);
- cc::PaintFlags flags;
- flags.setAntiAlias(false);
- flags.setColor(SK_ColorRED);
- flags.setStyle(cc::PaintFlags::kFill_Style);
- canvas.drawRect(rect, flags);
- doc->endPage();
- doc->close();
-
- size_t len = stream.bytesWritten();
- base::MappedReadOnlyRegion memory =
- base::ReadOnlySharedMemoryRegion::Create(len);
- CHECK(memory.IsValid());
- stream.copyTo(memory.mapping.memory());
- return std::move(memory.region);
- }
-
- void CallCompositorWithSuccess(mojom::PdfCompositorPtr ptr) {
- static constexpr uint64_t kFrameGuid = 1234;
- auto handle = CreateMSKP();
- ASSERT_TRUE(handle.IsValid());
- EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(1);
- ptr->CompositeDocumentToPdf(
- kFrameGuid, std::move(handle), ContentToFrameMap(),
- base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
- base::Unretained(this)));
- run_loop_->Run();
- }
-
- base::test::ScopedTaskEnvironment task_environment_;
- std::unique_ptr<base::RunLoop> run_loop_;
- mojom::PdfCompositorPtr compositor_;
- base::TestDiscardableMemoryAllocator discardable_memory_allocator_;
-
- private:
- service_manager::TestConnectorFactory test_connector_factory_;
- std::unique_ptr<service_manager::Connector> connector_;
- PdfCompositorService service_;
-
- DISALLOW_COPY_AND_ASSIGN(PdfCompositorServiceTest);
-};
-
-// Test callback function is called on error conditions in service.
-TEST_F(PdfCompositorServiceTest, InvokeCallbackOnContentError) {
- auto serialized_content = base::ReadOnlySharedMemoryRegion::Create(10);
-
- EXPECT_CALL(*this, CallbackOnCompositeStatus(
- mojom::PdfCompositor::Status::kContentFormatError))
- .Times(1);
- compositor_->CompositeDocumentToPdf(
- 5u, std::move(serialized_content.region), ContentToFrameMap(),
- base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
- base::Unretained(this)));
- run_loop_->Run();
-}
-
-// Test callback function is called upon success.
-TEST_F(PdfCompositorServiceTest, InvokeCallbackOnSuccess) {
- CallCompositorWithSuccess(std::move(compositor_));
-}
-
-// Test coexistence of multiple PdfCompositor interface bindings.
-TEST_F(PdfCompositorServiceTest, MultipleCompositors) {
- // One service can bind multiple interfaces.
- mojom::PdfCompositorPtr another_compositor;
- ASSERT_FALSE(another_compositor);
- connector()->BindInterface(mojom::kServiceName, &another_compositor);
- ASSERT_TRUE(another_compositor);
- ASSERT_NE(compositor_.get(), another_compositor.get());
-
- // Terminating one interface won't affect another.
- compositor_.reset();
- CallCompositorWithSuccess(std::move(another_compositor));
-}
-
-// Test data structures and content of multiple PdfCompositor interface bindings
-// are independent from each other.
-TEST_F(PdfCompositorServiceTest, IndependentCompositors) {
- // Create a new connection 2.
- mojom::PdfCompositorPtr compositor2;
- ASSERT_FALSE(compositor2);
- connector()->BindInterface(mojom::kServiceName, &compositor2);
- ASSERT_TRUE(compositor2);
-
- // In original connection, add frame 4 with content 2 referring
- // to subframe 1.
- compositor_->AddSubframeContent(1u, CreateMSKP(), ContentToFrameMap());
-
- // Original connection can use this subframe 1.
- EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(1);
- ContentToFrameMap subframe_content_map;
- subframe_content_map[2u] = 1u;
-
- compositor_->CompositeDocumentToPdf(
- 4u, CreateMSKP(), std::move(subframe_content_map),
- base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
- base::Unretained(this)));
- run_loop_->Run();
- testing::Mock::VerifyAndClearExpectations(this);
-
- // Connection 2 doesn't know about subframe 1.
- subframe_content_map.clear();
- subframe_content_map[2u] = 1u;
- EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(0);
- compositor2->CompositeDocumentToPdf(
- 4u, CreateMSKP(), std::move(subframe_content_map),
- base::BindOnce(&PdfCompositorServiceTest::OnCompositeToPdfCallback,
- base::Unretained(this)));
- testing::Mock::VerifyAndClearExpectations(this);
-
- // Add info about subframe 1 to connection 2 so it can use it.
- EXPECT_CALL(*this, CallbackOnCompositeSuccess(testing::_)).Times(1);
- // Add subframe 1's content.
- // Now all content needed for previous request is ready.
- compositor2->AddSubframeContent(1u, CreateMSKP(), ContentToFrameMap());
- run_loop_ = std::make_unique<base::RunLoop>();
- run_loop_->Run();
-}
-
-} // namespace printing
diff --git a/chromium/components/services/pdf_compositor/public/cpp/BUILD.gn b/chromium/components/services/pdf_compositor/public/cpp/BUILD.gn
index 6af5d249bb0..799b9eca87a 100644
--- a/chromium/components/services/pdf_compositor/public/cpp/BUILD.gn
+++ b/chromium/components/services/pdf_compositor/public/cpp/BUILD.gn
@@ -2,36 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//mojo/public/tools/bindings/mojom.gni")
-
-source_set("factory") {
+source_set("cpp") {
sources = [
- "pdf_compositor_service_factory.cc",
- "pdf_compositor_service_factory.h",
- ]
-
- deps = [
- "//components/services/pdf_compositor/",
- "//content/public/common",
- "//content/public/utility",
+ "pdf_service_mojo_types.h",
]
public_deps = [
- "//components/services/pdf_compositor/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
"//base",
- "//components/services/pdf_compositor/public/mojom",
- "//components/strings",
- "//services/service_manager/public/cpp",
]
}
diff --git a/chromium/components/services/pdf_compositor/public/cpp/OWNERS b/chromium/components/services/pdf_compositor/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/pdf_compositor/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/pdf_compositor/public/cpp/manifest.cc b/chromium/components/services/pdf_compositor/public/cpp/manifest.cc
deleted file mode 100644
index ee6ebc04abb..00000000000
--- a/chromium/components/services/pdf_compositor/public/cpp/manifest.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 "components/services/pdf_compositor/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
-#include "components/strings/grit/components_strings.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace printing {
-
-const service_manager::Manifest& GetPdfCompositorManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName(IDS_PDF_COMPOSITOR_SERVICE_DISPLAY_NAME)
- .WithOptions(
- service_manager::ManifestOptionsBuilder()
- .WithExecutionMode(service_manager::Manifest::ExecutionMode::
- kOutOfProcessBuiltin)
- .WithSandboxType("pdf_compositor")
- .WithInstanceSharingPolicy(
- service_manager::Manifest::InstanceSharingPolicy::
- kSharedAcrossGroups)
- .Build())
- .ExposeCapability(
- "compositor",
- service_manager::Manifest::InterfaceList<mojom::PdfCompositor>())
- .RequireCapability("content_system", "app")
- .RequireCapability("content_system", "sandbox_support")
- .RequireCapability("ui", "discardable_memory")
- .Build()};
- return *manifest;
-}
-
-} // namespace printing
diff --git a/chromium/components/services/pdf_compositor/public/cpp/manifest.h b/chromium/components/services/pdf_compositor/public/cpp/manifest.h
deleted file mode 100644
index 52b57fcbc5d..00000000000
--- a/chromium/components/services/pdf_compositor/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace printing {
-
-const service_manager::Manifest& GetPdfCompositorManifest();
-
-} // namespace printing
-
-#endif // COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc b/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc
deleted file mode 100644
index d74c5bff4d8..00000000000
--- a/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h"
-
-#include "build/build_config.h"
-#include "components/services/pdf_compositor/pdf_compositor_service.h"
-#include "content/public/utility/utility_thread.h"
-#include "third_party/blink/public/platform/web_image_generator.h"
-#include "third_party/skia/include/core/SkGraphics.h"
-
-namespace printing {
-
-std::unique_ptr<service_manager::Service> CreatePdfCompositorService(
- service_manager::mojom::ServiceRequest request) {
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
- content::UtilityThread::Get()->EnsureBlinkInitializedWithSandboxSupport();
-#else
- content::UtilityThread::Get()->EnsureBlinkInitialized();
-#endif
- // Hook up blink's codecs so skia can call them.
- SkGraphics::SetImageGeneratorFromEncodedDataFactory(
- blink::WebImageGenerator::CreateAsSkImageGenerator);
- return printing::PdfCompositorService::Create(std::move(request));
-}
-
-} // namespace printing
diff --git a/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h b/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h
deleted file mode 100644
index 61400738273..00000000000
--- a/chromium/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_PDF_COMPOSITOR_SERVICE_FACTORY_H_
-#define COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_PDF_COMPOSITOR_SERVICE_FACTORY_H_
-
-#include <memory>
-#include <string>
-
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
-
-namespace printing {
-
-std::unique_ptr<service_manager::Service> CreatePdfCompositorService(
- service_manager::mojom::ServiceRequest request);
-
-} // namespace printing
-
-#endif // COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_PDF_COMPOSITOR_SERVICE_FACTORY_H_
diff --git a/chromium/components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h b/chromium/components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h
index dfc3b5f8e15..80acce93cec 100644
--- a/chromium/components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h
+++ b/chromium/components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_PDF_SERVICE_MOJO_TYPES_H_
#define COMPONENTS_SERVICES_PDF_COMPOSITOR_PUBLIC_CPP_PDF_SERVICE_MOJO_TYPES_H_
+#include <stdint.h>
+
#include "base/containers/flat_map.h"
namespace printing {
diff --git a/chromium/components/services/pdf_compositor/public/mojom/BUILD.gn b/chromium/components/services/pdf_compositor/public/mojom/BUILD.gn
index 75d1a926c86..901dfb94fba 100644
--- a/chromium/components/services/pdf_compositor/public/mojom/BUILD.gn
+++ b/chromium/components/services/pdf_compositor/public/mojom/BUILD.gn
@@ -9,6 +9,7 @@ mojom("mojom") {
"pdf_compositor.mojom",
]
public_deps = [
+ "//components/discardable_memory/public/mojom",
"//mojo/public/mojom/base",
"//url/mojom:url_mojom_gurl",
]
diff --git a/chromium/components/services/pdf_compositor/public/mojom/pdf_compositor.mojom b/chromium/components/services/pdf_compositor/public/mojom/pdf_compositor.mojom
index f788a459d60..3e3f40eca10 100644
--- a/chromium/components/services/pdf_compositor/public/mojom/pdf_compositor.mojom
+++ b/chromium/components/services/pdf_compositor/public/mojom/pdf_compositor.mojom
@@ -4,11 +4,10 @@
module printing.mojom;
+import "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom";
import "mojo/public/mojom/base/shared_memory.mojom";
import "url/mojom/url.mojom";
-const string kServiceName = "pdf_compositor";
-
interface PdfCompositor {
// The status of composition and conversion execution.
// These values are persisted to logs. Entries should not be renumbered and
@@ -20,6 +19,13 @@ interface PdfCompositor {
kCompositingFailure = 3,
};
+ // Provides an interface for managing discardable shared memory regions. Must
+ // be called before other methods on this interface if performing compositing
+ // operations.
+ SetDiscardableSharedMemoryManager(
+ pending_remote<discardable_memory.mojom.DiscardableSharedMemoryManager>
+ manager);
+
// Notifies that a subframe is unavailable, such as the render frame process
// hosting it crashed or terminated. The subframe will be composited with no
// content in the composited result.
diff --git a/chromium/components/services/quarantine/BUILD.gn b/chromium/components/services/quarantine/BUILD.gn
index 1fe5d0f2a68..47d1c6d4923 100644
--- a/chromium/components/services/quarantine/BUILD.gn
+++ b/chromium/components/services/quarantine/BUILD.gn
@@ -15,8 +15,6 @@ static_library("quarantine") {
"quarantine_impl.cc",
"quarantine_impl.h",
"quarantine_mac.mm",
- "quarantine_service.cc",
- "quarantine_service.h",
"quarantine_win.cc",
]
@@ -28,7 +26,6 @@ static_library("quarantine") {
":common",
"//base",
"//net",
- "//services/service_manager/public/cpp",
"//url",
]
@@ -118,8 +115,6 @@ source_set("unit_tests") {
"//base/test:test_support",
"//components/services/quarantine/public/mojom",
"//net",
- "//services/service_manager/public/cpp:cpp",
- "//services/service_manager/public/cpp/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//url",
diff --git a/chromium/components/services/quarantine/public/cpp/BUILD.gn b/chromium/components/services/quarantine/public/cpp/BUILD.gn
index 7c7e3877628..d0bb7256ead 100644
--- a/chromium/components/services/quarantine/public/cpp/BUILD.gn
+++ b/chromium/components/services/quarantine/public/cpp/BUILD.gn
@@ -4,23 +4,6 @@
import("//mojo/public/tools/bindings/mojom.gni")
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/quarantine/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-
- if (is_win) {
- deps += [ ":features" ]
- }
-}
-
if (is_win) {
source_set("features") {
sources = [
diff --git a/chromium/components/services/quarantine/public/cpp/OWNERS b/chromium/components/services/quarantine/public/cpp/OWNERS
deleted file mode 100644
index dad81cc1bad..00000000000
--- a/chromium/components/services/quarantine/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/quarantine/public/cpp/manifest.cc b/chromium/components/services/quarantine/public/cpp/manifest.cc
deleted file mode 100644
index cd8fb0bc508..00000000000
--- a/chromium/components/services/quarantine/public/cpp/manifest.cc
+++ /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.
-
-#include "components/services/quarantine/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
-#include "services/service_manager/public/cpp/manifest.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-#if defined(OS_WIN)
-#include "components/services/quarantine/public/cpp/quarantine_features_win.h"
-#endif
-
-namespace quarantine {
-
-service_manager::Manifest::ExecutionMode GetExecutionMode() {
-#if defined(OS_WIN)
- if (base::FeatureList::IsEnabled(quarantine::kOutOfProcessQuarantine))
- return service_manager::Manifest::ExecutionMode::kOutOfProcessBuiltin;
-#endif
- return service_manager::Manifest::ExecutionMode::kInProcessBuiltin;
-}
-
-const service_manager::Manifest& GetQuarantineManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName("Quarantine Service")
- .WithOptions(service_manager::ManifestOptionsBuilder()
- .WithExecutionMode(GetExecutionMode())
- .WithSandboxType("none")
- .WithInstanceSharingPolicy(
- service_manager::Manifest::
- InstanceSharingPolicy::kSharedAcrossGroups)
- .Build())
- .ExposeCapability(
- mojom::kQuarantineFileCapability,
- service_manager::Manifest::InterfaceList<mojom::Quarantine>())
- .Build()};
- return *manifest;
-}
-
-} // namespace quarantine
diff --git a/chromium/components/services/quarantine/public/cpp/manifest.h b/chromium/components/services/quarantine/public/cpp/manifest.h
deleted file mode 100644
index 48e068d250e..00000000000
--- a/chromium/components/services/quarantine/public/cpp/manifest.h
+++ /dev/null
@@ -1,18 +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 COMPONENTS_SERVICES_QUARANTINE_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_QUARANTINE_PUBLIC_CPP_MANIFEST_H_
-
-namespace service_manager {
-struct Manifest;
-}
-
-namespace quarantine {
-
-const service_manager::Manifest& GetQuarantineManifest();
-
-} // namespace quarantine
-
-#endif // COMPONENTS_SERVICES_QUARANTINE_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/quarantine/public/mojom/quarantine.mojom b/chromium/components/services/quarantine/public/mojom/quarantine.mojom
index a852bdeea5c..4f03cad882d 100644
--- a/chromium/components/services/quarantine/public/mojom/quarantine.mojom
+++ b/chromium/components/services/quarantine/public/mojom/quarantine.mojom
@@ -7,9 +7,6 @@ module quarantine.mojom;
import "mojo/public/mojom/base/file_path.mojom";
import "url/mojom/url.mojom";
-const string kServiceName = "quarantine";
-const string kQuarantineFileCapability = "quarantine_file";
-
enum QuarantineFileResult {
OK, // Success.
ACCESS_DENIED, // Access to the file was denied. The safety of the file
diff --git a/chromium/components/services/quarantine/quarantine_impl.cc b/chromium/components/services/quarantine/quarantine_impl.cc
index ffe9c2f272f..d3645b28a92 100644
--- a/chromium/components/services/quarantine/quarantine_impl.cc
+++ b/chromium/components/services/quarantine/quarantine_impl.cc
@@ -18,9 +18,11 @@
namespace quarantine {
+QuarantineImpl::QuarantineImpl() = default;
+
QuarantineImpl::QuarantineImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref)
- : service_ref_(std::move(service_ref)) {}
+ mojo::PendingReceiver<mojom::Quarantine> receiver)
+ : receiver_(this, std::move(receiver)) {}
QuarantineImpl::~QuarantineImpl() = default;
@@ -28,13 +30,13 @@ namespace {
#if defined(OS_WIN)
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
- return base::CreateCOMSTATaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ return base::CreateCOMSTATaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}
#else // OS_WIN
scoped_refptr<base::TaskRunner> GetTaskRunner() {
- return base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ return base::CreateTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}
#endif // OS_WIN
diff --git a/chromium/components/services/quarantine/quarantine_impl.h b/chromium/components/services/quarantine/quarantine_impl.h
index a7424543b7f..a1c3bcf010e 100644
--- a/chromium/components/services/quarantine/quarantine_impl.h
+++ b/chromium/components/services/quarantine/quarantine_impl.h
@@ -8,14 +8,15 @@
#include <memory>
#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
-#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
namespace quarantine {
class QuarantineImpl : public mojom::Quarantine {
public:
- explicit QuarantineImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+ QuarantineImpl();
+ explicit QuarantineImpl(mojo::PendingReceiver<mojom::Quarantine> receiver);
~QuarantineImpl() override;
// mojom::Quarantine:
@@ -27,7 +28,9 @@ class QuarantineImpl : public mojom::Quarantine {
mojom::Quarantine::QuarantineFileCallback callback) override;
private:
- const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+ mojo::Receiver<mojom::Quarantine> receiver_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(QuarantineImpl);
};
} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_service.cc b/chromium/components/services/quarantine/quarantine_service.cc
deleted file mode 100644
index 293029b3403..00000000000
--- a/chromium/components/services/quarantine/quarantine_service.cc
+++ /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.
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/time/time.h"
-#include "components/services/quarantine/quarantine_impl.h"
-#include "components/services/quarantine/quarantine_service.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace quarantine {
-
-namespace {
-
-void OnQuarantineRequest(service_manager::ServiceKeepalive* keepalive,
- mojom::QuarantineRequest request) {
- mojo::MakeStrongBinding(
- std::make_unique<QuarantineImpl>(keepalive->CreateRef()),
- std::move(request));
-}
-
-} // namespace
-
-QuarantineService::QuarantineService(
- service_manager::mojom::ServiceRequest request)
- : binding_(this, std::move(request)),
- keepalive_(&binding_, base::TimeDelta{}) {}
-
-QuarantineService::~QuarantineService() = default;
-
-void QuarantineService::OnStart() {
- registry_.AddInterface(
- base::BindRepeating(&OnQuarantineRequest, &keepalive_));
-}
-
-void QuarantineService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- registry_.BindInterface(interface_name, std::move(interface_pipe));
-}
-
-} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_service.h b/chromium/components/services/quarantine/quarantine_service.h
deleted file mode 100644
index 197089303dc..00000000000
--- a/chromium/components/services/quarantine/quarantine_service.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 COMPONENTS_SERVICES_QUARANTINE_QUARANTINE_SERVICE_H_
-#define COMPONENTS_SERVICES_QUARANTINE_QUARANTINE_SERVICE_H_
-
-#include <memory>
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-
-namespace quarantine {
-
-class QuarantineService : public service_manager::Service {
- public:
- explicit QuarantineService(service_manager::mojom::ServiceRequest request);
- ~QuarantineService() override;
-
- // service_manager::Service:
- void OnStart() override;
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- private:
- service_manager::ServiceBinding binding_;
- service_manager::ServiceKeepalive keepalive_;
- service_manager::BinderRegistry registry_;
-
- base::WeakPtrFactory<QuarantineService> weak_factory_{this};
-};
-
-} // namespace quarantine
-
-#endif // COMPONENTS_SERVICES_QUARANTINE_QUARANTINE_SERVICE_H_
diff --git a/chromium/components/services/quarantine/quarantine_service_unittest.cc b/chromium/components/services/quarantine/quarantine_service_unittest.cc
index c14d33b859a..a26f4fe69d3 100644
--- a/chromium/components/services/quarantine/quarantine_service_unittest.cc
+++ b/chromium/components/services/quarantine/quarantine_service_unittest.cc
@@ -11,10 +11,10 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
-#include "components/services/quarantine/quarantine_service.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
+#include "components/services/quarantine/quarantine_impl.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,11 +26,7 @@ const char kInternetReferrerURL[] = "http://example.com/some-other-url";
class QuarantineServiceTest : public testing::Test {
public:
- QuarantineServiceTest()
- : connector_(test_connector_factory_.CreateConnector()),
- service_(
- test_connector_factory_.RegisterInstance(mojom::kServiceName)) {}
-
+ QuarantineServiceTest() = default;
~QuarantineServiceTest() override = default;
void OnFileQuarantined(const base::FilePath& test_file,
@@ -42,23 +38,13 @@ class QuarantineServiceTest : public testing::Test {
}
protected:
- service_manager::Connector* connector() { return connector_.get(); }
- void SetUp() override {
- ASSERT_FALSE(quarantine_);
- connector()->BindInterface(mojom::kServiceName, &quarantine_);
- ASSERT_TRUE(quarantine_);
- }
-
- void TearDown() override { quarantine_.reset(); }
-
- base::test::ScopedTaskEnvironment task_environment_;
- mojom::QuarantinePtr quarantine_;
+ base::test::TaskEnvironment task_environment_;
+ mojo::Remote<mojom::Quarantine> quarantine_;
mojom::QuarantineFileResult result_;
private:
- service_manager::TestConnectorFactory test_connector_factory_;
- std::unique_ptr<service_manager::Connector> connector_;
- QuarantineService service_;
+ QuarantineImpl service_{quarantine_.BindNewPipeAndPassReceiver()};
+
DISALLOW_COPY_AND_ASSIGN(QuarantineServiceTest);
};
@@ -71,7 +57,6 @@ TEST_F(QuarantineServiceTest, QuarantineFile) {
base::WriteFile(test_file, kTestData, base::size(kTestData)));
base::RunLoop run_loop;
-
quarantine_->QuarantineFile(
test_file, GURL(kInternetURL), GURL(kInternetReferrerURL), std::string(),
base::BindOnce(&QuarantineServiceTest::OnFileQuarantined,
diff --git a/chromium/components/services/storage/BUILD.gn b/chromium/components/services/storage/BUILD.gn
new file mode 100644
index 00000000000..cb8a6ada8dc
--- /dev/null
+++ b/chromium/components/services/storage/BUILD.gn
@@ -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.
+
+source_set("storage") {
+ sources = [
+ "dom_storage/dom_storage_database.cc",
+ "dom_storage/dom_storage_database.h",
+ "origin_context_impl.cc",
+ "origin_context_impl.h",
+ "partition_impl.cc",
+ "partition_impl.h",
+ "storage_service_impl.cc",
+ "storage_service_impl.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//components/services/storage/public/mojom",
+ "//mojo/public/cpp/bindings",
+ "//third_party/leveldatabase",
+ "//url",
+ ]
+}
+
+source_set("tests") {
+ testonly = true
+
+ sources = [
+ "dom_storage/dom_storage_database_unittest.cc",
+ "partition_impl_unittest.cc",
+ "storage_service_impl_unittest.cc",
+ ]
+
+ deps = [
+ ":storage",
+ "//base",
+ "//base/test:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/services/storage/DEPS b/chromium/components/services/storage/DEPS
new file mode 100644
index 00000000000..743a2f3baec
--- /dev/null
+++ b/chromium/components/services/storage/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+third_party/leveldatabase",
+]
diff --git a/chromium/components/services/storage/OWNERS b/chromium/components/services/storage/OWNERS
new file mode 100644
index 00000000000..91200bd08e3
--- /dev/null
+++ b/chromium/components/services/storage/OWNERS
@@ -0,0 +1,3 @@
+jam@chromium.org
+pwnall@chromium.org
+rockot@google.com
diff --git a/chromium/components/services/storage/dom_storage/dom_storage_database.cc b/chromium/components/services/storage/dom_storage/dom_storage_database.cc
new file mode 100644
index 00000000000..184a55008e1
--- /dev/null
+++ b/chromium/components/services/storage/dom_storage/dom_storage_database.cc
@@ -0,0 +1,340 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/dom_storage/dom_storage_database.h"
+
+#include <utility>
+
+#include "base/no_destructor.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/threading/sequenced_task_runner_handle.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/leveldatabase/leveldb_chrome.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+
+namespace storage {
+
+namespace {
+
+class DomStorageDatabaseEnv : public leveldb_env::ChromiumEnv {
+ public:
+ DomStorageDatabaseEnv() : ChromiumEnv("ChromiumEnv.StorageService") {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DomStorageDatabaseEnv);
+};
+
+DomStorageDatabaseEnv* GetDomStorageDatabaseEnv() {
+ static base::NoDestructor<DomStorageDatabaseEnv> env;
+ return env.get();
+}
+
+std::string MakeFullPersistentDBName(const base::FilePath& directory,
+ const std::string& db_name) {
+ // ChromiumEnv treats DB name strings as UTF-8 file paths.
+ return directory.Append(base::FilePath::FromUTF8Unsafe(db_name))
+ .AsUTF8Unsafe();
+}
+
+leveldb_env::Options CreateDefaultInMemoryOptions() {
+ leveldb_env::Options options;
+ options.create_if_missing = true;
+ options.max_open_files = 0;
+ return options;
+}
+
+leveldb_env::Options AddEnvToOptions(const leveldb_env::Options& options,
+ leveldb::Env* env) {
+ leveldb_env::Options new_options = options;
+ new_options.env = env;
+ return new_options;
+}
+
+std::unique_ptr<leveldb::DB> TryOpenDB(
+ const leveldb_env::Options& options,
+ const std::string& name,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ DomStorageDatabase::StatusCallback callback) {
+ std::unique_ptr<leveldb::DB> db;
+ leveldb::Status status = leveldb_env::OpenDB(options, name, &db);
+ callback_task_runner->PostTask(FROM_HERE,
+ base::BindOnce(std::move(callback), status));
+ return db;
+}
+
+leveldb::Slice MakeSlice(base::span<const uint8_t> data) {
+ if (data.empty())
+ return leveldb::Slice();
+ return leveldb::Slice(reinterpret_cast<const char*>(data.data()),
+ data.size());
+}
+
+DomStorageDatabase::KeyValuePair MakeKeyValuePair(const leveldb::Slice& key,
+ const leveldb::Slice& value) {
+ auto key_span = base::make_span(key);
+ auto value_span = base::make_span(value);
+ return DomStorageDatabase::KeyValuePair(
+ DomStorageDatabase::Key(key_span.begin(), key_span.end()),
+ DomStorageDatabase::Value(value_span.begin(), value_span.end()));
+}
+
+template <typename Func>
+DomStorageDatabase::Status ForEachWithPrefix(leveldb::DB* db,
+ DomStorageDatabase::KeyView prefix,
+ Func function) {
+ // NOTE: We disable filling the cache for bulk scans. Either this is for
+ // deletion (where caching doesn't make sense) or a mass-read, which the user
+ // should be caching or only needing once.
+ leveldb::ReadOptions options;
+ options.fill_cache = false;
+ std::unique_ptr<leveldb::Iterator> iter(db->NewIterator(options));
+ const leveldb::Slice prefix_slice(MakeSlice(prefix));
+ iter->Seek(prefix_slice);
+ for (; iter->Valid(); iter->Next()) {
+ if (!iter->key().starts_with(prefix_slice))
+ break;
+ function(iter->key(), iter->value());
+ }
+ return iter->status();
+}
+
+} // namespace
+
+DomStorageDatabase::KeyValuePair::KeyValuePair() = default;
+
+DomStorageDatabase::KeyValuePair::~KeyValuePair() = default;
+
+DomStorageDatabase::KeyValuePair::KeyValuePair(KeyValuePair&&) = default;
+
+DomStorageDatabase::KeyValuePair::KeyValuePair(const KeyValuePair&) = default;
+
+DomStorageDatabase::KeyValuePair::KeyValuePair(Key key, Value value)
+ : key(std::move(key)), value(std::move(value)) {}
+
+DomStorageDatabase::KeyValuePair& DomStorageDatabase::KeyValuePair::operator=(
+ KeyValuePair&&) = default;
+
+DomStorageDatabase::KeyValuePair& DomStorageDatabase::KeyValuePair::operator=(
+ const KeyValuePair&) = default;
+
+bool DomStorageDatabase::KeyValuePair::operator==(
+ const KeyValuePair& rhs) const {
+ return std::tie(key, value) == std::tie(rhs.key, rhs.value);
+}
+
+DomStorageDatabase::DomStorageDatabase(
+ const base::FilePath& directory,
+ const std::string& name,
+ const leveldb_env::Options& options,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback)
+ : DomStorageDatabase(MakeFullPersistentDBName(directory, name),
+ /*env=*/nullptr,
+ options,
+ memory_dump_id,
+ std::move(callback_task_runner),
+ std::move(callback)) {}
+
+DomStorageDatabase::DomStorageDatabase(
+ const std::string& tracking_name,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback)
+ : DomStorageDatabase("",
+ leveldb_chrome::NewMemEnv(tracking_name),
+ CreateDefaultInMemoryOptions(),
+ memory_dump_id,
+ std::move(callback_task_runner),
+ std::move(callback)) {}
+
+DomStorageDatabase::DomStorageDatabase(
+ const std::string& name,
+ std::unique_ptr<leveldb::Env> env,
+ const leveldb_env::Options& options,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback)
+ : name_(name),
+ env_(std::move(env)),
+ options_(AddEnvToOptions(options,
+ env_ ? env_.get() : GetDomStorageDatabaseEnv())),
+ db_(TryOpenDB(options_,
+ name,
+ std::move(callback_task_runner),
+ std::move(callback))),
+ memory_dump_id_(memory_dump_id) {
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->RegisterDumpProviderWithSequencedTaskRunner(
+ this, "MojoLevelDB", base::SequencedTaskRunnerHandle::Get(),
+ MemoryDumpProvider::Options());
+}
+
+DomStorageDatabase::~DomStorageDatabase() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+}
+
+// static
+void DomStorageDatabase::OpenDirectory(
+ const base::FilePath& directory,
+ const std::string& name,
+ const leveldb_env::Options& options,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ OpenCallback callback) {
+ DCHECK(directory.IsAbsolute());
+ auto database = std::make_unique<base::SequenceBound<DomStorageDatabase>>();
+ auto* database_ptr = database.get();
+ *database_ptr = base::SequenceBound<DomStorageDatabase>(
+ blocking_task_runner, directory, name, options, memory_dump_id,
+ base::SequencedTaskRunnerHandle::Get(),
+ base::BindOnce(
+ [](std::unique_ptr<base::SequenceBound<DomStorageDatabase>> database,
+ OpenCallback callback, leveldb::Status status) {
+ if (status.ok())
+ std::move(callback).Run(std::move(*database), status);
+ else
+ std::move(callback).Run({}, status);
+ },
+ std::move(database), std::move(callback)));
+}
+
+// static
+void DomStorageDatabase::OpenInMemory(
+ const std::string& name,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ OpenCallback callback) {
+ auto database = std::make_unique<base::SequenceBound<DomStorageDatabase>>();
+ auto* database_ptr = database.get();
+ *database_ptr = base::SequenceBound<DomStorageDatabase>(
+ blocking_task_runner, name, memory_dump_id,
+ base::SequencedTaskRunnerHandle::Get(),
+ base::BindOnce(
+ [](std::unique_ptr<base::SequenceBound<DomStorageDatabase>> database,
+ OpenCallback callback, leveldb::Status status) {
+ if (status.ok())
+ std::move(callback).Run(std::move(*database), status);
+ else
+ std::move(callback).Run({}, status);
+ },
+ std::move(database), std::move(callback)));
+}
+
+// static
+void DomStorageDatabase::Destroy(
+ const base::FilePath& directory,
+ const std::string& name,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ StatusCallback callback) {
+ blocking_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](const std::string& db_name,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback) {
+ leveldb_env::Options options;
+ options.env = GetDomStorageDatabaseEnv();
+ callback_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback),
+ leveldb::DestroyDB(db_name, options)));
+ },
+ MakeFullPersistentDBName(directory, name),
+ base::SequencedTaskRunnerHandle::Get(), std::move(callback)));
+}
+
+DomStorageDatabase::Status DomStorageDatabase::Get(KeyView key,
+ Value* out_value) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::string value;
+ Status status = db_->Get(leveldb::ReadOptions(), MakeSlice(key), &value);
+ *out_value = Value(value.begin(), value.end());
+ return status;
+}
+
+DomStorageDatabase::Status DomStorageDatabase::Put(KeyView key,
+ ValueView value) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return db_->Put(leveldb::WriteOptions(), MakeSlice(key), MakeSlice(value));
+}
+
+DomStorageDatabase::Status DomStorageDatabase::Delete(KeyView key) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return db_->Delete(leveldb::WriteOptions(), MakeSlice(key));
+}
+
+DomStorageDatabase::Status DomStorageDatabase::GetPrefixed(
+ KeyView prefix,
+ std::vector<KeyValuePair>* entries) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return ForEachWithPrefix(
+ db_.get(), prefix,
+ [&](const leveldb::Slice& key, const leveldb::Slice& value) {
+ entries->push_back(MakeKeyValuePair(key, value));
+ });
+}
+
+DomStorageDatabase::Status DomStorageDatabase::DeletePrefixed(
+ KeyView prefix) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ leveldb::WriteBatch batch;
+ Status status = ForEachWithPrefix(
+ db_.get(), prefix,
+ [&](const leveldb::Slice& key, const leveldb::Slice& value) {
+ batch.Delete(key);
+ });
+ if (!status.ok())
+ return status;
+ return db_->Write(leveldb::WriteOptions(), &batch);
+}
+
+DomStorageDatabase::Status DomStorageDatabase::CopyPrefixed(
+ KeyView prefix,
+ KeyView new_prefix) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ leveldb::WriteBatch batch;
+ Key new_key(new_prefix.begin(), new_prefix.end());
+ Status status = ForEachWithPrefix(
+ db_.get(), prefix,
+ [&](const leveldb::Slice& key, const leveldb::Slice& value) {
+ DCHECK_GE(key.size(), prefix.size()); // By definition.
+ size_t suffix_length = key.size() - prefix.size();
+ new_key.resize(new_prefix.size() + suffix_length);
+ std::copy(key.data() + prefix.size(), key.data() + key.size(),
+ new_key.begin() + new_prefix.size());
+ batch.Put(MakeSlice(new_key), value);
+ });
+ if (!status.ok())
+ return status;
+ return db_->Write(leveldb::WriteOptions(), &batch);
+}
+
+bool DomStorageDatabase::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ auto* dump = leveldb_env::DBTracker::GetOrCreateAllocatorDump(pmd, db_.get());
+ if (!dump)
+ return true;
+ auto* global_dump = pmd->CreateSharedGlobalAllocatorDump(*memory_dump_id_);
+ pmd->AddOwnershipEdge(global_dump->guid(), dump->guid());
+ // Add size to global dump to propagate the size of the database to the
+ // client's dump.
+ global_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ dump->GetSizeInternal());
+ return true;
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/dom_storage/dom_storage_database.h b/chromium/components/services/storage/dom_storage/dom_storage_database.h
new file mode 100644
index 00000000000..aac805a0c6b
--- /dev/null
+++ b/chromium/components/services/storage/dom_storage/dom_storage_database.h
@@ -0,0 +1,190 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_DOM_STORAGE_DATABASE_H_
+#define COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_DOM_STORAGE_DATABASE_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/containers/span.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequence_bound.h"
+#include "base/trace_event/memory_allocator_dump_guid.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "third_party/leveldatabase/env_chromium.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+#include "third_party/leveldatabase/src/include/leveldb/env.h"
+
+namespace storage {
+
+// Wraps its own leveldb::DB instance on behalf of the DOM Storage backend
+// implementation. This object is not sequence-safe and must be instantiated on
+// a sequence which allows use of blocking file operations.
+//
+// Use the static |OpenInMemory()| or |OpenDirectory()| helpers to
+// asynchronously create an instance of this type from any sequence.
+// When owning a SequenceBound<DomStorageDatabase> as produced by these helpers,
+// all work on the DomStorageDatabase can be safely done via
+// |SequenceBound::PostTaskWithThisObject|.
+class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
+ public:
+ using Key = std::vector<uint8_t>;
+ using KeyView = base::span<const uint8_t>;
+ using Value = std::vector<uint8_t>;
+ using ValueView = base::span<const uint8_t>;
+ using Status = leveldb::Status;
+
+ // Callback used for basic async operations on this class.
+ using StatusCallback = base::OnceCallback<void(Status)>;
+
+ struct KeyValuePair {
+ KeyValuePair();
+ KeyValuePair(KeyValuePair&&);
+ KeyValuePair(const KeyValuePair&);
+ KeyValuePair(Key key, Value value);
+ ~KeyValuePair();
+ KeyValuePair& operator=(KeyValuePair&&);
+ KeyValuePair& operator=(const KeyValuePair&);
+
+ bool operator==(const KeyValuePair& rhs) const;
+
+ Key key;
+ Value value;
+ };
+
+ ~DomStorageDatabase() override;
+
+ // Callback invoked asynchronously with the result of both |OpenDirectory()|
+ // and |OpenInMemory()| defined below. Includes both the status and the
+ // (possibly null, on failure) sequence-bound DomStorageDatabase instance.
+ using OpenCallback =
+ base::OnceCallback<void(base::SequenceBound<DomStorageDatabase> database,
+ leveldb::Status status)>;
+
+ // Creates a DomStorageDatabase instance for a persistent database within a
+ // filesystem directory given by |directory|, which must be an absolute path.
+ // The database may or may not already exist at this path, and whether or not
+ // this operation succeeds in either case depends on options set in |options|,
+ // e.g. |create_if_missing| and/or |error_if_exists|.
+ //
+ // The instance will be bound to and perform all operations on |task_runner|,
+ // which must support blocking operations. |callback| is called on the calling
+ // sequence once the operation completes.
+ static void OpenDirectory(
+ const base::FilePath& directory,
+ const std::string& name,
+ const leveldb_env::Options& options,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ OpenCallback callback);
+
+ // Creates a DomStorageDatabase instance for a new in-memory database.
+ //
+ // The instance will be bound to and perform all operations on |task_runner|,
+ // which must support blocking operations. |callback| is called on the calling
+ // sequence once the operation completes.
+ static void OpenInMemory(
+ const std::string& name,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ OpenCallback callback);
+
+ // Destroys the persistent database named |name| within the filesystem
+ // directory identified by the absolute path in |directory|.
+ //
+ // All work is done on |task_runner|, which must support blocking operations,
+ // and upon completion |callback| is called on the calling sequence.
+ static void Destroy(
+ const base::FilePath& directory,
+ const std::string& name,
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+ StatusCallback callback);
+
+ // Retrieves the value for |key| in the database.
+ Status Get(KeyView key, Value* out_value) const;
+
+ // Sets the database entry for |key| to |value|.
+ Status Put(KeyView key, ValueView value) const;
+
+ // Deletes the database entry for |key|.
+ Status Delete(KeyView key) const;
+
+ // Gets all database entries whose key starts with |prefix|.
+ Status GetPrefixed(KeyView prefix, std::vector<KeyValuePair>* entries) const;
+
+ // Deletes all database entries whose key starts with |prefix|.
+ Status DeletePrefixed(KeyView prefix) const;
+
+ // Copies all database entries whose key starts with |prefix| over to new
+ // entries with |prefix| replaced by |new_prefix| in each new key.
+ Status CopyPrefixed(KeyView prefix, KeyView new_prefix) const;
+
+ private:
+ friend class base::SequenceBound<DomStorageDatabase>;
+
+ // Constructs a new DomStorageDatabase, creating or opening persistent
+ // on-filesystem database as specified. Asynchronously invokes |callback| on
+ // |callback_task_runner| when done.
+ //
+ // This must be called on a sequence that allows blocking operations. Prefer
+ // to instead call one of the static methods defined below, which can be
+ // called from any sequence.
+ DomStorageDatabase(
+ const base::FilePath& directory,
+ const std::string& name,
+ const leveldb_env::Options& options,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback);
+
+ // Same as above, but for an in-memory database. |tracking_name| is used
+ // internally for memory dump details.
+ DomStorageDatabase(
+ const std::string& tracking_name,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ memory_dump_id,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback);
+
+ DomStorageDatabase(
+ const std::string& name,
+ std::unique_ptr<leveldb::Env> env,
+ const leveldb_env::Options& options,
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ memory_dump_id_,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
+ StatusCallback callback);
+
+ // base::trace_event::MemoryDumpProvider implementation:
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
+ const std::string name_;
+ const std::unique_ptr<leveldb::Env> env_;
+ const leveldb_env::Options options_;
+ const std::unique_ptr<leveldb::DB> db_;
+ const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ memory_dump_id_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(DomStorageDatabase);
+};
+
+} // namespace storage
+
+#endif // COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_DOM_STORAGE_DATABASE_H_
diff --git a/chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc b/chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc
new file mode 100644
index 00000000000..e3982fc23dd
--- /dev/null
+++ b/chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc
@@ -0,0 +1,437 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/dom_storage/dom_storage_database.h"
+
+#include <algorithm>
+#include <functional>
+#include <iostream>
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
+#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/env_chromium.h"
+
+using ::testing::UnorderedElementsAreArray;
+
+// Helper to make Status checks a little more legible in test failures.
+#define EXPECT_STATUS(expectation, value) \
+ ([](auto s) { \
+ EXPECT_TRUE(s.expectation()) << "Actual status is: " << s.ToString(); \
+ }(value))
+
+#define EXPECT_STATUS_OK(value) EXPECT_STATUS(ok, value)
+
+// Helper to make database value expectation checks and failures more legible
+#define EXPECT_VALUE_EQ(expectation, value) \
+ EXPECT_EQ(std::string(expectation), std::string(value.begin(), value.end()))
+
+namespace storage {
+
+std::ostream& operator<<(std::ostream& os,
+ const DomStorageDatabase::KeyValuePair& kvp) {
+ os << "<\"" << std::string(kvp.key.begin(), kvp.key.end()) << "\", \""
+ << std::string(kvp.value.begin(), kvp.value.end()) << "\">";
+ return os;
+}
+
+namespace {
+
+// Helper for tests to create a |uint8_t| span from a StringPiece.
+base::span<const uint8_t> MakeBytes(base::StringPiece s) {
+ return base::as_bytes(base::make_span(s));
+}
+
+DomStorageDatabase::KeyValuePair MakeKeyValuePair(base::StringPiece key,
+ base::StringPiece value) {
+ return {DomStorageDatabase::Key(key.begin(), key.end()),
+ DomStorageDatabase::Value(value.begin(), value.end())};
+}
+
+std::string MakePrefixedKey(base::StringPiece prefix, base::StringPiece key) {
+ return prefix.as_string() + key.as_string();
+}
+
+class StorageServiceDomStorageDatabaseTest : public testing::Test {
+ public:
+ StorageServiceDomStorageDatabaseTest()
+ : blocking_task_runner_(base::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::ThreadPool(),
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {}
+
+ protected:
+ // Helper for tests to block on the result of an OpenInMemory call.
+ base::SequenceBound<DomStorageDatabase> OpenInMemorySync(
+ const std::string& db_name) {
+ base::SequenceBound<DomStorageDatabase> result;
+ base::RunLoop loop;
+ DomStorageDatabase::OpenInMemory(
+ db_name, /*memory_dump_id=*/base::nullopt, blocking_task_runner_,
+ base::BindLambdaForTesting(
+ [&](base::SequenceBound<DomStorageDatabase> database,
+ leveldb::Status status) {
+ result = std::move(database);
+ loop.Quit();
+ }));
+ loop.Run();
+ return result;
+ }
+
+ // Helper for tests to block on the result of an OpenDirectory call.
+ base::SequenceBound<DomStorageDatabase> OpenDirectorySync(
+ const base::FilePath& directory,
+ const std::string& db_name,
+ const leveldb_env::Options& options) {
+ base::SequenceBound<DomStorageDatabase> result;
+ base::RunLoop loop;
+ DomStorageDatabase::OpenDirectory(
+ directory, db_name, options, /*memory_dump_id=*/base::nullopt,
+ blocking_task_runner_,
+ base::BindLambdaForTesting(
+ [&](base::SequenceBound<DomStorageDatabase> database,
+ leveldb::Status status) {
+ result = std::move(database);
+ loop.Quit();
+ }));
+ loop.Run();
+ return result;
+ }
+
+ // Helper for tests to block on the result of a Destroy call.
+ leveldb::Status DestroySync(const base::FilePath& directory,
+ const std::string& db_name) {
+ leveldb::Status result;
+ base::RunLoop loop;
+ DomStorageDatabase::Destroy(
+ directory, db_name, blocking_task_runner_,
+ base::BindLambdaForTesting([&](leveldb::Status status) {
+ result = status;
+ loop.Quit();
+ }));
+ loop.Run();
+ return result;
+ }
+
+ // Helper to run an async operation on a DomStorageDatabase and wait for it to
+ // finish.
+ template <typename Func>
+ static void DoSync(const base::SequenceBound<DomStorageDatabase>& database,
+ Func operation) {
+ base::RunLoop loop;
+ database.PostTaskWithThisObject(
+ FROM_HERE,
+ base::BindLambdaForTesting([&](const DomStorageDatabase& database) {
+ operation(database);
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(StorageServiceDomStorageDatabaseTest);
+};
+
+} // namespace
+
+TEST_F(StorageServiceDomStorageDatabaseTest, BasicOpenInMemory) {
+ // Basic smoke test to verify that we can successfully create and destroy an
+ // in-memory database with no problems.
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenInMemorySync("test_db");
+ EXPECT_TRUE(database);
+}
+
+TEST_F(StorageServiceDomStorageDatabaseTest, BasicOpenDirectory) {
+ // Basic smoke test to verify that we can successfully create and destroy a
+ // persistent database with no problems.
+
+ base::ScopedTempDir temp_dir;
+ CHECK(temp_dir.CreateUniqueTempDir());
+ const char kTestDbName[] = "test_db";
+
+ leveldb_env::Options options;
+ options.create_if_missing = true;
+ options.error_if_exists = true;
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenDirectorySync(temp_dir.GetPath(), kTestDbName, options);
+ EXPECT_TRUE(database);
+
+ // Because the database owns filesystem artifacts in the temp directory, we
+ // will wait for the DomStorageDatabase instance to actually be destroyed
+ // before completing the test.
+ base::RunLoop loop;
+ database.ResetWithCallbackAfterDestruction(loop.QuitClosure());
+
+ // Destroy the database. Note that this should be safe to call immediately
+ // after |Reset()| as long as the same TaskRunner is used to open and destroy
+ // the database.
+ EXPECT_STATUS_OK(DestroySync(temp_dir.GetPath(), kTestDbName));
+
+ loop.Run();
+
+ // Verify that the database can't be reopened.
+ options.create_if_missing = false;
+ options.error_if_exists = false;
+ database = OpenDirectorySync(temp_dir.GetPath(), kTestDbName, options);
+ EXPECT_FALSE(database);
+}
+
+TEST_F(StorageServiceDomStorageDatabaseTest, BasicOperations) {
+ // Exercises basic Put, Get, Delete.
+
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenInMemorySync("test_db");
+ ASSERT_TRUE(database);
+
+ // Write a key and read it back.
+ const char kTestKey[] = "test_key";
+ const char kTestValue[] = "test_value";
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ EXPECT_STATUS_OK(db.Put(MakeBytes(kTestKey), MakeBytes(kTestValue)));
+
+ DomStorageDatabase::Value value;
+ EXPECT_STATUS_OK(db.Get(MakeBytes(kTestKey), &value));
+ EXPECT_VALUE_EQ(kTestValue, value);
+ });
+
+ // Now delete the key and expect the following read to fail.
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ EXPECT_STATUS_OK(db.Delete(MakeBytes(kTestKey)));
+
+ DomStorageDatabase::Value value;
+ EXPECT_STATUS(IsNotFound, db.Get(MakeBytes(kTestKey), &value));
+ });
+}
+
+TEST_F(StorageServiceDomStorageDatabaseTest, Reopen) {
+ // Verifies that if we Put() something into a persistent database, we can
+ // Get() it back out when we re-open the same database later.
+
+ base::ScopedTempDir temp_dir;
+ CHECK(temp_dir.CreateUniqueTempDir());
+ const char kTestDbName[] = "test_db";
+ const char kTestKey[] = "test_key";
+ const char kTestValue[] = "test_value";
+
+ leveldb_env::Options options;
+ options.create_if_missing = true;
+ options.error_if_exists = true;
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenDirectorySync(temp_dir.GetPath(), kTestDbName, options);
+ ASSERT_TRUE(database);
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ EXPECT_STATUS_OK(db.Put(MakeBytes(kTestKey), MakeBytes(kTestValue)));
+ });
+ database.Reset();
+
+ // Re-open and verify that we can read what was written above.
+ options.create_if_missing = false;
+ options.error_if_exists = false;
+ database = OpenDirectorySync(temp_dir.GetPath(), kTestDbName, options);
+ ASSERT_TRUE(database);
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ DomStorageDatabase::Value value;
+ EXPECT_STATUS_OK(db.Get(MakeBytes(kTestKey), &value));
+ EXPECT_VALUE_EQ(kTestValue, value);
+ });
+
+ // Because the database owns filesystem artifacts in the temp directory, block
+ // scope teardown until the DomStorageDatabase instance is actually destroyed
+ // on its background sequence.
+ base::RunLoop loop;
+ database.ResetWithCallbackAfterDestruction(loop.QuitClosure());
+ loop.Run();
+}
+
+TEST_F(StorageServiceDomStorageDatabaseTest, GetPrefixed) {
+ // Verifies basic prefixed reading behavior.
+
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenInMemorySync("test_db");
+ ASSERT_TRUE(database);
+
+ const char kTestPrefix1[] = "prefix";
+ const char kTestPrefix2[] = "something_completely_different";
+ const char kTestUnprefixedKey[] = "moot!";
+ const char kTestKeyBase1[] = "key1";
+ const char kTestKeyBase2[] = "key2";
+ auto kTestPrefix1Key1 = MakePrefixedKey(kTestPrefix1, kTestKeyBase1);
+ auto kTestPrefix1Key2 = MakePrefixedKey(kTestPrefix1, kTestKeyBase2);
+ auto kTestPrefix2Key1 = MakePrefixedKey(kTestPrefix2, kTestKeyBase1);
+ auto kTestPrefix2Key2 = MakePrefixedKey(kTestPrefix2, kTestKeyBase2);
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ std::vector<DomStorageDatabase::KeyValuePair> entries;
+
+ // No keys, so GetPrefixed should return nothing.
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix1), &entries));
+ EXPECT_TRUE(entries.empty());
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+ EXPECT_TRUE(entries.empty());
+
+ // Insert a key which matches neither test prefix. GetPrefixed should still
+ // return nothing.
+ EXPECT_STATUS_OK(db.Put(MakeBytes(kTestUnprefixedKey), MakeBytes("meh")));
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix1), &entries));
+ EXPECT_TRUE(entries.empty());
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+ EXPECT_TRUE(entries.empty());
+
+ // Insert a single prefixed key. GetPrefixed should return it when called
+ // with kTestPrefix1.
+ const char kTestValue1[] = "beep beep";
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix1Key1), MakeBytes(kTestValue1)));
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix1), &entries));
+ EXPECT_THAT(entries, UnorderedElementsAreArray({MakeKeyValuePair(
+ kTestPrefix1Key1, kTestValue1)}));
+
+ // But not when called with kTestPrefix2.
+ entries.clear();
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+ EXPECT_TRUE(entries.empty());
+
+ // Insert a second prefixed key with kTestPrefix1, and also insert some
+ // keys with kTestPrefix2.
+ const char kTestValue2[] = "beep bop boop";
+ const char kTestValue3[] = "vroom vroom";
+ const char kTestValue4[] = "this data is lit fam";
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix1Key2), MakeBytes(kTestValue2)));
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix2Key1), MakeBytes(kTestValue3)));
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix2Key2), MakeBytes(kTestValue4)));
+
+ // Verify that getting each prefix yields only the expected results.
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix1), &entries));
+ EXPECT_THAT(entries,
+ UnorderedElementsAreArray(
+ {MakeKeyValuePair(kTestPrefix1Key1, kTestValue1),
+ MakeKeyValuePair(kTestPrefix1Key2, kTestValue2)}));
+ entries.clear();
+
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+ EXPECT_THAT(entries,
+ UnorderedElementsAreArray(
+ {MakeKeyValuePair(kTestPrefix2Key1, kTestValue3),
+ MakeKeyValuePair(kTestPrefix2Key2, kTestValue4)}));
+ });
+}
+
+TEST_F(StorageServiceDomStorageDatabaseTest, DeletePrefixed) {
+ // Verifies basic prefixed deletion behavior.
+
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenInMemorySync("test_db");
+ ASSERT_TRUE(database);
+
+ const char kTestPrefix1[] = "prefix";
+ const char kTestPrefix2[] = "something_completely_different";
+ const char kTestUnprefixedKey[] = "moot!";
+ const char kTestKeyBase1[] = "key1";
+ const char kTestKeyBase2[] = "key2";
+ auto kTestPrefix1Key1 = MakePrefixedKey(kTestPrefix1, kTestKeyBase1);
+ auto kTestPrefix1Key2 = MakePrefixedKey(kTestPrefix1, kTestKeyBase2);
+ auto kTestPrefix2Key1 = MakePrefixedKey(kTestPrefix2, kTestKeyBase1);
+ auto kTestPrefix2Key2 = MakePrefixedKey(kTestPrefix2, kTestKeyBase2);
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ // Insert a bunch of entries. One unprefixed, two with one prefix, and two
+ // with another prefix.
+ const char kTestValue1[] = "meh";
+ const char kTestValue2[] = "bah";
+ const char kTestValue3[] = "doh";
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestUnprefixedKey), MakeBytes(kTestValue1)));
+ EXPECT_STATUS_OK(db.Put(MakeBytes(kTestPrefix1Key1), MakeBytes("x")));
+ EXPECT_STATUS_OK(db.Put(MakeBytes(kTestPrefix1Key2), MakeBytes("x")));
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix2Key1), MakeBytes(kTestValue2)));
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix2Key2), MakeBytes(kTestValue3)));
+
+ // Wipe out the first prefix. We should still see the second prefix.
+ std::vector<DomStorageDatabase::KeyValuePair> entries;
+ EXPECT_STATUS_OK(db.DeletePrefixed(MakeBytes(kTestPrefix1)));
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix1), &entries));
+ EXPECT_TRUE(entries.empty());
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+ EXPECT_THAT(entries,
+ UnorderedElementsAreArray(
+ {MakeKeyValuePair(kTestPrefix2Key1, kTestValue2),
+ MakeKeyValuePair(kTestPrefix2Key2, kTestValue3)}));
+
+ // Wipe out the second prefix.
+ EXPECT_STATUS_OK(db.DeletePrefixed(MakeBytes(kTestPrefix2)));
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+
+ // The lone unprefixed value should still exist.
+ DomStorageDatabase::Value value;
+ EXPECT_STATUS_OK(db.Get(MakeBytes(kTestUnprefixedKey), &value));
+ EXPECT_VALUE_EQ(kTestValue1, value);
+ });
+}
+
+TEST_F(StorageServiceDomStorageDatabaseTest, CopyPrefixed) {
+ // Verifies basic prefixed copying behavior.
+
+ base::SequenceBound<DomStorageDatabase> database =
+ OpenInMemorySync("test_db");
+ ASSERT_TRUE(database);
+
+ const char kTestUnprefixedKey[] = "moot!";
+ const char kTestPrefix1[] = "prefix";
+ const char kTestPrefix2[] = "something_completely_different";
+ const char kTestKeyBase1[] = "key1";
+ const char kTestKeyBase2[] = "key2";
+ auto kTestPrefix1Key1 = MakePrefixedKey(kTestPrefix1, kTestKeyBase1);
+ auto kTestPrefix1Key2 = MakePrefixedKey(kTestPrefix1, kTestKeyBase2);
+ auto kTestPrefix2Key1 = MakePrefixedKey(kTestPrefix2, kTestKeyBase1);
+ auto kTestPrefix2Key2 = MakePrefixedKey(kTestPrefix2, kTestKeyBase2);
+ const char kTestValue1[] = "a value";
+ const char kTestValue2[] = "another value";
+ const char kTestValue3[] = "the only other value in the world";
+
+ DoSync(database, [&](const DomStorageDatabase& db) {
+ // Populate the database with one unprefixed entry, and two values with
+ // a key prefix of |kTestPrefix1|.
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestUnprefixedKey), MakeBytes(kTestValue1)));
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix1Key1), MakeBytes(kTestValue2)));
+ EXPECT_STATUS_OK(
+ db.Put(MakeBytes(kTestPrefix1Key2), MakeBytes(kTestValue3)));
+
+ // Copy the prefixed entries to |kTestPrefix2| and verify that we have the
+ // expected entries.
+ EXPECT_STATUS_OK(
+ db.CopyPrefixed(MakeBytes(kTestPrefix1), MakeBytes(kTestPrefix2)));
+
+ std::vector<DomStorageDatabase::KeyValuePair> entries;
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix2), &entries));
+ EXPECT_THAT(entries,
+ UnorderedElementsAreArray(
+ {MakeKeyValuePair(kTestPrefix2Key1, kTestValue2),
+ MakeKeyValuePair(kTestPrefix2Key2, kTestValue3)}));
+
+ // The original prefixed values should still be there too.
+ entries.clear();
+ EXPECT_STATUS_OK(db.GetPrefixed(MakeBytes(kTestPrefix1), &entries));
+ EXPECT_THAT(entries,
+ UnorderedElementsAreArray(
+ {MakeKeyValuePair(kTestPrefix1Key1, kTestValue2),
+ MakeKeyValuePair(kTestPrefix1Key2, kTestValue3)}));
+ });
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/origin_context_impl.cc b/chromium/components/services/storage/origin_context_impl.cc
new file mode 100644
index 00000000000..1f537c7bdc3
--- /dev/null
+++ b/chromium/components/services/storage/origin_context_impl.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 "components/services/storage/origin_context_impl.h"
+
+#include "components/services/storage/partition_impl.h"
+
+namespace storage {
+
+OriginContextImpl::OriginContextImpl(PartitionImpl* partition,
+ const url::Origin& origin)
+ : partition_(partition), origin_(origin) {
+ receivers_.set_disconnect_handler(base::BindRepeating(
+ &OriginContextImpl::OnDisconnect, base::Unretained(this)));
+}
+
+OriginContextImpl::~OriginContextImpl() = default;
+
+void OriginContextImpl::BindReceiver(
+ mojo::PendingReceiver<mojom::OriginContext> receiver) {
+ receivers_.Add(this, std::move(receiver));
+}
+
+void OriginContextImpl::OnDisconnect() {
+ if (receivers_.empty()) {
+ // Deletes |this|.
+ partition_->RemoveOriginContext(origin_);
+ }
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/origin_context_impl.h b/chromium/components/services/storage/origin_context_impl.h
new file mode 100644
index 00000000000..dd41311f40d
--- /dev/null
+++ b/chromium/components/services/storage/origin_context_impl.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 COMPONENTS_SERVICES_STORAGE_ORIGIN_CONTEXT_IMPL_H_
+#define COMPONENTS_SERVICES_STORAGE_ORIGIN_CONTEXT_IMPL_H_
+
+#include "base/macros.h"
+#include "components/services/storage/public/mojom/origin_context.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "url/origin.h"
+
+namespace storage {
+
+class PartitionImpl;
+
+class OriginContextImpl : public mojom::OriginContext {
+ public:
+ OriginContextImpl(PartitionImpl* partition, const url::Origin& origin);
+ ~OriginContextImpl() override;
+
+ const mojo::ReceiverSet<mojom::OriginContext>& receivers() const {
+ return receivers_;
+ }
+
+ void BindReceiver(mojo::PendingReceiver<mojom::OriginContext> receiver);
+
+ private:
+ void OnDisconnect();
+
+ PartitionImpl* const partition_;
+ const url::Origin origin_;
+ mojo::ReceiverSet<mojom::OriginContext> receivers_;
+
+ DISALLOW_COPY_AND_ASSIGN(OriginContextImpl);
+};
+
+} // namespace storage
+
+#endif // COMPONENTS_SERVICES_STORAGE_ORIGIN_CONTEXT_IMPL_H_
diff --git a/chromium/components/services/storage/partition_impl.cc b/chromium/components/services/storage/partition_impl.cc
new file mode 100644
index 00000000000..a0a7912da0c
--- /dev/null
+++ b/chromium/components/services/storage/partition_impl.cc
@@ -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.
+
+#include "components/services/storage/partition_impl.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "components/services/storage/storage_service_impl.h"
+
+namespace storage {
+
+PartitionImpl::PartitionImpl(StorageServiceImpl* service,
+ const base::Optional<base::FilePath>& path)
+ : service_(service), path_(path) {
+ receivers_.set_disconnect_handler(base::BindRepeating(
+ &PartitionImpl::OnDisconnect, base::Unretained(this)));
+}
+
+PartitionImpl::~PartitionImpl() = default;
+
+void PartitionImpl::BindReceiver(
+ mojo::PendingReceiver<mojom::Partition> receiver) {
+ DCHECK(receivers_.empty() || path_.has_value())
+ << "In-memory partitions must have at most one client.";
+
+ receivers_.Add(this, std::move(receiver));
+}
+
+void PartitionImpl::BindOriginContext(
+ const url::Origin& origin,
+ mojo::PendingReceiver<mojom::OriginContext> receiver) {
+ auto iter = origin_contexts_.find(origin);
+ if (iter == origin_contexts_.end()) {
+ auto result = origin_contexts_.emplace(
+ origin, std::make_unique<OriginContextImpl>(this, origin));
+ iter = result.first;
+ }
+
+ iter->second->BindReceiver(std::move(receiver));
+}
+
+void PartitionImpl::OnDisconnect() {
+ if (receivers_.empty()) {
+ // Deletes |this|.
+ service_->RemovePartition(this);
+ }
+}
+
+void PartitionImpl::RemoveOriginContext(const url::Origin& origin) {
+ origin_contexts_.erase(origin);
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/partition_impl.h b/chromium/components/services/storage/partition_impl.h
new file mode 100644
index 00000000000..589a7f02193
--- /dev/null
+++ b/chromium/components/services/storage/partition_impl.h
@@ -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.
+
+#ifndef COMPONENTS_SERVICES_STORAGE_PARTITION_IMPL_H_
+#define COMPONENTS_SERVICES_STORAGE_PARTITION_IMPL_H_
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "components/services/storage/origin_context_impl.h"
+#include "components/services/storage/public/mojom/partition.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "url/origin.h"
+
+namespace storage {
+
+class StorageServiceImpl;
+
+// A PartitionImpl instance exclusively owns an isolated storage partition
+// corresponding to either a persistent filesystem directory or an in-memory
+// database.
+class PartitionImpl : public mojom::Partition {
+ public:
+ // |service| owns and outlives this object.
+ explicit PartitionImpl(StorageServiceImpl* service,
+ const base::Optional<base::FilePath>& path);
+ ~PartitionImpl() override;
+
+ const base::Optional<base::FilePath>& path() const { return path_; }
+
+ const mojo::ReceiverSet<mojom::Partition>& receivers() const {
+ return receivers_;
+ }
+
+ const auto& origin_contexts() const { return origin_contexts_; }
+
+ // Binds a new client endpoint to this partition.
+ void BindReceiver(mojo::PendingReceiver<mojom::Partition> receiver);
+
+ // mojom::Partition:
+ void BindOriginContext(
+ const url::Origin& origin,
+ mojo::PendingReceiver<mojom::OriginContext> receiver) override;
+
+ private:
+ friend class OriginContextImpl;
+
+ void OnDisconnect();
+ void RemoveOriginContext(const url::Origin& origin);
+
+ StorageServiceImpl* const service_;
+ const base::Optional<base::FilePath> path_;
+ mojo::ReceiverSet<mojom::Partition> receivers_;
+ std::map<url::Origin, std::unique_ptr<OriginContextImpl>> origin_contexts_;
+
+ DISALLOW_COPY_AND_ASSIGN(PartitionImpl);
+};
+
+} // namespace storage
+
+#endif // COMPONENTS_SERVICES_STORAGE_PARTITION_IMPL_H_
diff --git a/chromium/components/services/storage/partition_impl_unittest.cc b/chromium/components/services/storage/partition_impl_unittest.cc
new file mode 100644
index 00000000000..baa6f45f106
--- /dev/null
+++ b/chromium/components/services/storage/partition_impl_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/storage_service_impl.h"
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/services/storage/partition_impl.h"
+#include "components/services/storage/public/mojom/partition.mojom.h"
+#include "components/services/storage/public/mojom/storage_service.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace storage {
+
+class StorageServicePartitionImplTest : public testing::Test {
+ public:
+ StorageServicePartitionImplTest() = default;
+ ~StorageServicePartitionImplTest() override = default;
+
+ void SetUp() override {
+ remote_service_->BindPartition(
+ base::nullopt, remote_test_partition_.BindNewPipeAndPassReceiver());
+ remote_test_partition_.FlushForTesting();
+
+ ASSERT_EQ(1u, service_.partitions().size());
+ test_partition_impl_ = service_.partitions().begin()->get();
+ }
+
+ protected:
+ mojom::Partition* remote_test_partition() {
+ return remote_test_partition_.get();
+ }
+ PartitionImpl* test_partition_impl() { return test_partition_impl_; }
+
+ private:
+ base::test::ScopedTaskEnvironment task_environment_;
+ mojo::Remote<mojom::StorageService> remote_service_;
+ StorageServiceImpl service_{remote_service_.BindNewPipeAndPassReceiver()};
+ mojo::Remote<mojom::Partition> remote_test_partition_;
+ PartitionImpl* test_partition_impl_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(StorageServicePartitionImplTest);
+};
+
+TEST_F(StorageServicePartitionImplTest, IndependentOriginContexts) {
+ // Verifies that clients for unique origins get bound to unique OriginContext
+ // backends.
+
+ const url::Origin kTestOrigin1 =
+ url::Origin::Create(GURL("http://example.com"));
+ mojo::Remote<mojom::OriginContext> context1;
+ remote_test_partition()->BindOriginContext(
+ kTestOrigin1, context1.BindNewPipeAndPassReceiver());
+ context1.FlushForTesting();
+ EXPECT_EQ(1u, test_partition_impl()->origin_contexts().size());
+
+ const url::Origin kTestOrigin2 =
+ url::Origin::Create(GURL("https://google.com"));
+ mojo::Remote<mojom::OriginContext> context2;
+ remote_test_partition()->BindOriginContext(
+ kTestOrigin2, context2.BindNewPipeAndPassReceiver());
+ context2.FlushForTesting();
+ EXPECT_EQ(2u, test_partition_impl()->origin_contexts().size());
+
+ EXPECT_TRUE(context1.is_connected());
+ EXPECT_TRUE(context2.is_connected());
+
+ // Verify that |context1| was connected to the backend for |kTestOrigin1| by
+ // disconnecting |context1| and waiting for the backend to be destroyed.
+ context1.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(
+ base::Contains(test_partition_impl()->origin_contexts(), kTestOrigin2));
+ EXPECT_FALSE(
+ base::Contains(test_partition_impl()->origin_contexts(), kTestOrigin1));
+
+ // Same for |context2|.
+ context2.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(
+ base::Contains(test_partition_impl()->origin_contexts(), kTestOrigin2));
+}
+
+TEST_F(StorageServicePartitionImplTest, SingleOriginMultipleClients) {
+ // Verifies that multiple clients can bind a connection to the same
+ // OriginContext within a Partition.
+
+ const url::Origin kTestOrigin =
+ url::Origin::Create(GURL("http://example.com"));
+ mojo::Remote<mojom::OriginContext> context1;
+ remote_test_partition()->BindOriginContext(
+ kTestOrigin, context1.BindNewPipeAndPassReceiver());
+ context1.FlushForTesting();
+ EXPECT_EQ(1u, test_partition_impl()->origin_contexts().size());
+
+ mojo::Remote<mojom::OriginContext> context2;
+ remote_test_partition()->BindOriginContext(
+ kTestOrigin, context2.BindNewPipeAndPassReceiver());
+ context2.FlushForTesting();
+ EXPECT_EQ(1u, test_partition_impl()->origin_contexts().size());
+
+ EXPECT_TRUE(context1.is_connected());
+ EXPECT_TRUE(context2.is_connected());
+}
+
+TEST_F(StorageServicePartitionImplTest,
+ OriginContextDestroyedOnLastClientDisconnect) {
+ const url::Origin kTestOrigin =
+ url::Origin::Create(GURL("http://example.com"));
+ mojo::Remote<mojom::OriginContext> context1;
+ remote_test_partition()->BindOriginContext(
+ kTestOrigin, context1.BindNewPipeAndPassReceiver());
+ context1.FlushForTesting();
+
+ mojo::Remote<mojom::OriginContext> context2;
+ remote_test_partition()->BindOriginContext(
+ kTestOrigin, context2.BindNewPipeAndPassReceiver());
+ context2.FlushForTesting();
+
+ EXPECT_EQ(1u, test_partition_impl()->origin_contexts().size());
+
+ context1.reset();
+ context2.reset();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0u, test_partition_impl()->origin_contexts().size());
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/public/mojom/BUILD.gn b/chromium/components/services/storage/public/mojom/BUILD.gn
new file mode 100644
index 00000000000..28dffb169ea
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/BUILD.gn
@@ -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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+ sources = [
+ "origin_context.mojom",
+ "partition.mojom",
+ "storage_service.mojom",
+ ]
+
+ public_deps = [
+ "//mojo/public/mojom/base",
+ "//url/mojom:url_mojom_origin",
+ ]
+}
diff --git a/chromium/components/services/storage/public/mojom/OWNERS b/chromium/components/services/storage/public/mojom/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/storage/public/mojom/origin_context.mojom b/chromium/components/services/storage/public/mojom/origin_context.mojom
new file mode 100644
index 00000000000..9934e746345
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/origin_context.mojom
@@ -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.
+
+module storage.mojom;
+
+// An OriginContext exposes various storage backend interfaces scoped to a
+// single security origin and a single Partition. See
+// |Partition.BindOriginContext()|.
+//
+// It is safe for the browser to broker OriginContext endpoints to the Storage
+// Service if the renderer is known to be rendering content from the relevant
+// origin.
+interface OriginContext {};
diff --git a/chromium/components/services/storage/public/mojom/partition.mojom b/chromium/components/services/storage/public/mojom/partition.mojom
new file mode 100644
index 00000000000..d57e5264914
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/partition.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 storage.mojom;
+
+import "components/services/storage/public/mojom/origin_context.mojom";
+import "url/mojom/origin.mojom";
+
+// Partition controls an isolated storage partition owned by the Storage
+// Service. This is analogous to the browser's own storage partition concept.
+interface Partition {
+ // Binds a new OriginContext scoped to |origin| within this Partition.
+ BindOriginContext(url.mojom.Origin origin,
+ pending_receiver<OriginContext> receiver);
+};
diff --git a/chromium/components/services/storage/public/mojom/storage_service.mojom b/chromium/components/services/storage/public/mojom/storage_service.mojom
new file mode 100644
index 00000000000..7d15cae3f66
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_service.mojom
@@ -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.
+
+module storage.mojom;
+
+import "components/services/storage/public/mojom/partition.mojom";
+import "mojo/public/mojom/base/file_path.mojom";
+
+// The main interface into the Storage Service. The browser maintains a single
+// global connection to this interface.
+interface StorageService {
+ // Binds a new Partition endpoint.
+ //
+ // |path| if non-null must be an absolute path, and it identifies a persistent
+ // filesystem directory controlled by the partition. Persistent partitions
+ // support arbitrarily many simultaneous clients.
+ //
+ // If |path| is null, the bound partition exists only in-memory and is
+ // uniquely owned by a single client. Disconnecting the Partition client
+ // effectively destroys the partition and its contents.
+ BindPartition(mojo_base.mojom.FilePath? path,
+ pending_receiver<Partition> receiver);
+};
diff --git a/chromium/components/services/storage/storage_service_impl.cc b/chromium/components/services/storage/storage_service_impl.cc
new file mode 100644
index 00000000000..92738674a8c
--- /dev/null
+++ b/chromium/components/services/storage/storage_service_impl.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 "components/services/storage/storage_service_impl.h"
+
+#include "components/services/storage/partition_impl.h"
+
+namespace storage {
+
+StorageServiceImpl::StorageServiceImpl(
+ mojo::PendingReceiver<mojom::StorageService> receiver)
+ : receiver_(this, std::move(receiver)) {}
+
+StorageServiceImpl::~StorageServiceImpl() = default;
+
+void StorageServiceImpl::BindPartition(
+ const base::Optional<base::FilePath>& path,
+ mojo::PendingReceiver<mojom::Partition> receiver) {
+ if (path.has_value()) {
+ if (!path->IsAbsolute()) {
+ // Refuse to bind Partitions for relative paths.
+ return;
+ }
+
+ // If this is a persistent partition that already exists, bind to it and
+ // we're done.
+ auto iter = persistent_partition_map_.find(*path);
+ if (iter != persistent_partition_map_.end()) {
+ iter->second->BindReceiver(std::move(receiver));
+ return;
+ }
+ }
+
+ auto new_partition = std::make_unique<PartitionImpl>(this, path);
+ new_partition->BindReceiver(std::move(receiver));
+ if (path.has_value())
+ persistent_partition_map_[*path] = new_partition.get();
+ partitions_.insert(std::move(new_partition));
+}
+
+void StorageServiceImpl::RemovePartition(PartitionImpl* partition) {
+ if (partition->path().has_value())
+ persistent_partition_map_.erase(partition->path().value());
+
+ auto iter = partitions_.find(partition);
+ if (iter != partitions_.end())
+ partitions_.erase(iter);
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/storage_service_impl.h b/chromium/components/services/storage/storage_service_impl.h
new file mode 100644
index 00000000000..d001f940e99
--- /dev/null
+++ b/chromium/components/services/storage/storage_service_impl.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_STORAGE_STORAGE_SERVICE_IMPL_H_
+#define COMPONENTS_SERVICES_STORAGE_STORAGE_SERVICE_IMPL_H_
+
+#include <memory>
+#include <set>
+
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "components/services/storage/partition_impl.h"
+#include "components/services/storage/public/mojom/storage_service.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+namespace storage {
+
+class PartitionImpl;
+
+// Implementation of the main StorageService Mojo interface. This is the root
+// owner of all Storage service instance state, managing the set of active
+// persistent and in-memory partitions.
+class StorageServiceImpl : public mojom::StorageService {
+ public:
+ explicit StorageServiceImpl(
+ mojo::PendingReceiver<mojom::StorageService> receiver);
+ ~StorageServiceImpl() override;
+
+ const auto& partitions() const { return partitions_; }
+
+ // mojom::StorageService implementation:
+ void BindPartition(const base::Optional<base::FilePath>& path,
+ mojo::PendingReceiver<mojom::Partition> receiver) override;
+
+ private:
+ friend class PartitionImpl;
+
+ // Removes a partition from the set of tracked partitions.
+ void RemovePartition(PartitionImpl* partition);
+
+ const mojo::Receiver<mojom::StorageService> receiver_;
+
+ // The set of all isolated partitions owned by the service. This includes both
+ // persistent and in-memory partitions.
+ std::set<std::unique_ptr<PartitionImpl>, base::UniquePtrComparator>
+ partitions_;
+
+ // A mapping from FilePath to the corresponding PartitionImpl instance in
+ // |partitions_|. The pointers stored here are not owned by this map and must
+ // be removed when removed from |partitions_|. Only persistent partitions have
+ // entries in this map.
+ std::map<base::FilePath, PartitionImpl*> persistent_partition_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(StorageServiceImpl);
+};
+
+} // namespace storage
+
+#endif // COMPONENTS_SERVICES_STORAGE_STORAGE_SERVICE_IMPL_H_
diff --git a/chromium/components/services/storage/storage_service_impl_unittest.cc b/chromium/components/services/storage/storage_service_impl_unittest.cc
new file mode 100644
index 00000000000..b852bbccf6c
--- /dev/null
+++ b/chromium/components/services/storage/storage_service_impl_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/storage_service_impl.h"
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/services/storage/partition_impl.h"
+#include "components/services/storage/public/mojom/partition.mojom.h"
+#include "components/services/storage/public/mojom/storage_service.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+class StorageServiceImplTest : public testing::Test {
+ public:
+ StorageServiceImplTest() = default;
+ ~StorageServiceImplTest() override = default;
+
+ protected:
+ mojom::StorageService* remote_service() { return remote_service_.get(); }
+ StorageServiceImpl& service_impl() { return service_; }
+
+ private:
+ base::test::ScopedTaskEnvironment task_environment_;
+ mojo::Remote<mojom::StorageService> remote_service_;
+ StorageServiceImpl service_{remote_service_.BindNewPipeAndPassReceiver()};
+
+ DISALLOW_COPY_AND_ASSIGN(StorageServiceImplTest);
+};
+
+TEST_F(StorageServiceImplTest, UniqueInMemoryPartitions) {
+ // Verifies that every partition client bound without a path is bound to a
+ // unique partition instance.
+
+ mojo::Remote<mojom::Partition> in_memory_partition1;
+ remote_service()->BindPartition(
+ /*path=*/base::nullopt,
+ in_memory_partition1.BindNewPipeAndPassReceiver());
+ in_memory_partition1.FlushForTesting();
+
+ EXPECT_EQ(1u, service_impl().partitions().size());
+
+ mojo::Remote<mojom::Partition> in_memory_partition2;
+ remote_service()->BindPartition(
+ base::nullopt /* path */,
+ in_memory_partition2.BindNewPipeAndPassReceiver());
+ in_memory_partition2.FlushForTesting();
+
+ EXPECT_EQ(2u, service_impl().partitions().size());
+
+ // Also verify that a new client with a provided path is unique from the above
+ // partitions.
+ base::ScopedTempDir temp_dir;
+ CHECK(temp_dir.CreateUniqueTempDir());
+
+ mojo::Remote<mojom::Partition> persistent_partition;
+ remote_service()->BindPartition(
+ temp_dir.GetPath(), persistent_partition.BindNewPipeAndPassReceiver());
+ persistent_partition.FlushForTesting();
+
+ EXPECT_EQ(3u, service_impl().partitions().size());
+}
+
+TEST_F(StorageServiceImplTest, SharedPersistentPartition) {
+ // Verifies that multiple clients can share the same persistent partition
+ // instance.
+
+ base::ScopedTempDir temp_dir;
+ CHECK(temp_dir.CreateUniqueTempDir());
+
+ mojo::Remote<mojom::Partition> client1;
+ remote_service()->BindPartition(temp_dir.GetPath(),
+ client1.BindNewPipeAndPassReceiver());
+ client1.FlushForTesting();
+
+ EXPECT_EQ(1u, service_impl().partitions().size());
+
+ mojo::Remote<mojom::Partition> client2;
+ remote_service()->BindPartition(temp_dir.GetPath(),
+ client2.BindNewPipeAndPassReceiver());
+ client2.FlushForTesting();
+
+ EXPECT_EQ(1u, service_impl().partitions().size());
+ EXPECT_TRUE(client1.is_connected());
+ EXPECT_TRUE(client2.is_connected());
+}
+
+TEST_F(StorageServiceImplTest, PartitionDestroyedOnLastClientDisconnect) {
+ base::ScopedTempDir temp_dir;
+ CHECK(temp_dir.CreateUniqueTempDir());
+
+ mojo::Remote<mojom::Partition> client1;
+ remote_service()->BindPartition(temp_dir.GetPath(),
+ client1.BindNewPipeAndPassReceiver());
+ client1.FlushForTesting();
+
+ mojo::Remote<mojom::Partition> client2;
+ remote_service()->BindPartition(temp_dir.GetPath(),
+ client2.BindNewPipeAndPassReceiver());
+ client2.FlushForTesting();
+
+ EXPECT_EQ(1u, service_impl().partitions().size());
+
+ client1.reset();
+ client2.reset();
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0u, service_impl().partitions().size());
+}
+
+TEST_F(StorageServiceImplTest, PersistentPartitionRequiresAbsolutePath) {
+ mojo::Remote<mojom::Partition> client;
+ const base::FilePath kTestRelativePath{FILE_PATH_LITERAL("invalid")};
+ remote_service()->BindPartition(kTestRelativePath,
+ client.BindNewPipeAndPassReceiver());
+
+ // We should be imminently disconnected because the BindPartition request
+ // should be ignored by the service.
+ base::RunLoop loop;
+ client.set_disconnect_handler(loop.QuitClosure());
+ loop.Run();
+
+ EXPECT_FALSE(client.is_connected());
+}
+
+} // namespace storage
diff --git a/chromium/components/services/unzip/BUILD.gn b/chromium/components/services/unzip/BUILD.gn
index e078e76dfd5..0bf7b07a463 100644
--- a/chromium/components/services/unzip/BUILD.gn
+++ b/chromium/components/services/unzip/BUILD.gn
@@ -4,8 +4,6 @@
source_set("lib") {
sources = [
- "unzip_service.cc",
- "unzip_service.h",
"unzipper_impl.cc",
"unzipper_impl.h",
]
@@ -19,7 +17,27 @@ source_set("lib") {
public_deps = [
"//components/services/filesystem/public/mojom",
"//components/services/unzip/public/mojom",
- "//services/service_manager/public/cpp",
+ ]
+}
+
+source_set("in_process") {
+ # NOTE: In-process unzipping is unsafe! Unfortunately on iOS we have no other
+ # choice. On all other platforms, this target is restricted to tests.
+ testonly = !is_ios
+
+ sources = [
+ "in_process_unzipper.cc",
+ "in_process_unzipper.h",
+ ]
+
+ deps = [
+ ":lib",
+ "//base",
+ ]
+
+ public_deps = [
+ "//components/services/unzip/public/mojom",
+ "//mojo/public/cpp/bindings",
]
}
@@ -49,7 +67,6 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/services/unzip/public/cpp",
- "//services/service_manager/public/cpp/test:test_support",
"//testing/gtest",
]
}
diff --git a/chromium/components/services/unzip/DEPS b/chromium/components/services/unzip/DEPS
index 9a39d2dce2c..c182c3ca877 100644
--- a/chromium/components/services/unzip/DEPS
+++ b/chromium/components/services/unzip/DEPS
@@ -1,6 +1,5 @@
include_rules = [
"+components/services/filesystem",
"+mojo/public",
- "+services/service_manager/public",
"+third_party/zlib/google",
]
diff --git a/chromium/components/services/unzip/OWNERS b/chromium/components/services/unzip/OWNERS
index ec81839d0ad..a761ba58ebb 100644
--- a/chromium/components/services/unzip/OWNERS
+++ b/chromium/components/services/unzip/OWNERS
@@ -1,2 +1,4 @@
sorin@chromium.org
waffles@chromium.org
+# COMPONENT: Internals>Services>ServiceManager
+# TEAM: chrome-updates-dev@chromium.org
diff --git a/chromium/components/services/unzip/content/BUILD.gn b/chromium/components/services/unzip/content/BUILD.gn
new file mode 100644
index 00000000000..a7dac3d3167
--- /dev/null
+++ b/chromium/components/services/unzip/content/BUILD.gn
@@ -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.
+
+source_set("content") {
+ sources = [
+ "unzip_service.cc",
+ "unzip_service.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/strings",
+ "//content/public/browser",
+ ]
+
+ public_deps = [
+ "//components/services/unzip/public/mojom",
+ "//mojo/public/cpp/bindings",
+ ]
+}
diff --git a/chromium/components/services/unzip/content/DEPS b/chromium/components/services/unzip/content/DEPS
new file mode 100644
index 00000000000..1c35d9ca694
--- /dev/null
+++ b/chromium/components/services/unzip/content/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+content/public/browser",
+]
diff --git a/chromium/components/services/unzip/content/unzip_service.cc b/chromium/components/services/unzip/content/unzip_service.cc
new file mode 100644
index 00000000000..31f9a824ae9
--- /dev/null
+++ b/chromium/components/services/unzip/content/unzip_service.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 "components/services/unzip/content/unzip_service.h"
+
+#include "base/no_destructor.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/service_process_host.h"
+
+namespace unzip {
+
+namespace {
+
+LaunchCallback& GetLaunchOverride() {
+ static base::NoDestructor<LaunchCallback> callback;
+ return *callback;
+}
+
+} // namespace
+
+mojo::PendingRemote<mojom::Unzipper> LaunchUnzipper() {
+ auto& launcher = GetLaunchOverride();
+ if (launcher)
+ return launcher.Run();
+
+ mojo::PendingRemote<mojom::Unzipper> remote;
+ content::ServiceProcessHost::Launch<mojom::Unzipper>(
+ remote.InitWithNewPipeAndPassReceiver(),
+ content::ServiceProcessHost::Options()
+ .WithSandboxType(service_manager::SANDBOX_TYPE_UTILITY)
+ .WithDisplayName(IDS_UNZIP_SERVICE_DISPLAY_NAME)
+ .Pass());
+ return remote;
+}
+
+void SetUnzipperLaunchOverrideForTesting(LaunchCallback callback) {
+ GetLaunchOverride() = std::move(callback);
+}
+
+} // namespace unzip
diff --git a/chromium/components/services/unzip/content/unzip_service.h b/chromium/components/services/unzip/content/unzip_service.h
new file mode 100644
index 00000000000..1ce1789324e
--- /dev/null
+++ b/chromium/components/services/unzip/content/unzip_service.h
@@ -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.
+
+#ifndef COMPONENTS_SERVICES_UNZIP_CONTENT_UNZIP_SERVICE_H_
+#define COMPONENTS_SERVICES_UNZIP_CONTENT_UNZIP_SERVICE_H_
+
+#include "base/callback.h"
+#include "components/services/unzip/public/mojom/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace unzip {
+
+// Launches a new instance of the Unzipper service in an isolated, sandboxed
+// process, and returns a remote interface to control the service. The lifetime
+// of the process is tied to that of the Remote. May be called from any thread.
+mojo::PendingRemote<mojom::Unzipper> LaunchUnzipper();
+
+// Overrides the logic used by |LaunchUnzipper()| to produce a remote Unzipper,
+// allowing tests to set up an in-process instance to be used instead of an
+// out-of-process instance.
+using LaunchCallback =
+ base::RepeatingCallback<mojo::PendingRemote<mojom::Unzipper>()>;
+void SetUnzipperLaunchOverrideForTesting(LaunchCallback callback);
+
+} // namespace unzip
+
+#endif // COMPONENTS_SERVICES_UNZIP_CONTENT_UNZIP_SERVICE_H_
diff --git a/chromium/components/services/unzip/in_process_unzipper.cc b/chromium/components/services/unzip/in_process_unzipper.cc
new file mode 100644
index 00000000000..0ca9b5b10c2
--- /dev/null
+++ b/chromium/components/services/unzip/in_process_unzipper.cc
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/unzip/in_process_unzipper.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "components/services/unzip/unzipper_impl.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+
+namespace unzip {
+
+namespace {
+
+void BindInProcessUnzipper(mojo::PendingReceiver<mojom::Unzipper> receiver) {
+ mojo::MakeSelfOwnedReceiver(std::make_unique<UnzipperImpl>(),
+ std::move(receiver));
+}
+
+} // namespace
+
+mojo::PendingRemote<mojom::Unzipper> LaunchInProcessUnzipper() {
+ mojo::PendingRemote<mojom::Unzipper> remote;
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives()})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(&BindInProcessUnzipper,
+ remote.InitWithNewPipeAndPassReceiver()));
+ return remote;
+}
+
+} // namespace unzip
diff --git a/chromium/components/services/unzip/in_process_unzipper.h b/chromium/components/services/unzip/in_process_unzipper.h
new file mode 100644
index 00000000000..1669fba7c2f
--- /dev/null
+++ b/chromium/components/services/unzip/in_process_unzipper.h
@@ -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.
+
+#ifndef COMPONENTS_SERVICES_UNZIP_IN_PROCESS_UNZIPPER_H_
+#define COMPONENTS_SERVICES_UNZIP_IN_PROCESS_UNZIPPER_H_
+
+#include "components/services/unzip/public/mojom/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+
+namespace unzip {
+
+// Creates an in-process instance of the Unzipper service on a background
+// sequence and returns a PendingRemote which can be bound to communicate with
+// the service. This should only be used for testing environments or other
+// runtimes where multiprocess is infeasible, such as iOS, or Content
+// dependencies are not allowed.
+mojo::PendingRemote<mojom::Unzipper> LaunchInProcessUnzipper();
+
+} // namespace unzip
+
+#endif // COMPONENTS_SERVICES_UNZIP_IN_PROCESS_UNZIPPER_H_
diff --git a/chromium/components/services/unzip/public/cpp/BUILD.gn b/chromium/components/services/unzip/public/cpp/BUILD.gn
index 87709d4f358..148d110d520 100644
--- a/chromium/components/services/unzip/public/cpp/BUILD.gn
+++ b/chromium/components/services/unzip/public/cpp/BUILD.gn
@@ -13,35 +13,5 @@ source_set("cpp") {
public_deps = [
"//components/services/filesystem:lib",
"//components/services/unzip/public/mojom",
- "//services/service_manager/public/cpp",
- ]
-}
-
-static_library("test_support") {
- testonly = true
- sources = [
- "test_unzip_service.cc",
- "test_unzip_service.h",
- ]
-
- deps = [
- ":cpp",
- "//base",
- "//components/services/unzip:lib",
- "//services/service_manager/public/cpp/test:test_support",
- ]
-}
-
-source_set("manifest") {
- sources = [
- "manifest.cc",
- "manifest.h",
- ]
-
- deps = [
- "//base",
- "//components/services/unzip/public/mojom",
- "//components/strings",
- "//services/service_manager/public/cpp",
]
}
diff --git a/chromium/components/services/unzip/public/cpp/OWNERS b/chromium/components/services/unzip/public/cpp/OWNERS
deleted file mode 100644
index 6faeaa4752f..00000000000
--- a/chromium/components/services/unzip/public/cpp/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/services/unzip/public/cpp/manifest.cc b/chromium/components/services/unzip/public/cpp/manifest.cc
deleted file mode 100644
index 6eb82dc5648..00000000000
--- a/chromium/components/services/unzip/public/cpp/manifest.cc
+++ /dev/null
@@ -1,40 +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 "components/services/unzip/public/cpp/manifest.h"
-
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "components/services/unzip/public/mojom/constants.mojom.h"
-#include "components/services/unzip/public/mojom/unzipper.mojom.h"
-#include "components/strings/grit/components_strings.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-
-namespace unzip {
-
-const service_manager::Manifest& GetManifest() {
- static base::NoDestructor<service_manager::Manifest> manifest{
- service_manager::ManifestBuilder()
- .WithServiceName(mojom::kServiceName)
- .WithDisplayName(IDS_UNZIP_SERVICE_DISPLAY_NAME)
- .WithOptions(
- service_manager::ManifestOptionsBuilder()
-#if !defined(OS_IOS)
- .WithExecutionMode(service_manager::Manifest::ExecutionMode::
- kOutOfProcessBuiltin)
-#endif // !defined(OS_IOS)
- .WithSandboxType("utility")
- .WithInstanceSharingPolicy(
- service_manager::Manifest::InstanceSharingPolicy::
- kSharedAcrossGroups)
- .Build())
- .ExposeCapability(
- "unzip_file",
- service_manager::Manifest::InterfaceList<mojom::Unzipper>())
- .Build()
- };
- return *manifest;
-}
-
-} // namespace unzip
diff --git a/chromium/components/services/unzip/public/cpp/manifest.h b/chromium/components/services/unzip/public/cpp/manifest.h
deleted file mode 100644
index b17b2a186bd..00000000000
--- a/chromium/components/services/unzip/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_MANIFEST_H_
-#define COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace unzip {
-
-const service_manager::Manifest& GetManifest();
-
-} // namespace unzip
-
-#endif // COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_MANIFEST_H_
diff --git a/chromium/components/services/unzip/public/cpp/test_unzip_service.cc b/chromium/components/services/unzip/public/cpp/test_unzip_service.cc
deleted file mode 100644
index 572bbb605bf..00000000000
--- a/chromium/components/services/unzip/public/cpp/test_unzip_service.cc
+++ /dev/null
@@ -1,41 +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 "components/services/unzip/public/cpp/test_unzip_service.h"
-
-#include "components/services/filesystem/public/mojom/directory.mojom.h"
-
-namespace unzip {
-
-CrashyUnzipService::CrashyUnzipService(
- service_manager::mojom::ServiceRequest request)
- : binding_(this, std::move(request)) {}
-
-CrashyUnzipService::~CrashyUnzipService() = default;
-
-void CrashyUnzipService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- DCHECK(interface_name == mojom::Unzipper::Name_);
- DCHECK(!unzipper_binding_);
- unzipper_binding_ = std::make_unique<mojo::Binding<mojom::Unzipper>>(
- this, mojom::UnzipperRequest(std::move(interface_pipe)));
-}
-
-void CrashyUnzipService::Unzip(base::File zip_file,
- filesystem::mojom::DirectoryPtr output_dir,
- UnzipCallback callback) {
- unzipper_binding_.reset();
-}
-
-void CrashyUnzipService::UnzipWithFilter(
- base::File zip_file,
- filesystem::mojom::DirectoryPtr output_dir,
- mojom::UnzipFilterPtr filter,
- UnzipWithFilterCallback callback) {
- unzipper_binding_.reset();
-}
-
-} // namespace unzip
diff --git a/chromium/components/services/unzip/public/cpp/test_unzip_service.h b/chromium/components/services/unzip/public/cpp/test_unzip_service.h
deleted file mode 100644
index add69f3d3eb..00000000000
--- a/chromium/components/services/unzip/public/cpp/test_unzip_service.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_TEST_UNZIP_SERVICE_H_
-#define COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_TEST_UNZIP_SERVICE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/services/unzip/public/mojom/unzipper.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-
-namespace unzip {
-
-// An implementation of the UnzipService that closes the connection when
-// a call is made on the Unzipper interface.
-// Can be used with a TestConnectorFactory to simulate crashes in the service
-// while processing a call.
-class CrashyUnzipService : public service_manager::Service,
- public mojom::Unzipper {
- public:
- explicit CrashyUnzipService(service_manager::mojom::ServiceRequest request);
- ~CrashyUnzipService() override;
-
- // service_manager::Service:
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- // unzip::mojom::Unzipper:
- void Unzip(base::File zip_file,
- filesystem::mojom::DirectoryPtr output_dir,
- UnzipCallback callback) override;
- void UnzipWithFilter(base::File zip_file,
- filesystem::mojom::DirectoryPtr output_dir,
- mojom::UnzipFilterPtr filter,
- UnzipWithFilterCallback callback) override;
-
- private:
- service_manager::ServiceBinding binding_;
- std::unique_ptr<mojo::Binding<mojom::Unzipper>> unzipper_binding_;
-
- DISALLOW_COPY_AND_ASSIGN(CrashyUnzipService);
-};
-
-} // namespace unzip
-
-#endif // COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_TEST_UNZIP_SERVICE_H_
diff --git a/chromium/components/services/unzip/public/cpp/unzip.cc b/chromium/components/services/unzip/public/cpp/unzip.cc
index 7c66deca013..5e8ffb3b497 100644
--- a/chromium/components/services/unzip/public/cpp/unzip.cc
+++ b/chromium/components/services/unzip/public/cpp/unzip.cc
@@ -18,10 +18,9 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/services/filesystem/directory_impl.h"
#include "components/services/filesystem/lock_table.h"
-#include "components/services/unzip/public/mojom/constants.mojom.h"
#include "components/services/unzip/public/mojom/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/service_manager/public/cpp/connector.h"
namespace unzip {
@@ -49,7 +48,7 @@ class UnzipFilter : public unzip::mojom::UnzipFilter {
class UnzipParams : public base::RefCounted<UnzipParams> {
public:
UnzipParams(
- mojom::UnzipperPtr unzipper,
+ mojo::PendingRemote<mojom::Unzipper> unzipper,
const scoped_refptr<base::SequencedTaskRunner>& callback_task_runner,
UnzipCallback callback,
const scoped_refptr<base::SequencedTaskRunner>&
@@ -59,7 +58,7 @@ class UnzipParams : public base::RefCounted<UnzipParams> {
callback_(std::move(callback)),
background_task_runner_keep_alive_(background_task_runner_keep_alive) {}
- mojom::UnzipperPtr* unzipper() { return &unzipper_; }
+ mojo::Remote<mojom::Unzipper>& unzipper() { return unzipper_; }
void InvokeCallback(bool result) {
if (callback_) {
@@ -77,9 +76,9 @@ class UnzipParams : public base::RefCounted<UnzipParams> {
~UnzipParams() = default;
- // The UnzipperPtr and UnzipFilter are stored so they do not get deleted
- // before the callback runs.
- mojom::UnzipperPtr unzipper_;
+ // The Remote and UnzipFilter are stored so they do not get deleted before the
+ // callback runs.
+ mojo::Remote<mojom::Unzipper> unzipper_;
std::unique_ptr<UnzipFilter> filter_;
scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
@@ -92,11 +91,11 @@ class UnzipParams : public base::RefCounted<UnzipParams> {
void UnzipDone(scoped_refptr<UnzipParams> params, bool success) {
params->InvokeCallback(success);
- params->unzipper()->reset();
+ params->unzipper().reset();
}
void DoUnzipWithFilter(
- std::unique_ptr<service_manager::Connector> connector,
+ mojo::PendingRemote<mojom::Unzipper> unzipper,
const base::FilePath& zip_path,
const base::FilePath& output_dir,
const scoped_refptr<base::SequencedTaskRunner>& callback_task_runner,
@@ -117,9 +116,6 @@ void DoUnzipWithFilter(
std::make_unique<filesystem::DirectoryImpl>(output_dir, nullptr, nullptr),
mojo::MakeRequest(&directory_ptr));
- mojom::UnzipperPtr unzipper;
- connector->BindInterface(mojom::kServiceName, mojo::MakeRequest(&unzipper));
-
// |result_callback| is shared between the connection error handler and the
// Unzip call using a refcounted UnzipParams object that owns
// |result_callback|.
@@ -127,13 +123,13 @@ void DoUnzipWithFilter(
std::move(unzipper), callback_task_runner, std::move(result_callback),
background_task_runner_keep_alive);
- unzip_params->unzipper()->set_connection_error_handler(
- base::BindRepeating(&UnzipDone, unzip_params, false));
+ unzip_params->unzipper().set_disconnect_handler(
+ base::BindOnce(&UnzipDone, unzip_params, false));
if (filter_callback.is_null()) {
- (*unzip_params->unzipper())
- ->Unzip(std::move(zip_file), std::move(directory_ptr),
- base::BindOnce(&UnzipDone, unzip_params));
+ unzip_params->unzipper()->Unzip(std::move(zip_file),
+ std::move(directory_ptr),
+ base::BindOnce(&UnzipDone, unzip_params));
return;
}
@@ -141,23 +137,22 @@ void DoUnzipWithFilter(
unzip_params->set_unzip_filter(std::make_unique<UnzipFilter>(
mojo::MakeRequest(&unzip_filter_ptr), filter_callback));
- (*unzip_params->unzipper())
- ->UnzipWithFilter(std::move(zip_file), std::move(directory_ptr),
- std::move(unzip_filter_ptr),
- base::BindOnce(&UnzipDone, unzip_params));
+ unzip_params->unzipper()->UnzipWithFilter(
+ std::move(zip_file), std::move(directory_ptr),
+ std::move(unzip_filter_ptr), base::BindOnce(&UnzipDone, unzip_params));
}
} // namespace
-void Unzip(std::unique_ptr<service_manager::Connector> connector,
+void Unzip(mojo::PendingRemote<mojom::Unzipper> unzipper,
const base::FilePath& zip_path,
const base::FilePath& output_dir,
UnzipCallback callback) {
- UnzipWithFilter(std::move(connector), zip_path, output_dir,
+ UnzipWithFilter(std::move(unzipper), zip_path, output_dir,
UnzipFilterCallback(), std::move(callback));
}
-void UnzipWithFilter(std::unique_ptr<service_manager::Connector> connector,
+void UnzipWithFilter(mojo::PendingRemote<mojom::Unzipper> unzipper,
const base::FilePath& zip_path,
const base::FilePath& output_dir,
UnzipFilterCallback filter_callback,
@@ -165,12 +160,12 @@ void UnzipWithFilter(std::unique_ptr<service_manager::Connector> connector,
DCHECK(!result_callback.is_null());
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::TaskPriority::USER_VISIBLE, base::MayBlock(),
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+ base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
background_task_runner->PostTask(
FROM_HERE,
- base::BindOnce(&DoUnzipWithFilter, std::move(connector), zip_path,
+ base::BindOnce(&DoUnzipWithFilter, std::move(unzipper), zip_path,
output_dir, base::SequencedTaskRunnerHandle::Get(),
filter_callback, std::move(result_callback),
background_task_runner));
diff --git a/chromium/components/services/unzip/public/cpp/unzip.h b/chromium/components/services/unzip/public/cpp/unzip.h
index 2743df1b042..f7926ba83dc 100644
--- a/chromium/components/services/unzip/public/cpp/unzip.h
+++ b/chromium/components/services/unzip/public/cpp/unzip.h
@@ -8,20 +8,18 @@
#include <memory>
#include "base/callback_forward.h"
+#include "components/services/unzip/public/mojom/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
namespace base {
class FilePath;
}
-namespace service_manager {
-class Connector;
-}
-
namespace unzip {
// Unzips |zip_file| into |output_dir|.
using UnzipCallback = base::OnceCallback<void(bool result)>;
-void Unzip(std::unique_ptr<service_manager::Connector> connector,
+void Unzip(mojo::PendingRemote<mojom::Unzipper> unzipper,
const base::FilePath& zip_file,
const base::FilePath& output_dir,
UnzipCallback result_callback);
@@ -30,7 +28,7 @@ void Unzip(std::unique_ptr<service_manager::Connector> connector,
// Note that |filter_callback| may be invoked from a background thread.
using UnzipFilterCallback =
base::RepeatingCallback<bool(const base::FilePath& path)>;
-void UnzipWithFilter(std::unique_ptr<service_manager::Connector> connector,
+void UnzipWithFilter(mojo::PendingRemote<mojom::Unzipper> unzipper,
const base::FilePath& zip_file,
const base::FilePath& output_dir,
UnzipFilterCallback filter_callback,
diff --git a/chromium/components/services/unzip/public/cpp/unzip_unittest.cc b/chromium/components/services/unzip/public/cpp/unzip_unittest.cc
index c5166bc7eb3..ccb9053207a 100644
--- a/chromium/components/services/unzip/public/cpp/unzip_unittest.cc
+++ b/chromium/components/services/unzip/public/cpp/unzip_unittest.cc
@@ -12,10 +12,9 @@
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "components/services/unzip/public/mojom/constants.mojom.h"
-#include "components/services/unzip/unzip_service.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
+#include "base/test/task_environment.h"
+#include "components/services/unzip/unzipper_impl.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace unzip {
@@ -60,9 +59,7 @@ void CountFiles(const base::FilePath& dir,
class UnzipTest : public testing::Test {
public:
- UnzipTest()
- : unzip_service_(
- connector_factory_.RegisterInstance(unzip::mojom::kServiceName)) {}
+ UnzipTest() = default;
~UnzipTest() override = default;
// Unzips |zip_file| into |output_dir| and returns true if the unzip was
@@ -77,8 +74,8 @@ class UnzipTest : public testing::Test {
bool DoUnzipWithFilter(const base::FilePath& zip_file,
const base::FilePath& output_dir,
UnzipFilterCallback filter_callback) {
- std::unique_ptr<service_manager::Connector> connector =
- connector_factory_.CreateConnector()->Clone();
+ mojo::PendingRemote<mojom::Unzipper> unzipper;
+ receivers_.Add(&unzipper_, unzipper.InitWithNewPipeAndPassReceiver());
base::RunLoop run_loop;
bool result = false;
@@ -91,10 +88,10 @@ class UnzipTest : public testing::Test {
run_loop.QuitClosure(), &result);
if (filter_callback) {
- UnzipWithFilter(std::move(connector), zip_file, output_dir,
+ UnzipWithFilter(std::move(unzipper), zip_file, output_dir,
std::move(filter_callback), std::move(result_callback));
} else {
- Unzip(std::move(connector), zip_file, output_dir,
+ Unzip(std::move(unzipper), zip_file, output_dir,
std::move(result_callback));
}
run_loop.Run();
@@ -107,13 +104,13 @@ class UnzipTest : public testing::Test {
unzip_dir_ = temp_dir_.GetPath();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
base::FilePath unzip_dir_;
- service_manager::TestConnectorFactory connector_factory_;
- unzip::UnzipService unzip_service_;
+ unzip::UnzipperImpl unzipper_;
+ mojo::ReceiverSet<mojom::Unzipper> receivers_;
};
TEST_F(UnzipTest, UnzipBadArchive) {
diff --git a/chromium/components/services/unzip/public/mojom/BUILD.gn b/chromium/components/services/unzip/public/mojom/BUILD.gn
index 9b16b8a0b1f..88db8d34b44 100644
--- a/chromium/components/services/unzip/public/mojom/BUILD.gn
+++ b/chromium/components/services/unzip/public/mojom/BUILD.gn
@@ -10,14 +10,7 @@ mojom("mojom") {
]
public_deps = [
- ":constants",
"//components/services/filesystem/public/mojom",
"//mojo/public/mojom/base",
]
}
-
-mojom("constants") {
- sources = [
- "constants.mojom",
- ]
-}
diff --git a/chromium/components/services/unzip/public/mojom/constants.mojom b/chromium/components/services/unzip/public/mojom/constants.mojom
deleted file mode 100644
index 6cf09d156b6..00000000000
--- a/chromium/components/services/unzip/public/mojom/constants.mojom
+++ /dev/null
@@ -1,7 +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.
-
-module unzip.mojom;
-
-const string kServiceName = "unzip_service";
diff --git a/chromium/components/services/unzip/unzip_service.cc b/chromium/components/services/unzip/unzip_service.cc
deleted file mode 100644
index 66936a5babd..00000000000
--- a/chromium/components/services/unzip/unzip_service.cc
+++ /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.
-
-#include "components/services/unzip/unzip_service.h"
-
-#include "components/services/unzip/unzipper_impl.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace unzip {
-
-UnzipService::UnzipService(service_manager::mojom::ServiceRequest request)
- : binding_(this, std::move(request)),
- keepalive_(&binding_, base::TimeDelta::FromSeconds(0)) {}
-
-UnzipService::~UnzipService() = default;
-
-void UnzipService::OnBindInterface(
- const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) {
- if (interface_name == unzip::mojom::Unzipper::Name_) {
- mojo::MakeStrongBinding(
- std::make_unique<UnzipperImpl>(keepalive_.CreateRef()),
- unzip::mojom::UnzipperRequest(std::move(interface_pipe)));
- }
-}
-
-} // namespace unzip
diff --git a/chromium/components/services/unzip/unzip_service.h b/chromium/components/services/unzip/unzip_service.h
deleted file mode 100644
index bd3b34c92f6..00000000000
--- a/chromium/components/services/unzip/unzip_service.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SERVICES_UNZIP_UNZIP_SERVICE_H_
-#define COMPONENTS_SERVICES_UNZIP_UNZIP_SERVICE_H_
-
-#include "base/macros.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-
-namespace unzip {
-
-class UnzipService : public service_manager::Service {
- public:
- explicit UnzipService(service_manager::mojom::ServiceRequest request);
- ~UnzipService() override;
-
- private:
- // service_manager::Service:
- void OnBindInterface(const service_manager::BindSourceInfo& source_info,
- const std::string& interface_name,
- mojo::ScopedMessagePipeHandle interface_pipe) override;
-
- service_manager::ServiceBinding binding_;
- service_manager::ServiceKeepalive keepalive_;
-
- DISALLOW_COPY_AND_ASSIGN(UnzipService);
-};
-
-} // namespace unzip
-
-#endif // COMPONENTS_SERVICES_UNZIP_UNZIP_SERVICE_H_
diff --git a/chromium/components/services/unzip/unzipper_impl.cc b/chromium/components/services/unzip/unzipper_impl.cc
index eefdc200574..76b8a50810d 100644
--- a/chromium/components/services/unzip/unzipper_impl.cc
+++ b/chromium/components/services/unzip/unzipper_impl.cc
@@ -99,9 +99,10 @@ bool FilterWithFilterPtr(mojom::UnzipFilterPtr* filter,
} // namespace
-UnzipperImpl::UnzipperImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref)
- : service_ref_(std::move(service_ref)) {}
+UnzipperImpl::UnzipperImpl() = default;
+
+UnzipperImpl::UnzipperImpl(mojo::PendingReceiver<mojom::Unzipper> receiver)
+ : receiver_(this, std::move(receiver)) {}
UnzipperImpl::~UnzipperImpl() = default;
diff --git a/chromium/components/services/unzip/unzipper_impl.h b/chromium/components/services/unzip/unzipper_impl.h
index a9764867ae6..d5cc821e78c 100644
--- a/chromium/components/services/unzip/unzipper_impl.h
+++ b/chromium/components/services/unzip/unzipper_impl.h
@@ -10,14 +10,20 @@
#include "base/files/file.h"
#include "base/macros.h"
#include "components/services/unzip/public/mojom/unzipper.mojom.h"
-#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
namespace unzip {
class UnzipperImpl : public mojom::Unzipper {
public:
- explicit UnzipperImpl(
- std::unique_ptr<service_manager::ServiceContextRef> service_ref);
+ // Constructs an UnzipperImpl which will be bound to some externally owned
+ // Receiver, such as through |mojo::MakeSelfOwnedReceiver()|.
+ UnzipperImpl();
+
+ // Constructs an UnzipperImpl bound to |receiver|.
+ explicit UnzipperImpl(mojo::PendingReceiver<mojom::Unzipper> receiver);
+
~UnzipperImpl() override;
private:
@@ -31,7 +37,7 @@ class UnzipperImpl : public mojom::Unzipper {
mojom::UnzipFilterPtr filter,
UnzipWithFilterCallback callback) override;
- const std::unique_ptr<service_manager::ServiceContextRef> service_ref_;
+ mojo::Receiver<mojom::Unzipper> receiver_{this};
DISALLOW_COPY_AND_ASSIGN(UnzipperImpl);
};
diff --git a/chromium/components/session_manager/OWNERS b/chromium/components/session_manager/OWNERS
index b280edc9c78..22db12badbd 100644
--- a/chromium/components/session_manager/OWNERS
+++ b/chromium/components/session_manager/OWNERS
@@ -1,3 +1,4 @@
achuith@chromium.org
alemate@chromium.org
xiyuan@chromium.org
+# COMPONENT: UI>Shell
diff --git a/chromium/components/session_manager/core/OWNERS b/chromium/components/session_manager/core/OWNERS
new file mode 100644
index 00000000000..036a36bd6e6
--- /dev/null
+++ b/chromium/components/session_manager/core/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: UI>Shell
diff --git a/chromium/components/session_manager/core/session_manager.cc b/chromium/components/session_manager/core/session_manager.cc
index ed4a6565668..8d7eff9a65d 100644
--- a/chromium/components/session_manager/core/session_manager.cc
+++ b/chromium/components/session_manager/core/session_manager.cc
@@ -24,9 +24,6 @@ SessionManager::SessionManager() {
SessionManager::~SessionManager() {
DCHECK_EQ(instance, this);
SessionManager::SetInstance(nullptr);
-
- for (auto& observer : observers_)
- observer.OnSessionManagerDestroyed();
}
// static
@@ -70,14 +67,11 @@ bool SessionManager::IsSessionStarted() const {
}
void SessionManager::SessionStarted() {
- if (session_started_)
- return;
-
session_started_ = true;
- // SessionStarted() could be called in tests without any session created.
- if (sessions_.size() == 1)
- NotifyPrimaryUserSessionStarted();
+ bool is_primary = sessions_.size() == 1;
+ for (auto& observer : observers_)
+ observer.OnUserSessionStarted(is_primary);
}
bool SessionManager::HasSessionForAccountId(
@@ -113,11 +107,6 @@ void SessionManager::NotifyUserProfileLoaded(const AccountId& account_id) {
observer.OnUserProfileLoaded(account_id);
}
-void SessionManager::NotifyPrimaryUserSessionStarted() {
- for (auto& observer : observers_)
- observer.OnPrimaryUserSessionStarted();
-}
-
void SessionManager::NotifyUserLoggedIn(const AccountId& user_account_id,
const std::string& user_id_hash,
bool browser_restart,
diff --git a/chromium/components/session_manager/core/session_manager.h b/chromium/components/session_manager/core/session_manager.h
index 2414f048aef..27a7bfad23c 100644
--- a/chromium/components/session_manager/core/session_manager.h
+++ b/chromium/components/session_manager/core/session_manager.h
@@ -64,7 +64,6 @@ class SESSION_EXPORT SessionManager {
// Various helpers to notify observers.
void NotifyUserProfileLoaded(const AccountId& account_id);
- void NotifyPrimaryUserSessionStarted();
SessionState session_state() const { return session_state_; }
const std::vector<Session>& sessions() const { return sessions_; }
diff --git a/chromium/components/session_manager/core/session_manager_observer.h b/chromium/components/session_manager/core/session_manager_observer.h
index 98317fa46ba..a7516f28800 100644
--- a/chromium/components/session_manager/core/session_manager_observer.h
+++ b/chromium/components/session_manager/core/session_manager_observer.h
@@ -16,17 +16,18 @@ namespace session_manager {
// http://crbug.com/657149.
class SessionManagerObserver : public base::CheckedObserver {
public:
- // Inovked when session manager is destroyed.
- virtual void OnSessionManagerDestroyed() {}
-
// Invoked when session state is changed.
virtual void OnSessionStateChanged() {}
// Invoked when a user profile is loaded.
virtual void OnUserProfileLoaded(const AccountId& account_id) {}
- // Invoked when the primary user session is started.
- virtual void OnPrimaryUserSessionStarted() {}
+ // Invoked when a user session is started. If this is a new user on the
+ // machine this will not be called until after post-login steps are finished
+ // (for example a profile picture has been selected). In contrast,
+ // UserSessionStateObserver::OnActiveUserChanged() is invoked immediately
+ // after the user has logged in.
+ virtual void OnUserSessionStarted(bool is_primary_user) {}
};
} // namespace session_manager
diff --git a/chromium/components/sessions/BUILD.gn b/chromium/components/sessions/BUILD.gn
index 3c722bacb05..ff1e1c087cb 100644
--- a/chromium/components/sessions/BUILD.gn
+++ b/chromium/components/sessions/BUILD.gn
@@ -111,6 +111,7 @@ source_set("shared") {
public_deps = [
"//components/keyed_service/core",
+ "//skia",
]
deps = [
@@ -150,6 +151,17 @@ static_library("test_support") {
"core/base_session_service_test_helper.h",
]
}
+
+ if (!is_ios) {
+ sources += [
+ "content/content_test_helper.cc",
+ "content/content_test_helper.h",
+ ]
+ deps += [
+ "//content/public/browser",
+ "//content/public/common",
+ ]
+ }
}
source_set("unit_tests") {
diff --git a/chromium/components/sessions/OWNERS b/chromium/components/sessions/OWNERS
index 28a63b1ec6d..8ba53253f2c 100644
--- a/chromium/components/sessions/OWNERS
+++ b/chromium/components/sessions/OWNERS
@@ -1,3 +1,4 @@
sky@chromium.org
skuhne@chromium.org
+# COMPONENT: Services>Sync
diff --git a/chromium/components/sessions/content/OWNERS b/chromium/components/sessions/content/OWNERS
new file mode 100644
index 00000000000..dd4c58a6718
--- /dev/null
+++ b/chromium/components/sessions/content/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: UI>Browser>Sessions
diff --git a/chromium/components/sessions/content/content_test_helper.cc b/chromium/components/sessions/content/content_test_helper.cc
new file mode 100644
index 00000000000..5eda9133c9c
--- /dev/null
+++ b/chromium/components/sessions/content/content_test_helper.cc
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sessions/content/content_test_helper.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "components/sessions/content/content_serialized_navigation_builder.h"
+#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/common/referrer.h"
+#include "url/gurl.h"
+
+namespace sessions {
+
+// static
+SerializedNavigationEntry ContentTestHelper::CreateNavigation(
+ const std::string& virtual_url,
+ const std::string& title) {
+ std::unique_ptr<content::NavigationEntry> navigation_entry =
+ content::NavigationEntry::Create();
+ navigation_entry->SetReferrer(
+ content::Referrer(GURL("http://www.referrer.com"),
+ network::mojom::ReferrerPolicy::kDefault));
+ navigation_entry->SetURL(GURL(virtual_url));
+ navigation_entry->SetVirtualURL(GURL(virtual_url));
+ navigation_entry->SetTitle(base::UTF8ToUTF16(title));
+ navigation_entry->SetTimestamp(base::Time::Now());
+ navigation_entry->SetHttpStatusCode(200);
+ return ContentSerializedNavigationBuilder::FromNavigationEntry(
+ test_data::kIndex, navigation_entry.get());
+}
+
+} // namespace sessions
diff --git a/chromium/components/sessions/content/content_test_helper.h b/chromium/components/sessions/content/content_test_helper.h
new file mode 100644
index 00000000000..59711f15325
--- /dev/null
+++ b/chromium/components/sessions/content/content_test_helper.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 COMPONENTS_SESSIONS_CONTENT_CONTENT_TEST_HELPER_H_
+#define COMPONENTS_SESSIONS_CONTENT_CONTENT_TEST_HELPER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/sessions/core/serialized_navigation_entry.h"
+
+namespace sessions {
+
+// Set of test functions to manipulate a SerializedNavigationEntry.
+class ContentTestHelper {
+ public:
+ // Creates a SerializedNavigationEntry with the given URL and title and some
+ // common values for the other fields.
+ static SerializedNavigationEntry CreateNavigation(
+ const std::string& virtual_url,
+ const std::string& title);
+
+ private:
+ // Only static methods.
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ContentTestHelper);
+};
+
+} // namespace sessions
+
+#endif // COMPONENTS_SESSIONS_CONTENT_CONTENT_TEST_HELPER_H_
diff --git a/chromium/components/sessions/core/DEPS b/chromium/components/sessions/core/DEPS
index f2ecd68b07c..6c0a29aa7f7 100644
--- a/chromium/components/sessions/core/DEPS
+++ b/chromium/components/sessions/core/DEPS
@@ -1,4 +1,7 @@
include_rules = [
"+components/keyed_service/core",
"+components/prefs",
+
+ # SkColor is referenced in a struct in session_types.h
+ "+third_party/skia/include/core/SkColor.h",
]
diff --git a/chromium/components/sessions/core/base_session_service.cc b/chromium/components/sessions/core/base_session_service.cc
index 9c03e6084c3..bbf50c6fd71 100644
--- a/chromium/components/sessions/core/base_session_service.cc
+++ b/chromium/components/sessions/core/base_session_service.cc
@@ -55,8 +55,9 @@ BaseSessionService::BaseSessionService(SessionType type,
: pending_reset_(false),
commands_since_reset_(0),
delegate_(delegate),
- backend_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {
+ backend_task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {
backend_ = new SessionBackend(type, path);
DCHECK(backend_);
}
diff --git a/chromium/components/sessions/core/serialized_navigation_entry_test_helper.cc b/chromium/components/sessions/core/serialized_navigation_entry_test_helper.cc
index a78f63cf568..f5f08bce64f 100644
--- a/chromium/components/sessions/core/serialized_navigation_entry_test_helper.cc
+++ b/chromium/components/sessions/core/serialized_navigation_entry_test_helper.cc
@@ -68,21 +68,6 @@ void SerializedNavigationEntryTestHelper::ExpectNavigationEquals(
}
// static
-SerializedNavigationEntry SerializedNavigationEntryTestHelper::CreateNavigation(
- const std::string& virtual_url,
- const std::string& title) {
- SerializedNavigationEntry navigation;
- navigation.index_ = 0;
- navigation.referrer_url_ = GURL("http://www.referrer.com");
- navigation.virtual_url_ = GURL(virtual_url);
- navigation.title_ = base::UTF8ToUTF16(title);
- navigation.encoded_page_state_ = "fake state";
- navigation.timestamp_ = base::Time::Now();
- navigation.http_status_code_ = 200;
- return navigation;
-}
-
-// static
SerializedNavigationEntry
SerializedNavigationEntryTestHelper::CreateNavigationForTest() {
SerializedNavigationEntry navigation;
diff --git a/chromium/components/sessions/core/serialized_navigation_entry_test_helper.h b/chromium/components/sessions/core/serialized_navigation_entry_test_helper.h
index aa770c6e0c4..606b235859a 100644
--- a/chromium/components/sessions/core/serialized_navigation_entry_test_helper.h
+++ b/chromium/components/sessions/core/serialized_navigation_entry_test_helper.h
@@ -62,12 +62,6 @@ class SerializedNavigationEntryTestHelper {
static void ExpectNavigationEquals(const SerializedNavigationEntry& expected,
const SerializedNavigationEntry& actual);
- // Creates a SerializedNavigationEntry with the given URL and title and some
- // common values for the other fields.
- static SerializedNavigationEntry CreateNavigation(
- const std::string& virtual_url,
- const std::string& title);
-
// Creates a SerializedNavigationEntry using the |test_data| constants above.
static SerializedNavigationEntry CreateNavigationForTest();
diff --git a/chromium/components/sessions/core/session_command.cc b/chromium/components/sessions/core/session_command.cc
index 0f38cf79002..706233229be 100644
--- a/chromium/components/sessions/core/session_command.cc
+++ b/chromium/components/sessions/core/session_command.cc
@@ -28,8 +28,8 @@ bool SessionCommand::GetPayload(void* dest, size_t count) const {
return true;
}
-base::Pickle* SessionCommand::PayloadAsPickle() const {
- return new base::Pickle(contents(), static_cast<int>(size()));
+std::unique_ptr<base::Pickle> SessionCommand::PayloadAsPickle() const {
+ return std::make_unique<base::Pickle>(contents(), static_cast<int>(size()));
}
} // namespace sessions
diff --git a/chromium/components/sessions/core/session_command.h b/chromium/components/sessions/core/session_command.h
index 54d19e4beac..e5f766369ae 100644
--- a/chromium/components/sessions/core/session_command.h
+++ b/chromium/components/sessions/core/session_command.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/macros.h"
@@ -60,11 +61,10 @@ class SESSIONS_EXPORT SessionCommand {
// count is not equal to the size of data this command contains.
bool GetPayload(void* dest, size_t count) const;
- // Returns the contents as a pickle. It is up to the caller to delete the
- // returned Pickle. The returned Pickle references the underlying data of
- // this SessionCommand. If you need it to outlive the command, copy the
- // pickle.
- base::Pickle* PayloadAsPickle() const;
+ // Returns the contents as a pickle. The returned Pickle references the
+ // underlying data of this SessionCommand. If you need it to outlive the
+ // command, copy the pickle.
+ std::unique_ptr<base::Pickle> PayloadAsPickle() const;
private:
const id_type id_;
diff --git a/chromium/components/sessions/core/session_service_commands.cc b/chromium/components/sessions/core/session_service_commands.cc
index 99a3301af09..e232d5c6e7f 100644
--- a/chromium/components/sessions/core/session_service_commands.cc
+++ b/chromium/components/sessions/core/session_service_commands.cc
@@ -10,6 +10,7 @@
#include <utility>
#include <vector>
+#include "base/containers/flat_set.h"
#include "base/memory/ptr_util.h"
#include "base/pickle.h"
#include "base/token.h"
@@ -58,6 +59,7 @@ static const SessionCommand::id_type kCommandLastActiveTime = 21;
static const SessionCommand::id_type kCommandSetWindowWorkspace2 = 23;
static const SessionCommand::id_type kCommandTabNavigationPathPruned = 24;
static const SessionCommand::id_type kCommandSetTabGroup = 25;
+static const SessionCommand::id_type kCommandSetTabGroupMetadata = 26;
namespace {
@@ -112,7 +114,7 @@ struct TabNavigationPathPrunedPayload {
int32_t count;
};
-struct SerializedTabGroupId {
+struct SerializedToken {
// These fields correspond to the high and low fields of |base::Token|.
uint64_t id_high;
uint64_t id_low;
@@ -120,7 +122,7 @@ struct SerializedTabGroupId {
struct TabGroupPayload {
SessionID::id_type tab_id;
- SerializedTabGroupId maybe_group;
+ SerializedToken maybe_group;
bool has_group;
};
@@ -148,9 +150,6 @@ enum PersistedWindowShowState {
PERSISTED_SHOW_STATE_END = 8,
};
-using IdToSessionTab = std::map<SessionID, std::unique_ptr<SessionTab>>;
-using IdToSessionWindow = std::map<SessionID, std::unique_ptr<SessionWindow>>;
-
// Assert to ensure PersistedWindowShowState is updated if ui::WindowShowState
// is changed.
static_assert(ui::SHOW_STATE_END ==
@@ -217,6 +216,11 @@ void UpdateSelectedTabIndex(
}
}
+using IdToSessionTab = std::map<SessionID, std::unique_ptr<SessionTab>>;
+using IdToSessionWindow = std::map<SessionID, std::unique_ptr<SessionWindow>>;
+using TokenToSessionTabGroup =
+ std::map<base::Token, std::unique_ptr<SessionTabGroup>>;
+
// Returns the window in windows with the specified id. If a window does
// not exist, one is created.
SessionWindow* GetWindow(SessionID window_id, IdToSessionWindow* windows) {
@@ -244,6 +248,17 @@ SessionTab* GetTab(SessionID tab_id, IdToSessionTab* tabs) {
return i->second.get();
}
+SessionTabGroup* GetTabGroup(base::Token group_id,
+ TokenToSessionTabGroup* groups) {
+ DCHECK(groups);
+ // For |group_id|, insert a corresponding group entry or get the existing one.
+ auto result = groups->emplace(group_id, nullptr);
+ TokenToSessionTabGroup::iterator it = result.first;
+ if (result.second)
+ it->second = std::make_unique<SessionTabGroup>(group_id);
+ return it->second.get();
+}
+
// Returns an iterator into navigations pointing to the navigation whose
// index matches |index|. If no navigation index matches |index|, the first
// navigation with an index > |index| is returned.
@@ -312,9 +327,13 @@ void SortTabsBasedOnVisualOrderAndClear(
// Adds tabs to their parent window based on the tab's window_id. This
// ignores tabs with no navigations.
-void AddTabsToWindows(IdToSessionTab* tabs, IdToSessionWindow* windows) {
+void AddTabsToWindows(IdToSessionTab* tabs,
+ TokenToSessionTabGroup* tab_groups,
+ IdToSessionWindow* windows) {
DVLOG(1) << "AddTabsToWindows";
- DVLOG(1) << "Tabs " << tabs->size() << ", windows " << windows->size();
+ DVLOG(1) << "Tabs " << tabs->size() << ", groups " << tab_groups->size()
+ << ", windows " << windows->size();
+
for (auto& tab_pair : *tabs) {
std::unique_ptr<SessionTab> tab = std::move(tab_pair.second);
if (!tab->window_id.id() || tab->navigations.empty())
@@ -339,6 +358,35 @@ void AddTabsToWindows(IdToSessionTab* tabs, IdToSessionWindow* windows) {
// There are no more pointers left in |tabs|, just empty husks from the
// move, so clear it out.
tabs->clear();
+
+ // For each window, collect all the tab groups present. We rely on the fact
+ // that tab groups can't be split between windows.
+ for (auto& window_pair : *windows) {
+ SessionWindow* window = window_pair.second.get();
+
+ base::flat_set<base::Token> groups_in_current_window;
+ for (const auto& tab : window->tabs) {
+ if (tab->group.has_value())
+ groups_in_current_window.insert(tab->group.value());
+ }
+
+ // Move corresponding SessionTabGroup entries into SessionWindow.
+ for (const base::Token& group_id : groups_in_current_window) {
+ auto it = tab_groups->find(group_id);
+ if (it == tab_groups->end()) {
+ window->tab_groups.push_back(
+ std::make_unique<SessionTabGroup>(group_id));
+ continue;
+ }
+ window->tab_groups.push_back(std::move(it->second));
+ tab_groups->erase(it);
+ }
+ }
+
+ // We may have extraneous tab group entries. Since we don't have explicit
+ // commands for opening and closing tab groups, there may be dangling
+ // SessionTabGroup entries after all tabs in a group are closed.
+ tab_groups->clear();
}
void ProcessTabNavigationPathPrunedCommand(
@@ -376,6 +424,7 @@ void ProcessTabNavigationPathPrunedCommand(
bool CreateTabsAndWindows(
const std::vector<std::unique_ptr<SessionCommand>>& data,
IdToSessionTab* tabs,
+ TokenToSessionTabGroup* tab_groups,
IdToSessionWindow* windows,
SessionID* active_window_id) {
// If the file is corrupt (command with wrong size, or unknown command), we
@@ -573,6 +622,24 @@ bool CreateTabsAndWindows(
break;
}
+ case kCommandSetTabGroupMetadata: {
+ std::unique_ptr<base::Pickle> pickle = command->PayloadAsPickle();
+ base::PickleIterator iter(*pickle);
+
+ base::Optional<base::Token> group_id = ReadTokenFromPickle(&iter);
+ if (!group_id.has_value())
+ return true;
+
+ SessionTabGroup* group = GetTabGroup(group_id.value(), tab_groups);
+
+ if (!iter.ReadString16(&group->title))
+ return true;
+
+ if (!iter.ReadUInt32(&group->color))
+ return true;
+ break;
+ }
+
case kCommandSetPinnedState: {
PinnedStatePayload payload;
if (!command->GetPayload(&payload, sizeof(payload))) {
@@ -788,6 +855,17 @@ std::unique_ptr<SessionCommand> CreateTabGroupCommand(
return CreateSessionCommandForPayload(kCommandSetTabGroup, payload);
}
+std::unique_ptr<SessionCommand> CreateTabGroupMetadataUpdateCommand(
+ const base::Token& group,
+ const base::string16& title,
+ SkColor color) {
+ base::Pickle pickle;
+ WriteTokenToPickle(&pickle, group);
+ pickle.WriteString16(title);
+ pickle.WriteUInt32(color);
+ return std::make_unique<SessionCommand>(kCommandSetTabGroupMetadata, pickle);
+}
+
std::unique_ptr<SessionCommand> CreatePinnedStateCommand(
const SessionID& tab_id,
bool is_pinned) {
@@ -939,16 +1017,19 @@ void RestoreSessionFromCommands(
std::vector<std::unique_ptr<SessionWindow>>* valid_windows,
SessionID* active_window_id) {
IdToSessionTab tabs;
+ TokenToSessionTabGroup tab_groups;
IdToSessionWindow windows;
DVLOG(1) << "RestoreSessionFromCommands " << commands.size();
- if (CreateTabsAndWindows(commands, &tabs, &windows, active_window_id)) {
- AddTabsToWindows(&tabs, &windows);
+ if (CreateTabsAndWindows(commands, &tabs, &tab_groups, &windows,
+ active_window_id)) {
+ AddTabsToWindows(&tabs, &tab_groups, &windows);
SortTabsBasedOnVisualOrderAndClear(&windows, valid_windows);
UpdateSelectedTabIndex(valid_windows);
}
- // AddTabsToWindows should have processed all the tabs.
+ // AddTabsToWindows should have processed all the tabs and groups.
DCHECK_EQ(0u, tabs.size());
+ DCHECK_EQ(0u, tab_groups.size());
// SortTabsBasedOnVisualOrderAndClear should have processed all the windows.
DCHECK_EQ(0u, windows.size());
}
diff --git a/chromium/components/sessions/core/session_service_commands.h b/chromium/components/sessions/core/session_service_commands.h
index ce0a0c6ffd6..5715d6e5558 100644
--- a/chromium/components/sessions/core/session_service_commands.h
+++ b/chromium/components/sessions/core/session_service_commands.h
@@ -49,6 +49,10 @@ SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateSetWindowTypeCommand(
SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateTabGroupCommand(
const SessionID& tab_id,
base::Optional<base::Token> group);
+SESSIONS_EXPORT std::unique_ptr<SessionCommand>
+CreateTabGroupMetadataUpdateCommand(const base::Token& group,
+ const base::string16& title,
+ SkColor color);
SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreatePinnedStateCommand(
const SessionID& tab_id,
bool is_pinned);
diff --git a/chromium/components/sessions/core/session_types.cc b/chromium/components/sessions/core/session_types.cc
index 066099da452..eb4db88f36f 100644
--- a/chromium/components/sessions/core/session_types.cc
+++ b/chromium/components/sessions/core/session_types.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "components/sessions/core/session_command.h"
+#include "ui/gfx/color_palette.h"
namespace sessions {
@@ -22,12 +23,19 @@ SessionTab::SessionTab()
SessionTab::~SessionTab() {
}
+// SessionTab -----------------------------------------------------------------
+
+SessionTabGroup::SessionTabGroup(base::Token group_id)
+ : group_id(group_id), color(gfx::kPlaceholderColor) {}
+
+SessionTabGroup::~SessionTabGroup() {}
+
// SessionWindow ---------------------------------------------------------------
SessionWindow::SessionWindow()
: window_id(SessionID::NewUnique()),
selected_tab_index(-1),
- type(TYPE_TABBED),
+ type(TYPE_NORMAL),
is_constrained(true),
show_state(ui::SHOW_STATE_DEFAULT) {}
diff --git a/chromium/components/sessions/core/session_types.h b/chromium/components/sessions/core/session_types.h
index b160f2e992b..023965bc55d 100644
--- a/chromium/components/sessions/core/session_types.h
+++ b/chromium/components/sessions/core/session_types.h
@@ -19,6 +19,7 @@
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/sessions_export.h"
#include "components/variations/variations_associated_data.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -97,6 +98,30 @@ struct SESSIONS_EXPORT SessionTab {
DISALLOW_COPY_AND_ASSIGN(SessionTab);
};
+// SessionTabGroup -----------------------------------------------------------
+
+// Describes a tab group referenced by some SessionTab entry in its group
+// field. By default, this is initialized with placeholder values that are
+// visually obvious.
+struct SESSIONS_EXPORT SessionTabGroup {
+ explicit SessionTabGroup(base::Token group);
+ ~SessionTabGroup();
+
+ // Uniquely identifies this group. Initialized to zero and must be set be
+ // user. Unlike SessionID this should be globally unique, even across
+ // different sessions.
+ base::Token group_id;
+
+ // A human-readable title for the group.
+ base::string16 title;
+
+ // An accent color used when displaying the group.
+ SkColor color;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SessionTabGroup);
+};
+
// SessionWindow -------------------------------------------------------------
// Describes a saved window.
@@ -107,8 +132,10 @@ struct SESSIONS_EXPORT SessionWindow {
// Possible window types which can be stored here. Note that these values will
// be written out to disc via session commands.
enum WindowType {
- TYPE_TABBED = 0,
- TYPE_POPUP = 1
+ TYPE_NORMAL = 0,
+ TYPE_POPUP = 1,
+ TYPE_APP = 2,
+ TYPE_DEVTOOLS = 3
};
// Identifier of the window.
@@ -145,6 +172,10 @@ struct SESSIONS_EXPORT SessionWindow {
// The tabs, ordered by visual order.
std::vector<std::unique_ptr<SessionTab>> tabs;
+ // Tab groups in no particular order. For each group in |tab_groups|, there
+ // should be at least one tab in |tabs| in the group.
+ std::vector<std::unique_ptr<SessionTabGroup>> tab_groups;
+
// Is the window maximized, minimized, or normal?
ui::WindowShowState show_state;
diff --git a/chromium/components/sessions/ios/OWNERS b/chromium/components/sessions/ios/OWNERS
new file mode 100644
index 00000000000..f136fc175b8
--- /dev/null
+++ b/chromium/components/sessions/ios/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Internals
diff --git a/chromium/components/sessions/ios/ios_live_tab.h b/chromium/components/sessions/ios/ios_live_tab.h
index dc7133ed630..4d50f120a3c 100644
--- a/chromium/components/sessions/ios/ios_live_tab.h
+++ b/chromium/components/sessions/ios/ios_live_tab.h
@@ -9,9 +9,9 @@
#include "base/supports_user_data.h"
#include "components/sessions/core/live_tab.h"
#include "components/sessions/ios/ios_serialized_navigation_builder.h"
-#include "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state.h"
-namespace content {
+namespace web {
class NavigationManager;
}
diff --git a/chromium/components/signin/README b/chromium/components/signin/README
deleted file mode 100644
index 2c02bc49b68..00000000000
--- a/chromium/components/signin/README
+++ /dev/null
@@ -1,9 +0,0 @@
-Signin is in the process of becoming a layered component
-(https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design)
-to enable it to be shared cleanly on iOS.
-
-When this process is complete, this component will have the following structure:
-
-- core/: shared code that does not depend on src/content/ or src/ios/
-- content/: Driver for the shared code based on the content layer.
-- ios/: Driver for the shared code based on src/ios.
diff --git a/chromium/components/signin/README.md b/chromium/components/signin/README.md
new file mode 100644
index 00000000000..d2c989c64f7
--- /dev/null
+++ b/chromium/components/signin/README.md
@@ -0,0 +1,13 @@
+This component supports cross-platform access to and mutation of the user's Gaia
+identities. The core interfaces of interest to most consumers reside in
+public/identity_manager; see its README.md for documentation of those
+interfaces.
+
+The complete structure of the component is as follows:
+
+core/: Higher-level code that is publicly visible to consumers. Code therein will
+be transitioned to public/ and/or internal/.
+internal/: The internal implementation of public/. Not visible to consumers.
+ios/: Higher-level iOS-specific code that is publicly visible to consumers. Code
+therein will be transitioned to public/ and/or internal/.
+public/: The long-term public API surface of the component.
diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn
index 4221020aca2..df01214e98c 100644
--- a/chromium/components/signin/core/browser/BUILD.gn
+++ b/chromium/components/signin/core/browser/BUILD.gn
@@ -69,7 +69,7 @@ static_library("browser") {
]
deps = [
"//base:i18n",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/metrics",
"//components/os_crypt",
"//components/signin/public/identity_manager",
diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc
index 3032fad8753..7291d86bcb4 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.cc
+++ b/chromium/components/signin/core/browser/about_signin_internals.cc
@@ -418,7 +418,7 @@ void AboutSigninInternals::OnRefreshTokenRemovedForAccountFromSource(
void AboutSigninInternals::OnRefreshTokensLoaded() {
RefreshTokenEvent event;
- // event.account_id = CoreAccountId("All accounts");
+ // This event concerns all accounts, so it does not have any account id.
event.type = AboutSigninInternals::RefreshTokenEventType::kAllTokensLoaded;
signin_status_.AddRefreshTokenEvent(event);
NotifyObservers();
@@ -638,7 +638,7 @@ AboutSigninInternals::SigninStatus::ToValue(
signin_error_controller->error_account_id();
const base::Optional<AccountInfo> error_account_info =
identity_manager
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
error_account_id);
AddSectionEntry(basic_info, "Auth Error",
signin_error_controller->auth_error().ToString());
diff --git a/chromium/components/signin/core/browser/account_investigator_unittest.cc b/chromium/components/signin/core/browser/account_investigator_unittest.cc
index c752ee46940..c1aa8668e8b 100644
--- a/chromium/components/signin/core/browser/account_investigator_unittest.cc
+++ b/chromium/components/signin/core/browser/account_investigator_unittest.cc
@@ -8,7 +8,7 @@
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/base/signin_pref_names.h"
@@ -133,7 +133,7 @@ class AccountInvestigatorTest : public testing::Test {
private:
// Timer needs a message loop.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
signin::IdentityTestEnvironment identity_test_env_;
@@ -145,9 +145,9 @@ class AccountInvestigatorTest : public testing::Test {
namespace {
-ListedAccount Account(const std::string& id) {
+ListedAccount Account(const CoreAccountId& account_id) {
ListedAccount account;
- account.id = id;
+ account.id = account_id;
return account;
}
@@ -166,9 +166,9 @@ const std::string kGaiaId1 = signin::GetTestGaiaIdForEmail("1@mail.com");
const std::string kGaiaId2 = signin::GetTestGaiaIdForEmail("2@mail.com");
const std::string kGaiaId3 = signin::GetTestGaiaIdForEmail("3@mail.com");
-const ListedAccount one(Account(kGaiaId1));
-const ListedAccount two(Account(kGaiaId2));
-const ListedAccount three(Account(kGaiaId3));
+const ListedAccount one(Account(CoreAccountId(kGaiaId1)));
+const ListedAccount two(Account(CoreAccountId(kGaiaId2)));
+const ListedAccount three(Account(CoreAccountId(kGaiaId3)));
const std::vector<ListedAccount> no_accounts{};
const std::vector<ListedAccount> just_one{one};
diff --git a/chromium/components/signin/core/browser/account_reconcilor.cc b/chromium/components/signin/core/browser/account_reconcilor.cc
index f609c05f688..d1e171063f7 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor.cc
@@ -40,8 +40,13 @@
using signin::AccountReconcilorDelegate;
using signin_metrics::AccountReconcilorState;
+#if defined(OS_ANDROID) || defined(OS_IOS)
+const base::Feature kUseMultiloginEndpoint{"UseMultiloginEndpoint",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+#else
const base::Feature kUseMultiloginEndpoint{"UseMultiloginEndpoint",
base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
namespace {
@@ -65,6 +70,13 @@ gaia::ListedAccount AccountForId(const CoreAccountId& account_id) {
return account;
}
+bool ContainsGaiaAccount(const std::vector<gaia::ListedAccount>& gaia_accounts,
+ const CoreAccountId& account_id) {
+ return gaia_accounts.end() !=
+ std::find_if(gaia_accounts.begin(), gaia_accounts.end(),
+ AccountEqualToFunc(AccountForId(account_id)));
+}
+
// Returns a copy of |accounts| without the unverified accounts.
std::vector<gaia::ListedAccount> FilterUnverifiedAccounts(
const std::vector<gaia::ListedAccount>& accounts) {
@@ -125,6 +137,50 @@ bool RevokeAllSecondaryTokens(
return token_revoked;
}
+// TODO(msalama): Move this code and |RevokeAllSecondaryTokens|
+// to |DiceAccountReconcilorDelegate|.
+signin::RevokeTokenAction RevokeTokensNotInCookies(
+ signin::IdentityManager* identity_manager,
+ const CoreAccountId& primary_account,
+ const std::vector<gaia::ListedAccount>& gaia_accounts) {
+ bool invalidated_primary_account_token = false;
+ bool revoked_token_for_secondary_account = false;
+ signin_metrics::SourceForRefreshTokenOperation source =
+ signin_metrics::SourceForRefreshTokenOperation::
+ kAccountReconcilor_RevokeTokensNotInCookies;
+
+ for (const CoreAccountInfo& account_info :
+ identity_manager->GetAccountsWithRefreshTokens()) {
+ CoreAccountId account = account_info.account_id;
+ if (ContainsGaiaAccount(gaia_accounts, account))
+ continue;
+
+ auto* accounts_mutator = identity_manager->GetAccountsMutator();
+ if (account == primary_account) {
+ invalidated_primary_account_token = true;
+ accounts_mutator->InvalidateRefreshTokenForPrimaryAccount(source);
+ } else {
+ revoked_token_for_secondary_account = true;
+ accounts_mutator->RemoveAccount(account, source);
+ }
+ }
+
+ signin::RevokeTokenAction revoke_token_action =
+ signin::RevokeTokenAction::kNone;
+ if (invalidated_primary_account_token &&
+ revoked_token_for_secondary_account) {
+ revoke_token_action =
+ signin::RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts;
+ } else if (invalidated_primary_account_token) {
+ revoke_token_action =
+ signin::RevokeTokenAction::kInvalidatePrimaryAccountToken;
+ } else if (revoked_token_for_secondary_account) {
+ revoke_token_action =
+ signin::RevokeTokenAction::kRevokeSecondaryAccountsTokens;
+ }
+ return revoke_token_action;
+}
+
// Pick the account will become first after this reconcile is finished.
CoreAccountId PickFirstGaiaAccount(
const signin::MultiloginParameters& parameters,
@@ -592,6 +648,12 @@ void AccountReconcilor::OnAccountsInCookieUpdated(
<< " unverified account(s).";
CoreAccountId primary_account = identity_manager_->GetPrimaryAccountId();
+ if (delegate_->ShouldRevokeTokensNotInCookies()) {
+ signin::RevokeTokenAction revoke_token_action = RevokeTokensNotInCookies(
+ identity_manager_, primary_account, verified_gaia_accounts);
+ delegate_->OnRevokeTokensNotInCookiesCompleted(revoke_token_action);
+ }
+
// Revoking tokens for secondary accounts causes the AccountTracker to
// completely remove them from Chrome.
// Revoking the token for the primary account is not supported (it should be
@@ -758,17 +820,12 @@ void AccountReconcilor::FinishReconcile(
std::vector<CoreAccountId> add_to_cookie_copy = add_to_cookie_;
int added_to_cookie = 0;
for (size_t i = 0; i < add_to_cookie_copy.size(); ++i) {
- if (gaia_accounts.end() !=
- std::find_if(gaia_accounts.begin(), gaia_accounts.end(),
- AccountEqualToFunc(AccountForId(add_to_cookie_copy[i])))) {
+ if (ContainsGaiaAccount(gaia_accounts, add_to_cookie_copy[i])) {
OnAddAccountToCookieCompleted(add_to_cookie_copy[i],
GoogleServiceAuthError::AuthErrorNone());
} else {
PerformMergeAction(add_to_cookie_copy[i]);
- if (original_gaia_accounts.end() ==
- std::find_if(
- original_gaia_accounts.begin(), original_gaia_accounts.end(),
- AccountEqualToFunc(AccountForId(add_to_cookie_copy[i])))) {
+ if (!ContainsGaiaAccount(original_gaia_accounts, add_to_cookie_copy[i])) {
added_to_cookie++;
}
}
diff --git a/chromium/components/signin/core/browser/account_reconcilor.h b/chromium/components/signin/core/browser/account_reconcilor.h
index 387cd6f6ed6..f617f00ec6c 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.h
+++ b/chromium/components/signin/core/browser/account_reconcilor.h
@@ -140,6 +140,9 @@ class AccountReconcilor : public KeyedService,
private:
friend class AccountReconcilorTest;
friend class DiceBrowserTest;
+ friend class BaseAccountReconcilorTestTable;
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestForceDiceMigration,
+ TableRowTestCheckNoOp);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorEndpointParamTest,
IdentityManagerRegistration);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorEndpointParamTest, Reauth);
@@ -237,6 +240,8 @@ class AccountReconcilor : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
DelegateTimeoutIsNotCalledIfTimeoutIsNotReached);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, MultiloginLogout);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestForceDiceMigration,
+ TableRowTest);
void set_timer_for_testing(std::unique_ptr<base::OneShotTimer> timer);
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
index 3cf1a3bbb7a..46d7d0be1df 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -176,6 +176,10 @@ AccountReconcilorDelegate::ShouldRevokeSecondaryTokensBeforeReconcile(
return RevokeTokenOption::kDoNotRevoke;
}
+bool AccountReconcilorDelegate::ShouldRevokeTokensNotInCookies() const {
+ return false;
+}
+
bool AccountReconcilorDelegate::ShouldRevokeTokensOnCookieDeleted() {
return false;
}
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate.h b/chromium/components/signin/core/browser/account_reconcilor_delegate.h
index ab7cf8a88e4..d9edf545d9d 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate.h
@@ -18,6 +18,15 @@ class AccountReconcilor;
namespace signin {
+// Possible revoke token actions taken by the AccountReconcilor.
+enum class RevokeTokenAction {
+ kNone,
+ kInvalidatePrimaryAccountToken,
+ kRevokeSecondaryAccountsTokens,
+ kRevokeTokensForPrimaryAndSecondaryAccounts,
+ kMaxValue = kRevokeTokensForPrimaryAndSecondaryAccounts
+};
+
// Base class for AccountReconcilorDelegate.
class AccountReconcilorDelegate {
public:
@@ -84,6 +93,14 @@ class AccountReconcilorDelegate {
virtual RevokeTokenOption ShouldRevokeSecondaryTokensBeforeReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts);
+ // Invalidates primary account token or revokes token for any secondary
+ // account that does not have an equivalent gaia cookie.
+ virtual bool ShouldRevokeTokensNotInCookies() const;
+
+ // Called when |RevokeTokensNotInCookies| is finished.
+ virtual void OnRevokeTokensNotInCookiesCompleted(
+ RevokeTokenAction revoke_token_action) {}
+
// Returns whether tokens should be revoked when the Gaia cookie has been
// explicitly deleted by the user.
// If this returns false, tokens will not be revoked. If this returns true,
@@ -92,9 +109,9 @@ class AccountReconcilorDelegate {
virtual bool ShouldRevokeTokensOnCookieDeleted();
// Called when reconcile is finished.
- // |OnReconcileFinished| is always called at the end of reconciliation, even
- // when there is an error (except in cases where reconciliation times out
- // before finishing, see |GetReconcileTimeout|).
+ // |OnReconcileFinished| is always called at the end of reconciliation,
+ // even when there is an error (except in cases where reconciliation times
+ // out before finishing, see |GetReconcileTimeout|).
virtual void OnReconcileFinished(const CoreAccountId& first_account,
bool reconcile_is_noop) {}
diff --git a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
index 2269dd882ff..85c57f8ff6a 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -15,7 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/timer/mock_timer.h"
#include "build/build_config.h"
@@ -46,6 +46,7 @@
#include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
#endif
+using signin::RevokeTokenAction;
using signin_metrics::AccountReconcilorState;
namespace {
@@ -75,6 +76,14 @@ class SpyReconcilorDelegate : public signin::AccountReconcilorDelegate {
return primary_account;
}
+ std::vector<CoreAccountId> GetChromeAccountsForReconcile(
+ const std::vector<CoreAccountId>& chrome_accounts,
+ const CoreAccountId& primary_account,
+ const std::vector<gaia::ListedAccount>& gaia_accounts,
+ const gaia::MultiloginMode mode) const override {
+ return chrome_accounts;
+ }
+
void OnReconcileFinished(const CoreAccountId& first_account,
bool reconcile_is_noop) override {
++num_reconcile_finished_calls_;
@@ -99,13 +108,15 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
DummyAccountReconcilorWithDelegate(
signin::IdentityManager* identity_manager,
SigninClient* client,
- signin::AccountConsistencyMethod account_consistency)
+ signin::AccountConsistencyMethod account_consistency,
+ bool dice_migration_completed)
: AccountReconcilor(
identity_manager,
client,
CreateAccountReconcilorDelegate(client,
identity_manager,
- account_consistency)) {
+ account_consistency,
+ dice_migration_completed)) {
#if defined(OS_IOS)
SetIsWKHTTPSystemCookieStoreEnabled(true);
#endif // defined(OS_IOS)
@@ -132,7 +143,8 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
CreateAccountReconcilorDelegate(
SigninClient* signin_client,
signin::IdentityManager* identity_manager,
- signin::AccountConsistencyMethod account_consistency) {
+ signin::AccountConsistencyMethod account_consistency,
+ bool dice_migration_completed) {
switch (account_consistency) {
case signin::AccountConsistencyMethod::kMirror:
#if defined(OS_ANDROID)
@@ -147,7 +159,7 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
case signin::AccountConsistencyMethod::kDice:
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
return std::make_unique<signin::DiceAccountReconcilorDelegate>(
- signin_client, account_consistency);
+ signin_client, account_consistency, dice_migration_completed);
#else
NOTREACHED();
return nullptr;
@@ -161,12 +173,12 @@ class DummyAccountReconcilorWithDelegate : public AccountReconcilor {
class MockAccountReconcilor
: public testing::StrictMock<DummyAccountReconcilorWithDelegate> {
public:
- explicit MockAccountReconcilor(
- signin::IdentityManager* identity_manager,
- SigninClient* client,
- signin::AccountConsistencyMethod account_consistency);
+ MockAccountReconcilor(signin::IdentityManager* identity_manager,
+ SigninClient* client,
+ signin::AccountConsistencyMethod account_consistency,
+ bool dice_migration_completed);
- explicit MockAccountReconcilor(
+ MockAccountReconcilor(
signin::IdentityManager* identity_manager,
SigninClient* client,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
@@ -180,11 +192,13 @@ class MockAccountReconcilor
MockAccountReconcilor::MockAccountReconcilor(
signin::IdentityManager* identity_manager,
SigninClient* client,
- signin::AccountConsistencyMethod account_consistency)
+ signin::AccountConsistencyMethod account_consistency,
+ bool dice_migration_completed)
: testing::StrictMock<DummyAccountReconcilorWithDelegate>(
identity_manager,
client,
- account_consistency) {}
+ account_consistency,
+ dice_migration_completed) {}
MockAccountReconcilor::MockAccountReconcilor(
signin::IdentityManager* identity_manager,
@@ -230,9 +244,7 @@ class AccountReconcilorTest : public ::testing::Test {
return &identity_test_env_;
}
- base::test::ScopedTaskEnvironment* task_environment() {
- return &task_environment_;
- }
+ base::test::TaskEnvironment* task_environment() { return &task_environment_; }
TestSigninClient* test_signin_client() { return &test_signin_client_; }
base::HistogramTester* histogram_tester() { return &histogram_tester_; }
@@ -260,6 +272,9 @@ class AccountReconcilorTest : public ::testing::Test {
void SetAccountConsistency(signin::AccountConsistencyMethod method);
+ // Should never be called before |SetAccountConsistency|.
+ void SetDiceMigrationCompleted(bool dice_migration_completed);
+
PrefService* pref_service() { return &pref_service_; }
void DeleteReconcilor() { mock_reconcilor_.reset(); }
@@ -267,8 +282,9 @@ class AccountReconcilorTest : public ::testing::Test {
network::TestURLLoaderFactory test_url_loader_factory_;
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
signin::AccountConsistencyMethod account_consistency_;
+ bool dice_migration_completed_ = false;
sync_preferences::TestingPrefServiceSyncable pref_service_;
TestSigninClient test_signin_client_;
signin::IdentityTestEnvironment identity_test_env_;
@@ -301,6 +317,8 @@ class AccountReconcilorMirrorEndpointParamTest
SetAccountConsistency(signin::AccountConsistencyMethod::kMirror);
if (IsMultiloginEnabled())
scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
+ else
+ scoped_feature_list_.InitAndDisableFeature(kUseMultiloginEndpoint);
}
bool IsMultiloginEnabled() { return GetParam(); }
@@ -331,8 +349,7 @@ INSTANTIATE_TEST_SUITE_P(Dice_Mirror,
signin::AccountConsistencyMethod::kMirror));
AccountReconcilorTest::AccountReconcilorTest()
- : task_environment_(
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
+ : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
account_consistency_(signin::AccountConsistencyMethod::kDisabled),
test_signin_client_(&pref_service_, &test_url_loader_factory_),
identity_test_env_(/*test_url_loader_factory=*/nullptr,
@@ -350,7 +367,7 @@ MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() {
if (!mock_reconcilor_) {
mock_reconcilor_ = std::make_unique<MockAccountReconcilor>(
identity_test_env_.identity_manager(), &test_signin_client_,
- account_consistency_);
+ account_consistency_, dice_migration_completed_);
}
return mock_reconcilor_.get();
@@ -409,6 +426,14 @@ void AccountReconcilorTest::SimulateCookieContentSettingsChanged(
void AccountReconcilorTest::SetAccountConsistency(
signin::AccountConsistencyMethod method) {
account_consistency_ = method;
+ dice_migration_completed_ =
+ account_consistency_ == signin::AccountConsistencyMethod::kDice;
+}
+
+void AccountReconcilorTest::SetDiceMigrationCompleted(
+ bool dice_migration_completed) {
+ DCHECK_EQ(signin::AccountConsistencyMethod::kDice, account_consistency_);
+ dice_migration_completed_ = dice_migration_completed;
}
TEST_F(AccountReconcilorTest, Basic) {
@@ -454,6 +479,15 @@ std::vector<AccountReconcilorTestTableParam> GenerateTestCasesFromParams(
return return_params;
}
+struct ForceDiceMigrationTestTableParam {
+ const char* tokens;
+ const char* cookies;
+ const char* gaia_api_calls;
+ const char* tokens_after_reconcile;
+ const char* cookies_after_reconcile;
+ RevokeTokenAction revoke_token_action;
+};
+
// Pretty prints a AccountReconcilorTestTableParam. Used by gtest.
void PrintTo(const AccountReconcilorTestTableParam& param, ::std::ostream* os) {
*os << "Tokens: " << param.tokens << ". Cookies: " << param.cookies
@@ -462,11 +496,36 @@ void PrintTo(const AccountReconcilorTestTableParam& param, ::std::ostream* os) {
: "false");
}
-// Parameterized version of AccountReconcilorTest.
-class AccountReconcilorTestTable
- : public AccountReconcilorTest,
- public ::testing::WithParamInterface<AccountReconcilorTestTableParam> {
+class BaseAccountReconcilorTestTable : public AccountReconcilorTest {
protected:
+ BaseAccountReconcilorTestTable(const AccountReconcilorTestTableParam& param)
+ : BaseAccountReconcilorTestTable(param.tokens,
+ param.cookies,
+ param.is_first_reconcile,
+ param.gaia_api_calls,
+ param.tokens_after_reconcile,
+ param.cookies_after_reconcile) {}
+
+ BaseAccountReconcilorTestTable(const char* tokens,
+ const char* cookies,
+ IsFirstReconcile is_first_reconcile,
+ const char* gaia_api_calls,
+ const char* tokens_after_reconcile,
+ const char* cookies_after_reconcile)
+ : tokens_(tokens),
+ cookies_(cookies),
+ is_first_reconcile_(is_first_reconcile),
+ gaia_api_calls_(gaia_api_calls),
+ tokens_after_reconcile_(tokens_after_reconcile),
+ cookies_after_reconcile_(cookies_after_reconcile) {
+ accounts_['A'] = {"a@gmail.com",
+ signin::GetTestGaiaIdForEmail("a@gmail.com")};
+ accounts_['B'] = {"b@gmail.com",
+ signin::GetTestGaiaIdForEmail("b@gmail.com")};
+ accounts_['C'] = {"c@gmail.com",
+ signin::GetTestGaiaIdForEmail("c@gmail.com")};
+ }
+
struct Account {
std::string email;
std::string gaia_id;
@@ -479,15 +538,6 @@ class AccountReconcilorTestTable
bool has_error;
};
- AccountReconcilorTestTable() {
- accounts_['A'] = {"a@gmail.com",
- signin::GetTestGaiaIdForEmail("a@gmail.com")};
- accounts_['B'] = {"b@gmail.com",
- signin::GetTestGaiaIdForEmail("b@gmail.com")};
- accounts_['C'] = {"c@gmail.com",
- signin::GetTestGaiaIdForEmail("c@gmail.com")};
- }
-
// Build Tokens from string.
std::vector<Token> ParseTokenString(const char* token_string) {
std::vector<Token> parsed_tokens;
@@ -549,14 +599,13 @@ class AccountReconcilorTestTable
}
}
if (!authenticated_account_found)
- EXPECT_EQ("", identity_manager->GetPrimaryAccountId());
+ EXPECT_EQ(CoreAccountId(), identity_manager->GetPrimaryAccountId());
}
- void SetupTokens() {
- std::vector<Token> tokens_before_reconcile =
- ParseTokenString(GetParam().tokens);
+ void SetupTokens(const char* tokens_string) {
+ std::vector<Token> tokens = ParseTokenString(tokens_string);
Token primary_account;
- for (const Token& token : tokens_before_reconcile) {
+ for (const Token& token : tokens) {
CoreAccountId account_id;
if (token.is_authenticated) {
account_id = ConnectProfileToAccount(token.email).account_id;
@@ -571,9 +620,145 @@ class AccountReconcilorTestTable
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
}
}
- VerifyCurrentTokens(tokens_before_reconcile);
+ VerifyCurrentTokens(tokens);
+ }
+
+ void ConfigureCookieManagerService(const std::vector<Cookie>& cookies) {
+ std::vector<signin::CookieParams> cookie_params;
+ for (const auto& cookie : cookies) {
+ std::string gaia_id = cookie.gaia_id;
+
+ // Figure the account token of this specific account id,
+ // ie 'A', 'B', or 'C'.
+ char account_key = '\0';
+ for (const auto& account : accounts_) {
+ if (account.second.gaia_id == gaia_id) {
+ account_key = account.first;
+ break;
+ }
+ }
+ ASSERT_NE(account_key, '\0');
+
+ cookie_params.push_back({accounts_[account_key].email, gaia_id,
+ cookie.is_valid, false /* signed_out */,
+ true /* verified */});
+ }
+ signin::SetListAccountsResponseWithParams(cookie_params,
+ &test_url_loader_factory_);
+ identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
}
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ void RunReconcile() {
+ // Setup cookies.
+ std::vector<Cookie> cookies = ParseCookieString(cookies_);
+ ConfigureCookieManagerService(cookies);
+
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens(tokens_);
+
+ // Call list accounts now so that the next call completes synchronously.
+ identity_test_env()->identity_manager()->GetAccountsInCookieJar();
+ base::RunLoop().RunUntilIdle();
+
+ // Setup expectations.
+ testing::InSequence mock_sequence;
+ bool logout_action = false;
+ for (int i = 0; gaia_api_calls_[i] != '\0'; ++i) {
+ if (gaia_api_calls_[i] == 'X') {
+ logout_action = true;
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+ .Times(1);
+ cookies.clear();
+ continue;
+ }
+ std::string cookie(1, gaia_api_calls_[i]);
+ CoreAccountId account_id_for_cookie = PickAccountIdForAccount(
+ accounts_[cookie[0]].gaia_id, accounts_[cookie[0]].email);
+ EXPECT_CALL(*GetMockReconcilor(),
+ PerformMergeAction(account_id_for_cookie))
+ .Times(1);
+ // MergeSession fixes an existing cookie or appends it at the end.
+ auto it = std::find(cookies.begin(), cookies.end(),
+ Cookie{account_id_for_cookie, false /* is_valid */});
+ if (it == cookies.end())
+ cookies.push_back({account_id_for_cookie, true});
+ else
+ it->is_valid = true;
+ }
+ if (!logout_action) {
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+ .Times(0);
+ }
+
+ // Check the expected cookies after reconcile.
+ std::vector<Cookie> expected_cookies =
+ ParseCookieString(cookies_after_reconcile_);
+ ASSERT_EQ(expected_cookies, cookies);
+
+ // Reconcile.
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ ASSERT_TRUE(reconcilor->first_execution_);
+ reconcilor->first_execution_ =
+ is_first_reconcile_ == IsFirstReconcile::kFirst;
+ ASSERT_TRUE(reconcilor->delegate_->IsAccountConsistencyEnforced());
+ reconcilor->StartReconcile();
+ for (int i = 0; gaia_api_calls_[i] != '\0'; ++i) {
+ if (gaia_api_calls_[i] == 'X')
+ continue;
+ CoreAccountId account_id =
+ PickAccountIdForAccount(accounts_[gaia_api_calls_[i]].gaia_id,
+ accounts_[gaia_api_calls_[i]].email);
+ SimulateAddAccountToCookieCompleted(
+ reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
+ }
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+
+ if (tokens_ == tokens_after_reconcile_) {
+ EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+ } else {
+ // If the tokens were changed by the reconcile, a new reconcile should be
+ // scheduled.
+ EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
+ reconcilor->GetState());
+ }
+
+ VerifyCurrentTokens(ParseTokenString(tokens_after_reconcile_));
+
+ testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
+
+ // Another reconcile is sometimes triggered if Chrome accounts have changed.
+ // Allow it to finish.
+ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_))
+ .WillRepeatedly(testing::Return());
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+ .WillRepeatedly(testing::Return());
+ ConfigureCookieManagerService({});
+ base::RunLoop().RunUntilIdle();
+ }
+#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+ std::string GaiaIdForAccountKey(char account_key) {
+ return accounts_[account_key].gaia_id;
+ }
+
+ std::map<char, Account> accounts_;
+ const char* tokens_;
+ const char* cookies_;
+ IsFirstReconcile is_first_reconcile_;
+ const char* gaia_api_calls_;
+ const char* tokens_after_reconcile_;
+ const char* cookies_after_reconcile_;
+};
+
+// Parameterized version of AccountReconcilorTest.
+class AccountReconcilorTestTable
+ : public BaseAccountReconcilorTestTable,
+ public ::testing::WithParamInterface<AccountReconcilorTestTableParam> {
+ protected:
+ AccountReconcilorTestTable() : BaseAccountReconcilorTestTable(GetParam()) {}
+
// Checks that reconcile is idempotent.
void CheckReconcileIdempotent(
const std::vector<AccountReconcilorTestTableParam>& params,
@@ -606,37 +791,6 @@ class AccountReconcilorTestTable
ADD_FAILURE() << "Could not check that reconcile is idempotent.";
}
-
- void ConfigureCookieManagerService(const std::vector<Cookie>& cookies) {
- std::vector<signin::CookieParams> cookie_params;
- for (const auto& cookie : cookies) {
- std::string gaia_id = cookie.gaia_id;
-
- // Figure the account token of this specific account id,
- // ie 'A', 'B', or 'C'.
- char account_key = '\0';
- for (const auto& account : accounts_) {
- if (account.second.gaia_id == gaia_id) {
- account_key = account.first;
- break;
- }
- }
- ASSERT_NE(account_key, '\0');
-
- cookie_params.push_back({accounts_[account_key].email, gaia_id,
- cookie.is_valid, false /* signed_out */,
- true /* verified */});
- }
- signin::SetListAccountsResponseWithParams(cookie_params,
- &test_url_loader_factory_);
- identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
- }
-
- std::string GaiaIdForAccountKey(char account_key) {
- return accounts_[account_key].gaia_id;
- }
-
- std::map<char, Account> accounts_;
};
#if !defined(OS_CHROMEOS)
@@ -692,24 +846,23 @@ std::vector<Cookie> FakeSetAccountsInCookie(
if (parameters.mode ==
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER) {
for (const CoreAccountId& account : parameters.accounts_to_send) {
- cookies_after_reconcile.push_back({account, true});
+ cookies_after_reconcile.push_back({account.id, true});
}
} else {
- std::set<CoreAccountId> accounts_set;
- for (const CoreAccountId& account : parameters.accounts_to_send) {
- accounts_set.insert(account);
- }
+ std::set<CoreAccountId> accounts_set(parameters.accounts_to_send.begin(),
+ parameters.accounts_to_send.end());
cookies_after_reconcile = cookies_before_reconcile;
for (Cookie& param : cookies_after_reconcile) {
- if (accounts_set.find(param.gaia_id) != accounts_set.end()) {
+ if (accounts_set.find(CoreAccountId(param.gaia_id)) !=
+ accounts_set.end()) {
param.is_valid = true;
- accounts_set.erase(param.gaia_id);
+ accounts_set.erase(CoreAccountId(param.gaia_id));
} else {
param.is_valid = false;
}
}
for (const CoreAccountId& account : accounts_set) {
- cookies_after_reconcile.push_back({account, true});
+ cookies_after_reconcile.push_back({account.id, true});
}
}
return cookies_after_reconcile;
@@ -906,91 +1059,9 @@ TEST_P(AccountReconcilorTestTable, TableRowTest) {
// Check that reconcile is idempotent: when called twice in a row it should do
// nothing on the second call.
CheckReconcileIdempotent(kDiceParams, GetParam(), /*multilogin=*/false);
-
- // Setup cookies.
- std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
- ConfigureCookieManagerService(cookies);
-
- // Setup tokens. This triggers listing cookies so we need to setup cookies
- // before that.
- SetupTokens();
-
- // Call list accounts now so that the next call completes synchronously.
- identity_test_env()->identity_manager()->GetAccountsInCookieJar();
- base::RunLoop().RunUntilIdle();
-
- // Setup expectations.
- testing::InSequence mock_sequence;
- bool logout_action = false;
- for (int i = 0; GetParam().gaia_api_calls[i] != '\0'; ++i) {
- if (GetParam().gaia_api_calls[i] == 'X') {
- logout_action = true;
- EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
- .Times(1);
- cookies.clear();
- continue;
- }
- std::string cookie(1, GetParam().gaia_api_calls[i]);
- CoreAccountId account_id_for_cookie = PickAccountIdForAccount(
- accounts_[cookie[0]].gaia_id, accounts_[cookie[0]].email);
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_for_cookie))
- .Times(1);
- // MergeSession fixes an existing cookie or appends it at the end.
- auto it = std::find(cookies.begin(), cookies.end(),
- Cookie{account_id_for_cookie, false /* is_valid */});
- if (it == cookies.end())
- cookies.push_back({account_id_for_cookie, true});
- else
- it->is_valid = true;
- }
- if (!logout_action) {
- EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
- .Times(0);
- }
-
- // Check the expected cookies after reconcile.
- std::vector<Cookie> expected_cookies =
- ParseCookieString(GetParam().cookies_after_reconcile);
- ASSERT_EQ(expected_cookies, cookies);
-
- // Reconcile.
- AccountReconcilor* reconcilor = GetMockReconcilor();
- ASSERT_TRUE(reconcilor->first_execution_);
- reconcilor->first_execution_ =
- GetParam().is_first_reconcile == IsFirstReconcile::kFirst;
- reconcilor->StartReconcile();
- for (int i = 0; GetParam().gaia_api_calls[i] != '\0'; ++i) {
- if (GetParam().gaia_api_calls[i] == 'X')
- continue;
- CoreAccountId account_id =
- PickAccountIdForAccount(accounts_[GetParam().gaia_api_calls[i]].gaia_id,
- accounts_[GetParam().gaia_api_calls[i]].email);
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
- }
- ASSERT_FALSE(reconcilor->is_reconcile_started_);
-
- if (GetParam().tokens == GetParam().tokens_after_reconcile) {
- EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
- } else {
- // If the tokens were changed by the reconcile, a new reconcile should be
- // scheduled.
- EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
- reconcilor->GetState());
- }
-
- VerifyCurrentTokens(ParseTokenString(GetParam().tokens_after_reconcile));
-
- testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
-
- // Another reconcile is sometimes triggered if Chrome accounts have changed.
- // Allow it to finish.
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_))
- .WillRepeatedly(testing::Return());
- EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
- .WillRepeatedly(testing::Return());
- ConfigureCookieManagerService({});
- base::RunLoop().RunUntilIdle();
+ RunReconcile();
+ histogram_tester()->ExpectTotalCount("ForceDiceMigration.RevokeTokenAction",
+ 0);
}
// Checks one row of the kDiceParams table above.
@@ -998,11 +1069,11 @@ TEST_P(AccountReconcilorTestTable, InconsistencyReasonLogging) {
// Enable Dice Migration.
SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
// Setup cookies.
- std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
+ std::vector<Cookie> cookies = ParseCookieString(cookies_);
ConfigureCookieManagerService(cookies);
// Setup tokens. This triggers listing cookies so we need to setup cookies
// before that.
- SetupTokens();
+ SetupTokens(tokens_);
// Call list accounts now so that the next call completes synchronously.
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
base::RunLoop().RunUntilIdle();
@@ -1027,6 +1098,9 @@ TEST_P(AccountReconcilorTestTable, InconsistencyReasonLogging) {
"Signin.DiceMigrationNotReady.Reason." + histogram_name_suffix,
GetParam().inconsistency_reason, 1);
+ histogram_tester()->ExpectTotalCount("ForceDiceMigration.RevokeTokenAction",
+ 0);
+
ConfigureCookieManagerService({});
base::RunLoop().RunUntilIdle();
}
@@ -1036,6 +1110,101 @@ INSTANTIATE_TEST_SUITE_P(
AccountReconcilorTestTable,
::testing::ValuesIn(GenerateTestCasesFromParams(kDiceParams)));
+class AccountReconcilorTestForceDiceMigration
+ : public BaseAccountReconcilorTestTable,
+ public ::testing::WithParamInterface<ForceDiceMigrationTestTableParam> {
+ public:
+ AccountReconcilorTestForceDiceMigration()
+ : BaseAccountReconcilorTestTable(GetParam().tokens,
+ GetParam().cookies,
+ IsFirstReconcile::kFirst,
+ GetParam().gaia_api_calls,
+ GetParam().tokens_after_reconcile,
+ GetParam().cookies_after_reconcile) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTestForceDiceMigration);
+};
+
+// clang-format off
+const std::vector<ForceDiceMigrationTestTableParam> kForceDiceParams = {
+ {"*A", "AB", "XA", "*A", "A" , RevokeTokenAction::kNone},
+ {"*AxB", "AB", "XA", "*A", "A" , RevokeTokenAction::kNone},
+ {"AxB", "AB", "XA", "A", "A" , RevokeTokenAction::kNone},
+ {"xAxB", "AB", "X", "", "" , RevokeTokenAction::kNone},
+ {"*A", "", "", "*xA", "" , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+ {"*A", "B", "X", "*xA", "" , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+ {"*AB", "B", "", "*xAB", "B" , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+ {"*AxB", "B", "X", "*xA", "" , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+ {"*ABC", "CB", "", "*xABC", "CB" , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+ {"*AB", "A", "", "*A", "A" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"AB", "A", "", "A", "A" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"AB", "", "", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAB", "", "", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAB", "A", "X", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAB", "xA", "", "", "xA" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAB", "B", "", "B", "B" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"AxB", "B", "X", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"AxB", "", "", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAxB", "", "", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"B", "xA", "", "", "xA" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"AB", "xAB", "", "B", "xAB" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAB", "xAC", "X", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"xAB", "AxC", "X", "", "" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"AB", "BC", "XB", "B", "B" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+ {"*AB", "", "", "*xA", "" , RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts},
+ {"*xAB", "", "", "*xA", "" , RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts},
+ {"*AxB", "", "", "*xA", "" , RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts},
+ {"*AB", "xBxA", "", "*xA", "xBxA", RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts}
+ };
+// clang-format on
+
+// Checks one row of the kForceDiceParams table above.
+TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTest) {
+ SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
+ EXPECT_FALSE(test_signin_client()->is_dice_migration_completed());
+ SetDiceMigrationCompleted(false);
+ RunReconcile();
+ EXPECT_TRUE(test_signin_client()->is_dice_migration_completed());
+ EXPECT_FALSE(
+ GetMockReconcilor()->delegate_->ShouldRevokeTokensNotInCookies());
+ histogram_tester()->ExpectUniqueSample("ForceDiceMigration.RevokeTokenAction",
+ GetParam().revoke_token_action, 1);
+}
+
+// Check that the result state of the reconcile is in a final state (reconcile
+// started from this state is a no-op).
+TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTestCheckNoOp) {
+ SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
+ // Setup cookies.
+ std::vector<Cookie> cookies = ParseCookieString(cookies_after_reconcile_);
+ ConfigureCookieManagerService(cookies);
+
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens(tokens_after_reconcile_);
+
+ // Call list accounts now so that the next call completes synchronously.
+ identity_test_env()->identity_manager()->GetAccountsInCookieJar();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_)).Times(0);
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()).Times(0);
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
+ .Times(0);
+
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ EXPECT_FALSE(reconcilor->delegate_->ShouldRevokeTokensNotInCookies());
+ reconcilor->StartReconcile();
+ base::RunLoop().RunUntilIdle();
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+ ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+}
+
+INSTANTIATE_TEST_SUITE_P(DiceMigrationTable,
+ AccountReconcilorTestForceDiceMigration,
+ ::testing::ValuesIn(kForceDiceParams));
+
// Parameterized version of AccountReconcilorTest that tests Dice
// implementation with Multilogin endpoint.
class AccountReconcilorTestDiceMultilogin : public AccountReconcilorTestTable {
@@ -1051,7 +1220,6 @@ class AccountReconcilorTestDiceMultilogin : public AccountReconcilorTestTable {
// Checks one row of the kDiceParams table above.
TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
- // Enable Mirror.
SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
@@ -1064,7 +1232,7 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
// Setup tokens. This triggers listing cookies so we need to setup cookies
// before that.
- SetupTokens();
+ SetupTokens(GetParam().tokens);
// Call list accounts now so that the next call completes synchronously.
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
@@ -1081,8 +1249,8 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
// response.
std::vector<CoreAccountId> accounts_to_send;
for (int i = 1; GetParam().gaia_api_calls_multilogin[i] != '\0'; ++i) {
- accounts_to_send.push_back(
- accounts_[GetParam().gaia_api_calls_multilogin[i]].gaia_id);
+ accounts_to_send.push_back(CoreAccountId(
+ accounts_[GetParam().gaia_api_calls_multilogin[i]].gaia_id));
}
const signin::MultiloginParameters params(mode, accounts_to_send);
cookies_after_reconcile = FakeSetAccountsInCookie(params, cookies);
@@ -1755,7 +1923,7 @@ TEST_P(AccountReconcilorTestMirrorMultilogin, TableRowTest) {
scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
// Setup tokens.
- SetupTokens();
+ SetupTokens(GetParam().tokens);
// Setup cookies.
std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
@@ -1877,7 +2045,7 @@ TEST_P(AccountReconcilorTestMiceMultilogin, TableRowTest) {
// Setup tokens. This triggers listing cookies so we need to setup cookies
// before that.
- SetupTokens();
+ SetupTokens(GetParam().tokens);
// Call list accounts now so that the next call completes synchronously.
identity_test_env()->identity_manager()->GetAccountsInCookieJar();
@@ -2800,7 +2968,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, Lock) {
// performing a full logout.
TEST_P(AccountReconcilorMethodParamTest,
StartReconcileWithSessionInfoExpiredDefault) {
- SetAccountConsistency(GetParam());
+ signin::AccountConsistencyMethod account_consistency = GetParam();
+ SetAccountConsistency(account_consistency);
AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
const CoreAccountId account_id = account_info.account_id;
AccountInfo account_info2 =
@@ -2813,18 +2982,46 @@ TEST_P(AccountReconcilorMethodParamTest,
false /* signed_out */, true /* verified */}},
&test_url_loader_factory_);
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
-
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
+ if (!reconcilor->IsMultiloginEndpointEnabled()) {
+ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
+ } else {
+ switch (account_consistency) {
+ case signin::AccountConsistencyMethod::kMirror: {
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ {account_id, account_id2});
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
+ break;
+ }
+ case signin::AccountConsistencyMethod::kDice: {
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
+ {account_id2, account_id});
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
+ break;
+ }
+ case signin::AccountConsistencyMethod::kDisabled:
+ case signin::AccountConsistencyMethod::kDiceMigration:
+ NOTREACHED();
+ break;
+ }
+ }
+
ASSERT_FALSE(reconcilor->is_reconcile_started_);
reconcilor->StartReconcile();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
- SimulateAddAccountToCookieCompleted(reconcilor, account_id,
- GoogleServiceAuthError::AuthErrorNone());
+ if (!reconcilor->IsMultiloginEndpointEnabled()) {
+ SimulateAddAccountToCookieCompleted(
+ reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
+ } else {
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
+ }
ASSERT_FALSE(reconcilor->is_reconcile_started_);
}
@@ -2841,15 +3038,43 @@ TEST_P(AccountReconcilorMethodParamTest, AccountReconcilorStateScheduled) {
MOCK_METHOD1(OnStateChanged, void(AccountReconcilorState state));
};
- SetAccountConsistency(GetParam());
- AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
+ signin::AccountConsistencyMethod account_consistency = GetParam();
+ SetAccountConsistency(account_consistency);
+ AccountInfo account_info1 = ConnectProfileToAccount("user@gmail.com");
AccountInfo account_info2 =
identity_test_env()->MakeAccountAvailable("other@gmail.com");
+ const CoreAccountId account_id1 = account_info1.account_id;
const CoreAccountId account_id2 = account_info2.account_id;
signin::SetListAccountsResponseOneAccount(
- account_info.email, account_info.gaia, &test_url_loader_factory_);
+ account_info1.email, account_info1.gaia, &test_url_loader_factory_);
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ ASSERT_TRUE(reconcilor);
+
+ if (!reconcilor->IsMultiloginEndpointEnabled()) {
+ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2));
+ } else {
+ switch (account_consistency) {
+ case signin::AccountConsistencyMethod::kMirror: {
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ {account_id1, account_id2});
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
+ break;
+ }
+ case signin::AccountConsistencyMethod::kDice: {
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
+ {account_id2, account_id1});
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
+ break;
+ }
+ case signin::AccountConsistencyMethod::kDisabled:
+ case signin::AccountConsistencyMethod::kDiceMigration:
+ NOTREACHED();
+ break;
+ }
+ }
// The reconcilor should run twice without going to the OK state in between.
// OK only happens at the end.
@@ -2869,8 +3094,6 @@ TEST_P(AccountReconcilorMethodParamTest, AccountReconcilorStateScheduled) {
OnStateChanged(AccountReconcilorState::ACCOUNT_RECONCILOR_OK))
.Times(1);
- AccountReconcilor* reconcilor = GetMockReconcilor();
- ASSERT_TRUE(reconcilor);
ScopedObserver<AccountReconcilor, AccountReconcilor::Observer>
scoped_observer(&observer);
scoped_observer.Add(reconcilor);
@@ -2893,9 +3116,14 @@ TEST_P(AccountReconcilorMethodParamTest, AccountReconcilorStateScheduled) {
// reconcile after the current one.
identity_test_env()->RemoveRefreshTokenForAccount(account_id2);
- // Unblock the first reconcile.
- SimulateAddAccountToCookieCompleted(reconcilor, account_id2,
- GoogleServiceAuthError::AuthErrorNone());
+ if (!reconcilor->IsMultiloginEndpointEnabled()) {
+ SimulateAddAccountToCookieCompleted(
+ reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone());
+ } else {
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
+ }
+
// Wait until the first reconcile finishes, and a second reconcile is done.
// The second reconcile will be a no-op.
base::RunLoop().RunUntilIdle();
diff --git a/chromium/components/signin/core/browser/android/BUILD.gn b/chromium/components/signin/core/browser/android/BUILD.gn
index faf53256b5f..488f87090cb 100644
--- a/chromium/components/signin/core/browser/android/BUILD.gn
+++ b/chromium/components/signin/core/browser/android/BUILD.gn
@@ -100,6 +100,7 @@ android_library("signin_java_test_support") {
java_files = [
"javatests/src/org/chromium/components/signin/test/util/AccountHolder.java",
+ "javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java",
"javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java",
"javatests/src/org/chromium/components/signin/test/util/FakeProfileDataSource.java",
]
diff --git a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java
index ccf0a8e4ecc..204c3ab081d 100644
--- a/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java
+++ b/chromium/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountTrackerService.java
@@ -12,6 +12,7 @@ import org.chromium.base.ObserverList;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.AsyncTask;
@@ -162,7 +163,8 @@ public class AccountTrackerService {
return;
}
if (areAccountIdsValid(accountIdNameMap[0])) {
- nativeSeedAccountsInfo(mNativeAccountTrackerService, accountIdNameMap[0],
+ AccountTrackerServiceJni.get().seedAccountsInfo(
+ mNativeAccountTrackerService, accountIdNameMap[0],
accountIdNameMap[1]);
mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE;
notifyObserversOnSeedingComplete();
@@ -197,7 +199,8 @@ public class AccountTrackerService {
mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_IN_PROGRESS;
mSystemAccountsChanged = false;
mSyncForceRefreshedForTest = true;
- nativeSeedAccountsInfo(mNativeAccountTrackerService, accountIds, accountNames);
+ AccountTrackerServiceJni.get().seedAccountsInfo(
+ mNativeAccountTrackerService, accountIds, accountNames);
mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE;
}
@@ -237,7 +240,8 @@ public class AccountTrackerService {
for (int i = 0; i < accounts.size(); ++i) {
accountNames[i] = accounts.get(i).name;
}
- if (nativeAreAccountsSeeded(mNativeAccountTrackerService, accountNames)) {
+ if (AccountTrackerServiceJni.get().areAccountsSeeded(
+ mNativeAccountTrackerService, accountNames)) {
mSystemAccountsSeedingStatus = SystemAccountsSeedingStatus.SEEDING_DONE;
notifyObserversOnSeedingComplete();
}
@@ -250,8 +254,10 @@ public class AccountTrackerService {
}
}
- private static native void nativeSeedAccountsInfo(
- long accountTrackerServicePtr, String[] gaiaIds, String[] accountNames);
- private static native boolean nativeAreAccountsSeeded(
- long accountTrackerServicePtr, String[] accountNames);
+ @NativeMethods
+ interface Natives {
+ public void seedAccountsInfo(
+ long nativeAccountTrackerService, String[] gaiaIds, String[] accountNames);
+ public boolean areAccountsSeeded(long nativeAccountTrackerService, String[] accountNames);
+ }
}
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc b/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc
index 5b044244d8f..cd1f0cca6ea 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_android.cc
@@ -31,9 +31,7 @@ ConsistencyCookieManagerAndroid::~ConsistencyCookieManagerAndroid() {
Java_ConsistencyCookieManager_destroy(env, java_ref_);
}
-void ConsistencyCookieManagerAndroid::OnIsUpdatePendingChanged(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& java_obj) {
+void ConsistencyCookieManagerAndroid::OnIsUpdatePendingChanged(JNIEnv* env) {
bool is_update_pending_in_java =
Java_ConsistencyCookieManager_getIsUpdatePending(env, java_ref_);
if (is_update_pending_in_java == is_update_pending_in_java_)
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_android.h b/chromium/components/signin/core/browser/consistency_cookie_manager_android.h
index 093b8898262..6fa0f2e2e11 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_android.h
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_android.h
@@ -25,9 +25,7 @@ class ConsistencyCookieManagerAndroid : public ConsistencyCookieManagerBase {
~ConsistencyCookieManagerAndroid() override;
- void OnIsUpdatePendingChanged(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& java_self);
+ void OnIsUpdatePendingChanged(JNIEnv* env);
protected:
std::string CalculateCookieValue() override;
diff --git a/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc b/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc
index 5023f2c213f..b0cbd10dc9e 100644
--- a/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc
+++ b/chromium/components/signin/core/browser/consistency_cookie_manager_unittest.cc
@@ -8,7 +8,7 @@
#include <string>
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/public/base/account_consistency_method.h"
@@ -30,15 +30,14 @@ MATCHER_P(CookieHasValueMatcher, value, "") {
net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
return arg.Name() == "CHROME_ID_CONSISTENCY_STATE" && arg.Value() == value &&
arg.IncludeForRequestURL(GaiaUrls::GetInstance()->gaia_url(),
- cookie_options) ==
- net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+ cookie_options)
+ .IsInclude();
}
MATCHER(SetPermittedInContext, "") {
const net::CanonicalCookie& cookie = testing::get<0>(arg);
const net::CookieOptions& cookie_options = testing::get<1>(arg);
- return cookie.IsSetPermittedInContext(cookie_options) ==
- net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+ return cookie.IsSetPermittedInContext(cookie_options).IsInclude();
}
class MockCookieManager
@@ -100,7 +99,7 @@ class ConsistencyCookieManagerTest : public ::testing::Test {
private:
base::test::ScopedFeatureList scoped_feature_list_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
// Owned by signin_client_.
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
index bc560b63767..2adffa0a073 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -17,11 +17,16 @@ namespace signin {
DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate(
SigninClient* signin_client,
- AccountConsistencyMethod account_consistency)
- : signin_client_(signin_client), account_consistency_(account_consistency) {
+ AccountConsistencyMethod account_consistency,
+ bool migration_completed)
+ : signin_client_(signin_client),
+ account_consistency_(account_consistency),
+ migration_completed_(migration_completed) {
DCHECK(signin_client_);
DCHECK(DiceMethodGreaterOrEqual(account_consistency_,
AccountConsistencyMethod::kDiceMigration));
+ DCHECK(account_consistency == AccountConsistencyMethod::kDice ||
+ !migration_completed);
}
bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const {
@@ -235,11 +240,24 @@ DiceAccountReconcilorDelegate::ShouldRevokeSecondaryTokensBeforeReconcile(
return RevokeTokenOption::kRevoke;
}
- return (account_consistency_ == AccountConsistencyMethod::kDice)
+ return account_consistency_ == AccountConsistencyMethod::kDice
? RevokeTokenOption::kRevokeIfInError
: RevokeTokenOption::kDoNotRevoke;
}
+bool DiceAccountReconcilorDelegate::ShouldRevokeTokensNotInCookies() const {
+ return account_consistency_ == AccountConsistencyMethod::kDice &&
+ !migration_completed_;
+}
+
+void DiceAccountReconcilorDelegate::OnRevokeTokensNotInCookiesCompleted(
+ RevokeTokenAction revoke_token_action) {
+ migration_completed_ = true;
+ signin_client_->SetDiceMigrationCompleted();
+ UMA_HISTOGRAM_ENUMERATION("ForceDiceMigration.RevokeTokenAction",
+ revoke_token_action);
+}
+
bool DiceAccountReconcilorDelegate::ShouldRevokeTokensOnCookieDeleted() {
return account_consistency_ == AccountConsistencyMethod::kDice;
}
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
index d62c0375164..f1efabad871 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -19,7 +19,8 @@ namespace signin {
class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
public:
DiceAccountReconcilorDelegate(SigninClient* signin_client,
- AccountConsistencyMethod account_consistency);
+ AccountConsistencyMethod account_consistency,
+ bool migration_completed);
~DiceAccountReconcilorDelegate() override {}
// AccountReconcilorDelegate:
@@ -39,6 +40,11 @@ class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
bool will_logout) const override;
RevokeTokenOption ShouldRevokeSecondaryTokensBeforeReconcile(
const std::vector<gaia::ListedAccount>& gaia_accounts) override;
+ // Returns true if in force migration to dice state.
+ bool ShouldRevokeTokensNotInCookies() const override;
+ // Disables force dice migration and sets dice migration as completed.
+ void OnRevokeTokensNotInCookiesCompleted(
+ RevokeTokenAction revoke_token_action) override;
void OnReconcileFinished(const CoreAccountId& first_account,
bool reconcile_is_noop) override;
bool ShouldRevokeTokensOnCookieDeleted() override;
@@ -82,6 +88,7 @@ class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
SigninClient* signin_client_;
AccountConsistencyMethod account_consistency_;
+ bool migration_completed_;
// Last known "first account". Used when cookies are lost as a best guess.
CoreAccountId last_known_first_account_;
diff --git a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
index 5e3134224b7..10f66fcf2e3 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -32,17 +32,21 @@ namespace signin {
TEST(DiceAccountReconcilorDelegateTest, RevokeTokens) {
sync_preferences::TestingPrefServiceSyncable pref_service;
TestSigninClient client(&pref_service);
+ gaia::ListedAccount gaia_account;
+ gaia_account.id = CoreAccountId("other");
{
// Dice is enabled, revoke only tokens in error state.
- DiceAccountReconcilorDelegate delegate(&client,
- AccountConsistencyMethod::kDice);
- EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
- delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
- std::vector<gaia::ListedAccount>()));
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDice, /*migration_completed=*/true);
+ EXPECT_EQ(
+ signin::AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
+ delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
+ std::vector<gaia::ListedAccount>()));
}
{
DiceAccountReconcilorDelegate delegate(
- &client, AccountConsistencyMethod::kDiceMigration);
+ &client, AccountConsistencyMethod::kDiceMigration,
+ /*migration_completed=*/false);
// Gaia accounts are not empty, don't revoke.
gaia::ListedAccount gaia_account;
gaia_account.id = CoreAccountId("other");
@@ -68,7 +72,8 @@ TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
testing::InSequence mock_sequence;
EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
DiceAccountReconcilorDelegate delegate(
- &client, AccountConsistencyMethod::kDiceMigration);
+ &client, AccountConsistencyMethod::kDiceMigration,
+ /*migration_completed=*/false);
delegate.OnReconcileFinished(CoreAccountId("account"),
true /* is_reconcile_noop */);
}
@@ -81,7 +86,8 @@ TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
testing::InSequence mock_sequence;
EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
DiceAccountReconcilorDelegate delegate(
- &client, AccountConsistencyMethod::kDiceMigration);
+ &client, AccountConsistencyMethod::kDiceMigration,
+ /*migration_completed=*/false);
delegate.OnReconcileFinished(CoreAccountId("account"),
false /* is_reconcile_noop */);
}
@@ -91,26 +97,38 @@ TEST(DiceAccountReconcilorDelegateTest, OnReconcileFinished) {
testing::InSequence mock_sequence;
EXPECT_CALL(client, SetReadyForDiceMigration(true)).Times(1);
DiceAccountReconcilorDelegate delegate(
- &client, AccountConsistencyMethod::kDiceMigration);
+ &client, AccountConsistencyMethod::kDiceMigration, false);
delegate.OnReconcileFinished(CoreAccountId("account"),
true /* is_reconcile_noop */);
}
}
-TEST(DiceAccountReconcilorDelegateTest, ShouldRevokeTokensOnCookieDeleted) {
+TEST(DiceAccountReconcilorDelegateTest, ShouldRevokeTokensBasedOnCookies) {
sync_preferences::TestingPrefServiceSyncable pref_service;
TestSigninClient client(&pref_service);
{
// Dice is enabled, revoke tokens when Gaia cookie is deleted.
+ DiceAccountReconcilorDelegate delegate(
+ &client, AccountConsistencyMethod::kDice, /*migration_completed=*/true);
+ EXPECT_EQ(true, delegate.ShouldRevokeTokensOnCookieDeleted());
+ EXPECT_EQ(false, delegate.ShouldRevokeTokensNotInCookies());
+ }
+ {
+ // Dice is enabled, migration not completed, revoke tokens when
+ // Gaia cookie is deleted.
DiceAccountReconcilorDelegate delegate(&client,
- AccountConsistencyMethod::kDice);
+ AccountConsistencyMethod::kDice,
+ /*migration_completed=*/false);
EXPECT_EQ(true, delegate.ShouldRevokeTokensOnCookieDeleted());
+ EXPECT_EQ(true, delegate.ShouldRevokeTokensNotInCookies());
}
{
// Dice is not enabled, do not revoke tokens when Gaia cookie is deleted.
DiceAccountReconcilorDelegate delegate(
- &client, AccountConsistencyMethod::kDiceMigration);
+ &client, AccountConsistencyMethod::kDiceMigration,
+ /*migration_completed=*/false);
EXPECT_EQ(false, delegate.ShouldRevokeTokensOnCookieDeleted());
+ EXPECT_EQ(false, delegate.ShouldRevokeTokensNotInCookies());
}
}
diff --git a/chromium/components/signin/core/browser/signin_error_controller.cc b/chromium/components/signin/core/browser/signin_error_controller.cc
index bbfd519f5a0..88eb68fa75c 100644
--- a/chromium/components/signin/core/browser/signin_error_controller.cc
+++ b/chromium/components/signin/core/browser/signin_error_controller.cc
@@ -11,7 +11,6 @@ SigninErrorController::SigninErrorController(
signin::IdentityManager* identity_manager)
: account_mode_(mode),
identity_manager_(identity_manager),
- scoped_identity_manager_observer_(this),
auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
DCHECK(identity_manager_);
scoped_identity_manager_observer_.Add(identity_manager_);
@@ -27,10 +26,10 @@ void SigninErrorController::Shutdown() {
void SigninErrorController::Update() {
const GoogleServiceAuthError::State prev_error_state = auth_error_.state();
- const std::string prev_account_id = error_account_id_;
+ const CoreAccountId prev_account_id = error_account_id_;
bool error_changed = false;
- const std::string& primary_account_id =
+ const CoreAccountId& primary_account_id =
identity_manager_->GetPrimaryAccountId();
if (identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
@@ -51,7 +50,7 @@ void SigninErrorController::Update() {
if (!error_changed && prev_error_state != GoogleServiceAuthError::NONE) {
// No provider reported an error, so clear the error we have now.
auth_error_ = GoogleServiceAuthError::AuthErrorNone();
- error_account_id_.clear();
+ error_account_id_ = CoreAccountId();
error_changed = true;
}
@@ -70,8 +69,8 @@ void SigninErrorController::Update() {
}
bool SigninErrorController::UpdateSecondaryAccountErrors(
- const std::string& primary_account_id,
- const std::string& prev_account_id,
+ const CoreAccountId& primary_account_id,
+ const CoreAccountId& prev_account_id,
const GoogleServiceAuthError::State& prev_error_state) {
// This method should not have been called if we are in
// |AccountMode::PRIMARY_ACCOUNT|.
@@ -84,7 +83,7 @@ bool SigninErrorController::UpdateSecondaryAccountErrors(
bool error_changed = false;
for (const CoreAccountInfo& account_info :
identity_manager_->GetAccountsWithRefreshTokens()) {
- std::string account_id = account_info.account_id;
+ CoreAccountId account_id = account_info.account_id;
// Ignore the Primary Account. We are only interested in Secondary Accounts.
if (account_id == primary_account_id) {
diff --git a/chromium/components/signin/core/browser/signin_error_controller.h b/chromium/components/signin/core/browser/signin_error_controller.h
index b1f64862ecc..77324e7e752 100644
--- a/chromium/components/signin/core/browser/signin_error_controller.h
+++ b/chromium/components/signin/core/browser/signin_error_controller.h
@@ -57,7 +57,7 @@ class SigninErrorController : public KeyedService,
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
- const std::string& error_account_id() const { return error_account_id_; }
+ const CoreAccountId& error_account_id() const { return error_account_id_; }
const GoogleServiceAuthError& auth_error() const { return auth_error_; }
private:
@@ -71,8 +71,8 @@ class SigninErrorController : public KeyedService,
// Note: This function must not be called if |account_mode_| is
// |AccountMode::PRIMARY_ACCOUNT|.
bool UpdateSecondaryAccountErrors(
- const std::string& primary_account_id,
- const std::string& prev_account_id,
+ const CoreAccountId& primary_account_id,
+ const CoreAccountId& prev_account_id,
const GoogleServiceAuthError::State& prev_error_state);
// signin::IdentityManager::Observer:
@@ -88,11 +88,11 @@ class SigninErrorController : public KeyedService,
const AccountMode account_mode_;
signin::IdentityManager* identity_manager_;
- ScopedObserver<signin::IdentityManager, SigninErrorController>
- scoped_identity_manager_observer_;
+ ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
+ scoped_identity_manager_observer_{this};
// The account that generated the last auth error.
- std::string error_account_id_;
+ CoreAccountId error_account_id_;
// The auth error detected the last time AuthStatusChanged() was invoked (or
// NONE if AuthStatusChanged() has never been invoked).
diff --git a/chromium/components/signin/core/browser/signin_error_controller_unittest.cc b/chromium/components/signin/core/browser/signin_error_controller_unittest.cc
index 92b478fb49d..21fa1530d82 100644
--- a/chromium/components/signin/core/browser/signin_error_controller_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_error_controller_unittest.cc
@@ -11,7 +11,7 @@
#include "base/scoped_observer.h"
#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -35,7 +35,7 @@ TEST(SigninErrorControllerTest, SingleAccount) {
MockSigninErrorControllerObserver observer;
EXPECT_CALL(observer, OnErrorChanged()).Times(0);
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
@@ -51,7 +51,7 @@ TEST(SigninErrorControllerTest, SingleAccount) {
// updated.
EXPECT_CALL(observer, OnErrorChanged()).Times(0);
- std::string test_account_id =
+ CoreAccountId test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
::testing::Mock::VerifyAndClearExpectations(&observer);
@@ -83,12 +83,12 @@ TEST(SigninErrorControllerTest, SingleAccount) {
}
TEST(SigninErrorControllerTest, AccountTransitionAnyAccount) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
- std::string test_account_id =
+ CoreAccountId test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
- std::string other_test_account_id =
+ CoreAccountId other_test_account_id =
identity_test_env.MakeAccountAvailable(kOtherTestEmail).account_id;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
@@ -114,14 +114,14 @@ TEST(SigninErrorControllerTest, AccountTransitionAnyAccount) {
// ChromeOS.
#if !defined(OS_CHROMEOS)
TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
signin::PrimaryAccountMutator* primary_account_mutator =
identity_test_env.identity_manager()->GetPrimaryAccountMutator();
- std::string test_account_id =
+ CoreAccountId test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
- std::string other_test_account_id =
+ CoreAccountId other_test_account_id =
identity_test_env.MakeAccountAvailable(kOtherTestEmail).account_id;
SigninErrorController error_controller(
SigninErrorController::AccountMode::PRIMARY_ACCOUNT,
@@ -179,10 +179,10 @@ TEST(SigninErrorControllerTest, AccountTransitionPrimaryAccount) {
// Verify that SigninErrorController handles errors properly.
TEST(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
- std::string test_account_id =
+ CoreAccountId test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
@@ -219,19 +219,19 @@ TEST(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
} else {
EXPECT_EQ(GoogleServiceAuthError::NONE,
error_controller.auth_error().state());
- EXPECT_EQ("", error_controller.error_account_id());
+ EXPECT_EQ(CoreAccountId(), error_controller.error_account_id());
}
}
}
// Verify that existing error is not replaced by new error.
TEST(SigninErrorControllerTest, AuthStatusChange) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
- std::string test_account_id =
+ CoreAccountId test_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
- std::string other_test_account_id =
+ CoreAccountId other_test_account_id =
identity_test_env.MakeAccountAvailable(kOtherTestEmail).account_id;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
@@ -282,12 +282,12 @@ TEST(SigninErrorControllerTest, AuthStatusChange) {
TEST(SigninErrorControllerTest,
PrimaryAccountErrorsArePreferredToSecondaryAccountErrors) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
AccountInfo primary_account_info =
identity_test_env.MakePrimaryAccountAvailable(kPrimaryAccountEmail);
- std::string secondary_account_id =
+ CoreAccountId secondary_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
@@ -329,12 +329,12 @@ TEST(SigninErrorControllerTest,
}
TEST(SigninErrorControllerTest, PrimaryAccountErrorsAreSticky) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment identity_test_env;
AccountInfo primary_account_info =
identity_test_env.MakePrimaryAccountAvailable(kPrimaryAccountEmail);
- std::string secondary_account_id =
+ CoreAccountId secondary_account_id =
identity_test_env.MakeAccountAvailable(kTestEmail).account_id;
SigninErrorController error_controller(
SigninErrorController::AccountMode::ANY_ACCOUNT,
diff --git a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
index c36fd26f945..b6f8773773c 100644
--- a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -10,7 +10,7 @@
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/prefs/pref_member.h"
@@ -43,8 +43,8 @@ class SigninHeaderHelperTest : public testing::Test {
settings_map_ = new HostContentSettingsMap(
&prefs_, false /* is_off_the_record */, false /* store_last_modified */,
false /* migrate_requesting_and_top_level_origin_settings */);
- cookie_settings_ =
- new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");
+ cookie_settings_ = new content_settings::CookieSettings(settings_map_.get(),
+ &prefs_, false, "");
}
void TearDown() override { settings_map_->ShutdownOnUIThread(); }
@@ -112,7 +112,7 @@ class SigninHeaderHelperTest : public testing::Test {
}
#endif
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool sync_enabled_ = false;
std::string device_id_ = kTestDeviceId;
diff --git a/chromium/components/signin/core/browser/signin_investigator_unittest.cc b/chromium/components/signin/core/browser/signin_investigator_unittest.cc
index 31df9131e47..d9e30548d08 100644
--- a/chromium/components/signin/core/browser/signin_investigator_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_investigator_unittest.cc
@@ -5,7 +5,7 @@
#include <string>
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/signin/core/browser/signin_investigator.h"
#include "components/signin/public/base/signin_metrics.h"
@@ -33,7 +33,7 @@ class FakeProvider : public SigninInvestigator::DependencyProvider {
PrefService* GetPrefs() override { return &prefs_; }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
signin::IdentityTestEnvironment identity_test_env_;
};
diff --git a/chromium/components/signin/internal/README.md b/chromium/components/signin/internal/README.md
new file mode 100644
index 00000000000..ce0af3bae55
--- /dev/null
+++ b/chromium/components/signin/internal/README.md
@@ -0,0 +1,3 @@
+The internal implementation of //components/signin/public; visible only to
+implementation files in that directory. Subdirectories may further restrict
+their visibility to only certain subdirectories of //components/signin/public.
diff --git a/chromium/components/signin/internal/identity_manager/BUILD.gn b/chromium/components/signin/internal/identity_manager/BUILD.gn
index 40caa1eccaf..a6a8aa9037a 100644
--- a/chromium/components/signin/internal/identity_manager/BUILD.gn
+++ b/chromium/components/signin/internal/identity_manager/BUILD.gn
@@ -45,6 +45,7 @@ source_set("identity_manager") {
"profile_oauth2_token_service_delegate_chromeos.h",
"profile_oauth2_token_service_delegate_ios.h",
"profile_oauth2_token_service_delegate_ios.mm",
+ "profile_oauth2_token_service_observer.h",
"ubertoken_fetcher_impl.cc",
"ubertoken_fetcher_impl.h",
]
diff --git a/chromium/components/signin/internal/identity_manager/DEPS b/chromium/components/signin/internal/identity_manager/DEPS
index 4485df3b6a5..5898a127076 100644
--- a/chromium/components/signin/internal/identity_manager/DEPS
+++ b/chromium/components/signin/internal/identity_manager/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+chromeos/constants/chromeos_switches.h",
+ "+chromeos/constants/chromeos_features.h",
"+mojo/public",
]
diff --git a/chromium/components/signin/internal/identity_manager/README.md b/chromium/components/signin/internal/identity_manager/README.md
new file mode 100644
index 00000000000..501040b650a
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/README.md
@@ -0,0 +1,72 @@
+The internal implementation of //components/signin/public/identity_manager;
+visible only to implementation files in
+//components/signin/public/identity_manager. This directory contains
+implementations of pure interfaces in
+//components/signin/public/identity_manager as well as internal classes.
+
+Here is how the various core internal classes support the public functionality
+of IdentityManager (see
+//components/signin/public/identity_manager/README.md for definitions of core
+terms):
+
+- PrimaryAccountManager: Maintains the information of the primary account. When
+ it is set/cleared, calls out to IdentityManager via callbacks, resulting in the
+ firing of IdentityManager::Observer notifications. Setting/clearing occurs via
+ PrimaryAccountMutatorImpl.
+ Historically was exposed as SigninManager(Base).
+- PrimaryAccountPolicyManager: Helper class for PrimaryAccountManager that
+ manages interactions between policy and the primary account, e.g. clearing the
+ primary account if signin becomes disallowed by policy. Historically was
+ contained within SigninManager.
+- ProfileOAuth2TokenService: Manages the OAuth2 tokens for the user's Gaia
+ accounts. Delegates much of the functionality for refresh tokens to its
+ various platform-specific delegates, and delegates much of the functionality
+ for access tokens to the lower-level OAuth2AccessTokenManager class. Supports
+ the IdentityManager APIs for querying the state of the accounts with refresh
+ tokens and for fetching access tokens via (PrimaryAccount)AccessTokenFetcher.
+ Mutation of refresh tokens occurs via platform-specific flows:
+ - AcccountsMutatorImpl on desktop
+ - DeviceAccountsSynchronizerImpl on iOS
+ - Within the token service delegate by observing AccountManager on ChromeOS
+ - Via a legacy flow on Android (https://crbug.com/963391)
+ Has an observer API (ProfileOAuth2TokenServiceObserver); IdentityManager
+ observes token-related events via this API in order to fire
+ IdentityManager::Observer events. Other internal classes also observe
+ token-related events, which is why PO2TS still has observers rather than
+ directly calling out to IdentityManager via callbacks as other internal
+ classes do.
+- ProfileOAuth2TokenServiceDelegate: Mostly-abstract class via which
+ ProfileOAuth2TokenService interacts with platform-specific functionality for
+ OAuth2 tokens. Has various platform-specific implementations. The
+ platform-specific implementations glue the cross-platform
+ ProfileOAuth2TokenService interface to the underlying platform support, and
+ dictate the firing of ProfileOAuth2TokenServiceObserver events.
+- AccountTrackerService: Maintains the mapping from account ID to account
+ information for the user's Gaia accounts with refresh tokens. Supports the
+ various IdentityManager::FindAccountInfoXXX() methods. When account info is
+ updated/removed for a given account, calls out to IdentityManager via
+ callbacks, resulting in the firing of IdentityManager::Observer notifications.
+ Conceptually below ProfileOAuth2TokenService, as it is needed by various
+ platform-specific implementations of ProfileOAuth2TokenServiceDelegate, which
+ themselves are needed by ProfileOAuth2TokenService.
+- AccountFetcherService: Fetches account information for the user's Gaia
+ accounts with refresh tokens in order to populate this information in
+ AccountTrackerService. Observes ProfileOAuth2TokenService in order to observe
+ addition and removal of accounts with refresh tokens to initiate
+ fetching/removal of account information. Split from AccountTrackerService in
+ order to support knowledge of ProfileOAuth2TokenService.
+- GaiaCookieManagerService: Maintains information about the accounts in the Gaia
+ cookie. Supports IdentityManager::GetAccountsInCookieJar(). When the accounts
+ in the cookie are updated or the cookie itself is deleted, calls out to
+ IdentityManager via callbacks, resulting in the firing of
+ IdentityManager::Observer notifications.
+
+The layering of the core internal classes is as follows, with higher-level classes
+listed first:
+
+- PrimaryAccountManager
+- AccountFetcherService
+- GaiaCookieManagerService (note: GCMS and AFS are independent peers)
+- ProfileOAuth2TokenService
+- various ProfileOAuth2TokenServiceDelegate implementations
+- AccountTrackerService
diff --git a/chromium/components/signin/internal/identity_manager/account_fetcher_service.h b/chromium/components/signin/internal/identity_manager/account_fetcher_service.h
index 0cd1249ff97..7f07da9d0bd 100644
--- a/chromium/components/signin/internal/identity_manager/account_fetcher_service.h
+++ b/chromium/components/signin/internal/identity_manager/account_fetcher_service.h
@@ -15,7 +15,7 @@
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
class AccountInfoFetcher;
class AccountTrackerService;
@@ -41,7 +41,7 @@ class ImageDecoder;
class ImageFetcherImpl;
} // namespace image_fetcher
-class AccountFetcherService : public OAuth2TokenServiceObserver {
+class AccountFetcherService : public ProfileOAuth2TokenServiceObserver {
public:
// Name of the preference that tracks the int64_t representation of the last
// time the AccountTrackerService was updated.
@@ -94,7 +94,7 @@ class AccountFetcherService : public OAuth2TokenServiceObserver {
bool is_child_account);
#endif
- // OAuth2TokenServiceObserver implementation.
+ // ProfileOAuth2TokenServiceObserver implementation.
void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
void OnRefreshTokensLoaded() override;
diff --git a/chromium/components/signin/internal/identity_manager/account_tracker_service.cc b/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
index 710345b7cf6..76678a0e258 100644
--- a/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
@@ -124,8 +124,8 @@ void AccountTrackerService::Initialize(PrefService* pref_service,
if (!user_data_dir_.empty()) {
// |image_storage_task_runner_| is a sequenced runner because we want to
// avoid read and write operations to the same file at the same time.
- image_storage_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ image_storage_task_runner_ = base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
LoadAccountImagesFromDisk();
}
@@ -656,15 +656,10 @@ AccountTrackerService::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(java_ref_);
}
-void JNI_AccountTrackerService_SeedAccountsInfo(
+void AccountTrackerService::SeedAccountsInfo(
JNIEnv* env,
- jlong nativeAccountTrackerService,
const base::android::JavaParamRef<jobjectArray>& gaiaIds,
const base::android::JavaParamRef<jobjectArray>& accountNames) {
- AccountTrackerService* service =
- reinterpret_cast<AccountTrackerService*>(nativeAccountTrackerService);
- DCHECK(service);
-
std::vector<std::string> gaia_ids;
std::vector<std::string> account_names;
base::android::AppendJavaStringArrayToStringVector(env, gaiaIds, &gaia_ids);
@@ -675,28 +670,22 @@ void JNI_AccountTrackerService_SeedAccountsInfo(
DVLOG(1) << "AccountTrackerService.SeedAccountsInfo: "
<< " number of accounts " << gaia_ids.size();
for (size_t i = 0; i < gaia_ids.size(); ++i) {
- service->SeedAccountInfo(gaia_ids[i], account_names[i]);
+ SeedAccountInfo(gaia_ids[i], account_names[i]);
}
}
-jboolean JNI_AccountTrackerService_AreAccountsSeeded(
+jboolean AccountTrackerService::AreAccountsSeeded(
JNIEnv* env,
- jlong nativeAccountTrackerService,
- const base::android::JavaParamRef<jobjectArray>& accountNames) {
- AccountTrackerService* service =
- reinterpret_cast<AccountTrackerService*>(nativeAccountTrackerService);
- DCHECK(service);
-
+ const base::android::JavaParamRef<jobjectArray>& accountNames) const {
std::vector<std::string> account_names;
base::android::AppendJavaStringArrayToStringVector(env, accountNames,
&account_names);
- bool migrated =
- service->GetMigrationState() ==
- AccountTrackerService::AccountIdMigrationState::MIGRATION_DONE;
+ const bool migrated =
+ GetMigrationState() == AccountIdMigrationState::MIGRATION_DONE;
for (const auto& account_name : account_names) {
- AccountInfo info = service->FindAccountInfoByEmail(account_name);
+ AccountInfo info = FindAccountInfoByEmail(account_name);
if (info.account_id.empty()) {
return false;
}
diff --git a/chromium/components/signin/internal/identity_manager/account_tracker_service.h b/chromium/components/signin/internal/identity_manager/account_tracker_service.h
index 5fc76f4f017..171812926ae 100644
--- a/chromium/components/signin/internal/identity_manager/account_tracker_service.h
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service.h
@@ -40,7 +40,7 @@ class Image;
namespace signin {
class IdentityManager;
void SimulateSuccessfulFetchOfAccountInfo(IdentityManager*,
- const std::string&,
+ const CoreAccountId&,
const std::string&,
const std::string&,
const std::string&,
@@ -126,6 +126,17 @@ class AccountTrackerService {
#if defined(OS_ANDROID)
// Returns a reference to the corresponding Java AccountTrackerService object.
base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
+ // Seeds the accounts with |gaiaIds| and |accountNames|.
+ void SeedAccountsInfo(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobjectArray>& gaiaIds,
+ const base::android::JavaParamRef<jobjectArray>& accountNames);
+
+ // Checks whether all the accounts with |accountNames| are seeded.
+ jboolean AreAccountsSeeded(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobjectArray>& accountNames) const;
#endif
// If set, this callback will be invoked whenever the details of a tracked
@@ -150,7 +161,7 @@ class AccountTrackerService {
friend class AccountFetcherService;
friend void signin::SimulateSuccessfulFetchOfAccountInfo(
signin::IdentityManager*,
- const std::string&,
+ const CoreAccountId&,
const std::string&,
const std::string&,
const std::string&,
diff --git a/chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc b/chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
index a11e96f3681..18ca47453d9 100644
--- a/chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
@@ -11,7 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
#include "components/image_fetcher/core/image_data_fetcher.h"
@@ -118,7 +118,7 @@ std::string AccountKeyToPictureURLWithSize(AccountKey account_key) {
class TrackingEvent {
public:
TrackingEvent(TrackingEventType type,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& gaia_id,
const std::string& email)
: type_(type),
@@ -143,11 +143,11 @@ class TrackingEvent {
}
return base::StringPrintf(
"{ type: %s, account_id: %s, gaia: %s, email: %s }", typestr,
- account_id_.c_str(), gaia_id_.c_str(), email_.c_str());
+ account_id_.id.c_str(), gaia_id_.c_str(), email_.c_str());
}
TrackingEventType type_;
- std::string account_id_;
+ CoreAccountId account_id_;
std::string gaia_id_;
std::string email_;
};
@@ -186,7 +186,7 @@ class AccountTrackerServiceTest : public testing::Test {
void SetUp() override {
testing::Test::SetUp();
CreateAccountTracker(base::FilePath(), /*network_enabled=*/true);
- fake_oauth2_token_service_.LoadCredentials("");
+ fake_oauth2_token_service_.LoadCredentials(CoreAccountId());
}
void TearDown() override {
@@ -220,9 +220,9 @@ class AccountTrackerServiceTest : public testing::Test {
}
// Helpers to fake access token and user info fetching
- std::string AccountKeyToAccountId(AccountKey account_key) {
+ CoreAccountId AccountKeyToAccountId(AccountKey account_key) {
if (force_account_id_to_email_for_legacy_tests_)
- return AccountKeyToEmail(account_key);
+ return CoreAccountId(AccountKeyToEmail(account_key));
return AccountTrackerService::PickAccountIdForAccount(
&pref_service_, AccountKeyToGaiaId(account_key),
@@ -319,7 +319,7 @@ class AccountTrackerServiceTest : public testing::Test {
void ReturnFetchResults(net::HttpStatusCode response_code,
const std::string& response_string);
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
private:
void CreateAccountTracker(base::FilePath path, bool network_enabled) {
@@ -407,7 +407,7 @@ void AccountTrackerServiceTest::ReturnAccountImageFetchSuccess(
AccountKey account_key) {
GetTestURLLoaderFactory()->AddResponse(
AccountKeyToPictureURLWithSize(account_key), "image data");
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void AccountTrackerServiceTest::ReturnAccountImageFetchFailure(
@@ -415,7 +415,7 @@ void AccountTrackerServiceTest::ReturnAccountImageFetchFailure(
GetTestURLLoaderFactory()->AddResponse(
AccountKeyToPictureURLWithSize(account_key), std::string(),
net::HTTP_BAD_REQUEST);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
TEST_F(AccountTrackerServiceTest, Basic) {}
@@ -576,7 +576,7 @@ TEST_F(AccountTrackerServiceTest, GetAccounts) {
TEST_F(AccountTrackerServiceTest, GetAccountInfo_Empty) {
AccountInfo info = account_tracker()->GetAccountInfo(
AccountKeyToAccountId(kAccountKeyAlpha));
- EXPECT_EQ(std::string(), info.account_id);
+ EXPECT_EQ(CoreAccountId(), info.account_id);
}
TEST_F(AccountTrackerServiceTest, GetAccountInfo_TokenAvailable) {
@@ -650,7 +650,7 @@ TEST_F(AccountTrackerServiceTest, FindAccountInfoByEmail) {
const std::string email_beta = AccountKeyToEmail(kAccountKeyBeta);
info = account_tracker()->FindAccountInfoByEmail(email_beta);
- EXPECT_EQ(std::string(), info.account_id);
+ EXPECT_EQ(CoreAccountId(), info.account_id);
}
TEST_F(AccountTrackerServiceTest, Persistence) {
@@ -682,7 +682,7 @@ TEST_F(AccountTrackerServiceTest, Persistence) {
AccountKeyToEmail(kAccountKeyBeta)),
}));
// Wait until all account images are loaded.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_TRUE(CheckAccountTrackerEvents({
TrackingEvent(UPDATED, AccountKeyToAccountId(kAccountKeyAlpha),
AccountKeyToGaiaId(kAccountKeyAlpha),
@@ -735,7 +735,7 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfo) {
const std::string gaia_id = AccountKeyToGaiaId(kAccountKeyFooBar);
const std::string email = AccountKeyToEmail(kAccountKeyFooBar);
const std::string email_dotted = AccountKeyToEmail(kAccountKeyFooDotBar);
- const std::string account_id =
+ const CoreAccountId account_id =
account_tracker()->PickAccountIdForAccount(gaia_id, email);
account_tracker()->SeedAccountInfo(gaia_id, email);
@@ -962,8 +962,10 @@ TEST_F(AccountTrackerServiceTest, MigrateAccountIdToGaiaId) {
EXPECT_EQ(account_tracker()->GetMigrationState(),
AccountTrackerService::MIGRATION_IN_PROGRESS);
- AccountInfo account_info = account_tracker()->GetAccountInfo(gaia_alpha);
- EXPECT_EQ(account_info.account_id, gaia_alpha);
+ CoreAccountId gaia_alpha_account_id(gaia_alpha);
+ AccountInfo account_info =
+ account_tracker()->GetAccountInfo(gaia_alpha_account_id);
+ EXPECT_EQ(account_info.account_id, gaia_alpha_account_id);
EXPECT_EQ(account_info.gaia, gaia_alpha);
EXPECT_EQ(account_info.email, email_alpha);
@@ -1006,13 +1008,16 @@ TEST_F(AccountTrackerServiceTest, CanNotMigrateAccountIdToGaiaId) {
EXPECT_EQ(account_tracker()->GetMigrationState(),
AccountTrackerService::MIGRATION_NOT_STARTED);
- AccountInfo account_info = account_tracker()->GetAccountInfo(email_alpha);
- EXPECT_EQ(account_info.account_id, email_alpha);
+ CoreAccountId email_alpha_account_id(email_alpha);
+ AccountInfo account_info =
+ account_tracker()->GetAccountInfo(email_alpha_account_id);
+ EXPECT_EQ(account_info.account_id, email_alpha_account_id);
EXPECT_EQ(account_info.gaia, gaia_alpha);
EXPECT_EQ(account_info.email, email_alpha);
- account_info = account_tracker()->GetAccountInfo(email_beta);
- EXPECT_EQ(account_info.account_id, email_beta);
+ CoreAccountId email_beta_account_id(email_beta);
+ account_info = account_tracker()->GetAccountInfo(email_beta_account_id);
+ EXPECT_EQ(account_info.account_id, email_beta_account_id);
EXPECT_EQ(account_info.email, email_beta);
std::vector<AccountInfo> accounts = account_tracker()->GetAccounts();
@@ -1057,13 +1062,16 @@ TEST_F(AccountTrackerServiceTest, GaiaIdMigrationCrashInTheMiddle) {
EXPECT_EQ(account_tracker()->GetMigrationState(),
AccountTrackerService::MIGRATION_IN_PROGRESS);
- AccountInfo account_info = account_tracker()->GetAccountInfo(gaia_alpha);
- EXPECT_EQ(account_info.account_id, gaia_alpha);
+ CoreAccountId gaia_alpha_account_id(gaia_alpha);
+ AccountInfo account_info =
+ account_tracker()->GetAccountInfo(gaia_alpha_account_id);
+ EXPECT_EQ(account_info.account_id, gaia_alpha_account_id);
EXPECT_EQ(account_info.gaia, gaia_alpha);
EXPECT_EQ(account_info.email, email_alpha);
- account_info = account_tracker()->GetAccountInfo(gaia_beta);
- EXPECT_EQ(account_info.account_id, gaia_beta);
+ CoreAccountId gaia_beta_account_id(gaia_beta);
+ account_info = account_tracker()->GetAccountInfo(gaia_beta_account_id);
+ EXPECT_EQ(account_info.account_id, gaia_beta_account_id);
EXPECT_EQ(account_info.gaia, gaia_beta);
EXPECT_EQ(account_info.email, email_beta);
@@ -1077,13 +1085,13 @@ TEST_F(AccountTrackerServiceTest, GaiaIdMigrationCrashInTheMiddle) {
EXPECT_EQ(account_tracker()->GetMigrationState(),
AccountTrackerService::MIGRATION_DONE);
- account_info = account_tracker()->GetAccountInfo(gaia_alpha);
- EXPECT_EQ(account_info.account_id, gaia_alpha);
+ account_info = account_tracker()->GetAccountInfo(gaia_alpha_account_id);
+ EXPECT_EQ(account_info.account_id, gaia_alpha_account_id);
EXPECT_EQ(account_info.gaia, gaia_alpha);
EXPECT_EQ(account_info.email, email_alpha);
- account_info = account_tracker()->GetAccountInfo(gaia_beta);
- EXPECT_EQ(account_info.account_id, gaia_beta);
+ account_info = account_tracker()->GetAccountInfo(gaia_beta_account_id);
+ EXPECT_EQ(account_info.account_id, gaia_beta_account_id);
EXPECT_EQ(account_info.gaia, gaia_beta);
EXPECT_EQ(account_info.email, email_beta);
@@ -1291,7 +1299,7 @@ TEST_F(AccountTrackerServiceTest, AdvancedProtectionAccountBasic) {
SimulateTokenAvailable(kAccountKeyAdvancedProtection);
IssueAccessToken(kAccountKeyAdvancedProtection);
- const std::string account_id =
+ const CoreAccountId account_id =
AccountKeyToAccountId(kAccountKeyAdvancedProtection);
account_tracker()->SetIsAdvancedProtectionAccount(account_id, true);
AccountInfo info = account_tracker()->GetAccountInfo(account_id);
diff --git a/chromium/components/signin/internal/identity_manager/android/BUILD.gn b/chromium/components/signin/internal/identity_manager/android/BUILD.gn
new file mode 100644
index 00000000000..d9b022f516c
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/android/BUILD.gn
@@ -0,0 +1,9 @@
+import("//build/config/android/rules.gni")
+
+generate_jni("jni_headers") {
+ namespace = "signin"
+ sources = [
+ "//components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountInfo.java",
+ "//components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java",
+ ]
+}
diff --git a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc
index 586ce74d74f..2ae836ad7b5 100644
--- a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc
@@ -26,7 +26,7 @@ FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService(
FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() {}
void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& access_token,
const base::Time& expiration) {
GetFakeAccessTokenManager()->IssueAllTokensForAccount(
@@ -34,14 +34,14 @@ void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
}
void FakeProfileOAuth2TokenService::IssueAllTokensForAccount(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
GetFakeAccessTokenManager()->IssueAllTokensForAccount(account_id,
token_response);
}
void FakeProfileOAuth2TokenService::IssueErrorForAllPendingRequestsForAccount(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
GetFakeAccessTokenManager()->IssueErrorForAllPendingRequestsForAccount(
account_id, error);
diff --git a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h
index f06a83a1b14..8245090ec7b 100644
--- a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h
@@ -47,17 +47,17 @@ class FakeProfileOAuth2TokenService : public ProfileOAuth2TokenService {
GetPendingRequests();
// Helper routines to issue tokens for pending requests.
- void IssueAllTokensForAccount(const std::string& account_id,
+ void IssueAllTokensForAccount(const CoreAccountId& account_id,
const std::string& access_token,
const base::Time& expiration);
// Helper routines to issue token for pending requests based on TokenResponse.
void IssueAllTokensForAccount(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const OAuth2AccessTokenConsumer::TokenResponse& token_response);
void IssueErrorForAllPendingRequestsForAccount(
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
void IssueTokenForScope(const OAuth2AccessTokenManager::ScopeSet& scopes,
diff --git a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc
index 701bbe89c68..bef96b8b886 100644
--- a/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc
+++ b/chromium/components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.cc
@@ -154,9 +154,9 @@ void FakeProfileOAuth2TokenServiceDelegate::UpdateAuthError(
const CoreAccountId& account_id,
const GoogleServiceAuthError& error) {
backoff_entry_.InformOfRequest(!error.IsTransientError());
- // Drop transient errors to match OAuth2TokenService's stated contract for
- // GetAuthError() and to allow clients to test proper behavior in the case of
- // transient errors.
+ // Drop transient errors to match ProfileOAuth2TokenService's stated contract
+ // for GetAuthError() and to allow clients to test proper behavior in the case
+ // of transient errors.
if (error.IsTransientError())
return;
diff --git a/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
index 6cddb7a2071..bfda70d5b00 100644
--- a/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
+++ b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
@@ -13,19 +13,19 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/json/json_reader.h"
-#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
#include "components/signin/internal/identity_manager/oauth_multilogin_helper.h"
#include "components/signin/internal/identity_manager/ubertoken_fetcher_impl.h"
#include "components/signin/public/base/signin_metrics.h"
+#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
@@ -95,30 +95,6 @@ void RecordLogoutRequestState(LogoutRequestState logout_state) {
UMA_HISTOGRAM_ENUMERATION("Signin.GaiaCookieManager.Logout", logout_state);
}
-// Record ListAccounts errors for individual retries.
-void RecordListAccountsRetryResult(GoogleServiceAuthError error,
- int retry_attempt_number) {
- int net_error = net::OK;
- switch (error.state()) {
- case GoogleServiceAuthError::NONE:
- net_error = net::OK;
- break;
- case GoogleServiceAuthError::CONNECTION_FAILED:
- net_error = error.network_error();
- break;
- case GoogleServiceAuthError::REQUEST_CANCELED:
- net_error = net::ERR_ABORTED;
- break;
- default:
- return; // There is an error not related to network.
- }
-
- std::string histogram_name =
- base::StringPrintf("Gaia.AuthFetcher.ListAccounts.NetErrorCodes.Retry_%i",
- retry_attempt_number);
- base::UmaHistogramSparse(histogram_name, -net_error);
-}
-
} // namespace
GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
@@ -351,7 +327,7 @@ GaiaCookieManagerService::ExternalCcResultFetcher::CreateAndStartLoader(
auto request = std::make_unique<network::ResourceRequest>();
request->url = url;
- request->allow_credentials = false;
+ request->credentials_mode = network::mojom::CredentialsMode::kOmit;
std::unique_ptr<network::SimpleURLLoader> loader =
network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
@@ -442,37 +418,56 @@ GaiaCookieManagerService::GaiaCookieManagerService(
fetcher_backoff_(&kBackoffPolicy),
fetcher_retries_(0),
listAccountsUnexpectedServerResponseRetried_(false),
- cookie_listener_binding_(this),
external_cc_result_fetched_(false),
- list_accounts_stale_(true) {}
+ list_accounts_stale_(true) {
+ std::string gaia_cookie_last_list_accounts_data =
+ signin_client_->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData);
+
+ if (!gaia_cookie_last_list_accounts_data.empty()) {
+ if (!gaia::ParseListAccountsData(gaia_cookie_last_list_accounts_data,
+ &listed_accounts_,
+ &signed_out_accounts_)) {
+ DLOG(WARNING) << "GaiaCookieManagerService::ListAccounts: Failed to "
+ "parse list accounts data from pref.";
+ listed_accounts_.clear();
+ signed_out_accounts_.clear();
+ return;
+ }
+ InitializeListedAccountsIds();
+ }
+}
GaiaCookieManagerService::~GaiaCookieManagerService() {
CancelAll();
DCHECK(requests_.empty());
}
+// static
+void GaiaCookieManagerService::RegisterPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterStringPref(prefs::kGaiaCookieLastListAccountsData,
+ std::string());
+}
+
void GaiaCookieManagerService::InitCookieListener() {
- DCHECK(!cookie_listener_binding_);
+ DCHECK(!cookie_listener_receiver_.is_bound());
network::mojom::CookieManager* cookie_manager =
signin_client_->GetCookieManager();
// NOTE: |cookie_manager| can be nullptr when TestSigninClient is used in
// testing contexts.
if (cookie_manager) {
- network::mojom::CookieChangeListenerPtr listener_ptr;
- cookie_listener_binding_.Bind(mojo::MakeRequest(&listener_ptr));
- cookie_listener_binding_.set_connection_error_handler(base::BindOnce(
- &GaiaCookieManagerService::OnCookieListenerConnectionError,
- base::Unretained(this)));
-
cookie_manager->AddCookieChangeListener(
GaiaUrls::GetInstance()->google_url(), kGaiaCookieName,
- std::move(listener_ptr));
+ cookie_listener_receiver_.BindNewPipeAndPassRemote());
+ cookie_listener_receiver_.set_disconnect_handler(base::BindOnce(
+ &GaiaCookieManagerService::OnCookieListenerConnectionError,
+ base::Unretained(this)));
}
}
void GaiaCookieManagerService::Shutdown() {
- cookie_listener_binding_.Close();
+ cookie_listener_receiver_.reset();
}
void GaiaCookieManagerService::SetAccountsInCookie(
@@ -693,7 +688,7 @@ void GaiaCookieManagerService::OnCookieChange(
void GaiaCookieManagerService::OnCookieListenerConnectionError() {
// A connection error from the CookieManager likely means that the network
// service process has crashed. Try again to set up a listener.
- cookie_listener_binding_.Close();
+ cookie_listener_receiver_.reset();
InitCookieListener();
}
@@ -818,21 +813,19 @@ void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) {
&signed_out_accounts_)) {
listed_accounts_.clear();
signed_out_accounts_.clear();
+ signin_client_->GetPrefs()->ClearPref(
+ prefs::kGaiaCookieLastListAccountsData);
GoogleServiceAuthError error(
GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE);
OnListAccountsFailure(error);
return;
}
+ signin_client_->GetPrefs()->SetString(prefs::kGaiaCookieLastListAccountsData,
+ data);
RecordListAccountsFailure(GoogleServiceAuthError::NONE);
- RecordListAccountsRetryResult(GoogleServiceAuthError::AuthErrorNone(),
- fetcher_retries_);
- for (gaia::ListedAccount& account : listed_accounts_) {
- DCHECK(account.id.empty());
- account.id = AccountTrackerService::PickAccountIdForAccount(
- signin_client_->GetPrefs(), account.gaia_id, account.email);
- }
+ InitializeListedAccountsIds();
list_accounts_stale_ = false;
HandleNextRequest();
@@ -852,7 +845,6 @@ void GaiaCookieManagerService::OnListAccountsFailure(
VLOG(1) << "ListAccounts failed";
DCHECK(requests_.front().request_type() ==
GaiaCookieRequestType::LIST_ACCOUNTS);
- RecordListAccountsRetryResult(error, fetcher_retries_);
bool should_retry =
(++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) ||
@@ -916,6 +908,14 @@ void GaiaCookieManagerService::OnLogOutFailure(
HandleNextRequest();
}
+void GaiaCookieManagerService::InitializeListedAccountsIds() {
+ for (gaia::ListedAccount& account : listed_accounts_) {
+ DCHECK(account.id.empty());
+ account.id = AccountTrackerService::PickAccountIdForAccount(
+ signin_client_->GetPrefs(), account.gaia_id, account.email);
+ }
+}
+
void GaiaCookieManagerService::StartFetchingUbertoken() {
const CoreAccountId account_id = requests_.front().GetAccountID();
VLOG(1) << "GaiaCookieManagerService::StartFetchingUbertoken account_id="
diff --git a/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
index 7886970f94d..845f1f5e11a 100644
--- a/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
+++ b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h
@@ -18,12 +18,13 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
+#include "components/prefs/pref_registry_simple.h"
#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
#include "components/signin/public/base/signin_client.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/backoff_entry.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
@@ -293,6 +294,9 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
// Final call in the Setting accounts in cookie procedure. Public for testing.
void OnSetAccountsFinished(signin::SetAccountsInCookieResult result);
+ // Registers prefs used by this class.
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+
private:
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory();
@@ -320,6 +324,9 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
void OnLogOutSuccess() override;
void OnLogOutFailure(const GoogleServiceAuthError& error) override;
+ // Helper method to initialize listed accounts ids.
+ void InitializeListedAccountsIds();
+
// Helper method for AddAccountToCookie* methods.
void AddAccountToCookieInternal(
const CoreAccountId& account_id,
@@ -378,7 +385,8 @@ class GaiaCookieManagerService : public GaiaAuthConsumer,
std::string access_token_;
// Connection to the CookieManager that signals when the GAIA cookies change.
- mojo::Binding<network::mojom::CookieChangeListener> cookie_listener_binding_;
+ mojo::Receiver<network::mojom::CookieChangeListener>
+ cookie_listener_receiver_{this};
// A worklist for this class. Stores any pending requests that couldn't be
// executed right away, since this class only permits one request to be
diff --git a/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc
index 492ee78b725..1cf53419038 100644
--- a/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc
@@ -18,7 +18,7 @@
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/prefs/testing_pref_service.h"
@@ -121,6 +121,7 @@ class GaiaCookieManagerServiceTest : public testing::Test {
error_(GoogleServiceAuthError::SERVICE_ERROR),
canceled_(GoogleServiceAuthError::REQUEST_CANCELED) {
AccountTrackerService::RegisterPrefs(pref_service_.registry());
+ GaiaCookieManagerService::RegisterPrefs(pref_service_.registry());
signin_client_ = std::make_unique<TestSigninClient>(&pref_service_);
token_service_ =
std::make_unique<FakeProfileOAuth2TokenService>(&pref_service_);
@@ -227,7 +228,7 @@ class GaiaCookieManagerServiceTest : public testing::Test {
const CoreAccountId account_id3_;
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
GoogleServiceAuthError no_error_;
GoogleServiceAuthError error_;
GoogleServiceAuthError canceled_;
@@ -650,6 +651,10 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsFirstReturnsEmpty) {
ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
ASSERT_TRUE(list_accounts.empty());
ASSERT_TRUE(signed_out_accounts.empty());
+ ASSERT_TRUE(signin_client()
+ ->GetPrefs()
+ ->GetString(prefs::kGaiaCookieLastListAccountsData)
+ .empty());
}
TEST_F(GaiaCookieManagerServiceTest, ListAccountsFindsOneAccount) {
@@ -675,9 +680,12 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsFindsOneAccount) {
ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
- SimulateListAccountsSuccess(
- &helper,
- "[\"f\", [[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]]]");
+ std::string data =
+ "[\"f\", [[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]]]";
+ SimulateListAccountsSuccess(&helper, data);
+ EXPECT_EQ(signin_client()->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData),
+ data);
}
TEST_F(GaiaCookieManagerServiceTest, ListAccountsFindsSignedOutAccounts) {
@@ -709,12 +717,15 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsFindsSignedOutAccounts) {
ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
- SimulateListAccountsSuccess(
- &helper,
+ std::string data =
"[\"f\","
"[[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"],"
" [\"b\", 0, \"n\", \"c@d.com\", \"p\", 0, 0, 0, 0, 1, \"9\","
- "null,null,null,1]]]");
+ "null,null,null,1]]]";
+ SimulateListAccountsSuccess(&helper, data);
+ EXPECT_EQ(signin_client()->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData),
+ data);
}
TEST_F(GaiaCookieManagerServiceTest, ListAccountsAcceptsNull) {
@@ -723,12 +734,12 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsAcceptsNull) {
ASSERT_FALSE(helper.ListAccounts(nullptr, nullptr));
- SimulateListAccountsSuccess(
- &helper,
+ std::string data =
"[\"f\","
"[[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"],"
" [\"b\", 0, \"n\", \"c@d.com\", \"p\", 0, 0, 0, 0, 1, \"9\","
- "null,null,null,1]]]");
+ "null,null,null,1]]]";
+ SimulateListAccountsSuccess(&helper, data);
std::vector<gaia::ListedAccount> signed_out_accounts;
ASSERT_TRUE(helper.ListAccounts(nullptr, &signed_out_accounts));
@@ -737,6 +748,10 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsAcceptsNull) {
std::vector<gaia::ListedAccount> accounts;
ASSERT_TRUE(helper.ListAccounts(&accounts, nullptr));
ASSERT_EQ(1u, accounts.size());
+
+ EXPECT_EQ(signin_client()->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData),
+ data);
}
TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChange) {
@@ -764,14 +779,18 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChange) {
ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
ASSERT_TRUE(list_accounts.empty());
ASSERT_TRUE(signed_out_accounts.empty());
- SimulateListAccountsSuccess(
- &helper,
- "[\"f\", [[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]]]");
+
+ std::string data =
+ "[\"f\", [[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"]]]";
+ SimulateListAccountsSuccess(&helper, data);
// Sanity-check that ListAccounts returns the cached data.
ASSERT_TRUE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
ASSERT_TRUE(AreAccountListsEqual(nonempty_list_accounts, list_accounts));
ASSERT_TRUE(signed_out_accounts.empty());
+ EXPECT_EQ(signin_client()->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData),
+ data);
EXPECT_CALL(helper, StartFetchingListAccounts());
EXPECT_CALL(observer,
@@ -789,7 +808,128 @@ TEST_F(GaiaCookieManagerServiceTest, ListAccountsAfterOnCookieChange) {
ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
ASSERT_TRUE(AreAccountListsEqual(nonempty_list_accounts, list_accounts));
ASSERT_TRUE(signed_out_accounts.empty());
- SimulateListAccountsSuccess(&helper, "[\"f\",[]]");
+ data = "[\"f\",[]]";
+ SimulateListAccountsSuccess(&helper, data);
+ EXPECT_EQ(signin_client()->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData),
+ data);
+}
+
+TEST_F(GaiaCookieManagerServiceTest, GaiaCookieLastListAccountsDataSaved) {
+ std::string data =
+ "[\"f\","
+ "[[\"b\", 0, \"n\", \"a@b.com\", \"p\", 0, 0, 0, 0, 1, \"8\"],"
+ " [\"b\", 0, \"n\", \"c@d.com\", \"p\", 0, 0, 0, 0, 1, \"9\","
+ "null,null,null,1]]]";
+ std::vector<gaia::ListedAccount> expected_accounts;
+ gaia::ListedAccount listed_account;
+ listed_account.email = "a@b.com";
+ listed_account.raw_email = "a@b.com";
+ listed_account.gaia_id = "8";
+ expected_accounts.push_back(listed_account);
+
+ std::vector<gaia::ListedAccount> expected_signed_out_accounts;
+ gaia::ListedAccount signed_out_account;
+ signed_out_account.email = "c@d.com";
+ signed_out_account.raw_email = "c@d.com";
+ signed_out_account.gaia_id = "9";
+ signed_out_account.signed_out = true;
+ expected_signed_out_accounts.push_back(signed_out_account);
+ std::vector<gaia::ListedAccount> list_accounts;
+ std::vector<gaia::ListedAccount> signed_out_accounts;
+
+ {
+ InstrumentedGaiaCookieManagerService helper(token_service(),
+ signin_client());
+ MockObserver observer(&helper);
+
+ EXPECT_CALL(helper, StartFetchingListAccounts());
+ EXPECT_CALL(observer, OnGaiaAccountsInCookieUpdated(
+ ListedAccountEquals(expected_accounts),
+ ListedAccountEquals(expected_signed_out_accounts),
+ no_error()));
+
+ ASSERT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
+ // |kGaiaCookieLastListAccountsData| is empty.
+ EXPECT_TRUE(list_accounts.empty());
+ EXPECT_TRUE(signed_out_accounts.empty());
+ SimulateListAccountsSuccess(&helper, data);
+ // |kGaiaCookieLastListAccountsData| is set.
+ ASSERT_EQ(signin_client()->GetPrefs()->GetString(
+ prefs::kGaiaCookieLastListAccountsData),
+ data);
+ // List accounts is not stale.
+ ASSERT_TRUE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
+ }
+
+ // Now that the list accounts data is saved to the pref service, test that
+ // starting a new Gaia Service Manager gives synchronous answers to list
+ // accounts.
+ {
+ InstrumentedGaiaCookieManagerService helper(token_service(),
+ signin_client());
+ MockObserver observer(&helper);
+ auto test_task_runner =
+ base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+ base::ScopedClosureRunner task_runner_ =
+ base::ThreadTaskRunnerHandle::OverrideForTesting(test_task_runner);
+
+ EXPECT_CALL(helper, StartFetchingListAccounts()).Times(3);
+
+ // Though |SimulateListAccountsSuccess| is not yet called, we are able to
+ // retrieve last |list_accounts| and |expected_accounts| from the pref,
+ // but mark them as stale. A |StartFetchingListAccounts| is triggered.
+ EXPECT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
+ EXPECT_TRUE(AreAccountListsEqual(list_accounts, expected_accounts));
+ EXPECT_TRUE(AreAccountListsEqual(signed_out_accounts,
+ expected_signed_out_accounts));
+
+ // |SimulateListAccountsSuccess| and assert list accounts is not stale
+ // anymore.
+ EXPECT_CALL(observer, OnGaiaAccountsInCookieUpdated(
+ ListedAccountEquals(expected_accounts),
+ ListedAccountEquals(expected_signed_out_accounts),
+ no_error()));
+ SimulateListAccountsSuccess(&helper, data);
+ ASSERT_TRUE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
+
+ // Change list account state to be stale, which will trigger list accounts
+ // request.
+ helper.ForceOnCookieChangeProcessing();
+
+ // Receive an unexpected response from the server. Listed accounts as well
+ // as the pref should be cleared.
+ expected_accounts.clear();
+ expected_signed_out_accounts.clear();
+ GoogleServiceAuthError error(
+ GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE);
+ EXPECT_CALL(observer,
+ OnGaiaAccountsInCookieUpdated(
+ ListedAccountEquals(expected_accounts),
+ ListedAccountEquals(expected_signed_out_accounts), error));
+ SimulateListAccountsSuccess(&helper, "[]");
+ EXPECT_FALSE(helper.ListAccounts(&list_accounts, &signed_out_accounts));
+
+ // List accounts retries once on |UNEXPECTED_SERVICE_RESPONSE| errors with
+ // backoff protection.
+ Advance(test_task_runner, helper.GetBackoffEntry()->GetTimeUntilRelease());
+ SimulateListAccountsSuccess(&helper, "[]");
+
+ // |kGaiaCookieLastListAccountsData| is cleared.
+ EXPECT_TRUE(signin_client()
+ ->GetPrefs()
+ ->GetString(prefs::kGaiaCookieLastListAccountsData)
+ .empty());
+ }
+
+ {
+ // On next startup, |kGaiaCookieLastListAccountsData| contains last list
+ // accounts data.
+ EXPECT_TRUE(signin_client()
+ ->GetPrefs()
+ ->GetString(prefs::kGaiaCookieLastListAccountsData)
+ .empty());
+ }
}
TEST_F(GaiaCookieManagerServiceTest, ExternalCcResultFetcher) {
diff --git a/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
index 0364fbc2ce2..6b8be38232c 100644
--- a/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
+++ b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
@@ -34,28 +34,6 @@ namespace {
const char kAccountIdPrefix[] = "AccountId-";
const size_t kAccountIdPrefixLength = 10;
-// Used to record token state transitions in histograms.
-// Do not change existing values, new values can only be added at the end.
-enum class TokenStateTransition {
- // Update events.
- kNoneToInvalid = 0,
- kNoneToRegular,
- kInvalidToRegular,
- kRegularToInvalid,
- kRegularToRegular,
-
- // Revocation events.
- kInvalidToNone,
- kRegularToNone,
-
- // Load events.
- kLoadRegular,
- kLoadInvalid,
- kLoadInvalidNoTokenForPrimaryAccount,
-
- kCount
-};
-
// Enum for the Signin.LoadTokenFromDB histogram.
// Do not modify, or add or delete other than directly before
// NUM_LOAD_TOKEN_FROM_DB_STATUS.
@@ -88,14 +66,6 @@ enum class TokenRevocationRequestProgress {
kMaxValue = kRequestSucceeded
};
-// Adds a sample to the TokenStateTransition histogram. Encapsuled in a function
-// to reduce executable size, because histogram macros may generate a lot of
-// code.
-void RecordTokenStateTransition(TokenStateTransition transition) {
- UMA_HISTOGRAM_ENUMERATION("Signin.TokenStateTransition", transition,
- TokenStateTransition::kCount);
-}
-
// Adds a sample to the TokenRevocationRequestProgress histogram. Encapsuled in
// a function to reduce executable size, because histogram macros may generate a
// lot of code.
@@ -105,42 +75,6 @@ void RecordRefreshTokenRevocationRequestEvent(
event);
}
-// Record metrics when a token was updated.
-void RecordTokenChanged(const std::string& existing_token,
- const std::string& new_token) {
- DCHECK_NE(existing_token, new_token);
- DCHECK(!new_token.empty());
- TokenStateTransition transition = TokenStateTransition::kCount;
- if (existing_token.empty()) {
- transition = (new_token == GaiaConstants::kInvalidRefreshToken)
- ? TokenStateTransition::kNoneToInvalid
- : TokenStateTransition::kNoneToRegular;
- } else if (existing_token == GaiaConstants::kInvalidRefreshToken) {
- transition = TokenStateTransition::kInvalidToRegular;
- } else {
- // Existing token is a regular token.
- transition = (new_token == GaiaConstants::kInvalidRefreshToken)
- ? TokenStateTransition::kRegularToInvalid
- : TokenStateTransition::kRegularToRegular;
- }
- DCHECK_NE(TokenStateTransition::kCount, transition);
- RecordTokenStateTransition(transition);
-}
-
-// Record metrics when a token was loaded.
-void RecordTokenLoaded(const std::string& token) {
- RecordTokenStateTransition((token == GaiaConstants::kInvalidRefreshToken)
- ? TokenStateTransition::kLoadInvalid
- : TokenStateTransition::kLoadRegular);
-}
-
-// Record metrics when a token was revoked.
-void RecordTokenRevoked(const std::string& token) {
- RecordTokenStateTransition((token == GaiaConstants::kInvalidRefreshToken)
- ? TokenStateTransition::kInvalidToNone
- : TokenStateTransition::kRegularToNone);
-}
-
std::string ApplyAccountIdPrefix(const std::string& account_id) {
return kAccountIdPrefix + account_id;
}
@@ -179,35 +113,15 @@ signin::LoadCredentialsState LoadCredentialsStateFromTokenResult(
// Returns whether the token service should be migrated to Dice.
// Migration can happen if the following conditions are met:
// - Token service Dice migration is not already done,
-// - AccountTrackerService migration is done,
-// - All accounts in the AccountTrackerService are valid,
// - Account consistency is DiceMigration or greater.
// TODO(droger): Remove this code once Dice is fully enabled.
bool ShouldMigrateToDice(signin::AccountConsistencyMethod account_consistency,
- PrefService* prefs,
- AccountTrackerService* account_tracker,
- const std::map<std::string, std::string>& db_tokens) {
- AccountTrackerService::AccountIdMigrationState migration_state =
- account_tracker->GetMigrationState();
- if ((account_consistency == signin::AccountConsistencyMethod::kMirror) ||
- !signin::DiceMethodGreaterOrEqual(
- account_consistency,
- signin::AccountConsistencyMethod::kDiceMigration) ||
- (migration_state != AccountTrackerService::MIGRATION_DONE) ||
- prefs->GetBoolean(prefs::kTokenServiceDiceCompatible)) {
- return false;
- }
-
- // Do not migrate if some accounts are not valid.
- for (auto iter = db_tokens.begin(); iter != db_tokens.end(); ++iter) {
- const std::string& prefixed_account_id = iter->first;
- CoreAccountId account_id = RemoveAccountIdPrefix(prefixed_account_id);
- AccountInfo account_info = account_tracker->GetAccountInfo(account_id);
- if (!account_info.IsValid()) {
- return false;
- }
- }
- return true;
+ PrefService* prefs) {
+ return (account_consistency != signin::AccountConsistencyMethod::kMirror) &&
+ signin::DiceMethodGreaterOrEqual(
+ account_consistency,
+ signin::AccountConsistencyMethod::kDiceMigration) &&
+ !prefs->GetBoolean(prefs::kTokenServiceDiceCompatible);
}
} // namespace
@@ -524,6 +438,7 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadCredentials(
set_load_credentials_state(
signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS);
+ MaybeDeletePreDiceTokens();
FinishLoadingCredentials();
return;
}
@@ -562,6 +477,7 @@ void MutableProfileOAuth2TokenServiceDelegate::OnWebDataServiceRequestDone(
set_load_credentials_state(
signin::LoadCredentialsState::
LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED);
+ MaybeDeletePreDiceTokens();
}
// Make sure that we have an entry for |loading_primary_account_id_| in the
@@ -580,8 +496,6 @@ void MutableProfileOAuth2TokenServiceDelegate::OnWebDataServiceRequestDone(
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_MISSING));
- RecordTokenStateTransition(
- TokenStateTransition::kLoadInvalidNoTokenForPrimaryAccount);
FireRefreshTokenAvailable(loading_primary_account_id_);
}
@@ -600,8 +514,7 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
const std::map<std::string, std::string>& db_tokens) {
std::string old_login_token;
bool migrate_to_dice =
- ShouldMigrateToDice(account_consistency_, client_->GetPrefs(),
- account_tracker_service_, db_tokens);
+ ShouldMigrateToDice(account_consistency_, client_->GetPrefs());
{
ScopedBatchChange batch(this);
@@ -692,8 +605,16 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
// Revoke old hosted domain accounts as part of Dice migration.
AccountInfo account_info =
account_tracker_service_->GetAccountInfo(account_id);
- DCHECK(account_info.IsValid());
- if (account_info.hosted_domain != kNoHostedDomainFound) {
+ bool is_hosted_domain = false;
+ if (account_info.hosted_domain.empty()) {
+ // The AccountInfo is incomplete. Use a conservative approximation.
+ is_hosted_domain =
+ !client_->IsNonEnterpriseUser(account_info.email);
+ } else {
+ is_hosted_domain =
+ (account_info.hosted_domain != kNoHostedDomainFound);
+ }
+ if (is_hosted_domain) {
load_account = false;
load_token_status =
LoadTokenFromDBStatus::TOKEN_REVOKED_DICE_MIGRATION;
@@ -716,11 +637,9 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory(
LoadTokenFromDBStatus::NUM_LOAD_TOKEN_FROM_DB_STATUS);
if (load_account) {
- RecordTokenLoaded(refresh_token);
UpdateCredentialsInMemory(account_id, refresh_token);
FireRefreshTokenAvailable(account_id);
} else {
- RecordTokenRevoked(refresh_token);
RevokeCredentialsOnServer(refresh_token);
ClearPersistedCredentials(account_id);
FireRefreshTokenRevoked(account_id);
@@ -750,7 +669,6 @@ void MutableProfileOAuth2TokenServiceDelegate::UpdateCredentials(
const std::string& existing_token = GetRefreshToken(account_id);
if (existing_token != refresh_token) {
ScopedBatchChange batch(this);
- RecordTokenChanged(existing_token, refresh_token);
UpdateCredentialsInMemory(account_id, refresh_token);
PersistCredentials(account_id, refresh_token);
FireRefreshTokenAvailable(account_id);
@@ -837,10 +755,10 @@ void MutableProfileOAuth2TokenServiceDelegate::RevokeAllCredentials() {
}
// Make a temporary copy of the account ids.
- std::vector<std::string> accounts;
+ std::vector<CoreAccountId> accounts;
for (const auto& token : refresh_tokens_)
accounts.push_back(token.first);
- for (const std::string& account : accounts)
+ for (const auto& account : accounts)
RevokeCredentials(account);
DCHECK_EQ(0u, refresh_tokens_.size());
@@ -932,6 +850,10 @@ void MutableProfileOAuth2TokenServiceDelegate::AddAccountStatus(
}
void MutableProfileOAuth2TokenServiceDelegate::FinishLoadingCredentials() {
+#if !defined(OS_CHROMEOS)
+ if (account_consistency_ == signin::AccountConsistencyMethod::kDice)
+ DCHECK(client_->GetPrefs()->GetBoolean(prefs::kTokenServiceDiceCompatible));
+#endif
FireRefreshTokensLoaded();
}
@@ -945,7 +867,6 @@ void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentialsImpl(
VLOG(1) << "MutablePO2TS::RevokeCredentials for account_id=" << account_id;
ScopedBatchChange batch(this);
const std::string& token = refresh_tokens_[account_id].refresh_token;
- RecordTokenRevoked(token);
if (revoke_on_server)
RevokeCredentialsOnServer(token);
refresh_tokens_.erase(account_id);
@@ -953,3 +874,18 @@ void MutableProfileOAuth2TokenServiceDelegate::RevokeCredentialsImpl(
FireRefreshTokenRevoked(account_id);
}
}
+
+void MutableProfileOAuth2TokenServiceDelegate::MaybeDeletePreDiceTokens() {
+ DCHECK(load_credentials_state() ==
+ signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS ||
+ load_credentials_state() ==
+ signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED);
+
+ if (account_consistency_ == signin::AccountConsistencyMethod::kDice &&
+ !client_->GetPrefs()->GetBoolean(prefs::kTokenServiceDiceCompatible)) {
+ RevokeAllCredentials();
+ client_->GetPrefs()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
+ }
+}
diff --git a/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h
index 9c398812676..41b71cd2575 100644
--- a/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h
+++ b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h
@@ -111,6 +111,8 @@ class MutableProfileOAuth2TokenServiceDelegate
FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
DelayedRevoke);
FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
+ DiceMigrationWithMissingHostedDomain);
+ FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
DiceMigrationHostedDomainPrimaryAccount);
FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
ShutdownDuringRevoke);
@@ -187,6 +189,11 @@ class MutableProfileOAuth2TokenServiceDelegate
void RevokeCredentialsImpl(const CoreAccountId& account_id,
bool revoke_on_server);
+ // If the Dice migration happened before the tokens could be migrated, delete
+ // all the tokens. This is only called if the tokens could not be loaded
+ // successfully.
+ void MaybeDeletePreDiceTokens();
+
// Maps the |account_id| of accounts known to ProfileOAuth2TokenService
// to information about the account.
typedef std::map<CoreAccountId, AccountStatus> AccountStatusMap;
diff --git a/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
index a25bc19bb95..d0f61c6373b 100644
--- a/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -10,11 +10,10 @@
#include <vector>
#include "base/bind.h"
-#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -81,13 +80,13 @@ AccountInfo CreateTestAccountInfo(const std::string& name,
class MutableProfileOAuth2TokenServiceDelegateTest
: public testing::Test,
public OAuth2AccessTokenConsumer,
- public OAuth2TokenServiceObserver,
+ public ProfileOAuth2TokenServiceObserver,
public WebDataServiceConsumer {
public:
MutableProfileOAuth2TokenServiceDelegateTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC),
+ : task_environment_(
+ base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC),
access_token_success_count_(0),
access_token_failure_count_(0),
access_token_failure_(GoogleServiceAuthError::NONE),
@@ -122,8 +121,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
}
void LoadTokenDatabase() {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath path = temp_dir_.GetPath().AppendASCII("TestWebDB");
+ base::FilePath path(WebDatabase::kInMemoryPath);
scoped_refptr<WebDatabaseService> web_database =
new WebDatabaseService(path, base::ThreadTaskRunnerHandle::Get(),
base::ThreadTaskRunnerHandle::Get());
@@ -186,7 +184,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
access_token_failure_ = error;
}
- // OAuth2TokenServiceObserver implementation.
+ // ProfileOAuth2TokenServiceObserver implementation.
void OnRefreshTokenAvailable(const CoreAccountId& account_id) override {
++token_available_count_;
}
@@ -250,8 +248,7 @@ class MutableProfileOAuth2TokenServiceDelegateTest
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- base::ScopedTempDir temp_dir_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<TestSigninClient> client_;
std::unique_ptr<MutableProfileOAuth2TokenServiceDelegate>
oauth2_service_delegate_;
@@ -533,42 +530,53 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
// Tests that Dice migration does not happen if an account is invalid. In
// particular, no hosted domain tokens are revoked.
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
- DiceNoMigrationOnInvalidAccount) {
+ DiceMigrationWithMissingHostedDomain) {
ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
InitializeOAuth2ServiceDelegate(
signin::AccountConsistencyMethod::kDiceMigration);
oauth2_service_delegate_->RevokeAllCredentials();
- // Add account info to the account tracker.
- AccountInfo primary_account = CreateTestAccountInfo(
- "primary_account", true /* is_hosted_domain*/, true /* is_valid*/);
- AccountInfo secondary_account = CreateTestAccountInfo(
- "secondary_account", false /* is_hosted_domain*/, false /* is_valid*/);
- account_tracker_service_.SeedAccountInfo(primary_account);
- account_tracker_service_.SeedAccountInfo(secondary_account);
+ // Add incomplete accounts info to the account tracker.
+ AccountInfo account_info_consummer;
+ account_info_consummer.account_id = "consummer";
+ account_info_consummer.gaia = "consummer";
+ // gmail.com is known as a non-enterprise domain.
+ account_info_consummer.email = "consummer@gmail.com";
+ account_tracker_service_.SeedAccountInfo(account_info_consummer);
+
+ AccountInfo account_info_enterprise;
+ account_info_enterprise.account_id = "enterprise";
+ account_info_enterprise.gaia = "enterprise";
+ account_info_enterprise.email = "enterprise@email.com";
+ account_tracker_service_.SeedAccountInfo(account_info_enterprise);
ResetObserverCounts();
- AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
+ AddAuthTokenManually("AccountId-" + account_info_consummer.account_id.id,
"refresh_token");
- AddAuthTokenManually("AccountId-" + secondary_account.account_id.id,
+ AddAuthTokenManually("AccountId-" + account_info_enterprise.account_id.id,
"refresh_token");
- oauth2_service_delegate_->LoadCredentials(primary_account.account_id);
+ oauth2_service_delegate_->LoadCredentials(account_info_consummer.account_id);
base::RunLoop().RunUntilIdle();
+ // Only the enterprise token is revoked.
EXPECT_EQ(1, tokens_loaded_count_);
- EXPECT_EQ(2, token_available_count_);
- EXPECT_EQ(0, token_revoked_count_);
+ EXPECT_EQ(1, token_available_count_);
+ EXPECT_EQ(1, token_revoked_count_);
EXPECT_EQ(1, end_batch_changes_);
- EXPECT_EQ(2, auth_error_changed_count_);
- EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
- primary_account.account_id));
+ EXPECT_EQ(1, auth_error_changed_count_);
+ EXPECT_FALSE(oauth2_service_delegate_->RefreshTokenIsAvailable(
+ account_info_enterprise.account_id));
EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
- secondary_account.account_id));
+ account_info_consummer.account_id));
+ EXPECT_EQ("refresh_token",
+ oauth2_service_delegate_
+ ->refresh_tokens_[account_info_consummer.account_id]
+ .refresh_token);
EXPECT_EQ(
signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
oauth2_service_delegate_->load_credentials_state());
- EXPECT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
+ EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
}
// Tests that the migration happened after loading consummer accounts.
@@ -700,6 +708,51 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
EXPECT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
}
+// Checks that tokens are loaded and prefs::kTokenServiceDiceCompatible is set
+// to true if the tokens are loaded after the Dice migration.
+TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, LoadAfterDiceMigration) {
+ InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
+ ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
+
+ // Add account info to the account tracker.
+ AccountInfo primary_account = CreateTestAccountInfo(
+ "primary_account", false /* is_hosted_domain*/, true /* is_valid*/);
+ account_tracker_service_.SeedAccountInfo(primary_account);
+ AddAuthTokenManually("AccountId-" + primary_account.account_id.id,
+ "refresh_token");
+
+ oauth2_service_delegate_->LoadCredentials(std::string());
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
+ primary_account.account_id));
+ EXPECT_EQ(
+ signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
+ oauth2_service_delegate_->load_credentials_state());
+
+ ASSERT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
+}
+
+// Checks that prefs::kTokenServiceDiceCompatible is set to true if the tokens
+// are loaded after the Dice migration, even if there was a database read error.
+TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
+ LoadAfterDiceMigrationWithError) {
+ InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
+ ASSERT_FALSE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
+
+ // Shutdown the database to trigger a database read error.
+ token_web_data_->ShutdownDatabase();
+
+ oauth2_service_delegate_->LoadCredentials(std::string());
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(0u, oauth2_service_delegate_->GetAccounts().size());
+ EXPECT_EQ(signin::LoadCredentialsState::
+ LOAD_CREDENTIALS_FINISHED_WITH_DB_CANNOT_BE_OPENED,
+ oauth2_service_delegate_->load_credentials_state());
+
+ ASSERT_TRUE(pref_service_.GetBoolean(prefs::kTokenServiceDiceCompatible));
+}
#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
#if !defined(OS_CHROMEOS)
@@ -875,7 +928,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, UpdateInvalidToken) {
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
InvalidateTokensForMultilogin) {
- class TokenServiceErrorObserver : public OAuth2TokenServiceObserver {
+ class TokenServiceErrorObserver : public ProfileOAuth2TokenServiceObserver {
public:
MOCK_METHOD2(OnAuthErrorChanged,
void(const CoreAccountId&, const GoogleServiceAuthError&));
@@ -916,6 +969,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
}
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, LoadInvalidToken) {
+ pref_service_.SetBoolean(prefs::kTokenServiceDiceCompatible, true);
InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice);
std::map<std::string, std::string> tokens;
const CoreAccountId account_id("account_id");
@@ -1337,7 +1391,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
// Checks that OnAuthErrorChanged() is called during UpdateCredentials(), and
// that RefreshTokenIsAvailable() can be used at this time.
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, OnAuthErrorChanged) {
- class TokenServiceErrorObserver : public OAuth2TokenServiceObserver {
+ class TokenServiceErrorObserver : public ProfileOAuth2TokenServiceObserver {
public:
explicit TokenServiceErrorObserver(
MutableProfileOAuth2TokenServiceDelegate* delegate)
@@ -1407,7 +1461,7 @@ TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, GetAuthError) {
// Regression test for https://crbug.com/824791.
TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
InvalidTokenObserverCallsOrdering) {
- class TokenServiceErrorObserver : public OAuth2TokenServiceObserver {
+ class TokenServiceErrorObserver : public ProfileOAuth2TokenServiceObserver {
public:
explicit TokenServiceErrorObserver(
MutableProfileOAuth2TokenServiceDelegate* delegate)
diff --git a/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h
index 2d1eedc2f8c..b55902b86cd 100644
--- a/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h
+++ b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h
@@ -68,8 +68,8 @@ class OAuth2TokenServiceDelegateAndroid
const std::vector<CoreAccountId>& prev_ids,
const std::vector<CoreAccountId>& curr_ids);
- // Overridden from OAuth2TokenService to complete signout of all
- // OA2TService aware accounts.
+ // Overridden from ProfileOAuth2TokenService to complete signout of all
+ // POA2TService aware accounts.
void RevokeAllCredentials() override;
void LoadCredentials(const CoreAccountId& primary_account_id) override;
diff --git a/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc
index 731a71c9955..6f3272048aa 100644
--- a/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth2_token_service_delegate_android_unittest.cc
@@ -27,7 +27,7 @@ class OAuth2TokenServiceDelegateAndroidForTest
MOCK_METHOD1(SetAccounts, void(const std::vector<CoreAccountId>&));
};
-class TestObserver : public OAuth2TokenServiceObserver {
+class TestObserver : public ProfileOAuth2TokenServiceObserver {
public:
MOCK_METHOD1(OnRefreshTokenAvailable, void(const CoreAccountId&));
MOCK_METHOD1(OnRefreshTokenRevoked, void(const CoreAccountId&));
diff --git a/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
index e5a314674d9..6c4607cc90f 100644
--- a/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
@@ -196,8 +196,10 @@ void OAuthMultiloginHelper::StartSettingCookies(
cookie_manager->SetCanonicalCookie(
cookie, "https", options,
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(callback), net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_UNKNOWN_ERROR));
+ std::move(callback),
+ net::CanonicalCookie::CookieInclusionStatus(
+ net::CanonicalCookie::CookieInclusionStatus::
+ EXCLUDE_UNKNOWN_ERROR)));
} else {
LOG(ERROR) << "Duplicate cookie found: " << cookie.Name() << " "
<< cookie.Domain();
@@ -210,8 +212,7 @@ void OAuthMultiloginHelper::OnCookieSet(
const std::string& cookie_domain,
net::CanonicalCookie::CookieInclusionStatus status) {
cookies_to_set_.erase(std::make_pair(cookie_name, cookie_domain));
- bool success =
- (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+ bool success = status.IsInclude();
if (!success) {
LOG(ERROR) << "Failed to set cookie " << cookie_name
<< " for domain=" << cookie_domain << ".";
diff --git a/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
index 9ad5f88d61e..3fb516ade2f 100644
--- a/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
#include "components/signin/public/base/test_signin_client.h"
@@ -139,7 +139,7 @@ void RunSetCookieCallbackWithSuccess(
const std::string&,
const net::CookieOptions&,
network::mojom::CookieManager::SetCanonicalCookieCallback callback) {
- std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+ std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus());
}
class MockCookieManager
@@ -217,7 +217,7 @@ class OAuthMultiloginHelperTest : public testing::Test {
result_ = result;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool callback_called_ = false;
SetAccountsInCookieResult result_;
diff --git a/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc
index ebeb12b0a3a..bc8282ad5f8 100644
--- a/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
#include "components/signin/public/base/test_signin_client.h"
@@ -73,7 +73,7 @@ class OAuthMultiloginTokenFetcherTest : public testing::Test {
error_ = error;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool success_callback_called_ = false;
bool failure_callback_called_ = false;
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_manager.h b/chromium/components/signin/internal/identity_manager/primary_account_manager.h
index 7625fe002c3..1c6b8915347 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_manager.h
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager.h
@@ -24,9 +24,9 @@
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/macros.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "components/signin/public/base/account_consistency_method.h"
#include "components/signin/public/base/signin_client.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
struct AccountInfo;
class AccountTrackerService;
@@ -40,7 +40,7 @@ enum ProfileSignout : int;
enum class SignoutDelete;
} // namespace signin_metrics
-class PrimaryAccountManager : public OAuth2TokenServiceObserver {
+class PrimaryAccountManager : public ProfileOAuth2TokenServiceObserver {
public:
typedef base::RepeatingCallback<void(const AccountInfo&)>
AccountSigninCallback;
@@ -183,7 +183,7 @@ class PrimaryAccountManager : public OAuth2TokenServiceObserver {
// Send all observers |GoogleSignedOut| notifications.
void FireGoogleSignedOut(const AccountInfo& account_info);
- // OAuth2TokenServiceObserver:
+ // ProfileOAuth2TokenServiceObserver:
void OnRefreshTokensLoaded() override;
#endif
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc b/chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
index 8549cd814ff..55deafe0061 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
@@ -130,7 +130,7 @@ class PrimaryAccountManagerTest : public testing::Test {
void GoogleSignedOut(const AccountInfo& account_info) { num_signouts_++; }
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable user_prefs_;
TestingPrefServiceSimple local_state_;
TestSigninClient test_signin_client_;
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
index f9d1eba03ec..85de348118b 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
+++ b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
@@ -52,7 +52,7 @@ bool PrimaryAccountMutatorImpl::SetPrimaryAccount(
}
#if defined(OS_CHROMEOS)
-bool PrimaryAccountMutatorImpl::SetPrimaryAccountAndUpdateAccountInfo(
+bool PrimaryAccountMutatorImpl::DeprecatedSetPrimaryAccountAndUpdateAccountInfo(
const std::string& gaia_id,
const std::string& email) {
CoreAccountId account_id = account_tracker_->SeedAccountInfo(gaia_id, email);
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h
index f15e6c13f9b..91806ee41ca 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h
+++ b/chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h
@@ -27,8 +27,9 @@ class PrimaryAccountMutatorImpl : public PrimaryAccountMutator {
// PrimaryAccountMutator implementation.
bool SetPrimaryAccount(const CoreAccountId& account_id) override;
#if defined(OS_CHROMEOS)
- bool SetPrimaryAccountAndUpdateAccountInfo(const std::string& gaia_id,
- const std::string& email) override;
+ bool DeprecatedSetPrimaryAccountAndUpdateAccountInfo(
+ const std::string& gaia_id,
+ const std::string& email) override;
#endif
#if !defined(OS_CHROMEOS)
bool ClearPrimaryAccount(
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc
index 282eab2ec0e..6fd6d08c774 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/primary_account_policy_manager_impl_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include <string>
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
@@ -43,7 +43,7 @@ class PrimaryAccountPolicyManagerImplTest : public testing::Test {
test_signin_client_.Shutdown();
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable user_prefs_;
TestingPrefServiceSimple local_state_;
TestSigninClient test_signin_client_;
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
index 6d4f5c1d584..5308623e4e5 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
@@ -62,6 +62,9 @@ std::string SourceToString(SourceForRefreshTokenOperation source) {
return "MachineLogon::CredentialProvider";
case SourceForRefreshTokenOperation::kTokenService_ExtractCredentials:
return "TokenService::ExtractCredentials";
+ case SourceForRefreshTokenOperation::
+ kAccountReconcilor_RevokeTokensNotInCookies:
+ return "AccountReconcilor::RevokeTokensNotInCookies";
}
}
} // namespace
@@ -104,7 +107,7 @@ ProfileOAuth2TokenService::GetURLLoaderFactory() const {
void ProfileOAuth2TokenService::OnAccessTokenInvalidated(
const CoreAccountId& account_id,
const std::string& client_id,
- const std::set<std::string>& scopes,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
const std::string& access_token) {
delegate_->OnAccessTokenInvalidated(account_id, client_id, scopes,
access_token);
@@ -145,12 +148,12 @@ ProfileOAuth2TokenService::GetDelegate() const {
}
void ProfileOAuth2TokenService::AddObserver(
- OAuth2TokenServiceObserver* observer) {
+ ProfileOAuth2TokenServiceObserver* observer) {
delegate_->AddObserver(observer);
}
void ProfileOAuth2TokenService::RemoveObserver(
- OAuth2TokenServiceObserver* observer) {
+ ProfileOAuth2TokenServiceObserver* observer) {
delegate_->RemoveObserver(observer);
}
@@ -253,7 +256,7 @@ void ProfileOAuth2TokenService::SetRefreshTokenRevokedFromSourceCallback(
}
void ProfileOAuth2TokenService::Shutdown() {
- CancelAllRequests();
+ token_manager_->CancelAllRequests();
GetDelegate()->Shutdown();
}
@@ -287,8 +290,8 @@ void ProfileOAuth2TokenService::RevokeAllCredentials(
SourceForRefreshTokenOperation source) {
base::AutoReset<SourceForRefreshTokenOperation> auto_reset(
&update_refresh_token_source_, source);
- CancelAllRequests();
- ClearCache();
+ token_manager_->CancelAllRequests();
+ token_manager_->ClearCache();
GetDelegate()->RevokeAllCredentials();
}
@@ -341,24 +344,12 @@ void ProfileOAuth2TokenService::UpdateAuthErrorForTesting(
GetDelegate()->UpdateAuthError(account_id, error);
}
-int ProfileOAuth2TokenService::GetTokenCacheCountForTesting() {
- return token_manager_->token_cache().size();
-}
-
void ProfileOAuth2TokenService::
set_max_authorization_token_fetch_retries_for_testing(int max_retries) {
token_manager_->set_max_authorization_token_fetch_retries_for_testing(
max_retries);
}
-size_t ProfileOAuth2TokenService::GetNumPendingRequestsForTesting(
- const std::string& client_id,
- const CoreAccountId& account_id,
- const OAuth2AccessTokenManager::ScopeSet& scopes) const {
- return token_manager_->GetNumPendingRequestsForTesting(client_id, account_id,
- scopes);
-}
-
void ProfileOAuth2TokenService::OverrideAccessTokenManagerForTesting(
std::unique_ptr<OAuth2AccessTokenManager> token_manager) {
token_manager_ = std::move(token_manager);
@@ -380,8 +371,8 @@ void ProfileOAuth2TokenService::OnRefreshTokenAvailable(
is_valid = false;
}
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
+ token_manager_->CancelRequestsForAccount(account_id);
+ token_manager_->ClearCacheForAccount(account_id);
signin_metrics::RecordRefreshTokenUpdatedFromSource(
is_valid, update_refresh_token_source_);
@@ -397,8 +388,8 @@ void ProfileOAuth2TokenService::OnRefreshTokenRevoked(
// If this was the last token, recreate the device ID.
RecreateDeviceIdIfNeeded();
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
+ token_manager_->CancelRequestsForAccount(account_id);
+ token_manager_->ClearCacheForAccount(account_id);
signin_metrics::RecordRefreshTokenRevokedFromSource(
update_refresh_token_source_);
@@ -424,24 +415,6 @@ void ProfileOAuth2TokenService::OnRefreshTokensLoaded() {
RecreateDeviceIdIfNeeded();
}
-void ProfileOAuth2TokenService::ClearCache() {
- token_manager_->ClearCache();
-}
-
-void ProfileOAuth2TokenService::ClearCacheForAccount(
- const CoreAccountId& account_id) {
- token_manager_->ClearCacheForAccount(account_id);
-}
-
-void ProfileOAuth2TokenService::CancelAllRequests() {
- token_manager_->CancelAllRequests();
-}
-
-void ProfileOAuth2TokenService::CancelRequestsForAccount(
- const CoreAccountId& account_id) {
- token_manager_->CancelRequestsForAccount(account_id);
-}
-
bool ProfileOAuth2TokenService::HasLoadCredentialsFinishedWithNoErrors() {
switch (GetDelegate()->load_credentials_state()) {
case signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED:
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h
index 44a08697caa..8ddf142a4db 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service.h
@@ -14,12 +14,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "build/buildflag.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "components/signin/public/base/signin_buildflags.h"
#include "components/signin/public/base/signin_metrics.h"
#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_manager.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "net/base/backoff_entry.h"
namespace signin {
@@ -60,7 +60,7 @@ class ProfileOAuth2TokenServiceDelegate;
//
// Note: requests should be started from the UI thread.
class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
- public OAuth2TokenServiceObserver {
+ public ProfileOAuth2TokenServiceObserver {
public:
typedef base::RepeatingCallback<void(const CoreAccountId& /* account_id */,
bool /* is_refresh_token_valid */,
@@ -84,10 +84,11 @@ class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
bool FixRequestErrorIfPossible() override;
scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
const override;
- void OnAccessTokenInvalidated(const CoreAccountId& account_id,
- const std::string& client_id,
- const std::set<std::string>& scopes,
- const std::string& access_token) override;
+ void OnAccessTokenInvalidated(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ const std::string& access_token) override;
void OnAccessTokenFetched(const CoreAccountId& account_id,
const GoogleServiceAuthError& error) override;
@@ -98,8 +99,8 @@ class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
const ProfileOAuth2TokenServiceDelegate* GetDelegate() const;
// Add or remove observers of this token service.
- void AddObserver(OAuth2TokenServiceObserver* observer);
- void RemoveObserver(OAuth2TokenServiceObserver* observer);
+ void AddObserver(ProfileOAuth2TokenServiceObserver* observer);
+ void RemoveObserver(ProfileOAuth2TokenServiceObserver* observer);
// Add or remove observers of access token manager.
void AddAccessTokenDiagnosticsObserver(
@@ -250,16 +251,8 @@ class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
void UpdateAuthErrorForTesting(const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
- int GetTokenCacheCountForTesting();
-
void set_max_authorization_token_fetch_retries_for_testing(int max_retries);
- // Returns the current number of pending fetchers matching given params.
- size_t GetNumPendingRequestsForTesting(
- const std::string& client_id,
- const CoreAccountId& account_id,
- const OAuth2AccessTokenManager::ScopeSet& scopes) const;
-
// Override |token_manager_| for testing.
void OverrideAccessTokenManagerForTesting(
std::unique_ptr<OAuth2AccessTokenManager> token_manager);
@@ -270,25 +263,11 @@ class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
private:
friend class signin::IdentityManager;
- // OAuth2TokenServiceObserver implementation.
+ // ProfileOAuth2TokenServiceObserver implementation.
void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
void OnRefreshTokensLoaded() override;
- // Clears the internal token cache.
- void ClearCache();
-
- // Clears all of the tokens belonging to |account_id| from the internal token
- // cache. It does not matter what other parameters, like |client_id| were
- // used to request the tokens.
- void ClearCacheForAccount(const CoreAccountId& account_id);
-
- // Cancels all requests that are currently in progress.
- void CancelAllRequests();
-
- // Cancels all requests related to a given |account_id|.
- void CancelRequestsForAccount(const CoreAccountId& account_id);
-
// Creates a new device ID if there are no accounts, or if the current device
// ID is empty.
void RecreateDeviceIdIfNeeded();
@@ -309,10 +288,8 @@ class ProfileOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
signin_metrics::SourceForRefreshTokenOperation update_refresh_token_source_ =
signin_metrics::SourceForRefreshTokenOperation::kUnknown;
- FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest, UpdateClearsCache);
- FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest, CancelAllRequests);
FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
- CancelRequestsForAccount);
+ SameScopesRequestedForDifferentClients);
DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService);
};
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
index 7c95f143435..8544d3acb71 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc
@@ -22,7 +22,7 @@
#if defined(OS_CHROMEOS)
#include "chromeos/components/account_manager/account_manager.h"
-#include "chromeos/constants/chromeos_switches.h"
+#include "chromeos/constants/chromeos_features.h"
#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h"
#include "components/user_manager/user_manager.h"
#endif // defined(OS_CHROMEOS)
@@ -141,7 +141,7 @@ CreateOAuth2TokenServiceDelegate(
account_tracker_service);
#else // !defined(OS_ANDROID) && !defined(OS_IOS)
#if defined(OS_CHROMEOS)
- if (chromeos::switches::IsAccountManagerEnabled()) {
+ if (chromeos::features::IsAccountManagerEnabled()) {
return CreateCrOsOAuthDelegate(account_tracker_service,
network_connection_tracker, account_manager,
is_regular_profile);
@@ -150,7 +150,7 @@ CreateOAuth2TokenServiceDelegate(
// Fall back to |MutableProfileOAuth2TokenServiceDelegate|:
// 1. On all platforms other than Android and Chrome OS.
// 2. On Chrome OS, if Account Manager has not been switched on yet
- // (chromeos::switches::IsAccountManagerEnabled).
+ // (chromeos::features::IsAccountManagerEnabled).
return CreateMutableProfileOAuthDelegate(
account_tracker_service, account_consistency,
delete_signin_cookies_on_exit, token_web_data, signin_client,
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc
index 15c4384edfe..db2ba0df863 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc
@@ -4,8 +4,8 @@
#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
ProfileOAuth2TokenServiceDelegate::ScopedBatchChange::ScopedBatchChange(
@@ -43,12 +43,12 @@ bool ProfileOAuth2TokenServiceDelegate::ValidateAccountId(
}
void ProfileOAuth2TokenServiceDelegate::AddObserver(
- OAuth2TokenServiceObserver* observer) {
+ ProfileOAuth2TokenServiceObserver* observer) {
observer_list_.AddObserver(observer);
}
void ProfileOAuth2TokenServiceDelegate::RemoveObserver(
- OAuth2TokenServiceObserver* observer) {
+ ProfileOAuth2TokenServiceObserver* observer) {
observer_list_.RemoveObserver(observer);
}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
index 3e7738c8bfd..d22b7ea6327 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
@@ -17,6 +17,7 @@
#include "components/signin/public/identity_manager/load_credentials_state.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_manager.h"
#include "net/base/backoff_entry.h"
namespace network {
@@ -25,7 +26,7 @@ class SharedURLLoaderFactory;
class OAuth2AccessTokenFetcher;
class OAuth2AccessTokenConsumer;
-class OAuth2TokenServiceObserver;
+class ProfileOAuth2TokenServiceObserver;
class ProfileOAuth2TokenService;
// Abstract base class to fetch and maintain refresh tokens from various
@@ -60,10 +61,11 @@ class ProfileOAuth2TokenServiceDelegate {
virtual std::vector<CoreAccountId> GetAccounts() const;
virtual void RevokeAllCredentials() {}
- virtual void OnAccessTokenInvalidated(const CoreAccountId& account_id,
- const std::string& client_id,
- const std::set<std::string>& scopes,
- const std::string& access_token) {}
+ virtual void OnAccessTokenInvalidated(
+ const CoreAccountId& account_id,
+ const std::string& client_id,
+ const OAuth2AccessTokenManager::ScopeSet& scopes,
+ const std::string& access_token) {}
// If refresh token is accessible (on Desktop) sets error for it to
// INVALID_GAIA_CREDENTIALS and notifies the observers. Otherwise
@@ -87,8 +89,8 @@ class ProfileOAuth2TokenServiceDelegate {
bool ValidateAccountId(const CoreAccountId& account_id) const;
// Add or remove observers of this token service.
- void AddObserver(OAuth2TokenServiceObserver* observer);
- void RemoveObserver(OAuth2TokenServiceObserver* observer);
+ void AddObserver(ProfileOAuth2TokenServiceObserver* observer);
+ void RemoveObserver(ProfileOAuth2TokenServiceObserver* observer);
// Returns a pointer to its instance of net::BackoffEntry if it has one, or
// a nullptr otherwise.
@@ -169,7 +171,7 @@ class ProfileOAuth2TokenServiceDelegate {
private:
// List of observers to notify when refresh token availability changes.
// Makes sure list is empty on destruction.
- base::ObserverList<OAuth2TokenServiceObserver, true>::Unchecked
+ base::ObserverList<ProfileOAuth2TokenServiceObserver, true>::Unchecked
observer_list_;
// The state of the load credentials operation.
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc
index 3a064c68e01..247e746ce16 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc
@@ -106,7 +106,7 @@ ProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher(
if (it != errors_.end() && it->second.last_auth_error.IsPersistentError()) {
VLOG(1) << "Request for token has been rejected due to persistent error #"
<< it->second.last_auth_error.state();
- // |OAuth2TokenService| will manage the lifetime of this pointer.
+ // |ProfileOAuth2TokenService| will manage the lifetime of this pointer.
return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
consumer, it->second.last_auth_error);
}
@@ -114,7 +114,7 @@ ProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher(
if (backoff_entry_.ShouldRejectRequest()) {
VLOG(1) << "Request for token has been rejected due to backoff rules from"
<< " previous error #" << backoff_error_.state();
- // |OAuth2TokenService| will manage the lifetime of this pointer.
+ // |ProfileOAuth2TokenService| will manage the lifetime of this pointer.
return std::make_unique<OAuth2AccessTokenFetcherImmediateError>(
consumer, backoff_error_);
}
@@ -216,8 +216,9 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::LoadCredentials(
// initialization, but for Signin Profile and Lock Screen Profile this is a
// no-op: they do not and must not have a working Account Manager available
// to them. Note: They do have access to an Account Manager instance, but
- // that instance is never set up (|AccountManager::Initialize|). Also, see
- // http://crbug.com/891818
+ // that instance is never set up (|AccountManager::Initialize|). Also, see:
+ // - http://crbug.com/891818
+ // - https://crbug.com/996615 and |GetURLLoaderFactory|.
set_load_credentials_state(
signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
FireRefreshTokensLoaded();
@@ -285,6 +286,22 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateCredentials(
scoped_refptr<network::SharedURLLoaderFactory>
ProfileOAuth2TokenServiceDelegateChromeOS::GetURLLoaderFactory() const {
+ if (!is_regular_profile_) {
+ // Signin and Lock Screen profiles (non-|is_regular_profile_|s) have weird
+ // expectations around token loading. They do not have an account associated
+ // with them but expect calls like |LoadCredentials| and
+ // |GetURLLoaderFactory| to successfully complete.
+ // We *can* return a |nullptr| here because the return value of
+ // |GetURLLoaderFactory| is never used by Signin and Lock Screen profiles.
+ // They get a hard-coded |GoogleServiceAuthError::USER_NOT_SIGNED_UP| error
+ // returned to them by access token fetchers.
+ // We *must* return a |nullptr| here because otherwise |AccountManager|
+ // DCHECKs as it has not been initialized for non-|is_regular_profile_| and
+ // crashes for this weird case (Non-regular profiles expecting to act on
+ // accounts).
+ // See https://crbug.com/996615 for details.
+ return nullptr;
+ }
return account_manager_->GetUrlLoaderFactory();
}
@@ -300,7 +317,7 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnGetAccounts(
set_load_credentials_state(
signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS);
- // The typical order of |OAuth2TokenServiceObserver| callbacks is:
+ // The typical order of |ProfileOAuth2TokenServiceObserver| callbacks is:
// 1. OnRefreshTokenAvailable
// 2. OnEndBatchChanges
// 3. OnRefreshTokensLoaded
@@ -351,7 +368,7 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnTokenUpserted(
ScopedBatchChange batch(this);
FireRefreshTokenAvailable(account_id);
- // See |OAuth2TokenServiceObserver::OnAuthErrorChanged|.
+ // See |ProfileOAuth2TokenServiceObserver::OnAuthErrorChanged|.
// |OnAuthErrorChanged| must be always called after
// |OnRefreshTokenAvailable|, when refresh token is updated.
FireAuthErrorChanged(account_id, error);
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h
index affc6247883..a538d24bde2 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h
@@ -66,9 +66,9 @@ class ProfileOAuth2TokenServiceDelegateChromeOS
void OnConnectionChanged(network::mojom::ConnectionType type) override;
private:
- FRIEND_TEST_ALL_PREFIXES(CrOSOAuthDelegateTest,
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceDelegateChromeOSTest,
BackOffIsTriggerredForTransientErrors);
- FRIEND_TEST_ALL_PREFIXES(CrOSOAuthDelegateTest,
+ FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceDelegateChromeOSTest,
BackOffIsResetOnNetworkChange);
// A utility class to keep track of |GoogleServiceAuthError|s for an account.
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc
index d161cb81862..eeb1c6a49d2 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc
@@ -14,9 +14,10 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "chromeos/components/account_manager/account_manager.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/base/test_signin_client.h"
#include "components/signin/public/identity_manager/account_info.h"
@@ -25,7 +26,6 @@
#include "google_apis/gaia/oauth2_access_token_consumer.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#include "google_apis/gaia/oauth2_access_token_manager_test_util.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,7 +60,8 @@ class AccessTokenConsumer : public OAuth2AccessTokenConsumer {
DISALLOW_COPY_AND_ASSIGN(AccessTokenConsumer);
};
-class TestOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
+class TestOAuth2TokenServiceObserver
+ : public ProfileOAuth2TokenServiceObserver {
public:
// |delegate| is a non-owning pointer to an
// |ProfileOAuth2TokenServiceDelegate| that MUST outlive |this| instance.
@@ -145,10 +146,10 @@ class TestOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
} // namespace
-class CrOSOAuthDelegateTest : public testing::Test {
+class ProfileOAuth2TokenServiceDelegateChromeOSTest : public testing::Test {
public:
- CrOSOAuthDelegateTest() {}
- ~CrOSOAuthDelegateTest() override = default;
+ ProfileOAuth2TokenServiceDelegateChromeOSTest() {}
+ ~ProfileOAuth2TokenServiceDelegateChromeOSTest() override = default;
protected:
void SetUp() override {
@@ -159,7 +160,8 @@ class CrOSOAuthDelegateTest : public testing::Test {
client_ = std::make_unique<TestSigninClient>(&pref_service_);
account_manager_.Initialize(tmp_dir_.GetPath(),
client_->GetURLLoaderFactory(),
- immediate_callback_runner_, &pref_service_);
+ immediate_callback_runner_);
+ account_manager_.SetPrefService(&pref_service_);
task_environment_.RunUntilIdle();
account_tracker_service_.Initialize(&pref_service_, base::FilePath());
@@ -205,7 +207,7 @@ class CrOSOAuthDelegateTest : public testing::Test {
GetValidTokenResponse("token", 3600));
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir tmp_dir_;
AccountInfo account_info_;
@@ -221,12 +223,13 @@ class CrOSOAuthDelegateTest : public testing::Test {
std::unique_ptr<TestSigninClient> client_;
private:
- DISALLOW_COPY_AND_ASSIGN(CrOSOAuthDelegateTest);
+ DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenServiceDelegateChromeOSTest);
};
// Refresh tokens should load successfully for non-regular (Signin and Lock
// Screen) Profiles.
-TEST_F(CrOSOAuthDelegateTest, RefreshTokensAreLoadedForNonRegularProfiles) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ RefreshTokensAreLoadedForNonRegularProfiles) {
// Create an instance of Account Manager but do not
// |AccountManager::Initialize| it. This mimics Signin and Lock Screen Profile
// behaviour.
@@ -246,7 +249,7 @@ TEST_F(CrOSOAuthDelegateTest, RefreshTokensAreLoadedForNonRegularProfiles) {
delegate->load_credentials_state());
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
RefreshTokenIsAvailableReturnsTrueForValidGaiaTokens) {
EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate_->load_credentials_state());
@@ -262,7 +265,7 @@ TEST_F(CrOSOAuthDelegateTest,
base::Contains(delegate_->GetAccounts(), account_info_.account_id));
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
RefreshTokenIsAvailableReturnsTrueForInvalidGaiaTokens) {
EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate_->load_credentials_state());
@@ -279,7 +282,8 @@ TEST_F(CrOSOAuthDelegateTest,
base::Contains(delegate_->GetAccounts(), account_info_.account_id));
}
-TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAuthErrorChange) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ ObserversAreNotifiedOnAuthErrorChange) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
auto error =
GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
@@ -290,7 +294,8 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAuthErrorChange) {
EXPECT_EQ(error, observer.last_err_);
}
-TEST_F(CrOSOAuthDelegateTest, ObserversAreNotNotifiedIfErrorDidntChange) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ ObserversAreNotNotifiedIfErrorDidntChange) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
auto error =
GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
@@ -301,7 +306,8 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotNotifiedIfErrorDidntChange) {
EXPECT_EQ(1, observer.on_auth_error_changed_calls);
}
-TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedIfErrorDidChange) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ ObserversAreNotifiedIfErrorDidChange) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateAuthError(
account_info_.account_id,
@@ -315,7 +321,8 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedIfErrorDidChange) {
EXPECT_EQ(2, observer.on_auth_error_changed_calls);
}
-TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsInsertion) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ ObserversAreNotifiedOnCredentialsInsertion) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
@@ -325,7 +332,7 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsInsertion) {
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.last_err_);
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
ObserversDoNotSeeCachedErrorsOnCredentialsUpdate) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
auto error =
@@ -338,7 +345,8 @@ TEST_F(CrOSOAuthDelegateTest,
delegate_->UpdateCredentials(account_info_.account_id, "new-token");
}
-TEST_F(CrOSOAuthDelegateTest, DummyTokensArePreEmptivelyRejected) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ DummyTokensArePreEmptivelyRejected) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id,
chromeos::AccountManager::kInvalidToken);
@@ -356,7 +364,8 @@ TEST_F(CrOSOAuthDelegateTest, DummyTokensArePreEmptivelyRejected) {
EXPECT_EQ(account_info_.account_id, observer.last_err_account_id_);
}
-TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsUpdate) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ ObserversAreNotifiedOnCredentialsUpdate) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
@@ -366,7 +375,7 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnCredentialsUpdate) {
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), observer.last_err_);
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
ObserversAreNotNotifiedIfCredentialsAreNotUpdated) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
@@ -379,7 +388,7 @@ TEST_F(CrOSOAuthDelegateTest,
EXPECT_EQ(std::string(), observer.last_err_account_id_);
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
TestOAuth2TokenServiceObserver observer(delegate_.get());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
@@ -392,7 +401,8 @@ TEST_F(CrOSOAuthDelegateTest,
// If observers register themselves with |ProfileOAuth2TokenServiceDelegate|
// before |chromeos::AccountManager| has been initialized, they should receive
// all the accounts stored in |chromeos::AccountManager| in a single batch.
-TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ BatchChangeObserversAreNotifiedOncePerBatch) {
// Setup
AccountInfo account1 = CreateAccountInfoTestFixture(
"1" /* gaia_id */, "user1@example.com" /* email */);
@@ -413,7 +423,8 @@ TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
// chromeos::AccountManager will not be fully initialized until
// |task_environment_.RunUntilIdle()| is called.
account_manager.Initialize(tmp_dir_.GetPath(), client_->GetURLLoaderFactory(),
- immediate_callback_runner_, &pref_service_);
+ immediate_callback_runner_);
+ account_manager.SetPrefService(&pref_service_);
// Register callbacks before chromeos::AccountManager has been fully
// initialized.
@@ -444,7 +455,8 @@ TEST_F(CrOSOAuthDelegateTest, BatchChangeObserversAreNotifiedOncePerBatch) {
EXPECT_TRUE(base::Contains(first_batch, account2.account_id));
}
-TEST_F(CrOSOAuthDelegateTest, GetAccountsShouldNotReturnAdAccounts) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ GetAccountsShouldNotReturnAdAccounts) {
EXPECT_TRUE(delegate_->GetAccounts().empty());
// Insert an Active Directory account into chromeos::AccountManager.
@@ -456,7 +468,8 @@ TEST_F(CrOSOAuthDelegateTest, GetAccountsShouldNotReturnAdAccounts) {
EXPECT_TRUE(delegate_->GetAccounts().empty());
}
-TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccounts) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ GetAccountsReturnsGaiaAccounts) {
EXPECT_TRUE(delegate_->GetAccounts().empty());
account_manager_.UpsertAccount(gaia_account_key_, kUserEmail, kGaiaToken);
@@ -468,7 +481,8 @@ TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccounts) {
// |GetAccounts| should return all known Gaia accounts, whether or not they have
// a "valid" refresh token stored against them.
-TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccountsWithInvalidTokens) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ GetAccountsReturnsGaiaAccountsWithInvalidTokens) {
EXPECT_TRUE(delegate_->GetAccounts().empty());
account_manager_.UpsertAccount(gaia_account_key_, kUserEmail,
@@ -479,7 +493,7 @@ TEST_F(CrOSOAuthDelegateTest, GetAccountsReturnsGaiaAccountsWithInvalidTokens) {
EXPECT_EQ(account_info_.account_id, accounts[0]);
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
RefreshTokenMustBeAvailableForAllAccountsReturnedByGetAccounts) {
EXPECT_EQ(LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS,
delegate_->load_credentials_state());
@@ -512,7 +526,8 @@ TEST_F(CrOSOAuthDelegateTest,
}
}
-TEST_F(CrOSOAuthDelegateTest, UpdateCredentialsSucceeds) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ UpdateCredentialsSucceeds) {
EXPECT_TRUE(delegate_->GetAccounts().empty());
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
@@ -522,7 +537,8 @@ TEST_F(CrOSOAuthDelegateTest, UpdateCredentialsSucceeds) {
EXPECT_EQ(account_info_.account_id, accounts[0]);
}
-TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAccountRemoval) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ ObserversAreNotifiedOnAccountRemoval) {
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
TestOAuth2TokenServiceObserver observer(delegate_.get());
@@ -534,7 +550,7 @@ TEST_F(CrOSOAuthDelegateTest, ObserversAreNotifiedOnAccountRemoval) {
EXPECT_TRUE(observer.account_ids_.empty());
}
-TEST_F(CrOSOAuthDelegateTest,
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
SigninErrorObserversAreNotifiedOnAuthErrorChange) {
auto error =
GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR);
@@ -544,7 +560,8 @@ TEST_F(CrOSOAuthDelegateTest,
EXPECT_EQ(error, delegate_->GetAuthError(account_info_.account_id));
}
-TEST_F(CrOSOAuthDelegateTest, TransientErrorsAreNotShown) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ TransientErrorsAreNotShown) {
auto transient_error = GoogleServiceAuthError(
GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
@@ -556,7 +573,8 @@ TEST_F(CrOSOAuthDelegateTest, TransientErrorsAreNotShown) {
delegate_->GetAuthError(account_info_.account_id));
}
-TEST_F(CrOSOAuthDelegateTest, BackOffIsTriggerredForTransientErrors) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ BackOffIsTriggerredForTransientErrors) {
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
auto transient_error = GoogleServiceAuthError(
GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
@@ -593,7 +611,8 @@ TEST_F(CrOSOAuthDelegateTest, BackOffIsTriggerredForTransientErrors) {
EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
}
-TEST_F(CrOSOAuthDelegateTest, BackOffIsResetOnNetworkChange) {
+TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest,
+ BackOffIsResetOnNetworkChange) {
delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken);
auto transient_error = GoogleServiceAuthError(
GoogleServiceAuthError::State::SERVICE_UNAVAILABLE);
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
index 0ae0cd018da..5374520b5af 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios_unittest.mm
@@ -6,10 +6,11 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/base/test_signin_client.h"
#include "components/signin/public/identity_manager/ios/fake_device_accounts_provider.h"
@@ -17,7 +18,6 @@
#include "google_apis/gaia/oauth2_access_token_consumer.h"
#include "google_apis/gaia/oauth2_access_token_fetcher.h"
#include "google_apis/gaia/oauth2_access_token_manager_test_util.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -31,7 +31,7 @@ typedef DeviceAccountsProvider::AccountInfo ProviderAccount;
class ProfileOAuth2TokenServiceIOSDelegateTest
: public PlatformTest,
public OAuth2AccessTokenConsumer,
- public OAuth2TokenServiceObserver {
+ public ProfileOAuth2TokenServiceObserver {
public:
ProfileOAuth2TokenServiceIOSDelegateTest()
: factory_(nullptr),
@@ -77,7 +77,7 @@ class ProfileOAuth2TokenServiceIOSDelegateTest
last_access_token_error_ = error;
}
- // OAuth2TokenServiceObserver implementation.
+ // ProfileOAuth2TokenServiceObserver implementation.
void OnRefreshTokenAvailable(const CoreAccountId& account_id) override {
++token_available_count_;
}
@@ -105,7 +105,7 @@ class ProfileOAuth2TokenServiceIOSDelegateTest
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
net::FakeURLFetcherFactory factory_;
TestingPrefServiceSimple prefs_;
TestSigninClient client_;
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
index f6132ef08f7..333c6e2f22d 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_unittest.cc
@@ -9,9 +9,9 @@
#include "base/macros.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "services/network/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,7 +21,8 @@
// mobile where refresh tokens are not accessible. This test checks that refresh
// tokens are not affected on INVALID_TOKENS Multilogin error.
TEST(ProfileOAuth2TokenServiceDelegateTest, InvalidateTokensForMultilogin) {
- class TestOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
+ class TestOAuth2TokenServiceObserver
+ : public ProfileOAuth2TokenServiceObserver {
public:
MOCK_METHOD2(OnAuthErrorChanged,
void(const CoreAccountId&, const GoogleServiceAuthError&));
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h
new file mode 100644
index 00000000000..b9cc2ce41f5
--- /dev/null
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h
@@ -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.
+
+#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_OBSERVER_H_
+#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_OBSERVER_H_
+
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+// Classes that want to listen for refresh token availability should
+// implement this interface and register with the ProfileOAuth2TokenService::
+// AddObserver() call.
+class ProfileOAuth2TokenServiceObserver {
+ public:
+ // Called whenever a new login-scoped refresh token is available for
+ // account |account_id|. Once available, access tokens can be retrieved for
+ // this account. This is called during initial startup for each token
+ // loaded (and any time later when, e.g., credentials change). When called,
+ // any pending token request is canceled and needs to be retried. Such a
+ // pending request can easily occur on Android, where refresh tokens are
+ // held by the OS and are thus often available on startup even before
+ // OnRefreshTokenAvailable() is called.
+ virtual void OnRefreshTokenAvailable(const CoreAccountId& account_id) {}
+ // Called whenever the login-scoped refresh token becomes unavailable for
+ // account |account_id|.
+ virtual void OnRefreshTokenRevoked(const CoreAccountId& account_id) {}
+ // Called after all refresh tokens are loaded during ProfileOAuth2TokenService
+ // startup.
+ virtual void OnRefreshTokensLoaded() {}
+ // Sent after a batch of refresh token changes is done.
+ virtual void OnEndBatchChanges() {}
+ // Called when the authentication error state for |account_id| has changed.
+ // Note: It is always called after |OnRefreshTokenAvailable| when refresh
+ // token is updated. It is not called when the refresh token is revoked.
+ virtual void OnAuthErrorChanged(const CoreAccountId& account_id,
+ const GoogleServiceAuthError& auth_error) {}
+
+ protected:
+ virtual ~ProfileOAuth2TokenServiceObserver() {}
+};
+
+#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PROFILE_OAUTH2_TOKEN_SERVICE_OBSERVER_H_
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc
index c77c9336b7f..6c04923187a 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_unittest.cc
@@ -7,8 +7,8 @@
#include <stddef.h>
#include <string>
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h"
@@ -54,7 +54,8 @@ class RetryingTestingOAuth2AccessTokenManagerConsumer
std::unique_ptr<OAuth2AccessTokenManager::Request> request_;
};
-class FakeOAuth2TokenServiceObserver : public OAuth2TokenServiceObserver {
+class FakeOAuth2TokenServiceObserver
+ : public ProfileOAuth2TokenServiceObserver {
public:
MOCK_METHOD2(OnAuthErrorChanged,
void(const CoreAccountId&, const GoogleServiceAuthError&));
@@ -115,7 +116,9 @@ class ProfileOAuth2TokenServiceTest : public testing::Test {
}
protected:
- base::MessageLoopForIO message_loop_; // net:: stuff needs IO message loop.
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO}; // net:: stuff needs IO
+ // message loop.
network::TestURLLoaderFactory* test_url_loader_factory_ = nullptr;
FakeProfileOAuth2TokenServiceDelegate* delegate_ptr_ = nullptr; // Not owned.
std::unique_ptr<ProfileOAuth2TokenService> oauth2_service_;
@@ -643,65 +646,6 @@ TEST_F(ProfileOAuth2TokenServiceTest, InvalidateToken) {
EXPECT_EQ("token2", consumer_.last_token_);
}
-TEST_F(ProfileOAuth2TokenServiceTest, CancelAllRequests) {
- oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
- "refreshToken");
- std::unique_ptr<OAuth2AccessTokenManager::Request> request(
- oauth2_service_->StartRequest(
- account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
- const CoreAccountId account_id_2("account_id_2");
- oauth2_service_->GetDelegate()->UpdateCredentials(account_id_2,
- "refreshToken2");
- std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
- oauth2_service_->StartRequest(
- account_id_, OAuth2AccessTokenManager::ScopeSet(), &consumer_));
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(0, consumer_.number_of_errors_);
-
- oauth2_service_->CancelAllRequests();
-
- EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(2, consumer_.number_of_errors_);
-}
-
-TEST_F(ProfileOAuth2TokenServiceTest, CancelRequestsForAccount) {
- OAuth2AccessTokenManager::ScopeSet scope_set_1;
- scope_set_1.insert("scope1");
- scope_set_1.insert("scope2");
- OAuth2AccessTokenManager::ScopeSet scope_set_2(scope_set_1.begin(),
- scope_set_1.end());
- scope_set_2.insert("scope3");
-
- oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
- "refreshToken");
- std::unique_ptr<OAuth2AccessTokenManager::Request> request1(
- oauth2_service_->StartRequest(account_id_, scope_set_1, &consumer_));
- std::unique_ptr<OAuth2AccessTokenManager::Request> request2(
- oauth2_service_->StartRequest(account_id_, scope_set_2, &consumer_));
-
- const CoreAccountId account_id_2("account_id_2");
- oauth2_service_->GetDelegate()->UpdateCredentials(account_id_2,
- "refreshToken2");
- std::unique_ptr<OAuth2AccessTokenManager::Request> request3(
- oauth2_service_->StartRequest(account_id_2, scope_set_1, &consumer_));
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(0, consumer_.number_of_errors_);
-
- oauth2_service_->CancelRequestsForAccount(account_id_);
-
- EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(2, consumer_.number_of_errors_);
-
- oauth2_service_->CancelRequestsForAccount(account_id_2);
-
- EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(3, consumer_.number_of_errors_);
-}
-
TEST_F(ProfileOAuth2TokenServiceTest, SameScopesRequestedForDifferentClients) {
std::string client_id_1("client1");
std::string client_secret_1("secret1");
@@ -726,10 +670,12 @@ TEST_F(ProfileOAuth2TokenServiceTest, SameScopesRequestedForDifferentClients) {
account_id_, client_id_1, client_secret_1, scope_set, &consumer_));
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(2U, oauth2_service_->GetNumPendingRequestsForTesting(
- client_id_1, account_id_, scope_set));
- ASSERT_EQ(1U, oauth2_service_->GetNumPendingRequestsForTesting(
- client_id_2, account_id_, scope_set));
+ ASSERT_EQ(2U,
+ oauth2_service_->token_manager_->GetNumPendingRequestsForTesting(
+ client_id_1, account_id_, scope_set));
+ ASSERT_EQ(1U,
+ oauth2_service_->token_manager_->GetNumPendingRequestsForTesting(
+ client_id_2, account_id_, scope_set));
}
TEST_F(ProfileOAuth2TokenServiceTest, RequestParametersOrderTest) {
@@ -766,34 +712,6 @@ TEST_F(ProfileOAuth2TokenServiceTest, RequestParametersOrderTest) {
}
}
-TEST_F(ProfileOAuth2TokenServiceTest, UpdateClearsCache) {
- const CoreAccountId account_id("test@gmail.com");
- std::set<std::string> scope_list;
- scope_list.insert("scope");
- oauth2_service_->GetDelegate()->UpdateCredentials(account_id, "refreshToken");
- std::unique_ptr<OAuth2AccessTokenManager::Request> request(
- oauth2_service_->StartRequest(account_id, scope_list, &consumer_));
- SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(0, consumer_.number_of_errors_);
- EXPECT_EQ("token", consumer_.last_token_);
- EXPECT_EQ(1, oauth2_service_->GetTokenCacheCountForTesting());
-
- oauth2_service_->ClearCache();
-
- EXPECT_EQ(0, oauth2_service_->GetTokenCacheCountForTesting());
- oauth2_service_->GetDelegate()->UpdateCredentials(account_id, "refreshToken");
- SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 3600));
- request = oauth2_service_->StartRequest(account_id, scope_list, &consumer_);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
- EXPECT_EQ(0, consumer_.number_of_errors_);
- EXPECT_EQ("another token", consumer_.last_token_);
- EXPECT_EQ(1, oauth2_service_->GetTokenCacheCountForTesting());
-}
-
TEST_F(ProfileOAuth2TokenServiceTest, FixRequestErrorIfPossible) {
oauth2_service_->GetDelegate()->UpdateCredentials(account_id_,
"refreshToken");
diff --git a/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc
index f4e7d910727..4e28f6dead4 100644
--- a/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/ubertoken_fetcher_impl_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
@@ -51,8 +51,7 @@ class MockUbertokenConsumer {
class UbertokenFetcherImplTest : public testing::Test {
public:
UbertokenFetcherImplTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
token_service_(&pref_service_),
test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
@@ -65,7 +64,7 @@ class UbertokenFetcherImplTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple pref_service_;
FakeProfileOAuth2TokenService token_service_;
network::TestURLLoaderFactory url_loader_factory_;
diff --git a/chromium/components/signin/ios/browser/BUILD.gn b/chromium/components/signin/ios/browser/BUILD.gn
index 7a6fc1ae28e..095aa04f21e 100644
--- a/chromium/components/signin/ios/browser/BUILD.gn
+++ b/chromium/components/signin/ios/browser/BUILD.gn
@@ -14,7 +14,7 @@ source_set("browser") {
deps = [
"//components/content_settings/core/browser",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/prefs",
"//components/signin/core/browser",
"//components/signin/public/base",
diff --git a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
index 66f0de142e3..420def833f0 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -25,7 +25,7 @@
#include "ios/web/public/navigation/web_state_policy_decider.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
#import "ios/web/public/test/fakes/test_web_state.h"
-#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "ios/web/public/test/web_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -141,8 +141,8 @@ class AccountConsistencyServiceTest : public PlatformTest {
settings_map_ = new HostContentSettingsMap(
&prefs_, false /* is_off_the_record */, false /* store_last_modified */,
false /* migrate_requesting_and_top_level_origin_settings */);
- cookie_settings_ =
- new content_settings::CookieSettings(settings_map_.get(), &prefs_, "");
+ cookie_settings_ = new content_settings::CookieSettings(settings_map_.get(),
+ &prefs_, false, "");
account_reconcilor_ =
std::make_unique<MockAccountReconcilor>(signin_client_.get());
ResetAccountConsistencyService();
@@ -235,7 +235,7 @@ class AccountConsistencyServiceTest : public PlatformTest {
// Creates test threads, necessary for ActiveStateManager that needs a UI
// thread.
- web::TestWebThreadBundle thread_bundle_;
+ web::WebTaskEnvironment task_environment_;
web::TestBrowserState browser_state_;
sync_preferences::TestingPrefServiceSyncable prefs_;
TestWebState web_state_;
diff --git a/chromium/components/signin/ios/browser/active_state_manager_impl_unittest.mm b/chromium/components/signin/ios/browser/active_state_manager_impl_unittest.mm
index 5863e7b439f..3910a93f5eb 100644
--- a/chromium/components/signin/ios/browser/active_state_manager_impl_unittest.mm
+++ b/chromium/components/signin/ios/browser/active_state_manager_impl_unittest.mm
@@ -7,7 +7,7 @@
#include "components/signin/ios/browser/active_state_manager.h"
#include "ios/web/public/browser_state.h"
#include "ios/web/public/test/fakes/test_browser_state.h"
-#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "ios/web/public/test/web_task_environment.h"
#include "ios/web/public/test/web_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc b/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc
index 7fb8e7cc040..e23d22f65d3 100644
--- a/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc
+++ b/chromium/components/signin/ios/browser/wait_for_network_callback_helper_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "net/base/mock_network_change_notifier.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,7 +21,7 @@ class WaitForNetworkCallbackHelperTest : public testing::Test {
WaitForNetworkCallbackHelperTest() : num_callbacks_invoked_(0) {}
int num_callbacks_invoked_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<net::test::MockNetworkChangeNotifier>
network_change_notifier_ = net::test::MockNetworkChangeNotifier::Create();
WaitForNetworkCallbackHelper callback_helper_;
@@ -51,6 +51,6 @@ TEST_F(WaitForNetworkCallbackHelperTest, CallbackInvokedLater) {
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
network_change_notifier_->NotifyObserversOfConnectionTypeChangeForTests(
net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(2, num_callbacks_invoked_);
}
diff --git a/chromium/components/signin/public/README.md b/chromium/components/signin/public/README.md
new file mode 100644
index 00000000000..59703fdd552
--- /dev/null
+++ b/chromium/components/signin/public/README.md
@@ -0,0 +1,4 @@
+The public API surface of the signin component. Look in subdirectories'
+README.md files for their purpose and the defined dependency structure between
+them. General consumers are most likely interested in identity_manager/, which
+contains the core public API surfaces of the signin component.
diff --git a/chromium/components/signin/public/base/README.md b/chromium/components/signin/public/base/README.md
new file mode 100644
index 00000000000..78d5aaed72f
--- /dev/null
+++ b/chromium/components/signin/public/base/README.md
@@ -0,0 +1,3 @@
+Low-level and general-purpose interfaces and utilities of the signin component
+that are used both by its consumers and its implementation. Not allowed to
+depend on any other part of the signin component.
diff --git a/chromium/components/signin/public/base/signin_client.cc b/chromium/components/signin/public/base/signin_client.cc
index 8a358e0d2ef..fe2bb1c1b8e 100644
--- a/chromium/components/signin/public/base/signin_client.cc
+++ b/chromium/components/signin/public/base/signin_client.cc
@@ -14,3 +14,7 @@ void SigninClient::PreSignOut(
void SigninClient::PreGaiaLogout(base::OnceClosure callback) {
std::move(callback).Run();
}
+
+bool SigninClient::IsNonEnterpriseUser(const std::string& username) {
+ return false;
+}
diff --git a/chromium/components/signin/public/base/signin_client.h b/chromium/components/signin/public/base/signin_client.h
index d5c7889000c..88ecd18dd5d 100644
--- a/chromium/components/signin/public/base/signin_client.h
+++ b/chromium/components/signin/public/base/signin_client.h
@@ -93,8 +93,16 @@ class SigninClient : public KeyedService {
GaiaAuthConsumer* consumer,
gaia::GaiaSource source) = 0;
+ // Marks the DICE migration completed.
+ virtual void SetDiceMigrationCompleted() {}
+
// Schedules migration to happen at next startup.
virtual void SetReadyForDiceMigration(bool is_ready) {}
+
+ // Checks whether a user is known to be non-enterprise. Domains such as
+ // gmail.com and googlemail.com are known to not be managed. Also returns
+ // false if the username is empty.
+ virtual bool IsNonEnterpriseUser(const std::string& username);
};
#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_CLIENT_H_
diff --git a/chromium/components/signin/public/base/signin_metrics.h b/chromium/components/signin/public/base/signin_metrics.h
index 77fe702a4e5..ca12cc21287 100644
--- a/chromium/components/signin/public/base/signin_metrics.h
+++ b/chromium/components/signin/public/base/signin_metrics.h
@@ -310,8 +310,9 @@ enum class SourceForRefreshTokenOperation {
kDiceTurnOnSyncHelper_Abort,
kMachineLogon_CredentialProvider,
kTokenService_ExtractCredentials,
+ kAccountReconcilor_RevokeTokensNotInCookies,
- kMaxValue = kTokenService_ExtractCredentials
+ kMaxValue = kAccountReconcilor_RevokeTokensNotInCookies
};
// Different types of reporting. This is used as a histogram suffix.
diff --git a/chromium/components/signin/public/base/signin_pref_names.cc b/chromium/components/signin/public/base/signin_pref_names.cc
index d613924ca51..0fe30dad4e8 100644
--- a/chromium/components/signin/public/base/signin_pref_names.cc
+++ b/chromium/components/signin/public/base/signin_pref_names.cc
@@ -101,7 +101,7 @@ const char kSigninAllowed[] = "signin.allowed";
// True if the token service has been prepared for Dice migration.
const char kTokenServiceDiceCompatible[] = "token_service.dice_compatible";
-// Boolean which stores if the OAuth2TokenService should ignore secondary
+// Boolean which stores if the ProfileOAuth2TokenService should ignore secondary
// accounts.
const char kTokenServiceExcludeAllSecondaryAccounts[] =
"token_service.exclude_all_secondary_accounts";
@@ -111,4 +111,8 @@ const char kTokenServiceExcludeAllSecondaryAccounts[] =
const char kTokenServiceExcludedSecondaryAccounts[] =
"token_service.excluded_secondary_accounts";
+// Contains last |ListAccounts| data which corresponds to Gaia cookies.
+const char kGaiaCookieLastListAccountsData[] =
+ "gaia_cookie.last_list_accounts_data";
+
} // namespace prefs
diff --git a/chromium/components/signin/public/base/signin_pref_names.h b/chromium/components/signin/public/base/signin_pref_names.h
index 01d8bab7e53..26f1c460dd9 100644
--- a/chromium/components/signin/public/base/signin_pref_names.h
+++ b/chromium/components/signin/public/base/signin_pref_names.h
@@ -30,6 +30,7 @@ extern const char kSigninAllowed[];
extern const char kTokenServiceDiceCompatible[];
extern const char kTokenServiceExcludeAllSecondaryAccounts[];
extern const char kTokenServiceExcludedSecondaryAccounts[];
+extern const char kGaiaCookieLastListAccountsData[];
} // namespace prefs
diff --git a/chromium/components/signin/public/base/test_signin_client.cc b/chromium/components/signin/public/base/test_signin_client.cc
index cfa57bc209c..cefecdde86a 100644
--- a/chromium/components/signin/public/base/test_signin_client.cc
+++ b/chromium/components/signin/public/base/test_signin_client.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "google_apis/gaia/gaia_auth_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/test/test_cookie_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,7 +21,8 @@ TestSigninClient::TestSigninClient(
are_signin_cookies_allowed_(true),
network_calls_delayed_(false),
is_signout_allowed_(true),
- is_ready_for_dice_migration_(false) {}
+ is_ready_for_dice_migration_(false),
+ is_dice_migration_completed_(false) {}
TestSigninClient::~TestSigninClient() {}
@@ -120,3 +122,11 @@ void TestSigninClient::PreGaiaLogout(base::OnceClosure callback) {
void TestSigninClient::SetReadyForDiceMigration(bool ready) {
is_ready_for_dice_migration_ = ready;
}
+
+void TestSigninClient::SetDiceMigrationCompleted() {
+ is_dice_migration_completed_ = true;
+}
+
+bool TestSigninClient::IsNonEnterpriseUser(const std::string& email) {
+ return gaia::ExtractDomainName(email) == "gmail.com";
+}
diff --git a/chromium/components/signin/public/base/test_signin_client.h b/chromium/components/signin/public/base/test_signin_client.h
index 5ea2deeca75..120f28810c8 100644
--- a/chromium/components/signin/public/base/test_signin_client.h
+++ b/chromium/components/signin/public/base/test_signin_client.h
@@ -73,6 +73,7 @@ class TestSigninClient : public SigninClient {
void set_is_signout_allowed(bool value) { is_signout_allowed_ = value; }
bool is_ready_for_dice_migration() { return is_ready_for_dice_migration_; }
+ bool is_dice_migration_completed() { return is_dice_migration_completed_; }
// When |value| is true, network calls posted through DelayNetworkCall() are
// delayed indefinitely.
@@ -92,6 +93,8 @@ class TestSigninClient : public SigninClient {
gaia::GaiaSource source) override;
void PreGaiaLogout(base::OnceClosure callback) override;
void SetReadyForDiceMigration(bool ready) override;
+ void SetDiceMigrationCompleted() override;
+ bool IsNonEnterpriseUser(const std::string& email) override;
private:
std::unique_ptr<network::TestURLLoaderFactory>
@@ -104,6 +107,7 @@ class TestSigninClient : public SigninClient {
bool network_calls_delayed_;
bool is_signout_allowed_;
bool is_ready_for_dice_migration_;
+ bool is_dice_migration_completed_;
std::vector<base::OnceClosure> delayed_network_calls_;
diff --git a/chromium/components/signin/public/identity_manager/BUILD.gn b/chromium/components/signin/public/identity_manager/BUILD.gn
index 28717d1888c..149b8c49409 100644
--- a/chromium/components/signin/public/identity_manager/BUILD.gn
+++ b/chromium/components/signin/public/identity_manager/BUILD.gn
@@ -59,6 +59,11 @@ source_set("identity_manager") {
deps += [ "ios" ]
}
+ if (is_android) {
+ deps +=
+ [ "//components/signin/internal/identity_manager/android:jni_headers" ]
+ }
+
allow_circular_includes_from = [
# This target is a pair with internal/identity_manager. They always go
# together and include headers from each other.
diff --git a/chromium/components/signin/public/identity_manager/README.md b/chromium/components/signin/public/identity_manager/README.md
index 5f68f505c4e..b1542f2f796 100644
--- a/chromium/components/signin/public/identity_manager/README.md
+++ b/chromium/components/signin/public/identity_manager/README.md
@@ -1,38 +1,125 @@
-IdentityManager is the next-generation C++ API for interacting with Google
-identity.
+The core public API surfaces for interacting with Google identity. Header files
+in this directory are allowed to depend only on the following other parts of the
+signin component:
-Documentation on the mapping between usage of legacy signin
-classes (notably PrimaryAccountManager and ProfileOAuth2TokenService) and usage
-of IdentityManager is available here:
+//components/signin/public/base
+//components/signin/public/webdata
-https://docs.google.com/document/d/14f3qqkDM9IE4Ff_l6wuXvCMeHfSC9TxKezXTCyeaPUY/edit#
+Implementation files in this directory, however, are additionally allowed to
+depend on //components/signin/internal/identity_manager.
-A quick inline cheat sheet for developers migrating from usage of //components/
-signin and //google_apis/gaia:
+Here we take a quick guide through the core concepts (note: Documentation on
+specific IdentityManager and IdentityManager::Observer methods can be found as
+method-level comments in identity_manager.h; this guide defines the core
+concepts themselves and gives a high-level mapping between these core concepts
+and the relevant IdentityManager(::Observer) API surfaces).
-- "Primary account" in IdentityManager refers to what is called the
- "authenticated account" in PrimaryAccountManager, i.e., the account that has
- been blessed for sync by the user.
+# Accounts
+- "Account" always refers to a Gaia account.
+- An account has three core pieces of information, which are collected together
+ in the CoreAccountInfo struct and are available for the duration of the
+ account being visible to IdentityManager:
+ - The email address.
+ - The Gaia ID.
+ - The account ID. This is an opaque Chrome-specific identifier for the
+ account.
+- The AccountInfo struct contains extra "extended" information about the account
+ that may become available only asynchronously after the account is first added
+ to Chrome. To interact with the extended account info, use the IdentityManager
+ methods with "ExtendedAccountInfo" in their names. To observe changes in the
+ state of the extended account info for one or more accounts, observe
+ IdentityManager and override one or more of the IdentityManager::Observer
+ methods with "ExtendedAccountInfo" in their names.
+
+# The Primary Account
+- "Primary account" in IdentityManager refers to the account that has been
+ blessed for sync by the user (what in Chromium historically was often referred
+ to as the "authenticated account").
- "Unconsented primary account" is intuitively the browsing identity of the user
- that we display to the user; despite its name, the user may or may not have
- blessed this account for sync. In particular, whenever a primary account
- exists, the unconsented primary account equals to the primary account. On
- desktop platforms (excl. ChromeOS), if no primary account exists and there
- exist any content-area accounts, it equals to the first signed-in content-area
- account. In all other cases there is no unconsented primary account.
+ that we display to the user; the user may or may not have blessed this account
+ for sync. In particular, whenever a primary account exists, the unconsented
+ primary account equals to the primary account. On desktop platforms (excl.
+ ChromeOS), if no primary account exists and there exist any content-area
+ accounts, the unconsented primary account equals to the first signed-in content-
+ area account. In all other cases there is no unconsented primary account.
+ NOTE: This name is still subject to finalization. The problem with
+ "unconsented" in this context is that it means "did not consent"; really, this
+ account is the "possibly unconsented, possibly primary, default account", which
+ is a mouthful :).
+- To interact with the primary account and/or unconsented primary account, use
+ the IdentityManager methods with "PrimaryAccount" in their names. To observe
+ changes in the presence of either of these accounts, observe IdentityManager
+ and override one or more of the methods with "PrimaryAccount" in their names
+ as desired.
- PrimaryAccountTokenFetcher is the primary client-side interface for obtaining
- access tokens for the primary account. In particular, it can take care of
- waiting until the primary account is available.
+ OAuth2 access tokens for the primary account (see the next section for the
+ discussion of OAuth2 tokens). In particular, it can handle the common use case
+ of "wait until the primary account is available and then fetch an access token
+ for it" transparently on behalf of the client. See
+ primary_account_access_token_fetcher.h for usage explanation and examples.
+
+# OAuth2 Access and Refresh Tokens
+- "OAuth2 tokens" are tokens related to the OAuth2 client-server authorization
+ protocol. "OAuth2 refresh tokens" or just "refresh tokens" are long-lived
+ tokens that the browser obtains via the user explicitly adding an account.
+ Clients of IdentityManager do not explicitly see refresh tokens, but rather use
+ IdentityManager to obtain "OAuth2 access tokens" or just "access tokens".
+ Access tokens are short-lived tokens with given scopes that can be used to make
+ authorized requests to Gaia endpoints.
+- "The accounts with refresh tokens" refer to the accounts that are visible to
+ IdentityManager with OAuth2 refresh tokens present (e.g., because the user has
+ signed in to the browser and embedder-level code then added the account to
+ IdentityManager, or because the user has added an account at the
+ system level that embedder-level code then made visible to IdentityManager).
+ To interact with these accounts, use the IdentityManager methods with
+ "RefreshToken" in their name. To observe changes in the state of one or more
+ of these accounts, observe IdentityManager and override one or more of the
+ IdentityManager::Observer methods with "RefreshToken" in their name.
- AccessTokenFetcher is the client-side interface for obtaining access tokens
- for arbitrary accounts.
+ for arbitrary accounts; see access_token_fetcher.h for usage explanation and
+ examples.
+
+# The Gaia Cookie
+- "The Gaia cookie" refers to the cookie that contains the information of the
+ user's Gaia accounts that are available on the web.
+- "The accounts in the Gaia cookie" and "the accounts in the cookie jar" refer to
+ the set of accounts in this cookie. To interact with these accounts, use the
+ IdentityManager methods with "Cookie" in their name. To observe changes in the
+ state of one or more of these accounts, observe IdentityManager and override
+ one or more of the IdentityManager::Observer methods with "Cookie" in their
+ name. Note that as the information that Chrome has about these accounts is
+ fundamentally different than that which Chrome has about the user's accounts
+ with OAuth2 refresh tokens, the struct encoding this information is also
+ distinct: see accounts_in_cookie_jar_info.h.
+
+# Interacting with IdentityManager and Friends in Tests
- IdentityTestEnvironment is the preferred test infrastructure for unittests
of production code that interacts with IdentityManager. It is suitable for
use in cases where neither the production code nor the unittest is interacting
- with Profile (e.g., //components-level unittests).
+ with Profile.
- identity_test_utils.h provides lower-level test facilities for interacting
- explicitly with IdentityManager and its dependencies (PrimaryAccountManager,
- ProfileOAuth2TokenService). These facilities are the way to interact with
- IdentityManager in unittest contexts where the production code and/or the
+ explicitly with IdentityManager. These facilities are the way to interact with
+ IdentityManager in testing contexts where the production code and/or the
unittest are interacting with Profile (in particular, where the
IdentityManager instance with which the test is interacting must be
- IdentityManagerFactory::GetForProfile(profile)).
+ IdentityManagerFactory::GetForProfile(profile)). Examples include integration
+ tests and Profile-based unittests (in the latter case, consider migrating the
+ test and production code away from using Profile directly and using
+ IdentityTestEnvironment).
+
+# Mutation of Account State
+- Various mutators of account state are available through IdentityManager (e.g.,
+ PrimaryAccountMutator). These should in general be used only as part of larger
+ embedder-specific flows for mutating the user's account state in ways that are
+ in line with product specifications. If you are a consumer of
+ //components/identity/public/identity_manager and you believe that you have a
+ new use case for one of these API surfaces, you should first contact the
+ OWNERS of //components/signin to discuss this use case and how best to realize
+ it.
+
+# Mental Mapping from Chromium's Historical API Surfaces for Signin
+Documentation on the mapping between usage of legacy signin
+classes (notably PrimaryAccountManager and ProfileOAuth2TokenService) and usage
+of IdentityManager is available here:
+
+https://docs.google.com/document/d/14f3qqkDM9IE4Ff_l6wuXvCMeHfSC9TxKezXTCyeaPUY/edit#
diff --git a/chromium/components/signin/public/identity_manager/access_token_fetcher.cc b/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
index 200770b2a40..df7671a2efb 100644
--- a/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/logging.h"
-#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -82,8 +81,7 @@ AccessTokenFetcher::AccessTokenFetcher(
url_loader_factory_(std::move(url_loader_factory)),
scopes_(scopes),
mode_(mode),
- callback_(std::move(callback)),
- token_service_observer_(this) {
+ callback_(std::move(callback)) {
DCHECK(client_id_.empty() == client_secret_.empty());
DCHECK(client_id_.empty() || !url_loader_factory);
diff --git a/chromium/components/signin/public/identity_manager/access_token_fetcher.h b/chromium/components/signin/public/identity_manager/access_token_fetcher.h
index 0ee97625939..2f588f41488 100644
--- a/chromium/components/signin/public/identity_manager/access_token_fetcher.h
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher.h
@@ -12,9 +12,10 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/scoped_observer.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/oauth2_access_token_manager.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "services/identity/public/cpp/scope_set.h"
namespace network {
@@ -22,15 +23,121 @@ class SharedURLLoaderFactory;
}
class GoogleServiceAuthError;
-class ProfileOAuth2TokenService;
namespace signin {
struct AccessTokenInfo;
-// Helper class to ease the task of obtaining an OAuth2 access token for a
-// given account.
-// May only be used on the UI thread.
-class AccessTokenFetcher : public OAuth2TokenServiceObserver,
+// Class that supports obtaining OAuth2 access tokens for any of the user's
+// accounts with OAuth2 refresh tokens. Note that in the common case of
+// obtaining an OAuth2 access token for the user's primary account, use
+// PrimaryAccountAccessTokenFetcher rather than this class. See ./README.md
+// for the definition of "accounts with OAuth2 refresh tokens" and "primary
+// account".
+//
+// The usage model of this class is as follows: When an AccessTokenFetcher is
+// created via IdentityManager::CreateAccessTokenFetcherXXX(), the returned
+// object is owned by the caller. This object will make at most one access
+// token request for the specified account (either immediately or if/once a
+// refresh token for the specified account becomes available, based on the
+// value of the specified |Mode| parameter). When the access token request is
+// fulfilled the AccessTokenFetcher will call the specified callback, at which
+// point it is safe for the caller to destroy the object. If the object is
+// destroyed before the request is fulfilled the request is dropped and the
+// callback will never be invoked. This class may only be used on the UI
+// thread.
+//
+// To drive responses to access token fetches in unittests of clients of this
+// class, use IdentityTestEnvironment.
+//
+// Concrete usage example (related concrete test example follows):
+// class MyClass {
+// public:
+// MyClass(IdentityManager* identity_manager, account_id) :
+// identity_manager_(identity_manager) {
+// // An access token request could also be initiated at any arbitrary
+// // point in the lifetime of |MyClass|.
+// StartAccessTokenRequestForAccount(account_id);
+// }
+//
+//
+// ~MyClass() {
+// // If the access token request is still live, the destruction of
+// |access_token_fetcher_| will cause it to be dropped.
+// }
+//
+// private:
+// IdentityManager* identity_manager_;
+// std::unique_ptr<AccessTokenFetcher> access_token_fetcher_;
+// std::string access_token_;
+// GoogleServiceAuthError access_token_request_error_;
+//
+// // Most commonly invoked as part of some larger flow to hit a Gaia
+// // endpoint for a client-specific purpose (e.g., hitting sync
+// // endpoints).
+// // Could also be public, but in general, any clients that would need to
+// // create access token requests could and should just create
+// // AccessTokenFetchers directly themselves rather than introducing
+// // wrapper API surfaces.
+// MyClass::StartAccessTokenRequestForAccount(CoreAccountId account_id) {
+// // Choose scopes to obtain for the access token.
+// identity::ScopeSet scopes;
+// scopes.insert(GaiaConstants::kMyFirstScope);
+// scopes.insert(GaiaConstants::kMySecondScope);
+
+// // Choose the mode in which to fetch the access token:
+// // see AccessTokenFetcher::Mode below for definitions.
+// auto mode = signin::AccessTokenFetcher::Mode::kImmediate;
+
+// // Create the fetcher via |identity_manager_|.
+// access_token_fetcher_ =
+// identity_manager_->CreateAccessTokenFetcherForAccount(
+// account_id, /*consumer_name=*/"MyClass",
+// scopes,
+// base::BindOnce(&MyClass::OnAccessTokenRequestCompleted,
+// // It is safe to use base::Unretained as
+// // |this| owns |access_token_fetcher_|.
+// base::Unretained(this)),
+// mode);
+//
+// }
+// MyClass::OnAccessTokenRequestCompleted(
+// GoogleServiceAuthError error, AccessTokenInfo access_token_info) {
+// // It is safe to destroy |access_token_fetcher_| from this callback.
+// access_token_fetcher_.reset();
+//
+// if (error.state() == GoogleServiceAuthError::NONE) {
+// // The fetcher successfully obtained an access token.
+// access_token_ = access_token_info.token;
+// // MyClass can now take whatever action required having an access
+// // token (e.g.,hitting a given Gaia endpoint).
+// ...
+// } else {
+// // The fetcher failed to obtain a token; |error| specifies why.
+// access_token_request_error_ = error;
+// // MyClass can now perform any desired error handling.
+// ...
+// }
+// }
+// }
+//
+// Concrete test example:
+// TEST(MyClassTest, SuccessfulAccessTokenFetch) {
+// IdentityTestEnvironment identity_test_env;
+// AccountInfo account_info =
+// identity_test_env.MakeAccountAvailable("test_email");
+//
+// MyClass my_class(identity_test_env.identity_manager(),
+// account_info.account_id);
+// identity_test_env.
+// WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+// "access_token", base::Time::Max());
+//
+// // MyClass::OnAccessTokenRequestCompleted() will have been invoked with
+// // an AccessTokenInfo object containing the above-specified parameters;
+// // the test can now perform any desired validation of expected actions
+// // |MyClass| took in response.
+// }
+class AccessTokenFetcher : public ProfileOAuth2TokenServiceObserver,
public OAuth2AccessTokenManager::Consumer {
public:
// Specifies how this instance should behave:
@@ -108,7 +215,7 @@ class AccessTokenFetcher : public OAuth2TokenServiceObserver,
void StartAccessTokenRequest();
- // OAuth2TokenServiceObserver implementation.
+ // ProfileOAuth2TokenServiceObserver implementation.
void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
// OAuth2AccessTokenManager::Consumer implementation.
@@ -138,8 +245,8 @@ class AccessTokenFetcher : public OAuth2TokenServiceObserver,
// contract.
TokenCallback callback_;
- ScopedObserver<ProfileOAuth2TokenService, AccessTokenFetcher>
- token_service_observer_;
+ ScopedObserver<ProfileOAuth2TokenService, ProfileOAuth2TokenServiceObserver>
+ token_service_observer_{this};
std::unique_ptr<OAuth2AccessTokenManager::Request> access_token_request_;
diff --git a/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc b/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc
index 2de2b66224d..a9faaa187a6 100644
--- a/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
#include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h"
@@ -117,7 +117,7 @@ class AccessTokenFetcherTest
std::move(on_access_token_request_callback_).Run();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestingPrefServiceSyncable pref_service_;
TestSigninClient signin_client_;
FakeProfileOAuth2TokenService token_service_;
diff --git a/chromium/components/signin/public/identity_manager/account_info.cc b/chromium/components/signin/public/identity_manager/account_info.cc
index afe459f9f91..9435008860a 100644
--- a/chromium/components/signin/public/identity_manager/account_info.cc
+++ b/chromium/components/signin/public/identity_manager/account_info.cc
@@ -5,6 +5,11 @@
#include "components/signin/public/identity_manager/account_info.h"
#include "google_apis/gaia/gaia_auth_util.h"
+#if defined(OS_ANDROID)
+#include "base/android/jni_string.h"
+#include "components/signin/internal/identity_manager/android/jni_headers/CoreAccountInfo_jni.h"
+#endif
+
namespace {
// Updates |field| with |new_value| if non-empty and different; if |new_value|
@@ -119,3 +124,16 @@ std::ostream& operator<<(std::ostream& os, const CoreAccountInfo& account) {
<< account.is_under_advanced_protection;
return os;
}
+
+#if defined(OS_ANDROID)
+base::android::ScopedJavaLocalRef<jobject> ConvertToJavaCoreAccountInfo(
+ const CoreAccountInfo& account_info) {
+ if (account_info.IsEmpty())
+ return base::android::ScopedJavaLocalRef<jobject>();
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return signin::Java_CoreAccountInfo_Constructor(
+ env,
+ base::android::ConvertUTF8ToJavaString(env, account_info.account_id.id),
+ base::android::ConvertUTF8ToJavaString(env, account_info.email));
+}
+#endif
diff --git a/chromium/components/signin/public/identity_manager/account_info.h b/chromium/components/signin/public/identity_manager/account_info.h
index e8d5a61a74e..c5b0359e032 100644
--- a/chromium/components/signin/public/identity_manager/account_info.h
+++ b/chromium/components/signin/public/identity_manager/account_info.h
@@ -7,9 +7,14 @@
#include <string>
+#include "build/build_config.h"
#include "google_apis/gaia/core_account_id.h"
#include "ui/gfx/image/image.h"
+#if defined(OS_ANDROID)
+#include "base/android/scoped_java_ref.h"
+#endif
+
// Value representing no hosted domain associated with an account.
extern const char kNoHostedDomainFound[];
@@ -74,4 +79,10 @@ bool operator==(const CoreAccountInfo& l, const CoreAccountInfo& r);
bool operator!=(const CoreAccountInfo& l, const CoreAccountInfo& r);
std::ostream& operator<<(std::ostream& os, const CoreAccountInfo& account);
+#if defined(OS_ANDROID)
+// Constructs a Java CoreAccountInfo from the provided C++ CoreAccountInfo
+base::android::ScopedJavaLocalRef<jobject> ConvertToJavaCoreAccountInfo(
+ const CoreAccountInfo& account_info);
+#endif
+
#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_ACCOUNT_INFO_H_
diff --git a/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
index add100d356e..57be5bdc05f 100644
--- a/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc
@@ -11,7 +11,7 @@
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/gtest_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/base/list_accounts_test_utils.h"
#include "components/signin/public/base/test_signin_client.h"
#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
@@ -137,7 +137,7 @@ class AccountsCookieMutatorTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
TestSigninClient test_signin_client_;
IdentityTestEnvironment identity_test_env_;
diff --git a/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc b/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
index 98669f6dc8c..47769f98beb 100644
--- a/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/optional.h"
#include "base/test/gtest_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/base/device_id_helper.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/identity_manager/identity_manager.h"
@@ -110,7 +110,7 @@ class AccountsMutatorTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
network::TestURLLoaderFactory test_url_loader_factory_;
IdentityTestEnvironment identity_test_env_;
@@ -148,7 +148,8 @@ TEST_F(AccountsMutatorTest, AddOrUpdateAccount_AddNewAccount) {
AccountInfo account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
EXPECT_EQ(account_info.account_id, account_id);
EXPECT_EQ(account_info.email, kTestEmail);
@@ -180,7 +181,8 @@ TEST_F(AccountsMutatorTest, AddOrUpdateAccount_UpdateExistingAccount) {
account_id));
AccountInfo account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
EXPECT_EQ(account_info.account_id, account_id);
EXPECT_EQ(account_info.email, kTestEmail);
@@ -218,7 +220,8 @@ TEST_F(AccountsMutatorTest, AddOrUpdateAccount_UpdateExistingAccount) {
EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 1U);
AccountInfo updated_account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
EXPECT_EQ(account_info.account_id, updated_account_info.account_id);
EXPECT_EQ(account_info.gaia, updated_account_info.gaia);
@@ -252,7 +255,8 @@ TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
AccountInfo original_account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
EXPECT_EQ(original_account_info.account_id, account_id);
EXPECT_EQ(original_account_info.email, kTestEmail);
@@ -265,7 +269,8 @@ TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
/*is_under_advanced_protection=*/base::nullopt);
AccountInfo updated_account_info_1 =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
// Only |is_child_account| changed so far, everything else remains the same.
@@ -283,7 +288,8 @@ TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
/*is_under_advanced_protection=*/true);
AccountInfo updated_account_info_2 =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
// |is_under_advanced_protection| has changed now, but |is_child_account|
@@ -303,7 +309,8 @@ TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
/*is_under_advanced_protection=*/false);
AccountInfo reset_account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
// Everything is back to its original state now.
@@ -377,7 +384,8 @@ TEST_F(
AccountInfo secondary_account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByAccountId(account_id)
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_id)
.value();
EXPECT_EQ(identity_manager()->GetAccountsWithRefreshTokens().size(), 2U);
@@ -617,9 +625,10 @@ TEST_F(AccountsMutatorTest, LegacySetRefreshTokenForSupervisedUser) {
// In the context of supervised users, the ProfileOAuth2TokenService is used
// without the AccountTrackerService being used, so we can't use any of the
- // IdentityManager::FindAccountInfoForAccountWithRefreshTokenBy*() methods
- // since they won't find any account. Use GetAccountsWithRefreshTokens() and
- // HasAccountWithRefreshToken*() instead, that only relies in the PO2TS.
+ // IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenBy*()
+ // methods since they won't find any account. Use
+ // GetAccountsWithRefreshTokens() and HasAccountWithRefreshToken*() instead,
+ // that only relies in the PO2TS.
std::vector<CoreAccountInfo> accounts =
identity_manager()->GetAccountsWithRefreshTokens();
EXPECT_EQ(accounts.size(), 1U);
diff --git a/chromium/components/signin/public/identity_manager/android/BUILD.gn b/chromium/components/signin/public/identity_manager/android/BUILD.gn
new file mode 100644
index 00000000000..6d96dc4ddf8
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/android/BUILD.gn
@@ -0,0 +1,19 @@
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ deps = [
+ "//base:base_java",
+ "//base:jni_java",
+ "//components/signin/core/browser/android:java",
+ "//third_party/android_deps:android_support_v4_java",
+ "//third_party/android_deps:com_android_support_support_annotations_java",
+ ]
+
+ java_files = [
+ "java/src/org/chromium/components/signin/identitymanager/IdentityManager.java",
+ "java/src/org/chromium/components/signin/identitymanager/CoreAccountId.java",
+ "java/src/org/chromium/components/signin/identitymanager/CoreAccountInfo.java",
+ ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
diff --git a/chromium/components/signin/public/identity_manager/android/DEPS b/chromium/components/signin/public/identity_manager/android/DEPS
new file mode 100644
index 00000000000..d803ba10f5f
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/android/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ "CoreAccountInfo.java": [
+ "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java"
+ ],
+}
diff --git a/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountId.java b/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountId.java
new file mode 100644
index 00000000000..e690e4abca6
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountId.java
@@ -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.
+
+package org.chromium.components.signin.identitymanager;
+
+import android.support.annotation.NonNull;
+
+/**
+ * A wrapper around Gaia ID that represents a stable account identifier.
+ *
+ * This wrapper helps to make sure that code using accounts doesn't accidentally use account name in
+ * place of Gaia ID and vice versa.
+ *
+ * This class has a native counterpart called CoreAccountId.
+ */
+public class CoreAccountId {
+ private final String mGaiaId;
+
+ /**
+ * Constructs a new CoreAccountId from a String representation of Gaia ID.
+ */
+ public CoreAccountId(@NonNull String gaiaId) {
+ assert gaiaId != null;
+ // Check that a user email is not used by mistake.
+ assert !gaiaId.contains("@");
+
+ mGaiaId = gaiaId;
+ }
+
+ public String getGaiaIdAsString() {
+ return mGaiaId;
+ }
+
+ @Override
+ public String toString() {
+ return mGaiaId;
+ }
+
+ @Override
+ public int hashCode() {
+ return mGaiaId.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CoreAccountId)) return false;
+ CoreAccountId other = (CoreAccountId) obj;
+ return mGaiaId.equals(other.mGaiaId);
+ }
+}
diff --git a/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountInfo.java b/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountInfo.java
new file mode 100644
index 00000000000..cbb28e2f244
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/CoreAccountInfo.java
@@ -0,0 +1,84 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.signin.identitymanager;
+
+import android.accounts.Account;
+import android.support.annotation.NonNull;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.components.signin.AccountManagerFacade;
+
+/**
+ * Structure storing the core information about a Google account that is always known. The {@link
+ * CoreAccountInfo} for a given user is almost always the same but it may change in some rare cases.
+ * For example, the {@link android.accounts.Account} will change if a user changes email.
+ *
+ * This class has a native counterpart called CoreAccountInfo. There are several differences between
+ * these two classes:
+ * - Android class doesn't store Gaia ID as a string because {@link CoreAccountId} already contains
+ * it.
+ * - Android class additionally exposes {@link android.accounts.Account} object for interactions
+ * with the system.
+ * - Android class has the "account name" whereas the native class has "email". This is the same
+ * string, only the naming in different.
+ */
+public class CoreAccountInfo {
+ private final CoreAccountId mId;
+ private final Account mAccount;
+
+ public CoreAccountInfo(@NonNull CoreAccountId id, @NonNull Account account) {
+ assert id != null;
+ assert account != null;
+
+ mId = id;
+ mAccount = account;
+ }
+
+ @CalledByNative
+ private CoreAccountInfo(@NonNull String id, @NonNull String name) {
+ assert id != null;
+ assert name != null;
+ mAccount = AccountManagerFacade.createAccountFromName(name);
+ mId = new CoreAccountId(id);
+ }
+
+ /**
+ * Returns a unique identifier of the current account.
+ */
+ public CoreAccountId getId() {
+ return mId;
+ }
+
+ /**
+ * Returns a name of the current account.
+ */
+ public String getName() {
+ return mAccount.name;
+ }
+
+ /**
+ * Returns {@link android.accounts.Account} object holding a name of the current account.
+ */
+ public Account getAccount() {
+ return mAccount;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("CoreAccountInfo{id[%s], name[%s]}", getId(), getName());
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * mId.hashCode() + mAccount.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CoreAccountInfo)) return false;
+ CoreAccountInfo other = (CoreAccountInfo) obj;
+ return mId.equals(other.mId) && mAccount.equals(other.mAccount);
+ }
+}
diff --git a/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java b/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java
new file mode 100644
index 00000000000..29ab16b5284
--- /dev/null
+++ b/chromium/components/signin/public/identity_manager/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.signin.identitymanager;
+
+import org.chromium.base.ObserverList;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.NativeMethods;
+
+/**
+ * IdentityManager provides access to native IdentityManager's public API to java components.
+ */
+public class IdentityManager {
+ private static final String TAG = "IdentityManager";
+
+ /**
+ * IdentityManager.Observer is notified when the available account information are updated. This
+ * is a subset of native's IdentityManager::Observer.
+ */
+ public interface Observer {
+ /**
+ * Called when an account becomes the user's primary account.
+ * This method is not called during a reauth.
+ */
+ void onPrimaryAccountSet(CoreAccountInfo account);
+
+ /**
+ * Called when the user moves from having a primary account to no longer having a primary
+ * account (note that the user may still have an *unconsented* primary account after this
+ * event).
+ */
+ void onPrimaryAccountCleared(CoreAccountInfo account);
+ }
+
+ private long mNativeIdentityManager;
+
+ private final ObserverList<Observer> mObservers = new ObserverList<>();
+
+ /**
+ * Called by native to create an instance of IdentityManager.
+ */
+ @CalledByNative
+ static private IdentityManager create(long nativeIdentityManager) {
+ return new IdentityManager(nativeIdentityManager);
+ }
+ private IdentityManager(long nativeIdentityManager) {
+ assert nativeIdentityManager != 0;
+
+ mNativeIdentityManager = nativeIdentityManager;
+ }
+
+ /**
+ * Called by native upon KeyedService's shutdown
+ */
+ @CalledByNative
+ private void destroy() {
+ mNativeIdentityManager = 0;
+ }
+
+ /**
+ * Registers a IdentityManager.Observer
+ */
+ public void addObserver(Observer observer) {
+ mObservers.addObserver(observer);
+ }
+
+ /**
+ * Unregisters a IdentityManager.Observer
+ */
+ public void removeObserver(Observer observer) {
+ mObservers.removeObserver(observer);
+ }
+
+ /**
+ * Notifies observers that the primary account was set in C++.
+ */
+ @CalledByNative
+ private void onPrimaryAccountSet(CoreAccountInfo account) {
+ for (Observer observer : mObservers) {
+ observer.onPrimaryAccountSet(account);
+ }
+ }
+
+ /**
+ * Notifies observers that the primary account was cleared in C++.
+ */
+ @CalledByNative
+ private void onPrimaryAccountCleared(CoreAccountInfo account) {
+ for (Observer observer : mObservers) {
+ observer.onPrimaryAccountCleared(account);
+ }
+ }
+
+ /**
+ * Returns whether the user's primary account is available.
+ */
+ boolean hasPrimaryAccount() {
+ return IdentityManagerJni.get().hasPrimaryAccount(mNativeIdentityManager);
+ }
+
+ @NativeMethods
+ interface Natives {
+ public boolean hasPrimaryAccount(long nativeIdentityManager);
+ }
+}
diff --git a/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc b/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc
index 87fb50f9310..64b1fce2fa3 100644
--- a/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/diagnostics_provider_unittest.cc
@@ -6,7 +6,7 @@
#include "base/bind_helpers.h"
#include "base/macros.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/signin/public/identity_manager/load_credentials_state.h"
@@ -29,7 +29,7 @@ class DiagnosticsProviderTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
private:
signin::IdentityTestEnvironment identity_test_env_;
diff --git a/chromium/components/signin/public/identity_manager/identity_manager.cc b/chromium/components/signin/public/identity_manager/identity_manager.cc
index de180ab04ae..79bee2b42b7 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager.cc
+++ b/chromium/components/signin/public/identity_manager/identity_manager.cc
@@ -23,6 +23,8 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#if defined(OS_ANDROID)
+#include "base/android/jni_string.h"
+#include "components/signin/internal/identity_manager/android/jni_headers/IdentityManager_jni.h"
#include "components/signin/internal/identity_manager/oauth2_token_service_delegate_android.h"
#elif !defined(OS_IOS)
#include "components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.h"
@@ -121,6 +123,11 @@ IdentityManager::IdentityManager(
DCHECK(!account.account_id.empty());
SetPrimaryAccountInternal(std::move(account));
}
+
+#if defined(OS_ANDROID)
+ java_identity_manager_ = Java_IdentityManager_create(
+ base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this));
+#endif
}
IdentityManager::~IdentityManager() {
@@ -131,6 +138,12 @@ IdentityManager::~IdentityManager() {
token_service_->RemoveObserver(this);
token_service_->RemoveAccessTokenDiagnosticsObserver(this);
+
+#if defined(OS_ANDROID)
+ if (java_identity_manager_)
+ Java_IdentityManager_destroy(base::android::AttachCurrentThread(),
+ java_identity_manager_);
+#endif
}
void IdentityManager::AddObserver(Observer* observer) {
@@ -281,7 +294,8 @@ GoogleServiceAuthError IdentityManager::GetErrorStateOfRefreshTokenForAccount(
return token_service_->GetAuthError(account_id);
}
-base::Optional<AccountInfo> IdentityManager::FindExtendedAccountInfoForAccount(
+base::Optional<AccountInfo>
+IdentityManager::FindExtendedAccountInfoForAccountWithRefreshToken(
const CoreAccountInfo& account_info) const {
AccountInfo extended_account_info =
account_tracker_service_->GetAccountInfo(account_info.account_id);
@@ -296,7 +310,7 @@ base::Optional<AccountInfo> IdentityManager::FindExtendedAccountInfoForAccount(
}
base::Optional<AccountInfo>
-IdentityManager::FindAccountInfoForAccountWithRefreshTokenByAccountId(
+IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
const CoreAccountId& account_id) const {
AccountInfo account_info =
account_tracker_service_->GetAccountInfo(account_id);
@@ -310,9 +324,9 @@ IdentityManager::FindAccountInfoForAccountWithRefreshTokenByAccountId(
return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
}
-base::Optional<AccountInfo>
-IdentityManager::FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
- const std::string& email_address) const {
+base::Optional<AccountInfo> IdentityManager::
+ FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ const std::string& email_address) const {
AccountInfo account_info =
account_tracker_service_->FindAccountInfoByEmail(email_address);
@@ -326,7 +340,7 @@ IdentityManager::FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
}
base::Optional<AccountInfo>
-IdentityManager::FindAccountInfoForAccountWithRefreshTokenByGaiaId(
+IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
const std::string& gaia_id) const {
AccountInfo account_info =
account_tracker_service_->FindAccountInfoByGaiaId(gaia_id);
@@ -391,9 +405,19 @@ void IdentityManager::OnNetworkInitialized() {
account_fetcher_service_->OnNetworkInitialized();
}
-// static
-bool IdentityManager::IsAccountIdMigrationSupported() {
- return AccountTrackerService::IsMigrationSupported();
+IdentityManager::AccountIdMigrationState
+IdentityManager::GetAccountIdMigrationState() const {
+ return static_cast<IdentityManager::AccountIdMigrationState>(
+ account_tracker_service_->GetMigrationState());
+}
+
+CoreAccountId IdentityManager::PickAccountIdForAccount(
+ const std::string& gaia,
+ const std::string& email) const {
+ // TODO(triploblastic@): Remove explicit conversion once
+ // primary_account_manager has been fixed to use CoreAccountId.
+ return CoreAccountId(
+ account_tracker_service_->PickAccountIdForAccount(gaia, email));
}
// static
@@ -407,26 +431,12 @@ void IdentityManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
PrimaryAccountManager::RegisterProfilePrefs(registry);
AccountFetcherService::RegisterPrefs(registry);
AccountTrackerService::RegisterPrefs(registry);
+ GaiaCookieManagerService::RegisterPrefs(registry);
#if !defined(OS_ANDROID) && !defined(OS_IOS)
MutableProfileOAuth2TokenServiceDelegate::RegisterProfilePrefs(registry);
#endif
}
-CoreAccountId IdentityManager::PickAccountIdForAccount(
- const std::string& gaia,
- const std::string& email) const {
- // TODO(triploblastic@): Remove explicit conversion once
- // primary_account_manager has been fixed to use CoreAccountId.
- return CoreAccountId(
- account_tracker_service_->PickAccountIdForAccount(gaia, email));
-}
-
-IdentityManager::AccountIdMigrationState
-IdentityManager::GetAccountIdMigrationState() const {
- return static_cast<IdentityManager::AccountIdMigrationState>(
- account_tracker_service_->GetMigrationState());
-}
-
#if !defined(OS_IOS) && !defined(OS_ANDROID)
void IdentityManager::DeprecatedLoadCredentialsForSupervisedUser(
const CoreAccountId& primary_account_id) {
@@ -463,11 +473,20 @@ IdentityManager::LegacyGetOAuth2TokenServiceJavaObject() {
return delegate->GetJavaObject();
}
+base::android::ScopedJavaLocalRef<jobject> IdentityManager::GetJavaObject() {
+ DCHECK(java_identity_manager_);
+ return base::android::ScopedJavaLocalRef<jobject>(java_identity_manager_);
+}
+
void IdentityManager::ForceRefreshOfExtendedAccountInfo(
const CoreAccountId& account_id) {
DCHECK(HasAccountWithRefreshToken(account_id));
account_fetcher_service_->ForceRefreshOfAccountInfo(account_id);
}
+
+bool IdentityManager::HasPrimaryAccount(JNIEnv* env) const {
+ return HasPrimaryAccount();
+}
#endif
PrimaryAccountManager* IdentityManager::GetPrimaryAccountManager() {
@@ -569,6 +588,12 @@ void IdentityManager::GoogleSigninSucceeded(const AccountInfo& account_info) {
for (auto& observer : observer_list_) {
observer.OnPrimaryAccountSet(account_info);
}
+#if defined(OS_ANDROID)
+ if (java_identity_manager_)
+ Java_IdentityManager_onPrimaryAccountSet(
+ base::android::AttachCurrentThread(), java_identity_manager_,
+ ConvertToJavaCoreAccountInfo(account_info));
+#endif
}
void IdentityManager::GoogleSignedOut(const AccountInfo& account_info) {
@@ -576,6 +601,12 @@ void IdentityManager::GoogleSignedOut(const AccountInfo& account_info) {
for (auto& observer : observer_list_) {
observer.OnPrimaryAccountCleared(account_info);
}
+#if defined(OS_ANDROID)
+ if (java_identity_manager_)
+ Java_IdentityManager_onPrimaryAccountCleared(
+ base::android::AttachCurrentThread(), java_identity_manager_,
+ ConvertToJavaCoreAccountInfo(account_info));
+#endif
}
void IdentityManager::AuthenticatedAccountSet(const AccountInfo& account_info) {
DCHECK(primary_account_manager_->IsAuthenticated());
diff --git a/chromium/components/signin/public/identity_manager/identity_manager.h b/chromium/components/signin/public/identity_manager/identity_manager.h
index 00ad7000e59..66aa6cc9574 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager.h
+++ b/chromium/components/signin/public/identity_manager/identity_manager.h
@@ -12,11 +12,11 @@
#include "base/observer_list.h"
#include "build/build_config.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/ubertoken_fetcher.h"
#include "google_apis/gaia/oauth2_access_token_manager.h"
-#include "google_apis/gaia/oauth2_token_service_observer.h"
#include "services/identity/public/cpp/scope_set.h"
#if defined(OS_ANDROID)
@@ -33,9 +33,7 @@ class SharedURLLoaderFactory;
class TestURLLoaderFactory;
} // namespace network
-// Necessary to declare these classes as friends.
class PrefRegistrySimple;
-class SigninManagerAndroid;
class AccountFetcherService;
class AccountTrackerService;
@@ -60,7 +58,7 @@ struct CookieParamsForTest;
// ./README.md for detailed documentation.
class IdentityManager : public KeyedService,
public OAuth2AccessTokenManager::DiagnosticsObserver,
- public OAuth2TokenServiceObserver {
+ public ProfileOAuth2TokenServiceObserver {
public:
class Observer {
public:
@@ -265,7 +263,7 @@ class IdentityManager : public KeyedService,
// Returns extended information for account identified by |account_info|.
// The information will be returned if the information is available and
// refresh token is available for account.
- base::Optional<AccountInfo> FindExtendedAccountInfoForAccount(
+ base::Optional<AccountInfo> FindExtendedAccountInfoForAccountWithRefreshToken(
const CoreAccountInfo& account_info) const;
// Looks up and returns information for account with given |account_id|. If
@@ -273,7 +271,7 @@ class IdentityManager : public KeyedService,
// to searching on the vector returned by GetAccountsWithRefreshTokens() but
// without allocating memory for the vector.
base::Optional<AccountInfo>
- FindAccountInfoForAccountWithRefreshTokenByAccountId(
+ FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
const CoreAccountId& account_id) const;
// Looks up and returns information for account with given |email_address|. If
@@ -281,14 +279,15 @@ class IdentityManager : public KeyedService,
// to searching on the vector returned by GetAccountsWithRefreshTokens() but
// without allocating memory for the vector.
base::Optional<AccountInfo>
- FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
const std::string& email_address) const;
// Looks up and returns information for account with given |gaia_id|. If the
// account cannot be found, return an empty optional. This is equivalent to
// searching on the vector returned by GetAccountsWithRefreshTokens() but
// without allocating memory for the vector.
- base::Optional<AccountInfo> FindAccountInfoForAccountWithRefreshTokenByGaiaId(
+ base::Optional<AccountInfo>
+ FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
const std::string& gaia_id) const;
// Creates an UbertokenFetcher given the passed-in information, allowing
@@ -393,22 +392,10 @@ class IdentityManager : public KeyedService,
// initialized.
void OnNetworkInitialized();
- // Returns |true| if migration of the account ID from normalized email is
- // supported for the current platform.
- static bool IsAccountIdMigrationSupported();
-
- // Registers per-install prefs used by this class.
- static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
-
- // Registers per-profile prefs used by this class.
- static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
- // Picks the correct account_id for the specified account depending on the
- // migration state.
- // TODO(https://crbug.com/883272): Remove once all platform have migrated to
- // the new account_id based on gaia (currently, only Chrome OS remains).
- CoreAccountId PickAccountIdForAccount(const std::string& gaia,
- const std::string& email) const;
+ // Methods related to migration of account IDs from email to Gaia ID.
+ // TODO(https://crbug.com/883272): Remove these once all platforms have
+ // migrated to the new account_id based on gaia (currently, only ChromeOS
+ // remains).
// Possible values for the account ID migration state, needs to be kept in
// sync with AccountTrackerService::AccountIdMigrationState.
@@ -419,9 +406,21 @@ class IdentityManager : public KeyedService,
NUM_MIGRATION_STATES
};
- // Returns the currently saved state for the migration of accounts IDs.
+ // Returns the currently saved state of the migration of account IDs.
AccountIdMigrationState GetAccountIdMigrationState() const;
+ // Picks the correct account_id for the specified account depending on the
+ // migration state.
+ CoreAccountId PickAccountIdForAccount(const std::string& gaia,
+ const std::string& email) const;
+
+ // Methods used only by embedder-level factory classes.
+
+ // Registers per-install prefs used by this class.
+ static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+ // Registers per-profile prefs used by this class.
+ static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
#if !defined(OS_IOS) && !defined(OS_ANDROID)
// Explicitly triggers the loading of accounts in the context of supervised
// users.
@@ -450,7 +449,8 @@ class IdentityManager : public KeyedService,
// API calls ProfileOAuth2TokenServiceDelegate::ReloadAccountsFromSystem and
// it triggers platform specific implementation for Android. NOTE: In normal
// usage, this method SHOULD NOT be called.
- // TODO(https://crbug.com/930094): Eliminate the need to expose this.
+ // TODO(https://crbug.com/930094): Expose this through
+ // DeviceAccountsSynchronizer
void LegacyReloadAccountsFromSystem();
// Returns a pointer to the AccountTrackerService Java instance associated
@@ -467,11 +467,18 @@ class IdentityManager : public KeyedService,
base::android::ScopedJavaLocalRef<jobject>
LegacyGetOAuth2TokenServiceJavaObject();
+ // Get the reference on the java IdentityManager, InitializeJavaObject must
+ // be called before hand.
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
// This method has the contractual assumption that the account is a known
// account and has as its semantics that it fetches the account info for the
// account, triggering an OnExtendedAccountInfoUpdated() callback if the info
// was successfully fetched.
void ForceRefreshOfExtendedAccountInfo(const CoreAccountId& account_id);
+
+ // Overloads for calls from java:
+ bool HasPrimaryAccount(JNIEnv* env) const;
#endif
private:
@@ -498,13 +505,13 @@ class IdentityManager : public KeyedService,
const std::string& email,
const std::string& gaia_id);
friend void SetRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& token_value);
friend void SetInvalidRefreshTokenForAccount(
IdentityManager* identity_manager,
- const std::string& account_id);
+ const CoreAccountId& account_id);
friend void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id);
+ const CoreAccountId& account_id);
friend void UpdateAccountInfoForAccount(IdentityManager* identity_manager,
AccountInfo account_info);
friend void SetFreshnessOfAccountsInGaiaCookie(
@@ -512,7 +519,7 @@ class IdentityManager : public KeyedService,
bool accounts_are_fresh);
friend void UpdatePersistentErrorOfRefreshTokenForAccount(
IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error);
friend void DisableAccessTokenFetchRetries(IdentityManager* identity_manager);
@@ -527,7 +534,7 @@ class IdentityManager : public KeyedService,
friend void SimulateSuccessfulFetchOfAccountInfo(
IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& email,
const std::string& gaia,
const std::string& hosted_domain,
@@ -536,10 +543,6 @@ class IdentityManager : public KeyedService,
const std::string& locale,
const std::string& picture_url);
- // These friends are temporary during the conversion process.
- // TODO(https://crbug.com/889902): Delete this when conversion is done.
- friend SigninManagerAndroid;
-
// Temporary access to getters (e.g. GetTokenService()).
// TODO(https://crbug.com/944127): Remove this friendship by
// extending identity_test_utils.h as needed.
@@ -622,7 +625,7 @@ class IdentityManager : public KeyedService,
void AuthenticatedAccountSet(const AccountInfo& account_info);
void AuthenticatedAccountCleared();
- // OAuth2TokenServiceObserver:
+ // ProfileOAuth2TokenServiceObserver:
void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
void OnRefreshTokensLoaded() override;
@@ -695,6 +698,11 @@ class IdentityManager : public KeyedService,
base::Optional<CoreAccountInfo> primary_account_;
base::Optional<CoreAccountInfo> unconsented_primary_account_;
+#if defined(OS_ANDROID)
+ // Java-side IdentityManager object.
+ base::android::ScopedJavaGlobalRef<jobject> java_identity_manager_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(IdentityManager);
};
diff --git a/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc b/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
index 6b44b400350..ca1216e21b8 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -14,7 +14,7 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/image_fetcher/core/fake_image_decoder.h"
#include "components/signin/internal/identity_manager/account_fetcher_service.h"
@@ -403,7 +403,7 @@ class IdentityManagerTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
network::TestURLLoaderFactory test_url_loader_factory_;
TestSigninClient signin_client_;
@@ -2048,11 +2048,11 @@ TEST_F(IdentityManagerTest,
identity_manager_observer()->BatchChangeRecords().at(0).at(0));
}
-// Checks that FindAccountInfoForAccountWithRefreshTokenByAccountId() returns
-// information about the account if the account is found or nullopt if there
-// are no accounts with requested |account_id|.
+// Checks that FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId()
+// returns information about the account if the account is found or nullopt if
+// there are no accounts with requested |account_id|.
TEST_F(IdentityManagerTest,
- FindAccountInfoForAccountWithRefreshTokenByAccountId) {
+ FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId) {
// Add an account (note: cannot use kTestEmail as it is already inserted
// by the fixture common code, so use a different address).
const AccountInfo foo_account_info =
@@ -2060,24 +2060,26 @@ TEST_F(IdentityManagerTest,
base::Optional<AccountInfo> maybe_account_info;
maybe_account_info =
- identity_manager()->FindAccountInfoForAccountWithRefreshTokenByAccountId(
- "dummy_value");
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ "dummy_value");
EXPECT_FALSE(maybe_account_info.has_value());
maybe_account_info =
- identity_manager()->FindAccountInfoForAccountWithRefreshTokenByAccountId(
- foo_account_info.account_id);
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ foo_account_info.account_id);
EXPECT_TRUE(maybe_account_info.has_value());
EXPECT_EQ(foo_account_info.account_id, maybe_account_info.value().account_id);
EXPECT_EQ(foo_account_info.email, maybe_account_info.value().email);
EXPECT_EQ(foo_account_info.gaia, maybe_account_info.value().gaia);
}
-// Checks that FindAccountInfoForAccountWithRefreshTokenByEmailAddress() returns
-// information about the account if the account is found or nullopt if there
-// are no accounts with requested |email_address|.
+// Checks that FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress()
+// returns information about the account if the account is found or nullopt if
+// there are no accounts with requested |email_address|.
TEST_F(IdentityManagerTest,
- FindAccountInfoForAccountWithRefreshTokenByEmailAddress) {
+ FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress) {
// Add an account (note: cannot use kTestEmail as it is already inserted
// by the fixture common code, so use a different address).
const AccountInfo foo_account_info =
@@ -2086,13 +2088,13 @@ TEST_F(IdentityManagerTest,
base::Optional<AccountInfo> maybe_account_info;
maybe_account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
"dummy_value");
EXPECT_FALSE(maybe_account_info.has_value());
maybe_account_info =
identity_manager()
- ->FindAccountInfoForAccountWithRefreshTokenByEmailAddress(
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
foo_account_info.email);
EXPECT_TRUE(maybe_account_info.has_value());
EXPECT_EQ(foo_account_info.account_id, maybe_account_info.value().account_id);
@@ -2100,10 +2102,11 @@ TEST_F(IdentityManagerTest,
EXPECT_EQ(foo_account_info.gaia, maybe_account_info.value().gaia);
}
-// Checks that FindAccountInfoForAccountWithRefreshTokenByGaiaId() returns
-// information about the account if the account is found or nullopt if there
-// are no accounts with requested |gaia_id|.
-TEST_F(IdentityManagerTest, FindAccountInfoForAccountWithRefreshTokenByGaiaId) {
+// Checks that FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId()
+// returns information about the account if the account is found or nullopt if
+// there are no accounts with requested |gaia_id|.
+TEST_F(IdentityManagerTest,
+ FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId) {
// Add an account (note: cannot use kTestEmail as it is already inserted
// by the fixture common code, so use a different address).
const AccountInfo foo_account_info =
@@ -2111,13 +2114,15 @@ TEST_F(IdentityManagerTest, FindAccountInfoForAccountWithRefreshTokenByGaiaId) {
base::Optional<AccountInfo> maybe_account_info;
maybe_account_info =
- identity_manager()->FindAccountInfoForAccountWithRefreshTokenByGaiaId(
- "dummy_value");
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
+ "dummy_value");
EXPECT_FALSE(maybe_account_info.has_value());
maybe_account_info =
- identity_manager()->FindAccountInfoForAccountWithRefreshTokenByGaiaId(
- foo_account_info.gaia);
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
+ foo_account_info.gaia);
EXPECT_TRUE(maybe_account_info.has_value());
EXPECT_EQ(foo_account_info.account_id, maybe_account_info.value().account_id);
EXPECT_EQ(foo_account_info.email, maybe_account_info.value().email);
@@ -2144,7 +2149,7 @@ TEST_F(IdentityManagerTest, AreRefreshTokensLoaded) {
TEST_F(IdentityManagerTest, AccountIdMigration_DoneOnInitialization) {
// Migration gets marked as DONE while initializing the AccountTrackerService
// on platforms supporting account ID migration only.
- if (IdentityManager::IsAccountIdMigrationSupported()) {
+ if (account_tracker()->IsMigrationSupported()) {
EXPECT_EQ(identity_manager()->GetAccountIdMigrationState(),
IdentityManager::AccountIdMigrationState::MIGRATION_DONE);
} else {
@@ -2208,47 +2213,51 @@ TEST_F(IdentityManagerTest, TestPickAccountIdForAccount) {
}
}
-// Check that FindExtendedAccountInfoForAccount returns a valid account info
-// iff the account is known, has refresh token and all the extended information
-// is available.
-TEST_F(IdentityManagerTest, FindExtendedAccountInfoForAccount) {
+// Check that FindExtendedAccountInfoForAccountWithRefreshToken returns a valid
+// account info iff the account is known, has refresh token and all the extended
+// information is available.
+TEST_F(IdentityManagerTest, FindExtendedAccountInfoForAccountWithRefreshToken) {
CoreAccountInfo account_info;
account_info.email = kTestEmail;
account_info.gaia = kTestGaiaId;
account_info.account_id =
identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail);
- // FindExtendedAccountInfoForAccount() returns empty optional if the
- // account_info is invalid.
- EXPECT_FALSE(identity_manager()
- ->FindExtendedAccountInfoForAccount(CoreAccountInfo{})
- .has_value());
+ // FindExtendedAccountInfoForAccountWithRefreshToken() returns empty optional
+ // if the account_info is invalid.
+ EXPECT_FALSE(
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshToken(CoreAccountInfo{})
+ .has_value());
- // FindExtendedAccountInfoForAccount() returns empty optional if the
- // account_info is unknown.
- EXPECT_FALSE(identity_manager()
- ->FindExtendedAccountInfoForAccount(account_info)
- .has_value());
+ // FindExtendedAccountInfoForAccountWithRefreshToken() returns empty optional
+ // if the account_info is unknown.
+ EXPECT_FALSE(
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshToken(account_info)
+ .has_value());
// Insert the core account information in the AccountTrackerService.
const CoreAccountId account_id =
account_tracker()->SeedAccountInfo(kTestGaiaId, kTestEmail);
ASSERT_EQ(account_info.account_id, account_id);
- // FindExtendedAccountInfoForAccount() returns empty optional if the account
- // has no refresh token.
- EXPECT_FALSE(identity_manager()
- ->FindExtendedAccountInfoForAccount(account_info)
- .has_value());
+ // FindExtendedAccountInfoForAccountWithRefreshToken() returns empty optional
+ // if the account has no refresh token.
+ EXPECT_FALSE(
+ identity_manager()
+ ->FindExtendedAccountInfoForAccountWithRefreshToken(account_info)
+ .has_value());
// Insert refresh token for account.
SetRefreshTokenForAccount(identity_manager(), account_info.account_id,
"refresh-token");
- // FindExtendedAccountInfoForAccount() returns extended account information if
- // the account is known and has valid refresh token.
+ // FindExtendedAccountInfoForAccountWithRefreshToken() returns extended
+ // account information if the account is known and has valid refresh token.
const base::Optional<AccountInfo> extended_account_info =
- identity_manager()->FindExtendedAccountInfoForAccount(account_info);
+ identity_manager()->FindExtendedAccountInfoForAccountWithRefreshToken(
+ account_info);
ASSERT_TRUE(extended_account_info.has_value());
EXPECT_EQ(account_info.gaia, extended_account_info.value().gaia);
diff --git a/chromium/components/signin/public/identity_manager/identity_test_environment.cc b/chromium/components/signin/public/identity_manager/identity_test_environment.cc
index 6c033416f65..69068413873 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_environment.cc
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment.cc
@@ -127,7 +127,7 @@ void IdentityTestEnvironment::Initialize() {
"environment. "
"If your test has an existing one, move it to be initialized before "
"IdentityTestEnvironment. Otherwise, use "
- "base::test::ScopedTaskEnvironment.";
+ "base::test::TaskEnvironment.";
test_identity_manager_observer_ =
std::make_unique<TestIdentityManagerObserver>(this->identity_manager());
this->identity_manager()->AddDiagnosticsObserver(this);
@@ -461,7 +461,7 @@ void IdentityTestEnvironment::ResetToAccountsNotYetLoadedFromDiskState() {
}
void IdentityTestEnvironment::ReloadAccountsFromDisk() {
- fake_token_service()->LoadCredentials("");
+ fake_token_service()->LoadCredentials(CoreAccountId());
}
bool IdentityTestEnvironment::IsAccessTokenRequestPending() {
diff --git a/chromium/components/signin/public/identity_manager/identity_test_environment.h b/chromium/components/signin/public/identity_manager/identity_test_environment.h
index 3b5efc73fbf..ab6184e8b99 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_environment.h
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment.h
@@ -39,7 +39,7 @@ class TestIdentityManagerObserver;
// not available; call MakePrimaryAccountAvailable() as needed.
// NOTE: IdentityTestEnvironment requires that tests have a properly set up
// task environment. If your test doesn't already have one, use a
-// base::test::ScopedTaskEnvironment instance variable to fulfill this
+// base::test::TaskEnvironment instance variable to fulfill this
// requirement.
class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver {
public:
@@ -287,7 +287,7 @@ class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver {
kPending,
kAvailable,
} state;
- base::Optional<std::string> account_id;
+ base::Optional<CoreAccountId> account_id;
base::OnceClosure on_available;
};
diff --git a/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc b/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc
index 9c03209a972..d8441583a76 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment_unittest.cc
@@ -5,7 +5,7 @@
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "base/bind.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,17 +14,14 @@ namespace signin {
class IdentityTestEnvironmentTest : public testing::Test {
public:
IdentityTestEnvironmentTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT,
- base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
- QUEUED) {}
+ : task_environment_(
+ base::test::TaskEnvironment::MainThreadType::DEFAULT,
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
- ~IdentityTestEnvironmentTest() override {
- scoped_task_environment_.RunUntilIdle();
- }
+ ~IdentityTestEnvironmentTest() override { task_environment_.RunUntilIdle(); }
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironmentTest);
};
diff --git a/chromium/components/signin/public/identity_manager/identity_test_utils.cc b/chromium/components/signin/public/identity_manager/identity_test_utils.cc
index 1cbd39b19bf..bf0617f556c 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_utils.cc
+++ b/chromium/components/signin/public/identity_manager/identity_test_utils.cc
@@ -51,7 +51,7 @@ void UpdateRefreshTokenForAccount(
ProfileOAuth2TokenService* token_service,
AccountTrackerService* account_tracker_service,
IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& new_token) {
DCHECK_EQ(account_tracker_service->GetAccountInfo(account_id).account_id,
account_id)
@@ -106,14 +106,14 @@ CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
void SetRefreshTokenForPrimaryAccount(IdentityManager* identity_manager,
const std::string& token_value) {
DCHECK(identity_manager->HasPrimaryAccount());
- std::string account_id = identity_manager->GetPrimaryAccountId();
+ CoreAccountId account_id = identity_manager->GetPrimaryAccountId();
SetRefreshTokenForAccount(identity_manager, account_id, token_value);
}
void SetInvalidRefreshTokenForPrimaryAccount(
IdentityManager* identity_manager) {
DCHECK(identity_manager->HasPrimaryAccount());
- std::string account_id = identity_manager->GetPrimaryAccountId();
+ CoreAccountId account_id = identity_manager->GetPrimaryAccountId();
SetInvalidRefreshTokenForAccount(identity_manager, account_id);
}
@@ -122,7 +122,7 @@ void RemoveRefreshTokenForPrimaryAccount(IdentityManager* identity_manager) {
if (!identity_manager->HasPrimaryAccount())
return;
- std::string account_id = identity_manager->GetPrimaryAccountId();
+ CoreAccountId account_id = identity_manager->GetPrimaryAccountId();
RemoveRefreshTokenForAccount(identity_manager, account_id);
}
@@ -132,8 +132,9 @@ AccountInfo MakePrimaryAccountAvailable(IdentityManager* identity_manager,
CoreAccountInfo account_info = SetPrimaryAccount(identity_manager, email);
SetRefreshTokenForPrimaryAccount(identity_manager);
base::Optional<AccountInfo> primary_account_info =
- identity_manager->FindAccountInfoForAccountWithRefreshTokenByAccountId(
- account_info.account_id);
+ identity_manager
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+ account_info.account_id);
// Ensure that extended information for the account is available after setting
// the refresh token.
DCHECK(primary_account_info.has_value());
@@ -235,17 +236,17 @@ AccountInfo MakeAccountAvailableWithCookies(
}
void SetRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& token_value) {
UpdateRefreshTokenForAccount(
identity_manager->GetTokenService(),
identity_manager->GetAccountTrackerService(), identity_manager,
account_id,
- token_value.empty() ? "refresh_token_for_" + account_id : token_value);
+ token_value.empty() ? "refresh_token_for_" + account_id.id : token_value);
}
void SetInvalidRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
UpdateRefreshTokenForAccount(identity_manager->GetTokenService(),
identity_manager->GetAccountTrackerService(),
@@ -254,7 +255,7 @@ void SetInvalidRefreshTokenForAccount(IdentityManager* identity_manager,
}
void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id) {
+ const CoreAccountId& account_id) {
if (!identity_manager->HasAccountWithRefreshToken(account_id))
return;
@@ -327,7 +328,7 @@ std::string GetTestGaiaIdForEmail(const std::string& email) {
void UpdatePersistentErrorOfRefreshTokenForAccount(
IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error) {
DCHECK(identity_manager->HasAccountWithRefreshToken(account_id));
identity_manager->GetTokenService()->GetDelegate()->UpdateAuthError(
@@ -351,7 +352,7 @@ void CancelAllOngoingGaiaCookieOperations(IdentityManager* identity_manager) {
}
void SimulateSuccessfulFetchOfAccountInfo(IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& email,
const std::string& gaia,
const std::string& hosted_domain,
diff --git a/chromium/components/signin/public/identity_manager/identity_test_utils.h b/chromium/components/signin/public/identity_manager/identity_test_utils.h
index c7842e60214..9b014606a23 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_utils.h
+++ b/chromium/components/signin/public/identity_manager/identity_test_utils.h
@@ -115,21 +115,21 @@ AccountInfo MakeAccountAvailableWithCookies(
// value will be used instead.
// NOTE: See disclaimer at top of file re: direct usage.
void SetRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& token_value = std::string());
// Sets a special invalid refresh token for the given account (which must
// already be available). Blocks until the refresh token is set.
// NOTE: See disclaimer at top of file re: direct usage.
void SetInvalidRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id);
+ const CoreAccountId& account_id);
// Removes any refresh token that is present for the given account. Blocks until
// the refresh token is removed. Is a no-op if no refresh token is present for
// the given account.
// NOTE: See disclaimer at top of file re: direct usage.
void RemoveRefreshTokenForAccount(IdentityManager* identity_manager,
- const std::string& account_id);
+ const CoreAccountId& account_id);
// Puts the given accounts into the Gaia cookie, replacing any previous
// accounts. Blocks until the accounts have been set.
@@ -157,7 +157,7 @@ std::string GetTestGaiaIdForEmail(const std::string& email);
// account, i.e., an account with a refresh token.
void UpdatePersistentErrorOfRefreshTokenForAccount(
IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const GoogleServiceAuthError& auth_error);
// Disables internal retries of failed access token fetches.
@@ -174,7 +174,7 @@ void CancelAllOngoingGaiaCookieOperations(IdentityManager* identity_manager);
// Simulate account fetching using AccountTrackerService without sending
// network requests.
void SimulateSuccessfulFetchOfAccountInfo(IdentityManager* identity_manager,
- const std::string& account_id,
+ const CoreAccountId& account_id,
const std::string& email,
const std::string& gaia,
const std::string& hosted_domain,
diff --git a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc
index 5a1415fa58a..4b0ce696467 100644
--- a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc
+++ b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.cc
@@ -23,7 +23,6 @@ PrimaryAccountAccessTokenFetcher::PrimaryAccountAccessTokenFetcher(
identity_manager_(identity_manager),
scopes_(scopes),
callback_(std::move(callback)),
- identity_manager_observer_(this),
access_token_retried_(false),
mode_(mode) {
if (mode_ == Mode::kImmediate || AreCredentialsAvailable()) {
diff --git a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h
index 68436bc1958..7f09bc179f7 100644
--- a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h
+++ b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h
@@ -19,11 +19,116 @@ class GoogleServiceAuthError;
namespace signin {
struct AccessTokenInfo;
-// Helper class to ease the task of obtaining an OAuth2 access token for the
-// authenticated account. This handles various special cases, e.g. when the
-// refresh token isn't loaded yet (during startup), or when there is some
-// transient error.
-// May only be used on the UI thread.
+// Class that supports obtaining OAuth2 access tokens for the user's primary
+// account.See ./README.md for the definition of "accounts with OAuth2 refresh
+// tokens" and "primary account".
+//
+// The usage model of this class is as follows: When a
+// PrimaryAccountAccessTokenFetcher is created, it will make an access token
+// request for the primary account (either immediately or if/once the primary
+// account becomes available, based on the value of the specified |Mode|
+// parameter). When the access token request is fulfilled the
+// PrimaryAccountAccessTokenFetcher will call the specified callback, at which
+// point it is safe for the caller to destroy the object. If the object is
+// destroyed before the request is fulfilled the request is dropped and the
+// callback will never be invoked. This class may only be used on the UI thread.
+//
+// To drive responses to access token fetches in unittests of clients of this
+// class, use IdentityTestEnvironment.
+//
+// Concrete usage example (related concrete test example follows):
+// class MyClass {
+// public:
+// MyClass(IdentityManager* identity_manager) :
+// identity_manager_(identity_manager) {
+// // An access token request could also be initiated at any arbitrary
+// // point in the lifetime of |MyClass|.
+// StartAccessTokenRequestForPrimaryAccount();
+// }
+//
+//
+// ~MyClass() {
+// // If the access token request is still live, the destruction of
+// |access_token_fetcher_| will cause it to be dropped.
+// }
+//
+// private:
+// IdentityManager* identity_manager_;
+// std::unique_ptr<PrimaryAccountAccessTokenFetcher> access_token_fetcher_;
+// std::string access_token_;
+// GoogleServiceAuthError access_token_request_error_;
+//
+// // Most commonly invoked as part of some larger flow to hit a Gaia
+// // endpoint for a client-specific purpose (e.g., hitting sync
+// // endpoints).
+// // Could also be public, but in general, any clients that would need to
+// // create access token requests could and should just create
+// // PrimaryAccountAccessTokenFetchers directly themselves rather than
+// // introducing wrapper API surfaces.
+// MyClass::StartAccessTokenRequestForPrimaryAccount() {
+// // Choose scopes to obtain for the access token.
+// identity::ScopeSet scopes;
+// scopes.insert(GaiaConstants::kMyFirstScope);
+// scopes.insert(GaiaConstants::kMySecondScope);
+
+// // Choose the mode in which to fetch the access token:
+// // see AccessTokenFetcher::Mode below for definitions.
+// auto mode =
+// signin::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable;
+
+// // Create the fetcher.
+// access_token_fetcher_ =
+// std::make_unique<PrimaryAccountAccessTokenFetcher(
+// /*consumer_name=*/"MyClass",
+// identity_manager_,
+// scopes,
+// base::BindOnce(&MyClass::OnAccessTokenRequestCompleted,
+// // It is safe to use base::Unretained as
+// // |this| owns |access_token_fetcher_|.
+// base::Unretained(this)),
+// mode);
+//
+// }
+// MyClass::OnAccessTokenRequestCompleted(
+// GoogleServiceAuthError error, AccessTokenInfo access_token_info) {
+// // It is safe to destroy |access_token_fetcher_| from this callback.
+// access_token_fetcher_.reset();
+//
+// if (error.state() == GoogleServiceAuthError::NONE) {
+// // The fetcher successfully obtained an access token.
+// access_token_ = access_token_info.token;
+// // MyClass can now take whatever action required having an access
+// // token (e.g.,hitting a given Gaia endpoint).
+// ...
+// } else {
+// // The fetcher failed to obtain a token; |error| specifies why.
+// access_token_request_error_ = error;
+// // MyClass can now perform any desired error handling.
+// ...
+// }
+// }
+// }
+//
+// Concrete test example:
+// TEST(MyClassTest, SuccessfulAccessTokenFetchForPrimaryAccount) {
+// IdentityTestEnvironment identity_test_env;
+//
+//
+// MyClass my_class(identity_test_env.identity_manager());
+//
+// // Make the primary account available, which should result in an access
+// // token fetch being made on behalf of |my_class|.
+// identity_test_env.MakePrimaryAccountAvailable("test_email");
+//
+// identity_test_env.
+// WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+// "access_token", base::Time::Max());
+//
+// // MyClass::OnAccessTokenRequestCompleted() will have been invoked with
+// // an AccessTokenInfo object containing the above-specified parameters;
+// // the test can now perform any desired validation of expected actions
+// // |MyClass| took in response.
+// }
class PrimaryAccountAccessTokenFetcher : public IdentityManager::Observer {
public:
// Specifies how this instance should behave:
@@ -86,8 +191,8 @@ class PrimaryAccountAccessTokenFetcher : public IdentityManager::Observer {
// code.
AccessTokenFetcher::TokenCallback callback_;
- ScopedObserver<IdentityManager, PrimaryAccountAccessTokenFetcher>
- identity_manager_observer_;
+ ScopedObserver<IdentityManager, IdentityManager::Observer>
+ identity_manager_observer_{this};
// Internal fetcher that does the actual access token request.
std::unique_ptr<AccessTokenFetcher> access_token_fetcher_;
diff --git a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
index b0136c69c2b..b08033c76d7 100644
--- a/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -77,7 +77,7 @@ class PrimaryAccountAccessTokenFetcherTest : public testing::Test,
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
IdentityTestEnvironment identity_test_env_;
AccessTokenInfo access_token_info_;
};
diff --git a/chromium/components/signin/public/identity_manager/primary_account_mutator.h b/chromium/components/signin/public/identity_manager/primary_account_mutator.h
index 94755efd2cd..452335d1148 100644
--- a/chromium/components/signin/public/identity_manager/primary_account_mutator.h
+++ b/chromium/components/signin/public/identity_manager/primary_account_mutator.h
@@ -64,9 +64,8 @@ class PrimaryAccountMutator {
// account is known by IdentityManager. The reason is that there are
// contexts on ChromeOS where the primary account is not guaranteed to be
// known by IdentityManager when it is set.
- // TODO(https://crbug.com/967605): Port callers to SetPrimaryAccount() once
- // https://crbug.com/867602 is fixed.
- virtual bool SetPrimaryAccountAndUpdateAccountInfo(
+ // TODO(https://crbug.com/987955): Remove this API.
+ virtual bool DeprecatedSetPrimaryAccountAndUpdateAccountInfo(
const std::string& gaia_id,
const std::string& email) = 0;
#endif
diff --git a/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc b/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
index a18d03c290f..58568eb5b39 100644
--- a/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
@@ -8,7 +8,7 @@
#include "base/containers/flat_set.h"
#include "base/run_loop.h"
#include "base/scoped_observer.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
@@ -100,7 +100,7 @@ void RunClearPrimaryAccountTest(
signin::PrimaryAccountMutator::ClearAccountsAction account_action,
RemoveAccountExpectation account_expectation,
AuthExpectation auth_expection = AuthExpectation::kAuthNormal) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment(
/*test_url_loader_factory=*/nullptr, /*pref_service=*/nullptr,
account_consistency_method);
@@ -215,7 +215,7 @@ using PrimaryAccountMutatorTest = PlatformTest;
// Checks that setting the primary account works.
TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment;
signin::IdentityManager* identity_manager = environment.identity_manager();
@@ -247,7 +247,7 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount) {
// Checks that setting the primary account fails if the account is not known by
// the identity service.
TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_NoAccount) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment;
signin::IdentityManager* identity_manager = environment.identity_manager();
@@ -265,7 +265,7 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_NoAccount) {
// Checks that setting the primary account fails if the account is unknown.
TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_UnknownAccount) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment;
signin::IdentityManager* identity_manager = environment.identity_manager();
@@ -287,7 +287,7 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_UnknownAccount) {
// Checks that trying to set the primary account fails when there is already a
// primary account.
TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_AlreadyHasPrimaryAccount) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment;
signin::IdentityManager* identity_manager = environment.identity_manager();
@@ -320,7 +320,7 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_AlreadyHasPrimaryAccount) {
// account is not allowed.
TEST_F(PrimaryAccountMutatorTest,
SetPrimaryAccount_SettingPrimaryAccountForbidden) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
sync_preferences::TestingPrefServiceSyncable pref_service;
signin::IdentityTestEnvironment environment(
@@ -354,7 +354,7 @@ TEST_F(PrimaryAccountMutatorTest,
// support clearing the primary account.
#if !defined(OS_CHROMEOS)
TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_NotSignedIn) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment;
signin::IdentityManager* identity_manager = environment.identity_manager();
@@ -385,7 +385,7 @@ TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_NotSignedIn) {
}
TEST_F(PrimaryAccountMutatorTest, ClearPrimaryAccount_Default) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
signin::IdentityTestEnvironment environment;
signin::IdentityManager* identity_manager = environment.identity_manager();
diff --git a/chromium/components/signin/public/webdata/README.md b/chromium/components/signin/public/webdata/README.md
new file mode 100644
index 00000000000..7b76d688f14
--- /dev/null
+++ b/chromium/components/signin/public/webdata/README.md
@@ -0,0 +1,3 @@
+Supports maintenance of the user's OAuth2 refresh tokens on disk. Conceptually
+below the rest of the signin component and not allowed to depend on any other
+directories under //components/signin.
diff --git a/chromium/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc b/chromium/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
index 9d030076080..df64b605f45 100644
--- a/chromium/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
+++ b/chromium/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
@@ -12,7 +12,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,7 +27,7 @@ class SpellcheckHostMetricsTest : public testing::Test {
void RecordWordCountsForTesting() { metrics_->RecordWordCounts(); }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<SpellCheckHostMetrics> metrics_;
};
diff --git a/chromium/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc b/chromium/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
index 155c2069d49..c671f3babde 100644
--- a/chromium/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
+++ b/chromium/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
@@ -12,7 +12,7 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -49,8 +49,8 @@ class SpellcheckPlatformMacTest: public testing::Test {
base::Unretained(this)));
}
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
spellcheck_platform::ScopedEnglishLanguageForTest scoped_language_;
};
diff --git a/chromium/components/spellcheck/browser/spellcheck_platform_win.cc b/chromium/components/spellcheck/browser/spellcheck_platform_win.cc
index 49cdd6d8acb..1ac94e7fa39 100644
--- a/chromium/components/spellcheck/browser/spellcheck_platform_win.cc
+++ b/chromium/components/spellcheck/browser/spellcheck_platform_win.cc
@@ -127,7 +127,7 @@ class WindowsSpellChecker {
// used to post task to the background thread from main thread.
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_;
- base::WeakPtrFactory<WindowsSpellChecker> weak_ptr_factory_;
+ base::WeakPtrFactory<WindowsSpellChecker> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WindowsSpellChecker);
};
@@ -136,8 +136,7 @@ WindowsSpellChecker::WindowsSpellChecker(
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner> background_task_runner)
: main_task_runner_(main_task_runner),
- background_task_runner_(background_task_runner),
- weak_ptr_factory_(this) {
+ background_task_runner_(background_task_runner) {
background_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
@@ -451,7 +450,8 @@ std::unique_ptr<WindowsSpellChecker>& GetWindowsSpellChecker() {
static base::NoDestructor<std::unique_ptr<WindowsSpellChecker>>
win_spell_checker(std::make_unique<WindowsSpellChecker>(
base::ThreadTaskRunnerHandle::Get(),
- base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()})));
+ base::CreateCOMSTATaskRunner(
+ {base::ThreadPool(), base::MayBlock()})));
return *win_spell_checker;
}
} // anonymous namespace
diff --git a/chromium/components/spellcheck/browser/spellcheck_platform_win_unittest.cc b/chromium/components/spellcheck/browser/spellcheck_platform_win_unittest.cc
index cd71ff6c5a1..576f963c011 100644
--- a/chromium/components/spellcheck/browser/spellcheck_platform_win_unittest.cc
+++ b/chromium/components/spellcheck/browser/spellcheck_platform_win_unittest.cc
@@ -13,7 +13,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/win/windows_version.h"
#include "components/spellcheck/common/spellcheck_features.h"
#include "components/spellcheck/common/spellcheck_result.h"
@@ -57,8 +57,8 @@ class SpellcheckPlatformWinTest : public testing::Test {
std::vector<SpellCheckResult> spell_check_results_;
base::OnceClosure quit_;
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
};
TEST_F(SpellcheckPlatformWinTest, SpellCheckSuggestions_EN_US) {
diff --git a/chromium/components/spellcheck/browser/spelling_service_client.cc b/chromium/components/spellcheck/browser/spelling_service_client.cc
index d41b5f74f31..4fc7f4a9902 100644
--- a/chromium/components/spellcheck/browser/spelling_service_client.cc
+++ b/chromium/components/spellcheck/browser/spelling_service_client.cc
@@ -167,7 +167,7 @@ bool SpellingServiceClient::RequestTextCheck(
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = BuildEndpointUrl(type);
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
std::unique_ptr<network::SimpleURLLoader> simple_url_loader =
diff --git a/chromium/components/spellcheck/common/OWNERS b/chromium/components/spellcheck/common/OWNERS
index 7f7ed5ec40d..3deee8cd9c3 100644
--- a/chromium/components/spellcheck/common/OWNERS
+++ b/chromium/components/spellcheck/common/OWNERS
@@ -2,7 +2,7 @@ per-file *_messages*.h=set noparent
per-file *_messages*.h=file://ipc/SECURITY_OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/spellcheck/common/spellcheck.typemap b/chromium/components/spellcheck/common/spellcheck.typemap
index fa84bd42eaf..9b8732426e1 100644
--- a/chromium/components/spellcheck/common/spellcheck.typemap
+++ b/chromium/components/spellcheck/common/spellcheck.typemap
@@ -6,7 +6,7 @@ mojom = "//components/spellcheck/common/spellcheck.mojom"
public_headers = [ "//components/spellcheck/common/spellcheck_result.h" ]
-traits_headers = [ "//components/spellcheck/common/spellcheck_struct_traits.h" ]
+traits_headers = [ "//components/spellcheck/common/spellcheck_mojom_traits.h" ]
deps = [
"//components/spellcheck:buildflags",
@@ -17,8 +17,8 @@ public_deps = [
]
sources = [
- "spellcheck_struct_traits.cc",
- "spellcheck_struct_traits.h",
+ "spellcheck_mojom_traits.cc",
+ "spellcheck_mojom_traits.h",
]
type_mappings = [
diff --git a/chromium/components/spellcheck/common/spellcheck_features.cc b/chromium/components/spellcheck/common/spellcheck_features.cc
index 4462a2ac330..0bc03af8d4d 100644
--- a/chromium/components/spellcheck/common/spellcheck_features.cc
+++ b/chromium/components/spellcheck/common/spellcheck_features.cc
@@ -14,7 +14,7 @@ namespace spellcheck {
#if BUILDFLAG(ENABLE_SPELLCHECK)
const base::Feature kSpellingServiceRestApi{"SpellingServiceRestApi",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
#if defined(OS_WIN)
const base::Feature kWinUseBrowserSpellChecker{
diff --git a/chromium/components/spellcheck/common/spellcheck_struct_traits.cc b/chromium/components/spellcheck/common/spellcheck_mojom_traits.cc
index 2f0c4efc373..f935eaba654 100644
--- a/chromium/components/spellcheck/common/spellcheck_struct_traits.cc
+++ b/chromium/components/spellcheck/common/spellcheck_mojom_traits.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 "components/spellcheck/common/spellcheck_struct_traits.h"
+#include "components/spellcheck/common/spellcheck_mojom_traits.h"
#include "mojo/public/cpp/base/string16_mojom_traits.h"
diff --git a/chromium/components/spellcheck/common/spellcheck_struct_traits.h b/chromium/components/spellcheck/common/spellcheck_mojom_traits.h
index cfdaa9e6dc9..6744c5ee804 100644
--- a/chromium/components/spellcheck/common/spellcheck_struct_traits.h
+++ b/chromium/components/spellcheck/common/spellcheck_mojom_traits.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 COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_STRUCT_TRAITS_H
-#define COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_STRUCT_TRAITS_H
+#ifndef COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_MOJOM_TRAITS_H_
+#define COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_MOJOM_TRAITS_H_
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/common/spellcheck_result.h"
@@ -44,4 +44,4 @@ struct StructTraits<spellcheck::mojom::SpellCheckResultDataView,
} // namespace mojo
-#endif // COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_STRUCT_TRAITS_H
+#endif // COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_MOJOM_TRAITS_H_
diff --git a/chromium/components/spellcheck/renderer/empty_local_interface_provider.h b/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
index 9fe12c4d2d6..d861c9fed06 100644
--- a/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
+++ b/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
@@ -10,7 +10,7 @@
namespace spellcheck {
// A dummy LocalInterfaceProvider that doesn't bind any remote application.
-// May require a base::test::ScopedTaskEnvironment if GetInterface() is expected
+// May require a base::test::TaskEnvironment if GetInterface() is expected
// to be called.
class EmptyLocalInterfaceProvider
: public service_manager::LocalInterfaceProvider {
diff --git a/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
index 62bbdace258..4c333abf366 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
@@ -14,7 +14,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "components/spellcheck/renderer/empty_local_interface_provider.h"
@@ -114,7 +114,7 @@ class MultilingualSpellCheckTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
spellcheck::EmptyLocalInterfaceProvider embedder_provider_;
// Owned by |provider_|.
diff --git a/chromium/components/spellcheck/renderer/spellcheck_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
index 9160d9b3fe4..69f05fffb34 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
@@ -16,7 +16,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
@@ -70,9 +70,12 @@ class SpellCheckTest : public testing::Test {
void InitializeSpellCheck(const std::string& language) {
base::FilePath hunspell_directory = GetHunspellDirectory();
EXPECT_FALSE(hunspell_directory.empty());
- base::File file(
- spellcheck::GetVersionedFileName(language, hunspell_directory),
- base::File::FLAG_OPEN | base::File::FLAG_READ);
+ base::FilePath hunspell_file_path =
+ spellcheck::GetVersionedFileName(language, hunspell_directory);
+ base::File file(hunspell_file_path,
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ EXPECT_TRUE(file.IsValid()) << hunspell_file_path << " is not valid"
+ << file.ErrorToString(file.GetLastFileError());
#if defined(OS_MACOSX)
// TODO(groby): Forcing spellcheck to use hunspell, even on OSX.
// Instead, tests should exercise individual spelling engines.
@@ -127,7 +130,7 @@ class SpellCheckTest : public testing::Test {
private:
spellcheck::EmptyLocalInterfaceProvider embedder_provider_;
std::unique_ptr<SpellCheck> spell_check_;
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
};
struct MockTextCheckingResult {
@@ -1338,29 +1341,16 @@ TEST_F(SpellCheckTest, EnglishWords) {
// Checks that NOSUGGEST works in English dictionaries.
TEST_F(SpellCheckTest, NoSuggest) {
+ ReinitializeSpellCheck("xx-XX");
+
static const struct {
const char* input;
const char* suggestion;
- const char* locale;
bool should_pass;
- } kTestCases[] = {
- {"suckerbert", "cocksucker", "en-GB", true},
- {"suckerbert", "cocksucker", "en-US", true},
- {"suckerbert", "cocksucker", "en-CA", true},
- {"suckerbert", "cocksucker", "en-AU", true},
- {"suckerbert", "cocksuckers", "en-GB", true},
- {"suckerbert", "cocksuckers", "en-US", true},
- {"suckerbert", "cocksuckers", "en-CA", true},
- {"suckerbert", "cocksuckers", "en-AU", true},
- {"Batasunaa", "Batasuna", "ca-ES", true},
- {"pornoo", "porno", "it-IT", true},
- {"catass", "catas", "lt-LT", true},
- {"kuracc", "kurac", "sl-SI", true},
- {"pittt", "pitt", "sv-SE", true},
- };
+ } kTestCases[] = {{"typograpy", "typographit", true},
+ {"typograpy", "typographits", true}};
for (const auto& test_case : kTestCases) {
- ReinitializeSpellCheck(test_case.locale);
size_t suggestion_length = 0;
if (test_case.suggestion)
suggestion_length = strlen(test_case.suggestion);
@@ -1374,10 +1364,8 @@ TEST_F(SpellCheckTest, NoSuggest) {
suggestion_length, kNoTag, &misspelling_start, &misspelling_length,
nullptr);
- EXPECT_EQ(test_case.should_pass, result)
- << test_case.suggestion << " in " << test_case.locale;
- // TODO(cb/673424): Bring this back when suggestions are sped up.
-#if 0
+ EXPECT_EQ(test_case.should_pass, result) << test_case.suggestion;
+
// Now verify that this test case does not show up as a suggestion.
std::vector<base::string16> suggestions;
size_t input_length = 0;
@@ -1387,19 +1375,18 @@ TEST_F(SpellCheckTest, NoSuggest) {
base::ASCIIToUTF16(test_case.input).c_str(), kNoOffset,
input_length, kNoTag, &misspelling_start,
&misspelling_length, &suggestions);
+
// Input word should be a misspelling.
- EXPECT_FALSE(result) << test_case.input << " is not a misspelling in "
- << test_case.locale;
+ EXPECT_FALSE(result) << test_case.input << " is not a misspelling";
+
// Check if the suggested words occur.
for (const base::string16& suggestion : suggestions) {
for (const auto& test_case_to_check : kTestCases) {
int compare_result = suggestion.compare(
base::ASCIIToUTF16(test_case_to_check.suggestion));
- EXPECT_FALSE(compare_result == 0)
- << test_case_to_check.suggestion << " in " << test_case.locale;
+ EXPECT_FALSE(compare_result == 0) << test_case_to_check.suggestion;
}
}
-#endif
}
}
diff --git a/chromium/components/ssl_errors/OWNERS b/chromium/components/ssl_errors/OWNERS
index 8921a14a7e6..62bf9b30082 100644
--- a/chromium/components/ssl_errors/OWNERS
+++ b/chromium/components/ssl_errors/OWNERS
@@ -6,3 +6,4 @@ meacer@chromium.org
rsleevi@chromium.org
# TEAM: security-enamel@chromium.org
+# COMPONENT: UI>Browser>Interstitials
diff --git a/chromium/components/ssl_errors/error_classification_unittest.cc b/chromium/components/ssl_errors/error_classification_unittest.cc
index 6161d194b4d..a06c22c8782 100644
--- a/chromium/components/ssl_errors/error_classification_unittest.cc
+++ b/chromium/components/ssl_errors/error_classification_unittest.cc
@@ -10,9 +10,9 @@
#include "base/files/file_path.h"
#include "base/strings/string_split.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
+#include "base/test/task_environment.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "components/network_time/network_time_test_utils.h"
@@ -363,8 +363,8 @@ TEST_F(SSLErrorClassificationTest, GetClockState) {
// Tests that all possible NetworkClockState histogram values are recorded
// appropriately.
TEST_F(SSLErrorClassificationTest, NetworkClockStateHistogram) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO);
scoped_refptr<network::TestSharedURLLoaderFactory> shared_url_loader_factory =
base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
diff --git a/chromium/components/ssl_errors/error_info.cc b/chromium/components/ssl_errors/error_info.cc
index fe7e6453509..f8ee1696706 100644
--- a/chromium/components/ssl_errors/error_info.cc
+++ b/chromium/components/ssl_errors/error_info.cc
@@ -111,8 +111,9 @@ ErrorInfo ErrorInfo::CreateError(ErrorType error_type,
l10n_util::GetStringUTF16(IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION);
break;
case CERT_NO_REVOCATION_MECHANISM:
- details = l10n_util::GetStringUTF16(
- IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS);
+ details = l10n_util::GetStringFUTF16(
+ IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS,
+ UTF8ToUTF16(request_url.host()));
short_description = l10n_util::GetStringUTF16(
IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION);
break;
@@ -162,8 +163,9 @@ ErrorInfo ErrorInfo::CreateError(ErrorType error_type,
IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DESCRIPTION);
break;
case CERT_UNABLE_TO_CHECK_REVOCATION:
- details = l10n_util::GetStringUTF16(
- IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS);
+ details = l10n_util::GetStringFUTF16(
+ IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS,
+ UTF8ToUTF16(request_url.host()));
short_description = l10n_util::GetStringUTF16(
IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DESCRIPTION);
break;
diff --git a/chromium/components/ssl_errors_strings_grdp/OWNERS b/chromium/components/ssl_errors_strings_grdp/OWNERS
index 877ebf5aaff..43af85e6516 100644
--- a/chromium/components/ssl_errors_strings_grdp/OWNERS
+++ b/chromium/components/ssl_errors_strings_grdp/OWNERS
@@ -1 +1,2 @@
file://components/ssl_errors/OWNERS
+# COMPONENT: UI>Browser>Interstitials
diff --git a/chromium/components/startup_metric_utils/browser/pref_names.cc b/chromium/components/startup_metric_utils/browser/pref_names.cc
index b479dd54566..906f4fd8ed9 100644
--- a/chromium/components/startup_metric_utils/browser/pref_names.cc
+++ b/chromium/components/startup_metric_utils/browser/pref_names.cc
@@ -7,9 +7,6 @@
namespace startup_metric_utils {
namespace prefs {
-// Time of the last startup stored as an int64.
-const char kLastStartupTimestamp[] = "startup_metric.last_startup_timestamp";
-
// Version of the product in the startup preceding this one as reported by
// version_info.h.
const char kLastStartupVersion[] = "startup_metric.last_startup_version";
diff --git a/chromium/components/startup_metric_utils/browser/pref_names.h b/chromium/components/startup_metric_utils/browser/pref_names.h
index 11a97095bfb..cc80416167b 100644
--- a/chromium/components/startup_metric_utils/browser/pref_names.h
+++ b/chromium/components/startup_metric_utils/browser/pref_names.h
@@ -11,7 +11,6 @@ namespace prefs {
// Alphabetical list of preference names specific to the startup_metric_utils
// component. Keep alphabetized, and document each in the .cc file.
-extern const char kLastStartupTimestamp[];
extern const char kLastStartupVersion[];
extern const char kSameVersionStartupCount[];
diff --git a/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc b/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
index 36657fa6fc8..c1bc9d5b635 100644
--- a/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
+++ b/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -32,6 +32,18 @@
#include "base/win/win_util.h"
#endif
+// Data from deprecated UMA histograms:
+//
+// Startup.TimeSinceLastStartup.[Cold/Warm]Startup, August 2019, Windows-only:
+// Time elapsed since the last startup that went up to the main message loop
+// start. This is recorded just before the main message loop starts.
+//
+// Cold startup Warm startup
+// 25th percentile 3.5 hours 4 minutes
+// 50th percentile 14.5 hours 21 minutes
+// 75th percentile 27 hours 90 minutes
+// 95th percentile 13 days 17 hours
+
namespace startup_metric_utils {
namespace {
@@ -438,44 +450,6 @@ void AddStartupEventsForTelemetry()
g_browser_main_entry_point_ticks);
}
-// Logs the Startup.TimeSinceLastStartup histogram. Obtains the timestamp of the
-// last startup from |pref_service| and overwrites it with the timestamp of the
-// current startup. If the startup temperature has been set by
-// RecordBrowserMainMessageLoopStart, the time since last startup is also logged
-// to a histogram suffixed with the startup temperature.
-void RecordTimeSinceLastStartup(PrefService* pref_service) {
-#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
- DCHECK(pref_service);
-
- // Get the timestamp of the current startup.
- const base::Time process_start_time =
- base::Process::Current().CreationTime();
-
- // Get the timestamp of the last startup from |pref_service|.
- const int64_t last_startup_timestamp_internal =
- pref_service->GetInt64(prefs::kLastStartupTimestamp);
- if (last_startup_timestamp_internal != 0) {
- // Log the Startup.TimeSinceLastStartup histogram.
- const base::Time last_startup_timestamp =
- base::Time::FromInternalValue(last_startup_timestamp_internal);
- const base::TimeDelta time_since_last_startup =
- process_start_time - last_startup_timestamp;
- const int minutes_since_last_startup = time_since_last_startup.InMinutes();
-
- // Ignore negative values, which can be caused by system clock changes.
- if (minutes_since_last_startup >= 0) {
- UMA_HISTOGRAM_WITH_TEMPERATURE_AND_SAME_VERSION_COUNT(
- UMA_HISTOGRAM_TIME_IN_MINUTES_MONTH_RANGE,
- "Startup.TimeSinceLastStartup", minutes_since_last_startup);
- }
- }
-
- // Write the timestamp of the current startup in |pref_service|.
- pref_service->SetInt64(prefs::kLastStartupTimestamp,
- process_start_time.ToInternalValue());
-#endif // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
-}
-
// Logs the Startup.SameVersionStartupCount histogram. Relies on |pref_service|
// to know information about the previous startups and store information for
// future ones. Stores the logged value in |g_startups_with_current_version|.
@@ -511,7 +485,6 @@ bool ShouldLogStartupHistogram() {
void RegisterPrefs(PrefRegistrySimple* registry) {
DCHECK(registry);
- registry->RegisterInt64Pref(prefs::kLastStartupTimestamp, 0);
registry->RegisterStringPref(prefs::kLastStartupVersion, std::string());
registry->RegisterIntegerPref(prefs::kSameVersionStartupCount, 0);
}
@@ -587,7 +560,6 @@ void RecordBrowserMainMessageLoopStart(base::TimeTicks ticks,
}
AddStartupEventsForTelemetry();
- RecordTimeSinceLastStartup(pref_service);
RecordSystemUptimeHistogram();
// Record values stored prior to startup temperature evaluation.
@@ -776,4 +748,32 @@ base::TimeTicks MainEntryPointTicks() {
return g_browser_main_entry_point_ticks;
}
+void RecordWebFooterDidFirstVisuallyNonEmptyPaint(base::TimeTicks ticks) {
+ static bool is_first_call = true;
+ if (!is_first_call || ticks.is_null())
+ return;
+ is_first_call = false;
+ if (!ShouldLogStartupHistogram())
+ return;
+
+ UMA_HISTOGRAM_AND_TRACE_WITH_TEMPERATURE(
+ UMA_HISTOGRAM_MEDIUM_TIMES,
+ "Startup.WebFooterExperiment.DidFirstVisuallyNonEmptyPaint",
+ g_process_creation_ticks, ticks);
+}
+
+void RecordWebFooterCreation(base::TimeTicks ticks) {
+ static bool is_first_call = true;
+ if (!is_first_call || ticks.is_null())
+ return;
+ is_first_call = false;
+ if (!ShouldLogStartupHistogram())
+ return;
+
+ UMA_HISTOGRAM_AND_TRACE_WITH_TEMPERATURE(
+ UMA_HISTOGRAM_MEDIUM_TIMES,
+ "Startup.WebFooterExperiment.WebFooterCreation", g_process_creation_ticks,
+ ticks);
+}
+
} // namespace startup_metric_utils
diff --git a/chromium/components/startup_metric_utils/browser/startup_metric_utils.h b/chromium/components/startup_metric_utils/browser/startup_metric_utils.h
index 87017036fc1..962d3cad72e 100644
--- a/chromium/components/startup_metric_utils/browser/startup_metric_utils.h
+++ b/chromium/components/startup_metric_utils/browser/startup_metric_utils.h
@@ -110,6 +110,10 @@ void RecordBrowserWindowFirstPaintCompositingEnded(base::TimeTicks ticks);
// recorded yet. This method is expected to be called from the UI thread.
base::TimeTicks MainEntryPointTicks();
+// Record metrics for the web-footer experiment. See https://crbug.com/993502.
+void RecordWebFooterDidFirstVisuallyNonEmptyPaint(base::TimeTicks ticks);
+void RecordWebFooterCreation(base::TimeTicks ticks);
+
} // namespace startup_metric_utils
#endif // COMPONENTS_STARTUP_METRIC_UTILS_BROWSER_STARTUP_METRIC_UTILS_H_
diff --git a/chromium/components/storage_monitor/BUILD.gn b/chromium/components/storage_monitor/BUILD.gn
index 5a434bdc9b4..00038296108 100644
--- a/chromium/components/storage_monitor/BUILD.gn
+++ b/chromium/components/storage_monitor/BUILD.gn
@@ -76,6 +76,8 @@ static_library("storage_monitor") {
"storage_monitor_linux.cc",
"storage_monitor_linux.h",
]
+ } else {
+ sources += [ "storage_monitor_dummy.cc" ]
}
}
diff --git a/chromium/components/storage_monitor/OWNERS b/chromium/components/storage_monitor/OWNERS
index ed5b39e3398..ff7f7648b35 100644
--- a/chromium/components/storage_monitor/OWNERS
+++ b/chromium/components/storage_monitor/OWNERS
@@ -1,2 +1,3 @@
thestig@chromium.org
tommycli@chromium.org
+# COMPONENT: Platform>Apps>FileManager
diff --git a/chromium/components/storage_monitor/image_capture_device.mm b/chromium/components/storage_monitor/image_capture_device.mm
index d0fea0272a7..3b2b0207e73 100644
--- a/chromium/components/storage_monitor/image_capture_device.mm
+++ b/chromium/components/storage_monitor/image_capture_device.mm
@@ -220,9 +220,9 @@ base::FilePath PathForCameraItem(ICCameraItem* item) {
// Shared result value from file-copy closure to tell-listener closure.
// This is worth blocking shutdown, as otherwise a file that has been
// downloaded will be incorrectly named.
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::Bind(&storage_monitor::RenameFile, savedPath, saveAsPath),
base::Bind(&storage_monitor::ReturnRenameResultToListener, listener_,
diff --git a/chromium/components/storage_monitor/image_capture_device_manager_unittest.mm b/chromium/components/storage_monitor/image_capture_device_manager_unittest.mm
index a0f39249d48..0f6118a83e8 100644
--- a/chromium/components/storage_monitor/image_capture_device_manager_unittest.mm
+++ b/chromium/components/storage_monitor/image_capture_device_manager_unittest.mm
@@ -15,7 +15,7 @@
#include "components/storage_monitor/image_capture_device_manager.h"
#include "components/storage_monitor/test_storage_monitor.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -266,10 +266,10 @@ class ImageCaptureDeviceManagerTest : public testing::Test {
moreGoing:NO];
}
- void RunUntilIdle() { thread_bundle_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
protected:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
TestStorageMonitor* monitor_;
TestCameraListener listener_;
};
diff --git a/chromium/components/storage_monitor/media_storage_util.cc b/chromium/components/storage_monitor/media_storage_util.cc
index ee054d8780f..7b3f5b11ae6 100644
--- a/chromium/components/storage_monitor/media_storage_util.cc
+++ b/chromium/components/storage_monitor/media_storage_util.cc
@@ -101,9 +101,9 @@ bool MediaStorageUtil::CanCreateFileSystem(const std::string& device_id,
void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices,
const base::Closure& done) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::PostTaskWithTraitsAndReply(
+ base::PostTaskAndReply(
FROM_HERE,
- {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&FilterAttachedDevicesOnBackgroundSequence, devices),
done);
diff --git a/chromium/components/storage_monitor/media_storage_util_unittest.cc b/chromium/components/storage_monitor/media_storage_util_unittest.cc
index 142c54c7097..c62837393fa 100644
--- a/chromium/components/storage_monitor/media_storage_util_unittest.cc
+++ b/chromium/components/storage_monitor/media_storage_util_unittest.cc
@@ -15,7 +15,7 @@
#include "components/storage_monitor/removable_device_constants.h"
#include "components/storage_monitor/storage_monitor.h"
#include "components/storage_monitor/test_storage_monitor.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -67,10 +67,10 @@ class MediaStorageUtilTest : public testing::Test {
TestStorageMonitor::Destroy();
}
- void RunUntilIdle() { test_browser_thread_bundle_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
private:
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
TestStorageMonitor* monitor_;
base::ScopedTempDir scoped_temp_dir_;
};
@@ -81,8 +81,9 @@ TEST_F(MediaStorageUtilTest, MediaDeviceAttached) {
// Create a dummy mount point with DCIM Directory.
base::FilePath mount_point(CreateMountPoint(true));
ASSERT_FALSE(mount_point.empty());
- base::PostTaskWithTraits(
- FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()},
base::BindOnce(&MediaStorageUtilTest::CheckDCIMDeviceType,
base::Unretained(this), mount_point));
RunUntilIdle();
@@ -94,8 +95,9 @@ TEST_F(MediaStorageUtilTest, NonMediaDeviceAttached) {
// Create a dummy mount point without DCIM Directory.
base::FilePath mount_point(CreateMountPoint(false));
ASSERT_FALSE(mount_point.empty());
- base::PostTaskWithTraits(
- FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()},
base::BindOnce(&MediaStorageUtilTest::CheckNonDCIMDeviceType,
base::Unretained(this), mount_point));
RunUntilIdle();
diff --git a/chromium/components/storage_monitor/mtp_manager_client_chromeos.cc b/chromium/components/storage_monitor/mtp_manager_client_chromeos.cc
index 9ac419e1fbc..21ae6e8ab69 100644
--- a/chromium/components/storage_monitor/mtp_manager_client_chromeos.cc
+++ b/chromium/components/storage_monitor/mtp_manager_client_chromeos.cc
@@ -16,10 +16,7 @@ namespace storage_monitor {
MtpManagerClientChromeOS::MtpManagerClientChromeOS(
StorageMonitor::Receiver* receiver,
device::mojom::MtpManager* mtp_manager)
- : mtp_manager_(mtp_manager),
- binding_(this),
- notifications_(receiver),
- weak_ptr_factory_(this) {
+ : mtp_manager_(mtp_manager), binding_(this), notifications_(receiver) {
device::mojom::MtpManagerClientAssociatedPtrInfo client;
binding_.Bind(mojo::MakeRequest(&client));
mtp_manager_->EnumerateStoragesAndSetClient(
diff --git a/chromium/components/storage_monitor/mtp_manager_client_chromeos.h b/chromium/components/storage_monitor/mtp_manager_client_chromeos.h
index d7716b35372..e88ac51f4f0 100644
--- a/chromium/components/storage_monitor/mtp_manager_client_chromeos.h
+++ b/chromium/components/storage_monitor/mtp_manager_client_chromeos.h
@@ -68,7 +68,7 @@ class MtpManagerClientChromeOS : public device::mojom::MtpManagerClient {
// Guaranteed to outlive this class.
StorageMonitor::Receiver* const notifications_;
- base::WeakPtrFactory<MtpManagerClientChromeOS> weak_ptr_factory_;
+ base::WeakPtrFactory<MtpManagerClientChromeOS> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(MtpManagerClientChromeOS);
};
diff --git a/chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc b/chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc
index 38455ea524c..5a7a8bd306a 100644
--- a/chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc
+++ b/chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc
@@ -19,7 +19,7 @@
#include "components/storage_monitor/storage_info_utils.h"
#include "components/storage_monitor/storage_monitor.h"
#include "components/storage_monitor/test_storage_monitor.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "services/device/public/mojom/mtp_manager.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -106,7 +106,7 @@ class FakeMtpManagerClientChromeOS : public MtpManagerClientChromeOS {
class MtpManagerClientChromeOSTest : public testing::Test {
public:
MtpManagerClientChromeOSTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
+ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
~MtpManagerClientChromeOSTest() override {}
@@ -134,7 +134,7 @@ class MtpManagerClientChromeOSTest : public testing::Test {
}
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<FakeMtpManagerClientChromeOS> mtp_device_observer_;
std::unique_ptr<MockRemovableStorageObserver> mock_storage_observer_;
diff --git a/chromium/components/storage_monitor/portable_device_watcher_win.cc b/chromium/components/storage_monitor/portable_device_watcher_win.cc
index 2d3b9b04644..ae44f0f086c 100644
--- a/chromium/components/storage_monitor/portable_device_watcher_win.cc
+++ b/chromium/components/storage_monitor/portable_device_watcher_win.cc
@@ -496,9 +496,7 @@ PortableDeviceWatcherWin::DeviceDetails::~DeviceDetails() {
}
PortableDeviceWatcherWin::PortableDeviceWatcherWin()
- : notifications_(nullptr),
- storage_notifications_(nullptr),
- weak_ptr_factory_(this) {}
+ : notifications_(nullptr), storage_notifications_(nullptr) {}
PortableDeviceWatcherWin::~PortableDeviceWatcherWin() {
UnregisterDeviceNotification(notifications_);
@@ -507,8 +505,8 @@ PortableDeviceWatcherWin::~PortableDeviceWatcherWin() {
void PortableDeviceWatcherWin::Init(HWND hwnd) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
notifications_ = RegisterPortableDeviceNotification(hwnd);
- media_task_runner_ = base::CreateCOMSTATaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ media_task_runner_ = base::CreateCOMSTATaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
EnumerateAttachedDevices();
}
diff --git a/chromium/components/storage_monitor/portable_device_watcher_win.h b/chromium/components/storage_monitor/portable_device_watcher_win.h
index b991471799d..377a97cd412 100644
--- a/chromium/components/storage_monitor/portable_device_watcher_win.h
+++ b/chromium/components/storage_monitor/portable_device_watcher_win.h
@@ -141,7 +141,7 @@ class PortableDeviceWatcherWin {
StorageMonitor::Receiver* storage_notifications_;
// Used by |media_task_runner_| to create cancelable callbacks.
- base::WeakPtrFactory<PortableDeviceWatcherWin> weak_ptr_factory_;
+ base::WeakPtrFactory<PortableDeviceWatcherWin> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PortableDeviceWatcherWin);
};
diff --git a/chromium/components/storage_monitor/storage_monitor_chromeos.cc b/chromium/components/storage_monitor/storage_monitor_chromeos.cc
index a7705cb24fc..9ef9b9966f0 100644
--- a/chromium/components/storage_monitor/storage_monitor_chromeos.cc
+++ b/chromium/components/storage_monitor/storage_monitor_chromeos.cc
@@ -103,7 +103,7 @@ bool GetFixedStorageInfo(const Disk& disk, StorageInfo* info) {
} // namespace
-StorageMonitorCros::StorageMonitorCros() : weak_ptr_factory_(this) {}
+StorageMonitorCros::StorageMonitorCros() {}
StorageMonitorCros::~StorageMonitorCros() {
DiskMountManager* manager = DiskMountManager::GetInstance();
@@ -141,8 +141,8 @@ void StorageMonitorCros::CheckExistingMountPoints() {
}
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT});
for (const auto& it : DiskMountManager::GetInstance()->mount_points()) {
base::PostTaskAndReplyWithResult(
@@ -215,8 +215,10 @@ void StorageMonitorCros::OnMountEvent(
return;
}
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT},
base::Bind(&MediaStorageUtil::HasDcim,
base::FilePath(mount_info.mount_path)),
base::Bind(&StorageMonitorCros::AddMountedPath,
diff --git a/chromium/components/storage_monitor/storage_monitor_chromeos.h b/chromium/components/storage_monitor/storage_monitor_chromeos.h
index 97a4e06dcbc..5bdcd970db4 100644
--- a/chromium/components/storage_monitor/storage_monitor_chromeos.h
+++ b/chromium/components/storage_monitor/storage_monitor_chromeos.h
@@ -90,7 +90,7 @@ class StorageMonitorCros : public StorageMonitor,
std::unique_ptr<MtpManagerClientChromeOS> mtp_manager_client_;
- base::WeakPtrFactory<StorageMonitorCros> weak_ptr_factory_;
+ base::WeakPtrFactory<StorageMonitorCros> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(StorageMonitorCros);
};
diff --git a/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc
index 65b86366213..40bdd34ef7c 100644
--- a/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc
+++ b/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -17,7 +17,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "chromeos/disks/disk.h"
#include "chromeos/disks/mock_disk_mount_manager.h"
#include "components/storage_monitor/mock_removable_storage_observer.h"
@@ -25,7 +25,7 @@
#include "components/storage_monitor/storage_info.h"
#include "components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h"
#include "components/storage_monitor/test_storage_monitor.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace storage_monitor {
@@ -151,7 +151,7 @@ class StorageMonitorCrosTest : public testing::Test {
StorageMonitor::EjectStatus status_;
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
// Temporary directory for created test data.
base::ScopedTempDir scoped_temp_dir_;
@@ -194,7 +194,7 @@ void StorageMonitorCrosTest::TearDown() {
disk_mount_manager_mock_ = NULL;
DiskMountManager::Shutdown();
- thread_bundle_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void StorageMonitorCrosTest::MountDevice(
@@ -214,7 +214,7 @@ void StorageMonitorCrosTest::MountDevice(
true /* on_removable_device */, kFileSystemType);
}
monitor_->OnMountEvent(DiskMountManager::MOUNTING, error_code, mount_info);
- thread_bundle_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void StorageMonitorCrosTest::UnmountDevice(
@@ -223,7 +223,7 @@ void StorageMonitorCrosTest::UnmountDevice(
monitor_->OnMountEvent(DiskMountManager::UNMOUNTING, error_code, mount_info);
if (error_code == chromeos::MOUNT_ERROR_NONE)
disk_mount_manager_mock_->RemoveDiskEntryForMountDevice(mount_info);
- thread_bundle_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
uint64_t StorageMonitorCrosTest::GetDeviceStorageSize(
diff --git a/chromium/components/storage_monitor/storage_monitor_dummy.cc b/chromium/components/storage_monitor/storage_monitor_dummy.cc
new file mode 100644
index 00000000000..07ef451dfaa
--- /dev/null
+++ b/chromium/components/storage_monitor/storage_monitor_dummy.cc
@@ -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.
+
+// StorageMonitorDummy implementation.
+
+#include "components/storage_monitor/storage_monitor.h"
+
+namespace storage_monitor {
+
+class StorageMonitorDummy : public StorageMonitor {
+ public:
+ // Should only be called by browser start up code.
+ // Use StorageMonitor::GetInstance() instead.
+ StorageMonitorDummy() = default;
+ ~StorageMonitorDummy() override = default;
+
+ // Must be called for StorageMonitorDummy to work.
+ void Init() override {}
+
+ private:
+ // StorageMonitor implementation:
+ bool GetStorageInfoForPath(const base::FilePath& path,
+ StorageInfo* device_info) const override {
+ return false;
+ }
+
+ void EjectDevice(const std::string& device_id,
+ base::Callback<void(EjectStatus)> callback) override {}
+
+ DISALLOW_COPY_AND_ASSIGN(StorageMonitorDummy);
+};
+
+StorageMonitor* StorageMonitor::CreateInternal() {
+ return new StorageMonitorDummy();
+}
+
+} // namespace storage_monitor
diff --git a/chromium/components/storage_monitor/storage_monitor_linux.cc b/chromium/components/storage_monitor/storage_monitor_linux.cc
index 3a0155c444d..f2b288e2a64 100644
--- a/chromium/components/storage_monitor/storage_monitor_linux.cc
+++ b/chromium/components/storage_monitor/storage_monitor_linux.cc
@@ -245,8 +245,9 @@ StorageMonitor::EjectStatus EjectPathOnBlockingTaskRunner(
StorageMonitorLinux::StorageMonitorLinux(const base::FilePath& path)
: mtab_path_(path),
get_device_info_callback_(base::Bind(&GetDeviceInfo)),
- mtab_watcher_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}
+ mtab_watcher_task_runner_(
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT})) {}
StorageMonitorLinux::~StorageMonitorLinux() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -326,8 +327,9 @@ void StorageMonitorLinux::EjectDevice(
receiver()->ProcessDetach(device_id);
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::Bind(&EjectPathOnBlockingTaskRunner, path, device), callback);
}
@@ -399,8 +401,8 @@ void StorageMonitorLinux::UpdateMtab(const MountPointDeviceMap& new_mtab) {
// Check new mtab entries against existing ones.
scoped_refptr<base::SequencedTaskRunner> mounting_task_runner =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+ base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT});
for (auto new_iter = new_mtab.begin(); new_iter != new_mtab.end();
++new_iter) {
const base::FilePath& mount_point = new_iter->first;
diff --git a/chromium/components/storage_monitor/storage_monitor_linux_unittest.cc b/chromium/components/storage_monitor/storage_monitor_linux_unittest.cc
index 2b475bff56c..c6a25dfeb09 100644
--- a/chromium/components/storage_monitor/storage_monitor_linux_unittest.cc
+++ b/chromium/components/storage_monitor/storage_monitor_linux_unittest.cc
@@ -21,8 +21,8 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/thread_pool/thread_pool.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/storage_monitor/mock_removable_storage_observer.h"
#include "components/storage_monitor/removable_device_constants.h"
@@ -188,13 +188,13 @@ class StorageMonitorLinuxTest : public testing::Test {
monitor_->AddObserver(mock_storage_observer_.get());
monitor_->Init();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void TearDown() override {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
monitor_->RemoveObserver(mock_storage_observer_.get());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Linux storage monitor must be destroyed on the UI thread, so do it here.
monitor_.reset();
@@ -309,7 +309,7 @@ class StorageMonitorLinuxTest : public testing::Test {
ASSERT_EQ(1, endmntent(file));
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<MockRemovableStorageObserver> mock_storage_observer_;
diff --git a/chromium/components/storage_monitor/storage_monitor_mac.mm b/chromium/components/storage_monitor/storage_monitor_mac.mm
index a57b21258e3..1f1745a2e45 100644
--- a/chromium/components/storage_monitor/storage_monitor_mac.mm
+++ b/chromium/components/storage_monitor/storage_monitor_mac.mm
@@ -306,8 +306,8 @@ void StorageMonitorMac::EjectDevice(
options->bsd_name = bsd_name;
options->callback = callback;
options->disk = std::move(disk);
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(EjectDisk, options));
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(EjectDisk, options));
}
// static
@@ -339,8 +339,9 @@ void StorageMonitorMac::GetDiskInfoAndUpdate(
base::ScopedCFTypeRef<CFDictionaryRef> dict(DADiskCopyDescription(disk));
std::string* bsd_name = new std::string;
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&BuildStorageInfo, dict, bsd_name),
base::BindOnce(&StorageMonitorMac::UpdateDisk, AsWeakPtr(), update_type,
base::Owned(bsd_name)));
diff --git a/chromium/components/storage_monitor/storage_monitor_mac_unittest.mm b/chromium/components/storage_monitor/storage_monitor_mac_unittest.mm
index eb6e34030d5..f13ef45d52c 100644
--- a/chromium/components/storage_monitor/storage_monitor_mac_unittest.mm
+++ b/chromium/components/storage_monitor/storage_monitor_mac_unittest.mm
@@ -21,7 +21,7 @@
#include "components/storage_monitor/test_storage_monitor.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
uint64_t kTestSize = 1000000ULL;
@@ -60,7 +60,7 @@ class StorageMonitorMacTest : public testing::Test {
}
void UpdateDisk(StorageInfo info, StorageMonitorMac::UpdateType update_type) {
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&StorageMonitorMac::UpdateDisk,
base::Unretained(monitor_.get()), update_type,
@@ -69,7 +69,7 @@ class StorageMonitorMacTest : public testing::Test {
}
protected:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<MockRemovableStorageObserver> mock_storage_observer_;
diff --git a/chromium/components/storage_monitor/storage_monitor_unittest.cc b/chromium/components/storage_monitor/storage_monitor_unittest.cc
index 3bf96fb7441..4fe8492b700 100644
--- a/chromium/components/storage_monitor/storage_monitor_unittest.cc
+++ b/chromium/components/storage_monitor/storage_monitor_unittest.cc
@@ -8,7 +8,7 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/storage_monitor/mock_removable_storage_observer.h"
#include "components/storage_monitor/test_storage_monitor.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,7 +24,7 @@ void SetLatch(bool* called) {
namespace storage_monitor {
TEST(StorageMonitorTest, TestInitialize) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
TestStorageMonitor::Destroy();
TestStorageMonitor monitor;
EXPECT_FALSE(monitor.init_called());
@@ -39,7 +39,7 @@ TEST(StorageMonitorTest, TestInitialize) {
TEST(StorageMonitorTest, DeviceAttachDetachNotifications) {
TestStorageMonitor::Destroy();
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
const std::string kDeviceId1 = "dcim:UUID:FFF0-0001";
const std::string kDeviceId2 = "dcim:UUID:FFF0-0002";
MockRemovableStorageObserver observer1;
@@ -82,7 +82,7 @@ TEST(StorageMonitorTest, DeviceAttachDetachNotifications) {
TEST(StorageMonitorTest, GetAllAvailableStoragesEmpty) {
TestStorageMonitor::Destroy();
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
TestStorageMonitor monitor;
std::vector<StorageInfo> devices = monitor.GetAllAvailableStorages();
EXPECT_EQ(0U, devices.size());
@@ -90,7 +90,7 @@ TEST(StorageMonitorTest, GetAllAvailableStoragesEmpty) {
TEST(StorageMonitorTest, GetAllAvailableStorageAttachDetach) {
TestStorageMonitor::Destroy();
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
TestStorageMonitor monitor;
const std::string kDeviceId1 = "dcim:UUID:FFF0-0042";
const base::FilePath kDevicePath1(FILE_PATH_LITERAL("/testfoo"));
diff --git a/chromium/components/storage_monitor/storage_monitor_win_unittest.cc b/chromium/components/storage_monitor/storage_monitor_win_unittest.cc
index ef4ba5a8ec6..aac0092fc8e 100644
--- a/chromium/components/storage_monitor/storage_monitor_win_unittest.cc
+++ b/chromium/components/storage_monitor/storage_monitor_win_unittest.cc
@@ -26,7 +26,7 @@
#include "components/storage_monitor/test_storage_monitor_win.h"
#include "components/storage_monitor/test_volume_mount_watcher_win.h"
#include "components/storage_monitor/volume_mount_watcher_win.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -72,7 +72,7 @@ class StorageMonitorWinTest : public testing::Test {
MockRemovableStorageObserver observer_;
private:
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(StorageMonitorWinTest);
};
diff --git a/chromium/components/storage_monitor/volume_mount_watcher_win.cc b/chromium/components/storage_monitor/volume_mount_watcher_win.cc
index 50919ff55c1..b594a63af47 100644
--- a/chromium/components/storage_monitor/volume_mount_watcher_win.cc
+++ b/chromium/components/storage_monitor/volume_mount_watcher_win.cc
@@ -225,9 +225,8 @@ void EjectDeviceInThreadPool(
// at not-just-drive-letter paths.
if (drive_letter < L'A' || drive_letter > L'Z' ||
device != device.DirName()) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
return;
}
base::SStringPrintf(&volume_name, L"\\\\.\\%lc:", drive_letter);
@@ -237,9 +236,8 @@ void EjectDeviceInThreadPool(
nullptr, OPEN_EXISTING, 0, nullptr));
if (!volume_handle.IsValid()) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
return;
}
@@ -267,9 +265,8 @@ void EjectDeviceInThreadPool(
return;
}
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_IN_USE));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_IN_USE));
return;
}
@@ -285,9 +282,8 @@ void EjectDeviceInThreadPool(
if (!dismounted) {
DeviceIoControl(volume_handle.Get(), FSCTL_UNLOCK_VOLUME, nullptr, 0,
nullptr, 0, &bytes_returned, nullptr);
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_OK));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_OK));
return;
}
@@ -297,33 +293,31 @@ void EjectDeviceInThreadPool(
if (!DeviceIoControl(volume_handle.Get(), IOCTL_STORAGE_MEDIA_REMOVAL,
&pmr_buffer, sizeof(PREVENT_MEDIA_REMOVAL), nullptr, 0,
&bytes_returned, nullptr)) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
return;
}
// Physically eject or soft-eject the device.
if (!DeviceIoControl(volume_handle.Get(), IOCTL_STORAGE_EJECT_MEDIA, nullptr,
0, nullptr, 0, &bytes_returned, nullptr)) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_FAILURE));
return;
}
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, StorageMonitor::EJECT_OK));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, StorageMonitor::EJECT_OK));
}
} // namespace
VolumeMountWatcherWin::VolumeMountWatcherWin()
- : device_info_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ : device_info_task_runner_(base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
- notifications_(nullptr),
- weak_factory_(this) {}
+ notifications_(nullptr) {}
// static
base::FilePath VolumeMountWatcherWin::DriveNumberToFilePath(int drive_number) {
@@ -376,14 +370,13 @@ void VolumeMountWatcherWin::RetrieveInfoForDeviceAndAdd(
base::WeakPtr<VolumeMountWatcherWin> volume_watcher) {
StorageInfo info;
if (!get_device_details_callback.Run(device_path, &info)) {
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&VolumeMountWatcherWin::DeviceCheckComplete,
- volume_watcher, device_path));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&VolumeMountWatcherWin::DeviceCheckComplete,
+ volume_watcher, device_path));
return;
}
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&VolumeMountWatcherWin::HandleDeviceAttachEventOnUIThread,
volume_watcher, device_path, info));
diff --git a/chromium/components/storage_monitor/volume_mount_watcher_win.h b/chromium/components/storage_monitor/volume_mount_watcher_win.h
index c8eafb2bf7c..0e60473a98b 100644
--- a/chromium/components/storage_monitor/volume_mount_watcher_win.h
+++ b/chromium/components/storage_monitor/volume_mount_watcher_win.h
@@ -114,7 +114,7 @@ class VolumeMountWatcherWin {
// removable devices will be notified.
StorageMonitor::Receiver* notifications_;
- base::WeakPtrFactory<VolumeMountWatcherWin> weak_factory_;
+ base::WeakPtrFactory<VolumeMountWatcherWin> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(VolumeMountWatcherWin);
};
diff --git a/chromium/components/strings/components_chromium_strings_mr.xtb b/chromium/components/strings/components_chromium_strings_mr.xtb
index 0cf41722125..98078ffca54 100644
--- a/chromium/components/strings/components_chromium_strings_mr.xtb
+++ b/chromium/components/strings/components_chromium_strings_mr.xtb
@@ -16,7 +16,7 @@
&gt;
LAN सेटिंग्ज
वर जा आणि "तुमच्या LAN साठी एक प्रॉक्सी सर्व्हर वापरा" चेकबॉक्स ची निवड रद्द करा.</translation>
-<translation id="48558539577516920">तुमच्या फायरवॉल किंवा अँटीव्हायरस सेटिंग्जमधील नेटवर्क अॅक्सेस करण्यास
+<translation id="48558539577516920">तुमच्या फायरवॉल किंवा अँटीव्हायरस सेटिंग्जमधील नेटवर्क ॲक्सेस करण्यास
Chromium ला परवानगी द्या.</translation>
<translation id="580822234363523061">Chromium मेनू &gt;
<ph name="SETTINGS_TITLE" />
diff --git a/chromium/components/strings/components_google_chrome_strings_ml.xtb b/chromium/components/strings/components_google_chrome_strings_ml.xtb
index 54c270f5bdc..2a282100b44 100644
--- a/chromium/components/strings/components_google_chrome_strings_ml.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_ml.xtb
@@ -19,12 +19,13 @@
&gt;
<ph name="PROXIES_TITLE" />
ഒപ്പം നിങ്ങളുടെ കോൺഫിഗറേഷൻ ''പ്രോക്‌സി അല്ല'' അല്ലെങ്കിൽ ''നേരിട്ട്'' എന്നതിലേക്ക് സജ്ജമാക്കിയിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക.</translation>
-<translation id="6341737370356890233">Chrome മെനു &gt;
+<translation id="6341737370356890233">ഇനിപ്പറയുന്നതിലേക്ക് പോകുക
+ Chrome മെനു &gt;
<ph name="SETTINGS_TITLE" />
&gt;
<ph name="ADVANCED_TITLE" /> എന്നതിലേക്ക് പോയി
- "<ph name="NO_PREFETCH_DESCRIPTION" />" തിരഞ്ഞെടുത്തത് മാറ്റുക.
- ഇത് പ്രശ്‌നം പരിഹരിക്കുന്നില്ലെങ്കിൽ, മെച്ചപ്പെട്ട പ്രകടനത്തിനായി ഈ ഓപ്‌ഷൻ വീണ്ടും തിരഞ്ഞെടുക്കുന്നതിനായി ഞങ്ങൾ ശുപാർശചെയ്യുന്നു.</translation>
+ "<ph name="NO_PREFETCH_DESCRIPTION" />" തിരഞ്ഞെടുത്തത് മാറ്റുക.
+ ഇത് പ്രശ്‌നം പരിഹരിക്കുന്നില്ലെങ്കിൽ, മെച്ചപ്പെട്ട പ്രകടനത്തിനായി ഈ ഓപ്‌ഷൻ വീണ്ടും തിരഞ്ഞെടുക്കുന്നതിനായി ഞങ്ങൾ ശുപാർശ ചെയ്യുന്നു.</translation>
<translation id="6855094794438142393">Chrome മെനു &gt;
<ph name="SETTINGS_TITLE" />
&gt;
diff --git a/chromium/components/strings/components_google_chrome_strings_mr.xtb b/chromium/components/strings/components_google_chrome_strings_mr.xtb
index 5ef11e3e2c0..5a578ecd439 100644
--- a/chromium/components/strings/components_google_chrome_strings_mr.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_mr.xtb
@@ -7,7 +7,7 @@
<translation id="2874156562296220396"><ph name="BEGIN_LINK_CHROMIUM" />Chromium<ph name="END_LINK_CHROMIUM" /> मुक्त-स्रोत प्रोजेक्ट आणि अन्य <ph name="BEGIN_LINK_OSS" />मुक्त स्रोत सॉफ्टवेअर<ph name="END_LINK_OSS" /> द्वारे Google Chrome ची निर्मिती करणे शक्य झाले.</translation>
<translation id="3140883423282498090">पुढील वेळी तुम्ही Google Chrome पुन्हा लाँच केल्यानंतर तुमचे बदल प्रभावी होतील.</translation>
<translation id="3444832043240812445">हे पेज तुम्ही <ph name="BEGIN_LINK" />कॅश अहवाल सुरू<ph name="END_LINK" /> केल्यास केवळ तुम्हाला अलीकडील क्रॅशची माहिती दाखवते.</translation>
-<translation id="3875312571075912821">तुमच्या फायरवॉल किंवा अँटीव्हायरस सेटिंग्जमधील नेटवर्क अॅक्सेस करण्यास
+<translation id="3875312571075912821">तुमच्या फायरवॉल किंवा अँटीव्हायरस सेटिंग्जमधील नेटवर्क ॲक्सेस करण्यास
Chrome ला परवानगी द्या.</translation>
<translation id="4010643444566880169">Chrome OS ने त्याचे प्रारंभीचे सेटअप पूर्ण केले नाही.</translation>
<translation id="4853578032408195113">तुम्ही एक सुरक्षित Google Chrome पृष्ठ पाहत आहात</translation>
diff --git a/chromium/components/strings/components_strings_am.xtb b/chromium/components/strings/components_strings_am.xtb
index 9bdc049f0a1..3e86b78cd81 100644
--- a/chromium/components/strings/components_strings_am.xtb
+++ b/chromium/components/strings/components_strings_am.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">መረጃ ጠቋሚ-5x8</translation>
<translation id="1088860948719068836">በካርድ ላይ ስም ያክሉ</translation>
<translation id="1089439967362294234">የይለፍ ቃል ቀይር</translation>
+<translation id="1096545575934602868">ይህመስክ ከ<ph name="MAX_ITEMS_LIMIT" /> ግቤቶች በላይ ሊኖሩት አይገባም። ሌሎች ተጨማሪ ግቤቶች ሁሉ ይወገዳሉ።</translation>
<translation id="109743633954054152">የይለፍ ቃላትን በChrome ቅንብሮች ውስጥ ያቀናብሩ</translation>
<translation id="1103523840287552314">ሁልጊዜ <ph name="LANGUAGE" />ን መተርጎም</translation>
<translation id="1107591249535594099">ምልክት ከተደረገበት፣ Chrome ለተሻለ ፈጣን የቅጽ አሞላል የካርድዎን ቅጂ በዚህ መሣሪያ ላይ ያከማቻል።</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">የ<ph name="URL" /> <ph name="BEGIN_LINK" />የተሸጎጠ ቅጂ<ph name="END_LINK" /> ይድረሱ</translation>
<translation id="1156303062776767266">አካባቢያዊ ወይም የተጋራ ፋይል እየተመለከቱ ነው</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ሳይታሰብ ግንኙነቱን ዘግቷል።</translation>
+<translation id="115926840831309955">የእርስዎን CVC ይፈትሹ እና እንደገና ይሞክሩ ወይም የአገልግሎት ማብቂያ ቀኑን ያዘምኑ</translation>
<translation id="1161325031994447685">ከWi-Fi ጋር ዳግም በማገናኘት</translation>
<translation id="1165039591588034296">ስህተት</translation>
<translation id="1175364870820465910">&amp;አትም…</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">«በእርስዎ ኮምፒውተር ላይ ያለ ሶፍትዌር Chrome ደህንነቱ በተጠበቀ ሁኔታ ከድር ጋር እንዳይገናኝ እያስቆመው ነው» (የWindows ኮምፒውተሮች ብቻ)</translation>
<translation id="1294154142200295408">የትእዛዝ መስመር ልዩነቶች</translation>
<translation id="129553762522093515">በቅርብ ጊዜ የተዘጉ</translation>
+<translation id="1298536327547837046">የማልዌር ቅኝት</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />ኩኪዎችዎን ማጽዳት ይሞክሩ<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">የተቋረጡ ባህሪያት</translation>
<translation id="1320233736580025032">Prc1 (የደብዳቤ ፖስታ)</translation>
<translation id="132301787627749051">የቅንጥብ ሰሌዳ ምስልን ይፈልጉ</translation>
<translation id="1323433172918577554">ተጨማሪ አሳይ</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google ሉሆች</translation>
<translation id="1527263332363067270">ግንኙነትን በመጠበቅ ላይ…</translation>
<translation id="1529521330346880926">10x15 (የደብዳቤ ፖስታ)</translation>
+<translation id="1530707389502320859">አሁን ለመጎብኘት የሞከሩት ጣቢያ የሐስት ይመስላል። አጥቂዎች አንዳንድ ግ ጊዜ በዩአርኤሉ ላይ ለመታየት የሚያስቸግሩ አነስተኛ ለውጦችን በማድረግ ጥኣቢያዎችን ያስመስላሉ።</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">ይህ ገጽ እንዲህ ይላል፦</translation>
<translation id="153384715582417236">ለአሁን ያለው ይኸው ነው</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">ስርዓተ ክወና</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">ሰነድ ለመብራራት ከልክ በላይ ትልቅ ነው</translation>
-<translation id="1721312023322545264">ይህን ጣቢያ ለመጎብኘት ከ<ph name="NAME" /> ፈቃድ ያስፈልገዎታል</translation>
<translation id="1721424275792716183">* መስክ ያስፈልጋል</translation>
<translation id="1727741090716970331">የሚሰራ የካርድ ቁጥር ያክሉ</translation>
<translation id="1728677426644403582">የአንድ ድረ-ገጽ ምንጭ እየተመለከቱ ነው</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">እርስዎ የሚጎበኟቸው ጣቢያዎች እና በእነሱ ላይ የሚያጠፉት ጊዜ</translation>
<translation id="1826516787628120939">በመፈተሸ ላይ</translation>
<translation id="1834321415901700177">ይህ ጣቢያ ጎጂ ፕሮግራሞችን ይዟል</translation>
+<translation id="1838374766361614909">ፍለጋን ያፅዱ</translation>
<translation id="1839551713262164453">የመመሪያ እሴቶችን ማረጋገጥ ከስህተቶች ጋር አልተሳካም</translation>
<translation id="1842969606798536927">ይክፈሉ</translation>
<translation id="1871208020102129563">የ.pac ስክሪፕት ዩአርኤል ሳይሆን ተኪ አገልጋዮችን እንዲጠቀም ነው ተኪ የተዋቀረው።</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">ዝርዝር ሰብስብ</translation>
<translation id="1898423065542865115">በማጣራት ላይ</translation>
<translation id="1914326953223720820">አገልግሎትን በትን</translation>
+<translation id="1915697529809968049">ከCVC ይልቅ የንክኪ መታወቂያ ይጠቀሙ?</translation>
<translation id="1916770123977586577">የተዘመኑ ቅንብሮችዎን በዚህ ጣቢያ ላይ ለመተግበር ይህን ገጽ እንደገና ይጫኑት</translation>
<translation id="1919345977826869612">ማስታወቂያዎች</translation>
<translation id="1919367280705858090">በአንድ የተወሰነ የስህተት መልዕክት ላይ እገዛ ያግኙ</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> እልባቶች</translation>
<translation id="1973335181906896915">የመለያ ቁጥር መስጠት ላይ ስህተት</translation>
<translation id="1974060860693918893">የላቀ</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" /> እርስዎ የጎበኟቸውን አንዳንድ ገጾች ዩአርኤሎች፣ የተወሰነ የሥርዓት መረጃ እና አንዳንድ የገጽ ይዘት<ph name="END_WHITEPAPER_LINK" /> ወደ Google በመላክ የ Chrome ደህንነትን ለማሻሻል ያግዙ።<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">የጽኑ ትዕዛዝ ስሪት</translation>
<translation id="1981206234434200693">የChrome የአሰሳ ታሪክ ውሂብን አጽዳ</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{እና 1 ተጨማሪ}one{እና # ተጨማሪ}other{እና # ተጨማሪ}}</translation>
@@ -244,10 +251,12 @@
<translation id="2202020181578195191">ትክክለኛ የአገልግሎት ማብቂያ ዓመት ያስገቡ</translation>
<translation id="2212735316055980242">መመሪያ አልተገኘም</translation>
<translation id="2213606439339815911">ግቤቶችን በማምጣት ላይ...</translation>
+<translation id="2215727959747642672">የፋይል አርትዖት አደራረግ</translation>
<translation id="2218879909401188352">በ<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ላይ አሁን ያሉ አጥቂዎች የእርስዎን መሣሪያ የሚያበላሹ አደገኛ መተግበሪያዎችን ሊጭኑ፣ በእርስዎ ሞባይል ክፍያ መጠየቂያ ላይ የተደበቁ ክፍያ መጠየቂያዎችን ሊያክሉ ወይም የእርስዎን የግል መረጃ ሊሰርቁ ይችላሉ። <ph name="BEGIN_LEARN_MORE_LINK" />የበለጠ ለመረዳት<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ምንም በይነመረብ የለም</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />የመመርመሪያ መተግበሪያውን<ph name="END_LINK" /> በመጠቀም ግንኙነትዎን ያስተካክሉት</translation>
<translation id="2239100178324503013">አሁን ላክ</translation>
+<translation id="2248949050832152960">WebAuthnን ተጠቀም</translation>
<translation id="225207911366869382">ይህ ዋጋ ለዚህ መመሪያ ተቋርጧል።</translation>
<translation id="2257315177824333709">ይቅርታ፣ የእርስዎ ካርድ አሁን ላይ ሊቀመጥ አይችልም</translation>
<translation id="2262243747453050782">የኤች ቲ ቲ ፒ ስህተት</translation>
@@ -292,7 +301,6 @@
<translation id="2479410451996844060">ልክ ያልሆነ የፍለጋ ዩአርኤል።</translation>
<translation id="2482878487686419369">ማስታወቂያዎች</translation>
<translation id="248348093745724435">የማሽን መመሪያዎች</translation>
-<translation id="2485387744899240041">የእርስዎ መሣሪያ እና አሳሽ የተጠቃሚ ስሞች</translation>
<translation id="2491120439723279231">የአገልጋይ እውቅና ማረጋገጫ ስህተቶችን ይዟል።</translation>
<translation id="2493640343870896922">ደብዳቤ-ፕላስ</translation>
<translation id="2495083838625180221">JSON ተንታኝ</translation>
@@ -302,6 +310,7 @@
<translation id="2501278716633472235">ወደ ኋላ ተመለስ</translation>
<translation id="2503184589641749290">ተቀባይነት ያላቸው የዴቢት እና የቅድመ-ክፍያ ካርዶች</translation>
<translation id="2505268675989099013">መለያን ጠብቅ</translation>
+<translation id="2515335152965840738">ችላ በል</translation>
<translation id="2515629240566999685">በእርስዎ አካባቢ ያለውን ሲግናል መፈተሽ</translation>
<translation id="2523886232349826891">በዚህ መሣሪያ ላይ ብቻ ይቀመጣል</translation>
<translation id="2524461107774643265">ተጨማሪ መረጃ ያክሉ</translation>
@@ -326,7 +335,6 @@
<translation id="2653659639078652383">አስገባ</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{ምንም}=1{1 የይለፍ ቃል (ለ<ph name="DOMAIN_LIST" />)}=2{2 የይለፍ ቃላት (ለ<ph name="DOMAIN_LIST" />)}one{# የይለፍ ቃላት (ለ<ph name="DOMAIN_LIST" />)}other{# የይለፍ ቃላት (ለ<ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">ሌሎች ትሮችን ወይም መተግበሪያዎችን ይዝጉ</translation>
-<translation id="267371737713284912">ለመቀልበስ <ph name="MODIFIER_KEY_DESCRIPTION" />ን ይጫኑ</translation>
<translation id="2674170444375937751">እርግጠኛ ነዎት እነዚህን ገጾች ከታሪክዎ መሰረዝ ይፈልጋሉ?</translation>
<translation id="2676271551327853224">ROC 8K</translation>
<translation id="2677748264148917807">ለቅቀህ ውጣ</translation>
@@ -336,12 +344,12 @@
<translation id="2704283930420550640">ዋጋ ከቅርጸት ጋር አይዛመድም።</translation>
<translation id="2705137772291741111">የተቀመጠው (የተሸጎጠ) የዚህ ጣቢያ ቅጂ የሚነበብ አልነበረም።</translation>
<translation id="2709516037105925701">ራስ-ሙላ</translation>
-<translation id="2712173769900027643">ፍቃድ ጠይቅ</translation>
<translation id="2713444072780614174">ነጭ</translation>
<translation id="2720342946869265578">በአቅራቢያ</translation>
<translation id="2721148159707890343">ጥያቄ ተሳክቷል</translation>
<translation id="2728127805433021124">የአገልጋዩ እውቅና ማረጋገጫ የተፈረመው በደካማ የፊርማ ስልተቀመር ነው።</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />የግንኙነት መመርመሪያን በማሄድ ላይ<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">እነዚህን ባህሪያት በማንቃት የአሳሽ ውሂብ ሊያጡ ወይም የእርስዎን ደህንነት ወይም ግላዊነት ለአደጋ ሊያጋልጡት ይችላሉ። የነቁ ባህሪያት በሁሉም የዚህ አሳሽ ተጠቃሚዎች ላይ ተፈጻሚ ናቸው።</translation>
<translation id="2735043616039983645">ለዚህ መመሪያ የሚጋጩ እሴቶች ያላቸው ከአንድ በላይ ምንጮች አሉ!</translation>
<translation id="2738330467931008676">የመውሰጃ አድራሻ ይምረጡ</translation>
<translation id="2740531572673183784">እሺ</translation>
@@ -352,16 +360,15 @@
<translation id="2784949926578158345">ግንኙነቱ ዳግም እንዲጀምር ተደርጓል።</translation>
<translation id="2788784517760473862">ተቀባይነት ያላቸው ክሬዲት ካርዶች</translation>
<translation id="2792012897584536778">የዚህ መሣሪያ አስተዳዳሪዎች እርስዎ የሚጎበኟቸው የድር ጣቢያዎች ይዘትን እንዲያዩ ሊያስችሉ የሚችሉ የደህንነት እውቅና ማረጋገጫዎችን አቀናብረዋል።</translation>
-<translation id="2794233252405721443">ጣቢያ ታግዷል</translation>
<translation id="2799020568854403057">ቀጥሎ ያለው ጣቢያ ጎጂ መተግበሪያዎች አሉት</translation>
<translation id="2799223571221894425">ዳግም አስጀምር</translation>
<translation id="2803306138276472711">Google የጥንቃቄ አሰሳ በቅርብ ጊዜ <ph name="SITE" /> ላይ <ph name="BEGIN_LINK" />ተንኮል-አዘል ዌር<ph name="END_LINK" /> አግኝቷል። በመደበኛ ጊዜ ደህንነታቸው የተጠበቁ ድር ጣቢያዎች አንዳንድ ጊዜ በተንኮል-አዘል ዌር ይጠቃሉ።</translation>
+<translation id="2815364696811431560">ከጣቢያ ውጣ</translation>
<translation id="2824775600643448204">የአድራሻ እና ፍለጋ አሞሌ</translation>
<translation id="2826760142808435982">ግንኙነቱ የተመሰጠረ እና <ph name="CIPHER" />ን በመጠቀም የተረጋገጠ ነው፣ እና <ph name="KX" />ን እንደ የቁልፍ መቀያየሪያ ስልት ይጠቀምበታል።</translation>
<translation id="2835170189407361413">ቅጽ አጽዳ</translation>
<translation id="2847118875340931228">ማንነት የማያሳውቅ መስኮት ክፈት</translation>
<translation id="2850739647070081192">ግብዣ (የደብዳቤ ፖስታ)</translation>
-<translation id="2851634818064021665">ይህን ጣቢያ ለመጎብኘት ፈቃድ ያስፈልገዎታል</translation>
<translation id="2856444702002559011">አጥቂዎች የእርስዎን መረጃ (ለምሳሌ፦ የይለፍ ቃላትን፣ መልዕክቶችን፣ ወይም የክሬዲት ካርዶችን የመሳሰሉ) ከ<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ለመስረቅ እየሞከሩ ሊሆኑ ይችላሉ። <ph name="BEGIN_LEARN_MORE_LINK" />የበለጠ ለመረዳት<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">ካርድ ይቀመጥ?</translation>
@@ -386,6 +393,7 @@
<translation id="2985306909656435243">ከነቃ Chromium ለተሻለ የቅጽ አሞላል ፍጥነት ሲባል በዚህ መሣሪያ ላይ ያለው የካርድዎን ቅጂ ያከማቻል።</translation>
<translation id="2985398929374701810">የሚሰራ አድራሻ ያስገቡ</translation>
<translation id="2986368408720340940">ይህ የመውሰጃ ዘዴ አይደገፍም። የተለየ ዘዴ ይምረጡ።</translation>
+<translation id="2987034854559945715">ምንም ተዛማጅ ባህሪያት የሉም</translation>
<translation id="2991174974383378012">ከድረ ገጾች ጋር ማጋራት</translation>
<translation id="2991571918955627853">የድር ጣቢያው HSTS ስለሚጠቀም አሁን <ph name="SITE" />ን መጎብኘት አይችሉም። የአውታረ መረብ ስህተቶች እና ጥቃቶች አብዛኛው ጊዜ ጊዜያዊ ናቸው፣ ስለዚህ ይህ ገጽ በኋላ ላይ ሳይሠራ አይቀርም።</translation>
<translation id="3005723025932146533">የተቀመጠ ቅጂ አሳይ</translation>
@@ -396,6 +404,7 @@
<translation id="3024663005179499861">የተሳሳተ የመምሪያ አይነት</translation>
<translation id="3037605927509011580">ውይ፣ ተሰናከለ!</translation>
<translation id="3041612393474885105">የሰርቲፊኬት መረጃ</translation>
+<translation id="3057676462092457419">የDnsOverHttps ሁነታ <ph name="SECURE_DNS_MODE_SECURE" /> ገና አይደገፍም፣ ሁነታው ወደ <ph name="SECURE_DNS_MODE_OFF" /> ተቀናብሯል።</translation>
<translation id="3060227939791841287">C9 (የደብዳቤ ፖስታ)</translation>
<translation id="3061707000357573562">የመጠገኛ አገልግሎት</translation>
<translation id="3064966200440839136">በውጫዊ ማከማቻ በኩል ለማጫወት ማንነት ከማያሳውቅ ሁነታ በመውጣት ላይ። ይቀጥል?</translation>
@@ -420,6 +429,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> በ<ph name="SERVER_NAME" /> ላይ</translation>
<translation id="320323717674993345">ክፍያን ሰርዝ</translation>
<translation id="3207960819495026254">ዕልባት ተደርጎበታል</translation>
+<translation id="3209034400446768650">ገጽ ገንዘብ ሊያስከፍል ይችል ይሆናል</translation>
<translation id="3225919329040284222">አገልጋዩ አብረው የተሰሩ የሚጠበቁ ማሟያዎችን የማያሟላ የእውቅና ማረጋገጫ ነው ያቀረበው። እነዚህ የሚጠበቁ ማሟያዎች እርስዎን ለመጠበቅ ለተረጋገጡ ከፍተኛ ደህንነት ላላቸው ድር ጣቢያዎች ተካትተዋል።</translation>
<translation id="3226128629678568754">ገጹን ለመጫን የሚያስፈልገው ውሂብ ዳግም ለማስገባት የዳግም ጫን አዝራሩን ይጫኑ።</translation>
<translation id="3227137524299004712">ማይክሮፎን</translation>
@@ -427,7 +437,6 @@
<translation id="3229041911291329567">የእርስዎ መሣሪያ እና አሳሽ የስሪት መረጃ</translation>
<translation id="323107829343500871">የ<ph name="CREDIT_CARD" /> ሲቪሲ ያስገቡ</translation>
<translation id="3234666976984236645">ሁልጊዜ በዚህ ጣቢያ ላይ ያለ አስፈላጊ ይዘትን አግኝ</translation>
-<translation id="3254409185687681395">ለእዚህ ገጽ ዕልባት አብጅ</translation>
<translation id="3270847123878663523">&amp;ዳግም ደርድርን ቀልብስ</translation>
<translation id="3274521967729236597">ፓ-ካይ</translation>
<translation id="3282497668470633863">በካርድ ላይ ስም ያክሉ</translation>
@@ -437,7 +446,6 @@
<translation id="3320021301628644560">የመክፈያ አድራሻ አክል</translation>
<translation id="3324983252691184275">ክሪምሶን</translation>
<translation id="3338095232262050444">ደህንነቱ የተጠበቀ ነው</translation>
-<translation id="3345135638360864351">ይህን ጣቢያ ለመድረስ ያቀረቡት ጥያቄ ወደ <ph name="NAME" /> ሊላክ አልተቻለም። እባክዎ እንደገና ይሞክሩ።</translation>
<translation id="3355823806454867987">የተኪ ቅንብሮችን በመቀየር ላይ...</translation>
<translation id="3361596688432910856">Chrome የሚከተሉትን መረጃዎች <ph name="BEGIN_EMPHASIS" />አያስቀምጥም<ph name="END_EMPHASIS" />፦
<ph name="BEGIN_LIST" />
@@ -471,18 +479,15 @@
<translation id="3462200631372590220">የላቁ ደብቅ</translation>
<translation id="3467763166455606212">የካርድ ያዥ ስም ያስፈልጋል</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />፣ በአሁኑ ጊዜ ክፍት፣ ወደ ክፍቱ ትር ለመቀየር ከዚያ Enter ይጫኑ</translation>
-<translation id="3479539252931486093">ይህ ያልተጠበቀ ነበር? <ph name="BEGIN_LINK" />ያሳውቁን<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">አሁን አይደለም</translation>
<translation id="3484560055331845446">የGoogle መለያዎን መዳረሻ ሊያጡ ይችላሉ። Chrome የይለፍ ቃልዎን አሁኑኑ እንዲቀይሩት ይመክራል። በመለያ እንዲገቡ ይጠየቃሉ።</translation>
<translation id="3495081129428749620">በገጽ ውስጥ ያግኙ
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">በዚህ ጊዜ ላይ ወላጅህን ማግኘት አልቻልንም። እባክህ እንደገና ሞክር።</translation>
<translation id="3512163584740124171">ይህ መመሪያ ከተመሳሳይ የመመሪያ ቡድን የመጣ ሌላ መመሪያ ከፍተኛ ተቀዳሚነት ስላለው ችላ ተብሏል።</translation>
<translation id="3528171143076753409">የአገልጋይ እውቅና ማረጋገጫ የታመነ አይደለም።</translation>
<translation id="3528485271872257980">ደማቅ ቡናማ</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{በተሰመሩ መሣሪያዎች ላይ ቢያንስ 1 ንጥል}=1{1 ንጥል (እና ተጨማሪ የተሰመሩ መሣሪያዎች ላይ)}one{# ንጥሎች (እና ተጨማሪ የተሰመሩ መሣሪያዎች ላይ)}other{# ንጥሎች (እና ተጨማሪ የተሰመሩ መሣሪያዎች ላይ)}}</translation>
<translation id="3539171420378717834">የዚህን ካርድ ቅጂ በዚህ መሣሪያ ላይ አቆይ</translation>
-<translation id="3556433843310711081">የእርስዎ አስተዳዳሪ እገዳውን ሊያነሱልዎ ይችላሉ</translation>
<translation id="3566021033012934673">ግንኙነትዎ የግል አይደለም</translation>
<translation id="3574305903863751447"><ph name="CITY" />፣ <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> ላይ የተካተተ ገጽ እንዲህ ይላል፦</translation>
@@ -510,6 +515,7 @@
<translation id="3678529606614285348">ገጹን ማንነት በማያሳውቅ አዲስ መስኮት ውስጥ ይክፈቱ (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">የብልሽት ሪፖርት <ph name="CRASH_TIME" /> ላይ ተይዟል፣ <ph name="UPLOAD_TIME" /> ላይ ተሰቅሏል</translation>
<translation id="3681007416295224113">የሰርቲፊኬት መረጃ</translation>
+<translation id="3701427423622901115">ዳግም ማስጀመር እውቅና ተሰጥቶታል።</translation>
<translation id="3704162925118123524">እየተጠቀሙ ያሉት አውታረ መረብ በመለያ መግቢያ ገጹን እንዲጎበኙ ሊጠይቅዎት ይችላል።</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">በመጫን ላይ…</translation>
@@ -526,6 +532,7 @@
<translation id="3748148204939282805">በ<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ላይ ያሉ አጥቂዎች ልክ እንደ ሶፍትዌርን መጫን ወይም የግል መረጃዎችን (ለምሳሌ፦ የይለፍ ቃላትን፣ የስልክ ቁጥሮችን ወይም የክሬዲት ካርዶችን የመሳሰሉ) አጋልጦ መስጠት እንዲያደርጉ ሊያታልለዎት ይችላል። <ph name="BEGIN_LEARN_MORE_LINK" />የበለጠ ለመረዳት<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">በአገልጋይ ስህተት ምክንያት የትርጉም ስራው ተሰናክሏል።</translation>
<translation id="3759461132968374835">በቅርብ ጊዜ ሪፖርት የተደረጉ ብልሽቶች የለዎትም። የብልሽት ሪፖርት ማድረግ ተሰናክሎ ሳለ የተከሰቱ ብልሽቶች እዚህ አይታዩም።</translation>
+<translation id="3760561303380396507">ከCVC ይልቅ Windows Helloን ይጠቀሙ?</translation>
<translation id="3761718714832595332">ሁኔታን ደብቅ</translation>
<translation id="3765032636089507299">የSafe Browsing ገጽ በግንባታ ላይ ነው።</translation>
<translation id="3778403066972421603">ይህን ካርድ በእርስዎ የGoogle መለያ እና በዚህ መሣሪያ ላይ ማስቀመጥ ይፈልጋሉ?</translation>
@@ -535,6 +542,7 @@
<translation id="3789155188480882154">መጠን 16</translation>
<translation id="3797522431967816232">Prc3 (የደብዳቤ ፖስታ)</translation>
<translation id="3807873520724684969">ጎጂ ይዘት ታግዷል።</translation>
+<translation id="3808375843007691220">ማስጠንቀቂያ፦ የሙከራ ባህሪያት አሉ!</translation>
<translation id="3810973564298564668">አቀናብር</translation>
<translation id="382518646247711829">ተኪ አገልጋይ የሚጠቀሙ ከሆኑ...</translation>
<translation id="3828924085048779000">ባዶ የይለፍ ሐረግ አይፈቀድም።</translation>
@@ -543,11 +551,11 @@
<translation id="3858027520442213535">ቀን እና ሰዓትን አዘምን</translation>
<translation id="3884278016824448484">የሚጋጭ የመሣሪያ ለዪ</translation>
<translation id="3885155851504623709">ፓሪሽ</translation>
-<translation id="3886446263141354045">ይህን ጣቢያ የመድረስ ጥያቄዎ ለ<ph name="NAME" /> ተልኳል</translation>
<translation id="3890664840433101773">ኢሜይል ያክሉ</translation>
<translation id="3901925938762663762">ካርዱ አገልግሎት ጊዜው አብቅቷል</translation>
<translation id="3906600011954732550">B5-ተጨማሪ</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">ከCVC ይልቅ WebAuthnን ይጠቀሙ?</translation>
<translation id="3946209740501886391">ሁልጊዜ በዚህ ጣቢያ ላይ ጠይቅ</translation>
<translation id="3949571496842715403">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት ዕውቅና ማረጋገጫው የርዕሰ ጒዳይ አማራጭ ስሞችን አይጠቅስም። ይህ በተሳሳተ ውቅረት የተከሰተ ወይም አጥቂ የእርስዎን ግንኙነት አቋርጦ እየገባ ስለሆነ ሊሆን ይችላል።</translation>
<translation id="3949601375789751990">የአሰሳ ታሪክዎ እዚህ ይመጣል</translation>
@@ -558,11 +566,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ምንም}=1{ከ1 ጣቢያ }one{ከ# ጣቢያዎች }other{ከ# ጣቢያዎች }}</translation>
<translation id="397105322502079400">በማስላት ላይ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ታግዷል</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> Chromeየድርጅት ጥቃት ስጋት ጥበቃ በእርስዎ አሳሽ ላይ አንቅቷል። Chrome የድርጅት ጥቃት ስጋት ጥበቃ ወደ የእርስዎ አንዳንድ ውሂብ መዳረሻ አለው።</translation>
<translation id="3987940399970879459">ከ1 ሜባ ያነሰ</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 ድረ-ገጽ በአቅራቢያ}one{# ድረ-ገጾች በአቅራቢያ}other{# ድረ-ገጾች በአቅራቢያ}}</translation>
<translation id="4030383055268325496">&amp;አክልን ቀልብስ</translation>
<translation id="4032320456957708163">የእርስዎ አሳሽ በ<ph name="ENROLLMENT_DOMAIN" /> የሚተዳደር ነው</translation>
-<translation id="4034375457890803692">የከፈቱት አገናኝ ወደ እርስዎ ብዙውን ጊዜ የማይጎበኙት ጣቢያ ይሄዳል። እርስዎን ግራ ለማጋባት ይሞክር ይሆናል።</translation>
<translation id="4058922952496707368">ቁልፍ «<ph name="SUBKEY" />»፦ <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (የደብዳቤ ፖስታ)</translation>
<translation id="4067947977115446013">የሚሰራ አድራሻ ያስገቡ</translation>
@@ -575,6 +583,7 @@
<translation id="4103249731201008433">የመሣሪያ መለያ ቁጥር ልክ ያልሆነ ነው</translation>
<translation id="410351446219883937">ራስ-አጫውት</translation>
<translation id="4103763322291513355">የተከለከሉ የዩ አር ኤሎች ዝርዝር እና ሌሎች በስርዓት አስተዳዳሪዎ አስገዳጅነት የተሰጣቸው መመሪያዎችን ለማየት &lt;strong&gt;chrome://policy&lt;/strong&gt;ን ይጎብኙ።</translation>
+<translation id="4108231218301530806">ይህን ካርድ በሚቀጥለው ጊዜ ለማረጋገጥ የጣት አሻራ ይጠቀሙ።</translation>
<translation id="4110652170750985508">የእርስዎን ክፍያ ይገምግሙ</translation>
<translation id="4112140312785995938">ወደኋላ ፈልግ</translation>
<translation id="4116663294526079822">ሁልጊዜ በዚህ ጣቢያ ላይ ፍቀድ</translation>
@@ -589,6 +598,7 @@
<translation id="4171400957073367226">መጥፎ የማረጋገጫ ፊርማ</translation>
<translation id="4173315687471669144">ፉልስካፕ</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> ተጨማሪ ንጥል}one{<ph name="ITEM_COUNT" /> ተጨማሪ ንጥሎች}other{<ph name="ITEM_COUNT" /> ተጨማሪ ንጥሎች}}</translation>
+<translation id="4176463684765177261">ተሰናክሏል</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">በሚቀጥለው ጊዜ በበለጠ ፍጥነት ለመክፈል ካርድዎን እና የማስከፈያ አድራሻዎን ወደ Google መለያዎ ያክሉ።</translation>
<translation id="4196861286325780578">&amp;ውሰድን ድገም</translation>
@@ -625,6 +635,7 @@
<translation id="4277028893293644418">የይለፍ ቃል ዳግም አቀናብር</translation>
<translation id="4279811152705618813">የእርስዎ <ph name="DEVICE_TYPE" /> በ<ph name="ENROLLMENT_DOMAIN" /> የሚተዳደር ነው</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ይህ ካርድ በእርስዎ የGoogle መለያ ላይ ተቀምጧል}one{እነዚህ ካርዶች በእርስዎ የGoogle መለያ ላይ ተቀምጠዋል}other{እነዚህ ካርዶች በእርስዎ የGoogle መለያ ላይ ተቀምጠዋል}}</translation>
+<translation id="428847186335018806">በ Chrome ውስጥ ያወረዱት ወይም የሰቀሉት ፋይሎችን ይቃኙ።</translation>
<translation id="42981349822642051">ዘርጋ</translation>
<translation id="4302965934281694568">Chou3 (የደብዳቤ ፖስታ)</translation>
<translation id="4305817255990598646">ቀይር</translation>
@@ -654,7 +665,6 @@
<translation id="4435702339979719576">የፖስታ ካርድ)</translation>
<translation id="443673843213245140">የተኪ መጠቀም ተሰናክሏል ግን ግልጽ የሆነ የተኪ ውቅር ተገልጿል።</translation>
<translation id="445100540951337728">ተቀባይነት ያላቸው ዴቢት ካርዶች</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> አጠራጣሪ ባህሪ</translation>
<translation id="4466881336512663640">የቅጽ ለውጦች ይጠፋሉ። እርግጠኛ ነዎት መቀጠል ይፈልጋሉ?</translation>
<translation id="4477350412780666475">ቀጣይ ትራክ</translation>
<translation id="4482953324121162758">ይህ ጣቢያ አይተረጎምም።</translation>
@@ -681,6 +691,7 @@
<translation id="4594403342090139922">&amp;ሰርዝን ቀልብስ</translation>
<translation id="4597348597567598915">መጠን 8</translation>
<translation id="4600854749408232102">C6/C5 (የደብዳቤ ፖስታ)</translation>
+<translation id="464342062220857295">ባህሪያትን ይፈልጉ</translation>
<translation id="4646534391647090355">አሁን ወደዚያ ውሰደኝ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት እውቅና ማረጋገጫው ስህተቶች አሉበት። ይሄ በተሳሳተ አወቃቀር ወይም አንድ አጥቂ ግንኙነትዎን በመጥለፉ የተከሰተ ሊሆን ይችላል።</translation>
@@ -689,7 +700,6 @@
<translation id="4691835149146451662">ስነ-ሕንጻ-A (የደብዳቤ ፖስታ)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">የእርስዎ ግንኙነት ተቋርጧል</translation>
-<translation id="471880041731876836">ይህን ጣቢያ የመጎብኘት ፈቃድ የለዎትም</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />የWindows አውታረ መረብ መመርመሪያን በማሄድ ላይ<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">መምሪያዎችን ዳግም ጫን</translation>
<translation id="4728558894243024398">መድረክ</translation>
@@ -717,7 +727,6 @@
<translation id="4816492930507672669">ገጹን አመጣጥን</translation>
<translation id="4850886885716139402">አሳይ</translation>
<translation id="4854362297993841467">የማድረሻ ዘዴው አይገኝም። የተለየ ዘዴ ይሞክሩ።</translation>
-<translation id="4858792381671956233">ይህን ገጽ መጎብኘት ችግር ካለው ወላጆችዎንጠይቀዋል</translation>
<translation id="4864052566555297930">ጠቃሚ የጥንቃቄ ምክር፦</translation>
<translation id="4876188919622883022">የተቃለለ እይታ</translation>
<translation id="4876305945144899064">ምንም የተጠቃሚ ስም የለም</translation>
@@ -741,7 +750,9 @@
<translation id="4974590756084640048">ማስጠንቀቂያዎችን ዳግም አንቃ</translation>
<translation id="4984339528288761049">Prc5 (የደብዳቤ ፖስታ)</translation>
<translation id="4989163558385430922">ሁሉንም ይመልከቱ</translation>
+<translation id="4989542687859782284">አይገኝም</translation>
<translation id="4989809363548539747">ይህ ተሰኪ አይደገፍም</translation>
+<translation id="4995216769782533993">ከዚህ ጣቢያ ጋር የእርስዎን የካርድ ዝርዝሮች ለማጋራት የደህንነት ኮዱን ያረጋግጡ</translation>
<translation id="5002932099480077015">የነቃ እንደሆነ Chrome ለበለጠ ፈጣን ቅጽ አሞላል ሲባል በዚህ መሳሪያ ላይ ያለው የካርድዎን ቅጂ ያከማቻል።</translation>
<translation id="5015510746216210676">የማሽን ስም፦</translation>
<translation id="5017554619425969104">እርስዎ የቀዱት ጽሑፍ</translation>
@@ -770,6 +781,7 @@
<translation id="5115216390227830982">የአውሮፓ-Edp</translation>
<translation id="5115563688576182185">(64-ቢት)</translation>
<translation id="5125394840236832993">B-ፕላስ</translation>
+<translation id="5126510351761255129">የእርስዎን ኮርድ ያረጋግጡ</translation>
<translation id="5135404736266831032">አድራሻዎችን ያቀናብሩ...</translation>
<translation id="5138227688689900538">ያነሰ አሳይ</translation>
<translation id="5141240743006678641">የተመሳሰሉ የይለፍ ቃላት ከGoogle ምስክርነቶችዎ ጋር ያመሳስሉ</translation>
@@ -796,6 +808,7 @@
<translation id="5251803541071282808">ደመና</translation>
<translation id="5252000469029418751">C7 (የደብዳቤ ፖስታ)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">በመላው ስርዓት ላይ የሚተገበሩ ባህሪያት በባለቤቱ ብቻ ነው ሊዋቀሩ የሚችሉት፦ <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">ማስጠንቀቂያ፦ ይህ መመሪያ ሊዋሃዱ የሚችሉ የመዝገበ-ቃላት መመሪያዎች አካል ስላልሆነ በPolicyDictionaryMultipleSourceMergeList መመሪያ ላይ በተገለጸው መሠረትት አልተዋሃደም።</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">ጨርስ</translation>
@@ -819,7 +832,6 @@
<translation id="536296301121032821">የመምሪያ ቅንብሮችን ማከማቸት አልተሳካም</translation>
<translation id="5371425731340848620">ካርድ ያዘምኑ</translation>
<translation id="5377026284221673050">«የእርስዎ ሰዓት ቀርቷል» ወይም «የእርስዎ ሰዓት ቀድሟል» ወይም «&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;»</translation>
-<translation id="5377179979757081683">ይህ ገጽ እርስዎን ለማታለል፣ የግል መረጃን ለመስረቅ ወይም መሣሪያዎን ለመጉዳት ሊሞክር ይችላል። የግል መረጃ ሲያስገቡ ወይም የወረዱ ፋይሎችን ሲከፍቱ ይጠንቀቁ።</translation>
<translation id="5384855140246857529">ካርዶችዎን በሁሉም መሣሪያዎችዎ ላይ ለመጠቀም በመለያ ይግቡና ስምረትን ያብሩ።</translation>
<translation id="5386426401304769735">የዚህ ጣቢያ የዕውቅና ማረጋገጫ ሰንሰለቱ SHA-1 በመጠቀም የተፈረመ የዕውቅና ማረጋገጫን ያካትታል።</translation>
<translation id="538659543871111977">A4-ትር</translation>
@@ -833,6 +845,7 @@
<translation id="5457113250005438886">ልክ ያልሆነ</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ተጨማሪ}one{<ph name="CONTACT_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ተጨማሪ}other{<ph name="CONTACT_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ተጨማሪ}}</translation>
<translation id="5470861586879999274">&amp;አርትዕን ድገም</translation>
+<translation id="5473728911100096288">እነዚህን ባህሪያት በማንቃት በወደፊት ስሪቶች ላይ የሚጠፉ የተቋረጡ ባህሪያትን ይጠቀማሉ።</translation>
<translation id="5478437291406423475">B6/C4 (የደብዳቤ ፖስታ)</translation>
<translation id="5481076368049295676">ይህ ይዘት በእርስዎ መሣሪያ ላይ መረጃዎን የሚሰርቅ ወይም የሚሰርዝ አደገኛ ሶፍትዌርን ለመጫን ሊሞክር ይችል ይሆናል። <ph name="BEGIN_LINK" />የሆነው ሆኖ አሳይ<ph name="END_LINK" /></translation>
<translation id="54817484435770891">የሚሰራ አድራሻ ያስገቡ</translation>
@@ -856,7 +869,6 @@
<translation id="5570825185877910964">መለያን ጠብቅ</translation>
<translation id="5571083550517324815">ከዚህ አድራሻ ላይ መውሰድ አይቻልም። የተለየ አድራሻ ይምረጡ።</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 ጥቅም ላይ ያለ}one{# ጥቅም ላይ ያለ}other{# ጥቅም ላይ}})</translation>
-<translation id="5572851009514199876">Chrome እርስዎ ይህን ጣቢያ እንዲደርሱ የተፈቀደልዎ መሆኑን ወይም አለመሆኑን እንዲያረጋግጥ እባክዎ ይጀምሩና ወደ Chrome ይግቡ።</translation>
<translation id="5580958916614886209">የእርስዎን የአገልግሎት ማብቂያ ወር ይመልከቱ እና እንደገና ይሞክሩ</translation>
<translation id="5586446728396275693">ምንም የተቀመጡ አድራሻዎች የሉም</translation>
<translation id="5595485650161345191">አድራሻ አርትዕ</translation>
@@ -864,6 +876,7 @@
<translation id="560412284261940334">አስተዳደር አይደገፍም</translation>
<translation id="5605670050355397069">ሌጀር</translation>
<translation id="5607240918979444548">ስነ-ሕንጻ-C</translation>
+<translation id="5608165884683734521">ይህ ጣቢያ ሐሰተኛ ወይም አጭበርባሪ ሊሆን ይችላል። Chrome አሁኑኑ ትቶ መውጣትን ይመክራል።</translation>
<translation id="5610142619324316209">ግንኙነቱን መፈተሽ</translation>
<translation id="5610807607761827392">ካርዶችን እና አድራሻዎችን በ<ph name="BEGIN_LINK" />ቅንብሮች<ph name="END_LINK" /> ውስጥ ማቀናበር ይችላሉ።</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> እርስዎን በጣም ብዙ ጊዜ ወደ ሌላ ቦታ መርተዎታል።</translation>
@@ -887,11 +900,11 @@
<translation id="5720705177508910913">የአሁኑ ተጠቃሚ</translation>
<translation id="5728056243719941842">C5 (የደብዳቤ ፖስታ)</translation>
<translation id="5730040223043577876">Chrome የእርስዎን ይለፍ ቃል በሌሎች ጣቢያዎች ላይ ዳግም ከተጠቀሙበት እንደገና እንዲያዋቅሩት ይመክራል።</translation>
-<translation id="5732392974455271431">የእርስዎ ወላጆች እገዳውን ሊያነሱልዎ ይችላሉ</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{ካርድ በGoogle መለያዎ ውስጥ ያስቀምጡ}one{ካርዶችን ወደ የእርስዎ የGoogle መለያ ያስቀምጡ}other{ካርዶችን ወደ የእርስዎ የGoogle መለያ ያስቀምጡ}}</translation>
<translation id="5763042198335101085">ትክክለኛ የኢሜይል አድራሻ ያስገቡ</translation>
<translation id="5765072501007116331">የማድረሻ ዘዴዎችን እና መስፈርቶችን ለመመልከት አድራሻ ይምረጡ</translation>
<translation id="5778550464785688721">MIDI መሣሪያዎች ሙሉ ቁጥጥር</translation>
+<translation id="5781136890105823427">ሙከራ ነቅቷል</translation>
<translation id="578305955206182703">አምበር</translation>
<translation id="57838592816432529">ድምጽ ይዝጉ</translation>
<translation id="5784606427469807560">የእርስዎን ካርድ ማረጋገጥ ላይ አንድ ችግር ነበር። የበይነመረብ ግንኙነትዎን ይፈትሹት እና እንደገና ይሞክሩ።</translation>
@@ -908,13 +921,16 @@
<translation id="5860033963881614850">አጥፋ</translation>
<translation id="5863847714970149516">ከፊት ያለው ገጽ እርስዎን ገንዘብ ለማስከፈል ሊሞክር ይችላል</translation>
<translation id="5866257070973731571">ስልክ ቁጥር ያክሉ</translation>
+<translation id="5866898949289125849">እርስዎ የገንቢ መሣሪያዎች ገጽ እየተመለከቱ ነው</translation>
<translation id="5869405914158311789">ይህ ጣቢያ ሊደረስበት አይችልም</translation>
<translation id="5869522115854928033">የተቀመጡ የይለፍ ቃሎች</translation>
<translation id="5887400589839399685">ካርድ ተቀምጧል</translation>
<translation id="5893752035575986141">ክሬዲት ካርዶች ተቀባይነት አላቸው።</translation>
+<translation id="5895138241574237353">እንደገና ጀምር</translation>
<translation id="5901630391730855834">ቢጫ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ሰምሯል)</translation>
<translation id="5916664084637901428">በርቷል</translation>
+<translation id="59174027418879706">ነቅቷል</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">ወደ Google መለያ ካርድ ይቀመጥ?</translation>
<translation id="5922853866070715753">በቃ ሊያልቅ ነው</translation>
@@ -948,6 +964,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">በሁሉም የእርስዎ መሣሪያዎች ላይ የእርስዎ ኮርዶች ጥቅም ላይ ይዋሉ?</translation>
<translation id="6059925163896151826">የዩኤስቢ መሣሪያዎች</translation>
+<translation id="6060009363608157444">ልክ ያልሆነ የDnsOverHttps ሁነታ።</translation>
<translation id="6080696365213338172">በአስተዳዳሪ የቀረበ የእውቅና ማረጋገጫ በመጠቀም ይዘት ደርሰዋል። ለ<ph name="DOMAIN" /> የሚያቀርቡት ውሂብ በአስተዳዳሪዎ ሊያዝ ይችላል።</translation>
<translation id="6094273045989040137">አብራራ</translation>
<translation id="610911394827799129">የእርስዎ Google መለያ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> ላይ ሌሎች የአሰሳ ታሪክ ዓይነቶች ሊኖረው ይችላል።</translation>
@@ -996,13 +1013,12 @@
<translation id="6404511346730675251">ዕልባት አርትዕ</translation>
<translation id="6406765186087300643">C0 (የደብዳቤ ፖስታ)</translation>
<translation id="6410264514553301377">የ<ph name="CREDIT_CARD" /> የአገልግሎት ማብቂያ ቀን እና ሲቪሲ ያስገቡ</translation>
-<translation id="6414888972213066896">ይህን ጣቢያ መጎብኘት ችግር ካለው ወላጅዎን ጠይቀዋል</translation>
<translation id="6415778972515849510">Chromium የGoogle መለያዎን እንዲጠብቁ እና የይለፍ ቃልዎን እንዲቀይሩት ያግዘዎታል።</translation>
-<translation id="6417515091412812850">የእውቅና ማረጋገጫው ተሽሮ እንደሆነ ማረጋገጥ አልተቻለም።</translation>
<translation id="6431585503458005759">አታከማች</translation>
<translation id="6433490469411711332">የዕውቂያ መረጃን ያርትዑ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ማገናኘት አሻፈረኝ ብሏል።</translation>
<translation id="6434309073475700221">አስወግድ</translation>
+<translation id="6435221585574090192">በ Chrome የድርጅት ጥቃት ስጋት ጥበቃ ከእርስዎ አስተዳዳሪ ጋር ጠቁም ስለ ተደረገባቸው የደህንነት ክስተቶች ውሂብን ያጋሩ። እነዚህ የገጽ ዩአርኤሎችን፣ የፋይል ስም እና የፋይል ዲበ ውሂብ፣ የእርስዎ መሣሪያ የተጠቃሚ ስም እና የ Chrome ተጠቃሚ ስም ሊያካትት ይችላል።</translation>
<translation id="6440503408713884761">የተተወ</translation>
<translation id="6446163441502663861">ካሁ (የደብዳቤ ፖስታ)</translation>
<translation id="6446608382365791566">ተጨማሪ መረጃ ያክሉ</translation>
@@ -1011,20 +1027,19 @@
<translation id="6465306955648956876">የይለፍ ቃላትን ያቀናብሩ...</translation>
<translation id="647261751007945333">የመሣሪያ መምሪያዎች</translation>
<translation id="6476284679642588870">የመክፈያ ዘዴዎችን ያቀናብሩ</translation>
-<translation id="6477321094435799029">Chrome በዚህ ገጽ ላይ ያልተለመደ ኮድ አግኝቷል፣ እና የእርስዎን የግል መረጃ (ለምሳሌ፦ የይለፍ ቃላት፣ ስልክ ቁጥሮች እና ክሬዲት ካርዶች) ለመጠበቅ ሲባል አግዶታል።</translation>
<translation id="6489534406876378309">ድምስሶችን መስቀል ጀምር</translation>
<translation id="6499038740797743453">የይለፍ ቃል ዳግም ይቀናበር?</translation>
<translation id="6507833130742554667">ክሬዲት እና ዴቢት ካርዶች ተቀባይነት አላቸው።</translation>
<translation id="650855688985305916">አዎ፣ አአከማች</translation>
<translation id="6508722015517270189">Chromeን ዳግም ያስጀምሩት</translation>
<translation id="6517596291481585650">ማስጠንቀቂያ፦ ይህ መመሪያ ዝርዝር ስላልሆነ በመመሪያ በተገለጸው መሠረት እንደ ዝርዝር አልተዋሃደም።</translation>
+<translation id="6518133107902771759">አረጋግጥ</translation>
<translation id="6521745193039995384">ገባሪ አይደለም</translation>
<translation id="6529602333819889595">&amp;ሰርዝን ድገም</translation>
<translation id="6534179046333460208">የአካላዊ ድር ጥቆማዎች</translation>
<translation id="6545864417968258051">የብሉቱዝ ቅኝት</translation>
<translation id="6554795675067793129">የእርስዎ መለያ በ<ph name="ENROLLMENT_DOMAIN" /> ነው የሚተዳደረው።</translation>
<translation id="6556866813142980365">ድገም</translation>
-<translation id="6563469144985748109">የእርስዎ አስተዳዳሪ ገና አላጸደቁትም</translation>
<translation id="6569060085658103619">የቅጥያ ገጽ እየተመለከቱ ነው</translation>
<translation id="6578796323535178455">C2 (የደብዳቤ ፖስታ)</translation>
<translation id="6579990219486187401">ፈዛዛ ሮዝ</translation>
@@ -1042,11 +1057,13 @@
<translation id="6643016212128521049">አጽዳ</translation>
<translation id="6644283850729428850">ይህ መመሪያ ተቋርጧል።</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{ምንም}=1{ከ1 ጣቢያ (ከእርስዎ የGoogle መለያ ዘግተው እንዲወጡ አይደረጉም)}one{ከ# ጣቢያዎች (ከእርስዎ የGoogle መለያ ዘግተው እንዲወጡ አይደረጉም)}other{ከ# ጣቢያዎች (ከእርስዎ የGoogle መለያ ዘግተው እንዲወጡ አይደረጉም)}}</translation>
+<translation id="6652101503459149953">Windows Helloን ይጠቀሙ</translation>
<translation id="6657585470893396449">የይለፍ ቃል፦</translation>
<translation id="6670613747977017428">ወደ ደህንነት ተመለስ።</translation>
<translation id="6671697161687535275">የአስተያየት ጥቆማ ከChromium ይወገድ?</translation>
<translation id="6685834062052613830">ዘግተው ይውጡ እና ቅንብርን ያጠናቅቁ</translation>
<translation id="6689271823431384964">በመለያ ስለገቡ Chrome ካርዶችዎን በGoogle መለያዎ ሊያስቀምጥልዎ እየጠየቀ ነው። ይህን ባህሪ በቅንብሮች ውስጥ መቀየር ይችላሉ። የካርድ ያዢው ስም ከመለያዎ ነው የመጣው።</translation>
+<translation id="6707256370811247129">በ Chrome ውስጥ ያወረዱዋቸውን ወይም የሰቀሏቸውን መሸጎጫ እና ፋይሎች ይዘቶችን ይቅረጹ።</translation>
<translation id="6710213216561001401">ቀዳሚ</translation>
<translation id="6710594484020273272">&lt;የፍለጋ ቃል ይተይቡ&gt;</translation>
<translation id="671076103358959139">የምዝገባ ማስመሰያ፦</translation>
@@ -1054,10 +1071,10 @@
<translation id="6738516213925468394">የእርስዎ ውሂብ በ<ph name="TIME" /> ላይ በእርስዎ <ph name="BEGIN_LINK" />የስምረት ይለፍ ሐረግ<ph name="END_LINK" /> ተመስጥሯል። ስምረትን ለመጀመር ያስገቡት።</translation>
<translation id="674375294223700098">ያልታወቀ የአገልጋይ እውቅና ማረጋገጫ ስህተት።</translation>
<translation id="6744009308914054259">ግንኙነትን እየተጠባበቁ ሳሉ የመስመር ውጪ ጽሑፎችን ለማንበብ ውርዶችን መጎብኘት ይችላሉ።</translation>
+<translation id="6747611005629681221">ማስጠንቀቂያ፦ ከፊት የተቋረጡ ባህሪያት አሉ!</translation>
<translation id="6753269504797312559">የመምሪያ እሴት</translation>
<translation id="6757797048963528358">የእርስዎ መሣሪያ ተኝቷል።</translation>
<translation id="6768213884286397650">ሃጋኪ (ፖስታ ካርድ)</translation>
-<translation id="6778737459546443941">የእርስዎ ወላጅ ገና አላጸደቁትም</translation>
<translation id="67862343314499040">ወይን ጠጅ</translation>
<translation id="6786747875388722282">ቅጥያዎች</translation>
<translation id="6790428901817661496">አጫውት</translation>
@@ -1065,6 +1082,7 @@
<translation id="681021252041861472">የሚያስፈልግ መስክ</translation>
<translation id="6810899417690483278">የብጁነት መታወቂያ</translation>
<translation id="6825578344716086703">እርስዎ <ph name="DOMAIN" />ን ለመድረስ ሞክረዋል፣ ነገር ግን አገልጋዩ ደካማ የፊርማ ስልተ-ቀመር (እንደ SHA-1 ያለ) በመጠቀም የተፈረመ የዕውቅና ማረጋገጫ ነው ያቀረበው። ይህ ማለት አገልጋዩ ያቀረበው የደህንነት ምስክርነቶች የተጭበረበሩ ሊሆኑ ይችላሉ፣ እናም አገልጋዩ እርስዎ የሚጠብቁት አገልጋይ ላይሆን ይችላል (ከአጥቂ ጋር እየተገናኙ ሊሆን ይችላል)።</translation>
+<translation id="6826370046007623921">የውሂብ መጥፋትን መከላከያ</translation>
<translation id="6831043979455480757">መተርጎም</translation>
<translation id="6839929833149231406">አካባቢ</translation>
<translation id="6852204201400771460">መተግበሪያ ዳግም ይጫን?</translation>
@@ -1077,7 +1095,6 @@
<translation id="6891596781022320156">የመመሪያ ደረጃ አይደገፍም።</translation>
<translation id="6895330447102777224">የእርስዎ ካርድ ተረጋግጧል</translation>
<translation id="6897140037006041989">የተጠቀሚ ተወካይ</translation>
-<translation id="6903319715792422884">አንዳንድ <ph name="BEGIN_WHITEPAPER_LINK" />የሥርዓት መረጃ እና የገጽ ይዘት<ph name="END_WHITEPAPER_LINK" />ን ወደ Google በመላክ የጥንቃቄ አሰሳን ለማሻሻል እንዲቻል ያግዙ።<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ተጠቃሚ፦</translation>
<translation id="6934672428414710184">ይህ ስም ከእርስዎ Google መለያ የተገኘ ነው</translation>
<translation id="6944692733090228304">በ<ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ወደ የማይተዳደር ጣቢያ ላይ የእርስዎን የይለፍ ቃል አስገብተዋል። ለእርስዎ መለያ ጥበቃ ለማድረግ፣ በሌሎች መተግበሪያዎች እና ጣቢያዎች ላይ የእርስዎን የይለፍ ቃል ዳግም አይጠቀሙ።</translation>
@@ -1122,6 +1139,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ተጨማሪ}one{<ph name="PAYMENT_METHOD_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ተጨማሪ}other{<ph name="PAYMENT_METHOD_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ተጨማሪ}}</translation>
<translation id="7153618581592392745">ፈዘዝ ያለ ወይን ጠጅ</translation>
<translation id="717330890047184534">የGaia መታወቂያ፦</translation>
+<translation id="7174545416324379297">ተዋህደዋል</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ተጨማሪ}one{<ph name="SHIPPING_OPTION_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ተጨማሪ}other{<ph name="SHIPPING_OPTION_PREVIEW" /> እና <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ተጨማሪ}}</translation>
<translation id="7177397715882417099">የሚሄዱበት አገልጋይ <ph name="ORIGIN" /> ለጠየቁ ሁሉ የደህንነት መመሪያ እንዲተገበር ጠይቋል። ነገር ግን መመሪያን ከማድረስ ይልቅ አሳሹን ወደ ሌላ ቦታ አዙሮታል፣ ይህም አሳሹ የ<ph name="SITE" /> ጥያቄዎን ከማሟላት ይከለክለዋል።</translation>
<translation id="7179323680825933600">የመክፈያ ዘዴዎችን አስቀምጥ እና ሙላ</translation>
@@ -1156,6 +1174,7 @@
<translation id="7320336641823683070">የግንኙነት እገዛ</translation>
<translation id="733354035281974745">የመሣሪያ አካባቢያዊ መለያ መሻር</translation>
<translation id="7334320624316649418">&amp;ማስተካከልን ድገም</translation>
+<translation id="7337706099755338005">በእርስዎ የመሣሪያ ስርዓት ላይ አይገኝም።</translation>
<translation id="733923710415886693">የአገልጋዩ የእውቅና ማረጋገጫ በእውቅና ማረጋገጫ ግልጽነት በኩል አልተገለጸም።</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">ከዚህ ጋር ግንኙነት አለው፦</translation>
@@ -1187,7 +1206,6 @@
<translation id="7440140511386898319">ከመስመር ውጪ ሆነው ሳለ ያስሱ</translation>
<translation id="7441627299479586546">የተሳሳተ የመምሪያ ርዕሰ ጉዳይ</translation>
<translation id="7442725080345379071">ፈዘዝ ያለ ብርትኳናማ</translation>
-<translation id="7444046173054089907">ይህ ጣቢያ ታግዷል</translation>
<translation id="7445762425076701745">የተገናኙት የአገልጋይ ማንነት ሙሉ ለሙሉ ሊረጋገጥ አልቻለም። ስሙ በአውታረ መረብዎ ውስጥ ብቻ ልክ ከሆነ አገልጋይ ጋር ነው የተገናኙት፣ እና ባለቤትነቱ በውጫዊ የእውቅና ማረጋገጫ ሊረጋገጥ አይችልም። አንዳንድ የእውቅና ማረጋገጫ ባለስልጣናት ይሁን ብለው ለእነዚህ ስሞች የእውቅና ማረጋገጫዎች መስጠታቸው የማይቀር እንደመሆኑ መጠን፣ ከአጥቂ ሳይሆን ከታሰበው ድር ጣቢያ ጋር መገናኘትዎን የሚረጋገጥበት ምንም መንገድ የለም።</translation>
<translation id="7451311239929941790">ስለዚህ ችግር <ph name="BEGIN_LINK" />ይበልጥ በመረዳት ላይ<ph name="END_LINK" />።</translation>
<translation id="7455133967321480974">ሁለንተናዊ ነባሪውን ተጠቀም (አግድ)</translation>
@@ -1209,9 +1227,9 @@
<translation id="7538364083937897561">A2 (የደብዳቤ ፖስታ)</translation>
<translation id="7542403920425041731">አንዴ ካረጋገጡ በኋላ የካርድ ዝርዝሮችዎ ለዚህ ጣቢያ ይጋራሉ።</translation>
<translation id="7542995811387359312">ይህ ቅጽ ደህንነቱ የተጠበቀ ግንኙነት ስለማይጠቀም የክሬዲት ካርድ ራስ-መሙላት ተሰናክሏል።</translation>
-<translation id="7543525346216957623">የእርስዎን ወላጅ ይጠይቁ</translation>
<translation id="7548892272833184391">የግንኙነት ስህተቶችን ያስተካክሉ</translation>
<translation id="7549584377607005141">ይህ ድረ-ገጽ በአግባቡ እንዲታይ ቀደም ብለው ያስገቡት ውሂብ ያስፈልገዋል። ይህን ውሂብ እንደገና መላክ ይችላሉ፣ ነገር ግን ይህን በማድረግዎ ይህ ገጽ ከዚህ በፊት ያከናወነው ማንኛውም እርምጃ ይደግማሉ።</translation>
+<translation id="7550637293666041147">የእርስዎ መሣሪያ ተጠቃሚ ስም እና የ Chrome ተጠቃሚ ስም</translation>
<translation id="7552846755917812628">የሚከተሉትን ጠቃሚ ምክሮች ይሞክሩ፦</translation>
<translation id="7554791636758816595">አዲስ ትር</translation>
<translation id="7564049878696755256">የ<ph name="ORG_NAME" /> መለያዎን መዳረሻ ሊያጡ ወይም የማንነት ስርቆት ሊያጋጥመዎት ይችላሉ። Chrome የይለፍ ቃልዎን አሁን እንዲቀይሩ ይመክራል።</translation>
@@ -1226,6 +1244,7 @@
<translation id="7610193165460212391">እሴት ከክልል <ph name="VALUE" /> ውጪ ነው።</translation>
<translation id="7613889955535752492">የሚያበቃበት ጊዜ፦ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">አስቀድሞ በተለየ የGoogle መለያዎ ይለፍ ቃል ስሪት የተመሰጠረ ውሂብ አለዎት። እባክዎ ከታች ያስገቡት።</translation>
+<translation id="7625784245512586808">Chrome የድርጅት ጥቃት ስጋት ጥበቃ</translation>
<translation id="7633909222644580952">የአፈጻጸም ውሂብ እና የብልሽት ሪፖርቶች</translation>
<translation id="7637571805876720304">ክሬዲት ካርድ ከChromium ይወገድ?</translation>
<translation id="7638605456503525968">ተከታታይ ወደቦች</translation>
@@ -1238,7 +1257,6 @@
<translation id="7668654391829183341">ያልታወቀ መሣሪያ</translation>
<translation id="7669271284792375604">በዚህ ጣቢያ ላይ ያሉ አጥቂዎች እርስዎ የአሰሳ ተሞክሮዎን ሊጎዱ (ለምሳሌ፦ መነሻ ገጽዎን በመቀየር ወይም በሚጎበኟቸው ጣቢያዎች ላይ ተጨማሪ ማስታወቂያዎችን በማሳየት) የሚችሉ ፕሮግራሞችን እንዲጭኑ ለማታለል ሊሞክሩ ይችላሉ።</translation>
<translation id="7676643023259824263">የቅንጥብ ሰሌዳ ጽሑፍ <ph name="TEXT" /> ይፈልጉ</translation>
-<translation id="7679176406634891508">መድረክ እና ክላውድ</translation>
<translation id="7681101578153515023">የፍለጋ ፕሮግራም ቀይር</translation>
<translation id="7682287625158474539">ዕቃን የማጓጓዝ ስራ</translation>
<translation id="7687186412095877299">የክፍያ ቅጾችን በተቀመጡ የመክፈያ ዘዴዎችዎ ይሞላቸዋል</translation>
@@ -1253,7 +1271,6 @@
<translation id="7723047071702270851">ካርትን ያርትዑ</translation>
<translation id="774634243536837715">አደገኛ ይዘት ታግዷል።</translation>
<translation id="7752995774971033316">አይቀናበርም</translation>
-<translation id="7755287808199759310">የእርስዎ ወላጅ እገዳውን ሊያነሱልዎ ይችላሉ</translation>
<translation id="7757555340166475417">ዳይ ፓ ካይ</translation>
<translation id="7758069387465995638">የኬላ ወይም የፀረ-ቫይረስ ሶፍትዌር ግንኙነቱን አግዶት ሊሆን ይችላል።</translation>
<translation id="7759163816903619567">የማሳያ ጎራ፦</translation>
@@ -1297,7 +1314,6 @@
<translation id="8004582292198964060">አሳሽ</translation>
<translation id="8009225694047762179">የይለፍ ቃላትን ያቀናብሩ</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ይህ ካርድ እና የክፍያ መጠየቂያ አድራሻው ይቀመጣሉ። በመለያ ወደ <ph name="USER_EMAIL" /> ሲገቡ ሊጠቀሙበት ይችላሉ።}one{እነዚህ ካርዶች እና የክፍያ መጠየቂያ አድራሻዎቻቸው ይቀመጣሉ። በመለያ ወደ <ph name="USER_EMAIL" /> ሲገቡ ሊጠቀሙባቸው ይችላሉ።}other{እነዚህ ካርዶች እና የክፍያ መጠየቂያ አድራሻዎቻቸው ይቀመጣሉ። በመለያ ወደ <ph name="USER_EMAIL" /> ሲገቡ ሊጠቀሙባቸው ይችላሉ።}}</translation>
-<translation id="8012647001091218357">በዚህ ጊዜ ላይ ወላጆችህን መድረስ አልቻልንም። እባክህ እንደገና ሞክር።</translation>
<translation id="8025119109950072390">በዚህ ጣቢያ ላይ ያሉ አጥቂዎች እርስዎ እንደ ሶፍትዌር መጫን ወይም የግል መረጃዎን (ለምሳሌ፦ የይለፍ ቃላት፣ ስልክ ቁጥሮች ወይም ክሬዲት ካርዶች) አሳልፈው እንዲሰጡ ያሉ አደገኛ ነገር እንዲያደርጉ ሊያታልሉዎት ይችላሉ።</translation>
<translation id="8034522405403831421">ይህ ገጽ በ<ph name="SOURCE_LANGUAGE" /> ነው። ወደ <ph name="TARGET_LANGUAGE" /> ይተርጎም?</translation>
<translation id="8035152190676905274">ብዕር</translation>
@@ -1308,6 +1324,7 @@
<translation id="8041940743680923270">ሁለንተናዊ ነባሪውን ተጠቀሙ (ጠይቅ)</translation>
<translation id="8042918947222776840">የመውሰጃ ዘዴ ይምረጡ</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» በአግባቡ አልተዋቀረም። «<ph name="SOFTWARE_NAME" />»ን ማራገፍ አብዛኛው ጊዜ ችግሩን ይፈታዋል። <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">ከአሁን ወዲህ የካርድ ደህንነት ኮድ ማስገባት አይኖርብዎት</translation>
<translation id="8066955247577885446">ይቅርታ፣ የሆነ ችግር ተፈጥሯል።</translation>
<translation id="8074253406171541171">10x13 (የደብዳቤ ፖስታ)</translation>
<translation id="8078141288243656252">በሚሸከርከርበት ጊዜ ማብራራት አይችልም</translation>
@@ -1338,6 +1355,7 @@
<translation id="8211406090763984747">ግንኙነት ደኅንነቱ የተጠበቀ ነው</translation>
<translation id="8218327578424803826">የተመደበ መገኛ አካባቢ፦</translation>
<translation id="8220146938470311105">C7/C6 (የደብዳቤ ፖስታ)</translation>
+<translation id="8220639454292072926">የድርጅት ሪፖርት አደራረግ</translation>
<translation id="8225771182978767009">ይህን ኮምፒውተር ያቀናበረው ሰው ይህን ጣቢያ ለማገድ መርጧል።</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />፣ <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">ገጹን ማንነት በማያሳውቅ አዲስ ትር ውስጥ ይክፈቱ</translation>
@@ -1392,24 +1410,24 @@
<translation id="8508648098325802031">የፍለጋ አዶ</translation>
<translation id="8522552481199248698">Chrome የGoogle መለያዎን እንዲጠብቁ እና የይለፍ ቃልዎን እንዲቀይሩት ያግዘዎታል።</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />የፈልጎ ማግኘት ችግርን ሪፖርት ማድረግ<ph name="END_ERROR_LINK" />፣ ወይም ደግሞ በእርስዎ ደህንነት ላይ ሊያስከትል የሚችለውን አደጋ ከተረዱ <ph name="BEGIN_LINK" />ይህን ደህንነቱ ያልተጠበቀ ጣቢያ መጎብኘት<ph name="END_LINK" /> ይችላሉ።</translation>
-<translation id="8543556556237226809">ጥያቄዎች አለዎት? የእርስዎን መገለጫ የሚቆጣጠረውን ግለሰብ ያነጋግሩ።</translation>
<translation id="8553075262323480129">የገጹ ቋንቋ ሊታወቅ ስላልቻለ ትርጉሙ አልተሳካም።</translation>
<translation id="8557066899867184262">CVC ከካርድዎ በስተጀርባ ላይ ይገኛል።</translation>
<translation id="8559762987265718583">የእርስዎ መሣሪያ ቀን (<ph name="DATE_AND_TIME" />) ልክ ስላልሆነ ወደ <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> የግል ግንኙነት መመስረት አይቻልም።</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> አጠራጣሪ ጣቢያ</translation>
<translation id="8564985650692024650">Chromium የእርስዎን የ<ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ይለፍ ቃል በሌሎች ጣቢያዎች ላይ ዳግም ከተጠቀሙበት እንደገና እንዲያዋቅሩት ይመክራል።</translation>
<translation id="8571890674111243710">ገጽ ወደ <ph name="LANGUAGE" /> በመተርጎም ላይ...</translation>
<translation id="858637041960032120">ስልክ ቁጥር ያክሉ
</translation>
-<translation id="859285277496340001">የእውቅና ማረጋገጫው ተሽሮ እንደሆነ የሚታይበት ምንም ስልት አይገልጽም።</translation>
<translation id="860043288473659153">የካርድ ያዢ ስም</translation>
<translation id="861775596732816396">መጠን 4</translation>
-<translation id="8620436878122366504">የእርስዎ ወላጆች ገና አላጸደቁትም</translation>
<translation id="8622948367223941507">የህግ-ተጨማሪ</translation>
<translation id="8625384913736129811">ይህን ካርድ ወደዚህ መሣሪያ አስቀምጥ</translation>
<translation id="8626112503828625890">የሒሳብ ማስከፈያ ዝርዝሮች በGoogle መለያ ላይ ይከማቹ?</translation>
+<translation id="8647750283161643317">ሁሉንም ወደ ነባሪ ዳግም አስጀምር</translation>
<translation id="8663226718884576429">የትዕዛዝ ማጠቃለያ፣ <ph name="TOTAL_LABEL" />፣ ተጨማሪ ዝርዝሮች</translation>
<translation id="8680536109547170164"><ph name="QUERY" />፣ መልስ፣ <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">PRC 16K</translation>
+<translation id="8688672835843460752">ይገኛል</translation>
<translation id="8703575177326907206">ከ<ph name="DOMAIN" /> ጋር ያለዎት ግንኙነት አልተመሰጠረም</translation>
<translation id="8718314106902482036">ክፍያ አልተጠናቀቀም</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />፣ <ph name="DESCRIPTION" />፣ የፍለጋ ጥቆማ ሐሳብ</translation>
@@ -1420,6 +1438,7 @@
<translation id="8738058698779197622">ደህንነቱ የተጠበቀ ግንኙነት ለመመስረት፣ የእርስዎ ሰዓት በትክክል መቀናበር ያስፈልገዋል። ይህን የሆነበት ምክንያት የድር ጣቢያዎች ራሳቸውን ለማሳወቅ የሚጠቀሙባቸው የምስክር ወረቀቶች የሚሰሩት ለተወሰኑ ክፍለ ጊዜያቶች ብቻ ስለሆነ ነው። የእርስዎ መሣሪያ ሰዓት ልክ እንዳለመሆኑ መጠን Chromium እነዚህን ምስክር ወረቀቶች ሊያረጋግጣቸው አይችልም።</translation>
<translation id="8740359287975076522">የ<ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;የዲኤንኤስ አድራሻ&lt;/abbr&gt; ሊገኝ አልተቻለም። ችግሩን በመመርመር ላይ።</translation>
<translation id="874846938927089722">ተቀባይነት ያላቸው የክሬዲት እና የቅድመ-ክፍያ ካርዶች</translation>
+<translation id="874918643257405732">ይህን ትር ዕልባት ያድርጉት</translation>
<translation id="8759274551635299824">ይህ ካርድ የአገልግሎት ጊዜው አብቅቷል</translation>
<translation id="8761567432415473239">Google የጥንቃቄ አሰሳ በቅርብ ጊዜ በ<ph name="SITE" /> ላይ <ph name="BEGIN_LINK" />ጎጂ ፕሮግርራሞችን አግኝቷል<ph name="END_LINK" />።</translation>
<translation id="8763927697961133303">የዩኤስቢ መሣሪያ</translation>
@@ -1449,6 +1468,7 @@
<translation id="8938939909778640821">ተቀባይነት ያላቸው የክሬዲት እና የቅድመ-ክፍያ ካርዶች</translation>
<translation id="8943282376843390568">ሎሚ ቀለም</translation>
<translation id="8957210676456822347">የተያዥ መግቢያ ፈቀዳ</translation>
+<translation id="8962950042226115166">አጠራጣሪ ጣቢያ</translation>
<translation id="8968766641738584599">ካርድ አስቀምጥ</translation>
<translation id="8971063699422889582">የአገልጋይ እውቅና ማረጋገጫ ጊዜው አልፎበታል።</translation>
<translation id="8975012916872825179">እንደ ስልክ ቁጥሮች፣ ኢሜይል አድራሻዎች እና የመላኪያ አድራሻዎች ያሉ መረጃዎችን ያካትታል</translation>
@@ -1471,24 +1491,24 @@
<translation id="9035022520814077154">የደህንነት ጥበቃ ስህተት</translation>
<translation id="9038649477754266430">ገጾችን ይበልጥ በፍጥነት ለመጫን የግመታ አገልግሎትን ይጠቀሙ</translation>
<translation id="9039213469156557790">በተጨማሪ፣ ይህ ገጽ ደህንነታቸው ያልተጠበቀ ሌሎች ንብረቶችን አካትቷል። እነዚህ ንብረቶች በሽግግር ወቅት በሌሎች ሊታዩ ይችላሉ፣ እናም የገጹን ባህሪ ለመለወጥ በአጥቂዎች ሊቀየሩ ይችላሉ።</translation>
+<translation id="9044359186343685026">የንክኪ መታወቂያን ተጠቀም</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619"><ph name="DOMAIN" />ን ለመድረስ ሞክረው ነበር፣ ግን አገልጋዩ ልክ ያልሆነ የእውቅና ማረጋገጫ ነው ያሳየው።</translation>
<translation id="9050666287014529139">የይለፍ ሐረግ</translation>
<translation id="9065203028668620118">አርትዕ</translation>
<translation id="9065745800631924235">የ<ph name="TEXT" /> ፍለጋ ከታሪክ</translation>
<translation id="9069693763241529744">በቅጥያ ታግዷል</translation>
-<translation id="9076283476770535406">ለአዋቂ ብቻ የሚሆን ይዘት ሊኖረው ይችላል</translation>
<translation id="9076630408993835509">ይህ አሳሽ በኩባንያ ወይም ሌላ ድርጅት አይተዳደርም። በዚህ መሣሪያ ላይ ያለ እንቅስቃሴ ከChrome ውጭ ሊተዳደር ይይችላል። <ph name="BEGIN_LINK" />የበለጠ ለመረዳት<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">ተጨማሪ መረጃ ያስፈልጋል</translation>
<translation id="9080712759204168376">የትዕዛዝ ማጠቃለያ</translation>
<translation id="9089260154716455634">ከሰዓታት ውጭ መመሪያ፦</translation>
<translation id="9095388113577226029">ተጨማሪ ቋንቋዎች...</translation>
+<translation id="9098981495403789647">የእርስዎ አስተዳዳሪ በእርስዎ አሳሽ ላይ የ Chrome የድርጅት ጥቃት ስጋት ጥበቃን አንቅቷል። Chrome የድርጅት ጥቃት ስጋት ጥበቃ ወደ የእርስዎ አንዳንድ ውሂብ መዳረሻ አለው።</translation>
<translation id="9103872766612412690"><ph name="SITE" /> የእርስዎን መረጃ ለመጠበቅ በመደበኝነት ምስጠራን ይጠቀማል። Chromium አሁን ከ<ph name="SITE" /> ጋር ለመገናኘት ሲሞክር ድር ጣቢያው ያልተለመዱ እና ትክክል ያልሆኑ ምስክርነቶችን መልሷል። ይህ አንድ አጥቂ <ph name="SITE" />ን አስመስሎ ለመቅረብ ሲሞክር ነው ወይም አንድ የWi-Fi መግቢያ ገጽ ግንኙነቱን ሲቋረጥ ሊከሰት ይችላል። Chromium ማንኛውም የውሂብ ልውውጥ ከመካሄዱ በፊት ግንኙነቱን ስላቋረጠው አሁንም የእርስዎ መረጃ ደህንነት የተጠበቀ ነው።</translation>
<translation id="9106062320799175032">የመክፈያ አድራሻ ያክሉ</translation>
<translation id="9114524666733003316">ካርድን በማረጋገጥ ላይ...</translation>
<translation id="9128870381267983090">ከአውታረ መረብ ጋር ይገናኙ</translation>
<translation id="9137013805542155359">የመጀመሪያውን አሳይ</translation>
-<translation id="9137248913990643158">ይህን መተግበሪያ ከመጠቀምዎ በፊት እባክዎ ይጀምሩና ወደ Chrome ይግቡ።</translation>
<translation id="9141013498910525015">አድራሻዎችን ያቀናብሩ</translation>
<translation id="9148088599418889305">የመላኪያ ዘዴ ይምረጡ</translation>
<translation id="9148507642005240123">&amp;አርትዕን ቀልብስ</translation>
diff --git a/chromium/components/strings/components_strings_ar.xtb b/chromium/components/strings/components_strings_ar.xtb
index c0cd3c211b9..6f8de6fe48d 100644
--- a/chromium/components/strings/components_strings_ar.xtb
+++ b/chromium/components/strings/components_strings_ar.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">إضافة الاسم الوارد في البطاقة</translation>
<translation id="1089439967362294234">تغيير كلمة المرور</translation>
+<translation id="1096545575934602868">يجب ألا يحتوي هذا الحقل على أكثر من <ph name="MAX_ITEMS_LIMIT" /> إدخال. سيتم تجاهل جميع الإدخالات الأخرى.</translation>
<translation id="109743633954054152">‏إدارة كلمات المرور في إعدادات Chrome</translation>
<translation id="1103523840287552314">ترجمة اللغة <ph name="LANGUAGE" /> دائمًا</translation>
<translation id="1107591249535594099">‏إذا تم وضع علامة على هذا الخيار، سيخزّن Chrome نسخة من هذه البطاقة على هذا الجهاز لتعبئة النماذج بشكل أسرع.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">الدخول إلى <ph name="BEGIN_LINK" />النسخة المخزنة مؤقتًا<ph name="END_LINK" /> من <ph name="URL" /></translation>
<translation id="1156303062776767266">يتمّ عرض ملف محلي أو مشترك.</translation>
<translation id="1158211211994409885">أغلق <ph name="HOST_NAME" /> الاتصال على نحو غير متوقع.</translation>
+<translation id="115926840831309955">‏يُرجى التحقق من رمز التحقق من البطاقة (CVC) ثم إعادة المحاولة، أو تعديل تاريخ انتهاء الصلاحية.</translation>
<translation id="1161325031994447685">‏إعادة الاتصال بـ Wi-Fi</translation>
<translation id="1165039591588034296">خطأ</translation>
<translation id="1175364870820465910">ط&amp;باعة...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">‏"هناك برامج على جهاز الكمبيوتر تمنع اتصال Chrome بالويب بأمان" (أجهزة الكمبيوتر المزوّدة بنظام التشغيل Windows فقط)</translation>
<translation id="1294154142200295408">صيغ سطر الأوامر</translation>
<translation id="129553762522093515">المغلقة حديثًا</translation>
+<translation id="1298536327547837046">فحص البرامج الضارة</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />جرّب محو ملفات تعريف الارتباط<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">الميزات المتوقفة</translation>
<translation id="1320233736580025032">‏Prc1 (مغلف)</translation>
<translation id="132301787627749051">البحث عن صورة الحافظة</translation>
<translation id="1323433172918577554">إظهار مزيد من الأقسام</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">‏جداول بيانات Google</translation>
<translation id="1527263332363067270">في انتظار الاتصال بالإنترنت…</translation>
<translation id="1529521330346880926">‏10x15 (مغلف)</translation>
+<translation id="1530707389502320859">‏يبدو الموقع الإلكتروني الذي حاولت الانتقال إليه مزيفًا. يحاكي المهاجمون أحيانًا المواقع الإلكترونية من خلال إجراء تغييرات بسيطة يصعب رؤيتها على عنوان URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">تعرض هذه الصفحة</translation>
<translation id="153384715582417236">هذا كل شيء الآن</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">نظام التشغيل</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">حجم المستند كبير جدًا بحيث تتعذّر إضافة تعليق توضيحي إليه</translation>
-<translation id="1721312023322545264">أنت بحاجة لإذن من <ph name="NAME" /> لزيارة هذا الموقع</translation>
<translation id="1721424275792716183">* هناك حقل مطلوب</translation>
<translation id="1727741090716970331">إضافة رقم بطاقة صالح</translation>
<translation id="1728677426644403582">أنت تعرض مصدر صفحة ويب</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">مواقع الويب التي تزورها والوقت المُستغرق في تصفُّحها</translation>
<translation id="1826516787628120939">حساب شيكات</translation>
<translation id="1834321415901700177">يحتوي هذا الموقع على برامج ضارة</translation>
+<translation id="1838374766361614909">محو البحث</translation>
<translation id="1839551713262164453">لقد تعذّر التحقق من قيم السياسة مع ظهور أخطاء.</translation>
<translation id="1842969606798536927">الدفع</translation>
<translation id="1871208020102129563">‏تم تعيين الخادم الوكيل لاستخدام الخوادم الوكيلة الثابتة وليس عنوان URL لنص برمجي pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">تصغير القائمة</translation>
<translation id="1898423065542865115">التصفية</translation>
<translation id="1914326953223720820">خدمة "فك الضغط"</translation>
+<translation id="1915697529809968049">‏هل تريد استخدام رقم التعريف باللمس بدلاً من رمز التحقق من البطاقة (CVC)؟</translation>
<translation id="1916770123977586577">لتطبيق الإعدادات المُحدَّثة على موقع الويب هذا، أعِد تحميل هذه الصفحة</translation>
<translation id="1919345977826869612">الإعلانات</translation>
<translation id="1919367280705858090">الحصول على مساعدة بخصوص رسالة خطأ محددة</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">إشارات <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">خطأ أثناء التسلسل</translation>
<translation id="1974060860693918893">الإعدادات المتقدّمة</translation>
+<translation id="1974883374937189061">‏يمكنك المساعدة على تحسين مستوى أمان Chrome من خلال إرسال <ph name="BEGIN_WHITEPAPER_LINK" />عناوين URL لبعض الصفحات التي تزورها ومعلومات محدودة للنظام وبعض أنواع محتوى الصفحات<ph name="END_WHITEPAPER_LINK" /> إلى Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">إصدار البرامج الثابتة</translation>
<translation id="1981206234434200693">‏محو بيانات سجلّ التصفُّح على Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{وتطبيق آخر}zero{و# تطبيق آخر}two{وتطبيقان (#) آخران}few{و# تطبيقات أخرى}many{و# تطبيقًا آخر}other{و# تطبيق آخر}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">أدخِل سنة تاريخ انتهاء صلاحية صحيحة</translation>
<translation id="2212735316055980242">تعذر العثور على السياسة</translation>
<translation id="2213606439339815911">جارٍ جلب الإدخالات...</translation>
+<translation id="2215727959747642672">تعديل الملف</translation>
<translation id="2218879909401188352">يمكن للمهاجمين الموجودين حاليًا على <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> تثبيت تطبيقات خطيرة تضرّ جهازك أو تضيف رسومًا إلى فاتورة الجوّال أو تسرق معلوماتك الشخصية. <ph name="BEGIN_LEARN_MORE_LINK" />مزيد من المعلومات<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">الاتصال بالإنترنت مقطوع</translation>
<translation id="2230458221926704099">إصلاح الاتصال باستخدام <ph name="BEGIN_LINK" />تطبيق بيانات التشخيص<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">إرسال الآن</translation>
+<translation id="2248949050832152960">‏استخدام WebAuthn</translation>
<translation id="225207911366869382">تم تجاهل القيمة لهذه السياسة.</translation>
<translation id="2257315177824333709">عفوًا، يتعذّر حفظ بطاقتك الآن.</translation>
<translation id="2262243747453050782">‏خطأ HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">‏عنوان URL للبحث غير صالح.</translation>
<translation id="2482878487686419369">الإشعارات</translation>
<translation id="248348093745724435">سياسات الأجهزة</translation>
-<translation id="2485387744899240041">أسماء المستخدمين لجهازك ومتصفِّحك</translation>
<translation id="2491120439723279231">تحتوي شهادة الخادم على أخطاء.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">‏محلل JSON اللغوي</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">الرجوع</translation>
<translation id="2503184589641749290">بطاقات السحب الآلي وبطاقات الدفع المسبق المقبولة</translation>
<translation id="2505268675989099013">حماية الحساب</translation>
+<translation id="2515335152965840738">تجاهل</translation>
<translation id="2515629240566999685">التحقّق من اتصال الإنترنت في منطقتك</translation>
<translation id="2523886232349826891">سيتم حفظ البطاقة على هذا الجهاز فقط</translation>
<translation id="2524461107774643265">إضافة مزيد من المعلومات</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">إرسال</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{ما من كلمات مرور}=1{كلمة مرور واحدة (للقائمة <ph name="DOMAIN_LIST" />)}=2{كلمتا مرور (للقائمة <ph name="DOMAIN_LIST" />)}few{# كلمات مرور (للقائمة <ph name="DOMAIN_LIST" />)}many{# كلمة مرور (للقائمة <ph name="DOMAIN_LIST" />)}other{# كلمة مرور (للقائمة <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">إغلاق علامات التبويب والتطبيقات الأخرى</translation>
-<translation id="267371737713284912">اضغط على <ph name="MODIFIER_KEY_DESCRIPTION" /> للتراجع</translation>
<translation id="2674170444375937751">هل تريد فعلًا حذف هذه الصفحات من السجل؟</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">الخروج</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">القيمة لا تطابق التنسيق.</translation>
<translation id="2705137772291741111">تعذر قراءة النسخة المحفوظة (المخزنة في ذاكرة التخزين المؤقت) لموقع الويب هذا.</translation>
<translation id="2709516037105925701">الملء التلقائي</translation>
-<translation id="2712173769900027643">طلب إذن</translation>
<translation id="2713444072780614174">أبيض</translation>
<translation id="2720342946869265578">المجاورة</translation>
<translation id="2721148159707890343">تم إرسال الطلب بنجاح</translation>
<translation id="2728127805433021124">شهادة الخادم موقّعة باستخدام خوارزمية توقيع ضعيفة.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />تشغيل بيانات تشخيص الاتصال<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">من خلال تفعيل هذه الميزات، قد تفقد بيانات المتصفِّح أو
+ يتعرّض أمانك وخصوصيتك للاختراق. يتم تطبيق الميزات المفعَّلة على جميع
+ مستخدمي هذا المتصفِّح.</translation>
<translation id="2735043616039983645">لهذه السياسة مصادر متعدّدة ذات قيم متضاربة.</translation>
<translation id="2738330467931008676">اختيار عنوان الاستلام من المستخدم</translation>
<translation id="2740531572673183784">موافق</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">تمت إعادة تعيين الاتصال.</translation>
<translation id="2788784517760473862">بطاقات الائتمان المقبولة</translation>
<translation id="2792012897584536778">أعدّ مشرفو هذا الجهاز شهادات الأمان التي قد تسمح لهم بالاطّلاع على محتوى مواقع الويب التي تزورها.</translation>
-<translation id="2794233252405721443">تم حظر الموقع</translation>
<translation id="2799020568854403057">يحتوي موقع الويب المقصود على تطبيقات ضارة</translation>
<translation id="2799223571221894425">إعادة تشغيل</translation>
<translation id="2803306138276472711">‏اكتشف التصفح الآمن من Google مؤخرًا <ph name="BEGIN_LINK" />برامج ضارة<ph name="END_LINK" /> على <ph name="SITE" />. أحيانًا تصاب مواقع الويب الآمنة في الوضع العادي ببرامج ضارة.</translation>
+<translation id="2815364696811431560">مغادرة الموقع الإلكتروني</translation>
<translation id="2824775600643448204">شريط العناوين والبحث</translation>
<translation id="2826760142808435982">تم تشفير الاتصال ومصادقته باستخدام <ph name="CIPHER" />، ويستخدم <ph name="KX" /> كآلية التبادل الرئيسية.</translation>
<translation id="2835170189407361413">محو النموذج</translation>
<translation id="2847118875340931228">فتح نافذة التصفُّح المتخفي</translation>
<translation id="2850739647070081192">دعوة (مغلف)</translation>
-<translation id="2851634818064021665">يلزمك الحصول على إذن لزيارة هذا الموقع</translation>
<translation id="2856444702002559011">قد يحاول المهاجمون سرقة معلوماتك من <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (مثل كلمات المرور أو الرسائل أو بطاقات الائتمان). <ph name="BEGIN_LEARN_MORE_LINK" />مزيد من المعلومات<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">هل تريد حفظ البطاقة؟</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">‏عند التمكين، سيُخزن Chromium نسخة من بطاقتك على هذا الجهاز لتعبئة النماذج بشكل أسرع.</translation>
<translation id="2985398929374701810">أدخِل عنوانًا صحيحًا</translation>
<translation id="2986368408720340940">طريقة الاستلام هذه غير متاحة. جرِّب طريقة أخرى.</translation>
+<translation id="2987034854559945715">لا تتوفر ميزات متطابقة.</translation>
<translation id="2991174974383378012">المشاركة مع مواقع الويب</translation>
<translation id="2991571918955627853">‏لا يمكنك زيارة <ph name="SITE" /> في الوقت الحالي لأن موقع الويب يستخدم HSTS. أخطاء الشبكة والهجمات عليها عادةً ما تكون مؤقتة، لذا ستعمل هذه الصفحة في وقت لاحق على الأرجح.</translation>
<translation id="3005723025932146533">عرض نسخة محفوظة</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">نوع السياسة غير صحيح</translation>
<translation id="3037605927509011580">عذرًا!</translation>
<translation id="3041612393474885105">معلومات الشهادة</translation>
+<translation id="3057676462092457419">‏لا يتوفر وضع DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> بعد، تم ضبط الوضع على <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">‏C9 (مغلف)</translation>
<translation id="3061707000357573562">خدمة رمز التصحيح</translation>
<translation id="3064966200440839136">ستتم مغادرة وضع التصفح المتخفي للدفع عبر تطبيق خارجي. هل تريد المتابعة؟</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> على <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">إلغاء الدفع</translation>
<translation id="3207960819495026254">تمت إضافتها إلى الإشارات المرجعية.</translation>
+<translation id="3209034400446768650">إمكانية تحصيل الصفحة للرسوم</translation>
<translation id="3225919329040284222">قدم الخادم شهادة لا تتطابق مع التوقعات المضمّنة. تم تضمين هذه التوقعات للحصول على مواقع ويب موثوقة وآمنة جدًا لتوفير الحماية لك.</translation>
<translation id="3226128629678568754">اضغط على زر إعادة التحميل لإعادة إرسال البيانات المطلوبة لتحميل الصفحة.</translation>
<translation id="3227137524299004712">الميكروفون</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">معلومات الإصدار حول جهازك ومتصفِّحك</translation>
<translation id="323107829343500871">‏أدخل رمز التحقق من البطاقة (CVC) لـ <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">الكشف دائمًا عن المحتوى المهم على هذا الموقع</translation>
-<translation id="3254409185687681395">وضع إشارة على هذه الصفحة</translation>
<translation id="3270847123878663523">تراجع عن إعادة الت&amp;رتيب</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">إضافة الاسم الوارد في البطاقة</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">إضافة عنوان إرسال الفواتير</translation>
<translation id="3324983252691184275">قرمزي</translation>
<translation id="3338095232262050444">آمن</translation>
-<translation id="3345135638360864351">تعذر إرسال طلبك للوصول إلى هذا الموقع إلى <ph name="NAME" />. يُرجى إعادة المحاولة مرة أخرى.</translation>
<translation id="3355823806454867987">تغيير إعدادات الخادم الوكيل...</translation>
<translation id="3361596688432910856">‏لن يحفظ <ph name="BEGIN_EMPHASIS" />Chrome<ph name="END_EMPHASIS" /> المعلومات التالية:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">الإخفاء (خيار متقدم)</translation>
<translation id="3467763166455606212">اسم حامل البطاقة مطلوب</translation>
<translation id="3468054117417088249">‏<ph name="TAB_SWITCH_SUFFIX" /> مفتوحة الآن، يمكنك الضغط على مفتاح Tab ثم مفتاح Enter للتبديل إلى علامة التبويب المفتوحة.</translation>
-<translation id="3479539252931486093">ألم تتوقَّع هذا؟ <ph name="BEGIN_LINK" />أطلِعنا على الأمر<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">ليس الآن</translation>
<translation id="3484560055331845446">‏قد لا تتمكّن من الوصول إلى حسابك على Google. لذا ينصح Chrome بتغيير كلمة مرورك الآن. وسيُطلَب منك تسجيل الدخول.</translation>
<translation id="3495081129428749620">البحث في الصفحة
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">لم نتمكن من الوصول إلى أحد والديك في الوقت الحالي. يُرجى إعادة المحاولة مرة أخرى.</translation>
<translation id="3512163584740124171">يتم تجاهل هذه السياسة بسبب سياسة أخرى من نفس مجموعة السياسة لها أولوية أعلى.</translation>
<translation id="3528171143076753409">شهادة الخادم غير موثوق فيها.</translation>
<translation id="3528485271872257980">بني داكن</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{عنصر واحد على الأقل على الأجهزة المتزامنة}=1{عنصر واحد (1) (وأكثر على الأجهزة المتزامنة)}two{عنصران (#) (وأكثر على الأجهزة المتزامنة)}few{# عناصر (وأكثر على الأجهزة المتزامنة)}many{# عنصرًا (وأكثر على الأجهزة المتزامنة)}other{# عنصر (وأكثر على الأجهزة المتزامنة)}}</translation>
<translation id="3539171420378717834">الاحتفاظ بنسخة من هذه البطاقة على هذا الجهاز</translation>
-<translation id="3556433843310711081">يمكن لمديرك إلغاء الحظر لك</translation>
<translation id="3566021033012934673">الاتصال بهذا الموقع الإلكتروني ليس خاصًا</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">تعرض صفحة مُضمنة في موقع <ph name="SITE" /></translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">‏يمكنك فتح الصفحة في نافذة جديدة للتصفح المتخفي (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">تم تسجيل تقرير الأعطال في <ph name="CRASH_TIME" />، وتم تحميله في <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">معلومات الشهادة</translation>
+<translation id="3701427423622901115">تمت الموافقة على إعادة الضبط.</translation>
<translation id="3704162925118123524">قد تتطلب الشبكة التي تستخدمها زيارة صفحة تسجيل الدخول.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">جارٍ التحميل...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">قد يخدعك المهاجمون على <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> لاتّخاذ إجراءات خطيرة، مثل تثبيت برامج معيّنة أو كشف معلوماتك الشخصية (مثل كلمات المرور أو أرقام الهاتف أو بطاقات الائتمان). <ph name="BEGIN_LEARN_MORE_LINK" />مزيد من المعلومات<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">تعذّرت الترجمة بسبب حدوث خطأ في الخادم.</translation>
<translation id="3759461132968374835">ليس لديك أي أعطال تم الإبلاغ عنها مؤخرًا. الأعطال التي حدثت عندما تم إيقاف الإبلاغ عن الأعطال لن تظهر هنا.</translation>
+<translation id="3760561303380396507">‏هل تريد استخدام Windows Hello بدلاً من رمز التحقق من البطاقة (CVC)؟</translation>
<translation id="3761718714832595332">إخفاء الحالة</translation>
<translation id="3765032636089507299">صفحة التصفح الآمن تحت الإنشاء.</translation>
<translation id="3778403066972421603">‏هل تريد حفظ هذه البطاقة في حسابك في Google وعلى هذا الجهاز؟</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">الحجم 16</translation>
<translation id="3797522431967816232">‏Prc3 (مغلف)</translation>
<translation id="3807873520724684969">تم حظر المحتوى الضار.</translation>
+<translation id="3808375843007691220">تحذير: الميزات التجريبية في انتظارك!</translation>
<translation id="3810973564298564668">إدارة محرّكات البحث</translation>
<translation id="382518646247711829">إذا كنت تستخدم خادمًا وكيلاً...</translation>
<translation id="3828924085048779000">غير مسموح باستخدام عبارة مرور فارغة.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">تحديث التاريخ والوقت</translation>
<translation id="3884278016824448484">معرف جهاز متضارب</translation>
<translation id="3885155851504623709">الأبرشية</translation>
-<translation id="3886446263141354045">تمّ إرسال طلبك للدخول إلى هذا الموقع إلى <ph name="NAME" /></translation>
<translation id="3890664840433101773">إضافة بريد إلكتروني</translation>
<translation id="3901925938762663762">انتهت صلاحية البطاقة</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">‏هل تريد استخدم WebAuthn بدلاً من رمز التحقق من البطاقة (CVC)؟</translation>
<translation id="3946209740501886391">السؤال دائمًا على موقع الويب هذا</translation>
<translation id="3949571496842715403">لم يتمكن هذا الخادم من إثبات أنه <ph name="DOMAIN" />؛ بل إن شهادة الأمان التابعة له لا تُحدّد الأسماء البديلة للمضيفات. وربما يكون السبب في ذلك وجود خطأ في التهيئة أو اعتراض أحد المهاجمين للاتصال.</translation>
<translation id="3949601375789751990">يظهر سجلّ التصفّح هنا</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{بدون}=1{من موقع واحد }two{من موقعين (#) }few{من # مواقع }many{من # موقعًا }other{من # موقع }}</translation>
<translation id="397105322502079400">جارٍ الحساب...</translation>
<translation id="3973234410852337861">تم حظر <ph name="HOST_NAME" /></translation>
+<translation id="3981540111851280311">‏فعَّل <ph name="ENROLLMENT_DOMAIN" /> "الحماية من التهديدات من خلال Chrome Enterprise" على متصفحك. تتضمن ميزة "الحماية من التهديدات من خلال Chrome Enterprise" إذن الوصول إلى بعض بياناتك.</translation>
<translation id="3987940399970879459">أقل من ميغابايت واحد</translation>
<translation id="40103911065039147">{URL_count,plural, =1{صفحة ويب واحدة مجاورة}zero{# صفحات ويب مجاورة}two{صفحتا ويب (#) مجاورتان}few{# صفحات ويب مجاورة}many{# صفحة ويب مجاورة}other{# صفحة ويب مجاورة}}</translation>
<translation id="4030383055268325496">تراجع عن الإ&amp;ضافة</translation>
<translation id="4032320456957708163">إدارة متصفِّحك من خلال <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">ينتقل الرابط الذي تم فتحه إلى موقع إلكتروني لا تزوره عادة. قد يكون ذلك لمحاولة إرباكك.</translation>
<translation id="4058922952496707368">المفتاح "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">‏C1 (مغلف)</translation>
<translation id="4067947977115446013">إضافة عنوان صالح</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">الرقم التسلسلي للجهاز غير صالح</translation>
<translation id="410351446219883937">التشغيل التلقائي</translation>
<translation id="4103763322291513355">‏انتقل إلى &lt;strong&gt;chrome://policy&lt;/strong&gt; لمشاهدة قائمة بعناوين URL المضافة إلى القائمة السوداء والسياسات الأخرى التي فرضها مشرف النظام.</translation>
+<translation id="4108231218301530806">استخدام بصمة الإصبع لإثبات ملكيتك لهذه البطاقة المرة القادمة.</translation>
<translation id="4110652170750985508">مراجعة الدفعة</translation>
<translation id="4112140312785995938">الانتقال إلى الخلف</translation>
<translation id="4116663294526079822">إلغاء الحظر دومًا على هذا الموقع</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">توقيع تحقق سيئ</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{عنصر (<ph name="ITEM_COUNT" />) آخر}zero{<ph name="ITEM_COUNT" /> عنصر آخر}two{عنصران (<ph name="ITEM_COUNT" />) آخران}few{<ph name="ITEM_COUNT" /> عناصر أخرى}many{<ph name="ITEM_COUNT" /> عنصرًا آخر}other{<ph name="ITEM_COUNT" /> عنصر آخر}}</translation>
+<translation id="4176463684765177261">غير مفعّل</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">‏للدفع بشكلٍ أسرع في المرة القادمة، عليك إضافة تفاصيل البطاقة المصرفية وعنوان إرسال الفواتير في حسابك على Google.</translation>
<translation id="4196861286325780578">إ&amp;عادة النقل</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">إعادة تعيين كلمة المرور</translation>
<translation id="4279811152705618813">يدير <ph name="ENROLLMENT_DOMAIN" /> الجهاز <ph name="DEVICE_TYPE" />.</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{‏تم حفظ هذه البطاقة في حسابك على Google}zero{‏تم حفظ هذه البطاقات في حسابك على Google}two{‏تم حفظ هاتين البطاقتين في حسابك على Google}few{‏تم حفظ هذه البطاقات في حسابك على Google}many{‏تم حفظ هذه البطاقات في حسابك على Google}other{‏تم حفظ هذه البطاقات في حسابك على Google}}</translation>
+<translation id="428847186335018806">‏فحص الملفات التي يتم تنزيلها أو تحميلها في Chrome</translation>
<translation id="42981349822642051">توسيع</translation>
<translation id="4302965934281694568">‏Chou3 (مغلف)</translation>
<translation id="4305817255990598646">تبديل</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">بطاقة بريدية)</translation>
<translation id="443673843213245140">تم إيقاف استخدام الخادم الوكيل ولكن تم تحديد تهيئة صريحة للخادم الوكيل.</translation>
<translation id="445100540951337728">بطاقات السحب الآلي المقبولة</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> سلوك مريب</translation>
<translation id="4466881336512663640">سيتم فقدان تغييرات النموذج. هل تريد فعلاً المتابعة؟</translation>
<translation id="4477350412780666475">المقطع الصوتي التالي</translation>
<translation id="4482953324121162758">لن تتم ترجمة هذا الموقع.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">تراجع عن الحذ&amp;ف</translation>
<translation id="4597348597567598915">الحجم 8</translation>
<translation id="4600854749408232102">‏C6/C5 (مغلف)</translation>
+<translation id="464342062220857295">ميزات البحث</translation>
<translation id="4646534391647090355">الانتقال الآن</translation>
<translation id="4668929960204016307">،</translation>
<translation id="467662567472608290">هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان تحتوي على أخطاء. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض اتصالك.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">‏Architecture-A (مغلف)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" />‏ <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">تم قطع اتصالك</translation>
-<translation id="471880041731876836">ليس لديك إذن لزيارة هذا الموقع</translation>
<translation id="4722547256916164131">‏<ph name="BEGIN_LINK" />تشغيل بيانات تشخيص شبكة Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">إعادة تحميل السياسات</translation>
<translation id="4728558894243024398">النظام الأساسي</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">احتواء ضمن الصفحة</translation>
<translation id="4850886885716139402">عرض</translation>
<translation id="4854362297993841467">طريقة التسليم هذه غير متاحة. جرِّب طريقة أخرى.</translation>
-<translation id="4858792381671956233">لقد سألت والديك ما إذا كانت زيارة هذا الموقع مناسبةً لك</translation>
<translation id="4864052566555297930">نصيحة الأمان:</translation>
<translation id="4876188919622883022">العرض المبسَّط</translation>
<translation id="4876305945144899064">ليس هناك اسم مستخدم</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">إعادة تفعيل التحذيرات</translation>
<translation id="4984339528288761049">‏Prc5 (مغلف)</translation>
<translation id="4989163558385430922">عرض الكل</translation>
+<translation id="4989542687859782284">التجارب غير المتاحة</translation>
<translation id="4989809363548539747">هذا المكوِّن الإضافي غير مدعوم</translation>
+<translation id="4995216769782533993">يُرجى التأكيد على رمز الأمان لمشاركة تفاصيل البطاقة مع الموقع الإلكتروني.</translation>
<translation id="5002932099480077015">‏إذا تم التمكين، سيخزن Chrome نسخة من بطاقتك على هذا الجهاز لملء النموذج بشكل أسرع.</translation>
<translation id="5015510746216210676">اسم الجهاز:</translation>
<translation id="5017554619425969104">النص الذي نسخته</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 بت)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">التحقق من بطاقتك</translation>
<translation id="5135404736266831032">إدارة العناوين...</translation>
<translation id="5138227688689900538">عرض أقل</translation>
<translation id="5141240743006678641">‏تشفير كلمات المرور المتزامنة باستخدام بيانات اعتماد Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">السحاب</translation>
<translation id="5252000469029418751">‏C7 (مغلف)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">لا يمكن ضبط الميزات التي تنطبق على مستوى النظام إلا من قِبل المالك: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">‏تحذير: لم يتم دمج هذه السياسة كما هو موضح في سياسة PolicyDictionaryMultipleSourceMergeList؛ لأنها ليست جزءًا من سياسات المعجم التي يمكن دمجها.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">‏مفتاح End</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">تعذّر تخزين إعدادات السياسة</translation>
<translation id="5371425731340848620">تحديث البطاقة</translation>
<translation id="5377026284221673050">‏""توقيت ساعتك متأخِّر" أو "توقيت ساعتك متقدِّم" أو "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">قد تحاول هذه الصفحة الاحتيال عليك أو سرقة معلوماتك الشخصية أو إلحاق الضرر بجهازك. يُرجى توخي الحذر عند إدخال معلوماتك الشخصية أو فتح الملفات التي تم تنزيلها.</translation>
<translation id="5384855140246857529">لاستخدام بطاقاتك على جميع الأجهزة، يُرجى تسجيل الدخول وتفعيل المزامنة.</translation>
<translation id="5386426401304769735">‏تتضمن سلسلة الشهادات لهذا الموقع شهادة موقعة باستخدام SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,7 @@
<translation id="5457113250005438886">غير صالحة</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> وجهة اتصال <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> أخرى}two{<ph name="CONTACT_PREVIEW" /> وجهتا اتصال (<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />) أخريان}few{<ph name="CONTACT_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> جهات اتصال أخرى}many{<ph name="CONTACT_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> جهة اتصال أخرى}other{<ph name="CONTACT_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> جهة اتصال أخرى}}</translation>
<translation id="5470861586879999274">إعادة الت&amp;حرير</translation>
+<translation id="5473728911100096288">إنّ الميزات التي تريد تفعيلها قديمة ولن تكون متوفرة في الإصدارات المستقبلية.</translation>
<translation id="5478437291406423475">‏B6/C4 (مغلف)</translation>
<translation id="5481076368049295676">قد يحاول هذا المحتوى تثبيت برامج خطيرة على جهازك تسرق معلوماتك أو تحذفها. <ph name="BEGIN_LINK" />عرض على أي حال<ph name="END_LINK" /></translation>
<translation id="54817484435770891">إضافة عنوان صالح</translation>
@@ -863,7 +878,6 @@
<translation id="5570825185877910964">حماية الحساب</translation>
<translation id="5571083550517324815">لا يمكن الاستلام من هذا العنوان. حدِّد عنوانًا آخر.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 قيد الاستخدام}zero{# قيد الاستخدام}two{# قيد الاستخدام}few{# قيد الاستخدام}many{# قيد الاستخدام}other{# قيد الاستخدام}})</translation>
-<translation id="5572851009514199876">‏يُرجى البدء وتسجيل الدخول إلى Chrome لكي يتأكد Chrome مما إذا كان مسموحًا لك الوصول إلى موقع الويب هذا أم لا.</translation>
<translation id="5580958916614886209">تحقق من شهر انتهاء الصلاحية وأعِد المحاولة مرة أخرى</translation>
<translation id="5586446728396275693">لا توجد عناوين محفوظة</translation>
<translation id="5595485650161345191">تعديل العنوان</translation>
@@ -871,6 +885,7 @@
<translation id="560412284261940334">الإدارة غير متوفرة</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">‏قد يكون هذا الموقع الإلكتروني مزيفًا أو احتياليًا. ينصح Chrome بمغادرة هذا الموقع الإلكتروني الآن.</translation>
<translation id="5610142619324316209">التحقق من الاتصال</translation>
<translation id="5610807607761827392">يمكنك إدارة البطاقات والعناوين في <ph name="BEGIN_LINK" />الإعدادات<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">أعاد <ph name="HOST_NAME" /> توجيهك مرات كثيرة جدًا.</translation>
@@ -894,11 +909,11 @@
<translation id="5720705177508910913">المستخدم الحالي</translation>
<translation id="5728056243719941842">‏C5 (مغلف)</translation>
<translation id="5730040223043577876">‏يُوصي Chrome بإعادة تحديد كلمة المرور في حال إعادة استخدامها في مواقع ويب أخرى.</translation>
-<translation id="5732392974455271431">يمكن لوالديك إلغاء الحظر لك</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{‏حفظ بطاقة واحدة في حسابك على Google}zero{‏حفظ بطاقات في حسابك على Google}two{‏حفظ بطاقتين في حسابك على Google}few{‏حفظ بطاقات في حسابك على Google}many{‏حفظ بطاقات في حسابك على Google}other{‏حفظ بطاقات في حسابك على Google}}</translation>
<translation id="5763042198335101085">أدخِل عنوان بريد إلكتروني صحيحًا</translation>
<translation id="5765072501007116331">لعرض طرق التسليم ومتطلباته، حدِّد عنوانًا</translation>
<translation id="5778550464785688721">‏التحكم الكامل في MIDI</translation>
+<translation id="5781136890105823427">تم تفعيل التجربة.</translation>
<translation id="578305955206182703">كهرمان</translation>
<translation id="57838592816432529">كتم الصوت</translation>
<translation id="5784606427469807560">حدثت مشكلة أثناء التأكد من بطاقتك. تحقق من اتصالك بالإنترنت وأعد المحاولة.</translation>
@@ -915,13 +930,16 @@
<translation id="5860033963881614850">غير مفعّل</translation>
<translation id="5863847714970149516">قد تحاول الصفحة التالية تحصيل رسوم منك</translation>
<translation id="5866257070973731571">إضافة رقم الهاتف</translation>
+<translation id="5866898949289125849">أنت تطّلع على صفحة أدوات المطوّرين.</translation>
<translation id="5869405914158311789">لا يمكن الوصول إلى موقع الويب هذا</translation>
<translation id="5869522115854928033">كلمات المرور المحفوظة</translation>
<translation id="5887400589839399685">تم حفظ البطاقة</translation>
<translation id="5893752035575986141">يتم قبول بطاقات الائتمان.</translation>
+<translation id="5895138241574237353">إعادة التشغيل</translation>
<translation id="5901630391730855834">أصفر</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (تمت المزامنة)</translation>
<translation id="5916664084637901428">مفعّل</translation>
+<translation id="59174027418879706">تم التمكين</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">‏هل تريد حفظ البطاقة في حساب Google؟</translation>
<translation id="5922853866070715753">أوشكْت على الانتهاء.</translation>
@@ -955,6 +973,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">هل تستخدم بطاقاتك على جميع أجهزتك؟</translation>
<translation id="6059925163896151826">‏أجهزة USB</translation>
+<translation id="6060009363608157444">‏وضع DnsOverHttps غير صحيح.</translation>
<translation id="6080696365213338172">لقد دخلت إلى المحتوى باستخدام شهادة وفرها المشرف. ويمكن أن يعترض المشرف طريق البيانات التي تقدمها إلى <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">إضافة تعليق توضيحي</translation>
<translation id="610911394827799129">‏قد يتضمّن حسابك على Google نماذج أخرى من سجلّ التصفّح على <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1022,12 @@
<translation id="6404511346730675251">تعديل الإشارة المرجعية</translation>
<translation id="6406765186087300643">‏C0 (مغلف)</translation>
<translation id="6410264514553301377">‏أدخِل تاريخ انتهاء الصلاحية ورمز التحقق من البطاقة (CVC) لـ <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">لقد سألت والديك ما إذا كانت زيارة هذا الموقع مناسبةً لك</translation>
<translation id="6415778972515849510">‏يمكن أن يساعدك Chromium على حماية حسابك على Google وتغيير كلمة المرور.</translation>
-<translation id="6417515091412812850">تعذر التحقق مما إذا كانت الشهادة قد تم إبطالها.</translation>
<translation id="6431585503458005759">عدم الحفظ</translation>
<translation id="6433490469411711332">تعديل معلومات الاتصال</translation>
<translation id="6433595998831338502">رفض <ph name="HOST_NAME" /> الاتصال.</translation>
<translation id="6434309073475700221">إلغاء</translation>
+<translation id="6435221585574090192">‏يمكنك مشاركة البيانات حول الأحداث الأمنية التي تم وضع علامة عليها من خلال "الحماية من التهديدات باستخدام Chrome Enterprise" مع المشرف. يمكن أن تتضمن هذه البيانات عناوين URL للصفحة واسم الملف والبيانات الوصفية للملف واسم المستخدم لجهازك واسم مستخدم Chrome.</translation>
<translation id="6440503408713884761">تم تجاهله</translation>
<translation id="6446163441502663861">‏Kahu (مغلف)</translation>
<translation id="6446608382365791566">إضافة مزيد من المعلومات</translation>
@@ -1018,20 +1036,19 @@
<translation id="6465306955648956876">إدارة كلمات المرور...</translation>
<translation id="647261751007945333">سياسات الأجهزة</translation>
<translation id="6476284679642588870">إدارة طرق الدفع</translation>
-<translation id="6477321094435799029">‏اكتشف Chrome وجود رمز غير عادي على هذه الصفحة وأجرى حظرًا لهذا الرمز لحماية معلوماتك الشخصية (على سبيل المثال، كلمات المرور، وأرقام الهواتف، وبطاقات الائتمان).</translation>
<translation id="6489534406876378309">بدء تحميل الأعطال</translation>
<translation id="6499038740797743453">هل تريد إعادة تعيين كلمة المرور؟</translation>
<translation id="6507833130742554667">يتم قبول بطاقات الائتمان وبطاقات السحب الآلي.</translation>
<translation id="650855688985305916">نعم، حفظ</translation>
<translation id="6508722015517270189">‏إعادة تشغيل Chrome</translation>
<translation id="6517596291481585650">تحذير: لم يتم دمج هذه السياسة كقائمة كما هو موضح بموجب السياسة؛ لأنها ليست قائمة.</translation>
+<translation id="6518133107902771759">تحقق</translation>
<translation id="6521745193039995384">غير مفعلة</translation>
<translation id="6529602333819889595">إعادة الح&amp;ذف</translation>
<translation id="6534179046333460208">اقتراحات الشبكة المادية</translation>
<translation id="6545864417968258051">البحث عن بلوتوث</translation>
<translation id="6554795675067793129">يدير <ph name="ENROLLMENT_DOMAIN" /> حسابك.</translation>
<translation id="6556866813142980365">إعادة</translation>
-<translation id="6563469144985748109">لم يوافق عليه مديرك حتى الآن</translation>
<translation id="6569060085658103619">أنت تعرض صفحة إضافة</translation>
<translation id="6578796323535178455">‏C2 (مغلف)</translation>
<translation id="6579990219486187401">وردي فاتح</translation>
@@ -1049,11 +1066,13 @@
<translation id="6643016212128521049">محو</translation>
<translation id="6644283850729428850">تم تجاهل هذه السياسة.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{بدون}=1{‏من موقع ويب واحد (لن يتم تسجيل خروجك من حسابك على Google)}two{‏من موقعي ويب (#) (لن يتم تسجيل خروجك من حسابك على Google)}few{‏من # مواقع ويب (لن يتم تسجيل خروجك من حسابك على Google)}many{‏من # موقع ويب (لن يتم تسجيل خروجك من حسابك على Google)}other{‏من # موقع ويب (لن يتم تسجيل خروجك من حسابك على Google)}}</translation>
+<translation id="6652101503459149953">‏استخدام Windows Hello</translation>
<translation id="6657585470893396449">كلمة المرور</translation>
<translation id="6670613747977017428">الرجوع</translation>
<translation id="6671697161687535275">‏هل تريد إزالة اقتراح النموذج من Chromium؟</translation>
<translation id="6685834062052613830">الخروج وإكمال الإعداد</translation>
<translation id="6689271823431384964">‏يتيح لك Chrome حفظ بطاقاتك في حسابك على Google لأنك سجَّلت الدخول. يمكنك تغيير هذا السلوك في الإعدادات. ويتم الحصول على اسم حامل البطاقة من حسابك.</translation>
+<translation id="6707256370811247129">‏فحص محتوى ذاكرة التخزين المؤقت والملفات التي يتم تنزيلها أو تحميلها في Chrome</translation>
<translation id="6710213216561001401">السابق</translation>
<translation id="6710594484020273272">&lt;إدخال عبارة البحث&gt;</translation>
<translation id="671076103358959139">الرمز المميّز للتسجيل:</translation>
@@ -1061,10 +1080,10 @@
<translation id="6738516213925468394">تم تشفير بياناتك باستخدام <ph name="BEGIN_LINK" />عبارة مرور المزامنة<ph name="END_LINK" /> في <ph name="TIME" />. يُرجى إدخالها لبدء المزامنة.</translation>
<translation id="674375294223700098">حدث خطأ غير معروف في شهادة الخادم.</translation>
<translation id="6744009308914054259">أثناء انتظار اتصال، يمكنك الانتقال إلى "التنزيلات" للاطِّلاع على المقالات بلا اتصال بالإنترنت.</translation>
+<translation id="6747611005629681221">تحذير: ميزات الصفحة تجريبية.</translation>
<translation id="6753269504797312559">قيمة السياسة</translation>
<translation id="6757797048963528358">خضع جهازك إلى وضع السكون.</translation>
<translation id="6768213884286397650">‏Hagaki (بطاقة بريدية)</translation>
-<translation id="6778737459546443941">لم يوافق عليه والداك حتى الآن</translation>
<translation id="67862343314499040">بنفسجي</translation>
<translation id="6786747875388722282">الإضافات</translation>
<translation id="6790428901817661496">التشغيل</translation>
@@ -1072,6 +1091,7 @@
<translation id="681021252041861472">الحقل مطلوب</translation>
<translation id="6810899417690483278">رقم تعريف التخصيص</translation>
<translation id="6825578344716086703">‏لقد حاولت الوصول إلى <ph name="DOMAIN" />، ولكن قدَّم الخادم شهادة موقّعة باستخدام خوارزمية توقيع ضعيفة (مثل SHA-1)، مما يعني أن بيانات اعتماد الأمان التي قدمها الخادم من المحتمل أنه تم تزييفها، وأن الخادم قد لا يكون هو الخادم الذي تتوقعه (قد تكون على اتصال بأحد المهاجمين).</translation>
+<translation id="6826370046007623921">منع فقدان البيانات</translation>
<translation id="6831043979455480757">ترجمة</translation>
<translation id="6839929833149231406">المنطقة</translation>
<translation id="6852204201400771460">هل تريد إعادة تحميل التطبيق؟</translation>
@@ -1084,7 +1104,6 @@
<translation id="6891596781022320156">مستوى السياسة غير مدعوم.</translation>
<translation id="6895330447102777224">تم التأكد من بطاقتك</translation>
<translation id="6897140037006041989">وكيل المستخدم</translation>
-<translation id="6903319715792422884">‏يمكنك المساعدة في تحسين التصفُّح الآمن عن طريق إرسال بعض <ph name="BEGIN_WHITEPAPER_LINK" />معلومات النظام ومحتوى الصفحة<ph name="END_WHITEPAPER_LINK" /> إلى Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">المستخدم:</translation>
<translation id="6934672428414710184">‏هذا الاسم من حسابك على Google</translation>
<translation id="6944692733090228304">لقد أدخلتَ كلمة المرور في موقع ويب لا تديره <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. ويُرجى عدم إعادة استخدام كلمة المرور في التطبيقات ومواقع الويب الأخرى لحماية حسابك.</translation>
@@ -1129,6 +1148,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> وطريقة دفع <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> أخرى}two{<ph name="PAYMENT_METHOD_PREVIEW" /> وطريقتا دفع <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> أخريان}few{<ph name="PAYMENT_METHOD_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> طرق دفع أخرى}many{<ph name="PAYMENT_METHOD_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> طريقة دفع أخرى}other{<ph name="PAYMENT_METHOD_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> طريقة دفع أخرى}}</translation>
<translation id="7153618581592392745">بنفسجي فاتح</translation>
<translation id="717330890047184534">‏معرّف GAIA:</translation>
+<translation id="7174545416324379297">تم الدمج</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> وخيار <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> آخر}two{<ph name="SHIPPING_OPTION_PREVIEW" /> وخياران (<ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />) آخران}few{<ph name="SHIPPING_OPTION_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> خيارات أخرى}many{<ph name="SHIPPING_OPTION_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> خيارًا آخر}other{<ph name="SHIPPING_OPTION_PREVIEW" /> و<ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> خيار آخر}}</translation>
<translation id="7177397715882417099">لقد طلب الخادم الذي تنتقل إليه، <ph name="ORIGIN" />، أن
يتم تطبيق سياسة الأمان على جميع الطلبات المقدَّمة إليه. ولكن بدلاً من
@@ -1166,6 +1186,7 @@
<translation id="7320336641823683070">المساعدة بشأن الاتصال</translation>
<translation id="733354035281974745">إلغاء حساب الجهاز المحلي</translation>
<translation id="7334320624316649418">إعادة إ&amp;جراء الترتيب</translation>
+<translation id="7337706099755338005">غير متاحة على نظامك الأساسي.</translation>
<translation id="733923710415886693">لم يتم الكشف عن شهادة الخادم عن طريق شهادة الشفافية.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">تابع إلى:</translation>
@@ -1197,7 +1218,6 @@
<translation id="7440140511386898319">الاستكشاف أثناء عدم الاتصال بالإنترنت</translation>
<translation id="7441627299479586546">موضوع السياسة غير صحيح</translation>
<translation id="7442725080345379071">برتقالي فاتح</translation>
-<translation id="7444046173054089907">تم حظر هذا الموقع</translation>
<translation id="7445762425076701745">لا يمكن التحقق بصورة كاملة من صحة هوية الخادم الذي تتصل به. فأنت متصل بخادم باستخدام اسم صالح فقط ضمن شبكتك، والذي لن يتمكن المرجع المصدق الخارجي من التحقق من ملكيته. وحيث إن بعض المراجع المصدقة تُصدر الشهادات لهذه الأسماء على أي حال، فليست هناك طريقة للتأكد من أنك متصل بموقع الويب المقصود وليس بأحد المهاجمين.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /> حول هذه المشكلة.</translation>
<translation id="7455133967321480974">استخدام الإعداد التلقائي العمومي (حظر)</translation>
@@ -1219,9 +1239,9 @@
<translation id="7538364083937897561">‏A2 (مغلف)</translation>
<translation id="7542403920425041731">بعد تأكيدك، ستتم مشاركة تفاصيل بطاقتك مع موقع الويب هذا.</translation>
<translation id="7542995811387359312">تم إيقاف الملء التلقائي لبطاقة الائتمان لأن هذا النموذج لا يستخدم اتصالاً آمنًا.</translation>
-<translation id="7543525346216957623">اسأل والديك</translation>
<translation id="7548892272833184391">إصلاح أخطاء الاتصال</translation>
<translation id="7549584377607005141">تتطلب صفحة الويب هذه البيانات التي أدخلتها في وقت سابق لعرضها بشكل صحيح. يمكنك إرسال هذه المعلومات مرة أخرى ولكن بذلك ستكرر أي إجراء اتخذته هذه الصفحة في وقت سابق.</translation>
+<translation id="7550637293666041147">‏اسم مستخدم الجهاز واسم مستخدم Chrome</translation>
<translation id="7552846755917812628">جرّب النصائح التالية:</translation>
<translation id="7554791636758816595">علامة تبويب جديدة</translation>
<translation id="7564049878696755256">‏قد تفقد إمكانية الوصول إلى حسابك على <ph name="ORG_NAME" /> أو تتعرض لسرقة هويتك. لذا يوصي Chrome بتغيير كلمة مرورك الآن.</translation>
@@ -1236,6 +1256,7 @@
<translation id="7610193165460212391">القيمة خارج النطاق <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">تاريخ انتهاء الصلاحية: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">‏لديك فعلاً بيانات تم تشفيرها باستخدام نسخة أخرى من كلمة مرور حسابك في Google. يُرجى إدخالها أدناه.</translation>
+<translation id="7625784245512586808">‏الحماية من التهديدات من خلال Chrome Enterprise</translation>
<translation id="7633909222644580952">تقارير الأعطال وبيانات الأداء</translation>
<translation id="7637571805876720304">‏هل تريد إزالة بطاقة الائتمان من Chromium؟</translation>
<translation id="7638605456503525968">المنافذ التسلسلية</translation>
@@ -1248,7 +1269,6 @@
<translation id="7668654391829183341">جهاز غير معروف</translation>
<translation id="7669271284792375604">قد يحاول المهاجمون في هذا الموقع خداعك من خلال تثبيت برامج تضر بتجربة التصفح (على سبيل المثال، من خلال تغيير صفحتك الرئيسية أو عرض إعلانات إضافية على المواقع التي تزورها).</translation>
<translation id="7676643023259824263">البحث عن نص الحافظة،<ph name="TEXT" /></translation>
-<translation id="7679176406634891508">وسيط عرض الإعلان والسحابة الإلكترونية</translation>
<translation id="7681101578153515023">تغيير محرّك البحث</translation>
<translation id="7682287625158474539">الشحن</translation>
<translation id="7687186412095877299">تعبئة نماذج الدفع باستخدام طرق الدفع المحفوظة</translation>
@@ -1263,7 +1283,6 @@
<translation id="7723047071702270851">تعديل البطاقة</translation>
<translation id="774634243536837715">تم حظر المحتوى الخطير.</translation>
<translation id="7752995774971033316">غير مُدار</translation>
-<translation id="7755287808199759310">قد يلغي والداك الحظر لك</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ربما حظر الجدار الناري أو برامج مكافحة الفيروسات الاتصال.</translation>
<translation id="7759163816903619567">نطاق العرض:</translation>
@@ -1307,7 +1326,6 @@
<translation id="8004582292198964060">المتصفّح</translation>
<translation id="8009225694047762179">إدارة كلمات المرور</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{سيتم حفظ هذه البطاقة وعنوان إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}zero{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}two{سيتم حفظ هاتين البطاقتين وعنواني إرسال الفواتير. ستتمكَّن من استخدامهما عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}few{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}many{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}other{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">لم نتمكن من الوصول إلى والديك في الوقت الحالي. يُرجى إعادة المحاولة مرة أخرى.</translation>
<translation id="8025119109950072390">قد يحاول المهاجمون على هذا الموقع خداعك لاتّخاذ إجراءات خطيرة مثل تثبيت برامج معيّنة أو كشف معلوماتك الشخصية (مثل كلمات المرور أو أرقام الهواتف أو بطاقات الائتمان).</translation>
<translation id="8034522405403831421">هذه الصفحة باللغة <ph name="SOURCE_LANGUAGE" />. هل تريد ترجمتها إلى اللغة <ph name="TARGET_LANGUAGE" />؟</translation>
<translation id="8035152190676905274">قلم</translation>
@@ -1318,6 +1336,7 @@
<translation id="8041940743680923270">استخدام الإعداد التلقائي العمومي (طلب)</translation>
<translation id="8042918947222776840">اختيار طريقة الاستلام من المستخدم</translation>
<translation id="8057711352706143257">لم تتم تهيئة "<ph name="SOFTWARE_NAME" />" بشكل صحيح. يؤدي عادةً إلغاء تثبيت "<ph name="SOFTWARE_NAME" />" إلى إصلاح المشكلة. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">ليس عليك إدخال رمز أمان البطاقة من الآن فصاعدًا.</translation>
<translation id="8066955247577885446">عذرًا، حدث خطأ.</translation>
<translation id="8074253406171541171">‏10x13 (مغلف)</translation>
<translation id="8078141288243656252">لا يمكن إضافة تعليق توضيحي عند تدوير المستند</translation>
@@ -1348,6 +1367,7 @@
<translation id="8211406090763984747">الاتصال بموقع الويب هذا آمن</translation>
<translation id="8218327578424803826">الموقع الذي تم تعيينه:</translation>
<translation id="8220146938470311105">‏C7/C6 (مغلف)</translation>
+<translation id="8220639454292072926">إعداد التقارير للمؤسسة</translation>
<translation id="8225771182978767009">اختار الشخص الذي أعد جهاز الكمبيوتر حظر موقع الويب هذا.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />، <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">يمكنك فتح الصفحة في علامة تبويب جديدة للتصفح المتخفي</translation>
@@ -1402,24 +1422,24 @@
<translation id="8508648098325802031">رمز البحث</translation>
<translation id="8522552481199248698">‏يمكن أن يساعدك Chrome على حماية حسابك على Google وتغيير كلمة المرور.</translation>
<translation id="8543181531796978784">يمكنك <ph name="BEGIN_ERROR_LINK" />الإبلاغ عن اكتشاف مشكلة<ph name="END_ERROR_LINK" /> أو، إذا كنت تدرك المخاطر المتعلقة بالأمان، يمكنك <ph name="BEGIN_LINK" />زيارة هذا الموقع غير الآمن<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">هل هناك أي أسئلة؟ اتصل بالشخص الذي يشرف على ملفك الشخصي.</translation>
<translation id="8553075262323480129">تعذّرت الترجمة لتعذر تحديد لغة الصفحة.</translation>
<translation id="8557066899867184262">‏رمز التحقق من البطاقة (CVC) موجود خلف بطاقتك.</translation>
<translation id="8559762987265718583">تعذر إنشاء اتصال خاص بـ <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> نظرًا لأن التاريخ والوقت للجهاز (<ph name="DATE_AND_TIME" />) غير صحيحين.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> موقع إلكتروني مريب</translation>
<translation id="8564985650692024650">‏يُوصي Chromium بإعادة تحديد كلمة المرور <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> في حال إعادة استخدامها في مواقع ويب أخرى.</translation>
<translation id="8571890674111243710">جارٍ ترجمة الصفحة إلى <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">إضافة رقم هاتف
</translation>
-<translation id="859285277496340001">لا تحدد الشهادة آلية للتحقق مما إذا كانت الشهادة قد تم إبطالها.</translation>
<translation id="860043288473659153">اسم حامل البطاقة</translation>
<translation id="861775596732816396">الحجم 4</translation>
-<translation id="8620436878122366504">لم يوافق عليه والداك حتى الآن</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">حفظ هذه البطاقة إلى هذا الجهاز</translation>
<translation id="8626112503828625890">‏هل تريد حفظ تفاصيل الفوترة في حساب Google؟</translation>
+<translation id="8647750283161643317">إعادة الضبط إلى الإعدادات التلقائية</translation>
<translation id="8663226718884576429">ملخّص الطلب و<ph name="TOTAL_LABEL" /> وتفاصيل إضافية</translation>
<translation id="8680536109547170164"><ph name="QUERY" />، إجابة، <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">متوفِّر</translation>
<translation id="8703575177326907206">الاتصال بالموقع <ph name="DOMAIN" /> غير محميّ بنظام تشفير.</translation>
<translation id="8718314106902482036">لم تكتمل عملية الدفع</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />، <ph name="DESCRIPTION" />، اقتراح البحث</translation>
@@ -1430,6 +1450,7 @@
<translation id="8738058698779197622">‏لإنشاء اتصال آمن، فإنك بحاجة إلى ضبط ساعتك بشكل صحيح. وذلك لأن الشهادات التي تستخدمها مواقع الويب لتعريف نفسها تكون صالحة فقط لفترات محددة من الوقت. فإذا كانت ساعة جهازك غير صحيحة، فلن يتمكن Chromium من التحقق من هذه الشهادات.</translation>
<translation id="8740359287975076522">‏تعذر العثور على &lt;/abbr&gt;عنوان نظام أسماء النطاقات (DNS)‏&lt;abbr id="dnsDefinition"&gt; لـ <ph name="HOST_NAME" />. جارٍ تشخيص المشكلة.</translation>
<translation id="874846938927089722">بطاقات الائتمان وبطاقات الدفع المسبق المقبولة</translation>
+<translation id="874918643257405732">وضع إشارة مرجعية لعلامة التبويب هذه</translation>
<translation id="8759274551635299824">هذه البطاقة منتهية الصلاحية</translation>
<translation id="8761567432415473239">‏عثر ‏‫التصفح الآمن من Google‬ مؤخرًا <ph name="BEGIN_LINK" />على برامج ضارة<ph name="END_LINK" /> في <ph name="SITE" />.</translation>
<translation id="8763927697961133303">‏جهاز USB</translation>
@@ -1459,6 +1480,7 @@
<translation id="8938939909778640821">بطاقات الائتمان وبطاقات الدفع المسبق المقبولة</translation>
<translation id="8943282376843390568">ليموني</translation>
<translation id="8957210676456822347">تفويض المدخل المقيد</translation>
+<translation id="8962950042226115166">موقع إلكتروني مريب</translation>
<translation id="8968766641738584599">حفظ البطاقة</translation>
<translation id="8971063699422889582">انتهت صلاحية شهادة الخادم.</translation>
<translation id="8975012916872825179">تتضمّن معلومات مثل أرقام الهواتف وعناوين البريد الإلكتروني وعناوين الشحن.</translation>
@@ -1481,24 +1503,24 @@
<translation id="9035022520814077154">خطأ متعلق بالأمان</translation>
<translation id="9038649477754266430">استخدام إحدى خدمات التوقع لتحميل الصفحات بسرعة أكبر</translation>
<translation id="9039213469156557790">إضافة إلى ذلك، تتضمن هذه الصفحة موارد أخرى غير آمنة. ويستطيع الآخرون مشاهدة هذه الموارد أثناء نقلها، كما يستطيع أي مهاجم تعديلها لتغيير سلوك الصفحة.</translation>
+<translation id="9044359186343685026">استخدام رقم التعريف باللمس</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">لقد حاولت الوصول إلى <ph name="DOMAIN" />, ولكن الخادم قدّم شهادة غير صالحة.</translation>
<translation id="9050666287014529139">عبارة المرور</translation>
<translation id="9065203028668620118">تعديل</translation>
<translation id="9065745800631924235">البحث عن <ph name="TEXT" /> من السجلّ.</translation>
<translation id="9069693763241529744">تم الحظر بواسطة إحدى الإضافات</translation>
-<translation id="9076283476770535406">قد يتضمن محتوى للبالغين</translation>
<translation id="9076630408993835509">‏لا تتم إدارة هذا المتصفِّح من خلال شركة أو مؤسسة أخرى. قد تتم إدارة النشاط على هذا الجهاز خارج Chrome. <ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">مطلوب مزيد من المعلومات</translation>
<translation id="9080712759204168376">ملخص الطلبات</translation>
<translation id="9089260154716455634">سياسة "التوقف عن العمل":</translation>
<translation id="9095388113577226029">مزيد من اللغات...</translation>
+<translation id="9098981495403789647">‏فعَّل مشرفك ميزة "الحماية من التهديدات من خلال Chrome Enterprise" على متصفحك. تتضمن ميزة "الحماية من التهديدات من خلال Chrome Enterprise" إذن الوصول إلى بعض بياناتك.</translation>
<translation id="9103872766612412690">‏يستخدم <ph name="SITE" /> التشفير عادة لحماية معلوماتك. عندما حاول Chromium الاتصال بموقع <ph name="SITE" /> هذه المرة، أرجَع موقع الويب بيانات اعتماد غير عادية وغير صحيحة. وقد يحدث هذا عندما يحاول أحد المهاجمين التظاهر بأنه موقع <ph name="SITE" />، أو إذا قاطعت شاشة تسجيل دخول Wi-Fi الاتصال. ولكن لا تزال معلوماتك آمنة نظرًا لأن Chromium أوقَفَ الاتصال قبل تبادل أي بيانات.</translation>
<translation id="9106062320799175032">إضافة عنوان إرسال الفواتير</translation>
<translation id="9114524666733003316">جارٍ التحقق من البطاقة...</translation>
<translation id="9128870381267983090">الاتصال بالشبكة</translation>
<translation id="9137013805542155359">إظهار الصفحة الأصلية</translation>
-<translation id="9137248913990643158">‏يُرجى البدء وتسجيل الدخول إلى Chrome قبل استخدام هذا التطبيق.</translation>
<translation id="9141013498910525015">إدارة العناوين الجغرافية</translation>
<translation id="9148088599418889305">اختيار طريقة الشحن</translation>
<translation id="9148507642005240123">تراجع عن ا&amp;لتحرير</translation>
diff --git a/chromium/components/strings/components_strings_bg.xtb b/chromium/components/strings/components_strings_bg.xtb
index a1fad219707..b13d0feec37 100644
--- a/chromium/components/strings/components_strings_bg.xtb
+++ b/chromium/components/strings/components_strings_bg.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5 x 8</translation>
<translation id="1088860948719068836">Добавяне на името на картодържателя</translation>
<translation id="1089439967362294234">Промяна на паролата</translation>
+<translation id="1096545575934602868">Това поле не трябва да съдържа повече от <ph name="MAX_ITEMS_LIMIT" /> записа. Всички допълнителни записи ще бъдат отхвърлени.</translation>
<translation id="109743633954054152">Управлявайте паролите от настройките на Chrome</translation>
<translation id="1103523840287552314">Винаги да се превежда от <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Ако поставите отметка, Chrome ще съхранява копие на картата ви на това устройство с цел по-бързо попълване на формуляри.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Вижте <ph name="BEGIN_LINK" />кеширано копие<ph name="END_LINK" /> на <ph name="URL" /></translation>
<translation id="1156303062776767266">Преглеждате локален или споделен файл</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> неочаквано прекрати връзката.</translation>
+<translation id="115926840831309955">Прегледайте кода за проверка и опитайте отново или актуализирайте датата на валидност</translation>
<translation id="1161325031994447685">Свържете се отново с Wi-Fi.</translation>
<translation id="1165039591588034296">Грешка</translation>
<translation id="1175364870820465910">&amp;Печат...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Софтуер на компютъра ви пречи на Chrome да се свърже безопасно с мрежата“ (само на компютри под Windows)</translation>
<translation id="1294154142200295408">Варианти във формат за командния ред</translation>
<translation id="129553762522093515">Наскоро затворени</translation>
+<translation id="1298536327547837046">Сканиране за злонамерен софтуер</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Опитайте да изчистите „бисквитките“ си<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Оттеглени функции</translation>
<translation id="1320233736580025032">Prc1 (плик)</translation>
<translation id="132301787627749051">Търсене на изображението от буферната памет</translation>
<translation id="1323433172918577554">Показване на още</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Таблици</translation>
<translation id="1527263332363067270">Изчаква се връзка…</translation>
<translation id="1529521330346880926">10 x 15 (плик)</translation>
+<translation id="1530707389502320859">Сайтът, който току-що се опитахте да отворите, изглежда фалшив. Понякога атакуващите имитират сайтове, като правят незначителни, труднозабележими промени в URL адреса</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Тази страница изпраща съобщение</translation>
<translation id="153384715582417236">Това е всичко засега</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">ОС</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Документът е твърде голям за добавяне на пояснения</translation>
-<translation id="1721312023322545264">Необходимо ви е разрешение от <ph name="NAME" />, за да посетите този сайт</translation>
<translation id="1721424275792716183">* Полето е задължително</translation>
<translation id="1727741090716970331">Добавяне на валиден номер на карта</translation>
<translation id="1728677426644403582">Преглеждате изходния код на уеб страница</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Уебсайтовете, които посещавате, и колко време прекарвате на тях</translation>
<translation id="1826516787628120939">Извършва се проверка</translation>
<translation id="1834321415901700177">Този сайт съдържа опасни програми</translation>
+<translation id="1838374766361614909">Изчистване на търсенето</translation>
<translation id="1839551713262164453">Проверката на стойностите на правилата не бе успешна – възникнаха грешки</translation>
<translation id="1842969606798536927">Плащане</translation>
<translation id="1871208020102129563">За прокси сървъра е зададено да използва фиксирани прокси сървъри, а не URL адрес на скрипт във формат .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Свиване на списъка</translation>
<translation id="1898423065542865115">Филтриране</translation>
<translation id="1914326953223720820">Услуга за разкомпресиране</translation>
+<translation id="1915697529809968049">Искате ли да използвате Touch ID вместо код за проверка?</translation>
<translation id="1916770123977586577">Презаредете страницата, за да приложите актуализираните си настройки към този сайт</translation>
<translation id="1919345977826869612">Реклами</translation>
<translation id="1919367280705858090">Получаване на помощ за конкретно съобщение за грешка</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Отметки от <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Грешка при сериализирането</translation>
<translation id="1974060860693918893">Разширени</translation>
+<translation id="1974883374937189061">Помогнете за подобряването на сигурността на Chrome, като изпращате до Google <ph name="BEGIN_WHITEPAPER_LINK" />URL адресите на някои от страниците, които посещавате, ограничена системна информация и част от съдържанието на страниците<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Версия на фърмуера</translation>
<translation id="1981206234434200693">Изчистване на данните за историята на сърфиране в Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{и още 1}other{и още #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Въведете валидна година на изтичане</translation>
<translation id="2212735316055980242">Правилото не е намерено</translation>
<translation id="2213606439339815911">Записите се извличат...</translation>
+<translation id="2215727959747642672">Редактиране на файлове</translation>
<translation id="2218879909401188352">Понастоящем извършители на атака срещу <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> могат да инсталират опасни приложения, които да повредят устройството ви, да добавят скрити такси към сметката ви за мобилни услуги или да откраднат личната ви информация. <ph name="BEGIN_LEARN_MORE_LINK" />Научете повече<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Няма достъп до интернет</translation>
<translation id="2230458221926704099">Поправете връзката си посредством <ph name="BEGIN_LINK" />приложението за диагностика<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Изпращане сега</translation>
+<translation id="2248949050832152960">Използване на WebAuthn</translation>
<translation id="225207911366869382">Стойността е оттеглена за това правило.</translation>
<translation id="2257315177824333709">За съжаление, картата ви не може да бъде запазена в момента</translation>
<translation id="2262243747453050782">HTTP грешка</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Невалиден URL адрес за търсене.</translation>
<translation id="2482878487686419369">Известия</translation>
<translation id="248348093745724435">Правила за компютъра</translation>
-<translation id="2485387744899240041">Потребителските имена за устройството и браузъра ви</translation>
<translation id="2491120439723279231">Сертификатът на сървъра съдържа грешки.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Синтактичен анализ на JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Назад</translation>
<translation id="2503184589641749290">Приемани дебитни и предплатени карти</translation>
<translation id="2505268675989099013">Защита на профила</translation>
+<translation id="2515335152965840738">ПРЕНЕБРЕГВАНЕ</translation>
<translation id="2515629240566999685">Проверете сигнала в района.</translation>
<translation id="2523886232349826891">Запазено само на това устройство</translation>
<translation id="2524461107774643265">Добавяне на още информация</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Изпращане</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Няма}=1{1 парола (за <ph name="DOMAIN_LIST" />)}=2{2 пароли (за <ph name="DOMAIN_LIST" />)}other{# пароли (за <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Затворете другите раздели или приложения.</translation>
-<translation id="267371737713284912">натиснете <ph name="MODIFIER_KEY_DESCRIPTION" /> за отмяна</translation>
<translation id="2674170444375937751">Наистина ли искате да изтриете тези страници от историята си?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Излизане</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">Стойността не съответства на формата.</translation>
<translation id="2705137772291741111">Запазеното (кеширано) копие на този сайт не можа да се прочете.</translation>
<translation id="2709516037105925701">Автоматично попълване</translation>
-<translation id="2712173769900027643">Искане на разрешение</translation>
<translation id="2713444072780614174">бяло</translation>
<translation id="2720342946869265578">В близост</translation>
<translation id="2721148159707890343">Заявката е успешна</translation>
<translation id="2728127805433021124">Сертификатът на сървъра е подписан със слаб алгоритъм.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Стартирайте диагностика на свързаността<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Активирането на тези функции може да доведе до загуба на данни на браузъра или компрометиране на сигурността или поверителността ви. Активираните функции се прилагат за всички потребители на този браузър.</translation>
<translation id="2735043616039983645">За това правило има повече от един източник с несъвместими стойности.</translation>
<translation id="2738330467931008676">Избиране на адрес за вземане</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">Връзката бе възстановена.</translation>
<translation id="2788784517760473862">Приемани кредитни карти</translation>
<translation id="2792012897584536778">Администраторите на това устройство са настроили сертификати за сигурност, които може да им дадат възможност да виждат съдържанието на посещаваните от вас уебсайтове.</translation>
-<translation id="2794233252405721443">Сайтът е блокиран</translation>
<translation id="2799020568854403057">На хоризонта се задава сайт с опасни приложения</translation>
<translation id="2799223571221894425">Стартиране отново</translation>
<translation id="2803306138276472711">Google Безопасно сърфиране наскоро <ph name="BEGIN_LINK" />откри злонамерен софтуер<ph name="END_LINK" /> на <ph name="SITE" />. Уебсайтовете, които обикновено са надеждни, понякога се заразяват с опасен софтуер.</translation>
+<translation id="2815364696811431560">НАПУСКАНЕ НА САЙТА</translation>
<translation id="2824775600643448204">Лента за адреси и за търсене</translation>
<translation id="2826760142808435982">Връзката е шифрована и удостоверена посредством <ph name="CIPHER" /> и използва <ph name="KX" /> като механизъм за обмен на ключове.</translation>
<translation id="2835170189407361413">Изчистване на формуляра</translation>
<translation id="2847118875340931228">Отваряне на прозорец в режим „инкогнито“</translation>
<translation id="2850739647070081192">Invite (плик)</translation>
-<translation id="2851634818064021665">Необходимо ви е разрешение, за да посетите този сайт</translation>
<translation id="2856444702002559011">Възможно е извършители на атака да опитват да откраднат информацията ви от <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (например пароли, съобщения или номера на кредитни карти). <ph name="BEGIN_LEARN_MORE_LINK" />Научете повече<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Да се запази ли картата?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Ако настройката е активирана, Chromium ще съхранява на това устройство копие на картата ви с цел по-бързо попълване на формуляри.</translation>
<translation id="2985398929374701810">Въведете валиден адрес</translation>
<translation id="2986368408720340940">Този начин на вземане не се поддържа. Опитайте с друг.</translation>
+<translation id="2987034854559945715">Няма съответстващи функции</translation>
<translation id="2991174974383378012">Споделяне с уебсайтове</translation>
<translation id="2991571918955627853">В момента не можете да посетите <ph name="SITE" />, тъй като уебсайтът използва HSTS. Обикновено грешките в мрежата и атаките срещу нея са временни, така че тази страница вероятно ще работи по-късно.</translation>
<translation id="3005723025932146533">Показване на запазено копие</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Грешен тип на правилото</translation>
<translation id="3037605927509011580">Ужас!</translation>
<translation id="3041612393474885105">Информация за сертификата</translation>
+<translation id="3057676462092457419">Режимът <ph name="SECURE_DNS_MODE_SECURE" /> за DnsOverHttps още не се поддържа. Зададен бе режимът <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (плик)</translation>
<translation id="3061707000357573562">Услуга за корекции</translation>
<translation id="3064966200440839136">Ще напуснете режим „инкогнито“, за да платите във външно приложение. Искате ли да продължите?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Анулиране на плащането</translation>
<translation id="3207960819495026254">С отметка</translation>
+<translation id="3209034400446768650">Страницата може да ви таксува</translation>
<translation id="3225919329040284222">Сървърът предостави сертификат, който не съответства на вградените очаквания. Те са включени за определени уебсайтове с голяма степен на сигурност, за да ви предпазим.</translation>
<translation id="3226128629678568754">Натиснете бутона за презареждане, за да изпратите отново данните, необходими за отварянето на страницата.</translation>
<translation id="3227137524299004712">Микрофон</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">Информацията за версията на устройството и браузъра</translation>
<translation id="323107829343500871">Въведете кода за проверка за <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Важното съдържание на този сайт да се открива винаги</translation>
-<translation id="3254409185687681395">Запазване на отметка към тази страница</translation>
<translation id="3270847123878663523">&amp;Отмяна на пренареждането</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Добавяне на името на картодържателя</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">Добавяне на адреса за фактуриране</translation>
<translation id="3324983252691184275">пурпурно</translation>
<translation id="3338095232262050444">Има защита</translation>
-<translation id="3345135638360864351">Заявката ви за достъп до този сайт не можа да се изпрати до <ph name="NAME" />. Моля, опитайте отново.</translation>
<translation id="3355823806454867987">Промяна на настройките на прокси сървъра...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />няма да съхранява<ph name="END_EMPHASIS" /> следната информация:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">Скриване на подробностите</translation>
<translation id="3467763166455606212">Трябва да въведете името на титуляря на картата</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, понастоящем отворено, натиснете Tab и след това Enter, за да превключите към отворения раздел</translation>
-<translation id="3479539252931486093">Това неочаквано ли беше? <ph name="BEGIN_LINK" />Уведомете ни<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Не сега</translation>
<translation id="3484560055331845446">Възможно е да загубите достъп до профила си в Google. Chrome препоръчва да промените паролата си сега. Ще получите подкана за влизане в профила си.</translation>
<translation id="3495081129428749620">Търсене в страницата
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Не можахме да се свържем с родителя ви. Моля, опитайте отново.</translation>
<translation id="3512163584740124171">Това правило е пренебрегнато, защото друго правило от същата група е с по-висок приоритет.</translation>
<translation id="3528171143076753409">Сертификатът на сървъра не е надежден.</translation>
<translation id="3528485271872257980">тъмнокафяво</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Поне 1 елемент на синхронизирани устройства}=1{1 елемент (и други на синхронизирани устройства)}other{# елемента (и други на синхронизирани устройства)}}</translation>
<translation id="3539171420378717834">Съхраняване на копие на картата на това устройство</translation>
-<translation id="3556433843310711081">Мениджърът ви може да го отблокира за вас</translation>
<translation id="3566021033012934673">Връзката ви не е поверителна</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Вградена страница на адрес <ph name="SITE" /> изпраща съобщение</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">Отворете страницата в нов прозорец в режим „инкогнито“ (Ctrl-Shift-N).</translation>
<translation id="3679803492151881375">Сигналът за срив е записан в/ъв <ph name="CRASH_TIME" /> и качен в/ъв <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Информация за сертификата</translation>
+<translation id="3701427423622901115">Нулирането е потвърдено.</translation>
<translation id="3704162925118123524">Използваната от вас мрежа може да изисква да посетите страницата й за вход.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> „<ph name="TITLE" />“ <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Зарежда се...</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805">Извършители на атака, използващи <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, може да ви подведат да направите нещо опасно, като например да инсталирате софтуер или да разкриете лична информация (например пароли, телефонни номера или номера на кредитни карти). <ph name="BEGIN_LEARN_MORE_LINK" />Научете повече<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Преводът не бе успешен поради грешка в сървъра.</translation>
<translation id="3759461132968374835">Наскоро не сте съобщавали за сривове. Тези, възникнали при деактивирано изпращане на сигнали за сривове, не се показват тук.</translation>
+<translation id="3760561303380396507">Искате ли да използвате Windows Hello вместо код за проверка?</translation>
<translation id="3761718714832595332">Скриване на състоянието</translation>
<translation id="3765032636089507299">Страницата на Безопасно сърфиране е в процес на разработка.</translation>
<translation id="3778403066972421603">Искате ли тази карта да се запази на устройството и в профила ви в Google?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">Размер 16</translation>
<translation id="3797522431967816232">Prc3 (плик)</translation>
<translation id="3807873520724684969">Блокирано бе вредно съдържание.</translation>
+<translation id="3808375843007691220">Предупреждение: Експериментални функции на хоризонта!</translation>
<translation id="3810973564298564668">Управление</translation>
<translation id="382518646247711829">Ако използвате прокси сървър...</translation>
<translation id="3828924085048779000">Не може пропускът да не се попълни.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">Актуализиране на датата и часа</translation>
<translation id="3884278016824448484">Идентификационният номер на устройството е несъвместим</translation>
<translation id="3885155851504623709">Енория</translation>
-<translation id="3886446263141354045">Заявката ви за достъп до този сайт бе изпратена до <ph name="NAME" /></translation>
<translation id="3890664840433101773">Добавяне на имейл адрес</translation>
<translation id="3901925938762663762">Картата е с изтекла валидност</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> – <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Искате ли да използвате WebAuthn вместо код за проверка?</translation>
<translation id="3946209740501886391">Винаги да се извежда запитване за този сайт</translation>
<translation id="3949571496842715403">Сървърът не можа да докаже, че е <ph name="DOMAIN" />. В сертификата му за сигурност не са посочени алтернативни имена на обекта. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от извършител на атака.</translation>
<translation id="3949601375789751990">Тук се показва историята ви на сърфиране</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Няма}=1{От 1 сайт }other{От # сайта }}</translation>
<translation id="397105322502079400">Изчислява се...</translation>
<translation id="3973234410852337861">Хостът <ph name="HOST_NAME" /> е блокиран</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> активира защитата срещу заплахи на Chrome Enterprise в браузъра ви. Функцията има достъп до някои от данните ви.</translation>
<translation id="3987940399970879459">По-малко от 1 МБ</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 уеб страница в близост}other{# уеб страници в близост}}</translation>
<translation id="4030383055268325496">&amp;Отмяна на добавянето</translation>
<translation id="4032320456957708163">Браузърът ви се управлява от <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Отворената от вас връзка води до сайт, който обикновено не посещавате. Възможно е връзката да се опитва да ви обърка.</translation>
<translation id="4058922952496707368">Ключ „<ph name="SUBKEY" />“: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (плик)</translation>
<translation id="4067947977115446013">Добавяне на валиден адрес</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">Серийният номер на устройството е невалиден</translation>
<translation id="410351446219883937">Автоматично възпроизвеждане</translation>
<translation id="4103763322291513355">Посетете &lt;strong&gt;chrome://policy&lt;/strong&gt;, за да видите изброени URL адресите в черния списък и другите правила, наложени от системния ви администратор.</translation>
+<translation id="4108231218301530806">Използване на пръстов отпечатък за потвърждаване на тази карта следващия път.</translation>
<translation id="4110652170750985508">Преглед на плащането ви</translation>
<translation id="4112140312785995938">Придвижване назад</translation>
<translation id="4116663294526079822">Разрешаване винаги на този сайт</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">Невалиден подпис за потвърждаване</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{още <ph name="ITEM_COUNT" /> елемент}other{още <ph name="ITEM_COUNT" /> елемента}}</translation>
+<translation id="4176463684765177261">Деактивирано</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> – <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">За да платите по-бързо следващия път, добавете картата и адреса си за фактуриране към профила си в Google.</translation>
<translation id="4196861286325780578">&amp;Възстановяване на преместването</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">Повторно задаване на паролата</translation>
<translation id="4279811152705618813">Вашият <ph name="DEVICE_TYPE" /> се управлява от <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Тази карта е запазена в профила ви в Google}other{Тези карти са запазени в профила ви в Google}}</translation>
+<translation id="428847186335018806">Сканиране на файловете, които изтегляте или качвате в Chrome.</translation>
<translation id="42981349822642051">Разгъване</translation>
<translation id="4302965934281694568">Chou3 (плик)</translation>
<translation id="4305817255990598646">Превключване</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">пощенска картичка)</translation>
<translation id="443673843213245140">Използването на прокси сървър е деактивирано, но е посочена изрична негова конфигурация.</translation>
<translation id="445100540951337728">Приемани дебитни карти</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> подозрително поведение</translation>
<translation id="4466881336512663640">Промените във формуляра ще бъдат заличени. Наистина ли искате да продължите?</translation>
<translation id="4477350412780666475">Следващ запис</translation>
<translation id="4482953324121162758">Този сайт няма да се превежда.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">&amp;Отмяна на изтриването</translation>
<translation id="4597348597567598915">Размер 8</translation>
<translation id="4600854749408232102">C6/C5 (плик)</translation>
+<translation id="464342062220857295">Функции за търсене</translation>
<translation id="4646534391647090355">Към изтеглянията</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Сървърът не можа да докаже, че е <ph name="DOMAIN" />; сертификатът му за сигурност съдържа грешки. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от атакуващ.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A (плик)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Връзката ви бе прекъсната</translation>
-<translation id="471880041731876836">Нямате разрешение да посетите този сайт</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Стартирайте мрежова диагностика в Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Презареждане на правилата</translation>
<translation id="4728558894243024398">Платформа</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">Да се побере в страницата</translation>
<translation id="4850886885716139402">Изглед</translation>
<translation id="4854362297993841467">Този начин на бърза доставка не се поддържа. Опитайте с друг.</translation>
-<translation id="4858792381671956233">Попитахте родителите си дали може да посетите този сайт</translation>
<translation id="4864052566555297930">Съвет за безопасност:</translation>
<translation id="4876188919622883022">Опростен изглед</translation>
<translation id="4876305945144899064">Няма потребителско име</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">Повторно активиране на предупрежденията</translation>
<translation id="4984339528288761049">Prc5 (плик)</translation>
<translation id="4989163558385430922">Преглед на всички</translation>
+<translation id="4989542687859782284">Експерименти, които не са налице</translation>
<translation id="4989809363548539747">Тази приставка не се поддържа</translation>
+<translation id="4995216769782533993">Потвърдете кода за сигурност, за да споделите данните за картата си с този сайт</translation>
<translation id="5002932099480077015">Ако настройката е активирана, копие на картата ви ще се съхранява в Chrome на това устройство с цел по-бързо попълване на формуляри.</translation>
<translation id="5015510746216210676">Име на компютъра:</translation>
<translation id="5017554619425969104">Копиран от вас текст</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 бита)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Потвърдете картата</translation>
<translation id="5135404736266831032">Управление на адресите...</translation>
<translation id="5138227688689900538">Показване на по-малко</translation>
<translation id="5141240743006678641">Синхронизираните пароли да се шифроват с идентификационните ви данни за Google</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">Облак</translation>
<translation id="5252000469029418751">C7 (плик)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Функциите, които се прилагат за цялата система, могат да бъдат зададени само от собственика: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Предупреждение: Това правило не бе обединено според посоченото в правилото PolicyDictionaryMultipleSourceMergeList, тъй като не е част от правилата речници с възможност за обединяване.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Край</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">Съхраняването на настройките за правилото не бе успешно</translation>
<translation id="5371425731340848620">Актуализиране на картата</translation>
<translation id="5377026284221673050">„Часовникът ви е назад“, „Часовникът ви е напред“ или „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;“</translation>
-<translation id="5377179979757081683">Тази страница може да се опита да ви подведе, да открадне лична информация или да навреди на устройството ви. Действайте предпазливо, когато въвеждате лична информация или отваряте изтеглени файлове.</translation>
<translation id="5384855140246857529">За да използвате картите си на всичките си устройства, влезте в профила си и включете синхронизирането.</translation>
<translation id="5386426401304769735">Веригата от сертификати за този сайт съдържа сертификат, подписан с SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,7 @@
<translation id="5457113250005438886">Невалидно</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Възстановяване на редактирането</translation>
+<translation id="5473728911100096288">Напът сте да активирате функции, които няма да са достъпни в бъдещите версии, понеже са оттеглени.</translation>
<translation id="5478437291406423475">B6/C4 (плик)</translation>
<translation id="5481076368049295676">Въпросното съдържание може да се опита да инсталира опасен софтуер на устройството ви, който да открадне или изтрие информацията ви. <ph name="BEGIN_LINK" />Показване въпреки това<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Добавяне на валиден адрес</translation>
@@ -863,7 +876,6 @@
<translation id="5570825185877910964">Защита на профила</translation>
<translation id="5571083550517324815">Този адрес за вземане не се поддържа. Изберете друг.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{използва се 1}other{използват се #}})</translation>
-<translation id="5572851009514199876">Моля, стартирайте браузъра Chrome и влезте в него, за да се провери дали имате достъп до този сайт.</translation>
<translation id="5580958916614886209">Проверете месеца на валидност и опитайте отново</translation>
<translation id="5586446728396275693">Няма запазени адреси</translation>
<translation id="5595485650161345191">Редактиране на адреса</translation>
@@ -871,6 +883,7 @@
<translation id="560412284261940334">Управлението не се поддържа</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Този сайт може да е фалшив или измамнически. Chrome препоръчва да го напуснете сега.</translation>
<translation id="5610142619324316209">Проверете връзката.</translation>
<translation id="5610807607761827392">Можете да управлявате картите и адресите от <ph name="BEGIN_LINK" />настройките<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ви пренасочи твърде много пъти.</translation>
@@ -894,11 +907,11 @@
<translation id="5720705177508910913">Текущият потребител</translation>
<translation id="5728056243719941842">C5 (плик)</translation>
<translation id="5730040223043577876">Chrome препоръчва да зададете повторно паролата си, ако сте я използвали и на други сайтове.</translation>
-<translation id="5732392974455271431">Родителите ви могат да го отблокират за вас</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Запазване на картата в профила ви в Google}other{Запазване на картите в профила ви в Google}}</translation>
<translation id="5763042198335101085">Въведете валиден имейл адрес</translation>
<translation id="5765072501007116331">За да видите начините на бърза доставка и изискванията, изберете адрес</translation>
<translation id="5778550464785688721">Пълен контрол над MIDI устройства</translation>
+<translation id="5781136890105823427">Експериментът е активиран</translation>
<translation id="578305955206182703">кехлибарено</translation>
<translation id="57838592816432529">Заглушаване</translation>
<translation id="5784606427469807560">При потвърждаването на картата ви възникна проблем. Проверете връзката си с интернет и опитайте отново.</translation>
@@ -915,13 +928,16 @@
<translation id="5860033963881614850">Изключено</translation>
<translation id="5863847714970149516">На страницата, която искате да посетите, е възможно да ви бъдат удържани средства</translation>
<translation id="5866257070973731571">Добавяне на телефонен номер</translation>
+<translation id="5866898949289125849">Преглеждате страница с инструменти за програмисти</translation>
<translation id="5869405914158311789">Няма достъп до този сайт</translation>
<translation id="5869522115854928033">Запазени пароли</translation>
<translation id="5887400589839399685">Картата бе запазена</translation>
<translation id="5893752035575986141">Приемат се кредитни карти.</translation>
+<translation id="5895138241574237353">Рестартиране</translation>
<translation id="5901630391730855834">жълто</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (синхронизирано)</translation>
<translation id="5916664084637901428">Включено</translation>
+<translation id="59174027418879706">Активирано</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Картата да се запази ли в профила в Google?</translation>
<translation id="5922853866070715753">Почти готово</translation>
@@ -955,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Искате ли да използвате картите си на всичките си устройства?</translation>
<translation id="6059925163896151826">USB устройства</translation>
+<translation id="6060009363608157444">Невалиден режим за DnsOverHttps.</translation>
<translation id="6080696365213338172">Осъществихте достъп до съдържанието посредством осигурен от администратора сертификат. Данните, които предоставите на <ph name="DOMAIN" />, могат да бъдат прихванати от администратора ви.</translation>
<translation id="6094273045989040137">Добавяне на пояснения</translation>
<translation id="610911394827799129">В профила ви в Google може да има други видове история на сърфиране, съхранявани на адрес <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1020,12 @@
<translation id="6404511346730675251">Редактиране на отметката</translation>
<translation id="6406765186087300643">C0 (плик)</translation>
<translation id="6410264514553301377">Въвеждане на датата на валидност и кода за проверка за <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Попитахте родителя си дали може да посетите този сайт</translation>
<translation id="6415778972515849510">Chromium може да ви помогне да защитите профила си в Google и да промените паролата си.</translation>
-<translation id="6417515091412812850">Не може да се провери дали сертификатът е анулиран.</translation>
<translation id="6431585503458005759">Без съхраняване</translation>
<translation id="6433490469411711332">Редактиране на информацията за връзка</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> отказа да установи връзка.</translation>
<translation id="6434309073475700221">Отхвърляне</translation>
+<translation id="6435221585574090192">Споделяне с администратора ви на данни за събития, свързани със сигурността, за които е сигнализирано от функцията на Chrome Enterprise за защита срещу заплахи. Данните може да включват URL адреси на страници, имена и метаданни на файлове, както и потребителското име на устройството ви и в Chrome.</translation>
<translation id="6440503408713884761">Пренебрегнато</translation>
<translation id="6446163441502663861">Kahu (плик)</translation>
<translation id="6446608382365791566">Добавяне на още информация</translation>
@@ -1018,20 +1034,19 @@
<translation id="6465306955648956876">Управление на паролите...</translation>
<translation id="647261751007945333">Правила за устройството</translation>
<translation id="6476284679642588870">Управление на начините на плащане</translation>
-<translation id="6477321094435799029">Chrome откри необичаен код на тази страница и я блокира, за да защити личната ви информация (например пароли, телефонни номера и номера на кредитни карти).</translation>
<translation id="6489534406876378309">Стартиране на качването на сривове</translation>
<translation id="6499038740797743453">Да се зададе ли повторно паролата?</translation>
<translation id="6507833130742554667">Приемат се кредитни и дебитни карти.</translation>
<translation id="650855688985305916">Да, искам</translation>
<translation id="6508722015517270189">Рестартирайте Chrome.</translation>
<translation id="6517596291481585650">Предупреждение: Това правило не бе обединено като списък според посоченото в правилото, тъй като не е списък.</translation>
+<translation id="6518133107902771759">Потвърждаване</translation>
<translation id="6521745193039995384">Не е активно</translation>
<translation id="6529602333819889595">&amp;Възстановяване на изтриването</translation>
<translation id="6534179046333460208">Предложения от Физическата мрежа</translation>
<translation id="6545864417968258051">Сканиране за устройства с Bluetooth</translation>
<translation id="6554795675067793129">Профилът ви се управлява от <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Възстановяване</translation>
-<translation id="6563469144985748109">Мениджърът ви все още не е одобрил заявката</translation>
<translation id="6569060085658103619">Преглеждате страница на разширение</translation>
<translation id="6578796323535178455">C2 (плик)</translation>
<translation id="6579990219486187401">светлорозово</translation>
@@ -1049,11 +1064,13 @@
<translation id="6643016212128521049">Изчистване</translation>
<translation id="6644283850729428850">Това правило е оттеглено.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Няма}=1{От 1 сайт (няма да излезете от профила си в Google)}other{От # сайта (няма да излезете от профила си в Google)}}</translation>
+<translation id="6652101503459149953">Използване на Windows Hello</translation>
<translation id="6657585470893396449">Парола</translation>
<translation id="6670613747977017428">Назад към безопасната страница.</translation>
<translation id="6671697161687535275">Предложението за формуляри да се премахне ли от Chromium?</translation>
<translation id="6685834062052613830">Излизане от профила и завършване на настройването</translation>
<translation id="6689271823431384964">Chrome предлага да запази картите ви в профила ви в Google, защото сте влезли в него. Можете да промените това поведение от настройките. Името на картодържателя е от профила ви.</translation>
+<translation id="6707256370811247129">Сканиране на съдържанието на кеша и файловете, които изтегляте или качвате в Chrome.</translation>
<translation id="6710213216561001401">Предишна</translation>
<translation id="6710594484020273272">&lt;Въведете дума за търсене&gt;</translation>
<translation id="671076103358959139">Означение за регистриране:</translation>
@@ -1061,10 +1078,10 @@
<translation id="6738516213925468394">На <ph name="TIME" /> данните ви бяха шифровани с <ph name="BEGIN_LINK" />пропуска ви за синхронизиране<ph name="END_LINK" />. Въведете го, за да стартирате синхронизирането.</translation>
<translation id="674375294223700098">Неизвестна грешка в сертификата на сървъра.</translation>
<translation id="6744009308914054259">Докато чакате да се установи връзка, можете да посетите страницата „Изтегляния“, за да четете офлайн статии.</translation>
+<translation id="6747611005629681221">Предупреждение: оттеглени функции на хоризонта!</translation>
<translation id="6753269504797312559">Стойност за правилото</translation>
<translation id="6757797048963528358">Устройството ви премина в спящ режим.</translation>
<translation id="6768213884286397650">Hagaki (пощенска картичка)</translation>
-<translation id="6778737459546443941">Родителят ви все още не е одобрил заявката</translation>
<translation id="67862343314499040">виолетово</translation>
<translation id="6786747875388722282">Разширения</translation>
<translation id="6790428901817661496">Пускане</translation>
@@ -1072,6 +1089,7 @@
<translation id="681021252041861472">Задължително поле</translation>
<translation id="6810899417690483278">Идент. № на персонализирането</translation>
<translation id="6825578344716086703">Опитахте да отворите <ph name="DOMAIN" />, но сървърът предостави сертификат, подписан със слаб алгоритъм (например SHA-1). Това означава, че идентификационните данни за сигурност от сървъра може да са фалшифицирани и той да не е този, който очаквате (възможно е да сте се свързали с извършител на атака).</translation>
+<translation id="6826370046007623921">Защита от загуба на данни</translation>
<translation id="6831043979455480757">Превод</translation>
<translation id="6839929833149231406">Район</translation>
<translation id="6852204201400771460">Искате ли да презаредите приложението?</translation>
@@ -1084,7 +1102,6 @@
<translation id="6891596781022320156">Нивото на правилото не се поддържа.</translation>
<translation id="6895330447102777224">Картата ви е потвърдена</translation>
<translation id="6897140037006041989">Потребителски агент</translation>
-<translation id="6903319715792422884">Помогнете за подобряването на Безопасно сърфиране, като ни изпращате <ph name="BEGIN_WHITEPAPER_LINK" />системна информация и част от съдържанието на страниците<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Потребител:</translation>
<translation id="6934672428414710184">Това име е от профила ви в Google</translation>
<translation id="6944692733090228304">Въведохте паролата си на сайт, който не се управлява от <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. За да защитите профила си, не използвайте паролата си повторно в други приложения и сайтове.</translation>
@@ -1129,6 +1146,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">лавандулово</translation>
<translation id="717330890047184534">Идентификатор в GAIA:</translation>
+<translation id="7174545416324379297">Обединени стойности</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Сървърът, който отваряте (<ph name="ORIGIN" />), е поискал
за всички заявки към него да се прилага правило за сигурност. Вместо обаче
@@ -1166,6 +1184,7 @@
<translation id="7320336641823683070">Помощ при проблеми с връзката</translation>
<translation id="733354035281974745">Отменено от локалния профил на устройството</translation>
<translation id="7334320624316649418">&amp;Възстановяване на пренареждането</translation>
+<translation id="7337706099755338005">Не е налице за платформата ви.</translation>
<translation id="733923710415886693">Сертификатът на сървъра не е разкрит чрез Прозрачност на сертификатите.</translation>
<translation id="734600844861828519">11 x 15</translation>
<translation id="7346048084945669753">Потребителят е вътрешен:</translation>
@@ -1197,7 +1216,6 @@
<translation id="7440140511386898319">Разгледайте, докато сте офлайн</translation>
<translation id="7441627299479586546">Грешен предмет на правилото</translation>
<translation id="7442725080345379071">светлооранжево</translation>
-<translation id="7444046173054089907">Този сайт е блокиран</translation>
<translation id="7445762425076701745">Идентичността на сървъра, към който сте свързани, не може да бъде потвърдена изцяло. Свързани сте към сървър чрез име, което е валидно само във вашата мрежа и чиято собственост няма начин да се потвърди от външен сертифициращ орган. Тъй като някои сертифициращи органи въпреки това издават сертификати за такива имена, не е възможно да се гарантира, че сте свързани към желания сайт, а не към атакуващ.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Научете повече<ph name="END_LINK" /> за този проблем.</translation>
<translation id="7455133967321480974">Използване на глобалната стандартна стойност (блокиране)</translation>
@@ -1219,9 +1237,9 @@
<translation id="7538364083937897561">A2 (плик)</translation>
<translation id="7542403920425041731">След като потвърдите картата си, данните за нея ще бъдат споделени с този сайт.</translation>
<translation id="7542995811387359312">Автоматичното попълване на кредитната карта е деактивирано, защото този формуляр не използва защитена връзка.</translation>
-<translation id="7543525346216957623">Попитайте родителя си</translation>
<translation id="7548892272833184391">Отстраняване на грешки във връзката</translation>
<translation id="7549584377607005141">За да се покаже правилно тази уеб страница, са необходими по-рано въведените от вас данни. Можете да ги изпратите отново, но така ще повторите всяко изпълнено от нея действие.</translation>
+<translation id="7550637293666041147">Потребителското име на устройството ви и в Chrome</translation>
<translation id="7552846755917812628">Изпробвайте следните съвети:</translation>
<translation id="7554791636758816595">Нов раздел</translation>
<translation id="7564049878696755256">Възможно е да загубите достъп до профила си в/ъв <ph name="ORG_NAME" /> или самоличността ви да бъде открадната. Chrome препоръчва да промените паролата си сега.</translation>
@@ -1236,6 +1254,7 @@
<translation id="7610193165460212391">Стойността е извън обхват <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Валидна до: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Вече имате данни, които са шифровани посредством друга версия на паролата за профила ви в Google. Моля, въведете я по-долу.</translation>
+<translation id="7625784245512586808">Защита срещу заплахи на Chrome Enterprise</translation>
<translation id="7633909222644580952">Данни за ефективността и сигнали за сривове</translation>
<translation id="7637571805876720304">Кредитната карта да се премахне ли от Chromium?</translation>
<translation id="7638605456503525968">Серийни портове</translation>
@@ -1248,7 +1267,6 @@
<translation id="7668654391829183341">Неизвестно устройство</translation>
<translation id="7669271284792375604">Извършителите на атаки, използващи този сайт, може да опитат да ви подведат да инсталирате програми, които вредят на сърфирането ви (например, като променят началната ви страница или показват допълнителни реклами в посещаваните от вас сайтове).</translation>
<translation id="7676643023259824263">Търсене на текста от буферната памет, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">На ниво платформа и от облака</translation>
<translation id="7681101578153515023">Промяна на търсещата машина</translation>
<translation id="7682287625158474539">Адрес за доставка</translation>
<translation id="7687186412095877299">Попълване на платежни формуляри със запазените от вас начини на плащане</translation>
@@ -1263,7 +1281,6 @@
<translation id="7723047071702270851">Редактиране на картата</translation>
<translation id="774634243536837715">Блокирахме опасно съдържание.</translation>
<translation id="7752995774971033316">Не се управлява</translation>
-<translation id="7755287808199759310">Родителят ви може да го отблокира за вас</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Възможно е връзката да е блокирана от защитна стена или антивирусен софтуер.</translation>
<translation id="7759163816903619567">Показван домейн:</translation>
@@ -1307,7 +1324,6 @@
<translation id="8004582292198964060">Браузър</translation>
<translation id="8009225694047762179">Управление на паролите</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Тази карта и адресът й за фактуриране ще бъдат запазени. Ще можете да я използвате, когато сте влезли в профила <ph name="USER_EMAIL" />.}other{Тези карти и адресите им за фактуриране ще бъдат запазени. Ще можете да ги използвате, когато сте влезли в профила <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Не можахме да се свържем с родителите ви. Моля, опитайте отново.</translation>
<translation id="8025119109950072390">Извършителите на атаки, използващи този сайт, може да ви подведат да направите нещо опасно, като например да инсталирате софтуер или да разкриете лична информация (например пароли, телефонни номера или номера на кредитни карти).</translation>
<translation id="8034522405403831421">Тази страница е на <ph name="SOURCE_LANGUAGE" />. Да се преведе ли на <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Писалка</translation>
@@ -1318,6 +1334,7 @@
<translation id="8041940743680923270">Използване на глобалната стандартна стойност (запитване)</translation>
<translation id="8042918947222776840">Избиране на начин на вземане</translation>
<translation id="8057711352706143257">Софтуерът <ph name="SOFTWARE_NAME" /> не е конфигуриран правилно. Обикновено проблемът се отстранява с деинсталиране на <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Повече няма да се налага да въвеждате кода за сигурност на картата си</translation>
<translation id="8066955247577885446">За съжаление, нещо се обърка.</translation>
<translation id="8074253406171541171">10 x 13 (плик)</translation>
<translation id="8078141288243656252">Добавянето на пояснения не е възможно, когато документът е завъртян</translation>
@@ -1348,6 +1365,7 @@
<translation id="8211406090763984747">Връзката е защитена</translation>
<translation id="8218327578424803826">Зададено местоположение:</translation>
<translation id="8220146938470311105">C7/C6 (плик)</translation>
+<translation id="8220639454292072926">Корпоративно отчитане</translation>
<translation id="8225771182978767009">Човекът, който е настроил компютъра, е блокирал този сайт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> и <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Отворете страницата в нов раздел в режим „инкогнито“.</translation>
@@ -1402,23 +1420,23 @@
<translation id="8508648098325802031">Икона за търсене</translation>
<translation id="8522552481199248698">Chrome може да ви помогне да защитите профила си в Google и да промените паролата си.</translation>
<translation id="8543181531796978784">Можете да <ph name="BEGIN_ERROR_LINK" />подадете сигнал за проблем при откриването<ph name="END_ERROR_LINK" /> или, ако разбирате рисковете за сигурността си, да <ph name="BEGIN_LINK" />посетите този небезопасен сайт<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">При въпроси се свържете с лицето, което контролира потребителския ви профил.</translation>
<translation id="8553075262323480129">Преводът не бе успешен, защото езикът на страницата не можа да бъде определен.</translation>
<translation id="8557066899867184262">Кодът за проверка се намира на гърба на картата ви.</translation>
<translation id="8559762987265718583">Не може да се установи частна връзка с/ъс <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, тъй като датата и часът на устройството ви (<ph name="DATE_AND_TIME" />) са неправилни.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> подозрителен сайт</translation>
<translation id="8564985650692024650">Chromium препоръчва да зададете повторно паролата си за <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, ако сте я използвали и на други сайтове.</translation>
<translation id="8571890674111243710">Превод на страницата на <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">+ тел. номер</translation>
-<translation id="859285277496340001">Сертификатът не посочва механизъм за проверка дали е бил анулиран.</translation>
<translation id="860043288473659153">Име на титуляря на картата</translation>
<translation id="861775596732816396">Размер 4</translation>
-<translation id="8620436878122366504">Родителите ви все още не са одобрили заявката</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Запазване на картата на това устройство</translation>
<translation id="8626112503828625890">Искате ли данните за плащане да бъдат съхранени в профила в Google?</translation>
+<translation id="8647750283161643317">Възстановяване на всичко към стандартното състояние</translation>
<translation id="8663226718884576429">Обобщение на поръчката, <ph name="TOTAL_LABEL" />, още подробности</translation>
<translation id="8680536109547170164">„<ph name="QUERY" />“, отговор: „<ph name="ANSWER" />“</translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Свободно място</translation>
<translation id="8703575177326907206">Връзката ви с <ph name="DOMAIN" /> не е шифрована.</translation>
<translation id="8718314106902482036">Плащането не е завършено</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, предложение за търсене</translation>
@@ -1429,6 +1447,7 @@
<translation id="8738058698779197622">За установяване на сигурна връзка е необходимо часовникът ви да е верен. Това е така, защото сертификатите, с които уебсайтовете се идентифицират, са валидни само за конкретни периоди от време. Тъй като часовникът на устройството ви не е верен, Chromium не може да потвърди тези сертификати.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;DNS адресът&lt;/abbr&gt; на <ph name="HOST_NAME" /> не можа да бъде намерен. Проблемът се диагностицира.</translation>
<translation id="874846938927089722">Приемани кредитни и предплатени карти</translation>
+<translation id="874918643257405732">Запазване на отметка към този раздел</translation>
<translation id="8759274551635299824">Тази карта е изтекла</translation>
<translation id="8761567432415473239">Google Безопасно сърфиране наскоро <ph name="BEGIN_LINK" />откри опасни програми<ph name="END_LINK" /> на <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB устройство</translation>
@@ -1458,6 +1477,7 @@
<translation id="8938939909778640821">Приемани кредитни и предплатени карти</translation>
<translation id="8943282376843390568">лимоненозелено</translation>
<translation id="8957210676456822347">Упълномощаване в портал за удостоверяване</translation>
+<translation id="8962950042226115166">Подозрителен сайт</translation>
<translation id="8968766641738584599">Запазване на картата</translation>
<translation id="8971063699422889582">Сертификатът на сървъра е с изтекла валидност.</translation>
<translation id="8975012916872825179">Включва информация като телефонни номера, имейл адреси и адреси за доставка</translation>
@@ -1480,24 +1500,24 @@
<translation id="9035022520814077154">Грешка в сигурността</translation>
<translation id="9038649477754266430">Използване на услуга за предвиждане с цел по-бързо зареждане на страниците</translation>
<translation id="9039213469156557790">Освен това тази страница включва други ресурси, които не са защитени. Докато се предават, те могат да бъдат видени от други хора и да бъдат модифицирани от извършител на атака, така че да се промени поведението на страницата.</translation>
+<translation id="9044359186343685026">Използване на Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Опитахте да отворите <ph name="DOMAIN" />, но сървърът предостави невалиден сертификат.</translation>
<translation id="9050666287014529139">Парола</translation>
<translation id="9065203028668620118">Редактиране</translation>
<translation id="9065745800631924235">Търсене на „<ph name="TEXT" />“ от историята</translation>
<translation id="9069693763241529744">Блокирано от разширение</translation>
-<translation id="9076283476770535406">Възможно е да има съдържание за пълнолетни</translation>
<translation id="9076630408993835509">Този браузър не се управлява от дружество или друга организация. Възможно е активността на устройството да се управлява извън Chrome. <ph name="BEGIN_LINK" />Научете повече<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Изисква се още информация</translation>
<translation id="9080712759204168376">Обобщена информация за поръчката</translation>
<translation id="9089260154716455634">Пренебрегване на правилата:</translation>
<translation id="9095388113577226029">Още езици...</translation>
+<translation id="9098981495403789647">Администраторът ви е активирал защитата срещу заплахи на Chrome Enterprise в браузъра ви. Функцията има достъп до някои от данните ви.</translation>
<translation id="9103872766612412690">Обикновено <ph name="SITE" /> използва шифроване за защита на информацията ви. Когато Chromium опита да установи връзка с/ъс <ph name="SITE" /> този път, уебсайтът върна необичайни и неправилни идентификационни данни. Това може да се случи, когато извършител на атака пробва да се представи за <ph name="SITE" /> или връзката е прекъсната от екран за вход в Wi-Fi. Информацията ви продължава да е защитена, тъй като Chromium спря връзката, преди да бъдат обменени данни.</translation>
<translation id="9106062320799175032">Добавяне на адрес за фактуриране</translation>
<translation id="9114524666733003316">Картата се потвърждава...</translation>
<translation id="9128870381267983090">Свързване към мрежа</translation>
<translation id="9137013805542155359">Показване на оригинала</translation>
-<translation id="9137248913990643158">Моля, стартирайте браузъра Chrome и влезте в него, преди да използвате това приложение.</translation>
<translation id="9141013498910525015">Управление на адресите</translation>
<translation id="9148088599418889305">Избиране на начин на доставка</translation>
<translation id="9148507642005240123">&amp;Отмяна на редактирането</translation>
diff --git a/chromium/components/strings/components_strings_bn.xtb b/chromium/components/strings/components_strings_bn.xtb
index 6d50e45e59b..30368650d23 100644
--- a/chromium/components/strings/components_strings_bn.xtb
+++ b/chromium/components/strings/components_strings_bn.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">কার্ডে নাম যোগ করুন</translation>
<translation id="1089439967362294234">পাসওয়ার্ড পরিবর্তন করুন</translation>
+<translation id="1096545575934602868">এই ফিল্ডে <ph name="MAX_ITEMS_LIMIT" />টির বেশি এন্ট্রি লেখা যাবে না। অন্য সব এন্ট্রি বাতিল করা হবে।</translation>
<translation id="109743633954054152">Chrome সেটিংসে পাসওয়ার্ড পরিচালনা করুন</translation>
<translation id="1103523840287552314">সর্বদা অনুবাদ করুন <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">যদি চেক করা হয়, দ্রুত ফর্ম পূরণ করার জন্য এই ডিভাইসে থাকা আপনার কার্ডের একটি কপি Chrome স্টোর করবে৷</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" />-এর <ph name="BEGIN_LINK" />ক্যাশে করা কপি<ph name="END_LINK" /> অ্যাক্সেস করুন</translation>
<translation id="1156303062776767266">আপনি একটি স্থানীয় বা শেয়ার করা ফাইল দেখছেন</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> অপ্রত্যাশিতভাবে সংযোগ বন্ধ করেছে।</translation>
+<translation id="115926840831309955">কার্ডের সিভিসি নম্বরটি ঠিক লিখেছেন কিনা দেখে নিয়ে আবার চেষ্টা করুন অথবা মেয়াদ শেষ হওয়ার তারিখটি আপডেট করুন</translation>
<translation id="1161325031994447685">ওয়াই-ফাই এ আবার সংযুক্ত করে দেখুন</translation>
<translation id="1165039591588034296">ত্রুটি</translation>
<translation id="1175364870820465910">&amp;প্রিন্ট...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"আপনার কম্পিউটারের সফ্টওয়্যার Chrome-কে নিরাপদে ইন্টারনেটে কানেক্ট করতে বাধা দিচ্ছে" (শুধুমাত্র Windows কম্পিউটারের জন্য)</translation>
<translation id="1294154142200295408">কম্যান্ড-লাইন ভেরিয়েশন</translation>
<translation id="129553762522093515">সম্প্রতি বন্ধ হয়েছে</translation>
+<translation id="1298536327547837046">ম্যালওয়্যার স্ক্যান করা</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />আপনার কুকিজ সাফ করে দেখুন<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">শীঘ্রই বন্ধ করা হবে এমন ফিচার</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">ক্লিপবোর্ডে ছবির জন্য সার্চ করুন</translation>
<translation id="1323433172918577554">আরও দেখুন</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google পত্রক</translation>
<translation id="1527263332363067270">সংযোগের জন্য অপেক্ষা করা হচ্ছে...</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">এখন যে সাইট দেখার চেষ্টা করছেন তা নকল বলে মনে হচ্ছে। ইউআরএলে সামান্য বা সহজে দেখা যায় না এমন পরিবর্তন করে আক্রমণকারীরা সাইট নকল করে।</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">এই পৃষ্ঠায় এটি দেখানো হচ্ছে</translation>
<translation id="153384715582417236">এখন এই পর্যন্তই</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">ব্যাখ্যার জন্য ডকুমেন্টের সাইজ বেশি বড়</translation>
-<translation id="1721312023322545264">এই সাইটে যেতে আপনাকে <ph name="NAME" /> এর কাছ থেকে অনুমতি নিতে হবে</translation>
<translation id="1721424275792716183">* এই ফিল্ডে কিছু লেখা প্রয়োজন</translation>
<translation id="1727741090716970331">সঠিক কার্ড নম্বর যোগ করুন</translation>
<translation id="1728677426644403582">আপনি একটি ওয়েব পৃষ্ঠার উৎস কোড দেখছেন</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">আপনি যে ওয়েবসাইটগুলি দেখেন এবং দেখার জন্য সময় খরচ করেন</translation>
<translation id="1826516787628120939">চেক করা হচ্ছে</translation>
<translation id="1834321415901700177">এই সাইটটিতে ক্ষতিকর প্রোগ্রাম রয়েছে</translation>
+<translation id="1838374766361614909">সার্চ সাফ করুন</translation>
<translation id="1839551713262164453">নীতির মূল্য যাচাইকরণে সমস্যা হওয়ার জন্য যাচাই করা যায়নি</translation>
<translation id="1842969606798536927">পেমেন্ট করুন</translation>
<translation id="1871208020102129563">
@@ -192,6 +197,7 @@
<translation id="1883255238294161206">তালিকা সঙ্কুচিত করুন</translation>
<translation id="1898423065542865115">ফিল্টার হচ্ছে</translation>
<translation id="1914326953223720820">পরিষেবা আনজিপ করুন</translation>
+<translation id="1915697529809968049">সিভিসি কোডের পরিবর্তে টাচ আইডি ব্যবহার করবেন?</translation>
<translation id="1916770123977586577">আপডেট করা সেটিংস এই সাইটে প্রয়োগ করতে পৃষ্ঠাটি আবার লোড করুন</translation>
<translation id="1919345977826869612">বিজ্ঞাপন</translation>
<translation id="1919367280705858090">কোনও নির্দিষ্ট এরর মেসেজের বিষয়ে সাহায্য পান</translation>
@@ -203,6 +209,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> বুকমার্ক</translation>
<translation id="1973335181906896915">ধারাবাহিকতাতে ত্রুটি</translation>
<translation id="1974060860693918893">উন্নত</translation>
+<translation id="1974883374937189061">Google-এ <ph name="BEGIN_WHITEPAPER_LINK" />আপনার দেখা পৃষ্ঠাগুলির ইউআরএল, সিস্টেমের কিছু তথ্য এবং কিছু পৃষ্ঠার কন্টেন্ট<ph name="END_WHITEPAPER_LINK" /> পাঠিয়ে Chrome-এর নিরাপত্তা উন্নত করতে সাহায্য করুন। <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">ফার্মওয়্যার ভার্সন</translation>
<translation id="1981206234434200693">Chrome-এর ব্রাউজিং ইতিহাসের ডেটা মুছুন</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{এবং আরও ১টি}one{এবং আরও #টি}other{এবং আরও #টি}}</translation>
@@ -248,10 +255,12 @@
<translation id="2202020181578195191">মেয়াদ শেষ হওয়ার বছরের সঠিক মান লিখুন</translation>
<translation id="2212735316055980242">নীতি পাওয়া যায়নি</translation>
<translation id="2213606439339815911">এন্ট্রিগুলি আনা হচ্ছে...</translation>
+<translation id="2215727959747642672">ফাইল এডিট করা</translation>
<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />-এ যে আক্রমণকারীরা এই মুহূর্তে সক্রিয় আছে, তারা এমন বিপজ্জনক অ্যাপ ইনস্টল করে দিতে পারে যেগুলি আপনার ডিভাইসের ক্ষতি করতে, আপনার মোবাইলের বিলে লুকানো চার্জ যোগ করতে বা আপনার ব্যক্তিগত তথ্য চুরি করতে পারে৷ <ph name="BEGIN_LEARN_MORE_LINK" />আরও জানুন<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ইন্টারনেট কানেকশন নেই</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />ডায়াগনস্টিক অ্যাপ্লিকেশান<ph name="END_LINK" /> ব্যবহার করে আপনার সংযোগ ঠিক করুন</translation>
<translation id="2239100178324503013">এখনই পাঠান</translation>
+<translation id="2248949050832152960">WebAuthn ব্যবহার করুন</translation>
<translation id="225207911366869382">এই মান এই নীতির জন্য অসমর্থিত হয়েছে৷</translation>
<translation id="2257315177824333709">আপনার কার্ড এখন সেভ করা যাচ্ছে না</translation>
<translation id="2262243747453050782">HTTP ত্রুটি</translation>
@@ -299,7 +308,6 @@
<translation id="2479410451996844060">ভুল সার্চের ইউআরএল৷</translation>
<translation id="2482878487686419369">বিজ্ঞপ্তিগুলি</translation>
<translation id="248348093745724435">মেশিনের নীতি</translation>
-<translation id="2485387744899240041">আপনার ডিভাইস এবং ব্রাউজারের জন্য ইউজারনেম</translation>
<translation id="2491120439723279231">সার্ভারের সার্টিফিকেটে ত্রুটি আছে৷</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON বিশ্লেষক</translation>
@@ -309,6 +317,7 @@
<translation id="2501278716633472235">ফিরে যান</translation>
<translation id="2503184589641749290">ডেবিট ও প্রিপেড কার্ড গ্রহণ করা হয়</translation>
<translation id="2505268675989099013">অ্যাকাউন্ট সুরক্ষিত রাখা</translation>
+<translation id="2515335152965840738">উপেক্ষা করুন</translation>
<translation id="2515629240566999685">আপনার এলাকায় সংকেত পরীক্ষা করে দেখুন</translation>
<translation id="2523886232349826891">শুধুমাত্র এই ডিভাইসে সেভ করা যাবে</translation>
<translation id="2524461107774643265">আরও তথ্য যোগ করুন</translation>
@@ -333,7 +342,6 @@
<translation id="2653659639078652383">জমা দিন</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{একটিও নয়}=1{১টি পাসওয়ার্ড (<ph name="DOMAIN_LIST" />-এর জন্য)}=2{২টি পাসওয়ার্ড (<ph name="DOMAIN_LIST" />-এর জন্য)}one{#টি পাসওয়ার্ড (<ph name="DOMAIN_LIST" />-এর জন্য)}other{#টি পাসওয়ার্ড (<ph name="DOMAIN_LIST" />-এর জন্য)}}</translation>
<translation id="2666117266261740852">অন্যান্য ট্যাব বা অ্যাপ্লিকেশানগুলি বন্ধ করুন</translation>
-<translation id="267371737713284912">পূর্বাবস্থায় ফিরে যেতে <ph name="MODIFIER_KEY_DESCRIPTION" /> টিপুন</translation>
<translation id="2674170444375937751">আপনি কি আপনার ইতিহাস থেকে এই পৃষ্ঠাগুলি মোছার বিষয়ে নিশ্চিত?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">ছেড়ে চলে যান</translation>
@@ -343,12 +351,14 @@
<translation id="2704283930420550640">বিন্যাসের সাথে মূল্য মেলে না৷</translation>
<translation id="2705137772291741111">এই সাইটের সেভ করা (ক্যাশে করা) কপি পড়া যাবে না।</translation>
<translation id="2709516037105925701">স্বয়ংপূরণ</translation>
-<translation id="2712173769900027643">অনুমতি নিন</translation>
<translation id="2713444072780614174">সাদা</translation>
<translation id="2720342946869265578">আশেপাশে</translation>
<translation id="2721148159707890343">অনুরোধ সফল হয়েছে</translation>
<translation id="2728127805433021124">একটি দুর্বল স্বাক্ষর অ্যালগোরিদম ব্যবহার করে সার্ভারের সার্টিফিকেটে সাইন করা হয়েছে৷</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />সংযোগের ডায়গনিস্টিক্স চালান<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">এইসব ফিচার চালু করলে আপনার ব্রাউজ করা ডেটা মুছে যেতে পারে
+ অথবা আপনার নিরাপত্তা বা গোপনীয়তা বিঘ্নিত হতে পারে। চালু করা ফিচারগুলি
+ এই ব্রাউজারের সব ব্যবহারকারীর ক্ষেত্রে প্রযোজ্য হবে।</translation>
<translation id="2735043616039983645">এই নীতির জন্য পরস্পরবিরোধী মান সহ একাধিক উৎস রয়েছে!</translation>
<translation id="2738330467931008676">পিক-আপের ঠিকানা বেছে নিন</translation>
<translation id="2740531572673183784">ঠিক আছে</translation>
@@ -359,16 +369,15 @@
<translation id="2784949926578158345">কানেকশন রিসেট করা হয়েছে৷</translation>
<translation id="2788784517760473862">ক্রেডিট কার্ড গ্রহণ করা হয়</translation>
<translation id="2792012897584536778">এই ডিভাইসের অ্যাডমিনিস্ট্রেটর যে নিরাপত্তার সার্টিফিকেট সেট-আপ করেছেন সেটি তাকে আপনার ঘোরা ওয়েবসাইটগুলির কন্টেন্ট দেখার অনুমতি দিতে পারে।</translation>
-<translation id="2794233252405721443">সাইট অবরুদ্ধ করা হয়েছে</translation>
<translation id="2799020568854403057">যে সাইট খুলতে চলেছেন সেটিতে ক্ষতিকারক অ্যাপ আছে</translation>
<translation id="2799223571221894425">পুনঃশুরু</translation>
<translation id="2803306138276472711">Google নিরাপদ ব্রাউজিং সাম্প্রতিক <ph name="SITE" />-এ <ph name="BEGIN_LINK" />ম্যালওয়্যার শনাক্ত করেছে<ph name="END_LINK" />। যেসব ওয়েবসাইট সাধারণত নিরাপদ থাকে, সেগুলি কখনও কখনও ম্যালওয়্যার দিয়ে আক্রান্ত হয়।</translation>
+<translation id="2815364696811431560">সাইট ছেড়ে বেরিয়ে আসুন</translation>
<translation id="2824775600643448204">ঠিকানা এবং সার্চ দণ্ড</translation>
<translation id="2826760142808435982"><ph name="CIPHER" /> ব্যবহার করে এই সংযোগটি এনক্রিপ্টেড এবং প্রমাণীকৃত করা হয়েছে এবং কী এক্সচেঞ্জ প্রক্রিয়া হিসাবে <ph name="KX" /> ব্যবহার করে৷</translation>
<translation id="2835170189407361413">ফর্ম সাফ করুন</translation>
<translation id="2847118875340931228">ছদ্মবেশী উইন্ডো খুলুন</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">এই সাইট দেখার জন্য আপনার অনুমতির প্রয়োজন</translation>
<translation id="2856444702002559011">আক্রমণকারীরা হয়ত <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> থেকে আপনার তথ্য (যেমন পাসওয়ার্ড, মেসেজ বা ক্রেডিট কার্ড) চুরি করার চেষ্টা করছে। <ph name="BEGIN_LEARN_MORE_LINK" />আরও জানুন<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">কার্ড সেভ করবেন?</translation>
@@ -393,6 +402,7 @@
<translation id="2985306909656435243">চালু করা হলে, ফর্ম পূরণের কাজ দ্রুত করতে Chromium এই ডিভাইসে আপনার কার্ডের একটি কপি স্টোর করবে।</translation>
<translation id="2985398929374701810">একটি সঠিক ঠিকানা লিখুন</translation>
<translation id="2986368408720340940">এই পদ্ধতিতে পিক-আপ করা যাবে না। অন্য পদ্ধতি ব্যবহার করুন।</translation>
+<translation id="2987034854559945715">একই ধরনের ফিচার পাওয়া যায়নি</translation>
<translation id="2991174974383378012">ওয়েবসাইটের সাথে ভাগ করছে</translation>
<translation id="2991571918955627853">ওয়েবসাইটটি HSTS ব্যবহার করার কারণে আপনি এখন <ph name="SITE" />-এ যেতে পারবেন না। নেটওয়ার্ক ত্রুটি এবং আক্রমণ সাধারণত সাময়িকভাবে হয়, তাই এই পৃষ্ঠাটি সম্ভবত পরে কাজ করবে।</translation>
<translation id="3005723025932146533">সেভ করা কপি দেখুন</translation>
@@ -403,6 +413,7 @@
<translation id="3024663005179499861">নীতির ভুল প্রকার</translation>
<translation id="3037605927509011580">ইস!</translation>
<translation id="3041612393474885105">সার্টিফিকেট তথ্য</translation>
+<translation id="3057676462092457419">এখনও <ph name="SECURE_DNS_MODE_SECURE" /> DnsOverHttps মোড কাজ করে না, মোডটি <ph name="SECURE_DNS_MODE_OFF" />-এ সেট করা আছে।</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">প্যাচ পরিষেবা</translation>
<translation id="3064966200440839136">বহিরাগত অ্যাপের মাধ্যমে পেমেন্ট করার জন্য ছদ্মবেশী মোড থেকে বেরিয়ে যাচ্ছে। চালিয়ে যাবেন?</translation>
@@ -428,6 +439,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> এ <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">পেমেন্ট বাতিল করুন</translation>
<translation id="3207960819495026254">বুকমার্ক করা হয়েছে</translation>
+<translation id="3209034400446768650">পৃষ্ঠাটির মাধ্যমে টাকা চার্জ করা হতে পারে</translation>
<translation id="3225919329040284222">সার্ভারটি এমন একটি সার্টিফিকেট উপস্থাপনা করেছে যা বিল্ট-ইন প্রত্যাশাগুলির সাথে মেলে না৷ এই প্রত্যাশাগুলি আপনাকে সুরক্ষিত করতে কিছু নিশ্চিত, উচ্চ সুরক্ষার ওয়েবসাইটের জন্য অন্তর্ভুক্ত৷</translation>
<translation id="3226128629678568754">পৃষ্ঠা লোড করার জন্য প্রয়োজনীয় ডেটা আবার জমা দিতে রিলোড বোতামটি টিপুন৷</translation>
<translation id="3227137524299004712">মাইক্রোফোন</translation>
@@ -435,7 +447,6 @@
<translation id="3229041911291329567">আপনার ডিভাইস এবং ব্রাউজারের ভার্সন সম্বন্ধীয় তথ্য</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" />-এর CVC লিখুন</translation>
<translation id="3234666976984236645">এই সাইটে সবসময় গুরুত্বপূর্ণ কন্টেন্ট শনাক্ত করুন</translation>
-<translation id="3254409185687681395">এই পৃষ্ঠাটি বুকমার্ক করুন</translation>
<translation id="3270847123878663523">&amp;পুনর্বিন্যাসকে পূর্বাবস্থায় ফেরান</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">কার্ডে থাকা নাম যোগ করুন</translation>
@@ -445,7 +456,6 @@
<translation id="3320021301628644560">বিলিংয়ের ঠিকানা যোগ করুন</translation>
<translation id="3324983252691184275">টকটকে লাল</translation>
<translation id="3338095232262050444">সুরক্ষিত</translation>
-<translation id="3345135638360864351">এই সাইটটি অ্যাক্সেস করার জন্য আপনার অনুরোধ <ph name="NAME" /> এ পাঠানো যায়নি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷</translation>
<translation id="3355823806454867987">প্রক্সি সেটিংস পরিবর্তন করুন...</translation>
<translation id="3361596688432910856">Chrome এ নিম্নলিখিত তথ্য <ph name="BEGIN_EMPHASIS" />সংরক্ষণ করা হয় না<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -479,18 +489,15 @@
<translation id="3462200631372590220">উন্নত করার বিশদ বিবরণ, লুকান</translation>
<translation id="3467763166455606212">কার্ডহোল্ডারের নাম প্রয়োজন</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, এখন খোলা আছে, খোলা ট্যাবে যেতে ট্যাব প্রেস করে এন্টার প্রেস করুন</translation>
-<translation id="3479539252931486093">এটি কি অপ্রত্যাশিত ছিল? <ph name="BEGIN_LINK" />আমাদেরকে জানান<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">এখনই নয়</translation>
<translation id="3484560055331845446">আপনি আপনার Google অ্যাকাউন্টে অ্যাক্সেস হারাতে পারেন। Chrome-এর প্রস্তাব হল যে আপনি আপনার পাসওয়ার্ড এখনই পরিবর্তন করুন। আপনাকে আবার সাইন-ইন করতে বলা হবে।</translation>
<translation id="3495081129428749620">এই পৃষ্ঠাতে খুঁজুন
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">আমরা এই মুহূর্তে আপনার পিতামাতার সাথে যোগাযোগ করতে পারিনি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷</translation>
<translation id="3512163584740124171">একই নীতির গ্রুপের অন্য একটি নীতি অগ্রাধিকার পেয়েছে, তাই এই নীতি অগ্রাহ্য করা হয়েছে।</translation>
<translation id="3528171143076753409">সার্ভারের সার্টিফিকেট বিশ্বস্ত নয়৷</translation>
<translation id="3528485271872257980">গাঢ় বাদামি</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{সিঙ্ক করা ডিভাইসে কমপক্ষে ১টি আইটেম}=1{১টি আইটেম (এবং সিঙ্ক করা ডিভাইসে আরও)}one{#টি আইটেম (এবং সিঙ্ক করা ডিভাইসে আরও)}other{#টি আইটেম (এবং সিঙ্ক করা ডিভাইসে আরও)}}</translation>
<translation id="3539171420378717834">এই ডিভাইসে কার্ডটির একটি কপি রাখুন</translation>
-<translation id="3556433843310711081">আপনার পরিচালক আপনার হয়ে এটি অবরোধ মুক্ত করতে পারবে</translation>
<translation id="3566021033012934673">আপনার সংযোগ ব্যক্তিগত নয়</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> এ এম্বেডেড করা পৃষ্ঠায় এটি দেখানো হচ্ছে</translation>
@@ -518,6 +525,7 @@
<translation id="3678529606614285348">নতুন ছদ্মবেশী উইন্ডোতে (Ctrl-Shift-N) করে একটি পৃষ্ঠা খুলুন</translation>
<translation id="3679803492151881375">ক্র্যাশ রিপোর্ট <ph name="CRASH_TIME" />-এ ক্যাপচার করা হয়েছে, <ph name="UPLOAD_TIME" />-এ আপলোড করা হয়েছে</translation>
<translation id="3681007416295224113">সার্টিফিকেট তথ্য</translation>
+<translation id="3701427423622901115">সব এক্সপেরিমেন্ট রিসেট ভ্যালুতে সেট করা হয়েছে, Chrome রিস্টার্ট করার পর এই পরিবর্তনগুলি প্রয়োগ করা হবে।</translation>
<translation id="3704162925118123524">আপনি যে নেটওয়ার্কটি ব্যবহার করছেন সেটির জন্য অপনাকে এটির লগ-ইন পৃষ্ঠাতে যেতে হতে পরে৷</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">লোড হচ্ছে...</translation>
@@ -534,6 +542,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />-এর আক্রমণকারীরা আপনাকে সফ্টওয়্যার ইনস্টলেশন বা আপনার ব্যক্তিগত তথ্য (যেমন পাসওয়ার্ড, ফোন নম্বর বা ক্রেডিট কার্ড) প্রকাশ করার মত বিপজ্জনক কাজ করার জন্য আপনাকে প্রতারিত করতে পারে। <ph name="BEGIN_LEARN_MORE_LINK" />আরও জানুন<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">একটি সার্ভার ত্রুটির কারণে অনুবাদ ব্যর্থ হয়েছে৷</translation>
<translation id="3759461132968374835">আপনার কাছে সাম্প্রতিক প্রতিবেদন করা কোনও ক্র্যাশ নেই৷ ক্র্যাশ প্রতিবেদন অক্ষম থাকাকালীন ঘটা ক্র্যাশ এখানে উপস্থিত হবে না৷</translation>
+<translation id="3760561303380396507">সিভিসি কোডের পরিবর্তে Windows Hello ব্যবহার করবেন?</translation>
<translation id="3761718714832595332">স্ট্যাটাসটি লুকান</translation>
<translation id="3765032636089507299">নিরাপদ ব্রাউজিং পৃষ্ঠা তৈরি করা হচ্ছে।</translation>
<translation id="3778403066972421603">আপনি কি এই কার্ডটি আপনার Google অ্যাকাউন্টে ও এই ডিভাইসে সেভ করতে চান?</translation>
@@ -543,6 +552,7 @@
<translation id="3789155188480882154">সাইজ ১৬</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">ক্ষতিকর কন্টেন্ট ব্লক করা হয়েছে।</translation>
+<translation id="3808375843007691220">সতর্কতা: পরীক্ষামূলক বৈশিষ্ট্যটি চালু আছে!</translation>
<translation id="3810973564298564668">পরিচালনা</translation>
<translation id="382518646247711829">যদি আপনি একটি প্রক্সি সার্ভার ব্যবহার করেন...</translation>
<translation id="3828924085048779000">ফাঁকা পাসফ্রেজের অনুমতি নেই৷</translation>
@@ -551,11 +561,11 @@
<translation id="3858027520442213535">তারিখ এবং সময় আপডেট করুন</translation>
<translation id="3884278016824448484">পরস্পর বিরোধী ডিভাইস সনাক্তকারী</translation>
<translation id="3885155851504623709">প্যারিশ</translation>
-<translation id="3886446263141354045">এই সাইটটি অ্যাক্সেস করার জন্য আপনার অনুরোধ <ph name="NAME" />কে পাঠানো হয়েছে</translation>
<translation id="3890664840433101773">ইমেল আইডি যোগ করুন</translation>
<translation id="3901925938762663762">কার্ডটির মেয়াদ শেষ হয়েছে</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">সিভিসি কোডের পরিবর্তে WebAuthn ব্যবহার করবেন?</translation>
<translation id="3946209740501886391">এই সাইটে সর্বদা জিজ্ঞাসা করুন</translation>
<translation id="3949571496842715403">এই সার্ভারটিকে <ph name="DOMAIN" /> হিসাবে প্রমাণ করা যায়নি; এটির নিরাপত্তা সার্টিফিকেটে সাবজেক্ট অল্টারনেটিভ নেম্স নির্দিষ্ট করা নেই। কনফিগারেশনের কোনও সমস্যা অথবা আপনার সংযোগে কোনও আক্রমণকারী আড়ি পাতার কারণে এটি হয়ে থাকতে পারে।</translation>
<translation id="3949601375789751990">আপনার ব্রাউজিং এর ইতিহাস এখানে দেখা যায়</translation>
@@ -566,11 +576,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{কিছুই নয়}=1{১টি সাইট থেকে }one{#টি সাইট থেকে }other{#টি সাইট থেকে }}</translation>
<translation id="397105322502079400">গণনা করা হচ্ছে...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> অবরুদ্ধ হয়ে রয়েছে</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> আপনার ব্রাউজারে Chrome এন্টারপ্রাইজ থ্রেট প্রোটেকশন চালু করেছে। Chrome এন্টারপ্রাইজ থ্রেট প্রোটেকশন আপনার কিছু ডেটা অ্যাক্সেস করতে পারে।</translation>
<translation id="3987940399970879459">১ এমবির কম</translation>
<translation id="40103911065039147">{URL_count,plural, =1{আশেপাশের ১টি ওয়েবপৃষ্ঠা}one{আশেপাশের #টি ওয়েবপৃষ্ঠা}other{আশেপাশের #টি ওয়েবপৃষ্ঠা}}</translation>
<translation id="4030383055268325496">&amp;যোগ করাকে পূর্বাবস্থায় ফেরান</translation>
<translation id="4032320456957708163"><ph name="ENROLLMENT_DOMAIN" /> আপনার ব্রাউজার ম্যানেজ করে</translation>
-<translation id="4034375457890803692">আপনার খোলা লিঙ্কটি এমন কোনও সাইটে নিয়ে যায়, যেখানে সাধারণত আপনি যান না। এটি আপনাকে সম্ভবত বিভ্রান্ত করার চেষ্টা করছে।</translation>
<translation id="4058922952496707368">কী "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">সঠিক ঠিকানা যোগ করুন</translation>
@@ -583,6 +593,7 @@
<translation id="4103249731201008433">ডিভাইসের ক্রমিক সংখ্যা ভুল</translation>
<translation id="410351446219883937">স্বতঃচালানো</translation>
<translation id="4103763322291513355">কালো তালিকাভুক্ত ইউআরএলগুলির তালিকা এবং আপনার সিস্টেম অ্যাডমিনিস্ট্রেটরের প্রয়োগ করা অন্যান্য নীতিগুলি দেখার জন্য &lt;strong&gt;chrome://policy&lt;/strong&gt;-এ যান৷</translation>
+<translation id="4108231218301530806">পরের বার এই কার্ড যাচাই করতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন।</translation>
<translation id="4110652170750985508">আপনার পেমেন্টের রিভিউ</translation>
<translation id="4112140312785995938">পিছিয়ে যান</translation>
<translation id="4116663294526079822">এই সাইটে সর্বদা অনুমতি দিন</translation>
@@ -597,6 +608,7 @@
<translation id="4171400957073367226">খারাপ যাচাইকরণের স্বাক্ষর</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{আরও <ph name="ITEM_COUNT" />টি আইটেম}one{আরও <ph name="ITEM_COUNT" />টি আইটেম}other{আরও <ph name="ITEM_COUNT" />টি আইটেম}}</translation>
+<translation id="4176463684765177261">অক্ষম হয়েছে</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">পরের বার আরও দ্রুত পে করতে, আপনার Google অ্যাকাউন্টে কার্ড ও বিলিংয়ের ঠিকানা যোগ করে রাখুন।</translation>
<translation id="4196861286325780578">&amp;সরানোর কাজটি আবার করুন</translation>
@@ -633,6 +645,7 @@
<translation id="4277028893293644418">পাসওয়ার্ড রিসেট করুন</translation>
<translation id="4279811152705618813"><ph name="ENROLLMENT_DOMAIN" /> আপনার <ph name="DEVICE_TYPE" /> ম্যানেজ করে</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{এই কার্ডটি আপনার Google অ্যাকাউন্টে সেভ করা হয়েছে}one{এই কার্ডগুলি আপনার Google অ্যাকাউন্টে সেভ করা হয়েছে}other{এই কার্ডগুলি আপনার Google অ্যাকাউন্টে সেভ করা হয়েছে}}</translation>
+<translation id="428847186335018806">Chrome-এ ডাউনলোড বা আপলোড করা ফাইল স্ক্যান করুন।</translation>
<translation id="42981349822642051">প্রসারিত করুন</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">পাল্টান</translation>
@@ -662,7 +675,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">প্রক্সির ব্যবহার অক্ষম করা হয়েছে কিন্তু কোনো স্পষ্ট প্রক্সি কনফিগারেশান নির্দিষ্ট করা হয়েছে৷</translation>
<translation id="445100540951337728">ডেবিট কার্ড গ্রহণ করা হয়</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> সন্দেহজনক ব্যবহার</translation>
<translation id="4466881336512663640">ফর্মে করা পরিবর্তনগুলি সেভ হবে না। আপনি কি চালিয়ে যেতে চান?</translation>
<translation id="4477350412780666475">পরের ট্র্যাক চালান</translation>
<translation id="4482953324121162758">এই সাইটটি অনুবাদ করা হবে না।</translation>
@@ -689,6 +701,7 @@
<translation id="4594403342090139922">&amp;মুছে ফেলাকে পূর্বাবস্থায় ফেরান</translation>
<translation id="4597348597567598915">সাইজ ৮</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">সার্চের ফিচার</translation>
<translation id="4646534391647090355">আমাকে এখনই সেখানে নিয়ে চলুন</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">এই সার্ভার প্রমাণ করতে পারেনি যে এটি <ph name="DOMAIN" />; এর নিরাপত্তা সার্টিফিকেটে কিছু ত্রুটি আছে। কোনো ভুল কনফিগারেশনের কারণে অথবা কোনো আক্রমণকারী আপনার সংযোগ মাঝপথে আটকে দিচ্ছে বলে এমনটা হতে পারে।</translation>
@@ -697,7 +710,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">আপনার সংযোগ বাধাপ্রাপ্ত হয়েছে</translation>
-<translation id="471880041731876836">এই সাইট দেখার অনুমতি আপনার নেই</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows নেটওয়ার্ক ডায়গনিস্টিক্স চালান<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">নীতিগুলি রিলোড করুন</translation>
<translation id="4728558894243024398">প্ল্যাটফর্ম</translation>
@@ -725,7 +737,6 @@
<translation id="4816492930507672669">পৃষ্ঠাতে মানানসই</translation>
<translation id="4850886885716139402">দেখুন</translation>
<translation id="4854362297993841467">এই পদ্ধতিতে ডেলিভারি করা যাবে না। অন্য পদ্ধতি ব্যবহার করুন।</translation>
-<translation id="4858792381671956233">এই পৃষ্ঠাটি দেখার জন্য উপযুক্ত কিনা তা আপনি আপনার অভিভাবককে জিজ্ঞাসা করেছেন</translation>
<translation id="4864052566555297930">সুরক্ষা সংক্রান্ত পরামর্শ:</translation>
<translation id="4876188919622883022">সরলীকৃত ভিউ</translation>
<translation id="4876305945144899064">কোনও ব্যবহারকারীর নাম নেই</translation>
@@ -749,7 +760,9 @@
<translation id="4974590756084640048">সতর্কবার্তাগুলি পুনঃসক্ষম করুন</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">সবগুলি দেখুন</translation>
+<translation id="4989542687859782284">উপলভ্য নেই</translation>
<translation id="4989809363548539747">এই প্লাগ-ইন সমর্থিত নয়</translation>
+<translation id="4995216769782533993">এই সাইটের সাথে আপনার কার্ডের বিবরণ শেয়ার করতে নিরাপত্তা কোডটি কনফার্ম করুন</translation>
<translation id="5002932099480077015">সক্রিয় করা হলে, ফর্ম পূরণের কাজ দ্রুত করতে Chrome এই ডিভাইসে আপনার কার্ডের একটি কপি স্টোর করবে।</translation>
<translation id="5015510746216210676">মেশিনের নাম:</translation>
<translation id="5017554619425969104">আপনার কপি করা টেক্সট</translation>
@@ -778,6 +791,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(৬৪-বিট)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">আপনার কার্ডটি যাচাই করুন</translation>
<translation id="5135404736266831032">ঠিকানাগুলি পরিচালনা করুন...</translation>
<translation id="5138227688689900538">কম দেখুন</translation>
<translation id="5141240743006678641">আপনার Google সার্টিফিকেটের সাথে সিঙ্ক করা পাসওয়ার্ডগুলি এনক্রিপ্ট করুন৷</translation>
@@ -804,6 +818,7 @@
<translation id="5251803541071282808">ক্লাউড</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">যেসব ফিচার সিস্টেম জুড়ে প্রয়োগ করা হয় সেগুলি শুধুমাত্র মালিক সেট করতে পারবেন: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">সতর্কতা: এই নীতি ডিকশনারি নীতির অংশ নয় বলে এটিকে PolicyDictionaryMultipleSourceMergeList নীতি অনুযায়ী মার্জ করা হয়নি।</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">শেষ</translation>
@@ -827,7 +842,6 @@
<translation id="536296301121032821">নীতি সেটিংস সংরক্ষণ করতে ব্যর্থ হয়েছে</translation>
<translation id="5371425731340848620">কার্ড আপডেট করুন</translation>
<translation id="5377026284221673050">"আপনার ঘড়ি লেটে চলছে" অথবা "আপনার ঘড়ি ফাস্ট আছে" অথবা "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">এই পৃষ্ঠাটি হয়ত আপনাকে প্রতারণা করার চেষ্টা করতে পারে, ব্যক্তিগত তথ্য চুরি করতে বা আপনার ডিভাইসের ক্ষতি করতে পারে। ব্যক্তিগত তথ্য লেখার সময় বা ডাউনলোড করা ফাইল খোলার সময় সতর্ক থাকুন।</translation>
<translation id="5384855140246857529">সমস্ত ডিভাইসে আপনার কার্ড ব্যবহার করতে, সাইন-ইন করে সিঙ্ক চালু করুন।</translation>
<translation id="5386426401304769735">এই সাইটের সার্টিফিকেট শৃঙ্খলে SHA-1 ব্যবহার করে স্বাক্ষর করা একটি সার্টিফিকেট রয়েছে।</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -841,6 +855,8 @@
<translation id="5457113250005438886">ভুল</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />টি}one{<ph name="CONTACT_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />টি}other{<ph name="CONTACT_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />টি}}</translation>
<translation id="5470861586879999274">&amp;সম্পাদনাকে আবার করুন</translation>
+<translation id="5473728911100096288">এইসব ফিচার চালু করে, আপনি শীঘ্রই বন্ধ করে দেওয়া হবে এমন ফিচার ব্যবহার
+ করতে চলেছেন যা পরবর্তী ভার্সনগুলিতে আর পাওয়া যাবে না।</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">এই কন্টেন্ট আপনার ডিভাইসে এমন বিপজ্জনক সফ্টওয়্যার ইনস্টল করার চেষ্টা করতে পারে যা আপনার তথ্য চুরি করে বা মুছে দেয়। <ph name="BEGIN_LINK" />তবুও এটি দেখতে চাই<ph name="END_LINK" /></translation>
<translation id="54817484435770891">বৈধ ঠিকানা যোগ করুন</translation>
@@ -864,7 +880,6 @@
<translation id="5570825185877910964">অ্যাকাউন্ট সুরক্ষিত রাখুন</translation>
<translation id="5571083550517324815">এই ঠিকানা থেকে পিক-আপ করা যাবে না। অন্য ঠিকানা বেছে নিন।</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{১টি ব্যবহৃত হচ্ছে}one{#টি ব্যবহৃত হচ্ছে}other{#টি ব্যবহৃত হচ্ছে}})</translation>
-<translation id="5572851009514199876">আপনার এই সাইটে অ্যাক্সেস আছে কিনা, তা দেখার জন্য Chrome চালু করে সাইন-ইন করুন।</translation>
<translation id="5580958916614886209">আপনার মেয়াদ শেষের মাস পরীক্ষা করে আবার চেষ্টা করুন</translation>
<translation id="5586446728396275693">কোনও ঠিকানা সংরক্ষণ করা নেই</translation>
<translation id="5595485650161345191">ঠিকানা সম্পাদনা করুন</translation>
@@ -872,6 +887,7 @@
<translation id="560412284261940334">পরিচালনা সমর্থিত নয়</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">এই সাইটটি জাল বা প্রতারণামূলক হতে পারে। Chrome এখনই আপনাকে সাইটটি ছেড়ে বেরিয়ে আসতে সাজেস্ট করছে।</translation>
<translation id="5610142619324316209">সংযোগ পরীক্ষা করে দেখুন</translation>
<translation id="5610807607761827392">আপনি <ph name="BEGIN_LINK" />সেটিংস<ph name="END_LINK" /> থেকে কার্ড এবং ঠিকানাগুলি পরিচালনা করতে পারেন।</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> আপনাকে অনেক বেশিবার পুনঃনির্দেশিত করেছে।</translation>
@@ -895,11 +911,11 @@
<translation id="5720705177508910913">বর্তমান ব্যবহারকারী</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome-এর নীতি অনুযায়ী আপনার পাসওয়ার্ড বদলে ফেলা উচিত যদি আপনি সেটি অন্য কোনও সাইটে ব্যবহার করে থাকেন।</translation>
-<translation id="5732392974455271431">আপনার পিতামাতা এটি আপনার জন্য অবরোধ মুক্ত করতে পারবেন</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Google অ্যাকাউন্টে কার্ড সেভ করুন}one{Google অ্যাকাউন্টে কার্ড সেভ করুন}other{Google অ্যাকাউন্টে কার্ড সেভ করুন}}</translation>
<translation id="5763042198335101085">একটি সঠিক ইমেল আইডি লিখুন</translation>
<translation id="5765072501007116331">ডেলিভারির পদ্ধতি এবং প্রয়োজনীয়তাগুলি দেখতে একটি ঠিকানা বেছে নিন</translation>
<translation id="5778550464785688721">MIDI ডিভাইসসমূহ পূর্ণ নিয়ন্ত্রণ</translation>
+<translation id="5781136890105823427">এক্সপেরিমেন্ট চালু করা হয়েছে</translation>
<translation id="578305955206182703">হলুদাভ বাদামি</translation>
<translation id="57838592816432529">মিউট করুন</translation>
<translation id="5784606427469807560">আপনার কার্ডটি নিশ্চিত করতে একটি সমস্যা হয়েছিল৷ আপনার ইন্টারনেট সংযোগ পরীক্ষা করে আবার চেষ্টা করুন৷</translation>
@@ -916,13 +932,16 @@
<translation id="5860033963881614850">বন্ধ করুন</translation>
<translation id="5863847714970149516">পরের পৃষ্ঠাতে আপনাকে চার্জ করা হতে পারে</translation>
<translation id="5866257070973731571">ফোন নম্বর যোগ করুন</translation>
+<translation id="5866898949289125849">আপনি ডেভেলপারের টুল পৃষ্ঠা দেখছেন</translation>
<translation id="5869405914158311789">এই সাইটটিতে পৌছানো যাচ্ছে না</translation>
<translation id="5869522115854928033">সংরক্ষিত পাসওয়ার্ড</translation>
<translation id="5887400589839399685">কার্ড সেভ করা হয়েছে</translation>
<translation id="5893752035575986141">ক্রেডিট কার্ড গ্রহণ করা হয়।</translation>
+<translation id="5895138241574237353">পুনর্সূচনা</translation>
<translation id="5901630391730855834">হলুদ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (সিঙ্ক হয়েছে)</translation>
<translation id="5916664084637901428">চালু</translation>
+<translation id="59174027418879706">সক্ষমিত</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google অ্যাকাউন্টে কার্ড সেভ করবেন?</translation>
<translation id="5922853866070715753">প্রায় শেষ</translation>
@@ -956,6 +975,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">আপনার সমস্ত ডিভাইসে কার্ডগুলি ব্যবহার করবেন?</translation>
<translation id="6059925163896151826">USB ডিভাইসগুলি</translation>
+<translation id="6060009363608157444">ভুল DnsOverHttps মোড।</translation>
<translation id="6080696365213338172">অ্যাডমিনিস্ট্রেটরের দ্বারা সরবরাহ করা সার্টিফিকেট ব্যবহার করে আপনি কন্টেন্ট ব্যবহার করেছেন৷ <ph name="DOMAIN" />-কে আপনি যে ডেটা সরবরাহ করেন তাতে আপনার অ্যাডমিনিস্ট্রেটর বাধা দিতে পারে৷</translation>
<translation id="6094273045989040137">ব্যাখ্যা করুন</translation>
<translation id="610911394827799129"><ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />-এ আপনার Google অ্যাকাউন্টের অন্যান্য ধরনের ব্রাউজিংয়ের ইতিহাস থাকতে পারে</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">বুকমার্ক সম্পাদনা করুন</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Enter the expiration date and CVC for <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">এই পৃষ্ঠাটিতে যাওয়া ঠিক হবে কিনা সেই বিষয়ে আপনি আপনার অভিভাবকের অনুমতি নিন৷</translation>
<translation id="6415778972515849510">আপনার পাসওয়ার্ড পরিবর্তন করে Google অ্যাকাউন্ট সুরক্ষিত রাখতে Chromium সাহায্য করতে পারবে।</translation>
-<translation id="6417515091412812850">সার্টিফিকেটকরণটি প্রত্যাহার করা হয়েছে কিনা তা যাচাইয়ে অক্ষম৷</translation>
<translation id="6431585503458005759">সেভ করতে হবে না</translation>
<translation id="6433490469411711332">পরিচিতি তথ্য সম্পাদনা করুন</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> সংযোগ করতে প্রত্যাখ্যান করেছে।</translation>
<translation id="6434309073475700221">বাতিল</translation>
+<translation id="6435221585574090192">আপনার অ্যাডমিনিস্ট্রেটরের সাথে Chrome এন্টারপ্রাইজ থ্রেট প্রোটেকশন দ্বারা ফ্ল্যাগ করা হয়েছে এমন নিরাপত্তা সংক্রান্ত ঘটনা সম্পর্কিত ডেটা শেয়ার করুন। এর মধ্যে পৃষ্ঠার ইউআরএল, ফাইলের নাম ও মেটাডেটা, আপনার ডিভাইসের ব্যবহারকারীর নাম এবং Chrome-এর ব্যবহারকারীর নাম থাকতে পারে।</translation>
<translation id="6440503408713884761">এড়ানো হয়েছে</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">আরও তথ্য যোগ করুন</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">পাসওয়ার্ড পরিচালনা করুন...</translation>
<translation id="647261751007945333">ডিভাইস নীতিগুলি</translation>
<translation id="6476284679642588870">পেমেন্টের পদ্ধতি ম্যানেজ করুন</translation>
-<translation id="6477321094435799029">Chrome এই পৃষ্ঠাতে অস্বাভাবিক কোড পেয়েছে এবং আপনার ব্যক্তিগত তথ্যের (উদাহরণস্বরূপ, পাসওয়ার্ড, ফোন নম্বর, এবং ক্রেডিট কার্ড) সুরক্ষার জন্য এটি অবরুদ্ধ করেছে।</translation>
<translation id="6489534406876378309">ক্র্যাশগুলি আপলোড করা শুরু করুন</translation>
<translation id="6499038740797743453">পাসওয়ার্ড রিসেট করবেন?</translation>
<translation id="6507833130742554667">ক্রেডিট ও ডেবিট কার্ড গ্রহণ করা হয়।</translation>
<translation id="650855688985305916">হ্যাঁ, সেভ করুন</translation>
<translation id="6508722015517270189">Chrome পুনরায় চালু করুন</translation>
<translation id="6517596291481585650">সতর্কতা: এই নীতি কোনও তালিকা নয় বলে সেটি নীতি অনুযায়ী তালিকা হিসেবে মার্জ করা হয়নি।</translation>
+<translation id="6518133107902771759">যাচাই করুন</translation>
<translation id="6521745193039995384">অ্যাক্টিভ নয়</translation>
<translation id="6529602333819889595">&amp;মুছে ফেলাকে আবার করুন</translation>
<translation id="6534179046333460208">বাস্তবিক ওয়েব প্রস্তাবনাগুলি</translation>
<translation id="6545864417968258051">ব্লুটুথ স্ক্যানিং</translation>
<translation id="6554795675067793129">আপনার অ্যাকাউন্ট <ph name="ENROLLMENT_DOMAIN" /> ম্যানেজ করে।</translation>
<translation id="6556866813142980365">আবার করুন</translation>
-<translation id="6563469144985748109">আপনার পরিচালক এখনও এটি অনুমোদন করেন নি</translation>
<translation id="6569060085658103619">আপনি একটি এক্সটেনশন পৃষ্ঠা দেখছেন</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">হালকা গোলাপি</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">সাফ করুন</translation>
<translation id="6644283850729428850">এই নীতিটি অসমর্থিত হয়েছে৷</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{কিছুই নয়}=1{১টি সাইট থেকে (আপনাকে আপনার Google অ্যাকাউন্ট থেকে সাইন-আউট করা হবে না)}one{#টি সাইট থেকে (আপনাকে আপনার Google অ্যাকাউন্ট থেকে সাইন-আউট করা হবে না)}other{#টি সাইট থেকে (আপনাকে আপনার Google অ্যাকাউন্ট থেকে সাইন-আউট করা হবে না)}}</translation>
+<translation id="6652101503459149953">Windows Hello ব্যবহার করুন</translation>
<translation id="6657585470893396449">পাসওয়ার্ড</translation>
<translation id="6670613747977017428">সুরক্ষিত জায়গায় ফিরুন।</translation>
<translation id="6671697161687535275">Chromium থেকে ফর্ম প্রস্তাবনা সরাবেন?</translation>
<translation id="6685834062052613830">সাইন-আউট করে সেট-আপ সম্পূর্ণ করুন</translation>
<translation id="6689271823431384964">আপনি সাইন-ইন করে আছেন বলে, Chrome আপনার কার্ডগুলি Google অ্যাকাউন্টে সেভ করতে চান কিনা তা জানতে চাইছে। সেটিংস থেকে আপনি এই বিকল্প পরিবর্তন করতে পারেন। আপনার অ্যাকাউন্ট থেকেই কার্ডহোল্ডারের নাম পাওয়া গেছে।</translation>
+<translation id="6707256370811247129">Chrome-এ আপনার ডাউনলোড বা আপলোড করা ক্যাশে এবং ফাইলগুলির কন্টেন্ট স্ক্যান করুন।</translation>
<translation id="6710213216561001401">পূর্ববর্তী</translation>
<translation id="6710594484020273272">&lt;সার্চের পদ লিখুন&gt;</translation>
<translation id="671076103358959139">নথিভুক্ত করার জন্য টোকেন:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394"><ph name="TIME" />-এ আপনার <ph name="BEGIN_LINK" />সিঙ্ক পাসফ্রেজ<ph name="END_LINK" /> দিয়ে ডেটা এনক্রিপ্ট করা হয়েছিল। সিঙ্ক শুরু করতে সেটি লিখুন।</translation>
<translation id="674375294223700098">অজানা সার্ভার সার্টিফিকেট ত্রুটি৷</translation>
<translation id="6744009308914054259">কানেকশনের জন্য অপেক্ষা করার সময়, আপনি ডাউনলোডে গিয়ে অফলাইন নিবন্ধগুলি পড়তে পারেন।</translation>
+<translation id="6747611005629681221">সতর্কতা: এরপর শীঘ্রই বন্ধ করা হবে এমন ফিচার আছে!</translation>
<translation id="6753269504797312559">নীতি মান</translation>
<translation id="6757797048963528358">আপনার ডিভাইস নিদ্রা মোডে গিয়েছে।</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">আপনার পিতামাতা এখনও এটি অনুমোদন করেন নি</translation>
<translation id="67862343314499040">বেগুনি</translation>
<translation id="6786747875388722282">এক্সটেনশানসমূহ</translation>
<translation id="6790428901817661496">চালু করুন</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">এই ফিল্ডটি ফাঁকা রাখা যাবে না</translation>
<translation id="6810899417690483278">কাস্টমাইজেশন আইডি</translation>
<translation id="6825578344716086703">আপনি <ph name="DOMAIN" />-এ পৌঁছানোর প্রচেষ্টা করেছেন, কিন্তু সার্ভারটি একটি দুর্বল অ্যালগারিদম স্বাক্ষর (যেমন SHA-1) ব্যবহার করে একটি স্বাক্ষরিত সার্টিফিকেট উপস্থাপন করেছে। এর অর্থ হল সার্ভার যে সুরক্ষা প্রমাণপত্রাদি উপস্থাপন করেছে তা জাল হতে পারে এবং সার্ভারটি আপনার প্রত্যাশিত সার্ভার নাও হতে পারে (হতে পারে আপনি একজন আক্রমণকারীর সাথে যোগাযোগ করছেন)।</translation>
+<translation id="6826370046007623921">ডেটা হারানো প্রতিরোধ</translation>
<translation id="6831043979455480757">অনুবাদ</translation>
<translation id="6839929833149231406">এলাকা</translation>
<translation id="6852204201400771460">আবার অ্যাপ লোড করতে চান?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">নীতি স্তর সমর্থিত নয়।</translation>
<translation id="6895330447102777224">আপনার কার্ডটি নিশ্চিত করা হয়েছে</translation>
<translation id="6897140037006041989">ব্যবহারকারী এজেন্ট</translation>
-<translation id="6903319715792422884">সিস্টেমের কিছু <ph name="BEGIN_WHITEPAPER_LINK" />তথ্য এবং পৃষ্ঠার কন্টেন্ট<ph name="END_WHITEPAPER_LINK" /> Google-কে পাঠানোর মাধ্যমে আপনি নিরাপদ ব্রাউজিং আরও ভাল করে তুলতে সহায়তা করতে পারেন। <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ব্যবহারকারী:</translation>
<translation id="6934672428414710184">এই নাম আপনার Google অ্যাকাউন্ট থেকে নেওয়া</translation>
<translation id="6944692733090228304">আপনার <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />-এর নয় এমন একটি সাইটে আপনার পাসওয়ার্ড লিখেছেন। আপনার অ্যাকাউন্টের সুরক্ষার জন্য অন্যান্য অ্যাপ এবং সাইটে আপনার এই পাসওয়ার্ডটি ব্যবহার করবেন না।</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />টি}one{<ph name="PAYMENT_METHOD_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />টি}other{<ph name="PAYMENT_METHOD_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />টি}}</translation>
<translation id="7153618581592392745">ল্যাভেণ্ডার</translation>
<translation id="717330890047184534">Gaia আইডি:</translation>
+<translation id="7174545416324379297">মার্জ করা হয়েছে</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />টি}one{<ph name="SHIPPING_OPTION_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />টি}other{<ph name="SHIPPING_OPTION_PREVIEW" /> এবং আরও <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />টি}}</translation>
<translation id="7177397715882417099">আপনি যে সার্ভারে যাচ্ছেন, <ph name="ORIGIN" />, সেটিতে করা যেকোনও অনুরোধের জন্যই একটি নিরাপত্তা নীতি
প্রযুক্ত হবে বলে সেটি জানাচ্ছে। কিন্তু এটি
@@ -1166,6 +1187,7 @@
<translation id="7320336641823683070">কানেকশন সহায়তা</translation>
<translation id="733354035281974745">ডিভাইসের স্থানীয় অ্যাকাউন্ট ওভাররাইড করা</translation>
<translation id="7334320624316649418">&amp;পুনর্বিন্যাসকে আবার করুন</translation>
+<translation id="7337706099755338005">আপনার প্ল্যাটফর্মে উপলভ্য নেই।</translation>
<translation id="733923710415886693">সার্ভারের সার্টিফিকেটটি সার্টিফিকেটের স্বচ্ছতার মাধ্যমে প্রকাশ করা হয়নি।</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">অ্যাফিলিয়েট কিনা:</translation>
@@ -1197,7 +1219,6 @@
<translation id="7440140511386898319">অফলাইন থাকা অবস্থায় দেখুন</translation>
<translation id="7441627299479586546">ভুল বিষয় বিশিষ্ট নীতি</translation>
<translation id="7442725080345379071">হালকা কমলা</translation>
-<translation id="7444046173054089907">সাইটটি অবরুদ্ধ</translation>
<translation id="7445762425076701745">আপনি যে সার্ভারে সংযুক্ত রয়েছে সেটিকে সম্পূর্ণ যাচাই করতে পারা যায় না৷ আপনি নামগুলি দিয়ে এমন একটি সার্ভারে সংযুক্ত রয়েছেন যা আপনার নেটওয়ার্কে বৈধ, যেটি একটি বাহ্যিক শংসাকরণ কর্তৃপক্ষ যার এটির মালিকানা যাচাই করার কোনও উপায় নেই৷ কিছু সার্টিফিকেট কর্তৃপক্ষ এই নামগুলি নির্বিচারে সার্টিফিকেটগুলি ইস্যু করবে, আপনি উদ্দিষ্ট ওয়েবসাইটে সংযুক্ত রয়েছেন কোনও আক্রমণকারীতে নয় তা নিশ্চিত করার কোনও উপায় নেই৷</translation>
<translation id="7451311239929941790">এই সমস্যা সম্পর্কে <ph name="BEGIN_LINK" />আরও জানুন<ph name="END_LINK" />।</translation>
<translation id="7455133967321480974">বিশ্বব্যাপী ডিফল্ট ব্যবহার করুন (অবরোধ করুন)</translation>
@@ -1219,9 +1240,9 @@
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">আপনি নিশ্চিত করলে আপনার কার্ডের বিবরণ এই সাইটের সাথে শেয়ার করা হবে।</translation>
<translation id="7542995811387359312">স্বয়ংক্রিয় ক্রেডিট কার্ড পূরণটি অক্ষম রয়েছে কারণ এই ফর্মটি কোনও সুরক্ষিত সংযোগ ব্যবহার করে না৷</translation>
-<translation id="7543525346216957623">আপনার বাবা-মাকে জিজ্ঞাসা করুন</translation>
<translation id="7548892272833184391">কানেকশনের সমস্যার সমাধান করুন</translation>
<translation id="7549584377607005141">ঠিকঠাক ডিসপ্লে করার জন্য এই ওয়েবপৃষ্ঠার আপনার আগে দেওয়া ডেটা প্রযোজন৷ আপনি এই ডেটাটি আবার পাঠাতে পারেন, কিন্তু এমনটি করে আপনি যেকোনো পদক্ষেপের পুনরাবৃত্তি করবেন যা এই পৃষ্ঠাটি আগেই সম্পাদনা করেছে৷</translation>
+<translation id="7550637293666041147">আপনার ডিভাইসের ব্যবহারকারীর নাম এবং Chrome-এর ব্যবহারকারীর নাম</translation>
<translation id="7552846755917812628">নিম্নোল্লিখিত টিপ্স ব্যবহার করে দেখুন:</translation>
<translation id="7554791636758816595">নতুন ট্যাব</translation>
<translation id="7564049878696755256">আপনি নিজের <ph name="ORG_NAME" /> অ্যাকাউন্টের অ্যাক্সেস হারাতে পারেন অথবা আপনার পরিচয় চুরি হয়ে যেতে পারে। Chrome এখনই আপনার পাসওয়ার্ড পরিবর্তন করার আর্জি জানাচ্ছে।</translation>
@@ -1236,6 +1257,7 @@
<translation id="7610193165460212391">সীমার বাইরে মান <ph name="VALUE" />৷</translation>
<translation id="7613889955535752492">মেয়াদোত্তীর্ণ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">আপনার কাছে ইতিমধ্যেই এমন ডেটা আছে যা Google অ্যাকাউন্টের পাসওয়ার্ডের কোনো ভিন্ন ভার্সন ব্যবহারের দ্বারা এনক্রিপ্ট করা হয়৷ অনুগ্রহ করে এটিকে নিচে লিখুন৷</translation>
+<translation id="7625784245512586808">Chrome এন্টারপ্রাইজ থ্রেট প্রোটেকশন</translation>
<translation id="7633909222644580952">পারফর্ম্যান্সের ডেটা ও ক্র্যাশ রিপোর্ট</translation>
<translation id="7637571805876720304">Chromium থেকে ক্রেডিট কার্ড সরাবেন?</translation>
<translation id="7638605456503525968">সিরিয়াল পোর্ট</translation>
@@ -1248,7 +1270,6 @@
<translation id="7668654391829183341">অজানা ডিভাইস</translation>
<translation id="7669271284792375604">Attackers on this site might try to trick you into installing programs that harm your browsing experience (for example, by changing your homepage or showing extra ads on sites you visit).</translation>
<translation id="7676643023259824263">ক্লিপবোর্ড টেক্সট <ph name="TEXT" /> সার্চ করুন</translation>
-<translation id="7679176406634891508">প্ল্যাটফর্ম ও ক্লাউড</translation>
<translation id="7681101578153515023">সার্চ ইঞ্জিন পরিবর্তন করুন</translation>
<translation id="7682287625158474539">শিপিং</translation>
<translation id="7687186412095877299">আপনার সেভ করা পেমেন্ট পদ্ধতি দিয়ে পেমেন্ট ফর্ম পূরণ করে</translation>
@@ -1263,7 +1284,6 @@
<translation id="7723047071702270851">কার্ড সম্পাদনা করুন</translation>
<translation id="774634243536837715">বিপজ্জনক কন্টেন্ট ব্লক করা হয়েছে।</translation>
<translation id="7752995774971033316">অপরিচালিত</translation>
-<translation id="7755287808199759310">আপনার পিতামাতা এটি আপনার জন্য অবরোধ মুক্ত করতে পারবেন</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ফায়ারওয়াল বা অ্যান্টিভাইরাস সফটওয়্যার সংযোগকে অবরুদ্ধ করে থাকতে পারে।</translation>
<translation id="7759163816903619567">ডিসপ্লে ডোমেন:</translation>
@@ -1307,7 +1327,6 @@
<translation id="8004582292198964060">ব্রাউজার</translation>
<translation id="8009225694047762179">পাসওয়ার্ড পরিচালনা করুন</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{এই কার্ড ও সেটির বিলিং ঠিকানা সেভ করা হবে। <ph name="USER_EMAIL" />-এ সাইন-ইন করে থাকা অবস্থায় আপনি সেটি ব্যবহার করতে পারবেন।}one{এই কার্ডগুলি ও সেগুলির বিলিং ঠিকানা সেভ করা হবে। <ph name="USER_EMAIL" />-এ সাইন-ইন করে থাকা অবস্থায় আপনি সেগুলি ব্যবহার করতে পারবেন।}other{এই কার্ডগুলি ও সেগুলির বিলিং ঠিকানা সেভ করা হবে। <ph name="USER_EMAIL" />-এ সাইন-ইন করে থাকা অবস্থায় আপনি সেগুলি ব্যবহার করতে পারবেন।}}</translation>
-<translation id="8012647001091218357">এই মুহূর্তে আমরা আপনার পিতামাতার কাছে পৌঁছাতে পারিনি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷</translation>
<translation id="8025119109950072390">Attackers on this site may trick you into doing something dangerous like installing software or revealing your personal information (for example, passwords, phone numbers, or credit cards).</translation>
<translation id="8034522405403831421">এই পৃষ্ঠাটি <ph name="SOURCE_LANGUAGE" /> ভাষায় রয়েছে৷ এটিকে <ph name="TARGET_LANGUAGE" /> ভাষায় অনুবাদ করবেন?</translation>
<translation id="8035152190676905274">কলম</translation>
@@ -1318,6 +1337,7 @@
<translation id="8041940743680923270">বিশ্বব্যাপী ডিফল্ট ব্যবহার করুন (জানতে চান)</translation>
<translation id="8042918947222776840">পিক-আপের পদ্ধতি বেছে নিন</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" সঠিকভাবে কনফিগার হয়নি। সাধারণত "<ph name="SOFTWARE_NAME" />" আন-ইনস্টল করা হলে সমস্যার সমাধান হয়ে যায়। <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">এখন থেকে আপনাকে কার্ডের নিরাপত্তা কোড লিখতে হবে না</translation>
<translation id="8066955247577885446">কিছু সমস্যা হয়েছে।</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">ঘূর্ণনের সময় ব্যাখ্যা করা যাবে না</translation>
@@ -1348,6 +1368,7 @@
<translation id="8211406090763984747">কানেকশনটি নিরাপদ</translation>
<translation id="8218327578424803826">নির্ধারিত লোকেশন:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">এন্টারপ্রাইজ রিপোর্টিং</translation>
<translation id="8225771182978767009">এই কম্পিউটার যিনি সেট-আপ করেছেন তিনি এই সাইটটি অবরুদ্ধ করার বিষয়টি চয়ন করেছেন।</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">নতুন ছদ্মবেশী ট্যাবে একটি পৃষ্ঠা খুলুন</translation>
@@ -1402,23 +1423,23 @@
<translation id="8508648098325802031">সার্চ আইকন</translation>
<translation id="8522552481199248698">পাসওয়ার্ড পরিবর্তন করে আপনার Google অ্যাকাউন্ট সুরক্ষিত রাখতে Chrome সাহায্য করতে পারবে।</translation>
<translation id="8543181531796978784">আপনি <ph name="BEGIN_ERROR_LINK" />একটি শনাক্তকরণ সমস্যা রিপোর্ট করতে পারেন<ph name="END_ERROR_LINK" /> অথবা, আপনি আপনার নিরাপত্তা ঝুঁকি বুঝতে পারলে, <ph name="BEGIN_LINK" />এই অনিরাপদ সাইটটি ঘুরে দেখুন<ph name="END_LINK" />।</translation>
-<translation id="8543556556237226809">প্রশ্ন? আপনার প্রোফাইল যে তত্ত্বাবধান করে তার সাথে যোগাযোগ করুন।</translation>
<translation id="8553075262323480129">পৃষ্ঠার ভাষা নির্ধারণ না করতে পারার কারণে অনুবাদ ব্যর্থ হয়েছে৷</translation>
<translation id="8557066899867184262">আপনার কার্ডের পিছনে CVC ছবিটি আছে।</translation>
<translation id="8559762987265718583"><ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> এ একটি ব্যক্তিগত সংযোগ স্থাপন করা যায়নি কারণ আপনার ডিভাইসের তারিখ এবং সময় (<ph name="DATE_AND_TIME" />) সঠিক নয়৷</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> সন্দেহজনক সাইট</translation>
<translation id="8564985650692024650">Chromium-এর নীতি অনুযায়ী আপনার <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> পাসওয়ার্ড বদলে ফেলা উচিত যদি আপনি সেটি অন্য কোনও সাইটে ব্যবহার করে থাকেন।</translation>
<translation id="8571890674111243710">পৃষ্ঠাটি<ph name="LANGUAGE" />তে অনুবাদ করুন...</translation>
<translation id="858637041960032120">ফোননম্বর জুড়ুন</translation>
-<translation id="859285277496340001">সার্টিফিকেটটি প্রত্যাহার করা হয়েছে কিনা তা যাচাই করতে সার্টিফিকেটটি কোনও কারিগরীকে নির্দিষ্ট করে না৷</translation>
<translation id="860043288473659153">কার্ডধারকের নাম</translation>
<translation id="861775596732816396">সাইজ ৪</translation>
-<translation id="8620436878122366504">আপনার পিতামাতা এখনও এটি অনুমোদন করেন নি</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">এই ডিভাইসে এই কার্ডটি সেভ করুন</translation>
<translation id="8626112503828625890">বিলিংয়ের বিবরণ Google অ্যাকাউন্টে সেভ করে রাখতে চান?</translation>
+<translation id="8647750283161643317">সবগুলিকে ডিফল্টে আবার সেট করুন</translation>
<translation id="8663226718884576429">অর্ডারের সারসংক্ষেপ, <ph name="TOTAL_LABEL" />, আরও বিবরণ</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, উত্তর, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">উপলব্ধ</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" />-এ আপনার কানেকশন এনক্রিপ্ট হয় নি৷</translation>
<translation id="8718314106902482036">পেমেন্ট করা যায়নি</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, সার্চ সাজেশন</translation>
@@ -1429,6 +1450,7 @@
<translation id="8738058698779197622">নিরাপদ নেটওয়ার্ক সংযোগ স্থাপন করতে আপনার ঘড়িকে সঠিকভাবে সেট করতে হবে৷ নিরাপদ সংযোগ স্থাপন করার জন্য নিজেদের শনাক্ত করার জন্য ওয়েবসাইটগুলি যে শংসাপত্রগুলি ব্যবহার করে, সেগুলি শুধুমাত্র নির্দিষ্ট সময়ের জন্য বৈধ থাকে৷ যেহেতু আপনার ডিভাইসের ঘড়িটি ভুল, সেই জন্য Chromium সঠিকভাবে শংসাপত্রগুলি পরীক্ষা করতে পারে না৷</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> এর &lt;abbr id="ডিএনএসDefinition"&gt;ডিএনএস ঠিকানা&lt;/abbr&gt; পাওয়া যায়নি। সমস্যা নির্ণয় করা হচ্ছে।</translation>
<translation id="874846938927089722">এই ক্রেডিট ও প্রিপেড কার্ডগুলি গ্রহণ করা হয়</translation>
+<translation id="874918643257405732">এই ট্যাব বুকমার্ক করুন</translation>
<translation id="8759274551635299824">এই কার্ডটির মেয়াদ শেষ হয়েছে</translation>
<translation id="8761567432415473239">Google নিরাপদ ব্রাউজিং সম্প্রতি <ph name="SITE" /> এ <ph name="BEGIN_LINK" />ক্ষতিকারক প্রোগ্রামগুলি খুঁজে পেয়েছে<ph name="END_LINK" />৷</translation>
<translation id="8763927697961133303">USB ডিভাইস</translation>
@@ -1458,6 +1480,7 @@
<translation id="8938939909778640821">ক্রেডিট ও প্রিপেড কার্ড গ্রহণ করা হয়</translation>
<translation id="8943282376843390568">লাইম</translation>
<translation id="8957210676456822347">ক্যাপটিভ পোর্টাল অনুমোদন</translation>
+<translation id="8962950042226115166">সন্দেহজনক সাইট</translation>
<translation id="8968766641738584599">কার্ড সেভ করুন</translation>
<translation id="8971063699422889582">সার্ভারের সার্টিফিকেটের মেয়াদ ফুরিয়েছে৷</translation>
<translation id="8975012916872825179">ফোন নম্বর, ইমেল আইডি এবং শিপিং ঠিকানার মতো তথ্য এতে আছে</translation>
@@ -1480,24 +1503,24 @@
<translation id="9035022520814077154">নিরাপত্তা ত্রুটি</translation>
<translation id="9038649477754266430">পৃষ্ঠা আরও দ্রুত লোড করার জন্য কোনো পূর্বাভাষ পরিষেবা ব্যবহার করুন</translation>
<translation id="9039213469156557790">উপরন্তু, এই পৃষ্ঠাতে অন্যান্য সংস্থান অন্তর্ভুক্ত রয়েছে যা নিরাপদ নয়৷ এই সংস্থানগুলি ট্রানজিটের সময় অন্যরা দেখতে পাবে এবং পৃষ্ঠাটির আচরণ পরিবর্তন করার জন্য কোনো আক্রমণকারী এর পরিবর্তন করতে পারেন৷</translation>
+<translation id="9044359186343685026">টাচ আইডি ব্যবহার করুন</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">আপনি <ph name="DOMAIN" />-এ পৌছানোর প্রয়াস করছেন, কিন্তু সার্ভার একটি ভুল সার্টিফিকেট উপস্থাপন করেছে|</translation>
<translation id="9050666287014529139">পাসফ্রেজ</translation>
<translation id="9065203028668620118">সম্পাদনা</translation>
<translation id="9065745800631924235">ইতিহাসে <ph name="TEXT" /> সার্চ</translation>
<translation id="9069693763241529744">একটি এক্সটেনশন ব্লক করেছে</translation>
-<translation id="9076283476770535406">এতে প্রাপ্তবয়স্কদের উপযোগী কন্টেন্ট থাকতে পারে</translation>
<translation id="9076630408993835509">কোনও কোম্পানি বা অন্য কোনও সংস্থা এই ব্রাউজারটি ম্যানেজ করে না। এই ডিভাইসের অ্যাক্টিভিটি Chrome-এর বাইরে থেকে ম্যানেজ করা হতে পারে। <ph name="BEGIN_LINK" />আরও জানুন<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">আরও তথ্য প্রয়োজন</translation>
<translation id="9080712759204168376">অর্ডারের সারসংক্ষেপ</translation>
<translation id="9089260154716455634">Off-Hours সংক্রান্ত নীতি:</translation>
<translation id="9095388113577226029">আরও ভাষা...</translation>
+<translation id="9098981495403789647">আপনার অ্যাডমিনিস্ট্রেটর আপনার ব্রাউজারে Chrome এন্টারপ্রাইজ থ্রেট প্রোটেকশন চালু করেছে। Chrome এন্টারপ্রাইজ থ্রেট প্রোটেকশন আপনার কিছু ডেটা অ্যাক্সেস করতে পারে।</translation>
<translation id="9103872766612412690"><ph name="SITE" /> সাধারণত আপনার তথ্য সুরক্ষিত রাখতে এনক্রিপশন ব্যবহার করে। এবার Chromium, <ph name="SITE" />-এর সাথে কানেক্ট করার চেষ্টা করলে ওয়েবসাইটটি অস্বাভাবিক এবং ভুল ক্রেডেনশিয়াল পাঠিয়ে দেয়। হয় একজন আক্রমণকারী <ph name="SITE" /> হতে চাইছে অথবা একটি ওয়াই-ফাই সাইন-ইন স্ক্রিন কানেকশনকে বাধা দিয়েছে। আপনার তথ্য এখনো নিরাপদ আছে কারণ কোনো ডেটা আদানপ্রদানের আগেই Chromium কানেকশন বন্ধ করে দিয়েছে।</translation>
<translation id="9106062320799175032">বিলিংয়ের ঠিকানা যোগ করুন</translation>
<translation id="9114524666733003316">কার্ড নিশ্চিত করা হচ্ছে...</translation>
<translation id="9128870381267983090">নেটওয়ার্কে সংযোগ করুন</translation>
<translation id="9137013805542155359">প্রকৃত রূপ দেখান</translation>
-<translation id="9137248913990643158">এই অ্যাপ্লিকেশানটি ব্যবহার করার আগে অনুগ্রহ করে শুরু করুন এবং Chrome এ প্রবেশ করুন।</translation>
<translation id="9141013498910525015">ঠিকানা ম্যানেজ করুন</translation>
<translation id="9148088599418889305">শিপিংয়ের পদ্ধতি বেছে নিন</translation>
<translation id="9148507642005240123">&amp;সম্পাদনাকে পূর্বাবস্থায় ফেরান</translation>
diff --git a/chromium/components/strings/components_strings_ca.xtb b/chromium/components/strings/components_strings_ca.xtb
index d8c9fbbb814..13e9b2eb161 100644
--- a/chromium/components/strings/components_strings_ca.xtb
+++ b/chromium/components/strings/components_strings_ca.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Afegeix el titular de la targeta</translation>
<translation id="1089439967362294234">Canvia la contrasenya</translation>
+<translation id="1096545575934602868">Aquest camp no pot tenir més de <ph name="MAX_ITEMS_LIMIT" /> entrades. Es descartaran totes les entrades restants.</translation>
<translation id="109743633954054152">Gestiona les contrasenyes a la configuració de Chrome</translation>
<translation id="1103523840287552314">Tradueix sempre el text en <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Si s'activa aquesta casella, Chrome emmagatzema una còpia d'aquesta targeta al dispositiu per agilitzar l'emplenament de formularis.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Accediu a una <ph name="BEGIN_LINK" />còpia emmagatzemada a la memòria cau<ph name="END_LINK" /> de la pàgina <ph name="URL" />.</translation>
<translation id="1156303062776767266">Estàs consultant un fitxer local o compartit</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ha tancat la connexió de manera inesperada.</translation>
+<translation id="115926840831309955">Comprova el CVC i torna-ho a provar o actualitza la data de caducitat</translation>
<translation id="1161325031994447685">Torna't a connectar a la xarxa Wi-Fi.</translation>
<translation id="1165039591588034296">Error</translation>
<translation id="1175364870820465910">&amp;Imprimeix...</translation>
@@ -69,17 +71,19 @@
<translation id="1292701964462482250">"L'ordinador conté programari que impedeix que Chrome es connecti de manera segura al web" (només en ordinadors Windows)</translation>
<translation id="1294154142200295408">Variacions de la línia d'ordres</translation>
<translation id="129553762522093515">Tancades recentment</translation>
+<translation id="1298536327547837046">Escaneig per detectar programari maliciós</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Esborreu les galetes<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funcions obsoletes</translation>
<translation id="1320233736580025032">Prc1 (sobre)</translation>
<translation id="132301787627749051">Cerca la imatge del porta-retalls</translation>
<translation id="1323433172918577554">Mostra'n més</translation>
<translation id="132390688737681464">Desa i emplena les adreces</translation>
-<translation id="1333989956347591814">És possible que la teva activitat <ph name="BEGIN_EMPHASIS" />continuï sent visible<ph name="END_EMPHASIS" /> en:
- <ph name="BEGIN_LIST" />
- <ph name="LIST_ITEM" />Els llocs web que visitis
- <ph name="LIST_ITEM" />La teva empresa o el teu centre educatiu
- <ph name="LIST_ITEM" />El teu proveïdor de serveis d'Internet
- <ph name="END_LIST" /></translation>
+<translation id="1333989956347591814">És possible que la teva activitat <ph name="BEGIN_EMPHASIS" />continuï sent visible<ph name="END_EMPHASIS" /> per a:
+<ph name="BEGIN_LIST" />
+<ph name="LIST_ITEM" />els llocs web que visitis
+<ph name="LIST_ITEM" />la teva empresa o el teu centre educatiu
+<ph name="LIST_ITEM" />el teu proveïdor d'Internet
+<ph name="END_LIST" /></translation>
<translation id="1339601241726513588">Domini d'inscripció:</translation>
<translation id="1340482604681802745">Adreça de recollida</translation>
<translation id="1348198688976932919">Aquest lloc web conté aplicacions perilloses</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Fulls de càlcul de Google</translation>
<translation id="1527263332363067270">S'està esperant que hi hagi connexió…</translation>
<translation id="1529521330346880926">10x15 (sobre)</translation>
+<translation id="1530707389502320859">El lloc web al qual acabes de provar d'accedir sembla fals. De vegades, els atacants imiten llocs web introduint petits canvis difícils de veure a l'URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Aquesta pàgina diu</translation>
<translation id="153384715582417236">De moment, això és tot</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">SO</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">No es poden afegir anotacions a aquest fitxer perquè és massa gran</translation>
-<translation id="1721312023322545264">Cal que <ph name="NAME" /> et doni permís per visitar aquest lloc</translation>
<translation id="1721424275792716183">* El camp és obligatori</translation>
<translation id="1727741090716970331">Afegeix un número de targeta vàlid</translation>
<translation id="1728677426644403582">Estàs consultant el codi font d'una pàgina web</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Els llocs web que visites i el temps que hi passes</translation>
<translation id="1826516787628120939">S'està comprovant</translation>
<translation id="1834321415901700177">Aquest lloc conté programes perjudicials</translation>
+<translation id="1838374766361614909">Esborra la cerca</translation>
<translation id="1839551713262164453">S'han produït errors a la validació dels valors de la política</translation>
<translation id="1842969606798536927">Paga</translation>
<translation id="1871208020102129563">El servidor intermediari està configurat perquè utilitzi servidors intermediaris fixos, en lloc d'un URL d'script .pac.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Redueix la llista</translation>
<translation id="1898423065542865115">Filtratge</translation>
<translation id="1914326953223720820">Descomprimeix el servei</translation>
+<translation id="1915697529809968049">Vols utilitzar Touch ID en lloc del CVC?</translation>
<translation id="1916770123977586577">Per aplicar la configuració actualitzada a aquest lloc web, torna a carregar la pàgina</translation>
<translation id="1919345977826869612">Anuncis</translation>
<translation id="1919367280705858090">Obtenir ajuda amb un missatge d'error específic</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Adreces d'interès de <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Error de serialització</translation>
<translation id="1974060860693918893">Configuració avançada</translation>
+<translation id="1974883374937189061">Per ajudar a millorar la seguretat de Chrome, envia a Google <ph name="BEGIN_WHITEPAPER_LINK" />URL d'algunes pàgines que visites, informació limitada del sistema i part del contingut de les pàgines<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versió del microprogramari</translation>
<translation id="1981206234434200693">Esborra les dades de l'historial de navegació de Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{i 1 aplicació més}other{i # aplicacions més}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Introdueix un any de caducitat vàlid</translation>
<translation id="2212735316055980242">No es troba la política</translation>
<translation id="2213606439339815911">S'estan recuperant les entrades...</translation>
+<translation id="2215727959747642672">Edició de fitxers</translation>
<translation id="2218879909401188352">És possible que els atacants que es troben a <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> instal·lin aplicacions perilloses que malmetin el teu dispositiu, afegeixin càrrecs amagats a la teva factura telefònica o et robin informació personal. <ph name="BEGIN_LEARN_MORE_LINK" />Més informació<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Sense connexió a Internet</translation>
<translation id="2230458221926704099">Repareu la connexió amb l'<ph name="BEGIN_LINK" />aplicació de diagnòstic<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Envia ara</translation>
+<translation id="2248949050832152960">Utilitza WebAuthn</translation>
<translation id="225207911366869382">El valor d'aquesta política és obsolet.</translation>
<translation id="2257315177824333709">Ara mateix no es pot desar la targeta</translation>
<translation id="2262243747453050782">Error d'HTTP</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">URL de cerca no vàlid.</translation>
<translation id="2482878487686419369">Notificacions</translation>
<translation id="248348093745724435">Polítiques de l'ordinador</translation>
-<translation id="2485387744899240041">Noms d'usuari del dispositiu i del navegador</translation>
<translation id="2491120439723279231">El certificat del servidor conté errors.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analitzador JSON</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Torna</translation>
<translation id="2503184589641749290">Targetes de dèbit i de prepagament acceptades</translation>
<translation id="2505268675989099013">Protegeix el compte</translation>
+<translation id="2515335152965840738">IGNORA</translation>
<translation id="2515629240566999685">Comprova el senyal a la teva zona.</translation>
<translation id="2523886232349826891">Només es desarà en aquest dispositiu</translation>
<translation id="2524461107774643265">Afegeix més informació</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Envia</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Cap}=1{1 contrasenya (per a <ph name="DOMAIN_LIST" />)}=2{2 contrasenyes (per a <ph name="DOMAIN_LIST" />)}other{# contrasenyes (per a <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Tanca altres pestanyes o aplicacions</translation>
-<translation id="267371737713284912">prem <ph name="MODIFIER_KEY_DESCRIPTION" /> per desfer l'acció</translation>
<translation id="2674170444375937751">Confirmes que vols suprimir aquestes pàgines de l'historial?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Surt</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">El valor no coincideix amb el format.</translation>
<translation id="2705137772291741111">La còpia desada (a la memòria cau) d'aquest lloc no s'ha pogut llegir.</translation>
<translation id="2709516037105925701">Emplenament automàtic</translation>
-<translation id="2712173769900027643">Demana permís</translation>
<translation id="2713444072780614174">Blanc</translation>
<translation id="2720342946869265578">A prop</translation>
<translation id="2721148159707890343">Sol·licitud realitzada correctament</translation>
<translation id="2728127805433021124">El certificat del servidor està signat mitjançant un algoritme de signatura dèbil.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Executar el Diagnòstic de connectivitat<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">En activar aquestes funcions, podries perdre dades del navegador o posar en perill la teva seguretat o privadesa. Les funcions activades s'apliquen a tots els usuaris d'aquest navegador.</translation>
<translation id="2735043616039983645">Hi ha més d'un origen amb valors conflictius en aquesta política.</translation>
<translation id="2738330467931008676">Tria l'adreça de recollida</translation>
<translation id="2740531572673183784">D'acord</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">S'ha restablert la connexió.</translation>
<translation id="2788784517760473862">Targetes de crèdit acceptades</translation>
<translation id="2792012897584536778">Els administradors d'aquest dispositiu han configurat certificats de seguretat que els permeten veure el contingut dels llocs web que visites.</translation>
-<translation id="2794233252405721443">Lloc bloquejat</translation>
<translation id="2799020568854403057">Aquest lloc web conté aplicacions perjudicials</translation>
<translation id="2799223571221894425">Reinicia</translation>
<translation id="2803306138276472711">Navegació segura de Google ha <ph name="BEGIN_LINK" />detectat programari maliciós<ph name="END_LINK" /> recentment a la pàgina <ph name="SITE" />. De vegades, els llocs web que acostumen a ser segurs s'infecten amb programari maliciós.</translation>
+<translation id="2815364696811431560">SURT DEL LLOC WEB</translation>
<translation id="2824775600643448204">Barra d'adreces i de cerca</translation>
<translation id="2826760142808435982">La connexió s'ha encriptat i autenticat mitjançant <ph name="CIPHER" /> i fa servir <ph name="KX" /> com a mecanisme d'intercanvi clau.</translation>
<translation id="2835170189407361413">Esborra el formulari</translation>
<translation id="2847118875340931228">Obre una finestra d'incògnit</translation>
<translation id="2850739647070081192">Invite (sobre)</translation>
-<translation id="2851634818064021665">Necessites permís per visitar aquest lloc web</translation>
<translation id="2856444702002559011">Pot ser que els atacants provin de robar la teva informació del lloc web <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (per exemple, contrasenyes, missatges o targetes de crèdit). <ph name="BEGIN_LEARN_MORE_LINK" />Més informació<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Vols desar la targeta?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Si s'activa aquesta opció, Chromium desa una còpia de la vostra targeta en aquest dispositiu per agilitzar l'emplenament de formularis.</translation>
<translation id="2985398929374701810">Introdueix una adreça vàlida</translation>
<translation id="2986368408720340940">Aquest mètode de recollida no està disponible. Prova'n un altre.</translation>
+<translation id="2987034854559945715">No hi ha cap funció que coincideixi</translation>
<translation id="2991174974383378012">Comparteix informació amb llocs web</translation>
<translation id="2991571918955627853">En aquest moments no pots visitar la pàgina <ph name="SITE" /> perquè el lloc web fa servir HSTS. Els atacs i els errors de xarxa acostumen a ser temporals, o sigui que probablement la pàgina funcionarà més endavant.</translation>
<translation id="3005723025932146533">Mostra la còpia desada</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Tipus de política incorrecte</translation>
<translation id="3037605927509011580">Vaja!</translation>
<translation id="3041612393474885105">Informació del certificat</translation>
+<translation id="3057676462092457419">Encara no s'admet el mode DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" />; el mode s'ha establert en <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (sobre)</translation>
<translation id="3061707000357573562">Servei de pedaç</translation>
<translation id="3064966200440839136">Per pagar amb una aplicació externa sortiràs del mode d'incògnit. Vols continuar?</translation>
@@ -419,6 +428,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> a <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancel·la el pagament</translation>
<translation id="3207960819495026254">S'ha afegit a les adreces d'interès.</translation>
+<translation id="3209034400446768650">És possible que la pàgina faci un càrrec de diners</translation>
<translation id="3225919329040284222">El servidor ha presentat un certificat que no coincideix amb les expectatives integrades. Les expectatives s'inclouen perquè determinats llocs web d'alta seguretat us protegeixin.</translation>
<translation id="3226128629678568754">Premeu el botó de tornar a carregar per tornar a enviar les dades necessàries per carregar la pàgina.</translation>
<translation id="3227137524299004712">Micròfon</translation>
@@ -426,7 +436,6 @@
<translation id="3229041911291329567">Informació sobre la versió del dispositiu i del navegador</translation>
<translation id="323107829343500871">Introdueix el CVC de la targeta <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Detecta sempre el contingut important d'aquest lloc</translation>
-<translation id="3254409185687681395">Afegeix aquesta pàgina a les adreces d'interès</translation>
<translation id="3270847123878663523">&amp;Desfés el canvi d'ordre</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Afegeix el titular de la targeta</translation>
@@ -436,7 +445,6 @@
<translation id="3320021301628644560">Afegeix una adreça de facturació</translation>
<translation id="3324983252691184275">Carmesí</translation>
<translation id="3338095232262050444">Segur</translation>
-<translation id="3345135638360864351">La sol·licitud per accedir al lloc no s'ha pogut enviar a <ph name="NAME" />. Torneu-ho a provar.</translation>
<translation id="3355823806454867987">Canvia la configuració del servidor intermediari...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />no desarà<ph name="END_EMPHASIS" /> la informació següent:
<ph name="BEGIN_LIST" />
@@ -470,18 +478,15 @@
<translation id="3462200631372590220">Amaga la configuració avançada</translation>
<translation id="3467763166455606212">El nom del titular de la targeta és obligatori</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, oberta actualment; prem el tabulador i després Retorn per canviar a la pestanya oberta</translation>
-<translation id="3479539252931486093">Heu trobat el lloc bloquejat de manera inesperada? <ph name="BEGIN_LINK" />Informeu-nos-en<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ara no</translation>
<translation id="3484560055331845446">Podries perdre l'accés al Compte de Google. Chrome et recomana que canviïs la contrasenya ara. Se't demanarà que iniciïs la sessió.</translation>
<translation id="3495081129428749620">Cerca a la pàgina
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">En aquests moments no ens hem pogut posar en contacte amb els pares. Torneu-ho a provar.</translation>
<translation id="3512163584740124171">Aquesta política s'ignora perquè una altra política del mateix grup de polítiques té una prioritat més alta.</translation>
<translation id="3528171143076753409">El certificat del servidor no és de confiança.</translation>
<translation id="3528485271872257980">Marró fosc</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Almenys 1 element als dispositius sincronitzats}=1{1 element (i altres elements als dispositius sincronitzats)}other{# elements (i altres elements als dispositius sincronitzats)}}</translation>
<translation id="3539171420378717834">Desa una còpia d'aquesta targeta al dispositiu</translation>
-<translation id="3556433843310711081">El teu gestor te'l pot desbloquejar</translation>
<translation id="3566021033012934673">La connexió no és privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Una pàgina inserida a <ph name="SITE" /> diu</translation>
@@ -509,6 +514,7 @@
<translation id="3678529606614285348">Obre la pàgina en una finestra d'incògnit nova (Ctrl+Maj+N)</translation>
<translation id="3679803492151881375">Informe d'error generat el <ph name="CRASH_TIME" /> i enviat el <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informació del certificat</translation>
+<translation id="3701427423622901115">Restabliment acceptat.</translation>
<translation id="3704162925118123524">És possible que la xarxa que esteu fent servir requereixi que visiteu la pàgina d'inici de sessió.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">S'està carregant...</translation>
@@ -525,6 +531,7 @@
<translation id="3748148204939282805">Els atacants del lloc web <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> et poden enganyar perquè facis alguna acció perillosa, com ara instal·lar programari o revelar informació personal (per exemple, contrasenyes, números de telèfon o targetes de crèdit). <ph name="BEGIN_LEARN_MORE_LINK" />Més informació<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">S'ha produït un error en el procés de traducció a causa d'un error del servidor.</translation>
<translation id="3759461132968374835">No has informat de cap error recentment. Els errors que s'hagin produït mentre la creació d'informes d'error estava desactivada no es mostraran aquí.</translation>
+<translation id="3760561303380396507">Vols utilitzar Windows Hello en lloc del CVC?</translation>
<translation id="3761718714832595332">Amaga l'estat</translation>
<translation id="3765032636089507299">La pàgina Navegació segura està en construcció.</translation>
<translation id="3778403066972421603">Vols desar aquesta targeta al teu compte de Google i en aquest dispositiu?</translation>
@@ -534,6 +541,7 @@
<translation id="3789155188480882154">Mida 16</translation>
<translation id="3797522431967816232">Prc3 (sobre)</translation>
<translation id="3807873520724684969">S'ha bloquejat contingut perjudicial.</translation>
+<translation id="3808375843007691220">Advertiment: s'han detectat funcions experimentals.</translation>
<translation id="3810973564298564668">Gestiona</translation>
<translation id="382518646247711829">Si feu servir un servidor intermediari...</translation>
<translation id="3828924085048779000">Les frases de contrasenya no poder estar buides.</translation>
@@ -542,11 +550,11 @@
<translation id="3858027520442213535">Actualitza la data i l'hora</translation>
<translation id="3884278016824448484">L'identificador del dispositiu ja s'està utilitzant</translation>
<translation id="3885155851504623709">Districte</translation>
-<translation id="3886446263141354045">La teva sol·licitud per accedir a aquest lloc s'ha enviat a <ph name="NAME" /></translation>
<translation id="3890664840433101773">Afegeix un correu electrònic</translation>
<translation id="3901925938762663762">La targeta ha caducat</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Vols utilitzar WebAuthn en lloc del CVC?</translation>
<translation id="3946209740501886391">Pregunta sempre en aquest lloc</translation>
<translation id="3949571496842715403">Aquest servidor no ha pogut demostrar que sigui <ph name="DOMAIN" />, perquè el seu certificat de seguretat no especifica noms alternatius per a l'assumpte. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la connexió.</translation>
<translation id="3949601375789751990">Aquí es mostra l'historial de navegació</translation>
@@ -557,11 +565,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Cap}=1{D'1 lloc }other{De # llocs }}</translation>
<translation id="397105322502079400">S’està calculant...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> està bloquejat</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ha activat la protecció contra amenaces de Chrome Enterprise al navegador. La protecció contra amenaces de Chrome Enterprise té accés a algunes de les teves dades.</translation>
<translation id="3987940399970879459">Menys d'1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{Hi ha 1 pàgina web a prop}other{Hi ha # pàgines web a prop}}</translation>
<translation id="4030383055268325496">&amp;Desfés l'addició</translation>
<translation id="4032320456957708163"><ph name="ENROLLMENT_DOMAIN" /> gestiona el teu navegador</translation>
-<translation id="4034375457890803692">L'enllaç que has obert dirigeix a un lloc web que no acostumes a visitar. Pot ser que estigui provant de confondre't.</translation>
<translation id="4058922952496707368">Tecla "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (sobre)</translation>
<translation id="4067947977115446013">Afegeix una adreça vàlida</translation>
@@ -574,6 +582,7 @@
<translation id="4103249731201008433">El número de sèrie del dispositiu no és vàlid</translation>
<translation id="410351446219883937">Reproducció automàtica</translation>
<translation id="4103763322291513355">Ves a &lt;strong&gt;chrome://policy&lt;/strong&gt; per veure la llista d'URL inclosos a la llista negra i altres polítiques aplicades per l'administrador del sistema.</translation>
+<translation id="4108231218301530806">Fes servir l'empremta digital per verificar aquesta targeta la propera vegada.</translation>
<translation id="4110652170750985508">Revisa el pagament</translation>
<translation id="4112140312785995938">Retrocedeix</translation>
<translation id="4116663294526079822">Permet sempre en aquest lloc web</translation>
@@ -588,6 +597,7 @@
<translation id="4171400957073367226">La signatura de verificació és incorrecta</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> element més}other{<ph name="ITEM_COUNT" /> elements més}}</translation>
+<translation id="4176463684765177261">Desactivat</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Perquè la propera vegada puguis pagar més ràpidament, afegeix la targeta i l'adreça de facturació al Compte de Google.</translation>
<translation id="4196861286325780578">&amp;Refés el moviment</translation>
@@ -624,6 +634,7 @@
<translation id="4277028893293644418">Restableix la contrasenya</translation>
<translation id="4279811152705618813"><ph name="ENROLLMENT_DOMAIN" /> gestiona el dispositiu <ph name="DEVICE_TYPE" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Aquesta targeta s'ha desat al Compte de Google}other{Aquestes targetes s'han desat al Compte de Google}}</translation>
+<translation id="428847186335018806">Escaneja els fitxers que baixes de Chrome o que hi penges.</translation>
<translation id="42981349822642051">Desplega</translation>
<translation id="4302965934281694568">Chou3 (sobre)</translation>
<translation id="4305817255990598646">Canvia</translation>
@@ -653,7 +664,6 @@
<translation id="4435702339979719576">Postal)</translation>
<translation id="443673843213245140">L'ús d'un servidor intermediari no està activat, però s'ha especificat una configuració explícita d'un servidor intermediari.</translation>
<translation id="445100540951337728">Targetes de dèbit acceptades</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" />comportament sospitós</translation>
<translation id="4466881336512663640">Es perdran els canvis fets al formulari. Confirmes que vols continuar?</translation>
<translation id="4477350412780666475">Pista següent</translation>
<translation id="4482953324121162758">Aquest lloc web no es traduirà.</translation>
@@ -680,6 +690,7 @@
<translation id="4594403342090139922">&amp;Desfés la supressió</translation>
<translation id="4597348597567598915">Mida 8</translation>
<translation id="4600854749408232102">C6/C5 (sobre)</translation>
+<translation id="464342062220857295">Funcions de cerca</translation>
<translation id="4646534391647090355">Porta-m'hi ara</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">El servidor no ha pogut comprovar que sigui <ph name="DOMAIN" /> perquè el seu certificat de seguretat conté errors. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.</translation>
@@ -688,7 +699,6 @@
<translation id="4691835149146451662">Architecture-A (sobre)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">La connexió s'ha interromput</translation>
-<translation id="471880041731876836">No tens permís per visitar aquest lloc web</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executa el Diagnòstic de xarxa de Windows<ph name="END_LINK" />.</translation>
<translation id="4726672564094551039">Torna a carregar les polítiques</translation>
<translation id="4728558894243024398">Plataforma</translation>
@@ -712,11 +722,10 @@
<translation id="480334179571489655">Error de la política d'origen</translation>
<translation id="4803924862070940586"><ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
<translation id="4807049035289105102">En aquest moment no podeu visitar <ph name="SITE" /> perquè el lloc web ha enviat credencials aleatòries que Google Chrome no pot processar. Els errors i els atacs de xarxa solen ser temporals, de manera que és probable que aquesta pàgina torni a funcionar més tard.</translation>
-<translation id="4813512666221746211">Error de xarxa</translation>
+<translation id="4813512666221746211">Error de la xarxa</translation>
<translation id="4816492930507672669">Ajusta a la mida de la pàgina</translation>
<translation id="4850886885716139402">Mostra</translation>
<translation id="4854362297993841467">Aquest mètode d'entrega no està disponible. Prova'n un altre.</translation>
-<translation id="4858792381671956233">Has demanat permís als teus pares per visitar aquest lloc web</translation>
<translation id="4864052566555297930">Consell de seguretat:</translation>
<translation id="4876188919622883022">Visualització simplificada</translation>
<translation id="4876305945144899064">Sense nom d'usuari</translation>
@@ -732,7 +741,7 @@
<translation id="4926049483395192435">S'ha d'especificar.</translation>
<translation id="4926159001844873046"><ph name="SITE" /> diu</translation>
<translation id="4926340098269537727"><ph name="ACTIVE_MATCH" />/<ph name="TOTAL_MATCHCOUNT" /></translation>
-<translation id="4943872375798546930">No hi ha resultats</translation>
+<translation id="4943872375798546930">No hi ha cap resultat</translation>
<translation id="4950898438188848926">Botó per canviar de pestanya; prem Retorn per canviar a la pestanya oberta, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Accions</translation>
<translation id="4955242332710481440">A5-Extra</translation>
@@ -740,7 +749,9 @@
<translation id="4974590756084640048">Torna a activar els advertiments</translation>
<translation id="4984339528288761049">Prc5 (sobre)</translation>
<translation id="4989163558385430922">Mostra-ho tot</translation>
+<translation id="4989542687859782284">No disponibles</translation>
<translation id="4989809363548539747">Aquest connector no és compatible</translation>
+<translation id="4995216769782533993">Confirma el codi de seguretat per compartir els detalls de la targeta amb aquest lloc web</translation>
<translation id="5002932099480077015">Si s'activa, Chrome emmagatzemarà una còpia de la targeta en aquest dispositiu per agilitzar l'emplenament de formularis.</translation>
<translation id="5015510746216210676">Nom de l'ordinador:</translation>
<translation id="5017554619425969104">Text que has copiat</translation>
@@ -769,6 +780,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verifica la targeta</translation>
<translation id="5135404736266831032">Gestiona les adreces...</translation>
<translation id="5138227688689900538">Mostra'n menys</translation>
<translation id="5141240743006678641">Encripta contrasenyes sincronitzades amb les vostres credencials de Google</translation>
@@ -795,6 +807,7 @@
<translation id="5251803541071282808">Núvol</translation>
<translation id="5252000469029418751">C7 (sobre)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Les funcions que s'apliquen a tot el sistema només les pot definir l'usuari: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Advertiment: aquesta política no s'ha combinat segons el que s'especifica a la política PolicyDictionaryMultipleSourceMergeList perquè no forma part de les polítiques de diccionari que es poden combinar.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Finalitza</translation>
@@ -818,7 +831,6 @@
<translation id="536296301121032821">No s'ha pogut emmagatzemar la configuració de la política</translation>
<translation id="5371425731340848620">Actualitza la targeta</translation>
<translation id="5377026284221673050">"El rellotge està endarrerit", "El rellotge està avançat" o "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Pot ser que aquesta pàgina provi d'enganyar-te, de robar-te informació personal o de malmetre't el dispositiu. Ves amb compte a l'hora d'introduir informació personal o d'obrir fitxers baixats.</translation>
<translation id="5384855140246857529">Per utilitzar les targetes en tots els dispositius, inicia la sessió i activa la sincronització.</translation>
<translation id="5386426401304769735">La cadena de certificats d'aquest lloc conté un certificat que s'ha signat amb SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -832,6 +844,7 @@
<translation id="5457113250005438886">No vàlides</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> i <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> més}other{<ph name="CONTACT_PREVIEW" /> i <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> més}}</translation>
<translation id="5470861586879999274">&amp;Refés la modificació</translation>
+<translation id="5473728911100096288">En activar aquestes funcions, estaràs utilitzant funcions obsoletes que es retiraran en versions futures.</translation>
<translation id="5478437291406423475">B6/C4 (sobre)</translation>
<translation id="5481076368049295676">Aquest contingut pot provar d'instal·lar programari maliciós al teu dispositiu per suprimir-ne informació o robar-te'n. <ph name="BEGIN_LINK" />Mostra igualment<ph name="END_LINK" />.</translation>
<translation id="54817484435770891">Afegeix una adreça vàlida</translation>
@@ -855,7 +868,6 @@
<translation id="5570825185877910964">Protegeix el compte</translation>
<translation id="5571083550517324815">No es pot fer la recollida en aquesta adreça. Selecciona'n una altra.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 en ús}other{# en ús}})</translation>
-<translation id="5572851009514199876">Obre Chrome i inicia-hi la sessió perquè Chrome pugui comprovar si tens permís per accedir a aquest lloc.</translation>
<translation id="5580958916614886209">Comprova el mes de caducitat i torna-ho a provar</translation>
<translation id="5586446728396275693">No hi ha cap adreça desada</translation>
<translation id="5595485650161345191">Edita l'adreça</translation>
@@ -863,6 +875,7 @@
<translation id="560412284261940334">Gestió no compatible</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Aquest lloc web podria ser fals o fraudulent. Chrome recomana que en surtis ara.</translation>
<translation id="5610142619324316209">Comproveu la connexió</translation>
<translation id="5610807607761827392">Pots gestionar les targetes i les adreces a <ph name="BEGIN_LINK" />Configuració<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> us ha redirigit massa vegades.</translation>
@@ -886,11 +899,11 @@
<translation id="5720705177508910913">Usuari actual</translation>
<translation id="5728056243719941842">C5 (sobre)</translation>
<translation id="5730040223043577876">Chrome et recomana que restableixis la contrasenya si l'has fet servir en altres llocs web.</translation>
-<translation id="5732392974455271431">Els teus pares te'l poden desbloquejar</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Desa la targeta al Compte de Google}other{Desa targetes al Compte de Google}}</translation>
<translation id="5763042198335101085">Introdueix una adreça electrònica vàlida</translation>
<translation id="5765072501007116331">Per veure els mètodes i els requisits d'entrega, selecciona una adreça</translation>
<translation id="5778550464785688721">Control total dels dispositius MIDI</translation>
+<translation id="5781136890105823427">Experiment activat</translation>
<translation id="578305955206182703">Ambre</translation>
<translation id="57838592816432529">Silencia</translation>
<translation id="5784606427469807560">S'ha produït un problema en confirmar la targeta. Comprova la connexió a Internet i torna-ho a provar.</translation>
@@ -907,13 +920,16 @@
<translation id="5860033963881614850">Desactivat</translation>
<translation id="5863847714970149516">És possible que aquesta pàgina provi de fer-te algun càrrec</translation>
<translation id="5866257070973731571">Afegeix un número de telèfon</translation>
+<translation id="5866898949289125849">Estàs consultant una pàgina d'eines per a desenvolupadors</translation>
<translation id="5869405914158311789">No es pot accedir a aquest lloc web</translation>
<translation id="5869522115854928033">Contrasenyes desades</translation>
<translation id="5887400589839399685">S'ha desat la targeta</translation>
<translation id="5893752035575986141">S'accepten targetes de crèdit.</translation>
+<translation id="5895138241574237353">Reinicia</translation>
<translation id="5901630391730855834">Groc</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (informació sincronitzada)</translation>
<translation id="5916664084637901428">Activat</translation>
+<translation id="59174027418879706">Activat</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Vols desar la targeta al Compte de Google?</translation>
<translation id="5922853866070715753">Ja queda poc</translation>
@@ -947,6 +963,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Vols utilitzar les targetes en tots els dispositius?</translation>
<translation id="6059925163896151826">Dispositius USB</translation>
+<translation id="6060009363608157444">El mode DnsOverHttps no és vàlid.</translation>
<translation id="6080696365213338172">Has accedit a contingut mitjançant un certificat proporcionat per l'administrador. Per tant, l'administrador por interceptar les dades que proporcioneu a <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">Anota</translation>
<translation id="610911394827799129">A <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> trobaràs altres maneres d'explorar l'historial de navegació del teu Compte de Google</translation>
@@ -995,13 +1012,12 @@
<translation id="6404511346730675251">Edita l'adreça d'interès</translation>
<translation id="6406765186087300643">C0 (sobre)</translation>
<translation id="6410264514553301377">Introdueix la data de caducitat i el CVC de la targeta <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Has demanat permís als teus pares per visitar aquest lloc web</translation>
<translation id="6415778972515849510">Chromium et pot ajudar a protegir el Compte de Google i a canviar la contrasenya.</translation>
-<translation id="6417515091412812850">No es pot comprovar si s'ha revocat el certificat.</translation>
<translation id="6431585503458005759">No emmagatzemis</translation>
<translation id="6433490469411711332">Edita la informació de contacte</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> no ens ha permès establir la connexió.</translation>
<translation id="6434309073475700221">Descarta</translation>
+<translation id="6435221585574090192">Comparteix amb el teu administrador les dades sobre esdeveniments de seguretat que marqui la Protecció contra amenaces de Chrome Enterprise. Per exemple, URL de pàgines, noms i metadades de fitxers, el nom d'usuari del dispositiu i el nom d'usuari de Chrome.</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6446163441502663861">Kahu (sobre)</translation>
<translation id="6446608382365791566">Afegeix més informació</translation>
@@ -1010,20 +1026,19 @@
<translation id="6465306955648956876">Gestiona les contrasenyes...</translation>
<translation id="647261751007945333">Polítiques de dispositius</translation>
<translation id="6476284679642588870">Gestiona les formes de pagament</translation>
-<translation id="6477321094435799029">Chrome ha detectat codi poc comú en aquesta pàgina i, per tant, l'ha bloquejat per protegir la teva informació personal (per exemple, contrasenyes, números de telèfon i targetes de crèdit).</translation>
<translation id="6489534406876378309">Comença a penjar els errors</translation>
<translation id="6499038740797743453">Vols restablir la contrasenya?</translation>
<translation id="6507833130742554667">S'accepten targetes de crèdit i de dèbit.</translation>
<translation id="650855688985305916">Sí, desa</translation>
<translation id="6508722015517270189">Reinicia Chrome</translation>
<translation id="6517596291481585650">Advertiment: aquesta política no s'ha combinat com a llista segons el que s'especifica a la política perquè no és una llista.</translation>
+<translation id="6518133107902771759">Verifica</translation>
<translation id="6521745193039995384">No activa</translation>
<translation id="6529602333819889595">&amp;Refés la supressió</translation>
<translation id="6534179046333460208">Suggeriments del Web físic</translation>
<translation id="6545864417968258051">Cerca de dispositius Bluetooth</translation>
<translation id="6554795675067793129">El teu compte està gestionat per <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Refés</translation>
-<translation id="6563469144985748109">El teu gestor encara no ho ha aprovat</translation>
<translation id="6569060085658103619">Estàs consultant la pàgina d'una extensió</translation>
<translation id="6578796323535178455">C2 (sobre)</translation>
<translation id="6579990219486187401">Rosa clar</translation>
@@ -1041,11 +1056,13 @@
<translation id="6643016212128521049">Esborra</translation>
<translation id="6644283850729428850">Aquesta política ha quedat obsoleta.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Cap}=1{D'1 lloc web (no se't tancarà la sessió del Compte de Google)}other{De # llocs web (no se't tancarà la sessió del Compte de Google)}}</translation>
+<translation id="6652101503459149953">Utilitza Windows Hello</translation>
<translation id="6657585470893396449">Contrasenya</translation>
<translation id="6670613747977017428">Torna a una pàgina segura.</translation>
<translation id="6671697161687535275">Voleu suprimir el suggeriment de formulari de Chromium?</translation>
<translation id="6685834062052613830">Tanqueu la sessió i completeu la configuració</translation>
<translation id="6689271823431384964">Chrome t'està oferint desar les targetes al Compte de Google perquè tens la sessió iniciada. Pots canviar aquest comportament a la configuració. El nom del titular de la targeta s'obté del teu compte.</translation>
+<translation id="6707256370811247129">Comprova el contingut de la memòria cau i els fitxers que baixis de Chrome o que hi pengis.</translation>
<translation id="6710213216561001401">Anterior</translation>
<translation id="6710594484020273272">&lt;Escriviu el terme de cerca&gt;</translation>
<translation id="671076103358959139">Testimoni d'inscripció:</translation>
@@ -1053,10 +1070,10 @@
<translation id="6738516213925468394">Les teves dades es van encriptar el dia <ph name="TIME" /> amb la teva <ph name="BEGIN_LINK" />frase de contrasenya de sincronització<ph name="END_LINK" />. Introdueix-la per començar la sincronització.</translation>
<translation id="674375294223700098">Error de certificat del servidor desconegut.</translation>
<translation id="6744009308914054259">Mentre esperes a tenir connexió, pots visitar Baixades per llegir articles sense connexió.</translation>
+<translation id="6747611005629681221">Advertiment: s'han detectat funcions obsoletes.</translation>
<translation id="6753269504797312559">Valor de la política</translation>
<translation id="6757797048963528358">El dispositiu ha entrat en mode de repòs.</translation>
<translation id="6768213884286397650">Hagaki (postal)</translation>
-<translation id="6778737459546443941">El teu pare o la teva mare encara no ho han aprovat</translation>
<translation id="67862343314499040">Violeta</translation>
<translation id="6786747875388722282">Extensions</translation>
<translation id="6790428901817661496">Reprodueix</translation>
@@ -1064,6 +1081,7 @@
<translation id="681021252041861472">Camp obligatori</translation>
<translation id="6810899417690483278">Identificador de personalització</translation>
<translation id="6825578344716086703">Has provat d'accedir a <ph name="DOMAIN" />, però el servidor ha presentat un certificat signat mitjançant un algoritme de signatura dèbil (com ara SHA-1). Això indica que les credencials de seguretat que ha presentat el servidor podrien haver estat falsificades i que pot ser que el servidor no sigui el que esperaves (és possible que t'estiguis comunicant amb un atacant).</translation>
+<translation id="6826370046007623921">Prevenció de pèrdua de dades</translation>
<translation id="6831043979455480757">Tradueix</translation>
<translation id="6839929833149231406">Àrea</translation>
<translation id="6852204201400771460">Vols tornar a carregar l'aplicació?</translation>
@@ -1076,7 +1094,6 @@
<translation id="6891596781022320156">No s'admet el nivell de la política.</translation>
<translation id="6895330447102777224">La teva targeta s'ha confirmat</translation>
<translation id="6897140037006041989">Agent d'usuari</translation>
-<translation id="6903319715792422884">Per ajudar a millorar Navegació segura, envia a Google <ph name="BEGIN_WHITEPAPER_LINK" />algunes dades del sistema i contingut de les pàgines<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuari:</translation>
<translation id="6934672428414710184">Aquest nom prové del teu Compte de Google</translation>
<translation id="6944692733090228304">Has introduït la contrasenya en un lloc web que no està gestionat per <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Per protegir el teu compte, no facis servir la mateixa contrasenya en altres aplicacions ni llocs web.</translation>
@@ -1121,6 +1138,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> i <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> més}other{<ph name="PAYMENT_METHOD_PREVIEW" /> i <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> més}}</translation>
<translation id="7153618581592392745">Lavanda</translation>
<translation id="717330890047184534">Identificador de Gaia:</translation>
+<translation id="7174545416324379297">Combinats</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> i <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> més}other{<ph name="SHIPPING_OPTION_PREVIEW" /> i <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> més}}</translation>
<translation id="7177397715882417099">El servidor de destinació, <ph name="ORIGIN" />, ha sol·licitat que s'apliqui una política de seguretat a totes les sol·licituds que rebi. Però en comptes de proporcionar una política, ha redirigit el navegador a una altra destinació, de manera que el navegador no pot completar la sol·licitud que has fet per a <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Desa i emplena les formes de pagament</translation>
@@ -1146,7 +1164,7 @@ Detalls addicionals:
<translation id="7271803869921933038">Targetes de prepagament acceptades</translation>
<translation id="7275334191706090484">Adreces d'interès gestionades</translation>
<translation id="7298195798382681320">Recomanada</translation>
-<translation id="7300012071106347854">Blau elèctric</translation>
+<translation id="7300012071106347854">Blau de cobalt</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7303701124147721189">Perquè la propera vegada puguis pagar més ràpidament, emmagatzema la targeta i l'adreça de facturació al Compte de Google i en aquest dispositiu.</translation>
<translation id="7309308571273880165">S'ha capturat un informe d'error (<ph name="CRASH_TIME" />) (pujada sol·licitada per l'usuari, encara no s'ha dut a terme)</translation>
@@ -1155,6 +1173,7 @@ Detalls addicionals:
<translation id="7320336641823683070">Ajuda amb la connexió</translation>
<translation id="733354035281974745">Substitució del compte local del dispositiu</translation>
<translation id="7334320624316649418">&amp;Refés el canvi d'ordre</translation>
+<translation id="7337706099755338005">No està disponible a la teva plataforma.</translation>
<translation id="733923710415886693">El certificat del servidor no s'ha divulgat mitjançant la Transparència de certificats.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Està afiliat:</translation>
@@ -1186,7 +1205,6 @@ Detalls addicionals:
<translation id="7440140511386898319">Explora sense connexió</translation>
<translation id="7441627299479586546">Usuari de la política incorrecte</translation>
<translation id="7442725080345379071">Taronja clar</translation>
-<translation id="7444046173054089907">Aquest lloc està bloquejat</translation>
<translation id="7445762425076701745">La identitat del servidor al qual esteu connectat no es pot acabar de validar. Esteu connectat a un servidor que utilitza un nom que només és vàlid dins la vostra xarxa, de manera que una autoritat de certificació externa no en pot validar la propietat. Com que de tota manera algunes autoritats de certificació emetran certificats per a aquests noms, no es pot assegurar que estigueu connectat al lloc web previst i no a un atacant.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Obtenir més informació<ph name="END_LINK" /> sobre aquest problema</translation>
<translation id="7455133967321480974">Utilitza l'opció predeterminada global (Bloqueja)</translation>
@@ -1208,9 +1226,9 @@ Detalls addicionals:
<translation id="7538364083937897561">A2 (sobre)</translation>
<translation id="7542403920425041731">Un cop confirmada, els detalls de la targeta es compartiran amb aquest lloc web.</translation>
<translation id="7542995811387359312">L'emplenament automàtic de targetes de crèdit està desactivat perquè el formulari no utilitza una connexió segura.</translation>
-<translation id="7543525346216957623">Demana-ho al teu pare o a la teva mare</translation>
<translation id="7548892272833184391">Solucionar errors de connexió</translation>
<translation id="7549584377607005141">Aquesta pàgina web necessita dades que heu introduït anteiorment per poder mostrar-la correctament. Podeu tornar a enviar les dades, però es tornarà a repetir qualsevol acció que la pàgina hagi dut a terme prèviament.</translation>
+<translation id="7550637293666041147">El nom d'usuari del dispositiu i el nom d'usuari de Chrome</translation>
<translation id="7552846755917812628">Prova els consells següents:</translation>
<translation id="7554791636758816595">Pestanya nova</translation>
<translation id="7564049878696755256">Podries perdre l'accés al compte de <ph name="ORG_NAME" /> o tenir problemes de suplantació d'identitat. Chrome et recomana que canviïs la contrasenya ara.</translation>
@@ -1225,6 +1243,7 @@ Detalls addicionals:
<translation id="7610193165460212391">El valor es troba fora de l'interval <ph name="VALUE" /> .</translation>
<translation id="7613889955535752492">Data de caducitat: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Ja teniu dades encriptades amb una versió diferent de la contrasenya del vostre compte de Google. Introduïu-la a continuació.</translation>
+<translation id="7625784245512586808">Protecció contra amenaces de Chrome Enterprise</translation>
<translation id="7633909222644580952">Dades de rendiment i informes d'errors</translation>
<translation id="7637571805876720304">Voleu suprimir la targeta de crèdit de Chromium?</translation>
<translation id="7638605456503525968">Ports en sèrie</translation>
@@ -1237,7 +1256,6 @@ Detalls addicionals:
<translation id="7668654391829183341">Dispositiu desconegut</translation>
<translation id="7669271284792375604">És possible que els atacants d'aquest lloc intentin enganyar-te perquè instal·lis programes que perjudiquen la teva navegació (per exemple, et poden canviar la pàgina d'inici o mostrar anuncis addicionals als llocs que visites).</translation>
<translation id="7676643023259824263">Cerca el text (<ph name="TEXT" />) del porta-retalls</translation>
-<translation id="7679176406634891508">Plataforma i núvol</translation>
<translation id="7681101578153515023">Canvia el motor de cerca</translation>
<translation id="7682287625158474539">Enviament</translation>
<translation id="7687186412095877299">Emplena els formularis amb les formes de pagament desades</translation>
@@ -1252,7 +1270,6 @@ Detalls addicionals:
<translation id="7723047071702270851">Edita la targeta</translation>
<translation id="774634243536837715">S'ha bloquejat el contingut perillós.</translation>
<translation id="7752995774971033316">Sense gestionar</translation>
-<translation id="7755287808199759310">El teu pare o la teva mare et poden desbloquejar el lloc</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">És possible que l'antivirus o el tallafoc hagi bloquejat la connexió.</translation>
<translation id="7759163816903619567">Domini de publicació:</translation>
@@ -1296,7 +1313,6 @@ Detalls addicionals:
<translation id="8004582292198964060">Navegador</translation>
<translation id="8009225694047762179">Gestiona les contrasenyes</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Aquesta targeta i l'adreça de facturació associada es desaran. La podràs utilitzar quan tinguis la sessió iniciada a <ph name="USER_EMAIL" />.}other{Aquestes targetes i les adreces de facturació associades es desaran. Les podràs utilitzar quan tinguis la sessió iniciada a <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">En aquests moments no hem pogut contactar amb els teus pares. Torna-ho a provar.</translation>
<translation id="8025119109950072390">Els atacants d'aquest lloc et poden enganyar perquè facis alguna acció perillosa, com ara instal·lar programari o revelar informació personal (per exemple, contrasenyes, números de telèfon o targetes de crèdit).</translation>
<translation id="8034522405403831421">Aquesta pàgina està escrita en <ph name="SOURCE_LANGUAGE" />. Vols traduir-la a <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Bolígraf</translation>
@@ -1307,6 +1323,7 @@ Detalls addicionals:
<translation id="8041940743680923270">Utilitza l'opció predeterminada global (Pregunta)</translation>
<translation id="8042918947222776840">Tria un mètode de recollida</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> no s'ha configurat correctament. Normalment el problema se soluciona desinstal·lant <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">No caldrà que introdueixis el codi de seguretat de la targeta a partir d'ara</translation>
<translation id="8066955247577885446">S'ha produït un error.</translation>
<translation id="8074253406171541171">10x13 (sobre)</translation>
<translation id="8078141288243656252">No es poden fer anotacions en un document girat</translation>
@@ -1337,6 +1354,7 @@ Detalls addicionals:
<translation id="8211406090763984747">La connexió és segura</translation>
<translation id="8218327578424803826">Ubicació assignada:</translation>
<translation id="8220146938470311105">C7/C6 (sobre)</translation>
+<translation id="8220639454292072926">Informes d'empresa</translation>
<translation id="8225771182978767009">La persona que ha configurat l'ordinador ha bloquejat aquest lloc.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Obre la pàgina en una pestanya d'incògnit nova</translation>
@@ -1391,23 +1409,23 @@ Detalls addicionals:
<translation id="8508648098325802031">Icona de la cerca</translation>
<translation id="8522552481199248698">Chrome et pot ajudar a protegir el Compte de Google i a canviar la contrasenya.</translation>
<translation id="8543181531796978784">Podeu <ph name="BEGIN_ERROR_LINK" />informar d'un problema de detecció<ph name="END_ERROR_LINK" /> o, si enteneu els riscos que això comporta per a la vostra seguretat, <ph name="BEGIN_LINK" />visiteu aquest lloc no segur<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Tens preguntes? Contacta amb la persona que et supervisa el perfil.</translation>
<translation id="8553075262323480129">S'ha produït un error en fer la traducció perquè no s'ha pogut determinar l'idioma de la pàgina.</translation>
<translation id="8557066899867184262">El CVC es troba a la part posterior de la targeta.</translation>
<translation id="8559762987265718583">No es pot establir una connexió privada amb <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> perquè la data i l'hora (<ph name="DATE_AND_TIME" />) del dispositiu són incorrectes.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> lloc web sospitós</translation>
<translation id="8564985650692024650">Chromium et recomana que restableixis la contrasenya per a <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> si l'has fet servir en altres llocs web.</translation>
<translation id="8571890674111243710">S'està traduint la pàgina a l'idioma <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Afegeix un número de telèfon</translation>
-<translation id="859285277496340001">El certificat no especifica un mecanisme per comprovar si s'ha revocat.</translation>
<translation id="860043288473659153">Nom del titular de la targeta</translation>
<translation id="861775596732816396">Mida 4</translation>
-<translation id="8620436878122366504">Els teus pares encara no ho han aprovat</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Desa aquesta targeta al dispositiu</translation>
<translation id="8626112503828625890">Vols desar els detalls de facturació al Compte de Google?</translation>
+<translation id="8647750283161643317">Restableix-ho tot als valors predeterminats</translation>
<translation id="8663226718884576429">Resum de la comanda, <ph name="TOTAL_LABEL" />, més detalls</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, resposta, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponible</translation>
<translation id="8703575177326907206">La teva connexió a <ph name="DOMAIN" /> no està xifrada.</translation>
<translation id="8718314106902482036">No s'ha completat el pagament</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, suggeriment de cerca</translation>
@@ -1418,6 +1436,7 @@ Detalls addicionals:
<translation id="8738058698779197622">Per establir una connexió segura, el rellotge ha d'estar ben ajustat, perquè els certificats que els llocs web fan servir per identificar-se només són vàlids per a períodes de temps concrets. Com que el rellotge del dispositiu no està ben ajustat, Chromium no pot verificar aquests certificats.</translation>
<translation id="8740359287975076522">No s'ha trobat l'&lt;abbr id="dnsDefinition"&gt;adreça DNS&lt;/abbr&gt; de <ph name="HOST_NAME" />. S'està diagnosticant el problema.</translation>
<translation id="874846938927089722">Targetes de crèdit i de prepagament acceptades</translation>
+<translation id="874918643257405732">Afegeix aquesta pestanya a les adreces d'interès</translation>
<translation id="8759274551635299824">Aquesta targeta ha caducat</translation>
<translation id="8761567432415473239">Recentment, amb Navegació segura de Google s'han <ph name="BEGIN_LINK" />detectat programes perjudicials<ph name="END_LINK" /> al lloc <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispositiu USB</translation>
@@ -1447,6 +1466,7 @@ Detalls addicionals:
<translation id="8938939909778640821">Targetes de crèdit i de prepagament acceptades</translation>
<translation id="8943282376843390568">Verd llima</translation>
<translation id="8957210676456822347">Autorització de portals captius</translation>
+<translation id="8962950042226115166">Lloc web sospitós</translation>
<translation id="8968766641738584599">Desa la targeta</translation>
<translation id="8971063699422889582">El certificat del servidor ha caducat.</translation>
<translation id="8975012916872825179">Inclou informació com ara números de telèfon, adreces electròniques i adreces d'enviament</translation>
@@ -1469,24 +1489,24 @@ Detalls addicionals:
<translation id="9035022520814077154">Error de seguretat</translation>
<translation id="9038649477754266430">Utilitza un servei de predicció per poder carregar les pàgines més ràpidament</translation>
<translation id="9039213469156557790">A més, aquesta pàgina conté altres recursos que no són segurs. La resta d'usuaris poden visualitzar-los mentre estan en trànsit, i algun atacant podria modificar-los per canviar el comportament de la pàgina.</translation>
+<translation id="9044359186343685026">Utilitza Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" />, <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Heu provat d'accedir a <ph name="DOMAIN" />, però el servidor ha presentat un certificat no vàlid.</translation>
<translation id="9050666287014529139">Frase de contrasenya</translation>
<translation id="9065203028668620118">Edita</translation>
<translation id="9065745800631924235">Cerca de <ph name="TEXT" /> des de l'historial</translation>
<translation id="9069693763241529744">Bloquejat per una extensió</translation>
-<translation id="9076283476770535406">Pot incloure contingut no apte per a menors</translation>
<translation id="9076630408993835509">Cap empresa ni cap altra organització supervisa aquest navegador. És possible que l'activitat d'aquest dispositiu es gestioni fora de Chrome. <ph name="BEGIN_LINK" />Més informació<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Necessitem més informació</translation>
<translation id="9080712759204168376">Resum de la comanda</translation>
<translation id="9089260154716455634">Política fora de l'horari:</translation>
<translation id="9095388113577226029">Més idiomes...</translation>
+<translation id="9098981495403789647">L'administrador ha activat la protecció contra amenaces de Chrome Enterprise al navegador. La protecció contra amenaces de Chrome Enterprise té accés a algunes de les teves dades.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> utilitza normalment l'encriptació per protegir la vostra informació. En aquesta ocasió, quan Chromium ha provat de connectar-se a <ph name="SITE" />, el lloc web ha enviat credencials poc comunes i incorrectes. Pot ser que un atacant estigui provant de fer-se passar per <ph name="SITE" /> o que una pantalla d'inici de sessió a la xarxa Wi-Fi hagi interromput la connexió. En qualsevol cas, la vostra informació continua estant segura, perquè Chromium ha aturat la connexió abans no s'intercanviés cap dada.</translation>
<translation id="9106062320799175032">Afegeix una adreça de facturació</translation>
<translation id="9114524666733003316">S'està confirmant la targeta...</translation>
<translation id="9128870381267983090">Connecta't a la xarxa</translation>
<translation id="9137013805542155359">Mostra l'original</translation>
-<translation id="9137248913990643158">Obre Chrome i inicia-hi la sessió abans d'utilitzar aquesta aplicació.</translation>
<translation id="9141013498910525015">Gestiona les adreces</translation>
<translation id="9148088599418889305">Tria el mètode d'enviament</translation>
<translation id="9148507642005240123">&amp;Desfés la modificació</translation>
diff --git a/chromium/components/strings/components_strings_cs.xtb b/chromium/components/strings/components_strings_cs.xtb
index e6fd54b16bb..daccd623767 100644
--- a/chromium/components/strings/components_strings_cs.xtb
+++ b/chromium/components/strings/components_strings_cs.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Přidání jména na kartě</translation>
<translation id="1089439967362294234">Změnit heslo</translation>
+<translation id="1096545575934602868">Toto pole nesmí mít více než <ph name="MAX_ITEMS_LIMIT" /> položek. Všechny další položky budou zahozeny.</translation>
<translation id="109743633954054152">Hesla můžete spravovat v nastavení Chromu</translation>
<translation id="1103523840287552314">Vždy překládat jazyk <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Pokud je tato možnost zaškrtnuta, Chrome v tomto zařízení bude za účelem rychlejšího vyplňování formulářů uchovávat kopii vaší karty.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Otevřete <ph name="BEGIN_LINK" />archivovanou kopii<ph name="END_LINK" /> stránky <ph name="URL" /></translation>
<translation id="1156303062776767266">Prohlížíte si místní nebo sdílený soubor.</translation>
<translation id="1158211211994409885">Web <ph name="HOST_NAME" /> neočekávaně ukončil připojení.</translation>
+<translation id="115926840831309955">Zkontrolujte kód CVC a zkuste to znovu nebo aktualizujte datum konce platnosti</translation>
<translation id="1161325031994447685">Obnovit připojení k síti Wi-Fi</translation>
<translation id="1165039591588034296">Chyba</translation>
<translation id="1175364870820465910">Tisk...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">Software na počítači Chromu brání v bezpečném připojení k webu (pouze počítače se systémem Windows)</translation>
<translation id="1294154142200295408">Varianty pro příkazový řádek</translation>
<translation id="129553762522093515">Nedávno zavřené</translation>
+<translation id="1298536327547837046">Vyhledávání malwaru</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Zkuste vymazat soubory cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funkce, které již nejsou podporovány</translation>
<translation id="1320233736580025032">Prc1 (obálka)</translation>
<translation id="132301787627749051">Vyhledat obrázek ve schránce</translation>
<translation id="1323433172918577554">Zobrazit více</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Tabulky Google</translation>
<translation id="1527263332363067270">Čeká se na připojení…</translation>
<translation id="1529521330346880926">10x15 (obálka)</translation>
+<translation id="1530707389502320859">Web, který se pokoušíte navštívit, vypadá falešný. Útočníci někdy weby napodobují tak, že v adrese URL provádějí drobné, obtížně odhalitelné změny.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Tato stránka říká</translation>
<translation id="153384715582417236">To je prozatím vše</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">Operační systém</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokument je na přidání označení a poznámek příliš velký</translation>
-<translation id="1721312023322545264">Zdá se, že k návštěvě tohoto webu potřebujete povolení od správce <ph name="NAME" /></translation>
<translation id="1721424275792716183">* Pole je povinné</translation>
<translation id="1727741090716970331">Přidání platného čísla karty</translation>
<translation id="1728677426644403582">Prohlížíte si zdrojový kód webové stránky</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Navštívené weby a na nich strávený čas</translation>
<translation id="1826516787628120939">Probíhá kontrola</translation>
<translation id="1834321415901700177">Tento web obsahuje škodlivé programy</translation>
+<translation id="1838374766361614909">Vymazat vyhledávání</translation>
<translation id="1839551713262164453">Ověření hodnot zásad selhalo s chybami</translation>
<translation id="1842969606798536927">Zaplatit</translation>
<translation id="1871208020102129563">Proxy je nastaveno na používání pevně daných serverů proxy, nikoliv adresy URL skriptu PAC.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Sbalit seznam</translation>
<translation id="1898423065542865115">Filtrování</translation>
<translation id="1914326953223720820">Služba rozbalování souborů ZIP</translation>
+<translation id="1915697529809968049">Použít Touch ID namísto CVC?</translation>
<translation id="1916770123977586577">Chcete-li pro tento web použít aktualizovaná nastavení, načtěte tuto stránku znovu</translation>
<translation id="1919345977826869612">Reklamy</translation>
<translation id="1919367280705858090">Nápověda ke konkrétní chybové zprávě</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Záložky domény <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Chyba serializace</translation>
<translation id="1974060860693918893">Rozšířená nastavení</translation>
+<translation id="1974883374937189061">Pomozte zlepšit zabezpečení Chromu tím, že do Googlu budete odesílat <ph name="BEGIN_WHITEPAPER_LINK" />adresy URL některých navštívených stránek, omezené informace o systému a část obsahu stránek<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Verze firmwaru</translation>
<translation id="1981206234434200693">Vymazat z Chromu údaje o historii procházení</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{a 1 další}few{a # další}many{a # další}other{a # dalších}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Zadejte platný rok vypršení platnosti</translation>
<translation id="2212735316055980242">Zásada nebyla nalezena</translation>
<translation id="2213606439339815911">Načítání záznamů...</translation>
+<translation id="2215727959747642672">Úprava souborů</translation>
<translation id="2218879909401188352">Útočníci, kteří na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> aktuálně působí, by vám do zařízení mohli nainstalovat nebezpečné aplikace, které jej poškodí, přidat skryté poplatky na účet za mobilní služby nebo odcizit osobní údaje. <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Nejste připojeni k internetu</translation>
<translation id="2230458221926704099">Opravte připojení pomocí <ph name="BEGIN_LINK" />diagnostické aplikace<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Odeslat</translation>
+<translation id="2248949050832152960">Použít WebAuthn</translation>
<translation id="225207911366869382">Tato hodnota již pro tuto zásadu není podporována.</translation>
<translation id="2257315177824333709">Kartu v tuto chvíli nelze uložit</translation>
<translation id="2262243747453050782">Chyba protokolu HTTP</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">Neplatná adresa URL vyhledávání.</translation>
<translation id="2482878487686419369">Oznámení</translation>
<translation id="248348093745724435">Zásady zařízení</translation>
-<translation id="2485387744899240041">Uživatelská jména pro zařízení a prohlížeč</translation>
<translation id="2491120439723279231">Certifikát serveru obsahuje chyby.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analyzátor souborů JSON</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Zpět</translation>
<translation id="2503184589641749290">Přijímané debetní a předplacené karty</translation>
<translation id="2505268675989099013">Ochránit účet</translation>
+<translation id="2515335152965840738">IGNOROVAT</translation>
<translation id="2515629240566999685">Zkontrolovat, zda máte dostatečně silný signál</translation>
<translation id="2523886232349826891">Uloženo pouze do tohoto zařízení</translation>
<translation id="2524461107774643265">Přidání dalších informací</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Odeslat</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Žádné}=1{1 heslo (pro <ph name="DOMAIN_LIST" />)}=2{2 hesla (pro <ph name="DOMAIN_LIST" />)}few{# hesla (pro <ph name="DOMAIN_LIST" />)}many{# hesla (pro <ph name="DOMAIN_LIST" />)}other{# hesel (pro <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Zavřete ostatní karty nebo aplikace</translation>
-<translation id="267371737713284912">akci vrátíte zpět stisknutím kombinace kláves <ph name="MODIFIER_KEY_DESCRIPTION" /></translation>
<translation id="2674170444375937751">Jste si jisti, že chcete tyto stránky odstranit ze své historie?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Odejít</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">Hodnota neodpovídá formátu.</translation>
<translation id="2705137772291741111">Kopii tohoto webu uloženou v mezipaměti se nepodařilo přečíst.</translation>
<translation id="2709516037105925701">Automatické vyplňování</translation>
-<translation id="2712173769900027643">Požádat o oprávnění</translation>
<translation id="2713444072780614174">Bílá</translation>
<translation id="2720342946869265578">Nablízku</translation>
<translation id="2721148159707890343">Požadavek byl úspěšný</translation>
<translation id="2728127805433021124">Certifikát serveru je podepsán slabým algoritmem.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Spustit Diagnostiku připojení<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Aktivací těchto funkcí byste mohli přijít o údaje v prohlížeči nebo ohrozit svoji bezpečnost nebo soukromí. Aktivace funkcí se vztahuje na všechny uživatele tohoto prohlížeče.</translation>
<translation id="2735043616039983645">Pro tuto zásadu je přítomno několik zdrojů s konfliktními hodnotami.</translation>
<translation id="2738330467931008676">Vybrat adresu vyzvednutí</translation>
<translation id="2740531572673183784">OK</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">Připojení bylo resetováno.</translation>
<translation id="2788784517760473862">Přijímané kreditní karty</translation>
<translation id="2792012897584536778">Administrátoři tohoto zařízení nastavili bezpečnostní certifikáty, které jim mohou umožnit zobrazit obsah webů, které navštěvujete.</translation>
-<translation id="2794233252405721443">Web je blokován</translation>
<translation id="2799020568854403057">Web, na který se chystáte přejít, obsahuje škodlivé aplikace</translation>
<translation id="2799223571221894425">Restartovat</translation>
<translation id="2803306138276472711">Služba Bezpečné prohlížení Google na webu <ph name="SITE" /> nedávno <ph name="BEGIN_LINK" />zjistila malware<ph name="END_LINK" />. Někdy mohou být malwarem nakaženy i weby, které jsou obvykle bezpečné.</translation>
+<translation id="2815364696811431560">OPUSTIT WEB</translation>
<translation id="2824775600643448204">Adresní a vyhledávací řádek</translation>
<translation id="2826760142808435982">Připojení je šifrováno a ověřeno pomocí šifry <ph name="CIPHER" /> a jako mechanismus výměny klíčů používá <ph name="KX" />.</translation>
<translation id="2835170189407361413">Vymazat formulář</translation>
<translation id="2847118875340931228">Otevřít anonymní okno</translation>
<translation id="2850739647070081192">Invite (obálka)</translation>
-<translation id="2851634818064021665">K návštěvě tohoto webu potřebujete povolení</translation>
<translation id="2856444702002559011">Útočníci se mohou pokusit odcizit vaše údaje na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (například hesla, zprávy nebo informace o platebních kartách). <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Uložit kartu?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Pokud je tato možnost aktivována, prohlížeč Chromium do zařízení uloží kopii karty za účelem rychlejšího vyplňování formulářů.</translation>
<translation id="2985398929374701810">Zadejte platnou adresu</translation>
<translation id="2986368408720340940">Tento způsob vyzvednutí není k dispozici. Zkuste použít jiný způsob.</translation>
+<translation id="2987034854559945715">Žádné funkce neodpovídají</translation>
<translation id="2991174974383378012">Sdílení s weby</translation>
<translation id="2991571918955627853">Web <ph name="SITE" /> teď nemůžete navštívit, protože používá zabezpečení HSTS. Síťové chyby a útoky jsou obvykle dočasné, tato stránka pravděpodobně později bude fungovat.</translation>
<translation id="3005723025932146533">Zobrazit uloženou kopii</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Chybný typ zásady</translation>
<translation id="3037605927509011580">Aj, chyba!</translation>
<translation id="3041612393474885105">Informace o certifikátu</translation>
+<translation id="3057676462092457419">Režim DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> zatím není podporován. Režim byl nastaven na <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (obálka)</translation>
<translation id="3061707000357573562">Služba oprav</translation>
<translation id="3064966200440839136">Chystáte se opustit anonymní režim, abyste mohli zaplatit v externí aplikaci. Chcete pokračovat?</translation>
@@ -416,6 +425,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na serveru <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Zrušit platbu</translation>
<translation id="3207960819495026254">Přidáno do záložek</translation>
+<translation id="3209034400446768650">Stránka může účtovat poplatky</translation>
<translation id="3225919329040284222">Server se prokázal certifikátem, který neodpovídá integrovaným očekáváním. Tato očekávaní jsou zahrnuta u určitých webových stránek s vysokou úrovní zabezpečení kvůli vaší ochraně.</translation>
<translation id="3226128629678568754">Klikněte na tlačítko Načíst znovu. Tím znovu odešlete údaje potřebné k načtení stránky.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -423,7 +433,6 @@
<translation id="3229041911291329567">Informace o verzi zařízení a prohlížeče</translation>
<translation id="323107829343500871">Zadejte kód CVC karty <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Vždy na tomto webu zjišťovat důležitý obsah</translation>
-<translation id="3254409185687681395">Přidat stránku do záložek</translation>
<translation id="3270847123878663523">&amp;Vrátit změnu uspořádání zpět</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Přidání jména na kartě</translation>
@@ -433,7 +442,6 @@
<translation id="3320021301628644560">Přidání fakturační adresy</translation>
<translation id="3324983252691184275">Karmínová</translation>
<translation id="3338095232262050444">Zabezpečeno</translation>
-<translation id="3345135638360864351">Odeslání žádosti o přístup k tomuto webu uživateli <ph name="NAME" /> se nezdařilo. Zkuste to prosím znovu.</translation>
<translation id="3355823806454867987">Změna nastavení proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />nebude ukládat<ph name="END_EMPHASIS" /> následující informace:
<ph name="BEGIN_LIST" />
@@ -467,18 +475,15 @@
<translation id="3462200631372590220">Skrýt rozšířené</translation>
<translation id="3467763166455606212">Je nutné zadat jméno držitele karty</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, aktuálně otevřeno, na otevřenou kartu přejdete tak, že stisknete tabulátor a poté Enter</translation>
-<translation id="3479539252931486093">Nebylo toto očekáváno? <ph name="BEGIN_LINK" />Informujte nás<ph name="END_LINK" />.</translation>
<translation id="3479552764303398839">Teď ne</translation>
<translation id="3484560055331845446">Mohli byste ztratit přístup k účtu Google. Chrome doporučuje okamžitě změnit heslo. Budete vyzváni k přihlášení.</translation>
<translation id="3495081129428749620">Najít na stránce
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">V tuto chvíli se nám s vaším rodičem nepodařilo spojit. Zkuste to prosím znovu.</translation>
<translation id="3512163584740124171">Tato zásada se ignoruje, protože jiná zásada ze stejné skupiny zásad má vyšší prioritu.</translation>
<translation id="3528171143076753409">Certifikát serveru není důvěryhodný.</translation>
<translation id="3528485271872257980">Tmavě hnědá</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Alespoň jedna položka v synchronizovaných zařízeních}=1{1 položka (a další v synchronizovaných zařízeních)}few{# položky (a další v synchronizovaných zařízeních)}many{# položky (a další v synchronizovaných zařízeních)}other{# položek (a další v synchronizovaných zařízeních)}}</translation>
<translation id="3539171420378717834">Uchovat kopii této karty v tomto zařízení</translation>
-<translation id="3556433843310711081">Správce vám jej může odblokovat.</translation>
<translation id="3566021033012934673">Vaše připojení není soukromé</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Vložená stránka na webu <ph name="SITE" /> říká</translation>
@@ -505,6 +510,7 @@
<translation id="3678529606614285348">Otevřete stránku v novém anonymním okně (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Zpráva o selhání pořízená <ph name="CRASH_TIME" /> byla nahrána <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informace o certifikátu</translation>
+<translation id="3701427423622901115">Resetování bylo potvrzeno.</translation>
<translation id="3704162925118123524">Síť, kterou používáte, může vyžadovat, abyste navštívili její stránku přihlášení.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Načítání...</translation>
@@ -521,6 +527,7 @@
<translation id="3748148204939282805">Útočníci na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> vás mohou podvodem přimět k nebezpečnému chování, jako je instalace softwaru nebo vyzrazení osobních údajů (například hesel, telefonních čísel nebo platebních karet). <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Z důvodu chyby serveru se překlad nezdařil.</translation>
<translation id="3759461132968374835">Nemáte žádná nedávno hlášená selhání. Selhání, ke kterým došlo, když byla služba hlášení o selháních vypnutá, se zde nezobrazují.</translation>
+<translation id="3760561303380396507">Použít Windows Hello namísto CVC?</translation>
<translation id="3761718714832595332">Skrýt stav</translation>
<translation id="3765032636089507299">Stránka Bezpečného procházení je ve výstavbě.</translation>
<translation id="3778403066972421603">Chcete tuto kartu uložit do svého účtu Google a do tohoto zařízení?</translation>
@@ -530,6 +537,7 @@
<translation id="3789155188480882154">Velikost 16</translation>
<translation id="3797522431967816232">Prc3 (obálka)</translation>
<translation id="3807873520724684969">Byl zablokován škodlivý obsah.</translation>
+<translation id="3808375843007691220">Upozornění: Tyto funkce jsou experimentální</translation>
<translation id="3810973564298564668">Spravovat</translation>
<translation id="382518646247711829">Pokud používáte proxy server...</translation>
<translation id="3828924085048779000">Prázdná heslová fráze není povolena.</translation>
@@ -538,11 +546,11 @@
<translation id="3858027520442213535">Aktualizovat datum a čas</translation>
<translation id="3884278016824448484">Konfliktní identifikátor zařízení</translation>
<translation id="3885155851504623709">Farnost</translation>
-<translation id="3886446263141354045">Vaše žádost o přístup k tomuto webu byla odeslána uživateli <ph name="NAME" />.</translation>
<translation id="3890664840433101773">Přidat e-mail</translation>
<translation id="3901925938762663762">Karta vypršela</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Použít WebAuthn namísto CVC?</translation>
<translation id="3946209740501886391">Na tomto webu se vždy zeptat</translation>
<translation id="3949571496842715403">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />. V jeho bezpečnostním certifikátu nejsou uvedeny alternativní názvy subjektu. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
<translation id="3949601375789751990">Zde se zobrazuje vaše historie prohlížení</translation>
@@ -553,11 +561,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Žádné}=1{Z 1 webu }few{Z # webů }many{Z # webu }other{Z # webů }}</translation>
<translation id="397105322502079400">Probíhá výpočet…</translation>
<translation id="3973234410852337861">Web <ph name="HOST_NAME" /> je blokován</translation>
+<translation id="3981540111851280311">Organizace <ph name="ENROLLMENT_DOMAIN" /> ve vašem prohlížeči zapnula ochranu před hrozbami Chrome Enterprise. Ochrana před hrozbami Chrome Enterprise má přístup k některým vašim datům.</translation>
<translation id="3987940399970879459">Méně než 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 webová stránka v okolí}few{# webové stránky v okolí}many{# webové stránky v okolí}other{# webových stránek v okolí}}</translation>
<translation id="4030383055268325496">&amp;Vrátit přidání zpět</translation>
<translation id="4032320456957708163">Prohlížeč je spravován doménou <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Otevřeli jste odkaz na web, který obvykle nenavštěvujete. Je možné, že se vás pokouší zmást.</translation>
<translation id="4058922952496707368">Klíč <ph name="SUBKEY" />: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (obálka)</translation>
<translation id="4067947977115446013">Přidejte platnou adresu</translation>
@@ -570,6 +578,7 @@
<translation id="4103249731201008433">Sériové číslo zařízení je neplatné</translation>
<translation id="410351446219883937">Automatické přehrávání</translation>
<translation id="4103763322291513355">Na stránce &lt;strong&gt;chrome://policy&lt;/strong&gt; naleznete seznam zakázaných adres URL a další zásady vynucené vaším správcem systému.</translation>
+<translation id="4108231218301530806">Příště tuto kartu ověřit otiskem prstu.</translation>
<translation id="4110652170750985508">Kontrola platby</translation>
<translation id="4112140312785995938">Přetočit dozadu</translation>
<translation id="4116663294526079822">Povolit vždy na tomto webu</translation>
@@ -584,6 +593,7 @@
<translation id="4171400957073367226">Chybný ověřovací podpis</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> další položka}few{<ph name="ITEM_COUNT" /> další položky}many{<ph name="ITEM_COUNT" /> další položky}other{<ph name="ITEM_COUNT" /> dalších položek}}</translation>
+<translation id="4176463684765177261">Vypnuto</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Chcete-li příště zaplatit rychleji, přidejte si kartu a fakturační adresu do účtu Google.</translation>
<translation id="4196861286325780578">&amp;Opakovat přesunutí</translation>
@@ -620,6 +630,7 @@
<translation id="4277028893293644418">Resetovat heslo</translation>
<translation id="4279811152705618813">Váš <ph name="DEVICE_TYPE" /> spravuje doména <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Tato karta byla uložena do vašeho učtu Google}few{Tyto karty byly uloženy do vašeho účtu Google.}many{Tyto karty byly uloženy do vašeho účtu Google.}other{Tyto karty byly uloženy do vašeho účtu Google.}}</translation>
+<translation id="428847186335018806">Prohledávat soubory, které v Chromu stahujete nebo nahráváte.</translation>
<translation id="42981349822642051">Rozbalit</translation>
<translation id="4302965934281694568">Chou3 (obálka)</translation>
<translation id="4305817255990598646">Přepínač</translation>
@@ -649,7 +660,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Využití proxy serveru je zakázáno, je však určena explicitní konfigurace proxy serveru.</translation>
<translation id="445100540951337728">Přijímané debetní karty</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> podezřelé chování</translation>
<translation id="4466881336512663640">Změny ve formuláři budou ztraceny. Opravdu chcete pokračovat?</translation>
<translation id="4477350412780666475">Další skladba</translation>
<translation id="4482953324121162758">Tento web se nebude překládat.</translation>
@@ -676,6 +686,7 @@
<translation id="4594403342090139922">&amp;Vrátit smazání zpět</translation>
<translation id="4597348597567598915">Velikost 8</translation>
<translation id="4600854749408232102">C6/C5 (obálka)</translation>
+<translation id="464342062220857295">Funkce vyhledávání</translation>
<translation id="4646534391647090355">Zobrazit</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />, protože jeho bezpečnostní certifikát obsahuje chyby. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
@@ -684,7 +695,6 @@
<translation id="4691835149146451662">Architecture-A (obálka)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Připojení bylo přerušeno</translation>
-<translation id="471880041731876836">K návštěvě tohoto webu nemáte povolení</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Spustit Diagnostiku sítě systému Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Znovu načíst zásady</translation>
<translation id="4728558894243024398">Platforma</translation>
@@ -712,7 +722,6 @@
<translation id="4816492930507672669">Přizpůsobit na stránku</translation>
<translation id="4850886885716139402">Zobrazit</translation>
<translation id="4854362297993841467">Tento způsob doručení není k dispozici. Zkuste použít jiný způsob.</translation>
-<translation id="4858792381671956233">Požádal(a) jsi rodiče o povolení návštěvy tohoto webu.</translation>
<translation id="4864052566555297930">Bezpečnostní tip:</translation>
<translation id="4876188919622883022">Zjednodušené zobrazení</translation>
<translation id="4876305945144899064">Žádné uživatelské jméno</translation>
@@ -736,7 +745,9 @@
<translation id="4974590756084640048">Znovu zapnout upozornění</translation>
<translation id="4984339528288761049">Prc5 (obálka)</translation>
<translation id="4989163558385430922">Zobrazit vše</translation>
+<translation id="4989542687859782284">Nedostupné</translation>
<translation id="4989809363548539747">Tento plugin není podporován</translation>
+<translation id="4995216769782533993">Chcete-li s tímto webem sdílet údaje o kartě, zadejte bezpečnostní kód</translation>
<translation id="5002932099480077015">Pokud je tato možnost aktivována, Chrome do zařízení uloží kopii karty za účelem rychlejšího vyplňování formulářů.</translation>
<translation id="5015510746216210676">Název počítače:</translation>
<translation id="5017554619425969104">Zkopírovaný text</translation>
@@ -765,6 +776,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64bitový)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Ověřte svou kartu</translation>
<translation id="5135404736266831032">Spravovat adresy...</translation>
<translation id="5138227688689900538">Zobrazit méně</translation>
<translation id="5141240743006678641">Šifrovat synchronizovaná hesla pomocí hesla k účtu Google</translation>
@@ -791,6 +803,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (obálka)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funkce, které se vztahují na celý systém, může nastavit pouze vlastník: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Upozornění: Tato zásada nebyla sloučena podle zásady PolicyDictionaryMultipleSourceMergeList, protože nepatří mezi slovníkové zásady, které lze sloučit.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Konec</translation>
@@ -814,7 +827,6 @@
<translation id="536296301121032821">Ukládání nastavení zásady se nezdařilo</translation>
<translation id="5371425731340848620">Aktualizace karty</translation>
<translation id="5377026284221673050">Vaše hodiny se zpožďují, Vaše hodiny jdou napřed nebo &lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;</translation>
-<translation id="5377179979757081683">Tato stránka by se vás mohla pokusit oklamat, ukrást vám osobní údaje nebo vám poškodit zařízení. Při zadávání osobních údajů a otevírání stažených souborů buďte opatrní.</translation>
<translation id="5384855140246857529">Chcete-li své karty používat na všech zařízeních, přihlaste se a zapněte synchronizaci.</translation>
<translation id="5386426401304769735">Řetězec certifikátů tohoto webu obsahuje certifikát podepsaný algoritmem SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -828,6 +840,7 @@
<translation id="5457113250005438886">Neplatné</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> další}few{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> další}many{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> dalšího}other{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> dalších}}</translation>
<translation id="5470861586879999274">&amp;Opakovat úpravy</translation>
+<translation id="5473728911100096288">Pokud aktivujete tyto funkce, budete používat funkce, jejichž podpora byla ukončena a které v budoucích verzích již nebudou k dispozici</translation>
<translation id="5478437291406423475">B6/C4 (obálka)</translation>
<translation id="5481076368049295676">Tento obsah by vám do zařízení mohl zkusit nainstalovat nebezpečný software, který odcizuje nebo maže informace. <ph name="BEGIN_LINK" />Přesto zobrazit<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Přidejte platnou adresu</translation>
@@ -851,7 +864,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="5570825185877910964">Ochránit účet</translation>
<translation id="5571083550517324815">Vyzvednutí na této adrese není možné. Vyberte jinou adresu.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{používá se 1}few{používají se #}many{používá se #}other{používá se #}})</translation>
-<translation id="5572851009514199876">Přihlaste se do Chromu, aby bylo možné ověřit, zda máte povolení tento web navštívit.</translation>
<translation id="5580958916614886209">Zkontrolujte měsíc vypršení platnosti a zkuste to znovu.</translation>
<translation id="5586446728396275693">Žádné uložené adresy</translation>
<translation id="5595485650161345191">Upravit adresu</translation>
@@ -859,6 +871,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="560412284261940334">Správa není podporována</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Tento web může být falešný nebo podvodný. Chrome vám doporučuje okamžitě odejít.</translation>
<translation id="5610142619324316209">Zkontrolovat připojení</translation>
<translation id="5610807607761827392">Karty a adresy můžete spravovat v <ph name="BEGIN_LINK" />Nastavení<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Web <ph name="HOST_NAME" /> vás přesměroval příliš mnohokrát.</translation>
@@ -882,11 +895,11 @@ Kontaktujte administrátora systému.</translation>
<translation id="5720705177508910913">Aktuální uživatel</translation>
<translation id="5728056243719941842">C5 (obálka)</translation>
<translation id="5730040223043577876">Pokud jste heslo použili na jiném webu, doporučujeme vám ho resetovat.</translation>
-<translation id="5732392974455271431">Rodiče ti jej mohou odblokovat.</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Uložit kartu do účtu Google}few{Uložit karty do účtu Google}many{Uložit karty do účtu Google}other{Uložit karty do účtu Google}}</translation>
<translation id="5763042198335101085">Zadejte platnou e-mailovou adresu</translation>
<translation id="5765072501007116331">Chcete-li zobrazit způsoby doručení a požadavky, vyberte adresu</translation>
<translation id="5778550464785688721">Úplná kontrola zařízení MIDI</translation>
+<translation id="5781136890105823427">Je zapnutý experiment</translation>
<translation id="578305955206182703">Žlutohnědá</translation>
<translation id="57838592816432529">Ztlumit</translation>
<translation id="5784606427469807560">Při ověřování vaší karty došlo k problému. Zkontrolujte připojení k internetu a zkuste to znovu.</translation>
@@ -903,13 +916,16 @@ Kontaktujte administrátora systému.</translation>
<translation id="5860033963881614850">Vypnuto</translation>
<translation id="5863847714970149516">Následující stránka se vám může pokusit naúčtovat poplatky</translation>
<translation id="5866257070973731571">Přidání telefonního čísla</translation>
+<translation id="5866898949289125849">Prohlížíte si stránku nástrojů pro vývojáře</translation>
<translation id="5869405914158311789">Tento web není dostupný</translation>
<translation id="5869522115854928033">Uložená hesla</translation>
<translation id="5887400589839399685">Karta byla uložena</translation>
<translation id="5893752035575986141">Obchodník přijímá kreditní karty.</translation>
+<translation id="5895138241574237353">Restartovat</translation>
<translation id="5901630391730855834">Žlutá</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronizováno)</translation>
<translation id="5916664084637901428">Zapnuto</translation>
+<translation id="59174027418879706">Povoleno</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Uložit kartu do účtu Google?</translation>
<translation id="5922853866070715753">Téměř dokončeno</translation>
@@ -943,6 +959,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Chcete své karty používat na všech svých zařízeních?</translation>
<translation id="6059925163896151826">Zařízení USB</translation>
+<translation id="6060009363608157444">Režim DnsOverHttps je neplatný.</translation>
<translation id="6080696365213338172">Získali jste přístup k obsahu pomocí certifikátu poskytnutého správcem. Údaje poskytovaná doméně <ph name="DOMAIN" /> bude správce moci zachytit.</translation>
<translation id="6094273045989040137">Přidat značky a poznámky</translation>
<translation id="610911394827799129">Na stránce <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> mohou být k dispozici další druhy historie prohlížení zaznamenané ve vašem účtu Google.</translation>
@@ -990,13 +1007,12 @@ Kontaktujte administrátora systému.</translation>
<translation id="6404511346730675251">Upravit záložku</translation>
<translation id="6406765186087300643">C0 (obálka)</translation>
<translation id="6410264514553301377">Zadejte datum vypršení platnosti a kód CVC karty <ph name="CREDIT_CARD" />.</translation>
-<translation id="6414888972213066896">Zeptal(a) ses rodiče, zda můžeš navštívit tento web.</translation>
<translation id="6415778972515849510">Chromium vám může pomoci ochránit váš účet Google a změnit heslo.</translation>
-<translation id="6417515091412812850">Nelze ověřit, zda byl certifikát zrušen.</translation>
<translation id="6431585503458005759">Neukládat</translation>
<translation id="6433490469411711332">Upravit kontaktní údaje</translation>
<translation id="6433595998831338502">Web <ph name="HOST_NAME" /> odmítl připojení.</translation>
<translation id="6434309073475700221">Zahodit</translation>
+<translation id="6435221585574090192">Sdílet s administrátorem údaje o událostech zabezpečení nahlášených ochranou před hrozbami Chrome Enterprise. Sdílené údaje mohou zahrnovat adresy URL stránek, názvy souborů, metadata souborů, uživatelské jméno použité v zařízení a uživatelské jméno použité v Chromu.</translation>
<translation id="6440503408713884761">Ignorováno</translation>
<translation id="6446163441502663861">Kahu (obálka)</translation>
<translation id="6446608382365791566">Přidání dalších informací</translation>
@@ -1005,20 +1021,19 @@ Kontaktujte administrátora systému.</translation>
<translation id="6465306955648956876">Spravovat hesla...</translation>
<translation id="647261751007945333">Zásady zařízení</translation>
<translation id="6476284679642588870">Správa platebních metod</translation>
-<translation id="6477321094435799029">Chrome na této stránce zjistil neobvyklý kód a z důvodu ochrany vašich osobních údajů (například hesel, telefonních čísel a platebních karet) ji zablokoval.</translation>
<translation id="6489534406876378309">Začít nahrávat zprávy o selhání</translation>
<translation id="6499038740797743453">Resetovat heslo?</translation>
<translation id="6507833130742554667">Obchodník přijímá kreditní a debetní karty.</translation>
<translation id="650855688985305916">Ano, uložit</translation>
<translation id="6508722015517270189">Restartujte Chrome</translation>
<translation id="6517596291481585650">Upozornění: Tato zásada nebyla podle zásady sloučena jako seznam, protože se nejedná o seznam.</translation>
+<translation id="6518133107902771759">Ověřit</translation>
<translation id="6521745193039995384">Neaktivní</translation>
<translation id="6529602333819889595">&amp;Opakovat smazání</translation>
<translation id="6534179046333460208">Návrhy fyzického webu</translation>
<translation id="6545864417968258051">Vyhledávání Bluetooth</translation>
<translation id="6554795675067793129">Váš účet je spravován doménou <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Opakovat</translation>
-<translation id="6563469144985748109">Správce vám přístup na web dosud neschválil.</translation>
<translation id="6569060085658103619">Prohlížíte si stránku rozšíření</translation>
<translation id="6578796323535178455">C2 (obálka)</translation>
<translation id="6579990219486187401">Světle růžová</translation>
@@ -1036,11 +1051,13 @@ Kontaktujte administrátora systému.</translation>
<translation id="6643016212128521049">Vymazat</translation>
<translation id="6644283850729428850">Tato zásada se již nepoužívá.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Žádné}=1{Z 1 webu (nebudete odhlášeni z účtu Google)}few{Ze # webů (nebudete odhlášeni z účtu Google)}many{Z # webu (nebudete odhlášeni z účtu Google)}other{Z # webů (nebudete odhlášeni z účtu Google)}}</translation>
+<translation id="6652101503459149953">Použít Windows Hello</translation>
<translation id="6657585470893396449">Heslo</translation>
<translation id="6670613747977017428">Zpět do bezpečí</translation>
<translation id="6671697161687535275">Odstranit návrh položky formuláře z prohlížeče Chromium?</translation>
<translation id="6685834062052613830">Odhlaste se a dokončete nastavení</translation>
<translation id="6689271823431384964">Chrome vám nabízí uložení karet do účtu Google, protože jste přihlášeni. Toto chování můžete změnit v Nastavení. Jméno držitele karty pochází z vašeho účtu.</translation>
+<translation id="6707256370811247129">Prohledávat obsah mezipaměti a soubory, které v Chromu stahujete nebo nahráváte.</translation>
<translation id="6710213216561001401">Předchozí</translation>
<translation id="6710594484020273272">&lt;Zadejte vyhledávací dotaz&gt;</translation>
<translation id="671076103358959139">Registrační token:</translation>
@@ -1048,10 +1065,10 @@ Kontaktujte administrátora systému.</translation>
<translation id="6738516213925468394">Vaše data byla <ph name="TIME" /> zašifrována pomocí <ph name="BEGIN_LINK" />heslové fráze pro synchronizaci<ph name="END_LINK" />. Chcete-li zahájit synchronizaci, zadejte ji.</translation>
<translation id="674375294223700098">Neznámá chyba certifikátu serveru.</translation>
<translation id="6744009308914054259">Zatímco čekáte na připojení, v sekci Stažené soubory si můžete přečíst offline články.</translation>
+<translation id="6747611005629681221">Upozornění: Podpora těchto funkcí byla ukončena.</translation>
<translation id="6753269504797312559">Hodnota zásady</translation>
<translation id="6757797048963528358">Zařízení přešlo do režimu spánku.</translation>
<translation id="6768213884286397650">Hagaki (pohlednice)</translation>
-<translation id="6778737459546443941">Rodič ti přístup na web dosud neschválil.</translation>
<translation id="67862343314499040">Fialová</translation>
<translation id="6786747875388722282">Rozšíření</translation>
<translation id="6790428901817661496">Přehrát</translation>
@@ -1059,6 +1076,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="681021252041861472">Povinné pole</translation>
<translation id="6810899417690483278">ID přizpůsobení</translation>
<translation id="6825578344716086703">Pokusili jste se přejít na web <ph name="DOMAIN" />, server však předložil certifikát podepsaný slabým algoritmem (například SHA-1). To znamená, že bezpečnostní pověření předložená serverem mohou být falešná a může se jednat o úplně jiný server, než předpokládáte (můžete komunikovat s útočníkem).</translation>
+<translation id="6826370046007623921">Ochrana před únikem informací</translation>
<translation id="6831043979455480757">Přeložit</translation>
<translation id="6839929833149231406">Oblast</translation>
<translation id="6852204201400771460">Načíst aplikaci znovu?</translation>
@@ -1071,7 +1089,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="6891596781022320156">Úroveň zásady není podporována.</translation>
<translation id="6895330447102777224">Vaše karta je ověřena</translation>
<translation id="6897140037006041989">User agent</translation>
-<translation id="6903319715792422884">Pomozte zlepšit Bezpečné vyhledávání tím, že budete část <ph name="BEGIN_WHITEPAPER_LINK" />informací o systému a obsahu stránek<ph name="END_WHITEPAPER_LINK" /> odesílat do Googlu. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Uživatel:</translation>
<translation id="6934672428414710184">Toto jméno pochází z vašeho účtu Google</translation>
<translation id="6944692733090228304">Zadali jste heslo na webu, který není spravován organizací <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Aby byl váš účet chráněn, nepoužívejte jeho heslo v jiných aplikacích a na jiných webech.</translation>
@@ -1116,6 +1133,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> další}few{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> další}many{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> další}other{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> dalších}}</translation>
<translation id="7153618581592392745">Levandulová</translation>
<translation id="717330890047184534">ID Gaia:</translation>
+<translation id="7174545416324379297">Sloučeno</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> další}few{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> další}many{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> další}other{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> dalších}}</translation>
<translation id="7177397715882417099">Server, na který přecházíte (<ph name="ORIGIN" />), požádal, aby se na všechny na něj odesílané požadavky vztahovaly bezpečnostní zásady. Server však namísto poskytnutí zásad přesměroval prohlížeč jinam. Prohlížeč proto váš požadavek na web <ph name="SITE" /> nemůže splnit.</translation>
<translation id="7179323680825933600">Ukládat a vyplňovat platební metody</translation>
@@ -1149,6 +1167,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7320336641823683070">Pomoc s připojením</translation>
<translation id="733354035281974745">Místní přepsání účtu na zařízení</translation>
<translation id="7334320624316649418">&amp;Opakovat změnu uspořádání</translation>
+<translation id="7337706099755338005">Pro vaši platformu nedostupné.</translation>
<translation id="733923710415886693">Certifikát serveru nebyl zveřejněn prostřednictvím projektu Certificate Transparency.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Je přidružený:</translation>
@@ -1180,7 +1199,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="7440140511386898319">Prozkoumávejte i offline</translation>
<translation id="7441627299479586546">Chybný předmět zásady</translation>
<translation id="7442725080345379071">Světle oranžová</translation>
-<translation id="7444046173054089907">Tento web je blokován</translation>
<translation id="7445762425076701745">Totožnost serveru, k němuž jste připojeni, nelze plně ověřit. Jste připojeni k serveru, který používá název platný pouze v rámci vaší sítě. Externí certifikační autorita nemůže vlastnictví názvu nijak ověřit. Některé certifikační autority však vydají certifikát i pro takové názvy, a nelze tedy zaručit, že jste připojeni k požadovanému webu a nikoli k webu útočníka.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Další informace<ph name="END_LINK" /> o tomto problému.</translation>
<translation id="7455133967321480974">Použít výchozí globální hodnotu (Blokovat)</translation>
@@ -1202,9 +1220,9 @@ Kontaktujte administrátora systému.</translation>
<translation id="7538364083937897561">A2 (obálka)</translation>
<translation id="7542403920425041731">Po ověření budou údaje o kartě sdíleny s tímto webem.</translation>
<translation id="7542995811387359312">Automatické vyplňování údajů platební karty je deaktivováno, protože tento formulář nepoužívá zabezpečené připojení.</translation>
-<translation id="7543525346216957623">Požádej rodiče</translation>
<translation id="7548892272833184391">Oprava chyb připojení</translation>
<translation id="7549584377607005141">Tato stránka potřebuje ke správnému zobrazení data, která jste zadali dříve. Tyto údaje můžete odeslat znovu, ale zopakujete tím všechny akce, které tato stránka již předtím provedla.</translation>
+<translation id="7550637293666041147">Vaše uživatelské jméno na zařízení a v Chromu</translation>
<translation id="7552846755917812628">Vyzkoušejte následující tipy:</translation>
<translation id="7554791636758816595">Nová karta</translation>
<translation id="7564049878696755256">Mohli byste ztratit přístup k účtu <ph name="ORG_NAME" /> nebo by mohlo dojít k odcizení vaší identity. Doporučujeme vám okamžitě změnit heslo.</translation>
@@ -1219,6 +1237,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7610193165460212391">Hodnota <ph name="VALUE" /> je mimo rozsah.</translation>
<translation id="7613889955535752492">Vypršení platnosti: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Již máte údaje, které jsou šifrovány pomocí jiné verze vašeho hesla k účtu Google. Zadejte toto heslo prosím níže.</translation>
+<translation id="7625784245512586808">Ochrana před hrozbami Chrome Enterprise</translation>
<translation id="7633909222644580952">Údaje o výkonu a přehledy selhání</translation>
<translation id="7637571805876720304">Odstranit platební kartu z prohlížeče Chromium?</translation>
<translation id="7638605456503525968">Sériové porty</translation>
@@ -1231,7 +1250,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="7668654391829183341">Neznámé zařízení</translation>
<translation id="7669271284792375604">Útočníci na tomto webu by se mohli pokusit přimět vás k instalaci programů, které nepříznivě ovlivní procházení webu (například změní vaši domovskou stránku nebo na navštěvovaných stránkách budou zobrazovat další reklamy).</translation>
<translation id="7676643023259824263">Vyhledat text ve schránce (<ph name="TEXT" />)</translation>
-<translation id="7679176406634891508">Platforma a cloud</translation>
<translation id="7681101578153515023">Změnit vyhledávač</translation>
<translation id="7682287625158474539">Doprava</translation>
<translation id="7687186412095877299">Vyplní platební formuláře údaji pro uložené platební metody</translation>
@@ -1246,7 +1264,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="7723047071702270851">Úprava karty</translation>
<translation id="774634243536837715">Byl zablokován nebezpečný obsah.</translation>
<translation id="7752995774971033316">Nespravováno</translation>
-<translation id="7755287808199759310">Rodič ti jej může odblokovat.</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Připojení mohlo být zablokováno firewallem nebo antivirovým softwarem.</translation>
<translation id="7759163816903619567">Zobrazovaná doména:</translation>
@@ -1290,7 +1307,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="8004582292198964060">Prohlížeč</translation>
<translation id="8009225694047762179">Spravovat hesla</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Tato karta a její fakturační adresa se uloží. Budete ji moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}few{Tyto karty a jejich fakturační adresy se uloží. Budete je moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}many{Tyto karty a jejich fakturační adresy se uloží. Budete je moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}other{Tyto karty a jejich fakturační adresy se uloží. Budete je moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">V tuto chvíli se nám s vašimi rodiči nepodařilo spojit. Zkuste to prosím znovu.</translation>
<translation id="8025119109950072390">Útočníci na tomto webu vás mohou podvodem přimět k nebezpečnému chování, jako je instalace softwaru nebo vyzrazení osobních údajů (například hesel, telefonních čísel nebo platebních karet).</translation>
<translation id="8034522405403831421">Stránka je v jazyce <ph name="SOURCE_LANGUAGE" />. Chcete ji přeložit do jazyka <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pero</translation>
@@ -1301,6 +1317,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8041940743680923270">Použít výchozí globální hodnotu (Dotázat se)</translation>
<translation id="8042918947222776840">Vybrat způsob vyzvednutí</translation>
<translation id="8057711352706143257">Software <ph name="SOFTWARE_NAME" /> není nakonfigurován správně. Tento problém lze obvykle vyřešit odinstalováním softwaru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Od teď už nebudete muset zadávat bezpečnostní kód karty</translation>
<translation id="8066955247577885446">Lituji, něco se pokazilo.</translation>
<translation id="8074253406171541171">10x13 (obálka)</translation>
<translation id="8078141288243656252">Když je dokument otočený, nelze do něj přidávat značky a poznámky</translation>
@@ -1331,6 +1348,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8211406090763984747">Připojení je zabezpečené</translation>
<translation id="8218327578424803826">Přiřazené místo:</translation>
<translation id="8220146938470311105">C7/C6 (obálka)</translation>
+<translation id="8220639454292072926">Přehledy pro podniky</translation>
<translation id="8225771182978767009">Uživatel, který tento počítač nastavoval, se rozhodl tento web blokovat.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Otevřete stránku na nové anonymní kartě</translation>
@@ -1385,24 +1403,24 @@ Další podrobnosti:
<translation id="8508648098325802031">Ikona Vyhledávání</translation>
<translation id="8522552481199248698">Chrome vám může pomoci ochránit váš účet Google a změnit heslo.</translation>
<translation id="8543181531796978784">Můžete <ph name="BEGIN_ERROR_LINK" />nahlásit problém se zjištěným webem<ph name="END_ERROR_LINK" />. Pokud bezpečnostní rizika chápete, můžete <ph name="BEGIN_LINK" />tento nespolehlivý web navštívit<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Máte nějaké dotazy? Kontaktujte osobu, která dohlíží na váš profil.</translation>
<translation id="8553075262323480129">Překlad se nezdařil. Nepodařilo se rozpoznat jazyk stránky.</translation>
<translation id="8557066899867184262">Kód CVC je uveden na zadní straně karty.</translation>
<translation id="8559762987265718583">Soukromé připojení k doméně <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> nelze navázat, protože máte v zařízení nastaveno chybné datum a čas (<ph name="DATE_AND_TIME" />).</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> podezřelý web</translation>
<translation id="8564985650692024650">Pokud jste heslo organizace <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> použili na jiném webu, doporučujeme vám ho resetovat.</translation>
<translation id="8571890674111243710">Překlad stránky do jazyka: <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Přidat telefon
</translation>
-<translation id="859285277496340001">V certifikátu není uvedeno, jakým způsobem lze zkontrolovat, zda nebyl zrušen.</translation>
<translation id="860043288473659153">Jméno držitele karty</translation>
<translation id="861775596732816396">Velikost 4</translation>
-<translation id="8620436878122366504">Rodiče přístup dosud neschválili.</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Uložit tuto kartu do zařízení</translation>
<translation id="8626112503828625890">Ukládat fakturační údaje v účtu Google?</translation>
+<translation id="8647750283161643317">Obnovit u experimentů výchozí nastavení</translation>
<translation id="8663226718884576429">Shrnutí objednávky, <ph name="TOTAL_LABEL" />, další podrobnosti</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, odpověď, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Dostupné</translation>
<translation id="8703575177326907206">Vaše spojení se serverem <ph name="DOMAIN" /> není šifrované.</translation>
<translation id="8718314106902482036">Platba nebyla dokončena</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, návrh vyhledávacího dotazu</translation>
@@ -1413,6 +1431,7 @@ Další podrobnosti:
<translation id="8738058698779197622">Aby bylo možné navázat zabezpečené spojení, hodiny musejí být nastaveny správně. Důvodem je, že certifikáty, pomocí kterých se weby identifikují, platí pouze pro pevně daná období. Jelikož hodiny v zařízení nejsou nastaveny správně, prohlížeč Chromium tyto certifikáty nemůže ověřit.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Adresu DNS&lt;/abbr&gt; webu <ph name="HOST_NAME" /> nelze najít. Diagnostikování problému…</translation>
<translation id="874846938927089722">Přijímané kreditní a předplacené karty</translation>
+<translation id="874918643257405732">Přidat tuto kartu do záložek</translation>
<translation id="8759274551635299824">Platnost této karty vypršela</translation>
<translation id="8761567432415473239">Bezpečné prohlížení Google na webu <ph name="SITE" /> nedávno <ph name="BEGIN_LINK" />nalezlo škodlivé programy<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">Zařízení USB</translation>
@@ -1442,6 +1461,7 @@ Další podrobnosti:
<translation id="8938939909778640821">Přijímané kreditní a předplacené karty</translation>
<translation id="8943282376843390568">Limetková</translation>
<translation id="8957210676456822347">Autorizace captive portálu</translation>
+<translation id="8962950042226115166">Podezřelý web</translation>
<translation id="8968766641738584599">Uložit kartu</translation>
<translation id="8971063699422889582">Platnost certifikátu serveru vypršela.</translation>
<translation id="8975012916872825179">Zahrnuje informace jako telefonní čísla, e-mailové adresy a dodací adresy</translation>
@@ -1464,24 +1484,24 @@ Další podrobnosti:
<translation id="9035022520814077154">Chyba zabezpečení</translation>
<translation id="9038649477754266430">Používat službu předpovídání k rychlejšímu načítání stránek</translation>
<translation id="9039213469156557790">Tato stránka obsahuje ještě další nezabezpečené zdroje. Tyto zdroje budou během přenosu moci zobrazit jiní uživatelé a případní útočníci je mohou upravit a změnit tak chování stránky.</translation>
+<translation id="9044359186343685026">Použít Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Pokusili jste se přejít do domény <ph name="DOMAIN" />, ale server předložil certifikát, jehož platnost vypršela.</translation>
<translation id="9050666287014529139">Heslová fráze</translation>
<translation id="9065203028668620118">Upravit</translation>
<translation id="9065745800631924235">vyhledávání <ph name="TEXT" /> z historie</translation>
<translation id="9069693763241529744">Blokováno rozšířením</translation>
-<translation id="9076283476770535406">Může obsahovat materiály pouze pro dospělé</translation>
<translation id="9076630408993835509">Tento prohlížeč není spravován administrátorem ani jinou organizací. Aktivita na tomto zařízení může být spravována mimo Chrome. <ph name="BEGIN_LINK" />Další informace<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Jsou potřeba další informace</translation>
<translation id="9080712759204168376">Přehled objednávky</translation>
<translation id="9089260154716455634">Zásada Off-Hours:</translation>
<translation id="9095388113577226029">Další jazyky...</translation>
+<translation id="9098981495403789647">Administrátor ve vašem prohlížeči zapnul ochranu před hrozbami Chrome Enterprise. Ochrana před hrozbami Chrome Enterprise má přístup k některým vašim datům.</translation>
<translation id="9103872766612412690">Web <ph name="SITE" /> vaše informace běžně chrání šifrováním. Když se prohlížeč Chromium k webu <ph name="SITE" /> pokusil připojit tentokrát, web vrátil neobvyklé a nesprávné identifikační údaje. K tomuto problému může dojít, pokud se za web <ph name="SITE" /> pokouší vydávat nějaký útočník nebo pokud bylo připojení přerušeno přihlašovací obrazovkou sítě Wi-Fi. Vaše informace jsou i nadále v bezpečí, protože prohlížeč Chromium připojení přerušil dříve, než došlo k odeslání jakýchkoliv dat.</translation>
<translation id="9106062320799175032">Přidání fakturační adresy</translation>
<translation id="9114524666733003316">Ověřování karty...</translation>
<translation id="9128870381267983090">Připojit k síti</translation>
<translation id="9137013805542155359">Zobrazit originál</translation>
-<translation id="9137248913990643158">Chcete-li tuto aplikaci použít, přihlaste se do Chromu.</translation>
<translation id="9141013498910525015">Spravovat adresy</translation>
<translation id="9148088599418889305">Vybrat způsob dopravy</translation>
<translation id="9148507642005240123">&amp;Vrátit úpravy zpět</translation>
diff --git a/chromium/components/strings/components_strings_da.xtb b/chromium/components/strings/components_strings_da.xtb
index 238ab49da04..527a15c1e8c 100644
--- a/chromium/components/strings/components_strings_da.xtb
+++ b/chromium/components/strings/components_strings_da.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Tilføj navn på kort</translation>
<translation id="1089439967362294234">Skift adgangskode</translation>
+<translation id="1096545575934602868">Dette felt må ikke have mere end <ph name="MAX_ITEMS_LIMIT" /> poster. Alle yderligere poster kasseres.</translation>
<translation id="109743633954054152">Administrer adgangskoder i indstillingerne for Chrome</translation>
<translation id="1103523840287552314">Oversæt altid <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Hvis dette felt er markeret, gemmer Chrome en kopi af dit kort på denne enhed, så formularer hurtigere kan udfyldes fremover.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Få adgang til en <ph name="BEGIN_LINK" />cachelagret kopi<ph name="END_LINK" /> af <ph name="URL" /></translation>
<translation id="1156303062776767266">Du får vist en lokal eller delt fil</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> lukkede forbindelsen uventet.</translation>
+<translation id="115926840831309955">Tjek din kontrolkode, og prøv igen, eller opdater udløbsdatoen</translation>
<translation id="1161325031994447685">Genoprette forbindelse til Wi-Fi</translation>
<translation id="1165039591588034296">Fejl</translation>
<translation id="1175364870820465910">&amp;Udskriv...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Der er software på computeren, som forhindrer, at Chrome kan oprette en sikker forbindelse til nettet" (kun Windows-computere)</translation>
<translation id="1294154142200295408">Variationer i kommandolinjer</translation>
<translation id="129553762522093515">Senest lukkede</translation>
+<translation id="1298536327547837046">Malwarescanning</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Prøv at rydde dine cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Udfasede funktioner</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Søg efter billede i udklipsholderen</translation>
<translation id="1323433172918577554">Se flere</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">Venter på forbindelse…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">Det website, du netop forsøgte at gå til, ser ud til at være falsk. Svindlere efterligner nogle gange websites ved at lave små ændringer af webadressen, som er svære at se.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Denne side siger</translation>
<translation id="153384715582417236">Det var det hele indtil videre</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokumenterne er for store til at blive annoteret</translation>
-<translation id="1721312023322545264">Du skal have tilladelse fra <ph name="NAME" /> til at besøge dette website</translation>
<translation id="1721424275792716183">* Feltet skal udfyldes</translation>
<translation id="1727741090716970331">Tilføj et gyldigt kortnummer</translation>
<translation id="1728677426644403582">Du ser kilden for en webside</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Hvilke websites du besøger, og hvor lang tid du bruger på dem</translation>
<translation id="1826516787628120939">Kontrollerer</translation>
<translation id="1834321415901700177">Dette website indeholder skadelige programmer</translation>
+<translation id="1838374766361614909">Ryd søgning</translation>
<translation id="1839551713262164453">Validering af politikværdier mislykkedes med fejl</translation>
<translation id="1842969606798536927">Betal</translation>
<translation id="1871208020102129563">Proxy er indstillet til at bruge faste proxyservere, ikke webadresser til .pac-scripts.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Skjul liste</translation>
<translation id="1898423065542865115">Filtrering</translation>
<translation id="1914326953223720820">Udpakningstjeneste</translation>
+<translation id="1915697529809968049">Vil du bruge Touch ID i stedet for kontrolkoden?</translation>
<translation id="1916770123977586577">Genindlæs denne side for at anvende dine opdaterede indstillinger på dette website</translation>
<translation id="1919345977826869612">Annoncer</translation>
<translation id="1919367280705858090">Få hjælp til en specifik fejlmeddelelse</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Bogmærker fra <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Serialiseringsfejl</translation>
<translation id="1974060860693918893">Avanceret</translation>
+<translation id="1974883374937189061">Hjælp med at forbedre sikkerheden i Chrome ved at sende <ph name="BEGIN_WHITEPAPER_LINK" />webadresser på nogle af de sider, du besøger, begrænsede systemoplysninger og noget sideindhold<ph name="END_WHITEPAPER_LINK" /> til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Firmwareversion</translation>
<translation id="1981206234434200693">Ryd data fra Chromes browserhistorik</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{og 1 mere}one{og # mere}other{og # mere}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Angiv et gyldigt udløbsår</translation>
<translation id="2212735316055980242">Politikken blev ikke fundet</translation>
<translation id="2213606439339815911">Indlæg hentes...</translation>
+<translation id="2215727959747642672">Filredigering</translation>
<translation id="2218879909401188352">Hackere, der i øjeblikket er på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, kan installere farlige apps, som kan skade din enhed, føje skjulte gebyrer til din mobilregning eller stjæle dine personlige oplysninger. <ph name="BEGIN_LEARN_MORE_LINK" />Få flere oplysninger<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Der er ingen internetforbindelse</translation>
<translation id="2230458221926704099">Ret problemerne med din forbindelse ved hjælp af <ph name="BEGIN_LINK" />diagnoseappen<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Send nu</translation>
+<translation id="2248949050832152960">Brug WebAuthn</translation>
<translation id="225207911366869382">Denne værdi er forældet for denne politik.</translation>
<translation id="2257315177824333709">Kortet kan desværre ikke gemmes lige nu</translation>
<translation id="2262243747453050782">HTTP-fejl</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Ugyldig søgewebadresse.</translation>
<translation id="2482878487686419369">Notifikationer</translation>
<translation id="248348093745724435">Maskinpolitikker</translation>
-<translation id="2485387744899240041">Brugernavne for din enhed og browser</translation>
<translation id="2491120439723279231">Serverens certifikat indeholder fejl.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Værktøj til parsing af JSON-filer</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Gå tilbage</translation>
<translation id="2503184589641749290">Accepterede debetkort og forudbetalte kort</translation>
<translation id="2505268675989099013">Beskyt konto</translation>
+<translation id="2515335152965840738">IGNORER</translation>
<translation id="2515629240566999685">Tjekke signalet i dit område</translation>
<translation id="2523886232349826891">Gemmes kun på denne enhed</translation>
<translation id="2524461107774643265">Tilføj flere oplysninger</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Indsend</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Ingen}=1{1 adgangskode (til <ph name="DOMAIN_LIST" />)}=2{2 adgangskoder (til <ph name="DOMAIN_LIST" />)}one{# adgangskode (til <ph name="DOMAIN_LIST" />)}other{# adgangskoder (til <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Luk andre faner eller apps</translation>
-<translation id="267371737713284912">tryk på <ph name="MODIFIER_KEY_DESCRIPTION" /> for at fortryde</translation>
<translation id="2674170444375937751">Er du sikker på, at du vil slette disse sider fra din historik?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Forlad</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Værdien stemmer ikke overens med formatet.</translation>
<translation id="2705137772291741111">Den gemte (cachelagrede) kopi af dette website kunne ikke læses.</translation>
<translation id="2709516037105925701">AutoFyld</translation>
-<translation id="2712173769900027643">Spørg om tilladelse</translation>
<translation id="2713444072780614174">Hvid</translation>
<translation id="2720342946869265578">Tæt på</translation>
<translation id="2721148159707890343">Anmodning lykkedes</translation>
<translation id="2728127805433021124">Serverens certifikat er signeret ved hjælp af en svag signaturalgoritme.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Køre Diagnosticering af forbindelse<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Hvis du aktiverer disse funktioner, kan du miste browserdata eller
+ kompromittere din sikkerhed eller dit privatliv. Aktiverede funktioner gælder for alle
+ brugere i denne browser.</translation>
<translation id="2735043616039983645">Der er mere end én kilde med modstridende værdier for denne politik.</translation>
<translation id="2738330467931008676">Vælg afhentningsadresse</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Forbindelsen blev nulstillet.</translation>
<translation id="2788784517760473862">Accepterede kreditkort</translation>
<translation id="2792012897584536778">Administratorer for denne enhed har konfigureret sikkerhedscertifikater, som muligvis giver dem mulighed for at se indholdet af de websites, du besøger.</translation>
-<translation id="2794233252405721443">Websitet er blokeret</translation>
<translation id="2799020568854403057">Det website, du er på vej til, indeholder skadelige apps</translation>
<translation id="2799223571221894425">Genstart</translation>
<translation id="2803306138276472711">Google Beskyttet browsing <ph name="BEGIN_LINK" />registrerede malware<ph name="END_LINK" /> på <ph name="SITE" />. Websites, der normalt er sikre, bliver undertiden inficeret med malware.</translation>
+<translation id="2815364696811431560">FORLAD WEBSITET</translation>
<translation id="2824775600643448204">Adresse og søgelinje</translation>
<translation id="2826760142808435982">Forbindelsen er krypteret og godkendt ved hjælp af <ph name="CIPHER" />, og den anvender <ph name="KX" /> som primær udvekslingsmekanisme.</translation>
<translation id="2835170189407361413">Ryd formular</translation>
<translation id="2847118875340931228">Åbn inkognitovindue</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Du skal have tilladelse til at besøge dette website</translation>
<translation id="2856444702002559011">Brugere med ondsindede hensigter kan forsøge at stjæle dine oplysninger fra <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (f.eks. adgangskoder, beskeder eller kreditkort). <ph name="BEGIN_LEARN_MORE_LINK" />Få flere oplysninger<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Vil du gemme kortet?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Hvis denne indstilling er slået til, gemmer Chromium en kopi af dit kort på denne enhed for at gøre det hurtigere at udfylde formularer.</translation>
<translation id="2985398929374701810">Angiv en gyldig adresse</translation>
<translation id="2986368408720340940">Denne afhentningsmetode er ikke tilgængelig. Prøv en anden metode.</translation>
+<translation id="2987034854559945715">Der er ingen matchende funktioner</translation>
<translation id="2991174974383378012">Deling med websites</translation>
<translation id="2991571918955627853">Du kan ikke besøge <ph name="SITE" /> lige nu, da websitet bruger HSTS. Netværksfejl og angreb er normalt midlertidige, så siden vil sandsynligvis fungere senere.</translation>
<translation id="3005723025932146533">Vis gemt kopi</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Forkert politiktype</translation>
<translation id="3037605927509011580">Øv, surt!</translation>
<translation id="3041612393474885105">Certifikatoplysninger</translation>
+<translation id="3057676462092457419">DnsOverHttps-tilstanden <ph name="SECURE_DNS_MODE_SECURE" /> understøttes endnu ikke. Tilstanden er angivet som <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Tjeneste til programrettelse</translation>
<translation id="3064966200440839136">Du forlader inkognitotilstand for at betale via en ekstern applikation. Vil du fortsætte?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> på <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Annuller betaling</translation>
<translation id="3207960819495026254">Gemt som bogmærke</translation>
+<translation id="3209034400446768650">Siden kan opkræve betaling</translation>
<translation id="3225919329040284222">Serveren præsenterede et certifikat, der ikke svarer til de indbyggede forventninger. Disse forventninger medtages for bestemte websites med høj sikkerhed for at beskytte dig.</translation>
<translation id="3226128629678568754">Tryk på genindlæsningsknappen for at genindsende de data, der er nødvendige for at indlæse siden.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Versionsoplysninger om din enhed og browser</translation>
<translation id="323107829343500871">Angiv kontrolkoden for <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Registrer altid vigtigt indhold på dette website</translation>
-<translation id="3254409185687681395">Tilføj denne side som bogmærke</translation>
<translation id="3270847123878663523">&amp;Fortryd omarrangering</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Tilføj navn på kort</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Tilføj faktureringsadresse</translation>
<translation id="3324983252691184275">Højrød</translation>
<translation id="3338095232262050444">Sikker</translation>
-<translation id="3345135638360864351">Din anmodning om at få adgang til dette website kunne ikke sendes til <ph name="NAME" />. Prøv igen.</translation>
<translation id="3355823806454867987">Skift indstillinger for proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />gemmer ikke<ph name="END_EMPHASIS" /> følgende oplysninger:
<ph name="BEGIN_LIST" />
@@ -455,7 +465,7 @@
<translation id="3362968246557010467">Denne politik blev automatisk kopieret fra den udfasede politik <ph name="OLD_POLICY" />. Du bør bruge denne politik i stedet.</translation>
<translation id="3366477098757335611">Se kort</translation>
<translation id="3369192424181595722">Urfejl</translation>
-<translation id="337363190475750230">Fjernet</translation>
+<translation id="337363190475750230">Deprovisioneret</translation>
<translation id="3377188786107721145">Det opstod en fejl ved parsing af politik</translation>
<translation id="3380365263193509176">Ukendt fejl</translation>
<translation id="3380864720620200369">Klient-id:</translation>
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Skjul avanceret</translation>
<translation id="3467763166455606212">Kortindehavers navn skal angives</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> er i øjeblikket åben. Tryk på tabulatortasten og derefter på Enter for at skifte til den åbne fane</translation>
-<translation id="3479539252931486093">Var dette uventet? <ph name="BEGIN_LINK" />Giv os gerne feedback<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ikke nu</translation>
<translation id="3484560055331845446">Du kan miste adgangen til din Google-konto. Chrome anbefaler, at du skifter din adgangskode nu. Du bliver bedt om at logge ind.</translation>
<translation id="3495081129428749620">Find på side
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Vi kan ikke få fat i din forælder på nuværende tidspunkt. Prøv igen.</translation>
<translation id="3512163584740124171">Politikken ignoreres, da en anden politik fra samme politikgruppe har højere prioritet.</translation>
<translation id="3528171143076753409">Serverens certifikat er ikke troværdigt.</translation>
<translation id="3528485271872257980">Mørkebrun</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Mindst 1 element på synkroniserede enheder}=1{1 element (og flere på synkroniserede enheder)}one{# element (og flere på synkroniserede enheder)}other{# elementer (og flere på synkroniserede enheder)}}</translation>
<translation id="3539171420378717834">Gem en kopi af dette kort på denne enhed</translation>
-<translation id="3556433843310711081">Din administrator kan fjerne blokeringen for dig</translation>
<translation id="3566021033012934673">Din forbindelse er ikke privat</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">En integreret side på <ph name="SITE" /> siger</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Åbn siden i et nyt inkognitovindue (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Nedbrud registreret <ph name="CRASH_TIME" />, uploadet <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Certifikatoplysninger</translation>
+<translation id="3701427423622901115">Nulstillingen blev anerkendt.</translation>
<translation id="3704162925118123524">Det netværk, du bruger, kan kræve, at du går til netværkets loginside.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Indlæser...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Brugere med ondsindede hensigter <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan narre dig til at gøre noget farligt såsom at installere software eller afsløre dine personlige oplysninger (f.eks. adgangskoder, telefonnumre eller kreditkort). <ph name="BEGIN_LEARN_MORE_LINK" />Få flere oplysninger<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Oversættelsen mislykkedes på grund af en serverfejl.</translation>
<translation id="3759461132968374835">Du har ingen nyligt rapporterede nedbrud. Nedbrud, der opstod, mens rapportering om nedbrud var deaktiveret, vises ikke her.</translation>
+<translation id="3760561303380396507">Vil du bruge Windows Hello i stedet for kontrolkoden?</translation>
<translation id="3761718714832595332">Skjul status</translation>
<translation id="3765032636089507299">Siden Beskyttet browsing er under opførelse.</translation>
<translation id="3778403066972421603">Vil du gemme dette kort på din Google-konto og på denne enhed?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Størrelse 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Skadeligt indhold blokeres.</translation>
+<translation id="3808375843007691220">Advarsel! Testfunktioner forude.</translation>
<translation id="3810973564298564668">Valgmuligheder</translation>
<translation id="382518646247711829">Hvis du bruger en proxyserver...</translation>
<translation id="3828924085048779000">Tomme adgangssætninger er ikke tilladt.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Opdater dato og tid</translation>
<translation id="3884278016824448484">Modstridende enheds-id</translation>
<translation id="3885155851504623709">Amt</translation>
-<translation id="3886446263141354045">Din anmodning om adgang til dette website er blevet sendt til <ph name="NAME" />.</translation>
<translation id="3890664840433101773">Tilføj mail</translation>
<translation id="3901925938762663762">Kortet er udløbet</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Vil du bruge WebAuthn i stedet for kontrolkoden?</translation>
<translation id="3946209740501886391">Spørg altid på dette website</translation>
<translation id="3949571496842715403">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da sikkerhedscertifikatet ikke angiver alternative navne på emner. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
<translation id="3949601375789751990">Din browserhistorik vises her</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ingen}=1{1 website }one{# website }other{# websites }}</translation>
<translation id="397105322502079400">Beregner...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> er blokeret</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> har aktiveret Chrome Enterprise Threat Protection i din browser. Chrome Enterprise Threat Protection har adgang til nogle af dine data.</translation>
<translation id="3987940399970879459">Mindre end 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 webside tæt på}one{# webside tæt på}other{# websider tæt på}}</translation>
<translation id="4030383055268325496">&amp;Fortryd tilføjelse</translation>
<translation id="4032320456957708163">Din browser administreres af <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Linket, du åbnede, fører til et website, som du ikke normalt besøger. Det forsøger muligvis at forvirre dig.</translation>
<translation id="4058922952496707368">Nøgle "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Tilføj gyldig adresse</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Enhedens serienummer er ugyldigt</translation>
<translation id="410351446219883937">Autoplay</translation>
<translation id="4103763322291513355">Gå til &lt;strong&gt;chrome://policy&lt;/strong&gt; for at se listen over sortlistede webadresser og andre politikker, din systemadministrator har igangsat.</translation>
+<translation id="4108231218301530806">Brug fingeraftryk til at bekræfte dette kort næste gang.</translation>
<translation id="4110652170750985508">Gennemgå din betaling</translation>
<translation id="4112140312785995938">Spol tilbage</translation>
<translation id="4116663294526079822">Tillad altid på dette website</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Ugyldig verifikationssignatur</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> element mere}one{<ph name="ITEM_COUNT" /> element mere}other{<ph name="ITEM_COUNT" /> elementer mere}}</translation>
+<translation id="4176463684765177261">Deaktiveret</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Du kan betale hurtigere næste gang ved at føje dit kort og din faktureringsadresse til din Google-konto.</translation>
<translation id="4196861286325780578">&amp;Annuller fortryd flytning</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Nulstil adgangskoden</translation>
<translation id="4279811152705618813">Din <ph name="DEVICE_TYPE" /> administreres af <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Kortet er gemt på din Google-konto}one{Kortet er gemt på din Google-konto}other{Kortene er gemt på din Google-konto}}</translation>
+<translation id="428847186335018806">Scan filer, du downloader eller uploader i Chrome.</translation>
<translation id="42981349822642051">Udvid</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Skift</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Brug af en proxy er deaktiveret, men en eksplicit proxykonfiguration er angivet.</translation>
<translation id="445100540951337728">Accepterede debetkort</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> Mistænkelig adfærd</translation>
<translation id="4466881336512663640">Du mister eventuelle formularændringer. Er du sikker på, at du vil fortsætte?</translation>
<translation id="4477350412780666475">Næste nummer</translation>
<translation id="4482953324121162758">Dette website kan ikke oversættes.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Fortryd sletning</translation>
<translation id="4597348597567598915">Størrelse 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Søgefunktioner</translation>
<translation id="4646534391647090355">Før mig dertil nu</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da sikkerhedscertifikatet indeholder fejl. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Din forbindelse blev afbrudt</translation>
-<translation id="471880041731876836">Du har ikke tilladelse til at besøge dette website</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Køre Windows Netværksdiagnosticering<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Opdater politikker</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Tilpas til siden</translation>
<translation id="4850886885716139402">Vis</translation>
<translation id="4854362297993841467">Denne leveringsmetode er ikke tilgængelig. Prøv en anden metode.</translation>
-<translation id="4858792381671956233">Du har spurgt dine forældre, om det er i orden at besøge dette website.</translation>
<translation id="4864052566555297930">Sikkerhedstip:</translation>
<translation id="4876188919622883022">Enkel visning</translation>
<translation id="4876305945144899064">Intet brugernavn</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Genaktiver advarsler</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Se alle</translation>
+<translation id="4989542687859782284">Ikke tilgængelige</translation>
<translation id="4989809363548539747">Dette plugin understøttes ikke</translation>
+<translation id="4995216769782533993">Bekræft sikkerhedskoden for at dele dine kortoplysninger med dette website</translation>
<translation id="5002932099480077015">Hvis denne indstilling er slået til, gemmer Chrome en kopi af dit kort på denne enhed for at gøre det hurtigere at udfylde formularer.</translation>
<translation id="5015510746216210676">Maskinnavn:</translation>
<translation id="5017554619425969104">Tekst, du har kopieret</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Bekræft dit kort</translation>
<translation id="5135404736266831032">Administrer adresser...</translation>
<translation id="5138227688689900538">Vis færre</translation>
<translation id="5141240743006678641">Krypter synkroniserede adgangskoder med dine Google-loginoplysninger</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Skyen</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funktioner, der gælder for hele systemet, kan kun angives af ejeren: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Advarsel! Denne politik blev ikke flettet som angivet i politikken PolicyDictionaryMultipleSourceMergeList, da den ikke er en del af de ordbogspolitikker, der kan flettes.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Afslut</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Der kunne ikke gemmes indstillinger for politik</translation>
<translation id="5371425731340848620">Opdater kortet</translation>
<translation id="5377026284221673050">"Dit ur er bagud" eller "Dit ur er forud" eller "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Denne side forsøger muligvis at narre dig, stjæle personlige oplysninger eller beskadige din enhed. Vær forsigtig, når du angiver personlige oplysninger eller åbner downloadede filer.</translation>
<translation id="5384855140246857529">Log ind, og aktivér synkronisering for at bruge dine kort på alle enheder.</translation>
<translation id="5386426401304769735">Certifikatkæden for dette website indeholder et certifikat, der er signeret med SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Ugyldig</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> anden}one{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> anden}other{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> andre}}</translation>
<translation id="5470861586879999274">&amp;Annuller fortryd redigering</translation>
+<translation id="5473728911100096288">Hvis du aktiverer disse funktioner, får du adgang til udfasede funktioner,
+ der ikke vil være tilgængelige i fremtidige versioner.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Dette indhold forsøger muligvis at installere farlig software på din enhed, der kan stjæle eller slette dine oplysninger. <ph name="BEGIN_LINK" />Vis alligevel<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Tilføj gyldig adresse</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Beskyt konto</translation>
<translation id="5571083550517324815">Der kan ikke afhentes på denne adresse. Vælg en anden adresse.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 i brug}one{# i brug}other{# i brug}})</translation>
-<translation id="5572851009514199876">Start og log ind på Chrome, så Chrome kan kontrollere, om du har adgang til dette website.</translation>
<translation id="5580958916614886209">Kontrollér, om udløbsmåneden er korrekt, og prøv igen.</translation>
<translation id="5586446728396275693">Der er ikke nogen gemte adresser</translation>
<translation id="5595485650161345191">Rediger adresse</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Administration er ikke understøttet</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Dette website er muligvis falsk eller ondsindet. Chrome anbefaler, at du forlader websitet med det samme.</translation>
<translation id="5610142619324316209">Kontrollere forbindelsen</translation>
<translation id="5610807607761827392">Du kan administrere kort og adresser i <ph name="BEGIN_LINK" />Indstillinger<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> omdirigerede dig for mange gange.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Aktuel bruger</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome anbefaler, at du nulstiller din adgangskode, hvis du har brugt den på andre websites.</translation>
-<translation id="5732392974455271431">Dine forældre kan fjerne blokeringen for dig</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Gem kortet på din Google-konto}one{Gem kortet på din Google-konto}other{Gem kortene på din Google-konto}}</translation>
<translation id="5763042198335101085">Angiv en gyldig mailadresse</translation>
<translation id="5765072501007116331">Vælg en adresse for at se leveringsmetoder og -krav</translation>
<translation id="5778550464785688721">Fuld kontrol over MIDI</translation>
+<translation id="5781136890105823427">Eksperimentet er aktiveret</translation>
<translation id="578305955206182703">Ravgul</translation>
<translation id="57838592816432529">Slå lyden fra</translation>
<translation id="5784606427469807560">Der opstod et problem under bekræftelsen af dit kort. Kontrollér, at du har forbindelse til internettet, og prøv igen.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Fra</translation>
<translation id="5863847714970149516">Siden forude kan forsøge at opkræve dig penge</translation>
<translation id="5866257070973731571">Tilføj telefonnummer</translation>
+<translation id="5866898949289125849">Du kigger på en side for udviklerværktøjer</translation>
<translation id="5869405914158311789">Der kan ikke oprettes forbindelse til dette website</translation>
<translation id="5869522115854928033">Gemte adgangskoder</translation>
<translation id="5887400589839399685">Kortet er gemt</translation>
<translation id="5893752035575986141">Kreditkort accepteres.</translation>
+<translation id="5895138241574237353">Genstart</translation>
<translation id="5901630391730855834">Gul</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkroniseret)</translation>
<translation id="5916664084637901428">Til</translation>
+<translation id="59174027418879706">Aktiveret</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Vil du gemme kortet på din Google-konto?</translation>
<translation id="5922853866070715753">Næsten færdig</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Vil du bruge kortene på alle dine enheder?</translation>
<translation id="6059925163896151826">USB-enheder</translation>
+<translation id="6060009363608157444">Ugyldig DnsOverHttps-tilstand.</translation>
<translation id="6080696365213338172">Du har opnår adgang til indhold vha. et administratorcertifikat. De data, du angiver til <ph name="DOMAIN" />, kan indhentes af din administrator.</translation>
<translation id="6094273045989040137">Annoter</translation>
<translation id="610911394827799129">Din Google-konto kan have andre former for browserhistorik på <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Rediger bogmærke</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Angiv udløbsdatoen og kontrolkoden for <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Du har spurgt en af dine forældre, om det er i orden, at du besøger dette website.</translation>
<translation id="6415778972515849510">Chromium kan hjælpe dig med at beskytte din Google-konto og ændre din adgangskode.</translation>
-<translation id="6417515091412812850">Kan ikke kontrollere, om certifikatet er tilbagekaldt.</translation>
<translation id="6431585503458005759">Gem ikke</translation>
<translation id="6433490469411711332">Rediger kontaktoplysninger</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> nægtede at oprette forbindelse.</translation>
<translation id="6434309073475700221">Kasser</translation>
+<translation id="6435221585574090192">Del data om sikkerhedshændelser, som rapporteres af Chrome Enterprise Threat Protection, med din administrator. Disse data kan indeholde webadresser, filnavne og -metadata, brugernavnet for din enhed samt dit Chrome-brugernavn.</translation>
<translation id="6440503408713884761">Ignoreret</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Tilføj flere oplysninger</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Administrer adgangskoder...</translation>
<translation id="647261751007945333">Enhedspolitikker</translation>
<translation id="6476284679642588870">Administrer betalingsmetoder</translation>
-<translation id="6477321094435799029">Chrome registrerede usædvanlig kode på denne side og blokerede den for at beskytte dine personlige oplysninger (f.eks. adgangskoder, telefonnumre eller kreditkort).</translation>
<translation id="6489534406876378309">Start upload af nedbrud</translation>
<translation id="6499038740797743453">Vil du nulstille adgangskoden?</translation>
<translation id="6507833130742554667">Betalingskort accepteres.</translation>
<translation id="650855688985305916">Ja, gem</translation>
<translation id="6508722015517270189">Genstart Chrome</translation>
<translation id="6517596291481585650">Advarsel! Denne politik blev ikke flettet som angivet i politikken, da den ikke er en liste.</translation>
+<translation id="6518133107902771759">Bekræft</translation>
<translation id="6521745193039995384">Ikke aktiv</translation>
<translation id="6529602333819889595">&amp;Annuller fortryd slet</translation>
<translation id="6534179046333460208">Forslag til Fysisk web</translation>
<translation id="6545864417968258051">Bluetooth-scanning</translation>
<translation id="6554795675067793129">Din konto administreres af <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Gør det igen</translation>
-<translation id="6563469144985748109">Din administrator har ikke godkendt det endnu</translation>
<translation id="6569060085658103619">Du ser en udvidelsesside</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Lys pink</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Ryd</translation>
<translation id="6644283850729428850">Denne politik er forældet.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Ingen}=1{Fra 1 website (du logges ikke ud af din Google-konto)}one{Fra # website (du logges ikke ud af din Google-konto)}other{Fra # websites (du logges ikke ud af din Google-konto)}}</translation>
+<translation id="6652101503459149953">Brug Windows Hello</translation>
<translation id="6657585470893396449">Adgangskode</translation>
<translation id="6670613747977017428">Gå tilbage i sikkerhed</translation>
<translation id="6671697161687535275">Vil du fjerne formularforslag fra Chromium?</translation>
<translation id="6685834062052613830">Log ud, og fuldfør konfigurationen</translation>
<translation id="6689271823431384964">Chrome tilbyder at gemme dine kort på din Google-konto, fordi du er logget ind. Du kan ændre dette i indstillingerne. Kortindehaverens navn hentes fra din konto.</translation>
+<translation id="6707256370811247129">Scan indholdet af cachen og de filer, som du downloader eller uploader i Chrome.</translation>
<translation id="6710213216561001401">Forrige</translation>
<translation id="6710594484020273272">&lt;Indtast søgeterm&gt;</translation>
<translation id="671076103358959139">Tilmeldingstoken:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Dine data blev krypteret med din <ph name="BEGIN_LINK" />adgangssætning til synkronisering<ph name="END_LINK" /> <ph name="TIME" />. Indtast adgangssætningen for at starte synkroniseringen.</translation>
<translation id="674375294223700098">Ukendt fejl i servercertifikatet.</translation>
<translation id="6744009308914054259">Mens du venter på en forbindelse, kan du gå til Downloads for at læse artikler offline.</translation>
+<translation id="6747611005629681221">Advarsel! Funktionerne her vil blive udfaset.</translation>
<translation id="6753269504797312559">Politikkens værdi</translation>
<translation id="6757797048963528358">Din enhed gik i dvale.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Din forælder har ikke godkendt det endnu</translation>
<translation id="67862343314499040">Violet</translation>
<translation id="6786747875388722282">Udvidelser</translation>
<translation id="6790428901817661496">Afspil</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Skal udfyldes</translation>
<translation id="6810899417690483278">Tilpasnings-id</translation>
<translation id="6825578344716086703">Du forsøgte at få fat i <ph name="DOMAIN" />, men serveren præsenterede et certifikat, der er signeret med en svag signaturalgoritme (f.eks. SHA-1). Det betyder, at sikkerhedsoplysningerne fra serveren kan være forfalskede, og at serveren muligvis ikke er den server, som du forventede (du kommunikerer muligvis med en person med ondsindede hensigter).</translation>
+<translation id="6826370046007623921">Forebyggelse af datatab</translation>
<translation id="6831043979455480757">Oversæt</translation>
<translation id="6839929833149231406">Område</translation>
<translation id="6852204201400771460">Vil du genindlæse appen?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Politikniveauet understøttes ikke.</translation>
<translation id="6895330447102777224">Dit kort er bekræftet</translation>
<translation id="6897140037006041989">Brugeragent</translation>
-<translation id="6903319715792422884">Hjælp med at forbedre Beskyttet browsing ved at sende nogle <ph name="BEGIN_WHITEPAPER_LINK" />systemoplysninger og noget sideindhold<ph name="END_WHITEPAPER_LINK" /> til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Bruger:</translation>
<translation id="6934672428414710184">Dette navn er fra din Google-konto</translation>
<translation id="6944692733090228304">Du indtastede din adgangskode på et website, der ikke administreres af <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Du kan beskytte din konto ved at undgå at bruge din adgangskode i andre apps og på andre websites.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> anden}one{<ph name="PAYMENT_METHOD_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> anden}other{<ph name="PAYMENT_METHOD_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> andre}}</translation>
<translation id="7153618581592392745">Lavendelblå</translation>
<translation id="717330890047184534">Gaia-id:</translation>
+<translation id="7174545416324379297">Flettet</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> anden}one{<ph name="SHIPPING_OPTION_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> anden}other{<ph name="SHIPPING_OPTION_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> andre}}</translation>
<translation id="7177397715882417099">Den server, du er på vej til, <ph name="ORIGIN" />, har anmodet om, at
der anvendes en sikkerhedspolitik for alle anmodninger, der sendes til den. I stedet for at
@@ -1166,6 +1187,7 @@ Yderligere oplysninger:
<translation id="7320336641823683070">Hjælp til at oprette forbindelse</translation>
<translation id="733354035281974745">Tilsidesættelse af enhedslokal konto</translation>
<translation id="7334320624316649418">&amp;Annuller fortryd omarrangering</translation>
+<translation id="7337706099755338005">Ikke tilgængelig på din platform.</translation>
<translation id="733923710415886693">Servercertifikatet blev ikke fremvist via Certifikatsgennemsigtighed.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Er tilknyttet:</translation>
@@ -1197,7 +1219,6 @@ Yderligere oplysninger:
<translation id="7440140511386898319">Udforsk, mens du er offline</translation>
<translation id="7441627299479586546">Forkert emne for politik</translation>
<translation id="7442725080345379071">Lys orange</translation>
-<translation id="7444046173054089907">Dette website er blokeret</translation>
<translation id="7445762425076701745">Identiteten på den server, som du er tilknyttet, kan ikke bekræftes. Du er tilknyttet en server via et navn, der kun er gyldigt i dit netværk, og som en ekstern certifikatautoritet derfor ikke har mulighed for at bekræfte ejerskabet på. Da enkelte certifikatautoriteter alligevel udsteder certifikater for disse navne, kan vi på ingen måde sikre, at du er tilknyttet det tilsigtede website og ikke til en forbryder.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Få flere oplysninger<ph name="END_LINK" /> om dette problem.</translation>
<translation id="7455133967321480974">Brug global standard (bloker)</translation>
@@ -1219,9 +1240,9 @@ Yderligere oplysninger:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Når du har bekræftet, deles dine kortoplysninger med dette website.</translation>
<translation id="7542995811387359312">Automatisk udfyldning af kreditkort er deaktiveret, fordi formularen ikke bruger en sikker forbindelse.</translation>
-<translation id="7543525346216957623">Spørg en af dine forældre</translation>
<translation id="7548892272833184391">Ret forbindelsesfejl</translation>
<translation id="7549584377607005141">Denne webside kræver data, du tidligere har indtastet, før den kan vises korrekt. Du kan sende disse data igen, men hvis du gør dette, gentager du enhver handling, som denne side tidligere har foretaget.</translation>
+<translation id="7550637293666041147">Brugernavnet for din enhed og dit Chrome-brugernavn</translation>
<translation id="7552846755917812628">Prøv de følgende tips:</translation>
<translation id="7554791636758816595">Ny fane</translation>
<translation id="7564049878696755256">Du kan miste adgangen til din <ph name="ORG_NAME" />-konto eller udsættes for identitetstyveri. Chrome anbefaler, at du skifter din adgangskode nu.</translation>
@@ -1236,6 +1257,7 @@ Yderligere oplysninger:
<translation id="7610193165460212391">Værdien er uden for intervallet <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Udløbsdato: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Du har allerede data, der er krypteret med en anden version af adgangskoden til din Google-konto. Angiv adgangskoden i feltet nedenfor.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Effektivitetsdata og nedbrudsrapporter</translation>
<translation id="7637571805876720304">Vil du fjerne kreditkortet fra Chromium?</translation>
<translation id="7638605456503525968">Serieporte</translation>
@@ -1248,7 +1270,6 @@ Yderligere oplysninger:
<translation id="7668654391829183341">Ukendt enhed</translation>
<translation id="7669271284792375604">Hackere på dette website kan forsøge at narre dig til at installere programmer, der skader din browseroplevelse (f.eks. ved at ændre din startside eller vise flere annoncer på de websites, du besøger).</translation>
<translation id="7676643023259824263">Søg efter tekst i udklipsholderen, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform og Cloud</translation>
<translation id="7681101578153515023">Skift søgemaskine</translation>
<translation id="7682287625158474539">Forsendelse</translation>
<translation id="7687186412095877299">Udfylder betalingsformularer med dine gemte betalingsmetoder</translation>
@@ -1263,7 +1284,6 @@ Yderligere oplysninger:
<translation id="7723047071702270851">Rediger kort</translation>
<translation id="774634243536837715">Farligt indhold er blokeret.</translation>
<translation id="7752995774971033316">Administreres ikke</translation>
-<translation id="7755287808199759310">Din forælder kan fjerne blokeringen for dig</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Firewall- eller antivirussoftware kan have blokeret forbindelsen.</translation>
<translation id="7759163816903619567">Vist domæne:</translation>
@@ -1307,7 +1327,6 @@ Yderligere oplysninger:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Administrer adgangskoder</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Kortet og faktureringsadressen gemmes. Du kan bruge dem, når du er logget ind på <ph name="USER_EMAIL" />.}one{Kortet og faktureringsadressen gemmes. Du kan bruge dem, når du er logget ind på <ph name="USER_EMAIL" />.}other{Kortene og faktureringsadresserne gemmes. Du kan bruge dem, når du er logget ind på <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Vi kan ikke få kontakt til dine forældre på nuværende tidspunkt. Prøv igen.</translation>
<translation id="8025119109950072390">Hackere på dette website kan narre dig til at gøre noget farligt, såsom at installere software eller afsløre dine personlige oplysninger (f.eks. adgangskoder, telefonnumre eller kreditkort).</translation>
<translation id="8034522405403831421">Denne side er på <ph name="SOURCE_LANGUAGE" />. Vil du oversætte den til <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pen</translation>
@@ -1318,6 +1337,7 @@ Yderligere oplysninger:
<translation id="8041940743680923270">Brug global standard (spørg)</translation>
<translation id="8042918947222776840">Vælg afhentningsmetode</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" er ikke konfigureret korrekt. Problemet kan normalt løses ved at afinstallere "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Du behøver ikke længere at angive en sikkerhedskode til kortet</translation>
<translation id="8066955247577885446">Der opstod en fejl.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Der kan ikke annoteres ved rotering</translation>
@@ -1348,6 +1368,7 @@ Yderligere oplysninger:
<translation id="8211406090763984747">Forbindelsen er sikker</translation>
<translation id="8218327578424803826">Tildelt placering:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Rapportering til arbejdsbrug</translation>
<translation id="8225771182978767009">Den person, der har konfigureret denne computer, har valgt at blokere dette website.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Åbn siden på en ny inkognitofane</translation>
@@ -1402,24 +1423,24 @@ Yderligere oplysninger:
<translation id="8508648098325802031">Søgeikon</translation>
<translation id="8522552481199248698">Chrome kan hjælpe dig med at beskytte din Google-konto og ændre din adgangskode.</translation>
<translation id="8543181531796978784">Du kan <ph name="BEGIN_ERROR_LINK" />rapportere et registreringsproblem<ph name="END_ERROR_LINK" /> eller, hvis du forstår den sikkerhedsrisiko, du udsætter dig for, <ph name="BEGIN_LINK" />kan du gå til dette usikre website<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Har du spørgsmål? Kontakt din profiladministrator.</translation>
<translation id="8553075262323480129">Oversættelsen mislykkedes, fordi sidens sprog ikke kunne fastslås.</translation>
<translation id="8557066899867184262">Kontrolkoden findes på bagsiden af kortet.</translation>
<translation id="8559762987265718583">Der kan ikke oprettes en privat forbindelse til <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, da tid og dato (<ph name="DATE_AND_TIME" />) på din enhed er forkerte.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> Mistænkeligt website</translation>
<translation id="8564985650692024650">Chromium anbefaler, at du nulstiller din adgangskode til <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, hvis du har brugt den på andre websites.</translation>
<translation id="8571890674111243710">Oversætter siden til <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Tilføj tlf.nr.
</translation>
-<translation id="859285277496340001">Certifikatet angiver ikke en mekanisme, der kontrollerer, om den har været tilbagekaldt.</translation>
<translation id="860043288473659153">Kortholderens navn</translation>
<translation id="861775596732816396">Størrelse 4</translation>
-<translation id="8620436878122366504">Dine forældre har ikke godkendt det endnu</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Gem dette kort på denne enhed</translation>
<translation id="8626112503828625890">Skal faktureringsoplysningerne gemmes på din Google-konto?</translation>
+<translation id="8647750283161643317">Nulstil alle til standard</translation>
<translation id="8663226718884576429">Ordreoversigt, <ph name="TOTAL_LABEL" />, flere oplysninger</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, svar, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Tilgængelig</translation>
<translation id="8703575177326907206">Din forbindelse til <ph name="DOMAIN" /> er ikke krypteret.</translation>
<translation id="8718314106902482036">Betalingen blev ikke fuldført</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, søgeforslag</translation>
@@ -1430,6 +1451,7 @@ Yderligere oplysninger:
<translation id="8738058698779197622">For at kunne oprette en sikker forbindelse skal dit ur være indstillet korrekt. Det er vigtigt, da de certifikater, som websites bruger til at identificere sig selv, kun er gyldige i bestemte tidsperioder. Da uret på din enhed går forkert, kan Chromium ikke bekræfte disse certifikater.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;DNS-adressen&lt;/abbr&gt; for <ph name="HOST_NAME" /> blev ikke fundet. Diagnosticerer problemet.</translation>
<translation id="874846938927089722">Accepterede kreditkort og forudbetalte kort</translation>
+<translation id="874918643257405732">Tilføj denne fane som bogmærke</translation>
<translation id="8759274551635299824">Kortet er udløbet</translation>
<translation id="8761567432415473239">Beskyttet browsing i Google har for nylig <ph name="BEGIN_LINK" />fundet skadelige programmer<ph name="END_LINK" /> på <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB-enhed</translation>
@@ -1459,6 +1481,7 @@ Yderligere oplysninger:
<translation id="8938939909778640821">Accepterede betalingskort</translation>
<translation id="8943282376843390568">Limegrøn</translation>
<translation id="8957210676456822347">Godkendelse af captive portal</translation>
+<translation id="8962950042226115166">Mistænkeligt website</translation>
<translation id="8968766641738584599">Gem kort</translation>
<translation id="8971063699422889582">Serverens certifikat er udløbet.</translation>
<translation id="8975012916872825179">Omfatter oplysninger såsom telefonnumre, mailadresser og leveringsadresser</translation>
@@ -1481,24 +1504,24 @@ Yderligere oplysninger:
<translation id="9035022520814077154">Sikkerhedsfejl</translation>
<translation id="9038649477754266430">Brug en forudsigelsestjeneste til hurtigere sideindlæsning</translation>
<translation id="9039213469156557790">Desuden indeholder denne side andre ressourcer, som ikke er sikre. Disse ressourcer kan ses af andre under overførslen og kan ændres af en hacker, så siden opfører sig anderledes.</translation>
+<translation id="9044359186343685026">Brug Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Du har forsøgt at nå <ph name="DOMAIN" />, men serveren præsenterede et ugyldigt certifikat.</translation>
<translation id="9050666287014529139">Adgangssætning</translation>
<translation id="9065203028668620118">Rediger</translation>
<translation id="9065745800631924235">Søgningen <ph name="TEXT" /> i historikken</translation>
<translation id="9069693763241529744">Blokeret af en udvidelse</translation>
-<translation id="9076283476770535406">Der er muligvis indhold for voksne på websitet</translation>
<translation id="9076630408993835509">Denne browser administreres ikke af en virksomhed eller en anden organisation. Aktivitet på denne enhed administreres muligvis uden for Chrome. <ph name="BEGIN_LINK" />Få flere oplysninger<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Flere oplysninger kræves</translation>
<translation id="9080712759204168376">Bestillingsoversigt</translation>
<translation id="9089260154716455634">Politik uden for åbningstiden:</translation>
<translation id="9095388113577226029">Flere sprog...</translation>
+<translation id="9098981495403789647">Din administrator har aktiveret Chrome Enterprise Threat Protection i din browser. Chrome Enterprise Threat Protection har adgang til nogle af dine data.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> bruger normalt kryptering til at beskytte dine oplysninger. Da Chromium forsøgte at oprette forbindelse til <ph name="SITE" /> denne gang, returnerede websitet usædvanlige og forkerte loginoplysninger. Dette kan skyldes, at en hacker forsøger at udgive sig for at være <ph name="SITE" />, eller at en Wi-Fi-loginskærm har forstyrret forbindelsen. Dine oplysninger er stadig sikre, idet Chromium afbrød forbindelsen, inden der blev udvekslet data.</translation>
<translation id="9106062320799175032">Tilføj faktureringsadresse</translation>
<translation id="9114524666733003316">Bekræfter kort...</translation>
<translation id="9128870381267983090">Opret forbindelse til netværk</translation>
<translation id="9137013805542155359">Vis oprindelig</translation>
-<translation id="9137248913990643158">Start og log ind på Chrome, inden du bruger denne app.</translation>
<translation id="9141013498910525015">Administrer adresser</translation>
<translation id="9148088599418889305">Vælg forsendelsesmetode</translation>
<translation id="9148507642005240123">&amp;Fortryd redigering</translation>
diff --git a/chromium/components/strings/components_strings_de.xtb b/chromium/components/strings/components_strings_de.xtb
index 12c055ae34a..8ffc2af2805 100644
--- a/chromium/components/strings/components_strings_de.xtb
+++ b/chromium/components/strings/components_strings_de.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Angabe für "Name auf der Karte" hinzufügen</translation>
<translation id="1089439967362294234">Passwort ändern</translation>
+<translation id="1096545575934602868">Dieses Feld sollte nicht mehr als <ph name="MAX_ITEMS_LIMIT" /> Einträge enthalten. Alle weiteren werden verworfen.</translation>
<translation id="109743633954054152">Passwörter in den Chrome-Einstellungen verwalten</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> immer übersetzen</translation>
<translation id="1107591249535594099">Bei Aktivierung speichert Chrome eine Kopie Ihrer Karte auf diesem Gerät, damit Formulare schneller ausgefüllt werden können.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Rufen Sie eine <ph name="BEGIN_LINK" />im Cache gespeicherte Kopie<ph name="END_LINK" /> von <ph name="URL" /> auf.</translation>
<translation id="1156303062776767266">Sie sehen sich eine lokale oder freigegebene Datei an</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> hat die Verbindung unerwartet geschlossen.</translation>
+<translation id="115926840831309955">Prüfen Sie Ihren CVC und versuchen Sie es noch einmal oder ändern Sie das Ablaufdatum</translation>
<translation id="1161325031994447685">WLAN-Verbindung erneut herstellen</translation>
<translation id="1165039591588034296">Fehler</translation>
<translation id="1175364870820465910">&amp;Drucken...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Software auf Ihrem Computer verhindert, dass Chrome eine sichere Internetverbindung herstellt" (nur Windows-Computer)</translation>
<translation id="1294154142200295408">Befehlszeilen-Varianten</translation>
<translation id="129553762522093515">Kürzlich geschlossen</translation>
+<translation id="1298536327547837046">Malware-Scan</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Löschen Sie Ihre Cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Eingestellte Funktionen</translation>
<translation id="1320233736580025032">Prc1 (Umschlag)</translation>
<translation id="132301787627749051">Nach Bild aus Zwischenablage suchen</translation>
<translation id="1323433172918577554">Mehr anzeigen</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google Tabellen</translation>
<translation id="1527263332363067270">Warten auf Verbindung…</translation>
<translation id="1529521330346880926">10x15 (Umschlag)</translation>
+<translation id="1530707389502320859">Die Website, die Sie besuchen möchten, ist möglicherweise eine Fälschung. Angreifer kopieren manchmal Websites und nehmen kleine, unauffällige Änderungen an der URL vor.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Auf dieser Seite wird Folgendes angezeigt</translation>
<translation id="153384715582417236">Das ist im Moment alles</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">Betriebssystem</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Das Dokument kann aufgrund seiner Größe nicht mit Anmerkungen versehen werden</translation>
-<translation id="1721312023322545264">Du benötigst die Berechtigung von <ph name="NAME" />, um diese Website zu besuchen</translation>
<translation id="1721424275792716183">* Pflichtfeld</translation>
<translation id="1727741090716970331">Gültige Kartennummer hinzufügen</translation>
<translation id="1728677426644403582">Dies ist die Quelle einer Webseite</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Von Ihnen besuchte Websites und Dauer des Besuchs</translation>
<translation id="1826516787628120939">Überprüfung läuft</translation>
<translation id="1834321415901700177">Diese Website enthält schädliche Programme</translation>
+<translation id="1838374766361614909">Suche löschen</translation>
<translation id="1839551713262164453">Die Validierung der Richtlinienwerte hat Fehler ergeben und ist fehlgeschlagen</translation>
<translation id="1842969606798536927">Bezahlen</translation>
<translation id="1871208020102129563">Der Proxy ist zur Verwendung von festen Proxyservern konfiguriert, nicht zur Verwendung einer PAC-Skript-URL.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Liste ausblenden</translation>
<translation id="1898423065542865115">Filtern</translation>
<translation id="1914326953223720820">Dienst entpacken</translation>
+<translation id="1915697529809968049">Touch ID anstelle des CVCs verwenden?</translation>
<translation id="1916770123977586577">Laden Sie diese Seite neu, um die aktualisierten Einstellungen für diese Website zu übernehmen</translation>
<translation id="1919345977826869612">Werbung</translation>
<translation id="1919367280705858090">Hilfe bei bestimmten Fehlermeldungen</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" />-Lesezeichen</translation>
<translation id="1973335181906896915">Fehler bei der Serialisierung</translation>
<translation id="1974060860693918893">Erweitert</translation>
+<translation id="1974883374937189061">Dabei helfen, die Sicherheit von Chrome zu verbessern. Hierfür werden <ph name="BEGIN_WHITEPAPER_LINK" />die URLs einiger von Ihnen besuchter Seiten, bestimmte Systeminformationen und einige Seiteninhalte<ph name="END_WHITEPAPER_LINK" /> an Google gesendet. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Firmwareversion</translation>
<translation id="1981206234434200693">Chrome-Browserverlauf löschen</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{und 1 weitere}other{und # weitere}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Geben Sie ein gültiges Ablaufjahr ein</translation>
<translation id="2212735316055980242">Richtlinie nicht gefunden</translation>
<translation id="2213606439339815911">Einträge werden abgerufen...</translation>
+<translation id="2215727959747642672">Dateien bearbeiten</translation>
<translation id="2218879909401188352">Angreifer auf der Website <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> könnten gefährliche Apps installieren, die Ihr Gerät beschädigen, Ihrer Mobilfunkrechnung versteckte Kosten hinzufügen oder Ihre personenbezogenen Daten stehlen könnten. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Kein Internet</translation>
<translation id="2230458221926704099">Beheben Sie den Verbindungsfehler mithilfe der <ph name="BEGIN_LINK" />Diagnose-App<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Jetzt senden</translation>
+<translation id="2248949050832152960">WebAuthn verwenden</translation>
<translation id="225207911366869382">Dieser Wert für die Richtlinie ist veraltet.</translation>
<translation id="2257315177824333709">Ihre Karte kann momentan nicht gespeichert werden</translation>
<translation id="2262243747453050782">HTTP-Fehler</translation>
@@ -272,7 +281,7 @@
<translation id="2365563543831475020">Absturzbericht erfasst am <ph name="CRASH_TIME" />, wurde nicht hochgeladen</translation>
<translation id="2367567093518048410">Ebene</translation>
<translation id="2380886658946992094">Legal</translation>
-<translation id="2384307209577226199">Standardeinstellung durch Unternehmen</translation>
+<translation id="2384307209577226199">Unternehmensstandard</translation>
<translation id="2386255080630008482">Das Serverzertifikat wurde aufgehoben.</translation>
<translation id="2392959068659972793">Richtlinien ohne Wert zeigen</translation>
<translation id="239429038616798445">Diese Versandart ist nicht verfügbar. Bitte wählen Sie eine andere aus.</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">Ungültige Such-URL</translation>
<translation id="2482878487686419369">Benachrichtigungen</translation>
<translation id="248348093745724435">Computerrichtlinien</translation>
-<translation id="2485387744899240041">Nutzernamen für Ihr Gerät und Ihren Browser</translation>
<translation id="2491120439723279231">Das Serverzertifikat enthält Fehler.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON-Parser</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Zurück</translation>
<translation id="2503184589641749290">Akzeptierte Debit- und Prepaidkarten</translation>
<translation id="2505268675989099013">Konto schützen</translation>
+<translation id="2515335152965840738">IGNORIEREN</translation>
<translation id="2515629240566999685">Signal an Ihrem Standort prüfen</translation>
<translation id="2523886232349826891">Nur auf diesem Gerät gespeichert</translation>
<translation id="2524461107774643265">Weitere Informationen hinzufügen</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Senden</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Keins}=1{1 Passwort (für <ph name="DOMAIN_LIST" />)}=2{2 Passwörter (für <ph name="DOMAIN_LIST" />)}other{# Passwörter (für <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Andere Tabs oder Apps schließen</translation>
-<translation id="267371737713284912">Zum Rückgängigmachen <ph name="MODIFIER_KEY_DESCRIPTION" /> drücken</translation>
<translation id="2674170444375937751">Möchten Sie diese Seiten wirklich aus dem Verlauf löschen?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Verlassen</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">Wert stimmt nicht mit dem Format überein.</translation>
<translation id="2705137772291741111">Die (im Cache) gespeicherte Kopie dieser Website war nicht lesbar.</translation>
<translation id="2709516037105925701">AutoFill</translation>
-<translation id="2712173769900027643">Berechtigung anfordern</translation>
<translation id="2713444072780614174">Weiß</translation>
<translation id="2720342946869265578">In der Nähe</translation>
<translation id="2721148159707890343">Anfrage erfolgreich</translation>
<translation id="2728127805433021124">Das Serverzertifikat ist mit einem schwachen Signaturalgorithmus signiert.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Verbindungsdiagnose ausführen<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Wenn Sie diese Funktionen aktivieren, verlieren Sie unter Umständen Browserdaten oder gefährden Ihre Sicherheit oder Ihre Privatsphäre. Aktivierte Funktionen werden für alle Nutzer dieses Browsers angewendet.</translation>
<translation id="2735043616039983645">Für diese Richtlinie sind mehrere Quellen mit in Konflikt stehenden Werten vorhanden.</translation>
<translation id="2738330467931008676">Abholadresse auswählen</translation>
<translation id="2740531572673183784">Ok</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">Verbindung wurde zurückgesetzt.</translation>
<translation id="2788784517760473862">Akzeptierte Kreditkarten</translation>
<translation id="2792012897584536778">Administratoren dieses Geräts haben Sicherheitszertifikate eingerichtet, die es ihnen möglicherweise erlauben, Inhalte der von Ihnen besuchten Websites anzuzeigen.</translation>
-<translation id="2794233252405721443">Website blockiert</translation>
<translation id="2799020568854403057">Die Website, die Sie aufrufen möchten, enthält schädliche Apps</translation>
<translation id="2799223571221894425">Neu starten</translation>
<translation id="2803306138276472711">Google Safe Browsing hat kürzlich <ph name="BEGIN_LINK" />Malware<ph name="END_LINK" /> auf <ph name="SITE" /> gefunden. Websites, die in der Regel sicher sind, können gelegentlich mit Malware infiziert sein.</translation>
+<translation id="2815364696811431560">WEBSITE VERLASSEN</translation>
<translation id="2824775600643448204">Adress- und Suchleiste</translation>
<translation id="2826760142808435982">Die Verbindung ist mit <ph name="CIPHER" /> verschlüsselt und authentifiziert und verwendet <ph name="KX" /> als Mechanismus für den Schlüsselaustausch.</translation>
<translation id="2835170189407361413">Formular leeren</translation>
<translation id="2847118875340931228">Inkognitofenster öffnen</translation>
<translation id="2850739647070081192">Invite (Umschlag)</translation>
-<translation id="2851634818064021665">Du benötigst eine Berechtigung, um auf diese Website zuzugreifen</translation>
<translation id="2856444702002559011">Hacker könnten versuchen, Ihre Daten von <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> zu stehlen, zum Beispiel Passwörter, Nachrichten oder Kreditkartendaten. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Karte speichern?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Wenn Sie diese Option auswählen, speichert Chromium eine Kopie Ihrer Karte auf diesem Gerät, damit Formulare schneller ausgefüllt werden können.</translation>
<translation id="2985398929374701810">Gültige Adresse eingeben</translation>
<translation id="2986368408720340940">Diese Abholoption ist nicht verfügbar. Bitte wählen Sie eine andere Option aus.</translation>
+<translation id="2987034854559945715">Keine passenden Funktionen</translation>
<translation id="2991174974383378012">Datenfreigabe an Websites</translation>
<translation id="2991571918955627853">Sie können <ph name="SITE" /> derzeit nicht aufrufen, da die Website HSTS verwendet. Netzwerkfehler und Angriffe sind in der Regel nur vorübergehend, sodass die Seite wahrscheinlich später wieder funktioniert.</translation>
<translation id="3005723025932146533">Gespeicherte Kopie anzeigen</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Falscher Richtlinientyp</translation>
<translation id="3037605927509011580">Oh nein!</translation>
<translation id="3041612393474885105">Zertifikatinformationen</translation>
+<translation id="3057676462092457419">Der DnsOverHttps-Modus "<ph name="SECURE_DNS_MODE_SECURE" />" wird noch nicht unterstützt. Der Modus wurde deshalb auf "<ph name="SECURE_DNS_MODE_OFF" />" festgelegt.</translation>
<translation id="3060227939791841287">C9 (Umschlag)</translation>
<translation id="3061707000357573562">Patchdienst</translation>
<translation id="3064966200440839136">Der Inkognitomodus wird beendet, um über eine externe Anwendung zu zahlen. Fortfahren?</translation>
@@ -419,6 +428,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> auf <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Zahlung abbrechen</translation>
<translation id="3207960819495026254">Mit einem Lesezeichen versehen</translation>
+<translation id="3209034400446768650">Auf der Seite wird möglicherweise Geld verlangt</translation>
<translation id="3225919329040284222">Der Server hat ein Zertifikat übermittelt, das nicht mit den integrierten Erwartungen übereinstimmt. Diese Erwartungen sind zu Ihrem Schutz in bestimmten Websites mit hohen Sicherheitsstandards enthalten.</translation>
<translation id="3226128629678568754">Klicken Sie auf die Schaltfläche zum erneuten Laden, um die für das Laden der Seite erforderlichen Daten noch einmal zu senden.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -426,7 +436,6 @@
<translation id="3229041911291329567">Versionsinformationen zu Ihrem Gerät und Browser</translation>
<translation id="323107829343500871">CVC für <ph name="CREDIT_CARD" /> eingeben</translation>
<translation id="3234666976984236645">Wichtige Inhalte auf dieser Website immer erkennen</translation>
-<translation id="3254409185687681395">Lesezeichen für diese Seite erstellen</translation>
<translation id="3270847123878663523">&amp;Neu anordnen rückgängig machen</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Angabe für "Name auf der Karte" hinzufügen</translation>
@@ -436,7 +445,6 @@
<translation id="3320021301628644560">Rechnungsadresse hinzufügen</translation>
<translation id="3324983252691184275">Purpur</translation>
<translation id="3338095232262050444">Sicher</translation>
-<translation id="3345135638360864351">Ihre Zugriffsanfrage für diese Website konnte nicht an <ph name="NAME" /> gesendet werden. Bitte versuchen Sie es erneut.</translation>
<translation id="3355823806454867987">Proxy-Einstellungen ändern...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />speichert die folgenden Daten nicht<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -457,7 +465,7 @@
<translation id="3399952811970034796">Lieferadresse</translation>
<translation id="3422248202833853650">Versuchen Sie, andere Programme zu beenden, um Speicher freizugeben.</translation>
<translation id="3422472998109090673"><ph name="HOST_NAME" /> ist momentan nicht erreichbar.</translation>
-<translation id="3427092606871434483">Zulassen (Standardeinstellung)</translation>
+<translation id="3427092606871434483">Zulassen (Standard)</translation>
<translation id="3427342743765426898">&amp;Bearbeiten wiederholen</translation>
<translation id="342781501876943858">Chromium empfiehlt, Ihr Passwort zurückzusetzen, wenn Sie es auf anderen Websites verwendet haben.</translation>
<translation id="3431636764301398940">Diese Karte für dieses Gerät speichern</translation>
@@ -470,17 +478,14 @@
<translation id="3462200631372590220">Erweiterte Informationen ausblenden</translation>
<translation id="3467763166455606212">Name des Karteninhabers erforderlich</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, derzeit geöffnet, Tabulatortaste und dann Eingabetaste drücken, um zum offenen Tab zu wechseln</translation>
-<translation id="3479539252931486093">Geschah dies unerwartet? <ph name="BEGIN_LINK" />Informieren Sie uns<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Jetzt nicht</translation>
<translation id="3484560055331845446">Sie könnten den Zugriff auf Ihr Google-Konto verlieren. Chrome empfiehlt Ihnen, Ihr Passwort jetzt zu ändern. Sie werden dazu aufgefordert, sich anzumelden.</translation>
<translation id="3495081129428749620">Auf Seite "<ph name="PAGE_TITLE" />" suchen</translation>
-<translation id="3498215018399854026">Wir können deinen Vater bzw. deine Mutter momentan nicht erreichen. Bitte versuche es später noch einmal.</translation>
<translation id="3512163584740124171">Diese Richtlinie wird ignoriert, da eine andere Richtlinie aus derselben Richtliniengruppe eine höhere Priorität hat.</translation>
<translation id="3528171143076753409">Serverzertifikat ist nicht vertrauenswürdig.</translation>
<translation id="3528485271872257980">Dunkelbraun</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Mindestens 1 Eintrag auf synchronisierten Geräten}=1{1 Eintrag (und weitere auf synchronisierten Geräten)}other{# Einträge (und weitere auf synchronisierten Geräten)}}</translation>
<translation id="3539171420378717834">Kopie dieser Karte auf diesem Gerät speichern</translation>
-<translation id="3556433843310711081">Dein Administrator kann die Blockierung aufheben</translation>
<translation id="3566021033012934673">Dies ist keine sichere Verbindung</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Auf einer in <ph name="SITE" /> eingebetteten Seite wird Folgendes angezeigt</translation>
@@ -507,6 +512,7 @@
<translation id="3678529606614285348">Seite in einem neuen Inkognitofenster öffnen (Strg + Umschalttaste + N)</translation>
<translation id="3679803492151881375">Absturz am <ph name="CRASH_TIME" /> erfasst und am <ph name="UPLOAD_TIME" /> hochgeladen</translation>
<translation id="3681007416295224113">Zertifikatinformationen</translation>
+<translation id="3701427423622901115">Zurücksetzen bestätigt.</translation>
<translation id="3704162925118123524">Eventuell müssen Sie die Anmeldeseite des verwendeten Netzwerks aufrufen.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Wird geladen...</translation>
@@ -523,6 +529,7 @@
<translation id="3748148204939282805">Hacker könnten auf <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> etwa versuchen, Sie zur Installation von Software oder zur Herausgabe von Daten wie Passwörtern, Telefonnummern oder Kreditkartendetails zu bewegen. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Aufgrund eines Serverfehlers ist die Übersetzung fehlgeschlagen.</translation>
<translation id="3759461132968374835">Es liegen keine kürzlich gemeldeten Abstürze vor. Abstürze, die bei deaktivierter Absturzberichtsfunktion aufgetreten sind, werden hier nicht angezeigt.</translation>
+<translation id="3760561303380396507">Windows Hello anstelle des CVCs verwenden?</translation>
<translation id="3761718714832595332">Status ausblenden</translation>
<translation id="3765032636089507299">Die Seite "Safe Browsing" wird überarbeitet.</translation>
<translation id="3778403066972421603">Möchten Sie diese Karte in Ihrem Google-Konto und auf diesem Gerät speichern?</translation>
@@ -532,6 +539,7 @@
<translation id="3789155188480882154">Größe 16</translation>
<translation id="3797522431967816232">Prc3 (Umschlag)</translation>
<translation id="3807873520724684969">Schädliche Inhalte blockiert.</translation>
+<translation id="3808375843007691220">Warnung: experimentelle Funktionen!</translation>
<translation id="3810973564298564668">Verwalten</translation>
<translation id="382518646247711829">Falls Sie einen Proxyserver verwenden...</translation>
<translation id="3828924085048779000">Eine leere Passphrase ist nicht zulässig.</translation>
@@ -540,11 +548,11 @@
<translation id="3858027520442213535">Datum und Uhrzeit aktualisieren</translation>
<translation id="3884278016824448484">In Konflikt stehende Gerätekennung</translation>
<translation id="3885155851504623709">Gemeinde</translation>
-<translation id="3886446263141354045">Deine Anfrage zum Zugriff auf diese Website wurde an <ph name="NAME" /> gesendet</translation>
<translation id="3890664840433101773">E-Mail-Adresse hinzufügen</translation>
<translation id="3901925938762663762">Die Karte ist abgelaufen.</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> – <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">WebAuthn anstelle des CVCs verwenden?</translation>
<translation id="3946209740501886391">Auf dieser Website immer fragen</translation>
<translation id="3949571496842715403">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat gibt keine alternativen Namen an. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
<translation id="3949601375789751990">Hier wird Ihr Browserverlauf angezeigt</translation>
@@ -555,11 +563,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Keine}=1{Von 1 Website }other{Von # Websites }}</translation>
<translation id="397105322502079400">Wird berechnet...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ist gesperrt</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> hat das Chrome Enterprise-Sicherheitssystem für Ihren Browser aktiviert. Das Chrome Enterprise-Sicherheitssystem kann auf manche Ihrer Daten zugreifen.</translation>
<translation id="3987940399970879459">Weniger als 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 Webseite in der Nähe}other{# Webseiten in der Nähe}}</translation>
<translation id="4030383055268325496">&amp;Hinzufügen rückgängig machen</translation>
<translation id="4032320456957708163">Ihr Browser wird von <ph name="ENROLLMENT_DOMAIN" /> verwaltet</translation>
-<translation id="4034375457890803692">Der geöffnete Link führt auf eine Website, die Sie normalerweise nicht besuchen. Es könnte sich um einen Täuschungsversuch handeln.</translation>
<translation id="4058922952496707368">Schlüssel "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Umschlag)</translation>
<translation id="4067947977115446013">Gültige Adresse hinzufügen</translation>
@@ -572,6 +580,7 @@
<translation id="4103249731201008433">Seriennummer des Geräts ist ungültig.</translation>
<translation id="410351446219883937">Autoplay</translation>
<translation id="4103763322291513355">Unter &lt;strong&gt;chrome://policy&lt;/strong&gt; finden Sie eine Liste der blockierten URLs und andere Richtlinien, die durch Ihren Systemadministrator erzwungen werden.</translation>
+<translation id="4108231218301530806">Diese Karte das nächste Mal per Fingerabdruck bestätigen.</translation>
<translation id="4110652170750985508">Zahlung überprüfen</translation>
<translation id="4112140312785995938">Zurück springen</translation>
<translation id="4116663294526079822">Auf dieser Website immer zulassen</translation>
@@ -586,6 +595,7 @@
<translation id="4171400957073367226">Ungültige Bestätigungssignatur</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> weiteres Element}other{<ph name="ITEM_COUNT" /> weitere Elemente}}</translation>
+<translation id="4176463684765177261">Deaktiviert</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" />: <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Damit Zahlungen zukünftig schneller abgewickelt werden können, fügen Sie Ihre Kreditkartendaten und Ihre Rechnungsadresse in Ihrem Google-Konto hinzu.</translation>
<translation id="4196861286325780578">&amp;Verschieben wiederholen</translation>
@@ -622,11 +632,12 @@
<translation id="4277028893293644418">Passwort zurücksetzen</translation>
<translation id="4279811152705618813">Ihr <ph name="DEVICE_TYPE" /> wird von <ph name="ENROLLMENT_DOMAIN" /> verwaltet</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Diese Karte wurde in Ihrem Google-Konto gespeichert}other{Diese Karten wurden in Ihrem Google-Konto gespeichert}}</translation>
+<translation id="428847186335018806">Dateien scannen, die Sie in Chrome herunter- oder hochladen.</translation>
<translation id="42981349822642051">Maximieren</translation>
<translation id="4302965934281694568">Chou3 (Umschlag)</translation>
<translation id="4305817255990598646">Wechseln</translation>
<translation id="4312613361423056926">B2</translation>
-<translation id="4312866146174492540">Blockieren (Standardeinstellung)</translation>
+<translation id="4312866146174492540">Blockieren (Standard)</translation>
<translation id="4318566738941496689">Gerätename und Netzwerkadresse</translation>
<translation id="4325863107915753736">Der Artikel wurde nicht gefunden.</translation>
<translation id="4326324639298822553">Prüfen Sie Ihr Ablaufdatum und versuchen Sie es dann erneut</translation>
@@ -651,7 +662,6 @@
<translation id="4435702339979719576">Postkarte)</translation>
<translation id="443673843213245140">Die Proxy-Nutzung ist deaktiviert, es ist jedoch eine explizite Proxy-Konfiguration festgelegt.</translation>
<translation id="445100540951337728">Akzeptierte Debitkarten</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> verdächtiges Verhalten</translation>
<translation id="4466881336512663640">Änderungen im Formular gehen verloren. Möchten Sie den Vorgang wirklich fortsetzen?</translation>
<translation id="4477350412780666475">Nächster Titel</translation>
<translation id="4482953324121162758">Diese Website wird nicht übersetzt.</translation>
@@ -678,6 +688,7 @@
<translation id="4594403342090139922">&amp;Löschen rückgängig machen</translation>
<translation id="4597348597567598915">Größe 8</translation>
<translation id="4600854749408232102">C6/C5 (Umschlag)</translation>
+<translation id="464342062220857295">Suchfunktionen</translation>
<translation id="4646534391647090355">Jetzt aufrufen</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat enthält Fehler. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
@@ -686,7 +697,6 @@
<translation id="4691835149146451662">Architecture-A (Umschlag)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Die Verbindung wurde unterbrochen</translation>
-<translation id="471880041731876836">Sie sind nicht berechtigt, auf diese Website zuzugreifen</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows-Netzwerkdiagnose ausführen<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Richtlinien neu laden</translation>
<translation id="4728558894243024398">Plattform</translation>
@@ -714,7 +724,6 @@
<translation id="4816492930507672669">An Seite anpassen</translation>
<translation id="4850886885716139402">Anzeigen</translation>
<translation id="4854362297993841467">Diese Lieferoption ist nicht verfügbar. Bitte wählen Sie eine andere Option aus.</translation>
-<translation id="4858792381671956233">Du hast deine Eltern gefragt, ob du diese Website besuchen darfst</translation>
<translation id="4864052566555297930">Sicherheitstipp:</translation>
<translation id="4876188919622883022">Vereinfachte Ansicht</translation>
<translation id="4876305945144899064">Kein Nutzername</translation>
@@ -738,7 +747,9 @@
<translation id="4974590756084640048">Warnmeldungen wieder aktivieren</translation>
<translation id="4984339528288761049">Prc5 (Umschlag)</translation>
<translation id="4989163558385430922">Alle ansehen</translation>
+<translation id="4989542687859782284">Nicht verfügbar</translation>
<translation id="4989809363548539747">Dieses Plug-in wird nicht unterstützt</translation>
+<translation id="4995216769782533993">Bestätigen Sie den Sicherheitscode, um Ihre Kartendetails mit dieser Website zu teilen</translation>
<translation id="5002932099480077015">Wenn diese Funktion aktiviert ist, speichert Chrome eine Kopie Ihrer Karte auf diesem Gerät, um ein Ausfüllen von Formularen zu beschleunigen.</translation>
<translation id="5015510746216210676">Computername:</translation>
<translation id="5017554619425969104">Von Ihnen kopierter Text</translation>
@@ -767,6 +778,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-Bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Karte bestätigen</translation>
<translation id="5135404736266831032">Adressen verwalten…</translation>
<translation id="5138227688689900538">Weniger anzeigen</translation>
<translation id="5141240743006678641">Synchronisierte Passwörter mit Ihren Google-Anmeldeinformationen verschlüsseln</translation>
@@ -793,6 +805,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Umschlag)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Systemweite Funktionen können nur vom Inhaber festgelegt werden: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Warnung: Diese Richtlinie wurde nicht wie in der Richtlinie "PolicyDictionaryMultipleSourceMergeList" vorgesehen zusammengeführt, weil sie nicht Teil der Wörterbuchrichtlinien ist, die zusammengeführt werden können.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Ende</translation>
@@ -816,7 +829,6 @@
<translation id="536296301121032821">Fehler beim Speichern der Richtlinieneinstellungen</translation>
<translation id="5371425731340848620">Karte aktualisieren</translation>
<translation id="5377026284221673050">"Ihre Uhr geht nach", "Ihre Uhr geht vor" oder "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Mit dieser Webseite wird möglicherweise versucht, Sie zu täuschen, Ihnen personenbezogene Daten zu stehlen oder Ihrem Gerät zu schaden. Seien Sie vorsichtig, wenn Sie personenbezogene Daten eingeben oder heruntergeladene Dateien öffnen.</translation>
<translation id="5384855140246857529">Wenn Sie Ihre Karten auf allen Geräten verwenden möchten, melden Sie sich an und aktivieren Sie die Synchronisierung.</translation>
<translation id="5386426401304769735">Die Zertifikatskette für diese Website enthält ein Zertifikat mit SHA-1-Signatur.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -830,6 +842,7 @@
<translation id="5457113250005438886">Ungültig</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> und <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> weiterer}other{<ph name="CONTACT_PREVIEW" /> und <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> weitere}}</translation>
<translation id="5470861586879999274">&amp;Bearbeiten wiederholen</translation>
+<translation id="5473728911100096288">Bitte beachten Sie, dass diese Funktionen eingestellt wurden und in zukünftigen Versionen nicht mehr verfügbar sein werden.</translation>
<translation id="5478437291406423475">B6/C4 (Umschlag)</translation>
<translation id="5481076368049295676">Diese Inhalte versuchen möglicherweise, gefährliche Software auf Ihrem Gerät zu installieren, durch die Ihre Informationen gestohlen oder gelöscht werden. <ph name="BEGIN_LINK" />Trotzdem anzeigen<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Gültige Adresse hinzufügen</translation>
@@ -853,7 +866,6 @@
<translation id="5570825185877910964">Konto schützen</translation>
<translation id="5571083550517324815">Diese Abholadresse wird nicht unterstützt. Bitte wählen Sie eine andere Adresse aus.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 wird verwendet}other{# werden verwendet}})</translation>
-<translation id="5572851009514199876">Melden Sie sich zuerst in Chrome an, damit überprüft werden kann, ob Sie auf diese Website zugreifen dürfen.</translation>
<translation id="5580958916614886209">Prüfen Sie Ihren Ablaufmonat und versuchen Sie es dann erneut</translation>
<translation id="5586446728396275693">Keine gespeicherten Adressen</translation>
<translation id="5595485650161345191">Adresse bearbeiten</translation>
@@ -861,6 +873,7 @@
<translation id="560412284261940334">Verwaltung wird nicht unterstützt.</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Diese Website ist eventuell gefälscht oder betrügerisch. Sie sollten sie am besten verlassen.</translation>
<translation id="5610142619324316209">Verbindung prüfen</translation>
<translation id="5610807607761827392"><ph name="BEGIN_LINK" />Karten und Adressen können Sie in den Einstellungen verwalten.<ph name="END_LINK" /></translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> hat Sie zu oft weitergeleitet.</translation>
@@ -884,11 +897,11 @@
<translation id="5720705177508910913">Aktueller Nutzer</translation>
<translation id="5728056243719941842">C5 (Umschlag)</translation>
<translation id="5730040223043577876">Chrome empfiehlt, Ihr Passwort zurückzusetzen, wenn Sie es auf anderen Websites verwendet haben.</translation>
-<translation id="5732392974455271431">Deine Eltern können die Blockierung aufheben</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Karte in Ihrem Google-Konto speichern}other{Karten in Ihrem Google-Konto speichern}}</translation>
<translation id="5763042198335101085">Geben Sie eine gültige E-Mail-Adresse ein</translation>
<translation id="5765072501007116331">Wählen Sie eine Adresse aus, um Lieferoptionen und -anforderungen zu sehen</translation>
<translation id="5778550464785688721">MIDI-Geräte: volle Kontrolle</translation>
+<translation id="5781136890105823427">Test aktiviert</translation>
<translation id="578305955206182703">Bernsteingelb</translation>
<translation id="57838592816432529">Stummschalten</translation>
<translation id="5784606427469807560">Beim Bestätigen Ihrer Karte ist ein Problem aufgetreten. Überprüfen Sie Ihre Internetverbindung und versuchen Sie es noch einmal.</translation>
@@ -905,13 +918,16 @@
<translation id="5860033963881614850">Aus</translation>
<translation id="5863847714970149516">Auf der nächsten Seite wird möglicherweise versucht, Ihnen etwas in Rechnung zu stellen</translation>
<translation id="5866257070973731571">Telefonnummer hinzufügen</translation>
+<translation id="5866898949289125849">Sie haben eine Entwicklertools-Seite aufgerufen</translation>
<translation id="5869405914158311789">Die Website ist nicht erreichbar</translation>
<translation id="5869522115854928033">Gespeicherte Passwörter</translation>
<translation id="5887400589839399685">Karte gespeichert</translation>
<translation id="5893752035575986141">Kreditkarten werden akzeptiert.</translation>
+<translation id="5895138241574237353">Neu starten</translation>
<translation id="5901630391730855834">Gelb</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronisiert)</translation>
<translation id="5916664084637901428">An</translation>
+<translation id="59174027418879706">Aktiviert</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Karte im Google-Konto speichern?</translation>
<translation id="5922853866070715753">Fast fertig</translation>
@@ -945,6 +961,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Karten auf allen Ihren Geräten nutzen?</translation>
<translation id="6059925163896151826">USB-Geräte</translation>
+<translation id="6060009363608157444">Ungültiger DnsOverHttps-Modus.</translation>
<translation id="6080696365213338172">Sie haben über ein vom Administrator bereitgestelltes Zertifikat auf Inhalte zugegriffen. Die Daten, die Sie innerhalb von <ph name="DOMAIN" /> bereitstellen, können von Ihrem Administrator abgefangen werden.</translation>
<translation id="6094273045989040137">Anmerkung hinzufügen</translation>
<translation id="610911394827799129">Unter <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> sind möglicherweise weitere Arten von Browserverlaufsdaten für Ihr Google-Konto gespeichert.</translation>
@@ -993,13 +1010,12 @@
<translation id="6404511346730675251">Lesezeichen bearbeiten</translation>
<translation id="6406765186087300643">C0 (Umschlag)</translation>
<translation id="6410264514553301377">Ablaufdatum und CVC für <ph name="CREDIT_CARD" /> eingeben</translation>
-<translation id="6414888972213066896">Du hast ein Elternteil gefragt, ob du diese Website besuchen darfst</translation>
<translation id="6415778972515849510">Mithilfe von Chromium können Sie Ihr Google-Konto schützen und Ihr Passwort ändern.</translation>
-<translation id="6417515091412812850">Überprüfung, ob das Zertifikat zurückgerufen wurde, nicht möglich</translation>
<translation id="6431585503458005759">Nicht speichern</translation>
<translation id="6433490469411711332">Kontaktdaten bearbeiten</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> hat die Verbindung abgelehnt.</translation>
<translation id="6434309073475700221">Verwerfen</translation>
+<translation id="6435221585574090192">Sicherheitshinweise, die vom Chrome Enterprise-Sicherheitssystem gemeldet wurden, werden mit Ihrem Administrator geteilt. Sie können Seiten-URLs, Dateinamen, Dateimetadaten, den Nutzernamen für Ihr Gerät und Ihren Chrome-Nutzernamen enthalten.</translation>
<translation id="6440503408713884761">Ignoriert</translation>
<translation id="6446163441502663861">Kahu (Umschlag)</translation>
<translation id="6446608382365791566">Weitere Informationen hinzufügen</translation>
@@ -1008,20 +1024,19 @@
<translation id="6465306955648956876">Passwörter verwalten…</translation>
<translation id="647261751007945333">Geräterichtlinien</translation>
<translation id="6476284679642588870">Zahlungsmethoden verwalten</translation>
-<translation id="6477321094435799029">Chrome hat auf dieser Seite ungewöhnlichen Code erfasst und diese Seite daher blockiert, um Ihre personenbezogenen Daten wie Passwörter, Telefonnummern oder Kreditkarteninformationen zu schützen.</translation>
<translation id="6489534406876378309">Hochladen von Abstürzen starten</translation>
<translation id="6499038740797743453">Passwort zurücksetzen?</translation>
<translation id="6507833130742554667">Kredit- und Debitkarten werden akzeptiert.</translation>
<translation id="650855688985305916">Ja, speichern</translation>
<translation id="6508722015517270189">Chrome neu starten</translation>
<translation id="6517596291481585650">Warnung: Diese Richtlinie wurde nicht gemäß Richtlinie in einer Liste zusammengeführt, weil sie keine Liste ist.</translation>
+<translation id="6518133107902771759">Bestätigen</translation>
<translation id="6521745193039995384">Nicht aktiv</translation>
<translation id="6529602333819889595">&amp;Löschen wiederholen</translation>
<translation id="6534179046333460208">Physical Web-Vorschläge</translation>
<translation id="6545864417968258051">Bluetooth-Suche</translation>
<translation id="6554795675067793129">Ihr Konto wird von <ph name="ENROLLMENT_DOMAIN" /> verwaltet.</translation>
<translation id="6556866813142980365">Wiederholen</translation>
-<translation id="6563469144985748109">Der Administrator hat die Berechtigung noch nicht erteilt</translation>
<translation id="6569060085658103619">Dies ist eine Erweiterungsseite</translation>
<translation id="6578796323535178455">C2 (Umschlag)</translation>
<translation id="6579990219486187401">Hellrosa</translation>
@@ -1039,11 +1054,13 @@
<translation id="6643016212128521049">Löschen</translation>
<translation id="6644283850729428850">Diese Richtlinie ist veraltet.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Keine}=1{1 Website (Anmeldung in Google-Konto bleibt erhalten)}other{# Websites (Anmeldung in Google-Konto bleibt erhalten)}}</translation>
+<translation id="6652101503459149953">Windows Hello verwenden</translation>
<translation id="6657585470893396449">Passwort</translation>
<translation id="6670613747977017428">Zurück zu sicherer Website.</translation>
<translation id="6671697161687535275">Vorschlag für das Formular aus Chromium entfernen?</translation>
<translation id="6685834062052613830">Abmelden und Einrichtung abschließen</translation>
<translation id="6689271823431384964">Chrome bietet Ihnen die Möglichkeit, die Karten in Ihrem Google-Konto zu speichern, weil Sie angemeldet sind. Sie können dies in den Einstellungen ändern. Der Name des Karteninhabers stammt aus Ihrem Konto.</translation>
+<translation id="6707256370811247129">Cache-Inhalte und Dateien scannen, die Sie in Chrome herunter- oder hochladen.</translation>
<translation id="6710213216561001401">Zurück</translation>
<translation id="6710594484020273272">&lt;Suchbegriff eingeben&gt;</translation>
<translation id="671076103358959139">Registrierungstoken:</translation>
@@ -1051,10 +1068,10 @@
<translation id="6738516213925468394">Ihre Daten wurden am <ph name="TIME" /> mit Ihrer <ph name="BEGIN_LINK" />Synchronisierungspassphrase<ph name="END_LINK" /> verschlüsselt. Geben Sie diese ein, um die Synchronisierung zu starten.</translation>
<translation id="674375294223700098">Fehler wegen unbekanntem Serverzertifikat</translation>
<translation id="6744009308914054259">Während Sie auf eine Verbindung warten, können Sie "Downloads" aufrufen und Offline-Artikel lesen.</translation>
+<translation id="6747611005629681221">Warnung: Eingestellte Funktionen!</translation>
<translation id="6753269504797312559">Wert der Richtlinie</translation>
<translation id="6757797048963528358">Ihr Gerät ist im Ruhemodus.</translation>
<translation id="6768213884286397650">Hagaki (Postkarte)</translation>
-<translation id="6778737459546443941">Dein Elternteil hat die Berechtigung noch nicht erteilt</translation>
<translation id="67862343314499040">Violett</translation>
<translation id="6786747875388722282">Erweiterungen</translation>
<translation id="6790428901817661496">Wiedergabe</translation>
@@ -1062,6 +1079,7 @@
<translation id="681021252041861472">Pflichtfeld</translation>
<translation id="6810899417690483278">Personalisierungs-ID</translation>
<translation id="6825578344716086703">Sie haben versucht, auf <ph name="DOMAIN" /> zuzugreifen, der Server hat jedoch ein Zertifikat übermittelt, das einen schwachen Signaturalgorithmus verwendet, zum Beispiel SHA-1. Das bedeutet, dass die vom Server übermittelten Sicherheitsinformationen gefälscht sein könnten und es sich möglicherweise gar nicht um den erwarteten Server handelt, sondern Sie mit einem Hacker kommunizieren.</translation>
+<translation id="6826370046007623921">Schutz vor Datenverlust</translation>
<translation id="6831043979455480757">Übersetzen</translation>
<translation id="6839929833149231406">Region</translation>
<translation id="6852204201400771460">App neu laden?</translation>
@@ -1074,7 +1092,6 @@
<translation id="6891596781022320156">Richtlinienebene wird nicht unterstützt.</translation>
<translation id="6895330447102777224">Ihre Karte wurde bestätigt</translation>
<translation id="6897140037006041989">User-Agent</translation>
-<translation id="6903319715792422884">Sie können uns dabei helfen, Safe Browsing weiter zu verbessern, indem Sie einige <ph name="BEGIN_WHITEPAPER_LINK" />Systeminformationen und Seiteninhalte<ph name="END_WHITEPAPER_LINK" /> an Google senden. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Nutzer: </translation>
<translation id="6934672428414710184">Dieser Name stammt aus Ihrem Google-Konto</translation>
<translation id="6944692733090228304">Sie haben Ihr Passwort auf einer Website eingegeben, die nicht von <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> verwaltet wird. Zum Schutz Ihres Kontos sollten Sie das Passwort nicht für andere Apps und Websites verwenden.</translation>
@@ -1119,6 +1136,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> und <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> weitere}other{<ph name="PAYMENT_METHOD_PREVIEW" /> und <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> weitere}}</translation>
<translation id="7153618581592392745">Lavendel</translation>
<translation id="717330890047184534">GAIA-ID: </translation>
+<translation id="7174545416324379297">Zusammengeführt</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> und <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> weitere}other{<ph name="SHIPPING_OPTION_PREVIEW" /> und <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> weitere}}</translation>
<translation id="7177397715882417099">Der Server <ph name="ORIGIN" />, zu dem Sie gehen, verlangt, dass auf alle an ihn gerichteten Anfragen eine Sicherheitsrichtlinie angewendet wird. Aber statt eine Richtlinie bereitzustellen, hat er den Browser weitergeleitet, was den Browser daran hindert, Ihre Anfrage für <ph name="SITE" /> auszuführen.</translation>
<translation id="7179323680825933600">Zahlungsmethoden speichern und ausfüllen</translation>
@@ -1153,6 +1171,7 @@ Weitere Details:
<translation id="7320336641823683070">Hilfe bei der Verbindungsherstellung</translation>
<translation id="733354035281974745">Durch Sitzung mit einem lokalen Gerätekonto überschrieben</translation>
<translation id="7334320624316649418">&amp;Neu anordnen wiederholen</translation>
+<translation id="7337706099755338005">Nicht auf Ihrer Plattform verfügbar.</translation>
<translation id="733923710415886693">Das Serverzertifikat wurde nicht über die Zertifikatstransparenz offengelegt.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Ist verknüpft:</translation>
@@ -1184,7 +1203,6 @@ Weitere Details:
<translation id="7440140511386898319">Verfügbare Offline-Inhalte</translation>
<translation id="7441627299479586546">Falsche(r) Nutzername/Domain der Richtlinie</translation>
<translation id="7442725080345379071">Helles Orange</translation>
-<translation id="7444046173054089907">Diese Website ist blockiert</translation>
<translation id="7445762425076701745">Die Identität des Servers, mit dem Sie verbunden sind, kann nicht vollständig überprüft werden. Sie sind mit einem Server verbunden, dessen Name nur innerhalb Ihres Netzwerks gültig ist und dessen Eigentümerschaft von einer externen Zertifizierungsstelle nicht überprüft werden kann. Da einige Zertifizierungsstellen ungeachtet dessen dennoch Zertifikate für diese Namen ausstellen, gibt es keine Möglichkeit, sicherzustellen, dass Sie mit der gewünschten Website und nicht mit einem Angreifer verbunden sind.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Weitere Informationen<ph name="END_LINK" /> zu diesem Problem.</translation>
<translation id="7455133967321480974">Globalen Standard verwenden (Blockieren)</translation>
@@ -1206,9 +1224,9 @@ Weitere Details:
<translation id="7538364083937897561">A2 (Umschlag)</translation>
<translation id="7542403920425041731">Nach erfolgter Bestätigung werden die Kartendetails an diese Website weitergegeben.</translation>
<translation id="7542995811387359312">Die Funktion zur automatischen Ausfüllung der Kreditkartendaten ist deaktiviert, da dieses Formular keine sichere Verbindung nutzt.</translation>
-<translation id="7543525346216957623">Frag deine Eltern</translation>
<translation id="7548892272833184391">Verbindungsfehler beheben</translation>
<translation id="7549584377607005141">Damit diese Webseite richtig angezeigt wird, werden die Daten benötigt, die Sie vorher eingegeben haben. Sie können diese Daten noch einmal senden, dabei werden jedoch sämtliche Aktionen wiederholt, die vorher durch diese Seite ausgeführt wurden.</translation>
+<translation id="7550637293666041147">Der Nutzername für Ihr Gerät und Ihr Chrome-Nutzername</translation>
<translation id="7552846755917812628">Probieren Sie folgende Tipps aus:</translation>
<translation id="7554791636758816595">Neuer Tab</translation>
<translation id="7564049878696755256">Sie könnten den Zugriff auf Ihr <ph name="ORG_NAME" />-Konto verlieren oder zum Opfer von Identitätsdiebstahl werden. Chrome empfiehlt Ihnen, Ihr Passwort jetzt zu ändern.</translation>
@@ -1223,6 +1241,7 @@ Weitere Details:
<translation id="7610193165460212391">Wert liegt außerhalb des zulässigen Bereichs (<ph name="VALUE" />).</translation>
<translation id="7613889955535752492">Gültig bis: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Sie verfügen bereits über Daten, die mit einem vorherigen Passwort für Ihr Google-Konto verschlüsselt wurden. Bitte geben Sie dieses Passwort unten ein.</translation>
+<translation id="7625784245512586808">Chrome Enterprise-Sicherheitssystem</translation>
<translation id="7633909222644580952">Leistungsdaten und Absturzberichte</translation>
<translation id="7637571805876720304">Kreditkarte aus Chromium entfernen?</translation>
<translation id="7638605456503525968">Serielle Schnittstellen</translation>
@@ -1235,7 +1254,6 @@ Weitere Details:
<translation id="7668654391829183341">Unbekanntes Gerät</translation>
<translation id="7669271284792375604">Unbefugte Dritte auf dieser Website versuchen eventuell, Sie zur Installation von Programmen zu bewegen, die sich nachteilig auf Ihre Browsernutzung auswirken. Dabei kann zum Beispiel Ihre Startseite geändert werden oder es erscheinen zusätzliche Anzeigen auf von Ihnen besuchten Websites.</translation>
<translation id="7676643023259824263">Nach Text aus Zwischenablage suchen: <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Plattform und Cloud</translation>
<translation id="7681101578153515023">Suchmaschine ändern</translation>
<translation id="7682287625158474539">Versand</translation>
<translation id="7687186412095877299">Zahlungsformulare werden mit Ihren gespeicherten Zahlungsmethoden ausgefüllt</translation>
@@ -1250,7 +1268,6 @@ Weitere Details:
<translation id="7723047071702270851">Karte bearbeiten</translation>
<translation id="774634243536837715">Gefährliche Inhalte blockiert.</translation>
<translation id="7752995774971033316">Nicht verwaltet</translation>
-<translation id="7755287808199759310">Deine Eltern können die Blockierung aufheben</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Möglicherweise wurde die Verbindung von einer Firewall oder Antivirensoftware blockiert.</translation>
<translation id="7759163816903619567">Anzeigebereich: </translation>
@@ -1294,17 +1311,17 @@ Weitere Details:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Passwort verwalten</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Diese Karte und die entsprechende Rechnungsadresse werden gespeichert. Sie können sie nutzen, wenn Sie in <ph name="USER_EMAIL" /> angemeldet sind.}other{Diese Karten und die entsprechenden Rechnungsadressen werden gespeichert. Sie können sie nutzen, wenn Sie in <ph name="USER_EMAIL" /> angemeldet sind.}}</translation>
-<translation id="8012647001091218357">Wir können deine Eltern momentan nicht erreichen. Bitte versuche es später noch einmal.</translation>
<translation id="8025119109950072390">Unbefugte Dritte auf dieser Website versuchen unter Umständen auf betrügerische Weise, Sie zur Installation von Software zu bewegen oder Ihnen personenbezogene Daten zu entlocken, zum Beispiel Passwörter, Telefonnummern oder Kreditkartendaten.</translation>
<translation id="8034522405403831421">Diese Seite ist auf <ph name="SOURCE_LANGUAGE" />. In folgende Sprache übersetzen: <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Stift</translation>
<translation id="8037117624646282037">Nutzer, die das Gerät vor Kurzem verwendet haben</translation>
-<translation id="8037357227543935929">Nachfragen (Standardeinstellung)</translation>
+<translation id="8037357227543935929">Nachfragen (Standard)</translation>
<translation id="803771048473350947">Datei</translation>
<translation id="8041089156583427627">Feedback geben</translation>
<translation id="8041940743680923270">Globalen Standard verwenden (Fragen)</translation>
<translation id="8042918947222776840">Abholoption auswählen</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ist nicht ordnungsgemäß konfiguriert. Durch die Deinstallation von "<ph name="SOFTWARE_NAME" />" sollte das Problem behoben werden. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Sie müssen ab sofort keine Kartenprüfnummer mehr eingeben</translation>
<translation id="8066955247577885446">Ein Fehler ist aufgetreten.</translation>
<translation id="8074253406171541171">10x13 (Umschlag)</translation>
<translation id="8078141288243656252">Anmerkungen bei gedrehtem Dokument nicht möglich</translation>
@@ -1335,6 +1352,7 @@ Weitere Details:
<translation id="8211406090763984747">Verbindung ist sicher</translation>
<translation id="8218327578424803826">Zugewiesener Standort: </translation>
<translation id="8220146938470311105">C7/C6 (Umschlag)</translation>
+<translation id="8220639454292072926">Unternehmensberichte</translation>
<translation id="8225771182978767009">Die Person, die diesen Computer eingerichtet hat, hat diese Website gesperrt.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Seite in einem neuen Inkognito-Tab öffnen</translation>
@@ -1389,24 +1407,24 @@ Weitere Details:
<translation id="8508648098325802031">Symbol "Suche"</translation>
<translation id="8522552481199248698">Mithilfe von Chrome können Sie Ihr Google-Konto schützen und Ihr Passwort ändern.</translation>
<translation id="8543181531796978784">Sie können ein <ph name="BEGIN_ERROR_LINK" />Erkennungsproblem melden<ph name="END_ERROR_LINK" /> oder, wenn Sie die Sicherheitsrisiken kennen, <ph name="BEGIN_LINK" />diese unsichere Website aufrufen<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Fragen? Wenden Sie sich an die Person, die Ihr Profil überwacht.</translation>
<translation id="8553075262323480129">Die Übersetzung ist fehlgeschlagen, weil die Sprache der Seite nicht ermittelt werden konnte.</translation>
<translation id="8557066899867184262">Der CVC befindet sich auf der Rückseite Ihrer Karte.</translation>
<translation id="8559762987265718583">Es kann keine private Verbindung zu <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> hergestellt werden, weil Datum und Uhrzeit Ihres Geräts falsch sind (<ph name="DATE_AND_TIME" />).</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> verdächtige Website</translation>
<translation id="8564985650692024650">Chromium empfiehlt, Ihr Passwort für <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> zurückzusetzen, wenn Sie es auf anderen Websites verwendet haben.</translation>
<translation id="8571890674111243710">Seite wird in folgende Sprache übersetzt: <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Weitere Nummer
</translation>
-<translation id="859285277496340001">In dem Zertifikat ist kein Mechanismus angegeben, mit dem geprüft werden kann, ob es zurückgerufen wurde.</translation>
<translation id="860043288473659153">Name des Karteninhabers</translation>
<translation id="861775596732816396">Größe 4</translation>
-<translation id="8620436878122366504">Deine Eltern haben die Berechtigung noch nicht erteilt</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Diese Karte für dieses Gerät speichern</translation>
<translation id="8626112503828625890">Rechnungsdetails in Google-Konto speichern?</translation>
+<translation id="8647750283161643317">Alle auf Standardeinstellung zurücksetzen</translation>
<translation id="8663226718884576429">Bestellübersicht, <ph name="TOTAL_LABEL" />, weitere Details</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, Antwort, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Verfügbar</translation>
<translation id="8703575177326907206">Die Verbindung zu <ph name="DOMAIN" /> ist nicht verschlüsselt.</translation>
<translation id="8718314106902482036">Zahlung nicht abgeschlossen</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, Suchvorschlag</translation>
@@ -1417,6 +1435,7 @@ Weitere Details:
<translation id="8738058698779197622">Zum Aufbau einer sicheren Verbindung muss die Uhrzeit richtig eingestellt sein. Der Grund hierfür ist, dass Websites sich mithilfe von Zertifikaten identifizieren, die nur für einen bestimmten Zeitraum gelten. Da die Uhrzeit Ihres Geräts falsch ist, kann Chromium diese Zertifikate nicht bestätigen.</translation>
<translation id="8740359287975076522">Die &lt;abbr id="dnsDefinition"&gt;DNS-Adresse&lt;/abbr&gt; von <ph name="HOST_NAME" /> wurde nicht gefunden. Eine Problemdiagnose wird durchgeführt.</translation>
<translation id="874846938927089722">Akzeptierte Kredit- und Prepaidkarten</translation>
+<translation id="874918643257405732">Lesezeichen für diesen Tab erstellen</translation>
<translation id="8759274551635299824">Diese Karte ist abgelaufen</translation>
<translation id="8761567432415473239">Google Safe Browsing hat vor Kurzem <ph name="BEGIN_LINK" />schädliche Programme<ph name="END_LINK" /> auf <ph name="SITE" /> gefunden.</translation>
<translation id="8763927697961133303">USB-Gerät</translation>
@@ -1446,6 +1465,7 @@ Weitere Details:
<translation id="8938939909778640821">Akzeptierte Kredit- und Prepaidkarten</translation>
<translation id="8943282376843390568">Limone</translation>
<translation id="8957210676456822347">Erfassungsportal-Autorisierung</translation>
+<translation id="8962950042226115166">Verdächtige Website</translation>
<translation id="8968766641738584599">Karte speichern</translation>
<translation id="8971063699422889582">Das Serverzertifikat ist abgelaufen.</translation>
<translation id="8975012916872825179">Enthält Informationen wie Telefonnummern, E-Mail-Adressen und Lieferadressen</translation>
@@ -1469,24 +1489,24 @@ Weitere Details:
<translation id="9038649477754266430">Vorhersagefunktion zum schnelleren Laden von Seiten verwenden
</translation>
<translation id="9039213469156557790">Außerdem enthält diese Seite andere, nicht sichere Ressourcen. Diese Ressourcen können während der Übertragung von anderen Nutzern angezeigt und von Angreifern bearbeitet werden, die das Verhalten der Seite verändern.</translation>
+<translation id="9044359186343685026">Touch ID verwenden</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Sie haben versucht, auf <ph name="DOMAIN" /> zuzugreifen, der Server hat sich jedoch mit einem ungültigen Zertifikat ausgewiesen.</translation>
<translation id="9050666287014529139">Passphrase</translation>
<translation id="9065203028668620118">Bearbeiten</translation>
<translation id="9065745800631924235">"<ph name="TEXT" />" im Verlauf suchen</translation>
<translation id="9069693763241529744">Von einer Erweiterung blockiert</translation>
-<translation id="9076283476770535406">Eventuell enthält sie nicht jugendfreie Inhalte</translation>
<translation id="9076630408993835509">Dieser Browser wird nicht von einem Unternehmen oder einer anderen Organisation verwaltet. Aktivitäten auf diesem Gerät werden eventuell außerhalb von Chrome verwaltet. <ph name="BEGIN_LINK" />Weitere Informationen<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Weitere Informationen erforderlich</translation>
<translation id="9080712759204168376">Bestellübersicht</translation>
<translation id="9089260154716455634">Richtlinie für Abwesenheitszeiten:</translation>
<translation id="9095388113577226029">Weitere Sprachen...</translation>
+<translation id="9098981495403789647">Ihr Administrator hat das Chrome Enterprise-Sicherheitssystem für Ihren Browser aktiviert. Das Chrome Enterprise-Sicherheitssystem kann auf manche Ihrer Daten zugreifen.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> schützt Ihre Daten in der Regel durch Verschlüsselung. Als Chromium dieses Mal versuchte, eine Verbindung zu <ph name="SITE" /> herzustellen, gab die Website ungewöhnliche und falsche Anmeldedaten zurück. Entweder versucht ein Angreifer, sich als <ph name="SITE" /> auszugeben, oder die Verbindung wurde durch eine WLAN-Anmeldeseite unterbrochen. Da Chromium die Verbindung vor dem Austausch von Daten unterbrochen hat, sind Ihre Informationen weiterhin sicher.</translation>
<translation id="9106062320799175032">Rechnungsadresse hinzufügen</translation>
<translation id="9114524666733003316">Karte wird bestätigt…</translation>
<translation id="9128870381267983090">Mit Netzwerk verbinden</translation>
<translation id="9137013805542155359">Original anzeigen</translation>
-<translation id="9137248913990643158">Melden Sie sich in Chrome an, bevor Sie diese App nutzen.</translation>
<translation id="9141013498910525015">Adressen verwalten</translation>
<translation id="9148088599418889305">Versandart auswählen</translation>
<translation id="9148507642005240123">&amp;Bearbeiten rückgängig machen</translation>
diff --git a/chromium/components/strings/components_strings_el.xtb b/chromium/components/strings/components_strings_el.xtb
index 4f971ad09f1..3f4f772dc3c 100644
--- a/chromium/components/strings/components_strings_el.xtb
+++ b/chromium/components/strings/components_strings_el.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Προσθήκη ονόματος στην κάρτα</translation>
<translation id="1089439967362294234">Αλλαγή κωδικού πρόσβασης</translation>
+<translation id="1096545575934602868">Αυτό το πεδίο δεν θα πρέπει να έχει περισσότερες από <ph name="MAX_ITEMS_LIMIT" /> καταχωρίσεις. Τυχόν επιπλέον καταχωρίσεις θα απορριφθούν.</translation>
<translation id="109743633954054152">Διαχείριση κωδικών πρόσβασης στις ρυθμίσεις του Chrome</translation>
<translation id="1103523840287552314">Να μεταφράζονται πάντα τα <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Εάν επιλεγεί, το Chrome θα αποθηκεύει ένα αντίγραφο της κάρτας σας σε αυτήν τη συσκευή για ταχύτερη συμπλήρωση φορμών.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Πρόσβαση σε <ph name="BEGIN_LINK" />προσωρινό αντίγραφο<ph name="END_LINK" /> της διεύθυνσης <ph name="URL" /></translation>
<translation id="1156303062776767266">Βλέπετε ένα τοπικό ή κοινόχρηστο αρχείο</translation>
<translation id="1158211211994409885">Ο κεντρικός υπολογιστής <ph name="HOST_NAME" /> τερμάτισε απροσδόκητα τη σύνδεση.</translation>
+<translation id="115926840831309955">Ελέγξτε το CVC και δοκιμάστε ξανά ή ενημερώστε την ημερομηνία λήξης.</translation>
<translation id="1161325031994447685">Επανασυνδεθείτε στο Wi-Fi</translation>
<translation id="1165039591588034296">Σφάλμα</translation>
<translation id="1175364870820465910">&amp;Εκτύπωση...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Κάποιο λογισμικό στον υπολογιστή σας παρεμποδίζει την ασφαλή σύνδεση του Chrome στον ιστό" (μόνο για υπολογιστές με Windows)</translation>
<translation id="1294154142200295408">Παραλλαγές γραμμής εντολών</translation>
<translation id="129553762522093515">Έκλεισαν πρόσφατα</translation>
+<translation id="1298536327547837046">Σάρωση για κακόβουλο λογισμικό</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Δοκιμάστε να διαγράψετε τα cookie σας<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Λειτουργίες που καταργήθηκαν</translation>
<translation id="1320233736580025032">Prc1 (Φάκελος)</translation>
<translation id="132301787627749051">Αναζήτηση εικόνας στο πρόχειρο</translation>
<translation id="1323433172918577554">Εμφάνιση περισσότερων</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Υπολογιστικά φύλλα Google</translation>
<translation id="1527263332363067270">Αναμονή για σύνδεση…</translation>
<translation id="1529521330346880926">10x15 (Φάκελος)</translation>
+<translation id="1530707389502320859">Ο ιστότοπος που προσπαθήσατε μόλις να επισκεφτείτε μοιάζει ψεύτικος. Οι εισβολείς απομιμούνται μερικές φορές ιστοτόπους κάνοντας μικρές, δυσδιάκριτες αλλαγές στο URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Αυτή η σελίδα λέει</translation>
<translation id="153384715582417236">Αυτά προς το παρόν</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Το έγγραφο είναι πάρα πολύ μεγάλο για σχολιασμό.</translation>
-<translation id="1721312023322545264">Για να επισκεφτείτε αυτήν τη σελίδα, χρειάζεστε άδεια από τον διαχειριστή <ph name="NAME" /></translation>
<translation id="1721424275792716183">* Το πεδίο είναι υποχρεωτικό</translation>
<translation id="1727741090716970331">Προσθήκη έγκυρου αριθμού κάρτας</translation>
<translation id="1728677426644403582">Βλέπετε την πηγή μιας ιστοσελίδας</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Οι ιστότοποι που επισκέπτεστε και ο χρόνος χρήσης τους</translation>
<translation id="1826516787628120939">Έλεγχος</translation>
<translation id="1834321415901700177">Αυτός ο ιστότοπος περιέχει κακόβουλα προγράμματα</translation>
+<translation id="1838374766361614909">Διαγραφή αναζητήσεων</translation>
<translation id="1839551713262164453">Η επικύρωση των τιμών πολιτικής απέτυχε αφού παρουσίασε σφάλματα</translation>
<translation id="1842969606798536927">Πληρωμή</translation>
<translation id="1871208020102129563">Ο διακομιστής μεσολάβησης έχει ρυθμιστεί να χρησιμοποιεί διακομιστές μεσολάβησης και όχι μια διεύθυνση URL σεναρίου .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Σύμπτυξη λίστας</translation>
<translation id="1898423065542865115">Φιλτράρισμα</translation>
<translation id="1914326953223720820">Υπηρεσία αποσυμπίεσης</translation>
+<translation id="1915697529809968049">Χρήση Touch ID αντί του CVC;</translation>
<translation id="1916770123977586577">Προκειμένου να εφαρμοστούν οι ενημερωμένες ρυθμίσεις σας σε αυτόν τον ιστότοπο, επαναλάβετε τη φόρτωση αυτής της σελίδες</translation>
<translation id="1919345977826869612">Διαφημίσεις</translation>
<translation id="1919367280705858090">Λήψη βοήθειας για συγκεκριμένο μήνυμα σφάλματος</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Σελιδοδείκτες <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Σφάλμα σειριοποίησης</translation>
<translation id="1974060860693918893">Σύνθετες</translation>
+<translation id="1974883374937189061">Συμβάλετε στη βελτίωση της ασφάλειας του Chrome με την αποστολή <ph name="BEGIN_WHITEPAPER_LINK" />URL από ορισμένες σελίδες που επισκέπτεστε, περιορισμένων πληροφοριών συστήματος και ορισμένου περιεχομένου σελίδας<ph name="END_WHITEPAPER_LINK" /> στην Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Έκδοση υλικολογισμικού</translation>
<translation id="1981206234434200693">Διαγραφή δεδομένων ιστορικού περιήγησης Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{και άλλο 1 άτομο}other{και άλλα # άτομα}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Εισαγάγετε ένα έγκυρο έτος λήξης</translation>
<translation id="2212735316055980242">Η πολιτική δε βρέθηκε</translation>
<translation id="2213606439339815911">Ανάκτηση καταχωρίσεων…</translation>
+<translation id="2215727959747642672">Επεξεργασία αρχείου</translation>
<translation id="2218879909401188352">Οι εισβολείς στον ιστότοπο <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> θα μπορούσαν να εγκαταστήσουν επικίνδυνες εφαρμογές που προκαλούν ζημιά στη συσκευή σας, να προσθέσουν κρυφές χρεώσεις στον λογαριασμό του κινητού σας ή να κλέψουν τα προσωπικά στοιχεία σας. <ph name="BEGIN_LEARN_MORE_LINK" />Μάθετε περισσότερα<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Χωρίς σύνδεση στο διαδίκτυο</translation>
<translation id="2230458221926704099">Επιδιορθώστε τη σύνδεσή σας χρησιμοποιώντας την <ph name="BEGIN_LINK" />εφαρμογή διαγνωστικών ελέγχων<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Αποστολή τώρα</translation>
+<translation id="2248949050832152960">Χρήση WebAuthn</translation>
<translation id="225207911366869382">Αυτή η πολιτική έχει καταργηθεί για τη συγκεκριμένη πολιτική.</translation>
<translation id="2257315177824333709">Δυστυχώς, δεν είναι δυνατή η αποθήκευση της κάρτας σας αυτήν τη στιγμή</translation>
<translation id="2262243747453050782">Σφάλμα HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Μη έγκυρη διεύθυνση URL αναζήτησης.</translation>
<translation id="2482878487686419369">Ειδοποιήσεις</translation>
<translation id="248348093745724435">Πολιτικές συσκευής</translation>
-<translation id="2485387744899240041">Τα ονόματα χρήστη για τη συσκευή και το πρόγραμμα περιήγησής σας</translation>
<translation id="2491120439723279231">Το πιστοποιητικό του διακομιστή περιέχει σφάλματα.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Συντακτικός αναλυτής JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Επιστροφή</translation>
<translation id="2503184589641749290">Αποδεκτές χρεωστικές και προπληρωμένες κάρτες</translation>
<translation id="2505268675989099013">Προστασία λογαριασμού</translation>
+<translation id="2515335152965840738">ΠΑΡΑΒΛΕΨΗ</translation>
<translation id="2515629240566999685">Ελέγξτε το σήμα στην περιοχή σας.</translation>
<translation id="2523886232349826891">Αποθηκεύτηκε μόνο σε αυτήν τη συσκευή</translation>
<translation id="2524461107774643265">Προσθήκη περισσότερων πληροφοριών</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Υποβολή</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Κανένας}=1{1 κωδικός πρόσβασης (για <ph name="DOMAIN_LIST" />)}=2{2 κωδικοί πρόσβασης (για <ph name="DOMAIN_LIST" />)}other{# κωδικοί πρόσβασης (για <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Κλείστε τις άλλες καρτέλες ή εφαρμογές</translation>
-<translation id="267371737713284912">πατήστε <ph name="MODIFIER_KEY_DESCRIPTION" /> για αναίρεση</translation>
<translation id="2674170444375937751">Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτές τις σελίδες από το ιστορικό σας;</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Αποχώρηση</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Η τιμή δεν συμφωνεί με τη μορφή.</translation>
<translation id="2705137772291741111">Δεν είναι δυνατή η ανάγνωση του αποθηκευμένου αντιγράφου (κρυφής μνήμης) αυτού του ιστότοπου.</translation>
<translation id="2709516037105925701">Αυτόματη συμπλήρωση</translation>
-<translation id="2712173769900027643">Να ζητηθεί άδεια</translation>
<translation id="2713444072780614174">Λευκό</translation>
<translation id="2720342946869265578">Σε κοντινή απόσταση</translation>
<translation id="2721148159707890343">Το αίτημα ήταν επιτυχές</translation>
<translation id="2728127805433021124">Το πιστοποιητικό του διακομιστή είναι υπογεγραμμένο με έναν αδύναμο αλγόριθμο υπογραφής.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Να εκτελέσετε τα Διαγνωστικά στοιχεία συνδεσιμότητας<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ενεργοποιώντας αυτές τις λειτουργίες, μπορεί να χάσετε δεδομένα του προγράμματος περιήγησης ή
+ να θέσετε σε κίνδυνο την ασφάλεια ή το απόρρητό σας. Οι ενεργοποιημένες λειτουργίες ισχύουν για
+ όλους τους χρήστες αυτού του προγράμματος περιήγησης.</translation>
<translation id="2735043616039983645">Υπάρχουν πάνω από μία πηγές με τιμές σε διένεξη για αυτήν την πολιτική!</translation>
<translation id="2738330467931008676">Επιλογή διεύθυνσης παραλαβής</translation>
<translation id="2740531572673183784">ΟK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Έγινε επαναφορά της σύνδεσης.</translation>
<translation id="2788784517760473862">Αποδεκτές πιστωτικές κάρτες</translation>
<translation id="2792012897584536778">Οι διαχειριστές αυτής της συσκευής έχουν εγκαταστήσει πιστοποιητικά ασφαλείας που μπορεί να τους επιτρέπουν να βλέπουν το περιεχόμενο των ιστοτόπων που επισκέπτεστε.</translation>
-<translation id="2794233252405721443">Ο ιστότοπος έχει αποκλειστεί</translation>
<translation id="2799020568854403057">Ο ιστότοπος που πρόκειται να επισκεφτείτε περιέχει επιβλαβείς εφαρμογές</translation>
<translation id="2799223571221894425">Επανεκκίνηση</translation>
<translation id="2803306138276472711">Πρόσφατα η Ασφαλής περιήγηση Google <ph name="BEGIN_LINK" />εντόπισε κακόβουλο λογισμικό<ph name="END_LINK" /> στον ιστότοπο <ph name="SITE" />. Οι ιστότοποι που είναι ασφαλείς υπό φυσιολογικές συνθήκες μερικές φορές προσβάλλονται από κακόβουλα λογισμικά.</translation>
+<translation id="2815364696811431560">ΑΠΟΧΩΡΗΣΗ ΑΠΟ ΤΟΝ ΙΣΤΟΤΟΠΟ</translation>
<translation id="2824775600643448204">Γραμμή διευθύνσεων και αναζήτησης</translation>
<translation id="2826760142808435982">Η κρυπτογράφηση και ο έλεγχος ταυτότητας της σύνδεσης γίνονται με <ph name="CIPHER" /> και χρησιμοποιεί το <ph name="KX" /> ως μηχανισμό ανταλλαγής κλειδιών.</translation>
<translation id="2835170189407361413">Διαγραφή φόρμας</translation>
<translation id="2847118875340931228">Άνοιγμα παραθύρου για ανώνυμη περιήγηση</translation>
<translation id="2850739647070081192">Invite (Φάκελος)</translation>
-<translation id="2851634818064021665">Απαιτείται άδεια για να επισκεφτείτε αυτόν τον ιστότοπο</translation>
<translation id="2856444702002559011">Οι εισβολείς ενδέχεται να προσπαθήσουν να υποκλέψουν τα στοιχεία σας από τον ιστότοπο <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (για παράδειγμα, κωδικούς πρόσβασης, μηνύματα ή πιστωτικές κάρτες). <ph name="BEGIN_LEARN_MORE_LINK" />Μάθετε περισσότερα<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Αποθήκευση κάρτας;</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Εάν ενεργοποιηθεί, το Chromium θα αποθηκεύσει ένα αντίγραφο της κάρτας σας σε αυτήν τη συσκευή για ταχύτερη συμπλήρωση φορμών.</translation>
<translation id="2985398929374701810">Εισαγάγετε μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου</translation>
<translation id="2986368408720340940">Ο τρόπος παραλαβής δεν είναι διαθέσιμος. Δοκιμάστε έναν άλλο τρόπο.</translation>
+<translation id="2987034854559945715">Δεν υπάρχουν λειτουργίες που να ταιριάζουν στο ερώτημα</translation>
<translation id="2991174974383378012">Κοινοποίηση σε ιστότοπους</translation>
<translation id="2991571918955627853">Δεν μπορείτε να επισκεφτείτε τον ιστότοπο <ph name="SITE" /> αυτήν τη στιγμή, επειδή ο ιστότοπος χρησιμοποιεί HSTS. Τα σφάλματα δικτύου και οι επιθέσεις είναι συνήθως προσωρινά, συνεπώς αυτή η σελίδα πιθανότατα θα λειτουργήσει αργότερα.</translation>
<translation id="3005723025932146533">Εμφάνιση αποθηκευμένου αντιγράφου</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Λανθασμένος τύπος πολιτικής</translation>
<translation id="3037605927509011580">Όπα! Κάτι πήγε στραβά!</translation>
<translation id="3041612393474885105">Πληροφορίες πιστοποιητικού</translation>
+<translation id="3057676462092457419">Η λειτουργία DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> δεν υποστηρίζεται ακόμη, η λειτουργία έχει οριστεί σε <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Φάκελος)</translation>
<translation id="3061707000357573562">Υπηρεσία ενημέρωσης κώδικα</translation>
<translation id="3064966200440839136">Αποχώρηση από την κατάσταση ανώνυμης περιήγησης για πληρωμή μέσω εξωτερικής εφαρμογής. Συνέχεια;</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> στο <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Ακύρωση πληρωμής</translation>
<translation id="3207960819495026254">Προστέθηκε στους σελιδοδείκτες</translation>
+<translation id="3209034400446768650">Η σελίδα ενδέχεται να σας χρεώσει</translation>
<translation id="3225919329040284222">Ο διακομιστής παρουσίασε ένα πιστοποιητικό που δεν αντιστοιχεί στις ενσωματωμένες προϋποθέσεις. Αυτές οι προϋποθέσεις συμπεριλαμβάνονται σε συγκεκριμένους ιστότοπους υψηλής ασφάλειας για την προστασία σας.</translation>
<translation id="3226128629678568754">Πατήστε το κουμπί της επανάληψης φόρτωσης για να υποβάλετε ξανά τα δεδομένα που απαιτούνται για τη φόρτωση της σελίδας.</translation>
<translation id="3227137524299004712">Μικρόφωνο</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Πληροφορίες έκδοσης σχετικά με τη συσκευή και το πρόγραμμα περιήγησης</translation>
<translation id="323107829343500871">Εισαγάγετε τον κωδικό CVC για την πιστωτική κάρτα <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Να εντοπίζεται πάντα σημαντικό περιεχόμενο σε αυτόν τον ιστότοπο</translation>
-<translation id="3254409185687681395">Προσθήκη αυτής της σελίδας στους σελιδοδείκτες</translation>
<translation id="3270847123878663523">&amp;Αναίρεση αναδιάταξης</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Προσθήκη ονόματος στην κάρτα</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Προσθήκη διεύθυνσης χρέωσης</translation>
<translation id="3324983252691184275">Βαθύ κόκκινο</translation>
<translation id="3338095232262050444">Ασφαλές</translation>
-<translation id="3345135638360864351">Δεν ήταν δυνατή η αποστολή του αιτήματος πρόσβασής σας σε αυτόν τον ιστότοπο σε <ph name="NAME" />. Δοκιμάστε ξανά.</translation>
<translation id="3355823806454867987">Αλλαγή ρυθμίσεων διακομιστή μεσολάβησης...</translation>
<translation id="3361596688432910856">Το Chrome <ph name="BEGIN_EMPHASIS" />δεν θα αποθηκεύει<ph name="END_EMPHASIS" /> τις παρακάτω πληροφορίες:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Απόκρυψη σύνθετων</translation>
<translation id="3467763166455606212">Απαιτείται το όνομα κατόχου κάρτας</translation>
<translation id="3468054117417088249">Αυτήν τη στιγμή είναι ανοιχτή η καρτέλα <ph name="TAB_SWITCH_SUFFIX" />, πατήστε Tab και έπειτα Enter για μετάβαση στην ανοιχτή καρτέλα</translation>
-<translation id="3479539252931486093">Δεν το περιμένατε; <ph name="BEGIN_LINK" />Ενημερώστε μας<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Όχι τώρα</translation>
<translation id="3484560055331845446">Μπορεί να χάσετε την πρόσβαση στον Λογαριασμό σας Google. Το Chrome συνιστά να αλλάξετε τον κωδικό πρόσβασής σας τώρα. Θα σας ζητηθεί να συνδεθείτε.</translation>
<translation id="3495081129428749620">Εύρεση στη σελίδα
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Δεν ήταν δυνατή η επικοινωνία με τον γονέα σας αυτήν τη στιγμή. Δοκιμάστε ξανά.</translation>
<translation id="3512163584740124171">Αυτή η πολιτική αγνοείται επειδή μια άλλη πολιτική από την ίδια ομάδα πολιτικής έχει υψηλότερη προτεραιότητα.</translation>
<translation id="3528171143076753409">Το πιστοποιητικό του διακομιστή δεν είναι αξιόπιστο.</translation>
<translation id="3528485271872257980">Σκούρο καφέ</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Τουλάχιστον ένα στοιχείο στις συγχρονισμένες συσκευές}=1{1 στοιχείο (και περισσότερα στις συγχρονισμένες συσκευές)}other{# στοιχεία (και περισσότερα στις συγχρονισμένες συσκευές)}}</translation>
<translation id="3539171420378717834">Διατήρηση αντιγράφου αυτής της κάρτας σε αυτήν τη συσκευή</translation>
-<translation id="3556433843310711081">Ο διαχειριστής σας μπορεί να καταργήσει τον αποκλεισμό του για εσάς</translation>
<translation id="3566021033012934673">Η σύνδεσή σας δεν είναι ιδιωτική</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Μια ενσωματωμένη σελίδα στον ιστότοπο <ph name="SITE" /> λέει</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Ανοίξτε τη σελίδα σε ένα νέο παράθυρο ανώνυμης περιήγησης (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Η αναφορά σφαλμάτων καταγράφηκε στις <ph name="CRASH_TIME" /> και μεταφορτώθηκε στις <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Πληροφορίες πιστοποιητικού</translation>
+<translation id="3701427423622901115">Έγινε επιβεβαίωση της επαναφοράς.</translation>
<translation id="3704162925118123524">Το δίκτυο που χρησιμοποιείτε ενδέχεται να σας ζητήσει να επισκεφτείτε τη σελίδα σύνδεσης του.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Φόρτωση...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Οι εισβολείς σε αυτόν τον ιστότοπο <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> μπορεί να σας εξαπατήσουν και να κάνετε κάτι επικίνδυνο, όπως να εγκαταστήσετε κάποιο λογισμικό ή να αποκαλύψετε προσωπικά σας στοιχεία (για παράδειγμα, κωδικούς πρόσβασης, αριθμούς τηλεφώνου ή στοιχεία πιστωτικών καρτών). <ph name="BEGIN_LEARN_MORE_LINK" />Μάθετε περισσότερα<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Η μετάφραση απέτυχε λόγω σφάλματος διακομιστή.</translation>
<translation id="3759461132968374835">Δεν έχετε πρόσφατα αναφερθέντα σφάλματα. Τα σφάλματα που προέκυψαν όταν η αναφορά σφαλμάτων ήταν απενεργοποιημένη δεν θα εμφανιστούν εδώ.</translation>
+<translation id="3760561303380396507">Χρήση Windows Hello αντί του CVC;</translation>
<translation id="3761718714832595332">Απόκρυψη κατάστασης</translation>
<translation id="3765032636089507299">Η σελίδα Ασφαλούς περιήγησης είναι υπό κατασκευή.</translation>
<translation id="3778403066972421603">Θέλετε να αποθηκεύσετε αυτήν την κάρτα στον Λογαριασμό σας Google και σε αυτήν τη συσκευή;</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Μέγεθος 16</translation>
<translation id="3797522431967816232">Prc3 (Φάκελος)</translation>
<translation id="3807873520724684969">Το επιβλαβές περιεχόμενο αποκλείστηκε.</translation>
+<translation id="3808375843007691220">Προειδοποίηση: Ακολουθούν πειραματικές λειτουργίες!</translation>
<translation id="3810973564298564668">Διαχείριση</translation>
<translation id="382518646247711829">Εάν χρησιμοποιείτε διακομιστή μεσολάβησης…</translation>
<translation id="3828924085048779000">Δεν επιτρέπεται να είναι κενή η φράση πρόσβασης.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Ενημέρωση ημερομηνίας και ώρας</translation>
<translation id="3884278016824448484">Αναγνωριστικό συσκευής που προκαλεί διένεξη</translation>
<translation id="3885155851504623709">Ενορία</translation>
-<translation id="3886446263141354045">Το αίτημά σας για να αποκτήσετε πρόσβαση σε αυτόν τον ιστότοπο έχει σταλεί στον/η(ν) <ph name="NAME" /></translation>
<translation id="3890664840433101773">Προσθήκη διεύθυνσης ηλεκτρονικού ταχυδρομείου</translation>
<translation id="3901925938762663762">Η κάρτα έχει λήξει</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Χρήση WebAuthn αντί του CVC;</translation>
<translation id="3946209740501886391">Να γίνεται πάντα ερώτηση σε αυτόν τον ιστότοπο</translation>
<translation id="3949571496842715403">Αυτός ο διακομιστής δεν μπορεί να αποδείξει ότι είναι ο τομέας <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας δεν προσδιορίζει Εναλλακτικά ονόματα θέματος. Αυτό μπορεί να οφείλεται σε εσφαλμένη διαμόρφωση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
<translation id="3949601375789751990">Το ιστορικό περιήγησής σας εμφανίζεται εδώ</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Κανένα}=1{Από 1 ιστότοπο }other{Από # ιστοτόπους }}</translation>
<translation id="397105322502079400">Υπολογισμός…</translation>
<translation id="3973234410852337861">Ο κεντρικός υπολογιστής <ph name="HOST_NAME" /> είναι αποκλεισμένος</translation>
+<translation id="3981540111851280311">Ο τομέας <ph name="ENROLLMENT_DOMAIN" /> έχει ενεργοποιήσει την Προστασία από απειλές του Chrome για Επιχειρήσεις στο πρόγραμμά περιήγησής σας. Η Προστασία από απειλές του Chrome για Επιχειρήσεις έχει πρόσβαση σε ορισμένα από τα δεδομένα σας.</translation>
<translation id="3987940399970879459">Λιγότερα από 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 ιστοσελίδα σε κοντινή απόσταση}other{# ιστοσελίδες σε κοντινή απόσταση}}</translation>
<translation id="4030383055268325496">&amp;Αναίρεση προσθήκης</translation>
<translation id="4032320456957708163">Το πρόγραμμα περιήγησής σας είναι διαχειριζόμενο από τον τομέα <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Ο σύνδεσμος που ανοίξατε οδηγεί σε έναν ιστότοπο που δεν επισκέπτεστε συχνά. Πιθανώς, να προσπαθεί να σας προκαλέσει σύγχυση.</translation>
<translation id="4058922952496707368">Κλειδί "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Φάκελος)</translation>
<translation id="4067947977115446013">Προσθήκη έγκυρης διεύθυνσης</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Ο σειριακός αριθμός της συσκευής δεν είναι έγκυρος</translation>
<translation id="410351446219883937">Αυτ. αναπαραγωγή</translation>
<translation id="4103763322291513355">Επισκεφτείτε την &lt;strong&gt;chrome://policy&lt;/strong&gt; για να δείτε τη λίστα των ανεπιθύμητων διευθύνσεων URL και άλλες πολιτικές που έχουν τεθεί σε εφαρμογή από το διαχειριστή του συστήματός σας.</translation>
+<translation id="4108231218301530806">Την επόμενη φορά να χρησιμοποιηθεί μοναδικό χαρακτηριστικό για την επαλήθευση αυτής της κάρτας.</translation>
<translation id="4110652170750985508">Έλεγχος πληρωμής</translation>
<translation id="4112140312785995938">Αναζήτηση προς τα πίσω</translation>
<translation id="4116663294526079822">Να επιτρέπεται πάντα σε αυτόν τον ιστότοπο</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Εσφαλμένη υπογραφή επαλήθευσης</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> ακόμη στοιχείο}other{<ph name="ITEM_COUNT" /> ακόμη στοιχεία}}</translation>
+<translation id="4176463684765177261">Απενεργοποιημένη</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Για πιο γρήγορες πληρωμές, προσθέστε τα στοιχεία της κάρτας και τη διεύθυνση χρέωσης στον Λογαριασμό σας Google.</translation>
<translation id="4196861286325780578">&amp;Επανάληψη μετακίνησης</translation>
@@ -633,6 +645,7 @@
<translation id="4277028893293644418">Επαναφορά κωδικού πρόσβασης</translation>
<translation id="4279811152705618813">Η συσκευή <ph name="DEVICE_TYPE" /> είναι διαχειριζόμενη από τον οργανισμό <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Αυτή η κάρτα αποθηκεύτηκε στον Λογαριασμό σας Google}other{Αυτές οι κάρτες αποθηκεύτηκαν στον Λογαριασμό σας Google}}</translation>
+<translation id="428847186335018806">Σάρωση των αρχείων που κατεβάζετε ή ανεβάζετε στο Chrome.</translation>
<translation id="42981349822642051">Επέκταση</translation>
<translation id="4302965934281694568">Chou3 (Φάκελος)</translation>
<translation id="4305817255990598646">Εναλλαγή</translation>
@@ -662,7 +675,6 @@
<translation id="4435702339979719576">Ταχυδρομική κάρτα)</translation>
<translation id="443673843213245140">Η χρήση ενός διακομιστή μεσολάβησης είναι απενεργοποιημένη, αλλά έχει καθοριστεί μια ρητή διαμόρφωση διακομιστή μεσολάβησης.</translation>
<translation id="445100540951337728">Αποδεκτές χρεωστικές κάρτες</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> ύποπτη συμπεριφορά</translation>
<translation id="4466881336512663640">Οι αλλαγές που πραγματοποιήθηκαν στη φόρμα θα χαθούν. Είστε βέβαιοι ότι θέλετε να συνεχίσετε;</translation>
<translation id="4477350412780666475">Επόμενο κομμάτι</translation>
<translation id="4482953324121162758">Αυτός ο ιστότοπος δεν θα μεταφραστεί.</translation>
@@ -689,6 +701,7 @@
<translation id="4594403342090139922">&amp;Αναίρεση διαγραφής</translation>
<translation id="4597348597567598915">Μέγεθος 8</translation>
<translation id="4600854749408232102">C6/C5 (Φάκελος)</translation>
+<translation id="464342062220857295">Λειτουργίες αναζήτησης</translation>
<translation id="4646534391647090355">Μετάβαση εκεί τώρα</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Ο διακομιστής δεν κατάφερε να αποδείξει ότι είναι <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του περιέχει σφάλματα. Αυτό μπορεί να οφείλεται σε λανθασμένη ρύθμιση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
@@ -697,7 +710,6 @@
<translation id="4691835149146451662">Architecture-A (Φάκελος)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Η σύνδεσή σας διακόπηκε</translation>
-<translation id="471880041731876836">Δεν έχετε άδεια να επισκεφτείτε αυτόν τον ιστότοπο</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Να εκτελέσετε τον Διαγνωστικό έλεγχο δικτύου των Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Επανάληψη φόρτωσης πολιτικών</translation>
<translation id="4728558894243024398">Πλατφόρμα</translation>
@@ -725,7 +737,6 @@
<translation id="4816492930507672669">Προσαρμογή στη σελίδα</translation>
<translation id="4850886885716139402">Προβολή</translation>
<translation id="4854362297993841467">Αυτός ο τρόπος παράδοσης δεν είναι διαθέσιμος. Δοκιμάστε έναν άλλο τρόπο.</translation>
-<translation id="4858792381671956233">Ρώτησες τους γονείς σου εάν σου επιτρέπουν να επισκεφτείς αυτόν τον ιστότοπο</translation>
<translation id="4864052566555297930">Συμβουλή ασφαλείας:</translation>
<translation id="4876188919622883022">Απλοποιημένη προβολή</translation>
<translation id="4876305945144899064">Δεν υπάρχει όνομα χρήστη</translation>
@@ -749,7 +760,9 @@
<translation id="4974590756084640048">Επανενεργοποίηση προειδοποιήσεων</translation>
<translation id="4984339528288761049">Prc5 (Φάκελος)</translation>
<translation id="4989163558385430922">Εμφάνιση όλων</translation>
+<translation id="4989542687859782284">Μη διαθέσιμο</translation>
<translation id="4989809363548539747">Αυτή η προσθήκη δεν υποστηρίζεται</translation>
+<translation id="4995216769782533993">Επιβεβαιώστε τον κωδικό ασφαλείας για να μοιραστείτε τις λεπτομέρειες της κάρτας σας με αυτόν τον ιστότοπο.</translation>
<translation id="5002932099480077015">Εάν ενεργοποιηθεί, το Chrome θα αποθηκεύσει ένα αντίγραφο της κάρτας σας σε αυτήν τη συσκευή για ταχύτερη συμπλήρωση φορμών.</translation>
<translation id="5015510746216210676">Όνομα συσκευής:</translation>
<translation id="5017554619425969104">Κείμενο που αντιγράψατε</translation>
@@ -778,6 +791,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Επαλήθευση κάρτας</translation>
<translation id="5135404736266831032">Διαχείριση διευθύνσεων…</translation>
<translation id="5138227688689900538">Εμφάνιση λιγότερων</translation>
<translation id="5141240743006678641">Κρυπτογραφήστε συγχρονισμένους κωδικούς πρόσβασης με τα διαπιστευτήριά σας Google.</translation>
@@ -804,6 +818,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Φάκελος)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Οι λειτουργίες που ισχύουν για ολόκληρο το σύστημα μπορούν να οριστούν μόνο από τον κάτοχο: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Προειδοποίηση: Αυτή η πολιτική δεν συγχωνεύτηκε, όπως ορίζεται στην πολιτική PolicyDictionaryMultipleSourceMergeList, επειδή δεν ανήκει στις πολιτικές λεξικού που μπορούν να συγχωνευτούν.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Τέλος</translation>
@@ -827,7 +842,6 @@
<translation id="536296301121032821">Αποτυχία αποθήκευσης ρυθμίσεων πολιτικής</translation>
<translation id="5371425731340848620">Ενημέρωση κάρτας</translation>
<translation id="5377026284221673050">"Το ρολόι σας πάει πίσω" ή "Το ρολόι σας πάει μπροστά" ή "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Αυτή η σελίδα ίσως προσπαθήσει να σας εξαπατήσει, να κλέψει τα προσωπικά σας στοιχεία ή να βλάψει τη συσκευή σας. Να είστε προσεκτικοί κατά την εισαγωγή προσωπικών στοιχείων ή κατά το άνοιγμα ληφθέντων αρχείων.</translation>
<translation id="5384855140246857529">Για να χρησιμοποιείτε τις κάρτες σας σε όλες τις συσκευές, συνδεθείτε και ενεργοποιήστε τον συγχρονισμό.</translation>
<translation id="5386426401304769735">Η αλυσίδα πιστοποιητικού για αυτόν τον ιστότοπο περιέχει ένα πιστοποιητικό το οποίο είναι υπογεγραμμένο με χρήση SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -841,6 +855,8 @@
<translation id="5457113250005438886">Μη έγκυρο</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ακόμη}other{<ph name="CONTACT_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ακόμη}}</translation>
<translation id="5470861586879999274">&amp;Επανάληψη επεξεργασίας</translation>
+<translation id="5473728911100096288">Ενεργοποιώντας αυτές τις λειτουργίες, θα χρησιμοποιείτε λειτουργίες που έχουν καταργηθεί
+ και θα εξαφανιστούν σε μελλοντικές εκδόσεις.</translation>
<translation id="5478437291406423475">B6/C4 (Φάκελος)</translation>
<translation id="5481076368049295676">Αυτό το περιεχόμενο μπορεί να προσπαθήσει να εγκαταστήσει επικίνδυνο λογισμικό στη συσκευή σας το οποίο κλέβει ή διαγράφει τα στοιχεία σας. <ph name="BEGIN_LINK" />Εμφάνιση ούτως ή άλλως<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Προσθήκη έγκυρης διεύθυνσης</translation>
@@ -864,7 +880,6 @@
<translation id="5570825185877910964">Προστασία λογαριασμού</translation>
<translation id="5571083550517324815">Δεν είναι δυνατή η παραλαβή από αυτήν τη διεύθυνση. Επιλέξτε μια άλλη διεύθυνση.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 σε χρήση}other{# σε χρήση}})</translation>
-<translation id="5572851009514199876">Εκκινήστε και συνδεθείτε στο Chrome, έτσι ώστε το Chrome να μπορεί να ελέγξει εάν έχετε δικαίωμα πρόσβασης σε αυτόν τον ιστότοπο.</translation>
<translation id="5580958916614886209">Ελέγξτε τον μήνα λήξης σας και δοκιμάστε ξανά</translation>
<translation id="5586446728396275693">Δεν υπάρχουν αποθηκευμένες διευθύνσεις</translation>
<translation id="5595485650161345191">Επεξεργασία διεύθυνσης</translation>
@@ -872,6 +887,7 @@
<translation id="560412284261940334">Η διαχείριση δεν υποστηρίζεται</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Αυτός ο ιστότοπος μπορεί να είναι ψεύτικος ή μη νόμιμος. Το Chrome συνιστά να αποχωρήσετε τώρα.</translation>
<translation id="5610142619324316209">Ελέγξτε τη σύνδεση</translation>
<translation id="5610807607761827392">Μπορείτε να διαχειριστείτε τις κάρτες και τις διευθύνσεις στις <ph name="BEGIN_LINK" />Ρυθμίσεις<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Ο κεντρικός υπολογιστής <ph name="HOST_NAME" /> έκανε πάρα πολλές ανακατευθύνσεις.</translation>
@@ -895,11 +911,11 @@
<translation id="5720705177508910913">Τρέχων χρήστης</translation>
<translation id="5728056243719941842">C5 (Φάκελος)</translation>
<translation id="5730040223043577876">Το Chrome συνιστά την επαναφορά του κωδικού πρόσβασης, εάν τον έχετε χρησιμοποιήσει και σε άλλους ιστοτόπους.</translation>
-<translation id="5732392974455271431">Οι γονείς σου μπορούν να καταργήσουν τον αποκλεισμό του</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Αποθήκευση κάρτας στον Λογαριασμό Google}other{Αποθήκευση καρτών στον Λογαριασμό Google}}</translation>
<translation id="5763042198335101085">Εισαγάγετε μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου</translation>
<translation id="5765072501007116331">Για να δείτε τρόπους και απαιτήσεις παράδοσης, επιλέξτε μια διεύθυνση</translation>
<translation id="5778550464785688721">Πλήρης έλεγχος συσκευών MIDI</translation>
+<translation id="5781136890105823427">Το πείραμα ενεργοποιήθηκε</translation>
<translation id="578305955206182703">Καφεκίτρινο</translation>
<translation id="57838592816432529">Σίγαση</translation>
<translation id="5784606427469807560">Παρουσιάστηκε κάποιο πρόβλημα κατά την επιβεβαίωση της κάρτας σας. Ελέγξτε τη σύνδεσή σας στο διαδίκτυο και δοκιμάστε ξανά.</translation>
@@ -916,13 +932,16 @@
<translation id="5860033963881614850">Απενεργοποιημένη</translation>
<translation id="5863847714970149516">Η σελίδα που ακολουθεί μπορεί να προσπαθήσει να σας χρεώσει</translation>
<translation id="5866257070973731571">Προσθήκη αριθμού τηλεφώνου</translation>
+<translation id="5866898949289125849">Προβάλετε μια σελίδα εργαλείων προγραμματιστή.</translation>
<translation id="5869405914158311789">Δεν είναι δυνατή η πρόσβαση σε αυτόν τον ιστότοπο</translation>
<translation id="5869522115854928033">Αποθηκευμένοι κωδικοί πρόσβασης</translation>
<translation id="5887400589839399685">Η κάρτα αποθηκεύτηκε</translation>
<translation id="5893752035575986141">Οι πιστωτικές κάρτες γίνονται δεκτές.</translation>
+<translation id="5895138241574237353">Επανεκκίνηση</translation>
<translation id="5901630391730855834">Κίτρινο</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (συγχρονισμένο)</translation>
<translation id="5916664084637901428">Ενεργό</translation>
+<translation id="59174027418879706">Ενεργοποιημένο</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Αποθήκευση κάρτας στον Λογαριασμό Google;</translation>
<translation id="5922853866070715753">Σχεδόν ολοκληρώθηκε</translation>
@@ -956,6 +975,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Χρήση των καρτών σας σε όλες τις συσκευές σας;</translation>
<translation id="6059925163896151826">Συσκευές USB</translation>
+<translation id="6060009363608157444">Μη έγκυρη λειτουργία DnsOverHttps.</translation>
<translation id="6080696365213338172">Η πρόσβασή σας στο περιεχόμενο πραγματοποιήθηκε με τη χρήση ενός πιστοποιητικού που παρασχέθηκε από διαχειριστή. Τα δεδομένα που παρέχετε στο <ph name="DOMAIN" /> μπορεί να ελέγχονται από το διαχειριστή σας.</translation>
<translation id="6094273045989040137">Σχολιασμός</translation>
<translation id="610911394827799129">Ο Λογαριασμός Google ενδέχεται να διαθέτει άλλες μορφές ιστορικού περιήγησης στη διεύθυνση <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1004,13 +1024,12 @@
<translation id="6404511346730675251">Επεξεργασία σελιδοδείκτη</translation>
<translation id="6406765186087300643">C0 (Φάκελος)</translation>
<translation id="6410264514553301377">Εισαγάγετε την ημερομηνία λήξης και τον κωδικό CVC για την κάρτα <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Ρώτησες τους γονείς σου εάν σου επιτρέπουν να επισκεφτείς αυτόν τον ιστότοπο</translation>
<translation id="6415778972515849510">Το Chromium μπορεί να σας βοηθήσει να προστατεύσετε τον Λογαριασμό σας Google και να αλλάξετε τον κωδικό πρόσβασής σας.</translation>
-<translation id="6417515091412812850">Δεν είναι δυνατόν να ελεγχθεί αν το πιστοποιητικό έχει ακυρωθεί.</translation>
<translation id="6431585503458005759">Να μην αποθηκευτεί</translation>
<translation id="6433490469411711332">Επεξεργασία στοιχείων επαφής</translation>
<translation id="6433595998831338502">Ο κεντρικός υπολογιστής <ph name="HOST_NAME" /> απέρριψε τη σύνδεση.</translation>
<translation id="6434309073475700221">Απόρριψη</translation>
+<translation id="6435221585574090192">Κοινοποίηση δεδομένων σχετικά με συμβάντα ασφαλείας που έχουν επισημανθεί από την Προστασία από απειλές του Chrome για Επιχειρήσεις στον Διαχειριστή σας. Αυτά μπορεί να περιλαμβάνουν URL σελίδων, το όνομα αρχείου και τα μεταδεδομένα αρχείου, το όνομα χρήστη της συσκευής σας και το όνομα χρήστη Chrome.</translation>
<translation id="6440503408713884761">Αγνοείται</translation>
<translation id="6446163441502663861">Kahu (Φάκελος)</translation>
<translation id="6446608382365791566">Προσθήκη περισσότερων πληροφοριών</translation>
@@ -1019,20 +1038,19 @@
<translation id="6465306955648956876">Διαχείριση κωδικών πρόσβασης…</translation>
<translation id="647261751007945333">Πολιτικές συσκευών </translation>
<translation id="6476284679642588870">Διαχείριση τρόπων πληρωμής</translation>
-<translation id="6477321094435799029">Το Chrome εντόπισε ασυνήθιστο κώδικα σε αυτήν τη σελίδα και τον απέκλεισε για να προστατεύσει τα προσωπικά σας στοιχεία (για παράδειγμα, κωδικούς πρόσβασης, αριθμούς τηλεφώνου ή πιστωτικές κάρτες).</translation>
<translation id="6489534406876378309">Έναρξη μεταφόρτωσης σφαλμάτων</translation>
<translation id="6499038740797743453">Επαναφορά κωδικού πρόσβασης;</translation>
<translation id="6507833130742554667">Οι πιστωτικές και οι χρεωστικές κάρτες γίνονται δεκτές.</translation>
<translation id="650855688985305916">Ναι, να αποθηκευτεί</translation>
<translation id="6508722015517270189">Επανεκκινήστε το Chrome</translation>
<translation id="6517596291481585650">Προειδοποίηση: Αυτή η πολιτική δεν συγχωνεύτηκε ως λίστα, όπως ορίζεται από την πολιτική, επειδή δεν είναι λίστα.</translation>
+<translation id="6518133107902771759">Επαλήθευση</translation>
<translation id="6521745193039995384">Ανενεργή</translation>
<translation id="6529602333819889595">&amp;Επανάληψη διαγραφής</translation>
<translation id="6534179046333460208">Προτάσεις Φυσικού δικτύου</translation>
<translation id="6545864417968258051">Σάρωση Bluetooth</translation>
<translation id="6554795675067793129">Η διαχείριση του λογαριασμού σας γίνεται από τον τομέα <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Επανάληψη ενέργειας</translation>
-<translation id="6563469144985748109">Ο διαχειριστής σας δεν τον έχει εγκρίνει ακόμα</translation>
<translation id="6569060085658103619">Βλέπετε μια σελίδα επέκτασης</translation>
<translation id="6578796323535178455">C2 (Φάκελος)</translation>
<translation id="6579990219486187401">Ανοιχτό ροζ</translation>
@@ -1050,11 +1068,13 @@
<translation id="6643016212128521049">Διαγραφή</translation>
<translation id="6644283850729428850">Αυτή η πολιτική έχει αποσυρθεί.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Κανένας}=1{Από 1 ιστότοπο (δεν θα αποσυνδεθείτε από τον Λογαριασμό σας Google)}other{Από # ιστοτόπους (δεν θα αποσυνδεθείτε από τον Λογαριασμό σας Google)}}</translation>
+<translation id="6652101503459149953">Χρήση Windows Hello</translation>
<translation id="6657585470893396449">Κωδικός πρόσβασης</translation>
<translation id="6670613747977017428">Επιστροφή στην ασφάλεια.</translation>
<translation id="6671697161687535275">Να καταργηθεί η πρόταση φόρμας από το Chromium;</translation>
<translation id="6685834062052613830">Αποσυνδεθείτε και ολοκληρώστε την εγκατάσταση</translation>
<translation id="6689271823431384964">Το Chrome προσφέρεται να αποθηκεύσει τις κάρτες σας στον Λογαριασμό σας Google, επειδή έχετε συνδεθεί. Μπορείτε να αλλάξετε αυτήν τη συμπεριφορά στις ρυθμίσεις. Το όνομα του κατόχου κάρτας προέρχεται από τον λογαριασμό σας.</translation>
+<translation id="6707256370811247129">Σάρωση των περιεχομένων της κρυφής μνήμης και των αρχείων που κατεβάζετε ή ανεβάζετε στο Chrome.</translation>
<translation id="6710213216561001401">Προηγούμενο</translation>
<translation id="6710594484020273272">&lt;Πληκτρολογήστε όρο αναζήτησης&gt;</translation>
<translation id="671076103358959139">Διακριτικό εγγραφής:</translation>
@@ -1062,10 +1082,10 @@
<translation id="6738516213925468394">Τα δεδομένα σας κρυπτογραφήθηκαν με τη <ph name="BEGIN_LINK" />φράση πρόσβασης συγχρονισμού<ph name="END_LINK" /> στις <ph name="TIME" />. Καταχωρίστε την, για να ξεκινήσει ο συγχρονισμός.</translation>
<translation id="674375294223700098">Άγνωστο σφάλμα πιστοποιητικού διακομιστή</translation>
<translation id="6744009308914054259">Ενώ περιμένετε για την επίτευξη κάποιας σύνδεσης, μπορείτε να μεταβείτε στις Λήψεις, για να διαβάσετε άρθρα εκτός σύνδεσης.</translation>
+<translation id="6747611005629681221">Προειδοποίηση: Ακολουθούν λειτουργίες που καταργήθηκαν!</translation>
<translation id="6753269504797312559">Τιμή πολιτικής</translation>
<translation id="6757797048963528358">Η συσκευή σας τέθηκε σε αδράνεια.</translation>
<translation id="6768213884286397650">Hagaki (Ταχυδρομική κάρτα)</translation>
-<translation id="6778737459546443941">Ο γονέας σου δεν τον έχει εγκρίνει ακόμα</translation>
<translation id="67862343314499040">Βιολετί</translation>
<translation id="6786747875388722282">Επεκτάσεις</translation>
<translation id="6790428901817661496">Αναπαραγωγή</translation>
@@ -1073,6 +1093,7 @@
<translation id="681021252041861472">Υποχρεωτικό πεδίο</translation>
<translation id="6810899417690483278">Αναγνωριστικό προσαρμογής</translation>
<translation id="6825578344716086703">Προσπαθήσατε να μεταβείτε στον τομέα <ph name="DOMAIN" />, αλλά ο διακομιστής παρουσίασε ένα πιστοποιητικό το οποίο ήταν υπογεγραμμένο με έναν αδύναμο αλγόριθμο υπογραφής (όπως SHA-1). Αυτό σημαίνει ότι μπορεί να έχουν πλαστογραφηθεί τα διαπιστευτήρια ασφαλείας που επέδειξε ο διακομιστής και ότι αυτός ο διακομιστής ενδέχεται να μην είναι αυτό που αναμένετε (ενδέχεται να επικοινωνείτε με έναν εισβολέα).</translation>
+<translation id="6826370046007623921">Πρόληψη απώλειας δεδομένων (DLP)</translation>
<translation id="6831043979455480757">Μετάφραση</translation>
<translation id="6839929833149231406">Περιοχή</translation>
<translation id="6852204201400771460">Επανάληψη φόρτωσης εφαρμογής;</translation>
@@ -1085,7 +1106,6 @@
<translation id="6891596781022320156">Το επίπεδο πολιτικής δεν υποστηρίζεται.</translation>
<translation id="6895330447102777224">Η κάρτα σας επιβεβαιώθηκε</translation>
<translation id="6897140037006041989">Παράγοντας χρήστη</translation>
-<translation id="6903319715792422884">Συμβάλετε στη βελτίωση της Ασφαλούς περιήγησης στέλνοντας ορισμένες <ph name="BEGIN_WHITEPAPER_LINK" />πληροφορίες συστήματος και περιεχόμενο σελίδων<ph name="END_WHITEPAPER_LINK" /> στην Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Χρήστης</translation>
<translation id="6934672428414710184">Αυτό το όνομα προέρχεται από τον Λογαριασμό σας Google</translation>
<translation id="6944692733090228304">Καταχωρίσατε τον κωδικό πρόσβασής σας σε έναν ιστότοπο τον οποίο δεν διαχειρίζεται ο οργανισμός <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Για να προστατεύσετε τον λογαριασμό σας, μην χρησιμοποιήσετε ξανά αυτόν τον κωδικό πρόσβασης σε άλλες εφαρμογές και ιστότοπους.</translation>
@@ -1130,6 +1150,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ακόμη}other{<ph name="PAYMENT_METHOD_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ακόμη}}</translation>
<translation id="7153618581592392745">Λιλά</translation>
<translation id="717330890047184534">Αναγνωριστικό Gaia:</translation>
+<translation id="7174545416324379297">Έγινε συγχώνευση</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ακόμη}other{<ph name="SHIPPING_OPTION_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ακόμη}}</translation>
<translation id="7177397715882417099">Ο διακομιστής στον οποίο μεταβαίνετε, <ph name="ORIGIN" />, έχει ζητήσει να εφαρμόζεται
μια πολιτική ασφαλείας σε όλα τα αιτήματα προς αυτόν. Αλλά αντί να
@@ -1167,6 +1188,7 @@
<translation id="7320336641823683070">Βοήθεια σύνδεσης</translation>
<translation id="733354035281974745">Παράκαμψη τοπικού λογαριασμού συσκευής</translation>
<translation id="7334320624316649418">&amp;Επανάληψη αναδιάταξης</translation>
+<translation id="7337706099755338005">Δεν είναι διαθέσιμο στην πλατφόρμα σας.</translation>
<translation id="733923710415886693">Το πιστοποιητικό του διακομιστή δεν αποκαλύφθηκε μέσω της Διαφάνειας πιστοποιητικών.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Είναι συνδεδεμένος:</translation>
@@ -1198,7 +1220,6 @@
<translation id="7440140511386898319">Αναζήτηση εκτός σύνδεσης</translation>
<translation id="7441627299479586546">Εσφαλμένο θέμα πολιτικής</translation>
<translation id="7442725080345379071">Ανοιχτό πορτοκαλί</translation>
-<translation id="7444046173054089907">Αυτός ο ιστότοπος είναι αποκλεισμένος</translation>
<translation id="7445762425076701745">Η ταυτότητα του διακομιστή στον οποίο έχετε συνδεθεί δεν μπορεί να επικυρωθεί πλήρως. Είστε συδεδεμένοι σε ένα διακομιστή χρησιμοποιώντας ένα όνομα που είναι έγκυρο μόνο εντός του δικτύου σας, την κατοχή του οποίου δεν έχει τρόπο να επικυρώσει μια εξωτερική αρχή πιστοποίησης. Καθώς ορισμένες αρχές πιστοποιητικών εκδίδουν πιστοποιητικά για αυτά τα ονόματα ούτως ή άλλως, δεν υπάρχει τρόπος να βεβαιωθείτε ότι είστε συνδεδεμένοι στον ιστότοπο που επιθυμείτε και όχι σε έναν εισβολέα.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Να μάθετε περισσότερα<ph name="END_LINK" /> σχετικά με αυτό το πρόβλημα.</translation>
<translation id="7455133967321480974">Χρήση καθολικής προεπιλεγμένης ρύθμισης (Αποκλεισμός)</translation>
@@ -1220,9 +1241,9 @@
<translation id="7538364083937897561">A2 (Φάκελος)</translation>
<translation id="7542403920425041731">Μετά την επιβεβαίωση, τα στοιχεία της κάρτας θα κοινοποιηθούν σε αυτόν τον ιστότοπο.</translation>
<translation id="7542995811387359312">Η αυτόματη συμπλήρωση πιστωτικής κάρτας έχει απενεργοποιηθεί, επειδή αυτή η φόρμα δεν χρησιμοποιεί ασφαλή σύνδεση.</translation>
-<translation id="7543525346216957623">Ζητήστε την άδεια του γονέα σας</translation>
<translation id="7548892272833184391">Διόρθωση σφαλμάτων σύνδεσης</translation>
<translation id="7549584377607005141">Για τη σωστή εμφάνιση αυτής της ιστοσελίδας, απαιτούνται δεδομένα που καταχωρίσατε νωρίτερα. Μπορείτε να αποστείλετε ξανά αυτά τα δεδομένα, ωστόσο, έτσι θα επαναλάβετε κάθε ενέργεια που εκτέλεσε νωρίτερα αυτή η σελίδα.</translation>
+<translation id="7550637293666041147">Το όνομα χρήστη της συσκευής σας και το όνομα χρήστη Chrome</translation>
<translation id="7552846755917812628">Δοκιμάστε τις παρακάτω συμβουλές:</translation>
<translation id="7554791636758816595">Νέα καρτέλα</translation>
<translation id="7564049878696755256">Μπορεί να χάσετε την πρόσβαση στον λογαριασμό σας <ph name="ORG_NAME" /> ή να πέσετε θύμα κλοπής στοιχείων ταυτότητας. Το Chrome συνιστά να αλλάξετε τον κωδικό πρόσβασής σας τώρα.</translation>
@@ -1237,6 +1258,7 @@
<translation id="7610193165460212391">Η τιμή είναι εκτός του εύρους τιμών <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Λήξη: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Έχετε ήδη δεδομένα που είναι κρυπτογραφημένα με χρήση διαφορετικής έκδοσης του κωδικού πρόσβασης για τον Λογαριασμό σας Google. Εισαγάγετέ τον παρακάτω.</translation>
+<translation id="7625784245512586808">Προστασία από απειλές του Chrome για Επιχειρήσεις</translation>
<translation id="7633909222644580952">Δεδομένα απόδοσης και αναφορές σφαλμάτων</translation>
<translation id="7637571805876720304">Να καταργηθεί η πιστωτική κάρτα από το Chromium;</translation>
<translation id="7638605456503525968">Σειριακές θύρες</translation>
@@ -1249,7 +1271,6 @@
<translation id="7668654391829183341">Άγνωστη συσκευή</translation>
<translation id="7669271284792375604">Οι εισβολείς σε αυτόν τον ιστότοπο μπορεί να επιχειρήσουν να σας ξεγελάσουν, έτσι ώστε να εγκαταστήσετε προγράμματα που βλάπτουν την εμπειρία περιήγησής σας (για παράδειγμα, αλλάζοντας την αρχική σελίδα σας ή εμφανίζοντας επιπλέον διαφημίσεις στους ιστότοπους που επισκέπτεστε).</translation>
<translation id="7676643023259824263">Αναζήτηση κειμένου σε πρόχειρο, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Πλατφόρμα και cloud</translation>
<translation id="7681101578153515023">Αλλαγή μηχανής αναζήτησης</translation>
<translation id="7682287625158474539">Αποστολή</translation>
<translation id="7687186412095877299">Συμπληρώνει φόρμες πληρωμής με τους αποθηκευμένους τρόπους πληρωμής σας</translation>
@@ -1264,7 +1285,6 @@
<translation id="7723047071702270851">Επεξεργασία κάρτας</translation>
<translation id="774634243536837715">Το επικίνδυνο περιεχόμενο αποκλείστηκε.</translation>
<translation id="7752995774971033316">Χωρίς διαχείριση</translation>
-<translation id="7755287808199759310">Ο γονέας σας μπορεί να καταργήσει τον αποκλεισμό του για εσάς</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Το τείχος προστασίας ή το λογισμικό προστασίας από ιούς ενδέχεται να έχει αποκλείσει τη σύνδεση.</translation>
<translation id="7759163816903619567">Τομέας προβολής:</translation>
@@ -1308,7 +1328,6 @@
<translation id="8004582292198964060">Πρόγραμμα περιήγησης</translation>
<translation id="8009225694047762179">Διαχείριση Κωδικός πρόσβασης</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Αυτή η κάρτα και η διεύθυνση χρέωσής της θα αποθηκευτούν. Θα μπορείτε να τη χρησιμοποιείτε όταν συνδέεστε στον λογαριασμό <ph name="USER_EMAIL" />.}other{Αυτές οι κάρτες και οι διευθύνσεις χρέωσής τους θα αποθηκευτούν. Θα μπορείτε να τις χρησιμοποιείτε όταν συνδέεστε στον λογαριασμό <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Δεν ήταν δυνατή η επικοινωνία με τους γονείς σας αυτήν τη στιγμή. Δοκιμάστε ξανά.</translation>
<translation id="8025119109950072390">Οι εισβολείς σε αυτόν τον ιστότοπο μπορεί να σας ξεγελάσουν και να κάνετε κάτι επικίνδυνο, όπως να εγκαταστήσετε κάποιο λογισμικό ή να αποκαλύψετε προσωπικά σας στοιχεία (για παράδειγμα, κωδικούς πρόσβασης, αριθμούς τηλεφώνου ή πιστωτικές κάρτες).</translation>
<translation id="8034522405403831421">Αυτή η σελίδα είναι στα <ph name="SOURCE_LANGUAGE" />. Μετάφρασή της στα <ph name="TARGET_LANGUAGE" />;</translation>
<translation id="8035152190676905274">Πένα</translation>
@@ -1319,6 +1338,7 @@
<translation id="8041940743680923270">Χρήση καθολικής προεπιλεγμένης ρύθμισης (Ερώτηση)</translation>
<translation id="8042918947222776840">Επιλογή τρόπου παραλαβής</translation>
<translation id="8057711352706143257">Το λογισμικό "<ph name="SOFTWARE_NAME" />" δεν έχει διαμορφωθεί σωστά. Το πρόβλημα διορθώνεται συνήθως με την απεγκατάσταση του λογισμικού "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Δεν θα χρειάζεται στο εξής να εισάγετε τον κωδικό ασφαλείας της κάρτας</translation>
<translation id="8066955247577885446">Δυστυχώς, παρουσιάστηκε κάποιο πρόβλημα.</translation>
<translation id="8074253406171541171">10x13 (Φάκελος)</translation>
<translation id="8078141288243656252">Δεν είναι δυνατός ο σχολιασμός μετά από περιστροφή</translation>
@@ -1349,6 +1369,7 @@
<translation id="8211406090763984747">Η σύνδεση είναι ασφαλής</translation>
<translation id="8218327578424803826">Εκχωρημένη τοποθεσία:</translation>
<translation id="8220146938470311105">C7/C6 (Φάκελος)</translation>
+<translation id="8220639454292072926">Αναφορές επιχειρήσεων</translation>
<translation id="8225771182978767009">Το άτομο που ρύθμισε αυτόν τον υπολογιστή επέλεξε να αποκλείσει αυτόν τον ιστότοπο.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Ανοίξτε τη σελίδα σε μια νέα καρτέλα ανώνυμης περιήγησης</translation>
@@ -1403,24 +1424,24 @@
<translation id="8508648098325802031">Εικονίδιο αναζήτησης</translation>
<translation id="8522552481199248698">Το Chrome μπορεί να σας βοηθήσει να προστατεύσετε τον Λογαριασμό σας Google και να αλλάξετε τον κωδικό πρόσβασής σας.</translation>
<translation id="8543181531796978784">Μπορείτε να <ph name="BEGIN_ERROR_LINK" />αναφέρετε ένα πρόβλημα εντοπισμού<ph name="END_ERROR_LINK" /> ή, εάν κατανοείτε τους κινδύνους ασφαλείας, να <ph name="BEGIN_LINK" />επισκεφτείτε αυτόν τον μη ασφαλή ιστότοπο<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Έχετε ερωτήσεις; Επικοινωνήστε με το άτομο που επιβλέπει το προφίλ σας.</translation>
<translation id="8553075262323480129">Η μετάφραση απέτυχε επειδή δεν ήταν δυνατός ο προσδιορισμός της σελίδας.</translation>
<translation id="8557066899867184262">Ο κωδικός CVC βρίσκεται στο πίσω μέρος της κάρτας.</translation>
<translation id="8559762987265718583">Δεν είναι δυνατή η επίτευξη ιδιωτικής σύνδεσης με τον τομέα <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> επειδή η ημερομηνία και η ώρα (<ph name="DATE_AND_TIME" />) της συσκευής σας είναι λανθασμένες.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> ύποπτος ιστότοπος</translation>
<translation id="8564985650692024650">Το Chromium συνιστά την επαναφορά του κωδικού πρόσβασης <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, εάν τον έχετε χρησιμοποιήσει και σε άλλους ιστοτόπους.</translation>
<translation id="8571890674111243710">Μετάφραση σελίδας σε <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Προσθ. τηλεφ.
</translation>
-<translation id="859285277496340001">Αυτό το πιστοποιητικό δεν καθορίζει κάποιο μηχανισμό για να ελέγχεται εάν έχει ανακληθεί.</translation>
<translation id="860043288473659153">Όνομα κατόχου κάρτας</translation>
<translation id="861775596732816396">Μέγεθος 4</translation>
-<translation id="8620436878122366504">Οι γονείς σας δεν τον έχουν εγκρίνει ακόμα</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Αποθήκευση αυτής της κάρτας στη συγκεκριμένη συσκευή</translation>
<translation id="8626112503828625890">Να αποθηκευτούν τα στοιχεία χρέωσης στον Λογαριασμό Google;</translation>
+<translation id="8647750283161643317">Επαναφορά προεπιλογών</translation>
<translation id="8663226718884576429">Σύνοψη παραγγελίας, <ph name="TOTAL_LABEL" />, Περισσότερες λεπτομέρειες</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, απάντηση, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Διαθέσιμο</translation>
<translation id="8703575177326907206">Η σύνδεσή σας με τον τομέα <ph name="DOMAIN" /> δεν είναι κρυπτογραφημένη.</translation>
<translation id="8718314106902482036">Η πληρωμή δεν ολοκληρώθηκε</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, πρόταση αναζήτησης</translation>
@@ -1431,6 +1452,7 @@
<translation id="8738058698779197622">Για την επίτευξη μιας ασφαλούς σύνδεσης, θα πρέπει να γίνει σωστή ρύθμιση του ρολογιού σας. Αυτό οφείλεται στο γεγονός ότι τα πιστοποιητικά που χρησιμοποιούν οι ιστότοποι για την ταυτοποίησή τους είναι έγκυρα μόνο για συγκεκριμένες χρονικές περιόδους. Εφόσον το ρολόι της συσκευής σας δεν είναι σωστά ρυθμισμένο, το Chromium δεν μπορεί να επαληθεύσει αυτά τα πιστοποιητικά.</translation>
<translation id="8740359287975076522">Δεν ήταν δυνατός ο εντοπισμός της &lt;abbr id="dnsDefinition"&gt;διεύθυνσης DNS&lt;/abbr&gt; του κεντρικού υπολογιστή <ph name="HOST_NAME" />. Γίνεται διάγνωση του προβλήματος.</translation>
<translation id="874846938927089722">Αποδεκτές πιστωτικές και προπληρωμένες κάρτες</translation>
+<translation id="874918643257405732">Προσθήκη αυτής της καρτέλας στους σελιδοδείκτες</translation>
<translation id="8759274551635299824">Αυτή η κάρτα έχει λήξει</translation>
<translation id="8761567432415473239">Η ασφαλής περιήγηση Google <ph name="BEGIN_LINK" />εντόπισε επιβλαβή προγράμματα<ph name="END_LINK" /> πρόσφατα στο <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Συσκευή USB</translation>
@@ -1460,6 +1482,7 @@
<translation id="8938939909778640821">Αποδεκτές πιστωτικές και προπληρωμένες κάρτες</translation>
<translation id="8943282376843390568">Λάιμ</translation>
<translation id="8957210676456822347">Εξουσιοδότηση πύλης υποδοχής</translation>
+<translation id="8962950042226115166">Ύποπτος ιστότοπος</translation>
<translation id="8968766641738584599">Αποθήκευση κάρτας</translation>
<translation id="8971063699422889582">Το πιστοποιητικό του διακομιστή έχει λήξει.</translation>
<translation id="8975012916872825179">Περιλαμβάνει πληροφορίες, όπως αριθμούς τηλεφώνου, διευθύνσεις ηλεκτρονικού ταχυδρομείου και διευθύνσεις αποστολής</translation>
@@ -1482,24 +1505,24 @@
<translation id="9035022520814077154">Σφάλμα ασφάλειας</translation>
<translation id="9038649477754266430">Χρήση μιας υπηρεσίας πρόβλεψης για ταχύτερη φόρτωση σελίδων</translation>
<translation id="9039213469156557790">Επίσης, αυτή η σελίδα περιέχει άλλους πόρους, οι οποίοι δεν είναι ασφαλείς. Αυτοί οι πόροι μπορούν να προβληθούν από άλλους χρήστες κατά τη μετάβαση και μπορούν να τροποποιηθούν από έναν εισβολέα ώστε να αλλάξει η συμπεριφορά της σελίδας.</translation>
+<translation id="9044359186343685026">Χρήση Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Επιχειρήσατε να μεταβείτε στον <ph name="DOMAIN" /> , αλλά ο διακομιστής παρουσίασε ένα μη έγκυρο πιστοποιητικό.</translation>
<translation id="9050666287014529139">Φράση πρόσβασής σας</translation>
<translation id="9065203028668620118">Επεξεργασία</translation>
<translation id="9065745800631924235">Αναζήτηση <ph name="TEXT" /> από το ιστορικό</translation>
<translation id="9069693763241529744">Αποκλείστηκε από μια επέκταση</translation>
-<translation id="9076283476770535406">Μπορεί να διαθέτει περιεχόμενο για ενηλίκους</translation>
<translation id="9076630408993835509">Αυτός ο ιστότοπος δεν είναι διαχειριζόμενος από κάποια εταιρεία ή άλλον οργανισμό. Η διαχείριση της δραστηριότητας σε αυτήν τη συσκευή μπορεί να πραγματοποιηθεί εκτός Chrome. <ph name="BEGIN_LINK" />Μάθετε περισσότερα<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Απαιτούνται περισσότερες πληροφορίες</translation>
<translation id="9080712759204168376">Σύνοψη παραγγελίας</translation>
<translation id="9089260154716455634">Πολιτική ελεύθερου χρόνου:</translation>
<translation id="9095388113577226029">Περισσότερες γλώσσες…</translation>
+<translation id="9098981495403789647">Ο διαχειριστής σας έχει ενεργοποιήσει την Προστασία από απειλές του Chrome για Επιχειρήσεις στο πρόγραμμά περιήγησής σας. Η Προστασία από απειλές του Chrome για Επιχειρήσεις έχει πρόσβαση σε ορισμένα από τα δεδομένα σας.</translation>
<translation id="9103872766612412690">Κανονικά, ο ιστότοπος <ph name="SITE" /> χρησιμοποιεί κρυπτογράφηση για να προστατεύει τα στοιχεία σας. Όταν το Chromium επιχείρησε πρόσφατα να συνδεθεί στο <ph name="SITE" />, ο ιστότοπος ανταποκρίθηκε δημιουργώντας ασυνήθιστα και εσφαλμένα διαπιστευτήρια. Αυτό μπορεί να συμβεί όταν κάποιος εισβολέας προσπαθεί να υποκριθεί ότι είναι ο ιστότοπος <ph name="SITE" /> ή όταν κάποια οθόνη σύνδεσης Wi-Fi έχει διακόψει τη σύνδεσή σας. Τα στοιχεία σας εξακολουθούν να είναι ασφαλή επειδή το Chromium διέκοψε τη σύνδεση πριν από την ανταλλαγή δεδομένων.</translation>
<translation id="9106062320799175032">Προσθήκη διεύθυνσης χρέωσης</translation>
<translation id="9114524666733003316">Επιβεβαίωση κάρτας…</translation>
<translation id="9128870381267983090">Σύνδεση σε δίκτυο</translation>
<translation id="9137013805542155359">Εμφάνιση πρωτοτύπου</translation>
-<translation id="9137248913990643158">Εκκινήστε και συνδεθείτε στο Chrome πριν χρησιμοποιήσετε αυτήν την εφαρμογή.</translation>
<translation id="9141013498910525015">Διαχείριση διευθύνσεων</translation>
<translation id="9148088599418889305">Επιλογή τρόπου αποστολής</translation>
<translation id="9148507642005240123">&amp;Αναίρεση επεξεργασίας</translation>
diff --git a/chromium/components/strings/components_strings_en-GB.xtb b/chromium/components/strings/components_strings_en-GB.xtb
index ed2eb942613..46eaee325df 100644
--- a/chromium/components/strings/components_strings_en-GB.xtb
+++ b/chromium/components/strings/components_strings_en-GB.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Add Name on Card</translation>
<translation id="1089439967362294234">Change Password</translation>
+<translation id="1096545575934602868">This field should not have more than <ph name="MAX_ITEMS_LIMIT" /> entries. All further entries will be discarded.</translation>
<translation id="109743633954054152">Manage passwords in Chrome settings</translation>
<translation id="1103523840287552314">Always translate <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">If ticked, Chrome will store a copy of your card on this device for faster form filling.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Access a <ph name="BEGIN_LINK" />cached copy<ph name="END_LINK" /> of <ph name="URL" /></translation>
<translation id="1156303062776767266">You're viewing a local or shared file</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> unexpectedly closed the connection.</translation>
+<translation id="115926840831309955">Check your CVC and try again or update the expiry date</translation>
<translation id="1161325031994447685">Reconnecting to Wi-Fi</translation>
<translation id="1165039591588034296">Error</translation>
<translation id="1175364870820465910">&amp;Print...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">'Software on your computer is stopping Chrome from safely connecting to the web' (Windows computers only)</translation>
<translation id="1294154142200295408">Command-line variations</translation>
<translation id="129553762522093515">Recently closed</translation>
+<translation id="1298536327547837046">Malware Scanning</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Try clearing your cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Deprecated Features</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Search for clipboard image</translation>
<translation id="1323433172918577554">Show More</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">Waiting for connection…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">The site that you just tried to visit looks fake. Attackers sometimes mimic sites by making small, hard-to-see changes to the URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">This page says</translation>
<translation id="153384715582417236">That’s all for now</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Document is too large to be annotated</translation>
-<translation id="1721312023322545264">You need permission from <ph name="NAME" /> to visit this site</translation>
<translation id="1721424275792716183">* Field is required</translation>
<translation id="1727741090716970331">Add Valid Card Number</translation>
<translation id="1728677426644403582">You're viewing the source of a web page</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Websites that you visit and time spent on them</translation>
<translation id="1826516787628120939">Checking</translation>
<translation id="1834321415901700177">This site contains harmful programs</translation>
+<translation id="1838374766361614909">Clear search</translation>
<translation id="1839551713262164453">Validation of policy values has failed with errors</translation>
<translation id="1842969606798536927">Pay</translation>
<translation id="1871208020102129563">Proxy is set to use fixed proxy servers, not a .pac script URL.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Collapse list</translation>
<translation id="1898423065542865115">Filtering</translation>
<translation id="1914326953223720820">Unzip Service</translation>
+<translation id="1915697529809968049">Use touch ID instead of CVC?</translation>
<translation id="1916770123977586577">To apply your updated settings to this site, reload this page</translation>
<translation id="1919345977826869612">Ads</translation>
<translation id="1919367280705858090">Get help with a specific error message</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> Bookmarks</translation>
<translation id="1973335181906896915">Serialisation error</translation>
<translation id="1974060860693918893">Advanced</translation>
+<translation id="1974883374937189061">Help improve Chrome security by sending <ph name="BEGIN_WHITEPAPER_LINK" />URLs of some pages that you visit, limited system information and some page content<ph name="END_WHITEPAPER_LINK" /> to Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Firmware Version</translation>
<translation id="1981206234434200693">Clear Chrome's browsing history data</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{and 1 more}other{and # more}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Enter a valid expiry year</translation>
<translation id="2212735316055980242">Policy not found</translation>
<translation id="2213606439339815911">Fetching entries...</translation>
+<translation id="2215727959747642672">File editing</translation>
<translation id="2218879909401188352">Attackers currently on <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> could install dangerous apps that damage your device, add hidden charges to your mobile bill or steal your personal information. <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">No Internet</translation>
<translation id="2230458221926704099">Fix your connection using the <ph name="BEGIN_LINK" />diagnostics app<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Send now</translation>
+<translation id="2248949050832152960">Use WebAuthn</translation>
<translation id="225207911366869382">This value is deprecated for this policy.</translation>
<translation id="2257315177824333709">Sorry, your card can't be saved at the moment</translation>
<translation id="2262243747453050782">HTTP error</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">Invalid search URL.</translation>
<translation id="2482878487686419369">Notifications</translation>
<translation id="248348093745724435">Machine policies</translation>
-<translation id="2485387744899240041">Usernames for your device and browser</translation>
<translation id="2491120439723279231">Server's certificate contains errors.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Parser</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Go back</translation>
<translation id="2503184589641749290">Accepted debit and prepaid cards</translation>
<translation id="2505268675989099013">Protect Account</translation>
+<translation id="2515335152965840738">IGNORE</translation>
<translation id="2515629240566999685">Checking the signal in your area</translation>
<translation id="2523886232349826891">Saved on this device only</translation>
<translation id="2524461107774643265">Add More Information</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Submit</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{None}=1{1 password (for <ph name="DOMAIN_LIST" />)}=2{2 passwords (for <ph name="DOMAIN_LIST" />)}other{# passwords (for <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Close other tabs or apps</translation>
-<translation id="267371737713284912">press <ph name="MODIFIER_KEY_DESCRIPTION" /> to undo</translation>
<translation id="2674170444375937751">Are you sure that you want to delete these pages from your history?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Leave</translation>
@@ -334,12 +342,14 @@
<translation id="2704283930420550640">Value doesn't match format.</translation>
<translation id="2705137772291741111">The saved (cached) copy of this site was unreadable.</translation>
<translation id="2709516037105925701">Auto-fill</translation>
-<translation id="2712173769900027643">Ask permission</translation>
<translation id="2713444072780614174">White</translation>
<translation id="2720342946869265578">Nearby</translation>
<translation id="2721148159707890343">Request succeeded</translation>
<translation id="2728127805433021124">Server's certificate is signed using a weak signature algorithm.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Running Connectivity Diagnostics<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">By enabling these features, you could lose browser data or
+ compromise your security or privacy. Enabled features apply to all
+ users of this browser.</translation>
<translation id="2735043616039983645">More than one source with conflicting values is present for this policy!</translation>
<translation id="2738330467931008676">Choose pickup address</translation>
<translation id="2740531572673183784">OK</translation>
@@ -350,16 +360,15 @@
<translation id="2784949926578158345">The connection was reset.</translation>
<translation id="2788784517760473862">Accepted credit cards</translation>
<translation id="2792012897584536778">Administrators of this device have set up security certificates that may allow them to see the content of websites that you visit.</translation>
-<translation id="2794233252405721443">Site blocked</translation>
<translation id="2799020568854403057">The site ahead contains harmful apps</translation>
<translation id="2799223571221894425">Relaunch</translation>
<translation id="2803306138276472711">Google Safe Browsing recently <ph name="BEGIN_LINK" />detected malware<ph name="END_LINK" /> on <ph name="SITE" />. Websites that are normally safe are sometimes infected with malware.</translation>
+<translation id="2815364696811431560">LEAVE SITE</translation>
<translation id="2824775600643448204">Address and search bar</translation>
<translation id="2826760142808435982">The connection is encrypted and authenticated using <ph name="CIPHER" /> and uses <ph name="KX" /> as the key exchange mechanism.</translation>
<translation id="2835170189407361413">Clear form</translation>
<translation id="2847118875340931228">Open incognito window</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">You need permission to visit this site</translation>
<translation id="2856444702002559011">Attackers might be trying to steal your information from <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (for example, passwords, messages or credit cards). <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Save card?</translation>
@@ -384,6 +393,7 @@
<translation id="2985306909656435243">If enabled, Chromium will store a copy of your card on this device for faster form filling.</translation>
<translation id="2985398929374701810">Enter a valid address</translation>
<translation id="2986368408720340940">This pickup method isn’t available. Try a different method.</translation>
+<translation id="2987034854559945715">No matching features</translation>
<translation id="2991174974383378012">Sharing with Websites</translation>
<translation id="2991571918955627853">You cannot visit <ph name="SITE" /> right now because the website uses HSTS. Network errors and attacks are usually temporary, so this page will probably work later.</translation>
<translation id="3005723025932146533">Show saved copy</translation>
@@ -394,6 +404,7 @@
<translation id="3024663005179499861">Wrong policy type</translation>
<translation id="3037605927509011580">Aw, Snap!</translation>
<translation id="3041612393474885105">Certificate Information</translation>
+<translation id="3057676462092457419">The DnsOverHttps mode <ph name="SECURE_DNS_MODE_SECURE" /> is not yet supported; the mode has been set to <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Patch Service</translation>
<translation id="3064966200440839136">Leaving incognito mode to pay via an external application. Continue?</translation>
@@ -419,6 +430,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> on <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancel payment</translation>
<translation id="3207960819495026254">Bookmarked</translation>
+<translation id="3209034400446768650">Page may charge money</translation>
<translation id="3225919329040284222">The server presented a certificate that doesn't match built-in expectations. These expectations are included for certain, high-security websites in order to protect you.</translation>
<translation id="3226128629678568754">Press the reload button to resubmit the data needed to load the page.</translation>
<translation id="3227137524299004712">Microphone</translation>
@@ -426,7 +438,6 @@
<translation id="3229041911291329567">Version information about your device and browser</translation>
<translation id="323107829343500871">Enter the CVC for <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Always detect important content on this site</translation>
-<translation id="3254409185687681395">Bookmark this page</translation>
<translation id="3270847123878663523">&amp;Undo Reorder</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Add name on card</translation>
@@ -436,7 +447,6 @@
<translation id="3320021301628644560">Add billing address</translation>
<translation id="3324983252691184275">Crimson</translation>
<translation id="3338095232262050444">Secure</translation>
-<translation id="3345135638360864351">Your request to access this site could not be sent to <ph name="NAME" />. Please try again.</translation>
<translation id="3355823806454867987">Change proxy settings...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />won’t save<ph name="END_EMPHASIS" /> the following information:
<ph name="BEGIN_LIST" />
@@ -470,18 +480,15 @@
<translation id="3462200631372590220">Hide advanced</translation>
<translation id="3467763166455606212">Cardholder name required</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, currently open, press Tab then Enter to switch to the open tab</translation>
-<translation id="3479539252931486093">Was this unexpected? <ph name="BEGIN_LINK" />Let us know<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Not now</translation>
<translation id="3484560055331845446">You could lose access to your Google Account. Chrome recommends changing your password now. You'll be asked to sign in.</translation>
<translation id="3495081129428749620">Find in page
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">We could not reach your parent at the moment. Please try again.</translation>
<translation id="3512163584740124171">This policy is ignored because another policy from the same policy group has a higher priority.</translation>
<translation id="3528171143076753409">Server's certificate is not trusted</translation>
<translation id="3528485271872257980">Dark brown</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{At least 1 item on synced devices}=1{1 item (and more on synced devices)}other{# items (and more on synced devices)}}</translation>
<translation id="3539171420378717834">Keep a copy of this card on this device</translation>
-<translation id="3556433843310711081">Your manager can unblock it for you</translation>
<translation id="3566021033012934673">Your connection is not private</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">An embedded page at <ph name="SITE" /> says</translation>
@@ -509,6 +516,7 @@
<translation id="3678529606614285348">Open page in a new Incognito window (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Crash report captured on <ph name="CRASH_TIME" />, uploaded on <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Certificate information</translation>
+<translation id="3701427423622901115">Reset acknowledged.</translation>
<translation id="3704162925118123524">The network that you are using may require you to visit its log-in page.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Loading...</translation>
@@ -525,6 +533,7 @@
<translation id="3748148204939282805">Attackers on <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> may trick you into doing something dangerous like installing software or revealing your personal information (for example, passwords, phone numbers or credit cards). <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">The translation failed because of a server error.</translation>
<translation id="3759461132968374835">You have no recently reported crashes. Crashes that occurred when crash reporting was disabled will not appear here.</translation>
+<translation id="3760561303380396507">Use Windows Hello instead of CVC?</translation>
<translation id="3761718714832595332">Hide status</translation>
<translation id="3765032636089507299">The Safe Browsing page is under construction.</translation>
<translation id="3778403066972421603">Do you want to save this card to your Google Account and on this device?</translation>
@@ -534,6 +543,7 @@
<translation id="3789155188480882154">Size 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Harmful content blocked.</translation>
+<translation id="3808375843007691220">Warning: Experimental features ahead!</translation>
<translation id="3810973564298564668">Manage</translation>
<translation id="382518646247711829">If you use a proxy server...</translation>
<translation id="3828924085048779000">Empty passphrase is not allowed.</translation>
@@ -542,11 +552,11 @@
<translation id="3858027520442213535">Update date and time</translation>
<translation id="3884278016824448484">Conflicting device identifier</translation>
<translation id="3885155851504623709">Parish</translation>
-<translation id="3886446263141354045">Your request to access this site has been sent to <ph name="NAME" /></translation>
<translation id="3890664840433101773">Add email</translation>
<translation id="3901925938762663762">The card is expired</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Use WebAuthn instead of CVC?</translation>
<translation id="3946209740501886391">Always ask on this site</translation>
<translation id="3949571496842715403">This server could not prove that it is <ph name="DOMAIN" />; its security certificate does not specify Subject Alternative Names. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
<translation id="3949601375789751990">Your browsing history appears here</translation>
@@ -557,11 +567,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{None}=1{From 1 site }other{From # sites }}</translation>
<translation id="397105322502079400">Calculating...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> is blocked</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> has enabled Chrome Enterprise Threat Protection on your browser. Chrome Enterprise Threat Protection has access to some of your data.</translation>
<translation id="3987940399970879459">Less than 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 web page nearby}other{# web pages nearby}}</translation>
<translation id="4030383055268325496">&amp;Undo add</translation>
<translation id="4032320456957708163">Your browser is managed by <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">The link that you opened goes to a site that you don't usually visit. It might be trying to confuse you.</translation>
<translation id="4058922952496707368">Key "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Add Valid Address</translation>
@@ -574,6 +584,7 @@
<translation id="4103249731201008433">Device serial number is invalid</translation>
<translation id="410351446219883937">Auto-play</translation>
<translation id="4103763322291513355">Visit &lt;strong&gt;chrome://policy&lt;/strong&gt; to see the list of blacklisted URLs and other policies enforced by your system administrator.</translation>
+<translation id="4108231218301530806">Use fingerprint to verify this card next time.</translation>
<translation id="4110652170750985508">Review your payment</translation>
<translation id="4112140312785995938">Seek backwards</translation>
<translation id="4116663294526079822">Always allow on this site</translation>
@@ -588,6 +599,7 @@
<translation id="4171400957073367226">Bad verification signature</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> more item}other{<ph name="ITEM_COUNT" /> more items}}</translation>
+<translation id="4176463684765177261">Disabled</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">To pay faster next time, add your card and billing address to your Google account.</translation>
<translation id="4196861286325780578">&amp;Redo move</translation>
@@ -624,6 +636,7 @@
<translation id="4277028893293644418">Reset password</translation>
<translation id="4279811152705618813">Your <ph name="DEVICE_TYPE" /> is managed by <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{This card has been saved in your Google Account}other{These cards have been saved in your Google Account}}</translation>
+<translation id="428847186335018806">Scan files that you download or upload in Chrome.</translation>
<translation id="42981349822642051">Expand</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Switch</translation>
@@ -653,7 +666,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Use of a proxy is disabled but an explicit proxy configuration is specified.</translation>
<translation id="445100540951337728">Accepted debit cards</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> suspicious behaviour</translation>
<translation id="4466881336512663640">Form changes will be lost. Are you sure that you want to continue?</translation>
<translation id="4477350412780666475">Next track</translation>
<translation id="4482953324121162758">This site will not be translated.</translation>
@@ -680,6 +692,7 @@
<translation id="4594403342090139922">&amp;Undo Delete</translation>
<translation id="4597348597567598915">Size 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Search features</translation>
<translation id="4646534391647090355">Take me there now</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">This server could not prove that it is <ph name="DOMAIN" />; its security certificate contains errors. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
@@ -688,7 +701,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Your connection was interrupted</translation>
-<translation id="471880041731876836">You don't have permission to visit this site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Running Windows Network Diagnostics<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Reload policies</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -716,7 +728,6 @@
<translation id="4816492930507672669">Fit to page</translation>
<translation id="4850886885716139402">View</translation>
<translation id="4854362297993841467">This delivery method isn’t available. Try a different method.</translation>
-<translation id="4858792381671956233">You asked your parents if it's OK to visit this site</translation>
<translation id="4864052566555297930">Safety tip:</translation>
<translation id="4876188919622883022">Simplified view</translation>
<translation id="4876305945144899064">No username</translation>
@@ -740,7 +751,9 @@
<translation id="4974590756084640048">Re-enable warnings</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">See all</translation>
+<translation id="4989542687859782284">Unavailable</translation>
<translation id="4989809363548539747">This plug-in is not supported</translation>
+<translation id="4995216769782533993">Confirm the security code to share your card details with this site</translation>
<translation id="5002932099480077015">If enabled, Chrome will store a copy of your card on this device for faster form filling.</translation>
<translation id="5015510746216210676">Machine Name:</translation>
<translation id="5017554619425969104">Text that you copied</translation>
@@ -769,6 +782,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verify your card</translation>
<translation id="5135404736266831032">Manage addresses...</translation>
<translation id="5138227688689900538">Show less</translation>
<translation id="5141240743006678641">Encrypt synced passwords with your Google credentials</translation>
@@ -795,6 +809,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Features that apply system-wide can only be set by the owner: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Warning: This policy was not merged as specified in PolicyDictionaryMultipleSourceMergeList policy because it is not part of the dictionary policies that can be merged.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">End</translation>
@@ -818,7 +833,6 @@
<translation id="536296301121032821">Failed to store policy settings</translation>
<translation id="5371425731340848620">Update card</translation>
<translation id="5377026284221673050">'Your clock is behind' or 'Your clock is ahead' or "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">This page might try to trick you, steal personal information or harm your device. Be cautious when entering personal information or opening downloaded files.</translation>
<translation id="5384855140246857529">To get your cards on all devices, sign in and turn on sync.</translation>
<translation id="5386426401304769735">The certificate chain for this site contains a certificate signed using SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -832,6 +846,8 @@
<translation id="5457113250005438886">Invalid</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> and <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> more}other{<ph name="CONTACT_PREVIEW" /> and <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> more}}</translation>
<translation id="5470861586879999274">&amp;Redo edit</translation>
+<translation id="5473728911100096288">By enabling these features, you will be using deprecated features
+ that will disappear in future versions.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">This content might try to install dangerous software on your device that steals or deletes your information. <ph name="BEGIN_LINK" />Show anyway<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Add valid address</translation>
@@ -855,7 +871,6 @@
<translation id="5570825185877910964">Protect account</translation>
<translation id="5571083550517324815">Can’t pick up from this address. Select a different address.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{One in use}other{# in use}})</translation>
-<translation id="5572851009514199876">Please start and sign in to Chrome so that Chrome can check whether you are allowed to access this site.</translation>
<translation id="5580958916614886209">Check your expiry month and try again</translation>
<translation id="5586446728396275693">No saved addresses</translation>
<translation id="5595485650161345191">Edit address</translation>
@@ -863,6 +878,7 @@
<translation id="560412284261940334">Management not supported</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">This site could be fake or fraudulent. Chrome recommends leaving now.</translation>
<translation id="5610142619324316209">Checking the connection</translation>
<translation id="5610807607761827392">You can manage cards and addresses in <ph name="BEGIN_LINK" />Settings<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> redirected you too many times.</translation>
@@ -886,11 +902,11 @@
<translation id="5720705177508910913">Current user</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome recommends resetting your password if you reused it on other sites.</translation>
-<translation id="5732392974455271431">Your parents can unblock it for you</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Save card in your Google Account}other{Save cards in your Google Account}}</translation>
<translation id="5763042198335101085">Enter a valid email address</translation>
<translation id="5765072501007116331">To see delivery methods and requirements, select an address</translation>
<translation id="5778550464785688721">MIDI devices full control</translation>
+<translation id="5781136890105823427">Experiment enabled</translation>
<translation id="578305955206182703">Amber</translation>
<translation id="57838592816432529">Mute</translation>
<translation id="5784606427469807560">There was a problem confirming your card. Check your Internet connection and try again.</translation>
@@ -907,13 +923,16 @@
<translation id="5860033963881614850">Off</translation>
<translation id="5863847714970149516">The page ahead may try to charge you money</translation>
<translation id="5866257070973731571">Add Phone Number</translation>
+<translation id="5866898949289125849">You're viewing a developer tools page</translation>
<translation id="5869405914158311789">This site can’t be reached</translation>
<translation id="5869522115854928033">Saved passwords</translation>
<translation id="5887400589839399685">Card saved</translation>
<translation id="5893752035575986141">Credit cards are accepted.</translation>
+<translation id="5895138241574237353">Restart</translation>
<translation id="5901630391730855834">Yellow</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synced)</translation>
<translation id="5916664084637901428">On</translation>
+<translation id="59174027418879706">Enabled</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Save card to Google Account?</translation>
<translation id="5922853866070715753">Almost finished</translation>
@@ -947,6 +966,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Use your cards on all your devices?</translation>
<translation id="6059925163896151826">USB devices</translation>
+<translation id="6060009363608157444">Invalid DnsOverHttps mode.</translation>
<translation id="6080696365213338172">You have accessed content using an administrator-provided certificate. Data you provide to <ph name="DOMAIN" /> can be intercepted by your administrator.</translation>
<translation id="6094273045989040137">Annotate</translation>
<translation id="610911394827799129">Your Google Account may have other forms of browsing history at <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -995,13 +1015,12 @@
<translation id="6404511346730675251">Edit bookmark</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Enter the expiry date and CVC for <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">You asked your parent if it's OK to visit this site</translation>
<translation id="6415778972515849510">Chromium can help you protect your Google account and change your password.</translation>
-<translation id="6417515091412812850">Unable to check whether the certificate has been revoked.</translation>
<translation id="6431585503458005759">Don't store</translation>
<translation id="6433490469411711332">Edit contact info</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> refused to connect.</translation>
<translation id="6434309073475700221">Discard</translation>
+<translation id="6435221585574090192">Share data about security events that have been flagged by Chrome Enterprise Threat Protection with your Administrator. These may include page urls, file name and file metadata, your device username and Chrome username.</translation>
<translation id="6440503408713884761">Ignored</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Add more information</translation>
@@ -1010,20 +1029,19 @@
<translation id="6465306955648956876">Manage passwords...</translation>
<translation id="647261751007945333">Device policies</translation>
<translation id="6476284679642588870">Manage payment methods</translation>
-<translation id="6477321094435799029">Chrome detected unusual code on this page and blocked it to protect your personal information (for example, passwords, phone numbers and credit cards).</translation>
<translation id="6489534406876378309">Start uploading crashes</translation>
<translation id="6499038740797743453">Reset password?</translation>
<translation id="6507833130742554667">Credit and debit cards are accepted.</translation>
<translation id="650855688985305916">Yes, store</translation>
<translation id="6508722015517270189">Restart Chrome</translation>
<translation id="6517596291481585650">Warning: This policy was not merged as a list as specified by policy because it is not a list.</translation>
+<translation id="6518133107902771759">Verify</translation>
<translation id="6521745193039995384">Not active</translation>
<translation id="6529602333819889595">&amp;Redo Delete</translation>
<translation id="6534179046333460208">Physical Web suggestions</translation>
<translation id="6545864417968258051">Bluetooth scanning</translation>
<translation id="6554795675067793129">Your account is managed by <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Redo</translation>
-<translation id="6563469144985748109">Your manager hasn't approved it yet</translation>
<translation id="6569060085658103619">You're viewing an extension page</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Light pink</translation>
@@ -1041,11 +1059,13 @@
<translation id="6643016212128521049">Clear</translation>
<translation id="6644283850729428850">This policy has been deprecated.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{None}=1{From 1 site (you won't be signed out of your Google Account)}other{From # sites (you won't be signed out of your Google Account)}}</translation>
+<translation id="6652101503459149953">Use Windows Hello</translation>
<translation id="6657585470893396449">Password</translation>
<translation id="6670613747977017428">Back to safety.</translation>
<translation id="6671697161687535275">Remove form suggestion from Chromium?</translation>
<translation id="6685834062052613830">Sign out and complete setup</translation>
<translation id="6689271823431384964">Chrome is offering to save your cards in your Google account because you are signed in. You can change this behaviour in settings. The cardholder name comes from your account.</translation>
+<translation id="6707256370811247129">Scan the contents of the cache and files that you download or upload in Chrome.</translation>
<translation id="6710213216561001401">Previous</translation>
<translation id="6710594484020273272">&lt;Type search term&gt;</translation>
<translation id="671076103358959139">Enrolment Token:</translation>
@@ -1053,10 +1073,10 @@
<translation id="6738516213925468394">Your data was encrypted with your <ph name="BEGIN_LINK" />sync passphrase<ph name="END_LINK" /> on <ph name="TIME" />. Enter it to start sync.</translation>
<translation id="674375294223700098">Unknown server certificate error.</translation>
<translation id="6744009308914054259">While waiting for a connection, you can visit Downloads to read offline articles.</translation>
+<translation id="6747611005629681221">Warning: Deprecated features ahead!</translation>
<translation id="6753269504797312559">Policy Value</translation>
<translation id="6757797048963528358">Your device went to sleep.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Your parent hasn't approved it yet</translation>
<translation id="67862343314499040">Violet</translation>
<translation id="6786747875388722282">Extensions</translation>
<translation id="6790428901817661496">Play</translation>
@@ -1064,6 +1084,7 @@
<translation id="681021252041861472">Required Field</translation>
<translation id="6810899417690483278">Customisation ID</translation>
<translation id="6825578344716086703">You attempted to reach <ph name="DOMAIN" />, but the server presented a certificate signed using a weak signature algorithm (such as SHA-1). This means that the security credentials that the server presented could have been forged, and the server may not be the server that you expected (you may be communicating with an attacker).</translation>
+<translation id="6826370046007623921">Data Loss Prevention</translation>
<translation id="6831043979455480757">Translate</translation>
<translation id="6839929833149231406">Area</translation>
<translation id="6852204201400771460">Reload app?</translation>
@@ -1076,7 +1097,6 @@
<translation id="6891596781022320156">Policy level is not supported.</translation>
<translation id="6895330447102777224">Your card is confirmed</translation>
<translation id="6897140037006041989">User Agent</translation>
-<translation id="6903319715792422884">Help improve Safe Browsing by sending some <ph name="BEGIN_WHITEPAPER_LINK" />system information and page content<ph name="END_WHITEPAPER_LINK" /> to Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">User:</translation>
<translation id="6934672428414710184">This name is from your Google Account</translation>
<translation id="6944692733090228304">You entered your password on a site that’s not managed by <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. To protect your account, don’t reuse your password on other apps and sites.</translation>
@@ -1121,6 +1141,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> and <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> more}other{<ph name="PAYMENT_METHOD_PREVIEW" /> and <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> more}}</translation>
<translation id="7153618581592392745">Lavender</translation>
<translation id="717330890047184534">Gaia ID:</translation>
+<translation id="7174545416324379297">Merged</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> and <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> more}other{<ph name="SHIPPING_OPTION_PREVIEW" /> and <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> more}}</translation>
<translation id="7177397715882417099">The server that you are going to, <ph name="ORIGIN" />, has requested that a security policy will be applied to all requests to it. But instead of delivering a policy, it has redirected the browser elsewhere, which prevents the browser from fulfilling your request for <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Save and fill payment methods</translation>
@@ -1155,6 +1176,7 @@ Additional details:
<translation id="7320336641823683070">Connection Help</translation>
<translation id="733354035281974745">Device local account override</translation>
<translation id="7334320624316649418">&amp;Redo reorder</translation>
+<translation id="7337706099755338005">Not available on your platform.</translation>
<translation id="733923710415886693">The server's certificate was not disclosed via Certificate Transparency.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Is affiliated:</translation>
@@ -1186,7 +1208,6 @@ Additional details:
<translation id="7440140511386898319">Explore while offline</translation>
<translation id="7441627299479586546">Wrong policy subject</translation>
<translation id="7442725080345379071">Light orange</translation>
-<translation id="7444046173054089907">This site is blocked</translation>
<translation id="7445762425076701745">The identity of the server to which you are connected cannot be fully validated. You are connected to a server using a name valid only within your network, and an external certificate authority has no way to validate ownership. As some certificate authorities will issue certificates for these names regardless, there is no way to ensure that you are connected to the intended website and not to an attacker.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Find out more<ph name="END_LINK" /> about this problem.</translation>
<translation id="7455133967321480974">Use global default (Block)</translation>
@@ -1208,9 +1229,9 @@ Additional details:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Once you confirm, your card details will be shared with this site.</translation>
<translation id="7542995811387359312">Automatic credit card filling is disabled because this form does not use a secure connection.</translation>
-<translation id="7543525346216957623">Ask your parent</translation>
<translation id="7548892272833184391">Fix connection errors</translation>
<translation id="7549584377607005141">This web page requires data that you entered earlier in order to be properly displayed. You can send this data again, but by doing so you will repeat any action this page previously performed.</translation>
+<translation id="7550637293666041147">Your device username and Chrome username</translation>
<translation id="7552846755917812628">Try the following tips:</translation>
<translation id="7554791636758816595">New Tab</translation>
<translation id="7564049878696755256">You could lose access to your <ph name="ORG_NAME" /> account or experience identity theft. Chrome recommends changing your password now.</translation>
@@ -1225,6 +1246,7 @@ Additional details:
<translation id="7610193165460212391">Value is out of range <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Exp: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">You already have data that is encrypted using a different version of your Google Account password. Please enter it below.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Performance data and crash reports</translation>
<translation id="7637571805876720304">Remove credit card from Chromium?</translation>
<translation id="7638605456503525968">Serial ports</translation>
@@ -1237,7 +1259,6 @@ Additional details:
<translation id="7668654391829183341">Unknown device</translation>
<translation id="7669271284792375604">Attackers on this site might try to trick you into installing programs that harm your browsing experience (for example, by changing your homepage or showing extra ads on sites that you visit).</translation>
<translation id="7676643023259824263">Search for clipboard text, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform and Cloud</translation>
<translation id="7681101578153515023">Change search engine</translation>
<translation id="7682287625158474539">Shipping</translation>
<translation id="7687186412095877299">Fills in payment forms with your saved payment methods</translation>
@@ -1252,7 +1273,6 @@ Additional details:
<translation id="7723047071702270851">Edit Card</translation>
<translation id="774634243536837715">Dangerous content blocked.</translation>
<translation id="7752995774971033316">Unmanaged</translation>
-<translation id="7755287808199759310">Your parent can unblock it for you</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Firewall or antivirus software may have blocked the connection.</translation>
<translation id="7759163816903619567">Display domain:</translation>
@@ -1296,7 +1316,6 @@ Additional details:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Manage Passwords</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{This card and its billing address will be saved. You'll be able to use it when signed in to <ph name="USER_EMAIL" />.}other{These cards and their billing addresses will be saved. You'll be able to use them when signed in to <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">We could not reach your parents at the moment. Please try again.</translation>
<translation id="8025119109950072390">Attackers on this site may trick you into doing something dangerous like installing software or revealing your personal information (for example passwords, phone numbers or credit cards).</translation>
<translation id="8034522405403831421">This page is in <ph name="SOURCE_LANGUAGE" />. Translate it to <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pen</translation>
@@ -1307,6 +1326,7 @@ Additional details:
<translation id="8041940743680923270">Use global default (Ask)</translation>
<translation id="8042918947222776840">Choose pickup method</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />' isn’t configured correctly. Uninstalling '<ph name="SOFTWARE_NAME" />' usually fixes the problem. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">You won't need to enter a card security code from now on</translation>
<translation id="8066955247577885446">Sorry, something went wrong.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Cannot annotate when rotated</translation>
@@ -1337,6 +1357,7 @@ Additional details:
<translation id="8211406090763984747">Connection is secure</translation>
<translation id="8218327578424803826">Assigned Location:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Enterprise Reporting</translation>
<translation id="8225771182978767009">The person who set up this computer has chosen to block this site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Open page in a new Incognito tab</translation>
@@ -1391,23 +1412,23 @@ Additional details:
<translation id="8508648098325802031">Search icon</translation>
<translation id="8522552481199248698">Chrome can help you protect your Google account and change your password.</translation>
<translation id="8543181531796978784">You can <ph name="BEGIN_ERROR_LINK" />report a detection problem<ph name="END_ERROR_LINK" /> or, if you understand the risks to your security, <ph name="BEGIN_LINK" />visit this unsafe site<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Questions? Contact the person who supervises your profile.</translation>
<translation id="8553075262323480129">The translation failed because the page's language could not be determined.</translation>
<translation id="8557066899867184262">The CVC is located behind your card.</translation>
<translation id="8559762987265718583">A private connection to <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> can't be established because your device's date and time (<ph name="DATE_AND_TIME" />) are incorrect.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> suspicious site</translation>
<translation id="8564985650692024650">Chromium recommends resetting your <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> password if you reused it on other sites.</translation>
<translation id="8571890674111243710">Translating page into <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Add phone no.</translation>
-<translation id="859285277496340001">The certificate does not specify a mechanism to check whether it has been revoked.</translation>
<translation id="860043288473659153">Cardholder name</translation>
<translation id="861775596732816396">Size 4</translation>
-<translation id="8620436878122366504">Your parents haven't approved it yet</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Save This Card to This Device</translation>
<translation id="8626112503828625890">Store billing details in Google Account?</translation>
+<translation id="8647750283161643317">Reset all to default</translation>
<translation id="8663226718884576429">Order Summary, <ph name="TOTAL_LABEL" />, More Details</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, answer, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Available</translation>
<translation id="8703575177326907206">Your connection to <ph name="DOMAIN" /> is not encrypted.</translation>
<translation id="8718314106902482036">Payment not completed</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, search suggestion</translation>
@@ -1418,6 +1439,7 @@ Additional details:
<translation id="8738058698779197622">To establish a secure connection, your clock needs to be set correctly. This is because the certificates that websites use to identify themselves are only valid for specific periods of time. Since your device's clock is incorrect, Chromium cannot verify these certificates.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" />’s &lt;abbr id="dnsDefinition"&gt;DNS address&lt;/abbr&gt; could not be found. Diagnosing the problem.</translation>
<translation id="874846938927089722">Accepted Credit and Prepaid Cards</translation>
+<translation id="874918643257405732">Bookmark this tab</translation>
<translation id="8759274551635299824">This card has expired</translation>
<translation id="8761567432415473239">Google Safe Browsing recently <ph name="BEGIN_LINK" />found harmful programs<ph name="END_LINK" /> on <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB device</translation>
@@ -1447,6 +1469,7 @@ Additional details:
<translation id="8938939909778640821">Accepted credit and prepaid cards</translation>
<translation id="8943282376843390568">Lime</translation>
<translation id="8957210676456822347">Captive Portal Authorisation</translation>
+<translation id="8962950042226115166">Suspicious site</translation>
<translation id="8968766641738584599">Save card</translation>
<translation id="8971063699422889582">Server's certificate has expired.</translation>
<translation id="8975012916872825179">Includes information such as phone numbers, email addresses and delivery addresses</translation>
@@ -1469,24 +1492,24 @@ Additional details:
<translation id="9035022520814077154">Security error</translation>
<translation id="9038649477754266430">Use a prediction service to load pages more quickly</translation>
<translation id="9039213469156557790">Furthermore, this page includes other resources which are not secure. These resources can be viewed by others while in transit, and can be modified by an attacker to change the behaviour of the page.</translation>
+<translation id="9044359186343685026">Use touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">You attempted to reach <ph name="DOMAIN" />, but the server presented an invalid certificate.</translation>
<translation id="9050666287014529139">Passphrase</translation>
<translation id="9065203028668620118">Edit</translation>
<translation id="9065745800631924235"><ph name="TEXT" /> search from history</translation>
<translation id="9069693763241529744">Blocked by an extension</translation>
-<translation id="9076283476770535406">It may have mature content</translation>
<translation id="9076630408993835509">This browser is not managed by a company or other organisation. Activity on this device may be managed outside of Chrome. <ph name="BEGIN_LINK" />Find out more<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">More information required</translation>
<translation id="9080712759204168376">Order Summary</translation>
<translation id="9089260154716455634">Off-hours policy:</translation>
<translation id="9095388113577226029">More languages...</translation>
+<translation id="9098981495403789647">Your administrator has enabled Chrome Enterprise Threat Protection on your browser. Chrome Enterprise Threat Protection has access to some of your data.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> normally uses encryption to protect your information. When Chromium tried to connect to <ph name="SITE" /> this time, the website sent back unusual and incorrect credentials. This may happen when an attacker is trying to pretend to be <ph name="SITE" />, or a Wi-Fi sign-in screen has interrupted the connection. Your information is still secure because Chromium stopped the connection before any data was exchanged.</translation>
<translation id="9106062320799175032">Add Billing Address</translation>
<translation id="9114524666733003316">Confirming card...</translation>
<translation id="9128870381267983090">Connect to network</translation>
<translation id="9137013805542155359">Show original</translation>
-<translation id="9137248913990643158">Please start and sign in to Chrome before using this app.</translation>
<translation id="9141013498910525015">Manage addresses</translation>
<translation id="9148088599418889305">Choose delivery method</translation>
<translation id="9148507642005240123">&amp;Undo edit</translation>
diff --git a/chromium/components/strings/components_strings_es-419.xtb b/chromium/components/strings/components_strings_es-419.xtb
index 244369a8863..df20286dee2 100644
--- a/chromium/components/strings/components_strings_es-419.xtb
+++ b/chromium/components/strings/components_strings_es-419.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Agregar el nombre en la tarjeta</translation>
<translation id="1089439967362294234">Cambiar contraseña</translation>
+<translation id="1096545575934602868">Esta campo no debe tener más de <ph name="MAX_ITEMS_LIMIT" /> entradas. Se descartarán las restantes.</translation>
<translation id="109743633954054152">Administra las contraseñas en la configuración de Chrome</translation>
<translation id="1103523840287552314">Siempre traducir <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Si marcas esta opción, Chrome almacenará una copia de la tarjeta en el dispositivo para completar más rápidamente los formularios.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Accede a una <ph name="BEGIN_LINK" />copia almacenada en caché<ph name="END_LINK" /> de <ph name="URL" />.</translation>
<translation id="1156303062776767266">Estás viendo un archivo local o compartido</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> cerró la conexión de forma inesperada.</translation>
+<translation id="115926840831309955">Verifica el CVC y vuelve a intentarlo o actualiza la fecha de vencimiento.</translation>
<translation id="1161325031994447685">Volver a conectarte a Wi-Fi</translation>
<translation id="1165039591588034296">Error</translation>
<translation id="1175364870820465910">Im&amp;primir...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Un software en tu computadora evita que Chrome se conecte de forma segura a la Web" (solo en computadoras con Windows)</translation>
<translation id="1294154142200295408">Variaciones en la línea de comandos</translation>
<translation id="129553762522093515">Cerrado recientemente</translation>
+<translation id="1298536327547837046">Búsqueda de software malicioso</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Intenta borrar tus cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funciones obsoletas</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Buscar imagen del portapapeles</translation>
<translation id="1323433172918577554">Mostrar más</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Hojas de cálculo de Google</translation>
<translation id="1527263332363067270">Esperando conexión…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">El sitio que intentaste visitar parece falso. A veces, los atacantes hacen cambios sutiles y difíciles de detectar en la URL para imitar sitios.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Esta página dice</translation>
<translation id="153384715582417236">Eso es todo por ahora</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">SO</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">El documento es demasiado grande para contener anotaciones</translation>
-<translation id="1721312023322545264">Necesitas permiso de <ph name="NAME" /> para visitar este sitio</translation>
<translation id="1721424275792716183">* El campo es obligatorio</translation>
<translation id="1727741090716970331">Agregar un número de tarjeta válido</translation>
<translation id="1728677426644403582">Estás viendo la fuente de una página web</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Los sitios web que visitas y el tiempo que pasas en ellos</translation>
<translation id="1826516787628120939">Comprobando</translation>
<translation id="1834321415901700177">Este sitio contiene programas dañinos</translation>
+<translation id="1838374766361614909">Borrar la búsqueda</translation>
<translation id="1839551713262164453">Se produjeron errores en la validación de los valores de la política</translation>
<translation id="1842969606798536927">Pagar</translation>
<translation id="1871208020102129563">El proxy está configurado para usar servidores proxy fijos, no una URL de script .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Ocultar lista</translation>
<translation id="1898423065542865115">Filtrado</translation>
<translation id="1914326953223720820">Servicio de descompresión</translation>
+<translation id="1915697529809968049">¿Deseas usar Touch ID en lugar de CVC?</translation>
<translation id="1916770123977586577">Para aplicar la configuración actualizada en este sitio, vuelve a cargar la página</translation>
<translation id="1919345977826869612">Anuncios</translation>
<translation id="1919367280705858090">Cómo obtener ayuda con un mensaje de error específico</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Favoritos de <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Error de serialización</translation>
<translation id="1974060860693918893">Configuración avanzada</translation>
+<translation id="1974883374937189061">Para ayudar a mejorar la seguridad de Chrome, envía <ph name="BEGIN_WHITEPAPER_LINK" />las URL de algunas páginas que visitas, información limitada sobre el sistema y determinado contenido de páginas<ph name="END_WHITEPAPER_LINK" /> a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versión de firmware</translation>
<translation id="1981206234434200693">Borrar datos del historial de navegación de Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{y 1 más}other{y # más}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Ingresa un año de vencimiento válido</translation>
<translation id="2212735316055980242">No se encontró la política.</translation>
<translation id="2213606439339815911">Recuperando entradas…</translation>
+<translation id="2215727959747642672">Edición de archivo</translation>
<translation id="2218879909401188352">Es posible que los atacantes que se encuentran actualmente en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> instalen apps peligrosas que dañen tu dispositivo, agreguen cargos ocultos en la factura de tu servicio móvil o roben tu información personal. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Sin Internet</translation>
<translation id="2230458221926704099">Corregir la conexión con la <ph name="BEGIN_LINK" />app de diagnóstico<ph name="END_LINK" />.</translation>
<translation id="2239100178324503013">Enviar ahora</translation>
+<translation id="2248949050832152960">Usar WebAuthn</translation>
<translation id="225207911366869382">Este valor ya no se utiliza para esta política.</translation>
<translation id="2257315177824333709">No se puede guardar tu tarjeta en este momento</translation>
<translation id="2262243747453050782">Error de HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL de búsqueda no válida</translation>
<translation id="2482878487686419369">Notificaciones</translation>
<translation id="248348093745724435">Políticas de la máquina</translation>
-<translation id="2485387744899240041">Nombres de usuario para tu dispositivo y navegador</translation>
<translation id="2491120439723279231">El certificado del servidor contiene errores.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analizador de JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Ir atrás</translation>
<translation id="2503184589641749290">Tarjetas de débito y prepago aceptadas</translation>
<translation id="2505268675989099013">Proteger cuenta</translation>
+<translation id="2515335152965840738">IGNORAR</translation>
<translation id="2515629240566999685">Verificar la señal en tu área.</translation>
<translation id="2523886232349826891">Solo se guardará en este dispositivo</translation>
<translation id="2524461107774643265">Agregar más información</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Enviar</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Ninguna}=1{1 contraseña (para <ph name="DOMAIN_LIST" />)}=2{2 contraseñas (para <ph name="DOMAIN_LIST" />)}other{# contraseñas (para <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Cierra las demás pestañas o apps.</translation>
-<translation id="267371737713284912">presiona <ph name="MODIFIER_KEY_DESCRIPTION" /> para deshacer</translation>
<translation id="2674170444375937751">¿Estás seguro de que deseas eliminar estas páginas del historial?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Abandonar</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">El valor no coincide con el formato.</translation>
<translation id="2705137772291741111">La copia guardada (en caché) de este sitio es ilegible.</translation>
<translation id="2709516037105925701">Autocompletar</translation>
-<translation id="2712173769900027643">Solicitar permiso</translation>
<translation id="2713444072780614174">Blanco</translation>
<translation id="2720342946869265578">Cercanas</translation>
<translation id="2721148159707890343">Solicitud correcta</translation>
<translation id="2728127805433021124">El certificado del servidor está firmado con un algoritmo de firma no seguro.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Ejecución del Diagnóstico de conectividad<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Si habilitas estas funciones, es posible que pierdas datos de navegación o pongas en riesgo tu seguridad o privacidad. Las funciones habilitadas se aplican a todos los usuarios de este navegador.</translation>
<translation id="2735043616039983645">Hay más de una fuente con valores en conflicto para esta política.</translation>
<translation id="2738330467931008676">Elegir dirección de retiro</translation>
<translation id="2740531572673183784">Aceptar</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">Se ha restablecido la conexión.</translation>
<translation id="2788784517760473862">Tarjetas de crédito aceptadas</translation>
<translation id="2792012897584536778">Los administradores de este dispositivo configuraron certificados de seguridad que les permiten ver el contenido de los sitios web que visitas.</translation>
-<translation id="2794233252405721443">Sitio bloqueado</translation>
<translation id="2799020568854403057">El siguiente sitio incluye apps dañinas</translation>
<translation id="2799223571221894425">Reiniciar</translation>
<translation id="2803306138276472711">La Navegación segura de Google <ph name="BEGIN_LINK" />detectó software malicioso<ph name="END_LINK" /> en <ph name="SITE" /> recientemente. A veces, los sitios web que suelen ser seguros contienen software malicioso.</translation>
+<translation id="2815364696811431560">SALIR DEL SITIO</translation>
<translation id="2824775600643448204">Barra de direcciones y de búsqueda</translation>
<translation id="2826760142808435982">La conexión se encriptó y autenticó con <ph name="CIPHER" />, y utiliza <ph name="KX" /> como el mecanismo de intercambio de claves.</translation>
<translation id="2835170189407361413">Eliminar formulario</translation>
<translation id="2847118875340931228">Abrir ventana de incógnito</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Necesitas permiso para visitar este sitio</translation>
<translation id="2856444702002559011">Es posible que algunos atacantes intenten robar tu información de <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (p. ej., contraseñas, mensajes o tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">¿Quieres guardar la tarjeta?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Si se habilita esta opción, Chromium almacenará una copia de la tarjeta en el dispositivo para completar más rápidamente los formularios.</translation>
<translation id="2985398929374701810">Ingresa una dirección válida</translation>
<translation id="2986368408720340940">El método de retiro no está disponible. Prueba otro método.</translation>
+<translation id="2987034854559945715">No hay funciones que coincidan</translation>
<translation id="2991174974383378012">Compartir con los sitios web</translation>
<translation id="2991571918955627853">No puedes visitar <ph name="SITE" /> ahora porque el sitio web usa HSTS. Los ataques y errores de red suelen ser temporales, por lo que es posible que esta página funcione más tarde.</translation>
<translation id="3005723025932146533">Mostrar copia guardada</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Tipo de política incorrecto</translation>
<translation id="3037605927509011580">¡Oh, no!</translation>
<translation id="3041612393474885105">Información sobre el certificado</translation>
+<translation id="3057676462092457419">El modo DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> aún no está disponible. El valor que se le asignó es <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Aplicar parche al servicio</translation>
<translation id="3064966200440839136">Saldrás del modo de navegación incógnito para pagar mediante una aplicación externa. ¿Deseas continuar?</translation>
@@ -428,6 +437,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> en <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pago</translation>
<translation id="3207960819495026254">Agregada a favoritos</translation>
+<translation id="3209034400446768650">La página puede cobrar cargos</translation>
<translation id="3225919329040284222">El servidor mostró un certificado que no coincide con lo esperado. Estas expectativas se incluyen en determinados sitios web con un alto nivel de seguridad para garantizar tu protección.</translation>
<translation id="3226128629678568754">Presiona el botón para volver a cargar y, de ese modo, enviar nuevamente los datos necesarios para cargar la página.</translation>
<translation id="3227137524299004712">Micrófono</translation>
@@ -435,7 +445,6 @@
<translation id="3229041911291329567">Información de versión sobre tu dispositivo y navegador</translation>
<translation id="323107829343500871">Ingresar el CVC de la tarjeta <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Siempre detectar contenido importante en este sitio</translation>
-<translation id="3254409185687681395">Agregar esta página a Favoritos</translation>
<translation id="3270847123878663523">&amp;Deshacer Reorganizar</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Agregar el nombre en la tarjeta</translation>
@@ -445,7 +454,6 @@
<translation id="3320021301628644560">Agregar dirección de facturación</translation>
<translation id="3324983252691184275">Carmesí</translation>
<translation id="3338095232262050444">Seguro</translation>
-<translation id="3345135638360864351">No se pudo enviar la solicitud de acceso al sitio a <ph name="NAME" />. Vuelve a intentarlo.</translation>
<translation id="3355823806454867987">Cambiar la configuración del proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />no guardará<ph name="END_EMPHASIS" /> la siguiente información:
<ph name="BEGIN_LIST" />
@@ -479,18 +487,15 @@
<translation id="3462200631372590220">Ocultar detalles avanzados</translation>
<translation id="3467763166455606212">Se requiere el nombre del titular de la tarjeta</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />; abierta actualmente; presiona Tabulación y, luego, Intro para cambiar a la pestaña abierta</translation>
-<translation id="3479539252931486093">¿Ocurrió algo inesperado? <ph name="BEGIN_LINK" />Cuéntanos<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ahora no</translation>
<translation id="3484560055331845446">Podrías perder el acceso a tu Cuenta de Google. Chrome te recomienda cambiar la contraseña ahora. Deberás acceder a la cuenta.</translation>
<translation id="3495081129428749620">Buscar en la página
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">No pudimos comunicarnos con ninguno de tus padres. Vuelve a intentarlo.</translation>
<translation id="3512163584740124171">Se ignora esta política porque otra del mismo grupo tiene prioridad.</translation>
<translation id="3528171143076753409">El certificado del servidor no es de confianza.</translation>
<translation id="3528485271872257980">Marrón oscuro</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Al menos 1 elemento en dispositivos sincronizados}=1{1 elemento (y más en dispositivos sincronizados)}other{# elementos (y más en dispositivos sincronizados)}}</translation>
<translation id="3539171420378717834">Conservar una copia de la tarjeta en el dispositivo.</translation>
-<translation id="3556433843310711081">Tu administrador puede desbloquearlo por ti</translation>
<translation id="3566021033012934673">La conexión no es privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Una página incorporada en <ph name="SITE" /> dice</translation>
@@ -518,6 +523,7 @@
<translation id="3678529606614285348">Abre la página en una nueva ventana de incógnito (Ctrl-mayúscula-N).</translation>
<translation id="3679803492151881375">El informe de fallos se capturó el <ph name="CRASH_TIME" /> y se cargó el <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Información sobre el certificado</translation>
+<translation id="3701427423622901115">Se detectó el restablecimiento.</translation>
<translation id="3704162925118123524">Es posible que la red que estás usando requiera que visites la página de acceso.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Cargando...</translation>
@@ -534,6 +540,7 @@
<translation id="3748148204939282805">Es posible que los atacantes en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> intenten engañarte para que realices alguna acción peligrosa, como instalar software o revelar información personal (p. ej., contraseñas, números de teléfono o tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Falló la traducción debido a un error de servidor.</translation>
<translation id="3759461132968374835">No has notificado ningún bloqueo recientemente. Los bloqueos que se hayan producido mientras la función de notificación de bloqueos estaba desactivada no aparecerán en esta página.</translation>
+<translation id="3760561303380396507">¿Deseas usar Windows Hello en lugar de CVC?</translation>
<translation id="3761718714832595332">Ocultar estado</translation>
<translation id="3765032636089507299">La página de Navegación segura está en construcción.</translation>
<translation id="3778403066972421603">¿Deseas guardar esta tarjeta en tu cuenta de Google y en este dispositivo?</translation>
@@ -543,6 +550,7 @@
<translation id="3789155188480882154">Tamaño 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Se bloqueó el contenido dañino</translation>
+<translation id="3808375843007691220">Advertencia: Se detectaron funciones experimentales</translation>
<translation id="3810973564298564668">Administrar</translation>
<translation id="382518646247711829">Si utilizas un servidor proxy...</translation>
<translation id="3828924085048779000">No se permite una frase de contraseña vacía.</translation>
@@ -551,11 +559,11 @@
<translation id="3858027520442213535">Actualizar fecha y hora</translation>
<translation id="3884278016824448484">Hay un identificador de dispositivo en conflicto.</translation>
<translation id="3885155851504623709">Distrito</translation>
-<translation id="3886446263141354045">Tu solicitud de acceso a este sitio se envió a <ph name="NAME" /></translation>
<translation id="3890664840433101773">Agregar correo electrónico</translation>
<translation id="3901925938762663762">Caducó la tarjeta.</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">¿Deseas usar WebAuthn en lugar de CVC?</translation>
<translation id="3946209740501886391">Preguntar siempre en este sitio</translation>
<translation id="3949571496842715403">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" />; su certificado de seguridad no especifica la extensión Nombres alternativos del asunto. Es posible que se deba a un error en la configuración o a que haya un atacante que está interceptando tu conexión.</translation>
<translation id="3949601375789751990">Tu historial de navegación aparece aquí</translation>
@@ -566,11 +574,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ninguno}=1{De 1 sitio }other{De # sitios }}</translation>
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861">Se bloqueó <ph name="HOST_NAME" /></translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> habilitó la Protección contra amenazas de Chrome Enterprise en el navegador. La Protección contra amenazas de Chrome Enterprise tiene acceso a algunos de tus datos.</translation>
<translation id="3987940399970879459">Menos de 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 página web cercana}other{# páginas web cercanas}}</translation>
<translation id="4030383055268325496">&amp;Deshacer Agregar</translation>
<translation id="4032320456957708163"><ph name="ENROLLMENT_DOMAIN" /> administra tu navegador</translation>
-<translation id="4034375457890803692">El vínculo que abriste te dirige a un sitio que no visitas con frecuencia. Es posible que quiera engañarte.</translation>
<translation id="4058922952496707368">Clave "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Agregar una dirección válida</translation>
@@ -583,6 +591,7 @@
<translation id="4103249731201008433">El número de serie del dispositivo no es válido.</translation>
<translation id="410351446219883937">Reproducción automática</translation>
<translation id="4103763322291513355">Visita &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver las URL en lista negra y otras políticas que estableció el administrador del sistema.</translation>
+<translation id="4108231218301530806">Usar la huella digital para verificar esta tarjeta la próxima vez</translation>
<translation id="4110652170750985508">Revisar el pago</translation>
<translation id="4112140312785995938">Buscar más atrás</translation>
<translation id="4116663294526079822">Permitir siempre en este sitio</translation>
@@ -597,6 +606,7 @@
<translation id="4171400957073367226">La firma de verificación no es válida.</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> elemento más}other{<ph name="ITEM_COUNT" /> elementos más}}</translation>
+<translation id="4176463684765177261">Inhabilitada</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Para realizar pagos de forma más rápida la próxima vez, agrega tu tarjeta y dirección de facturación a tu Cuenta de Google.</translation>
<translation id="4196861286325780578">&amp;Rehacer Mover</translation>
@@ -633,6 +643,7 @@
<translation id="4277028893293644418">Restablecer contraseña</translation>
<translation id="4279811152705618813"><ph name="ENROLLMENT_DOMAIN" /> administra tu dispositivo <ph name="DEVICE_TYPE" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Se guardó esta tarjeta en tu Cuenta de Google}other{Se guardaron estas tarjetas en tu Cuenta de Google}}</translation>
+<translation id="428847186335018806">Analiza los archivos que descargas y subes mediante Chrome.</translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Cambiar</translation>
@@ -662,7 +673,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Se inhabilitó el uso de un proxy, pero se especificó una configuración explícita de proxy.</translation>
<translation id="445100540951337728">Tarjetas de débito aceptadas</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> comportamiento sospechoso</translation>
<translation id="4466881336512663640">Se perderán los cambios del formulario. ¿Confirmas que deseas continuar?</translation>
<translation id="4477350412780666475">Siguiente pista</translation>
<translation id="4482953324121162758">Este sitio no se traducirá.</translation>
@@ -689,6 +699,7 @@
<translation id="4594403342090139922">&amp;Deshacer Eliminar</translation>
<translation id="4597348597567598915">Tamaño 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Buscar funciones</translation>
<translation id="4646534391647090355">Ir ahora</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" />; el certificado de seguridad contiene errores. Es posible que esto se deba a una configuración incorrecta o a que un atacante interceptó la conexión.</translation>
@@ -697,7 +708,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Se interrumpió la conexión</translation>
-<translation id="471880041731876836">No tienes permiso para visitar este sitio</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ejecución del Diagnóstico de red de Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Volver a cargar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
@@ -725,7 +735,6 @@
<translation id="4816492930507672669">Ajustar a la página</translation>
<translation id="4850886885716139402">Ver</translation>
<translation id="4854362297993841467">Este método de entrega no está disponible. Prueba otro método.</translation>
-<translation id="4858792381671956233">Les preguntaste a tus padres si puedes visitar este sitio</translation>
<translation id="4864052566555297930">Consejo de seguridad:</translation>
<translation id="4876188919622883022">Vista simplificada</translation>
<translation id="4876305945144899064">Sin nombre de usuario</translation>
@@ -749,7 +758,9 @@
<translation id="4974590756084640048">Volver a habilitar las advertencias</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Ver todo</translation>
+<translation id="4989542687859782284">No disponible</translation>
<translation id="4989809363548539747">Este complemento no es compatible</translation>
+<translation id="4995216769782533993">Confirma el código de seguridad para compartir los detalles de la tarjeta con este sitio</translation>
<translation id="5002932099480077015">Si se habilita esta opción, Chrome almacenará una copia de la tarjeta en el dispositivo para llenar más rápidamente los formularios.</translation>
<translation id="5015510746216210676">Nombre de la máquina:</translation>
<translation id="5017554619425969104">Texto que copiaste</translation>
@@ -778,6 +789,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verifica tu tarjeta</translation>
<translation id="5135404736266831032">Administrar direcciones…</translation>
<translation id="5138227688689900538">Mostrar menos</translation>
<translation id="5141240743006678641">Encriptar contraseñas sincronizadas con tus credenciales de Google</translation>
@@ -804,6 +816,7 @@
<translation id="5251803541071282808">Nube</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">El propietario es el único que puede configurar las funciones que se aplican a todo el sistema: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Advertencia: Esta política no se combinó según la política PolicyDictionaryMultipleSourceMergeList porque no es parte de las políticas del diccionario que se pueden combinar.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Finalizar</translation>
@@ -827,7 +840,6 @@
<translation id="536296301121032821">Error al almacenar la configuración de la política</translation>
<translation id="5371425731340848620">Actualizar tarjeta</translation>
<translation id="5377026284221673050">"El reloj está atrasado", "El reloj está adelantado" o "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Es posible que esta página trate de engañarte, robarte información personal o dañar tu dispositivo. Ten cuidado cuando ingreses este tipo de información o abras documentos descargados.</translation>
<translation id="5384855140246857529">Para usar tus tarjetas en todos los dispositivos, accede a tu cuenta y activa la sincronización.</translation>
<translation id="5386426401304769735">La cadena del certificado de este sitio web contiene un certificado que se firmó con SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -841,6 +853,7 @@
<translation id="5457113250005438886">Sin validez</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> más}other{<ph name="CONTACT_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> más}}</translation>
<translation id="5470861586879999274">&amp;Rehacer Editar</translation>
+<translation id="5473728911100096288">Las funciones que quieres habilitar son obsoletas y dejarán de estar disponibles en versiones futuras.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Es posible que este contenido intente instalar software peligroso que robe o borre tu información en tu dispositivo . <ph name="BEGIN_LINK" />Mostrar de todos modos<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Agregar una dirección válida</translation>
@@ -864,7 +877,6 @@
<translation id="5570825185877910964">Proteger cuenta</translation>
<translation id="5571083550517324815">No se puede retirar el artículo en esta dirección. Selecciona una diferente.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 en uso}other{# en uso}})</translation>
-<translation id="5572851009514199876">Abre Chrome y accede a tu cuenta para que el programa pueda comprobar si puedes acceder a este sitio.</translation>
<translation id="5580958916614886209">Comprueba el mes de vencimiento y vuelve a intentarlo</translation>
<translation id="5586446728396275693">No hay direcciones guardadas</translation>
<translation id="5595485650161345191">Editar dirección</translation>
@@ -872,6 +884,7 @@
<translation id="560412284261940334">No se admite la administración.</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Este sitio podría ser falso o fraudulento. Chrome te recomienda que salgas de él ahora.</translation>
<translation id="5610142619324316209">Comprobar la conexión.</translation>
<translation id="5610807607761827392">Puedes administrar tarjetas y direcciones en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> te redireccionó demasiadas veces.</translation>
@@ -895,11 +908,11 @@
<translation id="5720705177508910913">Usuario actual</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome te recomienda que restablezcas tu contraseña si la volviste a usar en otros sitios.</translation>
-<translation id="5732392974455271431">Tus padres pueden desbloquearlo por ti</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Guarda la tarjeta en tu Cuenta de Google}other{Guarda las tarjetas en tu Cuenta de Google}}</translation>
<translation id="5763042198335101085">Escribe una dirección de correo electrónico válida</translation>
<translation id="5765072501007116331">Para ver los requisitos y métodos de entrega, selecciona una dirección</translation>
<translation id="5778550464785688721">Control total de dispositivos MIDI</translation>
+<translation id="5781136890105823427">Se habilitó un experimento</translation>
<translation id="578305955206182703">Ámbar</translation>
<translation id="57838592816432529">Silenciar</translation>
<translation id="5784606427469807560">Se produjo un problema al confirmar tu tarjeta. Comprueba tu conexión a Internet y vuelve a intentarlo.</translation>
@@ -916,13 +929,16 @@
<translation id="5860033963881614850">No</translation>
<translation id="5863847714970149516">Es posible que la página siguiente intente cobrarte dinero</translation>
<translation id="5866257070973731571">Agregar número de teléfono</translation>
+<translation id="5866898949289125849">Estás viendo una página de herramientas para desarrolladores</translation>
<translation id="5869405914158311789">No se puede acceder a este sitio</translation>
<translation id="5869522115854928033">Contraseñas almacenadas</translation>
<translation id="5887400589839399685">Tarjeta guardada</translation>
<translation id="5893752035575986141">Se aceptan tarjetas de crédito.</translation>
+<translation id="5895138241574237353">Reiniciar</translation>
<translation id="5901630391730855834">Amarillo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizado)</translation>
<translation id="5916664084637901428">Sí</translation>
+<translation id="59174027418879706">Habilitado</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">¿Quieres guardar la tarjeta en la Cuenta de Google?</translation>
<translation id="5922853866070715753">Ya casi</translation>
@@ -956,6 +972,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">¿Quieres usar tus tarjetas en todos los dispositivos?</translation>
<translation id="6059925163896151826">Dispositivos USB</translation>
+<translation id="6060009363608157444">Modo DnsOverHttps no válido</translation>
<translation id="6080696365213338172">Accediste al contenido mediante un certificado proporcionado por el administrador. Los datos que proporciones a <ph name="DOMAIN" /> pueden ser interceptados por tu administrador.</translation>
<translation id="6094273045989040137">Agregar anotación</translation>
<translation id="610911394827799129">Es posible que tu cuenta de Google tenga otros formularios del historial de navegación en <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1004,13 +1021,12 @@
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Ingresar la fecha de vencimiento y el CVC para <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Les preguntaste a tus padres si puedes visitar este sitio</translation>
<translation id="6415778972515849510">Chromium puede ayudarte a proteger tu Cuenta de Google y cambiar tu contraseña.</translation>
-<translation id="6417515091412812850">No se pudo verificar si el certificado ha sido revocado.</translation>
<translation id="6431585503458005759">No almacenar</translation>
<translation id="6433490469411711332">Editar la información de contacto</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> rechazó la conexión.</translation>
<translation id="6434309073475700221">Rechazar</translation>
+<translation id="6435221585574090192">Comparte con tu administrador información sobre eventos de seguridad que se hayan marcado en la función de Protección contra amenazas de Chrome Enterprise. Esos eventos pueden incluir URL de páginas, nombres y metadatos de archivos y tu nombre de usuario de Chrome y el de tu dispositivo.</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Agregar más información</translation>
@@ -1019,20 +1035,19 @@
<translation id="6465306955648956876">Administrar contraseñas…</translation>
<translation id="647261751007945333">Políticas de dispositivos</translation>
<translation id="6476284679642588870">Administrar las formas de pago</translation>
-<translation id="6477321094435799029">Chrome detectó código inusual en esta página y la bloqueó para proteger tu información personal (p. ej.: contraseñas, números de teléfono y tarjetas de crédito).</translation>
<translation id="6489534406876378309">Comenzar a cargar fallos</translation>
<translation id="6499038740797743453">¿Deseas restablecer la contraseña?</translation>
<translation id="6507833130742554667">Se aceptan tarjetas de crédito y débito.</translation>
<translation id="650855688985305916">Sí, almacenar</translation>
<translation id="6508722015517270189">Reinicia Chrome.</translation>
<translation id="6517596291481585650">Advertencia: Esta política no se combinó según la política porque no es una lista.</translation>
+<translation id="6518133107902771759">Verificar</translation>
<translation id="6521745193039995384">Inactiva</translation>
<translation id="6529602333819889595">&amp;Rehacer Eliminar</translation>
<translation id="6534179046333460208">Sugerencias de la Web física</translation>
<translation id="6545864417968258051">Búsqueda de dispositivos Bluetooth</translation>
<translation id="6554795675067793129"><ph name="ENROLLMENT_DOMAIN" /> administra tu cuenta.</translation>
<translation id="6556866813142980365">Rehacer</translation>
-<translation id="6563469144985748109">Tu administrador aún no lo aprobó</translation>
<translation id="6569060085658103619">Estás viendo la página de una extensión</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Rosa claro</translation>
@@ -1050,11 +1065,13 @@
<translation id="6643016212128521049">Borrar</translation>
<translation id="6644283850729428850">Esta política no ha sido aprobada.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Ninguno}=1{De 1 sitio (no saldrás de tu cuenta de Google)}other{De # sitios (no saldrás de tu cuenta de Google)}}</translation>
+<translation id="6652101503459149953">Usar Windows Hello</translation>
<translation id="6657585470893396449">Contraseña</translation>
<translation id="6670613747977017428">Volver a la versión segura</translation>
<translation id="6671697161687535275">¿Confirmas que quieres quitar la sugerencia de formulario de Chromium?</translation>
<translation id="6685834062052613830">Salir y completar la configuración</translation>
<translation id="6689271823431384964">Como accediste a tu Cuenta de Google, Chrome te ofrece guardar tus tarjetas allí. Puedes modificar este comportamiento en la configuración. El nombre del titular de la tarjeta se obtiene de tu cuenta.</translation>
+<translation id="6707256370811247129">Analiza el contenido de la caché y los archivos que descargas o subes mediante Chrome.</translation>
<translation id="6710213216561001401">Anterior</translation>
<translation id="6710594484020273272">&lt;Escribe el término de búsqueda&gt;</translation>
<translation id="671076103358959139">Token de inscripción:</translation>
@@ -1062,10 +1079,10 @@
<translation id="6738516213925468394">Tus datos se encriptaron con la <ph name="BEGIN_LINK" />frase de contraseña de sincronización<ph name="END_LINK" /> el <ph name="TIME" />. Ingresa la frase para iniciar la sincronización.</translation>
<translation id="674375294223700098">Error de certificado de servidor desconocido.</translation>
<translation id="6744009308914054259">Mientras esperas a que se restablezca la conexión, puedes visitar Descargas para leer artículos sin conexión.</translation>
+<translation id="6747611005629681221">Advertencia: Se detectaron funciones obsoletas</translation>
<translation id="6753269504797312559">Valor de la política</translation>
<translation id="6757797048963528358">El dispositivo se suspendió.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Uno de tus padres aún no lo aprobó</translation>
<translation id="67862343314499040">Violeta</translation>
<translation id="6786747875388722282">Extensiones</translation>
<translation id="6790428901817661496">Reproducir</translation>
@@ -1073,6 +1090,7 @@
<translation id="681021252041861472">Campo obligatorio</translation>
<translation id="6810899417690483278">ID de personalización</translation>
<translation id="6825578344716086703">Intentaste acceder a <ph name="DOMAIN" />, pero el servidor presentó un certificado firmado con un algoritmo de firma no seguro (como SHA-1). Esto significa que podrían haberse falsificado las credenciales de seguridad presentadas por el servidor y que este no sea el servidor esperado (es posible que hayas establecido comunicación con un atacante).</translation>
+<translation id="6826370046007623921">Prevención de pérdida de datos</translation>
<translation id="6831043979455480757">Traducir</translation>
<translation id="6839929833149231406">Área</translation>
<translation id="6852204201400771460">¿Deseas volver a cargar la app?</translation>
@@ -1085,7 +1103,6 @@
<translation id="6891596781022320156">No se admite el nivel de políticas.</translation>
<translation id="6895330447102777224">Tu tarjeta se confirmó</translation>
<translation id="6897140037006041989">User agent</translation>
-<translation id="6903319715792422884">Para mejorar la Navegación segura, envía <ph name="BEGIN_WHITEPAPER_LINK" />información del sistema y contenido de la página<ph name="END_WHITEPAPER_LINK" /> a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuario:</translation>
<translation id="6934672428414710184">Este nombre es de tu Cuenta de Google</translation>
<translation id="6944692733090228304">Ingresaste tu contraseña en un sitio que no está administrado por <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para proteger tu cuenta, no vuelvas a usar la contraseña en otras apps y sitios.</translation>
@@ -1130,6 +1147,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> más}other{<ph name="PAYMENT_METHOD_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> más}}</translation>
<translation id="7153618581592392745">Lavanda</translation>
<translation id="717330890047184534">ID de GAIA:</translation>
+<translation id="7174545416324379297">Combinados</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> más}other{<ph name="SHIPPING_OPTION_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> más}}</translation>
<translation id="7177397715882417099">El servidor <ph name="ORIGIN" /> al que te diriges solicitó
que se aplicara una política de seguridad a todas las solicitudes. Sin embargo, en lugar de
@@ -1167,6 +1185,7 @@ Detalles adicionales:
<translation id="7320336641823683070">Ayuda con la conexión</translation>
<translation id="733354035281974745">Se anuló la cuenta local del dispositivo</translation>
<translation id="7334320624316649418">&amp;Rehacer Reorganizar</translation>
+<translation id="7337706099755338005">No está disponible para tu plataforma.</translation>
<translation id="733923710415886693">El certificado del servidor no se divulgó mediante el Certificado de transparencia.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Se afilió:</translation>
@@ -1198,7 +1217,6 @@ Detalles adicionales:
<translation id="7440140511386898319">Explorar sin conexión</translation>
<translation id="7441627299479586546">Nombre de usuario o dominio de política incorrecto</translation>
<translation id="7442725080345379071">Naranja claro</translation>
-<translation id="7444046173054089907">Este sitio está bloqueado</translation>
<translation id="7445762425076701745">La identidad del servidor al que estás conectado no se puede validar en su totalidad. Estás conectado a un servidor utilizando un nombre que sólo es válido dentro de tu red y cuya propiedad no puede validar una entidad externa de certificación. Debido a que algunas entidades emiten certificados aún para estos nombres, no hay manera de asegurar que estás conectado al sitio web que pretendías o a un atacante.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /> acerca de este problema</translation>
<translation id="7455133967321480974">Usar configuración global predeterminada (Bloquear)</translation>
@@ -1220,9 +1238,9 @@ Detalles adicionales:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Después de que se confirme, los datos de tu tarjeta se compartirán con este sitio.</translation>
<translation id="7542995811387359312">El rellenado automático de la tarjeta de crédito se inhabilitó porque este formulario no usa una conexión segura.</translation>
-<translation id="7543525346216957623">Pregúntales a tus padres</translation>
<translation id="7548892272833184391">Cómo corregir errores de conexión</translation>
<translation id="7549584377607005141">Esta página web necesita los datos ingresados anteriormente para mostrarse correctamente. Puedes volver a enviar los datos, pero ten en cuenta que se repetirán las acciones que la página haya realizado anteriormente.</translation>
+<translation id="7550637293666041147">Tu nombre de usuario de Chrome y el de tu dispositivo</translation>
<translation id="7552846755917812628">Intenta las siguientes sugerencias:</translation>
<translation id="7554791636758816595">Nueva pestaña</translation>
<translation id="7564049878696755256">Es posible que hayas perdido el acceso a tu cuenta de <ph name="ORG_NAME" /> o sufrido un robo de identidad. Chrome te recomienda que cambies la contraseña ahora.</translation>
@@ -1237,6 +1255,7 @@ Detalles adicionales:
<translation id="7610193165460212391">El valor <ph name="VALUE" /> está fuera del rango.</translation>
<translation id="7613889955535752492">Vencimiento: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Ya has utilizado otra versión de la contraseña de tu cuenta de Google para encriptar contenido. Ingrésala a continuación.</translation>
+<translation id="7625784245512586808">Protección contra amenazas de Chrome Enterprise</translation>
<translation id="7633909222644580952">Informes sobre fallos y datos de rendimiento</translation>
<translation id="7637571805876720304">¿Confirmas que quieres quitar la tarjeta de crédito de Chromium?</translation>
<translation id="7638605456503525968">Puertos en serie</translation>
@@ -1249,7 +1268,6 @@ Detalles adicionales:
<translation id="7668654391829183341">Dispositivo desconocido</translation>
<translation id="7669271284792375604">Es posible que los atacantes de este sitio intenten engañarte para que instales programas que pueden afectar tu experiencia de navegación (p. ej., podrían cambiar la página principal o mostrar más anuncios en los sitios que visitas).</translation>
<translation id="7676643023259824263">Buscar el texto <ph name="TEXT" /> en el portapapeles</translation>
-<translation id="7679176406634891508">Plataforma y nube</translation>
<translation id="7681101578153515023">Cambiar motor de búsqueda</translation>
<translation id="7682287625158474539">Envío</translation>
<translation id="7687186412095877299">Completa los formularios de pago con la información que tengas guardada</translation>
@@ -1264,7 +1282,6 @@ Detalles adicionales:
<translation id="7723047071702270851">Editar tarjeta</translation>
<translation id="774634243536837715">Se bloqueó contenido peligroso.</translation>
<translation id="7752995774971033316">Sin administrar</translation>
-<translation id="7755287808199759310">Uno de tus padres puede desbloquearlo por ti</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Es posible que un software antivirus o un firewall hayan bloqueado la conexión.</translation>
<translation id="7759163816903619567">Dominio para mostrar:</translation>
@@ -1308,7 +1325,6 @@ Detalles adicionales:
<translation id="8004582292198964060">Navegador</translation>
<translation id="8009225694047762179">Administrar contraseñas</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Se guardará esta tarjeta y su dirección de facturación. Podrás usarla cuando accedas a <ph name="USER_EMAIL" />.}other{Se guardarán estas tarjetas y sus direcciones de facturación. Podrás usarlas cuando accedas a <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">No pudimos comunicarnos con tus padres. Vuelve a intentarlo.</translation>
<translation id="8025119109950072390">Es posible que los atacantes de este sitio te engañen para que hagas algo peligroso, como instalar software o divulgar información personal (p. ej., contraseñas, números de teléfono o tarjetas de crédito).</translation>
<translation id="8034522405403831421">Esta página está en <ph name="SOURCE_LANGUAGE" />. ¿Quieres traducirla al <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Lápiz</translation>
@@ -1319,6 +1335,7 @@ Detalles adicionales:
<translation id="8041940743680923270">Usar configuración global predeterminada (Preguntar)</translation>
<translation id="8042918947222776840">Elegir método de retiro</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" no se configuró correctamente. Prueba desinstalar "<ph name="SOFTWARE_NAME" />" para corregir el problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">A partir de ahora, no tendrás que ingresar el código de seguridad de la tarjeta</translation>
<translation id="8066955247577885446">Se produjo un error.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">No se pueden realizar anotaciones cuando el documento está rotado</translation>
@@ -1349,6 +1366,7 @@ Detalles adicionales:
<translation id="8211406090763984747">La conexión es segura</translation>
<translation id="8218327578424803826">Ubicación asignada:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Informes empresariales</translation>
<translation id="8225771182978767009">La persona que configuró esta computadora decidió bloquear este sitio.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Abre la página en una nueva pestaña de incógnito.</translation>
@@ -1403,24 +1421,24 @@ Detalles adicionales:
<translation id="8508648098325802031">Ícono de Búsqueda</translation>
<translation id="8522552481199248698">Chrome puede ayudarte a proteger tu Cuenta de Google y cambiar tu contraseña.</translation>
<translation id="8543181531796978784">Puedes <ph name="BEGIN_ERROR_LINK" />informar un problema de detección<ph name="END_ERROR_LINK" /> o, si comprendes los riesgos de seguridad, puedes <ph name="BEGIN_LINK" />visitar el sitio no seguro<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">¿Tienes preguntas? Comunícate con la persona que supervisa tu perfil.</translation>
<translation id="8553075262323480129">Falló la traducción debido a que no se pudo determinar el idioma de la página.</translation>
<translation id="8557066899867184262">El CVC se encuentra al dorso de tu tarjeta.</translation>
<translation id="8559762987265718583">No se puede establecer una conexión privada a <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> porque la fecha y la hora del dispositivo (<ph name="DATE_AND_TIME" />) son incorrectas.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> sitio sospechoso</translation>
<translation id="8564985650692024650">Chromium te recomienda que restablezcas la contraseña de <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> si la volviste a usar en otros sitios.</translation>
<translation id="8571890674111243710">Traduciendo página a <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Agregar teléfono
</translation>
-<translation id="859285277496340001">El certificado no especifica un mecanismo para verificar si ha sido revocado.</translation>
<translation id="860043288473659153">Nombre del titular de la tarjeta</translation>
<translation id="861775596732816396">Tamaño 4</translation>
-<translation id="8620436878122366504">Tus padres aún no lo aprobaron</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Guardar esta tarjeta para este dispositivo</translation>
<translation id="8626112503828625890">¿Quieres almacenar los detalles de facturación en tu Cuenta de Google?</translation>
+<translation id="8647750283161643317">Restablecer todos los valores predeterminados</translation>
<translation id="8663226718884576429">Resumen del pedido, <ph name="TOTAL_LABEL" />, Más detalles</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, respuesta, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponible</translation>
<translation id="8703575177326907206">Tu conexión a <ph name="DOMAIN" /> no está cifrada.</translation>
<translation id="8718314106902482036">No se completó el pago</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, sugerencia de búsqueda</translation>
@@ -1431,6 +1449,7 @@ Detalles adicionales:
<translation id="8738058698779197622">Para establecer una conexión segura, el reloj debe estar configurado correctamente. Esto se debe a que los certificados que usan los sitios web para su identificación solo son válidos por períodos de tiempo específicos. Debido a que la configuración del reloj del dispositivo es incorrecta, Chromium no puede verificar estos certificados.</translation>
<translation id="8740359287975076522">No se encontró <ph name="HOST_NAME" />’s &lt;abbr id="dnsDefinition"&gt;DNS address&lt;/abbr&gt;. Se está diagnosticando el problema.</translation>
<translation id="874846938927089722">Tarjetas de crédito y prepago aceptadas</translation>
+<translation id="874918643257405732">Agregar esta pestaña a favoritos</translation>
<translation id="8759274551635299824">La tarjeta está vencida</translation>
<translation id="8761567432415473239">La navegación segura de Google <ph name="BEGIN_LINK" />encontró programas peligrosos<ph name="END_LINK" /> recientemente en <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispositivo USB</translation>
@@ -1460,6 +1479,7 @@ Detalles adicionales:
<translation id="8938939909778640821">Tarjetas de crédito y prepago aceptadas</translation>
<translation id="8943282376843390568">Verde lima</translation>
<translation id="8957210676456822347">Autorización de portal cautivo</translation>
+<translation id="8962950042226115166">Sitio sospechoso</translation>
<translation id="8968766641738584599">Guardar la tarjeta</translation>
<translation id="8971063699422889582">El certificado del servidor ha caducado.</translation>
<translation id="8975012916872825179">Incluye información, como números de teléfono, direcciones de correo electrónico y direcciones de envío</translation>
@@ -1482,24 +1502,24 @@ Detalles adicionales:
<translation id="9035022520814077154">Error de seguridad</translation>
<translation id="9038649477754266430">Utilizar un servicio de predicción para cargar las páginas más rápido</translation>
<translation id="9039213469156557790">Además, esta página incluye otros recursos que no son seguros. Otras personas pueden ver estos recursos mientras se encuentran en tránsito, y un atacante puede modificarlos para cambiar el funcionamiento de la página.</translation>
+<translation id="9044359186343685026">Usar Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Has intentado acceder a <ph name="DOMAIN" />, pero el servidor presentó un certificado no válido.</translation>
<translation id="9050666287014529139">Frase de contraseña</translation>
<translation id="9065203028668620118">Editar</translation>
<translation id="9065745800631924235">Búsqueda de <ph name="TEXT" /> desde el historial</translation>
<translation id="9069693763241529744">Bloqueado por una extensión</translation>
-<translation id="9076283476770535406">Es posible que incluya contenido para adultos</translation>
<translation id="9076630408993835509">Este navegador no está administrado por una empresa ni por otra organización. Es posible que la actividad en este dispositivo se administre fuera de Chrome. <ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Se requiere más información</translation>
<translation id="9080712759204168376">Resumen del pedido</translation>
<translation id="9089260154716455634">Política fuera de horario:</translation>
<translation id="9095388113577226029">Más idiomas…</translation>
+<translation id="9098981495403789647">Tu administrador habilitó la Protección contra amenazas de Chrome Enterprise en el navegador. La Protección contra amenazas de Chrome Enterprise tiene acceso a algunos de tus datos.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> suele utilizar la encriptación para proteger la información. Cuando Chromium intentó conectarse a <ph name="SITE" />, el sitio web devolvió credenciales incorrectas y poco comunes. Es posible que un atacante quiera suplantar a <ph name="SITE" /> o que una pantalla de acceso Wi-Fi haya interrumpido la conexión. Tu información permanece segura porque Chromium detuvo la conexión para evitar el intercambio de datos.</translation>
<translation id="9106062320799175032">Agregar dirección de facturación</translation>
<translation id="9114524666733003316">Confirmando tarjeta…</translation>
<translation id="9128870381267983090">Conectarse a una red</translation>
<translation id="9137013805542155359">Mostrar original</translation>
-<translation id="9137248913990643158">Abre Chrome y accede a tu cuenta antes de usar esta app.</translation>
<translation id="9141013498910525015">Administrar direcciones</translation>
<translation id="9148088599418889305">Elegir método de envío</translation>
<translation id="9148507642005240123">&amp;Deshacer Editar</translation>
diff --git a/chromium/components/strings/components_strings_es.xtb b/chromium/components/strings/components_strings_es.xtb
index cd92a7dd5a1..2b93cb30f62 100644
--- a/chromium/components/strings/components_strings_es.xtb
+++ b/chromium/components/strings/components_strings_es.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Añade el nombre de la tarjeta</translation>
<translation id="1089439967362294234">Cambiar contraseña</translation>
+<translation id="1096545575934602868">Este campo no debe tener más de <ph name="MAX_ITEMS_LIMIT" /> entradas. Las entradas adicionales se descartarán.</translation>
<translation id="109743633954054152">Gestiona contraseñas en la configuración de Chrome</translation>
<translation id="1103523840287552314">Traducir siempre del <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Si se selecciona, Chrome almacenará una copia de tu tarjeta en este dispositivo para completar formularios más rápidamente.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Accede a una <ph name="BEGIN_LINK" />copia almacenada en caché<ph name="END_LINK" /> de <ph name="URL" /></translation>
<translation id="1156303062776767266">Estás viendo un archivo local o compartido</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ha cerrado la conexión de forma inesperada.</translation>
+<translation id="115926840831309955">Comprueba el código CVC y vuelve a intentarlo o actualiza la fecha de vencimiento</translation>
<translation id="1161325031994447685">Volver a conectarte a una red Wi-Fi</translation>
<translation id="1165039591588034296">Error</translation>
<translation id="1175364870820465910">Im&amp;primir...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Hay software en tu ordenador que impide que Chrome se conecte a la Web de forma segura" (solo para ordenadores Windows)</translation>
<translation id="1294154142200295408">Variaciones de la línea de comandos</translation>
<translation id="129553762522093515">Cerrado recientemente</translation>
+<translation id="1298536327547837046">Análisis de software malicioso</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Borrar las cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funciones obsoletas</translation>
<translation id="1320233736580025032">Prc1 (sobre)</translation>
<translation id="132301787627749051">Buscar imagen del portapapeles</translation>
<translation id="1323433172918577554">Mostrar más</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Hojas de cálculo de Google</translation>
<translation id="1527263332363067270">Esperando conexión…</translation>
<translation id="1529521330346880926">10x15 (sobre)</translation>
+<translation id="1530707389502320859">El sitio web al que estás intentando acceder parece falso. Los atacantes suelen imitar los sitios web haciendo pequeños cambios en la URL que son difíciles de ver.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Esta página dice</translation>
<translation id="153384715582417236">Eso es todo por ahora</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">Sistema operativo</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">El documento es demasiado grande para poder añadir anotaciones</translation>
-<translation id="1721312023322545264">Necesitas permiso de <ph name="NAME" /> para acceder a este sitio web</translation>
<translation id="1721424275792716183">* El campo es obligatorio</translation>
<translation id="1727741090716970331">Añade un número de tarjeta válido</translation>
<translation id="1728677426644403582">Estás viendo el código fuente de una página web</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Sitios web que visitas y el tiempo que pasas en ellos</translation>
<translation id="1826516787628120939">Comprobando</translation>
<translation id="1834321415901700177">Este sitio web contiene programas dañinos</translation>
+<translation id="1838374766361614909">Borrar búsqueda</translation>
<translation id="1839551713262164453">No se ha podido hacer la validación de los valores de la política porque se han producido errores</translation>
<translation id="1842969606798536927">Pagar</translation>
<translation id="1871208020102129563">Se ha configurado el proxy de forma que use servidores proxy fijos, en lugar de una URL de secuencia de comandos .pac.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Contraer lista</translation>
<translation id="1898423065542865115">Filtrado</translation>
<translation id="1914326953223720820">Servicio de descompresión</translation>
+<translation id="1915697529809968049">¿Usar Touch ID en lugar de CVC?</translation>
<translation id="1916770123977586577">Vuelve a cargar esta página para aplicar la configuración actualizada a este sitio web</translation>
<translation id="1919345977826869612">Anuncios</translation>
<translation id="1919367280705858090">Solucionar un error específico</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Marcadores de <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Error de serialización</translation>
<translation id="1974060860693918893">Configuración avanzada</translation>
+<translation id="1974883374937189061">Ayuda a mejorar la seguridad de Chrome enviando a Google las <ph name="BEGIN_WHITEPAPER_LINK" />URL de algunas de las páginas que visitas, información limitada del sistema y parte del contenido de las páginas<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versión de firmware</translation>
<translation id="1981206234434200693">Borrar los datos del historial de navegación de Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{y una más}other{y # más}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Introduce un año de vencimiento válido</translation>
<translation id="2212735316055980242">Política no encontrada</translation>
<translation id="2213606439339815911">Recuperando entradas...</translation>
+<translation id="2215727959747642672">Edición de archivos</translation>
<translation id="2218879909401188352">Se ha detectado la presencia de atacantes en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> que podrían instalar aplicaciones peligrosas que dañen tu dispositivo, añadir cargos ocultos a tu factura del móvil o robar tu información personal. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Sin conexión a Internet</translation>
<translation id="2230458221926704099">Soluciona los problemas de tu conexión con la <ph name="BEGIN_LINK" />aplicación de diagnóstico<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Enviar ahora</translation>
+<translation id="2248949050832152960">Usar WebAuthn</translation>
<translation id="225207911366869382">Este valor ya no se utiliza para esta política.</translation>
<translation id="2257315177824333709">En estos momentos no se puede guardar tu tarjeta</translation>
<translation id="2262243747453050782">Error de HTTP</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">La URL de búsqueda no es válida.</translation>
<translation id="2482878487686419369">Notificaciones</translation>
<translation id="248348093745724435">Políticas del equipo</translation>
-<translation id="2485387744899240041">Nombres de usuario de tu dispositivo y navegador</translation>
<translation id="2491120439723279231">El certificado del servidor contiene errores.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analizador de archivos JSON</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Volver</translation>
<translation id="2503184589641749290">Tarjetas prepago y de débito aceptadas</translation>
<translation id="2505268675989099013">Proteger cuenta</translation>
+<translation id="2515335152965840738">IGNORAR</translation>
<translation id="2515629240566999685">Comprobar la señal en tu zona</translation>
<translation id="2523886232349826891">Solo se guardará en este dispositivo</translation>
<translation id="2524461107774643265">Añade más información</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Enviar</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Ninguna}=1{1 contraseña de <ph name="DOMAIN_LIST" />}=2{2 contraseñas de <ph name="DOMAIN_LIST" />}other{# contraseñas de <ph name="DOMAIN_LIST" />}}</translation>
<translation id="2666117266261740852">Cierra otras pestañas o aplicaciones</translation>
-<translation id="267371737713284912">pulsa <ph name="MODIFIER_KEY_DESCRIPTION" /> para deshacer</translation>
<translation id="2674170444375937751">¿Seguro que quieres eliminar estas páginas del historial?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Salir</translation>
@@ -334,12 +342,14 @@
<translation id="2704283930420550640">El valor no coincide con el formato.</translation>
<translation id="2705137772291741111">La copia guardada (almacenada en caché) de este sitio web no se ha podido leer.</translation>
<translation id="2709516037105925701">Autocompletar</translation>
-<translation id="2712173769900027643">Solicitar permiso</translation>
<translation id="2713444072780614174">Blanco</translation>
<translation id="2720342946869265578">Cercanas</translation>
<translation id="2721148159707890343">Solicitud correcta</translation>
<translation id="2728127805433021124">El certificado del servidor está firmado con un algoritmo de firma no seguro.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Ejecutar Diagnóstico de conectividad<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Si habilitas estas funciones, podrías perder los datos de navegación o
+ poner en riesgo tu seguridad o privacidad. Las funciones habilitadas se aplican a todos
+ los usuarios de este navegador.</translation>
<translation id="2735043616039983645">Esta política tiene más de una fuente con valores en conflicto.</translation>
<translation id="2738330467931008676">Seleccionar dirección de recogida</translation>
<translation id="2740531572673183784">Aceptar</translation>
@@ -350,16 +360,15 @@
<translation id="2784949926578158345">Se ha restablecido la conexión.</translation>
<translation id="2788784517760473862">Tarjetas de crédito aceptadas</translation>
<translation id="2792012897584536778">Los administradores de este dispositivo han configurado certificados de seguridad que pueden permitirles ver el contenido de los sitios web que visitas.</translation>
-<translation id="2794233252405721443">Sito web bloqueado</translation>
<translation id="2799020568854403057">El sitio web al que vas a acceder contiene aplicaciones dañinas</translation>
<translation id="2799223571221894425">Reiniciar</translation>
<translation id="2803306138276472711">Recientemente, la función de Navegación Segura de Google <ph name="BEGIN_LINK" />ha detectado software malicioso<ph name="END_LINK" /> en <ph name="SITE" />. En ocasiones, los sitios web que normalmente son seguros contienen software malicioso.</translation>
+<translation id="2815364696811431560">SALIR DEL SITIO WEB</translation>
<translation id="2824775600643448204">Barra de direcciones y de búsqueda </translation>
<translation id="2826760142808435982">La conexión se ha encriptado y autenticado con <ph name="CIPHER" />, y utiliza <ph name="KX" /> como el mecanismo de intercambio clave.</translation>
<translation id="2835170189407361413">Eliminar formulario</translation>
<translation id="2847118875340931228">Abrir una ventana de incógnito</translation>
<translation id="2850739647070081192">Invite (sobre)</translation>
-<translation id="2851634818064021665">Necesitas permiso para acceder a este sitio web</translation>
<translation id="2856444702002559011">Es posible que los atacantes estén intentando robar tu información de <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (por ejemplo, contraseñas, mensajes o tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">¿Quieres guardar la tarjeta?</translation>
@@ -384,6 +393,7 @@
<translation id="2985306909656435243">Si se habilita esta opción, Chromium guardará una copia de tu tarjeta en este dispositivo para completar formularios más rápidamente.</translation>
<translation id="2985398929374701810">Introduce una dirección válida</translation>
<translation id="2986368408720340940">Este método de recogida no está disponible. Selecciona otro.</translation>
+<translation id="2987034854559945715">No se ha encontrado ninguna función</translation>
<translation id="2991174974383378012">Compartir con otros sitios web</translation>
<translation id="2991571918955627853">No puedes acceder a <ph name="SITE" /> en este momento porque el sitio web utiliza HSTS. Los ataques y los errores de red suelen ser temporales, por lo que es probable que esta página funcione más tarde.</translation>
<translation id="3005723025932146533">Mostrar copia guardada</translation>
@@ -394,6 +404,7 @@
<translation id="3024663005179499861">Tipo de política incorrecto</translation>
<translation id="3037605927509011580">¡Vaya!</translation>
<translation id="3041612393474885105">Datos del certificado</translation>
+<translation id="3057676462092457419">El modo DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> aún no está disponible. El valor que se le ha asignado es <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (sobre)</translation>
<translation id="3061707000357573562">Aplicar parche a servicio</translation>
<translation id="3064966200440839136">Saldrás del modo de incógnito para realizar un pago en una aplicación externa. ¿Quieres continuar?</translation>
@@ -419,6 +430,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> de <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pago</translation>
<translation id="3207960819495026254">Añadido a marcadores</translation>
+<translation id="3209034400446768650">La página puede cobrarte dinero</translation>
<translation id="3225919329040284222">El servidor ha mostrado un certificado que no coincide con lo que se esperaba. Algunos sitios web tienen un alto nivel de seguridad para garantizar tu protección y esperan ciertas características de los certificados.</translation>
<translation id="3226128629678568754">Pulsa el botón de actualización de página para que se vuelvan a enviar los datos necesarios para cargar la página.</translation>
<translation id="3227137524299004712">Micrófono</translation>
@@ -426,7 +438,6 @@
<translation id="3229041911291329567">Información de la versión del dispositivo y del navegador</translation>
<translation id="323107829343500871">Introduce el código CVC de la tarjeta <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Detectar siempre contenido importante en este sitio</translation>
-<translation id="3254409185687681395">Añadir esta página a marcadores</translation>
<translation id="3270847123878663523">&amp;Deshacer reorganización</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Añadir un nombre de la tarjeta</translation>
@@ -436,7 +447,6 @@
<translation id="3320021301628644560">Añadir dirección de facturación</translation>
<translation id="3324983252691184275">Carmesí</translation>
<translation id="3338095232262050444">Es seguro</translation>
-<translation id="3345135638360864351">No se ha podido enviar la solicitud de acceso a este sitio a <ph name="NAME" />. Vuelve a intentarlo.</translation>
<translation id="3355823806454867987">Cambiar la configuración de proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />no guardará<ph name="END_EMPHASIS" /> la siguiente información:
<ph name="BEGIN_LIST" />
@@ -470,18 +480,15 @@
<translation id="3462200631372590220">Ocultar configuración avanzada</translation>
<translation id="3467763166455606212">El nombre del titular de la tarjeta es obligatorio</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, abierta actualmente; pulsa el tabulador y luego Intro para cambiar a la pestaña abierta</translation>
-<translation id="3479539252931486093">¿No te lo esperabas? <ph name="BEGIN_LINK" />Notifícanoslo<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ahora no</translation>
<translation id="3484560055331845446">Podrías perder el acceso a tu cuenta de Google. Chrome te recomienda que cambies la contraseña ahora. Se te pedirá que inicies sesión.</translation>
<translation id="3495081129428749620">Buscar en la página
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">No hemos podido contactar con tu padre/madre/tutor. Vuelve a intentarlo.</translation>
<translation id="3512163584740124171">Se ha ignorado esta política porque existe otra en el mismo grupo de políticas con mayor prioridad.</translation>
<translation id="3528171143076753409">El certificado de servidor no es de confianza.</translation>
<translation id="3528485271872257980">Marrón oscuro</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Al menos 1 elemento en dispositivos sincronizados}=1{1 elemento (y otros en dispositivos sincronizados)}other{# elementos (y otros en dispositivos sincronizados)}}</translation>
<translation id="3539171420378717834">Guardar una copia de la tarjeta en este dispositivo</translation>
-<translation id="3556433843310711081">Tu administrador puede desbloquearlo</translation>
<translation id="3566021033012934673">La conexión no es privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Una página insertada en <ph name="SITE" /> dice</translation>
@@ -509,6 +516,7 @@
<translation id="3678529606614285348">Abre una página en una nueva ventana de incógnito (Ctrl + Mayús + N).</translation>
<translation id="3679803492151881375">Informe sobre fallos registrado el <ph name="CRASH_TIME" /> y subido el <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Datos del certificado</translation>
+<translation id="3701427423622901115">Se han restablecido los ajustes.</translation>
<translation id="3704162925118123524">La red que estás utilizando puede requerir el acceso a su página de inicio de sesión.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Cargando...</translation>
@@ -525,6 +533,7 @@
<translation id="3748148204939282805">Es posible que los atacantes que se encuentren en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> intenten engañarte para que realices una acción peligrosa, como instalar software o revelar tu información personal (por ejemplo, contraseñas, números de teléfono o tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Se ha producido un error de traducción debido a un problema con el servidor.</translation>
<translation id="3759461132968374835">No se ha notificado ningún fallo recientemente. Los fallos que se hayan producido cuando la función de notificación de fallos estaba inhabilitada no aparecerán en esta página.</translation>
+<translation id="3760561303380396507">¿Usar Windows Hello en lugar de CVC?</translation>
<translation id="3761718714832595332">Ocultar estado</translation>
<translation id="3765032636089507299">La página Navegación Segura está en construcción.</translation>
<translation id="3778403066972421603">¿Quieres guardar esta tarjeta en tu cuenta de Google y en este dispositivo?</translation>
@@ -534,6 +543,7 @@
<translation id="3789155188480882154">Tamaño 16</translation>
<translation id="3797522431967816232">Prc3 (sobre)</translation>
<translation id="3807873520724684969">Contenido dañino bloqueado.</translation>
+<translation id="3808375843007691220">Advertencia: Se han detectado funciones experimentales.</translation>
<translation id="3810973564298564668">Gestionar</translation>
<translation id="382518646247711829">Si utilizas un servidor proxy...</translation>
<translation id="3828924085048779000">La frase de contraseña no puede estar vacía.</translation>
@@ -542,11 +552,11 @@
<translation id="3858027520442213535">Actualizar fecha y hora</translation>
<translation id="3884278016824448484">Identificador de dispositivo en conflicto</translation>
<translation id="3885155851504623709">Municipio</translation>
-<translation id="3886446263141354045">Tu solicitud de acceso a este sitio web se ha enviado a <ph name="NAME" /></translation>
<translation id="3890664840433101773">Añadir correo electrónico</translation>
<translation id="3901925938762663762">La tarjeta ha caducado</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">¿Usar WebAuthn en lugar de CVC?</translation>
<translation id="3946209740501886391">Preguntar siempre en este sitio web</translation>
<translation id="3949571496842715403">Este servidor no ha podido demostrar que es <ph name="DOMAIN" />; su certificado de seguridad no especifica nombres alternativos del sujeto. Este problema puede deberse a una configuración incorrecta o a que un atacante ha interceptado la conexión.</translation>
<translation id="3949601375789751990">Tu historial de navegación aparece aquí</translation>
@@ -557,11 +567,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ninguno}=1{De 1 sitio web }other{De # sitios web }}</translation>
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861">La página <ph name="HOST_NAME" /> está bloqueada</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ha habilitado la protección contra amenazas de Chrome Enterprise en tu navegador. La protección contra amenazas de Chrome Enterprise tiene acceso a algunos de tus datos.</translation>
<translation id="3987940399970879459">Menos de 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{ 1 página web cercana}other{ # páginas web cercanas}}</translation>
<translation id="4030383055268325496">&amp;Deshacer acción de añadir</translation>
<translation id="4032320456957708163">El navegador lo administra <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">El enlace que has abierto lleva a un sitio web que no sueles visitar. Podría intentar confundirte.</translation>
<translation id="4058922952496707368">Clave "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (sobre)</translation>
<translation id="4067947977115446013">Añade una dirección válida</translation>
@@ -574,6 +584,7 @@
<translation id="4103249731201008433">El número de serie del dispositivo no es válido.</translation>
<translation id="410351446219883937">Reproducción automática</translation>
<translation id="4103763322291513355">Accede a la página &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver la lista de URLs no admitidas y otras políticas establecidas por el administrador del sistema.</translation>
+<translation id="4108231218301530806">Usar la huella digital para verificar esta tarjeta la próxima vez</translation>
<translation id="4110652170750985508">Revisa tu pago</translation>
<translation id="4112140312785995938">Ir hacia atrás</translation>
<translation id="4116663294526079822">Permitir siempre en este sitio</translation>
@@ -588,6 +599,7 @@
<translation id="4171400957073367226">La firma de verificación no es válida</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> elemento más}other{<ph name="ITEM_COUNT" /> elementos más}}</translation>
+<translation id="4176463684765177261">Inhabilitado</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Para pagar más rápido la próxima vez, añade tu tarjeta y tu dirección de facturación a tu cuenta de Google.</translation>
<translation id="4196861286325780578">&amp;Rehacer movimiento</translation>
@@ -624,6 +636,7 @@
<translation id="4277028893293644418">Cambiar contraseña</translation>
<translation id="4279811152705618813">Tu <ph name="DEVICE_TYPE" /> lo gestiona <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Se ha guardado esta tarjeta en tu cuenta de Google}other{Se han guardado estas tarjetas en tu cuenta de Google}}</translation>
+<translation id="428847186335018806">Analiza los archivos que descargues o subas en Chrome.</translation>
<translation id="42981349822642051">Mostrar</translation>
<translation id="4302965934281694568">Chou3 (sobre)</translation>
<translation id="4305817255990598646">Cambiar</translation>
@@ -653,7 +666,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Se ha inhabilitado el uso de un servidor proxy, pero se han especificado ajustes de proxy explícitos.</translation>
<translation id="445100540951337728">Tarjetas de débito aceptadas</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> comportamiento sospechoso</translation>
<translation id="4466881336512663640">Se perderán los cambios realizados en el formulario. ¿Seguro que quieres continuar?</translation>
<translation id="4477350412780666475">Pista siguiente</translation>
<translation id="4482953324121162758">Este sitio web no se traducirá.</translation>
@@ -680,6 +692,7 @@
<translation id="4594403342090139922">&amp;Deshacer eliminación</translation>
<translation id="4597348597567598915">Tamaño 8</translation>
<translation id="4600854749408232102">C6/C5 (sobre)</translation>
+<translation id="464342062220857295">Funciones de búsqueda</translation>
<translation id="4646534391647090355">Ir allí ahora</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" />, su certificado de seguridad contiene errores. El problema puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
@@ -688,7 +701,6 @@
<translation id="4691835149146451662">Architecture-A (sobre)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Se ha interrumpido la conexión</translation>
-<translation id="471880041731876836">No tienes permiso para acceder a este sitio web</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ejecutar Diagnósticos de red de Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Volver a cargar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
@@ -716,7 +728,6 @@
<translation id="4816492930507672669">Ajustar a página</translation>
<translation id="4850886885716139402">Ver</translation>
<translation id="4854362297993841467">Este método de entrega no está disponible. Selecciona otro.</translation>
-<translation id="4858792381671956233">Has solicitado permiso a tus padres para poder acceder a este sitio web</translation>
<translation id="4864052566555297930">Consejo de seguridad:</translation>
<translation id="4876188919622883022">Vista simplificada</translation>
<translation id="4876305945144899064">Ningún nombre de usuario</translation>
@@ -740,7 +751,9 @@
<translation id="4974590756084640048">Volver a habilitar advertencias</translation>
<translation id="4984339528288761049">Prc5 (sobre)</translation>
<translation id="4989163558385430922">Ver todo</translation>
+<translation id="4989542687859782284">No disponibles</translation>
<translation id="4989809363548539747">Este complemento no es compatible</translation>
+<translation id="4995216769782533993">Confirma el código de seguridad para compartir la información de tu tarjeta con este sitio web</translation>
<translation id="5002932099480077015">Si se habilita esta opción, Chrome guardará una copia de tu tarjeta en este dispositivo para rellenar la información más rápido.</translation>
<translation id="5015510746216210676">Nombre del equipo:</translation>
<translation id="5017554619425969104">Texto copiado</translation>
@@ -769,6 +782,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verifica tu tarjeta</translation>
<translation id="5135404736266831032">Gestiona tus direcciones...</translation>
<translation id="5138227688689900538">Mostrar menos</translation>
<translation id="5141240743006678641">Cifrar contraseñas sincronizadas con tus credenciales de Google</translation>
@@ -795,6 +809,7 @@
<translation id="5251803541071282808">Nube</translation>
<translation id="5252000469029418751">C7 (sobre)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Las funciones que se aplican a todo el sistema solo las puede establecer el propietario: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Advertencia: Esta política no se ha combinado tal como se especifica en la política PolicyDictionaryMultipleSourceMergeList porque no forma parte de las políticas de diccionario que se pueden combinar.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Finalizar</translation>
@@ -818,7 +833,6 @@
<translation id="536296301121032821">Error al almacenar la configuración de la política</translation>
<translation id="5371425731340848620">Actualizar tarjeta</translation>
<translation id="5377026284221673050">"Tu reloj está atrasado" o "Tu reloj está adelantado" o "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Es posible que esta página intente engañarte, robarte información personal o dañar tu dispositivo. Ten cuidado al introducir información personal y al abrir archivos descargados.</translation>
<translation id="5384855140246857529">Para utilizar las tarjetas en todos tus dispositivos, inicia sesión y activa la sincronización.</translation>
<translation id="5386426401304769735">La cadena de certificados de este sitio web contiene un certificado firmado con SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -832,6 +846,8 @@
<translation id="5457113250005438886">No válido</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> más}other{<ph name="CONTACT_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> más}}</translation>
<translation id="5470861586879999274">&amp;Rehacer edición</translation>
+<translation id="5473728911100096288">Puedes habilitar estas funciones, pero son funciones obsoletas
+ que desaparecerán en las próximas versiones.</translation>
<translation id="5478437291406423475">B6/C4 (sobre)</translation>
<translation id="5481076368049295676">Es posible que este contenido intente instalar software peligroso que robe o elimine tu información en el dispositivo. <ph name="BEGIN_LINK" />Mostrar de todos modos<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Añadir dirección válida</translation>
@@ -855,7 +871,6 @@
<translation id="5570825185877910964">Proteger cuenta</translation>
<translation id="5571083550517324815">Los pedidos no se pueden recoger en esta dirección. Selecciona otra.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 en uso}other{# en uso}})</translation>
-<translation id="5572851009514199876">Abre Chrome e inicia sesión en el navegador para que compruebe si tienes permiso para acceder a este sitio web.</translation>
<translation id="5580958916614886209">Consulta el mes de vencimiento y vuelve a intentarlo</translation>
<translation id="5586446728396275693">Ninguna dirección guardada</translation>
<translation id="5595485650161345191">Editar dirección</translation>
@@ -863,6 +878,7 @@
<translation id="560412284261940334">Administración no admitida</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Este sitio web podría ser falso o fraudulento. Chrome te recomienda que salgas ahora.</translation>
<translation id="5610142619324316209">Comprobar la conexión</translation>
<translation id="5610807607761827392">Puedes gestionar las tarjetas y las direcciones en <ph name="BEGIN_LINK" />Configuración<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">La página <ph name="HOST_NAME" /> te ha redirigido demasiadas veces.</translation>
@@ -886,11 +902,11 @@
<translation id="5720705177508910913">Usuario actual</translation>
<translation id="5728056243719941842">C5 (sobre)</translation>
<translation id="5730040223043577876">Chrome te recomienda que cambies tu contraseña si la has vuelto a utilizar en otros sitios web.</translation>
-<translation id="5732392974455271431">Tus padres pueden desbloquearlo</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Guarda la tarjeta en tu cuenta de Google}other{Guarda las tarjetas en tu cuenta de Google}}</translation>
<translation id="5763042198335101085">Introduce una dirección de correo electrónico válida</translation>
<translation id="5765072501007116331">Selecciona una dirección para ver los métodos de entrega y los requisitos</translation>
<translation id="5778550464785688721">Control total de dispositivos MIDI</translation>
+<translation id="5781136890105823427">Experimento habilitado</translation>
<translation id="578305955206182703">Ámbar</translation>
<translation id="57838592816432529">Silenciar</translation>
<translation id="5784606427469807560">Se ha producido un problema al confirmar tu tarjeta. Comprueba tu conexión a Internet y vuelve a intentarlo.</translation>
@@ -907,13 +923,16 @@
<translation id="5860033963881614850">No</translation>
<translation id="5863847714970149516">Es posible que la página a la que vas a acceder intente aplicar algún cargo</translation>
<translation id="5866257070973731571">Añade un número de teléfono</translation>
+<translation id="5866898949289125849">Estás viendo una página de las herramientas para desarrolladores</translation>
<translation id="5869405914158311789">No se puede acceder a este sitio web</translation>
<translation id="5869522115854928033">Contraseñas guardadas</translation>
<translation id="5887400589839399685">Tarjeta guardada</translation>
<translation id="5893752035575986141">Se aceptan tarjetas de crédito.</translation>
+<translation id="5895138241574237353">Reiniciar</translation>
<translation id="5901630391730855834">Amarillo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizado)</translation>
<translation id="5916664084637901428">Activado</translation>
+<translation id="59174027418879706">Habilitado</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">¿Quieres guardar la tarjeta en tu cuenta de Google?</translation>
<translation id="5922853866070715753">Casi hemos acabado</translation>
@@ -947,6 +966,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">¿Quieres usar las tarjetas en todos tus dispositivos?</translation>
<translation id="6059925163896151826">Dispositivos USB</translation>
+<translation id="6060009363608157444">Modo DnsOverHttps no válido.</translation>
<translation id="6080696365213338172">Has accedido al contenido mediante un certificado proporcionado por el administrador. Los datos que proporciones a <ph name="DOMAIN" /> pueden ser interceptados por tu administrador.</translation>
<translation id="6094273045989040137">Anotar</translation>
<translation id="610911394827799129">Es posible que tu cuenta de Google tenga otros tipos de historial de navegación en la página <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -995,13 +1015,12 @@
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (sobre)</translation>
<translation id="6410264514553301377">Introduce la fecha de vencimiento y el código CVC de la tarjeta <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Has solicitado permiso a uno de tus padres para poder acceder a este sitio web</translation>
<translation id="6415778972515849510">Chromium puede ayudarte a proteger tu cuenta de Google y a cambiar tu contraseña.</translation>
-<translation id="6417515091412812850">No se ha podido comprobar si se ha revocado el certificado.</translation>
<translation id="6431585503458005759">No guardar</translation>
<translation id="6433490469411711332">Editar información de contacto</translation>
<translation id="6433595998831338502">La página <ph name="HOST_NAME" /> ha rechazado la conexión.</translation>
<translation id="6434309073475700221">Rechazar</translation>
+<translation id="6435221585574090192">Comparte con tu administrador los datos de actividades relacionadas con la seguridad que marque la protección contra amenazas de Chrome Enterprise. Estos datos pueden incluir las URL de páginas, los nombres y metadatos de archivos, y tu nombre de usuario en el dispositivo y en Chrome.</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6446163441502663861">Kahu (sobre)</translation>
<translation id="6446608382365791566">Añadir más información</translation>
@@ -1010,20 +1029,19 @@
<translation id="6465306955648956876">Gestiona tus contraseñas...</translation>
<translation id="647261751007945333">Políticas de dispositivos</translation>
<translation id="6476284679642588870">Gestionar métodos de pago</translation>
-<translation id="6477321094435799029">Chrome ha detectado un código inusual en esta página y lo ha bloqueado para proteger tu información personal (por ejemplo, contraseñas, números de teléfono y tarjetas de crédito).</translation>
<translation id="6489534406876378309">Empezar a subir errores</translation>
<translation id="6499038740797743453">¿Quieres cambiar la contraseña?</translation>
<translation id="6507833130742554667">Se aceptan tarjetas de crédito y débito.</translation>
<translation id="650855688985305916">Sí, guardar</translation>
<translation id="6508722015517270189">Reinicia Chrome</translation>
<translation id="6517596291481585650">Advertencia: Esta política no se ha combinado como lista tal como se especifica en la política porque no es una lista.</translation>
+<translation id="6518133107902771759">Verificar</translation>
<translation id="6521745193039995384">Inactiva</translation>
<translation id="6529602333819889595">&amp;Rehacer eliminación</translation>
<translation id="6534179046333460208">Sugerencias de la Web física</translation>
<translation id="6545864417968258051">Búsqueda de dispositivos Bluetooth</translation>
<translation id="6554795675067793129"><ph name="ENROLLMENT_DOMAIN" /> administra tu cuenta.</translation>
<translation id="6556866813142980365">Rehacer</translation>
-<translation id="6563469144985748109">Tu administrador aún no la ha aprobado</translation>
<translation id="6569060085658103619">Estas viendo la página de una extensión</translation>
<translation id="6578796323535178455">C2 (sobre)</translation>
<translation id="6579990219486187401">Rosa claro</translation>
@@ -1041,11 +1059,13 @@
<translation id="6643016212128521049">Eliminar</translation>
<translation id="6644283850729428850">Esta política está obsoleta.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Ninguno}=1{De 1 sitio web (no se cerrará la sesión en tu cuenta de Google)}other{De # sitios web (no se cerrará la sesión en tu cuenta de Google)}}</translation>
+<translation id="6652101503459149953">Usar Windows Hello</translation>
<translation id="6657585470893396449">Contraseña</translation>
<translation id="6670613747977017428">Volver para estar a salvo.</translation>
<translation id="6671697161687535275">¿Quitar sugerencia de formulario de Chromium?</translation>
<translation id="6685834062052613830">Cierra sesión y completa la configuración</translation>
<translation id="6689271823431384964">Chrome te ofrece guardar las tarjetas en tu cuenta de Google porque has iniciado sesión. Puedes cambiar esta opción en los ajustes. El nombre del titular procede de tu cuenta.</translation>
+<translation id="6707256370811247129">Comprueba el contenido de caché y los archivos que has descargado o subido en Chrome.</translation>
<translation id="6710213216561001401">Anterior</translation>
<translation id="6710594484020273272">&lt;Introducir término de búsqueda&gt;</translation>
<translation id="671076103358959139">Token de registro:</translation>
@@ -1053,10 +1073,10 @@
<translation id="6738516213925468394">Tus datos están cifrados con tu <ph name="BEGIN_LINK" />frase de contraseña de sincronización<ph name="END_LINK" /> desde el <ph name="TIME" />. Introdúcela para iniciar la sincronización.</translation>
<translation id="674375294223700098">Error de certificado de servidor desconocido</translation>
<translation id="6744009308914054259">Mientras esperas a que haya conexión, puedes ir a Descargas para leer artículos sin conexión.</translation>
+<translation id="6747611005629681221">Advertencia: Se han detectado funciones experimentales.</translation>
<translation id="6753269504797312559">Valor de la política</translation>
<translation id="6757797048963528358">El dispositivo se ha suspendido.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Uno de tus padres aún no lo ha aprobado</translation>
<translation id="67862343314499040">Violeta</translation>
<translation id="6786747875388722282">Extensiones</translation>
<translation id="6790428901817661496">Reproducir</translation>
@@ -1064,6 +1084,7 @@
<translation id="681021252041861472">Campo obligatorio</translation>
<translation id="6810899417690483278">ID de personalización</translation>
<translation id="6825578344716086703">Has intentado acceder a <ph name="DOMAIN" />, pero el servidor ha presentado un certificado firmado con un algoritmo de firma no seguro (por ejemplo, SHA-1). Una posible causa de este problema es que se hayan falsificado las credenciales de seguridad presentadas por el servidor y que hayas accedido a la página de un atacante en lugar de establecer conexión con el servidor en cuestión.</translation>
+<translation id="6826370046007623921">Prevención de la pérdida de datos</translation>
<translation id="6831043979455480757">Traducir</translation>
<translation id="6839929833149231406">Área</translation>
<translation id="6852204201400771460">¿Quieres volver a cargar la aplicación?</translation>
@@ -1076,7 +1097,6 @@
<translation id="6891596781022320156">No se admite el nivel de la política.</translation>
<translation id="6895330447102777224">Tu tarjeta se ha confirmado</translation>
<translation id="6897140037006041989">User-agent</translation>
-<translation id="6903319715792422884">Ayuda a mejorar la Navegación Segura enviando <ph name="BEGIN_WHITEPAPER_LINK" />datos del sistema y contenido de las páginas<ph name="END_WHITEPAPER_LINK" /> a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuario:</translation>
<translation id="6934672428414710184">Este nombre proviene de tu cuenta de Google</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> no gestiona el sitio web en el que has introducido tu contraseña. Para proteger tu cuenta, no utilices la misma contraseña en otras aplicaciones o sitios web.</translation>
@@ -1121,6 +1141,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> más}other{<ph name="PAYMENT_METHOD_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> más}}</translation>
<translation id="7153618581592392745">Lavanda</translation>
<translation id="717330890047184534">ID de GAIA:</translation>
+<translation id="7174545416324379297">Combinados</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> más}other{<ph name="SHIPPING_OPTION_PREVIEW" /> y <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> más}}</translation>
<translation id="7177397715882417099">El servidor al que te diriges, <ph name="ORIGIN" />, ha solicitado que se aplique una política de seguridad a todas las solicitudes que reciba. Sin embargo, en lugar de proporcionar una política, ha redirigido el navegador a otro sitio web, lo que impide que el navegador procese tu solicitud de <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Guardar y autocompletar métodos de pago</translation>
@@ -1155,6 +1176,7 @@ Más información:
<translation id="7320336641823683070">Ayuda de conexión</translation>
<translation id="733354035281974745">Anulación de la cuenta local del dispositivo</translation>
<translation id="7334320624316649418">&amp;Rehacer reorganización</translation>
+<translation id="7337706099755338005">No está disponible en esta plataforma.</translation>
<translation id="733923710415886693">El certificado del servidor no se ha revelado a través de la Transparencia en los Certificados.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Se ha afiliado:</translation>
@@ -1186,7 +1208,6 @@ Más información:
<translation id="7440140511386898319">Contenido sin conexión</translation>
<translation id="7441627299479586546">Asunto de política incorrecto</translation>
<translation id="7442725080345379071">Naranja claro</translation>
-<translation id="7444046173054089907">Este sitio web se ha bloqueado</translation>
<translation id="7445762425076701745">La identidad del servidor al que estás conectado no se puede validar por completo. Estás conectado a un servidor con un nombre que solo es válido en tu red y cuya propiedad no puede validar en modo alguno una entidad emisora de certificados externa. A pesar de ello, algunas entidades emisoras emiten certificados para esos nombres, por lo que no es posible garantizar que estés conectado al sitio web deseado, en lugar de a un atacante.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Consultar más información<ph name="END_LINK" /> sobre este problema</translation>
<translation id="7455133967321480974">Utilizar valor predeterminado global (Bloquear)</translation>
@@ -1208,9 +1229,9 @@ Más información:
<translation id="7538364083937897561">A2 (sobre)</translation>
<translation id="7542403920425041731">Cuando la confirmes, la información de la tarjeta se compartirá con este sitio web.</translation>
<translation id="7542995811387359312">La opción de autocompletado de la tarjeta de crédito está inhabilitada porque este formulario no utiliza una conexión segura.</translation>
-<translation id="7543525346216957623">Pide permiso a uno de tus padres</translation>
<translation id="7548892272833184391">Solucionar errores de conexión</translation>
<translation id="7549584377607005141">Esta página web necesita los datos introducidos anteriormente para mostrarse correctamente. Puedes volver a enviar los datos, pero se repetirán las acciones que haya realizado la página.</translation>
+<translation id="7550637293666041147">Tu nombre de usuario en el dispositivo y en Chrome</translation>
<translation id="7552846755917812628">Prueba los siguientes consejos:</translation>
<translation id="7554791636758816595">Nueva pestaña</translation>
<translation id="7564049878696755256">Podrías perder el acceso a tu cuenta de <ph name="ORG_NAME" /> o tener problemas de suplantación de identidad. Chrome te recomienda que cambies tu contraseña ahora.</translation>
@@ -1225,6 +1246,7 @@ Más información:
<translation id="7610193165460212391">El valor <ph name="VALUE" /> se encuentra fuera del intervalo.</translation>
<translation id="7613889955535752492">Caducidad: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Has usado anteriormente otra versión de la contraseña de tu cuenta de Google para el cifrado de datos. Introdúcela a continuación.</translation>
+<translation id="7625784245512586808">Protección contra amenazas de Chrome Enterprise</translation>
<translation id="7633909222644580952">Datos de rendimiento e informes sobre fallos</translation>
<translation id="7637571805876720304">¿Quitar tarjeta de crédito de Chromium?</translation>
<translation id="7638605456503525968">Puertos serie</translation>
@@ -1237,7 +1259,6 @@ Más información:
<translation id="7668654391829183341">Dispositivo desconocido</translation>
<translation id="7669271284792375604">Es posible que los atacantes que se encuentren en este sitio web intenten engañarte para que instales programas que empeoren tu experiencia de navegación (por ejemplo, que cambien tu página principal o muestren anuncios adicionales en los sitios web a los que accedas).</translation>
<translation id="7676643023259824263">Buscar texto <ph name="TEXT" /> del portapapeles</translation>
-<translation id="7679176406634891508">Plataforma y nube</translation>
<translation id="7681101578153515023">Cambiar motor de búsqueda</translation>
<translation id="7682287625158474539">Dirección de envío</translation>
<translation id="7687186412095877299">Rellena formularios de pago con tus métodos de pago guardados</translation>
@@ -1252,7 +1273,6 @@ Más información:
<translation id="7723047071702270851">Edita la tarjeta</translation>
<translation id="774634243536837715">Contenido peligroso bloqueado.</translation>
<translation id="7752995774971033316">No administrado</translation>
-<translation id="7755287808199759310">Uno de tus padres puede desbloquearlo</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Puede que el cortafuegos o el software antivirus hayan bloqueado la conexión.</translation>
<translation id="7759163816903619567">Dominio visible:</translation>
@@ -1296,7 +1316,6 @@ Más información:
<translation id="8004582292198964060">Navegador</translation>
<translation id="8009225694047762179">Administrar contraseñas</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Se guardará la tarjeta y su dirección de facturación. Podrás utilizarla cuando inicies sesión como <ph name="USER_EMAIL" />.}other{Se guardarán las tarjetas y sus direcciones de facturación. Podrás utilizarlas cuando inicies sesión como <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">No hemos podido contactar con tus padres. Vuelve a intentarlo.</translation>
<translation id="8025119109950072390">Es posible que los atacantes que se encuentren en este sitio web intenten engañarte para que realices una acción peligrosa, como instalar software o revelar tu información personal (por ejemplo, contraseñas, números de teléfono o tarjetas de crédito).</translation>
<translation id="8034522405403831421">Esta página está escrita en <ph name="SOURCE_LANGUAGE" />. ¿Quieres traducirla al <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Bolígrafo</translation>
@@ -1307,6 +1326,7 @@ Más información:
<translation id="8041940743680923270">Utilizar valor predeterminado global (Preguntar)</translation>
<translation id="8042918947222776840">Seleccionar método de recogida</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" no se ha configurado correctamente. Normalmente, el problema se soluciona al desinstalar "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">A partir de ahora, no tendrás que introducir el código de seguridad de la tarjeta.</translation>
<translation id="8066955247577885446">Se ha producido un error.</translation>
<translation id="8074253406171541171">10x13 (sobre)</translation>
<translation id="8078141288243656252">No se pueden añadir anotaciones a los documentos girados</translation>
@@ -1337,6 +1357,7 @@ Más información:
<translation id="8211406090763984747">La conexión es segura</translation>
<translation id="8218327578424803826">Ubicación asignada:</translation>
<translation id="8220146938470311105">C7/C6 (sobre)</translation>
+<translation id="8220639454292072926">Informes de empresa</translation>
<translation id="8225771182978767009">La persona que ha configurado este ordenador ha elegido bloquear este sitio web.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> o <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Abre una página en una nueva pestaña de incógnito</translation>
@@ -1391,23 +1412,23 @@ Más información:
<translation id="8508648098325802031">Icono de búsqueda</translation>
<translation id="8522552481199248698">Chrome puede ayudarte a proteger tu cuenta de Google y a cambiar tu contraseña.</translation>
<translation id="8543181531796978784">Puedes <ph name="BEGIN_ERROR_LINK" />informar de un problema de detección<ph name="END_ERROR_LINK" /> o, si comprendes los riesgos que conlleva esta acción para tu seguridad, <ph name="BEGIN_LINK" />accede a este sitio web no seguro<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">¿Tienes alguna pregunta? Ponte en contacto con la persona que supervisa tu perfil.</translation>
<translation id="8553075262323480129">La traducción no se ha realizado correctamente porque no se ha podido determinar el idioma de la página.</translation>
<translation id="8557066899867184262">Puedes encontrar el CVC en el reverso de la tarjeta.</translation>
<translation id="8559762987265718583">No se puede establecer una conexión privada con <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> porque la fecha y la hora de tu dispositivo (<ph name="DATE_AND_TIME" />) no son correctas.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> sitio web sospechoso</translation>
<translation id="8564985650692024650">Chromium te recomienda que cambies tu contraseña de <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> si la has vuelto a utilizar en otros sitios web.</translation>
<translation id="8571890674111243710">Traduciendo página a <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Añade un teléfono</translation>
-<translation id="859285277496340001">El certificado no especifica ningún mecanismo para comprobar si se ha revocado.</translation>
<translation id="860043288473659153">Nombre del titular de la tarjeta</translation>
<translation id="861775596732816396">Tamaño 4</translation>
-<translation id="8620436878122366504">Tus padres aún no lo han aprobado</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Guardar esta tarjeta en el dispositivo</translation>
<translation id="8626112503828625890">¿Quieres almacenar los detalles de facturación en tu cuenta de Google?</translation>
+<translation id="8647750283161643317">Restablecer todo a su estado predeterminado</translation>
<translation id="8663226718884576429">Resumen del pedido: <ph name="TOTAL_LABEL" /> (más detalles)</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, respuesta: <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponible</translation>
<translation id="8703575177326907206">Tu conexión a <ph name="DOMAIN" /> no está cifrada.</translation>
<translation id="8718314106902482036">El pago no se ha completado</translation>
<translation id="8719263113926255150">Sugerencia de búsqueda: <ph name="ENTITY" />, <ph name="DESCRIPTION" /></translation>
@@ -1418,6 +1439,7 @@ Más información:
<translation id="8738058698779197622">Para establecer una conexión segura, tu reloj debe estar correctamente configurado. Esto se debe a que los certificados utilizados por los sitios web para identificarse son solo válidos durante períodos específicos de tiempo. Dado que la hora de tu dispositivo no es correcta, Chromium no puede verificar estos certificados.</translation>
<translation id="8740359287975076522">No se ha podido encontrar la &lt;abbr id="dnsDefinition"&gt;dirección DNS&lt;/abbr&gt; de la página <ph name="HOST_NAME" />. Se está diagnosticando el problema.</translation>
<translation id="874846938927089722">Tarjetas prepago y de crédito aceptadas</translation>
+<translation id="874918643257405732">Añadir esta pestaña a marcadores</translation>
<translation id="8759274551635299824">La tarjeta ha caducado</translation>
<translation id="8761567432415473239">La función de Navegación Segura de Google <ph name="BEGIN_LINK" />encontró programas dañinos<ph name="END_LINK" /> recientemente en el sitio <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispositivo USB</translation>
@@ -1447,6 +1469,7 @@ Más información:
<translation id="8938939909778640821">Tarjetas prepago y de crédito aceptadas</translation>
<translation id="8943282376843390568">Lima</translation>
<translation id="8957210676456822347">Autorización de portal cautivo</translation>
+<translation id="8962950042226115166">Sitio web sospechoso</translation>
<translation id="8968766641738584599">Guardar tarjeta</translation>
<translation id="8971063699422889582">El certificado del servidor ha caducado.</translation>
<translation id="8975012916872825179">Incluye información como números de teléfono, direcciones de correo electrónico y direcciones de envío</translation>
@@ -1469,24 +1492,24 @@ Más información:
<translation id="9035022520814077154">Error de seguridad</translation>
<translation id="9038649477754266430">Utilizar un servicio de predicciones para que las páginas se carguen más rápido</translation>
<translation id="9039213469156557790">Además, esta página incluye otros recursos que no son seguros. Otros usuarios pueden acceder a estos recursos mientras están en circulación y un atacante puede modificarlos para cambiar el comportamiento de la página.</translation>
+<translation id="9044359186343685026">Usar Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" />: <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Has intentado acceder a <ph name="DOMAIN" />, pero el servidor ha presentado un certificado no válido.</translation>
<translation id="9050666287014529139">Frase de contraseña</translation>
<translation id="9065203028668620118">Editar</translation>
<translation id="9065745800631924235">Búsqueda de <ph name="TEXT" /> en el historial</translation>
<translation id="9069693763241529744">Bloqueado por una extensión</translation>
-<translation id="9076283476770535406">Es posible que incluya contenido para adultos</translation>
<translation id="9076630408993835509">Este navegador no lo administra ninguna empresa ni organización. Es posible que se administre la actividad de este dispositivo fuera de Chrome. <ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Se necesita más información</translation>
<translation id="9080712759204168376">Resumen del pedido</translation>
<translation id="9089260154716455634">Política fuera del horario:</translation>
<translation id="9095388113577226029">Más idiomas...</translation>
+<translation id="9098981495403789647">Tu administrador ha habilitado la protección contra amenazas de Chrome Enterprise en tu navegador. La protección contra amenazas de Chrome Enterprise tiene acceso a algunos de tus datos.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> utiliza normalmente el cifrado para proteger tu información. Cuando Chromium intentó establecer conexión con <ph name="SITE" />, el sitio web devolvió unas credenciales inusuales e incorrectas. Esto puede ocurrir si un atacante intenta suplantar la identidad de <ph name="SITE" /> o si una pantalla de inicio de sesión Wi-Fi interrumpe la conexión. Tu información sigue estando protegida, ya que Chromium detuvo la conexión antes de que se intercambiaran datos.</translation>
<translation id="9106062320799175032">Añade una dirección de facturación</translation>
<translation id="9114524666733003316">Confirmando tarjeta...</translation>
<translation id="9128870381267983090">Conectarse a la red</translation>
<translation id="9137013805542155359">Mostrar original</translation>
-<translation id="9137248913990643158">Abre Chrome e inicia sesión en el navegador para usar esta aplicación.</translation>
<translation id="9141013498910525015">Gestionar direcciones</translation>
<translation id="9148088599418889305">Seleccionar método de envío</translation>
<translation id="9148507642005240123">&amp;Deshacer edición</translation>
diff --git a/chromium/components/strings/components_strings_et.xtb b/chromium/components/strings/components_strings_et.xtb
index d47fdd13ad4..557fe5d9595 100644
--- a/chromium/components/strings/components_strings_et.xtb
+++ b/chromium/components/strings/components_strings_et.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Kaardil oleva nime lisamine</translation>
<translation id="1089439967362294234">Parooli muutmine</translation>
+<translation id="1096545575934602868">Sellel väljal ei tohi olla üle <ph name="MAX_ITEMS_LIMIT" /> kirje. Kõigist ülejäänud kirjetest loobutakse.</translation>
<translation id="109743633954054152">Hallake paroole Chrome'i seadetes</translation>
<translation id="1103523840287552314">Tõlgi alati: <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Kui see on märgitud, salvestab Chrome teie kaardi koopia sellesse seadmesse, et vormi kiiremini täita.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Hankige juurdepääs aadressi <ph name="URL" /> <ph name="BEGIN_LINK" />vahemällu salvestatud koopiale<ph name="END_LINK" /></translation>
<translation id="1156303062776767266">Vaatate kohalikku või jagatud faili</translation>
<translation id="1158211211994409885">Host <ph name="HOST_NAME" /> sulges ootamatult ühenduse.</translation>
+<translation id="115926840831309955">Kontrollige oma CVC-d ja proovige uuesti või värskendage aegumiskuupäeva</translation>
<translation id="1161325031994447685">Ühendage uuesti WiFi-ga</translation>
<translation id="1165039591588034296">Viga</translation>
<translation id="1175364870820465910">&amp;Prindi...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Teie arvutis olev tarkvara ei luba Chrome'il veebiga turvaliselt ühendust luua” (ainult Windowsi arvutid)</translation>
<translation id="1294154142200295408">Käsurea variatsioonid</translation>
<translation id="129553762522093515">Viimati suletud</translation>
+<translation id="1298536327547837046">Pahavara skannimine</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Kustutage küpsisefailid<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Katkestatud toega funktsioonid</translation>
<translation id="1320233736580025032">Prc1 (ümbrik)</translation>
<translation id="132301787627749051">Lõikelaua kujutise otsimine</translation>
<translation id="1323433172918577554">Kuva rohkem</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google'i arvutustabelid</translation>
<translation id="1527263332363067270">Ühenduse ootamine …</translation>
<translation id="1529521330346880926">10x15 (ümbrik)</translation>
+<translation id="1530707389502320859">Sait, mida üritasite külastada, näib olevat võltsitud. Ründajad imiteerivad mõnikord saite, tehes URL-is väikeseid raskestimärgatavaid muudatusi.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Leht ütleb</translation>
<translation id="153384715582417236">See on praeguseks kõik</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokument on märkuste lisamiseks liiga suur</translation>
-<translation id="1721312023322545264">Vajate saidi külastamiseks halduri <ph name="NAME" /> luba</translation>
<translation id="1721424275792716183">* Kohustuslik väli</translation>
<translation id="1727741090716970331">Kehtiva kaardinumbri lisamine</translation>
<translation id="1728677426644403582">Vaatate veebilehe lähtekoodi</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Teie külastatavad veebisaidid ja nendel veedetav aeg</translation>
<translation id="1826516787628120939">Kontrollimine</translation>
<translation id="1834321415901700177">See sait sisaldab kahjulikke programme</translation>
+<translation id="1838374766361614909">Otsingu kustutamine</translation>
<translation id="1839551713262164453">Reegli väärtuste valideerimine nurjus ja selle käigus ilmnesid vead</translation>
<translation id="1842969606798536927">Maksmine</translation>
<translation id="1871208020102129563">Puhverserver on seatud kasutama fikseeritud puhverservereid, mitte pac-skripti URL-i.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Ahenda loend</translation>
<translation id="1898423065542865115">Filtreerimine</translation>
<translation id="1914326953223720820">Lahtipakkimisteenus</translation>
+<translation id="1915697529809968049">Kas kasutada CVC asemel Touch ID-d?</translation>
<translation id="1916770123977586577">Laadige leht uuesti, et rakendada värskendatud seaded saidile</translation>
<translation id="1919345977826869612">Reklaamid</translation>
<translation id="1919367280705858090">Konkreetse veateate puhul abi hankimine</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Domeeni <ph name="DOMAIN" /> järjehoidjad</translation>
<translation id="1973335181906896915">Viga jadaks teisendamisel</translation>
<translation id="1974060860693918893">Täpsemad</translation>
+<translation id="1974883374937189061">Aidake täiustada Chrome'i turvalisust, saates Google'ile <ph name="BEGIN_WHITEPAPER_LINK" />mõne teie külastatud lehe URL-i, piiratud süsteemiteabe ja mõne lehe sisu<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Püsivara versioon</translation>
<translation id="1981206234434200693">Kustuta Chrome'i sirvimisajaloo andmed</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ja veel 1}other{ja veel #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Sisestage kehtiv aegumisaasta</translation>
<translation id="2212735316055980242">Reeglit ei leitud</translation>
<translation id="2213606439339815911">Kirjete toomine ...</translation>
+<translation id="2215727959747642672">Failide muutmine</translation>
<translation id="2218879909401188352">Saidil <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> olevad ründajad võivad installida ohtlikke rakendusi, mis kahjustavad teie seadet, lisavad mobiiliarvele varjatud kulusid või varastavad teie isiklikke andmeid. <ph name="BEGIN_LEARN_MORE_LINK" />Lisateave<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Interneti-ühendus puudub</translation>
<translation id="2230458221926704099">Parandage oma ühendus <ph name="BEGIN_LINK" />diagnostikarakenduse<ph name="END_LINK" /> abil</translation>
<translation id="2239100178324503013">Saada kohe</translation>
+<translation id="2248949050832152960">Kasuta WebAuthn-autentimist</translation>
<translation id="225207911366869382">Väärtus on eeskirjade jaoks aegunud.</translation>
<translation id="2257315177824333709">Vabandust, teie kaarti ei saa praegu salvestada</translation>
<translation id="2262243747453050782">HTTP viga</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Kehtetu otsingu URL.</translation>
<translation id="2482878487686419369">Märguanded</translation>
<translation id="248348093745724435">Seadme reeglid</translation>
-<translation id="2485387744899240041">Teie seadme ja brauseri kasutajanimed</translation>
<translation id="2491120439723279231">Serveri sertifikaat sisaldab vigu.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON-i parser</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Mine tagasi</translation>
<translation id="2503184589641749290">Aktsepteeritavad ettemakstud ja deebetkaardid</translation>
<translation id="2505268675989099013">Konto kaitsmine</translation>
+<translation id="2515335152965840738">EIRA</translation>
<translation id="2515629240566999685">Kontrollige oma piirkonna signaali</translation>
<translation id="2523886232349826891">Salvestatakse ainult sellesse seadmesse</translation>
<translation id="2524461107774643265">Lisateabe lisamine</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Esita</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Puudub}=1{1 parool (loendile <ph name="DOMAIN_LIST" />)}=2{2 parooli (loendile <ph name="DOMAIN_LIST" />)}other{# parooli (loendile <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Sulgege muud vahelehed või rakendused</translation>
-<translation id="267371737713284912">tagasivõtmiseks vajutage klahvi <ph name="MODIFIER_KEY_DESCRIPTION" /></translation>
<translation id="2674170444375937751">Olete kindel, et soovite need leheküljed oma ajaloost kustutada?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Lahku</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Väärtus ei vasta vormingule.</translation>
<translation id="2705137772291741111">Selle saidi (vahemällu) salvestatud koopia oli loetamatu.</translation>
<translation id="2709516037105925701">Automaatne täitmine</translation>
-<translation id="2712173769900027643">Küsi luba</translation>
<translation id="2713444072780614174">Valge</translation>
<translation id="2720342946869265578">Läheduses</translation>
<translation id="2721148159707890343">Taotlus õnnestus</translation>
<translation id="2728127805433021124">Serveri sertifikaat on allkirjastatud nõrga allkirjaalgoritmiga.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Ühenduvusdiagnostika käitamine<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Nende funktsioonide lubamisel võivad sirvimisandmed kaotsi minna või
+ teie turvalisus või privaatsus võib ohtu sattuda. Lubatud funktsioonid on
+ saadaval kõigile selle brauseri kasutajatele.</translation>
<translation id="2735043616039983645">Selle reegli puhul on leitud rohkem kui üks vastuoluliste väärtustega allikas.</translation>
<translation id="2738330467931008676">Valige kättesaamisaadress</translation>
<translation id="2740531572673183784">Ok</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Ühendus lähtestati.</translation>
<translation id="2788784517760473862">Aktsepteeritavad krediitkaardid</translation>
<translation id="2792012897584536778">Seadme administraatorid on seadistanud turvasertifikaadid, mille abil võivad nad näha teie külastatavate veebisaitide sisu.</translation>
-<translation id="2794233252405721443">Sait on blokeeritud</translation>
<translation id="2799020568854403057">Sait, mille soovite avada, sisaldab kahjulikke rakendusi</translation>
<translation id="2799223571221894425">Taaskäivita</translation>
<translation id="2803306138276472711">Google'i ohutu sirvimise teenus <ph name="BEGIN_LINK" />tuvastas hiljuti pahavara<ph name="END_LINK" /> saidil <ph name="SITE" />. Tavaliselt turvalisi veebisaite võidakse mõnikord nakatada pahavaraga.</translation>
+<translation id="2815364696811431560">LAHKU SAIDILT</translation>
<translation id="2824775600643448204">Aadressi- ja otsinguriba</translation>
<translation id="2826760142808435982">Ühendus on krüptitud ja autenditud üksusega <ph name="CIPHER" /> ning kasutab peamise vahetusmehhanismina üksust <ph name="KX" />.</translation>
<translation id="2835170189407361413">Tühjenda vorm</translation>
<translation id="2847118875340931228">Ava inkognito aken</translation>
<translation id="2850739647070081192">Invite (ümbrik)</translation>
-<translation id="2851634818064021665">Vajate selle saidi külastamiseks luba</translation>
<translation id="2856444702002559011">Ründajad võivad üritada varastada teie teavet (nt paroole, sõnumeid või krediitkaarditeavet) saidilt <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />. <ph name="BEGIN_LEARN_MORE_LINK" />Lisateave<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Kas salvestada kaart?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Kui see on lubatud, salvestab Chromium teie kaardi koopia vormide kiiremaks täitmiseks sellesse seadmesse.</translation>
<translation id="2985398929374701810">Sisestage kehtiv aadress</translation>
<translation id="2986368408720340940">See kättesaamisviis pole saadaval. Proovige mõnda teist kättesaamisviisi.</translation>
+<translation id="2987034854559945715">Sobivaid funktsioone ei leitud</translation>
<translation id="2991174974383378012">Veebisaitidega jagamine</translation>
<translation id="2991571918955627853">Te ei saa saiti <ph name="SITE" /> praegu külastada, sest veebisait kasutab HSTS-i. Võrguvead ja -rünnakud on tavaliselt ajutised, nii et leht tõenäoliselt hiljem töötab.</translation>
<translation id="3005723025932146533">Kuva salvestatud koopia</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Reegli tüüp on vale</translation>
<translation id="3037605927509011580">Ups, ebaõnn!</translation>
<translation id="3041612393474885105">Sertifikaadi andmed</translation>
+<translation id="3057676462092457419">DnsOverHttps-režiimi <ph name="SECURE_DNS_MODE_SECURE" /> ei toetata veel. Režiimiks on määratud <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (ümbrik)</translation>
<translation id="3061707000357573562">Teenuse paikamine</translation>
<translation id="3064966200440839136">Väljute inkognito režiimist, et välise rakenduse kaudu maksta. Kas soovite jätkata?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956">Printer <ph name="PRINTER_NAME" /> serveris <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Tühista makse</translation>
<translation id="3207960819495026254">Järjehoidjatesse lisatud</translation>
+<translation id="3209034400446768650">Leht võib võtta tasu</translation>
<translation id="3225919329040284222">Serveri esitatud sertifikaat ei vasta sisseehitatud ootustele. Ootused on teie kaitsmiseks kaasatud kindlate kõrge turvalisusega veebisaitide jaoks.</translation>
<translation id="3226128629678568754">Lehe laadimiseks vajalike andmete uuesti esitamiseks vajutage uuesti laadimise nuppu.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Teie seadme ja brauseri versiooniteave</translation>
<translation id="323107829343500871">Krediitkaardi <ph name="CREDIT_CARD" /> CVC sisestamine</translation>
<translation id="3234666976984236645">Sellel saidil olulise sisu alati tuvastamine</translation>
-<translation id="3254409185687681395">Lisa see lehekülg järjehoidjatesse</translation>
<translation id="3270847123878663523">&amp;Võta korrastamine tagasi</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Kaardil oleva nime lisamine</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Arveldusaadressi lisamine</translation>
<translation id="3324983252691184275">Tulipunane</translation>
<translation id="3338095232262050444">Turvaline</translation>
-<translation id="3345135638360864351">Saidi külastamise taotlust ei õnnestunud saata kontaktile <ph name="NAME" />. Proovige uuesti.</translation>
<translation id="3355823806454867987">Muuda puhverserveri seadeid ...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />ei salvesta<ph name="END_EMPHASIS" /> järgmist teavet:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Peida täpsemad üksikasjad</translation>
<translation id="3467763166455606212">Kaardiomaniku nimi on kohustuslik</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, praegu avatud, vajutage avatud vahelehe aktiveerimiseks tabeldusklahvi ja seejärel sisestusklahvi</translation>
-<translation id="3479539252931486093">Kas see oli ootamatu? <ph name="BEGIN_LINK" />Andke meile sellest teada<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Mitte praegu</translation>
<translation id="3484560055331845446">Võite kaotada juurdepääsu oma Google'i kontole. Chrome soovitab teil kohe oma parooli muuta. Teil palutakse sisse logida.</translation>
<translation id="3495081129428749620">Lehelt otsimine
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Teie vanemaga ei õnnestunud praegu ühendust võtta. Proovige hiljem uuesti.</translation>
<translation id="3512163584740124171">Seda reeglit eiratakse, kuna sama reegligrupi teisel reeglil on kõrgem prioriteet.</translation>
<translation id="3528171143076753409">Serveri sertifikaat ei ole usaldusväärne.</translation>
<translation id="3528485271872257980">Tumepruun</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Vähemalt 1 üksus sünkroonitud seadmetes}=1{1 üksus (ja rohkem sünkroonitud seadmetes)}other{# üksust (ja rohkem sünkroonitud seadmetes)}}</translation>
<translation id="3539171420378717834">Säilita kaardi koopia seadmes</translation>
-<translation id="3556433843310711081">Haldur saab blokeeringu teie eest tühistada</translation>
<translation id="3566021033012934673">Teie ühendus ei ole privaatne</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Manustatud leht saidil <ph name="SITE" /> ütleb</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Avage leht uues inkognito aknas (Ctrl + tõstuklahv + N)</translation>
<translation id="3679803492151881375">Krahhiaruanne jäädvustati ajal <ph name="CRASH_TIME" />, see laaditi üles ajal <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Sertifikaadi andmed</translation>
+<translation id="3701427423622901115">Lähtestamine kinnitati.</translation>
<translation id="3704162925118123524">Võrk, mida kasutate, võib nõuda sisselogimislehe külastamist.</translation>
<translation id="3704609568417268905"><ph name="TIME" />, <ph name="BOOKMARKED" />, <ph name="TITLE" />, <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Laadimine...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Saidil <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> asuvad ründajad võivad teid meelitada ohtlikele tegevustele, nagu tarkvara installimine või isiklike andmete (nt paroolid, telefoninumbrid või krediitkaarditeave) avaldamine. <ph name="BEGIN_LEARN_MORE_LINK" />Lisateave<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Tõlkimine ebaõnnestus serverivea tõttu.</translation>
<translation id="3759461132968374835">Hiljuti teatatud krahhe ei ole. Siin ei ilmu krahhid, mis toimusid siis, kui krahhide aruandlus oli keelatud.</translation>
+<translation id="3760561303380396507">Kas kasutada CVC asemel Windows Hello autentimist?</translation>
<translation id="3761718714832595332">Peida olek</translation>
<translation id="3765032636089507299">Google'i ohutu sirvimise leht on loomisel.</translation>
<translation id="3778403066972421603">Kas soovite selle kaardi salvestada oma Google'i kontole ja sellesse seadmesse?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Suurus 16</translation>
<translation id="3797522431967816232">Prc3 (ümbrik)</translation>
<translation id="3807873520724684969">Kahjulik sisu on blokeeritud.</translation>
+<translation id="3808375843007691220">Hoiatus: katselised funktsioonid!</translation>
<translation id="3810973564298564668">Halda</translation>
<translation id="382518646247711829">Kui kasutate puhverserverit ...</translation>
<translation id="3828924085048779000">Tühi parool ei ole lubatud.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Värskenda kuupäeva ja kellaaega</translation>
<translation id="3884278016824448484">Seadme identifikaator on konfliktne</translation>
<translation id="3885155851504623709">Vald</translation>
-<translation id="3886446263141354045">Teie juurdepääsutaotlus sellele saidile saadeti kasutajale <ph name="NAME" /></translation>
<translation id="3890664840433101773">E-posti aadressi lisamine</translation>
<translation id="3901925938762663762">Kaart on aegunud</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Kas kasutada CVC asemel WebAuthn-autentimist?</translation>
<translation id="3946209740501886391">Küsi sellel saidil alati</translation>
<translation id="3949571496842715403">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />; selle turvasertifikaat ei määra laiendust Subject Alternative Names. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
<translation id="3949601375789751990">Siin kuvatakse teie sirvimisajalugu</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ükski}=1{1 saidilt }other{# saidilt }}</translation>
<translation id="397105322502079400">Arvutamine ...</translation>
<translation id="3973234410852337861">Host <ph name="HOST_NAME" /> on blokeeritud</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> lubas teie brauseris funktsiooni Chrome Enterprise Threat Protection. Funktsioonil Chrome Enterprise Threat Protection on juurdepääs osadele teie andmetele.</translation>
<translation id="3987940399970879459">Alla 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{Läheduses on 1 veebileht}other{Läheduses on # veebilehte}}</translation>
<translation id="4030383055268325496">&amp;Võta lisamine tagasi</translation>
<translation id="4032320456957708163">Teie brauserit haldab <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Avatud link suunab saidile, mida te tavaliselt ei külasta. See võib üritada teid segadusse ajada.</translation>
<translation id="4058922952496707368">Võti „<ph name="SUBKEY" />”: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (ümbrik)</translation>
<translation id="4067947977115446013">Sobiva aadressi lisamine</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Seadme seerianumber on kehtetu</translation>
<translation id="410351446219883937">Automaatesitus</translation>
<translation id="4103763322291513355">Külastage saiti &lt;strong&gt;chrome://policy&lt;/strong&gt;, et näha mustas nimekirjas olevate URL-ide loendit ja teisi reegleid, mille on jõustanud teie süsteemiadministraator.</translation>
+<translation id="4108231218301530806">Kasuta järgmisel korral selle kaardi kinnitamiseks sõrmejälge.</translation>
<translation id="4110652170750985508">Vaadake makse üle</translation>
<translation id="4112140312785995938">Keri tagasi</translation>
<translation id="4116663294526079822">Luba sellel saidil alati</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Sobimatu kinnitusallkiri</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Veel <ph name="ITEM_COUNT" /> üksus}other{Veel <ph name="ITEM_COUNT" /> üksust}}</translation>
+<translation id="4176463684765177261">Keelatud</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" />: <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Kui soovite järgmisel korral kiiremini maksta, lisage kaart ja arveldusaadress oma Google'i kontole.</translation>
<translation id="4196861286325780578">&amp;Teisalda uuesti</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Lähtesta parool</translation>
<translation id="4279811152705618813">Teie seadet <ph name="DEVICE_TYPE" /> haldab <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{See kaart salvestati teie Google'i kontole}other{Need kaardid salvestati teie Google'i kontole}}</translation>
+<translation id="428847186335018806">Skannitakse faile, mille Chrome'is alla või üles laadite.</translation>
<translation id="42981349822642051">Laienda</translation>
<translation id="4302965934281694568">Chou3 (ümbrik)</translation>
<translation id="4305817255990598646">Lüliti</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Postkaart)</translation>
<translation id="443673843213245140">Puhverserveri kasutamine on keelatud, kuid määratud on ka konkreetne puhverserveri konfigureerimine.</translation>
<translation id="445100540951337728">Aktsepteeritavad deebetkaardid</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> kahtlane käitumine</translation>
<translation id="4466881336512663640">Vormil tehtud muudatused lähevad kaotsi. Kas soovite kindlasti jätkata?</translation>
<translation id="4477350412780666475">Järgmine lugu</translation>
<translation id="4482953324121162758">Seda saiti ei tõlgita.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Võta kustutamine tagasi</translation>
<translation id="4597348597567598915">Suurus 8</translation>
<translation id="4600854749408232102">C6/C5 (ümbrik)</translation>
+<translation id="464342062220857295">Otsingufunktsioonid</translation>
<translation id="4646534391647090355">Vii mind kohe sinna</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />, selle turvasertifikaat sisaldab vigu. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (ümbrik)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Teie ühendus katkes</translation>
-<translation id="471880041731876836">Teil ei ole selle saidi külastamiseks luba</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windowsi võrgudiagnostika käitamine<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Laadi reeglid uuesti</translation>
<translation id="4728558894243024398">Platvorm</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Sobita lehele</translation>
<translation id="4850886885716139402">Kuva</translation>
<translation id="4854362297993841467">See kohaletoimetamisviis pole saadaval. Proovige mõnda teist kohaletoimetamisviisi.</translation>
-<translation id="4858792381671956233">Küsisite oma vanematelt, kas võite seda lehte külastada</translation>
<translation id="4864052566555297930">Ohutusnõuanne:</translation>
<translation id="4876188919622883022">Lihtsustatud vaade</translation>
<translation id="4876305945144899064">Kasutajanimi puudub</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Luba hoiatused uuesti</translation>
<translation id="4984339528288761049">Prc5 (ümbrik)</translation>
<translation id="4989163558385430922">Kuva kõik</translation>
+<translation id="4989542687859782284">Pole saadaval</translation>
<translation id="4989809363548539747">Seda pistikprogrammi ei toetata</translation>
+<translation id="4995216769782533993">Kui soovite kaardi üksikasju selle saidiga jagada, kinnitage turvakood</translation>
<translation id="5002932099480077015">Kui see on lubatud, salvestab Chrome teie kaardi koopia vormide kiiremini täitmiseks sellesse seadmesse.</translation>
<translation id="5015510746216210676">Seadme nimi:</translation>
<translation id="5017554619425969104">Teie kopeeritud tekst</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bitine)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Kaardi kinnitamine</translation>
<translation id="5135404736266831032">Halda aadresse …</translation>
<translation id="5138227688689900538">Kuva vähem</translation>
<translation id="5141240743006678641">Krüpteerige sünkroonitud paroolid oma Google'i mandaadiga</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Pilv</translation>
<translation id="5252000469029418751">C7 (ümbrik)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Kogu süsteemis kehtivaid funktsioone saab määrata ainult omanik: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Hoiatus! Seda reeglit ei liidetud reeglis PolicyDictionaryMultipleSourceMergeList määratud viisil, kuna see ei ole osa sõnastiku reeglitest, mida saab liita.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Lõpeta</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Reegli seadete talletamine ebaõnnestus</translation>
<translation id="5371425731340848620">Värskendage kaarti</translation>
<translation id="5377026284221673050">„Teie kell on ajast maas” või „Teie kell on ajast ees” või „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;”</translation>
-<translation id="5377179979757081683">See leht võib üritada teid petta, varastada teie isiklikke andmeid või kahjustada teie seadet. Olge isiklike andmete sisestamisel või allalaaditud failide avamisel ettevaatlik.</translation>
<translation id="5384855140246857529">Kõigis seadmetes kaartide kasutamiseks logige sisse ja lülitage sünkroonimine sisse.</translation>
<translation id="5386426401304769735">Selle saidi sertifikaadiahel sisaldab sertifikaati, mis on allkirjastatud SHA-1-ga.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Kehtetu</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> ja veel <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> ja veel <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Muuda uuesti</translation>
+<translation id="5473728911100096288">Kui lubate need funktsioonid, kasutate katkestatud toega funktsioone,
+ mis eemaldatakse tulevastest versioonidest.</translation>
<translation id="5478437291406423475">B6/C4 (ümbrik)</translation>
<translation id="5481076368049295676">See sisu võib üritada installida teie seadmesse ohtlikku tarkvara, mis varastab või kustutab teie teavet. <ph name="BEGIN_LINK" />Kuva ikkagi<ph name="END_LINK" />.</translation>
<translation id="54817484435770891">Sisestage sobiv aadress</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Kaitse kontot</translation>
<translation id="5571083550517324815">Sellelt aadressilt ei saa kaupa kätte. Valige mõni teine aadress.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{kasutusel on 1}other{kasutusel on #}})</translation>
-<translation id="5572851009514199876">Alustage ja logige Chrome'i sisse, et Chrome saaks kontrollida, kas teil on luba sellele saidile juurdepääsemiseks.</translation>
<translation id="5580958916614886209">Kontrollige aegumiskuud ja proovige uuesti</translation>
<translation id="5586446728396275693">Salvestatud aadresse pole</translation>
<translation id="5595485650161345191">Muuda aadressi</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Haldust ei toetata</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">See sait võib olla võlts või petturlik. Chrome soovitab kohe lahkuda.</translation>
<translation id="5610142619324316209">Kontrollige ühendust</translation>
<translation id="5610807607761827392">Kaarte ja aadresse saate hallata menüüs <ph name="BEGIN_LINK" />Seaded<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Host <ph name="HOST_NAME" /> suunas teid liiga mitu korda ümber.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Praegune kasutaja</translation>
<translation id="5728056243719941842">C5 (ümbrik)</translation>
<translation id="5730040223043577876">Chrome soovitab teil parooli lähtestada, kui kasutasite seda ka muudel saitidel.</translation>
-<translation id="5732392974455271431">Vanemad saavad blokeeringu teie eest tühistada</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Salvestage kaart oma Google'i kontole}other{Salvestage kaardid oma Google'i kontole}}</translation>
<translation id="5763042198335101085">Sisestage kehtiv e-posti aadress</translation>
<translation id="5765072501007116331">Kohaletoimetamisviiside ja nõuete nägemiseks valige aadress</translation>
<translation id="5778550464785688721">MIDI-seadmete täielik juhtimine</translation>
+<translation id="5781136890105823427">Katse on lubatud</translation>
<translation id="578305955206182703">Merevaigukollane</translation>
<translation id="57838592816432529">Vaigista</translation>
<translation id="5784606427469807560">Kaardi kinnitamisel tekkis probleem. Kontrollige Interneti-ühendust ja proovige uuesti.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Väljas</translation>
<translation id="5863847714970149516">Järgmisel lehel võidakse teilt üritada tasu võtta</translation>
<translation id="5866257070973731571">Telefoninumbri lisamine</translation>
+<translation id="5866898949289125849">Vaatate arendaja tööriistade lehte</translation>
<translation id="5869405914158311789">Selle saidiga ei saa ühendust</translation>
<translation id="5869522115854928033">Salvestatud paroolid</translation>
<translation id="5887400589839399685">Kaart on salvestatud</translation>
<translation id="5893752035575986141">Kaupmees aktsepteerib krediitkaarte.</translation>
+<translation id="5895138241574237353">Taaskäivitamine</translation>
<translation id="5901630391730855834">Kollane</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sünkroonitud)</translation>
<translation id="5916664084637901428">Sees</translation>
+<translation id="59174027418879706">Lubatud</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Kas salvestada kaart Google'i kontole?</translation>
<translation id="5922853866070715753">Peaaegu valmis</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Kas soovite kaarte kasutada kõigis oma seadmetes?</translation>
<translation id="6059925163896151826">USB-seadmed</translation>
+<translation id="6060009363608157444">Kehtetu DnsOverHttps-režiim.</translation>
<translation id="6080696365213338172">Olete sisule juurde pääsenud administraatori antud sertifikaadiga. Administraator saab domeenile <ph name="DOMAIN" /> edastatavaid andmeid kinni pidada.</translation>
<translation id="6094273045989040137">Lisa märkus</translation>
<translation id="610911394827799129">Aadressil <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> võib teie Google'i kontol olla muus vormis sirvimisajalugu</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Muuda järjehoidjat</translation>
<translation id="6406765186087300643">C0 (ümbrik)</translation>
<translation id="6410264514553301377">Sisestage krediitkaardi <ph name="CREDIT_CARD" /> aegumiskuupäev ja CVC</translation>
-<translation id="6414888972213066896">Küsisite vanemalt, kas võite seda saiti külastada</translation>
<translation id="6415778972515849510">Chromium aitab teil oma Google'i kontot kaitsta ja parooli muuta.</translation>
-<translation id="6417515091412812850">Ei saa kontrollida sertifikaadi võimalikku tühistamist.</translation>
<translation id="6431585503458005759">Ära salvesta</translation>
<translation id="6433490469411711332">Kontaktandmete muutmine</translation>
<translation id="6433595998831338502">Host <ph name="HOST_NAME" /> keeldus ühendamast.</translation>
<translation id="6434309073475700221">Tühista</translation>
+<translation id="6435221585574090192">Administraatoriga jagatakse andmeid turvasündmuste kohta, mille Chrome Enterprise Threat Protection on esile tõstnud. See võib hõlmata lehtede URL-e, failide nimesid ja metaandmeid, teie seadme kasutajanime ning Chrome'i kasutajanime.</translation>
<translation id="6440503408713884761">Eiras</translation>
<translation id="6446163441502663861">Kahu (ümbrik)</translation>
<translation id="6446608382365791566">Lisateabe lisamine</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Halda paroole …</translation>
<translation id="647261751007945333">Seadme reeglid</translation>
<translation id="6476284679642588870">Makseviiside haldamine</translation>
-<translation id="6477321094435799029">Chrome tuvastas sellel lehel ebatavalise koodi ja blokeeris selle, et teie isiklikke andmeid (nt paroolid, telefoninumbrid ja krediitkaardiandmed) kaitsta.</translation>
<translation id="6489534406876378309">Krahhide üleslaadimise alustamine</translation>
<translation id="6499038740797743453">Kas lähtestada parool?</translation>
<translation id="6507833130742554667">Kaupmees aktsepteerib krediit- ja deebetkaarte.</translation>
<translation id="650855688985305916">Jah, salvesta</translation>
<translation id="6508722015517270189">Taaskäivitage Chrome</translation>
<translation id="6517596291481585650">Hoiatus! Seda reeglit ei liidetud reeglis määratud loendina, kuna see ei ole loend.</translation>
+<translation id="6518133107902771759">Kinnita</translation>
<translation id="6521745193039995384">Pole aktiivne</translation>
<translation id="6529602333819889595">&amp;Kustuta uuesti</translation>
<translation id="6534179046333460208">Füüsilise veebi soovitused</translation>
<translation id="6545864417968258051">Bluetoothi otsimine</translation>
<translation id="6554795675067793129">Teie kontot haldab <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Tee uuesti</translation>
-<translation id="6563469144985748109">Haldur ei ole seda veel kinnitanud</translation>
<translation id="6569060085658103619">Vaatate laienduse lehte</translation>
<translation id="6578796323535178455">C2 (ümbrik)</translation>
<translation id="6579990219486187401">Heleroosa</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Tühjenda</translation>
<translation id="6644283850729428850">See reegel on aegunud.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Mitte ükski}=1{1 saidilt (teid ei logita Google'i kontolt välja)}other{# saidilt (teid ei logita Google'i kontolt välja)}}</translation>
+<translation id="6652101503459149953">Kasuta Windows Hello autentimist</translation>
<translation id="6657585470893396449">Parool</translation>
<translation id="6670613747977017428">Tagasi turvalisusse.</translation>
<translation id="6671697161687535275">Kas eemaldada Chromiumist vormi soovitus?</translation>
<translation id="6685834062052613830">Logige välja ja viige seadistus lõpule</translation>
<translation id="6689271823431384964">Chrome pakub kaartide salvestamist teie Google'i kontole, kuna olete sisse logitud. Seda käitumist saab seadetes muuta. Kaardiomaniku nimi pärineb teie kontolt.</translation>
+<translation id="6707256370811247129">Skannitakse vahemälu ja faile, mille Chrome'is alla või üles laadite.</translation>
<translation id="6710213216561001401">Eelmine</translation>
<translation id="6710594484020273272">&lt;Sisestage otsingutermin&gt;</translation>
<translation id="671076103358959139">Registreerimismärk:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Teie andmed krüpteeriti teie <ph name="BEGIN_LINK" />sünkroonimisparooliga<ph name="END_LINK" /> kuupäeval <ph name="TIME" />. Sisestage see sünkroonimise alustamiseks.</translation>
<translation id="674375294223700098">Serveri sertifikaadi tundmatu viga.</translation>
<translation id="6744009308914054259">Ühenduse loomise ajal võite avada jaotise Allalaadimised ja lugeda võrguühenduseta artikleid.</translation>
+<translation id="6747611005629681221">Hoiatus: katkestatud toega funktsioonid!</translation>
<translation id="6753269504797312559">Reegli väärtus</translation>
<translation id="6757797048963528358">Teie seade lülitus unerežiimile.</translation>
<translation id="6768213884286397650">Hagaki (postkaart)</translation>
-<translation id="6778737459546443941">Vanem ei ole seda veel kinnitanud</translation>
<translation id="67862343314499040">Violetne</translation>
<translation id="6786747875388722282">Laiendused</translation>
<translation id="6790428901817661496">Esita</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Kohustuslik väli</translation>
<translation id="6810899417690483278">Kohandamise ID</translation>
<translation id="6825578344716086703">Püüdsite jõuda domeenile <ph name="DOMAIN" />, kuid server esitas sertifikaadi, mis on allkirjastatud nõrga allkirjaalgoritmiga (nt SHA-1). See tähendab, et serveri esitatud turvamandaadid võivad olla võltsitud ja server ei pruugi olla see, mida eeldate (võimalik, et suhtlete ründajaga).</translation>
+<translation id="6826370046007623921">Andmekao vältimine</translation>
<translation id="6831043979455480757">Tõlgi</translation>
<translation id="6839929833149231406">Ala</translation>
<translation id="6852204201400771460">Kas soovite rakenduse uuesti laadida?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Reegli taset ei toetata.</translation>
<translation id="6895330447102777224">Teie kaart on kinnitatud</translation>
<translation id="6897140037006041989">Kasutajaagent</translation>
-<translation id="6903319715792422884">Aidake ohutu sirvimise funktsiooni täiustada, saates Google'ile <ph name="BEGIN_WHITEPAPER_LINK" />süsteemiteavet ja lehesisu<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Kasutaja:</translation>
<translation id="6934672428414710184">Nimi pärineb teie Google'i kontolt</translation>
<translation id="6944692733090228304">Sisestasite oma parooli saidile, mida ei halda <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Oma konto kaitsmiseks ärge kasutage oma parooli muudes rakendustes ega saitidel.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> ja veel <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> ja veel <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavendlililla</translation>
<translation id="717330890047184534">Gaia ID:</translation>
+<translation id="7174545416324379297">Liidetud</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ja veel <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ja veel <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Server, kuhu sisenete, <ph name="ORIGIN" />, taotleb, et
turvalisuse reeglit kohaldatakse igale sisenemistaotlusele. Reegli
@@ -1166,6 +1187,7 @@ Lisateave:
<translation id="7320336641823683070">Ühendamise abi</translation>
<translation id="733354035281974745">Seadme kohaliku konto alistamine</translation>
<translation id="7334320624316649418">&amp;Korrasta uuesti</translation>
+<translation id="7337706099755338005">Pole teie platvormil saadaval.</translation>
<translation id="733923710415886693">Serveri sertifikaati ei avalikustatud sertifikaadi läbipaistvuse reegli kaudu.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">On seotud:</translation>
@@ -1197,7 +1219,6 @@ Lisateave:
<translation id="7440140511386898319">Uurige võrguühenduseta sisu</translation>
<translation id="7441627299479586546">Reegli objekt on vale</translation>
<translation id="7442725080345379071">Heleoranž</translation>
-<translation id="7444046173054089907">See sait on blokeeritud</translation>
<translation id="7445762425076701745">Serveri identiteeti, millega olete ühenduses, ei saa täielikult valideerida. Olete ühenduses serveriga nime abil, mis kehtib ainult teie võrgus, mistõttu ei saa väline sertifitseerimisorgan selle omandiõigust valideerida. Kuna mõni sertifitseerimisorgan väljastab sertifikaate hoolimata nende nimedest, puudub igasugune võimalus tagada, et olete ühenduses soovitud veebisaidi, mitte ründajaga.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Vaadake lisateavet<ph name="END_LINK" /> probleemi kohta.</translation>
<translation id="7455133967321480974">Kasuta globaalset vaikeseadet (blokeeri)</translation>
@@ -1219,9 +1240,9 @@ Lisateave:
<translation id="7538364083937897561">A2 (ümbrik)</translation>
<translation id="7542403920425041731">Kui selle kinnitate, jagatakse teie kaardi üksikasju selle saidiga.</translation>
<translation id="7542995811387359312">Automaatne krediitkaardi täide on keelatud, sest see vorm ei kasuta turvalist ühendust.</translation>
-<translation id="7543525346216957623">Küsige vanematelt abi</translation>
<translation id="7548892272833184391">Ühendusvigade parandamine</translation>
<translation id="7549584377607005141">See veebileht vajab korralikult kuvamiseks varem sisestatud andmeid. Võite need andmed uuesti saata, kuid seda tehes kordate lehe iga eelnevat toimingut.</translation>
+<translation id="7550637293666041147">Teie seadme kasutajanimi ja Chrome'i kasutajanimi</translation>
<translation id="7552846755917812628">Proovige järgmiseid nõuandeid.</translation>
<translation id="7554791636758816595">Uus vaheleht</translation>
<translation id="7564049878696755256">Võite kaotada juurdepääsu oma teenuse <ph name="ORG_NAME" /> kontole või teie identiteet võidakse varastada. Chrome soovitab teil kohe oma parooli muuta.</translation>
@@ -1236,6 +1257,7 @@ Lisateave:
<translation id="7610193165460212391">Väärtus on vahemikust (<ph name="VALUE" />) väljaspool.</translation>
<translation id="7613889955535752492">Aegub: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Teil on juba andmed, mis on krüpteeritud Google'i konto parooli teise versiooniga. Sisestage see allpool.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Toimivusandmed ja krahhiaruanded</translation>
<translation id="7637571805876720304">Kas eemaldada Chromiumist krediitkaart?</translation>
<translation id="7638605456503525968">Jadapordid</translation>
@@ -1248,7 +1270,6 @@ Lisateave:
<translation id="7668654391829183341">Tundmatu seade</translation>
<translation id="7669271284792375604">Sellel saidil asuvad ründajad võivad proovida meelitada teid installima programme, mis kahjustavad sirvimiskogemust (nt muudavad avalehte või kuvavad külastatavatel saitidel lisareklaame).</translation>
<translation id="7676643023259824263">Lõikelaua teksti otsimine, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platvorm ja pilv</translation>
<translation id="7681101578153515023">Muuda otsingumootorit</translation>
<translation id="7682287625158474539">Kohaletoimetamine</translation>
<translation id="7687186412095877299">Täidab maksevormid teie salvestatud makseviiside andmete alusel</translation>
@@ -1263,7 +1284,6 @@ Lisateave:
<translation id="7723047071702270851">Kaardi muutmine</translation>
<translation id="774634243536837715">Ohtlik sisu blokeeriti.</translation>
<translation id="7752995774971033316">Haldamata</translation>
-<translation id="7755287808199759310">Vanem saab blokeeringu teie eest tühistada</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Tulemüür või viirusetõrjetarkvara võis ühenduse blokeerida.</translation>
<translation id="7759163816903619567">Kuvatav domeen:</translation>
@@ -1307,7 +1327,6 @@ Lisateave:
<translation id="8004582292198964060">Brauser</translation>
<translation id="8009225694047762179">Halda paroole</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{See kaart ja selle arveldusaadress salvestatakse. Saate seda kasutada, kui olete kontole <ph name="USER_EMAIL" /> sisse logitud.}other{Need kaardid ja nende arveldusaadressid salvestatakse. Saate neid kasutada, kui olete kontole <ph name="USER_EMAIL" /> sisse logitud.}}</translation>
-<translation id="8012647001091218357">Teie vanematega ei õnnestunud praegu ühendust võtta. Proovige hiljem uuesti.</translation>
<translation id="8025119109950072390">Sellel saidil asuvad ründajad võivad teid meelitada ohtlikele tegevustele, nagu tarkvara installimine või isiklike andmete (nt paroolid, telefoninumbrid või krediitkaardid) avaldamine.</translation>
<translation id="8034522405403831421">Leht on <ph name="SOURCE_LANGUAGE" /> keeles. Kas tõlkida <ph name="TARGET_LANGUAGE" /> keelde?</translation>
<translation id="8035152190676905274">Sulepea</translation>
@@ -1318,6 +1337,7 @@ Lisateave:
<translation id="8041940743680923270">Kasuta globaalset vaikeseadet (küsi)</translation>
<translation id="8042918947222776840">Valige kättesaamisviis</translation>
<translation id="8057711352706143257">Tarkvara „<ph name="SOFTWARE_NAME" />” ei ole õigesti seadistatud. Tarkvara „<ph name="SOFTWARE_NAME" />” desinstallimine lahendab tavaliselt probleemi. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Te ei pea enam kaardi turvakoodi sisestama</translation>
<translation id="8066955247577885446">Kahjuks läks midagi valesti</translation>
<translation id="8074253406171541171">10x13 (ümbrik)</translation>
<translation id="8078141288243656252">Pööramisel ei saa märkusi lisada</translation>
@@ -1348,6 +1368,7 @@ Lisateave:
<translation id="8211406090763984747">Ühendus on turvaline</translation>
<translation id="8218327578424803826">Määratud asukoht:</translation>
<translation id="8220146938470311105">C7/C6 (ümbrik)</translation>
+<translation id="8220639454292072926">Ettevõtte teavitamine</translation>
<translation id="8225771182978767009">Arvuti seadistanud inimene blokeeris selle saidi.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Avage leht uuel inkognito vahekaardil</translation>
@@ -1402,23 +1423,23 @@ Lisateave:
<translation id="8508648098325802031">Otsinguikoon</translation>
<translation id="8522552481199248698">Chrome aitab teil oma Google'i kontot kaitsta ja parooli muuta.</translation>
<translation id="8543181531796978784">Võite <ph name="BEGIN_ERROR_LINK" />teavitada tuvastusprobleemist<ph name="END_ERROR_LINK" />. Kui mõistate ohtusid oma turvalisusele, võite <ph name="BEGIN_LINK" />seda ebaturvalist saiti külastada<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Kas teil on küsimusi? Võtke ühendust profiili operaatoriga.</translation>
<translation id="8553075262323480129">Tõlkimine nurjus, kuna lehe keelt ei õnnestunud määrata.</translation>
<translation id="8557066899867184262">CVC asub kaardi tagaküljel.</translation>
<translation id="8559762987265718583">Privaatset ühendust ei saa domeeniga <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> luua, kuna seadme kuupäev ja kellaaeg (<ph name="DATE_AND_TIME" />) on valed.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> kahtlane sait</translation>
<translation id="8564985650692024650">Chromium soovitab teil organisatsiooni <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> parooli lähtestada, kui kasutasite seda ka muudel saitidel.</translation>
<translation id="8571890674111243710">Lehe tõlkimine <ph name="LANGUAGE" /> keelde...</translation>
<translation id="858637041960032120">Lisage telefoninumber</translation>
-<translation id="859285277496340001">Sertifikaat ei määratle mehhanismi enda võimaliku tühistamise kontrollimiseks.</translation>
<translation id="860043288473659153">Kaardiomaniku nimi</translation>
<translation id="861775596732816396">Suurus 4</translation>
-<translation id="8620436878122366504">Vanemad ei ole seda veel kinnitanud</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Salvesta kaart sellesse seadmesse</translation>
<translation id="8626112503828625890">Kas salvestada arvelduse üksikasjad Google'i kontole?</translation>
+<translation id="8647750283161643317">Lähtesta kõik vaikeolekusse</translation>
<translation id="8663226718884576429">Tellimuse kokkuvõte, <ph name="TOTAL_LABEL" />, rohkem üksikasju</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, vastus, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Saadaval</translation>
<translation id="8703575177326907206">Teie ühendus <ph name="DOMAIN" />'ga pole krüptitud.</translation>
<translation id="8718314106902482036">Makset ei viidud lõpule</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, otsingusoovitus</translation>
@@ -1429,6 +1450,7 @@ Lisateave:
<translation id="8738058698779197622">Turvalise ühenduse loomiseks peab kell olema õigesti seadistatud. See on nii, kuna sertifikaadid, mida veebisaidid kasutavad enda tuvastamiseks, kehtivad ainult teatud perioodi jooksul. Kuna teie seadme kell on vale, ei saa Chromium neid sertifikaate kinnitada.</translation>
<translation id="8740359287975076522">Hosti <ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS-aadressi&lt;/abbr&gt; ei leitud. Probleemi diagnoositakse.</translation>
<translation id="874846938927089722">Aktsepteeritavad ettemakstud ja krediitkaardid</translation>
+<translation id="874918643257405732">Lisa vaheleht järjehoidjatesse</translation>
<translation id="8759274551635299824">See kaart on aegunud</translation>
<translation id="8761567432415473239">Google'i ohutu sirvimine <ph name="BEGIN_LINK" />tuvastas hiljuti kahjulikud programmid<ph name="END_LINK" /> saidil <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB-seade</translation>
@@ -1458,6 +1480,7 @@ Lisateave:
<translation id="8938939909778640821">Aktsepteeritavad ettemakstud ja krediitkaardid</translation>
<translation id="8943282376843390568">Laimiroheline</translation>
<translation id="8957210676456822347">Kontrollportaali volitamine</translation>
+<translation id="8962950042226115166">Kahtlane sait</translation>
<translation id="8968766641738584599">Salvesta kaart</translation>
<translation id="8971063699422889582">Serveri sertifikaat on aegunud.</translation>
<translation id="8975012916872825179">Hõlmab näiteks telefoninumbreid, e-posti ja postiaadresse</translation>
@@ -1480,24 +1503,24 @@ Lisateave:
<translation id="9035022520814077154">Turvaviga</translation>
<translation id="9038649477754266430">Kasuta lehtede kiiremaks laadimiseks ennustusteenust</translation>
<translation id="9039213469156557790">Lisaks sisaldab see leht teisi ressursse, mis pole turvalised. Edastamise ajal võivad ressursse vaadata ka teised ja ründajad saavad lehe käitumise muutmiseks ressursse muuta.</translation>
+<translation id="9044359186343685026">Kasuta Touch ID-d</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Proovisite jõuda domeenile <ph name="DOMAIN" />, kuid server esitas kehtetu sertifikaadi.</translation>
<translation id="9050666287014529139">Parool</translation>
<translation id="9065203028668620118">Muuda</translation>
<translation id="9065745800631924235">Otsing <ph name="TEXT" /> ajaloost</translation>
<translation id="9069693763241529744">Blokeeris laiendus</translation>
-<translation id="9076283476770535406">See võib sisaldada täiskasvanutele mõeldud sisu</translation>
<translation id="9076630408993835509">Seda brauserit ei halda ettevõte ega muu organisatsioon. Selle seadme tegevusi võidakse hallata ka väljaspool Chrome'i. <ph name="BEGIN_LINK" />Lisateave<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Vaja on rohkem teavet</translation>
<translation id="9080712759204168376">Tellimuse kokkuvõte</translation>
<translation id="9089260154716455634">Eemalolekuaegade eeskirjad:</translation>
<translation id="9095388113577226029">Rohkem keeli …</translation>
+<translation id="9098981495403789647">Administraator lubas teie brauseris funktsiooni Chrome Enterprise Threat Protection. Funktsioonil Chrome Enterprise Threat Protection on juurdepääs osadele teie andmetele.</translation>
<translation id="9103872766612412690">Sait <ph name="SITE" /> kasutab teie teabe kaitsmiseks tavaliselt krüpteerimist. Kui Chromium püüdis seekord saidiga <ph name="SITE" /> ühendust luua, tagastas veebisait ebatavalised ja valed mandaadid. See võib juhtuda siis, kui ründaja proovib teeselda, et on sait <ph name="SITE" />, või WiFi sisselogimisekraan on ühenduse katkestanud. Teie teave on endiselt kaitstud, sest Chromium peatas ühenduse enne andmevahetust.</translation>
<translation id="9106062320799175032">Arveldusaadressi lisamine</translation>
<translation id="9114524666733003316">Kaardi kinnitamine …</translation>
<translation id="9128870381267983090">Ühendumine Internetiga</translation>
<translation id="9137013805542155359">Kuva originaal</translation>
-<translation id="9137248913990643158">Enne selle rakenduse kasutamist alustage ja logige Chrome'i sisse.</translation>
<translation id="9141013498910525015">Aadresside haldamine</translation>
<translation id="9148088599418889305">Valige tarneviis</translation>
<translation id="9148507642005240123">&amp;Võta muudatus tagasi</translation>
diff --git a/chromium/components/strings/components_strings_fa.xtb b/chromium/components/strings/components_strings_fa.xtb
index 55547f13a62..5a995559466 100644
--- a/chromium/components/strings/components_strings_fa.xtb
+++ b/chromium/components/strings/components_strings_fa.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">افزودن نام روی کارت</translation>
<translation id="1089439967362294234">تغییر گذرواژه</translation>
+<translation id="1096545575934602868">این فیلد نباید بیشتر از <ph name="MAX_ITEMS_LIMIT" /> ورودی داشته باشد. از همه ورودی‌های آینده صرف‌نظر می‌شود.</translation>
<translation id="109743633954054152">‏گذرواژها را در تنظیمات Chrome مدیریت کنید</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> همیشه ترجمه شود</translation>
<translation id="1107591249535594099">‏اگر علامت زده شود، Chrome یک کپی از این کارت را در دستگاه نگهداری می‌کند تا برای پرکردن فرم‌ها از آن استفاده شود.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">دسترسی به یک <ph name="BEGIN_LINK" />نسخه ذخیره شده در حافظه پنهان<ph name="END_LINK" /> از <ph name="URL" /></translation>
<translation id="1156303062776767266">شما فایلی محلی یا هم‌رسانی‌شده را مشاهده می‌کنید</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> به‌طور غیرمنتظره‌ای اتصال را قطع کرد.</translation>
+<translation id="115926840831309955">‏CVC را بررسی کنید و دوباره امتحان کنید یا تاریخ انقضا را به‌روزرسانی کنید</translation>
<translation id="1161325031994447685">‏اتصال مجدد به Wi-Fi</translation>
<translation id="1165039591588034296">خطا</translation>
<translation id="1175364870820465910">&amp;چاپ...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">‏«نرم‌افزاری در رایانه شما مانع از اتصال ایمن Chrome به وب می‌شود» (فقط رایانه‌های Windows)</translation>
<translation id="1294154142200295408">انواع مختلف خط فرمان</translation>
<translation id="129553762522093515">اخیراً بسته‌شده</translation>
+<translation id="1298536327547837046">اسکن بدافزار</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />کوکی‌ها را پاک کنید<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">ویژگی‌های منسوخ‌شده</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">جستجوی تصویر بریده‌دان</translation>
<translation id="1323433172918577554">نمایش موارد بیشتر</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">‏کاربرگ‌نگار Google</translation>
<translation id="1527263332363067270">درانتظار برقراری اتصال…‏</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">سایتی که لحظاتی پیش تلاش کردید از آن بازدید کنید، جعلی به‌نظر می‌رسد. گاهی‌اوقات حمله‌کنندگان با ایجاد تغییرات کوچک در نشانی وب که به‌آسانی قابل‌دیدن نیست، سایت‌ها را جعل می‌کنند.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">این صفحه می‌گوید</translation>
<translation id="153384715582417236">درحال‌حاضر مورد دیگری وجود ندارد</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">این سند بسیار بزرگ است و نمی‌تواند حاشیه‌نویسی شود</translation>
-<translation id="1721312023322545264">برای بازدید این سایت باید از <ph name="NAME" /> اجازه بگیرید</translation>
<translation id="1721424275792716183">* این فیلد اجباری است</translation>
<translation id="1727741090716970331">افزودن شماره کارت معتبر</translation>
<translation id="1728677426644403582">درحال مشاهده منبع یک صفحه وب هستید</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">وب‌سایت‌هایی که بازدید می‌کنید و زمانی که در آن‌ها صرف می‌کنید</translation>
<translation id="1826516787628120939">در حال بررسی</translation>
<translation id="1834321415901700177">این سایت محتوی برنامه‌های مضر است</translation>
+<translation id="1838374766361614909">پاک کردن جستجو</translation>
<translation id="1839551713262164453">اعتبارسنجی مقادیر خط‌مشی با خطا متوقف شد</translation>
<translation id="1842969606798536927">پرداخت</translation>
<translation id="1871208020102129563">‏تنظیم پروکسی به گونه‌ای است که از سرورهای ثابت پروکسی استفاده کند و از آدرس اسکریپت pac. استفاده نکند.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">کوچک کردن فهرست</translation>
<translation id="1898423065542865115">فیلتر کردن</translation>
<translation id="1914326953223720820">سرویس خارج کردن از فشرده‌سازی</translation>
+<translation id="1915697529809968049">‏به‌جای CVC از شناسه لمسی استفاده شود؟</translation>
<translation id="1916770123977586577">برای اعمال کردن تنظیمات به‌روزرسانی‌شده خود در این سایت، این صفحه را تازه‌سازی کنید</translation>
<translation id="1919345977826869612">آگهی‌ها</translation>
<translation id="1919367280705858090">دریافت راهنمایی برای پیام خطایی خاص</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">نشانک‌های <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">خطای ترتیب</translation>
<translation id="1974060860693918893">پیشرفته</translation>
+<translation id="1974883374937189061">‏با ارسال <ph name="BEGIN_WHITEPAPER_LINK" />نشانی وب برخی از صفحه‌هایی که بازدید می‌کنید، اطلاعات محدود سیستم، و بخشی از محتوای صفحه<ph name="END_WHITEPAPER_LINK" /> به Google، به بهبود امنیت Chrome کمک کنید. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">نسخه سفت‌افزار</translation>
<translation id="1981206234434200693">‏داده‌های سابقه مرور Chrome را پاک کنید</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{و ۱ برنامه دیگر}one{و # برنامه دیگر}other{و # برنامه دیگر}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">سال انقضای معتبری وارد کنید</translation>
<translation id="2212735316055980242">خط‌مشی یافت نشد</translation>
<translation id="2213606439339815911">در حال واکشی موارد...</translation>
+<translation id="2215727959747642672">ویرایش فایل</translation>
<translation id="2218879909401188352">درحال‌حاضر مهاجم‌ها در <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> می‌توانند برنامه‌های خطرناکی نصب کنند که به دستگاهتان آسیب بزند، هزینه‌های پنهانی به صورت‌حساب دستگاه همراهتان اضافه کند یا اطلاعات شخصی‌تان را سرقت کند. <ph name="BEGIN_LEARN_MORE_LINK" />بیشتر بدانید<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">اتصال اینترنت وجود ندارد</translation>
<translation id="2230458221926704099">با استفاده از <ph name="BEGIN_LINK" />برنامه عیب‌یابی<ph name="END_LINK" />، مشکل اتصالتان را برطرف کنید</translation>
<translation id="2239100178324503013">اکنون ارسال شود</translation>
+<translation id="2248949050832152960">‏استفاده از WebAuthn</translation>
<translation id="225207911366869382">این مقدار برای این خط‌مشی منسوخ شده است؟</translation>
<translation id="2257315177824333709">متأسفیم، درحال‌حاضر نمی‌توان کارت شما را ذخیره کرد</translation>
<translation id="2262243747453050782">‏خطای HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">‏URL جستجو نامعتبر است.</translation>
<translation id="2482878487686419369">اعلان‌ها</translation>
<translation id="248348093745724435">خط‌مشی‌های ماشین</translation>
-<translation id="2485387744899240041">نام کاربری دستگاه و مرورگرتان</translation>
<translation id="2491120439723279231">گواهی سرور دارای چندین خطاست.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">‏تجزیه‌کننده JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">بازگشت</translation>
<translation id="2503184589641749290">کارت‌های نقدی و پیش‌پرداخت قابل‌قبول</translation>
<translation id="2505268675989099013">محافظت از حساب</translation>
+<translation id="2515335152965840738">نادیده‌ گرفتن</translation>
<translation id="2515629240566999685">بررسی سیگنال در منطقه‌تان</translation>
<translation id="2523886232349826891">فقط در این دستگاه ذخیره شد</translation>
<translation id="2524461107774643265">افزودن اطلاعات بیشتر</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">ارائه</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{هیچ‌کدام}=1{۱ گذرواژه (برای <ph name="DOMAIN_LIST" />)}=2{۲ گذرواژه (برای <ph name="DOMAIN_LIST" />)}one{# گذرواژه (برای <ph name="DOMAIN_LIST" />)}other{# گذرواژه (برای <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">برگه‌ها یا برنامه‌های دیگر را ببندید</translation>
-<translation id="267371737713284912">برای واگرد، <ph name="MODIFIER_KEY_DESCRIPTION" /> را فشار دهید</translation>
<translation id="2674170444375937751">آیا مطمئن هستید می‌خواهید این صفحات را از سابقه خود حذف کنید؟</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">خروج</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">مقدار با فرمت مطابقت ندارد.</translation>
<translation id="2705137772291741111">کپی ذخیره‌شده (ذخیره موقت‌شده) این سایت قابل خواندن نبود.</translation>
<translation id="2709516037105925701">تکمیل خودکار</translation>
-<translation id="2712173769900027643">درخواست اجازه</translation>
<translation id="2713444072780614174">سفید</translation>
<translation id="2720342946869265578">اطراف</translation>
<translation id="2721148159707890343">درخواست با موفقیت انجام شد</translation>
<translation id="2728127805433021124">گواهی سرور با استفاده از یک الگوریتم امضای ضعیف امضا شده است.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />در حال اجرای عیب‌یابی اتصال<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">با فعال کردن این ویژگی‌ها، ممکن است داده‌های محصول مرور را از دست بدهید یا امنیت یا حریم‌خصوصی‌تان را به‌خطر بیندازید. ویژگی‌های فعال‌شده برای همه کاربران این مرورگر اعمال می‌شود.</translation>
<translation id="2735043616039983645">بیش از یک منبع با مقادیر مغایر برای این خط‌مشی موجود است!</translation>
<translation id="2738330467931008676">انتخاب نشانی تحویل گرفتن</translation>
<translation id="2740531572673183784">تأیید</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">اتصال مجدداً برقرار شد.</translation>
<translation id="2788784517760473862">کارت‌های اعتباری قابل‌قبول</translation>
<translation id="2792012897584536778">سرپرستان این دستگاه چند گواهینامه امنیتی راه‌اندازی کرده‌اند که می‌تواند به آن‌ها اجازه دهد محتوای وب‌سایت‌هایی را که بازدید می‌کنید، ببینند.</translation>
-<translation id="2794233252405721443">سایت مسدودشده</translation>
<translation id="2799020568854403057">سایت پیش‌رو حاوی برنامه‌های خطرناک است</translation>
<translation id="2799223571221894425">راه‌اندازی مجدد</translation>
<translation id="2803306138276472711">‏Google Safe Browsing به تازگی در <ph name="SITE" />، ‏<ph name="BEGIN_LINK" />بدافزار شناسایی کرده است<ph name="END_LINK" />. گاهی اوقات وب‌سایت‌هایی که معمولاً ایمن هستند با بدافزار آلوده می‌شوند.</translation>
+<translation id="2815364696811431560">خروج از سایت</translation>
<translation id="2824775600643448204">نوار جستجو و آدرس</translation>
<translation id="2826760142808435982">اتصال با استفاده از <ph name="CIPHER" /> رمزگذاری و راستی‌آزمایی شده است و از <ph name="KX" /> به عنوان مکانیسم تبادل کلید استفاده می‌کند.</translation>
<translation id="2835170189407361413">پاک کردن فرم</translation>
<translation id="2847118875340931228">پنجره ناشناس باز کنید</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">برای بازدید کردن از این سایت، مجوز لازم دارید</translation>
<translation id="2856444702002559011">شاید مهاجم‌ها در تلاش باشند اطلاعات شما (مانند گذرواژه‌ها، پیام‌ها یا کارت‌های اعتباری) را از <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> سرقت کنند. <ph name="BEGIN_LEARN_MORE_LINK" />بیشتر بدانید<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">کارت ذخیره شود؟</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">‏اگر فعال شود، Chromium برای پر کردن سریع‌تر فرم، یک کپی از کارت شما در این دستگاه ذخیره می‌کند.</translation>
<translation id="2985398929374701810">نشانی معتبری وارد کنید</translation>
<translation id="2986368408720340940">این روش تحویل گرفتن در دسترس نیست. روش دیگری را امتحان کنید.</translation>
+<translation id="2987034854559945715">ویژگی مطابقی وجود ندارد</translation>
<translation id="2991174974383378012">اشتراک‌گذاری با وب‌سایت‌ها</translation>
<translation id="2991571918955627853">‏درحال‌حاضر نمی‌توانید از <ph name="SITE" /> دیدن کنید، زیرا این وب‌سایت از HSTS استفاده می‌کند. خطاهای شبکه و حمله‌ها معمولاً موقتی هستند، بنابراین احتمالاً این صفحه بعداً کار خواهد کرد.</translation>
<translation id="3005723025932146533">نمایش کپی ذخیره شده</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">نوع خط‌مشی اشتباه است</translation>
<translation id="3037605927509011580">اوه، نه!</translation>
<translation id="3041612393474885105">اطلاعات گواهی</translation>
+<translation id="3057676462092457419">‏حالت DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> هنوز پشتیبانی نمی‌شود، حالت مربوطه روی <ph name="SECURE_DNS_MODE_OFF" /> تنظیم شده است.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">سرویس وصله</translation>
<translation id="3064966200440839136">درحال خروج از حالت ناشناس، برای پرداخت ازطریق یک برنامه خارجی. ادامه می‌دهید؟</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> در <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">لغو پرداخت</translation>
<translation id="3207960819495026254">نشانک‌گذاری شده</translation>
+<translation id="3209034400446768650">ممکن است این صفحه از شما هزینه کسر کند</translation>
<translation id="3225919329040284222">سرور گواهی را نشان می‌دهد که با موارد پیش‌بینی‌شده داخلی مطابقت ندارد. این پیش‌بینی‌ها به‌طور حتم وب‌سایتهای دارای امنیت بالا را جهت محافظت از شما در بر می‌گیرند.</translation>
<translation id="3226128629678568754">دکمه تازه‌سازی را فشار دهید تا داده‌های مورد نیاز برای بارگیری صفحه مجدداً ارسال شود.</translation>
<translation id="3227137524299004712">میکروفن</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">اطلاعات مربوط به نسخه دستگاه و مرورگر</translation>
<translation id="323107829343500871">‏CVC کارت <ph name="CREDIT_CARD" /> را وارد کنید</translation>
<translation id="3234666976984236645">همیشه محتوای مهم در این سایت شناسایی شود</translation>
-<translation id="3254409185687681395">نشانک گذاری این صفحه</translation>
<translation id="3270847123878663523">&amp;واگرد ترتیب‌بندی مجدد</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">افزودن نام روی کارت</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">افزودن نشانی صورتحساب</translation>
<translation id="3324983252691184275">زرشکی</translation>
<translation id="3338095232262050444">ایمن</translation>
-<translation id="3345135638360864351">درخواست شما برای دسترسی به این سایت به <ph name="NAME" /> ارسال نشد. لطفاً دوباره امتحان کنید.</translation>
<translation id="3355823806454867987">تغییر تنظیمات پروکسی...</translation>
<translation id="3361596688432910856">‏Chrome اطلاعات زیر را <ph name="BEGIN_EMPHASIS" />ذخیره نخواهد کرد<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">پنهان کردن پیشرفته</translation>
<translation id="3467763166455606212">نام صاحب حساب الزامی است</translation>
<translation id="3468054117417088249">‏<ph name="TAB_SWITCH_SUFFIX" />، اکنون باز است، برای جابه‌جا شدن به برگه باز، ابتدا دکمه Tab سپس Enter را فشار دهید</translation>
-<translation id="3479539252931486093">غیرمنتظره بود؟ <ph name="BEGIN_LINK" />به ما اطلاع دهید<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">اکنون نه</translation>
<translation id="3484560055331845446">‏ممکن است دسترسی به حساب Google را از دست بدهید. Chrome توصیه می‌کند اکنون گذرواژه‌تان را تغییر دهید. از شما خواسته می‌شود به سیستم وارد شوید.</translation>
<translation id="3495081129428749620">یافتن در صفحه
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">در حال حاضر نمی‌توانیم با والدینتان تماس برقرار کنیم. لطفاً دوباره امتحان کنید.</translation>
<translation id="3512163584740124171">این خط‌مشی، چون خط‌مشی دیگری از همین گروه خط‌مشی اولویت بالاتری دارد، لحاظ نمی‌شود.</translation>
<translation id="3528171143076753409">گواهی سرور مطمئن نیست.</translation>
<translation id="3528485271872257980">قهوه‌ای تیره</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{حداقل ۱ مورد در دستگاه‌های همگام‌سازی‌شده}=1{۱ مورد (و بیشتر در دستگاه‌های همگام‌سازی‌شده)}one{# مورد (و بیشتر در دستگاه‌های همگام‌سازی‌شده)}other{# مورد (و بیشتر در دستگاه‌های همگام‌سازی‌شده)}}</translation>
<translation id="3539171420378717834">یک کپی از این کارت در این دستگاه نگهداری شود</translation>
-<translation id="3556433843310711081">مدیرتان می‌تواند این سایت را برای شما بگشاید</translation>
<translation id="3566021033012934673">اتصال شما خصوصی نیست</translation>
<translation id="3574305903863751447"><ph name="CITY" />، <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">صفحه جاسازی‌شده‌ای در <ph name="SITE" /> می‌گوید</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">‏صفحه را در پنجره‌ «ناشناس» جدیدی باز کنید (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">گزارش خرابی در <ph name="CRASH_TIME" /> ثبت شد، در <ph name="UPLOAD_TIME" /> بارگذاری شد</translation>
<translation id="3681007416295224113">اطلاعات گواهی</translation>
+<translation id="3701427423622901115">بازنشانی تأیید شد.</translation>
<translation id="3704162925118123524">شاید شبکه‌ای که استفاده می‌کنید، بازدید از صفحه ورود به سیستم خودش را برای شما ضروری کرده باشد.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> ‏<ph name="BOOKMARKED" /> ‏<ph name="TITLE" /> ‏<ph name="DOMAIN" /></translation>
<translation id="370665806235115550">در حال بارکردن…</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805">ممکن است مهاجم‌ها در <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> شما را فریب دهند تا اقدام خطرناکی همچون نصب نرم‌افزار یا افشای اطلاعات شخصی (مانند گذرواژه‌ها، پیام‌ها یا کارت‌های اعتباری) انجام دهید. <ph name="BEGIN_LEARN_MORE_LINK" />بیشتر بدانید<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">بدلیل خطای سرور ترجمه انجام نشد.</translation>
<translation id="3759461132968374835">شما اخیراً گزارش خرابی ارسال نکرده‌اید. مشکلاتی که در هنگام غیرفعال بودن ویژگی ارائه گزارش خرابی ایجاد شده است، در اینجا نمایش داده نمی‌شود.</translation>
+<translation id="3760561303380396507">‏به‌جای CVC از Windows Hello استفاده شود؟</translation>
<translation id="3761718714832595332">پنهان کردن وضعیت</translation>
<translation id="3765032636089507299">صفحه «مرور ایمن» در دست ساخت است.</translation>
<translation id="3778403066972421603">‏آیا می‌خواهید این کارت در حساب Google شما و این دستگاه ذخیره شود؟</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">اندازه ۱۶</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">محتوای مضر مسدود شد.</translation>
+<translation id="3808375843007691220">هشدار: ویژگی‌های آزمایشی پیش رو است!</translation>
<translation id="3810973564298564668">مدیریت</translation>
<translation id="382518646247711829">اگر از سرور پراکسی استفاده می‌کنید...</translation>
<translation id="3828924085048779000">عبارت عبور خالی مجاز نیست.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">به‌روزرسانی تاریخ و زمان</translation>
<translation id="3884278016824448484">شناسه دستگاه یکسان نیست</translation>
<translation id="3885155851504623709">استان</translation>
-<translation id="3886446263141354045">درخواست شما برای دسترسی به این سایت برای <ph name="NAME" /> ارسال شده است</translation>
<translation id="3890664840433101773">افزودن ایمیل</translation>
<translation id="3901925938762663762">کارت منقضی شده است</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">‏به‌جای CVC از WebAuthn استفاده شود؟</translation>
<translation id="3946209740501886391">در این سایت، همیشه سؤال شود</translation>
<translation id="3949571496842715403">‏این سرور نتوانست ثابت کند که <ph name="DOMAIN" /> است؛ در گواهی امنیتی آن، Subject Alternative Names مشخص نشده است. ممکن است این مشکل به دلیل پیکربندی نادرست یا قطع اتصال شما توسط مهاجم ایجاد شده باشد.</translation>
<translation id="3949601375789751990">سابقه مرورتان در اینجا نشان داده می‌شود</translation>
@@ -564,12 +572,12 @@
<translation id="3963837677003247395">به‌صورت دستی ادامه می‌دهید؟</translation>
<translation id="3964661563329879394">{COUNT,plural, =0{هیچ‌کدام}=1{از ۱ سایت }one{از # سایت }other{از # سایت }}</translation>
<translation id="397105322502079400">در حال محاسبه…</translation>
-<translation id="3973234410852337861"><ph name="HOST_NAME" /> مسدود است</translation>
+<translation id="3973234410852337861"><ph name="HOST_NAME" /> مسدود شده است</translation>
+<translation id="3981540111851280311">‏<ph name="ENROLLMENT_DOMAIN" /> «محافظت از تهدیدهای شرکتی در Chrome» را در مرورگرتان فعال کرده است. «محافظت از تهدیدهای شرکتی در Chrome» به برخی داده‌هایتان دسترسی دارد.</translation>
<translation id="3987940399970879459">کمتر از ۱ مگابایت</translation>
<translation id="40103911065039147">{URL_count,plural, =1{ ۱ صفحه وب در این نزدیکی است}one{ # صفحه وب در این نزدیکی است}other{ # صفحه وب در این نزدیکی است}}</translation>
<translation id="4030383055268325496">&amp;واگرد افزودن</translation>
<translation id="4032320456957708163">مرورگرتان توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود</translation>
-<translation id="4034375457890803692">پیوندی که باز کردید به سایتی هدایت می‌شود که معمولاً از آن بازدید نمی‌کنید. شاید این پیوند سعی می‌کند شما را دچار اشتباه کند.</translation>
<translation id="4058922952496707368">کلید "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">افزودن نشانی معتبر</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">شماره سریال دستگاه نامعتبر است</translation>
<translation id="410351446219883937">پخش خودکار</translation>
<translation id="4103763322291513355">‏برای مشاهده فهرست نشانی‌های وب ممنوع و سایر خط‌مشی‌های اجباری براساس تصمیم سرپرست سیستم خود از &lt;strong&gt;chrome://policy&lt;/strong&gt; بازدید نمایید.</translation>
+<translation id="4108231218301530806">دفعه بعد از اثر انگشت برای به‌تأیید رساندن این کارت استفاده کنید.</translation>
<translation id="4110652170750985508">مرور پرداخت</translation>
<translation id="4112140312785995938">رفتن به عقب</translation>
<translation id="4116663294526079822">همیشه مجاز در این سایت</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">امضای تأیید نامناسب</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> مورد دیگر}one{<ph name="ITEM_COUNT" /> مورد دیگر}other{<ph name="ITEM_COUNT" /> مورد دیگر}}</translation>
+<translation id="4176463684765177261">غیرفعال شد</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">‏برای اینکه دفعات بعد پرداخت سریع‌تری داشته باشید، اطلاعات کارت و نشانی صورت‌حسابتان را به حساب Google خود اضافه کنید.</translation>
<translation id="4196861286325780578">&amp;انجام مجدد انتقال</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">بازنشانی گذرواژه</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> شما توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود.</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{‏این کارت در حساب Google ذخیره شده است}one{‏این کارت‌ها در حساب Google ذخیره شده‌اند}other{‏این کارت‌ها در حساب Google ذخیره شده‌اند}}</translation>
+<translation id="428847186335018806">‏اسکن فایل‌هایی که در Chrome بارگیری یا بارگذاری کرده‌اید</translation>
<translation id="42981349822642051">بزرگ کردن</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">جابه‌جایی</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">استفاده از پروکسی غیرفعال است اما یک پیکربندی خاص برای پروکسی تعیین شده است.</translation>
<translation id="445100540951337728">کارت‌های نقدی قابل‌قبول</translation>
-<translation id="4453237654902532092">رفتار مشکوک <ph name="SAFETY_TIP" /></translation>
<translation id="4466881336512663640">تغییرات فرم از بین می‌رود. مطمئن هستید می‌خواهید ادامه دهید؟</translation>
<translation id="4477350412780666475">آهنگ بعدی</translation>
<translation id="4482953324121162758">این سایت ترجمه نخواهد شد.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">&amp;واگرد حذف</translation>
<translation id="4597348597567598915">اندازه ۸</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">ویژگی‌های جستجو</translation>
<translation id="4646534391647090355">اکنون من را به آنجا ببر</translation>
<translation id="4668929960204016307">،</translation>
<translation id="467662567472608290">این سرور نتوانست اثبات کند که این <ph name="DOMAIN" /> است؛ گواهی امنیتی آن خطاهایی دارد. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصال شما را قطع کرده است.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">اتصال شما قطع شد</translation>
-<translation id="471880041731876836">برای بازدید کردن از این سایت، مجوز لازم ندارید</translation>
<translation id="4722547256916164131">‏<ph name="BEGIN_LINK" />اجرای Windows Network Diagnostics<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">تازه‌سازی خط مشی‌ها</translation>
<translation id="4728558894243024398">پلت فورم</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">متناسب با صفحه</translation>
<translation id="4850886885716139402">نما</translation>
<translation id="4854362297993841467">این روش تحویل در دسترس نیست. روش دیگری را امتحان کنید.</translation>
-<translation id="4858792381671956233">از والدینتان پرسیدید آیا اجازه بازدید از این سایت را دارید</translation>
<translation id="4864052566555297930">نکته ایمنی:</translation>
<translation id="4876188919622883022">نمای ساده‌شده</translation>
<translation id="4876305945144899064">بدون نام کاربری</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">فعال کردن مجدد اخطارها</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">دیدن همه</translation>
+<translation id="4989542687859782284">دردسترس نیست</translation>
<translation id="4989809363548539747">این افزایه پشتیبانی نمی‌شود</translation>
+<translation id="4995216769782533993">برای اشتراک‌گذاری جزئیات کارتتان با این سایت، کد امنیتی را تأیید کنید</translation>
<translation id="5002932099480077015">‏اگر فعال شود، Chrome یک کپی از کارت شما را برای پرکردن سریع‌تر فرم در این دستگاه ذخیره می‌کند.</translation>
<translation id="5015510746216210676">نام ماشین:</translation>
<translation id="5017554619425969104">نوشتاری که کپی کرده‌اید</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(۶۴ بیت)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">کارتتان را تأیید کنید</translation>
<translation id="5135404736266831032">مدیریت نشانی‌ها…</translation>
<translation id="5138227688689900538">نمایش موارد کمتر</translation>
<translation id="5141240743006678641">‏رمزگذاری گذرواژه‌های همگام‌سازی شده با اطلاعات کاربری Google شما</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">فقط مالک می‌تواند ویژگی‌هایی را که در کل سیستم اعمال می‌شود تنظیم کند: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">‏هشدار: این خط‌مشی طبق آنچه در خط‌مشی PolicyDictionaryMultipleSourceMergeList مشخص شده ادغام نشد، زیرا بخشی از خط‌مشی‌های فهرستی نیست که بتواند ادغام شود.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">پایان</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">تنظیمات خط‌‌مشی ذخیره نشد</translation>
<translation id="5371425731340848620">به‌روزرسانی کارت</translation>
<translation id="5377026284221673050">‏«ساعتتان عقب است» یا «ساعتتان جلو است» یا «&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;»</translation>
-<translation id="5377179979757081683">شاید این صفحه شما را برای سرقت اطلاعات شخصی یا آسیب به دستگاهتان فریب دهد. هنگام وارد کردن اطلاعات شخصی یا باز کردن فایل‌های بارگیری‌شده، احتیاط کنید.</translation>
<translation id="5384855140246857529">برای اینکه از کارت‌هایتان در همه دستگاه‌ها استفاده کنید، به سیستم وارد شوید و همگام‌سازی را روشن کنید.</translation>
<translation id="5386426401304769735">‏زنجیره گواهی این سایت حاوی یک گواهی با امضای SHA-1 است.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,8 @@
<translation id="5457113250005438886">نامعتبر</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> مخاطب دیگر}one{<ph name="CONTACT_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> مخاطب دیگر}other{<ph name="CONTACT_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> مخاطب دیگر}}</translation>
<translation id="5470861586879999274">&amp;انجام مجدد ویرایش</translation>
+<translation id="5473728911100096288">با فعال کردن این ویژگی‌ها، از ویژگی‌های منسوخ‌شده استفاده خواهید کرد
+ که در نسخه‌های آینده وجود نخواهند داشت.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">شاید این محتوا تلاش کند نرم‌افزار خطرناکی در دستگاهتان نصب کند که اطلاعاتتان را به سرقت برد یا حذف کند. <ph name="BEGIN_LINK" />درهرصورت نمایش داده شود<ph name="END_LINK" /></translation>
<translation id="54817484435770891">نشانی معتبری اضافه کنید</translation>
@@ -863,7 +877,6 @@
<translation id="5570825185877910964">محافظت از حساب</translation>
<translation id="5571083550517324815">تحویل گرفتن از این نشانی ممکن نیست. نشانی دیگری را انتخاب کنید.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{۱ کوکی درحال استفاده}one{# کوکی درحال استفاده}other{# کوکی درحال استفاده}})</translation>
-<translation id="5572851009514199876">‏لطفاً Chrome را باز کنید و به سیستم آن وارد شوید تا Chrome بتواند بررسی کند آیا مجاز به دسترسی به این سایت هستید یا خیر.</translation>
<translation id="5580958916614886209">ماه انقضا را بررسی و دوباره امتحان کنید</translation>
<translation id="5586446728396275693">نشانی ذخیره‌شده‌ای وجود ندارد</translation>
<translation id="5595485650161345191">ویرایش آدرس</translation>
@@ -871,6 +884,7 @@
<translation id="560412284261940334">مدیریت پشتیبانی نمی‌شود</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">‏این سایت می‌تواند جعلی یا کلاهبردارانه باشد. Chrome توصیه می‌کند همین‌الان خارج شوید.</translation>
<translation id="5610142619324316209">بررسی اتصال</translation>
<translation id="5610807607761827392">می‌توانید در <ph name="BEGIN_LINK" />تنظیمات<ph name="END_LINK" />، کارت‌ها و نشانی‌ها را مدیریت کنید.</translation>
<translation id="5617949217645503996">تعداد دفعاتی که <ph name="HOST_NAME" /> شما را به نشانی‌های دیگر هدایت کرده بیش از حد است.</translation>
@@ -894,11 +908,11 @@
<translation id="5720705177508910913">کاربر کنونی</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">‏Chrome توصیه می‌کند اگر از گذرواژه‌تان در سایت‌های دیگری استفاده کردید آن را بازنشانی کنید.</translation>
-<translation id="5732392974455271431">والدینتان می‌توانند این سایت را برای شما بگشایند</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{‏ذخیره کردن کارت در حساب Google شما}one{‏ذخیره کردن کارت‌ها در حساب Google}other{‏ذخیره کردن کارت‌ها در حساب Google}}</translation>
<translation id="5763042198335101085">نشانی ایمیل معتبری وارد کنید</translation>
<translation id="5765072501007116331">برای دیدن روش‌های تحویل و شرایط موردنیاز، یک نشانی انتخاب کنید</translation>
<translation id="5778550464785688721">‏کنترل کامل دستگاه‌های MIDI</translation>
+<translation id="5781136890105823427">آزمایش فعال شد</translation>
<translation id="578305955206182703">کهربایی</translation>
<translation id="57838592816432529">بی‌صدا کردن</translation>
<translation id="5784606427469807560">هنگام تأیید کارت مشکلی پیش آمد. اتصال اینترنتتان را بررسی و دوباره امتحان کنید.</translation>
@@ -915,13 +929,16 @@
<translation id="5860033963881614850">خاموش</translation>
<translation id="5863847714970149516">صفحه پیش‌رو ممکن است تلاش کند از شما پول دریافت کند</translation>
<translation id="5866257070973731571">افزودن شماره تلفن</translation>
+<translation id="5866898949289125849">درحال مشاهده یک صفحه ابزار برنامه‌نویس هستید</translation>
<translation id="5869405914158311789">دسترسی به این سایت امکان‌پذیر نیست</translation>
<translation id="5869522115854928033">گذرواژه‌های ذخیره‌شده</translation>
<translation id="5887400589839399685">کارت ذخیره‌ شد</translation>
<translation id="5893752035575986141">کارت‌های اعتباری پذیرفته می‌شوند.</translation>
+<translation id="5895138241574237353">راه‌اندازی مجدد</translation>
<translation id="5901630391730855834">زرد</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (همگام‌سازی‌شده)</translation>
<translation id="5916664084637901428">روشن</translation>
+<translation id="59174027418879706">فعال شد</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">‏کارت در حساب Google ذخیره شود؟</translation>
<translation id="5922853866070715753">تقريباً تمام است</translation>
@@ -955,6 +972,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">از کارت‌ها در همه دستگاه‌هایتان استفاده شود؟</translation>
<translation id="6059925163896151826">‏دستگاه‌های USB</translation>
+<translation id="6060009363608157444">‏حالت DnsOverHttps نامعتبر است.</translation>
<translation id="6080696365213338172">شما با استفاده از گواهی ارائه شده توسط سرپرست سیستم به محتوا دسترسی پیدا کرده‌اید. داده‌هایی که به <ph name="DOMAIN" /> ارائه می‌کنید ممکن است توسط سرپرست سیستم رهگیری شوند.</translation>
<translation id="6094273045989040137">حاشیه‌نویسی</translation>
<translation id="610911394827799129">‏ممکن است حساب Google شما اشکال دیگری از سابقه مرور در <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> داشته باشد</translation>
@@ -1003,13 +1021,12 @@
<translation id="6404511346730675251">ویرایش نشانک</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">‏CVC‏ و تاریخ انقضای <ph name="CREDIT_CARD" /> را وارد کنید</translation>
-<translation id="6414888972213066896">از والدینتان پرسیدید آیا اجازه بازدید از این سایت را دارید</translation>
<translation id="6415778972515849510">‏Chromium می‌تواند کمک کند از حساب Google خود محافظت کنید و گذرواژه‌تان را تغییر دهید.</translation>
-<translation id="6417515091412812850">امکان بررسی اینکه آیا مجوز باطل شده است یا نه وجود ندارد.</translation>
<translation id="6431585503458005759">ذخیره نشود</translation>
<translation id="6433490469411711332">ویرایش اطلاعات تماس</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> از اتصال خودداری کرد.</translation>
<translation id="6434309073475700221">رد کردن</translation>
+<translation id="6435221585574090192">‏داده‌های مربوط به رویدادهای امنیتی‌ای را که «محافظت از تهدیدهای شرکتی در Chrome» پرچم‌گذاری کرده‌ است، با «سرپرست» به اشتراک بگذارید. این کار ممکن است شامل نشانی وب صفحه‌ها، نام فایل و فراداده فایل، نام کاربری دستگاه، و نام کاربری Chrome باشد.</translation>
<translation id="6440503408713884761">نادیده گرفته شد</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">افزودن اطلاعات بیشتر</translation>
@@ -1018,20 +1035,19 @@
<translation id="6465306955648956876">مدیریت گذرواژه‌ها…</translation>
<translation id="647261751007945333">خط‌‌مشی‌های دستگاه</translation>
<translation id="6476284679642588870">مدیریت روش‌های پرداخت</translation>
-<translation id="6477321094435799029">‏Chrome کد نامعمول در این این صفحه شناسایی کرده و برای محافظت از اطلاعات شخصی‌تان (مثلاً گذرواژه‌ها، شماره تلفن‌‌ها و کارت‌های اعتباری) آن را مسدود کرده است.</translation>
<translation id="6489534406876378309">شروع بارگذاری کردن خرابی‌ها</translation>
<translation id="6499038740797743453">گذرواژه بازنشانی شود؟</translation>
<translation id="6507833130742554667">کارت‌های اعتباری و نقدی پذیرفته می‌شوند.</translation>
<translation id="650855688985305916">بله، ذخیره شود</translation>
<translation id="6508722015517270189">‏Chrome را راه‌اندازی مجدد کنید</translation>
<translation id="6517596291481585650">این خط‌مشی به‌عنوان فهرستی که خط‌مشی مشخص کرده است ادغام نشد، زیرا فهرست نیست.</translation>
+<translation id="6518133107902771759">تأیید</translation>
<translation id="6521745193039995384">غیرفعال</translation>
<translation id="6529602333819889595">&amp;انجام مجدد حذف</translation>
<translation id="6534179046333460208">پیشنهادهای «وب فیزیکی»</translation>
<translation id="6545864417968258051">اسکن کردن بلوتوث</translation>
<translation id="6554795675067793129">حساب شما توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود.</translation>
<translation id="6556866813142980365">انجام مجدد</translation>
-<translation id="6563469144985748109">مدیرتان هنوز این سایت را تأیید نکرده است</translation>
<translation id="6569060085658103619">درحال مشاهده یک صفحه افزونه هستید</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">صورتی کم‌رنگ</translation>
@@ -1049,11 +1065,13 @@
<translation id="6643016212128521049">پاک کردن</translation>
<translation id="6644283850729428850">این قانون قدیمی شده است.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{هیچ‌کدام}=1{‏از ۱ سایت (از سیستم حساب Google خود خارج نخواهید شد)}one{‏از # سایت (از سیستم حساب Google خود خارج نخواهید شد)}other{‏از # سایت (از سیستم حساب Google خود خارج نخواهید شد)}}</translation>
+<translation id="6652101503459149953">‏استفاده از Windows Hello</translation>
<translation id="6657585470893396449">گذرواژه</translation>
<translation id="6670613747977017428">بازگشت به ایمنی.</translation>
<translation id="6671697161687535275">‏پیشنهاد فرم از Chromium پاک شود؟</translation>
<translation id="6685834062052613830">خروج از سیستم و تکمیل راه‌اندازی</translation>
<translation id="6689271823431384964">‏چون به سیستم وارد شده‌اید، Chrome پیشنهاد می‌کند کارت‌ها را در حساب Google ذخیره کنید. در تنظیمات می‌توانید این رفتار را تغییر دهید. نام دارنده کارت از حساب شما گرفته شده است.</translation>
+<translation id="6707256370811247129">‏اسکن محتواهای حافظه پنهان و فایل‌هایی که در Chrome بارگیری یا بارگذاری کرده‌اید.</translation>
<translation id="6710213216561001401">قبلی</translation>
<translation id="6710594484020273272">&lt;عبارت جستجو را تایپ کنید&gt;</translation>
<translation id="671076103358959139">کد ثبت‌نام:</translation>
@@ -1061,10 +1079,10 @@
<translation id="6738516213925468394">داده‌ها با <ph name="BEGIN_LINK" />گذرنویسه همگام‌سازی‌شده<ph name="END_LINK" /> شما در <ph name="TIME" /> رمز می‌شود. برای شروع همگام‌سازی، آن را وارد کنید.</translation>
<translation id="674375294223700098">خطای ناشناس گواهی سرور.</translation>
<translation id="6744009308914054259">وقتی درانتظار اتصال هستید، می‌توانید برای خواندن مقاله‌های آفلاین، «بارگیری‌ها» را مشاهده کنید.</translation>
+<translation id="6747611005629681221">هشدار: ویژگی‌های منسوخ‌شده!</translation>
<translation id="6753269504797312559">مقدار خط‌‌مشی</translation>
<translation id="6757797048963528358">دستگاهتان به خواب رفته است.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">والدینتان هنوز این سایت را تأیید نکرده‌اند</translation>
<translation id="67862343314499040">بنفش</translation>
<translation id="6786747875388722282">افزونه‌ها</translation>
<translation id="6790428901817661496">پخش</translation>
@@ -1072,6 +1090,7 @@
<translation id="681021252041861472">فیلد ضروری</translation>
<translation id="6810899417690483278">شناسه سفارشی‌سازی</translation>
<translation id="6825578344716086703">‏تلاش کردید به <ph name="DOMAIN" /> دسترسی داشته باشید، اما گواهینامه ارائه‌شده از سوی سرور با استفاده از یک الگوریتم امضای ضعیف (مانند SHA-1) امضا شده است. یعنی ممکن است اعتبارنامه امنیتی ارائه‌شده از سوی سرور جعلی باشد و ممکن است سرور، سرور موردانتظار شما نباشد (ممکن است با یک مهاجم در ارتباط باشید).</translation>
+<translation id="6826370046007623921">جلوگیری از از بین رفتن داده‌ها</translation>
<translation id="6831043979455480757">ترجمه</translation>
<translation id="6839929833149231406">ناحیه</translation>
<translation id="6852204201400771460">برنامه تازه‌سازی شود؟</translation>
@@ -1084,7 +1103,6 @@
<translation id="6891596781022320156">سطح خط‌مشی پشتیبانی نمی‌شود.</translation>
<translation id="6895330447102777224">کارتتان تأیید شد</translation>
<translation id="6897140037006041989">نماینده کاربر</translation>
-<translation id="6903319715792422884">‏با ارسال برخی <ph name="BEGIN_WHITEPAPER_LINK" />اطلاعات سیستم و محتوای صفحه<ph name="END_WHITEPAPER_LINK" /> به Google، به بهبود «مرور ایمن» کمک کنید. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">کاربر:</translation>
<translation id="6934672428414710184">‏این نام از حساب Google شما گرفته شده است</translation>
<translation id="6944692733090228304">گذرواژه‌تان را در سایتی وارد کردید که توسط <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> مدیریت نمی‌شود. برای محافظت از حسابتان، از گذرواژه‌تان در برنامه‌ها و سایت‌های دیگر استفاده نکنید.</translation>
@@ -1129,6 +1147,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> روش دیگر}one{<ph name="PAYMENT_METHOD_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> روش دیگر}other{<ph name="PAYMENT_METHOD_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> روش دیگر}}</translation>
<translation id="7153618581592392745">نیلی کم‌رنگ</translation>
<translation id="717330890047184534">‏شناسه Gaia:</translation>
+<translation id="7174545416324379297">ادغام شد</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> گزینه دیگر}one{<ph name="SHIPPING_OPTION_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> گزینه دیگر}other{<ph name="SHIPPING_OPTION_PREVIEW" /> و <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> گزینه دیگر}}</translation>
<translation id="7177397715882417099">سروری که به آن می‌روید، <ph name="ORIGIN" />، درخواست کرده است
برای همه درخواست‌هایش خط‌مشی ایمنی اعمال شود. اما به‌جای
@@ -1166,6 +1185,7 @@
<translation id="7320336641823683070">راهنمای اتصال</translation>
<translation id="733354035281974745">لغو حساب محلی دستگاه</translation>
<translation id="7334320624316649418">&amp;انجام مجدد ترتیب‌بندی مجدد</translation>
+<translation id="7337706099755338005">در پلتفورم شما دردسترس نیست.</translation>
<translation id="733923710415886693">گواهی سرور از طریق شفافیت گواهینامه نشان داده نشده بود.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">وابسته است:</translation>
@@ -1197,7 +1217,6 @@
<translation id="7440140511386898319">کاوش درحالت آفلاین</translation>
<translation id="7441627299479586546">موضوع خط‌مشی اشتباه است</translation>
<translation id="7442725080345379071">نارنجی روشن</translation>
-<translation id="7444046173054089907">این سایت مسدود شده است</translation>
<translation id="7445762425076701745">هویت سروری که به آن متصل شده‌اید به‌طور کامل راستی‌آزمایی نمی‌شود. با استفاده از نامی به سرور متصل شده‌اید که فقط در شبکه شما معتبر است و ارائه دهنده مجوز خارجی قادر به راستی‌آزمایی مالکیت آن نیست. به دلیل آنکه برخی از ارائه دهندگان مجوز بدون توجه به هر موردی، مجوزهایی را برای این نام‌ها ارائه می‌کنند، روشی برای اطمینان از این امر وجود ندارد که آیا شما به سایت موردنظر خود متصل شده‌اید یا یک سایت مضر.</translation>
<translation id="7451311239929941790">درباره این مشکل <ph name="BEGIN_LINK" />بیشتر بدانید<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">استفاده از پیش‌فرض جهانی (مسدود)</translation>
@@ -1219,9 +1238,9 @@
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">بعد از تأیید شما، جزئیات کارتتان با این سایت به اشتراک گذاشته می‌شود.</translation>
<translation id="7542995811387359312">تکمیل خودکار کارت اعتباری غیر فعال است زیرا این فرم از یک اتصال امن استفاده نمی‌کند.</translation>
-<translation id="7543525346216957623">از والدینتان بخواهید این کار را انجام دهد</translation>
<translation id="7548892272833184391">رفع خطاهای اتصال</translation>
<translation id="7549584377607005141">این صفحه وب برای نمایش صحیح به داده‌هایی نیاز دارد که قبلاً وارد کرده‌اید. می‌توانید این داده‌ها را دوباره ارسال کنید، اما با انجام این کار، هر اقدامی که این صفحه قبلاً انجام داده است تکرار می‌شود.</translation>
+<translation id="7550637293666041147">‏نام کاربری شما در دستگاه و Chrome</translation>
<translation id="7552846755917812628">نکته‌های زیر را امتحان کنید:</translation>
<translation id="7554791636758816595">برگهٔ جدید</translation>
<translation id="7564049878696755256">‏ممکن است دسترسی به حساب <ph name="ORG_NAME" /> را از دست بدهید یا به سرقت هویت دچار شوید. Chrome توصیه می‌کند هم‌اکنون گذرواژه‌تان را تغییر دهید.</translation>
@@ -1236,6 +1255,7 @@
<translation id="7610193165460212391">مقدار خارج از محدوده <ph name="VALUE" /> است.</translation>
<translation id="7613889955535752492">انقضا: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">‏شما در حال حاضر داده‌هایی دارید که با استفاده از نسخه دیگری از گذرواژه حساب Google شما رمزگذاری شده‌اند. لطفاً آن را در زیر وارد کنید.</translation>
+<translation id="7625784245512586808">‏محافظت از تهدیدهای شرکتی در Chrome</translation>
<translation id="7633909222644580952">داده‌های عملکرد و گزارش‌های خرابی</translation>
<translation id="7637571805876720304">‏کارت اعتباری از Chromium پاک شود؟</translation>
<translation id="7638605456503525968">درگاه‌های سریال</translation>
@@ -1248,7 +1268,6 @@
<translation id="7668654391829183341">دستگاه ناشناس</translation>
<translation id="7669271284792375604">مهاجمان در این سایت ممکن است تلاش کنند شما را با نصب برنامه‌هایی که به تجربه مرور شما آسیب می‌رساند، فریب دهند (مثلاً با تغییر دادن صفحه اصلی شما یا با نشان دادن آگهی‌های بیش از حد در سایت‌هایی که بازدید می‌کنید).</translation>
<translation id="7676643023259824263">جستجوی نوشتار بریده‌دان، <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">پلتفورم و ابر</translation>
<translation id="7681101578153515023">موتور جستجو را تغییر دهید</translation>
<translation id="7682287625158474539">ارسال</translation>
<translation id="7687186412095877299">فرم‌های پرداخت را با روش‌های پرداخت ذخیره‌شده‌تان پر می‌کند</translation>
@@ -1263,7 +1282,6 @@
<translation id="7723047071702270851">ویرایش کارت</translation>
<translation id="774634243536837715">محتوای خطرناک مسدود شد.</translation>
<translation id="7752995774971033316">مدیریت نشده</translation>
-<translation id="7755287808199759310">والدینتان می‌توانند این سایت را برای شما بگشایند</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">دیوار آتش یا نرم‌افزار ضدویروس ممکن است مانع اتصال شده باشد.</translation>
<translation id="7759163816903619567">نمایش دامنه:</translation>
@@ -1307,7 +1325,6 @@
<translation id="8004582292198964060">مرورگر</translation>
<translation id="8009225694047762179">مدیریت گذرواژه</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{این کارت و نشانی صورت‌حساب آن ذخیره می‌شود. وقتی به سیستم <ph name="USER_EMAIL" /> وارد شوید می‌توانید از آن استفاده کنید.}one{این کارت‌ها و نشانی صورت‌حساب آن‌ها ذخیره می‌شود. وقتی به سیستم <ph name="USER_EMAIL" /> وارد شوید می‌توانید از آن‌ها استفاده کنید.}other{این کارت‌ها و نشانی صورت‌حساب آن‌ها ذخیره می‌شود. وقتی به سیستم <ph name="USER_EMAIL" /> وارد شوید می‌توانید از آن‌ها استفاده کنید.}}</translation>
-<translation id="8012647001091218357">در حال حاضر نمی‌توانیم با والدینتان ارتباط برقرار کنیم. لطفاً دوباره امتحان کنید.</translation>
<translation id="8025119109950072390">مهاجمان در این سایت ممکن است شما را فریب دهند که کارهای خطرناکی مثل نصب نرم‌افزار یا ارائه اطلاعات شخصی‌تان (مثلاً گذرواژه‌ها، شماره تلفن‌ها یا کارت‌های اعتباری) انجام دهید.</translation>
<translation id="8034522405403831421">این صفحه به زبان <ph name="SOURCE_LANGUAGE" /> است. مایلید آن را به <ph name="TARGET_LANGUAGE" /> ترجمه کنید؟</translation>
<translation id="8035152190676905274">قلم</translation>
@@ -1318,6 +1335,7 @@
<translation id="8041940743680923270">استفاده از پیش‌فرض جهانی (سؤال شود)</translation>
<translation id="8042918947222776840">انتخاب روش تحویل گرفتن</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» درست پیکربندی نمی‌شود. معمولاً حذف‌ نصب «<ph name="SOFTWARE_NAME" />» مشکل را برطرف می‌کند. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">از این پس، لازم نیست کد امنیتی کارت وارد کنید</translation>
<translation id="8066955247577885446">متأسفیم، مشکلی پیش آمد</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">در حالت چرخش نمی‌توان حاشیه‌نویسی کرد</translation>
@@ -1348,6 +1366,7 @@
<translation id="8211406090763984747">اتصال امن است</translation>
<translation id="8218327578424803826">مکان اختصاص یافته:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">گزارش خطای شرکتی</translation>
<translation id="8225771182978767009">شخصی که این رایانه را راه‌اندازی کرده این سایت را مسدود کرده است.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />،‏ <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">صفحه را در برگه «ناشناس» جدیدی باز کنید</translation>
@@ -1402,23 +1421,23 @@
<translation id="8508648098325802031">نماد جستجو</translation>
<translation id="8522552481199248698">‏Chrome می‌تواند کمک کند از حساب Google خود محافظت کنید و گذرواژه‌تان را تغییر دهید.</translation>
<translation id="8543181531796978784">می‌توانید <ph name="BEGIN_ERROR_LINK" />یک مشکل شناسایی‌شده را گزارش کنید<ph name="END_ERROR_LINK" /> یا اگر از خطراتی که امنیت شما را تهدید می‌کنند مطلع شدید، <ph name="BEGIN_LINK" />از این سایت ناامن دیدن کنید<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">سؤال دارید؟ با فردی که بر نمایه‌تان نظارت دارد تماس بگیرید.</translation>
<translation id="8553075262323480129">ترجمه انجام نشد زیرا زبان صفحه تعیین نشد.</translation>
<translation id="8557066899867184262">‏CVC در پشت کارتتان قرار گرفته است.</translation>
<translation id="8559762987265718583">اتصال خصوصی به <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> انجام نمی‌شود، زیرا تاریخ و زمان دستگاه شما (<ph name="DATE_AND_TIME" />) نادرست است.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> سایت مشکوک</translation>
<translation id="8564985650692024650">‏Chromium توصیه می‌کند اگر از گذرواژه <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> خود در سایت دیگری استفاده کردید آن را بازنشانی کنید.</translation>
<translation id="8571890674111243710">ترجمه صفحه به <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">افزودن شماره تلفن</translation>
-<translation id="859285277496340001">این مجوز هیچ مکانیزمی را برای بررسی اینکه آیا باطل شده یا نه مشخص نمی‌کند.</translation>
<translation id="860043288473659153">نام صاحب کارت</translation>
<translation id="861775596732816396">اندازه ۴</translation>
-<translation id="8620436878122366504">والدینتان هنوز این سایت را تأیید نکرده‌اند</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">ذخیره کردن این کارت در این دستگاه</translation>
<translation id="8626112503828625890">‏جزئیات صدور صورت‌حساب در حساب Google ذخیره شود؟</translation>
+<translation id="8647750283161643317">بازنشانی همه به موارد پیش‌فرض</translation>
<translation id="8663226718884576429">خلاصه سفارش، <ph name="TOTAL_LABEL" />، جزئيات بیشتر</translation>
<translation id="8680536109547170164"><ph name="QUERY" />، پاسخ، <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">دردسترس</translation>
<translation id="8703575177326907206">اتصال شما به <ph name="DOMAIN" /> رمزگذاری نشده است.</translation>
<translation id="8718314106902482036">پرداخت کامل نشد</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />، <ph name="DESCRIPTION" />، پیشنهاد جستجو</translation>
@@ -1429,6 +1448,7 @@
<translation id="8738058698779197622">‏به منظور برقراری یک اتصال امن، لازم است که ساعت شما به درستی تنظیم شود. زیرا گواهینامه‌هایی که وب‌سایت‌ها برای شناسایی خودشان استفاده می‌کنند تنها برای دوره‌های زمانی خاصی معتبر هستند. از آنجایی که ساعت دستگاه نادرست است، Chromium نمی‌تواند این گواهینامه‌ها را تأیید کند.</translation>
<translation id="8740359287975076522">‏<ph name="HOST_NAME" />’s &lt;abbr id="dnsDefinition"&gt;آدرس DNS&lt;/abbr&gt; پیدا نشد. درحال بررسی برای تشخیص مشکل.</translation>
<translation id="874846938927089722">کارت‌های اعتباری و پیش‌پرداخت قابل‌قبول</translation>
+<translation id="874918643257405732">نشانک گذاشتن این برگه</translation>
<translation id="8759274551635299824">کارت منقضی شده است</translation>
<translation id="8761567432415473239">‏مرور ایمن Google اخیراً <ph name="BEGIN_LINK" />برنامه‌های خطرناک<ph name="END_LINK" /> را در <ph name="SITE" /> پیدا کرده است.</translation>
<translation id="8763927697961133303">‏دستگاه USB</translation>
@@ -1458,6 +1478,7 @@
<translation id="8938939909778640821">کارت‌های اعتباری و پیش‌پرداخت قابل‌قبول</translation>
<translation id="8943282376843390568">لیمویی</translation>
<translation id="8957210676456822347">مجوز پورتال محدود</translation>
+<translation id="8962950042226115166">سایت مشکوک</translation>
<translation id="8968766641738584599">ذخیره کارت</translation>
<translation id="8971063699422889582">گواهی سرور منقضی شده است.</translation>
<translation id="8975012916872825179">شامل اطلاعاتی مانند شماره تلفن، نشانی ایمیل و نشانی تحویل کالا می‌شود</translation>
@@ -1480,24 +1501,24 @@
<translation id="9035022520814077154">خطای امنیتی</translation>
<translation id="9038649477754266430">استفاده از یک سرویس پیش‌بینی برای بار کردن سریع‌تر صفحه‌ها</translation>
<translation id="9039213469156557790">علاوه بر این، این صفحه دارای منابع دیگری است که امن نیستند. دیگران می‌توانند در حین انتقال، این منابع را ببینند و این منابع می‌توانند برای تغییر رفتار صفحه، توسط یک مهاجم تغییر داده شوند.</translation>
+<translation id="9044359186343685026">استفاده از شناسه لمسی</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">شما سعی کردید به <ph name="DOMAIN" /> دسترسی داشته باشید، اما سرور یک گواهی نامعتبر را نشان داد.</translation>
<translation id="9050666287014529139">عبارت عبور</translation>
<translation id="9065203028668620118">ویرایش</translation>
<translation id="9065745800631924235">جستجوی <ph name="TEXT" /> از سابقه</translation>
<translation id="9069693763241529744">توسط افزونه مسدود شده است</translation>
-<translation id="9076283476770535406">این سایت ممکن است شامل محتوای مخصوص بزرگسالان باشد</translation>
<translation id="9076630408993835509">‏این مرورگر توسط شرکت یا سازمان دیگری مدیریت نمی‌شود. فعالیت در این دستگاه ممکن است خارج از Chrome مدیریت شود. <ph name="BEGIN_LINK" />بیشتر بدانید<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">اطلاعات بیشتری نیاز است</translation>
<translation id="9080712759204168376">خلاصه سفارش</translation>
<translation id="9089260154716455634">خط‌مشی ساعت‌های خاموشی:</translation>
<translation id="9095388113577226029">زبان‌های بیشتر...</translation>
+<translation id="9098981495403789647">‏سرپرست «محافظت از تهدیدهای شرکتی در Chrome» در مرورگرتان فعال شده است. «محافظت از تهدیدهای شرکتی در Chrome» به برخی داده‌هایتان دسترسی دارد.</translation>
<translation id="9103872766612412690">‏<ph name="SITE" /> معمولاً برای محافظت از اطلاعات شما از رمزگذاری استفاده می‌کند. اما این بار که Chromium تلاش کرد به <ph name="SITE" /> متصل شود، وب‌سایت اعتبارنامه‌ای نامعمول و نادرست را برگرداند. ممکن است مهاجمی در تلاش باشد خود را به‌جای <ph name="SITE" /> معرفی کند یا یک صفحه ورود به سیستم Wi-Fi در ارتباط اختلال ایجاد کرده باشد. اطلاعات شما همچنان ایمن است، زیرا Chromium قبل از هرگونه تبادل داده، اتصال را متوقف کرد.</translation>
<translation id="9106062320799175032">افزودن نشانی صورت‌حساب</translation>
<translation id="9114524666733003316">درحال تأیید کردن کارت…</translation>
<translation id="9128870381267983090">اتصال به شبکه</translation>
<translation id="9137013805542155359">نمایش مورد اصلی</translation>
-<translation id="9137248913990643158">‏لطفاً پیش از استفاده از این برنامه، Chrome را باز کنید و به سیستم آن وارد شوید.</translation>
<translation id="9141013498910525015">مدیریت نشانی‌ها</translation>
<translation id="9148088599418889305">انتخاب روش ارسال</translation>
<translation id="9148507642005240123">&amp;واگرد ویرایش</translation>
diff --git a/chromium/components/strings/components_strings_fi.xtb b/chromium/components/strings/components_strings_fi.xtb
index 1a3d2a5a8c3..8c79ae13b64 100644
--- a/chromium/components/strings/components_strings_fi.xtb
+++ b/chromium/components/strings/components_strings_fi.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Lisää kortissa oleva nimi</translation>
<translation id="1089439967362294234">Vaihda salasana</translation>
+<translation id="1096545575934602868">Kentässä voi olla korkeintaan <ph name="MAX_ITEMS_LIMIT" /> kohtaa. Muut kohdat ohitetaan.</translation>
<translation id="109743633954054152">Määritä salasanat Chrome-asetuksissa</translation>
<translation id="1103523840287552314">Käännä <ph name="LANGUAGE" /> aina</translation>
<translation id="1107591249535594099">Jos tämä ruutu on valittu, Chrome tallentaa kortin kopion tälle laitteelle, jotta lomakkeiden täyttö nopeutuu.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Käytä osoitteen <ph name="URL" /> <ph name="BEGIN_LINK" />välimuistiversiota<ph name="END_LINK" /></translation>
<translation id="1156303062776767266">Katselet paikallista tai jaettua tiedostoa</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> katkaisi yhteyden yllättäen.</translation>
+<translation id="115926840831309955">Tarkista CVC ja yritä uudelleen tai korjaa viimeinen voimassaolopäivä</translation>
<translation id="1161325031994447685">Muodosta yhteys Wi-Fi-verkkoon uudelleen.</translation>
<translation id="1165039591588034296">Virhe</translation>
<translation id="1175364870820465910">Tulo&amp;sta...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">Tietokoneelle asennettu ohjelmisto estää Chromea muodostamasta turvallista yhteyttä verkkoon (vain Windows-tietokoneilla)</translation>
<translation id="1294154142200295408">Komentorivin muunnelmat</translation>
<translation id="129553762522093515">Hiljattain suljetut välilehdet</translation>
+<translation id="1298536327547837046">Haittaohjelmien tarkistus</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Tyhjennä evästeet.<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Käytöstä poistetut ominaisuudet</translation>
<translation id="1320233736580025032">Prc1 (kirjekuori)</translation>
<translation id="132301787627749051">Hae leikepöytäkuvaa</translation>
<translation id="1323433172918577554">Näytä lisää</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">Odotetaan yhteyttä…</translation>
<translation id="1529521330346880926">10x15 (kirjekuori)</translation>
+<translation id="1530707389502320859">Sivusto, jolle yritit juuri siirtyä, ei vaikuta aidolta. Hyökkääjät jäljittelevät joskus sivustoja tekemällä URL-osoitteeseen pieniä muutoksia, joita on vaikea havaita.</translation>
<translation id="1531205177818805254">Johto</translation>
<translation id="1532118530259321453">Viesti tältä sivulta</translation>
<translation id="153384715582417236">Siinä kaikki toistaiseksi</translation>
@@ -130,7 +135,7 @@
&lt;p&gt;Muokkaa aikaa ja päivämäärää &lt;strong&gt;Asetukset&lt;/strong&gt;‑sovelluksen &lt;strong&gt;Yleistä&lt;/strong&gt;‑osiossa.&lt;/p&gt;</translation>
<translation id="1569487616857761740">Lisää viimeinen voimassaolopäivä</translation>
<translation id="1581080074034554886">CVC</translation>
-<translation id="1583429793053364125">Jokin meni vikaan tätä verkkosivua näytettäessä.</translation>
+<translation id="1583429793053364125">Jotain meni pieleen. tätä verkkosivua näytettäessä.</translation>
<translation id="1592005682883173041">Tietojen paikallinen käyttö</translation>
<translation id="1594030484168838125">Valitse</translation>
<translation id="161042844686301425">Turkoosi</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">Käyttöjärjestelmä</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Tiedosto on liian suuri merkintöihin</translation>
-<translation id="1721312023322545264">Tarvitset henkilön <ph name="NAME" /> luvan käydä tällä sivustolla</translation>
<translation id="1721424275792716183">* Kenttä on pakollinen.</translation>
<translation id="1727741090716970331">Lisää kelvollinen kortin numero</translation>
<translation id="1728677426644403582">Tämä on verkkosivun lähdekoodi.</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Avaamasi verkkosivustot ja niillä vietetty aika</translation>
<translation id="1826516787628120939">Tarkistetaan</translation>
<translation id="1834321415901700177">Tämä sivusto sisältää haitallisia ohjelmia</translation>
+<translation id="1838374766361614909">Tyhjennä haku</translation>
<translation id="1839551713262164453">Käytäntöarvojen vahvistus epäonnistui sisältäen virheitä</translation>
<translation id="1842969606798536927">Maksa</translation>
<translation id="1871208020102129563">Välityspalvelin on asetettu käyttämään kiinteitä välityspalvelimia, ei .pac-URL-osoitetta.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Tiivistä luettelo</translation>
<translation id="1898423065542865115">Suodatus</translation>
<translation id="1914326953223720820">Purkupalvelu</translation>
+<translation id="1915697529809968049">Käytetäänkö Touch ID:tä CVC:n sijaan?</translation>
<translation id="1916770123977586577">Päivitä tämä sivu, niin päivitetyt asetuksesi otetaan käyttöön tällä sivustolla.</translation>
<translation id="1919345977826869612">Mainokset</translation>
<translation id="1919367280705858090">Tiettyjen virheiden korjaaminen</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Verkkotunnuksen <ph name="DOMAIN" /> kirjanmerkit</translation>
<translation id="1973335181906896915">Sarjaesittämisen virhe</translation>
<translation id="1974060860693918893">Lisäasetukset</translation>
+<translation id="1974883374937189061">Auta kehittämään Chromen turvallisuutta lähettämällä <ph name="BEGIN_WHITEPAPER_LINK" />joidenkin avattujen sivujen URL-osoitteita, rajallisia järjestelmätietoja ja osia sivujen sisällöstä<ph name="END_WHITEPAPER_LINK" /> Googlelle. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Laiteohjelmiston versio</translation>
<translation id="1981206234434200693">Tyhjennä Chromen selaushistoriadata</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ja 1 muu}other{ja # muuta}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Anna kelvollinen viimeinen voimassaolovuosi.</translation>
<translation id="2212735316055980242">Käytäntöä ei löydy</translation>
<translation id="2213606439339815911">Noudetaan merkintöjä…</translation>
+<translation id="2215727959747642672">Tiedostojen muokkaus</translation>
<translation id="2218879909401188352">Sivustolla <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> tällä hetkellä olevat hyökkääjät voivat asentaa vaarallisia laitettasi vahingoittavia sovelluksia, lisätä piilomaksuja puhelinlaskuusi tai varastaa henkilökohtaisia tietojasi. <ph name="BEGIN_LEARN_MORE_LINK" />Lisätietoja<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Ei internetyhteyttä</translation>
<translation id="2230458221926704099">Korjaa yhteytesi käyttämällä <ph name="BEGIN_LINK" />diagnostiikkasovellusta<ph name="END_LINK" />.</translation>
<translation id="2239100178324503013">Lähetä nyt</translation>
+<translation id="2248949050832152960">Käytä WebAuthnia</translation>
<translation id="225207911366869382">Tämän käytännön arvo on vanhentunut.</translation>
<translation id="2257315177824333709">Korttia ei voi juuri nyt tallentaa</translation>
<translation id="2262243747453050782">HTTP-virhe</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Virheellinen hakukoneen URL-osoite.</translation>
<translation id="2482878487686419369">Ilmoitukset</translation>
<translation id="248348093745724435">Laitteen käytännöt</translation>
-<translation id="2485387744899240041">Laitteen ja selaimen käyttäjänimet</translation>
<translation id="2491120439723279231">Palvelimen varmenteessa on virheitä.</translation>
<translation id="2493640343870896922">Kirje-plus</translation>
<translation id="2495083838625180221">JSON-jäsentäjä</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Takaisin</translation>
<translation id="2503184589641749290">Hyväksytyt maksu- ja prepaid-kortit</translation>
<translation id="2505268675989099013">Suojaa tili</translation>
+<translation id="2515335152965840738">OHITA</translation>
<translation id="2515629240566999685">Tarkista alueesi mobiilisignaali.</translation>
<translation id="2523886232349826891">Tallennetaan vain tälle laitteelle</translation>
<translation id="2524461107774643265">Lisää tietoja</translation>
@@ -321,7 +330,7 @@
<translation id="2587730715158995865">Julkaisijalta <ph name="ARTICLE_PUBLISHER" />. Lue tämä ja <ph name="OTHER_ARTICLE_COUNT" /> muuta tarinaa.</translation>
<translation id="2587841377698384444">Hakemistosovellusliittymän tunnus:</translation>
<translation id="2595719060046994702">Yritys tai muu organisaatio ei ylläpidä tätä laitetta tai tiliä.</translation>
-<translation id="2597378329261239068">Tämä asiakirja on suojattu salasanalla. Anna salasana.</translation>
+<translation id="2597378329261239068">Tämä asiakirja on suojattu salasanalla. Lisää salasana.</translation>
<translation id="2609632851001447353">Muunnelmat</translation>
<translation id="2618023639789766142">C10 (kirjekuori)</translation>
<translation id="2625385379895617796">Kellosi edistää</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Lähetä</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Ei mitään}=1{1 salasana (<ph name="DOMAIN_LIST" />)}=2{2 salasanaa (<ph name="DOMAIN_LIST" />)}other{# salasanaa (<ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Sulje muita välilehtiä tai sovelluksia.</translation>
-<translation id="267371737713284912">kumoa painamalla <ph name="MODIFIER_KEY_DESCRIPTION" /></translation>
<translation id="2674170444375937751">Haluatko varmasti poistaa nämä sivut historiastasi?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Poistu</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Arvo ei vastaa muotoa.</translation>
<translation id="2705137772291741111">Tämän sivuston välimuistiin tallennettu kopio oli lukukelvoton.</translation>
<translation id="2709516037105925701">Automaattinen täyttö</translation>
-<translation id="2712173769900027643">Pyydä käyttölupaa</translation>
<translation id="2713444072780614174">Valkoinen</translation>
<translation id="2720342946869265578">Nearby</translation>
<translation id="2721148159707890343">Pyyntö onnistui</translation>
<translation id="2728127805433021124">Palvelimen varmenne on allekirjoitettu heikolla allekirjoitusalgoritmilla.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />yhteysdiagnostiikkaa<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Jos otat nämä ominaisuudet käyttöön, voit menettää selaustietoja tai
+ vaarantaa tietosuojasi tai yksityisyytesi. Ominaisuuksien käyttöönotto koskee kaikkia
+ selaimen käyttäjiä.</translation>
<translation id="2735043616039983645">Käytännölle on useita lähteitä, joiden arvot ovat ristiriidassa.</translation>
<translation id="2738330467931008676">Valitse noutopaikan osoite</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Yhteys katkaistiin.</translation>
<translation id="2788784517760473862">Hyväksytyt luottokortit</translation>
<translation id="2792012897584536778">Tämän laitteen järjestelmänvalvojat ovat ottaneet käyttöön tietosuojavarmenteita, joiden avulla he saattavat nähdä avaamiesi sivustojen sisällöt.</translation>
-<translation id="2794233252405721443">Sivusto estetty</translation>
<translation id="2799020568854403057">Sivusto sisältää haitallisia sovelluksia</translation>
<translation id="2799223571221894425">Käynnistä uudelleen</translation>
<translation id="2803306138276472711">Google-selaussuoja havaitsi sivustossa <ph name="SITE" /> äskettäin <ph name="BEGIN_LINK" />haittaohjelmia<ph name="END_LINK" />. Tavallisesti turvalliset sivustot voivat joskus saada haittaohjelmatartunnan.</translation>
+<translation id="2815364696811431560">POISTU SIVUSTOLTA</translation>
<translation id="2824775600643448204">Osoite- ja hakupalkki</translation>
<translation id="2826760142808435982">Yhteys on salattu ja todennettu <ph name="CIPHER" />:n avulla ja se käyttää menetelmää <ph name="KX" /> avainvaihtomekanismina.</translation>
<translation id="2835170189407361413">Tyhjennä lomake</translation>
<translation id="2847118875340931228">Avaa incognito-ikkuna</translation>
<translation id="2850739647070081192">Kutsu (kirjekuori)</translation>
-<translation id="2851634818064021665">Tarvitset luvan tälle sivustolle siirtymiseen.</translation>
<translation id="2856444702002559011">Sivustolle <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> hyökännyt taho voi yrittää varastaa tietojasi (esimerkiksi salasanoja, viestejä tai luottokorttitietoja). <ph name="BEGIN_LEARN_MORE_LINK" />Lisätietoja<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Tallennetaanko kortti?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Jos tämä on käytössä, Chromium tallentaa kortin kopion tälle laitteelle nopeuttaakseen lomakkeiden täyttöä.</translation>
<translation id="2985398929374701810">Anna kelvollinen osoite.</translation>
<translation id="2986368408720340940">Tämä noutotapa ei ole käytettävissä. Kokeile toista tapaa.</translation>
+<translation id="2987034854559945715">Ei hakua vastaavia ominaisuuksia</translation>
<translation id="2991174974383378012">Jakaminen verkkosivustojen kanssa</translation>
<translation id="2991571918955627853"><ph name="SITE" /> ei ole juuri nyt käytettävissä, koska se käyttää HSTS:ää. Verkkovirheet ja hyökkäykset ovat yleensä väliaikaisia, joten sivu luultavasti toimii myöhemmin.</translation>
<translation id="3005723025932146533">Näytä tallennettu kopio</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Väärä käytäntötyyppi</translation>
<translation id="3037605927509011580">Harmin paikka!</translation>
<translation id="3041612393474885105">Varmenteen tiedot</translation>
+<translation id="3057676462092457419">DnsOverHttps-tilaa <ph name="SECURE_DNS_MODE_SECURE" /> ei vielä tueta, tilaksi on asetettu <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (kirjekuori)</translation>
<translation id="3061707000357573562">Virheenkorjauspalvelu</translation>
<translation id="3064966200440839136">Incognito-tilasta poistutaan ulkoisessa sovelluksessa maksamisen vuoksi. Haluatko jatkaa?</translation>
@@ -428,6 +439,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" />, palvelin: <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Peruuta maksu</translation>
<translation id="3207960819495026254">Kirjanmerkeissä</translation>
+<translation id="3209034400446768650">Sivu voi veloittaa</translation>
<translation id="3225919329040284222">Palvelin esitti varmenteen, joka ei vastaa sisäänrakennettuja odotuksia. Tietyillä tehokkaasti suojatuilla sivustoilla on odotuksia, joilla suojataan käyttäjiä.</translation>
<translation id="3226128629678568754">Paina päivityspainiketta, niin sivun lataukseen tarvittavat tiedot lähetetään uudelleen.</translation>
<translation id="3227137524299004712">Mikrofoni</translation>
@@ -435,7 +447,6 @@
<translation id="3229041911291329567">Laitteen ja selaimen versiotiedot</translation>
<translation id="323107829343500871">Anna kortin <ph name="CREDIT_CARD" /> CVC</translation>
<translation id="3234666976984236645">Havaitse aina tärkeä sisältö tällä sivustolla</translation>
-<translation id="3254409185687681395">Luo kirjanmerkki tälle sivulle</translation>
<translation id="3270847123878663523">K&amp;umoa uudelleenjärjestely</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Lisää kortissa oleva nimi</translation>
@@ -445,7 +456,6 @@
<translation id="3320021301628644560">Lisää laskutusosoite</translation>
<translation id="3324983252691184275">Karmiininpunainen</translation>
<translation id="3338095232262050444">Turvallinen</translation>
-<translation id="3345135638360864351">Tämän sivuston käyttöpyyntöä ei voitu lähettää henkilölle <ph name="NAME" />. Yritä uudelleen.</translation>
<translation id="3355823806454867987">Muuta välityspalvelimen asetuksia...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />ei tallenna<ph name="END_EMPHASIS" />
<ph name="BEGIN_LIST" />
@@ -479,18 +489,15 @@
<translation id="3462200631372590220">Piilota lisäasetukset</translation>
<translation id="3467763166455606212">Kortinhaltijan nimi on pakollinen.</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, tällä hetkellä avoinna, siirry avoimelle välilehdelle painamalla ensin sarkainta ja sitten Enteriä</translation>
-<translation id="3479539252931486093">Etkö odottanut tätä? <ph name="BEGIN_LINK" />Kerro siitä meille.<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ei nyt</translation>
<translation id="3484560055331845446">Saatat menettää pääsyn Google-tilillesi. Chrome suosittelee vaihtamaan salasanan nyt. Sinua pyydetään kirjautumaan sisään.</translation>
<translation id="3495081129428749620">Hae sivulta
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Emme tavoittaneet vanhempaasi. Yritä uudelleen.</translation>
<translation id="3512163584740124171">Tämä käytäntö ohitetaan, koska saman käytäntöryhmän toisella käytännöllä on korkeampi prioriteetti.</translation>
<translation id="3528171143076753409">Palvelimen varmenne ei ole luotettava.</translation>
<translation id="3528485271872257980">Tummanruskea</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Vähintään 1 kohde synkronoiduilla laitteilla}=1{1 kohde (ja lisää synkronoiduilla laitteilla)}other{# kohdetta (ja lisää synkronoiduilla laitteilla)}}</translation>
<translation id="3539171420378717834">Säilytä tämän kortin kopio laitteella.</translation>
-<translation id="3556433843310711081">Ylläpitäjä voi kumota eston puolestasi.</translation>
<translation id="3566021033012934673">Yhteytesi ei ole salattu</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Viesti upotetulta sivulta osoitteessa <ph name="SITE" /></translation>
@@ -518,6 +525,7 @@
<translation id="3678529606614285348">Avaa sivu uudessa incognito-ikkunassa (Ctrl + Vaihto + N).</translation>
<translation id="3679803492151881375">Kaatumisraportti tallennettu <ph name="CRASH_TIME" />, lähetetty <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Varmenteen tiedot</translation>
+<translation id="3701427423622901115">Palautus hyväksyttiin.</translation>
<translation id="3704162925118123524">Käyttämäsi verkko saattaa edellyttää kirjautumista.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Ladataan...</translation>
@@ -534,6 +542,7 @@
<translation id="3748148204939282805">Sivustolle <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> hyökännyt taho voi yrittää huijata sinua tekemään jotain vaarallista, kuten asentamaan ohjelmia tai paljastamaan henkilötietojasi (esimerkiksi salasanoja, puhelinnumeroita tai luottokorttitietoja). <ph name="BEGIN_LEARN_MORE_LINK" />Lisätietoja<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Käännös epäonnistui palvelinvirheen vuoksi.</translation>
<translation id="3759461132968374835">Ei viimeaikaisia kaatumisilmoituksia. Jos selain kaatui kaatumisilmoitusten ollessa pois käytöstä, ilmoituksia ei näytetä täällä.</translation>
+<translation id="3760561303380396507">Käytetäänkö Windows Hellota CVC:n sijaan?</translation>
<translation id="3761718714832595332">Piilota tila</translation>
<translation id="3765032636089507299">Selaussuojasivu on työn alla.</translation>
<translation id="3778403066972421603">Haluatko tallentaa tämän kortin Google-tilille ja tälle laitteelle?</translation>
@@ -543,6 +552,7 @@
<translation id="3789155188480882154">Koko 16</translation>
<translation id="3797522431967816232">Prc3 (kirjekuori)</translation>
<translation id="3807873520724684969">Haitallinen sisältö estetty</translation>
+<translation id="3808375843007691220">Varoitus: Kokeellisia ominaisuuksia</translation>
<translation id="3810973564298564668">Hallinnoi</translation>
<translation id="382518646247711829">Jos käytät välityspalvelinta…</translation>
<translation id="3828924085048779000">Tunnuslause ei voi olla tyhjä.</translation>
@@ -551,11 +561,11 @@
<translation id="3858027520442213535">Päivitä päivämäärä ja aika</translation>
<translation id="3884278016824448484">Ristiriitainen laitteen tunnus</translation>
<translation id="3885155851504623709">Kunta</translation>
-<translation id="3886446263141354045">Pyyntösi päästä tälle sivustolle on lähetetty henkilölle <ph name="NAME" />.</translation>
<translation id="3890664840433101773">Lisää sähköposti</translation>
<translation id="3901925938762663762">Kortti on vanhentunut.</translation>
<translation id="3906600011954732550">B5-ekstra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Käytetäänkö WebAuthnia CVC:n sijaan?</translation>
<translation id="3946209740501886391">Kysy aina tällä sivustolla</translation>
<translation id="3949571496842715403">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenteessa ei määritetä kohteen vaihtoehtoisia nimiä. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
<translation id="3949601375789751990">Selaushistoriasi näkyy tässä.</translation>
@@ -566,11 +576,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ei mitään}=1{1 sivustolta }other{# sivustolta }}</translation>
<translation id="397105322502079400">Lasketaan...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> on estetty</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> on ottanut Chrome Enterprisen uhkientorjunnan käyttöön selaimellesi. Chrome Enterprisen uhkientorjunnalla on pääsy osaan datastasi.</translation>
<translation id="3987940399970879459">Alle 1 Mt</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 verkkosivu lähistöllä}other{# verkkosivua lähistöllä}}</translation>
<translation id="4030383055268325496">K&amp;umoa lisäys</translation>
<translation id="4032320456957708163">Selaimen ylläpitäjä on <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Avaamasi linkki johtaa sivustolle, jolla et yleensä käy. Se voi yrittää johtaa sinua harhaan.</translation>
<translation id="4058922952496707368">Avain <ph name="SUBKEY" />: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (kirjekuori)</translation>
<translation id="4067947977115446013">Lisää kelvollinen osoite</translation>
@@ -583,6 +593,7 @@
<translation id="4103249731201008433">Laitteen sarjanumero on virheellinen</translation>
<translation id="410351446219883937">Automaattinen toisto</translation>
<translation id="4103763322291513355">Voit lukea listan kielletyistä URL-osoitteista ja muut järjestelmänvalvojasi määräämät käytännöt osoitteessa &lt;strong&gt;chrome://policy&lt;/strong&gt;.</translation>
+<translation id="4108231218301530806">Vahvista kortti seuraavan kerran sormenjäljellä.</translation>
<translation id="4110652170750985508">Tarkasta maksu</translation>
<translation id="4112140312785995938">Kelaa taaksepäin</translation>
<translation id="4116663294526079822">Salli aina tässä sivustossa</translation>
@@ -597,6 +608,7 @@
<translation id="4171400957073367226">Virheellinen vahvistusallekirjoitus.</translation>
<translation id="4173315687471669144">Foolscap (203 mm x 330 mm)</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> toinen kohde}other{<ph name="ITEM_COUNT" /> muuta kohdetta}}</translation>
+<translation id="4176463684765177261">Pois käytöstä</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Jos haluat maksaa nopeammin ensi kerralla, lisää kortti ja laskutusosoite Google-tilillesi.</translation>
<translation id="4196861286325780578">&amp;Toista siirto</translation>
@@ -633,6 +645,7 @@
<translation id="4277028893293644418">Pyydä uusi salasana</translation>
<translation id="4279811152705618813"><ph name="ENROLLMENT_DOMAIN" /> ylläpitää laitetta (<ph name="DEVICE_TYPE" />)</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Tämä kortti on tallennettu Google-tilillesi}other{Nämä kortit on tallennettu Google-tilillesi}}</translation>
+<translation id="428847186335018806">Tarkista Chromessa lataamasi tai lähettämäsi tiedostot.</translation>
<translation id="42981349822642051">Laajenna</translation>
<translation id="4302965934281694568">Chou3 (kirjekuori)</translation>
<translation id="4305817255990598646">Vaihda</translation>
@@ -662,7 +675,6 @@
<translation id="4435702339979719576">Postikortti</translation>
<translation id="443673843213245140">Välityspalvelinta ei saa käyttää, mutta erilliset välityspalvelimen asetukset on määritetty.</translation>
<translation id="445100540951337728">Hyväksytyt maksukortit</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" />: epäilyttävää toimintaa</translation>
<translation id="4466881336512663640">Lomakkeen muutokset menetetään. Haluatko varmasti jatkaa?</translation>
<translation id="4477350412780666475">Seuraava kappale</translation>
<translation id="4482953324121162758">Tätä sivustoa ei käännetä.</translation>
@@ -689,6 +701,7 @@
<translation id="4594403342090139922">K&amp;umoa poisto</translation>
<translation id="4597348597567598915">Koko 8</translation>
<translation id="4600854749408232102">C6/C5 (kirjekuori)</translation>
+<translation id="464342062220857295">Hakutoiminnot</translation>
<translation id="4646534391647090355">Siirry nyt</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenne sisältää virheitä. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
@@ -697,7 +710,6 @@
<translation id="4691835149146451662">Arkkitehti-A (kirjekuori)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Yhteys keskeytyi</translation>
-<translation id="471880041731876836">Sinulla ei ole lupaa siirtyä tälle sivustolle.</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windowsin verkon diagnostiikkaa<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Päivitä käytännöt</translation>
<translation id="4728558894243024398">Käyttöympäristö</translation>
@@ -725,7 +737,6 @@
<translation id="4816492930507672669">Sovita sivulle</translation>
<translation id="4850886885716139402">Näytä</translation>
<translation id="4854362297993841467">Tämä toimitustapa ei ole käytettävissä. Kokeile toista tapaa.</translation>
-<translation id="4858792381671956233">Pyysit vanhemmiltasi lupaa käydä tällä sivustolla.</translation>
<translation id="4864052566555297930">Turvallisuusvinkki:</translation>
<translation id="4876188919622883022">Yksinkertaistettu näkymä</translation>
<translation id="4876305945144899064">Ei käyttäjänimeä</translation>
@@ -749,7 +760,9 @@
<translation id="4974590756084640048">Ota varoitukset uudelleen käyttöön</translation>
<translation id="4984339528288761049">Prc5 (kirjekuori)</translation>
<translation id="4989163558385430922">Näytä kaikki</translation>
+<translation id="4989542687859782284">Ei käytettävissä</translation>
<translation id="4989809363548539747">Tätä laajennusta ei tueta.</translation>
+<translation id="4995216769782533993">Vahvista turvakoodi, jotta kortin tiedot voidaan jakaa tälle sivustolle</translation>
<translation id="5002932099480077015">Kun tämä vaihtoehto on käytössä, Chrome nopeuttaa lomakkeiden täyttämistä tallentamalla kortin tiedot tälle laittelle.</translation>
<translation id="5015510746216210676">Laitteen nimi:</translation>
<translation id="5017554619425969104">Kopioimasi teksti</translation>
@@ -778,6 +791,7 @@
<translation id="5115216390227830982">Eurooppalainen-Edp</translation>
<translation id="5115563688576182185">(64-bittinen)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Vahvista kortti</translation>
<translation id="5135404736266831032">Hallinnoi osoitteita…</translation>
<translation id="5138227688689900538">Näytä vähemmän</translation>
<translation id="5141240743006678641">Salaa synkronoidut salasanat Google-kirjautumistietojesi avulla</translation>
@@ -804,6 +818,7 @@
<translation id="5251803541071282808">Pilvi</translation>
<translation id="5252000469029418751">C7 (kirjekuori)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Koko järjestelmään vaikuttavat ominaisuudet voi tehdä vain omistaja: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Varoitus: tätä käytäntöä ei yhdistetty PolicyDictionaryMultipleSourceMergeList-käytännössä kuvatulla tavalla, sillä se ei kuulu yhdistettävissä oleviin sanakirjakäytäntöihin.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Loppu</translation>
@@ -827,7 +842,6 @@
<translation id="536296301121032821">Käytännön asetuksien tallentaminen epäonnistui</translation>
<translation id="5371425731340848620">Päivitä kortti</translation>
<translation id="5377026284221673050">"Kellosi jätättää", "Kellosi edistää" tai "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Tämä sivu voi yrittää huijata sinua, varastaa henkilökohtaisia tietojasi tai vahingoittaa laitettasi. Ole varovainen, kun lisäät henkilökohtaisia tietoja tai avaat ladattuja tiedostoja.</translation>
<translation id="5384855140246857529">Jos haluat käyttää kortteja kaikilla laitteillasi, kirjaudu sisään ja ota synkronointi käyttöön.</translation>
<translation id="5386426401304769735">Tämän sivuston varmenneketju sisältää varmenteen, joka on allekirjoitettu SHA-1:llä.</translation>
<translation id="538659543871111977">A4-välilehti</translation>
@@ -841,6 +855,8 @@
<translation id="5457113250005438886">Virheellinen</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> ja <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> toinen}other{<ph name="CONTACT_PREVIEW" /> ja <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> muuta}}</translation>
<translation id="5470861586879999274">&amp;Toista muokkaus</translation>
+<translation id="5473728911100096288">Jos otat nämä ominaisuudet käyttöön, käytät käytöstä poistettuja ominaisuuksia,
+ jotka eivät näy tulevissa versioissa.</translation>
<translation id="5478437291406423475">B6/C4 (kirjekuori)</translation>
<translation id="5481076368049295676">Tämä sisältö saattaa yrittää asentaa vaarallisia ohjelmistoja laitteellesi tai varastaa tai poistaa tietojasi. <ph name="BEGIN_LINK" />Näytä silti<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Lisää kelvollinen osoite</translation>
@@ -864,7 +880,6 @@
<translation id="5570825185877910964">Suojaa tili</translation>
<translation id="5571083550517324815">Nouto tästä osoitteesta ei onnistu. Valitse eri osoite.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 käytössä}other{# käytössä}})</translation>
-<translation id="5572851009514199876">Aloita ja kirjaudu sisään, jotta Chrome voi tarkistaa, onko sinulla oikeus käyttää tätä sivustoa.</translation>
<translation id="5580958916614886209">Tarkista vanhentumiskuukausi ja yritä uudelleen.</translation>
<translation id="5586446728396275693">Ei tallennettuja osoitteita</translation>
<translation id="5595485650161345191">Osoitteen muokkaus</translation>
@@ -872,6 +887,7 @@
<translation id="560412284261940334">Hallintaa ei tueta</translation>
<translation id="5605670050355397069">Kierrevihko</translation>
<translation id="5607240918979444548">Arkkitehti-C</translation>
+<translation id="5608165884683734521">Tämä voi olla vilpillinen tai valesivusto. Chrome suosittelee siltä poistumista.</translation>
<translation id="5610142619324316209">Tarkista yhteys.</translation>
<translation id="5610807607761827392">Voit hallita kortteja ja osoitteita <ph name="BEGIN_LINK" />Asetuksissa<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> uudelleenohjasi sinut liian monta kertaa.</translation>
@@ -895,11 +911,11 @@
<translation id="5720705177508910913">Nykyinen käyttäjä</translation>
<translation id="5728056243719941842">C5 (kirjekuori)</translation>
<translation id="5730040223043577876">Chrome suosittelee salasanan vaihtamista, jos olet käyttänyt sitä myös muilla sivustoilla.</translation>
-<translation id="5732392974455271431">Vanhempasi voivat kumota eston puolestasi.</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Tallenna kortti Google-tilillesi}other{Tallenna kortit Google-tilillesi}}</translation>
<translation id="5763042198335101085">Anna voimassa oleva sähköpostiosoite.</translation>
<translation id="5765072501007116331">Valitse osoite, niin näet toimitustavat ja vaatimukset.</translation>
<translation id="5778550464785688721">MIDI-laitteiden täysi käyttöoikeus</translation>
+<translation id="5781136890105823427">Kokeilu käytössä</translation>
<translation id="578305955206182703">Kullanruskea</translation>
<translation id="57838592816432529">Mykistä</translation>
<translation id="5784606427469807560">Korttia vahvistettaessa tapahtui virhe. Tarkista internetyhteys ja yritä uudelleen.</translation>
@@ -916,13 +932,16 @@
<translation id="5860033963881614850">Pois käytöstä</translation>
<translation id="5863847714970149516">Avaamasi sivu voi yrittää veloittaa sinulta rahaa</translation>
<translation id="5866257070973731571">Lisää puhelinnumero</translation>
+<translation id="5866898949289125849">Katselet kehittäjätyökalut-sivustoa</translation>
<translation id="5869405914158311789">Sivustoon ei saada yhteyttä</translation>
<translation id="5869522115854928033">Tallennetut salasanat</translation>
<translation id="5887400589839399685">Kortti tallennettu</translation>
<translation id="5893752035575986141">Luottokortit hyväksytään.</translation>
+<translation id="5895138241574237353">Käynnistä uudelleen</translation>
<translation id="5901630391730855834">Keltainen</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkronoitu)</translation>
<translation id="5916664084637901428">Käytössä</translation>
+<translation id="59174027418879706">Käytössä</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Tallennetaanko kortti Google-tilille?</translation>
<translation id="5922853866070715753">Lähes valmis</translation>
@@ -956,6 +975,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Haluatko käyttää kortteja kaikilla laitteillasi?</translation>
<translation id="6059925163896151826">USB-laitteet</translation>
+<translation id="6060009363608157444">Virheellinen DnsOverHttps-tila</translation>
<translation id="6080696365213338172">Käytät sisältöä järjestelmänvalvojan myöntämällä varmenteella. Järjestelmänvalvoja voi käyttää verkkotunnukselle <ph name="DOMAIN" /> lähettämiäsi tietoja.</translation>
<translation id="6094273045989040137">Tee merkintä</translation>
<translation id="610911394827799129">Google-tililläsi voi olla muita selaushistoriatietoja osoitteessa <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1004,13 +1024,12 @@
<translation id="6404511346730675251">Muokkaa kirjanmerkkiä</translation>
<translation id="6406765186087300643">C0 (kirjekuori)</translation>
<translation id="6410264514553301377">Anna kortin <ph name="CREDIT_CARD" /> vanhentumispäivä ja CVC</translation>
-<translation id="6414888972213066896">Pyysit vanhemmiltasi lupaa käydä tällä sivustolla.</translation>
<translation id="6415778972515849510">Chromium voi auttaa suojaamaan Google-tiliäsi ja vaihtamaan salasanasi.</translation>
-<translation id="6417515091412812850">Ei voida tarkistaa, onko varmenne kumottu.</translation>
<translation id="6431585503458005759">Älä tallenna</translation>
<translation id="6433490469411711332">Muokkaa yhteystietoja</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> kieltäytyi muodostamasta yhteyttä.</translation>
<translation id="6434309073475700221">Hylkää</translation>
+<translation id="6435221585574090192">Jaa järjestelmänvalvojalle dataa Chrome Enterprisen uhkientorjunnan merkitsemistä tietoturvatapahtumista. Dataan voi sisältyä sivujen URL-osoitteita, tiedostojen nimiä ja sisällönkuvaustietoja, laitteesi käyttäjänimi ja Chromen käyttäjänimi.</translation>
<translation id="6440503408713884761">Ohitettu</translation>
<translation id="6446163441502663861">Kahu (kirjekuori)</translation>
<translation id="6446608382365791566">Lisää tietoja</translation>
@@ -1019,20 +1038,19 @@
<translation id="6465306955648956876">Hallinnoi salasanoja…</translation>
<translation id="647261751007945333">Laitekäytännöt</translation>
<translation id="6476284679642588870">Ylläpidä maksutapoja</translation>
-<translation id="6477321094435799029">Chrome havaitsi tällä sivulla epätavallista koodia ja esti sen suojellakseen henkilötietojasi (esimerkiksi salasanoja, puhelinnumeroita tai luottokorttitietoja).</translation>
<translation id="6489534406876378309">Aloita kaatumistietojen lähettäminen</translation>
<translation id="6499038740797743453">Vaihdetaanko salasana?</translation>
<translation id="6507833130742554667">Luotto- ja maksukortit hyväksytään.</translation>
<translation id="650855688985305916">Kyllä, tallenna</translation>
<translation id="6508722015517270189">Käynnistä Chrome uudelleen.</translation>
<translation id="6517596291481585650">Varoitus: tätä käytäntöä ei yhdistetty käytännössä kuvatulla tavalla luettelona, sillä se ei ole luettelo.</translation>
+<translation id="6518133107902771759">Vahvista</translation>
<translation id="6521745193039995384">Ei aktiivinen</translation>
<translation id="6529602333819889595">&amp;Toista poisto</translation>
<translation id="6534179046333460208">Fyysisen webin ehdotukset</translation>
<translation id="6545864417968258051">Bluetooth-haku</translation>
<translation id="6554795675067793129">Tätä tiliä ylläpitää <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Tee uudelleen</translation>
-<translation id="6563469144985748109">Ylläpitäjä ei ole hyväksynyt sitä vielä.</translation>
<translation id="6569060085658103619">Tämä on laajennussivu.</translation>
<translation id="6578796323535178455">C2 (kirjekuori)</translation>
<translation id="6579990219486187401">Vaaleanpinkki</translation>
@@ -1050,11 +1068,13 @@
<translation id="6643016212128521049">Tyhjennä</translation>
<translation id="6644283850729428850">Tämä käytäntö on vanhentunut.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Ei mitään}=1{1 sivustolta (sinua ei kirjata ulos Google-tililtäsi)}other{# sivustolta (sinua ei kirjata ulos Google-tililtäsi)}}</translation>
+<translation id="6652101503459149953">Käytä Windows Hellota</translation>
<translation id="6657585470893396449">Salasana</translation>
<translation id="6670613747977017428">Takaisin turvaan</translation>
<translation id="6671697161687535275">Poistetaanko lomake-ehdotus Chromiumista?</translation>
<translation id="6685834062052613830">Kirjaudu ulos ja suorita määritys loppuun.</translation>
<translation id="6689271823431384964">Chrome tarjoaa korttien tallentamista Google-tilillesi, koska olet kirjautuneena sisään. Voit muuttaa tätä koska tahansa asetuksista. Kortinhaltijan nimi on peräisin tililtäsi.</translation>
+<translation id="6707256370811247129">Tarkista välimuistin ja Chromessa lataamiesi tai lähettämiesi tiedostojen sisältö.</translation>
<translation id="6710213216561001401">Edellinen</translation>
<translation id="6710594484020273272">&lt;Anna hakukysely&gt;</translation>
<translation id="671076103358959139">Käyttöönottotunnus:</translation>
@@ -1062,10 +1082,10 @@
<translation id="6738516213925468394">Datasi salattiin <ph name="BEGIN_LINK" />synkronoinnin tunnuslauseella<ph name="END_LINK" /> <ph name="TIME" />. Aloita synkronointi antamalla tunnuslause.</translation>
<translation id="674375294223700098">Tuntematon palvelimen varmennevirhe.</translation>
<translation id="6744009308914054259">Voit lukea artikkeleita offline-tilassa Lataukset-kohdassa, kun odotat yhteyden muodostamista.</translation>
+<translation id="6747611005629681221">Varoitus: Käytöstä poistettuja ominaisuuksia</translation>
<translation id="6753269504797312559">Käytännön arvo</translation>
<translation id="6757797048963528358">Laitteesi siirtyi virransäästötilaan.</translation>
<translation id="6768213884286397650">Hagaki (postikortti)</translation>
-<translation id="6778737459546443941">Vanhempasi ei ole hyväksynyt sitä vielä.</translation>
<translation id="67862343314499040">Lila</translation>
<translation id="6786747875388722282">Laajennukset</translation>
<translation id="6790428901817661496">Toista</translation>
@@ -1073,6 +1093,7 @@
<translation id="681021252041861472">Pakollinen kenttä</translation>
<translation id="6810899417690483278">Muokkaustunnus</translation>
<translation id="6825578344716086703"><ph name="DOMAIN" />-palvelin, johon yritit muodostaa yhteyden, esitti heikkoa allekirjoitusalgoritmia käyttävän varmenteen (esim. SHA-1). Tästä syystä palvelimen esittämät tunnistetiedot saattavat olla väärennettyjä. Palvelin ei siis välttämättä ole tavoittelemasi palvelin, vaan saatat viestiä hakkerin kanssa.</translation>
+<translation id="6826370046007623921">Tietojen menetyksen esto</translation>
<translation id="6831043979455480757">Käännä</translation>
<translation id="6839929833149231406">Alue</translation>
<translation id="6852204201400771460">Ladataanko sovellus uudelleen?</translation>
@@ -1085,7 +1106,6 @@
<translation id="6891596781022320156">Käytännön tasoa ei tueta.</translation>
<translation id="6895330447102777224">Korttisi vahvistettiin.</translation>
<translation id="6897140037006041989">User agent</translation>
-<translation id="6903319715792422884">Auta kehittämään Selaussuojaa lähettämällä <ph name="BEGIN_WHITEPAPER_LINK" />järjestelmätietoja ja sivujen sisältöä<ph name="END_WHITEPAPER_LINK" /> Googlelle. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Käyttäjä:</translation>
<translation id="6934672428414710184">Tämä nimi on peräisin Google-tililtäsi</translation>
<translation id="6944692733090228304">Kirjoitit salasanan sivustolle, jota <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ei ylläpidä. Älä käytä samaa salasanaa muissa sovelluksissa tai muilla sivustoilla tilisi turvallisuuden vuoksi.</translation>
@@ -1130,6 +1150,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> ja <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> toinen}other{<ph name="PAYMENT_METHOD_PREVIEW" /> ja <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> muuta}}</translation>
<translation id="7153618581592392745">Laventeli</translation>
<translation id="717330890047184534">Gaia-tunnus:</translation>
+<translation id="7174545416324379297">Yhdistetty</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ja <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> toinen}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ja <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> muuta}}</translation>
<translation id="7177397715882417099">Kohdepalvelin <ph name="ORIGIN" /> pyytää
tietosuojakäytännön soveltamista kaikkiin sen saamiin pyyntöihin. Käytännön näyttämisen sijaan se ohjaa selaimen muualle,
@@ -1167,6 +1188,7 @@ Lisätietoja:
<translation id="7320336641823683070">Yhteysohjeet</translation>
<translation id="733354035281974745">Laitteen paikallisen tilin ohitus</translation>
<translation id="7334320624316649418">&amp;Toista uudelleenjärjestely</translation>
+<translation id="7337706099755338005">Ei saatavilla käyttöympäristössäsi</translation>
<translation id="733923710415886693">Palvelimen varmenteesta ei ole saatu Certificate Transparencyn vaatimia tietoja.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">On yhdistetty:</translation>
@@ -1198,7 +1220,6 @@ Lisätietoja:
<translation id="7440140511386898319">Tutki offline-tilassa</translation>
<translation id="7441627299479586546">Väärä käytännön aihe</translation>
<translation id="7442725080345379071">Vaaleanoranssi</translation>
-<translation id="7444046173054089907">Tämä sivusto on estetty</translation>
<translation id="7445762425076701745">Palvelimen, johon olet muodostanut yhteyden, identiteettiä ei voi täysin todentaa. Tietokoneesi on yhdistetty palvelimeen sellaisen nimen avulla, joka on kelvollinen vain verkkosi sisällä ja jonka omistajaa ulkopuolinen varmenteen myöntäjä ei pysty todentamaan. Koska jotkin varmenteen myöntäjät kuitenkin myöntävät varmenteita tällaisille nimille, et voi varmistaa, että olet muodostanut yhteyden haluamaasi verkkosivustoon etkä hakkeriin.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />tiedonhakua<ph name="END_LINK" /> ongelmaan liittyen</translation>
<translation id="7455133967321480974">Käytä yleistä oletusasetusta (estä)</translation>
@@ -1220,9 +1241,9 @@ Lisätietoja:
<translation id="7538364083937897561">A2 (kirjekuori)</translation>
<translation id="7542403920425041731">Vahvistamisen jälkeen korttisi tiedot jaetaan sivuston kanssa.</translation>
<translation id="7542995811387359312">Automaattinen luottokortin tietojen täyttäminen on poistettu käytöstä, koska tämä lomake ei käytä suojattua yhteyttä.</translation>
-<translation id="7543525346216957623">Pyydä lupaa vanhemmalta</translation>
<translation id="7548892272833184391">Yhteysvirheiden korjaaminen</translation>
<translation id="7549584377607005141">Tämän sivun näyttäminen oikein edellyttää aiemmin lähetettyjä tietoja. Voit lähettää tiedot uudelleen, mutta tällöin sivulla mahdollisesti suoritettu toiminto toistetaan.</translation>
+<translation id="7550637293666041147">Käyttäjänimi laitteella ja käyttäjänimi Chromessa</translation>
<translation id="7552846755917812628">Kokeile seuraavia keinoja:</translation>
<translation id="7554791636758816595">Uusi välilehti</translation>
<translation id="7564049878696755256">Saatat menettää <ph name="ORG_NAME" />-tilisi käyttöoikeuden tai joutua identiteettivarkauden uhriksi. Chrome suosittelee salasanan vaihtamista välittömästi.</translation>
@@ -1237,6 +1258,7 @@ Lisätietoja:
<translation id="7610193165460212391">Arvo on alueen ulkopuolella (<ph name="VALUE" />).</translation>
<translation id="7613889955535752492">Vanhenee: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Tietojasi on jo salattu Google-tilisi salasanan muulla versiolla. Syötä salasana alla.</translation>
+<translation id="7625784245512586808">Chrome Enterprisen uhkientorjunta</translation>
<translation id="7633909222644580952">Tehokkuusdata ja virheraportit</translation>
<translation id="7637571805876720304">Poistetaanko luottokortti Chromiumista?</translation>
<translation id="7638605456503525968">Sarjaportit</translation>
@@ -1249,7 +1271,6 @@ Lisätietoja:
<translation id="7668654391829183341">Tuntematon laite</translation>
<translation id="7669271284792375604">Tämän sivuston hyökkääjät saattavat yrittää huijata sinua asentamaan ohjelmia, jotka ovat haitallisia selauskokemuksellesi (esimerkiksi vaihtamalla aloitussivusi tai näyttämällä ylimääräisiä mainoksia käymilläsi sivustoilla).</translation>
<translation id="7676643023259824263">Hae leikepöydän tekstiä <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Alusta ja pilvipalvelu</translation>
<translation id="7681101578153515023">Vaihda hakukonetta</translation>
<translation id="7682287625158474539">Toimitus</translation>
<translation id="7687186412095877299">Täyttää tallennetut maksutapasi maksulomakkeisiin</translation>
@@ -1264,7 +1285,6 @@ Lisätietoja:
<translation id="7723047071702270851">Muokkaa korttia</translation>
<translation id="774634243536837715">Vaarallinen sisältö estetty</translation>
<translation id="7752995774971033316">Ei hallinnoida</translation>
-<translation id="7755287808199759310">Vanhempasi voi kumota eston puolestasi.</translation>
<translation id="7757555340166475417">Dai Pa Kai (275 mm x 395 mm)</translation>
<translation id="7758069387465995638">Palomuuri tai virustorjuntaohjelmisto on saattanut estää yhteyden.</translation>
<translation id="7759163816903619567">Näytä verkkotunnus:</translation>
@@ -1308,7 +1328,6 @@ Lisätietoja:
<translation id="8004582292198964060">Selain</translation>
<translation id="8009225694047762179">Salasanojen hallinta</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Tämä kortti ja sen laskutusosoite tallennetaan. Voit käyttää sitä sisäänkirjautuneena (<ph name="USER_EMAIL" />).}other{Nämä kortit ja niiden laskutusosoitteet tallennetaan. Voit käyttää niitä sisäänkirjautuneena (<ph name="USER_EMAIL" />).}}</translation>
-<translation id="8012647001091218357">Emme tavoittaneet vanhempiasi. Yritä uudelleen.</translation>
<translation id="8025119109950072390">Tälle sivustolle hyökännyt taho voi yrittää huijata sinua tekemään jotain vaarallista, kuten asentamaan ohjelmistoja tai paljastamaan henkilötietojasi (esimerkiksi salasanoja, puhelinnumeroita tai luottokorttitietoja).</translation>
<translation id="8034522405403831421">Sivu on kirjoitettu kielellä <ph name="SOURCE_LANGUAGE" />. Haluatko kääntää sen kielelle <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Kynä</translation>
@@ -1319,6 +1338,7 @@ Lisätietoja:
<translation id="8041940743680923270">Käytä yleistä oletusasetusta (kysy)</translation>
<translation id="8042918947222776840">Valitse noutotapa</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> on määritetty virheellisesti. Ongelma korjaantuu yleensä, jos <ph name="SOFTWARE_NAME" /> poistetaan. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Kortin turvakoodin lisääminen ei ole jatkossa enää tarpeen</translation>
<translation id="8066955247577885446">Jokin meni pieleen.</translation>
<translation id="8074253406171541171">10x13 (kirjekuori)</translation>
<translation id="8078141288243656252">Kierrettyyn asiakirjaan ei voi tehdä merkintöjä</translation>
@@ -1349,6 +1369,7 @@ Lisätietoja:
<translation id="8211406090763984747">Yhteys on turvallinen</translation>
<translation id="8218327578424803826">Määrätty sijainti:</translation>
<translation id="8220146938470311105">C7/C6 (kirjekuori)</translation>
+<translation id="8220639454292072926">Yrityksen raportointi</translation>
<translation id="8225771182978767009">Tämän tietokoneen määrittänyt henkilö on estänyt tämän sivuston.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Avaa sivu uudessa incognito-välilehdessä.</translation>
@@ -1403,24 +1424,24 @@ Lisätietoja:
<translation id="8508648098325802031">Hakukuvake</translation>
<translation id="8522552481199248698">Chrome voi auttaa suojaamaan Google-tiliäsi ja vaihtamaan salasanasi.</translation>
<translation id="8543181531796978784">Voit <ph name="BEGIN_ERROR_LINK" />ilmoittaa löytyneestä ongelmasta<ph name="END_ERROR_LINK" /> tai <ph name="BEGIN_LINK" />siirtyä mahdollisesti haitalliselle sivustolle<ph name="END_LINK" />, jos ymmärrät tietoturvariskit.</translation>
-<translation id="8543556556237226809">Onko sinulla kysyttävää? Ota yhteyttä profiiliasi valvovaan henkilöön.</translation>
<translation id="8553075262323480129">Käännös epäonnistui, sillä sivun kieltä ei voitu määrittää.</translation>
<translation id="8557066899867184262">CVC sijaitsee kortin takapuolella.</translation>
<translation id="8559762987265718583">Verkkotunnukseen <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> ei voi muodostaa salattua yhteyttä, koska laitteesi aika ja päivämäärä (<ph name="DATE_AND_TIME" />) ovat virheelliset.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> epäilyttävä sivusto</translation>
<translation id="8564985650692024650">Chromium suosittelee organisaation <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> salasanasi vaihtamista, jos olet käyttänyt sitä myös muilla sivustoilla.</translation>
<translation id="8571890674111243710">Käännetään sivua kielelle <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Lisää puh.nro
</translation>
-<translation id="859285277496340001">Varmenne ei määritä mekanismia, jonka avulla voitaisiin tarkistaa, onko varmenne kumottu.</translation>
<translation id="860043288473659153">Kortinhaltijan nimi</translation>
<translation id="861775596732816396">Koko 4</translation>
-<translation id="8620436878122366504">Vanhempasi eivät ole hyväksyneet sitä vielä.</translation>
<translation id="8622948367223941507">Laki-ekstra</translation>
<translation id="8625384913736129811">Tallenna kortti tälle laitteelle</translation>
<translation id="8626112503828625890">Tallennetaanko laskutustiedot Google-tilille?</translation>
+<translation id="8647750283161643317">Palauta kaikki oletusarvoon</translation>
<translation id="8663226718884576429">Tilauksen yhteenveto, <ph name="TOTAL_LABEL" />, lisätietoja</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, vastaus, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Saatavilla</translation>
<translation id="8703575177326907206">Yhteyttäsi verkkotunnukseen <ph name="DOMAIN" /> ei ole salattu.</translation>
<translation id="8718314106902482036">Maksua ei suoritettu loppuun</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, hakuehdotus</translation>
@@ -1431,6 +1452,7 @@ Lisätietoja:
<translation id="8738058698779197622">Kellosi täytyy asettaa oikeaan aikaan, jotta salattu yhteys voidaan muodostaa. Tämä johtuu siitä, että verkkosivustojen tunnistamisessa käytettävät varmenteet ovat voimassa vain tiettyinä ajanjaksoina. Chromium ei voi vahvistaa varmenteita, koska laitteesi kello on väärässä ajassa.</translation>
<translation id="8740359287975076522">Sivuston <ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS-osoitetta&lt;/abbr&gt; ei löydy. Ongelmaa diagnosoidaan.</translation>
<translation id="874846938927089722">Hyväksytyt luotto- ja prepaid-kortit</translation>
+<translation id="874918643257405732">Aseta tämä välilehti kirjanmerkiksi</translation>
<translation id="8759274551635299824">Tämä kortti on vanhentunut.</translation>
<translation id="8761567432415473239">Google-selaussuoja <ph name="BEGIN_LINK" />löysi hiljattain haitallisia ohjelmia<ph name="END_LINK" /> sivustolta <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB-laite</translation>
@@ -1460,6 +1482,7 @@ Lisätietoja:
<translation id="8938939909778640821">Hyväksytyt luotto- ja prepaid-kortit</translation>
<translation id="8943282376843390568">Lime</translation>
<translation id="8957210676456822347">Captive portal -valtuutus</translation>
+<translation id="8962950042226115166">Epäilyttävä sivusto</translation>
<translation id="8968766641738584599">Tallenna kortti</translation>
<translation id="8971063699422889582">Palvelimen varmenne on vanhentunut.</translation>
<translation id="8975012916872825179">Tallenna puhelinnumerot, sähköpostiosoitteet, toimitusosoitteet ja muita tietoja</translation>
@@ -1482,24 +1505,24 @@ Lisätietoja:
<translation id="9035022520814077154">Suojausvirhe</translation>
<translation id="9038649477754266430">Ennakointipalvelun avulla voit ladata sivuja nopeammin</translation>
<translation id="9039213469156557790">Tällä sivulla on kuitenkin muita osia, jotka eivät ole suojattuja. Muut voivat tarkastella näitä osia siirron aikana, ja hyökkääjä voi muuttaa sivun käyttäytymistä muokkaamalla näitä osia.</translation>
+<translation id="9044359186343685026">Käytä Touch ID:tä</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Yritit muodostaa yhteyden verkkotunnukseen <ph name="DOMAIN" />, mutta palvelin esitti virheellisen varmenteen.</translation>
<translation id="9050666287014529139">Tunnuslause</translation>
<translation id="9065203028668620118">Muokkaa</translation>
<translation id="9065745800631924235">Historiasta löydetty haku <ph name="TEXT" /></translation>
<translation id="9069693763241529744">Laajennuksen estämä</translation>
-<translation id="9076283476770535406">Se saattaa sisältää vain aikuisille tarkoitettua sisältöä.</translation>
<translation id="9076630408993835509">Yritys tai muu organisaatio ei ylläpidä selainta. Laitteen toimintaa saatetaan ylläpitää muualta kuin Chromesta käsin. <ph name="BEGIN_LINK" />Lue lisää<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Lisätietoja tarvitaan</translation>
<translation id="9080712759204168376">Tilauksen yhteenveto</translation>
<translation id="9089260154716455634">Ei-aktiivisen ajan käytäntö:</translation>
<translation id="9095388113577226029">Lisää kieliä…</translation>
+<translation id="9098981495403789647">Järjestelmänvalvoja on ottanut Chrome Enterprisen uhkientorjunnan käyttöön selaimellesi. Chrome Enterprisen uhkientorjunnalla on pääsy osaan datastasi.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> suojaa tietosi normaalisti salauksen avulla. Kun Chromium yritti tällä kertaa yhdistää sivustoon <ph name="SITE" />, sivusto palautti epätavalliset ja virheelliset kirjautumistiedot. Hyökkääjä saattaa yrittää esiintyä sivustona <ph name="SITE" />, tai Wi-Fi-kirjautumisruutu on keskeyttänyt yhteyden. Tietosi ovat edelleen turvassa, sillä Chromium katkaisi yhteyden, ennen kuin mitään tietoja vaihdettiin.</translation>
<translation id="9106062320799175032">Lisää laskutusosoite</translation>
<translation id="9114524666733003316">Vahvistetaan korttia…</translation>
<translation id="9128870381267983090">Yhdistä verkkoon</translation>
<translation id="9137013805542155359">Näytä alkuperäinen</translation>
-<translation id="9137248913990643158">Aloita ja kirjaudu sisään Chromeen ennen tämän sovelluksen käyttämistä.</translation>
<translation id="9141013498910525015">Ylläpidä osoitteita</translation>
<translation id="9148088599418889305">Valitse toimitustapa</translation>
<translation id="9148507642005240123">K&amp;umoa muokkaus</translation>
diff --git a/chromium/components/strings/components_strings_fil.xtb b/chromium/components/strings/components_strings_fil.xtb
index b9ba31695e7..94db7c77692 100644
--- a/chromium/components/strings/components_strings_fil.xtb
+++ b/chromium/components/strings/components_strings_fil.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Magdagdag ng Pangalan sa Card</translation>
<translation id="1089439967362294234">Palitan ang Password</translation>
+<translation id="1096545575934602868">Ang field na ito ay hindi dapat magkaroon ng higit sa <ph name="MAX_ITEMS_LIMIT" /> (na) entry. Madi-discard ang lahat ng karagdagang entry.</translation>
<translation id="109743633954054152">Pamahalaan ang mga password sa mga setting ng Chrome</translation>
<translation id="1103523840287552314">Palaging i-translate ang <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Kung lalagyan ng check, mag-iimbak ang Chrome ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Mag-access ng <ph name="BEGIN_LINK" />naka-cache na kopya<ph name="END_LINK" /> ng <ph name="URL" /></translation>
<translation id="1156303062776767266">Tumitingin ka ng lokal o nakabahaging file</translation>
<translation id="1158211211994409885">Pinutol ng <ph name="HOST_NAME" /> ang koneksyon nang hindi inaasahan.</translation>
+<translation id="115926840831309955">Tingnan ang iyong CVC at subukan ulit o i-update ang petsa ng pag-expire</translation>
<translation id="1161325031994447685">Muling kumonekta sa Wi-Fi</translation>
<translation id="1165039591588034296">Error</translation>
<translation id="1175364870820465910">&amp;I-print...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Pinipigilan ng software sa iyong computer na makakonekta nang ligtas ang Chrome sa web" (mga Windows computer lang)</translation>
<translation id="1294154142200295408">Mga variation ng command-line</translation>
<translation id="129553762522093515">Kamakailang isinara</translation>
+<translation id="1298536327547837046">Pag-scan ng Malware</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Subukang i-clear ang iyong cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Mga Hindi na Ginagamit na Feature</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Maghanap ng larawan sa clipboard</translation>
<translation id="1323433172918577554">Magpakita Nang Higit Pa</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">Naghihintay ng koneksyon…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">Mukhang peke ang site na sinubukan mong bisitahin. Kung minsan, ginagaya ng mga nang-aatake ang mga site sa pamamagitan ng paggawa ng mga pagbabago sa URL na maliit at mahirap makita.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Isinasaad ng page na ito na</translation>
<translation id="153384715582417236">'Yan na muna sa ngayon</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Masyadong malaki para i-annotate ang dokumento</translation>
-<translation id="1721312023322545264">Kailangan mo ng pahintulot mula kay <ph name="NAME" /> upang mabisita ang site na ito</translation>
<translation id="1721424275792716183">Kinakailangan ang field na may *</translation>
<translation id="1727741090716970331">Magdagdag ng Wastong Numero ng Card</translation>
<translation id="1728677426644403582">Pinagmulan ng isang web page ang tinitingnan mo</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Mga website na binibisita mo at oras na ginugugol dito</translation>
<translation id="1826516787628120939">Sinusuri</translation>
<translation id="1834321415901700177">Naglalaman ng mga mapanirang program ang site na ito</translation>
+<translation id="1838374766361614909">I-clear ang paghahanap</translation>
<translation id="1839551713262164453">Hindi na-validate ang mga value ng patakaran at may mga error</translation>
<translation id="1842969606798536927">Magbayad</translation>
<translation id="1871208020102129563">Nakatakda ang proxy upang gumamit ng mga hindi nababagong proxy server, hindi ng isang .pac script URL.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Tiklupin ang listahan</translation>
<translation id="1898423065542865115">Pagfi-filter</translation>
<translation id="1914326953223720820">I-unzip ang Serbisyo</translation>
+<translation id="1915697529809968049">Gamitin ang Touch ID sa halip na CVC?</translation>
<translation id="1916770123977586577">Upang ilapat ang iyong mga na-update na setting sa site na ito, i-reload ang page</translation>
<translation id="1919345977826869612">Mga Ad</translation>
<translation id="1919367280705858090">Humingi ng tulong sa partikular na mensahe ng error</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Mga Bookmark ng <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Error sa serialization</translation>
<translation id="1974060860693918893">Advanced</translation>
+<translation id="1974883374937189061">Tumulong na mapaigting ang seguridad ng Chrome sa pamamagitan ng pagpapadala ng mga <ph name="BEGIN_WHITEPAPER_LINK" />URL ng ilang page na binibisita mo, limitadong impormasyon ng system, at ilang content ng page<ph name="END_WHITEPAPER_LINK" /> sa Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Bersyon ng Firmware</translation>
<translation id="1981206234434200693">I-clear ang data ng history ng pag-browse sa Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{at 1 pa}one{at # pa}other{at # pa}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Maglagay ng wastong taon ng pag-expire</translation>
<translation id="2212735316055980242">Hindi nahanap ang patakaran</translation>
<translation id="2213606439339815911">Kinukuha ang mga entry...</translation>
+<translation id="2215727959747642672">Pag-edit ng file</translation>
<translation id="2218879909401188352">Ang mga umaatake na kasalukuyang nasa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ay maaaring mag-install ng mga mapanganib na app na makakapinsala sa iyong device, magdagdag ng mga hindi alam na singil sa mobile bill mo, o magnakaw ng iyong personal na impormasyon. <ph name="BEGIN_LEARN_MORE_LINK" />Matuto pa<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Walang internet</translation>
<translation id="2230458221926704099">Ayusin ang iyong koneksyon gamit ang <ph name="BEGIN_LINK" />diagnostics app<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Ipadala ngayon</translation>
+<translation id="2248949050832152960">Gamitin ang WebAuthn</translation>
<translation id="225207911366869382">Hindi na gimagamit ang halagang ito para sa patakarang ito.</translation>
<translation id="2257315177824333709">Paumanhin, hindi mase-save sa ngayon ang iyong card</translation>
<translation id="2262243747453050782">Error sa HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Di-wastong URL ng paghahanap.</translation>
<translation id="2482878487686419369">Mga Abiso</translation>
<translation id="248348093745724435">Mga patakaran sa machine</translation>
-<translation id="2485387744899240041">Mga username para sa iyong device at browser</translation>
<translation id="2491120439723279231">Naglalaman ng mga error ang certificate ng server.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Pang-parse ng JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Bumalik</translation>
<translation id="2503184589641749290">Mga tinatanggap na debit at prepaid card</translation>
<translation id="2505268675989099013">Protektahan ang Account</translation>
+<translation id="2515335152965840738">BALEWALAIN</translation>
<translation id="2515629240566999685">Suriin ang signal sa iyong lugar</translation>
<translation id="2523886232349826891">Ise-save sa device lang na ito</translation>
<translation id="2524461107774643265">Magdagdag ng Higit Pang Impormasyon</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Isumite</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Wala}=1{1 password (para sa <ph name="DOMAIN_LIST" />)}=2{2 password (para sa <ph name="DOMAIN_LIST" />)}one{# password (para sa <ph name="DOMAIN_LIST" />)}other{# na password (para sa <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Isara ang iba pang tab o app</translation>
-<translation id="267371737713284912">pindutin ang <ph name="MODIFIER_KEY_DESCRIPTION" /> para i-undo</translation>
<translation id="2674170444375937751">Sigurado ka bang nais mong tanggalin ang mga pahinang ito mula sa iyong history?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Umalis</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Hindi tumutugma ang format sa halaga.</translation>
<translation id="2705137772291741111">Hindi mabasa ang naka-save (naka-cache) na kopya ng site na ito.</translation>
<translation id="2709516037105925701">AutoFill</translation>
-<translation id="2712173769900027643">Humingi ng pahintulot</translation>
<translation id="2713444072780614174">Puti</translation>
<translation id="2720342946869265578">Malapit</translation>
<translation id="2721148159707890343">Matagumpay ang kahilingan</translation>
<translation id="2728127805433021124">Nilagdaan ang certificate ng server gamit ang mahinang algorithm ng lagda.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Magpatakbo ng Connectivity Diagnostics<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Sa pamamagitan ng pag-enable sa mga feature na ito, puwedeng mawala ang data sa iyong browser o
+ makompromiso ang seguridad o privacy mo. Nalalapat ang mga naka-enable na feature sa lahat
+ ng user ng browser na ito.</translation>
<translation id="2735043616039983645">Mayroong higit sa isang pinagmulan na may magkakasalungat na value para sa patakarang ito!</translation>
<translation id="2738330467931008676">Pumili ng Address sa Pag-pick up</translation>
<translation id="2740531572673183784">Ok</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Na-reset ang koneksyon.</translation>
<translation id="2788784517760473862">Mga tinatanggap na credit card</translation>
<translation id="2792012897584536778">Nag-set up ang mga administrator ng device na ito ng mga certificate ng seguridad na puwedeng magbigay-daan sa kanilang matingnan ang content ng mga website na binibisita mo.</translation>
-<translation id="2794233252405721443">Naka-block ang site</translation>
<translation id="2799020568854403057">Naglalaman ng mga mapaminsalang app ang pupuntahang site</translation>
<translation id="2799223571221894425">Ilunsad Muli</translation>
<translation id="2803306138276472711">Kamakailan lang, ang Google Safe Browsing ay <ph name="BEGIN_LINK" />nakakita ng malware<ph name="END_LINK" /> sa <ph name="SITE" />. Paminsan-minsan, nagkakaroon ng malware ang mga website na karaniwang ligtas.</translation>
+<translation id="2815364696811431560">UMALIS SA SITE</translation>
<translation id="2824775600643448204">Address bar at bar sa paghahanap</translation>
<translation id="2826760142808435982">Ine-encrypt at pinapatotoo ang koneksyon gamit ang <ph name="CIPHER" /> at ginagamit ang <ph name="KX" /> bilang key exchange mechanism.</translation>
<translation id="2835170189407361413">I-clear ang form</translation>
<translation id="2847118875340931228">Magbukas ng Incognito Window</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Kailangan mo ng pahintulot upang mabisita ang site na ito</translation>
<translation id="2856444702002559011">Maaaring sinusubukang nakawin ng mga attacker ang iyong impormasyon mula sa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (halimbawa, mga password, mensahe, o credit card). <ph name="BEGIN_LEARN_MORE_LINK" />Matuto pa<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">I-save ang card?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Kung naka-enable, mag-iimbak ang Chromium ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
<translation id="2985398929374701810">Maglagay ng wastong address</translation>
<translation id="2986368408720340940">Hindi available ang pamamaraan ng pag-pick up na ito. Sumubok ng ibang pamamaraan.</translation>
+<translation id="2987034854559945715">Walang tumutugmang feature</translation>
<translation id="2991174974383378012">Pagbabahagi sa Mga Website</translation>
<translation id="2991571918955627853">Hindi mo maaaring bisitahin ang <ph name="SITE" /> sa ngayon dahil gumagamit ng HSTS ang website. Karaniwang pansamantala lang ang mga error at pag-atake sa network, kaya malamang na gagana ang page na ito sa ibang pagkakataon.</translation>
<translation id="3005723025932146533">Ipakita ang naka-save na kopya</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Maling uri ng patakaran</translation>
<translation id="3037605927509011580">Ay, Naku!</translation>
<translation id="3041612393474885105">Impormasyon sa Certificate</translation>
+<translation id="3057676462092457419">Ang DnsOverHttps mode <ph name="SECURE_DNS_MODE_SECURE" /> ay hindi pa sinusuportahan, itinakda sa <ph name="SECURE_DNS_MODE_OFF" /> ang mode.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Serbisyo sa Pag-patch</translation>
<translation id="3064966200440839136">Aalis sa incognito mode upang magbayad sa pamamagitan ng external na application. Magpatuloy?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> sa <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Kanselahin ang Pagbabayad</translation>
<translation id="3207960819495026254">Naka-bookmark</translation>
+<translation id="3209034400446768650">Puwedeng maningil ang page</translation>
<translation id="3225919329040284222">Nagpakita ang server ng certificate na hindi tumutugma sa mga built-in na inaasahan. Ang mga inaasahang ito ay isinama para sa ilang partikular na website na may mataas na antas ng seguridad upang maprotektahan ka.</translation>
<translation id="3226128629678568754">Pindutin ang button na i-reload upang isumiteng muli ang data na kailangan upang ma-load ang pahina.</translation>
<translation id="3227137524299004712">Mikropono</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Impormasyon ng bersyon tungkol sa iyong device at browser</translation>
<translation id="323107829343500871">Ilagay ang iyong CVC para sa <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Palaging tukuyin ang mahalagang content sa site na ito</translation>
-<translation id="3254409185687681395">I-bookmark ang page na ito</translation>
<translation id="3270847123878663523">&amp;I-undo ang Pagbabago sa Ayos</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Magdagdag ng pangalan sa card</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Magdagdag ng billing address</translation>
<translation id="3324983252691184275">Crimson</translation>
<translation id="3338095232262050444">Secure</translation>
-<translation id="3345135638360864351">Hindi maipadala kay <ph name="NAME" /> ang iyong kahilingang i-access ang site na ito. Pakisubukang muli.</translation>
<translation id="3355823806454867987">Baguhin ang mga setting ng proxy...</translation>
<translation id="3361596688432910856"><ph name="BEGIN_EMPHASIS" />Hindi ise-save<ph name="END_EMPHASIS" /> ng Chrome ang sumusunod na impormasyon:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Itago ang advanced</translation>
<translation id="3467763166455606212">Kinakailangan ang pangalan ng cardholder</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, kasalukuyang nakabukas, pindutin ang Tab at pagkatapos ay ang Enter para lumipat sa nakabukas na tab</translation>
-<translation id="3479539252931486093">Hindi mo ba ito inaasahan? <ph name="BEGIN_LINK" />Ipaalam sa amin<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Hindi ngayon</translation>
<translation id="3484560055331845446">Maaari kang mawalan ng access sa iyong Google Account. Inirerekomenda ng Chrome na palitan na ang iyong password. Hihilingin sa iyong mag-sign in.</translation>
<translation id="3495081129428749620">Hanapin sa page
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Hindi namin makaugnayan ang iyong magulang sa sandaling ito. Pakisubukang muli.</translation>
<translation id="3512163584740124171">Binabalewala ang patakarang ito dahil may isa pang patakaran mula sa parehong pangkat ng patakaran na may mas mataas na priyoridad.</translation>
<translation id="3528171143076753409">Hindi pinagkakatiwalaan ang certificate ng server.</translation>
<translation id="3528485271872257980">Dark Brown</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Hindi bababa sa 1 item sa mga naka-sync na device}=1{1 item (at higit pa sa mga naka-sync na device)}one{# item (at higit pa sa mga naka-sync na device)}other{# na item (at higit pa sa mga naka-sync na device)}}</translation>
<translation id="3539171420378717834">Magtago ng kopya ng card na ito sa device na ito</translation>
-<translation id="3556433843310711081">Maaari itong i-unblock ng iyong manager para sa iyo</translation>
<translation id="3566021033012934673">Hindi pribado ang iyong koneksyon</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Isinasaad ng naka-embed na page sa <ph name="SITE" /> na</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Buksan ang page sa bagong Incognito window (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Nakuha ang ulat ng pag-crash noong <ph name="CRASH_TIME" />, na-upload noong <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Impormasyon sa certificate</translation>
+<translation id="3701427423622901115">Tinanggap ang pag-reset.</translation>
<translation id="3704162925118123524">Ang network na ginagamit mo ay maaaring humiling sa iyo na bisitahin ang page ng pag-login nito.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Naglo-load...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Maaaring linlangin ka ng mga attacker sa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> na gawin ang isang mapanganib na bagay tulad ng pag-install ng software o paghayag ng iyong personal na impormasyon (halimbawa, mga password, numero ng telepono, o credit card). <ph name="BEGIN_LEARN_MORE_LINK" />Matuto pa<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Nabigo ang translation dahil sa error sa server.</translation>
<translation id="3759461132968374835">Wala kang kamakailang iniulat na mga pag-crash. Hindi lilitaw dito ang mga pag-crash na naganap kapag hindi pinagana ang pag-uulat ng pag-crash.</translation>
+<translation id="3760561303380396507">Gamitin ang Windows Hello sa halip na CVC?</translation>
<translation id="3761718714832595332">Itago ang status</translation>
<translation id="3765032636089507299">Kasalukuyang ginagawa ang Ligtas na Pag-browse.</translation>
<translation id="3778403066972421603">Gusto mo bang i-save ang card na ito sa iyong Google Account at sa device na ito?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Laki 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Na-block ang mapaminsalang content.</translation>
+<translation id="3808375843007691220">Babala: May mga kasunod na pang-eksperimentong feature!</translation>
<translation id="3810973564298564668">Mamahala</translation>
<translation id="382518646247711829">Kung gumagamit ka ng proxy server...</translation>
<translation id="3828924085048779000">Hindi pinapayagan ang walang laman na passphrase.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">I-update ang petsa at oras</translation>
<translation id="3884278016824448484">Sumasalungat na tagatukoy ng device</translation>
<translation id="3885155851504623709">Parish</translation>
-<translation id="3886446263141354045">Ipinadala ang iyong kahilingang i-access ang site na ito kay <ph name="NAME" /></translation>
<translation id="3890664840433101773">Magdagdag ng email</translation>
<translation id="3901925938762663762">Na-expire na ang card</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Gamitin ang WebAuthn sa halip na CVC?</translation>
<translation id="3946209740501886391">Palaging hilingin sa site na ito</translation>
<translation id="3949571496842715403">Hindi mapatunayan ng server na ito na <ph name="DOMAIN" /> ito; hindi tinutukoy ng certificate ng seguridad nito ang Mga Alternatibong Pangalan ng Subject. Maaaring dahil ito sa isang maling configuration o sa isang umaatake na humahadlang sa iyong koneksyon.</translation>
<translation id="3949601375789751990">Lalabas dito ang iyong history ng pag-browse</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Wala}=1{Mula sa 1 site }one{Mula sa # site }other{Mula sa # na site }}</translation>
<translation id="397105322502079400">Kinakalkula...</translation>
<translation id="3973234410852337861">Naka-block ang <ph name="HOST_NAME" /></translation>
+<translation id="3981540111851280311">Na-enable ng <ph name="ENROLLMENT_DOMAIN" /> ang Proteksyon Laban sa Banta ng Chrome Enterprise sa iyong browser. May access ang Proteksyon Laban sa Banta ng Chrome Enterprise sa ilan sa iyong data.</translation>
<translation id="3987940399970879459">Wala pang 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 web page ang malapit}one{# web page ang malapit}other{# na web page ang malapit}}</translation>
<translation id="4030383055268325496">&amp;I-undo ang pagdagdag</translation>
<translation id="4032320456957708163">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang iyong browser</translation>
-<translation id="4034375457890803692">Napupunta ang link na binuksan mo sa isang site na hindi mo karaniwang binibisita. Maaaring sinusubukan ka nitong lituhin.</translation>
<translation id="4058922952496707368">Key "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Magdagdag ng Wastong Address</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Di-wasto ang serial number ng device</translation>
<translation id="410351446219883937">I-autoplay</translation>
<translation id="4103763322291513355">Bisitahin ang &lt;strong&gt;chrome://policy&lt;/strong&gt; upang makita ang listahan ng mga naka-blacklist na URL at iba pang mga patakaran na ipinapatupad ng iyong system administrator.</translation>
+<translation id="4108231218301530806">Gamitin ang fingerprint para i-verify ang card na ito sa susunod.</translation>
<translation id="4110652170750985508">Suriin ang iyong pagbabayad</translation>
<translation id="4112140312785995938">Mag-seek Pabalik</translation>
<translation id="4116663294526079822">Palaging payagan sa site na ito</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Hindi wasto ang signature sa pag-verify</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> pang item}one{<ph name="ITEM_COUNT" /> pang item}other{<ph name="ITEM_COUNT" /> pang item}}</translation>
+<translation id="4176463684765177261">Hindi pinapaganana</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Para mas mabilis na makapagbayad sa susunod, idagdag ang iyong card at billing address sa Google Account mo.</translation>
<translation id="4196861286325780578">&amp;Gawing muli ang paglilipat</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">I-reset ang password</translation>
<translation id="4279811152705618813">Ang iyong <ph name="DEVICE_TYPE" /> ay pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Na-save na ang card na ito sa iyong Google Account}one{Na-save na ang mga card na ito sa iyong Google Account}other{Na-save na ang mga card na ito sa iyong Google Account}}</translation>
+<translation id="428847186335018806">I-scan ang mga file na dina-download o ina-upload mo sa Chrome.</translation>
<translation id="42981349822642051">Palawakin</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Lumipat</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Hindi pinagana ang paggamit ng isang proxy ngunit tinutukoy ang isang tahasang configuration ng proxy.</translation>
<translation id="445100540951337728">Mga tinatanggap na debit card</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> kahina-hinalang gawi</translation>
<translation id="4466881336512663640">Mawawala ang mga pagbabago sa form. Sigurado ka bang gusto mong magpatuloy?</translation>
<translation id="4477350412780666475">Susunod na Track</translation>
<translation id="4482953324121162758">Hindi ita-translate ang site na ito.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;I-undo ang Pagtanggal</translation>
<translation id="4597348597567598915">Laki 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Mga feature sa paghahanap</translation>
<translation id="4646534391647090355">Dalhin na ako roon</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Hindi mapatunayan ng server na ito na ito ay <ph name="DOMAIN" />; naglalaman ng mga error ang certificate ng seguridad nito. Maaaring dulot ito ng maling configuration o isang umaatake na hinahadlangan ang iyong koneksyon.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Naputol ang iyong koneksyon</translation>
-<translation id="471880041731876836">Wala kang pahintulot na bisitahin ang site na ito</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Magpatakbo ng Windows Network Diagnostics<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">I-reload ang mga patakaran</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Pagkasyahin sa pahina</translation>
<translation id="4850886885716139402">View</translation>
<translation id="4854362297993841467">Hindi available ang pamamaraan ng paghahatid na ito. Sumubok ng ibang pamamaraan.</translation>
-<translation id="4858792381671956233">Tinanong mo sa iyong mga magulang kung maaari mong bisitahin ang site na ito</translation>
<translation id="4864052566555297930">Tip para sa kaligtasan:</translation>
<translation id="4876188919622883022">Pinasimpleng view</translation>
<translation id="4876305945144899064">Walang username</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Muling i-enable ang mga babala</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Tingnan lahat</translation>
+<translation id="4989542687859782284">Hindi Available</translation>
<translation id="4989809363548539747">Hindi sinusuportahan ang plugin na ito</translation>
+<translation id="4995216769782533993">Kumpirmahin ang panseguridad na code para ibahagi ang mga detalye ng iyong card sa site na ito</translation>
<translation id="5002932099480077015">Kung naka-enable, mag-iimbak ang Chrome ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
<translation id="5015510746216210676">Pangalan ng Machine:</translation>
<translation id="5017554619425969104">Text na kinopya mo</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">I-verify ang iyong card</translation>
<translation id="5135404736266831032">Pamahalaan ang mga address...</translation>
<translation id="5138227688689900538">Magpakita ng mas kaunti</translation>
<translation id="5141240743006678641">I-encrypt ang mga naka-sync na password gamit ang iyong mga kredensyal sa Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Ang makakapagtakda lang ng mga feature na nalalapat sa buong system ay ang may-ari: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Babala: Hindi na-merge ang patakarang ito bilang tinukoy sa patakarang PolicyDictionaryMultipleSourceMergeList dahil hindi ito bahagi ng mga patakaran ng diksyunaryo na puwedeng i-merge.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Tapusin</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Nabigo i-load ang mga setting ng patakaran sa store</translation>
<translation id="5371425731340848620">I-update ang card</translation>
<translation id="5377026284221673050">"Nahuhuli ang iyong orasan" o "Nauuna ang iyong orasan" o "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Puwedeng subukang ng page na ito na linlangin ka, magnakaw ng personal na impormasyon, o magdulot ng pinsala sa iyong device. Mag-ingat kapag naglalagay ng personal na impormasyon o nagbubukas ng mga na-download na file.</translation>
<translation id="5384855140246857529">Para magamit ang iyong mga card sa lahat ng device, mag-sign in at i-on ang pag-sync.</translation>
<translation id="5386426401304769735">Naglalaman ang chain ng certificate para sa site na ito ng certificate na naka-sign gamit ang SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Di-wasto</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> pa}one{<ph name="CONTACT_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> pa}other{<ph name="CONTACT_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> pa}}</translation>
<translation id="5470861586879999274">&amp;Gawing muli ang pag-e-edit</translation>
+<translation id="5473728911100096288">Sa pamamagitan ng pag-enable sa mga feature na ito, gagamit ka ng mga hindi na ginagamit na feature
+ na mawawala sa mga bersyon sa hinaharap.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Maaaring subukan ng content na ito na mag-install ng mapanganib na software sa iyong device na magnanakaw o magde-delete ng impormasyon mo. <ph name="BEGIN_LINK" />Ipakita pa rin<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Magdagdag ng wastong address</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Protektahan ang account</translation>
<translation id="5571083550517324815">Hindi maaaring mag-pick up mula sa address na ito. Pumili ng ibang address.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 ang ginagamit}one{# ang ginagamit}other{# ang ginagamit}})</translation>
-<translation id="5572851009514199876">Magsimula at mag-sign in sa Chrome upang masuri ng Chrome kung pinapayagan kang i-access ang site na ito.</translation>
<translation id="5580958916614886209">Tingnan ang iyong buwan ng pag-expire at subukang muli</translation>
<translation id="5586446728396275693">Walang naka-save na address</translation>
<translation id="5595485650161345191">Mag-edit ng address</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Hindi sinusuportahan ang pamamahala</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Puwedeng maging peke o mapanloko ang site na ito. Inirerekomenda ng Chrome na umalis ngayon.</translation>
<translation id="5610142619324316209">Suriin ang koneksyon</translation>
<translation id="5610807607761827392">Maaari mong pamahalaan ang mga card at address sa <ph name="BEGIN_LINK" />Mga Setting<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Masyadong maraming beses kang na-redirect ng <ph name="HOST_NAME" />.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Kasalukuyang user</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Inirerekomenda ng Chrome na i-reset ang iyong password kung ginamit mo ito sa iba pang site.</translation>
-<translation id="5732392974455271431">Maaari itong i-unblock ng iyong mga magulang para sa iyo</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{I-save ang card sa iyong Google Account}one{I-save ang mga card sa iyong Google Account}other{I-save ang mga card sa iyong Google Account}}</translation>
<translation id="5763042198335101085">Maglagay ng wastong email address</translation>
<translation id="5765072501007116331">Upang makita ang mga pamamaraan at kinakailangan sa paghahatid, pumili ng address</translation>
<translation id="5778550464785688721">Ganap na pagkontrol sa mga MIDI device</translation>
+<translation id="5781136890105823427">Naka-enable ang eksperimento</translation>
<translation id="578305955206182703">Amber</translation>
<translation id="57838592816432529">I-mute</translation>
<translation id="5784606427469807560">Nagkaroon ng problema sa pagkumpirma ng iyong card. Suriin ang koneksyon sa internet at subukang muli.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Naka-off</translation>
<translation id="5863847714970149516">Maaari kang singilin sa susunod na page</translation>
<translation id="5866257070973731571">Magdagdag ng Numero ng Telepono</translation>
+<translation id="5866898949289125849">Isang page ng mga tool ng developer ang tinitingnan mo</translation>
<translation id="5869405914158311789">Hindi makakonekta sa site na ito</translation>
<translation id="5869522115854928033">Mga naka-save na password</translation>
<translation id="5887400589839399685">Na-save ang card</translation>
<translation id="5893752035575986141">Tinatanggap ang mga credit card.</translation>
+<translation id="5895138241574237353">I-restart</translation>
<translation id="5901630391730855834">Dilaw</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (naka-sync)</translation>
<translation id="5916664084637901428">Naka-on</translation>
+<translation id="59174027418879706">Pinagana</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">I-save ang card sa Google Account?</translation>
<translation id="5922853866070715753">Malapit nang matapos</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Gamitin ang iyong mga card sa lahat ng device mo?</translation>
<translation id="6059925163896151826">Mga USB device</translation>
+<translation id="6060009363608157444">Invalid ang DnsOverHttps mode.</translation>
<translation id="6080696365213338172">Nag-access ka ng nilalaman gamit ang isang certificate na ibinigay ng administrator. Maaaring harangin ng iyong administrator ang data na ibibigay mo sa <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">I-annotate</translation>
<translation id="610911394827799129">Maaaring may iba pang anyo ng history ng pag-browse ang iyong Google Account sa <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">I-edit ang bookmark</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Ilagay ang petsa ng pag-expire at CVC para sa <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Tinanong mo ang iyong magulang kung maaari mong bisitahin ang site na ito</translation>
<translation id="6415778972515849510">Makakatulong sa iyo ang Chromium na protektahan ang iyong Google Account at palitan ang password mo.</translation>
-<translation id="6417515091412812850">Hindi nagawang masuri kung nabawi na ang certificate.</translation>
<translation id="6431585503458005759">Huwag mag-store</translation>
<translation id="6433490469411711332">I-edit ang impormasyon sa pakikipag-ugnayan</translation>
<translation id="6433595998831338502">Tumangging kumonekta ang <ph name="HOST_NAME" />.</translation>
<translation id="6434309073475700221">Itapon</translation>
+<translation id="6435221585574090192">Ibahagi ang data tungkol sa mga pangyayari sa seguridad na na-flag ng Proteksyon Laban sa Banta ng Chrome Enterprise sa iyong Administrator. Puwedeng kasama sa mga ito ang mga url ng page, pangalan ng file, at metadata ng file, username ng iyong device at username sa Chrome.</translation>
<translation id="6440503408713884761">Binalewala</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Magdagdag ng higit pang impormasyon</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Pamahalaan ang mga password...</translation>
<translation id="647261751007945333">Mga patakaran sa device</translation>
<translation id="6476284679642588870">Pamahalaan ang mga paraan ng pagbabayad</translation>
-<translation id="6477321094435799029">May natukoy na kakaibang code ang Chrome sa page na ito at na-block ito upang protektahan ang iyong personal na impormasyon (halimbawa, mga password, numero ng telepono at credit card).</translation>
<translation id="6489534406876378309">Simulang mag-upload ng mga pag-crash</translation>
<translation id="6499038740797743453">I-reset ang password?</translation>
<translation id="6507833130742554667">Tinatanggap ang mga credit at debit card.</translation>
<translation id="650855688985305916">Oo, i-store</translation>
<translation id="6508722015517270189">I-restart ang Chrome</translation>
<translation id="6517596291481585650">Babala: Hindi na-merge ang patakarang ito bilang listahan gaya ng tinukoy ng patakaran dahil hindi ito isang listahan.</translation>
+<translation id="6518133107902771759">I-verify</translation>
<translation id="6521745193039995384">Hindi aktibo</translation>
<translation id="6529602333819889595">&amp;Gawing Muli ang Pagtanggal</translation>
<translation id="6534179046333460208">Mga suhestyon sa Pisikal na Web</translation>
<translation id="6545864417968258051">Pag-scan ng Bluetooth</translation>
<translation id="6554795675067793129">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang iyong account.</translation>
<translation id="6556866813142980365">Redo</translation>
-<translation id="6563469144985748109">Hindi pa ito inaaprubahan ng iyong manager</translation>
<translation id="6569060085658103619">Isang page ng extension ang tinitingnan mo</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Light Pink</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">I-clear</translation>
<translation id="6644283850729428850">Hindi na ginagamit ang patakarang ito.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Wala}=1{Mula sa 1 site (hindi ka masa-sign out sa iyong Google Account)}one{Mula sa # site (hindi ka masa-sign out sa iyong Google Account)}other{Mula sa # na site (hindi ka masa-sign out sa iyong Google Account)}}</translation>
+<translation id="6652101503459149953">Gamitin ang Windows Hello</translation>
<translation id="6657585470893396449">Password</translation>
<translation id="6670613747977017428">Bumalik sa kaligtasan.</translation>
<translation id="6671697161687535275">Gusto mo bang alisin ang form para sa suhestyon sa Chromium?</translation>
<translation id="6685834062052613830">Mag-sign out at kumpletuhin ang setup</translation>
<translation id="6689271823431384964">Nag-aalok ang Chrome na i-save ang iyong mga card sa Google Account mo dahil naka-sign in ka. Puwede mong baguhin ang gawing ito sa mga setting. Mula sa iyong account ang pangalan ng cardholder.</translation>
+<translation id="6707256370811247129">I-scan ang mga content ng cache at mga file na ida-download o ia-upload mo sa Chrome.</translation>
<translation id="6710213216561001401">Nakaraan</translation>
<translation id="6710594484020273272">&lt;I-type ang termino para sa paghahanap&gt;</translation>
<translation id="671076103358959139">Token sa Pag-enroll</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Na-encrypt ang data mo gamit ang iyong <ph name="BEGIN_LINK" />passphrase sa pag-sync<ph name="END_LINK" /> noong <ph name="TIME" />. Ilagay ito para simulan ang pag-sync.</translation>
<translation id="674375294223700098">Hindi alam na error sa certificate ng server</translation>
<translation id="6744009308914054259">Habang naghihintay ng koneksyon, maaari mong bisitahin ang Mga Download para magbasa ng mga offline na artikulo.</translation>
+<translation id="6747611005629681221">Babala: May mga hindi na ginagamit na feature!</translation>
<translation id="6753269504797312559">Halaga ng patakaran</translation>
<translation id="6757797048963528358">Nag-sleep ang iyong device.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Hindi pa ito inaaprubahan ng iyong magulang</translation>
<translation id="67862343314499040">Violet</translation>
<translation id="6786747875388722282">Mga Extension</translation>
<translation id="6790428901817661496">I-play</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Kinakailangang Field</translation>
<translation id="6810899417690483278">Customization ID</translation>
<translation id="6825578344716086703">Tinangka mong abutin ang <ph name="DOMAIN" />, ngunit nagpakita ang server ng certificate na nilagdaan gamit ang isang mahinang signature algorithm (tulad ng SHA-1). Nangangahulugan ito na maaaring pineke ang mga panseguridad na kredensyal na ipinakita ng server, at ang server ay maaaring hindi ang server na inaasahan mo (maaaring nakikipag-ugnayan ka sa isang attacker).</translation>
+<translation id="6826370046007623921">Pag-iwas sa Pagkawala ng Data</translation>
<translation id="6831043979455480757">Isalin</translation>
<translation id="6839929833149231406">Lugar</translation>
<translation id="6852204201400771460">I-reload ang app?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Hindi sinusuportahan ang antas ng patakaran.</translation>
<translation id="6895330447102777224">Nakumpirma na ang iyong card</translation>
<translation id="6897140037006041989">User Agent</translation>
-<translation id="6903319715792422884">Tumulong sa pagpapahusay ng Ligtas na Pag-browse sa pamamagitan ng pagpapadala sa Google ng ilang <ph name="BEGIN_WHITEPAPER_LINK" />impormasyon ng system at content ng page<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">User:</translation>
<translation id="6934672428414710184">Nagmula ang pangalang ito sa iyong Google Account</translation>
<translation id="6944692733090228304">Inilagay mo ang iyong password sa site na hindi pinapamahalaan ng <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para protektahan ang iyong account, huwag gamiting muli ang password mo sa iba pang app at site.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> pa}one{<ph name="PAYMENT_METHOD_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> pa}other{<ph name="PAYMENT_METHOD_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> pa}}</translation>
<translation id="7153618581592392745">Lavender</translation>
<translation id="717330890047184534">Gaia ID:</translation>
+<translation id="7174545416324379297">Naka-merge</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> pa}one{<ph name="SHIPPING_OPTION_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> pa}other{<ph name="SHIPPING_OPTION_PREVIEW" /> at <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> pa}}</translation>
<translation id="7177397715882417099">Hiniling ng server na pupuntahan mo, ang <ph name="ORIGIN" />, na
ilapat ang isang patakaran sa seguridad sa lahat ng kahilingan dito. Ngunit sa halip na
@@ -1166,6 +1187,7 @@ Mga karagdagang detalye:
<translation id="7320336641823683070">Tulong sa Koneksyon</translation>
<translation id="733354035281974745">Pag-override ng lokal na account ng device</translation>
<translation id="7334320624316649418">&amp;Gawing muli ang pagbabago sa ayos</translation>
+<translation id="7337706099755338005">Hindi available sa iyong platform.</translation>
<translation id="733923710415886693">Ang certificate ng server ay hindi inihayag sa pamamagitan ng Transparency ng Certificate.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Naka-affiliate:</translation>
@@ -1197,7 +1219,6 @@ Mga karagdagang detalye:
<translation id="7440140511386898319">Mag-explore habang offline</translation>
<translation id="7441627299479586546">Maling paksa ng patakaran</translation>
<translation id="7442725080345379071">Light Orange</translation>
-<translation id="7444046173054089907">Naka-block ang site na ito</translation>
<translation id="7445762425076701745">Hindi ganap na mapatunayan ang pagkakakilanlan ng server na konektado ka. Konektado ka sa server gamit ang pangalan na angkop lamang sa loob ng iyong network, na walang paraan ang panglabas na certificate authority na patunayan ang pagmamay-ari. Dahil magbibigay ang ilang kinauukulan sa certificate para sa mga pangalang ito, walang paraan upang matiyak na konektado ka sa nilayong website at hindi isang umaatake.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Matuto pa<ph name="END_LINK" /> tungkol sa problemang ito.</translation>
<translation id="7455133967321480974">Gamitin ang pangkalahatang default (I-block)</translation>
@@ -1219,9 +1240,9 @@ Mga karagdagang detalye:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Kapag nagkumpirma ka, ibabahagi ang mga detalye ng iyong card sa site na ito.</translation>
<translation id="7542995811387359312">Hindi pinagana ang awtomatikong pagpuno ng credit card dahil ang form na ito ay hindi gumagamit ng secure na koneksyon.</translation>
-<translation id="7543525346216957623">Hilingin sa iyong magulang</translation>
<translation id="7548892272833184391">Ayusin ang mga error sa koneksyon</translation>
<translation id="7549584377607005141">Kinakailangan ng webpage na ito ng data na inilagay mo dati upang maipakita nang maayos. Maipapadala mong muli ang data na ito, ngunit kapag ginawa mo iyon, mauulit ang anumang pagkilos na isinagawa dati ng pahinang ito.</translation>
+<translation id="7550637293666041147">Username ng iyong device at username sa Chrome</translation>
<translation id="7552846755917812628">Subukan ang mga sumusunod na tip:</translation>
<translation id="7554791636758816595">Bagong Tab</translation>
<translation id="7564049878696755256">Maaari kang mawalan ng access sa iyong account sa <ph name="ORG_NAME" /> o manakawan ng pagkakakilanlan. Inirerekomenda ng Chrome na palitan ang iyong password ngayon.</translation>
@@ -1236,6 +1257,7 @@ Mga karagdagang detalye:
<translation id="7610193165460212391">Wala sa sakop ang halaga <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Exp: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Mayroon ka nang data na na-encrypt gamit ang ibang bersyon ng iyong password ng Google Account. Pakilagay ito sa ibaba.</translation>
+<translation id="7625784245512586808">Proteksyon Laban sa Banta ng Chrome Enterprise</translation>
<translation id="7633909222644580952">Date ng performance at mga ulat ng pag-crash</translation>
<translation id="7637571805876720304">Gusto mo bang alisin ang credit card sa Chromium?</translation>
<translation id="7638605456503525968">Mga serial port</translation>
@@ -1248,7 +1270,6 @@ Mga karagdagang detalye:
<translation id="7668654391829183341">Hindi kilalang device</translation>
<translation id="7669271284792375604">Maaaring subukan ng mga attacker sa site na ito na linlangin ka upang mag-install ng mga program na makakasama sa iyong karanasan sa pag-browse (halimbawa, sa pamamagitan ng pagbabago ng iyong homepage o pagpapakita ng mga karagdagang ad sa mga site na binibisita mo).</translation>
<translation id="7676643023259824263">Hanapin ang text sa clipboard, na <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform at Cloud</translation>
<translation id="7681101578153515023">Baguhin ang Search Engine</translation>
<translation id="7682287625158474539">Pagpapadala</translation>
<translation id="7687186412095877299">Pinupunan ang mga form sa pagbabayad ng iyong mga naka-save na paraan ng pagbabayad</translation>
@@ -1263,7 +1284,6 @@ Mga karagdagang detalye:
<translation id="7723047071702270851">I-edit ang Card</translation>
<translation id="774634243536837715">Na-block ang mapanganib na content.</translation>
<translation id="7752995774971033316">Hindi pinamamahalaan</translation>
-<translation id="7755287808199759310">Maaari itong i-unblock ng iyong magulang para sa iyo</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Maaaring na-block ng firewall o antivirus software ang koneksyon.</translation>
<translation id="7759163816903619567">Display domain:</translation>
@@ -1307,7 +1327,6 @@ Mga karagdagang detalye:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Pamahalaan ang Mga Password</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ise-save ang card na ito at ang billing address nito. Magagamit mo ito kapag nag-sign in ka sa <ph name="USER_EMAIL" />.}one{Ise-save ang mga card na ito at ang mga billing address ng mga ito. Magagamit mo ang mga ito kapag nag-sign in ka sa <ph name="USER_EMAIL" />.}other{Ise-save ang mga card na ito at ang mga billing address ng mga ito. Magagamit mo ang mga ito kapag nag-sign in ka sa <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Hindi namin makaugnayan ang iyong mga magulang sa sandaling ito. Pakisubukang muli.</translation>
<translation id="8025119109950072390">Maaari kang linlangin ng mga attacker sa site na ito na gumawa ng mga bagay na mapanganib tulad ng pag-i-install ng software o pagbubunyag ng iyong personal na impormasyon (halimbawa, mga password, numero ng telepono o credit card).</translation>
<translation id="8034522405403831421">Nasa <ph name="SOURCE_LANGUAGE" /> ang pahinang ito. Isalin ito sa <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pen</translation>
@@ -1318,6 +1337,7 @@ Mga karagdagang detalye:
<translation id="8041940743680923270">Gamitin ang pangkalahatang default (Tanungin)</translation>
<translation id="8042918947222776840">Pumili ng Paraan ng Pag-pick up</translation>
<translation id="8057711352706143257">Hindi maayos na naka-configure ang "<ph name="SOFTWARE_NAME" />." Kadalasang naaayos ang problema kapag in-uninstall ang "<ph name="SOFTWARE_NAME" />." <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Hindi mo na kailangang maglagay ng security code ng card simula ngayon</translation>
<translation id="8066955247577885446">Paumanhin, nagkaproblema.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Hindi maaaring i-annotate kapag naka-rotate</translation>
@@ -1348,6 +1368,7 @@ Mga karagdagang detalye:
<translation id="8211406090763984747">Secure ang koneksyon</translation>
<translation id="8218327578424803826">Itinakdang Lokasyon:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Pag-uulat ng Enterprise</translation>
<translation id="8225771182978767009">Pinili ng taong nag-set up ng computer na ito na i-block ang site na ito.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Buksan ang page sa bagong Incognito tab</translation>
@@ -1402,23 +1423,23 @@ Mga karagdagang detalye:
<translation id="8508648098325802031">Icon ng paghahanap</translation>
<translation id="8522552481199248698">Matutulungan ka ng Chrome na protektahan ang iyong Google Account at palitan ang password mo.</translation>
<translation id="8543181531796978784">Maaari kang <ph name="BEGIN_ERROR_LINK" />mag-ulat ng problema sa pagtukoy<ph name="END_ERROR_LINK" /> o, kung nauunawaan mo ang mga panganib sa iyong seguridad, <ph name="BEGIN_LINK" />bisitahin ang hindi ligtas na site na ito<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">May mga tanong? Makipag-ugnayan sa taong nangangasiwa sa iyong profile.</translation>
<translation id="8553075262323480129">Nabigo ang pag-translate dahil hindi matukoy ang wika ng pahina.</translation>
<translation id="8557066899867184262">Makikita ang CVC sa likod ng iyong card.</translation>
<translation id="8559762987265718583">Hindi makapagtatag ng pribadong koneksyon sa <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> dahil mali ang petsa at oras ng iyong device (<ph name="DATE_AND_TIME" />).</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> kahina-hinalang site</translation>
<translation id="8564985650692024650">Inirerekomenda ng Chromium na i-reset ang iyong password sa <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> kung ginamit mo ito sa iba pang site.</translation>
<translation id="8571890674111243710">Tina-translate ang pahina sa <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Magdagdag ng numero ng telepono</translation>
-<translation id="859285277496340001">Hindi tumutukoy ang certificate na ito ng mekanismo upang masuri kung nabawi ito.</translation>
<translation id="860043288473659153">Pangalan ng cardholder</translation>
<translation id="861775596732816396">Laki 4</translation>
-<translation id="8620436878122366504">Hindi pa ito inaaprubahan ng iyong mga magulang</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">I-save ang Card na Ito sa Device na Ito</translation>
<translation id="8626112503828625890">Mag-store ng mga datalye ng pagsingil sa Google Account?</translation>
+<translation id="8647750283161643317">I-reset ang lahat sa default</translation>
<translation id="8663226718884576429">Buod ng Order, <ph name="TOTAL_LABEL" />, Higit pang Detalye</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, sagot, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Available</translation>
<translation id="8703575177326907206">Ang iyong koneksyon sa <ph name="DOMAIN" /> ay hindi naka-encrypt.</translation>
<translation id="8718314106902482036">Hindi nakumpleto ang pagbabayad</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, suhestyon sa paghahanap</translation>
@@ -1429,6 +1450,7 @@ Mga karagdagang detalye:
<translation id="8738058698779197622">Upang makapagtatag ng secure na koneksyon, kailangang itakda nang tama ang iyong orasan. Ito ay dahil sa may-bisa lang ang mga certificate na ginagamit ng mga website upang tukuyin ang mga sarili ng mga ito sa loob ng mga partikular na tagal ng panahon. Dahil mali ang orasan ng iyong device, hindi ma-verify ng Chromium ang mga certificate na ito.</translation>
<translation id="8740359287975076522">Hindi makita ang &lt;abbr id="dnsDefinition"&gt;DNS address&lt;/abbr&gt; ng <ph name="HOST_NAME" />. Dina-diagnose ang problema.</translation>
<translation id="874846938927089722">Mga Tinatanggap na Credit at Prepaid Card</translation>
+<translation id="874918643257405732">I-bookmark ang tab na ito</translation>
<translation id="8759274551635299824">Nag-expire na ang card na ito</translation>
<translation id="8761567432415473239">Ang Google Safe Browsing ay may <ph name="BEGIN_LINK" />natagpuang mga nakakasirang program<ph name="END_LINK" /> sa <ph name="SITE" /> kamakailan.</translation>
<translation id="8763927697961133303">USB device</translation>
@@ -1458,6 +1480,7 @@ Mga karagdagang detalye:
<translation id="8938939909778640821">Mga tinatanggap na credit at prepaid card</translation>
<translation id="8943282376843390568">Lime</translation>
<translation id="8957210676456822347">Pagpapahintulot sa Captive Portal</translation>
+<translation id="8962950042226115166">Kahina-hinalang site</translation>
<translation id="8968766641738584599">I-save ang card</translation>
<translation id="8971063699422889582">Nag-expire na ang certificate ng server.</translation>
<translation id="8975012916872825179">May kasamang impormasyon tulad ng mga numero ng telepono, email address, at address sa pagpapadala</translation>
@@ -1480,24 +1503,24 @@ Mga karagdagang detalye:
<translation id="9035022520814077154">Error sa seguridad</translation>
<translation id="9038649477754266430">Gumamit ng serbisyo sa paghula upang ma-load ang mga page nang mas mabilis</translation>
<translation id="9039213469156557790">Bukod pa rito, ang page na ito ay may iba pang mga mapagkukunang hindi secure. Makikita ng iba ang mga mapagkukunang ito habang ipinadadala, at maaaring baguhin ng isang umaatake upang baguhin ang gawi ng page.</translation>
+<translation id="9044359186343685026">Gamitin ang Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Tinangka mong maabot ang <ph name="DOMAIN" />, ngunit nagpakita ang server ng isang di-wastong certificate.</translation>
<translation id="9050666287014529139">Passphrase</translation>
<translation id="9065203028668620118">I-edit</translation>
<translation id="9065745800631924235">Paghahanap para sa <ph name="TEXT" /> mula sa history</translation>
<translation id="9069693763241529744">Na-block ng isang extension</translation>
-<translation id="9076283476770535406">Maaaring mayroon itong mature content</translation>
<translation id="9076630408993835509">Hindi pinapamahalaan ng kumpanya o iba pang organisasyon ang browser na ito. Maaaring pinapamahalaan sa labas ng Chrome ang aktibidad sa device na ito. <ph name="BEGIN_LINK" />Matuto Pa<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Nangangailangan ng higit pang impormasyon</translation>
<translation id="9080712759204168376">Buod ng Order</translation>
<translation id="9089260154716455634">Patakaran sa Mga Off Hour:</translation>
<translation id="9095388113577226029">Higit pang wika...</translation>
+<translation id="9098981495403789647">Na-enable ng iyong administrator ang Proteksyon Laban sa Banta ng Chrome Enterprise sa browser mo. May access ang Proteksyon Laban sa Banta ng Chrome Enterprise sa ilan sa iyong data.</translation>
<translation id="9103872766612412690">Karaniwang gumagamit ang <ph name="SITE" /> ng pag-encrypt upang protektahan ang iyong impormasyon. Noong sinubukang kumonekta ng Chromium sa <ph name="SITE" /> sa pagkakataong ito, nagbalik ang website ng mga hindi pangkaraniwan at maling kredensyal. Maaari itong mangyari kapag sinusubukan ng isang attacker na magpanggap bilang <ph name="SITE" />, o naputol ang koneksyon dahil sa isang screen ng pag-sign in sa Wi-Fi. Secure pa rin ang iyong impormasyon dahil inihinto ng Chromium ang koneksyon bago magkaroon ng palitan ng anumang data.</translation>
<translation id="9106062320799175032">Magdagdag ng Billing Address</translation>
<translation id="9114524666733003316">Kinukumpirma ang card...</translation>
<translation id="9128870381267983090">Kumonekta sa network</translation>
<translation id="9137013805542155359">Ipakita ang orihinal</translation>
-<translation id="9137248913990643158">Magsimula at mag-sign in sa Chrome bago gamitin ang app na ito.</translation>
<translation id="9141013498910525015">Pamahalaan ang mga address</translation>
<translation id="9148088599418889305">Pumili ng Paraan ng Pagpapadala</translation>
<translation id="9148507642005240123">&amp;I-undo ang pag-e-edit</translation>
diff --git a/chromium/components/strings/components_strings_fr.xtb b/chromium/components/strings/components_strings_fr.xtb
index 4d1338da805..8ecf03a5479 100644
--- a/chromium/components/strings/components_strings_fr.xtb
+++ b/chromium/components/strings/components_strings_fr.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Ajouter le nom du titulaire de la carte</translation>
<translation id="1089439967362294234">Modifier le mot de passe</translation>
+<translation id="1096545575934602868">Ce champ ne peut pas contenir plus de <ph name="MAX_ITEMS_LIMIT" /> entrées. Toutes les entrées supplémentaires seront supprimées.</translation>
<translation id="109743633954054152">Gérer les mots de passe dans les paramètres de Chrome</translation>
<translation id="1103523840287552314">Toujours traduire les pages en <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Si cette case est cochée, une copie de votre carte est stockée sur cet appareil pour compléter les formulaires plus rapidement.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Accédez à une <ph name="BEGIN_LINK" />copie mise en cache<ph name="END_LINK" /> de <ph name="URL" />.</translation>
<translation id="1156303062776767266">Vous consultez un fichier local ou partagé</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> a mis fin à la connexion de manière inattendue.</translation>
+<translation id="115926840831309955">Vérifiez votre code CVC et réessayez, ou mettez à jour la date d'expiration</translation>
<translation id="1161325031994447685">Reconnectez-vous au réseau Wi-Fi</translation>
<translation id="1165039591588034296">Erreur</translation>
<translation id="1175364870820465910">Im&amp;primer...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">Un logiciel installé sur votre ordinateur empêche Chrome de se connecter au Web de manière sécurisée (sous Windows uniquement)</translation>
<translation id="1294154142200295408">Variations de ligne de commande</translation>
<translation id="129553762522093515">Récemment fermés</translation>
+<translation id="1298536327547837046">Détection des logiciels malveillants</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Essayez de supprimer les cookies.<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Fonctionnalités obsolètes</translation>
<translation id="1320233736580025032">Prc1 (enveloppe)</translation>
<translation id="132301787627749051">Rechercher l'image du presse-papier</translation>
<translation id="1323433172918577554">Afficher plus</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">En attente de connexion…</translation>
<translation id="1529521330346880926">10x15 (enveloppe)</translation>
+<translation id="1530707389502320859">Le site auquel vous tentez d'accéder semble faux. Les pirates tentent parfois d'imiter des sites Web en modifiant légèrement l'URL utilisée.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Cette page indique</translation>
<translation id="153384715582417236">C'est tout !</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">Système d'exploitation</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Le document est trop volumineux pour être annoté</translation>
-<translation id="1721312023322545264">Vous devez disposer de l'autorisation de <ph name="NAME" /> pour consulter ce site</translation>
<translation id="1721424275792716183">* Champ obligatoire</translation>
<translation id="1727741090716970331">Ajouter un numéro de carte valide</translation>
<translation id="1728677426644403582">Vous consultez actuellement la source d'une page Web</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Sites Web consultés et durée des visites</translation>
<translation id="1826516787628120939">Vérification en cours…</translation>
<translation id="1834321415901700177">Ce site contient des programmes dangereux</translation>
+<translation id="1838374766361614909">Effacer la recherche</translation>
<translation id="1839551713262164453">Échec de la validation des valeurs de règle avec des erreurs</translation>
<translation id="1842969606798536927">Paiement</translation>
<translation id="1871208020102129563">Le proxy est configuré pour utiliser des serveurs proxy déterminés, pas une URL de script .pac.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Réduire la liste</translation>
<translation id="1898423065542865115">Filtrage</translation>
<translation id="1914326953223720820">Service de décompression de fichier</translation>
+<translation id="1915697529809968049">Utiliser Touch ID au lieu du code CVC ?</translation>
<translation id="1916770123977586577">Pour appliquer vos paramètres mis à jour à ce site, actualisez la page</translation>
<translation id="1919345977826869612">Annonces</translation>
<translation id="1919367280705858090">Obtenir de l'aide pour un message d'erreur spécifique</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Favoris du domaine <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Erreur de sérialisation.</translation>
<translation id="1974060860693918893">Paramètres avancés</translation>
+<translation id="1974883374937189061">Contribuez à améliorer la sécurité de Chrome en envoyant à Google les <ph name="BEGIN_WHITEPAPER_LINK" />URL de certaines pages que vous consultez, ainsi que des informations système limitées et une partie du contenu de certaines pages<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Version du micrologiciel</translation>
<translation id="1981206234434200693">Effacer les données de l'historique de navigation de Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{et 1 autre}one{et # autre}other{et # autres}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Saisissez une année d'expiration valide</translation>
<translation id="2212735316055980242">Règle introuvable.</translation>
<translation id="2213606439339815911">Obtention des entrées en cours…</translation>
+<translation id="2215727959747642672">Modification de fichier</translation>
<translation id="2218879909401188352">Les pirates informatiques qui contrôlent le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> peuvent installer des applications dangereuses qui endommagent votre appareil, ajoutent des frais cachés à votre facture de téléphonie mobile ou dérobent vos informations personnelles. <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Aucun accès à Internet</translation>
<translation id="2230458221926704099">Vérifiez la connexion à l'aide de l'<ph name="BEGIN_LINK" />application de diagnostic<ph name="END_LINK" />.</translation>
<translation id="2239100178324503013">Envoyer maintenant</translation>
+<translation id="2248949050832152960">Utiliser WebAuthn</translation>
<translation id="225207911366869382">Cette valeur n'est plus utilisée dans le cadre de cette règle.</translation>
<translation id="2257315177824333709">Désolé, votre carte ne peut pas être enregistrée pour le moment</translation>
<translation id="2262243747453050782">Erreur HTTP.</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">URL de recherche incorrecte</translation>
<translation id="2482878487686419369">Notifications</translation>
<translation id="248348093745724435">Règles associées à la machine</translation>
-<translation id="2485387744899240041">Noms d'utilisateur pour votre appareil et votre navigateur</translation>
<translation id="2491120439723279231">Le certificat du serveur contient des erreurs.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analyse de fichiers JSON</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Retour</translation>
<translation id="2503184589641749290">Cartes de débit et cartes prépayées acceptées</translation>
<translation id="2505268675989099013">Protéger le compte</translation>
+<translation id="2515335152965840738">IGNORER</translation>
<translation id="2515629240566999685">Vérifiez le signal dans votre zone.</translation>
<translation id="2523886232349826891">Enregistrée sur cet appareil uniquement</translation>
<translation id="2524461107774643265">Ajouter des informations</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Valider</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Aucun}=1{1 mot de passe (associé à <ph name="DOMAIN_LIST" />)}=2{2 mots de passe (associés à <ph name="DOMAIN_LIST" />)}one{# mot de passe (associé à <ph name="DOMAIN_LIST" />)}other{# mots de passe (associés à <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Fermez les autres onglets ou applications</translation>
-<translation id="267371737713284912">appuyez sur <ph name="MODIFIER_KEY_DESCRIPTION" /> pour annuler</translation>
<translation id="2674170444375937751">Voulez-vous vraiment supprimer ces pages de votre historique ?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Quitter</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">La valeur ne respecte pas le format requis.</translation>
<translation id="2705137772291741111">La copie enregistrée (en cache) de ce site est illisible.</translation>
<translation id="2709516037105925701">Saisie automatique</translation>
-<translation id="2712173769900027643">Demander l'autorisation</translation>
<translation id="2713444072780614174">Blanc</translation>
<translation id="2720342946869265578">À proximité</translation>
<translation id="2721148159707890343">Demande réussie.</translation>
<translation id="2728127805433021124">Le certificat du serveur a été signé avec un algorithme de signature faible.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Exécuter les diagnostics de connectivité<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">En activant ces fonctionnalités, vous risquez de perdre les données de navigation, ou de compromettre votre sécurité ou votre vie privée. Les fonctionnalités activées s'appliquent à tous les utilisateurs de ce navigateur.</translation>
<translation id="2735043616039983645">Il existe plusieurs sources avec des valeurs en conflit pour cette règle.</translation>
<translation id="2738330467931008676">Sélectionner une adresse d'enlèvement</translation>
<translation id="2740531572673183784">OK</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">La connexion a été réinitialisée.</translation>
<translation id="2788784517760473862">Cartes de crédit acceptées</translation>
<translation id="2792012897584536778">Les administrateurs de cet appareil ont configuré des certificats de sécurité grâce auxquels ils ont la possibilité d'afficher le contenu des sites Web que vous consultez.</translation>
-<translation id="2794233252405721443">Site bloqué</translation>
<translation id="2799020568854403057">Ce site contient des applications malveillantes</translation>
<translation id="2799223571221894425">Relancer</translation>
<translation id="2803306138276472711">La fonctionnalité de navigation sécurisée Google a récemment permis de <ph name="BEGIN_LINK" />détecter des logiciels malveillants<ph name="END_LINK" /> sur le site <ph name="SITE" />. Un site Web qui est normalement sans danger peut parfois être infecté par des logiciels malveillants.</translation>
+<translation id="2815364696811431560">QUITTER LE SITE</translation>
<translation id="2824775600643448204">Barre d'adresse et de recherche</translation>
<translation id="2826760142808435982">La connexion est chiffrée et authentifiée avec la clé <ph name="CIPHER" />. La méthode d'échange de clés utilisée est <ph name="KX" />.</translation>
<translation id="2835170189407361413">Effacer le formulaire</translation>
<translation id="2847118875340931228">Ouvrir une fenêtre de navigation privée</translation>
<translation id="2850739647070081192">Invite (enveloppe)</translation>
-<translation id="2851634818064021665">Tu n'es pas autorisé à consulter ce site</translation>
<translation id="2856444702002559011">Des individus malveillants tentent peut-être de subtiliser vos informations personnelles sur le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (mots de passe, messages ou numéros de carte de crédit, par exemple). <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Enregistrer la carte ?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Si cette option est activée, Chromium enregistre une copie de votre carte sur cet appareil pour vous permettre de remplir plus rapidement les formulaires.</translation>
<translation id="2985398929374701810">Saisissez une adresse valide</translation>
<translation id="2986368408720340940">Mode d'enlèvement non disponible. Choisissez-en un autre.</translation>
+<translation id="2987034854559945715">Aucune fonctionnalité correspondante</translation>
<translation id="2991174974383378012">Partage avec les sites Web</translation>
<translation id="2991571918955627853">Le site <ph name="SITE" /> est actuellement inaccessible, car il utilise la technologie HSTS. Les erreurs réseau et les attaques sont généralement temporaires. Vous devriez donc pouvoir accéder à cette page plus tard.</translation>
<translation id="3005723025932146533">Afficher la copie enregistrée</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Type de règle incorrect.</translation>
<translation id="3037605927509011580">Aïe aïe aïe</translation>
<translation id="3041612393474885105">Informations relatives au certificat</translation>
+<translation id="3057676462092457419">Le mode DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> n'est pas compatible pour le moment. Il a été défini sur <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (enveloppe)</translation>
<translation id="3061707000357573562">Service d'application de correctifs</translation>
<translation id="3064966200440839136">En payant via une application externe, vous allez quitter le mode navigation privée. Voulez-vous continuer ?</translation>
@@ -419,6 +428,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> sur <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Annuler le paiement</translation>
<translation id="3207960819495026254">Favori</translation>
+<translation id="3209034400446768650">Cette page peut vous facturer de l'argent</translation>
<translation id="3225919329040284222">Le serveur dispose d'un certificat qui ne répond pas aux exigences intégrées. Celles-ci sont incluses dans certains sites Web très sécurisés afin de vous protéger.</translation>
<translation id="3226128629678568754">Veuillez appuyer sur le bouton d'actualisation pour renvoyer les données nécessaires au chargement de la page.</translation>
<translation id="3227137524299004712">Micro</translation>
@@ -426,7 +436,6 @@
<translation id="3229041911291329567">Informations sur la version de l'appareil et du navigateur</translation>
<translation id="323107829343500871">Saisir le code CVC de la carte <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Toujours détecter du contenu important sur ce site</translation>
-<translation id="3254409185687681395">Ajouter cette page aux favoris</translation>
<translation id="3270847123878663523">&amp;Annuler la réorganisation</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Ajouter le nom sur la carte</translation>
@@ -436,7 +445,6 @@
<translation id="3320021301628644560">Ajouter une adresse de facturation</translation>
<translation id="3324983252691184275">Pourpre</translation>
<translation id="3338095232262050444">Sécurisé</translation>
-<translation id="3345135638360864351">Impossible d'envoyer votre demande d'accès au site à <ph name="NAME" />. Veuillez réessayer.</translation>
<translation id="3355823806454867987">Modifier les paramètres du proxy...</translation>
<translation id="3361596688432910856">Les informations suivantes <ph name="BEGIN_EMPHASIS" />ne seront pas enregistrées<ph name="END_EMPHASIS" /> dans Chrome :
<ph name="BEGIN_LIST" />
@@ -470,18 +478,15 @@
<translation id="3462200631372590220">Masquer les paramètres avancés</translation>
<translation id="3467763166455606212">Nom du titulaire de la carte obligatoire</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, actuellement ouvert, appuyez sur la touche tabulation, puis sur Entrée pour passer à l'onglet ouvert</translation>
-<translation id="3479539252931486093">S'agit-il d'une erreur inattendue ? <ph name="BEGIN_LINK" />Signalez-nous ce problème.<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Pas maintenant</translation>
<translation id="3484560055331845446">Vous pourriez perdre l'accès à votre compte Google. L'équipe Chrome vous recommande de modifier votre mot de passe maintenant. Vous devrez vous connecter.</translation>
<translation id="3495081129428749620">Rechercher sur la page
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Impossible de joindre votre parent pour le moment. Veuillez réessayer.</translation>
<translation id="3512163584740124171">Cette règle est ignorée, car une autre issue du même groupe de règles présente une priorité plus élevée.</translation>
<translation id="3528171143076753409">Le certificat du serveur n'est pas approuvé.</translation>
<translation id="3528485271872257980">Marron foncé</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Au moins 1 élément sur les appareils synchronisés}=1{1 élément (et plus sur les appareils synchronisés)}one{# élément (et plus sur les appareils synchronisés)}other{# éléments (et plus sur les appareils synchronisés)}}</translation>
<translation id="3539171420378717834">Conserver une copie de cette carte sur cet appareil</translation>
-<translation id="3556433843310711081">Votre responsable peut vous le débloquer</translation>
<translation id="3566021033012934673">Votre connexion n'est pas privée</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Une page intégrée à l'adresse <ph name="SITE" /> indique</translation>
@@ -509,6 +514,7 @@
<translation id="3678529606614285348">Ouvrir la page dans une nouvelle fenêtre de navigation privée (Ctrl+Maj+N)</translation>
<translation id="3679803492151881375">Rapport d'erreur enregistré le <ph name="CRASH_TIME" /> et importé le <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informations relatives au certificat</translation>
+<translation id="3701427423622901115">Réinitialisation appliquée.</translation>
<translation id="3704162925118123524">Pour utiliser ce réseau, il est possible que vous deviez vous rendre sur la page de connexion correspondante.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Chargement en cours...</translation>
@@ -525,6 +531,7 @@
<translation id="3748148204939282805">Des individus malveillants à l'œuvre sur le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> pourraient vous inciter à effectuer des opérations dangereuses, comme installer des logiciels ou divulguer des informations personnelles (mots de passe, numéros de téléphone ou numéros de carte de crédit, par exemple). <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Échec de la traduction en raison d'une erreur de serveur</translation>
<translation id="3759461132968374835">Aucune erreur n'a été signalée récemment. Les erreurs n'apparaissent ici que lorsque l'envoi de rapports d'erreur est activé.</translation>
+<translation id="3760561303380396507">Utiliser Windows Hello au lieu du code CVC ?</translation>
<translation id="3761718714832595332">Masquer l'état</translation>
<translation id="3765032636089507299">La page de navigation sécurisée est en cours de création.</translation>
<translation id="3778403066972421603">Voulez-vous enregistrer cette carte dans votre compte Google et sur cet appareil ?</translation>
@@ -534,6 +541,7 @@
<translation id="3789155188480882154">Taille 16</translation>
<translation id="3797522431967816232">Prc3 (enveloppe)</translation>
<translation id="3807873520724684969">Contenu malveillant bloqué.</translation>
+<translation id="3808375843007691220">Attention : Fonctionnalités expérimentales sur cette page !</translation>
<translation id="3810973564298564668">Gérer</translation>
<translation id="382518646247711829">Si vous utilisez un serveur proxy…</translation>
<translation id="3828924085048779000">La phrase secrète est obligatoire.</translation>
@@ -542,11 +550,11 @@
<translation id="3858027520442213535">Mettre à jour la date et l'heure</translation>
<translation id="3884278016824448484">Identifiant de l'appareil en conflit.</translation>
<translation id="3885155851504623709">Paroisse</translation>
-<translation id="3886446263141354045">Votre demande d'accès à ce site a bien été envoyée à <ph name="NAME" /></translation>
<translation id="3890664840433101773">Ajouter une adresse e-mail</translation>
<translation id="3901925938762663762">La carte a expiré.</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Utiliser WebAuthn au lieu du code CVC ?</translation>
<translation id="3946209740501886391">Toujours demander sur ce site</translation>
<translation id="3949571496842715403">Impossible de vérifier que ce serveur est bien <ph name="DOMAIN" />, car son certificat de sécurité ne contient pas l'extension "Subject Alternative Names" (Autres noms de l'objet). Cela peut être dû à une mauvaise configuration ou à l'interception de votre connexion par un pirate informatique.</translation>
<translation id="3949601375789751990">Votre historique de navigation s'affiche ici</translation>
@@ -557,11 +565,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Aucun}=1{De 1 site }one{De # site }other{De # sites }}</translation>
<translation id="397105322502079400">Calcul en cours…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> est bloqué</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> a activé la protection contre les menaces de Chrome Enterprise dans votre navigateur. Cette fonctionnalité a accès à certaines de vos données.</translation>
<translation id="3987940399970879459">Moins de 1 Mo</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 page Web à proximité}one{# page Web à proximité}other{# pages Web à proximité}}</translation>
<translation id="4030383055268325496">&amp;Annuler l'ajout</translation>
<translation id="4032320456957708163">Votre navigateur est géré par <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Le lien que vous avez ouvert mène à un site que vous ne consultez généralement pas. Il s'agit peut-être d'une tentative de tromperie.</translation>
<translation id="4058922952496707368">Clé "<ph name="SUBKEY" />" : <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (enveloppe)</translation>
<translation id="4067947977115446013">Ajouter une adresse valide</translation>
@@ -574,6 +582,7 @@
<translation id="4103249731201008433">Le numéro de série de l'appareil n'est pas valide.</translation>
<translation id="410351446219883937">Lecture automatique</translation>
<translation id="4103763322291513355">Accédez à &lt;strong&gt;chrome://policy&lt;/strong&gt; pour consulter une liste des URL ajoutées à la liste noire et des autres règles définies par votre administrateur système.</translation>
+<translation id="4108231218301530806">Utiliser votre empreinte digitale pour valider cette carte la prochaine fois.</translation>
<translation id="4110652170750985508">Vérifier votre paiement</translation>
<translation id="4112140312785995938">Retour rapide</translation>
<translation id="4116663294526079822">Toujours autoriser sur ce site</translation>
@@ -588,6 +597,7 @@
<translation id="4171400957073367226">Signature de validation non valide.</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> élément supplémentaire}one{<ph name="ITEM_COUNT" /> élément supplémentaire}other{<ph name="ITEM_COUNT" /> éléments supplémentaires}}</translation>
+<translation id="4176463684765177261">Désactivé</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Pour régler vos achats plus rapidement la prochaine fois, ajoutez votre carte et votre adresse de facturation à votre compte Google.</translation>
<translation id="4196861286325780578">&amp;Rétablir le déplacement</translation>
@@ -624,6 +634,7 @@
<translation id="4277028893293644418">Réinitialiser le mot de passe</translation>
<translation id="4279811152705618813">Votre <ph name="DEVICE_TYPE" /> est géré par <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Cette carte a été enregistrée dans votre compte Google}one{Cette carte a été enregistrée dans votre compte Google}other{Ces cartes ont été enregistrées dans votre compte Google}}</translation>
+<translation id="428847186335018806">Analysez les fichiers que vous téléchargez ou importez dans Chrome.</translation>
<translation id="42981349822642051">Développer</translation>
<translation id="4302965934281694568">Chou3 (enveloppe)</translation>
<translation id="4305817255990598646">Changer</translation>
@@ -653,7 +664,6 @@
<translation id="4435702339979719576">Carte postale)</translation>
<translation id="443673843213245140">L'utilisation d'un proxy est désactivée, mais une configuration de proxy explicite est spécifiée.</translation>
<translation id="445100540951337728">Cartes de débit acceptées</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> : Comportement suspect</translation>
<translation id="4466881336512663640">Les modifications apportées au formulaire seront perdues. Voulez-vous vraiment continuer ?</translation>
<translation id="4477350412780666475">Titre suivant</translation>
<translation id="4482953324121162758">Ce site ne sera pas traduit.</translation>
@@ -680,6 +690,7 @@
<translation id="4594403342090139922">&amp;Annuler la suppression</translation>
<translation id="4597348597567598915">Taille 8</translation>
<translation id="4600854749408232102">C6/C5 (enveloppe)</translation>
+<translation id="464342062220857295">Rechercher des fonctionnalités</translation>
<translation id="4646534391647090355">Accéder</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car son certificat de sécurité contient des erreurs. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
@@ -688,7 +699,6 @@
<translation id="4691835149146451662">Architecture-A (enveloppe)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Votre connexion a été interrompue</translation>
-<translation id="471880041731876836">Vous n'êtes pas autorisé à consulter ce site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Exécutez les diagnostics réseau de Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Actualiser les règles</translation>
<translation id="4728558894243024398">Plate-forme</translation>
@@ -716,7 +726,6 @@
<translation id="4816492930507672669">Ajuster à la page</translation>
<translation id="4850886885716139402">Afficher</translation>
<translation id="4854362297993841467">Mode de livraison non disponible. Choisissez-en un autre.</translation>
-<translation id="4858792381671956233">Une demande d'autorisation a été envoyée à tes parents pour la consultation de ce site</translation>
<translation id="4864052566555297930">Conseil de sécurité :</translation>
<translation id="4876188919622883022">Vue simplifiée</translation>
<translation id="4876305945144899064">Aucun nom d'utilisateur</translation>
@@ -740,7 +749,9 @@
<translation id="4974590756084640048">Réactiver les avertissements</translation>
<translation id="4984339528288761049">Prc5 (enveloppe)</translation>
<translation id="4989163558385430922">Tout afficher</translation>
+<translation id="4989542687859782284">Indisponible</translation>
<translation id="4989809363548539747">Ce plug-in n'est pas compatible.</translation>
+<translation id="4995216769782533993">Confirmez le code de sécurité pour partager les informations relatives à la carte avec ce site</translation>
<translation id="5002932099480077015">Si cette option est activée, Chrome enregistre une copie de votre carte sur cet appareil pour vous permettre de remplir plus rapidement les formulaires.</translation>
<translation id="5015510746216210676">Nom de la machine :</translation>
<translation id="5017554619425969104">Texte copié</translation>
@@ -769,6 +780,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Valider votre carte</translation>
<translation id="5135404736266831032">Gérer les adresses…</translation>
<translation id="5138227688689900538">Afficher moins</translation>
<translation id="5141240743006678641">Chiffrer les mots de passe synchronisés avec vos informations de connexion Google</translation>
@@ -795,6 +807,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (enveloppe)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Seul le propriétaire suivant peut définir les fonctionnalités qui s'appliquent à tout le système : <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Avertissement : Cette règle n'a pas été fusionnée comme indiqué dans la règle PolicyDictionaryMultipleSourceMergeList, car elle ne fait pas partie des règles de dictionnaire fusionnables.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Fin</translation>
@@ -818,7 +831,6 @@
<translation id="536296301121032821">Échec du stockage des paramètres de la règle.</translation>
<translation id="5371425731340848620">Mettre à jour la carte</translation>
<translation id="5377026284221673050">"Votre horloge est en retard.", "Votre horloge est en avance." ou "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Cette page pourrait tenter de récupérer vos informations personnelles ou d'endommager votre appareil à votre insu. Faites toujours attention lorsque vous saisissez des informations personnelles ou lorsque vous ouvrez des fichiers téléchargés.</translation>
<translation id="5384855140246857529">Connectez-vous et activez la synchronisation pour utiliser vos cartes sur tous vos appareils.</translation>
<translation id="5386426401304769735">La chaîne de certificats de ce site contient un certificat signé avec SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -832,6 +844,7 @@
<translation id="5457113250005438886">Non valide</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> autre}one{<ph name="CONTACT_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> autre}other{<ph name="CONTACT_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> autres}}</translation>
<translation id="5470861586879999274">&amp;Rétablir la modification</translation>
+<translation id="5473728911100096288">Si vous activez ces fonctionnalités obsolètes, sachez qu'elles seront abandonnées dans les futures versions.</translation>
<translation id="5478437291406423475">B6/C4 (enveloppe)</translation>
<translation id="5481076368049295676">Ce contenu peut essayer d'installer un logiciel dangereux sur votre appareil pour dérober ou supprimer vos informations. <ph name="BEGIN_LINK" />Je souhaite y accéder malgré tout.<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Ajouter une adresse valide</translation>
@@ -855,7 +868,6 @@
<translation id="5570825185877910964">Protéger le compte</translation>
<translation id="5571083550517324815">Enlèvement impossible à cette adresse. Sélectionnez-en une autre.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 en cours d'utilisation}one{# en cours d'utilisation}other{# en cours d'utilisation}})</translation>
-<translation id="5572851009514199876">Veuillez démarrer Chrome et vous connecter à votre compte pour que le navigateur puisse vérifier que vous êtes autorisé à accéder à ce site.</translation>
<translation id="5580958916614886209">Veuillez vérifier le mois d'expiration, puis réessayer</translation>
<translation id="5586446728396275693">Aucune adresse enregistrée</translation>
<translation id="5595485650161345191">Modifier l'adresse</translation>
@@ -863,6 +875,7 @@
<translation id="560412284261940334">Gestion non acceptée.</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Ce site est peut-être fictif ou frauduleux. Chrome vous recommande de le quitter immédiatement.</translation>
<translation id="5610142619324316209">Vérifier la connexion</translation>
<translation id="5610807607761827392">Vous pouvez gérer les cartes et les adresses dans les <ph name="BEGIN_LINK" />paramètres<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> vous a redirigé à de trop nombreuses reprises.</translation>
@@ -886,11 +899,11 @@
<translation id="5720705177508910913">Utilisateur actuel</translation>
<translation id="5728056243719941842">C5 (enveloppe)</translation>
<translation id="5730040223043577876">L'équipe Chrome vous recommande de réinitialiser votre mot de passe si vous l'avez réutilisé sur d'autres sites.</translation>
-<translation id="5732392974455271431">Tes parents peuvent te le débloquer</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Enregistrer une carte dans votre compte Google}one{Enregistrer une carte dans votre compte Google}other{Enregistrer des cartes dans votre compte Google}}</translation>
<translation id="5763042198335101085">Saisissez une adresse e-mail valide</translation>
<translation id="5765072501007116331">Sélectionnez une adresse pour consulter les modes et conditions de livraison disponibles</translation>
<translation id="5778550464785688721">Contrôle total des appareils MIDI</translation>
+<translation id="5781136890105823427">Test activé</translation>
<translation id="578305955206182703">Ambre</translation>
<translation id="57838592816432529">Couper le son</translation>
<translation id="5784606427469807560">Un problème est survenu lors de la validation de votre carte. Vérifiez votre connexion Internet, puis réessayez.</translation>
@@ -907,13 +920,16 @@
<translation id="5860033963881614850">Désactivé</translation>
<translation id="5863847714970149516">Il se peut que l'accès à la page suivante engendre des frais</translation>
<translation id="5866257070973731571">Ajouter un numéro de téléphone</translation>
+<translation id="5866898949289125849">Vous consultez une page d'outils pour les développeurs</translation>
<translation id="5869405914158311789">Ce site est inaccessible</translation>
<translation id="5869522115854928033">Mots de passe enregistrés</translation>
<translation id="5887400589839399685">Carte enregistrée</translation>
<translation id="5893752035575986141">Les cartes de crédit sont acceptées.</translation>
+<translation id="5895138241574237353">Redémarrer</translation>
<translation id="5901630391730855834">Jaune</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronisés)</translation>
<translation id="5916664084637901428">Activé</translation>
+<translation id="59174027418879706">Activé</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Enregistrer la carte dans votre compte Google ?</translation>
<translation id="5922853866070715753">Vous avez presque terminé !</translation>
@@ -947,6 +963,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Vous utilisez vos cartes sur tous vos appareils ?</translation>
<translation id="6059925163896151826">Appareils USB</translation>
+<translation id="6060009363608157444">Mode DnsOverHttps non valide.</translation>
<translation id="6080696365213338172">Vous avez accédé à du contenu à l'aide d'un certificat fourni par l'administrateur. Les données que vous fournissez à <ph name="DOMAIN" /> peuvent être interceptées par votre administrateur.</translation>
<translation id="6094273045989040137">Annoter</translation>
<translation id="610911394827799129">Votre compte Google conserve peut-être d'autres contenus d'historique de navigation sur la page <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -995,13 +1012,12 @@
<translation id="6404511346730675251">Modifier le favori</translation>
<translation id="6406765186087300643">C0 (enveloppe)</translation>
<translation id="6410264514553301377">Saisissez la date d'expiration et le code CVC pour <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Une demande d'autorisation a été envoyée à tes parents pour la consultation de ce site</translation>
<translation id="6415778972515849510">Chromium peut vous aider à protéger votre compte Google et à modifier votre mot de passe.</translation>
-<translation id="6417515091412812850">Impossible de vérifier si le certificat a été révoqué.</translation>
<translation id="6431585503458005759">Ne pas enregistrer</translation>
<translation id="6433490469411711332">Modifier les coordonnées</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> n'autorise pas la connexion.</translation>
<translation id="6434309073475700221">Annuler</translation>
+<translation id="6435221585574090192">Transmettez à votre administrateur les données sur les événements liés à la sécurité signalés par la protection contre les menaces de Chrome Enterprise. Il peut s'agir d'URL de pages, de noms et de métadonnées de fichiers, de votre nom d'utilisateur Chrome et de celui lié à votre appareil.</translation>
<translation id="6440503408713884761">Ignoré</translation>
<translation id="6446163441502663861">Kahu (enveloppe)</translation>
<translation id="6446608382365791566">Ajouter d'autres informations</translation>
@@ -1010,20 +1026,19 @@
<translation id="6465306955648956876">Gérer les mots de passe…</translation>
<translation id="647261751007945333">Règles relatives aux appareils</translation>
<translation id="6476284679642588870">Gérer les modes de paiement</translation>
-<translation id="6477321094435799029">Chrome a détecté un code inhabituel sur cette page et a bloqué cette dernière pour protéger vos informations personnelles (mots de passe, numéros de téléphone et de cartes de paiement).</translation>
<translation id="6489534406876378309">Lancer l'importation des plantages</translation>
<translation id="6499038740797743453">Réinitialiser le mot de passe ?</translation>
<translation id="6507833130742554667">Les cartes de crédit et de débit sont acceptées.</translation>
<translation id="650855688985305916">Oui, enregistrer</translation>
<translation id="6508722015517270189">Relancez Chrome</translation>
<translation id="6517596291481585650">Avertissement : Cette règle n'a pas été fusionnée en tant que liste comme indiqué, car ce n'est pas une liste.</translation>
+<translation id="6518133107902771759">Valider</translation>
<translation id="6521745193039995384">Inactive</translation>
<translation id="6529602333819889595">&amp;Rétablir la suppression</translation>
<translation id="6534179046333460208">Suggestions pour le Web physique</translation>
<translation id="6545864417968258051">Recherche Bluetooth</translation>
<translation id="6554795675067793129">Votre compte est géré par <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Rétablir</translation>
-<translation id="6563469144985748109">Votre responsable ne l'a pas encore autorisé</translation>
<translation id="6569060085658103619">Vous consultez actuellement une page d'extension</translation>
<translation id="6578796323535178455">C2 (enveloppe)</translation>
<translation id="6579990219486187401">Rose clair</translation>
@@ -1041,11 +1056,13 @@
<translation id="6643016212128521049">Effacer</translation>
<translation id="6644283850729428850">Cette règle est obsolète.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Aucun}=1{De 1 site (vous ne serez pas déconnecté de votre compte Google)}one{De # site (vous ne serez pas déconnecté de votre compte Google)}other{De # sites (vous ne serez pas déconnecté de votre compte Google)}}</translation>
+<translation id="6652101503459149953">Utiliser Windows Hello</translation>
<translation id="6657585470893396449">Mot de passe</translation>
<translation id="6670613747977017428">Retour à la sécurité.</translation>
<translation id="6671697161687535275">Supprimer la suggestion de saisie de formulaire de Chromium ?</translation>
<translation id="6685834062052613830">Déconnectez-vous et complétez la configuration.</translation>
<translation id="6689271823431384964">Chrome propose d'enregistrer vos cartes dans votre compte Google, car vous êtes connecté. Vous pouvez modifier ce comportement dans les paramètres. Le nom du titulaire de la carte provient de votre compte.</translation>
+<translation id="6707256370811247129">Analysez le contenu du cache et des fichiers que vous téléchargez ou importez dans Chrome.</translation>
<translation id="6710213216561001401">Précédent</translation>
<translation id="6710594484020273272">&lt;Saisissez le terme de recherche&gt;</translation>
<translation id="671076103358959139">Jeton d'inscription :</translation>
@@ -1053,10 +1070,10 @@
<translation id="6738516213925468394">Vos données ont été chiffrées avec votre <ph name="BEGIN_LINK" />phrase secrète de synchronisation<ph name="END_LINK" /> le <ph name="TIME" />. Saisissez-la pour lancer la synchronisation.</translation>
<translation id="674375294223700098">Erreur inconnue liée au certificat du serveur.</translation>
<translation id="6744009308914054259">En attendant d'avoir une connexion, vous pouvez consulter les téléchargements pour lire des articles hors connexion.</translation>
+<translation id="6747611005629681221">Attention : Fonctionnalités prochainement obsolètes !</translation>
<translation id="6753269504797312559">Valeur de la règle</translation>
<translation id="6757797048963528358">Votre appareil s'est mis en veille.</translation>
<translation id="6768213884286397650">Hagaki (carte postale)</translation>
-<translation id="6778737459546443941">Tes parents ne l'ont pas encore autorisé</translation>
<translation id="67862343314499040">Mauve</translation>
<translation id="6786747875388722282">Extensions</translation>
<translation id="6790428901817661496">Lire</translation>
@@ -1064,6 +1081,7 @@
<translation id="681021252041861472">Champ obligatoire</translation>
<translation id="6810899417690483278">ID de la personnalisation</translation>
<translation id="6825578344716086703">Vous avez tenté d'accéder à <ph name="DOMAIN" />, mais le serveur a présenté un certificat signé à l'aide d'un algorithme de signature faible (par exemple, SHA-1). Il est possible que le certificat fourni par le serveur ait été falsifié. Il se peut donc que le serveur ne soit pas celui auquel vous souhaitez accéder, et qu'il s'agisse d'une tentative de piratage.</translation>
+<translation id="6826370046007623921">Protection contre la perte de données</translation>
<translation id="6831043979455480757">Traduire</translation>
<translation id="6839929833149231406">Zone</translation>
<translation id="6852204201400771460">Actualiser l'application ?</translation>
@@ -1076,7 +1094,6 @@
<translation id="6891596781022320156">Le niveau de la règle n'est pas accepté.</translation>
<translation id="6895330447102777224">Carte validée</translation>
<translation id="6897140037006041989">Agent utilisateur</translation>
-<translation id="6903319715792422884">Aidez-nous à améliorer la navigation sécurisée en nous envoyant <ph name="BEGIN_WHITEPAPER_LINK" />des informations système et du contenu de pages<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utilisateur : </translation>
<translation id="6934672428414710184">Ce nom provient de votre compte Google</translation>
<translation id="6944692733090228304">Vous avez saisi votre mot de passe sur un site qui n'est pas géré par <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Pour protéger votre compte, ne réutilisez pas ce mot de passe dans d'autres applications ni sur d'autres sites.</translation>
@@ -1121,6 +1138,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> autre}one{<ph name="PAYMENT_METHOD_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> autre}other{<ph name="PAYMENT_METHOD_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> autres}}</translation>
<translation id="7153618581592392745">Lavande</translation>
<translation id="717330890047184534">Identifiant GAIA : </translation>
+<translation id="7174545416324379297">Valeurs fusionnées</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> autre}one{<ph name="SHIPPING_OPTION_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> autre}other{<ph name="SHIPPING_OPTION_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> autres}}</translation>
<translation id="7177397715882417099">Le serveur auquel vous accédez, <ph name="ORIGIN" />, a exigé qu'une règle de sécurité soit appliquée à toutes les demandes qu'il reçoit. Cependant, au lieu d'émettre une règle, il a redirigé le navigateur vers une autre destination, ce qui empêche ce dernier de répondre à votre demande pour <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Enregistrer et renseigner les modes de paiement</translation>
@@ -1155,6 +1173,7 @@ Informations supplémentaires :
<translation id="7320336641823683070">Aide à la connexion</translation>
<translation id="733354035281974745">Ignorer le compte local de l'appareil</translation>
<translation id="7334320624316649418">&amp;Rétablir la réorganisation</translation>
+<translation id="7337706099755338005">Non disponible sur votre plate-forme</translation>
<translation id="733923710415886693">Le certificat du serveur n'a pas été communiqué tel que le prévoient les règles de transparence des certificats.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Affilié :</translation>
@@ -1186,7 +1205,6 @@ Informations supplémentaires :
<translation id="7440140511386898319">Parcourir hors connexion</translation>
<translation id="7441627299479586546">Objet de la règle incorrect.</translation>
<translation id="7442725080345379071">Orange clair</translation>
-<translation id="7444046173054089907">Ce site est bloqué</translation>
<translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /> sur ce problème.</translation>
<translation id="7455133967321480974">Utiliser le paramètre global par défaut ("Bloquer")</translation>
@@ -1208,9 +1226,9 @@ Informations supplémentaires :
<translation id="7538364083937897561">A2 (enveloppe)</translation>
<translation id="7542403920425041731">Une fois la validation terminée, les informations relatives à votre carte seront partagées avec ce site.</translation>
<translation id="7542995811387359312">La saisie automatique des numéros de carte de paiement est désactivée, car la connexion utilisée par ce formulaire n'est pas sécurisée.</translation>
-<translation id="7543525346216957623">Demande à tes parents</translation>
<translation id="7548892272833184391">Corriger les erreurs de connexion</translation>
<translation id="7549584377607005141">Pour s'afficher correctement, cette page Web a besoin des données que vous avez saisies précédemment. Vous pouvez envoyer de nouveau ces données. Cependant, en procédant ainsi, vous répéterez toute action déjà effectuée sur cette page.</translation>
+<translation id="7550637293666041147">Votre nom d'utilisateur Chrome et celui lié à votre appareil</translation>
<translation id="7552846755917812628">Essayez les astuces suivantes :</translation>
<translation id="7554791636758816595">Nouvel onglet</translation>
<translation id="7564049878696755256">Vous risquez de perdre l'accès à votre compte <ph name="ORG_NAME" /> ou d'être victime d'usurpation d'identité. L'équipe Chrome vous recommande de modifier votre mot de passe maintenant.</translation>
@@ -1225,6 +1243,7 @@ Informations supplémentaires :
<translation id="7610193165460212391">La valeur <ph name="VALUE" /> est hors limites.</translation>
<translation id="7613889955535752492">Date d'expiration : <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Vous disposez déjà de données chiffrées à l'aide d'une autre version de votre mot de passe de compte Google. Veuillez saisir celui-ci ci-dessous.</translation>
+<translation id="7625784245512586808">Protection contre les menaces de Chrome Enterprise</translation>
<translation id="7633909222644580952">Données relatives aux performances et rapports d'erreur</translation>
<translation id="7637571805876720304">Supprimer les données de carte de paiement de Chromium ?</translation>
<translation id="7638605456503525968">Ports série</translation>
@@ -1237,7 +1256,6 @@ Informations supplémentaires :
<translation id="7668654391829183341">Appareil inconnu</translation>
<translation id="7669271284792375604">Des individus malveillants à l'œuvre sur ce site pourraient vous inciter à installer des programmes qui nuisent à votre confort de navigation (par exemple, en changeant votre page d'accueil ou en affichant des annonces supplémentaires sur les sites que vous consultez.</translation>
<translation id="7676643023259824263">Rechercher le texte du presse-papier "<ph name="TEXT" />"</translation>
-<translation id="7679176406634891508">Plate-forme et cloud</translation>
<translation id="7681101578153515023">Changer de moteur de recherche</translation>
<translation id="7682287625158474539">Adresse de livraison</translation>
<translation id="7687186412095877299">Saisit automatiquement les informations correspondant aux modes de paiement enregistrés</translation>
@@ -1252,7 +1270,6 @@ Informations supplémentaires :
<translation id="7723047071702270851">Modifier la carte</translation>
<translation id="774634243536837715">Contenu dangereux bloqué.</translation>
<translation id="7752995774971033316">Non géré</translation>
-<translation id="7755287808199759310">Ton parent peut te le débloquer</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Il est possible qu'un pare-feu ou un logiciel antivirus ait bloqué la connexion.</translation>
<translation id="7759163816903619567">Domaine d'affichage : </translation>
@@ -1296,7 +1313,6 @@ Informations supplémentaires :
<translation id="8004582292198964060">Navigateur</translation>
<translation id="8009225694047762179">Gérer les mots de passe</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Cette carte et l'adresse de facturation associée seront enregistrées. Vous pourrez vous en servir lorsque vous serez connecté à <ph name="USER_EMAIL" />.}one{Cette carte et l'adresse de facturation associée seront enregistrées. Vous pourrez vous en servir lorsque vous serez connecté à <ph name="USER_EMAIL" />.}other{Ces cartes et les adresses de facturation associées seront enregistrées. Vous pourrez vous en servir lorsque vous serez connecté à <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Impossible de joindre vos parents pour le moment. Veuillez réessayer.</translation>
<translation id="8025119109950072390">Des individus malveillants à l'œuvre sur ce site pourraient vous inciter à effectuer des opérations dangereuses, telles que l'installation d'un logiciel ou la révélation d'informations personnelles (par exemple des mots de passe, des numéros de téléphone ou des numéros de carte de paiement).</translation>
<translation id="8034522405403831421">Cette page est rédigée en <ph name="SOURCE_LANGUAGE" />. Voulez-vous la traduire en <ph name="TARGET_LANGUAGE" /> ?</translation>
<translation id="8035152190676905274">Stylo</translation>
@@ -1307,6 +1323,7 @@ Informations supplémentaires :
<translation id="8041940743680923270">Utiliser le paramètre global par défaut ("Demander")</translation>
<translation id="8042918947222776840">Sélectionner un mode d'enlèvement</translation>
<translation id="8057711352706143257">Le logiciel "<ph name="SOFTWARE_NAME" />" n'est pas configuré correctement. En général, la désinstallation de "<ph name="SOFTWARE_NAME" />" permet de remédier à la situation. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Vous n'aurez plus besoin de saisir le code de sécurité de votre carte</translation>
<translation id="8066955247577885446">Désolé, un problème est survenu.</translation>
<translation id="8074253406171541171">10x13 (enveloppe)</translation>
<translation id="8078141288243656252">Impossible d'ajouter des annotations si le document a pivoté</translation>
@@ -1337,6 +1354,7 @@ Informations supplémentaires :
<translation id="8211406090763984747">La connexion est sécurisée</translation>
<translation id="8218327578424803826">Position attribuée : </translation>
<translation id="8220146938470311105">C7/C6 (enveloppe)</translation>
+<translation id="8220639454292072926">Rapports d'entreprise</translation>
<translation id="8225771182978767009">La personne qui a configuré cet ordinateur a choisi de bloquer ce site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Ouvrir la page dans un nouvel onglet de navigation privée</translation>
@@ -1391,23 +1409,23 @@ Informations supplémentaires :
<translation id="8508648098325802031">Icône Recherche</translation>
<translation id="8522552481199248698">Chrome peut vous aider à protéger votre compte Google et à modifier votre mot de passe.</translation>
<translation id="8543181531796978784">Vous pouvez <ph name="BEGIN_ERROR_LINK" />signaler un problème de détection<ph name="END_ERROR_LINK" />. Si vous avez compris les risques auxquels vous vous exposez, vous pouvez <ph name="BEGIN_LINK" />consulter ce site dangereux<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Des questions ? Contactez la personne qui supervise votre profil.</translation>
<translation id="8553075262323480129">La traduction a échoué, car nous n'avons pas pu déterminer la langue de la page.</translation>
<translation id="8557066899867184262">Le code CVC figure au recto de votre carte.</translation>
<translation id="8559762987265718583">Impossible d'établir une connexion privée à <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> : la date et l'heure de votre appareil (<ph name="DATE_AND_TIME" />) sont incorrectes.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> site suspect</translation>
<translation id="8564985650692024650">L'équipe Chromium vous recommande de réinitialiser votre mot de passe <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> si vous l'avez réutilisé sur d'autres sites.</translation>
<translation id="8571890674111243710">Traduction de la page en <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Saisir num tél</translation>
-<translation id="859285277496340001">Le certificat n'indique aucun mécanisme permettant de vérifier s'il a été révoqué.</translation>
<translation id="860043288473659153">Nom du titulaire de la carte</translation>
<translation id="861775596732816396">Taille 4</translation>
-<translation id="8620436878122366504">Tes parents ne l'ont pas encore autorisé</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Enregistrer cette carte sur cet appareil</translation>
<translation id="8626112503828625890">Enregistrer les informations de facturation dans le compte Google ?</translation>
+<translation id="8647750283161643317">Rétablir tous les tests par défaut</translation>
<translation id="8663226718884576429">Récapitulatif de la commande, <ph name="TOTAL_LABEL" />, détails supplémentaires</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, réponse, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponible</translation>
<translation id="8703575177326907206">Votre connexion à <ph name="DOMAIN" /> n'est pas chiffrée.</translation>
<translation id="8718314106902482036">Paiement non finalisé</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, suggestion de recherche</translation>
@@ -1418,6 +1436,7 @@ Informations supplémentaires :
<translation id="8738058698779197622">Afin d'établir une connexion sécurisée, votre horloge doit être réglée correctement. Les certificats permettant aux sites Web de s'identifier sont en effet valides pendant une période précise. Si l'horloge de votre appareil est incorrecte, Chromium n'est pas en mesure de vérifier la validité des certificats.</translation>
<translation id="8740359287975076522">L'&lt;abbr id="dnsDefinition"&gt;adresse DNS&lt;/abbr&gt; de <ph name="HOST_NAME" /> est introuvable. Identification du problème…</translation>
<translation id="874846938927089722">Cartes de crédit et cartes prépayées acceptées</translation>
+<translation id="874918643257405732">Ajouter cet onglet aux favoris</translation>
<translation id="8759274551635299824">Carte arrivée à expiration</translation>
<translation id="8761567432415473239">La fonctionnalité de navigation sécurisée a récemment permis de <ph name="BEGIN_LINK" />détecter des programmes dangereux<ph name="END_LINK" /> sur le site <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Périphérique USB</translation>
@@ -1447,6 +1466,7 @@ Informations supplémentaires :
<translation id="8938939909778640821">Cartes de crédit et cartes prépayées acceptées</translation>
<translation id="8943282376843390568">Citron vert</translation>
<translation id="8957210676456822347">Autorisation du portail captif</translation>
+<translation id="8962950042226115166">Site suspect</translation>
<translation id="8968766641738584599">Enregistrer la carte</translation>
<translation id="8971063699422889582">Le certificat du serveur a expiré.</translation>
<translation id="8975012916872825179">Y compris les numéros de téléphone, les adresses e-mail et les adresses de livraison</translation>
@@ -1469,24 +1489,24 @@ Informations supplémentaires :
<translation id="9035022520814077154">Erreur liée à la sécurité</translation>
<translation id="9038649477754266430">Utiliser un service de prédiction pour charger les pages plus rapidement</translation>
<translation id="9039213469156557790">De plus, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer le comportement de cette page.</translation>
+<translation id="9044359186343685026">Utiliser Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Vous avez tenté de contacter <ph name="DOMAIN" />, mais le certificat présenté par le serveur est incorrect.</translation>
<translation id="9050666287014529139">Phrase secrète</translation>
<translation id="9065203028668620118">Modifier</translation>
<translation id="9065745800631924235">Recherche sur "<ph name="TEXT" />" dans l'historique</translation>
<translation id="9069693763241529744">Bloqué par une extension</translation>
-<translation id="9076283476770535406">Il est possible qu'il comporte du contenu réservé aux adultes</translation>
<translation id="9076630408993835509">Ce navigateur n'est géré par aucune entreprise ni aucune autre organisation. Il se peut que l'activité sur cet appareil soit gérée en dehors de Chrome. <ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Veuillez fournir d'autres informations</translation>
<translation id="9080712759204168376">Récapitulatif de la commande</translation>
<translation id="9089260154716455634">Règle en heures creuses :</translation>
<translation id="9095388113577226029">Plus de langues…</translation>
+<translation id="9098981495403789647">Votre administrateur a activé la protection contre les menaces de Chrome Enterprise dans votre navigateur. Cette fonctionnalité a accès à certaines de vos données.</translation>
<translation id="9103872766612412690">Un chiffrement est normalement utilisé sur le site <ph name="SITE" /> pour protéger vos informations. Lors de la dernière tentative de connexion de Chromium au site <ph name="SITE" />, des identifiants inhabituels et incorrects ont été retournés. Il est possible qu'un individu malveillant tente de se faire passer pour <ph name="SITE" /> ou qu'un écran de connexion Wi-Fi ait interrompu la connexion. Vos informations restent sécurisées, car nous avons arrêté la connexion avant l'échange des données.</translation>
<translation id="9106062320799175032">Ajouter une adresse de facturation</translation>
<translation id="9114524666733003316">Validation de la carte…</translation>
<translation id="9128870381267983090">Se connecter au réseau</translation>
<translation id="9137013805542155359">Afficher l'original</translation>
-<translation id="9137248913990643158">Veuillez démarrer Chrome et vous connecter à votre compte avant d'utiliser cette application</translation>
<translation id="9141013498910525015">Gérer les adresses</translation>
<translation id="9148088599418889305">Sélectionner un mode de livraison</translation>
<translation id="9148507642005240123">&amp;Annuler la modification</translation>
diff --git a/chromium/components/strings/components_strings_gu.xtb b/chromium/components/strings/components_strings_gu.xtb
index 528ff89b41c..c776c291985 100644
--- a/chromium/components/strings/components_strings_gu.xtb
+++ b/chromium/components/strings/components_strings_gu.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">અનુક્રમણિકા-5x8</translation>
<translation id="1088860948719068836">કાર્ડ પર નામ ઉમેરો</translation>
<translation id="1089439967362294234">પાસવર્ડ બદલો</translation>
+<translation id="1096545575934602868">આ ફીલ્ડમાં <ph name="MAX_ITEMS_LIMIT" /> કરતાં વધારે એન્ટ્રી હોવી જોઈએ નહી. વધારાની બધી એન્ટ્રીને કાઢી નાખવામાં આવશે.</translation>
<translation id="109743633954054152">Chrome સેટિંગમાં પાસવર્ડ મેનેજ કરો</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> નો હંમેશાં અનુવાદ કરો</translation>
<translation id="1107591249535594099">જો ચેક કરેલું હોય, તો ઝડપથી ફોર્મ ભરવા માટે Chrome આ ઉપકરણ પર તમારા કાર્ડની એક કૉપિ સંગ્રહશે.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> ની <ph name="BEGIN_LINK" />કેશ કરેલ કૉપિ<ph name="END_LINK" /> ઍક્સેસ કરો</translation>
<translation id="1156303062776767266">તમે સ્થાનિક અથવા શેર કરેલી ફાઇલ જોઈ રહ્યાં છો</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> એ અનપેક્ષિત રીતે કનેક્શન બંધ કર્યું.</translation>
+<translation id="115926840831309955">તમારું CVC ચેક કરો અને ફરીથી પ્રયાસ કરો અથવા સમાપ્તિ તારીખ અપડેટ કરો</translation>
<translation id="1161325031994447685">વાઇ-ફાઇ સાથે ફરીથી કનેક્ટ કરીને</translation>
<translation id="1165039591588034296">ભૂલ</translation>
<translation id="1175364870820465910">&amp;છાપો...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"તમારા કમ્પ્યુટરમાંનું સૉફ્ટવેર Chromeને સુરક્ષિત રીતે વેબ સાથે કનેક્ટ થવાથી અટકાવે છે" (માત્ર Windows કમ્પ્યુટર)</translation>
<translation id="1294154142200295408">આદેશ વાક્યમાં વિવિધતા</translation>
<translation id="129553762522093515">તાજેતરમાં બંધ કરેલા</translation>
+<translation id="1298536327547837046">માલવેરની તપાસ કરવી</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />તમારી કૂકીઝને સાફ કરવાનો પ્રયાસ કરો<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">નાપસંદ કરેલી સુવિધાઓ</translation>
<translation id="1320233736580025032">Prc1 (એન્વલપ)</translation>
<translation id="132301787627749051">ક્લિપબોર્ડ છબી શોધો</translation>
<translation id="1323433172918577554">વધુ બતાવો</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google શીટ</translation>
<translation id="1527263332363067270">કનેક્શનની રાહ જોઈ રહ્યાં છીએ...</translation>
<translation id="1529521330346880926">10x15 (એન્વલપ)</translation>
+<translation id="1530707389502320859">તમે હમણાં જે સાઇટની મુલાકાત લેવાનો પ્રયાસ કર્યો તે બનાવટી હોય એવું લાગે છે. હુમલાખોરો URLમાં સરળતાથી ન જોઈ શકાય એવા મામૂલી ફેરફારો કરીને કેટલીક વખત સાઇટની નકલ કરે છે.</translation>
<translation id="1531205177818805254">એક્સેક</translation>
<translation id="1532118530259321453">આ પેજ કહે છે કે</translation>
<translation id="153384715582417236">હમણાં માટે બસ આટલું પૂરતું છે</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">એનોટેટ કરવા માટે દસ્તાવેજ ઘણો મોટો છે</translation>
-<translation id="1721312023322545264">આ સાઇટની મુલાકાત લેવા માટે તમને <ph name="NAME" /> ની પરવાનગીની જરૂર છે</translation>
<translation id="1721424275792716183">* ફીલ્ડ આવશ્યક છે</translation>
<translation id="1727741090716970331">માન્ય કાર્ડ નંબર ઉમેરો</translation>
<translation id="1728677426644403582">તમે વેબ પેજનો સ્રોત જોઈ રહ્યાં છો</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">તમે મુલાકાત લો તે વેબસાઇટ અને તેના પર વિતાવેલો સમય</translation>
<translation id="1826516787628120939">તપાસી રહ્યાં છે</translation>
<translation id="1834321415901700177">આ સાઇટમાં હાનિકારક પ્રોગ્રામ્સ છે</translation>
+<translation id="1838374766361614909">શોધ સાફ કરો</translation>
<translation id="1839551713262164453">ભૂલના લીધે નીતિ મૂલ્યોની માન્યતા નિષ્ફળ થઈ</translation>
<translation id="1842969606798536927">ચુકવણી કરો</translation>
<translation id="1871208020102129563">પ્રૉક્સી નક્કી કરેલા પ્રૉક્સી સર્વરનો ઉપયોગ કરવા માટે સેટ કરેલી છે, .pac સ્ક્રિપ્ટ URL નથી.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">સૂચિ સંકુચિત કરો</translation>
<translation id="1898423065542865115">ફિલ્ટરિંગ</translation>
<translation id="1914326953223720820">સેવાને અનઝિપ કરો</translation>
+<translation id="1915697529809968049">CVCને બદલે Touch IDનો ઉપયોગ કરીએ?</translation>
<translation id="1916770123977586577">આ સાઇટ પર તમારી અપડેટ કરેલ સેટિંગ્સ લાગુ પાડવા માટે, આ પેજને ફરીથી લોડ કરો</translation>
<translation id="1919345977826869612">જાહેરાતો</translation>
<translation id="1919367280705858090">ભૂલના ચોક્કસ સંદેશ વડે સહાય મેળવો</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> બુકમાર્ક્સ</translation>
<translation id="1973335181906896915">અનુક્રમાંકન ભૂલ</translation>
<translation id="1974060860693918893">વિગતવાર</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />તમે મુલાકાત લો તે કેટલાક પેજના URLs, સિસ્ટમ વિશેની સીમિત માહિતી અને પેજનું કેટલુંક કન્ટેન્ટ<ph name="END_WHITEPAPER_LINK" /> Googleને મોકલીને Chromeની સુરક્ષા વધુ સારી બનાવવામાં સહાય કરો. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">ફર્મવેયર વર્ઝન</translation>
<translation id="1981206234434200693">Chromeના બ્રાઉઝિંગ ઇતિહાસનો ડેટા સાફ કરો</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{અને 1 વધુ}one{અને # વધુ}other{અને # વધુ}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">એક માન્ય સમાપ્તિ વર્ષ દાખલ કરો</translation>
<translation id="2212735316055980242">નીતિ મળી નથી</translation>
<translation id="2213606439339815911">પ્રવિષ્ટિઓનું આનયન કરી રહ્યાં છે...</translation>
+<translation id="2215727959747642672">ફાઇલમાં ફેરફાર કરવો</translation>
<translation id="2218879909401188352">હાલમાં હુમલાખોરો <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> પર જોખમકારક ઍપ્લિકેશન ઇન્સ્ટૉલ કરી શકે છે જે તમારા ઉપકરણને નુકસાન પહોંચાડે છે, તમારા મોબાઇલ બિલમાં છુપાયેલા ચાર્જ ઉમેરી શકે છે અથવા તમારી વ્યક્તિગત માહિતી ચોરી શકે છે. <ph name="BEGIN_LEARN_MORE_LINK" />વધુ જાણો<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ઇન્ટરનેટ ઍક્સેસ નથી</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />ડાયગ્નોસ્ટિક્સ ઍપ્લિકેશન<ph name="END_LINK" />નો ઉપયોગ કરીને તમારું કનેક્શન ઠીક કરો</translation>
<translation id="2239100178324503013">હમણાં મોકલો</translation>
+<translation id="2248949050832152960">WebAuthnનો ઉપયોગ કરો</translation>
<translation id="225207911366869382">આ નીતિ માટે આ મૂલ્યને નાપસંદ કરેલું છે.</translation>
<translation id="2257315177824333709">માફ કરશો, અત્યારે તમારું કાર્ડ સાચવી શકતા નથી</translation>
<translation id="2262243747453050782">HTTP ભૂલ</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">અમાન્ય શોધ URL.</translation>
<translation id="2482878487686419369">સૂચનાઓ</translation>
<translation id="248348093745724435">મશીન નીતિઓ</translation>
-<translation id="2485387744899240041">તમારા ડિવાઇસ અને બ્રાઉઝર માટે વપરાશકર્તાનું નામ</translation>
<translation id="2491120439723279231">સર્વરના પ્રમાણપત્રમાં ભૂલો છે.</translation>
<translation id="2493640343870896922">લેટર-પ્લસ</translation>
<translation id="2495083838625180221">JSON વિશ્લેષક</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">પાછા જાઓ</translation>
<translation id="2503184589641749290">સ્વીકૃત ડેબિટ અને પ્રીપેઇડ કાર્ડ</translation>
<translation id="2505268675989099013">એકાઉન્ટ સુરક્ષિત કરો</translation>
+<translation id="2515335152965840738">અવગણો</translation>
<translation id="2515629240566999685">તમારા વિસ્તારમાં સિગ્નલ તપાસીને</translation>
<translation id="2523886232349826891">કાર્ડની માહિતીને માત્ર આ ડિવાઇસ પર સાચવવામાં આવી છે</translation>
<translation id="2524461107774643265">વધુ માહિતી ઉમેરો</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">સબમિટ કરો</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{એકપણ નહીં}=1{1 પાસવર્ડ (<ph name="DOMAIN_LIST" /> માટે)}=2{2 પાસવર્ડ (<ph name="DOMAIN_LIST" /> માટે)}one{# પાસવર્ડ (<ph name="DOMAIN_LIST" /> માટે)}other{# પાસવર્ડ (<ph name="DOMAIN_LIST" /> માટે)}}</translation>
<translation id="2666117266261740852">અન્ય ટૅબ અથવા ઍપ્લિકેશનો બંધ કરો</translation>
-<translation id="267371737713284912">છેલ્લો ફેરફાર રદ કરવા માટે <ph name="MODIFIER_KEY_DESCRIPTION" /> દબાવો</translation>
<translation id="2674170444375937751">શું તમે ખરેખર તમારા ઇતિહાસમાંથી આ પેજને ડિલીટ કરવા માંગો છો?</translation>
<translation id="2676271551327853224">રૉક-8K</translation>
<translation id="2677748264148917807">છોડો</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">મૂલ્ય ફોર્મેટથી મેળ ખાતું નથી.</translation>
<translation id="2705137772291741111">આ સાઇટની સાચવેલ (કૅશ કરેલ) કૉપિ વાંચવા યોગ્ય ન હતી.</translation>
<translation id="2709516037105925701">સ્વતઃભરો</translation>
-<translation id="2712173769900027643">પરવાનગી માગો</translation>
<translation id="2713444072780614174">શ્વેત</translation>
<translation id="2720342946869265578">નજીકના</translation>
<translation id="2721148159707890343">વિનંતી સફળ થઇ</translation>
<translation id="2728127805433021124">સર્વરનું પ્રમાણપત્ર એક નબળા સહી ઍલ્ગોરિધમનો ઉપયોગ કરીને સહીિત કરેલું છે.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />કનેક્ટિવિટી ડાયગ્નોસ્ટિક્સ ચલાવી રહ્યાં છે<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">આ સુવિધાઓ ચાલુ કરવાથી, તમે બ્રાઉઝરનો ડેટા ગુમાવશો અથવા
+ તમારી સુરક્ષા કે પ્રાઇવસી સાથે સમાધાન કરશો. ચાલુ કરેલી સુવિધાઓ આ બ્રાઉઝરના બધા
+ વપરાશકર્તાઓ માટે લાગુ છે.</translation>
<translation id="2735043616039983645">આ નીતિ માટે વિરોધાભાસ મૂલ્ય ધરાવતા એકથી વધુ સૉર્સ ઉપલબ્ધ છે!</translation>
<translation id="2738330467931008676">પિકઅપ માટેનું સરનામું પસંદ કરો</translation>
<translation id="2740531572673183784">બરાબર, સમજાઇ ગયું</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">કનેક્શન ફરીથી સેટ થયું.</translation>
<translation id="2788784517760473862">સ્વીકૃત ક્રેડિટ કાર્ડ</translation>
<translation id="2792012897584536778">આ ડિવાઇસના વ્યવસ્થાપકોએ સુરક્ષા પ્રમાણપત્રો સેટ અપ કર્યા છે, જેના કારણે તેમને તમે મુલાકાત લો તે વેબસાઇટનું કન્ટેન્ટ જોવાની મંજૂરી મળી શકે છે.</translation>
-<translation id="2794233252405721443">સાઇટ અવરોધિત કરી</translation>
<translation id="2799020568854403057">સાઇટ આગળ હાનિકારક ઍપ્લિકેશનો ધરાવે છે</translation>
<translation id="2799223571221894425">ફરીથી લોંચ કરો</translation>
<translation id="2803306138276472711">Google Safe Browsing ને તાજેતરમાં <ph name="SITE" /> પર <ph name="BEGIN_LINK" />મૉલવેર મળ્યું<ph name="END_LINK" />. વેબસાઇટ્સ કે જે સામાન્ય રીતે સુરક્ષિત છે તે ક્યારેક મૉલવેરથી દૂષિત હોય છે.</translation>
+<translation id="2815364696811431560">સાઇટ છોડી દો</translation>
<translation id="2824775600643448204">સરનામું અને શોધ બાર</translation>
<translation id="2826760142808435982">કનેક્શન <ph name="CIPHER" />નો ઉપયોગ કરીને એન્ક્રિપ્ટ અને પ્રમાણિત કરેલુંં છે અને મુખ્ય એક્સચેન્જ મેકેનિઝ્મ તરીકે <ph name="KX" />નો ઉપયોગ કરે છે.</translation>
<translation id="2835170189407361413">ફોર્મ સાફ કરો</translation>
<translation id="2847118875340931228">છુપી વિન્ડો ખોલો</translation>
<translation id="2850739647070081192">આમંત્રણ (એન્વલપ)</translation>
-<translation id="2851634818064021665">આ સાઇટની મુલાકાત લેવા માટે તમને પરનાવગીની જરૂર છે</translation>
<translation id="2856444702002559011">હુમલાખોરો કદાચ <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />માંથી તમારી માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ, સંદેશા અથવા ક્રેડિટ કાર્ડ) ચોરવાનો પ્રયાસ કરી રહ્યાં હોઈ શકે છે. <ph name="BEGIN_LEARN_MORE_LINK" />વધુ જાણો<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">કાર્ડ સાચવીએ?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">જો સક્ષમ કરેલું હોય, તો ઝડપથી ફોર્મ ભરવા માટે Chromium આ ઉપકરણ પર તમારા કાર્ડની એક કૉપિ સંગ્રહિત કરશે.</translation>
<translation id="2985398929374701810">એક માન્ય સરનામું દાખલ કરો</translation>
<translation id="2986368408720340940">આ પિકઅપ પદ્ધતિ ઉપલબ્ધ નથી. કોઈ ભિન્ન પદ્ધતિ અજમાવો.</translation>
+<translation id="2987034854559945715">કોઈ મેળ ખાતી સુવિધા નથી</translation>
<translation id="2991174974383378012">વેબસાઇટ્સ સાથે શેર કરવું</translation>
<translation id="2991571918955627853">તમે હમણાં <ph name="SITE" />ની મુલાકાત લઈ શકતાં નથી કારણ કે તે વેબસાઇટ HSTSનો ઉપયોગ કરે છે. નેટવર્કમાં ભૂલ આવવી અને હુમલા થવા સામાન્ય રીતે અસ્થાયી હોય છે, તેથી આ પેજ સંભવિત રૂપે થોડા સમય પછી કાર્ય કરશે.</translation>
<translation id="3005723025932146533">સાચવેલી કૉપિ બતાવો</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">ખોટો નીતિ પ્રકાર</translation>
<translation id="3037605927509011580">અરર કંઇક ભુલ થઇ!</translation>
<translation id="3041612393474885105">પ્રમાણપત્ર માહિતી</translation>
+<translation id="3057676462092457419">DnsOverHttps મોડ <ph name="SECURE_DNS_MODE_SECURE" />ને હજુ પણ સપોર્ટ અપાતો નથી, મોડને <ph name="SECURE_DNS_MODE_OFF" /> પર સેટ કરવામાં આવ્યો છે.</translation>
<translation id="3060227939791841287">C9 (એન્વલપ)</translation>
<translation id="3061707000357573562">પૅચ સેવા</translation>
<translation id="3064966200440839136">બાહ્ય ઍપ્લિકેશન મારફતે ચુકવણી કરવા માટે છુપો મોડ છોડી રહ્યાં છીએ. તો ચાલુ રાખીએ?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> પર <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">ચુકવણી રદ કરો</translation>
<translation id="3207960819495026254">બુકમાર્ક કરેલ</translation>
+<translation id="3209034400446768650">પેજ કદાચ નાણાં વસૂલી શકે છે</translation>
<translation id="3225919329040284222">સર્વર એક પ્રમાણપત્ર પ્રસ્તુત કરે છે જે બિલ્ટ-ઇન અપેક્ષાઓ સાથે મેળ ખાતું નથી. આ અપેક્ષાઓમાં તમને સુરક્ષિત રાખવા માટે અમુક ચોક્કસ, ઉચ્ચ-સુરક્ષા વેબસાઇટ્સનો સમાવેશ થાય છે.</translation>
<translation id="3226128629678568754">પૃષ્ઠને લોડ કરવા માટે જરૂરી ડેટા ફરીથી સબમિટ કરવા માટે ફરીથી લોડ કરો બટન દબાવો.</translation>
<translation id="3227137524299004712">માઇક્રોફોન</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">તમારા ડિવાઇસ અને બ્રાઉઝર વિશે વર્ઝન માહિતી</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> માટે CVC દાખલ કરો</translation>
<translation id="3234666976984236645">હંમેશાં આ સાઇટ પરનું મહત્ત્વનું કન્ટેન્ટ શોધો</translation>
-<translation id="3254409185687681395">આ પૃષ્ઠને બુકમાર્ક કરો</translation>
<translation id="3270847123878663523">&amp;પુનઃક્રમાંકિત કરવું પૂર્વવત્ કરો</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">કાર્ડ પર નામ ઉમેરો</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">બિલિંગ સરનામું ઉમેરો</translation>
<translation id="3324983252691184275">કિરમજી</translation>
<translation id="3338095232262050444">સુરક્ષિત</translation>
-<translation id="3345135638360864351">આ સાઇટને ઍક્સેસ કરવાની તમારી વિનંતી <ph name="NAME" /> ને મોકલી શકાઈ નથી. કૃપા કરીને ફરી પ્રયાસ કરો.</translation>
<translation id="3355823806454867987">પ્રૉક્સી સેટિંગ બદલો...</translation>
<translation id="3361596688432910856">Chrome નિમ્નલિખિત માહિતી <ph name="BEGIN_EMPHASIS" />સાચવશે નહીં<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" /> <ph name="LIST_ITEM" />તમારો બ્રાઉઝિંગ ઇતિહાસ
@@ -477,18 +487,15 @@
<translation id="3462200631372590220">વિગતવાર છુપાવો</translation>
<translation id="3467763166455606212">કાર્ડધારકનું નામ આવશ્યક છે</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, હાલમાં ખુલ્લું છે, ખુલ્લા ટૅબ પર સ્વિચ કરવા માટે ટૅબ પછી Enter દબાવો</translation>
-<translation id="3479539252931486093">શું આ અનપેક્ષિત હતું? <ph name="BEGIN_LINK" />અમને જણાવો<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">હમણાં નહીં</translation>
<translation id="3484560055331845446">તમે તમારા Google એકાઉન્ટનો ઍક્સેસ ગુમાવી શકો છો. Chrome તમને હમણાં જ તમારો પાસવર્ડ બદલવાનો સુઝાવ આપે છે. તમને સાઇન ઇન કરવા માટે કહેવામાં આવશે.</translation>
<translation id="3495081129428749620">પેજ
<ph name="PAGE_TITLE" />માં શોધો</translation>
-<translation id="3498215018399854026">અમે આ પળે તમારા વાલી સુધી પહોંચી શક્યાં નથી. કૃપા કરીને ફરી પ્રયાસ કરો.</translation>
<translation id="3512163584740124171">આ નીતિને અવગણવામાં આવે છે કારણ કે સમાન નીતિ ગ્રૂપની બીજી નીતિ ઉચ્ચ પ્રાથમિકતા ધરાવે છે.</translation>
<translation id="3528171143076753409">સર્વરનું પ્રમાણપત્ર વિશ્વસનીય નથી.</translation>
<translation id="3528485271872257980">ઘાટો ભૂરો</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{સિંક કરેલ ઉપકરણો પર ઓછામાં ઓછી 1 આઇટમ}=1{1 આઇટમ (અને સિંક કરેલ ઉપકરણો પર બીજી ઘણી બધી)}one{# આઇટમ (અને સિંક કરેલ ઉપકરણો પર બીજી ઘણી બધી)}other{# આઇટમ (અને સિંક કરેલ ઉપકરણો પર બીજી ઘણી બધી)}}</translation>
<translation id="3539171420378717834">આ ઉપકરણ પર આ કાર્ડની એક કૉપિ રાખો</translation>
-<translation id="3556433843310711081">તમારા માટે તમારા સંચાલક તેને અનાવરોધિત કરી શકે છે</translation>
<translation id="3566021033012934673">તમારું કનેક્શન ખાનગી નથી</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> પરનું શામેલ કરેલ પેજ કહે છે કે</translation>
@@ -516,6 +523,7 @@
<translation id="3678529606614285348">એક નવી છુપી વિંડોમાં પેજ ખોલો (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375"><ph name="CRASH_TIME" /> એ ક્રૅશ રિપોર્ટ કૅપ્ચર કરી અને <ph name="UPLOAD_TIME" /> એ અપલોડ કર્યો હતો</translation>
<translation id="3681007416295224113">પ્રમાણપત્ર માહિતી</translation>
+<translation id="3701427423622901115">રીસેટ કરવાનું સ્વીકાર્યું હતું.</translation>
<translation id="3704162925118123524">તમે ઉપયોગમાં લઈ રહ્યાં છો તે નેટવર્ક માટે, તમારે તેના લોગિન પૃષ્ઠની મુલાકાત લેવાની જરૂર હોઈ શકે છે.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">લોડ કરી રહ્યું છે...</translation>
@@ -532,6 +540,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> પરના હુમલાખોરો તમને કંઈક જોખમકારક પ્રવૃત્તિ જેમ કે સૉફ્ટવેર ઇન્સ્ટૉલ કરવા અથવા તમારી વ્યક્તિગત માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ, ફોન નંબર અથવા ક્રેડિટ કાર્ડ) જણાવવા ફસાવી શકે છે. <ph name="BEGIN_LEARN_MORE_LINK" />વધુ જાણો<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">સર્વર ભૂલને કારણે ભાષાંતર નિષ્ફળ રહ્યું.</translation>
<translation id="3759461132968374835">તમે હાલમાં ક્રૅશની જાણ કરી નથી. ક્રૅશની જાણ કરવાનું બંધ હતું ત્યારે થયેલા ક્રૅશ અહીં દેખાશે નહિ.</translation>
+<translation id="3760561303380396507">CVCને બદલે Windows Helloનો ઉપયોગ કરીએ?</translation>
<translation id="3761718714832595332">સ્ટેટસ છુપાવો</translation>
<translation id="3765032636089507299">Safe Browsing પેજ રચના હેઠળ છે.</translation>
<translation id="3778403066972421603">શું તમે આ કાર્ડને તમારા Google એકાઉન્ટ અને આ ડિવાઇસ પર સાચવવા માગો છો?</translation>
@@ -541,6 +550,7 @@
<translation id="3789155188480882154">કદ 16</translation>
<translation id="3797522431967816232">Prc3 (એન્વલપ)</translation>
<translation id="3807873520724684969">નુકસાનકારક કન્ટેન્ટ બ્લૉક કર્યું.</translation>
+<translation id="3808375843007691220">ચેતવણી: આગળ પ્રાયોગિક સુવિધાઓ છે!</translation>
<translation id="3810973564298564668">મેનેજ કરો</translation>
<translation id="382518646247711829">જો તમે કોઈ પ્રૉક્સી સર્વરનો ઉપયોગ કરો છો...</translation>
<translation id="3828924085048779000">ખાલી પાસફ્રેઝને અનુમતિ નથી. </translation>
@@ -549,11 +559,11 @@
<translation id="3858027520442213535">તારીખ અને સમય અપડેટ કરો</translation>
<translation id="3884278016824448484">વિરોધાભાસી ઉપકરણ ઓળખકર્તા</translation>
<translation id="3885155851504623709">પેરિશ</translation>
-<translation id="3886446263141354045">આ સાઇટને ઍક્સેસ કરવાની તમારી વિનંતી <ph name="NAME" /> ને મોકલવામાં આવી છે</translation>
<translation id="3890664840433101773">ઇમેઇલ ઉમેરો</translation>
<translation id="3901925938762663762">કાર્ડની સમયસીમા સમાપ્ત થઇ ગઈ છે</translation>
<translation id="3906600011954732550">B5-અતિરિક્ત</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVCને બદલે WebAuthnનો ઉપયોગ કરીએ?</translation>
<translation id="3946209740501886391">આ સાઇટ પર હંમેશાં પૂછો</translation>
<translation id="3949571496842715403">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેનું સુરક્ષા પ્રમાણપત્ર વિષય વૈકલ્પિક નામનો ઉલ્લેખ કરતું નથી. આ કોઈ ખોટી ગોઠવણીને કારણે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવતો હોવાને કારણે બન્યું હોઈ શકે.</translation>
<translation id="3949601375789751990">તમારો બ્રાઉઝિંગ ઇતિહાસ અહીં દેખાય છે</translation>
@@ -564,11 +574,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{કોઈ નહીં}=1{1 સાઇટમાંથી }one{# સાઇટમાંથી }other{# સાઇટમાંથી }}</translation>
<translation id="397105322502079400">ગણના કરી રહ્યું છે...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> અવરોધિત છે</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" />માં તમારા બ્રાઉઝર પર Chrome એન્ટરપ્રાઇઝ જોખમ સંરક્ષણ સેવા ચાલુ કરેલી છે. Chrome એન્ટરપ્રાઇઝ જોખમ સંરક્ષણ સેવાને તમારા અમુક ડેટાનો ઍક્સેસ છે.</translation>
<translation id="3987940399970879459">1 MB કરતાં ઓછું</translation>
<translation id="40103911065039147">{URL_count,plural, =1{નજીકમાં 1 વેબ પેજ}one{નજીકમાં # વેબ પેજ}other{નજીકમાં # વેબ પેજ}}</translation>
<translation id="4030383055268325496">&amp;ઉમેરવું પૂર્વવત્ કરો</translation>
<translation id="4032320456957708163">તમારું બ્રાઉઝર <ph name="ENROLLMENT_DOMAIN" /> દ્વારા મેનેજ કરવામાં આવે છે</translation>
-<translation id="4034375457890803692">તમે ખોલેલી લિંક તમે સામાન્ય રીતે મુલાકાત ન લેતા હોય એવી સાઇટ પર જાય છે. તે કદાચ તમને ગુંચવણમાં મૂકવાનો પ્રયાસ કરતી હોય શકે.</translation>
<translation id="4058922952496707368">કી "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (એન્વલપ)</translation>
<translation id="4067947977115446013">માન્ય સરનામું ઉમેરો</translation>
@@ -581,6 +591,7 @@
<translation id="4103249731201008433">ઉપકરણ અનુક્ર્માંક નંબર અમાન્ય છે</translation>
<translation id="410351446219883937">ઑટોપ્લે</translation>
<translation id="4103763322291513355">બ્લેકલિસ્ટ કરેલા URL ની સૂચિ અને તમારા સિસ્ટમ વ્યવસ્થાપક દ્વારા લાગુ અન્ય નીતિઓ જોવા માટે &lt;strong&gt;chrome://policy&lt;/strong&gt; ની મુલાકાત લો.</translation>
+<translation id="4108231218301530806">આગલી વખતે આ કાર્ડની ચકાસણી કરવા માટે ફિંગરપ્રિન્ટનો ઉપયોગ કરો.</translation>
<translation id="4110652170750985508">તમારી ચુકવણીને રિવ્યૂ કરો</translation>
<translation id="4112140312785995938">પાછળ કરો</translation>
<translation id="4116663294526079822">હંમેશા આ સાઇટ પર મંજૂરી આપો</translation>
@@ -595,6 +606,7 @@
<translation id="4171400957073367226">ખોટી ચકાસણી સહી</translation>
<translation id="4173315687471669144">ફૂલ્સ્કૅપ</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{વધુ <ph name="ITEM_COUNT" /> આઇટમ}one{વધુ <ph name="ITEM_COUNT" /> આઇટમ}other{વધુ <ph name="ITEM_COUNT" /> આઇટમ}}</translation>
+<translation id="4176463684765177261">અક્ષમ કરેલું</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">આગલી વખતે વધુ ઝડપથી ચુકવણી કરવા માટે, તમારા કાર્ડ અને બિલિંગ સરનામાને તમારા Google એકાઉન્ટમાં ઉમેરો.</translation>
<translation id="4196861286325780578">&amp;ખસેડવું ફરી કરો</translation>
@@ -631,6 +643,7 @@
<translation id="4277028893293644418">પાસવર્ડ રીસેટ કરો</translation>
<translation id="4279811152705618813">તમારા <ph name="DEVICE_TYPE" />ને <ph name="ENROLLMENT_DOMAIN" /> મેનેજ કરે છે</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{આ કાર્ડને તમારા Google એકાઉન્ટમાં સાચવવામાં આવ્યું છે}one{આ કાર્ડને Google એકાઉન્ટમાં સાચવવામાં આવ્યાં છે}other{આ કાર્ડને Google એકાઉન્ટમાં સાચવવામાં આવ્યાં છે}}</translation>
+<translation id="428847186335018806">તમે Chromeમાં ડાઉનલોડ અથવા અપલોડ કરેલી ફાઇલો તપાસો.</translation>
<translation id="42981349822642051">વિસ્તૃત કરો</translation>
<translation id="4302965934281694568">Chou3 (એન્વલપ)</translation>
<translation id="4305817255990598646">સ્વિચ</translation>
@@ -660,7 +673,6 @@
<translation id="4435702339979719576">પોસ્ટકાર્ડ)</translation>
<translation id="443673843213245140">પ્રૉક્સીનો ઉપયોગ બંધ કરેલો છે પણ એક સ્પષ્ટ પ્રૉક્સી ગોઠવણીનો ઉલ્લેખ કરેલો છે.</translation>
<translation id="445100540951337728">સ્વીકૃત ડેબિટ કાર્ડ</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> શંકાસ્પદ વર્તણૂક</translation>
<translation id="4466881336512663640">ફોર્મના ફેરફારો ગુમાવશો. શું તમે ખરેખર ચાલુ રાખવા માગો છો?</translation>
<translation id="4477350412780666475">આગલો ટ્રૅક</translation>
<translation id="4482953324121162758">આ સાઇટનો અનુવાદ થશે નહીં.</translation>
@@ -687,6 +699,7 @@
<translation id="4594403342090139922">&amp;ડિલીટ રદ કરો</translation>
<translation id="4597348597567598915">કદ 8</translation>
<translation id="4600854749408232102">C6/C5 (એન્વલપ)</translation>
+<translation id="464342062220857295">શોધ સુવિધાઓ</translation>
<translation id="4646534391647090355">મને હવે ડાઉનલોડ હોમ પર લઈ જાઓ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેના સુરક્ષા પ્રમાણપત્રમાં ભૂલો છે. આ કોઈ ખોટી ગોઠવણીને કારણે થયું હશે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવી રહ્યો છે.</translation>
@@ -695,7 +708,6 @@
<translation id="4691835149146451662">સ્થાપત્ય-A (એન્વલપ)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">તમારું કનેક્શન અવરોધાયું હતું</translation>
-<translation id="471880041731876836">તમારી પાસે આ સાઇટની મુલાકાત લેવાની પરવાનગી નથી</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows નેટવર્ક ડાયગ્નોસ્ટિક્સ ચલાવી રહ્યાં છે<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">નીતિઓ ફરીથી લોડ કરો</translation>
<translation id="4728558894243024398">પ્લેટફોર્મ</translation>
@@ -723,7 +735,6 @@
<translation id="4816492930507672669">પૃષ્ઠ પર ફિટ</translation>
<translation id="4850886885716139402">જુઓ</translation>
<translation id="4854362297993841467">વિતરણની આ પદ્ધતિ ઉપલબ્ધ નથી. કોઈ ભિન્ન પદ્ધતિ અજમાવો.</translation>
-<translation id="4858792381671956233">તમે આ સાઇટની મુલાકાત લો છો તે ઠીક છે કે કેમ તેવું તમે તમારા માતાપિતાને પૂછ્યું</translation>
<translation id="4864052566555297930">સુરક્ષા માટે સુઝાવ:</translation>
<translation id="4876188919622883022">સરળ દૃશ્ય</translation>
<translation id="4876305945144899064">કોઈ વપરાશકર્તા નામ નથી</translation>
@@ -747,7 +758,9 @@
<translation id="4974590756084640048">ચેતવણીઓ ફરીથી ચાલુ કરો</translation>
<translation id="4984339528288761049">Prc5 (એન્વલપ)</translation>
<translation id="4989163558385430922">બધા જુઓ</translation>
+<translation id="4989542687859782284">અનુપલબ્ધ</translation>
<translation id="4989809363548539747">આ પ્લગ-ઇન સમર્થિત નથી</translation>
+<translation id="4995216769782533993">આ સાઇટ સાથે તમારા કાર્ડની વિગતો શેર કરવા માટે સુરક્ષા કોડ કન્ફર્મ કરો</translation>
<translation id="5002932099480077015">જો સક્ષમ કરેલું હોય, તો ઝડપથી ફોર્મ ભરવા માટે Chrome આ ઉપકરણ પર તમારા કાર્ડની એક કૉપિ સંગ્રહશે.</translation>
<translation id="5015510746216210676">મશીનનું નામ:</translation>
<translation id="5017554619425969104">તમે કૉપિ કરેલી ટેક્સ્ટ</translation>
@@ -776,6 +789,7 @@
<translation id="5115216390227830982">યુરોપિયન-Edp</translation>
<translation id="5115563688576182185">(64-બિટ)</translation>
<translation id="5125394840236832993">B-પ્લસ</translation>
+<translation id="5126510351761255129">તમારું કાર્ડ ચકાસો</translation>
<translation id="5135404736266831032">સરનામા મેનેજ કરો…</translation>
<translation id="5138227688689900538">ઓછું બતાવો</translation>
<translation id="5141240743006678641">તમારા Google લૉગ ઇન વિગત સાથે સિંક પાસવર્ડને એન્ક્રિપ્ટ કરો</translation>
@@ -802,6 +816,7 @@
<translation id="5251803541071282808">મેઘ</translation>
<translation id="5252000469029418751">C7 (એન્વલપ)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">સુવિધાઓ કે જે સિસ્ટમ-વ્યાપી લાગુ છે તે ફક્ત માલિક દ્વારા જ સેટ કરી શકાય છે: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">ચેતવણી: આ નીતિને ઉલ્લેખ કર્યા મુજબ PolicyDictionaryMultipleSourceMergeList નીતિમાં મર્જ કરવામાં આવી ન હતી, કારણ કે તે મર્જ કરી શકાય તેવી શબ્દકોશ નીતિઓનો ભાગ નથી.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">સમાપ્ત</translation>
@@ -825,7 +840,6 @@
<translation id="536296301121032821">નીતિ સેટિંગ્સ સ્ટોર કરવામાં નિષ્ફળ થયાં</translation>
<translation id="5371425731340848620">કાર્ડને અપડેટ કરો</translation>
<translation id="5377026284221673050">"તમારી ઘડિયાળ પાછળ છે" અથવા "તમારી ઘડિયાળ આગળ છે" અથવા "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">આ પેજ તમને છેતરવાનો, વ્યક્તિગત માહિતી ચોરવાનો અથવા તમારા ડિવાઇસને નુકસાન પહોંચાડવાનો પ્રયાસ કરી શકે છે. વ્યક્તિગત માહિતી દાખલ કરતી વખતે અથવા ડાઉનલોડ કરેલી ફાઇલો ખોલતી વખતે સાવચેત રહેજો.</translation>
<translation id="5384855140246857529">બધા ડિવાઇસ પર તમારા કાર્ડનો ઉપયોગ કરવા માટે, સાઇન ઇન કરો અને સિંક ચાલુ કરો.</translation>
<translation id="5386426401304769735">આ સાઇટ માટેની પ્રમાણપત્ર શ્રૃંખલા SHA-1 નો ઉપયોગ કરીને સહી કરેલ પ્રમાણપત્ર ધરાવે છે.</translation>
<translation id="538659543871111977">A4-ટૅબ</translation>
@@ -839,6 +853,8 @@
<translation id="5457113250005438886">અમાન્ય</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> વધુ}one{<ph name="CONTACT_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> વધુ}other{<ph name="CONTACT_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> વધુ}}</translation>
<translation id="5470861586879999274">&amp;ફરી ફેરફાર કરો</translation>
+<translation id="5473728911100096288">આ સુવિધાઓ ચાલુ કરવાથી, તમે એવી નાપસંદ કરેલી સુવિધાનો
+ ઉપયોગ કરશો કે જે ભાવિ વર્ઝનમાં દેખાશે નહીં.</translation>
<translation id="5478437291406423475">B6/C4 (એન્વલપ)</translation>
<translation id="5481076368049295676">આ કન્ટેન્ટ કદાચ તમારા ડિવાઇસ પર જોખમકારક સૉફ્ટવેર ઇન્સ્ટૉલ કરવાનો પ્રયાસ કરી શકે છે કે જે તમારી માહિતીની ચોરી કરે અથવા કાઢી નાખે છે. <ph name="BEGIN_LINK" />છતાં પણ બતાવો<ph name="END_LINK" /></translation>
<translation id="54817484435770891">માન્ય સરનામું ઉમેરો</translation>
@@ -862,7 +878,6 @@
<translation id="5570825185877910964">એકાઉન્ટ સુરક્ષિત કરો</translation>
<translation id="5571083550517324815">આ સરનામેથી પિકઅપ કરી શકતા નથી. કોઈ ભિન્ન સરનામું પસંદ કરો.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 ઉપયોગમાં છે}one{# ઉપયોગમાં છે}other{# ઉપયોગમાં છે}})</translation>
-<translation id="5572851009514199876">કૃપા કરીને Chrome ને પ્રારંભ કરો અને સાઇન ઇન કરો જેથી કરીને Chrome તપાસી શકે કે તમને આ સાઇટની ઍક્સેસની મંજૂરી છે કે કેમ.</translation>
<translation id="5580958916614886209">તમારો સમાપ્તિ મહિનો તપાસો અને ફરી પ્રયાસ કરો</translation>
<translation id="5586446728396275693">કોઈ સાચવેલ ઍડ્રેસ નથી</translation>
<translation id="5595485650161345191">ઍડ્રેસમાં ફેરફાર કરો</translation>
@@ -870,6 +885,7 @@
<translation id="560412284261940334">સંચાલન સમર્થિત નથી</translation>
<translation id="5605670050355397069">લેજર</translation>
<translation id="5607240918979444548">સ્થાપત્ય-C</translation>
+<translation id="5608165884683734521">આ સાઇટ બનાવટી અથવા કપટપૂર્ણ હોઈ શકે છે. Chrome ભલામણ કરે છે કે તમે અત્યારે જ આ સાઇટ બંધ કરી દો.</translation>
<translation id="5610142619324316209">કનેક્શન તપાસીને</translation>
<translation id="5610807607761827392">તમે <ph name="BEGIN_LINK" />સેટિંગ્સ<ph name="END_LINK" />માં કાર્ડ્સ અને સરનામાં સંચાલિત કરી શકો છો.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> એ તમને ઘણીબધી વખત રીડાયરેક્ટ કર્યું.</translation>
@@ -893,11 +909,11 @@
<translation id="5720705177508910913">વર્તમાન વપરાશકર્તા</translation>
<translation id="5728056243719941842">C5 (એન્વલપ)</translation>
<translation id="5730040223043577876">જો તમે અન્ય સાઇટ પર તમારા પાસવર્ડનો ફરી ઉપયોગ કર્યો હોય, તો Chrome તેને રીસેટ કરવાનો સુઝાવ આપે છે.</translation>
-<translation id="5732392974455271431">તમારા માટે તમારા માતાપિતા તેને અનાવરોધિત કરી શકે છે</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{તમારા Google એકાઉન્ટમાં કાર્ડ સાચવો}one{તમારા Google એકાઉન્ટમાં કાર્ડ સાચવો}other{તમારા Google એકાઉન્ટમાં કાર્ડ સાચવો}}</translation>
<translation id="5763042198335101085">એક માન્ય ઇમેઇલ ઍડ્રેસ ઉમેરો</translation>
<translation id="5765072501007116331">વિતરણ પદ્ધતિઓ અને આવશ્યકતાઓ જોવા માટે, એક સરનામું પસંદ કરો</translation>
<translation id="5778550464785688721">MIDI ઉપકરણોનું પૂર્ણ નિયંત્રણ</translation>
+<translation id="5781136890105823427">પ્રયોગ ચાલુ કર્યો</translation>
<translation id="578305955206182703">પીળાશ પડતો નારંગી</translation>
<translation id="57838592816432529">અવાજ બંધ કરો</translation>
<translation id="5784606427469807560">તમારા કાર્ડની પુષ્ટિ કરવામાં એક સમસ્યા આવી હતી. તમારું ઇન્ટરનેટ કનેક્શન તપાસો અને ફરીથી પ્રયાસ કરો.</translation>
@@ -914,13 +930,16 @@
<translation id="5860033963881614850">બંધ</translation>
<translation id="5863847714970149516">આગળનું પેજ તમને શુલ્ક લાગુ કરી શકે છે</translation>
<translation id="5866257070973731571">ફોન નંબર ઉમેરો</translation>
+<translation id="5866898949289125849">તમે ડેવલપર સાધનોનું પેજ જોઈ રહ્યાં છો</translation>
<translation id="5869405914158311789">આ સાઇટ પર પહોંચી શકાતું નથી</translation>
<translation id="5869522115854928033">સાચવેલા પાસવર્ડ્સ</translation>
<translation id="5887400589839399685">કાર્ડ સાચવ્યું</translation>
<translation id="5893752035575986141">ક્રેડિટ કાર્ડ સ્વીકારવામાં આવે છે.</translation>
+<translation id="5895138241574237353">પુનઃપ્રારંભ કરો</translation>
<translation id="5901630391730855834">પીળો</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (સમન્વયિત)</translation>
<translation id="5916664084637901428">ચાલુ</translation>
+<translation id="59174027418879706">સક્ષમ કરેલું</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google એકાઉન્ટમાં કાર્ડ સાચવીએ?</translation>
<translation id="5922853866070715753">લગભગ થઈ ગયું</translation>
@@ -954,6 +973,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">તમારા બધાં ડિવાઇસ પર તમારાં કાર્ડનો ઉપયોગ કરીએ?</translation>
<translation id="6059925163896151826">USB ઉપકરણો</translation>
+<translation id="6060009363608157444">અમાન્ય DnsOverHttps મોડ.</translation>
<translation id="6080696365213338172">તમે વ્યવસ્થાપક-પ્રદત્ત પ્રમાણપત્રનો ઉપયોગ કરીને કન્ટેન્ટ ઍક્સેસ કરી છે. તમે <ph name="DOMAIN" /> ને પ્રદાન કરેલ ડેટા તમારા વ્યવસ્થાપક દ્વારા ઇન્ટરસેપ્ટ થઈ શકે છે.</translation>
<translation id="6094273045989040137">એનોટેટ કરો</translation>
<translation id="610911394827799129">તમારા Google એકાઉન્ટમાં <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> પર બ્રાઉઝિંગ ઇતિહાસના બીજા સ્વરૂપો હોય શકે છે</translation>
@@ -1002,13 +1022,12 @@
<translation id="6404511346730675251">બુકમાર્કમાં ફેરફાર કરો</translation>
<translation id="6406765186087300643">C0 (એન્વલપ)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> માટે સમાપ્તિ તારીખ અને CVC દાખલ કરો</translation>
-<translation id="6414888972213066896">આ પૃષ્ઠની મુલાકાત લો છો તે ઠીક છે કે કેમ તેવું તમે તમારા માતાપિતાને પૂછ્યું</translation>
<translation id="6415778972515849510">Chromium તમારા Google એકાઉન્ટને સુરક્ષિત કરવામાં અને તમારો પાસવર્ડ બદલવામાં તમારી સહાય કરી શકે છે.</translation>
-<translation id="6417515091412812850">પ્રમાણપત્ર રદ કરવામાં આવ્યું છે કે નહીં તે તપાસવામાં અક્ષમ છે.</translation>
<translation id="6431585503458005759">સ્ટોર કરશો નહીં</translation>
<translation id="6433490469411711332">સંપર્ક માહિતીમાં ફેરફાર કરો</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> એ કનેક્ટ કરવાનો ઇનકાર કર્યો.</translation>
<translation id="6434309073475700221">કાઢી નાખો</translation>
+<translation id="6435221585574090192">Chrome એન્ટરપ્રાઇઝ જોખમ સંરક્ષણ સેવા દ્વારા ચિહ્નિત કરવામાં આવેલી સુરક્ષા ઇવેન્ટ વિશેનો ડેટા તમારા વ્યવસ્થાપક સાથે શેર કરો. આમાં પેજની URLs, ફાઇલનું નામ અને ફાઇલ મેટાડેટા, તમારું ડિવાઇસ વપરાશકર્તા નામ અને Chrome વપરાશકર્તા નામનો સમાવેશ હોય શકે.</translation>
<translation id="6440503408713884761">અવગણી</translation>
<translation id="6446163441502663861">Kahu (એન્વલપ)</translation>
<translation id="6446608382365791566">વધુ માહિતી ઉમેરો</translation>
@@ -1017,20 +1036,19 @@
<translation id="6465306955648956876">બધા પાસવર્ડ મેનેજ કરો…</translation>
<translation id="647261751007945333">ઉપકરણ નીતિઓ</translation>
<translation id="6476284679642588870">ચુકવણી પદ્ધતિઓ મેનેજ કરો</translation>
-<translation id="6477321094435799029">Chrome ને આ પૃષ્ઠ પર અસામાન્ય કોડ મળ્યો અને તમારી વ્યક્તિગત માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ્સ, ફોન નંબર્સ અને ક્રેડિટ કાર્ડ્સ)ની સુરક્ષા કરવા માટે તેને અવરોધિત કરેલ છે.</translation>
<translation id="6489534406876378309">ક્રેશ અપલોડ કરવાનું શરૂ કરો</translation>
<translation id="6499038740797743453">પાસવર્ડ રીસેટ કરીએ?</translation>
<translation id="6507833130742554667">ક્રેડિટ અને ડેબિટ કાર્ડ સ્વીકારવામાં આવે છે.</translation>
<translation id="650855688985305916">હા, સ્ટોર કરો</translation>
<translation id="6508722015517270189">Chrome ને પુનઃપ્રારંભ કરો</translation>
<translation id="6517596291481585650">ચેતવણી: આ નીતિને નીતિ દ્વારા ઉલ્લેખ થયા મુજબ સૂચિ તરીકે મર્જ કરવામાં આવી ન હતી, કારણ કે તે સૂચિ નથી.</translation>
+<translation id="6518133107902771759">પ્રમાણિત કરો</translation>
<translation id="6521745193039995384">સક્રિય નથી</translation>
<translation id="6529602333819889595">&amp;ફરી કરો ડિલીટ કરો</translation>
<translation id="6534179046333460208">વાસ્તવિક વેબ સૂચનો</translation>
<translation id="6545864417968258051">બ્લૂટૂથ સ્કૅનિંગ</translation>
<translation id="6554795675067793129"><ph name="ENROLLMENT_DOMAIN" /> દ્વારા તમારું એકાઉન્ટ મેનેજ કરવામાં આવે છે.</translation>
<translation id="6556866813142980365">ફરી કરો</translation>
-<translation id="6563469144985748109">તમારા સંચાલકે હજી સુધી તેને મંજૂર કરેલ નથી</translation>
<translation id="6569060085658103619">તમે એક્સ્ટેન્શન પૃષ્ઠ જોઈ રહ્યાં છો</translation>
<translation id="6578796323535178455">C2 (એન્વલપ)</translation>
<translation id="6579990219486187401">આછો ગુલાબી</translation>
@@ -1048,11 +1066,13 @@
<translation id="6643016212128521049">સાફ કરો</translation>
<translation id="6644283850729428850">આ નીતિ દૂર કરવામાં આવેલી છે.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{કોઈ નહિ}=1{From 1 site (you won't be signed out of your Google Account)}one{From # sites (you won't be signed out of your Google Account)}other{From # sites (you won't be signed out of your Google Account)}}</translation>
+<translation id="6652101503459149953">Windows Helloનો ઉપયોગ કરો</translation>
<translation id="6657585470893396449">પાસવર્ડ</translation>
<translation id="6670613747977017428">સુરક્ષા પર પાછા.</translation>
<translation id="6671697161687535275">Chromium માંથી ફોર્મ સૂચન દૂર કરીએ?</translation>
<translation id="6685834062052613830">સાઇન આઉટ કરો અને સેટઅપ પૂર્ણ કરો</translation>
<translation id="6689271823431384964">તમે સાઇન ઇન કરેલું છે તેથી Chrome તમને તમારા કાર્ડ તમારા Google એકાઉન્ટમાં સાચવવાની ઑફર કરે છે. તમે સેટિંગમાં આ વર્તણૂકને બદલી શકો છો. કાર્ડધારકનું નામ તમારા એકાઉન્ટમાંથી આવે છે.</translation>
+<translation id="6707256370811247129">તમે Chromeમાં ડાઉનલોડ અથવા અપલોડ કરો છો તે કૅશ મેમરી અને ફાઇલોનું કન્ટેન્ટ તપાસો.</translation>
<translation id="6710213216561001401">પાછલી</translation>
<translation id="6710594484020273272">&lt;શોધ શબ્દ લખો&gt;</translation>
<translation id="671076103358959139">નોંધણી ટોકન:</translation>
@@ -1060,10 +1080,10 @@
<translation id="6738516213925468394">તમારો ડેટા <ph name="TIME" />ના રોજ તમારા <ph name="BEGIN_LINK" />સિંક પાસફ્રેઝ<ph name="END_LINK" /> સાથે એન્ક્રિપ્ટ કરવામાં આવ્યો હતો. સિંક શરૂ કરવા માટે એ દાખલ કરો.</translation>
<translation id="674375294223700098">અજ્ઞાત સર્વર પ્રમાણપત્ર ભૂલ.</translation>
<translation id="6744009308914054259">કનેક્શન માટે રાહ જોતી વખતે, ઑફલાઇન લેખ વાંચવા માટે તમે ડાઉનલોડની મુલાકાત લઈ શકો.</translation>
+<translation id="6747611005629681221">ચેતવણી: આગળ નાપસંદ કરેલી સુવિધાઓ છે!</translation>
<translation id="6753269504797312559">નીતિ મૂલ્ય</translation>
<translation id="6757797048963528358">તમારું ઉપકરણ નિષ્ક્રિય થઈ ગયું હતું.</translation>
<translation id="6768213884286397650">Hagaki (પોસ્ટકાર્ડ)</translation>
-<translation id="6778737459546443941">તમારા માતાપિતાએ હજી સુધી તેને મંજૂર કરેલ નથી</translation>
<translation id="67862343314499040">જાંબુડિયો</translation>
<translation id="6786747875388722282">એક્સ્ટેન્શન્સ</translation>
<translation id="6790428901817661496">ચલાવો</translation>
@@ -1071,6 +1091,7 @@
<translation id="681021252041861472">ફરજિયાત</translation>
<translation id="6810899417690483278">કસ્ટમાઇઝેશન ID</translation>
<translation id="6825578344716086703">તમે <ph name="DOMAIN" /> પર પહોંચવાનો પ્રયાસ કર્યો, પરંતુ સર્વરે નબળા સહી ઍલ્ગોરિધમ (જેમ કે SHA-1)નો ઉપયોગ કરીને સહીિત કરેલું પ્રમાણપત્ર પ્રસ્તુત કર્યું. આનો અર્થ એ છે કે સર્વરે પ્રસ્તુત કરેલા સુરક્ષા પ્રમાણપત્રો બનાવટી હોય શકે છે અને તે સર્વર તમારું અપેક્ષિત સર્વર (તમે કોઈ હુમલાખોર સાથે વાર્તાલાપ કરતા હોય શકે) ન પણ હોય.</translation>
+<translation id="6826370046007623921">ડેટા નુકસાન અટકાવ</translation>
<translation id="6831043979455480757">અનુવાદ કરો</translation>
<translation id="6839929833149231406">ક્ષેત્ર</translation>
<translation id="6852204201400771460">ઍપ ફરીથી લોડ કરીએ?</translation>
@@ -1083,7 +1104,6 @@
<translation id="6891596781022320156">નીતિ સ્તર સમર્થિત નથી.</translation>
<translation id="6895330447102777224">તમારા કાર્ડની પુષ્ટિ કરવામાં આવી છે</translation>
<translation id="6897140037006041989">વપરાશકર્તા એજન્ટ</translation>
-<translation id="6903319715792422884">Googleને અમુક <ph name="BEGIN_WHITEPAPER_LINK" />સિસ્ટમ માહિતી અને પેજ કન્ટેન્ટ<ph name="END_WHITEPAPER_LINK" />મોકલીને સલામત બ્રાઉઝિંગ બહેતર બનાવવામાં સહાય કરો. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">વપરાશકર્તા: </translation>
<translation id="6934672428414710184">આ નામ તમારા Google એકાઉન્ટમાંથી લીધું છે</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> દ્વારા સંચાલિત ન થતી હોય, તેવી સાઇટ પર તમે તમારો પાસવર્ડ દાખલ કર્યો છે. તમારા એકાઉન્ટની સુરક્ષા માટે, અન્ય ઍપ અને સાઇટ પર તમારા પાસવર્ડનો ફરી ઉપયોગ ન કરો.</translation>
@@ -1128,6 +1148,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> વધુ}one{<ph name="PAYMENT_METHOD_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> વધુ}other{<ph name="PAYMENT_METHOD_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> વધુ}}</translation>
<translation id="7153618581592392745">આછો જાંબલી</translation>
<translation id="717330890047184534">Gaia ID:</translation>
+<translation id="7174545416324379297">મર્જ કર્યાં</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> વધુ}one{<ph name="SHIPPING_OPTION_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> વધુ}other{<ph name="SHIPPING_OPTION_PREVIEW" /> અને <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> વધુ}}</translation>
<translation id="7177397715882417099">તમે જેના પર જવાનો પ્રયાસ કરી રહ્યાં છો, તે<ph name="ORIGIN" /> સર્વર દ્વારા વિનંતી
કરવામાં આવી છે કે સુરક્ષા પૉલિસી તેના પરની બધી વિનંતીઓ પર લાગુ થશે. પણ પૉલિસી વિતરિત
@@ -1165,6 +1186,7 @@
<translation id="7320336641823683070">કનેક્શન સહાય</translation>
<translation id="733354035281974745">ડિવાઇસ સ્થાનિક એકાઉન્ટ ઓવરરાઇડ</translation>
<translation id="7334320624316649418">&amp;પુનઃક્રમાંકિત કરવું ફરી કરો</translation>
+<translation id="7337706099755338005">તમારા પ્લૅટફૉર્મ પર ઉપલબ્ધ નથી.</translation>
<translation id="733923710415886693">પ્રમાણપત્ર પારદર્શિતા દ્વારા સર્વરનું પ્રમાણપત્ર જાહેર કરવામાં આવ્યું ન હતું.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">સંકળાયેલા છે:</translation>
@@ -1196,7 +1218,6 @@
<translation id="7440140511386898319">ઑફલાઇન હો તે સમયે જાણકારી મેળવો</translation>
<translation id="7441627299479586546">ખોટો નીતિ વિષય</translation>
<translation id="7442725080345379071">આછો નારંગી</translation>
-<translation id="7444046173054089907">આ સાઇટ અવરોધિત છે</translation>
<translation id="7445762425076701745">તમે જે સર્વરથી કનેક્ટ છો તેની ઓળખ સંપૂર્ણ રૂપે માન્ય કરી શકાતી નથી. તમે જે નામનો ઉપયોગ કરીને સર્વરથી કનેક્ટ છો, તે ફક્ત તમારા નેટવર્કની અંતર્ગત જ માન્ય છે, જેના બાહ્ય પ્રમાણપત્ર અધિકારીને માલિકીને માન્ય કરવાની કોઈ રીત નથી. આના પર ધ્યાન આપ્યાં વગર કેટલાક પ્રમાણપત્ર અધિકારીઓ આ નામો માટે પ્રમાણપત્ર બહાર પાડશે, તેથી તમે ઇચ્છિત વેબસાઇટથી કનેક્ટ છો કોઈ હુમલાખોરથી નહીં, તેની ખાતરી કરવાની કોઈ રીત નથી.</translation>
<translation id="7451311239929941790">આ સમસ્યા વિશે <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">વૈશ્વિક ડિફોલ્ટનો ઉપયોગ કરો (અવરોધિત કરો)</translation>
@@ -1218,9 +1239,9 @@
<translation id="7538364083937897561">A2 (એન્વલપ)</translation>
<translation id="7542403920425041731">એકવાર તમે પુષ્ટિ કરી લો તે પછી, આ સાઇટ સાથે તમારા કાર્ડની વિગતો શેર કરવામાં આવશે.</translation>
<translation id="7542995811387359312">આપમેળે ક્રેડિટ કાર્ડ ભરણ અક્ષમ કર્યું છે કારણ કે આ ફોર્મ સુરક્ષિત કનેક્શનનો ઉપયોગ કરતું નથી.</translation>
-<translation id="7543525346216957623">તમારા માતા-પિતાને કહો</translation>
<translation id="7548892272833184391">કનેક્શન ભૂલો સુધારો</translation>
<translation id="7549584377607005141">આ વેબપેજને તે ડેટાની જરૂર છે જે તમે પહેલાં બરાબર રીતે પ્રદર્શિત થાય તે માટે દાખલ કર્યો હતો. તમે આ ડેટા ફરીથી મોકલી શકો છો, પણ આમ કરીને તમે કોઈપણ ક્રિયા કે જે પેજ પહેલાં જ કરી ચૂક્યું છે તેનું પુનરાવર્તન કરશો.</translation>
+<translation id="7550637293666041147">તમારું ડિવાઇસ વપરાશકર્તા નામ અને Chrome વપરાશકર્તા નામ</translation>
<translation id="7552846755917812628">નીચેની ટિપને અજમાવો:</translation>
<translation id="7554791636758816595">નવું ટૅબ</translation>
<translation id="7564049878696755256">તમે તમારા <ph name="ORG_NAME" /> એકાઉન્ટનો ઍક્સેસ ગુમાવી શકો છો અથવા તમને ઓળખ ચોરીનો અનુભવ થઈ શકે છે. Chrome તમને હમણાં જ તમારો પાસવર્ડ બદલવાની ભલામણ કરે છે.</translation>
@@ -1235,6 +1256,7 @@
<translation id="7610193165460212391">મૂલ્ય <ph name="VALUE" /> શ્રેણી બહારનું છે.</translation>
<translation id="7613889955535752492">સમાપ્તિ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">તમારી પાસે પેહલાથી જ ડેટા છે જે તમારા Google એકાઉન્ટ પાસવર્ડના વિવિધ વર્ઝનનો ઉપયોગ કરીને એન્ક્રિપ્ટ કરેલો છે.</translation>
+<translation id="7625784245512586808">Chrome એન્ટરપ્રાઇઝ જોખમ સંરક્ષણ સેવા</translation>
<translation id="7633909222644580952">કાર્યપ્રદર્શન ડેટા અને ક્રૅશ રિપોર્ટ</translation>
<translation id="7637571805876720304">Chromium માંથી ક્રેડિટ કાર્ડ દૂર કરીએ?</translation>
<translation id="7638605456503525968">સીરિયલ પોર્ટ</translation>
@@ -1247,7 +1269,6 @@
<translation id="7668654391829183341">અજ્ઞાત ઉપકરણ</translation>
<translation id="7669271284792375604">આ સાઇટ પરના હુમલાખોરો તમને તમારા બ્રાઉઝિંગ અનુભવને નુકસાન પહોંચાડે એવા પ્રોગ્રામ્સ ઇન્સ્ટૉલ કરવા માટે છેતરવાનો પ્રયાસ કરી શકે છે (ઉદાહરણ તરીકે, તમારું હોમપેજ બદલીને અથવા તમે મુલાકાત લો છો તે સાઇટ્સ પર વધુ પડતી જાહેરાતો બતાવીને).</translation>
<translation id="7676643023259824263">ક્લિપબોર્ડ ટેક્સ્ટમાંથી શોધો, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">પ્લૅટફૉર્મ અને ક્લાઉડ</translation>
<translation id="7681101578153515023">સર્ચ એંજિન બદલો</translation>
<translation id="7682287625158474539">શિપિંગ</translation>
<translation id="7687186412095877299">તમારી સાચવેલી ચુકવણી પદ્ધતિઓ વડે ચુકવણી ફૉર્મ ભરે છે</translation>
@@ -1262,7 +1283,6 @@
<translation id="7723047071702270851">કાર્ડમાં ફેરફાર કરો</translation>
<translation id="774634243536837715">જોખમકારક કન્ટેન્ટ બ્લૉક કર્યું.</translation>
<translation id="7752995774971033316">બિનસંચાલિત</translation>
-<translation id="7755287808199759310">તમારા માટે તમારા માતાપિતા તેને અનાવરોધિત કરી શકે છે</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ફાયરવોલ અથવા એન્ટિવાયરસ સોફ્ટવેર એ કનેક્શન અવરોધિત કર્યું હોઈ શકે છે.</translation>
<translation id="7759163816903619567">ડોમેન બતાવો:</translation>
@@ -1306,7 +1326,6 @@
<translation id="8004582292198964060">બ્રાઉઝર</translation>
<translation id="8009225694047762179">બધા પાસવર્ડ મેનેજ કરો</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{આ કાર્ડ અને તેનું બિલિંગ સરનામું સાચવવામાં આવશે. જ્યારે <ph name="USER_EMAIL" />માં સાઇન ઇન કર્યું હશે ત્યારે તમે તેનો ઉપયોગ કરી શકશો.}one{આ કાર્ડ અને તેના બિલિંગ સરનામાં સાચવવામાં આવશે. જ્યારે <ph name="USER_EMAIL" />માં સાઇન ઇન કર્યું હશે ત્યારે તમે તેમનો ઉપયોગ કરી શકશો.}other{આ કાર્ડ અને તેના બિલિંગ સરનામાં સાચવવામાં આવશે. જ્યારે <ph name="USER_EMAIL" />માં સાઇન ઇન કર્યું હશે ત્યારે તમે તેમનો ઉપયોગ કરી શકશો.}}</translation>
-<translation id="8012647001091218357">અમે આ પળે તમારા વાલીઓ સુધી પહોંચી શક્યાં નથી. કૃપા કરીને ફરી પ્રયાસ કરો.</translation>
<translation id="8025119109950072390">આ સાઇટ પરના હુમલાખોરો તમારી વ્યક્તિગત માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ, ફોન નંબર અથવા ક્રેડિટ કાર્ડ)ને દર્શાવવા અથવા સોફ્ટવેર ઇન્સ્ટૉલ કરવા જેવી જોખમી વસ્તુઓને કરવા માટે તમને છેતરવાનો પ્રયાસ કરી શકે છે.</translation>
<translation id="8034522405403831421">આ પૃષ્ઠ <ph name="SOURCE_LANGUAGE" /> માં છે. શું તેનો અનુવાદ <ph name="TARGET_LANGUAGE" /> માં કરીએ?</translation>
<translation id="8035152190676905274">પેન</translation>
@@ -1317,6 +1336,7 @@
<translation id="8041940743680923270">વૈશ્વિક ડિફોલ્ટનો ઉપયોગ કરો (કહો)</translation>
<translation id="8042918947222776840">પિકઅપ પદ્ધતિ પસંદ કરો</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />"ની ગોઠવણી યોગ્ય રીતે કરવામાં આવી નથી. સામાન્ય રીતે "<ph name="SOFTWARE_NAME" />"ને અનઇન્સ્ટૉલ કરવાથી સમસ્યા હલ થઈ જાય છે. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">તમારે હવેથી કાર્ડનો સુરક્ષા કોડ દાખલ કરવો નહીં પડે</translation>
<translation id="8066955247577885446">માફ કરશો, કંઈક ખોટું થયું.</translation>
<translation id="8074253406171541171">10x13 (એન્વલપ)</translation>
<translation id="8078141288243656252">ફેરવેલ હોય ત્યારે એનોટેટ કરી શકતા નથી</translation>
@@ -1347,6 +1367,7 @@
<translation id="8211406090763984747">કનેક્શન સુરક્ષિત છે</translation>
<translation id="8218327578424803826">સોંપાયેલ સ્થાન:</translation>
<translation id="8220146938470311105">C7/C6 (એન્વલપ)</translation>
+<translation id="8220639454292072926">એન્ટરપ્રાઇઝ રિપોર્ટિંગ</translation>
<translation id="8225771182978767009">આ કમ્પ્યુટરને સેટ કરનાર વ્યક્તિએ આ સાઇટને અવરોધિત કરવાનું પસંદ કર્યું છે.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">એક નવી છુપી વિંડોમાં પેજ ખોલો</translation>
@@ -1401,23 +1422,23 @@
<translation id="8508648098325802031">શોધ આઇકન</translation>
<translation id="8522552481199248698">Chrome તમારા Google એકાઉન્ટને સુરક્ષિત કરવામાં અને તમારો પાસવર્ડ બદલવામાં તમારી સહાય કરી શકે છે.</translation>
<translation id="8543181531796978784">તમે <ph name="BEGIN_ERROR_LINK" />શોધ સમસ્યાની જાણ<ph name="END_ERROR_LINK" /> કરી શકો છો અથવા જો તમે તમારી સુરક્ષા અંગેનાં જોખમોને સમજતાં હોવ, તો <ph name="BEGIN_LINK" />આ અસુરક્ષિત સાઇટની મુલાકાત<ph name="END_LINK" /> લઈ શકો છો.</translation>
-<translation id="8543556556237226809">પ્રશ્નો છે? તમારી પ્રોફાઇલનું નિરીક્ષણ કરનાર વ્યક્તિનો સંપર્ક કરો.</translation>
<translation id="8553075262323480129">ભાષાંતર નિષ્ફળ રહ્યું કારણ કે પૃષ્ઠની ભાષા નિર્ધારિત થઈ શકી નથી.</translation>
<translation id="8557066899867184262">CVC તમારા કાર્ડની પાછળ હોય છે.</translation>
<translation id="8559762987265718583"><ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> પર ખાનગી કનેક્શન સ્થાપિત કરી શકાતું નથી કારણ કે તમારા ઉપકરણની તારીખ અને સમય (<ph name="DATE_AND_TIME" />) અયોગ્ય છે.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> શંકાસ્પદ સાઇટ</translation>
<translation id="8564985650692024650">જો તમે અન્ય સાઇટ પર <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> પાસવર્ડનો ફરી ઉપયોગ કર્યો હોય, તો Chromium તેને રીસેટ કરવાનો સુઝાવ આપે છે.</translation>
<translation id="8571890674111243710">પૃષ્ઠને <ph name="LANGUAGE" /> માં અનુવાદિત કરી રહ્યું છે...</translation>
<translation id="858637041960032120">ફોન નંબર ઉમેરો</translation>
-<translation id="859285277496340001">પ્રમાણપત્રને રદ કરવામાં આવ્યું છે કે નહિ તે તપાસવા માટે કોઈપણ મેકેનિઝમ નિર્દિષ્ટ કરતું નથી.</translation>
<translation id="860043288473659153">કાર્ડધારકનું નામ</translation>
<translation id="861775596732816396">કદ 4</translation>
-<translation id="8620436878122366504">તમારા માતાપિતાએ તેને હજી સુધી મંજૂર કરેલ નથી</translation>
<translation id="8622948367223941507">કાનૂની-અતિરિક્ત</translation>
<translation id="8625384913736129811">આ કાર્ડને આ ડિવાઇસમાં સાચવો</translation>
<translation id="8626112503828625890">બિલિંગની વિગતોને Google એકાઉન્ટમાં સ્ટોર કરીએ?</translation>
+<translation id="8647750283161643317">બધાને ડિફોલ્ટ પર ફરીથી સેટ કરો</translation>
<translation id="8663226718884576429">ઑર્ડરનો સારાંશ, <ph name="TOTAL_LABEL" />, વધુ વિગતો</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, જવાબ, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">ઉપલબ્ધ</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> સાથેનું તમારું કનેક્શન એન્ક્રિપ્ટેડ નથી.</translation>
<translation id="8718314106902482036">ચુકવણી પૂર્ણ થઈ નથી</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, શોધ સૂચન</translation>
@@ -1428,6 +1449,7 @@
<translation id="8738058698779197622">એક સુરક્ષિત કનેક્શન સ્થાપિત કરવા માટે, તમારું ઘડિયાળ યોગ્ય રીતે સેટ હોવું જરૂરી છે. આનું કારણ એ કે વેબસાઇટ્સ તેઓને ઓળખવા માટે જે પ્રમાણપત્રોનો ઉપયોગ કરે છે તે ચોક્કસ સમય અવધિ માટે જ માન્ય હોય છે. તમારા ઉપકરણની ઘડિયાળ ખોટી હોવાને લીધે, Chromium આ પ્રમાણપત્રોને ચકાસી શકતું નથી.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> નું &lt;abbr id="dnsDefinition"&gt;DNS સરનામું&lt;/abbr&gt; શોધી શકાયું નથી. સમસ્યાનું નિદાન કરી રહ્યાં છીએ.</translation>
<translation id="874846938927089722">સ્વીકૃત ક્રેડિટ અને પ્રિપેઇડ કાર્ડ</translation>
+<translation id="874918643257405732">આ ટૅબને બુકમાર્ક કરો</translation>
<translation id="8759274551635299824">આ કાર્ડની સમયસીમા સમાપ્ત થઈ ગઈ છે</translation>
<translation id="8761567432415473239">Google Safe Browsing ને તાજેતરમાં <ph name="SITE" /> પર <ph name="BEGIN_LINK" />હાનિકારક પ્રોગ્રામ્સ મળ્યાં<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB ઉપકરણ</translation>
@@ -1457,6 +1479,7 @@
<translation id="8938939909778640821">સ્વીકૃત ક્રેડિટ અને પ્રીપેઇડ કાર્ડ</translation>
<translation id="8943282376843390568">લાઇમ</translation>
<translation id="8957210676456822347">કૅપ્ટિવ પોર્ટલ પ્રમાણિત</translation>
+<translation id="8962950042226115166">શંકાસ્પદ સાઇટ</translation>
<translation id="8968766641738584599">કાર્ડ સાચવો</translation>
<translation id="8971063699422889582">સર્વરના પ્રમાણપત્રની સમયસીમા સમાપ્ત થઈ છે.</translation>
<translation id="8975012916872825179">ફોન નંબર, ઇમેઇલ ઍડ્રેસ અને શિપિંગ સરનામા જેવી માહિતીનો સમાવેશ છે</translation>
@@ -1479,24 +1502,24 @@
<translation id="9035022520814077154">સુરક્ષા ભૂલ</translation>
<translation id="9038649477754266430">પૃષ્ઠોને વધુ ઝડપથી લોડ કરવા માટે પૂર્વાનુમાન સેવાનો ઉપયોગ કરો</translation>
<translation id="9039213469156557790">વળી, આ પૃષ્ઠમાં અન્ય એવા સાધનો છે જે સુરક્ષિત નથી. ટ્રાંઝિટમાં હોવા પર અન્ય લોકો દ્વારા આ સાધનો જોઈ શકાય છે અને પૃષ્ઠનો વ્યવહાર બદલવા માટે હુમલાખોર દ્વારા સંશોધિત કરવામાં આવી શકે છે.</translation>
+<translation id="9044359186343685026">Touch IDનો ઉપયોગ કરો</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">તમે <ph name="DOMAIN" /> સુધી પહોંચવાનો પ્રયાસ કર્યો, પરંતુ સર્વરે અમાન્ય પ્રમાણપત્ર પ્રસ્તુત કર્યું. </translation>
<translation id="9050666287014529139">પાસફ્રેઝ</translation>
<translation id="9065203028668620118">ફેરફાર કરો</translation>
<translation id="9065745800631924235">ઇતિહાસમાંથી <ph name="TEXT" /> શોધો</translation>
<translation id="9069693763241529744">એક્સ્ટેન્શન દ્વારા અવરોધિત કરેલ છે</translation>
-<translation id="9076283476770535406">તેમાં વયસ્ક કન્ટેન્ટ હોઈ શકે છે</translation>
<translation id="9076630408993835509">આ બ્રાઉઝર કંપની દ્વારા અથવા અન્ય સંસ્થા દ્વારા મેનેજ કરવામાં આવતું નથી. આ ડિવાઇસ પરની પ્રવૃત્તિ Chromeની બહાર મેનેજ કરી શકાય છે. <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">વધુ માહિતી આવશ્યક</translation>
<translation id="9080712759204168376">ઑર્ડરનો સારાંશ</translation>
<translation id="9089260154716455634">બિન-કામકાજી સમય સંબંધી નીતિ:</translation>
<translation id="9095388113577226029">વધુ ભાષાઓ...</translation>
+<translation id="9098981495403789647">તમારા વ્યવસ્થાપકે તમારા બ્રાઉઝર પર Chrome એન્ટરપ્રાઇઝ જોખમ સંરક્ષણ સેવા ચાલુ કરેલી છે. Chrome એન્ટરપ્રાઇઝ જોખમ સંરક્ષણ સેવાને તમારા અમુક ડેટાનો ઍક્સેસ છે.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> સામાન્ય રીતે તમારી માહિતીને સુરક્ષિત રાખવા માટે એન્ક્રિપ્શનનો ઉપયોગ કરે છે. જ્યારે આ સમયે Chromium દ્વારા <ph name="SITE" />થી કનેક્ટ કરવાનો પ્રયાસ થયો, ત્યારે વેબસાઇટે અસામાન્ય અને ખોટા લૉગ ઇન વિગતને પાછા મોકલ્યાં. આવું ત્યારે થઈ શકે જ્યારે કોઈ હુમલાખોર <ph name="SITE" /> હોવાનો ડોળ કરવાનો પ્રયાસ કરી રહ્યો હોવ અથવા કોઈ Wi-Fi સાઇન-ઇન સ્ક્રીને કનેક્શનમાં વિક્ષેપ પાડ્યો હોય. તમારી માહિતી હજી પણ સુરક્ષિત છે કારણ કે Chromium એ કોઈ પણ ડેટા વિનિમય થાય એ પહેલાં જ કનેક્શન રોકી દીધું.</translation>
<translation id="9106062320799175032">બિલિંગ સરનામું ઉમેરો</translation>
<translation id="9114524666733003316">કાર્ડ કન્ફર્મ કરી રહ્યાં છીએ...</translation>
<translation id="9128870381267983090">નેટવર્કથી કનેક્ટ કરો</translation>
<translation id="9137013805542155359">મૂળ બતાવો</translation>
-<translation id="9137248913990643158">આ ઍપ્લિકેશનનો ઉપયોગ કરતાં પહેલાં કૃપા કરીને Chrome ને પ્રારંભ કરો અને સાઇન ઇન કરો.</translation>
<translation id="9141013498910525015">ઍડ્રેસ મેનેજ કરો</translation>
<translation id="9148088599418889305">વિતરણની પદ્ધતિ પસંદ કરો</translation>
<translation id="9148507642005240123">&amp;છેલ્લો ફેરફાર રદ કરો</translation>
diff --git a/chromium/components/strings/components_strings_hi.xtb b/chromium/components/strings/components_strings_hi.xtb
index 457f9346b21..0ac94061904 100644
--- a/chromium/components/strings/components_strings_hi.xtb
+++ b/chromium/components/strings/components_strings_hi.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">इंडेक्स-5x8</translation>
<translation id="1088860948719068836">कार्ड पर नाम जोड़ें</translation>
<translation id="1089439967362294234">पासवर्ड बदलें</translation>
+<translation id="1096545575934602868">इस फ़ाइल में <ph name="MAX_ITEMS_LIMIT" /> से ज़्यादा एंट्री नहीं हो सकती. इसके बाद की सभी एंट्री खारिज हो जाएंगी.</translation>
<translation id="109743633954054152">Chrome सेटिंग में पासवर्ड प्रबंधित करें</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> का हमेशा अनुवाद करें</translation>
<translation id="1107591249535594099">चेक किए होने पर, ज़्यादा तेज़ फ़ॉर्म भरने के लिए Chrome इस डिवाइस पर आपके कार्ड की कॉपी संग्रहित कर लेगा.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> की <ph name="BEGIN_LINK" />सहेजी गई (कैश) कॉपी<ph name="END_LINK" /> एक्सेस करें</translation>
<translation id="1156303062776767266">आप स्थानीय या शेयर की गई फ़ाइल देख रहे हैं</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ने अनपेक्षित रूप से कनेक्शन बंद कर दिया है.</translation>
+<translation id="115926840831309955">अपना कार्ड वेरीफ़िकेशन कोड (सीवीसी) जाँचें और फिर से कोशिश करें या कार्ड की समयसीमा खत्म होने की तारीख में बदलाव करें</translation>
<translation id="1161325031994447685">वाई-फ़ाई से फिर से कनेक्ट करें</translation>
<translation id="1165039591588034296">गड़बड़ी</translation>
<translation id="1175364870820465910">&amp;प्रिंट करें...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"आपके कंप्यूटर पर मौजूद सॉफ़्टवेयर Chrome को सुरक्षित रूप से वेब से कनेक्ट होने से रोक रहा है" (केवल Windows कंप्यूटर)</translation>
<translation id="1294154142200295408">अलग-अलग तरह की कमांड-लाइन</translation>
<translation id="129553762522093515">हाल ही में बंद किए गए</translation>
+<translation id="1298536327547837046">मैलवेयर स्कैनिंग</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />अपनी कुकी साफ़ करके देखें<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">बंद की गई सुविधाएं</translation>
<translation id="1320233736580025032">पीआरसी1 (एन्वेलप)</translation>
<translation id="132301787627749051">क्लिपबोर्ड इमेज खोजें</translation>
<translation id="1323433172918577554">और दिखाएं</translation>
@@ -116,6 +120,7 @@
<translation id="1521655867290435174">Google पत्रक</translation>
<translation id="1527263332363067270">कनेक्शन का इंतज़ार हो रहा है</translation>
<translation id="1529521330346880926">10x15 (एन्वेलप)</translation>
+<translation id="1530707389502320859">जिस साइट पर आपने जाने की कोशिश की, वह नकली लग रही है. हमलावर कभी-कभी यूआरएल में छोटे और नज़र न आने वाले बदलाव करके साइट की नकल कर लेते हैं.</translation>
<translation id="1531205177818805254">एक्ज़ीक्यूटिव</translation>
<translation id="1532118530259321453">इस पेज का कहना है कि</translation>
<translation id="153384715582417236">फिलहाल बस इतना ही</translation>
@@ -156,7 +161,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">एफ़</translation>
<translation id="1718029547804390981">एनोटेट करने के लिए दस्तावेज़ बहुत बड़ा है</translation>
-<translation id="1721312023322545264">आपको <ph name="NAME" /> से इस साइट पर जाने की अनुमति लेनी होगी</translation>
<translation id="1721424275792716183">* फ़ील्ड ज़रूरी है</translation>
<translation id="1727741090716970331">मान्य कार्ड नंबर जोड़ें</translation>
<translation id="1728677426644403582">आप एक वेब पेज का स्रोत देख रहे हैं</translation>
@@ -180,8 +184,9 @@
<translation id="1822540298136254167">आप किन वेबसाइटों पर जाते हैं और उन पर कितना समय देते हैं</translation>
<translation id="1826516787628120939">जाँच की जा रही है</translation>
<translation id="1834321415901700177">इस साइट में हानिकारक प्रोग्राम हैं</translation>
+<translation id="1838374766361614909">खोज साफ़ करें</translation>
<translation id="1839551713262164453">गड़बड़ियों के चलते नीति मानों की पुष्टि नहीं हो सकी</translation>
-<translation id="1842969606798536927">भुगतान करें</translation>
+<translation id="1842969606798536927">पैसे चुकाएं</translation>
<translation id="1871208020102129563">प्रॉक्‍सी की सेटिंग इस तरह से की गई है कि वह फ़िक्‍स्‍ड प्रॉक्‍सी सर्वर इस्तेमाल करे, न कि .pac स्‍क्रिप्‍ट यूआरअल.</translation>
<translation id="1871284979644508959">ज़रूरी फ़ील्ड</translation>
<translation id="1874765382782611674">स्वीकार किए जाने वाले डेबिट कार्ड</translation>
@@ -190,6 +195,7 @@
<translation id="1883255238294161206">सूची छोटी करें</translation>
<translation id="1898423065542865115">फ़िल्टर किया जा रहा है</translation>
<translation id="1914326953223720820">अनज़िप सेवा</translation>
+<translation id="1915697529809968049">क्या आप कार्ड वेरीफ़िकेशन कोड (सीवीसी) के बजाय टच आईडी का इस्तेमाल करना चाहते हैं?</translation>
<translation id="1916770123977586577">इस साइट पर अपनी अपडेट की गई सेटिंग लागू करने के लिए, इस पेज को फिर से लोड करें</translation>
<translation id="1919345977826869612">विज्ञापन</translation>
<translation id="1919367280705858090">गड़बड़ी के किसी खास मैसेज से मदद पाना</translation>
@@ -201,6 +207,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> बुकमार्क</translation>
<translation id="1973335181906896915">क्रमबद्ध करने में गड़बड़ी</translation>
<translation id="1974060860693918893">बेहतर</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />आप जिन पेजों पर जाते हैं उनमें से कुछ के यूआरएल, सिस्टम की थोड़ी जानकारी, और पेज की कुछ सामग्री<ph name="END_WHITEPAPER_LINK" /> Google को भेजकर Chrome की सुरक्षा सुधारने में मदद करें. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">फ़र्मवेयर वर्शन</translation>
<translation id="1981206234434200693">Chrome के ब्राउज़िंग इतिहास का डेटा हटाएं</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{और 1 ज़्यादा}one{और # ज़्यादा}other{और # ज़्यादा}}</translation>
@@ -246,10 +253,12 @@
<translation id="2202020181578195191">खत्म होने का मान्य वर्ष डालें</translation>
<translation id="2212735316055980242">नीति नहीं मिली</translation>
<translation id="2213606439339815911">प्रविष्टियां फ़ेच की जा रही हैं...</translation>
+<translation id="2215727959747642672">फ़ाइल में बदलाव करना</translation>
<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> पर इस समय मौजूद हमलावर ऐसे खतरनाक ऐप्लिकेशन इंस्टॉल कर सकते हैं जो आपके डिवाइस को नुकसान पहुंचा सकते हैं और आपके मोबाइल बिल में अनजाने खर्चे जोड़ सकते हैं या आपकी व्‍यक्‍तिगत जानकारी चुरा सकते हैं. <ph name="BEGIN_LEARN_MORE_LINK" />ज़्यादा जानें<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">इंटरनेट कनेक्शन नहीं है</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />गड़बड़ी की पहचान करने वाले ऐप्लिकेशन<ph name="END_LINK" /> का उपयोग करके अपने कनेक्शन को ठीक करें</translation>
<translation id="2239100178324503013">अभी भेजें</translation>
+<translation id="2248949050832152960">WebAuthn का इस्तेमाल करें</translation>
<translation id="225207911366869382">यह मान इस नीति के लिए हटा दिया गया है.</translation>
<translation id="2257315177824333709">माफ़ करें, आपके कार्ड को अभी सेव नहीं किया जा सकता</translation>
<translation id="2262243747453050782">HTTP गड़बड़ी</translation>
@@ -297,7 +306,6 @@
<translation id="2479410451996844060">गलत खोज URL.</translation>
<translation id="2482878487686419369">सूचनाएं</translation>
<translation id="248348093745724435">मशीन के लिए नीतियां</translation>
-<translation id="2485387744899240041">आपके डिवाइस और ब्राउज़र के लिए उपयोगकर्ता नाम</translation>
<translation id="2491120439723279231">सर्वर के प्रमाणपत्र में त्रुटियां हैं.</translation>
<translation id="2493640343870896922">लेटर-प्लस</translation>
<translation id="2495083838625180221">JSON पार्सर</translation>
@@ -307,6 +315,7 @@
<translation id="2501278716633472235">वापस जाएं</translation>
<translation id="2503184589641749290">स्वीकृत डेबिट और प्रीपेड कार्ड</translation>
<translation id="2505268675989099013">खाते की सुरक्षा करें</translation>
+<translation id="2515335152965840738">अनदेखा करें</translation>
<translation id="2515629240566999685">अपने इलाके में सिग्नल की जाँच करें</translation>
<translation id="2523886232349826891">सिर्फ़ इस डिवाइस पर सेव किया गया</translation>
<translation id="2524461107774643265">ज़्यादा जानकारी जोड़ें</translation>
@@ -331,7 +340,6 @@
<translation id="2653659639078652383">सबमिट करें</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{कोई पासवर्ड नहीं है}=1{(<ph name="DOMAIN_LIST" /> के लिए) 1 पासवर्ड}=2{(<ph name="DOMAIN_LIST" /> के लिए) 2 पासवर्ड}one{(<ph name="DOMAIN_LIST" /> के लिए) # पासवर्ड}other{(<ph name="DOMAIN_LIST" /> के लिए) # पासवर्ड}}</translation>
<translation id="2666117266261740852">दूसरे टैब या ऐप्लिकेशन बंद करें</translation>
-<translation id="267371737713284912">पहले जैसा करने के लिए <ph name="MODIFIER_KEY_DESCRIPTION" /> दबाएं</translation>
<translation id="2674170444375937751">क्या आप वाकई अपने इतिहास से इन पेजों को मिटाना चाहते हैं?</translation>
<translation id="2676271551327853224">रॉक-8के</translation>
<translation id="2677748264148917807">छोड़ें</translation>
@@ -341,12 +349,12 @@
<translation id="2704283930420550640">मान का प्रारूप से मिलान नहीं होता.</translation>
<translation id="2705137772291741111">इस साइट की सहेजी गई (संचित) कॉपी पढ़ने योग्य नहीं थी.</translation>
<translation id="2709516037105925701">ऑटोमैटिक भरना</translation>
-<translation id="2712173769900027643">अनुमति मांगें</translation>
<translation id="2713444072780614174">सफ़ेद</translation>
<translation id="2720342946869265578">आस-पास</translation>
<translation id="2721148159707890343">अनुरोध कामयाब रहा</translation>
<translation id="2728127805433021124">सर्वर का प्रमाणपत्र कमज़ोर एल्गोरिद्म का उपयोग करके हस्ताक्षरित किया गया है.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />नेटवर्क कनेक्टिविटी चलाकर देखें<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">इन सुविधाओं को चालू करके, आप ब्राउज़र डेटा खो सकते हैं या आपकी सुरक्षा या निजता से समझौता हो सकता है. चालू की गई सुविधाएं इस ब्राउज़र के सभी उपयोगकर्ताओं पर लागू होती हैं.</translation>
<translation id="2735043616039983645">इस नीति के लिए एक-दूसरे से अलग मान वाले एक से ज़्यादा स्रोत मौजूद हैं!</translation>
<translation id="2738330467931008676">पिकअप का पता चुनें</translation>
<translation id="2740531572673183784">ठीक है</translation>
@@ -357,16 +365,15 @@
<translation id="2784949926578158345">कनेक्‍शन रीसेट किया गया था.</translation>
<translation id="2788784517760473862">स्वीकृत क्रेडिट कार्ड</translation>
<translation id="2792012897584536778">इस डिवाइस के एडमिन ने कुछ सुरक्षा प्रमाणपत्र सेट अप किए हैं. इनसे उन्हें ऐसी वेबसाइटों की सामग्री दिख सकती है जिन पर आप जाते हैं.</translation>
-<translation id="2794233252405721443">साइट अवरोधित है</translation>
<translation id="2799020568854403057">आगे आने वाली साइट में नुकसान पहुंचाने वाले ऐप्लिकेशन हैं</translation>
<translation id="2799223571221894425">फिर से लॉन्‍च करें</translation>
<translation id="2803306138276472711">Google सुरक्षित ब्राउज़िंग को <ph name="SITE" /> पर हाल ही में <ph name="BEGIN_LINK" />मैलवेयर का पता चला<ph name="END_LINK" /> है. आमतौर पर सुरक्षित रहने वाली वेबसाइटें कभी-कभी मैलवेयर से संक्रमित हो जाती हैं.</translation>
+<translation id="2815364696811431560">साइट छोड़ें</translation>
<translation id="2824775600643448204">पता और सर्च बार</translation>
<translation id="2826760142808435982">कनेक्शन को <ph name="CIPHER" /> का उपयोग करके सुरक्षित किया गया है और उसकी पहचान की गई है और यह मुख्य विनिमय तकनीक के रूप में <ph name="KX" /> का उपयोग करता है.</translation>
<translation id="2835170189407361413">फ़ॉर्म साफ़ करें</translation>
<translation id="2847118875340931228">गुप्त विंडो खोलें</translation>
<translation id="2850739647070081192">न्योता (एन्वेलप)</translation>
-<translation id="2851634818064021665">आपको इस साइट पर जाने की अनुमति लेनी होगी</translation>
<translation id="2856444702002559011">हो सकता है कि हमलावर <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> से आपकी जानकारी (जैसे- पासवर्ड, मैसेज या क्रेडिट कार्ड वगैरह) चुराने की कोशिश कर रहे हों. <ph name="BEGIN_LEARN_MORE_LINK" />ज़्यादा जानें<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">ए1</translation>
<translation id="2881276955470682203">कार्ड सेव करें?</translation>
@@ -391,6 +398,7 @@
<translation id="2985306909656435243">अगर सक्षम किया गया हो, तो ज़्यादा तेज़ी से फ़ॉर्म भरने के लिए क्रोमियम इस डिवाइस पर आपके कार्ड की एक कॉपी संग्रहित करेगा.</translation>
<translation id="2985398929374701810">मान्य पता डालें</translation>
<translation id="2986368408720340940">पिकअप का यह तरीका उपलब्ध नहीं है. कोई दूसरा तरीका आज़माएं.</translation>
+<translation id="2987034854559945715">कोई मिलते-जुलते फ़ीचर नहीं</translation>
<translation id="2991174974383378012">वेबसाइटों के साथ साझाकरण</translation>
<translation id="2991571918955627853">आप इस समय <ph name="SITE" /> पर नहीं जा सकते क्योंकि वेबसाइट एचएसटीएस का उपयोग करती है. नेटवर्क की गड़बड़ियां और हमले आमतौर पर कुछ समय के लिए होते हैं इसलिए यह पेज शायद बाद में ठीक से काम करेगा.</translation>
<translation id="3005723025932146533">सहेजी गई कॉपी दिखाएं</translation>
@@ -401,6 +409,7 @@
<translation id="3024663005179499861">गलत नीति प्रकार</translation>
<translation id="3037605927509011580">हे भगवान!</translation>
<translation id="3041612393474885105">प्रमाणपत्र जानकारी</translation>
+<translation id="3057676462092457419">DnsOverHttps मोड <ph name="SECURE_DNS_MODE_SECURE" /> अभी इस्तेमाल नहीं किया जा सकता. मोड <ph name="SECURE_DNS_MODE_OFF" /> पर सेट किया गया है.</translation>
<translation id="3060227939791841287">सी9 (एन्वेलप)</translation>
<translation id="3061707000357573562">पैच सेवा</translation>
<translation id="3064966200440839136">किसी बाहरी ऐप्लिकेशन के ज़रिए भुगतान करने के लिए गुप्त मोड छोड़ रहे हैं. जारी रखना चाहते हैं?</translation>
@@ -425,6 +434,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> पर <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">भुगतान रद्द करें</translation>
<translation id="3207960819495026254">बुकमार्क किया गया</translation>
+<translation id="3209034400446768650">पेज पर शुल्क लिया जा सकता है</translation>
<translation id="3225919329040284222">सर्वर द्वारा कोई प्रमाणपत्र प्रस्‍तुत किया गया, जो बिल्‍ट-इन अपेक्षाओं से मिलान नहीं करता. इन अपेक्षाओं को आपकी सुरक्षा करने के लिए कुछ, उच्‍च-सुरक्षा वेबसाइटों के लिए शामिल किया गया है.</translation>
<translation id="3226128629678568754">पेज को लोड करने के लिए ज़रूरी डेटा फिर सबमिट करने के लिए 'फिर लोड करें' बटन दबाएं.</translation>
<translation id="3227137524299004712">माइक्रोफ़ोन</translation>
@@ -432,7 +442,6 @@
<translation id="3229041911291329567">आपके डिवाइस और ब्राउज़र के वर्शन के बारे में जानकारी</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> का CVC डालें.</translation>
<translation id="3234666976984236645">इस साइट पर हमेशा महत्‍वपूर्ण सामग्री का पता लगाएं</translation>
-<translation id="3254409185687681395">इस पेज को बुकमार्क करें</translation>
<translation id="3270847123878663523">&amp;पुन: क्रमित करना वापस लाएं</translation>
<translation id="3274521967729236597">पा-काई</translation>
<translation id="3282497668470633863">कार्ड पर नाम जोड़ें</translation>
@@ -442,7 +451,6 @@
<translation id="3320021301628644560">बिलिंग पता जोड़ें</translation>
<translation id="3324983252691184275">गहरा लाल</translation>
<translation id="3338095232262050444">सुरक्षित</translation>
-<translation id="3345135638360864351">इस साइट को एक्‍सेस करने का आपका अनुरोध <ph name="NAME" /> को नहीं भेजा जा सका. कृपया फिर से कोशिश करें.</translation>
<translation id="3355823806454867987">प्रॉक्सी सेटिंग बदलें...</translation>
<translation id="3361596688432910856">Chrome नीचे दी गई जानकारी को <ph name="BEGIN_EMPHASIS" />सेव नहीं करेगा<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -476,18 +484,15 @@
<translation id="3462200631372590220">बेहतर को छिपाएं</translation>
<translation id="3467763166455606212">कार्ड मालिक का नाम ज़रूरी है</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, फ़िलहाल खुला है, 'टैब' दबाएं फिर खुले टैब पर जाने के लिए Enter दबाएं</translation>
-<translation id="3479539252931486093">क्या यह अनपेक्षित था? <ph name="BEGIN_LINK" />हमें बताएं<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">अभी नहीं</translation>
<translation id="3484560055331845446">आप अपने Google खाते का ऐक्सेस खो सकते हैं. Chrome आपको इसी समय अपना पासवर्ड बदलने का सुझाव देता है. आपको साइन इन करने को कहा जाएगा.</translation>
<translation id="3495081129428749620">पेज में ढूंढें
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">हम इस समय आपके अभिभावक तक नहीं पहुंच पा रहे हैं. कृपया फिर से प्रयास करें.</translation>
<translation id="3512163584740124171">इस नीति को अनदेखा कर दिया गया है, क्योंकि इसी नीति समूह की दूसरी नीति को ज़्यादा प्राथमिकता दी गई है.</translation>
<translation id="3528171143076753409">सर्वर का प्रमाणपत्र विश्वसनीय नहीं है.</translation>
<translation id="3528485271872257980">गहरा भूरा</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{सिंक किए हुए डिवाइस पर कम से कम 1 आइटम}=1{1 आइटम (सिंक किए हुए डिवाइस पर और भी बहुत कुछ)}one{# आइटम (सिंक किए हुए डिवाइस पर और भी बहुत कुछ)}other{# आइटम (सिंक किए हुए डिवाइस पर और भी बहुत कुछ)}}</translation>
<translation id="3539171420378717834">इस डिवाइस पर इस कार्ड की कॉपी रखें</translation>
-<translation id="3556433843310711081">आपका प्रबंधक इसे आपके लिए अनवरोधित कर सकता है</translation>
<translation id="3566021033012934673">आपका कनेक्शन निजी नहीं है</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> पर एम्बेड किए गए पेज का कहना है कि</translation>
@@ -515,6 +520,7 @@
<translation id="3678529606614285348">पेज को नई गुप्त विंडो में खोलें (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">खराबी रिपोर्ट <ph name="CRASH_TIME" /> पर कैप्चर की गई, <ph name="UPLOAD_TIME" /> पर अपलोड की गई</translation>
<translation id="3681007416295224113">प्रमाणपत्र जानकारी</translation>
+<translation id="3701427423622901115">रीसेट स्वीकार किया गया.</translation>
<translation id="3704162925118123524">आप जिस नेटवर्क का उपयोग कर रहे हैं उसके लिए आपको लॉगिन पेज पर जाने की ज़रूरत हो सकती है.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">लोड हो रही हैं...</translation>
@@ -531,6 +537,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> पर मौजूद हमलावर आपको सॉफ़्टवेयर इंस्टॉल करने या आपकी व्यक्तिगत जानकारी (उदाहरण के लिए, पासवर्ड, फ़ोन नंबर या क्रेडिट कार्ड) हासिल करने जैसा खतरनाक काम करने के लिए फंसा सकते हैं. <ph name="BEGIN_LEARN_MORE_LINK" />ज़्यादा जानें<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">सर्वर गड़बड़ी के कारण अनुवाद विफल.</translation>
<translation id="3759461132968374835">आपने हाल में खराबी की कोई रिपोर्ट नहीं की है. खराबी रिपोर्ट बंद होने पर होने वाली खराबी यहां दिखाई नहीं देगी.</translation>
+<translation id="3760561303380396507">क्या आप कार्ड वेरीफ़िकेशन कोड (सीवीसी) के बजाय Windows Hello का इस्तेमाल करना चाहते हैं?</translation>
<translation id="3761718714832595332">स्थिति छिपाएं</translation>
<translation id="3765032636089507299">सुरक्षित ब्राउज़िंग पेज अभी बन रहा है.</translation>
<translation id="3778403066972421603">क्या आप इस कार्ड को अपने Google खाते में और इस डिवाइस में सेव करना चाहते हैं?</translation>
@@ -540,6 +547,7 @@
<translation id="3789155188480882154">आकार 16</translation>
<translation id="3797522431967816232">पीआरसी3 (एन्वेलप)</translation>
<translation id="3807873520724684969">खतरनाक सामग्री ब्लॉक की गई.</translation>
+<translation id="3808375843007691220">चेतावनी: आगे ऐसी सुविधाएं हैं जो प्रयोग में हैं!</translation>
<translation id="3810973564298564668">प्रबंधित करें</translation>
<translation id="382518646247711829">अगर आप प्रॉक्सी सर्वर का उपयोग करते हैं...</translation>
<translation id="3828924085048779000">खाली 'पासफ़्रेज़' की अनुमति नहीं है.</translation>
@@ -548,11 +556,11 @@
<translation id="3858027520442213535">तारीख और समय अपडेट करें</translation>
<translation id="3884278016824448484">विरोधाभासी डिवाइस पहचानकर्ता</translation>
<translation id="3885155851504623709">पैरिश</translation>
-<translation id="3886446263141354045">यह साइट एक्सेस करने का आपका अनुरोध <ph name="NAME" /> को भेज दिया गया है</translation>
<translation id="3890664840433101773">ईमेल जोड़ें</translation>
<translation id="3901925938762663762">इस कार्ड की समय सीमा खत्म हो गई है</translation>
<translation id="3906600011954732550">बी5-एक्स्ट्रा</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">क्या आप कार्ड वेरीफ़िकेशन कोड (सीवीसी) के बजाय WebAuthn का इस्तेमाल करना चाहते हैं?</translation>
<translation id="3946209740501886391">इस साइट पर हमेशा पूछें</translation>
<translation id="3949571496842715403">यह सर्वर प्रमाणित नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसके सुरक्षा प्रमाणपत्र में विषय के वैकल्पिक नाम नहीं बताए गए हैं. ऐसा गलत कॉन्फ़िगरेशन के कारण या किसी आक्रमणकर्ता की ओर से आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
<translation id="3949601375789751990">आपका ब्राउज़िंग इतिहास यहां दिखाई देता है</translation>
@@ -563,11 +571,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{कुछ नहीं}=1{1 साइट से }one{# साइटों से }other{# साइटों से }}</translation>
<translation id="397105322502079400">गणना की जा रही है...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> को ब्लॉक किया गया है</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ने आपके ब्राउज़र पर Chrome Enterprise की खतरे से बचाने की सुविधा चालू की है. Chrome Enterprise की खतरे से बचाने की सुविधा आपका कुछ डेटा ऐक्सेस कर सकती है.</translation>
<translation id="3987940399970879459">एक एमबी से कम</translation>
<translation id="40103911065039147">{URL_count,plural, =1{आस-पास 1 वेब पेज है}one{आस-पास # वेब पेज हैं}other{आस-पास # वेब पेज हैं}}</translation>
<translation id="4030383055268325496">&amp;जोड़ना वापस लाएं</translation>
<translation id="4032320456957708163">आपके ब्राउज़र को <ph name="ENROLLMENT_DOMAIN" /> प्रबंधित करता है</translation>
-<translation id="4034375457890803692">जो लिंक आप खोलना चाहते हैं वह आपको ऐसी वेबसाइट तक ले जाएगा, जिस पर आप सामान्य तौर पर नहीं जाते. यह वेबसाइट आपको गुमराह कर सकती है.</translation>
<translation id="4058922952496707368">कुंजी "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">सी1 (एन्वेलप)</translation>
<translation id="4067947977115446013">मान्य पता जोड़ें</translation>
@@ -580,6 +588,7 @@
<translation id="4103249731201008433">डिवाइस की क्रम संख्या गलत है</translation>
<translation id="410351446219883937">अपने आप चलाएं</translation>
<translation id="4103763322291513355">प्रतिबंधित किए गए यूआरएल और आपके सिस्टम ए़़डमिन ने जिन अन्य नीतियों को लागू किया है, उन्हें देखने के लिए &lt;strong&gt;chrome://policy&lt;/strong&gt; पर जाएं.</translation>
+<translation id="4108231218301530806">अगली बार इस कार्ड की पुष्टि के लिए फ़िंगरप्रिंट का इस्तेमाल करें.</translation>
<translation id="4110652170750985508">अपना भुगतान देखें</translation>
<translation id="4112140312785995938">पीछे जाएं</translation>
<translation id="4116663294526079822">इस साइट पर हमेशा अनुमति दें</translation>
@@ -594,6 +603,7 @@
<translation id="4171400957073367226">गलत सत्यापन हस्ताक्षर</translation>
<translation id="4173315687471669144">फ़ूल्ज़कैप</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> और आइटम}one{<ph name="ITEM_COUNT" /> और आइटम}other{<ph name="ITEM_COUNT" /> और आइटम}}</translation>
+<translation id="4176463684765177261">अक्षम किए गए</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">अगली बार तेज़ी से भुगतान करने के लिए, अपने कार्ड और बिलिंग के पते को अपने Google खाते में जोड़ें.</translation>
<translation id="4196861286325780578">&amp;ले जाना फिर से करें</translation>
@@ -630,6 +640,7 @@
<translation id="4277028893293644418">पासवर्ड रीसेट करें</translation>
<translation id="4279811152705618813">आपके <ph name="DEVICE_TYPE" /> का प्रबंधन <ph name="ENROLLMENT_DOMAIN" /> करता है</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{यह कार्ड आपके Google खाते में सेव कर लिया गया है}one{ये कार्ड आपके Google खाते में सेव कर लिए गए हैं}other{ये कार्ड आपके Google खाते में सेव कर लिए गए हैं}}</translation>
+<translation id="428847186335018806">Chrome में डाउनलोड या अपलोड किए जाने वाली फ़ाइलों को स्कैन करें.</translation>
<translation id="42981349822642051">विस्तृत करें</translation>
<translation id="4302965934281694568">शू3 (एन्वेलप)</translation>
<translation id="4305817255990598646">बदलें</translation>
@@ -659,7 +670,6 @@
<translation id="4435702339979719576">पोस्टकार्ड)</translation>
<translation id="443673843213245140">प्रॉक्‍सी का उपयोग अक्षम है लेकिन कोई स्‍पष्ट प्रॉक्‍सी कॉन्फ़िगरेशन दर्ज किया गया है.</translation>
<translation id="445100540951337728">स्वीकृत डेबिट कार्ड</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> संदिग्ध गतिविधि</translation>
<translation id="4466881336512663640">फ़ॉर्म में किए गए बदलाव हटा दिए जाएँगे. क्या आप वाकई जारी रखना चाहते हैं?</translation>
<translation id="4477350412780666475">अगला ट्रैक</translation>
<translation id="4482953324121162758">इस साइट का अनुवाद नहीं किया जाएगा.</translation>
@@ -686,6 +696,7 @@
<translation id="4594403342090139922">मिटाना &amp;पहले जैसा करें</translation>
<translation id="4597348597567598915">आकार 8</translation>
<translation id="4600854749408232102">सी6/सी5 (एन्वेलप)</translation>
+<translation id="464342062220857295">खोज सुविधाएं</translation>
<translation id="4646534391647090355">मुझे अभी वहां ले जाएं</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">यह सर्वर यह प्रमाणित नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसके सुरक्षा प्रमाणपत्र में त्रुटियां हैं. ऐसा गलत कॉन्फ़िगरेशन के कारण या किसी आक्रमणकर्ता द्वारा आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
@@ -694,7 +705,6 @@
<translation id="4691835149146451662">आर्किटेक्चर-ए (एन्वेलप)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">आपका कनेक्शन बाधित था</translation>
-<translation id="471880041731876836">आपको इस साइट पर जाने की अनुमति नहीं है</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवर्क निदान चलाकर देखें<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">नीतियां फिर से लोड करें</translation>
<translation id="4728558894243024398">प्लेटफ़ॉर्म</translation>
@@ -722,7 +732,6 @@
<translation id="4816492930507672669">पेज में फ़िट करें</translation>
<translation id="4850886885716139402">देखें</translation>
<translation id="4854362297993841467">वितरण का यह तरीका उपलब्ध नहीं है. कोई दूसरा तरीका आज़माएं.</translation>
-<translation id="4858792381671956233">आपने अपने अभिभावकों से पूछा है कि इस साइट पर जाना ठीक है या नहीं</translation>
<translation id="4864052566555297930">सुरक्षा सुझाव:</translation>
<translation id="4876188919622883022">सरल बनाया गया व्यू</translation>
<translation id="4876305945144899064">कोई उपयोगकर्ता नाम नहीं</translation>
@@ -746,7 +755,9 @@
<translation id="4974590756084640048">चेतावनियां फिर से चालू करें</translation>
<translation id="4984339528288761049">पीआरसी5 (एन्वेलप)</translation>
<translation id="4989163558385430922">सभी देखें</translation>
+<translation id="4989542687859782284">अनुपलब्ध</translation>
<translation id="4989809363548539747">यह प्लग इन समर्थित नहीं है</translation>
+<translation id="4995216769782533993">इस साइट से कार्ड की जानकारी शेयर करने के लिए अपने सुरक्षा कोड की पुष्टि करें</translation>
<translation id="5002932099480077015">अगर सक्षम किया हुआ हो, तो Chrome फ़ॉर्म को तेज़ी से भरने के लिए इस डिवाइस पर आपके कार्ड की एक प्रति संग्रहित करेगा.</translation>
<translation id="5015510746216210676">मशीन का नाम:</translation>
<translation id="5017554619425969104">आपका कॉपी किया हुआ टेक्स्ट</translation>
@@ -775,6 +786,7 @@
<translation id="5115216390227830982">यूरोपियन-ईडीपी</translation>
<translation id="5115563688576182185">(64-बिट)</translation>
<translation id="5125394840236832993">बी-प्लस</translation>
+<translation id="5126510351761255129">कार्ड की पुष्टि करें</translation>
<translation id="5135404736266831032">पते प्रबंधित करें...</translation>
<translation id="5138227688689900538">कम दिखाएं</translation>
<translation id="5141240743006678641">अपने Google क्रेडेंशियल के साथ सिंक किए गए पासवर्ड सुरक्षित करें</translation>
@@ -801,6 +813,7 @@
<translation id="5251803541071282808">क्लाउड</translation>
<translation id="5252000469029418751">सी7 (एन्वेलप)</translation>
<translation id="5254958791078852567">ई1</translation>
+<translation id="5269999699920406580">सिस्टम से जुड़ी हुई सुविधाओं को सिर्फ़ मालिक ही सेट कर सकता है: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">चेतावनी: इस नीति को PolicyDictionaryMultipleSourceMergeList नीति में बताए अनुसार नहीं मिलाया जा सकता, क्योंकि यह शब्दकोश की उन नीतियों का हिस्सा नहीं है जिन्हें मिलाया जा सकता है.</translation>
<translation id="5283044957620376778">बी1</translation>
<translation id="528468243742722775">खत्म</translation>
@@ -824,7 +837,6 @@
<translation id="536296301121032821">नीति सेटिंग संग्रहित करने में विफल</translation>
<translation id="5371425731340848620">कार्ड अपडेट करें</translation>
<translation id="5377026284221673050">"आपकी घड़ी पीछे चल रही है" या "आपकी घड़ी आगे चल रही है" या "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">इस पेज से आपको धोखा देने, निजी जानकारी चुराने या डिवाइस को नुकसान पहुंचाने की कोशिश की जा सकती है. निजी जानकारी डालते समय या डाउनलोड की गई फ़ाइलें खोलते समय सावधानी बरतें.</translation>
<translation id="5384855140246857529">सभी डिवाइस पर अपने कार्ड का इस्तेमाल करने के लिए, साइन इन करें और 'सिंक करें' चालू करें.</translation>
<translation id="5386426401304769735">इस साइट की प्रमाणपत्र शृंखला में, SHA-1 का उपयोग करके हस्ताक्षर किया गया प्रमाणपत्र शामिल है.</translation>
<translation id="538659543871111977">ए4-टैब</translation>
@@ -838,6 +850,7 @@
<translation id="5457113250005438886">अमान्य</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> अन्य}one{<ph name="CONTACT_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> अन्य}other{<ph name="CONTACT_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> अन्य}}</translation>
<translation id="5470861586879999274">&amp;बदलाव को फिर से लागू करें</translation>
+<translation id="5473728911100096288">इन सुविधाओं को चालू करके, आप रोकी गई सुविधाएं इस्तेमाल करेंगे. ये आने वाले वर्शन में मौजूद नहीं होंगी.</translation>
<translation id="5478437291406423475">बी6/सी4 (एन्वेलप)</translation>
<translation id="5481076368049295676">यह सामग्री आपके डिवाइस पर ऐसा खतरनाक सॉफ़्टवेयर इंस्टॉल करने की कोशिश कर सकती है जो आपकी जानकारी चुरा सकता है या उसे हटा सकता है. <ph name="BEGIN_LINK" />फिर भी दिखाएं<ph name="END_LINK" /></translation>
<translation id="54817484435770891">मान्य पता जोड़ें</translation>
@@ -861,7 +874,6 @@
<translation id="5570825185877910964">खाते की सुरक्षा करें</translation>
<translation id="5571083550517324815">इस पते से पिक अप नहीं किया जा सकता. कोई दूसरा पता चुनें.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 इस्तेमाल में है}one{# इस्तेमाल में हैं}other{# इस्तेमाल में हैं}})</translation>
-<translation id="5572851009514199876">कृपया Chrome शुरू करके उसमें साइन इन करें ताकि Chrome देख सके कि क्या आपके पास यह साइट एक्सेस करने की अनुमति है.</translation>
<translation id="5580958916614886209">अपने क्रेडिट कार्ड की समय सीमा खत्म होने का महीना जांचें और फिर से कोशिश करें</translation>
<translation id="5586446728396275693">कोई सहेजा गया पता नहीं है</translation>
<translation id="5595485650161345191">पते में बदलाव करें</translation>
@@ -869,6 +881,7 @@
<translation id="560412284261940334">प्रबंधन समर्थित नहीं</translation>
<translation id="5605670050355397069">लेजर</translation>
<translation id="5607240918979444548">आर्किटेक्चर-सी</translation>
+<translation id="5608165884683734521">यह साइट नकली या धोखाधड़ी करने वाली हो सकती है. Chrome साइट छोड़ने का सुझाव देता है.</translation>
<translation id="5610142619324316209">कनेक्शन की जाँच करें</translation>
<translation id="5610807607761827392">आप <ph name="BEGIN_LINK" />सेटिंग<ph name="END_LINK" /> में कार्ड और पते प्रबंधित कर सकते हैं.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ने आपको कई बार रीडायरेक्ट किया है.</translation>
@@ -892,11 +905,11 @@
<translation id="5720705177508910913">मौजूदा उपयोगकर्ता</translation>
<translation id="5728056243719941842">सी5 (एन्वेलॉप)</translation>
<translation id="5730040223043577876">अगर आपने अपने पासवर्ड का दूसरी साइटों पर दोबारा इस्तेमाल किया है, तो Chrome आपको उसे रीसेट करने का सुझाव देता है.</translation>
-<translation id="5732392974455271431">आपके अभिभावक इसे आपके लिए अनवरोधित कर सकते हैं</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{अपने Google खाते में कार्ड सेव करें}one{अपने Google खाते में कार्ड सेव करें}other{अपने Google खाते में कार्ड सेव करें}}</translation>
<translation id="5763042198335101085">मान्य ईमेल पता डालें</translation>
<translation id="5765072501007116331">वितरण के तरीके और ज़रूरतें देखने के लिए, कोई पता चुनें</translation>
<translation id="5778550464785688721">MIDI डिवाइस पूरा नियंत्रण</translation>
+<translation id="5781136890105823427">परफ़ॉर्मेंस जांचना चालू है</translation>
<translation id="578305955206182703">ऐंबर</translation>
<translation id="57838592816432529">म्यूट करें</translation>
<translation id="5784606427469807560">आपके कार्ड की पुष्टि करते समय समस्‍या हुई. अपना इंटरनेट कनेक्‍शन जांचें और फिर से कोशिश करें.</translation>
@@ -913,13 +926,16 @@
<translation id="5860033963881614850">बंद</translation>
<translation id="5863847714970149516">आगे आने वाला पेज आपसे शुल्क लेने की कोशिश कर सकता है</translation>
<translation id="5866257070973731571">फ़ोन नंबर जोड़ें</translation>
+<translation id="5866898949289125849">आप डेवलपर के टूल वाला पेज देख रहे हैं</translation>
<translation id="5869405914158311789">इस साइट तक नहीं पहुंचा जा सकता</translation>
<translation id="5869522115854928033">सेव किए गए पासवर्ड</translation>
<translation id="5887400589839399685">कार्ड सेव किया गया</translation>
<translation id="5893752035575986141">क्रेडिट कार्ड स्वीकार किए जाते हैं.</translation>
+<translation id="5895138241574237353">फिर से प्रारंभ करें</translation>
<translation id="5901630391730855834">पीला</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (सिंक किया गया)</translation>
<translation id="5916664084637901428">चालू</translation>
+<translation id="59174027418879706">चालू किया गया</translation>
<translation id="5919090499915321845">बी10</translation>
<translation id="5921639886840618607">कार्ड को Google खाते में सेव करें?</translation>
<translation id="5922853866070715753">करीब-करीब हो गया है</translation>
@@ -953,6 +969,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">क्या आप अपने कार्ड का इस्तेमाल सभी डिवाइस पर करना चाहते हैं?</translation>
<translation id="6059925163896151826">USB डिवाइस</translation>
+<translation id="6060009363608157444">अमान्य DnsOverHttps मोड.</translation>
<translation id="6080696365213338172">आपने व्यवस्थापक द्वारा दिए गए प्रमाणपत्र के उपयोग से सामग्री ऐक्सेस की है. <ph name="DOMAIN" /> को दिया गया डेटा आपके व्यवस्थापक द्वारा बीच में रोका जा सकता है.</translation>
<translation id="6094273045989040137">एनोटेट करें</translation>
<translation id="610911394827799129">आपके Google खाते में <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> पर दूसरी तरह के ब्राउज़िंग इतिहास हो सकते हैं</translation>
@@ -1001,13 +1018,12 @@
<translation id="6404511346730675251">बुकमार्क में बदलाव करें</translation>
<translation id="6406765186087300643">सी0 (एन्वेलप)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> का समाप्ति तारीख और CVC डालें</translation>
-<translation id="6414888972213066896">आपने अपने अभिभावक से पूछा है कि इस साइट पर जाना ठीक है या नहीं</translation>
<translation id="6415778972515849510">क्रोमियम से आप अपने Google खाते की सुरक्षा कर सकते हैं और अपना पासवर्ड बदल सकते हैं.</translation>
-<translation id="6417515091412812850">प्रमाणपत्र को रद्द किया गया है या नहीं, इसकी जांच नहीं की जा सकी.</translation>
<translation id="6431585503458005759">सेव न करें</translation>
<translation id="6433490469411711332">संपर्क जानकारी में बदलाव करें</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ने कनेक्ट करने से मना कर दिया है.</translation>
<translation id="6434309073475700221">खारिज करें</translation>
+<translation id="6435221585574090192">सुरक्षा से जुड़ी उन गतिविधियों के बारे में डेटा शेयर करें जिन्हें Chrome Enterprise की खतरे से बचाने वाली सुविधा ने आपके एडमिन को फ़्लैग किया है. इनमें पेज के यूआरएल, फ़ाइल का नाम, और फ़ाइल का मेटाडेटा, आपके डिवाइस का उपयोगकर्ता नाम और Chrome उपयोगकर्ता नाम शामिल हो सकते हैं.</translation>
<translation id="6440503408713884761">अनदेखा किया गया</translation>
<translation id="6446163441502663861">काहू (एन्वेलप)</translation>
<translation id="6446608382365791566">और जानकारी जोड़ें</translation>
@@ -1016,20 +1032,19 @@
<translation id="6465306955648956876">पासवर्ड प्रबंधित करें...</translation>
<translation id="647261751007945333">डिवाइस नीतियां</translation>
<translation id="6476284679642588870">भुगतान के तरीकों को प्रबंधित करें</translation>
-<translation id="6477321094435799029">Chrome को इस पेज पर असामान्य कोड मिला था और उसने आपकी व्यक्तिगत जानकारी (उदाहरण के लिए, पासवर्ड, फ़ोन नंबर और क्रेडिट कार्ड) की सुरक्षा करने के लिए उसे रोक दिया है.</translation>
<translation id="6489534406876378309">क्रैश अपलोड करना प्रारंभ करें</translation>
<translation id="6499038740797743453">क्या पासवर्ड रीसेट करना चाहते हैं?</translation>
<translation id="6507833130742554667">क्रेडिट और डेबिट कार्ड स्वीकार किए जाते हैं.</translation>
<translation id="650855688985305916">हां, सेव करें</translation>
<translation id="6508722015517270189">Chrome को फिर से शुरू करें</translation>
<translation id="6517596291481585650">चेतावनी: इस नीति को सूची के तौर पर नीति के बताए अनुसार नहीं मिलाया जा सकता, क्योंकि यह सूची नहीं है.</translation>
+<translation id="6518133107902771759">पुष्टि करें</translation>
<translation id="6521745193039995384">चालू नहीं</translation>
<translation id="6529602333819889595">मिटाना &amp;फिर से करें</translation>
<translation id="6534179046333460208">जीता-जागता वेब के सुझाव</translation>
<translation id="6545864417968258051">ब्लूटूथ स्कैन करना</translation>
<translation id="6554795675067793129">आपके खाते का प्रबंधन <ph name="ENROLLMENT_DOMAIN" /> करता हैै.</translation>
<translation id="6556866813142980365">फिर से करें</translation>
-<translation id="6563469144985748109">आपके प्रबंधक ने अभी तक इसकी अनुमति नहीं दी है</translation>
<translation id="6569060085658103619">आप एक एक्सटेंशन पेज देख रहे हैं</translation>
<translation id="6578796323535178455">सी2 (एन्वेलप)</translation>
<translation id="6579990219486187401">हल्का गुलाबी रंग</translation>
@@ -1047,11 +1062,13 @@
<translation id="6643016212128521049">साफ़ करें</translation>
<translation id="6644283850729428850">यह नीति हटा दी गई है.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{कोई नहीं}=1{1 साइट से (आप अपने Google खाते से साइन आउट नहीं होंगे)}one{# साइटों से (आप अपने Google खाते से साइन आउट नहीं होंगे)}other{# साइटों से (आप अपने Google खाते से साइन आउट नहीं होंगे)}}</translation>
+<translation id="6652101503459149953">Windows Hello का इस्तेमाल करें</translation>
<translation id="6657585470893396449">पासवर्ड</translation>
<translation id="6670613747977017428">सुरक्षित जगह पर लौटें.</translation>
<translation id="6671697161687535275">क्रोमियम से फ़ॉर्म सुझाव निकालें?</translation>
<translation id="6685834062052613830">प्रस्थान करें और सेटअप पूरा करें</translation>
<translation id="6689271823431384964">आपके साइन इन किए होने की वजह से, Chrome आपको Google खाते में कार्ड सेव करने की सुविधा देता है. आप 'सेटिंग' में जाकर इसे बदल सकते हैं. कार्डधारक का नाम आपके खाते से लिया जाता है.</translation>
+<translation id="6707256370811247129">कैश मेमोरी की सामग्री और फ़ाइलों को स्कैन करें जिन्हें आप Chrome में डाउनलोड या अपलोड करते हैं.</translation>
<translation id="6710213216561001401">पिछला</translation>
<translation id="6710594484020273272">&lt;खोज शब्द लिखें&gt;</translation>
<translation id="671076103358959139">नाम दर्ज करने का टोकन:</translation>
@@ -1059,10 +1076,10 @@
<translation id="6738516213925468394">आपका डेटा <ph name="TIME" /> को <ph name="BEGIN_LINK" />सिंक करने के लिए लंबा पासवर्ड बनाकर<ph name="END_LINK" /> सुरक्षित किया गया था. सिंक शुरू करने के लिए पासवर्ड डालें.</translation>
<translation id="674375294223700098">अज्ञात सर्वर प्रमाणपत्र गड़बड़ी.</translation>
<translation id="6744009308914054259">कनेक्शन का इंतज़ार करते समय, ऑफ़लाइन लेख पढ़ने के लिए आप 'डाउनलोड' पर जा सकते हैं.</translation>
+<translation id="6747611005629681221">चेतावनी: आगे ऐसी सुविधाएं हैं जो रोक दी गई हैं!</translation>
<translation id="6753269504797312559">नीति मान</translation>
<translation id="6757797048963528358">आपका डिवाइस निष्क्रिय हो गया है.</translation>
<translation id="6768213884286397650">हगाकी (पोस्टकार्ड)</translation>
-<translation id="6778737459546443941">आपके अभिभावक ने अभी तक इसकी अनुमति नहीं दी है</translation>
<translation id="67862343314499040">बैंगनी</translation>
<translation id="6786747875388722282">एक्‍सटेंशन</translation>
<translation id="6790428901817661496">चलाएं</translation>
@@ -1070,6 +1087,7 @@
<translation id="681021252041861472">ज़रूरी फ़ील्ड</translation>
<translation id="6810899417690483278">कस्टमाइज़ेशन आईडी</translation>
<translation id="6825578344716086703">आपने <ph name="DOMAIN" /> तक पहुंचने की कोशिश की थी, लेकिन सर्वर ने कमज़ोर हस्ताक्षर एल्गोरिद्म (जैसे कि SHA-1) वाला प्रमाणपत्र प्रस्तुत किया. इसका मतलब है कि सर्वर की ओर से प्रस्तुत किए गए सुरक्षा क्रेडेंशियल नकली हो सकते हैं और हो सकता है कि सर्वर आपका अपेक्षित सर्वर न हो (हो सकता है कि आप किसी हमलावर से बातचीत कर रहे हों).</translation>
+<translation id="6826370046007623921">डेटा लीक होने की रोकथाम</translation>
<translation id="6831043979455480757">अनुवाद करें</translation>
<translation id="6839929833149231406">क्षेत्र</translation>
<translation id="6852204201400771460">ऐप्लिकेशन फिर लोड करें?</translation>
@@ -1082,7 +1100,6 @@
<translation id="6891596781022320156">नीति स्तर समर्थित नहीं है.</translation>
<translation id="6895330447102777224">आपके कार्ड की पुष्टि हो गई है</translation>
<translation id="6897140037006041989">उपयोगकर्ता एजेंट</translation>
-<translation id="6903319715792422884">'सुरक्षित ब्राउज़िंग' को बेहतर बनाने में मदद करने के लिए, Google को कुछ <ph name="BEGIN_WHITEPAPER_LINK" />'सिस्टम जानकारी' और 'पेज सामग्री'<ph name="END_WHITEPAPER_LINK" /> भेजें. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">उपयोगकर्ता:</translation>
<translation id="6934672428414710184">यह नाम आपके Google खाते से है</translation>
<translation id="6944692733090228304">आपने एक ऐसी साइट पर अपना पासवर्ड डाला है जिसे <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> प्रबंधित नहीं करता है. अपने खाते को सुरक्षित रखने के लिए, दूसरे ऐप्लिकेशन और साइटों पर अपने पासवर्ड का दोबारा इस्तेमाल न करें.</translation>
@@ -1127,6 +1144,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> अन्य}one{<ph name="PAYMENT_METHOD_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> अन्य}other{<ph name="PAYMENT_METHOD_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> अन्य}}</translation>
<translation id="7153618581592392745">हल्का बैंगनी</translation>
<translation id="717330890047184534">Gaia आईडी:</translation>
+<translation id="7174545416324379297">आपस में मिला दिया गया</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> अन्य}one{<ph name="SHIPPING_OPTION_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> अन्य}other{<ph name="SHIPPING_OPTION_PREVIEW" /> और <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> अन्य}}</translation>
<translation id="7177397715882417099">आप जिस सर्वर पर जा रहे हैं उसके लिए <ph name="ORIGIN" /> ने यह अनुरोध किया है
कि उसके सभी अनुरोधों पर सुरक्षा नीति लागू की जाए. लेकिन नीति
@@ -1164,6 +1182,7 @@
<translation id="7320336641823683070">कनेक्शन संबंधी सहायता</translation>
<translation id="733354035281974745">डिवाइस का स्थानीय खाता बदलें</translation>
<translation id="7334320624316649418">&amp;पुन: क्रमित करना फिर से करें</translation>
+<translation id="7337706099755338005">आपके प्लेटफ़ॉर्म पर उपलब्ध नहीं है.</translation>
<translation id="733923710415886693">प्रमाणपत्र पारदर्शिता के माध्यम से सर्वर के प्रमाणपत्र को प्रकट नहीं किया गया.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">जुड़ा हुआ है या नहीं:</translation>
@@ -1195,7 +1214,6 @@
<translation id="7440140511386898319">ऑफ़लाइन होने पर खोजें</translation>
<translation id="7441627299479586546">गलत नीति विषय</translation>
<translation id="7442725080345379071">हल्का नारंगी</translation>
-<translation id="7444046173054089907">यह साइट अवरोधित है</translation>
<translation id="7445762425076701745">जिस सर्वर से आप कनेक्‍ट हैं उसकी पहचान पूरी तरह सत्‍यापित नहीं की जा सकती. आपने केवल आपके नेटवर्क में ही मान्‍य नाम का उपयोग कर किसी सर्वर से कनेक्‍ट किया है, जिसकी मान्‍यता का सत्‍यापन कोई बाह्य प्रमाणपत्र प्राधिकरण नहीं करता है. जैसा कि कुछ प्रमाणपत्र प्राधिकरण इन नामों के लिए प्रमाणपत्र जारी कर देंगे, और इस पर ध्यान नहीं दिया जाएगा कि यह सुनिश्‍चित करने का कोई तरीका नहीं है कि आप नियत वेबसाइट से कनेक्‍ट हैं, न कि किसी आक्रमणकर्ता से.</translation>
<translation id="7451311239929941790">इस समस्या के बारे में <ph name="BEGIN_LINK" />ज़्यादा जानें<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">वैश्विक डिफ़ॉल्ट का उपयोग करें (अवरोधित करें)</translation>
@@ -1217,9 +1235,9 @@
<translation id="7538364083937897561">ए2 (एन्वेलप)</translation>
<translation id="7542403920425041731">आपकी तरफ से पुष्टि हो जाने पर, आपके कार्ड के विवरण इस साइट के साथ शेयर किए जाएंगे.</translation>
<translation id="7542995811387359312">अपने आप क्रेडिट कार्ड भरना अक्षम किया गया है क्योंकि यह फ़ॉर्म किसी सुरक्षित कनेक्शन का उपयोग नहीं करता है.</translation>
-<translation id="7543525346216957623">अपने अभिभावक से पूछें</translation>
<translation id="7548892272833184391">कनेक्शन गड़बड़ियां ठीक करना</translation>
<translation id="7549584377607005141">इस वेबपेज को उस डेटा की ज़रुरत है जो आपने पहले दर्ज की थी ताकि इसे सही रूप में डिस्प्ले किया जा सके. आप यह डेटा फिर से भेज सकते हैं, लेकिन ऐसा करके आप इस पेज की इससे पहले की जा चुकी कोई कार्रवाई दोहराएंगे.</translation>
+<translation id="7550637293666041147">आपके डिवाइस का उपयोगकर्ता नाम और Chrome उपयोगकर्ता नाम</translation>
<translation id="7552846755917812628">ये टिप्स आज़माएं:</translation>
<translation id="7554791636758816595">नया टैब</translation>
<translation id="7564049878696755256">आपके <ph name="ORG_NAME" /> खाते का एक्सेस खो सकता है या पहचान चोरी हो सकती है. Chrome आपको अभी अपना पासवर्ड बदलने का सुझाव देता है.</translation>
@@ -1234,6 +1252,7 @@
<translation id="7610193165460212391"><ph name="VALUE" /> मान सीमा से बाहर है.</translation>
<translation id="7613889955535752492">समय-सीमा खत्म: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">आपके पास पहले से ऐसा डेटा है, जिसे आपके Google खाते के पासवर्ड के किसी अलग वर्शन का इस्तेमाल करके सुरक्षित किया गया है. कृपया उसे नीचे लिखें.</translation>
+<translation id="7625784245512586808">Chrome Enterprise की खतरे से बचाने की सुविधा</translation>
<translation id="7633909222644580952">परफ़ॉर्मेंस डेटा और क्रैश रिपोर्ट</translation>
<translation id="7637571805876720304">क्रोमियम से क्रेडिट कार्ड निकालें?</translation>
<translation id="7638605456503525968">सीरियल पोर्ट</translation>
@@ -1246,7 +1265,6 @@
<translation id="7668654391829183341">अज्ञात डिवाइस</translation>
<translation id="7669271284792375604">इस साइट पर मौजूद हमलावर धोखे से आपसे ऐसे प्रोग्राम इंस्टॉल करवाने की कोशिश कर सकते हैं, जिनसे आपके ब्राउज़िंग अनुभव को नुकसान पहुंच सकता है (उदाहरण के लिए, आपका होमपेज बदलकर या आप जिन साइटों पर जाते हैं उन पर ज़्यादा विज्ञापन दिखाकर).</translation>
<translation id="7676643023259824263">क्लिपबोर्ड टेक्स्ट, <ph name="TEXT" /> खोजें</translation>
-<translation id="7679176406634891508">प्लैटफ़ॉर्म और क्लाउड</translation>
<translation id="7681101578153515023">सर्च इंजन बदलें</translation>
<translation id="7682287625158474539">शिपिंग</translation>
<translation id="7687186412095877299">आपके सेव किए गए भुगतान करने के तरीकों के ज़रिए भुगतान फ़ॉर्म भरता है</translation>
@@ -1261,7 +1279,6 @@
<translation id="7723047071702270851">कार्ड में बदलाव करें</translation>
<translation id="774634243536837715">खतरनाक सामग्री ब्लॉक की गई.</translation>
<translation id="7752995774971033316">अप्रबंधित</translation>
-<translation id="7755287808199759310">आपका अभिभावक इसे आपके लिए अनवरोधित कर सकता है</translation>
<translation id="7757555340166475417">दाई-पा-काई</translation>
<translation id="7758069387465995638">हो सकता है कि फायरवॉल या एंटीवायरस ने कनेक्शन को रोक दिया हो.</translation>
<translation id="7759163816903619567">डिसप्ले डोमेन:</translation>
@@ -1305,7 +1322,6 @@
<translation id="8004582292198964060">ब्राउज़र</translation>
<translation id="8009225694047762179">पासवर्ड संभालें</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{इस कार्ड और इसके बिलिंग पते को सेव किया जाएगा. <ph name="USER_EMAIL" /> में साइन इन रहने पर आप इसका इस्तेमाल कर पाएंगे.}one{ये कार्ड और इनके बिलिंग पते सेव किए जाएंगे. <ph name="USER_EMAIL" /> में साइन इन रहने पर आप उनका इस्तेमाल कर पाएंगे.}other{ये कार्ड और इनके बिलिंग पते सेव किए जाएंगे. <ph name="USER_EMAIL" /> में साइन इन रहने पर आप उनका इस्तेमाल कर पाएंगे.}}</translation>
-<translation id="8012647001091218357">हम इस समय आपके अभिभावकों तक नहीं पहुंच पा रहे हैं. कृपया फिर से प्रयास करें.</translation>
<translation id="8025119109950072390">इस साइट पर मौजूद हमलावर आपको धोखा देकर आपसे कुछ जोखिम वाला काम करा सकते हैं, जैसे सॉफ़्टवेयर इंस्टॉल करना या आपकी व्यक्तिगत जानकारी (उदाहरण के लिए, पासवर्ड, फ़ोन नंबर या क्रेडिट कार्ड) के बारे में बताना.</translation>
<translation id="8034522405403831421">यह पेज <ph name="SOURCE_LANGUAGE" /> में है. इसका <ph name="TARGET_LANGUAGE" /> में अनुवाद करें?</translation>
<translation id="8035152190676905274">पेन</translation>
@@ -1316,6 +1332,7 @@
<translation id="8041940743680923270">वैश्विक डिफ़ॉल्ट का उपयोग करें (पूछें)</translation>
<translation id="8042918947222776840">पिकअप का तरीका चुनें</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" सही तरीके से कॉन्फ़िगर नहीं किया गया है. आमतौर पर "<ph name="SOFTWARE_NAME" />" को अनइंस्टॉल करने से समस्या ठीक हो जाती है. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">अब से, आपको कार्ड का सुरक्षा कोड नहीं डालना होगा</translation>
<translation id="8066955247577885446">माफ़ करें, कोई गड़बड़ी हुई.</translation>
<translation id="8074253406171541171">10x13 (एन्वेलप)</translation>
<translation id="8078141288243656252">घुमाने पर एनोटेट नहीं कर सकते</translation>
@@ -1346,6 +1363,7 @@
<translation id="8211406090763984747">कनेक्शन सुरक्षित है</translation>
<translation id="8218327578424803826">सौंपा गया स्‍थान:</translation>
<translation id="8220146938470311105">सी7/सी6 (एन्वेलप)</translation>
+<translation id="8220639454292072926">एंटरप्राइज़ रिपोर्टिंग</translation>
<translation id="8225771182978767009">जिस व्यक्ति ने इस कंप्यूटर को सेट किया है, उसने इस साइट को ब्लॉक करना चुना है.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">पेज को नए गुप्त टैब में खोलें</translation>
@@ -1397,27 +1415,27 @@
<translation id="8498891568109133222"><ph name="HOST_NAME" /> को लोड होने में बहुत ज़्यादा समय लगा.</translation>
<translation id="8503559462189395349">Chrome पासवर्ड</translation>
<translation id="8503813439785031346">उपयोगकर्ता नाम</translation>
-<translation id="8508648098325802031">सर्च अाइकॉन</translation>
+<translation id="8508648098325802031">सर्च आइकॉन</translation>
<translation id="8522552481199248698">Chrome से आप अपने Google खाते की सुरक्षा कर सकते हैं और अपना पासवर्ड बदल सकते हैं.</translation>
<translation id="8543181531796978784">आप <ph name="BEGIN_ERROR_LINK" />पहचान संबंधी समस्‍या की रिपोर्ट<ph name="END_ERROR_LINK" /> कर सकते हैं या अगर आप अपनी सुरक्षा संबंधी जोखिमों को समझते हैं तो, <ph name="BEGIN_LINK" />इस असुरक्षित साइट पर जा<ph name="END_LINK" /> सकते हैं.</translation>
-<translation id="8543556556237226809">प्रश्न पूछना चाहते हैं? तो उस व्यक्ति से संपर्क करें जो आपकी प्रोफ़ाइल की निगरानी करता है.</translation>
<translation id="8553075262323480129">अनुवाद विफल हो गया क्योंकि पेज की भाषा तय नहीं की जा सकी.</translation>
<translation id="8557066899867184262">कार्ड वेरीफ़िकेशन कोड (सीवीसी) आपके कार्ड के पीछे मौजूद होता है.</translation>
<translation id="8559762987265718583"><ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> से एक निजी कनेक्‍शन स्‍थापित नहीं किया जा सकता क्‍योंकि आपके डिवाइस का तारीख और समय (<ph name="DATE_AND_TIME" />) गलत है.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> संदिग्ध साइट</translation>
<translation id="8564985650692024650">अगर आपने अपने <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> पासवर्ड का दूसरी साइटों पर दोबारा इस्तेमाल किया है, तो क्रोमियम आपको उसे रीसेट करने का सुझाव देता है.</translation>
<translation id="8571890674111243710">पेज का अनुवाद <ph name="LANGUAGE" /> में कर रहा है...</translation>
<translation id="858637041960032120">फ़ोन नंबर जोड़ें
</translation>
-<translation id="859285277496340001">प्रमाणपत्र यह जांचने के लिए कोई तरीका निर्दिष्‍ट नहीं करता कि इसे रद्द कर दिया गया है या नहीं.</translation>
<translation id="860043288473659153">कार्डधारक का नाम</translation>
<translation id="861775596732816396">आकार 4</translation>
-<translation id="8620436878122366504">आपके अभिभावकों ने अभी तक इसकी अनुमति नहीं दी है</translation>
<translation id="8622948367223941507">लीगल-एक्स्ट्रा</translation>
<translation id="8625384913736129811">इस कार्ड को इस डिवाइस में सेव करें</translation>
<translation id="8626112503828625890">Google खाते में बिलिंग की जानकारी सेव करें?</translation>
+<translation id="8647750283161643317">सभी को डिफ़ॉल्ट पर रीसेट करें</translation>
<translation id="8663226718884576429">ऑर्डर की खास बातें, <ph name="TOTAL_LABEL" />, ज़्यादा जानकारी</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, उत्तर, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">पीआरसी-16के</translation>
+<translation id="8688672835843460752">उपलब्ध</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> से आपके कनेक्शन को सुरक्षित नहीं किया गया है.</translation>
<translation id="8718314106902482036">भुगतान पूरा नहीं हुआ</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, खोज सुझाव</translation>
@@ -1428,6 +1446,7 @@
<translation id="8738058698779197622">सुरक्षित कनेक्‍शन स्‍थापित करने के लिए, आपकी घड़ी को ठीक से सेट किए जाने की आवश्‍यकता है. ऐसा इसलिए क्‍योंकि वेबसाइटों द्वारा स्‍वयं की पहचान करने के लिए उपयोग किए जाने वाले प्रमाण पत्र केवल विशिष्‍ट समयावधियों के लिए ही मान्‍य होते हैं. चूंकि आपके डिवाइस की घड़ी गलत है, इसलिए क्रोमियम इन प्रमाणपत्रों को सत्‍यापित नहीं कर सकता.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> का &lt;abbr id="dnsDefinition"&gt;DNS पता&lt;/abbr&gt; नहीं पाया जा सका. समस्या का निदान किया जा रहा है.</translation>
<translation id="874846938927089722">स्वीकार किए जाने वाले क्रेडिट और प्रीपेड कार्ड</translation>
+<translation id="874918643257405732">इस टैब को बुकमार्क करें</translation>
<translation id="8759274551635299824">इस कार्ड की अवधि खत्म हो चुकी है</translation>
<translation id="8761567432415473239">Google सुरक्षित ब्राउज़िंग को <ph name="SITE" /> पर हाल ही में <ph name="BEGIN_LINK" />हानिकारक प्रोग्राम मिले हैं<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB डिवाइस</translation>
@@ -1457,6 +1476,7 @@
<translation id="8938939909778640821">स्वीकृत क्रेडिट और प्रीपेड कार्ड</translation>
<translation id="8943282376843390568">नींबू पीला</translation>
<translation id="8957210676456822347">कैप्‍टिव पोर्टल की अनुमति देना</translation>
+<translation id="8962950042226115166">संदिग्ध साइट</translation>
<translation id="8968766641738584599">कार्ड सेव करें</translation>
<translation id="8971063699422889582">सर्वर के प्रमाणपत्र की समय-सीमा खत्म हो चुकी है.</translation>
<translation id="8975012916872825179">इसमें फ़ोन नंबर, ईमेल पते और शिपिंग पते जैसी जानकारी शामिल होती है</translation>
@@ -1479,24 +1499,24 @@
<translation id="9035022520814077154">सुरक्षा गड़बड़ी</translation>
<translation id="9038649477754266430">ज़्यादा तेज़ी से पेज लोड करने के लिए किसी पूर्वानुमान सेवा का उपयोग करें</translation>
<translation id="9039213469156557790">इसके अतिरिक्त, इस पेज में ऐसे अन्य संसाधन भी शामिल हैं, जो सुरक्षित नहीं हैं. ट्रांज़िट में होने के दौरान ये संसाधन अन्य लोगों द्वारा देखे जा सकते हैं और पेज का व्यवहार बदलने के लिए किसी हमवलावर द्वारा इनमें बदलाव किए जा सकते हैं.</translation>
+<translation id="9044359186343685026">टच आईडी का इस्तेमाल करें</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">आपने <ph name="DOMAIN" /> पर पहुंचने की कोशिश की लेकिन सर्वर ने एक अमान्‍य प्रमाणपत्र पेश किया.</translation>
<translation id="9050666287014529139">पासफ़्रेज़ (लंबा पासवर्ड)</translation>
<translation id="9065203028668620118">बदलाव करें</translation>
<translation id="9065745800631924235"><ph name="TEXT" /> इतिहास में खोजें</translation>
<translation id="9069693763241529744">किसी एक्सटेंशन से अवरोधित है</translation>
-<translation id="9076283476770535406">इसमें वयस्क सामग्री हो सकती है</translation>
<translation id="9076630408993835509">यह ब्राउज़र कोई कंपनी या दूसरा संगठन प्रबंधित नहीं करता. शायद इस डिवाइस की गतिविधि को Chrome से बाहर प्रबंधित किया जाए. <ph name="BEGIN_LINK" />ज़्यादा जानें<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">ज़्यादा जानकारी की आवश्यकता है</translation>
<translation id="9080712759204168376">ऑर्डर की जानकारी</translation>
<translation id="9089260154716455634">बंद रहने के समय के लिए नीति:</translation>
<translation id="9095388113577226029">और भाषाएं...</translation>
+<translation id="9098981495403789647">एडमिन ने आपके ब्राउज़र पर Chrome Enterprise की खतरे से बचाने की सुविधा चालू की है. Chrome Enterprise की खतरे से बचाने की सुविधा आपका कुछ डेटा ऐक्सेस कर सकती है.</translation>
<translation id="9103872766612412690">आपकी जानकारी की सुरक्षा करने के लिए <ph name="SITE" /> आम तौर पर, सुरक्षित करने के तरीके (एन्क्रिप्शन) का उपयोग करती है. जब 'क्रोमियम' ने इस बार <ph name="SITE" /> से कनेक्ट करने की कोशिश की तो, वेबसाइट ने असामान्य और गलत क्रेडेंशियल वापस भेजे. ऐसा तब हो सकता है जब कोई हमलावर <ph name="SITE" /> होने का दावा करने की कोशिश कर रहा हो या किसी वाई-फ़ाई 'साइन इन स्क्रीन' की वजह से कनेक्शन में खराबी आ गई हो. आपकी जानकारी अभी भी सुरक्षित है क्योंकि किसी भी डेटा को एक्सचेंज करने से पहले ही 'क्रोमियम' ने कनेक्शन रोक दिया था.</translation>
<translation id="9106062320799175032">बिलिंग पता जोड़ें</translation>
<translation id="9114524666733003316">कार्ड की पुष्टि की जा रही है...</translation>
<translation id="9128870381267983090">नेटवर्क से कनेक्ट करें</translation>
<translation id="9137013805542155359">मूल दिखाएं</translation>
-<translation id="9137248913990643158">इस ऐप्लिकेशन का उपयोग करने से पहले कृपया Chrome शुरू करके उसमें साइन इन करें.</translation>
<translation id="9141013498910525015">पते प्रबंधित करें</translation>
<translation id="9148088599418889305">शिपिंग का तरीका चुनें</translation>
<translation id="9148507642005240123">&amp;बदलाव को पहले जैसा करें</translation>
diff --git a/chromium/components/strings/components_strings_hr.xtb b/chromium/components/strings/components_strings_hr.xtb
index c2b61594fc8..4e31bae8175 100644
--- a/chromium/components/strings/components_strings_hr.xtb
+++ b/chromium/components/strings/components_strings_hr.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Dodajte ime na kartici</translation>
<translation id="1089439967362294234">Promjena zaporke</translation>
+<translation id="1096545575934602868">Broj unosa u ovom polju ne smije biti veći od <ph name="MAX_ITEMS_LIMIT" />. Svi će se daljnji unosi odbaciti.</translation>
<translation id="109743633954054152">Upravljajte zaporkama u postavkama Chromea</translation>
<translation id="1103523840287552314">Uvijek prevedi <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Ako je označeno, Chrome će pohraniti kopiju vaše kartice na uređaj radi bržeg popunjavanja obrazaca.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Pristupite <ph name="BEGIN_LINK" />predmemoriranoj kopiji<ph name="END_LINK" /> stranice <ph name="URL" /></translation>
<translation id="1156303062776767266">Gledate lokalnu ili dijeljenu datoteku</translation>
<translation id="1158211211994409885">Host <ph name="HOST_NAME" /> neočekivano je prekinuo vezu.</translation>
+<translation id="115926840831309955">Provjerite CVC i pokušajte ponovo ili ažurirajte datum isteka</translation>
<translation id="1161325031994447685">Ponovo se povežite s Wi-Fi mrežom</translation>
<translation id="1165039591588034296">Pogreška</translation>
<translation id="1175364870820465910">&amp;Ispis...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Softver na vašem računalu sprječava sigurno povezivanje Chromea s webom" (samo na Windows računalima)</translation>
<translation id="1294154142200295408">Varijacije naredbenog retka</translation>
<translation id="129553762522093515">Nedavno zatvoreno</translation>
+<translation id="1298536327547837046">Skeniranje zlonamjernog softvera</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Izbrišite kolačiće<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Ukinute značajke</translation>
<translation id="1320233736580025032">Prc1 (omotnica)</translation>
<translation id="132301787627749051">Traženje slike u međuspremniku</translation>
<translation id="1323433172918577554">Više</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google tablice</translation>
<translation id="1527263332363067270">Čekanje na uspostavu veze…</translation>
<translation id="1529521330346880926">10x15 (omotnica)</translation>
+<translation id="1530707389502320859">Web-lokacija koju ste upravo pokušali posjetiti izgleda lažno. Napadači ponekad oponašaju web-lokacije sitnim izmjenama URL-a.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Na ovoj se stranici navodi sljedeće</translation>
<translation id="153384715582417236">To je zasad sve</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokument je prevelik za dodavanje bilješki</translation>
-<translation id="1721312023322545264"><ph name="NAME" /> mora dopustiti da posjetiš tu web-lokaciju</translation>
<translation id="1721424275792716183">* Polje je obavezno</translation>
<translation id="1727741090716970331">Dodajte važeći broj kartice</translation>
<translation id="1728677426644403582">Gledate izvor web-stranice</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Web-lokacije koje posjećujete i vrijeme koje na njima provodite</translation>
<translation id="1826516787628120939">Provjera</translation>
<translation id="1834321415901700177">Ova web-lokacija sadrži štetne programe</translation>
+<translation id="1838374766361614909">Brisanje pretraživanja</translation>
<translation id="1839551713262164453">Potvrđivanje vrijednosti pravila nije uspjelo zbog pogrešaka</translation>
<translation id="1842969606798536927">Plaćanje</translation>
<translation id="1871208020102129563">Proxy poslužitelj postavljen je na upotrebu fiksnih proxy poslužitelja, a ne URL .pac skripte.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Sažmi popis</translation>
<translation id="1898423065542865115">Filtriranje</translation>
<translation id="1914326953223720820">Usluga raspakiravanja</translation>
+<translation id="1915697529809968049">Želite li koristiti Touch ID umjesto CVC-a?</translation>
<translation id="1916770123977586577">Ponovo učitajte stranicu da bi se ažurirane postavke primijenile na ovu web-lokaciju</translation>
<translation id="1919345977826869612">Oglasi</translation>
<translation id="1919367280705858090">Pomoć za konkretne poruke pogreške</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Oznake s domene <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Pogreška postavljanja u seriju</translation>
<translation id="1974060860693918893">Napredno</translation>
+<translation id="1974883374937189061">Pomognite poboljšati Chrome tako što ćete Googleu poslati <ph name="BEGIN_WHITEPAPER_LINK" />URL-ove nekih stranica koje posjetite, ograničene podatke o sustavu i dio sadržaja web-stranica<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Verzija opreme</translation>
<translation id="1981206234434200693">Izbrišite Chromeove podatke o povijesti pregledavanja</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{i još 1}one{i još #}few{i još #}other{i još #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Unesite važeću godinu isteka</translation>
<translation id="2212735316055980242">Pravilo nije pronađeno</translation>
<translation id="2213606439339815911">Dohvaćanje unosa...</translation>
+<translation id="2215727959747642672">Uređivanje datoteke</translation>
<translation id="2218879909401188352">Napadači koji su trenutačno na web-lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogli bi instalirati opasne aplikacije koje će oštetiti uređaj, dodati skrivene troškove na račun za mobilne usluge ili ukrasti vaše osobne podatke. <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte više<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Nema interneta</translation>
<translation id="2230458221926704099">Riješite problem s povezivanjem pomoću <ph name="BEGIN_LINK" />dijagnostičke aplikacije<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Pošalji sad</translation>
+<translation id="2248949050832152960">Koristi WebAuthn</translation>
<translation id="225207911366869382">Ta je vrijednost obustavljena za to pravilo.</translation>
<translation id="2257315177824333709">Vaša se kartica trenutačno ne može spremiti</translation>
<translation id="2262243747453050782">HTTP pogreška</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Nevažeći URL pretraživanja.</translation>
<translation id="2482878487686419369">Obavijesti</translation>
<translation id="248348093745724435">Pravila uređaja</translation>
-<translation id="2485387744899240041">Korisnička imena za uređaj i preglednik</translation>
<translation id="2491120439723279231">Certifikat poslužitelja sadrži pogreške.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Raščlanjivanje JSON datoteka</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Natrag</translation>
<translation id="2503184589641749290">Prihvaćene debitne i pretplatne kartice</translation>
<translation id="2505268675989099013">Zaštitite račun</translation>
+<translation id="2515335152965840738">ZANEMARI</translation>
<translation id="2515629240566999685">provjerite jačinu signala na svom području</translation>
<translation id="2523886232349826891">Sprema se samo na ovom uređaju</translation>
<translation id="2524461107774643265">Dodajte još podataka</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Pošalji</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nijedna}=1{Jedna zaporka (za <ph name="DOMAIN_LIST" />)}=2{Dvije zaporke (za <ph name="DOMAIN_LIST" />)}one{# zaporka (za <ph name="DOMAIN_LIST" />)}few{# zaporke (za <ph name="DOMAIN_LIST" />)}other{# zaporki (za <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Zatvorite ostale kartice ili aplikacije</translation>
-<translation id="267371737713284912">pritisnite <ph name="MODIFIER_KEY_DESCRIPTION" /> za poništavanje</translation>
<translation id="2674170444375937751">Jeste li sigurni da te stranice želite izbrisati iz Vaše povijesti?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Napusti</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Vrijednost ne odgovara formatu.</translation>
<translation id="2705137772291741111">Spremljena (predmemorirana) kopija web-lokacije nije čitljiva.</translation>
<translation id="2709516037105925701">Automatsko popunjavanje</translation>
-<translation id="2712173769900027643">Traži dopuštenje</translation>
<translation id="2713444072780614174">Bijela</translation>
<translation id="2720342946869265578">U blizini</translation>
<translation id="2721148159707890343">Zahtjev je uspio</translation>
<translation id="2728127805433021124">Certifikat poslužitelja potpisan je slabim algoritmom potpisa.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />pokrenuti Dijagnostiku povezivosti<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Omogućivanjem tih značajki mogli biste izgubiti podatke preglednika ili
+ ugroziti svoju sigurnost ili privatnost. Omogućene značajke primjenjuju se na sve
+ korisnike ovog preglednika.</translation>
<translation id="2735043616039983645">Za to je pravilo prisutno više izvora sa sukobljenim vrijednostima!</translation>
<translation id="2738330467931008676">Odaberite adresu preuzimanja</translation>
<translation id="2740531572673183784">U redu</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Veza je ponovo uspostavljena.</translation>
<translation id="2788784517760473862">Prihvaćene kreditne kartice</translation>
<translation id="2792012897584536778">Administratori uređaja postavili su sigurnosne certifikate koji im mogu omogućiti prikaz sadržaja web-lokacija koje posjetite.</translation>
-<translation id="2794233252405721443">Web-lokacija blokirana</translation>
<translation id="2799020568854403057">Sljedeća web-lokacija sadrži štetne aplikacije</translation>
<translation id="2799223571221894425">Pokreni ponovo</translation>
<translation id="2803306138276472711">Google sigurno pregledavanje nedavno je <ph name="BEGIN_LINK" />otkrilo zlonamjerni softver<ph name="END_LINK" /> na <ph name="SITE" />. Web-lokacije koje su inače sigurne ponekad mogu biti zaražene zlonamjernim softverom.</translation>
+<translation id="2815364696811431560">NAPUSTI WEB-LOKACIJU</translation>
<translation id="2824775600643448204">Adresna traka i traka za pretraživanje</translation>
<translation id="2826760142808435982">Veza je kriptirana i autentificirana šifrom <ph name="CIPHER" />, a <ph name="KX" /> služi za mehanizam razmjene ključeva.</translation>
<translation id="2835170189407361413">Obriši obrazac</translation>
<translation id="2847118875340931228">Otvori anonimni prozor</translation>
<translation id="2850739647070081192">Invite (omotnica)</translation>
-<translation id="2851634818064021665">Potrebno ti je dopuštenje za posjet toj web-lokaciji</translation>
<translation id="2856444702002559011">Napadači možda pokušavaju ukrasti vaše podatke s web-lokacije <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (na primjer zaporke, poruke ili brojeve kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte više<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Želite li spremiti karticu?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Ako je to omogućeno, Chromium će pohraniti kopiju vaše kartice na uređaj radi bržeg ispunjavanja obrazaca.</translation>
<translation id="2985398929374701810">Unesite važeću adresu</translation>
<translation id="2986368408720340940">Taj način preuzimanja nije dostupan. Pokušajte s nekim drugim načinom.</translation>
+<translation id="2987034854559945715">Nema podudarnih značajki</translation>
<translation id="2991174974383378012">Dijeljenje s web-lokacijama</translation>
<translation id="2991571918955627853">Trenutačno ne možete otvoriti <ph name="SITE" /> jer web-lokacija upotrebljava HSTS. Mrežne pogreške i napadi obično su privremeni, tako da će stranica kasnije vjerojatno funkcionirati.</translation>
<translation id="3005723025932146533">Prikaži spremljenu kopiju</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Pogrešna vrsta pravila</translation>
<translation id="3037605927509011580">O, ne!</translation>
<translation id="3041612393474885105">Podaci o certifikatu</translation>
+<translation id="3057676462092457419">Način DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> još nije podržan. Način je postavljen na <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (omotnica)</translation>
<translation id="3061707000357573562">Usluga zakrpe</translation>
<translation id="3064966200440839136">Napuštate anonimni način rada da biste platili putem vanjske aplikacije. Želite li nastaviti?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na poslužitelju <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Otkaži plaćanje</translation>
<translation id="3207960819495026254">Označeno</translation>
+<translation id="3209034400446768650">Stranica se možda naplaćuje</translation>
<translation id="3225919329040284222">Poslužitelj je pokazao certifikat koji ne odgovara ugrađenim očekivanjima. Ta su očekivanja uključena za određene web-lokacije s visokim stupnjem sigurnosti radi vaše zaštite.</translation>
<translation id="3226128629678568754">Pritisnite gumb za ponovno učitavanje da biste ponovo poslali podatke koji su potrebni za učitavanje stranice.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Informacije o verziji uređaja i preglednika</translation>
<translation id="323107829343500871">Unesite CVC za karticu <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Uvijek otkrivaj važan sadržaj na ovoj web-lokaciji</translation>
-<translation id="3254409185687681395">Označi ovu stranicu</translation>
<translation id="3270847123878663523">&amp;Poništi promjenu rasporeda</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Dodajte ime na kartici</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Dodajte adresu za naplatu</translation>
<translation id="3324983252691184275">Grimizna</translation>
<translation id="3338095232262050444">Sigurno</translation>
-<translation id="3345135638360864351">Slanje zahtjeva za pristup ovoj web-lokaciji korisniku <ph name="NAME" /> nije uspjelo. Pokušaj ponovo.</translation>
<translation id="3355823806454867987">Promijeni proxy postavke...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />neće spremati<ph name="END_EMPHASIS" /> sljedeće informacije:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Sakrij napredno</translation>
<translation id="3467763166455606212">Potrebno je unijeti ime nositelja kartice</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, trenutačno otvoreno, pritisnite karticu pa Enter za prebacivanje na otvorenu karticu</translation>
-<translation id="3479539252931486093">Niste to očekivali? <ph name="BEGIN_LINK" />Javite nam<ph name="END_LINK" />.</translation>
<translation id="3479552764303398839">Ne sada</translation>
<translation id="3484560055331845446">Mogli biste izgubiti pristup svojem Google računu. Chrome preporučuje da odmah promijenite zaporku. Morat ćete se prijaviti.</translation>
<translation id="3495081129428749620">Traži na stranici
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Nismo uspjeli stupiti u kontakt s tvojim roditeljem. Pokušaj ponovo.</translation>
<translation id="3512163584740124171">To se pravilo zanemaruje jer drugo pravilo iz iste grupe pravila ima viši prioritet.</translation>
<translation id="3528171143076753409">Certifikat poslužitelja nije pouzdan.</translation>
<translation id="3528485271872257980">Tamnosmeđa</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Najmanje 1 stavka na sinkroniziranim uređajima}=1{1 stavka (i više njih na sinkroniziranim uređajima)}one{# stavka (i više njih na sinkroniziranim uređajima)}few{# stavke (i više njih na sinkroniziranim uređajima)}other{# stavki (i više njih na sinkroniziranim uređajima)}}</translation>
<translation id="3539171420378717834">Zadrži kopiju te kartice na uređaju</translation>
-<translation id="3556433843310711081">Voditelj je može deblokirati</translation>
<translation id="3566021033012934673">Vaša veza nije privatna</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Na ugrađenoj stranici na web-lokaciji <ph name="SITE" /> navodi se sljedeće</translation>
@@ -516,6 +523,7 @@
<translation id="3678529606614285348">Otvorite stranicu u novom anonimnom prozoru (Ctrl – Shift – N)</translation>
<translation id="3679803492151881375">Izvješće o rušenju programa generirano u <ph name="CRASH_TIME" />, preneseno u <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Podaci o certifikatu</translation>
+<translation id="3701427423622901115">Poništavanje je potvrđeno.</translation>
<translation id="3704162925118123524">Mreža koju upotrebljavate može zahtijevati posjet stranici za prijavu.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Učitavanje...</translation>
@@ -532,6 +540,7 @@
<translation id="3748148204939282805">Napadači na web-lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogu vas na prijevaru pokušati navesti da napravite nešto opasno kao što je instaliranje softvera ili otkrivanje osobnih podataka (npr. zaporki, telefonskih brojeva ili brojeva kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte više<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Prijevod nije uspio zbog poslužiteljske pogreške.</translation>
<translation id="3759461132968374835">Nemate nedavnih izvješća o padu. Ovdje se neće prikazati padovi do kojih je došlo kada je izvješćivanje o padovima onemogućeno.</translation>
+<translation id="3760561303380396507">Želite li koristiti Windows Hello umjesto CVC-a?</translation>
<translation id="3761718714832595332">Sakrij status</translation>
<translation id="3765032636089507299">Stranica Sigurno pregledavanje trenutačno je u izradi.</translation>
<translation id="3778403066972421603">Želite li spremiti ovu karticu na svoj Google račun i na ovaj uređaj?</translation>
@@ -541,6 +550,7 @@
<translation id="3789155188480882154">Veličina 16</translation>
<translation id="3797522431967816232">Prc3 (omotnica)</translation>
<translation id="3807873520724684969">Blokiran je štetni sadržaj.</translation>
+<translation id="3808375843007691220">Upozorenje: pristupate eksperimentalnim značajkama!</translation>
<translation id="3810973564298564668">Upravljaj</translation>
<translation id="382518646247711829">Ako upotrebljavate proxy poslužitelj...</translation>
<translation id="3828924085048779000">Prazne zaporke nisu dopuštene.</translation>
@@ -549,11 +559,11 @@
<translation id="3858027520442213535">Ažuriraj datum i vrijeme</translation>
<translation id="3884278016824448484">Identifikator uređaja sukobljen je</translation>
<translation id="3885155851504623709">Župa</translation>
-<translation id="3886446263141354045">Zahtjev za pristup toj web-lokaciji poslan je korisniku <ph name="NAME" /></translation>
<translation id="3890664840433101773">Dodajte e-adresu</translation>
<translation id="3901925938762663762">Kartica je istekla</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Želite li koristiti WebAuthn umjesto CVC-a?</translation>
<translation id="3946209740501886391">Uvijek pitaj na ovoj web-lokaciji</translation>
<translation id="3949571496842715403">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat ne navodi alternativne nazive predmeta. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
<translation id="3949601375789751990">Ovdje se prikazuje vaša povijest pregledavanja</translation>
@@ -564,11 +574,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nijedna}=1{S 1 web-lokacije }one{S/sa # web-lokacije }few{S/sa # web-lokacije }other{S/sa # web-lokacija }}</translation>
<translation id="397105322502079400">Izračun u tijeku…</translation>
<translation id="3973234410852337861">Host <ph name="HOST_NAME" /> je blokiran</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> je u pregledniku omogućio funkciju Zaštite od prijetnji u Chromeu za poduzeća. Zaštita od prijetnji u Chromeu za poduzeća ima pristup nekim vašim podacima.</translation>
<translation id="3987940399970879459">Manje od 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 web-stranica u blizini}one{# web-stranica u blizini}few{# web-stranice u blizini}other{# web-stranica u blizini}}</translation>
<translation id="4030383055268325496">&amp;Poništi dodavanje</translation>
<translation id="4032320456957708163">Vašim preglednikom upravlja <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Veza koju ste otvorili vodi na web-lokaciju koju inače ne posjećujete. Možda vas pokušava zbuniti.</translation>
<translation id="4058922952496707368">Stavka "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (omotnica)</translation>
<translation id="4067947977115446013">Dodajte važeću adresu</translation>
@@ -581,6 +591,7 @@
<translation id="4103249731201008433">Serijski broj uređaja nije važeći</translation>
<translation id="410351446219883937">Automatska reprodukcija</translation>
<translation id="4103763322291513355">Posjetite &lt;strong&gt;chrome://policy&lt;/strong&gt; da biste vidjeli popis nedopuštenih URL-ova i druga pravila koja je nametnuo vaš administrator sustava.</translation>
+<translation id="4108231218301530806">Sljedeći put ovu karticu potvrdite otiskom prsta.</translation>
<translation id="4110652170750985508">Pregledajte uplatu</translation>
<translation id="4112140312785995938">Traži unatrag</translation>
<translation id="4116663294526079822">Uvijek dopusti na ovoj web-lokaciji</translation>
@@ -595,6 +606,7 @@
<translation id="4171400957073367226">Potpis za potvrdu nije ispravan.</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Još <ph name="ITEM_COUNT" /> stavka}one{Još <ph name="ITEM_COUNT" /> stavka}few{Još <ph name="ITEM_COUNT" /> stavke}other{Još <ph name="ITEM_COUNT" /> stavki}}</translation>
+<translation id="4176463684765177261">Onemogućeno</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Da biste sljedeći put platili brže, karticu i adresu za naplatu dodajte svojem Google računu.</translation>
<translation id="4196861286325780578">&amp;Ponovi premještanje</translation>
@@ -631,6 +643,7 @@
<translation id="4277028893293644418">Poništi zaporku</translation>
<translation id="4279811152705618813">Vašim uređajem <ph name="DEVICE_TYPE" /> upravlja <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ova je kartica spremljena na vašem Google računu}one{Ove su kartice spremljene na vašem Google računu}few{Ove su kartice spremljene na vašem Google računu}other{Ove su kartice spremljene na vašem Google računu}}</translation>
+<translation id="428847186335018806">Pregledajte datoteke koje preuzimate ili prenosite putem Chromea.</translation>
<translation id="42981349822642051">Proširi</translation>
<translation id="4302965934281694568">Chou3 (omotnica)</translation>
<translation id="4305817255990598646">Prebaci</translation>
@@ -660,7 +673,6 @@
<translation id="4435702339979719576">Dopisnica)</translation>
<translation id="443673843213245140">Upotreba proxy poslužitelja onemogućena je, ali određena je izričita konfiguracija proxy poslužitelja.</translation>
<translation id="445100540951337728">Prihvaćene debitne kartice</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> sumnjivo ponašanje</translation>
<translation id="4466881336512663640">Izgubit će se promjene koje ste unijeli u obrazac. Jeste li sigurni da želite nastaviti?</translation>
<translation id="4477350412780666475">Sljedeća pjesma</translation>
<translation id="4482953324121162758">Ova web-lokacija neće biti prevedena.</translation>
@@ -687,6 +699,7 @@
<translation id="4594403342090139922">&amp;Poništi brisanje</translation>
<translation id="4597348597567598915">Veličina 8</translation>
<translation id="4600854749408232102">C6/C5 (omotnica)</translation>
+<translation id="464342062220857295">Značajke pretraživanja</translation>
<translation id="4646534391647090355">Otvori odmah</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat sadrži pogreške. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
@@ -695,7 +708,6 @@
<translation id="4691835149146451662">Architecture-A (omotnica)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Veza je prekinuta</translation>
-<translation id="471880041731876836">Nemaš dopuštenje za posjet toj web-lokaciji</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />pokrenuti Mrežnu dijagnostiku sustava Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Ponovo učitaj pravila</translation>
<translation id="4728558894243024398">Platforma</translation>
@@ -723,7 +735,6 @@
<translation id="4816492930507672669">Prilagodi stranici</translation>
<translation id="4850886885716139402">Prikaz</translation>
<translation id="4854362297993841467">Taj način dostave nije dostupan. Pokušajte s nekim drugim načinom.</translation>
-<translation id="4858792381671956233">Pitao si roditelje smiješ li otvoriti tu web-lokaciju</translation>
<translation id="4864052566555297930">Sigurnosni savjet:</translation>
<translation id="4876188919622883022">Pojednostavljeni prikaz</translation>
<translation id="4876305945144899064">Nema korisničkog imena</translation>
@@ -747,7 +758,9 @@
<translation id="4974590756084640048">Ponovo omogući upozorenja</translation>
<translation id="4984339528288761049">Prc5 (omotnica)</translation>
<translation id="4989163558385430922">Prikaži sve</translation>
+<translation id="4989542687859782284">Nije dostupno</translation>
<translation id="4989809363548539747">Taj dodatak nije podržan</translation>
+<translation id="4995216769782533993">Potvrdite sigurnosni kôd da biste podijelili pojedinosti kartice s ovom web-lokacijom</translation>
<translation id="5002932099480077015">Ako je to omogućeno, Chrome će pohraniti kopiju vaše kartice na ovom uređaju radi bržeg ispunjavanja obrazaca.</translation>
<translation id="5015510746216210676">Naziv uređaja:</translation>
<translation id="5017554619425969104">Tekst koji ste kopirali</translation>
@@ -776,6 +789,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bitni)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Potvrdite svoju karticu</translation>
<translation id="5135404736266831032">Upravljajte adresama...</translation>
<translation id="5138227688689900538">Pokaži manje</translation>
<translation id="5141240743006678641">Šifriranje sinkroniziranih zaporki s vjerodajnicama za Google</translation>
@@ -802,6 +816,7 @@
<translation id="5251803541071282808">Oblak</translation>
<translation id="5252000469029418751">C7 (omotnica)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Značajke koje se primjenjuju na razini sustava može postaviti samo vlasnik: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Upozorenje: pravilo nije spojeno prema uputama u pravilu PolicyDictionaryMultipleSourceMergeList jer ne pripada pravilima rječnika koja se mogu spajati.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Završi</translation>
@@ -825,7 +840,6 @@
<translation id="536296301121032821">Pohrana postavki pravila nije uspjela</translation>
<translation id="5371425731340848620">Ažuriranje kartice</translation>
<translation id="5377026284221673050">"Sat kasni" ili "Sat ide unaprijed" ili "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Ova vas stranica može pokušati prevariti, ukrasti osobne podatke ili oštetiti uređaj. Pazite kad unosite osobne podatke ili otvarate preuzete datoteke.</translation>
<translation id="5384855140246857529">Da biste svoje kartice upotrebljavali na svim uređajima, prijavite se i uključite sinkronizaciju.</translation>
<translation id="5386426401304769735">Lanac certifikata za ovu web-lokaciju sadrži certifikat s SHA-1 potpisom.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -839,6 +853,8 @@
<translation id="5457113250005438886">Nije važeće</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Ponovi uređivanje</translation>
+<translation id="5473728911100096288">Omogućivanjem tih značajki upotrebljavat ćete značajke
+ koje su ukinute u budućim verzijama.</translation>
<translation id="5478437291406423475">B6/C4 (omotnica)</translation>
<translation id="5481076368049295676">Ovaj sadržaj može pokušati na vaš uređaj instalirati opasan softver koji krade ili briše podatke. <ph name="BEGIN_LINK" />Ipak prikaži<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Dodajte važeću adresu</translation>
@@ -862,7 +878,6 @@
<translation id="5570825185877910964">Zaštitite račun</translation>
<translation id="5571083550517324815">Preuzimanje na toj adresi nije moguće. Odaberite drugu adresu.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 u upotrebi}one{# u upotrebi}few{# u upotrebi}other{# u upotrebi}})</translation>
-<translation id="5572851009514199876">Pokrenite Chrome i prijavite se na njega kako bi mogao provjeriti imate li dopuštenje za pristup toj web-lokaciji.</translation>
<translation id="5580958916614886209">Provjerite mjesec isteka, pa pokušajte ponovo</translation>
<translation id="5586446728396275693">Nema nijedne spremljene adrese</translation>
<translation id="5595485650161345191">Uređivanje adrese</translation>
@@ -870,6 +885,7 @@
<translation id="560412284261940334">Upravljanje nije podržano</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Web-lokacija je možda lažna ili joj je cilj prijevara. Chrome preporučuje da je odmah napustite.</translation>
<translation id="5610142619324316209">provjerite vezu</translation>
<translation id="5610807607761827392">Karticama i adresama možete upravljati u <ph name="BEGIN_LINK" />Postavkama<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Host <ph name="HOST_NAME" /> preusmjerio vas je previše puta.</translation>
@@ -893,11 +909,11 @@
<translation id="5720705177508910913">Trenutačni korisnik:</translation>
<translation id="5728056243719941842">C5 (omotnica)</translation>
<translation id="5730040223043577876">Chrome preporučuje poništavanje zaporke ako ste je upotrebljavali za druge web-lokacije.</translation>
-<translation id="5732392974455271431">Tvoji je roditelji mogu deblokirati</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Spremite karticu na svoj Google račun}one{Spremite kartice na svoj Google račun}few{Spremite kartice na svoj Google račun}other{Spremite kartice na svoj Google račun}}</translation>
<translation id="5763042198335101085">Unesite važeću e-adresu</translation>
<translation id="5765072501007116331">Odaberite adresu za prikaz načina dostave i zahtjeva za dostavu.</translation>
<translation id="5778550464785688721">Potpuni nadzor nad MIDI uređajima</translation>
+<translation id="5781136890105823427">Eksperiment omogućen</translation>
<translation id="578305955206182703">Jantarna</translation>
<translation id="57838592816432529">Isključi zvuk</translation>
<translation id="5784606427469807560">Pojavio se problem prilikom potvrđivanja kartice. Provjerite internetsku vezu i pokušajte ponovo.</translation>
@@ -914,13 +930,16 @@
<translation id="5860033963881614850">Isključeno</translation>
<translation id="5863847714970149516">Stranica koja će se otvoriti može vam pokušati nešto naplatiti</translation>
<translation id="5866257070973731571">Dodajte telefonski broj</translation>
+<translation id="5866898949289125849">Pregledavate stranicu alata za razvojne programere</translation>
<translation id="5869405914158311789">Web-lokacija ne može se dohvatiti</translation>
<translation id="5869522115854928033">Spremljene zaporke</translation>
<translation id="5887400589839399685">Kartica je spremljena</translation>
<translation id="5893752035575986141">Prihvaćaju se kreditne kartice.</translation>
+<translation id="5895138241574237353">Ponovno pokreni</translation>
<translation id="5901630391730855834">Žuta</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sinkronizirano)</translation>
<translation id="5916664084637901428">Uključi</translation>
+<translation id="59174027418879706">Omogućeno</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Želite li spremiti karticu na Google račun?</translation>
<translation id="5922853866070715753">Skoro gotovo</translation>
@@ -954,6 +973,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Želite li plaćati svojim karticama na svim svojim uređajima?</translation>
<translation id="6059925163896151826">USB uređaji</translation>
+<translation id="6060009363608157444">Način DnsOverHttps nije važeći.</translation>
<translation id="6080696365213338172">Pristupili ste sadržaju pomoću certifikata koji je izdao administrator. Administrator može presresti podatke koje dostavljate domeni <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">Dodaj bilješku</translation>
<translation id="610911394827799129">Na vašem Google računu možda postoje drugi oblici povijesti pregledavanja na stranici <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1002,13 +1022,12 @@
<translation id="6404511346730675251">Uredi oznaku</translation>
<translation id="6406765186087300643">C0 (omotnica)</translation>
<translation id="6410264514553301377">Unesite datum isteka i CVC za karticu <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Pitao si roditelja smiješ li otvoriti tu web-lokaciju</translation>
<translation id="6415778972515849510">Chromium vam može pomoći da zaštitite svoj Google račun i promijenite zaporku.</translation>
-<translation id="6417515091412812850">Nije moguće provjeriti je li certifikat opozvan.</translation>
<translation id="6431585503458005759">Nemoj pohraniti</translation>
<translation id="6433490469411711332">Uređivanje podataka za kontakt</translation>
<translation id="6433595998831338502">Host <ph name="HOST_NAME" /> odbio je povezivanje.</translation>
<translation id="6434309073475700221">Odbaci</translation>
+<translation id="6435221585574090192">Podijelite s administratorom podatke o sigurnosnim događajima koji su označeni pomoću funkcije zaštite od prijetnji u Chromeu za poduzeća. Oni mogu obuhvaćati URL-ove stranica, naziv datoteke i metapodatke datoteke, korisničko ime uređaja i korisničko ime za Chrome.</translation>
<translation id="6440503408713884761">Zanemareno</translation>
<translation id="6446163441502663861">Kahu (omotnica)</translation>
<translation id="6446608382365791566">Dodajte još podataka</translation>
@@ -1017,20 +1036,19 @@
<translation id="6465306955648956876">Upravljajte zaporkama...</translation>
<translation id="647261751007945333">Pravila uređaja</translation>
<translation id="6476284679642588870">Upravljajte načinima plaćanja</translation>
-<translation id="6477321094435799029">Chrome je otkrio neuobičajeni kôd na toj stranici i blokirao ju je radi zaštite vaših osobnih podataka (primjerice zaporki, telefonskih brojeva i kreditnih kartica).</translation>
<translation id="6489534406876378309">Pokreni prijenos rušenja</translation>
<translation id="6499038740797743453">Želite li poništiti zaporku?</translation>
<translation id="6507833130742554667">Prihvaćaju se kreditne i debitne kartice.</translation>
<translation id="650855688985305916">Da, pohrani</translation>
<translation id="6508722015517270189">Ponovo pokrenite Chrome</translation>
<translation id="6517596291481585650">Upozorenje: pravilo nije spojeno kao popis prema uputama u pravilima jer se ne radi o popisu.</translation>
+<translation id="6518133107902771759">Potvrdi</translation>
<translation id="6521745193039995384">Nije aktivno</translation>
<translation id="6529602333819889595">&amp;Ponovi brisanje</translation>
<translation id="6534179046333460208">Prijedlozi Fizičkog weba</translation>
<translation id="6545864417968258051">Traženje Bluetootha</translation>
<translation id="6554795675067793129">Vašim računom upravlja <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Ponovi</translation>
-<translation id="6563469144985748109">Voditelj je još nije odobrio</translation>
<translation id="6569060085658103619">Gledate stranicu proširenja</translation>
<translation id="6578796323535178455">C2 (omotnica)</translation>
<translation id="6579990219486187401">Svijetloružičasta</translation>
@@ -1048,11 +1066,13 @@
<translation id="6643016212128521049">Izbriši</translation>
<translation id="6644283850729428850">Ovo je pravilo zastarjelo.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nijedna}=1{S jedne web-lokacije (nećete se odjaviti s Google računa)}one{S # web-lokacije (nećete se odjaviti s Google računa)}few{S # web-lokacije (nećete se odjaviti s Google računa)}other{S # web-lokacija (nećete se odjaviti s Google računa)}}</translation>
+<translation id="6652101503459149953">Koristi Windows Hello</translation>
<translation id="6657585470893396449">Zaporka</translation>
<translation id="6670613747977017428">Natrag u sigurnost.</translation>
<translation id="6671697161687535275">Želite li ukloniti prijedlog iz Chromiuma?</translation>
<translation id="6685834062052613830">Odjavite se i dovršite postavljanje</translation>
<translation id="6689271823431384964">Chrome vam nudi spremanje vaših kartica na vaš Google račun jer ste prijavljeni. To ponašanje možete promijeniti u postavkama. Ime nositelja kartice preuzeto je s vašeg računa.</translation>
+<translation id="6707256370811247129">Pregledajte sadržaj predmemorije i datoteka koje preuzimate s Chromea ili prenosite na Chrome.</translation>
<translation id="6710213216561001401">Prethodno</translation>
<translation id="6710594484020273272">&lt;Upišite pojam za pretraživanje&gt;</translation>
<translation id="671076103358959139">Oznaka za prijavu:</translation>
@@ -1060,10 +1080,10 @@
<translation id="6738516213925468394">Vaši su podaci kriptirani vašom <ph name="BEGIN_LINK" />šifrom za sinkronizaciju<ph name="END_LINK" /> <ph name="TIME" />. Unesite je da biste pokrenuli sinkronizaciju.</translation>
<translation id="674375294223700098">Nepoznata pogreška certifikata poslužitelja</translation>
<translation id="6744009308914054259">Dok čekate vezu, možete otvoriti Preuzimanja i čitati offline članke.</translation>
+<translation id="6747611005629681221">Upozorenje: sljedeće su značajke ukinute!</translation>
<translation id="6753269504797312559">Vrijednost pravila</translation>
<translation id="6757797048963528358">Uređaj je u stanju mirovanja.</translation>
<translation id="6768213884286397650">Hagaki (dopisnica)</translation>
-<translation id="6778737459546443941">Roditelj je još nije odobrio</translation>
<translation id="67862343314499040">Ljubičasta</translation>
<translation id="6786747875388722282">Proširenja</translation>
<translation id="6790428901817661496">Reproduciraj</translation>
@@ -1071,6 +1091,7 @@
<translation id="681021252041861472">Obavezno polje</translation>
<translation id="6810899417690483278">ID prilagođavanja</translation>
<translation id="6825578344716086703">Pokušali ste doseći domenu <ph name="DOMAIN" />, ali poslužitelj je predstavio certifikat potpisan slabim algoritmom potpisa (kao što je SHA-1). Znači da su sigurnosne vjerodajnice koje je poslužitelj predstavio možda krivotvorene, a poslužitelj možda nije poslužitelj koji očekujete (možda ste u komunikaciji s napadačem).</translation>
+<translation id="6826370046007623921">Sprječavanje gubitka podataka</translation>
<translation id="6831043979455480757">Prevedi</translation>
<translation id="6839929833149231406">Područje</translation>
<translation id="6852204201400771460">Ponovo učitati aplikaciju?</translation>
@@ -1083,7 +1104,6 @@
<translation id="6891596781022320156">Razina pravila nije podržana.</translation>
<translation id="6895330447102777224">Kartica je potvrđena</translation>
<translation id="6897140037006041989">Korisnički agent</translation>
-<translation id="6903319715792422884">Pomognite poboljšati Sigurno pregledavanje tako što ćete Googleu slati neke <ph name="BEGIN_WHITEPAPER_LINK" />podatke o sustavu i sadržaj web-stranice<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Korisnik:</translation>
<translation id="6934672428414710184">To je ime s vašeg Google računa</translation>
<translation id="6944692733090228304">Unijeli ste zaporku na web-lokaciju kojom ne upravlja <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Da biste zaštitili račun, nemojte upotrebljavati tu zaporku za druge aplikacije i web-lokacije.</translation>
@@ -1128,6 +1148,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavanda</translation>
<translation id="717330890047184534">ID za GAIA-u:</translation>
+<translation id="7174545416324379297">Spojeno</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> i još <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Poslužitelj kojem pristupate, <ph name="ORIGIN" />, zatražio je primjenu
sigurnosnog pravila na sve zahtjeve upućene prema njemu. No nije pružio
@@ -1165,6 +1186,7 @@ Dodatne pojedinosti:
<translation id="7320336641823683070">Pomoć za povezivanje</translation>
<translation id="733354035281974745">Nadjačavanje lokalnog računa na uređaju</translation>
<translation id="7334320624316649418">&amp;Ponovi promjenu rasporeda</translation>
+<translation id="7337706099755338005">Nije dostupno na vašoj platformi.</translation>
<translation id="733923710415886693">Certifikat poslužitelja nije otkriven putem Transparentnosti certifikata.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Korisnik je povezan:</translation>
@@ -1196,7 +1218,6 @@ Dodatne pojedinosti:
<translation id="7440140511386898319">Istraživanje dok ste offline</translation>
<translation id="7441627299479586546">Pogrešan predmet pravila</translation>
<translation id="7442725080345379071">Svijetlonarančasta</translation>
-<translation id="7444046173054089907">Ova je web-lokacija blokirana</translation>
<translation id="7445762425076701745">Identitet poslužitelja s kojim ste se povezali ne može se u potpunosti potvrditi. Povezali ste se s poslužiteljem upotrebom imena koje je valjano samo unutar vaše mreže, a za koje vanjsko tijelo za izdavanje certifikata nikako ne može potvrditi vlasništvo. Budući da postoje tijela za izdavanje certifikata koja će izdati certifikat za ta imena bez obzira na sve, nema načina da budete sigurni da ste povezani sa željenom web-lokacijom, a ne s napadačem.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /> o tom problemu.</translation>
<translation id="7455133967321480974">Upotrijebi globalnu zadanu vrijednost (blokiraj)</translation>
@@ -1218,9 +1239,9 @@ Dodatne pojedinosti:
<translation id="7538364083937897561">A2 (omotnica)</translation>
<translation id="7542403920425041731">Nakon što ih potvrdite, podaci o kartici dijelit će se s ovom web-lokacijom.</translation>
<translation id="7542995811387359312">Automatsko popunjavanje kreditne kartice onemogućeno je jer se ovaj obrazac ne služi sigurnom vezom.</translation>
-<translation id="7543525346216957623">Zamoli roditelja</translation>
<translation id="7548892272833184391">Ispravljanje pogrešaka veze</translation>
<translation id="7549584377607005141">Ova web-stranica zahtijeva podatke koje ste ranije unijeli da bi se pravilno prikazala. Te podatke možete poslati ponovo, ali time ćete ponoviti sve radnje koje je ta stranica prethodno izvela.</translation>
+<translation id="7550637293666041147">Korisničko ime uređaja i korisničko ime za Chrome</translation>
<translation id="7552846755917812628">Pokušajte učiniti sljedeće:</translation>
<translation id="7554791636758816595">Nova kartica</translation>
<translation id="7564049878696755256">Mogli biste izgubiti pristup svojem <ph name="ORG_NAME" /> računu ili bi netko mogao ukrasti vaš identitet. Chrome preporučuje da odmah promijenite zaporku.</translation>
@@ -1235,6 +1256,7 @@ Dodatne pojedinosti:
<translation id="7610193165460212391">Vrijednost je izvan raspona <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Istječe: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Već imate podatke koji su kriptirani pomoću druge verzije zaporke vašeg Google računa. Unesite je u nastavku.</translation>
+<translation id="7625784245512586808">Zaštita od prijetnji u Chromeu za poduzeća</translation>
<translation id="7633909222644580952">Podaci o uspješnosti i izvješća o padu programa</translation>
<translation id="7637571805876720304">Želite li ukloniti kreditnu karticu iz Chromiuma?</translation>
<translation id="7638605456503525968">Serijski priključci</translation>
@@ -1247,7 +1269,6 @@ Dodatne pojedinosti:
<translation id="7668654391829183341">Nepoznati uređaj</translation>
<translation id="7669271284792375604">Napadači na ovoj web-lokaciji mogu vas pokušati navesti na instaliranje programa koji smanjuju kvalitetu pregledavanja interneta (npr. promjenom početne stranice ili prikazivanjem dodatnih oglasa na web-lokacijama koje posjetite).</translation>
<translation id="7676643023259824263">Traženje teksta u međuspremniku, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platforma i oblak</translation>
<translation id="7681101578153515023">Promijeni tražilicu</translation>
<translation id="7682287625158474539">Dostava</translation>
<translation id="7687186412095877299">Popunjava obrasce za plaćanje spremljenim načinima plaćanja</translation>
@@ -1262,7 +1283,6 @@ Dodatne pojedinosti:
<translation id="7723047071702270851">Uredite karticu</translation>
<translation id="774634243536837715">Blokiran je opasan sadržaj.</translation>
<translation id="7752995774971033316">Nema upravitelja</translation>
-<translation id="7755287808199759310">Roditelj je može deblokirati</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Vezu možda blokira vatrozid ili antivirusni softver.</translation>
<translation id="7759163816903619567">Prikaži domenu:</translation>
@@ -1306,7 +1326,6 @@ Dodatne pojedinosti:
<translation id="8004582292198964060">Preglednik</translation>
<translation id="8009225694047762179">Upravljanje zaporkama</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ova kartica i njezina adresa za naplatu spremit će se. Moći ćete plaćati njome kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}one{Ove kartice i njihove adrese za naplatu spremit će se. Moći ćete plaćati njima kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}few{Ove kartice i njihove adrese za naplatu spremit će se. Moći ćete plaćati njima kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}other{Ove kartice i njihove adrese za naplatu spremit će se. Moći ćete plaćati njima kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Nismo uspjeli stupiti u kontakt s tvojim roditeljima. Pokušaj ponovo.</translation>
<translation id="8025119109950072390">Napadači na ovoj web-lokaciji mogu vas na prijevaru pokušati navesti da napravite nešto opasno kao što je instaliranje softvera ili otkrivanje osobnih podataka (npr. zaporki, telefonskih brojeva ili kreditnih kartica).</translation>
<translation id="8034522405403831421">Jezik ove stranice jest <ph name="SOURCE_LANGUAGE" />. Želite li je prevesti na <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pero</translation>
@@ -1317,6 +1336,7 @@ Dodatne pojedinosti:
<translation id="8041940743680923270">Upotrijebi globalnu zadanu vrijednost (pitaj)</translation>
<translation id="8042918947222776840">Odaberite način preuzimanja</translation>
<translation id="8057711352706143257">Softver "<ph name="SOFTWARE_NAME" />" nije ispravno konfiguriran. Taj se problem obično rješava deinstaliranjem softvera "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Odsad nećete trebati unositi sigurnosni kôd kartice</translation>
<translation id="8066955247577885446">Nešto nije u redu.</translation>
<translation id="8074253406171541171">10x13 (omotnica)</translation>
<translation id="8078141288243656252">Ne može dodati bilješku kada je dokument zakrenut</translation>
@@ -1347,6 +1367,7 @@ Dodatne pojedinosti:
<translation id="8211406090763984747">Veza je sigurna</translation>
<translation id="8218327578424803826">Dodijeljena lokacija:</translation>
<translation id="8220146938470311105">C7/C6 (omotnica)</translation>
+<translation id="8220639454292072926">Izvještavanje za poduzeća</translation>
<translation id="8225771182978767009">Osoba koja je postavila računalo blokirala je tu web-lokaciju.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Otvorite stranicu u novoj anonimnoj kartici</translation>
@@ -1401,24 +1422,24 @@ Dodatne pojedinosti:
<translation id="8508648098325802031">Ikona pretraživanja</translation>
<translation id="8522552481199248698">Chrome vam može pomoći da zaštitite svoj Google račun i promijenite zaporku.</translation>
<translation id="8543181531796978784">Možete <ph name="BEGIN_ERROR_LINK" />prijaviti problem s otkrivanjem<ph name="END_ERROR_LINK" /> ili, ako razumijete na koje je načine ugrožena vaša sigurnost, <ph name="BEGIN_LINK" />posjetite nesigurnu web-lokaciju<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Imate li pitanja? Obratite se osobi koja nadzire vaš profil.</translation>
<translation id="8553075262323480129">Prijevod nije uspio jer nije bilo moguće odrediti jezik stranice.</translation>
<translation id="8557066899867184262">CVC možete pronaći na poleđini kartice.</translation>
<translation id="8559762987265718583">Sigurnu vezu s domenom <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> nije moguće uspostaviti jer datum i vrijeme (<ph name="DATE_AND_TIME" />) na vašem uređaju nisu točni.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> sumnjiva web-lokacija</translation>
<translation id="8564985650692024650">Chromium preporučuje poništavanje zaporke za organizaciju <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ako ste je upotrebljavali za druge web-lokacije.</translation>
<translation id="8571890674111243710">Prijevod stranice na <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Dodaj tel. broj
</translation>
-<translation id="859285277496340001">Certifikat ne navodi mehanizam za provjeru svojeg opoziva.</translation>
<translation id="860043288473659153">Ime vlasnika kartice</translation>
<translation id="861775596732816396">Veličina 4</translation>
-<translation id="8620436878122366504">Roditelji je još nisu odobrili</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Spremi tu karticu na ovaj uređaj</translation>
<translation id="8626112503828625890">Želite li pohraniti podatke o naplati na Google račun?</translation>
+<translation id="8647750283161643317">Vrati sve na zadano</translation>
<translation id="8663226718884576429">Sažetak narudžbe, <ph name="TOTAL_LABEL" />, više pojedinosti</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, odgovor, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Dostupno</translation>
<translation id="8703575177326907206">Vaša veza s <ph name="DOMAIN" /> nije šifrirana.</translation>
<translation id="8718314106902482036">Plaćanje nije dovršeno</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, prijedlog za pretraživanje</translation>
@@ -1429,6 +1450,7 @@ Dodatne pojedinosti:
<translation id="8738058698779197622">Za uspostavu sigurne veze sat mora biti točno postavljen. To je zato što certifikati koje web-lokacije upotrebljavaju za međusobnu identifikaciju vrijede samo određeno vrijeme. Budući da sat na vašem uređaju nije točan, Chromium ne može potvrditi te certifikate.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;DNS adresa&lt;/abbr&gt; hosta <ph name="HOST_NAME" /> nije pronađena. U tijeku je dijagnosticiranje problema.</translation>
<translation id="874846938927089722">Prihvaćene kreditne i pretplatne kartice</translation>
+<translation id="874918643257405732">Označi ovu karticu</translation>
<translation id="8759274551635299824">Ta je kartica istekla</translation>
<translation id="8761567432415473239">Googleovo Sigurno pregledavanje nedavno je <ph name="BEGIN_LINK" />pronašlo štetne programe<ph name="END_LINK" /> na web-lokaciji <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB uređaj</translation>
@@ -1458,6 +1480,7 @@ Dodatne pojedinosti:
<translation id="8938939909778640821">Prihvaćene kreditne i pretplatne kartice</translation>
<translation id="8943282376843390568">Limeta</translation>
<translation id="8957210676456822347">Autorizacija obaveznog portala za autentifikaciju</translation>
+<translation id="8962950042226115166">Sumnjiva web-lokacija</translation>
<translation id="8968766641738584599">Spremanje kartice</translation>
<translation id="8971063699422889582">Istekao je certifikat poslužitelja.</translation>
<translation id="8975012916872825179">Sadrži podatke kao što su telefonski brojevi, e-adrese i adrese za dostavu</translation>
@@ -1480,25 +1503,25 @@ Dodatne pojedinosti:
<translation id="9035022520814077154">Sigurnosna pogreška</translation>
<translation id="9038649477754266430">Upotreba usluge predviđanja za brže učitavanje stranica</translation>
<translation id="9039213469156557790">Nadalje, ova stranica sadrži druge resurse koji nisu sigurni. Te resurse mogu vidjeti drugi tijekom prijenosa i napadač ih može izmijeniti kako bi promijenio ponašanje stranice.</translation>
+<translation id="9044359186343685026">Koristi Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Pokušali ste pristupiti domeni <ph name="DOMAIN" />, ali poslužitelj je prikazao nevažeći certifikat.</translation>
<translation id="9050666287014529139">Zaporka</translation>
<translation id="9065203028668620118">Uredi</translation>
<translation id="9065745800631924235">Pretraživanje <ph name="TEXT" /> iz povijesti</translation>
<translation id="9069693763241529744">Blokiralo proširenje</translation>
-<translation id="9076283476770535406">Možda ima sadržaj za odrasle</translation>
<translation id="9076630408993835509">Preglednikom ne upravlja tvrtka ili neka druga organizacija. Aktivnostima na tom uređaju možda se upravlja izvan Chromea. <ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Potrebno je više podataka</translation>
<translation id="9080712759204168376">Sažetak narudžbe</translation>
<translation id="9089260154716455634">Pravilo za prekid rada:</translation>
<translation id="9095388113577226029">Više jezika...</translation>
+<translation id="9098981495403789647">Administrator je u pregledniku omogućio funkciju zaštite od prijetnji u Chromeu za poduzeća. Zaštita od prijetnji u Chromeu za poduzeća ima pristup nekim vašim podacima.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> obično upotrebljava enkripciju radi zaštite vaših podataka. Prilikom ovog pokušaja povezivanja Chromiuma s web-lokacijom <ph name="SITE" /> ta je web-lokacija vratila neuobičajene
i netočne vjerodajnice. To može značiti da se neki napadač pokušava predstaviti kao <ph name="SITE" /> ili je zaslon za prijavu na Wi-Fi prekinuo vezu. Vaši su podaci još uvijek sigurni jer je Chromium zaustavio povezivanje prije razmjene podataka.</translation>
<translation id="9106062320799175032">Dodajte adresu za naplatu</translation>
<translation id="9114524666733003316">Potvrđivanje kartice...</translation>
<translation id="9128870381267983090">Povezivanje s mrežom</translation>
<translation id="9137013805542155359">Prikaži original</translation>
-<translation id="9137248913990643158">Pokrenite Chrome i prijavite se na njega da biste mogli upotrebljavati tu aplikaciju.</translation>
<translation id="9141013498910525015">Upravljanje adresama</translation>
<translation id="9148088599418889305">Odaberite način dostave</translation>
<translation id="9148507642005240123">&amp;Poništi uređivanje</translation>
diff --git a/chromium/components/strings/components_strings_hu.xtb b/chromium/components/strings/components_strings_hu.xtb
index e31dd0709e7..e72f8468162 100644
--- a/chromium/components/strings/components_strings_hu.xtb
+++ b/chromium/components/strings/components_strings_hu.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Adja meg a kártyán szereplő nevet</translation>
<translation id="1089439967362294234">Jelszó módosítása</translation>
+<translation id="1096545575934602868">Ebben a mezőben legfeljebb <ph name="MAX_ITEMS_LIMIT" /> bejegyzés szerepelhet. A rendszer az összes további bejegyzést elveti.</translation>
<translation id="109743633954054152">Jelszavak kezelése a Chrome beállításaiban</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> - mindig legyen lefordítva</translation>
<translation id="1107591249535594099">Ha be van jelölve, a Chrome ezen az eszközön tárolja a kártya egy példányát az űrlapok gyorsabb kitöltéséhez.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">A(z) <ph name="URL" /> egy <ph name="BEGIN_LINK" />tárolt változatának<ph name="END_LINK" /> megtekintése</translation>
<translation id="1156303062776767266">Helyi vagy megosztott fájlt tekint meg</translation>
<translation id="1158211211994409885">A(z) <ph name="HOST_NAME" /> váratlanul megszakította a kapcsolatot.</translation>
+<translation id="115926840831309955">Ellenőrizze a CVC-t, majd próbálja újra, vagy módosítsa a lejárati dátumot</translation>
<translation id="1161325031994447685">Újracsatlakozás Wi-Fi-hálózathoz</translation>
<translation id="1165039591588034296">Hiba</translation>
<translation id="1175364870820465910">&amp;Nyomtatás...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„A számítógépen található valamelyik szoftver megakadályozza a Chrome-ot abban, hogy biztonságosan csatlakozzon az internetre” (csak Windows rendszerű számítógépeken)</translation>
<translation id="1294154142200295408">Parancssorváltozatok</translation>
<translation id="129553762522093515">Mostanában bezárt</translation>
+<translation id="1298536327547837046">Rosszindulatú program keresése</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Próbálkozzon a cookie-k törlésével<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Elavult funkciók</translation>
<translation id="1320233736580025032">Prc1 (boríték)</translation>
<translation id="132301787627749051">Vágólapon lévő kép keresése</translation>
<translation id="1323433172918577554">Több</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Táblázatok</translation>
<translation id="1527263332363067270">Várakozás a kapcsolódásra…</translation>
<translation id="1529521330346880926">10x15 (boríték)</translation>
+<translation id="1530707389502320859">Az éppen felkeresni kívánt webhely hamisnak tűnik. A támadók néha úgy próbálnak meg webhelyeket utánozni, hogy apró, alig észrevehető változtatásokkal rendelkező URL-címeket használnak.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Az oldal közlendője</translation>
<translation id="153384715582417236">Egyelőre ennyi</translation>
@@ -145,7 +150,7 @@
<translation id="1645368109819982629">Nem támogatott protokoll</translation>
<translation id="1655462015569774233">{1,plural, =1{A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa tegnap lejárt. Ennek oka lehet konfigurációs hiba, de az is lehet, hogy egy támadó eltérítette az Ön kapcsolódását. Számítógépének órája jelenleg a következőre van állítva: <ph name="CURRENT_DATE" />. Ez megfelelőnek tűnik? Ha nem, állítsa be megfelelően a rendszer óráját, majd frissítse az oldalt.}other{A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa # nappal ezelőtt lejárt. Ennek oka lehet konfigurációs hiba, de az is lehet, hogy egy támadó eltérítette az Ön kapcsolódását. Számítógépének órája jelenleg a következőre van állítva: <ph name="CURRENT_DATE" />. Ez megfelelőnek tűnik? Ha nem, állítsa be megfelelően a rendszer óráját, majd frissítse az oldalt.}}</translation>
<translation id="1656489000284462475">Átvétel</translation>
-<translation id="1662550410081243962">Fizetési módok mentése és betöltése</translation>
+<translation id="1662550410081243962">Fizetési módok mentése és kitöltése</translation>
<translation id="1663943134801823270">A kártyák és a címek a Chrome-ból származnak. A <ph name="BEGIN_LINK" />Beállításokban<ph name="END_LINK" /> kezelheti őket.</translation>
<translation id="1669987054044193553">Megerősítés és mentés</translation>
<translation id="1671391448414634642">A(z) <ph name="SOURCE_LANGUAGE" /> nyelvű oldalak mostantól le lesznek fordítva <ph name="TARGET_LANGUAGE" /> nyelvre.</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">A dokumentum túl nagy a jegyzeteléshez</translation>
-<translation id="1721312023322545264">A webhely felkereséséhez <ph name="NAME" /> engedélyére van szükség</translation>
<translation id="1721424275792716183">* A mező kitöltése kötelező</translation>
<translation id="1727741090716970331">Érvényes kártyaszámot adjon meg</translation>
<translation id="1728677426644403582">Jelenleg weboldal forrását tekinti meg</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">A felkeresett webhelyek és a rajtuk eltöltött idő</translation>
<translation id="1826516787628120939">Ellenőrzés</translation>
<translation id="1834321415901700177">A webhely ártalmas programokat tartalmaz</translation>
+<translation id="1838374766361614909">Keresett kifejezés törlése</translation>
<translation id="1839551713262164453">A házirendértékek ellenőrzése hibák miatt sikertelen</translation>
<translation id="1842969606798536927">Fizetés</translation>
<translation id="1871208020102129563">A proxy fix proxyszerverek használatára van beállítva, nem pedig .pac típusú szkript URL címének használatára.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Lista bezárása</translation>
<translation id="1898423065542865115">Szűrés</translation>
<translation id="1914326953223720820">Kicsomagolási szolgáltatás</translation>
+<translation id="1915697529809968049">A Touch ID funkciót szeretné használni a CVC helyett?</translation>
<translation id="1916770123977586577">A frissített beállításoknak a webhelyen történő alkalmazásához töltse be újra az oldalt</translation>
<translation id="1919345977826869612">Hirdetések</translation>
<translation id="1919367280705858090">Segítség kérése adott hibaüzenet esetén</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">A(z) <ph name="DOMAIN" /> könyvjelzői</translation>
<translation id="1973335181906896915">Szerializálási hiba</translation>
<translation id="1974060860693918893">Speciális</translation>
+<translation id="1974883374937189061">Segítse a Chrome biztonságának fejlesztését azzal, hogy továbbítja <ph name="BEGIN_WHITEPAPER_LINK" />egyes felkeresett oldalak URL-jét, valamint korlátozott rendszer-információkat és bizonyos oldaltartalmakat<ph name="END_WHITEPAPER_LINK" /> a Google-nak. <ph name="PRIVACY_PAGE_LINK" />.</translation>
<translation id="1978555033938440688">Firmware verziószáma</translation>
<translation id="1981206234434200693">Törölje a Chrome böngészési előzményeit</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{és 1 további}other{és # további}}</translation>
@@ -247,17 +254,19 @@
<translation id="2202020181578195191">Érvényes lejárati évet kell megadnia</translation>
<translation id="2212735316055980242">Nem találhatók irányelvek</translation>
<translation id="2213606439339815911">Bejegyzések lekérése...</translation>
+<translation id="2215727959747642672">Fájlszerkesztés</translation>
<translation id="2218879909401188352">A(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhelyen lévő támadók veszélyes alkalmazásokat telepíthetnek, amelyek károsíthatják eszközét, rejtett költségeket okozhatnak a mobiltelefon-számlán, vagy ellophatják személyes adatait. <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="2224337661447660594">Nincs internet</translation>
<translation id="2230458221926704099">Javítsa meg kapcsolatát a <ph name="BEGIN_LINK" />diagnosztikai alkalmazás<ph name="END_LINK" /> segítségével</translation>
<translation id="2239100178324503013">Küldés most</translation>
+<translation id="2248949050832152960">WebAuthn használata</translation>
<translation id="225207911366869382">Ez az érték elavult ennél a házirendnél.</translation>
<translation id="2257315177824333709">A kártya jelenleg sajnos nem menthető</translation>
<translation id="2262243747453050782">HTTP hiba</translation>
<translation id="2263079731045660823">Hitelkártyával kapcsolatos automatikus kitöltési adatok frissítése a Chrome beállításaiban</translation>
<translation id="2270484714375784793">Telefonszám</translation>
<translation id="2277103315734023688">Ugrás előre</translation>
-<translation id="2283340219607151381">Címek mentése és betöltése</translation>
+<translation id="2283340219607151381">Címek mentése és kitöltése</translation>
<translation id="2292556288342944218">Az internethez való hozzáférést a rendszer letiltotta</translation>
<translation id="2297722699537546652">B5 (boríték)</translation>
<translation id="2310021320168182093">Chou2 (boríték)</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Érvénytelen keresési URL</translation>
<translation id="2482878487686419369">Értesítések</translation>
<translation id="248348093745724435">A számítógép házirendjei</translation>
-<translation id="2485387744899240041">Az eszköz és a böngésző felhasználónevei</translation>
<translation id="2491120439723279231">A szervezet tanúsítványa hibákat tartalmaz.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Parser</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Visszalépés</translation>
<translation id="2503184589641749290">Elfogadott bank- és feltöltőkártyák</translation>
<translation id="2505268675989099013">Fiók védelme</translation>
+<translation id="2515335152965840738">MELLŐZÉS</translation>
<translation id="2515629240566999685">A térerő ellenőrzése tartózkodási helyén</translation>
<translation id="2523886232349826891">Csak erre az eszközre mentve</translation>
<translation id="2524461107774643265">További adatok hozzáadása</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Elküldés</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nincs}=1{1 jelszó (a következő domainekhez: <ph name="DOMAIN_LIST" />)}=2{2 jelszó (a következő domainekhez: <ph name="DOMAIN_LIST" />)}other{# jelszó (a következő domainekhez: <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Zárja be a többi lapot vagy alkalmazást</translation>
-<translation id="267371737713284912">visszavonás: <ph name="MODIFIER_KEY_DESCRIPTION" /></translation>
<translation id="2674170444375937751">Biztosan törölni szeretné ezeket az oldalakat az előzmények közül?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Lap elhagyása</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">Az érték nem egyezik a formátummal.</translation>
<translation id="2705137772291741111">A webhely mentett (gyorsítótárazott) példánya nem olvasható.</translation>
<translation id="2709516037105925701">Automatikus kitöltés</translation>
-<translation id="2712173769900027643">Engedély kérése</translation>
<translation id="2713444072780614174">Fehér</translation>
<translation id="2720342946869265578">A közelben</translation>
<translation id="2721148159707890343">Sikeres kérés</translation>
<translation id="2728127805433021124">A szerver tanúsítványa gyenge aláírási algoritmussal van aláírva.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Kapcsolódási diagnosztika futtatása<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ha engedélyezi ezeket a funkciókat, előfordulhat, hogy elvesznek a böngészési adatok, illetve veszélyeztetheti biztonságát és személyes adatait. Az engedélyezett funkciók a böngésző minden felhasználójára vonatkoznak.</translation>
<translation id="2735043616039983645">Több, egymással ütköző értékekkel rendelkező forrás található ennél a házirendnél.</translation>
<translation id="2738330467931008676">Átvételi cím kiválasztása</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">A kapcsolat alaphelyzetbe állt.</translation>
<translation id="2788784517760473862">Elfogadott hitelkártyák</translation>
<translation id="2792012897584536778">Az eszköz rendszergazdái olyan biztonsági tanúsítványokat állítottak be, amelyek lehetővé tehetik számukra az Ön által felkeresett webhelyek tartalmának megtekintését.</translation>
-<translation id="2794233252405721443">A webhely le van tiltva</translation>
<translation id="2799020568854403057">A felkeresni kívánt webhely káros alkalmazásokat tartalmaz</translation>
<translation id="2799223571221894425">Újraindítás</translation>
<translation id="2803306138276472711">A Google – Biztonságos böngészés nemrég <ph name="BEGIN_LINK" />rosszindulatú programot<ph name="END_LINK" /> észlelt a(z) <ph name="SITE" /> webhelyen. A rendes esetben biztonságos webhelyek néha rosszindulatú programokkal fertőzöttek.</translation>
+<translation id="2815364696811431560">WEBHELY ELHAGYÁSA</translation>
<translation id="2824775600643448204">Cím- és keresősáv</translation>
<translation id="2826760142808435982">A kapcsolat <ph name="KX" /> algoritmust használ kulcscserélő mechanizmusként, kódolása pedig <ph name="CIPHER" /> használatával történt.</translation>
<translation id="2835170189407361413">Űrlap törlése</translation>
<translation id="2847118875340931228">Inkognitóablak megnyitása</translation>
<translation id="2850739647070081192">Invite (boríték)</translation>
-<translation id="2851634818064021665">A webhely felkereséséhez jogosultságra van szüksége</translation>
<translation id="2856444702002559011">A támadók megpróbálhatják ellopni a(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhelyen lévő adatait (például jelszavait, üzeneteit és hitelkártyaadatait). <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Menti a kártyát?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Ha engedélyezi, a Chromium megőrzi a kártya másolatát ezen az eszközön a gyorsabb űrlapkitöltés érdekében.</translation>
<translation id="2985398929374701810">Érvényes címet adjon meg</translation>
<translation id="2986368408720340940">Ez az átvételi mód nem áll rendelkezésre. Próbálkozzon másik móddal.</translation>
+<translation id="2987034854559945715">Nem található ilyen funkció</translation>
<translation id="2991174974383378012">Megosztás webhelyekkel</translation>
<translation id="2991571918955627853">A(z) <ph name="SITE" /> webhelyet pillanatnyilag nem tudja felkeresni, mert a webhely HSTS-t használ. A hálózati hibák és támadások rendszerint átmenetiek, ezért az említett oldal működése később valószínűleg helyreáll.</translation>
<translation id="3005723025932146533">Mentett másolat megjelenítése</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Nem megfelelő irányelvtípus</translation>
<translation id="3037605927509011580">A manóba!</translation>
<translation id="3041612393474885105">Tanúsítvány adatai</translation>
+<translation id="3057676462092457419">A DnsOverHttps módot (<ph name="SECURE_DNS_MODE_SECURE" />) még nem támogatja a rendszer, ezért az alkalmazott módot <ph name="SECURE_DNS_MODE_OFF" /> állapotra állította.</translation>
<translation id="3060227939791841287">C9 (boríték)</translation>
<translation id="3061707000357573562">Javítókészlet szolgáltatás</translation>
<translation id="3064966200440839136">Inkognitómód elhagyása külső alkalmazással történő fizetéshez. Folytatja?</translation>
@@ -415,7 +424,7 @@
<translation id="3145945101586104090">Nem sikerült dekódolni a választ</translation>
<translation id="3150653042067488994">Átmeneti szerverhiba</translation>
<translation id="3154506275960390542">Az oldal olyan űrlapot tartalmaz, amely esetében előfordulhat, hogy küldése nem biztonságosan történik. Az elküldött adatokat továbbítás közben mások is megtekinthetik, illetve támadók módosíthatják, hogy a szerver mást kapjon helyettük.</translation>
-<translation id="3157931365184549694">Visszaállítás</translation>
+<translation id="3157931365184549694">Helyreállítás</translation>
<translation id="3162559335345991374">Az Ön által használt Wi-Fi-hálózat megkövetelheti bejelentkezési oldalának felkeresését.</translation>
<translation id="3167968892399408617">Az inkognitólapon megtekintett oldalak az összes inkognitólap bezárását követően nem szerepelnek majd böngészési előzményei között, a cookie-k gyűjtőhelyén, illetve a keresési előzményekben. A letöltött fájlok és a könyvjelzők azonban megmaradnak.</translation>
<translation id="3169472444629675720">Discover</translation>
@@ -425,6 +434,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> nyomtató a(z) <ph name="SERVER_NAME" /> nevű szerveren</translation>
<translation id="320323717674993345">Fizetés visszavonása</translation>
<translation id="3207960819495026254">Könyvjelző rögzítve</translation>
+<translation id="3209034400446768650">Az oldal díjat számíthat fel</translation>
<translation id="3225919329040284222">A szerver tanúsítványa nem felel meg a beépített elvárásoknak. Ezek a beépített elvárások bizonyos nagy biztonságú webhelyekre vonatkoznak az Ön védelme érdekében.</translation>
<translation id="3226128629678568754">Nyomja meg a frissítés gombot az oldal betöltéséhez szükséges adatok újraküldéséhez.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -432,7 +442,6 @@
<translation id="3229041911291329567">Az eszköz és a böngésző verzióadatai</translation>
<translation id="323107829343500871">Adja meg a(z) <ph name="CREDIT_CARD" /> kártya CVC-kódját</translation>
<translation id="3234666976984236645">Mindig észlelje a fontos tartalmat ezen a webhelyen</translation>
-<translation id="3254409185687681395">Könyvjelző hozzáadása ehhez az oldalhoz</translation>
<translation id="3270847123878663523">&amp;Átrendezés visszavonása</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Adja meg a kártyán szereplő nevet</translation>
@@ -442,7 +451,6 @@
<translation id="3320021301628644560">Számlázási cím hozzáadása</translation>
<translation id="3324983252691184275">Karmazsinvörös</translation>
<translation id="3338095232262050444">Biztonságos</translation>
-<translation id="3345135638360864351">A webhelyhez való hozzáférésre irányuló kérelme nem jutott el <ph name="NAME" /> felhasználóhoz. Kérjük, próbálkozzon újra.</translation>
<translation id="3355823806454867987">Proxybeállítások módosítása...</translation>
<translation id="3361596688432910856">A Chrome <ph name="BEGIN_EMPHASIS" />nem menti<ph name="END_EMPHASIS" /> a következő adatokat:
<ph name="BEGIN_LIST" />
@@ -476,18 +484,15 @@
<translation id="3462200631372590220">Speciális beállítások elrejtése</translation>
<translation id="3467763166455606212">A kártyatulajdonos nevének megadása kötelező</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, jelenleg meg van nyitva, a Tab, majd az Enter billentyűk lenyomásával válthat a megnyitott lapra</translation>
-<translation id="3479539252931486093">Ez váratlanul érte Önt? <ph name="BEGIN_LINK" />Tudassa velünk.<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ne most</translation>
<translation id="3484560055331845446">Elveszítheti a hozzáférést Google-fiókjához. A Chrome azt javasolja, hogy azonnal módosítsa jelszavát. Be kell majd jelentkeznie.</translation>
<translation id="3495081129428749620">Keresés a következő oldalon:
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Jelenleg nem tudjuk elérni szüleidet. Próbálkozz újra.</translation>
<translation id="3512163584740124171">A böngésző figyelmen kívül hagyja ezt a házirendet, mert magasabb prioritással rendelkezik egy másik házirend ugyanabból a házirendcsoportból.</translation>
<translation id="3528171143076753409">A szervezet tanúsítványa nem megbízható.</translation>
<translation id="3528485271872257980">Sötétbarna</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Legalább 1 elem van a szinkronizált eszközökön}=1{1 elem (és még több a szinkronizált eszközökön)}other{# elem (és még több a szinkronizált eszközökön)}}</translation>
<translation id="3539171420378717834">A kártya másolatának megőrzése az eszközön</translation>
-<translation id="3556433843310711081">A letiltást a kezelő oldhatja fel</translation>
<translation id="3566021033012934673">Az Ön kapcsolata nem privát</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">A(z) <ph name="SITE" /> egyik beágyazott oldalának közlendője</translation>
@@ -515,6 +520,7 @@
<translation id="3678529606614285348">Oldal megnyitása új inkognitóablakban (Ctrl+Shift+N)</translation>
<translation id="3679803492151881375">A hibajelentés elkészítésének ideje: <ph name="CRASH_TIME" />; a feltöltés ideje: <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Tanúsítvány adatai</translation>
+<translation id="3701427423622901115">Visszaállítás elfogadva.</translation>
<translation id="3704162925118123524">Előfordulhat, hogy az Ön által használt hálózat megköveteli a bejelentkezési oldalán történő bejelentkezést.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Betöltés...</translation>
@@ -531,6 +537,7 @@
<translation id="3748148204939282805">A támadók a(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhelyen megpróbálhatják csellel rávenni Önt például arra, hogy veszélyes szoftvert telepítsen, vagy felfedje személyes adatait (jelszavakat, telefonszámokat, bankkártyaadatokat stb). <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="375403751935624634">A fordítás a szerver hibája miatt nem sikerült.</translation>
<translation id="3759461132968374835">Nincs a közelmúltban bejelentett rendszerösszeomlás. A kikapcsolt jelentésküldés során történt összeomlások nem jelennek meg itt.</translation>
+<translation id="3760561303380396507">A Windows Hello szolgáltatást szeretné használni a CVC helyett?</translation>
<translation id="3761718714832595332">Állapot elrejtése</translation>
<translation id="3765032636089507299">A Biztonságos Böngészés oldal fejlesztés alatt áll</translation>
<translation id="3778403066972421603">Szeretné menteni a kártyát Google-fiókjába és az eszközre?</translation>
@@ -540,6 +547,7 @@
<translation id="3789155188480882154">Méret: 16</translation>
<translation id="3797522431967816232">Prc3 (boríték)</translation>
<translation id="3807873520724684969">Kártékony tartalom letiltva.</translation>
+<translation id="3808375843007691220">Figyelem: Kísérleti funkciók következnek!</translation>
<translation id="3810973564298564668">Szerkesztés</translation>
<translation id="382518646247711829">Ha proxyszervert használ...</translation>
<translation id="3828924085048779000">Az üres összetett jelszó nem engedélyezett.</translation>
@@ -548,11 +556,11 @@
<translation id="3858027520442213535">Dátum és idő frissítése</translation>
<translation id="3884278016824448484">Eszközazonosító-ütközés</translation>
<translation id="3885155851504623709">Körzet</translation>
-<translation id="3886446263141354045">Webhely-hozzáférési kérelme elküldve a következő személynek: <ph name="NAME" /></translation>
<translation id="3890664840433101773">E-mail-cím hozzáadása</translation>
<translation id="3901925938762663762">A kártya lejárt</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">A WebAuthn szolgáltatást szeretné használni a CVC helyett?</translation>
<translation id="3946209740501886391">Mindig kérdezze meg ezen a webhelyen</translation>
<translation id="3949571496842715403">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványában nincs meghatározva a „Subject Alternative Names” mező. Ezt okozhatja konfigurációs hiba, vagy az, hogy egy támadó eltérítette az Ön kapcsolatát.</translation>
<translation id="3949601375789751990">A böngészési előzmények itt jelennek meg</translation>
@@ -563,11 +571,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nincs}=1{ 1 webhelytől }other{# webhelytől }}</translation>
<translation id="397105322502079400">Számítás…</translation>
<translation id="3973234410852337861">A(z) <ph name="HOST_NAME" /> le van tiltva</translation>
+<translation id="3981540111851280311">A(z) <ph name="ENROLLMENT_DOMAIN" /> engedélyezte a Chrome Enterprise fenyegetések elleni védelmét a böngészőben. A Chrome Enterprise fenyegetések elleni védelme hozzáfér az Ön bizonyos adataihoz.</translation>
<translation id="3987940399970879459">Kevesebb mint 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 közeli weboldal}other{# közeli weboldal}}</translation>
<translation id="4030383055268325496">&amp;Hozzáadás visszavonása</translation>
<translation id="4032320456957708163">Böngészőjét a(z) <ph name="ENROLLMENT_DOMAIN" /> felügyeli</translation>
-<translation id="4034375457890803692">A megnyitott link olyan webhelyre vezet, amelyet Ön nem szokott felkeresni. Lehet, hogy a link megpróbálja megtéveszteni Önt.</translation>
<translation id="4058922952496707368">"<ph name="SUBKEY" />" kulcs: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (boríték)</translation>
<translation id="4067947977115446013">Érvényes címet adjon meg</translation>
@@ -580,6 +588,7 @@
<translation id="4103249731201008433">Az eszköz sorozatszáma érvénytelen</translation>
<translation id="410351446219883937">Automatikus lejátszás</translation>
<translation id="4103763322291513355">Látogasson el a &lt;strong&gt;chrome://policy&lt;/strong&gt; oldalra a feketelistán lévő URL-ek és egyéb, a rendszergazda által előírt szabályok megtekintéséhez.</translation>
+<translation id="4108231218301530806">Ujjlenyomat használata ennek a kártyának az igazolására a következő alkalommal.</translation>
<translation id="4110652170750985508">Befizetés áttekintése</translation>
<translation id="4112140312785995938">Ugrás visszafelé</translation>
<translation id="4116663294526079822">Mindig engedélyezze ezen az oldalon</translation>
@@ -594,6 +603,7 @@
<translation id="4171400957073367226">Hibás igazoló aláírás.</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{ még <ph name="ITEM_COUNT" /> elem}other{ még <ph name="ITEM_COUNT" /> elem}}</translation>
+<translation id="4176463684765177261">Letiltva</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" />: <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">A következő alkalommal gyorsabban fizethet, ha kártyáját és számlázási címét hozzáadja Google-fiókjához.</translation>
<translation id="4196861286325780578">&amp;Áthelyezés újra</translation>
@@ -630,6 +640,7 @@
<translation id="4277028893293644418">Jelszó visszaállítása</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> eszközét a(z) <ph name="ENROLLMENT_DOMAIN" /> kezeli</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{A kártyát mentettük a Google-fiókjába.}other{Ezeket a kártyákat mentettük a Google-fiókjába.}}</translation>
+<translation id="428847186335018806">A Chrome használatával letöltött és feltöltött fájlok ellenőrzése.</translation>
<translation id="42981349822642051">Kibontás</translation>
<translation id="4302965934281694568">Chou3 (boríték)</translation>
<translation id="4305817255990598646">Váltás</translation>
@@ -659,7 +670,6 @@
<translation id="4435702339979719576">képeslap)</translation>
<translation id="443673843213245140">A proxy használata le van tiltva, de kifejezett proxykonfiguráció van megadva.</translation>
<translation id="445100540951337728">Elfogadott bankkártyák</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> gyanús viselkedés</translation>
<translation id="4466881336512663640">Az űrlapon végzett módosítások elvesznek. Biztosan folytatni szeretné?</translation>
<translation id="4477350412780666475">Következő szám</translation>
<translation id="4482953324121162758">Nem fordítjuk le ezt a webhelyet.</translation>
@@ -686,6 +696,7 @@
<translation id="4594403342090139922">&amp;Törlés visszavonása</translation>
<translation id="4597348597567598915">Méret: 8</translation>
<translation id="4600854749408232102">C6/C5 (boríték)</translation>
+<translation id="464342062220857295">Funkciók keresése</translation>
<translation id="4646534391647090355">Megnézem most</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa hibákat tartalmaz. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolódását.</translation>
@@ -694,7 +705,6 @@
<translation id="4691835149146451662">Architecture-A (boríték)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Kapcsolata megszakadt</translation>
-<translation id="471880041731876836">Nincs jogosultsága a webhely felkereséséhez</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />A Windows Hálózati diagnosztika futtatása<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Házirendek újratöltése</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -722,7 +732,6 @@
<translation id="4816492930507672669">Igazítás az oldalmérethez</translation>
<translation id="4850886885716139402">Nézet</translation>
<translation id="4854362297993841467">Ez a kézbesítési mód nem áll rendelkezésre. Próbálkozzon másik móddal.</translation>
-<translation id="4858792381671956233">Megkérdezted a szüleidet, hogy meg szabad-e látogatnod ezt a webhelyet</translation>
<translation id="4864052566555297930">Biztonsággal kapcsolatos tanács:</translation>
<translation id="4876188919622883022">Egyszerűsített nézet</translation>
<translation id="4876305945144899064">Nincs felhasználónév</translation>
@@ -746,7 +755,9 @@
<translation id="4974590756084640048">Figyelmeztetések újbóli engedélyezése</translation>
<translation id="4984339528288761049">Prc5 (boríték)</translation>
<translation id="4989163558385430922">Összes megtekintése</translation>
+<translation id="4989542687859782284">Nem áll rendelkezésre</translation>
<translation id="4989809363548539747">Ez a beépülő modul nem támogatott</translation>
+<translation id="4995216769782533993">Ahhoz, hogy megoszthassa kártyájának adatait ezzel a webhellyel, meg kell erősítenie a biztonsági kódot</translation>
<translation id="5002932099480077015">Ha engedélyezi, a Chrome megőrzi a kártya másolatát ezen az eszközön a gyorsabb űrlapkitöltés érdekében.</translation>
<translation id="5015510746216210676">Számítógépnév:</translation>
<translation id="5017554619425969104">Vágólapra másolt szöveg</translation>
@@ -775,6 +786,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bites)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Kártya ellenőrzése</translation>
<translation id="5135404736266831032">Címek kezelése…</translation>
<translation id="5138227688689900538">Kevesebb megjelenítése</translation>
<translation id="5141240743006678641">A szinkronizált jelszavak titkosítása a Google hitelesítési adataival</translation>
@@ -801,6 +813,7 @@
<translation id="5251803541071282808">Felhő</translation>
<translation id="5252000469029418751">C7 (boríték)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Rendszerszinten érvényes funkciókat csak a tulajdonos (<ph name="OWNER_EMAIL" />) állíthat be</translation>
<translation id="5273658854610202413">Figyelem: Ezt a házirendet nem egyesítette a rendszer a PolicyDictionaryMultipleSourceMergeList házirend előírásainak megfelelően, mert nem része az egyesíthető szótárházirendeknek.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Befejezés</translation>
@@ -824,7 +837,6 @@
<translation id="536296301121032821">Az irányelv-beállítások tárolása sikertelen</translation>
<translation id="5371425731340848620">Kártya frissítése</translation>
<translation id="5377026284221673050">„Az óra késik”, „Az óra siet” vagy „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;”</translation>
-<translation id="5377179979757081683">Ez az oldal megpróbálhatja becsapni Önt, személyes adatokat lophat, illetve kárt okozhat eszközében. Legyen óvatos személyes adatok megadásakor és letöltött fájlok megnyitásakor.</translation>
<translation id="5384855140246857529">Ha az összes eszközén szeretné használni kártyáit, jelentkezzen be, és kapcsolja be a szinkronizálást.</translation>
<translation id="5386426401304769735">A webhely tanúsítványlánca SHA-1 titkosítással aláírt tanúsítványt tartalmaz.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -838,6 +850,7 @@
<translation id="5457113250005438886">Érvénytelen</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> és további <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> és további <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Szerkesztés újra</translation>
+<translation id="5473728911100096288">Olyan elavult funkciók engedélyezésére készül, amelyek a későbbi verziókban már nem fognak szerepelni.</translation>
<translation id="5478437291406423475">B6/C4 (boríték)</translation>
<translation id="5481076368049295676">Lehet, hogy ez a tartalom megpróbál olyan veszélyes szoftvert telepíteni az eszközre, amely ellophatja vagy törölheti az Ön adatait. <ph name="BEGIN_LINK" />Megjelenítés mindenképpen<ph name="END_LINK" />.</translation>
<translation id="54817484435770891">Érvényes címet adjon meg</translation>
@@ -861,7 +874,6 @@
<translation id="5570825185877910964">Fiók védelme</translation>
<translation id="5571083550517324815">Ezen a címen nem lehetséges az átvétel. Válasszon másik címet.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 van használatban}other{# van használatban}})</translation>
-<translation id="5572851009514199876">Indítsa el a Chrome böngészőt és jelentkezzen be, hogy a Chrome ellenőrizni tudja, engedélyezték-e a hozzáférést ehhez a webhelyhez.</translation>
<translation id="5580958916614886209">Ellenőrizze a lejárati hónapot, majd próbálja újra</translation>
<translation id="5586446728396275693">Nincsenek mentett címek</translation>
<translation id="5595485650161345191">Cím szerkesztése</translation>
@@ -869,6 +881,7 @@
<translation id="560412284261940334">A kezelés nem támogatott</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Ez a webhely hamis vagy megtévesztő szándékú lehet. A Chrome a webhely azonnali elhagyását javasolja.</translation>
<translation id="5610142619324316209">A kapcsolat ellenőrzése</translation>
<translation id="5610807607761827392">A kártyákat és a címeket a <ph name="BEGIN_LINK" />Beállítások<ph name="END_LINK" /> menüpontban kezelheti.</translation>
<translation id="5617949217645503996">A(z) <ph name="HOST_NAME" /> túl sokszor irányította át.</translation>
@@ -892,11 +905,11 @@
<translation id="5720705177508910913">Jelenlegi felhasználó</translation>
<translation id="5728056243719941842">C5 (boríték)</translation>
<translation id="5730040223043577876">A Chrome azt javasolja, hogy adjon meg új jelszót a régi helyett, ha azt más webhelyeken is használta.</translation>
-<translation id="5732392974455271431">A letiltást a szüleid oldhatják fel</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Kártya mentése a Google-fiókba}other{Kártyák mentése a Google-fiókba}}</translation>
<translation id="5763042198335101085">Érvényes e-mail-címet adjon meg</translation>
<translation id="5765072501007116331">A kézbesítési módok és követelmények megtekintéséhez válassza ki a címet</translation>
<translation id="5778550464785688721">MIDI eszközök – teljes hozzáférés</translation>
+<translation id="5781136890105823427">Kísérlet engedélyezve</translation>
<translation id="578305955206182703">Borostyánsárga</translation>
<translation id="57838592816432529">Némítás</translation>
<translation id="5784606427469807560">A kártya ellenőrzése során hiba történt. Ellenőrizze az internetkapcsolatot, majd próbálkozzon újra.</translation>
@@ -913,13 +926,16 @@
<translation id="5860033963881614850">Kikapcsolva</translation>
<translation id="5863847714970149516">Előfordulhat, hogy a következő oldal megpróbál pénzt felszámolni Önnek</translation>
<translation id="5866257070973731571">Telefonszám hozzáadása</translation>
+<translation id="5866898949289125849">A fejlesztői eszközök egyik oldalát látja</translation>
<translation id="5869405914158311789">A webhely nem érhető el</translation>
<translation id="5869522115854928033">Mentett jelszavak</translation>
<translation id="5887400589839399685">Kártya elmentve</translation>
<translation id="5893752035575986141">Elfogadott hitelkártyák.</translation>
+<translation id="5895138241574237353">Újraindítás</translation>
<translation id="5901630391730855834">Sárga</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (szinkronizálva)</translation>
<translation id="5916664084637901428">Be</translation>
+<translation id="59174027418879706">Engedélyezve</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Menti a kártyát a Google-fiókjába?</translation>
<translation id="5922853866070715753">Majdnem kész</translation>
@@ -953,6 +969,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Minden eszközén szeretné használni a kártyákat?</translation>
<translation id="6059925163896151826">USB-eszközök</translation>
+<translation id="6060009363608157444">Érvénytelen DnsOverHttps-mód.</translation>
<translation id="6080696365213338172">A tartalmat egy rendszergazda által biztosított tanúsítványon keresztül érte el. A(z) <ph name="DOMAIN" /> számára megadott adatok a rendszergazda számára is elérhetők.</translation>
<translation id="6094273045989040137">Jegyzetelés</translation>
<translation id="610911394827799129">Előfordulhat, hogy a böngészési előzmények más formái még megtalálhatók Google-fiókjában a <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> webhelyen</translation>
@@ -1001,13 +1018,12 @@
<translation id="6404511346730675251">Könyvjelző szerkesztése</translation>
<translation id="6406765186087300643">C0 (boríték)</translation>
<translation id="6410264514553301377">Írja be a(z) <ph name="CREDIT_CARD" /> kártyán szereplő lejárati dátumot és CVC-t</translation>
-<translation id="6414888972213066896">Megkérdezted a szülőt, hogy meg szabad-e látogatnod ezt a webhelyet</translation>
<translation id="6415778972515849510">A Chromium segíthet a Google-fiók védelmében és a jelszó módosításában.</translation>
-<translation id="6417515091412812850">Nem lehet ellenőrizni, hogy a tanúsítványt visszavonták-e.</translation>
<translation id="6431585503458005759">Nem szeretném tárolni</translation>
<translation id="6433490469411711332">Kapcsolattartási adatok szerkesztése</translation>
<translation id="6433595998831338502">A(z) <ph name="HOST_NAME" /> visszautasította a csatlakozást.</translation>
<translation id="6434309073475700221">Elvetés</translation>
+<translation id="6435221585574090192">A Chrome Enterprise fenyegetések elleni védelme által megjelölt biztonsági események adatait megoszthatja az adminisztrátorral. Az adatok tartalmazhatják az oldalak URL-jeit, a fájlok nevét és metaadatait, valamint az eszközhöz és a Chrome-hoz tartozó felhasználónevét.</translation>
<translation id="6440503408713884761">Figyelmen kívül hagyva</translation>
<translation id="6446163441502663861">Kahu (boríték)</translation>
<translation id="6446608382365791566">További adatok hozzáadása</translation>
@@ -1016,20 +1032,19 @@
<translation id="6465306955648956876">Jelszavak kezelése…</translation>
<translation id="647261751007945333">Eszközházirendek</translation>
<translation id="6476284679642588870">Fizetési módok kezelése</translation>
-<translation id="6477321094435799029">A Chrome szokatlan kódot észlelt az oldalon, ezért letiltotta az Ön személyes adatainak (például jelszavak, telefonszámok és hitelkártyaszámok) védelme érdekében.</translation>
<translation id="6489534406876378309">Feltöltési összeomlások indítása</translation>
<translation id="6499038740797743453">Jelszó visszaállítása?</translation>
<translation id="6507833130742554667">Elfogadott hitel- és bankkártyák.</translation>
<translation id="650855688985305916">Igen, szeretném tárolni</translation>
<translation id="6508722015517270189">Indítsa újra a Chrome-ot</translation>
<translation id="6517596291481585650">Figyelem: Ezt a házirendet nem egyesítette a rendszer listaként a házirend előírásainak megfelelően, mert nem lista.</translation>
+<translation id="6518133107902771759">Ellenőrzés</translation>
<translation id="6521745193039995384">Nem aktív</translation>
<translation id="6529602333819889595">&amp;Törlés újra</translation>
<translation id="6534179046333460208">Fizikai web – javaslatok</translation>
<translation id="6545864417968258051">Bluetooth-alapú keresés</translation>
<translation id="6554795675067793129">Az Ön fiókkezelője: <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Újra</translation>
-<translation id="6563469144985748109">A kezelő még nem hagyta jóvá</translation>
<translation id="6569060085658103619">Jelenleg bővítményoldalt tekint meg</translation>
<translation id="6578796323535178455">C2 (boríték)</translation>
<translation id="6579990219486187401">Világos rózsaszín</translation>
@@ -1047,11 +1062,13 @@
<translation id="6643016212128521049">Törlés</translation>
<translation id="6644283850729428850">Ez a házirend már elavult.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nincs}=1{1 webhelyről (a böngésző nem jelentkezteti ki Google-fiókjából)}other{# webhelyről (a böngésző nem jelentkezteti ki Google-fiókjából)}}</translation>
+<translation id="6652101503459149953">Windows Hello használata</translation>
<translation id="6657585470893396449">Jelszó</translation>
<translation id="6670613747977017428">Vissza a biztonsághoz.</translation>
<translation id="6671697161687535275">Eltávolítja az űrlapjavaslatot a Chromiumból?</translation>
<translation id="6685834062052613830">Kijelentkezés és a beállítás befejezése</translation>
<translation id="6689271823431384964">A Chrome felajánlja a kártyák mentését az Ön Google-fiókjába, mert be van jelentkezve. A beállítások között ezt bármikor módosíthatja. A kártyatulajdonos nevének forrása az Ön fiókja.</translation>
+<translation id="6707256370811247129">A gyorsítótár és a Chrome használatával letöltött és feltöltött fájlok tartalmának ellenőrzése.</translation>
<translation id="6710213216561001401">Előző</translation>
<translation id="6710594484020273272">&lt;Írja be a keresési kifejezést&gt;</translation>
<translation id="671076103358959139">Regisztrációs token</translation>
@@ -1059,10 +1076,10 @@
<translation id="6738516213925468394">Adatai titkosítva lettek <ph name="BEGIN_LINK" />összetett szinkronizálási jelszavával<ph name="END_LINK" /> a következő időpontban: <ph name="TIME" />. Adja meg a jelszót a szinkronizálás megkezdéséhez.</translation>
<translation id="674375294223700098">Ismeretlen szervertanúsítvány-hiba.</translation>
<translation id="6744009308914054259">Miközben kapcsolatra vár, a Letöltések között elolvashatja az offline cikkeket.</translation>
+<translation id="6747611005629681221">Figyelem: Elavult funkciók következnek!</translation>
<translation id="6753269504797312559">Házirend értéke</translation>
<translation id="6757797048963528358">Eszköze alvó üzemmódba váltott.</translation>
<translation id="6768213884286397650">Hagaki (képeslap)</translation>
-<translation id="6778737459546443941">A szülő még nem hagyta jóvá</translation>
<translation id="67862343314499040">Ibolyaszín</translation>
<translation id="6786747875388722282">Bővítmények</translation>
<translation id="6790428901817661496">Játék</translation>
@@ -1070,6 +1087,7 @@
<translation id="681021252041861472">Kötelező mező</translation>
<translation id="6810899417690483278">Testreszabás-azonosító</translation>
<translation id="6825578344716086703">Megpróbálta elérni a(z) <ph name="DOMAIN" /> webhelyet, de a szerver gyenge aláírási algoritmust használó tanúsítványt mutatott be. Ez alapján elképzelhető, hogy a szerver által megadott biztonsági tanúsítványt meghamisították, és a szerver nem az, amelyikre számított (lehet, hogy éppen valamilyen támadóval kommunikál).</translation>
+<translation id="6826370046007623921">Adatszivárgás elleni védelem</translation>
<translation id="6831043979455480757">Fordítás</translation>
<translation id="6839929833149231406">Terület</translation>
<translation id="6852204201400771460">Újratölti az alkalmazást?</translation>
@@ -1082,7 +1100,6 @@
<translation id="6891596781022320156">Ezt a házirendszintet a rendszer nem támogatja.</translation>
<translation id="6895330447102777224">Kártyáját ellenőriztük</translation>
<translation id="6897140037006041989">User agent</translation>
-<translation id="6903319715792422884">Segítse a Biztonságos Böngészés fejlesztését azzal, hogy bizonyos <ph name="BEGIN_WHITEPAPER_LINK" />rendszer-információkat és oldaltartalmakat<ph name="END_WHITEPAPER_LINK" /> elküld a Google-nak. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Felhasználó:</translation>
<translation id="6934672428414710184">Ez a név a Google-fiókjából származik</translation>
<translation id="6944692733090228304">Olyan webhelyen adta meg a jelszavát, amelyet nem a(z) <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> kezel. Fiókja védelme érdekében ne használja fel újra a jelszót más alkalmazásokban és webhelyeken.</translation>
@@ -1127,12 +1144,13 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> és további <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> és további <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Levendula</translation>
<translation id="717330890047184534">Gaia-azonosító:</translation>
+<translation id="7174545416324379297">Egyesítve</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> és további <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> és további <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">A felkeresni kívánt szerver (<ph name="ORIGIN" />) egy adott biztonsági házirend
alkalmazását kérte az összes hozzá irányuló kérés esetében. De ahelyett, hogy
átadta volna a házirendet, átirányította máshova a böngészőt, megakadályozva,
hogy a böngésző teljesítse a(z) <ph name="SITE" /> webhelyre irányuló kérelmet.</translation>
-<translation id="7179323680825933600">Fizetési módok mentése és betöltése</translation>
+<translation id="7179323680825933600">Fizetési módok mentése és kitöltése</translation>
<translation id="7180611975245234373">Frissítés</translation>
<translation id="7182878459783632708">Nincsenek beállított házirendek</translation>
<translation id="7186367841673660872">Ezt az oldalt<ph name="ORIGINAL_LANGUAGE" />nyelvről fordítottuk<ph name="LANGUAGE_LANGUAGE" />nyelvre.</translation>
@@ -1164,6 +1182,7 @@ További részletek:
<translation id="7320336641823683070">Segítség a kapcsolódáshoz</translation>
<translation id="733354035281974745">Eszköz helyi fiókja általi felülbírálás</translation>
<translation id="7334320624316649418">&amp;Átrendezés újra</translation>
+<translation id="7337706099755338005">Nem áll rendelkezésre ezen a platformon.</translation>
<translation id="733923710415886693">A szerver tanúsítványát nem A tanúsítványok átláthatósága keretrendszeren keresztül hozták nyilvánosságra.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Társult felhasználó:</translation>
@@ -1195,7 +1214,6 @@ További részletek:
<translation id="7440140511386898319">Felfedezés offline állapotban</translation>
<translation id="7441627299479586546">Az irányelv tárgya nem megfelelő</translation>
<translation id="7442725080345379071">Világos narancssárga</translation>
-<translation id="7444046173054089907">Ez a webhely le van tiltva</translation>
<translation id="7445762425076701745">Nem sikerült teljesen ellenőrizni a szerver azonosságát, amelyhez kapcsolódik. Egy olyan névvel kapcsolódik a szerverhez, amelynek tulajdonjogát egy külső tanúsítványkibocsátó nem ellenőrizheti. Mivel egyes tanúsítványkibocsátók figyelmen kívül hagyják ezeket a neveket, így semmi nem biztosítja, hogy a kívánt webhelyhez kapcsolódik, és nem egy támadó webhelyhez.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />További információk megtekintése<ph name="END_LINK" /> a problémával kapcsolatban.</translation>
<translation id="7455133967321480974">Globális alapértelmezés használata (Tiltás)</translation>
@@ -1217,9 +1235,9 @@ További részletek:
<translation id="7538364083937897561">A2 (boríték)</translation>
<translation id="7542403920425041731">Az igazolást követően a böngésző megosztja kártyaadatait a webhellyel.</translation>
<translation id="7542995811387359312">Az automatikus bankkártya-kitöltés le van tiltva, mivel ez az űrlap nem biztonságos kapcsolatot használ.</translation>
-<translation id="7543525346216957623">Kérd a szülő segítségét</translation>
<translation id="7548892272833184391">A kapcsolódási hibák elhárítása</translation>
<translation id="7549584377607005141">Ez a weboldal korábban megadott adatokat kér ahhoz, hogy megfelelően jelenjen meg. Az adatokat újra elküldheti, de ezzel meg fog ismételni minden olyan műveletet, amelyet ez az oldal korábban végrehajtott.</translation>
+<translation id="7550637293666041147">Az Ön eszközhöz és Chrome-hoz tartozó felhasználóneve</translation>
<translation id="7552846755917812628">Próbálja ki az alábbi tippeket:</translation>
<translation id="7554791636758816595">Új lap</translation>
<translation id="7564049878696755256">Elveszítheti hozzáférést <ph name="ORG_NAME" />-fiókjához, vagy visszaélhetnek személyes adataival. A Chrome azt javasolja, hogy azonnal módosítsa jelszavát.</translation>
@@ -1234,6 +1252,7 @@ További részletek:
<translation id="7610193165460212391">Az érték kívül esik a következő tartományon: <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Lejárat: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Már rendelkezik olyan adattal, amely Google-fiókja jelszavának egy másik verziójával van titkosítva. Kérjük, lentebb adja azt meg.</translation>
+<translation id="7625784245512586808">Chrome Enterprise fenyegetések elleni védelme</translation>
<translation id="7633909222644580952">Teljesítményre vonatkozó adatok és hibajelentések</translation>
<translation id="7637571805876720304">Eltávolítja a hitelkártyát a Chromiumból?</translation>
<translation id="7638605456503525968">Soros portok</translation>
@@ -1246,7 +1265,6 @@ További részletek:
<translation id="7668654391829183341">Ismeretlen eszköz</translation>
<translation id="7669271284792375604">A webhelyen lévő támadók megpróbálhatják csellel rávenni Önt olyan programok telepítésére, amelyek károsak a böngészési élmény szempontjából (például módosítják a kezdőlapot, vagy plusz hirdetéseket jelenítenek meg a felkeresett webhelyeken).</translation>
<translation id="7676643023259824263">Vágólapon lévő szöveg keresése, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform és felhő</translation>
<translation id="7681101578153515023">Keresőmotor megváltoztatása</translation>
<translation id="7682287625158474539">Szállítási cím</translation>
<translation id="7687186412095877299">Kitölti a fizetési űrlapokat az Ön mentett fizetési módjaival</translation>
@@ -1261,7 +1279,6 @@ További részletek:
<translation id="7723047071702270851">Kártya szerkesztése</translation>
<translation id="774634243536837715">Veszélyes tartalom letiltva.</translation>
<translation id="7752995774971033316">Nem kezelt</translation>
-<translation id="7755287808199759310">A letiltást a szülő oldhatja fel</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Előfordulhat, hogy a tűzfal vagy a vírusirtó szoftver tiltotta le a kapcsolatot.</translation>
<translation id="7759163816903619567">Megjelenített domain:</translation>
@@ -1305,7 +1322,6 @@ További részletek:
<translation id="8004582292198964060">Böngésző</translation>
<translation id="8009225694047762179">Jelszó kezelése</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{A kártyát és a számlázási címet elmentjük. Az adatok kéznél lesznek, amíg <ph name="USER_EMAIL" /> e-mail-című fiókját használja.}other{A kártyákat és a számlázási címeket elmentjük. Az adatok kéznél lesznek, amíg <ph name="USER_EMAIL" /> e-mail-című fiókját használja.}}</translation>
-<translation id="8012647001091218357">Jelenleg nem tudjuk elérni szüleidet. Próbálkozz újra.</translation>
<translation id="8025119109950072390">A támadók ezen a webhelyen megpróbálhatják csellel rávenni Önt, hogy például telepítsen egy veszélyes szoftvert, vagy felfedje személyes adatait (jelszavát, telefonszámát, hitelkártyaszámát stb.).</translation>
<translation id="8034522405403831421">Ez az oldal <ph name="SOURCE_LANGUAGE" /> nyelven van. Lefordítja <ph name="TARGET_LANGUAGE" /> nyelvre?</translation>
<translation id="8035152190676905274">Toll</translation>
@@ -1316,6 +1332,7 @@ További részletek:
<translation id="8041940743680923270">Globális alapértelmezés használata (Megkérdezés)</translation>
<translation id="8042918947222776840">Átvételi mód kiválasztása</translation>
<translation id="8057711352706143257">A(z) „<ph name="SOFTWARE_NAME" />” nincs megfelelően beállítva. A(z) „<ph name="SOFTWARE_NAME" />” eltávolítása általában megoldja a problémát. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Mostantól nem kell megadnia a kártyájához tartozó biztonsági kódot</translation>
<translation id="8066955247577885446">Sajnos hiba történt.</translation>
<translation id="8074253406171541171">10x13 (boríték)</translation>
<translation id="8078141288243656252">Elforgatott állapotban nem lehetséges a jegyzetelés</translation>
@@ -1346,6 +1363,7 @@ További részletek:
<translation id="8211406090763984747">A kapcsolat biztonságos</translation>
<translation id="8218327578424803826">Hozzárendelt helyszín:</translation>
<translation id="8220146938470311105">C7/C6 (boríték)</translation>
+<translation id="8220639454292072926">Vállalati jelentéskészítés</translation>
<translation id="8225771182978767009">A számítógépet beállító személy a webhely letiltása mellett döntött.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> és <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Oldal megnyitása új inkognitóablakban</translation>
@@ -1400,24 +1418,24 @@ További részletek:
<translation id="8508648098325802031">Keresés ikon</translation>
<translation id="8522552481199248698">A Chrome segíthet a Google-fiók védelmében és a jelszó módosításában.</translation>
<translation id="8543181531796978784">Lehetősége van arra, hogy <ph name="BEGIN_ERROR_LINK" />jelentse az észlelési problémát<ph name="END_ERROR_LINK" />, ha pedig tisztában van a biztonságát fenyegető kockázatokkal, <ph name="BEGIN_LINK" />felkeresheti a nem biztonságos webhelyet<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Kérdése van? Vegye fel a kapcsolatot a fiókját felügyelő személlyel.</translation>
<translation id="8553075262323480129">A fordítás nem sikerült, mivel az oldal nyelvét nem lehet megállapítani.</translation>
<translation id="8557066899867184262">A CVC-kód a kártya hátulján található.</translation>
<translation id="8559762987265718583">Nem hozható létre privát kapcsolat a következővel: <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, mert az eszköz dátum- és időbeállítása helytelen (<ph name="DATE_AND_TIME" />).</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" />: gyanús webhely</translation>
<translation id="8564985650692024650">A Chromium azt javasolja, hogy adjon meg új <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />-jelszót a régi helyett, ha azt más webhelyeken is használta.</translation>
<translation id="8571890674111243710">Oldal fordítása erre a nyelvre: <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Szám hozzáadása
</translation>
-<translation id="859285277496340001">Ez a tanúsítvány nem határoz meg olyan mechanizmust, amely ellenőrizné, hogy visszavonták-e.</translation>
<translation id="860043288473659153">Kártyatulajdonos neve</translation>
<translation id="861775596732816396">Méret: 4</translation>
-<translation id="8620436878122366504">A szüleid még nem hagyták jóvá</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Kártya mentése az eszközre</translation>
<translation id="8626112503828625890">Szeretné tárolni a számlázási adatokat a Google-fiókjában?</translation>
+<translation id="8647750283161643317">Minden visszaállítása az alapértékre</translation>
<translation id="8663226718884576429">Rendelés-összefoglaló, <ph name="TOTAL_LABEL" />, További részletek</translation>
<translation id="8680536109547170164"><ph name="QUERY" />. A válasz: <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Rendelkezésre áll</translation>
<translation id="8703575177326907206">A kapcsolat (<ph name="DOMAIN" />) nem titkosított.</translation>
<translation id="8718314106902482036">A fizetés nem fejeződött be</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, keresési javaslat</translation>
@@ -1428,6 +1446,7 @@ További részletek:
<translation id="8738058698779197622">Biztonságos kapcsolat létrehozásához az órát pontosan be kell állítani. Ez azért szükséges, mert a webhelyek által az azonosításukra használt tanúsítványok csak adott ideig érvényesek. Mivel az eszköz órája nem pontos, a Chromium nem tudja ellenőrizni ezeket a tanúsítványokat.</translation>
<translation id="8740359287975076522">A(z) <ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS-címe&lt;/abbr&gt; nem található. A probléma diagnosztizálása folyamatban van.</translation>
<translation id="874846938927089722">Elfogadott hitel- és feltöltőkártyák</translation>
+<translation id="874918643257405732">Lap hozzáadása a könyvjelzőkhöz</translation>
<translation id="8759274551635299824">A kártya lejárt</translation>
<translation id="8761567432415473239">A Google Biztonságos Böngészés nemrég <ph name="BEGIN_LINK" />ártalmas programokat talált<ph name="END_LINK" /> a következő webhelyen: <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB-eszköz</translation>
@@ -1457,6 +1476,7 @@ További részletek:
<translation id="8938939909778640821">Elfogadott hitel- és feltöltőkártyák</translation>
<translation id="8943282376843390568">Limezöld</translation>
<translation id="8957210676456822347">Hitelesítés hitelesítési portállal</translation>
+<translation id="8962950042226115166">Gyanús webhely</translation>
<translation id="8968766641738584599">Kártya mentése</translation>
<translation id="8971063699422889582">A szerver tanúsítványa lejárt.</translation>
<translation id="8975012916872825179">Olyan adatokat tartalmaz, mint a telefonszámok, az e-mail-címek és a szállítási címek</translation>
@@ -1479,24 +1499,24 @@ További részletek:
<translation id="9035022520814077154">Biztonsági hiba</translation>
<translation id="9038649477754266430">A várható kifejezés szolgáltatás használata az oldalak gyorsabb betöltése érdekében</translation>
<translation id="9039213469156557790">Emellett az oldal más forrásokat is tartalmaz, amelyek nem biztonságosak. Ezeket a forrásokat mások is megtekinthetik átvitel közben, és megváltoztatásukkal a támadók módosíthatják az oldal viselkedését.</translation>
+<translation id="9044359186343685026">Touch ID használata</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Megpróbálta elérni a(z) <ph name="DOMAIN" /> webhelyet, de a szerver érvénytelen tanúsítványt mutatott be.</translation>
<translation id="9050666287014529139">Összetett jelszó</translation>
<translation id="9065203028668620118">Szerkesztés</translation>
<translation id="9065745800631924235"><ph name="TEXT" /> keresése az előzményekben</translation>
<translation id="9069693763241529744">Bővítmény tiltja</translation>
-<translation id="9076283476770535406">Lehet, hogy felnőtt tartalommal rendelkezik</translation>
<translation id="9076630408993835509">Ezt a böngészőt nem kezeli cég vagy más szervezet. Lehetséges, hogy az eszközön végzett tevékenységeket a Chrome-on kívülről felügyelik. <ph name="BEGIN_LINK" />További információ.<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Több információra van szükség</translation>
<translation id="9080712759204168376">Megrendelés összegzése</translation>
<translation id="9089260154716455634">Házirend figyelmen kívül hagyása:</translation>
<translation id="9095388113577226029">További nyelvek…</translation>
+<translation id="9098981495403789647">Az adminisztrátor engedélyezte a Chrome Enterprise fenyegetések elleni védelmét a böngészőben. A Chrome Enterprise fenyegetések elleni védelme hozzáfér az Ön bizonyos adataihoz.</translation>
<translation id="9103872766612412690">A(z) <ph name="SITE" /> webhely rendes esetben titkosítást alkalmaz az Ön adatainak védelme érdekében. Amikor a Chromium most csatlakozni próbált, a(z) <ph name="SITE" /> webhely szokatlan és helytelen hitelesítési adatokat küldött vissza.Ez olyankor fordulhat elő, amikor egy támadó megpróbálja magát kiadni a(z) <ph name="SITE" /> webhelynek, vagy valamilyen Wi-Fi-bejelentkezési képernyő megszakította a kapcsolatot. Adatai továbbra is biztonságban vannak, mivel a Chromium még azt megelőzően megszakította a kapcsolatot, hogy bármiféle adatcserére sor kerülhetett volna.</translation>
<translation id="9106062320799175032">Számlázási cím hozzáadása</translation>
<translation id="9114524666733003316">Kártya ellenőrzése…</translation>
<translation id="9128870381267983090">Csatlakozás hálózathoz</translation>
<translation id="9137013805542155359">Eredeti megjelenítése</translation>
-<translation id="9137248913990643158">Indítsa el a Chrome böngészőt és jelentkezzen be az alkalmazás használata előtt.</translation>
<translation id="9141013498910525015">Címek kezelése</translation>
<translation id="9148088599418889305">Szállítási mód kiválasztása</translation>
<translation id="9148507642005240123">&amp;Szerkesztés visszavonása</translation>
diff --git a/chromium/components/strings/components_strings_id.xtb b/chromium/components/strings/components_strings_id.xtb
index f77532e83c5..1b9843e0e2c 100644
--- a/chromium/components/strings/components_strings_id.xtb
+++ b/chromium/components/strings/components_strings_id.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Tambahkan Nama di Kartu</translation>
<translation id="1089439967362294234">Ubah Sandi</translation>
+<translation id="1096545575934602868">Kolom ini tidak boleh memiliki lebih dari <ph name="MAX_ITEMS_LIMIT" /> entri. Semua entri lanjutan akan dibuang.</translation>
<translation id="109743633954054152">Kelola sandi di setelan Chrome</translation>
<translation id="1103523840287552314">Selalu terjemahkan <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Apabila dicentang, Chrome akan menyimpan salinan kartu Anda pada perangkat ini untuk pengisian formulir yang lebih cepat.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Akses <ph name="BEGIN_LINK" />salinan yang disimpan dalam cache<ph name="END_LINK" /> dari <ph name="URL" /></translation>
<translation id="1156303062776767266">Anda melihat file lokal atau bersama</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> tiba-tiba menutup sambungan.</translation>
+<translation id="115926840831309955">Periksa CVC dan coba lagi atau perbarui tanggal habis masa berlaku</translation>
<translation id="1161325031994447685">Menyambungkan ulang ke Wi-Fi</translation>
<translation id="1165039591588034296">Kesalahan</translation>
<translation id="1175364870820465910">&amp;Cetak...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Software di komputer mencegah Chrome terhubung dengan aman ke web" (khusus komputer Windows)</translation>
<translation id="1294154142200295408">Variasi baris perintah</translation>
<translation id="129553762522093515">Baru saja ditutup</translation>
+<translation id="1298536327547837046">Pemindaian Malware</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Coba hapus cookie Anda<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Fitur yang Tidak Digunakan Lagi</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Telusuri gambar papan klip</translation>
<translation id="1323433172918577554">Tampilkan Lebih Banyak</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Spreadsheet</translation>
<translation id="1527263332363067270">Menunggu sambungan internet...</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">Situs yang baru saja Anda coba kunjungi terlihat palsu. Penyerang terkadang meniru situs dengan membuat perubahan kecil dan sulit terlihat pada URL situs.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Halaman ini menyatakan</translation>
<translation id="153384715582417236">Itu saja untuk sekarang</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokumen terlalu besar untuk dianotasi</translation>
-<translation id="1721312023322545264">Anda memerlukan izin dari <ph name="NAME" /> untuk mengunjungi situs ini</translation>
<translation id="1721424275792716183">* Kolom wajib diisi</translation>
<translation id="1727741090716970331">Tambahkan Nomor Kartu yang Valid</translation>
<translation id="1728677426644403582">Anda melihat sumber halaman web</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Situs yang Anda kunjungi dan waktu yang dihabiskan untuk mengunjunginya</translation>
<translation id="1826516787628120939">Memeriksa</translation>
<translation id="1834321415901700177">Situs ini berisi program yang berbahaya</translation>
+<translation id="1838374766361614909">Hapus penelusuran</translation>
<translation id="1839551713262164453">Validasi nilai kebijakan gagal karena terjadi error</translation>
<translation id="1842969606798536927">Bayar</translation>
<translation id="1871208020102129563">Proxy disetel untuk menggunakan server proxy tetap, bukan URL skrip .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Ciutkan daftar</translation>
<translation id="1898423065542865115">Pemfilteran</translation>
<translation id="1914326953223720820">Layanan Ekstraksi File</translation>
+<translation id="1915697529809968049">Gunakan Touch ID dan bukan CVC?</translation>
<translation id="1916770123977586577">Untuk menerapkan setelan yang telah diupdate pada situs ini, muat ulang halaman ini</translation>
<translation id="1919345977826869612">Iklan</translation>
<translation id="1919367280705858090">Mendapatkan bantuan terkait pesan error tertentu</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Bookmark <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Kesalahan serialisasi</translation>
<translation id="1974060860693918893">Lanjutan</translation>
+<translation id="1974883374937189061">Bantu sempurnakan keamanan Chrome dengan mengirimkan <ph name="BEGIN_WHITEPAPER_LINK" />URL beberapa halaman yang Anda kunjungi, informasi sistem terbatas, dan beberapa konten halaman <ph name="END_WHITEPAPER_LINK" /> ke Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versi Firmware</translation>
<translation id="1981206234434200693">Hapus data histori browsing Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{dan 1 lainnya}other{dan # lainnya}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Masukkan tahun habis masa berlaku yang valid</translation>
<translation id="2212735316055980242">Kebijakan tidak ditemukan</translation>
<translation id="2213606439339815911">Mengambil entri...</translation>
+<translation id="2215727959747642672">Pengeditan file</translation>
<translation id="2218879909401188352">Penyerang yang saat ini berada di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin berusaha menginstal aplikasi berbahaya yang dapat merusak perangkat, menambahkan biaya tersembunyi ke tagihan seluler, atau mencuri informasi pribadi Anda. <ph name="BEGIN_LEARN_MORE_LINK" />Pelajari lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Tidak ada internet</translation>
<translation id="2230458221926704099">Perbaiki sambungan menggunakan <ph name="BEGIN_LINK" />aplikasi diagnosis<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Kirim sekarang</translation>
+<translation id="2248949050832152960">Gunakan WebAuthn</translation>
<translation id="225207911366869382">Nilai ini sudah usang untuk kebijakan ini.</translation>
<translation id="2257315177824333709">Maaf, saat ini informasi kartu Anda tidak dapat disimpan</translation>
<translation id="2262243747453050782">Kesalahan HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL penelusuran tidak valid.</translation>
<translation id="2482878487686419369">Notifikasi</translation>
<translation id="248348093745724435">Kebijakan mesin</translation>
-<translation id="2485387744899240041">Nama pengguna untuk perangkat dan browser Anda</translation>
<translation id="2491120439723279231">Sertifikat server mengandung kesalahan.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Pengurai JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Kembali</translation>
<translation id="2503184589641749290">Kartu prabayar dan debit yang diterima</translation>
<translation id="2505268675989099013">Lindungi Akun</translation>
+<translation id="2515335152965840738">ABAIKAN</translation>
<translation id="2515629240566999685">Periksa sinyal di area Anda</translation>
<translation id="2523886232349826891">Hanya disimpan di perangkat ini</translation>
<translation id="2524461107774643265">Tambahkan Informasi Lainnya</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Kirim</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Tidak ada}=1{1 sandi (untuk <ph name="DOMAIN_LIST" />)}=2{2 sandi (untuk <ph name="DOMAIN_LIST" />)}other{# sandi (untuk <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Tutup tab atau aplikasi lain</translation>
-<translation id="267371737713284912">tekan <ph name="MODIFIER_KEY_DESCRIPTION" /> untuk mengurungkan</translation>
<translation id="2674170444375937751">Yakin ingin menghapus halaman ini dari histori?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Keluar</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Nilai tidak sesuai format.</translation>
<translation id="2705137772291741111">Salinan tersimpan (dalam cache) situs ini tidak dapat dibaca.</translation>
<translation id="2709516037105925701">Isi-Otomatis</translation>
-<translation id="2712173769900027643">Minta izin</translation>
<translation id="2713444072780614174">Putih</translation>
<translation id="2720342946869265578">Di Sekitar</translation>
<translation id="2721148159707890343">Permintaan berhasil</translation>
<translation id="2728127805433021124">Sertifikat server ditandai menggunakan algoritme yang lemah.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Jalankan Diagnostik Konektivitas<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Jika mengaktifkan fitur ini, Anda dapat kehilangan data browser atau
+ membahayakan keamanan atau privasi Anda. Fitur yang diaktifkan berlaku bagi semua
+ pengguna browser ini.</translation>
<translation id="2735043616039983645">Ada beberapa sumber dengan nilai yang bertentangan untuk kebijakan ini!</translation>
<translation id="2738330467931008676">Pilih Alamat Pengambilan</translation>
<translation id="2740531572673183784">Oke</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Sambungan disetel ulang.</translation>
<translation id="2788784517760473862">Kartu kredit yang diterima</translation>
<translation id="2792012897584536778">Administrator perangkat ini telah menetapkan sertifikat keamanan yang memungkinkan mereka melihat konten situs yang Anda kunjungi.</translation>
-<translation id="2794233252405721443">Situs diblokir</translation>
<translation id="2799020568854403057">Situs yang akan dibuka berisi aplikasi berbahaya</translation>
<translation id="2799223571221894425">Luncurkan Ulang</translation>
<translation id="2803306138276472711">Google Safe Browsing baru saja <ph name="BEGIN_LINK" />mendeteksi software perusak<ph name="END_LINK" /> di <ph name="SITE" />. Situs web yang umumnya aman terkadang terinfeksi software perusak.</translation>
+<translation id="2815364696811431560">KELUAR DARI SITUS</translation>
<translation id="2824775600643448204">Bilah penelusuran dan alamat</translation>
<translation id="2826760142808435982">Sambungan dienkripsi dan diautentikasi menggunakan <ph name="CIPHER" /> dan menggunakan <ph name="KX" /> sebagai mekanisme pertukaran kunci.</translation>
<translation id="2835170189407361413">Hapus formulir</translation>
<translation id="2847118875340931228">Buka Jendela Samaran</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Anda memerlukan izin untuk membuka situs ini</translation>
<translation id="2856444702002559011">Penyerang mungkin berusaha mencuri informasi Anda dari <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (misalnya, sandi, pesan, atau kartu kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Pelajari lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Simpan kartu?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Jika diaktifkan, Chromium akan menyimpan salinan kartu Anda di perangkat ini untuk pengisian formulir yang lebih cepat.</translation>
<translation id="2985398929374701810">Masukkan alamat yang valid</translation>
<translation id="2986368408720340940">Metode pengambilan tidak tersedia. Coba metode lain.</translation>
+<translation id="2987034854559945715">Tidak ada fitur yang cocok</translation>
<translation id="2991174974383378012">Berbagi dengan Situs Web</translation>
<translation id="2991571918955627853">Anda tidak dapat mengunjungi <ph name="SITE" /> sekarang karena situs menggunakan HSTS. Error jaringan dan serangan biasanya bersifat sementara, sehingga halaman ini mungkin akan berfungsi nanti.</translation>
<translation id="3005723025932146533">Tampilkan salinan yang disimpan</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Jenis kebijakan salah</translation>
<translation id="3037605927509011580">Yah!</translation>
<translation id="3041612393474885105">Informasi Sertifikat</translation>
+<translation id="3057676462092457419"><ph name="SECURE_DNS_MODE_SECURE" /> mode DnsOverHttps belum didukung, mode tersebut telah ditetapkan ke <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Layanan Patch</translation>
<translation id="3064966200440839136">Keluar dari mode samaran untuk membayar melalui aplikasi eksternal. Lanjutkan?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> di <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Batalkan Pembayaran</translation>
<translation id="3207960819495026254">Diberi bookmark</translation>
+<translation id="3209034400446768650">Halaman mungkin dikenakan biaya</translation>
<translation id="3225919329040284222">Server menunjukkan sertifikat yang tidak sesuai dengan harapan terpasang. Harapan ini disertakan untuk situs web tertentu dengan keamanan tinggi guna melindungi Anda.</translation>
<translation id="3226128629678568754">Tekan tombol muat ulang untuk mengirimkan lagi data yang dibutuhkan untuk memuat halaman ini.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Informasi versi tentang perangkat dan browser Anda</translation>
<translation id="323107829343500871">Masukkan CVC untuk <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Selalu deteksi konten penting di situs ini</translation>
-<translation id="3254409185687681395">Bookmark halaman ini</translation>
<translation id="3270847123878663523">&amp;Urungkan Pengaturan Ulang</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Tambahkan nama di kartu</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Tambahkan alamat penagihan</translation>
<translation id="3324983252691184275">Merah Lembayung</translation>
<translation id="3338095232262050444">Aman</translation>
-<translation id="3345135638360864351">Permintaan Anda untuk mengakses situs ini tidak dapat dikirimkan ke <ph name="NAME" />. Coba lagi.</translation>
<translation id="3355823806454867987">Ubah setelan proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />tidak akan menyimpan<ph name="END_EMPHASIS" /> informasi berikut:
<ph name="BEGIN_LIST" />
@@ -478,17 +488,14 @@
<translation id="3462200631372590220">Sembunyikan lanjutan</translation>
<translation id="3467763166455606212">Diperlukan nama pemegang kartu</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, sedang terbuka, tekan Tab lalu Enter untuk beralih ke tab yang terbuka</translation>
-<translation id="3479539252931486093">Apakah hal ini tidak diharapkan? <ph name="BEGIN_LINK" />Beri tahu kami<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Jangan sekarang</translation>
<translation id="3484560055331845446">Anda dapat kehilangan akses ke Akun Google Anda. Chrome merekomendasikan untuk mengubah sandi Anda sekarang. Anda akan diminta untuk login.</translation>
<translation id="3495081129428749620">Cari pada halaman <ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Orang tua Anda saat ini tidak dapat dihubungi. Coba lagi.</translation>
<translation id="3512163584740124171">Kebijakan ini diabaikan karena kebijakan lain dari grup kebijakan yang sama memiliki prioritas lebih tinggi.</translation>
<translation id="3528171143076753409">Sertifikat server tidak dipercaya.</translation>
<translation id="3528485271872257980">Cokelat Tua</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Minimal 1 item pada perangkat yang disinkronkan}=1{1 item (dan beberapa di perangkat yang disinkronkan)}other{# item (dan beberapa di perangkat yang disinkronkan)}}</translation>
<translation id="3539171420378717834">Menyimpan salinan kartu ini di perangkat ini</translation>
-<translation id="3556433843310711081">Pengelola dapat membuka blokirnya untuk Anda</translation>
<translation id="3566021033012934673">Koneksi Anda tidak pribadi</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Halaman tersemat di <ph name="SITE" /> menyatakan</translation>
@@ -516,6 +523,7 @@
<translation id="3678529606614285348">Buka halaman dalam Jendela samaran baru (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Laporan kerusakan direkam pada <ph name="CRASH_TIME" />, diupload pada <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informasi sertifikat</translation>
+<translation id="3701427423622901115">Setel ulang dikonfirmasi.</translation>
<translation id="3704162925118123524">Jaringan yang digunakan mungkin mewajibkan Anda mengunjungi halaman masuk jaringan.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Memuat...</translation>
@@ -532,6 +540,7 @@
<translation id="3748148204939282805">Penyerang di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> dapat mengelabui Anda agar melakukan tindakan yang berbahaya seperti menginstal software atau mengungkap informasi pribadi Anda (misalnya sandi, nomor telepon, atau kartu kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Pelajari lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Terjemahan gagal karena kesalahan server.</translation>
<translation id="3759461132968374835">Tidak ada laporan kondisi ngadat saat ini. Kondisi ngadat yang terjadi saat pelaporan kondisi ngadat tidak diaktifkan tidak akan tampil di sini.</translation>
+<translation id="3760561303380396507">Gunakan Windows Hello dan bukan CVC?</translation>
<translation id="3761718714832595332">Sembunyikan status</translation>
<translation id="3765032636089507299">Halaman Safe Browsing sedang diperbaiki.</translation>
<translation id="3778403066972421603">Ingin menyimpan kartu ini di Akun Google dan perangkat ini?</translation>
@@ -541,6 +550,7 @@
<translation id="3789155188480882154">Ukuran 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Konten yang berbahaya diblokir.</translation>
+<translation id="3808375843007691220">Peringatan: Anda akan mengakses fitur eksperimental!</translation>
<translation id="3810973564298564668">Kelola</translation>
<translation id="382518646247711829">Jika Anda menggunakan server proxy...</translation>
<translation id="3828924085048779000">Frasa sandi kosong tidak dibolehkan.</translation>
@@ -549,11 +559,11 @@
<translation id="3858027520442213535">Perbarui tanggal dan waktu</translation>
<translation id="3884278016824448484">Pengenal perangkat bertentangan</translation>
<translation id="3885155851504623709">Paroki</translation>
-<translation id="3886446263141354045">Permintaan Anda untuk mengakses situs ini telah dikirim ke <ph name="NAME" /></translation>
<translation id="3890664840433101773">Tambahkan email</translation>
<translation id="3901925938762663762">Kartu telah habis masa berlakunya</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Gunakan WebAuthn dan bukan CVC?</translation>
<translation id="3946209740501886391">Selalu tanyakan pada situs ini</translation>
<translation id="3949571496842715403">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya tidak menyebutkan Nama Alternatif Subjek. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
<translation id="3949601375789751990">Histori browsing Anda muncul di sini</translation>
@@ -564,11 +574,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Tidak ada}=1{Dari 1 situs }other{Dari # situs }}</translation>
<translation id="397105322502079400">Menghitung...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> diblokir.</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> telah mengaktifkan Perlindungan Ancaman Chrome Enterprise di browser Anda. Perlindungan Ancaman Chrome Enterprise memiliki akses ke beberapa data Anda.</translation>
<translation id="3987940399970879459">Kurang dari 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 halaman web di sekitar}other{# halaman web di sekitar}}</translation>
<translation id="4030383055268325496">&amp;Urungkan penambahan</translation>
<translation id="4032320456957708163">Browser Anda dikelola oleh <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Link yang Anda buka menuju ke situs yang tidak biasanya Anda kunjungi. Situs tersebut mungkin mencoba membingungkan Anda.</translation>
<translation id="4058922952496707368">Kunci "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Tambahkan Alamat yang Valid</translation>
@@ -581,6 +591,7 @@
<translation id="4103249731201008433">Nomor seri perangkat tidak valid</translation>
<translation id="410351446219883937">Putar otomatis</translation>
<translation id="4103763322291513355">Kunjungi &lt;strong&gt;chrome://policy&lt;/strong&gt; untuk melihat daftar URL yang masuk daftar hitam dan kebijakan lain yang diterapkan oleh administrator sistem Anda.</translation>
+<translation id="4108231218301530806">Gunakan sidik jari untuk memverifikasi kartu ini lain kali.</translation>
<translation id="4110652170750985508">Tinjau pembayaran</translation>
<translation id="4112140312785995938">Cari Mundur</translation>
<translation id="4116663294526079822">Selalu izinkan di situs ini</translation>
@@ -595,6 +606,7 @@
<translation id="4171400957073367226">Tanda tangan verifikasi tidak valid</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> item lainnya}other{<ph name="ITEM_COUNT" /> item lainnya}}</translation>
+<translation id="4176463684765177261">Dinonaktifkan</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Agar selanjutnya dapat melakukan pembayaran lebih cepat, tambahkan kartu dan alamat penagihan ke Akun Google Anda dan perangkat ini.</translation>
<translation id="4196861286325780578">&amp;Ulangi pemindahan</translation>
@@ -631,6 +643,7 @@
<translation id="4277028893293644418">Setel ulang sandi</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> Anda dikelola oleh <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Kartu ini telah disimpan di Akun Google Anda}other{Kartu-kartu ini telah disimpan di Akun Google Anda}}</translation>
+<translation id="428847186335018806">Pindai file yang Anda download atau upload di Chrome.</translation>
<translation id="42981349822642051">Luaskan</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Alihkan</translation>
@@ -660,7 +673,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Penggunaan proxy dinonaktifkan tetapi konfigurasi proxy yang eksplisit ditentukan.</translation>
<translation id="445100540951337728">Kartu kredit yang diterima</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> perilaku yang mencurigakan</translation>
<translation id="4466881336512663640">Perubahan pada formulir akan hilang. Yakin ingin melanjutkan?</translation>
<translation id="4477350412780666475">Lagu Berikutnya</translation>
<translation id="4482953324121162758">Situs ini tidak akan diterjemahkan.</translation>
@@ -687,6 +699,7 @@
<translation id="4594403342090139922">&amp;Urungkan Penghapusan</translation>
<translation id="4597348597567598915">Ukuran 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Fitur penelusuran</translation>
<translation id="4646534391647090355">Buka Download sekarang</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya berisi kesalahan. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
@@ -695,7 +708,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Sambungan Anda terganggu</translation>
-<translation id="471880041731876836">Anda tidak memiliki izin untuk membuka situs ini</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Jalankan Diagnostik Jaringan Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Muat ulang kebijakan</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -723,7 +735,6 @@
<translation id="4816492930507672669">Paskan dengan halaman</translation>
<translation id="4850886885716139402">Lihat</translation>
<translation id="4854362297993841467">Metode pengiriman tidak tersedia. Coba metode lain.</translation>
-<translation id="4858792381671956233">Kamu telah meminta izin kepada orang tua untuk mengunjungi situs ini</translation>
<translation id="4864052566555297930">Tips perlindungan:</translation>
<translation id="4876188919622883022">Tampilan sederhana</translation>
<translation id="4876305945144899064">Tidak ada nama pengguna</translation>
@@ -747,7 +758,9 @@
<translation id="4974590756084640048">Aktifkan kembali peringatan</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Lihat semua</translation>
+<translation id="4989542687859782284">Tidak Tersedia</translation>
<translation id="4989809363548539747">Plugin ini tidak didukung</translation>
+<translation id="4995216769782533993">Konfirmasi kode keamanan untuk berbagi detail kartu dengan situs ini</translation>
<translation id="5002932099480077015">Jika diaktifkan, Chrome akan menyimpan salinan kartu Anda di perangkat ini untuk pengisian formulir yang lebih cepat.</translation>
<translation id="5015510746216210676">Nama Mesin:</translation>
<translation id="5017554619425969104">Teks yang Anda salin</translation>
@@ -776,6 +789,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verifikasi kartu</translation>
<translation id="5135404736266831032">Kelola alamat...</translation>
<translation id="5138227688689900538">Tampilkan lebih sedikit</translation>
<translation id="5141240743006678641">Enkripsikan sandi yang disinkronkan dengan kredensial Google Anda</translation>
@@ -802,6 +816,7 @@
<translation id="5251803541071282808">Awan</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Fitur yang berlaku di seluruh sistem hanya dapat disetel oleh pemilik: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Peringatan: Kebijakan ini tidak digabung sebagaimana yang ditetapkan dalam kebijakan PolicyDictionaryMultipleSourceMergeList karena bukan merupakan bagian dari kebijakan kamus yang dapat digabung.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Berakhir</translation>
@@ -825,7 +840,6 @@
<translation id="536296301121032821">Gagal menyimpan setelan kebijakan</translation>
<translation id="5371425731340848620">Perbarui kartu</translation>
<translation id="5377026284221673050">"Jam Anda terlalu lambat" atau "Jam Anda terlalu cepat" atau "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Halaman ini mungkin mencoba mengelabui Anda, mencuri informasi pribadi, atau membahayakan perangkat Anda. Berhati-hatilah saat memasukkan informasi pribadi atau membuka file yang didownload.</translation>
<translation id="5384855140246857529">Untuk menggunakan kartu di semua perangkat, harap login dan aktifkan sinkronisasi.</translation>
<translation id="5386426401304769735">Rantai sertifikat untuk situs ini berisi sertifikat yang ditandatangani menggunakan SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -839,6 +853,8 @@
<translation id="5457113250005438886">Tidak valid</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> lainnya}other{<ph name="CONTACT_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> lainnya}}</translation>
<translation id="5470861586879999274">&amp;Ulangi pengeditan</translation>
+<translation id="5473728911100096288">Dengan mengaktifkan fitur ini, Anda akan menggunakan fitur yang tidak digunakan lagi
+ yang tidak tersedia dalam versi mendatang.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Konten ini mungkin mencoba menginstal software berbahaya yang mencuri atau menghapus informasi Anda di perangkat. <ph name="BEGIN_LINK" />Tetap tampilkan<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Tambahkan alamat yang valid</translation>
@@ -862,7 +878,6 @@
<translation id="5570825185877910964">Lindungi akun</translation>
<translation id="5571083550517324815">Tidak dapat mengambil dari alamat ini. Pilih alamat lain.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 terpakai}other{# terpakai}})</translation>
-<translation id="5572851009514199876">Mulai dan login ke Chrome agar Chrome dapat memeriksa apakah Anda diizinkan untuk mengakses situs ini atau tidak.</translation>
<translation id="5580958916614886209">Periksa bulan kedaluwarsa dan coba lagi</translation>
<translation id="5586446728396275693">Tidak ada alamat yang disimpan</translation>
<translation id="5595485650161345191">Edit alamat</translation>
@@ -870,6 +885,7 @@
<translation id="560412284261940334">Pengelolaan tidak didukung</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Situs ini mungkin palsu atau penipuan. Chrome merekomendasikan untuk keluar dari situs sekarang.</translation>
<translation id="5610142619324316209">Periksa sambungan</translation>
<translation id="5610807607761827392">Anda dapat mengelola kartu dan alamat di <ph name="BEGIN_LINK" />Setelan<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> terlalu sering mengalihkan Anda.</translation>
@@ -893,11 +909,11 @@
<translation id="5720705177508910913">Pengguna saat ini</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome menyarankan untuk menyetel ulang sandi jika Anda juga menggunakannya di situs lain.</translation>
-<translation id="5732392974455271431">Orang tua dapat membuka blokirnya untukmu</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Simpan kartu di Akun Google Anda}other{Simpan kartu di Akun Google Anda}}</translation>
<translation id="5763042198335101085">Masukkan alamat email yang valid</translation>
<translation id="5765072501007116331">Untuk melihat persyaratan dan metode pengiriman, pilih alamat</translation>
<translation id="5778550464785688721">Kontrol penuh perangkat MIDI</translation>
+<translation id="5781136890105823427">Eksperimen diaktifkan</translation>
<translation id="578305955206182703">Oranye kekuningan</translation>
<translation id="57838592816432529">Bisukan</translation>
<translation id="5784606427469807560">Terjadi masalah saat mengonfirmasi kartu. Periksa sambungan internet Anda dan coba lagi.</translation>
@@ -914,13 +930,16 @@
<translation id="5860033963881614850">Nonaktif</translation>
<translation id="5863847714970149516">Halaman berikutnya mungkin mencoba menagih Anda.</translation>
<translation id="5866257070973731571">Tambahkan Nomor Telepon</translation>
+<translation id="5866898949289125849">Anda sedang menampilkan halaman developer tools</translation>
<translation id="5869405914158311789">Situs ini tidak dapat dijangkau</translation>
<translation id="5869522115854928033">Sandi tersimpan</translation>
<translation id="5887400589839399685">Kartu disimpan</translation>
<translation id="5893752035575986141">Kartu kredit diterima.</translation>
+<translation id="5895138241574237353">Mulai Ulang</translation>
<translation id="5901630391730855834">Kuning</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (disinkronkan)</translation>
<translation id="5916664084637901428">Aktif</translation>
+<translation id="59174027418879706">Diaktifkan</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Simpan kartu ke Akun Google?</translation>
<translation id="5922853866070715753">Hampir selesai</translation>
@@ -954,6 +973,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Gunakan kartu Anda di semua perangkat?</translation>
<translation id="6059925163896151826">Perangkat USB</translation>
+<translation id="6060009363608157444">Mode DnsOverHttps tidak valid.</translation>
<translation id="6080696365213338172">Anda telah mengakses konten menggunakan sertifikat yang diberikan oleh administrator. Data yang diberikan ke <ph name="DOMAIN" /> dapat dicegat oleh administrator Anda.</translation>
<translation id="6094273045989040137">Anotasi</translation>
<translation id="610911394827799129">Akun Google Anda mungkin memiliki bentuk histori penjelajahan lainnya di <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1002,13 +1022,12 @@
<translation id="6404511346730675251">Edit bookmark</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Masukkan tanggal kedaluwarsa dan CVC <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Kamu telah meminta izin kepada orang tua untuk mengunjungi situs ini</translation>
<translation id="6415778972515849510">Chromium dapat membantu Anda melindungi Akun Google dan mengubah sandi Anda.</translation>
-<translation id="6417515091412812850">Tidak dapat memeriksa apakah sertifikat telah ditarik.</translation>
<translation id="6431585503458005759">Jangan simpan</translation>
<translation id="6433490469411711332">Edit info kontak</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> menolak untuk tersambung.</translation>
<translation id="6434309073475700221">Tutup</translation>
+<translation id="6435221585574090192">Bagikan data tentang peristiwa keamanan yang telah ditandai oleh Perlindungan Ancaman Chrome Enterprise kepada Administrator Anda. Ini mungkin termasuk URL halaman, nama file dan metadata file, nama pengguna perangkat, dan nama pengguna Chrome Anda.</translation>
<translation id="6440503408713884761">Diabaikan</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Tambahkan informasi lainnya</translation>
@@ -1017,20 +1036,19 @@
<translation id="6465306955648956876">Kelola sandi...</translation>
<translation id="647261751007945333">Kebijakan perangkat</translation>
<translation id="6476284679642588870">Kelola metode pembayaran</translation>
-<translation id="6477321094435799029">Chrome mendeteksi kode yang tidak biasa pada halaman ini dan memblokirnya untuk melindungi informasi pribadi Anda (misalnya, sandi, nomor telepon, dan kartu kredit).</translation>
<translation id="6489534406876378309">Mulai mengupload kerusakan</translation>
<translation id="6499038740797743453">Setel ulang sandi?</translation>
<translation id="6507833130742554667">Kartu kredit dan debit diterima.</translation>
<translation id="650855688985305916">Ya, simpan</translation>
<translation id="6508722015517270189">Buka Ulang Chrome</translation>
<translation id="6517596291481585650">Peringatan: Kebijakan ini tidak digabung sebagai daftar sebagaimana yang ditetapkan oleh kebijakan karena bukan merupakan daftar.</translation>
+<translation id="6518133107902771759">Verifikasi</translation>
<translation id="6521745193039995384">Tidak aktif</translation>
<translation id="6529602333819889595">&amp;Ulangi Penghapusan</translation>
<translation id="6534179046333460208">Saran Web Fisik</translation>
<translation id="6545864417968258051">Pemindaian Bluetooth</translation>
<translation id="6554795675067793129">Akun Anda dikelola oleh <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Urungkan</translation>
-<translation id="6563469144985748109">Pengelola Anda belum menyetujuinya</translation>
<translation id="6569060085658103619">Anda melihat halaman ekstensi</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Merah Muda Terang</translation>
@@ -1048,11 +1066,13 @@
<translation id="6643016212128521049">Hapus</translation>
<translation id="6644283850729428850">Kebijakan ini telah usang.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Tidak ada}=1{Dari 1 situs (Anda tidak akan logout dari Akun Google)}other{Dari # situs (Anda tidak akan logout dari Akun Google)}}</translation>
+<translation id="6652101503459149953">Gunakan Windows Hello</translation>
<translation id="6657585470893396449">Sandi</translation>
<translation id="6670613747977017428">Kembali agar aman.</translation>
<translation id="6671697161687535275">Hapus saran formulir dari Chromium?</translation>
<translation id="6685834062052613830">Keluar dan selesaikan penyiapan</translation>
<translation id="6689271823431384964">Chrome menawarkan untuk menyimpan informasi kartu ke Akun Google Anda karena Anda sedang login. Anda dapat mengubah perilaku ini di setelan. Nama pemegang kartu berasal dari akun Anda.</translation>
+<translation id="6707256370811247129">Pindai konten cache dan file yang Anda download atau upload di Chrome.</translation>
<translation id="6710213216561001401">Sebelumnya</translation>
<translation id="6710594484020273272">&lt;Ketik istilah penelusuran&gt;</translation>
<translation id="671076103358959139">Token Pendaftaran:</translation>
@@ -1060,10 +1080,10 @@
<translation id="6738516213925468394">Data Anda dienkripsi dengan <ph name="BEGIN_LINK" />frasa sandi sinkronisasi<ph name="END_LINK" /> pada tanggal <ph name="TIME" />. Masukkan frasa sandi untuk memulai sinkronisasi.</translation>
<translation id="674375294223700098">Kesalahan sertifikat server tidak dikenal.</translation>
<translation id="6744009308914054259">Sambil menunggu koneksi, Anda dapat mengunjungi Hasil Download untuk membaca artikel secara offline.</translation>
+<translation id="6747611005629681221">Peringatan: Anda akan mengakses fitur yang tidak digunakan lagi!</translation>
<translation id="6753269504797312559">Nilai kebijakan</translation>
<translation id="6757797048963528358">Perangkat Anda sedang dalam mode tidur.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Orang tuamu belum menyetujuinya</translation>
<translation id="67862343314499040">Violet</translation>
<translation id="6786747875388722282">Ekstensi</translation>
<translation id="6790428901817661496">Putar</translation>
@@ -1071,6 +1091,7 @@
<translation id="681021252041861472">Kolom Wajib Diisi</translation>
<translation id="6810899417690483278">ID Penyesuaian</translation>
<translation id="6825578344716086703">Anda berusaha menjangkau <ph name="DOMAIN" />, tetapi server menyajikan sertifikat yang ditandatangani menggunakan algoritme tanda tangan yang lemah (seperti SHA-1). Hal ini berarti kredensial keamanan yang disajikan server mungkin telah dipalsukan, dan server tersebut mungkin bukan yang diharapkan (Anda mungkin sedang berkomunikasi dengan penyerang).</translation>
+<translation id="6826370046007623921">Pencegahan Kebocoran Data</translation>
<translation id="6831043979455480757">Terjemahkan</translation>
<translation id="6839929833149231406">Wilayah</translation>
<translation id="6852204201400771460">Muat ulang aplikasi?</translation>
@@ -1083,7 +1104,6 @@
<translation id="6891596781022320156">Tingkat kebijakan tidak didukung.</translation>
<translation id="6895330447102777224">Kartu telah dikonfirmasi</translation>
<translation id="6897140037006041989">Agen Pengguna</translation>
-<translation id="6903319715792422884">Bantu sempurnakan Safe Browsing dengan mengirimkan sebagian <ph name="BEGIN_WHITEPAPER_LINK" />informasi sistem dan konten halaman<ph name="END_WHITEPAPER_LINK" /> ke Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Pengguna:</translation>
<translation id="6934672428414710184">Nama ini dari Akun Google Anda</translation>
<translation id="6944692733090228304">Anda memasukkan sandi di situs yang tidak dikelola oleh <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Untuk melindungi akun, jangan gunakan sandi yang sama di aplikasi dan situs lain.</translation>
@@ -1128,6 +1148,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> lainnya}other{<ph name="PAYMENT_METHOD_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> lainnya}}</translation>
<translation id="7153618581592392745">Lembayung Muda</translation>
<translation id="717330890047184534">ID GAIA:</translation>
+<translation id="7174545416324379297">Digabung</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> lainnya}other{<ph name="SHIPPING_OPTION_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> lainnya}}</translation>
<translation id="7177397715882417099">Server yang akan Anda akses, <ph name="ORIGIN" />, telah meminta
agar kebijakan keamanan diterapkan ke semua permintaannya. Namun bukannya
@@ -1163,6 +1184,7 @@
<translation id="7320336641823683070">Bantuan Koneksi</translation>
<translation id="733354035281974745">Penggantian akun lokal perangkat</translation>
<translation id="7334320624316649418">&amp;Ulangi pengaturan ulang</translation>
+<translation id="7337706099755338005">Tidak tersedia di platform Anda.</translation>
<translation id="733923710415886693">Sertifikat server tidak diungkapkan melalui Transparansi Sertifikat.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Berafiliasi:</translation>
@@ -1194,7 +1216,6 @@
<translation id="7440140511386898319">Jelajahi saat offline</translation>
<translation id="7441627299479586546">Subjek kebijakan salah</translation>
<translation id="7442725080345379071">Oranye Muda</translation>
-<translation id="7444046173054089907">Situs ini diblokir</translation>
<translation id="7445762425076701745">Identitas server yang Anda sambungkan tidak dapat divalidasi sepenuhnya. Anda terhubung ke server menggunakan nama yang hanya valid dalam jaringan Anda, yang mana otoritas sertifikat eksternal sama sekali tidak dapat memvalidasi kepemilikannya. Karena sejumlah otoritas sertifikat akan tetap menerbitkan sertifikat untuk nama tersebut, tidak dapat dipastikan apakah Anda akan tersambung ke situs web yang dimaksudkan dan bahwa tidak akan ada penyerang.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Pelajari lebih lanjut<ph name="END_LINK" /> tentang masalah ini.</translation>
<translation id="7455133967321480974">Gunakan default global (Cekal)</translation>
@@ -1216,9 +1237,9 @@
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Setelah mengonfirmasi, detail kartu Anda akan dibagikan dengan situs ini.</translation>
<translation id="7542995811387359312">Pengisian kartu kredit otomatis dinonaktifkan karena formulir ini tidak menggunakan sambungan aman.</translation>
-<translation id="7543525346216957623">Tanyakan kepada orang tua</translation>
<translation id="7548892272833184391">Memperbaiki error koneksi</translation>
<translation id="7549584377607005141">Halaman web ini membutuhkan data yang Anda masukkan sebelumnya agar dapat ditampilkan dengan benar. Anda dapat mengirimkan data ini lagi, namun dengan begitu Anda akan mengulangi tindakan apa pun yang sebelumnya dilakukan oleh halaman ini.</translation>
+<translation id="7550637293666041147">Nama pengguna perangkat dan nama pengguna Chrome Anda</translation>
<translation id="7552846755917812628">Coba tips berikut:</translation>
<translation id="7554791636758816595">Tab Baru</translation>
<translation id="7564049878696755256">Anda dapat kehilangan akses ke akun <ph name="ORG_NAME" /> atau mengalami pencurian identitas. Chrome menyarankan Anda untuk mengubah sandi sekarang.</translation>
@@ -1233,6 +1254,7 @@
<translation id="7610193165460212391">Nilai di luar jangkauan <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Masa berlaku habis: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Anda sudah memiliki data yang dienkripsi menggunakan versi sandi Akun Google yang berbeda. Masukkan sandi di bawah.</translation>
+<translation id="7625784245512586808">Perlindungan Ancaman Chrome Enterprise</translation>
<translation id="7633909222644580952">Data performa dan laporan kerusakan</translation>
<translation id="7637571805876720304">Hapus kartu kredit dari Chromium?</translation>
<translation id="7638605456503525968">Port serial</translation>
@@ -1245,7 +1267,6 @@
<translation id="7668654391829183341">Perangkat tidak dikenal</translation>
<translation id="7669271284792375604">Penyerang di situs ini mungkin berusaha mengelabui Anda agar memasang program yang dapat membahayakan pengalaman menjelajah Anda (misalnya dengan mengubah beranda Anda atau menayangkan iklan ekstra pada situs yang dikunjungi).</translation>
<translation id="7676643023259824263">Telusuri teks papan klip, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform dan Cloud</translation>
<translation id="7681101578153515023">Ubah Mesin Telusur</translation>
<translation id="7682287625158474539">Pengiriman</translation>
<translation id="7687186412095877299">Mengisi formulir pembayaran dengan metode pembayaran yang Anda simpan</translation>
@@ -1260,7 +1281,6 @@
<translation id="7723047071702270851">Edit Kartu</translation>
<translation id="774634243536837715">Konten berbahaya diblokir.</translation>
<translation id="7752995774971033316">Tidak terkelola</translation>
-<translation id="7755287808199759310">Orang tua dapat membuka blokirnya untukmu</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Software antivirus atau firewall mungkin memblokir sambungan.</translation>
<translation id="7759163816903619567">Tampilkan domain:</translation>
@@ -1304,7 +1324,6 @@
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Kelola Kata sandi</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Kartu ini dan alamat penagihannya akan disimpan. Anda dapat menggunakannya saat login ke <ph name="USER_EMAIL" />.}other{Semua kartu ini dan alamat penagihannya akan disimpan. Anda dapat menggunakannya saat login ke <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Orang tua Anda saat ini tidak dapat dihubungi. Coba lagi.</translation>
<translation id="8025119109950072390">Penyerang di situs ini dapat mengelabui Anda agar melakukan hal yang berbahaya seperti memasang software atau mengungkap informasi pribadi Anda (misalnya sandi, nomor telepon, atau kartu kredit).</translation>
<translation id="8034522405403831421">Halaman ini berbahasa <ph name="SOURCE_LANGUAGE" />. Terjemahkan ke <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pena</translation>
@@ -1315,6 +1334,7 @@
<translation id="8041940743680923270">Gunakan default global (Tanyakan)</translation>
<translation id="8042918947222776840">Pilih Metode Pengambilan</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" tidak dikonfigurasi dengan benar. Biasanya masalah akan terselesaikan dengan meng-uninstal "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Mulai sekarang Anda tidak perlu memasukkan kode keamanan kartu</translation>
<translation id="8066955247577885446">Maaf, terjadi error.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Tidak dapat menambahkan anotasi saat diputar</translation>
@@ -1345,6 +1365,7 @@
<translation id="8211406090763984747">Koneksi aman</translation>
<translation id="8218327578424803826">Lokasi yang Ditetapkan:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Pelaporan Perusahaan</translation>
<translation id="8225771182978767009">Orang yang menyiapkan komputer ini telah memilih untuk memblokir situs ini.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Buka halaman dalam tab Samaran baru</translation>
@@ -1397,23 +1418,23 @@
<translation id="8508648098325802031">Ikon penelusuran</translation>
<translation id="8522552481199248698">Chrome dapat membantu Anda melindungi Akun Google dan mengubah sandi Anda.</translation>
<translation id="8543181531796978784">Anda dapat <ph name="BEGIN_ERROR_LINK" />melaporkan masalah pendeteksian<ph name="END_ERROR_LINK" /> atau, jika memahami risiko bagi keamanan, Anda dapat <ph name="BEGIN_LINK" />mengunjungi situs yang tidak aman<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Ada pertanyaan? Hubungi orang yang memantau profil Anda.</translation>
<translation id="8553075262323480129">Terjemahan gagal karena bahasa halaman tidak dapat ditentukan.</translation>
<translation id="8557066899867184262">CVC terletak di bagian belakang kartu Anda.</translation>
<translation id="8559762987265718583">Sambungan pribadi ke <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> tidak dapat dibuat karena tanggal dan waktu (<ph name="DATE_AND_TIME" />) perangkat tidak benar.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> situs mencurigakan</translation>
<translation id="8564985650692024650">Chromium menyarankan untuk menyetel ulang sandi <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> jika Anda juga menggunakannya di situs lain.</translation>
<translation id="8571890674111243710">Menerjemahkan halaman ke <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">+ nomor telepon</translation>
-<translation id="859285277496340001">Sertifikat tidak menetapkan mekanisme untuk memeriksa apakah sertifikat telah ditarik.</translation>
<translation id="860043288473659153">Nama pemegang kartu</translation>
<translation id="861775596732816396">Ukuran 4</translation>
-<translation id="8620436878122366504">Orang tuamu belum menyetujuinya</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Simpan Kartu Ini ke Perangkat Ini</translation>
<translation id="8626112503828625890">Simpan detail penagihan di Akun Google?</translation>
+<translation id="8647750283161643317">Setel ulang semua ke default</translation>
<translation id="8663226718884576429">Ringkasan Pesanan, <ph name="TOTAL_LABEL" />, Detail Selengkapnya</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, dengan jawaban, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Tersedia</translation>
<translation id="8703575177326907206">Sambungan ke <ph name="DOMAIN" /> tidak dienkripsi.</translation>
<translation id="8718314106902482036">Pembayaran belum selesai</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, saran penelusuran</translation>
@@ -1424,6 +1445,7 @@
<translation id="8738058698779197622">Untuk membuat sambungan aman, jam perlu disetel dengan benar. Hal ini karena sertifikat yang digunakan situs web untuk mengidentifikasi situs web tersebut hanya valid untuk jangka waktu tertentu. Karena jam perangkat tidak benar, Chromium tidak dapat memverifikasi sertifikat ini.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Alamat DNS&lt;/abbr&gt; <ph name="HOST_NAME" /> tidak dapat ditemukan. Mendiagnosis masalah.</translation>
<translation id="874846938927089722">Kartu Kredit dan Prabayar yang Diterima</translation>
+<translation id="874918643257405732">Bookmark tab ini</translation>
<translation id="8759274551635299824">Kartu sudah tidak aktif</translation>
<translation id="8761567432415473239">Google Safe Browsing baru-baru ini <ph name="BEGIN_LINK" />menemukan program berbahaya<ph name="END_LINK" /> di <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Perangkat USB</translation>
@@ -1453,6 +1475,7 @@
<translation id="8938939909778640821">Kartu kredit dan prabayar yang diterima</translation>
<translation id="8943282376843390568">Hijau limau</translation>
<translation id="8957210676456822347">Otorisasi Portal Tawanan</translation>
+<translation id="8962950042226115166">Situs mencurigakan</translation>
<translation id="8968766641738584599">Simpan kartu</translation>
<translation id="8971063699422889582">Sertifikat server telah kedaluwarsa.</translation>
<translation id="8975012916872825179">Termasuk informasi seperti nomor telepon, alamat email, dan alamat pengiriman</translation>
@@ -1475,24 +1498,24 @@
<translation id="9035022520814077154">Kesalahan keamanan</translation>
<translation id="9038649477754266430">Gunakan layanan prediksi agar halaman dimuat dengan lebih cepat</translation>
<translation id="9039213469156557790">Selain itu, halaman ini berisi sumber daya lainnya yang tidak aman. Sumber daya ini dapat dilihat oleh orang lain saat transit dan dapat dimodifikasi oleh penyerang untuk mengubah perilaku halaman.</translation>
+<translation id="9044359186343685026">Gunakan Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Anda berupaya menjangkau <ph name="DOMAIN" />, tetapi server menyajikan sertifikat yang tidak valid.</translation>
<translation id="9050666287014529139">Frasa sandi</translation>
<translation id="9065203028668620118">Edit</translation>
<translation id="9065745800631924235">penelusuran <ph name="TEXT" /> dari histori</translation>
<translation id="9069693763241529744">Diblokir oleh ekstensi</translation>
-<translation id="9076283476770535406">Situs mungkin berisi konten dewasa</translation>
<translation id="9076630408993835509">Browser ini tidak dikelola oleh sebuah perusahaan atau organisasi lain. Aktivitas di perangkat ini mungkin dikelola di luar Chrome. <ph name="BEGIN_LINK" />Pelajari Lebih Lanjut<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Dibutuhkan informasi lebih lanjut</translation>
<translation id="9080712759204168376">Ringkasan Pesanan</translation>
<translation id="9089260154716455634">Kebijakan Waktu Nonaktif:</translation>
<translation id="9095388113577226029">Bahasa lainnya...</translation>
+<translation id="9098981495403789647">Administrator Anda telah mengaktifkan Perlindungan Ancaman Chrome Enterprise di browser Anda. Perlindungan Ancaman Chrome Enterprise memiliki akses ke beberapa data Anda.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> biasanya menggunakan enkripsi untuk melindungi informasi Anda. Saat Chromium mencoba menyambung ke <ph name="SITE" /> kali ini, situs web mengembalikan kredensial yang salah dan tidak biasa. Hal ini dapat terjadi jika ada penyerang yang berpura-pura menjadi <ph name="SITE" />, atau layar masuk Wi-Fi mengganggu sambungan. Informasi Anda masih aman karena Chromium menghentikan sambungan sebelum terjadi pertukaran data apa pun.</translation>
<translation id="9106062320799175032">Tambahkan Alamat Penagihan</translation>
<translation id="9114524666733003316">Mengonfirmasi kartu...</translation>
<translation id="9128870381267983090">Sambungkan ke jaringan</translation>
<translation id="9137013805542155359">Perlihatkan halaman asli</translation>
-<translation id="9137248913990643158">Mulai dan login ke Chrome sebelum menggunakan aplikasi ini.</translation>
<translation id="9141013498910525015">Kelola alamat</translation>
<translation id="9148088599418889305">Pilih Metode Pengiriman</translation>
<translation id="9148507642005240123">&amp;Urungkan pengeditan</translation>
diff --git a/chromium/components/strings/components_strings_it.xtb b/chromium/components/strings/components_strings_it.xtb
index ca00a14aff0..d928c7b75b6 100644
--- a/chromium/components/strings/components_strings_it.xtb
+++ b/chromium/components/strings/components_strings_it.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Aggiungi il nome indicato sulla carta</translation>
<translation id="1089439967362294234">Cambia password</translation>
+<translation id="1096545575934602868">Questo campo non deve avere più di <ph name="MAX_ITEMS_LIMIT" /> voci. Tutte le voci in esubero verranno eliminate.</translation>
<translation id="109743633954054152">Gestisci le password nelle impostazioni di Chrome</translation>
<translation id="1103523840287552314">Traduci sempre <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Se questa opzione viene selezionata, Chrome memorizza una copia della carta sul dispositivo per velocizzare la compilazione dei moduli.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Accedi a una <ph name="BEGIN_LINK" />copia memorizzata nella cache<ph name="END_LINK" /> di <ph name="URL" /></translation>
<translation id="1156303062776767266">È visualizzato un file locale o condiviso</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ha chiuso in modo imprevisto la connessione.</translation>
+<translation id="115926840831309955">Controlla il tuo codice CVC e riprova o aggiorna la data di scadenza</translation>
<translation id="1161325031994447685">Riconnessione alla rete Wi-Fi</translation>
<translation id="1165039591588034296">Errore</translation>
<translation id="1175364870820465910">&amp;Stampa...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Il software installato sul computer sta impedendo a Chrome di connettersi in sicurezza a Internet" (solo su computer Windows)</translation>
<translation id="1294154142200295408">Variazioni nella riga di comando</translation>
<translation id="129553762522093515">Chiuse di recente</translation>
+<translation id="1298536327547837046">Analisi della presenza di malware</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Prova a cancellare i cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funzionalità obsolete</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Cerca immagine negli appunti</translation>
<translation id="1323433172918577554">Espandi</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Fogli Google</translation>
<translation id="1527263332363067270">In attesa di connessione…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">Il sito che stai provando a visitare risulta contraffatto. A volte i malintenzionati imitano i siti modificando leggermente e in modo poco evidente l'URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Questa pagina dice</translation>
<translation id="153384715582417236">Per il momento è tutto</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">Sistema operativo</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Il documento è troppo voluminoso per potervi inserire annotazioni</translation>
-<translation id="1721312023322545264">Ti occorre l'autorizzazione di <ph name="NAME" /> per poter visitare il sito</translation>
<translation id="1721424275792716183">* Campo obbligatorio</translation>
<translation id="1727741090716970331">Aggiungi un numero di carta valido</translation>
<translation id="1728677426644403582">È visualizzata l'origine di una pagina web</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Siti web visitati e tempo trascorso sui siti</translation>
<translation id="1826516787628120939">Verifica in corso...</translation>
<translation id="1834321415901700177">Il sito contiene programmi dannosi.</translation>
+<translation id="1838374766361614909">Cancella ricerca</translation>
<translation id="1839551713262164453">Convalida dei valori della norma non riuscita con errori</translation>
<translation id="1842969606798536927">Paga</translation>
<translation id="1871208020102129563">L'impostazione del proxy prevede l'utilizzo di server proxy fissi, non di un URL script .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Comprimi elenco</translation>
<translation id="1898423065542865115">Filtri</translation>
<translation id="1914326953223720820">Servizio di decompressione</translation>
+<translation id="1915697529809968049">Usare Touch ID anziché CVC?</translation>
<translation id="1916770123977586577">Ricarica la pagina per applicare le impostazioni aggiornate a questo sito</translation>
<translation id="1919345977826869612">Annunci</translation>
<translation id="1919367280705858090">Assistenza per un messaggio di errore specifico</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Segnalibri di <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Errore di serializzazione</translation>
<translation id="1974060860693918893">Avanzate</translation>
+<translation id="1974883374937189061">Contribuisci a migliorare la sicurezza di Chrome inviando a Google <ph name="BEGIN_WHITEPAPER_LINK" />gli URL di alcune pagine visitate, informazioni limitate sul sistema e alcuni contenuti delle pagine<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versione firmware</translation>
<translation id="1981206234434200693">Cancella i dati della cronologia di navigazione di Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{e un'altra}other{e altre #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Inserisci un anno di scadenza valido</translation>
<translation id="2212735316055980242">Criterio non trovato</translation>
<translation id="2213606439339815911">Recupero voci...</translation>
+<translation id="2215727959747642672">Modifica del file</translation>
<translation id="2218879909401188352">Gli utenti malintenzionati attualmente presenti sul sito <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> potrebbero installare app pericolose che danneggiano il tuo dispositivo, generano addebiti nascosti sul tuo credito telefonico o si impossessano dei tuoi dati personali. <ph name="BEGIN_LEARN_MORE_LINK" />Ulteriori informazioni<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Nessuna connessione a Internet</translation>
<translation id="2230458221926704099">Correggi la connessione con l'<ph name="BEGIN_LINK" />app diagnostica<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Invia ora</translation>
+<translation id="2248949050832152960">Usa WebAuthn</translation>
<translation id="225207911366869382">Il valore specificato per la norma è obsoleto.</translation>
<translation id="2257315177824333709">Spiacenti, al momento non è possibile salvare la tua carta</translation>
<translation id="2262243747453050782">Errore HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL ricerca non valido.</translation>
<translation id="2482878487686419369">Notifiche</translation>
<translation id="248348093745724435">Norme macchina</translation>
-<translation id="2485387744899240041">Nomi utente del dispositivo e del browser</translation>
<translation id="2491120439723279231">Il certificato del server contiene degli errori.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Parser</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Indietro</translation>
<translation id="2503184589641749290">Carte di debito e prepagate accettate</translation>
<translation id="2505268675989099013">Proteggi account</translation>
+<translation id="2515335152965840738">IGNORA</translation>
<translation id="2515629240566999685">Controllare il segnale nella tua area</translation>
<translation id="2523886232349826891">Salvataggio effettuato solo su questo dispositivo</translation>
<translation id="2524461107774643265">Aggiungi altre informazioni</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Invia</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nessuna}=1{1 password per <ph name="DOMAIN_LIST" />}=2{2 password per <ph name="DOMAIN_LIST" />}other{# password per <ph name="DOMAIN_LIST" />}}</translation>
<translation id="2666117266261740852">Chiudi altre schede o app</translation>
-<translation id="267371737713284912">Premi <ph name="MODIFIER_KEY_DESCRIPTION" /> per annullare</translation>
<translation id="2674170444375937751">Eliminare le pagine dalla cronologia?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Esci</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Il valore non corrisponde al formato.</translation>
<translation id="2705137772291741111">La copia del sito salvata (nella cache) era illeggibile.</translation>
<translation id="2709516037105925701">Compilazione automatica</translation>
-<translation id="2712173769900027643">Chiedi autorizzazione</translation>
<translation id="2713444072780614174">Bianco</translation>
<translation id="2720342946869265578">Qui vicino</translation>
<translation id="2721148159707890343">Richiesta riuscita</translation>
<translation id="2728127805433021124">Il certificato del server è stato firmato utilizzando un algoritmo di firma debole.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Eseguire lo strumento Diagnostica della connettività<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Se attivi queste funzioni, potresti perdere i dati del browser oppure
+ compromettere la sicurezza o la privacy. Le funzioni attivate vengono applicate per tutti
+ gli utenti di questo browser.</translation>
<translation id="2735043616039983645">È presente più di un'origine con valori in conflitto per questo criterio.</translation>
<translation id="2738330467931008676">Scegli l'indirizzo di ritiro</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">La connessione è stata reimpostata.</translation>
<translation id="2788784517760473862">Carte di credito accettate</translation>
<translation id="2792012897584536778">Gli amministratori di questo dispositivo hanno configurato certificati di sicurezza che potrebbero consentire loro di visualizzare i contenuti dei siti web che visiti.</translation>
-<translation id="2794233252405721443">Sito bloccato</translation>
<translation id="2799020568854403057">Il sito che stai per visitare contiene app dannose</translation>
<translation id="2799223571221894425">Riavvia</translation>
<translation id="2803306138276472711">La funzione Navigazione sicura di Google ha <ph name="BEGIN_LINK" />rilevato malware<ph name="END_LINK" /> di recente sul sito <ph name="SITE" />. I siti web che in genere sono sicuri a volte vengono infettati da malware.</translation>
+<translation id="2815364696811431560">ESCI DAL SITO</translation>
<translation id="2824775600643448204">Barra degli indirizzi e di ricerca</translation>
<translation id="2826760142808435982">La connessione è stata criptata e autenticata utilizzando <ph name="CIPHER" /> e <ph name="KX" /> come meccanismo di scambio delle chiavi.</translation>
<translation id="2835170189407361413">Cancella modulo</translation>
<translation id="2847118875340931228">Apri finestra di navigazione in incognito</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Ti occorre l'autorizzazione per poter visitare questo sito</translation>
<translation id="2856444702002559011">Gli utenti malintenzionati potrebbero provare a carpire le tue informazioni da <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (ad esempio, password, messaggi o carte di credito). <ph name="BEGIN_LEARN_MORE_LINK" />Ulteriori informazioni<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Salvare la carta?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Se questa opzione viene attivata, Chromium memorizza una copia della carta sul dispositivo per velocizzare la compilazione dei moduli.</translation>
<translation id="2985398929374701810">Inserisci un indirizzo valido</translation>
<translation id="2986368408720340940">Questo metodo di ritiro non è disponibile. Prova un metodo diverso.</translation>
+<translation id="2987034854559945715">Nessuna funzionalità corrispondente</translation>
<translation id="2991174974383378012">Condivisione con i siti web</translation>
<translation id="2991571918955627853">Al momento non puoi visitare il sito web <ph name="SITE" /> perché utilizza HSTS. In genere gli errori di rete e gli attacchi sono temporanei, pertanto questa pagina potrebbe funzionare più tardi.</translation>
<translation id="3005723025932146533">Mostra copia salvata</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Tipo di criterio errato</translation>
<translation id="3037605927509011580">Uffa!</translation>
<translation id="3041612393474885105">Informazioni certificato</translation>
+<translation id="3057676462092457419">La modalità DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> non è ancora supportata. La modalità è stata impostata su <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Servizio di applicazione patch</translation>
<translation id="3064966200440839136">Per procedere al pagamento tramite un'applicazione esterna, uscirai dalla modalità di navigazione in incognito. Continuare?</translation>
@@ -424,6 +435,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> su <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Annulla pagamento</translation>
<translation id="3207960819495026254">Aggiunto ai preferiti</translation>
+<translation id="3209034400446768650">La pagina potrebbe addebitare denaro</translation>
<translation id="3225919329040284222">Il server ha presentato un certificato che non corrisponde alle previsioni integrate. Queste previsioni sono incluse per determinati siti web con protezione elevata allo scopo di proteggerti.</translation>
<translation id="3226128629678568754">Premi il pulsante Ricarica per inviare di nuovo i dati necessari per caricare la pagina.</translation>
<translation id="3227137524299004712">Microfono</translation>
@@ -431,7 +443,6 @@
<translation id="3229041911291329567">Informazioni sulla versione del dispositivo e del browser</translation>
<translation id="323107829343500871">Inserisci il codice CVC della carta <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Rileva sempre contenuti importanti di questo sito</translation>
-<translation id="3254409185687681395">Aggiungi ai Preferiti</translation>
<translation id="3270847123878663523">&amp;Annulla ridisposizione</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Aggiungi il nome indicato sulla carta</translation>
@@ -441,7 +452,6 @@
<translation id="3320021301628644560">Aggiungi l'indirizzo di fatturazione</translation>
<translation id="3324983252691184275">Cremisi</translation>
<translation id="3338095232262050444">Sicuro</translation>
-<translation id="3345135638360864351">Impossibile inviare a <ph name="NAME" /> la richiesta di accesso a questo sito. Riprova.</translation>
<translation id="3355823806454867987">Modifica impostazioni proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />non salverà<ph name="END_EMPHASIS" /> le seguenti informazioni:
<ph name="BEGIN_LIST" />
@@ -475,18 +485,15 @@
<translation id="3462200631372590220">Nascondi avanzate</translation>
<translation id="3467763166455606212">Nome titolare carta obbligatorio</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, attualmente aperta, premi TAB poi INVIO per passare alla scheda aperta</translation>
-<translation id="3479539252931486093">Non era previsto? <ph name="BEGIN_LINK" />Contattaci<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Non adesso</translation>
<translation id="3484560055331845446">Potresti non riuscire più ad accedere al tuo Account Google. Chrome consiglia di cambiare subito la password. Ti verrà chiesto di eseguire l'accesso.</translation>
<translation id="3495081129428749620">Trova nella pagina
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">In questo momento, non è possibile raggiungere il tuo genitore. Riprova.</translation>
<translation id="3512163584740124171">Questo criterio viene ignorato perché un altro criterio dello stesso gruppo ha una priorità più elevata.</translation>
<translation id="3528171143076753409">Il certificato del server non è affidabile.</translation>
<translation id="3528485271872257980">Marrone scuro</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Almeno 1 elemento sui dispositivi sincronizzati}=1{1 elemento (e altri sui dispositivi sincronizzati)}other{# elementi (e altri sui dispositivi sincronizzati)}}</translation>
<translation id="3539171420378717834">Conserva una copia di questa carta sul dispositivo</translation>
-<translation id="3556433843310711081">Il tuo gestore può sbloccarlo per te</translation>
<translation id="3566021033012934673">La connessione non è privata</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Una pagina incorporata in <ph name="SITE" /> dice</translation>
@@ -514,6 +521,7 @@
<translation id="3678529606614285348">Apri la pagina in un'altra finestra di navigazione in incognito (CTRL-MAIUSC-N)</translation>
<translation id="3679803492151881375">Rapporto sugli arresti anomali generato in data <ph name="CRASH_TIME" />, caricato in data <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informazioni certificato</translation>
+<translation id="3701427423622901115">Reimpostazione confermata.</translation>
<translation id="3704162925118123524">La rete che stai utilizzando può richiedere di visitare la relativa pagina di accesso.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Caricamento in corso...</translation>
@@ -530,6 +538,7 @@
<translation id="3748148204939282805">Gli utenti malintenzionati presenti sul sito <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> potrebbero indurti con l'inganno a effettuare operazioni pericolose, come installare software o rivelare informazioni personali (ad esempio password, numeri di telefono o carte di credito). <ph name="BEGIN_LEARN_MORE_LINK" />Ulteriori informazioni<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">La traduzione non è riuscita a causa di un errore del server.</translation>
<translation id="3759461132968374835">Non hai segnalato arresti anomali di recente. Quelli che si sono verificati quando la segnalazione degli arresti anomali era disabilitata non verranno visualizzati qui.</translation>
+<translation id="3760561303380396507">Usare Windows Hello anziché CVC?</translation>
<translation id="3761718714832595332">Nascondi stato</translation>
<translation id="3765032636089507299">La pagina Navigazione sicura è in fase di realizzazione.</translation>
<translation id="3778403066972421603">Vuoi salvare questa carta nel tuo Account Google e su questo dispositivo?</translation>
@@ -539,6 +548,7 @@
<translation id="3789155188480882154">Dimensione 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Contenuti dannosi bloccati.</translation>
+<translation id="3808375843007691220">Avviso: funzioni sperimentali da qui in avanti.</translation>
<translation id="3810973564298564668">Gestisci</translation>
<translation id="382518646247711829">Se utilizzi un server proxy...</translation>
<translation id="3828924085048779000">Non è consentita una passphrase vuota.</translation>
@@ -547,11 +557,11 @@
<translation id="3858027520442213535">Aggiorna data e ora</translation>
<translation id="3884278016824448484">Identificativo del dispositivo in conflitto</translation>
<translation id="3885155851504623709">Comune</translation>
-<translation id="3886446263141354045">La tua richiesta di accesso al sito è stata inviata a <ph name="NAME" /></translation>
<translation id="3890664840433101773">Aggiungi email</translation>
<translation id="3901925938762663762">La carta è scaduta</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Usare WebAuthn anziché CVC?</translation>
<translation id="3946209740501886391">Chiedi sempre su questo sito</translation>
<translation id="3949571496842715403">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza non contiene nomi alternativi del soggetto. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
<translation id="3949601375789751990">La cronologia di navigazione viene mostrata qui</translation>
@@ -562,11 +572,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nessuno}=1{Di 1 sito }other{Di # siti }}</translation>
<translation id="397105322502079400">Calcolo in corso...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> è bloccato</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ha attivato Chrome Enterprise Threat Protection sul tuo browser. Chrome Enterprise Threat Protection ha accesso ad alcuni tuoi dati.</translation>
<translation id="3987940399970879459">Meno di 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{Una pagina web nelle vicinanze}other{# pagine web nelle vicinanze}}</translation>
<translation id="4030383055268325496">&amp;Annulla aggiunta</translation>
<translation id="4032320456957708163">Il browser in uso è gestito da <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Il link che hai aperto indirizza a una pagina che solitamente non visiti. Potrebbe trattarsi di un tentativo per confonderti.</translation>
<translation id="4058922952496707368">Chiave "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Aggiungi un indirizzo valido</translation>
@@ -579,6 +589,7 @@
<translation id="4103249731201008433">Il numero di serie del dispositivo non è valido</translation>
<translation id="410351446219883937">Riproduzione automatica</translation>
<translation id="4103763322291513355">Visita &lt;strong&gt;chrome://policy&lt;/strong&gt; per visualizzare l'elenco di URL inseriti nella blacklist e altre norme applicate dall'amministratore di sistema.</translation>
+<translation id="4108231218301530806">Usa l'impronta per verificare questa carta la prossima volta</translation>
<translation id="4110652170750985508">Verifica il pagamento</translation>
<translation id="4112140312785995938">Vai indietro</translation>
<translation id="4116663294526079822">Consenti sempre su questo sito</translation>
@@ -593,6 +604,7 @@
<translation id="4171400957073367226">Firma di verifica non valida</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> altro elemento}other{Altri <ph name="ITEM_COUNT" /> elementi}}</translation>
+<translation id="4176463684765177261">Disattivate</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Per pagare più velocemente la prossima volta, aggiungi la carta e l'indirizzo di fatturazione al tuo Account Google.</translation>
<translation id="4196861286325780578">&amp;Ripeti spostamento</translation>
@@ -629,6 +641,7 @@
<translation id="4277028893293644418">Reimposta password</translation>
<translation id="4279811152705618813">Il tuo dispositivo <ph name="DEVICE_TYPE" /> è gestito dal dominio <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Questa carta è stata salvata nel tuo Account Google}other{Queste carte sono state salvate nel tuo Account Google}}</translation>
+<translation id="428847186335018806">Consente di analizzare i file scaricati e caricati in Chrome.</translation>
<translation id="42981349822642051">Espandi</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Cambia</translation>
@@ -658,7 +671,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">L'utilizzo di un proxy è stato disattivato ma è stata specificata una configurazione proxy esplicita.</translation>
<translation id="445100540951337728">Carte di debito accettate</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> comportamento sospetto</translation>
<translation id="4466881336512663640">Le modifiche apportate al modulo andranno perse. Vuoi continuare?</translation>
<translation id="4477350412780666475">Traccia successiva</translation>
<translation id="4482953324121162758">Questo sito non verrà tradotto.</translation>
@@ -685,6 +697,7 @@
<translation id="4594403342090139922">&amp;Annulla eliminazione</translation>
<translation id="4597348597567598915">Dimensione 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Funzionalità di ricerca</translation>
<translation id="4646534391647090355">Vai subito</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza contiene errori. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
@@ -693,7 +706,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">La connessione è stata interrotta</translation>
-<translation id="471880041731876836">Non sei autorizzato a visitare questo sito</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Eseguire lo strumento Diagnostica di rete Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Ricarica criteri</translation>
<translation id="4728558894243024398">Piattaforma</translation>
@@ -721,7 +733,6 @@
<translation id="4816492930507672669">Adatta alla pagina</translation>
<translation id="4850886885716139402">Visualizza</translation>
<translation id="4854362297993841467">Questo metodo di consegna non è disponibile. Prova un metodo diverso.</translation>
-<translation id="4858792381671956233">Hai chiesto ai tuoi genitori se puoi visitare questo sito</translation>
<translation id="4864052566555297930">Suggerimento sulla sicurezza:</translation>
<translation id="4876188919622883022">Visualizzazione semplificata</translation>
<translation id="4876305945144899064">Nessun nome utente</translation>
@@ -745,7 +756,9 @@
<translation id="4974590756084640048">Riattiva avvisi</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Mostra tutto</translation>
+<translation id="4989542687859782284">Non disponibili</translation>
<translation id="4989809363548539747">Questo plug-in non è supportato</translation>
+<translation id="4995216769782533993">Conferma il codice di sicurezza per condividere i dettagli della carta con questo sito</translation>
<translation id="5002932099480077015">Se questa opzione viene attivata, Chrome memorizza una copia della carta sul dispositivo per velocizzare la compilazione dei moduli.</translation>
<translation id="5015510746216210676">Nome macchina:</translation>
<translation id="5017554619425969104">Testo copiato</translation>
@@ -774,6 +787,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(a 64 bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verifica la carta</translation>
<translation id="5135404736266831032">Gestisci indirizzi…</translation>
<translation id="5138227688689900538">Mostra meno</translation>
<translation id="5141240743006678641">Cripta le password sincronizzate con le tue credenziali Google</translation>
@@ -800,6 +814,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Le funzionalità che vengono applicate a livello di sistema possono essere impostate solo dal proprietario: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Avviso: questo criterio non è stato unito come specificato nel criterio PolicyDictionaryMultipleSourceMergeList perché non fa parte dei criteri del dizionario che possono essere uniti.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Fine</translation>
@@ -823,7 +838,6 @@
<translation id="536296301121032821">Archiviazione delle impostazioni criterio non riuscita</translation>
<translation id="5371425731340848620">Aggiorna carta</translation>
<translation id="5377026284221673050">"L'orologio è indietro", "L'orologio è avanti" oppure "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Questa pagina potrebbe provare a ingannarti, a sottrarti informazioni personali o a danneggiare il tuo dispositivo. Fai attenzione quando inserisci informazioni personali o quando apri i file scaricati.</translation>
<translation id="5384855140246857529">Accedi e attiva la sincronizzazione per utilizzare le tue carte su tutti i dispositivi.</translation>
<translation id="5386426401304769735">Il certificato di questo sito contiene un certificato che è stato firmato utilizzando SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -837,6 +851,8 @@
<translation id="5457113250005438886">Non validi</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> e <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> altro}other{<ph name="CONTACT_PREVIEW" /> e altri <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Ripeti modifica</translation>
+<translation id="5473728911100096288">Se attivi queste funzionalità, userai funzionalità obsolete
+ che non saranno più disponibili nelle versioni future.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Questi contenuti potrebbero cercare di installare sul tuo dispositivo software pericoloso che si impossessa delle tue informazioni o le elimina. <ph name="BEGIN_LINK" />Mostra comunque<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Aggiungi un indirizzo valido</translation>
@@ -860,7 +876,6 @@
<translation id="5570825185877910964">Proteggi account</translation>
<translation id="5571083550517324815">Impossibile ritirare dall'indirizzo specificato. Seleziona un indirizzo diverso.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 in uso}other{# in uso}})</translation>
-<translation id="5572851009514199876">Accedi a Chrome per consentire al browser di verificare che tu sia autorizzato ad accedere a questo sito.</translation>
<translation id="5580958916614886209">Controlla il mese di scadenza e riprova</translation>
<translation id="5586446728396275693">Nessun indirizzo salvato</translation>
<translation id="5595485650161345191">Modifica indirizzo</translation>
@@ -868,6 +883,7 @@
<translation id="560412284261940334">Gestione non supportata</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Il sito potrebbe essere falso o fraudolento. Chrome ti consiglia di uscire immediatamente.</translation>
<translation id="5610142619324316209">Verificare la connessione</translation>
<translation id="5610807607761827392">Puoi gestire carte e indirizzi nelle <ph name="BEGIN_LINK" />Impostazioni<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ti ha reindirizzato troppe volte.</translation>
@@ -891,11 +907,11 @@
<translation id="5720705177508910913">Utente corrente</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome ti consiglia di reimpostare la password, se l'hai utilizzata su altri siti.</translation>
-<translation id="5732392974455271431">I tuoi genitori possono sbloccarlo per te</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Salva la carta nel tuo Account Google}other{Salva carte nel tuo Account Google}}</translation>
<translation id="5763042198335101085">Inserisci un indirizzo email valido</translation>
<translation id="5765072501007116331">Seleziona un indirizzo per conoscere i requisiti e i metodi di consegna</translation>
<translation id="5778550464785688721">Controllo completo di dispositivi MIDI</translation>
+<translation id="5781136890105823427">Esperimento attivato</translation>
<translation id="578305955206182703">Ambra</translation>
<translation id="57838592816432529">Disattiva audio</translation>
<translation id="5784606427469807560">Si è verificato un problema durante la conferma della carta. Controlla la connessione Internet e riprova.</translation>
@@ -912,13 +928,16 @@
<translation id="5860033963881614850">Off</translation>
<translation id="5863847714970149516">La pagina che segue potrebbe tentare di addebitarti dei costi</translation>
<translation id="5866257070973731571">Aggiungi numero di telefono</translation>
+<translation id="5866898949289125849">Stai visualizzando una pagina di strumenti per sviluppatori</translation>
<translation id="5869405914158311789">Impossibile raggiungere il sito</translation>
<translation id="5869522115854928033">Password salvate</translation>
<translation id="5887400589839399685">Carta salvata</translation>
<translation id="5893752035575986141">Le carte di credito sono accettate.</translation>
+<translation id="5895138241574237353">Riavvia</translation>
<translation id="5901630391730855834">Giallo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizzati)</translation>
<translation id="5916664084637901428">On</translation>
+<translation id="59174027418879706">Attivato</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Vuoi salvare la carta nell'Account Google?</translation>
<translation id="5922853866070715753">Hai quasi finito.</translation>
@@ -952,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Utilizzare le carte su tutti i tuoi dispositivi?</translation>
<translation id="6059925163896151826">Dispositivi USB</translation>
+<translation id="6060009363608157444">Modalità DnsOverHttps non valida.</translation>
<translation id="6080696365213338172">Hai raggiunto i contenuti utilizzando un certificato fornito dall'amministratore. I dati che fornisci a <ph name="DOMAIN" /> possono essere intercettati dal tuo amministratore.</translation>
<translation id="6094273045989040137">Consente di inserire l'annotazione</translation>
<translation id="610911394827799129">Il tuo Account Google potrebbe avere altre forme di cronologia di navigazione all'indirizzo <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -999,13 +1019,12 @@
<translation id="6404511346730675251">Modifica preferito</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Inserisci la data di scadenza e il codice CVC della carta <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Hai chiesto ai tuoi genitori l'autorizzazione per visitare questo sito</translation>
<translation id="6415778972515849510">Chromium può aiutarti a proteggere il tuo Account Google e a modificare la password.</translation>
-<translation id="6417515091412812850">Impossibile controllare se il certificato è stato revocato.</translation>
<translation id="6431585503458005759">Non memorizzare</translation>
<translation id="6433490469411711332">Modifica informazioni di contatto</translation>
<translation id="6433595998831338502">Connessione negata da <ph name="HOST_NAME" />.</translation>
<translation id="6434309073475700221">Annulla</translation>
+<translation id="6435221585574090192">Consente di condividere con l'amministratore i dati relativi agli eventi di sicurezza segnalati da Chrome Enterprise Threat Protection. Tali dati potrebbero includere URL di pagine, metadati di file e nomi file, il nome utente del dispositivo e di Chrome.</translation>
<translation id="6440503408713884761">Ignorata</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Aggiungi altre informazioni</translation>
@@ -1014,20 +1033,19 @@
<translation id="6465306955648956876">Gestisci password…</translation>
<translation id="647261751007945333">Criteri dispositivo</translation>
<translation id="6476284679642588870">Gestisci metodi di pagamento</translation>
-<translation id="6477321094435799029">Chrome ha rilevato un codice insolito su questa pagina e l'ha bloccata per proteggere le tue informazioni personali (ad esempio password, numeri di telefono e carte di credito).</translation>
<translation id="6489534406876378309">Avvia caricamento arresti anomali</translation>
<translation id="6499038740797743453">Reimpostare la password?</translation>
<translation id="6507833130742554667">Le carte di credito e di debito sono accettate.</translation>
<translation id="650855688985305916">Sì, memorizza</translation>
<translation id="6508722015517270189">Riavvia Chrome</translation>
<translation id="6517596291481585650">Avviso: questo criterio non è stato unito come elenco come specificato dal criterio perché non è un elenco.</translation>
+<translation id="6518133107902771759">Verifica</translation>
<translation id="6521745193039995384">Non attivo</translation>
<translation id="6529602333819889595">&amp;Ripeti eliminazione</translation>
<translation id="6534179046333460208">Suggerimenti relativi al Physical Web</translation>
<translation id="6545864417968258051">Scansione Bluetooth</translation>
<translation id="6554795675067793129">Il tuo account è gestito da <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Ripeti</translation>
-<translation id="6563469144985748109">Il tuo gestore non ha ancora approvato la richiesta</translation>
<translation id="6569060085658103619">È visualizzata la pagina di un'estensione</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Rosa chiaro</translation>
@@ -1045,11 +1063,13 @@
<translation id="6643016212128521049">Cancella</translation>
<translation id="6644283850729428850">Questa norma è obsoleta.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nessuno}=1{Da 1 sito (non verrai disconnesso dal tuo Account Google)}other{Da # siti (non verrai disconnesso dal tuo Account Google)}}</translation>
+<translation id="6652101503459149953">Usa Windows Hello</translation>
<translation id="6657585470893396449">Password</translation>
<translation id="6670613747977017428">Torna nell'area protetta.</translation>
<translation id="6671697161687535275">Rimuovere il suggerimento per i moduli da Chromium?</translation>
<translation id="6685834062052613830">Esci e completa la configurazione</translation>
<translation id="6689271823431384964">Chrome chiede se vuoi salvare le tue carte nel tuo Account Google perché hai eseguito l'accesso. Puoi modificare questo comportamento nelle impostazioni. Il nome del titolare della carta proviene dal tuo account.</translation>
+<translation id="6707256370811247129">Consente di analizzare i contenuti della cache e i file scaricati o caricati in Chrome.</translation>
<translation id="6710213216561001401">Indietro</translation>
<translation id="6710594484020273272">&lt;Digita un termine di ricerca&gt;</translation>
<translation id="671076103358959139">Token di registrazione:</translation>
@@ -1057,10 +1077,10 @@
<translation id="6738516213925468394">I tuoi dati sono stati criptati con la tua <ph name="BEGIN_LINK" />passphrase di sincronizzazione<ph name="END_LINK" /> in data <ph name="TIME" />. Inseriscila per avviare la sincronizzazione.</translation>
<translation id="674375294223700098">Errore sconosciuto del certificato del server.</translation>
<translation id="6744009308914054259">In attesa di una connessione, puoi visitare la pagina Download per leggere gli articoli offline.</translation>
+<translation id="6747611005629681221">Avviso: le funzionalità verranno ritirate a breve.</translation>
<translation id="6753269504797312559">Valore criterio</translation>
<translation id="6757797048963528358">Il dispositivo è entrato in modalità sospensione.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Il tuo genitore non ha ancora approvato la richiesta</translation>
<translation id="67862343314499040">Lilla</translation>
<translation id="6786747875388722282">Estensioni</translation>
<translation id="6790428901817661496">Play</translation>
@@ -1068,6 +1088,7 @@
<translation id="681021252041861472">Campo obbligatorio</translation>
<translation id="6810899417690483278">ID personalizzazione</translation>
<translation id="6825578344716086703">Hai tentato di accedere al sito <ph name="DOMAIN" />, ma il server ha presentato un certificato firmato utilizzando un algoritmo di firma debole (ad esempio SHA-1). Ciò significa che le credenziali di sicurezza presentate dal server potrebbero essere state falsificate e il server potrebbe non essere quello previsto (è possibile che tu stia comunicando con un malintenzionato).</translation>
+<translation id="6826370046007623921">Prevenzione della perdita dei dati</translation>
<translation id="6831043979455480757">Traduci</translation>
<translation id="6839929833149231406">Area</translation>
<translation id="6852204201400771460">Ricaricare l'app?</translation>
@@ -1080,7 +1101,6 @@
<translation id="6891596781022320156">Il livello della norma non è supportato.</translation>
<translation id="6895330447102777224">La carta è stata confermata</translation>
<translation id="6897140037006041989">User-agent</translation>
-<translation id="6903319715792422884">Contribuisci a migliorare la Navigazione sicura inviando a Google <ph name="BEGIN_WHITEPAPER_LINK" />informazioni di sistema e contenuti delle pagine<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utente:</translation>
<translation id="6934672428414710184">Questo nome proviene dal tuo Account Google</translation>
<translation id="6944692733090228304">Hai inserito la password in un sito non gestito da <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Per proteggere il tuo account, non riutilizzare la password con altri siti e app.</translation>
@@ -1125,6 +1145,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> e <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> altro}other{<ph name="PAYMENT_METHOD_PREVIEW" /> e altri <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavanda</translation>
<translation id="717330890047184534">ID GAIA:</translation>
+<translation id="7174545416324379297">Uniti</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> e <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> altra}other{<ph name="SHIPPING_OPTION_PREVIEW" /> e altre <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Il server a cui ti stai collegando, <ph name="ORIGIN" />, ha richiesto
l'applicazione di una norma di sicurezza per tutte le richieste. Ma anziché
@@ -1162,6 +1183,7 @@ Ulteriori dettagli:
<translation id="7320336641823683070">Guida alla connessione</translation>
<translation id="733354035281974745">Override account locale del dispositivo</translation>
<translation id="7334320624316649418">&amp;Ripeti ridisposizione</translation>
+<translation id="7337706099755338005">Non disponibile sulla piattaforma in uso.</translation>
<translation id="733923710415886693">Il certificato del server non è stato reso pubblico tramite Certificate Transparency.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Con affiliazione:</translation>
@@ -1193,7 +1215,6 @@ Ulteriori dettagli:
<translation id="7440140511386898319">Esplora offline</translation>
<translation id="7441627299479586546">Oggetto del criterio errato</translation>
<translation id="7442725080345379071">Arancione chiaro</translation>
-<translation id="7444046173054089907">Questo sito è bloccato</translation>
<translation id="7445762425076701745">Impossibile convalidare completamente l'identità del server a cui sei collegato. Sei collegato a un server con un nome valido soltanto nella tua rete, di cui un'autorità di certificazione esterna non può convalidare in alcun modo la proprietà. Poiché alcune autorità di certificazione emettono comunque certificati per questi nomi, non è in alcun modo possibile garantire che tu sia collegato al sito web desiderato anziché a un sito dannoso.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Leggere ulteriori informazioni<ph name="END_LINK" /> sul problema.</translation>
<translation id="7455133967321480974">Usa predefinita globale (Blocca)</translation>
@@ -1215,9 +1236,9 @@ Ulteriori dettagli:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Dopo essere stati confermati, i dati della carta saranno condivisi con questo sito.</translation>
<translation id="7542995811387359312">La compilazione automatica della carta di credito è disattivata perché questo modulo non utilizza una connessione sicura.</translation>
-<translation id="7543525346216957623">Chiedi a uno dei tuoi genitori</translation>
<translation id="7548892272833184391">Correggere gli errori di connessione</translation>
<translation id="7549584377607005141">Questa pagina web richiede dati che hai inserito in precedenza per poter essere visualizzata correttamente. Puoi inviare di nuovo i dati, ma in questo caso ripeterai l'azione precedentemente eseguita nella pagina.</translation>
+<translation id="7550637293666041147">Nome utente del dispositivo e nome utente di Chrome</translation>
<translation id="7552846755917812628">Prova i seguenti suggerimenti:</translation>
<translation id="7554791636758816595">Nuova scheda</translation>
<translation id="7564049878696755256">Potresti non riuscire più ad accedere al tuo account <ph name="ORG_NAME" /> o subire un furto d'identità. Chrome ti consiglia di cambiare subito la password.</translation>
@@ -1232,6 +1253,7 @@ Ulteriori dettagli:
<translation id="7610193165460212391">Il valore non è compreso nell'intervallo (<ph name="VALUE" />).</translation>
<translation id="7613889955535752492">Scadenza: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Hai già dati criptati con una versione diversa della password del tuo Account Google. Inseriscila qui di seguito.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Dati sulle prestazioni e rapporti sugli arresti anomali</translation>
<translation id="7637571805876720304">Rimuovere la carta di credito da Chromium?</translation>
<translation id="7638605456503525968">Porte seriali</translation>
@@ -1244,7 +1266,6 @@ Ulteriori dettagli:
<translation id="7668654391829183341">Dispositivo sconosciuto</translation>
<translation id="7669271284792375604">I malintenzionati su questo sito potrebbero cercare di indurti con l'inganno a installare programmi che danneggiano la tua navigazione (ad esempio cambiando la tua pagina iniziale o mostrando annunci extra sui siti che visiti).</translation>
<translation id="7676643023259824263">Cerca testo negli appunti, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Piattaforma e cloud</translation>
<translation id="7681101578153515023">Cambia motore di ricerca</translation>
<translation id="7682287625158474539">Spedizione</translation>
<translation id="7687186412095877299">Compila i moduli di pagamento con i metodi di pagamento salvati</translation>
@@ -1259,7 +1280,6 @@ Ulteriori dettagli:
<translation id="7723047071702270851">Modifica la carta</translation>
<translation id="774634243536837715">Contenuti pericolosi bloccati.</translation>
<translation id="7752995774971033316">Non gestito</translation>
-<translation id="7755287808199759310">Il tuo genitore può sbloccarlo per te</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Il software antivirus o il firewall potrebbe avere bloccato la connessione.</translation>
<translation id="7759163816903619567">Dominio visualizzato:</translation>
@@ -1303,7 +1323,6 @@ Ulteriori dettagli:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Gestisci password</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Questa carta e il relativo indirizzo di fatturazione verranno salvati. Potrai usarla dopo aver eseguito l'accesso all'account <ph name="USER_EMAIL" />.}other{Queste carte e i relativi indirizzi di fatturazione verranno salvati. Potrai usarle dopo aver eseguito l'accesso all'account <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">In questo momento, non è possibile raggiungere i tuoi genitori. Riprova.</translation>
<translation id="8025119109950072390">I malintenzionati su questo sito potrebbero indurti con l'inganno a effettuare operazioni pericolose, come installare software o fornire i tuoi dati personali (ad esempio password, numeri di telefono o carte di credito).</translation>
<translation id="8034522405403831421">Questa pagina è in <ph name="SOURCE_LANGUAGE" />. Tradurla in <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Penna</translation>
@@ -1314,6 +1333,7 @@ Ulteriori dettagli:
<translation id="8041940743680923270">Usa predefinita globale (Chiedi)</translation>
<translation id="8042918947222776840">Scegli il metodo di ritiro</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" non è configurato correttamente. La disinstallazione di "<ph name="SOFTWARE_NAME" />" solitamente risolve il problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">D'ora in poi non dovrai più indicare il codice di sicurezza di una carta</translation>
<translation id="8066955247577885446">Si è verificato un problema.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Non è possibile inserire annotazioni se il documento è ruotato</translation>
@@ -1344,6 +1364,7 @@ Ulteriori dettagli:
<translation id="8211406090763984747">La connessione è protetta</translation>
<translation id="8218327578424803826">Posizione assegnata:</translation>
<translation id="8220146938470311105">C7/C6 (Busta)</translation>
+<translation id="8220639454292072926">Rapporti Enterprise</translation>
<translation id="8225771182978767009">La persona che ha configurato il computer ha deciso di bloccare questo sito.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Apri la pagina in una nuova scheda di navigazione in incognito</translation>
@@ -1398,23 +1419,23 @@ Ulteriori dettagli:
<translation id="8508648098325802031">Icona Ricerca</translation>
<translation id="8522552481199248698">Chrome può aiutarti a proteggere il tuo Account Google e a modificare la password.</translation>
<translation id="8543181531796978784">Puoi <ph name="BEGIN_ERROR_LINK" />segnalare un problema di rilevamento<ph name="END_ERROR_LINK" /> oppure, se sei consapevole dei rischi per la tua sicurezza, <ph name="BEGIN_LINK" />visita questo sito non sicuro<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Domande? Contatta il supervisore del tuo profilo.</translation>
<translation id="8553075262323480129">La traduzione non è riuscita perché non è stato possibile determinare la lingua della pagina.</translation>
<translation id="8557066899867184262">Il codice CVC si trova sul lato posteriore della carta.</translation>
<translation id="8559762987265718583">Impossibile stabilire una connessione privata con il sito <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> perché data e ora del dispositivo (<ph name="DATE_AND_TIME" />) sono sbagliate.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> sito sospetto</translation>
<translation id="8564985650692024650">Chromium ti consiglia di reimpostare la password di <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, se l'hai utilizzata su altri siti.</translation>
<translation id="8571890674111243710">Traduzione della pagina in <ph name="LANGUAGE" /> in corso...</translation>
<translation id="858637041960032120">Aggiungi telefono</translation>
-<translation id="859285277496340001">Il certificato non specifica un meccanismo per il controllo della sua revoca.</translation>
<translation id="860043288473659153">Nome del titolare della carta</translation>
<translation id="861775596732816396">Dimensione 4</translation>
-<translation id="8620436878122366504">I tuoi genitori non hanno ancora approvato la richiesta</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Salva la carta su questo dispositivo</translation>
<translation id="8626112503828625890">Memorizzare i dettagli di fatturazione nell'Account Google?</translation>
+<translation id="8647750283161643317">Ripristina i valori predefiniti per tutto</translation>
<translation id="8663226718884576429">Riepilogo ordine, <ph name="TOTAL_LABEL" />, altri dettagli</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, risposta, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponibile</translation>
<translation id="8703575177326907206">La connessione a <ph name="DOMAIN" /> non è criptata.</translation>
<translation id="8718314106902482036">Pagamento non completato</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, suggerimento di ricerca</translation>
@@ -1425,6 +1446,7 @@ Ulteriori dettagli:
<translation id="8738058698779197622">Per poter stabilire una connessione protetta, l'orologio deve essere impostato correttamente perché i certificati utilizzati dai siti web per identificarsi sono validi soltanto per determinati periodi di tempo. L'orologio del dispositivo è sbagliato, pertanto Chromium non può verificare i certificati.</translation>
<translation id="8740359287975076522">Impossibile trovare l'&lt;abbr id="dnsDefinition"&gt;indirizzo DNS&lt;/abbr&gt; di <ph name="HOST_NAME" />. Stiamo analizzando il problema.</translation>
<translation id="874846938927089722">Carte di credito e prepagate accettate</translation>
+<translation id="874918643257405732">Aggiungi questa scheda ai preferiti</translation>
<translation id="8759274551635299824">La carta è scaduta</translation>
<translation id="8761567432415473239">La funzione Navigazione sicura di Google <ph name="BEGIN_LINK" />ha trovato di recente programmi dannosi<ph name="END_LINK" /> su <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispositivo USB</translation>
@@ -1454,6 +1476,7 @@ Ulteriori dettagli:
<translation id="8938939909778640821">Carte di credito e prepagate accettate</translation>
<translation id="8943282376843390568">Giallo-verde</translation>
<translation id="8957210676456822347">Autorizzazione Captive Portal</translation>
+<translation id="8962950042226115166">Sito sospetto</translation>
<translation id="8968766641738584599">Salva carta</translation>
<translation id="8971063699422889582">Il certificato del server è scaduto.</translation>
<translation id="8975012916872825179">Include informazioni come numeri di telefono, indirizzi email e indirizzi di spedizione</translation>
@@ -1476,24 +1499,24 @@ Ulteriori dettagli:
<translation id="9035022520814077154">Errore di sicurezza</translation>
<translation id="9038649477754266430">Utilizza un servizio di previsione per velocizzare il caricamento delle pagine</translation>
<translation id="9039213469156557790">Inoltre, questa pagina include altre risorse che non sono sicure. Tali risorse possono essere visualizzate da altri durante il transito dei dati e possono essere modificate da un utente malintenzionato al fine di modificare il comportamento della pagina.</translation>
+<translation id="9044359186343685026">Usa Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Hai tentato di connetterti a <ph name="DOMAIN" />, ma il server ha presentato un certificato scaduto.</translation>
<translation id="9050666287014529139">Passphrase</translation>
<translation id="9065203028668620118">Modifica</translation>
<translation id="9065745800631924235">Ricerca di <ph name="TEXT" /> nella cronologia</translation>
<translation id="9069693763241529744">Bloccata da un'estensione</translation>
-<translation id="9076283476770535406">Può includere contenuti per adulti</translation>
<translation id="9076630408993835509">Questo browser non è gestito da un'azienda o da un'altra organizzazione. L'attività svolta su questo dispositivo potrebbe essere gestita al di fuori di Chrome. <ph name="BEGIN_LINK" />Ulteriori informazioni<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Sono necessarie maggiori informazioni</translation>
<translation id="9080712759204168376">Riepilogo dell'ordine</translation>
<translation id="9089260154716455634">Criterio Orari di disattivazione:</translation>
<translation id="9095388113577226029">Altre lingue</translation>
+<translation id="9098981495403789647">L'amministratore ha attivato Chrome Enterprise Threat Protection sul tuo browser. Chrome Enterprise Threat Protection ha accesso ad alcuni tuoi dati.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> in genere utilizza la crittografia per proteggere le tue informazioni. Questa volta, quando Chromium ha provato a connettersi a <ph name="SITE" />, il sito web ha restituito credenziali insolite e sbagliate. È possibile che un malintenzionato stia cercando di spacciarsi per il sito <ph name="SITE" /> oppure che una schermata di accesso alla rete Wi-Fi abbia interrotto la connessione. Le tue informazioni sono ancora al sicuro perché Chromium ha interrotto la connessione prima che avvenissero scambi di dati.</translation>
<translation id="9106062320799175032">Aggiungi indirizzo di fatturazione</translation>
<translation id="9114524666733003316">Conferma della carta...</translation>
<translation id="9128870381267983090">Collegati alla rete</translation>
<translation id="9137013805542155359">Mostra originale</translation>
-<translation id="9137248913990643158">Accedi a Chrome prima di usare questa app.</translation>
<translation id="9141013498910525015">Gestisci gli indirizzi</translation>
<translation id="9148088599418889305">Scegli il metodo di spedizione</translation>
<translation id="9148507642005240123">&amp;Annulla modifica</translation>
diff --git a/chromium/components/strings/components_strings_iw.xtb b/chromium/components/strings/components_strings_iw.xtb
index 1de496f1aab..98c71694fc3 100644
--- a/chromium/components/strings/components_strings_iw.xtb
+++ b/chromium/components/strings/components_strings_iw.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">הוספת השם שמופיע בכרטיס</translation>
<translation id="1089439967362294234">שינוי סיסמה</translation>
+<translation id="1096545575934602868">השדה הזה יכול לכלול עד <ph name="MAX_ITEMS_LIMIT" /> רשומות. כל הרשומות הנוספות יימחקו.</translation>
<translation id="109743633954054152">‏ניהול סיסמאות בהגדרות Chrome</translation>
<translation id="1103523840287552314">ברצוני לקבל תרגום מ<ph name="LANGUAGE" /> תמיד</translation>
<translation id="1107591249535594099">‏אם האפשרות הזו מסומנת, Chrome ישמור עותק של הכרטיס במכשיר הזה כדי למלא טפסים במהירות רבה יותר.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">גש אל <ph name="BEGIN_LINK" />עותק בקובץ שמור<ph name="END_LINK" /> של <ph name="URL" /></translation>
<translation id="1156303062776767266">מוצג לך קובץ מקומי או משותף</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> סגר את החיבור באופן בלתי צפוי.</translation>
+<translation id="115926840831309955">‏יש לבדוק שה-CVC תקין ולנסות שוב, או לעדכן את תאריך התפוגה</translation>
<translation id="1161325031994447685">‏להתחבר מחדש אל ה-Wi-Fi</translation>
<translation id="1165039591588034296">שגיאה</translation>
<translation id="1175364870820465910">הדפסה…</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">‏"יש תוכנה במחשב שלך שמונעת מ-Chrome להתחבר באופן מאובטח אל האינטרנט" (מחשבי Windows בלבד)</translation>
<translation id="1294154142200295408">וריאציות של שורת פקודה</translation>
<translation id="129553762522093515">נסגרו לאחרונה</translation>
+<translation id="1298536327547837046">סריקה לאיתור תוכנות זדוניות</translation>
<translation id="129863573139666797">‏<ph name="BEGIN_LINK" />נסה לנקות את קובצי ה-Cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">תכונות שהוצאו משימוש</translation>
<translation id="1320233736580025032">Prc1 (Envelope)‎</translation>
<translation id="132301787627749051">חיפוש תמונה בלוח</translation>
<translation id="1323433172918577554">הצגת פריטים נוספים</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">תיכף נתחבר…</translation>
<translation id="1529521330346880926">10x15 (Envelope)‎</translation>
+<translation id="1530707389502320859">‏האתר שניסית לבקר בו נראה כמו אתר מזויף. תוקפים שמחקים אתרים לפעמים משתמשים בכתובת ה-URL של האתר המקורי ועושים בה שינויים קלים ביותר כדי שיהיה קשה להבחין בהבדל.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">הדף הזה אומר</translation>
<translation id="153384715582417236">זה הכול בינתיים</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">מערכת הפעלה</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">המסמך גדול מדי ולא ניתן להוסיף לו הערות</translation>
-<translation id="1721312023322545264">עליך לפנות אל <ph name="NAME" /> לקבלת הרשאה לביקור באתר הזה</translation>
<translation id="1721424275792716183">* זהו שדה חובה</translation>
<translation id="1727741090716970331">הוספת מספר כרטיס חוקי</translation>
<translation id="1728677426644403582">אתה מציג את המקור של דף אינטרנט</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">אתרים שנכנסת אליהם וזמני השהייה באתרים האלה</translation>
<translation id="1826516787628120939">מתבצעת בדיקה</translation>
<translation id="1834321415901700177">האתר הזה מכיל תוכניות מזיקות</translation>
+<translation id="1838374766361614909">ניקוי חיפוש</translation>
<translation id="1839551713262164453">אימות ערכי המדיניות נכשל והתרחשו שגיאות</translation>
<translation id="1842969606798536927">לתשלום</translation>
<translation id="1871208020102129563">‏שרת ה-Proxy מוגדר להשתמש בשרתי Proxy קבועים, לא בכתובת אתר של סקריפט ‎.Pac</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">כווץ רשימה</translation>
<translation id="1898423065542865115">סינון</translation>
<translation id="1914326953223720820">שירות לפתיחת קבצים דחוסים</translation>
+<translation id="1915697529809968049">‏האם להשתמש ב-Touch ID במקום ב-CVC?</translation>
<translation id="1916770123977586577">כדי להחיל על האתר את ההגדרות המעודכנות, טען מחדש את הדף</translation>
<translation id="1919345977826869612">מודעות</translation>
<translation id="1919367280705858090">עזרה לגבי הודעות שגיאה ספציפיות</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">סימניות של <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">שגיאה בעריכה בסידרה</translation>
<translation id="1974060860693918893">מתקדם</translation>
+<translation id="1974883374937189061">‏אפשר לעזור לנו לשפר את האבטחה של Chrome על-ידי שליחת <ph name="BEGIN_WHITEPAPER_LINK" />כתובות URL של חלק מהדפים שאליהם נכנסת, מידע מוגבל על המערכת וחלק מתכני הדפים<ph name="END_WHITEPAPER_LINK" /> אל Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">גרסת קושחה</translation>
<translation id="1981206234434200693">‏ניקוי נתוני היסטוריית הגלישה של Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ואפליקציה אחת נוספת}two{ושתי אפליקציות נוספות}many{ו-# אפליקציות נוספות}other{ו-# אפליקציות נוספות}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">עליך להזין שנת תפוגה חוקית</translation>
<translation id="2212735316055980242">לא נמצאה מדיניות</translation>
<translation id="2213606439339815911">מאחזר רשומות...</translation>
+<translation id="2215727959747642672">עריכת קובץ</translation>
<translation id="2218879909401188352">תוקפים שמשתמשים עכשיו ב-<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> עלולים להתקין יישומים מסוכנים ולגרום נזק למכשיר שלך, להגדיל את החיובים שלך על החבילה לנייד או לגנוב את המידע האישי שלך. <ph name="BEGIN_LEARN_MORE_LINK" />מידע נוסף<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">אין אינטרנט</translation>
<translation id="2230458221926704099">תקן את החיבור באמצעות <ph name="BEGIN_LINK" />אפליקציית הבדיקה<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">שלח עכשיו</translation>
+<translation id="2248949050832152960">‏שימוש ב-WebAuthn</translation>
<translation id="225207911366869382">ערך זה הוצא משימוש עבור מדיניות זו.</translation>
<translation id="2257315177824333709">מצטערים, אי אפשר לשמור את הכרטיס שלך עכשיו</translation>
<translation id="2262243747453050782">‏שגיאת HTTP</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">כתובת אתר לא חוקית של חיפוש</translation>
<translation id="2482878487686419369">התראות</translation>
<translation id="248348093745724435">מדיניות המחשב</translation>
-<translation id="2485387744899240041">שמות משתמש למכשיר ולדפדפן שלך</translation>
<translation id="2491120439723279231">אישור השרת מכיל שגיאות.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">‏מנתח JSON</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">חזרה</translation>
<translation id="2503184589641749290">כרטיסי חיוב וכרטיסים משולמים מראש שהסוחר מקבל</translation>
<translation id="2505268675989099013">הגנה על החשבון</translation>
+<translation id="2515335152965840738">התעלמות</translation>
<translation id="2515629240566999685">לבדוק את האות באזור שלך</translation>
<translation id="2523886232349826891">הכרטיס יישמר רק במכשיר הזה</translation>
<translation id="2524461107774643265">הוספת עוד מידע</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">שלח</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{אין}=1{סיסמה אחת (עבור <ph name="DOMAIN_LIST" />)}=2{שתי סיסמאות (עבור <ph name="DOMAIN_LIST" />)}many{# סיסמאות (עבור <ph name="DOMAIN_LIST" />)}other{# סיסמאות (עבור <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">סגירת כרטיסיות או יישומים אחרים</translation>
-<translation id="267371737713284912">הקשה על <ph name="MODIFIER_KEY_DESCRIPTION" /> מבטלת את הפעולה</translation>
<translation id="2674170444375937751">האם אתה בטוח שברצונך להסיר דפים אלו מההיסטוריה שלך?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">יציאה</translation>
@@ -334,12 +342,14 @@
<translation id="2704283930420550640">הערך לא תואם לפורמט.</translation>
<translation id="2705137772291741111">העותק השמור (בקובץ השמור) של האתר הזה היה בלתי קריא.</translation>
<translation id="2709516037105925701">מילוי אוטומטי</translation>
-<translation id="2712173769900027643">בקש רשות</translation>
<translation id="2713444072780614174">לבן</translation>
<translation id="2720342946869265578">קרוב</translation>
<translation id="2721148159707890343">הבקשה בוצעה בהצלחה</translation>
<translation id="2728127805433021124">האישור של השרת נחתם באמצעות אלגוריתם של חתימה חלשה.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />מפעיל את אבחון הקישוריות<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">הפעלת התכונות האלה עלולה לגרום לאובדן נתוני גלישה או
+ לפגיעה באבטחה או בפרטיות שלך. התכונות המופעלות משפיעות על כל מי
+ שמשתמש בדפדפן הזה.</translation>
<translation id="2735043616039983645">קיים יותר ממקור אחד עם ערכים סותרים עבור המדיניות הזו!</translation>
<translation id="2738330467931008676">בחירת כתובת לאיסוף</translation>
<translation id="2740531572673183784">אישור</translation>
@@ -350,16 +360,15 @@
<translation id="2784949926578158345">החיבור עבר איפוס.</translation>
<translation id="2788784517760473862">כרטיסי אשראי שהסוחר מקבל</translation>
<translation id="2792012897584536778">מנהלי מערכת של המכשיר הזה הגדירו אישורי אבטחה שעשויים לאפשר להם לראות את התוכן של אתרים שביקרת בהם.</translation>
-<translation id="2794233252405721443">אתר חסום</translation>
<translation id="2799020568854403057">האתר הבא מכיל יישומים מזיקים</translation>
<translation id="2799223571221894425">הפעל מחדש</translation>
<translation id="2803306138276472711">‏לאחרונה, 'גלישה בטוחה של Google‏' <ph name="BEGIN_LINK" />זיהתה תוכנה זדונית<ph name="END_LINK" /> באתר <ph name="SITE" />. אתרים שבדרך כלל נחשבים לבטוחים נדבקים לעתים בתוכנה זדונית.</translation>
+<translation id="2815364696811431560">יציאה מהאתר</translation>
<translation id="2824775600643448204">שורת חיפוש וכתובות אתרים</translation>
<translation id="2826760142808435982">החיבור מוצפן ומאומת באמצעות <ph name="CIPHER" /> ומשתמש ב-<ph name="KX" /> כמנגנון להחלפת מפתחות.</translation>
<translation id="2835170189407361413">ניקוי הטופס</translation>
<translation id="2847118875340931228">פתיחת חלון גלישה בסתר</translation>
<translation id="2850739647070081192">Invite (Envelope)‎</translation>
-<translation id="2851634818064021665">יש צורך בהרשאה כדי להיכנס אל האתר הזה</translation>
<translation id="2856444702002559011">ייתכן שתוקפים מנסים לגנוב את הפרטים שלך מהאתר <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (לדוגמה, סיסמאות, הודעות או כרטיסי אשראי). <ph name="BEGIN_LEARN_MORE_LINK" />מידע נוסף<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">לשמור את הכרטיס?</translation>
@@ -384,6 +393,7 @@
<translation id="2985306909656435243">‏אם האפשרות תופעל, Chromium יאחסן עותק של הכרטיס שלך במכשיר הזה למילוי מהיר יותר של טפסים.</translation>
<translation id="2985398929374701810">עליך להזין כתובת חוקית</translation>
<translation id="2986368408720340940">שיטת האיסוף הזו אינה זמינה. עליך לבחור שיטה אחרת.</translation>
+<translation id="2987034854559945715">אין תכונות תואמות</translation>
<translation id="2991174974383378012">שיתוף עם אתרים</translation>
<translation id="2991571918955627853">‏נכון לעכשיו אי אפשר לבקר באתר <ph name="SITE" /> מאחר שנעשה בו שימוש ב-HSTS. שגיאות רשת ומתקפות הן בדרך כלל זמניות, כך שהדף הזה יחזור כנראה לפעול מאוחר יותר.</translation>
<translation id="3005723025932146533">הצג עותק שמור</translation>
@@ -394,6 +404,7 @@
<translation id="3024663005179499861">סוג המדיניות שגוי</translation>
<translation id="3037605927509011580">אוי, לא!</translation>
<translation id="3041612393474885105">פרטי אישור</translation>
+<translation id="3057676462092457419">‏המצב <ph name="SECURE_DNS_MODE_SECURE" /> של DnsOverHttps לא נתמך עדיין, המצב הועבר להגדרה <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)‎</translation>
<translation id="3061707000357573562">שירות תיקון</translation>
<translation id="3064966200440839136">בחרת לצאת ממצב גלישה בסתר כדי לשלם באמצעות יישום חיצוני. להמשיך?</translation>
@@ -419,6 +430,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> בשרת <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">בטל תשלום</translation>
<translation id="3207960819495026254">מסומן בסימניה</translation>
+<translation id="3209034400446768650">כניסה לדף עשויה להיות כרוכה בתשלום</translation>
<translation id="3225919329040284222">השרת הציג אישור שאינו תואם את הציפיות המובנות. ציפיות אלה נכללות עבור אתרי אינטרנט מסוימים בעלי אבטחה גבוהה כדי להגן עליך.</translation>
<translation id="3226128629678568754">לחץ על לחצן הטעינה מחדש כדי לשלוח מחדש את הנתונים הדרושים לטעינת הדף.</translation>
<translation id="3227137524299004712">מיקרופון</translation>
@@ -426,7 +438,6 @@
<translation id="3229041911291329567">פרטי גרסה של המכשיר והדפדפן</translation>
<translation id="323107829343500871">הזן את קוד האימות של הכרטיס <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">זהה תמיד תוכן חשוב באתר זה</translation>
-<translation id="3254409185687681395">הוסף את הדף לסימניות</translation>
<translation id="3270847123878663523">&amp;ביטול של שינוי סדר</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">הוספה של השם המופיע בכרטיס</translation>
@@ -436,7 +447,6 @@
<translation id="3320021301628644560">הוספה של כתובת לחיוב</translation>
<translation id="3324983252691184275">ארגמן</translation>
<translation id="3338095232262050444">מאובטח</translation>
-<translation id="3345135638360864351">לא ניתן היה לשלוח אל <ph name="NAME" /> את הבקשה שלך לגשת לאתר הזה. נסה שוב.</translation>
<translation id="3355823806454867987">‏שנה הגדרות שרת Proxy...</translation>
<translation id="3361596688432910856">‏Chrome <ph name="BEGIN_EMPHASIS" />לא ישמור<ph name="END_EMPHASIS" /> את המידע הבא:
<ph name="BEGIN_LIST" />
@@ -470,18 +480,15 @@
<translation id="3462200631372590220">הסתר פרטים מתקדמים</translation>
<translation id="3467763166455606212">עליך לציין את שם בעל הכרטיס</translation>
<translation id="3468054117417088249">‏<ph name="TAB_SWITCH_SUFFIX" />, פתוחה כרגע, יש להקיש על Tab ולאחר מכן על Enter כדי לעבור לכרטיסייה הפתוחה</translation>
-<translation id="3479539252931486093">האם זה קרה באופן בלתי צפוי? <ph name="BEGIN_LINK" />ספר לנו על כך<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">לא עכשיו</translation>
<translation id="3484560055331845446">‏ייתכן שמישהו אחר ישלול את הגישה שלך לחשבון Google. לגלישה בטוחה ב-Chrome, מומלץ לשנות את הסיסמה עכשיו.</translation>
<translation id="3495081129428749620">חיפוש בדף
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">לא הצלחנו ליצור קשר עם ההורה שלך. נסה שוב מאוחר יותר.</translation>
<translation id="3512163584740124171">המערכת מתעלמת מהמדיניות הזו כי יש מדיניות אחרת מאותה קבוצה של הגדרות מדיניות שקיבלה עדיפות גבוהה יותר.</translation>
<translation id="3528171143076753409">אישור השרת אינו מהימן.</translation>
<translation id="3528485271872257980">חום כהה</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{לפחות פריט אחד במכשירים מסונכרנים}=1{פריט אחד (ופריטים נוספים במכשירים מסונכרנים)}two{שני פריטים (ופריטים נוספים במכשירים מסונכרנים)}many{# פריטים (ופריטים נוספים במכשירים מסונכרנים)}other{# פריטים (ופריטים נוספים במכשירים מסונכרנים)}}</translation>
<translation id="3539171420378717834">שמור עותק של הכרטיס הזה במכשיר הזה</translation>
-<translation id="3556433843310711081">המנהל שלך יכול לבטל בשבילך את החסימה</translation>
<translation id="3566021033012934673">החיבור שלך אינו פרטי</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">דף מוטמע באתר <ph name="SITE" /> אומר</translation>
@@ -509,6 +516,7 @@
<translation id="3678529606614285348">‏פתח את הדף בחלון חדש של גלישה בסתר (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">דוח קריסה תועד ב-<ph name="CRASH_TIME" />, הועלה ב-<ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">פרטי אישור</translation>
+<translation id="3701427423622901115">האיפוס אושר.</translation>
<translation id="3704162925118123524">ייתכן שתוצג דרישה להיכנס לדף ההתחברות של הרשת שבה אתה משתמש.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">טוען...</translation>
@@ -525,6 +533,7 @@
<translation id="3748148204939282805">תוקפים באתר <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> עלולים להונות אותך כדי לגרום לך לבצע פעולות מסוכנות, כמו התקנת תוכנה או חשיפת מידע אישי (לדוגמה, סיסמאות, מספרי טלפון או כרטיסי אשראי). <ph name="BEGIN_LEARN_MORE_LINK" />מידע נוסף<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">התרגום נכשל עקב שגיאת שרת.</translation>
<translation id="3759461132968374835">לא התקבלו דיווחים על קריסות לאחרונה. קריסות שהתרחשו בזמן שאפשרות הדיווח על קריסות היתה מושבתת לא יופיעו כאן.</translation>
+<translation id="3760561303380396507">‏האם להשתמש ב-Windows Hello במקום ב-CVC?</translation>
<translation id="3761718714832595332">הסתרת הסטטוס</translation>
<translation id="3765032636089507299">הדף 'גלישה בטוחה' נמצא כרגע בבנייה.</translation>
<translation id="3778403066972421603">‏האם ברצונך לשמור את הכרטיס בחשבון Google שלך ובמכשיר הזה?</translation>
@@ -534,6 +543,7 @@
<translation id="3789155188480882154">גודל 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)‎</translation>
<translation id="3807873520724684969">תוכן מזיק נחסם.</translation>
+<translation id="3808375843007691220">אזהרה: תכונות ניסיוניות לפניך!</translation>
<translation id="3810973564298564668">נהל</translation>
<translation id="382518646247711829">‏אם אתה משתמש בשרת Proxy...</translation>
<translation id="3828924085048779000">אין אפשרות להשתמש במשפט-סיסמה ריק.</translation>
@@ -542,11 +552,11 @@
<translation id="3858027520442213535">עדכן את התאריך והשעה</translation>
<translation id="3884278016824448484">מזהה מכשיר מתנגש</translation>
<translation id="3885155851504623709">פאריש</translation>
-<translation id="3886446263141354045">הבקשה שלך לגשת לאתר הזה נשלחה אל <ph name="NAME" /></translation>
<translation id="3890664840433101773">הוספת כתובת אימייל</translation>
<translation id="3901925938762663762">תוקף הכרטיס פג</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">‏האם להשתמש ב-WebAuthn במקום ב-CVC?</translation>
<translation id="3946209740501886391">שאל תמיד באתר הזה</translation>
<translation id="3949571496842715403">‏השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />; אישור האבטחה שלו לא מציין ערכי Subject Alternative Name. ייתכן שהסיבה לכך היא תצורה שגויה או תוקף המיירט את החיבור שלך.</translation>
<translation id="3949601375789751990">היסטוריית הגלישה שלך מופיעה כאן</translation>
@@ -557,11 +567,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ללא}=1{מאתר אחד }two{משני אתרים }many{מ-# אתרים }other{מ-# אתרים }}</translation>
<translation id="397105322502079400">מחשב...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> חסום</translation>
+<translation id="3981540111851280311">‏הכלי להגנה מפני איומים של Chrome Enterprise הופעל על ידי <ph name="ENROLLMENT_DOMAIN" /> בדפדפן שלך. לכלי להגנה מפני איומים של Chrome Enterprise יש גישה לחלק מהנתונים שלך.</translation>
<translation id="3987940399970879459">‏פחות מ-‎1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{דף אינטרנט קרוב אחד}two{# דפי אינטרנט קרובים}many{# דפי אינטרנט קרובים}other{# דפי אינטרנט קרובים}}</translation>
<translation id="4030383055268325496">&amp;ביטול הוספה</translation>
<translation id="4032320456957708163">הדפדפן שלך מנוהל על ידי <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">הקישור שנפתח מוביל לאתר שבדרך כלל לא נכנסים אליו. ייתכן שמדובר בניסיון לבלבל אותך.</translation>
<translation id="4058922952496707368">מפתח "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)‎</translation>
<translation id="4067947977115446013">הוספה של כתובת חוקית</translation>
@@ -574,6 +584,7 @@
<translation id="4103249731201008433">המספר הסידורי של המכשיר אינו חוקי</translation>
<translation id="410351446219883937">הפעלה אוטומטית</translation>
<translation id="4103763322291513355">‏היכנס לכתובת &lt;strong&gt;chrome://policy&lt;/strong&gt; כדי לראות רשימה של כתובות אתרים שנמנעה אליהם הגישה, כמו גם תקנונים אחרים שנאכפו על ידי מנהל המערכת שלך.</translation>
+<translation id="4108231218301530806">בפעם הבאה יש להשתמש בטביעת אצבע לאימות הכרטיס הזה.</translation>
<translation id="4110652170750985508">בדיקת התשלום</translation>
<translation id="4112140312785995938">הרצה לאחור</translation>
<translation id="4116663294526079822">אפשר תמיד באתר זה</translation>
@@ -588,6 +599,7 @@
<translation id="4171400957073367226">חתימת אימות לא חוקית</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{פריט אחד (<ph name="ITEM_COUNT" />) נוסף}two{<ph name="ITEM_COUNT" /> פריטים נוספים}many{<ph name="ITEM_COUNT" /> פריטים נוספים}other{<ph name="ITEM_COUNT" /> פריטים נוספים}}</translation>
+<translation id="4176463684765177261">מושבת</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">‏כדי לשלם מהר יותר בפעם הבאה, אפשר להוסיף לחשבון Google את פרטי הכרטיס ואת הכתובת לחיוב.</translation>
<translation id="4196861286325780578">&amp;ביצוע מחדש של העברה</translation>
@@ -624,6 +636,7 @@
<translation id="4277028893293644418">איפוס סיסמה</translation>
<translation id="4279811152705618813">ה-<ph name="DEVICE_TYPE" /> מנוהל על-ידי <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{‏הכרטיס הזה נשמר בחשבון Google שלך}two{‏הכרטיסים האלה נשמרו בחשבון Google שלך}many{‏הכרטיסים האלה נשמרו בחשבון Google שלך}other{‏הכרטיסים האלה נשמרו בחשבון Google שלך}}</translation>
+<translation id="428847186335018806">‏סריקת קבצים שהורדת או העלית ב-Chrome.</translation>
<translation id="42981349822642051">הרחבה</translation>
<translation id="4302965934281694568">Chou3 (Envelope)‎</translation>
<translation id="4305817255990598646">מעבר</translation>
@@ -653,7 +666,6 @@
<translation id="4435702339979719576">Postcard)‎</translation>
<translation id="443673843213245140">‏השימוש בשרת Proxy הושבת, אך צויינה תצורת שרת Proxy מפורשת.</translation>
<translation id="445100540951337728">כרטיסי חיוב שהסוחר מקבל</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> – התנהגות חשודה</translation>
<translation id="4466881336512663640">השינויים בטופס יתבטלו. להמשיך?</translation>
<translation id="4477350412780666475">הטראק הבא</translation>
<translation id="4482953324121162758">האתר הזה לא יתורגם.</translation>
@@ -680,6 +692,7 @@
<translation id="4594403342090139922">&amp;ביטול מחיקה</translation>
<translation id="4597348597567598915">גודל 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)‎</translation>
+<translation id="464342062220857295">תכונות חיפוש</translation>
<translation id="4646534391647090355">אני רוצה לעבור לשם עכשיו</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />; אישור האבטחה שלו מכיל שגיאות. ייתכן שהסיבה לכך היא הגדרה שגויה או תוקף המיירט את החיבור שלך.</translation>
@@ -688,7 +701,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)‎</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">החיבור נקטע</translation>
-<translation id="471880041731876836">אין לך הרשאה להיכנס אל האתר הזה</translation>
<translation id="4722547256916164131">‏<ph name="BEGIN_LINK" />מפעיל את אבחון הרשת של Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">טען מדיניות מחדש</translation>
<translation id="4728558894243024398">פלטפורמה</translation>
@@ -720,7 +732,6 @@ Del</translation>
<translation id="4816492930507672669">התאמה לדף</translation>
<translation id="4850886885716139402">הצגה</translation>
<translation id="4854362297993841467">שיטת המסירה הזו אינה זמינה. עליך לבחור שיטה אחרת.</translation>
-<translation id="4858792381671956233">שאלת את ההורים שלך אם אתה יכול לגשת לאתר הזה</translation>
<translation id="4864052566555297930">טיפ בנושא בטיחות:</translation>
<translation id="4876188919622883022">תצוגה נקייה</translation>
<translation id="4876305945144899064">אין שם משתמש</translation>
@@ -744,7 +755,9 @@ Del</translation>
<translation id="4974590756084640048">הפעל מחדש אזהרות</translation>
<translation id="4984339528288761049">Prc5 (Envelope)‎</translation>
<translation id="4989163558385430922">אני רוצה לראות הכול</translation>
+<translation id="4989542687859782284">לא זמין</translation>
<translation id="4989809363548539747">הפלאגין הזה אינו נתמך</translation>
+<translation id="4995216769782533993">יש לאמת את קוד האבטחה כדי לשתף פרטי כרטיס עם האתר הזה</translation>
<translation id="5002932099480077015">‏אם האפשרות הזו תופעל, Chrome יאחסן עותק של הכרטיס שלך במכשיר הזה למילוי מהיר יותר של טפסים.</translation>
<translation id="5015510746216210676">שם המחשב:</translation>
<translation id="5017554619425969104">טקסט שהעתקת</translation>
@@ -773,6 +786,7 @@ Del</translation>
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 סיביות)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">אימות הכרטיס</translation>
<translation id="5135404736266831032">ניהול כתובות...</translation>
<translation id="5138227688689900538">פחות אפליקציות</translation>
<translation id="5141240743006678641">‏הצפנת סיסמאות מסונכרנות באמצעות פרטי הכניסה שלך ל-Google</translation>
@@ -799,6 +813,7 @@ Del</translation>
<translation id="5251803541071282808">ענן</translation>
<translation id="5252000469029418751">C7 (Envelope)‎</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">רק הבעלים יכול להגדיר תכונות שחלות על כל המערכת: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">‏אזהרה: המדיניות הזו לא עברה מיזוג בהתאם למדיניות PolicyDictionaryMultipleSourceMergeList, מאחר שהיא לא חלק מכללי מדיניות המילון שניתן למזג.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">סיום</translation>
@@ -822,7 +837,6 @@ Del</translation>
<translation id="536296301121032821">אחסון הגדרות המדיניות נכשל</translation>
<translation id="5371425731340848620">עדכון כרטיס</translation>
<translation id="5377026284221673050">‏"השעון מאחר", "השעון מקדים" או "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">ייתכן שבדף הזה יש תוכן שנועד להטעות אותך, לגנוב ממך מידע אישי או לגרום נזק למכשיר שלך. יש להיזהר כשמזינים מידע אישי או כשפותחים קבצים שהורדו.</translation>
<translation id="5384855140246857529">כדי להשתמש בכרטיסים שלך בכל המכשירים, יש להיכנס לחשבון ולהפעיל את הסנכרון</translation>
<translation id="5386426401304769735">‏שרשרת האישורים של האתר הזה כוללת אישור שנחתם באמצעות SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -836,6 +850,8 @@ Del</translation>
<translation id="5457113250005438886">לא חוקי</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}two{<ph name="CONTACT_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}many{<ph name="CONTACT_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;ביצוע מחדש של עריכה</translation>
+<translation id="5473728911100096288">אם בוחרים להפעיל את התכונות האלו ולהשתמש בהן, חשוב לדעת שאלו
+ תכונות שהוצאו משימוש. הן לא יופיעו בגרסאות עתידיות.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)‎</translation>
<translation id="5481076368049295676">ייתכן שהתוכן הזה מכיל אמצעים שינסו להתקין תוכנה מסוכנת, שגונבת או מוחקת את המידע שלך. <ph name="BEGIN_LINK" />הצג בכל זאת<ph name="END_LINK" /></translation>
<translation id="54817484435770891">הוספה של כתובת חוקית</translation>
@@ -860,7 +876,6 @@ Del</translation>
<translation id="5570825185877910964">הגנה על החשבון</translation>
<translation id="5571083550517324815">לא ניתן לבצע איסוף מהכתובת הזו. עליך לבחור כתובת אחרת.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{אחד נמצא בשימוש}two{שניים נמצאים בשימוש}many{# נמצאים בשימוש}other{# נמצאים בשימוש}})</translation>
-<translation id="5572851009514199876">‏תחילה היכנס לחשבונך ב-Chrome כדי לאפשר ל-Chrome לבדוק אם יש לך הרשאה לגשת לאתר הזה.</translation>
<translation id="5580958916614886209">בדוק את חודש התפוגה ונסה שוב</translation>
<translation id="5586446728396275693">לא נשמרו כתובות</translation>
<translation id="5595485650161345191">עריכת כתובת</translation>
@@ -868,6 +883,7 @@ Del</translation>
<translation id="560412284261940334">ניהול אינו נתמך</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">‏האתר הזה עשוי להיות מזויף או לשמש להונאה ההמלצה של Chrome היא לצאת ממנו עכשיו.</translation>
<translation id="5610142619324316209">לבדוק את החיבור</translation>
<translation id="5610807607761827392">ב<ph name="BEGIN_LINK" />הגדרות<ph name="END_LINK" /> תוכל לנהל את האפשרויות של כרטיסים וכתובות.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> הפנה אותך מחדש פעמים רבות מדי.</translation>
@@ -891,11 +907,11 @@ Del</translation>
<translation id="5720705177508910913">משתמש נוכחי:</translation>
<translation id="5728056243719941842">C5 (Envelope)‎</translation>
<translation id="5730040223043577876">‏אם הזנת את הסיסמה שלך באתרים אחרים, ההמלצה של Chrome היא לאפס אותה.</translation>
-<translation id="5732392974455271431">ההורים שלך יכולים לבטל בשבילך את החסימה</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{‏שמירת הכרטיס בחשבון Google}two{‏שמירת הכרטיסים בחשבון Google}many{‏שמירת הכרטיסים בחשבון Google}other{‏שמירת הכרטיסים בחשבון Google}}</translation>
<translation id="5763042198335101085">עליך להזין כתובת אימייל חוקית</translation>
<translation id="5765072501007116331">עליך לבחור כתובת כדי לראות שיטות מסירה ודרישות</translation>
<translation id="5778550464785688721">‏שליטה מלאה במכשירי MIDI</translation>
+<translation id="5781136890105823427">הניסוי מופעל</translation>
<translation id="578305955206182703">ענבר</translation>
<translation id="57838592816432529">השתקה</translation>
<translation id="5784606427469807560">הייתה בעיה באישור הכרטיס. בדוק את החיבור לאינטרנט ונסה שוב.</translation>
@@ -912,13 +928,16 @@ Del</translation>
<translation id="5860033963881614850">כבוי</translation>
<translation id="5863847714970149516">בדף הבא עשויה להיות דרישה לתשלום</translation>
<translation id="5866257070973731571">הוספת מספר טלפון</translation>
+<translation id="5866898949289125849">הדף המוצג הוא של הכלים למפתחים</translation>
<translation id="5869405914158311789">לא ניתן לגשת לאתר הזה</translation>
<translation id="5869522115854928033">סיסמאות שמורות</translation>
<translation id="5887400589839399685">הכרטיס נשמר</translation>
<translation id="5893752035575986141">אפשר לשלם באמצעות כרטיסי אשראי.</translation>
+<translation id="5895138241574237353">הפעל מחדש</translation>
<translation id="5901630391730855834">צהוב</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (מסונכרנים)</translation>
<translation id="5916664084637901428">פועל</translation>
+<translation id="59174027418879706">מופעל</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">‏לשמור את הכרטיס בחשבון Google?</translation>
<translation id="5922853866070715753">עוד רגע מסיימים</translation>
@@ -952,6 +971,7 @@ Del</translation>
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">רוצה להשתמש בכרטיסים בכל המכשירים שברשותך?</translation>
<translation id="6059925163896151826">‏מכשירי USB</translation>
+<translation id="6060009363608157444">‏מצב DnsOverHttps לא חוקי.</translation>
<translation id="6080696365213338172">ניגשת לתוכן באמצעות אישור שהוענק על ידי מנהל מערכת. מנהל המערכת שלך עשוי ליירט נתונים שתספק ל-<ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">הוספת הערה</translation>
<translation id="610911394827799129">‏ייתכן שלחשבון Google שלך משויכים סוגים אחרים של היסטוריית גלישה בכתובת <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1000,13 +1020,12 @@ Del</translation>
<translation id="6404511346730675251">ערוך סימניה</translation>
<translation id="6406765186087300643">C0 (Envelope)‎</translation>
<translation id="6410264514553301377">הזן את תאריך התפוגה ואת קוד האימות של <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">שאלת אחד מהוריך אם אתה יכול לבקר באתר הזה</translation>
<translation id="6415778972515849510">‏בעזרת Chromium אפשר להגן על חשבון Google ולשנות את הסיסמה.</translation>
-<translation id="6417515091412812850">לא ניתן לבדוק אם האישור נשלל.</translation>
<translation id="6431585503458005759">לא לאחסן</translation>
<translation id="6433490469411711332">עריכת הפרטים ליצירת קשר</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> סירב להתחבר.</translation>
<translation id="6434309073475700221">התעלם</translation>
+<translation id="6435221585574090192">‏הנתונים של אירועי האבטחה שסומנו על-ידי הכלי להגנה מפני איומים של Chrome Enterprise ישותפו עם מנהל המערכת. הנתונים האלה עשויים לכלול כתובות URL של דפים, שמות ומטא-נתונים של קבצים, שם המשתמש במכשיר ושם המשתמש ב-Chrome.</translation>
<translation id="6440503408713884761">המערכת מתעלמת מהפריט</translation>
<translation id="6446163441502663861">Kahu (Envelope)‎</translation>
<translation id="6446608382365791566">הוסף מידע</translation>
@@ -1015,20 +1034,19 @@ Del</translation>
<translation id="6465306955648956876">ניהול סיסמאות...</translation>
<translation id="647261751007945333">מדיניות המכשיר</translation>
<translation id="6476284679642588870">ניהול אמצעי תשלום</translation>
-<translation id="6477321094435799029">‏Chrome זיהה קוד חריג בדף הזה וחסם אותו כדי להגן על המידע הפרטי שלך (כגון סיסמאות, מספרי טלפון ומספרי כרטיסי אשראי).</translation>
<translation id="6489534406876378309">התחל להעלות קריסות</translation>
<translation id="6499038740797743453">לאפס את הסיסמה?</translation>
<translation id="6507833130742554667">אפשר לשלם באמצעות כרטיסי אשראי וחיוב.</translation>
<translation id="650855688985305916">כן, לאחסן</translation>
<translation id="6508722015517270189">‏הפעלה מחדש של Chrome</translation>
<translation id="6517596291481585650">אזהרה! המדיניות הזו לא עברה מיזוג בהתאם למדיניות, מאחר שהיא אינה רשימה.</translation>
+<translation id="6518133107902771759">אימות</translation>
<translation id="6521745193039995384">לא פעילה</translation>
<translation id="6529602333819889595">&amp;ביצוע מחדש של מחיקה</translation>
<translation id="6534179046333460208">הצעות לאינטרנט הפיזי</translation>
<translation id="6545864417968258051">‏סריקת Bluetooth</translation>
<translation id="6554795675067793129">החשבון שלך מנוהל על-ידי <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">בצע מחדש</translation>
-<translation id="6563469144985748109">המנהל שלך עדיין לא אישר זאת</translation>
<translation id="6569060085658103619">אתה מציג דף של תוסף</translation>
<translation id="6578796323535178455">C2 (Envelope)‎</translation>
<translation id="6579990219486187401">ורוד בהיר</translation>
@@ -1046,11 +1064,13 @@ Del</translation>
<translation id="6643016212128521049">ניקוי</translation>
<translation id="6644283850729428850">מדיניות זו אינה בתוקף.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{ללא}=1{‏מאתר אחד (לא תבוצע יציאה מחשבון Google שלך.)}two{‏מ-# אתרים (לא תבוצע יציאה מחשבון Google שלך.)}many{‏מ-# אתרים (לא תבוצע יציאה מחשבון Google שלך.)}other{‏מ-# אתרים (לא תבוצע יציאה מחשבון Google שלך.)}}</translation>
+<translation id="6652101503459149953">‏שימוש ב-Windows Hello</translation>
<translation id="6657585470893396449">סיסמה</translation>
<translation id="6670613747977017428">חזרה לדף הבטוח.</translation>
<translation id="6671697161687535275">‏האם להסיר מ-Chromium הצעות לטפסים?</translation>
<translation id="6685834062052613830">צא והשלם את ההגדרה</translation>
<translation id="6689271823431384964">‏מאחר שנכנסת לחשבון, Chrome מציע לשמור את הכרטיסים שלך בחשבון Google. אפשר לשנות את ההתנהגות הזאת בהגדרות. שם בעל הכרטיס מגיע מהחשבון שלך.</translation>
+<translation id="6707256370811247129">‏סריקת התוכן של המטמון והקבצים שמעלים או מורידים ב-Chrome.</translation>
<translation id="6710213216561001401">הקודם</translation>
<translation id="6710594484020273272">&lt;הקלד מונח חיפוש&gt;</translation>
<translation id="671076103358959139">אסימון הרשמה:</translation>
@@ -1058,10 +1078,10 @@ Del</translation>
<translation id="6738516213925468394">הנתונים שלך הוצפנו באמצעות<ph name="BEGIN_LINK" />ביטוי סיסמה לסנכרון<ph name="END_LINK" /> בתאריך <ph name="TIME" />. צריך להזין אותו כדי להתחיל את הסנכרון.</translation>
<translation id="674375294223700098">שגיאת אישור שרת לא ידוע.</translation>
<translation id="6744009308914054259">בזמן ההמתנה לחיבור אפשר לעבור אל 'הורדות' כדי לקרוא מאמרים לא מקוונים.</translation>
+<translation id="6747611005629681221">אזהרה: יש כאן תכונות שהוצאו משימוש!</translation>
<translation id="6753269504797312559">ערך מדיניות</translation>
<translation id="6757797048963528358">המכשיר עבר למצב שינה.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)‎</translation>
-<translation id="6778737459546443941">ההורה ששאלת עדיין לא אישר זאת</translation>
<translation id="67862343314499040">סגול סיגלית</translation>
<translation id="6786747875388722282">תוספים</translation>
<translation id="6790428901817661496">הפעל</translation>
@@ -1069,6 +1089,7 @@ Del</translation>
<translation id="681021252041861472">שדה חובה</translation>
<translation id="6810899417690483278">מזהה של התאמה אישית</translation>
<translation id="6825578344716086703">‏ניסית להגיע אל <ph name="DOMAIN" />, אבל השרת הציג אישור שנחתם באמצעות אלגוריתם חתימה חלש (כמו SHA-1). המשמעות היא שפרטי האבטחה שהוצגו על-ידי השרת עלולים להיות מזויפים, וייתכן שהשרת הוא לא השרת שציפית לו (ייתכן שנוצר קשר בינך לבין התוקף).</translation>
+<translation id="6826370046007623921">מניעת אובדן נתונים</translation>
<translation id="6831043979455480757">תרגום</translation>
<translation id="6839929833149231406">אזור</translation>
<translation id="6852204201400771460">לטעון מחדש את האפליקציה?</translation>
@@ -1081,7 +1102,6 @@ Del</translation>
<translation id="6891596781022320156">רמת המדיניות אינה נתמכת.</translation>
<translation id="6895330447102777224">הכרטיס שלך מאושר</translation>
<translation id="6897140037006041989">User agent</translation>
-<translation id="6903319715792422884">‏על-ידי שליחה של חלק מ<ph name="BEGIN_WHITEPAPER_LINK" />פרטי המערכת ותוכן הדפים<ph name="END_WHITEPAPER_LINK" /> אל Google, אפשר לעזור בשיפור של 'גלישה בטוחה'. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">משתמש:</translation>
<translation id="6934672428414710184">‏השם הזה הוא מחשבון Google שלך</translation>
<translation id="6944692733090228304">הזנת את הסיסמה שלך באתר שלא מנוהל על ידי <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. כדי להגן על החשבון, מומלץ לא להשתמש בסיסמה שלך באפליקציות ובאתרים אחרים.</translation>
@@ -1126,6 +1146,7 @@ Del</translation>
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}two{<ph name="PAYMENT_METHOD_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}many{<ph name="PAYMENT_METHOD_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">לבנדר</translation>
<translation id="717330890047184534">‏מזהה GAIA:</translation>
+<translation id="7174545416324379297">משולבת</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}two{<ph name="SHIPPING_OPTION_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}many{<ph name="SHIPPING_OPTION_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ועוד <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">השרת שאליו ביקשת לעבור, <ph name="ORIGIN" />, ביקש להחיל מדיניות אבטחה על כל הבקשות הנשלחות אליו. עם זאת, במקום לספק מדיניות הוא הפנה את הדפדפן לכתובת אתר אחרת. מצב זה מונע מהדפדפן למלא את הבקשה לעבור אל <ph name="SITE" />.</translation>
<translation id="7179323680825933600">שמירה ומילוי של אמצעי תשלום</translation>
@@ -1160,6 +1181,7 @@ Del</translation>
<translation id="7320336641823683070">עזרה בחיבור</translation>
<translation id="733354035281974745">ביטול עקב סשן חשבון מקומי במכשיר</translation>
<translation id="7334320624316649418">&amp;ביצוע מחדש של שינוי סדר</translation>
+<translation id="7337706099755338005">לא זמין בפלטפורמה שלך.</translation>
<translation id="733923710415886693">אישור השרת לא נחשף דרך 'שקיפות אישורים'.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">משויך:</translation>
@@ -1191,7 +1213,6 @@ Del</translation>
<translation id="7440140511386898319">עיון במצב לא מקוון</translation>
<translation id="7441627299479586546">נושא המדיניות שגוי</translation>
<translation id="7442725080345379071">כתום בהיר</translation>
-<translation id="7444046173054089907">האתר הזה חסום</translation>
<translation id="7445762425076701745">לא ניתן לאמת לגמרי את הזהות של השרת שאליו אתה מחובר. אתה מחובר לשרת באמצעות שם שקיים רק ברשת שלך, ושלרשות אישורים חיצונית אין דרך לאמת את בעלותך עליו. מכיוון שחלק מרשויות האישורים ינפיקו אישורים לשמות אלה ללא קשר, אין דרך להבטיח שאתה מחובר לאתר המיועד ואינך גורם תוקף.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />למידע נוסף<ph name="END_LINK" /> על בעיה זו.</translation>
<translation id="7455133967321480974">השתמש בברירת המחדל הכללית (חסום)</translation>
@@ -1213,9 +1234,9 @@ Del</translation>
<translation id="7538364083937897561">A2 (Envelope)‎</translation>
<translation id="7542403920425041731">ברגע שתאשר, פרטי הכרטיס שלך ישותפו עם האתר הזה.</translation>
<translation id="7542995811387359312">מילוי אוטומטי של פרטי כרטיס אשראי מושבת כיוון שטופס זה אינו משתמש בחיבור מאובטח.</translation>
-<translation id="7543525346216957623">יש לבקש רשות מההורים</translation>
<translation id="7548892272833184391">פתרון שגיאות חיבור</translation>
<translation id="7549584377607005141">דף אינטרנט זה זקוק לנתונים שהזנת קודם לכן כדי שהוא יוצג כראוי. ניתן שוב את הנתונים, אך פעולה זו תגרום לחזרה על כל פעולה שדף זה ביצע בעבר.</translation>
+<translation id="7550637293666041147">‏שם המשתמש במכשיר ושם המשתמש ב-Chrome</translation>
<translation id="7552846755917812628">אולי הטיפים האלו יעזרו לך:</translation>
<translation id="7554791636758816595">כרטיסייה חדשה</translation>
<translation id="7564049878696755256">‏הגישה שלך לחשבון <ph name="ORG_NAME" /> עשויה להישלל והזהות שלך עשויה להיגנב. ההמלצה של Chrome היא לשנות את הסיסמה עכשיו.</translation>
@@ -1230,6 +1251,7 @@ Del</translation>
<translation id="7610193165460212391">הערך מחוץ לטווח <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">תפוגה: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">‏יש לך כבר נתונים שהוצפנו באמצעות גירסה אחרת של סיסמת חשבון Google שלך. הזן אותה למטה.</translation>
+<translation id="7625784245512586808">‏הכלי להגנה מפני איומים של Chrome Enterprise</translation>
<translation id="7633909222644580952">נתוני ביצועים ודוחות קריסה</translation>
<translation id="7637571805876720304">‏האם להסיר מ-Chromium את כרטיס האשראי?</translation>
<translation id="7638605456503525968">יציאות טוריות</translation>
@@ -1242,7 +1264,6 @@ Del</translation>
<translation id="7668654391829183341">מכשיר לא ידוע</translation>
<translation id="7669271284792375604">תוקפים באתר הזה עשויים לגרום לך, בדרכי מרמה, להתקין תוכניות שיפגעו בחוויית הגלישה שלך (לדוגמה, על ידי שינוי דף הבית או הצגת מודעות נוספות באתרים שבהם אתה מבקר).</translation>
<translation id="7676643023259824263">חיפוש טקסט בלוח, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">פלטפורמה וענן</translation>
<translation id="7681101578153515023">שינוי מנוע החיפוש</translation>
<translation id="7682287625158474539">משלוח</translation>
<translation id="7687186412095877299">ממלא בטופסי תשלום את אמצעי התשלום ששמרת</translation>
@@ -1257,7 +1278,6 @@ Del</translation>
<translation id="7723047071702270851">עריכת כרטיס</translation>
<translation id="774634243536837715">תוכן מסוכן נחסם.</translation>
<translation id="7752995774971033316">ללא ניהול</translation>
-<translation id="7755287808199759310">אחד מההורים שלך יכול לבטל בשבילך את החסימה</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ייתכן שחומת אש או תוכנת אנטי-וירוס חסמו את החיבור.</translation>
<translation id="7759163816903619567">דומיין תצוגה:</translation>
@@ -1301,7 +1321,6 @@ Del</translation>
<translation id="8004582292198964060">דפדפן</translation>
<translation id="8009225694047762179">ניהול סיסמאות</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{הכרטיס הזה יישמר יחד עם הכתובת שלו לחיוב. יתאפשר לך להשתמש בו לאחר התחברות אל <ph name="USER_EMAIL" />.}two{הכרטיסים האלה יישמרו יחד עם הכתובות שלהם לחיוב. יתאפשר לך להשתמש בהם לאחר התחברות אל <ph name="USER_EMAIL" />.}many{הכרטיסים האלה יישמרו יחד עם הכתובות שלהם לחיוב. יתאפשר לך להשתמש בהם לאחר התחברות אל <ph name="USER_EMAIL" />.}other{הכרטיסים האלה יישמרו יחד עם הכתובות שלהם לחיוב. יתאפשר לך להשתמש בהם לאחר התחברות אל <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">לא הצלחנו ליצור קשר עם ההורים שלך. נסה שוב מאוחר יותר.</translation>
<translation id="8025119109950072390">תוקפים באתר הזה עשויים לגרום לך, בדרכי מרמה, לבצע פעולות מסוכנות כמו התקנת תוכנה או חשיפה של מידע אישי (לדוגמה: סיסמאות, מספרי טלפון או פרטי כרטיסי אשראי).</translation>
<translation id="8034522405403831421">דף זה מוצג ב<ph name="SOURCE_LANGUAGE" />. האם לתרגם אותו ל<ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">עט</translation>
@@ -1312,6 +1331,7 @@ Del</translation>
<translation id="8041940743680923270">השתמש בברירת המחדל הכללית (שאל)</translation>
<translation id="8042918947222776840">בחירת שיטת איסוף</translation>
<translation id="8057711352706143257">יש בעיה בהגדרה של "<ph name="SOFTWARE_NAME" />". בדרך כלל, הסרת ההתקנה של "<ph name="SOFTWARE_NAME" />" פותרת את הבעיה. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">מעכשיו והלאה לא יהיה צורך להזין את קוד האבטחה של הכרטיס</translation>
<translation id="8066955247577885446">מצטערים, משהו השתבש.</translation>
<translation id="8074253406171541171">10x13 (Envelope)‎</translation>
<translation id="8078141288243656252">לא ניתן להוסיף הערה במצב מסובב</translation>
@@ -1342,6 +1362,7 @@ Del</translation>
<translation id="8211406090763984747">החיבור מאובטח</translation>
<translation id="8218327578424803826">מיקום מוקצה:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)‎</translation>
+<translation id="8220639454292072926">דיווח ארגוני</translation>
<translation id="8225771182978767009">המשתמש שהגדיר את המחשב הזה בחר לחסום את האתר הזה.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">פתיחת הדף בכרטיסייה חדשה של גלישה בסתר</translation>
@@ -1396,24 +1417,24 @@ Del</translation>
<translation id="8508648098325802031">סמל החיפוש</translation>
<translation id="8522552481199248698">‏בעזרת Chrome אפשר להגן על חשבון Google ולשנות את הסיסמה.</translation>
<translation id="8543181531796978784">באפשרותך <ph name="BEGIN_ERROR_LINK" />לדווח על בעיית זיהוי<ph name="END_ERROR_LINK" /> או, אם אתה מבין את סיכוני האבטחה, <ph name="BEGIN_LINK" />להיכנס לאתר הזה, שאינו מאובטח<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">יש לך שאלות? עליך לפנות לאיש הקשר שמפקח על הפרופיל שלך.</translation>
<translation id="8553075262323480129">התרגום נכשל כיוון שלא הייתה אפשרות לקבוע את שפת הדף.</translation>
<translation id="8557066899867184262">קוד האימות נמצא בגב הכרטיס.</translation>
<translation id="8559762987265718583">לא ניתן ליצור חיבור פרטי אל <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> מפני שהתאריך והשעה (<ph name="DATE_AND_TIME" />) במכשיר שלך שגויים.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> אתר חשוד</translation>
<translation id="8564985650692024650">‏אם הזנת את הסיסמה של <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> באתרים אחרים, ההמלצה של Chromium היא לאפס אותה.</translation>
<translation id="8571890674111243710">מתרגם דף ל<ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">הוסף מספר טלפון
</translation>
-<translation id="859285277496340001">האישור אינו מציין מנגנון הבודק אם הוא נשלל.</translation>
<translation id="860043288473659153">שם בעל הכרטיס</translation>
<translation id="861775596732816396">גודל 4</translation>
-<translation id="8620436878122366504">ההורים שלך עדיין לא אישרו זאת</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">שמירת כרטיס זה במכשיר הנוכחי</translation>
<translation id="8626112503828625890">‏האם לאחסן את פרטי החיוב בחשבון Google?</translation>
+<translation id="8647750283161643317">אפס הכל לברירת המחדל</translation>
<translation id="8663226718884576429">סיכום הזמנה, <ph name="TOTAL_LABEL" />, פרטים נוספים</translation>
<translation id="8680536109547170164"><ph name="QUERY" /> , תשובה, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">פנוי</translation>
<translation id="8703575177326907206">ההתחברות שלך אל <ph name="DOMAIN" /> אינה מוצפנת.</translation>
<translation id="8718314106902482036">התשלום לא הושלם</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, הצעת חיפוש</translation>
@@ -1424,6 +1445,7 @@ Del</translation>
<translation id="8738058698779197622">‏כדי ליצור חיבור מאובטח, השעון צריך להיות מוגדר כהלכה. הסיבה לכך היא שהאישורים שבהם אתרים משתמשים כדי לזהות את עצמם תקפים רק למשך פרקי זמן מסוימים. מאחר שהשעון במכשיר שלך שגוי, Chromium לא יכול לאמת את האישורים האלו.</translation>
<translation id="8740359287975076522">‏לא ניתן היה למצוא את &lt;abbr id="dnsDefinition"&gt;כתובת ה-DNS&lt;/abbr&gt; של <ph name="HOST_NAME" />. מאבחן את הבעיה.</translation>
<translation id="874846938927089722">כרטיסי אשראי וכרטיסים משולמים מראש שהסוחר מקבל</translation>
+<translation id="874918643257405732">הוספת הכרטיסייה לסימניות</translation>
<translation id="8759274551635299824">פג תוקפו של הכרטיס</translation>
<translation id="8761567432415473239">‏גלישה בטוחה של Google <ph name="BEGIN_LINK" />איתרה לאחרונה תוכניות מזיקות<ph name="END_LINK" /> באתר <ph name="SITE" />.</translation>
<translation id="8763927697961133303">‏התקן USB</translation>
@@ -1453,6 +1475,7 @@ Del</translation>
<translation id="8938939909778640821">כרטיסי אשראי וכרטיסים משולמים מראש שהסוחר מקבל</translation>
<translation id="8943282376843390568">ליים</translation>
<translation id="8957210676456822347">הרשאת פורטל חובה</translation>
+<translation id="8962950042226115166">אתר חשוד</translation>
<translation id="8968766641738584599">שמירת הכרטיס</translation>
<translation id="8971063699422889582">פג תוקפו של אישור השרת.</translation>
<translation id="8975012916872825179">כולל מידע כמו מספרי טלפון, כתובות אימייל וכתובות למשלוח</translation>
@@ -1475,24 +1498,24 @@ Del</translation>
<translation id="9035022520814077154">שגיאת אבטחה</translation>
<translation id="9038649477754266430">השתמש בשירות חיזוי כדי לטעון דפים מהר יותר</translation>
<translation id="9039213469156557790">כמו כן, דף זה כולל משאבים נוספים שאינם מאובטחים. גורמים אחרים עלולים לראות את המשאבים האלה במהלך העברתם, ותוקף עלול לשנות אותם באופן שישנה את התנהגות הדף.</translation>
+<translation id="9044359186343685026">‏שימוש ב-Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">ניסית להגיע ל-<ph name="DOMAIN" />, אך השרת הציג אישור לא חוקי.</translation>
<translation id="9050666287014529139">משפט-סיסמה</translation>
<translation id="9065203028668620118">עריכה</translation>
<translation id="9065745800631924235"><ph name="TEXT" /> – חיפוש מההיסטוריה</translation>
<translation id="9069693763241529744">נחסמה על-ידי תוסף</translation>
-<translation id="9076283476770535406">ייתכן שהאתר מכיל תוכן למבוגרים בלבד</translation>
<translation id="9076630408993835509">‏הדפדפן הזה לא מנוהל על ידי חברה או ארגון אחר. ייתכן שהפעילות במכשיר הזה מנוהלת מחוץ ל-Chrome. <ph name="BEGIN_LINK" />מידע נוסף<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">נדרש מידע נוסף</translation>
<translation id="9080712759204168376">סיכום הזמנה</translation>
<translation id="9089260154716455634">מדיניות לשעות ללא פעילות:</translation>
<translation id="9095388113577226029">שפות נוספות...</translation>
+<translation id="9098981495403789647">‏הכלי להגנה מפני איומים של Chrome Enterprise הופעל על ידי מנהל המערכת בדפדפן שלך. לכלי להגנה מפני איומים של Chrome Enterprise יש גישה לחלק מהנתונים שלך.</translation>
<translation id="9103872766612412690">‏האתר <ph name="SITE" /> משתמש בדרך כלל בהצפנה כדי להגן על המידע שלך. כאשר Chromium ניסה הפעם להתחבר ל-<ph name="SITE" />, האתר שלח חזרה אישורים חריגים ושגויים. ייתכן שתוקף מנסה להתחזות לאתר <ph name="SITE" />, או שמסך כניסה ל-Wi-Fi הפריע לחיבור. המידע שלך עדיין מאובטח מכיוון ש-Chromium הפסיק את החיבור לפני חילופי הנתונים.</translation>
<translation id="9106062320799175032">הוספה של כתובת לחיוב</translation>
<translation id="9114524666733003316">אישור הכרטיס מתבצע...</translation>
<translation id="9128870381267983090">התחבר לרשת</translation>
<translation id="9137013805542155359">הצג מקור</translation>
-<translation id="9137248913990643158">‏היכנס לחשבונך ב-Chrome לפני שתשתמש באפליקציה הזו.</translation>
<translation id="9141013498910525015">ניהול כתובות</translation>
<translation id="9148088599418889305">בחירת שיטת משלוח</translation>
<translation id="9148507642005240123">&amp;ביטול עריכה</translation>
diff --git a/chromium/components/strings/components_strings_ja.xtb b/chromium/components/strings/components_strings_ja.xtb
index dff733941d0..7f00e5a2d0c 100644
--- a/chromium/components/strings/components_strings_ja.xtb
+++ b/chromium/components/strings/components_strings_ja.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">名義人名の追加</translation>
<translation id="1089439967362294234">パスワードを変更</translation>
+<translation id="1096545575934602868">このフィールドに入力できる件数は <ph name="MAX_ITEMS_LIMIT" /> 件までです。この件数を超える部分は破棄されます。</translation>
<translation id="109743633954054152">Chrome の設定でパスワードを管理します</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" />を常に翻訳</translation>
<translation id="1107591249535594099">チェックボックスをオンにすると、Chrome はフォームに迅速に入力するために、カード情報のコピーをこのデバイスに保存します。</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> の<ph name="BEGIN_LINK" />キャッシュ コピー<ph name="END_LINK" />にアクセスします</translation>
<translation id="1156303062776767266">ローカル ファイルまたは共有ファイルを表示しています</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> により途中で接続が切断されました。</translation>
+<translation id="115926840831309955">CVC を確認してからもう一度試すか、有効期限を更新してください</translation>
<translation id="1161325031994447685">Wi-Fi に再度接続する</translation>
<translation id="1165039591588034296">エラー</translation>
<translation id="1175364870820465910">印刷(&amp;P)...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">「パソコンにインストールされているソフトウェアが原因で、Chrome からインターネットに安全に接続することができません」(Windows パソコンのみ)</translation>
<translation id="1294154142200295408">コマンドラインのバリエーション</translation>
<translation id="129553762522093515">最近閉じたタブ</translation>
+<translation id="1298536327547837046">マルウェア スキャン</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Cookie を消去してみてください<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">サポート終了の機能</translation>
<translation id="1320233736580025032">Prc1(封筒)</translation>
<translation id="132301787627749051">クリップボードにある画像を検索します</translation>
<translation id="1323433172918577554">もっと見る</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google スプレッドシート</translation>
<translation id="1527263332363067270">接続を待機しています…</translation>
<translation id="1529521330346880926">10x15(封筒)</translation>
+<translation id="1530707389502320859">アクセスしようとしたサイトは偽装サイトのようです。不正なユーザーが URL のごく一部を一目ではわからないように改変してサイトを偽装する場合があります。</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">このページの内容</translation>
<translation id="153384715582417236">現在、コンテンツはありません</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">ドキュメントのサイズが大きすぎるため注釈を追加できません</translation>
-<translation id="1721312023322545264">このサイトにアクセスするには <ph name="NAME" /> さんの許可が必要です</translation>
<translation id="1721424275792716183">* 必須欄です</translation>
<translation id="1727741090716970331">有効なカード番号の追加</translation>
<translation id="1728677426644403582">ウェブページのソースを表示しています</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">アクセスしたウェブサイトと閲覧時間</translation>
<translation id="1826516787628120939">確認中</translation>
<translation id="1834321415901700177">このサイトには有害なプログラムが含まれています</translation>
+<translation id="1838374766361614909">検索をクリア</translation>
<translation id="1839551713262164453">ポリシーの値を検証できませんでした(エラーが発生しました)</translation>
<translation id="1842969606798536927">お支払い</translation>
<translation id="1871208020102129563">プロキシは .pac スクリプト URL ではなく固定プロキシ サーバーを使用するように設定されています。</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">リストを折りたたむ</translation>
<translation id="1898423065542865115">フィルタ</translation>
<translation id="1914326953223720820">解凍サービス</translation>
+<translation id="1915697529809968049">CVC の代わりに Touch ID を使用しますか?</translation>
<translation id="1916770123977586577">更新後の設定をこのサイトに適用するには、このページを再読み込みしてください</translation>
<translation id="1919345977826869612">広告</translation>
<translation id="1919367280705858090">特定のエラー メッセージに関する情報</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> のブックマーク</translation>
<translation id="1973335181906896915">シリアル化エラーです</translation>
<translation id="1974060860693918893">詳細設定</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />アクセスしたページの URL、システム情報、およびページのコンテンツの一部<ph name="END_WHITEPAPER_LINK" />を Google に送信して、Chrome セキュリティの改善にご協力ください。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">ファームウェアのバージョン</translation>
<translation id="1981206234434200693">Chrome の閲覧履歴データを削除する</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{他 1 個}other{他 # 個}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">有効期限(年)を正しい形式で入力してください</translation>
<translation id="2212735316055980242">ポリシーが見つかりません</translation>
<translation id="2213606439339815911">エントリを取得しています...</translation>
+<translation id="2215727959747642672">ファイルの編集</translation>
<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> では現在、悪意のあるユーザーによって危険なアプリ(デバイスに問題を生じさせたり、モバイル利用料に不明瞭な請求を加えたり、個人情報を抜き取ったりするアプリ)がインストールされる可能性があります。<ph name="BEGIN_LEARN_MORE_LINK" />詳細<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">インターネットに接続されていません</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />診断アプリ<ph name="END_LINK" />を使用して接続を修正してください</translation>
<translation id="2239100178324503013">送信</translation>
+<translation id="2248949050832152960">WebAuthn を使用</translation>
<translation id="225207911366869382">この値は、このポリシーではサポートが終了しています。</translation>
<translation id="2257315177824333709">現在、このカードは保存できません</translation>
<translation id="2262243747453050782">HTTP エラーです</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">検索 URL が無効です。</translation>
<translation id="2482878487686419369">通知</translation>
<translation id="248348093745724435">マシンポリシー</translation>
-<translation id="2485387744899240041">デバイスとブラウザのユーザー名</translation>
<translation id="2491120439723279231">サーバーの証明書にエラーがあります。</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON パーサー</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">戻る</translation>
<translation id="2503184589641749290">利用可能なデビットカードとプリペイド カード</translation>
<translation id="2505268675989099013">アカウントを保護</translation>
+<translation id="2515335152965840738">無視</translation>
<translation id="2515629240566999685">電波状況を確認する</translation>
<translation id="2523886232349826891">カードはこのデバイスのみに保存されます</translation>
<translation id="2524461107774643265">その他の情報の追加</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">送信</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{なし}=1{<ph name="DOMAIN_LIST" /> のパスワード 1 件}=2{<ph name="DOMAIN_LIST" /> のパスワード 2 件}other{<ph name="DOMAIN_LIST" /> のパスワード # 件}}</translation>
<translation id="2666117266261740852">他のタブやアプリを閉じる</translation>
-<translation id="267371737713284912">元に戻すには <ph name="MODIFIER_KEY_DESCRIPTION" /> を押します</translation>
<translation id="2674170444375937751">履歴からこれらのページを削除してもよろしいですか?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">このページを離れる</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">値が有効な形式ではありません。</translation>
<translation id="2705137772291741111">このサイトの保存(キャッシュ)されたコピーを読み取れませんでした。</translation>
<translation id="2709516037105925701">自動入力</translation>
-<translation id="2712173769900027643">許可をリクエスト</translation>
<translation id="2713444072780614174">白</translation>
<translation id="2720342946869265578">周辺</translation>
<translation id="2721148159707890343">リクエストを正常に送信しました</translation>
<translation id="2728127805433021124">サーバーの証明書は脆弱な署名アルゴリズムを使用して署名されています。</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />接続診断ツールを実行する<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">これらの機能を有効にすると、ブラウザのデータが失われたり、セキュリティやプライバシーが侵害されたりする可能性があります。有効にした機能は、このブラウザのすべてのユーザーに適用されます。</translation>
<translation id="2735043616039983645">このポリシーには、値が競合する複数のソースがあります。</translation>
<translation id="2738330467931008676">集荷先住所を選択</translation>
<translation id="2740531572673183784">OK</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">接続がリセットされました。</translation>
<translation id="2788784517760473862">利用可能なクレジット カード</translation>
<translation id="2792012897584536778">このデバイスの管理者が設定したセキュリティ証明書により、アクセス先のウェブサイトのコンテンツを管理者が把握できるようになっている可能性があります。</translation>
-<translation id="2794233252405721443">サイトがブロックされています</translation>
<translation id="2799020568854403057">アクセス先のサイトには有害なアプリがあります</translation>
<translation id="2799223571221894425">再起動</translation>
<translation id="2803306138276472711"><ph name="SITE" /> では最近、Google セーフ ブラウジングにより、<ph name="BEGIN_LINK" />不正なソフトウェアが検出されました<ph name="END_LINK" />。通常は安全なウェブサイトであっても、不正なソフトウェアに感染している場合があります。</translation>
+<translation id="2815364696811431560">このサイトから離れる</translation>
<translation id="2824775600643448204">アドレス検索バー</translation>
<translation id="2826760142808435982">接続は <ph name="CIPHER" /> を使用して暗号化および認証されており、<ph name="KX" /> が鍵交換メカニズムとして使用されています。</translation>
<translation id="2835170189407361413">フォームをクリア</translation>
<translation id="2847118875340931228">シークレット ウィンドウを開く</translation>
<translation id="2850739647070081192">Invite(封筒)</translation>
-<translation id="2851634818064021665">このサイトにアクセスするには許可が必要です</translation>
<translation id="2856444702002559011"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> では、悪意のあるユーザーによって、パスワード、メッセージ、クレジット カードなどの情報が盗まれる可能性があります。<ph name="BEGIN_LEARN_MORE_LINK" />詳細<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">カードを保存しますか?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">有効にすると、Chromium がカード情報をこのデバイスに保存するためフォームにすばやく入力できるようになります。</translation>
<translation id="2985398929374701810">有効な住所を入力してください</translation>
<translation id="2986368408720340940">この受け取り方法はご利用いただけません。別の方法を選択してください。</translation>
+<translation id="2987034854559945715">一致する機能はありません</translation>
<translation id="2991174974383378012">ウェブサイトとの共有</translation>
<translation id="2991571918955627853"><ph name="SITE" /> では HSTS が使用されているため、現在アクセスできません。通常、ネットワーク エラーやネットワークへの攻撃は一時的なものです。しばらくするとページにアクセスできるようになります。</translation>
<translation id="3005723025932146533">保存済みのコピーを表示</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">ポリシー タイプが間違っています</translation>
<translation id="3037605927509011580">エラー</translation>
<translation id="3041612393474885105">証明書情報</translation>
+<translation id="3057676462092457419">DnsOverHttps モード <ph name="SECURE_DNS_MODE_SECURE" /> はまだサポートされていません。モードは <ph name="SECURE_DNS_MODE_OFF" /> に設定されました。</translation>
<translation id="3060227939791841287">C9(封筒)</translation>
<translation id="3061707000357573562">サービスへのパッチの適用</translation>
<translation id="3064966200440839136">外部アプリケーションを経由したお支払いの処理に進むため、シークレット モードを解除します。続行しますか?</translation>
@@ -419,6 +428,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" />(<ph name="SERVER_NAME" /> 上)</translation>
<translation id="320323717674993345">支払いをキャンセル</translation>
<translation id="3207960819495026254">ブックマークしました</translation>
+<translation id="3209034400446768650">このページでは料金が請求される可能性があります</translation>
<translation id="3225919329040284222">サーバーの提示した証明書が、組み込まれている想定の証明書と一致しません。これらの想定の証明書は、ユーザー保護のため、特定の安全性の高いウェブサイトについて用意されています。</translation>
<translation id="3226128629678568754">ページの読み込みに必要なデータを再送信するには、再読み込みボタンを押してください。</translation>
<translation id="3227137524299004712">マイク</translation>
@@ -426,7 +436,6 @@
<translation id="3229041911291329567">デバイスとブラウザに関するバージョン情報</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> の CVC を入力</translation>
<translation id="3234666976984236645">このサイトの重要なコンテンツを常に検出</translation>
-<translation id="3254409185687681395">このページをブックマークに追加します</translation>
<translation id="3270847123878663523">順序変更の取り消し(&amp;U)</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">名義人名を追加</translation>
@@ -436,7 +445,6 @@
<translation id="3320021301628644560">請求先住所を追加</translation>
<translation id="3324983252691184275">クリムゾン</translation>
<translation id="3338095232262050444">保護された通信</translation>
-<translation id="3345135638360864351">このサイトにアクセスするためのリクエストを <ph name="NAME" /> に送信できませんでした。もう一度お試しください。</translation>
<translation id="3355823806454867987">プロキシ設定の変更...</translation>
<translation id="3361596688432910856">Chrome には、<ph name="BEGIN_EMPHASIS" />次の情報は<ph name="END_EMPHASIS" />保存されません。
<ph name="BEGIN_LIST" />
@@ -470,18 +478,15 @@
<translation id="3462200631372590220">詳細情報を表示しない</translation>
<translation id="3467763166455606212">カード名義人は必須です</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> が現在開いています。Tab キー、Enter キーの順に押すと開いているタブに切り替わります</translation>
-<translation id="3479539252931486093">想定外の動作である場合は、<ph name="BEGIN_LINK" />問題を報告<ph name="END_LINK" />してください。</translation>
<translation id="3479552764303398839">後で</translation>
<translation id="3484560055331845446">Google アカウントにアクセスできなくなる可能性があります。Chrome で今すぐパスワードを変更することをおすすめします。変更の際には、ログインするよう求められます。</translation>
<translation id="3495081129428749620"><ph name="PAGE_TITLE" />
ページ内を検索</translation>
-<translation id="3498215018399854026">現在、保護者にたずねることができません。もう一度お試しください。</translation>
<translation id="3512163584740124171">より優先度の高いポリシーが同じポリシー グループにあるため、このポリシーは無視されます。</translation>
<translation id="3528171143076753409">サーバーの証明書を信頼できません。</translation>
<translation id="3528485271872257980">暗い茶色</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{同期デバイスで 1 件以上のアイテム}=1{1 件のアイテム(同期デバイスではそれ以上のアイテム)}other{# 件のアイテム(同期デバイスではそれ以上のアイテム)}}</translation>
<translation id="3539171420378717834">このデバイスにこのカード情報のコピーを保存する</translation>
-<translation id="3556433843310711081">ブロックの解除は管理者が行うことができます</translation>
<translation id="3566021033012934673">この接続ではプライバシーが保護されません</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" /> <ph name="STATE" /> <ph name="CITY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> に埋め込まれているページの内容</translation>
@@ -509,6 +514,7 @@
<translation id="3678529606614285348">ページを新しいシークレット ウィンドウで開く(Ctrl-Shift-N)</translation>
<translation id="3679803492151881375"><ph name="CRASH_TIME" /> にクラッシュ レポートが作成され、<ph name="UPLOAD_TIME" /> にアップロードされました</translation>
<translation id="3681007416295224113">証明書情報</translation>
+<translation id="3701427423622901115">リセットを確認しました。</translation>
<translation id="3704162925118123524">ご利用のネットワークでは、ログインページへのアクセスが必要な可能性があります。</translation>
<translation id="3704609568417268905"><ph name="TIME" />、<ph name="TITLE" />(<ph name="DOMAIN" />)を<ph name="BOOKMARKED" /></translation>
<translation id="370665806235115550">読み込んでいます...</translation>
@@ -525,6 +531,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> では、悪意のあるユーザーによって、ソフトウェアのインストールや個人情報(パスワード、電話番号、クレジット カードなど)の入力といった危険な操作を行うよう誘導される可能性があります。<ph name="BEGIN_LEARN_MORE_LINK" />詳細<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">サーバー エラーのため翻訳できませんでした。</translation>
<translation id="3759461132968374835">最近発生した障害はありません。障害レポートが無効になっているときに発生した障害は、ここには表示されません。</translation>
+<translation id="3760561303380396507">CVC の代わりに Windows Hello を使用しますか?</translation>
<translation id="3761718714832595332">ステータスを表示しない</translation>
<translation id="3765032636089507299">セーフ ブラウジング ページは準備中です。</translation>
<translation id="3778403066972421603">このカードを Google アカウントとこのデバイスに保存しますか?</translation>
@@ -534,6 +541,7 @@
<translation id="3789155188480882154">サイズ 16</translation>
<translation id="3797522431967816232">Prc3(封筒)</translation>
<translation id="3807873520724684969">有害なコンテンツがブロックされました。</translation>
+<translation id="3808375843007691220">警告: 試験運用版の機能です。</translation>
<translation id="3810973564298564668">管理</translation>
<translation id="382518646247711829">プロキシ サーバーを使用している場合...</translation>
<translation id="3828924085048779000">パスフレーズは必ず指定してください。</translation>
@@ -542,11 +550,11 @@
<translation id="3858027520442213535">日時を更新</translation>
<translation id="3884278016824448484">競合するデバイス識別子です</translation>
<translation id="3885155851504623709">教区</translation>
-<translation id="3886446263141354045">このサイトへのアクセス リクエストを <ph name="NAME" /> さんに送信しました</translation>
<translation id="3890664840433101773">メールを追加</translation>
<translation id="3901925938762663762">カードの有効期限が切れています</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVC の代わりに WebAuthn を使用しますか?</translation>
<translation id="3946209740501886391">このサイトでは常に確認</translation>
<translation id="3949571496842715403">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書で SAN(サブジェクトの別名)が指定されていません。設定が不適切であるか、悪意のあるユーザーによって接続が妨害されている可能性があります。</translation>
<translation id="3949601375789751990">閲覧履歴がここに表示されます</translation>
@@ -557,11 +565,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{なし}=1{1 件のサイトから}other{# 件のサイトから}}</translation>
<translation id="397105322502079400">計算しています...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> はブロックされています</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> がブラウザで Chrome Enterprise Threat Protection を有効にしています。Chrome Enterprise Threat Protection がユーザーのデータの一部にアクセスできます。</translation>
<translation id="3987940399970879459">1 MB 未満</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 件の近くのウェブページ}other{# 件の近くのウェブページ}}</translation>
<translation id="4030383055268325496">追加の取り消し(&amp;U)</translation>
<translation id="4032320456957708163">ご使用のブラウザは <ph name="ENROLLMENT_DOMAIN" /> によって管理されています</translation>
-<translation id="4034375457890803692">そのリンクを開くと、通常はアクセスしないサイトに移動します。ユーザーを混乱させようとしている可能性があります。</translation>
<translation id="4058922952496707368">キー「<ph name="SUBKEY" />」: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1(封筒)</translation>
<translation id="4067947977115446013">有効なアドレスの追加</translation>
@@ -574,6 +582,7 @@
<translation id="4103249731201008433">デバイスのシリアル番号が無効です</translation>
<translation id="410351446219883937">自動再生</translation>
<translation id="4103763322291513355">&lt;strong&gt;chrome://policy&lt;/strong&gt; にアクセスして、ブラックリストに登録されている URL とシステム管理者が設定した他のポリシーを確認できます。</translation>
+<translation id="4108231218301530806">今後は指紋を使ってこのカードを確認する。</translation>
<translation id="4110652170750985508">お支払いの確認</translation>
<translation id="4112140312785995938">後方に移動</translation>
<translation id="4116663294526079822">このサイトでは常に許可</translation>
@@ -588,6 +597,7 @@
<translation id="4171400957073367226">確認用の署名に問題があります</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{他 <ph name="ITEM_COUNT" /> 件のアイテム}other{他 <ph name="ITEM_COUNT" /> 件のアイテム}}</translation>
+<translation id="4176463684765177261">停止中</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">カードと請求先住所を Google アカウントに追加すると、次回のお支払いが簡単になります。</translation>
<translation id="4196861286325780578">移動のやり直し(&amp;R)</translation>
@@ -624,6 +634,7 @@
<translation id="4277028893293644418">パスワードを再設定</translation>
<translation id="4279811152705618813">この <ph name="DEVICE_TYPE" /> は <ph name="ENROLLMENT_DOMAIN" /> によって管理されています</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{このカードを Google アカウントに保存しました}other{これらのカードを Google アカウントに保存しました}}</translation>
+<translation id="428847186335018806">Chrome でダウンロードまたはアップロードするファイルをスキャンします。</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4302965934281694568">長3(封筒)</translation>
<translation id="4305817255990598646">切り替え</translation>
@@ -653,7 +664,6 @@
<translation id="4435702339979719576">ポストカード</translation>
<translation id="443673843213245140">プロキシの使用は無効ですが、プロキシの設定が明示的に指定されています。</translation>
<translation id="445100540951337728">利用可能なデビットカード</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" />: 不審な動作</translation>
<translation id="4466881336512663640">フォームの変更内容は破棄されます。続行してもよろしいですか?</translation>
<translation id="4477350412780666475">次の曲</translation>
<translation id="4482953324121162758">このサイトは翻訳されません。</translation>
@@ -680,6 +690,7 @@
<translation id="4594403342090139922">削除の取り消し(&amp;U)</translation>
<translation id="4597348597567598915">サイズ 8</translation>
<translation id="4600854749408232102">C6 / C5(封筒)</translation>
+<translation id="464342062220857295">検索機能</translation>
<translation id="4646534391647090355">今すぐ表示</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書にはエラーがあります。原因としては、不適切な設定や、悪意のあるユーザーによる接続妨害が考えられます。</translation>
@@ -688,7 +699,6 @@
<translation id="4691835149146451662">Architecture-A(封筒)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">接続が中断されました</translation>
-<translation id="471880041731876836">このサイトへのアクセスが許可されていません</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ネットワーク診断ツールを実行する<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">ポリシーを再読み込み</translation>
<translation id="4728558894243024398">プラットフォーム</translation>
@@ -716,7 +726,6 @@
<translation id="4816492930507672669">ページサイズに合わせる</translation>
<translation id="4850886885716139402">表示</translation>
<translation id="4854362297993841467">この配達方法はご利用いただけません。別の方法を選択してください。</translation>
-<translation id="4858792381671956233">このサイトを開いてもよいかの問い合わせを保護者に送信しました</translation>
<translation id="4864052566555297930">安全に関するヒント:</translation>
<translation id="4876188919622883022">簡易表示</translation>
<translation id="4876305945144899064">ユーザー名が指定されていません</translation>
@@ -740,7 +749,9 @@
<translation id="4974590756084640048">警告を再度有効にする</translation>
<translation id="4984339528288761049">Prc5(封筒)</translation>
<translation id="4989163558385430922">すべて表示</translation>
+<translation id="4989542687859782284">利用不可</translation>
<translation id="4989809363548539747">このプラグインはサポートされていません</translation>
+<translation id="4995216769782533993">このサイトでカード情報を共有するには、セキュリティ コードを確認してください</translation>
<translation id="5002932099480077015">有効にすると、Chrome ではこのデバイスにカードのコピーが保存されます。これにより、フォームにすばやく入力できるようになります。</translation>
<translation id="5015510746216210676">マシン名:</translation>
<translation id="5017554619425969104">コピーしたテキスト</translation>
@@ -769,6 +780,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 ビット)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">カードの確認</translation>
<translation id="5135404736266831032">住所を管理...</translation>
<translation id="5138227688689900538">一部を表示</translation>
<translation id="5141240743006678641">Google の認証情報で同期パスワードを暗号化する</translation>
@@ -795,6 +807,7 @@
<translation id="5251803541071282808">クラウド</translation>
<translation id="5252000469029418751">C7(封筒)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">システム全体に適用される機能は所有者(<ph name="OWNER_EMAIL" />)のみが設定できます</translation>
<translation id="5273658854610202413">警告: このポリシーは統合可能な辞書ポリシーに含まれていないため、PolicyDictionaryMultipleSourceMergeList ポリシーで指定されているとおりには統合されませんでした。</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">終了</translation>
@@ -818,7 +831,6 @@
<translation id="536296301121032821">ポリシー設定を保存できませんでした</translation>
<translation id="5371425731340848620">カードを更新</translation>
<translation id="5377026284221673050">「時計が遅れています」、「時計が進んでいます」、「&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;」</translation>
-<translation id="5377179979757081683">このページは、ユーザーをだましたり、個人情報を盗み取ったり、デバイスに損害を与えたりする可能性があります。個人情報を入力するときや、ダウンロードしたファイルを開くときはご注意ください。</translation>
<translation id="5384855140246857529">お使いのどのデバイスでも同じカードを使用するには、ログインして同期を有効にします。</translation>
<translation id="5386426401304769735">このサイトの証明書チェーンには SHA-1 を使って署名された証明書が含まれています。</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -832,6 +844,7 @@
<translation id="5457113250005438886">無効</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 件)}other{<ph name="CONTACT_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 件)}}</translation>
<translation id="5470861586879999274">編集のやり直し(&amp;R)</translation>
+<translation id="5473728911100096288">これらの機能を有効にすると、今後のバージョンでは使えなくなるサポート終了予定の機能を使用することになります。</translation>
<translation id="5478437291406423475">B6 / C4(封筒)</translation>
<translation id="5481076368049295676">アクセス先のコンテンツによって、個人情報を入手したり削除したりする危険なソフトウェアがインストールされる可能性があります。<ph name="BEGIN_LINK" />危険性を理解したうえで表示する<ph name="END_LINK" /></translation>
<translation id="54817484435770891">有効なアドレスを追加</translation>
@@ -855,7 +868,6 @@
<translation id="5570825185877910964">アカウントを保護</translation>
<translation id="5571083550517324815">この住所での受け取りはできません。別の住所を選択してください。</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 個が使用中}other{# 個が使用中}})</translation>
-<translation id="5572851009514199876">このサイトへのアクセス権があるかどうかを Chrome で確認できるように、Chrome を起動してログインしてください。</translation>
<translation id="5580958916614886209">有効期限の「月」を確認してもう一度お試しください</translation>
<translation id="5586446728396275693">保存されている住所がありません</translation>
<translation id="5595485650161345191">住所の編集</translation>
@@ -863,6 +875,7 @@
<translation id="560412284261940334">管理はサポートされていません</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">偽のサイトまたは不正なサイトの可能性があります。このサイトから離れることをおすすめします。</translation>
<translation id="5610142619324316209">接続を確認する</translation>
<translation id="5610807607761827392">カードと住所は [<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />] で管理できます。</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> でリダイレクトが繰り返し行われました。</translation>
@@ -886,11 +899,11 @@
<translation id="5720705177508910913">現在のユーザー</translation>
<translation id="5728056243719941842">C5(封筒)</translation>
<translation id="5730040223043577876">パスワードを他のサイトで再使用した場合、Chrome ではパスワードの再設定を促すメッセージが表示されます。</translation>
-<translation id="5732392974455271431">ブロックの解除は保護者が行うことができます</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Google アカウントにカードを保存}other{Google アカウントにカードを保存}}</translation>
<translation id="5763042198335101085">有効なメールアドレスを入力してください</translation>
<translation id="5765072501007116331">配達方法と要件を確認するには、住所を選択してください</translation>
<translation id="5778550464785688721">MIDI デバイスのフル コントロール</translation>
+<translation id="5781136890105823427">テスト機能を有効にしました</translation>
<translation id="578305955206182703">アンバー</translation>
<translation id="57838592816432529">ミュート</translation>
<translation id="5784606427469807560">カードの確認中に問題が発生しました。インターネット接続を確認してもう一度お試しください。</translation>
@@ -907,13 +920,16 @@
<translation id="5860033963881614850">オフ</translation>
<translation id="5863847714970149516">表示しようとしているページでは課金される恐れがあります</translation>
<translation id="5866257070973731571">電話番号の追加</translation>
+<translation id="5866898949289125849">デベロッパー ツール ページを表示しています</translation>
<translation id="5869405914158311789">このサイトにアクセスできません</translation>
<translation id="5869522115854928033">保存したパスワード</translation>
<translation id="5887400589839399685">カードが保存されました</translation>
<translation id="5893752035575986141">クレジット カードをご利用いただけます。</translation>
+<translation id="5895138241574237353">再起動</translation>
<translation id="5901630391730855834">黄</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" />(同期済み)</translation>
<translation id="5916664084637901428">オン</translation>
+<translation id="59174027418879706">有効</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">カードを Google アカウントに保存しますか?</translation>
<translation id="5922853866070715753">ほぼ完了です</translation>
@@ -945,8 +961,9 @@
<translation id="6047927260846328439">アクセス先のコンテンツは、ユーザーをだましてソフトウェアをインストールさせようとしたり、個人情報を危険にさらしたりする可能性があります。<ph name="BEGIN_LINK" />危険性を理解したうえで表示する<ph name="END_LINK" /></translation>
<translation id="6051221802930200923"><ph name="SITE" /> では証明書ピンニングが使用されているため、現在アクセスできません。通常、ネットワーク エラーやネットワークへの攻撃は一時的なものです。しばらくするとページにアクセスできるようになります。</translation>
<translation id="6052284303005792909">•</translation>
-<translation id="6058977677006700226">お使いのどのデバイスでも同じカードを使用できるようにしかすか?</translation>
+<translation id="6058977677006700226">お使いのどのデバイスでも同じカードを使用できるようにしますか?</translation>
<translation id="6059925163896151826">USB デバイス</translation>
+<translation id="6060009363608157444">無効な DnsOverHttps モードです。</translation>
<translation id="6080696365213338172">管理者が提供する証明書を使用してコンテンツにアクセスしています。<ph name="DOMAIN" /> に提供するデータは管理者によって傍受される可能性があります。</translation>
<translation id="6094273045989040137">注釈を追加</translation>
<translation id="610911394827799129">お使いの Google アカウントの <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> に、他の形式の閲覧履歴が記録されている場合があります</translation>
@@ -995,13 +1012,12 @@
<translation id="6404511346730675251">ブックマークを編集</translation>
<translation id="6406765186087300643">C0(封筒)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> の有効期限と CVC を入力</translation>
-<translation id="6414888972213066896">このサイトを開いてもよいかの問い合わせを保護者に送信しました</translation>
<translation id="6415778972515849510">Chromium には Google アカウントの保護とパスワードの変更をサポートする機能があります。</translation>
-<translation id="6417515091412812850">証明書が取り消されたかどうかを確認できません。</translation>
<translation id="6431585503458005759">保存しません</translation>
<translation id="6433490469411711332">連絡先情報の編集</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> で接続が拒否されました。</translation>
<translation id="6434309073475700221">破棄</translation>
+<translation id="6435221585574090192">Chrome Enterprise Threat Protection によってフラグ付けされたセキュリティ イベントに関するデータを、管理者と共有できます。データの例としては、ページ URL、ファイル名、ファイル メタデータ、デバイスのユーザー名、Chrome のユーザー名などがあります。</translation>
<translation id="6440503408713884761">除外されました</translation>
<translation id="6446163441502663861">Kahu(封筒)</translation>
<translation id="6446608382365791566">他の情報を追加</translation>
@@ -1010,20 +1026,19 @@
<translation id="6465306955648956876">パスワードを管理...</translation>
<translation id="647261751007945333">デバイス ポリシー</translation>
<translation id="6476284679642588870">お支払い方法を管理</translation>
-<translation id="6477321094435799029">このページで通常と異なるコードを検出したため、個人情報(例: パスワード、電話番号、クレジット カード番号)を保護するために、ページをブロックしました。</translation>
<translation id="6489534406876378309">クラッシュのアップロードを開始</translation>
<translation id="6499038740797743453">パスワードを再設定しますか?</translation>
<translation id="6507833130742554667">クレジット カードとデビットカードをご利用いただけます。</translation>
<translation id="650855688985305916">はい、保存します</translation>
<translation id="6508722015517270189">Chrome を再起動する</translation>
<translation id="6517596291481585650">警告: このポリシーはリストでないため、ポリシーで指定されているとおりにリストとして統合されませんでした。</translation>
+<translation id="6518133107902771759">確認</translation>
<translation id="6521745193039995384">無効</translation>
<translation id="6529602333819889595">削除のやり直し(&amp;R)</translation>
<translation id="6534179046333460208">フィジカル ウェブからの URL</translation>
<translation id="6545864417968258051">Bluetooth のスキャン</translation>
<translation id="6554795675067793129">あなたのアカウントは <ph name="ENROLLMENT_DOMAIN" /> によって管理されています。</translation>
<translation id="6556866813142980365">やり直す</translation>
-<translation id="6563469144985748109">管理者がまだサイトを開くことを許可していません</translation>
<translation id="6569060085658103619">拡張機能のページを表示しています</translation>
<translation id="6578796323535178455">C2(封筒)</translation>
<translation id="6579990219486187401">ライトピンク</translation>
@@ -1041,11 +1056,13 @@
<translation id="6643016212128521049">削除</translation>
<translation id="6644283850729428850">このポリシーは廃止されました。</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{なし}=1{1 件のサイト(Google アカウントへのログイン状態は維持されます)}other{# 件のサイト(Google アカウントへのログイン状態は維持されます)}}</translation>
+<translation id="6652101503459149953">Windows Hello を使用</translation>
<translation id="6657585470893396449">パスワード</translation>
<translation id="6670613747977017428">セキュリティで保護されたページに戻ります。</translation>
<translation id="6671697161687535275">Chromium から候補を削除してもよろしいですか?</translation>
<translation id="6685834062052613830">ログアウトして設定を完了してください</translation>
<translation id="6689271823431384964">ログインしている場合は、その Google アカウントにカードを保存できます。この動作は設定で変更できます。カード名義人はアカウントから取得されます。</translation>
+<translation id="6707256370811247129">Chrome でキャッシュのコンテンツとダウンロードまたはアップロードするファイルをスキャンします。</translation>
<translation id="6710213216561001401">前へ</translation>
<translation id="6710594484020273272">&lt;検索キーワードを入力&gt;</translation>
<translation id="671076103358959139">登録トークン:</translation>
@@ -1053,10 +1070,10 @@
<translation id="6738516213925468394">データは <ph name="TIME" />に<ph name="BEGIN_LINK" />同期パスフレーズ<ph name="END_LINK" />で暗号化されました。同期を開始するには、同期パスフレーズを入力してください。</translation>
<translation id="674375294223700098">不明なサーバー証明書エラー</translation>
<translation id="6744009308914054259">接続するまでの間、[ダウンロード] に移動してオフラインで記事を読むことができます。</translation>
+<translation id="6747611005629681221">警告: サポート終了予定の機能です。</translation>
<translation id="6753269504797312559">ポリシーの値</translation>
<translation id="6757797048963528358">デバイスがスリープ状態です。</translation>
<translation id="6768213884286397650">はがき</translation>
-<translation id="6778737459546443941">保護者がまだサイトを開くことを許可していません</translation>
<translation id="67862343314499040">バイオレット</translation>
<translation id="6786747875388722282">拡張機能</translation>
<translation id="6790428901817661496">再生</translation>
@@ -1064,6 +1081,7 @@
<translation id="681021252041861472">必須項目</translation>
<translation id="6810899417690483278">カスタム ID</translation>
<translation id="6825578344716086703"><ph name="DOMAIN" /> にアクセスしようとしましたが、脆弱な署名アルゴリズム(SHA-1 など)を使用して署名された証明書がサーバーから提示されました。このセキュリティ認証情報は偽装されたものである可能性があり、アクセスしようとしたサーバーとは別のサーバーが応答している可能性があります(悪意のあるユーザーと通信している可能性があります)。</translation>
+<translation id="6826370046007623921">データ損失の防止</translation>
<translation id="6831043979455480757">翻訳</translation>
<translation id="6839929833149231406">地区</translation>
<translation id="6852204201400771460">アプリを再読み込みしますか?</translation>
@@ -1076,7 +1094,6 @@
<translation id="6891596781022320156">ポリシーレベルがサポートされていません。</translation>
<translation id="6895330447102777224">カードを確認しました</translation>
<translation id="6897140037006041989">ユーザー エージェント</translation>
-<translation id="6903319715792422884"><ph name="BEGIN_WHITEPAPER_LINK" />一部のシステム情報とページのコンテンツ<ph name="END_WHITEPAPER_LINK" />を Google に送信して、セーフ ブラウジングの改善にご協力ください。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ユーザー:</translation>
<translation id="6934672428414710184">Google アカウントで設定されている名前です</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> が管理していないサイトでパスワードを入力しました。アカウントを保護するには、他のアプリやサイトでパスワードを再使用しないでください。</translation>
@@ -1121,6 +1138,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> 件)}other{<ph name="PAYMENT_METHOD_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> 件)}}</translation>
<translation id="7153618581592392745">ラベンダー</translation>
<translation id="717330890047184534">GAIA ID:</translation>
+<translation id="7174545416324379297">統合された値</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 件)}other{<ph name="SHIPPING_OPTION_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 件)}}</translation>
<translation id="7177397715882417099">アクセスしているサーバー <ph name="ORIGIN" /> では、サーバーへのすべてのリクエストにセキュリティ ポリシーを適用することが求められていますが、ポリシーは送信されず、ブラウザは他の場所にリダイレクトされたため、ブラウザは <ph name="SITE" /> のリクエストを満たすことができません。</translation>
<translation id="7179323680825933600">お支払い方法の保存と入力</translation>
@@ -1155,6 +1173,7 @@
<translation id="7320336641823683070">接続に関するヘルプ</translation>
<translation id="733354035281974745">デバイスのローカル アカウントのオーバーライド</translation>
<translation id="7334320624316649418">順序変更のやり直し(&amp;R)</translation>
+<translation id="7337706099755338005">現在のプラットフォームではご利用いただけません。</translation>
<translation id="733923710415886693">サーバーの証明書は、証明書の透明性ポリシーを介して公開されていません。</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">外部のユーザーかどうか:</translation>
@@ -1186,7 +1205,6 @@
<translation id="7440140511386898319">オフラインで利用できるコンテンツ</translation>
<translation id="7441627299479586546">ポリシーの対象が間違っています</translation>
<translation id="7442725080345379071">ライトオレンジ</translation>
-<translation id="7444046173054089907">このサイトはブロックされています</translation>
<translation id="7445762425076701745">接続してるサーバーの身元について、十分な検証ができません。接続しているサーバーは、そのネットワーク内でのみ有効な名前を使用しており、外部認証局がその所有権を検証する方法はありません。こうした名前で証明書を発行する認証局もあるので、接続先が意図したウェブサイトか、悪意のあるユーザーのサイトかは確認できません。</translation>
<translation id="7451311239929941790">この問題について<ph name="BEGIN_LINK" />詳細を確認<ph name="END_LINK" />する</translation>
<translation id="7455133967321480974">グローバルのデフォルト値([ブロック])を使用</translation>
@@ -1208,9 +1226,9 @@
<translation id="7538364083937897561">A2(封筒)</translation>
<translation id="7542403920425041731">確認すると、カードの情報がこのサイトに共有されます。</translation>
<translation id="7542995811387359312">このフォームは安全な接続を使用していないため、クレジットカードの自動入力が無効になっています。</translation>
-<translation id="7543525346216957623">保護者に頼んでください</translation>
<translation id="7548892272833184391">接続エラーを解決する</translation>
<translation id="7549584377607005141">このウェブページを正しく表示するには、先ほど入力したデータが必要です。データは再送信できますが、このページで先ほど行った操作を繰り返すことになります。</translation>
+<translation id="7550637293666041147">お客様のデバイスのユーザー名と Chrome のユーザー名</translation>
<translation id="7552846755917812628">次のことをお試しください。</translation>
<translation id="7554791636758816595">新しいタブ</translation>
<translation id="7564049878696755256"><ph name="ORG_NAME" /> アカウントにアクセスできなくなったり、個人情報が盗まれたりする可能性があります。今すぐパスワードを変更することをおすすめします。</translation>
@@ -1225,6 +1243,7 @@
<translation id="7610193165460212391">値(<ph name="VALUE" />)が範囲外です。</translation>
<translation id="7613889955535752492">有効期限: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">別の Google アカウント パスワードを使って暗号化したデータが既にあります。パスワードを以下に入力してください。</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">パフォーマンス データと障害レポート</translation>
<translation id="7637571805876720304">Chromium からクレジット カードを削除してもよろしいですか?</translation>
<translation id="7638605456503525968">シリアルポート</translation>
@@ -1237,7 +1256,6 @@
<translation id="7668654391829183341">不明なデバイス</translation>
<translation id="7669271284792375604">このサイトを利用すると、悪意のあるユーザーによって、閲覧時のエクスペリエンスを損なうプログラム(ホームページを改ざんする、アクセス先のサイトに追加の広告を表示するなどのプログラム)をインストールするよう誘導される可能性があります。</translation>
<translation id="7676643023259824263">クリップボードにあるテキスト<ph name="TEXT" />を検索します</translation>
-<translation id="7679176406634891508">プラットフォームとクラウド</translation>
<translation id="7681101578153515023">検索エンジンを変更する</translation>
<translation id="7682287625158474539">発送先</translation>
<translation id="7687186412095877299">保存したお支払い方法を使ってお支払いフォームに入力する</translation>
@@ -1252,7 +1270,6 @@
<translation id="7723047071702270851">カードの編集</translation>
<translation id="774634243536837715">危険なコンテンツがブロックされました。</translation>
<translation id="7752995774971033316">管理されていません</translation>
-<translation id="7755287808199759310">ブロックの解除は保護者が行うことができます</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ファイアウォールまたはウイルス対策ソフトウェアによって接続がブロックされた可能性があります。</translation>
<translation id="7759163816903619567">表示ドメイン:</translation>
@@ -1296,7 +1313,6 @@
<translation id="8004582292198964060">ブラウザ</translation>
<translation id="8009225694047762179">パスワードを管理</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{このカードと請求先住所は保存され、<ph name="USER_EMAIL" /> にログインすると使用できます。}other{これらのカードと請求先住所は保存され、<ph name="USER_EMAIL" /> にログインすると使用できます。}}</translation>
-<translation id="8012647001091218357">現在、保護者にたずねることができません。もう一度お試しください。</translation>
<translation id="8025119109950072390">このサイトを利用すると、悪意のあるユーザーによって、ソフトウェアのインストールや個人情報(例: パスワード、電話番号、クレジット カード番号)の入力などの危険な操作を行うよう誘導される可能性があります。</translation>
<translation id="8034522405403831421">このページの言語は<ph name="SOURCE_LANGUAGE" />です。<ph name="TARGET_LANGUAGE" />に翻訳しますか?</translation>
<translation id="8035152190676905274">ペン</translation>
@@ -1307,6 +1323,7 @@
<translation id="8041940743680923270">グローバルのデフォルト値([確認])を使用</translation>
<translation id="8042918947222776840">集荷方法を選択</translation>
<translation id="8057711352706143257">「<ph name="SOFTWARE_NAME" />」が正しく設定されていません。通常、この問題は「<ph name="SOFTWARE_NAME" />」をアンインストールすることで解決します。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">今後カードのセキュリティ コードを入力する必要がなくなります</translation>
<translation id="8066955247577885446">エラーが発生しました。</translation>
<translation id="8074253406171541171">10x13(封筒)</translation>
<translation id="8078141288243656252">回転時に注釈を追加することはできません</translation>
@@ -1337,6 +1354,7 @@
<translation id="8211406090763984747">この接続は保護されています</translation>
<translation id="8218327578424803826">割り当てられた場所:</translation>
<translation id="8220146938470311105">C7 / C6(封筒)</translation>
+<translation id="8220639454292072926">企業レポート</translation>
<translation id="8225771182978767009">このサイトは、このパソコンを設定したユーザーによってブロックされています。</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />、<ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">ページを新しいシークレット タブで開く</translation>
@@ -1391,24 +1409,24 @@
<translation id="8508648098325802031">検索アイコン</translation>
<translation id="8522552481199248698">Chrome には Google アカウントの保護とパスワードの変更をサポートする機能があります。</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />検出の問題をご報告<ph name="END_ERROR_LINK" />ください。<ph name="BEGIN_LINK" />安全でないこのサイトにアクセス<ph name="END_LINK" />する場合は、セキュリティ上のリスクがあることをご承知おきください。</translation>
-<translation id="8543556556237226809">ご不明な点は、プロフィールの管理担当者にお問い合わせください。</translation>
<translation id="8553075262323480129">ページの言語を検出できないため翻訳できません。</translation>
<translation id="8557066899867184262">CVC はカードの裏面に記載されています。</translation>
<translation id="8559762987265718583">デバイスの日時(<ph name="DATE_AND_TIME" />)が正しくないため、<ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> へのプライベート接続を確立できません。</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> 不審なサイト</translation>
<translation id="8564985650692024650"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> パスワードを他のサイトで再使用した場合、Chromium ではパスワードの再設定を促すメッセージが表示されます。</translation>
<translation id="8571890674111243710">ページを<ph name="LANGUAGE" />に翻訳しています...</translation>
<translation id="858637041960032120">電話番号を追加
</translation>
-<translation id="859285277496340001">この証明書には、取り消されたかどうかを確認する方法が指定されていません。</translation>
<translation id="860043288473659153">カード名義人</translation>
<translation id="861775596732816396">サイズ 4</translation>
-<translation id="8620436878122366504">保護者がまだサイトを開くことを許可していません</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">このカード情報をこのデバイスに保存する</translation>
<translation id="8626112503828625890">お支払い情報を Google アカウントに保存しますか?</translation>
+<translation id="8647750283161643317">すべてデフォルトに戻す</translation>
<translation id="8663226718884576429">ご注文の概要、<ph name="TOTAL_LABEL" />、その他の詳細</translation>
<translation id="8680536109547170164">「<ph name="QUERY" />」に対する答え: 「<ph name="ANSWER" />」</translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">使用可能</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> への接続は暗号化されていません。</translation>
<translation id="8718314106902482036">支払い処理を完了できませんでした</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />、<ph name="DESCRIPTION" />、検索候補</translation>
@@ -1419,6 +1437,7 @@
<translation id="8738058698779197622">安全な接続を確立するには時計が正しく設定されている必要があります。この理由は、本物のウェブサイトであることを示すためにウェブサイトで使用される証明書には、有効期間(発効日時と失効日時)が設定されているためです。デバイスの時計が正しくないため、Chromium ではこれらの証明書を確認できません。</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> の &lt;abbr id="dnsDefinition"&gt;DNS アドレス&lt;/abbr&gt;が見つかりませんでした。問題を診断しています。</translation>
<translation id="874846938927089722">利用可能なクレジット カードとプリペイド カード</translation>
+<translation id="874918643257405732">このタブをブックマークに追加します</translation>
<translation id="8759274551635299824">このカードは有効期限が切れています</translation>
<translation id="8761567432415473239"><ph name="SITE" /> では最近、Google セーフ ブラウジングにより<ph name="BEGIN_LINK" />有害なプログラムが検出<ph name="END_LINK" />されました。</translation>
<translation id="8763927697961133303">USB デバイス</translation>
@@ -1448,6 +1467,7 @@
<translation id="8938939909778640821">利用可能なクレジット カードとプリペイド カード</translation>
<translation id="8943282376843390568">ライム</translation>
<translation id="8957210676456822347">キャプティブ ポータル認証</translation>
+<translation id="8962950042226115166">不審なサイト</translation>
<translation id="8968766641738584599">カードを保存</translation>
<translation id="8971063699422889582">サーバーの証明書の有効期限が切れています。</translation>
<translation id="8975012916872825179">電話番号、メールアドレス、配送先住所などの情報が含まれます</translation>
@@ -1470,24 +1490,24 @@
<translation id="9035022520814077154">セキュリティ エラー</translation>
<translation id="9038649477754266430">予測サービスを使用してページをより迅速に読み込む</translation>
<translation id="9039213469156557790">加えて、このページには安全でない他のリソースが含まれています。このリソースは送信中に他のユーザーから見られる可能性があります。また、悪意のあるユーザーによって改変されページの動作が変わる可能性もあります。</translation>
+<translation id="9044359186343685026">Touch ID を使用</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619"><ph name="DOMAIN" /> にアクセスしようとしましたが、サーバーから無効な証明書が提示されました。</translation>
<translation id="9050666287014529139">パスフレーズ</translation>
<translation id="9065203028668620118">編集</translation>
<translation id="9065745800631924235"><ph name="TEXT" /> を履歴から検索</translation>
<translation id="9069693763241529744">拡張機能によってブロック</translation>
-<translation id="9076283476770535406">成人向けコンテンツが含まれている可能性があります</translation>
<translation id="9076630408993835509">このブラウザは、会社またはその他の組織によって管理されていません。このデバイスでのアクティビティは、Chrome 以外で管理されている可能性があります。<ph name="BEGIN_LINK" />詳細<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">その他の情報が必要です</translation>
<translation id="9080712759204168376">ご注文の概要</translation>
<translation id="9089260154716455634">管理時間外のポリシー:</translation>
<translation id="9095388113577226029">その他の言語...</translation>
+<translation id="9098981495403789647">管理者がブラウザで Chrome Enterprise Threat Protection を有効にしています。Chrome Enterprise Threat Protection がユーザーのデータの一部にアクセスできます。</translation>
<translation id="9103872766612412690"><ph name="SITE" /> では通常、暗号化して情報を保護しています。今回、Chromium から <ph name="SITE" /> への接続試行時に、このウェブサイトからいつもとは異なる誤った認証情報が返されました。悪意のあるユーザーが <ph name="SITE" /> になりすまそうとしているか、Wi-Fi ログイン画面で接続が中断された可能性があります。データのやり取りが行われる前に Chromium によって接続が停止されたため、情報は引き続き保護されています。</translation>
<translation id="9106062320799175032">請求先住所の追加</translation>
<translation id="9114524666733003316">カードを確認しています…</translation>
<translation id="9128870381267983090">ネットワークに接続する</translation>
<translation id="9137013805542155359">原文のページを表示</translation>
-<translation id="9137248913990643158">このアプリを使用するには、Chrome を起動してログインしてください。</translation>
<translation id="9141013498910525015">住所を管理</translation>
<translation id="9148088599418889305">配送方法を選択</translation>
<translation id="9148507642005240123">編集の取り消し(&amp;U)</translation>
diff --git a/chromium/components/strings/components_strings_kn.xtb b/chromium/components/strings/components_strings_kn.xtb
index aa94a693fbe..eace5a7938b 100644
--- a/chromium/components/strings/components_strings_kn.xtb
+++ b/chromium/components/strings/components_strings_kn.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">ಕಾರ್ಡ್‌ನಲ್ಲಿರುವ ಹೆಸರನ್ನು ಸೇರಿಸಿ</translation>
<translation id="1089439967362294234">ಪಾಸ್‌ವರ್ಡ್ ಬದಲಾಯಿಸಿ</translation>
+<translation id="1096545575934602868">ಈ ಕ್ಷೇತ್ರವು <ph name="MAX_ITEMS_LIMIT" /> ಗಿಂತ ಹೆಚ್ಚು ನಮೂದುಗಳನ್ನು ಹೊಂದಿರುವಂತಿಲ್ಲ. ಮುಂದಿನ ಎಲ್ಲಾ ನಮೂದುಗಳನ್ನು ತ್ಯಜಿಸಲಾಗುತ್ತದೆ.</translation>
<translation id="109743633954054152">ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು Chrome ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ನಿರ್ವಹಿಸಿ</translation>
<translation id="1103523840287552314">ಯಾವಾಗಲೂ ಅನುವಾದಿಸಿ <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">ಪರಿಶೀಲಿಸಿದರೆ, ವೇಗವಾಗಿ ಫಾರ್ಮ್ ಭರ್ತಿ ಮಾಡಲು Chrome ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ಪ್ರತಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> ನ <ph name="BEGIN_LINK" />ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಕಲನ್ನು<ph name="END_LINK" /> ಪ್ರವೇಶಿಸಿ</translation>
<translation id="1156303062776767266">ನೀವು ಸ್ಥಳೀಯ ಅಥವಾ ಹಂಚಿದ ಫೈಲ್‌ ಅನ್ನು ವೀಕ್ಷಿಸುತ್ತಿದ್ದೀರಿ</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ಅನಿರೀಕ್ಷಿತವಾಗಿ ಸಂಪರ್ಕವನ್ನು ಮುಚ್ಚಿದೆ.</translation>
+<translation id="115926840831309955">ನಿಮ್ಮ CVC ಯನ್ನು ಪರಿಶೀಲಿಸಿ, ಪುನಃ ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಅವಧಿ ಮುಗಿಯುವ ದಿನಾಂಕವನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಿ</translation>
<translation id="1161325031994447685">ವೈ-ಫೈಗೆ ಮರುಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="1165039591588034296">ದೋಷ</translation>
<translation id="1175364870820465910">&amp;ಮುದ್ರಿಸಿ...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"ಸುರಕ್ಷಿತವಾಗಿ ವೆಬ್‌ಗೆ ಸಂಪರ್ಕಿಸುವ Chrome ನ ಕಾರ್ಯವನ್ನು ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿರುವ ಸಾಫ್ಟ್‌ವೇರ್‌ ಸ್ಥಗಿತಗೊಳಿಸಿದೆ" (Windows ಕಂಪ್ಯೂಟರ್‌ಗಳಿಗೆ ಮಾತ್ರ)</translation>
<translation id="1294154142200295408">ಕಮಾಂಡ್-ಲೈನ್ ವ್ಯತ್ಯಾಸಗಳು</translation>
<translation id="129553762522093515">ಇತ್ತೀಚೆಗೆ ಮುಚ್ಚಲಾಗಿರುವುದು</translation>
+<translation id="1298536327547837046">ಮಾಲ್‌ವೇರ್‌ ಸ್ಕ್ಯಾನಿಂಗ್</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />ನಿಮ್ಮ ಕುಕೀಗಳನ್ನು ತೆರವುಗೊಳಿಸಲು ಪ್ರಯತ್ನಿಸಿ<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">ತೆಗೆದುಹಾಕಲಾದ ವೈಶಿಷ್ಟ್ಯಗಳು</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಚಿತ್ರಕ್ಕಾಗಿ ಹುಡುಕಿ</translation>
<translation id="1323433172918577554">ಇನ್ನಷ್ಟು ತೋರಿಸಿ</translation>
@@ -116,6 +120,7 @@
<translation id="1521655867290435174">Google ಶೀಟ್‌ಗಳು</translation>
<translation id="1527263332363067270">ಸಂಪರ್ಕಕ್ಕೆ ಕಾಯಲಾಗುತ್ತಿದೆ...</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">ನೀವು ಇದೀಗ ಭೇಟಿ ನೀಡಲು ಪ್ರಯತ್ನಿಸಿದ ವೆಬ್‌ಸೈಟ್ ನಕಲಿ ವೆಬ್‌ಸೈಟ್‌ನಂತೆ ಕಾಣುತ್ತದೆ. ದಾಳಿಕೋರರು ಕೆಲವೊಮ್ಮೆ ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ನಕಲಿಸುತ್ತಾರೆ ಮತ್ತು URL ನಲ್ಲಿ ಸಣ್ಣ ಪ್ರಮಾಣದ ಅಥವಾ ಗುರುತಿಸಲು ಸಾಧ್ಯವಾಗದ ರೀತಿಯಲ್ಲಿ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡುತ್ತಾರೆ.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">ಈ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
<translation id="153384715582417236">ಇದುವರೆಗೂ ಇಷ್ಟೇ</translation>
@@ -156,7 +161,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">ಟಿಪ್ಪಣಿ ಮಾಡಲು ಡಾಕ್ಯುಮೆಂಟ್‌ ತುಂಬಾ ದೊಡ್ಡದಾಗಿದೆ</translation>
-<translation id="1721312023322545264">ಈ ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ನಿಮಗೆ <ph name="NAME" /> ಅವರ ಅನುಮತಿಯ ಅಗತ್ಯವಿರುತ್ತದೆ</translation>
<translation id="1721424275792716183">* ಈ ಫೀಲ್ಡ್ ಅಗತ್ಯವಿದೆ</translation>
<translation id="1727741090716970331">ಮಾನ್ಯವಾದ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ</translation>
<translation id="1728677426644403582">ನೀವು ವೆಬ್ ಪುಟದ ಮೂಲವನ್ನು ವೀಕ್ಷಿಸುತ್ತಿರುವಿರಿ</translation>
@@ -180,6 +184,7 @@
<translation id="1822540298136254167">ನೀವು ಭೇಟಿ ನೀಡಿರುವ ವೆಬ್‌ಸೈಟ್‌ಗಳು ಮತ್ತು ಅವುಗಳಲ್ಲಿ ನೀವು ಕಳೆದಿರುವ ಸಮಯ</translation>
<translation id="1826516787628120939">ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="1834321415901700177">ಈ ಸೈಟ್ ಹಾನಿಕಾರಕ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಹೊಂದಿದೆ</translation>
+<translation id="1838374766361614909">ಹುಡುಕಾಟ ತೆರವುಗೊಳಿಸಿ</translation>
<translation id="1839551713262164453">ದೋಷಗಳಿರುವ ಕಾರಣ ಕಾರ್ಯನೀತಿಯ ಮೌಲ್ಯಗಳ ಮೌಲ್ಯೀಕರಣವು ವಿಫಲವಾಗಿದೆ</translation>
<translation id="1842969606798536927">ಪಾವತಿಸಿ</translation>
<translation id="1871208020102129563">.pac ಸ್ಕ್ರಿಪ್ಟ್ URL ಅಲ್ಲದೆ, ನಿಗಧಿತ ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್‌ಗಳನ್ನು ಬಳಸಲು ಪ್ರಾಕ್ಸಿಯನ್ನು ಹೊಂದಿಸಲಾಗಿದೆ.</translation>
@@ -190,6 +195,7 @@
<translation id="1883255238294161206">ಪಟ್ಟಿಯನ್ನು ಸಂಕುಚಿಸಿ</translation>
<translation id="1898423065542865115">ಫಿಲ್ಟರಿಂಗ್</translation>
<translation id="1914326953223720820">ಸೇವೆಯನ್ನು ಅನ್ ಜಿಪ್ ಮಾಡಿ</translation>
+<translation id="1915697529809968049">CVC ಬದಲಿಗೆ ಸ್ಪರ್ಶ ಐಡಿಯನ್ನು ಬಳಸುವಿರಾ?</translation>
<translation id="1916770123977586577">ನಿಮ್ಮ ಅಪ್‌ಡೇಟ್‌ ಮಾಡಲಾದ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಈ ಸೈಟ್‌ಗೆ ಅನ್ವಯಿಸಲು, ಈ ಪುಟವನ್ನು ಪುನಃ ಲೋಡ್‌ ಮಾಡಿ</translation>
<translation id="1919345977826869612">ಜಾಹೀರಾತುಗಳು</translation>
<translation id="1919367280705858090">ನಿರ್ದಿಷ್ಟ ದೋಷ ಸಂದೇಶಕ್ಕೆ ಸಹಾಯ ಪಡೆಯಿರಿ</translation>
@@ -201,6 +207,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳು</translation>
<translation id="1973335181906896915">ಅನುಕ್ರಮಗೊಳಿಸುವಿಕೆಯ ದೋಷ</translation>
<translation id="1974060860693918893">ಸುಧಾರಿತ</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />ನೀವು ಭೇಟಿ ನೀಡುವ ಕೆಲವೊಂದು ಪುಟಗಳ URL ಗಳು, ಸಿಸ್ಟಂಗೆ ಸಂಬಂಧಿಸಿದ ಸೀಮಿತ ಮಾಹಿತಿ ಹಾಗೂ ಪುಟದಲ್ಲಿನ ಕೆಲವು ಕಂಟೆಂಟ್<ph name="END_WHITEPAPER_LINK" /> ಅನ್ನು Google ಗೆ ಕಳುಹಿಸುವ ಮೂಲಕ Chrome ನ ಸುರಕ್ಷತೆಯನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಿ. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">ಫರ್ಮ್‌ವೇರ್ ಆವೃತ್ತಿ</translation>
<translation id="1981206234434200693">Chrome ನ ಬ್ರೌಸಿಂಗ್ ಇತಿಹಾಸದ ಡೇಟಾವನ್ನು ತೆರವುಗೊಳಿಸಿ</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ಮತ್ತು 1 ಇನ್ನಷ್ಟು}one{ಮತ್ತು # ಇನ್ನಷ್ಟು}other{ಮತ್ತು # ಇನ್ನಷ್ಟು}}</translation>
@@ -246,10 +253,12 @@
<translation id="2202020181578195191">ಮಾನ್ಯವಾದ ಅವಧಿ-ಮುಕ್ತಾಯ ವರ್ಷವನ್ನು ನಮೂದಿಸಿ</translation>
<translation id="2212735316055980242">ನೀತಿ ಕಂಡು ಬಂದಿಲ್ಲ</translation>
<translation id="2213606439339815911">ನಮೂದುಗಳನ್ನು ಪಡೆಯಲಾಗುತ್ತಿದೆ...</translation>
+<translation id="2215727959747642672">ಫೈಲ್ ಎಡಿಟ್ ಮಾಡುವಿಕೆ</translation>
<translation id="2218879909401188352">ದಾಳಿಕೋರರು ಪ್ರಸ್ತುತ <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ನಲ್ಲಿದ್ದಾರೆ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಹಾನಿಯನ್ನುಂಟು ಮಾಡುವ ಅಪಾಯಕಾರಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಬಹುದು, ನಿಮ್ಮ ಮೊಬೈಲ್ ಬಿಲ್‌ಗೆ ಮರೆಮಾಡಿದ ಶುಲ್ಕಗಳನ್ನು ಸೇರಿಸಬಹುದು, ಅಥವಾ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಕದಿಯಬಹುದು. <ph name="BEGIN_LEARN_MORE_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />ಡಯಾಗ್ನಸ್ಟಿಕ್ಸ್‌‌ ಅಪ್ಲಿಕೇಶನ್‌<ph name="END_LINK" /> ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಿ</translation>
<translation id="2239100178324503013">ಈಗ ಕಳುಹಿಸಿ</translation>
+<translation id="2248949050832152960">WebAuthn ಬಳಸಿ</translation>
<translation id="225207911366869382">ಈ ನೀತಿಗಾಗಿ ಈ ಮೌಲ್ಯವನ್ನು ಅಸಮ್ಮತಿಸಲಾಗಿದೆ.</translation>
<translation id="2257315177824333709">ಕ್ಷಮಿಸಿ, ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಇದೀಗ ಉಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ</translation>
<translation id="2262243747453050782">HTTP ದೋಷ</translation>
@@ -296,7 +305,6 @@
<translation id="2479410451996844060">ಅಮಾನ್ಯವಾದ ಹುಡುಕಾಟ URL.</translation>
<translation id="2482878487686419369">ಸೂಚನೆಗಳು</translation>
<translation id="248348093745724435">ಯಂತ್ರದ ಕಾರ್ಯನೀತಿಗಳು</translation>
-<translation id="2485387744899240041">ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಬ್ರೌಸರ್‌ಗಾಗಿ ಬಳಕೆದಾರ ಹೆಸರುಗಳು</translation>
<translation id="2491120439723279231">ಸರ್ವರ್‌ನ ಪ್ರಮಾಣಪತ್ರವು ದೋಷಗಳನ್ನು ಹೊಂದಿದೆ.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON ವಿಶ್ಲೇಷಕ</translation>
@@ -306,6 +314,7 @@
<translation id="2501278716633472235">ಹಿಂದಿರುಗಿ</translation>
<translation id="2503184589641749290">ಸಮ್ಮತಿಸಲಾದ ಡೆಬಿಟ್ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್ ಕಾರ್ಡ್‌ಗಳು</translation>
<translation id="2505268675989099013">ಖಾತೆಯನ್ನು ಸಂರಕ್ಷಿಸಿ</translation>
+<translation id="2515335152965840738">ನಿರ್ಲಕ್ಷಿಸಿ</translation>
<translation id="2515629240566999685">ನಿಮ್ಮ ಪ್ರದೇಶದಲ್ಲಿನ ಸಿಗ್ನಲ್ ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="2523886232349826891">ಈ ಸಾಧನದಲ್ಲಿ ಮಾತ್ರ ಉಳಿಸಲಾಗಿದೆ</translation>
<translation id="2524461107774643265">ಇನ್ನಷ್ಟು ಮಾಹಿತಿಯನ್ನು ಸೇರಿಸಿ</translation>
@@ -330,7 +339,6 @@
<translation id="2653659639078652383">ಸಲ್ಲಿಸು</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{ಒಂದೂ ಇಲ್ಲ}=1{1 ಪಾಸ್‌ವರ್ಡ್ (<ph name="DOMAIN_LIST" /> ಗೆ ಸಂಬಂಧಿಸಿದ್ದು)}=2{2 ಪಾಸ್‌ವರ್ಡ್‌ಗಳು (<ph name="DOMAIN_LIST" /> ಗೆ ಸಂಬಂಧಿಸಿದ್ದು)}one{# ಪಾಸ್‌ವರ್ಡ್‌ಗಳು (<ph name="DOMAIN_LIST" /> ಗೆ ಸಂಬಂಧಿಸಿದ್ದು)}other{# ಪಾಸ್‌ವರ್ಡ್‌ಗಳು (<ph name="DOMAIN_LIST" /> ಗೆ ಸಂಬಂಧಿಸಿದ್ದು)}}</translation>
<translation id="2666117266261740852">ಇತರ ಟ್ಯಾಬ್‌ಗಳು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್‍ಗಳನ್ನು ಮುಚ್ಚಿ</translation>
-<translation id="267371737713284912">ರದ್ದುಗೊಳಿಸಲು <ph name="MODIFIER_KEY_DESCRIPTION" /> ಒತ್ತಿರಿ</translation>
<translation id="2674170444375937751">ನಿಮ್ಮ ಇತಿಹಾಸದಿಂದ ನೀವು ಈ ಪುಟಗಳನ್ನು ಖಚಿತವಾಗಿ ಅಳಿಸಲು ಬಯಸುತ್ತಿದ್ದೀರಾ?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">ತೊರೆಯಿರಿ</translation>
@@ -340,12 +348,12 @@
<translation id="2704283930420550640">ಮೌಲ್ಯವು ಸ್ವರೂಪಕ್ಕೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ.</translation>
<translation id="2705137772291741111">ಈ ಸೈಟ್‌ನ ಉಳಿಸಿದ (ಸಂಗ್ರಹವಾಗಿರುವ) ನಕಲನ್ನು ಓದಲಾಗುತ್ತಿಲ್ಲ.</translation>
<translation id="2709516037105925701">ಸ್ವಯಂತುಂಬುವಿಕೆ</translation>
-<translation id="2712173769900027643">ಅನುಮತಿ ಕೇಳಿ</translation>
<translation id="2713444072780614174">ಬಿಳಿ</translation>
<translation id="2720342946869265578">ಸಮೀಪ ಸಾಧನ</translation>
<translation id="2721148159707890343">ವಿನಂತಿಯನ್ನು ಯಶಸ್ವಿಗೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="2728127805433021124">ಕ್ಷೀಣವಾದ ಸಹಿ ಅಲ್ಗಾರಿದಮ್ ಬಳಸಿಕೊಂಡು ಸರ್ವರ್‌ನ ಪ್ರಮಾಣಪತ್ರಕ್ಕೆ ಸಹಿ ಮಾಡಲಾಗಿದೆ.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />ಸಂಪರ್ಕ ಡಯಾಗ್ನಾಸ್ಟಿಕ್ಸ್‌ ರನ್ ಆಗುತ್ತಿದೆ<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">ಈ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದರಿಂದ, ನೀವು ಬ್ರೌಸಿಂಗ್‌ ಡೇಟಾವನ್ನು ಕಳೆದುಕೊಳ್ಳಬಹುದು ಅಥವಾ ನಿಮ್ಮ ಸುರಕ್ಷತೆ ಅಥವಾ ಗೌಪ್ಯತೆಗೆ ಧಕ್ಕೆ ಉಂಟಾಗಬಹುದು. ಸಕ್ರಿಯಗೊಳಿಸಲಾದ ವೈಶಿಷ್ಟ್ಯಗಳು ಈ ಬ್ರೌಸರ್‌ ಬಳಸುವ ಎಲ್ಲಾ ಬಳಕೆದಾರರಿಗೆ ಅನ್ವಯವಾಗುತ್ತವೆ.</translation>
<translation id="2735043616039983645">ಸಂಘರ್ಷವನ್ನು ಉಂಟುಮಾಡುವ ಮೌಲ್ಯಗಳನ್ನು ಹೊಂದಿರುವ ಒಂದಕ್ಕಿಂತ ಹೆಚ್ಚು ಮೂಲಗಳು ಈ ಕಾರ್ಯನೀತಿಗಾಗಿ ಅಸ್ತಿತ್ವದಲ್ಲಿವೆ!</translation>
<translation id="2738330467931008676">ಪಿಕಪ್ ವಿಳಾಸವನ್ನು ಆರಿಸಿ</translation>
<translation id="2740531572673183784">ಸರಿ</translation>
@@ -356,16 +364,15 @@
<translation id="2784949926578158345">ಸಂಪರ್ಕವನ್ನು ರೀಸೆಟ್ ಮಾಡಲಾಗಿದೆ.</translation>
<translation id="2788784517760473862">ಸ್ವೀಕೃತ ಕ್ರೆಡಿಟ್‌ ಕಾರ್ಡ್‌ಗಳು</translation>
<translation id="2792012897584536778">ಈ ಸಾಧನದ ನಿರ್ವಾಹಕರು ಭದ್ರತೆಯ ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಸೆಟಪ್ ಮಾಡಿದ್ದು, ಅದು ನೀವು ಭೇಟಿ ನೀಡುವ ವೆಬ್‌ಸೈಟ್‌ಗಳಲ್ಲಿನ ವಿಷಯವನ್ನು ನೋಡಲು ಅವರನ್ನು ಅನುಮತಿಸಬಹುದು.</translation>
-<translation id="2794233252405721443">ಸೈಟ್ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
<translation id="2799020568854403057">ಮುಂದಿರುವ ಸೈಟ್‌ನಲ್ಲಿ ಹಾನಿಕಾರಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿವೆ</translation>
<translation id="2799223571221894425">ಮರುಪ್ರಾರಂಭಿಸು</translation>
<translation id="2803306138276472711">Google ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್ ಇತ್ತೀಚೆಗೆ <ph name="SITE" /> ನಲ್ಲಿ <ph name="BEGIN_LINK" />ಮಾಲ್‌ವೇರ್ ಪತ್ತೆಹಚ್ಚಿದೆ<ph name="END_LINK" />. ವೆಬ್‌ಸೈಟ್‌ಗಳು ಸಾಮಾನ್ಯವಾಗಿ ಸುರಕ್ಷಿತವಾಗಿದ್ದರೂ, ಕೆಲವೊಮ್ಮೆ ಮಾಲ್‌ವೇರ್‌ಗೆ ತುತ್ತಾಗಿರುತ್ತವೆ.</translation>
+<translation id="2815364696811431560">ಸೈಟ್‌ ಅನ್ನು ತೊರೆಯಿರಿ</translation>
<translation id="2824775600643448204">ವಿಳಾಸ ಹಾಗೂ ಹುಡುಕಾಟ ಪಟ್ಟಿ</translation>
<translation id="2826760142808435982"><ph name="CIPHER" /> ಬಳಸಿಕೊಂಡು ಸಂಪರ್ಕವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ದೃಢೀಕರಿಸಲಾಗಿದೆ ಮತ್ತು <ph name="KX" /> ಅನ್ನು ಕೀ ವಿನಿಮಯ ಯಾಂತ್ರಿಕತೆಯಂತೆ ಬಳಸುತ್ತದೆ.</translation>
<translation id="2835170189407361413">ಫಾರ್ಮ್ ತೆರವುಗೊಳಿಸು</translation>
<translation id="2847118875340931228">ಅದೃಶ್ಯ ವಿಂಡೋವನ್ನು ತೆರೆಯಿರಿ</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">ಈ ಸೈಟ್‌ ಗೆ ಭೇಟಿ ನೀಡಲು ನಿಮ್ಮಗೆ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ</translation>
<translation id="2856444702002559011">ದಾಳಿಕೋರರು <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ನಿಂದ ನಿಮ್ಮ ಮಾಹಿತಿಯನ್ನು ಕದಿಯಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರಬಹುದು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಸಂದೇಶಗಳು ಅಥವಾ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು). <ph name="BEGIN_LEARN_MORE_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">ಕಾರ್ಡ್‌ ಉಳಿಸುವುದೇ?</translation>
@@ -390,6 +397,7 @@
<translation id="2985306909656435243">ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದರೆ, ವೇಗವಾಗಿ ಫಾರ್ಮ್ ಭರ್ತಿ ಮಾಡಲು Chromium ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ಪ್ರತಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.</translation>
<translation id="2985398929374701810">ಮಾನ್ಯ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ</translation>
<translation id="2986368408720340940">ಈ ಪಿಕಪ್ ವಿಧಾನ ಲಭ್ಯವಿಲ್ಲ. ಬೇರೊಂದು ವಿಧಾನವನ್ನು ಪ್ರಯತ್ನಿಸಿ.</translation>
+<translation id="2987034854559945715">ಯಾವುದೇ ಹೊಂದಾಣಿಕೆಯ ವೈಶಿಷ್ಟ್ಯಗಳು ಕಂಡುಬಂದಿಲ್ಲ</translation>
<translation id="2991174974383378012">ವೆಬ್‌ಸೈಟ್‌ಗಳ ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳುವುದು</translation>
<translation id="2991571918955627853">ವೆಬ್‌ಸೈಟ್ HSTS ಅನ್ನು ಬಳಸುವ ಕಾರಣದಿಂದ ನೀವು ಸದ್ಯಕ್ಕೆ <ph name="SITE" /> ಅನ್ನು ಭೇಟಿ ನೀಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ನೆಟ್‌ವರ್ಕ್ ದೋಷಗಳು ಮತ್ತು ಆಕ್ರಮಣಗಳು ಸಾಮಾನ್ಯವಾಗಿ ತಾತ್ಕಾಲಿಕವಾಗಿವೆ, ಹಾಗಾಗಿ ಈ ಪುಟವು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಕಾರ್ಯ ನಿರ್ವಹಿಸಬಹುದು.</translation>
<translation id="3005723025932146533">ಉಳಿಸಲಾದ ನಕಲನ್ನು ತೋರಿಸು</translation>
@@ -400,6 +408,7 @@
<translation id="3024663005179499861">ತಪ್ಪಾದ ನೀತಿಯ ಪ್ರಕಾರ</translation>
<translation id="3037605927509011580">ಓಹ್, ಹೋಯ್ತು!</translation>
<translation id="3041612393474885105">ಪ್ರಮಾಣಪತ್ರ ಮಾಹಿತಿ</translation>
+<translation id="3057676462092457419">DnsOverHttps ಮೋಡ್ <ph name="SECURE_DNS_MODE_SECURE" /> ಇನ್ನೂ ಬೆಂಬಲಿಸುತ್ತಿಲ್ಲ, ಮೋಡ್ ಅನ್ನು <ph name="SECURE_DNS_MODE_OFF" /> ಗೆ ಹೊಂದಿಸಲಾಗಿದೆ.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">ಪ್ಯಾಚ್ ಸೇವೆ</translation>
<translation id="3064966200440839136">ಬಾಹ್ಯ ಅಪ್ಲಿಕೇಶನ್‌‌ ಮೂಲಕರ ಪಾವತಿಸಲು ಅದೃಶ್ಯ ಮೋಡ್‌‌ ತೊರೆಯಲಾಗುತ್ತಿದೆ. ಮುಂದುವರಿಸುವುದೇ?</translation>
@@ -423,6 +432,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> ನಲ್ಲಿ <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">ಪಾವತಿಯನ್ನು ರದ್ದುಮಾಡಿ</translation>
<translation id="3207960819495026254">ಬುಕ್‌ಮಾರ್ಕ್‌ ಮಾಡಲಾಗಿದೆ</translation>
+<translation id="3209034400446768650">ಈ ಪುಟವು, ಶುಲ್ಕ ವಿಧಿಸಬಹುದು</translation>
<translation id="3225919329040284222">ಆಂತರಿಕ ಮಾನದಂಡಗಳಿಗೆ ಹೊಂದಿಕೆಯಾಗದ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಸರ್ವರ್ ಹಾಜರಿಪಡಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷತೆಯ ಸಲುವಾಗಿ ಕೆಲವು ಹೆಚ್ಚು ಸುರಕ್ಷಿತ ವೆಬ್ ಸೈಟ್‌ಗಳಲ್ಲಿ ಈ ಮಾನದಂಡಗಳನ್ನು ಸೇರ್ಪಡೆಗೊಳಿಸಲಾಗಿದೆ.</translation>
<translation id="3226128629678568754">ಪುಟವನ್ನು ಲೋಡ್ ಮಾಡುವುದಕ್ಕೆ ಅಗತ್ಯವಿರುವ ಡೇಟಾವನ್ನು ಮರುಸಲ್ಲಿಸಲು ಮರುಲೋಡ್ ಬಟನ್ ಒತ್ತಿರಿ.</translation>
<translation id="3227137524299004712">ಮೈಕ್ರೋಫೋನ್</translation>
@@ -430,7 +440,6 @@
<translation id="3229041911291329567">ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಬ್ರೌಸರ್ ಕುರಿತು ಆವೃತ್ತಿಯ ಮಾಹಿತಿ</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> ಗೆ CVC ಅನ್ನು ನಮೂದಿಸಿ</translation>
<translation id="3234666976984236645">ಈ ಸೈಟ್‌ನಲ್ಲಿ ಯಾವಾಗೂ ಮುಖ್ಯ ವಿಷಯವನ್ನು ಹುಡುಕಿ</translation>
-<translation id="3254409185687681395">ಈ ಪುಟ ಬುಕ್‌ಮಾರ್ಕ್ ಮಾಡಿ</translation>
<translation id="3270847123878663523">&amp;ಮರುಕ್ರಮಗೊಳಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸು</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">ಕಾರ್ಡ್‌ನಲ್ಲಿರುವ ಹೆಸರನ್ನು ಸೇರಿಸಿ</translation>
@@ -440,7 +449,6 @@
<translation id="3320021301628644560">ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸವನ್ನು ಸೇರಿಸಿ</translation>
<translation id="3324983252691184275">ಕಡುಗೆಂಪು</translation>
<translation id="3338095232262050444">ಸುರಕ್ಷಿತ</translation>
-<translation id="3345135638360864351">ಈ ಸೈಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಸಲ್ಲಿಸಿದ ವಿನಂತಿಯನ್ನು <ph name="NAME" /> ಗೆ ಕಳುಹಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="3355823806454867987">ಪ್ರಾಕ್ಸಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಿಸಿ...</translation>
<translation id="3361596688432910856">ಈ ಮುಂದಿನ ಮಾಹಿತಿಯನ್ನು Chrome ಗೆ <ph name="BEGIN_EMPHASIS" />ಉಳಿಸಲು ಆಗುವುದಿಲ್ಲ<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -474,18 +482,15 @@
<translation id="3462200631372590220">ಸುಧಾರಿತ ಆಯ್ಕೆಮಾಡಿ</translation>
<translation id="3467763166455606212">ಕಾರ್ಡ್‌ಹೋಲ್ಡರ್ ಹೆಸರು ಅಗತ್ಯವಿದೆ</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, ಪ್ರಸ್ತುತ ತೆರೆದಿದೆ, ತೆರೆದಿರುವ ಟ್ಯಾಬ್‌ಗೆ ಬದಲಾಯಿಸಲು, Tab ಒತ್ತಿ, ನಂತರ Enter ಒತ್ತಿರಿ</translation>
-<translation id="3479539252931486093">ಇದು ಅನಿರೀಕ್ಷಿತವೇ? <ph name="BEGIN_LINK" />ನಮಗೆ ತಿಳಿಸಿ<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">ಈಗ ಬೇಡ</translation>
<translation id="3484560055331845446">ನಿಮ್ಮ Google ಖಾತೆಗೆ ನೀವು ಪ್ರವೇಶವನ್ನು ಕಳೆದುಕೊಳ್ಳಬಹುದು. ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಈಗಲೇ ಬದಲಾಯಿಸುವಂತೆ Chrome ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ. ಸೈನ್ ಇನ್ ಮಾಡಲು ನಿಮ್ಮನ್ನು ಕೇಳಲಾಗುತ್ತದೆ.</translation>
<translation id="3495081129428749620">ಪುಟದಲ್ಲಿ ಹುಡುಕಿ
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">ಈ ಕ್ಷಣದಲ್ಲಿ ನಿಮ್ಮ ಪೋಷಕರನ್ನು ತಲುಪಲು ನಮಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="3512163584740124171">ಈ ಕಾರ್ಯನೀತಿಯನ್ನು ನಿರ್ಲಕ್ಷಿಸಲಾಗುತ್ತದೆ ಏಕೆಂದರೆ, ಅದೇ ಕಾರ್ಯನೀತಿಯ ಗುಂಪಿನ ಮತ್ತೊಂದು ಕಾರ್ಯನೀತಿಯು ಹೆಚ್ಚಿನ ಆದ್ಯತೆಯನ್ನು ಹೊಂದಿದೆ.</translation>
<translation id="3528171143076753409">ಸರ್ವರ್‌ನ ಪ್ರಮಾಣಪತ್ರ ನಂಬಲರ್ಹವಾಗಿಲ್ಲ.</translation>
<translation id="3528485271872257980">ಗಾಢ ಕಂದು</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{ಸಿಂಕ್ ಮಾಡಿದ ಸಾಧನಗಳಲ್ಲಿ ಕನಿಷ್ಠ 1 ಐಟಂ}=1{1 ಐಟಂ (ಮತ್ತು ಸಿಂಕ್ ಮಾಡಿದ ಸಾಧನಗಳಲ್ಲಿ ಇನ್ನಷ್ಟು ಐಟಂಗಳು)}one{# ಐಟಂಗಳು (ಮತ್ತು ಸಿಂಕ್ ಮಾಡಿದ ಸಾಧನಗಳಲ್ಲಿ ಇನ್ನಷ್ಟು ಐಟಂಗಳು)}other{# ಐಟಂಗಳು (ಮತ್ತು ಸಿಂಕ್ ಮಾಡಿದ ಸಾಧನಗಳಲ್ಲಿ ಇನ್ನಷ್ಟು ಐಟಂಗಳು)}}</translation>
<translation id="3539171420378717834">ಈ ಸಾಧನದಲ್ಲಿ ಈ ಕಾರ್ಡ್‌ನ ನಕಲನ್ನು ಇರಿಸಿಕೊಳ್ಳಿ</translation>
-<translation id="3556433843310711081">ನಿಮ್ಮ ಮ್ಯಾನೇಜರ್ ನಿಮಗಾಗಿ ಅದನ್ನು ಅನಿರ್ಬಂಧಿಸಬಹುದಾಗಿದೆ</translation>
<translation id="3566021033012934673">ನಿಮ್ಮ ಸಂಪರ್ಕವು ಖಾಸಗಿಯಲ್ಲ</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> ನಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
@@ -512,6 +517,7 @@
<translation id="3678529606614285348">ಪುಟವನ್ನು ಹೊಸ ಅದೃಶ್ಯ ವಿಂಡೋದಲ್ಲಿ ತೆರೆಯಿರಿ (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375"><ph name="CRASH_TIME" /> ನಲ್ಲಿ ಕ್ರ್ಯಾಶ್ ವರದಿಯನ್ನು ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ, <ph name="UPLOAD_TIME" /> ಸಮಯಕ್ಕೆ ಅಪ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ</translation>
<translation id="3681007416295224113">ಪ್ರಮಾಣಪತ್ರ ಮಾಹಿತಿ</translation>
+<translation id="3701427423622901115">ಮರುಹೊಂದಿಸುವಿಕೆಯನ್ನು ಅಂಗೀಕರಿಸಲಾಗಿದೆ.</translation>
<translation id="3704162925118123524">ನೀವು ಬಳಸುತ್ತಿರುವ ನೆಟ್‌ವರ್ಕ್‌ನ ಲಾಗಿನ್ ಪುಟಕ್ಕೆ ಭೇಟಿ ನೀಡಬೇಕಾದ ಅಗತ್ಯವಿದೆ.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">ಲೋಡ್ ಆಗುತ್ತಿದೆ...</translation>
@@ -528,6 +534,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ನಲ್ಲಿನ ಆಕ್ರಮಣಕಾರರು ಸಾಫ್ಟ್‌ವೇರ್ ಸ್ಥಾಪಿಸುವಿಕೆ ಅಥವಾ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಬಹಿರಂಗ ಪಡಿಸುವಂತಹ ಅಪಾಯಕಾರಿಯಾಗಿ ಏನಾದರೂ ಮಾಡುವಂತಹ ಮೋಸವನ್ನು ಮಾಡಬಹುದು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಫೋನ್‌ ಸಂಖ್ಯೆಗಳು ಅಥವಾ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು). <ph name="BEGIN_LEARN_MORE_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">ಸರ್ವರ್ ದೋಷದ ಕಾರಣ ಅನುವಾದವು ವಿಫಲವಾಗಿದೆ.</translation>
<translation id="3759461132968374835">ಇತ್ತೀಚೆಗೆ ನೀವು ಯಾವುದೇ ಕ್ರ‍್ಯಾಶ್‌ಗಳನ್ನು ವರದಿ ಮಾಡಿಲ್ಲ. ಕ್ರ‍್ಯಾಶ್‌‌ ಅನ್ನು ವರದಿಮಾಡುವಿಕೆಯನ್ನು ಉಂಟಾಗಿರುವ ಕ್ರ‍್ಯಾಶ್‌ಗಳು ಇಲ್ಲಿ ಗೋಚರಿಸುವುದಿಲ್ಲ.</translation>
+<translation id="3760561303380396507">CVC ಬದಲಿಗೆ Windows Hello ಬಳಸುವಿರಾ?</translation>
<translation id="3761718714832595332">ಸ್ಥಿತಿಯನ್ನು ಮರೆಮಾಡಿ</translation>
<translation id="3765032636089507299">ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್ ಪುಟವು ನಿರ್ಮಾಣ ಹಂತದಲ್ಲಿದೆ.</translation>
<translation id="3778403066972421603">ಈ ಕಾರ್ಡ್‌ ಅನ್ನು ನಿಮ್ಮ Google ಖಾತೆ ಮತ್ತು ಈ ಸಾಧನದಲ್ಲಿ ಉಳಿಸಲು ಬಯಸುವಿರಾ?</translation>
@@ -537,6 +544,7 @@
<translation id="3789155188480882154">ಗಾತ್ರ 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">ಹಾನಿಕಾರಕ ವಿಷಯವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ.</translation>
+<translation id="3808375843007691220">ಎಚ್ಚರಿಕೆ: ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಮುಂದೆ ಬರಲಿವೆ!</translation>
<translation id="3810973564298564668">ನಿರ್ವಹಿಸು</translation>
<translation id="382518646247711829">ನೀವು ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್ ಬಳಸಿದರೆ...</translation>
<translation id="3828924085048779000">ಖಾಲಿ ಪಾಸ್‌ಫ್ರೇಸ್ ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ.</translation>
@@ -545,11 +553,11 @@
<translation id="3858027520442213535">ದಿನಾಂಕ ಮತ್ತು ಸಮಯವನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಿ</translation>
<translation id="3884278016824448484">ಸಂಘರ್ಷಗೊಳ್ಳುತ್ತಿರುವ ಸಾಧನ ಗುರುತಿಸುವಿಕೆ</translation>
<translation id="3885155851504623709">ಪಾರಿಷ್</translation>
-<translation id="3886446263141354045">ಈ ಸೈಟ್‌ಗೆ ಪ್ರವೇಶಿಸುವ ನಿಮ್ಮ ವಿನಂತಿಯನ್ನು <ph name="NAME" /> ಅವರಿಗೆ ಕಳುಹಿಸಲಾಗಿದೆ</translation>
<translation id="3890664840433101773">ಇಮೇಲ್ ಸೇರಿಸಿ</translation>
<translation id="3901925938762663762">ಕಾರ್ಡ್ ಅವಧಿಯು ಮುಗಿದಿದೆ</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVC ಬದಲಿಗೆ WebAuthn ಬಳಸುವಿರಾ?</translation>
<translation id="3946209740501886391">ಯಾವಾಗಲೂ ಈ ಸೈಟ್‌ನಲ್ಲಿ ಕೇಳಿ</translation>
<translation id="3949571496842715403">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣ ಪತ್ರವು ವಿಷಯವಸ್ತು ಪರ್ಯಾಯ ಹೆಸರುಗಳನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿಲ್ಲ. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
<translation id="3949601375789751990">ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್ ಇತಿಹಾಸ ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ</translation>
@@ -560,11 +568,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ಯಾವುದೂ ಇಲ್ಲ}=1{1 ಸೈಟ್‌ನಿಂದ }one{# ಸೈಟ್‌ಗಳಿಂದ }other{# ಸೈಟ್‌ಗಳಿಂದ }}</translation>
<translation id="397105322502079400">ಎಣಿಸಲಾಗುತ್ತಿದೆ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
+<translation id="3981540111851280311">ನಿಮ್ಮ ಬ್ರೌಸರ್‌ನಲ್ಲಿ Chrome ಎಂಟರ್‌ಪ್ರೈಸ್ ಬೆದರಿಕೆ ರಕ್ಷಣೆಯನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಸಕ್ರಿಯಗೊಳಿಸಿದೆ. Chrome ಎಂಟರ್‌ಪ್ರೈಸ್ ಬೆದರಿಕೆ ರಕ್ಷಣೆಯು ನಿಮ್ಮ ಕೆಲವು ಡೇಟಾಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿದೆ.</translation>
<translation id="3987940399970879459">1 MB ಗಿಂತ ಕಡಿಮೆ</translation>
<translation id="40103911065039147">{URL_count,plural, =1{ಹತ್ತಿರದ 1 ವೆಬ್ ಪುಟ}one{ಹತ್ತಿರದ # ವೆಬ್ ಪುಟಗಳು}other{ಹತ್ತಿರದ # ವೆಬ್ ಪುಟಗಳು}}</translation>
<translation id="4030383055268325496">&amp;ಸೇರಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸಿ</translation>
<translation id="4032320456957708163">ನಿಮ್ಮ ಬ್ರೌಸರ್ ಅನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ನಿರ್ವಹಿಸುತ್ತಿದೆ</translation>
-<translation id="4034375457890803692">ನೀವು ತೆರೆದ ಲಿಂಕ್, ನೀವು ಸಾಮಾನ್ಯವಾಗಿ ಭೇಟಿ ನೀಡದ ಸೈಟ್‌ಗೆ ಹೋಗುತ್ತದೆ. ಅದು ನಿಮಗೆ ಗೊಂದಲ ಉಂಟುಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರಬಹುದು.</translation>
<translation id="4058922952496707368">ಕೀ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">ಮಾನ್ಯವಾದ ವಿಳಾಸ ಸೇರಿಸಿ</translation>
@@ -577,6 +585,7 @@
<translation id="4103249731201008433">ಸಾಧನದ ಸರಣಿಯ ಸಂಖ್ಯೆ ಅಮಾನ್ಯವಾಗಿದೆ</translation>
<translation id="410351446219883937">ಆಟೋಪ್ಲೇ</translation>
<translation id="4103763322291513355">ನಿಮ್ಮ ಸಿಸ್ಟಂ ನಿರ್ವಾಹಕರು ವಿಧಿಸಿರುವ ಕಪ್ಪುಪಟ್ಟಿಯ URLಗಳು ಮತ್ತು ಇತರ ನೀತಿಗಳನ್ನು ವೀಕ್ಷಿಸಲು &lt;strong&gt;chrome://policy&lt;/strong&gt; ಗೆ ಭೇಟಿ ನೀಡಿ.</translation>
+<translation id="4108231218301530806">ಮುಂದಿನ ಬಾರಿ ಈ ಕಾರ್ಡ್ ಪರಿಶೀಲಿಸಲು ಫಿಂಗರ್‌ ಪ್ರಿಂಟ್ ಬಳಸಿ.</translation>
<translation id="4110652170750985508">ನಿಮ್ಮ ಪಾವತಿಯನ್ನು ಪರಿಶೀಲಿಸಿ</translation>
<translation id="4112140312785995938">ಹಿಂದಕ್ಕೆ ಸೀಕ್ ಮಾಡಿ</translation>
<translation id="4116663294526079822">ಈ ಸೈಟ್‌ನಲ್ಲಿ ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ</translation>
@@ -591,6 +600,7 @@
<translation id="4171400957073367226">ತಪ್ಪು ಪರಿಶೀಲನೆ ಸಹಿ</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> ಹೆಚ್ಚಿನ ಐಟಂ}one{<ph name="ITEM_COUNT" /> ಹೆಚ್ಚಿನ ಐಟಂಗಳು}other{<ph name="ITEM_COUNT" /> ಹೆಚ್ಚಿನ ಐಟಂಗಳು}}</translation>
+<translation id="4176463684765177261">ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">ಮುಂದಿನ ಬಾರಿ ವೇಗವಾಗಿ ಪಾವತಿಸಲು, ನಿಮ್ಮ ಕಾರ್ಡ್ ಮತ್ತು ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸವನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಸೇರಿಸಿ.</translation>
<translation id="4196861286325780578">&amp;ಸರಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
@@ -627,6 +637,7 @@
<translation id="4277028893293644418">ಪಾಸ್‌ವರ್ಡ್ ಮರುಹೊಂದಿಸಿ</translation>
<translation id="4279811152705618813">ನಿಮ್ಮ <ph name="DEVICE_TYPE" /> ಸಾಧನವನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಡೊಮೇನ್ ನಿರ್ವಹಿಸುತ್ತಿದೆ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ಈ ಕಾರ್ಡ್ ಅನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ}one{ಈ ಕಾರ್ಡ್‌ಗಳನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ}other{ಈ ಕಾರ್ಡ್‌ಗಳನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ}}</translation>
+<translation id="428847186335018806">ನೀವು Chrome ನಲ್ಲಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡುವ ಅಥವಾ ಅಪ್‌ಲೋಡ್ ಮಾಡುವ ಫೈಲ್‌ಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ.</translation>
<translation id="42981349822642051">ವಿಸ್ತರಿಸಿ</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">ಬದಲಿಸಿ</translation>
@@ -656,7 +667,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">ಪ್ರಾಕ್ಸಿಯ ಬಳಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಆದರೆ ಬಹಿರಂಗ ಪ್ರಾಕ್ಸಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿದೆ.</translation>
<translation id="445100540951337728">ಸಮ್ಮತಿಸಲಾದ ಡೆಬಿಟ್ ಕಾರ್ಡ್‌ಗಳು</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> ಅನುಮಾನಾಸ್ಪದ ವರ್ತನೆ</translation>
<translation id="4466881336512663640">ಫಾರ್ಮ್‌ನಲ್ಲಿ ಮಾಡಿರುವ ಬದಲಾವಣೆಗಳು ಕಳೆದು ಹೋಗುತ್ತವೆ. ನೀವು ಖಂಡಿತವಾಗಿಯೂ ಮುಂದುವರಿಯಲು ಬಯಸುತ್ತೀರಾ?</translation>
<translation id="4477350412780666475">ಮುಂದಿನ ಟ್ರ್ಯಾಕ್</translation>
<translation id="4482953324121162758">ಈ ಸೈಟ್ ಅನುವಾದಕ್ಕೆ ಒಳಪಡುವುದಿಲ್ಲ.</translation>
@@ -683,6 +693,7 @@
<translation id="4594403342090139922">&amp;ಅಳಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸಿ</translation>
<translation id="4597348597567598915">ಗಾತ್ರ 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಹುಡುಕಿ</translation>
<translation id="4646534391647090355">ನನ್ನನ್ನು ಈಗ ಅಲ್ಲಿಗೆ ಕರೆದೊಯ್ಯಿರಿ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣಪತ್ರದಲ್ಲಿ ಸಾಕಷ್ಟು ದೋಷಗಳಿವೆ. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
@@ -691,7 +702,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">ನಿಮ್ಮ ಸಂಪರ್ಕಕ್ಕೆ ಅಡ್ಡಿಯಾಗಿದೆ</translation>
-<translation id="471880041731876836">ಈ ಸೈಟ್‌ ಗೆ ಭೇಟಿ ನೀಡಲು ನೀವು ಅನುಮತಿ ಹೊಂದಿಲ್ಲ</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ನೆಟ್‌ವರ್ಕ್ ಡಯಾಗ್ನಾಸ್ಟಿಕ್ಸ್ ರನ್ ಮಾಡಲಾಗುತ್ತಿದೆ<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">ನೀತಿಗಳನ್ನು ಮರುಲೋಡ್ ಮಾಡಿ</translation>
<translation id="4728558894243024398">ಪ್ಲಾಟ್‌ಫಾರ್ಮ್</translation>
@@ -719,7 +729,6 @@
<translation id="4816492930507672669">ಪುಟಕ್ಕೆ ಹೊಂದಿಸು</translation>
<translation id="4850886885716139402">ವೀಕ್ಷಣೆ</translation>
<translation id="4854362297993841467">ಈ ವಿತರಣೆಯ ವಿಧಾನ ಲಭ್ಯವಿಲ್ಲ. ಬೇರೊಂದು ವಿಧಾನವನ್ನು ಪ್ರಯತ್ನಿಸಿ.</translation>
-<translation id="4858792381671956233">ಈ ಸೈಟ್ ಅನ್ನು ಭೇಟಿ ಮಾಡಬಹುದು ಎಂದು ನಿಮ್ಮ ಪೋಷಕರಿಗೆ ನೀವು ಕೇಳಿರುವಿರಿ.</translation>
<translation id="4864052566555297930">ಸುರಕ್ಷತೆಯ ಸಲಹೆ:</translation>
<translation id="4876188919622883022">ಸರಳೀಕೃತ ವೀಕ್ಷಣೆ</translation>
<translation id="4876305945144899064">ಯಾವುದೇ ಬಳಕೆದಾರರ ಹೆಸರಿಲ್ಲ</translation>
@@ -743,7 +752,9 @@
<translation id="4974590756084640048">ಎಚ್ಚರಿಕೆಗಳನ್ನು ಮರುಸಕ್ರಿಯಗೊಳಿಸಿ</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">ಎಲ್ಲವನ್ನೂ ನೋಡಿ</translation>
+<translation id="4989542687859782284">ಲಭ್ಯವಿಲ್ಲ</translation>
<translation id="4989809363548539747">ಈ ಪ್ಲಗಿನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ</translation>
+<translation id="4995216769782533993">ಈ ಸೈಟ್‌ನೊಂದಿಗೆ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ವಿವರಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸುರಕ್ಷತಾ ಕೋಡ್ ಅನ್ನು ಖಚಿತಪಡಿಸಿ</translation>
<translation id="5002932099480077015">ಸಕ್ರಿಯವಾಗಿದ್ದರೆ, ವೇಗವಾಗಿ ಫಾರ್ಮ್ ಭರ್ತಿ ಮಾಡಲು Chrome ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ಪ್ರತಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.</translation>
<translation id="5015510746216210676">ಯಂತ್ರದ ಹೆಸರು:</translation>
<translation id="5017554619425969104">ನೀವು ನಕಲಿಸಿದ ಪಠ್ಯ</translation>
@@ -772,6 +783,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-ಬಿಟ್)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ</translation>
<translation id="5135404736266831032">ವಿಳಾಸಗಳನ್ನು ನಿರ್ವಹಿಸಿ...</translation>
<translation id="5138227688689900538">ಕಡಿಮೆ ತೋರಿಸಿ</translation>
<translation id="5141240743006678641">ನಿಮ್ಮ Google ರುಜುವಾತುಗಳ ಜೊತೆಗೆ ಸಿಂಕ್ ಮಾಡಿದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್‌ ಮಾಡಿ</translation>
@@ -798,6 +810,7 @@
<translation id="5251803541071282808">ಕ್ಲೌಡ್</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">ಸಿಸ್ಟಮ್‌ನಾದ್ಯಂತ ಅನ್ವಯವಾಗುವ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಮಾಲೀಕರಿಂದ ಮಾತ್ರ ಹೊಂದಿಸಬಹುದು: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">ಎಚ್ಚರಿಕೆ: ಈ ಕಾರ್ಯನೀತಿಯನ್ನು PolicyDictionaryMultipleSourceMergeList ಕಾರ್ಯನೀತಿಯಲ್ಲಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಿರುವಂತೆ ವಿಲೀನಗೊಳಿಸಲಾಗಿಲ್ಲ ಏಕೆಂದರೆ ಅದು ವಿಲೀನಗೊಳಿಸಬಹುದಾದ ನಿಘಂಟಿನ ಕಾರ್ಯನೀತಿಗಳ ಭಾಗವಾಗಿಲ್ಲ.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">ಅಂತ್ಯ</translation>
@@ -821,7 +834,6 @@
<translation id="536296301121032821">ನೀತಿಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಸಂಗ್ರಹಿಸುವಲ್ಲಿ ವಿಫಲವಾಗಿದೆ</translation>
<translation id="5371425731340848620">ಕಾರ್ಡ್ ಅಪ್‌ಡೇಟ್ ಮಾಡಿ</translation>
<translation id="5377026284221673050">"ನಿಮ್ಮ ಗಡಿಯಾರ ಹಿಂದಿದೆ" ಅಥವಾ "ನಿಮ್ಮ ಗಡಿಯಾರ ಮುಂದಿದೆ" ಅಥವಾ "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">ಈ ಪುಟವು ನಿಮಗೆ ಮೋಸಮಾಡಲು, ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಕದಿಯಲು ಅಥವಾ ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಲು ಪ್ರಯತ್ನಿಸಬಹುದು. ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ನಮೂದಿಸುವಾಗ ಅಥವಾ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿದ ಫೈಲ್‌ಗಳನ್ನು ತೆರೆಯುವಾಗ ಎಚ್ಚರಿಕೆ ವಹಿಸಿ.</translation>
<translation id="5384855140246857529">ನಿಮ್ಮ ಕಾರ್ಡ್‌ಗಳನ್ನು ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿ ಬಳಸಲು, ಸೈನ್ ಇನ್ ಮಾಡಿ ಮತ್ತು ಸಿಂಕ್ ಆನ್ ಮಾಡಿ.</translation>
<translation id="5386426401304769735">ಈ ಸೈಟ್‌ಗೆ ಪ್ರಮಾಣಪತ್ರ ಸರಣಿಯು SHA-1 ಬಳಸಿಕೊಂಡು ಸಹಿ ಮಾಡಲಾದ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -835,6 +847,8 @@
<translation id="5457113250005438886">ಅಮಾನ್ಯ</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ಇನ್ನಷ್ಟು}one{<ph name="CONTACT_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ಇನ್ನಷ್ಟು}other{<ph name="CONTACT_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ಇನ್ನಷ್ಟು}}</translation>
<translation id="5470861586879999274">&amp;ಎಡಿಟ್ ಮಾಡುವುದನ್ನು ಪುನಃ ಮಾಡು</translation>
+<translation id="5473728911100096288">ಈ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದರಿಂದ ನೀವು ಅಸಮ್ಮತಿಗೊಂಡ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ ಎಂದರ್ಥ
+ ಈ ವೈಶಿಷ್ಟ್ಯಗಳು ಇನ್ನು ಮುಂದೆ ಬರುವ ಆವೃತ್ತಿಗಳಲ್ಲಿ ಕಾಣಿಸುವುದಿಲ್ಲ.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">ಈ ಕಂಟೆಂಟ್‌ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿರುವ ಮಾಹಿತಿಯನ್ನು ಕದಿಯುವ ಅಥವಾ ಅಳಿಸುವ ಅಪಾಯಕಾರಿ ಸಾಫ್ಟ್‌ವೇರ್ ಅನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರಬಹುದು. <ph name="BEGIN_LINK" />ಹೇಗಿದ್ದರೂ ತೋರಿಸಿ<ph name="END_LINK" />.</translation>
<translation id="54817484435770891">ಮಾನ್ಯವಾದ ವಿಳಾಸ ಸೇರಿಸಿ</translation>
@@ -858,7 +872,6 @@
<translation id="5570825185877910964">ಖಾತೆಯನ್ನು ಸಂರಕ್ಷಿಸಿ</translation>
<translation id="5571083550517324815">ಈ ವಿಳಾಸದಿಂದ ಪಿಕಪ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಬೇರೊಂದು ವಿಳಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 ಬಳಕೆಯಲ್ಲಿದೆ}one{# ಬಳಕೆಯಲ್ಲಿದೆ}other{# ಬಳಕೆಯಲ್ಲಿದೆ}})</translation>
-<translation id="5572851009514199876">ದಯವಿಟ್ಟು Chrome ಪ್ರಾರಂಭಿಸಿ ಮತ್ತು ಸೈನ್ ಇನ್ ಮಾಡಿ ಈ ಮೂಲಕ ಈ ಸೈಟ್‌ಗೆ ಪ್ರವೇಶಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು Chrome ಪರಿಶೀಲಿಸಬಹುದು.</translation>
<translation id="5580958916614886209">ನಿಮ್ಮ ಮುಕ್ತಾಯ ತಿಂಗಳನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ</translation>
<translation id="5586446728396275693">ಯಾವುದೇ ಉಳಿಸಲಾದ ವಿಳಾಸಗಳಿಲ್ಲ</translation>
<translation id="5595485650161345191">ವಿಳಾಸ ಎಡಿಟ್ ಮಾಡಿ</translation>
@@ -866,6 +879,7 @@
<translation id="560412284261940334">ನಿರ್ವಾಹಕ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">ಇದು ನಕಲಿ ಅಥವಾ ವಂಚನೆಯ ಸೈಟ್ ಆಗಿರಬಹುದು. ಇದೀಗ ಈ ಸೈಟ್‌ನಿಂದ ಹೊರಹೋಗಲು Chrome ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ.</translation>
<translation id="5610142619324316209">ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="5610807607761827392">ನೀವು ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ವಿಳಾಸಗಳನ್ನು <ph name="BEGIN_LINK" />ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ<ph name="END_LINK" /> ನಿರ್ವಹಿಸಬಹುದು.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> ನಿಮ್ಮನ್ನು ತೀರಾ ಹೆಚ್ಚು ಬಾರಿ ಮರುನಿರ್ದೇಶಿಸಿದೆ.</translation>
@@ -889,11 +903,11 @@
<translation id="5720705177508910913">ಪ್ರಸ್ತುತ ಬಳಕೆದಾರ</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">ನೀವು ಇತರ ಸೈಟ್‌ಗಳಲ್ಲಿ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡಿದ್ದಲ್ಲಿ Chrome ನಿಮ್ಮ ಪಾಸವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲು ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ.</translation>
-<translation id="5732392974455271431">ನಿಮ್ಮ ಪೋಷಕರು ನಿಮಗಾಗಿ ಅದನ್ನು ಅನಿರ್ಬಂಧಿಸಬಹುದಾಗಿದೆ</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಕಾರ್ಡ್‌ ಉಳಿಸಿ}one{ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಕಾರ್ಡ್‌ಗಳನ್ನು ಉಳಿಸಿ}other{ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಕಾರ್ಡ್‌ಗಳನ್ನು ಉಳಿಸಿ}}</translation>
<translation id="5763042198335101085">ಮಾನ್ಯವಾದ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ</translation>
<translation id="5765072501007116331">ವಿತರಣೆಯ ವಿಧಾನಗಳು ಹಾಗೂ ಆವಶ್ಯಕತೆಗಳನ್ನು ನೋಡಲು, ಒಂದು ವಿಳಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</translation>
<translation id="5778550464785688721">MIDI ಸಾಧನಗಳು ಸಂಪೂರ್ಣ ನಿಯಂತ್ರಣ</translation>
+<translation id="5781136890105823427">ಪ್ರಾಯೋಗಿಕವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="578305955206182703">ಕಿತ್ತಳೆ ಹಳದಿ</translation>
<translation id="57838592816432529">ಮ್ಯೂಟ್</translation>
<translation id="5784606427469807560">ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ದೃಢೀಕರಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಇದೆ. ನಿಮ್ಮ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
@@ -910,13 +924,16 @@
<translation id="5860033963881614850">ಆಫ್</translation>
<translation id="5863847714970149516">ಮುಂದಿನ ಪುಟವು ನಿಮಗೆ ಶುಲ್ಕ ವಿಧಿಸಲು ಪ್ರಯತ್ನಿಸಬಹುದು</translation>
<translation id="5866257070973731571">ಫೋನ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ</translation>
+<translation id="5866898949289125849">ನೀವು, ಡೆವಲಪರ್ ಪರಿಕರಗಳ ಪುಟವನ್ನು ವೀಕ್ಷಿಸುತ್ತಿದ್ದೀರಿ</translation>
<translation id="5869405914158311789">ಈ ಸೈಟ್ ತಲುಪಲಾಗುವುದಿಲ್ಲ</translation>
<translation id="5869522115854928033">ಉಳಿಸಲಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು</translation>
<translation id="5887400589839399685">ಕಾರ್ಡ್ ಉಳಿಸಲಾಗಿದೆ</translation>
<translation id="5893752035575986141">ಕ್ರೆಡಿಟ್‌ ಕಾರ್ಡ್‌ಗಳನ್ನು ಸಮ್ಮತಿಸಲಾಗಿದೆ.</translation>
+<translation id="5895138241574237353">ಮರುಪ್ರಾರಂಭಿಸಿ</translation>
<translation id="5901630391730855834">ಹಳದಿ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ಸಿಂಕ್‌ ಮಾಡಲಾಗಿದೆ)</translation>
<translation id="5916664084637901428">ಆನ್‌</translation>
+<translation id="59174027418879706">ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google ಖಾತೆಯಲ್ಲಿ ಕಾರ್ಡ್ ಅನ್ನು ಉಳಿಸಬೇಕೇ?</translation>
<translation id="5922853866070715753">ಬಹುತೇಕ ಮುಗಿದಿದೆ</translation>
@@ -950,6 +967,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿಯೂ ನಿಮ್ಮ ಕಾರ್ಡ್‌ಗಳನ್ನು ಬಳಸಬೇಕೇ?</translation>
<translation id="6059925163896151826">USB ಸಾಧನಗಳು</translation>
+<translation id="6060009363608157444">ಅಮಾನ್ಯ DnsOverHttps ಮೋಡ್.</translation>
<translation id="6080696365213338172">ನಿರ್ವಾಹಕರು-ಒದಗಿಸಿದ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಬಳಸಿಕೊಂಡು ನೀವು ವಿಷಯವನ್ನು ಪ್ರವೇಶಿಸಿರುವಿರಿ. <ph name="DOMAIN" /> ಗೆ ನೀವು ಒದಗಿಸುವ ಡೇಟಾವನ್ನು ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ತಡೆಹಿಡಿಯಬಹುದಾಗಿದೆ.</translation>
<translation id="6094273045989040137">ಟಿಪ್ಪಣಿ</translation>
<translation id="610911394827799129">ನಿಮ್ಮ Google ಖಾತೆಯು <ph name="BEGIN_LINK" />history.google.com<ph name="END_LINK" /> ನಲ್ಲಿ ಇತರ ವಿಧಗಳ ಬ್ರೌಸಿಂಗ್ ಇತಿಹಾಸವನ್ನು ಹೊಂದಿರಬಹುದು</translation>
@@ -997,13 +1015,12 @@
<translation id="6404511346730675251">ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> ಗೆ ಮುಕ್ತಾಯ ದಿನಾಂಕ ಮತ್ತು ಸಿವಿಸಿ ಅನ್ನು ನಮೂದಿಸಿ</translation>
-<translation id="6414888972213066896">ಈ ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡುವುದು ಸರಿಯೇ ಎಂದು ನೀವು ನಿಮ್ಮ ಪೋಷಕರನ್ನು ಕೇಳಿರುವಿರಿ</translation>
<translation id="6415778972515849510">ನಿಮ್ಮ Google ಖಾತೆಯನ್ನು ಸಂರಕ್ಷಿಸಲು ಹಾಗೂ ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಬದಲಾಯಿಸಲು, Chromium ನಿಮಗೆ ಸಹಾಯ ಮಾಡಬಲ್ಲದು.</translation>
-<translation id="6417515091412812850">ಪ್ರಮಾಣಪತ್ರವನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆಯೆ ಎಂಬುದನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ.</translation>
<translation id="6431585503458005759">ಸಂಗ್ರಹಿಸಬೇಡಿ</translation>
<translation id="6433490469411711332">ಸಂಪರ್ಕ ಮಾಹಿತಿ ಎಡಿಟ್ ಮಾಡಿ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ಸಂಪರ್ಕಗೊಳ್ಳಲು ನಿರಾಕರಿಸಿದೆ.</translation>
<translation id="6434309073475700221">ತಿರಸ್ಕರಿಸಿ</translation>
+<translation id="6435221585574090192">ನಿಮ್ಮ ನಿರ್ವಾಹಕರೊಂದಿಗೆ Chrome ಎಂಟರ್‌ಪ್ರೈಸ್ ಬೆದರಿಕೆ ರಕ್ಷಣೆಯಿಂದ ಫ್ಲ್ಯಾಗ್ ಮಾಡಲಾದ ಭದ್ರತಾ ಈವೆಂಟ್‌ಗಳ ಕುರಿತು ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಿ. ಪುಟ URL ಗಳು, ಫೈಲ್ ಹೆಸರು ಮತ್ತು ಫೈಲ್ ಮೆಟಾಡೇಟಾ, ನಿಮ್ಮ ಸಾಧನದ ಬಳಕೆದಾರರ ಹೆಸರು ಮತ್ತು Chrome ಬಳಕೆದಾರರ ಹೆಸರುಗಳನ್ನು ಇವು ಒಳಗೊಂಡಿರಬಹುದು.</translation>
<translation id="6440503408713884761">ನಿರ್ಲಕ್ಷಿಸಲಾಗಿದೆ</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">ಇನ್ನಷ್ಟು ಮಾಹಿತಿಯನ್ನು ಸೇರಿಸಿ</translation>
@@ -1012,20 +1029,19 @@
<translation id="6465306955648956876">ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ...</translation>
<translation id="647261751007945333">ಸಾಧನ ನೀತಿಗಳು</translation>
<translation id="6476284679642588870">ಪಾವತಿ ವಿಧಾನಗಳನ್ನು ನಿರ್ವಹಿಸಿ</translation>
-<translation id="6477321094435799029">ಈ ಪುಟದಲ್ಲಿ ಅಸಹಜ ಕೋಡ್ ಅನ್ನು Chrome ಪತ್ತೆಹಚ್ಚಿದೆ ಮತ್ತು ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಫೋನ್‌ ಸಂಖ್ಯೆಗಳು ಮತ್ತು ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು) ರಕ್ಷಿಸಲು ಅದನ್ನು ನಿರ್ಬಂಧಿಸಿದೆ.</translation>
<translation id="6489534406876378309">ವಿಫಲತೆಗಳನ್ನು ಅಪ್‌ಲೋಡ್‌ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸು</translation>
<translation id="6499038740797743453">ಪಾಸ್‌ವರ್ಡ್ ಮರುಹೊಂದಿಸಬೇಕೆ?</translation>
<translation id="6507833130742554667">ಕ್ರೆಡಿಟ್‌ ಮತ್ತು ಡೆಬಿಟ್ ಕಾರ್ಡ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲಾಗುತ್ತದೆ.</translation>
<translation id="650855688985305916">ಹೌದು, ಸಂಗ್ರಹಿಸಿ</translation>
<translation id="6508722015517270189">Chrome ಮರುಪ್ರಾರಂಭಿಸಿ</translation>
<translation id="6517596291481585650">ಎಚ್ಚರಿಕೆ: ಈ ಕಾರ್ಯನೀತಿಯು ಪಟ್ಟಿಯಾಗಿಲ್ಲದ ಕಾರಣ, ಅದನ್ನು ಕಾರ್ಯನೀತಿ ಮೂಲಕ ನಿರ್ದಿಷ್ಟಪಡಿಸಿರುವಂತೆ ವಿಲೀನಗೊಳಿಸಲಾಗಿಲ್ಲ.</translation>
+<translation id="6518133107902771759">ಪರಿಶೀಲಿಸಿ</translation>
<translation id="6521745193039995384">ಸಕ್ರಿಯವಾಗಿಲ್ಲ</translation>
<translation id="6529602333819889595">&amp;ಅಳಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
<translation id="6534179046333460208">ಭೌತಿಕ ವೆಬ್ ಸಲಹೆಗಳು</translation>
<translation id="6545864417968258051">ಬ್ಲೂಟೂತ್ ಸ್ಕ್ಯಾನಿಂಗ್</translation>
<translation id="6554795675067793129">ನಿಮ್ಮ ಖಾತೆಯನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ನಿರ್ವಹಿಸುತ್ತಿದೆ.</translation>
<translation id="6556866813142980365">ಪುನಃ ಮಾಡು</translation>
-<translation id="6563469144985748109">ನಿಮ್ಮ ಮ್ಯಾನೇಜರ್ ಇನ್ನೂ ಇದನ್ನು ಅಂಗೀಕರಿಸಿಲ್ಲ</translation>
<translation id="6569060085658103619">ನೀವು ವಿಸ್ತರಣೆ ಪುಟವನ್ನು ವೀಕ್ಷಿಸುತ್ತಿರುವಿರಿ</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">ತಿಳಿ ಗುಲಾಬಿ</translation>
@@ -1043,11 +1059,13 @@
<translation id="6643016212128521049">ತೆರವುಗೊಳಿಸಿ</translation>
<translation id="6644283850729428850">ಈ ನೀತಿಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{ಯಾವುದೂ ಇಲ್ಲ}=1{1 ಸೈಟ್‌‍ನಿಂದ (ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ ನಿಮ್ಮನ್ನು ಸೈನ್ ಔಟ್ ಮಾಡುವುದಿಲ್ಲ)}one{# ಸೈಟ್‌ಗಳಿಂದ (ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ ನಿಮ್ಮನ್ನು ಸೈನ್ ಔಟ್ ಮಾಡುವುದಿಲ್ಲ)}other{# ಸೈಟ್‌ಗಳಿಂದ (ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ ನಿಮ್ಮನ್ನು ಸೈನ್ ಔಟ್ ಮಾಡುವುದಿಲ್ಲ)}}</translation>
+<translation id="6652101503459149953">Windows Hello ಬಳಸಿ</translation>
<translation id="6657585470893396449">ಪಾಸ್‌ವರ್ಡ್</translation>
<translation id="6670613747977017428">ಸುರಕ್ಷತೆಗೆ ಹಿಂತಿರುಗಿ.</translation>
<translation id="6671697161687535275">Chromium ನಿಂದ ಫಾರ್ಮ್ ಸಲಹೆಯನ್ನು ತೆಗೆದುಹಾಕುವುದೇ?</translation>
<translation id="6685834062052613830">ಸೈನ್‌ ಔಟ್‌ ಮಾಡಿ ಹಾಗೂ ಸೆಟಪ್ ಪೂರ್ಣಗೊಳಿಸಿ</translation>
<translation id="6689271823431384964">ನೀವು ಸೈನ್ ಇನ್ ಮಾಡಿರುವ ಕಾರಣದಿಂದಾಗಿ, ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ಗಳನ್ನು ಉಳಿಸಲು Chrome ಅವಕಾಶ ನೀಡುತ್ತಿದೆ. ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ನೀವು ಈ ವರ್ತನೆಯನ್ನು ಬದಲಿಸಬಹುದು. ಕಾರ್ಡ್ ಹೋಲ್ಡರ್ ಹೆಸರು ನಿಮ್ಮ ಖಾತೆಯಿಂದ ಬರುತ್ತದೆ.</translation>
+<translation id="6707256370811247129">ನೀವು Chrome ನಲ್ಲಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡುವ ಅಥವಾ ಅಪ್‌ಲೋಡ್ ಮಾಡುವ ಫೈಲ್‌ಗಳು ಮತ್ತು ಕ್ಯಾಷ್‌ನ ವಿಷಯಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ.</translation>
<translation id="6710213216561001401">ಹಿಂದೆ</translation>
<translation id="6710594484020273272">&lt;ಹುಡುಕಾಟದ ಪದ ಟೈಪ್ ಮಾಡಿ&gt;</translation>
<translation id="671076103358959139">ನೋಂದಣಿಯ ಟೋಕನ್:</translation>
@@ -1055,10 +1073,10 @@
<translation id="6738516213925468394">ನಿಮ್ಮ ಡೇಟಾವನ್ನು <ph name="TIME" /> ಸಮಯಕ್ಕೆ ನಿಮ್ಮ <ph name="BEGIN_LINK" />ಸಿಂಕ್ ಪಾಸ್‌ಫ್ರೇಸ್<ph name="END_LINK" /> ನೊಂದಿಗೆ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ. ಸಿಂಕ್ ಪ್ರಾರಂಭಿಸಲು ಅದನ್ನು ನಮೂದಿಸಿ.</translation>
<translation id="674375294223700098">ಅಪರಿಚಿತ ಸರ್ವರ್ ಪ್ರಮಾಣಪತ್ರ ದೋಷ.</translation>
<translation id="6744009308914054259">ಸಂಪರ್ಕಕ್ಕಾಗಿ ನಿರೀಕ್ಷಿಸುತ್ತಿರುವಾಗ, ಆಫ್‌ಲೈನ್ ​​ಲೇಖನಗಳನ್ನು ಓದಲು ನೀವು ಡೌನ್‌ಲೋಡ್‌ಗಳಿಗೆ ಭೇಟಿ ನೀಡಬಹುದು.</translation>
+<translation id="6747611005629681221">ಎಚ್ಚರಿಕೆ: ಪುಟದ ವೈಶಿಷ್ಟ್ಯಗಳು ಪ್ರಾಯೋಗಿಕವಾಗಿವೆ!</translation>
<translation id="6753269504797312559">ನೀತಿ ಮೌಲ್ಯ</translation>
<translation id="6757797048963528358">ನಿಮ್ಮ ಸಾಧನವು ನಿದ್ರಾವಸ್ಥೆಗೆ ಹೋಗಿದೆ.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">ನಿಮ್ಮ ಪೋಷಕರು ಇನ್ನೂ ಇದನ್ನು ಅಂಗೀಕರಿಸಿಲ್ಲ</translation>
<translation id="67862343314499040">ನೇರಳೆ</translation>
<translation id="6786747875388722282">ವಿಸ್ತರಣೆಗಳು</translation>
<translation id="6790428901817661496">ಪ್ಲೇ ಮಾಡು</translation>
@@ -1066,6 +1084,7 @@
<translation id="681021252041861472">ಅಗತ್ಯವಿರುವ ಕ್ಷೇತ್ರ</translation>
<translation id="6810899417690483278">ಕಸ್ಟಮೈಸೇಶನ್ ಐಡಿ</translation>
<translation id="6825578344716086703">ನೀವು <ph name="DOMAIN" /> ಅನ್ನು ತಲುಪಲು ಪ್ರಯತ್ನಿಸಿದಿರಿ, ಆದರೆ ದುರ್ಬಲ ಸಹಿ ಅಲ್ಗಾರಿದಮ್ (SHA-1 ಅದರಂತೆ) ಬಳಸಿಕೊಂಡು ಸಹಿ ಮಾಡಿದ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಸರ್ವರ್ ಒದಗಿಸಿದೆ. ಇದರರ್ಥ ಸರ್ವರ್ ಒದಗಿಸಿದ ಸುರಕ್ಷತೆ ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಖೋಟಾ ತಯಾರಿಸಿರಬಹುದು, ಮತ್ತು ನೀವು ನಿರೀಕ್ಷಿಸಿದ ಸರ್ವರ್ ಅದಾಗಿರದೇ ಇರಬಹುದು (ನೀವು ದಾಳಿಕೋರರೊಂದಿಗೆ ಸಂವಹನ ಮಾಡುತ್ತಿರಬಹುದು).</translation>
+<translation id="6826370046007623921">ಡೇಟಾ ನಷ್ಟದ ತಡೆ</translation>
<translation id="6831043979455480757">ಅನುವಾದಿಸು</translation>
<translation id="6839929833149231406">ಪ್ರದೇಶ</translation>
<translation id="6852204201400771460">ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಪುನಃ ಆರಂಭಿಸಬೇಕೆ?</translation>
@@ -1078,7 +1097,6 @@
<translation id="6891596781022320156">ನೀತಿಯ ಮಟ್ಟವು ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.</translation>
<translation id="6895330447102777224">ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ</translation>
<translation id="6897140037006041989">ಬಳಕೆದಾರರ ಏಜೆಂಟ್</translation>
-<translation id="6903319715792422884"><ph name="BEGIN_WHITEPAPER_LINK" />ಸಿಸ್ಟಂ ಕುರಿತು ಕೆಲವೊಂದು ಮಾಹಿತಿಯನ್ನು ಮತ್ತು ಪುಟದ ವಿಷಯವನ್ನು<ph name="END_WHITEPAPER_LINK" /> Google ಗೆ ಕಳುಹಿಸುವ ಮೂಲಕ, ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್ ಅನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಿ. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ಬಳಕೆದಾರ:</translation>
<translation id="6934672428414710184">ಈ ಹೆಸರು ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ ಬಂದಿದೆ</translation>
<translation id="6944692733090228304">ನೀವು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ನಿರ್ವಹಣೆ ಮಾಡದ ಸೈಟ್‌ನಲ್ಲಿ ನಮೂದಿಸಿದ್ದೀರಿ. ನಿಮ್ಮ ಖಾತೆಯನ್ನು ರಕ್ಷಿಸಲು, ಇತರ ಆ್ಯಪ್‌ಗಳಲ್ಲಿ ಮತ್ತು ಸೈಟ್‌ಗಳಲ್ಲಿ ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡಬೇಡಿ.</translation>
@@ -1123,6 +1141,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ಇನ್ನಷ್ಟು}one{<ph name="PAYMENT_METHOD_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ಇನ್ನಷ್ಟು}other{<ph name="PAYMENT_METHOD_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ಇನ್ನಷ್ಟು}}</translation>
<translation id="7153618581592392745">ನಸು ಕೆನ್ನೀಲಿ</translation>
<translation id="717330890047184534">Gaia ಐಡಿ:</translation>
+<translation id="7174545416324379297">ವಿಲೀನಗೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ಇನ್ನಷ್ಟು}one{<ph name="SHIPPING_OPTION_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ಇನ್ನಷ್ಟು}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ಇನ್ನಷ್ಟು}}</translation>
<translation id="7177397715882417099">ನೀವು ಪ್ರವೇಶಿಸುತ್ತಿರುವ ಸರ್ವರ್, <ph name="ORIGIN" />, ತನ್ನ ಎಲ್ಲಾ ವಿನಂತಿಗಳಿಗೆ
ಅನ್ವಯವಾಗುವ ಸುರಕ್ಷತೆ ನೀತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಂಡಿದೆ. ಆದರೆ ಕಾರ್ಯನೀತಿಯನ್ನು
@@ -1160,6 +1179,7 @@
<translation id="7320336641823683070">ಸಂಪರ್ಕ ಸಹಾಯ</translation>
<translation id="733354035281974745">ಸಾಧನದ ಸ್ಥಳೀಯ ಖಾತೆಯು ಅತಿಕ್ರಮಿಸಿದೆ</translation>
<translation id="7334320624316649418">&amp;ಮರುಕ್ರಮಗೊಳಿಸುವುದನ್ನು ಮತ್ತೆಮಾಡು</translation>
+<translation id="7337706099755338005">ನಿಮ್ಮ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ನಲ್ಲಿ ಲಭ್ಯವಿಲ್ಲ.</translation>
<translation id="733923710415886693">ಪ್ರಮಾಣಪತ್ರ ಪಾರದರ್ಶಕತೆಯ ಮೂಲಕ ಸರ್ವರ್ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಬಹಿರಂಗಪಡಿಸಲಾಗಿಲ್ಲ.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">ಸಂಯೋಜಿತವಾಗಿದ್ದಾರೆ:</translation>
@@ -1190,7 +1210,6 @@
<translation id="7440140511386898319">ಆಫ್‌ಲೈನ್‌ನಲ್ಲಿರುವಾಗ ಎಕ್ಸ್‌ಪ್ಲೋರ್‌ ಮಾಡಿ</translation>
<translation id="7441627299479586546">ತಪ್ಪಾದ ನೀತಿಯ ವಿಷಯ</translation>
<translation id="7442725080345379071">ತಿಳಿ ಕಿತ್ತಳೆ</translation>
-<translation id="7444046173054089907">ಈ ಸೈಟ್ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
<translation id="7445762425076701745">ನೀವು ಸಂಪರ್ಕ ಮಾಡಿರುವ ಸರ್ವರ್‌ನ ಗುರುತನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಮೌಲ್ಯೀಕರಿಸಲಾಗುವುದಿಲ್ಲ. ನೀವು ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿಯೇ ಮಾನ್ಯವಿರುವ ಹೆಸರನ್ನು ಮಾತ್ರ ಬಳಸಿಕೊಂಡು ಸಂಪರ್ಕ ಹೊಂದಿರುವಿರಿ, ಇದರ ಮಾಲಿಕತ್ವವನ್ನು ಮೌಲ್ಯೀಕರಿಸುವ ಯಾವ ಅವಕಾಶವನ್ನೂ ಬಾಹ್ಯ ಪ್ರಮಾಣಪತ್ರ ಪ್ರಾಧಿಕಾರವು ಹೊಂದಿಲ್ಲ. ಕೆಲವು ಪ್ರಮಾಣಪತ್ರ ಪ್ರಾಧಿಕಾರಗಳು, ಯಾವುದೇ ಹೆಸರನ್ನು ಪರಿಗಣಿಸದೇ, ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಬಿಡುಗಡೆ ಮಾಡುವ ಕಾರಣದಿಂದಾಗಿ, ನೀವು ಉದ್ದೇಶಿತ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಸಂಪರ್ಕಿಸಿರುವಿರೇ ಹೊರತು ದಾಳಿ ಮಾಡಲು ಅಲ್ಲ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳುವ ಯಾವ ಅವಕಾಶವೂ ಇಲ್ಲ.</translation>
<translation id="7451311239929941790">ಈ ಸಮಸ್ಯೆಯ ಕುರಿತು <ph name="BEGIN_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯುವಿಕೆ<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">ಜಾಗತಿಕ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ (ನಿರ್ಬಂಧಿಸಿ)</translation>
@@ -1212,9 +1231,9 @@
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">ನೀವು ಒಮ್ಮೆ ಖಚಿತಪಡಿಸಿದರೆ, ನಿಮ್ಮ ಕಾರ್ಡ್ ವಿವರಗಳನ್ನು ಈ ಸೈಟ್ ಜೊತೆಗೆ ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.</translation>
<translation id="7542995811387359312">ಈ ಫಾರ್ಮ್ ಸುರಕ್ಷಿತವಾದ ಸಂಪರ್ಕವನ್ನು ಬಳಸುತ್ತಿಲ್ಲವಾದ ಕಾರಣ ಸ್ವಯಂಚಾಲಿತ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಭರ್ತಿ ಮಾಡುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ.</translation>
-<translation id="7543525346216957623">ನಿಮ್ಮ ಪೋಷಕರಿಗೆ ಕೇಳಿ</translation>
<translation id="7548892272833184391">ಸಂಪರ್ಕ ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸಿ</translation>
<translation id="7549584377607005141">ಈ ವೆಬ್‌ಪುಟವು ಸರಿಯಾಗಿ ಪ್ರದರ್ಶನಗೊಳ್ಳಲು ಈ ಮೊದಲು ನೀವು ನಮೂದಿಸಿದ ಡೇಟಾದ ಅಗತ್ಯವಿದೆ. ನೀವು ಈ ಡೇಟಾವನ್ನು ಮತ್ತೆ ಕಳುಹಿಸಬಹುದು, ಆದರೆ ಹಾಗೆ ಮಾಡುವುದರಿಂದ ಈ ಪುಟವು ಈ ಮೊದಲು ಪೂರೈಸಿದ ಯಾವುದೇ ಕ್ರಿಯೆಯನ್ನು ನೀವು ಪುನರಾವರ್ತಿಸುತ್ತೀರಿ.</translation>
+<translation id="7550637293666041147">ನಿಮ್ಮ ಸಾಧನದ ಬಳಕೆದಾರರ ಹೆಸರು ಮತ್ತು Chrome ಬಳಕೆದಾರರ ಹೆಸರು</translation>
<translation id="7552846755917812628">ಕೆಳಗಿನ ಸಲಹೆಗಳನ್ನು ಪ್ರಯತ್ನಿಸಿ:</translation>
<translation id="7554791636758816595">ಹೊಸ ಟ್ಯಾಬ್</translation>
<translation id="7564049878696755256">ನಿಮ್ಮ <ph name="ORG_NAME" /> ಖಾತೆಗೆ ನೀವು ಪ್ರವೇಶವನ್ನು ಕಳೆದುಕೊಳ್ಳಬಹುದು ಅಥವಾ ಗುರುತು ಕಳ್ಳತನಕ್ಕೆ ಒಳಗಾಗಬಹುದು. ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಇದೀಗ ಬದಲಾಯಿಸುವಂತೆ Chrome ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ.</translation>
@@ -1229,6 +1248,7 @@
<translation id="7610193165460212391">ಮೌಲ್ಯವು ವ್ಯಾಪ್ತಿಯಿಂದ <ph name="VALUE" /> ಹೊರಗಿದೆ.</translation>
<translation id="7613889955535752492">ಅವಧಿ ಮೀರುವ ಸಮಯ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">ನಿಮ್ಮ Google ಖಾತೆಯ ಪಾಸ್‌ವರ್ಡ್‌ನ ಬೇರೆ ಆವೃತ್ತಿಯನ್ನು ಬಳಸಿಕೊಂಡು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾದ ಡೇಟಾವನ್ನು ನೀವು ಈಗಾಗಲೇ ಹೊಂದಿರುವಿರಿ. ದಯವಿಟ್ಟು ಕೆಳಗೆ ಇದನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="7625784245512586808">Chrome ಎಂಟರ್‌ಪ್ರೈಸ್ ಬೆದರಿಕೆ ರಕ್ಷಣೆ</translation>
<translation id="7633909222644580952">ಕಾರ್ಯಕ್ಷಮತೆಯ ಡೇಟಾ ಮತ್ತು ಕ್ರ್ಯಾಶ್ ವರದಿಗಳು</translation>
<translation id="7637571805876720304">Chromium ನಿಂದ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ತೆಗೆದುಹಾಕುವುದೇ?</translation>
<translation id="7638605456503525968">ಸೀರಿಯಲ್ ಪೋರ್ಟ್‌ಗಳು</translation>
@@ -1241,7 +1261,6 @@
<translation id="7668654391829183341">ಅಪರಿಚಿತ ಸಾಧನ</translation>
<translation id="7669271284792375604">ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್‌ ಅನುಭವವನ್ನು ಹಾನಿಮಾಡಲು ಸ್ಥಾಪಿಸಲಾಗುವ ಪ್ರೋಗ್ರಾಂಗಳಲ್ಲಿ ನಿಮ್ಮನ್ನು ವಂಚಿಸಲು ಆಕ್ರಮಣಕಾರರು ಈ ಸೈಟ್‌ ಮೇಲೆ ದಾಳಿ ಮಾಡಬಹುದು (ಉದಾಹರಣೆಗೆ, ನಿಮ್ಮ ಮುಖಪುಟವನ್ನು ಬದಲಾಯಿಸಲಾಗುತ್ತದೆ ಅಥವಾ ನೀವು ಭೇಟಿ ನೀಡುವ ಸೈಟ್‌ಗಳಲ್ಲಿ ಹೆಚ್ಚಿನ ಜಾಹೀರಾತುಗಳನ್ನು ತೋರಿಸಲಾಗುತ್ತದೆ).</translation>
<translation id="7676643023259824263">ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಪಠ್ಯಕ್ಕಾಗಿ ಹುಡುಕಿ, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">ಪ್ಲಾಟ್‌ಫಾರ್ಮ್ ಮತ್ತು ಕ್ಲೌಡ್</translation>
<translation id="7681101578153515023">ಹುಡುಕಾಟ ಎಂಜಿನ್ ಅನ್ನು ಬದಲಿಸಿ</translation>
<translation id="7682287625158474539">ಶಿಪ್ಪಿಂಗ್</translation>
<translation id="7687186412095877299">ಉಳಿಸಲಾದ ನಿಮ್ಮ ಪಾವತಿ ವಿಧಾನಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಪಾವತಿ ಫಾರ್ಮ್‌ಗಳನ್ನು ಭರ್ತಿ ಮಾಡುತ್ತದೆ</translation>
@@ -1256,7 +1275,6 @@
<translation id="7723047071702270851">ಕಾರ್ಡ್ ಅನ್ನು ಎಡಿಟ್ ಮಾಡಿ</translation>
<translation id="774634243536837715">ಅಪಾಯಕಾರಿ ವಿಷಯವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ.</translation>
<translation id="7752995774971033316">ನಿರ್ವಹಣೆಯಲ್ಲಿಲ್ಲ</translation>
-<translation id="7755287808199759310">ನಿಮ್ಮ ಪೋಷಕರು ನಿಮಗಾಗಿ ಅದನ್ನು ಅನಿರ್ಬಂಧಿಸಬಹುದಾಗಿದೆ</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ಸಂಪರ್ಕವನ್ನು ಫೈರ್‌ವಾಲ್ ಅಥವಾ ಆಂಟಿವೈರಸ್ ಸಾಫ್ಟ್‌ವೇರ್ ನಿರ್ಬಂಧಿಸಿರಬಹುದು.</translation>
<translation id="7759163816903619567">ಡಿಸ್‌ಪ್ಲೇ ಡೊಮೇನ್:</translation>
@@ -1300,7 +1318,6 @@
<translation id="8004582292198964060">ಬ್ರೌಸರ್</translation>
<translation id="8009225694047762179">ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ಈ ಕಾರ್ಡ್ ಮತ್ತು ಅದರ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸವನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು <ph name="USER_EMAIL" /> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅದನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.}one{ಈ ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ಅವುಗಳ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸಗಳನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು <ph name="USER_EMAIL" /> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅವುಗಳನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.}other{ಈ ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ಅವುಗಳ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸಗಳನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು <ph name="USER_EMAIL" /> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅವುಗಳನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.}}</translation>
-<translation id="8012647001091218357">ಈ ಕ್ಷಣದಲ್ಲಿ ನಿಮ್ಮ ಪೋಷಕರನ್ನು ತಲುಪಲು ನಮಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="8025119109950072390">ಈ ಸೈಟ್‌ನಲ್ಲಿನ ಆಕ್ರಮಣಕಾರರು ಸಾಫ್ಟ್‌ವೇರ್ ಸ್ಥಾಪಿಸುವಿಕೆ ಅಥವಾ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಬಹಿರಂಗ ಪಡಿಸುವಂತಹ ಅಪಾಯಕಾರಿಯಾಗಿ ಏನಾದರೂ ಮಾಡುವಂತಹ ಮೋಸವನ್ನು ಮಾಡಬಹುದು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಫೋನ್‌ ಸಂಖ್ಯೆಗಳು ಅಥವಾ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು).</translation>
<translation id="8034522405403831421">ಈ ಪುಟವು <ph name="SOURCE_LANGUAGE" /> ನಲ್ಲಿ ಇದೆ. ಇದನ್ನು <ph name="TARGET_LANGUAGE" /> ಗೆ ಅನುವಾದಿಸುವುದೇ?</translation>
<translation id="8035152190676905274">ಪೆನ್</translation>
@@ -1311,6 +1328,7 @@
<translation id="8041940743680923270">ಜಾಗತಿಕ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ (ಕೇಳಿ)</translation>
<translation id="8042918947222776840">ಪಿಕಪ್ ವಿಧಾನವನ್ನು ಆರಿಸಿ</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ಅನ್ನು ಸರಿಯಾಗಿ ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿಲ್ಲ. ಸಾಮಾನ್ಯವಾಗಿ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು "<ph name="SOFTWARE_NAME" />" ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತಿದೆ. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">ನೀವು ಈಗಿನಿಂದ ಕಾರ್ಡ್ ಭದ್ರತೆ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಬೇಕಾದ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ</translation>
<translation id="8066955247577885446">ಕ್ಷಮಿಸಿ, ಏನೋ ತಪ್ಪಾಗಿದೆ.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">ಡಾಕ್ಯುಮೆಂಟ್‌ ಅನ್ನು ತಿರುಗಿಸಿದಾಗ ಟಿಪ್ಪಣಿ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ</translation>
@@ -1341,6 +1359,7 @@
<translation id="8211406090763984747">ಸಂಪರ್ಕ ಸುರಕ್ಷಿತವಾಗಿದೆ</translation>
<translation id="8218327578424803826">ನಿಯೋಜಿಸಲಾದ ಸ್ಥಳ:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">ಎಂಟರ್‌ಪ್ರೈಸ್ ವರದಿಮಾಡುವಿಕೆ</translation>
<translation id="8225771182978767009">ಈ ಕಂಪ್ಯೂಟರ್ ಹೊಂದಿಸಿರುವ ವ್ಯಕ್ತಿಯು ಈ ಸೈಟ್ ನಿರ್ಬಂಧಿಸಲು ಆಯ್ಕೆಮಾಡಿದ್ದಾರೆ.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">ಪುಟವನ್ನು ಹೊಸ ಅದೃಶ್ಯ ಟ್ಯಾಬ್‌ನಲ್ಲಿ ತೆರೆಯಿರಿ</translation>
@@ -1395,24 +1414,24 @@
<translation id="8508648098325802031">ಹುಡುಕಾಟದ ಐಕಾನ್</translation>
<translation id="8522552481199248698">ನಿಮ್ಮ Google ಖಾತೆಯನ್ನು ಸಂರಕ್ಷಿಸಲು ಮತ್ತು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಬದಲಾಯಿಸಲು Chrome ಸಹಾಯ ಮಾಡಬಲ್ಲದು.</translation>
<translation id="8543181531796978784">ನೀವು <ph name="BEGIN_ERROR_LINK" />ಪತ್ತೆ ಹಚ್ಚುವಿಕೆ ಸಮಸ್ಯೆಯನ್ನು ವರದಿ ಮಾಡಬಹುದು<ph name="END_ERROR_LINK" /> ಅಥವಾ ನಿಮ್ಮ ಭದ್ರತೆಯ ಅಪಾಯಗಳ ಕುರಿತು ನಿಮಗೆ ಅರ್ಥವಾಗಿದ್ದರೆ, <ph name="BEGIN_LINK" />ಈ ಅಸುರಕ್ಷಿತ ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಿ<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">ಪ್ರಶ್ನೆಗಳಿವೆಯೇ? ನಿಮ್ಮ ಪ್ರೊಫೈಲ್‌ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ವ್ಯಕ್ತಿಯನ್ನು ಸಂಪರ್ಕಸಿ.</translation>
<translation id="8553075262323480129">ಪುಟದ ಭಾಷೆಯನ್ನು ಗುರುತಿಸಲು ಅಸಾಧ್ಯವಾದ ಕಾರಣ ಭಾಷಾಂತರವು ವಿಫಲವಾಗಿದೆ.</translation>
<translation id="8557066899867184262">ನಿಮ್ಮ ಕಾರ್ಡ್ ಹಿಂಬದಿಯಲ್ಲಿ CVC ಇರುತ್ತದೆ.</translation>
<translation id="8559762987265718583"><ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> ಗೆ ಖಾಸಗಿ ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ ಏಕೆಂದರೆ ನಿಮ್ಮ ಸಾಧನದ ದಿನಾಂಕ ಮತ್ತು ಸಮಯ (<ph name="DATE_AND_TIME" />) ತಪ್ಪಾಗಿದೆ.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> ಅನುಮಾನಾಸ್ಪದ ಸೈಟ್</translation>
<translation id="8564985650692024650">ನೀವು ಇತರ ಸೈಟ್‌ಗಳಲ್ಲಿ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡಿದ್ದಲ್ಲಿ ನಿಮ್ಮ <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ಪಾಸವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲು Chromium ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ.</translation>
<translation id="8571890674111243710"><ph name="LANGUAGE" /> ಗೆ ಪುಟವನ್ನು ಭಾಷಾಂತರಿಸಲಾಗುತ್ತಿದೆ...</translation>
<translation id="858637041960032120">ಫೋನ್ ಸಂ. ಸೇರಿಸಿ
</translation>
-<translation id="859285277496340001">ಇದನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಲು ಪ್ರಮಾಣಪತ್ರವು ಯಾಂತ್ರೀಕರಣವನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿಲ್ಲ.</translation>
<translation id="860043288473659153">ಕಾರ್ಡ್‌ಹೋಲ್ಡರ್ ಹೆಸರು</translation>
<translation id="861775596732816396">ಗಾತ್ರ 4</translation>
-<translation id="8620436878122366504">ನಿಮ್ಮ ಪೋಷಕರು ಇನ್ನೂ ಇದನ್ನು ಅಂಗೀಕರಿಸಿಲ್ಲ</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">ಈ ಕಾರ್ಡ್ ಅನ್ನು ಈ ಸಾಧನದಲ್ಲಿ ಉಳಿಸಿ</translation>
<translation id="8626112503828625890">Google ಖಾತೆಯಲ್ಲಿ ಬಿಲ್ಲಿಂಗ್ ವಿವರಗಳನ್ನು ಸಂಗ್ರಹಿಸಬೇಕೇ?</translation>
+<translation id="8647750283161643317">ಎಲ್ಲವನ್ನೂ ಡೀಫಾಲ್ಟ್‌ಗೆ ಮರುಹೊಂದಿಸಿ</translation>
<translation id="8663226718884576429">ಆರ್ಡರ್ ಸಾರಾಂಶ, <ph name="TOTAL_LABEL" />, ಹೆಚ್ಚಿನ ವಿವರಗಳು</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, ಉತ್ತರ, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">ಲಭ್ಯವಿದೆ</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> ಗೆ ನಿಮ್ಮ ಸಂಪರ್ಕವು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಆಗಿಲ್ಲ.</translation>
<translation id="8718314106902482036">ಪಾವತಿ ಪೂರ್ಣಗೊಂಡಿಲ್ಲ</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, ಹುಡುಕಾಟ ಸಲಹೆ</translation>
@@ -1423,6 +1442,7 @@
<translation id="8738058698779197622">ಸುರಕ್ಷಿತ ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸಲು, ನಿಮ್ಮ ಗಡಿಯಾರವನ್ನು ಸರಿಯಾಗಿ ಹೊಂದಿಸುವ ಅಗತ್ಯವಿದೆ. ವೆಬ್‌ಸೈಟ್‌ಗಳು ತಮ್ಮನ್ನು ಗುರುತಿಸಲು ಬಳಸುವ ಪ್ರಮಾಣಪತ್ರಗಳು ಸಮಯದ ನಿರ್ದಿಷ್ಟ ಅವಧಿಗಳಲ್ಲಿ ಮಾತ್ರ ಮಾನ್ಯವಾಗಿರುವ ಕಾರಣ ಹೀಗಾಗುತ್ತದೆ. ನಿಮ್ಮ ಸಾಧನದ ಗಡಿಯಾರವು ತಪ್ಪಾಗಿರುವ ಕಾರಣ, Chromium ಗೆ ಈ ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> ನ &lt;abbr id="dnsDefinition"&gt;DNS ವಿಳಾಸ&lt;/abbr&gt; ಕಂಡುಬರಲಿಲ್ಲ. ಸಮಸ್ಯೆಯನ್ನು ಪತ್ತೆಹಚ್ಚಲಾಗುತ್ತಿದೆ.</translation>
<translation id="874846938927089722">ಸ್ವೀಕೃತ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್ ಕಾರ್ಡ್‌ಗಳು</translation>
+<translation id="874918643257405732">ಈ ಟ್ಯಾಬ್ ಅನ್ನು ಬುಕ್‌ಮಾರ್ಕ್ ಮಾಡಿ</translation>
<translation id="8759274551635299824">ಈ ಕಾರ್ಡ್‌ನ ಅವಧಿ ಮುಕ್ತಾಯವಾಗಿದೆ</translation>
<translation id="8761567432415473239">Google ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್‌ ಇತ್ತೀಚಿಗೆ <ph name="SITE" /> ನಲ್ಲಿ <ph name="BEGIN_LINK" />ಹಾನಿಕಾರಕ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಕಂಡುಹಿಡಿದಿದೆ<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB ಸಾಧನ</translation>
@@ -1452,6 +1472,7 @@
<translation id="8938939909778640821">ಸಮ್ಮತಿಸಲಾದ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್ ಕಾರ್ಡ್‌ಗಳು</translation>
<translation id="8943282376843390568">ನಿಂಬೆ ಹಳದಿ</translation>
<translation id="8957210676456822347">ಕ್ಯಾಪ್ಟಿವ್ ಪೋರ್ಟಲ್ ದೃಢೀಕರಣ</translation>
+<translation id="8962950042226115166">ಅನುಮಾನಾಸ್ಪದ ಸೈಟ್</translation>
<translation id="8968766641738584599">ಕಾರ್ಡ್‌ ಉಳಿಸಿ</translation>
<translation id="8971063699422889582">ಸರ್ವರ್‌ನ ಪ್ರಕಮಾಣಪತ್ರದ ಅವಧಿ ಮುಕ್ತಾಯಗೊಂಡಿದೆ.</translation>
<translation id="8975012916872825179">ಫೋನ್ ಸಂಖ್ಯೆಗಳು, ಇಮೇಲ್ ವಿಳಾಸಗಳು ಮತ್ತು ಶಿಪ್ಪಿಂಗ್ ವಿಳಾಸಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ</translation>
@@ -1474,24 +1495,24 @@
<translation id="9035022520814077154">ಭದ್ರತಾ ದೋಷ</translation>
<translation id="9038649477754266430">ಪುಟಗಳನ್ನು ಹೆಚ್ಚು ವೇಗವಾಗಿ ಲೋಡ್ ಮಾಡಲು ಮುನ್ನೋಟಗಳನ್ನು ಬಳಸಿ</translation>
<translation id="9039213469156557790">ಅಲ್ಲದೇ, ಸುರಕ್ಷಿತವಲ್ಲದ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಈ ಪುಟ ಹೊಂದಿದೆ. ಸ್ಥಿತ್ಯಂತರಗೊಳ್ಳುವ ಸಂದರ್ಭದಲ್ಲಿ ಈ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಇತರರೂ ವೀಕ್ಷಿಸಬಹುದಾಗಿದೆ ಮತ್ತು ಪುಟದ ಹೊರನೋಟವೇ ಬದಲಾಗುವಂತೆ ಆಕ್ರಮಣಕಾರರು ಅದನ್ನು ತಿದ್ದಬಹುದಾಗಿದೆ.</translation>
+<translation id="9044359186343685026">ಸ್ಪರ್ಶ ಐಡಿ ಬಳಸಿ</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">ನೀವು <ph name="DOMAIN" /> ಅನ್ನು ತಲುಪಲು ಪ್ರಯತ್ನಿಸಿರುವಿರಿ, ಆದರೆ ಸರ್ವರ್ ಅಮಾನ್ಯ ಪ್ರಮಾಣಪತ್ರವನ್ನು ನೀಡಿದೆ.</translation>
<translation id="9050666287014529139">ಪಾಸ್‌ಫ್ರೇಸ್</translation>
<translation id="9065203028668620118">ಎಡಿಟ್</translation>
<translation id="9065745800631924235">ಇತಿಹಾಸದಿಂದ <ph name="TEXT" /> ಹುಡುಕಾಟ</translation>
<translation id="9069693763241529744">ವಿಸ್ತರಣೆಯ ಮೂಲಕ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
-<translation id="9076283476770535406">ಇದು ಪ್ರಬುದ್ಧ ವಿಷಯವನ್ನು ಹೊಂದಿರಬಹುದು</translation>
<translation id="9076630408993835509">ಈ ಬ್ರೌಸರ್ ಅನ್ನು ಕಂಪನಿ ಅಥವಾ ಇತರ ಸಂಸ್ಥೆಯ ಮೂಲಕ ನಿರ್ವಹಿಸುತ್ತಿಲ್ಲ. ಈ ಸಾಧನದಲ್ಲಿನ ಚಟುವಟಿಕೆಯನ್ನು Chrome ನಿಂದ ಹೊರಗೆ ನಿರ್ವಹಿಸಬಹುದು. <ph name="BEGIN_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">ಇನ್ನಷ್ಟು ಮಾಹಿತಿಯ ಅಗತ್ಯವಿದೆ</translation>
<translation id="9080712759204168376">ಆರ್ಡರ್ ಸಾರಾಂಶ</translation>
<translation id="9089260154716455634">ಬಿಡುವಿನ ಅವಧಿಯ ಕಾರ್ಯನೀತಿ:</translation>
<translation id="9095388113577226029">ಇನ್ನಷ್ಟು ಭಾಷೆಗಳು...</translation>
+<translation id="9098981495403789647">ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಬ್ರೌಸರ್‌ನಲ್ಲಿ Chrome ಎಂಟರ್‌ಪ್ರೈಸ್ ಬೆದರಿಕೆ ರಕ್ಷಣೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ. Chrome ಎಂಟರ್‌ಪ್ರೈಸ್ ಬೆದರಿಕೆ ರಕ್ಷಣೆಯು ನಿಮ್ಮ ಕೆಲವು ಡೇಟಾಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿದೆ.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> ಸಾಮಾನ್ಯವಾಗಿ ನಿಮ್ಮ ಮಾಹಿತಿಯನ್ನು ಸಂರಕ್ಷಿಸಲು ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಪ್ರಯೋಜನವನ್ನು ಬಳಸಿಕೊಳ್ಳುತ್ತದೆ. ಈ ಸಂದರ್ಭದಲ್ಲಿ Chromium <ph name="SITE" /> ವೆಬ್‌ಸೈಟ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ಪ್ರಯತ್ನಿಸಿದಾಗ, ಆ ವೆಬ್‌ಸೈಟ್‌‌ ಅಸಹಜ ಮತ್ತು ತಪ್ಪು ರುಜುವಾತುಗಳನ್ನು ಹಿಂತಿರುಗಿಸಿದೆ. ದಾಳಿಕೋರರು <ph name="SITE" /> ರೂಪದಲ್ಲಿ ಸೋಗು ಹಾಕಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರುವಾಗ ಅಥವಾ ವೈ-ಫೈ ಸೈನ್-ಇನ್ ಪರದೆಯು ಸಂಪರ್ಕಕ್ಕೆ ಅಡ್ಡಿಯುಂಟು ಮಾಡಿದಾಗ ಇದು ಕಂಡುಬರಬಹುದು. ಯಾವುದೇ ಡೇಟಾವನ್ನು ವಿನಿಮಯ ಮಾಡಿಕೊಳ್ಳುವ ಮೊದಲೇ Chromium ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಿರುವ ಕಾರಣ, ನಿಮ್ಮ ಮಾಹಿತಿ ಈಗಲೂ ಸುರಕ್ಷಿತವಾಗಿದೆ.</translation>
<translation id="9106062320799175032">ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸವನ್ನು ಸೇರಿಸಿ</translation>
<translation id="9114524666733003316">ಕಾರ್ಡ್‌ ದೃಢೀಕರಿಸಲಾಗುತ್ತಿದೆ...</translation>
<translation id="9128870381267983090">ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸು</translation>
<translation id="9137013805542155359">ಮೂಲವನ್ನು ತೋರಿಸಿ</translation>
-<translation id="9137248913990643158">ಈ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸುವ ಮೊದಲು Chrome ಪ್ರಾರಂಭಿಸಿ ಮತ್ತು ಸೈನ್ ಇನ್ ಮಾಡಿ.</translation>
<translation id="9141013498910525015">ವಿಳಾಸಗಳನ್ನು ನಿರ್ವಹಿಸಿ</translation>
<translation id="9148088599418889305">ಶಿಪ್ಪಿಂಗ್ ವಿಧಾನವನ್ನು ಆರಿಸಿ</translation>
<translation id="9148507642005240123">&amp;ಎಡಿಟ್ ಮಾಡುವುದನ್ನು ರದ್ದುಗೊಳಿಸಿ</translation>
diff --git a/chromium/components/strings/components_strings_ko.xtb b/chromium/components/strings/components_strings_ko.xtb
index 1344fc3651f..6d00f57ae3a 100644
--- a/chromium/components/strings/components_strings_ko.xtb
+++ b/chromium/components/strings/components_strings_ko.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">카드 명의 추가</translation>
<translation id="1089439967362294234">비밀번호 변경</translation>
+<translation id="1096545575934602868">입력란에 항목이 <ph name="MAX_ITEMS_LIMIT" />개 넘게 있으면 안 됩니다. 추가되는 모든 항목은 삭제됩니다.</translation>
<translation id="109743633954054152">Chrome 설정에서 비밀번호를 관리하세요.</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> 항상 번역</translation>
<translation id="1107591249535594099">선택하면 Chrome에서 양식을 더 빠르게 입력할 수 있도록 이 기기에 카드 사본을 저장합니다.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" />의 <ph name="BEGIN_LINK" />캐시된 사본<ph name="END_LINK" />에 액세스</translation>
<translation id="1156303062776767266">표시된 파일은 로컬 또는 공유 파일입니다.</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" />와(과)의 연결이 예기치 않게 종료되었습니다.</translation>
+<translation id="115926840831309955">CVC를 확인하고 다시 시도하거나 만료일을 업데이트하세요.</translation>
<translation id="1161325031994447685">Wi-Fi에 다시 연결</translation>
<translation id="1165039591588034296">오류</translation>
<translation id="1175364870820465910">인쇄(&amp;P)</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">'컴퓨터의 소프트웨어로 인해 Chrome이 안전하게 웹에 접속할 수 없습니다'(Windows 컴퓨터만 해당)</translation>
<translation id="1294154142200295408">명령줄 변형</translation>
<translation id="129553762522093515">최근에 닫은 탭</translation>
+<translation id="1298536327547837046">멀웨어 검사</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />쿠키 삭제해 보기<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">지원 중단 기능</translation>
<translation id="1320233736580025032">Prc1(봉투)</translation>
<translation id="132301787627749051">클립보드 이미지 검색</translation>
<translation id="1323433172918577554">더보기</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google 스프레드시트</translation>
<translation id="1527263332363067270">연결 대기 중...</translation>
<translation id="1529521330346880926">10x15(봉투)</translation>
+<translation id="1530707389502320859">방문하려고 한 사이트가 허위 사이트로 보입니다. 일부 공격자는 사이트의 URL을 알아채기 어려울 정도로 약간 변경하여 다른 사이트를 모방합니다.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">이 페이지 내용:</translation>
<translation id="153384715582417236">새 콘텐츠 없음</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">문서가 너무 커서 주석을 달 수 없습니다.</translation>
-<translation id="1721312023322545264">이 사이트를 방문하려면 <ph name="NAME" />님으로부터 권한을 받아야 합니다.</translation>
<translation id="1721424275792716183">* 필수 입력란</translation>
<translation id="1727741090716970331">유효한 카드 번호 추가</translation>
<translation id="1728677426644403582">웹페이지 소스를 보는 중</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">방문 웹사이트 및 접속 시간</translation>
<translation id="1826516787628120939">확인 중</translation>
<translation id="1834321415901700177">이 사이트에 유해한 프로그램이 있습니다.</translation>
+<translation id="1838374766361614909">검색어 지우기</translation>
<translation id="1839551713262164453">오류가 발생하여 정책 값의 유효성을 검사하지 못했습니다.</translation>
<translation id="1842969606798536927">결제</translation>
<translation id="1871208020102129563">프록시가 .pac 스크립트 URL이 아닌 고정 프록시 서버를 사용하도록 설정됩니다.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">접기 목록</translation>
<translation id="1898423065542865115">필터링</translation>
<translation id="1914326953223720820">압축 해제 서비스</translation>
+<translation id="1915697529809968049">CVC 대신 Touch ID를 사용하시겠습니까?</translation>
<translation id="1916770123977586577">이 사이트에 업데이트된 설정을 적용하려면 이 페이지를 다시 로드하세요.</translation>
<translation id="1919345977826869612">광고</translation>
<translation id="1919367280705858090">특정 오류 메시지에 관한 도움말 보기</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> 북마크</translation>
<translation id="1973335181906896915">일련화 오류</translation>
<translation id="1974060860693918893">고급</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />방문한 일부 페이지의 URL, 제한된 시스템 정보, 일부 페이지 콘텐츠<ph name="END_WHITEPAPER_LINK" />를 Google에 전송하여 Chrome 보안을 강화하는 데 참여해 주세요. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">펌웨어 버전</translation>
<translation id="1981206234434200693">Chrome 인터넷 사용 기록 삭제</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{외 1개}other{외 #개}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">올바른 만료 연도를 입력하세요.</translation>
<translation id="2212735316055980242">정책을 찾을 수 없음</translation>
<translation id="2213606439339815911">항목을 가져오는 중...</translation>
+<translation id="2215727959747642672">파일 수정</translation>
<translation id="2218879909401188352">현재 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />의 공격자가 기기를 손상시키거나, 모바일 요금에 몰래 추가 요금을 부과하거나, 개인정보를 도용하는 위험한 앱을 설치할 수도 있습니다. <ph name="BEGIN_LEARN_MORE_LINK" />자세히 알아보기<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">인터넷 연결 없음</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />진단 앱<ph name="END_LINK" />을 사용하여 연결 문제를 해결하세요.</translation>
<translation id="2239100178324503013">지금 보내기</translation>
+<translation id="2248949050832152960">WebAuthn 사용</translation>
<translation id="225207911366869382">이 값은 이 정책에 사용되지 않습니다.</translation>
<translation id="2257315177824333709">죄송합니다. 지금은 카드를 저장할 수 없습니다.</translation>
<translation id="2262243747453050782">HTTP 오류</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">검색 URL이 잘못됨</translation>
<translation id="2482878487686419369">알림</translation>
<translation id="248348093745724435">컴퓨터 정책</translation>
-<translation id="2485387744899240041">기기 및 브라우저에서 사용 중인 사용자 이름</translation>
<translation id="2491120439723279231">서버 인증서에 오류가 있습니다.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON 파서</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">뒤로 이동</translation>
<translation id="2503184589641749290">사용 가능한 직불카드 및 선불카드</translation>
<translation id="2505268675989099013">계정 보호</translation>
+<translation id="2515335152965840738">무시</translation>
<translation id="2515629240566999685">현재 지역의 신호 확인</translation>
<translation id="2523886232349826891">이 기기에만 저장됨</translation>
<translation id="2524461107774643265">자세한 정보 추가</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">제출</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{없음}=1{비밀번호 1개(도메인: <ph name="DOMAIN_LIST" />)}=2{비밀번호 2개(도메인: <ph name="DOMAIN_LIST" />)}other{비밀번호 #개(도메인: <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">다른 탭 또는 앱 닫기</translation>
-<translation id="267371737713284912"><ph name="MODIFIER_KEY_DESCRIPTION" />을(를) 눌러 실행취소합니다.</translation>
<translation id="2674170444375937751">방문 기록에서 이 페이지를 삭제하시겠습니까?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">나가기</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">값이 형식과 일치하지 않습니다.</translation>
<translation id="2705137772291741111">사이트의 저장된(캐시된) 사본을 읽을 수 없습니다.</translation>
<translation id="2709516037105925701">자동 완성</translation>
-<translation id="2712173769900027643">권한 요청</translation>
<translation id="2713444072780614174">흰색</translation>
<translation id="2720342946869265578">근처</translation>
<translation id="2721148159707890343">요청 성공</translation>
<translation id="2728127805433021124">서버의 인증서가 안전성이 낮은 서명 알고리즘을 사용하여 서명되어 있습니다.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />연결 진단 프로그램 실행<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">다음 기능을 사용 설정하면 브라우저 데이터가 손실되거나 보안이 악화되거나 개인정보가 유출될 수도 있습니다. 사용 설정된 기능은 이 브라우저의 모든 사용자에게 적용됩니다.</translation>
<translation id="2735043616039983645">이 정책에 충돌하는 값을 가진 소스가 두 개 이상 있습니다.</translation>
<translation id="2738330467931008676">수령 주소 선택</translation>
<translation id="2740531572673183784">확인</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">연결이 재설정되었습니다.</translation>
<translation id="2788784517760473862">사용 가능한 신용카드</translation>
<translation id="2792012897584536778">이 기기의 관리자가 보안 인증서를 설정했으며, 이를 통해 관리자가 내가 방문하는 웹사이트의 콘텐츠를 확인할 수 있습니다.</translation>
-<translation id="2794233252405721443">차단된 사이트</translation>
<translation id="2799020568854403057">방문하려는 사이트에 유해한 앱이 있습니다.</translation>
<translation id="2799223571221894425">다시 시작</translation>
<translation id="2803306138276472711">최근 Google 세이프 브라우징이 <ph name="SITE" />에서 <ph name="BEGIN_LINK" />멀웨어를 감지<ph name="END_LINK" />했습니다. 평소에 안전한 웹사이트도 멀웨어에 감염될 때가 있습니다.</translation>
+<translation id="2815364696811431560">사이트에서 나가기</translation>
<translation id="2824775600643448204">주소창 및 검색창</translation>
<translation id="2826760142808435982">이 연결은 <ph name="CIPHER" />을(를) 사용하여 암호화되고 인증되며 <ph name="KX" />을(를) 키 교환 매커니즘으로 사용합니다.</translation>
<translation id="2835170189407361413">서식 지우기</translation>
<translation id="2847118875340931228">시크릿 창 열기</translation>
<translation id="2850739647070081192">Invite(봉투)</translation>
-<translation id="2851634818064021665">이 사이트에 방문하려면 권한이 필요합니다.</translation>
<translation id="2856444702002559011">공격자가 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />에서 정보(예: 비밀번호, 메시지, 신용카드 등)를 도용하려고 시도 중일 수 있습니다. <ph name="BEGIN_LEARN_MORE_LINK" />자세히 알아보기<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">카드를 저장하시겠습니까?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">선택하면 이 기기에 카드 사본이 저장되어 Chromium에서 양식을 더 빠르게 작성할 수 있습니다.</translation>
<translation id="2985398929374701810">올바른 주소를 입력하세요.</translation>
<translation id="2986368408720340940">사용할 수 없는 수령 방법입니다. 다른 방법을 선택하세요.</translation>
+<translation id="2987034854559945715">일치하는 기능 없음</translation>
<translation id="2991174974383378012">웹사이트와 공유</translation>
<translation id="2991571918955627853">웹사이트에서 HSTS를 사용하므로 지금은 <ph name="SITE" />에 방문할 수 없습니다. 네트워크 오류와 공격은 대체로 일시적인 문제이기 때문에 나중에 이 페이지가 정상적으로 작동할 수 있습니다.</translation>
<translation id="3005723025932146533">저장된 사본 표시</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">잘못된 정책 유형</translation>
<translation id="3037605927509011580">앗, 이런!</translation>
<translation id="3041612393474885105">인증서 정보</translation>
+<translation id="3057676462092457419">DnsOverHttps 모드(<ph name="SECURE_DNS_MODE_SECURE" />)는 아직 지원되지 않으며 <ph name="SECURE_DNS_MODE_OFF" />(으)로 설정되었습니다.</translation>
<translation id="3060227939791841287">C9(봉투)</translation>
<translation id="3061707000357573562">서비스 패치</translation>
<translation id="3064966200440839136">시크릿 모드를 종료하고 외부 애플리케이션에서 결제합니다. 계속하시겠습니까?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" />의 <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">결제 취소</translation>
<translation id="3207960819495026254">북마크에 추가됨</translation>
+<translation id="3209034400446768650">페이지에서 요금을 청구할 수 있음</translation>
<translation id="3225919329040284222">서버가 내장된 기대치와 일치하지 않는 인증서를 전달했습니다. 이러한 기대치는 사용자를 보호하기 위해 보안이 엄격한 특정 웹사이트에 포함됩니다.</translation>
<translation id="3226128629678568754">페이지 로드에 필요한 데이터를 다시 제출하려면 새로고침 버튼을 누릅니다.</translation>
<translation id="3227137524299004712">마이크</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">기기와 브라우저에 관한 버전 정보</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> 카드의 CVC를 입력하세요.</translation>
<translation id="3234666976984236645">이 사이트에서 중요한 콘텐츠 항상 감지</translation>
-<translation id="3254409185687681395">현재 페이지를 북마크에 추가</translation>
<translation id="3270847123878663523">재정렬 실행 취소(&amp;U)</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">카드 명의 추가</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">청구지 주소 추가</translation>
<translation id="3324983252691184275">진홍색</translation>
<translation id="3338095232262050444">보안 연결</translation>
-<translation id="3345135638360864351">이 사이트에 대한 액세스 요청을 <ph name="NAME" />님에게 보내지 못했습니다. 나중에 다시 시도해 주세요.</translation>
<translation id="3355823806454867987">프록시 설정 변경...</translation>
<translation id="3361596688432910856">Chrome에 다음 정보가 <ph name="BEGIN_EMPHASIS" />저장되지 않습니다<ph name="END_EMPHASIS" />.
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">세부정보 숨기기</translation>
<translation id="3467763166455606212">카드 소유자 이름을 입력해야 합니다.</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, 현재 열려 있음, Tab을 누른 다음 Enter를 눌러 열린 탭으로 전환</translation>
-<translation id="3479539252931486093">예기치 않은 문제가 발생했나요? <ph name="BEGIN_LINK" />Google에 알리기<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">나중에</translation>
<translation id="3484560055331845446">Google 계정에 액세스하지 못할 수 있습니다. 따라서 지금 비밀번호를 변경하는 것이 좋습니다. 로그인하라는 메시지가 표시됩니다.</translation>
<translation id="3495081129428749620"><ph name="PAGE_TITLE" />
페이지에서 찾기</translation>
-<translation id="3498215018399854026">현재 부모님께 연락할 수 없습니다. 나중에 다시 시도해 주세요.</translation>
<translation id="3512163584740124171">동일한 정책 그룹에 있는 다른 정책이 우선순위가 높기 때문에 이 정책은 무시됩니다.</translation>
<translation id="3528171143076753409">서버의 인증서를 신뢰할 수 없습니다.</translation>
<translation id="3528485271872257980">진한 갈색</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{동기화된 기기에 항목 1개 이상}=1{항목 1개(동기화된 기기에는 그 이상)}other{항목 #개(동기화된 기기에는 그 이상)}}</translation>
<translation id="3539171420378717834">카드 사본을 이 기기에 저장</translation>
-<translation id="3556433843310711081">관리자가 차단 해제할 수 있습니다.</translation>
<translation id="3566021033012934673">연결이 비공개로 설정되어 있지 않습니다.</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" /> <ph name="STATE" />, <ph name="CITY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" />에 삽입된 페이지 내용:</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">새 시크릿 창에서 페이지 열기(Ctrl-Shift-N)</translation>
<translation id="3679803492151881375"><ph name="CRASH_TIME" />에 캡처된 비정상 종료 보고서가 <ph name="UPLOAD_TIME" />에 업로드됨</translation>
<translation id="3681007416295224113">인증서 정보</translation>
+<translation id="3701427423622901115">재설정이 확인되었습니다.</translation>
<translation id="3704162925118123524">사용 중인 네트워크에서 로그인 페이지 방문을 요청할 수 있습니다.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">로드 중...</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />의 공격자가 소프트웨어를 설치하거나 개인정보(예: 비밀번호, 전화번호, 신용카드)를 공개하는 등의 위험한 행동을 하도록 사용자를 속일 수 있습니다. <ph name="BEGIN_LEARN_MORE_LINK" />자세히 알아보기<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">서버 오류가 발생하여 번역하지 못했습니다.</translation>
<translation id="3759461132968374835">최근에 보고된 비정상 종료가 없습니다. 비정상 종료 보고를 사용 중지했을 때 발생한 비정상 종료는 여기에 표시되지 않습니다.</translation>
+<translation id="3760561303380396507">CVC 대신 Windows Hello를 사용하시겠습니까?</translation>
<translation id="3761718714832595332">상태 숨기기</translation>
<translation id="3765032636089507299">세이프 브라우징 페이지는 현재 준비 중입니다.</translation>
<translation id="3778403066972421603">이 카드를 Google 계정과 이 기기에 저장하시겠습니까?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">크기 16</translation>
<translation id="3797522431967816232">Prc3(봉투)</translation>
<translation id="3807873520724684969">유해한 콘텐츠 차단됨</translation>
+<translation id="3808375843007691220">경고: 실험 기능입니다.</translation>
<translation id="3810973564298564668">관리</translation>
<translation id="382518646247711829">프록시 서버를 사용하는 경우</translation>
<translation id="3828924085048779000">암호를 빈 칸으로 두어서는 안 됩니다.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">시간과 날짜 업데이트</translation>
<translation id="3884278016824448484">기기 식별자 충돌</translation>
<translation id="3885155851504623709">교구</translation>
-<translation id="3886446263141354045">사용자의 사이트 액세스 요청이 <ph name="NAME" />님에게 전송되었습니다.</translation>
<translation id="3890664840433101773">이메일 추가</translation>
<translation id="3901925938762663762">만료된 카드입니다.</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVC 대신 WebAuthn을 사용하시겠습니까?</translation>
<translation id="3946209740501886391">이 사이트에서 항상 물어보기</translation>
<translation id="3949571496842715403">보안 인증서에 주체 대체 이름(SAN)이 지정되어 있지 않아 이 서버가 <ph name="DOMAIN" />임을 입증할 수 없습니다. 서버를 잘못 설정했거나 공격자가 연결을 가로채고 있기 때문일 수도 있습니다.</translation>
<translation id="3949601375789751990">인터넷 사용 기록이 여기에 표시됩니다.</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{없음}=1{사이트 1개 }other{사이트 #개 }}</translation>
<translation id="397105322502079400">계산 중...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" />이(가) 차단됨</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" />에서 브라우저의 Chrome Enterprise Threat Protection을 사용 설정했습니다. Chrome Enterprise Threat Protection에서 내 데이터 중 일부에 액세스할 권한이 있습니다.</translation>
<translation id="3987940399970879459">1MB 미만</translation>
<translation id="40103911065039147">{URL_count,plural, =1{주변 웹페이지 1개}other{주변 웹페이지 #개}}</translation>
<translation id="4030383055268325496">추가 실행 취소(&amp;U)</translation>
<translation id="4032320456957708163"><ph name="ENROLLMENT_DOMAIN" />에서 관리하는 브라우저입니다</translation>
-<translation id="4034375457890803692">클릭한 링크가 평소에 방문하지 않는 사이트로 연결됩니다. 사용자에게 혼란을 주려는 시도일 수도 있습니다.</translation>
<translation id="4058922952496707368">'<ph name="SUBKEY" />' 키: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1(봉투)</translation>
<translation id="4067947977115446013">유효한 주소 추가</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">기기 일련번호가 잘못됨</translation>
<translation id="410351446219883937">자동재생</translation>
<translation id="4103763322291513355">차단된 URL 및 시스템 관리자가 설정한 기타 정책 목록을 확인하려면 &lt;strong&gt;chrome://policy&lt;/strong&gt;를 방문하세요.</translation>
+<translation id="4108231218301530806">다음번에 지문을 사용해 이 카드를 인증합니다.</translation>
<translation id="4110652170750985508">결제 검토</translation>
<translation id="4112140312785995938">뒤로 탐색</translation>
<translation id="4116663294526079822">이 사이트에서 항상 허용</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">잘못된 인증 서명입니다.</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{그 외 <ph name="ITEM_COUNT" />개 항목}other{그 외 <ph name="ITEM_COUNT" />개 항목}}</translation>
+<translation id="4176463684765177261">사용 중지됨</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">다음번에 더 빠르게 결제할 수 있도록 Google 계정에 카드와 청구서 수신 주소를 추가하세요.</translation>
<translation id="4196861286325780578">이동 다시 실행(&amp;R)</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">비밀번호 재설정</translation>
<translation id="4279811152705618813"><ph name="ENROLLMENT_DOMAIN" />에서 <ph name="DEVICE_TYPE" />을(를) 관리합니다</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{다음 카드가 Google 계정에 저장되었습니다.}other{다음 카드가 Google 계정에 저장되었습니다.}}</translation>
+<translation id="428847186335018806">Chrome에서 다운로드 또는 업로드한 파일을 검사합니다.</translation>
<translation id="42981349822642051">펼치기</translation>
<translation id="4302965934281694568">Chou3(봉투)</translation>
<translation id="4305817255990598646">전환</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">엽서)</translation>
<translation id="443673843213245140">프록시 사용은 중지되었지만 명시적 프록시 설정이 지정되어 있습니다.</translation>
<translation id="445100540951337728">사용 가능한 직불카드</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> 의심스러운 행위</translation>
<translation id="4466881336512663640">양식에서 변경한 사항이 삭제됩니다. 계속하시겠습니까?</translation>
<translation id="4477350412780666475">다음 트랙</translation>
<translation id="4482953324121162758">이 사이트는 번역되지 않습니다.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">삭제 실행 취소(&amp;U)</translation>
<translation id="4597348597567598915">크기 8</translation>
<translation id="4600854749408232102">C6/C5(봉투)</translation>
+<translation id="464342062220857295">검색 기능</translation>
<translation id="4646534391647090355">지금 이동</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">이 서버가 <ph name="DOMAIN" />임을 입증할 수 없으며 서버의 보안 인증서에 오류가 있습니다. 서버를 잘못 설정했거나 불법 사용자가 연결을 가로채고 있기 때문일 수 있습니다.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A(봉투)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">연결이 끊김</translation>
-<translation id="471880041731876836">이 사이트에 방문할 수 있는 권한이 없습니다.</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows 네트워크 진단 프로그램 실행<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">정책 새로고침</translation>
<translation id="4728558894243024398">플랫폼</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">페이지 맞춤</translation>
<translation id="4850886885716139402">보기</translation>
<translation id="4854362297993841467">사용할 수 없는 배달 방법입니다. 다른 방법을 선택하세요.</translation>
-<translation id="4858792381671956233">이 사이트를 방문해도 괜찮은지 부모님께 문의했습니다.</translation>
<translation id="4864052566555297930">보안 도움말:</translation>
<translation id="4876188919622883022">간단히 보기</translation>
<translation id="4876305945144899064">사용자 이름 없음</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">경고 다시 사용</translation>
<translation id="4984339528288761049">Prc5(봉투)</translation>
<translation id="4989163558385430922">모두 보기</translation>
+<translation id="4989542687859782284">사용할 수 없음</translation>
<translation id="4989809363548539747">이 플러그인은 지원되지 않습니다.</translation>
+<translation id="4995216769782533993">카드 세부정보를 이 사이트와 공유하려면 보안 코드를 확인하세요.</translation>
<translation id="5002932099480077015">선택하면 Chrome에서 양식을 더 빠르게 작성할 수 있도록 이 기기에 카드 사본을 저장합니다.</translation>
<translation id="5015510746216210676">컴퓨터 이름:</translation>
<translation id="5017554619425969104">복사한 텍스트</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64비트)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">카드 인증</translation>
<translation id="5135404736266831032">주소 관리...</translation>
<translation id="5138227688689900538">간략히</translation>
<translation id="5141240743006678641">동기화 비밀번호를 Google 자격증명으로 암호화</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">클라우드</translation>
<translation id="5252000469029418751">C7(봉투)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">시스템 전체에 적용되는 기능은 소유자(<ph name="OWNER_EMAIL" />)만 설정할 수 있습니다.</translation>
<translation id="5273658854610202413">경고: 이 정책은 병합 가능한 사전 정책의 일부가 아니므로 PolicyDictionaryMultipleSourceMergeList 정책에 명시된 대로 병합되지 않았습니다.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">종료</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">정책 설정 저장 실패</translation>
<translation id="5371425731340848620">카드 업데이트</translation>
<translation id="5377026284221673050">'시간이 너무 먼 과거로 설정되어 있습니다.', '시간이 너무 먼 미래로 설정되어 있습니다.', 또는 '&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;'</translation>
-<translation id="5377179979757081683">사용자를 속여 개인정보를 탈취하거나 기기를 손상시킬 수 있는 페이지입니다. 개인정보를 입력하거나 다운로드한 파일을 열 때 주의하세요.</translation>
<translation id="5384855140246857529">어느 기기에서나 카드를 사용하려면 로그인하고 동기화를 사용 설정하세요.</translation>
<translation id="5386426401304769735">이 사이트의 인증서 체인은 SHA-1을 사용하여 서명된 인증서를 포함합니다.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,7 @@
<translation id="5457113250005438886">잘못된 데이터</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />개}other{<ph name="CONTACT_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />개}}</translation>
<translation id="5470861586879999274">수정 다시 실행(&amp;R)</translation>
+<translation id="5473728911100096288">이 기능을 사용 설정하면 향후 버전에서 제외될 지원 중단 기능을 사용하게 됩니다.</translation>
<translation id="5478437291406423475">B6/C4(봉투)</translation>
<translation id="5481076368049295676">이 콘텐츠는 사용자의 정보를 도용하거나 삭제하는 위험한 소프트웨어를 기기에 설치하려 할 수도 있습니다. <ph name="BEGIN_LINK" />표시하기<ph name="END_LINK" /></translation>
<translation id="54817484435770891">유효한 주소 추가</translation>
@@ -863,7 +876,6 @@
<translation id="5570825185877910964">계정 보호</translation>
<translation id="5571083550517324815">이 주소에서 수령할 수 없습니다. 다른 주소를 선택하세요.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1개 사용 중}other{#개 사용 중}})</translation>
-<translation id="5572851009514199876">이 사이트에 액세스할 수 있는지 확인할 수 있도록 Chrome을 시작하고 로그인하세요.</translation>
<translation id="5580958916614886209">유효기간 월을 확인한 후 다시 시도해 주세요.</translation>
<translation id="5586446728396275693">저장된 주소 없음</translation>
<translation id="5595485650161345191">주소 수정</translation>
@@ -871,6 +883,7 @@
<translation id="560412284261940334">관리가 지원되지 않음</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">허위 또는 사기성 사이트일 수 있습니다. Chrome에서는 사이트에서 지금 바로 나갈 것을 권장합니다.</translation>
<translation id="5610142619324316209">연결 확인</translation>
<translation id="5610807607761827392"><ph name="BEGIN_LINK" />설정<ph name="END_LINK" />에서 카드와 주소를 관리할 수 있습니다.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" />에서 리디렉션한 횟수가 너무 많습니다.</translation>
@@ -894,11 +907,11 @@
<translation id="5720705177508910913">현재 사용자</translation>
<translation id="5728056243719941842">C5(봉투)</translation>
<translation id="5730040223043577876">다른 사이트에서 비밀번호를 재사용했다면 비밀번호를 재설정하는 것이 좋습니다.</translation>
-<translation id="5732392974455271431">부모님이 차단 해제할 수 있습니다.</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Google 계정에 카드 저장}other{Google 계정에 카드 저장}}</translation>
<translation id="5763042198335101085">올바른 이메일 주소를 입력하세요.</translation>
<translation id="5765072501007116331">배달 방법과 요구사항을 확인하려면 주소를 선택하세요.</translation>
<translation id="5778550464785688721">MIDI 기기 전체 제어</translation>
+<translation id="5781136890105823427">실험 기능 사용 설정됨</translation>
<translation id="578305955206182703">황색</translation>
<translation id="57838592816432529">음소거</translation>
<translation id="5784606427469807560">카드 확인 중에 문제가 발생했습니다. 인터넷 연결을 확인하고 다시 시도하세요.</translation>
@@ -915,13 +928,16 @@
<translation id="5860033963881614850">사용 안함</translation>
<translation id="5863847714970149516">방문하려는 페이지에서 금액을 청구할 수 있습니다.</translation>
<translation id="5866257070973731571">전화번호 추가</translation>
+<translation id="5866898949289125849">개발자 도구 페이지를 보는 중입니다.</translation>
<translation id="5869405914158311789">사이트에 연결할 수 없음</translation>
<translation id="5869522115854928033">저장된 비밀번호</translation>
<translation id="5887400589839399685">저장된 카드</translation>
<translation id="5893752035575986141">신용카드를 사용할 수 있습니다.</translation>
+<translation id="5895138241574237353">다시 시작</translation>
<translation id="5901630391730855834">노란색</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" />(동기화됨)</translation>
<translation id="5916664084637901428">사용</translation>
+<translation id="59174027418879706">사용가능</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">카드를 Google 계정에 저장하시겠습니까?</translation>
<translation id="5922853866070715753">거의 완료되었습니다</translation>
@@ -955,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">모든 기기에서 카드를 사용하고 싶으신가요?</translation>
<translation id="6059925163896151826">USB 기기</translation>
+<translation id="6060009363608157444">잘못된 DnsOverHttps 모드입니다.</translation>
<translation id="6080696365213338172">관리자 제공 인증서를 사용하여 콘텐츠에 액세스했습니다. 사용자가 <ph name="DOMAIN" />에 제공한 데이터가 관리자에 의해 차단될 수 있습니다.</translation>
<translation id="6094273045989040137">주석 추가</translation>
<translation id="610911394827799129">Google 계정의 내 활동(<ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />)에는 인터넷 방문 기록이 다른 형식으로 남아 있을 수도 있습니다</translation>
@@ -1003,13 +1020,12 @@
<translation id="6404511346730675251">북마크 수정</translation>
<translation id="6406765186087300643">C0(봉투)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" />의 만료일과 CVC를 입력하세요.</translation>
-<translation id="6414888972213066896">이 사이트를 방문해도 괜찮은지 부모님께 문의했습니다.</translation>
<translation id="6415778972515849510">Chromium을 통해 Google 계정을 보호하고 비밀번호를 변경할 수 있습니다.</translation>
-<translation id="6417515091412812850">인증서가 취소되었는지 확인할 수 없습니다.</translation>
<translation id="6431585503458005759">저장하지 않습니다</translation>
<translation id="6433490469411711332">연락처 정보 수정</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" />에서 연결을 거부했습니다.</translation>
<translation id="6434309073475700221">중지</translation>
+<translation id="6435221585574090192">Chrome Enterprise Threat Protection에서 신고한 보안 이벤트에 관한 데이터를 관리자와 공유합니다. 여기에는 페이지 URL, 파일 이름, 파일 메타데이터, 기기 사용자 이름 및 Chrome 사용자 이름이 포함될 수 있습니다.</translation>
<translation id="6440503408713884761">무시됨</translation>
<translation id="6446163441502663861">Kahu(봉투)</translation>
<translation id="6446608382365791566">자세한 정보 추가</translation>
@@ -1018,20 +1034,19 @@
<translation id="6465306955648956876">비밀번호 관리...</translation>
<translation id="647261751007945333">기기 정책</translation>
<translation id="6476284679642588870">결제 수단 관리</translation>
-<translation id="6477321094435799029">Chrome이 이 페이지에서 비정상적인 코드를 감지했으며 개인정보(예: 비밀번호, 전화번호, 신용카드) 보호를 위해 차단했습니다.</translation>
<translation id="6489534406876378309">비정상 종료 업로드 시작하기</translation>
<translation id="6499038740797743453">비밀번호를 재설정하시겠습니까?</translation>
<translation id="6507833130742554667">신용카드 및 직불카드를 사용할 수 있습니다.</translation>
<translation id="650855688985305916">예, 저장합니다</translation>
<translation id="6508722015517270189">Chrome 다시 시작하기</translation>
<translation id="6517596291481585650">경고: 이 정책은 목록이 아니므로 정책에 명시된 대로 목록으로 병합되지 않았습니다.</translation>
+<translation id="6518133107902771759">확인</translation>
<translation id="6521745193039995384">활성화되지 않음</translation>
<translation id="6529602333819889595">삭제 다시 실행(&amp;R)</translation>
<translation id="6534179046333460208">피지컬 웹 제안</translation>
<translation id="6545864417968258051">블루투스 검색</translation>
<translation id="6554795675067793129">사용자의 계정은 <ph name="ENROLLMENT_DOMAIN" />에서 관리합니다.</translation>
<translation id="6556866813142980365">다시실행</translation>
-<translation id="6563469144985748109">관리자가 아직 승인하지 않았습니다.</translation>
<translation id="6569060085658103619">확장 프로그램 페이지를 보는 중</translation>
<translation id="6578796323535178455">C2(봉투)</translation>
<translation id="6579990219486187401">연한 분홍색</translation>
@@ -1049,11 +1064,13 @@
<translation id="6643016212128521049">삭제</translation>
<translation id="6644283850729428850">이 정책은 사용되지 않습니다.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{없음}=1{사이트 1개(Google 계정에서 로그아웃되지 않음)}other{사이트 #개(Google 계정에서 로그아웃되지 않음)}}</translation>
+<translation id="6652101503459149953">Windows Hello 사용</translation>
<translation id="6657585470893396449">비밀번호</translation>
<translation id="6670613747977017428">안전한 페이지로 돌아갑니다.</translation>
<translation id="6671697161687535275">Chromium에서 자동완성 항목 추천을 삭제하시겠습니까?</translation>
<translation id="6685834062052613830">로그아웃 후 설정 완료</translation>
<translation id="6689271823431384964">Google 계정에 로그인되어 있기 때문에 Chrome에서 계정에 카드를 저장할지 묻는 메시지가 표시됩니다. 설정에서 이 동작을 변경할 수 있습니다. 카드 소지자 이름은 계정에서 가져온 것입니다.</translation>
+<translation id="6707256370811247129">Chrome에서 다운로드 또는 업로드하는 캐시와 파일의 내용을 검사합니다.</translation>
<translation id="6710213216561001401">이전</translation>
<translation id="6710594484020273272">&lt;검색어 입력&gt;</translation>
<translation id="671076103358959139">등록 토큰:</translation>
@@ -1061,10 +1078,10 @@
<translation id="6738516213925468394"><ph name="TIME" />자로 <ph name="BEGIN_LINK" />동기화 암호<ph name="END_LINK" />를 통해 데이터가 암호화되었습니다. 동기화를 시작하려면 암호를 입력하세요.</translation>
<translation id="674375294223700098">알 수 없는 서버 인증서 오류입니다.</translation>
<translation id="6744009308914054259">연결을 기다리는 동안 다운로드에서 오프라인 기사를 읽을 수 있습니다.</translation>
+<translation id="6747611005629681221">경고: 지원 중단된 기능입니다.</translation>
<translation id="6753269504797312559">정책 값</translation>
<translation id="6757797048963528358">기기가 절전 모드 상태입니다.</translation>
<translation id="6768213884286397650">Hagaki(엽서)</translation>
-<translation id="6778737459546443941">부모님이 아직 승인하지 않았습니다.</translation>
<translation id="67862343314499040">보라색</translation>
<translation id="6786747875388722282">확장 프로그램</translation>
<translation id="6790428901817661496">재생</translation>
@@ -1072,6 +1089,7 @@
<translation id="681021252041861472">필수 입력란</translation>
<translation id="6810899417690483278">맞춤설정 ID</translation>
<translation id="6825578344716086703"><ph name="DOMAIN" />에 접속하려 했으나 서버에서 안전성이 낮은 서명 알고리즘을 사용하여 서명된 인증서(예: SHA-1)를 전달했습니다. 이는 서버에서 전달한 보안 사용자 인증 정보가 위조되었을 수 있으며 사용하려는 서버가 아님을 의미합니다. 서버를 가장한 공격자와 통신 중일 수 있습니다.</translation>
+<translation id="6826370046007623921">데이터 손실 방지</translation>
<translation id="6831043979455480757">번역</translation>
<translation id="6839929833149231406">지구</translation>
<translation id="6852204201400771460">앱을 새로고침하시겠습니까?</translation>
@@ -1084,7 +1102,6 @@
<translation id="6891596781022320156">정책 수준이 지원되지 않습니다.</translation>
<translation id="6895330447102777224">카드가 확인되었습니다.</translation>
<translation id="6897140037006041989">사용자 에이전트</translation>
-<translation id="6903319715792422884">일부 <ph name="BEGIN_WHITEPAPER_LINK" />시스템 정보와 페이지 콘텐츠<ph name="END_WHITEPAPER_LINK" />를 Google로 전송하여 세이프 브라우징을 개선하도록 도와주세요. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">사용자:</translation>
<translation id="6934672428414710184">Google 계정에 등록된 이름입니다.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />에서 관리하지 않는 사이트에 비밀번호를 입력했습니다. 계정을 안전하게 보호하려면 다른 앱과 사이트에서 동일한 비밀번호를 재사용하지 마세요.</translation>
@@ -1129,6 +1146,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />개}other{<ph name="PAYMENT_METHOD_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />개}}</translation>
<translation id="7153618581592392745">라벤더색</translation>
<translation id="717330890047184534">GAIA ID:</translation>
+<translation id="7174545416324379297">병합됨</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />개}other{<ph name="SHIPPING_OPTION_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />개}}</translation>
<translation id="7177397715882417099">대상 서버인 <ph name="ORIGIN" />에서 모든 요청에
보안 정책 적용을 요청했습니다. 하지만
@@ -1166,6 +1184,7 @@
<translation id="7320336641823683070">연결 도움말</translation>
<translation id="733354035281974745">기기 로컬 계정 재정의</translation>
<translation id="7334320624316649418">재정렬 다시 실행(&amp;R)</translation>
+<translation id="7337706099755338005">사용 중인 플랫폼에서는 제공되지 않습니다.</translation>
<translation id="733923710415886693">서버 인증서가 인증서 투명성 정책을 사용하여 공개되지 않았습니다.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">연결됨:</translation>
@@ -1196,7 +1215,6 @@
<translation id="7440140511386898319">오프라인 상태일 때 탐색</translation>
<translation id="7441627299479586546">잘못된 정책 주체</translation>
<translation id="7442725080345379071">연한 주황색</translation>
-<translation id="7444046173054089907">차단된 사이트</translation>
<translation id="7445762425076701745">연결하려는 서버 ID를 확인할 수 없습니다. 외부 인증 기관에서 소유권을 확인할 수 없으므로 네트워크에서 유효한 이름을 사용하여 서버에 연결됩니다. 일부 인증 기관에서는 이러한 이름에 대해 관계없이 인증서를 발급하기 때문에 공격자가 아니라 의도한 웹사이트에 연결되어 있는지 확인할 수 없습니다.</translation>
<translation id="7451311239929941790">이 문제를 <ph name="BEGIN_LINK" />자세히 알아보기<ph name="END_LINK" /></translation>
<translation id="7455133967321480974">전체 기본값 사용(차단)</translation>
@@ -1218,9 +1236,9 @@
<translation id="7538364083937897561">A2(봉투)</translation>
<translation id="7542403920425041731">확인하면 카드 세부정보가 이 사이트와 공유됩니다.</translation>
<translation id="7542995811387359312">양식에 보안 연결이 사용되지 않아 신용카드 자동 채우기가 사용 중지되었습니다.</translation>
-<translation id="7543525346216957623">부모님께 물어보세요.</translation>
<translation id="7548892272833184391">연결 문제해결</translation>
<translation id="7549584377607005141">이 웹페이지를 제대로 표시하려면 이전에 입력한 데이터가 필요합니다. 이 데이터를 다시 보낼 수 있지만 이 경우 해당 페이지에서 이전에 수행한 작업이 반복됩니다.</translation>
+<translation id="7550637293666041147">기기 사용자 이름 및 Chrome 사용자 이름</translation>
<translation id="7552846755917812628">다음 도움말을 확인해 보세요.</translation>
<translation id="7554791636758816595">새 탭</translation>
<translation id="7564049878696755256"><ph name="ORG_NAME" /> 계정에 액세스할 수 없게 되거나 신원 도용이 발생할 수도 있습니다. 따라서 지금 비밀번호를 변경하는 것이 좋습니다.</translation>
@@ -1235,6 +1253,7 @@
<translation id="7610193165460212391">값(<ph name="VALUE" />)이 범위를 벗어났습니다.</translation>
<translation id="7613889955535752492">만료일: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">다른 Google 계정 비밀번호 버전을 사용하여 암호화된 데이터가 이미 있습니다. 아래에 암호를 입력하시기 바랍니다.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">성능 데이터 및 비정상 종료 보고서</translation>
<translation id="7637571805876720304">Chromium에서 신용카드를 삭제하시겠습니까?</translation>
<translation id="7638605456503525968">직렬 포트</translation>
@@ -1247,7 +1266,6 @@
<translation id="7668654391829183341">알 수 없는 기기</translation>
<translation id="7669271284792375604">이 사이트의 공격자가 인터넷 사용 환경에 악영향을 미치는 프로그램을 설치하도록 속임수(예를 들어, 방문하는 사이트의 홈페이지를 변경하거나 추가로 광고를 표시)를 시도할 수 있습니다.</translation>
<translation id="7676643023259824263">클립보드 텍스트 <ph name="TEXT" /> 검색</translation>
-<translation id="7679176406634891508">플랫폼 및 클라우드</translation>
<translation id="7681101578153515023">검색엔진 변경</translation>
<translation id="7682287625158474539">배송</translation>
<translation id="7687186412095877299">저장된 결제 수단이 결제 양식에 자동으로 입력됩니다.</translation>
@@ -1262,7 +1280,6 @@
<translation id="7723047071702270851">카드 수정</translation>
<translation id="774634243536837715">위험한 콘텐츠 차단됨</translation>
<translation id="7752995774971033316">관리되지 않음</translation>
-<translation id="7755287808199759310">부모님이 차단 해제할 수 있습니다.</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">방화벽이나 바이러스 백신 소프트웨어가 연결을 차단했을 수 있습니다.</translation>
<translation id="7759163816903619567">표시 도메인:</translation>
@@ -1306,7 +1323,6 @@
<translation id="8004582292198964060">브라우저</translation>
<translation id="8009225694047762179">비밀번호 관리</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{이 카드와 청구서 수신 주소가 저장됩니다. <ph name="USER_EMAIL" /> 계정으로 로그인하면 카드를 사용할 수 있습니다.}other{이 카드와 청구서 수신 주소가 저장됩니다. <ph name="USER_EMAIL" /> 계정으로 로그인하면 카드를 사용할 수 있습니다.}}</translation>
-<translation id="8012647001091218357">현재 부모님께 연락할 수 없습니다. 나중에 다시 시도해 주세요.</translation>
<translation id="8025119109950072390">이 사이트의 공격자가 소프트웨어를 설치하거나 개인정보(예: 비밀번호, 전화번호, 신용카드)를 공개하는 등의 위험한 행동을 하도록 사용자를 속일 수 있습니다.</translation>
<translation id="8034522405403831421">이 페이지는 <ph name="SOURCE_LANGUAGE" />로 되어 있습니다. <ph name="TARGET_LANGUAGE" />로 번역하시겠습니까?</translation>
<translation id="8035152190676905274">펜</translation>
@@ -1317,6 +1333,7 @@
<translation id="8041940743680923270">전체 기본값 사용(요청)</translation>
<translation id="8042918947222776840">수령 방법 선택</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />이(가) 올바르게 설정되지 않았습니다. 일반적으로 '<ph name="SOFTWARE_NAME" />'을(를) 제거하면 문제가 해결됩니다. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">지금부터 카드의 보안 코드를 입력하지 않아도 됩니다.</translation>
<translation id="8066955247577885446">문제 발생</translation>
<translation id="8074253406171541171">10x13(봉투)</translation>
<translation id="8078141288243656252">회전 시 주석을 달 수 없습니다.</translation>
@@ -1347,6 +1364,7 @@
<translation id="8211406090763984747">이 사이트는 보안 연결(HTTPS)이 사용되었습니다.</translation>
<translation id="8218327578424803826">지정된 위치:</translation>
<translation id="8220146938470311105">C7/C6(봉투)</translation>
+<translation id="8220639454292072926">엔터프라이즈 보고</translation>
<translation id="8225771182978767009">컴퓨터를 설정한 사용자가 이 사이트를 차단했습니다.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">새 시크릿 창에서 페이지 열기</translation>
@@ -1401,23 +1419,23 @@
<translation id="8508648098325802031">검색 아이콘</translation>
<translation id="8522552481199248698">Chrome을 통해 Google 계정을 보호하고 비밀번호를 변경할 수 있습니다.</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />감지 문제를 신고<ph name="END_ERROR_LINK" />할 수 있으며, 보안에 미치는 위험을 감수한다면 <ph name="BEGIN_LINK" />이 안전하지 않은 사이트를 방문<ph name="END_LINK" />할 수 있습니다.</translation>
-<translation id="8543556556237226809">질문이 있으신가요? 프로필 관리자에게 문의하세요.</translation>
<translation id="8553075262323480129">페이지의 언어를 결정할 수 없으므로 번역하지 못했습니다.</translation>
<translation id="8557066899867184262">CVC는 카드 뒷면에 있습니다.</translation>
<translation id="8559762987265718583">기기의 날짜와 시간(<ph name="DATE_AND_TIME" />)이 잘못되어 <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />에 대한 비공개 연결을 설정할 수 없습니다.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> 의심스러운 사이트</translation>
<translation id="8564985650692024650">다른 사이트에서 비밀번호를 재사용했다면 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 비밀번호를 재설정하는 것이 좋습니다.</translation>
<translation id="8571890674111243710">페이지를 <ph name="LANGUAGE" />(으)로 번역 중...</translation>
<translation id="858637041960032120">번호 추가</translation>
-<translation id="859285277496340001">인증서는 취소 여부를 확인하는 매커니즘을 지정하지 않습니다.</translation>
<translation id="860043288473659153">카드 명의자 이름</translation>
<translation id="861775596732816396">크기 4</translation>
-<translation id="8620436878122366504">부모님이 아직 승인하지 않았습니다.</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">이 기기에 카드 저장</translation>
<translation id="8626112503828625890">Google 계정에서 스토어 결제 세부정보를 확인하시겠습니까?</translation>
+<translation id="8647750283161643317">기본값으로 재설정</translation>
<translation id="8663226718884576429">주문 요약, <ph name="TOTAL_LABEL" />, 세부정보 더보기</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, 답변, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">사용 가능</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" />로의 연결은 암호화되지 않습니다.</translation>
<translation id="8718314106902482036">결제가 완료되지 않음</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, 추천 검색어</translation>
@@ -1428,6 +1446,7 @@
<translation id="8738058698779197622">보안 연결을 설정하려면 시계가 올바로 설정되어 있어야 합니다. 웹사이트가 자신을 식별하는 데 사용하는 인증서가 특정 기간에만 유효하기 때문입니다. 기기의 시계가 잘못 설정되어 Chromium에서 이 인증서를 확인할 수 없습니다.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" />의 &lt;abbr id="dnsDefinition"&gt;DNS 주소&lt;/abbr&gt;를 찾을 수 없습니다. 문제를 진단하는 중입니다.</translation>
<translation id="874846938927089722">사용 가능한 신용카드 및 선불카드</translation>
+<translation id="874918643257405732">현재 탭을 북마크에 추가</translation>
<translation id="8759274551635299824">만료된 카드입니다.</translation>
<translation id="8761567432415473239">Google 세이프 브라우징 결과 <ph name="SITE" />에서 최근 <ph name="BEGIN_LINK" />악성 프로그램이 발견<ph name="END_LINK" />되었습니다.</translation>
<translation id="8763927697961133303">USB 기기</translation>
@@ -1457,6 +1476,7 @@
<translation id="8938939909778640821">사용 가능한 신용카드 및 선불카드</translation>
<translation id="8943282376843390568">라임색</translation>
<translation id="8957210676456822347">캡티브 포털 승인</translation>
+<translation id="8962950042226115166">의심스러운 사이트</translation>
<translation id="8968766641738584599">카드 저장</translation>
<translation id="8971063699422889582">서버 인증서가 만료되었습니다.</translation>
<translation id="8975012916872825179">전화번호, 이메일 주소, 배송지 주소 등의 정보를 포함합니다.</translation>
@@ -1479,24 +1499,24 @@
<translation id="9035022520814077154">보안 오류</translation>
<translation id="9038649477754266430">빠른 페이지 로드를 위해 예상 검색어 서비스 사용</translation>
<translation id="9039213469156557790">또한 이 페이지에는 안전하지 않은 다른 리소스가 포함되어 있습니다. 이러한 리소스는 전송 중에 다른 사람이 볼 수 있으며 페이지의 작동을 변경하기 위해 공격자가 수정할 수 있습니다.</translation>
+<translation id="9044359186343685026">Touch ID 사용</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619"><ph name="DOMAIN" />에 접속하려 했지만 서버가 잘못된 인증서를 전달했습니다.</translation>
<translation id="9050666287014529139">암호</translation>
<translation id="9065203028668620118">수정</translation>
<translation id="9065745800631924235">검색기록에서 <ph name="TEXT" /> 검색</translation>
<translation id="9069693763241529744">확장 프로그램에서 차단함</translation>
-<translation id="9076283476770535406">성인용 콘텐츠가 포함되어 있을 수 있습니다.</translation>
<translation id="9076630408993835509">이 브라우저는 회사 또는 다른 조직에서 관리하지 않습니다. 이 기기의 활동은 Chrome 외부에서 관리될 수 있습니다. <ph name="BEGIN_LINK" />자세히 알아보기<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">자세한 정보 필요</translation>
<translation id="9080712759204168376">주문 요약</translation>
<translation id="9089260154716455634">제한 완화 시간 정책:</translation>
<translation id="9095388113577226029">다른 언어...</translation>
+<translation id="9098981495403789647">관리자가 브라우저에서 Chrome Enterprise Threat Protection을 사용 설정했습니다. Chrome Enterprise Threat Protection에서 내 데이터 중 일부에 액세스할 권한이 있습니다.</translation>
<translation id="9103872766612412690"><ph name="SITE" />에서는 사용자 정보를 보호하기 위해 일반적으로 암호화를 사용합니다. 이번에 Chromium에서 <ph name="SITE" />에 연결을 시도했을 때 웹사이트에서 비정상적이고 잘못된 사용자 인증 정보를 반환했습니다. 이는 공격자가 <ph name="SITE" />인 것처럼 가장하려고 하거나 Wi-Fi 로그인 화면이 연결을 방해했기 때문일 수 있습니다. 데이터 교환이 발생하기 전에 Chromium에서 연결을 중단했으므로 사용자 정보는 안전합니다.</translation>
<translation id="9106062320799175032">청구서 주소 추가</translation>
<translation id="9114524666733003316">카드 확인 중...</translation>
<translation id="9128870381267983090">네트워크에 연결</translation>
<translation id="9137013805542155359">원본 보기</translation>
-<translation id="9137248913990643158">이 앱을 사용하기 전에 Chrome을 시작하고 로그인하세요.</translation>
<translation id="9141013498910525015">주소 관리</translation>
<translation id="9148088599418889305">배송 방법 선택</translation>
<translation id="9148507642005240123">수정 실행 취소(&amp;U)</translation>
diff --git a/chromium/components/strings/components_strings_lt.xtb b/chromium/components/strings/components_strings_lt.xtb
index 540c1e9f56f..b893275eb18 100644
--- a/chromium/components/strings/components_strings_lt.xtb
+++ b/chromium/components/strings/components_strings_lt.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Kortelėje nurodytų vardo ir pavardės pridėjimas</translation>
<translation id="1089439967362294234">Slaptažodžio keitimas</translation>
+<translation id="1096545575934602868">Šiame lauke negali būti daugiau nei <ph name="MAX_ITEMS_LIMIT" /> įraš. Visi šį apribojimą viršijantys įrašai bus atmesti.</translation>
<translation id="109743633954054152">Tvarkyti slaptažodžius „Chrome“ nustatymuose</translation>
<translation id="1103523840287552314">Visada versti <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Jei pažymėta, „Chrome“ išsaugos kortelės kopiją įrenginyje, kad galėtumėte greičiau užpildyti formas.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Pasiekite <ph name="BEGIN_LINK" />talpykloje saugomą <ph name="URL" /> kopiją<ph name="END_LINK" /></translation>
<translation id="1156303062776767266">Peržiūrite vietinį arba bendrinamą failą</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> netikėtai nutraukė ryšį.</translation>
+<translation id="115926840831309955">Patikrinkite CVC ir bandykite dar kartą arba atnaujinkite galiojimo laiko pabaigos datą</translation>
<translation id="1161325031994447685">Iš naujo prisijungti prie „Wi-Fi“</translation>
<translation id="1165039591588034296">Klaida</translation>
<translation id="1175364870820465910">&amp;Spausdinti...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Programinė įranga jūsų kompiuteryje neleidžia „Chrome“ saugiai prisijungti prie žiniatinklio“ (tik „Windows“ kompiuteriuose)</translation>
<translation id="1294154142200295408">Komandos eilutės kintamieji</translation>
<translation id="129553762522093515">Neseniai uždarytas</translation>
+<translation id="1298536327547837046">Kenkėjiškų programų nuskaitymas</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Pabandykite išvalyti slapukus<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Nebenaudojamos funkcijos</translation>
<translation id="1320233736580025032">„Prc1“ (vokas)</translation>
<translation id="132301787627749051">Ieškoti iškarpinės vaizdo</translation>
<translation id="1323433172918577554">Rodyti daugiau</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">„Google“ skaičiuoklės</translation>
<translation id="1527263332363067270">Laukiama ryšio…</translation>
<translation id="1529521330346880926">10 x 15 (vokas)</translation>
+<translation id="1530707389502320859">Svetainė, kurioje ką tik bandėte apsilankyti, atrodo kaip suklastota svetainė. Užpuolėjai kartais sukuria svetainių kopijas ir atlieka nedidelius, sunkiai pastebimus URL pakeitimus.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Šiame puslapyje nurodyta:</translation>
<translation id="153384715582417236">Kol kas tiek</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokumentas per didelis, kad būtų galima komentuoti</translation>
-<translation id="1721312023322545264">Turite gauti <ph name="NAME" /> leidimą apsilankyti šioje svetainėje</translation>
<translation id="1721424275792716183">* Būtina užpildyti lauką</translation>
<translation id="1727741090716970331">Tinkamo kortelės numerio pridėjimas</translation>
<translation id="1728677426644403582">Peržiūrite tinklalapio šaltinį</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Svetainės, kuriose lankotės, ir jose praleidžiamas laikas</translation>
<translation id="1826516787628120939">Tikrinama</translation>
<translation id="1834321415901700177">Šioje svetainėje yra kenkėjiškų programų</translation>
+<translation id="1838374766361614909">Išvalyti paiešką</translation>
<translation id="1839551713262164453">Nepavyko patvirtinti politikos verčių (rasta klaidų)</translation>
<translation id="1842969606798536927">Mokėti</translation>
<translation id="1871208020102129563">Įgaliotasis serveris nustatytas naudoti fiksuotų įgaliotųjų serverių, o ne .pac scenarijaus URL.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Sutraukti sąrašą</translation>
<translation id="1898423065542865115">Filtravimas</translation>
<translation id="1914326953223720820">Išpakavimo paslauga</translation>
+<translation id="1915697529809968049">Naudoti „Touch ID“ vietoj CVC?</translation>
<translation id="1916770123977586577">Kad pritaikytumėte atnaujintus nustatymus šioje svetainėje, iš naujo įkelkite šį puslapį</translation>
<translation id="1919345977826869612">Skelbimai</translation>
<translation id="1919367280705858090">Gaukite pagalbos dėl konkretaus klaidos pranešimo</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> žymės</translation>
<translation id="1973335181906896915">Serijinio rengimo klaida</translation>
<translation id="1974060860693918893">Išplėstiniai</translation>
+<translation id="1974883374937189061">Padėkite tobulinti „Chrome“ saugą – atsiųskite <ph name="BEGIN_WHITEPAPER_LINK" />lankomų puslapių URL, ribotos sistemos informacijos ir puslapių turinio<ph name="END_WHITEPAPER_LINK" /> sistemai „Google“. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Programinės aparatinės įrangos versija</translation>
<translation id="1981206234434200693">Išvalyti „Chrome“ naršymo istorijos duomenis</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ir dar 1}one{ir dar #}few{ir dar #}many{ir dar #}other{ir dar #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Įveskite tinkamus galiojimo laiko pabaigos metus</translation>
<translation id="2212735316055980242">Politika nerasta</translation>
<translation id="2213606439339815911">Gaunami įrašai...</translation>
+<translation id="2215727959747642672">Failo redagavimas</translation>
<translation id="2218879909401188352">Šiuo metu užpuolikai svetainėje <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> gali įdiegti pavojingų programų, kurios gali būti žalingos įrenginiui, atlikti nepageidaujamų veiksmų, dėl kurių padidės mobiliojo telefono sąskaita, arba pavogti asmens informaciją. <ph name="BEGIN_LEARN_MORE_LINK" />Sužinokite daugiau<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Nėra interneto ryšio</translation>
<translation id="2230458221926704099">Išspręskite ryšio problemas naudodami <ph name="BEGIN_LINK" />diagnostikos programą<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Siųsti dabar</translation>
+<translation id="2248949050832152960">Naudoti „WebAuthn“</translation>
<translation id="225207911366869382">Pagal šią politiką ši vertė nepatvirtinta.</translation>
<translation id="2257315177824333709">Deja, šiuo metu negalima išsaugoti jūsų kortelės</translation>
<translation id="2262243747453050782">HTTP klaida</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Netinkamas paieškos URL.</translation>
<translation id="2482878487686419369">Pranešimai</translation>
<translation id="248348093745724435">Įrenginio politikos</translation>
-<translation id="2485387744899240041">Jūsų įrenginio ir naršyklės naudotojo vardai</translation>
<translation id="2491120439723279231">Serverio sertifikate yra klaidų.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON analizavimo įrankis</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Grįžti</translation>
<translation id="2503184589641749290">Tinkamos debeto ir išankstinio mokėjimo kortelės</translation>
<translation id="2505268675989099013">Apsaugoti paskyrą</translation>
+<translation id="2515335152965840738">NEPAISYTI</translation>
<translation id="2515629240566999685">Patikrinti signalo stiprumą savo srityje</translation>
<translation id="2523886232349826891">Išsaugota tik šiame įrenginyje</translation>
<translation id="2524461107774643265">Daugiau informacijos pridėjimas</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Pateikti</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nėra}=1{1 slaptažodis (skirta <ph name="DOMAIN_LIST" />)}=2{2 slaptažodžiai (skirta <ph name="DOMAIN_LIST" />)}one{# slaptažodis (skirta <ph name="DOMAIN_LIST" />)}few{# slaptažodžiai (skirta <ph name="DOMAIN_LIST" />)}many{# slaptažodžio (skirta <ph name="DOMAIN_LIST" />)}other{# slaptažodžių (skirta <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Uždarykite kitus skirtukus arba programas</translation>
-<translation id="267371737713284912">paspauskite <ph name="MODIFIER_KEY_DESCRIPTION" />, kad anuliuotumėte</translation>
<translation id="2674170444375937751">Ar tikrai norite pašalinti šiuos puslapius iš savo istorijos?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Išeiti</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Vertė neatitinka formato.</translation>
<translation id="2705137772291741111">Išsaugotos (talpykloje esančios) šios svetainės kopijos negalima skaityti.</translation>
<translation id="2709516037105925701">Automatinis pildymas</translation>
-<translation id="2712173769900027643">Prašyti leidimo</translation>
<translation id="2713444072780614174">Balta</translation>
<translation id="2720342946869265578">Netoliese</translation>
<translation id="2721148159707890343">Užklausa sėkminga</translation>
<translation id="2728127805433021124">Serverio sertifikatas pasirašytas naudojant nepatikimą parašo algoritmą.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Paleistas ryšio diagnostikos įrankis<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Įgalinus šias funkcijas gali būti prarasti naršymo duomenys arba
+ pažeistas jūsų privatumas ar sauga. Įgalintos funkcijos taikomos visiems
+ šios naršyklės naudotojams.</translation>
<translation id="2735043616039983645">Pateiktas daugiau nei vienas šios politikos šaltinis su nesuderinamomis vertėmis!</translation>
<translation id="2738330467931008676">Pasirinkti paėmimo adresą</translation>
<translation id="2740531572673183784">Gerai</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Ryšys atkurtas.</translation>
<translation id="2788784517760473862">Tinkamos kredito kortelės</translation>
<translation id="2792012897584536778">Šio įrenginio administratoriai nustatė saugos sertifikatus, leidžiančius jiems peržiūrėti svetainių, kuriose lankotės, turinį.</translation>
-<translation id="2794233252405721443">Svetainė užblokuota</translation>
<translation id="2799020568854403057">Pateiktoje svetainėje yra kenkėjiškų programų</translation>
<translation id="2799223571221894425">Paleisti iš naujo</translation>
<translation id="2803306138276472711">„Google“ saugaus naršymo sistema neseniai <ph name="BEGIN_LINK" />aptiko kenkėjiškų programų<ph name="END_LINK" /> svetainėje <ph name="SITE" />. Kartais svetainės, kurios paprastai yra saugios, užkrečiamos kenkėjiškomis programomis.</translation>
+<translation id="2815364696811431560">IŠEITI ŠI SVETAINĖS</translation>
<translation id="2824775600643448204">Adreso ir paieškos juosta</translation>
<translation id="2826760142808435982">Ryšys užšifruotas ir tapatybė nustatyta naudojant <ph name="CIPHER" />. <ph name="KX" /> naudojamas kaip pagrindinis mainų mechanizmas.</translation>
<translation id="2835170189407361413">Valyti formą</translation>
<translation id="2847118875340931228">Atidaryti inkognito langą</translation>
<translation id="2850739647070081192">„Invite“ (vokas)</translation>
-<translation id="2851634818064021665">Jums reikalingas leidimas, kad galėtumėte apsilankykite šioje svetainėje</translation>
<translation id="2856444702002559011">Užpuolikai gali bandyti pavogti jūsų informaciją iš <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (pvz., slaptažodžius, pranešimus ar kredito kortelių duomenis). <ph name="BEGIN_LEARN_MORE_LINK" />Sužinokite daugiau<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Išsaugoti kortelę?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Jei šis nustatymas įgalintas, „Chromium“ išsaugos kortelės kopiją įrenginyje, kad galėtumėte greičiau užpildyti formas.</translation>
<translation id="2985398929374701810">Įveskite tinkamą adresą</translation>
<translation id="2986368408720340940">Šis paėmimo metodas nepasiekiamas. Išbandykite kitą metodą.</translation>
+<translation id="2987034854559945715">Nėra jokių atitinkančių funkcijų</translation>
<translation id="2991174974383378012">Bendrinimas su svetainėmis</translation>
<translation id="2991571918955627853">Negalite dabar apsilankyti <ph name="SITE" />, nes svetainėje naudojama HSTS. Tinklo klaidos ir užpuolimai dažniausiai yra laikini, todėl šis puslapis vėliau tikriausiai veiks.</translation>
<translation id="3005723025932146533">Rodyti išsaugotą kopiją</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Netinkamas politikos tipas</translation>
<translation id="3037605927509011580">Oi!</translation>
<translation id="3041612393474885105">Sertifikato informacija</translation>
+<translation id="3057676462092457419">„DnsOverHttps“ režimas <ph name="SECURE_DNS_MODE_SECURE" /> kol kas nepalaikomas. Režimas nustatytas kaip <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (vokas)</translation>
<translation id="3061707000357573562">Pataisos paslauga</translation>
<translation id="3064966200440839136">Išjungiate inkognito režimą, kad galėtumėte sumokėti naudodami išorinę programą. Tęsti?</translation>
@@ -428,6 +439,7 @@
<translation id="3195213714973468956">„<ph name="PRINTER_NAME" />“ serveryje „<ph name="SERVER_NAME" />“</translation>
<translation id="320323717674993345">Atšaukti mokėjimą</translation>
<translation id="3207960819495026254">Pažymėta</translation>
+<translation id="3209034400446768650">Puslapyje galite būti apmokestinti</translation>
<translation id="3225919329040284222">Serveris pateikė sertifikatą, kuris neatitinka numatytų reikalavimų. Šie reikalavimai taikomi tam tikrose itin saugiose svetainėse, kad jūs būtumėte saugūs.</translation>
<translation id="3226128629678568754">Spustelėkite įkėlimo iš naujo mygtuką, kad iš naujo pateiktumėte duomenis, reikalingus puslapiui įkelti.</translation>
<translation id="3227137524299004712">Mikrofonas</translation>
@@ -435,7 +447,6 @@
<translation id="3229041911291329567">Įrenginio ir naršyklės versijos informacija</translation>
<translation id="323107829343500871">Įveskite „<ph name="CREDIT_CARD" />“ kortelės saugos kodą (CVC)</translation>
<translation id="3234666976984236645">Visada aptikti svarbų turinį šioje svetainėje</translation>
-<translation id="3254409185687681395">Įtraukti šį puslapį į žymes</translation>
<translation id="3270847123878663523">&amp;Anuliuoti pertvarkymą</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Ant kortelės pateikto vardo pridėjimas</translation>
@@ -445,7 +456,6 @@
<translation id="3320021301628644560">Atsiskaitymo adreso pridėjimas</translation>
<translation id="3324983252691184275">Tamsiai raudona</translation>
<translation id="3338095232262050444">Saugi</translation>
-<translation id="3345135638360864351">Nepavyko <ph name="NAME" /> išsiųsti jūsų prieigos prie šios svetainės užklausos. Bandykite dar kartą.</translation>
<translation id="3355823806454867987">Pakeisti įgaliotojo serverio nustatymus...</translation>
<translation id="3361596688432910856">„Chrome“ <ph name="BEGIN_EMPHASIS" />nesaugos<ph name="END_EMPHASIS" /> šios informacijos:
<ph name="BEGIN_LIST" />
@@ -479,18 +489,15 @@
<translation id="3462200631372590220">Slėpti išsamią informaciją</translation>
<translation id="3467763166455606212">Būtina nurodyti kortelės savininko vardą ir pavardę</translation>
<translation id="3468054117417088249">Šiuo metu atidarytas „<ph name="TAB_SWITCH_SUFFIX" />“. Paspauskite skirtuką, tada „Enter“, kad perjungtumėte į atidarytą skirtuką</translation>
-<translation id="3479539252931486093">Ar tai buvo netikėta? <ph name="BEGIN_LINK" />Praneškime mums apie tai<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ne dabar</translation>
<translation id="3484560055331845446">Galite prarasti prieigą prie „Google“ paskyros. „Chrome“ rekomenduoja pakeisti slaptažodį dabar. Bus prašoma prisijungti.</translation>
<translation id="3495081129428749620">Rasti puslapyje
„<ph name="PAGE_TITLE" />“</translation>
-<translation id="3498215018399854026">Šiuo metu nepavyko susisiekti su jūsų tėvu. Bandykite dar kartą.</translation>
<translation id="3512163584740124171">Šios politikos nepaisoma, nes kitos politikos toje pačioje politikos grupėje prioritetas yra didesnis.</translation>
<translation id="3528171143076753409">Serverio sertifikatas nepatikimas.</translation>
<translation id="3528485271872257980">Tamsiai ruda</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Mažiausiai 1 elementas sinchronizuotuose įrenginiuose}=1{1 elementas (ir daugiau sinchronizuotuose įrenginiuose)}one{# elementas (ir daugiau sinchronizuotuose įrenginiuose)}few{# elementai (ir daugiau sinchronizuotuose įrenginiuose)}many{# elemento (ir daugiau sinchronizuotuose įrenginiuose)}other{# elementų (ir daugiau sinchronizuotuose įrenginiuose)}}</translation>
<translation id="3539171420378717834">Išsaugoti kortelės kopiją įrenginyje</translation>
-<translation id="3556433843310711081">Jūsų valdytojas gali atblokuoti ją už jus</translation>
<translation id="3566021033012934673">Jūsų ryšys nėra privatus</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Svetainėje <ph name="SITE" /> įterptame puslapyje nurodyta:</translation>
@@ -518,6 +525,7 @@
<translation id="3678529606614285348">Atidarykite puslapį naujame inkognito lange („Ctrl“ – „Shift“ – N)</translation>
<translation id="3679803492151881375">Strigčių ataskaita užfiksuota <ph name="CRASH_TIME" />, įkelta <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Sertifikato informacija</translation>
+<translation id="3701427423622901115">Nustatymas iš naujo patvirtintas.</translation>
<translation id="3704162925118123524">Naudojant šį tinklą gali būti prašoma apsilankyti prisijungimo puslapyje.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Įkeliama...</translation>
@@ -534,6 +542,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> užpuolikai gali bandyti apgaule priversti jus atlikti pavojingus veiksmus, pvz., įdiegti programinę įrangą ar atskleisti asmens informaciją (pvz., slaptažodžius, telefonų numerius ar kredito kortelių duomenis). <ph name="BEGIN_LEARN_MORE_LINK" />Sužinokite daugiau<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Vertimas nepavyko dėl serverio klaidos.</translation>
<translation id="3759461132968374835">Nėra strigčių, apie kurias buvo neseniai pranešta. Strigtys, įvykusios tuo metu, kai strigčių ataskaitų teikimas buvo išjungtas, čia rodomos nebus.</translation>
+<translation id="3760561303380396507">Naudoti „Windows Hello“ vietoj CVC?</translation>
<translation id="3761718714832595332">Slėpti būseną</translation>
<translation id="3765032636089507299">Saugaus naršymo puslapis kuriamas.</translation>
<translation id="3778403066972421603">Ar norite išsaugoti šią kortelę „Google“ paskyroje ir šiame įrenginyje?</translation>
@@ -543,6 +552,7 @@
<translation id="3789155188480882154">Dydis: 16</translation>
<translation id="3797522431967816232">„Prc3“ (vokas)</translation>
<translation id="3807873520724684969">Žalingas turinys užblokuotas.</translation>
+<translation id="3808375843007691220">Įspėjimas: eksperimentinės funkcijos!</translation>
<translation id="3810973564298564668">Valdyti</translation>
<translation id="382518646247711829">Jei naudojate tarpinį serverį…</translation>
<translation id="3828924085048779000">Neleidžiama naudoti tuščios slaptafrazės.</translation>
@@ -551,11 +561,11 @@
<translation id="3858027520442213535">Atnaujinti datą ir laiką</translation>
<translation id="3884278016824448484">Nesuderinamas įrenginio identifikatorius</translation>
<translation id="3885155851504623709">Parapija</translation>
-<translation id="3886446263141354045">Jūsų užklausa pasiekti šią svetainę išsiųsta <ph name="NAME" />.</translation>
<translation id="3890664840433101773">Pridėti el. pašto adresą</translation>
<translation id="3901925938762663762">Kortelė nebegalioja</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Naudoti „WebAuthn“ vietoj CVC?</translation>
<translation id="3946209740501886391">Visada klausti šioje svetainėje</translation>
<translation id="3949571496842715403">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikate nenurodomi temos alternatyvūs pavadinimai. Tai gali būti dėl netinkamos konfigūracijos arba dėl ryšį pertraukusio užgrobėjo.</translation>
<translation id="3949601375789751990">Naršymo istorija rodoma čia</translation>
@@ -566,11 +576,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nėra}=1{Iš 1 svetainės }one{Iš # svetainės }few{Iš # svetainių }many{Iš # svetainės }other{Iš # svetainių }}</translation>
<translation id="397105322502079400">Skaičiuojama...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> užblokuota.</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> jūsų įrenginyje įgalino „Chrome Enterprise“ apsaugą nuo grėsmių. „Chrome Enterprise“ apsaugos nuo grėsmių funkcija gali pasiekti kai kuriuos jūsų duomenis.</translation>
<translation id="3987940399970879459">Mažiau nei 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 tinklalapis netoliese}one{# tinklalapis netoliese}few{# tinklalapiai netoliese}many{# tinklalapio netoliese}other{# tinklalapių netoliese}}</translation>
<translation id="4030383055268325496">&amp;Anuliuoti pridėjimą</translation>
<translation id="4032320456957708163">Jūsų naršyklę tvarko <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Jūsų atidaryta nuoroda veda į svetainę, kurioje paprastai nesilankote. Gali būti bandoma jus suklaidinti.</translation>
<translation id="4058922952496707368">Raktas „<ph name="SUBKEY" />“: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (vokas)</translation>
<translation id="4067947977115446013">Tinkamo adreso pridėjimas</translation>
@@ -583,6 +593,7 @@
<translation id="4103249731201008433">Netinkamas įrenginio serijos numeris</translation>
<translation id="410351446219883937">Automatinis paleidimas</translation>
<translation id="4103763322291513355">Apsilankykite &lt;strong&gt;chrome://policy&lt;/strong&gt;, kad peržiūrėtumėte į juodąjį sąrašą įtrauktų URL sąrašą ir kitą politiką, kurią priverstinai paleido sistemos administratorius.</translation>
+<translation id="4108231218301530806">Kitą kartą šią kortelę reikės patvirtinti naudojant kontrolinį kodą.</translation>
<translation id="4110652170750985508">Mokėjimo peržiūra</translation>
<translation id="4112140312785995938">Prasukti atgal</translation>
<translation id="4116663294526079822">Visada leisti šioje svetainėje</translation>
@@ -597,6 +608,7 @@
<translation id="4171400957073367226">Netinkamas patvirtinimo parašas</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Dar <ph name="ITEM_COUNT" /> elementas}one{Dar <ph name="ITEM_COUNT" /> elementas}few{Dar <ph name="ITEM_COUNT" /> elementai}many{Dar <ph name="ITEM_COUNT" /> elemento}other{Dar <ph name="ITEM_COUNT" /> elementų}}</translation>
+<translation id="4176463684765177261">Išjungta</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Kad kitą kartą galėtumėte greičiau atlikti mokėjimą, pridėkite kortelę ir atsiskaitymo adresą „Google“ paskyroje.</translation>
<translation id="4196861286325780578">&amp;Perkelti dar kartą</translation>
@@ -633,6 +645,7 @@
<translation id="4277028893293644418">Iš naujo nustatyti slaptažodį</translation>
<translation id="4279811152705618813">Jūsų „<ph name="DEVICE_TYPE" />“ tvarko <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ši kortelė išsaugota jūsų „Google“ paskyroje}one{Šios kortelės išsaugotos jūsų „Google“ paskyroje}few{Šios kortelės išsaugotos jūsų „Google“ paskyroje}many{Šios kortelės išsaugotos jūsų „Google“ paskyroje}other{Šios kortelės išsaugotos jūsų „Google“ paskyroje}}</translation>
+<translation id="428847186335018806">Nuskaitykite failus, kuriuos atsisiunčiate ar įkeliate į „Chrome“.</translation>
<translation id="42981349822642051">Išskleisti</translation>
<translation id="4302965934281694568">„Chou3“ (vokas)</translation>
<translation id="4305817255990598646">Perjungti</translation>
@@ -662,7 +675,6 @@
<translation id="4435702339979719576">Atvirukas</translation>
<translation id="443673843213245140">Įgaliotojo serverio naudojimas neleidžiamas, bet nurodyta aiški įgaliotojo serverio konfigūracija.</translation>
<translation id="445100540951337728">Tinkamos debeto kortelės</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> įtartina veikla</translation>
<translation id="4466881336512663640">Formos pakeitimai bus prarasti. Ar tikrai norite tęsti?</translation>
<translation id="4477350412780666475">Kitas takelis</translation>
<translation id="4482953324121162758">Ši svetainė nebus verčiama.</translation>
@@ -689,6 +701,7 @@
<translation id="4594403342090139922">&amp;Anuliuoti ištrynimą</translation>
<translation id="4597348597567598915">Dydis: 8</translation>
<translation id="4600854749408232102">C6 / C5 (vokas)</translation>
+<translation id="464342062220857295">Paieškos funkcijos</translation>
<translation id="4646534391647090355">Eiti dabar</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikate yra klaidų. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užgrobėjo.</translation>
@@ -697,7 +710,6 @@
<translation id="4691835149146451662">„Architecture-A“ (vokas)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Ryšys nutrauktas</translation>
-<translation id="471880041731876836">Neturite leidimo, kad galėtumėte apsilankykite šioje svetainėje</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Paleistas įrankis „Windows Network Diagnostics“<ph name="END_LINK" />.</translation>
<translation id="4726672564094551039">Iš naujo įkelti politiką</translation>
<translation id="4728558894243024398">Platforma</translation>
@@ -725,7 +737,6 @@
<translation id="4816492930507672669">Pritaikyti pagal puslapį</translation>
<translation id="4850886885716139402">Žiūrėti</translation>
<translation id="4854362297993841467">Šis pristatymo metodas nepasiekiamas. Išbandykite kitą metodą.</translation>
-<translation id="4858792381671956233">Paprašėte tėvų leidimo apsilankyti šiame puslapyje</translation>
<translation id="4864052566555297930">Saugumo patarimas:</translation>
<translation id="4876188919622883022">Supaprastintas rodinys</translation>
<translation id="4876305945144899064">Nėra naudotojo vardo</translation>
@@ -749,7 +760,9 @@
<translation id="4974590756084640048">Iš naujo įgalinti įspėjimus</translation>
<translation id="4984339528288761049">„Prc5“ (vokas)</translation>
<translation id="4989163558385430922">Žr. viską</translation>
+<translation id="4989542687859782284">Nepasiekiama</translation>
<translation id="4989809363548539747">Šis papildinys nepalaikomas</translation>
+<translation id="4995216769782533993">Patvirtinkite saugos kodą, kad išsami kortelės informacija būtų bendrinama su šia svetaine</translation>
<translation id="5002932099480077015">Jei šis nustatymas įgalintas, „Chrome“ saugos kortelės kopiją šiame įrenginyje, kad būtų galima greičiau užpildyti formas.</translation>
<translation id="5015510746216210676">Įrenginio pavadinimas:</translation>
<translation id="5017554619425969104">Nukopijuotas tekstas</translation>
@@ -778,6 +791,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bitų)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Kortelės patvirtinimas</translation>
<translation id="5135404736266831032">Tvarkyti adresus...</translation>
<translation id="5138227688689900538">Rodyti mažiau</translation>
<translation id="5141240743006678641">Šifruoti sinchronizuotus slaptažodžius naudojant „Google“ prisijungimo duomenis</translation>
@@ -804,6 +818,7 @@
<translation id="5251803541071282808">Debesis</translation>
<translation id="5252000469029418751">C7 (vokas)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Visoje sistemoje taikomas funkcijas gali nustatyti tik savininkas: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Įspėjimas: ši politika nebuvo sujungta, kaip nurodyta politikoje „PolicyDictionaryMultipleSourceMergeList“, nes ji nėra žodyno politikos nuostatų, kurias galima sujungti, dalis.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Baigti</translation>
@@ -827,7 +842,6 @@
<translation id="536296301121032821">Išsaugant politikos nustatymus įvyko klaida</translation>
<translation id="5371425731340848620">Atnaujinkite kortelę</translation>
<translation id="5377026284221673050">„Laikrodis atsilieka“, „Laikrodis skuba“ arba „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;“</translation>
-<translation id="5377179979757081683">Šiame puslapyje gali būti bandoma jus apgauti, pavogti asmens informacijos ar pažeisti įrenginį. Būkite atidūs įvesdami asmens informaciją ar atidarydami atsisiųstus failus.</translation>
<translation id="5384855140246857529">Norėdami naudoti korteles visuose įrenginiuose, prisijunkite ir įjunkite sinchronizavimą.</translation>
<translation id="5386426401304769735">Šios svetainės sertifikatų grandinėje yra sertifikatas, pasirašytas naudojant SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -841,6 +855,8 @@
<translation id="5457113250005438886">Netinkama</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}many{<ph name="CONTACT_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Redaguoti dar kartą</translation>
+<translation id="5473728911100096288">Įgalinus šias funkcijas bus pasiekiamos nebenaudojamos funkcijos,
+ kurių nebebus būsimose versijose.</translation>
<translation id="5478437291406423475">B6 / C4 (vokas)</translation>
<translation id="5481076368049295676">Šiuo turiniu gali būti bandoma priversti jus įrenginyje įdiegti pavojingą programinę įrangą, kuri vagia arba ištrina jūsų informaciją. <ph name="BEGIN_LINK" />Rodyti vis tiek<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Tinkamo adreso pridėjimas</translation>
@@ -864,7 +880,6 @@
<translation id="5570825185877910964">Apsaugoti paskyrą</translation>
<translation id="5571083550517324815">Negalima paimti šiuo adresu. Pasirinkite kitą adresą.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{naudojama: 1}one{naudojama: #}few{naudojama: #}many{naudojama: #}other{naudojama: #}})</translation>
-<translation id="5572851009514199876">Pirmiausia prisijunkite prie „Chrome“, kad „Chrome“ galėtų patikrinti, ar jums leidžiama pasiekti šią svetainę.</translation>
<translation id="5580958916614886209">Patikrinkite galiojimo pabaigos mėnesį ir bandykite dar kartą</translation>
<translation id="5586446728396275693">Nėra išsaugotų adresų</translation>
<translation id="5595485650161345191">Adreso redagavimas</translation>
@@ -872,6 +887,7 @@
<translation id="560412284261940334">Tvarkymas nepalaikomas</translation>
<translation id="5605670050355397069">Buhalterinis</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Svetainė gali būti suklastota ar apgavikiška. „Chrome“ rekomenduoja dabar iš jos išeiti.</translation>
<translation id="5610142619324316209">Patikrinti ryšį</translation>
<translation id="5610807607761827392">Korteles ir adresus galite tvarkyti skiltyje <ph name="BEGIN_LINK" />Nustatymai<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> buvote per daug kartų peradresuoti.</translation>
@@ -895,11 +911,11 @@
<translation id="5720705177508910913">Dabartinis naudotojas</translation>
<translation id="5728056243719941842">C5 (vokas)</translation>
<translation id="5730040223043577876">„Chrome“ rekomenduoja iš naujo nustatyti slaptažodį, jei naudojate jį kitose svetainėse.</translation>
-<translation id="5732392974455271431">Jūsų tėvai gali atblokuoti ją už jus</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Išsaugokite kortelę „Google“ paskyroje}one{Išsaugokite korteles „Google“ paskyroje}few{Išsaugokite korteles „Google“ paskyroje}many{Išsaugokite korteles „Google“ paskyroje}other{Išsaugokite korteles „Google“ paskyroje}}</translation>
<translation id="5763042198335101085">Įveskite galiojantį el. pašto adresą</translation>
<translation id="5765072501007116331">Jei norite peržiūrėti pristatymo metodus ir reikalavimus, pasirinkite adresą.</translation>
<translation id="5778550464785688721">MIDI įrenginių visateisis valdymas</translation>
+<translation id="5781136890105823427">Eksperimentas įgalintas</translation>
<translation id="578305955206182703">Gintaro spalva</translation>
<translation id="57838592816432529">Nutildyti</translation>
<translation id="5784606427469807560">Patvirtinant kortelę kilo problema. Patikrinkite interneto ryšį ir bandykite dar kartą.</translation>
@@ -916,13 +932,16 @@
<translation id="5860033963881614850">Išjungta</translation>
<translation id="5863847714970149516">Toliau pateiktame puslapyje gali būti bandoma jus apmokestinti</translation>
<translation id="5866257070973731571">Telefono numerio pridėjimas</translation>
+<translation id="5866898949289125849">Peržiūrite kūrėjo įrankių puslapį</translation>
<translation id="5869405914158311789">Nepavyksta pasiekti šios svetainės</translation>
<translation id="5869522115854928033">Išsaugoti slaptažodžiai</translation>
<translation id="5887400589839399685">Kortelė išsaugota</translation>
<translation id="5893752035575986141">Kredito kortelės tinkamos.</translation>
+<translation id="5895138241574237353">Paleisti iš naujo</translation>
<translation id="5901630391730855834">Geltona</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sinchronizuota)</translation>
<translation id="5916664084637901428">Įjungta</translation>
+<translation id="59174027418879706">Įjungta</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Išsaugoti kortelę „Google“ paskyroje?</translation>
<translation id="5922853866070715753">Beveik atlikta</translation>
@@ -956,6 +975,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Naudojate korteles visuose įrenginiuose?</translation>
<translation id="6059925163896151826">USB įrenginiai</translation>
+<translation id="6060009363608157444">Netinkamas „DnsOverHttps“ režimas.</translation>
<translation id="6080696365213338172">Pasiekėte turinį naudodami administratoriaus pateiktą sertifikatą. Duomenys, kuriuos pateikiate <ph name="DOMAIN" />, gali būti perimti administratoriaus.</translation>
<translation id="6094273045989040137">Komentuoti</translation>
<translation id="610911394827799129">„Google“ paskyroje gali būti kito tipo naršymo istorijos, kuri pasiekiama adresu <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1004,13 +1024,12 @@
<translation id="6404511346730675251">Redaguoti žymę</translation>
<translation id="6406765186087300643">C0 (vokas)</translation>
<translation id="6410264514553301377">įveskite „<ph name="CREDIT_CARD" />“ galiojimo pabaigos datą ir kortelės saugos kodą (CVC)</translation>
-<translation id="6414888972213066896">Paprašėte vieno iš tėvų leidimo apsilankyti šiame puslapyje</translation>
<translation id="6415778972515849510">„Chromium“ gali padėti apsaugoti „Google“ paskyrą ir pakeisti slaptažodį.</translation>
-<translation id="6417515091412812850">Nepavyksta patikrinti, ar sertifikatas buvo panaikintas.</translation>
<translation id="6431585503458005759">Nesaugoti</translation>
<translation id="6433490469411711332">Kontaktinės informacijos redagavimas</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> atsisakė prisijungti.</translation>
<translation id="6434309073475700221">Atmesti</translation>
+<translation id="6435221585574090192">Bendrinkite duomenis apie saugos įvykius, pažymėtus „Chrome Enterprise“ apsaugos nuo grėsmių funkcijos, su administratoriumi. Tai gali būti puslapių URL, failų pavadinimai ir failų metaduomenys, įrenginio naudotojo vardas ir „Chrome“ naudotojo vardas.</translation>
<translation id="6440503408713884761">Nepaisoma</translation>
<translation id="6446163441502663861">„Kahu“ (vokas)</translation>
<translation id="6446608382365791566">Daugiau informacijos pridėjimas</translation>
@@ -1019,20 +1038,19 @@
<translation id="6465306955648956876">Tvarkyti slaptažodžius...</translation>
<translation id="647261751007945333">Įrenginio politika</translation>
<translation id="6476284679642588870">Tvarkyti mokėjimo metodus</translation>
-<translation id="6477321094435799029">„Chrome“ šiame puslapyje aptiko neįprastą kodą ir jį užblokavo, kad apsaugotų asmens informaciją (pvz., slaptažodžius, telefonų numerius ir kredito korteles).</translation>
<translation id="6489534406876378309">Pradėti įkelti strigtis</translation>
<translation id="6499038740797743453">Iš naujo nustatyti slaptažodį?</translation>
<translation id="6507833130742554667">Kredito ir debeto kortelės tinkamos.</translation>
<translation id="650855688985305916">Taip, saugoti</translation>
<translation id="6508722015517270189">Iš naujo paleiskite „Chrome“</translation>
<translation id="6517596291481585650">Įspėjimas: ši politika nebuvo sujungta kaip sąrašas, kaip nurodyta politikoje, nes ji nėra sąrašas.</translation>
+<translation id="6518133107902771759">Patvirtinti</translation>
<translation id="6521745193039995384">Neaktyvi</translation>
<translation id="6529602333819889595">&amp;Ištrinti dar kartą</translation>
<translation id="6534179046333460208">Fizinio žiniatinklio pasiūlymai</translation>
<translation id="6545864417968258051">„Bluetooth“ nuskaitymas</translation>
<translation id="6554795675067793129">Jūsų paskyrą tvarko <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Grąžinti</translation>
-<translation id="6563469144985748109">Jūsų valdytojas dar jos nepatvirtino</translation>
<translation id="6569060085658103619">Peržiūrite plėtinio puslapį</translation>
<translation id="6578796323535178455">C2 (vokas)</translation>
<translation id="6579990219486187401">Šviesiai rausva spalva</translation>
@@ -1050,11 +1068,13 @@
<translation id="6643016212128521049">Išvalyti</translation>
<translation id="6644283850729428850">Ši politika nepatvirtinta.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nėra}=1{Iš 1 svetainės (nebūsite atjungti nuo „Google“ paskyros)}one{Iš # svetainės (nebūsite atjungti nuo „Google“ paskyros)}few{Iš # svetainių (nebūsite atjungti nuo „Google“ paskyros)}many{Iš # svetainės (nebūsite atjungti nuo „Google“ paskyros)}other{Iš # svetainių (nebūsite atjungti nuo „Google“ paskyros)}}</translation>
+<translation id="6652101503459149953">Naudoti „Windows Hello“</translation>
<translation id="6657585470893396449">Slaptažodis</translation>
<translation id="6670613747977017428">Grįžti prie saugumo.</translation>
<translation id="6671697161687535275">Pašalinti formos pasiūlymą iš „Chromium“?</translation>
<translation id="6685834062052613830">Atsijunkite ir užbaikite sąranką</translation>
<translation id="6689271823431384964">„Chrome“ siūlo išsaugoti korteles „Google“ paskyroje, nes esate prisijungę. Šią elgseną galite pakeisti nustatymuose. Kortelės savininko vardas gaunamas iš jūsų paskyros.</translation>
+<translation id="6707256370811247129">Nuskaitykite talpyklos ir failų, kuriuos atsisiunčiate ar įkeliate į „Chrome“, turinį.</translation>
<translation id="6710213216561001401">Ankstesnis</translation>
<translation id="6710594484020273272">&lt;Įveskite paieškos terminą&gt;</translation>
<translation id="671076103358959139">Registracijos prieigos raktas:</translation>
@@ -1062,10 +1082,10 @@
<translation id="6738516213925468394"><ph name="TIME" /> duomenys buvo užšifruoti naudojant <ph name="BEGIN_LINK" />sinchronizavimo slaptafrazę<ph name="END_LINK" />. Įveskite ją, kad pradėtumėte sinchronizuoti.</translation>
<translation id="674375294223700098">Nežinoma serverio sertifikato klaida.</translation>
<translation id="6744009308914054259">Laukdami ryšio galite apsilankyti skiltyje „Atsisiuntimai“ ir perskaityti neprisijungus pasiekiamus straipsnius.</translation>
+<translation id="6747611005629681221">Perspėjimas: nebenaudojamos funkcijos!</translation>
<translation id="6753269504797312559">Politikos vertė</translation>
<translation id="6757797048963528358">Įjungta įrenginio miego būsena.</translation>
<translation id="6768213884286397650">„Hagaki“ (atvirukas)</translation>
-<translation id="6778737459546443941">Jūsų tėtis ar mama dar jos nepatvirtino</translation>
<translation id="67862343314499040">Violetinė</translation>
<translation id="6786747875388722282">Plėtiniai</translation>
<translation id="6790428901817661496">Žaisti</translation>
@@ -1073,6 +1093,7 @@
<translation id="681021252041861472">Būtinas laukas</translation>
<translation id="6810899417690483278">Tinkinimo ID</translation>
<translation id="6825578344716086703">Bandėte pasiekti <ph name="DOMAIN" />, bet serveris pateikė sertifikatą, kuris pasirašytas naudojant nesudėtingą parašo algoritmą (pvz., SHA-1). Tai reiškia, kad serverio pateikti saugos prisijungimo duomenys galėjo būti suklastoti ir serveris gali būti ne tas, kurio tikėjotės (gali būti, kad bendraujate su užpuoliku).</translation>
+<translation id="6826370046007623921">Duomenų praradimo prevencija</translation>
<translation id="6831043979455480757">Vertėjas</translation>
<translation id="6839929833149231406">Sritis</translation>
<translation id="6852204201400771460">Įkelti programą iš naujo?</translation>
@@ -1085,7 +1106,6 @@
<translation id="6891596781022320156">Politikos lygis nepalaikomas.</translation>
<translation id="6895330447102777224">Kortelė patvirtinta</translation>
<translation id="6897140037006041989">Naudotojo atstovas</translation>
-<translation id="6903319715792422884">Padėkite tobulinti Saugų naršymą siųsdami tam tikrą <ph name="BEGIN_WHITEPAPER_LINK" />sistemos informaciją ir puslapių turinį<ph name="END_WHITEPAPER_LINK" /> „Google“. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Naudotojas:</translation>
<translation id="6934672428414710184">Šis vardas yra iš jūsų „Google“ paskyros</translation>
<translation id="6944692733090228304">Įvedėte slaptažodį svetainėje, kurios netvarko organizacija <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Kad apsaugotumėte paskyrą, nenaudokite to paties slaptažodžio kitose programose ir svetainėse.</translation>
@@ -1130,6 +1150,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}many{<ph name="PAYMENT_METHOD_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Levandų spalva</translation>
<translation id="717330890047184534">„Gaia“ ID:</translation>
+<translation id="7174545416324379297">Sujungta</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}many{<ph name="SHIPPING_OPTION_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ir dar <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Serveris, į kurį esate nukreipiami (<ph name="ORIGIN" />), pateikė užklausą
taikyti saugos politiką visoms jam teikiamoms užklausoms. Bet užuot
@@ -1167,6 +1188,7 @@ Papildoma išsami informacija:
<translation id="7320336641823683070">Su ryšiu susijusi pagalba</translation>
<translation id="733354035281974745">Įrenginio vietos paskyros nepaisymas</translation>
<translation id="7334320624316649418">&amp;Pertvarkyti dar kartą</translation>
+<translation id="7337706099755338005">Nepasiekiama jūsų platformoje.</translation>
<translation id="733923710415886693">Serverio sertifikatas nebuvo atskleistas taikant sertifikato skaidrumą.</translation>
<translation id="734600844861828519">11 x 15</translation>
<translation id="7346048084945669753">Susietas:</translation>
@@ -1198,7 +1220,6 @@ Papildoma išsami informacija:
<translation id="7440140511386898319">Naršymas neprisijungus</translation>
<translation id="7441627299479586546">Netinkamas politikos objektas</translation>
<translation id="7442725080345379071">Šviesiai oranžinė</translation>
-<translation id="7444046173054089907">Ši svetainė užblokuota</translation>
<translation id="7445762425076701745">Nepavyksta visiškai patvirtinti serverio, prie kurio esate prisijungę, tapatybės. Prie serverio esate prisijungę naudodami tik tinklui galiojantį vardą, kurio nuosavybės teisių išorinė sertifikatą išduodanti institucija negali patvirtinti. Nors kai kurios sertifikatus išduodančios institucijos vis tiek išduos sertifikatus pagal šiuos vardus, niekaip nebus galima užtikrinti, kad būsite prisijungę prie numatytos svetainės, o ne prie užpuolėjo.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Sužinokite daugiau<ph name="END_LINK" /> apie šią problemą.</translation>
<translation id="7455133967321480974">Naudoti visuotinį numatytąjį nustatymą (blokuoti)</translation>
@@ -1220,9 +1241,9 @@ Papildoma išsami informacija:
<translation id="7538364083937897561">A2 (vokas)</translation>
<translation id="7542403920425041731">Kai patvirtinsite, išsami kortelės informacija bus bendrinama su šia svetaine.</translation>
<translation id="7542995811387359312">Automatinis kredito kortelės informacijos pildymas neleidžiamas, nes šiai formai nenaudojamas saugus ryšys.</translation>
-<translation id="7543525346216957623">Paprašykite vieno iš tėvų</translation>
<translation id="7548892272833184391">Ryšio klaidų taisymas</translation>
<translation id="7549584377607005141">Jei norite, kad šis tinklalapis būtų tinkamai pateikiamas, reikalingi anksčiau įvesti duomenys. Galite nusiųsti šiuos duomenis iš naujo, bet taip pakartosite visus anksčiau šiame puslapyje įvykdytus veiksmus.</translation>
+<translation id="7550637293666041147">Įrenginio naudotojo vardas ir „Chrome“ naudotojo vardas</translation>
<translation id="7552846755917812628">Išbandykite toliau pateiktus patarimus.</translation>
<translation id="7554791636758816595">Naujas skirtukas</translation>
<translation id="7564049878696755256">Galite prarasti galimybę pasiekti „<ph name="ORG_NAME" />“ paskyrą arba gali būti pavogta tapatybė. „Chrome“ rekomenduoja pakeisti slaptažodį dabar.</translation>
@@ -1237,6 +1258,7 @@ Papildoma išsami informacija:
<translation id="7610193165460212391">Vertė nepatenka į diapazoną <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Galioja iki: <ph name="EXPIRATION_YEAR" />-<ph name="EXPIRATION_MONTH" /></translation>
<translation id="7615602087246926389">Jau turite duomenų, kurie šifruojami naudojant kitos versijos „Google“ paskyros slaptažodį. Įveskite juos toliau.</translation>
+<translation id="7625784245512586808">„Chrome Enterprise“ apsauga nuo grėsmių</translation>
<translation id="7633909222644580952">Našumo duomenys ir strigčių ataskaitos</translation>
<translation id="7637571805876720304">Pašalinti kredito kortelės informaciją iš „Chromium“?</translation>
<translation id="7638605456503525968">Nuoseklieji prievadai</translation>
@@ -1249,7 +1271,6 @@ Papildoma išsami informacija:
<translation id="7668654391829183341">Nežinomas įrenginys</translation>
<translation id="7669271284792375604">Šios svetainės užgrobėjai gali bandyti apgaule priversti jus įdiegti naršymo funkcijas trikdančių programų (pvz., pakeitę pagrindinį puslapį ar rodydami papildomų skelbimų svetainėse, kuriose lankotės).</translation>
<translation id="7676643023259824263">Ieškoti iškarpinės teksto „<ph name="TEXT" />“</translation>
-<translation id="7679176406634891508">Platforma ir debesis</translation>
<translation id="7681101578153515023">Keisti paieškos variklį</translation>
<translation id="7682287625158474539">Pristatymas</translation>
<translation id="7687186412095877299">Užpildomos mokėjimo formos naudojant išsaugotus mokėjimo metodus</translation>
@@ -1264,7 +1285,6 @@ Papildoma išsami informacija:
<translation id="7723047071702270851">Kortelės redagavimas</translation>
<translation id="774634243536837715">Pavojingas turinys užblokuotas.</translation>
<translation id="7752995774971033316">Netvarkoma</translation>
-<translation id="7755287808199759310">Jūsų tėtis ar mama gali ją atblokuoti už jus</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Gali būti, kad užkarda arba antivirusinė programinė įranga užblokavo ryšį.</translation>
<translation id="7759163816903619567">Pateikties domenas:</translation>
@@ -1308,7 +1328,6 @@ Papildoma išsami informacija:
<translation id="8004582292198964060">Naršyklė</translation>
<translation id="8009225694047762179">Tvarkyti slaptažodžius</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ši kortelė ir jos atsiskaitymo adresas bus išsaugoti. Ją galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}one{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}few{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}many{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}other{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Šiuo metu nepavyko susisiekti su jūsų tėvais. Bandykite dar kartą.</translation>
<translation id="8025119109950072390">Šios svetainės užpuolėjai gali bandyti apgaulingai priversti atlikti pavojingus veiksmus, pvz., įdiegti programinę įrangą ar atskleisti asmens informaciją (pvz., slaptažodžius, telefonų numerius ar kredito kortelių informaciją).</translation>
<translation id="8034522405403831421">Šis puslapis yra <ph name="SOURCE_LANGUAGE" /> k. Išversti į <ph name="TARGET_LANGUAGE" /> k.?</translation>
<translation id="8035152190676905274">Rašiklis</translation>
@@ -1319,6 +1338,7 @@ Papildoma išsami informacija:
<translation id="8041940743680923270">Naudoti visuotinį numatytąjį nustatymą (klausti)</translation>
<translation id="8042918947222776840">Pasirinkti paėmimo metodą</translation>
<translation id="8057711352706143257">„<ph name="SOFTWARE_NAME" />“ netinkamai sukonfigūruota. Pašalinus „<ph name="SOFTWARE_NAME" />“ paprastai pavyksta išspręsti šią problemą. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Nuo dabar nebereikės įvesti kortelės saugos kodo</translation>
<translation id="8066955247577885446">Deja, kažkas nepavyko.</translation>
<translation id="8074253406171541171">10 x 13 (vokas)</translation>
<translation id="8078141288243656252">Negalima rašyti komentarų, kai pasukta</translation>
@@ -1349,6 +1369,7 @@ Papildoma išsami informacija:
<translation id="8211406090763984747">Ryšys saugus</translation>
<translation id="8218327578424803826">Priskirta vieta:</translation>
<translation id="8220146938470311105">C7 / C6 (vokas)</translation>
+<translation id="8220639454292072926">Įmonės ataskaitų teikimas</translation>
<translation id="8225771182978767009">Šį kompiuterį nustatęs asmuo pasirinko blokuoti šią svetainę.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Atidarykite puslapį naujame inkognito skirtuke</translation>
@@ -1403,24 +1424,24 @@ Papildoma išsami informacija:
<translation id="8508648098325802031">Paieškos piktograma</translation>
<translation id="8522552481199248698">„Chrome“ gali padėti apsaugoti „Google“ paskyrą ir pakeisti slaptažodį.</translation>
<translation id="8543181531796978784">Galite <ph name="BEGIN_ERROR_LINK" />pranešti apie aptikimo problemą<ph name="END_ERROR_LINK" /> arba, jei suprantate saugos riziką, galite <ph name="BEGIN_LINK" />apsilankyti šioje nesaugioje svetainėje<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Turite klausimų? Susisiekite su jūsų profilį prižiūrinčiu asmeniu.</translation>
<translation id="8553075262323480129">Išversti negalima, nes nepavyko nustatyti puslapio kalbos.</translation>
<translation id="8557066899867184262">Kortelės saugos kodas (CVC) nurodytas kitoje kortelės pusėje.</translation>
<translation id="8559762987265718583">Nepavyksta užmegzti privataus ryšio su <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, nes įrenginio data ir laikas (<ph name="DATE_AND_TIME" />) yra netinkami.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> įtartina svetainė</translation>
<translation id="8564985650692024650">„Chromium“ rekomenduoja iš naujo nustatyti <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> slaptažodį, jei naudojate jį kitose svetainėse.</translation>
<translation id="8571890674111243710">Puslapis verčiamas į <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Pridėti tel. nr.
</translation>
-<translation id="859285277496340001">Sertifikatas nenurodo mechanizmo, skirto patikrinti, ar jis buvo panaikintas.</translation>
<translation id="860043288473659153">Kortelės savininko vardas</translation>
<translation id="861775596732816396">Dydis: 4</translation>
-<translation id="8620436878122366504">Jūsų tėvai dar jos nepatvirtino</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Išsaugoti šią kortelę šiame įrenginyje</translation>
<translation id="8626112503828625890">Saugoti išsamią atsiskaitymo informaciją „Google“ paskyroje?</translation>
+<translation id="8647750283161643317">Viską nustatyti į numatytuosius nustatymus</translation>
<translation id="8663226718884576429">Užsakymo suvestinė, <ph name="TOTAL_LABEL" />, daugiau informacijos</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, atsakymas, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Galima</translation>
<translation id="8703575177326907206">Jūsų ryšys su <ph name="DOMAIN" /> nekoduotas.</translation>
<translation id="8718314106902482036">Mokėjimas neužbaigtas</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, paieškos pasiūlymas</translation>
@@ -1431,6 +1452,7 @@ Papildoma išsami informacija:
<translation id="8738058698779197622">Jei norite užmegzti saugų ryšį, turėsite tinkamai nustatyti laikrodį. To reikalaujama todėl, kad svetainių tapatybei įrodyti naudojami sertifikatai galioja tik tam tikrą laikotarpį. Kadangi įrenginio laikrodis nustatytas netinkamai, „Chromium“ negali tinkamai patvirtinti sertifikatų.</translation>
<translation id="8740359287975076522">Nepavyko rasti <ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS adreso&lt;/abbr&gt;. Nustatoma problema.</translation>
<translation id="874846938927089722">Tinkamos kredito ir išankstinio mokėjimo kortelės</translation>
+<translation id="874918643257405732">Žymėti šį skirtuką</translation>
<translation id="8759274551635299824">Ši kortelė nebegalioja</translation>
<translation id="8761567432415473239">„Google“ saugaus naršymo funkcija neseniai <ph name="BEGIN_LINK" />rado kenkėjiškų programų<ph name="END_LINK" /> <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB įrenginys</translation>
@@ -1460,6 +1482,7 @@ Papildoma išsami informacija:
<translation id="8938939909778640821">Tinkamos kredito ir išankstinio mokėjimo kortelės</translation>
<translation id="8943282376843390568">Žaliųjų citrinų spalva</translation>
<translation id="8957210676456822347">Fiksuotojo portalo autorizavimas</translation>
+<translation id="8962950042226115166">Įtartina svetainė</translation>
<translation id="8968766641738584599">Išsaugoti kortelę</translation>
<translation id="8971063699422889582">Baigėsi serverio sertifikato galiojimo laikas.</translation>
<translation id="8975012916872825179">Įtraukiama tokia informacija kaip telefono numeriai, el. pašto adresai ir pristatymo adresai</translation>
@@ -1482,24 +1505,24 @@ Papildoma išsami informacija:
<translation id="9035022520814077154">Saugos klaida</translation>
<translation id="9038649477754266430">Naudokite numatymo paslaugą, kad puslapiai būtų įkeliami greičiau</translation>
<translation id="9039213469156557790">Be to, šiame puslapyje yra kitų nesaugių išteklių. Perduodant duomenis šiuos išteklius gali peržiūrėti kiti asmenys ir keisti atakuojanti programa, siekianti pakeisti puslapio veikimą.</translation>
+<translation id="9044359186343685026">Naudoti „Touch ID“</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Bandėte pasiekti <ph name="DOMAIN" />, bet serveris pateikė neteisingą sertifikatą.</translation>
<translation id="9050666287014529139">Slaptafrazė</translation>
<translation id="9065203028668620118">Redaguoti</translation>
<translation id="9065745800631924235">„<ph name="TEXT" />“ paieška istorijoje</translation>
<translation id="9069693763241529744">Užblokuota pagal plėtinį</translation>
-<translation id="9076283476770535406">Joje gali būti suaugusiesiems skirto turinio</translation>
<translation id="9076630408993835509">Šios naršyklės netvarko įmonė ar kita organizacija. Veiklą šiame įrenginyje galima tvarkyti ne naršyklėje „Chrome“. <ph name="BEGIN_LINK" />Sužinokite daugiau<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Būtina pateikti daugiau informacijos</translation>
<translation id="9080712759204168376">Užsakymų suvestinė</translation>
<translation id="9089260154716455634">Nenaudojimo valandų politika:</translation>
<translation id="9095388113577226029">Daugiau kalbų...</translation>
+<translation id="9098981495403789647">Administratorius jūsų naršyklėje įgalino „Chrome Enterprise“ apsaugą nuo grėsmių. „Chrome Enterprise“ apsaugos nuo grėsmių funkcija gali pasiekti kai kuriuos jūsų duomenis.</translation>
<translation id="9103872766612412690">Svetainėje <ph name="SITE" /> įprastai naudojama šifruotė informacijai apsaugoti. Šį kartą „Chromium“ bandant prisijungti prie <ph name="SITE" />, ji pateikė neįprastus ir netinkamus prisijungimo duomenis. Gali būti, kad užpuolėjas bando apsimesti svetaine <ph name="SITE" /> arba „Wi-Fi“ prisijungimo ekrane nutrūko ryšys. Jūsų informacija vis tiek liko apsaugota, nes „Chromium“ sustabdė prisijungimą prieš apsikeitimą bet kokiais duomenimis.</translation>
<translation id="9106062320799175032">Atsiskaitymo adreso pridėjimas</translation>
<translation id="9114524666733003316">Kortelė patvirtinama...</translation>
<translation id="9128870381267983090">Prisijungti prie tinklo</translation>
<translation id="9137013805542155359">Rodyti originalą</translation>
-<translation id="9137248913990643158">Prieš naudodami šią programą prisijunkite prie „Chrome“.</translation>
<translation id="9141013498910525015">Tvarkyti adresus</translation>
<translation id="9148088599418889305">Pasirinkti pristatymo metodą</translation>
<translation id="9148507642005240123">&amp;Anuliuoti redagavimą</translation>
diff --git a/chromium/components/strings/components_strings_lv.xtb b/chromium/components/strings/components_strings_lv.xtb
index 25c3bc69c00..7f80b366c72 100644
--- a/chromium/components/strings/components_strings_lv.xtb
+++ b/chromium/components/strings/components_strings_lv.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Uz kartes norādītā vārda pievienošana</translation>
<translation id="1089439967362294234">Nomainīt paroli</translation>
+<translation id="1096545575934602868">Šajā laukā drīkst būt ne vairāk kā <ph name="MAX_ITEMS_LIMIT" /> ierakstu. Visi turpmākie ieraksti tiks atmesti.</translation>
<translation id="109743633954054152">Pārvaldīt paroles Chrome iestatījumos</translation>
<translation id="1103523840287552314">Vienmēr tulkot <ph name="LANGUAGE" /> valodas saturu</translation>
<translation id="1107591249535594099">Ja šī izvēles rūtiņa ir atzīmēta, pārlūks Chrome saglabās jūsu kartes kopiju šajā ierīcē, lai nodrošinātu ātrāku veidlapu aizpildi.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Piekļūstiet vietnes <ph name="URL" /> <ph name="BEGIN_LINK" />kešatmiņā saglabātajai kopijai<ph name="END_LINK" /></translation>
<translation id="1156303062776767266">Jūs skatāt vietēju vai kopīgotu failu</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> negaidīti pārtrauca savienojumu.</translation>
+<translation id="115926840831309955">Pārbaudiet CVC un mēģiniet vēlreiz vai atjauniniet derīguma termiņu.</translation>
<translation id="1161325031994447685">Atkārtoti izveidojiet savienojumu ar Wi-Fi tīklu.</translation>
<translation id="1165039591588034296">Kļūda</translation>
<translation id="1175364870820465910">Drukāt...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">“Programmatūra jūsu datorā, kuras dēļ pārlūkā Chrome nevar izveidot drošu tīmekļa savienojumu” (tikai Windows datoros)</translation>
<translation id="1294154142200295408">Komandrindu varianti</translation>
<translation id="129553762522093515">Nesen aizvērtas</translation>
+<translation id="1298536327547837046">Ļaunprātīgas programmatūras meklēšana</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Dzēsiet sīkfailus<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funkcijas, kuru darbība ir pārtraukta</translation>
<translation id="1320233736580025032">Prc1 (aploksne)</translation>
<translation id="132301787627749051">Meklēt starpliktuves attēlu</translation>
<translation id="1323433172918577554">Rādīt vairāk</translation>
@@ -116,6 +120,7 @@
<translation id="1521655867290435174">Google izklājlapas</translation>
<translation id="1527263332363067270">Tiek gaidīta savienojuma izveide...</translation>
<translation id="1529521330346880926">10x15 (aploksne)</translation>
+<translation id="1530707389502320859">Vietne, ko tikko mēģinājāt apmeklēt, šķiet viltota. Uzbrucēji dažkārt atdarina vietnes, veicot nelielas un grūti pamanāmas izmaiņas vietrādī URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Šajā lapā ir rakstīts</translation>
<translation id="153384715582417236">Pagaidām tas arī viss!</translation>
@@ -156,7 +161,6 @@
<translation id="1710259589646384581">Operētājsistēma</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokuments ir pārāk liels, tādēļ tam nevar pievienot piezīmes</translation>
-<translation id="1721312023322545264">Jums ir nepieciešama atļauja no <ph name="NAME" />, lai apmeklētu šo vietni</translation>
<translation id="1721424275792716183">* Obligāts lauks</translation>
<translation id="1727741090716970331">Derīga kartes numura pievienošana</translation>
<translation id="1728677426644403582">Jūs skatāt tīmekļa lapas avotu.</translation>
@@ -180,6 +184,7 @@
<translation id="1822540298136254167">Tīmekļa vietnes, kuras apmeklējat, un cik daudz laika tajās pavadāt</translation>
<translation id="1826516787628120939">Pārbaude</translation>
<translation id="1834321415901700177">Šī vietne satur kaitnieciskas programmas</translation>
+<translation id="1838374766361614909">Notīrīt meklēšanas vaicājumu</translation>
<translation id="1839551713262164453">Politikas vērtību validēšana neizdevās, tika konstatētas kļūdas</translation>
<translation id="1842969606798536927">Maksāt</translation>
<translation id="1871208020102129563">Starpniekserveris ir iestatīts, lai tas lietotu fiksētus starpniekserverus, nevis .pac skripta URL.</translation>
@@ -190,6 +195,7 @@
<translation id="1883255238294161206">Sakļaut sarakstu</translation>
<translation id="1898423065542865115">Filtrēšana</translation>
<translation id="1914326953223720820">Pakalpojums failu izgūšanai no arhīva</translation>
+<translation id="1915697529809968049">Vai vēlaties izmantot Touch ID, nevis CVC?</translation>
<translation id="1916770123977586577">Lai lietotu atjauninātos iestatījumus šai vietnei, atkārtoti ielādējiet šo lapu</translation>
<translation id="1919345977826869612">Reklāmas</translation>
<translation id="1919367280705858090">Palīdzība par konkrētu kļūdas ziņojumu</translation>
@@ -201,6 +207,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> grāmatzīmes</translation>
<translation id="1973335181906896915">Radās serializēšanas kļūda.</translation>
<translation id="1974060860693918893">Papildu</translation>
+<translation id="1974883374937189061">Palīdzēt uzlabot Chrome drošību, nosūtot Google serveriem <ph name="BEGIN_WHITEPAPER_LINK" />dažu apmeklēto lapu vietrāžus URL, ierobežotu sistēmas informācijas apjomu un daļu lapu satura<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Pogrammaparatūras versija</translation>
<translation id="1981206234434200693">Notīrīt Chrome pārlūkošanas vēstures datus</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{un vēl 1}zero{un vēl #}one{un vēl #}other{un vēl #}}</translation>
@@ -243,10 +250,12 @@
<translation id="2202020181578195191">Ievadiet derīgu gadu</translation>
<translation id="2212735316055980242">Politika netika atrasta.</translation>
<translation id="2213606439339815911">Notiek ierakstu ienešana...</translation>
+<translation id="2215727959747642672">Faila rediģēšana</translation>
<translation id="2218879909401188352">Uzbrucēji vietnē <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> varētu instalēt bīstamas lietotnes, kas bojā jūsu ierīci, rada slēptas izmaksas mobilā tālruņa rēķinā vai zog jūsu personas informāciju. <ph name="BEGIN_LEARN_MORE_LINK" />Uzziniet vairāk<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="2224337661447660594">Nav interneta savienojuma</translation>
<translation id="2230458221926704099">Labojiet savienojumu, izmantojot <ph name="BEGIN_LINK" />diagnostikas lietotni<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Sūtīt tūlīt</translation>
+<translation id="2248949050832152960">Izmantot WebAuthn</translation>
<translation id="225207911366869382">Šī vērtība vairs netiek atbalstīta šai politikai.</translation>
<translation id="2257315177824333709">Atvainojiet, jūsu karti šobrīd nevar saglabāt</translation>
<translation id="2262243747453050782">HTTP kļūda</translation>
@@ -291,7 +300,6 @@
<translation id="2479410451996844060">Nederīgs meklēšanas URL.</translation>
<translation id="2482878487686419369">Paziņojumi</translation>
<translation id="248348093745724435">Ierīces politikas</translation>
-<translation id="2485387744899240041">Lietotājvārdi jūsu ierīcei un pārlūkam</translation>
<translation id="2491120439723279231">Servera sertifikātā ir kļūdas.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON parsētājs</translation>
@@ -301,6 +309,7 @@
<translation id="2501278716633472235">Doties atpakaļ</translation>
<translation id="2503184589641749290">Atbalstītās debetkartes un priekšapmaksas kartes</translation>
<translation id="2505268675989099013">Aizsargāt kontu</translation>
+<translation id="2515335152965840738">IGNORĒT</translation>
<translation id="2515629240566999685">Pārbaudiet signālu savā apkaimē.</translation>
<translation id="2523886232349826891">Tiks saglabāta tikai šajā ierīcē</translation>
<translation id="2524461107774643265">Papildu informācijas pievienošana</translation>
@@ -325,7 +334,6 @@
<translation id="2653659639078652383">Iesniegt</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nav}=1{1 parole (šādam domēnam: <ph name="DOMAIN_LIST" />)}=2{2 paroles (šādiem domēniem: <ph name="DOMAIN_LIST" />)}zero{# paroļu (šādiem domēniem: <ph name="DOMAIN_LIST" />)}one{# parole (šādiem domēniem: <ph name="DOMAIN_LIST" />)}other{# paroles (šādiem domēniem: <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Aizveriet citas cilnes vai lietotnes</translation>
-<translation id="267371737713284912">nospiediet taustiņu <ph name="MODIFIER_KEY_DESCRIPTION" />, lai atsauktu</translation>
<translation id="2674170444375937751">Vai tiešām vēlaties dzēst šīs lapas no savas vēstures?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Iziet</translation>
@@ -335,12 +343,12 @@
<translation id="2704283930420550640">Vērtība neatbilst formātam.</translation>
<translation id="2705137772291741111">Nevar nolasīt šīs vietnes saglabāto (kešatmiņā ievietoto) kopiju.</translation>
<translation id="2709516037105925701">Automātiskā aizpilde</translation>
-<translation id="2712173769900027643">Lūgt atļauju</translation>
<translation id="2713444072780614174">Balta</translation>
<translation id="2720342946869265578">Tuvumā</translation>
<translation id="2721148159707890343">Pieprasījums bija veiksmīgs.</translation>
<translation id="2728127805433021124">Servera sertifikāts ir parakstīts, izmantojot vāju paraksta algoritmu.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Palaist savienojamības diagnostiku<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ja iespējosiet šīs funkcijas, var tikt zaudēti pārlūkošanas dati vai apdraudēta jūsu datu drošība un konfidencialitāte. Iespējotās funkcijas būs aktīvas visiem šī pārlūka lietotājiem.</translation>
<translation id="2735043616039983645">Šai politikai pastāv vairāk nekā viens avots ar pretrunīgām vērtībām.</translation>
<translation id="2738330467931008676">Izvēlēties saņemšanas adresi</translation>
<translation id="2740531572673183784">Labi</translation>
@@ -351,16 +359,15 @@
<translation id="2784949926578158345">Savienojums tika atiestatīts.</translation>
<translation id="2788784517760473862">Atbalstītās kredītkartes</translation>
<translation id="2792012897584536778">Šīs ierīces administratori ir iestatījuši drošības sertifikātus, kas var ļaut viņiem skatīt jūsu apmeklēto vietņu saturu.</translation>
-<translation id="2794233252405721443">Vietne bloķēta</translation>
<translation id="2799020568854403057">Šajā vietnē, kas tiks atvērta, ir kaitīgas lietotnes</translation>
<translation id="2799223571221894425">Restartēt</translation>
<translation id="2803306138276472711">Google drošās pārlūkošanas tehnoloģija vietnē <ph name="SITE" /> nesen <ph name="BEGIN_LINK" />konstatēja ļaunprātīgu programmatūru<ph name="END_LINK" />. Vietnes, kuras parasti ir drošas, dažkārt tiek inficētas ar ļaunprātīgu programmatūru.</translation>
+<translation id="2815364696811431560">PAMEST VIETNI</translation>
<translation id="2824775600643448204">Adreses un meklēšanas josla</translation>
<translation id="2826760142808435982">Savienojums ir šifrēts un autentificēts, izmantojot <ph name="CIPHER" />, un tajā tiek izmantots <ph name="KX" /> kā atslēgu apmaiņas mehānisms.</translation>
<translation id="2835170189407361413">Notīrīt veidlapu</translation>
<translation id="2847118875340931228">Atvērt inkognito režīma logu</translation>
<translation id="2850739647070081192">Invite (aploksne)</translation>
-<translation id="2851634818064021665">Jums nepieciešama atļauja, lai apmeklētu šo vietni</translation>
<translation id="2856444702002559011">Iespējams, uzbrucēji mēģina nozagt jūsu informāciju no vietnes <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (piemēram, paroles, ziņojumus vai kredītkaršu datus). <ph name="BEGIN_LEARN_MORE_LINK" />Uzziniet vairāk<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Vai saglabāt karti?</translation>
@@ -385,6 +392,7 @@
<translation id="2985306909656435243">Ja šī opcija ir iespējota, Chromium saglabās jūsu kartes informāciju šajā ierīcē, lai nodrošinātu ātrāku veidlapu aizpildi.</translation>
<translation id="2985398929374701810">Ievadiet derīgu adresi</translation>
<translation id="2986368408720340940">Šis saņemšanas veids nav pieejams. Izmēģiniet citu veidu.</translation>
+<translation id="2987034854559945715">Nav atbilstošu līdzekļu</translation>
<translation id="2991174974383378012">Kopīgošana ar vietnēm</translation>
<translation id="2991571918955627853">Pašlaik nevarat apmeklēt vietni <ph name="SITE" />, jo tā izmanto HSTS. Tā kā tīkla kļūdas un uzbrukumi parasti ir īslaicīgi, visticamāk, šī lapa vēlāk darbosies.</translation>
<translation id="3005723025932146533">Rādīt saglabāto versiju</translation>
@@ -395,6 +403,7 @@
<translation id="3024663005179499861">Politikas tips nav pareizs.</translation>
<translation id="3037605927509011580">Cilnes avārija.</translation>
<translation id="3041612393474885105">Sertifikāta informācija</translation>
+<translation id="3057676462092457419">DnsOverHttps režīms “<ph name="SECURE_DNS_MODE_SECURE" />” vēl netiek atbalstīts. Tika iestatīts režīms “<ph name="SECURE_DNS_MODE_OFF" />”.</translation>
<translation id="3060227939791841287">C9 (aploksne)</translation>
<translation id="3061707000357573562">Ielāpu pakalpojums</translation>
<translation id="3064966200440839136">Ja maksāšanai tiks izmantota ārēja lietojumprogramma, tiks aizvērts inkognito režīms. Vai turpināt?</translation>
@@ -420,6 +429,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> serverī <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Atcelt maksājumu</translation>
<translation id="3207960819495026254">Atzīmēts kā grāmatzīme</translation>
+<translation id="3209034400446768650">Lapā var tikt iekasēta nauda</translation>
<translation id="3225919329040284222">Serveris uzrādīja sertifikātu, kas neatbilst iebūvētajām cerībām. Šīs cerības ir ietvertas konkrētām, augstas drošības vietnēm, lai aizsargātu jūs.</translation>
<translation id="3226128629678568754">Nospiediet atkārtotas ielādes pogu, lai atkārtoti iesniegtu datus, kas nepieciešami lapas ielādei.</translation>
<translation id="3227137524299004712">Mikrofons</translation>
@@ -427,7 +437,6 @@
<translation id="3229041911291329567">Versijas informācija par ierīci un pārlūku</translation>
<translation id="323107829343500871">Ievadiet kredītkartes <ph name="CREDIT_CARD" /> CVC</translation>
<translation id="3234666976984236645">Vienmēr noteikt nozīmīgu saturu šajā vietnē</translation>
-<translation id="3254409185687681395">Grāmatot šo lapu</translation>
<translation id="3270847123878663523">&amp;Pārkārtošanas atsaukšana</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Pievienot vārdu un uzvārdu uz kartes</translation>
@@ -437,7 +446,6 @@
<translation id="3320021301628644560">Norēķinu adreses pievienošana</translation>
<translation id="3324983252691184275">Tumši sarkana</translation>
<translation id="3338095232262050444">Droši</translation>
-<translation id="3345135638360864351">Lietotājam <ph name="NAME" /> nevarēja nosūtīt jūsu pieprasījumu piekļūt šai vietnei. Lūdzu, mēģiniet vēlreiz.</translation>
<translation id="3355823806454867987">Mainīt starpniekservera iestatījumus...</translation>
<translation id="3361596688432910856">Pārlūkā Chrome <ph name="BEGIN_EMPHASIS" />netiks saglabāta<ph name="END_EMPHASIS" /> šāda informācija:
<ph name="BEGIN_LIST" />
@@ -471,18 +479,15 @@
<translation id="3462200631372590220">Slēpt papildu informāciju</translation>
<translation id="3467763166455606212">Jānorāda kartes īpašnieka vārds un uzvārds</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, šobrīd atvērta. Nospiediet tabulēšanas taustiņu, pēc tam — ievadīšanas taustiņu, lai atvērtu cilni.</translation>
-<translation id="3479539252931486093">Vai tas bija negaidīti? <ph name="BEGIN_LINK" />Informējiet mūs<ph name="END_LINK" />!</translation>
<translation id="3479552764303398839">Vēlāk</translation>
<translation id="3484560055331845446">Varat zaudēt piekļuvi savam Google kontam. Chrome iesaka nekavējoties nomainīt paroli. Jums tiks lūgts pierakstīties.</translation>
<translation id="3495081129428749620">Meklēt lapā
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Mēs nevarējām sasniegt jūsu māti/tēvu. Lūdzu, mēģiniet vēlreiz.</translation>
<translation id="3512163584740124171">Šī politika tiek ignorēta, jo citai tās pašas politiku grupas politikai ir augstāka prioritāte.</translation>
<translation id="3528171143076753409">Servera sertifikāts nav uzticams.</translation>
<translation id="3528485271872257980">Tumši brūna</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Vismaz 1 vienums sinhronizētās ierīcēs}=1{1 vienums (un vēl citi sinhronizētās ierīcēs)}zero{# vienumi (un vēl citi sinhronizētās ierīcēs)}one{# vienums (un vēl citi sinhronizētās ierīcēs)}other{# vienumi (un vēl citi sinhronizētās ierīcēs)}}</translation>
<translation id="3539171420378717834">Saglabāt šīs kartes kopiju šajā ierīcē</translation>
-<translation id="3556433843310711081">Lai atbloķētu, vērsieties pie pārvaldnieka</translation>
<translation id="3566021033012934673">Jūsu savienojums nav privāts</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Vietnē <ph name="SITE" /> iegultā lapā ir rakstīts</translation>
@@ -509,6 +514,7 @@
<translation id="3678529606614285348">Atvērt lapu jaunā inkognito režīma logā (Ctrl+Shift+N)</translation>
<translation id="3679803492151881375">Avāriju pārskats tverts: <ph name="CRASH_TIME" />; augšupielādēts: <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Sertifikāta informācija</translation>
+<translation id="3701427423622901115">Atiestatīšana apstiprināta.</translation>
<translation id="3704162925118123524">Iespējams, izmantotajā tīklā tiks pieprasīts apmeklēt pieteikšanās lapu.</translation>
<translation id="3704609568417268905"><ph name="TIME" />, <ph name="BOOKMARKED" />, <ph name="TITLE" />, <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Notiek ielāde...</translation>
@@ -525,6 +531,7 @@
<translation id="3748148204939282805">Uzbrucēji vietnē <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> var mudināt jūs veikt bīstamas darbības, piemēram, instalēt programmatūru vai atklāt personas informāciju (piemēram, paroles, tālruņa numurus vai kredītkaršu datus). <ph name="BEGIN_LEARN_MORE_LINK" />Uzziniet vairāk<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="375403751935624634">Tulkojums neizdevās servera kļūdas dēļ.</translation>
<translation id="3759461132968374835">Pēdējā laikā neesat ziņojis par avārijām. Šeit nebūs redzamas avārijas, kas radās laikā, kad avāriju pārskatu izveide bija atspējota.</translation>
+<translation id="3760561303380396507">Vai vēlaties izmantot Windows Hello, nevis CVC?</translation>
<translation id="3761718714832595332">Slēpt statusu</translation>
<translation id="3765032636089507299">Drošās pārlūkošanas lapa pašlaik nav pieejama</translation>
<translation id="3778403066972421603">Vai vēlaties saglabāt šo karti savā Google kontā un šajā ierīcē?</translation>
@@ -534,6 +541,7 @@
<translation id="3789155188480882154">16. izmērs</translation>
<translation id="3797522431967816232">Prc3 (aploksne)</translation>
<translation id="3807873520724684969">Tika bloķēts kaitīgs saturs.</translation>
+<translation id="3808375843007691220">Uzmanību — turpmākās funkcijas ir eksperimentālas!</translation>
<translation id="3810973564298564668">Pārvaldīt</translation>
<translation id="382518646247711829">Ja izmantojat starpniekserveri...</translation>
<translation id="3828924085048779000">Tukša ieejas frāze nav atļauta.</translation>
@@ -542,11 +550,11 @@
<translation id="3858027520442213535">Atjaunināt datumu un laiku</translation>
<translation id="3884278016824448484">Ierīces identifikators rada konfliktu.</translation>
<translation id="3885155851504623709">Pagasts</translation>
-<translation id="3886446263141354045">Pieprasījums piekļūt šai vietnei ir nosūtīts lietotājam <ph name="NAME" /></translation>
<translation id="3890664840433101773">E-pasta adreses pievienošana</translation>
<translation id="3901925938762663762">Kartes derīguma termiņš ir beidzies.</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Vai vēlaties izmantot WebAuthn, nevis CVC?</translation>
<translation id="3946209740501886391">Vienmēr jautāt šajā vietnē</translation>
<translation id="3949571496842715403">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tā drošības sertifikātā nav norādīti temata citi nosaukumi. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ļaunprātīgi izmanto jūsu savienojumu.</translation>
<translation id="3949601375789751990">Šeit ir redzama jūsu pārlūkošanas vēsture.</translation>
@@ -557,11 +565,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nav}=1{No 1 vietnes }zero{No # vietnēm }one{No # vietnes }other{No # vietnēm }}</translation>
<translation id="397105322502079400">Aprēķina...</translation>
<translation id="3973234410852337861">Vietne <ph name="HOST_NAME" /> ir bloķēta</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ir iespējojis pārlūkā funkciju Chrome Enterprise Threat Protection. Chrome Enterprise Threat Protection var piekļūt daļai jūsu datu.</translation>
<translation id="3987940399970879459">Mazāk nekā 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{Tuvumā ir 1 tīmekļa lapa}zero{Tuvumā ir # tīmekļa lapas}one{Tuvumā ir # tīmekļa lapa}other{Tuvumā ir # tīmekļa lapas}}</translation>
<translation id="4030383055268325496">&amp;Atsaukt pievienošanu</translation>
<translation id="4032320456957708163">Jūsu pārlūku pārvalda <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Atvērtā saite novirza uz vietni, kuru parasti neapmeklējat. Iespējams, jūs tiekat maldināts.</translation>
<translation id="4058922952496707368">Atslēga <ph name="SUBKEY" />: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (aploksne)</translation>
<translation id="4067947977115446013">Derīgas adreses pievienošana</translation>
@@ -574,6 +582,7 @@
<translation id="4103249731201008433">Ierīces sērijas numurs nav derīgs.</translation>
<translation id="410351446219883937">Automātiskā atskaņošana</translation>
<translation id="4103763322291513355">Apmeklējiet vietni &lt;strong&gt;chrome://policy&lt;/strong&gt;, lai skatītu melnajā sarakstā iekļautos vietrāžus URL, kā arī citas politikas, ko noteicis sistēmas administrators.</translation>
+<translation id="4108231218301530806">Nākamreiz izmantot pirksta nospiedumu, lai verificētu šo karti</translation>
<translation id="4110652170750985508">Maksājuma pārskatīšana</translation>
<translation id="4112140312785995938">Pārtīt atpakaļ</translation>
<translation id="4116663294526079822">Vienmēr atļaut šajā vietnē</translation>
@@ -588,6 +597,7 @@
<translation id="4171400957073367226">Verifikācijas paraksts nav derīgs.</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Vēl <ph name="ITEM_COUNT" /> vienums}zero{Vēl <ph name="ITEM_COUNT" /> vienumi}one{Vēl <ph name="ITEM_COUNT" /> vienums}other{Vēl <ph name="ITEM_COUNT" /> vienumi}}</translation>
+<translation id="4176463684765177261">Atspējota</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" />: <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Lai nākamreiz veiktu maksājumu ātrāk, pievienojiet kartes datus un norēķinu adresi savam Google kontam.</translation>
<translation id="4196861286325780578">&amp;Atcelt pārvietošanas atsaukšanu</translation>
@@ -624,6 +634,7 @@
<translation id="4277028893293644418">Atiestatīt paroli</translation>
<translation id="4279811152705618813">Jūsu ierīci (veids: <ph name="DEVICE_TYPE" />) pārvalda <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Šī karte tika saglabāta jūsu Google kontā}zero{Šīs kartes tika saglabātas jūsu Google kontā}one{Šīs kartes tika saglabātas jūsu Google kontā}other{Šīs kartes tika saglabātas jūsu Google kontā}}</translation>
+<translation id="428847186335018806">Pārmeklēt failus, ko augšupielādējat vai lejupielādējat pārlūkā Chrome.</translation>
<translation id="42981349822642051">Izvērst</translation>
<translation id="4302965934281694568">Chou3 (aploksne)</translation>
<translation id="4305817255990598646">Pāriet</translation>
@@ -653,7 +664,6 @@
<translation id="4435702339979719576">Pastkarte)</translation>
<translation id="443673843213245140">Starpniekservera lietošana ir atspējota, bet ir norādīta atklāta starpniekservera konfigurācija.</translation>
<translation id="445100540951337728">Atbalstītās debetkartes</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> aizdomīga uzvedība</translation>
<translation id="4466881336512663640">Veidlapas izmaiņas tiks zaudētas. Vai tiešām vēlaties turpināt?</translation>
<translation id="4477350412780666475">Nākamais ieraksts</translation>
<translation id="4482953324121162758">Šī vietne netiks tulkota.</translation>
@@ -680,6 +690,7 @@
<translation id="4594403342090139922">&amp;Dzēšanas atsaukšana</translation>
<translation id="4597348597567598915">8. izmērs</translation>
<translation id="4600854749408232102">C6/C5 (aploksne)</translation>
+<translation id="464342062220857295">Meklēšanas funkcijas</translation>
<translation id="4646534391647090355">Doties uz turieni tagad</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tās drošības sertifikātā ir kļūdas. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ir ļaunprātīgi izmantojis jūsu savienojumu.</translation>
@@ -688,7 +699,6 @@
<translation id="4691835149146451662">Architecture-A (aploksne)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Savienojums tika pārtraukts</translation>
-<translation id="471880041731876836">Jums nav atļaujas apmeklēt šo vietni</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Palaist Windows tīkla diagnostiku<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Atkārtoti ielādēt politikas</translation>
<translation id="4728558894243024398">Platforma</translation>
@@ -716,7 +726,6 @@
<translation id="4816492930507672669">Ietilpināt lapā</translation>
<translation id="4850886885716139402">Skatīt</translation>
<translation id="4854362297993841467">Šis piegādes veids nav pieejams. Izmēģiniet citu veidu.</translation>
-<translation id="4858792381671956233">Jūs lūdzāt vecākiem atļauju apmeklēt šo lapu</translation>
<translation id="4864052566555297930">Drošības padoms:</translation>
<translation id="4876188919622883022">Vienkāršotais skats</translation>
<translation id="4876305945144899064">Nav lietotājvārda</translation>
@@ -740,7 +749,9 @@
<translation id="4974590756084640048">Atkārtoti iespējot brīdinājumus</translation>
<translation id="4984339528288761049">Prc5 (aploksne)</translation>
<translation id="4989163558385430922">Skatīt visu</translation>
+<translation id="4989542687859782284">Nav pieejami</translation>
<translation id="4989809363548539747">Šis spraudnis netiek atbalstīts</translation>
+<translation id="4995216769782533993">Lai kopīgotu kartes datus ar šo vietni, apstipriniet drošības kodu.</translation>
<translation id="5002932099480077015">Iespējojot šo opciju, Chrome saglabās jūsu kartes informāciju šajā ierīcē, lai jūs varētu ātrāk aizpildīt veidlapas.</translation>
<translation id="5015510746216210676">Ierīces nosaukums:</translation>
<translation id="5017554619425969104">Kopētais teksts</translation>
@@ -769,6 +780,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bitu)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Kartes verificēšana</translation>
<translation id="5135404736266831032">Pārvaldīt adreses...</translation>
<translation id="5138227688689900538">Rādīt mazāk</translation>
<translation id="5141240743006678641">Šifrēt sinhronizētās paroles, izmantojot Google akreditācijas datus</translation>
@@ -795,6 +807,7 @@
<translation id="5251803541071282808">Mākonis</translation>
<translation id="5252000469029418751">C7 (aploksne)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Tikai īpašnieks <ph name="OWNER_EMAIL" /> var iestatīt funkcijas, kas tiek lietotas visai sistēmai.</translation>
<translation id="5273658854610202413">Brīdinājums! Šī politika netika apvienota, kā norādīts politikā PolicyDictionaryMultipleSourceMergeList, jo tā nav daļa no apvienojamām vārdnīcu politikām.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Beigas</translation>
@@ -818,7 +831,6 @@
<translation id="536296301121032821">Neizdevās saglabāt politikas iestatījumus.</translation>
<translation id="5371425731340848620">Kartes atjaunināšana</translation>
<translation id="5377026284221673050">“Pulkstenis atpaliek”, “Pulkstenis steidzas” vai “&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;”</translation>
-<translation id="5377179979757081683">Šajā lapā var tikt mēģināts jūs maldināt, nozagt personas informāciju vai kaitēt jūsu ierīcei. Ievadot personas informāciju vai atverot lejupielādētus failus, ievērojiet piesardzību.</translation>
<translation id="5384855140246857529">Lai kartes varētu izmantot visās ierīcēs, pierakstieties un ieslēdziet sinhronizāciju.</translation>
<translation id="5386426401304769735">Šīs vietnes sertifikātu ķēdē ir iekļauts sertifikāts, kas ir parakstīts, izmantojot SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -832,6 +844,7 @@
<translation id="5457113250005438886">Nav derīgi</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}zero{<ph name="CONTACT_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Atcelt labojuma atsaukšanu</translation>
+<translation id="5473728911100096288">Pēc šo funkciju iespējošanas jūs izmantosiet funkcijas, kuru darbība ir pārtraukta un kuras turpmākajās versijās nebūs pieejamas.</translation>
<translation id="5478437291406423475">B6/C4 (aploksne)</translation>
<translation id="5481076368049295676">Šis saturs jūsu ierīcē var mēģināt instalēt bīstamu programmatūru, kas var nozagt vai izdzēst jūsu informāciju. <ph name="BEGIN_LINK" />Tāpat rādīt<ph name="END_LINK" />.</translation>
<translation id="54817484435770891">Derīgas adreses pievienošana</translation>
@@ -855,7 +868,6 @@
<translation id="5570825185877910964">Aizsargāt kontu</translation>
<translation id="5571083550517324815">Nevar saņemt sūtījumu šajā adresē. Atlasiet citu adresi.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 tiek lietots}zero{# tiek lietoti}one{# tiek lietots}other{# tiek lietoti}})</translation>
-<translation id="5572851009514199876">Lūdzu, palaidiet pārlūku Chrome un pierakstieties tajā, lai pārlūkā Chrome varētu pārbaudīt, vai jums ir atļauja piekļūt šai vietnei.</translation>
<translation id="5580958916614886209">Pārbaudiet derīguma termiņa mēnesi un mēģiniet vēlreiz.</translation>
<translation id="5586446728396275693">Nav saglabātu adrešu.</translation>
<translation id="5595485650161345191">Rediģēt adresi</translation>
@@ -863,6 +875,7 @@
<translation id="560412284261940334">Pārvaldīšana netiek atbalstīta.</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Šī vietne varētu būt viltota vai krāpnieciska. Chrome iesaka pamest vietni tūlīt.</translation>
<translation id="5610142619324316209">Pārbaudiet savienojumu.</translation>
<translation id="5610807607761827392">Varat pārvaldīt karšu un adrešu informāciju sadaļā <ph name="BEGIN_LINK" />Iestatījumi<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> novirzīja pārāk daudz reižu.</translation>
@@ -886,11 +899,11 @@
<translation id="5720705177508910913">Pašreizējais lietotājs</translation>
<translation id="5728056243719941842">C5 (aploksne)</translation>
<translation id="5730040223043577876">Chrome iesaka atiestatīt jūsu paroli, ja izmantojāt to citās vietnēs.</translation>
-<translation id="5732392974455271431">Lai atbloķētu, vērsieties pie vecākiem</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Kartes datu saglabāšana Google kontā}zero{Karšu datu saglabāšana Google kontā}one{Karšu datu saglabāšana Google kontā}other{Karšu datu saglabāšana Google kontā}}</translation>
<translation id="5763042198335101085">Ievadiet derīgu e-pasta adresi</translation>
<translation id="5765072501007116331">Lai skatītu piegādes veidus un prasības, atlasiet adresi.</translation>
<translation id="5778550464785688721">Pilnīga MIDI ierīču pārvaldība</translation>
+<translation id="5781136890105823427">Eksperiments iespējots</translation>
<translation id="578305955206182703">Dzintarkrāsa</translation>
<translation id="57838592816432529">Izslēgt skaņu</translation>
<translation id="5784606427469807560">Apstiprinot karti, radās problēma. Pārbaudiet interneta savienojumu un mēģiniet vēlreiz.</translation>
@@ -907,13 +920,16 @@
<translation id="5860033963881614850">Izsl.</translation>
<translation id="5863847714970149516">Nākamajā lapā var tikt mēģināts pieprasīt naudu</translation>
<translation id="5866257070973731571">Tālruņa numura pievienošana</translation>
+<translation id="5866898949289125849">Jūs skatāt izstrādātāja rīku lapu</translation>
<translation id="5869405914158311789">Šī vietne nav sasniedzama</translation>
<translation id="5869522115854928033">Saglabātās paroles</translation>
<translation id="5887400589839399685">Kartīte ir saglabāta</translation>
<translation id="5893752035575986141">Tiek pieņemtas kredītkartes.</translation>
+<translation id="5895138241574237353">Restartēt</translation>
<translation id="5901630391730855834">Dzeltena</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (veikta sinhronizācija)</translation>
<translation id="5916664084637901428">Iesl.</translation>
+<translation id="59174027418879706">Iespējots</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Vai saglabāt kartes datus Google kontā?</translation>
<translation id="5922853866070715753">Gandrīz pabeigts</translation>
@@ -947,6 +963,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Vai vēlaties izmantot kartes visās savās ierīcēs?</translation>
<translation id="6059925163896151826">USB ierīces</translation>
+<translation id="6060009363608157444">Nederīgs DnsOverHttps režīms.</translation>
<translation id="6080696365213338172">Jūs esat piekļuvis saturam, izmantojot administratora izsniegtu sertifikātu. Datus, kurus sniedzat domēnā <ph name="DOMAIN" />, var pārtvert jūsu administrators.</translation>
<translation id="6094273045989040137">Pievienot piezīmi</translation>
<translation id="610911394827799129">Jūsu Google kontam var būt citu veidu pārlūkošanas vēstures dati vietnē <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -995,13 +1012,12 @@
<translation id="6404511346730675251">Rediģēt grāmatzīmi</translation>
<translation id="6406765186087300643">C0 (aploksne)</translation>
<translation id="6410264514553301377">Ievadiet kredītkartes <ph name="CREDIT_CARD" /> derīguma termiņu un CVC.</translation>
-<translation id="6414888972213066896">Jūs lūdzāt vienam no vecākiem atļauju apmeklēt šo vietni</translation>
<translation id="6415778972515849510">Chromium var palīdzēt jums aizsargāt jūsu Google kontu un nomainīt paroli.</translation>
-<translation id="6417515091412812850">Nevar pārbaudīt, vai sertifikāts ir atsaukts.</translation>
<translation id="6431585503458005759">Nesaglabāt</translation>
<translation id="6433490469411711332">Kontaktinformācijas rediģēšana</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> noraidīja savienojuma izveidi.</translation>
<translation id="6434309073475700221">Atmest</translation>
+<translation id="6435221585574090192">Kopīgot ar jūsu administratoru datus par notikumiem, kuri ir saistīti ar drošību un ir atzīmēti funkcijā Chrome Enterprise Threat Protection. Šādos datos var būt ietverti lapu vietrāži URL, faila nosaukums un faila metadati, kā arī lietotājvārdi, ko izmantojat ierīcē un pārlūkā Chrome.</translation>
<translation id="6440503408713884761">Ignorēts</translation>
<translation id="6446163441502663861">Kahu (aploksne)</translation>
<translation id="6446608382365791566">Papildu informācijas pievienošana</translation>
@@ -1010,20 +1026,19 @@
<translation id="6465306955648956876">Pārvaldīt paroles...</translation>
<translation id="647261751007945333">Ierīces politikas</translation>
<translation id="6476284679642588870">Pārvaldīt maksājumu veidus</translation>
-<translation id="6477321094435799029">Pārlūkā Chrome tika noteikts, ka šajā lapā ir neparasts kods. Lapa tika bloķēta, lai aizsargātu jūsu personas informāciju (piemēram, paroles, tālruņa numurus un kredītkaršu informāciju).</translation>
<translation id="6489534406876378309">Sākt avāriju datu augšupielādi</translation>
<translation id="6499038740797743453">Vai atiestatīt paroli?</translation>
<translation id="6507833130742554667">Tiek pieņemtas kredītkartes un debetkartes.</translation>
<translation id="650855688985305916">Jā, saglabāt</translation>
<translation id="6508722015517270189">Restartējiet pārlūku Chrome</translation>
<translation id="6517596291481585650">Brīdinājums! Šī politika netika apvienota kā saraksts atbilstoši politikā noteiktajam, jo tā nav saraksts.</translation>
+<translation id="6518133107902771759">Verificēt</translation>
<translation id="6521745193039995384">Nav aktīva</translation>
<translation id="6529602333819889595">&amp;Dzēšanas atsaukuma atcelšana</translation>
<translation id="6534179046333460208">Fiziskā tīmekļa ieteikumi</translation>
<translation id="6545864417968258051">Bluetooth meklēšana</translation>
<translation id="6554795675067793129">Jūsu kontu pārvalda <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Atcelt atsaukšanu</translation>
-<translation id="6563469144985748109">Jūsu vadītājs vēl nav to apstiprinājis</translation>
<translation id="6569060085658103619">Jūs skatāt paplašinājumu lapu.</translation>
<translation id="6578796323535178455">C2 (aploksne)</translation>
<translation id="6579990219486187401">Gaiši rozā</translation>
@@ -1041,11 +1056,13 @@
<translation id="6643016212128521049">Notīrīt</translation>
<translation id="6644283850729428850">Šī politika ir izbeigta.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nav}=1{No 1 vietnes (jūs netiksiet izrakstīts no sava Google konta)}zero{No # vietnēm (jūs netiksiet izrakstīts no sava Google konta)}one{No # vietnes (jūs netiksiet izrakstīts no sava Google konta)}other{No # vietnēm (jūs netiksiet izrakstīts no sava Google konta)}}</translation>
+<translation id="6652101503459149953">Izmantot Windows Hello</translation>
<translation id="6657585470893396449">Parole</translation>
<translation id="6670613747977017428">Atpakaļ drošībā.</translation>
<translation id="6671697161687535275">Vai noņemt veidlapas ieteikumu no pārlūka Chromium?</translation>
<translation id="6685834062052613830">Izrakstieties un pabeidziet iestatīšanu</translation>
<translation id="6689271823431384964">Pārlūkprogrammā Chrome tiek piedāvāts saglabāt jūsu kartes Google kontā, jo esat pierakstījies. Varat mainīt šo darbību iestatījumos. Kartes īpašnieka vārds tiek iegūts no jūsu konta.</translation>
+<translation id="6707256370811247129">Meklēt datus kešatmiņas saturā un failos, ko augšupielādējat vai lejupielādējat pārlūkā Chrome.</translation>
<translation id="6710213216561001401">Iepriekšējais</translation>
<translation id="6710594484020273272">&lt;Ierakstiet meklēšanas vienumu&gt;</translation>
<translation id="671076103358959139">Reģistrācijas pilnvara:</translation>
@@ -1053,10 +1070,10 @@
<translation id="6738516213925468394">Jūsu dati tika šifrēti, izmantojot jūsu <ph name="BEGIN_LINK" />sinhronizācijas ieejas frāzi<ph name="END_LINK" />šādā datumā: <ph name="TIME" />. Lai sāktu sinhronizāciju, ievadiet ieejas frāzi.</translation>
<translation id="674375294223700098">Nezināma servera sertifikāta kļūda.</translation>
<translation id="6744009308914054259">Kamēr tiek gaidīts savienojums, varat apmeklēt Lejupielādes, lai lasītu rakstu bezsaistē.</translation>
+<translation id="6747611005629681221">Brīdinājums! Lapā tiek izmantotas funkcijas, kuru darbība ir pārtraukta.</translation>
<translation id="6753269504797312559">Politikas vērtība</translation>
<translation id="6757797048963528358">Ierīce tika pārslēgta miega režīmā.</translation>
<translation id="6768213884286397650">Hagaki (pastkarte)</translation>
-<translation id="6778737459546443941">Neviens no jūsu vecākiem vēl nav to apstiprinājis</translation>
<translation id="67862343314499040">Violeta</translation>
<translation id="6786747875388722282">Paplašinājumi</translation>
<translation id="6790428901817661496">Atskaņot</translation>
@@ -1064,6 +1081,7 @@
<translation id="681021252041861472">Obligātais lauks</translation>
<translation id="6810899417690483278">Pielāgošanas ID</translation>
<translation id="6825578344716086703">Jūs mēģinājāt sasniegt domēnu <ph name="DOMAIN" />, bet serveris uzrādīja sertifikātu, kas ir parakstīts, izmantojot vāju paraksta algoritmu (piemēram, SHA-1). Tas nozīmē, ka servera norādītie drošības akreditācijas dati var būt viltoti un šis serveris var nebūt tas serveris, kuru mēģināt sasniegt (iespējams, jūs sazināties ar uzbrucēju).</translation>
+<translation id="6826370046007623921">Datu zuduma novēršana</translation>
<translation id="6831043979455480757">Tulkot</translation>
<translation id="6839929833149231406">Apgabals</translation>
<translation id="6852204201400771460">Vai atkārtoti ielādēt lietotni?</translation>
@@ -1076,7 +1094,6 @@
<translation id="6891596781022320156">Politikas līmenis netiek atbalstīts.</translation>
<translation id="6895330447102777224">Karte ir apstiprināta</translation>
<translation id="6897140037006041989">Lietotāja aģents</translation>
-<translation id="6903319715792422884">Palīdziet uzlabot Drošo pārlūkošanu, nosūtot noteiktu <ph name="BEGIN_WHITEPAPER_LINK" />sistēmas informāciju un lapas saturu<ph name="END_WHITEPAPER_LINK" /> Google serveriem. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Lietotājs:</translation>
<translation id="6934672428414710184">Šis vārds ir no jūsu Google konta</translation>
<translation id="6944692733090228304">Jūs ievadījāt paroli vietnē, kuru nepārvalda <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Lai aizsargātu savu kontu, neizmantojiet šo paroli citās lietotnēs un vietnēs.</translation>
@@ -1121,6 +1138,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}zero{<ph name="PAYMENT_METHOD_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavandas krāsa</translation>
<translation id="717330890047184534">GAIA ID:</translation>
+<translation id="7174545416324379297">Apvienota</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}zero{<ph name="SHIPPING_OPTION_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> un vēl <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Visiem pieprasījumiem uz serveri <ph name="ORIGIN" />tiek piemērota drošības politika. Taču tā vietā, lai iesniegtu politiku, serveris ir novirzījis pārlūku citur, un tas neļauj pārlūkam izpildīt jūsu pieprasījumu vietnei <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Saglabāt un aizpildīt maksājumu veidus</translation>
@@ -1155,6 +1173,7 @@ Papildu informācija:
<translation id="7320336641823683070">Savienojuma palīdzība</translation>
<translation id="733354035281974745">Ierīces lokālā konta ignorēšana</translation>
<translation id="7334320624316649418">&amp;Atcelt pārkārtošanas atsaukšanu</translation>
+<translation id="7337706099755338005">Nav pieejams jūsu platformā.</translation>
<translation id="733923710415886693">Servera sertifikāts netika atklāts, izmantojot Certificate Transparency.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Ir saistīts:</translation>
@@ -1186,7 +1205,6 @@ Papildu informācija:
<translation id="7440140511386898319">Pārlūkošana bezsaistē</translation>
<translation id="7441627299479586546">Politikas subjekts nav pareizs.</translation>
<translation id="7442725080345379071">Gaiši oranža</translation>
-<translation id="7444046173054089907">Šī vietne ir bloķēta</translation>
<translation id="7445762425076701745">Nevar pilnībā apstiprināt servera identifikācijas datus, ar kuru esat savienots. Jums ir izveidots savienojums ar serveri, izmantojot nosaukumu, kas ir derīgs tikai jūsu tīklā, kam ārējā sertifikāta izdevējiestāde nekādā veidā nevar apstiprināt īpašumtiesības. Tā kā dažas sertifikāta izdevējiestādes tāpat izsniegs sertifikātus šādiem nosaukumiem, nav iespējams garantēt, ka jūs esat savienots ar vajadzīgo vietni, nevis uzbrucēju.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Uzzināt vairāk<ph name="END_LINK" /> par šo problēmu.</translation>
<translation id="7455133967321480974">Izmantot globālo noklusējumu (Bloķēt)</translation>
@@ -1208,9 +1226,9 @@ Papildu informācija:
<translation id="7538364083937897561">A2 (aploksne)</translation>
<translation id="7542403920425041731">Pēc apstiprinājuma jūsu kartes informācija tiks kopīgota ar šo vietni.</translation>
<translation id="7542995811387359312">Automātiska kredītkartes numura ievadīšana ir atspējota, jo šai veidlapai netiek izmantots drošs savienojums.</translation>
-<translation id="7543525346216957623">Lūdziet kādam no vecākiem</translation>
<translation id="7548892272833184391">Savienojuma kļūdu novēršana</translation>
<translation id="7549584377607005141">Lai tīmekļa lapu varētu attēlot pareizi, tai nepieciešami jūsu iepriekš ievadītie dati. Varat atkārtoti nosūtīt šos datus, taču tādā gadījumā tiks atkārtota ikviena darbība, ko pirms tam veica lapa.</translation>
+<translation id="7550637293666041147">Jūsu lietotājvārds ierīcē un pārlūkā Chrome</translation>
<translation id="7552846755917812628">Izmantojiet tālāk sniegtos padomus.</translation>
<translation id="7554791636758816595">Jauna cilne</translation>
<translation id="7564049878696755256">Varat zaudēt piekļuvi savam <ph name="ORG_NAME" /> kontam, vai jūsu identitāte var tikt nozagta. Chrome iesaka nekavējoties nomainīt paroli.</translation>
@@ -1225,6 +1243,7 @@ Papildu informācija:
<translation id="7610193165460212391">Vērtība pārsniedz diapazonu: <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Derīguma termiņš: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Jums jau ir dati, kas šifrēti, izmantojot citu Google konta paroles versiju. Ievadiet to šeit.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Veiktspējas dati un avāriju pārskati</translation>
<translation id="7637571805876720304">Vai noņemt kredītkarti no pārlūka Chromium?</translation>
<translation id="7638605456503525968">Seriālie porti</translation>
@@ -1237,7 +1256,6 @@ Papildu informācija:
<translation id="7668654391829183341">Nezināma ierīce</translation>
<translation id="7669271284792375604">Uzbrucēji šajā vietnē var mudināt jūs uz tādu programmu instalēšanu, kuras traucē pārlūkošanu (piemēram, mainot sākumlapu vai apmeklētajās vietnēs rādot papildu reklāmas).</translation>
<translation id="7676643023259824263">Meklēt starpliktuves tekstu <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platforma un mākonis</translation>
<translation id="7681101578153515023">Mainīt meklētājprogrammu</translation>
<translation id="7682287625158474539">Piegāde</translation>
<translation id="7687186412095877299">Aizpilda maksājumu veidlapas, izmantojot saglabātos maksājuma veidus</translation>
@@ -1252,7 +1270,6 @@ Papildu informācija:
<translation id="7723047071702270851">Kartes informācijas rediģēšana</translation>
<translation id="774634243536837715">Bloķēts bīstams saturs</translation>
<translation id="7752995774971033316">Netiek pārvaldīts</translation>
-<translation id="7755287808199759310">Lai atbloķētu, vēsieties pie vecāka</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Iespējams, savienojumu ir bloķējis ugunsmūris vai pretvīrusu programmatūra.</translation>
<translation id="7759163816903619567">Parādāmais domēns:</translation>
@@ -1296,7 +1313,6 @@ Papildu informācija:
<translation id="8004582292198964060">Pārlūkprogramma</translation>
<translation id="8009225694047762179">Pārvaldīt paroles</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Šī karte un tās norēķinu adrese tiks saglabāta. Jūs varēsiet to izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}zero{Šīs kartes un to norēķinu adreses tiks saglabātas. Jūs varēsiet tās izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}one{Šīs kartes un to norēķinu adreses tiks saglabātas. Jūs varēsiet tās izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}other{Šīs kartes un to norēķinu adreses tiks saglabātas. Jūs varēsiet tās izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Mēs nevarējām sasniegt jūsu vecākus. Lūdzu, mēģiniet vēlreiz.</translation>
<translation id="8025119109950072390">Uzbrucēji šajā vietnē var mudināt jūs veikt bīstamas darbības, piemēram, instalēt programmatūru vai atklāt savu personas informāciju (piemēram, paroles, tālruņa numurus vai informāciju par kredītkartēm).</translation>
<translation id="8034522405403831421">Šī lapas saturs ir šādā valodā: <ph name="SOURCE_LANGUAGE" />. Vai tulkot šādā valodā: <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pildspalva</translation>
@@ -1307,6 +1323,7 @@ Papildu informācija:
<translation id="8041940743680923270">Izmantot globālo noklusējumu (Vaicāt)</translation>
<translation id="8042918947222776840">Izvēlēties saņemšanas veidu</translation>
<translation id="8057711352706143257">Programmatūra <ph name="SOFTWARE_NAME" /> nav pareizi konfigurēta. Atinstalējot programmatūru <ph name="SOFTWARE_NAME" />, parasti problēma tiek novērsta. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Turpmāk nebūs jāievada kartes drošības kods</translation>
<translation id="8066955247577885446">Diemžēl radās problēma.</translation>
<translation id="8074253406171541171">10x13 (aploksne)</translation>
<translation id="8078141288243656252">Pagrieztiem dokumentiem nevar pievienot piezīmes</translation>
@@ -1337,6 +1354,7 @@ Papildu informācija:
<translation id="8211406090763984747">Savienojums ir drošs</translation>
<translation id="8218327578424803826">Piešķirtā atrašanās vieta:</translation>
<translation id="8220146938470311105">C7/C6 (aploksne)</translation>
+<translation id="8220639454292072926">Enterprise pārskati</translation>
<translation id="8225771182978767009">Persona, kura iestatīja šo datoru, izvēlējās bloķēt šo vietni.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Atvērt lapu jaunā inkognito režīma cilnē</translation>
@@ -1391,24 +1409,24 @@ Papildu informācija:
<translation id="8508648098325802031">Meklēšanas ikona</translation>
<translation id="8522552481199248698">Chrome var palīdzēt jums aizsargāt jūsu Google kontu un nomainīt paroli.</translation>
<translation id="8543181531796978784">Jūs varat <ph name="BEGIN_ERROR_LINK" />ziņot par noteikšanas problēmu<ph name="END_ERROR_LINK" /> vai, ja apzināties drošības riskus, <ph name="BEGIN_LINK" />apmeklēt šo nedrošo vietni<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Vai radušies jautājumi? Sazinieties ar personu, kas uzrauga jūsu profilu.</translation>
<translation id="8553075262323480129">Tulkošana neizdevās, jo lapas valoda nav nosakāma.</translation>
<translation id="8557066899867184262">CVC kods ir norādīts jūsu kartes aizmugurē.</translation>
<translation id="8559762987265718583">Nevar izveidot privātu savienojumu ar <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, jo jūsu ierīces datums un laiks (<ph name="DATE_AND_TIME" />) nav pareizs.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> aizdomīga vietne</translation>
<translation id="8564985650692024650">Chromium iesaka atiestatīt jūsu <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> paroli, ja izmantojāt to citās vietnēs.</translation>
<translation id="8571890674111243710">Notiek lapas tulkošana uz <ph name="LANGUAGE" /> valodu...</translation>
<translation id="858637041960032120">Piev. tālr. nr.
</translation>
-<translation id="859285277496340001">Sertifikāts nenorāda mehānismu, ar kuru pārbaudīt, vai tas nav atsaukts.</translation>
<translation id="860043288473659153">Bankas kartes īpašnieka vārds</translation>
<translation id="861775596732816396">4. izmērs</translation>
-<translation id="8620436878122366504">Jūsu vecāki vēl nav to apstiprinājuši</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Saglabāt šo karti šajā ierīcē</translation>
<translation id="8626112503828625890">Vai saglabāt norēķinu datus Google kontā?</translation>
+<translation id="8647750283161643317">Atiestatīt visiem to noklusējuma iestatījumus</translation>
<translation id="8663226718884576429">Pasūtījuma kopsavilkums, <ph name="TOTAL_LABEL" />, citi dati</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, atbilde, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Pieejams</translation>
<translation id="8703575177326907206">Jūsu savienojums ar <ph name="DOMAIN" /> nav kodēts.</translation>
<translation id="8718314106902482036">Maksājums nav pabeigts</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, meklēšanas ieteikums</translation>
@@ -1419,6 +1437,7 @@ Papildu informācija:
<translation id="8738058698779197622">Lai izveidotu drošu savienojumu, ir jāiestata pareizs pulksteņa laiks. Tas ir nepieciešams, jo sertifikāti, kurus vietnes izmanto, lai tiktu identificētas, ir derīgi tikai noteiktos laika periodos. Tā kā jūsu ierīces pulkstenis nav pareizi iestatīts, Chromium nevar verificēt šos sertifikātus.</translation>
<translation id="8740359287975076522">Nevarēja atrast <ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS adresi&lt;/abbr&gt;. Notiek problēmas diagnosticēšana.</translation>
<translation id="874846938927089722">Atbalstītās kredītkartes un priekšapmaksas kartes</translation>
+<translation id="874918643257405732">Saglabāt šo cilni kā grāmatzīmi</translation>
<translation id="8759274551635299824">Kartes derīguma termiņš ir beidzies</translation>
<translation id="8761567432415473239">Google drošās pārlūkošanas tehnoloģija nesen vietnē <ph name="SITE" /> <ph name="BEGIN_LINK" />atklāja kaitīgas programmas<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB ierīce</translation>
@@ -1448,6 +1467,7 @@ Papildu informācija:
<translation id="8938939909778640821">Atbalstītās kredītkartes un priekšapmaksas kartes</translation>
<translation id="8943282376843390568">Laima zaļa</translation>
<translation id="8957210676456822347">Caurlaides lapas autorizācija</translation>
+<translation id="8962950042226115166">Aizdomīga vietne</translation>
<translation id="8968766641738584599">Saglabāt karti</translation>
<translation id="8971063699422889582">Servera sertifikātam ir beidzies derīguma termiņš.</translation>
<translation id="8975012916872825179">Iekļauta tāda informācija kā tālruņa numuri, e-pasta un piegādes adreses</translation>
@@ -1470,24 +1490,24 @@ Papildu informācija:
<translation id="9035022520814077154">Drošības kļūda</translation>
<translation id="9038649477754266430">Ieteikumu pakalpojuma izmantošana ātrākai lapu ielādei</translation>
<translation id="9039213469156557790">Turklāt šajā lapā ir citi resursi, kas nav droši. Kamēr šie resursi tiek pārsūtīti, tos var aplūkot citi, kā arī uzbrucējs var tos pārveidot, lai mainītu lapas uzvedību.</translation>
+<translation id="9044359186343685026">Izmantot Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> — <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Jūs centāties piekļūt <ph name="DOMAIN" />, bet serveris piedāvāja nederīgu sertifikātu.</translation>
<translation id="9050666287014529139">Ieejas frāze</translation>
<translation id="9065203028668620118">Labot</translation>
<translation id="9065745800631924235">Teksta “<ph name="TEXT" />” meklēšana no vēstures</translation>
<translation id="9069693763241529744">Bloķēja paplašinājums</translation>
-<translation id="9076283476770535406">Vietnē var būt pieaugušajiem paredzēts saturs</translation>
<translation id="9076630408993835509">Šo pārlūku nepārvalda uzņēmums vai cita organizācija. Darbību šajā ierīcē var pārvaldīt ārpus pārlūka Chrome. <ph name="BEGIN_LINK" />Uzzināt vairāk<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Nepieciešama plašāka informācija.</translation>
<translation id="9080712759204168376">Pasūtījuma kopsavilkums</translation>
<translation id="9089260154716455634">Izslēgšanas stundu politika:</translation>
<translation id="9095388113577226029">Citas valodas…</translation>
+<translation id="9098981495403789647">Jūsu administrators pārlūkā ir iespējojis Chrome Enterprise Threat Protection. Chrome Enterprise Threat Protection var piekļūt daļai jūsu datu.</translation>
<translation id="9103872766612412690">Vietnē <ph name="SITE" /> informācijas aizsargāšanai parasti tiek izmantota šifrēšana. Kad pārlūkā Chromium tika mēģināts izveidot savienojumu ar vietni <ph name="SITE" />, šoreiz tā nosūtīja neparastus un nepareizus akreditācijas datus. Iespējams, tas notika, jo uzbrucējs mēģināja uzdoties par vietni <ph name="SITE" />, vai arī Wi-Fi pierakstīšanās ekrāns pārtrauca savienojumu. Jūsu informācija joprojām ir drošībā, jo pārlūks Chromium pārtrauca savienojumu, pirms tika veikta jebkādu datu apmaiņa.</translation>
<translation id="9106062320799175032">Norēķinu adreses pievienošana</translation>
<translation id="9114524666733003316">Notiek kartes apstiprināšana...</translation>
<translation id="9128870381267983090">Izveidot savienojumu ar tīklu</translation>
<translation id="9137013805542155359">Rādīt oriģinālo</translation>
-<translation id="9137248913990643158">Pirms šīs lietotnes izmantošanas, lūdzu, palaidiet pārlūku Chrome un pierakstieties tajā.</translation>
<translation id="9141013498910525015">Pārvaldīt adreses</translation>
<translation id="9148088599418889305">Izvēlēties nosūtīšanas veidu</translation>
<translation id="9148507642005240123">&amp;Atsaukt labojumu</translation>
diff --git a/chromium/components/strings/components_strings_ml.xtb b/chromium/components/strings/components_strings_ml.xtb
index e3d8ff0dac5..85bc6505a09 100644
--- a/chromium/components/strings/components_strings_ml.xtb
+++ b/chromium/components/strings/components_strings_ml.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">സൂചിക-5x8</translation>
<translation id="1088860948719068836">കാർഡിൽ പേര് ചേർക്കുക</translation>
<translation id="1089439967362294234">പാസ്‌വേഡ് മാറ്റുക</translation>
+<translation id="1096545575934602868">ഈ ഫീൽഡിന് <ph name="MAX_ITEMS_LIMIT" />-ൽ കൂടുതൽ എൻ‌ട്രികൾ ഉണ്ടാകരുത്. തുടർന്നുള്ള എല്ലാ എൻ‌ട്രികളും നിരസിക്കപ്പെടും.</translation>
<translation id="109743633954054152">Chrome ക്രമീകരണത്തിൽ പാസ്‌വേഡ് മാനേജ് ചെയ്യുക</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> എല്ലായ്പ്പോഴും വിവര്‍ത്തനം ചെയ്യുക </translation>
<translation id="1107591249535594099">പരിശോധിച്ചെങ്കിൽ, വേഗതയേറിയ ഫോം പൂരിപ്പിക്കലിനായി ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ കാർഡിന്റെ ഒരു പകർപ്പ് Chrome സംഭരിക്കും.</translation>
@@ -32,11 +33,12 @@
<translation id="1127259989763091435">കാർഡ് സ്ഥിരീകരിച്ച് Google അക്കൗണ്ടിലേക്ക് സംരക്ഷിക്കണോ?</translation>
<translation id="112840717907525620">നയ കാഷെ ശരി</translation>
<translation id="1131264053432022307">നിങ്ങൾ പകർത്തിയ ചിത്രം</translation>
-<translation id="1150979032973867961">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷ സർട്ടിഫിക്കറ്റിനെ നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ ഓപ്പറേറ്റിംഗ് സിസ്‌റ്റത്തിന് പരിചയമില്ല. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
+<translation id="1150979032973867961">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷ സർട്ടിഫിക്കറ്റിനെ നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ ഓപ്പറേറ്റിംഗ് സിസ്‌റ്റത്തിന് പരിചയമില്ല. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അറ്റാക്കർ നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
<translation id="1151972924205500581">പാസ്‍വേഡ് ആവശ്യമാണ്</translation>
<translation id="1152921474424827756"><ph name="URL" />-ന്‍റെ <ph name="BEGIN_LINK" />കാഷെ ചെയ്‌ത പകർപ്പ്<ph name="END_LINK" /> ആക്‌സസ് ചെയ്യുക</translation>
<translation id="1156303062776767266">ലോക്കൽ അല്ലെങ്കിൽ പങ്കിട്ട ഫയൽ ആണ് നിങ്ങൾ കാണുന്നത്</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> അപ്രതീക്ഷിതമായി കണക്ഷൻ അടച്ചു.</translation>
+<translation id="115926840831309955">നിങ്ങളുടെ CVC പരിശോധിച്ച ശേഷം വീണ്ടും ശ്രമിക്കുക അല്ലെങ്കിൽ കാലഹരണപ്പെടുന്ന തീയതി അപ്‌ഡേറ്റ് ചെയ്യുക</translation>
<translation id="1161325031994447685">Wi-Fi-ലേക്ക് വീണ്ടും കണക്റ്റുചെയ്യുന്നു</translation>
<translation id="1165039591588034296">പിശക്</translation>
<translation id="1175364870820465910">&amp;അച്ചടിക്കൂ...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"വെബിലേക്ക് സുരക്ഷിതമായി കണക്‌റ്റ് ചെയ്യുന്നതിൽ നിന്ന് Chrome-നെ നിങ്ങളുടെ കമ്പ്യൂട്ടറിലെ സോഫ്റ്റ്‌വെയർ തടയുന്നു" (Windows കമ്പ്യൂട്ടറുകളിൽ മാത്രം)</translation>
<translation id="1294154142200295408">കമാൻഡ്-ലൈൻ വ്യതിയാനങ്ങൾ</translation>
<translation id="129553762522093515">സമീപകാലത്ത് അടച്ചവ</translation>
+<translation id="1298536327547837046">മാൽവേർ സ്‌കാനിംഗ്</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />നിങ്ങളുടെ കുക്കികൾ മായ്‌ക്കുന്നത് പരീക്ഷിക്കുക<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">അവസാനിപ്പിച്ച ഫീച്ചറുകൾ</translation>
<translation id="1320233736580025032">Prc1 (എൻവലപ്പ്)</translation>
<translation id="132301787627749051">ക്ലിപ്പ്ബോർഡ് ചിത്രത്തിനായി തിരയുക</translation>
<translation id="1323433172918577554">കൂടുതൽ കാണിക്കുക</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google ഷീറ്റ്</translation>
<translation id="1527263332363067270">കണക്ഷനുവേണ്ടി കാക്കുന്നു…</translation>
<translation id="1529521330346880926">10x15 (എൻവലപ്പ്)</translation>
+<translation id="1530707389502320859">നിങ്ങൾ ഇപ്പോൾ സന്ദർശിക്കാൻ ശ്രമിച്ചത് വ്യാജ സൈറ്റാണെന്ന് തോന്നുന്നു. ചിലപ്പോൾ ചെറുതും കാണാൻ ബുദ്ധിമുട്ടുള്ളതുമായ മാറ്റങ്ങൾ URL-ൽ വരുത്തി ആക്രമണകാരികൾ സൈറ്റുകളുടെ അനുകരണ രൂപം സൃഷ്‌ടിക്കാറുണ്ട്.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">ഈ പേജ് പറയുന്നത്:</translation>
<translation id="153384715582417236">ഇപ്പോൾ ഇത്രമാത്രം ലഭ്യം</translation>
@@ -141,13 +146,13 @@
<translation id="1640244768702815859"><ph name="BEGIN_LINK" />സൈറ്റിന്റെ ഹോം പേജ് സന്ദർശിക്കുന്നത്<ph name="END_LINK" /> പരീക്ഷിച്ചുനോക്കൂ.</translation>
<translation id="1644574205037202324">ചരിത്രം</translation>
<translation id="1645368109819982629">പ്രോട്ടോക്കോൾ പിന്തുണയ്‌ക്കുന്നില്ല</translation>
-<translation id="1655462015569774233">{1,plural, =1{ഈ സെർവറിന് ഇത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് ഇന്നലെ കാലഹരണപ്പെട്ടു. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു ആക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്. നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ ക്ലോക്ക് നിലവിൽ <ph name="CURRENT_DATE" /> എന്ന് സജ്ജമാക്കി. അത് ശരിയാണോ? അല്ലെങ്കിൽ, നിങ്ങൾ സിസ്റ്റത്തിന്റെ ക്ലോക്ക് ശരിയാക്കി ഈ പേജ് പുതുക്കുക.}other{ഈ സെർവറിന് ഇത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; ഇതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് # ദിവസം മുമ്പ് കാലഹരണപ്പെട്ടു. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു ആക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്. നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ ക്ലോക്ക് നിലവിൽ <ph name="CURRENT_DATE" /> എന്ന് സജ്ജമാക്കി. അത് ശരിയാണോ? അല്ലെങ്കിൽ, നിങ്ങൾ സിസ്റ്റത്തിന്റെ ക്ലോക്ക് ശരിയാക്കി ഈ പേജ് പുതുക്കുക.}}</translation>
+<translation id="1655462015569774233">{1,plural, =1{ഈ സെർവറിന് ഇത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് ഇന്നലെ കാലഹരണപ്പെട്ടു. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു ആക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്. നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ ക്ലോക്ക് നിലവിൽ <ph name="CURRENT_DATE" /> എന്ന് സജ്ജമാക്കി. അത് ശരിയാണോ? അല്ലെങ്കിൽ, നിങ്ങൾ സിസ്റ്റത്തിന്റെ ക്ലോക്ക് ശരിയാക്കി ഈ പേജ് പുതുക്കുക.}other{ഈ സെർവറിന് ഇത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; ഇതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് # ദിവസം മുമ്പ് കാലഹരണപ്പെട്ടു. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അറ്റാക്കർ നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്. നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ ക്ലോക്ക് നിലവിൽ <ph name="CURRENT_DATE" /> എന്ന് സജ്ജമാക്കി. അത് ശരിയാണോ? അല്ലെങ്കിൽ, നിങ്ങൾ സിസ്റ്റത്തിന്റെ ക്ലോക്ക് ശരിയാക്കി ഈ പേജ് പുതുക്കുക.}}</translation>
<translation id="1656489000284462475">പിക്കപ്പ്</translation>
<translation id="1662550410081243962">പേയ്‌മെന്റ് രീതികൾ സംരക്ഷിച്ച് സ്വമേധയാ പൂരിപ്പിക്കുക</translation>
<translation id="1663943134801823270">കാർഡുകളും വിലാസങ്ങളും Chrome-ൽ നിന്നുള്ളതാണ്. നിങ്ങൾക്ക് അവ <ph name="BEGIN_LINK" />ക്രമീകരണത്തിൽ<ph name="END_LINK" /> മാനേജ് ചെയ്യാം.</translation>
<translation id="1669987054044193553">സ്ഥിരീകരിച്ച് സംരക്ഷിക്കുക</translation>
<translation id="1671391448414634642">ഇനിമുതൽ <ph name="SOURCE_LANGUAGE" /> ഭാഷയിലുള്ള പേജുകൾ <ph name="TARGET_LANGUAGE" /> ഭാഷയിലേക്ക് വിവർത്തനം ചെയ്യപ്പെടും.</translation>
-<translation id="1676269943528358898">നിങ്ങളുടെ വിവരങ്ങൾ പരിരക്ഷിക്കാൻ സാധാരണയായി <ph name="SITE" />, എൻക്രിപ്‌ഷൻ ഉപയോഗിക്കുന്നു. ഇപ്പോൾ <ph name="SITE" /> സൈറ്റിലേക്ക് കണക്‌റ്റ് ചെയ്യാൻ Google Chrome ശ്രമിച്ചപ്പോൾ, അസാധാരണമായതും തെറ്റായതുമായ ക്രെഡൻഷ്യലുകൾ വെബ്‌സൈറ്റ് തിരികെ അയച്ചു. ഒരു ആക്രമണകാരി, <ph name="SITE" /> എന്നതായി ഭാവിക്കാൻ ശ്രമിക്കുമ്പോഴോ Wi-Fi സൈൻ ഇൻ സ്‌ക്രീൻ, കണക്ഷനെ തടസ്സപ്പെടുത്തുമ്പോഴോ ആണ് ഇങ്ങനെ സംഭവിക്കാനിടയുള്ളത്. ഏതെങ്കിലും ഡാറ്റ കൈമാറുന്നതിനുമുമ്പ് Google Chrome കണക്ഷൻ അവസാനിപ്പിച്ചതിനാൽ, നിങ്ങളുടെ വിവരങ്ങൾ തുടർന്നും സുരക്ഷിതമായിരിക്കും.</translation>
+<translation id="1676269943528358898">നിങ്ങളുടെ വിവരങ്ങൾ പരിരക്ഷിക്കാൻ സാധാരണയായി <ph name="SITE" />, എൻക്രിപ്‌ഷൻ ഉപയോഗിക്കുന്നു. ഇപ്പോൾ <ph name="SITE" /> സൈറ്റിലേക്ക് കണക്‌റ്റുചെയ്യാൻ Google Chrome ശ്രമിച്ചപ്പോൾ, അസാധാരണമായതും തെറ്റായതുമായ ക്രെഡൻഷ്യലുകൾ വെബ്‌സൈറ്റ് തിരികെ അയച്ചു. ഒരു ആക്രമണകാരി, <ph name="SITE" /> എന്നതായി ഭാവിക്കാൻ ശ്രമിക്കുമ്പോഴോ Wi-Fi സൈൻ ഇൻ സ്‌ക്രീൻ, കണക്ഷനെ തടസ്സപ്പെടുത്തുമ്പോഴോ ആണ് ഇങ്ങനെ സംഭവിക്കാനിടയുള്ളത്. ഏതെങ്കിലും ഡാറ്റ കൈമാറുന്നതിനുമുമ്പ് Google Chrome കണക്ഷൻ അവസാനിപ്പിച്ചതിനാൽ, നിങ്ങളുടെ വിവരങ്ങൾ തുടർന്നും സുരക്ഷിതമായിരിക്കും.</translation>
<translation id="168841957122794586">സെർവർ സർട്ടിഫിക്കറ്റിൽ ഒരു ദുർബലമായ ഗൂഢഭാഷ കീ ഉൾപ്പെടുന്നു.</translation>
<translation id="1697532407822776718">എല്ലാം സജ്ജമായിക്കഴിഞ്ഞു!</translation>
<translation id="1703835215927279855">ലെറ്റർ</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">അനോട്ടേറ്റ് ചെയ്യാനാവുന്നതിലും വളരെ വലുതാണ് ഈ ഡോക്യുമെൻ്റ്</translation>
-<translation id="1721312023322545264">ഈ സൈറ്റ് സന്ദർശിക്കാൻ നിങ്ങൾക്ക് <ph name="NAME" /> എന്നയാളിൽ നിന്നുള്ള അനുമതി ആവശ്യമാണ്</translation>
<translation id="1721424275792716183">* ഫീൽഡ് ആവശ്യമാണ്</translation>
<translation id="1727741090716970331">സാധുവായ കാർഡ് നമ്പർ ചേർക്കുക</translation>
<translation id="1728677426644403582">നിങ്ങൾ ഒരു വെബ് പേജിന്റെ ഉറവിടമാണ് കാണുന്നത്</translation>
@@ -169,7 +173,7 @@
<translation id="1753706481035618306">പേജ് നമ്പർ</translation>
<translation id="1763864636252898013">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റിനെ നിങ്ങളുടെ ഉപകരണത്തിന്റെ ഓപ്പറേറ്റിംഗ് സിസ്‌റ്റത്തിന് പരിചയമില്ല. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Windows നെറ്റ്‌വർക്ക് ഡയഗണോസ്‌റ്റിക്‌സ് റൺ ചെയ്‌തുനോക്കൂ<ph name="END_LINK" />.</translation>
-<translation id="1783075131180517613">നിങ്ങളുടെ സമന്വയ പാസ്‌ഫ്രേസ് ദയവായി അപ്‌ഡേറ്റ് ചെയ്യുക.</translation>
+<translation id="1783075131180517613">നിങ്ങളുടെ സമന്വയ പാസ്‌ഫ്രേസ് അപ്‌ഡേറ്റ് ചെയ്യുക.</translation>
<translation id="1787142507584202372">നിങ്ങൾ നിലവിൽ തുറന്നിട്ടുള്ള ടാബുകൾ ഇവിടെ ദൃശ്യമാകും</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1800473098294731951">B9</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">നിങ്ങൾ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളും അവയിൽ ചെലവഴിക്കുന്ന സമയവും</translation>
<translation id="1826516787628120939">പരിശോധിക്കുന്നു</translation>
<translation id="1834321415901700177">ഈ സൈറ്റിൽ ദോഷകരമായ പ്രോഗ്രാമുകൾ അടങ്ങിയിരിക്കുന്നു</translation>
+<translation id="1838374766361614909">തിരയൽ മായ്ക്കുക</translation>
<translation id="1839551713262164453">നയ മൂല്യങ്ങളുടെ സാധൂകരണം പിശകുകളോടെ പരാജയപ്പെട്ടു</translation>
<translation id="1842969606798536927">പണമടയ്‌ക്കുക</translation>
<translation id="1871208020102129563">സ്ഥിരമായ പ്രോക്‌സി സെർവറുകൾ ഉപയോഗിക്കുന്നതിനായി പ്രോക്‌സി സജ്ജീകരിച്ചിരിക്കുന്നു, ഒരു .pac സ്‌ക്രിപ്റ്റ് URL ഉപയോഗിക്കുന്നതിനല്ല.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">ലിസ്റ്റ് ചുരുക്കുക</translation>
<translation id="1898423065542865115">ഫിൽട്ടർ ചെയ്യുന്നു</translation>
<translation id="1914326953223720820">അൺസിപ്പ് സേവനം</translation>
+<translation id="1915697529809968049">CVC-യ്ക്ക് പകരം ടച്ച് ഐഡി ഉപയോഗിക്കണോ?</translation>
<translation id="1916770123977586577">ഈ സൈറ്റിലേക്ക് നിങ്ങളുടെ അപ്‌ഡേറ്റ് ചെയ്ത ക്രമീകരണം ഉപയോഗിക്കുന്നതിന്, ഈ പേജ് റീലോഡ് ചെയ്യുക</translation>
<translation id="1919345977826869612">പരസ്യങ്ങള്‍</translation>
<translation id="1919367280705858090">നിർദ്ദിഷ്ട പിശക് സന്ദേശവുമായി ബന്ധപ്പെട്ട് സഹായം നേടുക</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> ബുക്ക്‌മാർക്കുകൾ</translation>
<translation id="1973335181906896915">സീരിയലൈസേഷൻ പിശക്</translation>
<translation id="1974060860693918893">നൂതനം</translation>
+<translation id="1974883374937189061">നിങ്ങൾ സന്ദർശിക്കുന്ന ചില പേജുകളുടെ <ph name="BEGIN_WHITEPAPER_LINK" />URL, പരിമിത സിസ്‌റ്റം വിവരങ്ങൾ, ചില പേജുകളുടെ ഉള്ളടക്കം<ph name="END_WHITEPAPER_LINK" /> എന്നിവ Google-ലേക്ക് അയച്ച് Chrome സുരക്ഷ മെച്ചപ്പെടുത്താൻ സഹായിക്കുക. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">ഫേംവെയർ പതിപ്പ്</translation>
<translation id="1981206234434200693">Chrome-ന്‍റെ ബ്രൗസിംഗ് ചരിത്ര ഡാറ്റ മായ്‌ക്കുക</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{കൂടാതെ 1 കൂടി}other{എന്നിവയും # എണ്ണവും കൂടി}}</translation>
@@ -231,7 +238,7 @@
<translation id="2147827593068025794">പശ്ചാത്തലം സമന്വയിപ്പിക്കൽ</translation>
<translation id="2148613324460538318">കാർഡ് ചേർക്കുക</translation>
<translation id="2154054054215849342">നിങ്ങളുടെ ഡൊമെയ്‌നിന് വേണ്ടി സമന്വയം ലഭ്യമല്ല</translation>
-<translation id="2154484045852737596">കാർഡ് എഡിറ്റുചെയ്യുക</translation>
+<translation id="2154484045852737596">കാർഡ് എഡിറ്റ് ചെയ്യുക</translation>
<translation id="2166049586286450108">പൂർണ്ണമായ അഡ്‌മിൻ ആക്‌സസ്</translation>
<translation id="2166378884831602661">ഈ സൈറ്റിന് സുരക്ഷിതമായ കണക്ഷൻ നൽകാനാകില്ല</translation>
<translation id="2169984857010174799">കാകു2 (എൻവലപ്പ്)</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">കാലഹരണപ്പെടുന്ന ശരിയായ വർഷം നല്‍കുക</translation>
<translation id="2212735316055980242">നയം കണ്ടെത്തിയില്ല</translation>
<translation id="2213606439339815911">എൻട്രികൾ ലഭ്യമാക്കുന്നു...</translation>
+<translation id="2215727959747642672">ഫയൽ എഡിറ്റ് ചെയ്യൽ</translation>
<translation id="2218879909401188352">നിലവിൽ <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്നതിലുള്ള അക്രമികൾക്ക് നിങ്ങളുടെ ഉപകരണം കേടുവരുത്തുന്ന ആപ്പുകൾ ഇൻസ്‌റ്റാൾ ചെയ്യാനോ മൊബൈൽ ബില്ലിലേക്ക് നിങ്ങളറിയാതെ നിരക്കുകൾ ചേർക്കാനോ നിങ്ങളുടെ വ്യക്തിഗത വിവരങ്ങൾ മോഷ്‌ടിക്കാനോ കഴിയും. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ഇന്റർനെറ്റ് ഇല്ല</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />ഡയഗണോസ്‌റ്റിക്‌സ് ആപ്പ്<ph name="END_LINK" /> ഉപയോഗിച്ച് കണകഷൻ പ്രശ്‌നം പരിഹരിക്കുക</translation>
<translation id="2239100178324503013">ഇപ്പോൾ അയയ്‌ക്കുക</translation>
+<translation id="2248949050832152960">WebAuthn ഉപയോഗിക്കുക</translation>
<translation id="225207911366869382">ഈ നയത്തിൽനിന്ന് ഈ മൂല്യം ഇല്ലാതാക്കി.</translation>
<translation id="2257315177824333709">ക്ഷമിക്കണം, നിങ്ങളുടെ കാർഡ് ഇപ്പോൾ സംരക്ഷിക്കാനാവില്ല.</translation>
<translation id="2262243747453050782">HTTP പിശക്</translation>
@@ -253,11 +262,11 @@
<translation id="2270484714375784793">ഫോൺ നമ്പർ</translation>
<translation id="2277103315734023688">മുന്നോട്ട് നീക്കുക</translation>
<translation id="2283340219607151381">വിലാസങ്ങൾ സംരക്ഷിച്ച് സ്വമേധയാ പൂരിപ്പിക്കുക</translation>
-<translation id="2292556288342944218">നിങ്ങളുടെ ഇന്‍റർനെറ്റ് ആക്‌സസ് തടഞ്ഞു</translation>
+<translation id="2292556288342944218">നിങ്ങളുടെ ഇന്റർനെറ്റ് ആക്‌സസ്സ് ബ്ലോക്ക് ചെയ്‌തു</translation>
<translation id="2297722699537546652">B5 (എൻവലപ്പ്)</translation>
<translation id="2310021320168182093">Chou2 (എൻവലപ്പ്)</translation>
<translation id="2316887270356262533">1 MB-യിൽ കുറഞ്ഞ ഡാറ്റ ലാഭിക്കുന്നു. അടുത്തതവണ നിങ്ങൾ സന്ദർശിക്കുമ്പോൾ ചില സൈറ്റുകൾ ഇതിനേക്കാൾ പതുക്കെ ലോഡാകാം.</translation>
-<translation id="2317259163369394535"><ph name="DOMAIN" /> ഡൊമെയ്‌ന് ഉപയോക്തൃനാമവും പാസ്‌വേഡും ആവശ്യമാണ്.</translation>
+<translation id="2317259163369394535"><ph name="DOMAIN" /> ഡൊമെയ്‌ന് ഒരു ഉപയോക്തൃനാമവും പാസ്‌വേഡും വേണം.</translation>
<translation id="2317583587496011522">ഡെബിറ്റ് കാർഡുകൾ സ്വീകരിക്കുന്നു.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" />-ന് കാലഹരണപ്പെടുന്നു</translation>
<translation id="2337852623177822836">ക്രമീകരണം നിയന്ത്രിക്കുന്നത് നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്ററാണ്</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">തിരയൽ URL അസാധുവാണ്.</translation>
<translation id="2482878487686419369">വിജ്ഞാപനങ്ങള്‍‌</translation>
<translation id="248348093745724435">മെഷീന്‍ നയങ്ങള്‍</translation>
-<translation id="2485387744899240041">നിങ്ങളുടെ ഉപകരണത്തിനും ബ്രൗസറിനുമുള്ള ഉപയോക്തൃനാമങ്ങൾ</translation>
<translation id="2491120439723279231">സെർവറിന്റെ സർട്ടിഫിക്കറ്റിൽ പിശകുകൾ ഉണ്ട്.</translation>
<translation id="2493640343870896922">ലെറ്റർ-പ്ലസ്</translation>
<translation id="2495083838625180221">JSON പാർസർ</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">പിന്നോട്ട് പോകുക</translation>
<translation id="2503184589641749290">ഡെബിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും സ്വീകരിക്കുന്നു</translation>
<translation id="2505268675989099013">അക്കൗണ്ട് പരിരക്ഷിക്കുക</translation>
+<translation id="2515335152965840738">അവഗണിക്കുക</translation>
<translation id="2515629240566999685">നിങ്ങളുടെ ഏരിയയിലെ സിഗ്‌നൽ പരിശോധിക്കുന്നു</translation>
<translation id="2523886232349826891">ഈ ഉപകരണത്തിൽ മാത്രം സംരക്ഷിക്കപ്പെടും</translation>
<translation id="2524461107774643265">കൂടുതൽ വിവരങ്ങൾ ചേർക്കുക</translation>
@@ -311,7 +320,7 @@
<translation id="2556876185419854533">&amp;എഡിറ്റുചെയ്യുന്നത് പഴയപടിയാക്കുക</translation>
<translation id="2586657967955657006">ക്ലിപ്പ്ബോർഡ്</translation>
<translation id="2587730715158995865"><ph name="ARTICLE_PUBLISHER" /> എന്നയാളുടെ ലേഖനം. ഇതും മറ്റ് <ph name="OTHER_ARTICLE_COUNT" /> ലേഖനങ്ങളും വായിക്കുക.</translation>
-<translation id="2587841377698384444">ഡയറക്‌റ്ററി API ഐഡി:</translation>
+<translation id="2587841377698384444">ഡയറക്‌ടറി API ഐഡി:</translation>
<translation id="2595719060046994702">ഏതെങ്കിലും കമ്പനിയോ മറ്റ് സ്ഥാപനമോ മാനേജ് ചെയ്യുന്നതല്ല ഈ ഉപകരണവും അക്കൗണ്ടും.</translation>
<translation id="2597378329261239068">ഈ പ്രമാണം പാസ്‌വേഡ് പരിരക്ഷിതമാണ്. പാസ്‌വേഡ് നല്‍‌കുക.</translation>
<translation id="2609632851001447353">വേരിയേഷനുകൾ</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">സമര്‍പ്പിക്കൂ</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{ഒന്നുമില്ല}=1{<ph name="DOMAIN_LIST" /> എന്നതിനുള്ള ഒരു പാസ്‌വേഡ്}=2{<ph name="DOMAIN_LIST" /> എന്നതിനുള്ള 2 പാസ്‌വേഡുകൾ}other{<ph name="DOMAIN_LIST" /> എന്നതിനുള്ള # പാസ്‌വേഡുകൾ}}</translation>
<translation id="2666117266261740852">മറ്റ് ടാബുകളോ ആപ്‌സുകളോ അടയ്‌ക്കുക</translation>
-<translation id="267371737713284912">പഴയപടിയാക്കാൻ <ph name="MODIFIER_KEY_DESCRIPTION" /> അമർത്തുക</translation>
<translation id="2674170444375937751">നിങ്ങളുടെ ചരിത്രത്തില്‍ നിന്നും ഈ പേജുകള്‍ മായ്ക്കുന്നതിന് നിങ്ങള്‍ താല്പര്യമുണ്ടോ?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">ഉപേക്ഷിക്കുക</translation>
@@ -333,13 +341,13 @@
<translation id="2702801445560668637">വായനാ ലിസ്റ്റ്</translation>
<translation id="2704283930420550640">മൂല്യം ഫോർമാറ്റുമായി പൊരുത്തപ്പെടുന്നില്ല.</translation>
<translation id="2705137772291741111">ഈ സൈറ്റിന്റെ സംരക്ഷിച്ച (കാഷെ ചെയ്‌ത) പതിപ്പ് വായിക്കാനാകാത്തതാണ്.</translation>
-<translation id="2709516037105925701">ഓട്ടോഫില്‍</translation>
-<translation id="2712173769900027643">അനുമതി ചോദിക്കുക</translation>
+<translation id="2709516037105925701">സ്വയമേവ പൂരിപ്പിക്കൽ</translation>
<translation id="2713444072780614174">വെള്ള</translation>
<translation id="2720342946869265578">സമീപമുള്ളവ</translation>
<translation id="2721148159707890343">അഭ്യർത്ഥന വിജയിച്ചു</translation>
<translation id="2728127805433021124">ഒരു ദുർബ്ബല സിഗ്‌നേച്ചർ അൽഗോരിതം ഉപയോഗിച്ച് സെർവറിന്റെ സർട്ടിഫിക്കറ്റ് സൈൻ ചെയ്‌തു.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />കണക്‌റ്റിവിറ്റി ഡയഗണോസ്‌റ്റിക്‌സ് റൺ ചെയ്യുന്നു<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">ഈ ഫീച്ചറുകൾ പ്രവർത്തനക്ഷമമാക്കുന്നതിലൂടെ, നിങ്ങളുടെ ബ്രൗസർ ഡാറ്റ നഷ്‌ടമാകുകയോ സുരക്ഷയ്‌ക്കോ സ്വകാര്യതയ്‌ക്കോ ഭീഷണി ഉയരുകയോ ചെയ്‌തേക്കാം. ഈ ബ്രൗസറിന്റെ എല്ലാ ഉപയോക്താക്കൾക്കും പ്രവർത്തനക്ഷമമാക്കിയ ഫീച്ചറുകൾ ബാധകമാണ്.</translation>
<translation id="2735043616039983645">ഈ നയത്തിന് വിരുദ്ധ മൂല്യങ്ങളുള്ള ഒന്നിലധികം ഉറവിടങ്ങളുണ്ട്!</translation>
<translation id="2738330467931008676">പിക്കപ്പ് വിലാസം തിരഞ്ഞെടുക്കുക</translation>
<translation id="2740531572673183784">ശരി</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">കണക്ഷന്‍ പുനഃസജ്ജമാക്കിയതാണ്.</translation>
<translation id="2788784517760473862">ക്രെഡിറ്റ് കാർഡുകൾ സ്വീകരിക്കുന്നു</translation>
<translation id="2792012897584536778">ഈ ഉപകരണത്തിന്റെ അഡ്‌മിൻമാർ സുരക്ഷാ സർട്ടിഫിക്കറ്റുകൾ സജ്ജീകരിച്ചിട്ടുണ്ട്, നിങ്ങൾ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളുടെ ഉള്ളടക്കം കാണാൻ അവ അവരെ അനുവദിച്ചേക്കാം.</translation>
-<translation id="2794233252405721443">സൈറ്റ് ബ്ലോക്ക് ചെയ്‌തു</translation>
<translation id="2799020568854403057">നിങ്ങൾ പോകുന്ന സൈറ്റിൽ ദോഷകരമായ ആപ്പുകളുണ്ട്</translation>
<translation id="2799223571221894425">വീണ്ടും സമാരംഭിക്കുക</translation>
<translation id="2803306138276472711"><ph name="SITE" /> എന്നതിൽ Google സുരക്ഷിത ബ്രൗസിംഗ് ഈയിടെ <ph name="BEGIN_LINK" />മാൽവെയർ കണ്ടെത്തി<ph name="END_LINK" />. സാധാരണ നിലയിൽ സുരക്ഷിതമായ വെബ്സൈറ്റുകളിൽ ചിലപ്പോൾ മാൽവെയർ ഉണ്ടായേക്കാം.</translation>
+<translation id="2815364696811431560">സൈറ്റ് വിടുക</translation>
<translation id="2824775600643448204">വിലാസവും തിരയൽ ബാറും</translation>
<translation id="2826760142808435982"><ph name="CIPHER" /> ഉപയോഗിച്ച് കണക്ഷൻ എൻക്രിപ്‌റ്റുചെയ്‌ത് പ്രാമാണീകരിക്കുന്നു, ഒപ്പം പ്രധാന എക്‌സേഞ്ച് മെക്കാനിസമായി <ph name="KX" /> ഉപയോഗിക്കുന്നു.</translation>
<translation id="2835170189407361413">ഫോം മായ്‌ക്കുക</translation>
<translation id="2847118875340931228">അദൃശ്യ വിൻഡോ തുറക്കുക</translation>
<translation id="2850739647070081192">ക്ഷണം (എൻവലപ്പ്)</translation>
-<translation id="2851634818064021665">ഈ സൈറ്റ് സന്ദർശിക്കാൻ നിങ്ങൾക്ക് അനുമതി ആവശ്യമാണ്</translation>
<translation id="2856444702002559011"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്നതിൽ നിന്ന് നിങ്ങളുടെ വിവരം മോഷ്‌ടിക്കാൻ അക്രമികൾ ശ്രമിക്കുന്നുണ്ടാവാം (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, അല്ലെങ്കിൽ ക്രെഡിറ്റ് കാർഡുകൾ). <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">കാർഡ് സംരക്ഷിക്കണോ?</translation>
@@ -381,9 +388,10 @@
<translation id="2972581237482394796">&amp;വീണ്ടും ചെയ്യുക</translation>
<translation id="2977665033722899841"><ph name="ROW_NAME" />, നിലവിൽ തിരഞ്ഞെടുത്തു. <ph name="ROW_CONTENT" /></translation>
<translation id="2982481275546140226">ഡാറ്റ മായ്‌ക്കുക</translation>
-<translation id="2985306909656435243">പ്രവർത്തനക്ഷമമാക്കിയെങ്കിൽ, വേഗത്തിൽ ഫോം പൂരിപ്പിക്കാൻ Chromium ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ കാർഡിന്റെ ഒരു പകർപ്പ് സൂക്ഷിക്കും.</translation>
+<translation id="2985306909656435243">പ്രവർത്തനക്ഷമമാക്കിയെങ്കിൽ, വേഗത്തിൽ ഫോം പൂരിപ്പിക്കാൻ Chromium ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ കാർഡിന്റെ പകർപ്പ് സൂക്ഷിക്കും.</translation>
<translation id="2985398929374701810">ശരിയായ വിലാസം നല്‍കുക</translation>
<translation id="2986368408720340940">ഈ പിക്കപ്പ് രീതി ലഭ്യമല്ല. മറ്റൊരു രീതി പരീക്ഷിക്കുക.</translation>
+<translation id="2987034854559945715">പൊരുത്തപ്പെടുന്ന ഫീച്ചറുകളൊന്നുമില്ല</translation>
<translation id="2991174974383378012">വെബ്‌സൈറ്റുകളുമായി പങ്കിടുന്നു</translation>
<translation id="2991571918955627853">വെബ്‌സൈറ്റ് HSTS ഉപയോഗിക്കുന്നതിനാൽ നിങ്ങൾക്ക് ഇപ്പോൾ <ph name="SITE" /> സന്ദർശിക്കാനാകില്ല. നെറ്റ്‌വർക്ക് പിശകുകളും ആക്രമണങ്ങളും സാധാരണയായി താൽക്കാലിക പ്രശ്‌നങ്ങളായതിനാൽ ഈ പേജ് മിക്കവാറും പിന്നീട് പ്രവർത്തിക്കും.</translation>
<translation id="3005723025932146533">സംരക്ഷിച്ച പകർപ്പ് കാണിക്കുക</translation>
@@ -394,9 +402,10 @@
<translation id="3024663005179499861">തെറ്റായ നയ തരം</translation>
<translation id="3037605927509011580">കഷ്ടം!</translation>
<translation id="3041612393474885105">സര്‍‌ട്ടിഫിക്കറ്റ് വിവരങ്ങള്‍‌</translation>
+<translation id="3057676462092457419">DnsOverHttps മോഡ് <ph name="SECURE_DNS_MODE_SECURE" /> ഇപ്പോഴും പിന്തുണയ്‌ക്കുന്നില്ല, <ph name="SECURE_DNS_MODE_OFF" /> എന്നതിലേക്ക് മോഡ് സജ്ജീകരിച്ചു.</translation>
<translation id="3060227939791841287">C9 (എൻവലപ്പ്)</translation>
<translation id="3061707000357573562">പാച്ച് സേവനം</translation>
-<translation id="3064966200440839136">ഒരു എക്‌സ്‌റ്റേണൽ അപ്ലിക്കേഷൻ വഴി പണമടയ്‌ക്കാൻ അദൃശ്യ മോഡ് ഒഴിവാക്കുന്നു. തുടരണോ?</translation>
+<translation id="3064966200440839136">ബാഹ്യ ആപ്പ് വഴി പണമടയ്‌ക്കാൻ അദൃശ്യ മോഡ് ഒഴിവാക്കുന്നു. തുടരണോ?</translation>
<translation id="3095940652251934233">പ്രസ്‌താവന</translation>
<translation id="3096100844101284527">പിക്കപ്പ് വിലാസം ചേർക്കുക</translation>
<translation id="3105172416063519923">അസറ്റ് ഐഡി:</translation>
@@ -413,11 +422,12 @@
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ഐലന്‍ഡ്</translation>
<translation id="3176929007561373547">പ്രോക്‌സി സെർവർ പ്രവർത്തിക്കുന്നുവെന്ന് ഉറപ്പാക്കാൻ
- നിങ്ങളുടെ പ്രോക്‌സി ക്രമീകരണം പരിശോധിക്കുകയോ നെറ്റ്‌വർക്ക് അഡ്‌മിനിസ്‌ട്രേറ്ററെ ബന്ധപ്പെടുകയോ ചെയ്യുക. നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഒരു പ്രോക്‌സി സെർവറാണെന്ന് കരുതുന്നില്ലെങ്കിൽ:
+ നിങ്ങളുടെ പ്രോക്‌സി ക്രമീകരണം പരിശോധിക്കുകയോ നെറ്റ്‌വർക്ക് അഡ്‌മിനെ ബന്ധപ്പെടുകയോ ചെയ്യുക. നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഒരു പ്രോക്‌സി സെർവറാണെന്ന് കരുതുന്നില്ലെങ്കിൽ:
<ph name="PLATFORM_TEXT" /></translation>
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> എന്നതിലെ <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">പേയ്‌മെന്റ് റദ്ദാക്കുക</translation>
<translation id="3207960819495026254">ബുക്ക്‌മാർക്കുചെയ്‌തു</translation>
+<translation id="3209034400446768650">പേജ് പണം ഈടാക്കിയേക്കാം</translation>
<translation id="3225919329040284222">ബിൽട്ട്-ഇൻ പ്രതീക്ഷകള്‍ക്ക് പൊരുത്തപ്പെടാത്ത സര്‍ട്ടിഫിക്കറ്റാണ് സെര്‍വര്‍ അവതരിപ്പിച്ചത്. നിങ്ങളെ സംരക്ഷിക്കുന്നതിലേക്കായുള്ള നിശ്ചിത, ഉന്നത-സുരക്ഷാ വെബ്‌സൈറ്റുകൾക്കായാണ് ഈ പ്രതീക്ഷകൾ ഉൾപ്പെടുത്തിയിരിക്കുന്നത്.</translation>
<translation id="3226128629678568754">പേജ് ലോഡ് ചെയ്യുന്നതിനാവശ്യമായ ഡാറ്റ വീണ്ടും സമർപ്പിക്കാൻ വീണ്ടും ലോഡ് ചെയ്യുക ബട്ടൺ അമർത്തുക.</translation>
<translation id="3227137524299004712">മൈക്രോഫോൺ</translation>
@@ -425,7 +435,6 @@
<translation id="3229041911291329567">നിങ്ങളുടെ ഉപകരണത്തെയും ബ്രൗസറിനെയും കുറിച്ചുള്ള പതിപ്പ് വിവരങ്ങൾ</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" />-ന്‍റെ CVC നൽകുക</translation>
<translation id="3234666976984236645">ഈ സൈറ്റിൽ എപ്പോഴും പ്രധാന ഉള്ളടക്കം കണ്ടെത്തുക</translation>
-<translation id="3254409185687681395">ഈ പേജ് ബുക്‌മാര്‍ക്ക് ചെയ്യുക</translation>
<translation id="3270847123878663523">&amp;പുനഃക്രമീകരിക്കുന്നത് പഴയപടിയാക്കുക</translation>
<translation id="3274521967729236597">പാ-കായ്</translation>
<translation id="3282497668470633863">കാർഡിൽ പേര് ചേർക്കുക</translation>
@@ -435,7 +444,6 @@
<translation id="3320021301628644560">ബില്ലിംഗ് വിലാസം ചേർക്കുക</translation>
<translation id="3324983252691184275">ക്രിംസൺ</translation>
<translation id="3338095232262050444">സുരക്ഷിതം</translation>
-<translation id="3345135638360864351">ഈ സൈറ്റ് ആക്‌സസ് ചെയ്യാനുള്ള നിങ്ങളുടെ അഭ്യർത്ഥന, <ph name="NAME" /> എന്നയാൾക്ക് അയയ്‌ക്കാനായില്ല. വീണ്ടും ശ്രമിക്കുക.</translation>
<translation id="3355823806454867987">പ്രോക്സി ക്രമീകരണങ്ങള്‍ മാറ്റുക...</translation>
<translation id="3361596688432910856">Chrome ഇനിപ്പറയുന്ന വിവരങ്ങൾ <ph name="BEGIN_EMPHASIS" />സംരക്ഷിക്കില്ല<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -449,7 +457,7 @@
<translation id="337363190475750230">ഡിപ്രൊവിഷൻ ചെയ്‌തു</translation>
<translation id="3377188786107721145">നയം പാഴ്‌സുചെയ്യുന്നതിൽ പിശക്</translation>
<translation id="3380365263193509176">അജ്ഞാതമായ പിശക്</translation>
-<translation id="3380864720620200369">ക്ലയന്റ് ID:</translation>
+<translation id="3380864720620200369">ക്ലയന്റ് ഐഡി:</translation>
<translation id="3387261909427947069">പേയ്‌മെന്റ് രീതികൾ</translation>
<translation id="3391030046425686457">ഡെലിവർ ചെയ്യേണ്ട വിലാസം</translation>
<translation id="3395827396354264108">പിക്കപ്പ് രീതി</translation>
@@ -469,18 +477,15 @@
<translation id="3462200631372590220">വിപുലമായവ മറയ്ക്കുക</translation>
<translation id="3467763166455606212">കാർഡ് ഉടമയുടെ പേര് ആവശ്യമാണ്</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> നിലവിൽ തുറന്നിരിക്കുന്നു, തുറന്നിരിക്കുന്ന ടാബിലേക്ക് പോകാൻ, 'ടാബ്' അമർത്തിയ ശേഷം എൻ്റർ അമർത്തുക</translation>
-<translation id="3479539252931486093">ഇത് അപ്രതീക്ഷിതമായിരുന്നോ? <ph name="BEGIN_LINK" />ഞങ്ങളെ അറിയിക്കുക<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">ഇപ്പോഴല്ല</translation>
<translation id="3484560055331845446">നിങ്ങളുടെ Google അക്കൗണ്ടിലേക്കുള്ള ആക്‌സസ് നഷ്‌ടപ്പെടാനിടയുണ്ട്. ഇപ്പോൾ തന്നെ പാസ്‌വേഡ് മാറ്റാൻ Chrome ശുപാർശ ചെയ്യുന്നു. സൈൻ ഇൻ ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.</translation>
<translation id="3495081129428749620">പേജിൽ കണ്ടെത്തുക
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">ഇപ്പോൾ ഞങ്ങൾക്ക് നിങ്ങളുടെ രക്ഷകർത്താവിനെ ബന്ധപ്പെടാനായില്ല. വീണ്ടും ശ്രമിക്കുക.</translation>
<translation id="3512163584740124171">ഇതേ നയ ഗ്രൂപ്പിൽ നിന്നുള്ള മറ്റൊരു നയത്തിന് ഉയർന്ന മുൻഗണനയുള്ളതിനാൽ ഈ നയം അവഗണിച്ചു.</translation>
<translation id="3528171143076753409">സെർവറിന്റെ സർട്ടിഫിക്കറ്റ് വിശ്വസനീയമല്ല.</translation>
<translation id="3528485271872257980">ഇരുണ്ട തവിട്ട് നിറം</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{സമന്വയിപ്പിച്ച ഉപകരണങ്ങളിൽ ഒരു ഇനമെങ്കിലും}=1{ഒരു ഇനം (ഒപ്പം സമന്വയിപ്പിച്ച ഉപകരണങ്ങളിൽ അതിൽ കൂടുതലും)}other{# ഇനങ്ങൾ (ഒപ്പം സമന്വയിപ്പിച്ച ഉപകരണങ്ങളിൽ അതിൽ കൂടുതലും)}}</translation>
<translation id="3539171420378717834">ഈ ഉപകരണത്തിൽ ഈ കാർഡിന്റെ ഒരു പകർപ്പ് സൂക്ഷിക്കുക</translation>
-<translation id="3556433843310711081">നിങ്ങൾക്ക് വേണ്ടി ഇത് അൺബ്ലോക്കുചെയ്യാൻ മാനേജർക്ക് കഴിയും</translation>
<translation id="3566021033012934673">നിങ്ങളുടെ കണക്ഷൻ സ്വകാര്യമല്ല</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> സൈറ്റിലെ ഉൾച്ചേർത്ത പേജ് പറയുന്നത്:</translation>
@@ -508,6 +513,7 @@
<translation id="3678529606614285348">പുതിയ അദൃശ്യ വിൻഡോയിൽ പേജ് തുറക്കുക (കൺട്രോൾ-ഷിഫ്റ്റ്-N)</translation>
<translation id="3679803492151881375">ക്രാഷ് റിപ്പോർട്ട് <ph name="CRASH_TIME" />-ന് ക്യാപ്‌ചർ ചെയ്‌ത്, <ph name="UPLOAD_TIME" />-ന് അപ്‌ലോഡുചെയ്‌തു</translation>
<translation id="3681007416295224113">സര്‍‌ട്ടിഫിക്കറ്റ് വിവരങ്ങള്‍‌</translation>
+<translation id="3701427423622901115">റീസെറ്റ് അംഗീകരിച്ചിരിക്കുന്നു</translation>
<translation id="3704162925118123524">നിങ്ങൾ ഉപയോഗിക്കുന്ന നെറ്റ്‌വർക്കിനായി, ഇതിന്റെ ലോഗിൻ പേജ് സന്ദർശിക്കേണ്ടിവരാം.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">ലോഡ്ചെയ്യുന്നു...</translation>
@@ -524,6 +530,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്ന സൈറ്റിലെ ആക്രമികൾ, സോഫ്‌റ്റ്‌വയറുകൾ ഇൻസ്‌റ്റാൾ ചെയ്യുന്നതോ, അല്ലെങ്കിൽ നിങ്ങളുടെ സ്വകാര്യ വിവരങ്ങൾ വെളിപ്പെടുത്തുന്നതോ (ഉദാഹരണത്തിന് പാസ്‌വേഡുകൾ, ഫോൺ നമ്പറുകൾ അല്ലെങ്കിൽ ക്രഡിറ്റ് ‌കാർഡുകൾ) പോലെയുള്ള അപകടകരമായ കാര്യങ്ങൾ ചെയ്യിപ്പിക്കുന്ന രീതിയിൽ നിങ്ങളെ കബളിപ്പിച്ചേക്കാം. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">ഒരു സെര്‍വര്‍ പിശക് കാരണം വിവര്‍‌ത്തനം പരാജയപ്പെട്ടു.</translation>
<translation id="3759461132968374835">നിങ്ങള്‍ക്ക് സമീപകാലത്ത് റിപ്പോര്‍ട്ട് ചെയ്ത ക്രാഷുകളൊന്നുമില്ല. ക്രാഷ് റിപ്പോര്‍ട്ട് ചെയ്യുന്ന സമയത്ത് സംഭവിച്ച ക്രാഷുകളെ അപ്രാപ്തമാക്കി, ഇവിടെ ദൃശ്യമാകില്ല.</translation>
+<translation id="3760561303380396507">CVC-യ്ക്ക് പകരം Windows Hello ഉപയോഗിക്കണോ?</translation>
<translation id="3761718714832595332">സ്‌റ്റാറ്റസ് മറയ്ക്കുക</translation>
<translation id="3765032636089507299">സുരക്ഷിത ബ്രൗസിംഗ് പേജ് നിർമ്മാണത്തിലാണ്.</translation>
<translation id="3778403066972421603">ഈ കാർഡ് നിങ്ങളുടെ Google അക്കൗണ്ടിലും ഈ ഉപകരണത്തിലും സംരക്ഷിക്കണോ?</translation>
@@ -533,6 +540,7 @@
<translation id="3789155188480882154">വലുപ്പം 16</translation>
<translation id="3797522431967816232">Prc3 (എൻവലപ്പ്)</translation>
<translation id="3807873520724684969">ദോഷകരമായ ഉള്ളടക്കം ബ്ലോക്ക് ചെയ്‌തു.</translation>
+<translation id="3808375843007691220">മുന്നറിയിപ്പ്: പരീക്ഷണാത്മക ഫീച്ചറുകൾ കണ്ടേക്കാം, ജാഗ്രത പുലർത്തുക!</translation>
<translation id="3810973564298564668">മാനേജ് ചെയ്യുക</translation>
<translation id="382518646247711829">നിങ്ങൾ ഒരു പ്രോക്‌സി സെർവർ ഉപയോഗിക്കുന്നെങ്കിൽ...</translation>
<translation id="3828924085048779000">പാസ്ഫ്രെയ്‍സ് പൂരിപ്പിക്കാതിരിക്കാനാവില്ല.</translation>
@@ -541,11 +549,11 @@
<translation id="3858027520442213535">തീയതിയും സമയവും അപ്‌ഡേറ്റ് ചെയ്യുക</translation>
<translation id="3884278016824448484">വിരുദ്ധ ഉപകരണ ഐഡന്റിഫയർ</translation>
<translation id="3885155851504623709">പാരിഷ്</translation>
-<translation id="3886446263141354045"><ph name="NAME" /> എന്നയാൾക്ക് ഈ സൈറ്റ് ആക്‌സസ് ചെയ്യാനുള്ള നിങ്ങളുടെ അഭ്യർത്ഥന അയച്ചു</translation>
<translation id="3890664840433101773">ഇമെയില്‍‌ ചേര്‍‌ക്കുക</translation>
<translation id="3901925938762663762">കാർഡ് കാലഹരണപ്പെട്ടു</translation>
<translation id="3906600011954732550">B5-അധികം</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVC-യ്ക്ക് പകരം WebAuthn ഉപയോഗിക്കണോ?</translation>
<translation id="3946209740501886391">ഈ സൈറ്റിൽ എല്ലായ്‌പ്പോഴും ചോദിക്കുക</translation>
<translation id="3949571496842715403">ഈ സെർവറിന് ഇത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് വിഷയേതര നാമങ്ങൾ വ്യക്തമാക്കുന്നില്ല. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
<translation id="3949601375789751990">നിങ്ങളുടെ ബ്രൗസിംഗ് ചരിത്രം ഇവിടെ ദൃശ്യമാകും</translation>
@@ -556,11 +564,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ഒന്നുമില്ല}=1{ഒരു സൈറ്റിൽ നിന്ന് }other{# സൈറ്റുകളിൽ നിന്ന് }}</translation>
<translation id="397105322502079400">കണക്കാക്കുന്നു...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ബ്ലോക്കുചെയ്‌തിരിക്കുന്നു</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> നിങ്ങളുടെ ബ്രൗസറിൽ Chrome എന്റർപ്രൈസ് ഭീഷണി പരിരക്ഷ പ്രവർത്തനക്ഷമമാക്കി. Chrome എന്റർപ്രൈസ് ഭീഷണി പരിരക്ഷയ്‌ക്ക് നിങ്ങളുടെ ചില ഡാറ്റയിലേക്ക് ആക്‌സസുണ്ട്.</translation>
<translation id="3987940399970879459">ഒരു MB-യിൽ കുറവാണ്</translation>
<translation id="40103911065039147">{URL_count,plural, =1{സമീപത്ത് ഒരു വെബ്‌ പേജുണ്ട്}other{സമീപത്ത് # വെബ്‌ പേജുകളുണ്ട്}}</translation>
<translation id="4030383055268325496">&amp;ചേർത്തത് പഴയപടിയാക്കുക</translation>
<translation id="4032320456957708163">നിങ്ങളുടെ ബ്രൗസർ മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" /> ആണ്</translation>
-<translation id="4034375457890803692">സാധാരണയായി സന്ദർശിക്കാത്ത സൈറ്റിലേക്കാണ് നിങ്ങൾ തുറന്ന ലിങ്ക് പോകുന്നത്. ഇത് നിങ്ങളെ ആശയക്കുഴപ്പത്തിലാക്കിയേക്കാം.</translation>
<translation id="4058922952496707368">കീ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (എൻവലപ്പ്)</translation>
<translation id="4067947977115446013">ശരിയായ വിലാസം ചേർക്കുക</translation>
@@ -573,6 +581,7 @@
<translation id="4103249731201008433">ഉപകരണ സീരിയൽ നമ്പർ അസാധുവാണ്</translation>
<translation id="410351446219883937">സ്വയം പ്ലേചെയ്യൽ</translation>
<translation id="4103763322291513355">ബ്ലാക്ക്‌ലിസ്റ്റിൽപ്പെട്ട URL-കളുടെ ലിസ്റ്റും നിങ്ങളുടെ സിസ്റ്റം അഡ്‌മിനിസ്‌ട്രേറ്റർ നടപ്പിലാക്കിയ മറ്റ് നയങ്ങളും കാണുന്നതിന് &lt;strong&gt;chrome://policy&lt;/strong&gt; സന്ദർശിക്കുക.</translation>
+<translation id="4108231218301530806">ഈ കാർഡ് അടുത്ത തവണ പരിശോധിച്ചുറപ്പിക്കാൻ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക.</translation>
<translation id="4110652170750985508">നിങ്ങളുടെ പേയ്‌മെന്‍റ് അവലോകനം ചെയ്യുക</translation>
<translation id="4112140312785995938">പുറകിലേക്ക് നീക്കുക</translation>
<translation id="4116663294526079822">ഈ സൈറ്റിൽ എല്ലായ്‌പ്പോഴും അനുവദിക്കുക</translation>
@@ -587,6 +596,7 @@
<translation id="4171400957073367226">മോശം പരിശോധിച്ചുറപ്പിക്കൽ സിഗ്‌നേച്ചർ</translation>
<translation id="4173315687471669144">ഫൂൾസ്‌‌കേപ്പ്</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> ഇനം കൂടി}other{<ph name="ITEM_COUNT" /> ഇനങ്ങൾ കൂടി}}</translation>
+<translation id="4176463684765177261">അപ്രാപ്തമാക്കി</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">അടുത്ത തവണ കൂടുതൽ വേഗത്തിൽ പണമടയ്ക്കാൻ കാർഡ്, ബില്ലിംഗ് വിലാസം എന്നിവ നിങ്ങളുടെ Google അക്കൗണ്ടിൽ ചേർക്കുക.</translation>
<translation id="4196861286325780578">&amp;നീക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
@@ -605,10 +615,10 @@
&lt;p&gt;പേജ് തുറക്കുന്നുവെങ്കിൽ, ഒരു Chrome വിപുലീകരണം ശരിയായി പ്രവർത്തിക്കുന്നില്ല. ഈ പിശക് പരിഹരിക്കാൻ, വിപുലീകരണം ഓഫാക്കുക.&lt;/p&gt;
&lt;h4&gt;ഘട്ടം 3: നിങ്ങളുടെ ഓപ്പറേറ്റിംഗ് സിസ്റ്റം അപ്‌ഡേറ്റ് ചെയ്യുക&lt;/h4&gt;
&lt;p&gt;നിങ്ങളുടെ ഉപകരണം അപ്-ടു-ഡേറ്റ് ആണെന്ന് ഉറപ്പാക്കുക.&lt;/p&gt;
- &lt;h4&gt;ഘട്ടം 4: ആന്റീവൈറസ് താൽക്കാലികമായി ഓഫാക്കുക&lt;/h4&gt;
- &lt;p&gt;നിങ്ങൾക്ക് "HTTPS പരിരക്ഷയോ" "HTTPS സ്‌കാനിംഗോ" നൽകുന്ന ആന്റീവൈറസ് സോഫ്റ്റ്‌വെയർ ഉണ്ടെങ്കിൽ, നിങ്ങൾ ഈ പിശക് കാണും. സുരക്ഷ നൽകുന്നതിൽ നിന്ന് Chrome-നെ ആന്റീവൈറസ് തടയുകയാണ്.&lt;/p&gt;
- &lt;p&gt;ഈ പ്രശ്‌നം പരിഹരിക്കാൻ, നിങ്ങളുടെ ആന്റീവൈറസ് സോഫ്റ്റ്‌വെയർ ഓഫാക്കുക. സോഫ്റ്റ്‌വെയർ ഓഫാക്കിയതിന് ശേഷം പേജ് പ്രവർത്തിക്കുന്നുവെങ്കിൽ, നിങ്ങൾ സുരക്ഷിതമായ സൈറ്റുകൾ ഉപയോഗിക്കുമ്പോഴൊക്കെ ഈ സോഫ്റ്റ്‌വെയർ ഓഫാക്കുക.&lt;/p&gt;
- &lt;p&gt;ചെയ്‌തുകഴിഞ്ഞാൽ, ആന്റീവൈറസ് പ്രോഗ്രാം വീണ്ടും ഓണാക്കാൻ മറക്കരുത്.&lt;/p&gt;
+ &lt;h4&gt;ഘട്ടം 4: ആന്റിവൈറസ് താൽക്കാലികമായി ഓഫാക്കുക&lt;/h4&gt;
+ &lt;p&gt;നിങ്ങൾക്ക് "HTTPS പരിരക്ഷയോ" "HTTPS സ്‌കാനിംഗോ" നൽകുന്ന ആന്റിവൈറസ് സോഫ്റ്റ്‌വെയർ ഉണ്ടെങ്കിൽ, നിങ്ങൾ ഈ പിശക് കാണും. സുരക്ഷ നൽകുന്നതിൽ നിന്ന് Chrome-നെ ആന്റിവൈറസ് തടയുകയാണ്.&lt;/p&gt;
+ &lt;p&gt;ഈ പ്രശ്‌നം പരിഹരിക്കാൻ, നിങ്ങളുടെ ആന്റിവൈറസ് സോഫ്റ്റ്‌വെയർ ഓഫാക്കുക. സോഫ്റ്റ്‌വെയർ ഓഫാക്കിയതിന് ശേഷം പേജ് പ്രവർത്തിക്കുന്നുവെങ്കിൽ, നിങ്ങൾ സുരക്ഷിതമായ സൈറ്റുകൾ ഉപയോഗിക്കുമ്പോഴൊക്കെ ഈ സോഫ്റ്റ്‌വെയർ ഓഫാക്കുക.&lt;/p&gt;
+ &lt;p&gt;ചെയ്‌തുകഴിഞ്ഞാൽ, ആന്റിവൈറസ് പ്രോഗ്രാം വീണ്ടും ഓണാക്കാൻ മറക്കരുത്.&lt;/p&gt;
&lt;h4&gt;ഘട്ടം 5: അധിക സഹായം സ്വീകരിക്കുക&lt;/h4&gt;
&lt;p&gt;നിങ്ങൾ ഇപ്പോഴും പിശക് കാണുന്നുവെങ്കിൽ, വെബ്‌സൈറ്റ് ഉടമയെ ബന്ധപ്പെടുക.&lt;/p&gt;</translation>
<translation id="4226937834893929579"><ph name="BEGIN_LINK" />നെറ്റ്‌വർക്ക് ഡയഗണോസ്‌റ്റിക്‌സ് റൺ ചെയ്‌തുനോക്കൂ<ph name="END_LINK" />.</translation>
@@ -623,6 +633,7 @@
<translation id="4277028893293644418">പാസ്‌വേഡ് റീസെറ്റ് ചെയ്യുക</translation>
<translation id="4279811152705618813">നിങ്ങളുടെ <ph name="DEVICE_TYPE" /> മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" /> ആണ്</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ഈ കാർഡ് നിങ്ങളുടെ Google അക്കൗണ്ടിൽ സംരക്ഷിച്ചു}other{ഈ കാർഡുകൾ നിങ്ങളുടെ Google അക്കൗണ്ടിൽ സംരക്ഷിച്ചു}}</translation>
+<translation id="428847186335018806">Chrome-ൽ നിങ്ങൾ ഡൗൺലോഡ് ചെയ്യുന്നതോ അപ്‌ലോഡ് ചെയ്യുന്നതോ ആയ ഫയലുകൾ സ്‌കാൻ ചെയ്യുക.</translation>
<translation id="42981349822642051">വികസിപ്പിക്കുക</translation>
<translation id="4302965934281694568">Chou3 (എൻവലപ്പ്)</translation>
<translation id="4305817255990598646">സ്വിച്ച് ചെയ്യുക</translation>
@@ -632,10 +643,10 @@
<translation id="4325863107915753736">ലേഖനം കണ്ടെത്തുന്നത് പരാജയപ്പെട്ടു</translation>
<translation id="4326324639298822553">കാലാവധി തീരുന്ന തീയതി പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക</translation>
<translation id="4331708818696583467">സുരക്ഷിതമല്ല</translation>
-<translation id="4340982228985273705">എന്റർപ്രൈസ് നിയന്ത്രിക്കുന്ന തരത്തിൽ ഈ കമ്പ്യൂട്ടർ തിരിച്ചറിയപ്പെടുന്നില്ല, അതുകൊണ്ട് Chrome വെബ്‌സ്റ്റോറിൽ ഹോസ്റ്റ് ചെയ്‌തിട്ടുള്ള വിപുലീകരണങ്ങൾ മാത്രമാണ് നയത്തിന് സ്വയമേവ ഇൻസ്റ്റാൾ ചെയ്യാനാവുക. Chrome വെബ്‌സ്റ്റോർ അപ്‌ഡേറ്റ് URL "<ph name="CWS_UPDATE_URL" />" ആണ്.</translation>
+<translation id="4340982228985273705">എന്റർപ്രൈസ് നിയന്ത്രിക്കുന്ന തരത്തിൽ ഈ കമ്പ്യൂട്ടർ തിരിച്ചറിയപ്പെടുന്നില്ല, അതുകൊണ്ട് Chrome വെബ്‌സ്റ്റോറിൽ ഹോസ്റ്റ് ചെയ്‌തിട്ടുള്ള വിപുലീകരണങ്ങൾ മാത്രമാണ് നയത്തിന് സ്വമേധയാ ഇൻസ്റ്റാൾ ചെയ്യാനാവുക. Chrome വെബ്‌സ്റ്റോർ അപ്‌ഡേറ്റ് URL "<ph name="CWS_UPDATE_URL" />" ആണ്.</translation>
<translation id="4346197816712207223">സ്വീകരിക്കുന്ന ക്രെഡിറ്റ് കാർഡുകൾ</translation>
<translation id="4346833872170306413">Roc-16K</translation>
-<translation id="4356973930735388585">ഈ സൈറ്റിലെ ആക്രമണകാരികൾ നിങ്ങളുടെ വിവരങ്ങൾ മോഷ്‌ടിക്കാനോ ഇല്ലാതാക്കാനോ ഇടയുള്ള (ഉദാഹരണത്തിന്, ഫോട്ടോകൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, ക്രെഡിറ്റ് കാർഡുകൾ എന്നിവ) അപകടകരമായ പ്രോഗ്രാമുകൾ കമ്പ്യൂട്ടറിൽ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ ശ്രമിച്ചേക്കാം.</translation>
+<translation id="4356973930735388585">ഈ സൈറ്റിലെ അറ്റാക്കർമാർ നിങ്ങളുടെ വിവരങ്ങൾ മോഷ്‌ടിക്കാനോ ഇല്ലാതാക്കാനോ ഇടയുള്ള (ഉദാഹരണത്തിന്, ഫോട്ടോകൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, ക്രെഡിറ്റ് കാർഡുകൾ എന്നിവ) അപകടകരമായ പ്രോഗ്രാമുകൾ കമ്പ്യൂട്ടറിൽ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ ശ്രമിച്ചേക്കാം.</translation>
<translation id="4358461427845829800">പേയ്മെന്റ് രീതികൾ മാനേജ് ചെയ്യുക...</translation>
<translation id="4367563149485757821">നമ്പർ-12 (എൻവലപ്പ്)</translation>
<translation id="4372516964750095882">ഫാൻഫോൾഡ്-Us</translation>
@@ -652,7 +663,6 @@
<translation id="4435702339979719576">പോസ്‌റ്റ്‌ കാർഡ്)</translation>
<translation id="443673843213245140">പ്രോക്‌സി ഉപയോഗം അപ്രാപ്‌തമാക്കി പക്ഷെ ഒരു വ്യക്തമായ പ്രോക്‌സി കോൺഫിഗറേഷൻ നിർദ്ദേശിച്ചു.</translation>
<translation id="445100540951337728">ഡെബിറ്റ് കാർഡുകൾ സ്വീകരിക്കുന്നു</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> സംശയാസ്‌പദമായ പ്രവർത്തനരീതി</translation>
<translation id="4466881336512663640">ഫോം മാറ്റങ്ങൾ നഷ്‌ടമാകും. തുടരണമെന്ന് നിങ്ങൾക്ക് തീർച്ചയാണോ?</translation>
<translation id="4477350412780666475">അടുത്ത ട്രാക്ക്</translation>
<translation id="4482953324121162758">ഈ സൈറ്റ് വിവർത്തനം ചെയ്യപ്പെടില്ല.</translation>
@@ -679,6 +689,7 @@
<translation id="4594403342090139922">&amp;ഇല്ലാതാക്കുന്നത് പഴയപടിയാക്കുക</translation>
<translation id="4597348597567598915">വലുപ്പം 8</translation>
<translation id="4600854749408232102">C6/C5 (എൻവലപ്പ്)</translation>
+<translation id="464342062220857295">തിരയൽ ഫീച്ചറുകൾ</translation>
<translation id="4646534391647090355">എന്നെ ഇപ്പോൾ അവിടെയെത്തിക്കൂ</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റിൽ പിശകുകൾ അടങ്ങിയിരിക്കുന്നു. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
@@ -687,7 +698,6 @@
<translation id="4691835149146451662">ആര്‍ക്കിടെക്ച്ചര്‍-A (എൻവലപ്പ്)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">നിങ്ങളുടെ കണക്ഷൻ തടസ്സപ്പെട്ടു</translation>
-<translation id="471880041731876836">ഈ സൈറ്റ് സന്ദർശിക്കാൻ നിങ്ങൾക്ക് അനുമതി ആവശ്യമില്ല</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows നെറ്റ്‌വർക്ക് ഡയഗണോസ്‌റ്റിക്‌സ് റൺ ചെയ്യുന്നു<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">നയങ്ങൾ വീണ്ടും ലോഡുചെയ്യുക</translation>
<translation id="4728558894243024398">പ്ലാറ്റ്ഫോം</translation>
@@ -715,7 +725,6 @@
<translation id="4816492930507672669">പേജിന് യുക്തമാക്കുക</translation>
<translation id="4850886885716139402">കാണുക</translation>
<translation id="4854362297993841467">ഈ ഡെലിവറി രീതി ലഭ്യമല്ല. മറ്റൊരു രീതി പരീക്ഷിക്കുക.</translation>
-<translation id="4858792381671956233">ഈ സൈറ്റ് സന്ദർശിക്കുന്നതിന് നിങ്ങൾ രക്ഷിതാക്കളോട് അനുമതി ആവശ്യപ്പെട്ടു</translation>
<translation id="4864052566555297930">സുരക്ഷാ നുറുങ്ങ്:</translation>
<translation id="4876188919622883022">ലളിതവൽക്കരിച്ച കാഴ്ച്ച</translation>
<translation id="4876305945144899064">ഉപയോക്തൃനാമമില്ല</translation>
@@ -739,7 +748,9 @@
<translation id="4974590756084640048">മുന്നറിയിപ്പുകൾ വീണ്ടും പ്രവർത്തനക്ഷമമാക്കുക</translation>
<translation id="4984339528288761049">Prc5 (എൻവലപ്പ്)</translation>
<translation id="4989163558385430922">എല്ലാം കാണുക</translation>
+<translation id="4989542687859782284">ലഭ്യമല്ല</translation>
<translation id="4989809363548539747">ഈ പ്ലഗിൻ പിന്തുണയ്‌ക്കുന്നില്ല</translation>
+<translation id="4995216769782533993">ഈ സൈറ്റുമായി നിങ്ങളുടെ കാർഡിന്റെ വിശദാംശങ്ങൾ പങ്കിടാൻ സുരക്ഷാ കോഡ് സ്ഥിരീകരിക്കുക</translation>
<translation id="5002932099480077015">പ്രവർത്തനക്ഷമമാക്കിയെങ്കിൽ, വേഗത്തിൽ ഫോം പൂരിപ്പിക്കാൻ Chrome ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ കാർഡിന്റെ ഒരു പകർപ്പ് സൂക്ഷിക്കും.</translation>
<translation id="5015510746216210676">മെഷീനിന്‍റെ പേര്‌:</translation>
<translation id="5017554619425969104">നിങ്ങൾ പകർത്തിയ ടെക്‌സ്‌റ്റ്</translation>
@@ -768,9 +779,10 @@
<translation id="5115216390227830982">യൂറോപ്യൻ-Edp</translation>
<translation id="5115563688576182185">(64-ബിറ്റ്)</translation>
<translation id="5125394840236832993">B-പ്ലസ്</translation>
+<translation id="5126510351761255129">നിങ്ങളുടെ കാർഡ് പരിശോധിച്ചുറപ്പിക്കുക</translation>
<translation id="5135404736266831032">വിലാസങ്ങൾ മാനേജ് ചെയ്യുക...</translation>
<translation id="5138227688689900538">കുറച്ച് കാണിക്കുക</translation>
-<translation id="5141240743006678641">Google ക്രെഡൻഷ്യലുകൾ ഉപയോഗിച്ച് സമന്വിത പാസ്‌വേഡുകൾ എൻക്രിപ്റ്റ് ചെയ്യുക</translation>
+<translation id="5141240743006678641">Google ക്രെഡൻഷ്യലുകൾ ഉപയോഗിച്ച് സമന്വിത പാസ്‌വേഡുകൾ എൻക്രിപ്റ്റുചെയ്യുക</translation>
<translation id="5145883236150621069">നയ പ്രതികരണത്തിൽ പിശക് കോഡ് ഉണ്ട്</translation>
<translation id="515292512908731282">C4 (എൻവലപ്പ്)</translation>
<translation id="5159010409087891077">പുതിയൊരു അദൃശ്യ വിൻഡോയിൽ പേജ് തുറക്കുക (⇧⌘N)</translation>
@@ -794,6 +806,7 @@
<translation id="5251803541071282808">ക്ലൗഡ്</translation>
<translation id="5252000469029418751">C7 (എൻവലപ്പ്)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">സിസ്‌റ്റത്തിലുടനീളം ബാധകമാകുന്ന ഫീച്ചറുകൾ ഉടമയ്‌ക്ക് മാത്രമേ സജ്ജീകരിക്കാനാവൂ: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">മുന്നറിയിപ്പ്: ഈ നയം ലയിപ്പിക്കാവുന്ന നിഘണ്ടു നയങ്ങളുടെ ഭാഗമല്ലാത്തതിനാലാണ് PolicyDictionaryMultipleSourceMergeList നയത്തിൽ വ്യക്തമാക്കിയിരിക്കുന്നത് പോലെ ലയിപ്പിക്കാത്തത്.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">അവസാനിപ്പിക്കുക</translation>
@@ -817,7 +830,6 @@
<translation id="536296301121032821">നയ ക്രമീകരണങ്ങൾ സംഭരിക്കുന്നതിൽ പരാജയപ്പെട്ടു</translation>
<translation id="5371425731340848620">കാർഡ് അപ്ഡേറ്റ് ചെയ്യുക</translation>
<translation id="5377026284221673050">"നിങ്ങളുടെ സമയം പിന്നിലാണ്" അല്ലെങ്കിൽ "നിങ്ങളുടെ സമയം മുന്നിലാണ്" അല്ലെങ്കിൽ "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">ഈ പേജ് നിങ്ങളെ കബളിപ്പിക്കാനോ നിങ്ങളുടെ വ്യക്തിഗത വിവരങ്ങൾ മോഷ്‌‌ടിക്കാനോ ഉപകരണത്തിന് കേടുവരുത്താനോ ശ്രമിച്ചേക്കാം. വ്യക്തിഗത വിവരങ്ങൾ നൽകുമ്പോഴോ ഡൗൺലോഡ് ചെയ്‌ത ഫയലുകൾ തുറക്കുമ്പോഴോ ജാഗ്രത പാലിക്കുക.</translation>
<translation id="5384855140246857529">എല്ലാ ഉപകരണങ്ങളിലും നിങ്ങളുടെ കാർഡുകൾ ഉപയോഗിക്കുന്നതിന്, സൈൻ ഇൻ ചെയ്‌ത് സമന്വയിപ്പിക്കൽ ഓണാക്കുക.</translation>
<translation id="5386426401304769735">ഈ സൈറ്റിന്റെ സർട്ടിഫിക്കറ്റ് ചെയിനിൽ SHA-1 ഉപയോഗിച്ച് സൈൻ ചെയ്‌ത ഒരു സർട്ടിഫിക്കറ്റ് അടങ്ങിയിരിക്കുന്നു.</translation>
<translation id="538659543871111977">A4-ടാബ്</translation>
@@ -831,13 +843,14 @@
<translation id="5457113250005438886">അസാധുവാണ്</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> എന്നതും മറ്റ് <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> എണ്ണവും}other{<ph name="CONTACT_PREVIEW" /> എന്നതും മറ്റ് <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> എണ്ണവും}}</translation>
<translation id="5470861586879999274">&amp;എഡിറ്റുചെയ്യുന്നത് വീണ്ടും ചെയ്യുക</translation>
+<translation id="5473728911100096288">ഈ ഫീച്ചറുകൾ പ്രവർത്തനക്ഷമമാക്കുന്നതിലൂടെ അവസാനിപ്പിച്ച ഫീച്ചറുകൾ നിങ്ങൾ ഉപയോഗിക്കും, ഭാവിയിലെ പതിപ്പുകളിൽ അവ അദൃശ്യമാകും.</translation>
<translation id="5478437291406423475">B6/C4 (എൻവലപ്പ്)</translation>
<translation id="5481076368049295676">ഈ ഉള്ളടക്കം, നിങ്ങളുടെ ഉപകരണത്തിൽ വിവരങ്ങൾ മോഷ്‌ടിക്കുകയോ ഇല്ലാതാക്കുയോ ചെയ്യുന്ന തരത്തിലുള്ള സോഫ്‌റ്റ്‌വെയർ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ ശ്രമിച്ചേക്കാം. <ph name="BEGIN_LINK" />എന്തായാലും കാണിക്കുക<ph name="END_LINK" /></translation>
<translation id="54817484435770891">ശരിയായ വിലാസം ചേർക്കുക</translation>
<translation id="5490432419156082418">വിലാസങ്ങളും മറ്റും</translation>
<translation id="5492298309214877701">കമ്പനി, ഓർഗനൈസേഷൻ അല്ലെങ്കിൽ സ്‌കൂൾ ഇൻട്രാനെറ്റിലെ ഈ സൈറ്റിന്, ബാഹ്യ വെബ്‌സൈറ്റിന് സമാനമായ URL ആണുള്ളത്.
<ph name="LINE_BREAK" />
- നിങ്ങളുടെ സിസ്‌റ്റം അഡ്‌മിനിസ്‌ട്രേറ്ററുമായി ബന്ധപ്പെടാൻ ശ്രമിക്കുക.</translation>
+ നിങ്ങളുടെ സിസ്‌റ്റം അഡ്‌മിനുമായി ബന്ധപ്പെടാൻ ശ്രമിക്കുക.</translation>
<translation id="549333378215107354">വലുപ്പം 3</translation>
<translation id="5509762909502811065">B0</translation>
<translation id="5509780412636533143">നിയന്ത്രിത ബുക്കുമാർക്കുകൾ</translation>
@@ -854,21 +867,21 @@
<translation id="5570825185877910964">അക്കൗണ്ട് പരിരക്ഷിക്കുക</translation>
<translation id="5571083550517324815">ഈ വിലാസത്തിൽ നിന്ന് പിക്ക്അപ്പ് ചെയ്യാൻ കഴിയില്ല. മറ്റൊരു വിലാസം തിരഞ്ഞെടുക്കുക.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{ഒരെണ്ണം ഉപയോഗത്തിലുണ്ട്}other{# എണ്ണം ഉപയോഗത്തിലുണ്ട്}})</translation>
-<translation id="5572851009514199876">ആരംഭിച്ച് Chrome-ൽ സൈൻ ഇൻ ചെയ്യുന്നതിലൂടെ, നിങ്ങൾക്ക് ഈ സൈറ്റ് ആക്‌സസ് ചെയ്യാൻ അനുവാദമുണ്ടോയെന്ന് Chrome-ന് പരിശോധിക്കാനാവും.</translation>
<translation id="5580958916614886209">കാലാവധി തീരുന്ന മാസം പരിശോധിച്ച് വീണ്ടും ശ്രമിക്കുക</translation>
<translation id="5586446728396275693">സംരക്ഷിച്ച വിലാസങ്ങളൊന്നുമില്ല</translation>
-<translation id="5595485650161345191">വിലാസം എഡിറ്റുചെയ്യുക</translation>
+<translation id="5595485650161345191">വിലാസം എഡിറ്റ് ചെയ്യുക</translation>
<translation id="5598944008576757369">പേയ്‌മെന്‍റ് രീതി തിരഞ്ഞെടുക്കുക</translation>
<translation id="560412284261940334">മാനേജുമെന്റ് പിന്തുണയ്‌ക്കുന്നില്ല</translation>
<translation id="5605670050355397069">ലെഡ്‌ജർ</translation>
<translation id="5607240918979444548">ആര്‍ക്കിടെക്ച്ചര്‍-C</translation>
+<translation id="5608165884683734521">ഈ സൈറ്റ് വ്യാജമോ വഞ്ചനാപരമോ ആകാം. ഈ സൈറ്റ് ഇപ്പോൾ വിടാൻ Chrome ശുപാർശ ചെയ്യുന്നു.</translation>
<translation id="5610142619324316209">കണക്ഷൻ പരിശോധിക്കുന്നു</translation>
<translation id="5610807607761827392">നിങ്ങൾക്ക് <ph name="BEGIN_LINK" />ക്രമീകരണത്തിൽ<ph name="END_LINK" /> കാർഡുകളും വിലാസങ്ങളും മാനേജ് ചെയ്യാം.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" />, നിരവധി തവണ നിങ്ങളെ റീഡയറക്‌ടുചെയ്‌തു.</translation>
<translation id="5629630648637658800">നയ ക്രമീകരണങ്ങൾ ലോഡ് ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു</translation>
<translation id="5631439013527180824">ഉപകരണ മാനേജ്‍മെന്റ് ടോക്കൺ അസാധുവാണ്</translation>
<translation id="5632627355679805402"><ph name="TIME" />-ന് <ph name="BEGIN_LINK" />Google പാസ്‌വേഡ്‌<ph name="END_LINK" /> ഉപയോഗിച്ച്‌ നിങ്ങളുടെ ഡാറ്റ എൻക്രിപ്‌റ്റ് ചെയ്‌തു. സമന്വയിപ്പിക്കൽ തുടങ്ങുന്നതിന് ഇത് നൽകുക.</translation>
-<translation id="5633066919399395251"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്ന സൈറ്റിലെ നിലവിലുള്ള ആക്രമികൾ നിങ്ങളുടെ വിവരങ്ങൾ മോഷ്‌ടിക്കാനോ ഇല്ലാതാക്കാനോ ഇടയുള്ള (ഉദാഹരണത്തിന്, ഫോട്ടോകൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, ക്രെഡിറ്റ് കാർഡുകൾ എന്നിവ) അപകടകരമായ പ്രോഗ്രാമുകൾ കമ്പ്യൂട്ടറിൽ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ ശ്രമിച്ചേക്കാം. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="5633066919399395251"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്ന സൈറ്റിലെ നിലവിലുള്ള അറ്റാക്കർമാർ നിങ്ങളുടെ വിവരങ്ങൾ മോഷ്‌ടിക്കാനോ ഇല്ലാതാക്കാനോ ഇടയുള്ള (ഉദാഹരണത്തിന്, ഫോട്ടോകൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, ക്രെഡിറ്റ് കാർഡുകൾ എന്നിവ) അപകടകരമായ പ്രോഗ്രാമുകൾ കമ്പ്യൂട്ടറിൽ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ ശ്രമിച്ചേക്കാം. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">തെറ്റിദ്ധരിപ്പിക്കുന്ന ഉള്ളടക്കം ബ്ലോക്കുചെയ്‌തു.</translation>
<translation id="5659593005791499971">ഇമെയില്‍</translation>
<translation id="5663614846592581799">9x11 (എൻവലപ്പ്)</translation>
@@ -885,11 +898,11 @@
<translation id="5720705177508910913">നിലവിലെ ഉപയോക്താവ്</translation>
<translation id="5728056243719941842">C5 (എൻവലപ്പ്)</translation>
<translation id="5730040223043577876">മറ്റ് സൈറ്റുകളിൽ നിങ്ങളുടെ പാസ്‌വേഡ് പുനരുപയോഗിച്ചിട്ടുണ്ടെങ്കിൽ, അത് പുനഃസജ്ജീകരിക്കാൻ Chrome ശുപാർശ ചെയ്യുന്നു.</translation>
-<translation id="5732392974455271431">നിങ്ങൾക്ക് വേണ്ടി ഇത് അൺബ്ലോക്കുചെയ്യാൻ രക്ഷിതാക്കൾക്ക് കഴിയും</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{നിങ്ങളുടെ Google അക്കൗണ്ടിൽ കാർഡ് സംരക്ഷിക്കുക}other{നിങ്ങളുടെ Google അക്കൗണ്ടിൽ കാർഡുകൾ സംരക്ഷിക്കുക}}</translation>
<translation id="5763042198335101085">ശരിയായ ഇമെയിൽ വിലാസം നൽകുക</translation>
<translation id="5765072501007116331">ഡെലിവറി രീതികളും ആവശ്യകതകളും കാണാൻ ഒരു വിലാസം തിരഞ്ഞെടുക്കുക</translation>
<translation id="5778550464785688721">MIDI ഉപകരണങ്ങളുടെ പൂർണ നിയന്ത്രണം</translation>
+<translation id="5781136890105823427">പരീക്ഷണം പ്രവർത്തനക്ഷമമാക്കി</translation>
<translation id="578305955206182703">ആംബർ</translation>
<translation id="57838592816432529">മ്യൂട്ട് ചെയ്യുക</translation>
<translation id="5784606427469807560">നിങ്ങളുടെ കാർഡ് സ്ഥിരീകരിക്കുന്നതിൽ പ്രശ്‌നമുണ്ടായി. ഇന്റർനെറ്റ് കണക്ഷൻ പരിശോധിച്ച്, വീണ്ടും ശ്രമിക്കുക.</translation>
@@ -906,13 +919,16 @@
<translation id="5860033963881614850">ഓഫാക്കുക</translation>
<translation id="5863847714970149516">മുമ്പോട്ടുള്ള പേജ് നിങ്ങളിൽ നിന്ന് പണമീടാക്കാൻ ശ്രമിച്ചേക്കാം</translation>
<translation id="5866257070973731571">ഫോണ്‍ നമ്പര്‍ ചേര്‍ക്കുക</translation>
+<translation id="5866898949289125849">നിങ്ങൾ ഒരു ഡെവലപ്പർ ടൂളുകളുടെ പേജാണ് കാണുന്നത്</translation>
<translation id="5869405914158311789">ഈ സൈറ്റ് ലഭ്യമാക്കാനാകുന്നില്ല</translation>
<translation id="5869522115854928033">സംരക്ഷിച്ച പാസ്‌വേഡുകള്‍</translation>
<translation id="5887400589839399685">കാർഡ് സംരക്ഷിച്ചു</translation>
<translation id="5893752035575986141">ക്രെഡിറ്റ് കാർഡുകൾ സ്വീകരിക്കുന്നു.</translation>
+<translation id="5895138241574237353">പുനരാരംഭിക്കുക</translation>
<translation id="5901630391730855834">മഞ്ഞ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (സമന്വയിപ്പിച്ചത്)</translation>
<translation id="5916664084637901428">ഓൺ ചെയ്യുക</translation>
+<translation id="59174027418879706">പ്രാപ്തമാക്കി</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google അക്കൗണ്ടിൽ കാർഡ് സംരക്ഷിക്കണോ?</translation>
<translation id="5922853866070715753">ഏതാണ്ട് പൂർത്തിയായി</translation>
@@ -946,7 +962,8 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങളിലും നിങ്ങളുടെ കാർഡുകൾ ഉപയോഗിക്കണോ?</translation>
<translation id="6059925163896151826">USB ഉപകരണങ്ങൾ</translation>
-<translation id="6080696365213338172">അഡ്‌മിനിസ്‌ട്രേറ്റർ നൽകിയ സർട്ടിഫിക്കറ്റ് ഉപയോഗിച്ച് നിങ്ങൾ ഉള്ളടക്കം ആക്‌സസ് ചെയ്‌തു. നിങ്ങൾ <ph name="DOMAIN" /> എന്നതിലേക്ക് നൽകുന്ന ഡാറ്റ അഡ്‌മിനിസ്‌ട്രേറ്റർക്ക് തടയാനാവും.</translation>
+<translation id="6060009363608157444">DnsOverHttps മോഡ് അസാധുവാണ്.</translation>
+<translation id="6080696365213338172">അഡ്‌മിനിസ്‌ട്രേറ്റർ നൽകിയ സർട്ടിഫിക്കറ്റ് ഉപയോഗിച്ച് നിങ്ങൾ ഉള്ളടക്കം ആക്‌സസ്സുചെയ്‌തു. നിങ്ങൾ <ph name="DOMAIN" /> എന്നതിലേക്ക് നൽകുന്ന ഡാറ്റ അഡ്‌മിനിസ്‌ട്രേറ്റർക്ക് തടയാനാവും.</translation>
<translation id="6094273045989040137">അനോട്ടേറ്റ് ചെയ്യുക</translation>
<translation id="610911394827799129">നിങ്ങളുടെ Google അക്കൗണ്ടിന് <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> എന്നതിൽ മറ്റ് തരത്തിലുള്ള ബ്രൗസിംഗ് ചരിത്രമുണ്ടായിരിക്കാം.</translation>
<translation id="6132597952260690497">ഇൻസ്‌റ്റാൾ ചെയ്‌ത വിപുലീകരണങ്ങളെയും പ്ലഗിന്നുകളെയും കുറിച്ചുള്ള വിവരങ്ങൾ</translation>
@@ -991,16 +1008,15 @@
<translation id="6387754724289022810">അടുത്ത പ്രാവശ്യം വേഗത്തിൽ പണമടയ്ക്കാൻ, നിങ്ങളുടെ Google അക്കൗണ്ടിലും ഈ ഉപകരണത്തിലും ഈ കാർഡും ബില്ലിംഗ് വിലാസവും സംരക്ഷിക്കുക.</translation>
<translation id="6390662030813198813">എഞ്ചിനീയറിംഗ്-E</translation>
<translation id="6401136357288658127">ഈ നയം അവസാനിപ്പിച്ചു. പകരം <ph name="NEW_POLICY" /> നയം ഉപയോഗിക്കണം.</translation>
-<translation id="6404511346730675251">ബുക്ക്‌മാർക്ക് എഡിറ്റുചെയ്യുക</translation>
+<translation id="6404511346730675251">ബുക്ക്‌മാർക്ക് എഡിറ്റ് ചെയ്യുക</translation>
<translation id="6406765186087300643">C0 (എൻവലപ്പ്)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" />-ന്‍റെ കാലാവധി തീരുന്ന തീയതിയും CVC-യും നൽകുക</translation>
-<translation id="6414888972213066896">ഈ സൈറ്റ് സന്ദർശിക്കുന്നതിന് നിങ്ങൾ രക്ഷിതാവിനോട് അനുമതി ആവശ്യപ്പെട്ടു</translation>
<translation id="6415778972515849510">നിങ്ങളുടെ Google അക്കൗണ്ട് പരിരക്ഷിക്കാനും പാസ്‌വേഡ് മാറ്റാനും Chromium സഹായിക്കും.</translation>
-<translation id="6417515091412812850">സര്‍ട്ടിഫിക്കറ്റ് അസാധുവാക്കിയോ എന്ന് പരിശോധിക്കുന്നതിനായില്ല.</translation>
<translation id="6431585503458005759">സംഭരിക്കരുത്</translation>
-<translation id="6433490469411711332">കോൺടാക്‌റ്റ് വിവരം എഡിറ്റുചെയ്യുക</translation>
+<translation id="6433490469411711332">കോൺടാക്‌റ്റ് വിവരം എഡിറ്റ് ചെയ്യുക</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> കണക്‌റ്റുചെയ്യൽ നിരസിച്ചു.</translation>
<translation id="6434309073475700221">നിരാകരിക്കുക</translation>
+<translation id="6435221585574090192">Chrome എന്റർപ്രൈസ് ഭീഷണി പരിരക്ഷ ഫ്ലാഗ് ചെയ്‌ത സുരക്ഷാ ഇവന്റുകളെക്കുറിച്ചുള്ള ഡാറ്റ നിങ്ങളുടെ അഡ്‌മിനുമായി പങ്കിടുക. പേജ് url-കൾ, ഫയലിന്റെ പേര്, ഫയൽ മെറ്റാഡാറ്റ, നിങ്ങളുടെ ഉപകരണത്തിന്റെ ഉപയോക്തൃനാമം, Chrome ഉപയോക്തൃനാമം എന്നിവ ഇവയിൽ ഉൾപ്പെട്ടേക്കാം.</translation>
<translation id="6440503408713884761">അവഗണിച്ചു</translation>
<translation id="6446163441502663861">കഹു (എൻവലപ്പ്)</translation>
<translation id="6446608382365791566">കൂടുതൽ വിവരങ്ങൾ ചേർക്കുക</translation>
@@ -1009,20 +1025,19 @@
<translation id="6465306955648956876">പാസ്‌വേഡുകൾ മാനേജ് ചെയ്യുക...</translation>
<translation id="647261751007945333">ഉപകരണ നയങ്ങൾ</translation>
<translation id="6476284679642588870">പേയ്മെൻ്റ് രീതികൾ മാനേജ് ചെയ്യുക</translation>
-<translation id="6477321094435799029">Chrome, ഈ പേജിൽ അസാധാരണമായ കോഡ് കണ്ടെത്തിയതിനാൽ നിങ്ങളുടെ വ്യക്തിഗത വിവരങ്ങൾ (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകളും ഫോൺ നമ്പറുകളും ക്രെഡിറ്റ് കാർഡുകളും പോലുള്ളവ) പരിരക്ഷിക്കുന്നതിന് അതിനെ ബ്ലോക്ക് ചെയ്‌തു.</translation>
<translation id="6489534406876378309">ക്രാഷുകൾ അപ്‌ലോഡുചെയ്യുന്നത് ആരംഭിക്കുക</translation>
<translation id="6499038740797743453">പാസ്‌വേഡ് റീസെറ്റ് ചെയ്യണോ?</translation>
<translation id="6507833130742554667">ക്രെഡിറ്റ് കാർഡുകളും ഡെബിറ്റ് കാർഡുകളും സ്വീകരിക്കുന്നു.</translation>
<translation id="650855688985305916">വേണം, സംഭരിക്കൂ</translation>
<translation id="6508722015517270189">Chrome റീസ്‌റ്റാർട്ടുചെയ്യുക</translation>
<translation id="6517596291481585650">മുന്നറിയിപ്പ്: ഈ നയം ഒരു ലിസ്‌റ്റ് അല്ലാത്തതിനാലാണ് നയത്തിൽ വ്യക്തമാക്കിയിരിക്കുന്നത് പോലെ ഒരു ലിസ്‌റ്റായി ലയിപ്പിക്കാത്തത്.</translation>
+<translation id="6518133107902771759">സ്ഥിരീകരിക്കുക</translation>
<translation id="6521745193039995384">സജീവമല്ല</translation>
<translation id="6529602333819889595">&amp;ഇല്ലാതാക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
<translation id="6534179046333460208">ഫിസിക്കൽ വെബ് നിർദ്ദേശങ്ങൾ</translation>
<translation id="6545864417968258051">Bluetooth സ്‌കാനിംഗ്</translation>
<translation id="6554795675067793129">നിങ്ങളുടെ അക്കൗണ്ട് മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" /> ആണ്.</translation>
<translation id="6556866813142980365">വീണ്ടും ചെയ്യുക</translation>
-<translation id="6563469144985748109">നിങ്ങളുടെ മാനേജർ ഇതുവരെ അംഗീകാരം നൽകിയിട്ടില്ല</translation>
<translation id="6569060085658103619">നിങ്ങൾ ഒരു വിപുലീകരണ പേജാണ് കാണുന്നത്</translation>
<translation id="6578796323535178455">C2 (എൻവലപ്പ്)</translation>
<translation id="6579990219486187401">ഇളം പിങ്ക്</translation>
@@ -1035,16 +1050,18 @@
<translation id="6624427990725312378">കോണ്‍ടാക്റ്റ് വിവരം</translation>
<translation id="6626291197371920147">ശരിയായ കാർഡ് നമ്പർ ചേർക്കുക</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> തിരയൽ</translation>
-<translation id="6630809736994426279"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്ന സൈറ്റിലെ നിലവിലുള്ള ആക്രമികൾ നിങ്ങളുടെ വിവരങ്ങൾ ഇല്ലാതാക്കാനോ മോഷ്‌ടിക്കാനോ ഇടയുള്ള (ഉദാഹരണത്തിന്, ഫോട്ടോകൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, ക്രെഡിറ്റ് കാർഡുകൾ മുതലായവ) അപകടകരമായ പ്രോഗ്രാമുകൾ Mac-ൽ ഇൻസ്‌റ്റാളുചെയ്യാൻ ശ്രമിച്ചേക്കാം. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="6630809736994426279"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്ന സൈറ്റിലെ നിലവിലുള്ള ആക്രമികൾ നിങ്ങളുടെ വിവരങ്ങൾ ഇല്ലാതാക്കാനോ മോഷ്‌ടിക്കാനോ ഇടയുള്ള (ഉദാഹരണത്തിന്, ഫോട്ടോകൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ, ക്രെഡിറ്റ് കാർഡുകൾ മുതലായവ) അപകടകരമായ പ്രോഗ്രാമുകൾ Mac-ൽ ഇൻസ്‌റ്റാൾ ചെയ്യാൻ ശ്രമിച്ചേക്കാം. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6631202559048444592">ഈ നയത്തിന് ഒന്നിലധികം ഉറവിടങ്ങളുണ്ടെങ്കിലും മൂല്യങ്ങൾ സമാനമാണ്.</translation>
<translation id="6643016212128521049">മായ്‌ക്കുക</translation>
<translation id="6644283850729428850">ഈ നയം ഇല്ലാതാക്കി.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{ഒന്നുമില്ല}=1{1 സൈറ്റിൽ നിന്ന് (നിങ്ങൾ Google അക്കൗണ്ടിൽ നിന്ന് സൈൻ ഔട്ട് ചെയ്യപ്പെടില്ല)}other{# സൈറ്റുകളിൽ നിന്ന് (നിങ്ങൾ Google അക്കൗണ്ടിൽ നിന്ന് സൈൻ ഔട്ട് ചെയ്യപ്പെടില്ല)}}</translation>
+<translation id="6652101503459149953">Windows Hello ഉപയോഗിക്കുക</translation>
<translation id="6657585470893396449">പാസ്‌വേഡ്</translation>
<translation id="6670613747977017428">സുരക്ഷയിലേക്ക് മടങ്ങുക.</translation>
<translation id="6671697161687535275">Chromium-ത്തിൽ നിന്ന് ഫോം നിർദ്ദേശം നീക്കംചെയ്യണോ?</translation>
<translation id="6685834062052613830">സൈൻ ഔട്ട് ചെയ്‌ത്, സജ്ജമാക്കൽ പൂർത്തിയാക്കുക</translation>
<translation id="6689271823431384964">നിങ്ങൾ സൈൻ ഇൻ ചെയ്‌തിരിക്കുന്നതിനാലാണ് നിങ്ങളുടെ Google അക്കൗണ്ടിൽ കാർഡുകൾ സംരക്ഷിക്കാമെന്ന് Chrome വാഗ്‌ദാനം ചെയ്യുന്നത്. ക്രമീകരണത്തിൽ ഈ രീതി മാറ്റാനാകും. കാർഡുടമയുടെ പേര് നിങ്ങളുടെ അക്കൗണ്ടിൽ നിന്നുമാണ് വന്നത്.</translation>
+<translation id="6707256370811247129">നിങ്ങൾ Chrome-ൽ അപ്‌ലോഡ് ചെയ്യുന്നതോ ഡൗൺലോഡ് ചെയ്യുന്നതോ ആയ ഫയലുകളും കാഷെയുടെ ഉള്ളടക്കങ്ങളും സ്‌കാൻ ചെയ്യുക.</translation>
<translation id="6710213216561001401">കഴിഞ്ഞ</translation>
<translation id="6710594484020273272">&lt;തിരയൽ പദം നൽകുക&gt;</translation>
<translation id="671076103358959139">എന്‍‌റോള്‍‌മെന്‍റ് ടോക്കണ്‍:</translation>
@@ -1052,10 +1069,10 @@
<translation id="6738516213925468394"><ph name="TIME" />-ന് നിങ്ങളുടെ <ph name="BEGIN_LINK" />സമന്വയ പാസ്‌ഫ്രെയ്‌സ്<ph name="END_LINK" /> ഉപയോഗിച്ച് ഡാറ്റ എൻക്രിപ്‌റ്റ് ചെയ്‌തു. സമന്വയം ആരംഭിക്കുന്നതിന് ഇത് നൽകുക.</translation>
<translation id="674375294223700098">അറിയപ്പെടാത്ത സെര്‍വര്‍ സര്‍ട്ടിഫിക്കറ്റ് പിശക്.</translation>
<translation id="6744009308914054259">കണക്‌ഷനായി കാത്തിരിക്കുമ്പോൾ, ഓഫ്‌ലൈൻ ലേഖനങ്ങൾ വായിക്കാനായി നിങ്ങൾക്ക് ഡൗൺലോഡുകൾ സന്ദർശിക്കാം.</translation>
+<translation id="6747611005629681221">മുന്നറിയിപ്പ്: അവസാനിപ്പിച്ച ഫീച്ചറുകൾ കണ്ടേക്കാം!</translation>
<translation id="6753269504797312559">നയ മൂല്യം</translation>
<translation id="6757797048963528358">നിങ്ങളുടെ ഉപകരണം സ്ലീപ്പ് മോഡിലായി</translation>
<translation id="6768213884286397650">ഹഗാക്കി (പോസ്‌റ്റ്‌കാർഡ്)</translation>
-<translation id="6778737459546443941">നിങ്ങളുടെ രക്ഷിതാവ് ഇതുവരെ അംഗീകാരം നൽകിയിട്ടില്ല</translation>
<translation id="67862343314499040">വയലറ്റ്</translation>
<translation id="6786747875388722282">വിപുലീകരണങ്ങള്‍</translation>
<translation id="6790428901817661496">പ്ലേചെയ്യുക</translation>
@@ -1063,6 +1080,7 @@
<translation id="681021252041861472">ഇത് പൂരിപ്പിക്കേണ്ടതുണ്ട്</translation>
<translation id="6810899417690483278">ഇഷ്‌ടാനുസൃതമാക്കൽ ഐഡി</translation>
<translation id="6825578344716086703">നിങ്ങൾ <ph name="DOMAIN" /> എന്നതിൽ എത്താൻ ശ്രമിച്ചു, പക്ഷേ ഒരു ദുർബലമായ സിഗ്‌നേച്ചർ അൽഗോരിതം ഉപയോഗിച്ച് ഒപ്പിട്ട ഒരു സർട്ടിഫിക്കറ്റ് സെർവർ നൽകി. ഇതിനർത്ഥം സെർവർ നൽകിയ സുരക്ഷാ ക്രെഡൻഷ്യലുകൾ വ്യാജമാകാമെന്നും നിങ്ങൾ ഉദ്ദേശിച്ച സെർവർ ആയിരിക്കില്ല എന്നുമാണ് (നിങ്ങൾ ആക്രമണകാരിയുമായിട്ടാകാം ആശയവിനിമയം നടത്തുന്നത്).</translation>
+<translation id="6826370046007623921">ഡാറ്റാ നഷ്‌ടം തടയൽ</translation>
<translation id="6831043979455480757">വിവർത്തനം ചെയ്യുക</translation>
<translation id="6839929833149231406">ഏരിയ</translation>
<translation id="6852204201400771460">ആപ്പ് റീലോഡ് ചെയ്യണോ?</translation>
@@ -1075,7 +1093,6 @@
<translation id="6891596781022320156">നയ നില പിന്തുണയ്ക്കുന്നില്ല.</translation>
<translation id="6895330447102777224">നിങ്ങളുടെ കാർഡ് സ്ഥിരീകരിച്ചു</translation>
<translation id="6897140037006041989">ഉപയോക്തൃ ഏജന്‍റ്</translation>
-<translation id="6903319715792422884">ചില <ph name="BEGIN_WHITEPAPER_LINK" />സിസ്‌റ്റം വിവരങ്ങളും പേജ് ഉള്ളടക്കവും<ph name="END_WHITEPAPER_LINK" /> Google-ലേക്ക് അയച്ച്, സുരക്ഷിത ബ്രൗസിംഗ് മെച്ചപ്പെടുത്താൻ സഹായിക്കുക. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ഉപയോക്താവ്:</translation>
<translation id="6934672428414710184">ഈ പേര് നിങ്ങളുടെ Google അക്കൗണ്ടിൽ നിന്നുള്ളതാണ്</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> മാനേജ് ചെയ്യാത്ത ഒരു സൈറ്റിൽ നിങ്ങൾ പാസ്‌വേഡ് നൽകി. നിങ്ങളുടെ അക്കൗണ്ട് പരിരക്ഷിക്കുന്നതിന്, മറ്റ് ആപ്പുകളിലും സൈറ്റുകളിലും നിങ്ങളുടെ പാസ്‌വേഡ് വീണ്ടും ഉപയോഗിക്കരുത്.</translation>
@@ -1120,6 +1137,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> എന്നതും മറ്റ് <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> എണ്ണവും}other{<ph name="PAYMENT_METHOD_PREVIEW" /> എന്നതും മറ്റ് <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> എണ്ണവും}}</translation>
<translation id="7153618581592392745">ലാവെൻഡർ</translation>
<translation id="717330890047184534">Gaia ഐഡി:</translation>
+<translation id="7174545416324379297">ലയിപ്പിച്ചു</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> എന്നതും മറ്റ് <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> എണ്ണവും}other{<ph name="SHIPPING_OPTION_PREVIEW" /> എന്നതും മറ്റ് <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> എണ്ണവും}}</translation>
<translation id="7177397715882417099">സെർവർ ഉപയോഗിച്ച് നിങ്ങൾ പോകുന്ന <ph name="ORIGIN" /> സൈറ്റ്, അതിൻ്റെ എല്ലാ അഭ്യർത്ഥനകളിലേക്കും ഒരു സുരക്ഷാ നയം ബാധകമാക്കുമെന്ന് ഇത് അഭ്യർത്ഥിച്ചിരിക്കുന്നു. എന്നാൽ ഒരു നയം നിർവഹിക്കുന്നതിന് പകരം ഇത് ബ്രൗസറിനെ മറ്റിടത്തേയ്ക്ക് റീഡയറക്‌ട് ചെയ്‌തതിനാൽ, <ph name="SITE" />എന്നതിനുള്ള നിങ്ങളുടെ അഭ്യർത്ഥന പൂർത്തീകരിക്കാൻ ബ്രൗസറിന് കഴിയുന്നില്ല.</translation>
<translation id="7179323680825933600">പേയ്‌മെന്റ് രീതികൾ സംരക്ഷിച്ച് പൂരിപ്പിക്കുക</translation>
@@ -1154,12 +1172,13 @@
<translation id="7320336641823683070">കണക്ഷൻ സഹായം</translation>
<translation id="733354035281974745">ഉപകരണ ലോക്കൽ അക്കൗണ്ട് അസാധുവാക്കുക</translation>
<translation id="7334320624316649418">&amp;പുനഃക്രമീകരിക്കുന്നത് വീണ്ടും ചെയ്യുക</translation>
+<translation id="7337706099755338005">നിങ്ങളുടെ പ്ലാറ്റ്‌ഫോമിൽ ലഭ്യമല്ല.</translation>
<translation id="733923710415886693">സർട്ടിഫിക്കറ്റ് സുതാര്യതയിലൂടെ സെർവറുടെ സർട്ടിഫിക്കറ്റ് വെളിപ്പെടുത്തിയിട്ടില്ല.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">അംഗമായി ഉള്‍പ്പെട്ടിട്ടുണ്ടോ:</translation>
<translation id="7349430561505560861">A4-അധികം</translation>
<translation id="7352902249897488700">ഈ സൈറ്റ് വിടുക</translation>
-<translation id="7353601530677266744">കമാന്‍റ് ലൈന്‍‌</translation>
+<translation id="7353601530677266744">കമാന്‍ഡ് ലൈന്‍‌</translation>
<translation id="7372973238305370288">തിരയൽ ഫലം</translation>
<translation id="7377249249140280793"><ph name="RELATIVE_DATE" /> - <ph name="FULL_DATE" /></translation>
<translation id="7378594059915113390">മീഡിയ നിയന്ത്രണങ്ങൾ</translation>
@@ -1169,7 +1188,7 @@
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">നിങ്ങളുടെ <ph name="DEVICE_NAME" /> മാനേജ് ചെയ്യപ്പെട്ടിരിക്കുന്നു</translation>
<translation id="7407424307057130981">&lt;p&gt;നിങ്ങളുടെ Windows കമ്പ്യൂട്ടറിൽ Superfish സോഫ്റ്റ്‌വെയർ ഉണ്ടെങ്കിൽ, നിങ്ങൾ ഈ പിശക് കാണും.&lt;/p&gt;
- &lt;p&gt;നിങ്ങൾക്ക് വെബിലേക്ക് കണക്‌റ്റ് ചെയ്യാൻ, സോഫ്‌റ്റ്‌വെയർ താൽക്കാലികമായി പ്രവർത്തനരഹിതമാക്കാൻ ഈ ഘട്ടങ്ങൾ പിന്തുടരുക. നിങ്ങൾക്ക് അഡ്‌മിനിസ്ട്രേറ്ററുടെ സവിശേഷാധികാരങ്ങൾ ആവശ്യമായിവരും.&lt;/p&gt;
+ &lt;p&gt;നിങ്ങൾക്ക് വെബിലേക്ക് കണക്‌റ്റ് ചെയ്യാൻ, സോഫ്‌റ്റ്‌വെയർ താൽക്കാലികമായി പ്രവർത്തനരഹിതമാക്കാൻ ഈ ഘട്ടങ്ങൾ പിന്തുടരുക. നിങ്ങൾക്ക് അഡ്‌മിന്‍റെ സവിശേഷാധികാരങ്ങൾ ആവശ്യമായിവരും.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;ആരംഭിക്കാൻ&lt;/strong&gt; ക്ലിക്ക് ചെയ്യുക, തുടർന്ന് &lt;strong&gt;"പ്രാദേശിക സേവനങ്ങൾ കാണുക "&lt;/strong&gt; എന്നത് തിരയുകയും തെരഞ്ഞെടുക്കുകയും ചെയ്യുക"
@@ -1183,7 +1202,6 @@
<translation id="7440140511386898319">ഓഫ്‌ലൈനായിരിക്കുമ്പോൾ ഉള്ളടക്കം അടുത്തറിയുക</translation>
<translation id="7441627299479586546">തെറ്റായ നയ വിഷയം</translation>
<translation id="7442725080345379071">ഇളം ഓറഞ്ച് നിറം</translation>
-<translation id="7444046173054089907">ഈ സൈറ്റ് ബ്ലോക്ക് ചെയ്‌തു</translation>
<translation id="7445762425076701745">നിങ്ങള്‍ ബന്ധിപ്പിച്ച സെര്‍വറിന്‍റെ ഐഡന്‍റിറ്റി പൂര്‍ണ്ണമായി സാധൂകരിക്കാന്‍ കഴിയില്ല. നിങ്ങളുടെ നെറ്റ്‍വര്‍ക്കില്‍ മാത്രം സാധുവായ ഒരു നാമം ഉപയോഗിക്കുന്ന സെര്‍വറിലേക്ക് നിങ്ങള്‍ ബന്ധിപ്പിച്ചിരിക്കുന്നു, അതിന്‍റെ ഉടമസ്ഥാവകാശം ഒരു ബാഹ്യ അതോറിറ്റിയ്ക്ക് ഒരിക്കലും സാധൂകരിക്കാന്‍ കഴിയില്ല. ചില സാക്‍ഷ്യപത്ര അതോറിറ്റികള്‍ ഈ നാമങ്ങളെ കണക്കാക്കാതെ സാക്‍ഷ്യപത്രങ്ങള്‍ നല്‍കുന്നതിനാല്‍, ഉദ്ദേശിച്ച വെബ്സൈറ്റിലേക്കാണ് നിങ്ങള്‍ ബന്ധിപ്പിച്ചിരിക്കുന്നതെന്നും ഒരു ആക്രമണകാരിയല്ലെന്നും ഉറപ്പാക്കാന്‍ ഒരു മാര്‍ഗ്ഗവുമില്ല.</translation>
<translation id="7451311239929941790">ഈ പ്രശ്‌നത്തെക്കുറിച്ച് <ph name="BEGIN_LINK" />കൂടുതലറിയുന്നു<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">ആഗോള ഡിഫോൾട്ട് ഉപയോഗിക്കുക (ബ്ലോക്ക് ചെയ്യുക)</translation>
@@ -1205,9 +1223,9 @@
<translation id="7538364083937897561">A2 (എൻവലപ്പ്)</translation>
<translation id="7542403920425041731">സ്ഥിരീകരിച്ചുകഴിഞ്ഞാൽ, നിങ്ങളുടെ കാർഡ് വിശദാംശങ്ങൾ ഈ സൈറ്റുമായി പങ്കിടും.</translation>
<translation id="7542995811387359312">ഈ ഫോം ഒരു സുരക്ഷിത കണക്ഷന്‍ ഉപയോഗിക്കാത്തതിനാല്‍ സ്വപ്രേരിത ക്രെഡിറ്റ് കാര്‍ഡ് പൂരിപ്പിക്കല്‍ അപ്രാപ്തമാക്കി.</translation>
-<translation id="7543525346216957623">നിങ്ങളുടെ രക്ഷിതാവിനോട്‌ ആവശ്യപ്പെടുക</translation>
<translation id="7548892272833184391">കണക്ഷൻ പിശകുകൾ പരിഹരിക്കുക</translation>
<translation id="7549584377607005141">ശരിയായി പ്രദർശിപ്പിക്കാൻ ഈ വെബ്‌ പേജിന് നിങ്ങൾ മുമ്പ് നൽകിയ ഡാറ്റ ആവശ്യമാണ്. നിങ്ങൾക്ക് ഈ ഡാറ്റ വീണ്ടും അയയ്‌ക്കാനാകുമെങ്കിലും, അങ്ങനെ ചെയ്യുന്നത് ഈ പേജിൽ മുമ്പ് ചെയ്‌ത ഏത് പ്രവർത്തനവും നിങ്ങൾക്ക് ആവർത്തിക്കേണ്ടതായി വരും.</translation>
+<translation id="7550637293666041147">നിങ്ങളുടെ ഉപകരണത്തിന്റെ ഉപയോക്തൃനാമവും Chrome ഉപയോക്തൃനാമവും</translation>
<translation id="7552846755917812628">ഇനിപ്പറയുന്ന നുറുങ്ങുകൾ പരീക്ഷിക്കൂ:</translation>
<translation id="7554791636758816595">പുതിയ ടാബ്</translation>
<translation id="7564049878696755256">നിങ്ങളുടെ <ph name="ORG_NAME" /> അക്കൗണ്ടിലേക്കുള്ള ആക്‌സസ് നഷ്‌ടമാകാനോ ഐഡന്‍റിറ്റി മോഷ്ടിക്കപ്പെടാനോ സാധ്യതയുണ്ട്. ഇപ്പോൾ തന്നെ പാസ്‍വേഡ് മാറ്റാൻ Chrome ശുപാർശ ചെയ്യുന്നു.</translation>
@@ -1221,7 +1239,8 @@
<translation id="7600965453749440009"><ph name="LANGUAGE" /> ഒരിക്കലും വിവര്‍‌ത്തനം ചെയ്യരുത്</translation>
<translation id="7610193165460212391">മൂല്യം പരിധിക്ക് പുറത്താണ് <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">കാലഹരണപ്പെടുന്നത്: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="7615602087246926389">Google അക്കൗണ്ട് പാസ്‌വേഡിന്റെ വ്യത്യസ്ത പതിപ്പ് ഉപയോഗിച്ച് എൻക്രിപ്റ്റ് ചെയ്ത ഡേറ്റ ഇപ്പോൾ തന്നെ നിങ്ങളുടെ കൈവശമുണ്ട്. ആ പാസ്‌വേഡ് താഴെ നൽകുക.</translation>
+<translation id="7615602087246926389">നിങ്ങൾക്ക് ഇതിനകം കൈവശമുള്ള എൻക്രിപ്‌റ്റ് ചെയ്ത ഡാറ്റ നിങ്ങളുടെ Google അക്കൗണ്ട് പാസ്‌വേഡിന്റെ ഒരു വ്യത്യസ്ത പതിപ്പ് ഉപയോഗിക്കുന്നു. ദയവായി അത് താഴെ നൽകുക.</translation>
+<translation id="7625784245512586808">Chrome എന്റർപ്രൈസ് ഭീഷണി പരിരക്ഷ</translation>
<translation id="7633909222644580952">പ്രകടന ഡാറ്റയും ക്രാഷ് റിപ്പോർട്ടുകളും</translation>
<translation id="7637571805876720304">Chromium-ൽ നിന്ന് ക്രെഡിറ്റ് കാർഡ് നീക്കംചെയ്യണോ?</translation>
<translation id="7638605456503525968">സീരിയൽ പോർട്ടുകൾ</translation>
@@ -1234,7 +1253,6 @@
<translation id="7668654391829183341">പരിചിതമല്ലാത്ത ഉപകരണം</translation>
<translation id="7669271284792375604">ഈ സൈറ്റിലെ ആക്രമണകാരികൾ, ബ്രൗസർ അനുഭവത്തെ ദോഷകരമായി ബാധിക്കുന്ന പ്രോഗ്രാമുകൾ ഇൻസ്‌റ്റാൾ ചെയ്യിക്കുന്ന വിധത്തിൽ നിങ്ങളെ കബളിപ്പിക്കാൻ ശ്രമിച്ചേക്കും (ഉദാഹരണത്തിന്, നിങ്ങളുടെ ഹോംപേജ് മാറ്റുന്നതിലൂടെയോ അല്ലെങ്കിൽ സന്ദർശിക്കുന്ന സൈറ്റുകളിൽ കൂടുതൽ പരസ്യങ്ങൾ കാണിക്കുന്നതിലൂടെയോ).</translation>
<translation id="7676643023259824263">ക്ലിപ്പ്‌ബോർഡ് ടെക്‌സ്‌റ്റിനായി തിരയുക, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">പ്ലാറ്റ്‌ഫോമും ക്ലൗഡും</translation>
<translation id="7681101578153515023">തിരയല്‍ യന്ത്രം മാറ്റുക</translation>
<translation id="7682287625158474539">ഷിപ്പിംഗ്</translation>
<translation id="7687186412095877299">നിങ്ങളുടെ സംരക്ഷിച്ച പേയ്‌മെന്‍റ് രീതികൾ ഉപയോഗിച്ച് പേയ്‌മെന്‍റ് ഫോമുകളിൽ പൂരിപ്പിക്കുന്നു</translation>
@@ -1246,10 +1264,9 @@
<translation id="7714464543167945231">സര്‍‌ട്ടിഫിക്കറ്റ്</translation>
<translation id="7716147886133743102">നിങ്ങളുടെ അ‌ഡ്‌മിനി‌സ്‌ട്രേറ്റർ ബ്ലോക്ക് ചെയ്‌തു</translation>
<translation id="7716424297397655342">ഈ സൈറ്റ് കാഷെയിൽ നിന്ന് ലോഡ് ചെയ്യാനാകില്ല</translation>
-<translation id="7723047071702270851">കാർഡ് എഡിറ്റുചെയ്യുക</translation>
-<translation id="774634243536837715">അപകടകരമായ ഉള്ളടക്കം ബ്ലോക്കുചെയ്‌തു.</translation>
+<translation id="7723047071702270851">കാർഡ് എഡിറ്റ് ചെയ്യുക</translation>
+<translation id="774634243536837715">അപകടകരമായ ഉള്ളടക്കം ബ്ലോക്ക് ചെയ്‌തു.</translation>
<translation id="7752995774971033316">നിയന്ത്രിക്കാനാകാത്തത്</translation>
-<translation id="7755287808199759310">നിങ്ങൾക്ക് വേണ്ടി ഇത് അൺബ്ലോക്കുചെയ്യാൻ രക്ഷിതാവിന് കഴിയും</translation>
<translation id="7757555340166475417">ഡായ്-പാ-കായ്</translation>
<translation id="7758069387465995638">ഫയർവാളോ ആന്റി വൈറസ് സോഫ്‌റ്റ്‌വെയറോ കണക്ഷൻ ബ്ലോക്ക് ചെയ്‌തിട്ടുണ്ടാകാം.</translation>
<translation id="7759163816903619567">പ്രദർശിപ്പിച്ച ഡൊമെയ്ന്‍:</translation>
@@ -1259,7 +1276,7 @@
<translation id="7770259615151589601">ഡെസിഗ്‌നേറ്റ് ചെയ്‌തത്-വലുത്</translation>
<translation id="777702478322588152">പ്രിഫെക്ച്വര്‍</translation>
<translation id="7791543448312431591">ചേര്‍ക്കൂ</translation>
-<translation id="7800304661137206267">സന്ദേശ പരിശോധിച്ചുറപ്പിക്കലിനായി <ph name="KX" /> കീ എക്സേഞ്ച് മെക്കാനിസമായി <ph name="CIPHER" /> ഉപയോഗിച്ച് ഈ കണക്ഷനെ <ph name="MAC" /> എന്നതുമായി എന്‍‌ക്രിപ്റ്റ് ചെയ്തിരിക്കുന്നു.</translation>
+<translation id="7800304661137206267">സന്ദേശ പ്രാമാണീകരണത്തിനും <ph name="KX" /> നും കീ എക്സേഞ്ച് മെക്കാനിസമായി <ph name="CIPHER" /> ഉപയോഗിച്ച് ഈ കണക്ഷനെ <ph name="MAC" /> എന്നതുമായി എന്‍‌ക്രിപ്റ്റ് ചെയ്തിരിക്കുന്നു.</translation>
<translation id="7802523362929240268">സൈറ്റ് നിയമാനുസൃതമാണ്</translation>
<translation id="780301667611848630">വേണ്ട നന്ദി</translation>
<translation id="7805768142964895445">നില</translation>
@@ -1267,10 +1284,10 @@
<translation id="7812922009395017822">Mir</translation>
<translation id="7813600968533626083">Chrome-ൽ നിന്നുള്ള നിർദ്ദേശം നീക്കംചെയ്യണോ?</translation>
<translation id="7815407501681723534">'<ph name="SEARCH_STRING" />' എന്നതിന്റെ <ph name="NUMBER_OF_RESULTS" /> <ph name="SEARCH_RESULTS" /> കണ്ടു</translation>
-<translation id="782886543891417279">നിങ്ങൾ ഉപയോഗിക്കുന്ന Wi-Fi (<ph name="WIFI_NAME" />) അതിന്റെ ലോഗിൻ പേജ് സന്ദർശിക്കാൻ ആവശ്യപ്പെടാം..</translation>
+<translation id="782886543891417279">നിങ്ങൾ ഉപയോഗിക്കുന്ന Wi-Fi (<ph name="WIFI_NAME" />) അതിന്റെ ലോഗിൻ പേജ് സന്ദർശിക്കാൻ ആവശ്യപ്പെടാം.</translation>
<translation id="7836231406687464395">പോസ്‌റ്റ്ഫിക്‌സ് (എൻവലപ്പ്)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ഒന്നുമില്ല}=1{ഒരു ആപ്പ് (<ph name="EXAMPLE_APP_1" />)}=2{2 ആപ്പുകൾ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# ആപ്പുകൾ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">എന്നിരുന്നാലും നിങ്ങൾ അദൃശ്യനല്ല. അദൃശ്യമാക്കുന്നതിലൂടെ, നിങ്ങളുടെ തൊഴിൽ ദാതാവിൽ നിന്നോ ഇന്റർനെറ്റ് സേവന ദാതാവിൽ നിന്നോ നിങ്ങൾ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളിൽ നിന്നോ നിങ്ങളുടെ ബ്രൗസിംഗിനെ മറയ്‌ക്കില്ല.</translation>
+<translation id="785549533363645510">എന്നിരുന്നാലും നിങ്ങൾ അദൃശ്യനല്ല. അദൃശ്യ മോഡിലേക്ക് പോകുന്നത്, നിങ്ങളുടെ തൊഴിൽ ദാതാവിൽ നിന്നോ ഇന്റർനെറ്റ് സേവന ദാതാവിൽ നിന്നോ നിങ്ങൾ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളിൽ നിന്നോ ഉള്ള ബ്രൗസിംഗിനെ മറയ്‌ക്കില്ല.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
<translation id="7862185352068345852">സൈറ്റ് വിടണോ?</translation>
<translation id="7878176543348854470">ഡെബിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും സ്വീകരിക്കുന്നു.</translation>
@@ -1293,7 +1310,6 @@
<translation id="8004582292198964060">ബ്രൗസര്‍</translation>
<translation id="8009225694047762179">പാസ്‌വേഡുകൾ മാനേജ് ചെയ്യുക</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ഈ കാർഡും അവയുടെ ബില്ലിംഗ് വിലാസവും സംരക്ഷിക്കപ്പെടും. നിങ്ങൾ <ph name="USER_EMAIL" /> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്‌തിരിക്കുമ്പോൾ അത് ഉപയോഗിക്കാനാകും.}other{ഈ കാർഡുകളും അവയുടെ ബില്ലിംഗ് വിലാസങ്ങളും സംരക്ഷിക്കപ്പെടും. നിങ്ങൾ <ph name="USER_EMAIL" /> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്‌തിരിക്കുമ്പോൾ അവ ഉപയോഗിക്കാനാകും.}}</translation>
-<translation id="8012647001091218357">ഇപ്പോൾ ഞങ്ങൾക്ക് നിങ്ങളുടെ രക്ഷകർത്താക്കളെ ബന്ധപ്പെടാനായില്ല. വീണ്ടും ശ്രമിക്കുക.</translation>
<translation id="8025119109950072390">ഈ സൈറ്റിലെ ആക്രമണകാരികൾ സോഫ്‌റ്റ്‌വെയർ ഇൻസ്റ്റാൾ ചെയ്യുന്നതോ വ്യക്തിപരമായ വിവരങ്ങൾ വെളിപ്പെടുത്തുന്നതോ (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകൾ, ഫോൺ നമ്പറുകൾ, ക്രെഡിറ്റ് കാർഡുകൾ എന്നീ വിവരങ്ങൾ) പോലുള്ള അപകടകരമായ കാര്യങ്ങൾ ചെയ്യിപ്പിക്കുന്ന തരത്തിൽ നിങ്ങളെ കബളിപ്പിച്ചേക്കാം.</translation>
<translation id="8034522405403831421">ഈ പേജ് <ph name="SOURCE_LANGUAGE" />-ലാണ്. <ph name="TARGET_LANGUAGE" />-ലേക്ക് വിവർത്തനം ചെയ്യണോ?</translation>
<translation id="8035152190676905274">പേന</translation>
@@ -1304,6 +1320,7 @@
<translation id="8041940743680923270">ആഗോള ഡിഫോൾട്ട് ഉപയോഗിക്കുക (ചോദിക്കുക)</translation>
<translation id="8042918947222776840">പിക്കപ്പ് രീതി തിരഞ്ഞെടുക്കുക</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ശരിയായി കോൺഫിഗർ ചെയ്‌‌തിട്ടില്ല. സാധാരണഗതിയിൽ "<ph name="SOFTWARE_NAME" />" അൺഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ ഈ പ്രശ്‌നം പരിഹരിക്കാം. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">ഇപ്പോൾ മുതൽ നിങ്ങൾ കാർഡ് സുരക്ഷാ കോഡ് നൽകേണ്ടതില്ല</translation>
<translation id="8066955247577885446">ക്ഷമിക്കണം, എന്തോ കുഴപ്പമുണ്ടായി.</translation>
<translation id="8074253406171541171">10x13 (എൻവലപ്പ്)</translation>
<translation id="8078141288243656252">തിരിക്കുമ്പോൾ അനോട്ടേറ്റ് ചെയ്യാനാവില്ല</translation>
@@ -1319,7 +1336,7 @@
<translation id="8103161714697287722">പേയ്‌മെന്റ് രീതി</translation>
<translation id="8105368624971345109">ഓഫാക്കുക</translation>
<translation id="8118489163946903409">പേയ്‌മെന്റ് രീതി</translation>
-<translation id="8127301229239896662">നിങ്ങളുടെ കമ്പ്യൂട്ടറിൽ അല്ലെങ്കിൽ നെറ്റ്‍വര്‍ക്കിൽ "<ph name="SOFTWARE_NAME" />" ശരിയായി ഇൻസ്‌റ്റാൾ ചെയ്‌തിട്ടില്ല. ഈ പ്രശ്‌നം പരിഹരിക്കാൻ നിങ്ങളുടെ ഐടി അഡ്‌മിനിസ്‌ട്രേറ്ററോട് ആവശ്യപ്പെടുക.</translation>
+<translation id="8127301229239896662">നിങ്ങളുടെ കമ്പ്യൂട്ടറിൽ അല്ലെങ്കിൽ നെറ്റ്‍വര്‍ക്കിൽ "<ph name="SOFTWARE_NAME" />" ശരിയായി ഇൻസ്‌റ്റാൾ ചെയ്‌തിട്ടില്ല. ഈ പ്രശ്‌നം പരിഹരിക്കാൻ നിങ്ങളുടെ ഐടി അഡ്‌മിനോട് ആവശ്യപ്പെടുക.</translation>
<translation id="8131740175452115882">സ്ഥിരീകരിക്കുക</translation>
<translation id="8149426793427495338">നിങ്ങളുടെ കമ്പ്യൂട്ടർ സ്ലീപ് മോഡിലാണ്.</translation>
<translation id="8150722005171944719"><ph name="URL" /> എന്നതിലെ ഫയൽ റീഡ് ചെയ്യാനാവുന്നില്ല. അത് നീക്കംചെയ്‌തിരിക്കുകയോ, നീക്കിയിരിക്കുകയോ ഫയൽ അനുമതികൾ ആക്‌സസ് തടയുകയോ ചെയ്യുന്നുണ്ടാകാം.</translation>
@@ -1327,13 +1344,14 @@
<translation id="8184538546369750125">ആഗോള ഡിഫോൾട്ട് ഉപയോഗിക്കുക (അനുവദിക്കുക)</translation>
<translation id="8194797478851900357">&amp;നീക്കുന്നത് പഴയപടിയാക്കുക</translation>
<translation id="8197543752516192074">പേജ് വിവർത്തനം ചെയ്യുക</translation>
-<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" എന്ന ഐഡിയുള്ള വിപുലീകരണത്തിന്റെ അസാധുവായ അപ്‌ഡേറ്റ് URL.</translation>
+<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" എന്ന ഐഡിയുള്ള വിപുലീകരണത്തിന്റെ അപ്‌ഡേറ്റ് URL അസാധുവാണ്.</translation>
<translation id="8202097416529803614">ഓർഡർ സംഗ്രഹം</translation>
<translation id="8202370299023114387">പൊരുത്തക്കേട്</translation>
<translation id="8206978196348664717">Prc4 (എൻവലപ്പ്)</translation>
<translation id="8211406090763984747">കണക്ഷൻ സുരക്ഷിതമാണ്</translation>
<translation id="8218327578424803826">നൽകിയിരിക്കുന്ന ലൊക്കേഷൻ:</translation>
<translation id="8220146938470311105">C7/C6 (എൻവലപ്പ്)</translation>
+<translation id="8220639454292072926">എന്റർപ്രൈസ് റിപ്പോർട്ടിംഗ്</translation>
<translation id="8225771182978767009">ഈ കമ്പ്യൂട്ടർ സജ്ജമാക്കിയ വ്യക്തി, ഈ സൈറ്റ് ബ്ലോക്ക് ചെയ്യാൻ തീരുമാനിച്ചിരുന്നു.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">പുതിയൊരു അദൃശ്യ ടാബിൽ പേജ് തുറക്കുക</translation>
@@ -1388,23 +1406,23 @@
<translation id="8508648098325802031">തിരയൽ ഐക്കൺ</translation>
<translation id="8522552481199248698">നിങ്ങളുടെ Google അക്കൗണ്ട് പരിരക്ഷിക്കാനും പാസ്‌വേഡ് മാറ്റാനും Chrome സഹായിക്കും.</translation>
<translation id="8543181531796978784">നിങ്ങൾക്ക് <ph name="BEGIN_ERROR_LINK" />സുരക്ഷാപ്രശ്‌നം റിപ്പോർട്ടുചെയ്യാം<ph name="END_ERROR_LINK" /> അല്ലെങ്കിൽ, സുരക്ഷയെ ബാധിച്ചേക്കാവുന്ന അപകട സാധ്യതകളെക്കുറിച്ച് ബോധ്യമുണ്ടെങ്കിൽ <ph name="BEGIN_LINK" />സുരക്ഷിതമല്ലാത്ത ഈ സൈറ്റ്<ph name="END_LINK" />സന്ദർശിക്കുക.</translation>
-<translation id="8543556556237226809">ചോദ്യങ്ങളുണ്ടോ? നിങ്ങളുടെ പ്രൊഫൈൽ മേൽനോട്ടത്തിലുള്ള വ്യക്തിയെ ബന്ധപ്പെടുക.</translation>
<translation id="8553075262323480129">പേജിന്‍റെ ഭാഷ നിര്‍‌ണ്ണയിക്കാന്‍‌ കഴിയാത്തതിനാല്‍‌ വിവര്‍‌ത്തനം പരാജയപ്പെട്ടു.</translation>
<translation id="8557066899867184262">കാർഡിന് പിന്നിലാണ് CVC രേഖപ്പെടുത്തിയിരിക്കുന്നത്.</translation>
<translation id="8559762987265718583">നിങ്ങളുടെ ഉപകരണത്തിന്റെ തീയതിയും സമയവും (<ph name="DATE_AND_TIME" />) തെറ്റായതിനാൽ <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> എന്നതിലേക്കുള്ള സ്വകാര്യ കണക്ഷൻ സ്ഥാപിക്കാനാവില്ല.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> സംശയാസ്‌പദമായ സൈറ്റ്</translation>
<translation id="8564985650692024650">മറ്റ് സൈറ്റുകളിൽ നിങ്ങൾ <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> പാസ്‌വേഡ് പുനരുപയോഗിച്ചിട്ടുണ്ടെങ്കിൽ, അത് റീസെറ്റ് ചെയ്യാൻ Chromium ശുപാർ‌ശ ചെയ്യുന്നു.</translation>
<translation id="8571890674111243710"><ph name="LANGUAGE" /> ലേക്ക് പേജ് വിവര്‍‌ത്തനം ചെയ്യുന്നു...</translation>
<translation id="858637041960032120">ഫോൺ നമ്പർ ചേർക്കൂ</translation>
-<translation id="859285277496340001">സർട്ടിഫിക്കറ്റ് അസാധുവാക്കിയോ എന്ന് പരിശോധിക്കുന്നതിന് അത് ഒരു മെക്കാനിസത്തെയും സൂചിപ്പിക്കുന്നില്ല.</translation>
<translation id="860043288473659153">കാർഡിന്റെ ഉടമയുടെ പേര്</translation>
<translation id="861775596732816396">വലുപ്പം 4</translation>
-<translation id="8620436878122366504">നിങ്ങളുടെ രക്ഷിതാക്കൾ ഇതുവരെ അംഗീകാരം നൽകിയിട്ടില്ല</translation>
<translation id="8622948367223941507">നിയമപരം-അധികം</translation>
<translation id="8625384913736129811">ഈ ഉപകരണത്തിലേക്ക് ഈ കാർഡ് സംരക്ഷിക്കുക</translation>
<translation id="8626112503828625890">Google അക്കൗണ്ടിൽ ബില്ലിംഗ് വിശദാംശങ്ങൾ സംഭരിക്കണോ?</translation>
+<translation id="8647750283161643317">എല്ലാം സ്ഥിരമായി പുനഃസജ്ജമാക്കുക</translation>
<translation id="8663226718884576429">ഓർഡർ സംഗ്രഹം, <ph name="TOTAL_LABEL" />, കൂടുതൽ വിശദാംശങ്ങൾ</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, ഉത്തരം, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">ലഭ്യമാണ്</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> ലേക്കുള്ള നിങ്ങളുടെ കണക്ഷന്‍ എന്‍‌ക്രിപ്റ്റ് ചെയ്തിട്ടില്ല.</translation>
<translation id="8718314106902482036">പേയ്‌മെന്റ് പൂർത്തിയായിട്ടില്ല</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, തിരയൽ നിർദ്ദേശം</translation>
@@ -1415,6 +1433,7 @@
<translation id="8738058698779197622">ഒരു സുരക്ഷിത കണക്ഷൻ സ്ഥാപിക്കുന്നതിന്, നിങ്ങളുടെ ക്ലോക്ക് ശരിയായി സജ്ജീകരിക്കേണ്ടതുണ്ട്. വെബ്‌സൈറ്റുകൾ സ്വയം തിരിച്ചറിയുന്നതിന് ഉപയോഗിക്കുന്ന സർട്ടിഫിക്കറ്റുകൾ, നിർദ്ദിഷ്‌ട സമയ പരിധിയ്‌ക്ക് മാത്രമായി സാധുതയുള്ളതിനാലാണിത്. നിങ്ങളുടെ ഉപകരണത്തിന്റെ ക്ലോക്ക് തെറ്റായിരിക്കുന്നതിനാൽ, Chromium-ന് ഈ സർട്ടിഫിക്കറ്റുകൾ പരിശോധിച്ചുറപ്പിക്കാനാവില്ല.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> ഹോസ്‌റ്റിന്‍റെ &lt;abbr id="dnsDefinition"&gt;DNS വിലാസം&lt;/abbr&gt; കണ്ടെത്താനായില്ല. പ്രശ്‌നം നിർണ്ണയിക്കുന്നു.</translation>
<translation id="874846938927089722">സ്വീകരിക്കുന്ന ക്രെഡിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും</translation>
+<translation id="874918643257405732">ഈ ടാബ് ബുക്ക്‌മാർക്ക് ചെയ്യുക</translation>
<translation id="8759274551635299824">ഈ കാർഡ് കാലഹരണപ്പെട്ടു</translation>
<translation id="8761567432415473239">Google സുരക്ഷിത ബ്രൗസിംഗ് <ph name="SITE" /> എന്നതിൽ ഈയിടെ <ph name="BEGIN_LINK" />ദോഷകരമായ പ്രോഗ്രാമുകൾ കണ്ടെത്തി<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB ഉപകരണം</translation>
@@ -1444,6 +1463,7 @@
<translation id="8938939909778640821">ക്രെഡിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും സ്വീകരിക്കുന്നു</translation>
<translation id="8943282376843390568">ചെറുനാരങ്ങയുടെ നിറം</translation>
<translation id="8957210676456822347">ക്യാപ്‌റ്റീവ് പോർട്ടൽ അംഗീകരിക്കൽ</translation>
+<translation id="8962950042226115166">സംശയാസ്‌പദമായ സൈറ്റ്</translation>
<translation id="8968766641738584599">കാർഡ് സംരക്ഷിക്കുക</translation>
<translation id="8971063699422889582">സെർവറിന്റെ സർട്ടിഫിക്കറ്റ് കാലഹരണപ്പെട്ടു.</translation>
<translation id="8975012916872825179">ഫോൺ നമ്പറുകൾ, ഇമെയിൽ വിലാസങ്ങൾ, ഷിപ്പിംഗ് വിലാസങ്ങൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഉൾപ്പെടുന്നു</translation>
@@ -1466,24 +1486,24 @@
<translation id="9035022520814077154">സുരക്ഷാ പിശക്</translation>
<translation id="9038649477754266430">പേജുകൾ കൂടുതൽ വേഗത്തിൽ ലോഡ് ചെയ്യാൻ ഒരു പ്രവചന സേവനം ഉപയോഗിക്കുക</translation>
<translation id="9039213469156557790">ഈ പേജിൽ സുരക്ഷിതമല്ലാത്ത മറ്റ് ഉറവിടങ്ങൾ ഉൾപ്പെടുന്നു. ഈ ഉറവിടങ്ങൾ കൈമാറുന്നതിനിടെ മറ്റുള്ളവർക്ക് കാണാനും പേജിന്റെ പ്രവർത്തനരീതി മാറ്റുന്ന തരത്തിൽ ഒരു ആക്രമണകാരിയ്‌ക്ക് പരിഷ്‌ക്കരിക്കാനുമായേക്കും.</translation>
+<translation id="9044359186343685026">ടച്ച് ഐഡി ഉപയോഗിക്കുക</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">നിങ്ങള്‍ <ph name="DOMAIN" /> എന്നതില്‍ എത്താന്‍ ശ്രമിച്ചു, പക്ഷേ സെര്‍വര്‍ ഒരു അസാധുവായ സര്‍ട്ടിഫിക്കറ്റ് അവതരിപ്പിച്ചു.</translation>
<translation id="9050666287014529139">പാസ്ഫ്രെയ്‍സ്</translation>
-<translation id="9065203028668620118">എഡിറ്റുചെയ്യുക</translation>
+<translation id="9065203028668620118">എഡിറ്റ് ചെയ്യുക</translation>
<translation id="9065745800631924235">ചരിത്രത്തിൽ നിന്നുള്ള <ph name="TEXT" /> തിരയൽ</translation>
<translation id="9069693763241529744">ഒരു വിപുലീകരണം മുഖേന ബ്ലോക്ക് ചെയ്‌തു</translation>
-<translation id="9076283476770535406">ഇതിൽ മുതിർന്നവർക്കുള്ള ഉള്ളടക്കം ഉണ്ടായിരിക്കാം</translation>
<translation id="9076630408993835509">ഈ ബ്രൗസർ ഒരു കമ്പനിയോ മറ്റേതെങ്കിലും സ്ഥാപനമോ മാനേജ് ചെയ്യുന്നില്ല. ഈ ഉപകരണത്തിലെ ആക്‌റ്റിവിറ്റി Chrome-ന് പുറത്ത് മാനേജ് ചെയ്യുന്നുണ്ടാകാം. <ph name="BEGIN_LINK" />കൂടുതലറിയുക<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">കൂടുതൽ വിവരങ്ങൾ ആവശ്യമാണ്</translation>
<translation id="9080712759204168376">ഓർഡർ സംഗ്രഹം</translation>
<translation id="9089260154716455634">ഓഫ് അവേഴ്‌സ് നയം:</translation>
<translation id="9095388113577226029">കൂടുതൽ ഭാഷകൾ...</translation>
-<translation id="9103872766612412690">നിങ്ങളുടെ വിവരങ്ങൾ പരിരക്ഷിക്കാൻ സാധാരണയായി <ph name="SITE" />, എൻക്രിപ്‌ഷൻ ഉപയോഗിക്കുന്നു. ഇപ്പോൾ <ph name="SITE" /> സൈറ്റിലേക്ക് കണക്‌റ്റ് ചെയ്യാൻ Chromium ശ്രമിച്ചപ്പോൾ, അസാധാരണമായതും തെറ്റായതുമായ ക്രെഡൻഷ്യലുകൾ വെബ്‌സൈറ്റ് തിരികെ അയച്ചു. ഒരു ആക്രമണകാരി <ph name="SITE" /> എന്നതായി ഭാവിക്കാൻ ശ്രമിക്കുമ്പോഴോ Wi-Fi സൈൻ ഇൻ സ്‌ക്രീൻ, കണക്ഷനെ തടസ്സപ്പെടുത്തുമ്പോഴോ ആണ് ഇങ്ങനെ സംഭവിക്കാനിടയുള്ളത്. ഏതെങ്കിലും ഡാറ്റ കൈമാറുന്നതിനുമുമ്പ് Chromium കണക്ഷൻ അവസാനിപ്പിച്ചതിനാൽ, നിങ്ങളുടെ വിവരങ്ങൾ തുടർന്നും സുരക്ഷിതമായിരിക്കും.</translation>
+<translation id="9098981495403789647">നിങ്ങളുടെ ബ്രൗസറിൽ Chrome എന്റർപ്രൈസ് ഭീഷണി പരിരക്ഷ അഡ്‌മിൻ പ്രവർത്തനക്ഷമമാക്കി. Chrome എന്റർപ്രൈസ് ഭീഷണി പരിരക്ഷയ്‌ക്ക് നിങ്ങളുടെ ചില ഡാറ്റയിലേക്ക് ആക്‌സസുണ്ട്.</translation>
+<translation id="9103872766612412690">നിങ്ങളുടെ വിവരങ്ങൾ പരിരക്ഷിക്കാൻ സാധാരണയായി <ph name="SITE" />, എൻക്രിപ്‌ഷൻ ഉപയോഗിക്കുന്നു. ഇപ്പോൾ <ph name="SITE" /> സൈറ്റിലേക്ക് കണക്‌റ്റുചെയ്യാൻ Chromium ശ്രമിച്ചപ്പോൾ, അസാധാരണമായതും തെറ്റായതുമായ ക്രെഡൻഷ്യലുകൾ വെബ്‌സൈറ്റ് തിരികെ അയച്ചു. ഒരു ആക്രമണകാരി <ph name="SITE" /> എന്നതായി ഭാവിക്കാൻ ശ്രമിക്കുമ്പോഴോ Wi-Fi സൈൻ ഇൻ സ്‌ക്രീൻ, കണക്ഷനെ തടസ്സപ്പെടുത്തുമ്പോഴോ ആണ് ഇങ്ങനെ സംഭവിക്കാനിടയുള്ളത്. ഏതെങ്കിലും ഡാറ്റ കൈമാറുന്നതിനുമുമ്പ് Chromium കണക്ഷൻ അവസാനിപ്പിച്ചതിനാൽ, നിങ്ങളുടെ വിവരങ്ങൾ തുടർന്നും സുരക്ഷിതമായിരിക്കും.</translation>
<translation id="9106062320799175032">ബില്ലിംഗ് വിലാസം ചേർക്കുക</translation>
<translation id="9114524666733003316">കാർഡ് സ്ഥിരീകരിക്കുന്നു...</translation>
<translation id="9128870381267983090">നെറ്റ്‌വർക്കിലേക്ക് ബന്ധിപ്പിക്കുക</translation>
<translation id="9137013805542155359">യഥാര്‍ത്ഥമായത് കാണിക്കുക</translation>
-<translation id="9137248913990643158">ഈ ആപ്പ് ഉപയോഗിക്കുന്നതിന് മുമ്പ് ആരംഭിച്ച് Chrome-ൽ സൈൻ ഇൻ ചെയ്യുക.</translation>
<translation id="9141013498910525015">വിലാസങ്ങൾ മാനേജ് ചെയ്യുക</translation>
<translation id="9148088599418889305">ഷിപ്പിംഗ് രീതി തിരഞ്ഞെടുക്കുക</translation>
<translation id="9148507642005240123">&amp;എഡിറ്റുചെയ്യുന്നത് പഴയപടിയാക്കുക</translation>
@@ -1498,9 +1518,9 @@
<translation id="9174917557437862841">ടാബ് മാറാനുള്ള ബട്ടൺ, ഈ ടാബിലേക്ക് മാറാൻ എൻ്റർ അമർത്തുക</translation>
<translation id="9183302530794969518">Google ഡോക്‌സ്</translation>
<translation id="9183425211371246419"><ph name="HOST_NAME" /> പിന്തുണയ്‌ക്കാത്ത ഒരു പ്രോട്ടോക്കോളാണ് ഉപയോഗിക്കുന്നത്.</translation>
-<translation id="9205078245616868884">നിങ്ങളുടെ സമന്വയ പാസ്‌ഫ്രെയ്‌സ് ഉപയോഗിച്ച് ഡാറ്റ എൻക്രിപ്‌റ്റ് ചെയ്‌തു. സമന്വയം ആരംഭിക്കുന്നതിന് ഇത് നൽകുക.</translation>
+<translation id="9205078245616868884">നിങ്ങളുടെ സമന്വയ പാസ്‌ഫ്രെയ്‌സ് ഉപയോഗിച്ച് ഡാറ്റ എൻക്രിപ്‌റ്റുചെയ്‌തു. സമന്വയം ആരംഭിക്കുന്നതിന് ഇത് നൽകുക.</translation>
<translation id="9207861905230894330">ലേഖനം ചേർക്കാനായില്ല.</translation>
-<translation id="9215416866750762878">ഈ സൈറ്റിലേക്ക് സുരക്ഷിതമായി കണക്റ്റ് ചെയ്യുന്നതിൽ നിന്ന് Chrome-നെ ഒരു ആപ്പ് തടയുന്നു</translation>
+<translation id="9215416866750762878">ഈ സൈറ്റിലേക്ക് സുരക്ഷിതമായി കണക്റ്റുചെയ്യുന്നതിൽ നിന്ന് Chrome-നെ ഒരു ആപ്പ് തടയുന്നു</translation>
<translation id="9219103736887031265">ചിത്രങ്ങൾ‌</translation>
<translation id="933712198907837967">Diners Club</translation>
<translation id="935608979562296692">ഫോം മായ്‌ക്കുക</translation>
diff --git a/chromium/components/strings/components_strings_mr.xtb b/chromium/components/strings/components_strings_mr.xtb
index 1ed346c50d4..6c76167bdac 100644
--- a/chromium/components/strings/components_strings_mr.xtb
+++ b/chromium/components/strings/components_strings_mr.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">कार्डवर नाव जोडा</translation>
<translation id="1089439967362294234">पासवर्ड बदला</translation>
+<translation id="1096545575934602868">या भागात <ph name="MAX_ITEMS_LIMIT" /> पेक्षा जास्त नोंदी असू शकत नाहीत. उरलेल्या सर्व नोंदी काढून टाकल्या जातील.</translation>
<translation id="109743633954054152">Chrome सेटिंग्जमध्ये पासवर्ड व्यवस्थापित करा</translation>
<translation id="1103523840287552314">नेहमी भाषांतर करा <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">चेक केल्यास, अधिक जलद फॉर्म भरण्यासाठी या डिव्हाइसवर Chrome तुमच्या कार्डची एक प्रत संचयित करेल.</translation>
@@ -34,9 +35,10 @@
<translation id="1131264053432022307">तुम्ही कॉपी केलेली इमेज</translation>
<translation id="1150979032973867961">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षितता प्रमाणपत्र तुमच्या कॉंप्युटरच्या ऑपरेटिंग प्रणालीद्वारे विश्वसनीय नाही. हे कदाचित एका चुकीच्या कॉन्फिगरेशनमुळे किंवा आक्रमणकर्त्याने तुमचे कनेक्शन आंतरखंडित केल्यामुळे झाले असू शकते.</translation>
<translation id="1151972924205500581">पासवर्ड आवश्यक</translation>
-<translation id="1152921474424827756"><ph name="URL" /> च्या <ph name="BEGIN_LINK" />कॅशे केलेली कॉपी<ph name="END_LINK" /> अॅक्सेस करा</translation>
+<translation id="1152921474424827756"><ph name="URL" /> च्या <ph name="BEGIN_LINK" />कॅशे केलेली कॉपी<ph name="END_LINK" /> ॲक्सेस करा</translation>
<translation id="1156303062776767266">तुम्ही स्थानिक किंवा शेअर केलेली फाइल पाहत आहात</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> नी कनेक्शन अनपेक्षितरित्या बंद केले.</translation>
+<translation id="115926840831309955">तुमचे CVC तपासा आणि पुन्हा प्रयत्न करा किंवा एक्स्पायरीची तारीख अपडेट करा</translation>
<translation id="1161325031994447685">वाय-फाय शी पुन्हा कनेक्ट करत आहे</translation>
<translation id="1165039591588034296">एरर</translation>
<translation id="1175364870820465910">&amp;मुद्रण...</translation>
@@ -57,11 +59,11 @@
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (सिंक केलेले)</translation>
<translation id="1256368399071562588">&lt;p&gt;जर तुम्ही एखाद्या वेबसाइटला भेट देण्याचा प्रयत्न केला आणि ती उघडली नाही, तर सगळ्यात आधी ट्रबलशूटिंग स्टेप्सद्धारे या एररवर उपाय काढण्याचा प्रयत्न करा:&lt;/p&gt;
&lt;ol&gt;
- &lt;li&gt;अक्षरातील चुकांसाठी वेब अॅड्रेस तपासा.&lt;/li&gt;
+ &lt;li&gt;अक्षरातील चुकांसाठी वेब ॲड्रेस तपासा.&lt;/li&gt;
&lt;li&gt;तुमचे इंटरनेट कनेक्शन नेहमीप्रमाणे चालत असल्याची खात्री करा.&lt;/li&gt;
&lt;li&gt;वेबसाइटच्या मालकाशी संपर्क साधा.&lt;/li&gt;
&lt;/ol&gt;</translation>
-<translation id="1257286744552378071">तुमच्या संस्थेद्वारे व्यवस्थापित केल्या न जाणाऱ्या साइटवर तुम्ही तुमचा पासवर्ड एंटर केला आहे. तुमचे खाते संरक्षित करण्यासाठी इतर अॅप्स आणि साइटवर तुमच्या पासवर्डचा पुन्हा वापर करू नका.</translation>
+<translation id="1257286744552378071">तुमच्या संस्थेद्वारे व्यवस्थापित केल्या न जाणाऱ्या साइटवर तुम्ही तुमचा पासवर्ड एंटर केला आहे. तुमचे खाते संरक्षित करण्यासाठी इतर अ‍ॅप्स आणि साइटवर तुमच्या पासवर्डचा पुन्हा वापर करू नका.</translation>
<translation id="1263231323834454256">वाचन सूची</translation>
<translation id="1264126396475825575"><ph name="CRASH_TIME" /> वाजता क्रॅश अहवाल कॅप्चर केला (अद्याप अपलोड केलेला नाही किंवा दुर्लक्ष केले)</translation>
<translation id="1270502636509132238">घेण्याची पद्धत</translation>
@@ -69,12 +71,14 @@
<translation id="1292701964462482250">"तुमच्या कॉंप्युटरवरील सॉफ्टवेअर Chrome ला सुरक्षितपणे वेबशी कनेक्ट होण्यापासून थांबवत आहे" (फक्‍त Windows कॉंप्युटरचा)</translation>
<translation id="1294154142200295408">विविध कमांड लाइन</translation>
<translation id="129553762522093515">अलीकडे बंद केलेले</translation>
+<translation id="1298536327547837046">मालवेअर स्कॅनिंग</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />आपल्या कुकीज साफ करून पहा<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">कालबाह्य झालेली वैशिष्‍ट्ये</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">क्लिपबोर्ड इमेज शोधा</translation>
<translation id="1323433172918577554">अधिक दाखवा</translation>
<translation id="132390688737681464">पत्ते भरा आणि सेव्ह करा</translation>
-<translation id="1333989956347591814">तुमच्या पुढील अॅक्टिव्हिटी <ph name="BEGIN_EMPHASIS" />अद्याप दिसतील<ph name="END_EMPHASIS" />:
+<translation id="1333989956347591814">तुमच्या पुढील ॲक्टिव्हिटी <ph name="BEGIN_EMPHASIS" />अद्याप दिसतील<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
<ph name="LIST_ITEM" />तुम्ही पाहत असलेल्या वेबसाइट
<ph name="LIST_ITEM" />तुमचा एम्पलॉयर किंवा शाळा
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google पत्रक</translation>
<translation id="1527263332363067270">कनेक्शनची वाट पाहत आहे...</translation>
<translation id="1529521330346880926">10x15 (Envelope)10x15 (Envelope)</translation>
+<translation id="1530707389502320859">तुम्ही नुकतेच भेट देण्याचा प्रयत्न करत असलेली साइट बनावट असल्याची दिसते. आक्रमणकर्ते काहीवेळा URL मध्ये छोटे व पाहण्यासाठी कठीण असलेले बदल करून बनावट साइट बनवतात.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">या पेजचे म्हणणे हे आहे की</translation>
<translation id="153384715582417236">सध्या इतकेच</translation>
@@ -131,7 +136,7 @@
<translation id="1569487616857761740">एक्स्पायरीची तारीख एंटर करा</translation>
<translation id="1581080074034554886">CVC</translation>
<translation id="1583429793053364125">हे वेबपेज प्रदर्शित करताना काहीतरी चूक झाली.</translation>
-<translation id="1592005682883173041">स्थानिक डेटा अॅक्सेस</translation>
+<translation id="1592005682883173041">स्थानिक डेटा ॲक्सेस</translation>
<translation id="1594030484168838125">निवडा</translation>
<translation id="161042844686301425">निळसर</translation>
<translation id="1620510694547887537">कॅमेरा</translation>
@@ -149,7 +154,7 @@
<translation id="1663943134801823270">कार्ड आणि पत्ते Chrome कडील आहेत. तुम्ही त्यांना <ph name="BEGIN_LINK" />सेटिंग्‍ज<ph name="END_LINK" /> मधून व्यवस्थापित करू शकता.</translation>
<translation id="1669987054044193553">निश्चित करा आणि सेव्ह करा</translation>
<translation id="1671391448414634642">आतापासून <ph name="SOURCE_LANGUAGE" />मधील पेज <ph name="TARGET_LANGUAGE" />मध्ये भाषांतरित केली जातील.</translation>
-<translation id="1676269943528358898"><ph name="SITE" /> तुमची माहिती संरक्षित करण्यासाठी सामान्यतः एंक्रिप्शन वापरते. Google Chrome ने यावेळी <ph name="SITE" /> शी कनेक्‍ट करण्‍याचा प्रयत्न केला तेव्‍हा, वेबसाइटने असामान्य आणि अयोग्य क्रेडेन्शियल परत पाठविले. एकतर आक्रमणकर्ता <ph name="SITE" /> असल्याची बतावणी करण्याचा प्रयत्न करतो तेव्‍हा किंवा वाय-फाय साइन इन स्क्रीनने कनेक्शनमध्ये व्यत्यय आणले तेव्‍हा हे घडू शकते. कोणत्याही डेटाची अदलाबदल करण्यापूर्वी Google Chrome ने कनेक्शन थांबविल्यामुळे तुमची माहिती अद्याप सुरक्षित आहे.</translation>
+<translation id="1676269943528358898"><ph name="SITE" /> तुमची माहिती संरक्षित करण्यासाठी सामान्यतः एंक्रिप्शन वापरते. Google Chrome ने यावेळी <ph name="SITE" /> शी कनेक्‍ट करण्‍याचा प्रयत्न केला तेव्‍हा, वेबसाइटने असामान्य आणि अयोग्य क्रेडेंशियल परत पाठवले. एकतर आक्रमणकर्ता <ph name="SITE" /> असल्याची बतावणी करण्याचा प्रयत्न करतो तेव्‍हा किंवा वाय-फाय साइन इन स्क्रीनने कनेक्शनमध्ये व्यत्यय आणले तेव्‍हा हे घडू शकते. कोणत्याही डेटाची अदलाबदल करण्यापूर्वी Google Chrome ने कनेक्शन थांबविल्यामुळे तुमची माहिती अद्याप सुरक्षित आहे.</translation>
<translation id="168841957122794586">सर्व्हर सर्टिफिकेटमध्ये एक कमकुवत क्रिप्टोग्राफिक की आहे.</translation>
<translation id="1697532407822776718">तुम्ही पूर्णपणे तयार आहात!</translation>
<translation id="1703835215927279855">Letter</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">भाष्य करण्यासाठी दस्तऐवज खूपच मोठे आहे</translation>
-<translation id="1721312023322545264">या साइटला भेट देण्यासाठी तुमच्या <ph name="NAME" /> कडील परवानगी आवश्यक आहे</translation>
<translation id="1721424275792716183">* फील्ड आवश्यक आहे</translation>
<translation id="1727741090716970331">वैध कार्ड नंबर जोडा</translation>
<translation id="1728677426644403582">तुम्ही वेब पेजचा स्रोत पाहत आहात</translation>
@@ -171,7 +175,7 @@
<translation id="1753706481035618306">पृष्ठ क्रमांक</translation>
<translation id="1763864636252898013">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षितता सर्टिफिकेट तुम्हाला डिव्हाइसच्या ऑपरेटिंग सिस्टमद्वारे विश्वसनीय नाही. हे कदाचित एका चुकीच्या कॉन्फिगरेशनमुळे किंवा हल्लेखोराने तुमचे कनेक्शन इंटरसेप्ट केल्यामुळे झाले असू शकते.</translation>
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Windows नेटवर्क निदान चालवून पहा<ph name="END_LINK" />.</translation>
-<translation id="1783075131180517613">कृपया तुमचे सिंक सांकेतिक पासफ्रेझ अपडेट करा.</translation>
+<translation id="1783075131180517613">कृपया तुमचे सिंक केलेली सांकेतिक पासफ्रेज अपडेट करा.</translation>
<translation id="1787142507584202372">तुमचे खुले टॅब येथे दिसतात</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1800473098294731951">B9</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">तुम्ही भेट देत असलेल्या वेबसाइट आणि त्यावर व्यतीत केलेला वेळ</translation>
<translation id="1826516787628120939">तपासत आहे</translation>
<translation id="1834321415901700177">या साइटमध्ये धोकादायक प्रोग्राम आहेत</translation>
+<translation id="1838374766361614909">शोध साफ करा</translation>
<translation id="1839551713262164453">धोरण मूल्यांची वैधता एररसह अयशस्वी झाली आहे</translation>
<translation id="1842969606798536927">पेमेंट करा</translation>
<translation id="1871208020102129563">प्रॉक्सी निश्चित प्रॉक्सी सर्व्हर वापरण्‍यास सेट करण्‍यात आले आहे, .pac स्क्रिप्ट URL नव्हे.</translation>
@@ -191,17 +196,19 @@
<translation id="1883255238294161206">सूची कोलॅप्स</translation>
<translation id="1898423065542865115">फिल्टर करणे</translation>
<translation id="1914326953223720820">अनझिप सेवा</translation>
+<translation id="1915697529809968049">CVC ऐवजी टच आयडी वापरायचा का?</translation>
<translation id="1916770123977586577">तुमच्या सेटिंग्ज या साइटवर लागू करण्यासाठी, हे पेज रीलोड करा</translation>
<translation id="1919345977826869612">जाहिराती</translation>
<translation id="1919367280705858090">विशिष्ट एरर मेसेजच्या बाबतीत मदत मिळवा</translation>
<translation id="192020519938775529">{COUNT,plural, =0{काहीही नाही}=1{1 साइट}other{# साइट}}</translation>
<translation id="1927235823738766038">स्वीकारली जाणारी क्रेडिट आणि डेबिट कार्डे</translation>
<translation id="194030505837763158"><ph name="LINK" /> दुव्याकडे जा</translation>
-<translation id="1945968466830820669">तुम्ही तुमच्या संस्थेच्या खात्याचा अॅक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chromium तुमचा पासवर्ड लगेच बदलण्याची शिफारस करत आहे.</translation>
+<translation id="1945968466830820669">तुम्ही तुमच्या संस्थेच्या खात्याचा ॲक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chromium तुमचा पासवर्ड लगेच बदलण्याची शिफारस करत आहे.</translation>
<translation id="1948773908305951926">स्वीकारली जाणारी प्रीपेड कार्डे</translation>
<translation id="1962204205936693436"><ph name="DOMAIN" /> बुकमार्क</translation>
<translation id="1973335181906896915">क्रमीकरण एरर</translation>
<translation id="1974060860693918893">प्रगत</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />तुम्ही भेट देता त्या काही पेजच्या URL, मर्यादित सिस्टम माहिती आणि काही पेज आशय<ph name="END_WHITEPAPER_LINK" />Google कडे पाठवून Chrome सुरक्षेमध्ये सुधारणा करण्यासाठी मदत करा. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">फर्मवेयर आवृत्ती</translation>
<translation id="1981206234434200693">Chrome चा ब्राउझिंग इतिहास डेटा साफ करा</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{आणि 1 अधिक}other{आणि # अधिक}}</translation>
@@ -237,7 +244,7 @@
<translation id="2148613324460538318">कार्ड जोडा</translation>
<translation id="2154054054215849342">आपल्या डोमेनसाठी संकालन उपलब्ध नाही</translation>
<translation id="2154484045852737596">कार्ड संपादित करा</translation>
-<translation id="2166049586286450108">पूर्ण अॅडमिन अॅक्सेस</translation>
+<translation id="2166049586286450108">पूर्ण ॲडमिन ॲक्सेस</translation>
<translation id="2166378884831602661">ही साइट सुरक्षित कनेक्शन प्रदान करू शकत नाही</translation>
<translation id="2169984857010174799">Kaku2 (Envelope)</translation>
<translation id="2181821976797666341">धोरणे</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">वैध समाप्ती वर्ष एंटर करा</translation>
<translation id="2212735316055980242">धोरण आढळले नाही</translation>
<translation id="2213606439339815911">एंट्री आणत आहे...</translation>
+<translation id="2215727959747642672">फाइलचे संपादन</translation>
<translation id="2218879909401188352">सध्या <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />वर असलेले आक्रमणकर्ता तुमच्या डिव्हाइसला हानी पोहोचवणारे धोकादायक ॲप इंस्टॉल करू शकतात, तुमच्या मोबाइल बिलामध्ये लपलेले शुल्क जोडू शकतात किंवा तुमची वैयक्तिक माहिती चोरू शकतात. <ph name="BEGIN_LEARN_MORE_LINK" />अधिक जाणून घ्या<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">इंटरनेट नाही</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />निदान ॲप<ph name="END_LINK" /> वापरून आपल्या कनेक्शनचे निराकरण करा</translation>
<translation id="2239100178324503013">आता पाठवा</translation>
+<translation id="2248949050832152960">WebAuthn वापरा</translation>
<translation id="225207911366869382">हे मूल्य या धोरणासाठी नापसंत करण्‍यात आले आहे.</translation>
<translation id="2257315177824333709">सॉरी, तुमचे कार्ड आता सेव्ह केले जाऊ शकत नाही</translation>
<translation id="2262243747453050782">HTTP एरर</translation>
@@ -258,14 +267,14 @@
<translation id="2270484714375784793">फोन नंबर</translation>
<translation id="2277103315734023688">पुढे जा</translation>
<translation id="2283340219607151381">पत्ते भरा आणि सेव्ह करा</translation>
-<translation id="2292556288342944218">तुमचा इंटरनेट अॅक्सेस ब्लॉक केला आहे</translation>
+<translation id="2292556288342944218">तुमचा इंटरनेट ॲक्सेस ब्लॉक केला आहे</translation>
<translation id="2297722699537546652">B5 (Envelope)</translation>
<translation id="2310021320168182093">Chou2 (Envelope)</translation>
<translation id="2316887270356262533">१ MB पेक्षा कमी जागा मोकळी करते. काही साइट तुमच्या पुढील भेटीच्या वेळी आणखी धीम्या गतीने लोड होऊ शकतात.</translation>
<translation id="2317259163369394535"><ph name="DOMAIN" /> साठी वापरकर्तानाव आणि पासवर्ड आवश्यक आहेत.</translation>
<translation id="2317583587496011522">डेबिट कार्डे स्वीकारली जातात.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> रोजी एक्स्पायर होईल</translation>
-<translation id="2337852623177822836">सेटिंग तुमच्या अॅडमिनिस्ट्रेटरने नियंत्रित केलेले आहे</translation>
+<translation id="2337852623177822836">सेटिंग तुमच्या ॲडमिनिस्ट्रेटरने नियंत्रित केलेले आहे</translation>
<translation id="2346319942568447007">तुम्ही कॉपी केलेली इमेज</translation>
<translation id="2354001756790975382">इतर बुकमार्क</translation>
<translation id="2354430244986887761">Google सुरक्षित ब्राउझिंगला अलीकडे <ph name="SITE" />मध्ये <ph name="BEGIN_LINK" />हानिकारक ॲप्स सापडले<ph name="END_LINK" />.</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">चुकीचे शोध URL.</translation>
<translation id="2482878487686419369">सूचना</translation>
<translation id="248348093745724435">मशीन धोरणे</translation>
-<translation id="2485387744899240041">तुमच्या डिव्हाइस आणि ब्राउझरसाठी वापरकर्तानावे</translation>
<translation id="2491120439723279231">सर्व्हरच्या सर्टिफिकेटमध्ये एरर आहेत.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON पार्सर</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">परत जा</translation>
<translation id="2503184589641749290">स्वीकारली जाणारी डेबिट आणि प्रीपेड कार्डे</translation>
<translation id="2505268675989099013">खात्याचे संरक्षण करा</translation>
+<translation id="2515335152965840738">दुर्लक्ष करा</translation>
<translation id="2515629240566999685">आपल्या क्षेत्रातील सिग्नल तपासणे</translation>
<translation id="2523886232349826891">फक्त या डिव्हाइसवर सेव्ह केले जाईल</translation>
<translation id="2524461107774643265">अधिक माहिती जोडा</translation>
@@ -325,14 +334,13 @@
<translation id="2609632851001447353">तफावत</translation>
<translation id="2618023639789766142">C10 (Envelope)</translation>
<translation id="2625385379895617796">तुमचे घड्याळ पुढे आहे</translation>
-<translation id="2634124572758952069"><ph name="HOST_NAME" /> चा सर्व्हर आयपी अॅड्रेस सापडला नाही.</translation>
+<translation id="2634124572758952069"><ph name="HOST_NAME" /> चा सर्व्हर आयपी ॲड्रेस सापडला नाही.</translation>
<translation id="2639739919103226564">स्थिती:</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
-<translation id="2650446666397867134">फाइलवरील अॅक्सेस नाकारण्यात आला</translation>
+<translation id="2650446666397867134">फाइलवरील ॲक्सेस नाकारण्यात आला</translation>
<translation id="2653659639078652383">सबमिट करा</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{काहीही नाही}=1{(<ph name="DOMAIN_LIST" /> साठी) एक पासवर्ड}=2{(<ph name="DOMAIN_LIST" /> साठी) दोन पासवर्ड}other{(<ph name="DOMAIN_LIST" /> साठी) # पासवर्ड}}</translation>
<translation id="2666117266261740852">इतर टॅब किंवा ॲप्स बंद करा</translation>
-<translation id="267371737713284912">पहिल्यासारखे करण्यासाठी <ph name="MODIFIER_KEY_DESCRIPTION" /> दाबा</translation>
<translation id="2674170444375937751">तुमची खात्री आहे की तुम्ही ही पेज आपल्‍या इतिहासातून हटवू इच्छिता?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">सोडा</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">मूल्य स्वरुपनाशी जुळत नाही.</translation>
<translation id="2705137772291741111">या साइटची सेव्ह (कॅश केलेली) केलेली प्रत वाचण्याजोगी नव्हती.</translation>
<translation id="2709516037105925701">ऑटोफिल</translation>
-<translation id="2712173769900027643">परवानगी मागा</translation>
<translation id="2713444072780614174">पांढरा</translation>
<translation id="2720342946869265578">जवळपास</translation>
<translation id="2721148159707890343">विनंती यशस्वी</translation>
<translation id="2728127805433021124">एक कमकुवत स्वाक्षरी अल्गोरिदम वापरून सर्व्हरचे सर्टिफिकेट साइन केले आहे.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />कनेक्टिव्हिटी निदान चालविणे<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">ही वैशिष्ट्ये सुरू केल्याने, तुम्ही ब्राउझर डेटा गमावू शकता किंवा
+ तुमची सुरक्षितता किंवा गोपनीयता धोक्यात असू शकते. सुरू केलेली वैशिष्ट्ये या
+ ब्राउझरच्या सर्व वापरकर्त्यांना लागू होतात.</translation>
<translation id="2735043616039983645">या धोरणासाठी परस्परविरोधी मूल्ये असलेले एकापेक्षा जास्त स्रोत आहेत!</translation>
<translation id="2738330467931008676">पिकअप पत्ता निवडा</translation>
<translation id="2740531572673183784">ठीक आहे</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">कनेक्शन रीसेट केले.</translation>
<translation id="2788784517760473862">क्रेडिट कार्डे स्वीकारली जातात</translation>
<translation id="2792012897584536778">या डिव्हाइसच्या अ‍ॅडमिनिस्ट्रेटरने सुरक्षा सर्टिफिकेट सेट केले आहे जे त्यांना तुम्ही भेट देत असलेल्या वेबसाइटचा आशय पाहण्याची परवानगी देऊ शकतात.</translation>
-<translation id="2794233252405721443">साइट अवरोधित केली</translation>
<translation id="2799020568854403057">पुढील साइटमध्ये हानिकारक ॲप आहे</translation>
<translation id="2799223571221894425">पुन्हा लाँच करा</translation>
<translation id="2803306138276472711">Google सुरक्षित ब्राउझिंगला अलीकडे <ph name="SITE" /> वर <ph name="BEGIN_LINK" />मालवेअर आढळले आहे<ph name="END_LINK" />. सामान्यतः सुरक्षित असलेल्या वेबसाइट काहीवेळा मालवेअरमुळे संक्रमित झालेल्या असतात.</translation>
+<translation id="2815364696811431560">साइट सोडा</translation>
<translation id="2824775600643448204">पत्ता आणि शोध बार</translation>
-<translation id="2826760142808435982">कनेक्शन <ph name="CIPHER" /> वापरून आणि महत्त्वाचे एक्स्चेंज तंत्र म्हणून <ph name="KX" /> वापर एंक्रिप्ट आणि अॉथेंटिकेट केले आहे.</translation>
+<translation id="2826760142808435982">कनेक्शन <ph name="CIPHER" /> वापरून आणि महत्त्वाचे एक्स्चेंज तंत्र म्हणून <ph name="KX" /> वापर एंक्रिप्ट आणि ऑथेंटिकेट केले आहे.</translation>
<translation id="2835170189407361413">फॉर्म क्लिअर करा</translation>
<translation id="2847118875340931228">गुप्त विंडो उघडा</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">या साइटला भेट देण्यासाठी तुम्हाला परवानगीची गरज आहे</translation>
<translation id="2856444702002559011">हल्लेखोर कदाचित तुमची माहिती (उदाहरणार्थ पासवर्ड, संदेश किंवा क्रेडिट कार्ड) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> मधून चोरण्याचा प्रयत्न करत असतील. <ph name="BEGIN_LEARN_MORE_LINK" />आणखी जाणून घ्या<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">कार्ड सेव्ह करायचे?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">सक्षम केल्‍यास, Chromium जलदपणे फॉर्म भरण्‍यासाठी तुमच्या कार्डची एक प्रत या डिव्‍हाइसवर संग्रहित करेल.</translation>
<translation id="2985398929374701810">वैध पत्ता एंटर करा</translation>
<translation id="2986368408720340940">ही पिकअप पद्धत उपलब्ध नाही. वेगळी पद्धत वापरून पहा.</translation>
+<translation id="2987034854559945715">कोणतीही जुळणारी वैशिष्‍ट्ये नाहीत</translation>
<translation id="2991174974383378012">वेबसाइटसह शेअर करीत आहे</translation>
<translation id="2991571918955627853">ही वेबसाइट HSTS वापरत असल्यामुळे तुम्ही <ph name="SITE" /> आत्ता पाहू शकत नाही. नेटवर्क एरर आणि आक्रमण शक्यतो तात्पुरती असतात, त्यामुळे हे पेज नंतर पाहता येईल.</translation>
<translation id="3005723025932146533">सेव्ह केलेली प्रत दर्शवा</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">चुकीचा धोरण प्रकार</translation>
<translation id="3037605927509011580">च्चक!</translation>
<translation id="3041612393474885105">सर्टिफिकेट माहिती</translation>
+<translation id="3057676462092457419">DnsOverHttps मोड <ph name="SECURE_DNS_MODE_SECURE" /> ला अद्याप सपोर्ट करत नाही, मोड <ph name="SECURE_DNS_MODE_OFF" /> वर सेट केला गेला आहे.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">पॅच सेवा</translation>
<translation id="3064966200440839136">बाह्य ॲप्लिकेशन द्वारे पेमेंट देण्यासाठी गुप्त मोड सोडत आहे. सुरु ठेवायचे?</translation>
@@ -416,17 +427,18 @@
<translation id="3150653042067488994">तात्पुरती सर्व्हर एरर</translation>
<translation id="3154506275960390542">या पेजवर एक फॉर्म आहे जो कदाचित सुरक्षितपणे सबमिट होणार नाही. तुम्ही पाठविलेला डेटा प्रवासादरम्यान इतर पाहू शकतात किंवा सर्व्हर प्राप्त करत असलेल्या आक्रमणकर्त्याद्वारे सुधारित केले जाऊ शकते.</translation>
<translation id="3157931365184549694">पुनर्संचयित करा</translation>
-<translation id="3162559335345991374">तुम्ही वापरत असलेल्या वाय-फाय च्या लॉग इन पेजला तुमच्या भेट देण्याची आवश्यकता असू शकते.</translation>
+<translation id="3162559335345991374">तुम्ही वापरत असलेल्या वाय-फाय च्या लॉग इन पेजला तुम्हाला भेट देण्याची आवश्यकता असू शकते.</translation>
<translation id="3167968892399408617">गुप्त मोडमध्‍ये तुम्ही पाहता ती पृष्‍ठे तुम्ही तुमचे सर्व गुप्त टॅब बंद केल्‍यानंतर तुमचा ब्राउझर इतिहास, कुकी स्टोअर किंवा शोध इतिहासामध्‍ये असणार नाहीत. तुम्ही डाउनलोड करता त्या कोणत्याही फायली किंवा तुम्ही केलेले बुकमार्क ठेवले जातील.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">बेट</translation>
<translation id="3176929007561373547">प्रॉक्सी सर्व्हर कार्य करत आहे हे निश्चित करण्यासाठी तुमच्या प्रॉक्सी सेटिंग्ज तपासा
- किंवा तुमच्या नेटवर्क अॅडमिनिस्ट्रेटरशी संपर्क साधा. तुम्ही प्रॉक्सी सर्व्हर वापरत
+ किंवा तुमच्या नेटवर्क ॲडमिनिस्ट्रेटरशी संपर्क साधा. तुम्ही प्रॉक्सी सर्व्हर वापरत
आहात यावर तुमचा विश्वास नसल्यास:
<ph name="PLATFORM_TEXT" /></translation>
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> वर <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">पेमेंट रद्द करा</translation>
<translation id="3207960819495026254">बुकमार्क केलेली</translation>
+<translation id="3209034400446768650">पेज कदाचित शुल्क आकारू शकते</translation>
<translation id="3225919329040284222">सर्व्हरने असे सर्टिफिकेट सादर केले आहे जे अंगभूत अपेक्षांशी जुळत नाही. या अपेक्षा तुम्हाला संरक्षित करण्यासाठी विशिष्ट, उच्च सुरक्षिततेच्या वेबसाइटसाठी समाविष्ट केल्या आहेत.</translation>
<translation id="3226128629678568754">पृष्ठ लोड करण्यास आवश्यक असलेला डेटा पुन्हा सबमिट करण्यासाठी रीलोड बटण दाबा.</translation>
<translation id="3227137524299004712">मायक्रोफोन</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">तुमच्या डिव्हाइस आणि ब्राउझरविषयी आवृत्ती माहिती</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> साठी CVC प्रविष्‍ट करा</translation>
<translation id="3234666976984236645">नेहमी या साइटवर महत्त्वाचा आशय शोधा</translation>
-<translation id="3254409185687681395">या पृष्ठास बुकमार्क करा</translation>
<translation id="3270847123878663523">&amp;पुनर्क्रमित करा पूर्ववत करा</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">कार्डवर नाव जोडा</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">बिलिंग पत्ता जोडा</translation>
<translation id="3324983252691184275">किरमिजी</translation>
<translation id="3338095232262050444">सुरक्षित</translation>
-<translation id="3345135638360864351">या साइट अॅक्सेस करण्याची तुमची विनंती <ph name="NAME" /> कडे पाठवली जाऊ शकली नाही. कृपया पुन्हा प्रयत्न करा.</translation>
<translation id="3355823806454867987">प्रॉक्सी सेटिंग्ज बदला...</translation>
<translation id="3361596688432910856">Chrome पुढील माहिती <ph name="BEGIN_EMPHASIS" />सेव्ह करणार नाही<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -478,17 +488,14 @@
<translation id="3462200631372590220">प्रगत लपवा</translation>
<translation id="3467763166455606212">कार्डधारकाचे नाव आवश्यक</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, सध्या खुला, उघड्या टॅबवर स्विच करण्यासाठी टॅब, त्यानंतर एंटर दाबा</translation>
-<translation id="3479539252931486093">हे अनपेक्षित होते? <ph name="BEGIN_LINK" />आम्हाला कळवा<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">सध्या नाही</translation>
<translation id="3484560055331845446">तुम्ही तुमच्या Google खात्याचा ॲक्सेस कदाचित गमवाल. Chrome आता तुमचा पासवर्ड बदलण्याची शिफारस करते. तुम्हाला साइन इन करण्यासाठी सांगितले जाऊ शकते.</translation>
<translation id="3495081129428749620">पेज <ph name="PAGE_TITLE" /> मध्ये शोधा</translation>
-<translation id="3498215018399854026">याक्षणी आम्ही आपल्या पालकांपर्यंत पोहोचू शकलो नाही. कृपया पुन्हा प्रयत्न करा.</translation>
<translation id="3512163584740124171">या धोरणाकडे दुर्लक्ष केले कारण त्याच धोरण गटातील दुसऱ्या धोरणाला उच्च प्राधान्य आहे.</translation>
<translation id="3528171143076753409">सर्व्हरचे सर्टिफिकेट विश्वसनीय नाही.</translation>
<translation id="3528485271872257980">गडद तपकिरी</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{ सिंक केलेल्या डिव्हाइसवर किमान 1 आयटम}=1{1 आयटम (सिंक केलेल्या डिव्‍हाइसवर आणखी काही)}other{# आयटम (सिंक केलेल्या डिव्‍हाइसवर आणि आणखी काही)}}</translation>
<translation id="3539171420378717834">या डिव्हाइसवर या कार्डची एक प्रत ठेवा</translation>
-<translation id="3556433843310711081">तुमचा व्यवस्थापक तुमच्यासाठी ती अनावरोधित करू शकतो</translation>
<translation id="3566021033012934673">तुमचे कनेक्शन खाजगी नाही</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> वरील एंबेड केलेल्‍या पेजचे म्हणणे हे आहे की</translation>
@@ -504,7 +511,7 @@
<translation id="3615877443314183785">वैध समाप्ती दिनांक एंटर करा</translation>
<translation id="36224234498066874">ब्राउझिंग डेटा साफ करा...</translation>
<translation id="362276910939193118">पूर्ण इतिहास दर्शवा</translation>
-<translation id="3630155396527302611">नेटवर्क अॅक्सेस करण्यासाठी परवानगी दिलेला प्रोग्राम म्हणून तो आधीपासून सूचीबद्ध केला असल्यास
+<translation id="3630155396527302611">नेटवर्क ॲक्सेस करण्यासाठी परवानगी दिलेला प्रोग्राम म्हणून तो आधीपासून सूचीबद्ध केला असल्यास
तो सूचीमधून काढा आणि पुन्हा जोडून पहा.</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3650584904733503804">प्रमाणीकरण यशस्वी</translation>
@@ -516,6 +523,7 @@
<translation id="3678529606614285348">पेज एका नवीन गुप्त विंडोमध्ये उघडा (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">क्रॅश अहवाल <ph name="CRASH_TIME" /> वाजता कॅप्चर केला, <ph name="UPLOAD_TIME" /> वाजता अपलोड केला</translation>
<translation id="3681007416295224113">सर्टिफिकेट माहिती</translation>
+<translation id="3701427423622901115">रीसेट करण्याची नोंद घेतली आहे.</translation>
<translation id="3704162925118123524">तुम्ही वापरत असलेल्या नेटवर्कला तुम्ही त्याच्या लॉग इन पेजला भेट देण्याची आवश्यकता असू शकते.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">लोड करीत आहे...</translation>
@@ -524,7 +532,7 @@
<translation id="3714780639079136834">मोबाइल डेटा किंवा वाय-फाय सुरू करणे</translation>
<translation id="3715597595485130451">वाय-फाय वर कनेक्ट करा</translation>
<translation id="3717027428350673159"><ph name="BEGIN_LINK" />प्रॉक्सी, फायरवॉल आणि DNS कॉन्फिगरेशन तपासणे<ph name="END_LINK" /></translation>
-<translation id="372429172604983730">या एररला कारणीभूत असू शकणार्‍या अॅप्लिकेशनमध्ये अँटिव्हायरस, फायरवॉल आणि वेब फिल्टरिंग किंवा प्रॉक्सी सॉफ्टवेअरचा समावेश होतो.</translation>
+<translation id="372429172604983730">या एररला कारणीभूत असू शकणार्‍या ॲप्लिकेशनमध्ये अँटिव्हायरस, फायरवॉल आणि वेब फिल्टरिंग किंवा प्रॉक्सी सॉफ्टवेअरचा समावेश होतो.</translation>
<translation id="373042150751172459">B4 (Envelope)</translation>
<translation id="3736520371357197498">तुम्ही तुमच्या सुरक्षिततेच्या जोखमी समजत असल्यास, धोकादायक प्रोग्राम काढण्यापूर्वी तुम्ही <ph name="BEGIN_LINK" />या असुरक्षित साइटला भेट देऊ शकता<ph name="END_LINK" />.</translation>
<translation id="3744899669254331632">Chromium प्रक्रिया करू शकत नसलेले सरमिसळ केलेले क्रेडेन्‍शियल वेबसाइटने पाठविल्‍याने तुम्ही आत्ता <ph name="SITE" /> ला भेट देऊ शकत नाही. नेटवर्क एरर आणि आक्रमण सहसा तात्पुरते आहेत त्यामुळे संभवत: हे पेज नंतर कार्य करेल.</translation>
@@ -532,6 +540,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> वरील हल्लेखोर कदाचित तुम्हाला सॉफ्टवेअर इंस्टॉल करणे किंवा तुमची वैयक्तिक माहिती (उदाहरणार्थ, पासवर्ड, फोन नंबर किंवा क्रेडिट कार्डे) उघड करणे यासारख्या काही धोकादायक गोष्टी करण्यासाठी तुम्हाला फसवू शकतात. <ph name="BEGIN_LEARN_MORE_LINK" />आणखी जाणून घ्या<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">सर्व्हर एररमुळे भाषांतर अयशस्वी झाले.</translation>
<translation id="3759461132968374835">तुम्ही अलीकडे कोणतेही क्रॅश नोंदवले नाहीत. क्रॅश नोंदवणे अक्षम असताना झालेले क्रॅश येथे दिसून येणार नाहीत.</translation>
+<translation id="3760561303380396507">CVC ऐवजी Windows Hello वापरायचे का?</translation>
<translation id="3761718714832595332">स्थिती लपवा</translation>
<translation id="3765032636089507299">सुरक्षित ब्राउझिंग पेज तयार होत आहे.</translation>
<translation id="3778403066972421603">तुम्हाला हे कार्ड तुमच्या Google खात्यामध्ये आणि या डिव्हाइसवर सेव्ह करायचे आहे का?</translation>
@@ -541,6 +550,7 @@
<translation id="3789155188480882154">आकार १६</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">हानिकारक आशय ब्लॉक केला गेला.</translation>
+<translation id="3808375843007691220">चेतावणी: पुढे प्रायोगिक वैशिष्ट्ये आहेत!</translation>
<translation id="3810973564298564668">व्यवस्थापित करा</translation>
<translation id="382518646247711829">तुम्ही प्रॉक्सी सर्व्हर वापरत असल्यास...</translation>
<translation id="3828924085048779000">रिक्त सांकेतिक पासफ्रेझाची परवानगी नाही.</translation>
@@ -549,11 +559,11 @@
<translation id="3858027520442213535">तारीख आणि वेळ अपडेट करा</translation>
<translation id="3884278016824448484">संघर्ष करणारा डिव्हाइस अभिज्ञापक</translation>
<translation id="3885155851504623709">परगणा</translation>
-<translation id="3886446263141354045">या साइट अॅक्सेस करण्याची तुमची विनंती <ph name="NAME" /> कडे पाठवली गेली आहे</translation>
<translation id="3890664840433101773">ईमेल जोडा</translation>
<translation id="3901925938762663762">कार्ड कालबाह्य झाले आहे</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVC ऐवजी WebAuthn वापरायचे का?</translation>
<translation id="3946209740501886391">नेहमी या साइटवर विचारा</translation>
<translation id="3949571496842715403">हा सर्व्हर <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षा सर्टिफिकेट विषय पर्यायी नावांचा उल्लेख करत नाही. हे कदाचित चुकीच्या कॉंफिगरेशनमुळे होत आहे किंवा हल्लेखोर तुमच्या कनेक्शनमध्ये अडथळा आणत आहे.</translation>
<translation id="3949601375789751990">तुमचा ब्राउझिंग इतिहास येथे दिसतो</translation>
@@ -564,11 +574,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{काहीही नाही}=1{1 साइटकडून }other{# साइटकडून }}</translation>
<translation id="397105322502079400">गणना करत आहे...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> अवरोधित केले आहे</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ने तुमच्या ब्राउझरवर Chrome एंटरप्राइझ जोखीम सुरक्षितता सुरू केली आहे. Chrome एंटरप्राइझ जोखीम सुरक्षितते ला तुमच्या काही डेटाचा ॲक्सेस आहे.</translation>
<translation id="3987940399970879459">1 MB पेक्षा कमी</translation>
<translation id="40103911065039147">{URL_count,plural, =1{जवळपास १ वेब पेज}other{जवळपास # वेब पेज}}</translation>
<translation id="4030383055268325496">&amp;जोडा पूर्ववत करा</translation>
<translation id="4032320456957708163">तुमचा ब्राउझर <ph name="ENROLLMENT_DOMAIN" /> द्वारे व्यवस्थापित केला आहे</translation>
-<translation id="4034375457890803692">तुम्ही उघडलेली लिंक अशा साइटवर जाते ज्या साइटला तुम्ही नेहमी भेट देत नाही. हे कदाचित तुम्हाला गोंधळात टाकू शकते.</translation>
<translation id="4058922952496707368">की "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">वैध पत्ता जोडा</translation>
@@ -580,7 +590,8 @@
<translation id="4098354747657067197">भ्रामक साइट पुढे आहे</translation>
<translation id="4103249731201008433">डिव्हाइस सिरीयल क्रमांक चुकीचा आहे</translation>
<translation id="410351446219883937">ऑटोप्ले</translation>
-<translation id="4103763322291513355">तुमच्या सिस्टम अॅडमिनिस्ट्रेटरद्वारे प्रवर्तित ब्लॅकलिस्टीतील URLs आणि अन्य धोरणांची सूची पाहण्यासाठी &lt;strong&gt;chrome://policy&lt;/strong&gt; ला भेट द्या.</translation>
+<translation id="4103763322291513355">तुमच्या सिस्टम ॲडमिनिस्ट्रेटरद्वारे प्रवर्तित ब्लॅकलिस्टीतील URLs आणि अन्य धोरणांची सूची पाहण्यासाठी &lt;strong&gt;chrome://policy&lt;/strong&gt; ला भेट द्या.</translation>
+<translation id="4108231218301530806">या कार्डची पुढच्या वेळी पडताळणी करण्यासाठी फिंगरप्रिंट वापरा.</translation>
<translation id="4110652170750985508">तुमचे पेमेंट पुन्हा एकदा तपासा</translation>
<translation id="4112140312785995938">मागे शोधा</translation>
<translation id="4116663294526079822">या साइटवर नेहमी अनुमती द्या</translation>
@@ -595,6 +606,7 @@
<translation id="4171400957073367226">खराब पडताळणी स्वाक्षरी</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{आणखी <ph name="ITEM_COUNT" /> आयटम}other{आणखी <ph name="ITEM_COUNT" /> आयटम}}</translation>
+<translation id="4176463684765177261">अक्षम केले</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">पुढील वेळेस जलद पेमेंट करण्यासाठी, तुमच्या Google खात्यामध्ये तुमचे कार्ड आणि बिलिंग पत्ता जोडा.</translation>
<translation id="4196861286325780578">&amp;हलवा पुन्हा करा</translation>
@@ -626,11 +638,12 @@
<translation id="425582637250725228">तुम्ही केलेले बदल कदाचित सेव्ह केले जाणार नाहीत.</translation>
<translation id="4258748452823770588">खराब स्वाक्षरी</translation>
<translation id="4261046003697461417">संरक्षित दस्तऐवजमध्ये भाष्य केले जाऊ शकत नाही</translation>
-<translation id="4265872034478892965">तुमच्या अॅडमिनिस्ट्रेटरकडून परवानगी असलेले</translation>
+<translation id="4265872034478892965">तुमच्या ॲडमिनिस्ट्रेटरकडून परवानगी असलेले</translation>
<translation id="4275830172053184480">तुमचा डिव्हाइस रीस्टार्ट करा</translation>
<translation id="4277028893293644418">पासवर्ड रीसेट करा</translation>
<translation id="4279811152705618813">तुमचा <ph name="DEVICE_TYPE" /> <ph name="ENROLLMENT_DOMAIN" /> द्वारे व्यवस्थापित केला आहे</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{हे कार्ड तुमच्या Google खात्यात सेव्ह केले गेले}other{ही कार्डे तुमच्या Google खात्यात सेव्ह केली गेली}}</translation>
+<translation id="428847186335018806">तुम्ही Chrome मध्ये डाउनलोड आणि अपलोड केलेल्या फाइल स्कॅन करा.</translation>
<translation id="42981349822642051">विस्तृत करा</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">स्विच</translation>
@@ -660,7 +673,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">प्रॉक्सीचा वापर अक्षम करण्‍यात आला आहे पण एक सुस्पष्‍ट प्रॉक्सी कॉन्‍फिगरेशन निर्दिष्‍ट करण्‍यात आले आहे.</translation>
<translation id="445100540951337728">डेबिट कार्डे स्वीकारली जातात</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> संशयास्पद वर्तन</translation>
<translation id="4466881336512663640">फॉर्म बदल गमावतील. तुम्हाला नक्की पुढे सुरू ठेवायचे आहे?</translation>
<translation id="4477350412780666475">पुढील ट्रॅक</translation>
<translation id="4482953324121162758">या साइटचे भाषांतर केले जाणार नाही.</translation>
@@ -669,7 +681,7 @@
<translation id="4503882053543859973">Architecture-D</translation>
<translation id="4506176782989081258">ऑथेंटिकेशन एरर: <ph name="VALIDATION_ERROR" /></translation>
<translation id="4506599922270137252">सिस्टम प्रशासकाशी संपर्क साधणे</translation>
-<translation id="450710068430902550">अॅडमिनिस्ट्रेटर शेअर करत आहे</translation>
+<translation id="450710068430902550">ॲडमिनिस्ट्रेटर शेअर करत आहे</translation>
<translation id="4510487217173779431">Chou4 (Envelope)</translation>
<translation id="4515275063822566619">कार्ड आणि पत्ते Chrome आणि आपल्या Google खात्याकडील (<ph name="ACCOUNT_EMAIL" />) आहेत. तुम्ही त्यांना <ph name="BEGIN_LINK" />सेटिंग्‍ज<ph name="END_LINK" /> मधून व्यवस्थापित करू शकता.</translation>
<translation id="4517607026994743406">Comm-10 (Envelope)</translation>
@@ -687,6 +699,7 @@
<translation id="4594403342090139922">&amp;हटवा पूर्ववत करा</translation>
<translation id="4597348597567598915">आकार ८</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">शोध वैशिष्ट्ये</translation>
<translation id="4646534391647090355">आता मला तेथे घेऊन जा</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याच्या सुरक्षितता सर्टिफिकेटमध्ये एरर आहेत. हे कदाचित एका चुकीच्या कॉंफिगरेशनमुळे किंवा हल्लेखोराने तुमचे कनेक्शन इंटरसेप्ट केल्यामुळे झाले असू शकते.</translation>
@@ -695,7 +708,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">आपल्या कनेक्शनमध्ये व्यत्यय आला</translation>
-<translation id="471880041731876836">या साइटला भेट देण्याची तुम्हाला परवानगी नाही</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवर्क निदान चालविणे<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">धोरणे रीलोड करा</translation>
<translation id="4728558894243024398">प्लॅटफॉर्म</translation>
@@ -713,7 +725,7 @@
<translation id="4771973620359291008">एक अज्ञात एरर आली आहे.</translation>
<translation id="4780900888022378816">तुमचे डिव्हाइस <ph name="ENROLLMENT_DOMAIN" /> कडून व्यवस्थापित केले जाते आणि तुमचे खाते <ph name="ACCOUNT_DOMAIN" /> कडून व्यवस्थापित केले जाते.</translation>
<translation id="4785689107224900852">या टॅबवर स्विच करा</translation>
-<translation id="4791134497475588553">इंस्टॉल केलेली Linux अॅप्स आणि ती कधी शेवटची वापरली</translation>
+<translation id="4791134497475588553">इंस्टॉल केलेली Linux अ‍ॅप्स आणि ती कधी शेवटची वापरली</translation>
<translation id="4798078619018708837">तुमच्या कार्डाचा तपशील अपडेट करण्यासाठी <ph name="CREDIT_CARD" /> साठी कार्डची एक्स्पायरेशन तारीख आणि CVC टाका. तुम्ही निश्चित केल्यानंतर, तुमच्या Google खात्यामधील कार्डाचा तपशील या साइटसोबत शेअर केला जाईल.</translation>
<translation id="4800132727771399293">तुमची कालबाह्यता तारीख आणि CVC तपासा आणि पुन्हा प्रयत्न करा</translation>
<translation id="480334179571489655">मूळ धोरण एरर</translation>
@@ -723,7 +735,6 @@
<translation id="4816492930507672669">पृष्‍ठानुरुप करा</translation>
<translation id="4850886885716139402">पहा</translation>
<translation id="4854362297993841467">ही वितरण पद्धत उपलब्ध नाही. वेगळी पद्धत वापरून पहा.</translation>
-<translation id="4858792381671956233">या साइटला भेट देणे ठीक आहे का ते तुम्ही तुमच्या पालकांना विचारले</translation>
<translation id="4864052566555297930">सुरक्षाविषयक सूचना:</translation>
<translation id="4876188919622883022">सिंप्लिफाइड व्ह्यू</translation>
<translation id="4876305945144899064">वापरकर्तानाव नाही</translation>
@@ -747,13 +758,15 @@
<translation id="4974590756084640048">चेतावण्या पुन्हा सुरू करा</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">सर्व पाहा</translation>
+<translation id="4989542687859782284">अनुपलब्ध</translation>
<translation id="4989809363548539747">हे प्लगइन सपोर्टेड नाही</translation>
+<translation id="4995216769782533993">या साइटसोबत तुमच्या कार्डाचा तपशील शेअर करण्यासाठी सुरक्षा कोडची खात्री करा</translation>
<translation id="5002932099480077015">सक्षम केल्‍यास, Chrome जलदपणे फॉर्म भरण्‍यासाठी तुमच्या कार्डची एक प्रत या डिव्‍हाइसवर संग्रहित करेल.</translation>
<translation id="5015510746216210676">मशीन नाव:</translation>
<translation id="5017554619425969104">तुम्ही कॉपी केलेला मजकूर</translation>
<translation id="5018422839182700155">हे पृष्‍ठ उघडू शकत नाही</translation>
<translation id="5019198164206649151">समर्थन संचयन खराब स्थितीत</translation>
-<translation id="5023310440958281426">तुमच्या अॅडमिनिस्ट्रेटरची धोरणे तपासा</translation>
+<translation id="5023310440958281426">तुमच्या ॲडमिनिस्ट्रेटरची धोरणे तपासा</translation>
<translation id="5029568752722684782">कॉपी साफ करा</translation>
<translation id="503069730517007720">"<ph name="SOFTWARE_NAME" />" साठी मूळ सर्टिफिकेट आवश्यक आहे परंतु ते इंस्टॉल केलेले नाही. तुमच्या IT अ‍ॅडमिनिस्ट्रेटरने ही समस्या सोडण्यासाठी "<ph name="SOFTWARE_NAME" />" साठीच्या कॉन्फिगरेशन सूचना पहाव्यात. <ph name="FURTHER_EXPLANATION" /></translation>
<translation id="5031870354684148875">Google भाषांतर बद्दल</translation>
@@ -776,6 +789,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-बिट)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">तुमच्या कार्डाची पडताळणी करा</translation>
<translation id="5135404736266831032">पत्ते व्यवस्थापित करा...</translation>
<translation id="5138227688689900538">कमी दाखवा</translation>
<translation id="5141240743006678641">तुमच्या Google क्रेडेंशियलसह सिंक केलेले पासवर्ड एंक्रिप्ट करा</translation>
@@ -783,7 +797,7 @@
<translation id="515292512908731282">C4 (Envelope)</translation>
<translation id="5159010409087891077">नवीन गुप्त विंडोमध्ये पेज उघडा (⇧⌘N)</translation>
<translation id="516920405563544094"><ph name="CREDIT_CARD" /> चा CVC टाका. तुम्ही निश्चित केल्यानंतर तुमच्या Google खात्यामधील कार्डाचा तपशील या साइटसोबत शेअर केला जाईल.</translation>
-<translation id="5169827969064885044">तुम्ही तुमच्या संस्थेच्या खात्याचा अॅक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chrome लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
+<translation id="5169827969064885044">तुम्ही तुमच्या संस्थेच्या खात्याचा ॲक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chrome लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
<translation id="5171045022955879922">URL शोधा किंवा टाइप करा</translation>
<translation id="5171689220826475070">Fanfold-European</translation>
<translation id="5172758083709347301">मशीन</translation>
@@ -802,6 +816,7 @@
<translation id="5251803541071282808">क्लाउड</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">संपूर्ण सिस्टमला लागू होणारी वैशिष्‍ट्ये फक्त मालकाद्वारे सेट केली जाऊ शकतात: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">चेतावणी: PolicyListMultipleSourceMergeList मध्ये नमूद केल्याप्रमाणे हे धोरण विलीन केले नाही कारण ते शब्दकोश धोरणांचा भाग नाही जो विलीन केला जाऊ शकतो.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">बंद करा</translation>
@@ -825,7 +840,6 @@
<translation id="536296301121032821">धोरण सेटिंग्ज संचयित करण्यात अयशस्वी</translation>
<translation id="5371425731340848620">कार्ड अपडेट करा</translation>
<translation id="5377026284221673050">"तुमचे क्लॉक मागे पडले आहे" किंवा "तुमचे क्लॉक वेळेपेक्षा पुढे आहे" किंवा "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">हे पेज कदाचित तुमची फसवणूक करण्याचा, वैयक्तिक माहिती चोरण्याचा किंवा तुमच्या डिव्हाइसला हानी पोहोचवण्याचा प्रयत्न करेल. वैयक्तिक माहिती एंटर करताना किंवा डाउनलोड केलेल्या फाइल उघडताना सावध राहा.</translation>
<translation id="5384855140246857529">तुमच्या सर्व डिव्हाइसवर तुमची कार्डे वापरण्यासाठी साइन इन करा आणि सिंक सुरू करा.</translation>
<translation id="5386426401304769735">या साइटसाठी असलेल्या सर्टिफिकेट श्रृंखलेत SHA-1 वापरून स्वाक्षरी केलेले सर्टिफिकेट असते.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -839,13 +853,15 @@
<translation id="5457113250005438886">चुकीचा</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> आणखी}other{<ph name="CONTACT_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> आणखी}}</translation>
<translation id="5470861586879999274">&amp;संपादित करा पुन्हा करा</translation>
+<translation id="5473728911100096288">ही वैशिष्ट्ये सुरू करून, तुम्ही कालबाह्य झालेली वैशिष्ट्ये वापराल
+ जी भविष्यातील आवृत्त्यांमध्ये दिसणार नाहीत.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">हा आशय तुमच्या डिव्हाइसवर तुमची माहिती चोरू किंवा मिटवू शकणारे धोकादायक सॉफ्टवेअर इंस्टॉल करण्याचा कदाचित प्रयत्न करेल. <ph name="BEGIN_LINK" />तरीही दाखवा<ph name="END_LINK" /></translation>
<translation id="54817484435770891">वैध पत्ता जोडा</translation>
<translation id="5490432419156082418">पत्ते आणि बरेच काही</translation>
<translation id="5492298309214877701">कंपनी, संस्था किंवा शाळा इंट्रानेट वरील या साइटची URL बाह्य वेबसाइटसारखीच आहे.
<ph name="LINE_BREAK" />
- सिस्टम अॅडमिनिस्ट्रेटरशी संपर्क साधण्याचा प्रयत्न करा.</translation>
+ सिस्टम ॲडमिनिस्ट्रेटरशी संपर्क साधण्याचा प्रयत्न करा.</translation>
<translation id="549333378215107354">आकार ३</translation>
<translation id="5509762909502811065">B0</translation>
<translation id="5509780412636533143">व्यवस्थापित केलेले बुकमार्क</translation>
@@ -862,7 +878,6 @@
<translation id="5570825185877910964">खात्याचे संरक्षण करा</translation>
<translation id="5571083550517324815">या पत्त्यावरून पिक अप करू शकत नाही. वेगळा पत्ता निवडा.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 वापरात आहे}other{# वापरात आहेत}})</translation>
-<translation id="5572851009514199876">कृपया सुरुवात करा आणि Chrome मध्‍ये साइन इन करा जेणेकरून तुम्हाला या साइट अॅक्सेस करण्‍याची परवानगी आहे किंवा नाही ते Chrome तपासू शकेल.</translation>
<translation id="5580958916614886209">तुमचा कालबाह्यता महिना तपासा आणि पुन्हा प्रयत्न करा</translation>
<translation id="5586446728396275693">कोणतेही सेव्ह केलेले ॲड्रेस नाही</translation>
<translation id="5595485650161345191">पत्ता संपादित करा</translation>
@@ -870,6 +885,7 @@
<translation id="560412284261940334">व्यवस्थापन समर्थित नाही</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">ही साइट बनावट किंवा कपटपूर्ण असू शकते. आता सोडून देण्याची Chrome शिफारस करते.</translation>
<translation id="5610142619324316209">कनेक्शन तपासणे</translation>
<translation id="5610807607761827392">तुम्ही कार्ड आणि पत्ते <ph name="BEGIN_LINK" />सेटिंग्ज<ph name="END_LINK" /> मध्ये व्यवस्थापित करू शकता.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> नी आपल्‍याला अनेक वेळा पुनर्निर्देशित केले.</translation>
@@ -893,11 +909,11 @@
<translation id="5720705177508910913">वर्तमान वापरकर्ता</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">तुम्ही तुमच्या पासवर्डचा इतर साइटवर पुन्हा वापर केला असेल तर Chrome तुम्हाला तो रीसेट करण्याची शिफारस करत आहे.</translation>
-<translation id="5732392974455271431">तुमचे पालक तुमच्यासाठी ती अनावरोधित करू शकतात</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{तुमच्या Google खात्यामध्ये कार्ड सेव्ह करा}other{तुमच्या Google खात्यामध्ये कार्डे सेव्ह करा}}</translation>
<translation id="5763042198335101085">वैध ईमेल ॲड्रेस एंटर करा</translation>
<translation id="5765072501007116331">वितरण पद्धती आणि आवश्यकता पाहण्यासाठी, एक पत्ता निवडा</translation>
<translation id="5778550464785688721">MIDI डिव्हाइसेस पूर्ण नियंत्रण</translation>
+<translation id="5781136890105823427">प्रयोग सुरू केला आहे</translation>
<translation id="578305955206182703">अंबर</translation>
<translation id="57838592816432529">म्यूट करा</translation>
<translation id="5784606427469807560">आपल्या कार्डची पुष्टी करताना समस्या आली. तुमचे इंटरनेट कनेक्शन तपासा आणि पुन्हा प्रयत्न करा.</translation>
@@ -907,20 +923,23 @@
<translation id="5798683403665926540">Chrome सेटिंग्जमध्ये होम पेज बदला</translation>
<translation id="5803412860119678065">तुम्ही तुमचे <ph name="CARD_DETAIL" /> भरू इच्छित आहात?</translation>
<translation id="5804241973901381774">परवानग्या</translation>
-<translation id="5810442152076338065">तुमचे <ph name="DOMAIN" /> वरील कनेक्शन अॉब्सोलीट सायफर सूट वापरून एंक्रिप्ट केलेले आहे.</translation>
+<translation id="5810442152076338065">तुमचे <ph name="DOMAIN" /> वरील कनेक्शन ऑब्सोलीट सायफर सूट वापरून एंक्रिप्ट केलेले आहे.</translation>
<translation id="5813119285467412249">&amp;जोडा पुन्हा करा</translation>
<translation id="583281660410589416">अज्ञात</translation>
<translation id="5838278095973806738">या साइटवर कोणतीही संवेदनशील माहिती (उदाहरणार्थ, पासवर्ड किंवा क्रेडिट कार्ड) एंटर करू नका, कारण आक्रमणकर्ते ती चोरू शकतात.</translation>
<translation id="5860033963881614850">बंद</translation>
<translation id="5863847714970149516">पुढील पेजवर तुमच्याकडून शुल्क आकारले जाऊ शकते</translation>
<translation id="5866257070973731571">फोन नंबर जोडा</translation>
+<translation id="5866898949289125849">तुम्ही डेव्हलपर टूल पेज पाहत आहात</translation>
<translation id="5869405914158311789">या साइटवर पोहचणे शक्य नाही</translation>
<translation id="5869522115854928033">सेव्ह केलेले पासवर्ड</translation>
<translation id="5887400589839399685">कार्ड सेव्ह केले</translation>
<translation id="5893752035575986141">क्रेडिट कार्डे स्वीकारली जातात.</translation>
+<translation id="5895138241574237353">रीस्टार्ट करा</translation>
<translation id="5901630391730855834">पिवळा</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (सिंक केलेले)</translation>
<translation id="5916664084637901428">चालू</translation>
+<translation id="59174027418879706">सक्षम</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google खात्यात कार्ड सेव्ह करायचे?</translation>
<translation id="5922853866070715753">जवळजवळ पूर्ण झाले</translation>
@@ -948,13 +967,14 @@
<translation id="6039846035001940113">समस्या कायम राहिल्यास साइटच्या मालकाशी संपर्क साधा.</translation>
<translation id="6040143037577758943">बंद करा</translation>
<translation id="6044573915096792553">आकार १२</translation>
-<translation id="6047233362582046994">तुम्हाला तुमच्या सुरक्षेला असणारा धोका समजत असल्यास, हानिकारक अॅप्स काढले जाण्यापूर्वी तुम्ही <ph name="BEGIN_LINK" />या साइटला भेट देऊ शकता<ph name="END_LINK" />.</translation>
+<translation id="6047233362582046994">तुम्हाला तुमच्या सुरक्षेला असणारा धोका समजत असल्यास, हानिकारक अ‍ॅप्स काढले जाण्यापूर्वी तुम्ही <ph name="BEGIN_LINK" />या साइटला भेट देऊ शकता<ph name="END_LINK" />.</translation>
<translation id="6047927260846328439">हा आशय तुम्हाला सॉफ्टवेअर इंस्टॉल करण्याचा किंवा वैयक्तिक माहिती उघड करण्याचा फसवा प्रयत्न करू शकेल. <ph name="BEGIN_LINK" />तरीही दाखवा<ph name="END_LINK" /></translation>
<translation id="6051221802930200923">ही वेबसाइट सर्टिफिकेट पिनिंग वापरत असल्यामुळे तुम्ही आत्ता <ph name="SITE" /> पाहू शकणार नाही. नेटवर्क एरर आणि आक्रमण शक्यतो तात्पुरती असतात, त्यामुळे हे पेज नंतर पाहता येईल.</translation>
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">तुमच्या सर्व डिव्हाइसवर तुमची कार्डे वापरायची का?</translation>
<translation id="6059925163896151826">USB डिव्हाइसेस</translation>
-<translation id="6080696365213338172">तुम्ही अॅडमिनिस्ट्रेटरने-दिलेले प्रमाणपत्र वापरून आशय अॅक्सेस केला. तुम्ही <ph name="DOMAIN" /> वर प्रदान करता तो डेटा तुमच्या अॅडमिनिस्ट्रेटरद्वारे अंतःखंडित केला जाऊ शकतो.</translation>
+<translation id="6060009363608157444">चुकीचा DnsOverHttps मोड.</translation>
+<translation id="6080696365213338172">तुम्ही ॲडमिनिस्ट्रेटरने-दिलेले प्रमाणपत्र वापरून आशय ॲक्सेस केला. तुम्ही <ph name="DOMAIN" /> वर प्रदान करता तो डेटा तुमच्या ॲडमिनिस्ट्रेटरद्वारे अंतःखंडित केला जाऊ शकतो.</translation>
<translation id="6094273045989040137">भाष्य करा</translation>
<translation id="610911394827799129">तुमच्या Google खात्यामध्ये <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> वर ब्राउझिंग इतिहासाची अन्य स्वरूपे असू शकतात.</translation>
<translation id="6132597952260690497">इंस्टॉल केलेल्या एक्स्टेंशन आणि प्लग-इनविषयी माहिती</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">बुकमार्क संपादित करा</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> साठी कालबाह्यता तारीख आणि CVC प्रविष्‍ट करा</translation>
-<translation id="6414888972213066896">या साइटला भेट देणे ठीक आहे का ते तुम्ही तुमच्या पालकास विचारले</translation>
<translation id="6415778972515849510">तुमच्या Google खात्याचे संरक्षण करण्यात आणि तुमचा पासवर्ड बदलण्यात Chromium तुम्हाला मदत करू शकते.</translation>
-<translation id="6417515091412812850">सर्टिफिकेट मागे घेतले की नाही हे तपासता आले नाही.</translation>
<translation id="6431585503458005759">स्टोअर करू नका</translation>
<translation id="6433490469411711332">संपर्क माहिती संपादित करा</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> नी कनेक्ट करण्यास नकार दिला.</translation>
<translation id="6434309073475700221">नाकारा</translation>
+<translation id="6435221585574090192">तुमच्या अ‍ॅडमिनिस्ट्रेटरला Chrome एंटरप्राइझ जोखीम सुरक्षितता ने फ्लॅग केलेल्या सुरक्षितता इव्‍हेंटसंबंधित डेटा शेअर करा. यामध्ये कदाचित पेजची url, फाइलचे नाव आणि फाइल मेटाडेटा, तुमच्या डिव्हाइसचे वापरकर्ता नाव आणि Chrome चे वापरकर्ता नाव यांचा समावेश आहे.</translation>
<translation id="6440503408713884761">दुर्लक्ष केले</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">अधिक माहिती जोडा</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">पासवर्ड व्यवस्थापित करा...</translation>
<translation id="647261751007945333">डिव्हाइस धोरणे</translation>
<translation id="6476284679642588870">पेमेंट पद्धती व्यवस्थापित करा</translation>
-<translation id="6477321094435799029">Chrome ला या पृष्‍ठावर असमान्य कोड सापडला आहे आणि तुमची वैयक्तिक माहिती (उदा, पासवर्ड, फोन नंबर आणि क्रेडिट कार्ड) संरक्षित करण्‍यासाठी अवरोधित केला आहे.</translation>
<translation id="6489534406876378309">क्रॅश अपलोड करणे प्रारंभ करा</translation>
<translation id="6499038740797743453">पासवर्ड रीसेट करायचा?</translation>
<translation id="6507833130742554667">क्रेडिट आणि डेबिट कार्डे स्वीकरली जातात.</translation>
<translation id="650855688985305916">होय, स्टोअर करा</translation>
<translation id="6508722015517270189">Chrome रीस्टार्ट करा</translation>
<translation id="6517596291481585650">चेतावणी: धोरणामध्ये नमूद केल्याप्रमाणे हे धोरण सूची म्हणून विलीन केले नाही कारण ती एखादी सूची नाही.</translation>
+<translation id="6518133107902771759">सत्यापित करा</translation>
<translation id="6521745193039995384">सुरू नाही</translation>
<translation id="6529602333819889595">&amp;पुन्हा करा हटवा</translation>
<translation id="6534179046333460208">वास्तविक वेब सूचना</translation>
<translation id="6545864417968258051">ब्लूटूथ स्कॅन करत आहे</translation>
<translation id="6554795675067793129">तुमचे खाते <ph name="ENROLLMENT_DOMAIN" /> ने व्यवस्थापित केले आहे.</translation>
<translation id="6556866813142980365">पुन्हा करा</translation>
-<translation id="6563469144985748109">आपल्या व्यवस्थापकाने अद्याप ती मंजूर केली नाही</translation>
<translation id="6569060085658103619">तुम्ही एक एक्स्टेंशन पेज पाहत आहात</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">फिकट गुलाबी</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">साफ करा</translation>
<translation id="6644283850729428850">हे धोरण नापसंत आहे.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{काहीही नाही}=1{एका साइटवरून (तुम्हाला तुमच्या Google खात्यातून साइन आउट केले जाणार नाही)}other{# साइटवरून (तुम्हाला तुमच्या Google खात्यातून साइन आउट केले जाणार नाही)}}</translation>
+<translation id="6652101503459149953">Windows Hello वापरा</translation>
<translation id="6657585470893396449">पासवर्ड</translation>
<translation id="6670613747977017428">सुरक्षिततेकडे परत जा.</translation>
<translation id="6671697161687535275">Chromium वरून फॉर्म सूचना काढून टाकायच्या?</translation>
<translation id="6685834062052613830">साइन आउट करा आणि सेटअप पूर्ण करा</translation>
<translation id="6689271823431384964">तुम्ही साइन इन केले असल्यामुळे Chrome तुमच्या Google खात्यामध्ये तुमची कार्डे सेव्ह करत आहे. तुम्‍ही हे वर्तन सेटिंग्‍जमध्‍ये बदलू शकता. कार्डधारकाचे नाव तुमच्या खात्यामधून घेतले जाते.</translation>
+<translation id="6707256370811247129">कॅशेचा आशय आणि तुम्ही Chrome मध्ये डाउनलोड किंवा अपलोड करता त्या फाइल स्कॅन करा</translation>
<translation id="6710213216561001401">मागील</translation>
<translation id="6710594484020273272">&lt;शोध संज्ञा एंटर करा&gt;</translation>
<translation id="671076103358959139">नोंदणी टोकन:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">तुमचा डेटा तुमच्या <ph name="BEGIN_LINK" />सिंक पासफ्रेज<ph name="END_LINK" /> ने <ph name="TIME" /> वाजता एंक्रिप्ट केला गेला होता. सिंक सुरू करण्यासाठी तो एंटर करा.</translation>
<translation id="674375294223700098">अज्ञात सर्व्हर सर्टिफिकेट एरर.</translation>
<translation id="6744009308914054259">कनेक्शनची वाट पाहत असताना, तुम्ही ऑफलाइन लेख वाचण्यासाठी डाउनलोडवर जाऊ शकता.</translation>
+<translation id="6747611005629681221">चेतावणी: पुढे कालबाह्य झालेली वैशिष्‍ट्ये आहेत!</translation>
<translation id="6753269504797312559">धोरण मूल्य</translation>
<translation id="6757797048963528358">तुमचे डिव्हाइस निष्क्रीय झाले.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">आपल्या पालकाने अद्याप ती मंजूर केली नाही</translation>
<translation id="67862343314499040">जांभळा</translation>
<translation id="6786747875388722282">विस्तार</translation>
<translation id="6790428901817661496">प्ले करा</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">या जागा भरणे आवश्यक</translation>
<translation id="6810899417690483278">सानुकूलीकरण आयडी</translation>
<translation id="6825578344716086703">तुम्ही <ph name="DOMAIN" /> वर पोहोचण्याचा प्रयत्न केला, परंतु सर्व्हरने एका कमकुवत स्वाक्षरी अल्गोरिदमचा (जसे SHA-1) वापर करून स्वाक्षरीकृत केलेले प्रमाणपत्र सादर केले. याचा अर्थ असा आहे, की सर्व्हरने सादर केलेली सुरक्षितता क्रेडेंशियल बनावट असू शकतात आणि हा सर्व्हर तुम्ही अपेक्षा करत असलेला नसेल. (तुम्ही कदाचित एखाद्या हल्लेखोराशी संभाषण करत आहात).</translation>
+<translation id="6826370046007623921">डेटा गमावण्यास प्रतिबंध</translation>
<translation id="6831043979455480757">भाषांतर करा</translation>
<translation id="6839929833149231406">क्षेत्र</translation>
<translation id="6852204201400771460">ॲप रीलोड करायचे?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">धोरण स्तर समर्थित नाही.</translation>
<translation id="6895330447102777224">आपल्या कार्डची पुष्टी केली</translation>
<translation id="6897140037006041989">वापरकर्ता एजंट</translation>
-<translation id="6903319715792422884">सुरक्षित ब्राउझिंगमध्ये सुधारणा करण्यासाठी Google ला काही <ph name="BEGIN_WHITEPAPER_LINK" />सिस्टम माहिती आणि पेज आशय<ph name="END_WHITEPAPER_LINK" /> पाठवून मदत करा. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">वापरकर्ता:</translation>
<translation id="6934672428414710184">हे नाव तुमच्या Google खात्यावरून आहे</translation>
<translation id="6944692733090228304">तुम्ही पासवर्ड एंटर केलेली साइट <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> द्वारे व्यवस्थापित केलेली नाही. तुमच्या खात्याच्या संरक्षणासाठी, तुमचा पासवर्ड इतर ॲप्स किंवा साइटवर पुन्हा वापरू नका.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> आणखी}other{<ph name="PAYMENT_METHOD_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> आणखी}}</translation>
<translation id="7153618581592392745">फिकट जांभळा</translation>
<translation id="717330890047184534">Gaia आयडी:</translation>
+<translation id="7174545416324379297">मर्ज केले</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> आणखी}other{<ph name="SHIPPING_OPTION_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> आणखी}}</translation>
<translation id="7177397715882417099">तुम्ही जात आहात तो सर्व्हर, <ph name="ORIGIN" />, ने विनंती केली आहे की
सुरक्षितता धोरण त्याच्या सर्व विनंत्यांना लागू होईल. परंतु धोरण डिलिव्हर
@@ -1153,7 +1174,7 @@
अतिरिक्त तपशील:
<ph name="DEBUG_INFO" /></translation>
<translation id="725866823122871198">तुमच्या कॉंप्युटरची तारीख आणि वेळ <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> चुकीची असल्यामुळे (<ph name="DATE_AND_TIME" />)सह खाजगी कनेक्शन इंस्टॉल केले जाऊ शकत नाही.</translation>
-<translation id="7260504762447901703">अॅक्सेस रद्द करा</translation>
+<translation id="7260504762447901703">ॲक्सेस रद्द करा</translation>
<translation id="7271803869921933038">स्वीकारली जाणारी प्रीपेड कार्डे</translation>
<translation id="7275334191706090484">व्यवस्थापित केलेले बुकमार्क</translation>
<translation id="7298195798382681320">शिफारस केलेले</translation>
@@ -1166,6 +1187,7 @@
<translation id="7320336641823683070">कनेक्शन मदत</translation>
<translation id="733354035281974745">डिव्हाइसचे स्थानिक खाते ओव्हरराइड करा</translation>
<translation id="7334320624316649418">&amp;पुनर्क्रमित करा पुन्हा करा</translation>
+<translation id="7337706099755338005">तुमच्या प्लॅटफॉर्मवर उपलब्ध नाही.</translation>
<translation id="733923710415886693">सर्टिफिकेट पारदर्शकतेअंतर्गत सर्व्हरचे सर्टिफिकेट उघड केले नाही.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">याच्याशी संबंधित आहे:</translation>
@@ -1181,7 +1203,7 @@
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">तुमचे <ph name="DEVICE_NAME" /> व्यवस्थापित केले आहे</translation>
<translation id="7407424307057130981">&lt;p&gt;जर तुमच्या Windows कॉंप्युटरवर Superfish सॉफ्टवेअर असेल, तर तुम्हाला हा एरर दिसेल.&lt;/p&gt;
- &lt;p&gt;सॉफ्टवेअरला तात्पुरत्या स्वरुपात बंद करण्यासाठी या पायऱ्यांनुसार कृती करा, जेणेकरून तुम्‍ही ते वेबवर मिळवू शकाल. तुमच्याकडे अॅडमिनिस्ट्रेटरचे अधिकार असणे आवश्यक आहे.&lt;/p&gt;
+ &lt;p&gt;सॉफ्टवेअरला तात्पुरत्या स्वरुपात बंद करण्यासाठी या पायऱ्यांनुसार कृती करा, जेणेकरून तुम्‍ही ते वेबवर मिळवू शकाल. तुमच्याकडे ॲडमिनिस्ट्रेटरचे अधिकार असणे आवश्यक आहे.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;सुरू&lt;/strong&gt; वर क्लिक करा, मग स्थानिक सेवा शोधा आणि&lt;strong&gt;"स्थानिक सेवा पाहा"&lt;/strong&gt; निवडा
&lt;li&gt;&lt;strong&gt;व्हिज्युअल डिस्कव्हरी&lt;/strong&gt; निवडा
@@ -1197,7 +1219,6 @@
<translation id="7440140511386898319">ऑफलाइन असताना एक्सप्लोर करा</translation>
<translation id="7441627299479586546">चुकीचे धोरण विषय</translation>
<translation id="7442725080345379071">फिकट नारिंगी</translation>
-<translation id="7444046173054089907">ही साइट अवरोधित केली आहे</translation>
<translation id="7445762425076701745">तुम्ही कनेक्ट केलेल्या सर्व्हरची ओळख पूर्णपणे पडताळणे शक्य नाही. तुम्ही सर्व्हरशी फक्त आपल्‍या डोमेनमध्ये वैध असलेले नाव वापरून कनेक्ट केलेले आहे, ज्याची मालकी सत्यापित करण्यासाठी बाह्य सर्टिफिकेट अधिकृततेला परवानगी नाही. काही सर्टिफिकेट अधिकारी तरीही या नावांसाठी सर्टिफिकेट जारी करतील, याची खात्री करण्याचा काहीही मार्ग नाही की तुम्ही इच्छित वेबसाइटशी कनेक्ट केले आहे आणि हल्लेखोराशी नाही.</translation>
<translation id="7451311239929941790">या समस्येविषयी <ph name="BEGIN_LINK" />अधिक जाणून घेणे<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">सार्वत्रिक डीफॉल्‍ट वापरा (अवरोधित करा)</translation>
@@ -1219,12 +1240,12 @@
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">तुम्ही निश्चित केल्यावर, तुमचे कार्ड तपशील या साइटसह शेअर केले जातील.</translation>
<translation id="7542995811387359312">स्वयंचलित क्रेडिट कार्ड भरणे अक्षम झाले आहे कारण हा फॉर्म सुरक्षित कनेक्शन वापरत नाही.</translation>
-<translation id="7543525346216957623">आपल्या पालकास विचारा</translation>
<translation id="7548892272833184391">कनेक्शन एरर दुरूस्त करा</translation>
<translation id="7549584377607005141">हे वेबपेज योग्यरितीने प्रदर्शित केले जाण्यासाठी तुम्ही पूर्वी एंटर केलेला डेटा आवश्यक आहे. तुम्ही हा डेटा पुन्हा पाठवू शकता, परंतु असे केल्याने या पेजने मागे केलेली कोणत्याही क्रियेची पुनरावृत्ती तुम्ही कराल.</translation>
+<translation id="7550637293666041147">तुमच्या डिव्हाइसचे वापरकर्ता नाव आणि Chrome चे वापरकर्ता नाव</translation>
<translation id="7552846755917812628">खालील टिपा वापरून पहा:</translation>
<translation id="7554791636758816595">नवीन टॅब</translation>
-<translation id="7564049878696755256">तुम्ही तुमच्या Google <ph name="ORG_NAME" /> चा अॅक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chrome लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
+<translation id="7564049878696755256">तुम्ही तुमच्या Google <ph name="ORG_NAME" /> चा ॲक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chrome लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
<translation id="7567204685887185387">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षितता सर्टिफिकेट कदाचित लबाडीने जारी केले असावे. हे कदाचित एका चुकीच्या कॉंफिगरेशनमुळे किंवा हल्लेखोराने तुमचे कनेक्शन इंटरसेप्ट केल्यामुळे झाले असू शकते.</translation>
<translation id="7569952961197462199">Chrome मधून क्रेडिट कार्ड काढून टाकायचे?</translation>
<translation id="7569983096843329377">काळा</translation>
@@ -1236,6 +1257,7 @@
<translation id="7610193165460212391">मूल्य <ph name="VALUE" /> श्रेणीच्या बाहेर आहे.</translation>
<translation id="7613889955535752492">कालबाह्य: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">तुमच्याकडे आधीपासूनच डेटा आहे जो तुमच्या Google खाते पासवर्डची विभिन्न आवृत्ती वापरुन एंक्रिप्शन करण्‍यात आला आहे. कृपया तो खाली एंटर करा.</translation>
+<translation id="7625784245512586808">Chrome एंटरप्राइझ जोखीम सुरक्षितता</translation>
<translation id="7633909222644580952">परफॉर्मंस डेटा आणि क्रॅश अहवाल</translation>
<translation id="7637571805876720304">Chromium वरून क्रेडिट कार्ड काढून टाकायचे?</translation>
<translation id="7638605456503525968">सिरीअल पोर्ट</translation>
@@ -1248,7 +1270,6 @@
<translation id="7668654391829183341">अज्ञात डिव्हाइस</translation>
<translation id="7669271284792375604">या साइट वरील आक्रमणकर्ते कदाचित तुमच्या ब्राउझिंग अनुभवास हानी पोहोचविणारे प्रोग्राम (उदाहरणार्थ, तुमचे होम बदलून किंवा तुम्ही भेट देता त्या साइटवर अतिरिक्त जाहिराती दर्शवून) इंस्टॉल करून तुमची फसवणूक करण्‍याचा प्रयत्न करू शकतात.</translation>
<translation id="7676643023259824263">क्लिपबोर्ड मजकूर, <ph name="TEXT" /> शोधा</translation>
-<translation id="7679176406634891508">प्लॅटफॉर्म आणि क्लाउड</translation>
<translation id="7681101578153515023">शोध इंजिन बदला</translation>
<translation id="7682287625158474539">शिपिंग</translation>
<translation id="7687186412095877299">तुमच्या सेव्ह केलेल्या पेमेंट पद्धतींसह पेमेंट फॉर्म भरते</translation>
@@ -1258,12 +1279,11 @@
<translation id="7701040980221191251">काहीही नाही</translation>
<translation id="7704050614460855821"><ph name="BEGIN_LINK" /> <ph name="SITE" /> (असुरक्षित) वर सुरु ठेवा<ph name="END_LINK" /></translation>
<translation id="7714464543167945231">सर्टिफिकेट</translation>
-<translation id="7716147886133743102">तुमच्या अॅडमिनिस्ट्रेटरने ब्लॉक केलेले</translation>
+<translation id="7716147886133743102">तुमच्या ॲडमिनिस्ट्रेटरने ब्लॉक केलेले</translation>
<translation id="7716424297397655342">ही साइट कॅशे मधून लोड करणे शक्य नाही</translation>
<translation id="7723047071702270851">कार्ड संपादित करा</translation>
<translation id="774634243536837715">धोकादायक आशय ब्लॉक केला.</translation>
<translation id="7752995774971033316">व्यवस्थापित न केलेले</translation>
-<translation id="7755287808199759310">तुमचे पालक तुमच्यासाठी ती अनावरोधित करू शकतात</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">फायरवॉल किंवा अँटीव्हायरस सॉफ्टवेअरने कदाचित कनेक्शन अवरोधित केले असावे.</translation>
<translation id="7759163816903619567">डोमेन दाखवा:</translation>
@@ -1273,7 +1293,7 @@
<translation id="7770259615151589601">Designated-Long</translation>
<translation id="777702478322588152">परफेक्चुअर</translation>
<translation id="7791543448312431591">जोडा</translation>
-<translation id="7800304661137206267">मेसेज अॉथेंटिकेशनसाठी <ph name="MAC" /> आणि की विनिमय तंत्र महणून <ph name="KX" /> सह <ph name="CIPHER" /> वापरून कनेक्शन कूटबद्ध केले आहे.</translation>
+<translation id="7800304661137206267">मेसेज ऑथेंटिकेशनसाठी <ph name="MAC" /> आणि की विनिमय तंत्र महणून <ph name="KX" /> सह <ph name="CIPHER" /> वापरून कनेक्शन कूटबद्ध केले आहे.</translation>
<translation id="7802523362929240268">साइट कायदेशीर आहे</translation>
<translation id="780301667611848630">नाही, नको</translation>
<translation id="7805768142964895445">स्थिती</translation>
@@ -1281,7 +1301,7 @@
<translation id="7812922009395017822">Mir</translation>
<translation id="7813600968533626083">Chrome मधून सूचना फॉर्म काढून टाकायचा?</translation>
<translation id="7815407501681723534">'<ph name="SEARCH_STRING" />' साठी <ph name="NUMBER_OF_RESULTS" /> <ph name="SEARCH_RESULTS" /> सापडले</translation>
-<translation id="782886543891417279">तुम्ही वापरत असलेल्या (<ph name="WIFI_NAME" />) वाय-फाय च्या लॉग इन पेजला तुमच्या भेट देण्याची आवश्यकता असू शकते.</translation>
+<translation id="782886543891417279">तुम्ही वापरत असलेल्या (<ph name="WIFI_NAME" />) वाय-फाय च्या लॉग इन पेजला तुम्हाला भेट देण्याची आवश्यकता असू शकते.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{काहीही नाही}=1{एक अ‍ॅप <ph name="EXAMPLE_APP_1" />}=2{२ अ‍ॅप्स <ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />}other{# अ‍ॅप्स <ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />}}</translation>
<translation id="785549533363645510">तथापि, तुम्ही अदृश्य नाही. गुप्त झाल्याने तुमचे ब्राउझिंग तुमचा नियोक्ता, तुमचा इंटरनेट सेवा पुरवठादार, किंवा तुम्ही भेट देता त्या वेबसाइटपासून लपत नाही.</translation>
@@ -1307,7 +1327,6 @@
<translation id="8004582292198964060">ब्राउझर</translation>
<translation id="8009225694047762179">पासवर्ड व्यवस्थापित करा</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{हे कार्ड आणि त्याचा बिलिंग पत्ता सेव्ह केला जाईल. <ph name="USER_EMAIL" /> मध्ये साइन इन केलेले असताना तुम्ही ते वापरू शकाल.}other{ही कार्डे आणि त्यांचे बिलिंग पत्ते सेव्ह केले जातील. <ph name="USER_EMAIL" /> मध्ये साइन इन केलेले असताना तुम्ही ती वापरू शकाल.}}</translation>
-<translation id="8012647001091218357">आम्ही याक्षणी आपल्या पालकांपर्यंत पोहोचू शकलो नाही. कृपया पुन्हा प्रयत्न करा.</translation>
<translation id="8025119109950072390">या साइट वरील आक्रमणकर्ते सॉफ्‍टवेअर इंस्टॉल करणे किंवा तुमची वैयक्तिक माहिती (उदाहरणार्थ, पासवर्ड, फोन नंबर किंवा क्रेडिट कार्ड) उघड करणे यासारखे काहीतरी धोकादायक करण्‍यामध्‍ये तुम्हाला चलाखीने गुंतवू शकतात.</translation>
<translation id="8034522405403831421">हे पृष्‍ठ <ph name="SOURCE_LANGUAGE" /> मध्ये आहे. त्यास <ph name="TARGET_LANGUAGE" /> मध्ये भाषांतरीत करायचे?</translation>
<translation id="8035152190676905274">पेन</translation>
@@ -1318,6 +1337,7 @@
<translation id="8041940743680923270">सार्वत्रिक डीफॉल्‍ट वापरा (विचारा)</translation>
<translation id="8042918947222776840">पिकअप पद्धत निवडा</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" योग्य रीतीने कॉन्फिगर केलेले नाही. "<ph name="SOFTWARE_NAME" />" अनइंस्टॉल केल्याने सहसा समस्या सुटते. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">यापुढे तुम्हाला कार्डचा सुरक्षितता कोड एंटर करण्याची आवश्यकता नाही.</translation>
<translation id="8066955247577885446">सॉरी, काहीतरी चूक झाली.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">फिरवल्यावर भाष्य करू शकत नाही</translation>
@@ -1336,7 +1356,7 @@
<translation id="8127301229239896662">"<ph name="SOFTWARE_NAME" />" तुमच्या काँप्युटरवर किंवा नेटवर्कवर योग्य रीतीने इंस्टॉल केले नव्हते. तुमच्या अ‍ॅडमिनिस्ट्रेटरला ही समस्या सोडवण्यास सांगा.</translation>
<translation id="8131740175452115882">पुष्टी करा</translation>
<translation id="8149426793427495338">तुमचा कॉंप्युटर निष्क्रीय झाला.</translation>
-<translation id="8150722005171944719"><ph name="URL" /> येथील फाइल वाचनीय नाही. ती काढून टाकलेली, हलविलेली असू शकते किंवा फाइल परवानग्या अॅक्सेस प्रतिबंधित करत असू शकतात.</translation>
+<translation id="8150722005171944719"><ph name="URL" /> येथील फाइल वाचनीय नाही. ती काढून टाकलेली, हलविलेली असू शकते किंवा फाइल परवानग्या ॲक्सेस प्रतिबंधित करत असू शकतात.</translation>
<translation id="8175796834047840627">तुम्ही साइन इन केले असल्यामुळे Chrome तुमच्या Google खात्यामध्ये तुमची कार्डे सेव्ह करत आहे. तुम्‍ही हे वर्तन सेटिंग्‍जमध्‍ये बदलू शकता.</translation>
<translation id="8184538546369750125">सार्वत्रिक डीफॉल्‍ट वापरा (अनुमती द्या)</translation>
<translation id="8194797478851900357">&amp;हलवा पूर्ववत करा</translation>
@@ -1348,6 +1368,7 @@
<translation id="8211406090763984747">कनेक्शन सुरक्षित आहे</translation>
<translation id="8218327578424803826">नियुक्त केलेले स्थान:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">एंटरप्राइझ रिपोर्टिंग</translation>
<translation id="8225771182978767009">ज्या व्यक्तीने हा कॉंप्युटर सेट केला त्या व्यक्तीने ही साइट ब्लॉक करण्याचे निवडले आहे.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">पेज नवीन गुप्त टॅबमध्ये उघडा</translation>
@@ -1362,13 +1383,13 @@
<translation id="8281084378435768645">Large-Photo</translation>
<translation id="8286036467436129157">साइन इन</translation>
<translation id="8288807391153049143">सर्टिफिकेट दाखवा</translation>
-<translation id="8289355894181816810">याचा निश्चित अर्थ तुम्हाला माहिती नसल्यास तुमच्या नेटवर्क अॅडमिनिस्ट्रेटरशी संपर्क साधा.</translation>
+<translation id="8289355894181816810">याचा निश्चित अर्थ तुम्हाला माहिती नसल्यास तुमच्या नेटवर्क ॲडमिनिस्ट्रेटरशी संपर्क साधा.</translation>
<translation id="8293206222192510085">बुकमार्क जोडा</translation>
<translation id="8294431847097064396">स्रोत</translation>
<translation id="8298115750975731693">तुम्ही वापरत असलेल्या (<ph name="WIFI_NAME" />) वाय-फाय ला तुम्ही <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" /> ला भेट देण्याची आवश्यकता असू शकते.</translation>
<translation id="8307358339886459768">Small-Photo</translation>
<translation id="8308427013383895095">नेटवर्क कनेक्शनसह समस्या असल्यामुळे भाषांतर अयशस्वी झाला.</translation>
-<translation id="8332188693563227489"><ph name="HOST_NAME" /> चा अॅक्सेस नाकारला</translation>
+<translation id="8332188693563227489"><ph name="HOST_NAME" /> चा ॲक्सेस नाकारला</translation>
<translation id="8340095855084055290"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="834457929814110454">तुमच्या सुरक्षिततेच्या जोखमी समजत असल्यास, धोकादायक प्रोग्राम काढले जाण्यापूर्वी तुम्ही <ph name="BEGIN_LINK" />या असुरक्षित साइटला भेट देऊ शकता<ph name="END_LINK" />.</translation>
<translation id="8349305172487531364">बुकमार्क बार</translation>
@@ -1402,23 +1423,23 @@
<translation id="8508648098325802031">शोध आयकन</translation>
<translation id="8522552481199248698">तुमच्या Google खात्याचे संरक्षण करण्यात आणि तुमचा पासवर्ड बदलण्यात Chrome तुम्हाला मदत करू शकते.</translation>
<translation id="8543181531796978784">तुम्ही <ph name="BEGIN_ERROR_LINK" />ओळखण्‍याच्या समस्‍येचा अहवाल<ph name="END_ERROR_LINK" /> देऊ शकता किंवा तुमच्या सुरक्षिततेस असणार्‍या जोखीम तुम्ही समजत असल्‍यास, <ph name="BEGIN_LINK" />या असुरक्षित साइटला भेट द्या<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">प्रश्न आहेत? तुमच्या प्रोफाइलचे निरीक्षण करणाऱ्या व्यक्तीशी संपर्क साधा.</translation>
<translation id="8553075262323480129">भाषांतर करण्यात अयशस्वी कारण पृष्ठाची भाषा निर्धारित करणे शक्य नाही.</translation>
<translation id="8557066899867184262">CVV तुमच्या कार्डाच्या मागील बाजूस दिलेला असतो.</translation>
<translation id="8559762987265718583">आपल्या डिव्हाइसची तारीख आणि वेळ (<ph name="DATE_AND_TIME" />) चुकीची असल्याने <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> सह खाजगी कनेक्शन इंस्टॉल केले जाऊ शकले नाही.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> संशयास्पद साइट</translation>
<translation id="8564985650692024650">जर तुम्ही तुमच्या <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> पासवर्डचा इतर साइटवर पुन्हा वापर केला असेल तर Chromium तुम्हाला तो रीसेट करण्याची शिफारस करतो.</translation>
<translation id="8571890674111243710"><ph name="LANGUAGE" /> मध्ये पृष्ठ अनुवादित करत आहे...</translation>
<translation id="858637041960032120">फोन नंबर जोडा</translation>
-<translation id="859285277496340001">सर्टिफिकेट रिव्होक झाले आहे किंवा नाही हे तपासण्यााची प्रणाली नमूद करत नाही.</translation>
<translation id="860043288473659153">कार्डधारकाचे नाव</translation>
<translation id="861775596732816396">आकार ४</translation>
-<translation id="8620436878122366504">आपल्या पालकांनी अद्याप ती मंजूर केली नाही</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">या डिव्हाइसवर हे कार्ड सेव्‍ह करा</translation>
<translation id="8626112503828625890">बिलिंग तपशील Google खात्यामध्ये स्टोअर करायचा आहे का?</translation>
+<translation id="8647750283161643317">सर्व डीफॉल्टमध्ये रीसेट करा</translation>
<translation id="8663226718884576429">ऑर्डर सारांश, <ph name="TOTAL_LABEL" />, आणखी तपशील</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, उत्तर, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">उपलब्ध</translation>
<translation id="8703575177326907206">तुमचे <ph name="DOMAIN" /> चे कनेक्शन एंक्रिप्ट केलेले नाही.</translation>
<translation id="8718314106902482036">पेमेंट पूर्ण झाले नाही</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, शोध सूचना</translation>
@@ -1429,13 +1450,14 @@
<translation id="8738058698779197622">एक सुरक्षित कनेक्‍शन स्‍थापित करण्‍यापूर्वी, तुमचे घड्‍याळ योग्यरित्या सेट केले असणे आवश्यक आहे. कारण वेबसाइट त्यांना स्‍वत:ला ओळखण्‍यासाठी वापरलेली ती सर्टिफिकेटे केवळ नमूद केलेल्‍या कालावधीसाठी वैध असतात. तुमच्या डिव्‍हाइसचे घड्‍याळ चुकीचे असल्‍यामुळे, Chromium ला सर्टिफिकेटे पडताळणी करता आले नाही.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" />चा &lt;abbr id="dnsDefinition"&gt;DNS पत्ता&lt;/abbr&gt; शोधणे शक्य झाले नाही. समस्येचे निराकरण करीत आहे.</translation>
<translation id="874846938927089722">स्वीकारली जाणारी क्रेडिट आणि प्रीपेड कार्डे</translation>
+<translation id="874918643257405732">हा टॅब बुकमार्क करा</translation>
<translation id="8759274551635299824">या कार्डची मुदत संपली आहे</translation>
<translation id="8761567432415473239">Google सुरक्षित ब्राउझिंग ला <ph name="SITE" /> वर अलीकडे <ph name="BEGIN_LINK" />हानिकारक प्रोग्राम आढळले आहेत<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB डिव्हाइस</translation>
<translation id="8768895707659403558">तुमच्या सर्व डिव्हाइसवर तुमची कार्डे वापरण्यासाठी, <ph name="SIGN_IN_LINK" />.</translation>
<translation id="877985182522063539">A4</translation>
<translation id="8790007591277257123">&amp;पुन्हा करा हटवा</translation>
-<translation id="8792621596287649091">तुम्ही तुमच्या Google <ph name="ORG_NAME" /> चा अॅक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chromium लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
+<translation id="8792621596287649091">तुम्ही तुमच्या Google <ph name="ORG_NAME" /> चा ॲक्सेस गमावू शकता किंवा तुमची संवेदनशील माहिती चोरीला जाऊ शकते. Chromium लगेच तुमचा पासवर्ड बदलण्याची शिफारस करत आहे.</translation>
<translation id="8800988563907321413">आपल्या जवळपासच्या सूचना येथे दिसतात</translation>
<translation id="8805819170075074995">सूची एंट्री "<ph name="LANGUAGE_ID" />": एंट्री SpellcheckLanguage धोरणामध्येदेखील समाविष्ट असल्यामुळे तिच्याकडे दुर्लक्ष केले गेले आहे.</translation>
<translation id="8820817407110198400">Bookmarks</translation>
@@ -1458,6 +1480,7 @@
<translation id="8938939909778640821">स्वीकारलेली क्रेडिट आणि प्रीपेड कार्डे</translation>
<translation id="8943282376843390568">लिंबू</translation>
<translation id="8957210676456822347">बंद पोर्टल प्राधिकृतता</translation>
+<translation id="8962950042226115166">संशयास्पद साइट</translation>
<translation id="8968766641738584599">कार्ड सेव्ह करा</translation>
<translation id="8971063699422889582">सर्व्हरचे सर्टिफिकेट एक्स्पायर झाले आहे.</translation>
<translation id="8975012916872825179">फोन नंबर, ईमेल ॲड्रेस आणि शिपिंग पत्ते यांसारखी माहिती समाविष्ट आहे</translation>
@@ -1480,24 +1503,24 @@
<translation id="9035022520814077154">सुरक्षितता एरर</translation>
<translation id="9038649477754266430">पेज अधिक जलदपणे लोड करण्यासाठी पूर्वानुमान सेवेचा वापर करा</translation>
<translation id="9039213469156557790">पुढे, या पृष्ठात सुरक्षित नसलेली इतर संसाधने समाविष्ट आहेत. ही संसाधने संक्रमणात असताना इतरांद्वारे पाहिली जाऊ शकतात आणि पृष्ठाचे वर्तन बदलण्यासाठी आक्रमणकर्त्याद्वारे सुधारित केली जाऊ शकतात.</translation>
+<translation id="9044359186343685026">टच आयडी वापरा</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">तुम्ही <ph name="DOMAIN" /> वर पोहोचण्याचा प्रयत्न केला, परंतु सर्व्हरने चुकीचे सर्टिफिकेट दाखवले आहे.</translation>
<translation id="9050666287014529139">सांकेतिक पासफ्रेझ</translation>
<translation id="9065203028668620118">संपादन</translation>
<translation id="9065745800631924235">इतिहासामधून <ph name="TEXT" /> शोध</translation>
<translation id="9069693763241529744">एक एक्स्टेंशनने ब्लॉक केलेले</translation>
-<translation id="9076283476770535406">कदाचित तिच्यामध्ये प्रौढ आशय असू शकते</translation>
<translation id="9076630408993835509">हा ब्राउझर कंपनी किंवा अन्य संस्थेद्वारे व्यवस्थापित केलेला नाही. या डिव्हाइसवरील अ‍ॅक्टिव्हिटी कदाचित Chrome च्या बाहेर व्यवस्थापित केलेली असू शकते. <ph name="BEGIN_LINK" />अधिक जाणून घ्या<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">अधिक माहिती आवश्यक आहे</translation>
<translation id="9080712759204168376">मागणी सारांश</translation>
<translation id="9089260154716455634">कामाच्या तासानंतरचे धोरण:</translation>
<translation id="9095388113577226029">आणखी भाषा...</translation>
-<translation id="9103872766612412690"><ph name="SITE" /> तुमची माहिती संरक्षित करण्यासाठी सामान्यतः एंक्रिप्शन वापरते. Chromium ने यावेळी <ph name="SITE" /> शी कनेक्‍ट करण्‍याचा प्रयत्न केला तेव्‍हा, वेबसाइटने असामान्य आणि अयोग्य क्रेडेन्शियल परत पाठविले. एकतर आक्रमणकर्ता <ph name="SITE" /> असल्याची बतावणी करण्याचा प्रयत्न करतो तेव्‍हा किंवा वाय-फाय साइन इन स्क्रीनने कनेक्शनमध्ये व्यत्यय आणले तेव्‍हा हे घडू शकते. कोणत्याही डेटाची अदलाबदल करण्यापूर्वी Chromium ने कनेक्शन थांबविल्यामुळे तुमची माहिती अद्याप सुरक्षित आहे.</translation>
+<translation id="9098981495403789647">तुमच्या अ‍ॅडमिनिस्ट्रेटरने तुमच्या ब्राउझरवर Chrome एंटरप्राइझ जोखीम सुरक्षितता सुरू केली आहे. Chrome एंटरप्राइझ जोखीम सुरक्षितते ला तुमच्या काही डेटाचा ॲक्सेस आहे.</translation>
+<translation id="9103872766612412690"><ph name="SITE" /> तुमची माहिती संरक्षित करण्यासाठी सामान्यतः एंक्रिप्शन वापरते. Chromium ने यावेळी <ph name="SITE" /> शी कनेक्‍ट करण्‍याचा प्रयत्न केला तेव्‍हा, वेबसाइटने असामान्य आणि अयोग्य क्रेडेंशियल परत पाठवले. एकतर आक्रमणकर्ता <ph name="SITE" /> असल्याची बतावणी करण्याचा प्रयत्न करतो तेव्‍हा किंवा वाय-फाय साइन इन स्क्रीनने कनेक्शनमध्ये व्यत्यय आणले तेव्‍हा हे घडू शकते. कोणत्याही डेटाची अदलाबदल करण्यापूर्वी Chromium ने कनेक्शन थांबविल्यामुळे तुमची माहिती अद्याप सुरक्षित आहे.</translation>
<translation id="9106062320799175032">बिलिंग पत्ता जोडा</translation>
<translation id="9114524666733003316">कार्डची निश्चिती करत आहे...</translation>
<translation id="9128870381267983090">नेटवर्कशी कनेक्ट करा</translation>
<translation id="9137013805542155359">मूळ दर्शवा</translation>
-<translation id="9137248913990643158">कृपया हा ॲप वापरण्‍यापूर्वी प्रारंभ करा आणि Chrome मध्‍ये साइन इन करा.</translation>
<translation id="9141013498910525015">पत्ते व्यवस्थापित करा</translation>
<translation id="9148088599418889305">पाठवण्याची पद्धत निवडा</translation>
<translation id="9148507642005240123">&amp;संपादित करा पूर्ववत करा</translation>
diff --git a/chromium/components/strings/components_strings_ms.xtb b/chromium/components/strings/components_strings_ms.xtb
index ee7dcb763bf..65e4f4aefab 100644
--- a/chromium/components/strings/components_strings_ms.xtb
+++ b/chromium/components/strings/components_strings_ms.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Indeks-5x8</translation>
<translation id="1088860948719068836">Tambahkan Nama pada Kad</translation>
<translation id="1089439967362294234">Tukar Kata Laluan</translation>
+<translation id="1096545575934602868">Medan ini tidak boleh mengandungi lebih daripada <ph name="MAX_ITEMS_LIMIT" /> entri. Semua entri selebihnya akan dibuang.</translation>
<translation id="109743633954054152">Urus kata laluan dalam tetapan Chrome</translation>
<translation id="1103523840287552314">Sentiasa terjemahkan <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Jika ditandai, Chrome akan menyimpan salinan kad anda pada peranti ini untuk pengisian borang yang lebih cepat.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Akses <ph name="BEGIN_LINK" />salinan cache<ph name="END_LINK" /> <ph name="URL" /></translation>
<translation id="1156303062776767266">Anda sedang melihat fail setempat atau yang dikongsi</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> menutup sambungan tanpa di jangka.</translation>
+<translation id="115926840831309955">Semak CVC anda, kemudian cuba lagi atau kemas kini tarikh tamat tempoh kad</translation>
<translation id="1161325031994447685">Menyambung semula kepada Wi-Fi</translation>
<translation id="1165039591588034296">Ralat</translation>
<translation id="1175364870820465910">&amp;Cetak...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Perisian pada komputer anda menghalang Chrome daripada menyambung ke web dengan selamat" (komputer Windows sahaja)</translation>
<translation id="1294154142200295408">Variasi baris perintah</translation>
<translation id="129553762522093515">Ditutup baru-baru ini</translation>
+<translation id="1298536327547837046">Pengimbasan Perisian Hasad</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Cuba kosongkan kuki anda<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Ciri yang Ditamatkan</translation>
<translation id="1320233736580025032">Prc1 (Sampul Surat)</translation>
<translation id="132301787627749051">Cari imej papan keratan</translation>
<translation id="1323433172918577554">Tunjukkan Lagi</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Helaian Google</translation>
<translation id="1527263332363067270">Menunggu sambungan...</translation>
<translation id="1529521330346880926">10x15 (Sampul Surat)</translation>
+<translation id="1530707389502320859">Tapak yang baru sahaja anda cuba lawati kelihatan seperti tapak palsu. Penyerang kadangkala meniru tapak dengan melakukan perubahan kecil yang sukar untuk dikesan pada URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Halaman ini menyatakan</translation>
<translation id="153384715582417236">Itu sahaja buat masa ini</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokumen terlalu besar untuk dianotasikan</translation>
-<translation id="1721312023322545264">Anda memerlukan kebenaran daripada <ph name="NAME" /> untuk melawat tapak ini</translation>
<translation id="1721424275792716183">* Medan perlu diisi</translation>
<translation id="1727741090716970331">Tambahkan Nombor Kad yang Sah</translation>
<translation id="1728677426644403582">Anda sedang melihat sumber halaman web</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Tapak web yang anda lawati dan tempoh anda melayarinya</translation>
<translation id="1826516787628120939">Menyemak</translation>
<translation id="1834321415901700177">Tapak ini mengandungi atur cara berbahaya</translation>
+<translation id="1838374766361614909">Kosongkan carian</translation>
<translation id="1839551713262164453">Pengesahan nilai dasar gagal dengan ralat</translation>
<translation id="1842969606798536927">Bayar</translation>
<translation id="1871208020102129563">Proksi ditetapkan untuk menggunakan pelayan proksi tetap, bukannya URL skrip .pac.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Runtuhkan senarai</translation>
<translation id="1898423065542865115">Penapisan</translation>
<translation id="1914326953223720820">Perkhidmatan Nyahzip</translation>
+<translation id="1915697529809968049">Gunakan Touch ID dan bukan CVC?</translation>
<translation id="1916770123977586577">Untuk menerapkan tetapan anda yang dikemas kini pada tapak ini, muatkan semula halaman ini</translation>
<translation id="1919345977826869612">Iklan</translation>
<translation id="1919367280705858090">Dapatkan bantuan berkaitan mesej ralat tertentu</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> Penanda halaman</translation>
<translation id="1973335181906896915">Ralat penyirian</translation>
<translation id="1974060860693918893">Lanjutan</translation>
+<translation id="1974883374937189061">Bantu kami meningkatkan keselamatan Chrome dengan menghantar <ph name="BEGIN_WHITEPAPER_LINK" />URL sesetengah halaman yang anda lawati, maklumat sistem yang terhad dan sebahagian kandungan halaman<ph name="END_WHITEPAPER_LINK" /> kepada Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versi Perisian Tegar</translation>
<translation id="1981206234434200693">Kosongkan data sejarah penyemakan imbas Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{dan 1 lagi}other{dan # lagi}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Masukkan tahun tamat tempoh yang sah</translation>
<translation id="2212735316055980242">Dasar tidak dijumpai</translation>
<translation id="2213606439339815911">Mengambil entri…</translation>
+<translation id="2215727959747642672">Pengeditan fail</translation>
<translation id="2218879909401188352">Penyerang yang berada di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> boleh memasang apl berbahaya yang boleh merosakkan peranti anda, menambahkan caj yang tersembunyi pada bil mudah alih anda atau mencuri maklumat peribadi anda. <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Tiada Internet</translation>
<translation id="2230458221926704099">Betulkan sambungan anda menggunakan <ph name="BEGIN_LINK" />apl diagnostik<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Hantar sekarang</translation>
+<translation id="2248949050832152960">Gunakan WebAuthn</translation>
<translation id="225207911366869382">Nilai ini tidak lagi digunakan untuk dasar ini.</translation>
<translation id="2257315177824333709">Maaf, kad anda tidak dapat disimpan sekarang</translation>
<translation id="2262243747453050782">Ralat HTTP</translation>
@@ -291,7 +300,6 @@
<translation id="2479410451996844060">URL carian tidak sah.</translation>
<translation id="2482878487686419369">Pemberitahuan</translation>
<translation id="248348093745724435">Dasar mesin</translation>
-<translation id="2485387744899240041">Nama pengguna bagi peranti dan penyemak imbas anda</translation>
<translation id="2491120439723279231">Sijil pelayan mengandungi ralat.</translation>
<translation id="2493640343870896922">Surat-Plus</translation>
<translation id="2495083838625180221">Penghurai JSON</translation>
@@ -301,6 +309,7 @@
<translation id="2501278716633472235">Kembali</translation>
<translation id="2503184589641749290">Kad debit dan prabayar yang diterima</translation>
<translation id="2505268675989099013">Lindungi Akaun</translation>
+<translation id="2515335152965840738">ABAIKAN</translation>
<translation id="2515629240566999685">Semak isyarat di kawasan anda</translation>
<translation id="2523886232349826891">Disimpan pada peranti ini sahaja</translation>
<translation id="2524461107774643265">Tambahkan Maklumat Lanjut</translation>
@@ -325,7 +334,6 @@
<translation id="2653659639078652383">Serah</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Tiada}=1{1 kata laluan (untuk <ph name="DOMAIN_LIST" />)}=2{2 kata laluan (untuk <ph name="DOMAIN_LIST" />)}other{# kata laluan (untuk <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Tutup tab atau apl lain</translation>
-<translation id="267371737713284912">tekan <ph name="MODIFIER_KEY_DESCRIPTION" /> untuk buat asal</translation>
<translation id="2674170444375937751">Adakah anda pasti anda mahu memadamkan halaman ini daripada sejarah anda?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Tinggalkan</translation>
@@ -335,12 +343,14 @@
<translation id="2704283930420550640">Nilai tidak sepadan dengan format.</translation>
<translation id="2705137772291741111">Salinan tapak ini yang disimpan (cache) tidak boleh dibaca.</translation>
<translation id="2709516037105925701">Autoisi</translation>
-<translation id="2712173769900027643">Minta kebenaran</translation>
<translation id="2713444072780614174">Putih</translation>
<translation id="2720342946869265578">Berdekatan</translation>
<translation id="2721148159707890343">Permintaan berjaya</translation>
<translation id="2728127805433021124">Sijil pelayan ditandatangani menggunakan algoritma tandatangan yang lemah.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Jalankan Diagnostik Sambungan<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Langkah mendayakan ciri ini mungkin akan menyebabkan anda kehilangan data penyemak imbas atau
+ menjejaskan keselamatan atau privasi anda. Ciri yang didayakan digunakan untuk semua
+ pengguna penyemak imbas ini.</translation>
<translation id="2735043616039983645">Lebih daripada satu sumber yang mempunyai nilai yang bercanggah terdapat dalam dasar ini!</translation>
<translation id="2738330467931008676">Pilih Alamat Pengambilan</translation>
<translation id="2740531572673183784">Ok</translation>
@@ -351,16 +361,15 @@
<translation id="2784949926578158345">Sambungan ditetapkan semula.</translation>
<translation id="2788784517760473862">Kad kredit yang diterima</translation>
<translation id="2792012897584536778">Pentadbir peranti ini telah menyediakan sijil keselamatan yang mungkin membolehkan mereka melihat kandungan tapak web yang anda lawati.</translation>
-<translation id="2794233252405721443">Tapak disekat</translation>
<translation id="2799020568854403057">Tapak yang akan disemak imbas mengandungi apl yang memudaratkan</translation>
<translation id="2799223571221894425">Lancarkan semula</translation>
<translation id="2803306138276472711">Penyemakan Selamat Google <ph name="BEGIN_LINK" />mengesan perisian hasad<ph name="END_LINK" /> pada <ph name="SITE" /> baru-baru ini. Tapak web yang biasanya selamat kadangkala dijangkiti oleh perisian hasad.</translation>
+<translation id="2815364696811431560">TINGGALKAN TAPAK</translation>
<translation id="2824775600643448204">Bar alamat dan carian</translation>
<translation id="2826760142808435982">Sambungan disulitkan dan disahkan menggunakan <ph name="CIPHER" /> dan menggunakan <ph name="KX" /> sebagai mekanisme pertukaran kunci.</translation>
<translation id="2835170189407361413">Kosongkan borang</translation>
<translation id="2847118875340931228">Buka Tetingkap Inkognito</translation>
<translation id="2850739647070081192">Jemputan (Sampul Surat)</translation>
-<translation id="2851634818064021665">Anda memerlukan kebenaran untuk melawat tapak ini</translation>
<translation id="2856444702002559011">Penyerang mungkin akan cuba mencuri maklumat anda daripada <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (contohnya, kata laluan, mesej atau kad kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Simpan kad?</translation>
@@ -385,6 +394,7 @@
<translation id="2985306909656435243">Jika didayakan, Chromium akan menyimpan salinan kad anda pada peranti ini untuk pengisian borang yang lebih cepat.</translation>
<translation id="2985398929374701810">Masukkan alamat yang sah</translation>
<translation id="2986368408720340940">Kaedah pengambilan ini tidak tersedia. Cuba kaedah lain.</translation>
+<translation id="2987034854559945715">Tiada ciri yang sepadan</translation>
<translation id="2991174974383378012">Berkongsi dengan Tapak Web</translation>
<translation id="2991571918955627853">Anda tidak boleh melawati <ph name="SITE" /> sekarang kerana tapak web ini menggunakan HSTS. Ralat dan serangan rangkaian biasanya sementara. Oleh sebab itu, halaman ini mungkin akan berfungsi semula kemudian.</translation>
<translation id="3005723025932146533">Paparkan salinan disimpan</translation>
@@ -395,6 +405,7 @@
<translation id="3024663005179499861">Jenis dasar salah</translation>
<translation id="3037605927509011580">Oh, Tidak!</translation>
<translation id="3041612393474885105">Maklumat Sijil</translation>
+<translation id="3057676462092457419">Mod DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> belum lagi disokong, mod telah ditetapkan pada <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Sampul Surat)</translation>
<translation id="3061707000357573562">Perkhidmatan Tampung</translation>
<translation id="3064966200440839136">Meninggalkan mod inkognito untuk membayar melalui aplikasi luar. Teruskan?</translation>
@@ -420,6 +431,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> pada <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Batal Pembayaran</translation>
<translation id="3207960819495026254">Ditandai halaman</translation>
+<translation id="3209034400446768650">Halaman mungkin mengenakan bayaran berbentuk wang</translation>
<translation id="3225919329040284222">Pelayan memberikan sijil yang tidak sepadan dengan jangkaan terbina dalam. Jangkaan ini disertakan untuk tapak web dengan keselamatan tinggi tertentu untuk melindungi anda.</translation>
<translation id="3226128629678568754">Tekan butang muat semula untuk menyerahkan kembali data yang diperlukan untuk memuatkan halaman.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -427,7 +439,6 @@
<translation id="3229041911291329567">Maklumat versi tentang peranti dan penyemak imbas anda</translation>
<translation id="323107829343500871">Masukkan CVC untuk <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Sentiasa kesan kandungan penting di tapak web ini</translation>
-<translation id="3254409185687681395">Tanda halaman ini</translation>
<translation id="3270847123878663523">&amp;Buat asal Susun semula</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Tambahkan nama pada kad</translation>
@@ -437,7 +448,6 @@
<translation id="3320021301628644560">Tambahkan alamat pengebilan</translation>
<translation id="3324983252691184275">Merah lembayung</translation>
<translation id="3338095232262050444">Selamat</translation>
-<translation id="3345135638360864351">Permintaan anda untuk mengakses tapak web ini tidak boleh dihantar kepada <ph name="NAME" />. Sila cuba lagi.</translation>
<translation id="3355823806454867987">Tukar tetapan proksi...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />tidak akan menyimpan<ph name="END_EMPHASIS" /> maklumat berikut:
<ph name="BEGIN_LIST" />
@@ -471,18 +481,15 @@
<translation id="3462200631372590220">Menyembunyikan butiran</translation>
<translation id="3467763166455606212">Nama pemegang kad diperlukan</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, dibuka sekarang, tekan Tab, kemudian Enter untuk beralih ke tab yang terbuka</translation>
-<translation id="3479539252931486093">Adakah hal ini tidak dijangka? <ph name="BEGIN_LINK" />Beritahu kami<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Bukan sekarang</translation>
<translation id="3484560055331845446">Anda mungkin akan kehilangan akses kepada Akaun Google anda. Chrome mengesyorkan supaya anda menukar kata laluan sekarang. Anda akan diminta untuk log masuk.</translation>
<translation id="3495081129428749620">Cari dalam halaman
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Kami tidak dapat menghubungi ibu bapa anda pada masa ini. Sila cuba lagi.</translation>
<translation id="3512163584740124171">Dasar ini diabaikan kerana dasar lain daripada kumpulan dasar yang sama mempunyai keutamaan yang lebih tinggi.</translation>
<translation id="3528171143076753409">Sijil pelayan tidak dipercayai.</translation>
<translation id="3528485271872257980">Coklat Gelap</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Sekurang-kurangnya 1 item pada peranti yang disegerakkan}=1{1 item (dan beberapa lagi pada peranti yang disegerakkan)}other{# item (dan beberapa lagi pada peranti yang disegerakkan)}}</translation>
<translation id="3539171420378717834">Simpan salinan kad ini pada peranti ini</translation>
-<translation id="3556433843310711081">Pengurus anda boleh menyahsekatnya untuk anda</translation>
<translation id="3566021033012934673">Sambungan anda tidak diperibadikan</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Halaman terbenam di <ph name="SITE" /> menyatakan</translation>
@@ -511,6 +518,7 @@
<translation id="3678529606614285348">Buka halaman dalam tetingkap Inkognito baharu (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Laporan ranap sistem dirakam pada <ph name="CRASH_TIME" />, dimuat naik pada <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Maklumat sijil</translation>
+<translation id="3701427423622901115">Tetap semula diakui.</translation>
<translation id="3704162925118123524">Rangkaian yang anda gunakan mungkin memerlukan anda untuk melawat halaman log masuknya.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Memuatkan...</translation>
@@ -527,6 +535,7 @@
<translation id="3748148204939282805">Penyerang di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin memperdaya anda agar melakukan sesuatu yang berbahaya seperti memasang perisian atau mendedahkan maklumat peribadi anda (contohnya, kata laluan, nombor telefon atau kad kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Gagal menterjemah disebabkan ralat pelayan.</translation>
<translation id="3759461132968374835">Tiada laporan nahas yang dibuat baru-baru ini. Nahas yang berlaku apabila laporan nahas dilumpuhkan tidak akan kelihatan di sini.</translation>
+<translation id="3760561303380396507">Gunakan Windows Hello dan bukan CVC?</translation>
<translation id="3761718714832595332">Sembunyikan status</translation>
<translation id="3765032636089507299">Halaman Penyemakan Imbas Selamat sedang dalam pembinaan.</translation>
<translation id="3778403066972421603">Adakah anda ingin menyimpan maklumat kad ini ke Akaun Google anda dan pada peranti ini?</translation>
@@ -536,6 +545,7 @@
<translation id="3789155188480882154">Saiz 16</translation>
<translation id="3797522431967816232">Prc3 (Sampul Surat)</translation>
<translation id="3807873520724684969">Kandungan berbahaya disekat.</translation>
+<translation id="3808375843007691220">Amaran: Ciri percubaan di hadapan!</translation>
<translation id="3810973564298564668">Urus</translation>
<translation id="382518646247711829">Jika anda menggunakan pelayan proksi...</translation>
<translation id="3828924085048779000">Kosongkan frasa laluan adalah tidak dibenarkan.</translation>
@@ -544,11 +554,11 @@
<translation id="3858027520442213535">Kemas kini tarikh dan masa</translation>
<translation id="3884278016824448484">Pengecam peranti bercanggah</translation>
<translation id="3885155851504623709">Mukim</translation>
-<translation id="3886446263141354045">Permintaan anda untuk mengakses tapak ini telah dihantar kepada <ph name="NAME" />.</translation>
<translation id="3890664840433101773">Tambah e-mel</translation>
<translation id="3901925938762663762">Kad telah tamat tempoh</translation>
<translation id="3906600011954732550">B5-Ekstra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Gunakan WebAuthn dan bukan CVC?</translation>
<translation id="3946209740501886391">Sentiasa tanya pada tapak ini</translation>
<translation id="3949571496842715403">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya tidak menyatakan Nama Alternatif Subjek. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang memintasi sambungan anda.</translation>
<translation id="3949601375789751990">Sejarah penyemakan imbas anda dipaparkan di sini</translation>
@@ -559,11 +569,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Tiada}=1{Daripada 1 tapak }other{Daripada # tapak }}</translation>
<translation id="397105322502079400">Mengira...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> disekat</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> telah mendayakan Perlindungan Ancaman Chrome Enterprise pada penyemak imbas anda. Perlindungan Ancaman Chrome Enterprise mempunyai akses kepada sesetengah data anda.</translation>
<translation id="3987940399970879459">Kurang daripada 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 halaman web berdekatan}other{# halaman web berdekatan}}</translation>
<translation id="4030383055268325496">&amp;Buat asal tambahkan</translation>
<translation id="4032320456957708163">Penyemak imbas anda diurus oleh <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Pautan yang anda buka pergi ke tapak yang biasanya tidak anda lawati. Pautan itu mungkin cuba mengelirukan anda.</translation>
<translation id="4058922952496707368">Kekunci "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Sampul Surat)</translation>
<translation id="4067947977115446013">Tambahkan Alamat yang Sah</translation>
@@ -576,6 +586,7 @@
<translation id="4103249731201008433">Nombor siri peranti tidak sah</translation>
<translation id="410351446219883937">Automain</translation>
<translation id="4103763322291513355">Lawati &lt;strong&gt;chrome://policy&lt;/strong&gt; untuk melihat senarai URL yang disenarai hitam dan dasar lain yang dikuatkuasakan oleh pentadbir sistem anda.</translation>
+<translation id="4108231218301530806">Gunakan cap jari untuk mengesahkan kad ini pada masa akan datang.</translation>
<translation id="4110652170750985508">Semak pembayaran anda</translation>
<translation id="4112140312785995938">Cari Ke Belakang</translation>
<translation id="4116663294526079822">Sentiasa benarkan di tapak ini</translation>
@@ -590,6 +601,7 @@
<translation id="4171400957073367226">Tandatangan pengesahan tidak sah</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> lagi item}other{<ph name="ITEM_COUNT" /> lagi item}}</translation>
+<translation id="4176463684765177261">Dilumpuhkan</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Untuk membayar dengan lebih cepat selepas ini, tambahkan kad dan alamat pengebilan pada Akaun Google anda.</translation>
<translation id="4196861286325780578">&amp;Buat semula pindahkan</translation>
@@ -626,6 +638,7 @@
<translation id="4277028893293644418">Tetapkan semula kata laluan</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> anda diurus oleh <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Kad ini telah disimpan ke Akaun Google anda}other{Kad ini telah disimpan ke Akaun Google anda}}</translation>
+<translation id="428847186335018806">Imbas fail yang anda muat turun atau muat naik dalam Chrome.</translation>
<translation id="42981349822642051">Kembangkan</translation>
<translation id="4302965934281694568">Chou3 (Sampul Surat)</translation>
<translation id="4305817255990598646">Tukar</translation>
@@ -655,7 +668,6 @@
<translation id="4435702339979719576">Poskad)</translation>
<translation id="443673843213245140">Penggunaan proksi dilumpuhkan tetapi konfigurasi proksi yang jelas dinyatakan.</translation>
<translation id="445100540951337728">Kad debit yang diterima</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> kelakuan mencurigakan</translation>
<translation id="4466881336512663640">Perubahan borang akan hilang. Adakah anda pasti mahu meneruskan?</translation>
<translation id="4477350412780666475">Lagu Seterusnya</translation>
<translation id="4482953324121162758">Tapak ini tidak akan diterjemah.</translation>
@@ -682,6 +694,7 @@
<translation id="4594403342090139922">&amp;Buat asal Pemadaman</translation>
<translation id="4597348597567598915">Saiz 8</translation>
<translation id="4600854749408232102">C6/C5 (Sampul Surat)</translation>
+<translation id="464342062220857295">Ciri carian</translation>
<translation id="4646534391647090355">Bawa saya ke sana sekarang</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya mengandungi ralat. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintas sambungan anda.</translation>
@@ -690,7 +703,6 @@
<translation id="4691835149146451662">Seni Bina-A (Sampul Surat)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Sambungan anda tergendala</translation>
-<translation id="471880041731876836">Anda tiada kebenaran untuk melawat tapak ini</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Jalankan Diagnostik Rangkaian Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Muat semula dasar</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -718,7 +730,6 @@
<translation id="4816492930507672669">Muat halaman</translation>
<translation id="4850886885716139402">Lihat</translation>
<translation id="4854362297993841467">Kaedah penghantaran ini tidak tersedia. Cuba kaedah lain.</translation>
-<translation id="4858792381671956233">Anda telah bertanya kepada ibu bapa anda sama ada OK untuk melawat tapak ini</translation>
<translation id="4864052566555297930">Petua keselamatan:</translation>
<translation id="4876188919622883022">Paparan ringkas</translation>
<translation id="4876305945144899064">Tiada nama pengguna</translation>
@@ -742,7 +753,9 @@
<translation id="4974590756084640048">Dayakan semula amaran</translation>
<translation id="4984339528288761049">Prc5 (Sampul Surat)</translation>
<translation id="4989163558385430922">Lihat semua</translation>
+<translation id="4989542687859782284">Tidak tersedia</translation>
<translation id="4989809363548539747">Pemalam ini tidak disokong</translation>
+<translation id="4995216769782533993">Sahkan kod keselamatan untuk berkongsi butiran kad anda dengan tapak ini</translation>
<translation id="5002932099480077015">Jika didayakan, Chrome akan menyimpan salinan kad anda pada peranti ini untuk pengisian borang yang lebih cepat.</translation>
<translation id="5015510746216210676">Nama Mesin:</translation>
<translation id="5017554619425969104">Teks yang anda salin</translation>
@@ -771,6 +784,7 @@
<translation id="5115216390227830982">Edp-Eropah</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Sahkan kad anda</translation>
<translation id="5135404736266831032">Urus alamat...</translation>
<translation id="5138227688689900538">Tunjukkan kurang</translation>
<translation id="5141240743006678641">Sulitkan kata laluan yang disegerakkan dengan bukti kelayakan Google anda</translation>
@@ -797,6 +811,7 @@
<translation id="5251803541071282808">Awan</translation>
<translation id="5252000469029418751">C7 (Sampul Surat)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Ciri yang diguna pakai di seluruh sistem hanya boleh ditetapkan oleh pemilik: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Amaran: Dasar ini tidak digabungkan seperti yang dinyatakan dalam dasar PolicyDictionaryMultipleSourceMergeList kerana dasar ini bukan sebahagian daripada dasar kamus yang boleh digabungkan.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">End</translation>
@@ -820,7 +835,6 @@
<translation id="536296301121032821">Gagal menyimpan tetapan dasar</translation>
<translation id="5371425731340848620">Kemas kini kad</translation>
<translation id="5377026284221673050">"Jam anda lambat" atau "Jam anda cepat" atau "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Halaman ini mungkin cuba menipu anda, mencuri maklumat peribadi atau membahayakan peranti anda. Berhati-hati semasa memasukkan maklumat peribadi atau membuka fail yang dimuat turun.</translation>
<translation id="5384855140246857529">Untuk menggunakan kad anda pada semua peranti, log masuk dan hidupkan penyegerakan.</translation>
<translation id="5386426401304769735">Rantaian sijil untuk tapak ini mengandungi sijil yang ditandatangani menggunakan SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -834,6 +848,8 @@
<translation id="5457113250005438886">Tidak sah</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> lagi}other{<ph name="CONTACT_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> lagi}}</translation>
<translation id="5470861586879999274">&amp;Buat semula edit</translation>
+<translation id="5473728911100096288">Dengan mendayakan ciri ini, anda akan menggunakan ciri yang ditamatkan
+ yang akan hilang dalam versi akan datang.</translation>
<translation id="5478437291406423475">B6/C4 (Sampul Surat)</translation>
<translation id="5481076368049295676">Kandungan ini mungkin cuba memasang perisian berbahaya pada peranti anda yang mencuri atau memadamkan maklumat anda. <ph name="BEGIN_LINK" />Tunjukkan juga<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Tambahkan alamat yang sah</translation>
@@ -857,7 +873,6 @@
<translation id="5570825185877910964">Lindungi akaun</translation>
<translation id="5571083550517324815">Tidak boleh mengambil dari alamat ini. Pilih alamat lain.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 sedang digunakan}other{# sedang digunakan}})</translation>
-<translation id="5572851009514199876">Sila mulakan dan log masuk ke Chrome supaya Chrome boleh menyemak sama ada anda dibenarkan mengakses tapak ini.</translation>
<translation id="5580958916614886209">Semak bulan tamat tempoh anda dan cuba lagi</translation>
<translation id="5586446728396275693">Tiada alamat yang disimpan</translation>
<translation id="5595485650161345191">Edit alamat</translation>
@@ -865,6 +880,7 @@
<translation id="560412284261940334">Pengurusan tidak disokong</translation>
<translation id="5605670050355397069">Lejar</translation>
<translation id="5607240918979444548">Seni Bina-C</translation>
+<translation id="5608165884683734521">Tapak ini mungkin palsu atau penipuan. Chrome mengesyorkan agar anda meninggalkan tapak sekarang.</translation>
<translation id="5610142619324316209">Menyemak sambungan</translation>
<translation id="5610807607761827392">Anda boleh mengurus kad dan alamat dalam <ph name="BEGIN_LINK" />Tetapan<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> telah terlalu kerap mengubah hala anda.</translation>
@@ -888,11 +904,11 @@
<translation id="5720705177508910913">Pengguna semasa</translation>
<translation id="5728056243719941842">C5 (Sampul Surat)</translation>
<translation id="5730040223043577876">Chrome mengesyorkan penetapan semula kata laluan jika anda menggunakan semula kata laluan itu di tapak lain.</translation>
-<translation id="5732392974455271431">Ibu bapa anda boleh menyahsekatnya untuk anda</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Simpan kad ke Akaun Google anda}other{Simpan kad ke Akaun Google anda}}</translation>
<translation id="5763042198335101085">Masukkan alamat e-mel yang sah</translation>
<translation id="5765072501007116331">Pilih alamat untuk melihat kaedah dan syarat penghantaran</translation>
<translation id="5778550464785688721">Kawalan penuh peranti MIDI</translation>
+<translation id="5781136890105823427">Percubaan didayakan</translation>
<translation id="578305955206182703">Kuning jingga</translation>
<translation id="57838592816432529">Redam</translation>
<translation id="5784606427469807560">Terdapat masalah mengesahkan kad anda. Semak sambungan Internet anda dan cuba lagi.</translation>
@@ -909,13 +925,16 @@
<translation id="5860033963881614850">Dimatikan</translation>
<translation id="5863847714970149516">Halaman yang seterusnya mungkin cuba mengenakan bayaran kepada anda</translation>
<translation id="5866257070973731571">Tambahkan Nombor Telefon</translation>
+<translation id="5866898949289125849">Anda sedang melihat halaman alatan pembangun</translation>
<translation id="5869405914158311789">Tapak ini tidak dapat dicapai</translation>
<translation id="5869522115854928033">Kata laluan disimpan</translation>
<translation id="5887400589839399685">Kad disimpan</translation>
<translation id="5893752035575986141">Kad kredit diterima.</translation>
+<translation id="5895138241574237353">Mulakan Semula</translation>
<translation id="5901630391730855834">Kuning</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (disegerakkan)</translation>
<translation id="5916664084637901428">Hidupkan</translation>
+<translation id="59174027418879706">Didayakan</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Simpan kad ke Akaun Google?</translation>
<translation id="5922853866070715753">Hampir selesai</translation>
@@ -949,6 +968,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Gunakan kad anda pada semua peranti anda?</translation>
<translation id="6059925163896151826">Peranti USB</translation>
+<translation id="6060009363608157444">Mod DnsOverHttps tidak sah.</translation>
<translation id="6080696365213338172">Anda telah mengakses kandungan menggunakan perakuan yang disediakan oleh pentadbir. Data yang anda berikan kepada <ph name="DOMAIN" /> boleh dipintas oleh pentadbir anda.</translation>
<translation id="6094273045989040137">Anotasi</translation>
<translation id="610911394827799129">Akaun Google anda mungkin mempunyai bentuk sejarah penyemakan imbas yang lain di <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -997,13 +1017,12 @@
<translation id="6404511346730675251">Edit penanda halaman</translation>
<translation id="6406765186087300643">C0 (Sampul Surat)</translation>
<translation id="6410264514553301377">Masukkan tarikh tamat tempoh dan CVC untuk <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Anda telah bertanya kepada ibu bapa anda sama ada OK untuk melawat tapak ini</translation>
<translation id="6415778972515849510">Chromium boleh membantu anda melindungi Akaun Google anda dan menukar kata laluan anda.</translation>
-<translation id="6417515091412812850">Tidak dapat memeriksa sama ada sijil telah dibatalkan.</translation>
<translation id="6431585503458005759">Jangan simpan</translation>
<translation id="6433490469411711332">Edit maklumat hubungan</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> enggan menyambung.</translation>
<translation id="6434309073475700221">Buang</translation>
+<translation id="6435221585574090192">Kongsi data tentang acara keselamatan yang telah dibenderakan oleh Perlindungan Ancaman Chrome Enterprise dengan Pentadbir anda. Data ini mungkin termasuk url halaman, nama fail dan metadata fail, nama pengguna peranti anda dan nama pengguna Chrome.</translation>
<translation id="6440503408713884761">Diabaikan</translation>
<translation id="6446163441502663861">Kahu (Sampul Surat)</translation>
<translation id="6446608382365791566">Tambahkan maklumat lanjut</translation>
@@ -1012,20 +1031,19 @@
<translation id="6465306955648956876">Urus kata laluan...</translation>
<translation id="647261751007945333">Dasar peranti</translation>
<translation id="6476284679642588870">Urus kaedah pembayaran</translation>
-<translation id="6477321094435799029">Chrome mengesan kod luar biasa pada halaman ini dan menyekatnya untuk melindungi maklumat peribadi anda (contohnya, kata laluan, nombor telefon dan maklumat kad kredit).</translation>
<translation id="6489534406876378309">Mulakan muat naik ranap sistem</translation>
<translation id="6499038740797743453">Tetapkan semula kata laluan?</translation>
<translation id="6507833130742554667">Kad kredit dan debit diterima.</translation>
<translation id="650855688985305916">Ya, simpan</translation>
<translation id="6508722015517270189">Mulakan semula Chrome</translation>
<translation id="6517596291481585650">Amaran: Dasar ini tidak digabungkan sebagai senarai seperti yang dinyatakan oleh dasar kerana dasar ini bukan senarai.</translation>
+<translation id="6518133107902771759">Sahkan</translation>
<translation id="6521745193039995384">Tidak aktif</translation>
<translation id="6529602333819889595">&amp;Buat Semula Pemadaman</translation>
<translation id="6534179046333460208">Cadangan Web Fizikal</translation>
<translation id="6545864417968258051">Pengimbasan Bluetooth</translation>
<translation id="6554795675067793129">Akaun anda diurus oleh <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Buat semula</translation>
-<translation id="6563469144985748109">Pengurus anda belum meluluskannya</translation>
<translation id="6569060085658103619">Anda sedang melihat halaman sambungan</translation>
<translation id="6578796323535178455">C2 (Sampul Surat)</translation>
<translation id="6579990219486187401">Merah Jambu Cerah</translation>
@@ -1043,11 +1061,13 @@
<translation id="6643016212128521049">Kosongkan</translation>
<translation id="6644283850729428850">Dasar ini telah dikecam.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Tiada}=1{Daripada 1 tapak (anda tidak akan dilog keluar daripada Akaun Google anda)}other{Daripada # tapak (anda tidak akan dilog keluar daripada Akaun Google anda)}}</translation>
+<translation id="6652101503459149953">Gunakan Windows Hello</translation>
<translation id="6657585470893396449">Kata laluan</translation>
<translation id="6670613747977017428">Kembali ke keselamatan.</translation>
<translation id="6671697161687535275">Alih keluar cadangan borang daripada Chromium?</translation>
<translation id="6685834062052613830">Log keluar dan selesaikan persediaan</translation>
<translation id="6689271823431384964">Chrome menawarkan penyimpanan kad dalam Akaun Google anda kerana anda telah log masuk. Anda boleh menukar gelagat ini dalam tetapan. Nama pemegang kad diambil daripada akaun anda.</translation>
+<translation id="6707256370811247129">Imbas kandungan cache dan fail yang anda muat turun atau muat naik dalam Chrome.</translation>
<translation id="6710213216561001401">Sebelumnya</translation>
<translation id="6710594484020273272">&lt;Taip istilah carian&gt;</translation>
<translation id="671076103358959139">Token Pendaftaran:</translation>
@@ -1055,10 +1075,10 @@
<translation id="6738516213925468394">Data anda disulitkan dengan <ph name="BEGIN_LINK" />ungkapan laluan segerak<ph name="END_LINK" /> anda pada <ph name="TIME" />. Masukkannya untuk memulakan penyegerakan.</translation>
<translation id="674375294223700098">Ralat sijil pelayan tidak diketahui.</translation>
<translation id="6744009308914054259">Sementara menunggu sambungan, anda boleh melawati Muat turun untuk membaca artikel luar talian.</translation>
+<translation id="6747611005629681221">Amaran: Ciri ditamatkan di hadapan!</translation>
<translation id="6753269504797312559">Nilai dasar</translation>
<translation id="6757797048963528358">Peranti anda tidak aktif.</translation>
<translation id="6768213884286397650">Hagaki (Poskad)</translation>
-<translation id="6778737459546443941">Ibu bapa anda belum meluluskannya</translation>
<translation id="67862343314499040">Ungu Lembayung</translation>
<translation id="6786747875388722282">Pelanjutan</translation>
<translation id="6790428901817661496">Mainkan</translation>
@@ -1066,6 +1086,7 @@
<translation id="681021252041861472">Medan Diperlukan</translation>
<translation id="6810899417690483278">ID Penyesuaian</translation>
<translation id="6825578344716086703">Anda cuba untuk mencapai <ph name="DOMAIN" />, tetapi pelayan memberikan sijil yang ditandatangani menggunakan algoritma tandatangan yang lemah (seperti SHA-1). Ini bermakna bahawa bukti kelayakan keselamatan yang diberi pelayan mungkin dipalsukan dan pelayan tersebut bukan seperti yang anda jangkakan (anda mungkin berkomunikasi dengan penyerang).</translation>
+<translation id="6826370046007623921">Pencegahan Kehilangan Data</translation>
<translation id="6831043979455480757">Terjemah</translation>
<translation id="6839929833149231406">Kawasan</translation>
<translation id="6852204201400771460">Muat semula apl?</translation>
@@ -1078,7 +1099,6 @@
<translation id="6891596781022320156">Tahap dasar tidak disokong.</translation>
<translation id="6895330447102777224">Kad anda telah disahkan</translation>
<translation id="6897140037006041989">Ejen Pengguna</translation>
-<translation id="6903319715792422884">Bantu dalam meningkatkan Penyemakan Imbas Selamat dengan menghantar beberapa <ph name="BEGIN_WHITEPAPER_LINK" />maklumat sistem dan kandungan halaman<ph name="END_WHITEPAPER_LINK" /> kepada Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Pengguna:</translation>
<translation id="6934672428414710184">Nama ini daripada Akaun Google anda</translation>
<translation id="6944692733090228304">Anda memasukkan kata laluan di tapak yang tidak diurus oleh <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Untuk melindungi akaun anda, jangan gunakan semula kata laluan anda pada apl dan tapak lain.</translation>
@@ -1123,6 +1143,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> lagi}other{<ph name="PAYMENT_METHOD_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> lagi}}</translation>
<translation id="7153618581592392745">Gandaria</translation>
<translation id="717330890047184534">ID Gaia:</translation>
+<translation id="7174545416324379297">Digabungkan</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> lagi}other{<ph name="SHIPPING_OPTION_PREVIEW" /> dan <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> lagi}}</translation>
<translation id="7177397715882417099">Pelayan destinasi anda, <ph name="ORIGIN" />, telah meminta agar dasar keselamatan dikenakan pada semua permintaan yang diterimanya. Pelayan itu sepatutnya menyampaikan dasar tersebut, tetapi sebaliknya telah mengubah hala penyemak imbas ke tempat lain, yang menghalang penyemak imbas daripada memenuhi permintaan anda untuk <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Simpan dan Lengkapkan Kaedah Pembayaran</translation>
@@ -1157,6 +1178,7 @@ Butiran tambahan:
<translation id="7320336641823683070">Bantuan Sambungan</translation>
<translation id="733354035281974745">Pembatalan akaun setempat peranti</translation>
<translation id="7334320624316649418">&amp;Buat semula susun semula</translation>
+<translation id="7337706099755338005">Tidak tersedia pada platform anda.</translation>
<translation id="733923710415886693">Sijil pelayan tidak didedahkan melalui Ketelusan Sijil.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Ialah ahli gabungan:</translation>
@@ -1188,7 +1210,6 @@ Butiran tambahan:
<translation id="7440140511386898319">Teroka semasa di luar talian</translation>
<translation id="7441627299479586546">Subjek dasar salah</translation>
<translation id="7442725080345379071">Jingga Cerah</translation>
-<translation id="7444046173054089907">Tapak ini disekat</translation>
<translation id="7445762425076701745">Identiti pelayan yang disambungkan kepada anda tidak dapat disahkan sepenuhnya. Anda disambungkan ke pelayan menggunakan nama yang sah dalam rangkaian anda sahaja, apabila pihak berkuasa sijil luaran tiada cara untuk mengesahkan pemilikan. Oleh kerana beberapa pihak berkuasa sijil juga akan terus mengeluarkan sijil untuk nama ini, tiada cara untuk memastikan anda disambungkan ke tapak web yang diingini dan bukannya penyerang.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Ketahui lebih lanjut<ph name="END_LINK" /> tentang masalah ini.</translation>
<translation id="7455133967321480974">Gunakan lalai global (Sekat)</translation>
@@ -1210,9 +1231,9 @@ Butiran tambahan:
<translation id="7538364083937897561">A2 (Sampul Surat)</translation>
<translation id="7542403920425041731">Setelah anda mengesahkan, butiran kad anda akan dikongsi dengan tapak ini.</translation>
<translation id="7542995811387359312">Pengisian kad kredit automatik dilumpuhkan kerana borang ini tidak menggunakan sambungan selamat.</translation>
-<translation id="7543525346216957623">Tanya ibu bapa anda</translation>
<translation id="7548892272833184391">Betulkan ralat sambungan</translation>
<translation id="7549584377607005141">Halaman web ini memerlukan data yang anda masukkan sebelum ini agar dapat dipaparkan dengan betul. Anda boleh menghantar data ini semula, tetapi dengan berbuat demikian anda akan mengulangi sebarang tindakan terdahulu yang telah dilakukan oleh halaman ini.</translation>
+<translation id="7550637293666041147">Nama pengguna peranti dan nama pengguna Chrome anda</translation>
<translation id="7552846755917812628">Cuba petua berikut:</translation>
<translation id="7554791636758816595">Tab Baharu</translation>
<translation id="7564049878696755256">Anda boleh kehilangan akses kepada akaun <ph name="ORG_NAME" /> anda atau mengalami kecurian identiti. Chrome mengesyorkan supaya kata laluan anda ditukar sekarang.</translation>
@@ -1227,6 +1248,7 @@ Butiran tambahan:
<translation id="7610193165460212391">Nilai berada di luar julat <ph name="VALUE" /></translation>
<translation id="7613889955535752492">Tamat: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Anda sudah mempunyai data yang disulitkan menggunakan versi kata laluan Akaun Google anda yang berbeza. Sila masukkannya di bawah.</translation>
+<translation id="7625784245512586808">Perlindungan Ancaman Chrome Enterprise</translation>
<translation id="7633909222644580952">Data prestasi dan laporan ranap sistem</translation>
<translation id="7637571805876720304">Alih keluar kad kredit daripada Chromium?</translation>
<translation id="7638605456503525968">Port siri</translation>
@@ -1239,7 +1261,6 @@ Butiran tambahan:
<translation id="7668654391829183341">Peranti tidak diketahui</translation>
<translation id="7669271284792375604">Penyerang pada tapak ini mungkin cuba menipu dengan meminta anda memasang atur cara yang membahayakan pengalaman penyemakan imbas anda (contohnya, dengan menukar halaman utama anda atau menunjukkan iklan tambahan pada laman yang anda lawati).</translation>
<translation id="7676643023259824263">Cari teks papan keratan, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform dan Awan</translation>
<translation id="7681101578153515023">Tukar Enjin Carian</translation>
<translation id="7682287625158474539">Penghantaran</translation>
<translation id="7687186412095877299">Mengisi borang pembayaran dengan kaedah pembayaran yang disimpan</translation>
@@ -1254,7 +1275,6 @@ Butiran tambahan:
<translation id="7723047071702270851">Edit Kad</translation>
<translation id="774634243536837715">Kandungan berbahaya disekat.</translation>
<translation id="7752995774971033316">Tidak Diurus</translation>
-<translation id="7755287808199759310">Ibu bapa anda boleh menyahsekatnya untuk anda</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Tembok api atau perisian antivirus mungkin telah menyekat sambungan.</translation>
<translation id="7759163816903619567">Domain paparan:</translation>
@@ -1298,7 +1318,6 @@ Butiran tambahan:
<translation id="8004582292198964060">Penyemak Imbas</translation>
<translation id="8009225694047762179">Urus Kata Laluan</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Kad ini dan alamat pengebilannya akan disimpan. Anda akan dapat menggunakan kad ini apabila anda log masuk ke <ph name="USER_EMAIL" />.}other{Kad ini dan alamat pengebilannya akan disimpan. Anda akan dapat menggunakan kad ini apabila anda log masuk ke <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Kami tidak dapat menghubungi ibu bapa anda pada masa ini. Sila cuba lagi.</translation>
<translation id="8025119109950072390">Penyerang pada tapak ini mungkin menipu anda supaya melakukan sesuatu yang berbahaya seperti memasang perisian atau mendedahkan maklumat peribadi anda (contohnya, kata laluan, nombor telefon atau maklumat kad kredit).</translation>
<translation id="8034522405403831421">Halaman ini dalam <ph name="SOURCE_LANGUAGE" />. Terjemahkannya kepada <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pen</translation>
@@ -1309,6 +1328,7 @@ Butiran tambahan:
<translation id="8041940743680923270">Gunakan lalai global (Tanya)</translation>
<translation id="8042918947222776840">Pilih Kaedah Pengambilan</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" tidak dikonfigurasi dengan betul. Tindakan menyahpasang "<ph name="SOFTWARE_NAME" />" biasanya dapat menyelesaikan masalah ini. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Anda tidak perlu memasukkan kod keselamatan kad selepas ini</translation>
<translation id="8066955247577885446">Maaf, kesilapan telah berlaku.</translation>
<translation id="8074253406171541171">10x13 (Sampul Surat)</translation>
<translation id="8078141288243656252">Tidak boleh melakukan anotasi apabila diputarkan</translation>
@@ -1339,6 +1359,7 @@ Butiran tambahan:
<translation id="8211406090763984747">Sambungan selamat</translation>
<translation id="8218327578424803826">Lokasi yang Ditentukan:</translation>
<translation id="8220146938470311105">C7/C6 (Sampul Surat)</translation>
+<translation id="8220639454292072926">Pelaporan Perusahaan</translation>
<translation id="8225771182978767009">Orang yang menyediakan komputer ini telah memilih untuk menyekat tapak ini.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Buka halaman dalam tab Inkognito baharu</translation>
@@ -1393,24 +1414,24 @@ Butiran tambahan:
<translation id="8508648098325802031">Ikon Carian</translation>
<translation id="8522552481199248698">Chrome boleh membantu anda melindungi Akaun Google anda dan menukar kata laluan anda.</translation>
<translation id="8543181531796978784">Anda boleh <ph name="BEGIN_ERROR_LINK" />laporkan masalah pengesanan<ph name="END_ERROR_LINK" /> atau jika anda memahami risikonya kepada keselamatan anda, <ph name="BEGIN_LINK" />lawati tapak yang tidak selamat ini<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Ada soalan? Hubungi orang yang menyelia profil anda.</translation>
<translation id="8553075262323480129">Gagal terjemahan kerana bahasa halaman tidak dapat ditentukan.</translation>
<translation id="8557066899867184262">CVC terletak di belakang kad anda.</translation>
<translation id="8559762987265718583">Sambungan peribadi ke <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> tidak boleh diwujudkan kerana tarikh dan masa peranti anda (<ph name="DATE_AND_TIME" />) tidak betul.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> tapak mencurigakan</translation>
<translation id="8564985650692024650">Chromium mengesyorkan penetapan semula kata laluan <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> jika anda menggunakan semula kata laluan itu di tapak lain.</translation>
<translation id="8571890674111243710">Menterjemah halaman ke <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Tambah no. tel.
</translation>
-<translation id="859285277496340001">Sijil tidak menyatakan mekanisme untuk memeriksa sama ada ia telah dibatalkan.</translation>
<translation id="860043288473659153">Nama pemegang kad</translation>
<translation id="861775596732816396">Saiz 4</translation>
-<translation id="8620436878122366504">Ibu bapa anda belum meluluskannya</translation>
<translation id="8622948367223941507">Perundangan-Ekstra</translation>
<translation id="8625384913736129811">Simpan Kad Ini pada Peranti Ini</translation>
<translation id="8626112503828625890">Simpan butiran pengebilan dalam Akaun Google?</translation>
+<translation id="8647750283161643317">Tetapkan semula semua kepada lalai</translation>
<translation id="8663226718884576429">Ringkasan Pesanan, <ph name="TOTAL_LABEL" />, Butiran Lanjut</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, jawapan, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Tersedia</translation>
<translation id="8703575177326907206">Sambungan anda ke <ph name="DOMAIN" /> tidak disulitkan.</translation>
<translation id="8718314106902482036">Pembayaran belum selesai</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, cadangan carian</translation>
@@ -1421,6 +1442,7 @@ Butiran tambahan:
<translation id="8738058698779197622">Untuk mewujudkan sambungan yang selamat, jam anda perlu ditetapkan dengan betul. Ini kerana sijil yang digunakan oleh tapak web untuk mengenal pastinya hanya sah untuk tempoh masa yang tertentu. Memandangkan jam peranti anda tidak betul, Chromium tidak boleh mengesahkan sijil-sijil ini.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Alamat DNS&lt;/abbr&gt; <ph name="HOST_NAME" /> tidak ditemui. Masalah sedang didiagnosis.</translation>
<translation id="874846938927089722">Kad Kredit dan Prabayar yang Diterima</translation>
+<translation id="874918643257405732">Tanda tab ini</translation>
<translation id="8759274551635299824">Kad ini telah tamat tempoh</translation>
<translation id="8761567432415473239">Penyemakan Imbas Selamat Google baru-baru ini <ph name="BEGIN_LINK" />menemui atur cara berbahaya<ph name="END_LINK" /> pada <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Peranti USB</translation>
@@ -1450,6 +1472,7 @@ Butiran tambahan:
<translation id="8938939909778640821">Kad kredit dan prabayar yang diterima</translation>
<translation id="8943282376843390568">Hijau pucuk pisang</translation>
<translation id="8957210676456822347">Keizinan Portal Tawanan</translation>
+<translation id="8962950042226115166">Tapak mencurigakan</translation>
<translation id="8968766641738584599">Simpan kad</translation>
<translation id="8971063699422889582">Sijil pelayan telah tamat tempoh.</translation>
<translation id="8975012916872825179">Merangkumi maklumat seperti nombor telefon, alamat e-mel dan alamat penghantaran</translation>
@@ -1472,24 +1495,24 @@ Butiran tambahan:
<translation id="9035022520814077154">Ralat keselamatan</translation>
<translation id="9038649477754266430">Gunakan perkhidmatan ramalan untuk memuatkan halaman lebih cepat</translation>
<translation id="9039213469156557790">Selain itu, halaman ini mengandungi sumber lain yang tidak selamat. Sumber ini boleh dilihat oleh orang lain semasa dalam transit dan boleh diubah oleh penyerang untuk menukar kelakuan halaman.</translation>
+<translation id="9044359186343685026">Gunakan Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Anda cuba untuk mencapai <ph name="DOMAIN" />, tetapi pelayan memberikan sijil tidak sah.</translation>
<translation id="9050666287014529139">Frasa laluan</translation>
<translation id="9065203028668620118">Edit</translation>
<translation id="9065745800631924235">Carian <ph name="TEXT" /> daripada sejarah</translation>
<translation id="9069693763241529744">Disekat oleh sambungan</translation>
-<translation id="9076283476770535406">Tapak mungkin mengandungi kandungan dewasa</translation>
<translation id="9076630408993835509">Penyemak imbas ini tidak diurus oleh syarikat atau organisasi lain. Aktiviti pada peranti ini mungkin diurus di luar Chrome. <ph name="BEGIN_LINK" />Ketahui Lebih Lanjut<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Maklumat lanjut diperlukan</translation>
<translation id="9080712759204168376">Ringkasan Pesanan</translation>
<translation id="9089260154716455634">Dasar Luar Waktu:</translation>
<translation id="9095388113577226029">Lagi bahasa...</translation>
+<translation id="9098981495403789647">Pentadbir telah mendayakan Perlindungan Ancaman Chrome Enterprise pada penyemak imbas anda. Perlindungan Ancaman Chrome Enterprise mempunyai akses kepada sesetengah data anda.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> biasanya menggunakan penyulitan untuk melindungi maklumat anda. Apabila Chromium cuba menyambung ke <ph name="SITE" /> pada kali ini, tapak web tersebut mengembalikan bukti kelayakan yang luar biasa dan salah. Hal ini boleh berlaku apabila penyerang sedang cuba menyamar sebagai <ph name="SITE" /> atau skrin log masuk Wi-Fi telah memutuskan sambungan. Maklumat anda masih selamat kerana Chromium menghentikan sambungan sebelum sebarang pertukaran data berlaku.</translation>
<translation id="9106062320799175032">Tambahkan Alamat Pengebilan</translation>
<translation id="9114524666733003316">Mengesahkan kad...</translation>
<translation id="9128870381267983090">Sambung ke rangkaian</translation>
<translation id="9137013805542155359">Paparkan asal</translation>
-<translation id="9137248913990643158">Sila mulakan dan log masuk ke Chrome sebelum menggunakan apl ini.</translation>
<translation id="9141013498910525015">Urus alamat</translation>
<translation id="9148088599418889305">Pilih Kaedah Penghantaran</translation>
<translation id="9148507642005240123">&amp;Buat asal edit</translation>
diff --git a/chromium/components/strings/components_strings_nl.xtb b/chromium/components/strings/components_strings_nl.xtb
index c6c76c9cdb1..c7294e03ad1 100644
--- a/chromium/components/strings/components_strings_nl.xtb
+++ b/chromium/components/strings/components_strings_nl.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Naam op pas toevoegen</translation>
<translation id="1089439967362294234">Wachtwoord wijzigen</translation>
+<translation id="1096545575934602868">Dit veld mag niet meer dan <ph name="MAX_ITEMS_LIMIT" /> items bevatten. Verdere items worden verwijderd.</translation>
<translation id="109743633954054152">Wachtwoorden beheren in de Chrome-instellingen</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> altijd vertalen</translation>
<translation id="1107591249535594099">Als deze optie is aangevinkt, bewaart Chrome een exemplaar van je pas op dit apparaat om formulieren sneller te kunnen invullen.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Een <ph name="BEGIN_LINK" />gecacht exemplaar<ph name="END_LINK" /> van <ph name="URL" /> openen</translation>
<translation id="1156303062776767266">Je bekijkt een lokaal of gedeeld bestand</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> heeft de verbinding onverwacht verbroken.</translation>
+<translation id="115926840831309955">Controleer je CVC en probeer het opnieuw of update de vervaldatum</translation>
<translation id="1161325031994447685">Maak opnieuw verbinding met wifi</translation>
<translation id="1165039591588034296">Fout</translation>
<translation id="1175364870820465910">&amp;Afdrukken...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">'Software op je computer voorkomt dat Chrome veilig verbinding kan maken met internet' (alleen Windows-computers)</translation>
<translation id="1294154142200295408">Opdrachtregelvarianten</translation>
<translation id="129553762522093515">Recent gesloten</translation>
+<translation id="1298536327547837046">Scannen op malware</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Probeer je cookies te wissen<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Verouderde functies</translation>
<translation id="1320233736580025032">Prc1 (envelop)</translation>
<translation id="132301787627749051">Zoeken naar klembordafbeelding</translation>
<translation id="1323433172918577554">Meer weergeven</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google Spreadsheets</translation>
<translation id="1527263332363067270">Wachten op verbinding...</translation>
<translation id="1529521330346880926">10x15 (envelop)</translation>
+<translation id="1530707389502320859">De site die je zojuist probeerde te bezoeken, lijkt nep te zijn. Aanvallers maken sites soms na door kleine wijzigingen in de URL aan te brengen die je moeilijk kunt zien.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Deze pagina meldt het volgende</translation>
<translation id="153384715582417236">Dat is voorlopig alles</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">Besturingssysteem</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Document is te groot om aantekeningen te maken</translation>
-<translation id="1721312023322545264">Je hebt toestemming van <ph name="NAME" /> nodig om deze site te bezoeken</translation>
<translation id="1721424275792716183">* Verplicht veld</translation>
<translation id="1727741090716970331">Een geldig kaartnummer toevoegen</translation>
<translation id="1728677426644403582">Je bekijkt de bron van een webpagina</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Websites die je bezoekt en waarop je tijd doorbrengt</translation>
<translation id="1826516787628120939">Controleren</translation>
<translation id="1834321415901700177">Deze site bevat schadelijke programma's</translation>
+<translation id="1838374766361614909">Zoekopdracht wissen</translation>
<translation id="1839551713262164453">De validatie van de beleidswaarden is mislukt doordat er fouten zijn opgetreden</translation>
<translation id="1842969606798536927">Betalen</translation>
<translation id="1871208020102129563">Proxy is ingesteld op het gebruik van vaste proxyservers, niet op een script-URL van het PAC-type.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Lijst samenvouwen</translation>
<translation id="1898423065542865115">Filteren</translation>
<translation id="1914326953223720820">Uitpakservice</translation>
+<translation id="1915697529809968049">Touch ID gebruiken in plaats van CVC?</translation>
<translation id="1916770123977586577">Laad deze pagina opnieuw om je geüpdatete instellingen toe te passen op deze site</translation>
<translation id="1919345977826869612">Advertenties</translation>
<translation id="1919367280705858090">Hulp bij een specifieke foutmelding</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Bladwijzers voor <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Serialisatiefout</translation>
<translation id="1974060860693918893">Geavanceerd</translation>
+<translation id="1974883374937189061">Help de Chrome-beveiliging te verbeteren door <ph name="BEGIN_WHITEPAPER_LINK" />URL's van sommige pagina's die je bezoekt, beperkte systeemgegevens en bepaalde paginacontent<ph name="END_WHITEPAPER_LINK" /> naar Google te sturen. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Firmwareversie</translation>
<translation id="1981206234434200693">De gegevens van de Chrome-browsegeschiedenis wissen</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{en 1 andere}other{en # andere}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Geef een geldig vervaljaar op</translation>
<translation id="2212735316055980242">Beleid niet gevonden</translation>
<translation id="2213606439339815911">Items ophalen…</translation>
+<translation id="2215727959747642672">Bestanden bewerken</translation>
<translation id="2218879909401188352">Op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> actieve cybercriminelen kunnen gevaarlijke apps installeren die je apparaat beschadigen, verborgen kosten toevoegen aan je mobiele telefoonrekening of je persoonlijke informatie stelen. <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Geen internet</translation>
<translation id="2230458221926704099">Los problemen met je verbinding op met de <ph name="BEGIN_LINK" />diagnose-app<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Nu verzenden</translation>
+<translation id="2248949050832152960">WebAuthn gebruiken</translation>
<translation id="225207911366869382">Deze waarde is verouderd voor dit beleid.</translation>
<translation id="2257315177824333709">Sorry, je kaart kan op dit moment niet worden opgeslagen</translation>
<translation id="2262243747453050782">HTTP-fout</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">Ongeldige zoek-URL.</translation>
<translation id="2482878487686419369">Meldingen</translation>
<translation id="248348093745724435">Apparaatbeleid</translation>
-<translation id="2485387744899240041">Gebruikersnamen voor je apparaat en browser</translation>
<translation id="2491120439723279231">Het servercertificaat bevat fouten.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Parser</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Terug</translation>
<translation id="2503184589641749290">Geaccepteerde betaalpassen en prepaidkaarten</translation>
<translation id="2505268675989099013">Account beschermen</translation>
+<translation id="2515335152965840738">NEGEREN</translation>
<translation id="2515629240566999685">Check of je bereik hebt in je omgeving</translation>
<translation id="2523886232349826891">Alleen opgeslagen op dit apparaat</translation>
<translation id="2524461107774643265">Meer informatie toevoegen</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Verzenden</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Geen}=1{1 wachtwoord (voor <ph name="DOMAIN_LIST" />)}=2{2 wachtwoorden (voor <ph name="DOMAIN_LIST" />)}other{# wachtwoorden (voor <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Andere tabbladen of apps sluiten</translation>
-<translation id="267371737713284912">druk op <ph name="MODIFIER_KEY_DESCRIPTION" /> om dit ongedaan maken</translation>
<translation id="2674170444375937751">Weet je zeker dat je deze pagina's uit je geschiedenis wilt verwijderen?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Verlaten</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">Waarde komt niet overeen met notatie.</translation>
<translation id="2705137772291741111">De in het cachegeheugen opgeslagen versie van deze site is niet bereikbaar.</translation>
<translation id="2709516037105925701">Automatisch aanvullen</translation>
-<translation id="2712173769900027643">Toestemming vragen</translation>
<translation id="2713444072780614174">Wit</translation>
<translation id="2720342946869265578">In de buurt</translation>
<translation id="2721148159707890343">Verzoek geslaagd</translation>
<translation id="2728127805433021124">Het certificaat van de server is ondertekend met een zwak ondertekeningsalgoritme.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Verbindingsdiagnose uitvoeren<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Als je deze functies inschakelt, kun je browsergegevens kwijtraken of je veiligheid of privacy in gevaar brengen. Ingeschakelde functies zijn van toepassing op alle gebruikers van deze browser.</translation>
<translation id="2735043616039983645">Er zijn meerdere bronnen met conflicterende waarden aanwezig voor dit beleid.</translation>
<translation id="2738330467931008676">Ophaaladres kiezen</translation>
<translation id="2740531572673183784">OK</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">De verbinding is opnieuw ingesteld.</translation>
<translation id="2788784517760473862">Geaccepteerde creditcards</translation>
<translation id="2792012897584536778">De beheerders van dit apparaat hebben beveiligingscertificaten ingesteld waarmee ze de content kunnen bekijken van websites die je bezoekt.</translation>
-<translation id="2794233252405721443">Site geblokkeerd</translation>
<translation id="2799020568854403057">De volgende site bevat schadelijke apps</translation>
<translation id="2799223571221894425">Opnieuw starten</translation>
<translation id="2803306138276472711">Google Safe Browsing heeft onlangs <ph name="BEGIN_LINK" />malware gedetecteerd<ph name="END_LINK" /> op <ph name="SITE" />. Websites die normaal gesproken veilig zijn, worden soms geïnfecteerd met malware.</translation>
+<translation id="2815364696811431560">SITE VERLATEN</translation>
<translation id="2824775600643448204">Adres- en zoekbalk</translation>
<translation id="2826760142808435982">De verbinding is gecodeerd en geverifieerd met <ph name="CIPHER" /> en gebruikt <ph name="KX" /> als mechanisme voor sleuteluitwisseling.</translation>
<translation id="2835170189407361413">Formulier leegmaken</translation>
<translation id="2847118875340931228">Incognitovenster openen</translation>
<translation id="2850739647070081192">Invite (envelop)</translation>
-<translation id="2851634818064021665">Je hebt toestemming nodig om deze site te bezoeken</translation>
<translation id="2856444702002559011">Cybercriminelen proberen mogelijk je gegevens van <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> te stelen (bijvoorbeeld wachtwoorden, berichten of creditcardgegevens). <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Pas opslaan?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Als deze instelling is ingeschakeld, slaat Chromium een kopie van je pas op dit apparaat op zodat formulieren sneller kunnen worden ingevuld.</translation>
<translation id="2985398929374701810">Geef een geldig adres op</translation>
<translation id="2986368408720340940">Deze ophaalmethode is niet beschikbaar. Kies een andere methode.</translation>
+<translation id="2987034854559945715">Geen overeenkomende functies</translation>
<translation id="2991174974383378012">Delen met websites</translation>
<translation id="2991571918955627853">Je kunt <ph name="SITE" /> momenteel niet bezoeken, omdat de website HSTS gebruikt. Netwerkfouten en aanvallen zijn doorgaans tijdelijk, dus deze pagina werkt later waarschijnlijk correct.</translation>
<translation id="3005723025932146533">Opgeslagen kopie weergeven</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Onjuist beleidstype</translation>
<translation id="3037605927509011580">Helaas.</translation>
<translation id="3041612393474885105">Certificaatgegevens</translation>
+<translation id="3057676462092457419">De DnsOverHttps-modus <ph name="SECURE_DNS_MODE_SECURE" /> wordt nog niet ondersteund. De modus is ingesteld op <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (envelop)</translation>
<translation id="3061707000357573562">Patchservice</translation>
<translation id="3064966200440839136">Je verlaat de incognitomodus om te betalen via een externe app. Doorgaan?</translation>
@@ -416,6 +425,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> op <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Betaling annuleren</translation>
<translation id="3207960819495026254">Toegevoegd aan 'Bladwijzers'</translation>
+<translation id="3209034400446768650">Pagina kan geld in rekening brengen</translation>
<translation id="3225919329040284222">De server heeft een certificaat gepresenteerd dat niet overeenkomt met de ingebouwde verwachtingen. Deze verwachtingen zijn opgenomen voor bepaalde websites om je te beschermen.</translation>
<translation id="3226128629678568754">Klik op de knop 'Opnieuw laden' om de gegevens opnieuw te verzenden die nodig zijn om de pagina te laden.</translation>
<translation id="3227137524299004712">Microfoon</translation>
@@ -423,7 +433,6 @@
<translation id="3229041911291329567">Versie-informatie over je apparaat en browser</translation>
<translation id="323107829343500871">De CVC-code voor <ph name="CREDIT_CARD" /> opgeven</translation>
<translation id="3234666976984236645">Altijd belangrijke content op deze site detecteren</translation>
-<translation id="3254409185687681395">Bladwijzer instellen voor deze pagina</translation>
<translation id="3270847123878663523">&amp;Volgorde wijzigen ongedaan maken</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Naam op pas toevoegen</translation>
@@ -433,7 +442,6 @@
<translation id="3320021301628644560">Factuuradres toevoegen</translation>
<translation id="3324983252691184275">Karmozijnrood</translation>
<translation id="3338095232262050444">Beveiligd</translation>
-<translation id="3345135638360864351">Je verzoek om toegang tot deze site kan niet worden verzonden naar <ph name="NAME" />. Probeer het opnieuw.</translation>
<translation id="3355823806454867987">Proxyinstellingen wijzigen...</translation>
<translation id="3361596688432910856">De volgende gegevens worden <ph name="BEGIN_EMPHASIS" />niet opgeslagen<ph name="END_EMPHASIS" /> in Chrome:
<ph name="BEGIN_LIST" />
@@ -467,17 +475,14 @@
<translation id="3462200631372590220">Gedetailleerde informatie verbergen</translation>
<translation id="3467763166455606212">Naam kaarthouder vereist</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, momenteel geopend. druk op Tab en vervolgens op Enter om naar het geopende tabblad te schakelen</translation>
-<translation id="3479539252931486093">Wat dit onverwacht? <ph name="BEGIN_LINK" />Laat het ons weten<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Niet nu</translation>
<translation id="3484560055331845446">Je kunt de toegang tot je Google-account kwijtraken. Chrome raadt je aan je wachtwoord nu te wijzigen. Je wordt gevraagd in te loggen op je account.</translation>
<translation id="3495081129428749620">Zoeken op pagina <ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">We kunnen je ouder momenteel niet bereiken. Probeer het opnieuw.</translation>
<translation id="3512163584740124171">Dit beleid wordt genegeerd omdat een ander beleid in dezelfde beleidsgroep een hogere prioriteit heeft.</translation>
<translation id="3528171143076753409">Het servercertificaat is niet betrouwbaar.</translation>
<translation id="3528485271872257980">Donkerbruin</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Ten minste één item op gesynchroniseerde apparaten}=1{1 item (en meer op gesynchroniseerde apparaten)}other{# items (en meer op gesynchroniseerde apparaten)}}</translation>
<translation id="3539171420378717834">Een exemplaar van deze pas op dit apparaat bewaren</translation>
-<translation id="3556433843310711081">Je beheerder kan de blokkering van de site opheffen</translation>
<translation id="3566021033012934673">Je verbinding is niet privé</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Een ingesloten pagina op <ph name="SITE" /> meldt het volgende</translation>
@@ -504,6 +509,7 @@
<translation id="3678529606614285348">Pagina openen in een nieuw incognitovenster (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Crashrapport vastgelegd op <ph name="CRASH_TIME" />, geüpload op <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Certificaatgegevens</translation>
+<translation id="3701427423622901115">Reset bevestigd.</translation>
<translation id="3704162925118123524">Het is mogelijk dat je de inlogpagina moet bezoeken van het netwerk dat je gebruikt.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Bezig met laden...</translation>
@@ -520,6 +526,7 @@
<translation id="3748148204939282805">Cybercriminelen op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kunnen proberen om je te misleiden zodat je iets gevaarlijks doet, bijvoorbeeld software installeren of je persoonlijke informatie bekendmaken (zoals wachtwoorden, telefoonnummers of creditcardgegevens). <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Het vertalen is mislukt wegens een serverfout.</translation>
<translation id="3759461132968374835">Je hebt geen onlangs gemelde crashes. Crashes die zich voordeden toen de crashrapportage was uitgeschakeld, worden hier niet weergegeven.</translation>
+<translation id="3760561303380396507">Windows Hello gebruiken in plaats van CVC?</translation>
<translation id="3761718714832595332">Status verbergen</translation>
<translation id="3765032636089507299">De Safe Browsing-pagina is in aanbouw.</translation>
<translation id="3778403066972421603">Wil je deze pas opslaan in je Google-account en op dit apparaat?</translation>
@@ -529,6 +536,7 @@
<translation id="3789155188480882154">Grootte 16</translation>
<translation id="3797522431967816232">Prc3 (envelop)</translation>
<translation id="3807873520724684969">Schadelijke content geblokkeerd.</translation>
+<translation id="3808375843007691220">Waarschuwing: Hierna volgen experimentele functies</translation>
<translation id="3810973564298564668">Beheren</translation>
<translation id="382518646247711829">Als je een proxyserver gebruikt...</translation>
<translation id="3828924085048779000">Een lege wachtwoordzin is niet toegestaan.</translation>
@@ -537,11 +545,11 @@
<translation id="3858027520442213535">Datum en tijd updaten</translation>
<translation id="3884278016824448484">Conflicterende apparaat-ID's</translation>
<translation id="3885155851504623709">Parochie</translation>
-<translation id="3886446263141354045">Je verzoek voor toegang tot deze website is verzonden naar <ph name="NAME" /></translation>
<translation id="3890664840433101773">E-mailadres toevoegen</translation>
<translation id="3901925938762663762">De pas is verlopen</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">WebAuthn gebruiken in plaats van CVC?</translation>
<translation id="3946209740501886391">Altijd vragen op deze site</translation>
<translation id="3949571496842715403">Deze server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. In het bijbehorende beveiligingscertificaat worden geen 'Subject Alternative Names' gespecificeerd. Dit kan worden veroorzaakt door een verkeerde configuratie of door een aanvaller die je verbinding heeft onderschept.</translation>
<translation id="3949601375789751990">Je browsegeschiedenis wordt hier weergegeven</translation>
@@ -552,11 +560,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Geen}=1{Van één site }other{Van # sites }}</translation>
<translation id="397105322502079400">Berekenen...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> wordt geblokkeerd</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> heeft Chrome Enterprise Threat Protection ingeschakeld in je browser. Chrome Enterprise Threat Protection heeft toegang tot sommige van je gegevens.</translation>
<translation id="3987940399970879459">Minder dan 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 webpagina in de buurt}other{# webpagina's in de buurt}}</translation>
<translation id="4030383055268325496">&amp;Toevoegen ongedaan maken</translation>
<translation id="4032320456957708163">Je browser wordt beheerd door <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">De link die je hebt geopend, leidt naar een site die je normaal niet bezoekt. De site probeert je mogelijk in verwarring te brengen.</translation>
<translation id="4058922952496707368">Sleutel '<ph name="SUBKEY" />': <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (envelop)</translation>
<translation id="4067947977115446013">Geldig adres toevoegen</translation>
@@ -569,6 +577,7 @@
<translation id="4103249731201008433">Serienummer van apparaat is ongeldig</translation>
<translation id="410351446219883937">Automatisch afspelen</translation>
<translation id="4103763322291513355">Ga naar &lt;strong&gt;chrome://policy&lt;/strong&gt; om de lijst met URL's op de zwarte lijst en andere beleidsregels te bekijken die worden afgedwongen door je systeembeheerder.</translation>
+<translation id="4108231218301530806">Gebruik de volgende keer je vingerafdruk om deze kaart te verifiëren.</translation>
<translation id="4110652170750985508">Je betaling controleren</translation>
<translation id="4112140312785995938">Achteruit zoeken</translation>
<translation id="4116663294526079822">Altijd toestaan op deze site</translation>
@@ -583,6 +592,7 @@
<translation id="4171400957073367226">Onjuiste verificatiehandtekening</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Nog <ph name="ITEM_COUNT" /> item}other{Nog <ph name="ITEM_COUNT" /> items}}</translation>
+<translation id="4176463684765177261">Uitgeschakeld</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Voeg je kaartgegevens en factuuradres toe aan je Google-account zodat je de volgende keer sneller kunt betalen.</translation>
<translation id="4196861286325780578">&amp;Opnieuw verplaatsen</translation>
@@ -619,6 +629,7 @@
<translation id="4277028893293644418">Wachtwoord opnieuw instellen</translation>
<translation id="4279811152705618813">Je <ph name="DEVICE_TYPE" /> wordt beheerd door <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Deze pas is opgeslagen in je Google-account}other{Deze passen zijn opgeslagen in je Google-account}}</translation>
+<translation id="428847186335018806">Scan de bestanden die je downloadt of uploadt in Chrome.</translation>
<translation id="42981349822642051">Uitvouwen</translation>
<translation id="4302965934281694568">Chou3 (envelop)</translation>
<translation id="4305817255990598646">Overschakelen</translation>
@@ -648,7 +659,6 @@
<translation id="4435702339979719576">Briefkaart</translation>
<translation id="443673843213245140">Het gebruik van een proxy is uitgeschakeld, maar er is wel een expliciete proxyconfiguratie opgegeven.</translation>
<translation id="445100540951337728">Geaccepteerde betaalpassen</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> verdacht gedrag</translation>
<translation id="4466881336512663640">Hiermee gaan formulierwijzigingen verloren. Weet je zeker dat je wilt doorgaan?</translation>
<translation id="4477350412780666475">Volgend nummer</translation>
<translation id="4482953324121162758">Deze site wordt niet vertaald.</translation>
@@ -675,6 +685,7 @@
<translation id="4594403342090139922">&amp;Verwijderen ongedaan maken</translation>
<translation id="4597348597567598915">Grootte 8</translation>
<translation id="4600854749408232102">C6/C5 (envelop)</translation>
+<translation id="464342062220857295">Zoekfuncties</translation>
<translation id="4646534391647090355">Breng me daar nu naartoe</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">De server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat van de server bevat fouten. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
@@ -683,7 +694,6 @@
<translation id="4691835149146451662">Architecture-A (envelop)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Je verbinding is onderbroken</translation>
-<translation id="471880041731876836">Je hebt geen toestemming om deze site te bezoeken</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Netwerkcontrole uitvoeren<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Beleid opnieuw laden</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -711,7 +721,6 @@
<translation id="4816492930507672669">Aanpassen aan pagina</translation>
<translation id="4850886885716139402">Weergave</translation>
<translation id="4854362297993841467">Deze bezorgingsmethode is niet beschikbaar. Kies een andere methode.</translation>
-<translation id="4858792381671956233">Je hebt je ouders gevraagd of je deze site mag bezoeken</translation>
<translation id="4864052566555297930">Veiligheidstip:</translation>
<translation id="4876188919622883022">Vereenvoudigde weergave</translation>
<translation id="4876305945144899064">Geen gebruikersnaam</translation>
@@ -735,7 +744,9 @@
<translation id="4974590756084640048">Waarschuwingen opnieuw inschakelen</translation>
<translation id="4984339528288761049">Prc5 (envelop)</translation>
<translation id="4989163558385430922">Alles weergeven</translation>
+<translation id="4989542687859782284">Niet beschikbaar</translation>
<translation id="4989809363548539747">Deze plug-in wordt niet ondersteund</translation>
+<translation id="4995216769782533993">Bevestig de beveiligingscode om je kaartgegevens met deze site te delen</translation>
<translation id="5002932099480077015">Indien ingeschakeld, slaat Chrome een kopie van je pas op dit apparaat op zodat formulieren sneller kunnen worden ingevuld.</translation>
<translation id="5015510746216210676">Naam apparaat:</translation>
<translation id="5017554619425969104">Tekst die je hebt gekopieerd</translation>
@@ -764,6 +775,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bits)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Je kaart verifiëren</translation>
<translation id="5135404736266831032">Adressen beheren...</translation>
<translation id="5138227688689900538">Minder weergeven</translation>
<translation id="5141240743006678641">Gesynchroniseerde wachtwoorden versleutelen met je Google-aanmeldingsgegevens</translation>
@@ -790,6 +802,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (envelop)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Functies die op het hele systeem van toepassing zijn, kunnen alleen worden ingesteld door de eigenaar: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Waarschuwing: Dit beleid is niet samengevoegd zoals gespecificeerd in het beleid PolicyListMultipleSourceMergeList, omdat het geen onderdeel is van het woordenboekbeleid dat kan worden samengevoegd.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Beëindigen</translation>
@@ -813,7 +826,6 @@
<translation id="536296301121032821">Opslaan van beleidsinstellingen is mislukt</translation>
<translation id="5371425731340848620">Pas updaten</translation>
<translation id="5377026284221673050">'Je klok loopt achter', 'Je klok loopt voor' of '&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;'</translation>
-<translation id="5377179979757081683">Deze pagina probeert je mogelijk te misleiden, persoonlijke informatie te stelen of je apparaat te beschadigen. Wees voorzichtig wanneer je persoonlijke informatie opgeeft of gedownloade bestanden opent.</translation>
<translation id="5384855140246857529">Als je je passen op alle apparaten wilt gebruiken, moet je inloggen en synchronisatie inschakelen.</translation>
<translation id="5386426401304769735">De certificaatketen voor deze site bevat een certificaat dat is ondertekend met SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -827,6 +839,7 @@
<translation id="5457113250005438886">Ongeldig</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> en nog <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> en nog <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Opnieuw bewerken</translation>
+<translation id="5473728911100096288">Als je deze functies inschakelt, gebruik je verouderde functies die in toekomstige versies gaan verdwijnen.</translation>
<translation id="5478437291406423475">B6/C4 (envelop)</translation>
<translation id="5481076368049295676">Deze content probeert mogelijk gevaarlijke software op je apparaat te installeren die je gegevens steelt of verwijdert. <ph name="BEGIN_LINK" />Toch weergeven<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Voeg een geldig adres toe</translation>
@@ -850,7 +863,6 @@
<translation id="5570825185877910964">Account beschermen</translation>
<translation id="5571083550517324815">Kan niet ophalen van dit adres. Selecteer een ander adres.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 in gebruik}other{# in gebruik}})</translation>
-<translation id="5572851009514199876">Start Chrome en log in zodat Chrome kan controleren of je deze site mag openen.</translation>
<translation id="5580958916614886209">Controleer de vervalmaand en probeer het opnieuw</translation>
<translation id="5586446728396275693">Geen opgeslagen adressen</translation>
<translation id="5595485650161345191">Adres bewerken</translation>
@@ -858,6 +870,7 @@
<translation id="560412284261940334">Beheer wordt niet ondersteund</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Deze site is mogelijk nep of bedrieglijk. Chrome raadt je aan de site direct te verlaten.</translation>
<translation id="5610142619324316209">Controleer de verbinding</translation>
<translation id="5610807607761827392">Je kunt passen en adressen beheren in <ph name="BEGIN_LINK" />Instellingen<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> heeft je te vaak omgeleid.</translation>
@@ -881,11 +894,11 @@
<translation id="5720705177508910913">Huidige gebruiker</translation>
<translation id="5728056243719941842">C5 (envelop)</translation>
<translation id="5730040223043577876">Chrome raadt je aan je wachtwoord opnieuw in te stellen als je het voor andere sites hebt hergebruikt.</translation>
-<translation id="5732392974455271431">Je ouders kunnen de blokkering van deze site opheffen</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Pas opslaan in je Google-account}other{Passen opslaan in je Google-account}}</translation>
<translation id="5763042198335101085">Geef een geldig e-mailadres op</translation>
<translation id="5765072501007116331">Selecteer een adres om bezorgingsmethoden en vereisten te bekijken</translation>
<translation id="5778550464785688721">Volledige controle voor MIDI-apparaten</translation>
+<translation id="5781136890105823427">Experiment ingeschakeld</translation>
<translation id="578305955206182703">Geelbruin</translation>
<translation id="57838592816432529">Dempen</translation>
<translation id="5784606427469807560">Er is een probleem opgetreden bij het bevestigen van je creditcard. Controleer je internetverbinding en probeer het opnieuw.</translation>
@@ -902,13 +915,16 @@
<translation id="5860033963881614850">Uit</translation>
<translation id="5863847714970149516">De komende pagina probeert misschien kosten in rekening te brengen</translation>
<translation id="5866257070973731571">Telefoonnummer toevoegen</translation>
+<translation id="5866898949289125849">Je bekijkt een Developer Tools-pagina</translation>
<translation id="5869405914158311789">Deze site is niet bereikbaar</translation>
<translation id="5869522115854928033">Opgeslagen wachtwoorden</translation>
<translation id="5887400589839399685">Pas opgeslagen</translation>
<translation id="5893752035575986141">Creditcards worden geaccepteerd.</translation>
+<translation id="5895138241574237353">Opnieuw starten</translation>
<translation id="5901630391730855834">Geel</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (gesynchroniseerd)</translation>
<translation id="5916664084637901428">Aan</translation>
+<translation id="59174027418879706">Ingeschakeld</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Pas opslaan in Google-account?</translation>
<translation id="5922853866070715753">Bijna klaar</translation>
@@ -942,6 +958,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Je passen gebruiken op al je apparaten?</translation>
<translation id="6059925163896151826">USB-apparaten</translation>
+<translation id="6060009363608157444">Ongeldige DnsOverHttps-modus.</translation>
<translation id="6080696365213338172">Je hebt toegang tot content gekregen met behulp van een certificaat van je beheerder. Gegevens die je verstrekt aan <ph name="DOMAIN" />, kunnen door je beheerder worden onderschept.</translation>
<translation id="6094273045989040137">Aantekeningen maken</translation>
<translation id="610911394827799129">Er kunnen andere vormen van browsegeschiedenis zijn opgeslagen voor je Google-account op <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -989,13 +1006,12 @@
<translation id="6404511346730675251">Bladwijzer bewerken</translation>
<translation id="6406765186087300643">C0 (envelop)</translation>
<translation id="6410264514553301377">Geef de vervaldatum en CVC-code op voor <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Je hebt je ouder of voogd gevraagd of je deze site mag bezoeken</translation>
<translation id="6415778972515849510">Chromium kan je helpen je Google-account te beschermen en je wachtwoord te wijzigen.</translation>
-<translation id="6417515091412812850">Kan niet controleren of het certificaat is ingetrokken.</translation>
<translation id="6431585503458005759">Niet opslaan</translation>
<translation id="6433490469411711332">Contactgegevens bewerken</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> heeft de verbinding geweigerd.</translation>
<translation id="6434309073475700221">Annuleren</translation>
+<translation id="6435221585574090192">Deel gegevens over beveiligingsgebeurtenissen die zijn gemarkeerd door Chrome Enterprise Threat Protection met je beheerder. Dit kunnen pagina-URL's, bestandsnamen, bestandsmetadata, de gebruikersnaam van je apparaat en je Chrome-gebruikersnaam zijn.</translation>
<translation id="6440503408713884761">Genegeerd</translation>
<translation id="6446163441502663861">Kahu (envelop)</translation>
<translation id="6446608382365791566">Meer informatie toevoegen</translation>
@@ -1004,20 +1020,19 @@
<translation id="6465306955648956876">Wachtwoorden beheren...</translation>
<translation id="647261751007945333">Apparaatbeleid</translation>
<translation id="6476284679642588870">Betaalmethoden beheren</translation>
-<translation id="6477321094435799029">Chrome heeft ongebruikelijke code op deze pagina gedetecteerd en heeft de code geblokkeerd om je persoonlijke informatie (zoals wachtwoorden, telefoonnummers en creditcards) te beschermen.</translation>
<translation id="6489534406876378309">Uploaden van crashes starten</translation>
<translation id="6499038740797743453">Wachtwoord opnieuw instellen?</translation>
<translation id="6507833130742554667">Creditcards en betaalpassen worden geaccepteerd.</translation>
<translation id="650855688985305916">Ja, opslaan</translation>
<translation id="6508722015517270189">Chrome opnieuw starten</translation>
<translation id="6517596291481585650">Waarschuwing: Dit beleid is niet samengevoegd als lijst zoals gespecificeerd door het beleid, omdat het geen lijst is.</translation>
+<translation id="6518133107902771759">Controleren</translation>
<translation id="6521745193039995384">Niet actief</translation>
<translation id="6529602333819889595">&amp;Opnieuw verwijderen</translation>
<translation id="6534179046333460208">Fysieke web-suggesties</translation>
<translation id="6545864417968258051">Bluetooth-scannen</translation>
<translation id="6554795675067793129">Je account wordt beheerd door <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Opnieuw</translation>
-<translation id="6563469144985748109">Je beheerder heeft dit nog niet goedgekeurd</translation>
<translation id="6569060085658103619">Je bekijkt een extensiepagina</translation>
<translation id="6578796323535178455">C2 (envelop)</translation>
<translation id="6579990219486187401">Lichtroze</translation>
@@ -1035,11 +1050,13 @@
<translation id="6643016212128521049">Wissen</translation>
<translation id="6644283850729428850">Dit beleid is verouderd.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Geen}=1{Van 1 site (je wordt niet uitgelogd bij je Google-account)}other{Van # sites (je wordt niet uitgelogd bij je Google-account)}}</translation>
+<translation id="6652101503459149953">Windows Hello gebruiken</translation>
<translation id="6657585470893396449">Wachtwoord</translation>
<translation id="6670613747977017428">Terug naar veilige pagina.</translation>
<translation id="6671697161687535275">Formuliersuggestie verwijderen uit Chromium?</translation>
<translation id="6685834062052613830">Uitloggen en configuratie voltooien</translation>
<translation id="6689271823431384964">Chrome biedt aan je kaarten in je Google-account op te slaan omdat je bent ingelogd. Je kunt dit wijzigen in de instellingen. De naam van de kaarthouder is afkomstig uit je account.</translation>
+<translation id="6707256370811247129">De content van het cachegeheugen en de bestanden die je downloadt of uploadt in Chrome scannen.</translation>
<translation id="6710213216561001401">Vorige</translation>
<translation id="6710594484020273272">&lt;Typ een zoekterm&gt;</translation>
<translation id="671076103358959139">Inschrijftoken:</translation>
@@ -1047,10 +1064,10 @@
<translation id="6738516213925468394">Je gegevens zijn op <ph name="TIME" /> versleuteld met je <ph name="BEGIN_LINK" />wachtwoordzin voor synchronisatie<ph name="END_LINK" />. Geef deze op om de synchronisatie te starten.</translation>
<translation id="674375294223700098">Onbekende fout met servercertificaat.</translation>
<translation id="6744009308914054259">Terwijl je op een verbinding wacht, kun je naar Downloads gaan om offline artikelen te lezen.</translation>
+<translation id="6747611005629681221">Waarschuwing: Hierna volgen verouderde functies</translation>
<translation id="6753269504797312559">Beleidswaarde</translation>
<translation id="6757797048963528358">De slaapstand van je apparaat is geactiveerd.</translation>
<translation id="6768213884286397650">Hagaki (briefkaart)</translation>
-<translation id="6778737459546443941">Je ouder of voogd heeft dit nog niet goedgekeurd</translation>
<translation id="67862343314499040">Violet</translation>
<translation id="6786747875388722282">Extensies</translation>
<translation id="6790428901817661496">Spelen</translation>
@@ -1058,6 +1075,7 @@
<translation id="681021252041861472">Verplicht veld</translation>
<translation id="6810899417690483278">Aanpassings-ID</translation>
<translation id="6825578344716086703">Je probeert <ph name="DOMAIN" /> te bereiken. De server heeft echter een certificaat geretourneerd dat een zwak ondertekeningsalgoritme (zoals SHA-1) gebruikt. Dit houdt in dat de betrouwbaarheidsverklaring van de server kan zijn vervalst. Het is mogelijk dat de server zelf een imitatie is (wellicht een server die je schade probeert te berokkenen).</translation>
+<translation id="6826370046007623921">Gegevensverlies voorkomen</translation>
<translation id="6831043979455480757">Vertalen</translation>
<translation id="6839929833149231406">Gebied</translation>
<translation id="6852204201400771460">App opnieuw laden?</translation>
@@ -1070,7 +1088,6 @@
<translation id="6891596781022320156">Beleidsniveau wordt niet ondersteund.</translation>
<translation id="6895330447102777224">Je creditcard is bevestigd</translation>
<translation id="6897140037006041989">User-agent</translation>
-<translation id="6903319715792422884">Help ons Safe Browsing beter te maken door bepaalde <ph name="BEGIN_WHITEPAPER_LINK" />systeeminformatie en paginacontent<ph name="END_WHITEPAPER_LINK" /> naar Google te verzenden. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Gebruiker:</translation>
<translation id="6934672428414710184">Dit is de naam die in je Google-account staat</translation>
<translation id="6944692733090228304">Je hebt je wachtwoord ingevoerd op een site die niet door <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> wordt beheerd. Ter bescherming van je account kun je je wachtwoord beter niet hergebruiken voor andere apps en sites.</translation>
@@ -1115,6 +1132,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> en nog <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> en nog <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavendel</translation>
<translation id="717330890047184534">Gaia-ID:</translation>
+<translation id="7174545416324379297">Samengevoegd</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> en nog <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> en nog <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">De server waar je naartoe gaat (<ph name="ORIGIN" />), heeft gevraagd om een beveiligingsbeleid toe te passen op alle verzoeken aan de server. De server heeft echter geen beleid geleverd, maar heeft de browser omgeleid naar een andere locatie. Hierdoor kan de browser je verzoek voor <ph name="SITE" /> niet uitvoeren.</translation>
<translation id="7179323680825933600">Betaalmethoden toevoegen en invullen</translation>
@@ -1149,6 +1167,7 @@ Aanvullende informatie:
<translation id="7320336641823683070">Hulp bij verbinding maken</translation>
<translation id="733354035281974745">Lokaal account op apparaat overschrijven</translation>
<translation id="7334320624316649418">&amp;Opnieuw volgorde wijzigen</translation>
+<translation id="7337706099755338005">Niet beschikbaar op je platform.</translation>
<translation id="733923710415886693">Het certificaat van de server is niet bekendgemaakt via Certificaattransparantie.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Is gelieerd:</translation>
@@ -1180,7 +1199,6 @@ Aanvullende informatie:
<translation id="7440140511386898319">Content bekijken wanneer je offline bent</translation>
<translation id="7441627299479586546">Onjuist beleidsonderwerp</translation>
<translation id="7442725080345379071">Lichtoranje</translation>
-<translation id="7444046173054089907">Deze site is geblokkeerd</translation>
<translation id="7445762425076701745">De identiteit van de server waarmee je verbinding maakt, kan niet volledig worden geverifieerd. Je hebt verbinding gemaakt met een server die een naam gebruikt die alleen binnen je netwerk geldig is. Een externe certificeringsinstantie kan hiervoor nooit het eigendom verifiëren. Aangezien sommige certificeringsinstanties toch certificaten voor deze namen verlenen, kun je nooit zeker weten of je verbinding hebt met de bedoelde website en niet met een aanvaller.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /> over dit probleem.</translation>
<translation id="7455133967321480974">Algemene standaardinstelling gebruiken (Blokkeren)</translation>
@@ -1202,9 +1220,9 @@ Aanvullende informatie:
<translation id="7538364083937897561">A2 (envelop)</translation>
<translation id="7542403920425041731">Zodra je bevestigt, worden je creditcardgegevens gedeeld met deze site.</translation>
<translation id="7542995811387359312">Het automatisch invullen van creditcardnummers is uitgeschakeld, omdat dit formulier geen beveiligde verbinding gebruikt.</translation>
-<translation id="7543525346216957623">Vraag het aan je ouder of voogd</translation>
<translation id="7548892272833184391">Verbindingsfouten oplossen</translation>
<translation id="7549584377607005141">Deze webpagina kan alleen correct worden weergegeven op basis van gegevens die je eerder hebt opgegeven. Je kunt deze gegevens opnieuw verzenden, maar hierdoor worden de acties herhaald die eerder op deze pagina zijn uitgevoerd.</translation>
+<translation id="7550637293666041147">De gebruikersnaam van je apparaat en je Chrome-gebruikersnaam</translation>
<translation id="7552846755917812628">Probeer de volgende tips:</translation>
<translation id="7554791636758816595">Nieuw tabblad</translation>
<translation id="7564049878696755256">Je kunt de toegang tot je account van <ph name="ORG_NAME" /> kwijtraken of slachtoffer worden van identiteitsdiefstal. Chrome raadt je aan je wachtwoord nu te wijzigen.</translation>
@@ -1219,6 +1237,7 @@ Aanvullende informatie:
<translation id="7610193165460212391">Waarde <ph name="VALUE" /> is buiten bereik.</translation>
<translation id="7613889955535752492">Vervaldatum: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Je hebt al gegevens die zijn gecodeerd met een andere versie van het wachtwoord voor je Google-account. Geef dit wachtwoord hieronder op.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Prestatiegegevens en crashrapporten</translation>
<translation id="7637571805876720304">Creditcard verwijderen uit Chromium?</translation>
<translation id="7638605456503525968">Seriële poorten</translation>
@@ -1231,7 +1250,6 @@ Aanvullende informatie:
<translation id="7668654391829183341">Onbekend apparaat</translation>
<translation id="7669271284792375604">Cybercriminelen op deze site proberen je mogelijk over te halen om programma's te installeren die schadelijk zijn voor de browsefunctionaliteit (door bijvoorbeeld je homepage te wijzigen of extra advertenties weer te geven op sites die je bezoekt).</translation>
<translation id="7676643023259824263">Zoeken naar klembordtekst, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platform en cloud</translation>
<translation id="7681101578153515023">Zoekmachine wijzigen</translation>
<translation id="7682287625158474539">Verzendadres</translation>
<translation id="7687186412095877299">Hiermee worden betalingsformulieren ingevuld met je opgeslagen betaalmethoden</translation>
@@ -1246,7 +1264,6 @@ Aanvullende informatie:
<translation id="7723047071702270851">Pas bewerken</translation>
<translation id="774634243536837715">Gevaarlijke content geblokkeerd.</translation>
<translation id="7752995774971033316">Niet-beheerd</translation>
-<translation id="7755287808199759310">Je ouder of voogd kan de blokkering van deze site opheffen</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">De verbinding is mogelijk geblokkeerd door de firewall of antivirussoftware.</translation>
<translation id="7759163816903619567">Weergegeven domein:</translation>
@@ -1290,7 +1307,6 @@ Aanvullende informatie:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Wachtwoorden beheren</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Deze pas en het bijbehorende factuuradres worden opgeslagen. Je kunt deze gegevens gebruiken wanneer je bent ingelogd op <ph name="USER_EMAIL" />.}other{Deze passen en de bijbehorende factuuradressen worden opgeslagen. Je kunt deze gegevens gebruiken wanneer je bent ingelogd op <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">We kunnen je ouders momenteel niet bereiken. Probeer het opnieuw.</translation>
<translation id="8025119109950072390">Cybercriminelen op deze site proberen je mogelijk te misleiden om iets gevaarlijks te doen, zoals software installeren of je persoonlijke informatie bekendmaken (bijvoorbeeld wachtwoorden, telefoonnummers of creditcards).</translation>
<translation id="8034522405403831421">Deze pagina is in het <ph name="SOURCE_LANGUAGE" />. Vertalen naar het <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pen</translation>
@@ -1301,6 +1317,7 @@ Aanvullende informatie:
<translation id="8041940743680923270">Algemene standaardinstelling gebruiken (Vragen)</translation>
<translation id="8042918947222776840">Ophaalmethode kiezen</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />' is niet correct geconfigureerd. Als je '<ph name="SOFTWARE_NAME" />' verwijdert, wordt het probleem meestal opgelost. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Je hoeft vanaf nu de beveiligingscode van de kaart niet meer op te geven</translation>
<translation id="8066955247577885446">Er is iets misgegaan.</translation>
<translation id="8074253406171541171">10x13 (envelop)</translation>
<translation id="8078141288243656252">Kan geen aantekeningen maken als het document is gedraaid</translation>
@@ -1331,6 +1348,7 @@ Aanvullende informatie:
<translation id="8211406090763984747">Verbinding is beveiligd</translation>
<translation id="8218327578424803826">Toegewezen locatie:</translation>
<translation id="8220146938470311105">C7/C6 (envelop)</translation>
+<translation id="8220639454292072926">Bedrijfsrapportage</translation>
<translation id="8225771182978767009">De persoon die deze computer heeft geconfigureerd, heeft deze site geblokkeerd.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Pagina openen op een nieuw incognitotabblad</translation>
@@ -1385,23 +1403,23 @@ Aanvullende informatie:
<translation id="8508648098325802031">Zoekpictogram</translation>
<translation id="8522552481199248698">Chrome kan je helpen je Google-account te beschermen en je wachtwoord te wijzigen.</translation>
<translation id="8543181531796978784">Je kunt <ph name="BEGIN_ERROR_LINK" />een detectieprobleem melden<ph name="END_ERROR_LINK" />. Als je de veiligheidsrisico's begrijpt, kun je ook <ph name="BEGIN_LINK" />deze onveilige site bezoeken<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Vragen? Neem contact op met de persoon die je profiel beheert.</translation>
<translation id="8553075262323480129">De vertaling is mislukt omdat de taal van de pagina niet kan worden bepaald.</translation>
<translation id="8557066899867184262">De CVC-code staat op de achterkant van je pas.</translation>
<translation id="8559762987265718583">Er kan geen privéverbinding met <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> tot stand worden gebracht, omdat de datum en tijd van je apparaat (<ph name="DATE_AND_TIME" />) onjuist zijn.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> verdachte site</translation>
<translation id="8564985650692024650">Chromium raadt je aan het wachtwoord voor <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> opnieuw in te stellen als je het voor andere sites hebt hergebruikt.</translation>
<translation id="8571890674111243710">Pagina wordt vertaald in het <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Telnr. toevoegen</translation>
-<translation id="859285277496340001">Er wordt in het certificaat geen methode gespecificeerd waarmee kan worden gecontroleerd of het certificaat is ingetrokken.</translation>
<translation id="860043288473659153">Naam kaarthouder</translation>
<translation id="861775596732816396">Grootte 4</translation>
-<translation id="8620436878122366504">Je ouders hebben dit nog niet goedgekeurd</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Deze pas opslaan op dit apparaat</translation>
<translation id="8626112503828625890">Factureringsgegevens opslaan in Google-account?</translation>
+<translation id="8647750283161643317">Alle standaardinstellingen herstellen</translation>
<translation id="8663226718884576429">Besteloverzicht, <ph name="TOTAL_LABEL" />, meer informatie</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, antwoord, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Beschikbaar</translation>
<translation id="8703575177326907206">Je verbinding met <ph name="DOMAIN" /> is niet gecodeerd.</translation>
<translation id="8718314106902482036">Betaling niet voltooid</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, zoeksuggestie</translation>
@@ -1412,6 +1430,7 @@ Aanvullende informatie:
<translation id="8738058698779197622">Als je een beveiligde verbinding tot stand wilt brengen, moet je klok goed zijn ingesteld. Dit moet omdat de certificaten die deze websites gebruiken om zichzelf te identificeren, slechts gedurende bepaalde perioden geldig zijn. Aangezien de klok van je apparaat niet goed is ingesteld, kan Chromium deze certificaten niet verifiëren.</translation>
<translation id="8740359287975076522">Het &lt;abbr id="dnsDefinition"&gt;DNS-adres&lt;/abbr&gt; van <ph name="HOST_NAME" /> kan niet worden gevonden. Er wordt een diagnose van het probleem uitgevoerd.</translation>
<translation id="874846938927089722">Geaccepteerde creditcards en prepaidkaarten</translation>
+<translation id="874918643257405732">Bladwijzer toevoegen voor dit tabblad</translation>
<translation id="8759274551635299824">Deze pas is verlopen</translation>
<translation id="8761567432415473239">Google Safe Browsing heeft onlangs <ph name="BEGIN_LINK" />schadelijke programma's gevonden<ph name="END_LINK" /> op <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB-apparaat</translation>
@@ -1441,6 +1460,7 @@ Aanvullende informatie:
<translation id="8938939909778640821">Geaccepteerde creditcards en prepaidkaarten</translation>
<translation id="8943282376843390568">Limoengroen</translation>
<translation id="8957210676456822347">Autorisatie van captive portal</translation>
+<translation id="8962950042226115166">Verdachte site</translation>
<translation id="8968766641738584599">Pas opslaan</translation>
<translation id="8971063699422889582">Het servercertificaat is verlopen.</translation>
<translation id="8975012916872825179">Inclusief informatie als telefoonnummers, e-mailadressen en verzendadressen</translation>
@@ -1463,24 +1483,24 @@ Aanvullende informatie:
<translation id="9035022520814077154">Beveiligingsfout</translation>
<translation id="9038649477754266430">Een voorspellingsservice gebruiken om pagina's sneller te laden</translation>
<translation id="9039213469156557790">Bovendien bevat deze pagina bronnen die niet beveiligd zijn. Deze bronnen kunnen tijdens verzending door anderen worden bekeken en kunnen door een aanvaller worden gewijzigd om het gedrag van de pagina aan te passen.</translation>
+<translation id="9044359186343685026">Touch ID gebruiken</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Je probeert <ph name="DOMAIN" /> te bereiken, maar de server heeft een ongeldig certificaat geretourneerd.</translation>
<translation id="9050666287014529139">Wachtwoordzin</translation>
<translation id="9065203028668620118">Bewerken</translation>
<translation id="9065745800631924235">Zoekopdracht <ph name="TEXT" /> in de geschiedenis</translation>
<translation id="9069693763241529744">Geblokkeerd door een extensie</translation>
-<translation id="9076283476770535406">De site kan content voor volwassenen bevatten</translation>
<translation id="9076630408993835509">Deze browser wordt niet beheerd door een bedrijf of andere organisatie. Activiteit op dit apparaat kan buiten Chrome worden beheerd. <ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Meer informatie vereist</translation>
<translation id="9080712759204168376">Besteloverzicht</translation>
<translation id="9089260154716455634">Beleid buiten gebruikstijd:</translation>
<translation id="9095388113577226029">Meer talen...</translation>
+<translation id="9098981495403789647">Je beheerder heeft Chrome Enterprise Threat Protection ingeschakeld in je browser. Chrome Enterprise Threat Protection heeft toegang tot sommige van je gegevens.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> gebruikt gewoonlijk versleuteling om je gegevens te beschermen. Toen Chromium deze keer probeerde verbinding te maken met <ph name="SITE" />, retourneerde de website ongewone en onjuiste inloggegevens. Dit gebeurt wanneer een aanvaller probeert zich als <ph name="SITE" /> voor te doen of wanneer een wifi-inlogscherm de verbinding heeft verbroken. Je gegevens zijn nog steeds beveiligd omdat Chromium de verbinding heeft beëindigd voordat er gegevens konden worden uitgewisseld.</translation>
<translation id="9106062320799175032">Factuuradres toevoegen</translation>
<translation id="9114524666733003316">Creditcard bevestigen...</translation>
<translation id="9128870381267983090">Verbinding maken met netwerk</translation>
<translation id="9137013805542155359">Origineel weergeven</translation>
-<translation id="9137248913990643158">Start Chrome en log in voordat je deze app gebruikt.</translation>
<translation id="9141013498910525015">Adressen beheren</translation>
<translation id="9148088599418889305">Verzendmethode kiezen</translation>
<translation id="9148507642005240123">&amp;Bewerken ongedaan maken</translation>
diff --git a/chromium/components/strings/components_strings_no.xtb b/chromium/components/strings/components_strings_no.xtb
index d16e3a8d4b7..6485befd1a0 100644
--- a/chromium/components/strings/components_strings_no.xtb
+++ b/chromium/components/strings/components_strings_no.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Legg til navnet på kortet</translation>
<translation id="1089439967362294234">Endre passord</translation>
+<translation id="1096545575934602868">Dette feltet skal ikke ha mer enn <ph name="MAX_ITEMS_LIMIT" /> oppføringer. Oppføringer utover dette blir forkastet.</translation>
<translation id="109743633954054152">Administrer passord i Chrome-innstillingene</translation>
<translation id="1103523840287552314">Oversett alltid <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Hvis det er merket av for dette alternativet, lagrer Chrome en kopi av kortet ditt på denne enheten, slik at det går raskere å fylle ut skjemaer.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Åpne en <ph name="BEGIN_LINK" />bufret kopi<ph name="END_LINK" /> av <ph name="URL" /></translation>
<translation id="1156303062776767266">Du ser en lokal eller delt fil</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> avsluttet tilkoblingen uventet.</translation>
+<translation id="115926840831309955">Kontrollér CVC-koden og prøv igjen, eller oppdater utløpsdatoen</translation>
<translation id="1161325031994447685">Koble til Wi-Fi på nytt</translation>
<translation id="1165039591588034296">Feil</translation>
<translation id="1175364870820465910">&amp;Skriv ut...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">«Det er programvare på datamaskinen din som hindrer Chrome i å koble trygt til Internett» (bare på Windows-datamaskiner)</translation>
<translation id="1294154142200295408">Variasjoner i kommandolinjen</translation>
<translation id="129553762522093515">Nylig lukket</translation>
+<translation id="1298536327547837046">Gjennomsøking etter skadelig programvare</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Prøv å slette informasjonskapslene dine<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Avviklede funksjoner</translation>
<translation id="1320233736580025032">Prc1 (konvolutt)</translation>
<translation id="132301787627749051">Søk etter bilde på utklippstavlen</translation>
<translation id="1323433172918577554">Vis mer</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Regneark</translation>
<translation id="1527263332363067270">Venter på tilkobling …</translation>
<translation id="1529521330346880926">10x15 (konvolutt)</translation>
+<translation id="1530707389502320859">Nettstedet du nettopp prøvde å besøke, ser falskt ut. Noen ganger etterligner angripere nettsteder ved å gjøre små endringer som er vanskelige å se, i nettadressen.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">På denne siden står det</translation>
<translation id="153384715582417236">Det var alt for denne gangen</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokumentet er for stort til å annoteres</translation>
-<translation id="1721312023322545264">Du trenger tillatelse fra <ph name="NAME" /> for å besøke dette nettstedet</translation>
<translation id="1721424275792716183">* Feltet er obligatorisk</translation>
<translation id="1727741090716970331">Legg til et gyldig kortnummer</translation>
<translation id="1728677426644403582">Du ser på kildekoden for en nettside</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Nettsteder du besøker, og hvor mye tid du bruker på dem</translation>
<translation id="1826516787628120939">Kontrollerer</translation>
<translation id="1834321415901700177">Dette nettstedet inneholder skadelige programmer</translation>
+<translation id="1838374766361614909">Fjern søket</translation>
<translation id="1839551713262164453">Validering av regelverdier mislyktes med feil</translation>
<translation id="1842969606798536927">Betal</translation>
<translation id="1871208020102129563">Mellomtjeneren er angitt til å bruke statiske proxytjenere, ikke en nettadresse med .pac-skript.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Skjul liste</translation>
<translation id="1898423065542865115">Filtrering</translation>
<translation id="1914326953223720820">Utpakkingstjeneste</translation>
+<translation id="1915697529809968049">Vil du bruke Touch ID i stedet for CVC?</translation>
<translation id="1916770123977586577">Last inn denne siden på nytt for å ta i bruk de oppdaterte innstillingene dine på dette nettstedet.</translation>
<translation id="1919345977826869612">Annonser</translation>
<translation id="1919367280705858090">Få hjelp med spesifikke feilmeldinger</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" />-bokmerker</translation>
<translation id="1973335181906896915">Serialiseringsfeil</translation>
<translation id="1974060860693918893">Avansert</translation>
+<translation id="1974883374937189061">Bidra til å gjøre sikkerheten i Chrome bedre ved å sende <ph name="BEGIN_WHITEPAPER_LINK" />nettadressene til noen av sidene du besøker, begrenset systeminformasjon og noe sideinnhold<ph name="END_WHITEPAPER_LINK" /> til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Fastvareversjon</translation>
<translation id="1981206234434200693">Tøm nettlesingsloggen i Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{og 1 til}other{og # til}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Angi et gyldig utløpsår</translation>
<translation id="2212735316055980242">Innstillingene ble ikke funnet</translation>
<translation id="2213606439339815911">Henter oppføringer …</translation>
+<translation id="2215727959747642672">Filredigering</translation>
<translation id="2218879909401188352">Angripere som er på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, kan installere farlige apper som skader enheten din, legge til skjulte belastninger på mobilregningen din eller stjele personopplysningene dine. <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Ingen nettilkobling</translation>
<translation id="2230458221926704099">Løs tilkoblingsproblemene med <ph name="BEGIN_LINK" />diagnostikkappen<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Send nå</translation>
+<translation id="2248949050832152960">Bruk WebAuthn</translation>
<translation id="225207911366869382">Denne verdien er foreldet for denne innstillingen.</translation>
<translation id="2257315177824333709">Beklager, men kortet kan ikke lagres akkurat nå</translation>
<translation id="2262243747453050782">HTTP-feil</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Ugyldig nettadresse for søk.</translation>
<translation id="2482878487686419369">Varsler</translation>
<translation id="248348093745724435">Maskininnstillinger</translation>
-<translation id="2485387744899240041">Brukernavn for enheten og nettleseren din</translation>
<translation id="2491120439723279231">Tjenerens sertifikat inneholder feil.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Parser</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Gå tilbake</translation>
<translation id="2503184589641749290">Godkjente debetkort og forhåndsbetalte kort</translation>
<translation id="2505268675989099013">Beskytt kontoen</translation>
+<translation id="2515335152965840738">IGNORER</translation>
<translation id="2515629240566999685">Sjekk signalet i området ditt</translation>
<translation id="2523886232349826891">Kun lagret på denne enheten</translation>
<translation id="2524461107774643265">Legg til mer informasjon</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Send</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Ingen}=1{1 passord (for <ph name="DOMAIN_LIST" />)}=2{2 passord (for <ph name="DOMAIN_LIST" />)}other{# passord (for <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Lukk andre faner eller apper</translation>
-<translation id="267371737713284912">trykk på <ph name="MODIFIER_KEY_DESCRIPTION" /> for å angre</translation>
<translation id="2674170444375937751">Er du sikker på at du vil slette disse sidene fra loggen?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Gå ut</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Verdien samsvarer ikke med formatet.</translation>
<translation id="2705137772291741111">Den lagrede (bufrede) kopien av dette nettstedet kunne ikke leses.</translation>
<translation id="2709516037105925701">Autofyll</translation>
-<translation id="2712173769900027643">Be om tillatelse</translation>
<translation id="2713444072780614174">Hvit</translation>
<translation id="2720342946869265578">Like ved</translation>
<translation id="2721148159707890343">Forespørselen var vellykket</translation>
<translation id="2728127805433021124">Tjenerens sertifikat er signert med en usikker signaturalgoritme.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Kjør Tilkoblingsdiagnostikk<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Hvis du slår på disse funksjonene, kan du miste nettlesingsdata eller
+sette sikkerheten eller personvernet på spill. Funksjoner som er slått på, gjelder for alle
+brukere av denne nettleseren.</translation>
<translation id="2735043616039983645">Denne regelen har mer enn én kilde med motstridende verdier.</translation>
<translation id="2738330467931008676">Velg henteadresse</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Tilkoblingen ble tilbakestilt.</translation>
<translation id="2788784517760473862">Godkjente kredittkort</translation>
<translation id="2792012897584536778">Enhetsadministratorene har satt opp sikkerhetssertifikater som kan gjøre det mulig for dem å se innholdet på nettsteder du besøker.</translation>
-<translation id="2794233252405721443">Nettstedet er blokkert</translation>
<translation id="2799020568854403057">Nettstedet du er på vei til, inneholder skadelige apper</translation>
<translation id="2799223571221894425">Start på nytt</translation>
<translation id="2803306138276472711">Google Safe Browsing oppdaget nylig <ph name="BEGIN_LINK" />skadelig programvare<ph name="END_LINK" /> på <ph name="SITE" />. Nettsteder som vanligvis er sikre, kan noen ganger være infisert av skadelig programvare.</translation>
+<translation id="2815364696811431560">FORLAT NETTSTEDET</translation>
<translation id="2824775600643448204">Adresse- og søkefelt</translation>
<translation id="2826760142808435982">Tilkoblingen er kryptert ved hjelp av <ph name="CIPHER" />, og bruker <ph name="KX" /> som mekanisme for nøkkelutveksling.</translation>
<translation id="2835170189407361413">Slett skjemaet</translation>
<translation id="2847118875340931228">Åpne et inkognitovindu</translation>
<translation id="2850739647070081192">Invite (konvolutt)</translation>
-<translation id="2851634818064021665">Du trenger tillatelse for å besøke dette nettstedet</translation>
<translation id="2856444702002559011">Det kan hende at angripere prøver å stjele informasjonen din fra <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (for eksempel passord, meldinger og kredittkortinformasjon). <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Vil du lagre kortet?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Hvis du slår på dette alternativet, lagrer Chromium en kopi av kortet ditt på denne enheten, slik at det går raskere å fylle ut skjemaer.</translation>
<translation id="2985398929374701810">Angi en gyldig adresse</translation>
<translation id="2986368408720340940">Denne hentemetoden er ikke tilgjengelig. Prøv en annen metode.</translation>
+<translation id="2987034854559945715">Ingen samsvarende funksjoner</translation>
<translation id="2991174974383378012">Deling med nettsteder</translation>
<translation id="2991571918955627853">Du kan ikke gå til <ph name="SITE" /> akkurat nå, siden nettstedet bruker HSTS. Nettverksfeil og -angrep er vanligvis midlertidige, så denne siden fungerer sannsynligvis senere.</translation>
<translation id="3005723025932146533">Vis lagret kopi</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Feil type enhetsinnstillinger</translation>
<translation id="3037605927509011580">Æsj!</translation>
<translation id="3041612393474885105">Sertifikatinformasjon</translation>
+<translation id="3057676462092457419">DnsOverHttps-modusen <ph name="SECURE_DNS_MODE_SECURE" /> støttes ikke ennå. Modusen er satt til <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (konvolutt)</translation>
<translation id="3061707000357573562">Feilrettingstjeneste</translation>
<translation id="3064966200440839136">Går ut av inkognitomodus for å betale via en ekstern app. Vil du fortsette?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> på <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Avbryt betalingen</translation>
<translation id="3207960819495026254">Bokmerket</translation>
+<translation id="3209034400446768650">Siden kan belaste deg for penger</translation>
<translation id="3225919329040284222">Tjeneren oppga et sertifikat som ikke samsvarte med innebygde forventninger. Disse forventningene benyttes for visse nettsteder med høy sikkerhet, og brukes for å beskytte deg.</translation>
<translation id="3226128629678568754">Trykk på knappen for å laste inn på nytt, for å sende inn dataene som trengs for å laste inn siden på nytt.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Versjonsinformasjon om enheten og nettleseren din</translation>
<translation id="323107829343500871">Skriv inn verifiseringskoden for <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Oppdag alltid viktig innhold på dette nettstedet</translation>
-<translation id="3254409185687681395">Legg til bokmerke for denne siden</translation>
<translation id="3270847123878663523">&amp;Angre omorganiseringen</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Legg til navnet på kortet</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Legg til faktureringsadresse</translation>
<translation id="3324983252691184275">Karmosinrød</translation>
<translation id="3338095232262050444">Sikker</translation>
-<translation id="3345135638360864351">Forespørselen om tilgang til dette nettstedet kunne ikke sendes til <ph name="NAME" />. Prøv igjen.</translation>
<translation id="3355823806454867987">Endre innstillinger for mellomtjener</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />lagrer ikke<ph name="END_EMPHASIS" />
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Skjul detaljer</translation>
<translation id="3467763166455606212">Kortinnhaverens navn er obligatorisk</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> – for øyeblikket åpen. Trykk på Tab og deretter Enter for å bytte til den åpne fanen</translation>
-<translation id="3479539252931486093">Var dette uventet? <ph name="BEGIN_LINK" />Si fra til oss<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ikke nå</translation>
<translation id="3484560055331845446">Du kan miste tilgangen til Google-kontoen din. Chrome anbefaler at du endrer passordet ditt nå. Du blir bedt om å logge på.</translation>
<translation id="3495081129428749620">Finn på siden
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Vi kunne ikke nå foreldrene dine akkurat nå. Prøv igjen.</translation>
<translation id="3512163584740124171">Denne regelen ignoreres fordi en annen regel i den samme regelgruppen har høyere prioritet.</translation>
<translation id="3528171143076753409">Tjenerens sertifikat er ikke pålitelig.</translation>
<translation id="3528485271872257980">Mørk brun</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Minst 1 element på synkroniserte enheter}=1{1 element (og flere på synkroniserte enheter)}other{# elementer (og flere på synkroniserte enheter)}}</translation>
<translation id="3539171420378717834">Lagre en kopi av dette kortet på denne enheten</translation>
-<translation id="3556433843310711081">Administratoren din kan oppheve blokkeringen for deg</translation>
<translation id="3566021033012934673">Tilkoblingen din er ikke privat</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" />, <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">På en innebygd side på <ph name="SITE" /> står det</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Åpne siden i et nytt inkognitovindu (Ctrl + Shift + N)</translation>
<translation id="3679803492151881375">Programstopprapport generert <ph name="CRASH_TIME" /> og lastet opp <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Sertifikatinformasjon</translation>
+<translation id="3701427423622901115">Tilbakestillingen er godtatt.</translation>
<translation id="3704162925118123524">Det kan hende at det er et krav for nettverket du bruker, at du besøker påloggingssiden for nettverket.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Laster inn ...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Angripere på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan lure deg til å gjøre farlige ting, deriblant å installere programvare eller oppgi personopplysninger (for eksempel passord, telefonnumre og kredittkortinformasjon). <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Oversettelsen mislyktes på grunn av en tjenerfeil.</translation>
<translation id="3759461132968374835">Du har ingen nylig rapportert programstopp. Programstopp som inntraff når rapportering om programstopp var deaktivert, blir ikke vist her.</translation>
+<translation id="3760561303380396507">Vil du bruke Windows Hello i stedet for CVC?</translation>
<translation id="3761718714832595332">Skjul statusen</translation>
<translation id="3765032636089507299">Safe Browsing-siden er under utvikling.</translation>
<translation id="3778403066972421603">Vil du lagre dette kortet i Google-kontoen din og på denne enheten?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Størrelse 16</translation>
<translation id="3797522431967816232">Prc3 (konvolutt)</translation>
<translation id="3807873520724684969">Skadelig innhold er blokkert.</translation>
+<translation id="3808375843007691220">Advarsel: eksperimentelle funksjoner!</translation>
<translation id="3810973564298564668">Administrer</translation>
<translation id="382518646247711829">Hvis du bruker en mellomtjener...</translation>
<translation id="3828924085048779000">Tom passordfrase er ikke tillatt.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Oppdater dato og klokkeslett</translation>
<translation id="3884278016824448484">Motstridende enhetsidentifikator</translation>
<translation id="3885155851504623709">Sogn</translation>
-<translation id="3886446263141354045">Forespørselen din om å få tilgang til dette nettstedet er sendt til <ph name="NAME" /></translation>
<translation id="3890664840433101773">Legg til e-post</translation>
<translation id="3901925938762663762">Kortet er utløpt</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Vil du bruke WebAuthn i stedet for CVC?</translation>
<translation id="3946209740501886391">Spør alltid på dette nettstedet</translation>
<translation id="3949571496842715403">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Det er ikke angitt noen alternative emnenavn i tjenerens sikkerhetssertifikat. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
<translation id="3949601375789751990">Nettleserloggen din vises her</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ingen}=1{Fra 1 nettsted }other{Fra # nettsteder }}</translation>
<translation id="397105322502079400">Beregner …</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> er blokkert</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> har slått på beskyttelsesfunksjoner for bedrifter i Chrome-nettleseren din. Beskyttelsesfunksjoner for bedrifter i Chrome har tilgang til noen av dataene dine.</translation>
<translation id="3987940399970879459">Under 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 Like ved-nettside}other{# Like ved-nettsider}}</translation>
<translation id="4030383055268325496">&amp;Angre tilleggingen</translation>
<translation id="4032320456957708163">Nettleseren din administreres av <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Linken du åpnet, tar deg til et nettsted du ikke vanligvis besøker. Det kan hende linken prøver å forvirre deg.</translation>
<translation id="4058922952496707368">Nøkkel – «<ph name="SUBKEY" />»: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (konvolutt)</translation>
<translation id="4067947977115446013">Du må angi en gyldig adresse</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Enhetens serienummer er ugyldig</translation>
<translation id="410351446219883937">Autoavspilling</translation>
<translation id="4103763322291513355">Gå til &lt;strong&gt;chrome://policy&lt;/strong&gt; for å se listen over sperrede nettadresser og andre innstillinger aktivert av systemadministratoren din.</translation>
+<translation id="4108231218301530806">Bruk fingeravtrykk til å bekrefte dette kortet neste gang.</translation>
<translation id="4110652170750985508">Gjennomgå betalingen</translation>
<translation id="4112140312785995938">Spol bakover</translation>
<translation id="4116663294526079822">Tillat alltid på dette nettstedet</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Ugyldig bekreftelsessignatur</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> element til}other{<ph name="ITEM_COUNT" /> elementer til}}</translation>
+<translation id="4176463684765177261">Deaktivert</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">For å betale raskere neste gang, legg til kortet og faktureringsadressen i Google-kontoen din.</translation>
<translation id="4196861286325780578">&amp;Flytt likevel</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Tilbakestill passordet</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> administreres av <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Dette kortet er lagret i Google-kontoen din}other{Disse kortene er lagret i Google-kontoen din}}</translation>
+<translation id="428847186335018806">Gjennomsøk filer du laster ned eller opp i Chrome.</translation>
<translation id="42981349822642051">Vis</translation>
<translation id="4302965934281694568">Chou3 (konvolutt)</translation>
<translation id="4305817255990598646">Bytt</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">postkort)</translation>
<translation id="443673843213245140">Bruk av mellomtjener er deaktivert, men det er angitt en uttrykkelig mellomtjenerkonfigurasjon.</translation>
<translation id="445100540951337728">Godkjente debetkort</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> – mistenkelig atferd</translation>
<translation id="4466881336512663640">Endringer i skjemaet går tapt. Er du sikker på at du vil fortsette?</translation>
<translation id="4477350412780666475">Neste spor</translation>
<translation id="4482953324121162758">Dette nettstedet oversettes ikke.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Angre slettingen</translation>
<translation id="4597348597567598915">Størrelse 8</translation>
<translation id="4600854749408232102">C6/C5 (konvolutt)</translation>
+<translation id="464342062220857295">Søkefunksjoner</translation>
<translation id="4646534391647090355">Gå dit nå</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Sikkerhetssertifikatet til tjeneren inneholder feil. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (konvolutt)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Tilkoblingen ble avbrutt</translation>
-<translation id="471880041731876836">Du har ikke tillatelse til å besøke dette nettstedet</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Kjør Windows Nettverksdiagnose<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Last inn retningslinjer på nytt</translation>
<translation id="4728558894243024398">Plattform</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Tilpass til siden</translation>
<translation id="4850886885716139402">Visning</translation>
<translation id="4854362297993841467">Denne leveringsmetoden er ikke tilgjengelig. Prøv en annen metode.</translation>
-<translation id="4858792381671956233">Du har spurt foreldrene dine om det er greit å besøke dette nettstedet</translation>
<translation id="4864052566555297930">Sikkerhetstips:</translation>
<translation id="4876188919622883022">Forenklet visning</translation>
<translation id="4876305945144899064">Uten brukernavn</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Slå på advarsler på nytt</translation>
<translation id="4984339528288761049">Prc5 (konvolutt)</translation>
<translation id="4989163558385430922">Se alle</translation>
+<translation id="4989542687859782284">Utilgjengelig</translation>
<translation id="4989809363548539747">Dette programtillegget støttes ikke</translation>
+<translation id="4995216769782533993">Bekreft sikkerhetskoden for å dele kortopplysningene dine med dette nettstedet</translation>
<translation id="5002932099480077015">Hvis du slår på dette alternativet, lagrer Chrome en kopi av kortet ditt på denne enheten, slik at det blir raskere å fylle ut skjemaer i fremtiden.</translation>
<translation id="5015510746216210676">Maskinnavn:</translation>
<translation id="5017554619425969104">Teksten du kopierte</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Bekreft kortet ditt</translation>
<translation id="5135404736266831032">Adminstrer adresser…</translation>
<translation id="5138227688689900538">Vis færre</translation>
<translation id="5141240743006678641">Kryptér synkroniserte passord med Google-legitimasjonen din</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Nettsky</translation>
<translation id="5252000469029418751">C7 (konvolutt)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funksjoner som gjelder for hele systemet, kan bare angis av eieren: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Advarsel: Denne regelen ble ikke sammenslått som angitt i PolicyDictionaryMultipleSourceMergeList-regelen fordi den ikke er en del av ordlistereglene som kan slås sammen.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Avslutt</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Kunne ikke lagre angivelsen for enhetsinnstillinger</translation>
<translation id="5371425731340848620">Oppdater kortet</translation>
<translation id="5377026284221673050">«Klokken går for sent», «Klokken går for fort» eller «&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;»</translation>
-<translation id="5377179979757081683">Denne siden kan prøve å lure deg, stjele personopplysninger eller skade enheten din. Vær forsiktig når du oppgir personopplysninger eller åpner filer du har lastet ned.</translation>
<translation id="5384855140246857529">For å bruke kortene dine på alle enheter, logg på og slå på synkronisering.</translation>
<translation id="5386426401304769735">Sertifikatkjeden for dette nettstedet inneholder et sertifikat som er signert med SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Ugyldig</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> til}other{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> til}}</translation>
<translation id="5470861586879999274">&amp;Endre likevel</translation>
+<translation id="5473728911100096288">Hvis du slår på disse funksjonene, tar du i bruk avviklede funksjoner
+ som kommer til å forsvinne i fremtidige versjoner.</translation>
<translation id="5478437291406423475">B6/C4 (konvolutt)</translation>
<translation id="5481076368049295676">Dette innholdet kan prøve å installere farlig programvare som stjeler eller sletter informasjon, på enheten din. <ph name="BEGIN_LINK" />Vis det likevel<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Du må angi en gyldig adresse</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Beskytt kontoen</translation>
<translation id="5571083550517324815">Kan ikke hente på denne adressen. Velg en annen adresse.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 er i bruk}other{# er i bruk}})</translation>
-<translation id="5572851009514199876">Start og logg på Chrome, så Chrome kan sjekke om du har tillatelse til å gå til dette nettstedet.</translation>
<translation id="5580958916614886209">Kontrollér utløpsmåneden, og prøv igjen</translation>
<translation id="5586446728396275693">Ingen adresser er lagret</translation>
<translation id="5595485650161345191">Rediger adresse</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Administrering støttes ikke</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Dette nettstedet kan være falskt eller prøve å svindle deg. Chrome anbefaler at du forlater det nå.</translation>
<translation id="5610142619324316209">Sjekk tilkoblingen</translation>
<translation id="5610807607761827392">Du kan administrere kort og adresser i <ph name="BEGIN_LINK" />Innstillinger<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> viderekoblet deg for mange ganger.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Gjeldende bruker</translation>
<translation id="5728056243719941842">C5 (konvolutt)</translation>
<translation id="5730040223043577876">Chrome anbefaler at du tilbakestiller passordet ditt hvis du også har brukt det på andre nettsteder.</translation>
-<translation id="5732392974455271431">Foreldrene dine kan oppheve blokkeringen for deg</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Lagre kort i Google-kontoen din}other{Lagre kort i Google-kontoen din}}</translation>
<translation id="5763042198335101085">Angi en gyldig e-postadresse</translation>
<translation id="5765072501007116331">For å se leveringsmetoder og -krav, velg en adresse</translation>
<translation id="5778550464785688721">Full kontroll av MIDI-enheter</translation>
+<translation id="5781136890105823427">Et eksperiment er slått på</translation>
<translation id="578305955206182703">Ravgul</translation>
<translation id="57838592816432529">Kutt lyden</translation>
<translation id="5784606427469807560">Det oppsto et problem under forsøket på å bekrefte kortet ditt. Kontrollér Internett-tilkoblingen din, og prøv igjen.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Av</translation>
<translation id="5863847714970149516">Den neste siden kan prøve å belaste deg for penger</translation>
<translation id="5866257070973731571">Legg til telefonnummer</translation>
+<translation id="5866898949289125849">Du ser på en side for utviklerverktøy</translation>
<translation id="5869405914158311789">Dette nettstedet er ikke tilgjengelig</translation>
<translation id="5869522115854928033">Lagrede passord</translation>
<translation id="5887400589839399685">Kortet er lagret</translation>
<translation id="5893752035575986141">Kredittkort godtas.</translation>
+<translation id="5895138241574237353">Start på nytt</translation>
<translation id="5901630391730855834">Gul</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkronisert)</translation>
<translation id="5916664084637901428">På</translation>
+<translation id="59174027418879706">Aktivert</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Vil du lagre kortet i Google-kontoen?</translation>
<translation id="5922853866070715753">Nesten ferdig</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Vil du bruke kortene på alle enhetene dine?</translation>
<translation id="6059925163896151826">USB-enheter</translation>
+<translation id="6060009363608157444">Ugyldig DnsOverHttps-modus.</translation>
<translation id="6080696365213338172">Du har åpnet innhold via et administratorlevert sertifikat. Data du sender til <ph name="DOMAIN" /> kan stoppes av administratoren din.</translation>
<translation id="6094273045989040137">Annoter</translation>
<translation id="610911394827799129">Det kan hende Google-kontoen din har andre typer nettleserlogger på <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Rediger bokmerket</translation>
<translation id="6406765186087300643">C0 (konvolutt)</translation>
<translation id="6410264514553301377">Skriv inn utløpsdatoen og verifiseringskoden for <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Du har spurt forelderen din om det er greit å besøke dette nettstedet</translation>
<translation id="6415778972515849510">Chromium kan hjelpe deg med å beskytte Google-kontoen din og endre passordet ditt.</translation>
-<translation id="6417515091412812850">Kan ikke kontrollere hvorvidt sertifikatet har blitt tilbakekalt.</translation>
<translation id="6431585503458005759">Ikke lagre</translation>
<translation id="6433490469411711332">Endre kontaktinformasjonen</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> avviste tilkoblingsforsøket.</translation>
<translation id="6434309073475700221">Forkast</translation>
+<translation id="6435221585574090192">Del data om sikkerhetshendelser som er rapportert av beskyttelsesfunksjoner for bedrifter i Chrome, med administratoren din. Dette kan inkludere nettadresser, filnavn eller -metadata samt brukernavnet ditt på enheten og i Chrome.</translation>
<translation id="6440503408713884761">Ignorert</translation>
<translation id="6446163441502663861">Kahu (konvolutt)</translation>
<translation id="6446608382365791566">Legg til mer informasjon</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Administrer passord…</translation>
<translation id="647261751007945333">Enhetsinnstillinger</translation>
<translation id="6476284679642588870">Administrer betalingsmåter</translation>
-<translation id="6477321094435799029">Chrome har oppdaget uvanlig kode på denne siden og blokkert den for å beskytte personopplysningene dine (for eksempel passord, telefonnumre og kredittkortinformasjon).</translation>
<translation id="6489534406876378309">Start opplastingen av krasj</translation>
<translation id="6499038740797743453">Vil du tilbakestille passordet?</translation>
<translation id="6507833130742554667">Kreditt- og debetkort godtas.</translation>
<translation id="650855688985305916">Ja, lagre</translation>
<translation id="6508722015517270189">Start Chrome på nytt</translation>
<translation id="6517596291481585650">Advarsel: Denne regelen ble ikke sammenslått som en regelspesifisert liste fordi den ikke er en liste.</translation>
+<translation id="6518133107902771759">Bekreft</translation>
<translation id="6521745193039995384">Ikke aktiv</translation>
<translation id="6529602333819889595">&amp;Slett likevel</translation>
<translation id="6534179046333460208">Fysisk nett-forslag</translation>
<translation id="6545864417968258051">Bluetooth-skanning</translation>
<translation id="6554795675067793129">Kontoen din administreres av <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Gjør om</translation>
-<translation id="6563469144985748109">Administratoren din har ikke godkjent det ennå</translation>
<translation id="6569060085658103619">Du ser på en utvidelsesside</translation>
<translation id="6578796323535178455">C2 (konvolutt)</translation>
<translation id="6579990219486187401">Lys rosa</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Tøm</translation>
<translation id="6644283850729428850">Denne retningslinjen er foreldet.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Ingen}=1{Fra 1 nettsted (du blir ikke logget av Google-kontoen din)}other{Fra # nettsteder (du blir ikke logget av Google-kontoen din)}}</translation>
+<translation id="6652101503459149953">Bruk Windows Hello</translation>
<translation id="6657585470893396449">Passord</translation>
<translation id="6670613747977017428">Tilbake til trygg grunn.</translation>
<translation id="6671697161687535275">Vil du fjerne forslaget fra Chromium?</translation>
<translation id="6685834062052613830">Logg av og fullfør konfigurasjonen</translation>
<translation id="6689271823431384964">Chrome tilbyr å lagre kort i Google-kontoen din fordi du er logget på. Du kan endre dette i innstillingene. Kortinnehaverens navn kommer fra kontoen din.</translation>
+<translation id="6707256370811247129">Gjennomsøk innholdet i bufferen og filene du laster ned eller opp i Chrome.</translation>
<translation id="6710213216561001401">Forrige</translation>
<translation id="6710594484020273272">&lt;Skriv inn en søketerm&gt;</translation>
<translation id="671076103358959139">Registreringstoken:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Dataene dine ble kryptert med <ph name="BEGIN_LINK" />passordfrasen for synkronisering<ph name="END_LINK" /> <ph name="TIME" />. Skriv den inn for å starte synkroniseringen.</translation>
<translation id="674375294223700098">Ukjent feil med tjenersertifikat.</translation>
<translation id="6744009308914054259">Mens du venter på å koble til, kan du gå til Nedlastinger for å lese artikler uten nett.</translation>
+<translation id="6747611005629681221">Advarsel: avviklede funksjoner!</translation>
<translation id="6753269504797312559">Retningslinjeverdi</translation>
<translation id="6757797048963528358">Enheten din gikk inn i hvilemodus.</translation>
<translation id="6768213884286397650">Hagaki (postkort)</translation>
-<translation id="6778737459546443941">Forelderen din har ikke godkjent det ennå</translation>
<translation id="67862343314499040">Fiolett</translation>
<translation id="6786747875388722282">Utvidelser</translation>
<translation id="6790428901817661496">Spill av</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Obligatorisk felt</translation>
<translation id="6810899417690483278">Tilpasnings-ID</translation>
<translation id="6825578344716086703">Du prøvde å gå til <ph name="DOMAIN" />, men tjeneren presenterte et sertifikat som er signert med en svak signaturalgoritme (for eksempel SHA-1). Dette betyr at sikkerhetslegitimasjonen tjeneren presenterte, kan være forfalsket. Tjeneren kan med andre ord være en annen tjener enn du tror (og du kommuniserer kanskje med en angriper).</translation>
+<translation id="6826370046007623921">Forebygging av datatap</translation>
<translation id="6831043979455480757">Oversett</translation>
<translation id="6839929833149231406">Område</translation>
<translation id="6852204201400771460">Vil du laste inn appen på nytt?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Innstillingsnivået støttes ikke.</translation>
<translation id="6895330447102777224">Kortet ditt er bekreftet</translation>
<translation id="6897140037006041989">Brukeragent</translation>
-<translation id="6903319715792422884">Bidra til å gjøre Safe Browsing bedre ved å sende noe <ph name="BEGIN_WHITEPAPER_LINK" />systeminformasjon og sideinnhold<ph name="END_WHITEPAPER_LINK" /> til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Bruker:</translation>
<translation id="6934672428414710184">Dette navnet er fra Google-kontoen din</translation>
<translation id="6944692733090228304">Du har skrevet inn passordet ditt på et nettsted som ikke administreres av <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. For å beskytte kontoen din må du ikke bruke det samme passordet i andre apper eller på andre nettsteder.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> til}other{<ph name="PAYMENT_METHOD_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> til}}</translation>
<translation id="7153618581592392745">Lavendel</translation>
<translation id="717330890047184534">Gaia-ID:</translation>
+<translation id="7174545416324379297">Slått sammen</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> til}other{<ph name="SHIPPING_OPTION_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> til}}</translation>
<translation id="7177397715882417099">Tjeneren du er på vei til (<ph name="ORIGIN" />), har bedt om at
en sikkerhetsregel brukes for alle forespørsler som sendes til den. Men i stedet for
@@ -1165,6 +1186,7 @@
<translation id="7320336641823683070">Tilkoblingshjelp</translation>
<translation id="733354035281974745">Overstyrt av lokal konto på enheten</translation>
<translation id="7334320624316649418">&amp;Omorganiser likevel</translation>
+<translation id="7337706099755338005">Ikke tilgjengelig på plattformen din.</translation>
<translation id="733923710415886693">Tjenerens sertifikat er ikke vist i henhold til regelen for sertifikatåpenhet.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Er tilknyttet:</translation>
@@ -1196,7 +1218,6 @@
<translation id="7440140511386898319">Utforsk uten nett</translation>
<translation id="7441627299479586546">Feil emne for innstillinger</translation>
<translation id="7442725080345379071">Lys oransje</translation>
-<translation id="7444046173054089907">Dette nettstedet er blokkert</translation>
<translation id="7445762425076701745">Identiteten til tjernen du er tilkoblet kan ikke valideres. Du er tilkoblet en tjener som bruker et navn som kun er gyldig i ditt nettverk, som en ekstern sertifiseringsinstans ikke har noen mulighet til å validere eierskap for. Siden enkelte sertifiseringsinstanser likevel utsteder sertifikater for disse navnene, er det umulig å sikre at du er tilkoblet ønsket nettsted og ikke en angriper.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Finn ut mer<ph name="END_LINK" /> om dette problemet.</translation>
<translation id="7455133967321480974">Bruk global standardinnstilling (Blokkér)</translation>
@@ -1218,9 +1239,9 @@
<translation id="7538364083937897561">A2 (konvolutt)</translation>
<translation id="7542403920425041731">Når du bekrefter, deles kortinformasjonen din med dette nettstedet.</translation>
<translation id="7542995811387359312">Automatisk utfylling av kredittkort er deaktivert fordi dette skjemaet ikke bruker en sikker tilkobling.</translation>
-<translation id="7543525346216957623">Spør forelderen din</translation>
<translation id="7548892272833184391">Fiks tilkoblingsfeil</translation>
<translation id="7549584377607005141">Denne nettsiden krever data som du har skrevet inn tidligere for å vises korrekt. Du kan sende inn dataene på nytt, men hvis du gjør det, gjentas eventuelle handlinger denne siden utførte.</translation>
+<translation id="7550637293666041147">Brukernavnet ditt på enheten og i Chrome</translation>
<translation id="7552846755917812628">Prøv følgende tips:</translation>
<translation id="7554791636758816595">Ny fane</translation>
<translation id="7564049878696755256">Du kan miste tilgangen til <ph name="ORG_NAME" />-kontoen din eller bli utsatt for identitetstyveri. Chrome anbefaler at du endrer passordet ditt nå.</translation>
@@ -1235,6 +1256,7 @@
<translation id="7610193165460212391">Verdien er utenfor rekkevidden <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Utløpsdato: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Du har allerede data som er kryptert med en annen versjon av Google-kontopassordet ditt. Skriv det inn nedenfor.</translation>
+<translation id="7625784245512586808">Beskyttelsesfunksjoner for bedrifter i Chrome</translation>
<translation id="7633909222644580952">Ytelsesdata og programstopprapporter</translation>
<translation id="7637571805876720304">Vil du fjerne kredittkortet fra Chromium?</translation>
<translation id="7638605456503525968">Serielle porter</translation>
@@ -1247,7 +1269,6 @@
<translation id="7668654391829183341">Ukjent enhet</translation>
<translation id="7669271284792375604">Angripere på dette nettstedet kan forsøke å lure deg til å installere programmer som ødelegger surfeopplevelsen din (for eksempel ved å endre startsiden din eller vise ekstra annonser på nettstedene du besøker).</translation>
<translation id="7676643023259824263">Søk etter teksten <ph name="TEXT" /> på utklippstavlen</translation>
-<translation id="7679176406634891508">Plattform og nettsky</translation>
<translation id="7681101578153515023">Endre søkemotoren</translation>
<translation id="7682287625158474539">Forsendelse</translation>
<translation id="7687186412095877299">Fyll ut betalingsskjemaer med de lagrede betalingsmåtene dine</translation>
@@ -1262,7 +1283,6 @@
<translation id="7723047071702270851">Endre kortet</translation>
<translation id="774634243536837715">Farlig innhold er blokkert.</translation>
<translation id="7752995774971033316">Administreres ikke</translation>
-<translation id="7755287808199759310">Forelderen din kan oppheve blokkeringen for deg</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Brannmur- eller antivirusprogramvare kan ha blokkert tilkoblingen.</translation>
<translation id="7759163816903619567">Visningsdomene:</translation>
@@ -1306,7 +1326,6 @@
<translation id="8004582292198964060">Nettleser</translation>
<translation id="8009225694047762179">Administrer passord</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Dette kortet og den tilknyttede faktureringsadressen lagres. Du kan bruke det når du er logget på <ph name="USER_EMAIL" />.}other{Disse kortene og de tilknyttede faktureringsadressene lagres. Du kan bruke dem når du er logget på <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Vi kunne ikke nå foreldrene dine akkurat nå. Prøv igjen.</translation>
<translation id="8025119109950072390">Angripere på dette nettstedet prøver kanskje å lure deg til å gjøre farlige ting som å installere programvare eller avsløre personopplysningene dine (for eksempel passord, telefonnumre eller kredittkortinformasjon).</translation>
<translation id="8034522405403831421">Denne siden er på <ph name="SOURCE_LANGUAGE" />. Vil du oversette den til <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Penn</translation>
@@ -1317,6 +1336,7 @@
<translation id="8041940743680923270">Bruk global standardinnstilling (Spør)</translation>
<translation id="8042918947222776840">Velg hentemåte</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» er ikke riktig konfigurert. Avinstallering av «<ph name="SOFTWARE_NAME" />» løser vanligvis problemet. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Du kommer ikke til å trenge å skrive inn noen sikkerhetskode for kortet fremover</translation>
<translation id="8066955247577885446">Beklager, noe gikk galt.</translation>
<translation id="8074253406171541171">10x13 (konvolutt)</translation>
<translation id="8078141288243656252">Kan ikke legge til annoteringer når dokumentet er rotert</translation>
@@ -1347,6 +1367,7 @@
<translation id="8211406090763984747">Tilkoblingen er sikker</translation>
<translation id="8218327578424803826">Tilordnet posisjon:</translation>
<translation id="8220146938470311105">C7/C6 (konvolutt)</translation>
+<translation id="8220639454292072926">Bedriftsrapportering</translation>
<translation id="8225771182978767009">Personen som konfigurerte denne datamaskinen, har valgt å blokkere dette nettstedet.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Åpne siden i et nytt inkognitovindu</translation>
@@ -1401,23 +1422,23 @@ Mer informasjon:
<translation id="8508648098325802031">Søkeikon</translation>
<translation id="8522552481199248698">Chrome kan hjelpe deg med å beskytte Google-kontoen din og endre passordet ditt.</translation>
<translation id="8543181531796978784">Du kan <ph name="BEGIN_ERROR_LINK" />rapportere et påvisningsproblem<ph name="END_ERROR_LINK" /> eller, hvis du forstår sikkerhetsrisikoen, <ph name="BEGIN_LINK" />gå til dette usikre nettstedet<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Har du spørsmål? Kontakt personen som administrer profilen din.</translation>
<translation id="8553075262323480129">Oversettelsen mislyktes fordi sidens språk ikke kunne fastslås.</translation>
<translation id="8557066899867184262">CVC-koden finner du på baksiden av kortet.</translation>
<translation id="8559762987265718583">En privat tilkobling til <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> kunne ikke etableres fordi datoen og klokkeslettet (<ph name="DATE_AND_TIME" />) er feil på enheten.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> mistenkelig nettsted</translation>
<translation id="8564985650692024650">Chromium anbefaler at du tilbakestiller passordet ditt for <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> hvis du også har brukt det på andre nettsteder.</translation>
<translation id="8571890674111243710">Oversett siden til <ph name="LANGUAGE" /></translation>
<translation id="858637041960032120">Legg til telefonnummer</translation>
-<translation id="859285277496340001">Sertifikatet spesifiserer ikke en mekanisme for å kontrollere hvorvidt det har blitt tilbakekalt.</translation>
<translation id="860043288473659153">Kortinnehavers navn</translation>
<translation id="861775596732816396">Størrelse 4</translation>
-<translation id="8620436878122366504">Foreldrene dine har ikke godkjent det ennå</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Lagre dette kortet på denne enheten</translation>
<translation id="8626112503828625890">Vil du lagre faktureringsopplysninger i Google-kontoen?</translation>
+<translation id="8647750283161643317">Tilbakestill alle til standard</translation>
<translation id="8663226718884576429">Bestillingssammendrag, <ph name="TOTAL_LABEL" />, mer informasjon</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, svar, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Tilgjengelig</translation>
<translation id="8703575177326907206">Tilkoblingen til <ph name="DOMAIN" /> er ikke kryptert.</translation>
<translation id="8718314106902482036">Betalingen er ikke fullført</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, søkeforslag</translation>
@@ -1428,6 +1449,7 @@ Mer informasjon:
<translation id="8738058698779197622">Klokken din må være riktig stilt for at du skal kunne opprette en sikker forbindelse. Sertifikatene som nettsteder bruker til å identifisere seg med, er nemlig bare gyldige i en viss tid. Siden enhetens klokke er feil, kan ikke Chromium kontrollere disse sertifikatene.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;DNS-adressen&lt;/abbr&gt; til <ph name="HOST_NAME" /> ble ikke funnet. Problemet diagnostiseres.</translation>
<translation id="874846938927089722">Godkjente kredittkort og forhåndsbetalte kort</translation>
+<translation id="874918643257405732">Bokmerk denne fanen</translation>
<translation id="8759274551635299824">Dette kortet er utløpt</translation>
<translation id="8761567432415473239">Google Safe Browsing oppdaget nylig <ph name="BEGIN_LINK" />skadelige programmer<ph name="END_LINK" /> på <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB-enhet</translation>
@@ -1457,6 +1479,7 @@ Mer informasjon:
<translation id="8938939909778640821">Godkjente kredittkort og forhåndsbetalte kort</translation>
<translation id="8943282376843390568">Limegrønn</translation>
<translation id="8957210676456822347">Captive Portal-autorisasjon</translation>
+<translation id="8962950042226115166">Mistenkelig nettsted</translation>
<translation id="8968766641738584599">Lagre kortet</translation>
<translation id="8971063699422889582">Tjenerens sertifikat er utløpt.</translation>
<translation id="8975012916872825179">Inkluderer informasjon som telefonnumre, e-postadresser og leveringsadresser</translation>
@@ -1479,24 +1502,24 @@ Mer informasjon:
<translation id="9035022520814077154">Sikkerhetsfeil</translation>
<translation id="9038649477754266430">Bruk en prediksjonstjeneste for å laste inn sider raskere</translation>
<translation id="9039213469156557790">Denne siden inneholder i tillegg andre ressurser som ikke er sikre. Disse ressursene er synlige for andre mens de sendes frem og tilbake, og eventuelle angripere kan modifisere dem for å endre på atferden til siden.</translation>
+<translation id="9044359186343685026">Bruk Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Du forsøkte å nå <ph name="DOMAIN" />, men tjeneren oppga et ugyldig sertifikat.</translation>
<translation id="9050666287014529139">Passordfrase</translation>
<translation id="9065203028668620118">Endre</translation>
<translation id="9065745800631924235"><ph name="TEXT" />-søk fra loggen</translation>
<translation id="9069693763241529744">Blokkert av en utvidelse</translation>
-<translation id="9076283476770535406">Det kan ha voksent innhold</translation>
<translation id="9076630408993835509">Denne nettleseren administreres ikke av et selskap eller en annen organisasjon. Aktiviteten på denne enheten kan administreres utenfor Chrome. <ph name="BEGIN_LINK" />Finn ut mer<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Mer informasjon er nødvendig</translation>
<translation id="9080712759204168376">Bestillingssammendrag</translation>
<translation id="9089260154716455634">Regler for bruk utenom arbeidstiden:</translation>
<translation id="9095388113577226029">Flere språk</translation>
+<translation id="9098981495403789647">Administratoren har slått på beskyttelsesfunksjoner for bedrifter i Chrome-nettleseren din. Beskyttelsesfunksjoner for bedrifter i Chrome har tilgang til noen av dataene dine.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> bruker vanligvis kryptering for å beskytte informasjonen din. Da Chromium prøvde å koble til <ph name="SITE" /> denne gangen, sendte nettstedet tilbake uvanlig og feil legitimasjon. Dette kan skje hvis en angriper prøver å utgi seg for å være <ph name="SITE" />, eller hvis en Wi-Fi-påloggingsskjerm har avbrutt tilkoblingen. Informasjonen din er likevel sikker fordi Chromium stoppet tilkoblingen før det ble utvekslet noen data.</translation>
<translation id="9106062320799175032">Legg til faktureringsadresse</translation>
<translation id="9114524666733003316">Bekrefter kortet …</translation>
<translation id="9128870381267983090">Koble til nettverk</translation>
<translation id="9137013805542155359">Vis original</translation>
-<translation id="9137248913990643158">Du må starte og logge på Chrome før du bruker denne appen.</translation>
<translation id="9141013498910525015">Administrer adresser</translation>
<translation id="9148088599418889305">Velg leveringsmåte</translation>
<translation id="9148507642005240123">&amp;Angre endringen</translation>
diff --git a/chromium/components/strings/components_strings_pl.xtb b/chromium/components/strings/components_strings_pl.xtb
index bb169b8778c..423e8c5d218 100644
--- a/chromium/components/strings/components_strings_pl.xtb
+++ b/chromium/components/strings/components_strings_pl.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Dodaj imię i nazwisko z karty</translation>
<translation id="1089439967362294234">Zmień hasło</translation>
+<translation id="1096545575934602868">Maksymalna liczba wpisów w tym polu to <ph name="MAX_ITEMS_LIMIT" />. Kolejne wpisy zostaną odrzucone.</translation>
<translation id="109743633954054152">Hasłami możesz zarządzać w ustawieniach Chrome</translation>
<translation id="1103523840287552314">Zawsze tłumacz z języka: <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Po zaznaczeniu tej opcji Chrome będzie zapisywać kopię danych karty na tym urządzeniu, by szybciej wypełniać formularze.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Przejdź do <ph name="BEGIN_LINK" />kopii<ph name="END_LINK" /> <ph name="URL" /> w pamięci podręcznej</translation>
<translation id="1156303062776767266">Przeglądasz plik lokalny lub udostępniony</translation>
<translation id="1158211211994409885">Serwer <ph name="HOST_NAME" /> nieoczekiwanie zakończył połączenie.</translation>
+<translation id="115926840831309955">Sprawdź kod CVC i spróbuj ponownie lub popraw datę ważności</translation>
<translation id="1161325031994447685">Ponownie połącz się z Wi-Fi</translation>
<translation id="1165039591588034296">Błąd</translation>
<translation id="1175364870820465910">&amp;Drukuj...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Oprogramowanie na Twoim komputerze uniemożliwia Chrome bezpieczne połączenie się z internetem” (tylko na komputerach z systemem Windows)</translation>
<translation id="1294154142200295408">Odmiany w wierszu poleceń</translation>
<translation id="129553762522093515">Ostatnio zamknięte</translation>
+<translation id="1298536327547837046">Skanowanie w poszukiwaniu złośliwego oprogramowania</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Usuń pliki cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funkcje wycofane</translation>
<translation id="1320233736580025032">Prc1 (koperta)</translation>
<translation id="132301787627749051">Wyszukaj obraz ze schowka</translation>
<translation id="1323433172918577554">Pokaż więcej</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Arkusze Google</translation>
<translation id="1527263332363067270">Czekam na połączenie…</translation>
<translation id="1529521330346880926">10x15 (koperta)</translation>
+<translation id="1530707389502320859">Próbujesz otworzyć stronę, która wygląda na fałszywą. Złośliwe strony czasami podszywają się pod inne, wprowadzając małe i trudne do zauważenia zmiany w adresie URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Komunikat z bieżącej strony</translation>
<translation id="153384715582417236">Na razie to wszystko</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">System operacyjny</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokument jest za duży i nie można dodawać do niego adnotacji</translation>
-<translation id="1721312023322545264">Aby wejść na tę stronę, musisz uzyskać pozwolenie od użytkownika <ph name="NAME" /></translation>
<translation id="1721424275792716183">* Pole jest wymagane</translation>
<translation id="1727741090716970331">Dodaj prawidłowy numer karty</translation>
<translation id="1728677426644403582">Przeglądasz źródło strony internetowej</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Odwiedzone strony internetowe i spędzony na nich czas</translation>
<translation id="1826516787628120939">Sprawdzam</translation>
<translation id="1834321415901700177">Ta strona zawiera szkodliwe programy</translation>
+<translation id="1838374766361614909">Wyczyść wyszukiwanie</translation>
<translation id="1839551713262164453">Weryfikacja wartości zasad nie udała się z powodu błędów</translation>
<translation id="1842969606798536927">Zapłać</translation>
<translation id="1871208020102129563">Proxy skonfigurowano do używania stałych serwerów proxy, a nie URL-a skryptu PAC.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Zwiń listę</translation>
<translation id="1898423065542865115">Filtrowanie</translation>
<translation id="1914326953223720820">Usługa rozpakowywania</translation>
+<translation id="1915697529809968049">Używać Touch ID zamiast kodu CVC?</translation>
<translation id="1916770123977586577">Załaduj stronę ponownie, by zastosować na niej zaktualizowane ustawienia</translation>
<translation id="1919345977826869612">Reklamy</translation>
<translation id="1919367280705858090">Uzyskiwanie pomocy w przypadku konkretnego komunikatu o błędzie</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Zakładki z <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Podczas przekształcania do postaci szeregowej wystąpił błąd</translation>
<translation id="1974060860693918893">Zaawansowane</translation>
+<translation id="1974883374937189061">Pomóż w ulepszaniu zabezpieczeń Chrome, wysyłając do Google <ph name="BEGIN_WHITEPAPER_LINK" />adresy URL niektórych odwiedzanych przez siebie stron, niektóre informacje o systemie i niektóre treści ze stron<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Wersja oprogramowania</translation>
<translation id="1981206234434200693">Wyczyść dane historii przeglądania Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{i jeszcze 1}few{i jeszcze #}many{i jeszcze #}other{i jeszcze #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Wpisz rok w prawidłowym formacie</translation>
<translation id="2212735316055980242">Nie znaleziono zasady</translation>
<translation id="2213606439339815911">Pobieram wpisy...</translation>
+<translation id="2215727959747642672">Edytowanie pliku</translation>
<translation id="2218879909401188352">Osoby obecnie atakujące stronę <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogą instalować niebezpieczne aplikacje, które mogą uszkodzić Twoje urządzenie, dodać ukryte opłaty do rachunku za usługi telefoniczne lub wykraść Twoje dane osobowe. <ph name="BEGIN_LEARN_MORE_LINK" />Więcej informacji<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Brak internetu</translation>
<translation id="2230458221926704099">Napraw połączenie, używając <ph name="BEGIN_LINK" />aplikacji diagnostycznej<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Wyślij teraz</translation>
+<translation id="2248949050832152960">Używaj WebAuthn</translation>
<translation id="225207911366869382">Ta wartość tej zasady została wycofana.</translation>
<translation id="2257315177824333709">Nie można teraz zapisać tej karty</translation>
<translation id="2262243747453050782">Błąd HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Nieprawidłowy URL wyszukiwania</translation>
<translation id="2482878487686419369">Powiadomienia</translation>
<translation id="248348093745724435">Zasady dotyczące komputera</translation>
-<translation id="2485387744899240041">Nazwy użytkownika z urządzenia i przeglądarki</translation>
<translation id="2491120439723279231">Certyfikat serwera zawiera błędy.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Parser JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Wróć</translation>
<translation id="2503184589641749290">Akceptowane karty debetowe i przedpłacone</translation>
<translation id="2505268675989099013">Chroń konto</translation>
+<translation id="2515335152965840738">IGNORUJ</translation>
<translation id="2515629240566999685">Sprawdź sygnał w swojej okolicy</translation>
<translation id="2523886232349826891">Zapisana tylko na tym urządzeniu</translation>
<translation id="2524461107774643265">Dodaj więcej informacji</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Prześlij</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Brak}=1{1 hasło (do <ph name="DOMAIN_LIST" />)}=2{2 hasła (do <ph name="DOMAIN_LIST" />)}few{# hasła (do <ph name="DOMAIN_LIST" />)}many{# haseł (do <ph name="DOMAIN_LIST" />)}other{# hasła (do <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Zamknij inne karty lub aplikacje</translation>
-<translation id="267371737713284912">naciśnij <ph name="MODIFIER_KEY_DESCRIPTION" />, by cofnąć</translation>
<translation id="2674170444375937751">Czy na pewno chcesz usunąć te strony z historii?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Wyjdź</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Wartość nie pasuje do formatu.</translation>
<translation id="2705137772291741111">Zapisana w pamięci podręcznej kopia tej strony jest uszkodzona.</translation>
<translation id="2709516037105925701">Autouzupełnianie</translation>
-<translation id="2712173769900027643">Poproś o pozwolenie</translation>
<translation id="2713444072780614174">Biały</translation>
<translation id="2720342946869265578">W pobliżu</translation>
<translation id="2721148159707890343">Żądanie wykonane pomyślnie</translation>
<translation id="2728127805433021124">Certyfikat serwera został podpisany przy użyciu słabego algorytmu podpisu.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Uruchomienie diagnostyki połączeń<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Włączenie tych funkcji może spowodować utratę danych z przeglądarki
+ oraz narazić bezpieczeństwo i prywatność użytkowników.
+ Funkcje są włączane dla wszystkich użytkowników tej przeglądarki.</translation>
<translation id="2735043616039983645">Dla tej zasady określono więcej niż jedno źródło, a wartości tych źródeł są sprzeczne.</translation>
<translation id="2738330467931008676">Wybierz adres odbioru</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Połączenie zostało zresetowane.</translation>
<translation id="2788784517760473862">Akceptowane karty kredytowe</translation>
<translation id="2792012897584536778">Administratorzy tego urządzenia skonfigurowali certyfikaty zabezpieczeń, dzięki którym mogą zobaczyć zawartość stron internetowych, które odwiedzasz.</translation>
-<translation id="2794233252405721443">Strona zablokowana</translation>
<translation id="2799020568854403057">Strona, którą chcesz otworzyć, zawiera szkodliwe aplikacje</translation>
<translation id="2799223571221894425">Uruchom ponownie</translation>
<translation id="2803306138276472711">Bezpieczne przeglądanie Google <ph name="BEGIN_LINK" />wykryło ostatnio złośliwe oprogramowanie<ph name="END_LINK" /> na <ph name="SITE" />. Strony, które zazwyczaj są bezpieczne, zostają czasem zainfekowane destrukcyjnym oprogramowaniem.</translation>
+<translation id="2815364696811431560">OPUŚĆ STRONĘ</translation>
<translation id="2824775600643448204">Pasek adresu i wyszukiwania</translation>
<translation id="2826760142808435982">Połączenie jest szyfrowane i uwierzytelniane algorytmem <ph name="CIPHER" />, a mechanizm wymiany kluczy to <ph name="KX" />.</translation>
<translation id="2835170189407361413">Wyczyść formularz</translation>
<translation id="2847118875340931228">Otwórz okno incognito</translation>
<translation id="2850739647070081192">Invite (koperta)</translation>
-<translation id="2851634818064021665">Musisz mieć pozwolenie, by wejść na tę stronę</translation>
<translation id="2856444702002559011">Osoby atakujące mogą próbować wykraść Twoje informacje ze strony <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (na przykład hasła, wiadomości lub dane kart kredytowych). <ph name="BEGIN_LEARN_MORE_LINK" />Więcej informacji<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Czy zapisać kartę?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Jeśli włączysz tę opcję, Chromium zapisze kopię Twojej karty na tym urządzeniu, by umożliwić Ci szybsze wypełnianie formularzy.</translation>
<translation id="2985398929374701810">Wpisz prawidłowy adres</translation>
<translation id="2986368408720340940">Ta metoda odbioru jest niedostępna. Wybierz inną.</translation>
+<translation id="2987034854559945715">Brak pasujących funkcji</translation>
<translation id="2991174974383378012">Udostępnianie stronom internetowym</translation>
<translation id="2991571918955627853">Nie możesz teraz wejść na stronę <ph name="SITE" />, ponieważ używa ona HSTS. Błędy sieciowe i ataki są zazwyczaj tymczasowe, więc prawdopodobnie strona będzie dostępna później.</translation>
<translation id="3005723025932146533">Pokaż zapisaną kopię</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Nieprawidłowy typ zasady</translation>
<translation id="3037605927509011580">Kurza twarz!</translation>
<translation id="3041612393474885105">Informacje o certyfikacie</translation>
+<translation id="3057676462092457419">Tryb DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> nie jest jeszcze obsługiwany. Został ustawiony jako <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (koperta)</translation>
<translation id="3061707000357573562">Zastosowanie poprawki do usługi</translation>
<translation id="3064966200440839136">Opuszczasz tryb incognito, by zapłacić w aplikacji zewnętrznej. Kontynuować?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na serwerze <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Anuluj płatność</translation>
<translation id="3207960819495026254">Dodano do zakładek</translation>
+<translation id="3209034400446768650">Strona może powodować naliczanie opłat</translation>
<translation id="3225919329040284222">Serwer przedstawił certyfikat, który nie pasuje do zaprogramowanych oczekiwań. Oczekiwania mają chronić Cię w określonych witrynach o wysokim poziomie zabezpieczeń.</translation>
<translation id="3226128629678568754">Naciśnij przycisk ponownego załadowania, by przesłać dane wymagane do wczytania strony.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Informacje o wersji urządzenia i przeglądarki</translation>
<translation id="323107829343500871">Wpisz kod CVC karty <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Zawsze wykrywaj ważną treść na tej stronie</translation>
-<translation id="3254409185687681395">Dodaj stronę do zakładek</translation>
<translation id="3270847123878663523">&amp;Cofnij zmianę kolejności</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Dodaj imię i nazwisko na karcie</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Dodaj adres rozliczeniowy</translation>
<translation id="3324983252691184275">Karmazynowy</translation>
<translation id="3338095232262050444">Bezpieczna</translation>
-<translation id="3345135638360864351">Nie udało się wysłać żądania dostępu do strony do <ph name="NAME" />. Spróbuj ponownie.</translation>
<translation id="3355823806454867987">Zmień ustawienia serwera proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />nie będzie zapisywać<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Ukryj zaawansowane</translation>
<translation id="3467763166455606212">Wymagane jest imię i nazwisko posiadacza karty</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, obecnie otwarta. Naciśnij klawisz Tab, a potem Enter, by przełączyć się na otwartą kartę</translation>
-<translation id="3479539252931486093">Zaskoczyło Cię to? <ph name="BEGIN_LINK" />Daj nam znać<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Nie teraz</translation>
<translation id="3484560055331845446">Możesz stracić dostęp do swojego konta Google. Chrome zaleca natychmiastową zmianę hasła. Zobaczysz prośbę, by się zalogować.</translation>
<translation id="3495081129428749620">Znajdź na stronie
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Obecnie nie możemy się skontaktować z Twoim rodzicem. Spróbuj ponownie.</translation>
<translation id="3512163584740124171">Ta zasada jest ignorowana, ponieważ inna zasada z tej samej grupy zasad ma wyższy priorytet.</translation>
<translation id="3528171143076753409">Certyfikat serwera nie jest zaufany.</translation>
<translation id="3528485271872257980">Ciemnobrązowy</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Co najmniej 1 element na synchronizowanych urządzeniach}=1{1 element (i więcej na synchronizowanych urządzeniach)}few{# elementy (i więcej na synchronizowanych urządzeniach)}many{# elementów (i więcej na synchronizowanych urządzeniach)}other{# elementu (i więcej na synchronizowanych urządzeniach)}}</translation>
<translation id="3539171420378717834">Zachowaj kopię tej karty na urządzeniu</translation>
-<translation id="3556433843310711081">Twój menedżer może ją dla Ciebie odblokować</translation>
<translation id="3566021033012934673">Połączenie nie jest prywatne</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Komunikat z elementu umieszczonego na stronie <ph name="SITE" /></translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Otwórz stronę w nowym oknie incognito (Ctrl+Shift+N)</translation>
<translation id="3679803492151881375">Raport o awarii zarejestrowano: <ph name="CRASH_TIME" />, przesłano: <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informacje o certyfikacie</translation>
+<translation id="3701427423622901115">Zresetowanie zostało potwierdzone.</translation>
<translation id="3704162925118123524">Sieć, której używasz, może wymagać otwarcia strony logowania.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Ładuję...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Osoby atakujące na stronie <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogą podstępem nakłonić Cię do wykonania czynności niebezpiecznych takich jak zainstalowanie oprogramowania czy ujawnienie danych osobowych (na przykład haseł, numerów telefonów lub danych kart kredytowych). <ph name="BEGIN_LEARN_MORE_LINK" />Więcej informacji<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Tłumaczenie nie powiodło się z powodu błędu serwera.</translation>
<translation id="3759461132968374835">Brak ostatnio zgłoszonych awarii. Awarie, które nastąpiły wówczas, gdy funkcja zgłaszania awarii była wyłączona, nie są tutaj wymienione.</translation>
+<translation id="3760561303380396507">Używać Windows Hello zamiast kodu CVC?</translation>
<translation id="3761718714832595332">Ukryj stan</translation>
<translation id="3765032636089507299">Strona funkcji Bezpieczne przeglądanie jest w budowie.</translation>
<translation id="3778403066972421603">Czy chcesz zapisać tę kartę na swoim koncie Google i na tym urządzeniu?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Rozmiar 16</translation>
<translation id="3797522431967816232">Prc3 (koperta)</translation>
<translation id="3807873520724684969">Zablokowano szkodliwe treści.</translation>
+<translation id="3808375843007691220">Ostrzeżenie: funkcje eksperymentalne</translation>
<translation id="3810973564298564668">Zarządzaj</translation>
<translation id="382518646247711829">Jeśli używasz serwera proxy...</translation>
<translation id="3828924085048779000">Puste hasło jest niedozwolone.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Zaktualizuj datę i godzinę</translation>
<translation id="3884278016824448484">Konflikt identyfikatorów urządzeń</translation>
<translation id="3885155851504623709">Parafia</translation>
-<translation id="3886446263141354045">Twoja prośba o dostęp to tej strony została wysłana do: <ph name="NAME" /></translation>
<translation id="3890664840433101773">Dodaj adres e-mail</translation>
<translation id="3901925938762663762">Karta straciła ważność</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Używać WebAuthn zamiast kodu CVC?</translation>
<translation id="3946209740501886391">Zawsze pytaj na tej stronie</translation>
<translation id="3949571496842715403">Serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa nie określa alternatywnych nazw podmiotu. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
<translation id="3949601375789751990">Tutaj wyświetla się Twoja historia przeglądania</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Brak}=1{Z 1 witryny }few{Z # witryn }many{Z # witryn }other{Z # witryny }}</translation>
<translation id="397105322502079400">Obliczanie...</translation>
<translation id="3973234410852337861">Strona <ph name="HOST_NAME" /> jest zablokowana</translation>
+<translation id="3981540111851280311">Domena <ph name="ENROLLMENT_DOMAIN" /> włączyła w Twojej przeglądarce dostępną w Chrome ochronę przed zagrożeniami dla firm. Ta funkcja ma dostęp do niektórych Twoich danych.</translation>
<translation id="3987940399970879459">Mniej niż 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 strona w pobliżu}few{# strony w pobliżu}many{# stron w pobliżu}other{# strony w pobliżu}}</translation>
<translation id="4030383055268325496">&amp;Cofnij dodanie</translation>
<translation id="4032320456957708163">Twoją przeglądarką zarządza <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Otwierany link prowadzi do strony, której zwykle nie odwiedzasz. Może to być próba wprowadzenia Cię w błąd.</translation>
<translation id="4058922952496707368">Klucz „<ph name="SUBKEY" />”: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (koperta)</translation>
<translation id="4067947977115446013">Dodaj poprawny adres</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Numer seryjny urządzenia jest nieprawidłowy</translation>
<translation id="410351446219883937">Autoodtwarzanie</translation>
<translation id="4103763322291513355">Wejdź na stronę &lt;strong&gt;chrome://policy&lt;/strong&gt;, aby wyświetlić czarną listę URL-i oraz inne zasady egzekwowane przez administratora systemu.</translation>
+<translation id="4108231218301530806">Następnym razem do weryfikacji tej karty użyj odcisku palca.</translation>
<translation id="4110652170750985508">Sprawdź szczegóły płatności</translation>
<translation id="4112140312785995938">Przewiń do tyłu</translation>
<translation id="4116663294526079822">Zawsze zezwalaj w tej witrynie</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Nieprawidłowy podpis weryfikujący</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Jeszcze <ph name="ITEM_COUNT" /> element}few{Jeszcze <ph name="ITEM_COUNT" /> elementy}many{Jeszcze <ph name="ITEM_COUNT" /> elementów}other{Jeszcze <ph name="ITEM_COUNT" /> elementu}}</translation>
+<translation id="4176463684765177261">Wyłączone</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Aby następnym razem zapłacić szybciej, dodaj kartę i adres rozliczeniowy do swojego konta Google.</translation>
<translation id="4196861286325780578">&amp;Ponów przeniesienie</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Resetuj hasło</translation>
<translation id="4279811152705618813">Twoim urządzeniem (<ph name="DEVICE_TYPE" />) zarządza domena <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ta karta została zapisana na Twoim koncie Google}few{Te karty zostały zapisane na Twoim koncie Google}many{Te karty zostały zapisane na Twoim koncie Google}other{Te karty zostały zapisane na Twoim koncie Google}}</translation>
+<translation id="428847186335018806">Skanuj pliki pobrane z Chrome i przesłane do Chrome.</translation>
<translation id="42981349822642051">Rozwiń</translation>
<translation id="4302965934281694568">Chou3 (koperta)</translation>
<translation id="4305817255990598646">Przełącz</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">pocztówka)</translation>
<translation id="443673843213245140">Korzystanie z serwera proxy jest wyłączone, ale podano konfigurację proxy.</translation>
<translation id="445100540951337728">Akceptowane karty debetowe</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> podejrzane zachowanie</translation>
<translation id="4466881336512663640">Zmiany w formularzu zostaną utracone. Na pewno chcesz kontynuować?</translation>
<translation id="4477350412780666475">Następny utwór</translation>
<translation id="4482953324121162758">Ta strona nie będzie tłumaczona.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Cofnij usunięcie</translation>
<translation id="4597348597567598915">Rozmiar 8</translation>
<translation id="4600854749408232102">C6/C5 (koperta)</translation>
+<translation id="464342062220857295">Funkcje wyszukiwarki</translation>
<translation id="4646534391647090355">Przejdź tam teraz</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa ma błędy. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (koperta)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Połączenie zostało przerwane</translation>
-<translation id="471880041731876836">Nie masz pozwolenia, by wejść na tę stronę</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Uruchom Diagnostykę sieci systemu Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Odśwież zasady</translation>
<translation id="4728558894243024398">Platforma</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Dopasuj do strony</translation>
<translation id="4850886885716139402">Widok</translation>
<translation id="4854362297993841467">Ta metoda dostawy jest niedostępna. Wybierz inną.</translation>
-<translation id="4858792381671956233">Zapytałeś rodziców, czy możesz wejść na tę stronę</translation>
<translation id="4864052566555297930">Wskazówka na temat bezpieczeństwa:</translation>
<translation id="4876188919622883022">Widok uproszczony</translation>
<translation id="4876305945144899064">Brak nazwy użytkownika</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Ponownie włącz ostrzeżenia</translation>
<translation id="4984339528288761049">Prc5 (koperta)</translation>
<translation id="4989163558385430922">Pokaż wszystko</translation>
+<translation id="4989542687859782284">Niedostępne</translation>
<translation id="4989809363548539747">Ta wtyczka nie jest obsługiwana</translation>
+<translation id="4995216769782533993">Aby udostępnić tej stronie dane karty, potwierdź kod zabezpieczający</translation>
<translation id="5002932099480077015">Jeśli włączysz tę opcję, Chrome zapisze kopię Twojej karty na tym urządzeniu, by umożliwić Ci szybsze wypełnianie formularzy.</translation>
<translation id="5015510746216210676">Nazwa komputera:</translation>
<translation id="5017554619425969104">Skopiowany tekst</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bitowa)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Zweryfikuj kartę</translation>
<translation id="5135404736266831032">Zarządzaj adresami…</translation>
<translation id="5138227688689900538">Pokaż mniej</translation>
<translation id="5141240743006678641">Szyfruj synchronizowane hasła za pomocą danych logowania Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Chmura</translation>
<translation id="5252000469029418751">C7 (koperta)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funkcje stosowane w całym systemie może ustawić tylko właściciel: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Ostrzeżenie: ta zasada nie została scalona na podstawie zasady PolicyDictionaryMultipleSourceMergeList, ponieważ nie należy do zasad słownikowych, które można scalić.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Zakończ</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Zapisanie ustawień zasady nie powiodło się</translation>
<translation id="5371425731340848620">Zaktualizuj dane karty</translation>
<translation id="5377026284221673050">„Twój zegar się spóźnia” lub „Twój zegar się śpieszy” lub „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;”</translation>
-<translation id="5377179979757081683">Ta strona może próbować Cię oszukać, wykraść Twoje dane osobowe lub uszkodzić Twoje urządzenie. Zachowaj ostrożność przy podawaniu swoich danych i otwieraniu pobranych z niej plików.</translation>
<translation id="5384855140246857529">Aby używać swoich kart na wszystkich urządzeniach, zaloguj się i włącz synchronizację.</translation>
<translation id="5386426401304769735">Łańcuch certyfikatów tej witryny zawiera certyfikat podpisany za pomocą SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Nieprawidłowe</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}many{<ph name="CONTACT_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Ponów edycję</translation>
+<translation id="5473728911100096288">Jeśli włączysz te funkcje, będziesz używać zaniechanych funkcji,
+ które zostaną wycofane w przyszłości.</translation>
<translation id="5478437291406423475">B6/C4 (koperta)</translation>
<translation id="5481076368049295676">Te treści mogą próbować instalować na Twoim urządzeniu niebezpieczne oprogramowanie, które wykrada lub usuwa dane. <ph name="BEGIN_LINK" />Wyświetl mimo to<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Dodaj poprawny adres</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Chroń konto</translation>
<translation id="5571083550517324815">Odbiór spod tego adresu jest niemożliwy. Wybierz inny adres.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{W użyciu: 1}few{W użyciu: #}many{W użyciu: #}other{W użyciu: #}})</translation>
-<translation id="5572851009514199876">Uruchom Chrome i zaloguj się w nim, by mógł sprawdzić, czy masz uprawnienia dostępu do tej strony.</translation>
<translation id="5580958916614886209">Sprawdź miesiąc ważności i spróbuj ponownie</translation>
<translation id="5586446728396275693">Brak zapisanych adresów</translation>
<translation id="5595485650161345191">Edytuj adres</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Zarządzanie jest nieobsługiwane</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Ta strona może być fałszywa. Chrome zaleca jej natychmiastowe opuszczenie.</translation>
<translation id="5610142619324316209">Sprawdź połączenie</translation>
<translation id="5610807607761827392">Możesz zarządzać kartami i adresami w <ph name="BEGIN_LINK" />Ustawieniach<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Strona <ph name="HOST_NAME" /> spowodowała zbyt wiele przekierowań.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Bieżący użytkownik</translation>
<translation id="5728056243719941842">C5 (koperta)</translation>
<translation id="5730040223043577876">Chrome zaleca zresetowanie hasła, jeśli zostało użyte na innej stronie.</translation>
-<translation id="5732392974455271431">Mogą ją dla Ciebie odblokować Twoi rodzice</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Zapisywanie karty na koncie Google}few{Zapisywanie kart na koncie Google}many{Zapisywanie kart na koncie Google}other{Zapisywanie kart na koncie Google}}</translation>
<translation id="5763042198335101085">Wpisz prawidłowy adres e-mail</translation>
<translation id="5765072501007116331">Aby zobaczyć metody dostawy oraz wymagania, wybierz adres</translation>
<translation id="5778550464785688721">Pełne sterowanie urządzeniami MIDI</translation>
+<translation id="5781136890105823427">Eksperyment włączony</translation>
<translation id="578305955206182703">Bursztynowy</translation>
<translation id="57838592816432529">Wycisz</translation>
<translation id="5784606427469807560">Podczas potwierdzania karty wystąpił problem. Sprawdź połączenie internetowe i spróbuj ponownie.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Wyłączone</translation>
<translation id="5863847714970149516">Otwierana strona może próbować obciążyć Cię płatnością</translation>
<translation id="5866257070973731571">Dodaj numer telefonu</translation>
+<translation id="5866898949289125849">To jest strona z narzędziami dla programistów</translation>
<translation id="5869405914158311789">Ta witryna jest nieosiągalna</translation>
<translation id="5869522115854928033">Zapisane hasła</translation>
<translation id="5887400589839399685">Zapisano kartę</translation>
<translation id="5893752035575986141">Karty kredytowe są akceptowane.</translation>
+<translation id="5895138241574237353">Uruchom ponownie</translation>
<translation id="5901630391730855834">Żółty</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (zsynchronizowane)</translation>
<translation id="5916664084637901428">Włączone</translation>
+<translation id="59174027418879706">Włączony</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Zapisać kartę na koncie Google?</translation>
<translation id="5922853866070715753">Prawie gotowe</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Chcesz używać swoich kart na wszystkich urządzeniach?</translation>
<translation id="6059925163896151826">Urządzenia USB</translation>
+<translation id="6060009363608157444">Nieprawidłowy tryb DnsOverHttps.</translation>
<translation id="6080696365213338172">Masz dostęp do treści dzięki certyfikatowi dostarczonemu przez administratora. Administrator może odczytać dane, jakie udostępnisz w <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">Dodaj adnotacje</translation>
<translation id="610911394827799129">Inne rodzaje historii przeglądania mogą być nadal dostępne na Twoim koncie Google na <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Edytuj zakładkę</translation>
<translation id="6406765186087300643">C0 (koperta)</translation>
<translation id="6410264514553301377">Wpisz datę ważności i kod CVC karty <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Zapytałeś rodzica, czy możesz odwiedzić tę stronę</translation>
<translation id="6415778972515849510">Chromium może Ci pomóc w zabezpieczeniu Twojego konta Google i zmianie hasła.</translation>
-<translation id="6417515091412812850">Nie można sprawdzić, czy certyfikat został unieważniony.</translation>
<translation id="6431585503458005759">Nie zapisuj</translation>
<translation id="6433490469411711332">Edytuj dane kontaktowe</translation>
<translation id="6433595998831338502">Serwer <ph name="HOST_NAME" /> odrzucił połączenie.</translation>
<translation id="6434309073475700221">Przerwij</translation>
+<translation id="6435221585574090192">Udostępniaj administratorowi dane na temat zdarzeń związanych z bezpieczeństwem zgłoszonych przez dostępną w Chrome ochronę przed zagrożeniami dla firm. Dane te mogą obejmować adresy URL stron, nazwę i metadane pliku oraz nazwę użytkownika urządzenia i Chrome.</translation>
<translation id="6440503408713884761">Ignorowany</translation>
<translation id="6446163441502663861">Kahu (koperta)</translation>
<translation id="6446608382365791566">Dodaj więcej informacji</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Zarządzaj hasłami…</translation>
<translation id="647261751007945333">Zasady dotyczące urządzeń</translation>
<translation id="6476284679642588870">Zarządzaj formami płatności</translation>
-<translation id="6477321094435799029">Chrome wykrył nietypowy kod na tej stronie i zablokował ją, by chronić Twoje dane osobowe (np. hasła, numery telefonu czy dane kart kredytowych).</translation>
<translation id="6489534406876378309">Rozpocznij przesyłanie informacji o awariach</translation>
<translation id="6499038740797743453">Zresetować hasło?</translation>
<translation id="6507833130742554667">Karty kredytowe i debetowe są akceptowane.</translation>
<translation id="650855688985305916">Tak, zapisz</translation>
<translation id="6508722015517270189">Uruchom ponownie Chrome</translation>
<translation id="6517596291481585650">Ostrzeżenie: ta zasada nie została scalona jako lista na podstawie zasady, ponieważ nie jest listą.</translation>
+<translation id="6518133107902771759">Zweryfikuj</translation>
<translation id="6521745193039995384">Nieaktywna</translation>
<translation id="6529602333819889595">&amp;Ponów usunięcie</translation>
<translation id="6534179046333460208">Sugestie dotyczące internetu rzeczy</translation>
<translation id="6545864417968258051">Skanowanie Bluetooth</translation>
<translation id="6554795675067793129">To konto jest zarządzane przez: <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Ponów</translation>
-<translation id="6563469144985748109">Twój menedżer jeszcze na to nie zezwolił</translation>
<translation id="6569060085658103619">Przeglądasz stronę rozszerzenia</translation>
<translation id="6578796323535178455">C2 (koperta)</translation>
<translation id="6579990219486187401">Jasnoróżowy</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Wyczyść</translation>
<translation id="6644283850729428850">Zasada jest wycofana</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Brak}=1{Z 1 witryny (nie spowoduje to wylogowania z konta Google)}few{Z # witryn (nie spowoduje to wylogowania z konta Google)}many{Z # witryn (nie spowoduje to wylogowania z konta Google)}other{Z # witryny (nie spowoduje to wylogowania z konta Google)}}</translation>
+<translation id="6652101503459149953">Używaj Windows Hello</translation>
<translation id="6657585470893396449">Hasło</translation>
<translation id="6670613747977017428">Wróć do bezpiecznej strony.</translation>
<translation id="6671697161687535275">Usunąć tę podpowiedź do formularza z Chromium?</translation>
<translation id="6685834062052613830">Wyloguj się i dokończ konfigurację</translation>
<translation id="6689271823431384964">Chrome proponuje zalogowanym użytkownikom zapisywanie kart na koncie Google. Możesz to zmienić w ustawieniach. Imię i nazwisko posiadacza karty pochodzi z Twojego konta.</translation>
+<translation id="6707256370811247129">Skanowanie zawartości pamięci podręcznej oraz plików pobranych z Chrome i przesłanych do Chrome.</translation>
<translation id="6710213216561001401">Wstecz</translation>
<translation id="6710594484020273272">&lt;Wpisz wyszukiwane słowa&gt;</translation>
<translation id="671076103358959139">Token rejestracji:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Twoje dane zostały zaszyfrowane <ph name="BEGIN_LINK" />hasłem synchronizacji<ph name="END_LINK" /> w dniu <ph name="TIME" />. Wpisz to hasło, by rozpocząć synchronizację.</translation>
<translation id="674375294223700098">Nieznany błąd certyfikatu serwera.</translation>
<translation id="6744009308914054259">Dopóki nie masz połączenia, możesz poczytać artykuły offline z Pobranych plików.</translation>
+<translation id="6747611005629681221">Ostrzeżenie: znajdziesz funkcje, które nie są już rozwijane</translation>
<translation id="6753269504797312559">Wartość zasady</translation>
<translation id="6757797048963528358">Twoje urządzenie przeszło w tryb uśpienia.</translation>
<translation id="6768213884286397650">Hagaki (pocztówka)</translation>
-<translation id="6778737459546443941">Twój rodzic jeszcze na to nie zezwolił</translation>
<translation id="67862343314499040">Fioletowy</translation>
<translation id="6786747875388722282">Rozszerzenia</translation>
<translation id="6790428901817661496">Odtwórz</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Pole wymagane</translation>
<translation id="6810899417690483278">Identyfikator dostosowania</translation>
<translation id="6825578344716086703">Próbujesz wejść na <ph name="DOMAIN" />, ale serwer przedstawił certyfikat podpisany słabym algorytmem (takim jak SHA-1). Oznacza to, że dane uwierzytelniające podane przez serwer mogły zostać sfałszowane, a serwer może nie być tym, którego oczekujesz (możliwe, że komunikujesz się z intruzem).</translation>
+<translation id="6826370046007623921">Zapobieganie utracie danych</translation>
<translation id="6831043979455480757">Tłumacz</translation>
<translation id="6839929833149231406">Obszar</translation>
<translation id="6852204201400771460">Załadować ponownie aplikację?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Ten poziom zasad nie jest obsługiwany.</translation>
<translation id="6895330447102777224">Karta została potwierdzona</translation>
<translation id="6897140037006041989">Klient</translation>
-<translation id="6903319715792422884">Pomóż w ulepszaniu Bezpiecznego przeglądania, wysyłając do Google pewne <ph name="BEGIN_WHITEPAPER_LINK" />informacje o systemie i część zawartości stron<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Użytkownik:</translation>
<translation id="6934672428414710184">To imię i nazwisko pochodzi z Twojego konta Google</translation>
<translation id="6944692733090228304">Wpisałeś swoje hasło na stronie, którą nie zarządza <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Aby chronić konto, nie używaj swojego hasła w innych aplikacjach ani witrynach.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}many{<ph name="PAYMENT_METHOD_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lawendowy</translation>
<translation id="717330890047184534">Identyfikator GAIA:</translation>
+<translation id="7174545416324379297">Wartości scalone</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}many{<ph name="SHIPPING_OPTION_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> i jeszcze <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Serwer <ph name="ORIGIN" />, z którym chcesz się połączyć, zażądał stosowania
zasady bezpieczeństwa do wszystkich swoich żądań. Jednak zamiast
@@ -1166,6 +1187,7 @@ Dodatkowe informacje:
<translation id="7320336641823683070">Pomoc dotycząca połączeń</translation>
<translation id="733354035281974745">Zastąpienie przez konto lokalne na urządzeniu</translation>
<translation id="7334320624316649418">&amp;Ponów zmianę kolejności</translation>
+<translation id="7337706099755338005">Niedostępny na Twojej platformie.</translation>
<translation id="733923710415886693">Certyfikat serwera nie został ujawniony przez protokół Certificate Transparency.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Jest w tej samej domenie:</translation>
@@ -1197,7 +1219,6 @@ Dodatkowe informacje:
<translation id="7440140511386898319">Przeglądaj offline</translation>
<translation id="7441627299479586546">Nieprawidłowy podmiot zasady</translation>
<translation id="7442725080345379071">Jasnopomarańczowy</translation>
-<translation id="7444046173054089907">Ta strona jest zablokowana</translation>
<translation id="7445762425076701745">Nie można w pełni zweryfikować tożsamości serwera, z którym nawiązano połączenie. Nawiązano połączenie z serwerem przy użyciu nazwy obowiązującej jedynie w Twojej sieci i której własności zewnętrzny urząd certyfikacji nie jest w stanie zweryfikować. Niektóre urzędy certyfikacji wydają certyfikaty dla takich nazw bez względu na to, że nie można upewnić się, iż nawiązano połączenie z witryną, z którą zamierzano, a nie z intruzem.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Dowiedz się więcej<ph name="END_LINK" /> o tym problemie.</translation>
<translation id="7455133967321480974">Użyj globalnej wartości domyślnej (Blokuj)</translation>
@@ -1219,9 +1240,9 @@ Dodatkowe informacje:
<translation id="7538364083937897561">A2 (koperta)</translation>
<translation id="7542403920425041731">Po potwierdzeniu szczegółowe dane karty zostaną udostępnione tej stronie.</translation>
<translation id="7542995811387359312">Automatyczne wypełnianie danych karty kredytowej jest wyłączone, ponieważ ten formularz nie korzysta z bezpiecznego połączenia.</translation>
-<translation id="7543525346216957623">Poproś rodzica</translation>
<translation id="7548892272833184391">Naprawianie błędów połączenia</translation>
<translation id="7549584377607005141">Do poprawnego wyświetlenia tej strony internetowej wymagane są dane wpisane przez Ciebie wcześniej. Możesz wysłać je ponownie, ale spowoduje to powtórzenie wszystkich działań wykonanych poprzednio przez stronę.</translation>
+<translation id="7550637293666041147">Twoja nazwa użytkownika na urządzeniu i w Chrome</translation>
<translation id="7552846755917812628">Skorzystaj z tych wskazówek:</translation>
<translation id="7554791636758816595">Nowa karta</translation>
<translation id="7564049878696755256">Możesz stracić dostęp do swojego konta <ph name="ORG_NAME" /> lub paść ofiarą kradzieży tożsamości. Chrome zaleca natychmiastową zmianę hasła.</translation>
@@ -1236,6 +1257,7 @@ Dodatkowe informacje:
<translation id="7610193165460212391">Wartość spoza zakresu (<ph name="VALUE" />)</translation>
<translation id="7613889955535752492">Wygasa: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Masz już dane zaszyfrowane przy użyciu innej wersji hasła konta Google. Wpisz je poniżej.</translation>
+<translation id="7625784245512586808">Dostępna w Chrome ochrona przed zagrożeniami dla firm</translation>
<translation id="7633909222644580952">Dane o wydajności i raporty o awariach</translation>
<translation id="7637571805876720304">Usunąć tę kartę kredytową z Chromium?</translation>
<translation id="7638605456503525968">Porty szeregowe</translation>
@@ -1248,7 +1270,6 @@ Dodatkowe informacje:
<translation id="7668654391829183341">Nieznane urządzenie</translation>
<translation id="7669271284792375604">Osoby atakujące tę stronę mogą podstępem próbować nakłonić Cię do zainstalowania programów utrudniających przeglądanie internetu (np. zmieniających stronę główną lub wyświetlających dodatkowe reklamy na stronach, na które wchodzisz).</translation>
<translation id="7676643023259824263">Wyszukaj tekst ze schowka, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platforma i chmura</translation>
<translation id="7681101578153515023">Zmień wyszukiwarkę</translation>
<translation id="7682287625158474539">Adres wysyłkowy</translation>
<translation id="7687186412095877299">Wypełniaj formularze płatności, używając zapisanych form płatności</translation>
@@ -1263,7 +1284,6 @@ Dodatkowe informacje:
<translation id="7723047071702270851">Edytuj kartę</translation>
<translation id="774634243536837715">Zablokowano niebezpieczne treści.</translation>
<translation id="7752995774971033316">Niezarządzany</translation>
-<translation id="7755287808199759310">Może ją dla Ciebie odblokować Twój rodzic</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Połączenie mogło zostać zablokowane przez zaporę sieciową lub program antywirusowy.</translation>
<translation id="7759163816903619567">Wyświetlana domena:</translation>
@@ -1307,7 +1327,6 @@ Dodatkowe informacje:
<translation id="8004582292198964060">Przeglądarka</translation>
<translation id="8009225694047762179">Zarządzaj hasłami</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ta karta i jej adres rozliczeniowy zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}few{Te karty i ich adresy rozliczeniowe zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}many{Te karty i ich adresy rozliczeniowe zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}other{Te karty i ich adresy rozliczeniowe zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Obecnie nie możemy się skontaktować z Twoimi rodzicami. Spróbuj ponownie.</translation>
<translation id="8025119109950072390">Osoby atakujące tę stronę mogą podstępem nakłonić Cię do zrobienia czegoś niebezpiecznego, np. zainstalowania oprogramowania lub ujawnienia danych osobowych (takich jak hasła, numery telefonów czy dane kart kredytowych).</translation>
<translation id="8034522405403831421">Język tej strony to <ph name="SOURCE_LANGUAGE" />. Przetłumaczyć ją na <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pióro</translation>
@@ -1318,6 +1337,7 @@ Dodatkowe informacje:
<translation id="8041940743680923270">Użyj globalnej wartości domyślnej (Pytaj)</translation>
<translation id="8042918947222776840">Wybierz metodę odbioru</translation>
<translation id="8057711352706143257">Oprogramowanie „<ph name="SOFTWARE_NAME" />” nie jest prawidłowo skonfigurowane. Odinstalowanie oprogramowania „<ph name="SOFTWARE_NAME" />” zwykle rozwiązuje problem. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Od tej pory nie musisz podawać kodu zabezpieczającego karty</translation>
<translation id="8066955247577885446">Coś poszło nie tak.</translation>
<translation id="8074253406171541171">10x13 (koperta)</translation>
<translation id="8078141288243656252">Nie można dodawać adnotacji, gdy dokument jest obrócony</translation>
@@ -1348,6 +1368,7 @@ Dodatkowe informacje:
<translation id="8211406090763984747">Połączenie jest bezpieczne</translation>
<translation id="8218327578424803826">Przypisana lokalizacja:</translation>
<translation id="8220146938470311105">C7/C6 (koperta)</translation>
+<translation id="8220639454292072926">Raportowanie w firmie</translation>
<translation id="8225771182978767009">Administrator tego komputera zablokował tę witrynę.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Otwórz stronę w nowej karcie incognito</translation>
@@ -1402,23 +1423,23 @@ Dodatkowe informacje:
<translation id="8508648098325802031">Ikona wyszukiwania</translation>
<translation id="8522552481199248698">Chrome może Ci pomóc w zabezpieczeniu Twojego konta Google i zmianie hasła.</translation>
<translation id="8543181531796978784">Możesz <ph name="BEGIN_ERROR_LINK" />zgłosić problem z wykrywaniem<ph name="END_ERROR_LINK" /> lub – jeśli rozumiesz zagrożenie – <ph name="BEGIN_LINK" />wejść na tę niebezpieczną stronę<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Masz pytania? Skontaktuj się z osobą, która nadzoruje Twój profil.</translation>
<translation id="8553075262323480129">Tłumaczenie nie powiodło się, ponieważ nie można określić języka strony.</translation>
<translation id="8557066899867184262">Kod CVC znajduje się na odwrocie karty.</translation>
<translation id="8559762987265718583">Nie można nawiązać prywatnego połączenia z <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, ponieważ data i godzina (<ph name="DATE_AND_TIME" />) ustawione na urządzeniu są nieprawidłowe.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> podejrzana strona</translation>
<translation id="8564985650692024650">Chromium zaleca zresetowanie hasła, którego używasz w: <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, jeśli zostało użyte na innej stronie.</translation>
<translation id="8571890674111243710">Trwa tłumaczenie strony na język: <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Dodaj numer telefonu</translation>
-<translation id="859285277496340001">Certyfikat nie określa mechanizmu do sprawdzania, czy został on unieważniony.</translation>
<translation id="860043288473659153">Imię i nazwisko posiadacza karty</translation>
<translation id="861775596732816396">Rozmiar 4</translation>
-<translation id="8620436878122366504">Twoi rodzice jeszcze na to nie zezwolili</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Zapisz tę kartę na tym urządzeniu</translation>
<translation id="8626112503828625890">Zapisać szczegóły płatności na koncie Google?</translation>
+<translation id="8647750283161643317">Przywróć wszystkie ustawienia domyślne</translation>
<translation id="8663226718884576429">Podsumowanie zamówienia, <ph name="TOTAL_LABEL" />, Szczegółowe informacje</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, odpowiedź, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Dostępne</translation>
<translation id="8703575177326907206">Połączenie z witryną <ph name="DOMAIN" /> nie jest szyfrowane.</translation>
<translation id="8718314106902482036">Płatność nie została zrealizowana</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, sugestia wyszukiwania</translation>
@@ -1429,6 +1450,7 @@ Dodatkowe informacje:
<translation id="8738058698779197622">Aby nawiązać bezpieczne połączenie, Twój zegar musi mieć ustawioną prawidłową godzinę. Jest to wymagane, ponieważ certyfikaty używane do identyfikacji stron internetowych są ważne tylko przez określony czas. Ponieważ zegar Twojego urządzenia nie jest ustawiony prawidłowo, Chromium nie może zweryfikować tych certyfikatów.</translation>
<translation id="8740359287975076522">Nie znaleziono &lt;abbr id="dnsDefinition"&gt;adresu DNS&lt;/abbr&gt; serwera <ph name="HOST_NAME" />. Diagnozujemy problem.</translation>
<translation id="874846938927089722">Akceptowane karty kredytowe i przedpłacone</translation>
+<translation id="874918643257405732">Dodaj tę kartę do zakładek</translation>
<translation id="8759274551635299824">Ta karta straciła ważność</translation>
<translation id="8761567432415473239">Funkcja Bezpieczne przeglądanie Google ostatnio <ph name="BEGIN_LINK" />znalazła szkodliwe<ph name="END_LINK" /> programy na <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Urządzenie USB</translation>
@@ -1458,6 +1480,7 @@ Dodatkowe informacje:
<translation id="8938939909778640821">Akceptowane karty kredytowe i przedpłacone</translation>
<translation id="8943282376843390568">Limonkowy</translation>
<translation id="8957210676456822347">Autoryzacja portalu przechwytującego</translation>
+<translation id="8962950042226115166">Podejrzana strona</translation>
<translation id="8968766641738584599">Zapisz kartę</translation>
<translation id="8971063699422889582">Ważność certyfikatu serwera wygasła.</translation>
<translation id="8975012916872825179">Obejmuje numery telefonów, adresy e-mail i adresy dostawy</translation>
@@ -1480,24 +1503,24 @@ Dodatkowe informacje:
<translation id="9035022520814077154">Błąd zabezpieczeń</translation>
<translation id="9038649477754266430">Używaj podpowiedzi, by strony ładowały się szybciej</translation>
<translation id="9039213469156557790">Ta strona zawiera także niezabezpieczone zasoby. Podczas przesyłania mogą je wyświetlić inni użytkownicy, a osoby atakujące mogą je zmodyfikować, by zmienić sposób działania strony.</translation>
+<translation id="9044359186343685026">Używaj Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Podjęto próbę nawiązania połączenia z witryną <ph name="DOMAIN" />, jednak serwer przedstawił nieprawidłowy certyfikat.</translation>
<translation id="9050666287014529139">Hasło</translation>
<translation id="9065203028668620118">Edytuj</translation>
<translation id="9065745800631924235">Wyszukiwanie ciągu <ph name="TEXT" /> w historii</translation>
<translation id="9069693763241529744">Zablokowane przez rozszerzenie</translation>
-<translation id="9076283476770535406">Może zawierać treści dla dorosłych</translation>
<translation id="9076630408993835509">Ta przeglądarka nie jest zarządzana przez firmę ani inną organizację. Aktywność na tym urządzeniu może być zarządzana poza Chrome. <ph name="BEGIN_LINK" />Więcej informacji<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Potrzebujemy więcej informacji</translation>
<translation id="9080712759204168376">Podsumowanie zamówienia</translation>
<translation id="9089260154716455634">Zasada „po godzinach”:</translation>
<translation id="9095388113577226029">Więcej języków…</translation>
+<translation id="9098981495403789647">Twój administrator włączył w przeglądarce dostępną w Chrome ochronę przed zagrożeniami dla firm. Ta funkcja ma dostęp do niektórych Twoich danych.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> zazwyczaj używa szyfrowania do ochrony Twoich informacji. Gdy tym razem przeglądarka Chromium próbowała połączyć się ze stroną <ph name="SITE" />, odesłała ona nietypowe i nieprawidłowe dane logowania. Może się tak zdarzyć, gdy pod stronę <ph name="SITE" /> podszywa się osoba atakująca albo gdy ekran logowania do sieci Wi-Fi przerwie połączenie. Twoje informacje są nadal bezpieczne, bo połączenie w Chromium zakończyło się przed wymianą jakichkolwiek danych.</translation>
<translation id="9106062320799175032">Dodaj adres rozliczeniowy</translation>
<translation id="9114524666733003316">Sprawdzam kartę…</translation>
<translation id="9128870381267983090">Połącz z siecią</translation>
<translation id="9137013805542155359">Pokaż tekst oryginalny</translation>
-<translation id="9137248913990643158">Aby użyć tej aplikacji, najpierw uruchom Chrome i zaloguj się w nim.</translation>
<translation id="9141013498910525015">Zarządzaj adresami</translation>
<translation id="9148088599418889305">Wybierz metodę wysyłki</translation>
<translation id="9148507642005240123">&amp;Cofnij edycję</translation>
diff --git a/chromium/components/strings/components_strings_pt-BR.xtb b/chromium/components/strings/components_strings_pt-BR.xtb
index ebd8ed03ad7..d133a99a377 100644
--- a/chromium/components/strings/components_strings_pt-BR.xtb
+++ b/chromium/components/strings/components_strings_pt-BR.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Ficha</translation>
<translation id="1088860948719068836">Adicionar Nome como consta no Cartão</translation>
<translation id="1089439967362294234">Alterar senha</translation>
+<translation id="1096545575934602868">Esse campo não pode ter mais que <ph name="MAX_ITEMS_LIMIT" /> entradas. Todas as outras entradas serão descartadas.</translation>
<translation id="109743633954054152">Gerencie senhas nas configurações do Chrome</translation>
<translation id="1103523840287552314">Sempre traduzir do <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Se esta opção for selecionada, o Chrome armazenará uma cópia do seu cartão neste dispositivo para preenchimento de formulários mais rapidamente.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Acessar uma <ph name="BEGIN_LINK" />cópia em cache<ph name="END_LINK" /> de <ph name="URL" /></translation>
<translation id="1156303062776767266">Você está vendo um arquivo local ou compartilhado</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> encerrou a conexão inesperadamente.</translation>
+<translation id="115926840831309955">Verifique o CVC e tente novamente ou atualize a data de validade</translation>
<translation id="1161325031994447685">Conectar à rede Wi-Fi novamente</translation>
<translation id="1165039591588034296">Erro</translation>
<translation id="1175364870820465910">&amp;Imprimir...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Algum software no seu computador está impedindo o Google Chrome de se conectar com segurança à Web" (somente computadores Windows)</translation>
<translation id="1294154142200295408">Variações de linha de comando</translation>
<translation id="129553762522093515">Recentemente fechadas</translation>
+<translation id="1298536327547837046">Verificação de malware</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Tente limpar os cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Recursos obsoletos</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Pesquisar uma imagem na área de transferência</translation>
<translation id="1323433172918577554">Mostrar mais</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Planilhas Google</translation>
<translation id="1527263332363067270">Aguardando conexão...</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">O site que você tentou acessar parece falso. Os invasores às vezes imitam sites fazendo pequenas alterações quase imperceptíveis no URL.</translation>
<translation id="1531205177818805254">Executivo</translation>
<translation id="1532118530259321453">Essa página diz</translation>
<translation id="153384715582417236">Isso é tudo por enquanto</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">SO</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">O documento é grande demais para receber anotações</translation>
-<translation id="1721312023322545264">É necessário pedir a permissão de <ph name="NAME" /> para visitar este site</translation>
<translation id="1721424275792716183">* Campo obrigatório</translation>
<translation id="1727741090716970331">Adicione um Número de Cartão Válido</translation>
<translation id="1728677426644403582">Você está vendo o código-fonte de uma página da Web.</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Os sites que você visita e o tempo gasto neles</translation>
<translation id="1826516787628120939">Em verificação</translation>
<translation id="1834321415901700177">Este site contém programas perigosos</translation>
+<translation id="1838374766361614909">Limpar pesquisa</translation>
<translation id="1839551713262164453">Falha com erros na validação dos valores da política</translation>
<translation id="1842969606798536927">Pagar</translation>
<translation id="1871208020102129563">O proxy foi configurado para utilizar servidores de proxy fixo e não um URL de script .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Recolher lista</translation>
<translation id="1898423065542865115">Filtragem</translation>
<translation id="1914326953223720820">Serviço Descompactar</translation>
+<translation id="1915697529809968049">Usar o Touch ID em vez do CVC?</translation>
<translation id="1916770123977586577">Para aplicar as configurações atualizadas a este site, recarregue a página</translation>
<translation id="1919345977826869612">Anúncios</translation>
<translation id="1919367280705858090">Receber ajuda com uma mensagem de erro específica</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Favoritos de <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Erro de serialização</translation>
<translation id="1974060860693918893">Avançado</translation>
+<translation id="1974883374937189061">Ajude a melhorar a segurança do Chrome, enviando para o Google <ph name="BEGIN_WHITEPAPER_LINK" />URLs de algumas das páginas que você visitou, informações limitadas do sistema e parte do conteúdo da página<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versão do firmware</translation>
<translation id="1981206234434200693">Limpe os dados do histórico de navegação do Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{e mais um}one{e mais #}other{e mais #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Informe um ano de validade válido</translation>
<translation id="2212735316055980242">Política não encontrada</translation>
<translation id="2213606439339815911">Buscando entradas...</translation>
+<translation id="2215727959747642672">Edição de arquivo</translation>
<translation id="2218879909401188352">Os invasores que estão em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> no momento podem instalar apps perigosos que danificam seu dispositivo, acrescentam cobranças ocultas junto à operadora ou roubam suas informações pessoais. <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Sem Internet</translation>
<translation id="2230458221926704099">Corrija sua conexão usando o <ph name="BEGIN_LINK" />app de diagnóstico<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Enviar agora</translation>
+<translation id="2248949050832152960">Usar WebAuthn</translation>
<translation id="225207911366869382">Este valor está obsoleto para esta política.</translation>
<translation id="2257315177824333709">Não é possível salvar este cartão no momento</translation>
<translation id="2262243747453050782">Erro HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL de pesquisa inválido.</translation>
<translation id="2482878487686419369">Notificações</translation>
<translation id="248348093745724435">Políticas do computador</translation>
-<translation id="2485387744899240041">Nomes de usuário para seu dispositivo e navegador</translation>
<translation id="2491120439723279231">O certificado do servidor contém erros.</translation>
<translation id="2493640343870896922">Letter Plus</translation>
<translation id="2495083838625180221">Analisador JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Voltar</translation>
<translation id="2503184589641749290">Cartões de débito e pré-pagos aceitos</translation>
<translation id="2505268675989099013">Proteger conta</translation>
+<translation id="2515335152965840738">IGNORAR</translation>
<translation id="2515629240566999685">Verificar o sinal na sua área</translation>
<translation id="2523886232349826891">Salvo apenas neste dispositivo</translation>
<translation id="2524461107774643265">Adicione Mais Informações</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Enviar</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nenhuma}=1{1 senha (para <ph name="DOMAIN_LIST" />)}=2{2 senhas (para <ph name="DOMAIN_LIST" />)}one{# senha (para <ph name="DOMAIN_LIST" />)}other{# senhas (para <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Fechar outras guias ou apps</translation>
-<translation id="267371737713284912">pressione <ph name="MODIFIER_KEY_DESCRIPTION" /> para desfazer</translation>
<translation id="2674170444375937751">Tem certeza que quer excluir essas páginas do seu histórico?</translation>
<translation id="2676271551327853224">8K 273 mm x 394 mm</translation>
<translation id="2677748264148917807">Sair</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">O valor não corresponde ao formato.</translation>
<translation id="2705137772291741111">Não foi possível ler a cópia armazenada em cache deste site.</translation>
<translation id="2709516037105925701">Preenchimento automático</translation>
-<translation id="2712173769900027643">Pedir permissão</translation>
<translation id="2713444072780614174">Branco</translation>
<translation id="2720342946869265578">Por perto</translation>
<translation id="2721148159707890343">Solicitação bem-sucedida</translation>
<translation id="2728127805433021124">O certificado do servidor é assinado com um algoritmo de assinatura fraco.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Executar o Diagnóstico de Conectividade<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ativando esses recursos, você pode perder dados do navegador ou comprometer sua segurança ou privacidade. Os recursos ativados se aplicam a todos os usuários desse navegador.</translation>
<translation id="2735043616039983645">Há mais de uma fonte com valores conflitantes para esta política.</translation>
<translation id="2738330467931008676">Escolher endereço de retirada</translation>
<translation id="2740531572673183784">Ok</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">A conexão foi redefinida.</translation>
<translation id="2788784517760473862">Cartões de crédito aceitos</translation>
<translation id="2792012897584536778">Os administradores deste dispositivo configuraram certificados de segurança que podem permitir que eles vejam o conteúdo dos sites que você visita.</translation>
-<translation id="2794233252405721443">Site bloqueado</translation>
<translation id="2799020568854403057">O site a seguir contém apps prejudiciais</translation>
<translation id="2799223571221894425">Reiniciar</translation>
<translation id="2803306138276472711">A Navegação segura do Google recentemente <ph name="BEGIN_LINK" />detectou malware<ph name="END_LINK" /> em <ph name="SITE" />. Websites que geralmente são seguros, algumas vezes, são infetados com malware.</translation>
+<translation id="2815364696811431560">SAIR DO SITE</translation>
<translation id="2824775600643448204">Barra de endereço e de pesquisa</translation>
<translation id="2826760142808435982">A conexão foi criptografada e autenticada utilizando <ph name="CIPHER" /> e usa <ph name="KX" /> como o mecanismo de troca de chave.</translation>
<translation id="2835170189407361413">Limpar formulário</translation>
<translation id="2847118875340931228">Abrir janela anônima</translation>
<translation id="2850739647070081192">Convite (Envelope)</translation>
-<translation id="2851634818064021665">Você precisa de permissão para visitar este site</translation>
<translation id="2856444702002559011">Invasores podem estar tentando roubar suas informações de <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (por exemplo, senhas, mensagens ou cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Salvar cartão?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Se esta opção for ativada, o Chromium armazenará uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="2985398929374701810">Informe um endereço válido</translation>
<translation id="2986368408720340940">Esse método de retirada não está disponível. Tente um método diferente.</translation>
+<translation id="2987034854559945715">Nenhum recurso correspondente</translation>
<translation id="2991174974383378012">Compartilhar com websites</translation>
<translation id="2991571918955627853">Você não pode visitar <ph name="SITE" /> agora, porque o site usa HSTS. Erros de rede e ataques são geralmente temporários. Esta página provavelmente funcionará mais tarde.</translation>
<translation id="3005723025932146533">Mostrar cópia salva</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Tipo de política incorreto</translation>
<translation id="3037605927509011580">Ah, não!</translation>
<translation id="3041612393474885105">Informações do certificado</translation>
+<translation id="3057676462092457419">O modo DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> ainda não é compatível, o modo foi definido como <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Aplicar patch ao serviço</translation>
<translation id="3064966200440839136">Saindo do modo de navegação anônima para pagar usando um aplicativo externo. Continuar?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> em <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pagamento</translation>
<translation id="3207960819495026254">Adicionado aos favoritos</translation>
+<translation id="3209034400446768650">Esta página pode emitir cobranças em dinheiro</translation>
<translation id="3225919329040284222">O servidor apresentou um certificado que não coincide com as expectativas incorporadas. Estas expectativas são incluídas para determinados websites de alta segurança com a finalidade de oferecer proteção a você.</translation>
<translation id="3226128629678568754">Pressione o botão "Atualizar" para reenviar os dados necessários para carregar a página.</translation>
<translation id="3227137524299004712">Microfone</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">Informações sobre a versão do seu dispositivo e navegador</translation>
<translation id="323107829343500871">Digite o CVC do <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Sempre detectar conteúdo importante neste site</translation>
-<translation id="3254409185687681395">Adicionar esta página aos favoritos</translation>
<translation id="3270847123878663523">&amp;Desfazer reordenar</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Adicionar nome (como consta no cartão)</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">Adicionar endereço de faturamento</translation>
<translation id="3324983252691184275">Carmim</translation>
<translation id="3338095232262050444">Seguro</translation>
-<translation id="3345135638360864351">Não foi possível enviar sua solicitação a <ph name="NAME" /> para acessar este site. Tente novamente.</translation>
<translation id="3355823806454867987">Alterar configurações de proxy...</translation>
<translation id="3361596688432910856">O Chrome <ph name="BEGIN_EMPHASIS" />não salvará<ph name="END_EMPHASIS" /> as seguintes informações:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">Ocultar detalhes</translation>
<translation id="3467763166455606212">O nome do titular do cartão é obrigatório</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> está aberta. Pressione Tab e depois Enter para alternar para a guia aberta</translation>
-<translation id="3479539252931486093">Isso foi inesperado? <ph name="BEGIN_LINK" />Informe-nos<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Não agora</translation>
<translation id="3484560055331845446">Você pode perder o acesso à sua Conta do Google. O Chrome recomenda que sua senha seja alterada agora. Solicitaremos que você faça login.</translation>
<translation id="3495081129428749620">Encontrar na página
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Não foi possível contatar seu pai/mãe no momento. Tente novamente.</translation>
<translation id="3512163584740124171">Esta política é ignorada porque outra política do mesmo grupo tem uma prioridade mais alta.</translation>
<translation id="3528171143076753409">O certificado do servidor não é confiável.</translation>
<translation id="3528485271872257980">Marrom-escuro</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Pelo menos 1 item em dispositivos sincronizados}=1{1 item (e mais em dispositivos sincronizados)}one{# item (e mais em dispositivos sincronizados)}other{# itens (e mais em dispositivos sincronizados)}}</translation>
<translation id="3539171420378717834">Manter uma cópia deste cartão neste dispositivo</translation>
-<translation id="3556433843310711081">Seu administrador pode desbloqueá-lo para você</translation>
<translation id="3566021033012934673">Sua conexão não é particular</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Uma página incorporada em <ph name="SITE" /> diz</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">Abrir página em uma nova janela anônima (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Relatório de erros registrado em <ph name="CRASH_TIME" />, enviado em <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informações do certificado</translation>
+<translation id="3701427423622901115">Redefinição confirmada.</translation>
<translation id="3704162925118123524">A rede que você está usando pode exigir que você visite a página de login.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Carregando...</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805">Invasores em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem levar você a fazer algo perigoso, como instalar software ou revelar suas informações pessoais (por exemplo, senhas, números de telefone ou cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">A tradução falhou devido a um erro no servidor.</translation>
<translation id="3759461132968374835">Você não relatou falhas recentemente. As falhas que ocorreram quando o relatório de erros estava desativado não aparecerão aqui.</translation>
+<translation id="3760561303380396507">Usar o Windows Hello em vez do CVC?</translation>
<translation id="3761718714832595332">Ocultar status</translation>
<translation id="3765032636089507299">A página de navegação segura está em construção.</translation>
<translation id="3778403066972421603">Quer salvar este cartão na sua Conta do Google e neste dispositivo?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">Tamanho 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Conteúdo nocivo bloqueado.</translation>
+<translation id="3808375843007691220">Aviso: recursos experimentais à vista!</translation>
<translation id="3810973564298564668">Gerenciar</translation>
<translation id="382518646247711829">Se você usa um servidor proxy...</translation>
<translation id="3828924085048779000">Uma senha vazia não é permitida.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">Atualizar data e hora</translation>
<translation id="3884278016824448484">Identificador de dispositivo em conflito</translation>
<translation id="3885155851504623709">Município</translation>
-<translation id="3886446263141354045">Sua solicitação para acessar este site foi enviada para <ph name="NAME" /></translation>
<translation id="3890664840433101773">Adicionar e-mail</translation>
<translation id="3901925938762663762">O cartão expirou</translation>
<translation id="3906600011954732550">B5 Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Usar WebAuthn em vez de CVC?</translation>
<translation id="3946209740501886391">Sempre perguntar neste site</translation>
<translation id="3949571496842715403">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança dele não especifica a extensão Nomes alternativos do requerente. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
<translation id="3949601375789751990">Seu histórico de navegação aparece aqui</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nenhum}=1{1 site }one{# site }other{# sites }}</translation>
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> está bloqueado</translation>
+<translation id="3981540111851280311">O domínio <ph name="ENROLLMENT_DOMAIN" /> ativou o serviço de proteção contra ameaças do Chrome Enterprise no seu navegador. Esse serviço tem acesso a parte dos seus dados.</translation>
<translation id="3987940399970879459">Menos de 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 página da Web por perto}one{# página da Web por perto}other{# páginas da Web por perto}}</translation>
<translation id="4030383055268325496">&amp;Desfazer adicionar</translation>
<translation id="4032320456957708163">Seu navegador é gerenciado por <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">O link aberto leva a um site que você não costuma visitar. Pode ser uma tentativa de confundir você.</translation>
<translation id="4058922952496707368">Chave "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Adicione um Endereço Válido</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">O número de série do dispositivo é inválido</translation>
<translation id="410351446219883937">Reprodução automática</translation>
<translation id="4103763322291513355">Visite &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver a lista de URLs adicionados à lista de proibições e outras políticas aplicadas pelo administrador do seu sistema.</translation>
+<translation id="4108231218301530806">Usar impressão digital para verificar o cartão na próxima vez.</translation>
<translation id="4110652170750985508">Analisar seu pagamento</translation>
<translation id="4112140312785995938">Retroceder</translation>
<translation id="4116663294526079822">Sempre permitir neste site</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">Assinatura de verificação inválida</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Mais <ph name="ITEM_COUNT" /> item}one{Mais <ph name="ITEM_COUNT" /> item}other{Mais <ph name="ITEM_COUNT" /> itens}}</translation>
+<translation id="4176463684765177261">Desativado</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" />: <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Para agilizar o próximo pagamento, adicione seu cartão e endereço de faturamento à sua Conta do Google.</translation>
<translation id="4196861286325780578">&amp;Refazer mover</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">Redefinir senha</translation>
<translation id="4279811152705618813">Seu <ph name="DEVICE_TYPE" /> é gerenciado por <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Esse cartão foi adicionado à sua Conta do Google}one{Esse cartão foi adicionado à sua Conta do Google}other{Esses cartões foram adicionados à sua Conta do Google}}</translation>
+<translation id="428847186335018806">Verifica os arquivos dos quais você faz o download ou upload no Chrome.</translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Alternar</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">Postal</translation>
<translation id="443673843213245140">O uso de um proxy está desativado, mas uma configuração explícita de proxy é especificada.</translation>
<translation id="445100540951337728">Cartões de débito aceitos</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> comportamento suspeito</translation>
<translation id="4466881336512663640">As alterações no formulário serão perdidas. Tem certeza de que quer continuar?</translation>
<translation id="4477350412780666475">Próxima faixa</translation>
<translation id="4482953324121162758">Este site não será traduzido.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">&amp;Desfazer exclusão</translation>
<translation id="4597348597567598915">Tamanho 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Recursos de pesquisa</translation>
<translation id="4646534391647090355">Acessar agora</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança contém erros. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Arch A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">A conexão foi interrompida</translation>
-<translation id="471880041731876836">Você não tem permissão para visitar este site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar o Diagnóstico de Rede do Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Atualizar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">Ajustar à página</translation>
<translation id="4850886885716139402">Visualizar</translation>
<translation id="4854362297993841467">Esse método de entrega não está disponível. Tente um método diferente.</translation>
-<translation id="4858792381671956233">Você perguntou aos seus responsáveis se pode visitar este site</translation>
<translation id="4864052566555297930">Dica de segurança:</translation>
<translation id="4876188919622883022">Visualização simplificada</translation>
<translation id="4876305945144899064">Sem nome de usuário</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">Reativar avisos</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Ver tudo</translation>
+<translation id="4989542687859782284">Indisponível</translation>
<translation id="4989809363548539747">Este plug-in não é compatível</translation>
+<translation id="4995216769782533993">Confirme o código de segurança para compartilhar os detalhes do seu cartão com este site</translation>
<translation id="5002932099480077015">Se ativado, o Chrome armazenará uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="5015510746216210676">Nome do computador:</translation>
<translation id="5017554619425969104">Texto que você copiou</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">64 bits</translation>
<translation id="5125394840236832993">B Plus</translation>
+<translation id="5126510351761255129">Verificar seu cartão</translation>
<translation id="5135404736266831032">Gerenciar endereços…</translation>
<translation id="5138227688689900538">Mostrar menos</translation>
<translation id="5141240743006678641">Criptografar senhas sincronizadas com suas credenciais do Google</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">Nuvem</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Recursos aplicáveis a todo o sistema só podem ser definidos pelo proprietário: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Aviso: esta política não foi mesclada conforme especificado na PolicyDictionaryMultipleSourceMergeList porque ela não faz parte das políticas de dicionário que podem ser mescladas.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Fim</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">Falha ao armazenar as configurações da política</translation>
<translation id="5371425731340848620">Atualizar cartão</translation>
<translation id="5377026284221673050">"Seu relógio está atrasado", "Seu relógio está adiantado" ou "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Esta página pode tentar enganar você, roubar suas informações pessoais ou prejudicar seu dispositivo. Tenha cuidado ao inserir informações pessoais ou abrir arquivos transferidos por download.</translation>
<translation id="5384855140246857529">Para usar seus cartões em todos os dispositivos, faça login e ative a sincronização.</translation>
<translation id="5386426401304769735">A cadeia de certificados desse site contém um certificado assinado usando SHA-1.</translation>
<translation id="538659543871111977">A4 Tab</translation>
@@ -840,6 +852,7 @@
<translation id="5457113250005438886">Inválidos</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Refazer editar</translation>
+<translation id="5473728911100096288">Ativando essas opções, você usará recursos obsoletos que desaparecerão em versões futuras.</translation>
<translation id="5478437291406423475">Envelope 125 mm x 324 mm</translation>
<translation id="5481076368049295676">Este conteúdo pode tentar instalar softwares perigosos no seu dispositivo que roubam ou excluem suas informações. <ph name="BEGIN_LINK" />Mostrar mesmo assim<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Adicionar endereço válido</translation>
@@ -863,7 +876,6 @@
<translation id="5570825185877910964">Proteger conta</translation>
<translation id="5571083550517324815">Não é possível fazer a retirada nesse endereço. Tente um endereço diferente.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 em uso}one{# em uso}other{# em uso}})</translation>
-<translation id="5572851009514199876">Inicie e faça login no Chrome para que ele possa verificar se você tem permissão para acessar este site.</translation>
<translation id="5580958916614886209">Verifique o mês de validade e tente novamente</translation>
<translation id="5586446728396275693">Nenhum endereço salvo</translation>
<translation id="5595485650161345191">Editar endereço</translation>
@@ -871,6 +883,7 @@
<translation id="560412284261940334">Gerenciamento não suportado</translation>
<translation id="5605670050355397069">Tabloide</translation>
<translation id="5607240918979444548">Arch C</translation>
+<translation id="5608165884683734521">Este site pode ser falso ou conter fraude. O Chrome recomenda sair imediatamente.</translation>
<translation id="5610142619324316209">Verificar a conexão</translation>
<translation id="5610807607761827392">É possível gerenciar cartões e endereços em <ph name="BEGIN_LINK" />Configurações<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Redirecionamento em excesso por <ph name="HOST_NAME" /></translation>
@@ -894,11 +907,11 @@
<translation id="5720705177508910913">Usuário atual</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">O Chrome recomenda redefinir sua senha se você a reutilizou em outros sites.</translation>
-<translation id="5732392974455271431">Seus responsáveis podem desbloqueá-lo para você</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Salvar cartão na Conta do Google}one{Salvar cartão na Conta do Google}other{Salvar cartões na Conta do Google}}</translation>
<translation id="5763042198335101085">Informe um endereço de e-mail válido.</translation>
<translation id="5765072501007116331">Para ver métodos e requisitos de entrega, selecione um endereço</translation>
<translation id="5778550464785688721">Controle total de dispositivos MIDI</translation>
+<translation id="5781136890105823427">Experimento ativado</translation>
<translation id="578305955206182703">Âmbar</translation>
<translation id="57838592816432529">Desativar som</translation>
<translation id="5784606427469807560">Ocorreu um problema ao confirmar seu cartão. Verifique a conexão com a Internet e tente novamente.</translation>
@@ -915,13 +928,16 @@
<translation id="5860033963881614850">Desativado</translation>
<translation id="5863847714970149516">A página que você está prestes a acessar pode tentar cobrar pagamentos</translation>
<translation id="5866257070973731571">Adicione um Número de Telefone</translation>
+<translation id="5866898949289125849">Você está vendo uma página de ferramentas para desenvolvedores</translation>
<translation id="5869405914158311789">Não é possível acessar esse site</translation>
<translation id="5869522115854928033">Senhas salvas</translation>
<translation id="5887400589839399685">Cartão salvo</translation>
<translation id="5893752035575986141">Cartões de crédito são aceitos.</translation>
+<translation id="5895138241574237353">Reiniciar</translation>
<translation id="5901630391730855834">Amarelo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizado)</translation>
<translation id="5916664084637901428">Ativado</translation>
+<translation id="59174027418879706">Ativado</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Salvar cartão na Conta do Google?</translation>
<translation id="5922853866070715753">Quase pronto</translation>
@@ -955,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Usar seus cartões em todos os dispositivos?</translation>
<translation id="6059925163896151826">Dispositivos USB</translation>
+<translation id="6060009363608157444">Modo DnsOverHttps inválido.</translation>
<translation id="6080696365213338172">Você acessou conteúdo usando um certificado fornecido pelo administrador. Os dados fornecidos a <ph name="DOMAIN" /> podem ser interceptados por seu administrador.</translation>
<translation id="6094273045989040137">Anotar</translation>
<translation id="610911394827799129">Sua Conta do Google pode ter outras formas de histórico de navegação em <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1020,12 @@
<translation id="6404511346730675251">Editar favorito</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Digite a data de validade e o CVC do <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Você perguntou ao seu responsável se pode visitar este site</translation>
<translation id="6415778972515849510">No Chromium, você pode receber ajuda para proteger sua Conta do Google e alterar sua senha.</translation>
-<translation id="6417515091412812850">Não foi possível verificar se o certificado foi revogado</translation>
<translation id="6431585503458005759">Não armazenar</translation>
<translation id="6433490469411711332">Editar informações de contato</translation>
<translation id="6433595998831338502">A conexão com <ph name="HOST_NAME" /> foi recusada.</translation>
<translation id="6434309073475700221">Descartar</translation>
+<translation id="6435221585574090192">Compartilhe os dados sobre ocorrências de segurança sinalizadas pelo serviço de proteção contra ameaças do Chrome Enterprise com seu administrador. Isso pode incluir URLs de páginas, nomes e metadados de arquivos, o nome de usuário do dispositivo e seu nome de usuário do Chrome.</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Adicionar mais informações</translation>
@@ -1018,20 +1034,19 @@
<translation id="6465306955648956876">Gerenciar senhas…</translation>
<translation id="647261751007945333">Políticas de dispositivos</translation>
<translation id="6476284679642588870">Gerenciar formas de pagamento</translation>
-<translation id="6477321094435799029">O Chrome detectou um código incomum nesta página e a bloqueou para proteger suas informações pessoais (por exemplo, senhas, números de telefone e cartões de crédito).</translation>
<translation id="6489534406876378309">Iniciar upload de falhas</translation>
<translation id="6499038740797743453">Redefinir senha?</translation>
<translation id="6507833130742554667">Cartões de crédito e débito são aceitos.</translation>
<translation id="650855688985305916">Sim, armazenar</translation>
<translation id="6508722015517270189">Reiniciar o Chrome</translation>
<translation id="6517596291481585650">Aviso: esta política não foi mesclada como uma lista conforme especificado porque ela não é uma lista.</translation>
+<translation id="6518133107902771759">Confirmar</translation>
<translation id="6521745193039995384">não ativa</translation>
<translation id="6529602333819889595">&amp;Refazer excluir</translation>
<translation id="6534179046333460208">Sugestões da Web física</translation>
<translation id="6545864417968258051">Verificação de Bluetooth</translation>
<translation id="6554795675067793129">Sua conta é gerenciada por <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Refazer</translation>
-<translation id="6563469144985748109">Seu administrador ainda não o aprovou</translation>
<translation id="6569060085658103619">Você está vendo uma página de extensões</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Rosa-claro</translation>
@@ -1049,11 +1064,13 @@
<translation id="6643016212128521049">Limpar</translation>
<translation id="6644283850729428850">Esta política foi encerrada.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nenhum}=1{De 1 site (você não será desconectado da sua Conta do Google)}one{De # site (você não será desconectado da sua Conta do Google)}other{De # sites (você não será desconectado da sua Conta do Google)}}</translation>
+<translation id="6652101503459149953">Usar Windows Hello</translation>
<translation id="6657585470893396449">Senha</translation>
<translation id="6670613747977017428">Voltar à segurança.</translation>
<translation id="6671697161687535275">Remover sugestão de formulário do Chromium?</translation>
<translation id="6685834062052613830">Saia e conclua a configuração</translation>
<translation id="6689271823431384964">A opção de salvar seus cartões na Conta do Google está disponível no Chrome porque você fez login. É possível alterar esse comportamento nas configurações. O nome do titular do cartão vem da sua conta.</translation>
+<translation id="6707256370811247129">Verifique o conteúdo de cache e arquivos dos quais você faz o download ou upload no Chrome.</translation>
<translation id="6710213216561001401">Anterior</translation>
<translation id="6710594484020273272">&lt;Digitar termo de pesquisa&gt;</translation>
<translation id="671076103358959139">Token de inscrição:</translation>
@@ -1061,10 +1078,10 @@
<translation id="6738516213925468394">Seus dados foram criptografados com sua <ph name="BEGIN_LINK" />senha longa de sincronização<ph name="END_LINK" /> em <ph name="TIME" />. Digite-a para iniciar a sincronização.</translation>
<translation id="674375294223700098">Erro, certificado de servidor desconhecido.</translation>
<translation id="6744009308914054259">Enquanto espera por uma conexão, acesse "Downloads" para ler artigos off-line.</translation>
+<translation id="6747611005629681221">Alerta: recursos obsoletos à vista!</translation>
<translation id="6753269504797312559">Valor da política</translation>
<translation id="6757797048963528358">O dispositivo entrou em modo de suspensão.</translation>
<translation id="6768213884286397650">Hagaki (Postal)</translation>
-<translation id="6778737459546443941">Seu responsável ainda não o aprovou</translation>
<translation id="67862343314499040">Violeta</translation>
<translation id="6786747875388722282">Extensões</translation>
<translation id="6790428901817661496">Reproduzir</translation>
@@ -1072,6 +1089,7 @@
<translation id="681021252041861472">Campo obrigatório</translation>
<translation id="6810899417690483278">Código de personalização</translation>
<translation id="6825578344716086703">Você tentou acessar <ph name="DOMAIN" />, mas o servidor apresentou um certificado assinado com um algoritmo de assinatura fraco (como SHA-1). Isso significa que as credenciais de segurança apresentadas pelo servidor podem ter sido forjadas, e talvez o servidor não seja o esperado (talvez você esteja se comunicando com um invasor).</translation>
+<translation id="6826370046007623921">Prevenção contra perda de dados</translation>
<translation id="6831043979455480757">Traduzir</translation>
<translation id="6839929833149231406">Área</translation>
<translation id="6852204201400771460">Recarregar app?</translation>
@@ -1084,7 +1102,6 @@
<translation id="6891596781022320156">O nível da política não é suportado.</translation>
<translation id="6895330447102777224">Seu cartão foi confirmado</translation>
<translation id="6897140037006041989">Agente do usuário</translation>
-<translation id="6903319715792422884">Ajudar a melhorar o recurso "Navegação segura" enviando algumas <ph name="BEGIN_WHITEPAPER_LINK" />informações do sistema e conteúdo da página<ph name="END_WHITEPAPER_LINK" /> para o Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuário:</translation>
<translation id="6934672428414710184">Este nome é da sua Conta do Google</translation>
<translation id="6944692733090228304">Você inseriu sua senha em um site que não é gerenciado por <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para proteger sua conta, não reutilize sua senha em outros apps e sites.</translation>
@@ -1129,6 +1146,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavanda</translation>
<translation id="717330890047184534">Código Gaia:</translation>
+<translation id="7174545416324379297">Mescla</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">O servidor que você acessará, <ph name="ORIGIN" />, solicitou que
uma política de segurança seja aplicada a todas as solicitações. Porém, em vez de
@@ -1166,6 +1184,7 @@ Mais detalhes:
<translation id="7320336641823683070">Ajuda de conexão</translation>
<translation id="733354035281974745">Substituição de conta local do dispositivo</translation>
<translation id="7334320624316649418">&amp;Refazer reordenar</translation>
+<translation id="7337706099755338005">Não está disponível na sua plataforma.</translation>
<translation id="733923710415886693">O certificado do servidor não foi divulgado por meio da Transparência dos certificados.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">O usuário é afiliado:</translation>
@@ -1197,7 +1216,6 @@ Mais detalhes:
<translation id="7440140511386898319">Ver conteúdo enquanto estiver off-line</translation>
<translation id="7441627299479586546">Assunto da política incorreto</translation>
<translation id="7442725080345379071">Laranja-claro</translation>
-<translation id="7444046173054089907">Este site está bloqueado</translation>
<translation id="7445762425076701745">A identidade do servidor ao qual você está conectado não pode ser validada completamente. Você está conectado ao servidor com um nome válido somente na sua rede e que, portanto, uma autoridade de certificação externa não consegue validar a propriedade. Como algumas autoridades de certificação emitem certificados para esses nomes mesmo assim, não é possível garantir que você esteja conectado ao site que gostaria e não a um invasor.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Saber mais<ph name="END_LINK" /> sobre esse problema.</translation>
<translation id="7455133967321480974">Usar padrão global (Bloquear)</translation>
@@ -1219,9 +1237,9 @@ Mais detalhes:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Depois da confirmação, os detalhes do cartão serão compartilhados com esse site.</translation>
<translation id="7542995811387359312">O preenchimento automático do cartão de crédito está desativado porque este formulário não usa uma conexão segura.</translation>
-<translation id="7543525346216957623">Peça para seu responsável</translation>
<translation id="7548892272833184391">Corrigir erros de conexão</translation>
<translation id="7549584377607005141">Esta página da Web requer os dados inseridos anteriormente para ser exibida de modo correto. É possível enviá-los novamente mas, ao fazer isso, você repete qualquer ação realizada anteriormente na página.</translation>
+<translation id="7550637293666041147">O nome de usuário no dispositivo e seu nome de usuário do Chrome</translation>
<translation id="7552846755917812628">Tente seguir estas dicas:</translation>
<translation id="7554791636758816595">Nova guia</translation>
<translation id="7564049878696755256">Você pode perder o acesso à sua conta de <ph name="ORG_NAME" /> ou ter sua identidade roubada. O Chrome recomenda que sua senha seja alterada agora.</translation>
@@ -1236,6 +1254,7 @@ Mais detalhes:
<translation id="7610193165460212391">O valor não corresponde ao período <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Data de expiração: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Você já possui dados criptografados utilizando uma versão diferente de sua senha para a Conta do Google. Digite-a abaixo.</translation>
+<translation id="7625784245512586808">Serviço de proteção contra ameaças do Chrome Enterprise</translation>
<translation id="7633909222644580952">Dados de desempenho e relatórios de erros</translation>
<translation id="7637571805876720304">Remover cartão de crédito do Chromium?</translation>
<translation id="7638605456503525968">Portas seriais</translation>
@@ -1248,7 +1267,6 @@ Mais detalhes:
<translation id="7668654391829183341">Dispositivo desconhecido</translation>
<translation id="7669271284792375604">Invasores nesse site podem tentar enganar você para que instale programas que prejudicam sua experiência de navegação (por exemplo, alterando sua página inicial ou mostrando mais anúncios nos sites que você visita).</translation>
<translation id="7676643023259824263">Pesquisar um texto na área de transferência, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Plataforma e nuvem</translation>
<translation id="7681101578153515023">Alterar mecanismo de pesquisa</translation>
<translation id="7682287625158474539">Entrega</translation>
<translation id="7687186412095877299">Preencher formulários com suas formas de pagamento salvas</translation>
@@ -1263,7 +1281,6 @@ Mais detalhes:
<translation id="7723047071702270851">Edite o Cartão</translation>
<translation id="774634243536837715">Conteúdo perigoso bloqueado.</translation>
<translation id="7752995774971033316">Não gerenciado</translation>
-<translation id="7755287808199759310">Seu responsável pode desbloqueá-lo para você</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">É possível que o software antivírus ou o firewall tenha bloqueado a conexão.</translation>
<translation id="7759163816903619567">Domínio de exibição:</translation>
@@ -1307,7 +1324,6 @@ Mais detalhes:
<translation id="8004582292198964060">Navegador</translation>
<translation id="8009225694047762179">Gerenciar senha</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Este cartão e o endereço de faturamento dele serão salvos. Você poderá usá-lo quando a conta <ph name="USER_EMAIL" /> estiver conectada.}one{Este cartão e o endereço de faturamento dele serão salvos. Você poderá usá-lo quando a conta <ph name="USER_EMAIL" /> estiver conectada.}other{Estes cartões e os endereços de faturamento deles serão salvos. Você poderá usá-los quando a conta <ph name="USER_EMAIL" /> estiver conectada.}}</translation>
-<translation id="8012647001091218357">Não foi possível contatar seus pais. Tente novamente.</translation>
<translation id="8025119109950072390">Invasores nesse site podem induzir você a fazer algo perigoso, como instalar um software ou revelar suas informações pessoais (por exemplo, senhas, números de telefone ou cartões de crédito).</translation>
<translation id="8034522405403831421">Esta página está escrita em <ph name="SOURCE_LANGUAGE" />. Traduzi-la para <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Caneta</translation>
@@ -1318,6 +1334,7 @@ Mais detalhes:
<translation id="8041940743680923270">Usar padrão global (Perguntar)</translation>
<translation id="8042918947222776840">Escolher método de retirada</translation>
<translation id="8057711352706143257">O software "<ph name="SOFTWARE_NAME" />" não foi configurado corretamente. A desinstalação do "<ph name="SOFTWARE_NAME" />" costuma resolver o problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Não será necessário inserir o código de segurança do cartão a partir de agora</translation>
<translation id="8066955247577885446">Algo deu errado.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Não é possível fazer anotações em documentos girados</translation>
@@ -1348,6 +1365,7 @@ Mais detalhes:
<translation id="8211406090763984747">A conexão é segura</translation>
<translation id="8218327578424803826">Local designado:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Relatório para empresas</translation>
<translation id="8225771182978767009">A pessoa que configurou este computador optou por bloquear esse site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Abrir página em uma nova guia anônima</translation>
@@ -1402,24 +1420,24 @@ Mais detalhes:
<translation id="8508648098325802031">Ícone de pesquisa</translation>
<translation id="8522552481199248698">No Chrome, você pode receber ajuda para proteger sua Conta do Google e alterar sua senha.</translation>
<translation id="8543181531796978784">Você pode <ph name="BEGIN_ERROR_LINK" />denunciar um problema de detecção<ph name="END_ERROR_LINK" /> ou, se entende os riscos à sua segurança, <ph name="BEGIN_LINK" />acessar este site não seguro<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Dúvidas? Entre em contato com a pessoa que supervisiona seu perfil.</translation>
<translation id="8553075262323480129">A tradução falhou porque não foi possível determinar o idioma da página.</translation>
<translation id="8557066899867184262">O CVC está localizado atrás do seu cartão.</translation>
<translation id="8559762987265718583">Não é possível estabelecer uma conexão privada com <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, porque a data e a hora do seu dispositivo (<ph name="DATE_AND_TIME" />) estão incorretas.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> site suspeito</translation>
<translation id="8564985650692024650">O Chromium recomenda redefinir sua senha de <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> se você a reutilizou em outros sites.</translation>
<translation id="8571890674111243710">Traduzindo página para <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Ad. nº. telefone
</translation>
-<translation id="859285277496340001">O certificado não especifica um mecanismo para verificar se ele foi revogado.</translation>
<translation id="860043288473659153">Nome do titular do cartão</translation>
<translation id="861775596732816396">Tamanho 4</translation>
-<translation id="8620436878122366504">Seus responsáveis ainda não o aprovaram</translation>
<translation id="8622948367223941507">Legal extra</translation>
<translation id="8625384913736129811">Salvar este cartão neste dispositivo</translation>
<translation id="8626112503828625890">Armazenar detalhes de faturamento na Conta do Google?</translation>
+<translation id="8647750283161643317">Redefinir tudo para o padrão</translation>
<translation id="8663226718884576429">Resumo do pedido, <ph name="TOTAL_LABEL" />, Mais detalhes</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, resposta, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponível</translation>
<translation id="8703575177326907206">Sua conexão com <ph name="DOMAIN" /> não está criptografada.</translation>
<translation id="8718314106902482036">Pagamento não concluído</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, sugestão de pesquisa</translation>
@@ -1430,6 +1448,7 @@ Mais detalhes:
<translation id="8738058698779197622">Para estabelecer uma conexão segura, o relógio precisa ser ajustado corretamente. Isso ocorre porque os certificados que os websites usam para se identificar são válidos apenas por períodos específicos. Como o relógio do seu dispositivo está incorreto, o Chromium não pode verificar esses certificados.</translation>
<translation id="8740359287975076522">Não foi possível encontrar o &lt;abbr id="dnsDefinition"&gt;endereço DNS&lt;/abbr&gt; de <ph name="HOST_NAME" />. Diagnosticando o problema.</translation>
<translation id="874846938927089722">Cartões de crédito e pré-pagos aceitos</translation>
+<translation id="874918643257405732">Adicionar esta guia aos favoritos</translation>
<translation id="8759274551635299824">Este cartão expirou</translation>
<translation id="8761567432415473239">Recentemente, a Navegação Segura do Google <ph name="BEGIN_LINK" />encontrou programas nocivos<ph name="END_LINK" /> no site <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispositivo USB</translation>
@@ -1459,6 +1478,7 @@ Mais detalhes:
<translation id="8938939909778640821">Cartões de crédito e pré-pagos aceitos</translation>
<translation id="8943282376843390568">Verde-limão</translation>
<translation id="8957210676456822347">Autorização de portal cativo</translation>
+<translation id="8962950042226115166">Site suspeito</translation>
<translation id="8968766641738584599">Salvar cartão</translation>
<translation id="8971063699422889582">O certificado do servidor expirou.</translation>
<translation id="8975012916872825179">Inclui informações como números de telefone, endereços de e-mail e endereços de entrega</translation>
@@ -1481,25 +1501,25 @@ Mais detalhes:
<translation id="9035022520814077154">Erro de segurança</translation>
<translation id="9038649477754266430">Usar um serviço de previsão para carregar páginas mais rapidamente</translation>
<translation id="9039213469156557790">Além disso, esta página inclui outros recursos que não são seguros. Esses recursos podem ser visualizados por outros usuários enquanto eles navegam e podem ser modificados por um invasor para alterar o comportamento da página.</translation>
+<translation id="9044359186343685026">Usar o Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" />: <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Você tentou acessar <ph name="DOMAIN" />, mas o servidor apresentou um certificado inválido.</translation>
<translation id="9050666287014529139">Senha</translation>
<translation id="9065203028668620118">Editar</translation>
<translation id="9065745800631924235">Pesquisa sobre <ph name="TEXT" /> no histórico</translation>
<translation id="9069693763241529744">Bloqueada por uma extensão</translation>
-<translation id="9076283476770535406">Pode apresentar conteúdo adulto</translation>
<translation id="9076630408993835509">Este navegador não é gerenciado por uma empresa ou outra organização. A atividade deste dispositivo pode ser gerenciada fora do Chrome. <ph name="BEGIN_LINK" />Saiba mais<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">São necessárias mais informações</translation>
<translation id="9080712759204168376">Resumo do pedido</translation>
<translation id="9089260154716455634">Política de horas de inatividade:</translation>
<translation id="9095388113577226029">Mais idiomas…</translation>
+<translation id="9098981495403789647">Seu administrador ativou o serviço de proteção contra ameaças do Chrome Enterprise no seu navegador. Esse serviço tem acesso a parte dos seus dados.</translation>
<translation id="9103872766612412690">O site <ph name="SITE" /> geralmente usa criptografia para proteger suas informações. Quando o Chromium tentou se conectar a <ph name="SITE" /> dessa vez, o website retornou credenciais
incomuns e incorretas. Isso pode acontecer quando um invasor está fingindo ser <ph name="SITE" /> ou quando uma tela de login por Wi-Fi interrompeu a conexão. Suas informações ainda estão protegidas, porque o Chromium interrompeu a conexão antes que os dados fossem trocados.</translation>
<translation id="9106062320799175032">Adicione um Endereço de Faturamento</translation>
<translation id="9114524666733003316">Confirmando cartão…</translation>
<translation id="9128870381267983090">Conectar à rede</translation>
<translation id="9137013805542155359">Mostrar original</translation>
-<translation id="9137248913990643158">Inicie e faça login no Chrome antes de usar este app.</translation>
<translation id="9141013498910525015">Gerenciar endereços</translation>
<translation id="9148088599418889305">Escolher método de envio</translation>
<translation id="9148507642005240123">&amp;Desfazer editar</translation>
diff --git a/chromium/components/strings/components_strings_pt-PT.xtb b/chromium/components/strings/components_strings_pt-PT.xtb
index 47d0e7f6847..d76f12218b3 100644
--- a/chromium/components/strings/components_strings_pt-PT.xtb
+++ b/chromium/components/strings/components_strings_pt-PT.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Adicionar nome no cartão</translation>
<translation id="1089439967362294234">Alterar palavra-passe</translation>
+<translation id="1096545575934602868">Este campo não deve ter mais de <ph name="MAX_ITEMS_LIMIT" /> entradas. Todas as restantes entradas serão rejeitadas.</translation>
<translation id="109743633954054152">Gerir palavras-passe nas definições do Chrome</translation>
<translation id="1103523840287552314">Traduzir sempre <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Se marcada, o Chrome armazena uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Aceda a uma <ph name="BEGIN_LINK" />cópia em cache<ph name="END_LINK" /> de <ph name="URL" /></translation>
<translation id="1156303062776767266">Está a visualizar um ficheiro local ou partilhado</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> fechou a ligação inesperadamente.</translation>
+<translation id="115926840831309955">Verifique o Código de Segurança/CVC e tente novamente ou atualize a data de validade.</translation>
<translation id="1161325031994447685">Ligar novamente à rede Wi-Fi</translation>
<translation id="1165039591588034296">Erro</translation>
<translation id="1175364870820465910">Im&amp;primir...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Existe software no computador que está a impedir que o Chrome se ligue à Web em segurança" (apenas para computadores com Windows)</translation>
<translation id="1294154142200295408">Variações da linha de comandos</translation>
<translation id="129553762522093515">Fechados recentemente</translation>
+<translation id="1298536327547837046">Análise de software malicioso</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Experimente limpar os cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funcionalidades descontinuadas</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Pesquisar imagem da área de transferência</translation>
<translation id="1323433172918577554">Mostrar mais</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Sheets</translation>
<translation id="1527263332363067270">A aguardar ligação…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">O site que acabou de tentar visitar parece falso. Por vezes, os atacantes imitam sites ao efetuarem pequenas alterações difíceis de detetar no URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Esta página diz</translation>
<translation id="153384715582417236">É tudo por agora</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">SO</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">O documento é demasiado grande para ser anotado.</translation>
-<translation id="1721312023322545264">Precisa da autorização de <ph name="NAME" /> para visitar este site</translation>
<translation id="1721424275792716183">* Campo de preenchimento obrigatório</translation>
<translation id="1727741090716970331">Adicionar número de cartão válido</translation>
<translation id="1728677426644403582">Está a ver a fonte de uma página Web</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Os Websites que visita e o tempo despendido nos mesmos.</translation>
<translation id="1826516787628120939">A verificar</translation>
<translation id="1834321415901700177">Este site contém programas prejudiciais</translation>
+<translation id="1838374766361614909">Limpar pesquisa</translation>
<translation id="1839551713262164453">A validação dos valores da política falhou devido a erros.</translation>
<translation id="1842969606798536927">Pagar</translation>
<translation id="1871208020102129563">O proxy está definido para utilizar servidores proxy fixos e não um URL de script .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Fechar lista</translation>
<translation id="1898423065542865115">Filtragem</translation>
<translation id="1914326953223720820">Serviço de descompressão de ficheiros</translation>
+<translation id="1915697529809968049">Pretende utilizar o Touch ID em vez do CVC?</translation>
<translation id="1916770123977586577">Para aplicar as definições atualizadas a este site, atualize esta página</translation>
<translation id="1919345977826869612">Anúncios</translation>
<translation id="1919367280705858090">Obter ajuda relativamente a uma mensagem de erro específica</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Marcadores de <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Erro de serialização</translation>
<translation id="1974060860693918893">Avançadas</translation>
+<translation id="1974883374937189061">Ajude a melhorar a segurança do Chrome ao enviar <ph name="BEGIN_WHITEPAPER_LINK" />os URLs de algumas páginas que visita, informações limitadas do sistema e algum conteúdo das páginas<ph name="END_WHITEPAPER_LINK" /> à Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versão do firmware</translation>
<translation id="1981206234434200693">Limpar os dados do histórico de navegação do Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{e mais 1}other{e mais #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Introduza um ano de expiração válido</translation>
<translation id="2212735316055980242">Política não encontrada</translation>
<translation id="2213606439339815911">A obter entradas...</translation>
+<translation id="2215727959747642672">Edição de ficheiros</translation>
<translation id="2218879909401188352">Os utilizadores mal-intencionados que se encontram em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem instalar aplicações perigosas que danificam o dispositivo, adicionam cobranças ocultas à fatura de dados móveis ou roubam as suas informações pessoais. <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Sem Internet</translation>
<translation id="2230458221926704099">Utilize a <ph name="BEGIN_LINK" />aplicação de diagnóstico<ph name="END_LINK" /> para corrigir a ligação</translation>
<translation id="2239100178324503013">Enviar agora</translation>
+<translation id="2248949050832152960">Utilizar WebAuthn</translation>
<translation id="225207911366869382">Este valor está desatualizado para esta política.</translation>
<translation id="2257315177824333709">De momento, não é possível guardar o seu cartão.</translation>
<translation id="2262243747453050782">Erro HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL de pesquisa inválido.</translation>
<translation id="2482878487686419369">Notificações</translation>
<translation id="248348093745724435">Políticas do computador</translation>
-<translation id="2485387744899240041">Os nomes de utilizador para o dispositivo e o navegador.</translation>
<translation id="2491120439723279231">O certificado do servidor contém erros.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analisador JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Voltar</translation>
<translation id="2503184589641749290">Cartões de débito e pré-pagos admitidos</translation>
<translation id="2505268675989099013">Proteger conta</translation>
+<translation id="2515335152965840738">IGNORAR</translation>
<translation id="2515629240566999685">Verificar o sinal na área</translation>
<translation id="2523886232349826891">Guardado apenas neste dispositivo.</translation>
<translation id="2524461107774643265">Adicionar mais informações</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Submeter</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nenhuma}=1{1 palavra-passe (de <ph name="DOMAIN_LIST" />)}=2{2 palavras-passe (de <ph name="DOMAIN_LIST" />)}other{# palavras-passe (de <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Fechar outros separadores ou aplicações</translation>
-<translation id="267371737713284912">prima <ph name="MODIFIER_KEY_DESCRIPTION" /> para anular</translation>
<translation id="2674170444375937751">Tem a certeza de que pretende eliminar estas páginas do seu histórico?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Sair</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">O valor não corresponde ao formato.</translation>
<translation id="2705137772291741111">A cópia guardada (em cache) deste site era ilegível.</translation>
<translation id="2709516037105925701">Preenchimento automático</translation>
-<translation id="2712173769900027643">Pedir autorização</translation>
<translation id="2713444072780614174">Branco</translation>
<translation id="2720342946869265578">Próximo</translation>
<translation id="2721148159707890343">Pedido com êxito</translation>
<translation id="2728127805433021124">O certificado do servidor foi assinado utilizando um algoritmo de assinatura fraco.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Executar o Diagnóstico de conetividade<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ao ativar estas funcionalidades, pode perder dados do navegador ou
+ comprometer a sua segurança ou privacidade. As funcionalidades ativadas aplicam-se a todos
+ os utilizadores deste navegador.</translation>
<translation id="2735043616039983645">Existe mais de uma origem com valores em conflito para esta política!</translation>
<translation id="2738330467931008676">Escolher endereço de levantamento</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">A ligação foi reposta.</translation>
<translation id="2788784517760473862">Cartões de crédito admitidos</translation>
<translation id="2792012897584536778">Os administradores deste dispositivo configuraram certificados de segurança que lhes podem permitir visualizar os conteúdos dos Websites visitados por si.</translation>
-<translation id="2794233252405721443">Site bloqueado</translation>
<translation id="2799020568854403057">O site que pretende visitar contém aplicações prejudiciais</translation>
<translation id="2799223571221894425">Reiniciar</translation>
<translation id="2803306138276472711">A Navegação Segura do Google <ph name="BEGIN_LINK" />detetou software malicioso<ph name="END_LINK" /> recentemente em <ph name="SITE" />. Os Sites que normalmente são seguros por vezes são infetados com software malicioso.</translation>
+<translation id="2815364696811431560">SAIR DO SITE</translation>
<translation id="2824775600643448204">Barra de pesquisa e endereço</translation>
<translation id="2826760142808435982">A ligação é encriptada e autenticada com <ph name="CIPHER" /> e utiliza <ph name="KX" /> como mecanismo de troca de chaves.</translation>
<translation id="2835170189407361413">Limpar formulário</translation>
<translation id="2847118875340931228">Abrir janela de navegação anónima</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Necessita de autorização para aceder a este site</translation>
<translation id="2856444702002559011">Os atacantes poderão estar a tentar roubar as suas informações de <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (por exemplo, palavras-passe, mensagens ou cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Pretende guardar o cartão?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Se ativada, o Chromium armazena uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="2985398929374701810">Introduza um endereço válido</translation>
<translation id="2986368408720340940">Este método de recolha não está disponível. Experimente um método diferente.</translation>
+<translation id="2987034854559945715">Nenhuma funcionalidade correspondente</translation>
<translation id="2991174974383378012">Partilha com Sites</translation>
<translation id="2991571918955627853">Não pode visitar <ph name="SITE" /> neste momento, porque o Website utiliza HSTS. Os erros de rede e os ataques são geralmente temporários, pelo que esta página deverá funcionar mais tarde.</translation>
<translation id="3005723025932146533">Mostrar cópia guardada</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Tipo de política incorreto</translation>
<translation id="3037605927509011580">Ah, bolas!!</translation>
<translation id="3041612393474885105">Informações do certificado</translation>
+<translation id="3057676462092457419">O modo DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> ainda não é suportado, o modo foi definido como <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Serviço de patch</translation>
<translation id="3064966200440839136">Está a sair do modo de navegação anónima para pagar através de uma aplicação externa. Pretende continuar?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> no servidor <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Cancelar pagamento</translation>
<translation id="3207960819495026254">Adicionado aos marcadores</translation>
+<translation id="3209034400446768650">A página pode efetuar cobranças</translation>
<translation id="3225919329040284222">O servidor apresentou um certificado que não corresponde às expectativas existentes. Estas expectativas são incluídas para determinados Web sites de alta segurança para sua proteção.</translation>
<translation id="3226128629678568754">Prima o botão de atualização para enviar novamente os dados necessários para carregar a página.</translation>
<translation id="3227137524299004712">Microfone</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Informações da versão do dispositivo e do navegador.</translation>
<translation id="323107829343500871">Introduzir o Código de Segurança/CVC de <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Detetar sempre conteúdo importante neste site</translation>
-<translation id="3254409185687681395">Marcar esta página</translation>
<translation id="3270847123878663523">&amp;Anular reordenação</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Adicionar nome no cartão</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Adicionar endereço de faturação</translation>
<translation id="3324983252691184275">Carmesim</translation>
<translation id="3338095232262050444">Seguro</translation>
-<translation id="3345135638360864351">Não é possível enviar o seu pedido de acesso a este site a <ph name="NAME" />. Tente novamente.</translation>
<translation id="3355823806454867987">Alterar definições de proxy...</translation>
<translation id="3361596688432910856">O Chrome <ph name="BEGIN_EMPHASIS" />não guardará<ph name="END_EMPHASIS" /> as seguintes informações:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Ocultar avançadas</translation>
<translation id="3467763166455606212">Nome do titular do cartão obrigatório</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, atualmente aberto, prima Tab e, em seguida, Enter para mudar para o separador aberto.</translation>
-<translation id="3479539252931486093">Esta ação foi inesperada? <ph name="BEGIN_LINK" />Informe-nos<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Agora não</translation>
<translation id="3484560055331845446">Pode perder o acesso à sua Conta Google. O Chrome recomenda que altere a palavra-passe agora. Ser-lhe-á pedido para iniciar sessão.</translation>
<translation id="3495081129428749620">Procurar na página
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Não conseguimos falar com o(a) seu (sua) pai/mãe de momento. Tente novamente.</translation>
<translation id="3512163584740124171">Esta política é ignorada, porque existe outra política do mesmo grupo de políticas com prioridade superior.</translation>
<translation id="3528171143076753409">O certificado do servidor não é fidedigno.</translation>
<translation id="3528485271872257980">Castanho-escuro</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Pelo menos 1 item em dispositivos sincronizados}=1{1 item (e mais em dispositivos sincronizados)}other{# itens (e mais em dispositivos sincronizados)}}</translation>
<translation id="3539171420378717834">Guardar uma cópia deste cartão neste dispositivo</translation>
-<translation id="3556433843310711081">O seu gestor pode desbloqueá-lo</translation>
<translation id="3566021033012934673">A sua ligação não é privada</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Uma página incorporada em <ph name="SITE" /> diz</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Abrir a página numa nova janela de navegação anónima (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Relatório de falhas capturado no(a) <ph name="CRASH_TIME" /> e carregado no(a) <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informações do certificado</translation>
+<translation id="3701427423622901115">Reposição confirmada.</translation>
<translation id="3704162925118123524">A rede que está a utilizar pode exigir que visite a respetivapágina de início de sessão.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">A carregar...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Os atacantes em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem levá-lo a tomar medidas perigosas, como instalar software ou revelar as suas informações pessoais (por exemplo, palavras-passe, números de telefone ou cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">A tradução falhou devido a um erro do servidor.</translation>
<translation id="3759461132968374835">Não tem comunicado falhas recentemente. As falhas que tenham ocorrido enquanto a criação de relatórios de falha esteve desativada não surgem aqui.</translation>
+<translation id="3760561303380396507">Pretende utilizar o Windows Hello em vez do CVC?</translation>
<translation id="3761718714832595332">Ocultar estado</translation>
<translation id="3765032636089507299">A página de Navegação segura está em construção.</translation>
<translation id="3778403066972421603">Pretende guardar este cartão na sua Conta Google e neste dispositivo?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Tamanho 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Conteúdo prejudicial bloqueado.</translation>
+<translation id="3808375843007691220">Aviso: funcionalidades experimentais mais à frente!</translation>
<translation id="3810973564298564668">Gerir</translation>
<translation id="382518646247711829">Se utilizar um servidor de proxy...</translation>
<translation id="3828924085048779000">Não é permitida uma frase de acesso vazia.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Atualizar a data e a hora</translation>
<translation id="3884278016824448484">Identificador do dispositivo em conflito</translation>
<translation id="3885155851504623709">Freguesia</translation>
-<translation id="3886446263141354045">O seu pedido para aceder a este site foi enviado para <ph name="NAME" />.</translation>
<translation id="3890664840433101773">Adicionar email</translation>
<translation id="3901925938762663762">O cartão expirou</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Pretende utilizar o WebAuthn em vez do CVC?</translation>
<translation id="3946209740501886391">Perguntar sempre neste site</translation>
<translation id="3949571496842715403">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O respetivo certificado de segurança não especifica Nomes alternativos do requerente. Isto pode ser o resultado de uma configuração incorreta ou de um utilizador mal-intencionado que intercetou a sua ligação.</translation>
<translation id="3949601375789751990">O histórico de navegação é apresentado aqui</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Nenhum}=1{De 1 site }other{De # sites }}</translation>
<translation id="397105322502079400">A calcular...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> está bloqueado</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ativou o Chrome Enterprise Threat Protection no seu navegador. O Chrome Enterprise Threat Protection tem acesso a alguns dos seus dados.</translation>
<translation id="3987940399970879459">Menos de 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 página Web próxima}other{# páginas Web próximas}}</translation>
<translation id="4030383055268325496">&amp;Anular adição</translation>
<translation id="4032320456957708163">O navegador é gerido por <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">O link que abriu aponta para um site que não costuma visitar. Poderá estar a tentar confundi-lo.</translation>
<translation id="4058922952496707368">Chave "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Adicionar endereço válido</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Número de série do dispositivo é inválido</translation>
<translation id="410351446219883937">Reprodução automática</translation>
<translation id="4103763322291513355">Visite &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver os URLs que foram colocados na lista negra e outras políticas aplicadas pelo gestor do sistema.</translation>
+<translation id="4108231218301530806">Utilizar impressão digital para validar este cartão na próxima vez</translation>
<translation id="4110652170750985508">Rever o seu pagamento</translation>
<translation id="4112140312785995938">Procurar para trás</translation>
<translation id="4116663294526079822">Permitir sempre neste Website</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Assinatura de verificação incorreta</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Mais <ph name="ITEM_COUNT" /> item}other{Mais <ph name="ITEM_COUNT" /> itens}}</translation>
+<translation id="4176463684765177261">Desativado</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Para pagar mais rapidamente da próxima vez, adicione o cartão e o endereço de faturação à sua Conta Google.</translation>
<translation id="4196861286325780578">&amp;Refazer movimentação</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Repor palavra-passe</translation>
<translation id="4279811152705618813">O seu <ph name="DEVICE_TYPE" /> é gerido por <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Este cartão foi guardado na sua Conta Google.}other{Estes cartões foram guardados na sua Conta Google.}}</translation>
+<translation id="428847186335018806">Analisar os ficheiros que transfere ou carrega no Chrome.</translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Mudar</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">A utilização de um proxy está desativada, mas existe uma configuração de proxy explícita especificada.</translation>
<translation id="445100540951337728">Cartões de débito admitidos</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> para o comportamento suspeito</translation>
<translation id="4466881336512663640">As alterações ao formulário serão perdidas. Tem a certeza de que pretende continuar?</translation>
<translation id="4477350412780666475">Faixa seguinte</translation>
<translation id="4482953324121162758">Este site não será traduzido.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Anular eliminação</translation>
<translation id="4597348597567598915">Tamanho 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Funcionalidades de pesquisa</translation>
<translation id="4646534391647090355">Aceder agora</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Este servidor não conseguiu provar que é o domínio <ph name="DOMAIN" />; o respetivo certificado de segurança contém erros. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">A ligação foi interrompida</translation>
-<translation id="471880041731876836">Não tem autorização para aceder a este site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar o Diagnóstico de rede do Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Recarregar políticas</translation>
<translation id="4728558894243024398">Plataforma</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Ajustar à página</translation>
<translation id="4850886885716139402">Ver</translation>
<translation id="4854362297993841467">Este método de fornecimento não está disponível. Experimente um método diferente.</translation>
-<translation id="4858792381671956233">Perguntaste aos teus pais se podes aceder a este site.</translation>
<translation id="4864052566555297930">Sugestão de segurança:</translation>
<translation id="4876188919622883022">Vista simplificada</translation>
<translation id="4876305945144899064">Sem nome de utilizador</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Reativar avisos</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Ver tudo</translation>
+<translation id="4989542687859782284">Indisponível</translation>
<translation id="4989809363548539747">Este plug-in não é compatível</translation>
+<translation id="4995216769782533993">Confirme o código de segurança para partilhar os detalhes do cartão com este site.</translation>
<translation id="5002932099480077015">Quando esta opção está ativada, o Chrome armazena uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="5015510746216210676">Nome do computador:</translation>
<translation id="5017554619425969104">Texto que copiou</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Valide o cartão</translation>
<translation id="5135404736266831032">Gerir endereços…</translation>
<translation id="5138227688689900538">Mostrar menos</translation>
<translation id="5141240743006678641">Encriptar palavras-passe sincronizadas com as credenciais Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Nuvem</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">As funcionalidades que se aplicam a todo o sistema apenas podem ser definidas pelo proprietário: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Aviso: esta política não foi unida, conforme especificado na política PolicyDictionaryMultipleSourceMergeList, porque não faz parte das políticas de dicionário que podem ser unidas.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Sair</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Falha ao armazenar as definições da política</translation>
<translation id="5371425731340848620">Atualizar cartão</translation>
<translation id="5377026284221673050">"O seu relógio está atrasado" ou "O seu relógio está adiantado" ou "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Esta página pode tentar enganá-lo, roubar as suas informações pessoais ou danificar o seu dispositivo. Tenha cuidado quando introduzir informações pessoais ou abrir ficheiros transferidos.</translation>
<translation id="5384855140246857529">Para utilizar os seus cartões em todos os dispositivos, inicie sessão e ative a sincronização.</translation>
<translation id="5386426401304769735">A cadeia de certificados inclui um certificado assinado através de SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Inválido</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Refazer edição</translation>
+<translation id="5473728911100096288">Ao ativar estas funcionalidades, estará a utilizar funcionalidades descontinuadas
+ que vão desaparecer em versões futuras.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Este conteúdo pode tentar instalar software perigoso no dispositivo que rouba ou elimina as suas informações. <ph name="BEGIN_LINK" />Mostrar mesmo assim<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Adicionar endereço válido</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Proteger conta</translation>
<translation id="5571083550517324815">Não é possível recolher a partir deste endereço. Selecione um diferente.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 em utilização}other{# em utilização}})</translation>
-<translation id="5572851009514199876">Comece e inicie sessão no Chrome para que este possa verificar se tem autorização para aceder a este site.</translation>
<translation id="5580958916614886209">Verifique o mês de validade e tente novamente</translation>
<translation id="5586446728396275693">Nenhum endereço guardado</translation>
<translation id="5595485650161345191">Editar morada</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Gestão não suportada</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Este site pode ser falso ou fraudulento. O Chrome recomenda que saia agora.</translation>
<translation id="5610142619324316209">Verificar a ligação</translation>
<translation id="5610807607761827392">Pode gerir cartões e endereços nas <ph name="BEGIN_LINK" />Definições<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> redirecionou-o demasiadas vezes.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Utilizador atual</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">O Chrome recomenda a reposição da palavra-passe se a tiver reutilizado noutros sites.</translation>
-<translation id="5732392974455271431">Os teus pais podem desbloquear-te</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Guardar o cartão na sua Conta Google}other{Guardar os cartões na sua Conta Google}}</translation>
<translation id="5763042198335101085">Introduza um endereço de email válido</translation>
<translation id="5765072501007116331">Para ver os métodos de fornecimento e os requisitos, selecione um endereço</translation>
<translation id="5778550464785688721">Controlo total de dispositivos MIDI</translation>
+<translation id="5781136890105823427">Experiência ativada</translation>
<translation id="578305955206182703">Âmbar</translation>
<translation id="57838592816432529">Desativar som</translation>
<translation id="5784606427469807560">Ocorreu um erro ao confirmar o cartão. Verifique a sua ligação à Internet e tente novamente.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Desativado</translation>
<translation id="5863847714970149516">A próxima página pode tentar cobrar-lhe dinheiro</translation>
<translation id="5866257070973731571">Adicionar número de telefone</translation>
+<translation id="5866898949289125849">Está a visualizar uma página de ferramentas para programadores</translation>
<translation id="5869405914158311789">Não é possível aceder a este site</translation>
<translation id="5869522115854928033">Palavras-passe guardadas</translation>
<translation id="5887400589839399685">Cartão guardado</translation>
<translation id="5893752035575986141">Os cartões de crédito são admitidos.</translation>
+<translation id="5895138241574237353">Reiniciar</translation>
<translation id="5901630391730855834">Amarelo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizados)</translation>
<translation id="5916664084637901428">Ativado</translation>
+<translation id="59174027418879706">Ativada</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Pretende guardar o cartão na Conta Google?</translation>
<translation id="5922853866070715753">Estamos quase a terminar</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Pretende utilizar os seus cartões em todos os seus dispositivos?</translation>
<translation id="6059925163896151826">Dispositivos USB</translation>
+<translation id="6060009363608157444">Modo DnsOverHttps inválido.</translation>
<translation id="6080696365213338172">Acedeu a conteúdos utilizando um certificado fornecido por um gestor. Os dados que fornecer a <ph name="DOMAIN" /> podem ser intercetados pelo seu gestor.</translation>
<translation id="6094273045989040137">Anotar</translation>
<translation id="610911394827799129">A sua Conta Google pode ter outras formas do histórico de navegação em <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Introduza a data de validade e o Código de Segurança/CVC de <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Perguntaste ao teu pai/à tua mãe se podes aceder a este site.</translation>
<translation id="6415778972515849510">O Chromium pode ajudá-lo a proteger a sua Conta Google e alterar a palavra-passe.</translation>
-<translation id="6417515091412812850">Não é possível verificar se o certificado foi revogado.</translation>
<translation id="6431585503458005759">Não armazenar</translation>
<translation id="6433490469411711332">Editar informações de contacto</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> recusou estabelecer ligação.</translation>
<translation id="6434309073475700221">Rejeitar</translation>
+<translation id="6435221585574090192">Partilhe dados sobre eventos de segurança sinalizados pelo Chrome Enterprise Threat Protection com o seu administrador. Estes podem incluir URLs de páginas, nomes e metadados de ficheiros, o nome de utilizador do dispositivo e o nome de utilizador do Chrome.</translation>
<translation id="6440503408713884761">Ignorado</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Adicionar mais informações</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Gerir palavras-passe…</translation>
<translation id="647261751007945333">Políticas do dispositivo</translation>
<translation id="6476284679642588870">Gerir métodos de pagamento</translation>
-<translation id="6477321094435799029">O Chrome detetou código estranho nesta página e bloqueou-a para proteger as suas informações pessoais (por exemplo, palavras-passe, números de telefone e números de cartões de crédito).</translation>
<translation id="6489534406876378309">Começar a carregar falhas</translation>
<translation id="6499038740797743453">Pretende repor a palavra-passe?</translation>
<translation id="6507833130742554667">Os cartões de crédito e de débito são admitidos.</translation>
<translation id="650855688985305916">Sim, armazenar</translation>
<translation id="6508722015517270189">Reiniciar o Chrome</translation>
<translation id="6517596291481585650">Aviso: esta política não foi unida como lista, conforme especificado pela política, porque não é uma lista.</translation>
+<translation id="6518133107902771759">Verificar</translation>
<translation id="6521745193039995384">Não ativa</translation>
<translation id="6529602333819889595">&amp;Refazer eliminação</translation>
<translation id="6534179046333460208">Sugestões da Web física</translation>
<translation id="6545864417968258051">Procura de Bluetooth</translation>
<translation id="6554795675067793129">A sua conta é gerida pelo domínio <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Refazer</translation>
-<translation id="6563469144985748109">O seu gestor ainda não o aprovou</translation>
<translation id="6569060085658103619">Está a ver a página de uma extensão</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Rosa claro</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Limpar</translation>
<translation id="6644283850729428850">Esta política está obsoleta.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nenhum}=1{De 1 site (a sessão na sua Conta Google não é terminada).}other{De # sites (a sessão na sua Conta Google não é terminada).}}</translation>
+<translation id="6652101503459149953">Utilizar o Windows Hello</translation>
<translation id="6657585470893396449">Palavra-passe</translation>
<translation id="6670613747977017428">Voltar para segurança.</translation>
<translation id="6671697161687535275">Pretende remover a sugestão do formulário do Chromium?</translation>
<translation id="6685834062052613830">Termine sessão e conclua a configuração</translation>
<translation id="6689271823431384964">O Chrome está a disponibilizar a opção de guardar os seus cartões na sua Conta Google porque tem sessão iniciada. Pode alterar este comportamento nas definições. O nome do titular do cartão vem da sua conta.</translation>
+<translation id="6707256370811247129">Analisar os conteúdos da cache e os ficheiros que transfere ou carrega no Chrome.</translation>
<translation id="6710213216561001401">Anterior</translation>
<translation id="6710594484020273272">&lt;Introduzir termo de pesquisa&gt;</translation>
<translation id="671076103358959139">Símbolo de inscrição:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Os seus dados foram encriptados com a sua <ph name="BEGIN_LINK" />frase de acesso de sincronização<ph name="END_LINK" /> à(s) <ph name="TIME" />. Introduza a mesma para iniciar a sincronização.</translation>
<translation id="674375294223700098">Erro de certificado de servidor desconhecido.</translation>
<translation id="6744009308914054259">Enquanto aguarda uma ligação, pode visitar a secção Transferências para ler artigos offline.</translation>
+<translation id="6747611005629681221">Aviso: funcionalidades descontinuadas à frente!</translation>
<translation id="6753269504797312559">Valor da política</translation>
<translation id="6757797048963528358">O dispositivo entrou em suspensão.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">O teu pai/a tua mãe ainda não o aprovou</translation>
<translation id="67862343314499040">Violeta</translation>
<translation id="6786747875388722282">Extensões</translation>
<translation id="6790428901817661496">Reproduzir</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Campo obrigatório</translation>
<translation id="6810899417690483278">ID de personalização</translation>
<translation id="6825578344716086703">Tentou aceder a <ph name="DOMAIN" />, mas o servidor apresentou um certificado assinado utilizando um algoritmo de assinatura fraco (como SHA-1). Isto significa que as credenciais de segurança apresentadas pelo servidor podem ter sido falsificadas e que o servidor pode não ser aquele que pretende (pode estar a comunicar com um utilizador mal intencionado).</translation>
+<translation id="6826370046007623921">Prevenção contra a perda de dados</translation>
<translation id="6831043979455480757">Traduzir</translation>
<translation id="6839929833149231406">Área</translation>
<translation id="6852204201400771460">Pretende atualizar a aplicação?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">O nível da política não é suportado.</translation>
<translation id="6895330447102777224">O seu cartão foi confirmado</translation>
<translation id="6897140037006041989">Agente do utilizador</translation>
-<translation id="6903319715792422884">Ajude a melhorar a Navegação segura ao enviar algumas <ph name="BEGIN_WHITEPAPER_LINK" />informações do sistema e conteúdo de páginas<ph name="END_WHITEPAPER_LINK" /> para a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utilizador:</translation>
<translation id="6934672428414710184">Este nome é proveniente da sua Conta Google.</translation>
<translation id="6944692733090228304">Introduziu a palavra-passe num site que não é gerido pela <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para proteger a conta, não reutilize a sua palavra-passe noutras aplicações e sites.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lilás</translation>
<translation id="717330890047184534">ID Gaia:</translation>
+<translation id="7174545416324379297">Unida</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> e mais <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">O servidor ao qual irá aceder, <ph name="ORIGIN" />, solicitou que seja aplicada uma
política de segurança a todos os pedidos. Contudo, em vez de
@@ -1166,6 +1187,7 @@ Detalhes adicionais:
<translation id="7320336641823683070">Ajuda para estabelecer ligação</translation>
<translation id="733354035281974745">Substituição da conta local do dispositivo</translation>
<translation id="7334320624316649418">&amp;Refazer reordenação</translation>
+<translation id="7337706099755338005">Indisponível na sua plataforma.</translation>
<translation id="733923710415886693">O certificado do servidor não foi divulgado através da Transparência de certificados.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Está afiliado:</translation>
@@ -1196,7 +1218,6 @@ Detalhes adicionais:
<translation id="7440140511386898319">Explorar offline</translation>
<translation id="7441627299479586546">Assunto da política incorreto</translation>
<translation id="7442725080345379071">Laranja-claro</translation>
-<translation id="7444046173054089907">Este site está bloqueado</translation>
<translation id="7445762425076701745">Não é possível validar totalmente a identidade do servidor ao qual está ligado. Está ligado a um servidor com um nome que apenas é válido na sua rede, que não permite que uma autoridade de certificação externa valide a respectiva propriedade. Ainda assim, algumas autoridades emitem certificados para esses nomes, pelo que não há forma de garantir que está ligado ao Website que pretende e não a um site pirata.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Saber mais<ph name="END_LINK" /> sobre este problema.</translation>
<translation id="7455133967321480974">Utilizar predefinição global (Bloquear)</translation>
@@ -1218,9 +1239,9 @@ Detalhes adicionais:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Ao confirmar, os detalhes do cartão são partilhados com este site.</translation>
<translation id="7542995811387359312">O preenchimento automático de cartões de crédito está desativado, porque este formulário não utiliza uma ligação segura.</translation>
-<translation id="7543525346216957623">Pede aos teus pais</translation>
<translation id="7548892272833184391">Corrigir erros de ligação</translation>
<translation id="7549584377607005141">Esta página Web requer os dados introduzidos anteriormente para ser corretamente apresentada. Pode enviar novamente esses dados, mas ao fazê-lo, irá repetir as ações que esta página executou anteriormente.</translation>
+<translation id="7550637293666041147">O nome de utilizador do dispositivo e o nome de utilizador do Chrome</translation>
<translation id="7552846755917812628">Experimente as sugestões seguintes:</translation>
<translation id="7554791636758816595">Novo separador</translation>
<translation id="7564049878696755256">Pode perder o acesso à sua conta do serviço <ph name="ORG_NAME" /> ou ser vítima de roubo de identidade. O Chrome recomenda a alteração da palavra-passe agora.</translation>
@@ -1235,6 +1256,7 @@ Detalhes adicionais:
<translation id="7610193165460212391">O valor está fora do intervalo <ph name="VALUE" /> .</translation>
<translation id="7613889955535752492">Exp.: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Já tem dados encriptados usando uma versão diferente da palavra-passe da sua Conta Google. Introduza-a abaixo.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Dados de desempenho e relatórios de falhas</translation>
<translation id="7637571805876720304">Pretende remover o cartão de crédito do Chromium?</translation>
<translation id="7638605456503525968">Portas de série</translation>
@@ -1247,7 +1269,6 @@ Detalhes adicionais:
<translation id="7668654391829183341">Dispositivo desconhecido</translation>
<translation id="7669271284792375604">Os utilizadores mal intencionados neste site podem tentar enganá-lo para instalar programas que são prejudiciais para a sua experiência de navegação (por exemplo, ao alterar a sua página inicial ou ao mostrar anúncios adicionais em sites que visita).</translation>
<translation id="7676643023259824263">Pesquisar texto da área de transferência, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Plataforma e nuvem</translation>
<translation id="7681101578153515023">Alterar motor de pesquisa</translation>
<translation id="7682287625158474539">Envio</translation>
<translation id="7687186412095877299">Preenche os formulários de pagamento com os seus métodos de pagamento guardados</translation>
@@ -1262,7 +1283,6 @@ Detalhes adicionais:
<translation id="7723047071702270851">Editar cartão</translation>
<translation id="774634243536837715">Conteúdo perigoso bloqueado.</translation>
<translation id="7752995774971033316">Não gerido</translation>
-<translation id="7755287808199759310">O teu pai/a tua mãe pode desbloquear-te</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">O software de firewall ou antivírus pode ter bloqueado a ligação.</translation>
<translation id="7759163816903619567">Domínio de apresentação:</translation>
@@ -1306,7 +1326,6 @@ Detalhes adicionais:
<translation id="8004582292198964060">Navegador</translation>
<translation id="8009225694047762179">Gerir palavras-passe</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Este cartão e o respetivo endereço de faturação serão guardados. Pode utilizá-lo quando tiver sessão iniciada em <ph name="USER_EMAIL" />.}other{Estes cartões e os respetivos endereços de faturação serão guardados. Pode utilizá-los quando tiver sessão iniciada em <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Não conseguimos falar com os seus pais de momento. Tente novamente.</translation>
<translation id="8025119109950072390">Os utilizadores mal intencionados neste site podem enganá-lo no sentido de fazer algo perigoso como instalar software ou revelar as suas informações pessoais (por exemplo, palavras-passe, números de telefone ou cartões de crédito).</translation>
<translation id="8034522405403831421">Esta página está em <ph name="SOURCE_LANGUAGE" />. Pretende traduzi-la para <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Caneta</translation>
@@ -1317,6 +1336,7 @@ Detalhes adicionais:
<translation id="8041940743680923270">Utilizar predefinição global (Perguntar)</translation>
<translation id="8042918947222776840">Escolher método de levantamento</translation>
<translation id="8057711352706143257">O "<ph name="SOFTWARE_NAME" />" não está configurado corretamente. Normalmente, a desinstalação do "<ph name="SOFTWARE_NAME" />" resolve o problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">A partir de agora, não precisa de introduzir um código de segurança do cartão.</translation>
<translation id="8066955247577885446">Lamentamos, mas ocorreu um erro.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Não é possível criar anotação se tiver sido aplicada uma rotação ao documento</translation>
@@ -1347,6 +1367,7 @@ Detalhes adicionais:
<translation id="8211406090763984747">A ligação é segura</translation>
<translation id="8218327578424803826">Localização atribuída:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Relatórios empresariais</translation>
<translation id="8225771182978767009">A pessoa que configurou este computador optou por bloquear este site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Abrir página num novo separador anónimo</translation>
@@ -1401,24 +1422,24 @@ Detalhes adicionais:
<translation id="8508648098325802031">Ícone de pesquisa</translation>
<translation id="8522552481199248698">O Chrome pode ajudá-lo a proteger a sua Conta Google e a alterar a palavra-passe.</translation>
<translation id="8543181531796978784">Pode <ph name="BEGIN_ERROR_LINK" />comunicar um problema de deteção<ph name="END_ERROR_LINK" /> ou, se compreende os riscos para a sua segurança, <ph name="BEGIN_LINK" />aceda a este site não seguro<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Tem dúvidas? Contacte a pessoa que supervisiona o seu perfil.</translation>
<translation id="8553075262323480129">A tradução falhou porque não foi possível determinar o idioma da página.</translation>
<translation id="8557066899867184262">O Código de Segurança/CVC está localizado no verso do cartão.</translation>
<translation id="8559762987265718583">Não é possível estabelecer uma ligação privada a <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, porque a data e a hora do seu dispositivo (<ph name="DATE_AND_TIME" />) estão incorretas.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> site suspeito</translation>
<translation id="8564985650692024650">O Chromium recomenda a reposição da palavra-passe da <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> se a tiver reutilizado noutros sites.</translation>
<translation id="8571890674111243710">A traduzir a página para <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Adic. n.º telef.
</translation>
-<translation id="859285277496340001">O certificado não indica um mecanismo para verificar se foi ou não revogado.</translation>
<translation id="860043288473659153">Nome do titular do cartão</translation>
<translation id="861775596732816396">Tamanho 4</translation>
-<translation id="8620436878122366504">Os teus pais ainda não o aprovaram</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Guardar este cartão neste dispositivo</translation>
<translation id="8626112503828625890">Pretende armazenar os detalhes de faturação na Conta Google?</translation>
+<translation id="8647750283161643317">Repor todas as predefinições</translation>
<translation id="8663226718884576429">Resumo da encomenda, <ph name="TOTAL_LABEL" />, mais detalhes</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, resposta, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponível</translation>
<translation id="8703575177326907206">A sua ligação a <ph name="DOMAIN" /> não está encriptada.</translation>
<translation id="8718314106902482036">Pagamento não concluído</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, sugestão de pesquisa.</translation>
@@ -1429,6 +1450,7 @@ Detalhes adicionais:
<translation id="8738058698779197622">Para estabelecer uma ligação segura, o relógio tem de ser definido corretamente. Isto deve-se ao facto de os certificados que os Sites utilizam para se identificarem serem apenas válidos para períodos de tempo específicos. Uma vez que o relógio do seu dispositivo está incorreto, o Chromium não consegue validar estes certificados.</translation>
<translation id="8740359287975076522">Não foi possível encontrar o &lt;abbr id="dnsDefinition"&gt;endereço DNS&lt;/abbr&gt; de <ph name="HOST_NAME" />. Estamos a diagnosticar o problema.</translation>
<translation id="874846938927089722">Cartões de crédito e pré-pagos aceites</translation>
+<translation id="874918643257405732">Adicione este separador aos marcadores</translation>
<translation id="8759274551635299824">Este cartão expirou</translation>
<translation id="8761567432415473239">A Navegação Segura do Google <ph name="BEGIN_LINK" />encontrou programas prejudiciais<ph name="END_LINK" /> recentemente em <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispositivo USB</translation>
@@ -1458,6 +1480,7 @@ Detalhes adicionais:
<translation id="8938939909778640821">Cartões de crédito e pré-pagos admitidos</translation>
<translation id="8943282376843390568">Lima</translation>
<translation id="8957210676456822347">Autorização de portal cativo</translation>
+<translation id="8962950042226115166">Site suspeito</translation>
<translation id="8968766641738584599">Guardar cartão</translation>
<translation id="8971063699422889582">O certificado do servidor expirou.</translation>
<translation id="8975012916872825179">Inclui informações como números de telefone, endereços de email e moradas para envio</translation>
@@ -1480,24 +1503,24 @@ Detalhes adicionais:
<translation id="9035022520814077154">Erro de segurança</translation>
<translation id="9038649477754266430">Utilizar um serviço de previsão para carregar páginas mais rapidamente</translation>
<translation id="9039213469156557790">Além disso, esta página inclui outros recursos que não são seguros. Estes recursos podem ser vistos por outros utilizadores em trânsito e modificados por um utilizador mal intencionado com o intuito de alterar o comportamento da página.</translation>
+<translation id="9044359186343685026">Utilizar Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Tentou aceder a <ph name="DOMAIN" />, mas o servidor apresentou um certificado inválido.</translation>
<translation id="9050666287014529139">Frase de acesso</translation>
<translation id="9065203028668620118">Editar</translation>
<translation id="9065745800631924235">Pesquisa de <ph name="TEXT" /> no histórico</translation>
<translation id="9069693763241529744">Bloqueada por uma extensão</translation>
-<translation id="9076283476770535406">Pode ter conteúdo para adultos</translation>
<translation id="9076630408993835509">Este navegador não é gerido por uma empresa ou outra entidade. A atividade neste dispositivo pode ser gerida fora do Chrome. <ph name="BEGIN_LINK" />Saiba mais<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">São necessárias mais informações</translation>
<translation id="9080712759204168376">Resumo da encomenda</translation>
<translation id="9089260154716455634">Política para fora do horário de funcionamento:</translation>
<translation id="9095388113577226029">Mais idiomas…</translation>
+<translation id="9098981495403789647">O seu administrador ativou o Chrome Enterprise Threat Protection no navegador. O Chrome Enterprise Threat Protection tem acesso a alguns dos seus dados.</translation>
<translation id="9103872766612412690">Normalmente, o site <ph name="SITE" /> utiliza a encriptação para proteger as suas informações. Quando o Chromium tentou estabelecer ligação a <ph name="SITE" /> desta vez, o Website devolveu credenciais invulgares e incorretas. Isto pode acontecer quando um utilizador mal intencionado tenta simular ser <ph name="SITE" /> ou quando um ecrã de início de sessão Wi-Fi interrompe a ligação. As suas informações continuam seguras porque o Chromium interrompeu a ligação antes de qualquer troca de dados.</translation>
<translation id="9106062320799175032">Adicionar endereço de faturação</translation>
<translation id="9114524666733003316">A confirmar o cartão…</translation>
<translation id="9128870381267983090">Ligar à rede</translation>
<translation id="9137013805542155359">Mostrar original</translation>
-<translation id="9137248913990643158">Comece e inicie sessão no Chrome antes de utilizar esta aplicação.</translation>
<translation id="9141013498910525015">Gerir endereços</translation>
<translation id="9148088599418889305">Escolher método de envio</translation>
<translation id="9148507642005240123">&amp;Anular edição</translation>
diff --git a/chromium/components/strings/components_strings_ro.xtb b/chromium/components/strings/components_strings_ro.xtb
index d440e9ec476..6c1f653f516 100644
--- a/chromium/components/strings/components_strings_ro.xtb
+++ b/chromium/components/strings/components_strings_ro.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Adaugă numele de pe card</translation>
<translation id="1089439967362294234">Schimbă parola</translation>
+<translation id="1096545575934602868">Acest câmp nu poate să conțină mai mult de <ph name="MAX_ITEMS_LIMIT" /> intrări. Toate intrările suplimentare vor fi șterse.</translation>
<translation id="109743633954054152">Gestionează parolele în setările Chrome</translation>
<translation id="1103523840287552314">Tradu întotdeauna din <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Dacă este bifată opțiunea, Chrome va stoca o copie a cardului pe dispozitiv pentru a completa formularul mai rapid.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Accesați o <ph name="BEGIN_LINK" />copie păstrată în memoria cache<ph name="END_LINK" /> a site-ului <ph name="URL" /></translation>
<translation id="1156303062776767266">Se afișează un fișier local sau comun</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> a închis conexiunea în mod neașteptat.</translation>
+<translation id="115926840831309955">Verifică codul CVC și încearcă din nou sau actualizează data expirării</translation>
<translation id="1161325031994447685">să te reconectezi la Wi-Fi</translation>
<translation id="1165039591588034296">Eroare</translation>
<translation id="1175364870820465910">&amp;Printează...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Pe computer există software care împiedică browserul Chrome să se conecteze în siguranță la internet” (doar pentru computerele Windows)</translation>
<translation id="1294154142200295408">Variații ale liniilor de comandă</translation>
<translation id="129553762522093515">Închise recent</translation>
+<translation id="1298536327547837046">Scanarea pentru programe malware</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Șterge cookie-urile<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funcții învechite</translation>
<translation id="1320233736580025032">Prc1 (Plic)</translation>
<translation id="132301787627749051">Caută imaginea din clipboard</translation>
<translation id="1323433172918577554">Afișează mai multe</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Foi de calcul Google</translation>
<translation id="1527263332363067270">Se așteaptă conectarea…</translation>
<translation id="1529521330346880926">10x15 (Plic)</translation>
+<translation id="1530707389502320859">Site-ul pe care ai încercat să-l accesezi pare fals. Uneori, atacatorii imită site-uri aducând modificări mici, greu de observat, adresei URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Această pagină afișează mesajul</translation>
<translation id="153384715582417236">Asta este tot</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">Sistem de operare</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Documentul este prea mare pentru a face adnotări</translation>
-<translation id="1721312023322545264">Ai nevoie de permisiunea utilizatorului <ph name="NAME" /> ca să accesezi acest site</translation>
<translation id="1721424275792716183">* Câmp obligatoriu</translation>
<translation id="1727741090716970331">Adaugă un număr de card valid</translation>
<translation id="1728677426644403582">Se afișează sursa unei pagini web</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Site-urile pe care le-ai accesat și timpul petrecut pe ele</translation>
<translation id="1826516787628120939">Se verifică</translation>
<translation id="1834321415901700177">Acest site conține programe dăunătoare</translation>
+<translation id="1838374766361614909">Șterge căutarea</translation>
<translation id="1839551713262164453">Validarea valorilor de politică a returnat erori</translation>
<translation id="1842969606798536927">Plătește</translation>
<translation id="1871208020102129563">Configurația proxy este setată să utilizeze servere proxy fixe, și nu o adresă URL pentru scripturi .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Restrângeți lista</translation>
<translation id="1898423065542865115">Filtrarea</translation>
<translation id="1914326953223720820">Serviciu de dezarhivare</translation>
+<translation id="1915697529809968049">Folosești Touch ID în loc de CVC?</translation>
<translation id="1916770123977586577">Ca să aplici setările actualizate pentru acest site, reîncarcă pagina</translation>
<translation id="1919345977826869612">Anunțuri</translation>
<translation id="1919367280705858090">Obține ajutor în privința unui anumit mesaj de eroare</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Marcaje <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Eroare de serializare</translation>
<translation id="1974060860693918893">Avansate</translation>
+<translation id="1974883374937189061">Contribuie la îmbunătățirea securității Chrome prin trimiterea la Google a <ph name="BEGIN_WHITEPAPER_LINK" />adreselor URL ale unor pagini pe care le accesezi, informații de sistem limitate și o parte din conținutul paginii<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Versiune de firmware</translation>
<translation id="1981206234434200693">Șterge datele istoricului de navigare ale Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{și încă una}few{și încă #}other{și încă #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Introdu un an de expirare valid</translation>
<translation id="2212735316055980242">Politica nu a fost găsită</translation>
<translation id="2213606439339815911">Se preiau intrările...</translation>
+<translation id="2215727959747642672">Editează fișiere</translation>
<translation id="2218879909401188352">Atacatorii de pe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ar putea să instaleze aplicații periculoase care deteriorează dispozitivul, adaugă costuri ascunse pe factura de telefonie mobilă sau îți fură informațiile cu caracter personal. <ph name="BEGIN_LEARN_MORE_LINK" />Află mai multe<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Nu există conexiune la internet</translation>
<translation id="2230458221926704099">Remediază conexiunea folosind <ph name="BEGIN_LINK" />aplicația de diagnosticare<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Trimite acum</translation>
+<translation id="2248949050832152960">Folosește WebAuthn</translation>
<translation id="225207911366869382">Valoarea este învechită pentru această politică.</translation>
<translation id="2257315177824333709">Momentan cardul nu poate fi salvat</translation>
<translation id="2262243747453050782">Eroare HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Adresă URL de căutare nevalidă.</translation>
<translation id="2482878487686419369">Notificări</translation>
<translation id="248348093745724435">Politicile dispozitivului</translation>
-<translation id="2485387744899240041">Nume de utilizator pentru dispozitivul și browserul tău</translation>
<translation id="2491120439723279231">Certificatul serverului conține erori.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Analizor JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Înapoi</translation>
<translation id="2503184589641749290">Carduri de debit și preplătite acceptate</translation>
<translation id="2505268675989099013">Protejează contul</translation>
+<translation id="2515335152965840738">IGNORĂ</translation>
<translation id="2515629240566999685">să verifici semnalul din zona ta.</translation>
<translation id="2523886232349826891">Salvat numai pe acest dispozitiv</translation>
<translation id="2524461107774643265">Adaugă mai multe informații</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Trimite</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Niciuna}=1{O parolă (pentru <ph name="DOMAIN_LIST" />)}=2{2 parole (pentru <ph name="DOMAIN_LIST" />)}few{# parole (pentru <ph name="DOMAIN_LIST" />)}other{# de parole (pentru <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">închide celelalte file sau aplicații;</translation>
-<translation id="267371737713284912">apasă <ph name="MODIFIER_KEY_DESCRIPTION" /> pentru a anula</translation>
<translation id="2674170444375937751">Sigur doriți să ștergeți aceste pagini din istoric?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Ieși</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">Valoarea nu se potrivește cu formatul.</translation>
<translation id="2705137772291741111">Copia salvată (în memoria cache) a acestui site nu a putut fi citită.</translation>
<translation id="2709516037105925701">Completare automată</translation>
-<translation id="2712173769900027643">Solicită permisiunea</translation>
<translation id="2713444072780614174">Alb</translation>
<translation id="2720342946869265578">În apropiere</translation>
<translation id="2721148159707890343">Solicitarea a reușit</translation>
<translation id="2728127805433021124">Certificatul serverului este semnat utilizând un algoritm de semnătură slab.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />să rulezi Diagnostice conectivitate<ph name="END_LINK" />;</translation>
+<translation id="2734544361860335147">Dacă activezi aceste funcții, ai putea pierde date din browser sau ți-ai putea compromite siguranța ori confidențialitatea. Funcțiile activate se aplică tuturor utilizatorilor acestui browser.</translation>
<translation id="2735043616039983645">Pentru această politică este prezentă mai mult de o sursă cu valori în conflict!</translation>
<translation id="2738330467931008676">Alege adresa de preluare</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">Conexiunea a fost resetată.</translation>
<translation id="2788784517760473862">Carduri de credit acceptate</translation>
<translation id="2792012897584536778">Administratorii acestui dispozitiv au configurat certificate de securitate cu care pot vedea conținutul site-urilor pe care le accesezi.</translation>
-<translation id="2794233252405721443">Site blocat</translation>
<translation id="2799020568854403057">Site-ul pe care urmează să îl accesezi conține aplicații dăunătoare</translation>
<translation id="2799223571221894425">Repornește</translation>
<translation id="2803306138276472711">Navigarea sigură Google <ph name="BEGIN_LINK" />a detectat recent programe malware<ph name="END_LINK" /> pe <ph name="SITE" />. Site-urile care sunt de obicei sigure sunt uneori infectate cu programe malware.</translation>
+<translation id="2815364696811431560">IEȘI DE PE SITE</translation>
<translation id="2824775600643448204">Bara de adrese și de căutare</translation>
<translation id="2826760142808435982">Conexiunea este criptată și autentificată utilizând <ph name="CIPHER" /> și folosește <ph name="KX" /> ca mecanism de schimb al cheii.</translation>
<translation id="2835170189407361413">Golește formularul</translation>
<translation id="2847118875340931228">Deschide o fereastră incognito</translation>
<translation id="2850739647070081192">Invite (Plic)</translation>
-<translation id="2851634818064021665">Ai nevoie de permisiune ca să accesezi acest site</translation>
<translation id="2856444702002559011">Atacatorii pot încerca să îți fure informațiile de pe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (de exemplu, parole, mesaje sau date despre cardurile de credit). <ph name="BEGIN_LEARN_MORE_LINK" />Află mai multe<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Salvezi cardul?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Dacă opțiunea este activată, Chromium va stoca o copie a cardului pe dispozitiv pentru a completa formularul mai rapid.</translation>
<translation id="2985398929374701810">Introdu o adresă validă</translation>
<translation id="2986368408720340940">Această metodă de preluare nu este disponibilă. Încearcă altă metodă.</translation>
+<translation id="2987034854559945715">Nu există funcții care corespund</translation>
<translation id="2991174974383378012">Permiterea accesului pentru site-uri</translation>
<translation id="2991571918955627853">Nu poți accesa <ph name="SITE" /> acum, deoarece site-ul folosește HSTS. Erorile de rețea și atacurile sunt de obicei temporare și probabil că această pagină va funcționa mai târziu.</translation>
<translation id="3005723025932146533">Afișați o copie salvată</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Tip de politică greșit</translation>
<translation id="3037605927509011580">Of, nu mai merge!</translation>
<translation id="3041612393474885105">Informații despre certificat</translation>
+<translation id="3057676462092457419">Modul DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> nu este încă acceptat. Modul a fost setat la <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Plic)</translation>
<translation id="3061707000357573562">Serviciu de corecție</translation>
<translation id="3064966200440839136">Vei părăsi modul incognito pentru a plăti folosind o aplicație externă. Continui?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> pe <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Anulează plata</translation>
<translation id="3207960819495026254">Marcată</translation>
+<translation id="3209034400446768650">Pagina poate percepe o taxă</translation>
<translation id="3225919329040284222">Serverul a prezentat un certificat care nu se potrivește cu așteptările încorporate. Aceste așteptări sunt incluse pentru anumite site-uri web, cu un grad sporit de securitate, pentru a vă proteja.</translation>
<translation id="3226128629678568754">Apăsați butonul de reîncărcare pentru a retrimite datele necesare pentru încărcarea paginii.</translation>
<translation id="3227137524299004712">Microfon</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">Informații despre versiunea dispozitivului și browserului</translation>
<translation id="323107829343500871">Introdu codul CVC pentru <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Detectează întotdeauna conținutul important pe acest site</translation>
-<translation id="3254409185687681395">Marcați această pagină</translation>
<translation id="3270847123878663523">&amp;Anulați reordonarea</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Adaugă numele de pe card</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">Adaugă o adresă de facturare</translation>
<translation id="3324983252691184275">Roșu aprins</translation>
<translation id="3338095232262050444">Securizat</translation>
-<translation id="3345135638360864351">Solicitarea de a accesa acest site nu a putut fi trimisă la <ph name="NAME" />. Încearcă din nou.</translation>
<translation id="3355823806454867987">Modifica setările proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />nu va salva<ph name="END_EMPHASIS" /> următoarele informații:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">Ascundeți detaliile avansate</translation>
<translation id="3467763166455606212">Este necesar numele titularului cardului</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, deschisă acum, apasă pe filă, apoi pe Enter pentru a comuta la fila deschisă</translation>
-<translation id="3479539252931486093">A fost o situație neașteptată? <ph name="BEGIN_LINK" />Anunță-ne<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Nu acum</translation>
<translation id="3484560055331845446">Este posibil să pierzi accesul la Contul Google. Chrome îți recomandă să îți schimbi parola acum. Ți se va cere să te conectezi.</translation>
<translation id="3495081129428749620">Caută în pagină
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Momentan, nu ți-am putut contacta părintele. Încearcă din nou.</translation>
<translation id="3512163584740124171">Această politică este ignorată deoarece o altă politică din același grup de politici are prioritate ridicată.</translation>
<translation id="3528171143076753409">Certificatul serverului nu este de încredere.</translation>
<translation id="3528485271872257980">Maro închis</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Cel puțin 1 element pe dispozitivele sincronizate}=1{1 element (și mai multe pe dispozitivele sincronizate)}few{# elemente (și mai multe pe dispozitivele sincronizate)}other{# de elemente (și mai multe pe dispozitivele sincronizate)}}</translation>
<translation id="3539171420378717834">Păstrează o copie a cardului pe dispozitiv</translation>
-<translation id="3556433843310711081">Administratorul îl poate debloca pentru tine</translation>
<translation id="3566021033012934673">Conexiunea nu este privată</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">O pagină încorporată de pe <ph name="SITE" /> afișează mesajul</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">Deschide pagina într-o fereastră incognito nouă (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Raport de blocare creat <ph name="CRASH_TIME" /> și încărcat <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informații despre certificat</translation>
+<translation id="3701427423622901115">Resetare confirmată.</translation>
<translation id="3704162925118123524">Rețeaua pe care o folosești poate solicita accesarea paginii de conectare.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Se încarcă…</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805">Atacatorii de pe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> te pot înșela, determinându-te să faci ceva periculos, cum ar fi să instalezi software sau să îți dezvălui informațiile cu caracter personal (de exemplu, parole, numere de telefon sau date despre cardurile de credit). <ph name="BEGIN_LEARN_MORE_LINK" />Află mai multe<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Traducerea nu a reușit din cauza unei erori de server.</translation>
<translation id="3759461132968374835">Nu există blocări raportate recent. Blocările care au avut loc când raportarea blocărilor era dezactivată nu vor apărea aici.</translation>
+<translation id="3760561303380396507">Folosești Windows Hello în loc de CVC?</translation>
<translation id="3761718714832595332">Ascunde starea</translation>
<translation id="3765032636089507299">Pagina Navigare sigură este în construcție.</translation>
<translation id="3778403066972421603">Dorești să salvezi acest card în Contul Google și pe acest dispozitiv?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">Mărimea 16</translation>
<translation id="3797522431967816232">Prc3 (Plic)</translation>
<translation id="3807873520724684969">Conținutul dăunător a fost blocat.</translation>
+<translation id="3808375843007691220">Avertisment: acestea sunt funcții experimentale!</translation>
<translation id="3810973564298564668">Gestionează</translation>
<translation id="382518646247711829">Dacă utilizați un server proxy...</translation>
<translation id="3828924085048779000">Trebuie să fie introdusă expresia de acces.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">Actualizează data și ora</translation>
<translation id="3884278016824448484">Identificator de gadget în conflict</translation>
<translation id="3885155851504623709">Parohie</translation>
-<translation id="3886446263141354045">Solicitarea de a accesa acest site a fost trimisă către <ph name="NAME" /></translation>
<translation id="3890664840433101773">Adaugă o adresă de e-mail</translation>
<translation id="3901925938762663762">Cardul este expirat</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Folosești WebAuthn în loc de CVC?</translation>
<translation id="3946209740501886391">Întreabă întotdeauna pe acest site</translation>
<translation id="3949571496842715403">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; în certificatul său de securitate nu este specificat câmpul Nume alternative subiect. Cauza poate fi o eroare de configurare sau interceptarea conexiunii de către un atacator.</translation>
<translation id="3949601375789751990">Istoricul de navigare apare aici</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Niciunul}=1{De la 1 site }few{De la # site-uri }other{De la # de site-uri }}</translation>
<translation id="397105322502079400">Se calculează...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> este blocat</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> a activat în browser Protecția Chrome împotriva amenințărilor la adresa întreprinderilor. Protecția Chrome împotriva amenințărilor la adresa întreprinderilor are acces la o parte din datele tale.</translation>
<translation id="3987940399970879459">Mai puțin de 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 pagină web în apropiere}few{# pagini web în apropiere}other{# de pagini web în apropiere}}</translation>
<translation id="4030383055268325496">&amp;Anulați adăugarea</translation>
<translation id="4032320456957708163">Browserul este gestionat de <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Linkul pe care l-ai deschis trimite către un site pe care nu îl accesezi de obicei. Poate încerca să te inducă în eroare.</translation>
<translation id="4058922952496707368">Cheie „<ph name="SUBKEY" />”: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Plic)</translation>
<translation id="4067947977115446013">Adaugă o adresă validă</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">Numărul de serie al gadgetului este nevalid</translation>
<translation id="410351446219883937">Redare automată</translation>
<translation id="4103763322291513355">Accesați &lt;strong&gt;chrome://policy&lt;/strong&gt; pentru a vedea adresele URL introduse pe lista neagră și alte politici impuse de către administratorul de sistem.</translation>
+<translation id="4108231218301530806">Folosește amprenta pentru a confirma cardul data viitoare.</translation>
<translation id="4110652170750985508">Examinează plata</translation>
<translation id="4112140312785995938">Derulează înapoi</translation>
<translation id="4116663294526079822">Permiteți întotdeauna pe acest site</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">Semnătură de verificare nevalidă</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Încă <ph name="ITEM_COUNT" /> articol}few{Încă <ph name="ITEM_COUNT" /> articole}other{Încă <ph name="ITEM_COUNT" /> de articole}}</translation>
+<translation id="4176463684765177261">Dezactivat</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Pentru a plăti mai rapid data viitoare, adaugă cardul și adresa de facturare în Contul Google.</translation>
<translation id="4196861286325780578">&amp;Repetați mutarea</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">Resetează parola</translation>
<translation id="4279811152705618813">Dispozitivul <ph name="DEVICE_TYPE" /> este gestionat de <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Acest card a fost salvat în Contul tău Google}few{Aceste carduri au fost salvate în Contul tău Google}other{Aceste carduri au fost salvate în Contul tău Google}}</translation>
+<translation id="428847186335018806">Scanează fișierele pe care le descarci sau le încarci în Chrome.</translation>
<translation id="42981349822642051">Extinde</translation>
<translation id="4302965934281694568">Chou3 (Plic)</translation>
<translation id="4305817255990598646">Comută</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">Carte poștală)</translation>
<translation id="443673843213245140">Utilizarea unui proxy este dezactivată, dar o configurare proxy este specificată în mod explicit.</translation>
<translation id="445100540951337728">Carduri de debit acceptate</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> – comportament suspect</translation>
<translation id="4466881336512663640">Modificările aduse formularului se vor pierde. Sigur dorești să continui?</translation>
<translation id="4477350412780666475">Melodia următoare</translation>
<translation id="4482953324121162758">Acest site nu va fi tradus.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">&amp;Anulați ștergerea</translation>
<translation id="4597348597567598915">Mărimea 8</translation>
<translation id="4600854749408232102">C6/C5 (Plic)</translation>
+<translation id="464342062220857295">Funcții de căutare</translation>
<translation id="4646534391647090355">Accesez acum</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; certificatul său de securitate conține erori. Cauza poate fi o configurare greșită sau interceptarea conexiunii de către un atacator.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A (Plic)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Conexiunea a fost întreruptă</translation>
-<translation id="471880041731876836">Nu ai permisiunea să accesezi acest site</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />să rulezi Diagnostice rețea Windows<ph name="END_LINK" />;</translation>
<translation id="4726672564094551039">Reîncărcați politicile</translation>
<translation id="4728558894243024398">Platformă</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">Încadrați în pagină</translation>
<translation id="4850886885716139402">Afișează</translation>
<translation id="4854362297993841467">Această metodă de livrare nu este disponibilă. Încearcă altă metodă.</translation>
-<translation id="4858792381671956233">Ți-ai întrebat părinții dacă poți accesa acest site</translation>
<translation id="4864052566555297930">Sfat privind siguranța:</translation>
<translation id="4876188919622883022">Afișare simplificată</translation>
<translation id="4876305945144899064">Niciun nume de utilizator</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">Reactivează avertismentele</translation>
<translation id="4984339528288761049">Prc5 (Plic)</translation>
<translation id="4989163558385430922">Afișează-le pe toate</translation>
+<translation id="4989542687859782284">Indisponibile</translation>
<translation id="4989809363548539747">Acest plugin nu este acceptat</translation>
+<translation id="4995216769782533993">Confirmă codul de securitate pentru a permite accesul site-ului la detaliile cardului</translation>
<translation id="5002932099480077015">Dacă este activată, Chrome va stoca o copie a cardului pe acest dispozitiv, pentru completarea mai rapidă a formularelor.</translation>
<translation id="5015510746216210676">Numele dispozitivului:</translation>
<translation id="5017554619425969104">Textul copiat de tine</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 de biți)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Confirmă cardul</translation>
<translation id="5135404736266831032">Gestionează adresele...</translation>
<translation id="5138227688689900538">Afișează mai puțin</translation>
<translation id="5141240743006678641">Criptează parolele sincronizate cu datele de conectare Google</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (Plic)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funcțiile care se aplică la nivel de sistem pot fi setate numai de proprietar: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Atenție: această politică nu a fost îmbinată așa cum este indicat în politica PolicyListMultipleSourceMergeList, deoarece nu este o parte din politicile din dicționar care pot fi îmbinate.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Oprește</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">Setările pentru politică nu au putut fi stocate</translation>
<translation id="5371425731340848620">Actualizează cardul</translation>
<translation id="5377026284221673050">„Ora este setată în trecut”, „Ora este setată în viitor” sau „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;”</translation>
-<translation id="5377179979757081683">Această pagină ar putea încerca să te păcălească, să fure informații cu caracter personal sau să dăuneze dispozitivului. Ai grijă atunci când introduci informații cu caracter personal sau deschizi fișiere descărcate.</translation>
<translation id="5384855140246857529">Pentru a-ți folosi cardurile pe toate dispozitivele, conectează-te și activează sincronizarea.</translation>
<translation id="5386426401304769735">Lanțul de certificate pentru acest site conține un certificat semnat folosind SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,7 @@
<translation id="5457113250005438886">Nevalide</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Repetați editarea</translation>
+<translation id="5473728911100096288">Dacă activezi aceste funcții, vei folosi funcții vechi care vor dispărea în versiunile ulterioare.</translation>
<translation id="5478437291406423475">B6/C4 (Plic)</translation>
<translation id="5481076368049295676">Acest conținut ar putea încerca să instaleze software periculos pe dispozitivul tău, care îți fură sau îți șterge informațiile. <ph name="BEGIN_LINK" />Afișează oricum<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Adaugă o adresă validă</translation>
@@ -863,7 +876,6 @@
<translation id="5570825185877910964">Protejează contul</translation>
<translation id="5571083550517324815">Nu se poate prelua de la această adresă. Selectează altă adresă.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 în uz}few{# în uz}other{# în uz}})</translation>
-<translation id="5572851009514199876">Pornește și conectează-te la Chrome, ca acesta să verifice dacă ai permisiunea să accesezi site-ul.</translation>
<translation id="5580958916614886209">Verifică luna în care expiră și încearcă din nou</translation>
<translation id="5586446728396275693">Nu există adrese salvate</translation>
<translation id="5595485650161345191">Editează adresa</translation>
@@ -871,6 +883,7 @@
<translation id="560412284261940334">Gestionarea nu este acceptată</translation>
<translation id="5605670050355397069">Registru</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Acest site poate fi fals sau fraudulos. Chrome îți recomandă să ieși acum.</translation>
<translation id="5610142619324316209">să verifici conexiunea;</translation>
<translation id="5610807607761827392">Poți să gestionezi cardurile și adresele în <ph name="BEGIN_LINK" />Setări<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> te-a redirecționat de prea multe ori.</translation>
@@ -894,11 +907,11 @@
<translation id="5720705177508910913">Utilizator curent</translation>
<translation id="5728056243719941842">C5 (Plic)</translation>
<translation id="5730040223043577876">Chrome îți recomandă să resetezi parola dacă ai folosit-o și pe alte site-uri.</translation>
-<translation id="5732392974455271431">Părinții tăi îl pot debloca pentru tine</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Salvează cardul în Contul Google}few{Salvează cardurile în Contul Google}other{Salvează cardurile în Contul Google}}</translation>
<translation id="5763042198335101085">Introdu o adresă de e-mail validă</translation>
<translation id="5765072501007116331">Pentru a vedea metodele de livrare și cerințele, selectează o adresă</translation>
<translation id="5778550464785688721">Control complet asupra dispozitivelor MIDI</translation>
+<translation id="5781136890105823427">Experimentul a fost activat</translation>
<translation id="578305955206182703">Chihlimbar</translation>
<translation id="57838592816432529">Dezactivează sunetul</translation>
<translation id="5784606427469807560">A apărut o eroare la confirmarea cardului. Verifică conexiunea la internet și încearcă din nou.</translation>
@@ -915,13 +928,16 @@
<translation id="5860033963881614850">Dezactivat</translation>
<translation id="5863847714970149516">Următoarea pagină poate să genereze costuri</translation>
<translation id="5866257070973731571">Adaugă un număr de telefon</translation>
+<translation id="5866898949289125849">Se afișează o pagină cu instrumente pentru dezvoltatori</translation>
<translation id="5869405914158311789">Acest site nu poate fi accesat</translation>
<translation id="5869522115854928033">Parole salvate</translation>
<translation id="5887400589839399685">Cardul a fost salvat</translation>
<translation id="5893752035575986141">Se acceptă carduri de credit.</translation>
+<translation id="5895138241574237353">Reîncepe</translation>
<translation id="5901630391730855834">Galben</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizat)</translation>
<translation id="5916664084637901428">Activat</translation>
+<translation id="59174027418879706">Activat</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Salvezi cardul în Contul Google?</translation>
<translation id="5922853866070715753">Aproape finalizat</translation>
@@ -955,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Folosești cardurile pe toate dispozitivele?</translation>
<translation id="6059925163896151826">Dispozitive USB</translation>
+<translation id="6060009363608157444">Mod DnsOverHttps nevalid.</translation>
<translation id="6080696365213338172">Ați accesat conținut utilizând un certificat oferit de administrator. Datele pe care le transmiteți către <ph name="DOMAIN" /> pot fi interceptate de administratorul dvs.</translation>
<translation id="6094273045989040137">Adnotează</translation>
<translation id="610911394827799129">Contul Google poate să ofere alte forme ale istoricului de navigare la <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1020,12 @@
<translation id="6404511346730675251">Modifică marcajul</translation>
<translation id="6406765186087300643">C0 (Plic)</translation>
<translation id="6410264514553301377">Introdu data de expirare și codul CVC pentru <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Ți-ai întrebat părintele dacă poți accesa acest site</translation>
<translation id="6415778972515849510">Chromium te poate ajuta să îți protejezi Contul Google și să îți schimbi parola.</translation>
-<translation id="6417515091412812850">Nu se poate verifica dacă certificatul a fost revocat.</translation>
<translation id="6431585503458005759">Nu stoca</translation>
<translation id="6433490469411711332">Editează informațiile de contact</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> a refuzat conexiunea.</translation>
<translation id="6434309073475700221">Renunță</translation>
+<translation id="6435221585574090192">Permite administratorului accesul la datele despre evenimentele de securitate semnalate de Protecția Chrome împotriva amenințărilor la adresa întreprinderilor. Între acestea se pot număra adresele URL ale paginilor, numele și metadatele fișierelor, numele de utilizator al dispozitivului și numele de utilizator Chrome.</translation>
<translation id="6440503408713884761">Ignorat</translation>
<translation id="6446163441502663861">Kahu (Plic)</translation>
<translation id="6446608382365791566">Adaugă mai multe informații</translation>
@@ -1018,20 +1034,19 @@
<translation id="6465306955648956876">Gestionează parolele...</translation>
<translation id="647261751007945333">Politici privind dispozitivele</translation>
<translation id="6476284679642588870">Gestionează metodele de plată</translation>
-<translation id="6477321094435799029">Chrome a detectat un cod neobișnuit pe această pagină și l-a blocat pentru a-ți proteja informațiile cu caracter personal (de exemplu, parole, numere de telefon sau carduri de credit).</translation>
<translation id="6489534406876378309">Începeți încărcarea rapoartelor de blocare</translation>
<translation id="6499038740797743453">Resetezi parola?</translation>
<translation id="6507833130742554667">Se acceptă carduri de credit și de debit.</translation>
<translation id="650855688985305916">Da, stochează</translation>
<translation id="6508722015517270189">repornește Chrome;</translation>
<translation id="6517596291481585650">Atenție: această politică nu a fost îmbinată ca listă așa cum este indicat de politică, deoarece nu este o listă.</translation>
+<translation id="6518133107902771759">Confirmați</translation>
<translation id="6521745193039995384">Inactivă</translation>
<translation id="6529602333819889595">&amp;Repetați ștergerea</translation>
<translation id="6534179046333460208">Sugestii pentru Webul material</translation>
<translation id="6545864417968258051">Căutare Bluetooth</translation>
<translation id="6554795675067793129">Contul tău este administrat de <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Repetă</translation>
-<translation id="6563469144985748109">Administratorul nu l-a aprobat încă</translation>
<translation id="6569060085658103619">Se afișează pagina unei extensii</translation>
<translation id="6578796323535178455">C2 (Plic)</translation>
<translation id="6579990219486187401">Roz deschis</translation>
@@ -1049,11 +1064,13 @@
<translation id="6643016212128521049">Șterge</translation>
<translation id="6644283850729428850">Această politică este învechită.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Niciunul}=1{De pe un site (nu te va deconecta de la Contul Google)}few{De pe # site-uri (nu te va deconecta de la Contul Google)}other{De pe # de site-uri (nu te va deconecta de la Contul Google)}}</translation>
+<translation id="6652101503459149953">Folosește Windows Hello</translation>
<translation id="6657585470893396449">Parolă</translation>
<translation id="6670613747977017428">Înapoi la zona sigură.</translation>
<translation id="6671697161687535275">Elimini sugestia pentru formular din Chromium?</translation>
<translation id="6685834062052613830">Deconectează-te și finalizează configurarea</translation>
<translation id="6689271823431384964">Chrome oferă salvarea cardurilor în Contul Google pentru că te-ai conectat. Poți schimba acest comportament în setări. Numele titularului de card vine din contul tău.</translation>
+<translation id="6707256370811247129">Scanează conținutul memoriei cache și fișierele pe care le descarci sau le încarci în Chrome.</translation>
<translation id="6710213216561001401">Înapoi</translation>
<translation id="6710594484020273272">&lt;Introdu termenul de căutare&gt;</translation>
<translation id="671076103358959139">Indicativ de înregistrare:</translation>
@@ -1061,10 +1078,10 @@
<translation id="6738516213925468394">Datele au fost criptate cu <ph name="BEGIN_LINK" />expresia de acces pentru sincronizare<ph name="END_LINK" /> la <ph name="TIME" />. Introdu expresia de acces pentru a începe sincronizarea.</translation>
<translation id="674375294223700098">Eroare de certificat de server necunoscută.</translation>
<translation id="6744009308914054259">În timp ce aștepți o conexiune, poți accesa Descărcările pentru a citi articole offline.</translation>
+<translation id="6747611005629681221">Avertisment: acestea sunt funcții învechite!</translation>
<translation id="6753269504797312559">Valoarea politicii</translation>
<translation id="6757797048963528358">Dispozitivul este inactiv.</translation>
<translation id="6768213884286397650">Hagaki (Carte poștală)</translation>
-<translation id="6778737459546443941">Părintele tău nu l-a aprobat încă</translation>
<translation id="67862343314499040">Violet</translation>
<translation id="6786747875388722282">Extensii</translation>
<translation id="6790428901817661496">Redă</translation>
@@ -1072,6 +1089,7 @@
<translation id="681021252041861472">Câmp obligatoriu</translation>
<translation id="6810899417690483278">ID-ul de personalizare</translation>
<translation id="6825578344716086703">Ai încercat să accesezi <ph name="DOMAIN" />, dar serverul a prezentat un certificat semnat folosind un algoritm de semnare slab (cum ar fi SHA-1). Acest lucru înseamnă că este posibil ca datele de conectare de securitate prezentate de server să fie falsificate sau ca serverul să nu fie cel așteptat (este posibil să comunici cu un atacator).</translation>
+<translation id="6826370046007623921">Prevenirea pierderii datelor</translation>
<translation id="6831043979455480757">Tradu</translation>
<translation id="6839929833149231406">Zonă</translation>
<translation id="6852204201400771460">Reîncarci aplicația?</translation>
@@ -1084,7 +1102,6 @@
<translation id="6891596781022320156">Nivelul politicii nu este acceptat.</translation>
<translation id="6895330447102777224">Cardul tău este confirmat</translation>
<translation id="6897140037006041989">User Agent</translation>
-<translation id="6903319715792422884">Ne poți ajuta să îmbunătățim Navigarea sigură dacă trimiți la Google anumite <ph name="BEGIN_WHITEPAPER_LINK" />informații despre sistem și conținutul paginii<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utilizator:</translation>
<translation id="6934672428414710184">Acest nume provine din Contul tău Google</translation>
<translation id="6944692733090228304">Ai introdus parola pe un site care nu este gestionat de <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Pentru a proteja contul, nu folosi aceeași parolă pentru alte aplicații și site-uri.</translation>
@@ -1129,6 +1146,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Lavandă</translation>
<translation id="717330890047184534">Cod Gaia:</translation>
+<translation id="7174545416324379297">Îmbinată</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> și încă <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Serverul pe care dorești să îl accesezi, <ph name="ORIGIN" />, a solicitat
ca o politică de securitate să fie aplicată tuturor solicitărilor către el. Însă, în loc să
@@ -1166,6 +1184,7 @@ Detalii suplimentare:
<translation id="7320336641823683070">Ajutor pentru conectare</translation>
<translation id="733354035281974745">Modificarea contului local al dispozitivului</translation>
<translation id="7334320624316649418">&amp;Repetați reordonarea</translation>
+<translation id="7337706099755338005">Nu este disponibil pe platforma ta.</translation>
<translation id="733923710415886693">Certificatul serverului nu a fost dezvăluit folosind Transparența certificatului.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Este afiliat:</translation>
@@ -1197,7 +1216,6 @@ Detalii suplimentare:
<translation id="7440140511386898319">Explorează în timp ce ești offline</translation>
<translation id="7441627299479586546">Subiectul politicii este greșit</translation>
<translation id="7442725080345379071">Portocaliu deschis</translation>
-<translation id="7444046173054089907">Acest site este blocat</translation>
<translation id="7445762425076701745">Identitatea serverului la care te-ai conectat nu poate fi validată complet. Ești conectat(ă) la un server folosind un nume valid numai în rețeaua ta, pentru care o autoritate de certificare externă nu are nici o modalitate de a-l valida. Deoarece unele autorități de certificare vor emite certificate pentru aceste nume oricum, nu există nicio modalitate de a te asigura că ești conectat(ă) la site-ul corect și nu la un atacator.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />să afli mai multe<ph name="END_LINK" /> despre această problemă.</translation>
<translation id="7455133967321480974">Utilizați setarea prestabilită la nivel global (Blocați)</translation>
@@ -1219,9 +1237,9 @@ Detalii suplimentare:
<translation id="7538364083937897561">A2 (Plic)</translation>
<translation id="7542403920425041731">După ce confirmi, acest site va avea acces la detaliile cardului tău.</translation>
<translation id="7542995811387359312">Completarea automată a cardului de credit este dezactivată, deoarece acest formular nu utilizează o conexiune sigură.</translation>
-<translation id="7543525346216957623">Roagă-ți părintele</translation>
<translation id="7548892272833184391">Remediază erorile de conexiune</translation>
<translation id="7549584377607005141">Pentru a fi afișată corespunzător, această pagină web necesită date pe care le-ați introdus anterior. Puteți trimite aceste date din nou, dar astfel veți repeta orice acțiuni realizate anterior de această pagină.</translation>
+<translation id="7550637293666041147">Numele de utilizator al dispozitivului și numele de utilizator Chrome</translation>
<translation id="7552846755917812628">Încearcă următoarele sfaturi:</translation>
<translation id="7554791636758816595">Filă nouă</translation>
<translation id="7564049878696755256">Este posibil să pierzi accesul la contul <ph name="ORG_NAME" /> sau să fii victima unui furt de identitate. Chrome îți recomandă să îți schimbi acum parola.</translation>
@@ -1236,6 +1254,7 @@ Detalii suplimentare:
<translation id="7610193165460212391">Valoarea este în afara intervalului <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Expiră pe: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Aveți deja date criptate utilizând o versiune diferită a parolei pentru Contul dvs. Google. Introduceți-o mai jos.</translation>
+<translation id="7625784245512586808">Protecția Chrome împotriva amenințărilor la adresa întreprinderilor</translation>
<translation id="7633909222644580952">Date privind performanța și rapoarte de blocare</translation>
<translation id="7637571805876720304">Elimini cardul de credit din Chromium?</translation>
<translation id="7638605456503525968">Porturi seriale</translation>
@@ -1248,7 +1267,6 @@ Detalii suplimentare:
<translation id="7668654391829183341">Dispozitiv necunoscut</translation>
<translation id="7669271284792375604">Atacatorii de pe acest site pot încerca să te înșele pentru a instala programe care dăunează experienței de navigare (de exemplu, schimbând pagina de pornire sau afișând anunțuri suplimentare pe site-urile pe care le accesezi).</translation>
<translation id="7676643023259824263">Caută text din clipboard, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platformă și cloud</translation>
<translation id="7681101578153515023">Schimbă motorul de căutare</translation>
<translation id="7682287625158474539">Expediere</translation>
<translation id="7687186412095877299">Completează formularele de plată cu metodele de plată salvate</translation>
@@ -1263,7 +1281,6 @@ Detalii suplimentare:
<translation id="7723047071702270851">Editează cardul</translation>
<translation id="774634243536837715">Conținutul periculos a fost blocat.</translation>
<translation id="7752995774971033316">Negestionat</translation>
-<translation id="7755287808199759310">Părintele tău îl poate debloca pentru tine</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Este posibil ca firewallul sau software-ul antivirus să fi blocat conexiunea.</translation>
<translation id="7759163816903619567">Domeniu afișat:</translation>
@@ -1307,7 +1324,6 @@ Detalii suplimentare:
<translation id="8004582292198964060">Browser</translation>
<translation id="8009225694047762179">Gestionează parolele</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Acest card și adresa de facturare vor fi salvate. Le vei putea folosi după ce te-ai conectat la <ph name="USER_EMAIL" />.}few{Aceste carduri și adresele de facturare vor fi salvate. Le vei putea folosi după ce te-ai conectat la <ph name="USER_EMAIL" />.}other{Aceste carduri și adresele de facturare vor fi salvate. Le vei putea folosi după ce te-ai conectat la <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Momentan, nu ți-am putut contacta părinții. Încearcă din nou.</translation>
<translation id="8025119109950072390">Atacatorii de pe acest site te pot înșela, determinându-te să faci ceva periculos, cum ar fi să instalezi software sau să îți dezvălui informațiile cu caracter personal (de exemplu, parole, numere de telefon sau carduri de credit).</translation>
<translation id="8034522405403831421">Această pagină este în <ph name="SOURCE_LANGUAGE" />. Doriți traducere în <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Stilou</translation>
@@ -1318,6 +1334,7 @@ Detalii suplimentare:
<translation id="8041940743680923270">Utilizați setarea prestabilită la nivel global (Întrebați)</translation>
<translation id="8042918947222776840">Alege metoda de preluare</translation>
<translation id="8057711352706143257">„<ph name="SOFTWARE_NAME" />” nu este configurat corect. De obicei, problema se remediază dezinstalând „<ph name="SOFTWARE_NAME" />” <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">De acum înainte, nu va mai fi nevoie să introduci codul de securitate al cardului</translation>
<translation id="8066955247577885446">A apărut o eroare.</translation>
<translation id="8074253406171541171">10x13 (Plic)</translation>
<translation id="8078141288243656252">Nu se poate adnota când este rotit</translation>
@@ -1348,6 +1365,7 @@ Detalii suplimentare:
<translation id="8211406090763984747">Conexiunea este securizată</translation>
<translation id="8218327578424803826">Locație atribuită:</translation>
<translation id="8220146938470311105">C7/C6 (Plic)</translation>
+<translation id="8220639454292072926">Raportare la nivel de întreprindere</translation>
<translation id="8225771182978767009">Persoana care a configurat computerul a ales să blocheze acest site.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Deschide pagina într-o filă incognito nouă</translation>
@@ -1402,24 +1420,24 @@ Detalii suplimentare:
<translation id="8508648098325802031">Pictograma Căutare</translation>
<translation id="8522552481199248698">Chrome te poate ajuta să îți protejezi Contul Google și să îți schimbi parola.</translation>
<translation id="8543181531796978784">Poți să <ph name="BEGIN_ERROR_LINK" />raportezi o problemă privind detectarea<ph name="END_ERROR_LINK" /> sau, dacă îți asumi riscurile de securitate, poți să <ph name="BEGIN_LINK" />accesezi acest site nesigur<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Întrebări? Contactează persoana care îți monitorizează profilul.</translation>
<translation id="8553075262323480129">Traducerea nu a reușit, deoarece nu a putut fi stabilită limba paginii.</translation>
<translation id="8557066899867184262">Codul CVC se află pe spatele cardului.</translation>
<translation id="8559762987265718583">O conexiune privată la <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> nu poate fi stabilită, deoarece data și ora dispozitivului (<ph name="DATE_AND_TIME" />) sunt incorecte.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> site suspect</translation>
<translation id="8564985650692024650">Chromium îți recomandă să resetezi parola pentru <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> dacă ai folosit-o și pe alte site-uri.</translation>
<translation id="8571890674111243710">Se traduce pagina în <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Adăugați telefon
</translation>
-<translation id="859285277496340001">Certificatul nu specifică un mecanism pentru a verifica dacă acesta a fost revocat.</translation>
<translation id="860043288473659153">Nume titular de card</translation>
<translation id="861775596732816396">Mărimea 4</translation>
-<translation id="8620436878122366504">Părinții tăi nu l-au aprobat încă</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Salvează cardul pe acest dispozitiv</translation>
<translation id="8626112503828625890">Stochezi datele de facturare în Contul Google?</translation>
+<translation id="8647750283161643317">Resetați-le pe toate la valorile prestabilite</translation>
<translation id="8663226718884576429">Rezumatul comenzii, <ph name="TOTAL_LABEL" />, Mai multe detalii</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, răspuns, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Disponibilă</translation>
<translation id="8703575177326907206">Conexiunea la <ph name="DOMAIN" /> nu este criptată.</translation>
<translation id="8718314106902482036">Plata nu a fost finalizată</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, sugestie de căutare</translation>
@@ -1430,6 +1448,7 @@ Detalii suplimentare:
<translation id="8738058698779197622">Pentru a stabili o conexiune securizată, ceasul trebuie să fie setat corect. Aceasta deoarece certificatele pe care site-urile le folosesc pentru a se identifica sunt valabile numai pentru anumite intervale de timp. Din moment ce ora de pe dispozitiv este incorectă, Chromium nu poate verifica aceste certificate.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Adresa DNS&lt;/abbr&gt; pentru <ph name="HOST_NAME" /> nu a putut fi găsită. Se diagnostichează problema.</translation>
<translation id="874846938927089722">Carduri de credit și preplătite acceptate</translation>
+<translation id="874918643257405732">Marchează această filă</translation>
<translation id="8759274551635299824">Acest card este expirat</translation>
<translation id="8761567432415473239">Recent, Navigarea sigură Google a <ph name="BEGIN_LINK" />descoperit programe dăunătoare<ph name="END_LINK" /> pe <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Dispozitiv USB</translation>
@@ -1459,6 +1478,7 @@ Detalii suplimentare:
<translation id="8938939909778640821">Carduri de credit și preplătite acceptate</translation>
<translation id="8943282376843390568">Verde-gălbui</translation>
<translation id="8957210676456822347">Autorizarea prin portalul captiv</translation>
+<translation id="8962950042226115166">Site suspect</translation>
<translation id="8968766641738584599">Salvează cardul</translation>
<translation id="8971063699422889582">Certificatul serverului a expirat.</translation>
<translation id="8975012916872825179">Include informații precum numerele de telefon, adresele de e-mail și adresele de expediere</translation>
@@ -1481,24 +1501,24 @@ Detalii suplimentare:
<translation id="9035022520814077154">Eroare de securitate</translation>
<translation id="9038649477754266430">Folosește un serviciu de predicții pentru a încărca paginile mai rapid</translation>
<translation id="9039213469156557790">În plus, această pagină include alte resurse care nu sunt securizate. Aceste resurse sunt vizibile pentru alți utilizatori în cursul transferului și pot fi modificate de un atacator pentru a schimba comportamentul paginii.</translation>
+<translation id="9044359186343685026">Folosește Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Ai încercat să accesezi <ph name="DOMAIN" />, dar serverul a prezentat un certificat nevalid.</translation>
<translation id="9050666287014529139">Expresie de acces</translation>
<translation id="9065203028668620118">Editează</translation>
<translation id="9065745800631924235">Căutare <ph name="TEXT" /> în istoric</translation>
<translation id="9069693763241529744">Blocată de o extensie</translation>
-<translation id="9076283476770535406">Poate include conținut destinat adulților</translation>
<translation id="9076630408993835509">Browserul nu este gestionat de o companie sau o altă organizație. Este posibil ca activitatea de pe acest dispozitiv să fie gestionată în afara Chrome. <ph name="BEGIN_LINK" />Află mai multe<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Sunt necesare mai multe informații</translation>
<translation id="9080712759204168376">Rezumatul comenzii</translation>
<translation id="9089260154716455634">Politica privind intervalele de inactivitate:</translation>
<translation id="9095388113577226029">Mai multe limbi...</translation>
+<translation id="9098981495403789647">Administratorul a activat în browser Protecția Chrome împotriva amenințărilor la adresa întreprinderilor. Protecția Chrome împotriva amenințărilor la adresa întreprinderilor are acces la o parte din datele tale.</translation>
<translation id="9103872766612412690">Site-ul <ph name="SITE" /> folosește în mod obișnuit criptarea pentru a-ți proteja informațiile. Când Chromium a încercat să se conecteze la <ph name="SITE" /> de această dată, site-ul a returnat date de conectare neobișnuite și incorecte. Acest lucru s-a întâmplat fie pentru că un atacator încearcă să falsifice site-ul <ph name="SITE" />, fie pentru că un ecran de conectare Wi-Fi a întrerupt conexiunea. Securitatea informațiilor tale nu a fost afectată, deoarece Chromium a oprit conexiunea înainte ca datele să fie transferate.</translation>
<translation id="9106062320799175032">Adaugă o adresă de facturare</translation>
<translation id="9114524666733003316">Se confirmă cardul…</translation>
<translation id="9128870381267983090">Conectați-vă la rețea</translation>
<translation id="9137013805542155359">Afișează originalul</translation>
-<translation id="9137248913990643158">Pornește și conectează-te la Chrome înainte de a folosi această aplicație.</translation>
<translation id="9141013498910525015">Gestionează adresele</translation>
<translation id="9148088599418889305">Alege metoda de expediere</translation>
<translation id="9148507642005240123">&amp;Anulați editarea</translation>
diff --git a/chromium/components/strings/components_strings_ru.xtb b/chromium/components/strings/components_strings_ru.xtb
index a7b9a7300d5..c3ec3f76e2e 100644
--- a/chromium/components/strings/components_strings_ru.xtb
+++ b/chromium/components/strings/components_strings_ru.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Укажите имя владельца карты</translation>
<translation id="1089439967362294234">Сменить пароль</translation>
+<translation id="1096545575934602868">Максимальное число записей в этом поле: <ph name="MAX_ITEMS_LIMIT" />. Остальные записи не будут сохранены.</translation>
<translation id="109743633954054152">Открыть настройки паролей в Chrome</translation>
<translation id="1103523840287552314">Всегда переводить <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Если флажок установлен, Chrome будет хранить на этом устройстве данные карты для быстрого заполнения форм.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Открыть <ph name="BEGIN_LINK" />кешированную версию<ph name="END_LINK" /> страницы <ph name="URL" /></translation>
<translation id="1156303062776767266">Вы просматриваете локальный или общий файл</translation>
<translation id="1158211211994409885">Сайт <ph name="HOST_NAME" /> неожиданно разорвал соединение.</translation>
+<translation id="115926840831309955">Проверьте CVC-код и повторите попытку или измените дату окончания срока действия.</translation>
<translation id="1161325031994447685">Подключитесь к сети Wi-Fi ещё раз.</translation>
<translation id="1165039591588034296">Ошибка</translation>
<translation id="1175364870820465910">&amp;Печать...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"ПО, установленное на компьютере, не позволяет Chrome безопасно подключиться к Интернету" (только для Windows)</translation>
<translation id="1294154142200295408">Модификации для командной строки</translation>
<translation id="129553762522093515">Недавно закрытые</translation>
+<translation id="1298536327547837046">Проверка на вредоносное ПО</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Удалите файлы cookie<ph name="END_LINK" />.</translation>
+<translation id="1307966114820526988">Устаревшие функции</translation>
<translation id="1320233736580025032">Prc1 (конверт)</translation>
<translation id="132301787627749051">Поиск по изображению из буфера обмена</translation>
<translation id="1323433172918577554">Развернуть</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google Таблицы</translation>
<translation id="1527263332363067270">Ожидание подключения…</translation>
<translation id="1529521330346880926">10x15 (конверт)</translation>
+<translation id="1530707389502320859">Сайт, на который вы пытались перейти, похож на подделку. Иногда злоумышленники создают копии сайтов и вносят небольшие изменения в их адрес, которые сложно заметить сразу.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Подтвердите действие</translation>
<translation id="153384715582417236">Пока это всё</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">ОС</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Недоступно, так как документ слишком большой</translation>
-<translation id="1721312023322545264">Для доступа к этой странице требуется разрешение пользователя <ph name="NAME" /></translation>
<translation id="1721424275792716183">*Обязательное поле</translation>
<translation id="1727741090716970331">Введите правильный номер карты</translation>
<translation id="1728677426644403582">Вы просматриваете код страницы</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Сайты, которые вы посещали, и время пребывания на них</translation>
<translation id="1826516787628120939">Проверка</translation>
<translation id="1834321415901700177">Сайт содержит вредоносное ПО</translation>
+<translation id="1838374766361614909">Удалить условия поиска</translation>
<translation id="1839551713262164453">При проверке значений политик обнаружены ошибки</translation>
<translation id="1842969606798536927">Оплатить</translation>
<translation id="1871208020102129563">Выбрано использование фиксированных прокси-серверов, а не URL PAC-скрипта.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Свернуть список</translation>
<translation id="1898423065542865115">Фильтры</translation>
<translation id="1914326953223720820">Распаковщик файлов</translation>
+<translation id="1915697529809968049">Использовать Touch ID вместо CVC-кода?</translation>
<translation id="1916770123977586577">Чтобы применить к сайту новые настройки, перезагрузите страницу</translation>
<translation id="1919345977826869612">Реклама</translation>
<translation id="1919367280705858090">Как устранить определенные виды ошибок</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Закладки <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Не удалось выполнить сериализацию</translation>
<translation id="1974060860693918893">Дополнительные</translation>
+<translation id="1974883374937189061">Отправлять в Google <ph name="BEGIN_WHITEPAPER_LINK" />URL и контент некоторых посещенных страниц, а также ограниченную информацию о системе<ph name="END_WHITEPAPER_LINK" /> для повышения безопасности Chrome. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Версия ПО</translation>
<translation id="1981206234434200693">Удалить данные о работе в браузере Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{и ещё 1}one{и ещё #}few{и ещё #}many{и ещё #}other{и ещё #}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Недопустимый формат года.</translation>
<translation id="2212735316055980242">Политика для устройства не найдена</translation>
<translation id="2213606439339815911">Извлечение записей…</translation>
+<translation id="2215727959747642672">Редактирование файлов</translation>
<translation id="2218879909401188352">Злоумышленники могут использовать сайт <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, чтобы установить опасные приложения, которые причиняют вред устройствам, увеличивают расходы на мобильную связь и крадут личные данные. <ph name="BEGIN_LEARN_MORE_LINK" />Подробнее…<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Нет подключения к Интернету</translation>
<translation id="2230458221926704099">Чтобы устранить неполадки, проведите <ph name="BEGIN_LINK" />диагностику<ph name="END_LINK" /> подключения.</translation>
<translation id="2239100178324503013">Отправить</translation>
+<translation id="2248949050832152960">Использовать WebAuthn</translation>
<translation id="225207911366869382">Это значение для данного правила больше не используется.</translation>
<translation id="2257315177824333709">Сейчас невозможно сохранить карту.</translation>
<translation id="2262243747453050782">Ошибка HTTP</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">Недействительный URL поисковой системы.</translation>
<translation id="2482878487686419369">Уведомления</translation>
<translation id="248348093745724435">Правила для компьютера</translation>
-<translation id="2485387744899240041">Имена пользователей для вашего устройства и браузера</translation>
<translation id="2491120439723279231">Сертификат сервера содержит ошибки.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Синтаксический анализатор JSON</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Назад</translation>
<translation id="2503184589641749290">Дебетовые карты и карты предоплаты, которые принимаются к оплате</translation>
<translation id="2505268675989099013">Защитить аккаунт</translation>
+<translation id="2515335152965840738">ИГНОРИРОВАТЬ</translation>
<translation id="2515629240566999685">Проверьте уровень сигнала сети.</translation>
<translation id="2523886232349826891">Карта будет сохранена только на этом устройстве</translation>
<translation id="2524461107774643265">Укажите дополнительную информацию</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Отправить</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Нет}=1{1 пароль (для <ph name="DOMAIN_LIST" />)}=2{2 пароля (для <ph name="DOMAIN_LIST" />)}one{# пароль (для <ph name="DOMAIN_LIST" />)}few{# пароля (для <ph name="DOMAIN_LIST" />)}many{# паролей (для <ph name="DOMAIN_LIST" />)}other{# пароля (для <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Закройте другие вкладки, расширения и приложения.</translation>
-<translation id="267371737713284912">для отмены нажмите <ph name="MODIFIER_KEY_DESCRIPTION" /></translation>
<translation id="2674170444375937751">Удалить эти страницы из истории посещений?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Закрыть</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">Значение не соответствует формату.</translation>
<translation id="2705137772291741111">Невозможно прочитать копию сайта, сохраненную в кеше.</translation>
<translation id="2709516037105925701">Автозаполнение</translation>
-<translation id="2712173769900027643">Попросить разрешения</translation>
<translation id="2713444072780614174">Белый</translation>
<translation id="2720342946869265578">Мое окружение</translation>
<translation id="2721148159707890343">Запрос выполнен успешно</translation>
<translation id="2728127805433021124">Сертификат сервера подписан с использованием ненадежного алгоритма.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Выполните диагностику подключения<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Используя эти функции, вы можете потерять данные браузера, а также подвергаете риску свою безопасность и конфиденциальность. Если включить их, они будут действовать для всех пользователей браузера.</translation>
<translation id="2735043616039983645">Для этого правила существует более одного источника с конфликтующими значениями.</translation>
<translation id="2738330467931008676">Выбрать адрес получения</translation>
<translation id="2740531572673183784">ОК</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">Соединение сброшено.</translation>
<translation id="2788784517760473862">Кредитные карты, которые принимаются к оплате</translation>
<translation id="2792012897584536778">Администраторы этого устройства настроили сертификаты безопасности, которые дают возможность просматривать контент посещаемых вами сайтов.</translation>
-<translation id="2794233252405721443">Сайт заблокирован</translation>
<translation id="2799020568854403057">Сайт содержит вредоносные приложения</translation>
<translation id="2799223571221894425">Перезапустить</translation>
<translation id="2803306138276472711">Система Google по проверке безопасности сайтов недавно обнаружила на <ph name="SITE" /> <ph name="BEGIN_LINK" />вредоносное ПО<ph name="END_LINK" />. Будьте внимательны, иногда даже на безопасных сайтах появляются вирусы.</translation>
+<translation id="2815364696811431560">ЗАКРЫТЬ САЙТ</translation>
<translation id="2824775600643448204">Адресная строка и строка поиска</translation>
<translation id="2826760142808435982">Соединение зашифровано и проверено с помощью <ph name="CIPHER" />. В качестве механизма обмена ключами используется <ph name="KX" />.</translation>
<translation id="2835170189407361413">Очистить форму</translation>
<translation id="2847118875340931228">Открыть окно в режиме инкогнито</translation>
<translation id="2850739647070081192">Invite (конверт)</translation>
-<translation id="2851634818064021665">Для доступа к этой странице требуется разрешение.</translation>
<translation id="2856444702002559011">Злоумышленники могут пытаться похитить ваши данные с сайта <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (например, пароли, сообщения или номера банковских карт). <ph name="BEGIN_LEARN_MORE_LINK" />Подробнее…<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Сохранить карту?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Если функция включена, Chromium будет хранить на этом устройстве данные карты для быстрого заполнения форм.</translation>
<translation id="2985398929374701810">Укажите действительный адрес.</translation>
<translation id="2986368408720340940">Этот способ выдачи недоступен. Выберите другой.</translation>
+<translation id="2987034854559945715">Совпадений не найдено.</translation>
<translation id="2991174974383378012">Доступ веб-сайтов</translation>
<translation id="2991571918955627853">Веб-сайт <ph name="SITE" /> использует механизм HSTS. Открыть сайт в настоящее время нельзя. Сбой мог быть вызван сетевой ошибкой или действиями злоумышленников. Скорее всего, сайт заработает через некоторое время.</translation>
<translation id="3005723025932146533">Открыть сохраненную копию</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Неверный тип политики</translation>
<translation id="3037605927509011580">Опаньки...</translation>
<translation id="3041612393474885105">Данные сертификата</translation>
+<translation id="3057676462092457419">Режим DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> пока не поддерживается, настройки изменены на <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (конверт)</translation>
<translation id="3061707000357573562">Исправление сервиса</translation>
<translation id="3064966200440839136">Вы выйдете из режима инкогнито, чтобы произвести оплату во внешнем приложении. Продолжить?</translation>
@@ -418,6 +427,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Отменить оплату</translation>
<translation id="3207960819495026254">Добавлено в закладки.</translation>
+<translation id="3209034400446768650">На этой странице может взиматься плата</translation>
<translation id="3225919329040284222">Сертификат не соответствует встроенным параметрам определенных сайтов с высоким уровнем безопасности.</translation>
<translation id="3226128629678568754">Чтобы повторно ввести данные, необходимые для загрузки страницы, нажмите "Обновить".</translation>
<translation id="3227137524299004712">Микрофон</translation>
@@ -425,7 +435,6 @@
<translation id="3229041911291329567">Версия вашего устройства и браузера</translation>
<translation id="323107829343500871">Введите CVC-код карты <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Всегда находить важный контент на этом сайте</translation>
-<translation id="3254409185687681395">Добавить страницу в закладки</translation>
<translation id="3270847123878663523">&amp;Отменить изменение порядка</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Укажите имя владельца карты</translation>
@@ -435,7 +444,6 @@
<translation id="3320021301628644560">Добавьте платежный адрес</translation>
<translation id="3324983252691184275">Малиновый</translation>
<translation id="3338095232262050444">Защищено</translation>
-<translation id="3345135638360864351">Не удалось отправить пользователю <ph name="NAME" /> запрос на доступ к этому сайту. Повторите попытку.</translation>
<translation id="3355823806454867987">Изменить настройки прокси-сервера...</translation>
<translation id="3361596688432910856">В Chrome <ph name="BEGIN_EMPHASIS" />не будет сохраняться<ph name="END_EMPHASIS" /> следующая информация:
<ph name="BEGIN_LIST" />
@@ -469,18 +477,15 @@
<translation id="3462200631372590220">Скрыть подробности</translation>
<translation id="3467763166455606212">Укажите имя владельца карты.</translation>
<translation id="3468054117417088249">Открыта вкладка <ph name="TAB_SWITCH_SUFFIX" />. Чтобы переключиться на нее, нажмите Tab, а затем Ввод.</translation>
-<translation id="3479539252931486093">Этот сайт не должен быть заблокирован? <ph name="BEGIN_LINK" />Сообщите нам об этом<ph name="END_LINK" />.</translation>
<translation id="3479552764303398839">Не сейчас</translation>
<translation id="3484560055331845446">Вы можете потерять доступ к аккаунту Google. Рекомендуем немедленно сменить пароль. После этого потребуется снова войти в аккаунт.</translation>
<translation id="3495081129428749620">Найти на странице
"<ph name="PAGE_TITLE" />"</translation>
-<translation id="3498215018399854026">Не удалось связаться с вашими родителями. Повторите попытку.</translation>
<translation id="3512163584740124171">Действует правило с более высоким приоритетом.</translation>
<translation id="3528171143076753409">Сертификат сервера не является доверенным.</translation>
<translation id="3528485271872257980">Темно-коричневый</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Как минимум 1 запись на синхронизируемых устройствах}=1{1 запись (не считая данных на синхронизируемых устройствах)}one{# запись (не считая данных на синхронизируемых устройствах)}few{# записи (не считая данных на синхронизируемых устройствах)}many{# записей (не считая данных на синхронизируемых устройствах)}other{# записей (не считая данных на синхронизируемых устройствах)}}</translation>
<translation id="3539171420378717834">Хранить данные карты на этом устройстве</translation>
-<translation id="3556433843310711081">Для разблокировки обратитесь к администратору.</translation>
<translation id="3566021033012934673">Подключение не защищено</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Подтвердите действие на странице <ph name="SITE" /></translation>
@@ -508,6 +513,7 @@
<translation id="3678529606614285348">Открыть страницу в новом окне в режиме инкогнито (Ctrl + Shift + N)</translation>
<translation id="3679803492151881375"><ph name="CRASH_TIME" />: отчет о сбоях сохранен. <ph name="UPLOAD_TIME" />: отчет о сбоях загружен.</translation>
<translation id="3681007416295224113">Данные сертификата</translation>
+<translation id="3701427423622901115">Сброс подтвержден.</translation>
<translation id="3704162925118123524">Возможно, вам нужно перейти на страницу входа используемой сети.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Загрузка...</translation>
@@ -524,6 +530,7 @@
<translation id="3748148204939282805">Посещение сайта <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> может привести к установке вредоносного ПО или хищению личной информации (например, паролей, телефонных номеров и данных банковских карт). <ph name="BEGIN_LEARN_MORE_LINK" />Подробнее…<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Сбой при переводе вследствие ошибки сервера.</translation>
<translation id="3759461132968374835">Нет записей о недавних сбоях. Сбои, которые произошли при отключенной функции записи сбоев, здесь не отображаются.</translation>
+<translation id="3760561303380396507">Использовать Windows Hello вместо CVC-кода?</translation>
<translation id="3761718714832595332">Скрыть статус</translation>
<translation id="3765032636089507299">Страница безопасного просмотра находится в разработке.</translation>
<translation id="3778403066972421603">Хотите сохранить карту в аккаунте Google и на этом устройстве?</translation>
@@ -533,6 +540,7 @@
<translation id="3789155188480882154">Размер: 16</translation>
<translation id="3797522431967816232">Prc3 (конверт)</translation>
<translation id="3807873520724684969">Заблокирован опасный контент</translation>
+<translation id="3808375843007691220">Внимание! Экспериментальные функции.</translation>
<translation id="3810973564298564668">Настроить</translation>
<translation id="382518646247711829">Если вы используете прокси-сервер...</translation>
<translation id="3828924085048779000">Пустые кодовые фразы запрещены.</translation>
@@ -541,11 +549,11 @@
<translation id="3858027520442213535">Обновить дату и время</translation>
<translation id="3884278016824448484">Конфликт идентификаторов устройств</translation>
<translation id="3885155851504623709">Округ</translation>
-<translation id="3886446263141354045">Ваш запрос на доступ к сайту отправлен пользователю <ph name="NAME" /></translation>
<translation id="3890664840433101773">Добавление адреса электронной почты</translation>
<translation id="3901925938762663762">Срок действия карты истек</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" />. <ph name="ERROR" />.</translation>
+<translation id="3939773374150895049">Использовать WebAuthn вместо CVC-кода?</translation>
<translation id="3946209740501886391">Всегда спрашивать на этом сайте</translation>
<translation id="3949571496842715403">Сервер не может подтвердить связь с доменом <ph name="DOMAIN" />. В его сертификате безопасности не указаны альтернативные варианты имен. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
<translation id="3949601375789751990">История просмотров появится здесь</translation>
@@ -556,11 +564,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Нет}=1{С 1 сайта }one{С # сайта }few{С # сайтов }many{С # сайтов }other{С # сайта }}</translation>
<translation id="397105322502079400">Вычисление…</translation>
<translation id="3973234410852337861">Сайт <ph name="HOST_NAME" /> заблокирован</translation>
+<translation id="3981540111851280311">Администратор домена <ph name="ENROLLMENT_DOMAIN" /> включил в вашем браузере систему защиты Chrome Enterprise, у которой есть доступ к некоторым вашим данным.</translation>
<translation id="3987940399970879459">Менее 1 МБ</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 веб-страница поблизости}one{# веб-страница поблизости}few{# веб-страницы поблизости}many{# веб-страниц поблизости}other{# веб-страницы поблизости}}</translation>
<translation id="4030383055268325496">&amp;Отменить добавление</translation>
<translation id="4032320456957708163">Этим браузером управляет администратор <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Эта ссылка ведет не на тот сайт, который вы обычно посещаете. Возможно, вас пытаются ввести в заблуждение.</translation>
<translation id="4058922952496707368">Ключ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (конверт)</translation>
<translation id="4067947977115446013">Введите действительный адрес</translation>
@@ -573,6 +581,7 @@
<translation id="4103249731201008433">Серийный номер устройства недействителен</translation>
<translation id="410351446219883937">Автовоспроизведение</translation>
<translation id="4103763322291513355">Чтобы просмотреть URL, внесенные в черный список, и другие правила, заданные системным администратором, перейдите по адресу: &lt;strong&gt;chrome://policy&lt;/strong&gt;.</translation>
+<translation id="4108231218301530806">В следующий раз подтверждать эту карту с помощью отпечатков пальцев</translation>
<translation id="4110652170750985508">Просмотр платежа</translation>
<translation id="4112140312785995938">Перемотать назад</translation>
<translation id="4116663294526079822">Всегда разрешать на этом сайте</translation>
@@ -587,6 +596,7 @@
<translation id="4171400957073367226">Подтверждающая подпись недействительна</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Ещё <ph name="ITEM_COUNT" /> товар}one{Ещё <ph name="ITEM_COUNT" /> товар}few{Ещё <ph name="ITEM_COUNT" /> товара}many{Ещё <ph name="ITEM_COUNT" /> товаров}other{Ещё <ph name="ITEM_COUNT" /> товара}}</translation>
+<translation id="4176463684765177261">Отключено</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" />: <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Чтобы ускорить процесс оплаты в будущем, сохраните карту и платежный адрес в аккаунте Google.</translation>
<translation id="4196861286325780578">&amp;Повторить перемещение</translation>
@@ -623,6 +633,7 @@
<translation id="4277028893293644418">Сбросить пароль</translation>
<translation id="4279811152705618813">Ваше устройство <ph name="DEVICE_TYPE" /> находится под управлением домена <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Карта сохранена в аккаунте Google.}one{Карты сохранены в аккаунте Google.}few{Карты сохранены в аккаунте Google.}many{Карты сохранены в аккаунте Google.}other{Карты сохранены в аккаунте Google.}}</translation>
+<translation id="428847186335018806">Проверять файлы, которые вы скачиваете и загружаете через Chrome.</translation>
<translation id="42981349822642051">Развернуть</translation>
<translation id="4302965934281694568">Chou3 (конверт)</translation>
<translation id="4305817255990598646">Переключиться</translation>
@@ -652,7 +663,6 @@
<translation id="4435702339979719576">Открытка</translation>
<translation id="443673843213245140">Прокси-сервер отключен, но при этом его конфигурация задана явным образом.</translation>
<translation id="445100540951337728">Дебетовые карты, которые принимаются к оплате</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> подозрительные действия</translation>
<translation id="4466881336512663640">Внесенные в форму изменения не сохранятся. Продолжить?</translation>
<translation id="4477350412780666475">Следующий трек</translation>
<translation id="4482953324121162758">Этот сайт не будет переводиться автоматически.</translation>
@@ -679,6 +689,7 @@
<translation id="4594403342090139922">&amp;Отменить удаление</translation>
<translation id="4597348597567598915">Размер: 8</translation>
<translation id="4600854749408232102">C6/C5 (конверт)</translation>
+<translation id="464342062220857295">Функции поиска</translation>
<translation id="4646534391647090355">Перейти сейчас</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Не удалось подтвердить, что это сервер <ph name="DOMAIN" />. Его сертификат безопасности содержит ошибки. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
@@ -687,7 +698,6 @@
<translation id="4691835149146451662">Architecture-A (конверт)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Соединение прервано</translation>
-<translation id="471880041731876836">Доступ запрещен</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Выполните диагностику сети в Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Повторно загрузить политики</translation>
<translation id="4728558894243024398">Платформа</translation>
@@ -715,7 +725,6 @@
<translation id="4816492930507672669">По размеру страницы</translation>
<translation id="4850886885716139402">Посмотреть</translation>
<translation id="4854362297993841467">Этот способ доставки недоступен. Выберите другой.</translation>
-<translation id="4858792381671956233">Запрос на просмотр сайта отправлен вашим родителям</translation>
<translation id="4864052566555297930">Совет по безопасности:</translation>
<translation id="4876188919622883022">Упрощенный просмотр</translation>
<translation id="4876305945144899064">Имя пользователя не указано</translation>
@@ -739,7 +748,9 @@
<translation id="4974590756084640048">Снова включить предупреждения</translation>
<translation id="4984339528288761049">Prc5 (конверт)</translation>
<translation id="4989163558385430922">Показать все</translation>
+<translation id="4989542687859782284">Недоступные</translation>
<translation id="4989809363548539747">Плагин не поддерживается</translation>
+<translation id="4995216769782533993">Чтобы предоставить этому сайту доступ к реквизитам карты, подтвердите защитный код.</translation>
<translation id="5002932099480077015">Chrome будет хранить на этом устройстве данные карты для быстрого заполнения форм.</translation>
<translation id="5015510746216210676">Имя компьютера:</translation>
<translation id="5017554619425969104">Скопированный текст</translation>
@@ -768,6 +779,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 бит)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Подтвердите данные карты</translation>
<translation id="5135404736266831032">Управление адресами…</translation>
<translation id="5138227688689900538">Свернуть</translation>
<translation id="5141240743006678641">Шифровать синхронизированные пароли с помощью учетных данных Google</translation>
@@ -794,6 +806,7 @@
<translation id="5251803541071282808">Облако</translation>
<translation id="5252000469029418751">C7 (конверт)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Системные функции может устанавливать только владелец (<ph name="OWNER_EMAIL" />).</translation>
<translation id="5273658854610202413">Внимание! Это правило не объединено в соответствии с правилом PolicyDictionaryMultipleSourceMergeList, так как оно не относится к словарю.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Завершить</translation>
@@ -817,7 +830,6 @@
<translation id="536296301121032821">Не удалось сохранить настройки политики</translation>
<translation id="5371425731340848620">Изменить информацию о карте</translation>
<translation id="5377026284221673050">"Часы отстают", "Часы спешат" или &lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;</translation>
-<translation id="5377179979757081683">Посещение этой страницы может привести к хищению личной информации или повреждению устройства. Будьте внимательны, вводя персональные данные и открывая скачанные файлы.</translation>
<translation id="5384855140246857529">Чтобы пользоваться картами на всех своих устройствах, войдите в аккаунт и включите синхронизацию.</translation>
<translation id="5386426401304769735">В цепочке сертификатов этого сайта есть сертификат, подписанный с помощью алгоритма SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -831,6 +843,7 @@
<translation id="5457113250005438886">Недопустимые данные</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> контакт}one{<ph name="CONTACT_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> контакт}few{<ph name="CONTACT_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> контакта}many{<ph name="CONTACT_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> контактов}other{<ph name="CONTACT_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> контакта}}</translation>
<translation id="5470861586879999274">&amp;Повторить изменения</translation>
+<translation id="5473728911100096288">После включения вы получите доступ к устаревшим функциям, которые будут удалены в следующих версиях.</translation>
<translation id="5478437291406423475">B6/C4 (конверт)</translation>
<translation id="5481076368049295676">Посещение этой страницы может привести к установке вредоносной программы, которая похищает или удаляет данные. <ph name="BEGIN_LINK" />Все равно продолжить<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Введите действительный адрес</translation>
@@ -847,14 +860,13 @@
<translation id="553484882784876924">Prc6 (конверт)</translation>
<translation id="5540224163453853">Не удалось найти указанную статью</translation>
<translation id="5541546772353173584">Добавьте адрес электронной почты</translation>
-<translation id="5545756402275714221">Новости для вас</translation>
+<translation id="5545756402275714221">Статьи для вас</translation>
<translation id="5556459405103347317">Перезагрузить</translation>
<translation id="5560088892362098740">Дата окончания срока действия</translation>
<translation id="5565735124758917034">Активен</translation>
<translation id="5570825185877910964">Защитить аккаунт</translation>
<translation id="5571083550517324815">Этот адрес не поддерживается. Выберите другой.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{используется 1 файл}one{используется # файл}few{используется # файла}many{используется # файлов}other{используется # файла}})</translation>
-<translation id="5572851009514199876">Выполните вход, чтобы Chrome определил, разрешен ли вам доступ к этому сайту.</translation>
<translation id="5580958916614886209">Проверьте месяц в сроке действия карты и повторите попытку</translation>
<translation id="5586446728396275693">Нет сохраненных адресов</translation>
<translation id="5595485650161345191">Изменить адрес</translation>
@@ -862,6 +874,7 @@
<translation id="560412284261940334">Управление устройствами не поддерживается</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Этот сайт может оказаться поддельным или мошенническим. Советуем покинуть его прямо сейчас.</translation>
<translation id="5610142619324316209">Проверьте подключение к Интернету.</translation>
<translation id="5610807607761827392">Сведения о картах и адресах можно изменить в <ph name="BEGIN_LINK" />настройках<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Сайт <ph name="HOST_NAME" /> выполнил переадресацию слишком много раз.</translation>
@@ -885,11 +898,11 @@
<translation id="5720705177508910913">Текущий пользователь</translation>
<translation id="5728056243719941842">C5 (конверт)</translation>
<translation id="5730040223043577876">Chrome рекомендует сбросить пароль, если вы использовали его на других сайтах.</translation>
-<translation id="5732392974455271431">Для разблокировки обратитесь к родителям.</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Сохраните карту в аккаунте Google}one{Сохраните карты в аккаунте Google}few{Сохраните карты в аккаунте Google}many{Сохраните карты в аккаунте Google}other{Сохраните карты в аккаунте Google}}</translation>
<translation id="5763042198335101085">Укажите действительный адрес электронной почты.</translation>
<translation id="5765072501007116331">Выберите адрес, чтобы посмотреть способы и условия доставки.</translation>
<translation id="5778550464785688721">Полный контроль над MIDI-устройствами</translation>
+<translation id="5781136890105823427">Эксперимент включен</translation>
<translation id="578305955206182703">Янтарный</translation>
<translation id="57838592816432529">Отключить звук</translation>
<translation id="5784606427469807560">Не удалось подтвердить данные карты. Проверьте подключение к Интернету и повторите попытку.</translation>
@@ -906,13 +919,16 @@
<translation id="5860033963881614850">ВЫКЛ</translation>
<translation id="5863847714970149516">При открытии этой страницы с вашего счета могут быть списаны средства</translation>
<translation id="5866257070973731571">Добавьте номер телефона</translation>
+<translation id="5866898949289125849">Вы просматриваете страницу инструментов разработчика</translation>
<translation id="5869405914158311789">Не удается получить доступ к сайту</translation>
<translation id="5869522115854928033">Сайты с сохраненными паролями</translation>
<translation id="5887400589839399685">Карта сохранена</translation>
<translation id="5893752035575986141">Принимаются кредитные карты.</translation>
+<translation id="5895138241574237353">Перезапустить</translation>
<translation id="5901630391730855834">Желтый</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (данные синхронизируются)</translation>
<translation id="5916664084637901428">ВКЛ</translation>
+<translation id="59174027418879706">Включен</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Сохранить карту в аккаунте Google?</translation>
<translation id="5922853866070715753">Почти готово…</translation>
@@ -946,6 +962,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Хотите использовать карты на всех устройствах?</translation>
<translation id="6059925163896151826">USB-устройства</translation>
+<translation id="6060009363608157444">Недопустимый режим DnsOverHttps.</translation>
<translation id="6080696365213338172">Вы используете сертификат, предоставленный администратором, поэтому он может заблокировать передачу данных на сайт <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">Аннотировать</translation>
<translation id="610911394827799129">Информация о других ваших действиях в Интернете может также храниться на странице <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -994,13 +1011,12 @@
<translation id="6404511346730675251">Изменить закладку</translation>
<translation id="6406765186087300643">C0 (конверт)</translation>
<translation id="6410264514553301377">Введите срок действия и CVC-код карты <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Запрос на просмотр сайта отправлен вашему родителю</translation>
<translation id="6415778972515849510">Защитите свой аккаунт Google и смените пароль с помощью Chromium.</translation>
-<translation id="6417515091412812850">Не удается проверить, был ли отозван сертификат.</translation>
<translation id="6431585503458005759">Не сохранять</translation>
<translation id="6433490469411711332">Изменить контактную информацию</translation>
<translation id="6433595998831338502">Сайт <ph name="HOST_NAME" /> не позволяет установить соединение.</translation>
<translation id="6434309073475700221">Отменить передачу</translation>
+<translation id="6435221585574090192">Отправлять администратору данные о событиях безопасности, определенных системой защиты Chrome Enterprise как потенциально опасные. К таким данным относятся URL страниц, названия файлов, метаданные файлов, название вашего устройства и имя пользователя Chrome.</translation>
<translation id="6440503408713884761">Пропускается</translation>
<translation id="6446163441502663861">Kahu (конверт)</translation>
<translation id="6446608382365791566">Укажите дополнительную информацию</translation>
@@ -1009,20 +1025,19 @@
<translation id="6465306955648956876">Управление паролями…</translation>
<translation id="647261751007945333">Правила устройства</translation>
<translation id="6476284679642588870">Управление способами оплаты</translation>
-<translation id="6477321094435799029">Браузер Chrome обнаружил на этой странице необычный код и заблокировал его, чтобы защитить ваши данные (например, пароли, а также номера телефонов и банковских карт).</translation>
<translation id="6489534406876378309">Начать загрузку сведений об ошибках</translation>
<translation id="6499038740797743453">Сбросить пароль?</translation>
<translation id="6507833130742554667">Принимаются кредитные и дебетовые карты.</translation>
<translation id="650855688985305916">Да</translation>
<translation id="6508722015517270189">Перезапустите Google Chrome.</translation>
<translation id="6517596291481585650">Внимание! Это правило не объединено, так как оно не является списком.</translation>
+<translation id="6518133107902771759">Подтвердить</translation>
<translation id="6521745193039995384">Не выбрано</translation>
<translation id="6529602333819889595">&amp;Повторить удаление</translation>
<translation id="6534179046333460208">Интернет вокруг нас: рекомендации</translation>
<translation id="6545864417968258051">Поиск Bluetooth-устройств</translation>
<translation id="6554795675067793129">Ваш аккаунт принадлежит домену <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Повторить</translation>
-<translation id="6563469144985748109">Ещё не одобрено администратором</translation>
<translation id="6569060085658103619">Вы просматриваете страницу расширения</translation>
<translation id="6578796323535178455">C2 (конверт)</translation>
<translation id="6579990219486187401">Светло-розовый</translation>
@@ -1040,11 +1055,13 @@
<translation id="6643016212128521049">Удалить</translation>
<translation id="6644283850729428850">Правило устарело.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Нет}=1{С 1 сайта (вы останетесь в аккаунте Google)}one{С # сайта (вы останетесь в аккаунте Google)}few{С # сайтов (вы останетесь в аккаунте Google)}many{С # сайтов (вы останетесь в аккаунте Google)}other{С # сайта (вы останетесь в аккаунте Google)}}</translation>
+<translation id="6652101503459149953">Использовать Windows Hello</translation>
<translation id="6657585470893396449">Пароль</translation>
<translation id="6670613747977017428">К настройкам безопасности</translation>
<translation id="6671697161687535275">Удалить подсказку из Chromium?</translation>
<translation id="6685834062052613830">Выйдите из аккаунта и завершите настройку</translation>
<translation id="6689271823431384964">Chrome предлагает вам сохранить карты в аккаунте Google, поскольку вы вошли в систему. Этот параметр можно изменить в разделе настроек. Имя владельца карты взято из вашего аккаунта.</translation>
+<translation id="6707256370811247129">Проверять содержимое кеша и файлов, которые вы скачиваете и загружаете через Chrome.</translation>
<translation id="6710213216561001401">Назад</translation>
<translation id="6710594484020273272">&lt;Введите поисковый запрос&gt;</translation>
<translation id="671076103358959139">Токен регистрации:</translation>
@@ -1052,10 +1069,10 @@
<translation id="6738516213925468394">Данные были зашифрованы <ph name="TIME" /> с помощью <ph name="BEGIN_LINK" />кодовой фразы<ph name="END_LINK" />. Введите ее, чтобы начать синхронизацию.</translation>
<translation id="674375294223700098">Неизвестная ошибка сертификата сервера.</translation>
<translation id="6744009308914054259">В ожидании подключения вы можете открыть скачанные файлы и почитать статьи офлайн.</translation>
+<translation id="6747611005629681221">Внимание! Устаревшие функции.</translation>
<translation id="6753269504797312559">Значение правила</translation>
<translation id="6757797048963528358">Устройство находится в спящем режиме.</translation>
<translation id="6768213884286397650">Hagaki (открытка)</translation>
-<translation id="6778737459546443941">Ещё не одобрено родителем</translation>
<translation id="67862343314499040">Фиолетовый</translation>
<translation id="6786747875388722282">Расширения</translation>
<translation id="6790428901817661496">Воспроизвести</translation>
@@ -1063,6 +1080,7 @@
<translation id="681021252041861472">Обязательное поле</translation>
<translation id="6810899417690483278">Идентификатор персонализации</translation>
<translation id="6825578344716086703">Вы пытаетесь обратиться к серверу в домене <ph name="DOMAIN" />, но его сертификат подписан с помощью ненадежного алгоритма (например, SHA-1). Это означает, что учетные данные безопасности и сам сервер могут оказаться поддельными. Возможно, вы имеете дело со злоумышленниками.</translation>
+<translation id="6826370046007623921">Предотвращение потери данных</translation>
<translation id="6831043979455480757">Перевести</translation>
<translation id="6839929833149231406">Район</translation>
<translation id="6852204201400771460">Перезапустить приложение?</translation>
@@ -1075,7 +1093,6 @@
<translation id="6891596781022320156">Значение правила не поддерживается.</translation>
<translation id="6895330447102777224">Ваша карта подтверждена</translation>
<translation id="6897140037006041989">User Agent</translation>
-<translation id="6903319715792422884">Чтобы улучшить режим Безопасного просмотра, вы можете <ph name="BEGIN_WHITEPAPER_LINK" />отправлять системную информацию и содержимое страниц<ph name="END_WHITEPAPER_LINK" /> в Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Пользователь:</translation>
<translation id="6934672428414710184">Это имя из вашего аккаунта Google</translation>
<translation id="6944692733090228304">Вы ввели пароль на сайте, который не находится под управлением организации <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Чтобы защитить свой аккаунт, не используйте этот пароль для других приложений и сайтов.</translation>
@@ -1120,6 +1137,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> способ оплаты}one{<ph name="PAYMENT_METHOD_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> способ оплаты}few{<ph name="PAYMENT_METHOD_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> способа оплаты}many{<ph name="PAYMENT_METHOD_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> способов оплаты}other{<ph name="PAYMENT_METHOD_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> способа оплаты}}</translation>
<translation id="7153618581592392745">Бледно-лиловый</translation>
<translation id="717330890047184534">Идентификатор GAIA:</translation>
+<translation id="7174545416324379297">Объединенное правило</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> вариант доставки}one{<ph name="SHIPPING_OPTION_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> вариант доставки}few{<ph name="SHIPPING_OPTION_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> варианта доставки}many{<ph name="SHIPPING_OPTION_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> вариантов доставки}other{<ph name="SHIPPING_OPTION_PREVIEW" /> и ещё <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> варианта доставки}}</translation>
<translation id="7177397715882417099">Ко всем запросам, отправляемым на сервер <ph name="ORIGIN" />, применяются правила безопасности. Однако вместо того, чтобы передать правила, сервер перенаправил браузер по другому адресу, поэтому браузер не может выполнить ваш запрос для сайта <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Сохранять и автоматически подставлять платежные данные</translation>
@@ -1154,6 +1172,7 @@
<translation id="7320336641823683070">Устранение ошибок при подключении к Интернету</translation>
<translation id="733354035281974745">Приоритет локального аккаунта на устройстве</translation>
<translation id="7334320624316649418">&amp;Повторить изменение порядка</translation>
+<translation id="7337706099755338005">Недоступно на вашей платформе.</translation>
<translation id="733923710415886693">Сертификат сервера не проходил проверку.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Аффилированный пользователь:</translation>
@@ -1185,7 +1204,6 @@
<translation id="7440140511386898319">Почитать офлайн</translation>
<translation id="7441627299479586546">Неверный субъект политики</translation>
<translation id="7442725080345379071">Светло-оранжевый</translation>
-<translation id="7444046173054089907">Сайт заблокирован</translation>
<translation id="7445762425076701745">Идентификация сервера, к которому вы подключились, не может быть полностью подтверждена. Вы подключились к серверу, используя название, которое действительно только в вашей сети; владелец этого сервера не может быть проверен или подтвержден внешним центром сертификации. Так как некоторые центры сертификации могут выдавать сертификаты для подобных названий, отсутствуют гарантии в том, что это действительно нужный вам сайт, а не сайт злоумышленника.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Узнайте больше<ph name="END_LINK" /> об этой проблеме.</translation>
<translation id="7455133967321480974">Использовать глобальный параметр по умолчанию (блокировать)</translation>
@@ -1207,9 +1225,9 @@
<translation id="7538364083937897561">A2 (конверт)</translation>
<translation id="7542403920425041731">После этого данные вашей карты будут переданы сайту.</translation>
<translation id="7542995811387359312">Автозаполнение отключено – незащищенное подключение.</translation>
-<translation id="7543525346216957623">Обратитесь за помощью к родителю</translation>
<translation id="7548892272833184391">Как устранить ошибки при подключении к Интернету</translation>
<translation id="7549584377607005141">Для корректного отображения веб-страницы требуются введенные ранее данные. Их можно отправить повторно, но в этом случае все действия на странице будут выполнены снова.</translation>
+<translation id="7550637293666041147">Имя пользователя устройства и браузера Chrome</translation>
<translation id="7552846755917812628">Попробуйте сделать следующее:</translation>
<translation id="7554791636758816595">Новая вкладка</translation>
<translation id="7564049878696755256">Кто-то посторонний мог получить доступ к вашим личным данным или аккаунту в домене <ph name="ORG_NAME" />. Рекомендуем немедленно сменить пароль.</translation>
@@ -1224,6 +1242,7 @@
<translation id="7610193165460212391">Значение <ph name="VALUE" /> лежит за пределами разрешенного диапазона.</translation>
<translation id="7613889955535752492">Срок действия: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">У вас уже есть данные, зашифрованные с другой версией пароля к аккаунту Google. Введите этот пароль ниже.</translation>
+<translation id="7625784245512586808">Система защиты Chrome Enterprise</translation>
<translation id="7633909222644580952">Данные о производительности и отчеты о сбоях</translation>
<translation id="7637571805876720304">Удалить кредитную карту из Chromium?</translation>
<translation id="7638605456503525968">Последовательные порты</translation>
@@ -1236,7 +1255,6 @@
<translation id="7668654391829183341">Неизвестное устройство</translation>
<translation id="7669271284792375604">Посещение этого сайта может привести к установке вредоносного ПО, которое будет мешать работе браузера (например, меняя стартовую страницу или показывая дополнительную рекламу на сайтах).</translation>
<translation id="7676643023259824263">Поиск по тексту "<ph name="TEXT" />" из буфера обмена</translation>
-<translation id="7679176406634891508">Платформа и облачный сервис</translation>
<translation id="7681101578153515023">Изменить поисковую систему</translation>
<translation id="7682287625158474539">Адрес доставки</translation>
<translation id="7687186412095877299">Сохранять и автоматически заполнять платежные данные</translation>
@@ -1251,7 +1269,6 @@
<translation id="7723047071702270851">Измените данные карты</translation>
<translation id="774634243536837715">Опасный контент заблокирован</translation>
<translation id="7752995774971033316">Не управляется</translation>
-<translation id="7755287808199759310">Для разблокировки обратитесь к родителю.</translation>
<translation id="7757555340166475417">Dai Pa Kai</translation>
<translation id="7758069387465995638">Возможно, подключение заблокировано брандмауэром или антивирусным ПО.</translation>
<translation id="7759163816903619567">Показывать домен:</translation>
@@ -1295,7 +1312,6 @@
<translation id="8004582292198964060">Браузер</translation>
<translation id="8009225694047762179">Управление паролями</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Данные этой карты и ее платежный адрес будут сохранены. Вы сможете пользоваться ею после входа в аккаунт <ph name="USER_EMAIL" />.}one{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}few{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}many{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}other{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Не удалось связаться с вашими родителями. Повторите попытку.</translation>
<translation id="8025119109950072390">Посещение этого сайта может привести к установке вредоносного ПО или хищению личной информации (например, паролей, телефонных номеров и данных банковских карт).</translation>
<translation id="8034522405403831421">Язык этой страницы: <ph name="SOURCE_LANGUAGE" />. Перевести ее на <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Ручка</translation>
@@ -1306,6 +1322,7 @@
<translation id="8041940743680923270">Использовать глобальный параметр по умолчанию (спрашивать)</translation>
<translation id="8042918947222776840">Выбрать способ получения</translation>
<translation id="8057711352706143257">Программа "<ph name="SOFTWARE_NAME" />" настроена неправильно. Чтобы устранить проблему, удалите программу "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Вам больше не нужно будет вводить защитный код карты.</translation>
<translation id="8066955247577885446">Произошла ошибка.</translation>
<translation id="8074253406171541171">10x13 (конверт)</translation>
<translation id="8078141288243656252">Недоступно, когда документ повернут</translation>
@@ -1336,6 +1353,7 @@
<translation id="8211406090763984747">Безопасное подключение</translation>
<translation id="8218327578424803826">Назначенное местоположение:</translation>
<translation id="8220146938470311105">C7/C6 (конверт)</translation>
+<translation id="8220639454292072926">Отчеты Enterprise</translation>
<translation id="8225771182978767009">Тот, кто настраивал компьютер, заблокировал этот сайт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" /> и <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Открыть страницу в новой вкладке инкогнито</translation>
@@ -1390,23 +1408,23 @@
<translation id="8508648098325802031">Значок поиска</translation>
<translation id="8522552481199248698">Защитите свой аккаунт Google и смените пароль с помощью Chrome.</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />Сообщите о зараженном сайте<ph name="END_ERROR_LINK" />. Если вы готовы подвергнуть риску личные данные, то можете <ph name="BEGIN_LINK" />перейти на страницу<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Есть вопросы? Обратитесь к человеку, который контролирует ваш профиль.</translation>
<translation id="8553075262323480129">Перевод не удался, так как не удается определить язык страницы.</translation>
<translation id="8557066899867184262">CVC-код указан на обратной стороне карты.</translation>
<translation id="8559762987265718583">Не удалось установить защищенное соединение с доменом <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> из-за неверных настроек системных часов и календаря (<ph name="DATE_AND_TIME" />).</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> подозрительный сайт</translation>
<translation id="8564985650692024650">Chromium рекомендует сбросить пароль, используемый в подразделении <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, если вы указывали его на других сайтах.</translation>
<translation id="8571890674111243710">Перевод страницы на <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Добавьте номер</translation>
-<translation id="859285277496340001">Этот сертификат не определяет механизм проверки отзыва.</translation>
<translation id="860043288473659153">Имя владельца карты</translation>
<translation id="861775596732816396">Размер: 4</translation>
-<translation id="8620436878122366504">Ещё не одобрено родителями</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Сохранить карту на этом устройстве</translation>
<translation id="8626112503828625890">Сохранить платежные данные в аккаунте Google?</translation>
+<translation id="8647750283161643317">Восстановить настройки по умолчанию</translation>
<translation id="8663226718884576429">Информация о заказе, <ph name="TOTAL_LABEL" />, дополнительные сведения</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, ответ, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Свободно</translation>
<translation id="8703575177326907206">Соединение с <ph name="DOMAIN" /> не зашифровано.</translation>
<translation id="8718314106902482036">Не удалось обработать платеж</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, подсказка</translation>
@@ -1417,6 +1435,7 @@
<translation id="8738058698779197622">Для создания безопасного подключения необходимо, чтобы показания системных часов были верны. Причина в том, что сертификаты для идентификации сайтов имеют ограниченный срок действия. Если часы на устройстве неточны, Chromium не может проверить актуальность этих сертификатов.</translation>
<translation id="8740359287975076522">Не удается найти &lt;abbr id="dnsDefinition"&gt;DNS-адрес&lt;/abbr&gt; сайта <ph name="HOST_NAME" />. Выполняется диагностика.</translation>
<translation id="874846938927089722">Кредитные карты и карты предоплаты, которые принимаются к оплате</translation>
+<translation id="874918643257405732">Добавить страницу в закладки</translation>
<translation id="8759274551635299824">Срок действия карты истек.</translation>
<translation id="8761567432415473239">Система Google по проверке безопасности сайтов недавно обнаружила на <ph name="SITE" /> <ph name="BEGIN_LINK" />вредоносное ПО<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB-устройство</translation>
@@ -1446,6 +1465,7 @@
<translation id="8938939909778640821">Кредитные карты и карты предоплаты, которые принимаются к оплате</translation>
<translation id="8943282376843390568">Лаймовый</translation>
<translation id="8957210676456822347">Авторизация через адаптивный портал</translation>
+<translation id="8962950042226115166">Подозрительный сайт</translation>
<translation id="8968766641738584599">Сохранить карту</translation>
<translation id="8971063699422889582">Сертификат сервера устарел.</translation>
<translation id="8975012916872825179">В том числе телефонные номера, адреса электронной почты и адреса доставки.</translation>
@@ -1468,24 +1488,24 @@
<translation id="9035022520814077154">Ошибка безопасности</translation>
<translation id="9038649477754266430">Использовать подсказки для ускорения загрузки страниц</translation>
<translation id="9039213469156557790">Обратите внимание, что на странице обнаружен небезопасный контент. Возможно, при передаче ресурсы просматриваются третьими лицами, а злоумышленники могут получить доступ к странице и изменить ее поведение.</translation>
+<translation id="9044359186343685026">Использовать Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Вы попытались открыть <ph name="DOMAIN" />, однако представленный сервером сертификат недействителен.</translation>
<translation id="9050666287014529139">Кодовая фраза</translation>
<translation id="9065203028668620118">Изменить</translation>
<translation id="9065745800631924235">Поисковый запрос "<ph name="TEXT" />" из истории</translation>
<translation id="9069693763241529744">Заблокировано расширением</translation>
-<translation id="9076283476770535406">Может содержать контент для взрослых</translation>
<translation id="9076630408993835509">Компания или организация не управляет этим браузером. Действиями на этом устройстве можно управлять вне браузера Chrome. <ph name="BEGIN_LINK" />Подробнее…<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Информации недостаточно</translation>
<translation id="9080712759204168376">Информация о заказе</translation>
<translation id="9089260154716455634">Время, когда правила не действуют:</translation>
<translation id="9095388113577226029">Другие языки</translation>
+<translation id="9098981495403789647">Администратор включил в браузере систему защиты Chrome Enterprise. У этой системы есть доступ к некоторым вашим данным.</translation>
<translation id="9103872766612412690">На сайте <ph name="SITE" /> для защиты ваших данных обычно используется шифрование. Однако учетные данные, которые мы получили от сайта <ph name="SITE" /> сейчас, отличаются от тех, которые он отправляет обычно. Вероятно, вредоносный сайт пытается выдать себя за <ph name="SITE" />, либо страница подключения к сети Wi-Fi прервала соединение. Ваша информация по-прежнему в безопасности, так как браузер Chromium разорвал соединение до того, как произошел обмен данными.</translation>
<translation id="9106062320799175032">Добавьте платежный адрес</translation>
<translation id="9114524666733003316">Подтверждение карты...</translation>
<translation id="9128870381267983090">Подключитесь к сети</translation>
<translation id="9137013805542155359">Показать оригинал</translation>
-<translation id="9137248913990643158">Войдите в Chrome, прежде чем использовать это приложение.</translation>
<translation id="9141013498910525015">Управление адресами</translation>
<translation id="9148088599418889305">Выбрать способ доставки посылок</translation>
<translation id="9148507642005240123">&amp;Отменить изменения</translation>
diff --git a/chromium/components/strings/components_strings_sk.xtb b/chromium/components/strings/components_strings_sk.xtb
index ae36063e602..caccd849693 100644
--- a/chromium/components/strings/components_strings_sk.xtb
+++ b/chromium/components/strings/components_strings_sk.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Pridanie mena na karte</translation>
<translation id="1089439967362294234">Zmeniť heslo</translation>
+<translation id="1096545575934602868">Toto pole by nemalo mať viac ako <ph name="MAX_ITEMS_LIMIT" /> vstupov. Všetky ďalšie vstupy budú zahodené.</translation>
<translation id="109743633954054152">Spravujte heslá v nastaveniach Chromu</translation>
<translation id="1103523840287552314">Vždy preložiť nasledujúci jazyk: <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Ak je toto nastavenie začiarknuté, Chrome uloží kópiu karty na toto zariadenie, aby ste mohli vypĺňať formuláre rýchlejšie.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Prístup ku <ph name="BEGIN_LINK" />kópii vo vyrovnávacej pamäti<ph name="END_LINK" /> stránky <ph name="URL" /></translation>
<translation id="1156303062776767266">Prezeráte si miestny alebo zdieľaný súbor</translation>
<translation id="1158211211994409885">Hostiteľský web <ph name="HOST_NAME" /> neočakávane ukončil pripojenie.</translation>
+<translation id="115926840831309955">Skontrolujte overovací kód karty a skúste to znova alebo aktualizujte dátum vypršania platnosti</translation>
<translation id="1161325031994447685">Znovu sa pripojiť k sieti Wi‑Fi</translation>
<translation id="1165039591588034296">Chyba</translation>
<translation id="1175364870820465910">&amp;Tlačiť...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Softvér vo vašom počítači bráni Chromu bezpečne sa pripojiť k internetu“ (iba počítače so systémom Windows)</translation>
<translation id="1294154142200295408">Variácie v príkazovom riadku</translation>
<translation id="129553762522093515">Nedávno zatvorené</translation>
+<translation id="1298536327547837046">Kontrola malvéru</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Skúste vymazať súbory cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Funkcie s ukončenou podporou</translation>
<translation id="1320233736580025032">Prc1 (obálka)</translation>
<translation id="132301787627749051">Hľadať obrázok v schránke</translation>
<translation id="1323433172918577554">Zobraziť viac</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Tabuľky Google</translation>
<translation id="1527263332363067270">Čaká sa na pripojenie...</translation>
<translation id="1529521330346880926">10x15 (obálka)</translation>
+<translation id="1530707389502320859">Web, ktorý sa pokúšate navštíviť, vyzerá falošne. Útočníci niekedy weby napodobňujú tak, že vo webovej adrese vykonajú drobné, ťažko odhaliteľné zmeny.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Táto stránka hovorí</translation>
<translation id="153384715582417236">To je zatiaľ všetko</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokument nie je možné anotovať, pretože je príliš veľký</translation>
-<translation id="1721312023322545264">Ak chcete navštíviť tento web, potrebujete povolenie od správcu <ph name="NAME" /></translation>
<translation id="1721424275792716183">* Toto pole je povinné</translation>
<translation id="1727741090716970331">Pridanie platného čísla karty</translation>
<translation id="1728677426644403582">Prezeráte si zdrojový kód webovej stránky</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">Weby, ktoré navštívite, a čas, ktorý na nich strávite</translation>
<translation id="1826516787628120939">Kontroluje sa</translation>
<translation id="1834321415901700177">Tento web obsahuje škodlivé programy</translation>
+<translation id="1838374766361614909">Vymazať vyhľadávanie</translation>
<translation id="1839551713262164453">Overenie hodnôt pravidiel zlyhalo a obsahuje chyby</translation>
<translation id="1842969606798536927">Zaplatiť</translation>
<translation id="1871208020102129563">Proxy je nastavené na použitie pevne daných serverov proxy, nie skriptov PAC webovej adresy.</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">Zbaliť zoznam</translation>
<translation id="1898423065542865115">Filtrovanie</translation>
<translation id="1914326953223720820">Rozbaliť službu</translation>
+<translation id="1915697529809968049">Chcete namiesto overovacieho kódu karty použiť Touch ID?</translation>
<translation id="1916770123977586577">Ak chcete na webe uplatniť aktualizované nastavenia, znova načítajte túto stránku</translation>
<translation id="1919345977826869612">Reklamy</translation>
<translation id="1919367280705858090">Pomoc s konkrétnym chybovým hlásením</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436">Záložky (<ph name="DOMAIN" />)</translation>
<translation id="1973335181906896915">Chyba serializácie</translation>
<translation id="1974060860693918893">Rozšírené</translation>
+<translation id="1974883374937189061">Pomôžte zlepšovať bezpečnosť Chromu odosielaním <ph name="BEGIN_WHITEPAPER_LINK" />webových adries a obsahu niektorých stránok, ktoré navštevujete, ako aj obmedzených informácií o systéme<ph name="END_WHITEPAPER_LINK" /> Googlu. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Verzia firmvéru</translation>
<translation id="1981206234434200693">Vymažte údaje histórie prehliadania Chromu</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{a 1 ďalšia}few{a # ďalšie}many{a # ďalšej}other{a # ďalších}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">Zadajte platný rok vypršania platnosti</translation>
<translation id="2212735316055980242">Pravidlo sa nenašlo</translation>
<translation id="2213606439339815911">Načítavanie záznamov...</translation>
+<translation id="2215727959747642672">Úprava súborov</translation>
<translation id="2218879909401188352">Útočníci na webe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> by mohli nainštalovať nebezpečné aplikácie, ktoré poškodia vaše zariadenia, pridať skryté poplatky do vašej faktúry za mobilné služby alebo ukradnúť vaše osobné informácie. <ph name="BEGIN_LEARN_MORE_LINK" />Ďalšie informácie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Bez internetu</translation>
<translation id="2230458221926704099">Opravte svoje pripojenie pomocou <ph name="BEGIN_LINK" />diagnostickej aplikácie<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Odoslať</translation>
+<translation id="2248949050832152960">Použiť WebAuthn</translation>
<translation id="225207911366869382">Táto hodnota už pre toto pravidlo nie je podporovaná.</translation>
<translation id="2257315177824333709">Je nám to ľúto, ale karta sa momentálne nedá uložiť.</translation>
<translation id="2262243747453050782">Chyba protokolu HTTP</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">Neplatná webová adresa vyhľadávania.</translation>
<translation id="2482878487686419369">Upozornenia</translation>
<translation id="248348093745724435">Pravidlá počítača</translation>
-<translation id="2485387744899240041">Používateľské mená pre vaše zariadenie a prehliadač</translation>
<translation id="2491120439723279231">Certifikát servera obsahuje chyby.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Parser</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">Prejsť späť</translation>
<translation id="2503184589641749290">Akceptované debetné a predplatené karty</translation>
<translation id="2505268675989099013">Ochrániť účet</translation>
+<translation id="2515335152965840738">IGNOROVAŤ</translation>
<translation id="2515629240566999685">Skontrolovať signál vo vašej oblasti</translation>
<translation id="2523886232349826891">Uložené iba na tomto zariadení</translation>
<translation id="2524461107774643265">Pridanie ďalších informácií</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">Odoslať</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Žiadne}=1{Jedno heslo (pre zoznam domén <ph name="DOMAIN_LIST" />)}=2{Dve heslá (pre zoznam domén <ph name="DOMAIN_LIST" />)}few{# heslá (pre zoznam domén <ph name="DOMAIN_LIST" />)}many{# passwords (for <ph name="DOMAIN_LIST" />)}other{# hesiel (pre zoznam domén <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Zavrite ostatné karty alebo aplikácie</translation>
-<translation id="267371737713284912">vráťte späť stlačením klávesa <ph name="MODIFIER_KEY_DESCRIPTION" /></translation>
<translation id="2674170444375937751">Naozaj chcete odstrániť tieto stránky zo svojej histórie?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Odísť</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">Hodnota nezodpovedá formátu.</translation>
<translation id="2705137772291741111">Uložená kópia tohto webu (vo vyrovnávacej pamäti) bola nečitateľná.</translation>
<translation id="2709516037105925701">Automatické dopĺňanie</translation>
-<translation id="2712173769900027643">Požiadať o povolenie</translation>
<translation id="2713444072780614174">Biela</translation>
<translation id="2720342946869265578">Nablízku</translation>
<translation id="2721148159707890343">Žiadosť bola úspešná</translation>
<translation id="2728127805433021124">Certifikát servera je podpísaný pomocou slabého podpisového algoritmu.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Spustiť nástroj Diagnostika konektivity<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ak aktivujete tieto funkcie, môžete prísť o dáta prehliadania alebo ohroziť zabezpečenie či súkromie. Funkcie sa aktivujú všetkým používateľom tohto prehliadača.</translation>
<translation id="2735043616039983645">V rámci tohto pravidla je k dispozícii viacero zdrojov s konfliktnými hodnotami.</translation>
<translation id="2738330467931008676">Zvoliť adresu vyzdvihnutia</translation>
<translation id="2740531572673183784">OK</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">Spojenie bolo resetované.</translation>
<translation id="2788784517760473862">Akceptované kreditné karty</translation>
<translation id="2792012897584536778">Správcovia tohto zariadenia nastavili bezpečnostné certifikáty, ktoré im môžu umožniť zobraziť obsah vami navštívených webov.</translation>
-<translation id="2794233252405721443">Web je blokovaný</translation>
<translation id="2799020568854403057">Web, ktorý chcete otvoriť, obsahuje škodlivé aplikácie</translation>
<translation id="2799223571221894425">Znova spustiť</translation>
<translation id="2803306138276472711">Funkcia Bezpečné prehliadanie Google nedávno <ph name="BEGIN_LINK" />zistila malvér<ph name="END_LINK" /> na stránkach <ph name="SITE" />. Webové stránky, ktoré sú zvyčajne bezpečné, môžu byť niekedy nakazené malvérom.</translation>
+<translation id="2815364696811431560">OPUSTIŤ WEB</translation>
<translation id="2824775600643448204">Panel s adresou a vyhľadávací panel</translation>
<translation id="2826760142808435982">Pripojenie je šifrované pomocou štandardu <ph name="CIPHER" /> a používa mechanizmus výmeny kľúčov <ph name="KX" />.</translation>
<translation id="2835170189407361413">Vymazať formulár</translation>
<translation id="2847118875340931228">Otvoriť okno inkognito</translation>
<translation id="2850739647070081192">Invite (obálka)</translation>
-<translation id="2851634818064021665">Na návštevu tohto webu potrebujete povolenie</translation>
<translation id="2856444702002559011">Útočníci sa môžu pokúsiť ukradnúť vaše informácie z webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (napríklad heslá, správy alebo kreditné karty). <ph name="BEGIN_LEARN_MORE_LINK" />Ďalšie informácie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Uložiť kartu?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">Ak túto možnosť povolíte, Chromium uloží na tomto zariadení kópiu karty, aby ste mohli rýchlejšie vypĺňať formuláre.</translation>
<translation id="2985398929374701810">Zadajte platnú adresu</translation>
<translation id="2986368408720340940">Tento spôsob vyzdvihnutia nie je k dispozícii. Skúste iný spôsob.</translation>
+<translation id="2987034854559945715">Žiadne zodpovedajúce funkcie</translation>
<translation id="2991174974383378012">Zdieľanie s webmi</translation>
<translation id="2991571918955627853">Web <ph name="SITE" /> momentálne nemôžete navštíviť, pretože používa certifikát HSTS. Chyby siete a útoky sú zvyčajne dočasné, takže by táto stránka mala neskôr pravdepodobne fungovať.</translation>
<translation id="3005723025932146533">Zobraziť uloženú kópiu</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">Chybný typ pravidla</translation>
<translation id="3037605927509011580">Aj, chyba!</translation>
<translation id="3041612393474885105">Informácie o certifikáte</translation>
+<translation id="3057676462092457419">Režim DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> zatiaľ nie je podporovaný. Režim bol nastavený na <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (obálka)</translation>
<translation id="3061707000357573562">Služba opráv</translation>
<translation id="3064966200440839136">Ak zaplatíte pomocou externej aplikácie, opustíte režim inkognito. Chcete pokračovať?</translation>
@@ -416,6 +425,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> na serveri <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Zrušiť platbu</translation>
<translation id="3207960819495026254">Pridané medzi záložky</translation>
+<translation id="3209034400446768650">Stránka môže účtovať peniaze</translation>
<translation id="3225919329040284222">Server sa preukázal certifikátom, ktorý nezodpovedá integrovaným očakávaniam. Tieto očakávania sú kvôli vašej ochrane zahrnuté pri určitých webových stránkach s vysokou úrovňou zabezpečenia.</translation>
<translation id="3226128629678568754">Stlačením tlačidla opakovaného spustenia znova odošlete údaje potrebné na načítanie stránky.</translation>
<translation id="3227137524299004712">Mikrofón</translation>
@@ -423,7 +433,6 @@
<translation id="3229041911291329567">Informácie o verzii vášho zariadenia a prehliadača</translation>
<translation id="323107829343500871">Zadajte kód CVC karty <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Vždy na tomto webe zisťovať dôležitý obsah</translation>
-<translation id="3254409185687681395">Vytvoriť záložku pre túto stránku</translation>
<translation id="3270847123878663523">&amp;Vrátiť späť zmenu poradia</translation>
<translation id="3274521967729236597">Pa‑Kai</translation>
<translation id="3282497668470633863">Pridanie mena na karte</translation>
@@ -433,7 +442,6 @@
<translation id="3320021301628644560">Pridanie fakturačnej adresy</translation>
<translation id="3324983252691184275">Karmínová</translation>
<translation id="3338095232262050444">Zabezpečené</translation>
-<translation id="3345135638360864351">Vašu žiadosť o prístup k týmto webovým stránkam sa používateľovi <ph name="NAME" /> neporadilo odoslať. Skúste to znova neskôr.</translation>
<translation id="3355823806454867987">Zmeniť nastavenia proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />nebude ukladať<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -467,18 +475,15 @@
<translation id="3462200631372590220">Skryť rozšírené podrobnosti</translation>
<translation id="3467763166455606212">Meno majiteľa karty je povinný údaj</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, aktuálne otvorené, stlačením klávesov Tab a Enter prepnete na otvorenú kartu</translation>
-<translation id="3479539252931486093">Neočakávali ste to? <ph name="BEGIN_LINK" />Dajte nám vedieť<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Teraz nie</translation>
<translation id="3484560055331845446">Môžete stratiť prístup do účtu Google. Chrome odporúča, aby ste si ihneď zmenili heslo. Zobrazí sa výzva na prihlásenie.</translation>
<translation id="3495081129428749620">Nájsť na stránke
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">V tejto chvíli sa nám nepodarilo spojiť s vaším rodičom. Skúste to znova neskôr.</translation>
<translation id="3512163584740124171">Toto pravidlo sa ignoruje, pretože iné pravidlo z rovnakej skupiny má vyššiu prioritu.</translation>
<translation id="3528171143076753409">Certifikát servera nie je dôveryhodný.</translation>
<translation id="3528485271872257980">Tmavohnedá</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Aspoň 1 položka v synchronizovaných zariadeniach}=1{1 položka (a ďalšie v synchronizovaných zariadeniach)}few{# položky (a ďalšie v synchronizovaných zariadeniach)}many{# položky (a ďalšie v synchronizovaných zariadeniach)}other{# položiek (a ďalšie v synchronizovaných zariadeniach)}}</translation>
<translation id="3539171420378717834">Ponechať kópiu tejto karty na tomto zariadení</translation>
-<translation id="3556433843310711081">Váš správca ho môže pre vás odblokovať</translation>
<translation id="3566021033012934673">Vaše pripojenie nie je súkromné</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Vložená stránka na webe <ph name="SITE" /> hovorí</translation>
@@ -505,6 +510,7 @@
<translation id="3678529606614285348">Otvorte stránku v novom okne inkognito (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Správa o zlyhaní zaznamenaná v čase <ph name="CRASH_TIME" /> bola nahraná o <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informácie o certifikáte</translation>
+<translation id="3701427423622901115">Resetovanie bolo potvrdené.</translation>
<translation id="3704162925118123524">Sieť, ktorú používate, môže vyžadovať, aby ste navštívili jej prihlasovaciu stránku.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Načítava sa...</translation>
@@ -521,6 +527,7 @@
<translation id="3748148204939282805">Útočníci na webe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> vás môžu oklamať, aby ste urobili niečo nebezpečné, napríklad nainštalovali softvér alebo odhalili svoje osobné informácie (napríklad heslá, telefónne čísla a kreditné karty). <ph name="BEGIN_LEARN_MORE_LINK" />Ďalšie informácie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Preklad zlyhal v dôsledku chyby servera.</translation>
<translation id="3759461132968374835">Nemáte žiadne nedávno nahlásené zlyhania. Na tejto stránke sa nezobrazujú zlyhania, ktoré nastali pri zakázanej možnosti hlásení zlyhaní.</translation>
+<translation id="3760561303380396507">Chcete namiesto overovacieho kódu karty použiť Windows Hello?</translation>
<translation id="3761718714832595332">Skryť stav</translation>
<translation id="3765032636089507299">Stránka Bezpečného prehliadania sa pripravuje.</translation>
<translation id="3778403066972421603">Chcete uložiť túto kartu do svojho účtu Google a tohto zariadenia?</translation>
@@ -530,6 +537,7 @@
<translation id="3789155188480882154">Veľkosť 16</translation>
<translation id="3797522431967816232">Prc3 (obálka)</translation>
<translation id="3807873520724684969">Škodlivý obsah bol zablokovaný.</translation>
+<translation id="3808375843007691220">Upozornenie: Čakajú vás experimentálne funkcie!</translation>
<translation id="3810973564298564668">Spravovať</translation>
<translation id="382518646247711829">Ak používate server proxy...</translation>
<translation id="3828924085048779000">Prístupová fráza nemôže byť prázdna.</translation>
@@ -538,11 +546,11 @@
<translation id="3858027520442213535">Aktualizovať dátum a čas</translation>
<translation id="3884278016824448484">Kolidujúci identifikátor zariadenia</translation>
<translation id="3885155851504623709">Farnosť</translation>
-<translation id="3886446263141354045">Vaša žiadosť o prístup na tento web sa odoslala správcovi <ph name="NAME" /></translation>
<translation id="3890664840433101773">Pridanie e-mailu</translation>
<translation id="3901925938762663762">Platnosť karty vypršala</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Chcete namiesto overovacieho kódu karty použiť WebAuthn?</translation>
<translation id="3946209740501886391">Vždy sa opýtať na tomto webe</translation>
<translation id="3949571496842715403">Tento server nedokázal potvrdiť, či ide o doménu <ph name="DOMAIN" /> – príslušný bezpečnostný certifikát neuvádza alternatívne názvy predmetu. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie napadol útočník.</translation>
<translation id="3949601375789751990">Tu sa zobrazí vaša história prehliadania</translation>
@@ -553,11 +561,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Žiadne}=1{Z 1 webu }few{Z # webov }many{Z # webu }other{Z # webov }}</translation>
<translation id="397105322502079400">Prebieha výpočet...</translation>
<translation id="3973234410852337861">Web <ph name="HOST_NAME" /> je zablokovaný</translation>
+<translation id="3981540111851280311">Organizácia <ph name="ENROLLMENT_DOMAIN" /> vo vašom prehliadači zapla systém ochrany Chrome Enterprise. Systém ochrany Chrome Enterprise má prístup k niektorým vašim údajom.</translation>
<translation id="3987940399970879459">Menej ako 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 webová stránka v okolí}few{# webové stránky v okolí}many{# webovej stránky v okolí}other{# webových stránok v okolí}}</translation>
<translation id="4030383055268325496">&amp;Vrátiť späť pridanie</translation>
<translation id="4032320456957708163">Váš prehliadač spravuje doména <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Odkaz, ktorý ste otvorili, vedie na web, ktorý zvyčajne nenavštevujete. Môže sa vás pokúsiť zmiasť.</translation>
<translation id="4058922952496707368">Kľúč <ph name="SUBKEY" />: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (obálka)</translation>
<translation id="4067947977115446013">Pridanie platnej adresy</translation>
@@ -570,6 +578,7 @@
<translation id="4103249731201008433">Sériové číslo zariadenia je neplatné</translation>
<translation id="410351446219883937">Automatické prehrávanie</translation>
<translation id="4103763322291513355">Na stránke &lt;strong&gt;chrome://policy&lt;/strong&gt; nájdete zoznam zakázaných webových adries a ďalšie pravidlá vynútené vaším správcom systému.</translation>
+<translation id="4108231218301530806">Pri ďalšom overení tejto karty použiť odtlačok prsta</translation>
<translation id="4110652170750985508">Kontrola platby</translation>
<translation id="4112140312785995938">Pretočiť dozadu</translation>
<translation id="4116663294526079822">Vždy povoliť na tomto webe</translation>
@@ -584,6 +593,7 @@
<translation id="4171400957073367226">Nesprávny overovací podpis</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> ďalšia položka}few{<ph name="ITEM_COUNT" /> ďalšie položky}many{<ph name="ITEM_COUNT" /> ďalšej položky}other{<ph name="ITEM_COUNT" /> ďalších položiek}}</translation>
+<translation id="4176463684765177261">Deaktivované</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Ak chcete nabudúce zaplatiť rýchlejšie, uložte si kartu a fakturačnú adresu do účtu Google.</translation>
<translation id="4196861286325780578">&amp;Znova presunúť</translation>
@@ -620,6 +630,7 @@
<translation id="4277028893293644418">Obnoviť heslo</translation>
<translation id="4279811152705618813">Vaše zariadenie <ph name="DEVICE_TYPE" /> spravuje doména <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Táto karta sa uložila do vášho účtu Google}few{Tieto karty sa uložili do vášho účtu Google}many{Tieto karty sa uložili do vášho účtu Google}other{Tieto karty sa uložili do vášho účtu Google}}</translation>
+<translation id="428847186335018806">Preskenovanie súborov, ktoré sťahujete alebo nahrávate v Chrome.</translation>
<translation id="42981349822642051">Rozbaliť</translation>
<translation id="4302965934281694568">Chou3 (obálka)</translation>
<translation id="4305817255990598646">Prepnúť</translation>
@@ -649,7 +660,6 @@
<translation id="4435702339979719576">pohľadnica)</translation>
<translation id="443673843213245140">Použitie servera proxy je zakázané, ale je určená explicitná konfigurácia servera proxy.</translation>
<translation id="445100540951337728">Akceptované debetné karty</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> podozrivé správanie</translation>
<translation id="4466881336512663640">Zmeny formulára sa odstránia. Naozaj chcete pokračovať?</translation>
<translation id="4477350412780666475">Ďalšia stopa</translation>
<translation id="4482953324121162758">Tento web nebude preložený.</translation>
@@ -676,6 +686,7 @@
<translation id="4594403342090139922">&amp;Vrátiť späť odstránenie</translation>
<translation id="4597348597567598915">Veľkosť 8</translation>
<translation id="4600854749408232102">C6/C5 (obálka)</translation>
+<translation id="464342062220857295">Funkcie vyhľadávania</translation>
<translation id="4646534391647090355">Prejsť do daného umiestnenia</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Server nedokáže overiť, či ide o doménu <ph name="DOMAIN" />, jej bezpečnostný certifikát obsahuje chyby. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie zachytil útočník.</translation>
@@ -684,7 +695,6 @@
<translation id="4691835149146451662">Architecture-A (obálka)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Pripojenie bolo prerušené</translation>
-<translation id="471880041731876836">Nemáte povolenie na návštevu tohto webu</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Spustiť nástroj Diagnostika siete systému Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Znova načítať pravidlá</translation>
<translation id="4728558894243024398">Platforma</translation>
@@ -712,7 +722,6 @@
<translation id="4816492930507672669">Prispôsobiť stránke</translation>
<translation id="4850886885716139402">Zobraziť</translation>
<translation id="4854362297993841467">Tento spôsob doručenia nie je k dispozícii. Skúste inú adresu.</translation>
-<translation id="4858792381671956233">Požiadali ste rodičov o povolenie návštevy tohto webu.</translation>
<translation id="4864052566555297930">Tip pre vyššiu bezpečnosť:</translation>
<translation id="4876188919622883022">Zjednodušené zobrazenie</translation>
<translation id="4876305945144899064">Žiadne používateľské meno</translation>
@@ -736,7 +745,9 @@
<translation id="4974590756084640048">Opätovne aktivovať upozornenia</translation>
<translation id="4984339528288761049">Prc5 (obálka)</translation>
<translation id="4989163558385430922">Zobraziť všetko</translation>
+<translation id="4989542687859782284">Nedostupné</translation>
<translation id="4989809363548539747">Tento doplnok nie je podporovaný</translation>
+<translation id="4995216769782533993">Potvrdením bezpečnostného kódu začnete zdieľať podrobnosti karty s týmto webom</translation>
<translation id="5002932099480077015">Ak túto možnosť povolíte, Chrome bude uchovávať kópiu vašej karty na tomto zariadení na účely rýchlejšieho dopĺňania formulárov.</translation>
<translation id="5015510746216210676">Názov počítača:</translation>
<translation id="5017554619425969104">Skopírovaný text</translation>
@@ -765,6 +776,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bitová verzia)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Overenie karty</translation>
<translation id="5135404736266831032">Spravovať adresy…</translation>
<translation id="5138227688689900538">Zobraziť menej</translation>
<translation id="5141240743006678641">Šifrovať synchronizované heslá pomocou poverení Google</translation>
@@ -791,6 +803,7 @@
<translation id="5251803541071282808">Cloud</translation>
<translation id="5252000469029418751">C7 (obálka)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funkcie, ktoré platia v celom systéme, môže nastaviť iba vlastník: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Upozornenie: Toto pravidlo nebolo zlúčené podľa špecifikácií pravidla PolicyDictionaryMultipleSourceMergeList, pretože nie je súčasťou pravidiel pre slovníky, ktoré sa dajú zlúčiť.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Koniec</translation>
@@ -814,7 +827,6 @@
<translation id="536296301121032821">Nastavenia pravidla sa nepodarilo uložiť</translation>
<translation id="5371425731340848620">Aktualizujte si kartu</translation>
<translation id="5377026284221673050">„Vaše hodiny meškajú“, „Vaše hodiny idú dopredu“ alebo „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;“</translation>
-<translation id="5377179979757081683">Táto stránka vás môže oklamať a ukradnúť vaše osobné údaje, prípadne môže poškodiť zariadenie. Pri zadávaní osobných údajov alebo otváraní stiahnutých súborov zvýšte opatrnosť.</translation>
<translation id="5384855140246857529">Ak chcete používať karty vo všetkých zariadeniach, prihláste sa a zapnite synchronizáciu.</translation>
<translation id="5386426401304769735">Reťazec certifikátu pre tento web obsahuje certifikát podpísaný pomocou funkcie SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -828,6 +840,7 @@
<translation id="5457113250005438886">Neplatné</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ďalší}few{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ďalšie}many{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ďalšieho}other{<ph name="CONTACT_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ďalších}}</translation>
<translation id="5470861586879999274">&amp;Znova upraviť</translation>
+<translation id="5473728911100096288">Ak aktivujete tieto funkce, budete používať tie, ktorých podpora bola ukončená a ktoré v budúcich verziách už nebudú k dispozícii.</translation>
<translation id="5478437291406423475">B6/C4 (obálka)</translation>
<translation id="5481076368049295676">Tento obsah sa môže pokúsiť nainštalovať v zariadení nebezpečný softvér, ktorý ukradne alebo odstráni vaše informácie. <ph name="BEGIN_LINK" />Napriek tomu zobraziť<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Pridanie platnej adresy</translation>
@@ -851,7 +864,6 @@
<translation id="5570825185877910964">Ochrániť účet</translation>
<translation id="5571083550517324815">Vyzdvihnutie na tejto adrese nie je možné. Vyberte inú adresu.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{Používa sa 1}few{Používajú sa #}many{Používa sa #}other{Používa sa #}})</translation>
-<translation id="5572851009514199876">Začnite a prihláste sa do Chromu, aby skontroloval, či môžete navštíviť tento web.</translation>
<translation id="5580958916614886209">Skontrolujte mesiac vypršania platnosti a skúste to znova</translation>
<translation id="5586446728396275693">Žiadne uložené adresy</translation>
<translation id="5595485650161345191">Upraviť adresu</translation>
@@ -859,6 +871,7 @@
<translation id="560412284261940334">Správa nie je podporovaná</translation>
<translation id="5605670050355397069">Účtovná kniha</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Tento web môže byť falošný alebo podvodný. Chrome vám odporúča okamžite odísť.</translation>
<translation id="5610142619324316209">Skontrolovať pripojenie</translation>
<translation id="5610807607761827392">Karty a adresy môžete spravovať v časti <ph name="BEGIN_LINK" />Nastavenia<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Web <ph name="HOST_NAME" /> vás presmeroval príliš veľakrát.</translation>
@@ -882,11 +895,11 @@
<translation id="5720705177508910913">Aktuálny používateľ</translation>
<translation id="5728056243719941842">C5 (obálka)</translation>
<translation id="5730040223043577876">Ak ste heslo použili aj na iných weboch, Chrome ho odporúča obnoviť.</translation>
-<translation id="5732392974455271431">Vaši rodičia ho môžu pre vás odblokovať</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Uloženie karty do účtu Google}few{Uloženie kariet do účtu Google}many{Save cards in your Google Account}other{Uloženie kariet do účtu Google}}</translation>
<translation id="5763042198335101085">Zadajte platnú e-mailovú adresu</translation>
<translation id="5765072501007116331">Ak chcete zobraziť spôsoby a požiadavky doručenia, vyberte adresu</translation>
<translation id="5778550464785688721">Úplné ovládanie zariadení MIDI</translation>
+<translation id="5781136890105823427">Experiment je povolený</translation>
<translation id="578305955206182703">Žltohnedá</translation>
<translation id="57838592816432529">Vypnúť zvuk</translation>
<translation id="5784606427469807560">Pri overovaní karty sa vyskytol problém. Skontrolujte pripojenie k internetu a skúste to znova.</translation>
@@ -903,13 +916,16 @@
<translation id="5860033963881614850">Vypnuté</translation>
<translation id="5863847714970149516">Stránka, na ktorú sa chystáte prejsť, vám môže účtovať poplatky</translation>
<translation id="5866257070973731571">Pridanie telefónneho čísla</translation>
+<translation id="5866898949289125849">Prezeráte si stránku s nástrojmi pre vývojárov</translation>
<translation id="5869405914158311789">Tento web je nedostupný</translation>
<translation id="5869522115854928033">Uložené heslá</translation>
<translation id="5887400589839399685">Karta bola uložená</translation>
<translation id="5893752035575986141">Kreditné karty sú akceptované.</translation>
+<translation id="5895138241574237353">Reštartovať</translation>
<translation id="5901630391730855834">Žltá</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronizované)</translation>
<translation id="5916664084637901428">Zapnuté</translation>
+<translation id="59174027418879706">Povolené</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Chcete uložiť kartu do účtu Google?</translation>
<translation id="5922853866070715753">Takmer dokončené</translation>
@@ -943,6 +959,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Chcete použiť svoje karty vo všetkých zariadeniach?</translation>
<translation id="6059925163896151826">Zariadenia USB</translation>
+<translation id="6060009363608157444">Neplatný režim DnsOverHttps.</translation>
<translation id="6080696365213338172">K obsahu ste pristúpili pomocou certifikátu, ktorý poskytol správca. Údaje, ktoré poskytnete doméne <ph name="DOMAIN" /> môžu byť zachytené správcom.</translation>
<translation id="6094273045989040137">Pridať anotáciu</translation>
<translation id="610911394827799129">Váš účet Google môže mať ďalšie formy histórie prehliadania na adrese <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -990,13 +1007,12 @@
<translation id="6404511346730675251">Upraviť záložku</translation>
<translation id="6406765186087300643">C0 (obálka)</translation>
<translation id="6410264514553301377">Zadajte dátum vypršania platnosti a kód CVC karty <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Opýtali ste sa svojho rodiča, či môžete navštíviť tento web</translation>
<translation id="6415778972515849510">Chromium vám pomôže ochrániť účet Google a zmeniť heslo.</translation>
-<translation id="6417515091412812850">Nie je možné skontrolovať, či bol certifikát odmietnutý.</translation>
<translation id="6431585503458005759">Neuchovať</translation>
<translation id="6433490469411711332">Úprava kontaktných informácií</translation>
<translation id="6433595998831338502">Web <ph name="HOST_NAME" /> zamietol pripojenie.</translation>
<translation id="6434309073475700221">Odstrániť</translation>
+<translation id="6435221585574090192">Zdieľajte so svojím správcom údaje o bezpečnostných udalostiach nahlásených systémom ochrany Chrome Enterprise. Môžu zahŕňať webové adresy stránok, názvy a metadáta súborov a vaše používateľské meno v zariadení aj Chrome.</translation>
<translation id="6440503408713884761">Ignorované</translation>
<translation id="6446163441502663861">Kahu (obálka)</translation>
<translation id="6446608382365791566">Pridanie ďalších informácií</translation>
@@ -1005,20 +1021,19 @@
<translation id="6465306955648956876">Spravovať heslá…</translation>
<translation id="647261751007945333">Pravidlá zariadenia</translation>
<translation id="6476284679642588870">Spravovať spôsoby platby</translation>
-<translation id="6477321094435799029">Chrome na tejto stránke zaznamenal nezvyčajný kód a v záujme ochrany vašich osobných informácií (napr. hesiel, telefónnych čísel a kreditných kariet) ho zablokoval.</translation>
<translation id="6489534406876378309">Spustiť nahrávanie správ o zlyhaní</translation>
<translation id="6499038740797743453">Obnoviť heslo?</translation>
<translation id="6507833130742554667">Kreditné a debetné karty sú akceptované.</translation>
<translation id="650855688985305916">Áno, uchovať</translation>
<translation id="6508722015517270189">Reštartujte Chrome</translation>
<translation id="6517596291481585650">Upozornenie: Toto pravidlo nebolo zlúčené ako zoznam podľa špecifikácií pravidla, pretože to nie je zoznam.</translation>
+<translation id="6518133107902771759">Overiť</translation>
<translation id="6521745193039995384">Neaktívne</translation>
<translation id="6529602333819889595">&amp;Znova odstrániť</translation>
<translation id="6534179046333460208">Návrhy Fyzického webu</translation>
<translation id="6545864417968258051">Vyhľadávanie zariadení Bluetooth</translation>
<translation id="6554795675067793129">Váš účet spravuje doména <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Znova</translation>
-<translation id="6563469144985748109">Váš správca to zatiaľ neschválil</translation>
<translation id="6569060085658103619">Prezeráte si stránku s rozšíreniami</translation>
<translation id="6578796323535178455">C2 (obálka)</translation>
<translation id="6579990219486187401">Svetloružová</translation>
@@ -1028,7 +1043,7 @@
<translation id="6596325263575161958">Možnosti šifrovania</translation>
<translation id="6604181099783169992">Senzory pohybu alebo svetla</translation>
<translation id="6609880536175561541">Prc7 (obálka)</translation>
-<translation id="6624427990725312378">Kontaktné informácie</translation>
+<translation id="6624427990725312378">Kontaktné údaje</translation>
<translation id="6626291197371920147">Pridanie platného čísla karty</translation>
<translation id="6628463337424475685">Vyhľadávanie <ph name="ENGINE" /></translation>
<translation id="6630809736994426279">Útočníci na webe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sa môžu pokúsiť vo vašom počítači Mac nainštalovať nebezpečné programy, pomocou ktorých ukradnú alebo odstránia informácie (napríklad fotky, heslá, správy a kreditné karty). <ph name="BEGIN_LEARN_MORE_LINK" />Ďalšie informácie<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -1036,11 +1051,13 @@
<translation id="6643016212128521049">Vymazať</translation>
<translation id="6644283850729428850">Toto pravidlo bolo označené ako zastarané.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Žiadne}=1{Z 1 webu (neodhlásime vás z účtu Google)}few{Z # webov (neodhlásime vás z účtu Google)}many{From # sites (you won't be signed out of your Google Account)}other{Z # webov (neodhlásime vás z účtu Google)}}</translation>
+<translation id="6652101503459149953">Použiť Windows Hello</translation>
<translation id="6657585470893396449">Heslo</translation>
<translation id="6670613747977017428">Späť do bezpečia</translation>
<translation id="6671697161687535275">Chcete návrh položky formulára odstrániť z prehliadača Chromium?</translation>
<translation id="6685834062052613830">Odhláste sa a dokončite nastavenie</translation>
<translation id="6689271823431384964">Chrome poskytuje možnosť uložiť karty v účte Google, pretože ste sa prihlásili. Toto správanie môžete zmeniť v nastaveniach. Toto meno majiteľa karty pochádza z vášho účtu.</translation>
+<translation id="6707256370811247129">Preskenovanie obsahu vyrovnávacej pamäte a súborov, ktoré sťahujete alebo nahrávate v Chrome.</translation>
<translation id="6710213216561001401">Dozadu</translation>
<translation id="6710594484020273272">&lt;Zadajte hľadaný výraz&gt;</translation>
<translation id="671076103358959139">Registračný token:</translation>
@@ -1048,10 +1065,10 @@
<translation id="6738516213925468394">Vaše údaje boli <ph name="TIME" /> zašifrované pomocou <ph name="BEGIN_LINK" />prístupovej frázy synchronizácie<ph name="END_LINK" />. Synchronizácia sa spustí po jej zadaní.</translation>
<translation id="674375294223700098">Neznáma chyba spôsobená certifikátom servera.</translation>
<translation id="6744009308914054259">Zatiaľ čo čakáte na pripojenie, môžete prejsť do priečinka stiahnutých súborov a prečítať si články v režime offline.</translation>
+<translation id="6747611005629681221">Upozornenie: Podpora týchto funkcií bola ukončená.</translation>
<translation id="6753269504797312559">Hodnota pravidla</translation>
<translation id="6757797048963528358">Vaše zariadenie prešlo do režimu spánku.</translation>
<translation id="6768213884286397650">Hagaki (pohľadnica)</translation>
-<translation id="6778737459546443941">Váš rodič to zatiaľ neschválil</translation>
<translation id="67862343314499040">Fialová</translation>
<translation id="6786747875388722282">Rozšírenia</translation>
<translation id="6790428901817661496">Prehrať</translation>
@@ -1059,6 +1076,7 @@
<translation id="681021252041861472">Povinné pole</translation>
<translation id="6810899417690483278">Identifikátor prispôsobenia</translation>
<translation id="6825578344716086703">Pokúsili ste sa o prístup do domény <ph name="DOMAIN" />, server však predložil certifikát podpísaný slabým algoritmom podpisu. Znamená to, že predložené poverenia zabezpečenia mohli byť sfalšované a môže ísť o úplne iný server, než ste očakávali (možno komunikujete s útočníkom).</translation>
+<translation id="6826370046007623921">Ochrana pred únikom údajov</translation>
<translation id="6831043979455480757">Preložiť</translation>
<translation id="6839929833149231406">Oblasť</translation>
<translation id="6852204201400771460">Načítať znova aplikáciu?</translation>
@@ -1071,7 +1089,6 @@
<translation id="6891596781022320156">Úroveň pravidla nie je podporovaná.</translation>
<translation id="6895330447102777224">Vaša karta je overená</translation>
<translation id="6897140037006041989">Používateľský agent</translation>
-<translation id="6903319715792422884">Pomáhať zlepšovať Bezpečné prehliadanie tak, že sa budú do Googlu odosielať niektoré <ph name="BEGIN_WHITEPAPER_LINK" />informácie o systéme a obsah stránok<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Používateľ:</translation>
<translation id="6934672428414710184">Meno pochádza z vášho účtu Google</translation>
<translation id="6944692733090228304">Zadali ste heslo na webe, ktorý nie je spravovaný organizáciou <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Ak chcete, aby bol váš účet chránený, nepoužívajte jeho heslo pre iné aplikácie a weby.</translation>
@@ -1098,7 +1115,7 @@
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Túto kartu nie je momentálne možné uložiť}few{Tieto karty nie je momentálne možné uložiť}many{Tieto karty nie je momentálne možné uložiť}other{Tieto karty nie je momentálne možné uložiť}}</translation>
<translation id="7053983685419859001">Blokovať</translation>
<translation id="7062635574500127092">Modrozelená</translation>
-<translation id="7064851114919012435">Kontaktné informácie</translation>
+<translation id="7064851114919012435">Kontaktné údaje</translation>
<translation id="7075452647191940183">Žiadosť je príliš veľká</translation>
<translation id="7079718277001814089">Tento web obsahuje malvér</translation>
<translation id="7087282848513945231">Okres</translation>
@@ -1116,6 +1133,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ďalší}few{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ďalšie}many{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ďalšieho}other{<ph name="PAYMENT_METHOD_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> ďalších}}</translation>
<translation id="7153618581592392745">Levanduľová</translation>
<translation id="717330890047184534">ID služby Gaia:</translation>
+<translation id="7174545416324379297">Zlúčené</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalšia}few{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalšie}many{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalšej}other{<ph name="SHIPPING_OPTION_PREVIEW" /> a <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ďalších}}</translation>
<translation id="7177397715882417099">Server <ph name="ORIGIN" />, na ktorý prechádzate, požiadal, aby sa na všetky naň odoslané žiadosti vzťahovalo pravidlo zabezpečenia. Namiesto poskytnutia pravidla presmeroval prehliadač inam, čo bráni prehliadaču splniť vašu žiadosť týkajúcu sa webu <ph name="SITE" />.</translation>
<translation id="7179323680825933600">Ukladať a dopĺňať spôsoby platby</translation>
@@ -1150,6 +1168,7 @@
<translation id="7320336641823683070">Pomocník s pripojením</translation>
<translation id="733354035281974745">Prekonanie miestneho účtu zariadenia</translation>
<translation id="7334320624316649418">&amp;Znova zmeniť poradie</translation>
+<translation id="7337706099755338005">Nie je k dispozícii pre vašu platformu.</translation>
<translation id="733923710415886693">Certifikát servera nebol zverejnený prostredníctvom pravidla transparentnosti certifikátov.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Je pridružený/-á</translation>
@@ -1181,7 +1200,6 @@
<translation id="7440140511386898319">Prieskum v režime offline</translation>
<translation id="7441627299479586546">Chybný predmet pravidla</translation>
<translation id="7442725080345379071">Svetlooranžová</translation>
-<translation id="7444046173054089907">Tento web je blokovaný</translation>
<translation id="7445762425076701745">Identita servera, ku ktorému ste pripojení, sa nedá úplne overiť. Ste pripojení k serveru, ktorý používa názov platný iba v rámci vašej siete. Externá certifikačná autorita nemôže vlastníctvo názvu nijakým spôsobom overiť. Niektoré certifikačné autority však vydajú certifikát aj pre takéto názvy, a preto sa nedá zaručiť, že ste pripojení k požadovaným webovým stránkam a nie k stránkam útočníka.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Ďalšie informácie o tomto probléme<ph name="END_LINK" /></translation>
<translation id="7455133967321480974">Použiť predvolené všeobecné nastavenie (Blokovať)</translation>
@@ -1203,9 +1221,9 @@
<translation id="7538364083937897561">A2 (obálka)</translation>
<translation id="7542403920425041731">Po potvrdení budú údaje karty zdieľané s týmto webom.</translation>
<translation id="7542995811387359312">Automatické dopĺňanie údajov o kreditnej karte je zakázané, pretože tento formulár nepoužíva zabezpečené pripojenie.</translation>
-<translation id="7543525346216957623">Opýtajte sa rodiča</translation>
<translation id="7548892272833184391">Oprava chýb pripojenia</translation>
<translation id="7549584377607005141">Správne zobrazenie tejto webovej stránky si vyžaduje údaje, ktoré ste zadali v minulosti. Tieto údaje môžete poslať znova, ale v tom prípade zopakujete všetky akcie, ktoré sa na tejto stránke vykonali v minulosti.</translation>
+<translation id="7550637293666041147">Vaše používateľské meno v zariadení a Chrome</translation>
<translation id="7552846755917812628">Vyskúšajte nasledujúce tipy:</translation>
<translation id="7554791636758816595">Nová karta</translation>
<translation id="7564049878696755256">Môžete stratiť prístup do účtu <ph name="ORG_NAME" /> alebo vám niekto môže ukradnúť identitu. Chrome odporúča, aby ste si ihneď zmenili heslo.</translation>
@@ -1220,6 +1238,7 @@
<translation id="7610193165460212391">Hodnota (<ph name="VALUE" />) presahuje povolený rozsah.</translation>
<translation id="7613889955535752492">Dátum vypršania platnosti: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Už máte údaje, ktoré sú šifrované pomocou inej verzie vášho hesla účtu Google. Zadajte ho nižšie.</translation>
+<translation id="7625784245512586808">Systém ochrany Chrome Enterprise</translation>
<translation id="7633909222644580952">Údaje o výkonnosti a správy o zlyhaní</translation>
<translation id="7637571805876720304">Chcete kreditnú kartu odstrániť z prehliadača Chromium?</translation>
<translation id="7638605456503525968">Sériové porty</translation>
@@ -1232,7 +1251,6 @@
<translation id="7668654391829183341">Neznáme zariadenie</translation>
<translation id="7669271284792375604">Útočníci na tomto webe sa vás môžu pokúsiť podvodom presvedčiť, aby ste si nainštalovali programy poškodzujúce vaše prostredie prehliadania (napríklad zmenou domovskej stránky alebo zobrazovaním ďalších reklám na weboch, ktoré navštevujete).</translation>
<translation id="7676643023259824263">Vyhľadať v schránke text <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Platforma a cloud</translation>
<translation id="7681101578153515023">Zmeniť vyhľadávač</translation>
<translation id="7682287625158474539">Dodacia</translation>
<translation id="7687186412095877299">Doplní do platobných formulárov vaše uložené spôsoby platby</translation>
@@ -1247,7 +1265,6 @@
<translation id="7723047071702270851">Úprava karty</translation>
<translation id="774634243536837715">Nebezpečný obsah bol zablokovaný.</translation>
<translation id="7752995774971033316">Nespravované</translation>
-<translation id="7755287808199759310">Váš rodič ho môže pre vás odblokovať</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Pripojenie mohla zablokovať brána firewall alebo antivírusový softvér.</translation>
<translation id="7759163816903619567">Zobrazená doména:</translation>
@@ -1291,7 +1308,6 @@
<translation id="8004582292198964060">Prehliadač</translation>
<translation id="8009225694047762179">Spravovať heslá</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Táto karta a jej fakturačná adresa budú uložené. Budete ju môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}few{Tieto karty a ich fakturačné adresy budú uložené. Budete ich môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}many{Tieto karty a ich fakturačné adresy budú uložené. Budete ich môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}other{Tieto karty a ich fakturačné adresy budú uložené. Budete ich môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">V tejto chvíli sa nám nepodarilo spojiť s vašimi rodičmi. Skúste to znova neskôr.</translation>
<translation id="8025119109950072390">Útočníci na tomto webe sa vás môžu pokúsiť naviesť vykonať niečo nebezpečné, ako je inštalovanie softvéru alebo odhalenie osobných informácií (napr. hesiel, telefónnych čísel alebo kreditných kariet).</translation>
<translation id="8034522405403831421">Táto stránka je v jazyku <ph name="SOURCE_LANGUAGE" />. Chcete ju preložiť do jazyka <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pero</translation>
@@ -1302,6 +1318,7 @@
<translation id="8041940743680923270">Použiť predvolené všeobecné nastavenie (Opýtať sa)</translation>
<translation id="8042918947222776840">Zvoliť spôsob vyzdvihnutia</translation>
<translation id="8057711352706143257">Softvér <ph name="SOFTWARE_NAME" /> nie je správne nakonfigurovaný. Tento problém sa zvyčajne odstráni odinštalovaním softvéru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Odteraz nemusíte zadávať bezpečnostný kód karty</translation>
<translation id="8066955247577885446">Je nám to ľúto, ale vyskytol sa problém.</translation>
<translation id="8074253406171541171">10x13 (obálka)</translation>
<translation id="8078141288243656252">Po otočení dokumentu nie je anotácia možná</translation>
@@ -1332,6 +1349,7 @@
<translation id="8211406090763984747">Spojenie je zabezpečené</translation>
<translation id="8218327578424803826">Pridelená poloha:</translation>
<translation id="8220146938470311105">C7/C6 (obálka)</translation>
+<translation id="8220639454292072926">Prehľady podniku</translation>
<translation id="8225771182978767009">Osoba, ktorá nastavila tento počítač, sa rozhodla daný web blokovať.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Otvorte stránku na novej karte inkognito</translation>
@@ -1386,24 +1404,24 @@
<translation id="8508648098325802031">Ikona vyhľadávania</translation>
<translation id="8522552481199248698">Chrome vám pomôže ochrániť účet Google a zmeniť heslo.</translation>
<translation id="8543181531796978784">Môžete buď <ph name="BEGIN_ERROR_LINK" />nahlásiť problém s zisťovaním<ph name="END_ERROR_LINK" />, alebo <ph name="BEGIN_LINK" />tieto nebezpečné stránky navštíviť<ph name="END_LINK" /> (ak si uvedomujete bezpečnostné riziko).</translation>
-<translation id="8543556556237226809">Máte otázky? Obráťte sa na osobu, ktorá kontroluje váš profil.</translation>
<translation id="8553075262323480129">Prekladanie zlyhalo, pretože sa nepodarilo určiť jazyk stránky.</translation>
<translation id="8557066899867184262">Kód CVC nájdete na zadnej strane karty.</translation>
<translation id="8559762987265718583">Súkromné pripojenie k doméne <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> sa nedá nadviazať, pretože dátum a čas (<ph name="DATE_AND_TIME" />) vášho zariadenia sú nesprávne.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> podozrivý web</translation>
<translation id="8564985650692024650">Ak ste heslo organizácie <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> použili aj na iných weboch, Chromium ho odporúča obnoviť.</translation>
<translation id="8571890674111243710">Prebieha preklad stránky do jazyka: <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Pridať telefón
</translation>
-<translation id="859285277496340001">V certifikáte nie je uvedené, akým spôsobom sa má skontrolovať, či certifikát nebol odmietnutý.</translation>
<translation id="860043288473659153">Meno držiteľa karty</translation>
<translation id="861775596732816396">Veľkosť 4</translation>
-<translation id="8620436878122366504">Vaši rodičia to zatiaľ neschválili</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Uložiť túto kartu do tohto zariadenia</translation>
<translation id="8626112503828625890">Chcete uchovávať fakturačné údaje v účte Google?</translation>
+<translation id="8647750283161643317">Obnoviť predvolené nastavenia všetkých experimentov</translation>
<translation id="8663226718884576429">Súhrn objednávky, <ph name="TOTAL_LABEL" />, ďalšie podrobnosti</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, odpoveď, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">K dispozícii</translation>
<translation id="8703575177326907206">Vaše pripojenie k doméne <ph name="DOMAIN" /> sa nešifruje.</translation>
<translation id="8718314106902482036">Platba nebola dokončená</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, návrh vyhľadávania</translation>
@@ -1414,6 +1432,7 @@
<translation id="8738058698779197622">Ak chcete nadviazať zabezpečené pripojenie, vaše hodiny musia byť nastavené správne. Je to preto, že certifikáty, ktoré webové stránky používajú na vlastnú identifikáciu, sú platné iba určitý čas. Keďže nie sú hodiny vášho zariadenia nastavené správne, Chromium nemôže tieto certifikáty overiť.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Adresa DNS&lt;/abbr&gt; webu <ph name="HOST_NAME" /> sa nenašla. Problém sa diagnostikuje.</translation>
<translation id="874846938927089722">Akceptované kreditné a predplatené karty</translation>
+<translation id="874918643257405732">Pridať kartu medzi záložky</translation>
<translation id="8759274551635299824">Platnosť tejto karty vypršala</translation>
<translation id="8761567432415473239">Bezpečné prehliadanie Google nedávno <ph name="BEGIN_LINK" />zistilo škodlivé programy<ph name="END_LINK" /> na webe <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Zariadenie USB</translation>
@@ -1443,6 +1462,7 @@
<translation id="8938939909778640821">Akceptované kreditné a predplatené karty</translation>
<translation id="8943282376843390568">Limetková</translation>
<translation id="8957210676456822347">Autorizácia portálu na prihlásenie do siete</translation>
+<translation id="8962950042226115166">Podozrivý web</translation>
<translation id="8968766641738584599">Uložiť kartu</translation>
<translation id="8971063699422889582">Platnosť certifikátu servera vypršala.</translation>
<translation id="8975012916872825179">Zahŕňa telefónne čísla, e‑mailové adresy a dodacie adresy</translation>
@@ -1465,24 +1485,24 @@
<translation id="9035022520814077154">Chyba zabezpečenia</translation>
<translation id="9038649477754266430">Používať službu predpovedí na rýchlejšie načítanie stránok</translation>
<translation id="9039213469156557790">Táto stránka obsahuje aj iné zdroje, ktoré nie sú zabezpečené. Tieto zdroje môžu pri prenose vidieť ostatní používatelia a útočník ich môže upraviť tak, aby zmenil správanie stránky.</translation>
+<translation id="9044359186343685026">Použiť Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Pokúšate sa otvoriť doménu <ph name="DOMAIN" />, ale server predložil neplatný certifikát.</translation>
<translation id="9050666287014529139">Prístupová fráza</translation>
<translation id="9065203028668620118">Upraviť</translation>
<translation id="9065745800631924235">Vyhľadávanie <ph name="TEXT" /> z histórie</translation>
<translation id="9069693763241529744">Blokované rozšírením</translation>
-<translation id="9076283476770535406">Môže zahŕňať obsah pre dospelých</translation>
<translation id="9076630408993835509">Tento prehliadač nespravuje firma ani iná organizácia. Aktivita v tomto zariadení môže byť spravovaná mimo Chromu. <ph name="BEGIN_LINK" />Ďalšie informácie<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Treba zadať ďalšie informácie</translation>
<translation id="9080712759204168376">Súhrn objednávky</translation>
<translation id="9089260154716455634">Pravidlo intervalov nečinnosti:</translation>
<translation id="9095388113577226029">Ďalšie jazyky…</translation>
+<translation id="9098981495403789647">Správca vo vašom prehliadači zapol systém ochrany Chrome Enterprise. Systém ochrany Chrome Enterprise má prístup k niektorým vašim údajom.</translation>
<translation id="9103872766612412690">Web <ph name="SITE" /> zvyčajne chráni vaše informácie pomocou šifrovania. Keď sa prehliadač Chromium tentokrát pokúsil pripojiť k webu <ph name="SITE" />, odoslal späť nezvyčajné a nesprávne poverenia. Môže sa to stať vtedy, keď sa za web <ph name="SITE" /> snaží vydávať útočník alebo keď pripojenie preruší prihlasovacia obrazovka siete Wi‑Fi. Vaše informácie sú stále zabezpečené, pretože prehliadač Chromium zastavil pripojenie ešte pred výmenou dát.</translation>
<translation id="9106062320799175032">Pridanie fakturačnej adresy</translation>
<translation id="9114524666733003316">Overuje sa karta…</translation>
<translation id="9128870381267983090">Pripojiť k sieti</translation>
<translation id="9137013805542155359">Zobraziť originál</translation>
-<translation id="9137248913990643158">Začnite a prihláste sa do Chromu ešte predtým, ako použijete túto aplikáciu.</translation>
<translation id="9141013498910525015">Spravovať adresy</translation>
<translation id="9148088599418889305">Zvoliť spôsob dodania</translation>
<translation id="9148507642005240123">&amp;Vrátiť späť úpravu</translation>
diff --git a/chromium/components/strings/components_strings_sl.xtb b/chromium/components/strings/components_strings_sl.xtb
index 105b9c35fd3..e1fe9d58adc 100644
--- a/chromium/components/strings/components_strings_sl.xtb
+++ b/chromium/components/strings/components_strings_sl.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Dodajanje imena na kartico</translation>
<translation id="1089439967362294234">Spremeni geslo</translation>
+<translation id="1096545575934602868">V tem polju je lahko največ toliko vnosov: <ph name="MAX_ITEMS_LIMIT" />. Vsi nadaljnji vnosi bodo zavrženi.</translation>
<translation id="109743633954054152">Upravljajte gesla v Chromovih nastavitvah</translation>
<translation id="1103523840287552314">Vedno prevedi ta jezik: <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Če je izbrana ta možnost, bo shranil kopijo kartice v tej napravi za hitrejše izpolnjevanje obrazcev.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Odprite <ph name="BEGIN_LINK" />predpomnjeno kopijo<ph name="END_LINK" /> strani na naslovu <ph name="URL" /></translation>
<translation id="1156303062776767266">Ogledujete si lokalno datoteko ali datoteko v skupni rabi</translation>
<translation id="1158211211994409885">Spletno mesto <ph name="HOST_NAME" /> je nepričakovano prekinilo povezavo.</translation>
+<translation id="115926840831309955">Preverite CVC in poskusite znova ali posodobite datum poteka veljavnosti</translation>
<translation id="1161325031994447685">znova vzpostaviti povezavo z omrežjem Wi-Fi</translation>
<translation id="1165039591588034296">Napaka</translation>
<translation id="1175364870820465910">&amp;Natisni ...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">»Programska oprema v računalniku Chromu preprečuje vzpostavitev varne povezave s spletom« (samo računalniki s sistemom Windows)</translation>
<translation id="1294154142200295408">Različice ukazne vrstice</translation>
<translation id="129553762522093515">Nedavno zaprto</translation>
+<translation id="1298536327547837046">Pregledovanje glede zlonamerne programske opreme</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Poskusite izbrisati piškotke<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Zastarele funkcije</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">Iskanje slike v odložišču</translation>
<translation id="1323433172918577554">Pokaži več</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Preglednice</translation>
<translation id="1527263332363067270">Čakanje na povezavo ...</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">Spletno mesto, ki ste ga pravkar poskusili odpreti, je videti lažno. Napadalci včasih poskušajo kopirati spletna mesta, tako da skoraj neopazno spremenijo URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Ta stran sporoča:</translation>
<translation id="153384715582417236">To je vse za zdaj</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">Operacijski sistem</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Dokument je prevelik, da bi mu dodali pripise</translation>
-<translation id="1721312023322545264"><ph name="NAME" /> vam mora odobriti obisk tega spletnega mesta</translation>
<translation id="1721424275792716183">*Polje je obvezno</translation>
<translation id="1727741090716970331">Dodajanje veljavne številke kartice</translation>
<translation id="1728677426644403582">Ogledujete si izvorno kodo spletne strani</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Spletna mesta, ki jih obiščete, in čas, ki ga porabite zanje</translation>
<translation id="1826516787628120939">Preverjanje</translation>
<translation id="1834321415901700177">Na tem spletnem mestu so škodljivi programi</translation>
+<translation id="1838374766361614909">Čiščenje iskanja</translation>
<translation id="1839551713262164453">Preverjanje vrednosti pravilnika je bilo neuspešno z napakami</translation>
<translation id="1842969606798536927">Plačilo</translation>
<translation id="1871208020102129563">Proxy je nastavljen na uporabo stalnih strežnikov proxy, ne na URL skripta .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Strni seznam</translation>
<translation id="1898423065542865115">Filtriranje</translation>
<translation id="1914326953223720820">Storitev razširjanja datotek</translation>
+<translation id="1915697529809968049">Želite namesto kode CVC uporabiti Touch ID?</translation>
<translation id="1916770123977586577">Če želite uporabiti posodobljene nastavitve za to spletno mesto, znova naložite to stran</translation>
<translation id="1919345977826869612">Oglasi</translation>
<translation id="1919367280705858090">Pomoč pri določenem sporočilu o napaki</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Zaznamki domene <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Napaka pri serializaciji</translation>
<translation id="1974060860693918893">Dodatno</translation>
+<translation id="1974883374937189061">S pošiljanjem <ph name="BEGIN_WHITEPAPER_LINK" />URL-jev nekaterih strani, ki jih obiščete, omejenih podatkov o sistemu in nekatere vsebine strani<ph name="END_WHITEPAPER_LINK" /> Googlu lahko pomagate izboljšati Chrome. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Različica vdelane programske opreme</translation>
<translation id="1981206234434200693">Počistite podatke zgodovine brskanja v Chromu</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{in še 1}one{in še #}two{in še #}few{in še #}other{in še #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Vnesite veljavno leto poteka veljavnosti</translation>
<translation id="2212735316055980242">Pravilnika ni mogoče najti</translation>
<translation id="2213606439339815911">Prenos vnosov ...</translation>
+<translation id="2215727959747642672">Urejanje datotek</translation>
<translation id="2218879909401188352">Napadalci, ki so trenutno na spletnem mestu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, bi lahko namestili nevarne aplikacije, ki poškodujejo napravo, dodajo skrite stroške na račun za mobilno napravo ali ukradejo osebne podatke. <ph name="BEGIN_LEARN_MORE_LINK" />Več o tem<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Ni internetne povezave</translation>
<translation id="2230458221926704099">Odpravite težave s povezavo z <ph name="BEGIN_LINK" />aplikacijo za diagnostiko<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Pošlji</translation>
+<translation id="2248949050832152960">Uporabi WebAuthn</translation>
<translation id="225207911366869382">Vrednost za ta pravilnik je zastarela.</translation>
<translation id="2257315177824333709">Kartice trenutno ni mogoče shraniti</translation>
<translation id="2262243747453050782">Napaka HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Neveljaven URL iskanja.</translation>
<translation id="2482878487686419369">Obvestila</translation>
<translation id="248348093745724435">Pravilniki naprave</translation>
-<translation id="2485387744899240041">Uporabniška imena za napravo in brskalnik</translation>
<translation id="2491120439723279231">V potrdilu strežnika so napake.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Razčlenjevalnik za JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Nazaj</translation>
<translation id="2503184589641749290">Sprejete debetne in predplačniške kartice</translation>
<translation id="2505268675989099013">Zaščita računa</translation>
+<translation id="2515335152965840738">PREZRI</translation>
<translation id="2515629240566999685">preveriti signal na svojem območju</translation>
<translation id="2523886232349826891">Shranjena samo v tej napravi</translation>
<translation id="2524461107774643265">Dodajanje več podatkov</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Pošlji</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Nič}=1{Eno geslo (za <ph name="DOMAIN_LIST" />)}=2{Dve gesli (za <ph name="DOMAIN_LIST" />)}one{# geslo (za <ph name="DOMAIN_LIST" />)}two{# gesli (za <ph name="DOMAIN_LIST" />)}few{# gesla (za <ph name="DOMAIN_LIST" />)}other{# gesel (za <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Zaprite druge zavihke ali aplikacije</translation>
-<translation id="267371737713284912">pritisk tipke <ph name="MODIFIER_KEY_DESCRIPTION" /> za razveljavitev</translation>
<translation id="2674170444375937751">Ali ste prepričani, da želite te strani izbrisati iz svoje zgodovine?</translation>
<translation id="2676271551327853224">ROC 16K</translation>
<translation id="2677748264148917807">Zapusti</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Vrednost se ne ujema z obliko.</translation>
<translation id="2705137772291741111">Shranjena (predpomnjena) kopija tega spletnega mesta je bila neberljiva.</translation>
<translation id="2709516037105925701">Samodejno izpolnjevanje</translation>
-<translation id="2712173769900027643">Zahtevaj dovoljenje</translation>
<translation id="2713444072780614174">Bela</translation>
<translation id="2720342946869265578">V bližini</translation>
<translation id="2721148159707890343">Zahteva je uspela</translation>
<translation id="2728127805433021124">Strežnikovo potrdilo je podpisano s šibkim podpisnim algoritmom.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Izvajanje orodja Diagnostika povezljivosti<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Če omogočite te funkcije, lahko izgubite podatke brskalnika oziroma
+ ogrozite svojo varnost ali zasebnost. Omogočene funkcije veljajo za vse
+ uporabnike tega brskalnika.</translation>
<translation id="2735043616039983645">Za ta pravilnik je več virov z navzkrižnimi vrednostmi.</translation>
<translation id="2738330467931008676">Izbira naslova za prevzem</translation>
<translation id="2740531572673183784">V redu</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Povezava je bila obnovljena.</translation>
<translation id="2788784517760473862">Sprejete kreditne kartice</translation>
<translation id="2792012897584536778">Skrbniki te naprave so nastavili varnostna potrdila, ki jim morda omogočajo ogled vsebine spletnih mest, ki jih obiščete.</translation>
-<translation id="2794233252405721443">Spletno mesto blokirano</translation>
<translation id="2799020568854403057">Spletno mesto vsebuje škodljive aplikacije</translation>
<translation id="2799223571221894425">Vnovičen zagon</translation>
<translation id="2803306138276472711">Googlova funkcija varnega brskanja je na spletnem mestu <ph name="SITE" /> nedavno <ph name="BEGIN_LINK" />zaznala zlonamerno programsko opremo<ph name="END_LINK" />. Spletna mesta, ki so običajno varna, so včasih okužena z zlonamerno programsko opremo.</translation>
+<translation id="2815364696811431560">ZAPUSTI SPLETNO MESTO</translation>
<translation id="2824775600643448204">Naslovna in iskalna vrstica</translation>
<translation id="2826760142808435982">Za šifriranje in preverjanje pristnosti povezave se uporablja <ph name="CIPHER" />, kot mehanizem za izmenjavo ključev pa <ph name="KX" />.</translation>
<translation id="2835170189407361413">Počisti obrazec</translation>
<translation id="2847118875340931228">Odpri novo okno brez beleženja zgodovine</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">Za obisk tega spletnega mesta potrebujete dovoljenje</translation>
<translation id="2856444702002559011">Morda poskušajo napadalci ukrasti vaše podatke s spletnega mesta <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (na primer gesla, sporočila ali podatke kreditnih kartic). <ph name="BEGIN_LEARN_MORE_LINK" />Več o tem<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Želite shraniti kartico?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Če je to omogočeno, Chromium shrani kopijo kartice v tej napravi zaradi hitrejšega izpolnjevanja obrazcev.</translation>
<translation id="2985398929374701810">Vnesite veljaven naslov</translation>
<translation id="2986368408720340940">Ta način prevzema ni na voljo. Poskusite uporabiti drugega.</translation>
+<translation id="2987034854559945715">Ni ustreznih funkcij</translation>
<translation id="2991174974383378012">Deljenje s spletnimi mesti</translation>
<translation id="2991571918955627853">Spletnega mesta <ph name="SITE" /> trenutno ni mogoče obiskati, saj uporablja protokol HSTS. Napake omrežja in napadi na omrežje so običajno začasni, zato bo ta stran verjetno delovala pozneje.</translation>
<translation id="3005723025932146533">Pokaži shranjeno kopijo</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Napačna vrsta pravilnika</translation>
<translation id="3037605927509011580">Ti šment!</translation>
<translation id="3041612393474885105">Informacije o potrdilu</translation>
+<translation id="3057676462092457419">Način DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> še ni podprt, način je nastavljen na <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">Storitev za popravke</translation>
<translation id="3064966200440839136">Zaradi plačila v zunanji aplikaciji boste zapustili način brez beleženja zgodovine. Želite nadaljevati?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> v strežniku <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Prekliči plačilo</translation>
<translation id="3207960819495026254">Dodano med zaznamke</translation>
+<translation id="3209034400446768650">Stran morda zaračunava</translation>
<translation id="3225919329040284222">Strežnik je poslal potrdilo, ki se ne ujema z vgrajenimi pričakovanji. Ta pričakovanja so zaradi vaše varnosti vključena za nekatera strogo zavarovana spletna mesta.</translation>
<translation id="3226128629678568754">Pritisnite gumb za vnovično nalaganje, da znova pošljete podatke za nalaganje strani.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Podatki o različici za napravo in brskalnik</translation>
<translation id="323107829343500871">Vnesite CVC za <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Vedno zaznaj pomembno vsebino na tem spletnem mestu</translation>
-<translation id="3254409185687681395">Zaznamujte to stran</translation>
<translation id="3270847123878663523">&amp;Razveljavi razvrstitev</translation>
<translation id="3274521967729236597">Pa Kai</translation>
<translation id="3282497668470633863">Dodajanje imena na kartico</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Dodajanje naslova za izstavitev računa</translation>
<translation id="3324983252691184275">Škrlatna</translation>
<translation id="3338095232262050444">Varno</translation>
-<translation id="3345135638360864351">Zahteve za dostop do tega spletnega mesta ni bilo mogoče poslati osebi <ph name="NAME" />. Poskusite znova.</translation>
<translation id="3355823806454867987">Spremeni nastavitve proxyja ...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />ne shrani<ph name="END_EMPHASIS" /> teh podatkov:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Skrij podrobnosti</translation>
<translation id="3467763166455606212">Ime imetnika kartice je obvezno</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, trenutno odprto, pritisnite tabulatorko, nato Enter, če želite preklopiti na odprti zavihek</translation>
-<translation id="3479539252931486093">Ali tega niste pričakovali? <ph name="BEGIN_LINK" />Sporočite nam<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Ne zdaj</translation>
<translation id="3484560055331845446">Izgubite lahko dostop do Google Računa. Chrome priporoča, da spremenite geslo. Pozvani boste, da se prijavite.</translation>
<translation id="3495081129428749620">Iskanje na strani
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Trenutno ni mogoče vzpostaviti stika s staršem. Poskusi znova pozneje.</translation>
<translation id="3512163584740124171">Ta pravilnik se prezre, ker ima drug pravilnik iz iste skupine pravilnikov prednost.</translation>
<translation id="3528171143076753409">Potrdilo strežnika ni zaupanja vredno.</translation>
<translation id="3528485271872257980">Temno rjava</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Vsaj en element v sinhroniziranih napravah}=1{1 element (in več v sinhroniziranih napravah)}one{# element (in več v sinhroniziranih napravah)}two{# elementa (in več v sinhroniziranih napravah)}few{# elementi (in več v sinhroniziranih napravah)}other{# elementov (in več v sinhroniziranih napravah)}}</translation>
<translation id="3539171420378717834">Ohrani kopijo te kartice v tej napravi</translation>
-<translation id="3556433843310711081">Skrbnik ga lahko odblokira</translation>
<translation id="3566021033012934673">Vaša povezava ni zasebna</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Vdelana stran na spletnem mestu <ph name="SITE" /> sporoča:</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Odpiranje strani v novem oknu brez beleženja zgodovine (Ctrl + Shift + N)</translation>
<translation id="3679803492151881375">Poročilo o zrušitvi je bilo zajeto takrat: <ph name="CRASH_TIME" />, naloženo takrat: <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Informacije o potrdilu</translation>
+<translation id="3701427423622901115">Ponastavitev je potrjena.</translation>
<translation id="3704162925118123524">Omrežje, ki ga uporabljate, morda zahteva, da obiščete stran za prijavo.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Nalaganje ...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Napadalci na <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> vas lahko z zavajanjem morda pripravijo do tega, da storite kaj nevarnega – denimo, da namestite programsko opremo ali razkrijete osebne podatke (na primer gesla, telefonske številke ali podatke kreditnih kartic). <ph name="BEGIN_LEARN_MORE_LINK" />Več o tem<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Prevajanje ni uspelo zaradi napake strežnika.</translation>
<translation id="3759461132968374835">Nimate nedavnih poročil o zrušitvah. Zrušitve, do katerih je prišlo, ko je bilo poročanje onemogočeno, ne bodo prikazane zukaj.</translation>
+<translation id="3760561303380396507">Želite namesto kode CVC uporabiti Hello?</translation>
<translation id="3761718714832595332">Skrivanje stanja</translation>
<translation id="3765032636089507299">Stran varnega brskanja je v izdelavi.</translation>
<translation id="3778403066972421603">Ali želite shraniti to kartico v Google Račun in v tej napravi?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Velikost 16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">Škodljiva vsebina je bila blokirana.</translation>
+<translation id="3808375843007691220">Opozorilo: pred vami so poskusne funkcije.</translation>
<translation id="3810973564298564668">Upravljanje</translation>
<translation id="382518646247711829">Če uporabite namestniški strežnik ...</translation>
<translation id="3828924085048779000">Prazno geslo ni dovoljeno.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Posodobi datum in uro</translation>
<translation id="3884278016824448484">Identifikator naprave je v sporu</translation>
<translation id="3885155851504623709">Župnija</translation>
-<translation id="3886446263141354045">Vaša zahteva za dostop do tega mesta je poslana uporabniku <ph name="NAME" /></translation>
<translation id="3890664840433101773">Dodajanje e-poštnega naslova</translation>
<translation id="3901925938762663762">Kartica je potekla</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> – <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Želite namesto kode CVC uporabiti WebAuthn?</translation>
<translation id="3946209740501886391">Vedno vprašaj na tem spletnem mestu</translation>
<translation id="3949571496842715403">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo ne določa nadomestnih imen SAN (Subject Alternative Name). Razlog za to je morda napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
<translation id="3949601375789751990">Tu je prikazana zgodovina brskanja</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Brez}=1{1 spletno mesto }one{# spletno mesto }two{# spletni mesti }few{# spletna mesta }other{# spletnih mest }}</translation>
<translation id="397105322502079400">Izračunavanje …</translation>
<translation id="3973234410852337861">Spletno mesto <ph name="HOST_NAME" /> je blokirano</translation>
+<translation id="3981540111851280311">Domena <ph name="ENROLLMENT_DOMAIN" /> je v brskalniku omogočila Chromovo funkcijo zaščite pred grožnjami za podjetja. Chromova funkcija zaščite pred grožnjami za podjetja ima dostop do nekaterih vaših podatkov.</translation>
<translation id="3987940399970879459">Manj kot 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 spletna stran v bližini}one{# spletna stran v bližini}two{# spletni strani v bližini}few{# spletne strani v bližini}other{# spletnih strani v bližini}}</translation>
<translation id="4030383055268325496">&amp;Razveljavi dodajanje</translation>
<translation id="4032320456957708163">Brskalnik upravlja domena <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Povezava, ki ste jo odprli, vodi na spletno mesto, ki ga običajno ne obiskujete. Morda vas poskuša zmesti.</translation>
<translation id="4058922952496707368">Ključ »<ph name="SUBKEY" />«: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">Dodajanje veljavnega naslova</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Neveljavna serijska številka naprave</translation>
<translation id="410351446219883937">Samodejno predvajanje</translation>
<translation id="4103763322291513355">Na &lt;strong&gt;chrome://policy&lt;/strong&gt; si lahko ogledate seznam blokiranih URL-jev in drugih pravilnikov, ki jih uveljavlja skrbnik sistema.</translation>
+<translation id="4108231218301530806">Uporaba prstnega odtisa za potrditev te kartice naslednjič.</translation>
<translation id="4110652170750985508">Pregled plačila</translation>
<translation id="4112140312785995938">Išči nazaj</translation>
<translation id="4116663294526079822">Vedno dovoli na tem spletnem mestu</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Neveljavni podpis za preverjanje</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Še <ph name="ITEM_COUNT" /> element}one{Še <ph name="ITEM_COUNT" /> element}two{Še <ph name="ITEM_COUNT" /> elementa}few{Še <ph name="ITEM_COUNT" /> elementi}other{Še <ph name="ITEM_COUNT" /> elementov}}</translation>
+<translation id="4176463684765177261">Onemogočeno</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Če želite naslednjič hitreje plačati, dodajte kartico in naslov za izstavitev računa v računu za Google.</translation>
<translation id="4196861286325780578">&amp;Uveljavi premik</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Ponastavi geslo</translation>
<translation id="4279811152705618813">Vašo napravo <ph name="DEVICE_TYPE" /> upravlja domena <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ta kartica je shranjena v Google Računu}one{Te kartice so shranjene v Google Računu}two{Te kartice so shranjene v Google Računu}few{Te kartice so shranjene v Google Računu}other{Te kartice so shranjene v Google Računu}}</translation>
+<translation id="428847186335018806">Pregledovanje datotek, ki jih prenesete iz Chroma ali naložite vanj.</translation>
<translation id="42981349822642051">Razširi</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">Preklopi</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Uporaba strežnika proxy je onemogočena, vendar je njegova konfiguracija izrecno določena.</translation>
<translation id="445100540951337728">Sprejete debetne kartice</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> sumljivo vedenje</translation>
<translation id="4466881336512663640">Spremembe obrazca bodo izgubljene. Ali ste prepričani, da želite nadaljevati?</translation>
<translation id="4477350412780666475">Naslednja skladba</translation>
<translation id="4482953324121162758">To spletno mesto ne bo prevedeno.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Razveljavi izbris</translation>
<translation id="4597348597567598915">Velikost 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">Funkcije iskanja</translation>
<translation id="4646534391647090355">Odpri zdaj</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo vsebuje napake. Razlog za to je lahko napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Povezava je bila prekinjena</translation>
-<translation id="471880041731876836">Nimate dovoljenja za obisk tega spletnega mesta</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Izvajanje orodja Omrežna diagnostika Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Znova naloži pravilnike</translation>
<translation id="4728558894243024398">Okolje</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Prilagodi strani</translation>
<translation id="4850886885716139402">Pogled</translation>
<translation id="4854362297993841467">Ta način pošiljanja ni na voljo. Poskusite uporabiti drugega.</translation>
-<translation id="4858792381671956233">Starše si vprašal(-a), ali smeš obiskati to spletno mesto</translation>
<translation id="4864052566555297930">Varnostni nasvet:</translation>
<translation id="4876188919622883022">Poenostavljen pogled</translation>
<translation id="4876305945144899064">Ni uporabniškega imena</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Vnovično omogočanje opozoril</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">Pokaži vse</translation>
+<translation id="4989542687859782284">Ni na voljo</translation>
<translation id="4989809363548539747">Ta vtičnik ni podprt</translation>
+<translation id="4995216769782533993">Potrdite varnostno kodo, če želite s tem mestom deliti podatke o kartici</translation>
<translation id="5002932099480077015">Če je to omogočeno, Chrome shrani kopijo kartice v tej napravi zaradi hitrejšega izpolnjevanja obrazcev.</translation>
<translation id="5015510746216210676">Ime naprave:</translation>
<translation id="5017554619425969104">Besedilo, ki ste ga kopirali</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-bitno)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Preverjanje kartice</translation>
<translation id="5135404736266831032">Upravljanje naslovov ...</translation>
<translation id="5138227688689900538">Pokaži manj</translation>
<translation id="5141240743006678641">Šifrirajte sinhronizirana gesla s poverilnicami za Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Oblak</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funkcije, ki se uporabijo v celotnem sistemu, lahko nastavi samo lastnik: <ph name="OWNER_EMAIL" />.</translation>
<translation id="5273658854610202413">Opozorilo: ta pravilnik ni bil združen, kot je določeno v pravilniku PolicyDictionaryMultipleSourceMergeList, ker ne sodi k pravilnikom o slovarjih, ki jih je mogoče združiti.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Konec</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Nastavitev pravilnika ni bilo mogoče shraniti</translation>
<translation id="5371425731340848620">Posodobite kartico</translation>
<translation id="5377026284221673050">Ura zaostaja« ali »Ura prehiteva« ali »&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;«</translation>
-<translation id="5377179979757081683">Ta stran vas morda poskuša zavesti, vam ukrasti osebne podatke ali škodovati napravi. Bodite previdni, ko vnašate osebne podatke ali odpirate prenesene datoteke.</translation>
<translation id="5384855140246857529">Če želite uporabljati kartice v vseh napravah, se prijavite in vklopite sinhronizacijo.</translation>
<translation id="5386426401304769735">Veriga potrdil za to spletno mesto vsebuje potrdilo, podpisano z algoritmom SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Neveljavno</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}two{<ph name="CONTACT_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Uveljavi urejanje</translation>
+<translation id="5473728911100096288">Če omogočite te funkcije, boste uporabljali zastarele funkcije,
+ ki bodo v prihodnjih različicah opuščene.</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">Ta vsebina morda v napravi poskuša namestiti nevarno programsko opremo, ki ukrade ali izbriše vaše podatke. <ph name="BEGIN_LINK" />Vseeno prikaži<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Dodajanje veljavnega naslova</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Zaščita računa</translation>
<translation id="5571083550517324815">Prevzem na tem naslovu ni mogoč. Izberite drugega.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 v uporabi}one{# v uporabi}two{# v uporabi}few{# v uporabi}other{# v uporabi}})</translation>
-<translation id="5572851009514199876">Začnite s prijavo v Chrome, da lahko Chrome preveri, ali vam je dovoljeno dostopati do tega spletnega mesta.</translation>
<translation id="5580958916614886209">Preverite mesec poteka veljavnosti in poskusite znova</translation>
<translation id="5586446728396275693">Ni shranjenih naslovov</translation>
<translation id="5595485650161345191">Uredi naslov</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Upravljanje ni podprto</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">To spletno mesto je lahko lažno ali goljufivo. Chrome predlaga, da ga takoj zapustite.</translation>
<translation id="5610142619324316209">preveriti povezavo</translation>
<translation id="5610807607761827392">Kartice in naslove je mogoče upravljati v <ph name="BEGIN_LINK" />nastavitvah<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Spletno mesto <ph name="HOST_NAME" /> vas je prevečkrat preusmerilo.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Trenutni uporabnik</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">Chrome priporoča, da ponastavite geslo, če ste ga uporabljali na drugih spletnih mestih.</translation>
-<translation id="5732392974455271431">Starši ga lahko odblokirajo</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Shranjevanje kartice v Google Računu}one{Shranjevanje kartic v Google Računu}two{Shranjevanje kartic v Google Računu}few{Shranjevanje kartic v Google Računu}other{Shranjevanje kartic v Google Računu}}</translation>
<translation id="5763042198335101085">Vnesite veljaven e-poštni naslov</translation>
<translation id="5765072501007116331">Če si želite ogledati načine dostave in zahteve, izberite naslov</translation>
<translation id="5778550464785688721">Popolni nadzor naprav MIDI</translation>
+<translation id="5781136890105823427">Preizkus je omogočen</translation>
<translation id="578305955206182703">Jantarna</translation>
<translation id="57838592816432529">Izklopi zvok</translation>
<translation id="5784606427469807560">Težava pri potrditvi kartice. Preverite internetno povezavo in poskusite znova.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Izklopljeno</translation>
<translation id="5863847714970149516">Stran, ki se bo odprla, vam bo morda poskusila kaj zaračunati</translation>
<translation id="5866257070973731571">Dodajanje telefonske številke</translation>
+<translation id="5866898949289125849">Ogledujete si stran z orodji za razvijalce</translation>
<translation id="5869405914158311789">Tega spletnega mesta ni mogoče doseči</translation>
<translation id="5869522115854928033">Shranjena gesla</translation>
<translation id="5887400589839399685">Kartica je shranjena</translation>
<translation id="5893752035575986141">Sprejema kreditne kartice.</translation>
+<translation id="5895138241574237353">Znova zaženi</translation>
<translation id="5901630391730855834">Rumena</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sinhronizirano)</translation>
<translation id="5916664084637901428">Vklopljeno</translation>
+<translation id="59174027418879706">Omogočeno</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Ali želite kartico shraniti v Google Račun?</translation>
<translation id="5922853866070715753">Skoraj končano</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Želite kartice uporabljati v vseh svojih napravah?</translation>
<translation id="6059925163896151826">Naprave USB</translation>
+<translation id="6060009363608157444">Neveljaven način DnsOverHttps.</translation>
<translation id="6080696365213338172">Do vsebine ste dostopali z geslom, ki ga je zagotovil skrbnik. Podatke, ki jih pošljete v <ph name="DOMAIN" />, lahko prestreže skrbnik.</translation>
<translation id="6094273045989040137">Pripisovanje</translation>
<translation id="610911394827799129">V Google Računu so morda druge vrste zgodovine brskanja na <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Uredi zaznamek</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">Vnesite datum poteka veljavnosti in kodo CVC za kartico <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Starša si vprašal(-a), ali smeš obiskati to spletno mesto</translation>
<translation id="6415778972515849510">Chromium vam lahko pomaga zaščititi račun za Google in spremeniti geslo.</translation>
-<translation id="6417515091412812850">Ni mogoče preveriti, ali je bilo potrdilo preklicano.</translation>
<translation id="6431585503458005759">Ne shrani</translation>
<translation id="6433490469411711332">Uredi informacije o stiku</translation>
<translation id="6433595998831338502">Spletno mesto <ph name="HOST_NAME" /> ni dovolilo povezave.</translation>
<translation id="6434309073475700221">Zavrzi</translation>
+<translation id="6435221585574090192">Skrbniku posredujte podatke o varnostnih dogodkih, ki jih je označila Chromova funkcija zaščite pred grožnjami za podjetja. Ti lahko vključujejo URL-je strani, ime datoteke in metapodatke o datoteki, uporabniško ime v napravi in uporabniško ime v Chromu.</translation>
<translation id="6440503408713884761">Prezrto</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">Dodajanje več podatkov</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Upravljanje gesel ...</translation>
<translation id="647261751007945333">Pravilniki za naprave</translation>
<translation id="6476284679642588870">Upravljanje plačilnih sredstev</translation>
-<translation id="6477321094435799029">Chrome je zaznal nenavadno kodo na tej strani in jo zaradi zaščite vaših osebnih podatkov (na primer gesel, telefonskih številk in kreditnih kartic) blokiral.</translation>
<translation id="6489534406876378309">Začetek prenašanja zrušitev v storitev</translation>
<translation id="6499038740797743453">Ali želite ponastaviti geslo?</translation>
<translation id="6507833130742554667">Sprejema kreditne in debetne kartice.</translation>
<translation id="650855688985305916">Da, shrani</translation>
<translation id="6508722015517270189">Znova zaženite Chrome</translation>
<translation id="6517596291481585650">Opozorilo: ta pravilnik ni bil združen kot seznam, kot je določeno v pravilniku, ker ni seznam.</translation>
+<translation id="6518133107902771759">Preveri</translation>
<translation id="6521745193039995384">Nedejavno</translation>
<translation id="6529602333819889595">&amp;Uveljavi izbris</translation>
<translation id="6534179046333460208">Predlogi za Fizični splet</translation>
<translation id="6545864417968258051">Iskanje naprav Bluetooth</translation>
<translation id="6554795675067793129">Vaš račun upravlja <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Uveljavi</translation>
-<translation id="6563469144985748109">Skrbnik še ni odobril</translation>
<translation id="6569060085658103619">Ogledujete si stran razširitve</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">Svetlo rožnata</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Izbriši</translation>
<translation id="6644283850729428850">Ta pravilnik je zastarel.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Nič}=1{Na 1 spletnem mestu (iz Google Računa ne boste odjavljeni)}one{Na # spletnem mestu (iz Google Računa ne boste odjavljeni)}two{Na # spletnih mestih (iz Google Računa ne boste odjavljeni)}few{Na # spletnih mestih (iz Google Računa ne boste odjavljeni)}other{Na # spletnih mestih (iz Google Računa ne boste odjavljeni)}}</translation>
+<translation id="6652101503459149953">Uporabi Windows Hello</translation>
<translation id="6657585470893396449">Geslo</translation>
<translation id="6670613747977017428">Nazaj na varno.</translation>
<translation id="6671697161687535275">Želite predlog obrazca odstraniti iz Chromiuma?</translation>
<translation id="6685834062052613830">Odjavite se in dokončajte nastavitev</translation>
<translation id="6689271823431384964">Chrome ponuja shranjevanje kartic v račun za Google, ker ste prijavljeni. To lahko spremenite v nastavitvah. Ime imetnika računa je iz vašega računa.</translation>
+<translation id="6707256370811247129">Pregled vsebine predpomnilnika in datotek, ki jih prenesete iz Chroma ali naložite vanj.</translation>
<translation id="6710213216561001401">Nazaj</translation>
<translation id="6710594484020273272">&lt;Vnesite iskalno poizvedbo&gt;</translation>
<translation id="671076103358959139">Žeton za včlanitev:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Podatki so bili šifrirani (<ph name="TIME" />) z vašim <ph name="BEGIN_LINK" />geslom za sinhronizacijo<ph name="END_LINK" />. Vnesite ga, če želite začeti sinhronizacijo.</translation>
<translation id="674375294223700098">Neznana napaka potrdila strežnika.</translation>
<translation id="6744009308914054259">Med čakanjem na povezavo lahko berete članke za branje brez povezave med prenosi.</translation>
+<translation id="6747611005629681221">Opozorilo: pred vami so zastarele funkcije.</translation>
<translation id="6753269504797312559">Vrednost pravilnika</translation>
<translation id="6757797048963528358">Naprava je preklopila v stanje pripravljenosti.</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">Starši še niso odobrili</translation>
<translation id="67862343314499040">Vijoličnomodra</translation>
<translation id="6786747875388722282">Razširitve</translation>
<translation id="6790428901817661496">Predvajanje</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Obvezno polje</translation>
<translation id="6810899417690483278">ID za prilagajanje</translation>
<translation id="6825578344716086703">Poskusili ste dostopati do domene <ph name="DOMAIN" />, vendar ima strežnik potrdilo, podpisano s šibkim podpisnim algoritmom (kot je SHA-1). To pomeni, da so varnostne poverilnice, ki jih je poslal strežnik, morda ponarejene in strežnik morda ni tisti, ki ga pričakujete (morda komunicirate z napadalcem).</translation>
+<translation id="6826370046007623921">Preprečevanje izgube podatkov</translation>
<translation id="6831043979455480757">Prevedi</translation>
<translation id="6839929833149231406">Območje</translation>
<translation id="6852204201400771460">Želite znova naložiti aplikacijo?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Raven pravilnika ni podprta.</translation>
<translation id="6895330447102777224">Kartica je potrjena.</translation>
<translation id="6897140037006041989">Uporabnikov posrednik</translation>
-<translation id="6903319715792422884">S pošiljanjem nekaterih <ph name="BEGIN_WHITEPAPER_LINK" />informacij o sistemu in vsebine strani<ph name="END_WHITEPAPER_LINK" /> Googlu lahko pomagate izboljšati Varno brskanje. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Uporabnik:</translation>
<translation id="6934672428414710184">To ime je iz vašega računa za Google</translation>
<translation id="6944692733090228304">Vnesli ste geslo na spletnem mestu, ki ga ne upravlja: <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Zaradi zaščite računa gesla ne uporabljajte za druge aplikacije in spletna mesta.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}two{<ph name="PAYMENT_METHOD_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Svetlo vijolična</translation>
<translation id="717330890047184534">ID za Gaio:</translation>
+<translation id="7174545416324379297">Združeno</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}two{<ph name="SHIPPING_OPTION_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> in še <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Strežnik, na katerega greste (<ph name="ORIGIN" />), je zahteval, da se
za vse zahteve, ki so mu poslane, uporabi varnostni pravilnik. Vendar pa ni
@@ -1166,6 +1187,7 @@ Dodatne podrobnosti:
<translation id="7320336641823683070">Pomoč pri povezavi</translation>
<translation id="733354035281974745">Preglasitev lokalnega računa v napravi</translation>
<translation id="7334320624316649418">&amp;Uveljavi razvrstitev</translation>
+<translation id="7337706099755338005">Ni na voljo v vašem okolju.</translation>
<translation id="733923710415886693">Potrdilo strežnika ni bilo razkrito na podlagi pravilnika o preglednosti potrdila.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Je povezan:</translation>
@@ -1197,7 +1219,6 @@ Dodatne podrobnosti:
<translation id="7440140511386898319">Raziskujte, ko ni povezave</translation>
<translation id="7441627299479586546">Napačen subjekt pravilnika</translation>
<translation id="7442725080345379071">Svetlo oranžna</translation>
-<translation id="7444046173054089907">To spletno mesto je blokirano</translation>
<translation id="7445762425076701745">Identitete strežnika, s katerim ste povezani, ni mogoče v celoti preveriti. S strežnikom ste povezani z uporabo imena, ki je veljavno samo v vašem omrežju, zato zunanji overitelj potrdil ne more preveriti njegovega lastništva. Ker nekateri overitelji potrdil kljub temu izdajajo potrdila za takšna imena, ni mogoče zagotoviti, da ste povezani z želenim spletnim mestom in ne z napadalcem.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Preberite več<ph name="END_LINK" /> o tej težavi.</translation>
<translation id="7455133967321480974">Uporabi globalno privzeto (Blokiraj)</translation>
@@ -1219,9 +1240,9 @@ Dodatne podrobnosti:
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">Ko potrdite, bodo temu spletnemu mestu razkriti podatki o kartici.</translation>
<translation id="7542995811387359312">Samodejno izpolnjevanje podatkov o kreditni kartici je onemogočeno, ker ta obrazec ne uporablja varne povezave.</translation>
-<translation id="7543525346216957623">Prosi starša</translation>
<translation id="7548892272833184391">Odpravljanje napak s povezavo</translation>
<translation id="7549584377607005141">Za pravilen prikaz te strani so potrebni podatki, ki ste jih vnesli prej. Podatke lahko pošljete še enkrat, vendar se bodo s tem ponovila vsa prejšnja dejanja strani.</translation>
+<translation id="7550637293666041147">Uporabniško ime v napravi in uporabniško ime v Chromu</translation>
<translation id="7552846755917812628">Poskusite te nasvete:</translation>
<translation id="7554791636758816595">Nov zavihek</translation>
<translation id="7564049878696755256">Izgubite lahko dostop do računa za <ph name="ORG_NAME" /> ali postanete žrtev kraje identitete. Chrome priporoča, da spremenite geslo.</translation>
@@ -1236,6 +1257,7 @@ Dodatne podrobnosti:
<translation id="7610193165460212391">Vrednost je zunaj obsega <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Veljavnost do: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Podatke, ki so šifrirani z drugo različico gesla za Google Račun, že imate. Geslo vnesite spodaj.</translation>
+<translation id="7625784245512586808">Chromova funkcija zaščite pred grožnjami za podjetja</translation>
<translation id="7633909222644580952">Podatki o delovanju in poročila o zrušitvah</translation>
<translation id="7637571805876720304">Želite kreditno kartico odstraniti iz Chromiuma?</translation>
<translation id="7638605456503525968">Serijska vrata</translation>
@@ -1248,7 +1270,6 @@ Dodatne podrobnosti:
<translation id="7668654391829183341">Neznana naprava</translation>
<translation id="7669271284792375604">Napadalci na tem spletnem mestu vas bodo morda poskusili zavesti, da bi namestili programe, ki škodljivo vplivajo na brskanje (na primer tako, da spremenijo vašo domačo stran ali na spletnih mestih, ki jih obiščete, prikazujejo dodatne oglase).</translation>
<translation id="7676643023259824263">Iskanje besedila v odložišču, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Okolje in oblak</translation>
<translation id="7681101578153515023">Zamenjaj iskalnik</translation>
<translation id="7682287625158474539">Pošiljanje</translation>
<translation id="7687186412095877299">Izpolni obrazce za plačilo s shranjenimi podatki o plačilnih sredstvih</translation>
@@ -1263,7 +1284,6 @@ Dodatne podrobnosti:
<translation id="7723047071702270851">Urejanje kartice</translation>
<translation id="774634243536837715">Nevarna vsebina blokirana.</translation>
<translation id="7752995774971033316">Odstranjen iz uporabe</translation>
-<translation id="7755287808199759310">Starš ga lahko odblokira</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Povezavo je morda blokiral požarni zid ali protivirusni program.</translation>
<translation id="7759163816903619567">Prikaz domene:</translation>
@@ -1307,7 +1327,6 @@ Dodatne podrobnosti:
<translation id="8004582292198964060">Brskalnik</translation>
<translation id="8009225694047762179">Upravljanje gesel</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Shranjena bosta ta kartica in njen naslov za izstavitev računa. Uporabljali jo boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}one{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}two{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}few{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}other{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Trenutno ni mogoče vzpostaviti stika s starši. Poskusi znova pozneje.</translation>
<translation id="8025119109950072390">Napadalci na tem spletnem mestu vas lahko z zavajanjem morda pripravijo do tega, da storite kaj nevarnega – denimo, da namestite programsko opremo ali razkrijete osebne podatke (na primer gesla, telefonske številke ali podatke kreditnih kartic).</translation>
<translation id="8034522405403831421">Ta stran je v jeziku <ph name="SOURCE_LANGUAGE" />. Jo želite prevesti v jezik <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pisalo</translation>
@@ -1318,6 +1337,7 @@ Dodatne podrobnosti:
<translation id="8041940743680923270">Uporabi globalno privzeto (Vprašaj)</translation>
<translation id="8042918947222776840">Izbira načina prevzema</translation>
<translation id="8057711352706143257">Programska oprema »<ph name="SOFTWARE_NAME" />« ni pravilno konfigurirana. Običajno težavo odpravite tako, da odstranite programsko opremo »<ph name="SOFTWARE_NAME" />«. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Od zdaj naprej vam ne bo treba vnesti varnostne kode kartice</translation>
<translation id="8066955247577885446">Prišlo je do napake.</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">Ko je dokument zasukan, pripisovanje ni mogoče</translation>
@@ -1348,6 +1368,7 @@ Dodatne podrobnosti:
<translation id="8211406090763984747">Povezava je varna</translation>
<translation id="8218327578424803826">Dodeljena lokacija:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">Poročanje za podjetja</translation>
<translation id="8225771182978767009">Oseba, ki je nastavila ta računalnik, je blokirala to spletno mesto.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Odpiranje strani v novem zavihku brez beleženja zgodovine.</translation>
@@ -1402,23 +1423,23 @@ Dodatne podrobnosti:
<translation id="8508648098325802031">Ikona za iskanje</translation>
<translation id="8522552481199248698">Chrome vam lahko pomaga zaščititi račun za Google in spremeniti geslo.</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />Prijavite lahko težavo z zaznavanjem<ph name="END_ERROR_LINK" />, če razumete varnostna tveganja, pa lahko <ph name="BEGIN_LINK" />obiščete to spletno mesto, ki ni varno<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Imate kakšno vprašanje? Obrnite se na osebo, ki nadzira vaš profil.</translation>
<translation id="8553075262323480129">Prevod ni uspel, ker ni mogoče določiti jezika strani.</translation>
<translation id="8557066899867184262">CVC je na zadnji strani kartice.</translation>
<translation id="8559762987265718583">Zasebne povezave z domeno <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> ni mogoče vzpostaviti, ker sta datum in ura (<ph name="DATE_AND_TIME" />) v napravi nepravilna.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> sumljivo spletno mesto</translation>
<translation id="8564985650692024650">Chromium priporoča, da ponastavite geslo za <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, če ste ga uporabljali tudi na drugih spletnih mestih.</translation>
<translation id="8571890674111243710">Prevajanje strani v jezik <ph name="LANGUAGE" /> ...</translation>
<translation id="858637041960032120">Dodajte tel. št. </translation>
-<translation id="859285277496340001">Potrdilo ne navaja mehanizma za preverjanje tega, ali je bilo preklicano.</translation>
<translation id="860043288473659153">Ime imetnika kartice</translation>
<translation id="861775596732816396">Velikost 4</translation>
-<translation id="8620436878122366504">Starši še niso odobrili</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Shrani to kartico v tej napravi</translation>
<translation id="8626112503828625890">Želite shraniti podrobnosti za obračun v račun za Google?</translation>
+<translation id="8647750283161643317">Ponastavi vse na privzete</translation>
<translation id="8663226718884576429">Povzetek naročila, <ph name="TOTAL_LABEL" />, več podrobnosti</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, odgovor, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Na voljo</translation>
<translation id="8703575177326907206">Vaša povezava z <ph name="DOMAIN" /> ni kodirana.</translation>
<translation id="8718314106902482036">Plačilo ni končano</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, predlog iskanja</translation>
@@ -1429,6 +1450,7 @@ Dodatne podrobnosti:
<translation id="8738058698779197622">Če želite vzpostaviti varno povezavo, mora biti ura pravilno nastavljena. Potrdila, ki jih uporabljajo spletna mesta za prepoznavanje, namreč veljajo samo določen čas. Ker je ura sistema nepravilna, Chromium teh potrdil ne more preveriti.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Naslova DNS&lt;/abbr&gt; spletnega mesta <ph name="HOST_NAME" /> ni bilo mogoče najti. Poteka diagnosticiranje težave.</translation>
<translation id="874846938927089722">Sprejete kreditne in predplačniške kartice</translation>
+<translation id="874918643257405732">Dodajanje tega zavihka med zaznamke</translation>
<translation id="8759274551635299824">Ta kartica je potekla</translation>
<translation id="8761567432415473239">Googlova funkcija varnega brskanja je nedavno <ph name="BEGIN_LINK" />odkrila škodljive programe<ph name="END_LINK" /> na spletnem mestu <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Naprava USB</translation>
@@ -1458,6 +1480,7 @@ Dodatne podrobnosti:
<translation id="8938939909778640821">Sprejete kreditne in predplačniške kartice</translation>
<translation id="8943282376843390568">Rumenozelena</translation>
<translation id="8957210676456822347">Odobritev prestreznega portala</translation>
+<translation id="8962950042226115166">Sumljivo spletno mesto</translation>
<translation id="8968766641738584599">Shrani kartico</translation>
<translation id="8971063699422889582">Potrdilo strežnika je poteklo.</translation>
<translation id="8975012916872825179">Vključuje podatke, kot so telefonske številke, e-poštni naslovi in naslovi za pošiljanje</translation>
@@ -1480,24 +1503,24 @@ Dodatne podrobnosti:
<translation id="9035022520814077154">Varnostna napaka</translation>
<translation id="9038649477754266430">Uporaba storitve predvidevanja za hitrejše nalaganje strani</translation>
<translation id="9039213469156557790">Poleg tega so na tej strani druga sredstva, ki niso varna. Ta sredstva lahko med prenosom pregledujejo drugi, morebitni napadalec pa jih lahko spremeni, tako da se spremeni način delovanja strani.</translation>
+<translation id="9044359186343685026">Uporabi Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Skušali ste dostopati do domene <ph name="DOMAIN" />, vendar je strežnik predložil neveljavno potrdilo.</translation>
<translation id="9050666287014529139">Geslo</translation>
<translation id="9065203028668620118">Uredi</translation>
<translation id="9065745800631924235">Iskanje poizvedbe <ph name="TEXT" /> iz zgodovine</translation>
<translation id="9069693763241529744">Blokirala razširitev</translation>
-<translation id="9076283476770535406">Morda vsebuje vsebino za odrasle</translation>
<translation id="9076630408993835509">Tega brskalnika ne upravlja podjetje ali druga organizacija. Dejavnost v tej napravi morda upravljajo zunaj Chroma. <ph name="BEGIN_LINK" />Več o tem<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Vnesti morate več podatkov</translation>
<translation id="9080712759204168376">Povzetek naročila</translation>
<translation id="9089260154716455634">Pravilnik za nedejavnost:</translation>
<translation id="9095388113577226029">Več jezikov …</translation>
+<translation id="9098981495403789647">Skrbnik je v brskalniku omogočil Chromovo funkcijo zaščite pred grožnjami za podjetja. Chromova funkcija zaščite pred grožnjami za podjetja ima dostop do nekaterih vaših podatkov.</translation>
<translation id="9103872766612412690">Spletno mesto <ph name="SITE" /> za zaščito vaših podatkov običajno uporablja šifriranje. Ko se je Chromium tokrat poskusil povezati s spletnim mestom <ph name="SITE" />, je to vrnilo nenavadne in nepravilne poverilnice. Do tega lahko pride, če se napadalec lažno predstavlja za spletno mesto <ph name="SITE" /> ali če je povezavo prekinil zaslon za prijavo v omrežje Wi-Fi. Vaši podatki so še vedno varni, saj je Chromium pred izmenjavo podatkov prekinil povezavo.</translation>
<translation id="9106062320799175032">Dodajanje naslova za izstavitev računa</translation>
<translation id="9114524666733003316">Potrjevanje kartice …</translation>
<translation id="9128870381267983090">Vzpostavi povezavo z omrežjem</translation>
<translation id="9137013805542155359">Pokaži izvirno besedilo</translation>
-<translation id="9137248913990643158">Začnite s prijavo v Chrome, preden začnete uporabljati to aplikacijo.</translation>
<translation id="9141013498910525015">Upravljanje naslovov</translation>
<translation id="9148088599418889305">Izbira načina pošiljanja</translation>
<translation id="9148507642005240123">&amp;Razveljavi urejanje</translation>
diff --git a/chromium/components/strings/components_strings_sr.xtb b/chromium/components/strings/components_strings_sr.xtb
index 12fab902b81..ed68852849a 100644
--- a/chromium/components/strings/components_strings_sr.xtb
+++ b/chromium/components/strings/components_strings_sr.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Додајте име са картице</translation>
<translation id="1089439967362294234">Промена лозинке</translation>
+<translation id="1096545575934602868">Ово поље не сме да има више од <ph name="MAX_ITEMS_LIMIT" /> уноса. Сви додатни уноси ће бити одбачени.</translation>
<translation id="109743633954054152">Управљајте лозинкама у подешавањима Chrome-а</translation>
<translation id="1103523840287552314">Увек преводи <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Ако означите ову опцију, Chrome ће складиштити копију картице на овом уређају ради бржег попуњавања образаца.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Приступите <ph name="BEGIN_LINK" />кешираној копији<ph name="END_LINK" /> странице <ph name="URL" /></translation>
<translation id="1156303062776767266">Прегледате локалну или дељену датотеку</translation>
<translation id="1158211211994409885">Хост <ph name="HOST_NAME" /> је неочекивано прекинуо везу.</translation>
+<translation id="115926840831309955">Проверите CVC и пробајте поново или ажурирајте датум истека</translation>
<translation id="1161325031994447685">поново да се повежете са Wi-Fi мрежом</translation>
<translation id="1165039591588034296">Грешка</translation>
<translation id="1175364870820465910">&amp;Одштампај...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">„Софтвер на вашем рачунару онемогућава Chrome-у да се безбедно повеже на веб“ (само на Windows рачунарима)</translation>
<translation id="1294154142200295408">Варијације командне линије</translation>
<translation id="129553762522093515">Недавно затворено</translation>
+<translation id="1298536327547837046">Скенирање малвера</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Покушајте да обришете колачиће<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Застареле функције</translation>
<translation id="1320233736580025032">Prc1 (коверат)</translation>
<translation id="132301787627749051">Потражите слику у привременој меморији</translation>
<translation id="1323433172918577554">Прикажи више</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google табеле</translation>
<translation id="1527263332363067270">Чека се веза…</translation>
<translation id="1529521330346880926">10x15 (коверат)</translation>
+<translation id="1530707389502320859">Сајт који сте управо пробали да посетите делује лажно. Нападачи понекад имитирају сајтове тако што незнатно и скоро неприметно измене URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Ова страница наводи:</translation>
<translation id="153384715582417236">То је све за сада</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">ОС</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Документ је исувише велики да бисте му додали напомене</translation>
-<translation id="1721312023322545264">Потребна вам је дозвола корисника <ph name="NAME" /> да бисте посетили овај сајт</translation>
<translation id="1721424275792716183">* Поље је обавезно</translation>
<translation id="1727741090716970331">Додајте важећи број картице</translation>
<translation id="1728677426644403582">Прегледате извор веб-странице.</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Веб-сајтови које посећујете и време проведено на њима</translation>
<translation id="1826516787628120939">Провера</translation>
<translation id="1834321415901700177">Овај сајт садржи штетне програме</translation>
+<translation id="1838374766361614909">Обришите претрагу</translation>
<translation id="1839551713262164453">Валидација вредности смерница није успела уз грешке</translation>
<translation id="1842969606798536927">Плати</translation>
<translation id="1871208020102129563">Прокси је подешен да користи фиксне прокси сервере, а не URL адресу .pac скрипте.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Скупи листу</translation>
<translation id="1898423065542865115">Филтрирање</translation>
<translation id="1914326953223720820">Услуга за отпакивање датотека</translation>
+<translation id="1915697529809968049">Желите ли да користите Touch ID уместо CVC-а?</translation>
<translation id="1916770123977586577">Да бисте применили ажурирана подешавања на овом сајту, учитајте страницу поново</translation>
<translation id="1919345977826869612">Огласи</translation>
<translation id="1919367280705858090">Потражите помоћ у вези са одређеном поруком о грешци</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> – обележивачи</translation>
<translation id="1973335181906896915">Грешка при серијализацији</translation>
<translation id="1974060860693918893">Напредне опције</translation>
+<translation id="1974883374937189061">Помозите да побољшамо безбедност Chrome-а тако што ћете слати <ph name="BEGIN_WHITEPAPER_LINK" />URL-ове неких страница које посећујете, ограничене информације о систему и одређени садржај страница<ph name="END_WHITEPAPER_LINK" /> Google-у. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Верзија фирмвера</translation>
<translation id="1981206234434200693">Обришите податке из историје прегледања у Chrome-у</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ и још 1}one{и још #}few{и још #}other{и још #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Унесите важећу годину истека</translation>
<translation id="2212735316055980242">Смернице нису пронађене</translation>
<translation id="2213606439339815911">Преузимање уноса...</translation>
+<translation id="2215727959747642672">Мењање датотека</translation>
<translation id="2218879909401188352">Нападачи који су тренутно на <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> могу да инсталирају опасне апликације које ће вам оштетити уређај, додати нежељене трошкове код мобилног оператера или украсти личне податке. <ph name="BEGIN_LEARN_MORE_LINK" />Сазнајте више<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Нема интернета</translation>
<translation id="2230458221926704099">Поправите везу помоћу <ph name="BEGIN_LINK" />апликације за дијагностику<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Пошаљи одмах</translation>
+<translation id="2248949050832152960">Користи WebAuthn</translation>
<translation id="225207911366869382">Ова вредност је застарела за ове смернице.</translation>
<translation id="2257315177824333709">Жао нам је, тренутно не можемо да сачувамо картицу</translation>
<translation id="2262243747453050782">HTTP грешка</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Неважећа URL адреса претраге.</translation>
<translation id="2482878487686419369">Обавештења</translation>
<translation id="248348093745724435">Смернице за уређаје</translation>
-<translation id="2485387744899240041">Корисничка имена за уређај и прегледач</translation>
<translation id="2491120439723279231">Сертификат сервера садржи грешке.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Рашчлањивач JSON датотека</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Назад</translation>
<translation id="2503184589641749290">Дебитне и припејд картице које се прихватају</translation>
<translation id="2505268675989099013">Заштити налог</translation>
+<translation id="2515335152965840738">ЗАНЕМАРИ</translation>
<translation id="2515629240566999685">да проверите сигнал у својој области</translation>
<translation id="2523886232349826891">Сачувано је само на овом уређају</translation>
<translation id="2524461107774643265">Додајте још информација</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Пошаљи</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Ниједна}=1{1 лозинка (за <ph name="DOMAIN_LIST" />)}=2{2 лозинке (за <ph name="DOMAIN_LIST" />)}one{# лозинка (за <ph name="DOMAIN_LIST" />)}few{# лозинке (за <ph name="DOMAIN_LIST" />)}other{# лозинки (за <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Затворите друге картице или апликације</translation>
-<translation id="267371737713284912">притисните <ph name="MODIFIER_KEY_DESCRIPTION" /> да бисте опозвали</translation>
<translation id="2674170444375937751">Желите ли стварно да избришете ове странице из историје?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Затвори</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Вредност се не подудара са форматом.</translation>
<translation id="2705137772291741111">Сачувана (кеширана) копија овог сајта није могла да се чита.</translation>
<translation id="2709516037105925701">Аутоматско попуњавање</translation>
-<translation id="2712173769900027643">Затражи дозволу</translation>
<translation id="2713444072780614174">Бела</translation>
<translation id="2720342946869265578">У близини</translation>
<translation id="2721148159707890343">Захтев је успео</translation>
<translation id="2728127805433021124">Сертификат сервера је потписан слабим алгоритмом.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />да покренете дијагностику везе<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Ако омогућите ове функције, можете да изгубите податке прегледача
+ или да угрозите сопствену безбедност или приватност. Омогућене функције се примењују
+ на све кориснике овог прегледача.</translation>
<translation id="2735043616039983645">Присутно је више извора са неусаглашеним вредностима за ове смернице!</translation>
<translation id="2738330467931008676">Одаберите адресу преузимања</translation>
<translation id="2740531572673183784">Потврди</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Веза је враћена на почетне вредности.</translation>
<translation id="2788784517760473862">Кредитне картице које се прихватају</translation>
<translation id="2792012897584536778">Администратори овог уређаја су подесили безбедносне сертификате који могу да им омогуће да виде садржај веб-сајтова које посећујете.</translation>
-<translation id="2794233252405721443">Сајт је блокиран</translation>
<translation id="2799020568854403057">Сајт који ћете посетити садржи штетне апликације</translation>
<translation id="2799223571221894425">Поново покрени</translation>
<translation id="2803306138276472711">Google безбедно прегледање је недавно <ph name="BEGIN_LINK" />открило малвер<ph name="END_LINK" /> на <ph name="SITE" />. Веб-сајтови који су обично безбедни се понекад заразе малвером.</translation>
+<translation id="2815364696811431560">НАПУСТИ САЈТ</translation>
<translation id="2824775600643448204">Трака за адресу и претрагу</translation>
<translation id="2826760142808435982">Веза је шифрована и њена аутентичност је потврђена помоћу <ph name="CIPHER" /> и користи <ph name="KX" /> као механизам за размену шифара.</translation>
<translation id="2835170189407361413">Обриши образац</translation>
<translation id="2847118875340931228">Отвори прозор без архивирања</translation>
<translation id="2850739647070081192">Invite (коверат)</translation>
-<translation id="2851634818064021665">Треба вам дозвола да бисте посетили овај сајт</translation>
<translation id="2856444702002559011">Нападачи можда покушавају да украду информације са <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (на пример, лозинке, поруке или кредитне картице). <ph name="BEGIN_LEARN_MORE_LINK" />Сазнајте више<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Желите ли да сачувате картицу?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Ако омогућите ову опцију, Chromium ће складиштити копију картице на овом уређају ради бржег попуњавања образаца.</translation>
<translation id="2985398929374701810">Унесите важећу адресу</translation>
<translation id="2986368408720340940">Овај начин преузимања није доступан. Испробајте неки други начин.</translation>
+<translation id="2987034854559945715">Нема функција које се подударају</translation>
<translation id="2991174974383378012">Дељење са веб-сајтовима</translation>
<translation id="2991571918955627853">Тренутно не можете да посетите <ph name="SITE" /> јер веб-сајт користи HSTS. Грешке и напади на мрежи су обично привремени, па ће ова страница вероватно функционисати касније.</translation>
<translation id="3005723025932146533">Прикажи сачувану копију</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Погрешан тип смерница</translation>
<translation id="3037605927509011580">О, не!</translation>
<translation id="3041612393474885105">Информације о сертификату</translation>
+<translation id="3057676462092457419">Режим DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> још увек није подржан, па је режим подешен на <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (коверат)</translation>
<translation id="3061707000357573562">Услуга крпљења</translation>
<translation id="3064966200440839136">Напустићете режим без архивирања да бисте платили у спољној апликацији. Желите ли да наставите?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на: <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Откажи плаћање</translation>
<translation id="3207960819495026254">Обележено</translation>
+<translation id="3209034400446768650">Страница може да наплаћује</translation>
<translation id="3225919329040284222">Сервер је приказао сертификат који се не подудара са уграђеним очекивањима. Та очекивања су обухваћена за одређене веб-сајтове са јаким безбедносним мерама како би вас заштитила.</translation>
<translation id="3226128629678568754">Притисните дугме Поново учитај да бисте поново послали податке потребне за учитавање странице.</translation>
<translation id="3227137524299004712">Микрофон</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Информације о верзији за уређај и прегледач</translation>
<translation id="323107829343500871">Унесите CVC за картицу <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Увек откривај важан садржај на овом сајту</translation>
-<translation id="3254409185687681395">Обележите ову страницу</translation>
<translation id="3270847123878663523">&amp;Опозови промену редоследа</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Додајте име на картици</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Додајте адресу за обрачун</translation>
<translation id="3324983252691184275">Јаркоцрвена</translation>
<translation id="3338095232262050444">Безбедан</translation>
-<translation id="3345135638360864351">Слање захтева за приступ овом сајту кориснику <ph name="NAME" /> није успело. Пробајте поново.</translation>
<translation id="3355823806454867987">Промени подешавања проксија...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />не чува<ph name="END_EMPHASIS" /> следеће информације:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Сакриј напредно</translation>
<translation id="3467763166455606212">Име власника картице је обавезно</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, тренутно је отворена, притисните картицу, па Enter да бисте прешли на отворену картицу</translation>
-<translation id="3479539252931486093">Да ли је ово било неочекивано? <ph name="BEGIN_LINK" />Обавестите нас<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Не сада</translation>
<translation id="3484560055331845446">Могли бисте да изгубите приступ Google налогу. Chrome препоручује да одмах промените лозинку. Мораћете да се пријавите.</translation>
<translation id="3495081129428749620">Пронађите на страници
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Тренутно не можемо да контактирамо родитеља. Пробај поново.</translation>
<translation id="3512163584740124171">Ове смернице су занемарене јер друге смернице из исте групе смерница имају предност.</translation>
<translation id="3528171143076753409">Сертификат сервера није поуздан.</translation>
<translation id="3528485271872257980">Тамнобраон</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Најмање 1 ставка на синхронизованим уређајима}=1{1 ставка (и још ставки на синхронизованим уређајима)}one{# ставка (и још ставки на синхронизованим уређајима)}few{# ставке (и још ставки на синхронизованим уређајима)}other{# ставки (и још ставки на синхронизованим уређајима)}}</translation>
<translation id="3539171420378717834">Задржи копију ове картице на овом уређају</translation>
-<translation id="3556433843310711081">Менаџер може да га деблокира за вас</translation>
<translation id="3566021033012934673">Веза није приватна</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Уграђена страница на <ph name="SITE" /> наводи:</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Отворите страницу у ноцом прозору без архивирања (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Извештај о отказивању је снимљен <ph name="CRASH_TIME" />, а отпремљен <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Информације о сертификату</translation>
+<translation id="3701427423622901115">Ресетовање је потврђено.</translation>
<translation id="3704162925118123524">Мрежа коју користите ће можда захтевати да посетите страницу за пријављивање.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Учитава се...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Нападачи на <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> могу да вас наведу да урадите нешто опасно, на пример, да инсталирате софтвер или откријете личне податке (попут лозинки, бројева телефона или бројева кредитних картица). <ph name="BEGIN_LEARN_MORE_LINK" />Сазнајте више<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Превођење није успело због грешке сервера.</translation>
<translation id="3759461132968374835">Немате ниједно недавно пријављено отказивање. Отказивања која су се десила док је пријављивање отказивања било онемогућено неће се овде приказати.</translation>
+<translation id="3760561303380396507">Желите ли да користите Windows Hello уместо CVC-а?</translation>
<translation id="3761718714832595332">Сакриј статус</translation>
<translation id="3765032636089507299">Радови на страници Безбедно прегледање су у току.</translation>
<translation id="3778403066972421603">Да ли желите да сачувате ову картицу на Google налогу и на овом уређају?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Величина 16</translation>
<translation id="3797522431967816232">Prc3 (коверат)</translation>
<translation id="3807873520724684969">Блокиран је штетан садржај.</translation>
+<translation id="3808375843007691220">Упозорење: У наставку су експерименталне функције!</translation>
<translation id="3810973564298564668">Промени</translation>
<translation id="382518646247711829">Ако користите прокси сервер...</translation>
<translation id="3828924085048779000">Није дозвољено да поље за приступну фразу буде празно.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Ажурирајте датум и време</translation>
<translation id="3884278016824448484">Неусаглашени идентификатор уређаја</translation>
<translation id="3885155851504623709">Парохија</translation>
-<translation id="3886446263141354045">Захтев за приступ овом сајту је послат кориснику <ph name="NAME" /></translation>
<translation id="3890664840433101773">Додајте имејл</translation>
<translation id="3901925938762663762">Картица је истекла</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Желите ли да користите WebAuthn уместо CVC-а?</translation>
<translation id="3946209740501886391">Увек питај на овом сајту</translation>
<translation id="3949571496842715403">Овај сервер не може да докаже да је <ph name="DOMAIN" />; његов безбедносни сертификат не наводи Алтернативне називе субјекта. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
<translation id="3949601375789751990">Историја прегледања ће се појавити овде</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{None}=1{Са 1 сајта }one{Са # сајта }few{Са # сајта }other{Са # сајтова }}</translation>
<translation id="397105322502079400">Израчунавање...</translation>
<translation id="3973234410852337861">Хост <ph name="HOST_NAME" /> је блокиран</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> је у прегледачу омогућио Chrome заштиту од претњи за предузећа. Chrome заштита од претњи за предузећа има приступ неким вашим подацима.</translation>
<translation id="3987940399970879459">Мање од 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 веб-страница у околини}one{# веб-страница у околини}few{# веб-странице у околини}other{# веб-страница у околини}}</translation>
<translation id="4030383055268325496">&amp;Опозови додавање</translation>
<translation id="4032320456957708163">Прегледачем управља <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Линк који сте отворили води до сајта који обично не посећујете. Можда жели да вас збуни.</translation>
<translation id="4058922952496707368">Кључ „<ph name="SUBKEY" />“: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (коверат)</translation>
<translation id="4067947977115446013">Додајте важећу адресу</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Серијски број уређаја је неважећи</translation>
<translation id="410351446219883937">Аутоплеј</translation>
<translation id="4103763322291513355">Посетите &lt;strong&gt;chrome://policy&lt;/strong&gt; да бисте видели листу URL-ова стављених на црну листу и друге смернице које је наметнуо администратор система.</translation>
+<translation id="4108231218301530806">Следећи пут верификуј ову картицу помоћу дигиталног отиска.</translation>
<translation id="4110652170750985508">Прегледајте уплату</translation>
<translation id="4112140312785995938">Премотај уназад</translation>
<translation id="4116663294526079822">Увек дозволи на овом сајту</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Неисправан потпис за верификацију</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{још <ph name="ITEM_COUNT" /> ставка}one{још <ph name="ITEM_COUNT" /> ставка}few{још <ph name="ITEM_COUNT" /> ставке}other{још <ph name="ITEM_COUNT" /> ставки}}</translation>
+<translation id="4176463684765177261">Онемогућено</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Да бисте следећи пут платили брже, додајте картицу и адресу за обрачун на Google налог.</translation>
<translation id="4196861286325780578">&amp;Понови премештање</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Ресетујте лозинку</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" />-ом управља <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ова картица је сачувана на Google налогу}one{Ове картице су сачуване на Google налогу}few{Ове картице су сачуване на Google налогу}other{Ове картице су сачуване на Google налогу}}</translation>
+<translation id="428847186335018806">Скенирајте датотеке које преузимате или отпремате у Chrome-у.</translation>
<translation id="42981349822642051">Проширите</translation>
<translation id="4302965934281694568">Chou3 (коверат)</translation>
<translation id="4305817255990598646">Пређи</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">разгледница)</translation>
<translation id="443673843213245140">Коришћење проксија је онемогућено, али је наведена експлицитна конфигурација проксија.</translation>
<translation id="445100540951337728">Дебитне картице које се прихватају</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> за сумњиво понашање</translation>
<translation id="4466881336512663640">Промене обрасца се неће сачувати. Желите ли стварно да наставите?</translation>
<translation id="4477350412780666475">Следећа песма</translation>
<translation id="4482953324121162758">Овај сајт неће бити преведен.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Опозови брисање</translation>
<translation id="4597348597567598915">Величина 8</translation>
<translation id="4600854749408232102">C6/C5 (коверат)</translation>
+<translation id="464342062220857295">Функције претраге</translation>
<translation id="4646534391647090355">Одведи ме тамо</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Овај сервер не може да докаже да је <ph name="DOMAIN" />; његов безбедносни сертификат садржи грешке. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (коверат)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Веза је прекинута</translation>
-<translation id="471880041731876836">Немате дозволу да посетите овај сајт</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />да покренете Windows дијагностику мреже<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Поново учитај смернице</translation>
<translation id="4728558894243024398">Платформа</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Уклопи у страницу</translation>
<translation id="4850886885716139402">Приказ</translation>
<translation id="4854362297993841467">Овај начин испоруке није доступан. Испробајте неки други начин.</translation>
-<translation id="4858792381671956233">Питао/ла си родитеље да ли смеш да посетиш овај сајт</translation>
<translation id="4864052566555297930">Безбедносни савет:</translation>
<translation id="4876188919622883022">Поједностављени приказ</translation>
<translation id="4876305945144899064">Нема корисничког имена</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Поново омогући упозорења</translation>
<translation id="4984339528288761049">Prc5 (коверат)</translation>
<translation id="4989163558385430922">Прикажи све</translation>
+<translation id="4989542687859782284">Недоступни</translation>
<translation id="4989809363548539747">Ова додатна компонента није подржана</translation>
+<translation id="4995216769782533993">Потврдите безбедносни кôд да бисте делили детаље картице са овим сајтом</translation>
<translation id="5002932099480077015">Ако је ова опција омогућена, Chrome ће складиштити копију картице на овом уређају ради бржег попуњавања образаца.</translation>
<translation id="5015510746216210676">Назив уређаја:</translation>
<translation id="5017554619425969104">Текст који сте копирали</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-битни)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Верификујте картицу</translation>
<translation id="5135404736266831032">Управљајте адресама...</translation>
<translation id="5138227688689900538">Прикажи мање</translation>
<translation id="5141240743006678641">Шифруј синхронизоване лозинке помоћу Google акредитива</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Клауд</translation>
<translation id="5252000469029418751">C7 (коверат)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Функције које се примењују у целом систему може да подеси само власник: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Упозорење: Ове смернице нису обједињене као што је наведено у смерницама PolicyDictionaryMultipleSourceMergeList зато што нису део смерница за речнике које могу да се обједињују.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Заврши</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Складиштење подешавања смерница није успело</translation>
<translation id="5371425731340848620">Ажурирајте картицу</translation>
<translation id="5377026284221673050">„Сат касни“ или „Сат жури“ или „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;“</translation>
-<translation id="5377179979757081683">Ова страница може да покуша да вас превари, украде личне податке или нашкоди уређају. Будите опрезни када уносите личне податке или отварате преузете датотеке.</translation>
<translation id="5384855140246857529">Да бисте користили картице на свим уређајима, пријавите се и укључите синхронизацију.</translation>
<translation id="5386426401304769735">Ланац сертификата за овај сајт садржи сертификат потписан помоћу алгоритма SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Неважеће</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Понови измену</translation>
+<translation id="5473728911100096288">Ако омогућите ове функције, користићете застареле функције
+ које ће нестати у будућим верзијама.</translation>
<translation id="5478437291406423475">B6/C4 (коверат)</translation>
<translation id="5481076368049295676">Овај садржај ће покушати да инсталира опасан софтвер на уређај који ће украсти или обрисати ваше податке. <ph name="BEGIN_LINK" />Ипак прикажи<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Додајте важећу адресу</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Заштити налог</translation>
<translation id="5571083550517324815">Преузимање са ове адресе није могуће. Изаберите другу адресу.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{Користи се 1}one{Користи се #}few{Користе се #}other{Користи се #}})</translation>
-<translation id="5572851009514199876">Отворите и пријавите се у Chrome да би Chrome могао да провери да ли имате дозволу за приступ овом сајту.</translation>
<translation id="5580958916614886209">Проверите месец истека и пробајте поново</translation>
<translation id="5586446728396275693">Нема сачуваних адреса</translation>
<translation id="5595485650161345191">Измена адресе</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Управљање није подржано</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Овај сајт је можда лажан или служи за превару. Chrome вам препоручује да га одмах напустите.</translation>
<translation id="5610142619324316209">да проверите везу</translation>
<translation id="5610807607761827392">Картицама и адресама можете да управљате у <ph name="BEGIN_LINK" />Подешавањима<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Хост <ph name="HOST_NAME" /> вас је преусмерио превелики број пута.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Тренутни корисник</translation>
<translation id="5728056243719941842">C5 (коверат)</translation>
<translation id="5730040223043577876">Chrome вам препоручује да ресетујете лозинку ако сте је користили на другим сајтовима.</translation>
-<translation id="5732392974455271431">Родитељи могу да га деблокирају за тебе</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Сачувајте картицу на Google налогу}one{Сачувајте картице на Google налогу}few{Сачувајте картице на Google налогу}other{Сачувајте картице на Google налогу}}</translation>
<translation id="5763042198335101085">Унесите важећу имејл адресу</translation>
<translation id="5765072501007116331">Да бисте видели начине и захтеве за испоруку, изаберите адресу</translation>
<translation id="5778550464785688721">Потпуна контрола над MIDI уређајима</translation>
+<translation id="5781136890105823427">Експеримент је омогућен</translation>
<translation id="578305955206182703">Окер</translation>
<translation id="57838592816432529">Искључи звук</translation>
<translation id="5784606427469807560">Дошло је до проблема при потврди картице. Проверите интернет везу и покушајте поново.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Искључено</translation>
<translation id="5863847714970149516">Следећа страница може да покуша да вам нешто наплати</translation>
<translation id="5866257070973731571">Додајте број телефона</translation>
+<translation id="5866898949289125849">Прегледате страницу са алаткама за прогамере</translation>
<translation id="5869405914158311789">Овај сајт није доступан</translation>
<translation id="5869522115854928033">Сачуване лозинке</translation>
<translation id="5887400589839399685">Картица је сачувана</translation>
<translation id="5893752035575986141">Прихватају се кредитне картице.</translation>
+<translation id="5895138241574237353">Покрени поново</translation>
<translation id="5901630391730855834">Жута</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (синхронизовано)</translation>
<translation id="5916664084637901428">Укључено</translation>
+<translation id="59174027418879706">Омогућено</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Желите ли да сачувате картицу на Google налогу?</translation>
<translation id="5922853866070715753">Скоро је готово</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Желите ли да користите картице на свим уређајима?</translation>
<translation id="6059925163896151826">USB уређаји</translation>
+<translation id="6060009363608157444">Режим DnsOverHttps је неважећи.</translation>
<translation id="6080696365213338172">Приступали сте садржају помоћу сертификата који је обезбедио администратор. Администратор може да пресретне податке које обезбедите домену <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">Додајте напомене</translation>
<translation id="610911394827799129">Google налог може да има друге облике историје прегледања на <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1002,13 +1022,12 @@
<translation id="6404511346730675251">Измена обележивача</translation>
<translation id="6406765186087300643">C0 (коверат)</translation>
<translation id="6410264514553301377">Унесите датум истека и CVC за картицу <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Питао/ла си родитеља да ли смеш да посетиш овај сајт</translation>
<translation id="6415778972515849510">Chromium може да вам помогне да заштитите Google налог и промените лозинку.</translation>
-<translation id="6417515091412812850">Није могуће проверити да ли је сертификат опозван.</translation>
<translation id="6431585503458005759">Не чувај</translation>
<translation id="6433490469411711332">Измените контакт информације</translation>
<translation id="6433595998831338502">Хост <ph name="HOST_NAME" /> је одбио повезивање.</translation>
<translation id="6434309073475700221">Одбаци</translation>
+<translation id="6435221585574090192">Делите са администатором податке о безбедносним догађајима које је пријавила Chrome заштита од претњи за предузећа. Они могу да обухватају URL-ове страница, називе датотека и метаподатке датотека, корисничко име за уређај и корисничко име за Chrome.</translation>
<translation id="6440503408713884761">Занемарено</translation>
<translation id="6446163441502663861">Kahu (коверат)</translation>
<translation id="6446608382365791566">Додајте још информација</translation>
@@ -1017,20 +1036,19 @@
<translation id="6465306955648956876">Управљајте лозинкама...</translation>
<translation id="647261751007945333">Смернице за уређај</translation>
<translation id="6476284679642588870">Управљајте начинима плаћања</translation>
-<translation id="6477321094435799029">Chrome је открио неуобичајени кôд на овој страници и блокирао је ради заштите ваших личних података (попут лозинки, бројева телефона или бројева кредитних картица).</translation>
<translation id="6489534406876378309">Покрени отпремање отказивања</translation>
<translation id="6499038740797743453">Желите ли да ресетујете лозинку?</translation>
<translation id="6507833130742554667">Прихватају се кредитне и дебитне картице.</translation>
<translation id="650855688985305916">Да, сачувај</translation>
<translation id="6508722015517270189">Поново покрените Chrome</translation>
<translation id="6517596291481585650">Упозорење: Ове смернице нису обједињене као листа како је наведено у смерницама јер нису листа.</translation>
+<translation id="6518133107902771759">Верификуј</translation>
<translation id="6521745193039995384">Нису активне</translation>
<translation id="6529602333819889595">&amp;Понови брисање</translation>
<translation id="6534179046333460208">Предлози Интернета око нас</translation>
<translation id="6545864417968258051">Bluetooth скенирање</translation>
<translation id="6554795675067793129">Вашим налогом управља <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Понови</translation>
-<translation id="6563469144985748109">Менаџер га још увек није одобрио</translation>
<translation id="6569060085658103619">Прегледате страницу додатка.</translation>
<translation id="6578796323535178455">C2 (коверат)</translation>
<translation id="6579990219486187401">Светлорозе</translation>
@@ -1048,11 +1066,13 @@
<translation id="6643016212128521049">Обриши</translation>
<translation id="6644283850729428850">Ове смернице су застареле.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{None}=1{Са 1 сајта (нећемо вас одјавити са Google налога)}one{Са # сајта (нећемо вас одјавити са Google налога)}few{Са # сајта (нећемо вас одјавити са Google налога)}other{Са # сајтова (нећемо вас одјавити са Google налога)}}</translation>
+<translation id="6652101503459149953">Користи Windows Hello</translation>
<translation id="6657585470893396449">Лозинка</translation>
<translation id="6670613747977017428">Назад на безбедно.</translation>
<translation id="6671697161687535275">Желите ли да уклоните предлог из Chromium-а?</translation>
<translation id="6685834062052613830">Одјавите се и довршите подешавање</translation>
<translation id="6689271823431384964">Chrome вам нуди чување картица на Google налогу зато што сте пријављени. То можете да промените у подешавањима. Име власника картице смо узели са налога.</translation>
+<translation id="6707256370811247129">Скенирајте садржај кеша и датотека које преузимате или отпремате у Chrome-у.</translation>
<translation id="6710213216561001401">Претходно</translation>
<translation id="6710594484020273272">&lt;Унесите термин за претрагу&gt;</translation>
<translation id="671076103358959139">Токен за регистрацију:</translation>
@@ -1060,10 +1080,10 @@
<translation id="6738516213925468394">Подаци су шифровани помоћу <ph name="BEGIN_LINK" />приступне фразе<ph name="END_LINK" /> (<ph name="TIME" />). Унесите је да бисте започели синхронизацију.</translation>
<translation id="674375294223700098">Непозната грешка сертификата сервера.</translation>
<translation id="6744009308914054259">Док чекате на везу, посетите Преузимања и читајте офлајн чланке.</translation>
+<translation id="6747611005629681221">Упозорење: У наставку су застареле функције!</translation>
<translation id="6753269504797312559">Вредност смерница</translation>
<translation id="6757797048963528358">Уређај је прешао у режим спавања.</translation>
<translation id="6768213884286397650">Hagaki (разгледница)</translation>
-<translation id="6778737459546443941">Родитељ га још увек није одобрио</translation>
<translation id="67862343314499040">Љубичаста</translation>
<translation id="6786747875388722282">Додаци</translation>
<translation id="6790428901817661496">Пусти</translation>
@@ -1071,6 +1091,7 @@
<translation id="681021252041861472">Обавезно поље</translation>
<translation id="6810899417690483278">ИД за прилагођавање</translation>
<translation id="6825578344716086703">Покушали сте да посетите <ph name="DOMAIN" />, али је сервер послао сертификат потписан слабим алгоритмом (као што је SHA-1). То значи да су безбедносни акредитиви које је сервер послао можда кривотворени и сервер можда није онај који мислите да јесте (можда комуницирате са нападачем).</translation>
+<translation id="6826370046007623921">Спречавање губитка података</translation>
<translation id="6831043979455480757">Преведи</translation>
<translation id="6839929833149231406">Област</translation>
<translation id="6852204201400771460">Желите ли да поново учитате апликацију?</translation>
@@ -1083,7 +1104,6 @@
<translation id="6891596781022320156">Ниво смерница није подржан.</translation>
<translation id="6895330447102777224">Картица је потврђена</translation>
<translation id="6897140037006041989">Кориснички агент</translation>
-<translation id="6903319715792422884">Побољшајте Безбедно прегледање слањем <ph name="BEGIN_WHITEPAPER_LINK" />системских информација и садржаја страница<ph name="END_WHITEPAPER_LINK" /> Google-у. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Корисник:</translation>
<translation id="6934672428414710184">То је име са вашег Google налога</translation>
<translation id="6944692733090228304">Унели сте лозинку на сајту којим не управља <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Да бисте заштитили налог, не користите лозинку поново у другим апликацијама ни на другим сајтовима.</translation>
@@ -1128,6 +1148,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Светлољубичаста</translation>
<translation id="717330890047184534">Gaia ИД:</translation>
+<translation id="7174545416324379297">Обједињено</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> и још <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Сервер на који идете, <ph name="ORIGIN" />, затражио је
да се безбедносне смернице примене на све захтеве ка њему. Међутим, уместо
@@ -1165,6 +1186,7 @@
<translation id="7320336641823683070">Помоћ при повезивању</translation>
<translation id="733354035281974745">Замена локалног налога на уређају</translation>
<translation id="7334320624316649418">&amp;Понови промену редоследа</translation>
+<translation id="7337706099755338005">Није доступно на вашој платформи.</translation>
<translation id="733923710415886693">Сертификат сервера није откривен помоћу Транспарентности сертификата.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Повезан је:</translation>
@@ -1196,7 +1218,6 @@
<translation id="7440140511386898319">Истражујте док сте офлајн</translation>
<translation id="7441627299479586546">Погрешан субјекат смерница</translation>
<translation id="7442725080345379071">Светлонаранџаста</translation>
-<translation id="7444046173054089907">Овај сајт је блокиран</translation>
<translation id="7445762425076701745">Није могуће у потпуности потврдити идентитет сервера са којим сте повезани. Повезани сте са сервером који користи назив који је важећи само у вашој мрежи, а којем спољни ауторитет за издавање сертификата не може да провери власништво. Будући да неки ауторитети за издавање сертификата упркос томе издају сертификате за ове називе, ни на који начин не можете да будете сигурни да сте повезани са жељеним веб-сајтом, а не са нападачем.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />да сазнате више<ph name="END_LINK" /> о овом проблему.</translation>
<translation id="7455133967321480974">Користи глобалну подразумевану вредност (Блокирај)</translation>
@@ -1218,9 +1239,9 @@
<translation id="7538364083937897561">A2 (коверат)</translation>
<translation id="7542403920425041731">Када будете потврдили, подаци о картици ће бити послати овом сајту.</translation>
<translation id="7542995811387359312">Онемогућено је аутоматско попуњавање кредитне картице зато што овај образац не користи безбедну везу.</translation>
-<translation id="7543525346216957623">Питај родитеља</translation>
<translation id="7548892272833184391">Отклоните грешке при повезивању</translation>
<translation id="7549584377607005141">Ова веб-страница захтева податке које сте унели раније да би се правилно приказала. Можете поново да пошаљете те податке, али ако то урадите, поновићете било коју радњу коју је ова страница претходно обавила.</translation>
+<translation id="7550637293666041147">Корисничко име уређаја и корисничко име за Chrome</translation>
<translation id="7552846755917812628">Испробајте следеће савете:</translation>
<translation id="7554791636758816595">Нова картица</translation>
<translation id="7564049878696755256">Можете да изгубите приступ налогу за <ph name="ORG_NAME" /> или би могло да дође до крађе идентитета. Chrome вам препоручује да одмах промените лозинку.</translation>
@@ -1235,6 +1256,7 @@
<translation id="7610193165460212391">Вредност је изван опсега <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Истиче: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Већ имате податке који су шифровани помоћу друге верзије лозинке за Google налог. Унесите је у наставку.</translation>
+<translation id="7625784245512586808">Chrome заштита од претњи за предузећа</translation>
<translation id="7633909222644580952">Подаци о учинку и извештаји о отказивању</translation>
<translation id="7637571805876720304">Желите ли да уклоните кредитну картицу из Chromium-а?</translation>
<translation id="7638605456503525968">Серијски портови</translation>
@@ -1247,7 +1269,6 @@
<translation id="7668654391829183341">Непознат уређај</translation>
<translation id="7669271284792375604">Нападачи на овом сајту могу да покушају да вас преваре да бисте инсталирали програме који штете доживљају прегледања (на пример, тако што мењају почетну страницу или приказују додатне огласе на сајтовима које посећујете).</translation>
<translation id="7676643023259824263">Потражите текст у привременој меморији, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Платформа и клауд</translation>
<translation id="7681101578153515023">Промените претраживач</translation>
<translation id="7682287625158474539">Испорука</translation>
<translation id="7687186412095877299">Попуњава обрасце за плаћање информацијама о сачуваним начинима плаћања</translation>
@@ -1262,7 +1283,6 @@
<translation id="7723047071702270851">Измените картицу</translation>
<translation id="774634243536837715">Опасан садржај је блокиран.</translation>
<translation id="7752995774971033316">Не управља</translation>
-<translation id="7755287808199759310">Родитељ може да га деблокира за тебе</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Можда је заштитни зид или антивирусни софтвер блокирао везу.</translation>
<translation id="7759163816903619567">Домен за приказ:</translation>
@@ -1306,7 +1326,6 @@
<translation id="8004582292198964060">Прегледач</translation>
<translation id="8009225694047762179">Управљај лозинкама</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Та картица и њена адреса за обрачун ће бити сачуване. Моћи ћете да је користите када сте пријављени на <ph name="USER_EMAIL" />.}one{Те картице и њихове адресе за обрачун ће бити сачуване. Моћи ћете да их користите када сте пријављени на <ph name="USER_EMAIL" />.}few{Те картице и њихове адресе за обрачун ће бити сачуване. Моћи ћете да их користите када сте пријављени на <ph name="USER_EMAIL" />.}other{Те картице и њихове адресе за обрачун ће бити сачуване. Моћи ћете да их користите када сте пријављени на <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Тренутно не можемо да контактирамо родитеље. Пробај поново.</translation>
<translation id="8025119109950072390">Нападачи на овом сајту могу да вас преваре да бисте урадили нешто опасно, на пример, да инсталирате софтвер или откријете личне податке (попут лозинки, бројева телефона или бројева кредитних картица).</translation>
<translation id="8034522405403831421">Језик ове странице је <ph name="SOURCE_LANGUAGE" />. Желите ли да је преведете на <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Перо</translation>
@@ -1317,6 +1336,7 @@
<translation id="8041940743680923270">Користи глобалну подразумевану вредност (Питај)</translation>
<translation id="8042918947222776840">Одаберите начин преузимања</translation>
<translation id="8057711352706143257">Софтвер „<ph name="SOFTWARE_NAME" />“ није правилно конфигурисан. Деинсталирање софтвера „<ph name="SOFTWARE_NAME" />“ обично решава проблем. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Од сада нећете морати да уносите безбедносни кôд картице</translation>
<translation id="8066955247577885446">Жао нам је, дошло је до грешке.</translation>
<translation id="8074253406171541171">10x13 (коверат)</translation>
<translation id="8078141288243656252">Додавање напомене није могуће када је ротиран</translation>
@@ -1347,6 +1367,7 @@
<translation id="8211406090763984747">Веза је безбедна</translation>
<translation id="8218327578424803826">Додељена локација:</translation>
<translation id="8220146938470311105">C7/C6 (коверат)</translation>
+<translation id="8220639454292072926">Извештавање за предузећа</translation>
<translation id="8225771182978767009">Особа која је подесила овај рачунар је одлучила да блокира овај сајт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Отворите страницу на новој картици без архивирања</translation>
@@ -1401,24 +1422,24 @@
<translation id="8508648098325802031">Икона Претрага</translation>
<translation id="8522552481199248698">Chrome може да вам помогне да заштитите Google налог и промените лозинку.</translation>
<translation id="8543181531796978784">Можете да <ph name="BEGIN_ERROR_LINK" />пријавите проблем са откривањем<ph name="END_ERROR_LINK" /> или, ако схватате безбедносне ризике, <ph name="BEGIN_LINK" />посетите овај небезбедан сајт<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Имате питања? Контактирајте особу која вам надгледа профил.</translation>
<translation id="8553075262323480129">Превод није успео јер језик странице није могао да буде утврђен.</translation>
<translation id="8557066899867184262">CVC је на полеђини картице.</translation>
<translation id="8559762987265718583">Није могуће успоставити приватну везу са доменом <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> јер датум и време на уређају (<ph name="DATE_AND_TIME" />) нису тачни.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> сумњиви сајт</translation>
<translation id="8564985650692024650">Chromium вам препоручује да ресетујете лозинку за <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ако сте је користили на другим сајтовима.</translation>
<translation id="8571890674111243710">Превођење странице на <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Додај тел. број
</translation>
-<translation id="859285277496340001">Сертификат не наводи механизам којим се проверава да ли је опозван.</translation>
<translation id="860043288473659153">Име власника картице</translation>
<translation id="861775596732816396">Величина 4</translation>
-<translation id="8620436878122366504">Родитељи га још увек нису одобрили</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Сачувај ову картицу на овом уређају</translation>
<translation id="8626112503828625890">Желите ли да сачувате детаље обрачуна на Google налогу?</translation>
+<translation id="8647750283161643317">Врати све на подразумевано</translation>
<translation id="8663226718884576429">Резиме поруџбине, <ph name="TOTAL_LABEL" />, још детаља</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, одговор, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Доступно</translation>
<translation id="8703575177326907206">Ваша веза са доменом <ph name="DOMAIN" /> није шифрована.</translation>
<translation id="8718314106902482036">Плаћање није довршено</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, предлог за претрагу</translation>
@@ -1429,6 +1450,7 @@
<translation id="8738058698779197622">Да бисте успоставили безбедну везу, сат на уређају мора да буде тачан. То је зато што сертификати које веб-сајтови користе за идентификацију важе само одређени временски период. Пошто сат на вашем уређају није тачан, Chromium не може да верификује ове сертификате.</translation>
<translation id="8740359287975076522">Нисмо успели да пронађемо &lt;abbr id="dnsDefinition"&gt;DNS адресу&lt;/abbr&gt; хоста <ph name="HOST_NAME" />. Покушавамо да утврдимо у чему је проблем.</translation>
<translation id="874846938927089722">Кредитне и припејд картице које се прихватају</translation>
+<translation id="874918643257405732">Обележите ову картицу</translation>
<translation id="8759274551635299824">Ова картица је истекла</translation>
<translation id="8761567432415473239">Google безбедно прегледање је недавно <ph name="BEGIN_LINK" />открило штетне програме<ph name="END_LINK" /> на <ph name="SITE" />.</translation>
<translation id="8763927697961133303">USB уређај</translation>
@@ -1458,6 +1480,7 @@
<translation id="8938939909778640821">Прихватају се кредитне и припејд картице</translation>
<translation id="8943282376843390568">Јаркозелена</translation>
<translation id="8957210676456822347">Овлашћење на улазном порталу</translation>
+<translation id="8962950042226115166">Сумњиви сајт</translation>
<translation id="8968766641738584599">Сачувај картицу</translation>
<translation id="8971063699422889582">Сертификат сервера је истекао.</translation>
<translation id="8975012916872825179">Обухвата информације попут бројева телефона, имејл адреса и адреса за испоруку</translation>
@@ -1480,24 +1503,24 @@
<translation id="9035022520814077154">Безбедносна грешка</translation>
<translation id="9038649477754266430">Користите услугу предвиђања да бисте брже учитавали странице</translation>
<translation id="9039213469156557790">Поред тога, ова страница садржи и друге ресурсе који нису безбедни. Ове ресурсе могу да виде и други док су у пролазу и нападач може да их измени како би променио понашање странице.</translation>
+<translation id="9044359186343685026">Користи Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Покушали сте да дођете до домена <ph name="DOMAIN" />, али сервер је послао неважећи сертификат.</translation>
<translation id="9050666287014529139">Приступна фраза</translation>
<translation id="9065203028668620118">Измени</translation>
<translation id="9065745800631924235">Претрага <ph name="TEXT" /> из историје</translation>
<translation id="9069693763241529744">Блокира додатак</translation>
-<translation id="9076283476770535406">Можда обухвата садржај за одрасле</translation>
<translation id="9076630408993835509">Овим прегледачем не управља компанија или нека друга организација. Активностима на овом уређају се можда управља ван Chrome-а. <ph name="BEGIN_LINK" />Сазнајте више<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Потребно је више информација</translation>
<translation id="9080712759204168376">Резиме поруџбине</translation>
<translation id="9089260154716455634">Смернице са временским распоредом:</translation>
<translation id="9095388113577226029">Још језика...</translation>
+<translation id="9098981495403789647">Администратор је у прегледачу омогућио Chrome заштиту од претњи за предузећа. Chrome заштита од претњи за предузећа има приступ неким вашим подацима.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> обично користи шифровање да би заштитио информације. Када је Chromium овог пута покушао да се повеже са <ph name="SITE" />, веб-сајт је вратио необичне и нетачне акредитиве. Или нападач покушава да се представи као <ph name="SITE" /> или је екран за Wi-Fi пријављивање прекинуо везу. Информације су и даље безбедне зато што је Chromium прекинуо везу пре него што су размењени било какви подаци.</translation>
<translation id="9106062320799175032">Додајте адресу за обрачун</translation>
<translation id="9114524666733003316">Картица се потврђује...</translation>
<translation id="9128870381267983090">Повезивање са мрежом</translation>
<translation id="9137013805542155359">Прикажи оригинал</translation>
-<translation id="9137248913990643158">Пријавите се у Chrome пре коришћења ове апликације.</translation>
<translation id="9141013498910525015">Управљајте адресама</translation>
<translation id="9148088599418889305">Одаберите начин испоруке</translation>
<translation id="9148507642005240123">&amp;Опозови измену</translation>
diff --git a/chromium/components/strings/components_strings_sv.xtb b/chromium/components/strings/components_strings_sv.xtb
index 478b8d603be..4dc6849abe4 100644
--- a/chromium/components/strings/components_strings_sv.xtb
+++ b/chromium/components/strings/components_strings_sv.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Lägg till namnet på kortet</translation>
<translation id="1089439967362294234">Ändra lösenordet</translation>
+<translation id="1096545575934602868">Fältet får ha högst <ph name="MAX_ITEMS_LIMIT" /> poster. Alla poster utöver detta antal ignoreras.</translation>
<translation id="109743633954054152">Hantera lösenord i Chrome-inställningarna</translation>
<translation id="1103523840287552314">Översätt alltid <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Om alternativet är markerat sparas en kopia av kortet på enheten så att det går snabbare att fylla i formulär.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Öppna en <ph name="BEGIN_LINK" />cachad kopia<ph name="END_LINK" /> av <ph name="URL" /></translation>
<translation id="1156303062776767266">Detta är en lokal eller delad fil</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> stängde oväntat ner anslutningen.</translation>
+<translation id="115926840831309955">Kontrollera CVC-koden och försök igen eller uppdatera sista giltighetsdatum</translation>
<translation id="1161325031994447685">återansluta till Wi-Fi</translation>
<translation id="1165039591588034296">Fel</translation>
<translation id="1175364870820465910">Skriv &amp;ut...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">Programvara på datorn förhindrar att Chrome ansluter till internet på ett säkert sätt (endast Windows-datorer)</translation>
<translation id="1294154142200295408">Varianter på kommandoraden</translation>
<translation id="129553762522093515">Nyligen stängda</translation>
+<translation id="1298536327547837046">Genomsökning efter skadlig programvara</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Testa att rensa cookies<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Utfasade funktioner</translation>
<translation id="1320233736580025032">Prc1 (kuvert)</translation>
<translation id="132301787627749051">Sök efter bilden i Urklipp</translation>
<translation id="1323433172918577554">Visa fler</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Kalkylark</translation>
<translation id="1527263332363067270">Väntar på anslutning …</translation>
<translation id="1529521330346880926">10x15 (kuvert)</translation>
+<translation id="1530707389502320859">Webbplatsen du försöker öppna ser inte ut att vara äkta. Ibland försöker hackare efterlikna webbplatser genom att göra små, svårupptäckta ändringar i webbadressen.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">På den här sidan står det</translation>
<translation id="153384715582417236">Det var allt för den här gången</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Det går inte att annotera det här dokumentet eftersom det är för stort</translation>
-<translation id="1721312023322545264">Du behöver tillstånd från <ph name="NAME" /> om du vill besöka den här webbplatsen</translation>
<translation id="1721424275792716183">* Fältet är obligatoriskt</translation>
<translation id="1727741090716970331">Lägg till ett giltigt kortnummer</translation>
<translation id="1728677426644403582">Du visar källkoden till en webbsida</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">De webbplatser du besöker och hur länge du är där</translation>
<translation id="1826516787628120939">Kontrollerar</translation>
<translation id="1834321415901700177">Den här webbplatsen innehåller skadliga program</translation>
+<translation id="1838374766361614909">Rensa sökning</translation>
<translation id="1839551713262164453">Valideringen av principvärdena har misslyckats med fel</translation>
<translation id="1842969606798536927">Betala</translation>
<translation id="1871208020102129563">Proxyn är inställd på att använda fasta proxyservrar, inte en webbadress med PAC-skript.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Komprimera lista</translation>
<translation id="1898423065542865115">Filtrering</translation>
<translation id="1914326953223720820">Uppackningstjänst</translation>
+<translation id="1915697529809968049">Vill du använda Touch ID i stället för CVC?</translation>
<translation id="1916770123977586577">Läs in sidan igen för att tillämpa dina uppdaterade inställningar för webbplatsen</translation>
<translation id="1919345977826869612">Annonser</translation>
<translation id="1919367280705858090">Få hjälp med ett specifikt felmeddelande</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Bokmärken på <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Serieproduktionsfel</translation>
<translation id="1974060860693918893">Avancerat</translation>
+<translation id="1974883374937189061">Hjälp oss att göra Chrome säkrare genom att skicka <ph name="BEGIN_WHITEPAPER_LINK" />webbadresser till vissa sidor som du besöker, vissa systemuppgifter och visst sidinnehåll<ph name="END_WHITEPAPER_LINK" /> till Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Firmwareversion</translation>
<translation id="1981206234434200693">Rensa webbhistoriken i Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{och 1 till}other{och # till}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Ange ett giltigt utgångsår</translation>
<translation id="2212735316055980242">Policyn hittades inte</translation>
<translation id="2213606439339815911">Hämtar poster …</translation>
+<translation id="2215727959747642672">Filredigering</translation>
<translation id="2218879909401188352">Angripare på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> skulle kunna installera farliga appar som skadar enheten, lägger till dolda avgifter på din mobilfaktura eller stjäl personliga uppgifter. <ph name="BEGIN_LEARN_MORE_LINK" />Läs mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Inget internet</translation>
<translation id="2230458221926704099">Åtgärda anslutningsproblemet med hjälp av <ph name="BEGIN_LINK" />diagnostiseringsappen<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Skicka nu</translation>
+<translation id="2248949050832152960">Använd WebAuthn</translation>
<translation id="225207911366869382">Värdet är inte längre giltigt för policyn.</translation>
<translation id="2257315177824333709">Det går tyvärr inte att spara kortet just nu</translation>
<translation id="2262243747453050782">HTTP-fel</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Ogiltig sökadress.</translation>
<translation id="2482878487686419369">Aviseringar</translation>
<translation id="248348093745724435">Datorprinciper</translation>
-<translation id="2485387744899240041">Användarnamn för din enhet och webbläsare</translation>
<translation id="2491120439723279231">Servercertifikatet innehåller fel.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON-analysator</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Föregående</translation>
<translation id="2503184589641749290">Godkända betalkort och förbetalda kort</translation>
<translation id="2505268675989099013">Skydda kontot</translation>
+<translation id="2515335152965840738">IGNORERA</translation>
<translation id="2515629240566999685">kontrollera mottagningen i området</translation>
<translation id="2523886232349826891">Endast sparat på den här enheten</translation>
<translation id="2524461107774643265">Lägg till mer information</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Skicka</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Inga}=1{1 lösenord (för <ph name="DOMAIN_LIST" />)}=2{2 lösenord (för <ph name="DOMAIN_LIST" />)}other{# lösenord (för <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Stäng andra flikar eller appar</translation>
-<translation id="267371737713284912">tryck på <ph name="MODIFIER_KEY_DESCRIPTION" /> för att ångra</translation>
<translation id="2674170444375937751">Vill du ta bort de här sidorna från historiken?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Lämna</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Värdet matchar inte formatet.</translation>
<translation id="2705137772291741111">Det gick inte att läsa den sparade (cachelagrade) kopian av webbplatsen.</translation>
<translation id="2709516037105925701">Autofyll</translation>
-<translation id="2712173769900027643">Begär behörighet</translation>
<translation id="2713444072780614174">Vit</translation>
<translation id="2720342946869265578">I närheten</translation>
<translation id="2721148159707890343">Begäran genomfördes</translation>
<translation id="2728127805433021124">Serverns certifikat är signerat med en svag signaturalgoritm.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />att köra anslutningsdiagnostik<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Om du aktiverar dessa funktioner kan du förlora webbinformation.
+ Detta kan även utgöra en säkerhetsrisk eller äventyra din sekretess. De aktiverade funktionerna gäller för alla
+ användare av webbläsaren.</translation>
<translation id="2735043616039983645">Den här principen har flera källor med olika värden.</translation>
<translation id="2738330467931008676">Välj hämtningsadress</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Anslutningen återställdes.</translation>
<translation id="2788784517760473862">Godkända kreditkort</translation>
<translation id="2792012897584536778">Den här enhetens administratör har konfigurerat säkerhetscertifikat som kan tillåta den att se innehållet på webbplatser du besöker.</translation>
-<translation id="2794233252405721443">Webbplatsen har blockerats</translation>
<translation id="2799020568854403057">Det finns skadliga appar på webbplatsen du är på väg till</translation>
<translation id="2799223571221894425">Starta om</translation>
<translation id="2803306138276472711">Google Säker webbsökning upptäckte nyligen <ph name="BEGIN_LINK" />skadlig programvara<ph name="END_LINK" /> på <ph name="SITE" />. Ibland förekommer det skadlig programvara på webbplatser som vanligtvis är säkra.</translation>
+<translation id="2815364696811431560">LÄMNA WEBBPLATSEN</translation>
<translation id="2824775600643448204">Adress- och sökfält</translation>
<translation id="2826760142808435982">Anslutningen är krypterad och verifieras med <ph name="CIPHER" /> och använder <ph name="KX" /> som nyckelutbytesmekanism.</translation>
<translation id="2835170189407361413">Rensa formuläret</translation>
<translation id="2847118875340931228">Öppna ett inkognitofönster</translation>
<translation id="2850739647070081192">Invite (kuvert)</translation>
-<translation id="2851634818064021665">Du behöver tillstånd att besöka den här webbplatsen</translation>
<translation id="2856444702002559011">En angripare kan försöka stjäla dina uppgifter från <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (t.ex. lösenord, meddelanden eller kreditkortsuppgifter). <ph name="BEGIN_LEARN_MORE_LINK" />Läs mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Vill du spara kortet?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Om alternativet är aktiverat sparar Chromium en kopia av kortet på enheten så att det går snabbare att fylla i formulär.</translation>
<translation id="2985398929374701810">Ange en giltig adress</translation>
<translation id="2986368408720340940">Det här alternativet för utlämning är inte tillgängligt. Testa ett annat alternativ.</translation>
+<translation id="2987034854559945715">Det finns inga matchande funktioner</translation>
<translation id="2991174974383378012">Dela med webbplatsen</translation>
<translation id="2991571918955627853">Du kan inte besöka <ph name="SITE" /> just nu eftersom webbplatsen använder HSTS. Nätverksfel och attacker är ofta tillfälliga, så sidan kommer förmodligen att fungera senare.</translation>
<translation id="3005723025932146533">Visa sparad kopia</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Felaktig policytyp</translation>
<translation id="3037605927509011580">Oj, ett fel har uppstått!</translation>
<translation id="3041612393474885105">Certifikatinformation</translation>
+<translation id="3057676462092457419">Läget <ph name="SECURE_DNS_MODE_SECURE" /> stöds inte ännu för DnsOverHttps. Inställningen <ph name="SECURE_DNS_MODE_OFF" /> används i stället.</translation>
<translation id="3060227939791841287">C9 (kuvert)</translation>
<translation id="3061707000357573562">Tjänst för programkorrigering</translation>
<translation id="3064966200440839136">Om du betalar i ett externt program sker inte det i inkognitoläge. Vill du fortsätta?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> på <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Avbryt betalningen</translation>
<translation id="3207960819495026254">Bokmärkt</translation>
+<translation id="3209034400446768650">Sidan kan vara avgiftsbelagd</translation>
<translation id="3225919329040284222">Ett certifikat som inte överensstämmer med inbyggda förväntningar presenterades på servern. Förväntningarna gäller för webbplatser med hög säkerhet för att skydda dig.</translation>
<translation id="3226128629678568754">Om du på nytt vill skicka datan som behövs för att läsa in sidan trycker du på knappen Läs in igen.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Versionsinformation om enhet och webbläsare</translation>
<translation id="323107829343500871">Ange CVC-koden för <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Upptäck alltid viktigt innehåll på den här webbplatsen</translation>
-<translation id="3254409185687681395">Bokmärk sidan</translation>
<translation id="3270847123878663523">&amp;Ångra Ändra ordning</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Lägg till namnet på kortet</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Lägg till faktureringsadress</translation>
<translation id="3324983252691184275">Karmosinröd</translation>
<translation id="3338095232262050444">Säker</translation>
-<translation id="3345135638360864351">Det gick inte att skicka begäran om åtkomst till den här webbplatsen till <ph name="NAME" />. Försök igen.</translation>
<translation id="3355823806454867987">Ändra proxyinställningar...</translation>
<translation id="3361596688432910856">Följande information <ph name="BEGIN_EMPHASIS" />sparas inte<ph name="END_EMPHASIS" /> i Chrome:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Dölja avancerade uppgifter</translation>
<translation id="3467763166455606212">Kortinnehavarens namn måste anges</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, öppen nu, tryck på Tabb och sedan Retur för att byta till den öppna fliken</translation>
-<translation id="3479539252931486093">Var det här oväntat? <ph name="BEGIN_LINK" />Meddela oss<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Inte nu</translation>
<translation id="3484560055331845446">Du kan förlora tillgången till Google-kontot. Du rekommenderas att ändra lösenordet nu. Du blir uppmanad att logga in.</translation>
<translation id="3495081129428749620">Hitta på sidan
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Vi kunde inte nå din förälder just nu. Försök igen.</translation>
<translation id="3512163584740124171">Den här principen ignoreras eftersom en annan princip i samma principgrupp har högre prioritet.</translation>
<translation id="3528171143076753409">Servercertifikatet är inte tillförlitligt.</translation>
<translation id="3528485271872257980">Mörkbrun</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Minst 1 objekt på synkroniserade enheter}=1{1 objekt (och fler på synkroniserade enheter)}other{# objekt (och fler på synkroniserade enheter)}}</translation>
<translation id="3539171420378717834">Spara en kopia av kortet på enheten</translation>
-<translation id="3556433843310711081">En ansvarig kan ta bort blockeringen</translation>
<translation id="3566021033012934673">Anslutningen är inte privat</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">På en inbäddad sida på <ph name="SITE" /> står det</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Öppna sidan i ett nytt inkognitofönster (Ctrl-Skift-N)</translation>
<translation id="3679803492151881375">Kraschrapporten skapades den <ph name="CRASH_TIME" /> och laddades upp den <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Certifikatinformation</translation>
+<translation id="3701427423622901115">Återställning bekräftad.</translation>
<translation id="3704162925118123524">Nätverket du använder kanske kräver att du besöker dess inloggningssida.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Läser in...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Angripare på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan försöka lura dig att göra något riskfyllt, som att installera programvara eller avslöja personliga uppgifter (t.ex. lösenord, telefonnummer eller kreditkortsuppgifter). <ph name="BEGIN_LEARN_MORE_LINK" />Läs mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Det gick inte att översätta på grund av ett serverfel.</translation>
<translation id="3759461132968374835">Inga krascher har rapporterats nyligen. Krascher som uppstod när kraschrapporteringen var inaktiverad visas inte här.</translation>
+<translation id="3760561303380396507">Vill du använda Windows Hello i stället för CVC?</translation>
<translation id="3761718714832595332">Dölj status</translation>
<translation id="3765032636089507299">Sidan Säker webbsökning är under utveckling</translation>
<translation id="3778403066972421603">Vill du spara det här kortet i Google-kontot och på den här enheten?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Storlek 16</translation>
<translation id="3797522431967816232">Prc3 (kuvert)</translation>
<translation id="3807873520724684969">Skadligt innehåll har blockerats.</translation>
+<translation id="3808375843007691220">Varning! Funktionerna är experimentella.</translation>
<translation id="3810973564298564668">Hantera</translation>
<translation id="382518646247711829">Om du använder en proxyserver ...</translation>
<translation id="3828924085048779000">Lösenfrasen får inte vara tom.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Uppdatera datum och tid</translation>
<translation id="3884278016824448484">Motstridiga enhetsidentifierare</translation>
<translation id="3885155851504623709">Församling</translation>
-<translation id="3886446263141354045">Din begäran om att få tillgång till denna webbplats har skickats till <ph name="NAME" /></translation>
<translation id="3890664840433101773">Lägg till e-post</translation>
<translation id="3901925938762663762">Kortet gäller inte längre</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Vill du använda WebAuthn i stället för CVC?</translation>
<translation id="3946209740501886391">Fråga alltid på den här webbplatsen</translation>
<translation id="3949571496842715403">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom inga alternativa namn på certifikatobjektet anges i säkerhetscertifikatet. Detta kan bero på en felaktig konfigurering eller att en angripare manipulerat anslutningen.</translation>
<translation id="3949601375789751990">Webbhistoriken visas här</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Ingen}=1{Från 1 webbplats }other{Från # webbplatser }}</translation>
<translation id="397105322502079400">Beräknar ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> har blockerats</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> har aktiverat skydd mot hot i Chrome Enterprise i webbläsaren. Skyddet mot hot i Chrome Enterprise har tillgång till en del av din data.</translation>
<translation id="3987940399970879459">Mindre än 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 webbsida i närheten}other{# webbsidor i närheten}}</translation>
<translation id="4030383055268325496">&amp;Ångra Lägg till</translation>
<translation id="4032320456957708163">Din webbläsare hanteras av <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Länken du öppnade leder till en webbplats som du inte brukar besöka. Det kan vara ett försök att lura dig.</translation>
<translation id="4058922952496707368">Nyckel <ph name="SUBKEY" />: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (kuvert)</translation>
<translation id="4067947977115446013">Lägg till giltig adress</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Enhetens serienummer är ogiltigt</translation>
<translation id="410351446219883937">Automatisk uppspelning</translation>
<translation id="4103763322291513355">Besök &lt;strong&gt;chrome://policy&lt;/strong&gt; om du vill visa listan med webbadresser som inte är godkända och andra policyer som angetts av systemadministratören.</translation>
+<translation id="4108231218301530806">Verifiera det här kortet med hjälp av fingeravtryck nästa gång.</translation>
<translation id="4110652170750985508">Granska betalningen</translation>
<translation id="4112140312785995938">Sök bakåt</translation>
<translation id="4116663294526079822">Tillåt alltid på den här webbplatsen</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Felaktig verifieringssignatur</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> objekt till}other{<ph name="ITEM_COUNT" /> objekt till}}</translation>
+<translation id="4176463684765177261">Inaktiverad</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Lägg till kortet och faktureringsadressen i Google-kontot så går det snabbare att betala nästa gång.</translation>
<translation id="4196861286325780578">&amp;Gör om Flytta</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Återställ lösenord</translation>
<translation id="4279811152705618813">Din <ph name="DEVICE_TYPE" /> hanteras av <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Det här kortet har sparats i ditt Google-konto}other{De här korten har sparats i ditt Google-konto}}</translation>
+<translation id="428847186335018806">Genomsök filer som du laddar ned eller laddar upp i Chrome.</translation>
<translation id="42981349822642051">Expandera</translation>
<translation id="4302965934281694568">Chou3 (kuvert)</translation>
<translation id="4305817255990598646">Byt</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">vykort)</translation>
<translation id="443673843213245140">Användning av proxy är inaktiverad men en explicit proxykonfiguration har angetts.</translation>
<translation id="445100540951337728">Godkända betalkort</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> Misstänkt aktivitet</translation>
<translation id="4466881336512663640">Ändringar i formuläret ändras inte. Vill du fortsätta?</translation>
<translation id="4477350412780666475">Nästa spår</translation>
<translation id="4482953324121162758">Den här webbplatsen översätts inte.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Ångra Ta bort</translation>
<translation id="4597348597567598915">Storlek 8</translation>
<translation id="4600854749408232102">C6/C5 (kuvert)</translation>
+<translation id="464342062220857295">Sökfunktioner</translation>
<translation id="4646534391647090355">Gå dit nu</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom dess säkerhetscertifikat innehåller fel. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (kuvert)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Anslutningen avbröts</translation>
-<translation id="471880041731876836">Du har inte behörighet att besöka den här webbplatsen.</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" /> köra nätverksdiagnostik för Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Läs in policyer på nytt</translation>
<translation id="4728558894243024398">Plattform</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Anpassa till sida</translation>
<translation id="4850886885716139402">Visa</translation>
<translation id="4854362297993841467">Det här leveranssättet är inte tillgängligt. Testa ett annat alternativ.</translation>
-<translation id="4858792381671956233">Du har frågat dina föräldrar om lov att besöka den här webbplatsen.</translation>
<translation id="4864052566555297930">Säkerhetstips:</translation>
<translation id="4876188919622883022">Förenklad visning</translation>
<translation id="4876305945144899064">Inget användarnamn</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Aktivera varningar igen</translation>
<translation id="4984339528288761049">Prc5 (kuvert)</translation>
<translation id="4989163558385430922">Visa alla</translation>
+<translation id="4989542687859782284">Inte tillgänglig</translation>
<translation id="4989809363548539747">Det här pluginprogrammet stöds inte</translation>
+<translation id="4995216769782533993">Ange säkerhetskoden om du vill dela dina kortuppgifter med den här webbplatsen</translation>
<translation id="5002932099480077015">Om alternativet är aktiverat sparar Chrome en kopia av kortet på enheten så att det går snabbare att fylla i formulär.</translation>
<translation id="5015510746216210676">Datornamn:</translation>
<translation id="5017554619425969104">Texten som du kopierade</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bitar)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Verifiera kortet</translation>
<translation id="5135404736266831032">Hantera adresser …</translation>
<translation id="5138227688689900538">Visa färre</translation>
<translation id="5141240743006678641">Kryptera synkroniserade lösenord med dina inloggningsuppgifter för Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Moln</translation>
<translation id="5252000469029418751">C7 (kuvert)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Funktioner som gäller hela systemet kan endast ställas in av ägaren: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Varning: Den här principen kombinerades inte enligt specifikationen i principen PolicyDictionaryMultipleSourceMergeList eftersom den inte ingår i de ordboksprinciper som kan kombineras.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Avsluta</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Det gick inte att spara policyinställningarna</translation>
<translation id="5371425731340848620">Uppdatera kortet</translation>
<translation id="5377026284221673050">Klockan går efter, Klockan går före eller &lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;</translation>
-<translation id="5377179979757081683">Den här sidan kan försöka lura dig, stjäla personliga uppgifter eller skada din enhet. Var försiktig när du anger personliga uppgifter eller öppnar nedladdade filer.</translation>
<translation id="5384855140246857529">Logga in och aktivera synkronisering så kan du använda korten på alla enheter.</translation>
<translation id="5386426401304769735">Certifikatkedjan för den här webbplatsen innehåller ett certifikat som signerades med SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Ogiltigt</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> och <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> till}other{<ph name="CONTACT_PREVIEW" /> och <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> till}}</translation>
<translation id="5470861586879999274">&amp;Gör om Redigera</translation>
+<translation id="5473728911100096288">När du aktiverar funktionerna använder du utfasade funktioner
+ som inte kommer att finnas i framtida versioner.</translation>
<translation id="5478437291406423475">B6/C4 (kuvert)</translation>
<translation id="5481076368049295676">Sidan kan ha till syfte att installera farlig programvara som stjäl eller raderar information på enheten. <ph name="BEGIN_LINK" />Visa ändå<ph name="END_LINK" />.</translation>
<translation id="54817484435770891">Lägg till giltig adress</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Skydda kontot</translation>
<translation id="5571083550517324815">Utlämning erbjuds inte på den här adressen. Välj en annan adress.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 används}other{# används}})</translation>
-<translation id="5572851009514199876">Logga in på Chrome så att Chrome kan kontrollera om du har tillgång till den här webbplatsen.</translation>
<translation id="5580958916614886209">Kontrollera utgångsmånad och försök igen</translation>
<translation id="5586446728396275693">Inga sparade adresser</translation>
<translation id="5595485650161345191">Redigera adress</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Hantering stöds inte</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Den här webbplatsen kan vara falsk eller bedräglig. Chrome rekommenderar att du lämnar den nu.</translation>
<translation id="5610142619324316209">kontrollera anslutningen</translation>
<translation id="5610807607761827392">Du hanterar kort och adresser under <ph name="BEGIN_LINK" />Inställningar<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> omdirigerade dig för många gånger.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Aktuell användare</translation>
<translation id="5728056243719941842">C5 (kuvert)</translation>
<translation id="5730040223043577876">Du rekommenderas att återställa lösenordet om du har återanvänt det på andra webbplatser.</translation>
-<translation id="5732392974455271431">Dina föräldrar kan ta bort blockeringen</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Spara kortet i Google-kontot}other{Spara korten i Google-kontot}}</translation>
<translation id="5763042198335101085">Ange en giltig e-postadress</translation>
<translation id="5765072501007116331">Välj en adress för att visa leveranssätt och krav</translation>
<translation id="5778550464785688721">MIDI-enheter – fullständig kontroll</translation>
+<translation id="5781136890105823427">Ett experiment har aktiverats</translation>
<translation id="578305955206182703">Bärnstensfärgad</translation>
<translation id="57838592816432529">Stäng av ljudet</translation>
<translation id="5784606427469807560">Det gick inte att bekräfta kortet. Kontrollera internetanslutningen och försök igen.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Av</translation>
<translation id="5863847714970149516">Sidan du är på väg till kan försöka debitera dig</translation>
<translation id="5866257070973731571">Ange telefonnummer</translation>
+<translation id="5866898949289125849">Du visar en sida för utvecklarverktyg</translation>
<translation id="5869405914158311789">Webbplatsen kan inte nås</translation>
<translation id="5869522115854928033">Sparade lösenord</translation>
<translation id="5887400589839399685">Kortet har sparats</translation>
<translation id="5893752035575986141">Kreditkort får användas.</translation>
+<translation id="5895138241574237353">Starta om</translation>
<translation id="5901630391730855834">Gul</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkroniserade)</translation>
<translation id="5916664084637901428">På</translation>
+<translation id="59174027418879706">Aktiverad</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Vill du spara kortet i Google-kontot?</translation>
<translation id="5922853866070715753">Nästan klart</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Vill du använda dina kort på alla enheter?</translation>
<translation id="6059925163896151826">USB-enheter</translation>
+<translation id="6060009363608157444">Ogiltigt läge för DnsOverHttps.</translation>
<translation id="6080696365213338172">Du har visat innehåll med hjälp av ett certifikat från en administratör. Det innebär att data som du har angett på <ph name="DOMAIN" /> även kan visas av administratören.</translation>
<translation id="6094273045989040137">Annotera</translation>
<translation id="610911394827799129">Det kan finnas andra former av webbhistorik i Google-kontot på <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Redigera bokmärke</translation>
<translation id="6406765186087300643">C0 (kuvert)</translation>
<translation id="6410264514553301377">Ange utgångsdatum och CVC-kod för <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Du har frågat en förälder om lov att besöka den här webbplatsen.</translation>
<translation id="6415778972515849510">Du kan skydda Google-kontot genom att byta lösenord.</translation>
-<translation id="6417515091412812850">Det gick inte att kontrollera om certifikatet har återkallats.</translation>
<translation id="6431585503458005759">Spara inte</translation>
<translation id="6433490469411711332">Redigera kontaktuppgifter</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> avvisade anslutningen.</translation>
<translation id="6434309073475700221">Kasta</translation>
+<translation id="6435221585574090192">Dela data om säkerhetshändelser som flaggats av skyddet mot hot i Chrome Enterprise med administratören. Det kan t.ex. vara webbadresser, filnamn och metadata om filer, ditt användarnamn på enheten och ditt användarnamn i Chrome.</translation>
<translation id="6440503408713884761">Ignoreras</translation>
<translation id="6446163441502663861">Kahu (kuvert)</translation>
<translation id="6446608382365791566">Lägg till mer information</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Hantera lösenord …</translation>
<translation id="647261751007945333">Enhetspolicyer</translation>
<translation id="6476284679642588870">Hantera betalningsmetoder</translation>
-<translation id="6477321094435799029">Chrome har identifierat ovanlig kod på sidan och blockerat den för att skydda dina personliga uppgifter (som lösenord, telefonnummer och kreditkortsuppgifter).</translation>
<translation id="6489534406876378309">Börja överföra information om krascher</translation>
<translation id="6499038740797743453">Vill du återställa lösenordet?</translation>
<translation id="6507833130742554667">Kreditkort och betalkort får användas.</translation>
<translation id="650855688985305916">Ja, spara</translation>
<translation id="6508722015517270189">Starta om Chrome</translation>
<translation id="6517596291481585650">Varning: Den här principen kombinerades inte som en lista enligt principens specifikation eftersom den inte är en lista.</translation>
+<translation id="6518133107902771759">Verifiera</translation>
<translation id="6521745193039995384">Inte aktiv</translation>
<translation id="6529602333819889595">&amp;Gör om Ta bort</translation>
<translation id="6534179046333460208">Förslag från Physical Web</translation>
<translation id="6545864417968258051">Bluetooth-sökning</translation>
<translation id="6554795675067793129">Kontot hanteras av <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Upprepa</translation>
-<translation id="6563469144985748109">Den ansvarige har inte godkänt den ännu</translation>
<translation id="6569060085658103619">Du visar en tilläggssida</translation>
<translation id="6578796323535178455">C2 (kuvert)</translation>
<translation id="6579990219486187401">Ljusrosa</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Rensa</translation>
<translation id="6644283850729428850">Policyn är föråldrad.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Ingen}=1{Från 1 webbplats (du loggas inte ut från Google-kontot)}other{Från # webbplatser (du loggas inte ut från Google-kontot)}}</translation>
+<translation id="6652101503459149953">Använd Windows Hello</translation>
<translation id="6657585470893396449">Lösenord</translation>
<translation id="6670613747977017428">Tillbaka till säker webbplats.</translation>
<translation id="6671697161687535275">Vill du ta bort formulärförslaget från Chromium?</translation>
<translation id="6685834062052613830">Logga ut och slutför konfigureringen</translation>
<translation id="6689271823431384964">Chrome ger möjlighet att spara dina kort i ditt Google-konto eftersom du är inloggad. Du kan ändra detta i inställningarna. Kortinnehavarens namn hämtas från ditt konto.</translation>
+<translation id="6707256370811247129">Genomsök cacheminnet och filer som du laddar ned eller laddar upp i Chrome.</translation>
<translation id="6710213216561001401">Föregående</translation>
<translation id="6710594484020273272">&lt;Ange sökterm&gt;</translation>
<translation id="671076103358959139">Registreringstoken:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Din data krypterades med din <ph name="BEGIN_LINK" />lösenfras för synkronisering<ph name="END_LINK" /> den <ph name="TIME" />. Ange den om du vill starta synkroniseringen.</translation>
<translation id="674375294223700098">Fel - okänt servercertifikat.</translation>
<translation id="6744009308914054259">Du kan öppna Nedladdningar och läsa artiklar offline medan du väntar på anslutningen.</translation>
+<translation id="6747611005629681221">Varning! Funktionerna är utfasade.</translation>
<translation id="6753269504797312559">Policyvärde</translation>
<translation id="6757797048963528358">Enheten gick i viloläge.</translation>
<translation id="6768213884286397650">Hagaki (vykort)</translation>
-<translation id="6778737459546443941">Din förälder har inte godkänt den ännu</translation>
<translation id="67862343314499040">Violett</translation>
<translation id="6786747875388722282">Tillägg</translation>
<translation id="6790428901817661496">Spela</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Obligatoriskt fält</translation>
<translation id="6810899417690483278">Anpassnings-id</translation>
<translation id="6825578344716086703">Du försökte besöka <ph name="DOMAIN" />, men servern skickade ett certifikat som signerats med en svag signaturalgoritm (t.ex. SHA-1). Det innebär att säkerhetsuppgifterna som servern uppgav kan vara förfalskade och att servern kanske inte är den server du tror (du kanske kommunicerar med en skadlig server).</translation>
+<translation id="6826370046007623921">Förebyggande av dataförlust</translation>
<translation id="6831043979455480757">Översätt</translation>
<translation id="6839929833149231406">Område</translation>
<translation id="6852204201400771460">Vill du läsa in appen igen?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Policynivån stöds inte.</translation>
<translation id="6895330447102777224">Kortet har bekräftats</translation>
<translation id="6897140037006041989">Användaragent</translation>
-<translation id="6903319715792422884">Hjälp oss att förbättra Säker webbsökning genom att låta <ph name="BEGIN_WHITEPAPER_LINK" />viss systeminformation och visst sidinnehåll<ph name="END_WHITEPAPER_LINK" /> skickas automatiskt till Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Användare:</translation>
<translation id="6934672428414710184">Det här namnet har hämtats från Google-kontot</translation>
<translation id="6944692733090228304">Du har angett ditt lösenord på en webbplats som inte hanteras av <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Skydda kontot genom att inte återanvända lösenordet i andra appar och webbplatser.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> och <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> till}other{<ph name="PAYMENT_METHOD_PREVIEW" /> och <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> till}}</translation>
<translation id="7153618581592392745">Lavendelfärgad</translation>
<translation id="717330890047184534">Gaia-id:</translation>
+<translation id="7174545416324379297">Sammanslagen</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> och <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> till}other{<ph name="SHIPPING_OPTION_PREVIEW" /> och <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> till}}</translation>
<translation id="7177397715882417099">Servern som du är på väg till, <ph name="ORIGIN" />, har begärt att en
säkerhetsprincip ska gälla varje gång den svarar på en begäran. Men i stället för att
@@ -1166,6 +1187,7 @@ Mer information.
<translation id="7320336641823683070">Anslutningshjälp</translation>
<translation id="733354035281974745">Åsidosätt enhetens lokala konto</translation>
<translation id="7334320624316649418">&amp;Gör om Ändra ordning</translation>
+<translation id="7337706099755338005">Ej tillgänglig för din plattform.</translation>
<translation id="733923710415886693">Servercertifikatet har inte lämnats ut via Certifikattransparens.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Är anknuten:</translation>
@@ -1197,7 +1219,6 @@ Mer information.
<translation id="7440140511386898319">Utforska medan du är offline</translation>
<translation id="7441627299479586546">Felaktigt policyämne</translation>
<translation id="7442725080345379071">Ljusorange</translation>
-<translation id="7444046173054089907">Webbplatsen är blockerad</translation>
<translation id="7445762425076701745">Det går inte att fastställa identiteten hos servern som du är ansluten till. Servernamnet som du angav vid anslutningen är bara giltigt inom ditt nätverk och externa certifikatutfärdare kan inte fastställa dess ägarskap. Vissa certifikatutfärdare utfärdar certifikat oavsett namn och därför går det inte att säkerställa att du är ansluten till den avsedda webbplatsen och inte till en skadlig server.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />att läsa mer<ph name="END_LINK" /> om det här problemet.</translation>
<translation id="7455133967321480974">Använd global standardinställning (Blockera)</translation>
@@ -1219,9 +1240,9 @@ Mer information.
<translation id="7538364083937897561">A2 (kuvert)</translation>
<translation id="7542403920425041731">När du bekräftar delas kortuppgifterna med den här webbplatsen.</translation>
<translation id="7542995811387359312">Automatisk ifyllning av kreditkort har inaktiverats eftersom formulärets anslutning inte är säker.</translation>
-<translation id="7543525346216957623">Fråga en förälder</translation>
<translation id="7548892272833184391">Åtgärda anslutningsproblem</translation>
<translation id="7549584377607005141">Den här webbsidan kräver uppgifter som du har angett tidigare för att kunna visas korrekt. Du kan skicka uppgifterna igen, men om du gör det upprepas de åtgärder som har utförts av sidan tidigare.</translation>
+<translation id="7550637293666041147">Ditt användarnamn på enheten och användarnamn i Chrome</translation>
<translation id="7552846755917812628">Testa följande tips:</translation>
<translation id="7554791636758816595">Ny flik</translation>
<translation id="7564049878696755256">Du kan förlora åtkomsten till kontot på <ph name="ORG_NAME" /> eller bli utsatt för identitetsstöld. Du rekommenderas att ändra lösenordet nu.</translation>
@@ -1236,6 +1257,7 @@ Mer information.
<translation id="7610193165460212391">Värdet är utanför intervallet <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Upphör: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Du har redan data som krypteras med en annan version av ditt lösenord till Google-kontot. Ange det nedan.</translation>
+<translation id="7625784245512586808">Skydd mot hot i Chrome Enterprise</translation>
<translation id="7633909222644580952">Prestandainformation och kraschrapporter</translation>
<translation id="7637571805876720304">Vill du ta bort kreditkortet från Chromium?</translation>
<translation id="7638605456503525968">Serieportar</translation>
@@ -1248,7 +1270,6 @@ Mer information.
<translation id="7668654391829183341">Okänd enhet</translation>
<translation id="7669271284792375604">Angripare på den här webbplatsen kan försöka lura dig att installera program som skadar din webbupplevelse (till exempel genom att byta ut din startsida eller visa extra annonser på webbplatser som du besöker).</translation>
<translation id="7676643023259824263">Sök efter texten i Urklipp, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Plattform och Cloud</translation>
<translation id="7681101578153515023">Ändra sökmotor</translation>
<translation id="7682287625158474539">Frakt</translation>
<translation id="7687186412095877299">Fyller i sparade betalningsmetoder i betalningsformulär</translation>
@@ -1263,7 +1284,6 @@ Mer information.
<translation id="7723047071702270851">Redigera kortet</translation>
<translation id="774634243536837715">Farligt innehåll har blockerats.</translation>
<translation id="7752995774971033316">Hanteras inte</translation>
-<translation id="7755287808199759310">En förälder kan ta bort blockeringen</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Anslutningen kan ha blockerats av en brandvägg eller antivirusprogram.</translation>
<translation id="7759163816903619567">Visningsdomän:</translation>
@@ -1307,7 +1327,6 @@ Mer information.
<translation id="8004582292198964060">Webbläsare</translation>
<translation id="8009225694047762179">Hantera Lösenord</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Det här kortet och dess faktureringsadress sparas. Du kan använda det när du är inloggad som <ph name="USER_EMAIL" />.}other{De här korten och deras faktureringsadresser sparas. Du kan använda dem när du är inloggad som <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Vi kunde inte nå dina föräldrar just nu. Försök igen.</translation>
<translation id="8025119109950072390">Angripare på den här webbplatsen kan lura dig att göra något farligt, till exempel installera programvara eller lämna ut personliga uppgifter (som lösenord, telefonnummer eller kreditkortsuppgifter).</translation>
<translation id="8034522405403831421">Den här sidan är skriven på <ph name="SOURCE_LANGUAGE" />. Vill du översätta den till <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Penna</translation>
@@ -1318,6 +1337,7 @@ Mer information.
<translation id="8041940743680923270">Använd global standardinställning (Fråga)</translation>
<translation id="8042918947222776840">Välj hämtningsalternativ</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> har inte konfigurerats korrekt. Ofta hjälper det att avinstallera <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Från och med nu behöver du inte ange någon säkerhetskod för kort</translation>
<translation id="8066955247577885446">Något gick tyvärr fel.</translation>
<translation id="8074253406171541171">10x13 (kuvert)</translation>
<translation id="8078141288243656252">Det går inte att annotera när dokumentet har roterats</translation>
@@ -1348,6 +1368,7 @@ Mer information.
<translation id="8211406090763984747">Anslutningen är säker</translation>
<translation id="8218327578424803826">Tilldelad plats:</translation>
<translation id="8220146938470311105">C7/C6 (kuvert)</translation>
+<translation id="8220639454292072926">Företagsrapportering</translation>
<translation id="8225771182978767009">Personen som konfigurerade datorn har valt att blockera den här webbplatsen.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Öppna sidan på en ny inkognitoflik</translation>
@@ -1402,24 +1423,24 @@ Mer information:
<translation id="8508648098325802031">Sökikon</translation>
<translation id="8522552481199248698">Du kan skydda Google-kontot genom att byta lösenord.</translation>
<translation id="8543181531796978784">Du kan <ph name="BEGIN_ERROR_LINK" />rapportera ett identifieringsproblem<ph name="END_ERROR_LINK" /> eller <ph name="BEGIN_LINK" />besöka den här osäkra webbplatsen<ph name="END_LINK" /> om du är medveten om säkerhetsriskerna.</translation>
-<translation id="8543556556237226809">Frågor? Kontakta den som kontrollerar profilen.</translation>
<translation id="8553075262323480129">Det gick inte att översätta eftersom det inte gick att avgöra vilket språk som användes på sidan.</translation>
<translation id="8557066899867184262">CVC-koden finns på baksidan av kortet.</translation>
<translation id="8559762987265718583">Det gick inte att upprätta en privat anslutning till <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> eftersom enhetens datum och tid (<ph name="DATE_AND_TIME" />) inte stämmer.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> misstänkt webbplats</translation>
<translation id="8564985650692024650">Du rekommenderas att återställa lösenordet för <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> om du har återanvänt det på andra webbplatser.</translation>
<translation id="8571890674111243710">Översätter sidan till <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Ange telefonnr
</translation>
-<translation id="859285277496340001">Certifikatet har inte någon specificerad mekanism för att kontrollera om det har återkallats.</translation>
<translation id="860043288473659153">Namn på kortinnehavare</translation>
<translation id="861775596732816396">Storlek 4</translation>
-<translation id="8620436878122366504">Dina föräldrar har inte godkänt den ännu</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Spara kortet på enheten</translation>
<translation id="8626112503828625890">Vill du spara faktureringsinformation i ditt Google-konto?</translation>
+<translation id="8647750283161643317">Återställ alla till standardvärden</translation>
<translation id="8663226718884576429">Beställningsöversikt, <ph name="TOTAL_LABEL" />, mer information</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, svar, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Tillgängligt</translation>
<translation id="8703575177326907206">Din anslutning till <ph name="DOMAIN" /> är inte krypterad.</translation>
<translation id="8718314106902482036">Betalningen slutfördes inte</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, sökförslag</translation>
@@ -1430,6 +1451,7 @@ Mer information:
<translation id="8738058698779197622">Om du vill upprätta en säker anslutning måste klockan vara rätt inställd. Det beror på att certifikaten som webbplatserna använder för att identifiera sig endast är giltiga under vissa tidsperioder. Chromium kan inte verifiera certifikaten eftersom klockan på enheten inte stämmer.</translation>
<translation id="8740359287975076522">Det gick inte att hitta <ph name="HOST_NAME" />s &lt;abbr id="dnsDefinition"&gt;DNS-adress&lt;/abbr&gt;. Diagnostiserar problemet.</translation>
<translation id="874846938927089722">Godkända kreditkort och förbetalda kort</translation>
+<translation id="874918643257405732">Bokmärk den här fliken</translation>
<translation id="8759274551635299824">Kortets giltighetstid har löpt ut</translation>
<translation id="8761567432415473239">Googles tjänst Säker webbsökning <ph name="BEGIN_LINK" />hittade skadliga program<ph name="END_LINK" /> på <ph name="SITE" /> nyligen.</translation>
<translation id="8763927697961133303">USB-enhet</translation>
@@ -1459,6 +1481,7 @@ Mer information:
<translation id="8938939909778640821">Godkända kreditkort och förbetalda kort</translation>
<translation id="8943282376843390568">Limegrön</translation>
<translation id="8957210676456822347">Auktorisering av infångstportal</translation>
+<translation id="8962950042226115166">Misstänkt webbplats</translation>
<translation id="8968766641738584599">Spara kortet</translation>
<translation id="8971063699422889582">Servercertifikatet har gått ut.</translation>
<translation id="8975012916872825179">Gäller uppgifter som telefonnummer, e-postadresser och leveransadresser</translation>
@@ -1481,24 +1504,24 @@ Mer information:
<translation id="9035022520814077154">Säkerhetsfel</translation>
<translation id="9038649477754266430">Använd en förslagstjänst om du vill läsa in sidor snabbare</translation>
<translation id="9039213469156557790">Den här sidan innehåller emellertid andra resurser som inte är säkra. Andra kan se resurserna när de överförs och hackare kan ändra resurserna så att sidan får ett annat beteende.</translation>
+<translation id="9044359186343685026">Använd Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Du försökte nå <ph name="DOMAIN" /> men servern angav ett ogiltigt certifikat.</translation>
<translation id="9050666287014529139">Lösenfras</translation>
<translation id="9065203028668620118">Redigera</translation>
<translation id="9065745800631924235">Sök efter <ph name="TEXT" /> i historiken</translation>
<translation id="9069693763241529744">Blockerades av ett tillägg</translation>
-<translation id="9076283476770535406">Den kan innehålla barnförbjudet innehåll</translation>
<translation id="9076630408993835509">Den här webbläsaren hanteras inte av ett företag eller en organisation. Aktiviteter på den här enheten kan hanteras utanför Chrome. <ph name="BEGIN_LINK" />Läs mer<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Mer information krävs</translation>
<translation id="9080712759204168376">Sammanfattning av beställningen</translation>
<translation id="9089260154716455634">Princip för användning utanför arbetstid:</translation>
<translation id="9095388113577226029">Fler språk …</translation>
+<translation id="9098981495403789647">Administratören har aktiverat skydd mot hot i Chrome Enterprise i webbläsaren. Skyddet mot hot i Chrome Enterprise har tillgång till en del av din data.</translation>
<translation id="9103872766612412690">På <ph name="SITE" /> används normalt kryptering (SSL) för att skydda din information. När Chromium försökte ansluta till <ph name="SITE" /> den här gången skickade webbplatsen tillbaka ovanliga och felaktiga uppgifter. Sådant kan hända när en angripare utger sig för att vara <ph name="SITE" /> eller när anslutningen har avbrutits av en Wi-Fi-inloggningsskärm. Din information är fortfarande säker eftersom Chromium avbröt anslutningen innan någon data utbyttes.</translation>
<translation id="9106062320799175032">Lägg till faktureringsadress</translation>
<translation id="9114524666733003316">Kortet kontrolleras …</translation>
<translation id="9128870381267983090">Anslut till ett nätverk</translation>
<translation id="9137013805542155359">Visa original</translation>
-<translation id="9137248913990643158">Logga in på Chrome innan du använder den här appen.</translation>
<translation id="9141013498910525015">Hantera adresser</translation>
<translation id="9148088599418889305">Välj fraktalternativ</translation>
<translation id="9148507642005240123">&amp;Ångra Redigera</translation>
diff --git a/chromium/components/strings/components_strings_sw.xtb b/chromium/components/strings/components_strings_sw.xtb
index a9fcdf3c5d9..7489da57fea 100644
--- a/chromium/components/strings/components_strings_sw.xtb
+++ b/chromium/components/strings/components_strings_sw.xtb
@@ -1,7 +1,7 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="sw">
-<translation id="1008557486741366299">Sio Sasa</translation>
+<translation id="1008557486741366299">Si Sasa</translation>
<translation id="1010200102790553230">Pakia ukurasa baadaye</translation>
<translation id="1015730422737071372">Toa maelezo ya ziada</translation>
<translation id="1021110881106174305">Kadi zinazokubaliwa</translation>
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Ongeza Jina kwenye Kadi</translation>
<translation id="1089439967362294234">Badilisha Nenosiri</translation>
+<translation id="1096545575934602868">Hupaswi kuweka zaidi ya vipengee <ph name="MAX_ITEMS_LIMIT" /> katika sehemu hii. Vipengee vyote vya ziada vitafutwa</translation>
<translation id="109743633954054152">Dhibiti manenosiri katika mipangilio ya Chrome</translation>
<translation id="1103523840287552314">Tafsiri <ph name="LANGUAGE" /> kila wakati</translation>
<translation id="1107591249535594099">Ikiteuliwa, Chrome itahifadhi nakala ya kadi yako kwenye kifaa hiki kwa ajili ya kujaza fomu haraka.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Fikia <ph name="BEGIN_LINK" />nakala iliyowekwa kwenye akiba<ph name="END_LINK" /> ya <ph name="URL" /></translation>
<translation id="1156303062776767266">Unaangalia faili ya mfumo au iliyoshirikiwa</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> imefunga muunganisho bila kutarajiwa.</translation>
+<translation id="115926840831309955">Angalia CVC yako kisha ujaribu tena au badilisha tarehe ya mwisho wa matumizi</translation>
<translation id="1161325031994447685">Kuunganisha tena kwenye Wi-Fi</translation>
<translation id="1165039591588034296">Hitilafu</translation>
<translation id="1175364870820465910">&amp;Chapisha...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Kuna programu kwenye kompyuta yako inayoizuia Chrome isiunganishe kwenye wavuti kwa usalama" (kompyuta za Windows pekee)</translation>
<translation id="1294154142200295408">Tofauti za miundo ya amri</translation>
<translation id="129553762522093515">Vilivyofungwa hivi karibuni</translation>
+<translation id="1298536327547837046">Uchanganuzi wa Programu Hasidi</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Jaribu kufuta vidakuzi kwenye kivinjari chako<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Vipengele Vilivyoacha Kutumiwa</translation>
<translation id="1320233736580025032">Prc1 (Bahasha)</translation>
<translation id="132301787627749051">Tafuta picha kwenye ubao wa kunakili</translation>
<translation id="1323433172918577554">Onyesha Zaidi</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Majedwali ya Google</translation>
<translation id="1527263332363067270">Inasubiri muunganisho...</translation>
<translation id="1529521330346880926">10x15 (Bahasha)</translation>
+<translation id="1530707389502320859">Tovuti ambayo umejaribu kutembelea inaonekana kuwa bandia. Wakati mwingine, wadukuzi wanaweza kuiga tovuti kwa kufanya mabadiliko madogo na yasiyoonekana kwa urahisi kwenye URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Ukurasa huu unasema</translation>
<translation id="153384715582417236">Hakuna maudhui mengine kwa sasa</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Huwezi kuweka vidokezo kwenye hati kwa kuwa ni kubwa mno</translation>
-<translation id="1721312023322545264">Unahitaji ruhusa kutoka kwa <ph name="NAME" /> ili utembelee tovuti hii</translation>
<translation id="1721424275792716183">* Unahitaji kujaza sehemu hii</translation>
<translation id="1727741090716970331">Ongeza Nambari Sahihi ya Kadi</translation>
<translation id="1728677426644403582">Unaangalia chanzo cha ukurasa wa wavuti</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Tovuti ulizotembelea na muda uliotumia kwenye tovuti hizo</translation>
<translation id="1826516787628120939">Inakagua</translation>
<translation id="1834321415901700177">Tovuti hii ina programu hatari</translation>
+<translation id="1838374766361614909">Futa utafutaji</translation>
<translation id="1839551713262164453">Imeshindwa kuthibitisha thamani za sera kutokana na hitilafu</translation>
<translation id="1842969606798536927">Lipa</translation>
<translation id="1871208020102129563">Proksi imewekwa ili kutumia seva za proksi thabiti, siyo URL ya hati .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Kunja orodha</translation>
<translation id="1898423065542865115">Kuchuja</translation>
<translation id="1914326953223720820">Huduma ya Kufungua Faili za Zip</translation>
+<translation id="1915697529809968049">Ungependa kutumia Touch ID badala ya CVC?</translation>
<translation id="1916770123977586577">Pakia upya ukurasa huu ili mipangilio iliyosasishwa itumike katika tovuti hii</translation>
<translation id="1919345977826869612">Matangazo</translation>
<translation id="1919367280705858090">Pata usaidizi kwa kutumia ujumbe mahususi kuhusu hitilafu</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Alamisho za <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Hitilafu ya namba tambulishi</translation>
<translation id="1974060860693918893">Mipangilio ya kina</translation>
+<translation id="1974883374937189061">Tusaidie kuboresha usalama wa Chrome kwa kutuma <ph name="BEGIN_WHITEPAPER_LINK" />URL za baadhi ya kurasa unazotembelea, maelezo machache ya mfumo na maudhui kadhaa ya ukurasa<ph name="END_WHITEPAPER_LINK" /> kwa Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Toleo la Programu dhibiti</translation>
<translation id="1981206234434200693">Futa data ya historia ya kuvinjari katika Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{na nyingine 1}other{na nyingine #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Andika mwaka sahihi wa kuisha kwa muda wa matumizi</translation>
<translation id="2212735316055980242">Sera haikupatikana</translation>
<translation id="2213606439339815911">Inachukua viingizo...</translation>
+<translation id="2215727959747642672">Kubadilisha faili</translation>
<translation id="2218879909401188352">Wavamizi walio kwenye <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> hivi sasa, wanaweza kusakinisha programu hatari zinazoweza kukiharibu kifaa chako, kuongeza gharama fiche kwenye malipo yako ya simu, au kuiba maelezo yako ya binafsi. <ph name="BEGIN_LEARN_MORE_LINK" />Pata maelezo zaidi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Hakuna intaneti</translation>
<translation id="2230458221926704099">Weka muunganisho wako kwa kutumia <ph name="BEGIN_LINK" />programu ya kuchunguza<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Tuma sasa</translation>
+<translation id="2248949050832152960">Tumia WebAuthn</translation>
<translation id="225207911366869382">Thamani hii inapingwa kwa sera hii.</translation>
<translation id="2257315177824333709">Samahani, kadi yako haiwezi kuhifadhiwa sasa hivi</translation>
<translation id="2262243747453050782">Hitilfau ya HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL batili ya utafutaji.</translation>
<translation id="2482878487686419369">Arifa</translation>
<translation id="248348093745724435">Sera za mashine</translation>
-<translation id="2485387744899240041">Majina ya watumiaji kwenye kivinjari na kifaa chako</translation>
<translation id="2491120439723279231">Cheti cha seva kina hitilafu.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Kichanganuzi cha JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Rudi nyuma</translation>
<translation id="2503184589641749290">Kadi za malipo na za kulipia awali zinazokubaliwa</translation>
<translation id="2505268675989099013">Linda Akaunti</translation>
+<translation id="2515335152965840738">PUUZA</translation>
<translation id="2515629240566999685">Kuangalia uthabiti wa mawimbi katika eneo lako</translation>
<translation id="2523886232349826891">Imehifadhiwa kwenye kifaa hiki pekee</translation>
<translation id="2524461107774643265">Ongeza Maelezo Zaidi</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Wasilisha</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Hamna}=1{Nenosiri 1 (la <ph name="DOMAIN_LIST" />)}=2{Manenosiri 2 (ya <ph name="DOMAIN_LIST" />)}other{Manenosiri # (ya <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Funga vichupo au programu nyingine</translation>
-<translation id="267371737713284912">bonyeza <ph name="MODIFIER_KEY_DESCRIPTION" /> ili utendue</translation>
<translation id="2674170444375937751">Je, una hakika kuwa ungependa kufuta kurasa hizi kutoka historia yako?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Ondoka</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Thamani haioani na umbizo.</translation>
<translation id="2705137772291741111">Nakala iliyohifadhiwa (iliyowekwa katika akiba) ya tovuti hii haikusomeka.</translation>
<translation id="2709516037105925701">Kujaza Kiotomatiki</translation>
-<translation id="2712173769900027643">Omba ruhusa</translation>
<translation id="2713444072780614174">Nyeupe</translation>
<translation id="2720342946869265578">Uhamishaji wa Karibu</translation>
<translation id="2721148159707890343">Ombi limefanikiwa</translation>
<translation id="2728127805433021124">Cheti cha seva kimetiwa sahihi kwa kutumia algoriti dhaifu ya sahihi.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Inaendesha Zana ya Kuchunguza Muunganisho<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Kwa kuwasha vipengele hivi, unaweza kupoteza data ya kivinjari au
+ kutelekeza usalama na faragha yako. Vipengele vilivyowashwa huathiri
+ watumiaji wote wa kivinjari hiki.</translation>
<translation id="2735043616039983645">Sera hii ina vyanzo vyenye thamani zinazokinzana!</translation>
<translation id="2738330467931008676">Chagua Anwani ya Mahali pa Kuchukulia Bidhaa</translation>
<translation id="2740531572673183784">Sawa</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Muunganisho uliwekwa upya.</translation>
<translation id="2788784517760473862">Kadi za malipo zinazokubaliwa</translation>
<translation id="2792012897584536778">Wasimamizi wa kifaa hiki wameweka mipangilio ya vyeti vya usalama ambavyo vinaweza kuwaruhusu kuona maudhui ya tovuti unazotembelea.</translation>
-<translation id="2794233252405721443">Tovuti imezuiwa</translation>
<translation id="2799020568854403057">Kuna programu hasidi kwenye tovuti unayotaka kuifungua</translation>
<translation id="2799223571221894425">Funga na ufungue</translation>
<translation id="2803306138276472711">Mfumo wa Google wa Kuvinjari kwa Usalama {<ph name="BEGIN_LINK" />uligundua programu hasidi<ph name="END_LINK" /> kwenye <ph name="SITE" /> hivi karibuni. Tovuti ambazo kwa kawaida huwa salama wakati mwingine huathiriwa na programu hasidi.</translation>
+<translation id="2815364696811431560">FUNGA TOVUTI</translation>
<translation id="2824775600643448204">Upau wa anwani na utafutaji</translation>
<translation id="2826760142808435982">Muunganisho umesimbwa kwa njia fiche na kuthibitishwa kupitia <ph name="CIPHER" /> na unatumia <ph name="KX" /> kama utaratibu msingi wa ubadilishaji.</translation>
<translation id="2835170189407361413">Futa fomu</translation>
<translation id="2847118875340931228">Fungua Dirisha Fiche</translation>
<translation id="2850739647070081192">Invite (Bahasha)</translation>
-<translation id="2851634818064021665">Unahitaji ruhusa ili utembelee tovuti hii</translation>
<translation id="2856444702002559011">Huenda wavamizi wanajaribu kuiba maelezo yako kutoka <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (kwa mfano, manenosiri, ujumbe au kadi za mikopo).<ph name="BEGIN_LEARN_MORE_LINK" />Pata maelezo zaidi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Ungependa kuhifadhi kadi?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Ikiwashwa, Chromium itahifadhi nakala ya kadi yako kwenye kifaa hiki kwa ajili ya kujaza fomu haraka zaidi.</translation>
<translation id="2985398929374701810">Andika anwani sahihi</translation>
<translation id="2986368408720340940">Mbinu hii ya kuchukua haipatikani. Jaribu mbinu tofauti.</translation>
+<translation id="2987034854559945715">Hakuna vipengele vinavyolingana</translation>
<translation id="2991174974383378012">Kushiriki kwenye Tovuti</translation>
<translation id="2991571918955627853">Huwezi kutembelea <ph name="SITE" /> sasa hivi kwa sababu tovuti inatumia HSTS. Hitilafu na uvamizi wa mtandao kwa kawaida huwa vya muda, kwa hivyo huenda ukurasa huu ukafanya kazi baadaye.</translation>
<translation id="3005723025932146533">Onyesha nakala iliyohifadhiwa</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Aina mbaya ya sera</translation>
<translation id="3037605927509011580">Lo!</translation>
<translation id="3041612393474885105">Maelezo ya Cheti</translation>
+<translation id="3057676462092457419">Hali ya DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> bado haitumiki, hali imewekwa kuwa <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Bahasha)</translation>
<translation id="3061707000357573562">Huduma ya Kurekebisha</translation>
<translation id="3064966200440839136">Inaacha hali fiche ili kulipa kupitia programu ya nje. Je, ungependa kuendelea?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> kwenye <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Ghairi Malipo</translation>
<translation id="3207960819495026254">Imealamishwa</translation>
+<translation id="3209034400446768650">Huenda ukurasa ukakutoza</translation>
<translation id="3225919329040284222">Seva imewasilisha cheti kisicholingana na matarajio ya kijenzi cha ndani. Matarajio haya yanajumlishwa kwa baadhi ya tovuti za usalama wa juu ili kukulinda.</translation>
<translation id="3226128629678568754">Bonyeza kitufe cha kupakia upya ili kuwasilisha upya data inayohitajika kupakia ukurasa.</translation>
<translation id="3227137524299004712">Maikrofoni</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Maelezo ya toleo kuhusu kivinjari na kifaa chako</translation>
<translation id="323107829343500871">Weka CVC ya <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Gundua maudhui muhimu kwenye tovuti hii wakati wowote</translation>
-<translation id="3254409185687681395">Alamisha ukurasa huu</translation>
<translation id="3270847123878663523">Tendua Kupanga upya</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Ongeza jina kwenye kadi</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Ongeza anwani ya kutuma bili</translation>
<translation id="3324983252691184275">Nyekundu Iliyoiva</translation>
<translation id="3338095232262050444">Salama</translation>
-<translation id="3345135638360864351">Ombi lako la kufikia tovuti hii halikutumwa kwa <ph name="NAME" />. Tafadhali jaribu tena.</translation>
<translation id="3355823806454867987">Badilisha mipangilio ya seva mbadala...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />haitahifadhi<ph name="END_EMPHASIS" /> maelezo yafuatayo:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Ficha mahiri</translation>
<translation id="3467763166455606212">Jina la mwenye kadi linahitajika</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, kwa sasa kimefunguka, bonyeza Kichupo kisha Enter ili uende kwenye kichupo ambacho kimefunguliwa</translation>
-<translation id="3479539252931486093">Je, hukutarajia tukio hili? <ph name="BEGIN_LINK" />Tujulishe<ph name="END_LINK" /></translation>
-<translation id="3479552764303398839">Sio sasa</translation>
+<translation id="3479552764303398839">Si sasa</translation>
<translation id="3484560055331845446">Unaweza kupoteza uwezo wa kufikia Akaunti yako ya Google. Chrome inapendekeza ubadilishe nenosiri lako sasa. Utaombwa uingie katika akaunti.</translation>
<translation id="3495081129428749620">Pata katika ukurasa wa
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Hatukuweza kufikia mzazi wako wakati huu. Tafadhali jaribu tena.</translation>
<translation id="3512163584740124171">Sera hii haitumiki kwa sababu sera nyingine kutoka kundi sawa la sera inapewa kipaumbele zaidi.</translation>
<translation id="3528171143076753409">Cheti cha seva hakiaminiki.</translation>
<translation id="3528485271872257980">Kahawia Iliyokolea</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Angalau kipengee 1 kwenye vifaa vilivyosawazishwa}=1{Kipengee 1 (na zaidi kwenye vifaa vilivyosawazishwa)}other{Vipengee # (na zaidi kwenye vifaa vilivyosawazishwa)}}</translation>
<translation id="3539171420378717834">Weka nakala ya kadi hii kwenye kifaa hiki</translation>
-<translation id="3556433843310711081">Msimamizi wako anaweza kukuondolea kizuizi</translation>
<translation id="3566021033012934673">Muunganisho wako si wa faragha</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Ukurasa uliopachikwa kwenye <ph name="SITE" /> unasema</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Fungua ukurasa kwenye dirisha fiche jipya (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Ripoti ya kuacha kufanya kazi ilitolewa <ph name="CRASH_TIME" /> na kupakiwa <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Maelezo ya cheti</translation>
+<translation id="3701427423622901115">Imekubali kuweka upya.</translation>
<translation id="3704162925118123524">Mtandao unaotumia unaweza kukuhitaji kuutembelea ukurasa wake wa kuingia katika akaunti.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Inapakia...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Wavamizi kwenye <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> huenda wakakuhadaa ufanye kitu hatari kama vile kusakinisha programu au kuonyesha maelezo yako ya binafsi (kwa mfano, manenosiri, nambari za simu au kadi za mikopo). <ph name="BEGIN_LEARN_MORE_LINK" />Pata maelezo zaidi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Utafsiri haukufanikiwa kwa sababu ya hitilafu ya seva.</translation>
<translation id="3759461132968374835">Huna uharibifu ulioripotiwa hivi karibuni. Uharibifu uliotokea wakati kuripoti kwa uharibifu kulipolemazwa hakutaonekana hapa.</translation>
+<translation id="3760561303380396507">Ungependa kutumia Windows Hello badala ya CVC?</translation>
<translation id="3761718714832595332">Ficha hali</translation>
<translation id="3765032636089507299">Ukurasa wa Kuvinjari Salama unaboreshwa.</translation>
<translation id="3778403066972421603">Je, ungependa kuhifadhi kadi hii kwenye Akaunti yako ya Google na kwenye kifaa hiki?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Ukubwa wa 16</translation>
<translation id="3797522431967816232">Prc3 (Bahasha)</translation>
<translation id="3807873520724684969">Imezuia maudhui hatari.</translation>
+<translation id="3808375843007691220">Onyo: Vipengele vya kufanyia jaribio vinafuata!</translation>
<translation id="3810973564298564668">Dhibiti</translation>
<translation id="382518646247711829">Ukitumia seva mbadala...</translation>
<translation id="3828924085048779000">Kaulisiri tupu hairuhusiwi.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Sasisha tarehe na saa</translation>
<translation id="3884278016824448484">Kitambulisho cha kifaa kinachokinzana</translation>
<translation id="3885155851504623709">Parokia</translation>
-<translation id="3886446263141354045">Ombi lako la kufikia tovuti hii limetumwa kwa <ph name="NAME" /></translation>
<translation id="3890664840433101773">Ongeza anwani ya barua pepe</translation>
<translation id="3901925938762663762">Kadi imekwisha muda</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Ungependa kutumia WebAuthn badala ya CVC?</translation>
<translation id="3946209740501886391">Uliza kwenye tovuti hii kila wakati</translation>
<translation id="3949571496842715403">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama hakibainishi Majina Mbadala ya Mada. Hii inaweza kusababishwa na uwekaji mipangilio usiofaa au muunganisho wako kukatwa na mvamizi.</translation>
<translation id="3949601375789751990">Historia yako ya kuvinjari itaonekana hapa</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Hamna}=1{Kutoka kwenye tovuti 1 }other{Kutoka kwenye tovuti # }}</translation>
<translation id="397105322502079400">Inakokotoa...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> imezuiwa.</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> imewasha Ulinzi wa Hatari wa Chrome Enterprise kwenye kivinjari chako. Kipengele cha Ulinzi wa Hatari cha Chrome Enterprise kina uwezo wa kufikia baadhi ya data yako.</translation>
<translation id="3987940399970879459">Chini ya MB 1</translation>
<translation id="40103911065039147">{URL_count,plural, =1{ukurasa 1 wa wavuti ulio karibu}other{kurasa # za wavuti zilizo karibu}}</translation>
<translation id="4030383055268325496">Tendua kuongeza</translation>
<translation id="4032320456957708163">Kivinjari chako kinadhibitiwa na <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Kiungo ulichofungua kinaelekeza kwenye tovuti ambayo huwa huitembelei. Huenda kinajaribu kukukanganya.</translation>
<translation id="4058922952496707368">Kitufe "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Bahasha)</translation>
<translation id="4067947977115446013">Ongeza Anwani Sahihi ya Mahali Bidhaa Itapelekwa</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Namabari tambulishi ya kifaa ni batili</translation>
<translation id="410351446219883937">Kucheza kiotomatiki</translation>
<translation id="4103763322291513355">Tembelea &lt;strong&gt;chrome://policy&lt;/strong&gt; ili kuona orodha ya URL zilizoondolewa idhini na sera zingine zinazosimamiwa na msimamizi wako wa mfumo.</translation>
+<translation id="4108231218301530806">Tumia alama ya kidole kuthibitisha kadi hii wakati ujao.</translation>
<translation id="4110652170750985508">Kagua malipo yako</translation>
<translation id="4112140312785995938">Sogeza Nyuma</translation>
<translation id="4116663294526079822">Ruhusu mara kwa mara kwenye tovuti hii</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Sahihi mbaya ya uthibitishaji</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{Kipengee kingine <ph name="ITEM_COUNT" />}other{Vipengee vingine <ph name="ITEM_COUNT" />}}</translation>
+<translation id="4176463684765177261">Kimelemazwa</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Ili ulipe kwa haraka wakati ujao, ongeza anwani yako ya kutuma bili na maelezo ya kadi kwenye Akaunti yako ya Google.</translation>
<translation id="4196861286325780578">Rudia hatua</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Badilisha nenosiri</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> yako inasimamiwa na <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Kadi hii imehifadhiwa kwenye Akaunti yako ya Google}other{Kadi hizi zimehifadhiwa kwenye Akaunti yako ya Google}}</translation>
+<translation id="428847186335018806">Kuchanganua faili unazopakua au kupakia kwenye Chrome.</translation>
<translation id="42981349822642051">Panua</translation>
<translation id="4302965934281694568">Chou3 (Bahasha)</translation>
<translation id="4305817255990598646">Badilisha</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Kad ya Posta)</translation>
<translation id="443673843213245140">Matumizi ya proksi yamelemazwa lakini usanidi wa proksi wazi umebainishwa.</translation>
<translation id="445100540951337728">Kadi za malipo zinazokubaliwa</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> hali ya kutiliwa shaka</translation>
<translation id="4466881336512663640">Haitahifadhi mabadiliko uliyofanya kwenye fomu. Je, una uhakika unataka kuendelea?</translation>
<translation id="4477350412780666475">Wimbo Unaofuata</translation>
<translation id="4482953324121162758">Haitatafsiri tovuti hii.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">Tendua Kufuta</translation>
<translation id="4597348597567598915">Ukubwa wa 8</translation>
<translation id="4600854749408232102">C6/C5 (Bahasha)</translation>
+<translation id="464342062220857295">Vipengele vya utafutaji</translation>
<translation id="4646534391647090355">Nipeleke kwenye sehemu hiyo sasa</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama kina hitilafu. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (Bahasha)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Muunganisho wako umekatizwa</translation>
-<translation id="471880041731876836">Huna ruhusa ya kutembelea tovuti hii</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Kuendesha Zana ya Windows ya Kuchunguza Mtandao<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Pakia sera upya</translation>
<translation id="4728558894243024398">Mfumo wa uendeshaji</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Sawazisha kwenye ukurasa</translation>
<translation id="4850886885716139402">Mwonekano</translation>
<translation id="4854362297993841467">Njia hii ya kusafirisha haitumiki. Jaribu njia tofauti.</translation>
-<translation id="4858792381671956233">Umewaomba wazazi wako ruhusa ya kuutembelea ukurasa huu.</translation>
<translation id="4864052566555297930">Kidokezo cha usalama:</translation>
<translation id="4876188919622883022">Mwonekano rahisi</translation>
<translation id="4876305945144899064">Hakuna jina la mtumiaji</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Onyesha maonyo tena</translation>
<translation id="4984339528288761049">Prc5 (Bahasha)</translation>
<translation id="4989163558385430922">Angalia vyote</translation>
+<translation id="4989542687859782284">Hayapatikani</translation>
<translation id="4989809363548539747">Programu jalizi hii haitumiki</translation>
+<translation id="4995216769782533993">Thibitisha msimbo wa usalama ili ushiriki maelezo ya kadi yako na tovuti hii</translation>
<translation id="5002932099480077015">Ikiwashwa, Chrome itahifadhi nakala ya kadi yako kwenye kifaa hiki kwa ajili ya kujaza fomu haraka zaidi.</translation>
<translation id="5015510746216210676">Jina la Mashine:</translation>
<translation id="5017554619425969104">Maandishi uliyonakili</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(biti 64)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Thibitisha kadi yako</translation>
<translation id="5135404736266831032">Dhibiti anwani...</translation>
<translation id="5138227688689900538">Onyesha chache</translation>
<translation id="5141240743006678641">Simba kwa njia fiche manenosiri yaliyosawazishwa ukitumia stakabadhi zako za Google</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Wingu</translation>
<translation id="5252000469029418751">C7 (Bahasha)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Vipengele vinavyotumika katika mfumo wote vinaweza tu kuwekwa na mmiliki: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Ilani: Sera hii haikuunganishwa jinsi ilivyobainishwa katika sera ya PolicyDictionaryMultipleSourceMergeList kwa sababu si sehemu ya sera za kamusi ambazo zinaweza kuunganishwa.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Mwisho</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Imeshindwa kuhifadhi mipangilio ya sera</translation>
<translation id="5371425731340848620">Badilisha maelezo ya kadi</translation>
<translation id="5377026284221673050">"Saa yako iko nyuma" au "Saa yako iko mbele" au "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Ukurasa huu unaweza kukuhadaa, kuiba taarifa binafsi au kudhuru kifaa chako. Kuwa makini wakati unaweka taarifa binafsi au unapofungua faili iliyopakuliwa.</translation>
<translation id="5384855140246857529">Ingia katika akaunti na uwashe kipengele cha kusawazisha ili utumie kadi zako kwenye vifaa vyako vyote.</translation>
<translation id="5386426401304769735">Msururu wa cheti wa tovuti hii una cheti kilichotiwa sahihi kwa kutumia SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Haiwezi kutumika</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> na mwingine <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> na wengine <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">Rudia kuhariri</translation>
+<translation id="5473728911100096288">Kwa kuwasha vipengele hivi, utakuwa ukitumia vipengele ambavyo vimeacha kutumika
+ ambavyo havitapatikana katika matoleo ya siku zijazo.</translation>
<translation id="5478437291406423475">B6/C4 (Bahasha)</translation>
<translation id="5481076368049295676">Huenda maudhui haya yakajaribu kusakinisha programu hatari inayoiba au kufuta maelezo yaliyo kwenye kifaa chako. <ph name="BEGIN_LINK" />Onyesha tu<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Ongeza anwani sahihi ya barua pepe</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Linda akaunti</translation>
<translation id="5571083550517324815">Haiwezi kuchukua kutoka kwenye anwani hii. Chagua anwani tofauti.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 kinatumika}other{ # vinatumika}})</translation>
-<translation id="5572851009514199876">Tafadhali anza na uingie katika Chrome ili Chrome iangalie ikiwa unaruhusiwa kufikia tovuti hii.</translation>
<translation id="5580958916614886209">Angalia mwezi kuisha kwa muda wa matumizi halafu ujajibu tena</translation>
<translation id="5586446728396275693">Hakuna anwani zilizohifadhiwa</translation>
<translation id="5595485650161345191">Badilisha anwani</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Usimamizi hautumiki</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Huenda tovuti hii ni bandia au laghai. Chrome inapendekeza uifunge sasa.</translation>
<translation id="5610142619324316209">Kuangalia muunganisho</translation>
<translation id="5610807607761827392">Unaweza kudhibiti maelezo ya kadi na anwani katika <ph name="BEGIN_LINK" />Mipangilio<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> imekuelekeza upya mara nyingi mno.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Mtumiaji wa sasa</translation>
<translation id="5728056243719941842">C5 (Bahasha)</translation>
<translation id="5730040223043577876">Chrome inapendekeza ubadilishe nenosiri lako ikiwa ulilitumia tena kwenye tovuti zingine.</translation>
-<translation id="5732392974455271431">Wazazi wako wanaweza kukuondolea kizuizi</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Hifadhi kadi katika Akaunti yako ya Google}other{Hifadhi kadi katika Akaunti yako ya Google}}</translation>
<translation id="5763042198335101085">Andika anwani sahihi ya barua pepe</translation>
<translation id="5765072501007116331">Chagua mahali ili uone njia za kusafirisha na mahitaji</translation>
<translation id="5778550464785688721">Udhibiti kamili wa vifaa vya MIDI</translation>
+<translation id="5781136890105823427">Jaribio limeruhusiwa</translation>
<translation id="578305955206182703">Rangi ya chungwa</translation>
<translation id="57838592816432529">Zima sauti</translation>
<translation id="5784606427469807560">Kulikuwa na tatizo wakati wa kuthibitisha kadi yako. Angalia muunganisho wako wa intaneti kisha ujaribu tena.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Kimezimwa</translation>
<translation id="5863847714970149516">Huenda ukurasa unaofuata ukajaribu kukutoza pesa</translation>
<translation id="5866257070973731571">Ongeza Nambari ya Simu</translation>
+<translation id="5866898949289125849">Unaangalia ukurasa wa zana za msanidi programu</translation>
<translation id="5869405914158311789">Imeshindwa kufungua tovuti hii</translation>
<translation id="5869522115854928033">Manenosiri yaliyohifadhiwa</translation>
<translation id="5887400589839399685">Kadi imehifadhiwa</translation>
<translation id="5893752035575986141">Kadi za mikopo zinakubaliwa.</translation>
+<translation id="5895138241574237353">Zzima na uwashe</translation>
<translation id="5901630391730855834">Manjano</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (imesawazishwa)</translation>
<translation id="5916664084637901428">Imewashwa</translation>
+<translation id="59174027418879706">Imewezeshwa</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Ungependa kuhifadhi kadi kwenye Akaunti ya Google?</translation>
<translation id="5922853866070715753">Unakaribia kumaliza</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Ungependa kutumia kadi zako kwenye vifaa vyako vyote?</translation>
<translation id="6059925163896151826">Vifaa vya USB</translation>
+<translation id="6060009363608157444">Hali ya DnsOverHttps isiyo sahihi.</translation>
<translation id="6080696365213338172">Umefikia maudhui kwa kutumia cheti kilichotolewa cha msimamizi. Data unayotoa katika <ph name="DOMAIN" /> inaweza kuzuiliwa na msimamizi wako.</translation>
<translation id="6094273045989040137">Weka vidokezo</translation>
<translation id="610911394827799129">Huenda Akaunti yako ya Google ina aina nyingine za historia ya kuvinjari katika <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Badilisha alamisho</translation>
<translation id="6406765186087300643">C0 (Bahasha)</translation>
<translation id="6410264514553301377">Weka tarehe ya mwisho wa matumizi na CVC ya <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Umewaomba wazazi wako ruhusa ya kuitembelea tovuti hii</translation>
<translation id="6415778972515849510">Chromium inaweza kukusaidia kulinda Akaunti yako ya Google na kubadilisha nenosiri lako.</translation>
-<translation id="6417515091412812850">Haiwezi kukagua ikiwa cheti kimebatilishwa.</translation>
<translation id="6431585503458005759">Usihifadhi</translation>
<translation id="6433490469411711332">Badilisha maelezo ya mawasiliano</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> imekataa kuunganisha.</translation>
<translation id="6434309073475700221">Tupa</translation>
+<translation id="6435221585574090192">Shiriki na msimamizi wako data kuhusu matukio ya usalama ambayo yameripotiwa na kipengele cha Ulinzi wa Hatari cha Chrome Enterprise. Hii inaweza kujumuisha URL za ukurasa, jina la faili na metadata ya faili, jina lako la mtumiaji wa kifaa na jina lako la mtumiaji wa Chrome.</translation>
<translation id="6440503408713884761">Imepuuzwa</translation>
<translation id="6446163441502663861">Kahu (Bahasha)</translation>
<translation id="6446608382365791566">Ongeza maelezo zaidi</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Dhibiti manenosiri...</translation>
<translation id="647261751007945333">Sera za kifaa</translation>
<translation id="6476284679642588870">Dhibiti njia za kulipa</translation>
-<translation id="6477321094435799029">Chrome imegundua nambari ya kuthibitisha isiyo ya kawaida kwenye ukurasa huu na ikaizuia ili kulinda maelezo ya binafsi (kwa mfano, manenosiri, nambari za simu na kadi za mikopo).</translation>
<translation id="6489534406876378309">Anza kupakia matukio ya kuacha kufanya kazi</translation>
<translation id="6499038740797743453">Ungependa kubadilisha nenosiri?</translation>
<translation id="6507833130742554667">Kadi za mikopo na malipo zinakubaliwa.</translation>
<translation id="650855688985305916">Ndiyo, hifadhi</translation>
<translation id="6508722015517270189">Zima na uwashe Chrome</translation>
<translation id="6517596291481585650">Ilani: Sera hii haikuunganishwa kama orodha jinsi ilivyobainishwa na sera kwa sababu haipo kwenye orodha.</translation>
+<translation id="6518133107902771759">Thibitisha</translation>
<translation id="6521745193039995384">Haitumiki</translation>
<translation id="6529602333819889595">Rudia Kufuta</translation>
<translation id="6534179046333460208">Mapendekezo ya Wavuti kila Mahali</translation>
<translation id="6545864417968258051">Kutafuta Bluetooth</translation>
<translation id="6554795675067793129">Akaunti yako inadhibitiwa na <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Rudia</translation>
-<translation id="6563469144985748109">Msimamizi wako bado hajaiidhinisha</translation>
<translation id="6569060085658103619">Unaangalia ukurasa wa kiendelezi</translation>
<translation id="6578796323535178455">C2 (Bahasha)</translation>
<translation id="6579990219486187401">Waridi Isiyokolea</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Futa</translation>
<translation id="6644283850729428850">Sera hii imepingwa.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Hamna}=1{Kutoka tovuti 1 (hutaondolewa kwenye Akaunti ya Google)}other{Kutoka tovuti # (hutaondolewa kwenye Akaunti ya Google)}}</translation>
+<translation id="6652101503459149953">Tumia Windows Hello</translation>
<translation id="6657585470893396449">Nenosiri</translation>
<translation id="6670613747977017428">Rudi kwenye ukurasa salama.</translation>
<translation id="6671697161687535275">Je, ungependa kuondoa pendekezo la fomu kwenye Chromium?</translation>
<translation id="6685834062052613830">Ondoka na ukamilishe kuweka mipangilio</translation>
<translation id="6689271823431384964">Chrome itakuhifadhia kadi zako katika Akaunti yako ya Google kwa sababu umeingia katika akaunti. Unaweza kubadilisha hali hii katika mipangilio. Jina la mwenye kadi linatoka kwenye akaunti yako.</translation>
+<translation id="6707256370811247129">Kuchanganua maudhui ya akiba na faili ambazo unapakia au kupakua kwenye Chrome.</translation>
<translation id="6710213216561001401">Iliyotangulia</translation>
<translation id="6710594484020273272">&lt;Andika neno unalotaka kutafuta&gt;</translation>
<translation id="671076103358959139">Tokeni ya Kujiandikisha:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Data yako ilisimbwa kwa kutumia <ph name="BEGIN_LINK" />kauli ya siri ya usawazishaji<ph name="END_LINK" /> mnamo <ph name="TIME" />. Iweke ili uanze kusawazisha.</translation>
<translation id="674375294223700098">Hitilafu isiyojulikana ya cheti cha seva.</translation>
<translation id="6744009308914054259">Wakati unasubiri muunganisho, unaweza kutembelea Vipakuliwa ili usome makala yaliyo nje ya mtandao.</translation>
+<translation id="6747611005629681221">Onyo: Vipengele vilivyo hapa viliacha kutumika!</translation>
<translation id="6753269504797312559">Thamani ya sera</translation>
<translation id="6757797048963528358">Kifaa chako kiko katika hali tuli.</translation>
<translation id="6768213884286397650">Hagaki (Kadi ya Posta)</translation>
-<translation id="6778737459546443941">Mzazi wako bado hajaiidhinisha</translation>
<translation id="67862343314499040">Zambarau iliyokolea</translation>
<translation id="6786747875388722282">Viendelezi</translation>
<translation id="6790428901817661496">Cheza</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Sehemu Hii Sharti Ijazwe</translation>
<translation id="6810899417690483278">Kitambulisho cha kubadilisha ili kukufaa</translation>
<translation id="6825578344716086703">Umejaribu kufikia <ph name="DOMAIN" />, lakini seva iliwasilisha cheti kilichotiwa sahihi na kanuni duni. Hii inamaanisha kuwa stakabadhi za usalama zilizowasilishwa na seva hiyo huenda ni bandia na seva hiyo huenda ikawa si ile uliyotarajia (unaweza kuwa unawasiliana na mvamizi).</translation>
+<translation id="6826370046007623921">Mfumo wa Kuzuia Data Isipotee</translation>
<translation id="6831043979455480757">Tafsiri</translation>
<translation id="6839929833149231406">Eneo</translation>
<translation id="6852204201400771460">Ungependa kupakia programu upya?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Kiwango cha sera hakitumiki.</translation>
<translation id="6895330447102777224">Kadi yako imethibitishwa</translation>
<translation id="6897140037006041989">Programu ya Mtumiaji</translation>
-<translation id="6903319715792422884">Tusaidie tuboreshe huduma ya Kuvinjari Salama kwa kutuma baadhi ya <ph name="BEGIN_WHITEPAPER_LINK" />maudhui ya ukurasa na maelezo ya mfumo<ph name="END_WHITEPAPER_LINK" /> kwa Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Mtumiaji:</translation>
<translation id="6934672428414710184">Jina hili linatoka kwenye Akaunti yako ya Google</translation>
<translation id="6944692733090228304">Uliweka nenosiri lako kwenye tovuti ambayo haisimamiwi na <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Ili kulinda akaunti yako, usitumie tena nenosiri lako kwenye programu na tovuti zingine.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> na nyingine <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> na nyingine <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Urujuani</translation>
<translation id="717330890047184534">Kitambulisho cha Gaia</translation>
+<translation id="7174545416324379297">Vimeunganishwa</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> na nyingine <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> na nyingine <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Seva ambako unaenda, <ph name="ORIGIN" />, imeomba kwamba
sera ya usalama itatumika katika maombi yake yote. Lakini badala ya
@@ -1164,6 +1185,7 @@
<translation id="7320336641823683070">Usaidizi kuhusu Muunganisho</translation>
<translation id="733354035281974745">Futa akaunti ya ndani ya kifaa</translation>
<translation id="7334320624316649418">Rudia Kupanga Upya</translation>
+<translation id="7337706099755338005">Haipatikani kwenye mfumo wako.</translation>
<translation id="733923710415886693">Cheti cha seva hakikufichuliwa kupitia Uwazi wa Cheti.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Ni mshirika:</translation>
@@ -1195,7 +1217,6 @@
<translation id="7440140511386898319">Gundua ukiwa nje ya mtandao</translation>
<translation id="7441627299479586546">Kichwa cha sera kisichofaa</translation>
<translation id="7442725080345379071">Chungwa Isiyokolea</translation>
-<translation id="7444046173054089907">Tovuti hii imezuiwa</translation>
<translation id="7445762425076701745">Utambulisho wa seva ambayo umejiunga kwayo hauwezi kuhalalishwa kikamilifu. Umeunganishwa kwenye seva kwa kutumia jina ambalo ni halali tu katika mtandao wako, ambalo mamlaka ya cheti cha nje hayana njia ya kuhalalisha umiliki wake. Kama baadhi ya mamlaka ya cheti yatatoa vyeti vya majina haya bila kujali, hakuna njia ya kuhakikisha umeunganishwa kwenye tovuti inayohitajika na sio mshambulizi.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Pata maelezo zaidi<ph name="END_LINK" /> kuhusu hitilafu hii.</translation>
<translation id="7455133967321480974">Tumia chaguomsingi la duniani (Zuia)</translation>
@@ -1217,9 +1238,9 @@
<translation id="7538364083937897561">A2 (Bahasha)</translation>
<translation id="7542403920425041731">Baada ya kuthibitisha, maelezo ya kadi yako yatashirikiwa na tovuti hii.</translation>
<translation id="7542995811387359312">Mjazo otomatiki wa kadi ya mkopo umelemazwa kwa sababu fomu hii haitumii muunganisho salama.</translation>
-<translation id="7543525346216957623">Muulize mzazi wako</translation>
<translation id="7548892272833184391">Rekebisha hitilafu za muunganisho</translation>
<translation id="7549584377607005141">Ukurasa huu wa wavuti unahitaji data ambayo uliingiza mapema ili ionyeshwe inavyostahili. Unaweza kutuma tena data hii, lakini kwa kufanya hivyo utarudia hatua yoyote ambayo ukurasa huu ulifanya hapo awali.</translation>
+<translation id="7550637293666041147">Jina lako la mtumiaji wa kifaa na jina lako la mtumiaji wa Chrome</translation>
<translation id="7552846755917812628">Jaribu vidokezo vinavyofuata:</translation>
<translation id="7554791636758816595">Kichupo Kipya</translation>
<translation id="7564049878696755256">Unaweza kupoteza uwezo wa kufikia Akaunti yako ya <ph name="ORG_NAME" /> au kuibiwa utambulisho. Chrome inapendekeza ubadilishe nenosiri lako sasa.</translation>
@@ -1234,6 +1255,7 @@
<translation id="7610193165460212391">Thamani imezidi masafa<ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Muda wa matumizi utakwisha: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Tayari una data ambayo imesimbwa kwa fiche kwa kutumia toleo tofauti la nenosiri lako la Akaunti ya Google. Tafadhali liingize hapo chini.</translation>
+<translation id="7625784245512586808">Ulinzi wa Hatari wa Chrome Enterprise</translation>
<translation id="7633909222644580952">Ripoti za utendaji na programu kuacha kufanya kazi</translation>
<translation id="7637571805876720304">Je, ungependa kuondoa kadi ya mikopo kwenye Chromium?</translation>
<translation id="7638605456503525968">Milango ya kuingiza</translation>
@@ -1246,7 +1268,6 @@
<translation id="7668654391829183341">Kifaa kisichojulikana</translation>
<translation id="7669271284792375604">Wavamizi kwenye tovuti hii wanaweza kujaribu kukulaghai kusakinisha programu zinazoathiri hali yako ya kuvinjari (kwa mfano, kwa kubadilisha ukurasa wako wa kwanza au kwa kuonyesha matangazo ya ziada kwenye tovuti unazotembelea).</translation>
<translation id="7676643023259824263">Tafuta maandishi ya ubao wa kunakili, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Mfumo na Wingu</translation>
<translation id="7681101578153515023">Badilisha Mtambo wa Kutafuta</translation>
<translation id="7682287625158474539">Anwani ya Kufikishia</translation>
<translation id="7687186412095877299">Hujaza fomu za malipo kwa kutumia njia za kulipa ulizohifadhi</translation>
@@ -1261,7 +1282,6 @@
<translation id="7723047071702270851">Badilisha Kadi</translation>
<translation id="774634243536837715">Maudhui hatari yamezuiwa.</translation>
<translation id="7752995774971033316">Haidhibitiwi</translation>
-<translation id="7755287808199759310">Mzazi wako anaweza kukuondolea kizuizi</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Huenda muunganisho huu umezuiwa na kinga mtandao au kingavirusi.</translation>
<translation id="7759163816903619567">Onyesha kikoa:</translation>
@@ -1305,7 +1325,6 @@
<translation id="8004582292198964060">Kivinjari</translation>
<translation id="8009225694047762179">Dhibiti Manenosiri</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Tutahifadhi maelezo ya kadi hii pamoja na anwani yake ya kutuma bili. Utaweza kuitumia utakapoingia katika akaunti ya <ph name="USER_EMAIL" />.}other{Tutahifadhi maelezo ya kadi hizi pamoja na anwani za kutuma bili. Utaweza kuzitumia utakapoingia katika akaunti ya <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Hatukuweza kuwafikia wazazi wako wakati huu. Tafadhali jaribu tena.</translation>
<translation id="8025119109950072390">Wavamizi kwenye tovuti hii wanaweza kukulaghai ili ufanye kitu hatari kama vile kusakinisha programu au kuonyesha maelezo yako binafsi (kwa mfano, manenosiri, nambari za simu au kadi za mikopo).</translation>
<translation id="8034522405403831421">Ukurasa huu ni wa lugha ya <ph name="SOURCE_LANGUAGE" />. Je, ungependa kuutasfiri kuwa <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Kalamu</translation>
@@ -1316,6 +1335,7 @@
<translation id="8041940743680923270">Tumia chaguomsingi la duniani (Uliza)</translation>
<translation id="8042918947222776840">Chagua Mbinu ya Kuchukua Bidhaa</translation>
<translation id="8057711352706143257">Haikuweka mipangilio ya "<ph name="SOFTWARE_NAME" />" kwa njia sahihi. Kwa kawaida, kuondoa "<ph name="SOFTWARE_NAME" />" hurekebisha tatizo hili. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Hutahitaji kuweka msimbo wa usalama wa kadi kuanzia sasa</translation>
<translation id="8066955247577885446">Samahani, hitilafu fulani imetokea.</translation>
<translation id="8074253406171541171">10x13 (Bahasha)</translation>
<translation id="8078141288243656252">Huwezi kuweka vidokezo ikiwa imezungushwa</translation>
@@ -1346,6 +1366,7 @@
<translation id="8211406090763984747">Muunganisho ni salama</translation>
<translation id="8218327578424803826">Mahali Palipohawilishwa:</translation>
<translation id="8220146938470311105">C7/C6 (Bahasha)</translation>
+<translation id="8220639454292072926">Kuripoti katika Shirika</translation>
<translation id="8225771182978767009">Mtu ambaye aliweka mipangilio ya kompyuta hii ameamua kuzuia tovuti hii.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Fungua ukurasa kwenye kichupo fiche kipya</translation>
@@ -1398,24 +1419,24 @@
<translation id="8508648098325802031">Aikoni ya Utafutaji</translation>
<translation id="8522552481199248698">Chrome inaweza kukusaidia kulinda Akaunti yako ya Google na kubadilisha nenosiri lako.</translation>
<translation id="8543181531796978784">Unaweza <ph name="BEGIN_ERROR_LINK" />kuripoti tatizo la ugunduzi<ph name="END_ERROR_LINK" /> au, ikiwa unaelewa kiwango cha hatari kinachoweza kutokea, <ph name="BEGIN_LINK" />tembelea tovuti hii isiyo salama<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Je, una maswali? Wasiliana na msimamizi wa wasifu wako.</translation>
<translation id="8553075262323480129">Tafsiri imeshindwa kwa sababu lugha ya ukurasa isingeweza kuthibitishwa.</translation>
<translation id="8557066899867184262">CVC inapatikana nyuma ya kadi yako.</translation>
<translation id="8559762987265718583">Muunganisho wa faragha kwenye <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> hauwezi kupatikana kwa sababu tarehe na wakati wa kifaa chako (<ph name="DATE_AND_TIME" />) si sahihi.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> tovuti inayotiliwa shaka</translation>
<translation id="8564985650692024650">Chromium inapendekeza ubadilishe nenosiri lako la <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ikiwa ulilitumia tena kwenye tovuti zingine.</translation>
<translation id="8571890674111243710">Inatafsiri ukurasa katika <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Ongeza simu
</translation>
-<translation id="859285277496340001">Cheti hakibainishi utaratibu wa kuangalia iwapo kimekataliwa.</translation>
<translation id="860043288473659153">Jina la mmiliki wa kadi</translation>
<translation id="861775596732816396">Ukubwa wa 4</translation>
-<translation id="8620436878122366504">Wazazi wako bado hawajaiidhinisha</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Hifadhi Maelezo ya Kadi Hii kwenye Kifaa Hiki</translation>
<translation id="8626112503828625890">Je, ungependa kuhifadhi maelezo ya bili kwenye Akaunti ya Google?</translation>
+<translation id="8647750283161643317">Rudisha zote katika chaguomsingi</translation>
<translation id="8663226718884576429">Muhtasari wa Agizo, <ph name="TOTAL_LABEL" />, Maelezo Zaidi</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, jibu, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Inapatikana</translation>
<translation id="8703575177326907206">Muunganisho wako kwa <ph name="DOMAIN" /> haujasimbwa.</translation>
<translation id="8718314106902482036">Malipo hayajakamilishwa</translation>
<translation id="8719263113926255150"><ph name="ENTITY" /> , <ph name="DESCRIPTION" /> , pendekezo la utafutaji</translation>
@@ -1426,6 +1447,7 @@
<translation id="8738058698779197622">Ili kutambua muunganisho salama, saa yako inahitaji kuwekwa sahihi. Hii ni kwa sababu vyeti ambavyo tovuti hutumia kujitambua ni sahihi kwa vipindi mahususi pekee. Kwa kuwa saa ya kifaa chako si sahihi, Chromium haiwezi kuthibitisha vyeti hivi.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;anwani ya DNS&lt;/abbr&gt; haikupatikana. Tatizo linachunguzwa.</translation>
<translation id="874846938927089722">Kadi za Mikopo na za Kulipia Awali Zinazokubaliwa</translation>
+<translation id="874918643257405732">Alamisha kichupo hiki</translation>
<translation id="8759274551635299824">Muda wa matumizi wa kadi hii umekwisha</translation>
<translation id="8761567432415473239">Kuvinjari Salama kwa Google <ph name="BEGIN_LINK" />kulipata programu zinazodhuru<ph name="END_LINK" /> kwenye <ph name="SITE" /> hivi karibuni.</translation>
<translation id="8763927697961133303">Kifaa cha USB</translation>
@@ -1455,6 +1477,7 @@
<translation id="8938939909778640821">Kadi za mikopo na za kulipia awali zinazokubaliwa</translation>
<translation id="8943282376843390568">Chokaa</translation>
<translation id="8957210676456822347">Uidhinishaji wa Ukurasa wa Wavuti</translation>
+<translation id="8962950042226115166">Tovuti inayotiliwa shaka</translation>
<translation id="8968766641738584599">Hifadhi kadi</translation>
<translation id="8971063699422889582">Cheti cha seva kimechina.</translation>
<translation id="8975012916872825179">Hujumuisha maelezo kama nambari za simu, anwani za barua pepe na anwani za mahali bidhaa zitakapopelekwa</translation>
@@ -1477,24 +1500,24 @@
<translation id="9035022520814077154">Hitilafu ya usalama</translation>
<translation id="9038649477754266430">Tumia huduma ya kutabiri ili upakie kurasa kwa haraka zaidi</translation>
<translation id="9039213469156557790">Mbali na hayo, ukurasa huu una rasilimali nyingine zisizo salama. Rasilimali hizi zinaweza kuangaliwa na watu wengine wanaosafiri, na zinaweza kurekebishwa na mvamizi kubadilisha tabia ya ukurasa.</translation>
+<translation id="9044359186343685026">Tumia Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Ulijaribu kufikia <ph name="DOMAIN" />, lakini seva iliwasilisha cheti batili.</translation>
<translation id="9050666287014529139">Kaulisiri</translation>
<translation id="9065203028668620118">Badilisha</translation>
<translation id="9065745800631924235"><ph name="TEXT" /> tafuta kwenye historia</translation>
<translation id="9069693763241529744">Imezuiwa na kiendelezi</translation>
-<translation id="9076283476770535406">Huenda ina maudhui ya ngono</translation>
<translation id="9076630408993835509">Kivinjari hiki hakidhibitiwi na kampuni au shirika lingine. Huenda shughuli kwenye kifaa hiki zinadhibitiwa nje ya Chrome. <ph name="BEGIN_LINK" />Pata Maelezo Zaidi<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Maelezo zaidi yanahitajika</translation>
<translation id="9080712759204168376">Muhtasari wa Agizo</translation>
<translation id="9089260154716455634">Sera ya Saa Zisizo za Kazi:</translation>
<translation id="9095388113577226029">Lugha zaidi...</translation>
+<translation id="9098981495403789647">Msimamizi wako amewasha kipengele cha Ulinzi wa Hatari cha Chrome Enterprise kwenye kivinjari chako. Kipengele cha Ulinzi wa Hatari cha Chrome Enterprise kina uwezo wa kufikia baadhi ya data yako.</translation>
<translation id="9103872766612412690">Kwa kawaida <ph name="SITE" /> hutumia usimbaji fiche ili kulinda maelezo yako. Chromium ilipojaribu kuunganisha kwenye <ph name="SITE" /> wakati huu, tovuti ilituma kitambulisho kisicho cha kawaida na kisicho sahihi. Hili linaweza kutokea mvamizi anapojaribu kujifanya kuwa <ph name="SITE" />, au uchanganuzi wa kuingia katika Wi-Fi umeingilia muunganisho. Maelezo yako yangali salama kwa sababu Chromium ilisimamisha muunganisho kabla data yoyote itumwe.</translation>
<translation id="9106062320799175032">Ongeza Anwani ya Kutuma Bili</translation>
<translation id="9114524666733003316">Inathibitisha kadi…</translation>
<translation id="9128870381267983090">Unganisha kwenye mtandao</translation>
<translation id="9137013805542155359">Onyesha asili</translation>
-<translation id="9137248913990643158">Tafadhali anza na uingie katika Chrome kabla ya kutumia programu hii.</translation>
<translation id="9141013498910525015">Dhibiti anwani</translation>
<translation id="9148088599418889305">Chagua Mbinu ya Usafirishaji</translation>
<translation id="9148507642005240123">Tendua kuhariri</translation>
diff --git a/chromium/components/strings/components_strings_ta.xtb b/chromium/components/strings/components_strings_ta.xtb
index 1adbfcc8350..91d4ce845c6 100644
--- a/chromium/components/strings/components_strings_ta.xtb
+++ b/chromium/components/strings/components_strings_ta.xtb
@@ -10,7 +10,7 @@
<translation id="1036348656032585052">முடக்கு</translation>
<translation id="1038842779957582377">அறியப்படாத பெயர்</translation>
<translation id="1039626062703039346">உங்கள் Google கணக்கைப் பாதுகாக்கவும் கடவுச்சொல்லை மாற்றவும் Chrome உதவும். இந்தத் தளம் குறித்து Googleளுக்குத் தெரியப்படுத்தும்.</translation>
-<translation id="1050038467049342496">பிற பயன்பாடுகளை மூடவும்</translation>
+<translation id="1050038467049342496">பிற ஆப்ஸை மூடவும்</translation>
<translation id="1055184225775184556">&amp;சேர்த்தலைச் செயல்தவிர்</translation>
<translation id="1056898198331236512">எச்சரிக்கை</translation>
<translation id="1058479211578257048">கார்டுகளைச் சேமிக்கிறது...</translation>
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">கார்டிலுள்ள பெயரைச் சேர்க்கவும்</translation>
<translation id="1089439967362294234">கடவுச்சொல்லை மாற்று</translation>
+<translation id="1096545575934602868">இதில் <ph name="MAX_ITEMS_LIMIT" /> உள்ளீடுகளுக்கு மேல் இருக்கக்கூடாது. மீதமிருக்கும் அனைத்தும் நிராகரிக்கப்படும்.</translation>
<translation id="109743633954054152">Chrome அமைப்புகளில் கடவுச்சொற்களை நிர்வகிக்கவும்</translation>
<translation id="1103523840287552314">எப்போதும் இந்த மொழியை மொழிபெயர் <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">இது தேர்ந்தெடுக்கப்பட்டால், விரைவாக படிவங்களை நிரப்புவதற்காக, Chrome இந்த கார்டின் பிரதியை சாதனத்தில் சேமிக்கும்.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> இன் <ph name="BEGIN_LINK" />தற்காலிகச் சேமிப்பு நகலை<ph name="END_LINK" /> அணுகவும்</translation>
<translation id="1156303062776767266">அகக் கோப்பு அல்லது பகிரப்பட்ட கோப்பைப் பார்க்கிறீர்கள்</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> எதிர்பாராத விதமாக இணைப்பை நிறுத்தியது.</translation>
+<translation id="115926840831309955">உங்கள் CVCயைச் சரிபார்த்து மீண்டும் முயலவும் அல்லது காலாவதித் தேதியை மாற்றவும்</translation>
<translation id="1161325031994447685">வைஃபையுடன் மீண்டும் இணைத்தல்</translation>
<translation id="1165039591588034296">பிழை</translation>
<translation id="1175364870820465910">&amp;அச்சிடு...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"உங்கள் கம்ப்யூட்டரில் உள்ள மென்பொருள் இணையத்துடன் பாதுகாப்பாக இணைவதிலிருந்து Chromeமைத் தடுக்கிறது" (Windows கம்ப்யூட்டர்கள் மட்டும்)</translation>
<translation id="1294154142200295408">கட்டளை வரி மாற்று வடிவங்கள்</translation>
<translation id="129553762522093515">சமீபத்தில் மூடியவை</translation>
+<translation id="1298536327547837046">மால்வேர் ஸ்கேனிங்</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />குக்கீகளை அழிக்கவும்<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">தடுக்கப்பட்ட அம்சங்கள்</translation>
<translation id="1320233736580025032">Prc1 (என்வலப்)</translation>
<translation id="132301787627749051">கிளிப்-போர்டு படத்தைத் தேடும்</translation>
<translation id="1323433172918577554">மேலும் காட்டு</translation>
@@ -82,7 +86,7 @@
<ph name="END_LIST" /></translation>
<translation id="1339601241726513588">பதிவுக் களம்:</translation>
<translation id="1340482604681802745">பிக்கப் முகவரி</translation>
-<translation id="1348198688976932919">தளத்தில் ஆபத்தான பயன்பாடுகள் உள்ளன</translation>
+<translation id="1348198688976932919">தளத்தில் ஆபத்தான ஆப்ஸ் உள்ளன</translation>
<translation id="1348779747280417563">பெயரை உறுதிப்படுத்தவும்</translation>
<translation id="1357195169723583938">சமீபத்தில் சாதனத்தை யார், எப்போது பயன்படுத்தியது</translation>
<translation id="1364822246244961190">இந்தக் கொள்கை தடைசெய்யப்பட்டுள்ளது, இதன் மதிப்பு புறக்கணிக்கப்படும்.</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google விரிதாள்</translation>
<translation id="1527263332363067270">இணைப்பிற்காகக் காத்திருக்கிறது…</translation>
<translation id="1529521330346880926">10x15 (என்வலப்)</translation>
+<translation id="1530707389502320859">நீங்கள் சற்றுமுன் பார்வையிட முயற்சித்த தளம் போலியானதைப் போல் தெரிகிறது. சில நேரங்களில் கண்டுப்பிடிக்கவே முடியாத அளவிற்கு URLல் சிறிய அளவு மாற்றங்களைச் செய்து போலியான தளங்களை தீங்கிழைப்பவர்கள் உருவாக்குவார்கள்.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">இந்தப் பக்கம் தெரிவிப்பது:</translation>
<translation id="153384715582417236">அவ்வளவு தான்!</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">ஆவணம் மிகப் பெரிதாக இருப்பதால் அதில் விரிவுரையைச் சேர்க்க முடியாது</translation>
-<translation id="1721312023322545264">இந்தத் தளத்திற்குச் செல்ல, <ph name="NAME" /> இன் அனுமதி வேண்டும்</translation>
<translation id="1721424275792716183">* அவசியமான புலம்</translation>
<translation id="1727741090716970331">சரியான கார்டு எண்ணைச் சேர்க்கவும்</translation>
<translation id="1728677426644403582">இணையப் பக்கத்தின் மூலத்தைப் பார்க்கிறீர்கள்</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">நீங்கள் பார்வையிட்ட இணையதளங்களும் அவற்றில் செலவழித்த நேரமும்</translation>
<translation id="1826516787628120939">சரிபார்க்கிறது</translation>
<translation id="1834321415901700177">இந்தத் தளத்தில் தீங்கிழைக்கும் நிரல்கள் உள்ளன</translation>
+<translation id="1838374766361614909">தேடலை அழி</translation>
<translation id="1839551713262164453">கொள்கை மதிப்புகளின் சரிபார்ப்பு பிழைகளுடன் தோல்வியில் முடிந்தது.</translation>
<translation id="1842969606798536927">பணம் செலுத்துக</translation>
<translation id="1871208020102129563">நிலையான ப்ராக்ஸி சேவையகங்களைப் பயன்படுத்த ப்ராக்ஸி அமைக்கப்பட்டுள்ளது, .pac ஸ்கிரிப்ட் URL அல்ல.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">பட்டியலைச் சுருக்கு</translation>
<translation id="1898423065542865115">வடிகட்டுதல்</translation>
<translation id="1914326953223720820">ஜிப் கோப்புகளைத் திறக்கும் சேவை</translation>
+<translation id="1915697529809968049">CVCக்குப் பதிலாக Touch IDயைப் பயன்படுத்தவா?</translation>
<translation id="1916770123977586577">மாற்றிய அமைப்புகளை இந்தத் தளத்தில் பயன்படுத்த, பக்கத்தை மீண்டும் ஏற்றவும்</translation>
<translation id="1919345977826869612">விளம்பரங்கள்</translation>
<translation id="1919367280705858090">குறிப்பிட்ட பிழைச் செய்திக்கான உதவியைப் பெறுங்கள்</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> புக்மார்க்குகள்</translation>
<translation id="1973335181906896915">தொடராக்க பிழை</translation>
<translation id="1974060860693918893">மேம்பட்டவை</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />நீங்கள் பார்வையிட்ட சில பக்கங்களின் URLகளையும், வரம்பிற்குட்பட்ட சிஸ்டம் தகவல்களையும், சில பக்கங்களின் உள்ளடக்கத்தையும்<ph name="END_WHITEPAPER_LINK" /> Googleளுக்கு அனுப்புவதன் மூலம் Chrome பாதுகாப்பை மேம்படுத்த உதவுங்கள். <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">நிலைப்பொருளின் பதிப்பு</translation>
<translation id="1981206234434200693">Chromeமின் உலாவல் வரலாற்றுத் தரவை அழி</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{மேலும் 1}other{மேலும் #}}</translation>
@@ -246,10 +253,12 @@
<translation id="2202020181578195191">சரியான காலாவதி ஆண்டை உள்ளிடவும்</translation>
<translation id="2212735316055980242">கொள்கை காணப்படவில்லை</translation>
<translation id="2213606439339815911">உள்ளீடுகளைப் பெறுகிறது...</translation>
+<translation id="2215727959747642672">கோப்பைத் திருத்துதல்</translation>
<translation id="2218879909401188352">தற்போது <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> எனும் தளத்தில் உள்ள தீங்கிழைப்பவர்கள் உங்கள் சாதனத்தைச் சேதப்படுத்தும் ஆபத்தான ஆப்ஸை நிறுவலாம், மொபைல் கட்டணத்தில் மறைமுகக் கட்டணங்களைச் சேர்க்கலாம் அல்லது உங்கள் தனிப்பட்ட தகவலைத் திருடலாம். <ph name="BEGIN_LEARN_MORE_LINK" />மேலும் அறிக<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">இணைய இணைப்பு இல்லை</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />கண்டறியும் பயன்பாட்டைப்<ph name="END_LINK" /> பயன்படுத்தி இணைப்பைச் சரிசெய்யவும்</translation>
<translation id="2239100178324503013">இப்போதே அனுப்பு</translation>
+<translation id="2248949050832152960">WebAuthnனைப் பயன்படுத்து</translation>
<translation id="225207911366869382">இந்த கொள்கைக்கான மதிப்பு தடுக்கப்பட்டது.</translation>
<translation id="2257315177824333709">தற்போது உங்கள் கார்டு விவரங்களைச் சேமிக்க இயலாது</translation>
<translation id="2262243747453050782">HTTP பிழை</translation>
@@ -299,7 +308,6 @@
<translation id="2479410451996844060">தவறான தேடல் URL.</translation>
<translation id="2482878487686419369">அறிவிப்புகள்</translation>
<translation id="248348093745724435">சாதனக் கொள்கைகள்</translation>
-<translation id="2485387744899240041">உங்கள் சாதனம் மற்றும் உலாவியின் பயனர்பெயர்கள்</translation>
<translation id="2491120439723279231">சேவையகச் சான்றிதழில் பிழைகள் உள்ளன.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON பார்சர்</translation>
@@ -309,6 +317,7 @@
<translation id="2501278716633472235">திரும்பிச் செல்</translation>
<translation id="2503184589641749290">ஏற்கப்படும் டெபிட் மற்றும் ப்ரீபெய்டு கார்டுகள்</translation>
<translation id="2505268675989099013">கணக்கைப் பாதுகாத்திடு</translation>
+<translation id="2515335152965840738">புறக்கணி</translation>
<translation id="2515629240566999685">உங்கள் பகுதியில் உள்ள சிக்னலைச் சரிபார்த்தல்</translation>
<translation id="2523886232349826891">இந்தச் சாதனத்தில் மட்டும் சேமிக்கப்படும்</translation>
<translation id="2524461107774643265">மேலும் தகவலைச் சேர்க்கவும்</translation>
@@ -332,8 +341,7 @@
<translation id="2650446666397867134">கோப்பிற்கான அணுகல் மறுக்கப்பட்டது</translation>
<translation id="2653659639078652383">சமர்ப்பி</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{எதுவுமில்லை}=1{ஒரு கடவுச்சொல் (டொமைன்கள்: <ph name="DOMAIN_LIST" />)}=2{2 கடவுச்சொற்கள் (டொமைன்கள்: <ph name="DOMAIN_LIST" />)}other{# கடவுச்சொற்கள் (டொமைன்கள்: <ph name="DOMAIN_LIST" />)}}</translation>
-<translation id="2666117266261740852">பிற தாவல்கள் அல்லது பயன்பாடுகளை மூடவும்</translation>
-<translation id="267371737713284912">செயல்தவிர்க்க, <ph name="MODIFIER_KEY_DESCRIPTION" />ஐ அழுத்தவும்</translation>
+<translation id="2666117266261740852">பிற தாவல்கள் அல்லது ஆப்ஸை மூடவும்</translation>
<translation id="2674170444375937751">உங்கள் வரலாற்றிலிருக்கும் பக்கங்களை நிச்சயமாக நீக்க விரும்புகிறீர்களா?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">வெளியேறு</translation>
@@ -343,12 +351,12 @@
<translation id="2704283930420550640">மதிப்பானது வடிவமைப்பிற்குப் பொருந்தவில்லை.</translation>
<translation id="2705137772291741111">இந்தத் தளத்தின் சேமிக்கப்பட்ட (தற்காலிகச் சேமிப்பு) நகலைப் படிக்க முடியவில்லை.</translation>
<translation id="2709516037105925701">தானாகநிரப்பு</translation>
-<translation id="2712173769900027643">அனுமதி கேள்</translation>
<translation id="2713444072780614174">வெள்ளை</translation>
<translation id="2720342946869265578">அருகிலுள்ளவை</translation>
<translation id="2721148159707890343">கோரிக்கை வெற்றியடைந்தது</translation>
<translation id="2728127805433021124">சேவையகச் சான்றிதழ் ஒரு வலுவற்ற கையொப்ப அல்காரிதமைப் பயன்படுத்தி கையொப்பமிடப்பட்டுள்ளது.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />கனெக்டிவிட்டி டயக்னஸ்டிக்ஸ் கருவியை இயக்கவும்<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">இந்த அம்சங்களை இயக்கினால் நீங்கள் உலாவிய தரவை இழக்கக்கூடும், உங்கள் பாதுகாப்பு அல்லது தனியுரிமையில் சிக்கல் ஏற்படக்கூடும். இயக்கிய அம்சங்கள் இந்த உலாவியின் எல்லாப் பயனர்களுக்கும் பொருந்தும்.</translation>
<translation id="2735043616039983645">பொருந்தாத மதிப்புகளைக் கொண்ட ஒன்றுக்கும் மேற்பட்ட மூலங்கள் இந்தக் கொள்கையில் உள்ளன!</translation>
<translation id="2738330467931008676">பிக்அப் முகவரியைத் தேர்வு செய்</translation>
<translation id="2740531572673183784">சரி</translation>
@@ -359,16 +367,15 @@
<translation id="2784949926578158345">இணைப்பு மீட்டமைக்கப்பட்டது.</translation>
<translation id="2788784517760473862">ஏற்கப்படும் கிரெடிட் கார்டுகள்</translation>
<translation id="2792012897584536778">இந்தச் சாதனத்தின் நிர்வாகிகள் பாதுகாப்புச் சான்றிதழ்களை அமைத்துள்ளனர். இவற்றின் மூலம் நீங்கள் சென்ற இணையதளங்களின் உள்ளடக்கத்தை அவர்கள் பார்க்கக்கூடும்.</translation>
-<translation id="2794233252405721443">தளம் தடுக்கப்பட்டது</translation>
-<translation id="2799020568854403057">தளத்தில் தீங்கிழைக்கும் பயன்பாடுகள் உள்ளன</translation>
+<translation id="2799020568854403057">தளத்தில் தீங்கிழைக்கும் ஆப்ஸ் உள்ளன</translation>
<translation id="2799223571221894425">மீண்டும் தொடங்கு</translation>
<translation id="2803306138276472711">Google பாதுகாப்பு உலாவலானது சமீபத்தில் <ph name="SITE" /> இல் <ph name="BEGIN_LINK" />தீம்பொருள் உள்ளதைக் கண்டுபிடித்தது<ph name="END_LINK" />. இயல்பாகவே பாதுகாப்பாக இருக்கும் இணையதளங்களும் சில சமயங்களில் தீம்பொருளினால் பாதிக்கப்பட்டிருக்கும்.</translation>
+<translation id="2815364696811431560">தளத்திலிருந்து வெளியேறு</translation>
<translation id="2824775600643448204">முகவரி மற்றும் தேடல் பட்டி</translation>
<translation id="2826760142808435982">இந்த இணைப்பு <ph name="CIPHER" /> ஐப் பயன்படுத்தி என்க்ரிப்ட் செய்யப்பட்டு அங்கீகரிக்கப்பட்டது, ஒரு முக்கிய பரிமாற்ற செயல்முறையாக <ph name="KX" /> ஐப் பயன்படுத்துகிறது.</translation>
<translation id="2835170189407361413">படிவத்தை அழி</translation>
<translation id="2847118875340931228">மறைநிலை சாளரத்தைத் திற</translation>
<translation id="2850739647070081192">Invite (என்வலப்)</translation>
-<translation id="2851634818064021665">இந்தத் தளத்தைப் பார்ப்பதற்கு அனுமதி தேவை</translation>
<translation id="2856444702002559011"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> தளத்திலிருந்து ஹேக்கர்கள் உங்கள் தகவலை (எடுத்துக்காட்டாக, கடவுச்சொற்கள், செய்திகள் அல்லது கிரெடிட் கார்டுகள்) திருட முயற்சிக்கக்கூடும். <ph name="BEGIN_LEARN_MORE_LINK" />மேலும் அறிக<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">கார்டைச் சேமிக்கவா?</translation>
@@ -393,6 +400,7 @@
<translation id="2985306909656435243">இது இயக்கப்பட்டால், விரைவாகப் படிவத்தை நிரப்ப, உங்கள் கார்டின் நகலை Chromium இந்தச் சாதனத்தில் சேமிக்கும்.</translation>
<translation id="2985398929374701810">சரியான முகவரியை உள்ளிடவும்</translation>
<translation id="2986368408720340940">இந்தப் பிக்அப் முறை இல்லை. வேறு முறையைப் பயன்படுத்திப் பார்க்கவும்.</translation>
+<translation id="2987034854559945715">பொருந்தும் அம்சங்கள் இல்லை</translation>
<translation id="2991174974383378012">இணையதளங்களுடன் பகிர்பவை</translation>
<translation id="2991571918955627853">இணையதளமானது HSTSஸைப் பயன்படுத்துவதால், தற்போது <ph name="SITE" />ஐப் பார்க்க முடியாது. பொதுவாக நெட்வொர்க் பிழைகளும் பாதிப்புகளும் தற்காலிகமானவை என்பதால், இந்தப் பக்கம் பின்னர் சரியாகச் செயல்படக்கூடும்.</translation>
<translation id="3005723025932146533">சேமித்த நகலைக் காட்டு</translation>
@@ -403,6 +411,7 @@
<translation id="3024663005179499861">தவறான கொள்கை வகை</translation>
<translation id="3037605927509011580">அச்சச்சோ!</translation>
<translation id="3041612393474885105">சான்றிதழ் தகவல்</translation>
+<translation id="3057676462092457419">DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> பயன்முறையைப் பயன்படுத்த இயலாது, இது <ph name="SECURE_DNS_MODE_OFF" /> என்று அமைக்கப்பட்டுள்ளது.</translation>
<translation id="3060227939791841287">C9 (என்வலப்)</translation>
<translation id="3061707000357573562">பேட்ச் சேவை</translation>
<translation id="3064966200440839136">வெளிப்புற ஆப்ஸின் மூலம் பணத்தை செலுத்த, மறைநிலையிலிருந்து வெளியேறுகிறீர்கள். தொடரவா?</translation>
@@ -425,6 +434,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> இல் <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">கட்டணம் செலுத்துவதை ரத்துசெய்</translation>
<translation id="3207960819495026254">புக்மார்க் செய்யப்பட்டது</translation>
+<translation id="3209034400446768650">இந்தப் பக்கத்திற்குச் சென்றால் கட்டணம் விதிக்கக்கூடும்</translation>
<translation id="3225919329040284222">உள்ளமைந்த எதிர்பார்ப்புகளுடன் பொருந்தாத சான்றிதழை சேவையகம் வழங்கியது. சில உயர்-பாதுகாப்பு வலைத்தளங்களில் உங்களைப் பாதுகாக்கவே இந்த எதிர்பார்ப்புகள் சேர்க்கப்படுகின்றன.</translation>
<translation id="3226128629678568754">பக்கத்தை ஏற்ற தேவைப்படும் தரவை மறுமுறைச் சமர்ப்பிப்பதற்கு மீண்டும் ஏற்று என்ற பொத்தானை அழுத்துக.</translation>
<translation id="3227137524299004712">மைக்ரோஃபோன்</translation>
@@ -432,7 +442,6 @@
<translation id="3229041911291329567">உங்கள் சாதனம் மற்றும் உலாவியின் பதிப்புத் தகவல்</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> இன் CVC எண்ணை உள்ளிடவும்</translation>
<translation id="3234666976984236645">இந்தத் தளத்தின் முக்கிய உள்ளடக்கத்தை எப்போதும் இயக்கவும்</translation>
-<translation id="3254409185687681395">இந்தப் பக்கத்தை புக்மார்க் செய்க</translation>
<translation id="3270847123878663523">&amp;மறுவரிசைப்படுத்தலைச் செயல்தவிர்</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">கார்டிலுள்ள பெயரைச் சேர்க்கவும்</translation>
@@ -442,7 +451,6 @@
<translation id="3320021301628644560">பில்லிங் முகவரியைச் சேர்க்கவும்</translation>
<translation id="3324983252691184275">அடர்சிவப்பு</translation>
<translation id="3338095232262050444">பாதுகாப்பானது</translation>
-<translation id="3345135638360864351">இந்தத் தளத்தை அணுகுவதற்கான கோரிக்கையை <ph name="NAME" />க்கு அனுப்ப முடியவில்லை. மீண்டும் முயலவும்.</translation>
<translation id="3355823806454867987">ப்ராக்ஸி அமைப்புகளை மாற்றுக...</translation>
<translation id="3361596688432910856">பின்வரும் தகவலை Chrome <ph name="BEGIN_EMPHASIS" />சேமிக்காது<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -476,17 +484,14 @@
<translation id="3462200631372590220">மேம்பட்டவையை மறை</translation>
<translation id="3467763166455606212">கார்டு உரிமையாளரின் பெயர் தேவை</translation>
<translation id="3468054117417088249">தற்போது திறந்துள்ள <ph name="TAB_SWITCH_SUFFIX" /> தாவலுக்கு மாற, ‘தாவல்’ மாற்ற பட்டனைத் தட்டி, ‘எண்டர்’ பட்டனை அழுத்தவும்</translation>
-<translation id="3479539252931486093">இதை எதிர்பார்க்கவில்லையா? <ph name="BEGIN_LINK" />எங்களுக்குத் தெரியப்படுத்தவும்<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">இப்பொழுது இல்லை</translation>
<translation id="3484560055331845446">உங்கள் Google கணக்கிற்கான அணுகலை நீங்கள் இழக்கக்கூடும். இப்போதே உங்கள் கடவுச்சொல்லை மாற்றுமாறு Chrome பரிந்துரைக்கிறது. அதற்கு நீங்கள் உள்நுழைய வேண்டும்.</translation>
<translation id="3495081129428749620"><ph name="PAGE_TITLE" /> பக்கத்தில் கண்டறிக</translation>
-<translation id="3498215018399854026">தற்போது உங்கள் பெற்றோரைத் தொடர்புகொள்ள முடியவில்லை. மீண்டும் முயற்சிக்கவும்.</translation>
<translation id="3512163584740124171">அதே கொள்கை வகையைச் சார்ந்த வேறொன்று அதிக முக்கியத்துவம் வாய்ந்தது என்பதால் இந்தக் கொள்கை ஏற்றுக் கொள்ளப்படவில்லை.</translation>
<translation id="3528171143076753409">சேவையகச் சான்றிதழ் நம்பப்படவில்லை.</translation>
<translation id="3528485271872257980">அடர் பழுப்பு</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{ஒத்திசைத்த சாதனங்களில் குறைந்தது 1 உருப்படி உள்ளது}=1{1 உருப்படி (ஒத்திசைத்த சாதனங்களில் இதற்கு மேல் உள்ளன)}other{# உருப்படிகள் (ஒத்திசைத்த சாதனங்களில் இதற்கு மேல் உள்ளன)}}</translation>
<translation id="3539171420378717834">இந்தக் கார்டின் பிரதியை சாதனத்தில் சேமி</translation>
-<translation id="3556433843310711081">உங்களுக்காக, தளத்தின் தடுப்பை உங்கள் நிர்வாகி நீக்க முடியும்</translation>
<translation id="3566021033012934673">உங்கள் இணைப்பு தனிப்பட்டது அல்ல</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> இல் உள்ள உட்பொதிக்கப்பட்ட பக்கம் தெரிவிப்பது:</translation>
@@ -514,6 +519,7 @@
<translation id="3678529606614285348">புதிய மறைநிலைச் சாளரத்தில் பக்கத்தைத் திறக்கவும் (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375"><ph name="CRASH_TIME" /> அன்று சிதைவு அறிக்கை பதிவுசெய்யப்பட்டு, <ph name="UPLOAD_TIME" /> அன்று பதிவேற்றப்பட்டது</translation>
<translation id="3681007416295224113">சான்றிதழ் தகவல்</translation>
+<translation id="3701427423622901115">மீட்டமைத்தல் ஏற்கப்பட்டது.</translation>
<translation id="3704162925118123524">நீங்கள் பயன்படுத்திக் கொண்டிருக்கும் நெட்வொர்க், அதன் உள்நுழைவுப் பக்கத்தை நீங்கள் பார்க்கக் கோரலாம்.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">ஏற்றுகிறது…</translation>
@@ -530,6 +536,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> தளத்திலுள்ள ஹேக்கர்கள் மென்பொருளை நிறுவுவது அல்லது உங்கள் தனிப்பட்ட தகவலை (எடுத்துக்காட்டாக, கடவுச்சொற்கள், ஃபோன் எண்கள் அல்லது கிரெடிட் கார்டுகள்) திருடுவது போன்ற ஆபத்தான காரணங்களில் ஈடுபடக்கூடும். <ph name="BEGIN_LEARN_MORE_LINK" />மேலும் அறிக<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">ஒரு சேவையகப் பிழையின் காரணமாக மொழிபெயர்ப்புத் தோல்வியடைந்தது.</translation>
<translation id="3759461132968374835">உங்களிடம் சமீபத்தில் செயலிழப்புகள் எதுவும் புகாரளிக்கப்படவில்லை. செயலிழப்பு புகாரளித்தல் முடக்கப்பட்டிருந்தபோது ஏற்பட்ட செயலிழப்புகள் இங்கு காண்பிக்கப்படாது.</translation>
+<translation id="3760561303380396507">CVCக்குப் பதிலாக Windows Helloவைப் பயன்படுத்தவா?</translation>
<translation id="3761718714832595332">நிலையை மறை</translation>
<translation id="3765032636089507299">பாதுகாப்பு உலாவல் பக்கம் உருவாக்கப்படுகிறது.</translation>
<translation id="3778403066972421603">கார்டை உங்கள் Google கணக்கிலும் இந்தச் சாதனத்திலும் சேமிக்க விரும்புகிறீர்களா?</translation>
@@ -539,6 +546,7 @@
<translation id="3789155188480882154">அளவு: 16</translation>
<translation id="3797522431967816232">Prc3 (என்வலப்)</translation>
<translation id="3807873520724684969">தீங்கிழைக்கும் உள்ளடக்கம் தடுக்கப்பட்டது.</translation>
+<translation id="3808375843007691220">எச்சரிக்கை: சோதனை அம்சங்கள்!</translation>
<translation id="3810973564298564668">நிர்வகி</translation>
<translation id="382518646247711829">நீங்கள் பிராக்சி சர்வரைப் பயன்படுத்தினால்....</translation>
<translation id="3828924085048779000">வெற்று கடவுச்சொற்றொடருக்கு அனுமதியில்லை.</translation>
@@ -547,11 +555,11 @@
<translation id="3858027520442213535">தேதியையும் நேரத்தையும் புதுப்பி</translation>
<translation id="3884278016824448484">முரண்பாடான சாதன அடையாளங்காட்டி</translation>
<translation id="3885155851504623709">வட்டாரம்</translation>
-<translation id="3886446263141354045">இந்தத் தளத்தை அணுகுவதற்கான உங்கள் கோரிக்கை <ph name="NAME" />க்கு அனுப்பப்பட்டது</translation>
<translation id="3890664840433101773">மின்னஞ்சலைச் சேர்</translation>
<translation id="3901925938762663762">கார்டு காலாவதியானது</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVCக்கு பதிலாக WebAuthnனைப் பயன்படுத்தவா?</translation>
<translation id="3946209740501886391">இந்தத் தளத்தில் எப்போதும் கேள்</translation>
<translation id="3949571496842715403">இது <ph name="DOMAIN" /> தான் என்பதை, இந்தச் சேவையகத்தால் உறுதிப்படுத்த முடியவில்லை; பொருள் மாற்றுப் பெயர்களை அதன் பாதுகாப்புச் சான்றிதழ் குறிப்பிடவில்லை. இது தவறான உள்ளமைவினால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
<translation id="3949601375789751990">உலாவல் வரலாறு இங்கே தோன்றும்</translation>
@@ -562,11 +570,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ஏதுமில்லை}=1{1 தளத்திலிருந்து }other{# தளங்களிலிருந்து }}</translation>
<translation id="397105322502079400">கணக்கிடுகிறது...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> தடுக்கப்பட்டுள்ளது</translation>
+<translation id="3981540111851280311">உங்கள் உலாவியில் Chrome Enterprise Threat Protectionனை <ph name="ENROLLMENT_DOMAIN" /> இயக்கியுள்ளது. உங்களின் சில தரவை Chrome Enterprise Threat Protectionனால் அணுக முடியும்.</translation>
<translation id="3987940399970879459">1 மெ.பை. அளவை விடக் குறைவாக உள்ளது</translation>
<translation id="40103911065039147">{URL_count,plural, =1{அருகில் ஒரு இணையப் பக்கம் உள்ளது}other{அருகில் # இணையப் பக்கங்கள் உள்ளன}}</translation>
<translation id="4030383055268325496">&amp;சேர்த்தலைச் செயல்தவிர்</translation>
<translation id="4032320456957708163">உங்கள் உலாவியை <ph name="ENROLLMENT_DOMAIN" /> நிர்வகிக்கிறது</translation>
-<translation id="4034375457890803692">நீங்கள் வழக்கமாகப் பார்க்காத இணையதளத்திற்கு இந்த இணைப்பு செல்கிறது. இது உங்களைக் குழப்புவதற்காக இருக்கலாம்.</translation>
<translation id="4058922952496707368">விசை "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (என்வலப்)</translation>
<translation id="4067947977115446013">சரியான முகவரியைச் சேர்க்கவும்</translation>
@@ -579,6 +587,7 @@
<translation id="4103249731201008433">சாதன சீரியல் எண் தவறானது</translation>
<translation id="410351446219883937">தானியங்கி</translation>
<translation id="4103763322291513355">ஏற்கத்தகாத URLகளின் பட்டியலையும் உங்கள் கணினி நிர்வாகியால் செயற்படுத்தப்படும் பிற கொள்கைகளையும் காண &lt;strong&gt;chrome://policy&lt;/strong&gt; ஐப் பார்வையிடவும்.</translation>
+<translation id="4108231218301530806">அடுத்த முறை இந்தக் கார்டை சரிபார்க்க கைரேகையைப் பயன்படுத்தவும்.</translation>
<translation id="4110652170750985508">உங்கள் கட்டணத்தை மதிப்பாய்வு செய்யவும்</translation>
<translation id="4112140312785995938">பின்செல்</translation>
<translation id="4116663294526079822">இந்தத் தளத்தில் எப்போதும் அனுமதி</translation>
@@ -593,6 +602,7 @@
<translation id="4171400957073367226">தவறான சரிபார்ப்பு கையொப்பம்</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{மேலும் <ph name="ITEM_COUNT" /> உருப்படி}other{மேலும் <ph name="ITEM_COUNT" /> உருப்படிகள்}}</translation>
+<translation id="4176463684765177261">முடக்கப்பட்டது</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">அடுத்த முறை விரைவாகப் பணம் செலுத்த கார்டு விவரங்களையும் பில்லிங் முகவரியையும் Google கணக்கில் சேமிக்கவும்.</translation>
<translation id="4196861286325780578">&amp;நகர்த்தலை மீண்டும் செய்</translation>
@@ -629,6 +639,7 @@
<translation id="4277028893293644418">கடவுச்சொல்லை மீட்டமை</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" />ஐ நிர்வகிப்பது: <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{இந்தக் கார்டு உங்கள் Google கணக்கில் சேமிக்கப்பட்டது}other{இந்தக் கார்டுகள் உங்கள் Google கணக்கில் சேமிக்கப்பட்டன}}</translation>
+<translation id="428847186335018806">Chromeமில் நீங்கள் பதிவேற்றும் அல்லது பதிவிறக்கும் கோப்புகளை ஸ்கேன் செய்யும்.</translation>
<translation id="42981349822642051">விரி</translation>
<translation id="4302965934281694568">Chou3 (என்வலப்)</translation>
<translation id="4305817255990598646">மாறு</translation>
@@ -658,7 +669,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">ப்ராக்ஸி பயன்பாடு முடக்கப்பட்டுள்ளது. ஆனால் வெளிப்படையான ப்ராக்ஸி உள்ளமைவு குறிப்பிடப்பட்டுள்ளது.</translation>
<translation id="445100540951337728">ஏற்கப்படும் டெபிட் கார்டுகள்</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> சந்தேகிக்கும்படியான செயல்பாடு</translation>
<translation id="4466881336512663640">படிவத்தில் செய்த மாற்றங்கள் சேமிக்கப்படாது. நிச்சயமாகத் தொடர விரும்புகிறீர்களா?</translation>
<translation id="4477350412780666475">அடுத்த டிராக்</translation>
<translation id="4482953324121162758">இந்தத் தளம் மொழிபெயர்க்கப்படாது.</translation>
@@ -685,6 +695,7 @@
<translation id="4594403342090139922">&amp;நீக்குதலைச் செயல்தவிர்</translation>
<translation id="4597348597567598915">அளவு: 8</translation>
<translation id="4600854749408232102">C6/C5 (என்வலப்)</translation>
+<translation id="464342062220857295">தேடல் அம்சங்கள்</translation>
<translation id="4646534391647090355">அங்கே செல்</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">இது <ph name="DOMAIN" /> தான் என்பதை இந்தச் சேவையகம் உறுதிப்படுத்தவில்லை; இதன் பாதுகாப்புச் சான்றிதழில் பிழைகள் உள்ளன. இது தவறான உள்ளமைவால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
@@ -693,7 +704,6 @@
<translation id="4691835149146451662">Architecture-A (என்வலப்)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">உங்கள் இணைப்பில் தடங்கல் ஏற்பட்டது</translation>
-<translation id="471880041731876836">இந்தத் தளத்தைப் பார்ப்பதற்கான அனுமதி உங்களிடம் இல்லை</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows நெட்வொர்க் டயக்னாஸ்டிக்ஸ் கருவியை இயக்கவும்<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">கொள்கைகளை மீண்டும் ஏற்று</translation>
<translation id="4728558894243024398">ப்ளாட்ஃபார்ம்</translation>
@@ -721,7 +731,6 @@
<translation id="4816492930507672669">பக்கத்தில் பொருத்து</translation>
<translation id="4850886885716139402">காட்சி</translation>
<translation id="4854362297993841467">இந்த டெலிவரி முறை இல்லை. வேறு முறையைப் பயன்படுத்திப் பார்க்கவும்.</translation>
-<translation id="4858792381671956233">இந்தத் தளத்தைப் பார்வையிடலாமா என, நீங்கள் பெற்றோரிடம் கேட்டுள்ளீர்கள்</translation>
<translation id="4864052566555297930">பாதுகாப்புக் குறிப்பு:</translation>
<translation id="4876188919622883022">எளிதாக்கப்பட்ட காட்சி</translation>
<translation id="4876305945144899064">பயனர்பெயர் இல்லை</translation>
@@ -745,7 +754,9 @@
<translation id="4974590756084640048">எச்சரிக்கைகளை மீண்டும் இயக்கு</translation>
<translation id="4984339528288761049">Prc5 (என்வலப்)</translation>
<translation id="4989163558385430922">எல்லாம் காட்டு</translation>
+<translation id="4989542687859782284">இல்லை</translation>
<translation id="4989809363548539747">இந்தச் செருகுநிரல் ஆதரிக்கப்படவில்லை</translation>
+<translation id="4995216769782533993">கார்டு விவரங்களை இந்தத் தளத்தில் பகிர பாதுகாப்புக் குறியீட்டை உறுதிசெய்யவும்</translation>
<translation id="5002932099480077015">இயக்கப்பட்டால், விரைவாகப் படிவத்தை நிரப்ப உங்கள் கார்டின் நகலை இச்சாதனத்தில் Chrome சேமித்து வைக்கும்.</translation>
<translation id="5015510746216210676">சாதனப் பெயர்:</translation>
<translation id="5017554619425969104">நீங்கள் நகலெடுத்த உரை</translation>
@@ -774,6 +785,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-பிட்)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">உங்கள் கார்டு விவரங்களைச் சரிபார்த்தல்</translation>
<translation id="5135404736266831032">முகவரிகளை நிர்வகி...</translation>
<translation id="5138227688689900538">குறைவாகக் காட்டு</translation>
<translation id="5141240743006678641">ஒத்திசைக்கப்பட்ட கடவுச்சொற்களை உங்கள் Google அனுமதிச் சான்றுகள் மூலம் என்க்ரிப்ட் செய்யும்</translation>
@@ -800,6 +812,7 @@
<translation id="5251803541071282808">கிளவுடு</translation>
<translation id="5252000469029418751">C7 (என்வலப்)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">சிஸ்டம் முழுவதிலும் பயன்படுத்தப்படும் அம்சங்களை உரிமையாளரால் மட்டுமே அமைக்க முடியும்: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">எச்சரிக்கை: இது ஒன்றிணைக்கப்படக்கூடிய டிக்‌ஷனரி கொள்கைகளைச் சேர்ந்ததல்ல என்பதால் PolicyDictionaryMultipleSourceMergeList கொள்கையில் குறிப்பிட்டுள்ளபடி ஒன்றிணைக்கப்படவில்லை.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">நிறுத்து</translation>
@@ -823,7 +836,6 @@
<translation id="536296301121032821">கொள்கை அமைப்புகளைச் சேமிப்பதில் தோல்வி</translation>
<translation id="5371425731340848620">கார்டை மாற்றவும்</translation>
<translation id="5377026284221673050">"நேரம் பின்தங்கியுள்ளது" அல்லது "நேரம் கூடுதலாக அமைக்கப்பட்டுள்ளது" அல்லது "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">இந்தப் பக்கம் உங்களை ஏமாற்றவோ, தனிப்பட்ட தகவலைத் திருடவோ சாதனத்திற்குத் தீங்கிழைக்கவோ கூடும். தனிப்பட்ட தகவலை உள்ளிடும்போதோ பதிவிறக்கப்பட்ட கோப்புகளைத் திறக்கும்போதோ கவனமாக இருக்கவும்.</translation>
<translation id="5384855140246857529">உங்கள் சாதனங்கள் அனைத்திலும் உங்கள் கார்டுகளைப் பயன்படுத்த, உள்நுழைந்து, ஒத்திசைவை இயக்கவும்.</translation>
<translation id="5386426401304769735">இந்தச் சான்றிதழ் சங்கிலியில், SHA-1ஐப் பயன்படுத்தி கையொப்பமிடப்பட்ட சான்றிதழ் உள்ளது.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -837,6 +849,7 @@
<translation id="5457113250005438886">தவறானது</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" />, மேலும் <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" />, மேலும் <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;மீண்டும் திருத்து</translation>
+<translation id="5473728911100096288">இந்த அம்சங்களை இயக்கினால் தடுக்கப்பட்ட அம்சங்களைப் பயன்படுத்துவீர்கள். இவை எதிர்காலப் பதிப்புகளில் இருக்காது.</translation>
<translation id="5478437291406423475">B6/C4 (என்வலப்)</translation>
<translation id="5481076368049295676">உங்கள் தகவலைத் திருடும் அல்லது நீக்கும் ஆபத்தான மென்பொருளை உங்கள் சாதனத்தில் இந்த உள்ளடக்கம் நிறுவ முயலலாம். <ph name="BEGIN_LINK" />பரவாயில்லை, காட்டு<ph name="END_LINK" /></translation>
<translation id="54817484435770891">சரியான முகவரியைச் சேர்க்கவும்</translation>
@@ -860,7 +873,6 @@
<translation id="5570825185877910964">கணக்கைப் பாதுகாத்திடு</translation>
<translation id="5571083550517324815">இந்த முகவரியிலிருந்து பிக்அப் செய்ய முடியாது. வேறு முகவரியைத் தேர்ந்தெடுக்கவும்.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{ஒரு குக்கீ பயன்படுத்தப்படுகிறது}other{# குக்கீகள் பயன்படுத்தப்படுகின்றன}})</translation>
-<translation id="5572851009514199876">Chromeமைத் தொடங்கி உள்நுழையவும். அப்போதுதான் இந்தத் தளத்தை அணுகுவதற்கு உங்களுக்கு அனுமதி உள்ளதா என்பதை Chrome சரிபார்க்க முடியும்.</translation>
<translation id="5580958916614886209">காலாவதி மாதத்தைச் சரிபார்த்து, மீண்டும் முயலவும்</translation>
<translation id="5586446728396275693">சேமித்த முகவரிகள் இல்லை</translation>
<translation id="5595485650161345191">முகவரியைத் திருத்து</translation>
@@ -868,6 +880,7 @@
<translation id="560412284261940334">நிர்வாகம் ஆதரிக்கவில்லை</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">இந்தத் தளம் போலியானதாகவோ மோசடி செய்யக்கூடியதாகவோ இருக்கும். இதிலிருந்து இப்போதே வெளியேறுமாறு Chrome பரிந்துரைக்கிறது.</translation>
<translation id="5610142619324316209">இணைப்பைச் சரிபார்த்தல்</translation>
<translation id="5610807607761827392"><ph name="BEGIN_LINK" />அமைப்புகளில்<ph name="END_LINK" /> கார்டுகளையும் முகவரிகளையும் நிர்வகிக்கலாம்.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> உங்களைப் பலமுறை திசைதிருப்பம் செய்தது.</translation>
@@ -891,11 +904,11 @@
<translation id="5720705177508910913">நடப்புப் பயனர்</translation>
<translation id="5728056243719941842">C5 (என்வலப்)</translation>
<translation id="5730040223043577876">பிற தளங்களில் உங்கள் கடவுச்சொல்லை மீண்டும் பயன்படுத்தினால், அதை மீட்டமைக்கும்படி Chrome பரிந்துரைக்கிறது.</translation>
-<translation id="5732392974455271431">உங்களுக்காக, தளத்தின் தடுப்பை உங்கள் பெற்றோர் நீக்க முடியும்</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{உங்கள் Google கணக்கில் கார்டைச் சேமியுங்கள்}other{உங்கள் Google கணக்கில் கார்டுகளைச் சேமியுங்கள்}}</translation>
<translation id="5763042198335101085">சரியான மின்னஞ்சல் முகவரியை உள்ளிடவும்</translation>
<translation id="5765072501007116331">டெலிவரி முறைகளையும் தேவைகளையும் பார்க்க, முகவரியைத் தேர்ந்தெடுக்கவும்</translation>
<translation id="5778550464785688721">MIDI சாதனங்கள் முழுக்கட்டுப்பாடு</translation>
+<translation id="5781136890105823427">சோதனை இயக்கப்பட்டுள்ளது</translation>
<translation id="578305955206182703">ஆம்பர்</translation>
<translation id="57838592816432529">ஒலியடக்கு</translation>
<translation id="5784606427469807560">கார்டை உறுதிசெய்வதில் சிக்கல் ஏற்பட்டது. இணைய இணைப்பைச் சரிபார்த்து, மீண்டும் முயலவும்.</translation>
@@ -912,13 +925,16 @@
<translation id="5860033963881614850">ஆஃப்</translation>
<translation id="5863847714970149516">அடுத்த பக்கத்தில் உங்களிடமிருந்து கட்டணம் வசூலிக்கப்படலாம்</translation>
<translation id="5866257070973731571">மொபைல் எண்ணைச் சேர்க்கவும்</translation>
+<translation id="5866898949289125849">டெவெலப்பர் கருவிகள் பக்கத்தைப் பார்க்கிறீர்கள்</translation>
<translation id="5869405914158311789">இந்தத் தளத்தை அணுக முடியவில்லை</translation>
<translation id="5869522115854928033">சேமிக்கப்பட்ட கடவுச்சொற்கள்</translation>
<translation id="5887400589839399685">கார்டு சேமிக்கப்பட்டது</translation>
<translation id="5893752035575986141">கிரெடிட் கார்டுகள் ஏற்கப்படுகின்றன.</translation>
+<translation id="5895138241574237353">மறுதொடக்கம்</translation>
<translation id="5901630391730855834">மஞ்சள்</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ஒத்திசைக்கப்பட்டது)</translation>
<translation id="5916664084637901428">இயக்கு</translation>
+<translation id="59174027418879706">இயக்கப்பட்டது</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google கணக்கில் கார்டைச் சேமிக்கவா?</translation>
<translation id="5922853866070715753">கிட்டத்தட்ட முடிந்துவிட்டது</translation>
@@ -946,12 +962,13 @@
<translation id="6039846035001940113">சிக்கல் தொடர்ந்தால், தள உரிமையாளரைத் தொடர்புகொள்ளவும்.</translation>
<translation id="6040143037577758943">மூடு</translation>
<translation id="6044573915096792553">அளவு: 12</translation>
-<translation id="6047233362582046994">உங்கள் பாதுகாப்பிற்கான ஆபத்துகளைப் புரிந்துகொண்டால், தீங்கிழைக்கும் பயன்பாடுகள் அகற்றப்படுவதற்கு முன் நீங்கள் <ph name="BEGIN_LINK" />இந்தத் தளத்தைப் பார்வையிடலாம்<ph name="END_LINK" />.</translation>
+<translation id="6047233362582046994">உங்கள் பாதுகாப்பிற்கான ஆபத்துகளைப் புரிந்துகொண்டால், தீங்கிழைக்கும் ஆப்ஸ் அகற்றப்படுவதற்கு முன் நீங்கள் <ph name="BEGIN_LINK" />இந்தத் தளத்தைப் பார்வையிடலாம்<ph name="END_LINK" />.</translation>
<translation id="6047927260846328439">இந்த உள்ளடக்கம், உங்களை ஏமாற்றி மென்பொருளை நிறுவ வைக்கலாம் அல்லது தனிப்பட்ட தகவலை வெளிப்படுத்தச் செய்யலாம். <ph name="BEGIN_LINK" />பரவாயில்லை, காட்டு<ph name="END_LINK" /></translation>
<translation id="6051221802930200923"><ph name="SITE" /> தளமானது சர்டிஃபிகேட் பின்னிங்கைப் பயன்படுத்துவதால், தற்போது அதைப் பார்க்க முடியாது. பொதுவாக நெட்வொர்க் பிழைகளும் பாதிப்புகளும் தற்காலிகமானவை என்பதால், இந்தப் பக்கம் பின்னர் சரியாகச் செயல்படக்கூடும்.</translation>
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">உங்கள் சாதனங்கள் அனைத்திலும் உங்கள் கார்டுகளைப் பயன்படுத்தவா?</translation>
<translation id="6059925163896151826">USB சாதனங்கள்</translation>
+<translation id="6060009363608157444">தவறான DnsOverHttps பயன்முறை.</translation>
<translation id="6080696365213338172">நிர்வாகி வழங்கிய சான்றிதழைப் பயன்படுத்தி உள்ளடக்கத்தை அணுகியுள்ளீர்கள். <ph name="DOMAIN" /> க்கு நீங்கள் வழங்கிய தரவானது உங்கள் நிர்வாகியால் இடைமறிக்கப்படலாம்.</translation>
<translation id="6094273045989040137">விரிவுரைப் பயன்முறை</translation>
<translation id="610911394827799129"><ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> என்ற முகவரியில், உங்கள் Google கணக்கிற்கான பிற வகை உலாவல் வரலாறும் இருக்கக்கூடும்</translation>
@@ -999,13 +1016,12 @@
<translation id="6404511346730675251">புக்மார்க்களைத் திருத்து</translation>
<translation id="6406765186087300643">C0 (என்வலப்)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" />க்கான காலாவதித் தேதியையும் CVC எண்ணையும் உள்ளிடவும்</translation>
-<translation id="6414888972213066896">இந்தத் தளத்தைப் பார்வையிடலாமா என, நீங்கள் பெற்றோரிடம் கேட்டுள்ளீர்கள்</translation>
<translation id="6415778972515849510">உங்கள் Google கணக்கைப் பாதுகாக்கவும் கடவுச்சொல்லை மாற்றவும் Chromium உதவும்.</translation>
-<translation id="6417515091412812850">சான்றிதழ் திரும்பப்பெறப்பட்டதா என்று சோதிக்க முடியவில்லை.</translation>
<translation id="6431585503458005759">சேமிக்க வேண்டாம்</translation>
<translation id="6433490469411711332">தொடர்புத் தகவலை மாற்று</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> இணைக்க மறுத்தது.</translation>
<translation id="6434309073475700221">நிராகரி</translation>
+<translation id="6435221585574090192">உங்கள் நிர்வாகியுடன் Chrome Enterprise Threat Protection கொடியிட்டுள்ள பாதுகாப்பு தொடர்பான செயல்பாடுகளின் தரவைப் பகிரும். இவற்றில் பக்க URLகள், கோப்பின் பெயர் மற்றும் தரவுத்தகவல், உங்கள் சாதன மற்றும் Chrome பயனர்பெயர் ஆகியவை அடங்கும்.</translation>
<translation id="6440503408713884761">புறக்கணிக்கப்பட்டது</translation>
<translation id="6446163441502663861">Kahu (என்வலப்)</translation>
<translation id="6446608382365791566">மேலும் தகவலைச் சேர்க்கவும்</translation>
@@ -1014,20 +1030,19 @@
<translation id="6465306955648956876">கடவுச்சொற்களை நிர்வகி...</translation>
<translation id="647261751007945333">சாதனக் கொள்கைகள்</translation>
<translation id="6476284679642588870">கட்டண முறைகளை நிர்வகி</translation>
-<translation id="6477321094435799029">இந்தப் பக்கத்தில் வழக்கத்திற்கு மாறான குறியீடு இருப்பதை Chrome கண்டறிந்துள்ளது, மேலும் உங்கள் தனிப்பட்ட தகவலை (எடுத்துக்காட்டு: கடவுச்சொற்கள், ஃபோன் எண்கள் மற்றும் கிரெடிட் கார்டுகள்) பாதுகாக்க அதைத் தடுத்துள்ளது.</translation>
<translation id="6489534406876378309">சிதைவுகளைப் பதிவேற்றுவதைத் தொடங்கு</translation>
<translation id="6499038740797743453">கடவுச்சொல்லை மீட்டமைக்கவா?</translation>
<translation id="6507833130742554667">கிரெடிட் மற்றும் டெபிட் கார்டுகள் ஏற்கப்படுகின்றன.</translation>
<translation id="650855688985305916">ஆம், சேமி</translation>
<translation id="6508722015517270189">Chromeஐ மீண்டும் தொடங்கவும்</translation>
<translation id="6517596291481585650">எச்சரிக்கை: இது பட்டியல் இல்லை என்பதால் கொள்கையில் குறிப்பிட்டுள்ளபடி ஒன்றிணைக்கப்படவில்லை.</translation>
+<translation id="6518133107902771759">சரிபார்</translation>
<translation id="6521745193039995384">செயலில் இல்லை</translation>
<translation id="6529602333819889595">&amp;நீக்குதலை மீண்டும் செய்</translation>
<translation id="6534179046333460208">இயல்நிலை இணையப் பரிந்துரைகள்</translation>
<translation id="6545864417968258051">புளூடூத் ஸ்கேனிங்</translation>
<translation id="6554795675067793129">உங்கள் கணக்கை நிர்வகிப்பது: <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">மீண்டும் செய்</translation>
-<translation id="6563469144985748109">இன்னும் உங்கள் நிர்வாகி அனுமதிக்கவில்லை</translation>
<translation id="6569060085658103619">நீட்டிப்புப் பக்கத்தைப் பார்க்கிறீர்கள்</translation>
<translation id="6578796323535178455">C2 (என்வலப்)</translation>
<translation id="6579990219486187401">வெளிர் பிங்க் நிறம்</translation>
@@ -1045,11 +1060,13 @@
<translation id="6643016212128521049">அழி</translation>
<translation id="6644283850729428850">இந்தக் கொள்கை தவிர்க்கப்பட்டது.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{எதுவுமில்லை}=1{1 தளத்திலிருந்து (உங்கள் Google கணக்கிலிருந்து வெளியேறமாட்டீர்கள்)}other{# தளங்களிலிருந்து (உங்கள் Google கணக்கிலிருந்து வெளியேறமாட்டீர்கள்)}}</translation>
+<translation id="6652101503459149953">Windows Helloவைப் பயன்படுத்து</translation>
<translation id="6657585470893396449">கடவுச்சொல்</translation>
<translation id="6670613747977017428">பாதுகாப்பான நிலைக்குத் திரும்பு.</translation>
<translation id="6671697161687535275">Chromium இலிருந்து படிவப் பரிந்துரையை அகற்றவா?</translation>
<translation id="6685834062052613830">வெளியேறி, அமைப்பை முடிக்கவும்</translation>
<translation id="6689271823431384964">நீங்கள் உள்நுழைந்துள்ளதால் Google கணக்கில் உங்கள் கார்டு விவரங்களைச் சேமிக்கும் விருப்பத்தை Chrome வழங்குகிறது. இதை நீங்கள் அமைப்புகளில் மாற்றலாம். கார்டு உரிமையாளரின் பெயர் உங்கள் கணக்கிலிருந்து பெறப்படுகிறது.</translation>
+<translation id="6707256370811247129">Chromeமில் நீங்கள் பதிவேற்றும் அல்லது பதிவிறக்கும் கோப்புகளையும் தற்காலிக சேமிப்பின் உள்ளடக்கங்களையும் ஸ்கேன் செய்யும்.</translation>
<translation id="6710213216561001401">முந்தையது</translation>
<translation id="6710594484020273272">&lt;தேடல் வார்த்தையை உள்ளிடுக&gt;</translation>
<translation id="671076103358959139">பதிவு டோக்கன்:</translation>
@@ -1057,10 +1074,10 @@
<translation id="6738516213925468394"><ph name="TIME" />க்கு உங்கள் தரவு உங்கள் <ph name="BEGIN_LINK" />ஒத்திசைவுக் கடவுச்சொற்றொடரைக்<ph name="END_LINK" /> கொண்டு என்க்ரிப்ட் செய்யப்பட்டது. ஒத்திசைவைத் தொடங்க, அதை உள்ளிடவும்.</translation>
<translation id="674375294223700098">தெரியாத சேவையகச் சான்றிதழ் பிழை.</translation>
<translation id="6744009308914054259">இணைப்புக்காகக் காத்திருக்கும்போது ​​ஆஃப்லைன் கட்டுரைகளைப் படிக்க, ‘பதிவிறக்கங்கள்’ என்பதைப் பார்க்கவும்.</translation>
+<translation id="6747611005629681221">எச்சரிக்கை: தடுக்கப்பட்ட அம்சங்கள் உள்ளன!</translation>
<translation id="6753269504797312559">கொள்கை மதிப்பு</translation>
<translation id="6757797048963528358">உங்கள் சாதனம் உறக்கநிலைக்குச் சென்றது.</translation>
<translation id="6768213884286397650">Hagaki (போஸ்ட்கார்டு)</translation>
-<translation id="6778737459546443941">இன்னும் உங்கள் பெற்றோர் அனுமதிக்கவில்லை</translation>
<translation id="67862343314499040">ஊதா</translation>
<translation id="6786747875388722282">நீட்டிப்புகள்</translation>
<translation id="6790428901817661496">இயக்கு</translation>
@@ -1068,6 +1085,7 @@
<translation id="681021252041861472">அவசியமானவை</translation>
<translation id="6810899417690483278">தனிப்பயனாக்கல் ஐடி</translation>
<translation id="6825578344716086703"><ph name="DOMAIN" />க்குச் செல்ல முயற்சி செய்தீர்கள். ஆனால் சேவையகமானது வலிமையற்ற கையொப்ப அல்காரிதமை (SHA-1 போன்றது) பயன்படுத்தி, கையொப்பமிடப்பட்ட சான்றிதழை வழங்கியது. அதாவது, சேவையகம் வழங்கிய பாதுகாப்பு அனுமதிச் சான்றுகள் போலியானதாக்கப்பட்டிருக்கலாம், மேலும் அந்தச் சேவையகம் நீங்கள் எதிர்பார்த்த (ஹேக்கருடன் தகவல் பரிமாற்றம் செய்திருக்கக்கூடும்) சேவையகமாக இல்லாமலிருக்கலாம்.</translation>
+<translation id="6826370046007623921">தரவு இழப்புத் தடுப்பு</translation>
<translation id="6831043979455480757">மொழிபெயர்</translation>
<translation id="6839929833149231406">பரப்பு</translation>
<translation id="6852204201400771460">ஆப்ஸை ரெஃப்ரெஷ் செய்யவா?</translation>
@@ -1080,7 +1098,6 @@
<translation id="6891596781022320156">கொள்கையின் நிலை ஆதரிக்கப்படவில்லை.</translation>
<translation id="6895330447102777224">கார்டு உறுதிசெய்யப்பட்டது</translation>
<translation id="6897140037006041989">பயனர் ஏஜெண்ட்</translation>
-<translation id="6903319715792422884">Googleளுக்குச் சில <ph name="BEGIN_WHITEPAPER_LINK" />சாதனத் தகவல்களையும் பக்க உள்ளடக்கத்தையும்<ph name="END_WHITEPAPER_LINK" /> அனுப்புவதன் மூலம் பாதுகாப்பான உலாவலை மேம்படுத்த உதவுங்கள். <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">பயனர்:</translation>
<translation id="6934672428414710184">இந்தப் பெயர் உங்கள் ‘Google கணக்கிலிருந்து’ பெறப்பட்டது</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> நிர்வகிக்காத ஒரு தளத்தில் உங்கள் கடவுச்சொல்லை உள்ளிட்டுள்ளீர்கள். உங்கள் கணக்கைப் பாதுகாக்க, பிற ஆப்ஸிலும் தளங்களிலும் உங்கள் கடவுச்சொல்லை மீண்டும் பயன்படுத்த வேண்டாம்.</translation>
@@ -1125,6 +1142,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" />, மேலும் <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" />, மேலும் <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">லாவெண்டர் நிறம்</translation>
<translation id="717330890047184534">Gaia ஐடி:</translation>
+<translation id="7174545416324379297">ஒன்றிணைக்கப்பட்டது</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" />, மேலும் <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" />, மேலும் <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">நீங்கள் செல்லும் <ph name="ORIGIN" /> சேவையகம், அதனுடன் தொடர்புடைய எல்லாக் கோரிக்கைகளுக்கும்
பாதுகாப்புக் கொள்கை பொருந்த வேண்டுமெனக் கோரிக்கை விடுத்துள்ளது. ஆனால், கொள்கையை
@@ -1162,6 +1180,7 @@
<translation id="7320336641823683070">இணைப்பிற்கான உதவி</translation>
<translation id="733354035281974745">சாதனத்தின் அகக் கணக்கில் மேலெழுதுதல்</translation>
<translation id="7334320624316649418">&amp;மறுவரிசைப்படுத்தலை மீண்டும் செய்</translation>
+<translation id="7337706099755338005">உங்கள் இயங்குதளத்தில் இல்லை.</translation>
<translation id="733923710415886693">சான்றிதழ் வெளிப்படைத்தன்மை மூலம் சேவையகத்தின் சான்றிதழ் வெளியிடப்படவில்லை.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">இணைக்கப்பட்டுள்ளாரா?:</translation>
@@ -1193,7 +1212,6 @@
<translation id="7440140511386898319">ஆஃப்லைன் உள்ளடக்கப் பட்டியல்</translation>
<translation id="7441627299479586546">தவறான கொள்கைத் தலைப்பு</translation>
<translation id="7442725080345379071">வெளிர் ஆரஞ்சு</translation>
-<translation id="7444046173054089907">இந்தத் தளம் தடுக்கப்பட்டது</translation>
<translation id="7445762425076701745">நீங்கள் இணைந்துள்ள சேவையகத்தின் அடையாளத்தை முழுமையாகச் சரிபார்க்க முடியவில்லை. உங்கள் நெட்வொர்க்கில் மட்டுமே செல்லுபடியாகும் பெயரைப் பயன்படுத்தி சேவையகத்துடன் இணைந்துள்ளீர்கள். இதன் உரிமையை ஒரு வெளிப்புற சான்றிதழ் மையம் உறுதிப்படுத்த முடியாது. சில சான்றிதழ் மையங்கள், இந்தப் பெயர்களுக்கும் சான்றிதழ்களை வழங்கும் என்பதால், நீங்கள் நினைத்த வலைப்பக்கத்துடனே இணைந்துள்ளீர்கள் என்பதையும் ஏதேனும் மோசடி தளத்துடன் இணையவில்லை என்பதையும் உறுதிப்படுத்த எந்த வழியும் இல்லை.</translation>
<translation id="7451311239929941790">இந்தச் சிக்கல் குறித்து <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">முழுமையான இயல்புநிலையைப் பயன்படுத்து (தடு)</translation>
@@ -1215,9 +1233,9 @@
<translation id="7538364083937897561">A2 (என்வலப்)</translation>
<translation id="7542403920425041731">நீங்கள் உறுதிசெய்ததும், உங்கள் கார்டு விவரங்கள் இந்தத் தளத்துடன் பகிரப்படும்.</translation>
<translation id="7542995811387359312">இந்தப் படிவம் பாதுகாப்பான இணைப்பைப் பயன்படுத்தாத காரணத்தால், தானியங்கு கடன் அட்டை நிரப்புதல் முடக்கப்பட்டிருக்கிறது.</translation>
-<translation id="7543525346216957623">உங்கள் பெற்றோரிடம் கேட்கவும்</translation>
<translation id="7548892272833184391">இணைப்புப் பிழைகளைச் சரிசெய்யவும்</translation>
<translation id="7549584377607005141">சரியாக காண்பிக்கப்படுவதற்கு நீங்கள் ஏற்கனவே உள்ளிட்ட தரவு இந்த இணையப்பக்கத்திற்கு தேவைப்படுகிறது. இந்த தரவை நீங்கள் மீண்டும் அனுப்பலாம், ஆனால் அவ்வாறு செய்வதனால் இந்தப் பக்கம் ஏற்கனவே செயற்படுத்திய எல்லாச் செயலையும் மீண்டும் செய்வீர்கள்.</translation>
+<translation id="7550637293666041147">உங்கள் சாதன மற்றும் Chrome பயனர்பெயர்</translation>
<translation id="7552846755917812628">பின்வரும் உதவிக் குறிப்புகளைச் செய்து பார்க்கவும்:</translation>
<translation id="7554791636758816595">புதிய தாவல்</translation>
<translation id="7564049878696755256"><ph name="ORG_NAME" /> கணக்கிற்கான அணுகலை நீங்கள் இழக்கக்கூடும் அல்லது அடையாளத் திருட்டை எதிர்கொள்ளக்கூடும். இப்போதே உங்கள் கடவுச்சொல்லை மாற்றும்படி Chrome பரிந்துரைக்கிறது.</translation>
@@ -1232,6 +1250,7 @@
<translation id="7610193165460212391"><ph name="VALUE" /> என்ற மதிப்பு வரம்பை மீறியுள்ளது.</translation>
<translation id="7613889955535752492">காலாவதியாவது: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">உங்கள் Google கணக்கு கடவுச்சொல்லின் மற்றொரு பதிப்பைப் பயன்படுத்தி குறியாக்கப்பட்ட தரவு உங்களிடம் ஏற்கனவே உள்ளது. கீழே அதை உள்ளிடுக.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">செயல்திறன் தரவுகள் &amp; சிதைவு அறிக்கைகள்</translation>
<translation id="7637571805876720304">Chromium இலிருந்து கிரெடிட் கார்டை அகற்றவா?</translation>
<translation id="7638605456503525968">சீரியல் போர்ட்டுகள்</translation>
@@ -1244,7 +1263,6 @@
<translation id="7668654391829183341">அறியப்படாத சாதனம்</translation>
<translation id="7669271284792375604">இந்தத் தளத்தில் உள்ள ஹேக்கர்கள், உங்களை ஏமாற்றி (எடுத்துக்காட்டாக, உங்கள் முகப்புப் பக்கத்தை மாற்றுவது அல்லது நீங்கள் பார்வையிடும் தளங்களில் கூடுதல் விளம்பரங்களைக் காட்டுவது), உங்கள் உலாவல் அனுபவத்தைப் பாதிக்கக்கூடிய நிரல்களை நிறுவ வைக்கலாம்.</translation>
<translation id="7676643023259824263"><ph name="TEXT" /> கிளிப்-போர்டு உரையைத் தேடும்</translation>
-<translation id="7679176406634891508">இயங்குதளம் மற்றும் கிளவுட்</translation>
<translation id="7681101578153515023">தேடல் இன்ஜினை மாற்று</translation>
<translation id="7682287625158474539">ஷிப்பிங்</translation>
<translation id="7687186412095877299">கட்டணப் படிவங்களில் உங்கள் சேமிக்கப்பட்ட கட்டண முறைகளை நிரப்பும்</translation>
@@ -1259,7 +1277,6 @@
<translation id="7723047071702270851">கார்டைத் திருத்தவும்</translation>
<translation id="774634243536837715">ஆபத்தான உள்ளடக்கம் தடுக்கப்பட்டது.</translation>
<translation id="7752995774971033316">நிர்வகிக்கப்படாதது</translation>
-<translation id="7755287808199759310">உங்களுக்காக, தளத்தின் தடுப்பை உங்கள் பெற்றோர் நீக்க முடியும்</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ஃபயர்வால் அல்லது வைரஸ்தடுப்பு மென்பொருள் உங்கள் இணைப்பைத் தடுத்திருக்கலாம்.</translation>
<translation id="7759163816903619567">காட்சி டொமைன்:</translation>
@@ -1303,7 +1320,6 @@
<translation id="8004582292198964060">உலாவி</translation>
<translation id="8009225694047762179">கடவுச்சொற்களை நிர்வகி</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{இந்தக் கார்டும் அதன் பில்லிங் முகவரியும் சேமிக்கப்படும். <ph name="USER_EMAIL" /> இல் உள்நுழைந்திருக்கும்போது இதைப் பயன்படுத்தலாம்.}other{இந்தக் கார்டுகளும் அவற்றின் பில்லிங் முகவரிகளும் சேமிக்கப்படும். <ph name="USER_EMAIL" /> இல் உள்நுழைந்திருக்கும்போது இவற்றைப் பயன்படுத்தலாம்.}}</translation>
-<translation id="8012647001091218357">தற்போது எங்களால் உங்கள் பெற்றோர்களைத் தொடர்புகொள்ள முடியவில்லை. மீண்டும் முயற்சிக்கவும்.</translation>
<translation id="8025119109950072390">இந்தத் தளத்தில் உள்ள ஹேக்கர்கள், உங்களை ஏமாற்றி, மென்பொருளை நிறுவுவது அல்லது தனிப்பட்ட தகவலை (எடுத்துக்காட்டாக, கடவுச்சொற்கள், ஃபோன் எண்கள் அல்லது கிரெடிட் கார்டுகள்) வெளிப்படுத்துவது போன்ற உங்களுக்கு ஆபத்தை விளைவிக்கும் செயல்களைச் செய்ய வைக்கலாம்.</translation>
<translation id="8034522405403831421">இந்தப் பக்கம் <ph name="SOURCE_LANGUAGE" /> மொழியில் உள்ளது. இதை <ph name="TARGET_LANGUAGE" /> க்கு மொழிபெயர்க்கவா?</translation>
<translation id="8035152190676905274">பேனா</translation>
@@ -1314,6 +1330,7 @@
<translation id="8041940743680923270">முழுமையான இயல்புநிலையைப் பயன்படுத்து (கேள்)</translation>
<translation id="8042918947222776840">பிக்அப் முறையைத் தேர்வு செய்</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" மென்பொருள் சரியாக உள்ளமைக்கப்படவில்லை. வழக்கமாக, "<ph name="SOFTWARE_NAME" />"ஐ நிறுவல் நீக்கினால் சிக்கல் சரியாகிவிடும். <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">இனிமேல் கார்டின் பாதுகாப்புக் குறியீட்டை உள்ளிட வேண்டியதில்லை</translation>
<translation id="8066955247577885446">ஏதோ தவறாகிவிட்டது.</translation>
<translation id="8074253406171541171">10x13 (என்வலப்)</translation>
<translation id="8078141288243656252">சுழற்றப்பட்டுள்ளபோது ஆவணத்தில் விரிவுரையைச் சேர்க்க முடியாது</translation>
@@ -1344,6 +1361,7 @@
<translation id="8211406090763984747">இணைப்பு பாதுகாப்பானது</translation>
<translation id="8218327578424803826">ஒதுக்கிய இருப்பிடம்:</translation>
<translation id="8220146938470311105">C7/C6 (என்வலப்)</translation>
+<translation id="8220639454292072926">நிறுவன அறிக்கையளித்தல்</translation>
<translation id="8225771182978767009">இந்தக் கம்ப்யூட்டரை அமைத்த நபர் இந்தத் தளத்தைத் தடுக்கும்படி தேர்வுசெய்துள்ளார்.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">புதிய மறைநிலைத் தாவலில் பக்கத்தைத் திறக்கவும்</translation>
@@ -1398,23 +1416,23 @@
<translation id="8508648098325802031">தேடல் ஐகான்</translation>
<translation id="8522552481199248698">உங்கள் Google கணக்கைப் பாதுகாக்கவும் கடவுச்சொல்லை மாற்றவும் Chrome உதவும்.</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />கண்டறிவதில் சிக்கல் இருப்பதைப் புகாரளிக்கலாம்<ph name="END_ERROR_LINK" /> அல்லது உங்கள் பாதுகாப்பிற்கு ஏற்படக்கூடிய ஆபத்துகளைப் புரிந்துகொண்டிருந்தால், <ph name="BEGIN_LINK" />இந்தப் பாதுகாப்பற்ற தளத்திற்குச் செல்லலாம்<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">கேள்விகள் உள்ளனவா? உங்கள் சுயவிவரக் கண்காணிப்பாளரைத் தொடர்புகொள்ளவும்.</translation>
<translation id="8553075262323480129">பக்கத்தின் மொழியைத் தீர்மானிக்க முடியாததால் மொழிபெயர்ப்பு தோல்வியடைந்தது.</translation>
<translation id="8557066899867184262">உங்கள் கார்டின் பின்புறத்தில் CVC எண் இருக்கும்.</translation>
<translation id="8559762987265718583">உங்கள் சாதனத்தின் தேதி மற்றும் நேரம் (<ph name="DATE_AND_TIME" />) தவறாக உள்ளதால் <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> க்கான தனிப்பட்ட இணைப்பை ஏற்படுத்த முடியவில்லை.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> சந்தேகத்திற்குரிய தளம்</translation>
<translation id="8564985650692024650">பிற தளங்களில் உங்கள் <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> கடவுச்சொல்லை மீண்டும் பயன்படுத்தினால், அதை மீட்டமைக்கும்படி Chromium பரிந்துரைக்கிறது.</translation>
<translation id="8571890674111243710"><ph name="LANGUAGE" /> க்கு பக்கத்தை மொழிபெயர்க்கிறது...</translation>
<translation id="858637041960032120">ஃபோன் எண்ணைச் சேர்</translation>
-<translation id="859285277496340001">இந்த சான்றிதழ் திரும்பப்பெறப்பட்டதா என்பதைச் சரிபார்ப்பதற்கான செயல்முறை இதில் இல்லை.</translation>
<translation id="860043288473659153">கார்டு உரிமையாளரின் பெயர்</translation>
<translation id="861775596732816396">அளவு: 4</translation>
-<translation id="8620436878122366504">இன்னும் உங்கள் பெற்றோர் அனுமதிக்கவில்லை</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">இந்தச் சாதனத்தில் கார்டைச் சேமி</translation>
<translation id="8626112503828625890">Google கணக்கில் பில்லிங் விவரங்களைச் சேமிக்கவா?</translation>
+<translation id="8647750283161643317">எல்லாவற்றையும் இயல்புநிலைக்கு மீட்டமை</translation>
<translation id="8663226718884576429">ஆர்டர் சுருக்கம், <ph name="TOTAL_LABEL" />, மேலும் விவரங்கள்</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, பதில், <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">மீதமுள்ளது:</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> க்கான உங்கள் இணைப்பு என்க்ரிப்ட் செய்யப்படவில்லை.</translation>
<translation id="8718314106902482036">பேமெண்ட் முடியவில்லை</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, தேடல் பரிந்துரை</translation>
@@ -1425,6 +1443,7 @@
<translation id="8738058698779197622">பாதுகாப்பான இணைப்பை அமைக்க, கடிகாரம் சரியாக அமைக்கப்பட வேண்டும். இதற்குக் காரணம், இணையதளங்கள் தங்களைத் தானே அடையாளப்படுத்த பயன்படுத்தும் சான்றிதழ்கள் குறிப்பிட்ட காலநேரத்திற்கே செல்லுபடியாகும். உங்கள் சாதனத்தின் கடிகாரம் தவறாக இருந்தால், Chromium இந்தச் சான்றிதழ்களைச் சரிபார்க்காது.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" />’s &lt;abbr id="dnsDefinition"&gt;DNS முகவரியைக்&lt;/abbr&gt; கண்டறிய முடியவில்லை. சிக்கலை ஆய்வு செய்கிறது.</translation>
<translation id="874846938927089722">ஏற்கப்படும் கிரெடிட் மற்றும் ப்ரீபெய்டு கார்டுகள்</translation>
+<translation id="874918643257405732">இந்தத் தாவலைப் புக்மார்க் செய்யும்</translation>
<translation id="8759274551635299824">கார்டு காலாவதியாகிவிட்டது</translation>
<translation id="8761567432415473239">Google பாதுகாப்பான தேடல், <ph name="SITE" /> இல் சமீபத்தில் <ph name="BEGIN_LINK" />தீங்கான நிரல்களைக் கண்டறிந்தது<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB சாதனம்</translation>
@@ -1454,6 +1473,7 @@
<translation id="8938939909778640821">ஏற்கப்படும் கிரெடிட் மற்றும் ப்ரீபெய்டு கார்டுகள்</translation>
<translation id="8943282376843390568">சுண்ணாம்பு நிறம்</translation>
<translation id="8957210676456822347">கேப்டிவ் போர்டல் அங்கீகாரம்</translation>
+<translation id="8962950042226115166">சந்தேகத்திற்குரிய தளம்</translation>
<translation id="8968766641738584599">கார்டைச் சேமி</translation>
<translation id="8971063699422889582">சேவையகச் சான்றிதழ் காலாவதியானது.</translation>
<translation id="8975012916872825179">இதில் ஃபோன் எண்கள், மின்னஞ்சல் முகவரிகள், ஷிப்பிங் முகவரிகள் போன்ற தகவல்கள் உள்ளடங்கும்</translation>
@@ -1476,25 +1496,25 @@
<translation id="9035022520814077154">பாதுகாப்புப் பிழை</translation>
<translation id="9038649477754266430">பக்கங்களை இன்னும் விரைவாக ஏற்ற, யூக சேவையைப் பயன்படுத்தவும்</translation>
<translation id="9039213469156557790">மேலும், பாதுகாப்பற்ற பிற ஆதாரங்கள் இந்தப் பக்கத்தில் உள்ளன. இந்த ஆதாரங்களை ட்ரான்ஸிட்டில் இருக்கும்போதும் பிறர் பார்வையிடலாம், மேலும் பக்கத்தின் செயல்பாட்டை மாற்ற, தீங்கிழைப்பவர் அதை மாற்றியமைக்கலாம்.</translation>
+<translation id="9044359186343685026">Touch IDயைப் பயன்படுத்து</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">நீங்கள் <ph name="DOMAIN" /> ஐ அடைய முயற்சி செய்தீர்கள், ஆனால் சேவையகம் ஒரு செல்லாத சான்றிதழை வழங்கியது.</translation>
<translation id="9050666287014529139">கடவுச்சொற்றொடர்</translation>
<translation id="9065203028668620118">திருத்து</translation>
<translation id="9065745800631924235">வரலாற்றிலிருந்து <ph name="TEXT" /> பற்றிய தேடல்கள்</translation>
<translation id="9069693763241529744">நீட்டிப்பு தடுத்துள்ளது</translation>
-<translation id="9076283476770535406">இதில் பெரியவர்களுக்கான உள்ளடக்கம் இருக்கக்கூடும்</translation>
<translation id="9076630408993835509">இந்த உலாவியை ஒரு நிறுவனமோ பிற அமைப்போ நிர்வகிக்கவில்லை. இந்தச் சாதனத்தின் செயல்பாடுகளை Chromeமுக்கு வெளியிலிருந்து நிர்வகிக்கலாம். <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">கூடுதல் தகவல் தேவை</translation>
<translation id="9080712759204168376">ஆர்டர் பற்றிய சுருக்கவிவரம்</translation>
<translation id="9089260154716455634">Off-Hours கொள்கை:</translation>
<translation id="9095388113577226029">மேலும் மொழிகள்...</translation>
+<translation id="9098981495403789647">உலாவியில் Chrome Enterprise Threat Protectionனை உங்கள் நிர்வாகி இயக்கியுள்ளார். உங்களின் சில தரவை Chrome Enterprise Threat Protectionனால் அணுக முடியும்.</translation>
<translation id="9103872766612412690">வழக்கமாக, <ph name="SITE" /> உங்கள் தகவலைப் பாதுகாப்பதற்காக என்க்ரிப்ஷனைப் பயன்படுத்துகிறது.
இந்த முறை <ph name="SITE" /> உடன் இணைவதற்கு Chromium முயற்சித்தபோது வழக்கத்திற்கு மாறான, தவறான நற்சான்றிதழ்களை இணையதளம் வழங்கியது. தாக்குபவர் தன்னை <ph name="SITE" /> ஆகக் காட்ட முயற்சிக்கும் போது அல்லது இணைப்பை வைஃபை உள்நுழைவுத் திரை குறுக்கிடும் போது இது ஏற்படலாம். இருப்பினும், தரவு எதுவும் பரிமாற்றப்படுவதற்கு முன் Chromium இணைப்பை நிறுத்தியதால் உங்கள் தகவல் பாதுகாப்பாகவே இருக்கிறது.</translation>
<translation id="9106062320799175032">பில்லிங் முகவரியைச் சேர்க்கவும்</translation>
<translation id="9114524666733003316">கார்டை உறுதிசெய்கிறது...</translation>
<translation id="9128870381267983090">நெட்வொர்க்குடன் இணையவும்</translation>
<translation id="9137013805542155359">அசலைக் காண்பி</translation>
-<translation id="9137248913990643158">இந்தப் பயன்பாட்டைப் பயன்படுத்தும் முன், Chromeஐத் தொடங்கி உள்நுழையவும்.</translation>
<translation id="9141013498910525015">முகவரிகளை நிர்வகி</translation>
<translation id="9148088599418889305">ஷிப்பிங் முறையைத் தேர்வு செய்</translation>
<translation id="9148507642005240123">&amp;திருத்தலைச் செயல்தவிர்</translation>
diff --git a/chromium/components/strings/components_strings_te.xtb b/chromium/components/strings/components_strings_te.xtb
index 14fdbe8e852..7eb2a74c5a3 100644
--- a/chromium/components/strings/components_strings_te.xtb
+++ b/chromium/components/strings/components_strings_te.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">సూచిక-5x8</translation>
<translation id="1088860948719068836">కార్డ్‌లో పేరుని జోడించండి</translation>
<translation id="1089439967362294234">పాస్‌వర్డ్‌ని మార్చు</translation>
+<translation id="1096545575934602868">ఈ ఫీల్డ్‌లో <ph name="MAX_ITEMS_LIMIT" /> కంటే ఎక్కువ నమోదులు ఉండకూడదు. తదుపరి అన్ని నమోదులు విస్మరించబడతాయి.</translation>
<translation id="109743633954054152">Chrome సెట్టింగ్‌లలో పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
<translation id="1103523840287552314">ఎల్లప్పుడూ <ph name="LANGUAGE" />ను అనువదించు</translation>
<translation id="1107591249535594099">ఎంచుకున్నట్లయితే, Chrome వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> యొక్క <ph name="BEGIN_LINK" />కాష్ చేయబడిన కాపీ<ph name="END_LINK" />ని యాక్సెస్‌ చేయండి</translation>
<translation id="1156303062776767266">మీరు స్థానిక లేదా షేర్ చేసిన ఫైల్‌ను చూస్తున్నారు</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ఊహించని విధంగా కనెక్షన్‌ను మూసివేసింది.</translation>
+<translation id="115926840831309955">మీ CVCని తనిఖీ చేసి మళ్ళీ ప్రయత్నించండి లేదా గడువు ముగింపు తేదీని అప్‌డేట్ చేయండి</translation>
<translation id="1161325031994447685">Wi-Fiకి మళ్లీ కనెక్ట్ చేయడం</translation>
<translation id="1165039591588034296">ఎర్రర్</translation>
<translation id="1175364870820465910">&amp;ముద్రించు...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"మీ కంప్యూటర్‌లో ఉన్న సాఫ్ట్‌వేర్ కారణంగా Chrome సురక్షితంగా వెబ్‌కు కనెక్ట్ కాలేకపోతోంది" (Windows కంప్యూటర్‌ల కోసం మాత్రమే)</translation>
<translation id="1294154142200295408">ఆదేశ-పంక్తి వ్యత్యాసాలు</translation>
<translation id="129553762522093515">ఇటీవల మూసివెయ్యబడినవి</translation>
+<translation id="1298536327547837046">మాల్‌వేర్ స్కానింగ్</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />మీ కుక్కీలను తీసివేయడానికి ప్రయత్నించండి<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">విస్మరించబడిన ఫీచర్‌లు</translation>
<translation id="1320233736580025032">Prc1 (ఎన్వలప్)</translation>
<translation id="132301787627749051">క్లిప్‌బోర్డ్ చిత్రం కోసం వెతకండి</translation>
<translation id="1323433172918577554">మరింత చూపు</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google షీట్‌లు</translation>
<translation id="1527263332363067270">కనెక్షన్ కోసం వేచి ఉన్నాము...</translation>
<translation id="1529521330346880926">10x15 (ఎన్వలప్)</translation>
+<translation id="1530707389502320859">ఇప్పుడు మీరు సందర్శించాలని ప్రయత్నించిన సైట్ నకిలీదిగా అనిపిస్తుంది. URLకు చిన్న, అంత తేలికగా కనపడని మార్పులను చేయడం ద్వారా దాడి చేసేవారు కొన్నిసార్లు సైట్‌లను అనుకరిస్తారు.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">ఈ పేజీ ఇలా చెబుతోంది</translation>
<translation id="153384715582417236">ఇప్పటికి ఇంతే</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">పత్రం అదనపు గమనికలను జోడించడానికి వీలు లేకుండా చాలా అధిక పరిమాణంలో ఉంది</translation>
-<translation id="1721312023322545264">ఈ సైట్‌ని సందర్శించడానికి మీకు <ph name="NAME" /> నుండి అనుమతి అవసరం</translation>
<translation id="1721424275792716183">* అవసరమైన ఫీల్డ్</translation>
<translation id="1727741090716970331">చెల్లుబాటయ్యే కార్డ్ నంబర్‌ను జోడించండి</translation>
<translation id="1728677426644403582">మీరు వెబ్ పేజీ యొక్క మూలాధారాన్ని వీక్షిస్తున్నారు</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">మీరు సందర్శించిన వెబ్‌సైట్‌లు, వాటిపై వెచ్చించిన సమయం</translation>
<translation id="1826516787628120939">తనిఖీ చేస్తోంది</translation>
<translation id="1834321415901700177">ఈ సైట్‌లో హానికరమైన ప్రోగ్రామ్‌లు ఉన్నాయి</translation>
+<translation id="1838374766361614909">శోధనను తీసివేయి</translation>
<translation id="1839551713262164453">విధాన విలువల క్రమబద్ధీకరణ ఎర్రర్‌లతో విఫలమైంది</translation>
<translation id="1842969606798536927">చెల్లింపు</translation>
<translation id="1871208020102129563">.pac స్క్రిప్ట్ URLను కాకుండా, స్థిరమైన ప్రాక్సీ సర్వర్‌లను ఉపయోగించేలా ప్రాక్సీ సెట్ చేయబడింది.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">జాబితాను కుదించు</translation>
<translation id="1898423065542865115">ఫిల్టరింగ్</translation>
<translation id="1914326953223720820">సేవను అన్‌జిప్ చేయండి</translation>
+<translation id="1915697529809968049">CVCకి బదులుగా Touch IDని ఉపయోగించాలా?</translation>
<translation id="1916770123977586577">ఈ సైట్ విషయంలో మీరు అప్‌డేట్ చేసిన సెట్టింగ్‌లను వర్తింపజేయడానికి, ఈ పేజీని మళ్లీ లోడ్ చేయండి</translation>
<translation id="1919345977826869612">ప్రకటనలు</translation>
<translation id="1919367280705858090">నిర్దిష్ట ఎర్రర్ సందేశానికి సంబంధించిన సహాయం పొందండి</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> బుక్‌మార్క్‌లు</translation>
<translation id="1973335181906896915">శ్రేణిగా రూపొందించడంలో ఎర్రర్</translation>
<translation id="1974060860693918893">ఆధునిక</translation>
+<translation id="1974883374937189061">Googleకు <ph name="BEGIN_WHITEPAPER_LINK" />మీరు సందర్శించిన కొన్ని పేజీల URLలు, పరిమిత సిస్టమ్ సమాచారం మరియు కొంత పేజీ కంటెంట్<ph name="END_WHITEPAPER_LINK" />ను పంపడం ద్వారా Chrome సెక్యూరిటీని మెరుగుపరచడంలో సహాయం చేయండి. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">ఫర్మ్‌వేర్ వెర్షన్</translation>
<translation id="1981206234434200693">Chrome బ్రౌజింగ్ చరిత్ర డేటాని తీసివేయి</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{మరియు మరొకటి}other{మరియు మరో #}}</translation>
@@ -244,10 +251,12 @@
<translation id="2202020181578195191">చెల్లుబాటు అయ్యే గడువు ముగింపు సంవత్సరాన్ని నమోదు చేయండి</translation>
<translation id="2212735316055980242">విధానం కనుగొనబడలేదు</translation>
<translation id="2213606439339815911">నమోదులను పొందుతోంది...</translation>
+<translation id="2215727959747642672">ఫైల్‌ను సవరించడం</translation>
<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />లోని హ్యాకర్‌లు మీ పరికరంలో హానికరమైన యాప్‌లను ఇన్‌స్టాల్ చేయవచ్చు. మీ మొబైల్ బిల్‌లో అదృశ్య ఛార్జీలకు కారణం కావచ్చు లేదా మీ వ్యక్తిగత సమాచారాన్ని దొంగిలించవచ్చు. <ph name="BEGIN_LEARN_MORE_LINK" />మరింత తెలుసుకోండి<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ఇంటర్నెట్ లేదు</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />విశ్లేషణల యాప్‌<ph name="END_LINK" />ను ఉపయోగించి మీ కనెక్షన్‌ను సరి చేయండి</translation>
<translation id="2239100178324503013">ఇప్పుడే పంపండి</translation>
+<translation id="2248949050832152960">WebAuthnను ఉపయోగించండి</translation>
<translation id="225207911366869382">ఈ విధానం కోసం ఈ విలువ విస్మరించబడింది.</translation>
<translation id="2257315177824333709">క్షమించండి, మీ కార్డ్‌ను ప్రస్తుతం సేవ్ చేయలేకపోయాము</translation>
<translation id="2262243747453050782">HTTP ఎర్రర్</translation>
@@ -292,7 +301,6 @@
<translation id="2479410451996844060">శోధన URL చెల్లదు.</translation>
<translation id="2482878487686419369">ప్రకటనలు</translation>
<translation id="248348093745724435">మెషీన్ విధానాలు</translation>
-<translation id="2485387744899240041">మీ పరికరం, బ్రౌజర్‌ల వినియోగదారు పేర్లు</translation>
<translation id="2491120439723279231">సర్వర్ యొక్క ప్రమాణపత్రంలో లోపాలు ఉన్నాయి.</translation>
<translation id="2493640343870896922">లెటర్-ప్లస్</translation>
<translation id="2495083838625180221">JSON పార్సర్</translation>
@@ -302,6 +310,7 @@
<translation id="2501278716633472235">వెనుకకు వెళ్ళు</translation>
<translation id="2503184589641749290">ఆమోదించబడిన డెబిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
<translation id="2505268675989099013">ఖాతాను సంరక్షించు</translation>
+<translation id="2515335152965840738">విస్మరించు</translation>
<translation id="2515629240566999685">మీ ప్రాంతంలో సిగ్నల్‌ను తనిఖీ చేయడం</translation>
<translation id="2523886232349826891">ఈ పరికరంలో మాత్రమే సేవ్ చేయబడి ఉంటుంది</translation>
<translation id="2524461107774643265">మరింత సమాచారాన్ని జోడించండి</translation>
@@ -326,7 +335,6 @@
<translation id="2653659639078652383">సమర్పించు</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{ఏవీ లేవు}=1{1 పాస్‌వర్డ్ (<ph name="DOMAIN_LIST" /> కోసం)}=2{2 పాస్‌వర్డ్‌లు (<ph name="DOMAIN_LIST" /> కోసం)}other{# పాస్‌వర్డ్‌లు (<ph name="DOMAIN_LIST" /> కోసం)}}</translation>
<translation id="2666117266261740852">ఇతర ట్యాబ్‌లు లేదా అనువర్తనాలను మూసివేయండి</translation>
-<translation id="267371737713284912">చర్యరద్దు చేయడం కోసం <ph name="MODIFIER_KEY_DESCRIPTION" /> నొక్కండి</translation>
<translation id="2674170444375937751">మీ చరిత్ర నుండి ఈ పేజీలను తొలగించదలిచారా?</translation>
<translation id="2676271551327853224">ROC 8K</translation>
<translation id="2677748264148917807">నిష్క్రమించు</translation>
@@ -336,12 +344,12 @@
<translation id="2704283930420550640">విలువ ఆకృతికి సరిపోలలేదు.</translation>
<translation id="2705137772291741111">ఈ సైట్ యొక్క సేవ్ చేయబడిన (కాష్ చేసిన) కాపీ చదవదగినట్లుగా లేదు.</translation>
<translation id="2709516037105925701">స్వయంపూర్తి</translation>
-<translation id="2712173769900027643">అనుమతి అడుగు</translation>
<translation id="2713444072780614174">తెలుపు</translation>
<translation id="2720342946869265578">సమీపం</translation>
<translation id="2721148159707890343">అభ్యర్థన విజయవంతం అయింది</translation>
<translation id="2728127805433021124">సర్వర్ ప్రమాణపత్రం బలహీన సంతకం అల్గారిథమ్‌ను ఉపయోగించి సంతకం చేయబడింది.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />కనెక్టివిటీ సమస్య విశ్లేషణలను అమలు చేయడం<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">ఈ ఫీచర్‌లను ప్రారంభించడం ద్వారా మీరు బ్రౌజర్ డేటాను కోల్పోవచ్చు లేదా మీ భద్రత లేదా గోప్యత ప్రమాదంలో పడవచ్చు. ప్రారంభించబడిన ఫీచర్‌లు ఈ బ్రౌజర్‌లోని వినియోగదారులందరికీ వర్తిస్తాయి.</translation>
<translation id="2735043616039983645">ఈ విధానంలో వైరుధ్య విలువలతో కూడిన ఒకటి కంటే ఎక్కువ మూలాధారాలు ఉన్నాయి!</translation>
<translation id="2738330467931008676">పికప్ చిరునామాను ఎంచుకోండి</translation>
<translation id="2740531572673183784">సరే</translation>
@@ -352,16 +360,15 @@
<translation id="2784949926578158345">కనెక్షన్ మళ్ళీ సెట్ చేయబడింది.</translation>
<translation id="2788784517760473862">ఆమోదించబడిన క్రెడిట్ కార్డ్‌లు</translation>
<translation id="2792012897584536778">ఈ పరికర నిర్వాహకులు మీరు సందర్శించే వెబ్‌సైట్‌ల కంటెంట్‌ను చూడటానికి వారిని అనుమతించే అవకాశం ఉండే భద్రతా సర్టిఫికెట్‌లను సెటప్ చేశారు.</translation>
-<translation id="2794233252405721443">సైట్ బ్లాక్ చేయబడింది</translation>
<translation id="2799020568854403057">రాబోయే సైట్‌లో హానికరమైన యాప్‌లు ఉన్నాయి</translation>
<translation id="2799223571221894425">మళ్లీ ప్రారంభించు</translation>
<translation id="2803306138276472711">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />మాల్వేర్‌ను గుర్తించింది<ph name="END_LINK" />. సాధారణంగా సురక్షితమైన వెబ్‌సైట్‌‌లకు కూడా కొన్నిసార్లు మాల్వేర్ సోకుతుంది.</translation>
+<translation id="2815364696811431560">సైట్ నుండి నిష్క్రమించండి</translation>
<translation id="2824775600643448204">చిరునామా మరియు శోధన బార్</translation>
<translation id="2826760142808435982"><ph name="CIPHER" />ను ఉపయోగించి కనెక్షన్ ఎన్‌క్రిప్ట్ చేయ‌బ‌డింది, ప్రామాణీకరించబడింది మరియు <ph name="KX" />ను కీలకమైన పరివర్తన విధానంగా ఉపయోగిస్తుంది.</translation>
<translation id="2835170189407361413">ఫారమ్‌ను క్లియర్ చేయి</translation>
<translation id="2847118875340931228">అజ్ఞాత విండోని తెరువు</translation>
<translation id="2850739647070081192">ఆహ్వానం (ఎన్వలప్)</translation>
-<translation id="2851634818064021665">ఈ సైట్‌ను సందర్శించడానికి మీకు అనుమతి అవసరం</translation>
<translation id="2856444702002559011">హ్యాకర్‌లు <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> నుండి మీ సమాచారాన్ని దొంగిలించడానికి ప్రయత్నిస్తూ ఉండవచ్చు (ఉదాహరణకు, పాస్‌వర్డ్‌లు, సందేశాలు లేదా క్రెడిట్ కార్డ్‌లు). <ph name="BEGIN_LEARN_MORE_LINK" />మరింత తెలుసుకోండి<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">కార్డ్‌ను సేవ్ చేయాలా?</translation>
@@ -386,6 +393,7 @@
<translation id="2985306909656435243">ప్రారంభిస్తే, Chromium వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
<translation id="2985398929374701810">చెల్లుబాటు అయ్యే చిరునామాని నమోదు చేయండి</translation>
<translation id="2986368408720340940">ఈ పికప్ పద్ధతి అందుబాటులో లేదు. వేరే పద్ధతిని ప్రయత్నించండి.</translation>
+<translation id="2987034854559945715">సరిపోలే ఫీచర్‌లు లేవు</translation>
<translation id="2991174974383378012">వెబ్‌సైట్‌లతో భాగస్వామ్యం</translation>
<translation id="2991571918955627853">వెబ్‌సైట్ HSTS ఉపయోగిస్తున్నందున మీరు ప్రస్తుతం <ph name="SITE" />‌ను సందర్శించలేరు. నెట్‌వర్క్ ఎర్ర‌ర్‌లు మరియు దాడులు సాధారణంగా తాత్కాలికమే. కనుక ఈ పేజీ తర్వాత పని చేయవచ్చు.</translation>
<translation id="3005723025932146533">సేవ్ చేయబడిన కాపీని చూపు</translation>
@@ -396,6 +404,7 @@
<translation id="3024663005179499861">చెల్లని విధాన రకం</translation>
<translation id="3037605927509011580">ఆవ్, స్నాప్!</translation>
<translation id="3041612393474885105">సర్టిఫికెట్ సమాచారం</translation>
+<translation id="3057676462092457419">DnsOverHttps మోడ్ <ph name="SECURE_DNS_MODE_SECURE" />కు ఇంకా మద్దతు లేదు, ఆ మోడ్ <ph name="SECURE_DNS_MODE_OFF" />కు సెట్ చేయబడింది.</translation>
<translation id="3060227939791841287">C9 (ఎన్వలప్)</translation>
<translation id="3061707000357573562">ప్యాచ్ సేవ</translation>
<translation id="3064966200440839136">బాహ్య అప్లికేషన్‌ ద్వారా చెల్లించడానికి అజ్ఞాత మోడ్ నుండి నిష్క్రమిస్తోంది. కొనసాగించాలా?</translation>
@@ -421,6 +430,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" />లో <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">చెల్లింపును రద్దు చేయండి</translation>
<translation id="3207960819495026254">బుక్‌మార్క్ చేయబడింది</translation>
+<translation id="3209034400446768650">పేజీ, నగదును ఛార్జ్ చేయవచ్చు</translation>
<translation id="3225919329040284222">అంతర్గత అంచనాలకు సరిపోలని ఒక ధృవీకరణ పత్రాన్ని సర్వర్ సమర్పించింది. మిమ్మల్ని సంరక్షించే దిశగా నిర్దిష్ట, ఉన్నత స్ధాయి భద్రతా వెబ్‌సైట్‌ల కోసం ఈ అంచనాలు చేర్చబడ్డాయి.</translation>
<translation id="3226128629678568754">పేజీని లోడ్ చేయడానికి అవసరమైన డేటాను మళ్లీ సమర్పించడం కోసం 'మళ్లీ లోడ్ చేయి' బటన్ క్లిక్ చేయండి.</translation>
<translation id="3227137524299004712">మైక్రోఫోన్</translation>
@@ -428,7 +438,6 @@
<translation id="3229041911291329567">మీ పరికరం, బ్రౌజర్‌ల వెర్షన్ సమాచారం</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> కార్డ్ CVCని నమోదు చేయండి</translation>
<translation id="3234666976984236645">ఈ సైట్‌లో ఎప్పుడూ ముఖ్యమైన కంటెంట్‌ను గుర్తించు</translation>
-<translation id="3254409185687681395">ఈ పేజీని బుక్‌మార్క్ చేయి</translation>
<translation id="3270847123878663523">&amp;మళ్లీ క్రమం చేయడాన్ని రద్దు చేయి</translation>
<translation id="3274521967729236597">పా-కాయ్</translation>
<translation id="3282497668470633863">కార్డ్‌లో పేరుని జోడించండి</translation>
@@ -438,7 +447,6 @@
<translation id="3320021301628644560">బిల్లింగ్ చిరునామాను జోడించండి</translation>
<translation id="3324983252691184275">ముదురు ఎరుపు రంగు</translation>
<translation id="3338095232262050444">సురక్షితం</translation>
-<translation id="3345135638360864351">ఈ సైట్‌ను యాక్సెస్ చేయడానికి మీరు చేసిన అభ్యర్థన <ph name="NAME" />కు పంపబడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="3355823806454867987">ప్రాక్సీ సెట్టింగ్‌లను మార్చు...</translation>
<translation id="3361596688432910856">Chrome ఈ కింది సమాచారాన్ని <ph name="BEGIN_EMPHASIS" />సేవ్ చేయదు<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -472,18 +480,15 @@
<translation id="3462200631372590220">అధునాతనం దాచు</translation>
<translation id="3467763166455606212">కార్డుదారుని పేరు అవసరం</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, ప్రస్తుతం తెరవబడి ఉంది, తెరిచియున్న ట్యాబ్‌కు మారడానికి ట్యాబ్‌ని నొక్కి, ఎంటర్ నొక్కండి</translation>
-<translation id="3479539252931486093">ఊహించని విధంగా ఇది సంభవించిందా? <ph name="BEGIN_LINK" />మాకు తెలియజేయండి<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">ఇప్పుడు కాదు</translation>
<translation id="3484560055331845446">మీరు మీ Google ఖాతాకు యాక్సెస్‌ని కోల్పోవచ్చు. మీరు ఇప్పుడే మీ పాస్‌వర్డ్‌ని మార్చాల్సిందిగా Chrome సిఫార్సు చేస్తోంది. మీరు సైన్ ఇన్ చేయాల్సి ఉంటుంది.</translation>
<translation id="3495081129428749620">పేజీలో కనుగొను
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">మేము ప్రస్తుతం మీ తల్లి/తండ్రిని సంప్రదించలేకపోయాము. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="3512163584740124171">ఈ విధానం విస్మరించబడుతుంది, ఎందుకంటే ఒకే విధాన సమూహం నుండి మరొక విధానం అధిక ప్రాధాన్యతను కలిగి ఉంది.</translation>
<translation id="3528171143076753409">సర్వర్ ప్రమాణపత్రం విశ్వసనీయమైనది కాదు.</translation>
<translation id="3528485271872257980">ముదురు గోధుమ రంగు</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{సమకాలీకరించిన పరికరాల్లో కనీసం 1 అంశం}=1{1 అంశం (మరియు సమకాలీకరించిన పరికరాల్లో మరిన్ని)}other{# అంశాలు (మరియు సమకాలీకరించిన పరికరాల్లో మరిన్ని)}}</translation>
<translation id="3539171420378717834">ఈ పరికరంలో ఈ కార్డ్ కాపీని ఉంచు</translation>
-<translation id="3556433843310711081">మీ నిర్వాహకుడు మీ కోసం దీన్ని అన్‌బ్లాక్ చేయగలరు</translation>
<translation id="3566021033012934673">మీ కనెక్షన్ ప్రైవేట్ కాదు</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" />లో పొందుపరిచిన పేజీ ఇలా చెబుతోంది</translation>
@@ -511,6 +516,7 @@
<translation id="3678529606614285348">కొత్త అజ్ఞాత విండోలో పేజీని తెరవండి (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">క్రాష్ నివేదిక <ph name="CRASH_TIME" />కు క్యాప్చ‌ర్ చేయ‌బ‌డింది, <ph name="UPLOAD_TIME" />కు అప్‌లోడ్ చేయబడింది</translation>
<translation id="3681007416295224113">సర్టిఫికెట్ సమాచారం</translation>
+<translation id="3701427423622901115">రీసెట్ ఆమోదించబడింది.</translation>
<translation id="3704162925118123524">మీరు ఉపయోగించే నెట్‌వర్క్‌కు మీరు దాని లాగిన్ పేజీని సందర్శించడం అవసరం కావచ్చు.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">లోడ్ అవుతోంది...</translation>
@@ -527,6 +533,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />లోని హ్యాకర్‌లు మిమ్మల్ని సాఫ్ట్‌వేర్ ఇన్‌స్టాల్ చేసే విధంగా లేదా మీ వ్యక్తిగత సమాచారాన్ని (ఉదాహరణకు, పాస్‌వర్డ్‌లు, ఫోన్ నంబర్‌లు లేదా క్రెడిట్ కార్డ్‌లు) బహిర్గతం చేసే విధంగా మిమ్మల్ని మాయ చేయవచ్చు. <ph name="BEGIN_LEARN_MORE_LINK" />మరింత తెలుసుకోండి<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">సర్వర్ లోపం వల్ల అనువాదం విఫలమైంది.</translation>
<translation id="3759461132968374835">మీకు ఇటీవల నివేదించిన క్రాష్‌లు లేవు. క్రాష్‌ నివేదన నిలిపివేసినపుడు ఏర్పడే క్రాష్‌లు ఇక్కడ కనిపించవు.</translation>
+<translation id="3760561303380396507">CVCకి బదులుగా Windows Helloను ఉపయోగించాలా?</translation>
<translation id="3761718714832595332">స్థితిని దాచు</translation>
<translation id="3765032636089507299">సురక్షిత బ్రౌజింగ్ పేజీ నిర్మాణంలో ఉంది.</translation>
<translation id="3778403066972421603">ఈ కార్డ్‌ను మీ Google ఖాతాకు మరియు ఈ పరికరంలో సేవ్ చేయాలని అనుకుంటున్నారా?</translation>
@@ -536,6 +543,7 @@
<translation id="3789155188480882154">పరిమాణం 16</translation>
<translation id="3797522431967816232">Prc3 (ఎన్వలప్)</translation>
<translation id="3807873520724684969">హానికర కంటెంట్ బ్లాక్ చేయబడింది.</translation>
+<translation id="3808375843007691220">హెచ్చరిక: ప్రయోగాత్మక ఫీచర్‌లు ముందున్నాయి!</translation>
<translation id="3810973564298564668">నిర్వహించు</translation>
<translation id="382518646247711829">మీరు ప్రాక్సీ సర్వర్‌ను ఉపయోగిస్తే...</translation>
<translation id="3828924085048779000">ఖాళీ రహస్య పదబంధం అనుమతించబడదు.</translation>
@@ -544,11 +552,11 @@
<translation id="3858027520442213535">తేదీని, సమయాన్ని అప్‌డేట్ చేయి</translation>
<translation id="3884278016824448484">వైరుధ్యమైన పరికరం ఐడెంటిఫైయర్</translation>
<translation id="3885155851504623709">పారిష్</translation>
-<translation id="3886446263141354045">మీరు ఈ సైట్‌ను యాక్సెస్ చేయడానికి చేసిన అభ్యర్థన <ph name="NAME" />కు పంపబడింది</translation>
<translation id="3890664840433101773">ఇమెయిల్‌ను జోడించండి</translation>
<translation id="3901925938762663762">కార్డ్ గడువు సమయం ముగిసింది</translation>
<translation id="3906600011954732550">B5-అదనం</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVCకి బదులుగా WebAuthnను ఉపయోగించాలా?</translation>
<translation id="3946209740501886391">ఈ సైట్‌లో ఎల్లప్పుడూ అడగాలి</translation>
<translation id="3949571496842715403">ఈ సర్వర్ తను <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో విషయ ప్రత్యామ్నాయ పేర్లు పేర్కొనబడలేదు. తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా హ్యాకర్ మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన ఇలా జరిగి ఉండవచ్చు.</translation>
<translation id="3949601375789751990">మీ బ్రౌజింగ్ చరిత్ర ఇక్కడ కనిపిస్తుంది</translation>
@@ -559,11 +567,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ఏవీ కాదు}=1{1 సైట్ నుండి }other{# సైట్‌ల నుండి }}</translation>
<translation id="397105322502079400">గణిస్తోంది...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> బ్లాక్ చేయబడింది</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" />, మీ బ్రౌజర్‌లో Chrome ఎంటర్‌ప్రైజ్ అపాయ నివారణను ప్రారంభించింది. 'Chrome ఎంటర్‌ప్రైజ్ అపాయ నివారణ'కు మీ డేటాలో కొంత డేటాకు యాక్సెస్ ఉంది.</translation>
<translation id="3987940399970879459">1 MB కంటే తక్కువ</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 వెబ్ పేజీ సమీపంలో ఉంది}other{# వెబ్ పేజీలు సమీపంలో ఉన్నాయి}}</translation>
<translation id="4030383055268325496">&amp;జోడించడాన్ని రద్దు చేయి</translation>
<translation id="4032320456957708163">మీ బ్రౌజర్ <ph name="ENROLLMENT_DOMAIN" /> ద్వారా నిర్వహించబడుతోంది</translation>
-<translation id="4034375457890803692">మీరు క్లిక్ చేసిన లింక్‌ సాధారణంగా మీరు సందర్శించని సైట్‌కు తీసుకెళుతోంది. మిమ్మల్ని తికమక పెట్టడానికి ఇది ప్రయత్నిస్తుండవచ్చు.</translation>
<translation id="4058922952496707368">కీ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (ఎన్వలప్)</translation>
<translation id="4067947977115446013">చెల్లుబాటు అయ్యే చిరునామాను జోడించండి</translation>
@@ -576,6 +584,7 @@
<translation id="4103249731201008433">పరికరం క్రమ సంఖ్య చెల్లదు</translation>
<translation id="410351446219883937">స్వీయ ప్లే</translation>
<translation id="4103763322291513355">బ్లాక్‌లిస్ట్‌లో ఉన్న URLల జాబితాను మరియు మీ సిస్టమ్ నిర్వాహకుని ద్వారా అమలు చేయబడిన ఇతర విధానాలను చూడటానికి &lt;strong&gt;chrome://policy&lt;/strong&gt;ని సందర్శించండి.</translation>
+<translation id="4108231218301530806">తర్వాతిసారి ఈ కార్డ్‌ను ధృవీకరించడానికి వేలిముద్రను ఉపయోగించండి.</translation>
<translation id="4110652170750985508">మీ చెల్లింపును సమీక్షించండి</translation>
<translation id="4112140312785995938">వెనుకకు జరుపు</translation>
<translation id="4116663294526079822">ఈ సైట్‌లో ఎల్లప్పుడూ అనుమతించు</translation>
@@ -590,6 +599,7 @@
<translation id="4171400957073367226">ధృవీకరణ సంతకం చెల్లదు</translation>
<translation id="4173315687471669144">ఫుల్‌స్కేప్</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{మరో <ph name="ITEM_COUNT" /> అంశం}other{మరో <ph name="ITEM_COUNT" /> అంశాలు}}</translation>
+<translation id="4176463684765177261">ఆపివేయబడింది</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">తర్వాతిసారి మరింత వేగంగా చెల్లించడానికి, మీ కార్డ్, బిల్లింగ్ చిరునామాలను మీ Google ఖాతాకు జోడించండి.</translation>
<translation id="4196861286325780578">&amp;తరలించడాన్ని పునరావృతం చేయి</translation>
@@ -626,6 +636,7 @@
<translation id="4277028893293644418">పాస్‌వర్డ్‌ను రీసెట్ చేయి</translation>
<translation id="4279811152705618813">మీ <ph name="DEVICE_TYPE" /> పరికరం <ph name="ENROLLMENT_DOMAIN" /> నిర్వహణలో ఉంది</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ఈ కార్డ్ మీ Google ఖాతాలో సేవ్ చేయబడింది}other{ఈ కార్డ్‌లు మీ Google ఖాతాలో సేవ్ చేయబడ్డాయి}}</translation>
+<translation id="428847186335018806">మీరు Chromeలో డౌన్‌లోడ్ లేదా అప్‌లోడ్ చేసే ఫైల్‌లను స్కాన్ చేస్తుంది.</translation>
<translation id="42981349822642051">విస్తరించు</translation>
<translation id="4302965934281694568">Chou3 (ఎన్వలప్)</translation>
<translation id="4305817255990598646">స్విచ్</translation>
@@ -655,7 +666,6 @@
<translation id="4435702339979719576">పోస్ట్‌కార్డ్)</translation>
<translation id="443673843213245140">ప్రాక్సీని ఉపయోగించడం ఆపివేయబడింది కానీ స్పష్టమైన ప్రాక్సీ కాన్ఫిగరేషన్ పేర్కొనబడింది.</translation>
<translation id="445100540951337728">ఆమోదించబడిన డెబిట్ కార్డ్‌లు</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> అనుమానాస్పద ప్రవర్తనతో ఉంది</translation>
<translation id="4466881336512663640">ఫారమ్‌లో చేసిన మార్పులను కోల్పోతారు. మీరు ఖచ్చితంగా కొనసాగాలనుకుంటున్నారా?</translation>
<translation id="4477350412780666475">తర్వాతి ట్రాక్</translation>
<translation id="4482953324121162758">ఈ సైట్ అనువదించబడదు.</translation>
@@ -682,6 +692,7 @@
<translation id="4594403342090139922">&amp;తొలగించడాన్ని రద్దు చేయి</translation>
<translation id="4597348597567598915">పరిమాణం 8</translation>
<translation id="4600854749408232102">C6/C5 (ఎన్వలప్)</translation>
+<translation id="464342062220857295">శోధన ఫీచర్‌లు</translation>
<translation id="4646534391647090355">ఇప్పుడు నన్ను అక్కడకు తీసుకు వెళ్లు</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో లోపాలు ఉన్నాయి. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
@@ -690,7 +701,6 @@
<translation id="4691835149146451662">ఆర్కిటెక్చర్-A (ఎన్వలప్)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">మీ కనెక్షన్‌కు అంతరాయం ఏర్పడింది</translation>
-<translation id="471880041731876836">ఈ సైట్‌ను సందర్శించడానికి మీకు అనుమతి లేదు</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows నెట్‌వర్క్ సమస్య విశ్లేషణలను అమలు చేయడం<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">విధానాలను మళ్లీ లోడ్ చేయి</translation>
<translation id="4728558894243024398">ప్లాట్‌ఫారమ్</translation>
@@ -718,7 +728,6 @@
<translation id="4816492930507672669">పేజీకి తగినట్లు అమర్చు</translation>
<translation id="4850886885716139402">వీక్షణ</translation>
<translation id="4854362297993841467">ఈ బట్వాడా పద్ధతి అందుబాటులో లేదు. వేరే పద్ధతిని ప్రయత్నించండి.</translation>
-<translation id="4858792381671956233">ఈ సైట్‌ను సందర్శించడానికి అనుమతించమని కోరుతూ మీ తల్లిదండ్రులకు అభ్యర్థన పంపారు</translation>
<translation id="4864052566555297930">సురక్షిత చిట్కా:</translation>
<translation id="4876188919622883022">సరళీకృత వీక్షణ</translation>
<translation id="4876305945144899064">వినియోగదారు పేరు లేదు</translation>
@@ -742,7 +751,9 @@
<translation id="4974590756084640048">హెచ్చరికలను మళ్లీ ప్రారంభించు</translation>
<translation id="4984339528288761049">Prc5 (ఎన్వలప్)</translation>
<translation id="4989163558385430922">అన్నీ చూడండి</translation>
+<translation id="4989542687859782284">అందుబాటులో లేనివి</translation>
<translation id="4989809363548539747">ఈ ప్లగ్ఇన్‌‌కు మద్దతు లేదు</translation>
+<translation id="4995216769782533993">మీ కార్డ్ వివరాలను ఈ సైట్‌తో షేర్ చేయడానికి, సెక్యూరిటీ కోడ్‌ను ధృవీకరించండి</translation>
<translation id="5002932099480077015">ప్రారంభిస్తే, వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
<translation id="5015510746216210676">మెషీన్ పేరు:</translation>
<translation id="5017554619425969104">మీరు కాపీ చేసిన వచనం</translation>
@@ -771,6 +782,7 @@
<translation id="5115216390227830982">యూరోపియన్-Edp</translation>
<translation id="5115563688576182185">(64-బిట్)</translation>
<translation id="5125394840236832993">B-ప్లస్</translation>
+<translation id="5126510351761255129">మీ కార్డ్‌ను ధృవీకరించండి</translation>
<translation id="5135404736266831032">చిరునామాలను నిర్వహించండి...</translation>
<translation id="5138227688689900538">తక్కువ చూపు</translation>
<translation id="5141240743006678641">మీ Google ఆధారాలతో సింక్ చేయ‌బ‌డిన పాస్‌వర్డ్‌లను ఎన్‌క్రిప్ట్ చేయండి</translation>
@@ -797,6 +809,7 @@
<translation id="5251803541071282808">క్లౌడ్</translation>
<translation id="5252000469029418751">C7 (ఎన్వలప్)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">సిస్టమ్ వ్యాప్తంగా వర్తింపజేయబడే ఫీచర్‌లు యజమాని ద్వారా మాత్రమే సెట్ చేయబడతాయి: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">హెచ్చరిక: ఈ విధానం విలీనం చేయగల నిఘంటువు విధానాలలో భాగం కానందున, PolicyDictionaryMultipleSourceMergeList విధానంలో పేర్కొన్నట్లుగా ఇది విలీనం చేయబడలేదు.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">ముగించు</translation>
@@ -820,7 +833,6 @@
<translation id="536296301121032821">విధాన సెట్టింగ్‌లను నిల్వ చేయడంలో విఫలమైంది</translation>
<translation id="5371425731340848620">కార్డ్‌ని అప్‌డేట్ చేయండి</translation>
<translation id="5377026284221673050">"మీ గడియారం ఆలస్యంగా నడుస్తోంది" లేదా "మీ గడియారం ముందుగా ఉంది" లేదా "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">వ్యక్తిగత సమాచారాన్ని దొంగిలించడానికి లేదా మీ పరికరానికి హాని కలుగజేయడానికి, ఈ పేజీ మిమ్మల్ని మోసగించేందుకు ప్రయత్నించవచ్చు. వ్యక్తిగత సమాచారాన్ని నమోదు చేస్తున్నప్పుడు లేదా డౌన్‌లోడ్ చేసిన ఫైల్‌లను తెరుస్తున్నప్పుడు జాగ్రత్త వహించండి.</translation>
<translation id="5384855140246857529">మీ కార్డ్‌ల‌ను అన్ని పరికరాలలో ఉపయోగించాలంటే, సైన్ ఇన్ చేసి, సమకాలీకరణను ఆన్ చేయండి.</translation>
<translation id="5386426401304769735">ఈ సైట్ సర్టిఫికెట్ గొలుసులో SHA-1 ఉపయోగించి సంతకం చేసిన సర్టిఫికెట్ ఉంది.</translation>
<translation id="538659543871111977">A4-ట్యాబ్</translation>
@@ -834,6 +846,7 @@
<translation id="5457113250005438886">చెల్లదు</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;సవరించడాన్ని పునరావృతం చేయి</translation>
+<translation id="5473728911100096288">ఈ ఫీచర్‌లను ప్రారంభించడం ద్వారా, రాబోయే వెర్షన్‌లలో కనపడకుండా పోయే విస్మరించబడిన ఫీచర్‌లను మీరు ఉపయోగిస్తున్నారు.</translation>
<translation id="5478437291406423475">B6/C4 (ఎన్వలప్)</translation>
<translation id="5481076368049295676">ఈ కంటెంట్ మీ సమాచారాన్ని దొంగిలించగల లేదా తొలగించగల హానికరమైన సాఫ్ట్‌వేర్‌ను మీ పరికరంలో ఇన్‌స్టాల్ చేయడానికి ప్రయత్నించవచ్చు. <ph name="BEGIN_LINK" />ఏదేమైనా చూపు<ph name="END_LINK" /></translation>
<translation id="54817484435770891">చెల్లుబాటు అయ్యే చిరునామాను జోడించండి</translation>
@@ -857,7 +870,6 @@
<translation id="5570825185877910964">ఖాతాను సంరక్షించు</translation>
<translation id="5571083550517324815">ఈ చిరునామా నుండి పికప్ చేసుకోవడం సాధ్యం కాదు. వేరే చిరునామాని ఎంచుకోండి.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 వినియోగంలో ఉంది}other{# వినియోగంలో ఉన్నాయి}})</translation>
-<translation id="5572851009514199876">దయచేసి Chromeను ప్రారంభించి, దానికి సైన్ ఇన్ చేయండి, అప్పుడు ఈ సైట్‌ను యాక్సెస్ చేయడానికి మీకు అనుమతి ఉందో లేదో Chrome తనిఖీ చేయగలదు.</translation>
<translation id="5580958916614886209">మీ గడువు ముగింపు నెలను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి</translation>
<translation id="5586446728396275693">సేవ్ చేయబడిన చిరునామాలు లేవు</translation>
<translation id="5595485650161345191">చిరునామాను సవరించు</translation>
@@ -865,6 +877,7 @@
<translation id="560412284261940334">నిర్వహణకు మద్దతు లేదు</translation>
<translation id="5605670050355397069">లెడ్జర్</translation>
<translation id="5607240918979444548">ఆర్కిటెక్చర్-C</translation>
+<translation id="5608165884683734521">ఈ సైట్ నకిలీ లేదా మోసపూరితమైనది కావచ్చు. ఇప్పుడే నిష్క్రమించమని Chrome సిఫార్సు చేస్తోంది.</translation>
<translation id="5610142619324316209">కనెక్షన్‌ను తనిఖీ చేయడం</translation>
<translation id="5610807607761827392">మీరు కార్డ్‌లు మరియు చిరునామాలను <ph name="BEGIN_LINK" />సెట్టింగ్‌ల<ph name="END_LINK" />లో నిర్వహించగలరు.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> మిమ్మల్ని అనేక సార్లు దారి మళ్లించింది.</translation>
@@ -888,11 +901,11 @@
<translation id="5720705177508910913">ప్రస్తుత వినియోగదారు</translation>
<translation id="5728056243719941842">C5 (ఎన్వలప్)</translation>
<translation id="5730040223043577876">మీరు మీ పాస్‌వర్డ్‌ని ఇతర సైట్‌లలో తిరిగి ఉపయోగించినట్లయితే దీనిని రీసెట్ చేయాల్సిందిగా Chrome సిఫార్సు చేస్తోంది.</translation>
-<translation id="5732392974455271431">మీ తల్లిదండ్రులు దీన్ని మీ కోసం అన్‌బ్లాక్ చేయగలరు</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{కార్డ్‌ను మీ Google ఖాతాలో సేవ్ చేయండి}other{కార్డ్‌లను మీ Google ఖాతాలో సేవ్ చేయండి}}</translation>
<translation id="5763042198335101085">చెల్లుబాటు అయ్యే ఇమెయిల్ చిరునామాను నమోదు చేయండి</translation>
<translation id="5765072501007116331">బట్వాడా పద్ధతులు మరియు అవసరాలను చూడాలంటే, చిరునామాని ఎంచుకోండి</translation>
<translation id="5778550464785688721">MIDI పరికరాల పూర్తి నియంత్రణ</translation>
+<translation id="5781136890105823427">ప్రయోగం ప్రారంభించబడింది</translation>
<translation id="578305955206182703">కాషాయ రంగు</translation>
<translation id="57838592816432529">మ్యూట్ చేయి</translation>
<translation id="5784606427469807560">మీ కార్డ్‌ను నిర్ధారించడంలో సమస్య ఏర్పడింది. మీ ఇంటర్నెట్ కనెక్షన్‌ని తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
@@ -909,13 +922,16 @@
<translation id="5860033963881614850">ఆఫ్ అయ్యింది</translation>
<translation id="5863847714970149516">మీరు చూడబోతున్న పేజీ మీకు డబ్బు ఛార్జ్ చేయడానికి ప్రయత్నించవచ్చు</translation>
<translation id="5866257070973731571">ఫోన్ నంబర్‌ను జోడించండి</translation>
+<translation id="5866898949289125849">మీరు డెవలపర్ సాధనాల పేజీని వీక్షిస్తున్నారు</translation>
<translation id="5869405914158311789">ఈ సైట్‌ను చేరుకోలేకపోయాము</translation>
<translation id="5869522115854928033">సేవ్ చేసిన పాస్‌వర్డ్‌లు</translation>
<translation id="5887400589839399685">కార్డ్ సేవ్ చేయబడింది</translation>
<translation id="5893752035575986141">క్రెడిట్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
+<translation id="5895138241574237353">మళ్ళీ ప్రారంభించు</translation>
<translation id="5901630391730855834">పసుపు</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (సమకాలీకరించబడింది)</translation>
<translation id="5916664084637901428">ఆన్ చేయి</translation>
+<translation id="59174027418879706">ప్రారంభించబడింది</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Google ఖాతాకు కార్డ్‌ను సేవ్ చేయాలా?</translation>
<translation id="5922853866070715753">దాదాపు పూర్తయింది</translation>
@@ -949,6 +965,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">మీ కార్డ్‌లను మీ అన్ని పరికరాలలో ఉపయోగించాలా?</translation>
<translation id="6059925163896151826">USB పరికరాలు</translation>
+<translation id="6060009363608157444">చెల్లని DnsOverHttps మోడ్.</translation>
<translation id="6080696365213338172">మీరు నిర్వాహకుని ద్వారా అందించబడిన ప్రమాణపత్రాన్ని ఉపయోగించి కంటెంట్‌ను యాక్సెస్ చేసారు. మీరు <ph name="DOMAIN" />కు అందించే డేటాకు మీ నిర్వాహకుని ద్వారా అంతరాయం ఏర్పడవచ్చు.</translation>
<translation id="6094273045989040137">అదనపు గమనికను జోడించండి</translation>
<translation id="610911394827799129">మీ Google ఖాతా <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />లో ఇతర రూపాల్లో ఉన్న బ్రౌజింగ్ చరిత్రను కలిగి ఉండవచ్చు</translation>
@@ -997,13 +1014,12 @@
<translation id="6404511346730675251">బుక్‌మార్క్‌ను సవరించు</translation>
<translation id="6406765186087300643">C0 (ఎన్వలప్)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> గడువు ముగింపు తేదీ మరియు CVCని నమోదు చేయండి</translation>
-<translation id="6414888972213066896">మీరు ఈ సైట్‌ను సందర్శించడానికి అనుమతించమని కోరుతూ మీ తల్లి/తండ్రికి అభ్యర్థన పంపారు</translation>
<translation id="6415778972515849510">మీ Google ఖాతాను సంరక్షించుకోవడంలో, మీ పాస్‌వర్డ్‌ను మార్చడంలో Chromium మీకు సహాయపడగలదు.</translation>
-<translation id="6417515091412812850">ప్రమాణపత్రం రద్దు చెయ్యబడిందా అని తనిఖీ చెయ్యడం సాధ్యం కాలేదు.</translation>
<translation id="6431585503458005759">నిల్వ చేయవద్దు</translation>
<translation id="6433490469411711332">సంప్రదింపు సమాచారాన్ని సవరించండి</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> కనెక్ట్ కావడానికి నిరాకరించింది.</translation>
<translation id="6434309073475700221">తొలగించు</translation>
+<translation id="6435221585574090192">Chrome ఎంటర్‌ప్రైజ్ అపాయ నివారణచే ఫ్లాగ్ చేయబడిన భద్రతా ఈవెంట్‌ల డేటాను మీ నిర్వాహకుడితో షేర్ చేస్తుంది. ఈ ఈవెంట్‌లలో పేజీ urlలు, ఫైల్ పేరు, ఫైల్ మెటాడేటా, మీ పరికర వినియోగదారు పేరు, Chrome వినియోగదారు పేరు ఉంటాయి.</translation>
<translation id="6440503408713884761">విస్మరించబడింది</translation>
<translation id="6446163441502663861">Kahu (ఎన్వలప్)</translation>
<translation id="6446608382365791566">మరింత సమాచారాన్ని జోడించండి</translation>
@@ -1012,20 +1028,19 @@
<translation id="6465306955648956876">పాస్‌వర్డ్‌లను నిర్వహించండి...</translation>
<translation id="647261751007945333">పరికర విధానాలు</translation>
<translation id="6476284679642588870">చెల్లింపు పద్ధతులను నిర్వహించండి</translation>
-<translation id="6477321094435799029">Chrome, ఈ పేజీలో అసాధారణ కోడ్‌ను గుర్తించింది. మీ వ్యక్తిగత సమాచారం (ఉదాహరణకు, పాస్‌వర్డ్‌లు, ఫోన్ నంబర్‌లు మరియు క్రెడిట్ కార్డ్‌లు) రక్షించడానికి దాన్ని బ్లాక్ చేసింది.</translation>
<translation id="6489534406876378309">క్రాష్‌లను అప్‌లోడ్ చేయడాన్ని ప్రారంభించండి</translation>
<translation id="6499038740797743453">పాస్‌వర్డ్‌ను రీసెట్ చేయాలా?</translation>
<translation id="6507833130742554667">క్రెడిట్ మరియు డెబిట్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
<translation id="650855688985305916">అవును, నిల్వ చేయి</translation>
<translation id="6508722015517270189">Chromeను పునఃప్రారంభించండి</translation>
<translation id="6517596291481585650">హెచ్చరిక: ఈ విధానం ఒక జాబితా కానందున, విధానంలో పేర్కొన్నట్లుగా ఇది జాబితా రూపంలో విలీనం చేయబడలేదు.</translation>
+<translation id="6518133107902771759">ధృవీకరించు</translation>
<translation id="6521745193039995384">యాక్టివ్‌గా లేదు</translation>
<translation id="6529602333819889595">&amp;తొలగించడాన్ని పునరావృతం చేయి</translation>
<translation id="6534179046333460208">ప్రత్యక్ష వెబ్ సూచనలు</translation>
<translation id="6545864417968258051">బ్లూటూత్ స్కానింగ్</translation>
<translation id="6554795675067793129">మీ ఖాతా <ph name="ENROLLMENT_DOMAIN" /> నిర్వహణలో ఉంది.</translation>
<translation id="6556866813142980365">మళ్లీ చేయి</translation>
-<translation id="6563469144985748109">మీ నిర్వాహకుడు దీన్ని ఇంకా ఆమోదించలేదు</translation>
<translation id="6569060085658103619">మీరు పొడిగింపు పేజీని వీక్షిస్తున్నారు</translation>
<translation id="6578796323535178455">C2 (ఎన్వలప్)</translation>
<translation id="6579990219486187401">లేత గులాబీ రంగు</translation>
@@ -1043,11 +1058,13 @@
<translation id="6643016212128521049">క్లియర్ చేయి</translation>
<translation id="6644283850729428850">ఈ విధానం విస్మరించబడింది.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{ఏవీ లేవు}=1{1 సైట్ నుండి (మీరు మీ Google ఖాతా నుండి సైన్ అవుట్ చేయబడరు)}other{# సైట్‌ల నుండి (మీరు మీ Google ఖాతా నుండి సైన్ అవుట్ చేయబడరు)}}</translation>
+<translation id="6652101503459149953">Windows Helloను ఉపయోగించండి</translation>
<translation id="6657585470893396449">పాస్‌వర్డ్</translation>
<translation id="6670613747977017428">భద్రతకు తిరిగి వెళ్ళు.</translation>
<translation id="6671697161687535275">Chromium నుండి ఫారమ్ సూచనను తీసివేయాలా?</translation>
<translation id="6685834062052613830">సైన్ అవుట్ చేసి, సెటప్‌ను పూర్తి చేయండి</translation>
<translation id="6689271823431384964">మీరు సైన్ ఇన్ చేసి ఉన్నందున, మీ కార్డ్‌లను మీ Google ఖాతాలో సేవ్ చేసుకోగల అవకాశాన్ని Chrome మీకు అందిస్తోంది. మీరు సెట్టింగ్‌లలో ఈ ప్రవర్తనను మార్చవచ్చు. కార్డుదారుడి పేరు మీ ఖాతా నుండి అందించబడింది.</translation>
+<translation id="6707256370811247129">Chromeలో మీరు డౌన్‌లోడ్ లేదా అప్‌లోడ్ చేసే కాష్, ఫైల్‌ల కంటెంట్‌లను స్కాన్ చేస్తుంది.</translation>
<translation id="6710213216561001401">మునుపటి</translation>
<translation id="6710594484020273272">&lt;శోధన పదాన్ని టైప్ చేయండి&gt;</translation>
<translation id="671076103358959139">నమోదు టోకెన్:</translation>
@@ -1055,10 +1072,10 @@
<translation id="6738516213925468394"><ph name="TIME" /> తేదీన మీ <ph name="BEGIN_LINK" />సింక్‌ రహస్య పదబంధం <ph name="END_LINK" />తో మీ డేటా ఎన్‌క్రిప్ట్ చేయ‌బ‌డింది. సింక్‌ను ప్రారంభించడానికి దీన్ని నమోదు చేయండి.</translation>
<translation id="674375294223700098">తెలియని సర్వర్ ప్రమాణపత్రం లోపం.</translation>
<translation id="6744009308914054259">కనెక్షన్ కోసం వేచి ఉన్నప్పుడు, మీరు ఆఫ్‌లైన్ కథనాలను చదవడానికి డౌన్‌లోడ్‌లను సందర్శించవచ్చు.</translation>
+<translation id="6747611005629681221">హెచ్చరిక: విస్మరించబడిన ఫీచర్‌లు ముందున్నాయి!</translation>
<translation id="6753269504797312559">విధానం విలువ</translation>
<translation id="6757797048963528358">మీ పరికరం నిద్రావస్థకు వెళ్లింది.</translation>
<translation id="6768213884286397650">హగకి (పోస్ట్‌కార్డ్)</translation>
-<translation id="6778737459546443941">మీ తల్లి/తండ్రి దీన్ని ఇంకా ఆమోదించలేదు</translation>
<translation id="67862343314499040">నీలి ఊదా రంగు</translation>
<translation id="6786747875388722282">ఎక్స్‌టెన్షన్‌లు</translation>
<translation id="6790428901817661496">ప్లే చేయి</translation>
@@ -1066,6 +1083,7 @@
<translation id="681021252041861472">అవసరమైన ఫీల్డ్</translation>
<translation id="6810899417690483278">అనుకూలీకరణ ID</translation>
<translation id="6825578344716086703"><ph name="DOMAIN" />ను చేరుకోవడానికి మీరు ప్రయత్నించారు, కానీ సర్వర్ (SHA-1 వంటి) బలహీనమైన సంతకం అల్గారిథమ్‌ను ఉపయోగించి సంతకం చేసిన ప్రమాణపత్రాన్ని అందించింది. అంటే సర్వర్ అందించిన భద్రత ఆధారాలు నకిలీ కావచ్చు మరియు సర్వర్ మీరు ఊహించిన సర్వర్ కాకపోవచ్చు (మీరు హ్యాకర్‌తో పరస్పర చర్య చేస్తుండవచ్చు).</translation>
+<translation id="6826370046007623921">డేటా నష్టం నివారణ</translation>
<translation id="6831043979455480757">అనువదించు</translation>
<translation id="6839929833149231406">ప్రాంతం</translation>
<translation id="6852204201400771460">యాప్‌ను మళ్లీ లోడ్ చేయాలా?</translation>
@@ -1078,7 +1096,6 @@
<translation id="6891596781022320156">విధాన స్థాయికి మద్దతు లేదు.</translation>
<translation id="6895330447102777224">మీ కార్డ్ నిర్ధారించబడింది</translation>
<translation id="6897140037006041989">వినియోగదారు ప్రతినిధి</translation>
-<translation id="6903319715792422884"><ph name="BEGIN_WHITEPAPER_LINK" />కొంత సిస్టమ్ సమాచారం మరియు పేజీ కంటెంట్‌<ph name="END_WHITEPAPER_LINK" />ను Googleకి పంపడం ద్వారా సురక్షిత బ్రౌజింగ్‌ని మెరుగుపరచడంలో సహాయపడండి. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">వినియోగదారు:</translation>
<translation id="6934672428414710184">ఇది మీ Google ఖాతాలో ఉన్న పేరు</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> నిర్వహించని ఒక సైట్‌లో మీరు మీ పాస్‌వర్డ్‌ని నమోదు చేసారు. మీ ఖాతాని రక్షించడం కోసం, మీ పాస్‌వర్డ్‌ని ఇతర యాప్‌లు మరియు సైట్‌లలో తిరిగి ఉపయోగించవద్దు.</translation>
@@ -1123,6 +1140,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">లావెండర్ రంగు</translation>
<translation id="717330890047184534">Gaia ID:</translation>
+<translation id="7174545416324379297">విలీనం చేయబడ్డాయి</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">మీరు వెళ్లాలనుకుంటున్న సర్వర్ <ph name="ORIGIN" /> దానికి చేసే అన్ని అభ్యర్థనలకు భద్రతా విధానం వర్తిస్తుందని తెలియజేసింది. కానీ విధానాన్ని డెలివరీ చేయడానికి బదులు అది బ్రౌజర్‌ను మరెక్కడికో మళ్లించింది, దీని వలన <ph name="SITE" /> కోసం మీ అభ్యర్థనను పూర్తి చేయకుండా బ్రౌజర్‌ను నివారిస్తుంది.</translation>
<translation id="7179323680825933600">చెల్లింపు పద్ధతులను సేవ్ చేసి, పూరించు</translation>
@@ -1157,6 +1175,7 @@
<translation id="7320336641823683070">కనెక్షన్ సహాయం</translation>
<translation id="733354035281974745">పరికర స్థానిక ఖాతా భర్తీ</translation>
<translation id="7334320624316649418">&amp;మళ్లీ క్రమం చేయడాన్ని పునరావృతం చేయి</translation>
+<translation id="7337706099755338005">మీ ప్లాట్‌ఫారమ్‌లో అందుబాటులో లేదు.</translation>
<translation id="733923710415886693">సర్వర్ ప్రమాణపత్రాన్ని ప్రమాణపత్రం పారదర్శకత ద్వారా బహిరంగపరచలేదు.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">అనుబంధితం:</translation>
@@ -1188,7 +1207,6 @@
<translation id="7440140511386898319">ఆఫ్‌లైన్‌లో ఉన్నప్పుడు అన్వేషించండి</translation>
<translation id="7441627299479586546">చెల్లని విధాన విషయం</translation>
<translation id="7442725080345379071">లేత నారింజ రంగు</translation>
-<translation id="7444046173054089907">ఈ సైట్ బ్లాక్ చేయబడింది</translation>
<translation id="7445762425076701745">మీరు కనెక్ట్ చేసిన సర్వర్ యొక్క గుర్తింపు పూర్తిగా ధృవీకరించబడలేదు. మీరు దీని యొక్క యాజమాన్యాన్ని ధృవీకరించడానికి అంతర్గత స‌ర్టిఫికెట్‌ అధికారికి మరొక దాని లేని మీ నెట్‌వర్క్‌లో మాత్రమే చెల్లుబాటు అయ్యే పేరును ఉపయోగించి సర్వర్‌కు కనెక్ట్ చేశారు. కొన్ని స‌ర్టిఫికెట్‌ అధికారులు సంబంధం లేని ఈ పేర్లకు స‌ర్టిఫికెట్‌ను జారీ చేస్తారు. మీరు సరైన వెబ్‌సైట్‌కు మరియు అటాకర్‌కు కనెక్ట్ చేశారా అని నిర్ధారించడానికి వేరే మార్గం లేదు.</translation>
<translation id="7451311239929941790">ఈ సమస్య గురించి <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">సార్వజనీన డిఫాల్ట్‌ను ఉపయోగించు (బ్లాక్ చేయి)</translation>
@@ -1210,9 +1228,9 @@
<translation id="7538364083937897561">A2 (ఎన్వలప్)</translation>
<translation id="7542403920425041731">మీరు నిర్ధారించిన తర్వాత, మీ కార్డ్ వివరాలు ఈ సైట్‌తో షేర్ చేయబడతాయి.</translation>
<translation id="7542995811387359312">ఈ ఫారమ్ సురక్షిత కనెక్షన్‌ను ఉపయోగించనందున క్రెడిట్ కార్డ్ వివరాలను ఆటోమేటిక్‌గా పూర్తి చేయడం ఆపివేయబడింది.</translation>
-<translation id="7543525346216957623">మీ తల్లి/తండ్రిని అడగండి</translation>
<translation id="7548892272833184391">కనెక్షన్ ఎర్రర్‌లను పరిష్కరించండి</translation>
<translation id="7549584377607005141">ఈ వెబ్‌పేజీ సరిగ్గా ప్రదర్శించబడటానికి మీరు మునుపు నమోదు చేసిన డేటా అవసరం. మీరు ఈ డేటాను మళ్లీ పంపవచ్చు. కానీ అలా చేయడం వ‌ల్ల‌ ఈ పేజీ మునుపు ప్రదర్శించిన ఏదైనా చర్య పునరావృతం కావచ్చు.</translation>
+<translation id="7550637293666041147">మీ పరికరం వినియోగదారు పేరు మరియు Chrome వినియోగదారు పేరు</translation>
<translation id="7552846755917812628">క్రింది చిట్కాలను ప్రయత్నించండి:</translation>
<translation id="7554791636758816595">కొత్త ట్యాబ్</translation>
<translation id="7564049878696755256">మీరు మీ <ph name="ORG_NAME" /> ఖాతాకు యాక్సెస్‌ని కోల్పోవచ్చు లేదా గుర్తింపు చోరీకి గురి కావచ్చు. మీ పాస్‌వర్డ్‌ని ఇప్పుడే రీసెట్ చేయాల్సిందిగా Chrome సిఫార్సు చేస్తోంది.</translation>
@@ -1227,6 +1245,7 @@
<translation id="7610193165460212391">విలువ <ph name="VALUE" /> పరిధి వెలుపల ఉంది.</translation>
<translation id="7613889955535752492">గడువు ముగింపు: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">మీకు ఇప్పటికే మీ Google ఖాతా పాస్‌వర్డ్ యొక్క మరొక వెర్ష‌న్‌ను ఉపయోగించి ఎన్‌క్రిప్ట్ అయిన డేటా ఉంది. దయచేసి దాన్ని దిగువ నమోదు చేయండి.</translation>
+<translation id="7625784245512586808">Chrome ఎంటర్‌ప్రైజ్ అపాయ నివారణ</translation>
<translation id="7633909222644580952">పనితీరు డేటా, క్రాష్ నివేదికలు</translation>
<translation id="7637571805876720304">Chromium నుండి క్రెడిట్ కార్డ్‌ను తీసివేయాలా?</translation>
<translation id="7638605456503525968">సీరియల్ పోర్ట్‌లు</translation>
@@ -1239,7 +1258,6 @@
<translation id="7668654391829183341">తెలియని పరికరం</translation>
<translation id="7669271284792375604">ఈ సైట్‌లోని దాడి చేసేవారు మీ బ్రౌజింగ్ అనుభవానికి (ఉదాహరణకు, మీ హోమ్ పేజీని మార్చడం లేదా మీరు సందర్శించే సైట్‌ల్లో అదనపు ప్రకటనలను చూపడం ద్వారా) హాని కలిగించే ప్రోగ్రామ్‌లను ఇన్‌స్టాల్ చేసే విధంగా మిమ్మల్ని మోసగించడానికి ప్రయత్నించవచ్చు.</translation>
<translation id="7676643023259824263">క్లిప్‌బోర్డ్ వచనం, <ph name="TEXT" /> కోసం వెతకండి</translation>
-<translation id="7679176406634891508">ప్లాట్‌ఫామ్ మరియు క్లౌడ్</translation>
<translation id="7681101578153515023">శోధన ఇంజిన్‌ను మార్చు</translation>
<translation id="7682287625158474539">ఓడ రవాణా</translation>
<translation id="7687186412095877299">సేవ్ చేయబడిన మీ చెల్లింపు పద్ధతులతో చెల్లింపు ఫారమ్‌లను పూరిస్తుంది</translation>
@@ -1254,7 +1272,6 @@
<translation id="7723047071702270851">కార్డ్‌ను సవరించండి</translation>
<translation id="774634243536837715">హానికరమైన కంటెంట్ బ్లాక్ చేయబడింది.</translation>
<translation id="7752995774971033316">నిర్వహించడం లేదు</translation>
-<translation id="7755287808199759310">మీ తల్లి/తండ్రి దీన్ని మీ కోసం అన్‌బ్లాక్ చేయగలరు</translation>
<translation id="7757555340166475417">డాయ్-పా-కాయ్</translation>
<translation id="7758069387465995638">ఫైర్‌వాల్ లేదా యాంటీవైరస్ సాఫ్ట్‌వేర్ కనెక్షన్‌ను బ్లాక్ చేసి ఉండవచ్చు.</translation>
<translation id="7759163816903619567">ప్రదర్శన డొమైన్:</translation>
@@ -1298,7 +1315,6 @@
<translation id="8004582292198964060">బ్రౌజర్</translation>
<translation id="8009225694047762179">పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ఈ కార్డ్, దీని బిల్లింగ్ చిరునామా సేవ్ చేయబడతాయి. <ph name="USER_EMAIL" />కు సైన్ ఇన్ చేసినప్పుడు మీరు దీనిని ఉపయోగించగలరు.}other{ఈ కార్డ్‌లు, వీటి బిల్లింగ్ చిరునామాలు సేవ్ చేయబడతాయి. <ph name="USER_EMAIL" />కు సైన్ ఇన్ చేసినప్పడు, మీరు వీటిని ఉపయోగించగలరు.}}</translation>
-<translation id="8012647001091218357">మేము ప్రస్తుతం మీ తల్లిదండ్రులను సంప్రదించలేకపోయాము. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8025119109950072390">ఈ సైట్‌లోని దాడి చేసే వారు సాఫ్ట్‌వేర్‌ను ఇన్‌స్టాల్ చేయడం లేదా మీ వ్యక్తిగత సమాచారాన్ని (ఉదాహరణకు, పాస్‌వర్డ్‌లు, ఫోన్ నంబర్‌లు లేదా క్రెడిట్ కార్డ్‌లు) వెల్లడించడం వంటి ప్రమాదకరమైన పనులు చేసేలా మిమ్మల్ని మాయ చేయవచ్చు.</translation>
<translation id="8034522405403831421">ఈ పేజీ <ph name="SOURCE_LANGUAGE" />లో ఉంది. దీన్ని <ph name="TARGET_LANGUAGE" />లోకి అనువదించాలా?</translation>
<translation id="8035152190676905274">పెన్</translation>
@@ -1309,6 +1325,7 @@
<translation id="8041940743680923270">సార్వజనీన డిఫాల్ట్‌ను ఉపయోగించు (అడుగు)</translation>
<translation id="8042918947222776840">పికప్ పద్ధతిని ఎంచుకోండి</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />"ని సరిగ్గా కాన్ఫిగర్ చేయలేదు. సాధారణంగా "<ph name="SOFTWARE_NAME" />"ని అన్ఇన్‌స్టాల్ చేయడం ద్వారా సమస్య పరిష్కారం కావచ్చు. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">ఇప్పటి నుండి మీరు కార్డ్ సెక్యూరిటీ కోడ్‌ను నమోదు చేయనవసరం లేదు</translation>
<translation id="8066955247577885446">క్షమించండి, ఏదో తప్పు జరిగింది.</translation>
<translation id="8074253406171541171">10x13 (ఎన్వలప్)</translation>
<translation id="8078141288243656252">తిప్పినప్పుడు అదనపు గమనికలను అందించడం సాధ్యపడదు</translation>
@@ -1339,6 +1356,7 @@
<translation id="8211406090763984747">కనెక్షన్ సురక్షితంగా ఉంది</translation>
<translation id="8218327578424803826">కేటాయించిన స్థానం:</translation>
<translation id="8220146938470311105">C7/C6 (ఎన్వలప్)</translation>
+<translation id="8220639454292072926">ఎంటర్‌ప్రైజ్ నివేదన</translation>
<translation id="8225771182978767009">ఈ కంప్యూటర్‌ను సెటప్ చేసిన వ్యక్తి ఈ సైట్‌ను బ్లాక్ చేయడం ఎంచుకున్నారు.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">కొత్త అజ్ఞాత ట్యాబ్‌లో పేజీని తెరవండి</translation>
@@ -1393,23 +1411,23 @@
<translation id="8508648098325802031">శోధన చిహ్నం</translation>
<translation id="8522552481199248698">మీ Google ఖాతాను సంరక్షించుకోవడంలో, మీ పాస్‌వర్డ్‌ను మార్చడంలో Chrome మీకు సహాయపడగలదు.</translation>
<translation id="8543181531796978784">మీరు <ph name="BEGIN_ERROR_LINK" />గుర్తింపు సమస్యను నివేదించవచ్చు<ph name="END_ERROR_LINK" /> లేదా మీకు మీ భద్రతకు పొంచి ఉన్న ప్రమాదాలు అర్థం అయ్యి ఉంటే, మ<ph name="BEGIN_LINK" />ఈ అసురక్షిత సైట్‌ను సందర్శించండి<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">ప్రశ్నలు ఏమైనా ఉన్నాయా? మీ ప్రొఫైల్‌ను పర్యవేక్షించే వ్యక్తిని సంప్రదించండి.</translation>
<translation id="8553075262323480129">పేజీ భాష నిర్థారించలేకపోయినందున అనువాదం విఫలమైంది.</translation>
<translation id="8557066899867184262">మీ కార్డు వెనుకవైపు CVC ఉంటుంది.</translation>
<translation id="8559762987265718583">మీ పరికరం తేదీ మరియు సమయం <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> తప్పుగా ఉన్నందున (<ph name="DATE_AND_TIME" />)కు ప్రైవేట్ కనెక్షన్ ఏర్పాటు చేయబడదు.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> అనుమానాస్పద సైట్</translation>
<translation id="8564985650692024650">మీరు మీ <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> పాస్‌వర్డ్‌ని ఇతర సైట్‌లలో తిరిగి ఉపయోగించినట్లయితే దీనిని రీసెట్ చేయాల్సిందిగా Chromium సిఫార్సు చేస్తోంది.</translation>
<translation id="8571890674111243710">పేజీని <ph name="LANGUAGE" />కు అనువదిస్తోంది...</translation>
<translation id="858637041960032120">ఫోన్ నం. జోడిం.</translation>
-<translation id="859285277496340001">ఇది రద్దు చెయ్యబడిందా అని తనిఖీ చెయ్యడానికి ప్రమాణపత్రం విధానాన్ని పేర్కొనలేదు.</translation>
<translation id="860043288473659153">కార్డుదారుని పేరు</translation>
<translation id="861775596732816396">పరిమాణం 4</translation>
-<translation id="8620436878122366504">మీ తల్లిదండ్రులు దీన్ని ఇంకా ఆమోదించలేదు</translation>
<translation id="8622948367223941507">చట్ట సంబంధితం-అదనం</translation>
<translation id="8625384913736129811">ఈ కార్డ్‌ను ఈ పరికరానికి సేవ్ చేయి</translation>
<translation id="8626112503828625890">బిల్లింగ్ వివరాలను Google ఖాతాలో నిల్వ చేయాలా?</translation>
+<translation id="8647750283161643317">అన్నింటినీ డిఫాల్ట్‌కు రీసెట్ చేయి</translation>
<translation id="8663226718884576429">ఆర్డర్ సారాంశం, <ph name="TOTAL_LABEL" />, మరిన్ని వివరాలు</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, సమాధానం, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">అందుబాటులో ఉంది</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" />కు మీ కనెక్షన్ ఎన్‌క్రిప్ట్ చేయ‌బ‌డ‌లేదు.</translation>
<translation id="8718314106902482036">చెల్లింపు పూర్తి కాలేదు</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, శోధన సూచన</translation>
@@ -1420,6 +1438,7 @@
<translation id="8738058698779197622">సురక్షిత కనెక్షన్‌ను ఏర్పాటు చేయడానికి, మీ గడియారాన్ని సరైన సమయానికి సెట్ చేయాలి. ఎందుకంటే వెబ్‌సైట్‌లు వాటిని గుర్తించడానికి ఉపయోగించే సర్టిఫికెట్‌లు నిర్దిష్ట కాలవ్యవధులలో మాత్రమే చెల్లుబాటు అవుతాయి. మీ పరికరం యొక్క గడియారం సమయం తప్పుగా ఉన్నందున, Chromium ఈ సర్టిఫికెట్‌లను ధృవీకరించలేకపోయింది.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS చిరునామా&lt;/abbr&gt; కనుగొనబడలేదు. సమస్యను నిర్ధారిస్తోంది.</translation>
<translation id="874846938927089722">ఆమోదించే క్రెడిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
+<translation id="874918643257405732">ఈ ట్యాబ్‌ను బుక్‌మార్క్ చేయి</translation>
<translation id="8759274551635299824">ఈ కార్డ్ గడువు ముగిసింది</translation>
<translation id="8761567432415473239">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />హానికర ప్రోగ్రామ్‍లను కనుగొనింది<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB పరికరం</translation>
@@ -1449,6 +1468,7 @@
<translation id="8938939909778640821">ఆమోదించబడిన క్రెడిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
<translation id="8943282376843390568">నిమ్మపండు రంగు</translation>
<translation id="8957210676456822347">క్యాప్టివ్ పోర్టల్ ప్రామాణీకరణ</translation>
+<translation id="8962950042226115166">అనుమానాస్పద సైట్</translation>
<translation id="8968766641738584599">కార్డ్‌ని సేవ్ చేయండి</translation>
<translation id="8971063699422889582">సర్వర్ ప్రమాణపత్రం గడువు ముగిసింది.</translation>
<translation id="8975012916872825179">ఫోన్ నంబర్‌లు, ఇమెయిల్ చిరునామాలు మరియు బట్వాడా చిరునామాలు లాంటి సమాచారం ఉంటుంది</translation>
@@ -1471,24 +1491,24 @@
<translation id="9035022520814077154">భద్రతా ఎర్రర్</translation>
<translation id="9038649477754266430">పేజీలను మరింత త్వరగా లోడ్ చేయడానికి సూచన సేవను ఉపయోగించండి</translation>
<translation id="9039213469156557790">అలాగే, ఈ పేజీలో సురక్షితం కాని ఇతర వనరులు ఉన్నాయి. ఈ వనరులను బదిలీ చేస్తున్నప్పుడు ఇతరులు చూడగలరు మరియు దాడికి పాల్పడేవారు పేజీ ప్రవర్తనను మార్చేలా వీటిని సవరించగలరు.</translation>
+<translation id="9044359186343685026">Touch IDని ఉపయోగించు</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">మీరు <ph name="DOMAIN" />ను చేరుకోవడానికి ప్రయత్నించారు, కానీ సర్వర్ ఒక చెల్లుబాటులో లేని ప్రమాణపత్రంను అందించింది.</translation>
<translation id="9050666287014529139">రహస్య పదబంధం</translation>
<translation id="9065203028668620118">సవరించు</translation>
<translation id="9065745800631924235">చరిత్ర నుండి <ph name="TEXT" /> శోధన</translation>
<translation id="9069693763241529744">పొడిగింపు ద్వారా బ్లాక్ చేయబడింది</translation>
-<translation id="9076283476770535406">ఇందులో పెద్దలకు మాత్రమే తగిన కంటెంట్ ఉండవచ్చు</translation>
<translation id="9076630408993835509">ఈ బ్రౌజర్‌ను కంపెనీ లేదా సంస్థ నిర్వహించట్లేదు. ఈ పరికరంలోని కార్యకలాపం Chrome వెలుపల నిర్వహిస్తుండవచ్చు. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">మరింత సమాచారం ఆవశ్యకం</translation>
<translation id="9080712759204168376">ఆర్డర్ సారాంశం</translation>
<translation id="9089260154716455634">తీరిక వేళల విధానం:</translation>
<translation id="9095388113577226029">మరిన్ని భాషలు...</translation>
+<translation id="9098981495403789647">మీ నిర్వాహకులు, మీ బ్రౌజర్‌లో Chrome ఎంటర్‌ప్రైజ్ అపాయ నివారణను ప్రారంభించారు. 'Chrome ఎంటర్‌ప్రైజ్ అపాయ నివారణ'కు మీ డేటాలో కొంత డేటాకు యాక్సెస్ ఉంది.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> సాధారణంగా మీ సమాచారాన్ని రక్షించడానికి ఎన్‌క్రిప్ష‌న్‌ను ఉపయోగిస్తుంది. Chromium ఈసారి <ph name="SITE" />‌ను కనెక్ట్ చేయడానికి ప్రయత్నించినప్పుడు, వెబ్‌సైట్ అసాధారణ మరియు తప్పు ఆధారాలు అని ప్రతిస్పందించింది. దాడి చేసే వ్యక్తి <ph name="SITE" />గా వ్యవహరించి మోసగించడానికి ప్రయత్నిస్తున్నప్పుడు లేదా Wi-Fi సైన్-ఇన్ స్క్రీన్ కనెక్షన్‌కు అంతరాయం కలిగించినప్పుడు ఇలా జరగవచ్చు. ఎలాంటి డేటా వినిమయం సంభవించక ముందే Chromium, కనెక్షన్‌ను ఆపివేసినందున మీ సమాచారం ఇప్పటికీ సురక్షితంగానే ఉంది.</translation>
<translation id="9106062320799175032">బిల్లింగ్ చిరునామాను జోడించండి</translation>
<translation id="9114524666733003316">కార్డ్‌ నిర్ధారించబడుతోంది...</translation>
<translation id="9128870381267983090">నెట్‌వర్క్‌కి కనెక్ట్ చేయి</translation>
<translation id="9137013805542155359">అసలును చూపించు</translation>
-<translation id="9137248913990643158">ఈ యాప్‌ను ఉపయోగించే ముందు, దయచేసి Chromeను ప్రారంభించి, దానికి సైన్ ఇన్ చేయండి.</translation>
<translation id="9141013498910525015">చిరునామాలను నిర్వహించండి</translation>
<translation id="9148088599418889305">షిప్పింగ్ పద్ధతిని ఎంచుకోండి</translation>
<translation id="9148507642005240123">&amp;సవరించడాన్ని రద్దు చేయి</translation>
diff --git a/chromium/components/strings/components_strings_th.xtb b/chromium/components/strings/components_strings_th.xtb
index 4e2389adcda..8cff5b98d33 100644
--- a/chromium/components/strings/components_strings_th.xtb
+++ b/chromium/components/strings/components_strings_th.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">เพิ่มชื่อบนบัตร</translation>
<translation id="1089439967362294234">เปลี่ยนรหัสผ่าน</translation>
+<translation id="1096545575934602868">ช่องนี้ต้องมีข้อมูลไม่เกิน <ph name="MAX_ITEMS_LIMIT" /> รายการ ระบบจะทิ้งรายการอื่นๆ ทั้งหมด</translation>
<translation id="109743633954054152">จัดการรหัสผ่านในการตั้งค่า Chrome</translation>
<translation id="1103523840287552314">แปลภาษา<ph name="LANGUAGE" />ทุกครั้ง</translation>
<translation id="1107591249535594099">หากเลือก Chrome จะจัดเก็บสำเนาของบัตรบนอุปกรณ์นี้เพื่อการกรอกข้อมูลแบบฟอร์มอย่างรวดเร็ว</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">เข้าถึง<ph name="BEGIN_LINK" />สำเนาแคช<ph name="END_LINK" />ของ <ph name="URL" /></translation>
<translation id="1156303062776767266">คุณกำลังดูไฟล์ในเครื่องหรือไฟล์ที่แชร์</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> ปิดการเชื่อมต่อโดยไม่คาดคิด</translation>
+<translation id="115926840831309955">ตรวจสอบ CVC แล้วลองอีกครั้งหรืออัปเดตวันที่หมดอายุ</translation>
<translation id="1161325031994447685">เชื่อมต่อ Wi-Fi ใหม่</translation>
<translation id="1165039591588034296">ข้อผิดพลาด</translation>
<translation id="1175364870820465910">&amp;พิมพ์...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"ซอฟต์แวร์ในคอมพิวเตอร์ของคุณทำให้ Chrome เชื่อมต่อกับเว็บอย่างปลอดภัยไม่ได้" (คอมพิวเตอร์ที่ใช้ระบบปฏิบัติการ Windows เท่านั้น)</translation>
<translation id="1294154142200295408">บรรทัดคำสั่งรูปแบบต่างๆ</translation>
<translation id="129553762522093515">เพิ่งปิด</translation>
+<translation id="1298536327547837046">การสแกนหามัลแวร์</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />ลองล้างคุกกี้<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">ฟีเจอร์ที่เลิกใช้งานแล้ว</translation>
<translation id="1320233736580025032">Prc1 (ซองจดหมาย)</translation>
<translation id="132301787627749051">ค้นหารูปภาพในคลิปบอร์ด</translation>
<translation id="1323433172918577554">แสดงเพิ่มเติม</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google ชีต</translation>
<translation id="1527263332363067270">กำลังรอการเชื่อมต่อ…</translation>
<translation id="1529521330346880926">10x15 (ซองจดหมาย)</translation>
+<translation id="1530707389502320859">เว็บไซต์ที่คุณเพิ่งพยายามเข้าถึงดูเป็นเว็บไซต์ปลอม บางครั้งผู้โจมตีจะเลียนแบบเว็บไซต์ต่างๆ โดยทำการเปลี่ยนแปลงเล็กๆ น้อยๆ ที่สังเกตเห็นได้ยากกับ URL</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">หน้านี้บอกว่า</translation>
<translation id="153384715582417236">เสร็จเรียบร้อย</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">ระบบปฏิบัติการ</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">เอกสารมีขนาดใหญ่เกินกว่าจะใส่หมายเหตุได้</translation>
-<translation id="1721312023322545264">คุณต้องได้รับสิทธิ์จาก <ph name="NAME" /> เพื่อเข้าชมเว็บไซต์นี้</translation>
<translation id="1721424275792716183">* ช่องที่ต้องกรอก</translation>
<translation id="1727741090716970331">เพิ่มหมายเลขบัตรที่ถูกต้อง</translation>
<translation id="1728677426644403582">คุณกำลังดูซอร์สโค้ดของหน้าเว็บ</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">เว็บไซต์ที่คุณเข้าชมและเวลาที่ใช้ไป</translation>
<translation id="1826516787628120939">กำลังตรวจสอบ</translation>
<translation id="1834321415901700177">เว็บไซต์นี้มีโปรแกรมอันตราย</translation>
+<translation id="1838374766361614909">ล้างการค้นหา</translation>
<translation id="1839551713262164453">การตรวจสอบความถูกต้องของค่านโยบายมีข้อผิดพลาดและล้มเหลว</translation>
<translation id="1842969606798536927">จ่าย</translation>
<translation id="1871208020102129563">พร็อกซีถูกตั้งค่าให้ใช้พร็อกซีเซิร์ฟเวอร์แบบคงที่ ไม่ใช่ URL สคริปต์ .pac</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">ยุบรายการ</translation>
<translation id="1898423065542865115">การกรอง</translation>
<translation id="1914326953223720820">บริการแตกไฟล์</translation>
+<translation id="1915697529809968049">ใช้ Touch ID แทน CVC ไหม</translation>
<translation id="1916770123977586577">โหลดหน้านี้ซ้ำเพื่อใช้การตั้งค่าที่อัปเดตกับไซต์นี้</translation>
<translation id="1919345977826869612">โฆษณา</translation>
<translation id="1919367280705858090">ขอความช่วยเหลือเกี่ยวกับข้อความแสดงข้อผิดพลาดที่เจาะจง</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">บุ๊กมาร์กของ <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">ข้อผิดพลาดในการจัดเรียง</translation>
<translation id="1974060860693918893">ขั้นสูง</translation>
+<translation id="1974883374937189061">ช่วยปรับปรุงความปลอดภัยของ Chrome โดยการส่ง <ph name="BEGIN_WHITEPAPER_LINK" />URL ของหน้าเว็บบางหน้าที่คุณเข้าชม ข้อมูลระบบที่จำกัด และเนื้อหาบางส่วนของหน้า<ph name="END_WHITEPAPER_LINK" />ไปให้ Google <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">เวอร์ชันของเฟิร์มแวร์</translation>
<translation id="1981206234434200693">ล้างข้อมูลประวัติการเข้าชมของ Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{และอีก 1 แอป}other{และอีก # แอป}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">ป้อนปีที่หมดอายุที่ถูกต้อง</translation>
<translation id="2212735316055980242">ไม่พบนโยบาย</translation>
<translation id="2213606439339815911">กำลังดึงรายการ...</translation>
+<translation id="2215727959747642672">การแก้ไขไฟล์</translation>
<translation id="2218879909401188352">ผู้โจมตีที่กำลังอยู่ใน <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> สามารถติดตั้งแอปอันตรายที่ทำลายอุปกรณ์ของคุณ เพิ่มค่าใช้จ่ายแฝงในใบแจ้งยอดมือถือ หรือขโมยข้อมูลส่วนบุคคล <ph name="BEGIN_LEARN_MORE_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">ไม่มีอินเทอร์เน็ต</translation>
<translation id="2230458221926704099">แก้ไขการเชื่อมต่อของคุณด้วย<ph name="BEGIN_LINK" />แอปการวินิจฉัย<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">ส่งเลย</translation>
+<translation id="2248949050832152960">ใช้ WebAuthn</translation>
<translation id="225207911366869382">เลิกใช้งานค่านี้กับนโยบายนี้</translation>
<translation id="2257315177824333709">ขออภัย บันทึกบัตรไม่ได้ในตอนนี้</translation>
<translation id="2262243747453050782">ข้อผิดพลาดของ HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL ค้นหาไม่ถูกต้อง</translation>
<translation id="2482878487686419369">การแจ้งเตือน</translation>
<translation id="248348093745724435">นโยบายเครื่อง</translation>
-<translation id="2485387744899240041">ชื่อผู้ใช้สำหรับอุปกรณ์และเบราว์เซอร์ของคุณ</translation>
<translation id="2491120439723279231">ใบรับรองของเซิร์ฟเวอร์มีข้อผิดพลาด</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">โปรแกรมแยกวิเคราะห์ JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">ย้อนกลับ</translation>
<translation id="2503184589641749290">บัตรเดบิตและบัตรเติมเงินที่ยอมรับ</translation>
<translation id="2505268675989099013">ปกป้องบัญชี</translation>
+<translation id="2515335152965840738">ไม่สนใจ</translation>
<translation id="2515629240566999685">ตรวจสอบสัญญาณในพื้นที่ของคุณ</translation>
<translation id="2523886232349826891">บันทึกไว้เฉพาะในอุปกรณ์นี้</translation>
<translation id="2524461107774643265">เพิ่มข้อมูลอื่นๆ</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">ส่ง</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{ไม่มี}=1{มีรหัสผ่าน 1 รายการ (สำหรับ <ph name="DOMAIN_LIST" />)}=2{มีรหัสผ่าน 2 รายการ (สำหรับ <ph name="DOMAIN_LIST" />)}other{มีรหัสผ่าน # รายการ (สำหรับ <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">ปิดแท็บหรือแอปอื่นๆ</translation>
-<translation id="267371737713284912">กด <ph name="MODIFIER_KEY_DESCRIPTION" /> เพื่อเลิกทำ</translation>
<translation id="2674170444375937751">คุณแน่ใจหรือไม่ว่าต้องการนำออกหน้าเหล่านี้ออกจากประวัติการเข้าชมของคุณ</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">ออก</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">ค่าไม่ตรงกับรูปแบบ</translation>
<translation id="2705137772291741111">อ่านสำเนาที่บันทึกไว้ (แคช) ของเว็บไซต์นี้ไม่ได้</translation>
<translation id="2709516037105925701">ป้อนอัตโนมัติ</translation>
-<translation id="2712173769900027643">ขออนุญาต</translation>
<translation id="2713444072780614174">สีขาว</translation>
<translation id="2720342946869265578">ใกล้เคียง</translation>
<translation id="2721148159707890343">คำขอสำเร็จ</translation>
<translation id="2728127805433021124">ใบรับรองของเซิร์ฟเวอร์ถูกเซ็นชื่อด้วยอัลกอริทึมลายเซ็นที่ไม่รัดกุม</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />เรียกใช้การวินิจฉัยการเชื่อมต่อ<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">การเปิดใช้ฟีเจอร์เหล่านี้อาจทำให้คุณสูญเสียข้อมูลในเบราว์เซอร์หรือทำให้เกิดความเสี่ยงต่อความปลอดภัยหรือความเป็นส่วนตัว ฟีเจอร์ที่เปิดใช้จะมีผลกับผู้ใช้ทั้งหมดของเบราว์เซอร์นี้</translation>
<translation id="2735043616039983645">นโยบายนี้มีแหล่งที่มามากกว่า 1 แห่งที่มีค่าขัดแย้งกัน</translation>
<translation id="2738330467931008676">เลือกที่อยู่สำหรับรับสินค้า</translation>
<translation id="2740531572673183784">ตกลง</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">การเชื่อมต่อได้รับการรีเซ็ตแล้ว</translation>
<translation id="2788784517760473862">บัตรเครดิตที่ยอมรับ</translation>
<translation id="2792012897584536778">ผู้ดูแลระบบของอุปกรณ์นี้ได้ตั้งค่าใบรับรองความปลอดภัยที่อาจอนุญาตให้ตนดูเนื้อหาของเว็บไซต์ที่คุณเข้าชมได้</translation>
-<translation id="2794233252405721443">เว็บไซต์ที่ถูกบล็อก</translation>
<translation id="2799020568854403057">เว็บไซต์ที่จะเปิดมีแอปอันตราย</translation>
<translation id="2799223571221894425">เปิดใหม่</translation>
<translation id="2803306138276472711">เมื่อเร็วๆ นี้ Google Safe Browsing <ph name="BEGIN_LINK" />ตรวจพบมัลแวร์<ph name="END_LINK" />ใน <ph name="SITE" /> เว็บไซต์ที่โดยปกติจะปลอดภัยบางครั้งอาจติดมัลแวร์</translation>
+<translation id="2815364696811431560">ออกจากเว็บไซต์</translation>
<translation id="2824775600643448204">ที่อยู่และแถบค้นหา</translation>
<translation id="2826760142808435982">การเชื่อมต่อถูกเข้ารหัสและรับรองความถูกต้องโดยใช้ <ph name="CIPHER" /> และใช้ <ph name="KX" /> เป็นกลไกการแลกเปลี่ยนคีย์</translation>
<translation id="2835170189407361413">ล้างฟอร์ม</translation>
<translation id="2847118875340931228">เปิดหน้าต่างที่ไม่ระบุตัวตน</translation>
<translation id="2850739647070081192">Invite (ซองจดหมาย)</translation>
-<translation id="2851634818064021665">คุณต้องได้รับสิทธิ์เพื่อเข้าชมไซต์นี้</translation>
<translation id="2856444702002559011">ผู้โจมตีอาจพยายามขโมยข้อมูลจาก <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (ตัวอย่างเช่น รหัสผ่าน ข้อความ หรือบัตรเครดิต) <ph name="BEGIN_LEARN_MORE_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">บันทึกบัตรไหม</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">หากเปิดใช้ไว้ Chromium จะจัดเก็บสำเนาบัตรของคุณในอุปกรณ์นี้เพื่อการกรอกแบบฟอร์มที่รวดเร็วขึ้น</translation>
<translation id="2985398929374701810">ป้อนที่อยู่ที่ถูกต้อง</translation>
<translation id="2986368408720340940">วิธีการรับสินค้านี้ไม่พร้อมให้บริการ โปรดลองใช้วิธีการอื่น</translation>
+<translation id="2987034854559945715">ไม่มีฟีเจอร์ที่ตรงกัน</translation>
<translation id="2991174974383378012">การแชร์กับเว็บไซต์</translation>
<translation id="2991571918955627853">คุณไม่สามารถไปที่ <ph name="SITE" /> ได้ในขณะนี้เนื่องจากเว็บไซต์ใช้ HSTS โดยปกติข้อผิดพลาดของเครือข่ายและการโจมตีจะเกิดขึ้นเพียงชั่วคราว หน้านี้จึงอาจใช้งานได้ในภายหลัง</translation>
<translation id="3005723025932146533">แสดงสำเนาที่บันทึกไว้</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">ประเภทนโยบายไม่ถูกต้อง</translation>
<translation id="3037605927509011580">แย่จัง!</translation>
<translation id="3041612393474885105">ข้อมูลในใบรับรอง</translation>
+<translation id="3057676462092457419">ยังไม่รองรับโหมด DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" /> มีการตั้งค่าโหมดดังกล่าวเป็น <ph name="SECURE_DNS_MODE_OFF" /></translation>
<translation id="3060227939791841287">C9 (ซองจดหมาย)</translation>
<translation id="3061707000357573562">แพตช์บริการ</translation>
<translation id="3064966200440839136">ออกจากโหมดไม่ระบุตัวตนเพื่อชำระเงินผ่านแอปพลิเคชันภายนอก ดำเนินการต่อไหม</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> ใน <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">ยกเลิกการชำระเงิน</translation>
<translation id="3207960819495026254">บุ๊กมาร์กแล้ว</translation>
+<translation id="3209034400446768650">อาจมีการเรียกเก็บเงินในหน้านี้</translation>
<translation id="3225919329040284222">เซิร์ฟเวอร์แสดงใบรับรองที่ไม่ตรงกับการคาดการณ์ที่มีอยู่ การคาดการณ์เหล่านี้มีอยู่ในบางเว็บไซต์ที่มีการรักษาความปลอดภัยสูงเพื่อปกป้องคุณ</translation>
<translation id="3226128629678568754">กดปุ่มโหลดซ้ำเพื่อส่งซ้ำข้อมูลที่จำเป็นในการโหลดหน้าเว็บ</translation>
<translation id="3227137524299004712">ไมโครโฟน</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">ข้อมูลเวอร์ชันเกี่ยวกับอุปกรณ์และเบราว์เซอร์</translation>
<translation id="323107829343500871">ป้อน CVC สำหรับ <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">ตรวจหาเนื้อหาที่สำคัญบนไซต์นี้เสมอ</translation>
-<translation id="3254409185687681395">บุ๊กมาร์กหน้านี้</translation>
<translation id="3270847123878663523">&amp;เลิกทำการจัดลำดับใหม่</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">เพิ่มชื่อบนบัตร</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">เพิ่มที่อยู่สำหรับการเรียกเก็บเงิน</translation>
<translation id="3324983252691184275">แดงเข้ม</translation>
<translation id="3338095232262050444">ปลอดภัย</translation>
-<translation id="3345135638360864351">ไม่สามารถส่งคำขอเข้าถึงไซต์นี้ไปยัง <ph name="NAME" /> ได้ โปรดลองอีกครั้ง</translation>
<translation id="3355823806454867987">เปลี่ยนการตั้งค่าพร็อกซี...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />จะไม่บันทึก<ph name="END_EMPHASIS" />ข้อมูลต่อไปนี้:
<ph name="BEGIN_LIST" />
@@ -478,17 +486,14 @@
<translation id="3462200631372590220">ซ่อนข้อมูลขั้นสูง</translation>
<translation id="3467763166455606212">ต้องระบุชื่อผู้ถือบัตร</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> เปิดอยู่ กด Tab จากนั้นกด Enter เพื่อเปลี่ยนไปยังแท็บที่เปิดอยู่</translation>
-<translation id="3479539252931486093">หากเหตุการณ์นี้ผิดปกติ <ph name="BEGIN_LINK" />โปรดแจ้งให้เราทราบ<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">ไม่ใช่ตอนนี้</translation>
<translation id="3484560055331845446">คุณอาจสูญเสียสิทธิ์เข้าถึงบัญชี Google ของคุณ Chrome ขอแนะนำให้เปลี่ยนรหัสผ่านทันที ระบบจะขอให้คุณลงชื่อเข้าใช้</translation>
<translation id="3495081129428749620">ค้นหาในหน้าเว็บ <ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">เราไม่สามารถติดต่อผู้ปกครองของคุณได้ในขณะนี้ โปรดลองอีกครั้ง</translation>
<translation id="3512163584740124171">ระบบจะไม่สนใจนโยบายนี้เพราะอีกนโยบายหนึ่งจากกลุ่มนโยบายเดียวกันมีลำดับความสำคัญสูงกว่า</translation>
<translation id="3528171143076753409">ใบรับรองของเซิร์ฟเวอร์ไม่น่าเชื่อถือ</translation>
<translation id="3528485271872257980">น้ำตาลเข้ม</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{อย่างน้อย 1 รายการบนอุปกรณ์ที่ซิงค์}=1{1 รายการ (และมากกว่าบนอุปกรณ์ที่ซิงค์)}other{# รายการ (และมากกว่าบนอุปกรณ์ที่ซิงค์)}}</translation>
<translation id="3539171420378717834">เก็บสำเนาบัตรนี้ไว้บนอุปกรณ์นี้</translation>
-<translation id="3556433843310711081">ผู้จัดการสามารถเลิกบล็อกเว็บไซต์ให้คุณ</translation>
<translation id="3566021033012934673">การเชื่อมต่อของคุณไม่เป็นส่วนตัว</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">หน้าที่ฝังไว้ใน <ph name="SITE" /> บอกว่า</translation>
@@ -516,6 +521,7 @@
<translation id="3678529606614285348">เปิดหน้าเว็บในหน้าต่างที่ไม่ระบุตัวตนใหม่ (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">รายงานข้อขัดข้องเมื่อ <ph name="CRASH_TIME" /> อัปโหลดเมื่อ <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">ข้อมูลในใบรับรอง</translation>
+<translation id="3701427423622901115">รับทราบการรีเซ็ตแล้ว</translation>
<translation id="3704162925118123524">เครือข่ายที่คุณใช้อาจต้องการให้คุณไปที่หน้าการเข้าสู่ระบบ</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">กำลังโหลด ...</translation>
@@ -532,6 +538,7 @@
<translation id="3748148204939282805">ผู้โจมตีที่อยู่ใน <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> อาจหลอกล่อให้คุณทำบางสิ่งที่อันตราย เช่น การติดตั้งซอฟต์แวร์หรือเปิดเผยข้อมูลส่วนบุคคล (ตัวอย่างเช่น รหัสผ่าน หมายเลขโทรศัพท์ หรือบัตรเครดิต) <ph name="BEGIN_LEARN_MORE_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">การแปลล้มเหลวเนื่องจากข้อผิดพลาดของเซิร์ฟเวอร์</translation>
<translation id="3759461132968374835">คุณไม่ได้รายงานข้อขัดข้องเมื่อเร็วๆ นี้ ข้อขัดข้องที่เกิดขึ้นเมื่อปิดใช้งานการรายงานข้อขัดข้อง จะไม่ปรากฏที่นี่</translation>
+<translation id="3760561303380396507">ใช้ Windows Hello แทน CVC ไหม</translation>
<translation id="3761718714832595332">ซ่อนสถานะ</translation>
<translation id="3765032636089507299">หน้า Google Safe Browsing อยู่ในระหว่างการปรับปรุง</translation>
<translation id="3778403066972421603">คุณต้องการบันทึกบัตรนี้ลงในบัญชี Google และในอุปกรณ์นี้ไหม</translation>
@@ -541,6 +548,7 @@
<translation id="3789155188480882154">ขนาด 16</translation>
<translation id="3797522431967816232">Prc3 (ซองจดหมาย)</translation>
<translation id="3807873520724684969">บล็อกเนื้อหาอันตรายแล้ว</translation>
+<translation id="3808375843007691220">คำเตือน: จากนี้ไปจะเป็นฟีเจอร์ทดลอง!</translation>
<translation id="3810973564298564668">จัดการ</translation>
<translation id="382518646247711829">หากคุณใช้พร็อกซีเซิร์ฟเวอร์...</translation>
<translation id="3828924085048779000">ข้อความรหัสผ่านต้องไม่เว้นว่างไว้</translation>
@@ -549,11 +557,11 @@
<translation id="3858027520442213535">อัปเดตวันที่และเวลา</translation>
<translation id="3884278016824448484">ตัวชี้อุปกรณ์ขัดแย้งกัน</translation>
<translation id="3885155851504623709">Parish</translation>
-<translation id="3886446263141354045">ระบบส่งคำขอเข้าถึงเว็บไซต์นี้ของคุณให้ <ph name="NAME" /> แล้ว</translation>
<translation id="3890664840433101773">เพิ่มอีเมล</translation>
<translation id="3901925938762663762">บัตรหมดอายุ</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">ใช้ WebAuthn แทน CVC ไหม</translation>
<translation id="3946209740501886391">ถามทุกครั้งบนเว็บไซต์นี้</translation>
<translation id="3949571496842715403">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะใบรับรองความปลอดภัยไม่ได้ระบุชื่อสำรองของหัวเรื่อง โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้โจมตีที่ขัดขวางการเชื่อมต่อของคุณ</translation>
<translation id="3949601375789751990">ประวัติการท่องเว็บของคุณจะปรากฏที่นี่</translation>
@@ -564,11 +572,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{ไม่มี}=1{จากเว็บไซต์ 1 แห่ง }other{จากเว็บไซต์ # แห่ง }}</translation>
<translation id="397105322502079400">กำลังคำนวณ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ถูกบล็อก</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> ได้เปิดใช้ฟีเจอร์ป้องกันภัยคุกคามของ Chrome Enterprise ในเบราว์เซอร์ ฟีเจอร์ป้องกันภัยคุกคามของ Chrome Enterprise มีสิทธิ์เข้าถึงข้อมูลบางส่วนของคุณ</translation>
<translation id="3987940399970879459">ไม่ถึง 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{มีหน้าเว็บ 1 หน้าใกล้ๆ}other{มีหน้าเว็บ # หน้าใกล้ๆ}}</translation>
<translation id="4030383055268325496">&amp;เลิกทำการเพิ่ม</translation>
<translation id="4032320456957708163">เบราว์เซอร์ของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">ลิงก์ที่เปิดนำไปยังเว็บไซต์ที่คุณไม่ค่อยเข้าชม และอาจพยายามทำให้คุณสับสน</translation>
<translation id="4058922952496707368">คีย์ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (ซองจดหมาย)</translation>
<translation id="4067947977115446013">เพิ่มที่อยู่ที่ถูกต้อง</translation>
@@ -581,6 +589,7 @@
<translation id="4103249731201008433">หมายเลขซีเรียลของอุปกรณ์ไม่ถูกต้อง</translation>
<translation id="410351446219883937">เล่นอัตโนมัติ</translation>
<translation id="4103763322291513355">ไปที่ &lt;strong&gt;chrome://policy&lt;/strong&gt; เพื่อดูรายการของ URL ที่ไม่ได้รับอนุญาต และนโยบายอื่นๆ ที่ผู้ดูแลระบบของคุณบังคับใช้</translation>
+<translation id="4108231218301530806">ครั้งต่อไปใช้ลายนิ้วมือเพื่อยืนยันบัตรนี้</translation>
<translation id="4110652170750985508">ตรวจสอบการชำระเงิน</translation>
<translation id="4112140312785995938">ย้อนกลับ</translation>
<translation id="4116663294526079822">อนุญาตบนไซต์นี้เสมอ</translation>
@@ -595,6 +604,7 @@
<translation id="4171400957073367226">ลายเซ็นยืนยันไม่ถูกต้อง</translation>
<translation id="4173315687471669144">กระดาษฟุลสแก๊ป</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{อีก <ph name="ITEM_COUNT" /> รายการ}other{อีก <ph name="ITEM_COUNT" /> รายการ}}</translation>
+<translation id="4176463684765177261">ปิดการทำงาน</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">โปรดเพิ่มบัตรและที่อยู่สำหรับการเรียกเก็บเงินไว้ในบัญชี Google เพื่อให้ชำระเงินได้เร็วขึ้นในครั้งถัดไป</translation>
<translation id="4196861286325780578">&amp;ทำซ้ำการย้าย</translation>
@@ -631,6 +641,7 @@
<translation id="4277028893293644418">รีเซ็ตรหัสผ่าน</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> ของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{บันทึกบัตรนี้ลงในบัญชี Google ของคุณแล้ว}other{บันทึกบัตรเหล่านี้ลงในบัญชี Google ของคุณแล้ว}}</translation>
+<translation id="428847186335018806">สแกนไฟล์ที่คุณดาวน์โหลดหรืออัปโหลดใน Chrome</translation>
<translation id="42981349822642051">ขยาย</translation>
<translation id="4302965934281694568">Chou3 (ซองจดหมาย)</translation>
<translation id="4305817255990598646">สลับ</translation>
@@ -660,7 +671,6 @@
<translation id="4435702339979719576">โปสการ์ด)</translation>
<translation id="443673843213245140">การใช้พร็อกซีถูกปิดใช้งาน แต่มีการระบุการกำหนดค่าพร็อกซีอย่างชัดเจน</translation>
<translation id="445100540951337728">บัตรเดบิตที่ยอมรับ</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> มีพฤติกรรมที่น่าสงสัย</translation>
<translation id="4466881336512663640">การเปลี่ยนแปลงในฟอร์มจะหายไป คุณแน่ใจไหมว่าต้องการดำเนินการต่อ</translation>
<translation id="4477350412780666475">แทร็กถัดไป</translation>
<translation id="4482953324121162758">ระบบจะไม่แปลเว็บไซต์นี้</translation>
@@ -687,6 +697,7 @@
<translation id="4594403342090139922">&amp;เลิกทำการนำออก</translation>
<translation id="4597348597567598915">ขนาด 8</translation>
<translation id="4600854749408232102">C6/C5 (ซองจดหมาย)</translation>
+<translation id="464342062220857295">ฟีเจอร์การค้นหา</translation>
<translation id="4646534391647090355">พาฉันไปที่นั่นเลย</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะใบรับรองความปลอดภัยมีข้อผิดพลาด โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้บุกรุกที่ขัดขวางการเชื่อมต่อของคุณ</translation>
@@ -695,7 +706,6 @@
<translation id="4691835149146451662">Architecture-A (ซองจดหมาย)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">การเชื่อมต่อของคุณขัดข้อง</translation>
-<translation id="471880041731876836">คุณไม่มีสิทธิ์เข้าชมไซต์นี้</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />เรียกใช้การวินิจฉัยเครือข่ายของ Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">โหลดนโยบายซ้ำ</translation>
<translation id="4728558894243024398">แพลตฟอร์ม</translation>
@@ -723,7 +733,6 @@
<translation id="4816492930507672669">พอดีกับหน้า</translation>
<translation id="4850886885716139402">มุมมอง</translation>
<translation id="4854362297993841467">วิธีการนำส่งสินค้านี้ไม่พร้อมให้บริการ โปรดลองใช้วิธีการอื่น</translation>
-<translation id="4858792381671956233">คุณถามผู้ปกครองแล้วว่าสามารถเข้าชมเว็บไซต์นี้ได้ไหม</translation>
<translation id="4864052566555297930">คำแนะนำเพื่อความปลอดภัย:</translation>
<translation id="4876188919622883022">มุมมองอย่างง่าย</translation>
<translation id="4876305945144899064">ไม่มีชื่อผู้ใช้</translation>
@@ -747,7 +756,9 @@
<translation id="4974590756084640048">เปิดใช้คำเตือนอีกครั้ง</translation>
<translation id="4984339528288761049">Prc5 (ซองจดหมาย)</translation>
<translation id="4989163558385430922">ดูทั้งหมด</translation>
+<translation id="4989542687859782284">ไม่มี</translation>
<translation id="4989809363548539747">ไม่รองรับปลั๊กอินนี้</translation>
+<translation id="4995216769782533993">ยืนยันรหัสความปลอดภัยเพื่อแชร์รายละเอียดบัตรกับเว็บไซต์นี้</translation>
<translation id="5002932099480077015">หากเปิดใช้ Chrome จะเก็บสำเนาการ์ดของคุณในอุปกรณ์นี้เพื่อให้การกรอกฟอร์มทำได้เร็วขึ้น</translation>
<translation id="5015510746216210676">ชื่อเครื่อง:</translation>
<translation id="5017554619425969104">ข้อความที่คุณคัดลอก</translation>
@@ -776,6 +787,7 @@
<translation id="5115216390227830982">Edp แบบยุโรป</translation>
<translation id="5115563688576182185">(64 บิต)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">ยืนยันบัตร</translation>
<translation id="5135404736266831032">จัดการที่อยู่...</translation>
<translation id="5138227688689900538">แสดงน้อยลง</translation>
<translation id="5141240743006678641">เข้ารหัสผ่านที่ซิงค์ด้วยข้อมูลรับรอง Google ของคุณ</translation>
@@ -802,6 +814,7 @@
<translation id="5251803541071282808">ระบบคลาวด์</translation>
<translation id="5252000469029418751">C7 (ซองจดหมาย)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">ฟีเจอร์ที่ใช้กับทั้งระบบจะตั้งค่าได้โดยเจ้าของเท่านั้น: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">คำเตือน: ระบบไม่ได้รวมนโยบายนี้ตามที่ระบุในนโยบาย PolicyDictionaryMultipleSourceMergeList เพราะไม่ใช่ส่วนหนึ่งของนโยบายพจนานุกรมที่รวมได้</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">สิ้นสุด</translation>
@@ -825,7 +838,6 @@
<translation id="536296301121032821">ไม่สามารถจัดเก็บการตั้งค่านโยบาย</translation>
<translation id="5371425731340848620">อัปเดตบัตร</translation>
<translation id="5377026284221673050">"นาฬิกาของคุณช้ากว่าปัจจุบัน" หรือ "นาฬิกาของคุณเร็วกว่าปัจจุบัน" หรือ "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">หน้านี้อาจพยายามหลอกคุณ ขโมยข้อมูลส่วนบุคคล หรือทำให้อุปกรณ์เสียหาย โปรดระมัดระวังเมื่อป้อนข้อมูลส่วนบุคคลหรือเปิดไฟล์ที่ดาวน์โหลด</translation>
<translation id="5384855140246857529">ลงชื่อเข้าใช้และเปิดการซิงค์เพื่อใช้บัตรในอุปกรณ์ทุกเครื่อง</translation>
<translation id="5386426401304769735">กลุ่มใบรับรองสำหรับเว็บไซต์นี้มีใบรับรองที่ลงนามโดยใช้ SHA-1</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -839,6 +851,7 @@
<translation id="5457113250005438886">ไม่ถูกต้อง</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> และอีก <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> รายการ}other{<ph name="CONTACT_PREVIEW" /> และอีก <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> รายการ}}</translation>
<translation id="5470861586879999274">&amp;ทำซ้ำการแก้ไข</translation>
+<translation id="5473728911100096288">การเปิดใช้ฟีเจอร์เหล่านี้จะเป็นการใช้ฟีเจอร์ที่เลิกใช้งานแล้ว ซึ่งจะไม่มีให้ใช้อีกในเวอร์ชันต่อๆ ไป</translation>
<translation id="5478437291406423475">B6/C4 (ซองจดหมาย)</translation>
<translation id="5481076368049295676">เนื้อหานี้อาจพยายามติดตั้งซอฟต์แวร์อันตรายที่จะขโมยหรือลบข้อมูลในอุปกรณ์ของคุณ <ph name="BEGIN_LINK" />แสดงเนื้อหา<ph name="END_LINK" /></translation>
<translation id="54817484435770891">เพิ่มที่อยู่ที่ถูกต้อง</translation>
@@ -862,7 +875,6 @@
<translation id="5570825185877910964">ปกป้องบัญชี</translation>
<translation id="5571083550517324815">ไม่สามารถรับสินค้าจากที่อยู่นี้ โปรดเลือกที่อยู่อื่น</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{ใช้งานอยู่ 1 รายการ}other{ใช้งานอยู่ # รายการ}})</translation>
-<translation id="5572851009514199876">โปรดเปิดและลงชื่อเข้าใช้ Chrome เพื่อให้ Chrome ตรวจสอบได้ว่าคุณได้รับอนุญาตให้เข้าถึงไซต์นี้หรือไม่</translation>
<translation id="5580958916614886209">ตรวจสอบเดือนหมดอายุแล้วลองอีกครั้ง</translation>
<translation id="5586446728396275693">ไม่มีที่อยู่ที่บันทึกไว้</translation>
<translation id="5595485650161345191">แก้ไขที่อยู่</translation>
@@ -870,6 +882,7 @@
<translation id="560412284261940334">ไม่สนับสนุนการจัดการ</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">เว็บไซต์นี้อาจเป็นเว็บไซต์ปลอมหรือฉ้อโกง Chrome แนะนำให้คุณออกจากเว็บไซต์เดี๋ยวนี้</translation>
<translation id="5610142619324316209">ตรวจสอบการเชื่อมต่อ</translation>
<translation id="5610807607761827392">คุณสามารถจัดการบัตรและที่อยู่ใน<ph name="BEGIN_LINK" />การตั้งค่า<ph name="END_LINK" /></translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> เปลี่ยนเส้นทางของคุณบ่อยเกินไป</translation>
@@ -893,11 +906,11 @@
<translation id="5720705177508910913">ผู้ใช้ปัจจุบัน</translation>
<translation id="5728056243719941842">C5 (ซองจดหมาย)</translation>
<translation id="5730040223043577876">Chrome ขอแนะนำให้รีเซ็ตรหัสผ่านหากคุณใช้รหัสผ่านนี้ซ้ำในเว็บไซต์อื่น</translation>
-<translation id="5732392974455271431">ผู้ปกครองสามารถเลิกบล็อกเว็บไซต์ให้คุณ</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{บันทึกบัตรลงในบัญชี Google ของคุณ}other{บันทึกบัตรลงในบัญชี Google ของคุณ}}</translation>
<translation id="5763042198335101085">ป้อนที่อยู่อีเมลที่ถูกต้อง</translation>
<translation id="5765072501007116331">หากต้องการดูวิธีการนำส่งสินค้าและข้อกำหนด โปรดเลือกที่อยู่</translation>
<translation id="5778550464785688721">การควบคุมอุปกรณ์ MIDI เต็มรูปแบบ</translation>
+<translation id="5781136890105823427">เปิดใช้การทดสอบอยู่</translation>
<translation id="578305955206182703">เหลืองอำพัน</translation>
<translation id="57838592816432529">ปิดเสียง</translation>
<translation id="5784606427469807560">เกิดปัญหาในการยืนยันบัตรของคุณ โปรดตรวจสอบการเชื่อมต่ออินเทอร์เน็ตและลองอีกครั้ง</translation>
@@ -914,13 +927,16 @@
<translation id="5860033963881614850">ปิด</translation>
<translation id="5863847714970149516">ระบบอาจพยายามเรียกเก็บเงินจากคุณในหน้าถัดไป</translation>
<translation id="5866257070973731571">เพิ่มหมายเลขโทรศัพท์</translation>
+<translation id="5866898949289125849">คุณกำลังดูหน้าเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์</translation>
<translation id="5869405914158311789">ไม่สามารถเข้าถึงเว็บไซต์นี้</translation>
<translation id="5869522115854928033">รหัสผ่านที่บันทึกไว้</translation>
<translation id="5887400589839399685">บันทึกการ์ดแล้ว</translation>
<translation id="5893752035575986141">รับบัตรเครดิต</translation>
+<translation id="5895138241574237353">ปิดแล้วเปิดอีกครั้ง</translation>
<translation id="5901630391730855834">สีเหลือง</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ซิงค์แล้ว)</translation>
<translation id="5916664084637901428">เปิด</translation>
+<translation id="59174027418879706">เปิดใช้งาน</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">บันทึกบัตรลงในบัญชี Google ไหม</translation>
<translation id="5922853866070715753">เกือบเสร็จแล้ว</translation>
@@ -954,6 +970,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">ต้องการใช้บัตรในอุปกรณ์ทุกเครื่องไหม</translation>
<translation id="6059925163896151826">อุปกรณ์ USB</translation>
+<translation id="6060009363608157444">โหมด DnsOverHttps ไม่ถูกต้อง</translation>
<translation id="6080696365213338172">คุณเข้าถึงเนื้อหาโดยใช้ใบรับรองที่ผู้ดูแลระบบออกให้ ข้อมูลที่คุณให้กับ <ph name="DOMAIN" /> อาจถูกสกัดกั้นโดยผู้ดูแลระบบ</translation>
<translation id="6094273045989040137">ใส่หมายเหตุ</translation>
<translation id="610911394827799129">บัญชี Google อาจมีประวัติการท่องเว็บรูปแบบอื่นๆ ที่ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1002,13 +1019,12 @@
<translation id="6404511346730675251">แก้ไขบุ๊กมาร์ก</translation>
<translation id="6406765186087300643">C0 (ซองจดหมาย)</translation>
<translation id="6410264514553301377">ป้อนวันหมดอายุและ CVC ของ <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">คุณถามผู้ปกครองแล้วว่าสามารถเข้าชมเว็บไซต์นี้ได้ไหม</translation>
<translation id="6415778972515849510">Chromium ช่วยคุณปกป้องบัญชี Google และเปลี่ยนรหัสผ่านได้</translation>
-<translation id="6417515091412812850">ไม่สามารถตรวจสอบว่าใบรับรองถูกเพิกถอนหรือไม่</translation>
<translation id="6431585503458005759">ไม่ต้องเก็บ</translation>
<translation id="6433490469411711332">แก้ไขข้อมูลติดต่อ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ปฏิเสธการเชื่อมต่อ</translation>
<translation id="6434309073475700221">ทิ้ง</translation>
+<translation id="6435221585574090192">แชร์ข้อมูลให้ผู้ดูแลระบบทราบเกี่ยวกับการดำเนินการด้านความปลอดภัยที่ฟีเจอร์ป้องกันภัยคุกคามของ Chrome Enterprise แจ้งว่าไม่เหมาะสม ข้อมูลดังกล่าวอาจรวมถึง URL หน้าเว็บ ชื่อไฟล์และข้อมูลเมตาของไฟล์ ชื่อผู้ใช้ในอุปกรณ์ และชื่อผู้ใช้ใน Chrome</translation>
<translation id="6440503408713884761">ละเว้น</translation>
<translation id="6446163441502663861">Kahu (ซองจดหมาย)</translation>
<translation id="6446608382365791566">เพิ่มข้อมูลเพิ่มเติม</translation>
@@ -1017,20 +1033,19 @@
<translation id="6465306955648956876">จัดการรหัสผ่าน...</translation>
<translation id="647261751007945333">นโยบายอุปกรณ์</translation>
<translation id="6476284679642588870">จัดการวิธีการชำระเงิน</translation>
-<translation id="6477321094435799029">Chrome ได้ตรวจพบรหัสที่ผิดปกติบนหน้านี้และได้บล็อกรหัสดังกล่าวเพื่อปกป้องข้อมูลส่วนบุคคลของคุณ (เช่น รหัสผ่าน หมายเลขโทรศัพท์ และบัตรเครดิต)</translation>
<translation id="6489534406876378309">เริ่มอัปโหลดข้อขัดข้อง</translation>
<translation id="6499038740797743453">รีเซ็ตรหัสผ่านไหม</translation>
<translation id="6507833130742554667">รับบัตรเครดิตและบัตรเดบิต</translation>
<translation id="650855688985305916">เก็บไว้</translation>
<translation id="6508722015517270189">รีสตาร์ท Chrome</translation>
<translation id="6517596291481585650">คำเตือน: ระบบไม่ได้รวมนโยบายนี้เป็นรายการตามที่นโยบายระบุเพราะไม่ใช่รายการ</translation>
+<translation id="6518133107902771759">ยืนยัน</translation>
<translation id="6521745193039995384">ไม่ได้ใช้งานอยู่</translation>
<translation id="6529602333819889595">&amp;ทำซ้ำการนำออก</translation>
<translation id="6534179046333460208">คำแนะนำ Physical Web</translation>
<translation id="6545864417968258051">การสแกนหาบลูทูธ</translation>
<translation id="6554795675067793129">บัญชีของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="6556866813142980365">ทำซ้ำ</translation>
-<translation id="6563469144985748109">ผู้จัดการยังไม่ได้อนุมัติเว็บไซต์นี้</translation>
<translation id="6569060085658103619">คุณกำลังดูหน้าส่วนขยาย</translation>
<translation id="6578796323535178455">C2 (ซองจดหมาย)</translation>
<translation id="6579990219486187401">ชมพูอ่อน</translation>
@@ -1048,11 +1063,13 @@
<translation id="6643016212128521049">ล้าง</translation>
<translation id="6644283850729428850">นโยบายนี้ถูกยกเลิกแล้ว</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{ไม่มี}=1{จาก 1 เว็บไซต์ (คุณจะไม่ออกจากระบบบัญชี Google)}other{จาก # เว็บไซต์ (คุณจะไม่ออกจากระบบบัญชี Google)}}</translation>
+<translation id="6652101503459149953">ใช้ Windows Hello</translation>
<translation id="6657585470893396449">รหัสผ่าน</translation>
<translation id="6670613747977017428">กลับสู่ความปลอดภัย</translation>
<translation id="6671697161687535275">ต้องการนำคำแนะนำสำหรับแบบฟอร์มออกจาก Chromium ใช่ไหม</translation>
<translation id="6685834062052613830">ออกจากระบบและตั้งค่าให้เสร็จสมบูรณ์</translation>
<translation id="6689271823431384964">Chrome เสนอที่จะบันทึกบัตรลงในบัญชี Google ของคุณเพราะคุณลงชื่อเข้าใช้อยู่ คุณปรับเปลี่ยนลักษณะการทำงานนี้ได้ในการตั้งค่า ชื่อผู้ถือบัตรมาจากบัญชีของคุณ</translation>
+<translation id="6707256370811247129">สแกนเนื้อหาของแคชและไฟล์ที่คุณดาวน์โหลดหรืออัปโหลดใน Chrome</translation>
<translation id="6710213216561001401">ก่อนหน้า</translation>
<translation id="6710594484020273272">&lt;พิมพ์ข้อความค้นหา&gt;</translation>
<translation id="671076103358959139">โทเค็นการลงทะเบียน:</translation>
@@ -1060,10 +1077,10 @@
<translation id="6738516213925468394">ข้อมูลของคุณเข้ารหัสลับไว้ด้วย<ph name="BEGIN_LINK" />รหัสผ่านการซิงค์<ph name="END_LINK" />เมื่อ <ph name="TIME" /> ป้อนรหัสผ่านเพื่อเริ่มซิงค์</translation>
<translation id="674375294223700098">ข้อผิดพลาดใบรับรองของเซิร์ฟเวอร์ที่ไม่รู้จัก</translation>
<translation id="6744009308914054259">ระหว่างที่รอการเชื่อมต่อ คุณไปที่หน้า "ดาวน์โหลด" เพื่ออ่านบทความออฟไลน์ได้</translation>
+<translation id="6747611005629681221">คำเตือน: พบฟีเจอร์ที่เลิกใช้งาน</translation>
<translation id="6753269504797312559">ค่านโยบาย</translation>
<translation id="6757797048963528358">อุปกรณ์ของคุณเข้าสู่โหมดสลีปแล้ว</translation>
<translation id="6768213884286397650">Hagaki (โปสการ์ด)</translation>
-<translation id="6778737459546443941">ผู้ปกครองยังไม่ได้อนุมัติเว็บไซต์นี้</translation>
<translation id="67862343314499040">ม่วงอมน้ำเงิน</translation>
<translation id="6786747875388722282">ส่วนขยาย</translation>
<translation id="6790428901817661496">เล่น</translation>
@@ -1071,6 +1088,7 @@
<translation id="681021252041861472">ช่องที่ต้องกรอก</translation>
<translation id="6810899417690483278">รหัสการปรับแต่ง</translation>
<translation id="6825578344716086703">คุณพยายามเข้าถึง <ph name="DOMAIN" /> แต่เซิร์ฟเวอร์แสดงใบรับรองที่ลงนามด้วยอัลกอริทึมลายเซ็นที่ไม่รัดกุม (เช่น SHA-1) ซึ่งหมายความว่าข้อมูลรับรองด้านความปลอดภัยที่เซิร์ฟเวอร์แสดงอาจถูกปลอมแปลงขึ้น และเซิร์ฟเวอร์ดังกล่าวอาจไม่ใช่เซิร์ฟเวอร์ที่คุณคิด (คุณอาจกำลังติดต่อกับผู้โจมตี)</translation>
+<translation id="6826370046007623921">ป้องกันข้อมูลรั่วไหล</translation>
<translation id="6831043979455480757">แปลภาษา</translation>
<translation id="6839929833149231406">พื้นที่</translation>
<translation id="6852204201400771460">โหลดแอปซ้ำไหม</translation>
@@ -1083,7 +1101,6 @@
<translation id="6891596781022320156">ระดับนโยบายไม่ได้รับการสนับสนุน</translation>
<translation id="6895330447102777224">บัตรของคุณได้รับการยืนยันแล้ว</translation>
<translation id="6897140037006041989">User agent</translation>
-<translation id="6903319715792422884">ช่วยปรับปรุง Safe Browsing โดยส่ง<ph name="BEGIN_WHITEPAPER_LINK" />ข้อมูลบางอย่างของระบบและเนื้อหาของหน้า<ph name="END_WHITEPAPER_LINK" />ให้ Google <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ผู้ใช้:</translation>
<translation id="6934672428414710184">ชื่อนี้มาจากบัญชี Google ของคุณ</translation>
<translation id="6944692733090228304">คุณป้อนรหัสผ่านในเว็บไซต์ที่ <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ไม่ได้จัดการ เพื่อปกป้องบัญชี โปรดอย่าใช้รหัสผ่านซ้ำในแอปและเว็บไซต์อื่นๆ</translation>
@@ -1128,6 +1145,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> และอีก <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> รายการ}other{<ph name="PAYMENT_METHOD_PREVIEW" /> และอีก <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> รายการ}}</translation>
<translation id="7153618581592392745">ลาเวนเดอร์</translation>
<translation id="717330890047184534">รหัส GAIA:</translation>
+<translation id="7174545416324379297">รวมแล้ว</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> และอีก <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> วิธี}other{<ph name="SHIPPING_OPTION_PREVIEW" /> และอีก <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> วิธี}}</translation>
<translation id="7177397715882417099">เซิร์ฟเวอร์ที่คุณกำลังจะเข้าถึง <ph name="ORIGIN" /> ขอให้บังคับใช้
นโยบายความปลอดภัยกับคำขอทั้งหมดที่จะส่งถึงเซิร์ฟเวอร์ แต่แทนที่จะแสดงนโยบาย
@@ -1165,6 +1183,7 @@
<translation id="7320336641823683070">ความช่วยเหลือเกี่ยวกับการเชื่อมต่อ</translation>
<translation id="733354035281974745">ลบล้างบัญชีภายในอุปกรณ์</translation>
<translation id="7334320624316649418">&amp;ทำซ้ำการจัดลำดับใหม่</translation>
+<translation id="7337706099755338005">ยังไม่พร้อมให้ใช้งานในแพลตฟอร์มของคุณ</translation>
<translation id="733923710415886693">ไม่มีการเปิดเผยใบรับรองของเซิร์ฟเวอร์ผ่านความโปร่งใสของใบรับรอง</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">เป็นพาร์ทเนอร์:</translation>
@@ -1196,7 +1215,6 @@
<translation id="7440140511386898319">สำรวจขณะที่ออฟไลน์</translation>
<translation id="7441627299479586546">หัวเรื่องนโยบายไม่ถูกต้อง</translation>
<translation id="7442725080345379071">ส้มอ่อน</translation>
-<translation id="7444046173054089907">เว็บไซต์นี้ถูกบล็อก</translation>
<translation id="7445762425076701745">ไม่สามารถตรวจสอบความถูกต้องของข้อมูลประจำตัวของเซิร์ฟเวอร์ที่คุณเชื่อมต่ออยู่ได้ทั้งหมด คุณกำลังเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้ชื่อที่ใช้ได้เฉพาะในเครือข่ายของคุณ ซึ่งผู้ออกใบรับรองภายนอกไม่สามารถตรวจสอบการเป็นเจ้าของได้ เนื่องจากผู้ออกใบรับรองบางรายจะยังคงออกใบรับรองให้กับชื่อเหล่านี้อยู่ คุณจึงไม่มีทางมั่นใจได้ว่ากำลังเชื่อมต่อกับเว็บไซต์ที่คุณต้องการดูโดยไม่ใช่ผู้โจมตี</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK" />เกี่ยวกับปัญหานี้</translation>
<translation id="7455133967321480974">ใช้ค่าเริ่มต้นสากล (บล็อก)</translation>
@@ -1218,9 +1236,9 @@
<translation id="7538364083937897561">A2 (ซองจดหมาย)</translation>
<translation id="7542403920425041731">เมื่อคุณยืนยันแล้ว จะมีการแชร์รายละเอียดบัตรของคุณกับไซต์นี้</translation>
<translation id="7542995811387359312">การป้อนหมายเลขบัตรเครดิตอัตโนมัติถูกปิดใช้งานเนื่องจากฟอร์มนี้ไม่ได้ใช้การเชื่อมต่อที่ปลอดภัย</translation>
-<translation id="7543525346216957623">ถามผู้ปกครอง</translation>
<translation id="7548892272833184391">แก้ไขข้อผิดพลาดในการเชื่อมต่อ</translation>
<translation id="7549584377607005141">หน้าเว็บนี้ต้องใช้ข้อมูลที่คุณป้อนก่อนหน้านี้เพื่อให้แสดงได้อย่างถูกต้อง คุณสามารถส่งข้อมูลนี้ได้อีกครั้ง แต่การทำเช่นนั้นจะเป็นการทำสิ่งที่หน้าเว็บนี้เคยดำเนินการซ้ำอีกครั้ง</translation>
+<translation id="7550637293666041147">ชื่อผู้ใช้ของคุณในอุปกรณ์และใน Chrome</translation>
<translation id="7552846755917812628">ลองทำตามเคล็ดลับต่อไปนี้:</translation>
<translation id="7554791636758816595">แท็บใหม่</translation>
<translation id="7564049878696755256">คุณอาจเข้าถึงบัญชี <ph name="ORG_NAME" /> ไม่ได้หรือถูกโจรกรรมข้อมูลประจำตัว Chrome ขอแนะนำให้เปลี่ยนรหัสผ่านตอนนี้เลย</translation>
@@ -1235,6 +1253,7 @@
<translation id="7610193165460212391">ค่าอยู่นอกช่วง <ph name="VALUE" /></translation>
<translation id="7613889955535752492">หมดอายุ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">คุณมีข้อมูลที่ถูกเข้ารหัสโดยใช้รหัสผ่านบัญชี Google รูปแบบอื่นอยู่แล้ว โปรดป้อนรหัสผ่านด้านล่าง</translation>
+<translation id="7625784245512586808">การป้องกันภัยคุกคามของ Chrome Enterprise</translation>
<translation id="7633909222644580952">ข้อมูลประสิทธิภาพและรายงานข้อขัดข้อง</translation>
<translation id="7637571805876720304">ต้องการนำบัตรเครดิตออกจาก Chromium ใช่ไหม</translation>
<translation id="7638605456503525968">พอร์ตอนุกรม</translation>
@@ -1247,7 +1266,6 @@
<translation id="7668654391829183341">อุปกรณ์ที่ไม่รู้จัก</translation>
<translation id="7669271284792375604">ผู้โจมตีเว็บไซต์นี้อาจพยายามหลอกล่อให้คุณติดตั้งโปรแกรมที่เป็นอันตรายต่อประสบการณ์การท่องเว็บของคุณ (ตัวอย่างเช่น โดยการเปลี่ยนแปลงหน้าแรกหรือแสดงโฆษณาเพิ่มเติมในเว็บไซต์ที่คุณเข้าชม)</translation>
<translation id="7676643023259824263">ค้นหาข้อความในคลิปบอร์ด <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">แพลตฟอร์มและระบบคลาวด์</translation>
<translation id="7681101578153515023">เปลี่ยนเครื่องมือค้นหา</translation>
<translation id="7682287625158474539">จัดส่ง</translation>
<translation id="7687186412095877299">กรอกฟอร์มการชำระเงินด้วยวิธีการชำระเงินที่คุณบันทึกไว้</translation>
@@ -1262,7 +1280,6 @@
<translation id="7723047071702270851">แก้ไขบัตร</translation>
<translation id="774634243536837715">บล็อกเนื้อหาอันตรายแล้ว</translation>
<translation id="7752995774971033316">ไม่ได้จัดการ</translation>
-<translation id="7755287808199759310">ผู้ปกครองสามารถเลิกบล็อกเว็บไซต์ให้คุณ</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">ไฟร์วอลล์หรือซอฟต์แวร์ป้องกันไวรัสอาจบล็อกการเชื่อมต่อนี้</translation>
<translation id="7759163816903619567">โดเมนที่แสดง:</translation>
@@ -1306,7 +1323,6 @@
<translation id="8004582292198964060">เบราว์เซอร์</translation>
<translation id="8009225694047762179">จัดการรหัสผ่าน</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ระบบจะบันทึกบัตรนี้และที่อยู่สำหรับการเรียกเก็บเงินของบัตร คุณจะใช้บัตรนี้ได้เมื่อลงชื่อเข้าใช้ <ph name="USER_EMAIL" />}other{ระบบจะบันทึกบัตรเหล่านี้และที่อยู่สำหรับการเรียกเก็บเงินของบัตร คุณจะใช้บัตรเหล่านี้ได้เมื่อลงชื่อเข้าใช้ <ph name="USER_EMAIL" />}}</translation>
-<translation id="8012647001091218357">เราไม่สามารถติดต่อผู้ปกครองของคุณได้ในขณะนี้ โปรดลองอีกครั้ง</translation>
<translation id="8025119109950072390">ผู้โจมตีในเว็บไซต์นี้อาจหลอกล่อให้คุณทำบางสิ่งที่อันตราย เช่น การติดตั้งซอฟต์แวร์หรือเปิดเผยข้อมูลส่วนบุคคล (ตัวอย่างเช่น รหัสผ่าน หมายเลขโทรศัพท์ หรือบัตรเครดิต)</translation>
<translation id="8034522405403831421">หน้าเว็บนี้อยู่ในภาษา<ph name="SOURCE_LANGUAGE" /> ต้องการแปลเป็นภาษา<ph name="TARGET_LANGUAGE" />ไหม</translation>
<translation id="8035152190676905274">ปากกา</translation>
@@ -1317,6 +1333,7 @@
<translation id="8041940743680923270">ใช้ค่าเริ่มต้นสากล (ถาม)</translation>
<translation id="8042918947222776840">เลือกวิธีรับสินค้า</translation>
<translation id="8057711352706143257">กำหนดค่า "<ph name="SOFTWARE_NAME" />" ไม่ถูกต้อง การถอนการติดตั้ง "<ph name="SOFTWARE_NAME" />" มักแก้ไขปัญหานี้ได้ <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">คุณจะไม่ต้องป้อนรหัสความปลอดภัยของบัตรอีกต่อไป</translation>
<translation id="8066955247577885446">ขออภัย มีบางอย่างผิดพลาด</translation>
<translation id="8074253406171541171">10x13 (ซองจดหมาย)</translation>
<translation id="8078141288243656252">เมื่อหมุนแล้วจะใส่หมายเหตุไม่ได้</translation>
@@ -1347,6 +1364,7 @@
<translation id="8211406090763984747">การเชื่อมต่อปลอดภัย</translation>
<translation id="8218327578424803826">ตำแหน่งที่มอบหมาย:</translation>
<translation id="8220146938470311105">C7/C6 (ซองจดหมาย)</translation>
+<translation id="8220639454292072926">การรายงานระดับองค์กร</translation>
<translation id="8225771182978767009">ผู้ที่ตั้งค่าคอมพิวเตอร์เครื่องนี้เลือกบล็อกเว็บไซต์นี้</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">เปิดหน้าเว็บในแท็บไม่ระบุตัวตนใหม่</translation>
@@ -1401,24 +1419,24 @@
<translation id="8508648098325802031">ไอคอนค้นหา</translation>
<translation id="8522552481199248698">Chrome ช่วยคุณปกป้องบัญชี Google และเปลี่ยนรหัสผ่านได้</translation>
<translation id="8543181531796978784">คุณสามารถ<ph name="BEGIN_ERROR_LINK" />รายงานปัญหาในการตรวจหา<ph name="END_ERROR_LINK" />ได้ หรือหากคุณเข้าใจถึงความเสี่ยงต่อความปลอดภัยของคุณ คุณสามารถ<ph name="BEGIN_LINK" />เข้าชมเว็บไซต์ที่ไม่ปลอดภัย<ph name="END_LINK" />ได้</translation>
-<translation id="8543556556237226809">โปรดติดต่อผู้ที่ดูแลโปรไฟล์ของคุณหากมีคำถาม</translation>
<translation id="8553075262323480129">การแปลล้มเหลวเนื่องจากไม่สามารถระบุภาษาของหน้าเว็บนี้ได้</translation>
<translation id="8557066899867184262">CVC จะอยู่ที่ด้านหลังบัตร</translation>
<translation id="8559762987265718583">ไม่สามารถเริ่มการเชื่อมต่อส่วนตัวกับ <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> ได้เนื่องจากวันที่และเวลาของอุปกรณ์ (<ph name="DATE_AND_TIME" />) ไม่ถูกต้อง</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> เว็บไซต์ที่น่าสงสัย</translation>
<translation id="8564985650692024650">Chromium ขอแนะนำให้รีเซ็ตรหัสผ่าน <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> หากคุณใช้รหัสผ่านนี้ซ้ำในเว็บไซต์อื่น</translation>
<translation id="8571890674111243710">กำลังแปลหน้าเว็บนี้เป็นภาษา<ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">เพิ่มเบอร์โทร
</translation>
-<translation id="859285277496340001">ใบรับรองไม่ระบุวิธีการตรวจสอบว่ามีการเพิกถอนไปแล้วหรือไม่</translation>
<translation id="860043288473659153">ชื่อผู้ถือบัตร</translation>
<translation id="861775596732816396">ขนาด 4</translation>
-<translation id="8620436878122366504">ผู้ปกครองยังไม่ได้อนุมัติเว็บไซต์นี้</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">บันทึกบัตรนี้ลงในอุปกรณ์นี้</translation>
<translation id="8626112503828625890">เก็บรายละเอียดการเรียกเก็บเงินไว้ในบัญชี Google ไหม</translation>
+<translation id="8647750283161643317">รีเซ็ตทั้งหมดเป็นค่าเริ่มต้น</translation>
<translation id="8663226718884576429">สรุปคำสั่งซื้อ <ph name="TOTAL_LABEL" /> รายละเอียดเพิ่มเติม</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, คำตอบ, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">มีอยู่</translation>
<translation id="8703575177326907206">การเชื่อมต่อของคุณไปยัง <ph name="DOMAIN" /> ไม่ได้รับการเข้ารหัส</translation>
<translation id="8718314106902482036">การชำระเงินไม่เสร็จสมบูรณ์</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, คำแนะนำการค้นหา</translation>
@@ -1429,6 +1447,7 @@
<translation id="8738058698779197622">หากต้องเริ่มการเชื่อมต่อที่ปลอดภัย นาฬิกาจะต้องตั้งค่าไว้อย่างถูกต้อง เนื่องจากใบรับรองที่เว็บไซต์ใช้เพื่อระบุตนเองจะใช้ได้เฉพาะช่วงเวลาหนึ่งเท่านั้น นาฬิกาของอุปกรณ์ไม่ถูกต้อง Chromium จึงไม่สามารถยืนยันใบรับรองเหล่านี้ได้</translation>
<translation id="8740359287975076522">ไม่พบ&lt;abbr id="dnsDefinition"&gt;ที่อยู่ DNS&lt;/abbr&gt; ของ <ph name="HOST_NAME" /> กำลังวินิจฉัยปัญหา</translation>
<translation id="874846938927089722">บัตรเครดิตและบัตรเติมเงินที่ยอมรับ</translation>
+<translation id="874918643257405732">บุ๊กมาร์กแท็บนี้</translation>
<translation id="8759274551635299824">บัตรนี้หมดอายุแล้ว</translation>
<translation id="8761567432415473239">Google Safe Browsing <ph name="BEGIN_LINK" />พบโปรแกรมที่เป็นอันตราย<ph name="END_LINK" />บน <ph name="SITE" /> เมื่อเร็วๆ นี้</translation>
<translation id="8763927697961133303">อุปกรณ์ USB</translation>
@@ -1458,6 +1477,7 @@
<translation id="8938939909778640821">บัตรเครดิตและบัตรเติมเงินที่ยอมรับ</translation>
<translation id="8943282376843390568">เหลืองมะนาว</translation>
<translation id="8957210676456822347">การให้สิทธิ์แคปทีฟพอร์ทัล</translation>
+<translation id="8962950042226115166">เว็บไซต์ที่น่าสงสัย</translation>
<translation id="8968766641738584599">บันทึกบัตร</translation>
<translation id="8971063699422889582">ใบรับรองของเซิร์ฟเวอร์หมดอายุแล้ว</translation>
<translation id="8975012916872825179">รวมข้อมูล เช่น หมายเลขโทรศัพท์ อีเมล และที่อยู่สำหรับจัดส่ง</translation>
@@ -1480,24 +1500,24 @@
<translation id="9035022520814077154">ข้อผิดพลาดของการรักษาความปลอดภัย</translation>
<translation id="9038649477754266430">ใช้บริการการคาดคะเนเพื่อโหลดหน้าได้เร็วขึ้น</translation>
<translation id="9039213469156557790">นอกจากนี้ หน้านี้ประกอบด้วยทรัพยากรอื่นๆ ซึ่งไม่ปลอดภัย ผู้อื่นสามารถดูทรัพยากรเหล่านี้ขณะถ่ายโอน และผู้บุกรุกสามารถแก้ไขเพื่อเปลี่ยนการทำงานของหน้าได้</translation>
+<translation id="9044359186343685026">ใช้ Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">คุณพยายามเข้าถึง <ph name="DOMAIN" /> แต่เซิร์ฟเวอร์แสดงใบรับรองที่ไม่ถูกต้อง</translation>
<translation id="9050666287014529139">ข้อความรหัสผ่าน</translation>
<translation id="9065203028668620118">แก้ไข</translation>
<translation id="9065745800631924235">การค้นหา <ph name="TEXT" /> จากประวัติ</translation>
<translation id="9069693763241529744">ถูกบล็อกโดยส่วนขยาย</translation>
-<translation id="9076283476770535406">เว็บไซต์นี้อาจมีเนื้อหาสำหรับผู้ใหญ่</translation>
<translation id="9076630408993835509">เบราว์เซอร์นี้ไม่ได้จัดการโดยบริษัทหรือองค์กรอื่นๆ กิจกรรมในอุปกรณ์นี้อาจมีการจัดการภายนอก Chrome <ph name="BEGIN_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">ต้องระบุข้อมูลเพิ่มเติม</translation>
<translation id="9080712759204168376">สรุปการสั่งซื้อ</translation>
<translation id="9089260154716455634">นโยบายสำหรับช่วงที่ไม่ค่อยมีการใช้งาน:</translation>
<translation id="9095388113577226029">ภาษาเพิ่มเติม...</translation>
+<translation id="9098981495403789647">ผู้ดูแลระบบได้เปิดใช้ฟีเจอร์ป้องกันภัยคุกคามของ Chrome Enterprise ในเบราว์เซอร์ ฟีเจอร์ป้องกันภัยคุกคามของ Chrome Enterprise มีสิทธิ์เข้าถึงข้อมูลบางส่วนของคุณ</translation>
<translation id="9103872766612412690">โดยทั่วไป <ph name="SITE" /> จะใช้การเข้ารหัสเพื่อปกป้องข้อมูลของคุณ เมื่อ Chromium พยายามเชื่อมต่อกับ <ph name="SITE" /> ในครั้งนี้ เว็บไซต์ดังกล่าวส่งข้อมูลรับรองที่ผิดปกติและไม่ถูกต้องกลับมา เหตุการณ์นี้อาจเกิดขึ้นเมื่อผู้บุกรุกพยายามปลอมเป็น <ph name="SITE" /> หรือหน้าจอการลงชื่อเข้าใช้ Wi-Fi รบกวนการเชื่อมต่อ ข้อมูลของคุณยังปลอดภัยอยู่เนื่องจาก Chromium หยุดการเชื่อมต่อก่อนมีการแลกเปลี่ยนข้อมูล</translation>
<translation id="9106062320799175032">เพิ่มที่อยู่สำหรับการเรียกเก็บเงิน</translation>
<translation id="9114524666733003316">กำลังยืนยันบัตร…</translation>
<translation id="9128870381267983090">เชื่อมต่อกับเครือข่าย</translation>
<translation id="9137013805542155359">แสดงหน้าเว็บเดิม</translation>
-<translation id="9137248913990643158">โปรดเปิดและลงชื่อเข้าใช้ Chrome ก่อนใช้แอปนี้</translation>
<translation id="9141013498910525015">จัดการที่อยู่</translation>
<translation id="9148088599418889305">เลือกวิธีการจัดส่ง</translation>
<translation id="9148507642005240123">&amp;เลิกทำการแก้ไข</translation>
diff --git a/chromium/components/strings/components_strings_tr.xtb b/chromium/components/strings/components_strings_tr.xtb
index 225a4344334..52f2f154cd2 100644
--- a/chromium/components/strings/components_strings_tr.xtb
+++ b/chromium/components/strings/components_strings_tr.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Kart Üzerindeki Adı Ekleyin</translation>
<translation id="1089439967362294234">Şifreyi Değiştir</translation>
+<translation id="1096545575934602868">Bu alanda en çok <ph name="MAX_ITEMS_LIMIT" /> giriş olabilir. Diğer tüm girişler silinecektir.</translation>
<translation id="109743633954054152">Şifreleri Chrome ayarlarından yönetin</translation>
<translation id="1103523840287552314"><ph name="LANGUAGE" /> dilini daima çevir</translation>
<translation id="1107591249535594099">İşaretlenirse Chrome, formları daha hızlı doldurma amacıyla kartınızın bir kopyasını bu cihazda depolar.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756"><ph name="URL" /> sitesinin <ph name="BEGIN_LINK" />önbelleğe alınmış bir kopyasına<ph name="END_LINK" /> erişin</translation>
<translation id="1156303062776767266">Yerel veya paylaşılan bir dosyayı görüntülüyorsunuz</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> bağlantıyı beklenmedik şekilde kapattı.</translation>
+<translation id="115926840831309955">CVC'nizi kontrol edip tekrar deneyin veya son kullanma tarihini güncelleyin</translation>
<translation id="1161325031994447685">Kablosuz ağa yeniden bağlanma</translation>
<translation id="1165039591588034296">Hata</translation>
<translation id="1175364870820465910">Ya&amp;zdır...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Bilgisayarınızdaki yazılım, Chrome'un web'e güvenli bir şekilde bağlanmasını engelliyor" (yalnızca Windows bilgisayarlar)</translation>
<translation id="1294154142200295408">Komut satırı varyasyonları</translation>
<translation id="129553762522093515">Son kapatılan</translation>
+<translation id="1298536327547837046">Kötü Amaçlı Yazılım Tarama</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Çerezlerinizi temizlemeyi deneyin<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Kullanımdan Kaldırılan Özellikler</translation>
<translation id="1320233736580025032">Prc1 (Zarf)</translation>
<translation id="132301787627749051">Panoda resmi ara</translation>
<translation id="1323433172918577554">Daha Fazla Göster</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google E-Tablolar</translation>
<translation id="1527263332363067270">Bağlantı bekleniyor…</translation>
<translation id="1529521330346880926">10x15 (Zarf)</translation>
+<translation id="1530707389502320859">Az önce girmeye çalıştığınız site sahte görünüyor. Saldırganlar bazen URL'de görülmesi zor ufak değişiklikler yaparak siteleri taklit ederler.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Bu sayfanın mesajı</translation>
<translation id="153384715582417236">Şimdilik hepsi bu</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Doküman, ek açıklama ilave edilemeyecek kadar büyük</translation>
-<translation id="1721312023322545264">Bu siteyi ziyaret etmek için <ph name="NAME" /> size izin vermelidir</translation>
<translation id="1721424275792716183">* Zorunlu alan</translation>
<translation id="1727741090716970331">Geçerli Kart Numarası Ekleyin</translation>
<translation id="1728677426644403582">Bir web sayfasının kaynak kodunu görüntülüyorsunuz</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Ziyaret ettiğiniz web siteleri ve bu sitelerde geçirdiğiniz zaman</translation>
<translation id="1826516787628120939">Kontrol ediliyor</translation>
<translation id="1834321415901700177">Bu site zararlı programlar içeriyor</translation>
+<translation id="1838374766361614909">Aramayı temizle</translation>
<translation id="1839551713262164453">Politika değerlerini doğrulama işlemi hatalarla başarısız oldu</translation>
<translation id="1842969606798536927">Ödeme</translation>
<translation id="1871208020102129563">Proxy, bir .pac komut dosyası URL'sini değil, sabit proxy sunucuları kullanacak şekilde ayarlanır.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Listeyi daralt</translation>
<translation id="1898423065542865115">Filtreleme</translation>
<translation id="1914326953223720820">Sıkıştırma Açma Hizmeti</translation>
+<translation id="1915697529809968049">CVC yerine Touch ID kullanılsın mı?</translation>
<translation id="1916770123977586577">Güncellenen ayarlarınızı bu siteye uygulamak için sayfayı yeniden yükleyin</translation>
<translation id="1919345977826869612">Reklamlar</translation>
<translation id="1919367280705858090">Belirli bir hata mesajıyla ilgili yardım alma</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> Yer İşaretleri</translation>
<translation id="1973335181906896915">Serileştirme hatası</translation>
<translation id="1974060860693918893">Gelişmiş</translation>
+<translation id="1974883374937189061">Google'a <ph name="BEGIN_WHITEPAPER_LINK" />ziyaret ettiğiniz bazı sitelerin URL'lerini, sınırlı sistem bilgisini ve bazı sayfa içeriklerini<ph name="END_WHITEPAPER_LINK" /> göndererek Chrome güvenliğini iyileştirmeye yardımcı olun. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Donanım Yazılımı Sürümü</translation>
<translation id="1981206234434200693">Chrome'un tarama geçmişi verilerini temizleyin</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{ve 1 uygulama daha}other{ve # uygulama daha}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Geçerli bir son kullanma yılı girin</translation>
<translation id="2212735316055980242">Politika bulunamadı</translation>
<translation id="2213606439339815911">Girişler getiriliyor...</translation>
+<translation id="2215727959747642672">Dosya düzenleme</translation>
<translation id="2218879909401188352">Şu anda <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> öğesini kullanan saldırganlar cihazınıza zarar verebilecek uygulamalar yükleyebilir, sizden habersiz mobil faturanıza ücretler ekleyebilir veya kişisel bilgilerinizi çalabilirler. <ph name="BEGIN_LEARN_MORE_LINK" />Daha fazla bilgi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">İnternet bağlantısı yok</translation>
<translation id="2230458221926704099"><ph name="BEGIN_LINK" />Tanılama uygulamasını<ph name="END_LINK" /> kullanarak bağlantınızı düzeltin</translation>
<translation id="2239100178324503013">Şimdi gönder</translation>
+<translation id="2248949050832152960">WebAuthn'u kullan</translation>
<translation id="225207911366869382">Bu değer bu politika için kullanımdan kaldırıldı.</translation>
<translation id="2257315177824333709">Maalesef kartınız şu anda kaydedilemiyor</translation>
<translation id="2262243747453050782">HTTP hatası</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Geçersiz arama URL'si.</translation>
<translation id="2482878487686419369">Bildirimler</translation>
<translation id="248348093745724435">Makine politikaları</translation>
-<translation id="2485387744899240041">Cihazınız ve tarayıcınız için kullanıcı adları</translation>
<translation id="2491120439723279231">Sunucu sertifikası hatalar içeriyor.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON Ayrıştırıcı</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Geri dön</translation>
<translation id="2503184589641749290">Kabul edilen banka ve ön ödemeli kartlar</translation>
<translation id="2505268675989099013">Hesabı Koru</translation>
+<translation id="2515335152965840738">YOKSAY</translation>
<translation id="2515629240566999685">Bulunduğunuz bölgedeki sinyali kontrol etme</translation>
<translation id="2523886232349826891">Yalnızca bu cihazda kaydedildi</translation>
<translation id="2524461107774643265">Daha Fazla Bilgi Ekleyin</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Gönder</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Yok}=1{1 şifre (<ph name="DOMAIN_LIST" /> için)}=2{2 şifre (<ph name="DOMAIN_LIST" /> için)}other{# şifre (<ph name="DOMAIN_LIST" /> için)}}</translation>
<translation id="2666117266261740852">Diğer sekmeleri veya uygulamaları kapatın</translation>
-<translation id="267371737713284912">işlemi geri almak için <ph name="MODIFIER_KEY_DESCRIPTION" /> tuşuna basın</translation>
<translation id="2674170444375937751">Bu sayfaları geçmişinizden silmek istediğinizden emin misiniz?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Çık</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">Değer, biçimle eşleşmiyor.</translation>
<translation id="2705137772291741111">Bu sitenin kaydedilen (önbelleğe alınan) kopyası okunamadı.</translation>
<translation id="2709516037105925701">Otomatik doldurma</translation>
-<translation id="2712173769900027643">İzin iste</translation>
<translation id="2713444072780614174">Beyaz</translation>
<translation id="2720342946869265578">Etrafımda</translation>
<translation id="2721148159707890343">İstek başarılı oldu</translation>
<translation id="2728127805433021124">Sunucunun sertifikası, zayıf bir imza algoritması kullanılarak imzalanmış.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Bağlantı Teşhislerini Çalıştırma<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Bu özellikleri etkinleştirdiğinizde tarayıcı verilerinizi kaybedebilir veya güvenliğinizden ya da gizliliğinizden ödün verebilirsiniz. Etkinleştirilen özellikler, bu tarayıcının tüm kullanıcıları için geçerli olur.</translation>
<translation id="2735043616039983645">Bu politikada, birbiriyle çelişen değerler içeren birden fazla kaynak bulunuyor.</translation>
<translation id="2738330467931008676">Alınacağı Adres Seç</translation>
<translation id="2740531572673183784">Tamam</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">Bağlantı sıfırlandı.</translation>
<translation id="2788784517760473862">Kabul edilen kredi kartları</translation>
<translation id="2792012897584536778">Bu cihazın yöneticileri, ziyaret ettiğiniz web sitelerinin içeriğini görmelerine izin verebilecek güvenlik sertifikaları ayarladı.</translation>
-<translation id="2794233252405721443">Site engellenmiş</translation>
<translation id="2799020568854403057">Girmekte olduğunuz site zararlı uygulamalar içeriyor</translation>
<translation id="2799223571221894425">Yeniden başlat</translation>
<translation id="2803306138276472711">Google Güvenli Tarama yakın bir zamanda <ph name="SITE" /> sitesinde <ph name="BEGIN_LINK" />kötü amaçlı yazılım<ph name="END_LINK" /> tespit etti. Normalde güvenli olan web sitelerine bazen kötü amaçlı yazılımlar bulaşır.</translation>
+<translation id="2815364696811431560">SİTEDEN ÇIK</translation>
<translation id="2824775600643448204">Adres ve arama çubuğu</translation>
<translation id="2826760142808435982">Bağlantı <ph name="CIPHER" /> kullanılarak şifrelenmiş ve kimliği doğrulanmıştır. Anahtar değişim mekanizması olarak <ph name="KX" /> kullanılır.</translation>
<translation id="2835170189407361413">Formu temizle</translation>
<translation id="2847118875340931228">Gizli Pencereyi Aç</translation>
<translation id="2850739647070081192">Invite (Zarf)</translation>
-<translation id="2851634818064021665">Bu siteyi ziyaret etmek için izninizin olması gerekir</translation>
<translation id="2856444702002559011">Saldırganlar <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> üzerinden bilgilerinizi çalmaya çalışıyor olabilir (örneğin, şifreler, mesajlar veya kredi kartları). <ph name="BEGIN_LEARN_MORE_LINK" />Daha fazla bilgi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Kart kaydedilsin mi?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Bu seçenek etkinleştirildiğinde Chromium, formları daha hızlı doldurmak için kartınızın bir kopyasını bu cihazda saklar.</translation>
<translation id="2985398929374701810">Geçerli bir adres girin</translation>
<translation id="2986368408720340940">Bu alım yöntemi kullanılamıyor. Farklı bir yöntem deneyin.</translation>
+<translation id="2987034854559945715">Eşleşen özellik yok</translation>
<translation id="2991174974383378012">Web Siteleriyle Paylaşma</translation>
<translation id="2991571918955627853"><ph name="SITE" /> web sitesi HSTS kullandığından şu anda siteyi ziyaret edemezsiniz. Ağ hataları ve saldırılar genellikle geçici olduğundan bu sayfa muhtemelen daha sonra çalışacaktır.</translation>
<translation id="3005723025932146533">Kaydedilen kopyayı göster</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Yanlış politika türü</translation>
<translation id="3037605927509011580">Hay aksi!</translation>
<translation id="3041612393474885105">Sertifika Bilgileri</translation>
+<translation id="3057676462092457419">DnsOverHttps modu <ph name="SECURE_DNS_MODE_SECURE" /> henüz desteklenmiyor. Mod <ph name="SECURE_DNS_MODE_OFF" /> olarak ayarlandı.</translation>
<translation id="3060227939791841287">C9 (Zarf)</translation>
<translation id="3061707000357573562">Yama Hizmeti</translation>
<translation id="3064966200440839136">Harici bir uygulama üzerinden ödeme gerçekleştirmek için gizli moddan çıkılacak. Devam edilsin mi?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> üzerinde <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">Ödemeyi iptal et</translation>
<translation id="3207960819495026254">Yer işareti koyuldu</translation>
+<translation id="3209034400446768650">Sayfa sizden ücret alabilir</translation>
<translation id="3225919329040284222">Sunucu, yerleşik beklentilerle eşleşmeyen bir sertifika sundu. Bu beklentiler sizi korumak amacıyla bazı yüksek güvenlikli web sitelerinde bulunur.</translation>
<translation id="3226128629678568754">Sayfayı yüklemek üzere gereken verileri tekrar göndermek için yeniden yükle düğmesine basın.</translation>
<translation id="3227137524299004712">Mikrofon</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">Cihazınız ve tarayıcınızla ilgili sürüm bilgileri</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> numaralı kartın CVC kodunu girin</translation>
<translation id="3234666976984236645">Her zaman bu sitedeki önemli içeriği algıla</translation>
-<translation id="3254409185687681395">Bu sayfaya yer işareti koy</translation>
<translation id="3270847123878663523">Sıralama Değişikliğini &amp;Geri Al</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Kart üzerindeki ismi ekle</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">Fatura adresi ekle</translation>
<translation id="3324983252691184275">Kızıl</translation>
<translation id="3338095232262050444">Güvenli</translation>
-<translation id="3345135638360864351">Bu siteye erişim isteğiniz <ph name="NAME" /> adlı kullanıcıya gönderilemedi. Lütfen tekrar deneyin.</translation>
<translation id="3355823806454867987">Proxy ayarlarını değiştir...</translation>
<translation id="3361596688432910856">Chrome aşağıdaki bilgileri <ph name="BEGIN_EMPHASIS" />kaydetmez<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">Gelişmiş bilgileri gizle</translation>
<translation id="3467763166455606212">Kart sahibinin adı zorunludur</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />, şu anda açık, açık Sekmeye geçmek için Sekmeye ve sonra enter tuşuna basın</translation>
-<translation id="3479539252931486093">Bu beklenmedik bir durum mu? <ph name="BEGIN_LINK" />Bize bildirin<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Şimdi değil</translation>
<translation id="3484560055331845446">Google Hesabınıza erişimi kaybedebilirsiniz. Chrome, şifrenizi hemen değiştirmenizi önerir. Oturum açmanız istenecektir.</translation>
<translation id="3495081129428749620">Şu sayfada bul:
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Şu anda ebeveyninize erişemedik. Lütfen tekrar deneyin.</translation>
<translation id="3512163584740124171">Aynı politika grubundan farklı bir politika daha yüksek önceliği sahip olduğundan bu politika yok sayılır.</translation>
<translation id="3528171143076753409">Sunucunun sertifikasına güvenilmiyor.</translation>
<translation id="3528485271872257980">Koyu Kahverengi</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Senkronize edilmiş cihazlarda en az 1 öğe}=1{1 öğe (ve senkronize edilmiş cihazlarda daha fazlası)}other{# öğe (ve senkronize edilmiş cihazlarda daha fazlası)}}</translation>
<translation id="3539171420378717834">Bu kartın bir kopyasını bu cihazda tut</translation>
-<translation id="3556433843310711081">Yöneticiniz engellemeyi kaldırabilir</translation>
<translation id="3566021033012934673">Bağlantınız gizli değil</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> web sitesindeki yerleşik bir sayfanın mesajı</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">Sayfayı yeni Gizli pencerede açın (Ctrl-Üst Karakter-N)</translation>
<translation id="3679803492151881375">Kilitlenme raporunun oluşturulma zamanı: <ph name="CRASH_TIME" />, raporun yüklenme zamanı: <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Sertifika bilgileri</translation>
+<translation id="3701427423622901115">Sıfırlama işlemi onaylandı.</translation>
<translation id="3704162925118123524">Kullandığınız ağ bir giriş sayfasını ziyaret etmenizi gerektiriyor olabilir.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Yükleniyor...</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sitesine saldıranlar sizi yanıltarak yazılım yüklemek veya kişisel bilgilerinizi (örneğin, şifreler, telefon numaraları veya kredi kartları) ifşa etmek gibi tehlikeli bir şey yapmanızı sağlayabilirler. <ph name="BEGIN_LEARN_MORE_LINK" />Daha fazla bilgi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Çeviri, bir sunucu hatası nedeniyle başarısız oldu.</translation>
<translation id="3759461132968374835">Son zamanda herhangi bir kilitlenme bildirmediniz. Kilitlenme bildirme özelliği devre dışıyken oluşan kilitlenmeler burada görünmez.</translation>
+<translation id="3760561303380396507">CVC yerine Windows Hello kullanılsın mı?</translation>
<translation id="3761718714832595332">Durumu gizle</translation>
<translation id="3765032636089507299">Güvenli Tarama sayfası yapım aşamasında.</translation>
<translation id="3778403066972421603">Bu kartı Google Hesabınıza ve bu cihaza kaydetmek istiyor musunuz?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">Boyut 16</translation>
<translation id="3797522431967816232">Prc3 (Zarf)</translation>
<translation id="3807873520724684969">Zararlı içerik engellendi.</translation>
+<translation id="3808375843007691220">Uyarı: Deneysel özellikler!</translation>
<translation id="3810973564298564668">Yönet</translation>
<translation id="382518646247711829">Proxy sunucu kullanıyorsanız...</translation>
<translation id="3828924085048779000">Boş parolaya izin verilmez.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">Tarih ve saati güncelle</translation>
<translation id="3884278016824448484">Çakışan cihaz tanımlayıcısı</translation>
<translation id="3885155851504623709">İl</translation>
-<translation id="3886446263141354045">Bu siteye erişim isteğiniz şu kişiye gönderildi: <ph name="NAME" /></translation>
<translation id="3890664840433101773">E-posta adresi ekle</translation>
<translation id="3901925938762663762">Kartın kullanım süresi doldu</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">CVC yerine WebAuthn kullanılsın mı?</translation>
<translation id="3946209740501886391">Bu sitede her zaman sor</translation>
<translation id="3949571496842715403">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikasında Konu Diğer Adları belirtilmiyor. Bu durum, bir yanlış yapılandırmadan veya bağlantınıza müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
<translation id="3949601375789751990">Göz atma geçmişiniz burada görünür</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Yok}=1{1 siteden }other{# siteden }}</translation>
<translation id="397105322502079400">Hesaplanııyor...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> engellendi</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" />, tarayıcınızda Chrome Enterprise Threat Protection özelliğini etkinleştirdi. Chrome Enterprise Threat Protection özelliğinin verilerinizin bir kısmına erişimi vardır.</translation>
<translation id="3987940399970879459">1 MB'tan az</translation>
<translation id="40103911065039147">{URL_count,plural, =1{Yakındaki 1 web sayfası}other{Yakındaki # web sayfası}}</translation>
<translation id="4030383055268325496">Eklemeyi &amp;geri al</translation>
<translation id="4032320456957708163">Tarayıcınız <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetilmektedir</translation>
-<translation id="4034375457890803692">Açtığınız bağlantı, genellikle ziyaret etmediğiniz bir siteye yönlendiriyor. Kafanızı karıştırmaya çalışıyor olabilir.</translation>
<translation id="4058922952496707368">"<ph name="SUBKEY" />" anahtarı: <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Zarf)</translation>
<translation id="4067947977115446013">Geçerli Adres Ekleyin</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">Cihazın seri numarası geçersiz</translation>
<translation id="410351446219883937">Otomatik oynatma</translation>
<translation id="4103763322291513355">Kara listeye alınmış URL'lerin ve sistem yöneticinizin zorunlu tuttuğu diğer politikaların listesini görmek için &lt;strong&gt;chrome://policy&lt;/strong&gt; adresini ziyaret edin.</translation>
+<translation id="4108231218301530806">Bu kartı doğrulamak için bir dahaki sefere parmak izi kullan.</translation>
<translation id="4110652170750985508">Ödemenizi inceleyin</translation>
<translation id="4112140312785995938">Geri Sar</translation>
<translation id="4116663294526079822">Bu sitede her zaman izin ver</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">Geçersiz doğrulama imzası</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> öğe daha}other{<ph name="ITEM_COUNT" /> öğe daha}}</translation>
+<translation id="4176463684765177261">Devre dışı</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Bir dahaki sefere daha hızlı ödeme yapmak için kartınızı ve fatura adresinizi Google Hesabınıza ekleyin.</translation>
<translation id="4196861286325780578">Taşımayı &amp;yeniden yap</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">Şifreyi sıfırla</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> cihazınız <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetiliyor.</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Bu kart Google Hesabınıza kaydedildi}other{Bu kartlar Google Hesabınıza kaydedildi}}</translation>
+<translation id="428847186335018806">Chrome'da indirdiğiniz veya yüklediğiniz dosyaları tarama.</translation>
<translation id="42981349822642051">Genişlet</translation>
<translation id="4302965934281694568">Chou3 (Zarf)</translation>
<translation id="4305817255990598646">Anahtar</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">Kartpostal)</translation>
<translation id="443673843213245140">Proxy kullanımı devre dışı, ancak açık bir proxy yapılandırması belirtildi.</translation>
<translation id="445100540951337728">Kabul edilen banka kartları</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> şüpheli davranış</translation>
<translation id="4466881336512663640">Formda yaptığınız değişiklikler kaybolacak. Devam etmek istediğinizden emin misiniz?</translation>
<translation id="4477350412780666475">Sonraki Parça</translation>
<translation id="4482953324121162758">Bu site çevrilmeyecek.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">Silmeyi &amp;Geri Al</translation>
<translation id="4597348597567598915">Boyut 8</translation>
<translation id="4600854749408232102">C6/C5 (Zarf)</translation>
+<translation id="464342062220857295">Özellik ara</translation>
<translation id="4646534391647090355">İndirilenlere git</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikasında hatalar var. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A (Zarf)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Bağlantınız kesildi</translation>
-<translation id="471880041731876836">Bu siteyi ziyaret etmek için izniniz yok</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Ağ Teşhislerini Çalıştırma<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Politikaları yeniden yükle</translation>
<translation id="4728558894243024398">Platform</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">Sayfaya sığdır</translation>
<translation id="4850886885716139402">Görüntüle</translation>
<translation id="4854362297993841467">Bu teslimat yöntemi kullanılamıyor. Farklı bir yöntem deneyin.</translation>
-<translation id="4858792381671956233">Ebeveynlerinize bu siteyi ziyaret etmenizin uygun olup olmadığını sordunuz</translation>
<translation id="4864052566555297930">Güvenlik ipucu:</translation>
<translation id="4876188919622883022">Basitleştirilmiş görünüm</translation>
<translation id="4876305945144899064">Kullanıcı adı yok</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">Uyarıları yeniden etkinleştir</translation>
<translation id="4984339528288761049">Prc5 (Zarf)</translation>
<translation id="4989163558385430922">Tümünü göster</translation>
+<translation id="4989542687859782284">Kullanılamıyor</translation>
<translation id="4989809363548539747">Bu eklenti desteklenmiyor</translation>
+<translation id="4995216769782533993">Kart ayrıntılarınızı bu siteyle paylaşmak için güvenlik kodunu doğrulayın</translation>
<translation id="5002932099480077015">Bu seçenek etkinleştirildiğinde Chrome, formları daha hızlı doldurmak için kartınızın bir kopyasını bu cihazda saklar.</translation>
<translation id="5015510746216210676">Makine Adı:</translation>
<translation id="5017554619425969104">Kopyalanan metin</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Kartınızı doğrulayın</translation>
<translation id="5135404736266831032">Adresleri yönet...</translation>
<translation id="5138227688689900538">Daha az göster</translation>
<translation id="5141240743006678641">Senkronize edilen şifreleri Google kimlik bilgileriyle şifrele</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">Bulut</translation>
<translation id="5252000469029418751">C7 (Zarf)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Tüm sistem için geçerli olan özellikler sadece sahibi <ph name="OWNER_EMAIL" /> tarafından ayarlanabilir</translation>
<translation id="5273658854610202413">Uyarı: Bu politika, birleştirilebilecek sözlük politikalarının parçası olmadığından PolicyDictionaryMultipleSourceMergeList politikasında belirtildiği gibi birleştirilmemiştir.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Son</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">Politika ayarları saklanamadı</translation>
<translation id="5371425731340848620">Kartı güncelle</translation>
<translation id="5377026284221673050">"Saatiniz geri", "Saatiniz ileri" veya "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Bu sayfa sizi kandırmaya, kişisel bilgilerinizi çalmaya veya cihazınıza zarar vermeye çalışabilir. Kişisel bilgileri girerken veya indirilen dosyaları açarken dikkatli olun.</translation>
<translation id="5384855140246857529">Kartlarınızı tüm cihazlarınızda kullanmak için oturum açın ve senkronizasyonu etkinleştirin.</translation>
<translation id="5386426401304769735">Bu sitenin sertifika zinciri, SHA-1 kullanılarak imzalanmış bir sertifika içeriyor.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,8 @@
<translation id="5457113250005438886">Geçersiz</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> ve <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> kişi daha}other{<ph name="CONTACT_PREVIEW" /> ve <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> kişi daha}}</translation>
<translation id="5470861586879999274">Düzenlemeyi &amp;yeniden yap</translation>
+<translation id="5473728911100096288">Bu özellikleri etkinleştirirseniz, kullanımdan kaldırıldığı için ilerideki sürümlerde yer almayacak
+ özellikleri kullanıyor olacaksınız.</translation>
<translation id="5478437291406423475">B6/C4 (Zarf)</translation>
<translation id="5481076368049295676">Bu içerik, cihazınıza bilgilerinizi çalabilecek veya silebilecek tehlikeli yazılımlar yüklemeye çalışabilir. <ph name="BEGIN_LINK" />Yine de göster<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Geçerli adres ekleyin</translation>
@@ -863,7 +877,6 @@
<translation id="5570825185877910964">Hesabı koru</translation>
<translation id="5571083550517324815">Bu adresten alım yapılamıyor. Farklı bir adres seçin.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 çerez kullanımda}other{# çerez kullanımda}})</translation>
-<translation id="5572851009514199876">Chrome'un bu siteye erişmenize izin verilip verilmediğini kontrol edebilmesi için lütfen Chrome'u başlatıp oturum açın.</translation>
<translation id="5580958916614886209">Son kullanma tarihinin ayını kontrol edip tekrar deneyin</translation>
<translation id="5586446728396275693">Kaydedilmiş adres yok</translation>
<translation id="5595485650161345191">Adresi düzenle</translation>
@@ -871,6 +884,7 @@
<translation id="560412284261940334">Yönetim desteklenmiyor</translation>
<translation id="5605670050355397069">Ana Defter</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Bu site taklit veya sahte olabilir. Chrome siteden çıkmanızı önerir.</translation>
<translation id="5610142619324316209">Bağlantınızı kontrol etme</translation>
<translation id="5610807607761827392">Kartları ve adresleri <ph name="BEGIN_LINK" />Ayarlar<ph name="END_LINK" />'da yönetebilirsiniz.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> sizi çok fazla kez yönlendirdi.</translation>
@@ -894,11 +908,11 @@
<translation id="5720705177508910913">Geçerli kullanıcı</translation>
<translation id="5728056243719941842">C5 (Zarf)</translation>
<translation id="5730040223043577876">Chrome, şifrenizi başka sitelerde kullandıysanız sıfırlamanızı önerir.</translation>
-<translation id="5732392974455271431">Ebeveynleriniz engellemeyi kaldırabilir</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Kartı Google Hesabınıza kaydedin}other{Kartları Google Hesabınıza kaydedin}}</translation>
<translation id="5763042198335101085">Geçerli bir e-posta adresi girin</translation>
<translation id="5765072501007116331">Teslimat yöntemlerini ve gereksinimleri görmek için bir adres seçin</translation>
<translation id="5778550464785688721">MIDI cihazları tam denetimi</translation>
+<translation id="5781136890105823427">Deneme etkin</translation>
<translation id="578305955206182703">Kehribar rengi</translation>
<translation id="57838592816432529">Sesi kapat</translation>
<translation id="5784606427469807560">Kartınız onaylanırken bir sorun oluştu. İnternet bağlantınızı kontrol edip tekrar deneyin.</translation>
@@ -915,13 +929,16 @@
<translation id="5860033963881614850">Kapalı</translation>
<translation id="5863847714970149516">Gireceğiniz sayfa sizden para almaya çalışabilir</translation>
<translation id="5866257070973731571">Telefon Numarası Ekleyin</translation>
+<translation id="5866898949289125849">Geliştirici araçları sayfasını görüntülüyorsunuz</translation>
<translation id="5869405914158311789">Bu siteye ulaşılamıyor</translation>
<translation id="5869522115854928033">Kayıtlı şifreler</translation>
<translation id="5887400589839399685">Kart kaydedildi</translation>
<translation id="5893752035575986141">Kredi kartları kabul edilir.</translation>
+<translation id="5895138241574237353">Yeniden başlat</translation>
<translation id="5901630391730855834">Sarı</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (senkronize edildi)</translation>
<translation id="5916664084637901428">Açık</translation>
+<translation id="59174027418879706">Etkin</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Kart Google Hesabı'na kaydedilsin mi?</translation>
<translation id="5922853866070715753">Tamamlanmak üzere</translation>
@@ -955,6 +972,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Kartlarınızı tüm cihazlarınızda kullanmak istiyor musunuz?</translation>
<translation id="6059925163896151826">USB cihazları</translation>
+<translation id="6060009363608157444">Geçersiz DnsOverHttps modu.</translation>
<translation id="6080696365213338172">Yönetici tarafından sağlanmış bir sertifika kullanan içeriğe eriştiniz. <ph name="DOMAIN" /> alan adına sağladığınız verileri yöneticiniz görebilir ve bunlara müdahale edebilir.</translation>
<translation id="6094273045989040137">Ek açıklama ekle</translation>
<translation id="610911394827799129">Google Hesabınızın <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> adresinde başka biçimlerde tarama geçmişi olabilir</translation>
@@ -1003,13 +1021,12 @@
<translation id="6404511346730675251">Yer işaretini düzenle</translation>
<translation id="6406765186087300643">C0 (Zarf)</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> numaralı kartın son kullanma tarihini ve CVC kodunu girin</translation>
-<translation id="6414888972213066896">Ebeveyninize bu siteyi ziyaret etmenizin uygun olup olmadığını sordunuz</translation>
<translation id="6415778972515849510">Chromium, Google Hesabınızı korumanıza ve şifrenizi değiştirmenize yardımcı olabilir.</translation>
-<translation id="6417515091412812850">Sertifikanın iptal edilip edilmediği kontrol edilemiyor.</translation>
<translation id="6431585503458005759">Saklama</translation>
<translation id="6433490469411711332">İletişim bilgilerini düzenle</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> bağlanmayı reddetti.</translation>
<translation id="6434309073475700221">Sil</translation>
+<translation id="6435221585574090192">Chrome Enterprise Threat Protection tarafından işaretlenen güvenlik işlemleri hakkında Yöneticiniz ile veri paylaşın. Bu veriler, sayfa URL'lerini, dosya adını, dosya meta verisini, cihaz kullanıcı adınızı ve Chrome kullanıcı adınızı içerebilir.</translation>
<translation id="6440503408713884761">Yoksayıldı</translation>
<translation id="6446163441502663861">Kahu (Zarf)</translation>
<translation id="6446608382365791566">Daha fazla bilgi ekleyin</translation>
@@ -1018,20 +1035,19 @@
<translation id="6465306955648956876">Şifreleri yönet...</translation>
<translation id="647261751007945333">Cihaz politikaları</translation>
<translation id="6476284679642588870">Ödeme yöntemlerini yönetin</translation>
-<translation id="6477321094435799029">Chrome, bu sayfada olağan dışı kod tespit etti ve kişisel bilgilerinizi (örneğin, şifreler, telefon numaraları ve kredi kartları) korumak için sayfayı engelledi.</translation>
<translation id="6489534406876378309">Kilitlenmeleri yüklemeye başla</translation>
<translation id="6499038740797743453">Şifre sıfırlansın mı?</translation>
<translation id="6507833130742554667">Kredi ve banka kartları kabul edilir.</translation>
<translation id="650855688985305916">Evet, sakla</translation>
<translation id="6508722015517270189">Chrome'u yeniden başlatın</translation>
<translation id="6517596291481585650">Uyarı: Bu politika bir liste olmadığından politikada belirtildiği gibi bir liste olarak birleştirilmemiştir.</translation>
+<translation id="6518133107902771759">Doğrula</translation>
<translation id="6521745193039995384">Etkin değil</translation>
<translation id="6529602333819889595">Silmeyi &amp;Yeniden Yap</translation>
<translation id="6534179046333460208">Fiziksel Web önerileri</translation>
<translation id="6545864417968258051">Bluetooth taraması</translation>
<translation id="6554795675067793129">Hesabınız <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetiliyor.</translation>
<translation id="6556866813142980365">Yeniden Yap</translation>
-<translation id="6563469144985748109">Yöneticiniz henüz onaylamadı</translation>
<translation id="6569060085658103619">Bir uzantı sayfası görüntülüyorsunuz</translation>
<translation id="6578796323535178455">C2 (Zarf)</translation>
<translation id="6579990219486187401">Açık Pembe</translation>
@@ -1049,11 +1065,13 @@
<translation id="6643016212128521049">Temizle</translation>
<translation id="6644283850729428850">Bu politika uygun bulunmadı.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Yok}=1{1 siteden (Google Hesabınızdan çıkış yapılmaz)}other{# siteden (Google Hesabınızdan çıkış yapılmaz)}}</translation>
+<translation id="6652101503459149953">Windows Hello'yu kullan</translation>
<translation id="6657585470893396449">Şifre</translation>
<translation id="6670613747977017428">Güvenliğe dön.</translation>
<translation id="6671697161687535275">Form önerisi Chromium'dan kaldırılsın mı?</translation>
<translation id="6685834062052613830">Çıkış yapın ve kurulumu tamamlayın</translation>
<translation id="6689271823431384964">Chrome, oturumunuz açık olduğu için kartlarınızı Google Hesabınıza kaydetmeyi öneriyor. Bu davranışı ayarlardan değiştirebilirsiniz. Kart sahibinin adı hesabınızdan gelir.</translation>
+<translation id="6707256370811247129">Önbelleğin içeriğini ve Chrome'da indirdiğiniz veya yüklediğiniz dosyaları tarama.</translation>
<translation id="6710213216561001401">Önceki</translation>
<translation id="6710594484020273272">&lt;Arama terimini yazın&gt;</translation>
<translation id="671076103358959139">Kayıt Jetonu:</translation>
@@ -1061,10 +1079,10 @@
<translation id="6738516213925468394">Verileriniz <ph name="TIME" /> tarihinde <ph name="BEGIN_LINK" />senkronizasyon parolanızla<ph name="END_LINK" /> şifrelendi. Senkronizasyonu başlatmak için senkronizasyon parolanızı girin.</translation>
<translation id="674375294223700098">Bilinmeyen sunucu sertifikası hatası.</translation>
<translation id="6744009308914054259">Bağlantı kurulmasını beklerken çevrimdışı makaleleri okumak için İndirilenler bölümünü ziyaret edebilirsiniz.</translation>
+<translation id="6747611005629681221">Uyarı: Kullanımdan kaldırılmış özellikler!</translation>
<translation id="6753269504797312559">Politika değeri</translation>
<translation id="6757797048963528358">Cihazınız uyku moduna geçti.</translation>
<translation id="6768213884286397650">Hagaki (Kartpostal)</translation>
-<translation id="6778737459546443941">Ebeveyniniz henüz onaylamadı</translation>
<translation id="67862343314499040">Mor</translation>
<translation id="6786747875388722282">Uzantılar</translation>
<translation id="6790428901817661496">Oynat</translation>
@@ -1072,6 +1090,7 @@
<translation id="681021252041861472">Gerekli Alan</translation>
<translation id="6810899417690483278">Özelleştirme Kimliği</translation>
<translation id="6825578344716086703"><ph name="DOMAIN" /> alanına erişme girişiminde bulundunuz ancak sunucu SHA-1 gibi zayıf bir imza algoritması kullanılarak imzalanmış bir sertifika sağladı. Bu, sunucunun sağladığı güvenlik bilgilerinin sahte olabileceği anlamına gelir ve sunucu sizin beklediğiniz sunucu olmayabilir (bir saldırgan ile irtibat kuruyor olabilirsiniz).</translation>
+<translation id="6826370046007623921">Veri Kaybını Önleme</translation>
<translation id="6831043979455480757">Çevir</translation>
<translation id="6839929833149231406">Bölge</translation>
<translation id="6852204201400771460">Uygulama yeniden yüklensin mi?</translation>
@@ -1084,7 +1103,6 @@
<translation id="6891596781022320156">Politika düzeyi desteklenmiyor.</translation>
<translation id="6895330447102777224">Kartınız onaylandı</translation>
<translation id="6897140037006041989">Kullanıcı Aracısı</translation>
-<translation id="6903319715792422884">Google'a bazı <ph name="BEGIN_WHITEPAPER_LINK" />sistem bilgilerini ve sayfa içeriklerini<ph name="END_WHITEPAPER_LINK" /> göndererek Güvenli Tarama'nın iyileştirilmesine yardımcı olabilirsiniz. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Kullanıcı:</translation>
<translation id="6934672428414710184">Bu ad Google Hesabınızdan gelmektedir</translation>
<translation id="6944692733090228304">Şifrenizi <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> tarafından yönetilmeyen bir sitede girdiniz. Hesabınızı korumak için şifrenizi başka uygulama ve sitelerde tekrar kullanmayın.</translation>
@@ -1129,6 +1147,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> ve <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> yöntem daha}other{<ph name="PAYMENT_METHOD_PREVIEW" /> ve <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> yöntem daha}}</translation>
<translation id="7153618581592392745">Lavanta</translation>
<translation id="717330890047184534">Gaia Kimliği:</translation>
+<translation id="7174545416324379297">Birleştirildi</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ve <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> seçenek daha}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ve <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> seçenek daha}}</translation>
<translation id="7177397715882417099">Gittiğiniz sunucu (<ph name="ORIGIN" />) kendisine gelen tüm isteklere
bir güvenlik politikasının uygulanmasını talep etmişti. Ancak bir politika
@@ -1166,6 +1185,7 @@ Ek ayrıntılar:
<translation id="7320336641823683070">Bağlantı Yardımı</translation>
<translation id="733354035281974745">Cihaz yerel hesabını geçersiz kıl</translation>
<translation id="7334320624316649418">Sıralama değişikliğini &amp;yeniden yap</translation>
+<translation id="7337706099755338005">Platformunuzda kullanılamıyor.</translation>
<translation id="733923710415886693">Sunucunun sertifikası, Sertifika Şeffaflığı aracılığıyla açıklanmadı.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">İlişkili olma durumu:</translation>
@@ -1197,7 +1217,6 @@ Ek ayrıntılar:
<translation id="7440140511386898319">Çevrimdışıyken keşfetme</translation>
<translation id="7441627299479586546">Politika konusu yanlış</translation>
<translation id="7442725080345379071">Açık Turuncu</translation>
-<translation id="7444046173054089907">Bu site engellenmiş</translation>
<translation id="7445762425076701745">Bağlı olduğunuz sunucunun kimliği tam olarak doğrulanamıyor. Sunucuya yalnızca ağınızın içinde geçerli olan ve dış sertifika yetkilisi tarafından hiçbir şekilde sahipliği doğrulanamayacak bir ad kullanarak bağlandınız. Bazı sertifika yetkilileri bu adlar için sertifikalar yayınlasa da, bir saldırgana değil, hedeflenen web sitesine bağlandığınızdan emin olmanın herhangi bir yolu yoktur.</translation>
<translation id="7451311239929941790">Bu sorun hakkında <ph name="BEGIN_LINK" />daha fazla<ph name="END_LINK" /> bilgi edinme.</translation>
<translation id="7455133967321480974">Genel varsayılanı kullan (Engelle)</translation>
@@ -1219,9 +1238,9 @@ Ek ayrıntılar:
<translation id="7538364083937897561">A2 (Zarf)</translation>
<translation id="7542403920425041731">Onayladığınızda kart ayrıntılarınız bu siteyle paylaşılacaktır.</translation>
<translation id="7542995811387359312">Bu form güvenli bağlantı kullanmadığından kredi kartı bilgilerini otomatik doldurma özelliği devre dışı bırakıldı.</translation>
-<translation id="7543525346216957623">Ebeveyninize sorun</translation>
<translation id="7548892272833184391">Bağlantı hatalarını düzeltme</translation>
<translation id="7549584377607005141">Bu Web sayfasının düzgün şekilde görüntülenmesi için, önceden girdiğiniz veriler gerekiyor. Bu verileri tekrar gönderebilirsiniz, ancak bunu yaptığınızda bu sayfanın daha önce gerçekleştirdiği işlemler de tekrar edilir.</translation>
+<translation id="7550637293666041147">Cihaz kullanıcı adınız ve Chrome kullanıcı adınız</translation>
<translation id="7552846755917812628">Aşağıdaki ipuçlarını deneyin:</translation>
<translation id="7554791636758816595">Yeni Sekme</translation>
<translation id="7564049878696755256"><ph name="ORG_NAME" /> hesabınıza erişimi kaybedebilir veya kimlik hırsızlığına maruz kalabilirsiniz. Chrome, şifrenizi hemen değiştirmenizi önerir.</translation>
@@ -1236,6 +1255,7 @@ Ek ayrıntılar:
<translation id="7610193165460212391">Değer aralık dışında: <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Son kullanım tarihi: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Google Hesabı şifrenizin farklı bir sürümü kullanılarak şifrelenmiş verileriniz zaten var. Lütfen bu şifreyi aşağıya girin.</translation>
+<translation id="7625784245512586808">Chrome Enterprise Threat Protection</translation>
<translation id="7633909222644580952">Performans verileri ve kilitlenme raporları</translation>
<translation id="7637571805876720304">Kredi kartı Chromium'dan kaldırılsın mı?</translation>
<translation id="7638605456503525968">Seri bağlantı noktaları</translation>
@@ -1248,7 +1268,6 @@ Ek ayrıntılar:
<translation id="7668654391829183341">Bilinmeyen cihaz</translation>
<translation id="7669271284792375604">Bu sitedeki saldırganlar web'e göz atma deneyiminize zarar veren programlar yüklemeniz için sizi kandırmayı (örneğin ana sayfanızı değiştirerek ya da ziyaret ettiğiniz sitelerde ek reklamlar görüntüleyerek) deneyebilir.</translation>
<translation id="7676643023259824263">Panoda metni (<ph name="TEXT" />) ara</translation>
-<translation id="7679176406634891508">Platform ve Cloud</translation>
<translation id="7681101578153515023">Arama Motorunu değiştir</translation>
<translation id="7682287625158474539">Sevkiyat</translation>
<translation id="7687186412095877299">Ödeme formlarını kayıtlı ödeme yöntemlerinizle doldurur</translation>
@@ -1263,7 +1282,6 @@ Ek ayrıntılar:
<translation id="7723047071702270851">Kartı Düzenleyin</translation>
<translation id="774634243536837715">Tehlikeli içerik engellendi.</translation>
<translation id="7752995774971033316">Yönetimden kaldırıldı</translation>
-<translation id="7755287808199759310">Ebeveyniniz engellemeyi sizin için kaldırabilir</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Bağlantıyı güvenlik duvarı veya virüsten korunma yazılımı engellemiş olabilir.</translation>
<translation id="7759163816903619567">Görünen alan:</translation>
@@ -1307,7 +1325,6 @@ Ek ayrıntılar:
<translation id="8004582292198964060">Tarayıcı</translation>
<translation id="8009225694047762179">Şifreleri Yönet</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Aşağıdaki kart ve ona ait fatura adresi kaydedilecektir. Kaydettiğiniz kartı <ph name="USER_EMAIL" /> hesabında oturumunuz açıkken kullanabilirsiniz.}other{Aşağıdaki kartlar ve onlara ait fatura adresleri kaydedilecektir. Kaydettiğiniz kartları <ph name="USER_EMAIL" /> hesabında oturumunuz açıkken kullanabilirsiniz.}}</translation>
-<translation id="8012647001091218357">Şu anda ebeveynlerinize erişemedik. Lütfen tekrar deneyin.</translation>
<translation id="8025119109950072390">Bu sitedeki saldırganlar sizi kandırarak yazılım yükleme veya kişisel bilgilerinizi (örneğin şifreler, telefon numaraları veya kredi kartları) ifşa etme gibi tehlikeli şeyler yaptırabilir.</translation>
<translation id="8034522405403831421">Bu sayfa <ph name="SOURCE_LANGUAGE" /> dilinde. <ph name="TARGET_LANGUAGE" /> diline çevrilsin mi?</translation>
<translation id="8035152190676905274">Kalem</translation>
@@ -1318,6 +1335,7 @@ Ek ayrıntılar:
<translation id="8041940743680923270">Genel varsayılanı kullan (Sor)</translation>
<translation id="8042918947222776840">Alma Yöntemi Seç</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" doğru şekilde yapılandırılmamış. Genellikle "<ph name="SOFTWARE_NAME" />" kaldırıldığında sorun çözülür. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Bundan böyle bir kart güvenlik kodu girmeniz gerekmeyecek</translation>
<translation id="8066955247577885446">Maalesef bir hata oluştu.</translation>
<translation id="8074253406171541171">10x13 (Zarf)</translation>
<translation id="8078141288243656252">Doküman döndürüldüğünde ek açıklama özelliği kullanılamaz</translation>
@@ -1348,6 +1366,7 @@ Ek ayrıntılar:
<translation id="8211406090763984747">Bağlantı güvenli</translation>
<translation id="8218327578424803826">Atanan Konum:</translation>
<translation id="8220146938470311105">C7/C6 (Zarf)</translation>
+<translation id="8220639454292072926">Kurumsal Raporlama</translation>
<translation id="8225771182978767009">Bu bilgisayarı kuran kişi bu siteyi engellemeyi seçmiş.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Sayfayı yeni bir Gizli sekmede aç</translation>
@@ -1402,24 +1421,24 @@ Ek ayrıntılar:
<translation id="8508648098325802031">Arama simgesi</translation>
<translation id="8522552481199248698">Chrome, Google Hesabınızı korumanıza ve şifrenizi değiştirmenize yardımcı olabilir.</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />Bir tespit sorununu bildirebilir<ph name="END_ERROR_LINK" /> veya güvenliğiniz açısından riskleri anlıyorsanız <ph name="BEGIN_LINK" />güvenli olmayan bu siteyi ziyaret edebilirsiniz<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Sorularınız mı var? Profilinizi denetleyen kişiyle iletişime geçin.</translation>
<translation id="8553075262323480129">Sayfanın dili belirlenemediğinden çeviri başarısız oldu.</translation>
<translation id="8557066899867184262">CVC, kartınızın arkasında bulunur.</translation>
<translation id="8559762987265718583">Cihazınızın tarih ve saati (<ph name="DATE_AND_TIME" />) yanlış olduğundan <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> alan adına gizli bir bağlantı kurulamıyor.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> şüpheli site</translation>
<translation id="8564985650692024650">Chromium, <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> şifrenizi başka sitelerde kullandıysanız sıfırlamanızı önerir.</translation>
<translation id="8571890674111243710">Sayfa <ph name="LANGUAGE" /> diline çevriliyor...</translation>
<translation id="858637041960032120">Telefon no ekle
</translation>
-<translation id="859285277496340001">Sertifika, iptal edilip edilmediğinin denetlenebileceği bir mekanizma belirtmiyor.</translation>
<translation id="860043288473659153">Kart sahibinin adı</translation>
<translation id="861775596732816396">Boyut 4</translation>
-<translation id="8620436878122366504">Ebeveynleriniz henüz onaylamadı</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Bu Kartı Bu Cihaza Kaydet</translation>
<translation id="8626112503828625890">Fatura bilgileri Google Hesabı'nda saklansın mı?</translation>
+<translation id="8647750283161643317">Tümünü varsayılan değerlere sıfırla</translation>
<translation id="8663226718884576429">Sipariş Özeti, <ph name="TOTAL_LABEL" />, Daha Fazla Ayrıntı</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, yanıt, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Kullanılabilir</translation>
<translation id="8703575177326907206"><ph name="DOMAIN" /> bağlantınız şifrelenmedi.</translation>
<translation id="8718314106902482036">Ödeme işlemi tamamlanmadı</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, arama önerisi</translation>
@@ -1430,6 +1449,7 @@ Ek ayrıntılar:
<translation id="8738058698779197622">Güvenli bir bağlantı kurmak için saatinizin doğru ayarlanmış olması gerekir. Bunun sebebi, web sitelerinin kendilerini tanımlamak için kullandıkları sertifikaların sadece belli süreler için geçerli olmasıdır. Cihazınızın saati yanlış olduğundan, Chromium bu sertifikaları doğrulayamaz.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> ana makinesinin &lt;abbr id="dnsDefinition"&gt;DNS adresi&lt;/abbr&gt; bulunamadı. Sorun teşhis ediliyor.</translation>
<translation id="874846938927089722">Kabul Edilen Kredi Kartları ve Ön Ödemeli Kartlar</translation>
+<translation id="874918643257405732">Bu sekmeye yer işareti koy</translation>
<translation id="8759274551635299824">Bu kartın kullanım süresi doldu</translation>
<translation id="8761567432415473239">Google Güvenli Tarama, yakın zamanda <ph name="SITE" /> sitesinde <ph name="BEGIN_LINK" />zararlı programlar buldu<ph name="END_LINK" />.</translation>
<translation id="8763927697961133303">USB cihaz</translation>
@@ -1459,6 +1479,7 @@ Ek ayrıntılar:
<translation id="8938939909778640821">Kabul edilen kredi kartları ve ön ödemeli kartlar</translation>
<translation id="8943282376843390568">Küf yeşili</translation>
<translation id="8957210676456822347">Giriş Portalı Yetkilendirmesi</translation>
+<translation id="8962950042226115166">Şüpheli site</translation>
<translation id="8968766641738584599">Kartı kaydet</translation>
<translation id="8971063699422889582">Sunucu sertifikasının süresi doldu.</translation>
<translation id="8975012916872825179">Telefon numaraları, e-posta adresleri ve gönderim adresleri gibi bilgileri içerir</translation>
@@ -1481,24 +1502,24 @@ Ek ayrıntılar:
<translation id="9035022520814077154">Güvenlik hatası</translation>
<translation id="9038649477754266430">Sayfaları daha hızlı yüklemek için bir tahmin hizmeti kullan</translation>
<translation id="9039213469156557790">Ayrıca, bu sayfa güvenli olmayan başka kaynaklar içeriyor. Bu kaynaklar, aktarım sırasında başkaları tarafından görülebilir ve bir saldırgan tarafından sayfanın davranışını değiştirmek üzere kullanılabilir.</translation>
+<translation id="9044359186343685026">Touch ID'yi kullan</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619"><ph name="DOMAIN" /> alan adına erişmeye çalıştınız, ancak sunucu geçersiz bir sertifika sağladı.</translation>
<translation id="9050666287014529139">Parola</translation>
<translation id="9065203028668620118">Düzenle</translation>
<translation id="9065745800631924235">geçmişteki <ph name="TEXT" /> araması</translation>
<translation id="9069693763241529744">Bir uzantı tarafından engellendi</translation>
-<translation id="9076283476770535406">Yetişkin içeriği bulunabilir</translation>
<translation id="9076630408993835509">Bu tarayıcı bir şirket veya başka bir kuruluş tarafından yönetilmemektedir. Bu cihazdaki etkinlikler Chrome dışında yönetilebilir. <ph name="BEGIN_LINK" />Daha Fazla Bilgi<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Daha fazla bilgi gerekli</translation>
<translation id="9080712759204168376">Sipariş Özeti</translation>
<translation id="9089260154716455634">Mesai Dışı Saatler Politikası:</translation>
<translation id="9095388113577226029">Diğer diller...</translation>
+<translation id="9098981495403789647">Yöneticiniz, tarayıcınızda Chrome Enterprise Threat Protection özelliğini etkinleştirdi. Chrome Enterprise Threat Protection özelliğinin verilerinizin bir kısmına erişimi vardır.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> normalde bilgilerinizi korumak için şifreleme kullanmaktadır. Chromium bu sefer <ph name="SITE" /> sitesine bağlanmayı denediğinde, web sitesi sıra dışı ve yanlış kimlik bilgileri döndürdü. Bir saldırgan <ph name="SITE" /> gibi davranmaya çalışıyor olabilir ya da bir Kablosuz oturum açma ekranı bağlantıyı kesmiştir. Chromium herhangi bir veri alışverişinden önce bağlantıyı durdurduğu için bilgileriniz hâlâ güvendedir.</translation>
<translation id="9106062320799175032">Fatura Adresi Ekleyin</translation>
<translation id="9114524666733003316">Kart onaylanıyor...</translation>
<translation id="9128870381267983090">Ağa bağlan</translation>
<translation id="9137013805542155359">Orijinali göster</translation>
-<translation id="9137248913990643158">Lütfen bu uygulamayı kullanmadan önce Chrome'u başlatıp oturum açın.</translation>
<translation id="9141013498910525015">Adresleri yönet</translation>
<translation id="9148088599418889305">Gönderim Yöntemi Seç</translation>
<translation id="9148507642005240123">Düzenlemeyi &amp;geri al</translation>
diff --git a/chromium/components/strings/components_strings_uk.xtb b/chromium/components/strings/components_strings_uk.xtb
index ab86c3b3184..2be63e8f283 100644
--- a/chromium/components/strings/components_strings_uk.xtb
+++ b/chromium/components/strings/components_strings_uk.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Додайте ім’я на картці</translation>
<translation id="1089439967362294234">Змінити пароль</translation>
+<translation id="1096545575934602868">Максимальна кількість записів у цьому полі: <ph name="MAX_ITEMS_LIMIT" />. Усі подальші записи буде відхилено.</translation>
<translation id="109743633954054152">Керуйте паролями в налаштуваннях Chrome</translation>
<translation id="1103523840287552314">Завжди перекладати з такої мови: <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Якщо вибрати цю опцію, Chrome зберігатиме копію даних вашої картки на цьому пристрої для швидшого заповнення форм.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Відкрийте <ph name="BEGIN_LINK" />кешовану копію<ph name="END_LINK" /> <ph name="URL" /></translation>
<translation id="1156303062776767266">Ви переглядаєте локальний або спільний файл</translation>
<translation id="1158211211994409885">Хост <ph name="HOST_NAME" /> неочікувано розірвав з’єднання.</translation>
+<translation id="115926840831309955">Перевірте код CVC й повторіть спробу або оновіть дату закінчення терміну дії</translation>
<translation id="1161325031994447685">знову під’єднати пристрій до мережі Wi-Fi</translation>
<translation id="1165039591588034296">Помилка</translation>
<translation id="1175364870820465910">&amp;Друк...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Програмне забезпечення на вашому комп’ютері перешкоджає веб-переглядачеві Chrome безпечно під’єднуватися до Інтернету" (лише для комп’ютерів з ОС Windows)</translation>
<translation id="1294154142200295408">Варіанти командного рядка</translation>
<translation id="129553762522093515">Нещодавно закриті</translation>
+<translation id="1298536327547837046">Пошук зловмисного програмного забезпечення</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Спробуйте видалити файли cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Функції не підтримуються</translation>
<translation id="1320233736580025032">Prc1 (конверт)</translation>
<translation id="132301787627749051">Пошук зображення з буфера обміну</translation>
<translation id="1323433172918577554">Показати більше</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Таблиці</translation>
<translation id="1527263332363067270">Очікується з’єднання…</translation>
<translation id="1529521330346880926">10x15 (конверт)</translation>
+<translation id="1530707389502320859">Сайт, на який ви намагалися перейти, виглядає несправжнім. Зловмисники іноді імітують сайти, вносячи майже непомітні зміни в URL-адресу.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Повідомлення з цієї сторінки</translation>
<translation id="153384715582417236">Більше нічого немає</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">ОС</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Документ завеликий для створення приміток</translation>
-<translation id="1721312023322545264">Вам потрібен дозвіл адміністратора <ph name="NAME" />, щоб перейти на цей сайт</translation>
<translation id="1721424275792716183">* Обов’язкове поле</translation>
<translation id="1727741090716970331">Додайте дійсний номер картки</translation>
<translation id="1728677426644403582">Ви переглядаєте джерело веб-сторінки</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Відвідані веб-сайти й час перебування на них</translation>
<translation id="1826516787628120939">Перевірка</translation>
<translation id="1834321415901700177">Цей сайт містить шкідливі програми</translation>
+<translation id="1838374766361614909">Очистити поле пошуку</translation>
<translation id="1839551713262164453">Не вдалося перевірити значення правила. Знайдено помилки</translation>
<translation id="1842969606798536927">Оплатити</translation>
<translation id="1871208020102129563">Проксі-сервер налаштовано на використання фіксованих проксі-серверів, а не URL-адреси сценарію .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Згорнути список</translation>
<translation id="1898423065542865115">Фільтрування</translation>
<translation id="1914326953223720820">Сервіс розпакування</translation>
+<translation id="1915697529809968049">Використовувати Touch ID замість коду CVC?</translation>
<translation id="1916770123977586577">Щоб застосувати оновлені налаштування на цьому сайті, оновіть сторінку</translation>
<translation id="1919345977826869612">Оголошення</translation>
<translation id="1919367280705858090">Як виправити конкретну помилку</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Закладки <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Помилка серіалізації</translation>
<translation id="1974060860693918893">Розширені</translation>
+<translation id="1974883374937189061">Щоб допомогти покращити безпеку Chrome, надсилайте в Google <ph name="BEGIN_WHITEPAPER_LINK" />URL-адреси відвіданих сторінок, обмежену системну інформацію та контент деяких сторінок<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Версія мікропрограми</translation>
<translation id="1981206234434200693">Очистити дані історії веб-перегляду Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{і ще 1}one{і ще #}few{і ще #}many{і ще #}other{і ще #}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Введіть дійсний рік закінчення терміну дії</translation>
<translation id="2212735316055980242">Правило не знайдено</translation>
<translation id="2213606439339815911">Отримання записів…</translation>
+<translation id="2215727959747642672">Редагування файлу</translation>
<translation id="2218879909401188352">Зловмисники можуть використати сайт <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, щоб установити небезпечні додатки, які шкодять пристроям, наприклад, додають приховані платежі за мобільний зв’язок або викрадають особисту інформацію. <ph name="BEGIN_LEARN_MORE_LINK" />Докладніше<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Немає Інтернету</translation>
<translation id="2230458221926704099">Відновіть з’єднання за допомогою <ph name="BEGIN_LINK" />додатка для діагностики<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Надіслати</translation>
+<translation id="2248949050832152960">Використовувати веб-автентифікацію</translation>
<translation id="225207911366869382">Дію цього значення припинено для цього правила</translation>
<translation id="2257315177824333709">На жаль, зараз не вдається зберегти картку.</translation>
<translation id="2262243747453050782">Помилка HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">Недійсна URL-адреса для пошуку.</translation>
<translation id="2482878487686419369">Сповіщення</translation>
<translation id="248348093745724435">Правила пристрою</translation>
-<translation id="2485387744899240041">Імена користувачів пристрою та веб-переглядача</translation>
<translation id="2491120439723279231">Сертифікат сервера містить помилки.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Синтаксичний аналізатор файлів JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Назад</translation>
<translation id="2503184589641749290">Прийнятні дебетові та передплачені картки</translation>
<translation id="2505268675989099013">Захистити обліковий запис</translation>
+<translation id="2515335152965840738">ІГНОРУВАТИ</translation>
<translation id="2515629240566999685">перевірити сигнал у своїй місцевості</translation>
<translation id="2523886232349826891">Збережено лише на цьому пристрої</translation>
<translation id="2524461107774643265">Додайте більше інформації</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Надіслати</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Немає}=1{1 пароль (для <ph name="DOMAIN_LIST" />)}=2{2 паролі (для <ph name="DOMAIN_LIST" />)}one{# пароль (для <ph name="DOMAIN_LIST" />)}few{# паролі (для <ph name="DOMAIN_LIST" />)}many{# паролів (для <ph name="DOMAIN_LIST" />)}other{# пароля (для <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Закрийте інші вкладки та додатки</translation>
-<translation id="267371737713284912">натисніть <ph name="MODIFIER_KEY_DESCRIPTION" />, щоб відмінити</translation>
<translation id="2674170444375937751">Ви дійсно бажаєте видалити ці сторінки зі своєї історії?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Вийти</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">Значення не відповідає формату.</translation>
<translation id="2705137772291741111">Не вдається прочитати збережену (кешовану) копію цього сайту.</translation>
<translation id="2709516037105925701">Автозаповнення</translation>
-<translation id="2712173769900027643">Запитувати дозвіл</translation>
<translation id="2713444072780614174">Білий</translation>
<translation id="2720342946869265578">Поблизу</translation>
<translation id="2721148159707890343">Запит надіслано</translation>
<translation id="2728127805433021124">Сертифікат сервера підписано з використанням слабкого алгоритму підпису.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />провести діагностику з’єднання<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Увімкнувши ці функції, ви можете втратити дані веб-перегляду або створити загрозу безпеці чи конфіденційності. Увімкнені функції діють для всіх користувачів веб-переглядача.</translation>
<translation id="2735043616039983645">У цьому правилі є кілька джерел із конфліктними значеннями.</translation>
<translation id="2738330467931008676">Вибрати адресу отримання</translation>
<translation id="2740531572673183784">OK</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">З’єднання було скинуто.</translation>
<translation id="2788784517760473862">Прийнятні кредитні картки</translation>
<translation id="2792012897584536778">Адміністратори цього пристрою налаштували сертифікати безпеки, які дають їм змогу бачити вміст відкритих вами веб-сайтів.</translation>
-<translation id="2794233252405721443">Сайт заблоковано</translation>
<translation id="2799020568854403057">Сайт містить шкідливі додатки</translation>
<translation id="2799223571221894425">Перезапустити</translation>
<translation id="2803306138276472711">Функція безпечного перегляду від Google нещодавно <ph name="BEGIN_LINK" />виявила зловмисне програмне забезпечення<ph name="END_LINK" /> на сайті <ph name="SITE" />. Іноді зловмисне програмне забезпечення заражає зазвичай безпечні веб-сайти.</translation>
+<translation id="2815364696811431560">ЗАЛИШИТИ САЙТ</translation>
<translation id="2824775600643448204">Адресний і пошуковий рядок</translation>
<translation id="2826760142808435982">З’єднання зашифровано й автентифіковано з використанням шифру <ph name="CIPHER" /> і використовує механізм обміну ключами <ph name="KX" />.</translation>
<translation id="2835170189407361413">Очистити форму</translation>
<translation id="2847118875340931228">Відкрити вікно в режимі анонімного перегляду</translation>
<translation id="2850739647070081192">Invite (конверт)</translation>
-<translation id="2851634818064021665">Щоб відвідувати цей сайт, потрібен дозвіл</translation>
<translation id="2856444702002559011">Зловмисники можуть намагатися викрасти вашу інформацію із сайту <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (наприклад, паролі, повідомлення чи дані кредитних карток). <ph name="BEGIN_LEARN_MORE_LINK" />Докладніше<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Зберегти картку?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">Якщо цю функцію ввімкнено, Chromium зберігає копію даних вашої картки на пристрої, щоб ви могли швидше заповнювати форми.</translation>
<translation id="2985398929374701810">Введіть дійсну адресу</translation>
<translation id="2986368408720340940">Цей спосіб отримання недоступний. Виберіть інший спосіб.</translation>
+<translation id="2987034854559945715">Немає відповідних функцій</translation>
<translation id="2991174974383378012">Надання інформації веб-сайтам</translation>
<translation id="2991571918955627853">Зараз не можна перейти на сторінку <ph name="SITE" />, оскільки веб-сайт використовує протокол HSTS. Помилки мережі й атаки зазвичай тимчасові, тому ця сторінка, скоріш за все, запрацює пізніше.</translation>
<translation id="3005723025932146533">Показати збережену копію</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">Неправильний тип правила</translation>
<translation id="3037605927509011580">От халепа!</translation>
<translation id="3041612393474885105">Інформація про сертифікат</translation>
+<translation id="3057676462092457419">Значення режиму DnsOverHttps "<ph name="SECURE_DNS_MODE_SECURE" />" ще не підтримується, тому вибрано значення "<ph name="SECURE_DNS_MODE_OFF" />".</translation>
<translation id="3060227939791841287">C9 (конверт)</translation>
<translation id="3061707000357573562">Служба виправлень</translation>
<translation id="3064966200440839136">Щоб оплатити в зовнішньому додатку, ви вийдете з режиму анонімного перегляду. Продовжити?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> на сервері <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Скасувати оплату</translation>
<translation id="3207960819495026254">Створено закладку</translation>
+<translation id="3209034400446768650">На сторінці може стягуватися плата</translation>
<translation id="3225919329040284222">Сервер надав сертифікат, який не відповідає очікуваним вбудованим параметрам. Ці очікувані параметри встановлено для певних веб-сайтів із високим рівнем безпеки, щоб захистити вас.</translation>
<translation id="3226128629678568754">Натисніть кнопку перезавантаження, щоб повторно надіслати дані, потрібні для завантаження сторінки.</translation>
<translation id="3227137524299004712">Мікрофон</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">Інформація про версії пристрою та веб-переглядача</translation>
<translation id="323107829343500871">Ввести код CVC картки <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Завжди виявляти важливий вміст на цьому сайті</translation>
-<translation id="3254409185687681395">Додати цю сторінку до закладок</translation>
<translation id="3270847123878663523">&amp;Відмінити перевпорядкування</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Додати ім’я на кредитній картці</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">Додати платіжну адресу</translation>
<translation id="3324983252691184275">Малиновий</translation>
<translation id="3338095232262050444">Надійне</translation>
-<translation id="3345135638360864351">Не вдалося надіслати запит на доступ до цього сайту користувачеві <ph name="NAME" />. Повторіть спробу.</translation>
<translation id="3355823806454867987">Змінити налаштування проксі...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />не зберігатиме<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">Сховати додаткову інформацію</translation>
<translation id="3467763166455606212">Потрібно вказати ім’я власника картки</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />: зараз відкрито, натисніть Tab, а потім – клавішу Enter, щоб перейти на відкриту вкладку</translation>
-<translation id="3479539252931486093">Не очікували? <ph name="BEGIN_LINK" />Повідомте нас<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Не зараз</translation>
<translation id="3484560055331845446">Ви можете втратити доступ до облікового запису Google. Chrome радить змінити пароль. Вам буде запропоновано ввійти в обліковий запис.</translation>
<translation id="3495081129428749620">Знайти на сторінці
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Не вдалося зв’язатися з одним із ваших батьків. Повторіть спробу.</translation>
<translation id="3512163584740124171">Це правило ігнорується, оскільки інше правило цієї групи має вищий пріоритет.</translation>
<translation id="3528171143076753409">Сертифікат сервера ненадійний.</translation>
<translation id="3528485271872257980">Темно-коричневий</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Принаймні 1 запис на синхронізованих пристроях}=1{1 запис (не враховуючи записів на синхронізованих пристроях)}one{# запис (не враховуючи записів на синхронізованих пристроях)}few{# записи (не враховуючи записів на синхронізованих пристроях)}many{# записів (не враховуючи записів на синхронізованих пристроях)}other{# запису (не враховуючи записів на синхронізованих пристроях)}}</translation>
<translation id="3539171420378717834">Зберігати копію даних цієї картки на цьому пристрої</translation>
-<translation id="3556433843310711081">Адміністратор може розблокувати його</translation>
<translation id="3566021033012934673">З’єднання не конфіденційне</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Повідомлення з вбудованої сторінки сайту <ph name="SITE" /></translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">Відкрийте сторінку в анонімному вікні (Ctrl+Shift+N)</translation>
<translation id="3679803492151881375">Звіт про аварійне завершення роботи створено: <ph name="CRASH_TIME" />, завантажено: <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Інформація про сертифікат</translation>
+<translation id="3701427423622901115">Скидання підтверджено.</translation>
<translation id="3704162925118123524">Можливо, щоб з’єднатися з цією мережею, потрібно відвідати її сторінку входу.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Завантаження...</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805">Зловмисники можуть використовувати сайт <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, щоб обманом змусити вас виконати небезпечну дію, наприклад, установити шкідливе програмне забезпечення або повідомити особисту інформацію (пароль, номер телефону, дані кредитної картки тощо). <ph name="BEGIN_LEARN_MORE_LINK" />Докладніше<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Не вдалося виконати переклад через помилку сервера.</translation>
<translation id="3759461132968374835">У вас немає останніх повідомлень про аварійне завершення роботи. Тут не відображатимуться випадки аварійного завершення роботи, які сталися, коли повідомлення про аварійне завершення роботи було вимкнено.</translation>
+<translation id="3760561303380396507">Використовувати Windows Hello замість коду CVC?</translation>
<translation id="3761718714832595332">Сховати статус</translation>
<translation id="3765032636089507299">Сторінка "Безпечний перегляд" розробляється.</translation>
<translation id="3778403066972421603">Зберегти дані картки у вашому обліковому записі Google і на цьому пристрої?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">Розмір 16</translation>
<translation id="3797522431967816232">Prc3 (конверт)</translation>
<translation id="3807873520724684969">Заблоковано шкідливий вміст.</translation>
+<translation id="3808375843007691220">Застереження: експериментальна функція.</translation>
<translation id="3810973564298564668">Змінити</translation>
<translation id="382518646247711829">Якщо ви використовуєте проксі-сервер…</translation>
<translation id="3828924085048779000">Порожня парольна фраза заборонена.</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">Оновити дату й час</translation>
<translation id="3884278016824448484">Конфліктуючий ідентифікатор пристрою</translation>
<translation id="3885155851504623709">Цивільний округ</translation>
-<translation id="3886446263141354045">Запит на доступ до цього сайту надіслано користувачу <ph name="NAME" /></translation>
<translation id="3890664840433101773">Додати електронну адресу</translation>
<translation id="3901925938762663762">Термін дії картки минув</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" />: <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Використовувати веб-автентифікацію замість коду CVC?</translation>
<translation id="3946209740501886391">Завжди запитувати на цьому сайті</translation>
<translation id="3949571496842715403">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. У його сертифікаті безпеки не вказано альтернативні імена. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
<translation id="3949601375789751990">Тут відображається ваша історія веб-перегляду</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Немає}=1{З 1 сайту }one{З # сайту }few{З # сайтів }many{З # сайтів }other{З # сайту }}</translation>
<translation id="397105322502079400">Обчислення...</translation>
<translation id="3973234410852337861">Хост <ph name="HOST_NAME" /> заблокований</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> вмикає Захист від загроз Chrome Enterprise у вашому веб-переглядачі. Захист від загроз має доступ до деяких ваших даних.</translation>
<translation id="3987940399970879459">Менше 1 МБ</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 веб-сторінка поруч}one{# веб-сторінка поруч}few{# веб-сторінки поруч}many{# веб-сторінок поруч}other{# веб-сторінки поруч}}</translation>
<translation id="4030383055268325496">&amp;Відмінити додавання</translation>
<translation id="4032320456957708163">Вашим веб-переглядачем керує домен <ph name="ENROLLMENT_DOMAIN" /></translation>
-<translation id="4034375457890803692">Натиснуте посилання спрямовує на сайт, який ви зазвичай не відвідуєте. Воно може вас спантеличити.</translation>
<translation id="4058922952496707368">Ключ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (конверт)</translation>
<translation id="4067947977115446013">Додайте дійсну адресу</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">Недійсний серійний номер пристрою</translation>
<translation id="410351446219883937">Автовідтворення</translation>
<translation id="4103763322291513355">Перейдіть на сторінку &lt;strong&gt;chrome://policy&lt;/strong&gt;, щоб переглянути список URL-адрес із "чорного" списку й інші правила, що примусово застосовується системним адміністратором.</translation>
+<translation id="4108231218301530806">Підтвердити цю картку наступного разу можна цифровим відбитком.</translation>
<translation id="4110652170750985508">Переглянути платіж</translation>
<translation id="4112140312785995938">Перейти назад</translation>
<translation id="4116663294526079822">Завжди дозволяти на цьому сайті</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">Недійсний підпис для підтвердження</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{ще <ph name="ITEM_COUNT" /> елемент}one{ще <ph name="ITEM_COUNT" /> елемент}few{ще <ph name="ITEM_COUNT" /> елементи}many{ще <ph name="ITEM_COUNT" /> елементів}other{ще <ph name="ITEM_COUNT" /> елемента}}</translation>
+<translation id="4176463684765177261">Вимкнено</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Щоб наступного разу платити швидше, додайте дані картки та платіжну адресу в обліковий запис Google.</translation>
<translation id="4196861286325780578">&amp;Повторити переміщення</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">Скинути пароль</translation>
<translation id="4279811152705618813">Вашим пристроєм <ph name="DEVICE_TYPE" /> керує домен <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Цю картку збережено у вашому обліковому записі Google}one{Ці картки збережено у вашому обліковому записі Google}few{Ці картки збережено у вашому обліковому записі Google}many{Ці картки збережено у вашому обліковому записі Google}other{Ці картки збережено у вашому обліковому записі Google}}</translation>
+<translation id="428847186335018806">Перевіряти файли, які ви завантажуєте або додаєте в Chrome.</translation>
<translation id="42981349822642051">Розгорнути</translation>
<translation id="4302965934281694568">Chou3 (конверт)</translation>
<translation id="4305817255990598646">Перейти</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">Листівка)</translation>
<translation id="443673843213245140">Використання проксі-сервера вимкнено, але чітко вказано налаштування проксі-сервера.</translation>
<translation id="445100540951337728">Прийнятні дебетові картки</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> підозріла поведінка</translation>
<translation id="4466881336512663640">Зміни форми не буде збережено. Продовжити?</translation>
<translation id="4477350412780666475">Наступна композиція</translation>
<translation id="4482953324121162758">Цей сайт не перекладатиметься.</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">&amp;Відмінити видалення</translation>
<translation id="4597348597567598915">Розмір 8</translation>
<translation id="4600854749408232102">C6/C5 (конверт)</translation>
+<translation id="464342062220857295">Функції пошуку</translation>
<translation id="4646534391647090355">Перейти зараз</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. Його сертифікат безпеки містить помилки. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A (конверт)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">З’єднання розірвано</translation>
-<translation id="471880041731876836">У вас немає дозволу відвідувати цей сайт</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />провести діагностику мережі Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Перезавантажити правила</translation>
<translation id="4728558894243024398">Платформа</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">За розміром сторінки</translation>
<translation id="4850886885716139402">Перегляд</translation>
<translation id="4854362297993841467">Цей спосіб доставки недоступний. Виберіть інший спосіб.</translation>
-<translation id="4858792381671956233">Ви надіслали батькам запит на перегляд цього сайту</translation>
<translation id="4864052566555297930">Порада щодо безпеки:</translation>
<translation id="4876188919622883022">Спрощений перегляд</translation>
<translation id="4876305945144899064">Немає імені користувача</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">Показувати застереження</translation>
<translation id="4984339528288761049">Prc5 (конверт)</translation>
<translation id="4989163558385430922">Показати все</translation>
+<translation id="4989542687859782284">Недоступні</translation>
<translation id="4989809363548539747">Цей плагін не підтримується</translation>
+<translation id="4995216769782533993">Підтвердьте код безпеки, щоб повідомляти дані картки цьому сайту</translation>
<translation id="5002932099480077015">Коли цю функцію ввімкнено, Chrome зберігає копію даних вашої картки на пристрої, щоб ви могли швидше заповнювати форми.</translation>
<translation id="5015510746216210676">Назва пристрою:</translation>
<translation id="5017554619425969104">Скопійований текст</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64-розрядна версія)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Підтвердьте дані картки</translation>
<translation id="5135404736266831032">Керувати адресами…</translation>
<translation id="5138227688689900538">Показати менше</translation>
<translation id="5141240743006678641">Шифрувати синхронізовані паролі за допомогою облікових даних Google</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">Хмара</translation>
<translation id="5252000469029418751">C7 (конверт)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Функції, які застосовуються до всієї системи, може налаштовувати лише власник: <ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">Застереження: це правило не об'єднано, як указано в PolicyDictionaryMultipleSourceMergeList, оскільки воно не є частиною правил щодо словників, які можна об'єднувати.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Завершити</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">Помилка збереження налаштувань правила</translation>
<translation id="5371425731340848620">Оновити картку</translation>
<translation id="5377026284221673050">"Ваш годинник відстає", "Ваш годинник спішить" або "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Ця сторінка може намагатись оманливим шляхом викрасти вашу особисту інформацію або зашкодити пристрою. Будьте обачні, коли вводите особисту інформацію або відкриваєте завантажені файли.</translation>
<translation id="5384855140246857529">Щоб використовувати картки на всіх своїх пристроях, увійдіть в обліковий запис і ввімкніть синхронізацію.</translation>
<translation id="5386426401304769735">Ланцюжок сертифіката цього сайту містить сертифікат, підписаний за допомогою SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,7 @@
<translation id="5457113250005438886">Недійсні дані</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}one{<ph name="CONTACT_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}few{<ph name="CONTACT_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}many{<ph name="CONTACT_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;Повторити редагування</translation>
+<translation id="5473728911100096288">Ці функції не підтримуються та зникнуть у майбутніх версіях.</translation>
<translation id="5478437291406423475">B6/C4 (конверт)</translation>
<translation id="5481076368049295676">Цей вміст може намагатися встановити на ваш пристрій небезпечну програму, яка викрадає або видаляє інформацію. <ph name="BEGIN_LINK" />Усе одно показати<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Додати дійсну адресу</translation>
@@ -863,7 +876,6 @@
<translation id="5570825185877910964">Захистити обліковий запис</translation>
<translation id="5571083550517324815">Адреса отримання не підтримується. Укажіть іншу адресу.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{Використовується 1 файл}one{Використовується # файл}few{Використовуються # файли}many{Використовуються # файлів}other{Використовуються # файлу}})</translation>
-<translation id="5572851009514199876">Увійдіть в обліковий запис Chrome, щоб веб-переглядач міг перевірити, чи ви маєте дозвіл відвідувати цей сайт.</translation>
<translation id="5580958916614886209">Перевірте місяць закінчення терміну дії та повторіть спробу</translation>
<translation id="5586446728396275693">Немає збережених адрес</translation>
<translation id="5595485650161345191">Редагувати адресу</translation>
@@ -871,6 +883,7 @@
<translation id="560412284261940334">Керування не підтримується</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Цей сайт може бути підробленим або шахрайським. Chrome радить залишити його.</translation>
<translation id="5610142619324316209">перевірити наявність з’єднання</translation>
<translation id="5610807607761827392">Ви можете керувати картками й адресами в <ph name="BEGIN_LINK" />Налаштуваннях<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996">Хост <ph name="HOST_NAME" /> переспрямував вас забагато разів.</translation>
@@ -894,11 +907,11 @@
<translation id="5720705177508910913">Поточний користувач</translation>
<translation id="5728056243719941842">C5 (конверт)</translation>
<translation id="5730040223043577876">Chrome радить скинути пароль, якщо ви застосовували його на інших сайтах.</translation>
-<translation id="5732392974455271431">Батьки можуть розблокувати його</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Збережіть картку в обліковому записі Google}one{Збережіть картки в обліковому записі Google}few{Збережіть картки в обліковому записі Google}many{Збережіть картки в обліковому записі Google}other{Збережіть картки в обліковому записі Google}}</translation>
<translation id="5763042198335101085">Введіть дійсну електронну адресу</translation>
<translation id="5765072501007116331">Укажіть адресу, щоб переглянути способи доставки та вимоги.</translation>
<translation id="5778550464785688721">Повний контроль пристроїв MIDI</translation>
+<translation id="5781136890105823427">Експеримент увімкнено</translation>
<translation id="578305955206182703">Бурштиновий</translation>
<translation id="57838592816432529">Вимкнути звук</translation>
<translation id="5784606427469807560">Не вдалося підтвердити дані картки. Перевірте з’єднання з Інтернетом і повторіть спробу.</translation>
@@ -915,13 +928,16 @@
<translation id="5860033963881614850">Вимк.</translation>
<translation id="5863847714970149516">Наступна сторінка може спробувати стягнути плату</translation>
<translation id="5866257070973731571">Додайте номер телефону</translation>
+<translation id="5866898949289125849">Ви переглядаєте сторінку Інструментів розробника</translation>
<translation id="5869405914158311789">Немає зв’язку із сайтом</translation>
<translation id="5869522115854928033">Збережені паролі</translation>
<translation id="5887400589839399685">Картку збережено</translation>
<translation id="5893752035575986141">Кредитні картки, які приймаються.</translation>
+<translation id="5895138241574237353">Перезапустити</translation>
<translation id="5901630391730855834">Жовтий</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (синхронізовано)</translation>
<translation id="5916664084637901428">Увімкнути</translation>
+<translation id="59174027418879706">Увімкнено</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Зберегти картку в обліковому записі Google?</translation>
<translation id="5922853866070715753">Майже готово</translation>
@@ -955,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Використовувати картки на всіх ваших пристроях?</translation>
<translation id="6059925163896151826">Пристрої USB</translation>
+<translation id="6060009363608157444">Недійсний режим DnsOverHttps.</translation>
<translation id="6080696365213338172">Ви отримали доступ до вмісту, використовуючи наданий адміністратором сертифікат. Адміністратор може перехоплювати дані, які ви надасте домену <ph name="DOMAIN" />.</translation>
<translation id="6094273045989040137">Додати примітку</translation>
<translation id="610911394827799129">Історія веб-перегляду може також зберігатися у вашому обліковому записі Google на сторінці <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1020,12 @@
<translation id="6404511346730675251">Редагувати закладку</translation>
<translation id="6406765186087300643">C0 (конверт)</translation>
<translation id="6410264514553301377">Введіть дату закінчення терміну дії та код CVC картки <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Ви надіслали одному з батьків запит на перегляд цього сайту</translation>
<translation id="6415778972515849510">Chromium допоможе захистити обліковий запис Google і змінити пароль.</translation>
-<translation id="6417515091412812850">Неможливо перевірити, чи цей сертифікат було відкликано.</translation>
<translation id="6431585503458005759">Не зберігати</translation>
<translation id="6433490469411711332">Змінити контактні дані</translation>
<translation id="6433595998831338502">Хост <ph name="HOST_NAME" /> відхилив запит на з’єднання.</translation>
<translation id="6434309073475700221">Скасувати</translation>
+<translation id="6435221585574090192">Діліться з адміністратором даними про події системи безпеки, про які повідомляє Захист від загроз Chrome Enterprise. Це можуть бути URL-адреси сторінок, назви й метадані файлів, імена користувачів пристрою та Chrome.</translation>
<translation id="6440503408713884761">Ігнорується</translation>
<translation id="6446163441502663861">Kahu (конверт)</translation>
<translation id="6446608382365791566">Додати більше інформації</translation>
@@ -1018,20 +1034,19 @@
<translation id="6465306955648956876">Керувати паролями…</translation>
<translation id="647261751007945333">Правила пристрою</translation>
<translation id="6476284679642588870">Керувати способами оплати</translation>
-<translation id="6477321094435799029">Chrome виявив на цій сторінці незвичний код і заблокував його, щоб захистити вашу особисту інформацію (наприклад, паролі, номери телефонів або кредитних карток).</translation>
<translation id="6489534406876378309">Почати завантаження даних про аварійне завершення роботи</translation>
<translation id="6499038740797743453">Скинути пароль?</translation>
<translation id="6507833130742554667">Кредитні та дебетові картки, які приймаються.</translation>
<translation id="650855688985305916">Так, зберігати</translation>
<translation id="6508722015517270189">Перезапустіть Chrome</translation>
<translation id="6517596291481585650">Застереження: це правило не об'єднано в список, як указано в правилі, оскільки це не список.</translation>
+<translation id="6518133107902771759">Підтвердити</translation>
<translation id="6521745193039995384">Неактивне</translation>
<translation id="6529602333819889595">&amp;Повторити видалення</translation>
<translation id="6534179046333460208">Пропозиції сервісу "Інтернет навколо нас"</translation>
<translation id="6545864417968258051">Пошук пристроїв Bluetooth</translation>
<translation id="6554795675067793129">Вашим обліковим записом керує <ph name="ENROLLMENT_DOMAIN" />.</translation>
<translation id="6556866813142980365">Повторити</translation>
-<translation id="6563469144985748109">Адміністратор ще не схвалив його</translation>
<translation id="6569060085658103619">Ви переглядаєте сторінку розширень</translation>
<translation id="6578796323535178455">C2 (конверт)</translation>
<translation id="6579990219486187401">Світло-рожевий</translation>
@@ -1049,11 +1064,13 @@
<translation id="6643016212128521049">Очистити</translation>
<translation id="6644283850729428850">Це правило більше не використовується.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Немає}=1{З 1 сайту (ви не вийдете з облікового запису Google)}one{З # сайту (ви не вийдете з облікового запису Google)}few{З # сайтів (ви не вийдете з облікового запису Google)}many{З # сайтів (ви не вийдете з облікового запису Google)}other{З # сайту (ви не вийдете з облікового запису Google)}}</translation>
+<translation id="6652101503459149953">Використовувати Windows Hello</translation>
<translation id="6657585470893396449">Пароль</translation>
<translation id="6670613747977017428">Повернутися до безпечного режиму.</translation>
<translation id="6671697161687535275">Видалити пропозицію автозаповнення форм із Chromium?</translation>
<translation id="6685834062052613830">Вийдіть з облікового запису та завершіть процедуру налаштування</translation>
<translation id="6689271823431384964">Chrome пропонує вам зберегти картки в обліковому записі Google, оскільки ви ввійшли в нього. Це можна змінити в налаштуваннях. Ім'я власника картки взято з вашого облікового запису.</translation>
+<translation id="6707256370811247129">Перевіряти вміст кешу та файлів, які ви завантажуєте або додаєте в Chrome.</translation>
<translation id="6710213216561001401">Попереднє</translation>
<translation id="6710594484020273272">&lt;Введіть пошуковий термін&gt;</translation>
<translation id="671076103358959139">Маркер реєстрації:</translation>
@@ -1061,10 +1078,10 @@
<translation id="6738516213925468394">Ваші дані було зашифровано за допомогою <ph name="BEGIN_LINK" />парольної фрази для синхронізації<ph name="END_LINK" /> від <ph name="TIME" />. Введіть її, щоб почати синхронізацію.</translation>
<translation id="674375294223700098">Помилка "Невідомий сертифікат сервера".</translation>
<translation id="6744009308914054259">Очікуючи на з’єднання, можете перейти в папку "Завантаження" й переглянути статті, доступні в режимі офлайн.</translation>
+<translation id="6747611005629681221">Застереження: деякі функції сторінки можуть не підтримуватися.</translation>
<translation id="6753269504797312559">Значення правила</translation>
<translation id="6757797048963528358">Ваш пристрій перейшов у режим сну.</translation>
<translation id="6768213884286397650">Hagaki (листівка)</translation>
-<translation id="6778737459546443941">Батьки ще не схвалили його</translation>
<translation id="67862343314499040">Фіолетовий</translation>
<translation id="6786747875388722282">Розширення</translation>
<translation id="6790428901817661496">Відтворити</translation>
@@ -1072,6 +1089,7 @@
<translation id="681021252041861472">Обов’язкове поле</translation>
<translation id="6810899417690483278">Ідентифікатор налаштування</translation>
<translation id="6825578344716086703">Ви спробували зв’язатися з доменом <ph name="DOMAIN" />, проте сервер надав сертифікат, підписаний із використанням слабкого алгоритму підпису (як-от SHA-1). Це означає, що облікові дані безпеки, надані сервером, можуть бути сфальсифікованими, а сервер – не тим, який вам потрібен (ви можете передавати свої дані зловмиснику).</translation>
+<translation id="6826370046007623921">Запобігання витокам даних</translation>
<translation id="6831043979455480757">Перекласти</translation>
<translation id="6839929833149231406">Область</translation>
<translation id="6852204201400771460">Перезапустити додаток?</translation>
@@ -1084,7 +1102,6 @@
<translation id="6891596781022320156">Правило не підтримується.</translation>
<translation id="6895330447102777224">Дані картки підтверджено</translation>
<translation id="6897140037006041989">Агент користувача</translation>
-<translation id="6903319715792422884">Допоможіть покращити Безпечний перегляд, надсилаючи в Google деяку <ph name="BEGIN_WHITEPAPER_LINK" />інформацію про систему та вміст сторінок<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Користувач:</translation>
<translation id="6934672428414710184">Це ім’я з вашого облікового запису Google</translation>
<translation id="6944692733090228304">Ви ввели пароль на сайті, яким не керує <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Щоб захистити свій обліковий запис, не використовуйте цей пароль для інших додатків і сайтів.</translation>
@@ -1129,6 +1146,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}one{<ph name="PAYMENT_METHOD_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}few{<ph name="PAYMENT_METHOD_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}many{<ph name="PAYMENT_METHOD_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}other{<ph name="PAYMENT_METHOD_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" />}}</translation>
<translation id="7153618581592392745">Лавандовий</translation>
<translation id="717330890047184534">Ідентифікатор GAIA:</translation>
+<translation id="7174545416324379297">Об'єднано</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}one{<ph name="SHIPPING_OPTION_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}few{<ph name="SHIPPING_OPTION_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}many{<ph name="SHIPPING_OPTION_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}other{<ph name="SHIPPING_OPTION_PREVIEW" /> і ще <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" />}}</translation>
<translation id="7177397715882417099">Сервер, на який ви переходите (<ph name="ORIGIN" />), попросив, щоб
до всіх його запитів застосовувалося правило безпеки. Однак замість
@@ -1166,6 +1184,7 @@
<translation id="7320336641823683070">Довідка щодо з’єднання</translation>
<translation id="733354035281974745">Заміна локального облікового запису на пристрої</translation>
<translation id="7334320624316649418">&amp;Повторити перевпорядкування</translation>
+<translation id="7337706099755338005">Недоступний на вашій платформі.</translation>
<translation id="733923710415886693">Сертифікат сервера не надав інформацію про перевірку.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Зв'язано:</translation>
@@ -1197,7 +1216,6 @@
<translation id="7440140511386898319">Перегляд у режимі офлайн</translation>
<translation id="7441627299479586546">Неправильна тема правила</translation>
<translation id="7442725080345379071">Світло-оранжевий</translation>
-<translation id="7444046173054089907">Цей сайт заблоковано</translation>
<translation id="7445762425076701745">Ідентифікацію сервера, з яким ви з'єднані, не можна повністю підтвердити. Ви з'єднані із сервером за допомогою імені, дійсного лише у вашій мережі, і зовнішній центр сертифікації не має способів підтвердити право власності на це ім'я. Хоча деякі центри сертифікації, попри все, видають сертифікати на такі імена, неможливо цілком упевнитися, що ви з'єднані з безпечним сайтом, а не зі зловмисником.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />дізнатися більше<ph name="END_LINK" /> про цю проблему.</translation>
<translation id="7455133967321480974">Використовувати глобальне налаштування за умовчанням (Блокувати)</translation>
@@ -1219,9 +1237,9 @@
<translation id="7538364083937897561">A2 (конверт)</translation>
<translation id="7542403920425041731">Щойно ви підтвердите, цей сайт отримає доступ до даних вашої картки.</translation>
<translation id="7542995811387359312">Автоматичне заповнення кредитної картки вимкнено, оскільки ця форма не використовує безпечне з'єднання.</translation>
-<translation id="7543525346216957623">Попросіть когось із батьків</translation>
<translation id="7548892272833184391">Як виправити помилки з’єднання</translation>
<translation id="7549584377607005141">Для належного відображення цій веб-сторінці потрібні введені вами раніше дані. Можна ще раз надіслати дані, однак зробивши це, ви повторите всі дії, які ця сторінка виконувала раніше.</translation>
+<translation id="7550637293666041147">Імена користувачів для пристрою та Chrome</translation>
<translation id="7552846755917812628">Виконайте вказівки нижче.</translation>
<translation id="7554791636758816595">Нова вкладка</translation>
<translation id="7564049878696755256">Ви можете втратити доступ до облікового запису, який вам надає <ph name="ORG_NAME" />, або хтось може викрасти вашу особисту інформацію. Chrome радить змінити пароль.</translation>
@@ -1236,6 +1254,7 @@
<translation id="7610193165460212391">Значення за межами діапазону <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Діє до: <ph name="EXPIRATION_MONTH" />.<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Ви вже зашифрували дані, використовуючи іншу версію пароля облікового запису Google. Введіть його нижче.</translation>
+<translation id="7625784245512586808">Захист від загроз Chrome Enterprise</translation>
<translation id="7633909222644580952">Дані про ефективність і звіти про збої</translation>
<translation id="7637571805876720304">Видалити дані кредитної картки з Chromium?</translation>
<translation id="7638605456503525968">Послідовні порти</translation>
@@ -1248,7 +1267,6 @@
<translation id="7668654391829183341">Невідомий пристрій</translation>
<translation id="7669271284792375604">Зловмисники на цьому сайті можуть обманом змусити вас установити програми, які погіршують роботу в Інтернеті (наприклад, змінюють вашу домашню сторінку або показують додаткову рекламу на сайтах, які ви відвідуєте).</translation>
<translation id="7676643023259824263">Пошук тексту з буфера обміну: <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Платформа та хмара</translation>
<translation id="7681101578153515023">Змінити пошукову систему</translation>
<translation id="7682287625158474539">Адреса для надсилання</translation>
<translation id="7687186412095877299">Заповнює платіжні форми, використовуючи збережені способи оплати</translation>
@@ -1263,7 +1281,6 @@
<translation id="7723047071702270851">Відредагуйте картку</translation>
<translation id="774634243536837715">Заблоковано небезпечний вміст.</translation>
<translation id="7752995774971033316">Некерований клієнт</translation>
-<translation id="7755287808199759310">Хтось із батьків може розблокувати його</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Можливо, брандмауер або антивірусна програма заблокували з’єднання.</translation>
<translation id="7759163816903619567">Видимий домен:</translation>
@@ -1307,7 +1324,6 @@
<translation id="8004582292198964060">Переглядач</translation>
<translation id="8009225694047762179">Керувати паролями</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Цю картку та її платіжну адресу буде збережено. Ви зможете скористатися нею, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}one{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}few{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}many{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}other{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Не вдалося зв’язатися з вашими батьками. Повторіть спробу.</translation>
<translation id="8025119109950072390">Зловмисники на цьому сайті можуть обманом змусити вас виконати небезпечну дію, як-от установити програмне забезпечення або повідомити особисту інформацію (наприклад, паролі, номери телефонів або кредитних карток).</translation>
<translation id="8034522405403831421">Мова цієї сторінки: <ph name="SOURCE_LANGUAGE" />. Перекласти її такою мовою: <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Перо</translation>
@@ -1318,6 +1334,7 @@
<translation id="8041940743680923270">Використовувати глобальне налаштування за умовчанням (Запитувати)</translation>
<translation id="8042918947222776840">Вибрати спосіб отримання</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> налаштовано неправильно. Якщо видалити програмне забезпечення <ph name="SOFTWARE_NAME" />, проблема зазвичай зникає. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Надалі вам не потрібно буде вводити код безпеки картки</translation>
<translation id="8066955247577885446">Сталася помилка.</translation>
<translation id="8074253406171541171">10x13 (конверт)</translation>
<translation id="8078141288243656252">Коли документ обернено, створення приміток недоступне</translation>
@@ -1348,6 +1365,7 @@
<translation id="8211406090763984747">З’єднання безпечне</translation>
<translation id="8218327578424803826">Указане місцезнаходження:</translation>
<translation id="8220146938470311105">C7/C6 (конверт)</translation>
+<translation id="8220639454292072926">Звіти для підприємств</translation>
<translation id="8225771182978767009">Користувач, який налаштував комп’ютер, заблокував цей сайт.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Відкрити сторінку в новій анонімній вкладці</translation>
@@ -1402,24 +1420,24 @@
<translation id="8508648098325802031">Значок пошуку</translation>
<translation id="8522552481199248698">Chrome допоможе захистити обліковий запис Google і змінити пароль.</translation>
<translation id="8543181531796978784">Ви можете <ph name="BEGIN_ERROR_LINK" />повідомити про проблему з пошуком<ph name="END_ERROR_LINK" /> або <ph name="BEGIN_LINK" />перейти на цей незахищений сайт<ph name="END_LINK" /> (якщо розумієте, наскільки це небезпечно).</translation>
-<translation id="8543556556237226809">Маєте запитання? Зв’яжіться з особою, яка контролює ваш профіль.</translation>
<translation id="8553075262323480129">Помилка перекладу. Неможливо визначити мову сторінки.</translation>
<translation id="8557066899867184262">Код CVC розташований на зворотному боці картки.</translation>
<translation id="8559762987265718583">Не вдається встановити конфіденційне з’єднання з <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />, оскільки на пристрої встановлено неправильні дату й час (<ph name="DATE_AND_TIME" />).</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> підозрілий сайт</translation>
<translation id="8564985650692024650">Chromium радить скинути пароль <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />, якщо ви застосовували його на інших сайтах.</translation>
<translation id="8571890674111243710">Виконується переклад сторінки такою мовою: <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Додати тел.номер
</translation>
-<translation id="859285277496340001">Сертифікат не вказує на механізм перевірки його відкликання.</translation>
<translation id="860043288473659153">Ім’я та прізвище власника картки</translation>
<translation id="861775596732816396">Розмір 4</translation>
-<translation id="8620436878122366504">Батьки ще не схвалили його</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Зберегти цю картку на пристрої</translation>
<translation id="8626112503828625890">Зберігати платіжні дані в обліковому записі Google?</translation>
+<translation id="8647750283161643317">Скинути все до налаштувань за умовчанням</translation>
<translation id="8663226718884576429">Підсумок замовлення, <ph name="TOTAL_LABEL" />, докладніше</translation>
<translation id="8680536109547170164">"<ph name="QUERY" />", відповідь: "<ph name="ANSWER" />"</translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Доступно</translation>
<translation id="8703575177326907206">Ваше з’єднання з <ph name="DOMAIN" /> не зашифровано.</translation>
<translation id="8718314106902482036">Оплату не завершено</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, пропозиція пошуку</translation>
@@ -1430,6 +1448,7 @@
<translation id="8738058698779197622">Щоб установити безпечне з’єднання, потрібно правильно вказати час, оскільки сертифікати, які веб-сайти використовують для самоідентифікації дійсні лише протягом певного періоду часу. Час на вашому пристрої неправильний, тому Chromium не може перевірити сертифікати.</translation>
<translation id="8740359287975076522">&lt;abbr id="dnsDefinition"&gt;Адресу DNS&lt;/abbr&gt; хосту <ph name="HOST_NAME" /> не знайдено. Діагностика проблеми.</translation>
<translation id="874846938927089722">Кредитні та передплачені картки, які приймаються до оплати</translation>
+<translation id="874918643257405732">Зробити закладку для цієї вкладки</translation>
<translation id="8759274551635299824">Термін дії цієї картки минув</translation>
<translation id="8761567432415473239">Функція безпечного перегляду від Google нещодавно <ph name="BEGIN_LINK" />виявила шкідливі програми<ph name="END_LINK" /> на сайті <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Пристрій USB</translation>
@@ -1459,6 +1478,7 @@
<translation id="8938939909778640821">Прийнятні кредитні та передплачені картки</translation>
<translation id="8943282376843390568">Лаймовий</translation>
<translation id="8957210676456822347">Авторизація приєднаного порталу</translation>
+<translation id="8962950042226115166">Підозрілий сайт</translation>
<translation id="8968766641738584599">Зберегти картку</translation>
<translation id="8971063699422889582">Термін дії сертифіката сервера завершився.</translation>
<translation id="8975012916872825179">Номери телефонів, електронні адреси, адреси доставки тощо</translation>
@@ -1481,24 +1501,24 @@
<translation id="9035022520814077154">Помилка системи безпеки</translation>
<translation id="9038649477754266430">Користуйтеся службою передбачення, щоб сторінки завантажувалися швидше</translation>
<translation id="9039213469156557790">Окрім цього, сторінка містить незахищені ресурси. Інші особи можуть переглядати їх під час передавання даних, а зловмисники можуть змінювати роботу сторінки.</translation>
+<translation id="9044359186343685026">Використовувати Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> – <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Ви пробували зв’язатися з доменом <ph name="DOMAIN" />, але сервер надав недійсний сертифікат.</translation>
<translation id="9050666287014529139">Парольна фраза</translation>
<translation id="9065203028668620118">Редагувати</translation>
<translation id="9065745800631924235">Пошук в історії за запитом "<ph name="TEXT" />"</translation>
<translation id="9069693763241529744">Заблоковано розширенням</translation>
-<translation id="9076283476770535406">На ньому може бути вміст для дорослих</translation>
<translation id="9076630408993835509">Цим веб-переглядачем не керує адміністратор компанії чи іншої організації. Діями на цьому пристрої можна керувати за межами Chrome. <ph name="BEGIN_LINK" />Докладніше<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Потрібно більше інформації</translation>
<translation id="9080712759204168376">Підсумок замовлення</translation>
<translation id="9089260154716455634">Правило неробочого часу:</translation>
<translation id="9095388113577226029">Інші мови…</translation>
+<translation id="9098981495403789647">Ваш адміністратор увімкнув Захист від загроз Chrome Enterprise у веб-переглядачі. Захист від загроз має доступ до деяких ваших даних.</translation>
<translation id="9103872766612412690">Веб-сайт <ph name="SITE" /> зазвичай використовує шифрування для захисту вашої інформації. Під час цієї спроби Chromium під’єднатися до сторінки <ph name="SITE" /> з неї отримано незвичні й неправильні облікові дані. Це може статися, коли зловмисник намагається видавати себе за веб-сайт <ph name="SITE" /> або з’єднання перервано екраном входу Wi-Fi. Ваша інформація залишається захищеною, оскільки Chromium припинив з’єднання до того, як почався обмін будь-якими даними.</translation>
<translation id="9106062320799175032">Додайте платіжну адресу</translation>
<translation id="9114524666733003316">Підтверджуються дані картки…</translation>
<translation id="9128870381267983090">З'єднатися з мережею</translation>
<translation id="9137013805542155359">Показати оригінал</translation>
-<translation id="9137248913990643158">Перш ніж користуватися додатком, увійдіть в обліковий запис Chrome.</translation>
<translation id="9141013498910525015">Керувати адресами</translation>
<translation id="9148088599418889305">Вибрати спосіб доставки</translation>
<translation id="9148507642005240123">&amp;Відмінити редагування</translation>
diff --git a/chromium/components/strings/components_strings_vi.xtb b/chromium/components/strings/components_strings_vi.xtb
index a62af1ad57d..a1170ea6ed1 100644
--- a/chromium/components/strings/components_strings_vi.xtb
+++ b/chromium/components/strings/components_strings_vi.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">Thêm tên trên thẻ</translation>
<translation id="1089439967362294234">Thay đổi mật khẩu</translation>
+<translation id="1096545575934602868">Trường này không được chứa nhiều hơn <ph name="MAX_ITEMS_LIMIT" /> mục. Mọi mục thừa sẽ bị hủy.</translation>
<translation id="109743633954054152">Quản lý mật khẩu trong mục cài đặt của Chrome</translation>
<translation id="1103523840287552314">Luôn dịch <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">Nếu được chọn, Chrome sẽ lưu trữ bản sao thẻ của bạn trên thiết bị này để điền biểu mẫu nhanh hơn.</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">Truy cập <ph name="BEGIN_LINK" />bản sao được lưu trong bộ nhớ đệm<ph name="END_LINK" /> của <ph name="URL" /></translation>
<translation id="1156303062776767266">Bạn đang xem tệp trên máy hoặc tệp được chia sẻ</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> đã bất ngờ đóng kết nối.</translation>
+<translation id="115926840831309955">Hãy kiểm tra CVC của bạn rồi thử lại hoặc cập nhật ngày hết hạn</translation>
<translation id="1161325031994447685">Kết nối lại với Wi-Fi</translation>
<translation id="1165039591588034296">Lỗi</translation>
<translation id="1175364870820465910">&amp;In...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">"Phần mềm trên máy tính của bạn đang ngăn không cho Chrome kết nối an toàn với web" (chỉ trên máy tính Windows)</translation>
<translation id="1294154142200295408">Các biến thể của dòng lệnh</translation>
<translation id="129553762522093515">Các tab đã đóng gần đây</translation>
+<translation id="1298536327547837046">Quét tìm phần mềm độc hại</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Thử xóa các cookie của bạn<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">Tính năng sắp ngừng hoạt động</translation>
<translation id="1320233736580025032">Prc1 (Phong bì)</translation>
<translation id="132301787627749051">Tìm kiếm hình ảnh trong khay nhớ tạm</translation>
<translation id="1323433172918577554">Xem thêm</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google Trang tính</translation>
<translation id="1527263332363067270">Đang chờ kết nối…</translation>
<translation id="1529521330346880926">10x15 (Phong bì)</translation>
+<translation id="1530707389502320859">Có vẻ như trang web bạn vừa cố truy cập là giả mạo. Kẻ tấn công đôi khi bắt chước các trang web bằng cách thực hiện các thay đổi nhỏ, khó phát hiện đối với URL.</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">Trang này cho biết</translation>
<translation id="153384715582417236">Hiện chưa có nội dung</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">OS</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">Tài liệu quá lớn nên không thể chú thích được</translation>
-<translation id="1721312023322545264">Bạn cần được <ph name="NAME" /> cấp quyền để truy cập vào trang web này</translation>
<translation id="1721424275792716183">Trường * là bắt buộc</translation>
<translation id="1727741090716970331">Thêm số thẻ hợp lệ</translation>
<translation id="1728677426644403582">Bạn đang xem nguồn của trang web</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">Các trang web bạn đã truy cập và thời lượng truy cập các trang web đó</translation>
<translation id="1826516787628120939">Đang kiểm tra</translation>
<translation id="1834321415901700177">Trang web này có chứa các chương trình độc hại</translation>
+<translation id="1838374766361614909">Xóa tìm kiếm</translation>
<translation id="1839551713262164453">Không xác thực được các giá trị của chính sách do xảy ra lỗi</translation>
<translation id="1842969606798536927">Thanh toán</translation>
<translation id="1871208020102129563">Proxy được đặt để sử dụng máy chủ proxy cố định chứ không phải URL tập lệnh .pac.</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">Thu gọn danh sách</translation>
<translation id="1898423065542865115">Lọc</translation>
<translation id="1914326953223720820">Dịch vụ giải nén</translation>
+<translation id="1915697529809968049">Sử dụng Touch ID thay cho CVC?</translation>
<translation id="1916770123977586577">Để áp dụng các cài đặt đã cập nhật cho trang web này, hãy tải lại trang</translation>
<translation id="1919345977826869612">Quảng cáo</translation>
<translation id="1919367280705858090">Nhận trợ giúp về thông báo lỗi cụ thể</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436">Dấu trang của <ph name="DOMAIN" /></translation>
<translation id="1973335181906896915">Lỗi nối tiếp hóa</translation>
<translation id="1974060860693918893">Nâng cao</translation>
+<translation id="1974883374937189061">Giúp tăng cường khả năng bảo mật của Chrome bằng cách gửi <ph name="BEGIN_WHITEPAPER_LINK" />URL của một số trang mà bạn truy cập, thông tin hệ thống giới hạn và một số nội dung trang<ph name="END_WHITEPAPER_LINK" /> cho Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">Phiên bản chương trình cơ sở</translation>
<translation id="1981206234434200693">Xóa dữ liệu lịch sử duyệt web của Chrome</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{và 1 ứng dụng khác}other{và # ứng dụng khác}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">Nhập năm hết hạn hợp lệ</translation>
<translation id="2212735316055980242">Không tìm thấy chính sách</translation>
<translation id="2213606439339815911">Đang tìm nạp các mục nhập...</translation>
+<translation id="2215727959747642672">Chỉnh sửa tệp</translation>
<translation id="2218879909401188352">Những kẻ tấn công hiện ở trên <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> có thể cài đặt ứng dụng nguy hiểm làm hỏng thiết bị của bạn, thêm các khoản phí ẩn vào hóa đơn di động hoặc lấy cắp thông tin cá nhân của bạn. <ph name="BEGIN_LEARN_MORE_LINK" />Tìm hiểu thêm<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Không có Internet</translation>
<translation id="2230458221926704099">Sửa kết nối bằng <ph name="BEGIN_LINK" />ứng dụng chẩn đoán<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Gửi bây giờ</translation>
+<translation id="2248949050832152960">Sử dụng WebAuthn</translation>
<translation id="225207911366869382">Giá trị này không được dùng cho chính sách này nữa.</translation>
<translation id="2257315177824333709">Rất tiếc, không thể lưu thẻ của bạn ngay bây giờ</translation>
<translation id="2262243747453050782">Lỗi HTTP</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">URL tìm kiếm hợp lệ.</translation>
<translation id="2482878487686419369">Thông báo</translation>
<translation id="248348093745724435">Chính sách về máy</translation>
-<translation id="2485387744899240041">Tên người dùng dành cho thiết bị và trình duyệt của bạn</translation>
<translation id="2491120439723279231">Chứng chỉ của máy chủ có lỗi.</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">Trình phân tích cú pháp JSON</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">Quay lại</translation>
<translation id="2503184589641749290">Thẻ ghi nợ và thẻ trả trước được chấp nhận</translation>
<translation id="2505268675989099013">Bảo vệ tài khoản</translation>
+<translation id="2515335152965840738">BỎ QUA</translation>
<translation id="2515629240566999685">Kiểm tra tín hiệu trong khu vực của bạn</translation>
<translation id="2523886232349826891">Chỉ lưu trên thiết bị này</translation>
<translation id="2524461107774643265">Thêm thông tin khác</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">Gửi</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{Không có}=1{1 mật khẩu (cho <ph name="DOMAIN_LIST" />)}=2{2 mật khẩu (cho <ph name="DOMAIN_LIST" />)}other{# mật khẩu (cho <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">Đóng các tab hoặc ứng dụng khác</translation>
-<translation id="267371737713284912">nhấn <ph name="MODIFIER_KEY_DESCRIPTION" /> để hoàn tác</translation>
<translation id="2674170444375937751">Bạn có chắc chắn muốn xóa những trang này khỏi lịch sử duyệt web của mình không?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">Rời khỏi</translation>
@@ -342,12 +350,14 @@
<translation id="2704283930420550640">Giá trị không khớp với định dạng.</translation>
<translation id="2705137772291741111">Không thể đọc được bản sao đã lưu (đã lưu vào bộ nhớ đệm) của trang web này.</translation>
<translation id="2709516037105925701">Tự động điền</translation>
-<translation id="2712173769900027643">Xin phép</translation>
<translation id="2713444072780614174">Trắng</translation>
<translation id="2720342946869265578">Lân cận</translation>
<translation id="2721148159707890343">Yêu cầu đã thành công</translation>
<translation id="2728127805433021124">Chứng chỉ của máy chủ đã được ký bằng thuật toán chữ ký yếu.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />Chạy Chẩn đoán kết nối<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">Khi bật các tính năng này, dữ liệu trên trình duyệt có thể bị mất hoặc
+ tính bảo mật/quyền riêng tư của bạn có thể bị xâm phạm. Các tính năng được bật sẽ áp dụng cho tất cả
+ người dùng trình duyệt này.</translation>
<translation id="2735043616039983645">Chính sách này hiện có nhiều nguồn và các giá trị nguồn xung đột với nhau!</translation>
<translation id="2738330467931008676">Chọn địa chỉ nhận hàng</translation>
<translation id="2740531572673183784">Ok</translation>
@@ -358,16 +368,15 @@
<translation id="2784949926578158345">Kết nối đã được đặt lại.</translation>
<translation id="2788784517760473862">Thẻ tín dụng được chấp nhận</translation>
<translation id="2792012897584536778">Các quản trị viên của thiết bị này đã thiết lập các chứng chỉ bảo mật có thể cho phép họ xem nội dung của những trang web bạn truy cập.</translation>
-<translation id="2794233252405721443">Trang web đã bị chặn</translation>
<translation id="2799020568854403057">Trang web bạn sắp truy cập chứa ứng dụng có hại</translation>
<translation id="2799223571221894425">Chạy lại</translation>
<translation id="2803306138276472711">Duyệt web an toàn của Google gần đây <ph name="BEGIN_LINK" />đã phát hiện phần mềm độc hại<ph name="END_LINK" /> trên <ph name="SITE" />. Các trang web thường được coi là an toàn đôi khi vẫn bị nhiễm phần mềm độc hại.</translation>
+<translation id="2815364696811431560">RỜI KHỎI TRANG WEB</translation>
<translation id="2824775600643448204">Thanh địa chỉ và tìm kiếm</translation>
<translation id="2826760142808435982">Kết nối được mã hóa và xác thực bằng <ph name="CIPHER" /> đồng thời sử dụng <ph name="KX" /> làm cơ chế trao đổi chính.</translation>
<translation id="2835170189407361413">Xóa biểu mẫu</translation>
<translation id="2847118875340931228">Mở cửa sổ ẩn danh</translation>
<translation id="2850739647070081192">Invite (Phong bì)</translation>
-<translation id="2851634818064021665">Bạn cần quyền để truy cập trang web này</translation>
<translation id="2856444702002559011">Những kẻ tấn công có thể đang cố gắng đánh cắp thông tin của bạn từ <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (ví dụ: mật khẩu, thư hoặc thẻ tín dụng). <ph name="BEGIN_LEARN_MORE_LINK" />Tìm hiểu thêm<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">Lưu thẻ?</translation>
@@ -392,6 +401,7 @@
<translation id="2985306909656435243">Nếu được bật, Chromium sẽ lưu trữ bản sao thẻ của bạn trên thiết bị này để điền vào biểu mẫu nhanh hơn.</translation>
<translation id="2985398929374701810">Nhập địa chỉ hợp lệ</translation>
<translation id="2986368408720340940">Phương thức nhận hàng này không có sẵn. Hãy thử một phương thức khác.</translation>
+<translation id="2987034854559945715">Không có tính năng nào phù hợp</translation>
<translation id="2991174974383378012">Chia sẻ với trang web</translation>
<translation id="2991571918955627853">Bạn không thể truy cập vào <ph name="SITE" /> ngay bây giờ vì trang web sử dụng HSTS. Lỗi mạng và các cuộc tấn công mạng thường chỉ là tạm thời nên trang này có thể sẽ hoạt động lại sau.</translation>
<translation id="3005723025932146533">Hiển thị bản sao đã lưu</translation>
@@ -402,6 +412,7 @@
<translation id="3024663005179499861">Loại chính sách sai</translation>
<translation id="3037605927509011580">Ôi, hỏng! </translation>
<translation id="3041612393474885105">Thông tin Chứng chỉ</translation>
+<translation id="3057676462092457419">Chưa hỗ trợ chế độ DnsOverHttps <ph name="SECURE_DNS_MODE_SECURE" />. Đã đặt chế độ này thành <ph name="SECURE_DNS_MODE_OFF" />.</translation>
<translation id="3060227939791841287">C9 (Phong bì)</translation>
<translation id="3061707000357573562">Dịch vụ vá lỗi</translation>
<translation id="3064966200440839136">Rời khỏi chế độ ẩn danh để thanh toán qua một ứng dụng bên ngoài. Tiếp tục?</translation>
@@ -427,6 +438,7 @@
<translation id="3195213714973468956"><ph name="PRINTER_NAME" /> trên <ph name="SERVER_NAME" /></translation>
<translation id="320323717674993345">Hủy thanh toán</translation>
<translation id="3207960819495026254">Đã đánh dấu trang</translation>
+<translation id="3209034400446768650">Trang này có thể tính phí</translation>
<translation id="3225919329040284222">Máy chủ đưa ra chứng chỉ không khớp với kỳ vọng được tích hợp sẵn. Các kỳ vọng này có trong một số trang web nhất định, có tính bảo mật cao với mục đích bảo vệ bạn.</translation>
<translation id="3226128629678568754">Nhấn nút tải lại để gửi lại các dữ liệu cần thiết để tải trang.</translation>
<translation id="3227137524299004712">Micrô</translation>
@@ -434,7 +446,6 @@
<translation id="3229041911291329567">Thông tin phiên bản về thiết bị và trình duyệt của bạn</translation>
<translation id="323107829343500871">Nhập CVC cho <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Luôn luôn phát hiện nội dung quan trọng trên trang web này</translation>
-<translation id="3254409185687681395">Đánh dấu trang này</translation>
<translation id="3270847123878663523">&amp;Hoàn tác sắp xếp lại</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">Thêm tên trên thẻ</translation>
@@ -444,7 +455,6 @@
<translation id="3320021301628644560">Thêm địa chỉ thanh toán</translation>
<translation id="3324983252691184275">Đỏ thẫm</translation>
<translation id="3338095232262050444">Bảo mật</translation>
-<translation id="3345135638360864351">Không thể gửi yêu cầu truy cập trang web này của bạn tới <ph name="NAME" />. Vui lòng thử lại.</translation>
<translation id="3355823806454867987">Thay đổi cài đặt proxy...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />sẽ không lưu<ph name="END_EMPHASIS" /> thông tin sau đây:
<ph name="BEGIN_LIST" />
@@ -478,18 +488,15 @@
<translation id="3462200631372590220">Ẩn chi tiết</translation>
<translation id="3467763166455606212">Yêu cầu tên chủ thẻ</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" /> hiện đang mở, nhấn phím Tab rồi nhấn phím Enter để chuyển sang tab đang mở</translation>
-<translation id="3479539252931486093">Trang web này có như bạn mong đợi không? Hãy <ph name="BEGIN_LINK" />cho chúng tôi biết<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">Không phải bây giờ</translation>
<translation id="3484560055331845446">Bạn có thể mất quyền truy cập vào Tài khoản Google của mình. Chrome khuyên bạn nên đổi mật khẩu ngay bây giờ. Bạn sẽ được yêu cầu đăng nhập.</translation>
<translation id="3495081129428749620">Tìm trong trang
<ph name="PAGE_TITLE" /></translation>
-<translation id="3498215018399854026">Chúng tôi không thể liên lạc với cha mẹ của bạn vào thời điểm này. Vui lòng thử lại.</translation>
<translation id="3512163584740124171">Chính sách này bị bỏ qua vì một chính sách khác thuộc cùng nhóm chính sách có mức ưu tiên cao hơn.</translation>
<translation id="3528171143076753409">Chứng chỉ của máy chủ không đáng tin cậy.</translation>
<translation id="3528485271872257980">Nâu đậm</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{Ít nhất 1 mục trên các thiết bị đã đồng bộ hóa}=1{1 mục (và nhiều mục khác trên các thiết bị đã đồng bộ hóa)}other{# mục (và nhiều mục khác trên các thiết bị đã đồng bộ hóa)}}</translation>
<translation id="3539171420378717834">Giữ bản sao thẻ này trên thiết bị này</translation>
-<translation id="3556433843310711081">Người quản lý của bạn có thể bỏ chặn trang web cho bạn</translation>
<translation id="3566021033012934673">Kết nối của bạn không phải là kết nối riêng tư</translation>
<translation id="3574305903863751447"><ph name="CITY" />, <ph name="STATE" /> <ph name="COUNTRY" /></translation>
<translation id="3576616784287504635">Một trang được nhúng tại <ph name="SITE" /> cho biết</translation>
@@ -517,6 +524,7 @@
<translation id="3678529606614285348">Mở trang trong cửa sổ Ẩn danh mới (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">Báo cáo sự cố được ghi lại vào <ph name="CRASH_TIME" />, được tải lên vào <ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">Thông tin chứng chỉ</translation>
+<translation id="3701427423622901115">Đã xác nhận thao tác đặt lại.</translation>
<translation id="3704162925118123524">Mạng mà bạn đang sử dụng có thể yêu cầu bạn phải truy cập trang đăng nhập của mạng đó.</translation>
<translation id="3704609568417268905"><ph name="TIME" /> <ph name="BOOKMARKED" /> <ph name="TITLE" /> <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">Đang tải...</translation>
@@ -533,6 +541,7 @@
<translation id="3748148204939282805">Những kẻ tấn công trên <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> có thể đánh lừa bạn làm việc gì đó nguy hiểm như cài đặt phần mềm hoặc tiết lộ thông tin cá nhân (ví dụ: mật khẩu, số điện thoại hoặc thẻ tín dụng). <ph name="BEGIN_LEARN_MORE_LINK" />Tìm hiểu thêm<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Không thể dịch do lỗi máy chủ.</translation>
<translation id="3759461132968374835">Bạn không nhận được báo cáo sự cố nào gần đây. Sự cố xảy ra khi báo cáo sự cố đã bị tắt sẽ không xuất hiện ở đây.</translation>
+<translation id="3760561303380396507">Sử dụng Windows Hello thay cho CVC?</translation>
<translation id="3761718714832595332">Ẩn trạng thái</translation>
<translation id="3765032636089507299">Trang Duyệt web an toàn đang được xây dựng.</translation>
<translation id="3778403066972421603">Bạn có muốn lưu thẻ này vào Tài khoản Google của bạn và trên thiết bị này không?</translation>
@@ -542,6 +551,7 @@
<translation id="3789155188480882154">Kích thước 16</translation>
<translation id="3797522431967816232">Prc3 (Phong bì)</translation>
<translation id="3807873520724684969">Đã chặn nội dung độc hại.</translation>
+<translation id="3808375843007691220">Cảnh báo: Sắp có các tính năng thử nghiệm!</translation>
<translation id="3810973564298564668">Quản lý</translation>
<translation id="382518646247711829">Nếu bạn sử dụng máy chủ proxy...</translation>
<translation id="3828924085048779000">Không cho phép cụm mật khẩu trống.</translation>
@@ -550,11 +560,11 @@
<translation id="3858027520442213535">Cập nhật ngày và giờ</translation>
<translation id="3884278016824448484">Số nhận dạng thiết bị xung đột</translation>
<translation id="3885155851504623709">Giáo xứ</translation>
-<translation id="3886446263141354045">Yêu cầu truy cập trang web này của bạn đã được gửi tới <ph name="NAME" /></translation>
<translation id="3890664840433101773">Thêm email</translation>
<translation id="3901925938762663762">Thẻ đã hết hạn</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">Sử dụng WebAuthn thay cho CVC?</translation>
<translation id="3946209740501886391">Luôn hỏi trên trang web này</translation>
<translation id="3949571496842715403">Máy chủ này không thể chứng minh được đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ không chỉ định Tên thay thế đối tượng. Điều này có thể do cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
<translation id="3949601375789751990">Lịch sử duyệt web của bạn xuất hiện ở đây</translation>
@@ -565,11 +575,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{Không có}=1{Của 1 trang web }other{Của # trang web }}</translation>
<translation id="397105322502079400">Đang tính...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> bị chặn</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> đã bật tính năng Bảo vệ khỏi mối đe dọa của Chrome Enterprise trên trình duyệt. Tính năng Bảo vệ khỏi mối đe dọa của Chrome Enterprise có quyền truy cập vào một số dữ liệu của bạn.</translation>
<translation id="3987940399970879459">Dưới 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{1 trang web lân cận}other{# trang web lân cận}}</translation>
<translation id="4030383055268325496">&amp;Hoàn tác thêm</translation>
<translation id="4032320456957708163"><ph name="ENROLLMENT_DOMAIN" /> quản lý trình duyệt của bạn</translation>
-<translation id="4034375457890803692">Đường dẫn liên kết bạn mở dẫn đến một trang web mà bạn không thường xuyên truy cập. Có thể trang web này đang cố gây nhầm lẫn cho bạn.</translation>
<translation id="4058922952496707368">Khóa "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Phong bì)</translation>
<translation id="4067947977115446013">Thêm địa chỉ hợp lệ</translation>
@@ -582,6 +592,7 @@
<translation id="4103249731201008433">Số sê-ri thiết bị không hợp lệ</translation>
<translation id="410351446219883937">Tự động phát</translation>
<translation id="4103763322291513355">Truy cập &lt;strong&gt;chrome://policy&lt;/strong&gt; để xem danh sách các URL bị chặn quyền truy cập và các chính sách khác bị quản trị viên hệ thống buộc phải thực thi.</translation>
+<translation id="4108231218301530806">Dùng vân tay để xác minh thẻ này vào lần tới.</translation>
<translation id="4110652170750985508">Xem xét thanh toán của bạn</translation>
<translation id="4112140312785995938">Tua lùi</translation>
<translation id="4116663294526079822">Luôn cho phép trên trang web này</translation>
@@ -596,6 +607,7 @@
<translation id="4171400957073367226">Chữ ký xác minh không hợp lệ</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{<ph name="ITEM_COUNT" /> mục khác}other{<ph name="ITEM_COUNT" /> mục khác}}</translation>
+<translation id="4176463684765177261">Đã tắt</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">Để thanh toán nhanh hơn vào lần tới, hãy thêm địa chỉ thanh toán và thông tin thẻ vào Tài khoản Google của bạn.</translation>
<translation id="4196861286325780578">&amp;Làm lại di chuyển</translation>
@@ -632,6 +644,7 @@
<translation id="4277028893293644418">Đặt lại mật khẩu</translation>
<translation id="4279811152705618813"><ph name="DEVICE_TYPE" /> của bạn do <ph name="ENROLLMENT_DOMAIN" /> quản lý</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Đã lưu thẻ này vào Tài khoản Google của bạn}other{Đã lưu các thẻ này vào Tài khoản Google của bạn}}</translation>
+<translation id="428847186335018806">Quét các tệp mà bạn tải lên hoặc tải xuống trên Chrome.</translation>
<translation id="42981349822642051">Mở rộng</translation>
<translation id="4302965934281694568">Chou3 (Phong bì)</translation>
<translation id="4305817255990598646">Chuyển</translation>
@@ -661,7 +674,6 @@
<translation id="4435702339979719576">Bưu thiếp)</translation>
<translation id="443673843213245140">Đã tắt sử dụng proxy nhưng cấu hình proxy rõ ràng được chỉ định.</translation>
<translation id="445100540951337728">Thẻ ghi nợ được chấp nhận</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" /> hành vi đáng ngờ</translation>
<translation id="4466881336512663640">Các thay đổi đối với biểu mẫu sẽ bị mất. Bạn có chắc chắn muốn tiếp tục không?</translation>
<translation id="4477350412780666475">Bản nhạc tiếp theo</translation>
<translation id="4482953324121162758">Trang web này sẽ không được dịch.</translation>
@@ -688,6 +700,7 @@
<translation id="4594403342090139922">&amp;Hoàn tác xóa</translation>
<translation id="4597348597567598915">Kích thước 8</translation>
<translation id="4600854749408232102">C6/C5 (Phong bì)</translation>
+<translation id="464342062220857295">Tìm kiếm tính năng</translation>
<translation id="4646534391647090355">Chuyển đến đó ngay</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">Máy chủ này không chứng minh được rằng đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ này có lỗi. Điều này có thể do định cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
@@ -696,7 +709,6 @@
<translation id="4691835149146451662">Architecture-A (Phong bì)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">Kết nối của bạn bị gián đoạn</translation>
-<translation id="471880041731876836">Bạn không có quyền để truy cập trang web này</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Chạy Chẩn đoán mạng của Windows<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">Tải lại chính sách</translation>
<translation id="4728558894243024398">Nền tảng</translation>
@@ -724,7 +736,6 @@
<translation id="4816492930507672669">Vừa với trang</translation>
<translation id="4850886885716139402">Xem</translation>
<translation id="4854362297993841467">Phương thức phân phối này không có sẵn. Hãy thử một phương thức khác.</translation>
-<translation id="4858792381671956233">Bạn đã hỏi cha mẹ mình xem có thể truy cập vào trang này hay không</translation>
<translation id="4864052566555297930">Mẹo an toàn:</translation>
<translation id="4876188919622883022">Chế độ xem đơn giản</translation>
<translation id="4876305945144899064">Không có tên người dùng</translation>
@@ -748,7 +759,9 @@
<translation id="4974590756084640048">Bật lại cảnh báo</translation>
<translation id="4984339528288761049">Prc5 (Phong bì)</translation>
<translation id="4989163558385430922">Xem tất cả</translation>
+<translation id="4989542687859782284">Không được hỗ trợ</translation>
<translation id="4989809363548539747">Plugin này không được hỗ trợ</translation>
+<translation id="4995216769782533993">Xác nhận mã bảo mật để chia sẻ thông tin thẻ của bạn với trang web này</translation>
<translation id="5002932099480077015">Nếu được bật, Chrome sẽ lưu trữ bản sao thẻ của bạn trên thiết bị này để điền vào biểu mẫu nhanh hơn.</translation>
<translation id="5015510746216210676">Tên máy:</translation>
<translation id="5017554619425969104">Văn bản bạn đã sao chép</translation>
@@ -777,6 +790,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 bit)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">Xác minh thẻ của bạn</translation>
<translation id="5135404736266831032">Quản lý địa chỉ...</translation>
<translation id="5138227688689900538">Ẩn bớt</translation>
<translation id="5141240743006678641">Mã hóa mật khẩu đã đồng bộ hóa với thông tin đăng nhập Google của bạn</translation>
@@ -803,6 +817,7 @@
<translation id="5251803541071282808">Đám mây</translation>
<translation id="5252000469029418751">C7 (Phong bì)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">Chỉ chủ sở hữu <ph name="OWNER_EMAIL" /> mới có thể đặt các tính năng áp dụng trên toàn hệ thống.</translation>
<translation id="5273658854610202413">Cảnh báo: Chính sách này không được hợp nhất như chỉ định trong chính sách PolicyDictionaryMultipleSourceMergeList vì chính sách này không thuộc các chính sách từ điển có thể hợp nhất.</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">Kết thúc</translation>
@@ -826,7 +841,6 @@
<translation id="536296301121032821">Không thể lưu trữ cài đặt chính sách</translation>
<translation id="5371425731340848620">Cập nhật thẻ</translation>
<translation id="5377026284221673050">"Đồng hồ của bạn chạy chậm" hoặc "Đồng hồ của bạn chạy nhanh" hay "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
-<translation id="5377179979757081683">Trang này có thể cố lừa bạn, lấy cắp thông tin cá nhân hoặc gây hại cho thiết bị của bạn. Hãy thận trọng khi nhập thông tin cá nhân hoặc mở tệp đã tải xuống.</translation>
<translation id="5384855140246857529">Để sử dụng thẻ trên tất cả thiết bị, hãy đăng nhập và bật tính năng đồng bộ hóa.</translation>
<translation id="5386426401304769735">Chuỗi chứng chỉ cho trang web này có chứa một chứng chỉ đã ký bằng SHA-1.</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +854,8 @@
<translation id="5457113250005438886">Không hợp lệ</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> và <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> liên hệ khác}other{<ph name="CONTACT_PREVIEW" /> và <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> liên hệ khác}}</translation>
<translation id="5470861586879999274">&amp;Làm lại chỉnh sửa</translation>
+<translation id="5473728911100096288">Khi bật các tính năng này, bạn vẫn sẽ dùng các tính năng sắp ngừng hoạt động.
+ Các tính năng này sẽ không còn xuất hiện trong các phiên bản trong tương lai.</translation>
<translation id="5478437291406423475">B6/C4 (Phong bì)</translation>
<translation id="5481076368049295676">Nội dung này có thể tìm cách cài đặt phần mềm nguy hiểm trên thiết bị của bạn để lấy cắp hoặc xóa thông tin. <ph name="BEGIN_LINK" />Vẫn hiển thị<ph name="END_LINK" /></translation>
<translation id="54817484435770891">Thêm địa chỉ hợp lệ</translation>
@@ -863,7 +879,6 @@
<translation id="5570825185877910964">Bảo vệ tài khoản</translation>
<translation id="5571083550517324815">Không thể nhận hàng từ địa chỉ này. Chọn một địa chỉ khác.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{Đang sử dụng 1 cookie}other{Đang sử dụng # cookie}})</translation>
-<translation id="5572851009514199876">Vui lòng khởi động và đăng nhập vào Chrome để Chrome có thể kiểm tra xem bạn có được phép truy cập trang web này không.</translation>
<translation id="5580958916614886209">Kiểm tra tháng hết hạn của bạn và thử lại</translation>
<translation id="5586446728396275693">Không có địa chỉ nào được lưu</translation>
<translation id="5595485650161345191">Chỉnh sửa địa chỉ</translation>
@@ -871,6 +886,7 @@
<translation id="560412284261940334">Không hỗ trợ quản lý</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">Đây có thể là trang web giả mạo hoặc lừa đảo. Bạn nên thoát khỏi trang web này ngay.</translation>
<translation id="5610142619324316209">Kiểm tra kết nối</translation>
<translation id="5610807607761827392">Bạn có thể quản lý thẻ và địa chỉ trong <ph name="BEGIN_LINK" />Cài đặt<ph name="END_LINK" />.</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> đã chuyển hướng bạn quá nhiều lần.</translation>
@@ -894,11 +910,11 @@
<translation id="5720705177508910913">Người dùng hiện tại</translation>
<translation id="5728056243719941842">C5 (Phong bì)</translation>
<translation id="5730040223043577876">Chrome khuyên bạn nên đặt lại mật khẩu của mình nếu đã sử dụng lại mật khẩu này trên các trang web khác.</translation>
-<translation id="5732392974455271431">Cha mẹ của bạn có thể bỏ chặn trang web cho bạn</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{Lưu thẻ vào Tài khoản Google}other{Lưu các thẻ vào Tài khoản Google}}</translation>
<translation id="5763042198335101085">Nhập địa chỉ email hợp lệ</translation>
<translation id="5765072501007116331">Để xem các yêu cầu và phương thức phân phối, hãy chọn một địa chỉ</translation>
<translation id="5778550464785688721">Điều khiển toàn bộ thiết bị MIDI</translation>
+<translation id="5781136890105823427">Đã bật tính năng thử nghiệm</translation>
<translation id="578305955206182703">Hổ phách</translation>
<translation id="57838592816432529">Tắt tiếng</translation>
<translation id="5784606427469807560">Đã xảy ra sự cố khi xác nhận thẻ của bạn. Hãy kiểm tra kết nối Internet của bạn và thử lại.</translation>
@@ -915,13 +931,16 @@
<translation id="5860033963881614850">Tắt</translation>
<translation id="5863847714970149516">Trang phía trước có thể tìm cách tính phí bạn</translation>
<translation id="5866257070973731571">Thêm số điện thoại</translation>
+<translation id="5866898949289125849">Bạn đang xem trang công cụ dành cho nhà phát triển</translation>
<translation id="5869405914158311789">Không thể truy cập trang web này</translation>
<translation id="5869522115854928033">Mật khẩu đã lưu</translation>
<translation id="5887400589839399685">Đã lưu thẻ</translation>
<translation id="5893752035575986141">Thẻ tín dụng được chấp nhận.</translation>
+<translation id="5895138241574237353">Khởi động lại</translation>
<translation id="5901630391730855834">Vàng</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (được đồng bộ hóa)</translation>
<translation id="5916664084637901428">Bật</translation>
+<translation id="59174027418879706">Được kích hoạt</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">Bạn có muốn lưu thẻ vào Tài khoản Google không?</translation>
<translation id="5922853866070715753">Sắp hoàn tất</translation>
@@ -955,6 +974,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">Bạn muốn sử dụng thẻ trên tất cả thiết bị?</translation>
<translation id="6059925163896151826">Thiết bị USB</translation>
+<translation id="6060009363608157444">Chế độ DnsOverHttps không hợp lệ.</translation>
<translation id="6080696365213338172">Bạn đã truy cập nội dung bằng chứng chỉ do quản trị viên cấp. Dữ liệu mà bạn cung cấp cho <ph name="DOMAIN" /> có thể bị quản trị viên của bạn chặn.</translation>
<translation id="6094273045989040137">Chú thích</translation>
<translation id="610911394827799129">Tài khoản Google của bạn có thể có các dạng lịch sử duyệt web khác tại <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
@@ -1003,13 +1023,12 @@
<translation id="6404511346730675251">Chỉnh sửa dấu trang</translation>
<translation id="6406765186087300643">C0 (Phong bì)</translation>
<translation id="6410264514553301377">Nhập ngày hết hạn và CVC cho <ph name="CREDIT_CARD" /></translation>
-<translation id="6414888972213066896">Bạn đã hỏi cha mẹ mình xem có thể truy cập vào trang này hay không</translation>
<translation id="6415778972515849510">Chromium có thể giúp bạn bảo vệ Tài khoản Google của mình và đổi mật khẩu.</translation>
-<translation id="6417515091412812850">Không thể kiểm tra liệu chứng chỉ đã bị thu hồi hay chưa.</translation>
<translation id="6431585503458005759">Không lưu</translation>
<translation id="6433490469411711332">Chỉnh sửa thông tin liên hệ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> đã từ chối kết nối.</translation>
<translation id="6434309073475700221">Hủy</translation>
+<translation id="6435221585574090192">Chia sẻ với Quản trị viên các dữ liệu về những sự kiện bảo mật mà tính năng Bảo vệ khỏi mối đe dọa của Chrome Enterprise đã gắn cờ. Các dữ liệu này có thể bao gồm cả URL trang, tên tệp và siêu dữ liệu tệp, tên người dùng Chrome và tên người dùng thiết bị của bạn.</translation>
<translation id="6440503408713884761">Bị bỏ qua</translation>
<translation id="6446163441502663861">Kahu (Phong bì)</translation>
<translation id="6446608382365791566">Thêm thông tin khác</translation>
@@ -1018,20 +1037,19 @@
<translation id="6465306955648956876">Quản lý mật khẩu...</translation>
<translation id="647261751007945333">Chính sách thiết bị</translation>
<translation id="6476284679642588870">Quản lý phương thức thanh toán</translation>
-<translation id="6477321094435799029">Chrome đã phát hiện mã bất thường trên trang này và đã chặn mã này để bảo vệ thông tin cá nhân của bạn (ví dụ như mật khẩu, số điện thoại và thẻ tín dụng).</translation>
<translation id="6489534406876378309">Bắt đầu tải lên sự cố</translation>
<translation id="6499038740797743453">Đặt lại mật khẩu?</translation>
<translation id="6507833130742554667">Thẻ tín dụng và thẻ ghi nợ được chấp nhận.</translation>
<translation id="650855688985305916">Có, lưu</translation>
<translation id="6508722015517270189">Khởi động lại Chrome</translation>
<translation id="6517596291481585650">Cảnh báo: Chính sách này không phải là danh sách nên không được hợp nhất dưới dạng danh sách như chỉ định trong chính sách.</translation>
+<translation id="6518133107902771759">Xác minh</translation>
<translation id="6521745193039995384">Không hoạt động</translation>
<translation id="6529602333819889595">&amp;Làm lại xóa</translation>
<translation id="6534179046333460208">Đề xuất Web trong cuộc sống</translation>
<translation id="6545864417968258051">Quét tìm Bluetooth</translation>
<translation id="6554795675067793129">Tài khoản của bạn do <ph name="ENROLLMENT_DOMAIN" /> quản lý.</translation>
<translation id="6556866813142980365">Làm lại</translation>
-<translation id="6563469144985748109">Người quản lý của bạn chưa phê duyệt trang web</translation>
<translation id="6569060085658103619">Bạn đang xem trang tiện ích</translation>
<translation id="6578796323535178455">C2 (Phong bì)</translation>
<translation id="6579990219486187401">Hồng nhạt</translation>
@@ -1049,11 +1067,13 @@
<translation id="6643016212128521049">Xóa</translation>
<translation id="6644283850729428850">Chính sách này không được chấp thuận.</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{Không có}=1{Của 1 trang web (bạn sẽ không bị đăng xuất khỏi Tài khoản Google của mình)}other{Của # trang web (bạn sẽ không bị đăng xuất khỏi Tài khoản Google của mình)}}</translation>
+<translation id="6652101503459149953">Sử dụng Windows Hello</translation>
<translation id="6657585470893396449">Mật khẩu</translation>
<translation id="6670613747977017428">Quay lại trang an toàn.</translation>
<translation id="6671697161687535275">Bạn muốn xóa đề xuất biểu mẫu khỏi Chromium?</translation>
<translation id="6685834062052613830">Đăng xuất và hoàn thành quá trình thiết lập</translation>
<translation id="6689271823431384964">Chrome đang đề xuất lưu thẻ của bạn vào Tài khoản Google vì bạn đã đăng nhập. Bạn có thể thay đổi hoạt động này trong phần cài đặt. Tên chủ thẻ được lấy từ tài khoản của bạn.</translation>
+<translation id="6707256370811247129">Quét nội dung trong bộ nhớ đệm và các tệp mà bạn tải lên hoặc tải xuống trên Chrome.</translation>
<translation id="6710213216561001401">Trước đó</translation>
<translation id="6710594484020273272">&lt;Nhập cụm từ tìm kiếm&gt;</translation>
<translation id="671076103358959139">Mã đăng ký:</translation>
@@ -1061,10 +1081,10 @@
<translation id="6738516213925468394">Dữ liệu của bạn đã được mã hóa bằng <ph name="BEGIN_LINK" />cụm mật khẩu đồng bộ hóa<ph name="END_LINK" /> vào <ph name="TIME" />. Hãy nhập cụm mật khẩu đó để bắt đầu đồng bộ hóa.</translation>
<translation id="674375294223700098">Lỗi chứng chỉ máy chủ không xác định.</translation>
<translation id="6744009308914054259">Trong khi chờ kết nối, bạn có thể chuyển đến phần Tệp đã tải xuống để đọc các tin bài khi không có mạng.</translation>
+<translation id="6747611005629681221">Cảnh báo: Các tính năng sắp ngừng hoạt động!</translation>
<translation id="6753269504797312559">Giá trị chính sách</translation>
<translation id="6757797048963528358">Thiết bị của bạn đã chuyển sang chế độ ngủ.</translation>
<translation id="6768213884286397650">Hagaki (Bưu thiếp)</translation>
-<translation id="6778737459546443941">Cha mẹ của bạn chưa phê duyệt trang web</translation>
<translation id="67862343314499040">Tím vi-ô-lét</translation>
<translation id="6786747875388722282">Tiện ích</translation>
<translation id="6790428901817661496">Phát</translation>
@@ -1072,6 +1092,7 @@
<translation id="681021252041861472">Trường bắt buộc</translation>
<translation id="6810899417690483278">ID tùy chỉnh</translation>
<translation id="6825578344716086703">Bạn đã cố gắng truy cập vào <ph name="DOMAIN" /> nhưng máy chủ xuất trình một chứng chỉ được ký bằng một thuật toán chữ ký yếu (chẳng hạn như SHA-1). Điều này có nghĩa là thông tin đăng nhập bảo mật mà máy chủ xuất trình có thể đã bị giả mạo và máy chủ đó có thể không phải là máy chủ mà bạn mong đợi (bạn có thể đang kết nối với kẻ tấn công).</translation>
+<translation id="6826370046007623921">Ngăn chặn mất dữ liệu</translation>
<translation id="6831043979455480757">Dịch</translation>
<translation id="6839929833149231406">Vùng</translation>
<translation id="6852204201400771460">Tải lại ứng dụng?</translation>
@@ -1084,7 +1105,6 @@
<translation id="6891596781022320156">Cấp chính sách không được hỗ trợ.</translation>
<translation id="6895330447102777224">Thẻ của bạn đã được xác nhận</translation>
<translation id="6897140037006041989">Tác nhân Người dùng</translation>
-<translation id="6903319715792422884">Giúp cải thiện tính năng Duyệt web an toàn bằng cách gửi một số <ph name="BEGIN_WHITEPAPER_LINK" />thông tin hệ thống và nội dung trang<ph name="END_WHITEPAPER_LINK" /> tới Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Người dùng:</translation>
<translation id="6934672428414710184">Tên này lấy từ Tài khoản Google của bạn</translation>
<translation id="6944692733090228304">Bạn đã nhập mật khẩu trên trang web không do <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> quản lý. Để bảo vệ tài khoản, không sử dụng lại mật khẩu của bạn trên các ứng dụng và trang web khác.</translation>
@@ -1129,6 +1149,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> và <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> phương thức thanh toán khác}other{<ph name="PAYMENT_METHOD_PREVIEW" /> và <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> phương thức thanh toán khác}}</translation>
<translation id="7153618581592392745">Tím oải hương</translation>
<translation id="717330890047184534">ID Gaia:</translation>
+<translation id="7174545416324379297">Đã hợp nhất</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> và <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> tùy chọn giao hàng khác}other{<ph name="SHIPPING_OPTION_PREVIEW" /> và <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> tùy chọn giao hàng khác}}</translation>
<translation id="7177397715882417099">Máy chủ bạn định truy cập vào, <ph name="ORIGIN" />, đã yêu cầu phải áp dụng
một chính sách bảo mật cho tất cả các yêu cầu được gửi tới máy chủ đó. Tuy nhiên, thay vì
@@ -1166,6 +1187,7 @@ Thông tin chi tiết bổ sung:
<translation id="7320336641823683070">Trợ giúp kết nối</translation>
<translation id="733354035281974745">Ghi đè tài khoản trên thiết bị</translation>
<translation id="7334320624316649418">&amp;Làm lại sắp xếp lại</translation>
+<translation id="7337706099755338005">Không được hỗ trợ trên nền tảng của bạn.</translation>
<translation id="733923710415886693">Chứng chỉ của máy chủ đã không được tiết lộ qua Tính minh bạch của chứng chỉ.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Được liên kết:</translation>
@@ -1197,7 +1219,6 @@ Thông tin chi tiết bổ sung:
<translation id="7440140511386898319">Khám phá khi không có mạng</translation>
<translation id="7441627299479586546">Chủ đề chính sách sai</translation>
<translation id="7442725080345379071">Cam nhạt</translation>
-<translation id="7444046173054089907">Trang web này bị chặn</translation>
<translation id="7445762425076701745">Không thể xác thực đầy đủ nhận dạng của máy chủ bạn đã kết nối. Bạn đã kết nối vào máy chủ bằng một tên chỉ hợp lệ trong mạng của bạn và đó là tên mà các tổ chức phát hành chứng chỉ bên ngoài không thể xác thực được. Vì một số tổ chức phát hành chứng chỉ sẽ cấp chứng chỉ cho các tên này thay thế, nên không có cách nào đảm bảo bạn được kết nối tới trang web đã chỉ định và không phải là kẻ tấn công.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /> về sự cố này.</translation>
<translation id="7455133967321480974">Sử dụng cài đặt mặc định chung (Chặn)</translation>
@@ -1219,9 +1240,9 @@ Thông tin chi tiết bổ sung:
<translation id="7538364083937897561">A2 (Phong bì)</translation>
<translation id="7542403920425041731">Sau khi bạn xác nhận, chi tiết thẻ của bạn sẽ được chia sẻ với trang web này.</translation>
<translation id="7542995811387359312">Tính năng tự động điền thẻ tín dụng đã bị vô hiệu hóa vì biểu mẫu này không sử dụng kết nối an toàn.</translation>
-<translation id="7543525346216957623">Hãy hỏi ý kiến cha mẹ của bạn</translation>
<translation id="7548892272833184391">Khắc phục lỗi kết nối</translation>
<translation id="7549584377607005141">Trang web này yêu cầu dữ liệu mà bạn đã nhập trước đó để được hiển thị đúng cách. Bạn có thể gửi lại dữ liệu này nhưng làm như vậy bạn sẽ lặp lại mọi hoạt động mà trang này đã thực hiện trước đó.</translation>
+<translation id="7550637293666041147">Tên người dùng Chrome và tên người dùng thiết bị của bạn</translation>
<translation id="7552846755917812628">Thử các mẹo sau:</translation>
<translation id="7554791636758816595">Tab mới</translation>
<translation id="7564049878696755256">Bạn có thể mất quyền truy cập vào tài khoản <ph name="ORG_NAME" /> của mình hoặc bị đánh cắp danh tính. Chrome khuyên bạn nên thay đổi mật khẩu ngay bây giờ.</translation>
@@ -1236,6 +1257,7 @@ Thông tin chi tiết bổ sung:
<translation id="7610193165460212391">Giá trị nằm ngoài phạm vi <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Hết hạn: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">Bạn đã có dữ liệu được mã hóa bằng mật khẩu khác của Tài khoản Google. Vui lòng nhập mật khẩu đó bên dưới.</translation>
+<translation id="7625784245512586808">Tính năng Bảo vệ khỏi mối đe dọa của Chrome Enterprise</translation>
<translation id="7633909222644580952">Báo cáo sự cố và dữ liệu hiệu suất</translation>
<translation id="7637571805876720304">Bạn muốn xóa thẻ tín dụng khỏi Chromium?</translation>
<translation id="7638605456503525968">Cổng nối tiếp</translation>
@@ -1248,7 +1270,6 @@ Thông tin chi tiết bổ sung:
<translation id="7668654391829183341">Thiết bị không xác định</translation>
<translation id="7669271284792375604">Những kẻ tấn công trên trang web này có thể đánh lừa bạn cài đặt các chương trình ảnh hưởng đến trải nghiệm duyệt web của bạn (ví dụ: bằng cách thay đổi trang chủ của bạn hoặc hiển thị thêm quảng cáo trên các trang web bạn truy cập).</translation>
<translation id="7676643023259824263">Tìm kiếm văn bản trong khay nhớ tạm, <ph name="TEXT" /></translation>
-<translation id="7679176406634891508">Nền tảng và đám mây</translation>
<translation id="7681101578153515023">Thay đổi công cụ tìm kiếm</translation>
<translation id="7682287625158474539">Địa chỉ gửi hàng</translation>
<translation id="7687186412095877299">Điền vào biểu mẫu thanh toán bằng phương thức thanh toán đã lưu</translation>
@@ -1263,7 +1284,6 @@ Thông tin chi tiết bổ sung:
<translation id="7723047071702270851">Chỉnh sửa thẻ</translation>
<translation id="774634243536837715">Đã chặn nội dung nguy hiểm.</translation>
<translation id="7752995774971033316">Không được quản lý</translation>
-<translation id="7755287808199759310">Cha mẹ của bạn có thể bỏ chặn trang web cho bạn</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">Tường lửa hoặc phần mềm diệt vi-rút có thể đã chặn kết nối.</translation>
<translation id="7759163816903619567">Miền hiển thị:</translation>
@@ -1307,7 +1327,6 @@ Thông tin chi tiết bổ sung:
<translation id="8004582292198964060">Trình duyệt</translation>
<translation id="8009225694047762179">Quản lý mật khẩu</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Thẻ này và địa chỉ thanh toán của thẻ sẽ được lưu. Bạn có thể sử dụng thẻ khi đăng nhập vào <ph name="USER_EMAIL" />.}other{Các thẻ này và địa chỉ thanh toán của thẻ sẽ được lưu. Bạn có thể sử dụng các thẻ này khi đăng nhập vào <ph name="USER_EMAIL" />.}}</translation>
-<translation id="8012647001091218357">Chúng tôi không thể liên lạc với cha mẹ của bạn vào thời điểm này. Vui lòng thử lại.</translation>
<translation id="8025119109950072390">Những kẻ tấn công trên trang web này có thể đánh lừa bạn làm một việc gì đó nguy hiểm như cài đặt phần mềm hoặc tiết lộ thông tin cá nhân của bạn (ví dụ: mật khẩu, số điện thoại hoặc thẻ tín dụng).</translation>
<translation id="8034522405403831421">Trang này có ngôn ngữ là <ph name="SOURCE_LANGUAGE" />. Dịch trang này sang <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Bút</translation>
@@ -1318,6 +1337,7 @@ Thông tin chi tiết bổ sung:
<translation id="8041940743680923270">Sử dụng cài đặt mặc định chung (Hỏi)</translation>
<translation id="8042918947222776840">Chọn phương thức nhận hàng</translation>
<translation id="8057711352706143257">Cấu hình của "<ph name="SOFTWARE_NAME" />" không chính xác. Việc gỡ cài đặt "<ph name="SOFTWARE_NAME" />" thường sẽ khắc phục được sự cố này. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">Từ giờ trở đi, bạn sẽ không cần phải nhập mã bảo mật thẻ</translation>
<translation id="8066955247577885446">Rất tiếc, đã xảy ra lỗi.</translation>
<translation id="8074253406171541171">10x13 (Phong bì)</translation>
<translation id="8078141288243656252">Không thể chú thích khi xoay</translation>
@@ -1348,6 +1368,7 @@ Thông tin chi tiết bổ sung:
<translation id="8211406090763984747">Kết nối an toàn</translation>
<translation id="8218327578424803826">Vị trí được gán:</translation>
<translation id="8220146938470311105">C7/C6 (Phong bì)</translation>
+<translation id="8220639454292072926">Báo cáo của Enterprise</translation>
<translation id="8225771182978767009">Người thiết lập máy tính này đã chọn chặn trang web này.</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />, <ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">Mở trang trong tab Ẩn danh mới</translation>
@@ -1402,24 +1423,24 @@ Thông tin chi tiết bổ sung:
<translation id="8508648098325802031">Biểu tượng Tìm kiếm</translation>
<translation id="8522552481199248698">Chrome có thể giúp bạn bảo vệ Tài khoản Google của mình và đổi mật khẩu.</translation>
<translation id="8543181531796978784">Bạn có thể <ph name="BEGIN_ERROR_LINK" />báo cáo sự cố đã phát hiện<ph name="END_ERROR_LINK" /> hoặc nếu bạn hiểu rủi ro với bảo mật của mình, hãy <ph name="BEGIN_LINK" />truy cập trang web không an toàn này<ph name="END_LINK" />.</translation>
-<translation id="8543556556237226809">Bạn có câu hỏi? Hãy liên hệ với người giám sát hồ sơ của bạn.</translation>
<translation id="8553075262323480129">Dịch thất bại do ngôn ngữ của trang không được xác định.</translation>
<translation id="8557066899867184262">CVC nằm ở mặt sau thẻ của bạn.</translation>
<translation id="8559762987265718583">Không thể thiết lập kết nối riêng tư với <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> vì ngày và giờ (<ph name="DATE_AND_TIME" />) trên thiết bị của bạn không đúng.</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" /> trang web đáng ngờ</translation>
<translation id="8564985650692024650">Chromium khuyên bạn nên đặt lại mật khẩu <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> của mình nếu đã sử dụng lại mật khẩu này trên các trang web khác.</translation>
<translation id="8571890674111243710">Đang dịch trang sang <ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">Thêm số đ.thoại
</translation>
-<translation id="859285277496340001">Chứng chỉ không ghi rõ cơ chế kiểm tra xem chứng chỉ đã bị thu hồi hay chưa.</translation>
<translation id="860043288473659153">Tên chủ thẻ</translation>
<translation id="861775596732816396">Kích thước 4</translation>
-<translation id="8620436878122366504">Cha mẹ của bạn chưa phê duyệt trang web</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">Lưu thẻ này vào thiết bị này</translation>
<translation id="8626112503828625890">Lưu chi tiết thanh toán vào Tài khoản Google?</translation>
+<translation id="8647750283161643317">Đặt lại tất cả về mặc định</translation>
<translation id="8663226718884576429">Tóm tắt đơn hàng, <ph name="TOTAL_LABEL" />, chi tiết khác</translation>
<translation id="8680536109547170164"><ph name="QUERY" />, câu trả lời, <ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">Có sẵn</translation>
<translation id="8703575177326907206">Kết nối của bạn đến <ph name="DOMAIN" /> không được mã hóa.</translation>
<translation id="8718314106902482036">Thanh toán chưa hoàn tất</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />, <ph name="DESCRIPTION" />, đề xuất tìm kiếm</translation>
@@ -1430,6 +1451,7 @@ Thông tin chi tiết bổ sung:
<translation id="8738058698779197622">Để thiết lập kết nối an toàn, bạn cần đặt thời gian đúng cho đồng hồ. Nguyên nhân là do chứng chỉ mà các trang web dùng để tự nhận dạng chỉ có hiệu lực trong khoảng thời gian cụ thể. Vì đồng hồ trên thiết bị của bạn không đúng nên Chromium không thể xác minh các chứng chỉ này.</translation>
<translation id="8740359287975076522">Không thể tìm thấy &lt;abbr id="dnsDefinition"&gt;địa chỉ DNS&lt;/abbr&gt; của <ph name="HOST_NAME" />. Đang chẩn đoán sự cố.</translation>
<translation id="874846938927089722">Thẻ tín dụng và thẻ trả trước được chấp nhận</translation>
+<translation id="874918643257405732">Đánh dấu tab này</translation>
<translation id="8759274551635299824">Thẻ này đã hết hạn</translation>
<translation id="8761567432415473239">Gần đây, Duyệt web an toàn của Google <ph name="BEGIN_LINK" />tìm thấy chương trình độc hại<ph name="END_LINK" /> trên trang <ph name="SITE" />.</translation>
<translation id="8763927697961133303">Thiết bị USB</translation>
@@ -1459,6 +1481,7 @@ Thông tin chi tiết bổ sung:
<translation id="8938939909778640821">Thẻ tín dụng và thẻ trả trước được chấp nhận</translation>
<translation id="8943282376843390568">Vàng chanh</translation>
<translation id="8957210676456822347">Ủy quyền cổng bị khóa</translation>
+<translation id="8962950042226115166">Trang web đáng ngờ</translation>
<translation id="8968766641738584599">Lưu thẻ</translation>
<translation id="8971063699422889582">Chứng chỉ của máy chủ đã hết hạn.</translation>
<translation id="8975012916872825179">Bao gồm các thông tin như số điện thoại, địa chỉ email và địa chỉ giao hàng</translation>
@@ -1481,24 +1504,24 @@ Thông tin chi tiết bổ sung:
<translation id="9035022520814077154">Lỗi bảo mật</translation>
<translation id="9038649477754266430">Sử dụng dịch vụ gợi ý để tải trang nhanh hơn</translation>
<translation id="9039213469156557790">Ngoài ra, trang này bao gồm các tài nguyên khác không an toàn. Những tài nguyên này có thể bị người khác xem khi đang gửi và có thể bị kẻ tấn công sửa đổi nhằm thay đổi hành vi của trang.</translation>
+<translation id="9044359186343685026">Sử dụng Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">Bạn đã cố truy cập vào <ph name="DOMAIN" />, nhưng máy chủ cho biết chứng chỉ không hợp lệ.</translation>
<translation id="9050666287014529139">Cụm mật khẩu</translation>
<translation id="9065203028668620118">Chỉnh sửa</translation>
<translation id="9065745800631924235">Cụm từ tìm kiếm <ph name="TEXT" /> từ lịch sử</translation>
<translation id="9069693763241529744">Bị một tiện ích chặn</translation>
-<translation id="9076283476770535406">Trang web có thể có nội dung người lớn</translation>
<translation id="9076630408993835509">Không có công ty hay tổ chức nào quản lý trình duyệt này. Hoạt động trên thiết bị này có thể được quản lý ở bên ngoài Chrome. <ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">Yêu cầu thêm thông tin</translation>
<translation id="9080712759204168376">Tóm tắt đơn hàng</translation>
<translation id="9089260154716455634">Chính sách về khoảng thời gian tắt:</translation>
<translation id="9095388113577226029">Ngôn ngữ khác...</translation>
+<translation id="9098981495403789647">Quản trị viên đã bật tính năng Bảo vệ khỏi mối đe dọa của Chrome Enterprise trên trình duyệt. Tính năng Bảo vệ khỏi mối đe dọa của Chrome Enterprise có quyền truy cập vào một số dữ liệu của bạn.</translation>
<translation id="9103872766612412690"><ph name="SITE" /> thường sử dụng mã hóa để bảo vệ thông tin của bạn. Khi Chromium cố gắng kết nối với <ph name="SITE" /> tại thời điểm này, trang web đã gửi lại thông tin đăng nhập không chính xác và bất thường. Điều này có thể xảy ra khi kẻ tấn công đang cố gắng giả mạo là <ph name="SITE" /> hoặc màn hình đăng nhập Wi-Fi đã làm gián đoạn kết nối. Thông tin của bạn vẫn an toàn do Chromium đã ngừng kết nối trước khi bất kỳ dữ liệu nào được trao đổi.</translation>
<translation id="9106062320799175032">Thêm địa chỉ thanh toán</translation>
<translation id="9114524666733003316">Đang xác nhận thẻ...</translation>
<translation id="9128870381267983090">Kết nối đến mạng</translation>
<translation id="9137013805542155359">Hiển thị văn bản gốc</translation>
-<translation id="9137248913990643158">Vui lòng khởi động và đăng nhập vào Chrome trước khi sử dụng ứng dụng này.</translation>
<translation id="9141013498910525015">Quản lý địa chỉ</translation>
<translation id="9148088599418889305">Chọn phương thức giao hàng</translation>
<translation id="9148507642005240123">&amp;Hoàn tác chỉnh sửa</translation>
diff --git a/chromium/components/strings/components_strings_zh-CN.xtb b/chromium/components/strings/components_strings_zh-CN.xtb
index 8fef39e0f0d..744dbf211fa 100644
--- a/chromium/components/strings/components_strings_zh-CN.xtb
+++ b/chromium/components/strings/components_strings_zh-CN.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">添加持卡人姓名</translation>
<translation id="1089439967362294234">更改密码</translation>
+<translation id="1096545575934602868">此字段最多仅能包含 <ph name="MAX_ITEMS_LIMIT" /> 个条目,超出的条目会被舍弃。</translation>
<translation id="109743633954054152">在 Chrome 设置中管理密码</translation>
<translation id="1103523840287552314">一律翻译<ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">选中后,Chrome 会将您的信用卡副本存储在此设备上,以加快表单填写速度。</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">访问<ph name="URL" />的<ph name="BEGIN_LINK" />缓存副本<ph name="END_LINK" /></translation>
<translation id="1156303062776767266">您正在查看一个本地文件或共享文件</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> 意外终止了连接。</translation>
+<translation id="115926840831309955">请检查您的银行卡验证码 (CVC) 并重试,或者更新失效日期</translation>
<translation id="1161325031994447685">重新连接到 Wi-Fi 网络</translation>
<translation id="1165039591588034296">错误</translation>
<translation id="1175364870820465910">打印(&amp;P)...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">“您计算机上的软件导致 Chrome 无法安全地连接到网络”(仅限 Windows 计算机)</translation>
<translation id="1294154142200295408">命令行变体</translation>
<translation id="129553762522093515">最近关闭的标签页</translation>
+<translation id="1298536327547837046">恶意软件扫描</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />尝试清除 Cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">已被弃用的功能</translation>
<translation id="1320233736580025032">Prc1 (Envelope)</translation>
<translation id="132301787627749051">搜索剪贴板上的图片</translation>
<translation id="1323433172918577554">展开</translation>
@@ -115,6 +119,7 @@
<translation id="1521655867290435174">Google 表格</translation>
<translation id="1527263332363067270">正在等待建立连接…</translation>
<translation id="1529521330346880926">10x15 (Envelope)</translation>
+<translation id="1530707389502320859">您刚才尝试访问的网站貌似为虚假网站。攻击者有时会对网址做些令人难以发现的细微更改来仿冒网站。</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">此网页显示</translation>
<translation id="153384715582417236">暂无新内容</translation>
@@ -155,7 +160,6 @@
<translation id="1710259589646384581">操作系统</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">无法为该文档添加注释,因为它太大</translation>
-<translation id="1721312023322545264">您需要获得<ph name="NAME" />的许可,然后才能访问此网站</translation>
<translation id="1721424275792716183">标有“*”的字段均是必填字段</translation>
<translation id="1727741090716970331">添加有效卡号</translation>
<translation id="1728677426644403582">您正在查看网页的源代码</translation>
@@ -179,6 +183,7 @@
<translation id="1822540298136254167">您访问过的网站和您在这些网站上花费的时间</translation>
<translation id="1826516787628120939">正在检查</translation>
<translation id="1834321415901700177">此网站包含有害程序</translation>
+<translation id="1838374766361614909">清除搜索字词</translation>
<translation id="1839551713262164453">由于出现错误,未能成功验证政策值</translation>
<translation id="1842969606798536927">付款</translation>
<translation id="1871208020102129563">代理已设置为使用固定的代理服务器,而不是 .pac 脚本网址。</translation>
@@ -189,6 +194,7 @@
<translation id="1883255238294161206">收起列表</translation>
<translation id="1898423065542865115">过滤</translation>
<translation id="1914326953223720820">解压缩服务</translation>
+<translation id="1915697529809968049">要改用 Touch ID 来取代银行卡验证码 (CVC) 吗?</translation>
<translation id="1916770123977586577">要将您更新后的设置应用到此网站,请重新加载此页面</translation>
<translation id="1919345977826869612">广告</translation>
<translation id="1919367280705858090">了解如何解决特定错误消息指出的错误</translation>
@@ -200,6 +206,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" />书签</translation>
<translation id="1973335181906896915">序列化错误</translation>
<translation id="1974060860693918893">高级</translation>
+<translation id="1974883374937189061">将<ph name="BEGIN_WHITEPAPER_LINK" />您访问的部分网页的网址、有限的系统信息以及部分网页内容<ph name="END_WHITEPAPER_LINK" />发送给 Google,以帮助我们提升 Chrome 的安全性。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">固件版本</translation>
<translation id="1981206234434200693">清除 Chrome 的浏览记录数据</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{以及另外 1 个应用}other{以及另外 # 个应用}}</translation>
@@ -242,10 +249,12 @@
<translation id="2202020181578195191">请输入有效的失效年份</translation>
<translation id="2212735316055980242">找不到策略</translation>
<translation id="2213606439339815911">正在获取条目…</translation>
+<translation id="2215727959747642672">文件修改</translation>
<translation id="2218879909401188352"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 上的现有攻击者可能会安装危险应用来损害您的设备、给您的手机帐单增添隐含费用或窃取您的个人信息。<ph name="BEGIN_LEARN_MORE_LINK" />了解详情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">未连接到互联网</translation>
<translation id="2230458221926704099">请使用<ph name="BEGIN_LINK" />诊断应用<ph name="END_LINK" />修复网络连接</translation>
<translation id="2239100178324503013">立即发送</translation>
+<translation id="2248949050832152960">使用 WebAuthn</translation>
<translation id="225207911366869382">适用于该政策的此值已弃用。</translation>
<translation id="2257315177824333709">抱歉,当前无法保存您的卡</translation>
<translation id="2262243747453050782">HTTP 错误</translation>
@@ -290,7 +299,6 @@
<translation id="2479410451996844060">搜索网址无效。</translation>
<translation id="2482878487686419369">通知</translation>
<translation id="248348093745724435">设备政策</translation>
-<translation id="2485387744899240041">您的设备和浏览器的用户名</translation>
<translation id="2491120439723279231">服务器证书中包含错误。</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON 解析器</translation>
@@ -300,6 +308,7 @@
<translation id="2501278716633472235">返回</translation>
<translation id="2503184589641749290">接受的借记卡和预付卡</translation>
<translation id="2505268675989099013">保护帐号</translation>
+<translation id="2515335152965840738">忽略</translation>
<translation id="2515629240566999685">检查您所在区域的网络信号</translation>
<translation id="2523886232349826891">仅会保存在此设备上</translation>
<translation id="2524461107774643265">添加更多信息</translation>
@@ -324,7 +333,6 @@
<translation id="2653659639078652383">提交</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{无}=1{1 个密码(用于 <ph name="DOMAIN_LIST" />)}=2{2 个密码(用于 <ph name="DOMAIN_LIST" />)}other{# 个密码(用于 <ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">关闭其他标签页或应用</translation>
-<translation id="267371737713284912">按 <ph name="MODIFIER_KEY_DESCRIPTION" /> 即可撤消</translation>
<translation id="2674170444375937751">确定要从历史记录中删除这些页吗?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">离开</translation>
@@ -334,12 +342,12 @@
<translation id="2704283930420550640">值不符合格式要求。</translation>
<translation id="2705137772291741111">无法读取此网站的已保存(缓存)副本。</translation>
<translation id="2709516037105925701">自动填充</translation>
-<translation id="2712173769900027643">请求批准</translation>
<translation id="2713444072780614174">白色</translation>
<translation id="2720342946869265578">附近</translation>
<translation id="2721148159707890343">请求成功</translation>
<translation id="2728127805433021124">服务器的证书是使用弱签名算法进行签名的。</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />运行网络连接诊断<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">启用这些功能可能会致使您丢失浏览数据,或者致使您的安全或隐私受到威胁。此操作会为该浏览器的所有用户启用这些功能。</translation>
<translation id="2735043616039983645">此政策存在多个具有冲突值的来源!</translation>
<translation id="2738330467931008676">选择取货地址</translation>
<translation id="2740531572673183784">确定</translation>
@@ -350,16 +358,15 @@
<translation id="2784949926578158345">连接已重置。</translation>
<translation id="2788784517760473862">接受的信用卡</translation>
<translation id="2792012897584536778">此设备的管理员设置了安全证书,这些证书可能会允许管理员查看您所访问的网站的内容。</translation>
-<translation id="2794233252405721443">网站已被屏蔽</translation>
<translation id="2799020568854403057">您要访问的网站包含有害应用</translation>
<translation id="2799223571221894425">重新启动</translation>
<translation id="2803306138276472711">Google安全浏览功能最近在<ph name="SITE" />上<ph name="BEGIN_LINK" />检测到了恶意软件<ph name="END_LINK" />。平常非常安全的网站有时也会感染恶意软件。</translation>
+<translation id="2815364696811431560">离开网站</translation>
<translation id="2824775600643448204">地址和搜索栏</translation>
<translation id="2826760142808435982">该连接使用 <ph name="CIPHER" /> 进行加密和身份验证,并使用 <ph name="KX" /> 作为密钥交换机制。</translation>
<translation id="2835170189407361413">清除表单</translation>
<translation id="2847118875340931228">打开无痕式窗口</translation>
<translation id="2850739647070081192">Invite (Envelope)</translation>
-<translation id="2851634818064021665">您需获得许可,才能访问此网站</translation>
<translation id="2856444702002559011">攻击者可能会试图从 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 窃取您的信息(例如:密码、通讯内容或信用卡信息)。<ph name="BEGIN_LEARN_MORE_LINK" />了解详情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">保存卡片?</translation>
@@ -384,6 +391,7 @@
<translation id="2985306909656435243">启用后,Chromium 会将您的信用卡副本存储在此设备上,以加快表单填写速度。</translation>
<translation id="2985398929374701810">请输入有效的送货地址</translation>
<translation id="2986368408720340940">该取货方式不可用。请另选一种方式。</translation>
+<translation id="2987034854559945715">找不到任何相符的功能</translation>
<translation id="2991174974383378012">与网站分享</translation>
<translation id="2991571918955627853">您目前无法访问 <ph name="SITE" />,因为此网站使用了 HSTS。网络错误和攻击通常是暂时的,因此,此网页稍后可能会恢复正常。</translation>
<translation id="3005723025932146533">显示已保存的版本</translation>
@@ -394,6 +402,7 @@
<translation id="3024663005179499861">策略类型有误</translation>
<translation id="3037605927509011580">喔唷,崩溃啦!</translation>
<translation id="3041612393474885105">证书信息</translation>
+<translation id="3057676462092457419">尚不支持 DnsOverHttps 模式“<ph name="SECURE_DNS_MODE_SECURE" />”,该模式现已设为“<ph name="SECURE_DNS_MODE_OFF" />”。</translation>
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3061707000357573562">修补服务</translation>
<translation id="3064966200440839136">将要退出隐身模式,以便通过外部应用付款。是否继续?</translation>
@@ -417,6 +426,7 @@
<translation id="3195213714973468956">“<ph name="SERVER_NAME" />”上的“<ph name="PRINTER_NAME" />”</translation>
<translation id="320323717674993345">取消付款</translation>
<translation id="3207960819495026254">已加书签</translation>
+<translation id="3209034400446768650">此网页可能会收取费用</translation>
<translation id="3225919329040284222">服务器提供的证书与内置预期证书不匹配。这些预期证书是针对某些高安全性网站提供的,以便为您提供保护。</translation>
<translation id="3226128629678568754">按“重新加载”按钮,重新提交加载该网页所需的数据。</translation>
<translation id="3227137524299004712">麦克风</translation>
@@ -424,7 +434,6 @@
<translation id="3229041911291329567">与您的设备和浏览器相关的版本信息</translation>
<translation id="323107829343500871">输入“<ph name="CREDIT_CARD" />”的银行卡验证码 (CVC)</translation>
<translation id="3234666976984236645">始终检测此网站上的重要内容</translation>
-<translation id="3254409185687681395">为此页添加书签</translation>
<translation id="3270847123878663523">撤消顺序调整(&amp;U)</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">添加持卡人姓名</translation>
@@ -434,7 +443,6 @@
<translation id="3320021301628644560">添加账单邮寄地址</translation>
<translation id="3324983252691184275">深红色</translation>
<translation id="3338095232262050444">安全</translation>
-<translation id="3345135638360864351">无法将您访问此网站的请求发送给<ph name="NAME" />,请重试。</translation>
<translation id="3355823806454867987">更改代理服务器设置...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />不会保存<ph name="END_EMPHASIS" />以下信息:
<ph name="BEGIN_LIST" />
@@ -468,17 +476,14 @@
<translation id="3462200631372590220">隐藏详情</translation>
<translation id="3467763166455606212">必须输入持卡人姓名</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />,目前处于打开状态,按 Tab 键再按 Enter 键可切换到打开的标签页</translation>
-<translation id="3479539252931486093">不应该出现这种情况?请<ph name="BEGIN_LINK" />告诉我们<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">以后再说</translation>
<translation id="3484560055331845446">您可能会无法再访问自己的 Google 帐号。Chrome 建议您立即更改密码。系统会要求您登录。</translation>
<translation id="3495081129428749620">在网页“<ph name="PAGE_TITLE" />”中查找</translation>
-<translation id="3498215018399854026">我们暂时无法与您父母取得联系,请重试。</translation>
<translation id="3512163584740124171">此政策会被忽略,因为同一政策组中的另一个政策具有更高的优先级。</translation>
<translation id="3528171143076753409">服务器的证书不受信任。</translation>
<translation id="3528485271872257980">深棕色</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{在已同步的设备上至少有 1 项内容}=1{1 项内容(在已同步的设备上还有更多内容)}other{# 项内容(在已同步的设备上还有更多内容)}}</translation>
<translation id="3539171420378717834">在此设备上保存此信用卡的副本</translation>
-<translation id="3556433843310711081">您的管理员可为您取消屏蔽此网站</translation>
<translation id="3566021033012934673">您的连接不是私密连接</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" /><ph name="STATE" /><ph name="CITY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> 上的嵌入式页面显示</translation>
@@ -493,7 +498,7 @@
<translation id="361438452008624280">列表条目“<ph name="LANGUAGE_ID" />”:语言未知或不受支持。</translation>
<translation id="3615877443314183785">请输入有效的失效日期</translation>
<translation id="36224234498066874">清除浏览数据...</translation>
-<translation id="362276910939193118">显示所有历史记录</translation>
+<translation id="362276910939193118">显示全部历史记录</translation>
<translation id="3630155396527302611">如果它已在可访问网络的程序列表中,请尝试将它从该列表中移除,然后重新添加到其中。</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3650584904733503804">验证成功</translation>
@@ -505,6 +510,7 @@
<translation id="3678529606614285348">在新的无痕式窗口中打开网页 (Ctrl-Shift-N)</translation>
<translation id="3679803492151881375">崩溃报告的获取时间:<ph name="CRASH_TIME" />;上传时间:<ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">证书信息</translation>
+<translation id="3701427423622901115">已确认要重置。</translation>
<translation id="3704162925118123524">您正在使用的网络可能会要求您访问其登录页面。</translation>
<translation id="3704609568417268905"><ph name="TIME" /> - <ph name="BOOKMARKED" /> - <ph name="TITLE" /> - <ph name="DOMAIN" /></translation>
<translation id="370665806235115550">正在加载...</translation>
@@ -521,6 +527,7 @@
<translation id="3748148204939282805"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 上的攻击者可能会诱骗您做一些危险的事情,例如安装软件或泄露您的个人信息(如密码、电话号码或信用卡信息)。<ph name="BEGIN_LEARN_MORE_LINK" />了解详情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">由于服务器出错,翻译失败。</translation>
<translation id="3759461132968374835">您最近未收到崩溃报告。崩溃报告停用时发生的崩溃不会在此处显示。</translation>
+<translation id="3760561303380396507">要改用 Windows Hello 来取代银行卡验证码 (CVC) 吗?</translation>
<translation id="3761718714832595332">隐藏状态</translation>
<translation id="3765032636089507299">安全浏览页面正在构建中。</translation>
<translation id="3778403066972421603">要将此卡的信息保存到您的 Google 帐号中和此设备上吗?</translation>
@@ -530,6 +537,7 @@
<translation id="3789155188480882154">大小:16</translation>
<translation id="3797522431967816232">Prc3 (Envelope)</translation>
<translation id="3807873520724684969">有害内容已被拦截。</translation>
+<translation id="3808375843007691220">警告:您所要使用的是实验性功能!</translation>
<translation id="3810973564298564668">管理</translation>
<translation id="382518646247711829">如果您使用代理服务器…</translation>
<translation id="3828924085048779000">密码输入字段不能留空。</translation>
@@ -538,11 +546,11 @@
<translation id="3858027520442213535">更新日期和时间</translation>
<translation id="3884278016824448484">设备标识符存在冲突</translation>
<translation id="3885155851504623709">教区</translation>
-<translation id="3886446263141354045">系统已将您想访问此网站的请求发送给<ph name="NAME" /></translation>
<translation id="3890664840433101773">添加电子邮件地址</translation>
<translation id="3901925938762663762">此信用卡已过期</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
+<translation id="3939773374150895049">要改用 WebAuthn 来取代银行卡验证码 (CVC) 吗?</translation>
<translation id="3946209740501886391">在该网站上一律询问</translation>
<translation id="3949571496842715403">此服务器无法证实它就是 <ph name="DOMAIN" /> - 它的安全证书没有指定主题备用名称。这可能是因为某项配置有误或某个攻击者拦截了您的连接。</translation>
<translation id="3949601375789751990">您的浏览记录会显示在此处</translation>
@@ -553,11 +561,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{无}=1{来自 1 个网站}other{来自 # 个网站}}</translation>
<translation id="397105322502079400">正在计算...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> 已被屏蔽</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> 已在您的浏览器中启用了 Chrome 企业版威胁防护功能。Chrome 企业版威胁防护功能可以访问您的部分数据。</translation>
<translation id="3987940399970879459">小于 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{附近有 1 个网页}other{附近有 # 个网页}}</translation>
<translation id="4030383055268325496">撤消添加(&amp;U)</translation>
<translation id="4032320456957708163">您的浏览器由 <ph name="ENROLLMENT_DOMAIN" /> 管理</translation>
-<translation id="4034375457890803692">您打开的链接将转到您不常访问的网站。该链接可能在试图迷惑您。</translation>
<translation id="4058922952496707368">“<ph name="SUBKEY" />”键:<ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (Envelope)</translation>
<translation id="4067947977115446013">添加有效地址</translation>
@@ -570,6 +578,7 @@
<translation id="4103249731201008433">设备序列号无效</translation>
<translation id="410351446219883937">自动播放</translation>
<translation id="4103763322291513355">请访问 &lt;strong&gt;chrome:// 政策&lt;/strong&gt;,查看列入黑名单的网址列表以及您的系统管理员强制要求执行的其他政策。</translation>
+<translation id="4108231218301530806">下次使用指纹验证此卡片。</translation>
<translation id="4110652170750985508">查看您的付款</translation>
<translation id="4112140312785995938">快退</translation>
<translation id="4116663294526079822">在此网站上始终允许</translation>
@@ -584,6 +593,7 @@
<translation id="4171400957073367226">验证签名无效</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{另外 <ph name="ITEM_COUNT" /> 项}other{另外 <ph name="ITEM_COUNT" /> 项}}</translation>
+<translation id="4176463684765177261">已停用</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> - <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">若想在下次购物时更快捷地付款,请将您的付款卡信息和帐单邮寄地址添加到您的 Google 帐号中。</translation>
<translation id="4196861286325780578">恢复移动(&amp;R)</translation>
@@ -620,6 +630,7 @@
<translation id="4277028893293644418">重置密码</translation>
<translation id="4279811152705618813">您的 <ph name="DEVICE_TYPE" /> 由 <ph name="ENROLLMENT_DOMAIN" /> 管理</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{这张卡已保存到您的 Google 帐号中}other{这些卡已保存到您的 Google 帐号中}}</translation>
+<translation id="428847186335018806">扫描您在 Chrome 中下载或上传的文件。</translation>
<translation id="42981349822642051">展开</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305817255990598646">切换</translation>
@@ -649,7 +660,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">已停用代理,但是指定了明确的代理配置。</translation>
<translation id="445100540951337728">接受的借记卡</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" />可疑行为</translation>
<translation id="4466881336512663640">对表单所做的更改将会丢失。确定要继续吗?</translation>
<translation id="4477350412780666475">下一曲</translation>
<translation id="4482953324121162758">系统不会翻译此网站。</translation>
@@ -676,6 +686,7 @@
<translation id="4594403342090139922">撤消删除(&amp;U)</translation>
<translation id="4597348597567598915">大小:8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="464342062220857295">搜索功能</translation>
<translation id="4646534391647090355">立即前往</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">此服务器无法证明它是<ph name="DOMAIN" />;其安全证书有误。出现此问题的原因可能是配置有误或您的连接被拦截了。</translation>
@@ -684,7 +695,6 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /><ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">您的连接已中断</translation>
-<translation id="471880041731876836">您无权访问此网站</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />运行 Windows 网络诊断<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">重新加载政策</translation>
<translation id="4728558894243024398">平台</translation>
@@ -712,7 +722,6 @@
<translation id="4816492930507672669">适合页面大小</translation>
<translation id="4850886885716139402">视图</translation>
<translation id="4854362297993841467">该递送方式不可用。请另选一种方式。</translation>
-<translation id="4858792381671956233">您已向父母发送请求,询问他们是否允许您访问此网站</translation>
<translation id="4864052566555297930">安全提示:</translation>
<translation id="4876188919622883022">简化版视图</translation>
<translation id="4876305945144899064">无用户名</translation>
@@ -736,7 +745,9 @@
<translation id="4974590756084640048">重新启用警告功能</translation>
<translation id="4984339528288761049">Prc5 (Envelope)</translation>
<translation id="4989163558385430922">查看全部</translation>
+<translation id="4989542687859782284">不受支持的实验</translation>
<translation id="4989809363548539747">该插件不受支持</translation>
+<translation id="4995216769782533993">要将银行卡的详细信息分享给此网站,请先确认安全码</translation>
<translation id="5002932099480077015">如果您选中此项,Chrome 会将您的卡的副本存储在此设备上,以加快表单填写速度。</translation>
<translation id="5015510746216210676">设备名称:</translation>
<translation id="5017554619425969104">您复制的文字</translation>
@@ -765,6 +776,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 位)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">验证您的银行卡</translation>
<translation id="5135404736266831032">管理地址…</translation>
<translation id="5138227688689900538">收起</translation>
<translation id="5141240743006678641">使用您的 Google 凭据加密已同步的密码</translation>
@@ -791,6 +803,7 @@
<translation id="5251803541071282808">云端</translation>
<translation id="5252000469029418751">C7 (Envelope)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">在整个系统范围内应用的功能只能由所有者 <ph name="OWNER_EMAIL" /> 设定</translation>
<translation id="5273658854610202413">警告:系统未按照 PolicyDictionaryMultipleSourceMergeList 政策中指定的方式合并此政策,因为此政策不是可合并的字典政策的一部分。</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">结束</translation>
@@ -814,7 +827,6 @@
<translation id="536296301121032821">无法存储策略设置</translation>
<translation id="5371425731340848620">更新信用卡</translation>
<translation id="5377026284221673050">“您的时钟慢了”、“您的时钟快了”或“&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;”</translation>
-<translation id="5377179979757081683">此页面可能会试图诱骗您、窃取个人信息或损害您的设备。切勿轻易输入个人信息或打开下载的文件。</translation>
<translation id="5384855140246857529">要在所有设备上使用您的卡,请登录您的帐号并开启同步功能。</translation>
<translation id="5386426401304769735">此网站的证书链包含使用 SHA-1 签署的证书。</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -828,6 +840,7 @@
<translation id="5457113250005438886">无效</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" />以及另外 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 名联系人}other{<ph name="CONTACT_PREVIEW" />以及另外 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 名联系人}}</translation>
<translation id="5470861586879999274">恢复修改(&amp;R)</translation>
+<translation id="5473728911100096288">启用这些功能即表示您将使用已被弃用的功能。后续版本将不再包含这些功能。</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
<translation id="5481076368049295676">此内容可能会试图在您的设备上安装危险的软件来窃取或删除您的信息。<ph name="BEGIN_LINK" />仍然显示<ph name="END_LINK" /></translation>
<translation id="54817484435770891">添加有效地址</translation>
@@ -851,7 +864,6 @@
<translation id="5570825185877910964">保护帐号</translation>
<translation id="5571083550517324815">无法从此地址取货。请另选一个地址。</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{目前使用了 1 个}other{目前使用了 # 个}})</translation>
-<translation id="5572851009514199876">请启动并登录 Chrome,以便 Chrome 能够检查您是否可以访问此网站。</translation>
<translation id="5580958916614886209">请检查您的信用卡到期月份,然后重试</translation>
<translation id="5586446728396275693">没有已保存的地址</translation>
<translation id="5595485650161345191">修改地址</translation>
@@ -859,6 +871,7 @@
<translation id="560412284261940334">不支持管理</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">此网站可能是虚假或欺诈性网站。Chrome 建议您立即离开。</translation>
<translation id="5610142619324316209">检查网络连接</translation>
<translation id="5610807607761827392">您可以在<ph name="BEGIN_LINK" />设置<ph name="END_LINK" />中管理信用卡和地址信息。</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> 将您重定向的次数过多。</translation>
@@ -882,11 +895,11 @@
<translation id="5720705177508910913">当前用户</translation>
<translation id="5728056243719941842">C5 (Envelope)</translation>
<translation id="5730040223043577876">如果您在其他网站上重复使用了您的密码,Chrome 建议您重置该密码。</translation>
-<translation id="5732392974455271431">您的父母可为您取消屏蔽此网站</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{将这张卡保存在您的 Google 帐号中}other{将这些卡保存在您的 Google 帐号中}}</translation>
<translation id="5763042198335101085">请输入有效的电子邮件地址</translation>
<translation id="5765072501007116331">要查看递送方式和要求,请选择相应地址</translation>
<translation id="5778550464785688721">完全控制 MIDI 设备</translation>
+<translation id="5781136890105823427">已启用实验</translation>
<translation id="578305955206182703">琥珀色</translation>
<translation id="57838592816432529">静音</translation>
<translation id="5784606427469807560">确认您的信用卡时出现问题。请检查您的互联网连接,然后重试。</translation>
@@ -903,13 +916,16 @@
<translation id="5860033963881614850">关闭</translation>
<translation id="5863847714970149516">即将进入的页面可能会向您收取费用</translation>
<translation id="5866257070973731571">添加电话号码</translation>
+<translation id="5866898949289125849">您当前查看的是一个开发者工具页面</translation>
<translation id="5869405914158311789">无法访问此网站</translation>
<translation id="5869522115854928033">已保存的密码</translation>
<translation id="5887400589839399685">已保存卡片</translation>
<translation id="5893752035575986141">接受信用卡。</translation>
+<translation id="5895138241574237353">重新启动</translation>
<translation id="5901630391730855834">黄色</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" />(已同步)</translation>
<translation id="5916664084637901428">启用</translation>
+<translation id="59174027418879706">已启用</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">将银行卡信息保存到 Google 帐号中?</translation>
<translation id="5922853866070715753">即将完成</translation>
@@ -943,6 +959,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">在您的所有设备上使用您的卡?</translation>
<translation id="6059925163896151826">USB 设备</translation>
+<translation id="6060009363608157444">DnsOverHttps 模式无效。</translation>
<translation id="6080696365213338172">您已使用管理员提供的证书访问了内容,因此管理员可以拦截您提供给 <ph name="DOMAIN" /> 的数据。</translation>
<translation id="6094273045989040137">注释</translation>
<translation id="610911394827799129">您的 Google 帐号在 <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 上可能有其他形式的浏览记录</translation>
@@ -990,13 +1007,12 @@
<translation id="6404511346730675251">修改书签</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
<translation id="6410264514553301377">请输入“<ph name="CREDIT_CARD" />”的到期日期和银行卡验证码 (CVC)</translation>
-<translation id="6414888972213066896">您已向父亲/母亲发送请求,询问其是否允许您访问此网站</translation>
<translation id="6415778972515849510">Chromium 可以帮助您保护您的 Google 帐号和更改密码。</translation>
-<translation id="6417515091412812850">无法检查证书是否已吊销。</translation>
<translation id="6431585503458005759">不存储</translation>
<translation id="6433490469411711332">修改联系信息</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> 拒绝了我们的连接请求。</translation>
<translation id="6434309073475700221">放弃</translation>
+<translation id="6435221585574090192">与您的管理员分享 Chrome 企业版威胁防护功能所报告的安全性事件的相关数据。这些数据可能包括页面网址、文件名、文件元数据、您的设备用户名和 Chrome 用户名。</translation>
<translation id="6440503408713884761">已忽略</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
<translation id="6446608382365791566">添加更多信息</translation>
@@ -1005,20 +1021,19 @@
<translation id="6465306955648956876">管理密码…</translation>
<translation id="647261751007945333">设备政策</translation>
<translation id="6476284679642588870">管理付款方式</translation>
-<translation id="6477321094435799029">Chrome 在此网页上检测到了异常代码。为保护您的个人信息(例如密码、电话号码和信用卡信息),Chrome 已将该网页拦截。</translation>
<translation id="6489534406876378309">开始上传崩溃数据</translation>
<translation id="6499038740797743453">重置密码?</translation>
<translation id="6507833130742554667">接受信用卡和借记卡。</translation>
<translation id="650855688985305916">存储</translation>
<translation id="6508722015517270189">重新启动 Chrome</translation>
<translation id="6517596291481585650">警告:系统未按照相关政策中指定的方式将此政策合并为列表,因为此政策不是一个列表。</translation>
+<translation id="6518133107902771759">验证</translation>
<translation id="6521745193039995384">无效</translation>
<translation id="6529602333819889595">恢复删除(&amp;R)</translation>
<translation id="6534179046333460208">实物网建议</translation>
<translation id="6545864417968258051">蓝牙扫描</translation>
<translation id="6554795675067793129">您的帐号由 <ph name="ENROLLMENT_DOMAIN" /> 管理。</translation>
<translation id="6556866813142980365">重做</translation>
-<translation id="6563469144985748109">您的管理员尚未批准此网站</translation>
<translation id="6569060085658103619">您正在查看扩展程序页面</translation>
<translation id="6578796323535178455">C2 (Envelope)</translation>
<translation id="6579990219486187401">浅粉色</translation>
@@ -1036,11 +1051,13 @@
<translation id="6643016212128521049">清除</translation>
<translation id="6644283850729428850">此政策已弃用。</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{无}=1{来自 1 个网站(这不会致使您退出自己的 Google 帐号)}other{来自 # 个网站(这不会致使您退出自己的 Google 帐号)}}</translation>
+<translation id="6652101503459149953">使用 Windows Hello</translation>
<translation id="6657585470893396449">密码</translation>
<translation id="6670613747977017428">返回到安全网页。</translation>
<translation id="6671697161687535275">要从 Chromium 中移除表单填写建议吗?</translation>
<translation id="6685834062052613830">请退出并完成设置</translation>
<translation id="6689271823431384964">Chrome 正在询问是否要将卡保存到您的 Google 帐号中,因为您已登录。您可在“设置”中更改此行为。持卡人姓名来自您的帐号。</translation>
+<translation id="6707256370811247129">扫描您在 Chrome 中下载或上传的缓存和文件的内容。</translation>
<translation id="6710213216561001401">上一个</translation>
<translation id="6710594484020273272">&lt;输入搜索字词&gt;</translation>
<translation id="671076103358959139">注册令牌:</translation>
@@ -1048,10 +1065,10 @@
<translation id="6738516213925468394">您的数据已于 <ph name="TIME" />使用您的<ph name="BEGIN_LINK" />同步密码<ph name="END_LINK" />加密。输入该密码即可开始同步。</translation>
<translation id="674375294223700098">未知的服务器证书错误。</translation>
<translation id="6744009308914054259">在等待连接时,您可以前往“下载内容”页面阅读离线文章。</translation>
+<translation id="6747611005629681221">警告:您所要使用的功能已被弃用!</translation>
<translation id="6753269504797312559">政策值</translation>
<translation id="6757797048963528358">您的设备已进入休眠模式。</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
-<translation id="6778737459546443941">您的父亲/母亲尚未批准此网站</translation>
<translation id="67862343314499040">紫罗兰色</translation>
<translation id="6786747875388722282">扩展程序</translation>
<translation id="6790428901817661496">播放</translation>
@@ -1059,6 +1076,7 @@
<translation id="681021252041861472">必填字段</translation>
<translation id="6810899417690483278">自定义 ID</translation>
<translation id="6825578344716086703">您尝试访问的是 <ph name="DOMAIN" />,但是服务器出示的证书是使用弱签名算法(例如 SHA-1)签署的。这意味着服务器出示的安全凭据可能是伪造的,因此这可能并不是您想要访问的服务器(您可能正在与攻击者进行通信)。</translation>
+<translation id="6826370046007623921">数据泄露防护</translation>
<translation id="6831043979455480757">翻译</translation>
<translation id="6839929833149231406">地域</translation>
<translation id="6852204201400771460">要重新加载应用吗?</translation>
@@ -1071,7 +1089,6 @@
<translation id="6891596781022320156">政策级别不受支持。</translation>
<translation id="6895330447102777224">已确认您的信用卡</translation>
<translation id="6897140037006041989">用户代理</translation>
-<translation id="6903319715792422884">您可以选择向 Google 发送一些<ph name="BEGIN_WHITEPAPER_LINK" />系统信息和网页内容<ph name="END_WHITEPAPER_LINK" />,以帮助我们改进安全浏览功能。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">用户:</translation>
<translation id="6934672428414710184">此名称来自您的 Google 帐号</translation>
<translation id="6944692733090228304">您在一个不受 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 管理的网站上输入了您的密码。为了保护您的帐号,请不要在其他应用和网站上重复使用您的密码。</translation>
@@ -1116,6 +1133,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" />以及另外 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> 种付款方式}other{<ph name="PAYMENT_METHOD_PREVIEW" />以及另外 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> 种付款方式}}</translation>
<translation id="7153618581592392745">薰衣草色</translation>
<translation id="717330890047184534">GAIA ID:</translation>
+<translation id="7174545416324379297">已合并</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" />以及另外 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 种送货方式}other{<ph name="SHIPPING_OPTION_PREVIEW" />以及另外 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 种送货方式}}</translation>
<translation id="7177397715882417099">您要访问的服务器 <ph name="ORIGIN" /> 已请求将一项安全政策应用于向其发出的所有请求。但该服务器并未提供任何政策,而是将浏览器重定向到了别处,这会阻止浏览器满足您对 <ph name="SITE" /> 的访问请求。</translation>
<translation id="7179323680825933600">保存并填写付款方式</translation>
@@ -1150,6 +1168,7 @@
<translation id="7320336641823683070">与连接相关的帮助</translation>
<translation id="733354035281974745">设备本地帐号替换</translation>
<translation id="7334320624316649418">恢复顺序调整(&amp;R)</translation>
+<translation id="7337706099755338005">在您的平台上不可用。</translation>
<translation id="733923710415886693">该服务器的证书未通过证书透明度政策进行披露。</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">有无关联:</translation>
@@ -1181,7 +1200,6 @@
<translation id="7440140511386898319">离线浏览</translation>
<translation id="7441627299479586546">策略主题有误</translation>
<translation id="7442725080345379071">浅橙色</translation>
-<translation id="7444046173054089907">此网站已被屏蔽</translation>
<translation id="7445762425076701745">无法完全验证您所连接到的服务器的身份。您在连接服务器时使用的服务器名称仅在您的网络中有效,而外部证书授权中心无法验证该名称的所有权。由于一些证书授权中心仍然会为这些名称颁发证书,因此无法确保您连接到想要访问的网站而不是攻击网站。</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />详细了解<ph name="END_LINK" />此问题。</translation>
<translation id="7455133967321480974">使用全局默认设置(阻止)</translation>
@@ -1203,9 +1221,9 @@
<translation id="7538364083937897561">A2 (Envelope)</translation>
<translation id="7542403920425041731">一旦您予以确认,系统便会将您的信用卡详情共享给此网站。</translation>
<translation id="7542995811387359312">由于该表单不使用安全连接,因此自动填写信用卡信息的功能已停用。</translation>
-<translation id="7543525346216957623">请先征得您父亲/母亲的许可</translation>
<translation id="7548892272833184391">修正网络连接错误</translation>
<translation id="7549584377607005141">此网页需要使用您之前输入的数据才能正常显示。您可以重新发送这些数据,不过,这么做会重复执行此网页之前执行过的所有操作。</translation>
+<translation id="7550637293666041147">您的设备用户名和 Chrome 用户名</translation>
<translation id="7552846755917812628">请尝试按以下提示操作:</translation>
<translation id="7554791636758816595">新标签页</translation>
<translation id="7564049878696755256">您可能会无法再访问自己的 <ph name="ORG_NAME" /> 帐号,或者身份信息遭到盗用。Chrome 建议您立即更改密码。</translation>
@@ -1220,6 +1238,7 @@
<translation id="7610193165460212391">值超出了范围 (<ph name="VALUE" />)。</translation>
<translation id="7613889955535752492">过期时间:<ph name="EXPIRATION_YEAR" /> 年 <ph name="EXPIRATION_MONTH" /> 月</translation>
<translation id="7615602087246926389">您已经使用不同版本的 Google 帐号密码加密了数据。请在下方输入。</translation>
+<translation id="7625784245512586808">Chrome 企业版威胁防护</translation>
<translation id="7633909222644580952">性能数据和崩溃报告</translation>
<translation id="7637571805876720304">要从 Chromium 中移除信用卡吗?</translation>
<translation id="7638605456503525968">串行端口</translation>
@@ -1232,7 +1251,6 @@
<translation id="7668654391829183341">未知设备</translation>
<translation id="7669271284792375604">此网站上的攻击者可能会试图诱骗您安装有损浏览体验的程序(例如:通过更改您的主页或在您访问的网站上显示额外的广告)。</translation>
<translation id="7676643023259824263">搜索剪贴板上的文字:<ph name="TEXT" /></translation>
-<translation id="7679176406634891508">平台和云端</translation>
<translation id="7681101578153515023">更改搜索引擎</translation>
<translation id="7682287625158474539">送货地址</translation>
<translation id="7687186412095877299">在付款表单中填入已保存的付款方式</translation>
@@ -1247,7 +1265,6 @@
<translation id="7723047071702270851">修改支付卡</translation>
<translation id="774634243536837715">危险内容已被拦截。</translation>
<translation id="7752995774971033316">非托管</translation>
-<translation id="7755287808199759310">您的父亲/母亲可为您取消屏蔽此网站</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">防火墙或防病毒软件可能已阻止您连接到网络。</translation>
<translation id="7759163816903619567">显示网域:</translation>
@@ -1291,7 +1308,6 @@
<translation id="8004582292198964060">浏览器</translation>
<translation id="8009225694047762179">管理密码</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{这张卡及其帐单邮寄地址将被保存。登录 <ph name="USER_EMAIL" /> 后即可使用这张卡。}other{这些卡及其帐单邮寄地址将被保存。登录 <ph name="USER_EMAIL" /> 后即可使用这些卡。}}</translation>
-<translation id="8012647001091218357">我们暂时无法与您父母取得联系,请重试。</translation>
<translation id="8025119109950072390">此网站上的攻击者可能会诱骗您做出一些诸如安装软件或泄露个人信息(例如:密码、电话号码或信用卡信息)之类的危险事情。</translation>
<translation id="8034522405403831421">此网页的源语言为<ph name="SOURCE_LANGUAGE" />,要将其翻译成<ph name="TARGET_LANGUAGE" />吗?</translation>
<translation id="8035152190676905274">钢笔</translation>
@@ -1302,6 +1318,7 @@
<translation id="8041940743680923270">使用全局默认设置(询问)</translation>
<translation id="8042918947222776840">选择取货方式</translation>
<translation id="8057711352706143257">“<ph name="SOFTWARE_NAME" />”的配置有误。卸载“<ph name="SOFTWARE_NAME" />”通常可解决此问题。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">从现在起您无需再输入银行卡的安全码了</translation>
<translation id="8066955247577885446">抱歉,出了点问题。</translation>
<translation id="8074253406171541171">10x13 (Envelope)</translation>
<translation id="8078141288243656252">无法在旋转后添加注释</translation>
@@ -1332,6 +1349,7 @@
<translation id="8211406090763984747">连接是安全的</translation>
<translation id="8218327578424803826">分配的位置:</translation>
<translation id="8220146938470311105">C7/C6 (Envelope)</translation>
+<translation id="8220639454292072926">企业版报告</translation>
<translation id="8225771182978767009">设置此计算机的用户已选择屏蔽此网站。</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />、<ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">在新的无痕式标签页中打开网页</translation>
@@ -1386,24 +1404,24 @@
<translation id="8508648098325802031">搜索图标</translation>
<translation id="8522552481199248698">Chrome 可以帮助您保护您的 Google 帐号和更改密码。</translation>
<translation id="8543181531796978784">您可以<ph name="BEGIN_ERROR_LINK" />报告检测问题<ph name="END_ERROR_LINK" />;或者,如果您了解自己将面临的安全风险,则可以<ph name="BEGIN_LINK" />访问这个不安全的网站<ph name="END_LINK" />。</translation>
-<translation id="8543556556237226809">有问题?请与负责监管您的个人资料的人员联系。</translation>
<translation id="8553075262323480129">系统无法确定该网页的语言,因此无法进行翻译。</translation>
<translation id="8557066899867184262">银行卡验证码 (CVC) 位于银行卡背面。</translation>
<translation id="8559762987265718583">您设备的日期和时间(<ph name="DATE_AND_TIME" />)不正确,因此无法与 <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> 建立私密连接。</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" />可疑网站</translation>
<translation id="8564985650692024650">如果您在其他网站上重复使用了您的 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 密码,Chromium 建议您重置该密码。</translation>
<translation id="8571890674111243710">正在将网页翻译成<ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">添加电话号码
</translation>
-<translation id="859285277496340001">证书未指定用于检查是否已吊销证书的机制。</translation>
<translation id="860043288473659153">持卡人姓名</translation>
<translation id="861775596732816396">大小:4</translation>
-<translation id="8620436878122366504">您的父母尚未批准此请求</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">将此卡的信息保存到该设备</translation>
<translation id="8626112503828625890">要将帐单明细存储在 Google 帐号中吗?</translation>
+<translation id="8647750283161643317">全部重置为默认值</translation>
<translation id="8663226718884576429">订单摘要,<ph name="TOTAL_LABEL" />,更多详情</translation>
<translation id="8680536109547170164"><ph name="QUERY" />,答案,<ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">可用</translation>
<translation id="8703575177326907206">您与 <ph name="DOMAIN" /> 的连接未加密。</translation>
<translation id="8718314106902482036">未能完成付款</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />,<ph name="DESCRIPTION" />,搜索建议</translation>
@@ -1414,6 +1432,7 @@
<translation id="8738058698779197622">要建立安全连接,您的时钟设置必须正确。这是因为,网站用于证明身份的证书仅在特定时间段有效。由于您设备的时钟不正确,因此 Chromium 无法验证这些证书。</translation>
<translation id="8740359287975076522">无法找到 <ph name="HOST_NAME" /> 的 &lt;abbr id="dnsDefinition"&gt;DNS 地址&lt;/abbr&gt;。正在诊断该问题。</translation>
<translation id="874846938927089722">接受的信用卡和预付卡</translation>
+<translation id="874918643257405732">为此标签页添加书签</translation>
<translation id="8759274551635299824">此信用卡已失效</translation>
<translation id="8761567432415473239">Google安全浏览功能最近在<ph name="SITE" />上<ph name="BEGIN_LINK" />发现了有害程序<ph name="END_LINK" />。</translation>
<translation id="8763927697961133303">USB 设备</translation>
@@ -1443,6 +1462,7 @@
<translation id="8938939909778640821">接受的信用卡和预付卡</translation>
<translation id="8943282376843390568">绿黄色</translation>
<translation id="8957210676456822347">强制门户授权</translation>
+<translation id="8962950042226115166">可疑网站</translation>
<translation id="8968766641738584599">保存卡片</translation>
<translation id="8971063699422889582">服务器的证书已过期。</translation>
<translation id="8975012916872825179">包括电话号码、电子邮件地址和送货地址等信息</translation>
@@ -1465,24 +1485,24 @@
<translation id="9035022520814077154">安全错误</translation>
<translation id="9038649477754266430">使用联想查询服务更快速地加载网页</translation>
<translation id="9039213469156557790">而且,此页中包含其他不安全的资源。他人能在这些资源传输过程中进行查看,而攻击者可以修改这些资源,从而改变此页的行为。</translation>
+<translation id="9044359186343685026">使用 Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">您试图访问 <ph name="DOMAIN" />,但服务器提供的证书无效。</translation>
<translation id="9050666287014529139">密码</translation>
<translation id="9065203028668620118">编辑</translation>
<translation id="9065745800631924235">在历史记录中搜索<ph name="TEXT" /></translation>
<translation id="9069693763241529744">已被某款扩展程序阻止</translation>
-<translation id="9076283476770535406">此网站可能包含成人内容</translation>
<translation id="9076630408993835509">此浏览器不由某个公司或其他组织管理。此设备上的活动可能会在 Chrome 外部受管理。<ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">必须提供更多信息</translation>
<translation id="9080712759204168376">订单摘要</translation>
<translation id="9089260154716455634">“非工作时间”政策:</translation>
<translation id="9095388113577226029">更多语言…</translation>
+<translation id="9098981495403789647">您的管理员已在您的浏览器中启用了 Chrome 企业版威胁防护功能。Chrome 企业版威胁防护功能可以访问您的部分数据。</translation>
<translation id="9103872766612412690"><ph name="SITE" /> 通常会使用加密技术来保护您的信息。Chromium 此次尝试连接到 <ph name="SITE" /> 时,此网站发回了异常的错误凭据。这可能是因为有攻击者在试图冒充 <ph name="SITE" />,或 Wi-Fi 登录屏幕中断了此次连接。请放心,您的信息仍然是安全的,因为 Chromium 尚未进行任何数据交换便停止了连接。</translation>
<translation id="9106062320799175032">添加帐单邮寄地址</translation>
<translation id="9114524666733003316">正在确认信用卡…</translation>
<translation id="9128870381267983090">连接到网络</translation>
<translation id="9137013805542155359">显示原始网页</translation>
-<translation id="9137248913990643158">在使用此应用前,请先启动并登录 Chrome。</translation>
<translation id="9141013498910525015">管理地址</translation>
<translation id="9148088599418889305">选择送货方式</translation>
<translation id="9148507642005240123">撤消修改(&amp;U)</translation>
diff --git a/chromium/components/strings/components_strings_zh-TW.xtb b/chromium/components/strings/components_strings_zh-TW.xtb
index d1017f8dbc1..f1c8c34dc99 100644
--- a/chromium/components/strings/components_strings_zh-TW.xtb
+++ b/chromium/components/strings/components_strings_zh-TW.xtb
@@ -22,6 +22,7 @@
<translation id="1086953900555227778">Index-5x8</translation>
<translation id="1088860948719068836">新增持卡人姓名</translation>
<translation id="1089439967362294234">變更密碼</translation>
+<translation id="1096545575934602868">這個欄位最多只能包含 <ph name="MAX_ITEMS_LIMIT" /> 個項目,其餘將會捨棄。</translation>
<translation id="109743633954054152">在 Chrome 設定中管理密碼</translation>
<translation id="1103523840287552314">一律翻譯<ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">勾選後,Chrome 會在這個裝置上儲存您的信用卡複本,以便更快填寫資訊。</translation>
@@ -37,6 +38,7 @@
<translation id="1152921474424827756">存取 <ph name="URL" /> 的<ph name="BEGIN_LINK" />頁庫存檔副本<ph name="END_LINK" /></translation>
<translation id="1156303062776767266">目前查看的是本機檔案或共用檔案</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> 意外中斷連線。</translation>
+<translation id="115926840831309955">請檢查你的信用卡安全碼或更新到期日,然後再試一次</translation>
<translation id="1161325031994447685">重新連線至 Wi-Fi 網路</translation>
<translation id="1165039591588034296">錯誤</translation>
<translation id="1175364870820465910">列印(&amp;P)...</translation>
@@ -69,7 +71,9 @@
<translation id="1292701964462482250">「你的電腦上有軟體阻止 Chrome 建立安全的網路連線」(僅限 Windows 電腦)</translation>
<translation id="1294154142200295408">命令列變化版本</translation>
<translation id="129553762522093515">最近關閉的分頁</translation>
+<translation id="1298536327547837046">惡意軟體掃描</translation>
<translation id="129863573139666797"><ph name="BEGIN_LINK" />試試看清除 Cookie<ph name="END_LINK" /></translation>
+<translation id="1307966114820526988">已淘汰的功能</translation>
<translation id="1320233736580025032">Prc1 (信封)</translation>
<translation id="132301787627749051">搜尋剪貼簿圖片</translation>
<translation id="1323433172918577554">顯示完整清單</translation>
@@ -117,6 +121,7 @@
<translation id="1521655867290435174">Google 試算表</translation>
<translation id="1527263332363067270">正在等待連線…</translation>
<translation id="1529521330346880926">10x15 (信封)</translation>
+<translation id="1530707389502320859">你剛才嘗試造訪的網站可能是假網站。攻擊者有時會在網址中加入難以辨識的細微變更來仿冒網站。</translation>
<translation id="1531205177818805254">Exec</translation>
<translation id="1532118530259321453">這個網頁顯示</translation>
<translation id="153384715582417236">暫無內容</translation>
@@ -157,7 +162,6 @@
<translation id="1710259589646384581">作業系統</translation>
<translation id="1715874602234207">F</translation>
<translation id="1718029547804390981">文件過大,無法加註</translation>
-<translation id="1721312023322545264">你必須獲得<ph name="NAME" />授權,才能造訪這個網站</translation>
<translation id="1721424275792716183">* 這是必填欄位</translation>
<translation id="1727741090716970331">新增有效的信用卡號碼</translation>
<translation id="1728677426644403582">目前顯示的是網頁原始碼</translation>
@@ -181,6 +185,7 @@
<translation id="1822540298136254167">你造訪的網站和瀏覽時間</translation>
<translation id="1826516787628120939">檢查中</translation>
<translation id="1834321415901700177">這個網站含有有害程式</translation>
+<translation id="1838374766361614909">清除搜尋</translation>
<translation id="1839551713262164453">發生錯誤,政策值驗證失敗</translation>
<translation id="1842969606798536927">支付</translation>
<translation id="1871208020102129563">Proxy 設定為使用固定的 Proxy 伺服器,而非 .pac 指令碼網址。</translation>
@@ -191,6 +196,7 @@
<translation id="1883255238294161206">收合清單</translation>
<translation id="1898423065542865115">篩選</translation>
<translation id="1914326953223720820">解壓縮服務</translation>
+<translation id="1915697529809968049">要使用 Touch ID 取代信用卡安全碼嗎?</translation>
<translation id="1916770123977586577">如要將你更新過的設定套用到這個網站,請重新載入這個網頁</translation>
<translation id="1919345977826869612">廣告</translation>
<translation id="1919367280705858090">瞭解如何修正特定錯誤訊息指出的錯誤</translation>
@@ -202,6 +208,7 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> 書籤</translation>
<translation id="1973335181906896915">序列化錯誤</translation>
<translation id="1974060860693918893">進階</translation>
+<translation id="1974883374937189061"><ph name="BEGIN_WHITEPAPER_LINK" />將你造訪的部分網頁網址、特定的系統資訊以及部分網頁內容<ph name="END_WHITEPAPER_LINK" />傳送給 Google,協助改善 Chrome 的安全性。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="1978555033938440688">韌體版本</translation>
<translation id="1981206234434200693">清除 Chrome 的瀏覽記錄資料</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{以及另外 1 個應用程式}other{以及另外 # 個應用程式}}</translation>
@@ -247,10 +254,12 @@
<translation id="2202020181578195191">請輸入有效的到期年份</translation>
<translation id="2212735316055980242">找不到政策</translation>
<translation id="2213606439339815911">正在擷取項目...</translation>
+<translation id="2215727959747642672">檔案編輯</translation>
<translation id="2218879909401188352">目前在 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 上的攻擊者可能會讓你安裝不安全的應用程式,導致裝置受損、手機帳單中多出隱藏費用,或是個人資訊遭竊。<ph name="BEGIN_LEARN_MORE_LINK" />瞭解詳情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">沒有網際網路連線</translation>
<translation id="2230458221926704099">請使用<ph name="BEGIN_LINK" />診斷應用程式<ph name="END_LINK" />修正連線問題</translation>
<translation id="2239100178324503013">立即傳送</translation>
+<translation id="2248949050832152960">使用 WebAuthn</translation>
<translation id="225207911366869382">這個政策值已遭汰換。</translation>
<translation id="2257315177824333709">很抱歉,目前無法儲存你的卡片</translation>
<translation id="2262243747453050782">HTTP 錯誤</translation>
@@ -298,7 +307,6 @@
<translation id="2479410451996844060">無效的搜尋網址。</translation>
<translation id="2482878487686419369">通知</translation>
<translation id="248348093745724435">裝置政策</translation>
-<translation id="2485387744899240041">你在裝置和瀏覽器中的使用者名稱</translation>
<translation id="2491120439723279231">伺服器憑證含有錯誤。</translation>
<translation id="2493640343870896922">Letter-Plus</translation>
<translation id="2495083838625180221">JSON 剖析器</translation>
@@ -308,6 +316,7 @@
<translation id="2501278716633472235">返回</translation>
<translation id="2503184589641749290">接受的簽帳金融卡和預付卡</translation>
<translation id="2505268675989099013">保護帳戶</translation>
+<translation id="2515335152965840738">忽略</translation>
<translation id="2515629240566999685">檢查所在位置的網路訊號</translation>
<translation id="2523886232349826891">僅儲存在這部裝置</translation>
<translation id="2524461107774643265">新增詳細資訊</translation>
@@ -332,7 +341,6 @@
<translation id="2653659639078652383">提交</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{無}=1{有 1 組密碼 (<ph name="DOMAIN_LIST" />)}=2{有 2 組密碼 (<ph name="DOMAIN_LIST" />)}other{有 # 組密碼 (<ph name="DOMAIN_LIST" />)}}</translation>
<translation id="2666117266261740852">關閉其他分頁或應用程式</translation>
-<translation id="267371737713284912">按下 <ph name="MODIFIER_KEY_DESCRIPTION" /> 即可復原</translation>
<translation id="2674170444375937751">確定要從你的記錄中刪除這些網頁嗎?</translation>
<translation id="2676271551327853224">Roc-8K</translation>
<translation id="2677748264148917807">離開</translation>
@@ -342,12 +350,12 @@
<translation id="2704283930420550640">政策值格式不符。</translation>
<translation id="2705137772291741111">已儲存 (快取) 這個網站的複本,但無法讀取。</translation>
<translation id="2709516037105925701">自動填入</translation>
-<translation id="2712173769900027643">要求權限</translation>
<translation id="2713444072780614174">白色</translation>
<translation id="2720342946869265578">鄰近網頁</translation>
<translation id="2721148159707890343">要求成功</translation>
<translation id="2728127805433021124">伺服器憑證是以防護力較弱的簽章演算法進行簽署。</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />執行連線診斷<ph name="END_LINK" /></translation>
+<translation id="2734544361860335147">啟用這些功能可能會造成瀏覽器資料遺失,或導致你的安全性或隱私權面臨威脅。這個瀏覽器的所有使用者都會套用你所啟用的功能。</translation>
<translation id="2735043616039983645">這項政策有多個來源,且來源的值發生衝突!</translation>
<translation id="2738330467931008676">選擇取件地址</translation>
<translation id="2740531572673183784">確定</translation>
@@ -358,16 +366,15 @@
<translation id="2784949926578158345">連線已重設。</translation>
<translation id="2788784517760473862">接受的信用卡</translation>
<translation id="2792012897584536778">這個裝置的系統管理員已設定安全憑證,這些憑證將允許系統管理員檢視你所造訪的網站內容。</translation>
-<translation id="2794233252405721443">網站遭到封鎖</translation>
<translation id="2799020568854403057">你要造訪的網站含有有害的應用程式</translation>
<translation id="2799223571221894425">重新啟動</translation>
<translation id="2803306138276472711">Google 安全瀏覽功能最近在 <ph name="SITE" /> 上<ph name="BEGIN_LINK" />偵測到惡意軟體<ph name="END_LINK" />。即使是平常可以安全使用的網站,有時也會遭到惡意軟體感染。</translation>
+<translation id="2815364696811431560">離開網站</translation>
<translation id="2824775600643448204">網址與搜尋列</translation>
<translation id="2826760142808435982">連線採用 <ph name="CIPHER" /> 加密,並設有 <ph name="KX" /> 金鑰交換機制。</translation>
<translation id="2835170189407361413">清除表單</translation>
<translation id="2847118875340931228">開啟無痕式視窗</translation>
<translation id="2850739647070081192">Invite (信封)</translation>
-<translation id="2851634818064021665">你必須獲得授權,才能造訪這個網站</translation>
<translation id="2856444702002559011">攻擊者可能會試圖從 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 竊取你的資訊 (例如密碼、郵件或信用卡資料)。<ph name="BEGIN_LEARN_MORE_LINK" />瞭解詳情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2881276955470682203">要儲存卡片嗎?</translation>
@@ -392,6 +399,7 @@
<translation id="2985306909656435243">啟用後,Chromium 會將您的信用卡資料儲存在這個裝置上,以加快表單填寫速度。</translation>
<translation id="2985398929374701810">請輸入有效的地址</translation>
<translation id="2986368408720340940">不支援所選的取件方式,請改選其他方式。</translation>
+<translation id="2987034854559945715">找不到相符的功能</translation>
<translation id="2991174974383378012">與網站分享</translation>
<translation id="2991571918955627853">目前無法造訪 <ph name="SITE" />,因為這個網站使用 HSTS。網路錯誤和攻擊行為通常是暫時性的,因此這個網頁可能稍後就會恢復正常狀態。</translation>
<translation id="3005723025932146533">顯示儲存的複本</translation>
@@ -402,6 +410,7 @@
<translation id="3024663005179499861">政策類型有誤</translation>
<translation id="3037605927509011580">糟糕!</translation>
<translation id="3041612393474885105">憑證資訊</translation>
+<translation id="3057676462092457419">目前不支援將 DnsOverHttps 模式設為 <ph name="SECURE_DNS_MODE_SECURE" />,已將模式設為 <ph name="SECURE_DNS_MODE_OFF" />。</translation>
<translation id="3060227939791841287">C9 (信封)</translation>
<translation id="3061707000357573562">修補服務</translation>
<translation id="3064966200440839136">即將離開無痕模式,改為使用外部應用程式付款,要繼續嗎?</translation>
@@ -427,6 +436,7 @@
<translation id="3195213714973468956"><ph name="SERVER_NAME" /> 上的 <ph name="PRINTER_NAME" /></translation>
<translation id="320323717674993345">取消付款</translation>
<translation id="3207960819495026254">已加入書籤</translation>
+<translation id="3209034400446768650">這個頁面可能會產生費用</translation>
<translation id="3225919329040284222">伺服器呈現的憑證與內建的預期條件不符。我們在系統中針對特定高安全性的網站內建了這些預期條件,目的在於保護你的資料安全無虞。</translation>
<translation id="3226128629678568754">按下重新載入按鈕,重新提交載入網頁所需的資料。</translation>
<translation id="3227137524299004712">麥克風</translation>
@@ -434,7 +444,6 @@
<translation id="3229041911291329567">裝置和瀏覽器的版本資訊</translation>
<translation id="323107829343500871">輸入 <ph name="CREDIT_CARD" /> 的信用卡安全碼</translation>
<translation id="3234666976984236645">一律偵測這個網站的重要內容</translation>
-<translation id="3254409185687681395">把此頁加入書籤</translation>
<translation id="3270847123878663523">復原重新排序(&amp;U)</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282497668470633863">新增持卡人姓名</translation>
@@ -444,7 +453,6 @@
<translation id="3320021301628644560">新增帳單地址</translation>
<translation id="3324983252691184275">深紅色</translation>
<translation id="3338095232262050444">安全</translation>
-<translation id="3345135638360864351">無法將您的網站存取要求傳送給<ph name="NAME" />,請再試一次。</translation>
<translation id="3355823806454867987">變更 Proxy 設定...</translation>
<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />不會儲存<ph name="END_EMPHASIS" />下列資訊:
<ph name="BEGIN_LIST" />
@@ -478,18 +486,15 @@
<translation id="3462200631372590220">隱藏詳細資料</translation>
<translation id="3467763166455606212">持卡人姓名為必填項目</translation>
<translation id="3468054117417088249"><ph name="TAB_SWITCH_SUFFIX" />,目前已開啟,依序按下 Tab 鍵和 Enter 鍵即可切換至開啟的分頁</translation>
-<translation id="3479539252931486093">這是未預期的情況嗎?<ph name="BEGIN_LINK" />通知我們<ph name="END_LINK" /></translation>
<translation id="3479552764303398839">現在不要</translation>
<translation id="3484560055331845446">為避免失去 Google 帳戶存取權,Chrome 建議你立即變更密碼。系統會要求你登入帳戶。</translation>
<translation id="3495081129428749620">在
「<ph name="PAGE_TITLE" />」網頁中尋找</translation>
-<translation id="3498215018399854026">我們暫時無法與您的家長聯絡,請再試一次。</translation>
<translation id="3512163584740124171">由於相同政策群組中有其他政策的優先順序更高,因此系統已忽略這項政策。</translation>
<translation id="3528171143076753409">伺服器憑證授權不可靠。</translation>
<translation id="3528485271872257980">深棕色</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{在已同步的裝置上至少有 1 個項目}=1{1 個項目 (在已同步的裝置上還有更多項目)}other{# 個項目 (在已同步的裝置上還有更多項目)}}</translation>
<translation id="3539171420378717834">在這個裝置上保留這張信用卡的複本</translation>
-<translation id="3556433843310711081">你的管理員可以為你解除封鎖這個網站</translation>
<translation id="3566021033012934673">你的連線不是私人連線</translation>
<translation id="3574305903863751447"><ph name="COUNTRY" />,<ph name="STATE" />,<ph name="CITY" /></translation>
<translation id="3576616784287504635"><ph name="SITE" /> 的嵌入式網頁顯示</translation>
@@ -517,6 +522,7 @@
<translation id="3678529606614285348">在新的無痕式視窗中開啟網頁 (Ctrl + Shift + N 鍵)</translation>
<translation id="3679803492151881375">當機報告擷取時間:<ph name="CRASH_TIME" />,報告上傳時間:<ph name="UPLOAD_TIME" /></translation>
<translation id="3681007416295224113">憑證資訊</translation>
+<translation id="3701427423622901115">已確認重設。</translation>
<translation id="3704162925118123524">您可能需要造訪目前所使用網路的登入網頁。</translation>
<translation id="3704609568417268905"><ph name="TIME" />,<ph name="BOOKMARKED" />,<ph name="TITLE" />,<ph name="DOMAIN" /></translation>
<translation id="370665806235115550">載入中…</translation>
@@ -533,6 +539,7 @@
<translation id="3748148204939282805">攻擊者可能會試圖透過 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 誘使你做一些危險行為,例如安裝軟體或提供個人資訊 (包括密碼、電話號碼或信用卡資料)。<ph name="BEGIN_LEARN_MORE_LINK" />瞭解詳情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">伺服器錯誤,翻譯作業失敗。</translation>
<translation id="3759461132968374835">最近沒有收到當機資訊。當機回報功能停用時發生的當機不會列在這裡。</translation>
+<translation id="3760561303380396507">要使用 Windows Hello 取代信用卡安全碼嗎?</translation>
<translation id="3761718714832595332">隱藏狀態</translation>
<translation id="3765032636089507299">安全瀏覽網頁正在建構中。</translation>
<translation id="3778403066972421603">你要將這張信用卡的資訊儲存到你在這個裝置上的 Google 帳戶嗎?</translation>
@@ -542,6 +549,7 @@
<translation id="3789155188480882154">粗細:16</translation>
<translation id="3797522431967816232">Prc3 (信封)</translation>
<translation id="3807873520724684969">已封鎖有害內容。</translation>
+<translation id="3808375843007691220">警告:這是實驗性功能!</translation>
<translation id="3810973564298564668">管理</translation>
<translation id="382518646247711829">如果你使用 Proxy 伺服器...</translation>
<translation id="3828924085048779000">通關密語欄位不得留空。</translation>
@@ -550,11 +558,11 @@
<translation id="3858027520442213535">更新日期和時間</translation>
<translation id="3884278016824448484">裝置識別碼發生衝突</translation>
<translation id="3885155851504623709">教區</translation>
-<translation id="3886446263141354045">你想存取這個網站的要求已傳送給<ph name="NAME" /></translation>
<translation id="3890664840433101773">新增電子郵件地址</translation>
<translation id="3901925938762663762">這張信用卡已過期</translation>
<translation id="3906600011954732550">B5-Extra</translation>
<translation id="3909695131102177774"><ph name="LABEL" />:<ph name="ERROR" /></translation>
+<translation id="3939773374150895049">要使用 WebAuthn 取代信用卡安全碼嗎?</translation>
<translation id="3946209740501886391">一律詢問你是否接受這個網站的要求</translation>
<translation id="3949571496842715403">這個伺服器無法證明所屬網域為 <ph name="DOMAIN" />;其安全性憑證未指定主體別名。這可能是因為設定錯誤,或是有攻擊者攔截你的連線所致。</translation>
<translation id="3949601375789751990">你的瀏覽記錄會顯示在這裡</translation>
@@ -565,11 +573,11 @@
<translation id="3964661563329879394">{COUNT,plural, =0{無}=1{來自 1 個網站 }other{來自 # 個網站 }}</translation>
<translation id="397105322502079400">計算中…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> 遭到封鎖</translation>
+<translation id="3981540111851280311"><ph name="ENROLLMENT_DOMAIN" /> 已為你的瀏覽器啟用 Chrome Enterprise 威脅防護功能。Chrome Enterprise 威脅防護功能可以存取你的部分資料。</translation>
<translation id="3987940399970879459">不到 1 MB</translation>
<translation id="40103911065039147">{URL_count,plural, =1{附近有 1 個網頁}other{附近有 # 個網頁}}</translation>
<translation id="4030383055268325496">復原新增(&amp;U)</translation>
<translation id="4032320456957708163">你的瀏覽器受到 <ph name="ENROLLMENT_DOMAIN" /> 管理</translation>
-<translation id="4034375457890803692">開啟的連結指向你不常造訪的網站。這個連結可能試圖要誤導你。</translation>
<translation id="4058922952496707368">鍵「<ph name="SUBKEY" />」:<ph name="ERROR" /></translation>
<translation id="4067263367174615723">C1 (信封)</translation>
<translation id="4067947977115446013">新增有效的地址</translation>
@@ -582,6 +590,7 @@
<translation id="4103249731201008433">裝置序號無效</translation>
<translation id="410351446219883937">自動播放</translation>
<translation id="4103763322291513355">請前往 &lt;strong&gt;chrome://policy&lt;/strong&gt; 查看列入黑名單的網址清單,以及其他系統管理員強制執行的政策。</translation>
+<translation id="4108231218301530806">下次使用指紋驗證這張卡片。</translation>
<translation id="4110652170750985508">查看您的付款</translation>
<translation id="4112140312785995938">倒轉</translation>
<translation id="4116663294526079822">永遠允許在這個網站執行</translation>
@@ -596,6 +605,7 @@
<translation id="4171400957073367226">驗證簽名無效</translation>
<translation id="4173315687471669144">Foolscap</translation>
<translation id="4173827307318847180">{MORE_ITEMS,plural, =1{還有另外 <ph name="ITEM_COUNT" /> 個項目}other{還有另外 <ph name="ITEM_COUNT" /> 個項目}}</translation>
+<translation id="4176463684765177261">已停用</translation>
<translation id="4179515394835346607"><ph name="ROW_NAME" /> <ph name="ROW_CONTENT" /></translation>
<translation id="4193750898749511769">只要將卡片資訊與帳單地址新增到你的 Google 帳戶中,下次即可更快完成付款程序。</translation>
<translation id="4196861286325780578">重做移動(&amp;R)</translation>
@@ -632,6 +642,7 @@
<translation id="4277028893293644418">重設密碼</translation>
<translation id="4279811152705618813">你的 <ph name="DEVICE_TYPE" /> 是由 <ph name="ENROLLMENT_DOMAIN" /> 管理</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{這張卡片已儲存到你的 Google 帳戶}other{這些卡片已儲存到你的 Google 帳戶}}</translation>
+<translation id="428847186335018806">掃描你透過 Chrome 下載或上傳的檔案。</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4302965934281694568">Chou3 (信封)</translation>
<translation id="4305817255990598646">切換</translation>
@@ -661,7 +672,6 @@
<translation id="4435702339979719576">明信片)</translation>
<translation id="443673843213245140">雖然已停用 Proxy,不過已指定明確 Proxy 設定。</translation>
<translation id="445100540951337728">接受的簽帳金融卡</translation>
-<translation id="4453237654902532092"><ph name="SAFETY_TIP" />可疑行為</translation>
<translation id="4466881336512663640">你對表單所做變更將會遺失。確定要繼續嗎?</translation>
<translation id="4477350412780666475">下一首曲目</translation>
<translation id="4482953324121162758">系統不會翻譯這個網站。</translation>
@@ -688,6 +698,7 @@
<translation id="4594403342090139922">復原刪除(&amp;U)</translation>
<translation id="4597348597567598915">粗細:8</translation>
<translation id="4600854749408232102">C6/C5 (信封)</translation>
+<translation id="464342062220857295">搜尋功能</translation>
<translation id="4646534391647090355">立即前往下載中心</translation>
<translation id="4668929960204016307">,</translation>
<translation id="467662567472608290">伺服器無法證明其屬於 <ph name="DOMAIN" /> 網域;其安全性憑證含有錯誤。這可能是因為設定錯誤,或有攻擊者攔截你的連線所致。</translation>
@@ -696,7 +707,6 @@
<translation id="4691835149146451662">Architecture-A (信封)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">您的連線已中斷</translation>
-<translation id="471880041731876836">你沒有這個網站的瀏覽權限</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />執行 Windows 網路診斷<ph name="END_LINK" /></translation>
<translation id="4726672564094551039">重新載入政策</translation>
<translation id="4728558894243024398">平台</translation>
@@ -724,7 +734,6 @@
<translation id="4816492930507672669">依頁面大小自動調整</translation>
<translation id="4850886885716139402">檢視</translation>
<translation id="4854362297993841467">不支援所選的快遞方式,請改選其他方式。</translation>
-<translation id="4858792381671956233">你已詢問家長是否同意你造訪這個網站</translation>
<translation id="4864052566555297930">安全提示:</translation>
<translation id="4876188919622883022">簡易檢視</translation>
<translation id="4876305945144899064">沒有使用者名稱</translation>
@@ -748,7 +757,9 @@
<translation id="4974590756084640048">重新啟用警告功能</translation>
<translation id="4984339528288761049">Prc5 (信封)</translation>
<translation id="4989163558385430922">查看全部</translation>
+<translation id="4989542687859782284">尚未支援</translation>
<translation id="4989809363548539747">這是不支援的外掛程式</translation>
+<translation id="4995216769782533993">如要與這個網站分享你的卡片資料,請確認安全碼</translation>
<translation id="5002932099480077015">啟用後,Chrome 會將您的信用卡複本儲存在這個裝置上,以加快表單填寫速度。</translation>
<translation id="5015510746216210676">裝置名稱:</translation>
<translation id="5017554619425969104">你複製的文字</translation>
@@ -777,6 +788,7 @@
<translation id="5115216390227830982">European-Edp</translation>
<translation id="5115563688576182185">(64 位元)</translation>
<translation id="5125394840236832993">B-Plus</translation>
+<translation id="5126510351761255129">請驗證卡片</translation>
<translation id="5135404736266831032">管理地址...</translation>
<translation id="5138227688689900538">顯示較少</translation>
<translation id="5141240743006678641">使用你的 Google 憑證對已同步處理的密碼進行加密</translation>
@@ -803,6 +815,7 @@
<translation id="5251803541071282808">雲端</translation>
<translation id="5252000469029418751">C7 (信封)</translation>
<translation id="5254958791078852567">E1</translation>
+<translation id="5269999699920406580">這些功能會套用至整個系統,只有以下擁有者可設定:<ph name="OWNER_EMAIL" /></translation>
<translation id="5273658854610202413">警告:這項政策並非可合併的字典政策,因此未依照 PolicyDictionaryMultipleSourceMergeList 政策中指定的方式進行合併。</translation>
<translation id="5283044957620376778">B1</translation>
<translation id="528468243742722775">結束</translation>
@@ -826,7 +839,6 @@
<translation id="536296301121032821">無法儲存政策設定</translation>
<translation id="5371425731340848620">更新信用卡</translation>
<translation id="5377026284221673050">「你的時鐘時間過慢」、「你的時鐘時間過快」或 「&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;」</translation>
-<translation id="5377179979757081683">這個頁面可能會試圖騙取你的個人資訊或損害裝置。在輸入個人資訊或開啟下載檔案時,請務必格外小心。</translation>
<translation id="5384855140246857529">如要將卡片同步到所有裝置,請登入並開啟同步功能。</translation>
<translation id="5386426401304769735">這個網站的憑證鏈結包含使用 SHA-1 進行簽署的憑證。</translation>
<translation id="538659543871111977">A4-Tab</translation>
@@ -840,6 +852,7 @@
<translation id="5457113250005438886">無效</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{「<ph name="CONTACT_PREVIEW" />」和另外 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 項聯絡資訊}other{「<ph name="CONTACT_PREVIEW" />」和另外 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 項聯絡資訊}}</translation>
<translation id="5470861586879999274">重做編輯(&amp;R)</translation>
+<translation id="5473728911100096288">你啟用的這些功能已遭到淘汰,Chrome 將在日後發布的版本中予以移除。</translation>
<translation id="5478437291406423475">B6/C4 (信封)</translation>
<translation id="5481076368049295676">這項內容可能會試圖在你的裝置上安裝危險軟體,藉此竊取或刪除你的資訊。<ph name="BEGIN_LINK" />仍要顯示<ph name="END_LINK" /></translation>
<translation id="54817484435770891">新增有效的地址</translation>
@@ -863,7 +876,6 @@
<translation id="5570825185877910964">保護帳戶</translation>
<translation id="5571083550517324815">無法在這個地址取件,請改用其他地址。</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{目前使用 1 個 Cookie}other{目前使用 # 個 Cookie}})</translation>
-<translation id="5572851009514199876">請啟動 Chrome 並登入帳戶,Chrome 將確認你是否可存取這個網站。</translation>
<translation id="5580958916614886209">請檢查信用卡到期月份,然後再試一次</translation>
<translation id="5586446728396275693">沒有已儲存的地址</translation>
<translation id="5595485650161345191">編輯地址</translation>
@@ -871,6 +883,7 @@
<translation id="560412284261940334">系統不支援管理</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
+<translation id="5608165884683734521">這可能是偽造的網站或詐騙網站,Chrome 建議你立即離開。</translation>
<translation id="5610142619324316209">檢查連線狀態</translation>
<translation id="5610807607761827392">你可以在<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />中管理信用卡和地址資訊。</translation>
<translation id="5617949217645503996"><ph name="HOST_NAME" /> 將您重新導向的次數過多。</translation>
@@ -894,11 +907,11 @@
<translation id="5720705177508910913">目前使用者</translation>
<translation id="5728056243719941842">C5 (信封)</translation>
<translation id="5730040223043577876">如果你在其他網站上重複使用過你的密碼,Chrome 會建議你重設密碼。</translation>
-<translation id="5732392974455271431">你的家長可以為你解除封鎖這個網站</translation>
<translation id="5737183892635480227">{NUM_CARDS,plural, =1{將卡片儲存到你的 Google 帳戶}other{將卡片儲存到你的 Google 帳戶}}</translation>
<translation id="5763042198335101085">請輸入有效的電子郵件地址</translation>
<translation id="5765072501007116331">如要查看快遞方式和相關規定,請選取一個地址</translation>
<translation id="5778550464785688721">MIDI 裝置完整控制</translation>
+<translation id="5781136890105823427">實驗已啟用</translation>
<translation id="578305955206182703">琥珀色</translation>
<translation id="57838592816432529">靜音</translation>
<translation id="5784606427469807560">驗證您的信用卡時發生問題。請檢查網際網路連線,然後再試一次。</translation>
@@ -915,13 +928,16 @@
<translation id="5860033963881614850">關閉</translation>
<translation id="5863847714970149516">你要瀏覽的網頁可能會向你收取費用</translation>
<translation id="5866257070973731571">新增電話號碼</translation>
+<translation id="5866898949289125849">目前查看的是開發人員工具頁面</translation>
<translation id="5869405914158311789">無法連上這個網站</translation>
<translation id="5869522115854928033">已儲存的密碼</translation>
<translation id="5887400589839399685">已儲存卡片</translation>
<translation id="5893752035575986141">接受簽帳金融卡。</translation>
+<translation id="5895138241574237353">重新啟動</translation>
<translation id="5901630391730855834">黃色</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (已同步)</translation>
<translation id="5916664084637901428">開啟</translation>
+<translation id="59174027418879706">已啟用</translation>
<translation id="5919090499915321845">B10</translation>
<translation id="5921639886840618607">要將這張卡片儲存到 Google 帳戶嗎?</translation>
<translation id="5922853866070715753">即將完成</translation>
@@ -955,6 +971,7 @@
<translation id="6052284303005792909">•</translation>
<translation id="6058977677006700226">想在所有裝置上使用你的卡片嗎?</translation>
<translation id="6059925163896151826">USB 裝置</translation>
+<translation id="6060009363608157444">DnsOverHttps 模式無效。</translation>
<translation id="6080696365213338172">你使用了管理員提供的憑證存取內容,因此管理員可攔截你傳送至「<ph name="DOMAIN" />」的資料。</translation>
<translation id="6094273045989040137">註解</translation>
<translation id="610911394827799129">你的 Google 帳戶仍可能保留了其他類型的瀏覽記錄 (可前往 <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 查詢)。</translation>
@@ -1003,13 +1020,12 @@
<translation id="6404511346730675251">編輯書籤</translation>
<translation id="6406765186087300643">C0 (信封)</translation>
<translation id="6410264514553301377">輸入 <ph name="CREDIT_CARD" /> 的到期日和信用卡安全碼</translation>
-<translation id="6414888972213066896">你已詢問家長是否同意你造訪這個網站</translation>
<translation id="6415778972515849510">Chromium 可協助你保護 Google 帳戶並變更密碼。</translation>
-<translation id="6417515091412812850">無法檢查憑證是否已遭撤銷。</translation>
<translation id="6431585503458005759">不要儲存</translation>
<translation id="6433490469411711332">編輯聯絡資訊</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> 拒絕連線。</translation>
<translation id="6434309073475700221">捨棄</translation>
+<translation id="6435221585574090192">將 Chrome Enterprise 威脅防護功能標記的安全性事件相關資料提供給系統管理員。這些資料可能包括網頁網址、檔名、檔案中繼資料、你的裝置使用者名稱和 Chrome 使用者名稱。</translation>
<translation id="6440503408713884761">已忽略</translation>
<translation id="6446163441502663861">Kahu (信封)</translation>
<translation id="6446608382365791566">新增詳細資訊</translation>
@@ -1018,20 +1034,19 @@
<translation id="6465306955648956876">管理密碼...</translation>
<translation id="647261751007945333">裝置政策</translation>
<translation id="6476284679642588870">管理付款方式</translation>
-<translation id="6477321094435799029">Chrome 在這個網頁上偵測到異常代碼。為了保護你的個人資訊 (包括密碼、電話號碼或信用卡資料),Chrome 已封鎖這個網頁。</translation>
<translation id="6489534406876378309">開始上傳當機報告</translation>
<translation id="6499038740797743453">要重設密碼嗎?</translation>
<translation id="6507833130742554667">接受信用卡和簽帳金融卡。</translation>
<translation id="650855688985305916">是,我要儲存</translation>
<translation id="6508722015517270189">重新啟動 Chrome</translation>
<translation id="6517596291481585650">警告:這項政策並非清單,因此未依照政策中指定的方式合併為清單。</translation>
+<translation id="6518133107902771759">驗證</translation>
<translation id="6521745193039995384">未啟用</translation>
<translation id="6529602333819889595">重做刪除(&amp;R)</translation>
<translation id="6534179046333460208">實體化網路建議</translation>
<translation id="6545864417968258051">藍牙掃描</translation>
<translation id="6554795675067793129">你的帳戶是由 <ph name="ENROLLMENT_DOMAIN" /> 管理。</translation>
<translation id="6556866813142980365">重做</translation>
-<translation id="6563469144985748109">你的管理員尚未核准這個網站</translation>
<translation id="6569060085658103619">目前顯示的是擴充功能頁面</translation>
<translation id="6578796323535178455">C2 (信封)</translation>
<translation id="6579990219486187401">淺粉紅色</translation>
@@ -1049,11 +1064,13 @@
<translation id="6643016212128521049">清除</translation>
<translation id="6644283850729428850">這項政策已遭取代。</translation>
<translation id="6646269444027925224">{COUNT,plural, =0{無}=1{1 個網站 (你不會因此登出 Google 帳戶)}other{# 個網站 (你不會因此登出 Google 帳戶)}}</translation>
+<translation id="6652101503459149953">使用 Windows Hello</translation>
<translation id="6657585470893396449">密碼</translation>
<translation id="6670613747977017428">返回安全網頁。</translation>
<translation id="6671697161687535275">要從 Chromium 中移除表單填寫建議嗎?</translation>
<translation id="6685834062052613830">請登出並完成設定程序</translation>
<translation id="6689271823431384964">你已登入帳戶,因此 Chrome 詢問你是否要將卡片儲存至 Google 帳戶。你可以在設定中變更這項行為。持卡人姓名來自你的帳戶。</translation>
+<translation id="6707256370811247129">掃描你透過 Chrome 下載或上傳的快取內容和檔案。</translation>
<translation id="6710213216561001401">返回</translation>
<translation id="6710594484020273272">&lt;輸入搜尋字詞&gt;</translation>
<translation id="671076103358959139">註冊憑證:</translation>
@@ -1061,10 +1078,10 @@
<translation id="6738516213925468394">你在 <ph name="TIME" />已使用<ph name="BEGIN_LINK" />同步通關密語<ph name="END_LINK" />將資料加密。如要開始同步處理資料,請輸入通關密語。</translation>
<translation id="674375294223700098">不明的伺服器憑證錯誤。</translation>
<translation id="6744009308914054259">等待連線的同時,你可以前往「下載」頁面閱讀離線文章。</translation>
+<translation id="6747611005629681221">警告:你要使用的功能已淘汰!</translation>
<translation id="6753269504797312559">政策值</translation>
<translation id="6757797048963528358">您的裝置已進入睡眠模式。</translation>
<translation id="6768213884286397650">Hagaki (明信片)</translation>
-<translation id="6778737459546443941">你的家長尚未核准這個網站</translation>
<translation id="67862343314499040">紫羅蘭色</translation>
<translation id="6786747875388722282">擴充功能</translation>
<translation id="6790428901817661496">播放</translation>
@@ -1072,6 +1089,7 @@
<translation id="681021252041861472">必填欄位</translation>
<translation id="6810899417690483278">自訂 ID</translation>
<translation id="6825578344716086703">你嘗試連上 <ph name="DOMAIN" />,但伺服器的憑證是以防護力薄弱的簽章演算法 (例如 SHA-1) 進行簽署。這代表伺服器提供的安全性憑證可能遭到偽造,而且這個伺服器可能並不是你的目標伺服器 (你的連線對象可能是攻擊者的電腦)。</translation>
+<translation id="6826370046007623921">資料遺失防護</translation>
<translation id="6831043979455480757">翻譯</translation>
<translation id="6839929833149231406">區域</translation>
<translation id="6852204201400771460">要重新載入應用程式嗎?</translation>
@@ -1084,7 +1102,6 @@
<translation id="6891596781022320156">系統不支援這項政策的層級。</translation>
<translation id="6895330447102777224">您的信用卡已通過驗證</translation>
<translation id="6897140037006041989">使用者代理程式</translation>
-<translation id="6903319715792422884">將部分<ph name="BEGIN_WHITEPAPER_LINK" />系統資訊和網頁內容<ph name="END_WHITEPAPER_LINK" />傳送給 Google,協助我們改善安全瀏覽功能。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">使用者:</translation>
<translation id="6934672428414710184">這是你在 Google 帳戶中設定的名稱</translation>
<translation id="6944692733090228304">你在不是由 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 管理的網站上輸入了你的密碼。為確保帳戶安全,請勿在其他應用程式和網站上重複使用你的密碼。</translation>
@@ -1129,6 +1146,7 @@
<translation id="7153549335910886479">{PAYMENT_METHOD,plural, =0{<ph name="PAYMENT_METHOD_PREVIEW" />}=1{<ph name="PAYMENT_METHOD_PREVIEW" /> 和另外 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> 種付款方式}other{<ph name="PAYMENT_METHOD_PREVIEW" /> 和另外 <ph name="NUMBER_OF_ADDITIONAL_PAYMENT_METHODS" /> 種付款方式}}</translation>
<translation id="7153618581592392745">淡紫色</translation>
<translation id="717330890047184534">GAIA ID:</translation>
+<translation id="7174545416324379297">已合併</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" />和另外 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 種選項}other{<ph name="SHIPPING_OPTION_PREVIEW" />和另外 <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> 種選項}}</translation>
<translation id="7177397715882417099">你的目標伺服器「<ph name="ORIGIN" />」要求為其收到的所有要求
套用安全性政策。不過,由於該伺服器
@@ -1166,6 +1184,7 @@
<translation id="7320336641823683070">連線說明</translation>
<translation id="733354035281974745">裝置本機帳戶覆寫</translation>
<translation id="7334320624316649418">重做重新排序(&amp;R)</translation>
+<translation id="7337706099755338005">你的平台無法使用實驗性功能。</translation>
<translation id="733923710415886693">伺服器憑證未依憑證透明化政策公開。</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">是否已建立關聯:</translation>
@@ -1197,7 +1216,6 @@
<translation id="7440140511386898319">探索可供離線檢視的內容</translation>
<translation id="7441627299479586546">政策主體有誤</translation>
<translation id="7442725080345379071">淺橘色</translation>
-<translation id="7444046173054089907">這個網站遭到封鎖</translation>
<translation id="7445762425076701745">你所連線的伺服器身分無法完全驗證,該伺服器所使用的名稱僅在你的網路中有效,無法驗證外部憑證授權單位的擁有權。即使某些憑證授權單位會核發這些憑證,不過無法就此確保你所連上的網站是正確的,而不會遭到網路攻擊。</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />進一步瞭解<ph name="END_LINK" />這個問題。</translation>
<translation id="7455133967321480974">使用全域預設值 (封鎖)</translation>
@@ -1219,9 +1237,9 @@
<translation id="7538364083937897561">A2 (信封)</translation>
<translation id="7542403920425041731">經過你確認後,這個網站就會取得你的信用卡詳細資料。</translation>
<translation id="7542995811387359312">由於這個表單並未採用加密連線方式,所以信用卡自動填入功能已停用。</translation>
-<translation id="7543525346216957623">請徵求家長同意</translation>
<translation id="7548892272833184391">修正連線錯誤</translation>
<translation id="7549584377607005141">這個網頁需要使用你先前輸入的資料才能正確顯示。你可以重新傳送這些資料,不過這麼做會重複執行這個網頁先前執行過的任何動作。</translation>
+<translation id="7550637293666041147">你的裝置使用者名稱和 Chrome 使用者名稱</translation>
<translation id="7552846755917812628">嘗試按照下列提示操作:</translation>
<translation id="7554791636758816595">新增分頁</translation>
<translation id="7564049878696755256">你可能會失去 <ph name="ORG_NAME" /> 帳戶存取權,或身分遭到冒用。Chrome 建議你立即變更密碼。</translation>
@@ -1236,6 +1254,7 @@
<translation id="7610193165460212391">值超出 <ph name="VALUE" /> 的範圍。</translation>
<translation id="7613889955535752492">有效期限:<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7615602087246926389">你已經使用其他版本的「Google 帳戶」密碼對資料進行加密,請在下方輸入密碼。</translation>
+<translation id="7625784245512586808">Chrome Enterprise 威脅防護</translation>
<translation id="7633909222644580952">效能資料和當機報告</translation>
<translation id="7637571805876720304">要從 Chromium 中移除信用卡嗎?</translation>
<translation id="7638605456503525968">序列埠</translation>
@@ -1248,7 +1267,6 @@
<translation id="7668654391829183341">不明的裝置</translation>
<translation id="7669271284792375604">攻擊者可能會試圖透過這個網站誘使你安裝對瀏覽體驗有害 (例如變更你的首頁,或是在你造訪的網站上顯示多餘的廣告) 的程式。</translation>
<translation id="7676643023259824263">搜尋剪貼簿文字:<ph name="TEXT" /></translation>
-<translation id="7679176406634891508">平台和雲端</translation>
<translation id="7681101578153515023">變更搜尋引擎</translation>
<translation id="7682287625158474539">寄送地址</translation>
<translation id="7687186412095877299">在付款表單中填入已儲存的付款方式</translation>
@@ -1263,7 +1281,6 @@
<translation id="7723047071702270851">編輯卡片資訊</translation>
<translation id="774634243536837715">已封鎖危險內容。</translation>
<translation id="7752995774971033316">未管理</translation>
-<translation id="7755287808199759310">你的家長可以為你解除封鎖這個網站</translation>
<translation id="7757555340166475417">Dai-Pa-Kai</translation>
<translation id="7758069387465995638">防火牆或防毒軟體可能封鎖了連線。</translation>
<translation id="7759163816903619567">顯示網域:</translation>
@@ -1307,7 +1324,6 @@
<translation id="8004582292198964060">瀏覽器</translation>
<translation id="8009225694047762179">管理密碼</translation>
<translation id="8012116502927253373">{NUM_CARDS,plural, =1{系統會儲存這張卡片和相應的帳單地址。只要登入 <ph name="USER_EMAIL" /> 即可使用。}other{系統會儲存這些卡片和相應的帳單地址。只要登入 <ph name="USER_EMAIL" /> 即可使用。}}</translation>
-<translation id="8012647001091218357">我們暫時無法與您的家長聯絡,請再試一次。</translation>
<translation id="8025119109950072390">攻擊者可能會試圖透過這個網站誘使你做一些危險的行為,例如安裝軟體或提供個人資訊 (包括密碼、電話號碼或信用卡資料)。</translation>
<translation id="8034522405403831421">這是<ph name="SOURCE_LANGUAGE" />網頁,需要翻譯成<ph name="TARGET_LANGUAGE" />嗎?</translation>
<translation id="8035152190676905274">畫筆</translation>
@@ -1318,6 +1334,7 @@
<translation id="8041940743680923270">使用全域預設值 (要求確認)</translation>
<translation id="8042918947222776840">選擇取件方式</translation>
<translation id="8057711352706143257">「<ph name="SOFTWARE_NAME" />」的設定不正確。通常解除安裝「<ph name="SOFTWARE_NAME" />」即可修正這個問題。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8062224330780487419">從現在起,你再也不必輸入信用卡安全碼</translation>
<translation id="8066955247577885446">抱歉,系統發生錯誤。</translation>
<translation id="8074253406171541171">10x13 (信封)</translation>
<translation id="8078141288243656252">文件旋轉後無法加註</translation>
@@ -1348,6 +1365,7 @@
<translation id="8211406090763984747">已建立安全連線</translation>
<translation id="8218327578424803826">指派的位置:</translation>
<translation id="8220146938470311105">C7/C6 (信封)</translation>
+<translation id="8220639454292072926">企業報告</translation>
<translation id="8225771182978767009">設定這部電腦的使用者選擇封鎖這個網站。</translation>
<translation id="822964464349305906"><ph name="TYPE_1" />、<ph name="TYPE_2" /></translation>
<translation id="8238581221633243064">在新的無痕式分頁中開啟網頁</translation>
@@ -1402,23 +1420,23 @@
<translation id="8508648098325802031">搜尋圖示</translation>
<translation id="8522552481199248698">Chrome 可協助你保護 Google 帳戶並變更密碼。</translation>
<translation id="8543181531796978784">您可以<ph name="BEGIN_ERROR_LINK" />回報偵測問題<ph name="END_ERROR_LINK" />。或者在您瞭解安全性風險後,仍然可以<ph name="BEGIN_LINK" />前往這個不安全的網站<ph name="END_LINK" />。</translation>
-<translation id="8543556556237226809">如有問題,請與你個人資料的監管者聯絡。</translation>
<translation id="8553075262323480129">無法判定網頁的語言,翻譯作業失敗。</translation>
<translation id="8557066899867184262">信用卡安全碼位於信用卡背面。</translation>
<translation id="8559762987265718583">你裝置的日期和時間 (<ph name="DATE_AND_TIME" />) 不正確,因此無法與 <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> 建立私人連線。</translation>
+<translation id="8561575143530093465"><ph name="SAFETY_TIP" />可疑網站</translation>
<translation id="8564985650692024650">如果你在其他網站上重複使用過你的 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 密碼,Chromium 會建議你重設密碼。</translation>
<translation id="8571890674111243710">正在將網頁翻譯成<ph name="LANGUAGE" />...</translation>
<translation id="858637041960032120">新增電話號碼</translation>
-<translation id="859285277496340001">憑證未指定負責檢查其本身是否已遭到撤銷的機制。</translation>
<translation id="860043288473659153">持卡人姓名</translation>
<translation id="861775596732816396">粗細:4</translation>
-<translation id="8620436878122366504">你的家長尚未核准這個網站</translation>
<translation id="8622948367223941507">Legal-Extra</translation>
<translation id="8625384913736129811">將這張信用卡儲存到這個裝置</translation>
<translation id="8626112503828625890">要將帳單詳細資料儲存至 Google 帳戶嗎?</translation>
+<translation id="8647750283161643317">全部重設為預設值</translation>
<translation id="8663226718884576429">訂單摘要:<ph name="TOTAL_LABEL" />,更多詳細資料</translation>
<translation id="8680536109547170164"><ph name="QUERY" />,答案:<ph name="ANSWER" /></translation>
<translation id="8685155993131031756">Prc-16K</translation>
+<translation id="8688672835843460752">可用空間</translation>
<translation id="8703575177326907206">你到 <ph name="DOMAIN" /> 的連線未加密。</translation>
<translation id="8718314106902482036">未完成付款程序</translation>
<translation id="8719263113926255150"><ph name="ENTITY" />,<ph name="DESCRIPTION" />,搜尋建議</translation>
@@ -1429,6 +1447,7 @@
<translation id="8738058698779197622">你必須正確設定時鐘,才能建立安全連線。這是因為網站驗證身分時所使用的憑證僅於特定一段時間內有效。由於你裝置的時鐘不正確,因此 Chromium 無法驗證這些憑證。</translation>
<translation id="8740359287975076522">找不到 <ph name="HOST_NAME" /> 的 &lt;abbr id="dnsDefinition"&gt;DNS 位址&lt;/abbr&gt;,正在診斷問題。</translation>
<translation id="874846938927089722">接受的信用卡和預付卡</translation>
+<translation id="874918643257405732">將此分頁加入書籤</translation>
<translation id="8759274551635299824">這張信用卡已過期</translation>
<translation id="8761567432415473239">Google 安全瀏覽最近在「<ph name="SITE" />」<ph name="BEGIN_LINK" />發現了有害程式<ph name="END_LINK" />。</translation>
<translation id="8763927697961133303">USB 裝置</translation>
@@ -1458,6 +1477,7 @@
<translation id="8938939909778640821">接受的信用卡和預付卡</translation>
<translation id="8943282376843390568">萊姆綠</translation>
<translation id="8957210676456822347">監控式入口網站授權</translation>
+<translation id="8962950042226115166">可疑網站</translation>
<translation id="8968766641738584599">儲存卡片</translation>
<translation id="8971063699422889582">伺服器憑證已過期。</translation>
<translation id="8975012916872825179">包括電話號碼、電子郵件地址和運送地址等資訊</translation>
@@ -1480,24 +1500,24 @@
<translation id="9035022520814077154">安全性錯誤</translation>
<translation id="9038649477754266430">使用預測查詢字串服務,讓系統更快載入網頁</translation>
<translation id="9039213469156557790">此外,這個網頁含有其他不安全的資源。其他人可能會在資源傳輸期間檢視這些資源,攻擊者也可能會修改這些資源,進而變更網頁行為。</translation>
+<translation id="9044359186343685026">使用 Touch ID</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="9049981332609050619">你嘗試連線至 <ph name="DOMAIN" />,但伺服器提供的憑證無效。</translation>
<translation id="9050666287014529139">通關密語</translation>
<translation id="9065203028668620118">編輯</translation>
<translation id="9065745800631924235">「<ph name="TEXT" />」的搜尋記錄</translation>
<translation id="9069693763241529744">依據擴充功能設定封鎖</translation>
-<translation id="9076283476770535406">這個網站可能含有成人內容</translation>
<translation id="9076630408993835509">這個瀏覽器未受到任何公司或其他機構管理。這部裝置上的活動可透過 Chrome 以外的服務管理。<ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation>
<translation id="9078964945751709336">請提供詳細資訊</translation>
<translation id="9080712759204168376">訂單摘要</translation>
<translation id="9089260154716455634">停機時間政策:</translation>
<translation id="9095388113577226029">更多語言...</translation>
+<translation id="9098981495403789647">系統管理員已為你的瀏覽器啟用 Chrome Enterprise 威脅防護功能。Chrome Enterprise 威脅防護功能可以存取你的部分資料。</translation>
<translation id="9103872766612412690"><ph name="SITE" /> 通常使用加密方式保護您的資訊。但 Chromium 這次嘗試連線到 <ph name="SITE" /> 時,該網站傳回了異常且錯誤的憑證。這可能是因為有攻擊者企圖偽裝成 <ph name="SITE" />,或是受到 Wi-Fi 登入畫面影響而造成連線中斷。不過請放心,Chromium 已及時停止連線,並未傳輸任何資料,因此您的資訊仍然安全無虞。</translation>
<translation id="9106062320799175032">新增帳單地址</translation>
<translation id="9114524666733003316">正在驗證信用卡...</translation>
<translation id="9128870381267983090">連線至網路</translation>
<translation id="9137013805542155359">顯示原文</translation>
-<translation id="9137248913990643158">使用這個應用程式前,請先啟動 Chrome 並登入帳戶。</translation>
<translation id="9141013498910525015">管理地址</translation>
<translation id="9148088599418889305">選擇運送方式</translation>
<translation id="9148507642005240123">復原編輯(&amp;U)</translation>
diff --git a/chromium/components/subresource_filter/FILTER_LIST_GENERATION.md b/chromium/components/subresource_filter/FILTER_LIST_GENERATION.md
index 7b7efa41ee6..1d524cd3d3f 100644
--- a/chromium/components/subresource_filter/FILTER_LIST_GENERATION.md
+++ b/chromium/components/subresource_filter/FILTER_LIST_GENERATION.md
@@ -65,12 +65,7 @@ in buckets are restricted to 1GB, you'll have to shard the file over many
files. Select gzip compression and use `<your_bucket>/site_urls.*.json.gz` as
your destination.
-Once exported, you can download the files from your bucket and extract them
-into a single file for processing:
-
-```sh
-ls site_urls.*.gz | xargs gunzip -c > site_urls
-```
+Once exported, you can download the files from your bucket.
## 2. Acquire a filter list in the indexed format
Chromium's tools are designed to work with a binary indexed version of filter
@@ -89,7 +84,7 @@ An example using [EasyList](https://easylist.to/easylist/easylist.txt) follows:
## 3. Generate the smaller filter list
```sh
1. ninja -C out/Release subresource_filter_tools
-2. out/Release/subresource_filter_tool --ruleset=easylist_indexed match_rules --input_file=site_urls > ordered_list.txt
+2. cat site_urls.*.json.gz | gunzip - | out/Release/subresource_filter_tool --ruleset=easylist_indexed match_rules > ordered_list.txt
3. head -n 1000 ordered_list.txt | cut -d' ' -f2 > smaller_list.txt
```
diff --git a/chromium/components/subresource_filter/content/browser/BUILD.gn b/chromium/components/subresource_filter/content/browser/BUILD.gn
index 4b070918bd8..d40f10a5c2e 100644
--- a/chromium/components/subresource_filter/content/browser/BUILD.gn
+++ b/chromium/components/subresource_filter/content/browser/BUILD.gn
@@ -67,6 +67,8 @@ static_library("test_support") {
"async_document_subresource_filter_test_utils.h",
"fake_safe_browsing_database_manager.cc",
"fake_safe_browsing_database_manager.h",
+ "subframe_navigation_test_utils.cc",
+ "subframe_navigation_test_utils.h",
"subresource_filter_observer_test_utils.cc",
"subresource_filter_observer_test_utils.h",
]
@@ -75,6 +77,8 @@ static_library("test_support") {
"//base/test:test_support",
"//components/subresource_filter/core/common",
"//content/public/browser",
+ "//content/test:test_support",
+ "//net",
"//testing/gtest:gtest",
"//url",
]
diff --git a/chromium/components/subresource_filter/content/browser/DEPS b/chromium/components/subresource_filter/content/browser/DEPS
index 14df806edc7..bebcdf46cf6 100644
--- a/chromium/components/subresource_filter/content/browser/DEPS
+++ b/chromium/components/subresource_filter/content/browser/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+components/safe_browsing/db",
"+components/ukm",
"+content/public/browser",
+ "+content/public/test",
"+net/base",
"+services/metrics/public/cpp",
"+ui/base/page_transition_types.h",
diff --git a/chromium/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc b/chromium/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
index 91d4fe7a949..64b18a283fe 100644
--- a/chromium/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h"
@@ -77,7 +77,7 @@ class AsyncDocumentSubresourceFilterTest : public ::testing::Test {
// Note: ADSF assumes a task runner is associated with the current thread.
// Instantiate a MessageLoop on the current thread and use base::RunLoop to
// handle the replies ADSF tasks generate.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<base::TestSimpleTaskRunner> blocking_task_runner_ =
new base::TestSimpleTaskRunner;
diff --git a/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
index 51653d7057c..3a841a522a5 100644
--- a/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -21,6 +21,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/subresource_filter/content/browser/async_document_subresource_filter.h"
+#include "components/subresource_filter/content/browser/subframe_navigation_test_utils.h"
#include "components/subresource_filter/content/browser/subresource_filter_client.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
#include "components/subresource_filter/content/common/subresource_filter_messages.h"
@@ -223,13 +224,16 @@ class ContentSubresourceFilterThrottleManagerTest
void CreateTestNavigation(const GURL& url,
content::RenderFrameHost* render_frame_host) {
- DCHECK(!navigation_simulator_);
DCHECK(render_frame_host);
navigation_simulator_ =
content::NavigationSimulator::CreateRendererInitiated(
url, render_frame_host);
}
+ content::NavigationSimulator* navigation_simulator() {
+ return navigation_simulator_.get();
+ }
+
content::RenderFrameHost* CreateSubframeWithTestNavigation(
const GURL& url,
content::RenderFrameHost* parent) {
@@ -240,58 +244,12 @@ class ContentSubresourceFilterThrottleManagerTest
return subframe;
}
- void SimulateStartAndExpectResult(
- content::NavigationThrottle::ThrottleAction expect_result) {
- navigation_simulator_->Start();
- content::NavigationThrottle::ThrottleCheckResult result =
- navigation_simulator_->GetLastThrottleCheckResult();
- EXPECT_EQ(expect_result, result);
- if (result.action() != content::NavigationThrottle::PROCEED)
- navigation_simulator_.reset();
- }
-
- void SimulateRedirectAndExpectResult(
- const GURL& new_url,
- content::NavigationThrottle::ThrottleAction expect_result) {
- navigation_simulator_->Redirect(new_url);
- content::NavigationThrottle::ThrottleCheckResult result =
- navigation_simulator_->GetLastThrottleCheckResult();
- EXPECT_EQ(expect_result, result);
- if (result.action() != content::NavigationThrottle::PROCEED)
- navigation_simulator_.reset();
- }
-
- // Returns the RenderFrameHost that the navigation commit in.
- content::RenderFrameHost* SimulateCommitAndExpectResult(
- content::NavigationThrottle::ThrottleAction expect_result) {
- navigation_simulator_->Commit();
- content::NavigationThrottle::ThrottleCheckResult result =
- navigation_simulator_->GetLastThrottleCheckResult();
- EXPECT_EQ(expect_result, result);
-
- auto scoped_simulator = std::move(navigation_simulator_);
- if (result.action() == content::NavigationThrottle::PROCEED)
- return scoped_simulator->GetFinalRenderFrameHost();
- return nullptr;
- }
-
- void SimulateSameDocumentCommit() {
- navigation_simulator_->CommitSameDocument();
- navigation_simulator_.reset();
- }
-
- void SimulateFailedNavigation(net::Error error) {
- navigation_simulator_->Fail(error);
- if (error != net::ERR_ABORTED) {
- navigation_simulator_->CommitErrorPage();
- }
- navigation_simulator_.reset();
- }
-
void NavigateAndCommitMainFrame(const GURL& url) {
CreateTestNavigation(url, main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
}
bool ManagerHasRulesetHandle() {
@@ -387,8 +345,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should be successfully filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -406,8 +364,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, NoPageActivation) {
// A disallowed subframe navigation should not be filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
-
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
EXPECT_EQ(0, disallowed_notification_count());
}
@@ -420,9 +378,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should not be filtered in dry-run mode.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
// But it should still be activated.
ExpectActivationSignalForFrame(child, true /* expect_activation */,
true /* is_ad_subframe */);
@@ -440,12 +401,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/before-redirect.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- content::NavigationThrottle::ThrottleAction expected_action =
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
- SimulateRedirectAndExpectResult(
- GURL("https://www.example.com/disallowed.html"), expected_action);
-
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://www.example.com/disallowed.html")));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -458,11 +419,16 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// An allowed subframe navigation should complete successfully.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/allowed1.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- SimulateRedirectAndExpectResult(GURL("https://www.example.com/allowed2.html"),
- content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://www.example.com/allowed2.html")));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, true /* expect_activation */);
EXPECT_EQ(0, disallowed_notification_count());
@@ -479,15 +445,15 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should be successfully filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/1/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/2/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -501,8 +467,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should be successfully filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/1/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
@@ -512,8 +478,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/2/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(2, disallowed_notification_count());
}
@@ -529,21 +495,21 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should be successfully filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/1/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
// Commit another navigation that triggers page level activation.
GURL url2 = GURL(base::StringPrintf("%s#ref", kTestURLWithActivation));
CreateTestNavigation(url2, main_rfh());
- SimulateSameDocumentCommit();
+ navigation_simulator()->CommitSameDocument();
ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */);
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/2/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -560,9 +526,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A subframe navigation should complete successfully.
CreateSubframeWithTestNavigation(GURL("https://www.example.com/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
EXPECT_EQ(0, disallowed_notification_count());
@@ -576,8 +545,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, RulesetHandleRegeneration) {
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
@@ -592,8 +561,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, RulesetHandleRegeneration) {
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(2, disallowed_notification_count());
}
@@ -618,9 +587,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A subframe navigation should complete successfully.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
EXPECT_EQ(0, disallowed_notification_count());
@@ -636,15 +608,15 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
GURL(base::StringPrintf("%sinactive.html", kTestURLWithActivation));
CreateTestNavigation(same_site_inactive_url, main_rfh());
- SimulateFailedNavigation(net::ERR_ABORTED);
+ SimulateFailedNavigation(navigation_simulator(), net::ERR_ABORTED);
EXPECT_TRUE(ManagerHasRulesetHandle());
ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */);
// A subframe navigation fail.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -659,15 +631,18 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
GURL(base::StringPrintf("%sinactive.html", kTestURLWithActivation));
CreateTestNavigation(same_site_inactive_url, main_rfh());
- SimulateFailedNavigation(net::ERR_FAILED);
+ SimulateFailedNavigation(navigation_simulator(), net::ERR_FAILED);
EXPECT_FALSE(ManagerHasRulesetHandle());
ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */);
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
EXPECT_EQ(0, disallowed_notification_count());
@@ -683,25 +658,31 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, ActivationPropagation) {
// filtering for this subframe document should still be activated.
CreateSubframeWithTestNavigation(GURL("https://www.a.com/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* subframe1 =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe1, true /* expect_activation */);
// Navigate a sub-subframe to a URL that is not itself disallowed. Subresource
// filtering for this subframe document should still be activated.
CreateSubframeWithTestNavigation(GURL("https://www.b.com/allowed.html"),
subframe1);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* subframe2 =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe2, true /* expect_activation */);
// A final, nested subframe navigation is filtered.
CreateSubframeWithTestNavigation(GURL("https://www.c.com/disallowed.html"),
subframe2);
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -713,17 +694,23 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, ActivationPropagation2) {
// Navigate a subframe that is not filtered, but should still activate.
CreateSubframeWithTestNavigation(GURL("https://whitelist.com"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* subframe1 =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe1, true /* expect_activation */);
// Navigate a sub-subframe that is not filtered due to the whitelist.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), subframe1);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* subframe2 =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe2, true /* expect_activation */);
EXPECT_EQ(0, disallowed_notification_count());
@@ -731,16 +718,19 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, ActivationPropagation2) {
// An identical series of events that don't match whitelist rules cause
// filtering.
CreateSubframeWithTestNavigation(GURL("https://average-joe.com"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* subframe3 =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe3, true /* expect_activation */);
// Navigate a sub-subframe that is not filtered due to the whitelist.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), subframe3);
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -763,9 +753,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
EXPECT_EQ(0, disallowed_notification_count());
@@ -796,9 +789,12 @@ TEST_F(ContentSubresourceFilterThrottleManagerTest, LogActivation) {
// Navigate a subframe that is not filtered, but should still activate.
CreateSubframeWithTestNavigation(GURL("https://whitelist.com"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* subframe1 =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe1, true /* expect_activation */);
tester.ExpectTotalCount(kActivationStateHistogram, 3);
@@ -823,9 +819,8 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should be successfully filtered.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
-
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(1, disallowed_notification_count());
}
@@ -845,9 +840,11 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
throttle_manager()->OnFrameIsAdSubframe(subframe);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAd(subframe));
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- subframe =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
+ subframe = navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(subframe);
ExpectActivationSignalForFrame(subframe, true /* expect_activation */,
true /* is_ad_subframe */);
@@ -855,9 +852,9 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A non-ad navigation for the same frame should be considered an ad
// subframe as well.
CreateTestNavigation(GURL("https://example.com/allowed2.html"), subframe);
- subframe =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
- EXPECT_TRUE(subframe);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
+ subframe = navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe, true /* expect_activation */,
true /* is_ad_subframe */);
}
@@ -882,10 +879,13 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
throttle_manager()->OnFrameIsAdSubframe(initial_subframe);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAd(initial_subframe));
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* final_subframe =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(final_subframe);
EXPECT_NE(initial_subframe, final_subframe);
@@ -910,19 +910,22 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// Simulate the render process telling the manager that the frame is an ad.
throttle_manager()->OnFrameIsAdSubframe(subframe);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
-
- subframe =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
+ subframe = navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe, true /* expect_activation */,
true /* is_ad_subframe */);
// Create a grandchild frame that is marked as an ad because its parent is.
content::RenderFrameHost* grandchild_frame = CreateSubframeWithTestNavigation(
GURL("https://www.example.com/foo/allowed.html"), subframe);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- grandchild_frame =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
+ grandchild_frame = navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(grandchild_frame, true /* expect_activation */,
true /* is_ad_subframe */);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAd(grandchild_frame));
@@ -942,9 +945,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// A disallowed subframe navigation should not be filtered in dry-run mode.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(child);
// But it should still be activated.
@@ -956,9 +962,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// tagged as ad because of its parent.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/allowed_by_ruleset.html"), child);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* grandchild =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(grandchild);
ExpectActivationSignalForFrame(grandchild, true /* expect_activation */,
true /* is_ad_subframe */);
@@ -968,9 +977,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/great_grandchild_allowed_by_ruleset.html"),
child);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* greatGrandchild =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(greatGrandchild);
ExpectActivationSignalForFrame(greatGrandchild, true /* expect_activation */,
true /* is_ad_subframe */);
@@ -986,9 +998,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/allowed_by_ruleset.html"), main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* child =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(child);
ExpectActivationSignalForFrame(child, true /* expect_activation */,
false /* is_ad_subframe */);
@@ -998,9 +1013,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// as ad because its parent is not tagged as well.
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/also_allowed_by_ruleset.html"), child);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
content::RenderFrameHost* grandchild =
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ navigation_simulator()->GetFinalRenderFrameHost();
EXPECT_TRUE(grandchild);
ExpectActivationSignalForFrame(grandchild, true /* expect_activation */,
false /* is_ad_subframe */);
diff --git a/chromium/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc b/chromium/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc
index 3a24304ffd9..f37e2ff1964 100644
--- a/chromium/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc
+++ b/chromium/components/subresource_filter/content/browser/fake_safe_browsing_database_manager.cc
@@ -57,12 +57,11 @@ bool FakeSafeBrowsingDatabaseManager::CheckUrlForSubresourceFilter(
checks_.insert(client);
if (simulate_timeout_)
return false;
- base::PostTaskWithTraits(
- FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&FakeSafeBrowsingDatabaseManager::
- OnCheckUrlForSubresourceFilterComplete,
- weak_factory_.GetWeakPtr(), base::Unretained(client),
- url));
+ base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&FakeSafeBrowsingDatabaseManager::
+ OnCheckUrlForSubresourceFilterComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Unretained(client), url));
return false;
}
diff --git a/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.cc b/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.cc
index b158be8acb4..dafdb8665fc 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.cc
+++ b/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.cc
@@ -46,9 +46,10 @@ void CloseFile(base::File) {}
void CloseFileOnFileThread(base::File* file) {
if (!file->IsValid())
return;
- base::PostTaskWithTraits(FROM_HERE,
- {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
- base::BindOnce(&CloseFile, std::move(*file)));
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+ base::BindOnce(&CloseFile, std::move(*file)));
}
} // namespace
@@ -59,7 +60,7 @@ RulesetPublisherImpl::RulesetPublisherImpl(
: ruleset_service_(ruleset_service),
ruleset_dealer_(std::make_unique<VerifiedRulesetDealer::Handle>(
std::move(blocking_task_runner))) {
- best_effort_task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits(
+ best_effort_task_runner_ = base::CreateSingleThreadTaskRunner(
{content::BrowserThread::UI, base::TaskPriority::BEST_EFFORT});
DCHECK(best_effort_task_runner_->BelongsToCurrentThread());
// Must rely on notifications as RenderProcessHostObserver::RenderProcessReady
diff --git a/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc b/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc
index da459669a5e..7ff442344c1 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl_unittest.cc
@@ -30,9 +30,9 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/test/browser_task_environment.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_platform_file.h"
#include "ipc/ipc_test_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -102,7 +102,7 @@ class SubresourceFilterRulesetPublisherImplTest : public ::testing::Test {
private:
base::ScopedTempDir scoped_temp_dir_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
NotifyingMockRenderProcessHost existing_renderer_;
diff --git a/chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc b/chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc
index 1d4a284e92d..25e6a39278e 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc
@@ -24,7 +24,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/task_runner_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
@@ -359,7 +359,7 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir scoped_temp_dir_;
scoped_refptr<base::TestSimpleTaskRunner> blocking_task_runner_;
diff --git a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
index 345053a2511..597d0ebfa6e 100644
--- a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
+++ b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
@@ -42,10 +42,14 @@ SubframeNavigationFilteringThrottle::~SubframeNavigationFilteringThrottle() {
base::TimeDelta::FromSeconds(10), 50);
break;
case LoadPolicy::WOULD_DISALLOW:
- // fall through
+ UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.WouldDisallow",
+ total_defer_time_, base::TimeDelta::FromMicroseconds(1),
+ base::TimeDelta::FromSeconds(10), 50);
+ break;
case LoadPolicy::DISALLOW:
UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(
- "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed",
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed2",
total_defer_time_, base::TimeDelta::FromMicroseconds(1),
base::TimeDelta::FromSeconds(10), 50);
break;
@@ -54,17 +58,29 @@ SubframeNavigationFilteringThrottle::~SubframeNavigationFilteringThrottle() {
content::NavigationThrottle::ThrottleCheckResult
SubframeNavigationFilteringThrottle::WillStartRequest() {
- return DeferToCalculateLoadPolicy();
+ return MaybeDeferToCalculateLoadPolicy();
}
content::NavigationThrottle::ThrottleCheckResult
SubframeNavigationFilteringThrottle::WillRedirectRequest() {
- return DeferToCalculateLoadPolicy();
+ return MaybeDeferToCalculateLoadPolicy();
}
content::NavigationThrottle::ThrottleCheckResult
SubframeNavigationFilteringThrottle::WillProcessResponse() {
DCHECK_NE(load_policy_, LoadPolicy::DISALLOW);
+
+ // Load policy notifications should go out by WillProcessResponse,
+ // defer if we are still performing any ruleset checks. If we are here,
+ // and there are outstanding load policy calculations, we are in dry run
+ // mode.
+ if (pending_load_policy_calculations_ > 0) {
+ DCHECK((parent_frame_filter_->activation_state().activation_level ==
+ mojom::ActivationLevel::kDryRun));
+ DeferStart(DeferStage::kWillProcessResponse);
+ return DEFER;
+ }
+
NotifyLoadPolicy();
return PROCEED;
}
@@ -73,48 +89,97 @@ const char* SubframeNavigationFilteringThrottle::GetNameForLogging() {
return "SubframeNavigationFilteringThrottle";
}
+void SubframeNavigationFilteringThrottle::HandleDisallowedLoad() {
+ if (parent_frame_filter_->activation_state().enable_logging) {
+ std::string console_message = base::StringPrintf(
+ kDisallowSubframeConsoleMessageFormat,
+ navigation_handle()->GetURL().possibly_invalid_spec().c_str());
+ navigation_handle()->GetWebContents()->GetMainFrame()->AddMessageToConsole(
+ blink::mojom::ConsoleMessageLevel::kError, console_message);
+ }
+
+ parent_frame_filter_->ReportDisallowedLoad();
+}
+
content::NavigationThrottle::ThrottleCheckResult
-SubframeNavigationFilteringThrottle::DeferToCalculateLoadPolicy() {
+SubframeNavigationFilteringThrottle::MaybeDeferToCalculateLoadPolicy() {
DCHECK_NE(load_policy_, LoadPolicy::DISALLOW);
if (load_policy_ == LoadPolicy::WOULD_DISALLOW)
return PROCEED;
+
+ pending_load_policy_calculations_ += 1;
parent_frame_filter_->GetLoadPolicyForSubdocument(
navigation_handle()->GetURL(),
base::BindOnce(
&SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy,
weak_ptr_factory_.GetWeakPtr()));
- last_defer_timestamp_ = base::TimeTicks::Now();
- return DEFER;
+
+ // If the embedder document has activation enabled, we calculate frame load
+ // policy before proceeding with navigation as filtered navigations are not
+ // allowed to get a response. As a result, we must defer while
+ // we wait for the ruleset check to complete and pass handling the navigation
+ // decision to the callback.
+ if (parent_frame_filter_->activation_state().activation_level ==
+ mojom::ActivationLevel::kEnabled) {
+ DeferStart(DeferStage::kWillStartOrRedirectRequest);
+ return DEFER;
+ }
+
+ // Otherwise, issue the ruleset request in parallel as an optimization.
+ return PROCEED;
}
void SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy(
LoadPolicy policy) {
+ load_policy_ = MoreRestrictiveLoadPolicy(policy, load_policy_);
+ pending_load_policy_calculations_ -= 1;
+
+ // Callback is not responsible for handling navigation if we are not deferred.
+ if (defer_stage_ == DeferStage::kNotDeferring)
+ return;
+
+ // When we are deferred, callback is not responsible for handling navigation
+ // if there are still outstanding load policy calculations.
+ if (pending_load_policy_calculations_ > 0) {
+ // We defer waiting for each load policy calculations when the embedder
+ // document has activation enabled.
+ DCHECK(parent_frame_filter_->activation_state().activation_level !=
+ mojom::ActivationLevel::kEnabled);
+ return;
+ }
+
+ // If we are deferred and there are no pending load policy calculations,
+ // handle the deferred navigation.
+ DCHECK(defer_stage_ == DeferStage::kWillProcessResponse ||
+ defer_stage_ == DeferStage::kWillStartOrRedirectRequest);
DCHECK(!last_defer_timestamp_.is_null());
- load_policy_ = policy;
+ bool deferring_response = defer_stage_ == DeferStage::kWillProcessResponse;
total_defer_time_ += base::TimeTicks::Now() - last_defer_timestamp_;
-
- if (policy == LoadPolicy::DISALLOW) {
- if (parent_frame_filter_->activation_state().enable_logging) {
- std::string console_message = base::StringPrintf(
- kDisallowSubframeConsoleMessageFormat,
- navigation_handle()->GetURL().possibly_invalid_spec().c_str());
- navigation_handle()
- ->GetWebContents()
- ->GetMainFrame()
- ->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kError,
- console_message);
- }
-
- parent_frame_filter_->ReportDisallowedLoad();
- // Other load policies will be reported in WillProcessResponse.
+ defer_stage_ = DeferStage::kNotDeferring;
+ if (deferring_response) {
NotifyLoadPolicy();
+ Resume();
+ return;
+ }
+ // Otherwise, we deferred at start/redirect time. Either cancel navigation
+ // or resume here according to load policy.
+ if (load_policy_ == LoadPolicy::DISALLOW) {
+ HandleDisallowedLoad();
+ NotifyLoadPolicy();
CancelDeferredNavigation(BLOCK_REQUEST_AND_COLLAPSE);
} else {
Resume();
}
}
+void SubframeNavigationFilteringThrottle::DeferStart(DeferStage stage) {
+ DCHECK(defer_stage_ == DeferStage::kNotDeferring);
+ DCHECK(stage != DeferStage::kNotDeferring);
+ defer_stage_ = stage;
+ last_defer_timestamp_ = base::TimeTicks::Now();
+}
+
void SubframeNavigationFilteringThrottle::NotifyLoadPolicy() const {
auto* observer_manager = SubresourceFilterObserverManager::FromWebContents(
navigation_handle()->GetWebContents());
diff --git a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
index a0b99720f3a..317f823ba96 100644
--- a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
+++ b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
@@ -67,14 +67,27 @@ class SubframeNavigationFilteringThrottle : public content::NavigationThrottle {
const char* GetNameForLogging() override;
private:
- content::NavigationThrottle::ThrottleCheckResult DeferToCalculateLoadPolicy();
+ enum class DeferStage {
+ kNotDeferring,
+ kWillStartOrRedirectRequest,
+ kWillProcessResponse
+ };
+
+ content::NavigationThrottle::ThrottleCheckResult
+ MaybeDeferToCalculateLoadPolicy();
+
void OnCalculatedLoadPolicy(LoadPolicy policy);
+ void HandleDisallowedLoad();
void NotifyLoadPolicy() const;
+ void DeferStart(DeferStage stage);
+
// Must outlive this class.
AsyncDocumentSubresourceFilter* parent_frame_filter_;
+ int pending_load_policy_calculations_ = 0;
+ DeferStage defer_stage_ = DeferStage::kNotDeferring;
base::TimeTicks last_defer_timestamp_;
base::TimeDelta total_defer_time_;
LoadPolicy load_policy_ = LoadPolicy::ALLOW;
diff --git a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
index 49b40db465a..1065a37b3f8 100644
--- a/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
@@ -16,6 +16,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "components/subresource_filter/content/browser/async_document_subresource_filter.h"
#include "components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h"
+#include "components/subresource_filter/content/browser/subframe_navigation_test_utils.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h"
#include "components/subresource_filter/core/browser/subresource_filter_constants.h"
#include "components/subresource_filter/core/common/test_ruleset_creator.h"
@@ -127,32 +128,6 @@ class SubframeNavigationFilteringThrottleTest
render_frame);
}
- void SimulateStartAndExpectResult(
- content::NavigationThrottle::ThrottleAction expect_result) {
- navigation_simulator_->Start();
- EXPECT_EQ(expect_result,
- navigation_simulator_->GetLastThrottleCheckResult());
- }
-
- void SimulateRedirectAndExpectResult(
- const GURL& new_url,
- content::NavigationThrottle::ThrottleAction expect_result) {
- navigation_simulator_->Redirect(new_url);
- EXPECT_EQ(expect_result,
- navigation_simulator_->GetLastThrottleCheckResult());
- }
-
- void SimulateCommitAndExpectResult(
- content::NavigationThrottle::ThrottleAction expect_result) {
- navigation_simulator_->Commit();
- EXPECT_EQ(expect_result,
- navigation_simulator_->GetLastThrottleCheckResult());
- }
-
- void SimulateCommitErrorPage() {
- navigation_simulator_->CommitErrorPage();
- }
-
const std::vector<std::string>& GetConsoleMessages() {
return content::RenderFrameHostTester::For(main_rfh())
->GetConsoleMessages();
@@ -182,8 +157,8 @@ TEST_F(SubframeNavigationFilteringThrottleTest, FilterOnStart) {
InitializeDocumentSubresourceFilter(GURL("https://example.test"));
const GURL url("https://example.test/disallowed.html");
CreateTestSubframeAndInitNavigation(url, main_rfh());
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_TRUE(
base::Contains(GetConsoleMessages(), GetFilterConsoleMessage(url)));
}
@@ -193,11 +168,12 @@ TEST_F(SubframeNavigationFilteringThrottleTest, FilterOnRedirect) {
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- content::NavigationThrottle::ThrottleAction expected_result =
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
- SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
- expected_result);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://example.test/disallowed.html")));
}
TEST_F(SubframeNavigationFilteringThrottleTest, DryRunOnStart) {
@@ -206,7 +182,8 @@ TEST_F(SubframeNavigationFilteringThrottleTest, DryRunOnStart) {
const GURL url("https://example.test/disallowed.html");
CreateTestSubframeAndInitNavigation(url, main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
EXPECT_FALSE(
base::Contains(GetConsoleMessages(), GetFilterConsoleMessage(url)));
}
@@ -217,9 +194,12 @@ TEST_F(SubframeNavigationFilteringThrottleTest, DryRunOnRedirect) {
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
- content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://example.test/disallowed.html")));
}
TEST_F(SubframeNavigationFilteringThrottleTest, FilterOnSecondRedirect) {
@@ -227,13 +207,16 @@ TEST_F(SubframeNavigationFilteringThrottleTest, FilterOnSecondRedirect) {
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- SimulateRedirectAndExpectResult(GURL("https://example.test/allowed2.html"),
- content::NavigationThrottle::PROCEED);
- content::NavigationThrottle::ThrottleAction expected_result =
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
- SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
- expected_result);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(
+ content::NavigationThrottle::PROCEED,
+ SimulateRedirectAndGetResult(navigation_simulator(),
+ GURL("https://example.test/allowed2.html")));
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://example.test/disallowed.html")));
}
TEST_F(SubframeNavigationFilteringThrottleTest, NeverFilterNonMatchingRule) {
@@ -241,10 +224,14 @@ TEST_F(SubframeNavigationFilteringThrottleTest, NeverFilterNonMatchingRule) {
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- SimulateRedirectAndExpectResult(GURL("https://example.test/allowed2.html"),
- content::NavigationThrottle::PROCEED);
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(
+ content::NavigationThrottle::PROCEED,
+ SimulateRedirectAndGetResult(navigation_simulator(),
+ GURL("https://example.test/allowed2.html")));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
}
TEST_F(SubframeNavigationFilteringThrottleTest, FilterSubsubframe) {
@@ -261,8 +248,8 @@ TEST_F(SubframeNavigationFilteringThrottleTest, FilterSubsubframe) {
CreateTestSubframeAndInitNavigation(
GURL("https://example.test/disallowed.html"), parent_subframe);
- SimulateStartAndExpectResult(
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
}
TEST_F(SubframeNavigationFilteringThrottleTest, DelayMetrics) {
@@ -271,25 +258,71 @@ TEST_F(SubframeNavigationFilteringThrottleTest, DelayMetrics) {
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- content::NavigationThrottle::ThrottleAction expected_result =
- content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
- SimulateRedirectAndExpectResult(GURL("https://example.test/disallowed.html"),
- expected_result);
- SimulateCommitErrorPage();
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://example.test/disallowed.html")));
+
+ navigation_simulator()->CommitErrorPage();
const char kFilterDelayDisallowed[] =
- "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed";
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed2";
+ const char kFilterDelayWouldDisallow[] =
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.WouldDisallow";
const char kFilterDelayAllowed[] =
"SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Allowed";
histogram_tester.ExpectTotalCount(kFilterDelayDisallowed, 1);
+ histogram_tester.ExpectTotalCount(kFilterDelayWouldDisallow, 0);
histogram_tester.ExpectTotalCount(kFilterDelayAllowed, 0);
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- SimulateStartAndExpectResult(content::NavigationThrottle::PROCEED);
- SimulateCommitAndExpectResult(content::NavigationThrottle::PROCEED);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
+
histogram_tester.ExpectTotalCount(kFilterDelayDisallowed, 1);
+ histogram_tester.ExpectTotalCount(kFilterDelayWouldDisallow, 0);
+ histogram_tester.ExpectTotalCount(kFilterDelayAllowed, 1);
+}
+
+TEST_F(SubframeNavigationFilteringThrottleTest, DelayMetricsDryRun) {
+ base::HistogramTester histogram_tester;
+ InitializeDocumentSubresourceFilter(GURL("https://example.test"),
+ mojom::ActivationLevel::kDryRun);
+ CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
+ main_rfh());
+ navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateRedirectAndGetResult(
+ navigation_simulator(),
+ GURL("https://example.test/disallowed.html")));
+ navigation_simulator()->Commit();
+
+ const char kFilterDelayDisallowed[] =
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed2";
+ const char kFilterDelayWouldDisallow[] =
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.WouldDisallow";
+ const char kFilterDelayAllowed[] =
+ "SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Allowed";
+ histogram_tester.ExpectTotalCount(kFilterDelayDisallowed, 0);
+ histogram_tester.ExpectTotalCount(kFilterDelayWouldDisallow, 1);
+ histogram_tester.ExpectTotalCount(kFilterDelayAllowed, 0);
+
+ CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
+ main_rfh());
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateStartAndGetResult(navigation_simulator()));
+ EXPECT_EQ(content::NavigationThrottle::PROCEED,
+ SimulateCommitAndGetResult(navigation_simulator()));
+
+ histogram_tester.ExpectTotalCount(kFilterDelayDisallowed, 0);
+ histogram_tester.ExpectTotalCount(kFilterDelayWouldDisallow, 1);
histogram_tester.ExpectTotalCount(kFilterDelayAllowed, 1);
}
diff --git a/chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.cc b/chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.cc
new file mode 100644
index 00000000000..1549ba65c42
--- /dev/null
+++ b/chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.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 "components/subresource_filter/content/browser/subframe_navigation_test_utils.h"
+
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/test/navigation_simulator.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_filter {
+
+content::NavigationThrottle::ThrottleCheckResult SimulateStartAndGetResult(
+ content::NavigationSimulator* navigation_simulator) {
+ navigation_simulator->Start();
+ return navigation_simulator->GetLastThrottleCheckResult();
+}
+
+content::NavigationThrottle::ThrottleCheckResult SimulateRedirectAndGetResult(
+ content::NavigationSimulator* navigation_simulator,
+ const GURL& new_url) {
+ navigation_simulator->Redirect(new_url);
+ return navigation_simulator->GetLastThrottleCheckResult();
+}
+
+content::NavigationThrottle::ThrottleCheckResult SimulateCommitAndGetResult(
+ content::NavigationSimulator* navigation_simulator) {
+ navigation_simulator->Commit();
+ return navigation_simulator->GetLastThrottleCheckResult();
+}
+
+void SimulateFailedNavigation(
+ content::NavigationSimulator* navigation_simulator,
+ net::Error error) {
+ navigation_simulator->Fail(error);
+ if (error != net::ERR_ABORTED) {
+ navigation_simulator->CommitErrorPage();
+ }
+}
+
+} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.h b/chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.h
new file mode 100644
index 00000000000..c8ca5bfdd4c
--- /dev/null
+++ b/chromium/components/subresource_filter/content/browser/subframe_navigation_test_utils.h
@@ -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.
+
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBFRAME_NAVIGATION_TEST_UTILS_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBFRAME_NAVIGATION_TEST_UTILS_H_
+
+#include "content/public/browser/navigation_throttle.h"
+#include "net/base/net_errors.h"
+#include "url/gurl.h"
+
+namespace content {
+class NavigationSimulator;
+}
+
+namespace subresource_filter {
+
+content::NavigationThrottle::ThrottleCheckResult SimulateStartAndGetResult(
+ content::NavigationSimulator* navigation_simulator);
+
+content::NavigationThrottle::ThrottleCheckResult SimulateRedirectAndGetResult(
+ content::NavigationSimulator* navigation_simulator,
+ const GURL& new_url);
+
+content::NavigationThrottle::ThrottleCheckResult SimulateCommitAndGetResult(
+ content::NavigationSimulator* navigation_simulator);
+
+void SimulateFailedNavigation(
+ content::NavigationSimulator* navigation_simulator,
+ net::Error error);
+
+} // namespace subresource_filter
+
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBFRAME_NAVIGATION_TEST_UTILS_H_
diff --git a/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc b/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc
index 63d55c540bc..c65d4a913b1 100644
--- a/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc
@@ -14,7 +14,7 @@
#include "base/test/test_simple_task_runner.h"
#include "components/subresource_filter/core/common/memory_mapped_ruleset.h"
#include "components/subresource_filter/core/common/test_ruleset_creator.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace subresource_filter {
@@ -468,7 +468,7 @@ class SubresourceFilterVerifiedRulesetDealerHandleTest
private:
TestRulesets rulesets_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(SubresourceFilterVerifiedRulesetDealerHandleTest);
};
@@ -629,7 +629,7 @@ class SubresourceFilterVerifiedRulesetHandleTest : public ::testing::Test {
TestRulesets rulesets_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
std::unique_ptr<VerifiedRulesetDealer::Handle> dealer_handle_;
- content::TestBrowserThreadBundle thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(SubresourceFilterVerifiedRulesetHandleTest);
};
diff --git a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
index 081bb89e84c..120997bfc33 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -125,49 +125,6 @@ void SubresourceFilterAgent::RecordHistogramsOnLoadCommitted(
}
}
-void SubresourceFilterAgent::RecordHistogramsOnLoadFinished() {
- DCHECK(filter_for_last_committed_load_);
- const auto& statistics =
- filter_for_last_committed_load_->filter().statistics();
-
- UMA_HISTOGRAM_COUNTS_1000(
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Total",
- statistics.num_loads_total);
- UMA_HISTOGRAM_COUNTS_1000(
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Evaluated",
- statistics.num_loads_evaluated);
- UMA_HISTOGRAM_COUNTS_1000(
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.MatchedRules",
- statistics.num_loads_matching_rules);
- UMA_HISTOGRAM_COUNTS_1000(
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Disallowed",
- statistics.num_loads_disallowed);
-
- // If ThreadTicks is not supported or performance measuring is switched off,
- // then no time measurements have been collected.
- if (ScopedThreadTimers::IsSupported() &&
- filter_for_last_committed_load_->filter()
- .activation_state()
- .measure_performance) {
- UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(
- "SubresourceFilter.DocumentLoad.SubresourceEvaluation."
- "TotalWallDuration",
- statistics.evaluation_total_wall_duration,
- base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
- 50);
- UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(
- "SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalCPUDuration",
- statistics.evaluation_total_cpu_duration,
- base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10),
- 50);
- } else {
- DCHECK(statistics.evaluation_total_wall_duration.is_zero());
- DCHECK(statistics.evaluation_total_cpu_duration.is_zero());
- }
-
- SendDocumentLoadStatistics(statistics);
-}
-
void SubresourceFilterAgent::ResetInfoForNextCommit() {
activation_state_for_next_commit_ = mojom::ActivationState();
}
@@ -265,7 +222,9 @@ void SubresourceFilterAgent::DidFailProvisionalLoad(
void SubresourceFilterAgent::DidFinishLoad() {
if (!filter_for_last_committed_load_)
return;
- RecordHistogramsOnLoadFinished();
+ const auto& statistics =
+ filter_for_last_committed_load_->filter().statistics();
+ SendDocumentLoadStatistics(statistics);
}
void SubresourceFilterAgent::WillCreateWorkerFetchContext(
diff --git a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
index 70c04068980..5e4f270c154 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
@@ -86,7 +86,6 @@ class SubresourceFilterAgent
void RecordHistogramsOnLoadCommitted(
const mojom::ActivationState& activation_state);
- void RecordHistogramsOnLoadFinished();
void ResetInfoForNextCommit();
const mojom::SubresourceFilterHostAssociatedPtr& GetSubresourceFilterHost();
diff --git a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
index c038b95f70e..2e93e3b99f7 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
@@ -99,18 +99,6 @@ constexpr const char kDocumentLoadRulesetIsAvailable[] =
"SubresourceFilter.DocumentLoad.RulesetIsAvailable";
constexpr const char kDocumentLoadActivationLevel[] =
"SubresourceFilter.DocumentLoad.ActivationState";
-constexpr const char kSubresourcesEvaluated[] =
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Evaluated";
-constexpr const char kSubresourcesTotal[] =
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Total";
-constexpr const char kSubresourcesMatchedRules[] =
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.MatchedRules";
-constexpr const char kSubresourcesDisallowed[] =
- "SubresourceFilter.DocumentLoad.NumSubresourceLoads.Disallowed";
-constexpr const char kEvaluationTotalWallDuration[] =
- "SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalWallDuration";
-constexpr const char kEvaluationTotalCPUDuration[] =
- "SubresourceFilter.DocumentLoad.SubresourceEvaluation.TotalCPUDuration";
} // namespace
@@ -246,13 +234,6 @@ TEST_F(SubresourceFilterAgentTest, DisabledByDefault_NoFilterIsInjected) {
static_cast<int>(mojom::ActivationLevel::kDisabled), 1);
histogram_tester.ExpectTotalCount(kDocumentLoadRulesetIsAvailable, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesTotal, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesEvaluated, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesMatchedRules, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesDisallowed, 0);
-
- histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 0);
- histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, 0);
}
TEST_F(SubresourceFilterAgentTest, MmapFailure_FailsToInjectSubresourceFilter) {
@@ -291,14 +272,6 @@ TEST_F(SubresourceFilterAgentTest,
kDocumentLoadActivationLevel,
static_cast<int>(mojom::ActivationLevel::kEnabled), 1);
histogram_tester.ExpectUniqueSample(kDocumentLoadRulesetIsAvailable, 0, 1);
-
- histogram_tester.ExpectTotalCount(kSubresourcesTotal, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesEvaluated, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesMatchedRules, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesDisallowed, 0);
-
- histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 0);
- histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, 0);
}
// Never inject a filter for main frame about:blank loads, even though we do for
@@ -315,14 +288,6 @@ TEST_F(SubresourceFilterAgentTest, EmptyDocumentLoad_NoFilterIsInjected) {
histogram_tester.ExpectTotalCount(kDocumentLoadActivationLevel, 0);
histogram_tester.ExpectTotalCount(kDocumentLoadRulesetIsAvailable, 0);
-
- histogram_tester.ExpectTotalCount(kSubresourcesTotal, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesEvaluated, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesMatchedRules, 0);
- histogram_tester.ExpectTotalCount(kSubresourcesDisallowed, 0);
-
- histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 0);
- histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, 0);
}
TEST_F(SubresourceFilterAgentTest, Enabled_FilteringIsInEffectForOneLoad) {
@@ -357,10 +322,6 @@ TEST_F(SubresourceFilterAgentTest, Enabled_FilteringIsInEffectForOneLoad) {
// the figures below, as they came after the original page load event. There
// should be no samples recorded into subresource count histograms during the
// final load where there is no activation.
- histogram_tester.ExpectUniqueSample(kSubresourcesTotal, 2, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesEvaluated, 2, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesMatchedRules, 1, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesDisallowed, 1, 1);
EXPECT_THAT(
histogram_tester.GetAllSamples(kDocumentLoadActivationLevel),
::testing::ElementsAre(
@@ -410,22 +371,6 @@ TEST_F(SubresourceFilterAgentTest, Enabled_HistogramSamplesOverTwoLoads) {
kDocumentLoadActivationLevel,
static_cast<int>(mojom::ActivationLevel::kEnabled), 2);
histogram_tester.ExpectUniqueSample(kDocumentLoadRulesetIsAvailable, 1, 2);
-
- EXPECT_THAT(histogram_tester.GetAllSamples(kSubresourcesTotal),
- ::testing::ElementsAre(base::Bucket(2, 1), base::Bucket(3, 1)));
- EXPECT_THAT(histogram_tester.GetAllSamples(kSubresourcesEvaluated),
- ::testing::ElementsAre(base::Bucket(2, 1), base::Bucket(3, 1)));
- EXPECT_THAT(histogram_tester.GetAllSamples(kSubresourcesMatchedRules),
- ::testing::ElementsAre(base::Bucket(1, 1), base::Bucket(2, 1)));
- EXPECT_THAT(histogram_tester.GetAllSamples(kSubresourcesDisallowed),
- ::testing::ElementsAre(base::Bucket(1, 1), base::Bucket(2, 1)));
-
- base::HistogramBase::Count expected_total_count =
- measure_performance && base::ThreadTicks::IsSupported() ? 2 : 0;
- histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration,
- expected_total_count);
- histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration,
- expected_total_count);
}
}
@@ -507,15 +452,6 @@ TEST_F(SubresourceFilterAgentTest, DryRun_ResourcesAreEvaluatedButNotFiltered) {
static_cast<int>(mojom::ActivationLevel::kDryRun), 1);
histogram_tester.ExpectUniqueSample(kDocumentLoadRulesetIsAvailable, 1, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesTotal, 3, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesEvaluated, 3, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesMatchedRules, 2, 1);
- histogram_tester.ExpectUniqueSample(kSubresourcesDisallowed, 0, 1);
-
- // Performance measurement is switched off.
- histogram_tester.ExpectTotalCount(kEvaluationTotalWallDuration, 0);
- histogram_tester.ExpectTotalCount(kEvaluationTotalCPUDuration, 0);
-
EXPECT_FALSE(agent()->IsAdSubframe());
}
diff --git a/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc b/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
index 653b73b0418..c5245cafa30 100644
--- a/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
+++ b/chromium/components/subresource_filter/core/browser/subresource_filter_features_unittest.cc
@@ -10,17 +10,13 @@
#include <utility>
#include <vector>
-#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_params.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h"
#include "components/subresource_filter/core/common/common_features.h"
-#include "components/variations/variations_associated_data.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,35 +24,47 @@ namespace subresource_filter {
namespace {
-constexpr const char kTestFieldTrialName[] = "FieldTrialNameShouldNotMatter";
-constexpr const char kTestExperimentGroupName[] = "GroupNameShouldNotMatter";
-
class ScopedExperimentalStateToggle {
public:
- ScopedExperimentalStateToggle(
- base::FeatureList::OverrideState feature_state,
- std::map<std::string, std::string> variation_params)
- : field_trial_list_(nullptr /* entropy_provider */),
- scoped_configurator_(nullptr) {
- EXPECT_TRUE(base::AssociateFieldTrialParams(
- kTestFieldTrialName, kTestExperimentGroupName, variation_params));
- base::FieldTrial* field_trial = base::FieldTrialList::CreateFieldTrial(
- kTestFieldTrialName, kTestExperimentGroupName);
-
- std::unique_ptr<base::FeatureList> feature_list =
- std::make_unique<base::FeatureList>();
- feature_list->RegisterFieldTrialOverride(
- kSafeBrowsingSubresourceFilter.name, feature_state, field_trial);
- scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
+ ScopedExperimentalStateToggle(base::FeatureList::OverrideState feature_state,
+ base::FieldTrialParams variation_params)
+ : scoped_configurator_(nullptr) {
+ const base::Feature& kFeature = kSafeBrowsingSubresourceFilter;
+
+ // Handle OVERRIDE_USE_DEFAULT which ScopedFeatureList does not support.
+ if (feature_state == base::FeatureList::OVERRIDE_USE_DEFAULT) {
+ // Init a temp ScopedFeatureList to query the current default state.
+ // Note that this will take account any overrides coming from the
+ // command-line, unlike testing the feature's |default_state|.
+ base::test::ScopedFeatureList temp_scoped_feature_list;
+ temp_scoped_feature_list.Init();
+ if (base::FeatureList::IsEnabled(kFeature)) {
+ feature_state = base::FeatureList::OVERRIDE_ENABLE_FEATURE;
+ } else {
+ feature_state = base::FeatureList::OVERRIDE_DISABLE_FEATURE;
+ }
+ }
+
+ switch (feature_state) {
+ case base::FeatureList::OVERRIDE_ENABLE_FEATURE:
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ kFeature, variation_params);
+ break;
+
+ case base::FeatureList::OVERRIDE_DISABLE_FEATURE:
+ scoped_feature_list_.InitAndDisableFeature(kFeature);
+ break;
+
+ case base::FeatureList::OVERRIDE_USE_DEFAULT:
+ NOTREACHED();
+ break;
+ }
}
~ScopedExperimentalStateToggle() {
- variations::testing::ClearAllVariationParams();
}
private:
- base::FieldTrialList field_trial_list_;
-
testing::ScopedSubresourceFilterConfigurator scoped_configurator_;
base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chromium/components/subresource_filter/core/common/BUILD.gn b/chromium/components/subresource_filter/core/common/BUILD.gn
index e5aa77472f8..066fd903ea1 100644
--- a/chromium/components/subresource_filter/core/common/BUILD.gn
+++ b/chromium/components/subresource_filter/core/common/BUILD.gn
@@ -19,6 +19,7 @@ static_library("common") {
"first_party_origin.h",
"indexed_ruleset.cc",
"indexed_ruleset.h",
+ "load_policy.cc",
"load_policy.h",
"memory_mapped_ruleset.cc",
"memory_mapped_ruleset.h",
@@ -66,6 +67,7 @@ source_set("unit_tests") {
"document_subresource_filter_unittest.cc",
"first_party_origin_unittest.cc",
"indexed_ruleset_unittest.cc",
+ "load_policy_unittest.cc",
"scoped_timers_unittest.cc",
"unindexed_ruleset_unittest.cc",
]
diff --git a/chromium/components/subresource_filter/core/common/indexed_ruleset_fuzzer.cc b/chromium/components/subresource_filter/core/common/indexed_ruleset_fuzzer.cc
index 84675c0cdb3..12e51da9304 100644
--- a/chromium/components/subresource_filter/core/common/indexed_ruleset_fuzzer.cc
+++ b/chromium/components/subresource_filter/core/common/indexed_ruleset_fuzzer.cc
@@ -7,6 +7,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
#include <string>
#include <vector>
@@ -16,7 +18,6 @@
#include "components/subresource_filter/core/common/first_party_origin.h"
#include "components/subresource_filter/core/common/unindexed_ruleset.h"
#include "components/url_pattern_index/url_pattern_index.h"
-#include "third_party/libFuzzer/src/utils/FuzzedDataProvider.h"
#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
#include "url/gurl.h"
#include "url/origin.h"
diff --git a/chromium/components/subresource_filter/core/common/load_policy.cc b/chromium/components/subresource_filter/core/common/load_policy.cc
new file mode 100644
index 00000000000..d6c89e3a749
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/load_policy.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 <algorithm>
+
+#include "components/subresource_filter/core/common/load_policy.h"
+
+namespace subresource_filter {
+
+LoadPolicy MoreRestrictiveLoadPolicy(LoadPolicy a, LoadPolicy b) {
+ return std::max(a, b);
+}
+
+} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/core/common/load_policy.h b/chromium/components/subresource_filter/core/common/load_policy.h
index 0a235a7e4a0..44faca7e404 100644
--- a/chromium/components/subresource_filter/core/common/load_policy.h
+++ b/chromium/components/subresource_filter/core/common/load_policy.h
@@ -8,13 +8,18 @@
namespace subresource_filter {
// Represents the value returned by the DocumentSubresourceFilter corresponding
-// to a resource load.
+// to a resource load. Ordered by in increasing severity.
enum class LoadPolicy {
ALLOW,
- DISALLOW,
+ // Policy for disallowed resources when the filter is running in dry run mode.
WOULD_DISALLOW,
+ DISALLOW,
};
+// Returns the stricter of the two load policies, as determined by the order
+// of the LoadPolicy enum.
+LoadPolicy MoreRestrictiveLoadPolicy(LoadPolicy a, LoadPolicy b);
+
} // namespace subresource_filter
#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_LOAD_POLICY_H_
diff --git a/chromium/components/subresource_filter/core/common/load_policy_unittest.cc b/chromium/components/subresource_filter/core/common/load_policy_unittest.cc
new file mode 100644
index 00000000000..bf00c6e6089
--- /dev/null
+++ b/chromium/components/subresource_filter/core/common/load_policy_unittest.cc
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/subresource_filter/core/common/load_policy.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_filter {
+
+TEST(SubresourceFilterLoadPolicyTest, MoreRestrictiveLoadPolicy) {
+ EXPECT_EQ(MoreRestrictiveLoadPolicy(LoadPolicy::DISALLOW,
+ LoadPolicy::WOULD_DISALLOW),
+ LoadPolicy::DISALLOW);
+ EXPECT_EQ(MoreRestrictiveLoadPolicy(LoadPolicy::DISALLOW, LoadPolicy::ALLOW),
+ LoadPolicy::DISALLOW);
+ EXPECT_EQ(
+ MoreRestrictiveLoadPolicy(LoadPolicy::WOULD_DISALLOW, LoadPolicy::ALLOW),
+ LoadPolicy::WOULD_DISALLOW);
+}
+
+} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/tools/BUILD.gn b/chromium/components/subresource_filter/tools/BUILD.gn
index 2b0f9e14cf4..6228e1373fe 100644
--- a/chromium/components/subresource_filter/tools/BUILD.gn
+++ b/chromium/components/subresource_filter/tools/BUILD.gn
@@ -98,6 +98,7 @@ if (!is_ios) {
outputs = [
"$target_gen_dir/GeneratedRulesetData",
+ "$target_gen_dir/default_local_state.json",
]
inputs = [
@@ -109,10 +110,8 @@ if (!is_ios) {
args = [
rebase_path(inputs[0], root_build_dir),
- rebase_path("$target_gen_dir/GeneratedRulesetData", root_build_dir),
- "--version_output=" +
- rebase_path("$target_gen_dir/default_local_state.json",
- root_build_dir),
+ rebase_path(outputs[0], root_build_dir),
+ "--version_output=" + rebase_path(outputs[1], root_build_dir),
"--content_version=1000",
]
}
diff --git a/chromium/components/subresource_filter/tools/filter_tool_main.cc b/chromium/components/subresource_filter/tools/filter_tool_main.cc
index 708e7475a13..50013aea1a4 100644
--- a/chromium/components/subresource_filter/tools/filter_tool_main.cc
+++ b/chromium/components/subresource_filter/tools/filter_tool_main.cc
@@ -46,20 +46,20 @@ const char kHelpMsg[] = R"(
For a given request if a whitelist rule matches as well as a blacklist
rule, the whitelist rule is printed but not the blacklist rule.
- * match_batch --input_file=<json_file_path>
- Like match, except it does the same for each request in a json file.
- The file format is one json expression per line. An example line
- follows (note: in the file it wouldn't have a line break like this
- comment does):
+ * match_batch [--input_file=<json_file_path>]
+ Like match, except it does the same for each request in stdin. A json
+ file path may be provided to use in place of stdin. The input format
+ is one json expression per line. An example line follows (note: in
+ the file/input stream it wouldn't have a line break like this comment
+ does):
{"origin":"http://www.example.com/","request_url":"http://www.exam
ple.com/foo.js","request_type":"script"}
- * match_rules --input_file=<json_file_path> --min_matches=<optional>
- For each record in the given whitespace delimited file (see
- match_batch for input file format), records the matching rule (see
- match command above) and prints all of the matched rules and the
- number of times they matched at the end.
+ * match_rules [--input_file=<json_file_path>] [--min_matches=<optional>]
+ For each record in the input (see match_batch for input formats),
+ records the matching rule (see match command above) and prints all of
+ the matched rules and the number of times they matched at the end.
Which rules get recorded:
If only a blacklist rule(s) matches, a blacklist rule is
@@ -156,18 +156,18 @@ int main(int argc, char* argv[]) {
return 1;
}
- if (!command_line.HasSwitch(kSwitchInputFile)) {
- PrintHelp();
- return 1;
+ std::ifstream requests_stream;
+ std::istream* input_stream = &std::cin;
+ if (command_line.HasSwitch(kSwitchInputFile)) {
+ requests_stream =
+ std::ifstream(command_line.GetSwitchValueASCII(kSwitchInputFile));
+ input_stream = &requests_stream;
}
- std::ifstream requests_stream(
- command_line.GetSwitchValueASCII(kSwitchInputFile));
-
if (cmd == kMatchBatchCommand) {
- filter_tool.MatchBatch(&requests_stream);
+ filter_tool.MatchBatch(input_stream);
} else if (cmd == kMatchRulesCommand) {
- filter_tool.MatchRules(&requests_stream, min_match_count);
+ filter_tool.MatchRules(input_stream, min_match_count);
}
return 0;
diff --git a/chromium/components/suggestions/BUILD.gn b/chromium/components/suggestions/BUILD.gn
index fd86688c7bc..fcb9c81c7b7 100644
--- a/chromium/components/suggestions/BUILD.gn
+++ b/chromium/components/suggestions/BUILD.gn
@@ -27,7 +27,7 @@ static_library("suggestions") {
"//url",
]
deps = [
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/keyed_service/core",
"//components/pref_registry",
"//components/signin/public/identity_manager",
diff --git a/chromium/components/suggestions/suggestions_service_impl.cc b/chromium/components/suggestions/suggestions_service_impl.cc
index 943b73b30fd..3d1ed823c4c 100644
--- a/chromium/components/suggestions/suggestions_service_impl.cc
+++ b/chromium/components/suggestions/suggestions_service_impl.cc
@@ -24,7 +24,6 @@
#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
#include "components/suggestions/blacklist_store.h"
#include "components/suggestions/suggestions_store.h"
-#include "components/sync/driver/sync_service.h"
#include "components/variations/net/variations_http_headers.h"
#include "google_apis/gaia/gaia_constants.h"
#include "net/base/escape.h"
@@ -115,7 +114,6 @@ SuggestionsServiceImpl::SuggestionsServiceImpl(
const base::TickClock* tick_clock)
: identity_manager_(identity_manager),
sync_service_(sync_service),
- sync_service_observer_(this),
history_sync_state_(syncer::UploadState::INITIALIZING),
url_loader_factory_(url_loader_factory),
suggestions_store_(std::move(suggestions_store)),
@@ -420,7 +418,7 @@ SuggestionsServiceImpl::CreateSuggestionsRequest(
resource_request->url = url;
resource_request->method = "GET";
resource_request->load_flags = net::LOAD_DISABLE_CACHE;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
// Add Chrome experiment state to the request headers.
// TODO: We should call AppendVariationHeaders with explicit
// variations::SignedIn::kNo If the access_token is empty
diff --git a/chromium/components/suggestions/suggestions_service_impl.h b/chromium/components/suggestions/suggestions_service_impl.h
index 7c93353739d..9b0407ce473 100644
--- a/chromium/components/suggestions/suggestions_service_impl.h
+++ b/chromium/components/suggestions/suggestions_service_impl.h
@@ -24,6 +24,7 @@
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/suggestions/proto/suggestions.pb.h"
#include "components/suggestions/suggestions_service.h"
+#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_service_observer.h"
#include "components/sync/driver/sync_service_utils.h"
#include "google_apis/gaia/google_service_auth_error.h"
@@ -41,10 +42,6 @@ class SharedURLLoaderFactory;
class SimpleURLLoader;
} // namespace network
-namespace syncer {
-class SyncService;
-} // namespace syncer
-
namespace user_prefs {
class PrefRegistrySyncable;
} // namespace user_prefs
@@ -178,7 +175,7 @@ class SuggestionsServiceImpl : public SuggestionsService,
syncer::SyncService* sync_service_;
ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
- sync_service_observer_;
+ sync_service_observer_{this};
// The state of history sync, i.e. are we uploading history data to Google?
syncer::UploadState history_sync_state_;
diff --git a/chromium/components/suggestions/suggestions_service_impl_unittest.cc b/chromium/components/suggestions/suggestions_service_impl_unittest.cc
index 459ee072930..9ac6c86c6fd 100644
--- a/chromium/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/chromium/components/suggestions/suggestions_service_impl_unittest.cc
@@ -14,7 +14,7 @@
#include "base/macros.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/suggestions/blacklist_store.h"
#include "components/suggestions/proto/suggestions.pb.h"
@@ -134,7 +134,7 @@ class SuggestionsServiceTest : public testing::Test {
url_loader_factory()),
base::WrapUnique(test_suggestions_store_),
base::WrapUnique(mock_blacklist_store_),
- scoped_task_environment_.GetMockTickClock());
+ task_environment_.GetMockTickClock());
}
GURL GetCurrentlyQueriedUrl() {
@@ -171,7 +171,7 @@ class SuggestionsServiceTest : public testing::Test {
bool rv = url_loader_factory()->SimulateResponseForPendingRequest(
url, network::URLLoaderCompletionStatus(net_error),
network::CreateResourceResponseHead(response_code), response_body);
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
return rv;
}
@@ -193,8 +193,8 @@ class SuggestionsServiceTest : public testing::Test {
return &url_loader_factory_;
}
- base::test::ScopedTaskEnvironment scoped_task_environment_{
- base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private:
signin::IdentityTestEnvironment identity_test_env_;
@@ -224,7 +224,7 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsData) {
EXPECT_CALL(callback, Run(_));
// Wait for the eventual network request.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kSuggestionsUrlPath);
ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
@@ -247,7 +247,7 @@ TEST_F(SuggestionsServiceTest, IgnoresNoopSyncChange) {
->OnStateChanged(sync_service());
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}
@@ -263,7 +263,7 @@ TEST_F(SuggestionsServiceTest, PersistentAuthErrorState) {
->OnStateChanged(sync_service());
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
SuggestionsProfile empty_suggestions;
@@ -283,7 +283,7 @@ TEST_F(SuggestionsServiceTest, IgnoresUninterestingSyncChange) {
->OnStateChanged(sync_service());
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}
@@ -297,7 +297,7 @@ TEST_F(SuggestionsServiceTest, DoesNotFetchOnStartup) {
static_cast<SyncServiceObserver*>(suggestions_service())
->OnStateChanged(sync_service());
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_FALSE(suggestions_service()->HasPendingRequestForTesting());
// Sync getting enabled should not result in a fetch.
@@ -307,7 +307,7 @@ TEST_F(SuggestionsServiceTest, DoesNotFetchOnStartup) {
->OnStateChanged(sync_service());
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}
@@ -326,7 +326,7 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) {
suggestions_service()->FetchSuggestionsData();
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
// |suggestions_store()| should still contain the default values.
@@ -355,7 +355,7 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled) {
suggestions_service()->FetchSuggestionsData();
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}
@@ -376,7 +376,7 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) {
GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
// Wait for eventual (but unexpected) network requests.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}
@@ -387,7 +387,7 @@ TEST_F(SuggestionsServiceTest, FetchingSuggestionsIgnoresRequestFailure) {
suggestions_service()->FetchSuggestionsData();
// Wait for the eventual network request.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_OK,
net::ERR_INVALID_RESPONSE));
}
@@ -403,7 +403,7 @@ TEST_F(SuggestionsServiceTest, FetchingSuggestionsClearsStoreIfResponseNotOK) {
suggestions_service()->FetchSuggestionsData();
// Wait for the eventual network request.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_BAD_REQUEST));
SuggestionsProfile empty_suggestions;
@@ -433,14 +433,14 @@ TEST_F(SuggestionsServiceTest, BlacklistURL) {
// Wait on the upload task, the blacklist request and the next blacklist
// scheduling task.
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistUrlPath);
// The blacklist fetch needs to contain a valid profile or the favicon will
// not be set.
ASSERT_TRUE(RespondToBlacklistFetch(
CreateSuggestionsProfile().SerializeAsString(), net::HTTP_OK));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
SuggestionsProfile suggestions;
suggestions_store()->LoadSuggestions(&suggestions);
@@ -483,7 +483,7 @@ TEST_F(SuggestionsServiceTest, RetryBlacklistURLRequestAfterFailure) {
EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));
// Wait for the first scheduling receiving a failing response.
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistUrlPath);
ASSERT_TRUE(RespondToBlacklistFetch("irrelevant", net::HTTP_OK,
@@ -503,7 +503,7 @@ TEST_F(SuggestionsServiceTest, RetryBlacklistURLRequestAfterFailure) {
.WillOnce(Return(true));
// Wait for the second scheduling followed by a successful response.
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ task_environment_.FastForwardUntilNoTasksRemain();
ASSERT_TRUE(suggestions_service()->HasPendingRequestForTesting());
ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistUrlPath);
@@ -562,7 +562,7 @@ TEST_F(SuggestionsServiceTest, ClearBlacklist) {
suggestions_service()->ClearBlacklist();
// Wait for the eventual network request.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(suggestions_service()->HasPendingRequestForTesting());
EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistClearUrlPath);
}
@@ -628,13 +628,13 @@ TEST_F(SuggestionsServiceTest, TemporarilyIncreasesBlacklistDelayOnFailure) {
// Delay unchanged on success.
suggestions_service()->FetchSuggestionsData();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
EXPECT_EQ(initial_delay, suggestions_service()->BlacklistDelayForTesting());
// Delay increases on failure.
suggestions_service()->FetchSuggestionsData();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_BAD_REQUEST));
base::TimeDelta delay_after_fail =
suggestions_service()->BlacklistDelayForTesting();
@@ -643,15 +643,15 @@ TEST_F(SuggestionsServiceTest, TemporarilyIncreasesBlacklistDelayOnFailure) {
// Success resets future delays, but the current horizon remains. Since no
// time has passed, the actual current delay stays the same.
suggestions_service()->FetchSuggestionsData();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
EXPECT_EQ(delay_after_fail,
suggestions_service()->BlacklistDelayForTesting());
// After the current horizon has passed, we're back at the initial delay.
- scoped_task_environment_.FastForwardBy(delay_after_fail);
+ task_environment_.FastForwardBy(delay_after_fail);
suggestions_service()->FetchSuggestionsData();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
EXPECT_EQ(initial_delay, suggestions_service()->BlacklistDelayForTesting());
}
@@ -663,7 +663,7 @@ TEST_F(SuggestionsServiceTest, DoesNotOverrideDefaultExpiryTime) {
suggestions_service()->FetchSuggestionsData();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
// Creates one suggestion without timestamp and adds a second with timestamp.
SuggestionsProfile profile = CreateSuggestionsProfile();
ChromeSuggestion* suggestion = profile.add_suggestions();
diff --git a/chromium/components/supervised_user_error_page/BUILD.gn b/chromium/components/supervised_user_error_page/BUILD.gn
deleted file mode 100644
index e5cb205c915..00000000000
--- a/chromium/components/supervised_user_error_page/BUILD.gn
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_android) {
- import("//build/config/android/rules.gni")
-}
-
-static_library("supervised_user_error_page") {
- sources = [
- "supervised_user_error_page.cc",
- "supervised_user_error_page.h",
- ]
-
- deps = [
- "//base",
- "//components/resources",
- "//components/strings",
- "//ui/base",
- ]
-}
-
-if (is_android) {
- java_cpp_enum("enums_srcjar") {
- sources = [
- "supervised_user_error_page.h",
- ]
- }
-}
-
-source_set("unit_tests") {
- testonly = true
- sources = [
- "supervised_user_error_page_unittest.cc",
- ]
- deps = [
- ":supervised_user_error_page",
- "//base",
- "//base/test:test_support",
- "//components/resources",
- "//components/strings",
- "//testing/gmock",
- "//testing/gtest",
- "//ui/base",
- ]
-}
diff --git a/chromium/components/supervised_user_error_page/DEPS b/chromium/components/supervised_user_error_page/DEPS
deleted file mode 100644
index 14cb58ec1d5..00000000000
--- a/chromium/components/supervised_user_error_page/DEPS
+++ /dev/null
@@ -1,9 +0,0 @@
-include_rules = [
- "+components/grit/components_resources.h",
- "+components/strings/grit/components_strings.h",
- "+content/public/renderer",
- "+third_party/blink",
- "+ui/base",
- "+url",
- "+v8",
-]
diff --git a/chromium/components/supervised_user_error_page/OWNERS b/chromium/components/supervised_user_error_page/OWNERS
deleted file mode 100644
index e856a98423b..00000000000
--- a/chromium/components/supervised_user_error_page/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-pam@chromium.org
-treib@chromium.org
-
-# COMPONENT: Services>SupervisedUser
diff --git a/chromium/components/supervised_user_error_page/resources/OWNERS b/chromium/components/supervised_user_error_page/resources/OWNERS
deleted file mode 100644
index c05db2e16e1..00000000000
--- a/chromium/components/supervised_user_error_page/resources/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# For trivial or mechanical horizontal JS/CSS/HTML changes.
-file://ui/webui/PLATFORM_OWNERS
diff --git a/chromium/components/supervised_user_error_page/resources/default_100_percent/logo_avatar_circle_blue_color.png b/chromium/components/supervised_user_error_page/resources/default_100_percent/logo_avatar_circle_blue_color.png
deleted file mode 100644
index 79080803a5d..00000000000
--- a/chromium/components/supervised_user_error_page/resources/default_100_percent/logo_avatar_circle_blue_color.png
+++ /dev/null
Binary files differ
diff --git a/chromium/components/supervised_user_error_page/resources/default_200_percent/logo_avatar_circle_blue_color.png b/chromium/components/supervised_user_error_page/resources/default_200_percent/logo_avatar_circle_blue_color.png
deleted file mode 100644
index 0ec3547b4dd..00000000000
--- a/chromium/components/supervised_user_error_page/resources/default_200_percent/logo_avatar_circle_blue_color.png
+++ /dev/null
Binary files differ
diff --git a/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.css b/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.css
deleted file mode 100644
index 54c30650f22..00000000000
--- a/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.css
+++ /dev/null
@@ -1,536 +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. */
-
-body {
- --avatar-stroke-color: var(--google-gray-50);
- --custodian-name-color: #202124;
- --custodian-email-color: #5f6368;
- background-color: var(--quiet-background-color);
- color: var(--text-color);
-}
-
-button {
- background: var(--primary-button-fill-color);
- border: 0;
- border-radius: 4px;
- box-sizing: border-box;
- color: var(--primary-button-text-color);
- cursor: pointer;
- font-family: 'Google Sans', Roboto, sans-serif;
- font-size: 14px;
- line-height: 16pt;
- margin: 0;
- padding: 8px 16px;
- transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
- user-select: none;
-}
-
-button:active {
- background: var(--primary-button-fill-color-active)
- outline: 0;
-}
-
-[dir='rtl'] button {
- float: left;
-}
-
-.ask-permission-button {
- float: right;
-}
-
-.go-back-button {
- float: left;
-}
-
-#details {
- color: #696969;
- margin: 45px 0 50px;
-}
-
-#details p:not(:first-of-type) {
- margin-top: 20px;
-}
-
-#details-header {
- font-weight: bold;
-}
-
-#details-button-container {
- box-shadow: inherit;
-}
-
-.details-button {
- background: var(--secondary-button-fill-color);
- border: 1px solid var(--secondary-button-border-color);
- color: var(--secondary-button-text-color);
- float: none;
- margin: 0;
- padding: 8px 16px;
-}
-
-.details-button:hover {
- background: var(--secondary-button-hover-fill-color);
- border-color: var(--secondary-button-hover-border-color);
- text-decoration: none;
-}
-
-h1 {
- color: var(--heading-color);
- font-size: 1.6em;
- font-weight: normal;
- line-height: 1.25em;
- margin-bottom: 16px;
-}
-
-html {
- -webkit-text-size-adjust: 100%;
- font-size: 125%;
-}
-
-.icon {
- background-repeat: no-repeat;
- background-size: 100%;
- height: 72px;
- margin: 0 0 40px;
- width: 72px;
-}
-
-.main-frame-blocked {
- box-sizing: border-box;
- margin: 100px auto 0;
- max-width: 600px;
- width: 100%;
-}
-
-/* "Ask your Parent" title */
-.main-frame-blocked h1 {
- color: var(--heading-color);
- font-family: 'Google Sans', Roboto, sans-serif;
- font-size: 24px;
- font-weight: normal;
- line-height: 32px;
-}
-
-/* "You need permission..." message */
-.main-frame-blocked p {
- color: var(--text-color);
- font-family: Roboto;
- font-size: 16px;
- font-weight: normal;
-}
-
-#main-message > p:not([hidden]) {
- display: inline;
-}
-
-.button-container {
- margin-top: 51px;
-}
-
-.button-container::after {
- clear: both;
- content: '';
- display: table;
- width: 100%;
-}
-
-.small-link {
- color: var(--small-link-color);
- font-family: Roboto;
- font-size: 15px;
- font-weight: 500;
-}
-
-.avatar-img {
- border: 3px solid var(--avatar-stroke-color);
- border-radius: 50%;
- content: -webkit-image-set(
- url(default_100_percent/logo_avatar_circle_blue_color.png) 1x,
- url(default_200_percent/logo_avatar_circle_blue_color.png) 2x);
- height: 36px;
- margin-bottom: 5px;
- margin-right: 15px;
- margin-top: 5px;
- position: relative;
- user-select: none;
- width: 36px;
-}
-
-#feedback {
- margin-top: 50px;
-}
-
-.custodian-information {
- align-items: center;
- display: flex;
- font-family: Roboto;
- font-weight: 400;
- line-height: normal;
- margin-top: 14px;
-}
-
-.custodian-name {
- color: var(--custodian-name-color);
- font-size: 16px;
- line-height: 24px;
-}
-
-.custodian-email {
- color: var(--custodian-email-color);
- font-size: 14px;
- line-height: 20px;
-}
-
-
-@media (max-width: 700px) {
- .main-frame-blocked {
- padding: 0 10%;
- }
-}
-
-@media (max-height: 600px) {
- #feedback {
- margin-top: 35px;
- }
-}
-
-@media (max-width: 420px) {
- button,
- [dir='rtl'] button,
- .small-link {
- float: none;
- font-size: .825em;
- font-weight: 400;
- margin: 0;
- text-transform: uppercase;
- width: 100%;
- }
-
- #details {
- margin: 20px 0 20px 0;
- }
-
- #details p:not(:first-of-type) {
- margin-top: 10px;
- }
-
- .details-button {
- margin-top: 20px;
- text-align: center;
- width: 100%;
- }
-
- .main-frame-blocked {
- padding: 0 5%;
- }
-
- .button-container {
- margin-top: 30px;
- }
-}
-
-/**
- * Mobile specific styling.
- * Navigation buttons are anchored to the bottom of the screen.
- * Details message replaces the top content in its own scrollable area.
- */
-
-@media (max-width: 420px) and (max-height: 736px) and (orientation: portrait) {
- .details-button {
- border: 0;
- margin: 8px 0 0;
- }
-
- .secondary-button {
- margin-inline-end: 0;
- margin-top: 16px;
- }
-}
-
-/* Fixed nav. */
-@media (min-width: 240px) and (max-width: 420px) and
- (min-height: 401px) and (max-height: 736px) and (orientation:portrait),
- (min-width: 421px) and (max-width: 736px) and (min-height: 240px) and
- (max-height: 420px) and (orientation:landscape) {
- body .button-container {
- background: var(--background-color);
- bottom: 0;
- box-shadow: 0 -22px 40px var(--background-color);
- left: 0;
- margin: 0;
- max-width: 736px;
- padding-left: 24px;
- padding-right: 24px;
- position: fixed;
- z-index: 2;
- }
-
- .main-frame-blocked {
- max-width: 736px;
- }
-
- #details,
- #information-container {
- padding-bottom: 40px;
- }
-}
-
-@media (max-width: 420px) and (max-height: 736px) and (orientation: portrait),
- (max-width: 736px) and (max-height: 420px) and (orientation: landscape) {
- body {
- margin: 0 auto;
- }
-
- button,
- [dir='rtl'] button,
- button.small-link {
- font-family: Roboto-Regular,Helvetica;
- font-size: .933em;
- font-weight: 600;
- margin: 6px 0;
- text-transform: uppercase;
- transform: translatez(0);
- }
-
- .button-container {
- box-sizing: border-box;
- padding-bottom: 8px;
- width: 100%;
- }
-
- #details {
- box-sizing: border-box;
- height: auto;
- margin: 0;
- opacity: 1;
- padding-top: 40px;
- transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
- }
-
- .details-button {
- padding-bottom: 16px;
- padding-top: 16px;
- }
-
- h1 {
- font-size: 1.5em;
- margin-bottom: 8px;
- }
-
- .icon {
- margin-bottom: 12px;
- }
-
- .main-frame-blocked {
- box-sizing: border-box;
- margin: 24px auto 12px;
- padding: 0 24px;
- position: relative;
- }
-
- .main-frame-blocked p {
- font-size: .95em;
- line-height: 1.61em;
- margin-top: 8px;
- }
-
- #information-container {
- margin: 0;
- transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
- }
-
- .small-link {
- border: 0;
- }
-}
-
-@media (min-height: 400px) and (orientation:portrait) {
- .main-frame-blocked {
- margin-bottom: 145px;
- }
-}
-
-@media (min-height: 299px) and (orientation:portrait) {
- .button-container {
- padding-bottom: 16px;
- }
-}
-
-@media (min-height: 405px) and (max-height: 736px) and
- (max-width: 420px) and (orientation:portrait) {
- .icon {
- margin-bottom: 24px;
- }
-
- .main-frame-blocked {
- margin-top: 64px;
- }
-}
-
-@media (min-height: 480px) and (max-width: 420px) and
- (max-height: 736px) and (orientation: portrait),
- (min-height: 338px) and (max-height: 420px) and (max-width: 736px) and
- (orientation: landscape) {
- .icon {
- margin-bottom: 24px;
- }
-
- .button-container {
- padding-bottom: 24px;
- }
-}
-
-@media (min-height: 500px) and (max-width: 414px) and (orientation: portrait) {
- .main-frame-blocked {
- margin-top: 96px;
- }
-}
-
-/* Phablet sizing */
-@media (min-width: 375px) and (min-height: 641px) and (max-height: 736px) and
- (max-width: 414px) and (orientation: portrait) {
- button,
- [dir='rtl'] button,
- .small-link {
- font-size: 1em;
- padding-bottom: 12px;
- padding-top: 12px;
- }
-
- body:not(.offline) .icon {
- height: 80px;
- width: 80px;
- }
-
- .details-button {
- margin-top: 28px;
- }
-
- h1 {
- font-size: 1.7em;
- }
-
- .icon {
- margin-bottom: 28px;
- }
-
- .main-frame-blocked {
- padding: 28px;
- }
-
- .main-frame-blocked p {
- font-size: 1.05em;
- }
-
- .button-container {
- padding: 28px;
- }
-}
-
-@media (min-width: 420px) and (max-width: 736px) and
- (min-height: 240px) and (max-height: 298px) and
- (orientation:landscape) {
- body:not(.offline) .icon {
- height: 50px;
- width: 50px;
- }
-
- .icon {
- padding-top: 0;
- }
-
- .main-frame-blocked {
- margin-top: 16px;
- }
-
- .button-container {
- padding: 0 24px 8px;
- }
-}
-
-@media (min-width: 420px) and (max-width: 736px) and
- (min-height: 240px) and (max-height: 420px) and
- (orientation:landscape) {
- .details-button {
- margin: 0;
- }
-
- .main-frame-blocked {
- margin-bottom: 70px;
- }
-
- .button-container {
- margin-top: 0;
- }
-}
-
-/* Phablet landscape */
-@media (min-width: 680px) and (max-height: 414px) {
- .main-frame-blocked {
- margin: 24px auto;
- }
-
- .button-container {
- margin: 16px auto 0;
- }
-}
-
-@media (max-height: 240px) and (orientation: landscape),
- (max-height: 480px) and (orientation: portrait),
- (max-width: 419px) and (max-height: 323px) {
- body:not(.offline) .icon {
- height: 56px;
- width: 56px;
- }
-
- .icon {
- margin-bottom: 16px;
- }
-}
-
-/* Small mobile screens. No fixed nav. */
-@media (max-height: 400px) and (orientation: portrait),
- (max-height: 239px) and (orientation: landscape),
- (max-width: 419px) and (max-height: 399px) {
- .main-frame-blocked {
- display: flex;
- flex-direction: column;
- margin-bottom: 0;
- }
-
- #details {
- flex: 1 1 auto;
- order: 0;
- }
-
- #information-container {
- flex: 1 1 auto;
- order: 0;
- }
-
- .button-container {
- flex: 0 1 auto;
- margin-top: 8px;
- order: 1;
- padding-left: 0;
- padding-right: 0;
- position: relative;
- width: 100%;
- }
-}
-
-@media (max-width: 239px) and (orientation: portrait) {
- .button-container {
- padding-left: 0;
- padding-right: 0;
- }
-}
-
-@media (prefers-color-scheme: dark) {
- body.supervised-user-block {
- --avatar-stroke-color: var(--google-blue-100);
- --custodian-name-color: var(--google-gray-500);
- --custodian-email-color: var(--google-gray-500);
- }
-}
diff --git a/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.html b/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.html
deleted file mode 100644
index 256b9442bfa..00000000000
--- a/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
-<head>
-<meta charset="utf-8">
-<meta name="viewport"
- content="initial-scale=1, minimum-scale=1, width=device-width">
-<title>$i18n{blockPageTitle}</title>
-<link href="https://fonts.googleapis.com/css?family=Google+Sans" rel="stylesheet">
-<link rel="stylesheet" href="../../security_interstitials/core/common/resources/interstitial_core.css">
-<link rel="stylesheet" href="supervised_user_block_interstitial.css">
-<script src="../../../ui/webui/resources/js/cr.js"></script>
-<script src="../../../ui/webui/resources/js/util.js"></script>
-<script src="supervised_user_block_interstitial.js"></script>
-</head>
-<body class="supervised-user-block">
-<div class="main-frame-blocked">
- <div id="information-container">
- <div class="icon" id="icon"></div>
- <div id="main-message">
- <h1 id="block-page-header">$i18n{blockPageHeader}</h1>
- <p id="block-page-message">$i18n{blockPageMessage}</p>
- <h1 id="request-failed-message" hidden>$i18n{requestFailedMessage}</h1>
- <h1 id="request-sent-message" hidden>$i18n{requestSentMessage}</h1>
- </div>
- <div id="custodians-information" hidden>
- <div id="custodian-information" class="custodian-information">
- <img id="custodian-avatar-img" class="avatar-img">
- <div id="custodian-contact">
- <div id="custodian-name" class="custodian-name"></div>
- <div id="custodian-email" class="custodian-email"></div>
- </div>
- </div>
- <div id="second-custodian-information" class="custodian-information" hidden>
- <img id="second-custodian-avatar-img" class="avatar-img" hidden>
- <div id="second-custodian-contact">
- <div id="second-custodian-name" class="custodian-name"></div>
- <div id="second-custodian-email" class="custodian-email"></div>
- </div>
- </div>
- </div>
- </div>
- <div class="button-container">
- <button id="request-access-button" class="ask-permission-button">
- $i18n{requestAccessButton}
- </button>
- <div id="details-button-container">
- <button id="show-details-link" class="details-button small-link">
- $i18n{showDetailsLink}
- </button>
- <button id="hide-details-link" class="details-button small-link" hidden>
- $i18n{hideDetailsLink}
- </button>
- </div>
- <button id="back-button" class="go-back-button" hidden>
- $i18n{backButton}
- </button>
- </div>
- <div id="details" hidden>
- <p id="details-header">$i18n{blockReasonHeader}</p>
- <p id="details-message">$i18n{blockReasonMessage}</p>
- <p id="feedback">$i18nRaw{feedbackLink}</p>
- </div>
-</div>
-</body>
-</html>
diff --git a/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js b/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js
deleted file mode 100644
index 33e41fbc854..00000000000
--- a/chromium/components/supervised_user_error_page/resources/supervised_user_block_interstitial.js
+++ /dev/null
@@ -1,150 +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.
-
-var mobileNav = false;
-
-var showDetails = false;
-
-/**
- * For small screen mobile the navigation buttons are moved
- * below the advanced text.
- */
-function onResize() {
- var mediaQuery = '(min-width: 240px) and (max-width: 420px) and ' +
- '(max-height: 736px) and (min-height: 401px) and ' +
- '(orientation: portrait), (max-width: 736px) and ' +
- '(max-height: 420px) and (min-height: 240px) and ' +
- '(min-width: 421px) and (orientation: landscape)';
-
- // Check for change in nav status.
- if (mobileNav != window.matchMedia(mediaQuery).matches) {
- mobileNav = !mobileNav;
- updateDetails();
- }
-}
-
-function updateDetails() {
- $('information-container').hidden = mobileNav && showDetails;
- $('details').hidden = !showDetails;
-}
-
-function setupMobileNav() {
- window.addEventListener('resize', onResize);
- onResize();
-}
-
-document.addEventListener('DOMContentLoaded', setupMobileNav);
-
-function sendCommand(cmd) {
- if (window.supervisedUserErrorPageController) {
- switch (cmd) {
- case 'back':
- supervisedUserErrorPageController.goBack();
- break;
- case 'request':
- supervisedUserErrorPageController.requestPermission();
- break;
- case 'feedback':
- supervisedUserErrorPageController.feedback();
- break;
- }
- return;
- }
- // TODO(bauerb): domAutomationController is not defined when this page is
- // shown in chrome://interstitials. Use a MessageHandler or something to
- // support interactions.
- window.domAutomationController.send(cmd);
-}
-
-function makeImageSet(url1x, url2x) {
- return '-webkit-image-set(url(' + url1x + ') 1x, url(' + url2x + ') 2x)';
-}
-
-function initialize() {
- var allowAccessRequests = loadTimeData.getBoolean('allowAccessRequests');
- if (allowAccessRequests) {
- $('request-access-button').onclick = function(event) {
- $('request-access-button').hidden = true;
- sendCommand('request');
- };
- } else {
- $('request-access-button').hidden = true;
- }
- var avatarURL1x = loadTimeData.getString('avatarURL1x');
- var avatarURL2x = loadTimeData.getString('avatarURL2x');
- var custodianName = loadTimeData.getString('custodianName');
- if (custodianName && allowAccessRequests) {
- $('custodians-information').hidden = false;
- if (avatarURL1x) {
- $('custodian-avatar-img').style.content =
- makeImageSet(avatarURL1x, avatarURL2x);
- }
- $('custodian-name').textContent = custodianName;
- $('custodian-email').textContent = loadTimeData.getString('custodianEmail');
- var secondAvatarURL1x = loadTimeData.getString('secondAvatarURL1x');
- var secondAvatarURL2x = loadTimeData.getString('secondAvatarURL2x');
- var secondCustodianName = loadTimeData.getString('secondCustodianName');
- if (secondCustodianName) {
- $('second-custodian-information').hidden = false;
- $('second-custodian-avatar-img').hidden = false;
- if (secondAvatarURL1x) {
- $('second-custodian-avatar-img').style.content =
- makeImageSet(secondAvatarURL1x, secondAvatarURL2x);
- }
- $('second-custodian-name').textContent = secondCustodianName;
- $('second-custodian-email').textContent = loadTimeData.getString(
- 'secondCustodianEmail');
- }
- }
- $('back-button').onclick = function(event) {
- sendCommand('back');
- };
- if (loadTimeData.getBoolean('showFeedbackLink')) {
- $('show-details-link').onclick = function(event) {
- showDetails = true;
- $('show-details-link').hidden = true;
- $('hide-details-link').hidden = false;
- updateDetails();
- };
- $('hide-details-link').onclick = function(event) {
- showDetails = false;
- $('show-details-link').hidden = false;
- $('hide-details-link').hidden = true;
- updateDetails();
- };
- $('feedback-link').onclick = function(event) {
- sendCommand('feedback');
- };
- } else {
- $('feedback').hidden = true;
- $('details-button-container').hidden = true;
- }
-}
-
-/**
- * Updates the interstitial to show that the request failed or was sent.
- * @param {boolean} isSuccessful Whether the request was successful or not.
- */
-function setRequestStatus(isSuccessful) {
- console.log('setRequestStatus(' + isSuccessful +')');
- $('block-page-header').hidden = true;
- $('block-page-message').hidden = true;
- $('hide-details-link').hidden = true;
- showDetails = false;
- updateDetails();
-
- if (isSuccessful) {
- $('request-failed-message').hidden = true;
- $('request-sent-message').hidden = false;
- $('back-button').hidden = false;
- $('request-access-button').hidden = true;
- $('show-details-link').hidden = true;
- } else {
- $('request-failed-message').hidden = false;
- $('request-access-button').hidden = false;
- $('show-details-link').hidden = false;
- }
-}
-
-document.addEventListener('DOMContentLoaded', initialize);
diff --git a/chromium/components/supervised_user_error_page/supervised_user_error_page.cc b/chromium/components/supervised_user_error_page/supervised_user_error_page.cc
deleted file mode 100644
index bc630de15f0..00000000000
--- a/chromium/components/supervised_user_error_page/supervised_user_error_page.cc
+++ /dev/null
@@ -1,183 +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 "components/supervised_user_error_page/supervised_user_error_page.h"
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "components/grit/components_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/webui/jstemplate_builder.h"
-#include "ui/base/webui/web_ui_util.h"
-
-namespace supervised_user_error_page {
-
-namespace {
-
-static const int kAvatarSize1x = 36;
-static const int kAvatarSize2x = 72;
-
-bool ReasonIsAutomatic(FilteringBehaviorReason reason) {
- return reason == ASYNC_CHECKER || reason == BLACKLIST;
-}
-
-std::string BuildAvatarImageUrl(const std::string& url, int size) {
- std::string result = url;
- size_t slash = result.rfind('/');
- if (slash != std::string::npos) {
- // Check if the URL already contains the monogram (-mo) option.
- // In that case, we must use the '-' separator, instead of '/'.
- std::string separator = result.substr(slash - 3, 3) == "/mo" ? "-" : "/";
- result.insert(slash, separator + "s" + base::NumberToString(size) + "-c");
- }
- return result;
-}
-
-} // namespace
-
-int GetBlockMessageID(FilteringBehaviorReason reason,
- bool is_child_account,
- bool single_parent) {
- switch (reason) {
- case DEFAULT:
- if (!is_child_account)
- return IDS_SUPERVISED_USER_BLOCK_MESSAGE_DEFAULT;
- if (single_parent)
- return IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT;
- return IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT;
- case BLACKLIST:
- case ASYNC_CHECKER:
- return IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES;
- case WHITELIST:
- NOTREACHED();
- break;
- case MANUAL:
- if (!is_child_account)
- return IDS_SUPERVISED_USER_BLOCK_MESSAGE_MANUAL;
- if (single_parent)
- return IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT;
- return IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT;
- case NOT_SIGNED_IN:
- return IDS_SUPERVISED_USER_NOT_SIGNED_IN;
- }
- NOTREACHED();
- return 0;
-}
-
-std::string BuildHtml(bool allow_access_requests,
- const std::string& profile_image_url,
- const std::string& profile_image_url2,
- const std::string& custodian,
- const std::string& custodian_email,
- const std::string& second_custodian,
- const std::string& second_custodian_email,
- bool is_child_account,
- bool is_deprecated,
- FilteringBehaviorReason reason,
- const std::string& app_locale) {
- base::DictionaryValue strings;
- strings.SetString("blockPageTitle",
- l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_TITLE));
- strings.SetBoolean("allowAccessRequests", allow_access_requests);
- strings.SetString("avatarURL1x",
- BuildAvatarImageUrl(profile_image_url, kAvatarSize1x));
- strings.SetString("avatarURL2x",
- BuildAvatarImageUrl(profile_image_url, kAvatarSize2x));
- strings.SetString("secondAvatarURL1x",
- BuildAvatarImageUrl(profile_image_url2, kAvatarSize1x));
- strings.SetString("secondAvatarURL2x",
- BuildAvatarImageUrl(profile_image_url2, kAvatarSize2x));
- strings.SetString("custodianName", custodian);
- strings.SetString("custodianEmail", custodian_email);
- strings.SetString("secondCustodianName", second_custodian);
- strings.SetString("secondCustodianEmail", second_custodian_email);
-
- base::string16 custodian16 = base::UTF8ToUTF16(custodian);
- base::string16 block_header;
- base::string16 block_message;
- if (reason == FilteringBehaviorReason::NOT_SIGNED_IN) {
- block_header =
- l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_HEADER_NOT_SIGNED_IN);
- } else if (allow_access_requests) {
- if (is_child_account) {
- block_header =
- l10n_util::GetStringUTF16(IDS_CHILD_BLOCK_INTERSTITIAL_HEADER);
- block_message =
- l10n_util::GetStringUTF16(IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE);
- } else {
- block_header = l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_HEADER,
- custodian16);
- // For non-child accounts, the block message is empty.
- }
- } else {
- block_header = l10n_util::GetStringUTF16(
- IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED);
-
- if (is_deprecated) {
- DCHECK(!is_child_account);
- block_message = l10n_util::GetStringUTF16(
- IDS_BLOCK_INTERSTITIAL_MESSAGE_SUPERVISED_USERS_DEPRECATED);
- }
- }
- strings.SetString("blockPageHeader", block_header);
- strings.SetString("blockPageMessage", block_message);
- strings.SetString("blockReasonMessage",
- l10n_util::GetStringUTF16(GetBlockMessageID(
- reason, is_child_account, second_custodian.empty())));
- strings.SetString("blockReasonHeader", l10n_util::GetStringUTF16(
- IDS_SUPERVISED_USER_BLOCK_HEADER));
- bool show_feedback = ReasonIsAutomatic(reason);
- DCHECK(is_child_account || !show_feedback);
-
- strings.SetBoolean("showFeedbackLink", show_feedback);
- strings.SetString("feedbackLink", l10n_util::GetStringUTF16(
- IDS_BLOCK_INTERSTITIAL_SEND_FEEDBACK));
- strings.SetString("backButton", l10n_util::GetStringUTF16(IDS_BACK_BUTTON));
- strings.SetString(
- "requestAccessButton",
- l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON));
- strings.SetString(
- "showDetailsLink",
- l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_SHOW_DETAILS));
- strings.SetString(
- "hideDetailsLink",
- l10n_util::GetStringUTF16(IDS_BLOCK_INTERSTITIAL_HIDE_DETAILS));
- base::string16 request_sent_message;
- base::string16 request_failed_message;
- if (is_child_account) {
- if (second_custodian.empty()) {
- request_sent_message = l10n_util::GetStringUTF16(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT);
- request_failed_message = l10n_util::GetStringUTF16(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT);
- } else {
- request_sent_message = l10n_util::GetStringUTF16(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT);
- request_failed_message = l10n_util::GetStringUTF16(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT);
- }
- } else {
- request_sent_message = l10n_util::GetStringFUTF16(
- IDS_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE, custodian16);
- request_failed_message = l10n_util::GetStringFUTF16(
- IDS_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE, custodian16);
- }
- strings.SetString("requestSentMessage", request_sent_message);
- strings.SetString("requestFailedMessage", request_failed_message);
- webui::SetLoadTimeDataDefaults(app_locale, &strings);
- std::string html =
- ui::ResourceBundle::GetSharedInstance()
- .GetRawDataResource(IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_HTML)
- .as_string();
- webui::AppendWebUiCssTextDefaults(&html);
- std::string error_html = webui::GetI18nTemplateHtml(html, &strings);
- return error_html;
-}
-
-} // namespace supervised_user_error_page
diff --git a/chromium/components/supervised_user_error_page/supervised_user_error_page.h b/chromium/components/supervised_user_error_page/supervised_user_error_page.h
deleted file mode 100644
index 0950ada4265..00000000000
--- a/chromium/components/supervised_user_error_page/supervised_user_error_page.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SUPERVISED_USER_ERROR_PAGE_SUPERVISED_USER_ERROR_PAGE_H_
-#define COMPONENTS_SUPERVISED_USER_ERROR_PAGE_SUPERVISED_USER_ERROR_PAGE_H_
-
-#include <string>
-
-namespace supervised_user_error_page {
-
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.supervisedusererrorpage
-enum FilteringBehaviorReason {
- DEFAULT = 0,
- ASYNC_CHECKER = 1,
- BLACKLIST = 2,
- MANUAL = 3,
- WHITELIST = 4,
- NOT_SIGNED_IN = 5,
-};
-
-int GetBlockMessageID(
- supervised_user_error_page::FilteringBehaviorReason reason,
- bool is_child_account,
- bool single_parent);
-
-std::string BuildHtml(bool allow_access_requests,
- const std::string& profile_image_url,
- const std::string& profile_image_url2,
- const std::string& custodian,
- const std::string& custodian_email,
- const std::string& second_custodian,
- const std::string& second_custodian_email,
- bool is_child_account,
- bool is_deprecated,
- FilteringBehaviorReason reason,
- const std::string& app_locale);
-
-} // namespace supervised_user_error_page
-
-#endif // COMPONENTS_SUPERVISED_USER_ERROR_PAGE_SUPERVISED_USER_ERROR_PAGE_H_
diff --git a/chromium/components/supervised_user_error_page/supervised_user_error_page_unittest.cc b/chromium/components/supervised_user_error_page/supervised_user_error_page_unittest.cc
deleted file mode 100644
index c1e712a6172..00000000000
--- a/chromium/components/supervised_user_error_page/supervised_user_error_page_unittest.cc
+++ /dev/null
@@ -1,208 +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 "components/supervised_user_error_page/supervised_user_error_page.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "components/grit/components_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest-param-test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-
-namespace supervised_user_error_page {
-
-struct BlockMessageIDTestParameter {
- FilteringBehaviorReason reason;
- bool is_child_account;
- bool single_parent;
- int expected_result;
-};
-
-class SupervisedUserErrorPageTest_GetBlockMessageID
- : public ::testing::TestWithParam<BlockMessageIDTestParameter> {};
-
-TEST_P(SupervisedUserErrorPageTest_GetBlockMessageID, GetBlockMessageID) {
- BlockMessageIDTestParameter param = GetParam();
- EXPECT_EQ(param.expected_result,
- GetBlockMessageID(param.reason, param.is_child_account,
- param.single_parent))
- << "reason = " << param.reason
- << " is_child_account = " << param.is_child_account
- << " single parent = " << param.single_parent;
-}
-
-BlockMessageIDTestParameter block_message_id_test_params[] = {
- {DEFAULT, false, false, IDS_SUPERVISED_USER_BLOCK_MESSAGE_DEFAULT},
- {DEFAULT, false, true, IDS_SUPERVISED_USER_BLOCK_MESSAGE_DEFAULT},
- {DEFAULT, true, true, IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT},
- {DEFAULT, true, false, IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT},
- // SafeSites is not enabled for supervised users.
- {ASYNC_CHECKER, true, true, IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES},
- {ASYNC_CHECKER, true, false, IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES},
- {MANUAL, false, false, IDS_SUPERVISED_USER_BLOCK_MESSAGE_MANUAL},
- {MANUAL, false, true, IDS_SUPERVISED_USER_BLOCK_MESSAGE_MANUAL},
- {MANUAL, true, true, IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT},
- {MANUAL, true, false, IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT},
-};
-
-INSTANTIATE_TEST_SUITE_P(GetBlockMessageIDParameterized,
- SupervisedUserErrorPageTest_GetBlockMessageID,
- ::testing::ValuesIn(block_message_id_test_params));
-
-struct BuildHtmlTestParameter {
- bool allow_access_requests;
- const std::string& profile_image_url;
- const std::string& profile_image_url2;
- const std::string& custodian;
- const std::string& custodian_email;
- const std::string& second_custodian;
- const std::string& second_custodian_email;
- bool is_child_account;
- bool is_deprecated;
- FilteringBehaviorReason reason;
- bool has_two_parents;
-};
-
-class SupervisedUserErrorPageTest_BuildHtml
- : public ::testing::TestWithParam<BuildHtmlTestParameter> {};
-
-TEST_P(SupervisedUserErrorPageTest_BuildHtml, BuildHtml) {
- BuildHtmlTestParameter param = GetParam();
- std::string result = BuildHtml(
- param.allow_access_requests, param.profile_image_url,
- param.profile_image_url2, param.custodian, param.custodian_email,
- param.second_custodian, param.second_custodian_email,
- param.is_child_account, param.is_deprecated, param.reason, "");
- // The result should contain the original HTML (with $i18n{} replacements)
- // plus scripts that plug values into it. The test can't easily check that the
- // scripts are correct, but can check that the output contains the expected
- // values.
- EXPECT_THAT(result, testing::HasSubstr(param.profile_image_url));
- EXPECT_THAT(result, testing::HasSubstr(param.profile_image_url2));
- EXPECT_THAT(result, testing::HasSubstr(param.custodian));
- EXPECT_THAT(result, testing::HasSubstr(param.custodian_email));
- if (param.has_two_parents) {
- EXPECT_THAT(result, testing::HasSubstr(param.second_custodian));
- EXPECT_THAT(result, testing::HasSubstr(param.second_custodian_email));
- }
- if (param.reason == ASYNC_CHECKER || param.reason == BLACKLIST) {
- EXPECT_THAT(result, testing::HasSubstr("\"showFeedbackLink\":true"));
- } else {
- EXPECT_THAT(result, testing::HasSubstr("\"showFeedbackLink\":false"));
- }
-
- // Messages containing parameters aren't tested since they get modified before
- // they are added to the result.
- if (param.allow_access_requests) {
- if (param.is_child_account) {
- EXPECT_THAT(result, testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_HEADER)));
- EXPECT_THAT(result, testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE)));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED))));
- } else {
- EXPECT_THAT(result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_HEADER))));
- EXPECT_THAT(result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE))));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED))));
- }
- } else {
- EXPECT_THAT(result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_HEADER))));
- EXPECT_THAT(result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE))));
- EXPECT_THAT(result,
- testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED)));
- }
- if (param.is_child_account) {
- if (param.has_two_parents) {
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT))));
- EXPECT_THAT(
- result,
- testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT)));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT))));
- EXPECT_THAT(
- result,
- testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT)));
- } else {
- EXPECT_THAT(
- result,
- testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT)));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT))));
- EXPECT_THAT(
- result,
- testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT)));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT))));
- }
- } else {
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT))));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT))));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT))));
- EXPECT_THAT(
- result,
- testing::Not(testing::HasSubstr(l10n_util::GetStringUTF8(
- IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT))));
- }
-}
-
-BuildHtmlTestParameter build_html_test_parameter[] = {
- {true, "url1", "url2", "custodian", "custodian_email", "", "", true, false,
- DEFAULT, false},
- {true, "url1", "url2", "custodian", "custodian_email", "custodian2",
- "custodian2_email", true, false, DEFAULT, true},
- {false, "url1", "url2", "custodian", "custodian_email", "custodian2",
- "custodian2_email", true, false, DEFAULT, true},
- {false, "url1", "url2", "custodian", "custodian_email", "custodian2",
- "custodian2_email", false, true, DEFAULT, true},
- {true, "url1", "url2", "custodian", "custodian_email", "custodian2",
- "custodian2_email", false, false, DEFAULT, true},
- {true, "url1", "url2", "custodian", "custodian_email", "custodian2",
- "custodian2_email", true, false, ASYNC_CHECKER, true},
-};
-
-INSTANTIATE_TEST_SUITE_P(GetBlockMessageIDParameterized,
- SupervisedUserErrorPageTest_BuildHtml,
- ::testing::ValuesIn(build_html_test_parameter));
-
-} // namespace supervised_user_error_page
diff --git a/chromium/components/supervised_user_error_page_strings.grdp b/chromium/components/supervised_user_error_page_strings.grdp
deleted file mode 100644
index 5798f26c596..00000000000
--- a/chromium/components/supervised_user_error_page_strings.grdp
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<grit-part>
- <!-- Supervised User Block Interstitial data -->
- <message name="IDS_BLOCK_INTERSTITIAL_TITLE" desc="A title for the supervised-user block interstitial page.">
- Site blocked
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_HEADER" desc="A heading for the supervised user when they attempt to visit a site that is not permitted by the manager.">
- You need permission from <ph name="NAME">$1<ex>John Doe</ex></ph> to visit this site
- </message>
- <message name="IDS_CHILD_BLOCK_INTERSTITIAL_HEADER" desc="A heading for the message to the child user when they attempt to visit a site that is not permitted by their parent.">
- Ask your parent
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED" desc="A heading for the supervised user when they attempt to visit a site that is not permitted by the manager (and they can't ask for permission).">
- You don't have permission to visit this site
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_HEADER_NOT_SIGNED_IN" desc="A heading for the supervised user when the status cannot be established because they haven't signed in to Chrome).">
- Please start and sign in to Chrome before using this app.
- </message>
- <message name="IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE" desc="A message for the child user when they attempt to visit a site that is not permitted by their parent.">
- You need permission to visit this site
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_MESSAGE_SUPERVISED_USERS_DEPRECATED" desc="Message to be shown to a supervised user directing them to the supervisor.">
- Questions? Contact the person who supervises your profile.
- </message>
- <message name="IDS_BACK_BUTTON" desc="A button for going back to the last safe url after being blocked.">
- Go back
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON" desc="A button for requesting access to blocked sites.">
- Ask permission
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE" desc="The text that tells the supervised user that a request has been sent.">
- Your request to access this site has been sent to <ph name="NAME">$1<ex>John Doe</ex></ph>
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE" desc="The text that tells the supervised user that a request could not be sent.">
- Your request to access this site could not be sent to <ph name="NAME">$1<ex>John Doe</ex></ph>. Please try again.
- </message>
- <message name="IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT" desc="The text that tells the child user that a request has been sent to their parent.">
- You asked your parent if it's OK to visit this site
- </message>
- <message name="IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT" desc="The text that tells the child user that a request has been sent to their parents.">
- You asked your parents if it's OK to visit this site
- </message>
- <message name="IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT" desc="The text that tells the child user that a request to their parent failed.">
- We could not reach your parent at the moment. Please try again.
- </message>
- <message name="IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT" desc="The text that tells the child user that a request to their parents failed.">
- We could not reach your parents at the moment. Please try again.
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_SEND_FEEDBACK" desc="The text for a link to submit feedback about a blocked site.">
- Was this unexpected? <ph name="BEGIN_LINK">&lt;a href="#" id="feedback-link"&gt;</ph>Let us know<ph name="END_LINK">&lt;/a&gt;</ph>
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_SHOW_DETAILS" desc="The text for the link to show details about the interstitial.">
- Details
- </message>
- <message name="IDS_BLOCK_INTERSTITIAL_HIDE_DETAILS" desc="The text for the link to hide details about the interstitial.">
- Hide details
- </message>
- <message name="IDS_SUPERVISED_USER_BLOCK_HEADER" desc="Header for the message to be shown when a site was blocked.">
- This site is blocked
- </message>
- <message name="IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT" desc="Message to be shown when a site was blocked due to the default fallback behavior and the child has one parent.">
- Your parent hasn't approved it yet
- </message>
- <message name="IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT" desc="Message to be shown when a site was blocked due to the default fallback behavior and the child has two parents.">
- Your parents haven't approved it yet
- </message>
- <message name="IDS_SUPERVISED_USER_BLOCK_MESSAGE_DEFAULT" desc="Message to be show to a supervised user when a site was blocked due to the default fallback behaviour.">
- Your manager hasn't approved it yet
- </message>
- <message name="IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES" desc="Message to be shown when a site was blocked due to the SafeSites safety check.">
- It may have mature content
- </message>
- <message name="IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT" desc="Message to be shown to a child when a site was blocked due to a manual blacklist entry and the child has one parent.">
- Your parent can unblock it for you
- </message>
- <message name="IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT" desc="Message to be shown to a child when a site was blocked due to a manual blacklist entry and the child has two parents.">
- Your parents can unblock it for you
- </message>
- <message name="IDS_SUPERVISED_USER_BLOCK_MESSAGE_MANUAL" desc="Message to be shown to a supervised user when a site is blocked due to a manual blacklist entry">
- Your manager can unblock it for you
- </message>
- <message name="IDS_SUPERVISED_USER_NOT_SIGNED_IN" desc="Message to be shown to a supervised user who is not signed in to Chrome">
- Please start and sign in to Chrome so that Chrome can check whether you are allowed to access this site.
- </message>
-
-</grit-part>
diff --git a/chromium/components/supervised_user_error_page_strings_grdp/OWNERS b/chromium/components/supervised_user_error_page_strings_grdp/OWNERS
deleted file mode 100644
index 0ba46ac8d26..00000000000
--- a/chromium/components/supervised_user_error_page_strings_grdp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/supervised_user_error_page/OWNERS
diff --git a/chromium/components/supervised_user_error_page_strings_grdp/README.md b/chromium/components/supervised_user_error_page_strings_grdp/README.md
deleted file mode 100644
index 119d8b9bff7..00000000000
--- a/chromium/components/supervised_user_error_page_strings_grdp/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-This directory of image SHA-1 hashes is used to improve translations of UI
-strings through context images for translators.
-
-See also: [Chrome Translation Screenshots - Instructions & FAQ
-](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/chromium/components/sync/BUILD.gn b/chromium/components/sync/BUILD.gn
index 70b835d2093..0c0e3a30c5c 100644
--- a/chromium/components/sync/BUILD.gn
+++ b/chromium/components/sync/BUILD.gn
@@ -322,6 +322,9 @@ jumbo_static_library("rest_of_sync") {
"nigori/nigori_local_change_processor.h",
"nigori/nigori_model_type_processor.cc",
"nigori/nigori_model_type_processor.h",
+ "nigori/nigori_storage.h",
+ "nigori/nigori_storage_impl.cc",
+ "nigori/nigori_storage_impl.h",
"nigori/nigori_sync_bridge.h",
"nigori/nigori_sync_bridge_impl.cc",
"nigori/nigori_sync_bridge_impl.h",
@@ -356,6 +359,8 @@ jumbo_static_library("rest_of_sync") {
"syncable/mutable_entry.h",
"syncable/nigori_handler.cc",
"syncable/nigori_handler.h",
+ "syncable/nigori_handler_proxy.cc",
+ "syncable/nigori_handler_proxy.h",
"syncable/nigori_util.cc",
"syncable/nigori_util.h",
"syncable/on_disk_directory_backing_store.cc",
@@ -418,6 +423,7 @@ jumbo_static_library("rest_of_sync") {
]
deps = [
"//base:i18n",
+ "//build:branding_buildflags",
"//components/keyed_service/core",
"//services/network/public/cpp",
"//sql",
@@ -637,6 +643,7 @@ source_set("unit_tests") {
"nigori/cryptographer_unittest.cc",
"nigori/nigori_key_bag_unittest.cc",
"nigori/nigori_model_type_processor_unittest.cc",
+ "nigori/nigori_storage_impl_unittest.cc",
"nigori/nigori_sync_bridge_impl_unittest.cc",
"nigori/nigori_unittest.cc",
"protocol/proto_enum_conversions_unittest.cc",
diff --git a/chromium/components/sync/mojom/syncer.typemap b/chromium/components/sync/mojom/syncer.typemap
index 52b3b039419..8e75b17f023 100644
--- a/chromium/components/sync/mojom/syncer.typemap
+++ b/chromium/components/sync/mojom/syncer.typemap
@@ -8,4 +8,4 @@ traits_headers = [ "//components/sync/mojom/syncer_mojom_traits.h" ]
deps = [
"//components/sync:sync",
]
-type_mappings = [ "syncer.mojom.StringOrdinal=syncer::StringOrdinal" ]
+type_mappings = [ "syncer.mojom.StringOrdinal=::syncer::StringOrdinal" ]
diff --git a/chromium/components/sync/protocol/BUILD.gn b/chromium/components/sync/protocol/BUILD.gn
index 0de6835880b..17a2a941b72 100644
--- a/chromium/components/sync/protocol/BUILD.gn
+++ b/chromium/components/sync/protocol/BUILD.gn
@@ -35,26 +35,8 @@ jumbo_static_library("util") {
if (is_android) {
import("//build/config/android/rules.gni")
- _test_support_prepared_protos_dir =
- "$root_gen_dir/test_support_proto_java_prepare/"
- action("test_support_java_prepare") {
- script = "prepare_protos_for_java_tests.py"
- inputs = sync_protocol_sources
- outputs = process_file_template(
- sync_protocol_sources,
- [ "$_test_support_prepared_protos_dir/{{source_file_part}}" ])
- args = [
- "--output_dir",
- rebase_path(_test_support_prepared_protos_dir, root_build_dir),
- ]
- args += rebase_path(sync_protocol_sources, root_build_dir)
- }
-
- proto_java_library("test_support_java") {
- proto_path = _test_support_prepared_protos_dir
- sources = get_target_outputs(":test_support_java_prepare")
- deps = [
- ":test_support_java_prepare",
- ]
+ proto_java_library("protocol_java") {
+ proto_path = "//components/sync/protocol/"
+ sources = sync_protocol_sources
}
}
diff --git a/chromium/components/sync_bookmarks/OWNERS b/chromium/components/sync_bookmarks/OWNERS
index ef97383a899..2453e933292 100644
--- a/chromium/components/sync_bookmarks/OWNERS
+++ b/chromium/components/sync_bookmarks/OWNERS
@@ -1,3 +1,4 @@
file://components/sync/OWNERS
# COMPONENT: Services>Sync
+# TEAM: chromium-reviews@chromium.org
diff --git a/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc b/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
index b89dbfc8723..f1f4bbd0ac9 100644
--- a/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
@@ -125,7 +125,7 @@ class SyncBookmarkDataTypeControllerTest : public testing::Test {
history_service_->NotifyHistoryServiceLoaded();
}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
testing::NiceMock<syncer::SyncApiComponentFactoryMock> components_factory_;
std::unique_ptr<BookmarkModel> bookmark_model_;
std::unique_ptr<HistoryMock> history_service_;
diff --git a/chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index 9ea29d28cd1..3e8918c939a 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -12,7 +12,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/test/test_bookmark_client.h"
#include "components/favicon/core/test/mock_favicon_service.h"
@@ -170,7 +170,7 @@ class BookmarkModelTypeProcessorTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
BookmarkUndoService bookmark_undo_service_;
NiceMock<favicon::MockFaviconService> favicon_service_;
diff --git a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc
index 94c4a5f314b..92251c0f4a5 100644
--- a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc
@@ -8,6 +8,7 @@
#include <string>
#include <utility>
+#include "base/guid.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -678,7 +679,7 @@ TEST(BookmarkRemoteUpdatesHandlerTest,
sync_pb::EntitySpecifics specifics;
sync_pb::BookmarkSpecifics* bookmark_specifics = specifics.mutable_bookmark();
bookmark_specifics->set_title("Title");
- bookmarks::BookmarkNode node(/*id=*/1, GURL());
+ bookmarks::BookmarkNode node(/*id=*/1, base::GenerateGUID(), GURL());
// Track a sync entity (similar to what happens after a local creation). The
// |originator_client_item_id| is used a temp sync id and mark the entity that
// it needs to be committed..
diff --git a/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc b/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
index ea44438a578..796cb421f0d 100644
--- a/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
+++ b/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
@@ -5,6 +5,7 @@
#include "components/sync_bookmarks/synced_bookmark_tracker.h"
#include "base/base64.h"
+#include "base/guid.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "components/bookmarks/browser/bookmark_model.h"
@@ -70,7 +71,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldGetAssociatedNodes) {
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, kUrl);
+ bookmarks::BookmarkNode node(kId, base::GenerateGUID(), kUrl);
tracker.Add(kSyncId, &node, kServerVersion, kCreationTime,
unique_position.ToProto(), specifics);
const SyncedBookmarkTracker::Entity* entity =
@@ -103,7 +104,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldReturnNullForDisassociatedNodes) {
const sync_pb::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, GURL());
+ bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
unique_position, specifics);
ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
@@ -127,7 +128,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldBuildBookmarkModelMetadata) {
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, kUrl);
+ bookmarks::BookmarkNode node(kId, base::GenerateGUID(), kUrl);
tracker.Add(kSyncId, &node, kServerVersion, kCreationTime,
unique_position.ToProto(), specifics);
@@ -152,7 +153,7 @@ TEST(SyncedBookmarkTrackerTest,
const sync_pb::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, GURL());
+ bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
unique_position, specifics);
@@ -174,7 +175,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldAckSequenceNumber) {
const sync_pb::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, GURL());
+ bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
unique_position, specifics);
@@ -208,7 +209,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldUpdateUponCommitResponseWithNewId) {
const sync_pb::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(kId, GURL());
+ bookmarks::BookmarkNode node(kId, base::GenerateGUID(), GURL());
tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
unique_position, specifics);
ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
@@ -237,7 +238,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldUpdateId) {
const sync_pb::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
- bookmarks::BookmarkNode node(/*id=*/1, GURL());
+ bookmarks::BookmarkNode node(/*id=*/1, base::GenerateGUID(), GURL());
// Track a sync entity.
tracker.Add(kSyncId, &node, kServerVersion, kModificationTime,
unique_position, specifics);
@@ -269,8 +270,8 @@ TEST(SyncedBookmarkTrackerTest,
const std::string kId4 = "id4";
const GURL kUrl("http://www.foo.com");
- bookmarks::BookmarkNode node0(/*id=*/0, kUrl);
- bookmarks::BookmarkNode node1(/*id=*/1, kUrl);
+ bookmarks::BookmarkNode node0(/*id=*/0, base::GenerateGUID(), kUrl);
+ bookmarks::BookmarkNode node1(/*id=*/1, base::GenerateGUID(), kUrl);
std::vector<NodeMetadataPair> node_metadata_pairs;
node_metadata_pairs.emplace_back(
@@ -314,11 +315,11 @@ TEST(SyncedBookmarkTrackerTest,
const std::string kId4 = "id4";
const GURL kUrl("http://www.foo.com");
- bookmarks::BookmarkNode node0(/*id=*/0, kUrl);
- bookmarks::BookmarkNode node1(/*id=*/1, kUrl);
- bookmarks::BookmarkNode node2(/*id=*/2, kUrl);
- bookmarks::BookmarkNode node3(/*id=*/3, kUrl);
- bookmarks::BookmarkNode node4(/*id=*/4, kUrl);
+ bookmarks::BookmarkNode node0(/*id=*/0, base::GenerateGUID(), kUrl);
+ bookmarks::BookmarkNode node1(/*id=*/1, base::GenerateGUID(), kUrl);
+ bookmarks::BookmarkNode node2(/*id=*/2, base::GenerateGUID(), kUrl);
+ bookmarks::BookmarkNode node3(/*id=*/3, base::GenerateGUID(), kUrl);
+ bookmarks::BookmarkNode node4(/*id=*/4, base::GenerateGUID(), kUrl);
std::vector<NodeMetadataPair> node_metadata_pairs;
node_metadata_pairs.emplace_back(
diff --git a/chromium/components/sync_device_info/device_info_sync_bridge_unittest.cc b/chromium/components/sync_device_info/device_info_sync_bridge_unittest.cc
index f8f8ad36c18..67c741b2665 100644
--- a/chromium/components/sync_device_info/device_info_sync_bridge_unittest.cc
+++ b/chromium/components/sync_device_info/device_info_sync_bridge_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync/base/time.h"
#include "components/sync/model/data_batch.h"
@@ -399,7 +399,7 @@ class DeviceInfoSyncBridgeTest : public testing::Test,
int change_count_ = 0;
// In memory model type store needs to be able to post tasks.
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
diff --git a/chromium/components/sync_device_info/fake_device_info_tracker.cc b/chromium/components/sync_device_info/fake_device_info_tracker.cc
index c13f12dfdd2..12fb0d81032 100644
--- a/chromium/components/sync_device_info/fake_device_info_tracker.cc
+++ b/chromium/components/sync_device_info/fake_device_info_tracker.cc
@@ -49,11 +49,11 @@ FakeDeviceInfoTracker::GetAllDeviceInfo() const {
}
void FakeDeviceInfoTracker::AddObserver(Observer* observer) {
- NOTREACHED();
+ observers_.AddObserver(observer);
}
void FakeDeviceInfoTracker::RemoveObserver(Observer* observer) {
- NOTREACHED();
+ observers_.RemoveObserver(observer);
}
int FakeDeviceInfoTracker::CountActiveDevices() const {
@@ -76,10 +76,14 @@ bool FakeDeviceInfoTracker::IsRecentLocalCacheGuid(
void FakeDeviceInfoTracker::Add(const DeviceInfo* device) {
devices_.push_back(device);
+ for (auto& observer : observers_)
+ observer.OnDeviceInfoChange();
}
void FakeDeviceInfoTracker::OverrideActiveDeviceCount(int count) {
active_device_count_ = count;
+ for (auto& observer : observers_)
+ observer.OnDeviceInfoChange();
}
} // namespace syncer
diff --git a/chromium/components/sync_device_info/fake_device_info_tracker.h b/chromium/components/sync_device_info/fake_device_info_tracker.h
index d9fa2d27301..ecc390f8346 100644
--- a/chromium/components/sync_device_info/fake_device_info_tracker.h
+++ b/chromium/components/sync_device_info/fake_device_info_tracker.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/observer_list.h"
#include "base/optional.h"
#include "components/sync_device_info/device_info_tracker.h"
@@ -45,6 +46,8 @@ class FakeDeviceInfoTracker : public DeviceInfoTracker {
// DeviceInfo stored here are not owned.
std::vector<const DeviceInfo*> devices_;
base::Optional<int> active_device_count_;
+ // Registered observers, not owned.
+ base::ObserverList<Observer, true>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(FakeDeviceInfoTracker);
};
diff --git a/chromium/components/sync_preferences/pref_model_associator.cc b/chromium/components/sync_preferences/pref_model_associator.cc
index 6655e3772f3..266b7b49668 100644
--- a/chromium/components/sync_preferences/pref_model_associator.cc
+++ b/chromium/components/sync_preferences/pref_model_associator.cc
@@ -38,14 +38,6 @@ namespace sync_preferences {
namespace {
-// Enables deleting a pref from Sync if the the user clears it on a client. If
-// this feature is disabled, clearing a pref will cause setting it to the
-// default value instead of deleting it from sync.
-// TODO(crbug.com/943579): This has been introduced in M75 as a safety
-// mechanism, should be removed in M78 if no issues are observed.
-const base::Feature kSyncDeleteClearedPref{"SyncDeleteClearedPrefs",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
const sync_pb::PreferenceSpecifics& GetSpecifics(const syncer::SyncData& pref) {
DCHECK(pref.GetDataType() == syncer::PREFERENCES ||
pref.GetDataType() == syncer::PRIORITY_PREFERENCES);
@@ -526,8 +518,7 @@ void PrefModelAssociator::ProcessPrefChange(const std::string& name) {
LOG(ERROR) << "Failed to update preference.";
return;
}
- if (!base::FeatureList::IsEnabled(kSyncDeleteClearedPref) ||
- pref_accessor_->GetPreferenceState(type_, name).persisted_value) {
+ if (pref_accessor_->GetPreferenceState(type_, name).persisted_value) {
// If the pref was updated, update it.
changes.push_back(syncer::SyncChange(
FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data));
diff --git a/chromium/components/sync_sessions/DEPS b/chromium/components/sync_sessions/DEPS
index c1e43a70f46..7a0379d156a 100644
--- a/chromium/components/sync_sessions/DEPS
+++ b/chromium/components/sync_sessions/DEPS
@@ -5,7 +5,7 @@ include_rules = [
"+components/history/core/browser",
"+components/keyed_service/core",
"+components/prefs",
- "+components/sessions",
+ "+components/sessions/core",
"+components/sync",
"+components/sync_device_info",
"+components/sync_user_events",
diff --git a/chromium/components/sync_sessions/favicon_cache.h b/chromium/components/sync_sessions/favicon_cache.h
index d1855d5241b..46165efe44c 100644
--- a/chromium/components/sync_sessions/favicon_cache.h
+++ b/chromium/components/sync_sessions/favicon_cache.h
@@ -56,8 +56,12 @@ enum IconSize {
struct SyncedFaviconInfo;
-// Encapsulates the logic for loading and storing synced favicons.
+// FAVICON SYNC IS DEPRECATED: This class now only serves to the translation
+// from page url to icon url using sessions sync information.
+// TODO(https://crbug.com/978775): Stop implementing syncer::SyncableService
+// and rename the class accordingly.
// TODO(zea): make this a KeyedService.
+// Encapsulates the logic for loading and storing synced favicons.
class FaviconCache : public syncer::SyncableService,
public history::HistoryServiceObserver {
public:
diff --git a/chromium/components/sync_sessions/favicon_cache_unittest.cc b/chromium/components/sync_sessions/favicon_cache_unittest.cc
index 0a46b39354c..7135b3acf73 100644
--- a/chromium/components/sync_sessions/favicon_cache_unittest.cc
+++ b/chromium/components/sync_sessions/favicon_cache_unittest.cc
@@ -11,7 +11,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/favicon/core/test/mock_favicon_service.h"
#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
@@ -299,10 +299,10 @@ class SyncFaviconCacheTest : public testing::Test {
const std::string& icon_bytes,
base::Time last_visit_time = base::Time::Now());
- void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<favicon::MockFaviconService> mock_favicon_service_;
FaviconCache cache_;
@@ -313,8 +313,7 @@ class SyncFaviconCacheTest : public testing::Test {
};
SyncFaviconCacheTest::SyncFaviconCacheTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
cache_(&mock_favicon_service_, nullptr, kMaxSyncFavicons),
sync_processor_(new TestChangeProcessor),
sync_processor_wrapper_(new syncer::SyncChangeProcessorWrapperForTest(
diff --git a/chromium/components/sync_sessions/local_session_event_handler_impl.cc b/chromium/components/sync_sessions/local_session_event_handler_impl.cc
index f2e81eed26b..6951bea2bfe 100644
--- a/chromium/components/sync_sessions/local_session_event_handler_impl.cc
+++ b/chromium/components/sync_sessions/local_session_event_handler_impl.cc
@@ -55,7 +55,7 @@ bool ScanForTabbedWindow(SyncedWindowDelegatesGetter* delegates_getter) {
for (const auto& window_iter_pair :
delegates_getter->GetSyncedWindowDelegates()) {
const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
- if (window_delegate->IsTypeTabbed() && IsWindowSyncable(*window_delegate)) {
+ if (window_delegate->IsTypeNormal() && IsWindowSyncable(*window_delegate)) {
return true;
}
}
@@ -219,7 +219,7 @@ void LocalSessionEventHandlerImpl::AssociateWindows(ReloadTabsOption option,
if (found_tabs) {
SyncedSessionWindow* synced_session_window =
current_session->windows[window_id].get();
- if (window_delegate->IsTypeTabbed()) {
+ if (window_delegate->IsTypeNormal()) {
synced_session_window->window_type =
sync_pb::SessionWindow_BrowserType_TYPE_TABBED;
} else if (window_delegate->IsTypePopup()) {
diff --git a/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc b/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
index f3efa7015f5..17f8ee7c188 100644
--- a/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
+++ b/chromium/components/sync_sessions/lost_navigations_recorder_unittest.cc
@@ -8,7 +8,7 @@
#include <string>
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/sync/syncable/entry.h"
#include "components/sync/syncable/mutable_entry.h"
#include "components/sync/syncable/syncable_base_transaction.h"
@@ -121,7 +121,7 @@ class LostNavigationsRecorderTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
int _id;
LostNavigationsRecorder recorder_;
syncer::TestDirectorySetterUpper dir_maker_;
diff --git a/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc
index 1b30ab846a4..92c692bd18a 100644
--- a/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc
+++ b/chromium/components/sync_sessions/open_tabs_ui_delegate_impl_unittest.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
#include "components/sync_sessions/mock_sync_sessions_client.h"
@@ -55,28 +56,31 @@ TEST_F(OpenTabsUIDelegateImplTest, ShouldSortSessions) {
// Create three sessions, with one window and tab each.
session_tracker_.PutWindowInSession(kSessionTag1, kWindowId1);
session_tracker_.PutTabInWindow(kSessionTag1, kWindowId1, kTabId1);
- session_tracker_.GetTab(kSessionTag1, kTabId1)
- ->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url1", "title1"));
+ sessions::SerializedNavigationEntry entry1 =
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+ entry1.set_virtual_url(GURL("http://url1"));
+ entry1.set_title(base::UTF8ToUTF16("title1"));
+ session_tracker_.GetTab(kSessionTag1, kTabId1)->navigations.push_back(entry1);
session_tracker_.GetSession(kSessionTag1)->modified_time =
kTime0 + base::TimeDelta::FromSeconds(3);
session_tracker_.PutWindowInSession(kSessionTag2, kWindowId2);
session_tracker_.PutTabInWindow(kSessionTag2, kWindowId2, kTabId2);
- session_tracker_.GetTab(kSessionTag2, kTabId2)
- ->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url2", "title2"));
+ sessions::SerializedNavigationEntry entry2 =
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+ entry2.set_virtual_url(GURL("http://url2"));
+ entry2.set_title(base::UTF8ToUTF16("title2"));
+ session_tracker_.GetTab(kSessionTag2, kTabId2)->navigations.push_back(entry2);
session_tracker_.GetSession(kSessionTag2)->modified_time =
kTime0 + base::TimeDelta::FromSeconds(1);
session_tracker_.PutWindowInSession(kSessionTag3, kWindowId3);
session_tracker_.PutTabInWindow(kSessionTag3, kWindowId3, kTabId3);
- session_tracker_.GetTab(kSessionTag3, kTabId3)
- ->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url3", "title3"));
+ sessions::SerializedNavigationEntry entry3 =
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+ entry3.set_virtual_url(GURL("http://url3"));
+ entry3.set_title(base::UTF8ToUTF16("title3"));
+ session_tracker_.GetTab(kSessionTag3, kTabId3)->navigations.push_back(entry3);
session_tracker_.GetSession(kSessionTag3)->modified_time =
kTime0 + base::TimeDelta::FromSeconds(2);
@@ -98,20 +102,17 @@ TEST_F(OpenTabsUIDelegateImplTest, ShouldSortTabs) {
sessions::SessionTab* tab1 = session_tracker_.GetTab(kSessionTag1, kTabId1);
tab1->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url1", "title1"));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
tab1->timestamp = kTime0 + base::TimeDelta::FromSeconds(3);
sessions::SessionTab* tab2 = session_tracker_.GetTab(kSessionTag1, kTabId2);
tab2->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url1", "title1"));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
tab2->timestamp = kTime0 + base::TimeDelta::FromSeconds(1);
sessions::SessionTab* tab3 = session_tracker_.GetTab(kSessionTag1, kTabId3);
tab3->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url1", "title1"));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
tab3->timestamp = kTime0 + base::TimeDelta::FromSeconds(2);
std::vector<const SessionTab*> tabs;
@@ -136,9 +137,8 @@ TEST_F(OpenTabsUIDelegateImplTest, ShouldSkipNonPresentable) {
session_tracker_.PutWindowInSession(kSessionTag2, kWindowId2);
session_tracker_.PutTabInWindow(kSessionTag2, kWindowId2, kTabId2);
session_tracker_.GetTab(kSessionTag2, kTabId2)
- ->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url2", "title2"));
+ ->navigations.push_back(sessions::SerializedNavigationEntryTestHelper::
+ CreateNavigationForTest());
std::vector<const SyncedSession*> sessions;
EXPECT_TRUE(delegate_.GetAllForeignSessions(&sessions));
@@ -152,19 +152,23 @@ TEST_F(OpenTabsUIDelegateImplTest, ShouldSkipNonSyncableTabs) {
// Create two sessions, with one window and tab each. The first of the two
// contains a URL that should not be synced.
+ sessions::SerializedNavigationEntry nonsyncable_entry =
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+ nonsyncable_entry.set_virtual_url(GURL("http://url1"));
+ nonsyncable_entry.set_title(base::UTF8ToUTF16("title1"));
session_tracker_.PutWindowInSession(kSessionTag1, kWindowId1);
session_tracker_.PutTabInWindow(kSessionTag1, kWindowId1, kTabId1);
session_tracker_.GetTab(kSessionTag1, kTabId1)
- ->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url1", "title1"));
+ ->navigations.push_back(nonsyncable_entry);
+ sessions::SerializedNavigationEntry syncable_entry =
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+ syncable_entry.set_virtual_url(GURL("http://otherurl"));
+ syncable_entry.set_title(base::UTF8ToUTF16("title1"));
session_tracker_.PutWindowInSession(kSessionTag2, kWindowId2);
session_tracker_.PutTabInWindow(kSessionTag2, kWindowId2, kTabId2);
session_tracker_.GetTab(kSessionTag2, kTabId2)
- ->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://url2", "title2"));
+ ->navigations.push_back(syncable_entry);
std::vector<const SyncedSession*> sessions;
EXPECT_TRUE(delegate_.GetAllForeignSessions(&sessions));
diff --git a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc
index ca6743edc49..cea10db7e1b 100644
--- a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc
+++ b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.cc
@@ -46,9 +46,11 @@ void ProxyTabsDataTypeController::LoadModels(
model_load_callback.Run(type(), syncer::SyncError());
}
-void ProxyTabsDataTypeController::RegisterWithBackend(
- base::OnceCallback<void(bool)> set_downloaded,
- syncer::ModelTypeConfigurer* configurer) {}
+syncer::DataTypeController::RegisterWithBackendResult
+ProxyTabsDataTypeController::RegisterWithBackend(
+ syncer::ModelTypeConfigurer* configurer) {
+ return REGISTRATION_IGNORED;
+}
void ProxyTabsDataTypeController::StartAssociating(
StartCallback start_callback) {
diff --git a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
index 9d31df7c331..b5ae7c6ce7b 100644
--- a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
+++ b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
@@ -28,8 +28,8 @@ class ProxyTabsDataTypeController : public syncer::DataTypeController {
void BeforeLoadModels(syncer::ModelTypeConfigurer* configurer) override;
void LoadModels(const syncer::ConfigureContext& configure_context,
const ModelLoadCallback& model_load_callback) override;
- void RegisterWithBackend(base::OnceCallback<void(bool)> set_downloaded,
- syncer::ModelTypeConfigurer* configurer) override;
+ RegisterWithBackendResult RegisterWithBackend(
+ syncer::ModelTypeConfigurer* configurer) override;
void StartAssociating(StartCallback start_callback) override;
void Stop(syncer::ShutdownReason shutdown_reason,
StopCallback callback) override;
diff --git a/chromium/components/sync_sessions/session_model_type_controller.cc b/chromium/components/sync_sessions/session_model_type_controller.cc
index 1054648ad64..64ae9a53e19 100644
--- a/chromium/components/sync_sessions/session_model_type_controller.cc
+++ b/chromium/components/sync_sessions/session_model_type_controller.cc
@@ -45,22 +45,26 @@ SessionModelTypeController::~SessionModelTypeController() {
sync_service_->RemoveObserver(this);
}
-bool SessionModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+SessionModelTypeController::GetPreconditionState() const {
DCHECK(CalledOnValidThread());
- return !pref_service_->GetBoolean(history_disabled_pref_name_) &&
- !(syncer::IsWebSignout(sync_service_->GetAuthError()) &&
- base::FeatureList::IsEnabled(kStopSessionsIfSyncPaused));
+ bool preconditions_met =
+ !pref_service_->GetBoolean(history_disabled_pref_name_) &&
+ !(syncer::IsWebSignout(sync_service_->GetAuthError()) &&
+ base::FeatureList::IsEnabled(kStopSessionsIfSyncPaused));
+ return preconditions_met ? PreconditionState::kPreconditionsMet
+ : PreconditionState::kMustStopAndKeepData;
}
void SessionModelTypeController::OnStateChanged(syncer::SyncService* sync) {
DCHECK(CalledOnValidThread());
// Most of these calls will be no-ops but SyncService handles that just fine.
- sync_service_->ReadyForStartChanged(type());
+ sync_service_->DataTypePreconditionChanged(type());
}
void SessionModelTypeController::OnSavingBrowserHistoryPrefChanged() {
DCHECK(CalledOnValidThread());
- sync_service_->ReadyForStartChanged(type());
+ sync_service_->DataTypePreconditionChanged(type());
}
} // namespace sync_sessions
diff --git a/chromium/components/sync_sessions/session_model_type_controller.h b/chromium/components/sync_sessions/session_model_type_controller.h
index b5a77d56073..13c07973487 100644
--- a/chromium/components/sync_sessions/session_model_type_controller.h
+++ b/chromium/components/sync_sessions/session_model_type_controller.h
@@ -33,7 +33,7 @@ class SessionModelTypeController : public syncer::ModelTypeController,
~SessionModelTypeController() override;
// DataTypeController overrides.
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
// syncer::SyncServiceObserver implementation.
void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/chromium/components/sync_sessions/session_store_unittest.cc b/chromium/components/sync_sessions/session_store_unittest.cc
index 3cc21fa4399..7bc7294e79f 100644
--- a/chromium/components/sync_sessions/session_store_unittest.cc
+++ b/chromium/components/sync_sessions/session_store_unittest.cc
@@ -13,7 +13,7 @@
#include "base/cancelable_callback.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync/base/hash_util.h"
#include "components/sync/model/model_type_store_test_util.h"
@@ -175,7 +175,7 @@ class SessionStoreOpenTest : public ::testing::Test {
~SessionStoreOpenTest() override {}
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple pref_service_;
SessionSyncPrefs session_sync_prefs_;
std::unique_ptr<MockSyncSessionsClient> mock_sync_sessions_client_;
diff --git a/chromium/components/sync_sessions/session_sync_bridge_unittest.cc b/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
index f4ced445909..41ae2f8a102 100644
--- a/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
+++ b/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
@@ -15,7 +15,7 @@
#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync/base/hash_util.h"
#include "components/sync/base/sync_prefs.h"
@@ -322,7 +322,7 @@ class SessionSyncBridgeTest : public ::testing::Test {
syncer::ModelTypeStore* underlying_store() { return store_.get(); }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
const std::unique_ptr<syncer::ModelTypeStore> store_;
// Dependencies.
diff --git a/chromium/components/sync_sessions/session_sync_test_helper.cc b/chromium/components/sync_sessions/session_sync_test_helper.cc
index 8d301b723a4..cb86ee6a1a0 100644
--- a/chromium/components/sync_sessions/session_sync_test_helper.cc
+++ b/chromium/components/sync_sessions/session_sync_test_helper.cc
@@ -67,7 +67,7 @@ void SessionSyncTestHelper::VerifySyncedSession(
FAIL();
ASSERT_EQ(win_iter->size(), win_ptr->tabs.size());
ASSERT_EQ(0, win_ptr->selected_tab_index);
- ASSERT_EQ(sessions::SessionWindow::TYPE_TABBED, win_ptr->type);
+ ASSERT_EQ(sessions::SessionWindow::TYPE_NORMAL, win_ptr->type);
int j = 0;
for (auto tab_iter = (*win_iter).begin(); tab_iter != (*win_iter).end();
++tab_iter, ++j) {
diff --git a/chromium/components/sync_sessions/synced_session_tracker.cc b/chromium/components/sync_sessions/synced_session_tracker.cc
index ae74d646cc3..4e2224c5e1d 100644
--- a/chromium/components/sync_sessions/synced_session_tracker.cc
+++ b/chromium/components/sync_sessions/synced_session_tracker.cc
@@ -93,7 +93,7 @@ void PopulateSyncedSessionWindowFromSpecifics(
if (specifics.has_browser_type()) {
if (specifics.browser_type() ==
sync_pb::SessionWindow_BrowserType_TYPE_TABBED) {
- session_window->type = sessions::SessionWindow::TYPE_TABBED;
+ session_window->type = sessions::SessionWindow::TYPE_NORMAL;
} else {
// Note: custom tabs are treated like popup windows on restore, as you can
// restore a custom tab on a platform that doesn't support them.
diff --git a/chromium/components/sync_sessions/synced_session_tracker_unittest.cc b/chromium/components/sync_sessions/synced_session_tracker_unittest.cc
index 8d8ea545ff5..983797468a5 100644
--- a/chromium/components/sync_sessions/synced_session_tracker_unittest.cc
+++ b/chromium/components/sync_sessions/synced_session_tracker_unittest.cc
@@ -38,7 +38,6 @@ const sync_pb::SyncEnums::DeviceType kDeviceType =
const char kTag[] = "tag";
const char kTag2[] = "tag2";
const char kTag3[] = "tag3";
-const char kTitle[] = "title";
const int kTabNode1 = 0;
const int kTabNode2 = 1;
const int kTabNode3 = 2;
@@ -203,8 +202,7 @@ TEST_F(SyncedSessionTrackerTest, LookupAllSessions) {
sessions::SessionTab* tab = tracker_.GetTab(kTag, kTab1);
ASSERT_TRUE(tab);
tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(kValidUrl,
- kTitle));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::PRESENTABLE),
ElementsAre(HasSessionTag(kTag)));
@@ -215,8 +213,7 @@ TEST_F(SyncedSessionTrackerTest, LookupAllSessions) {
sessions::SessionTab* tab2 = tracker_.GetTab(kTag2, kTab2);
ASSERT_TRUE(tab2);
tab2->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(kValidUrl,
- kTitle));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
EXPECT_THAT(tracker_.LookupAllSessions(SyncedSessionTracker::PRESENTABLE),
ElementsAre(HasSessionTag(kTag), HasSessionTag(kTag2)));
}
@@ -235,8 +232,8 @@ TEST_F(SyncedSessionTrackerTest, LookupAllForeignSessions) {
sessions::SessionTab* tab = tracker_.GetTab(kTag, kTab1);
ASSERT_TRUE(tab);
tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(kValidUrl,
- kTitle));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
+ tab->navigations.back().set_virtual_url(GURL(kValidUrl));
tracker_.GetSession(kTag2);
tracker_.GetSession(kTag3);
tracker_.PutWindowInSession(kTag3, kWindow1);
@@ -244,8 +241,8 @@ TEST_F(SyncedSessionTrackerTest, LookupAllForeignSessions) {
tab = tracker_.GetTab(kTag3, kTab1);
ASSERT_TRUE(tab);
tab->navigations.push_back(
- sessions::SerializedNavigationEntryTestHelper::CreateNavigation(
- kInvalidUrl, kTitle));
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigationForTest());
+ tab->navigations.back().set_virtual_url(GURL(kInvalidUrl));
// Only the session with a valid window and tab gets returned.
EXPECT_THAT(
tracker_.LookupAllForeignSessions(SyncedSessionTracker::PRESENTABLE),
diff --git a/chromium/components/sync_sessions/synced_session_unittest.cc b/chromium/components/sync_sessions/synced_session_unittest.cc
index 67c31047a9e..07ff950507e 100644
--- a/chromium/components/sync_sessions/synced_session_unittest.cc
+++ b/chromium/components/sync_sessions/synced_session_unittest.cc
@@ -253,9 +253,11 @@ TEST(SyncedSessionTest, SessionTabToSyncData) {
tab.user_agent_override = "fake";
tab.timestamp = base::Time::FromInternalValue(100);
for (int i = 0; i < 5; ++i) {
- tab.navigations.push_back(
- SerializedNavigationEntryTestHelper::CreateNavigation(
- "http://foo/" + base::NumberToString(i), "title"));
+ sessions::SerializedNavigationEntry entry =
+ SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+ entry.set_virtual_url(GURL("http://foo/" + base::NumberToString(i)));
+ entry.set_title(base::UTF8ToUTF16("title" + base::NumberToString(i)));
+ tab.navigations.push_back(entry);
}
tab.session_storage_persistent_id = "fake";
diff --git a/chromium/components/sync_sessions/synced_window_delegate.h b/chromium/components/sync_sessions/synced_window_delegate.h
index 28d2d6f5229..1a78be80825 100644
--- a/chromium/components/sync_sessions/synced_window_delegate.h
+++ b/chromium/components/sync_sessions/synced_window_delegate.h
@@ -33,11 +33,8 @@ class SyncedWindowDelegate {
// see Browser::active_index
virtual int GetActiveIndex() const = 0;
- // see Browser::is_app
- virtual bool IsApp() const = 0;
-
- // see Browser::is_type_tabbed
- virtual bool IsTypeTabbed() const = 0;
+ // see Browser::is_type_normal
+ virtual bool IsTypeNormal() const = 0;
// see Browser::is_type_popup
virtual bool IsTypePopup() const = 0;
diff --git a/chromium/components/sync_sessions/test_synced_window_delegates_getter.cc b/chromium/components/sync_sessions/test_synced_window_delegates_getter.cc
index 4b599e93ac9..af19b3c8511 100644
--- a/chromium/components/sync_sessions/test_synced_window_delegates_getter.cc
+++ b/chromium/components/sync_sessions/test_synced_window_delegates_getter.cc
@@ -337,11 +337,7 @@ int TestSyncedWindowDelegate::GetActiveIndex() const {
return 0;
}
-bool TestSyncedWindowDelegate::IsApp() const {
- return false;
-}
-
-bool TestSyncedWindowDelegate::IsTypeTabbed() const {
+bool TestSyncedWindowDelegate::IsTypeNormal() const {
return window_type_ == sync_pb::SessionWindow_BrowserType_TYPE_TABBED;
}
diff --git a/chromium/components/sync_sessions/test_synced_window_delegates_getter.h b/chromium/components/sync_sessions/test_synced_window_delegates_getter.h
index 5e84190a80e..108df040d97 100644
--- a/chromium/components/sync_sessions/test_synced_window_delegates_getter.h
+++ b/chromium/components/sync_sessions/test_synced_window_delegates_getter.h
@@ -142,8 +142,7 @@ class TestSyncedWindowDelegate : public SyncedWindowDelegate {
SessionID GetSessionId() const override;
int GetTabCount() const override;
int GetActiveIndex() const override;
- bool IsApp() const override;
- bool IsTypeTabbed() const override;
+ bool IsTypeNormal() const override;
bool IsTypePopup() const override;
bool IsTabPinned(const SyncedTabDelegate* tab) const override;
SyncedTabDelegate* GetTabAt(int index) const override;
diff --git a/chromium/components/sync_user_events/user_event_model_type_controller.cc b/chromium/components/sync_user_events/user_event_model_type_controller.cc
index b9d8ef02663..5c22457cdbc 100644
--- a/chromium/components/sync_user_events/user_event_model_type_controller.cc
+++ b/chromium/components/sync_user_events/user_event_model_type_controller.cc
@@ -27,16 +27,22 @@ UserEventModelTypeController::~UserEventModelTypeController() {
sync_service_->RemoveObserver(this);
}
-bool UserEventModelTypeController::ReadyForStart() const {
+DataTypeController::PreconditionState
+UserEventModelTypeController::GetPreconditionState() const {
+ if (sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase()) {
+ return PreconditionState::kMustStopAndClearData;
+ }
// TODO(crbug.com/906995): Remove the syncer::IsWebSignout() check once we
// stop sync in this state. Also remove the "+google_apis/gaia" include
// dependency and the "//google_apis" build dependency of sync_user_events.
- return !sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase() &&
- !syncer::IsWebSignout(sync_service_->GetAuthError());
+ if (syncer::IsWebSignout(sync_service_->GetAuthError())) {
+ return PreconditionState::kMustStopAndClearData;
+ }
+ return PreconditionState::kPreconditionsMet;
}
void UserEventModelTypeController::OnStateChanged(syncer::SyncService* sync) {
- sync->ReadyForStartChanged(type());
+ sync->DataTypePreconditionChanged(type());
}
} // namespace syncer
diff --git a/chromium/components/sync_user_events/user_event_model_type_controller.h b/chromium/components/sync_user_events/user_event_model_type_controller.h
index b162b6b1df4..fd4d79648a2 100644
--- a/chromium/components/sync_user_events/user_event_model_type_controller.h
+++ b/chromium/components/sync_user_events/user_event_model_type_controller.h
@@ -25,7 +25,7 @@ class UserEventModelTypeController : public syncer::ModelTypeController,
~UserEventModelTypeController() override;
// syncer::DataTypeController implementation.
- bool ReadyForStart() const override;
+ PreconditionState GetPreconditionState() const override;
// syncer::SyncServiceObserver implementation.
void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/chromium/components/sync_user_events/user_event_service_impl_unittest.cc b/chromium/components/sync_user_events/user_event_service_impl_unittest.cc
index a0ca6897635..fbc885912e1 100644
--- a/chromium/components/sync_user_events/user_event_service_impl_unittest.cc
+++ b/chromium/components/sync_user_events/user_event_service_impl_unittest.cc
@@ -7,7 +7,7 @@
#include <utility>
#include <vector>
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/sync/base/model_type.h"
#include "components/sync/driver/test_sync_service.h"
#include "components/sync/model/mock_model_type_change_processor.h"
@@ -78,7 +78,7 @@ class UserEventServiceImplTest : public testing::Test {
MockModelTypeChangeProcessor* mock_processor() { return &mock_processor_; }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
syncer::TestSyncService sync_service_;
testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
TestGlobalIdMapper mapper_;
diff --git a/chromium/components/sync_user_events/user_event_sync_bridge_unittest.cc b/chromium/components/sync_user_events/user_event_sync_bridge_unittest.cc
index ed112219e57..fc6ff248fbc 100644
--- a/chromium/components/sync_user_events/user_event_sync_bridge_unittest.cc
+++ b/chromium/components/sync_user_events/user_event_sync_bridge_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/sync/model/data_batch.h"
#include "components/sync/model/mock_model_type_change_processor.h"
#include "components/sync/model/model_type_store_test_util.h"
@@ -185,7 +185,7 @@ class UserEventSyncBridgeTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
TestGlobalIdMapper test_global_id_mapper_;
std::unique_ptr<UserEventSyncBridge> bridge_;
diff --git a/chromium/components/timers/OWNERS b/chromium/components/timers/OWNERS
index 8a3310217a3..36c0d0f494e 100644
--- a/chromium/components/timers/OWNERS
+++ b/chromium/components/timers/OWNERS
@@ -1 +1,2 @@
chirantan@chromium.org
+# COMPONENT: Internals>TaskScheduler
diff --git a/chromium/components/timers/alarm_timer_chromeos.cc b/chromium/components/timers/alarm_timer_chromeos.cc
index 787e4f54411..af98c0650b5 100644
--- a/chromium/components/timers/alarm_timer_chromeos.cc
+++ b/chromium/components/timers/alarm_timer_chromeos.cc
@@ -48,7 +48,7 @@ std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateInternal(
}
SimpleAlarmTimer::SimpleAlarmTimer(base::ScopedFD alarm_fd)
- : alarm_fd_(std::move(alarm_fd)), weak_factory_(this) {}
+ : alarm_fd_(std::move(alarm_fd)) {}
SimpleAlarmTimer::~SimpleAlarmTimer() {
DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
diff --git a/chromium/components/timers/alarm_timer_chromeos.h b/chromium/components/timers/alarm_timer_chromeos.h
index e1301e9e947..c1e00122a2f 100644
--- a/chromium/components/timers/alarm_timer_chromeos.h
+++ b/chromium/components/timers/alarm_timer_chromeos.h
@@ -79,7 +79,7 @@ class SimpleAlarmTimer : public base::RetainingOneShotTimer {
std::unique_ptr<base::PendingTask> pending_task_;
// Used to invalidate pending callbacks.
- base::WeakPtrFactory<SimpleAlarmTimer> weak_factory_;
+ base::WeakPtrFactory<SimpleAlarmTimer> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SimpleAlarmTimer);
};
diff --git a/chromium/components/timers/alarm_timer_unittest.cc b/chromium/components/timers/alarm_timer_unittest.cc
index 166144ea329..c9e681304aa 100644
--- a/chromium/components/timers/alarm_timer_unittest.cc
+++ b/chromium/components/timers/alarm_timer_unittest.cc
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -97,8 +97,8 @@ class SelfDeletingAlarmTimerTester {
// that timers work properly in all configurations.
TEST(AlarmTimerTest, SimpleAlarmTimer) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
base::RunLoop run_loop;
bool did_run = false;
@@ -112,8 +112,8 @@ TEST(AlarmTimerTest, SimpleAlarmTimer) {
}
TEST(AlarmTimerTest, SimpleAlarmTimer_Cancel) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
bool did_run_a = false;
AlarmTimerTester* a =
@@ -140,8 +140,8 @@ TEST(AlarmTimerTest, SimpleAlarmTimer_Cancel) {
// If underlying timer does not handle this properly, we will crash or fail
// in full page heap environment.
TEST(AlarmTimerTest, SelfDeletingAlarmTimer) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
base::RunLoop run_loop;
bool did_run = false;
@@ -155,8 +155,8 @@ TEST(AlarmTimerTest, SelfDeletingAlarmTimer) {
}
TEST(AlarmTimerTest, AlarmTimerZeroDelay) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
base::RunLoop run_loop;
bool did_run = false;
@@ -170,8 +170,8 @@ TEST(AlarmTimerTest, AlarmTimerZeroDelay) {
}
TEST(AlarmTimerTest, AlarmTimerZeroDelay_Cancel) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
bool did_run_a = false;
AlarmTimerTester* a =
@@ -202,8 +202,8 @@ TEST(AlarmTimerTest, MessageLoopShutdown) {
// if debug heap checking is enabled.
bool did_run = false;
{
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
AlarmTimerTester a(&did_run, kTenMilliseconds, base::OnceClosure());
AlarmTimerTester b(&did_run, kTenMilliseconds, base::OnceClosure());
@@ -223,8 +223,8 @@ TEST(AlarmTimerTest, MessageLoopShutdown) {
}
TEST(AlarmTimerTest, NonRepeatIsRunning) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
auto timer = SimpleAlarmTimer::CreateForTesting();
EXPECT_FALSE(timer->IsRunning());
@@ -244,8 +244,8 @@ TEST(AlarmTimerTest, NonRepeatIsRunning) {
}
TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
auto timer = SimpleAlarmTimer::CreateForTesting();
EXPECT_FALSE(timer->IsRunning());
@@ -290,8 +290,8 @@ void SetCallbackHappened2(base::OnceClosure quit_closure) {
TEST(AlarmTimerTest, ContinuationStopStart) {
ClearAllCallbackHappened();
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
auto timer = SimpleAlarmTimer::CreateForTesting();
timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
@@ -311,8 +311,8 @@ TEST(AlarmTimerTest, ContinuationStopStart) {
TEST(AlarmTimerTest, ContinuationReset) {
ClearAllCallbackHappened();
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
base::RunLoop run_loop;
auto timer = SimpleAlarmTimer::CreateForTesting();
@@ -328,8 +328,8 @@ TEST(AlarmTimerTest, ContinuationReset) {
// Verify that no crash occurs if a timer is deleted while its callback is
// running.
TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunning) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
base::RunLoop run_loop;
@@ -347,8 +347,8 @@ TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunning) {
// Verify that no crash occurs if a zero-delay timer is deleted while its
// callback is running.
TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunningZeroDelay) {
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
base::RunLoop run_loop;
// Will be deleted by the callback.
diff --git a/chromium/components/tracing/child/background_tracing_agent_impl_unittest.cc b/chromium/components/tracing/child/background_tracing_agent_impl_unittest.cc
index a32cb570f8f..7a39f75c063 100644
--- a/chromium/components/tracing/child/background_tracing_agent_impl_unittest.cc
+++ b/chromium/components/tracing/child/background_tracing_agent_impl_unittest.cc
@@ -7,7 +7,7 @@
#include "base/run_loop.h"
#include "base/metrics/histogram_macros.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/tracing/child/background_tracing_agent_provider_impl.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -68,7 +68,7 @@ class BackgroundTracingAgentImplTest : public testing::Test {
BackgroundTracingAgentClientRecorder* recorder() const { return recorder_; }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
mojo::Remote<tracing::mojom::BackgroundTracingAgentProvider> provider_;
mojo::Remote<tracing::mojom::BackgroundTracingAgent> agent_;
mojo::UniqueReceiverSet<tracing::mojom::BackgroundTracingAgentProvider>
diff --git a/chromium/components/tracing/common/trace_startup_config.cc b/chromium/components/tracing/common/trace_startup_config.cc
index babe9cc1608..a5d7eb863a0 100644
--- a/chromium/components/tracing/common/trace_startup_config.cc
+++ b/chromium/components/tracing/common/trace_startup_config.cc
@@ -29,7 +29,6 @@ namespace {
// Maximum trace config file size that will be loaded, in bytes.
const size_t kTraceConfigFileSizeLimit = 64 * 1024;
-const int kDefaultStartupDuration = 5;
// Trace config file path:
// - Android: /data/local/chrome-trace-config.json
@@ -118,7 +117,7 @@ void TraceStartupConfig::SetDisabled() {
}
bool TraceStartupConfig::IsTracingStartupForDuration() const {
- return IsEnabled() && startup_duration_ > 0 &&
+ return IsEnabled() && startup_duration_in_seconds_ > 0 &&
session_owner_ == SessionOwner::kTracingController;
}
@@ -129,7 +128,7 @@ base::trace_event::TraceConfig TraceStartupConfig::GetTraceConfig() const {
int TraceStartupConfig::GetStartupDuration() const {
DCHECK(IsEnabled() || IsUsingPerfettoOutput());
- return startup_duration_;
+ return startup_duration_in_seconds_;
}
bool TraceStartupConfig::ShouldTraceToResultFile() const {
@@ -174,19 +173,21 @@ bool TraceStartupConfig::AttemptAdoptBySessionOwner(SessionOwner owner) {
bool TraceStartupConfig::EnableFromCommandLine() {
auto* command_line = base::CommandLine::ForCurrentProcess();
+ // Startup duration can be used by along with perfetto-output-file flag.
+ if (command_line->HasSwitch(switches::kTraceStartupDuration)) {
+ std::string startup_duration_str =
+ command_line->GetSwitchValueASCII(switches::kTraceStartupDuration);
+ if (!startup_duration_str.empty() &&
+ !base::StringToInt(startup_duration_str, &startup_duration_in_seconds_)) {
+ DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
+ << "=" << startup_duration_str << " defaulting to 5 (secs)";
+ startup_duration_in_seconds_ = kDefaultStartupDurationInSeconds;
+ }
+ }
+
if (!command_line->HasSwitch(switches::kTraceStartup))
return false;
- std::string startup_duration_str =
- command_line->GetSwitchValueASCII(switches::kTraceStartupDuration);
- startup_duration_ = kDefaultStartupDuration;
- if (!startup_duration_str.empty() &&
- !base::StringToInt(startup_duration_str, &startup_duration_)) {
- DLOG(WARNING) << "Could not parse --" << switches::kTraceStartupDuration
- << "=" << startup_duration_str << " defaulting to 5 (secs)";
- startup_duration_ = kDefaultStartupDuration;
- }
-
trace_config_ = base::trace_event::TraceConfig(
command_line->GetSwitchValueASCII(switches::kTraceStartup),
command_line->GetSwitchValueASCII(switches::kTraceStartupRecordMode));
@@ -210,9 +211,6 @@ bool TraceStartupConfig::EnableFromConfigFile() {
#endif
if (trace_config_file.empty()) {
- // If the trace config file path is not specified, trace Chrome with the
- // default configuration for 5 sec.
- startup_duration_ = kDefaultStartupDuration;
is_enabled_ = true;
should_trace_to_result_file_ = true;
DLOG(WARNING) << "Use default trace config.";
@@ -257,7 +255,7 @@ bool TraceStartupConfig::EnableFromBackgroundTracing() {
should_trace_to_result_file_ = false;
// Set startup duration to 0 since background tracing config will configure
// the durations later.
- startup_duration_ = 0;
+ startup_duration_in_seconds_ = 0;
return true;
}
@@ -276,11 +274,11 @@ bool TraceStartupConfig::ParseTraceConfigFileContent(
trace_config_ = base::trace_event::TraceConfig(*trace_config_dict);
- if (!dict->GetInteger(kStartupDurationParam, &startup_duration_))
- startup_duration_ = 0;
+ if (!dict->GetInteger(kStartupDurationParam, &startup_duration_in_seconds_))
+ startup_duration_in_seconds_ = 0;
- if (startup_duration_ < 0)
- startup_duration_ = 0;
+ if (startup_duration_in_seconds_ < 0)
+ startup_duration_in_seconds_ = 0;
base::FilePath::StringType result_file_or_dir_str;
if (dict->GetString(kResultFileParam, &result_file_or_dir_str))
diff --git a/chromium/components/tracing/common/trace_startup_config.h b/chromium/components/tracing/common/trace_startup_config.h
index 62f3ce10c3b..0ed5fa38a3f 100644
--- a/chromium/components/tracing/common/trace_startup_config.h
+++ b/chromium/components/tracing/common/trace_startup_config.h
@@ -147,6 +147,8 @@ class TRACING_EXPORT TraceStartupConfig {
friend class content::CommandlineStartupTracingTest;
friend class content::BackgroundStartupTracingTest;
+ constexpr static int kDefaultStartupDurationInSeconds = 5;
+
TraceStartupConfig();
~TraceStartupConfig();
@@ -161,7 +163,7 @@ class TRACING_EXPORT TraceStartupConfig {
bool is_enabled_ = false;
bool enable_background_tracing_for_testing_ = false;
base::trace_event::TraceConfig trace_config_;
- int startup_duration_ = 0;
+ int startup_duration_in_seconds_ = kDefaultStartupDurationInSeconds;
bool should_trace_to_result_file_ = false;
base::FilePath result_file_;
bool finished_writing_to_file_ = false;
diff --git a/chromium/components/translate/content/common/translate.typemap b/chromium/components/translate/content/common/translate.typemap
index 3aafd6a88ea..7486296ddb6 100644
--- a/chromium/components/translate/content/common/translate.typemap
+++ b/chromium/components/translate/content/common/translate.typemap
@@ -8,9 +8,9 @@ public_headers = [
"//components/translate/core/common/translate_errors.h",
]
traits_headers =
- [ "//components/translate/content/common/translate_struct_traits.h" ]
+ [ "//components/translate/content/common/translate_mojom_traits.h" ]
sources = [
- "//components/translate/content/common/translate_struct_traits.cc",
+ "//components/translate/content/common/translate_mojom_traits.cc",
]
deps = [
"//base",
@@ -18,6 +18,6 @@ deps = [
]
type_mappings = [
- "translate.mojom.LanguageDetectionDetails=translate::LanguageDetectionDetails",
- "translate.mojom.TranslateError=translate::TranslateErrors::Type",
+ "translate.mojom.LanguageDetectionDetails=::translate::LanguageDetectionDetails",
+ "translate.mojom.TranslateError=::translate::TranslateErrors::Type",
]
diff --git a/chromium/components/ui_devtools/BUILD.gn b/chromium/components/ui_devtools/BUILD.gn
index 1418dc99996..b01fc302441 100644
--- a/chromium/components/ui_devtools/BUILD.gn
+++ b/chromium/components/ui_devtools/BUILD.gn
@@ -2,6 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/buildflag_header.gni")
+import("//components/ui_devtools/devtools.gni")
+
_inspector_protocol = "//third_party/inspector_protocol"
import("$_inspector_protocol/inspector_protocol.gni")
@@ -19,6 +22,8 @@ _protocol_generated = [
"Page.h",
"Protocol.cpp",
"Protocol.h",
+ "Tracing.h",
+ "Tracing.cpp",
]
action("protocol_compatibility") {
@@ -58,9 +63,17 @@ inspector_protocol_generate("protocol_generated_sources") {
outputs = _protocol_generated
}
+buildflag_header("buildflags") {
+ header = "buildflags.h"
+ flags = [ "USE_VIZ_DEVTOOLS=$use_viz_devtools" ]
+}
+
component("ui_devtools") {
sources = rebase_path(_protocol_generated, ".", target_gen_dir)
sources += [
+ "agent_util.cc",
+ "agent_util.h",
+ "connector_delegate.h",
"css_agent.cc",
"css_agent.h",
"devtools_base_agent.h",
@@ -79,6 +92,8 @@ component("ui_devtools") {
"root_element.h",
"switches.cc",
"switches.h",
+ "tracing_agent.cc",
+ "tracing_agent.h",
"ui_element.cc",
"ui_element.h",
"ui_element_delegate.h",
@@ -95,13 +110,20 @@ component("ui_devtools") {
":devtools_protocol_encoding",
":protocol_generated_sources",
"//base",
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
"//net",
+ "//services/tracing/public/cpp",
+ "//services/tracing/public/mojom",
"//ui/gfx",
]
public_deps = [
+ ":buildflags",
"//services/network/public/cpp",
"//services/network/public/mojom",
+ "//services/service_manager/public/cpp",
+ "//third_party/perfetto/gn:default_deps",
]
}
@@ -142,6 +164,10 @@ source_set("unit_tests") {
"devtools_server_unittest.cc",
]
+ data = [
+ "//components/test/data/ui_devtools/test_file.cc",
+ ]
+
deps = [
":test_support",
"//base/test:test_support",
diff --git a/chromium/components/ui_devtools/DEPS b/chromium/components/ui_devtools/DEPS
index 9dab2575ff0..454d9846f8d 100644
--- a/chromium/components/ui_devtools/DEPS
+++ b/chromium/components/ui_devtools/DEPS
@@ -6,6 +6,8 @@ include_rules = [
"+third_party/blink/renderer/platform/inspector_protocol",
"+third_party/inspector_protocol",
"+ui/gfx",
+ "+services/tracing/public",
+ "+mojo/public",
]
specific_include_rules = {
diff --git a/chromium/components/ui_devtools/agent_util.cc b/chromium/components/ui_devtools/agent_util.cc
new file mode 100644
index 00000000000..f1dda66f5d1
--- /dev/null
+++ b/chromium/components/ui_devtools/agent_util.cc
@@ -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.
+
+#include "components/ui_devtools/agent_util.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+
+namespace ui_devtools {
+
+namespace {
+
+void OnSourceFile(base::OnceClosure quit_closure,
+ bool* return_value,
+ bool read_file_result) {
+ *return_value = read_file_result;
+ std::move(quit_closure).Run();
+}
+
+} // namespace
+
+const char kChromiumCodeSearchURL[] = "https://cs.chromium.org/";
+const char kChromiumCodeSearchSrcURL[] =
+ "https://cs.chromium.org/chromium/src/";
+
+bool GetSourceCode(std::string path, std::string* source_code) {
+ base::FilePath src_dir;
+ base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
+ src_dir = src_dir.AppendASCII(path);
+
+ base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+
+ bool return_value;
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+ base::BindOnce(&base::ReadFileToString, src_dir, source_code),
+ base::BindOnce(&OnSourceFile, run_loop.QuitClosure(), &return_value));
+
+ run_loop.Run();
+
+ if (!return_value)
+ DLOG(ERROR) << "Could not get source file of " << src_dir.value() << ".";
+
+ return return_value;
+}
+
+} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/agent_util.h b/chromium/components/ui_devtools/agent_util.h
new file mode 100644
index 00000000000..caaf2bdb173
--- /dev/null
+++ b/chromium/components/ui_devtools/agent_util.h
@@ -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.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_AGENT_UTIL_H_
+#define COMPONENTS_UI_DEVTOOLS_AGENT_UTIL_H_
+
+#include "base/files/file_path.h"
+#include "components/ui_devtools/devtools_export.h"
+
+namespace ui_devtools {
+
+UI_DEVTOOLS_EXPORT extern const char kChromiumCodeSearchURL[];
+UI_DEVTOOLS_EXPORT extern const char kChromiumCodeSearchSrcURL[];
+
+// Synchonously gets source code and returns true if successful.
+bool UI_DEVTOOLS_EXPORT GetSourceCode(std::string path,
+ std::string* source_code);
+
+} // namespace ui_devtools
+
+#endif // COMPONENTS_UI_DEVTOOLS_AGENT_UTIL_H_
diff --git a/chromium/components/ui_devtools/connector_delegate.h b/chromium/components/ui_devtools/connector_delegate.h
new file mode 100644
index 00000000000..29b54025058
--- /dev/null
+++ b/chromium/components/ui_devtools/connector_delegate.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 COMPONENTS_UI_DEVTOOLS_CONNECTOR_DELEGATE_H_
+#define COMPONENTS_UI_DEVTOOLS_CONNECTOR_DELEGATE_H_
+
+#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+
+namespace ui_devtools {
+
+// This is a delegate connector that has individual methods for specific
+// interfaces that you need to acquire.
+class ConnectorDelegate {
+ public:
+ ConnectorDelegate() {}
+ virtual ~ConnectorDelegate() {}
+
+ virtual void BindTracingConsumerHost(
+ mojo::PendingReceiver<tracing::mojom::ConsumerHost> receiver) = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ConnectorDelegate);
+};
+
+} // namespace ui_devtools
+
+#endif // COMPONENTS_UI_DEVTOOLS_CONNECTOR_DELEGATE_H_
diff --git a/chromium/components/ui_devtools/css_agent.cc b/chromium/components/ui_devtools/css_agent.cc
index d6fce623a01..7c609ed9df6 100644
--- a/chromium/components/ui_devtools/css_agent.cc
+++ b/chromium/components/ui_devtools/css_agent.cc
@@ -6,6 +6,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "components/ui_devtools/agent_util.h"
#include "components/ui_devtools/ui_element.h"
namespace ui_devtools {
@@ -19,7 +20,7 @@ const char kX[] = "x";
const char kY[] = "y";
const char kVisibility[] = "visibility";
-std::unique_ptr<CSS::SourceRange> BuildDefaultSourceRange() {
+std::unique_ptr<CSS::SourceRange> BuildDefaultPropertySourceRange() {
// These tell the frontend where in the stylesheet a certain style
// is located. Since we don't have stylesheets, this is all 0.
// We need this because CSS fields are not editable unless
@@ -32,6 +33,17 @@ std::unique_ptr<CSS::SourceRange> BuildDefaultSourceRange() {
.build();
}
+std::unique_ptr<CSS::SourceRange> BuildDefaultSelectorSourceRange() {
+ // This is a different source range from BuildDefaultPropertySourceRange()
+ // used for the Selectors, so the frontend correctly handles property edits.
+ return CSS::SourceRange::create()
+ .setStartLine(1)
+ .setEndLine(0)
+ .setStartColumn(0)
+ .setEndColumn(0)
+ .build();
+}
+
std::unique_ptr<protocol::Array<int>> BuildDefaultMatchingSelectors() {
auto matching_selectors = std::make_unique<protocol::Array<int>>();
@@ -44,7 +56,7 @@ std::unique_ptr<protocol::Array<int>> BuildDefaultMatchingSelectors() {
std::unique_ptr<CSS::CSSProperty> BuildCSSProperty(const std::string& name,
const std::string& value) {
return CSS::CSSProperty::create()
- .setRange(BuildDefaultSourceRange())
+ .setRange(BuildDefaultPropertySourceRange())
.setName(name)
.setValue(value)
.build();
@@ -64,7 +76,7 @@ std::unique_ptr<CSS::CSSStyle> BuildCSSStyle(
std::string stylesheet_uid,
const std::vector<UIElement::UIProperty>& properties) {
return protocol::CSS::CSSStyle::create()
- .setRange(BuildDefaultSourceRange())
+ .setRange(BuildDefaultPropertySourceRange())
.setCssProperties(BuildCSSProperties(properties))
.setShorthandEntries(
std::make_unique<Array<protocol::CSS::ShorthandEntry>>())
@@ -75,7 +87,10 @@ std::unique_ptr<CSS::CSSStyle> BuildCSSStyle(
std::unique_ptr<protocol::Array<protocol::CSS::Value>> BuildSelectors(
const std::string& name) {
auto selectors = std::make_unique<protocol::Array<protocol::CSS::Value>>();
- selectors->emplace_back(protocol::CSS::Value::create().setText(name).build());
+ selectors->emplace_back(protocol::CSS::Value::create()
+ .setText(name)
+ .setRange(BuildDefaultSelectorSourceRange())
+ .build());
return selectors;
}
@@ -90,6 +105,7 @@ std::unique_ptr<protocol::CSS::CSSRule> BuildCSSRule(
std::string stylesheet_uid,
const UIElement::ClassProperties& class_properties) {
return protocol::CSS::CSSRule::create()
+ .setStyleSheetId(stylesheet_uid)
.setSelectorList(BuildSelectorList(class_properties.class_name_))
.setStyle(BuildCSSStyle(stylesheet_uid, class_properties.properties_))
.build();
@@ -141,6 +157,10 @@ Response ParseProperties(const std::string& style_text,
bool* visible) {
std::vector<std::string> tokens = base::SplitString(
style_text, ":;", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ if (tokens.size() < 2 || tokens.size() % 2 != 0)
+ return Response::Error("Need both a property name and value.");
+
for (size_t i = 0; i < tokens.size() - 1; i += 2) {
const std::string& property = tokens.at(i);
int value;
@@ -163,6 +183,21 @@ Response ParseProperties(const std::string& style_text,
return Response::OK();
}
+std::unique_ptr<protocol::CSS::CSSStyleSheetHeader>
+BuildObjectForStyleSheetInfo(std::string stylesheet_uid,
+ std::string url_path,
+ int line) {
+ std::unique_ptr<protocol::CSS::CSSStyleSheetHeader> result =
+ protocol::CSS::CSSStyleSheetHeader::create()
+ .setStyleSheetId(stylesheet_uid)
+ .setSourceURL(kChromiumCodeSearchSrcURL + url_path +
+ "?l=" + base::NumberToString(line))
+ .setStartLine(line)
+ .setStartColumn(0)
+ .build();
+ return result;
+}
+
} // namespace
CSSAgent::CSSAgent(DOMAgent* dom_agent) : dom_agent_(dom_agent) {
@@ -194,6 +229,29 @@ Response CSSAgent::getMatchedStylesForNode(
return Response::OK();
}
+Response CSSAgent::getStyleSheetText(const protocol::String& style_sheet_id,
+ protocol::String* result) {
+ int node_id;
+ int stylesheet_id;
+ std::vector<std::string> ids = base::SplitString(
+ style_sheet_id, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (ids.size() < 2 || !base::StringToInt(ids[0], &node_id) ||
+ !base::StringToInt(ids[1], &stylesheet_id))
+ return Response::Error("Invalid stylesheet id");
+
+ UIElement* ui_element = dom_agent_->GetElementFromNodeId(node_id);
+ if (!ui_element)
+ return Response::Error("Node id not found");
+
+ auto sources = ui_element->GetSources();
+ if (static_cast<int>(sources.size()) <= stylesheet_id)
+ return Response::Error("Stylesheet id not found");
+
+ if (GetSourceCode(sources[stylesheet_id].path_, result))
+ return protocol::Response::OK();
+ return protocol::Response::Error("Could not read source file");
+}
+
Response CSSAgent::setStyleTexts(
std::unique_ptr<Array<CSS::StyleDeclarationEdit>> edits,
std::unique_ptr<Array<CSS::CSSStyle>>* result) {
@@ -287,8 +345,20 @@ CSSAgent::BuildMatchedStyles(UIElement* ui_element) {
.setMatchingSelectors(BuildDefaultMatchingSelectors())
.build());
}
-
+ if (!ui_element->header_sent()) {
+ InitStylesheetHeaders(ui_element);
+ }
return result;
}
+void CSSAgent::InitStylesheetHeaders(UIElement* ui_element) {
+ std::vector<UIElement::Source> sources = ui_element->GetSources();
+ for (size_t i = 0; i < sources.size(); i++) {
+ frontend()->styleSheetAdded(BuildObjectForStyleSheetInfo(
+ BuildStylesheetUId(ui_element->node_id(), i), sources[i].path_,
+ sources[i].line_));
+ }
+ ui_element->set_header_sent();
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/css_agent.h b/chromium/components/ui_devtools/css_agent.h
index b4b4ac99f3d..e962f70de9f 100644
--- a/chromium/components/ui_devtools/css_agent.h
+++ b/chromium/components/ui_devtools/css_agent.h
@@ -31,6 +31,8 @@ class UI_DEVTOOLS_EXPORT CSSAgent
int node_id,
protocol::Maybe<protocol::Array<protocol::CSS::RuleMatch>>*
matched_css_rules) override;
+ protocol::Response getStyleSheetText(const protocol::String& style_sheet_id,
+ protocol::String* text) override;
protocol::Response setStyleTexts(
std::unique_ptr<protocol::Array<protocol::CSS::StyleDeclarationEdit>>
edits,
@@ -53,6 +55,9 @@ class UI_DEVTOOLS_EXPORT CSSAgent
std::unique_ptr<protocol::Array<protocol::CSS::RuleMatch>> BuildMatchedStyles(
UIElement* ui_element);
+ // Sends header to frontend for each section in properties panel.
+ void InitStylesheetHeaders(UIElement* ui_element);
+
DOMAgent* const dom_agent_;
DISALLOW_COPY_AND_ASSIGN(CSSAgent);
diff --git a/chromium/components/ui_devtools/css_agent_unittest.cc b/chromium/components/ui_devtools/css_agent_unittest.cc
index 55061d6ccc2..bc60029c31d 100644
--- a/chromium/components/ui_devtools/css_agent_unittest.cc
+++ b/chromium/components/ui_devtools/css_agent_unittest.cc
@@ -6,6 +6,8 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/test/task_environment.h"
+#include "components/ui_devtools/agent_util.h"
#include "components/ui_devtools/dom_agent.h"
#include "components/ui_devtools/ui_devtools_unittest_utils.h"
#include "components/ui_devtools/ui_element.h"
@@ -30,6 +32,9 @@ class FakeUIElement : public UIElement {
}
bool visible() const { return visible_; }
gfx::Rect bounds() const { return bounds_; }
+ void AddSource(std::string path, int line) {
+ UIElement::AddSource(path, line);
+ }
private:
gfx::Rect bounds_;
@@ -84,6 +89,7 @@ class CSSAgentTest : public testing::Test {
}
protected:
+ base::test::TaskEnvironment task_environment_;
using StyleArray = protocol::Array<protocol::CSS::CSSStyle>;
std::pair<bool, std::unique_ptr<StyleArray>>
@@ -115,6 +121,7 @@ class CSSAgentTest : public testing::Test {
}
return std::string();
}
+
int GetStyleSheetChangedCount(std::string stylesheet_id) {
return frontend_channel_->CountProtocolNotificationMessage(
"{\"method\":\"CSS.styleSheetChanged\",\"params\":{"
@@ -122,6 +129,13 @@ class CSSAgentTest : public testing::Test {
stylesheet_id + "\"}}");
}
+ std::pair<bool, std::string> GetSourceForElement() {
+ std::string output;
+ auto response = css_agent_->getStyleSheetText(
+ BuildStylesheetUId(element()->node_id(), 0), &output);
+ return {response.isSuccess(), output};
+ }
+
CSSAgent* css_agent() { return css_agent_.get(); }
DOMAgent* dom_agent() { return dom_agent_.get(); }
FakeUIElement* element() { return element_.get(); }
@@ -163,6 +177,35 @@ TEST_F(CSSAgentTest, UnrecognizedValueFails) {
EXPECT_EQ(element()->bounds(), gfx::Rect(1, 2, 3, 4));
}
+TEST_F(CSSAgentTest, BadInputsFail) {
+ element()->SetVisible(true);
+ element()->SetBounds(gfx::Rect(1, 2, 3, 4));
+
+ // Input with no property name.
+ auto result = SetStyle(": 1;", element()->node_id());
+ EXPECT_FALSE(result.first);
+ EXPECT_FALSE(result.second);
+ // Ensure element didn't change.
+ EXPECT_TRUE(element()->visible());
+ EXPECT_EQ(element()->bounds(), gfx::Rect(1, 2, 3, 4));
+
+ // Input with no property value.
+ result = SetStyle("visibility:", element()->node_id());
+ EXPECT_FALSE(result.first);
+ EXPECT_FALSE(result.second);
+ // Ensure element didn't change.
+ EXPECT_TRUE(element()->visible());
+ EXPECT_EQ(element()->bounds(), gfx::Rect(1, 2, 3, 4));
+
+ // Blank input.
+ result = SetStyle(":", element()->node_id());
+ EXPECT_FALSE(result.first);
+ EXPECT_FALSE(result.second);
+ // Ensure element didn't change.
+ EXPECT_TRUE(element()->visible());
+ EXPECT_EQ(element()->bounds(), gfx::Rect(1, 2, 3, 4));
+}
+
TEST_F(CSSAgentTest, SettingVisibility) {
element()->SetVisible(false);
DCHECK(!element()->visible());
@@ -273,4 +316,24 @@ TEST_F(CSSAgentTest, UpdateOnBoundsChange) {
EXPECT_EQ(2, GetStyleSheetChangedCount(another_element_stylesheet_id));
}
+TEST_F(CSSAgentTest, GetSource) {
+ // Tests CSSAgent::getStyleSheetText() with one source file.
+ std::string file = "components/test/data/ui_devtools/test_file.cc";
+ element()->AddSource(file, 0);
+ auto result = GetSourceForElement();
+
+ // Ensure that test_file.cc was read in correctly.
+ EXPECT_TRUE(result.first);
+ EXPECT_NE(std::string::npos,
+ result.second.find("This file is for testing GetSource."));
+}
+
+TEST_F(CSSAgentTest, BadPathFails) {
+ element()->AddSource("not/a/real/path", 0);
+ auto result = GetSourceForElement();
+
+ EXPECT_FALSE(result.first);
+ EXPECT_EQ(result.second, "");
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/devtools_protocol_encoding.cc b/chromium/components/ui_devtools/devtools_protocol_encoding.cc
index 760ca2a21a8..caa0cf2c652 100644
--- a/chromium/components/ui_devtools/devtools_protocol_encoding.cc
+++ b/chromium/components/ui_devtools/devtools_protocol_encoding.cc
@@ -5,6 +5,9 @@
#include "components/ui_devtools/devtools_protocol_encoding.h"
#include <memory>
+#include <string>
+#include <vector>
+
#include "base/strings/string_number_conversions.h"
namespace ui_devtools {
@@ -35,4 +38,15 @@ IPEStatus ConvertCBORToJSON(span<uint8_t> cbor, std::string* json) {
return ::inspector_protocol_encoding::json::ConvertCBORToJSON(platform, cbor,
json);
}
+
+IPEStatus ConvertJSONToCBOR(span<uint8_t> json, std::string* cbor) {
+ Platform platform;
+ return ConvertJSONToCBOR(platform, json, cbor);
+}
+
+IPEStatus ConvertJSONToCBOR(span<uint8_t> json, std::vector<uint8_t>* cbor) {
+ Platform platform;
+ return ConvertJSONToCBOR(platform, json, cbor);
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/devtools_protocol_encoding.h b/chromium/components/ui_devtools/devtools_protocol_encoding.h
index caf57ed9061..2ef44910589 100644
--- a/chromium/components/ui_devtools/devtools_protocol_encoding.h
+++ b/chromium/components/ui_devtools/devtools_protocol_encoding.h
@@ -5,10 +5,14 @@
#ifndef COMPONENTS_UI_DEVTOOLS_DEVTOOLS_PROTOCOL_ENCODING_H_
#define COMPONENTS_UI_DEVTOOLS_DEVTOOLS_PROTOCOL_ENCODING_H_
+#include <string>
+#include <vector>
+
#include "third_party/inspector_protocol/encoding/encoding.h"
// Convenience adaptation of the conversion function
// ::inspector_protocol_encoding::json::ConvertCBORToJSON,
+// ::inspector_protocol_encoding::json::ConvertJSONToCBOR.
// using an implementation of
// ::inspector_protocol_encoding::json::Platform that
// delegates to base/strings/string_number_conversions.h.
@@ -16,6 +20,14 @@ namespace ui_devtools {
::inspector_protocol_encoding::Status ConvertCBORToJSON(
::inspector_protocol_encoding::span<uint8_t> cbor,
std::string* json);
+
+::inspector_protocol_encoding::Status ConvertJSONToCBOR(
+ ::inspector_protocol_encoding::span<uint8_t> json,
+ std::string* cbor);
+
+::inspector_protocol_encoding::Status ConvertJSONToCBOR(
+ ::inspector_protocol_encoding::span<uint8_t> json,
+ std::vector<uint8_t>* cbor);
} // namespace ui_devtools
#endif // COMPONENTS_UI_DEVTOOLS_DEVTOOLS_PROTOCOL_ENCODING_H_
diff --git a/chromium/components/ui_devtools/devtools_server.h b/chromium/components/ui_devtools/devtools_server.h
index 83cffc9d9fb..e44c587e9ca 100644
--- a/chromium/components/ui_devtools/devtools_server.h
+++ b/chromium/components/ui_devtools/devtools_server.h
@@ -21,6 +21,8 @@
namespace ui_devtools {
+class TracingAgent;
+
class UI_DEVTOOLS_EXPORT UiDevToolsServer
: public network::server::HttpServer::Delegate {
public:
@@ -67,6 +69,9 @@ class UI_DEVTOOLS_EXPORT UiDevToolsServer
int port() const { return port_; }
+ TracingAgent* tracing_agent() { return tracing_agent_; }
+ void set_tracing_agent(TracingAgent* agent) { tracing_agent_ = agent; }
+
private:
UiDevToolsServer(int port, const net::NetworkTrafficAnnotationTag tag);
@@ -97,6 +102,8 @@ class UI_DEVTOOLS_EXPORT UiDevToolsServer
const net::NetworkTrafficAnnotationTag tag_;
+ TracingAgent* tracing_agent_ = nullptr;
+
// The server (owned by Chrome for now)
static UiDevToolsServer* devtools_server_;
diff --git a/chromium/components/ui_devtools/devtools_server_unittest.cc b/chromium/components/ui_devtools/devtools_server_unittest.cc
index e75b267ea04..83020ce219e 100644
--- a/chromium/components/ui_devtools/devtools_server_unittest.cc
+++ b/chromium/components/ui_devtools/devtools_server_unittest.cc
@@ -5,7 +5,7 @@
#include "components/ui_devtools/devtools_server.h"
#include "base/command_line.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/ui_devtools/switches.h"
#include "net/base/address_list.h"
@@ -32,8 +32,8 @@ TEST(UIDevToolsServerTest, MAYBE_ConnectionToViewsServer) {
static constexpr int fake_port = 80;
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableUiDevTools);
- base::test::ScopedTaskEnvironment scoped_task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
network::mojom::NetworkServicePtr network_service_ptr;
network::mojom::NetworkServiceRequest network_service_request =
diff --git a/chromium/components/ui_devtools/dom_agent.cc b/chromium/components/ui_devtools/dom_agent.cc
index 003642012b3..6eee0ebad44 100644
--- a/chromium/components/ui_devtools/dom_agent.cc
+++ b/chromium/components/ui_devtools/dom_agent.cc
@@ -160,7 +160,7 @@ void DOMAgent::OnUIElementReordered(UIElement* parent, UIElement* child) {
auto iter = std::find(children.begin(), children.end(), child);
int prev_node_id =
(iter == children.begin()) ? 0 : (*std::prev(iter))->node_id();
- RemoveDomNode(child);
+ RemoveDomNode(child, false);
frontend()->childNodeInserted(parent->node_id(), prev_node_id,
BuildDomNodeFromUIElement(child));
}
@@ -168,8 +168,7 @@ void DOMAgent::OnUIElementReordered(UIElement* parent, UIElement* child) {
void DOMAgent::OnUIElementRemoved(UIElement* ui_element) {
DCHECK(node_id_to_ui_element_.count(ui_element->node_id()));
- RemoveDomNode(ui_element);
- node_id_to_ui_element_.erase(ui_element->node_id());
+ RemoveDomNode(ui_element, true);
}
void DOMAgent::OnUIElementBoundsChanged(UIElement* ui_element) {
@@ -250,11 +249,14 @@ void DOMAgent::OnElementBoundsChanged(UIElement* ui_element) {
observer.OnElementBoundsChanged(ui_element);
}
-void DOMAgent::RemoveDomNode(UIElement* ui_element) {
+void DOMAgent::RemoveDomNode(UIElement* ui_element, bool update_node_id_map) {
for (auto* child_element : ui_element->children())
- RemoveDomNode(child_element);
+ RemoveDomNode(child_element, update_node_id_map);
frontend()->childNodeRemoved(ui_element->parent()->node_id(),
ui_element->node_id());
+ if (update_node_id_map) {
+ node_id_to_ui_element_.erase(ui_element->node_id());
+ }
}
void DOMAgent::Reset() {
diff --git a/chromium/components/ui_devtools/dom_agent.h b/chromium/components/ui_devtools/dom_agent.h
index a46788f7368..2b06a42395f 100644
--- a/chromium/components/ui_devtools/dom_agent.h
+++ b/chromium/components/ui_devtools/dom_agent.h
@@ -89,7 +89,11 @@ class UI_DEVTOOLS_EXPORT DOMAgent
UIElement* ui_element) = 0;
void OnElementBoundsChanged(UIElement* ui_element);
- void RemoveDomNode(UIElement* ui_element);
+
+ // Recursively removes |ui_element| and its children from the frontend
+ // elements tree. If |update_node_id_map|=true, also remove |ui_element|'s
+ // |node_id| from |node_id_to_ui_element_|.
+ void RemoveDomNode(UIElement* ui_element, bool update_node_id_map);
void Reset();
Query PreprocessQuery(protocol::String query);
void SearchDomTree(const Query& query, std::vector<int>* result_collector);
diff --git a/chromium/components/ui_devtools/inspector_protocol_config.json b/chromium/components/ui_devtools/inspector_protocol_config.json
index afd3177b049..cf40a8c3891 100644
--- a/chromium/components/ui_devtools/inspector_protocol_config.json
+++ b/chromium/components/ui_devtools/inspector_protocol_config.json
@@ -5,7 +5,25 @@
"output": "",
"namespace": ["ui_devtools", "protocol"],
"export_macro": "UI_DEVTOOLS_EXPORT",
- "export_header": "components/ui_devtools/devtools_export.h"
+ "export_header": "components/ui_devtools/devtools_export.h",
+ "options": [
+ {
+ "domain": "DOM"
+ },
+ {
+ "domain": "CSS"
+ },
+ {
+ "domain": "Overlay"
+ },
+ {
+ "domain": "Page"
+ },
+ {
+ "domain": "Tracing",
+ "async": ["start"]
+ }
+ ]
},
"lib": {
"package": "components/ui_devtools",
diff --git a/chromium/components/ui_devtools/protocol.json b/chromium/components/ui_devtools/protocol.json
index 0f811997525..8f550cb7c9f 100644
--- a/chromium/components/ui_devtools/protocol.json
+++ b/chromium/components/ui_devtools/protocol.json
@@ -272,6 +272,23 @@
]
},
{
+ "name": "getStyleSheetText",
+ "parameters": [
+ {
+ "name": "styleSheetId",
+ "$ref": "StyleSheetId"
+ }
+ ],
+ "returns": [
+ {
+ "name": "text",
+ "type": "string",
+ "description": "The stylesheet text."
+ }
+ ],
+ "description": "Returns the current source content for a stylesheet."
+ },
+ {
"name": "setStyleTexts",
"description": "Applies specified style edits one after another in the given order.",
"parameters": [
@@ -311,6 +328,17 @@
"$ref": "StyleSheetId"
}
]
+ },
+ {
+ "name": "styleSheetAdded",
+ "parameters": [
+ {
+ "name": "header",
+ "$ref": "CSSStyleSheetHeader",
+ "description": "Added stylesheet metainfo."
+ }
+ ],
+ "description": "Fired whenever an active document stylesheet is added."
}
],
"types": [
@@ -479,6 +507,33 @@
"description": "Selector list data."
},
{
+ "id": "CSSStyleSheetHeader",
+ "type": "object",
+ "properties": [
+ {
+ "name": "styleSheetId",
+ "$ref": "StyleSheetId",
+ "description": "The stylesheet identifier."
+ },
+ {
+ "name": "sourceURL",
+ "type": "string",
+ "description": "Stylesheet resource URL."
+ },
+ {
+ "name": "startLine",
+ "type": "number",
+ "description": "Line offset of the stylesheet within the resource (zero based)."
+ },
+ {
+ "name": "startColumn",
+ "type": "number",
+ "description": "Column offset of the stylesheet within the resource (zero based)."
+ }
+ ],
+ "description": "CSS stylesheet metainformation."
+ },
+ {
"id": "CSSRule",
"description": "CSS rule representation.",
"type": "object",
@@ -716,12 +771,185 @@
}
],
"description": "Called on Ctrl+R with |ignoreCache|=false, which is used to toggle debug bounds rectangles and Ctrl+Shift+R with |ignoreCache|=true, which is used to toggle bubble locking."
+ },
+ {
+ "name": "getResourceTree",
+ "description": "Called when UI DevTools first loads. Used to populate sources panel.",
+ "returns": [
+ {
+ "name": "frameTree",
+ "$ref": "FrameResourceTree",
+ "description": "Present frame / resource tree structure."
+ }
+ ],
+ "experimental": true
+ },
+ {
+ "name": "getResourceContent",
+ "async": true,
+ "description": "Returns source file content of the given resource.",
+ "parameters": [
+ {
+ "name": "frameId",
+ "type": "string",
+ "description": "Frame id to get resource for."
+ },
+ {
+ "name": "url",
+ "type": "string",
+ "description": "URL of the resource to get content for."
+ }
+ ],
+ "returns": [
+ {
+ "name": "content",
+ "type": "string",
+ "description": "Resource content."
+ },
+ {
+ "name": "base64Encoded",
+ "type": "boolean",
+ "description": "True, if content was served as base64."
+ }
+ ],
+ "experimental": true
}
],
"description": "Actions and events related to the inspected page belong to the page domain.",
"domain": "Page",
"dependencies": [
"DOM"
+ ],
+ "types": [
+ {
+ "id": "ResourceType",
+ "type": "string",
+ "enum": ["Document", "Stylesheet", "Image", "Media", "Font", "Script", "TextTrack", "XHR", "Fetch", "EventSource", "WebSocket", "Manifest", "Other"],
+ "description": "Resource type as it was perceived by the rendering engine."
+ },
+ {
+ "id": "Frame",
+ "type": "object",
+ "description": "Information about the Frame on the page.",
+ "properties": [
+ {
+ "name": "id",
+ "type": "string",
+ "description": "Frame unique identifier."
+ },
+ {
+ "name": "url",
+ "type": "string",
+ "description": "Frame document's URL."
+ }
+ ]
+ },
+ {
+ "id": "FrameResource",
+ "type": "object",
+ "description": "Information about the Resource on the page.",
+ "properties": [
+ {
+ "name": "url",
+ "type": "string",
+ "description": "Resource URL."
+ },
+ {
+ "name": "type",
+ "$ref": "ResourceType",
+ "description": "Type of this resource."
+ },
+ {
+ "name": "mimeType",
+ "type": "string",
+ "description": "Resource mimeType as determined by the browser."
+ }
+ ],
+ "experimental": true
+ },
+ {
+ "id": "FrameResourceTree",
+ "type": "object",
+ "description": "Information about the Frame hierarchy along with their cached resources.",
+ "properties": [
+ {
+ "name": "frame",
+ "$ref": "Frame",
+ "description": "Frame information for this tree item."
+ },
+ {
+ "name": "childFrames",
+ "type": "array",
+ "optional": true,
+ "items":
+ {
+ "$ref": "FrameResourceTree"
+ },
+ "description": "Child frames."
+ },
+ {
+ "name": "resources",
+ "type": "array",
+ "items":
+ {
+ "$ref": "FrameResource"
+ },
+ "description": "Information about frame resources."
+ }
+ ],
+ "experimental": true
+ }
+ ]
+ },
+ {
+ "domain": "Tracing",
+ "experimental": true,
+ "commands": [
+ {
+ "name": "start",
+ "description": "Start trace events collection.",
+ "parameters": [
+ { "name": "categories", "type": "string", "optional": true, "deprecated": true, "description": "Category/tag filter" },
+ { "name": "options", "type": "string", "optional": true, "deprecated": true, "description": "Tracing options" },
+ { "name": "bufferUsageReportingInterval", "type": "number", "optional": true, "description": "If set, the agent will issue bufferUsage events at this interval, specified in milliseconds" }
+ ]
+ },
+ {
+ "name": "end",
+ "description": "Stop trace events collection."
+ },
+ {
+ "name": "disable",
+ "description": "Disables Tracing agent for the given page."
+ },
+ {
+ "name": "enable",
+ "description": "Enables Tracing agent for the given page."
+ }
+ ],
+ "events": [
+ {
+ "name": "dataCollected",
+ "parameters": [
+ { "name": "value", "type": "array", "items": { "type": "object" } }
+ ],
+ "description": "Contains an bucket of collected trace events. When tracing is stopped collected events will be send as a sequence of dataCollected events followed by tracingComplete event."
+ },
+ {
+ "name": "tracingComplete",
+ "description": "Signals that tracing is stopped and there is no trace buffers pending flush, all data were delivered via dataCollected events.",
+ "parameters": [
+ { "name": "dataLossOccurred", "type": "boolean", "optional": true, "description": "A handle of the stream that holds resulting trace data." }
+ ]
+ },
+ {
+ "name": "bufferUsage",
+ "parameters": [
+ { "name": "percentFull", "type": "number", "optional": true, "description": "A number in range [0..1] that indicates the used size of event buffer as a fraction of its total size." },
+ { "name": "eventCount", "type": "number", "optional": true, "description": "An approximate number of events in the trace log." },
+ { "name": "value", "type": "number", "optional": true, "description": "A number in range [0..1] that indicates the used size of event buffer as a fraction of its total size." }
+ ]
+ }
]
}
],
diff --git a/chromium/components/ui_devtools/tracing_agent.cc b/chromium/components/ui_devtools/tracing_agent.cc
new file mode 100644
index 00000000000..e4c0d3b0963
--- /dev/null
+++ b/chromium/components/ui_devtools/tracing_agent.cc
@@ -0,0 +1,541 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ui_devtools/tracing_agent.h"
+
+#include <algorithm>
+#include <unordered_set>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/process/process.h"
+#include "base/timer/timer.h"
+#include "base/trace_event/traced_value.h"
+#include "components/ui_devtools/connector_delegate.h"
+#include "components/ui_devtools/devtools_base_agent.h"
+#include "components/ui_devtools/devtools_protocol_encoding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe_drainer.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
+#include "services/tracing/public/cpp/tracing_features.h"
+#include "services/tracing/public/mojom/constants.mojom.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+
+namespace ui_devtools {
+
+using ui_devtools::protocol::Response;
+
+namespace {
+
+// Minimum reporting interval for the buffer usage status.
+const double kMinimumReportingInterval = 250.0;
+
+// We currently don't support concurrent tracing sessions, but are planning to.
+// For the time being, we're using this flag as a workaround to prevent devtools
+// users from accidentally starting two concurrent sessions.
+// TODO(eseckler): Remove once we add support for concurrent sessions to the
+// perfetto backend.
+static bool g_any_agent_tracing = false;
+
+base::trace_event::TraceConfig::ProcessFilterConfig CreateProcessFilterConfig(
+ base::ProcessId gpu_pid) {
+ base::ProcessId browser_pid = base::Process::Current().Pid();
+ std::unordered_set<base::ProcessId> included_process_ids({browser_pid});
+
+ if (gpu_pid != base::kNullProcessId)
+ included_process_ids.insert(gpu_pid);
+
+ return base::trace_event::TraceConfig::ProcessFilterConfig(
+ included_process_ids);
+}
+
+} // namespace
+
+// This class is passed to StopTracing() and receives the trace data followed by
+// a notification that data collection is over.
+class TracingAgent::DevToolsTraceEndpointProxy
+ : public base::RefCountedThreadSafe<DevToolsTraceEndpointProxy> {
+ public:
+ explicit DevToolsTraceEndpointProxy(base::WeakPtr<TracingAgent> tracing_agent)
+ : tracing_agent_(tracing_agent) {}
+
+ void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) {
+ if (TracingAgent* h = tracing_agent_.get())
+ h->OnTraceDataCollected(std::move(chunk));
+ }
+ void ReceiveTraceFinalContents(
+ std::unique_ptr<const base::DictionaryValue> metadata) {
+ if (TracingAgent* h = tracing_agent_.get())
+ h->OnTraceComplete();
+ }
+
+ protected:
+ friend class base::RefCountedThreadSafe<DevToolsTraceEndpointProxy>;
+
+ private:
+ ~DevToolsTraceEndpointProxy() = default;
+ base::WeakPtr<TracingAgent> tracing_agent_;
+};
+
+// Class used to communicate with the Perfetto Consumer interface.
+class TracingAgent::PerfettoTracingSession
+ : public tracing::mojom::TracingSessionClient,
+ public mojo::DataPipeDrainer::Client {
+ public:
+ explicit PerfettoTracingSession(ConnectorDelegate* connector)
+ : connector_(connector) {}
+
+ ~PerfettoTracingSession() override { DCHECK(!tracing_active_); }
+
+ // TracingAgent::TracingSession implementation:
+ // Make request and set up perfetto for tracing.
+ void EnableTracing(const base::trace_event::TraceConfig& chrome_config,
+ base::OnceClosure on_recording_enabled_callback) {
+ DCHECK(!tracing_session_host_);
+ DCHECK(!tracing_active_);
+ tracing_active_ = true;
+ connector_->BindTracingConsumerHost(
+ consumer_host_.BindNewPipeAndPassReceiver());
+ DCHECK(consumer_host_);
+ perfetto::TraceConfig perfetto_config =
+ CreatePerfettoConfiguration(chrome_config);
+
+ tracing::mojom::TracingSessionClientPtr tracing_session_client;
+ receiver_.Bind(mojo::MakeRequest(&tracing_session_client));
+ receiver_.set_disconnect_handler(
+ base::BindOnce(&PerfettoTracingSession::OnTracingSessionFailed,
+ base::Unretained(this)));
+
+ on_recording_enabled_callback_ = std::move(on_recording_enabled_callback);
+ consumer_host_->EnableTracing(
+ tracing_session_host_.BindNewPipeAndPassReceiver(),
+ std::move(tracing_session_client), std::move(perfetto_config),
+ tracing::mojom::TracingClientPriority::kUserInitiated);
+
+ tracing_session_host_.set_disconnect_handler(
+ base::BindOnce(&PerfettoTracingSession::OnTracingSessionFailed,
+ base::Unretained(this)));
+ }
+
+ void OnTracingEnabled() override {
+ if (on_recording_enabled_callback_) {
+ std::move(on_recording_enabled_callback_).Run();
+ }
+ }
+
+ void OnTracingDisabled() override {
+ // Since we're converting the tracing data to JSON, we will receive the
+ // tracing data via ConsumerHost::DisableTracingAndEmitJson().
+ return;
+ }
+
+ void DisableTracing(
+ const std::string& agent_label,
+ const scoped_refptr<DevToolsTraceEndpointProxy>& endpoint) {
+ agent_label_ = agent_label;
+ endpoint_ = endpoint;
+ tracing_active_ = false;
+
+ if (!tracing_session_host_) {
+ if (endpoint_) {
+ // Will delete |this|.
+ endpoint_->ReceiveTraceFinalContents(nullptr);
+ }
+ return;
+ }
+
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
+ if (result != MOJO_RESULT_OK) {
+ OnTracingSessionFailed();
+ return;
+ }
+ drainer_ = std::make_unique<mojo::DataPipeDrainer>(
+ this, std::move(consumer_handle));
+ tracing_session_host_->DisableTracingAndEmitJson(
+ agent_label_, std::move(producer_handle),
+ base::BindOnce(&PerfettoTracingSession::OnReadBuffersComplete,
+ base::Unretained(this)));
+ }
+
+ void GetBufferUsage(base::OnceCallback<void(float percent_full,
+ size_t approximate_event_count)>
+ on_buffer_usage_callback) {
+ if (!tracing_session_host_) {
+ std::move(on_buffer_usage_callback).Run(0.0f, 0);
+ return;
+ }
+ DCHECK(on_buffer_usage_callback);
+ tracing_session_host_->RequestBufferUsage(base::BindOnce(
+ &PerfettoTracingSession::OnBufferUsage, base::Unretained(this),
+ std::move(on_buffer_usage_callback)));
+ }
+
+ bool HasTracingFailed() { return tracing_active_ && !tracing_session_host_; }
+
+ bool HasDataLossOccurred() { return data_loss_; }
+
+ private:
+ perfetto::TraceConfig CreatePerfettoConfiguration(
+ const base::trace_event::TraceConfig& chrome_config) {
+#if DCHECK_IS_ON()
+ base::trace_event::TraceConfig processfilter_stripped_config(chrome_config);
+ processfilter_stripped_config.SetProcessFilterConfig(
+ base::trace_event::TraceConfig::ProcessFilterConfig());
+
+ // Ensure that the process filter is the only thing that gets changed
+ // in a configuration during a tracing session.
+ DCHECK((last_config_for_perfetto_.ToString() ==
+ base::trace_event::TraceConfig().ToString()) ||
+ (last_config_for_perfetto_.ToString() ==
+ processfilter_stripped_config.ToString()));
+ last_config_for_perfetto_ = std::move(processfilter_stripped_config);
+#endif
+
+ return tracing::GetDefaultPerfettoConfig(chrome_config);
+ }
+
+ void OnTracingSessionFailed() {
+ tracing_session_host_.reset();
+ receiver_.reset();
+ drainer_.reset();
+
+ if (on_recording_enabled_callback_)
+ std::move(on_recording_enabled_callback_).Run();
+
+ if (pending_disable_tracing_task_)
+ std::move(pending_disable_tracing_task_).Run();
+
+ if (endpoint_) {
+ endpoint_->ReceiveTraceFinalContents(nullptr);
+ }
+ }
+
+ // Notify client about data loss during tracing.
+ void OnBufferUsage(base::OnceCallback<void(float percent_full,
+ size_t approximate_event_count)>
+ on_buffer_usage_callback,
+ bool success,
+ float percent_full,
+ bool data_loss) {
+ if (!success) {
+ std::move(on_buffer_usage_callback).Run(0.0f, 0);
+ return;
+ }
+ data_loss_ |= data_loss;
+ std::move(on_buffer_usage_callback).Run(percent_full, 0);
+ }
+
+ // mojo::DataPipeDrainer::Client implementation:
+ void OnDataAvailable(const void* data, size_t num_bytes) override {
+ auto data_string = std::make_unique<std::string>(
+ reinterpret_cast<const char*>(data), num_bytes);
+ endpoint_->ReceiveTraceChunk(std::move(data_string));
+ }
+
+ void OnDataComplete() override {
+ data_complete_ = true;
+ MaybeTraceComplete();
+ }
+
+ void OnReadBuffersComplete() {
+ read_buffers_complete_ = true;
+ MaybeTraceComplete();
+ }
+
+ void MaybeTraceComplete() {
+ if (read_buffers_complete_ && data_complete_) {
+ // Request stats to check if data loss occurred.
+ GetBufferUsage(base::BindOnce(&PerfettoTracingSession::OnFinalBufferUsage,
+ base::Unretained(this)));
+ }
+ }
+
+ void OnFinalBufferUsage(float percent_full, size_t approximate_event_count) {
+ if (!endpoint_)
+ return;
+ // Will delete |this|.
+ endpoint_->ReceiveTraceFinalContents(nullptr);
+ }
+
+ mojo::Receiver<tracing::mojom::TracingSessionClient> receiver_{this};
+ mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_;
+
+ mojo::Remote<tracing::mojom::ConsumerHost> consumer_host_;
+ ConnectorDelegate* connector_;
+
+ std::string agent_label_;
+ base::OnceClosure on_recording_enabled_callback_;
+ base::OnceClosure pending_disable_tracing_task_;
+ scoped_refptr<DevToolsTraceEndpointProxy> endpoint_;
+ std::unique_ptr<mojo::DataPipeDrainer> drainer_;
+ bool data_complete_ = false;
+ bool read_buffers_complete_ = false;
+ bool tracing_active_ = false;
+ bool data_loss_ = false;
+
+#if DCHECK_IS_ON()
+ base::trace_event::TraceConfig last_config_for_perfetto_;
+#endif
+};
+
+TracingAgent::TracingAgent(std::unique_ptr<ConnectorDelegate> connector)
+ : connector_(std::move(connector)) {}
+
+TracingAgent::~TracingAgent() = default;
+
+void TracingAgent::OnTraceDataCollected(
+ std::unique_ptr<std::string> trace_fragment) {
+ const std::string valid_trace_fragment =
+ UpdateTraceDataBuffer(*trace_fragment);
+ if (valid_trace_fragment.empty())
+ return;
+
+ // Hand-craft protocol notification message so we can substitute JSON
+ // that we already got as string as a bare object, not a quoted string.
+ std::string message(
+ "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": [");
+ const size_t messageSuffixSize = 10;
+ message.reserve(message.size() + valid_trace_fragment.size() +
+ messageSuffixSize - trace_data_buffer_state_.offset);
+ message.append(valid_trace_fragment.c_str() +
+ trace_data_buffer_state_.offset);
+ message += "] } }";
+ std::vector<uint8_t> cbor;
+ ::inspector_protocol_encoding::Status status = ConvertJSONToCBOR(
+ ::inspector_protocol_encoding::SpanFrom(message), &cbor);
+ LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+
+ frontend()->sendRawCBORNotification(std::move(cbor));
+}
+
+void TracingAgent::OnTraceComplete() {
+ if (!trace_data_buffer_state_.data.empty())
+ OnTraceDataCollected(std::make_unique<std::string>(""));
+
+ DCHECK(trace_data_buffer_state_.data.empty());
+ DCHECK_EQ(0u, trace_data_buffer_state_.pos);
+ DCHECK_EQ(0, trace_data_buffer_state_.open_braces);
+ DCHECK(!trace_data_buffer_state_.in_string);
+ DCHECK(!trace_data_buffer_state_.slashed);
+
+ bool data_loss = perfetto_session_->HasDataLossOccurred();
+ perfetto_session_.reset();
+ frontend()->tracingComplete(data_loss);
+}
+
+void TracingAgent::start(
+ protocol::Maybe<std::string> categories,
+ protocol::Maybe<std::string> options,
+ protocol::Maybe<double> buffer_usage_reporting_interval,
+ std::unique_ptr<StartCallback> callback) {
+ if (g_any_agent_tracing) {
+ callback->sendFailure(Response::Error("Tracing is already started"));
+ return;
+ }
+
+ if (!categories.isJust() && !options.isJust()) {
+ callback->sendFailure(
+ Response::InvalidParams("categories+options should be specified."));
+ return;
+ }
+
+ did_initiate_recording_ = true;
+ buffer_usage_reporting_interval_ =
+ buffer_usage_reporting_interval.fromMaybe(0);
+
+ // Since we want minimum changes to the devtools frontend, enable the
+ // tracing categories for ui_devtools here.
+ std::string ui_devtools_categories =
+ "disabled-by-default-devtools.timeline,disabled-by-default-devtools."
+ "timeline.frame,views,latency,toplevel,"
+ "benchmark,cc,viz,input,latency,gpu,rail,viz,ui";
+ trace_config_ = base::trace_event::TraceConfig(ui_devtools_categories,
+ options.fromMaybe(""));
+ StartTracing(std::move(callback));
+}
+
+Response TracingAgent::end() {
+ if (!perfetto_session_)
+ return Response::Error("Tracing is not started");
+
+ if (perfetto_session_->HasTracingFailed())
+ return Response::Error("Tracing failed");
+
+ scoped_refptr<DevToolsTraceEndpointProxy> endpoint;
+ // Reset the trace data buffer state.
+ trace_data_buffer_state_ = TracingAgent::TraceDataBufferState();
+ endpoint = new DevToolsTraceEndpointProxy(weak_factory_.GetWeakPtr());
+ StopTracing(endpoint, tracing::mojom::kChromeTraceEventLabel);
+
+ return Response::OK();
+}
+
+void TracingAgent::StartTracing(std::unique_ptr<StartCallback> callback) {
+ trace_config_.SetProcessFilterConfig(CreateProcessFilterConfig(gpu_pid_));
+
+ if (tracing::TracingUsesPerfettoBackend()) {
+ perfetto_session_ =
+ std::make_unique<PerfettoTracingSession>(connector_.get());
+ } else {
+ callback->sendFailure(
+ Response::Error("Could not start tracing by Perfetto."));
+ return;
+ }
+ perfetto_session_->EnableTracing(
+ trace_config_,
+ base::BindOnce(&TracingAgent::OnRecordingEnabled,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ g_any_agent_tracing = true;
+}
+
+void TracingAgent::OnRecordingEnabled(std::unique_ptr<StartCallback> callback) {
+ EditTraceDataForFrontend();
+ callback->sendSuccess();
+ SetupTimer(buffer_usage_reporting_interval_);
+}
+
+void TracingAgent::EditTraceDataForFrontend() {
+ // TracingStartedInBrowser is used to enter _processInspectorTrace,
+ // which is the logic flow that browser devtools uses for the performance
+ // panel. Without this trace event, devtools will use the generic trace, which
+ // does not handle fps logic or use the color scheme defined by the
+ // category-event map. The processes that are of interest in ui_devtools needs
+ // to be specified in the data[frame] property of TracingStartedInBrowser
+ auto process_data = std::make_unique<base::trace_event::TracedValue>();
+ process_data->SetBoolean("persistentIds", true);
+ process_data->BeginArray("frames");
+
+ process_data->BeginDictionary();
+ process_data->SetString("frame", "ui_devtools_browser_frame");
+ process_data->SetString("name", "Browser");
+ process_data->SetInteger("processId", base::Process::Current().Pid());
+ process_data->EndDictionary();
+
+ process_data->BeginDictionary();
+ process_data->SetString("frame", "ui_devtools_gpu_frame");
+ process_data->SetString("name", "Gpu");
+ process_data->SetInteger("processId", gpu_pid_);
+ process_data->EndDictionary();
+
+ process_data->EndArray();
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
+ "TracingStartedInBrowser", TRACE_EVENT_SCOPE_THREAD,
+ "data", std::move(process_data));
+
+ // Browser devtools make sure the SetLayerTreeId trace event has the same
+ // layertreeid as the layertreeid from the frame trace events 'DrawFrame' and
+ // 'BeginFrame'. There is only 1 layer tree in ui_devtools, so the layertreeid
+ // for all frames in ui_devtools is 1. This is used to get the frames, which
+ // is later used for the fps metrics.
+ auto layer_tree_data = std::make_unique<base::trace_event::TracedValue>();
+ layer_tree_data->SetString("frame", "ui_devtools_browser_frame");
+ layer_tree_data->SetInteger("layerTreeId", 1);
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
+ "SetLayerTreeId", TRACE_EVENT_SCOPE_THREAD, "data",
+ std::move(layer_tree_data));
+}
+
+void TracingAgent::SetupTimer(double usage_reporting_interval) {
+ if (usage_reporting_interval == 0)
+ return;
+
+ if (usage_reporting_interval < kMinimumReportingInterval)
+ usage_reporting_interval = kMinimumReportingInterval;
+
+ base::TimeDelta interval =
+ base::TimeDelta::FromMilliseconds(std::ceil(usage_reporting_interval));
+ buffer_usage_poll_timer_.reset(new base::RepeatingTimer());
+ buffer_usage_poll_timer_->Start(
+ FROM_HERE, interval,
+ base::BindRepeating(&TracingAgent::UpdateBufferUsage,
+ weak_factory_.GetWeakPtr()));
+}
+
+void TracingAgent::OnBufferUsage(float percent_full,
+ size_t approximate_event_count) {
+ if (!did_initiate_recording_)
+ return;
+ frontend()->bufferUsage(percent_full, approximate_event_count, percent_full);
+}
+
+void TracingAgent::UpdateBufferUsage() {
+ perfetto_session_->GetBufferUsage(
+ base::BindOnce(&TracingAgent::OnBufferUsage, weak_factory_.GetWeakPtr()));
+}
+
+void TracingAgent::StopTracing(
+ const scoped_refptr<DevToolsTraceEndpointProxy>& endpoint,
+ const std::string& agent_label) {
+ DCHECK(perfetto_session_);
+ buffer_usage_poll_timer_.reset();
+ perfetto_session_->DisableTracing(agent_label, endpoint);
+ did_initiate_recording_ = false;
+ g_any_agent_tracing = false;
+}
+
+std::string TracingAgent::UpdateTraceDataBuffer(
+ const std::string& trace_fragment) {
+ size_t end = 0;
+ size_t last_open = 0;
+ TraceDataBufferState& state = trace_data_buffer_state_;
+ state.offset = 0;
+ bool update_offset = state.open_braces == 0;
+ for (; state.pos < trace_fragment.size(); ++state.pos) {
+ char c = trace_fragment[state.pos];
+ switch (c) {
+ case '{':
+ if (!state.in_string && !state.slashed) {
+ state.open_braces++;
+ if (state.open_braces == 1) {
+ last_open = state.data.size() + state.pos;
+ if (update_offset) {
+ state.offset = last_open;
+ update_offset = false;
+ }
+ }
+ }
+ break;
+ case '}':
+ if (!state.in_string && !state.slashed) {
+ DCHECK_GT(state.open_braces, 0);
+ state.open_braces--;
+ if (state.open_braces == 0)
+ end = state.data.size() + state.pos + 1;
+ }
+ break;
+ case '"':
+ if (!state.slashed)
+ state.in_string = !state.in_string;
+ break;
+ case 'u':
+ if (state.slashed)
+ state.pos += 4;
+ break;
+ }
+
+ if (state.in_string && c == '\\') {
+ state.slashed = !state.slashed;
+ } else {
+ state.slashed = false;
+ }
+ }
+
+ // Next starting position is usually 0 except when we are in the middle of
+ // processing a unicode character, i.e. \uxxxx.
+ state.pos -= trace_fragment.size();
+
+ std::string complete_str = state.data + trace_fragment;
+ state.data = complete_str.substr(std::max(end, last_open));
+
+ complete_str.resize(end);
+ return complete_str;
+}
+
+} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/tracing_agent.h b/chromium/components/ui_devtools/tracing_agent.h
new file mode 100644
index 00000000000..92334401517
--- /dev/null
+++ b/chromium/components/ui_devtools/tracing_agent.h
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_TRACING_AGENT_H_
+#define COMPONENTS_UI_DEVTOOLS_TRACING_AGENT_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/trace_event/trace_config.h"
+#include "components/ui_devtools/Tracing.h"
+#include "components/ui_devtools/devtools_base_agent.h"
+
+namespace base {
+class RepeatingTimer;
+}
+
+namespace ui_devtools {
+
+class ConnectorDelegate;
+
+// This class is used for tracing in the ui_devtools performance panel.
+// A lot of the code is based on TracingHandler from
+// content/browser/devtools/protocol/tracing_handler.h.
+class UI_DEVTOOLS_EXPORT TracingAgent
+ : public UiDevToolsBaseAgent<protocol::Tracing::Metainfo> {
+ public:
+ explicit TracingAgent(std::unique_ptr<ConnectorDelegate> connector);
+ ~TracingAgent() override;
+
+ void set_gpu_pid(base::ProcessId pid) { gpu_pid_ = pid; }
+
+ // Sends the Tracing JSON data in the form of CBOR to the frontend.
+ void OnTraceDataCollected(std::unique_ptr<std::string> trace_fragment);
+
+ // Signals that tracing is complete and notifies any data loss to the
+ // frontend.
+ void OnTraceComplete();
+
+ // Tracing::Backend:
+ void start(protocol::Maybe<std::string> categories,
+ protocol::Maybe<std::string> options,
+ protocol::Maybe<double> buffer_usage_reporting_interval,
+ std::unique_ptr<StartCallback> callback) override;
+ protocol::Response end() override;
+
+ private:
+ class DevToolsTraceEndpointProxy;
+ class PerfettoTracingSession;
+
+ struct TraceDataBufferState {
+ public:
+ std::string data;
+ size_t pos = 0;
+ int open_braces = 0;
+ bool in_string = false;
+ bool slashed = false;
+ size_t offset = 0;
+ };
+
+ // Returns the longest prefix of |trace_fragment| that is a valid list and
+ // stores the rest (tail) to be used in subsequent calls. This returns the
+ // longest prefix of the tail prepended to |trace_fragment| next time. Assumes
+ // that the input is a potentially incomplete string representation of a comma
+ // separated list of JSON objects.
+ std::string UpdateTraceDataBuffer(const std::string& trace_fragment);
+
+ // Sets TraceConfig to only collect trace events for the specified processes
+ // in this method. Currently, only the browser process is specified. Starts
+ // tracing by attempting to enable tracing via perfetto.
+ void StartTracing(std::unique_ptr<StartCallback>);
+
+ // Called when we have successfully started tracing with Perfetto session.
+ void OnRecordingEnabled(std::unique_ptr<StartCallback> callback);
+
+ // Edits tracing data to use the normal devtools frontend logic to display
+ // the performance metrics. Without this, it will use the devtools generic
+ // trace logic to display the performance metrics.
+ void EditTraceDataForFrontend();
+
+ // Sets up repeating timer to request the trace buffer status from the
+ // perfetto tracing session. If usage_reporting_interval is too small, it will
+ // be clipped to a minimum value.
+ void SetupTimer(double usage_reporting_interval);
+
+ // Sends frontend information on buffer usage such as how much of the buffer
+ // is used and the approximate number of events in the trace log.
+ void OnBufferUsage(float percent_full, size_t approximate_event_count);
+
+ // Gets updated buffer usage from the perfetto tracing session.
+ void UpdateBufferUsage();
+
+ // Resets buffer usage and passes the trace data to the trace data endpoint
+ // consumer.
+ void StopTracing(const scoped_refptr<DevToolsTraceEndpointProxy>& endpoint,
+ const std::string& agent_label);
+
+ std::unique_ptr<base::RepeatingTimer> buffer_usage_poll_timer_;
+ std::unique_ptr<ConnectorDelegate> connector_;
+ base::ProcessId gpu_pid_ = base::kNullProcessId;
+ bool did_initiate_recording_ = false;
+ double buffer_usage_reporting_interval_ = 0;
+ base::trace_event::TraceConfig trace_config_;
+ std::unique_ptr<PerfettoTracingSession> perfetto_session_;
+ TraceDataBufferState trace_data_buffer_state_;
+ base::WeakPtrFactory<TracingAgent> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(TracingAgent);
+};
+
+} // namespace ui_devtools
+
+#endif // COMPONENTS_UI_DEVTOOLS_TRACING_AGENT_H_
diff --git a/chromium/components/ui_devtools/ui_element.cc b/chromium/components/ui_devtools/ui_element.cc
index 4b964d9322e..2f36530ecc4 100644
--- a/chromium/components/ui_devtools/ui_element.cc
+++ b/chromium/components/ui_devtools/ui_element.cc
@@ -26,6 +26,9 @@ UIElement::ClassProperties::ClassProperties(
UIElement::ClassProperties::~ClassProperties() = default;
+UIElement::Source::Source(std::string path, int line)
+ : path_(path), line_(line) {}
+
// static
void UIElement::ResetNodeId() {
node_ids = 0;
@@ -134,4 +137,15 @@ bool UIElement::SetPropertiesFromString(const std::string& text) {
return false;
}
+void UIElement::AddSource(std::string path, int line) {
+ sources_.emplace_back(path, line);
+}
+
+std::vector<UIElement::Source> UIElement::GetSources() {
+ if (sources_.empty())
+ InitSources();
+
+ return sources_;
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/ui_element.h b/chromium/components/ui_devtools/ui_element.h
index 0d26d3b6e76..541b4ffd41f 100644
--- a/chromium/components/ui_devtools/ui_element.h
+++ b/chromium/components/ui_devtools/ui_element.h
@@ -40,6 +40,13 @@ class UI_DEVTOOLS_EXPORT UIElement {
std::vector<UIProperty> properties_;
};
+ struct UI_DEVTOOLS_EXPORT Source {
+ Source(std::string path, int line);
+
+ std::string path_;
+ int line_;
+ };
+
using UIElements = std::vector<UIElement*>;
// resets node ids to 0 so that they are reusable
@@ -59,6 +66,11 @@ class UI_DEVTOOLS_EXPORT UIElement {
int GetBaseStylesheetId() const { return base_stylesheet_id_; }
void SetBaseStylesheetId(int id) { base_stylesheet_id_ = id; }
+ // Gets/sets whether the element has sent its stylesheet header to the
+ // frontend.
+ bool header_sent() const { return header_sent_; }
+ void set_header_sent() { header_sent_ = true; }
+
using ElementCompare = bool (*)(const UIElement*, const UIElement*);
// Inserts |child| in front of |before|. If |before| is null, it is inserted
@@ -118,10 +130,17 @@ class UI_DEVTOOLS_EXPORT UIElement {
// Called from PageAgent to repaint Views for Debug Bounds Rectangles
virtual void PaintRect() const {}
+ // Called in the constructor to initialize the element's sources.
+ virtual void InitSources() {}
+
+ // Get the sources for the element.
+ std::vector<Source> GetSources();
+
protected:
UIElement(const UIElementType type,
UIElementDelegate* delegate,
UIElement* parent);
+ void AddSource(std::string path, int line);
private:
const int node_id_;
@@ -132,6 +151,8 @@ class UI_DEVTOOLS_EXPORT UIElement {
bool is_updating_ = false;
bool owns_children_ = true;
int base_stylesheet_id_;
+ bool header_sent_ = false;
+ std::vector<Source> sources_;
DISALLOW_COPY_AND_ASSIGN(UIElement);
};
diff --git a/chromium/components/ui_devtools/views/BUILD.gn b/chromium/components/ui_devtools/views/BUILD.gn
index d485d695fd7..e9fb3b23196 100644
--- a/chromium/components/ui_devtools/views/BUILD.gn
+++ b/chromium/components/ui_devtools/views/BUILD.gn
@@ -29,6 +29,7 @@ source_set("views") {
deps = [
"//components/ui_devtools",
+ "//extensions/common",
"//skia",
"//ui/views",
]
@@ -68,6 +69,7 @@ source_set("unit_tests") {
sources = [
"dom_agent_unittest.cc",
"overlay_agent_unittest.cc",
+ "page_agent_views_unittest.cc",
"view_element_unittest.cc",
"widget_element_unittest.cc",
]
diff --git a/chromium/components/ui_devtools/views/DEPS b/chromium/components/ui_devtools/views/DEPS
index f97255e94b1..7484cad79df 100644
--- a/chromium/components/ui_devtools/views/DEPS
+++ b/chromium/components/ui_devtools/views/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+extensions/common/image_util.h",
"+third_party/skia/include",
"+ui"
]
diff --git a/chromium/components/ui_devtools/views/devtools_server_util.cc b/chromium/components/ui_devtools/views/devtools_server_util.cc
index 18c0b08c48a..36444f21212 100644
--- a/chromium/components/ui_devtools/views/devtools_server_util.cc
+++ b/chromium/components/ui_devtools/views/devtools_server_util.cc
@@ -5,11 +5,13 @@
#include "components/ui_devtools/views/devtools_server_util.h"
#include <memory>
+#include <utility>
#include "components/ui_devtools/css_agent.h"
#include "components/ui_devtools/devtools_server.h"
#include "components/ui_devtools/page_agent.h"
#include "components/ui_devtools/switches.h"
+#include "components/ui_devtools/tracing_agent.h"
#include "components/ui_devtools/views/dom_agent_views.h"
#include "components/ui_devtools/views/overlay_agent_views.h"
#include "components/ui_devtools/views/page_agent_views.h"
@@ -17,7 +19,8 @@
namespace ui_devtools {
std::unique_ptr<UiDevToolsServer> CreateUiDevToolsServerForViews(
- network::mojom::NetworkContext* network_context) {
+ network::mojom::NetworkContext* network_context,
+ std::unique_ptr<ConnectorDelegate> connector) {
constexpr int kUiDevToolsDefaultPort = 9223;
int port = UiDevToolsServer::GetUiDevToolsPort(switches::kEnableUiDevTools,
kUiDevToolsDefaultPort);
@@ -31,6 +34,9 @@ std::unique_ptr<UiDevToolsServer> CreateUiDevToolsServerForViews(
client->AddAgent(std::move(dom_agent_views));
client->AddAgent(std::make_unique<CSSAgent>(dom_agent_views_ptr));
client->AddAgent(OverlayAgentViews::Create(dom_agent_views_ptr));
+ auto tracing_agent = std::make_unique<TracingAgent>(std::move(connector));
+ server->set_tracing_agent(tracing_agent.get());
+ client->AddAgent(std::move(tracing_agent));
server->AttachClient(std::move(client));
return server;
}
diff --git a/chromium/components/ui_devtools/views/devtools_server_util.h b/chromium/components/ui_devtools/views/devtools_server_util.h
index ec6a11400db..fb8e07e2fe5 100644
--- a/chromium/components/ui_devtools/views/devtools_server_util.h
+++ b/chromium/components/ui_devtools/views/devtools_server_util.h
@@ -7,13 +7,16 @@
#include <memory>
+#include "components/ui_devtools/connector_delegate.h"
#include "components/ui_devtools/devtools_server.h"
namespace ui_devtools {
// A factory helper to construct a UiDevToolsServer for Views.
+// The connector is used in TracingAgent to hook up with the tracing service.
std::unique_ptr<UiDevToolsServer> CreateUiDevToolsServerForViews(
- network::mojom::NetworkContext* network_context);
+ network::mojom::NetworkContext* network_context,
+ std::unique_ptr<ConnectorDelegate> connector);
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/dom_agent_unittest.cc b/chromium/components/ui_devtools/views/dom_agent_unittest.cc
index a702a402349..8f20d7306ef 100644
--- a/chromium/components/ui_devtools/views/dom_agent_unittest.cc
+++ b/chromium/components/ui_devtools/views/dom_agent_unittest.cc
@@ -78,7 +78,7 @@ class DOMAgentTest : public views::ViewsTestBase {
#if defined(USE_AURA)
params.parent = GetContext();
#endif
- widget->Init(params);
+ widget->Init(std::move(params));
return widget->native_widget_private();
}
@@ -95,7 +95,7 @@ class DOMAgentTest : public views::ViewsTestBase {
#endif
if (name)
params.name = *name;
- widget->Init(params);
+ widget->Init(std::move(params));
widget->Show();
return widget;
}
@@ -528,6 +528,7 @@ TEST_F(DOMAgentTest, ViewRearranged) {
EXPECT_TRUE(WasChildNodeInserted(parent_view));
int child_id = GetIDForBackendElement(child_view);
+ parent_view->RemoveChildView(child_view);
target_view->AddChildView(child_view);
EXPECT_TRUE(WasChildNodeRemoved(parent_view, child_id));
EXPECT_TRUE(WasChildNodeInserted(target_view));
@@ -557,6 +558,60 @@ TEST_F(DOMAgentTest, ViewRearrangedRemovedAndInserted) {
EXPECT_TRUE(WasChildNodeInserted(target_view));
}
+TEST_F(DOMAgentTest, NodeIdToUIElementTest) {
+ // widget
+ // root_view
+ // child_a1
+ // child_a11
+ // child_a111
+ // child_a1111
+ // child_a112
+ std::unique_ptr<views::Widget> widget(
+ CreateTestWidget(gfx::Rect(1, 1, 80, 80)));
+
+ widget->Show();
+ views::View* root_view = widget->GetRootView();
+ views::View* child_a1 =
+ root_view->AddChildView(std::make_unique<views::View>());
+ views::View* child_a11 =
+ child_a1->AddChildView(std::make_unique<views::View>());
+ views::View* child_a111 =
+ child_a11->AddChildView(std::make_unique<views::View>());
+ views::View* child_a112 =
+ child_a11->AddChildView(std::make_unique<views::View>());
+ views::View* child_a1111 =
+ child_a111->AddChildView(std::make_unique<views::View>());
+
+ std::unique_ptr<DOM::Node> root;
+ dom_agent()->getDocument(&root);
+
+ int child_a1_id = GetIDForBackendElement(child_a1);
+ int child_a11_id = GetIDForBackendElement(child_a11);
+ int child_a111_id = GetIDForBackendElement(child_a111);
+ int child_a112_id = GetIDForBackendElement(child_a112);
+ int child_a1111_id = GetIDForBackendElement(child_a1111);
+
+ // Make sure all child nodes are in the |node_id_to_ui_element_| map.
+ EXPECT_NE(dom_agent()->GetElementFromNodeId(child_a1_id), nullptr);
+ EXPECT_NE(dom_agent()->GetElementFromNodeId(child_a11_id), nullptr);
+ EXPECT_NE(dom_agent()->GetElementFromNodeId(child_a111_id), nullptr);
+ EXPECT_NE(dom_agent()->GetElementFromNodeId(child_a112_id), nullptr);
+ EXPECT_NE(dom_agent()->GetElementFromNodeId(child_a1111_id), nullptr);
+
+ root_view->RemoveChildView(child_a1);
+
+ // Check that child_a1 and its children are all removed from the
+ // |node_id_to_ui_element_| map.
+ EXPECT_EQ(dom_agent()->GetElementFromNodeId(child_a1_id), nullptr);
+ EXPECT_EQ(dom_agent()->GetElementFromNodeId(child_a11_id), nullptr);
+ EXPECT_EQ(dom_agent()->GetElementFromNodeId(child_a111_id), nullptr);
+ EXPECT_EQ(dom_agent()->GetElementFromNodeId(child_a112_id), nullptr);
+ EXPECT_EQ(dom_agent()->GetElementFromNodeId(child_a1111_id), nullptr);
+
+ // Required since it was removed from its parent view.
+ delete child_a1;
+}
+
// Tests to ensure dom search for native UI is working
TEST_F(DOMAgentTest, SimpleDomSearch) {
std::unique_ptr<views::Widget> widget_a(
diff --git a/chromium/components/ui_devtools/views/element_utility.cc b/chromium/components/ui_devtools/views/element_utility.cc
index eb1eef6de55..db30ea88597 100644
--- a/chromium/components/ui_devtools/views/element_utility.cc
+++ b/chromium/components/ui_devtools/views/element_utility.cc
@@ -5,6 +5,8 @@
#include "components/ui_devtools/views/element_utility.h"
#include "base/strings/string_number_conversions.h"
+#include "extensions/common/image_util.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/layer_owner.h"
namespace ui_devtools {
@@ -50,4 +52,14 @@ void AppendLayerPropertiesMatchedStyle(
}
}
+bool ParseColorFromFrontend(const std::string& input, std::string* output) {
+ std::string value;
+ base::TrimWhitespaceASCII(input, base::TRIM_ALL, &value);
+ SkColor color;
+ if (!extensions::image_util::ParseCssColorString(value, &color))
+ return false;
+ *output = base::NumberToString(color);
+ return true;
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/element_utility.h b/chromium/components/ui_devtools/views/element_utility.h
index 7aa19a1fe43..0423eb843b0 100644
--- a/chromium/components/ui_devtools/views/element_utility.h
+++ b/chromium/components/ui_devtools/views/element_utility.h
@@ -24,6 +24,11 @@ namespace ui_devtools {
void AppendLayerPropertiesMatchedStyle(const ui::Layer* layer,
std::vector<UIElement::UIProperty>* ret);
+// Takes in color property from DevTools frontend as string in rgba()/rgb(),
+// hex, or hsla()/hsl() format and sets |output| to the SkColor value as a
+// string. Returns true if successful.
+bool ParseColorFromFrontend(const std::string& input, std::string* output);
+
} // namespace ui_devtools
#endif // COMPONENTS_UI_DEVTOOLS_VIEWS_ELEMENT_UTILITY_H_
diff --git a/chromium/components/ui_devtools/views/overlay_agent_unittest.cc b/chromium/components/ui_devtools/views/overlay_agent_unittest.cc
index 20520e25ebc..bfd40f3b856 100644
--- a/chromium/components/ui_devtools/views/overlay_agent_unittest.cc
+++ b/chromium/components/ui_devtools/views/overlay_agent_unittest.cc
@@ -122,7 +122,7 @@ class OverlayAgentTest : public views::ViewsTestBase {
#if defined(USE_AURA)
params.parent = GetContext();
#endif
- widget_->Init(params);
+ widget_->Init(std::move(params));
widget_->Show();
}
diff --git a/chromium/components/ui_devtools/views/overlay_agent_views.cc b/chromium/components/ui_devtools/views/overlay_agent_views.cc
index cea9c64cfda..262dffc20f2 100644
--- a/chromium/components/ui_devtools/views/overlay_agent_views.cc
+++ b/chromium/components/ui_devtools/views/overlay_agent_views.cc
@@ -410,14 +410,15 @@ protocol::Response OverlayAgentViews::hideHighlight() {
void OverlayAgentViews::ShowDistancesInHighlightOverlay(int pinned_id,
int element_id) {
+ UIElement* element_r1 = dom_agent()->GetElementFromNodeId(pinned_id);
+ UIElement* element_r2 = dom_agent()->GetElementFromNodeId(element_id);
+ if (!element_r1 || !element_r2)
+ return;
+
const std::pair<gfx::NativeWindow, gfx::Rect> pair_r2(
- dom_agent()
- ->GetElementFromNodeId(element_id)
- ->GetNodeWindowAndScreenBounds());
+ element_r2->GetNodeWindowAndScreenBounds());
const std::pair<gfx::NativeWindow, gfx::Rect> pair_r1(
- dom_agent()
- ->GetElementFromNodeId(pinned_id)
- ->GetNodeWindowAndScreenBounds());
+ element_r1->GetNodeWindowAndScreenBounds());
#if defined(OS_MACOSX)
// TODO(lgrey): Explain this
if (pair_r1.first != pair_r2.first) {
@@ -471,6 +472,9 @@ Response OverlayAgentViews::HighlightNode(int node_id, bool show_size) {
if (!element)
return Response::Error("No node found with that id");
+ if (element->type() == UIElementType::ROOT)
+ return Response::Error("Cannot highlight root node.");
+
if (!layer_for_highlighting_) {
layer_for_highlighting_.reset(new ui::Layer(ui::LayerType::LAYER_TEXTURED));
layer_for_highlighting_->set_name("HighlightingLayer");
diff --git a/chromium/components/ui_devtools/views/page_agent_views.cc b/chromium/components/ui_devtools/views/page_agent_views.cc
index 98a80219c71..87175a720a9 100644
--- a/chromium/components/ui_devtools/views/page_agent_views.cc
+++ b/chromium/components/ui_devtools/views/page_agent_views.cc
@@ -4,16 +4,18 @@
#include "components/ui_devtools/views/page_agent_views.h"
+#include <unordered_set>
+
#include "base/command_line.h"
+#include "base/strings/string_split.h"
+#include "components/ui_devtools/agent_util.h"
#include "components/ui_devtools/ui_element.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/views_switches.h"
namespace ui_devtools {
-PageAgentViews::PageAgentViews(DOMAgent* dom_agent) : PageAgent(dom_agent) {}
-
-PageAgentViews::~PageAgentViews() {}
+namespace {
void PaintRectVector(std::vector<UIElement*> child_elements) {
for (auto* element : child_elements) {
@@ -24,6 +26,42 @@ void PaintRectVector(std::vector<UIElement*> child_elements) {
}
}
+std::unordered_set<std::string> GetSources(UIElement* root) {
+ std::unordered_set<std::string> ret;
+
+ for (auto& source : root->GetSources()) {
+ ret.insert(source.path_ + "?l=" + base::NumberToString(source.line_));
+ }
+
+ for (auto* child : root->children()) {
+ for (auto& child_source : GetSources(child)) {
+ ret.insert(child_source);
+ }
+ }
+
+ return ret;
+}
+
+void AddFrameResources(
+ std::unique_ptr<protocol::Array<protocol::Page::FrameResource>>&
+ frame_resources,
+ const std::unordered_set<std::string>& all_sources) {
+ for (const auto& source : all_sources) {
+ frame_resources->emplace_back(
+ protocol::Page::FrameResource::create()
+ .setUrl(kChromiumCodeSearchSrcURL + source)
+ .setType("Document")
+ .setMimeType("text/x-c++hdr")
+ .build());
+ }
+}
+
+} // namespace
+
+PageAgentViews::PageAgentViews(DOMAgent* dom_agent) : PageAgent(dom_agent) {}
+
+PageAgentViews::~PageAgentViews() {}
+
protocol::Response PageAgentViews::disable() {
// Set bubble lock flag back to false.
views::BubbleDialogDelegateView::devtools_dismiss_override_ = false;
@@ -63,4 +101,59 @@ protocol::Response PageAgentViews::reload(protocol::Maybe<bool> bypass_cache) {
return protocol::Response::OK();
}
+protocol::Response PageAgentViews::getResourceTree(
+ std::unique_ptr<protocol::Page::FrameResourceTree>* object) {
+ std::unique_ptr<protocol::Page::Frame> frame_object =
+ protocol::Page::Frame::create()
+ .setId("1")
+ .setUrl(kChromiumCodeSearchURL)
+ .build();
+ auto subresources =
+ std::make_unique<protocol::Array<protocol::Page::FrameResource>>();
+
+ // Ensure that the DOM tree has been initialized, so all sources have
+ // been added.
+ if (dom_agent_->element_root() == nullptr) {
+ std::unique_ptr<protocol::DOM::Node> node;
+ dom_agent_->getDocument(&node);
+ }
+
+ std::unordered_set<std::string> all_sources =
+ GetSources(dom_agent_->element_root());
+
+ AddFrameResources(subresources, all_sources);
+ std::unique_ptr<protocol::Page::FrameResourceTree> result =
+ protocol::Page::FrameResourceTree::create()
+ .setFrame(std::move(frame_object))
+ .setResources(std::move(subresources))
+ .build();
+ *object = std::move(result);
+ return protocol::Response::OK();
+}
+
+protocol::Response PageAgentViews::getResourceContent(
+ const protocol::String& in_frameId,
+ const protocol::String& in_url,
+ protocol::String* out_content,
+ bool* out_base64Encoded) {
+ auto split_url = base::SplitStringUsingSubstr(
+ in_url, "src/", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (split_url.size() != 2)
+ return protocol::Response::Error("Invalid URL");
+
+ auto split_path = base::SplitStringUsingSubstr(
+ split_url[1], "?l=", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (split_path.size() != 2)
+ return protocol::Response::Error("Invalid URL");
+
+ if (GetSourceCode(split_path[0], out_content))
+ return protocol::Response::OK();
+ else
+ return protocol::Response::Error("Could not read source file");
+}
+
+bool PageAgentViews::devtools_dismiss_override() {
+ return views::BubbleDialogDelegateView::devtools_dismiss_override_;
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/page_agent_views.h b/chromium/components/ui_devtools/views/page_agent_views.h
index 573ce5a400e..a7f079e06da 100644
--- a/chromium/components/ui_devtools/views/page_agent_views.h
+++ b/chromium/components/ui_devtools/views/page_agent_views.h
@@ -17,8 +17,17 @@ class PageAgentViews : public PageAgent {
// PageAgent:
protocol::Response disable() override;
protocol::Response reload(protocol::Maybe<bool> bypass_cache) override;
+ protocol::Response getResourceTree(
+ std::unique_ptr<protocol::Page::FrameResourceTree>* frame_tree) override;
+ protocol::Response getResourceContent(const protocol::String& in_frameId,
+ const protocol::String& in_url,
+ protocol::String* out_content,
+ bool* out_base64Encoded) override;
private:
+ friend class PageAgentViewsTest;
+ bool devtools_dismiss_override();
+
DISALLOW_COPY_AND_ASSIGN(PageAgentViews);
};
diff --git a/chromium/components/ui_devtools/views/page_agent_views_unittest.cc b/chromium/components/ui_devtools/views/page_agent_views_unittest.cc
new file mode 100644
index 00000000000..b9ebbf3ecad
--- /dev/null
+++ b/chromium/components/ui_devtools/views/page_agent_views_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ui_devtools/views/page_agent_views.h"
+
+#include "base/command_line.h"
+#include "components/ui_devtools/agent_util.h"
+#include "components/ui_devtools/ui_devtools_unittest_utils.h"
+#include "components/ui_devtools/ui_element.h"
+#include "components/ui_devtools/views/dom_agent_views.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/views_switches.h"
+
+namespace ui_devtools {
+
+class PageAgentViewsTest : public views::ViewsTestBase {
+ public:
+ void SetUp() override {
+ frontend_channel_ = std::make_unique<FakeFrontendChannel>();
+ uber_dispatcher_ =
+ std::make_unique<protocol::UberDispatcher>(frontend_channel_.get());
+ dom_agent_ = DOMAgentViews::Create();
+ dom_agent_->Init(uber_dispatcher_.get());
+ page_agent_ = std::make_unique<PageAgentViews>(dom_agent_.get());
+ page_agent_->Init(uber_dispatcher_.get());
+ page_agent_->enable();
+ views::ViewsTestBase::SetUp();
+ }
+
+ void TearDown() override {
+ page_agent_.reset();
+ dom_agent_.reset();
+ uber_dispatcher_.reset();
+ frontend_channel_.reset();
+ views::ViewsTestBase::TearDown();
+ }
+
+ bool HasSource(protocol::Array<protocol::Page::FrameResource>* resources,
+ std::string source) {
+ for (const auto& resource : *resources) {
+ if (resource->getUrl() == kChromiumCodeSearchSrcURL + source)
+ return true;
+ }
+ return false;
+ }
+
+ bool VerifyResources(
+ protocol::Array<protocol::Page::FrameResource>* resources) {
+ std::stack<UIElement*> elements;
+ elements.emplace(dom_agent()->element_root());
+
+ UIElement* cur_element;
+ while (!elements.empty()) {
+ cur_element = elements.top();
+ elements.pop();
+ for (const auto& source : cur_element->GetSources()) {
+ if (!HasSource(resources, source.path_ + "?l=" +
+ base::NumberToString(source.line_)))
+ return false;
+ }
+
+ for (auto* child : cur_element->children()) {
+ elements.emplace(child);
+ }
+ }
+
+ return true;
+ }
+
+ std::pair<bool, std::string> GetResourceContent(std::string url_input) {
+ std::string result;
+ bool out_bool;
+
+ auto response =
+ page_agent()->getResourceContent("1", url_input, &result, &out_bool);
+ return {response.isSuccess(), result};
+ }
+
+ protected:
+ PageAgentViews* page_agent() { return page_agent_.get(); }
+ DOMAgentViews* dom_agent() { return dom_agent_.get(); }
+ bool devtools_dismiss_override() {
+ return page_agent()->devtools_dismiss_override();
+ }
+
+ private:
+ std::unique_ptr<PageAgentViews> page_agent_;
+ std::unique_ptr<DOMAgentViews> dom_agent_;
+ std::unique_ptr<FakeFrontendChannel> frontend_channel_;
+ std::unique_ptr<protocol::UberDispatcher> uber_dispatcher_;
+};
+
+TEST_F(PageAgentViewsTest, ToggleBubbleLock) {
+ DCHECK(!devtools_dismiss_override());
+
+ // Enable bubble locking.
+ page_agent()->reload(true);
+
+ // Check that |devtools_dismiss_override_| is set to true.
+ EXPECT_TRUE(devtools_dismiss_override());
+
+ // Call again to disable bubble locking.
+ page_agent()->reload(true);
+
+ // Check that |devtools_dismiss_override_| set back to false.
+ EXPECT_FALSE(devtools_dismiss_override());
+}
+
+TEST_F(PageAgentViewsTest, ToggleViewDebugRects) {
+ std::unique_ptr<protocol::DOM::Node> root;
+ dom_agent()->getDocument(&root);
+
+ DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ views::switches::kDrawViewBoundsRects));
+
+ // Enable debug rectangles.
+ page_agent()->reload(false);
+
+ // Check that debug rectangles switch is present.
+ EXPECT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ views::switches::kDrawViewBoundsRects));
+
+ // Disable debug rectangles.
+ page_agent()->reload(false);
+
+ // Check that the debug rectangles switch is removed.
+ EXPECT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ views::switches::kDrawViewBoundsRects));
+}
+
+TEST_F(PageAgentViewsTest, ResetOnDisable) {
+ std::unique_ptr<protocol::DOM::Node> root;
+ dom_agent()->getDocument(&root);
+
+ // Enable both debug rectangles and bubble locking.
+ page_agent()->reload(false);
+ page_agent()->reload(true);
+ DCHECK(devtools_dismiss_override());
+ DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ views::switches::kDrawViewBoundsRects));
+
+ // Disable PageAgentViews, as is done on UI DevTools closing.
+ page_agent()->disable();
+
+ // Check that both bubble locking and debug rectangles are off.
+ EXPECT_FALSE(devtools_dismiss_override());
+ EXPECT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ views::switches::kDrawViewBoundsRects));
+}
+
+TEST_F(PageAgentViewsTest, GetResourceTree) {
+ std::unique_ptr<protocol::Page::FrameResourceTree> resource_tree;
+ EXPECT_TRUE(page_agent()->getResourceTree(&resource_tree).isSuccess());
+
+ protocol::Page::Frame* frame_object = resource_tree->getFrame();
+ EXPECT_EQ(frame_object->getId(), "1");
+ EXPECT_EQ(frame_object->getUrl(), kChromiumCodeSearchURL);
+
+ EXPECT_TRUE(VerifyResources(resource_tree->getResources()));
+}
+
+TEST_F(PageAgentViewsTest, GetResourceContent) {
+ auto result = GetResourceContent(
+ "chromium/src/components/test/data/ui_devtools/test_file.cc?l=0");
+
+ EXPECT_TRUE(result.first);
+ EXPECT_NE(result.second, "");
+}
+
+TEST_F(PageAgentViewsTest, GetResourceContentFailsOnBadURL) {
+ // Test if URL doesn't have src/.
+ auto result = GetResourceContent(
+ "incorrect/components/test/data/ui_devtools/test_file.cc?l=0");
+
+ EXPECT_FALSE(result.first);
+ EXPECT_EQ(result.second, "");
+
+ // Test if URL doesn't have line number.
+ result = GetResourceContent(
+ "chromium/src/components/test/data/ui_devtools/test_file.cc");
+
+ EXPECT_FALSE(result.first);
+ EXPECT_EQ(result.second, "");
+
+ // Test if URL isn't a real file.
+ result = GetResourceContent("chromium/src/not/a/real/file.cc?l=0");
+
+ EXPECT_FALSE(result.first);
+ EXPECT_EQ(result.second, "");
+}
+
+} // namespace ui_devtools \ No newline at end of file
diff --git a/chromium/components/ui_devtools/views/view_element.cc b/chromium/components/ui_devtools/views/view_element.cc
index 9756c6fbe91..6115ce97b8e 100644
--- a/chromium/components/ui_devtools/views/view_element.cc
+++ b/chromium/components/ui_devtools/views/view_element.cc
@@ -9,10 +9,30 @@
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_element_delegate.h"
#include "components/ui_devtools/views/element_utility.h"
+#include "ui/gfx/color_utils.h"
#include "ui/views/widget/widget.h"
namespace ui_devtools {
+namespace {
+
+// Returns true if |property_name| is type SkColor, false if not. If type
+// SkColor, remove the "--" from the name.
+bool GetSkColorPropertyName(std::string& property_name) {
+ if (property_name.length() < 2U)
+ return false;
+
+ // Check if property starts with "--", meaning its type is SkColor.
+ if (property_name[0] == '-' && property_name[1] == '-') {
+ // Remove "--" from |property_name|.
+ base::TrimString(property_name, "-", &property_name);
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
ViewElement::ViewElement(views::View* view,
UIElementDelegate* ui_element_delegate,
UIElement* parent)
@@ -90,9 +110,19 @@ ViewElement::GetCustomPropertiesForMatchedStyle() const {
base::UTF16ToUTF8(description));
}
- class_properties.emplace_back(
- (*member)->member_name(),
- base::UTF16ToUTF8((*member)->GetValueAsString(view_)));
+ // Check if type is SkColor and add "--" to property name so that DevTools
+ // frontend will interpret this field as a color. Also convert SkColor value
+ // to rgba string.
+ if ((*member)->member_type() == "SkColor") {
+ SkColor color;
+ if (base::StringToUint(
+ base::UTF16ToUTF8((*member)->GetValueAsString(view_)), &color))
+ class_properties.emplace_back("--" + (*member)->member_name(),
+ color_utils::SkColorToRgbaString(color));
+ } else
+ class_properties.emplace_back(
+ (*member)->member_name(),
+ base::UTF16ToUTF8((*member)->GetValueAsString(view_)));
if (member.IsLastMember()) {
ret.emplace_back(member.GetCurrentCollectionName(), class_properties);
@@ -121,6 +151,7 @@ void ViewElement::SetVisible(bool visible) {
}
bool ViewElement::SetPropertiesFromString(const std::string& text) {
+ bool property_set = false;
std::vector<std::string> tokens = base::SplitString(
text, ":;", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@@ -128,8 +159,15 @@ bool ViewElement::SetPropertiesFromString(const std::string& text) {
return false;
for (size_t i = 0; i < tokens.size() - 1; i += 2) {
- const std::string& property_name = tokens.at(i);
- const std::string& property_value = base::ToLowerASCII(tokens.at(i + 1));
+ std::string property_name = tokens.at(i);
+ std::string property_value = base::ToLowerASCII(tokens.at(i + 1));
+
+ // Check if property is type SkColor.
+ if (GetSkColorPropertyName(property_name)) {
+ // Convert from CSS color format to SkColor.
+ if (!ParseColorFromFrontend(property_value, &property_value))
+ continue;
+ }
views::metadata::ClassMetaData* metadata = view_->GetClassMetaData();
views::metadata::MemberMetaDataBase* member =
@@ -150,9 +188,10 @@ bool ViewElement::SetPropertiesFromString(const std::string& text) {
}
member->SetValueAsString(view_, base::UTF8ToUTF16(property_value));
+ property_set = true;
}
- return true;
+ return property_set;
}
std::vector<std::string> ViewElement::GetAttributes() const {
@@ -191,4 +230,18 @@ void ViewElement::PaintRect() const {
view()->SchedulePaint();
}
+void ViewElement::InitSources() {
+ if (view_->layer()) {
+ AddSource("ui/compositor/layer.h", 0);
+ }
+
+ for (views::metadata::ClassMetaData* metadata = view_->GetClassMetaData();
+ metadata != nullptr; metadata = metadata->parent_class_meta_data()) {
+ // If class has Metadata properties, add their sources.
+ if (!metadata->members().empty()) {
+ AddSource(metadata->file(), metadata->line());
+ }
+ }
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/view_element.h b/chromium/components/ui_devtools/views/view_element.h
index cbde8638874..6b286ad13d5 100644
--- a/chromium/components/ui_devtools/views/view_element.h
+++ b/chromium/components/ui_devtools/views/view_element.h
@@ -43,6 +43,7 @@ class ViewElement : public views::ViewObserver, public UIElement {
const override;
static views::View* From(const UIElement* element);
void PaintRect() const override;
+ void InitSources() override;
private:
views::View* view_;
diff --git a/chromium/components/ui_devtools/views/view_element_unittest.cc b/chromium/components/ui_devtools/views/view_element_unittest.cc
index 41a6a7c5370..f327ed890de 100644
--- a/chromium/components/ui_devtools/views/view_element_unittest.cc
+++ b/chromium/components/ui_devtools/views/view_element_unittest.cc
@@ -73,13 +73,18 @@ class NamedTestView : public views::View {
int GetBoolProperty() const { return bool_property_; }
void SetBoolProperty(bool bool_property) { bool_property_ = bool_property; }
+ SkColor GetColorProperty() const { return color_property_; }
+ void SetColorProperty(SkColor color) { color_property_ = color; }
+
private:
bool bool_property_ = false;
+ SkColor color_property_ = SK_ColorGRAY;
};
BEGIN_METADATA(NamedTestView)
METADATA_PARENT_CLASS(views::View)
ADD_PROPERTY_METADATA(NamedTestView, bool, BoolProperty)
+ADD_PROPERTY_METADATA(NamedTestView, SkColor, ColorProperty)
END_METADATA()
class ViewElementTest : public views::ViewsTestBase {
@@ -232,7 +237,7 @@ TEST_F(ViewElementTest, GetNodeWindowAndScreenBounds) {
views::Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget->Init(params);
+ widget->Init(std::move(params));
widget->Show();
widget->GetContentsView()->AddChildView(view());
@@ -247,4 +252,46 @@ TEST_F(ViewElementTest, GetNodeWindowAndScreenBounds) {
view()->parent()->RemoveChildView(view());
}
+TEST_F(ViewElementTest, ColorProperty) {
+ EXPECT_EQ(GetPropertyIndices(element(), "--ColorProperty").first, 0U);
+ DCHECK_EQ(view()->GetColorProperty(), SK_ColorGRAY);
+
+ EXPECT_TRUE(element()->SetPropertiesFromString(
+ "--ColorProperty: rgba(0,0, 255, 1);"));
+ EXPECT_EQ(view()->GetColorProperty(), SK_ColorBLUE);
+
+ EXPECT_TRUE(element()->SetPropertiesFromString("--ColorProperty: #0352fc"));
+ EXPECT_EQ(view()->GetColorProperty(), SkColorSetARGB(255, 3, 82, 252));
+
+ EXPECT_TRUE(element()->SetPropertiesFromString(
+ "--ColorProperty: hsl(240, 84%, 28%);"));
+ EXPECT_EQ(view()->GetColorProperty(), SkColorSetARGB(255, 11, 11, 131));
+}
+
+TEST_F(ViewElementTest, BadColorProperty) {
+ DCHECK_EQ(view()->GetColorProperty(), SK_ColorGRAY);
+
+ EXPECT_FALSE(
+ element()->SetPropertiesFromString("-ColorProperty: rgba(1,2,3,4);"));
+ EXPECT_EQ(view()->GetColorProperty(), SK_ColorGRAY);
+
+ EXPECT_FALSE(
+ element()->SetPropertiesFromString("--ColorProperty: rgba(1,2,3,4;"));
+ EXPECT_EQ(view()->GetColorProperty(), SK_ColorGRAY);
+
+ EXPECT_FALSE(
+ element()->SetPropertiesFromString("--ColorProperty: rgb(1,2,3,4;)"));
+ EXPECT_EQ(view()->GetColorProperty(), SK_ColorGRAY);
+}
+
+TEST_F(ViewElementTest, GetSources) {
+ std::vector<UIElement::Source> sources = element()->GetSources();
+
+ // ViewElement should have two sources: from NamedTestView and from View.
+ EXPECT_EQ(sources.size(), 2U);
+ EXPECT_EQ(sources[0].path_,
+ "components/ui_devtools/views/view_element_unittest.cc");
+ EXPECT_EQ(sources[1].path_, "ui/views/view.h");
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/widget_element.cc b/chromium/components/ui_devtools/views/widget_element.cc
index 41094c60cc0..086e6617bab 100644
--- a/chromium/components/ui_devtools/views/widget_element.cc
+++ b/chromium/components/ui_devtools/views/widget_element.cc
@@ -84,6 +84,10 @@ views::Widget* WidgetElement::From(const UIElement* element) {
return static_cast<const WidgetElement*>(element)->widget_;
}
+void WidgetElement::InitSources() {
+ AddSource("ui/views/widget/widget.h", 0);
+}
+
template <>
int UIElement::FindUIElementIdForBackendElement<views::Widget>(
views::Widget* element) const {
@@ -99,4 +103,5 @@ int UIElement::FindUIElementIdForBackendElement<views::Widget>(
}
return 0;
}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/widget_element.h b/chromium/components/ui_devtools/views/widget_element.h
index e82758f6491..dc43b46d4b5 100644
--- a/chromium/components/ui_devtools/views/widget_element.h
+++ b/chromium/components/ui_devtools/views/widget_element.h
@@ -45,6 +45,7 @@ class WidgetElement : public views::WidgetRemovalsObserver,
const override;
static views::Widget* From(const UIElement* element);
+ void InitSources() override;
private:
views::Widget* widget_;
diff --git a/chromium/components/ui_devtools/views/widget_element_unittest.cc b/chromium/components/ui_devtools/views/widget_element_unittest.cc
index 4fef1dfd1e5..dc3ede06df8 100644
--- a/chromium/components/ui_devtools/views/widget_element_unittest.cc
+++ b/chromium/components/ui_devtools/views/widget_element_unittest.cc
@@ -29,7 +29,7 @@ class WidgetElementTest : public views::ViewsTestBase {
views::Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
params.name = kWidgetName;
- widget_->Init(params);
+ widget_->Init(std::move(params));
delegate_.reset(new testing::NiceMock<MockUIElementDelegate>);
element_.reset(new WidgetElement(widget_, delegate_.get(), nullptr));
diff --git a/chromium/components/ui_devtools/views/window_element.cc b/chromium/components/ui_devtools/views/window_element.cc
index a6db840e002..7a137e2784b 100644
--- a/chromium/components/ui_devtools/views/window_element.cc
+++ b/chromium/components/ui_devtools/views/window_element.cc
@@ -155,4 +155,11 @@ int UIElement::FindUIElementIdForBackendElement<aura::Window>(
return 0;
}
+void WindowElement::InitSources() {
+ if (window_->layer()) {
+ AddSource("ui/compositor/layer.h", 0);
+ }
+ AddSource("ui/aura/window.h", 0);
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/window_element.h b/chromium/components/ui_devtools/views/window_element.h
index edc5c783d1f..40ed6c5773f 100644
--- a/chromium/components/ui_devtools/views/window_element.h
+++ b/chromium/components/ui_devtools/views/window_element.h
@@ -45,6 +45,7 @@ class WindowElement : public aura::WindowObserver, public UIElement {
const override;
static aura::Window* From(const UIElement* element);
+ void InitSources() override;
private:
aura::Window* window_;
diff --git a/chromium/components/ui_metrics/OWNERS b/chromium/components/ui_metrics/OWNERS
new file mode 100644
index 00000000000..b852eb748c3
--- /dev/null
+++ b/chromium/components/ui_metrics/OWNERS
@@ -0,0 +1,3 @@
+# COMPONENT: Mobile>iOSWeb
+# For Android related items, use COMPONENT: UI>Browser>Mobile
+# TEAM: ios-directory-owners@chromium.org
diff --git a/chromium/components/ukm/app_source_url_recorder_test.cc b/chromium/components/ukm/app_source_url_recorder_test.cc
index 444dedd4119..4015d76d2e2 100644
--- a/chromium/components/ukm/app_source_url_recorder_test.cc
+++ b/chromium/components/ukm/app_source_url_recorder_test.cc
@@ -5,7 +5,7 @@
#include "components/ukm/app_source_url_recorder.h"
#include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,7 +29,7 @@ class AppSourceUrlRecorderTest : public testing::Test {
}
base::test::ScopedFeatureList scoped_feature_list_;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
TestAutoSetUkmRecorder test_ukm_recorder_;
};
diff --git a/chromium/components/ukm/content/source_url_recorder_browsertest.cc b/chromium/components/ukm/content/source_url_recorder_browsertest.cc
index ff755a6783f..72969135457 100644
--- a/chromium/components/ukm/content/source_url_recorder_browsertest.cc
+++ b/chromium/components/ukm/content/source_url_recorder_browsertest.cc
@@ -94,7 +94,7 @@ IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest,
GURL url = embedded_test_server()->GetURL("/title1.html");
content::NavigationHandleObserver observer(shell()->web_contents(), url);
- content::NavigateToURL(shell(), url);
+ EXPECT_TRUE(content::NavigateToURL(shell(), url));
EXPECT_TRUE(observer.has_committed());
const ukm::UkmSource* source =
GetSourceForNavigationId(observer.navigation_id());
@@ -130,7 +130,7 @@ IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest,
main_url);
content::NavigationHandleObserver subframe_observer(shell()->web_contents(),
subframe_url);
- content::NavigateToURL(shell(), main_url);
+ EXPECT_TRUE(content::NavigateToURL(shell(), main_url));
EXPECT_TRUE(main_observer.has_committed());
EXPECT_TRUE(main_observer.is_main_frame());
EXPECT_TRUE(subframe_observer.has_committed());
@@ -161,12 +161,11 @@ IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest,
EXPECT_NE(source->id(), ukm_entries[1]->source_id);
}
-// Flaky on all OSes: https://crbug.com/951020
IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverDownloadBrowserTest,
- DISABLED_IgnoreDownload) {
+ IgnoreDownload) {
GURL url(embedded_test_server()->GetURL("/download-test1.lib"));
content::NavigationHandleObserver observer(shell()->web_contents(), url);
- content::NavigateToURL(shell(), url);
+ EXPECT_TRUE(content::NavigateToURLAndExpectNoCommit(shell(), url));
EXPECT_FALSE(observer.has_committed());
EXPECT_TRUE(observer.is_download());
EXPECT_EQ(nullptr, GetSourceForNavigationId(observer.navigation_id()));
diff --git a/chromium/components/ukm/debug/ukm_internals.js b/chromium/components/ukm/debug/ukm_internals.js
index 5bec3e1aafc..92aebee3912 100644
--- a/chromium/components/ukm/debug/ukm_internals.js
+++ b/chromium/components/ukm/debug/ukm_internals.js
@@ -86,7 +86,7 @@ function as64Bit(num) {
/**
* Sets the display option of all the elements in HtmlCollection to the value
* passed.
- * @param {!NodeList<!Element>} collection Collection of Elements.
+ * @param {!HTMLCollection<!Element>} collection Collection of Elements.
*/
function setDisplayStyle(collection, display_value) {
for (const el of collection) {
diff --git a/chromium/components/ukm/ukm_recorder_impl.cc b/chromium/components/ukm/ukm_recorder_impl.cc
index 4e265f9b44d..55f90237c52 100644
--- a/chromium/components/ukm/ukm_recorder_impl.cc
+++ b/chromium/components/ukm/ukm_recorder_impl.cc
@@ -64,8 +64,9 @@ size_t GetMaxSources() {
kUkmFeature, "MaxSources", kDefaultMaxSources));
}
-// Gets the maximum number of Sources we can kept in memory to defer to the next
-// reporting interval at the end of the current reporting cycle.
+// Gets the maximum number of Sources we can keep in memory at the end of the
+// current reporting cycle that will stay accessible in the next reporting
+// interval.
size_t GetMaxKeptSources() {
constexpr size_t kDefaultMaxKeptSources = 100;
return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt(
@@ -295,9 +296,11 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
std::unordered_map<ukm::SourceIdType, int> serialized_source_type_counts;
for (const auto& kv : recordings_.sources) {
- // Sources of non-navigation types will not be kept after current report.
- if (GetSourceIdType(kv.first) != base::UkmSourceId::Type::NAVIGATION_ID) {
- recordings_.obsolete_source_ids.insert(kv.first);
+ // Don't keep sources of these types after current report because their
+ // entries are logged only at source creation time.
+ if (GetSourceIdType(kv.first) == base::UkmSourceId::Type::APP_ID ||
+ GetSourceIdType(kv.first) == base::UkmSourceId::Type::HISTORY_ID) {
+ MarkSourceForDeletion(kv.first);
}
// If the source id is not whitelisted, don't send it unless it has
// associated entries and the URL matches that of a whitelisted source.
@@ -316,6 +319,10 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
// Omit entryless sources from the report.
if (!base::Contains(source_ids_seen, kv.first)) {
continue;
+ } else {
+ // Source of base::UkmSourceId::Type::UKM type will not be kept after
+ // entries are logged.
+ MarkSourceForDeletion(kv.first);
}
}
Source* proto_source = report->add_sources();
diff --git a/chromium/components/ukm/ukm_service.cc b/chromium/components/ukm/ukm_service.cc
index 66025adce8a..581cbf7f89c 100644
--- a/chromium/components/ukm/ukm_service.cc
+++ b/chromium/components/ukm/ukm_service.cc
@@ -78,13 +78,8 @@ UkmService::UkmService(PrefService* pref_service,
bool restrict_to_whitelist_entries)
: pref_service_(pref_service),
restrict_to_whitelist_entries_(restrict_to_whitelist_entries),
- client_id_(0),
- session_id_(0),
- report_count_(0),
client_(client),
- reporting_service_(client, pref_service),
- initialize_started_(false),
- initialize_complete_(false) {
+ reporting_service_(client, pref_service) {
DCHECK(pref_service_);
DCHECK(client_);
DVLOG(1) << "UkmService::Constructor";
@@ -131,6 +126,7 @@ void UkmService::EnableReporting() {
if (reporting_service_.reporting_active())
return;
+ log_creation_time_ = base::TimeTicks::Now();
metrics_providers_.OnRecordingEnabled();
if (!initialize_started_)
@@ -260,8 +256,8 @@ void UkmService::BuildAndStoreLog() {
metrics::MetricsLog::RecordCoreSystemProfile(client_,
report.mutable_system_profile());
- metrics_providers_.ProvideSystemProfileMetrics(
- report.mutable_system_profile());
+ metrics_providers_.ProvideSystemProfileMetricsWithLogCreationTime(
+ log_creation_time_, report.mutable_system_profile());
std::string serialized_log;
report.SerializeToString(&serialized_log);
diff --git a/chromium/components/ukm/ukm_service.h b/chromium/components/ukm/ukm_service.h
index 067aac66c2a..a510c2857e4 100644
--- a/chromium/components/ukm/ukm_service.h
+++ b/chromium/components/ukm/ukm_service.h
@@ -128,13 +128,13 @@ class UkmService : public UkmRecorderImpl {
bool restrict_to_whitelist_entries_;
// The UKM client id stored in prefs.
- uint64_t client_id_;
+ uint64_t client_id_ = 0;
// The UKM session id stored in prefs.
- int32_t session_id_;
+ int32_t session_id_ = 0;
// The number of reports generated this session.
- int32_t report_count_;
+ int32_t report_count_ = 0;
// Used to interact with the embedder. Weak pointer; must outlive |this|
// instance.
@@ -149,10 +149,12 @@ class UkmService : public UkmRecorderImpl {
// The scheduler for determining when uploads should happen.
std::unique_ptr<metrics::MetricsRotationScheduler> scheduler_;
- SEQUENCE_CHECKER(sequence_checker_);
+ base::TimeTicks log_creation_time_;
+
+ bool initialize_started_ = false;
+ bool initialize_complete_ = false;
- bool initialize_started_;
- bool initialize_complete_;
+ SEQUENCE_CHECKER(sequence_checker_);
// Weak pointers factory used to post task on different threads. All weak
// pointers managed by this factory have the same lifetime as UkmService.
diff --git a/chromium/components/ukm/ukm_service_unittest.cc b/chromium/components/ukm/ukm_service_unittest.cc
index 5a7dd66d0bf..c1e0f4b3233 100644
--- a/chromium/components/ukm/ukm_service_unittest.cc
+++ b/chromium/components/ukm/ukm_service_unittest.cc
@@ -711,8 +711,10 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) {
// The one whitelisted source is of navigation type.
EXPECT_EQ(1, proto_report.source_counts().navigation_sources());
EXPECT_EQ(0, proto_report.source_counts().unmatched_sources());
- // Only the navigation type source is deferred.
- EXPECT_EQ(1, proto_report.source_counts().deferred_sources());
+ // Source 0 of navigation type, and entryless sources 1, 3, 4, 5 of
+ // non-whitelisted type are eligible to be deferred, but MaxKeptSources
+ // restricts deferral to the 3 latest created ones.
+ EXPECT_EQ(3, proto_report.source_counts().deferred_sources());
EXPECT_EQ(0, proto_report.source_counts().carryover_sources());
ASSERT_EQ(3, proto_report.sources_size());
@@ -756,12 +758,14 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) {
// Only the navigation type source is deferred.
EXPECT_EQ(1, proto_report.source_counts().deferred_sources());
// Number of sources carried over from the previous report to this report.
- EXPECT_EQ(1, proto_report.source_counts().carryover_sources());
- // Only the navigation source is again included in current report and
- // there is a new entry associated to it.
- ASSERT_EQ(1, proto_report.sources_size());
- EXPECT_EQ(whitelisted_id, proto_report.sources(0).id());
+ EXPECT_EQ(3, proto_report.source_counts().carryover_sources());
+ // Out of sources 3, 4, 5 that were retained from the previous cycle,
+ // sources 3 and 4 got new entries are thus included in this report.
+ ASSERT_EQ(2, proto_report.sources_size());
+ EXPECT_EQ(ids[3], proto_report.sources(0).id());
EXPECT_EQ(kURL.spec(), proto_report.sources(0).url());
+ EXPECT_EQ(ids[4], proto_report.sources(1).id());
+ EXPECT_EQ(kURL.spec(), proto_report.sources(1).url());
}
}
}
diff --git a/chromium/components/undo/bookmark_undo_service.cc b/chromium/components/undo/bookmark_undo_service.cc
index 452f563a3c7..57ec66e107f 100644
--- a/chromium/components/undo/bookmark_undo_service.cc
+++ b/chromium/components/undo/bookmark_undo_service.cc
@@ -11,7 +11,6 @@
#include <utility>
#include "base/macros.h"
-#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node_data.h"
#include "components/bookmarks/browser/bookmark_undo_provider.h"
#include "components/bookmarks/browser/bookmark_utils.h"
@@ -329,9 +328,7 @@ int BookmarkReorderOperation::GetRedoLabelId() const {
// BookmarkUndoService --------------------------------------------------------
-BookmarkUndoService::BookmarkUndoService()
- : model_(nullptr), scoped_observer_(this) {
-}
+BookmarkUndoService::BookmarkUndoService() : model_(nullptr) {}
BookmarkUndoService::~BookmarkUndoService() {
}
diff --git a/chromium/components/undo/bookmark_undo_service.h b/chromium/components/undo/bookmark_undo_service.h
index 2604efd83b0..b7ccb71b85b 100644
--- a/chromium/components/undo/bookmark_undo_service.h
+++ b/chromium/components/undo/bookmark_undo_service.h
@@ -10,16 +10,12 @@
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "components/bookmarks/browser/base_bookmark_model_observer.h"
+#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node_data.h"
#include "components/bookmarks/browser/bookmark_undo_delegate.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/undo/undo_manager.h"
-namespace bookmarks {
-class BookmarkModel;
-class BookmarkModelObserver;
-}
-
// BookmarkUndoService --------------------------------------------------------
// BookmarkUndoService is owned by the profile, and is responsible for observing
@@ -75,7 +71,7 @@ class BookmarkUndoService : public bookmarks::BaseBookmarkModelObserver,
bookmarks::BookmarkUndoProvider* undo_provider_;
UndoManager undo_manager_;
ScopedObserver<bookmarks::BookmarkModel, bookmarks::BookmarkModelObserver>
- scoped_observer_;
+ scoped_observer_{this};
DISALLOW_COPY_AND_ASSIGN(BookmarkUndoService);
};
diff --git a/chromium/components/undo_strings.grdp b/chromium/components/undo_strings.grdp
index f1380cad036..8183e5d91b2 100644
--- a/chromium/components/undo_strings.grdp
+++ b/chromium/components/undo_strings.grdp
@@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_BOOKMARK_BAR_UNDO_DESCRIPTION" desc="Shortcut description for undoing a bookmark operation, used as a hint for keyboard users">
- press <ph name="MODIFIER_KEY_DESCRIPTION">$1<ex>Control Z</ex></ph> to undo
- </message>
-
<if expr="not use_titlecase">
<message name="IDS_BOOKMARK_BAR_UNDO" desc="Menu title for undoing a bookmark operation">
&amp;Undo
diff --git a/chromium/components/unified_consent/unified_consent_service_unittest.cc b/chromium/components/unified_consent/unified_consent_service_unittest.cc
index 1ff554835de..b4252dde064 100644
--- a/chromium/components/unified_consent/unified_consent_service_unittest.cc
+++ b/chromium/components/unified_consent/unified_consent_service_unittest.cc
@@ -9,7 +9,7 @@
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/sync/base/sync_prefs.h"
@@ -89,7 +89,7 @@ class UnifiedConsentServiceTest : public testing::Test {
}
protected:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
signin::IdentityTestEnvironment identity_test_environment_;
TestSyncService sync_service_;
diff --git a/chromium/components/update_client/BUILD.gn b/chromium/components/update_client/BUILD.gn
index 5f87e658c04..de3d06b32d4 100644
--- a/chromium/components/update_client/BUILD.gn
+++ b/chromium/components/update_client/BUILD.gn
@@ -39,6 +39,8 @@ source_set("patch_impl") {
deps = [
":update_client",
"//components/services/patch/public/cpp",
+ "//components/services/patch/public/mojom",
+ "//mojo/public/cpp/bindings",
]
}
@@ -124,6 +126,7 @@ static_library("update_client") {
deps = [
"//base",
+ "//build:branding_buildflags",
"//components/client_update_protocol",
"//components/crx_file",
"//components/prefs",
@@ -155,14 +158,11 @@ static_library("test_support") {
":unzip_impl",
"//base",
"//components/prefs",
- "//components/services/patch:lib",
- "//components/services/unzip:lib",
+ "//components/services/patch:in_process",
+ "//components/services/unzip:in_process",
"//mojo/public/cpp/bindings",
"//net:test_support",
"//services/network:test_support",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/cpp/test:test_support",
- "//services/service_manager/public/mojom",
"//testing/gmock",
"//testing/gtest",
"//url",
@@ -225,18 +225,17 @@ source_set("unit_tests") {
":unzip_impl",
":update_client",
"//base",
+ "//build:branding_buildflags",
"//components/crx_file",
"//components/prefs",
"//components/prefs:test_support",
- "//components/services/patch:lib",
+ "//components/services/patch:in_process",
"//components/version_info:version_info",
"//courgette:courgette_lib",
"//net:test_support",
"//services/network:test_support",
"//services/network/public/cpp:cpp",
"//services/network/public/cpp:cpp_base",
- "//services/service_manager/public/cpp",
- "//services/service_manager/public/cpp/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/re2",
diff --git a/chromium/components/update_client/DEPS b/chromium/components/update_client/DEPS
index b89a744f97f..8353d047772 100644
--- a/chromium/components/update_client/DEPS
+++ b/chromium/components/update_client/DEPS
@@ -7,8 +7,7 @@ include_rules = [
"+components/version_info",
"+courgette",
"+crypto",
- "+mojo",
- "+services/service_manager/public",
+ "+mojo/public",
"+third_party/re2",
"+third_party/zlib",
]
diff --git a/chromium/components/update_client/OWNERS b/chromium/components/update_client/OWNERS
index ddb2169c83a..b68ef3b42de 100644
--- a/chromium/components/update_client/OWNERS
+++ b/chromium/components/update_client/OWNERS
@@ -3,3 +3,4 @@ sorin@chromium.org
waffles@chromium.org
# COMPONENT: Internals>Installer>Components
+# TEAM: chrome-updates-dev@chromium.org
diff --git a/chromium/components/update_client/action_runner.cc b/chromium/components/update_client/action_runner.cc
index c1f8297c03a..e738bdcd9f6 100644
--- a/chromium/components/update_client/action_runner.cc
+++ b/chromium/components/update_client/action_runner.cc
@@ -40,7 +40,7 @@ void ActionRunner::Run(Callback run_complete) {
run_complete_ = std::move(run_complete);
- base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
+ base::CreateSequencedTaskRunner(kTaskTraits)
->PostTask(
FROM_HERE,
base::BindOnce(&ActionRunner::RunOnTaskRunner, base::Unretained(this),
diff --git a/chromium/components/update_client/action_runner_win.cc b/chromium/components/update_client/action_runner_win.cc
index 6985ee60eea..dca30597e70 100644
--- a/chromium/components/update_client/action_runner_win.cc
+++ b/chromium/components/update_client/action_runner_win.cc
@@ -34,10 +34,9 @@ void ActionRunner::RunCommand(const base::CommandLine& cmdline) {
options.start_hidden = true;
base::Process process = base::LaunchProcess(cmdline, options);
- base::PostTaskWithTraits(
- FROM_HERE, kTaskTraitsRunCommand,
- base::BindOnce(&ActionRunner::WaitForCommand, base::Unretained(this),
- std::move(process)));
+ base::PostTask(FROM_HERE, kTaskTraitsRunCommand,
+ base::BindOnce(&ActionRunner::WaitForCommand,
+ base::Unretained(this), std::move(process)));
}
void ActionRunner::WaitForCommand(base::Process process) {
@@ -67,7 +66,7 @@ base::CommandLine ActionRunner::MakeCommandLine(
}
void ActionRunner::RunRecoveryCRXElevated(const base::FilePath& crx_path) {
- base::CreateCOMSTATaskRunnerWithTraits(
+ base::CreateCOMSTATaskRunner(
kTaskTraitsRunCommand, base::SingleThreadTaskRunnerThreadMode::DEDICATED)
->PostTask(FROM_HERE,
base::BindOnce(&ActionRunner::RunRecoveryCRXElevatedInSTA,
diff --git a/chromium/components/update_client/background_downloader_win.cc b/chromium/components/update_client/background_downloader_win.cc
index 4d6e28e9f61..5e165799a31 100644
--- a/chromium/components/update_client/background_downloader_win.cc
+++ b/chromium/components/update_client/background_downloader_win.cc
@@ -399,8 +399,8 @@ void CleanupJob(const ComPtr<IBackgroundCopyJob>& job) {
BackgroundDownloader::BackgroundDownloader(
std::unique_ptr<CrxDownloader> successor)
: CrxDownloader(std::move(successor)),
- com_task_runner_(base::CreateCOMSTATaskRunnerWithTraits(
- kTaskTraitsBackgroundDownloader)),
+ com_task_runner_(
+ base::CreateCOMSTATaskRunner(kTaskTraitsBackgroundDownloader)),
git_cookie_bits_manager_(0),
git_cookie_job_(0) {}
diff --git a/chromium/components/update_client/component.cc b/chromium/components/update_client/component.cc
index 73fc259d0e7..7f5ecb5bfff 100644
--- a/chromium/components/update_client/component.cc
+++ b/chromium/components/update_client/component.cc
@@ -75,8 +75,9 @@ void InstallComplete(
InstallOnBlockingTaskRunnerCompleteCallback callback,
const base::FilePath& unpack_path,
const CrxInstaller::Result& result) {
- base::PostTaskWithTraits(
- FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+ base::PostTask(
+ FROM_HERE,
+ {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()},
base::BindOnce(
[](scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
InstallOnBlockingTaskRunnerCompleteCallback callback,
@@ -141,11 +142,10 @@ void UnpackCompleteOnBlockingTaskRunner(
return;
}
- base::PostTaskWithTraits(
- FROM_HERE, kTaskTraits,
- base::BindOnce(&InstallOnBlockingTaskRunner, main_task_runner,
- result.unpack_path, result.public_key, fingerprint,
- installer, std::move(callback)));
+ base::PostTask(FROM_HERE, kTaskTraits,
+ base::BindOnce(&InstallOnBlockingTaskRunner, main_task_runner,
+ result.unpack_path, result.public_key,
+ fingerprint, installer, std::move(callback)));
}
void StartInstallOnBlockingTaskRunner(
@@ -756,7 +756,7 @@ void Component::StateUpdatingDiff::DoHandle() {
component.NotifyObservers(Events::COMPONENT_UPDATE_READY);
- base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
+ base::CreateSequencedTaskRunner(kTaskTraits)
->PostTask(
FROM_HERE,
base::BindOnce(
@@ -818,7 +818,7 @@ void Component::StateUpdating::DoHandle() {
component.NotifyObservers(Events::COMPONENT_UPDATE_READY);
- base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
+ base::CreateSequencedTaskRunner(kTaskTraits)
->PostTask(FROM_HERE,
base::BindOnce(
&update_client::StartInstallOnBlockingTaskRunner,
diff --git a/chromium/components/update_client/component_patcher_unittest.cc b/chromium/components/update_client/component_patcher_unittest.cc
index 73204621396..78b1cc8043a 100644
--- a/chromium/components/update_client/component_patcher_unittest.cc
+++ b/chromium/components/update_client/component_patcher_unittest.cc
@@ -12,8 +12,7 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/values.h"
-#include "components/services/patch/patch_service.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
+#include "components/services/patch/in_process_file_patcher.h"
#include "components/update_client/component_patcher_operation.h"
#include "components/update_client/component_patcher_unittest.h"
#include "components/update_client/patch/patch_impl.h"
@@ -21,7 +20,6 @@
#include "components/update_client/update_client_errors.h"
#include "courgette/courgette.h"
#include "courgette/third_party/bsdiff/bsdiff.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -66,8 +64,7 @@ base::FilePath test_file(const char* file) {
namespace update_client {
ComponentPatcherOperationTest::ComponentPatcherOperationTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO) {
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {
EXPECT_TRUE(unpack_dir_.CreateUniqueTempDir());
EXPECT_TRUE(input_dir_.CreateUniqueTempDir());
EXPECT_TRUE(installed_dir_.CreateUniqueTempDir());
@@ -96,7 +93,7 @@ TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) {
op->Run(command_args.get(), input_dir_.GetPath(), unpack_dir_.GetPath(),
nullptr,
base::BindOnce(&TestCallback::Set, base::Unretained(&callback)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(true, callback.called_);
EXPECT_EQ(UnpackerError::kNone, callback.error_);
@@ -124,7 +121,7 @@ TEST_F(ComponentPatcherOperationTest, CheckCopyOperation) {
op->Run(command_args.get(), input_dir_.GetPath(), unpack_dir_.GetPath(),
installer_.get(),
base::BindOnce(&TestCallback::Set, base::Unretained(&callback)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(true, callback.called_);
EXPECT_EQ(UnpackerError::kNone, callback.error_);
@@ -151,20 +148,17 @@ TEST_F(ComponentPatcherOperationTest, CheckCourgetteOperation) {
command_args->SetString("input", "binary_input.bin");
command_args->SetString("patch", "binary_courgette_patch.bin");
- // The operation needs a Patcher to access the PatchService.
- service_manager::TestConnectorFactory connector_factory;
- patch::PatchService patch_service(
- connector_factory.RegisterInstance(patch::mojom::kServiceName));
- scoped_refptr<Patcher> patcher = base::MakeRefCounted<PatchChromiumFactory>(
- connector_factory.CreateConnector())
- ->Create();
+ scoped_refptr<Patcher> patcher =
+ base::MakeRefCounted<PatchChromiumFactory>(
+ base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+ ->Create();
TestCallback callback;
scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("courgette", patcher);
op->Run(command_args.get(), input_dir_.GetPath(), unpack_dir_.GetPath(),
installer_.get(),
base::BindOnce(&TestCallback::Set, base::Unretained(&callback)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(true, callback.called_);
EXPECT_EQ(UnpackerError::kNone, callback.error_);
@@ -192,19 +186,17 @@ TEST_F(ComponentPatcherOperationTest, CheckBsdiffOperation) {
command_args->SetString("patch", "binary_bsdiff_patch.bin");
// The operation needs a Patcher to access the PatchService.
- service_manager::TestConnectorFactory connector_factory;
- patch::PatchService patch_service(
- connector_factory.RegisterInstance(patch::mojom::kServiceName));
- scoped_refptr<Patcher> patcher = base::MakeRefCounted<PatchChromiumFactory>(
- connector_factory.CreateConnector())
- ->Create();
+ scoped_refptr<Patcher> patcher =
+ base::MakeRefCounted<PatchChromiumFactory>(
+ base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+ ->Create();
TestCallback callback;
scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("bsdiff", patcher);
op->Run(command_args.get(), input_dir_.GetPath(), unpack_dir_.GetPath(),
installer_.get(),
base::BindOnce(&TestCallback::Set, base::Unretained(&callback)));
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
EXPECT_EQ(true, callback.called_);
EXPECT_EQ(UnpackerError::kNone, callback.error_);
diff --git a/chromium/components/update_client/component_patcher_unittest.h b/chromium/components/update_client/component_patcher_unittest.h
index bf5168c308a..cb50e87d80d 100644
--- a/chromium/components/update_client/component_patcher_unittest.h
+++ b/chromium/components/update_client/component_patcher_unittest.h
@@ -11,7 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "courgette/courgette.h"
#include "courgette/third_party/bsdiff/bsdiff.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,7 +29,7 @@ class ComponentPatcherOperationTest : public testing::Test {
~ComponentPatcherOperationTest() override;
protected:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir input_dir_;
base::ScopedTempDir installed_dir_;
base::ScopedTempDir unpack_dir_;
diff --git a/chromium/components/update_client/component_unpacker_unittest.cc b/chromium/components/update_client/component_unpacker_unittest.cc
index 617abcb37d4..67e12a2fb6c 100644
--- a/chromium/components/update_client/component_unpacker_unittest.cc
+++ b/chromium/components/update_client/component_unpacker_unittest.cc
@@ -17,7 +17,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/crx_file/crx_verifier.h"
#include "components/update_client/component_unpacker.h"
@@ -78,7 +78,7 @@ class ComponentUnpackerTest : public testing::Test {
protected:
void RunThreads();
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_ =
base::ThreadTaskRunnerHandle::Get();
base::RunLoop runloop_;
@@ -109,7 +109,7 @@ TEST_F(ComponentUnpackerTest, UnpackFullCrx) {
test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"), nullptr,
config->GetUnzipperFactory()->Create(),
config->GetPatcherFactory()->Create(),
- crx_file::VerifierFormat::CRX2_OR_CRX3);
+ crx_file::VerifierFormat::CRX3);
component_unpacker->Unpack(base::BindOnce(
&ComponentUnpackerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
@@ -127,11 +127,8 @@ TEST_F(ComponentUnpackerTest, UnpackFullCrx) {
base::GetFileSize(unpack_path.AppendASCII("component1.dll"), &file_size));
EXPECT_EQ(1024, file_size);
EXPECT_TRUE(
- base::GetFileSize(unpack_path.AppendASCII("flashtest.pem"), &file_size));
- EXPECT_EQ(911, file_size);
- EXPECT_TRUE(
base::GetFileSize(unpack_path.AppendASCII("manifest.json"), &file_size));
- EXPECT_EQ(144, file_size);
+ EXPECT_EQ(169, file_size);
EXPECT_TRUE(base::DeleteFile(unpack_path, true));
}
@@ -141,7 +138,7 @@ TEST_F(ComponentUnpackerTest, UnpackFileNotFound) {
base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(jebg_hash), std::end(jebg_hash)),
test_file("file-not-found.crx"), nullptr, nullptr, nullptr,
- crx_file::VerifierFormat::CRX2_OR_CRX3);
+ crx_file::VerifierFormat::CRX3);
component_unpacker->Unpack(base::BindOnce(
&ComponentUnpackerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
@@ -159,7 +156,7 @@ TEST_F(ComponentUnpackerTest, UnpackFileHashMismatch) {
base::MakeRefCounted<ComponentUnpacker>(
std::vector<uint8_t>(std::begin(abag_hash), std::end(abag_hash)),
test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"), nullptr, nullptr,
- nullptr, crx_file::VerifierFormat::CRX2_OR_CRX3);
+ nullptr, crx_file::VerifierFormat::CRX3);
component_unpacker->Unpack(base::BindOnce(
&ComponentUnpackerTest::UnpackComplete, base::Unretained(this)));
RunThreads();
diff --git a/chromium/components/update_client/crx_downloader.cc b/chromium/components/update_client/crx_downloader.cc
index a881c865291..cf45d4cf5c8 100644
--- a/chromium/components/update_client/crx_downloader.cc
+++ b/chromium/components/update_client/crx_downloader.cc
@@ -120,7 +120,7 @@ void CrxDownloader::OnDownloadComplete(
DCHECK(thread_checker_.CalledOnValidThread());
if (!result.error)
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, kTaskTraits,
base::BindOnce(&CrxDownloader::VerifyResponse, base::Unretained(this),
is_handled, result, download_metrics));
diff --git a/chromium/components/update_client/crx_downloader_unittest.cc b/chromium/components/update_client/crx_downloader_unittest.cc
index 03c90026294..08e6794ff4e 100644
--- a/chromium/components/update_client/crx_downloader_unittest.cc
+++ b/chromium/components/update_client/crx_downloader_unittest.cc
@@ -14,7 +14,7 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/update_client/net/network_chromium.h"
@@ -34,7 +34,7 @@ namespace {
const char kTestFileName[] = "jebgalgnebhfojomionfpkfelancnnkf.crx";
const char hash_jebg[] =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
base::FilePath MakeTestFilePath(const char* file) {
base::FilePath path;
@@ -91,7 +91,7 @@ class CrxDownloaderTest : public testing::Test {
static const int kExpectedContext = 0xaabb;
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<network::SharedURLLoaderFactory>
test_shared_url_loader_factory_;
base::OnceClosure quit_closure_;
@@ -109,8 +109,7 @@ CrxDownloaderTest::CrxDownloaderTest()
crx_context_(0),
num_download_complete_calls_(0),
num_progress_calls_(0),
- scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
test_shared_url_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {}
@@ -186,7 +185,7 @@ void CrxDownloaderTest::RunThreads() {
}
void CrxDownloaderTest::RunThreadsUntilIdle() {
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
@@ -342,8 +341,8 @@ TEST_F(CrxDownloaderTest, TwoUrls_FirstInvalid) {
EXPECT_EQ(-1, download_metrics[0].total_bytes);
EXPECT_EQ(expected_crx_url, download_metrics[1].url);
EXPECT_EQ(0, download_metrics[1].error);
- EXPECT_EQ(1843, download_metrics[1].downloaded_bytes);
- EXPECT_EQ(1843, download_metrics[1].total_bytes);
+ EXPECT_EQ(1015, download_metrics[1].downloaded_bytes);
+ EXPECT_EQ(1015, download_metrics[1].total_bytes);
}
// Tests that the download succeeds if the first url is correct and the
diff --git a/chromium/components/update_client/net/network_impl.cc b/chromium/components/update_client/net/network_impl.cc
index c78853e885f..1e241a62dcb 100644
--- a/chromium/components/update_client/net/network_impl.cc
+++ b/chromium/components/update_client/net/network_impl.cc
@@ -106,9 +106,8 @@ void NetworkFetcherImpl::PostRequest(
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
resource_request->method = "POST";
- resource_request->load_flags = net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DISABLE_CACHE;
+ resource_request->load_flags = net::LOAD_DISABLE_CACHE;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
for (const auto& header : post_additional_headers)
resource_request->headers.SetHeader(header.first, header.second);
simple_url_loader_ = network::SimpleURLLoader::Create(
@@ -149,9 +148,8 @@ void NetworkFetcherImpl::DownloadToFile(
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
resource_request->method = "GET";
- resource_request->load_flags = net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DISABLE_CACHE;
+ resource_request->load_flags = net::LOAD_DISABLE_CACHE;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
simple_url_loader_->SetRetryOptions(
diff --git a/chromium/components/update_client/patch/patch_impl.cc b/chromium/components/update_client/patch/patch_impl.cc
index dd92cbbdab5..599101fd33d 100644
--- a/chromium/components/update_client/patch/patch_impl.cc
+++ b/chromium/components/update_client/patch/patch_impl.cc
@@ -6,7 +6,6 @@
#include "components/services/patch/public/cpp/patch.h"
#include "components/update_client/component_patcher_operation.h"
-#include "services/service_manager/public/cpp/connector.h"
namespace update_client {
@@ -14,14 +13,14 @@ namespace {
class PatcherImpl : public Patcher {
public:
- explicit PatcherImpl(std::unique_ptr<service_manager::Connector> connector)
- : connector_(std::move(connector)) {}
+ explicit PatcherImpl(PatchChromiumFactory::Callback callback)
+ : callback_(std::move(callback)) {}
void PatchBsdiff(const base::FilePath& old_file,
const base::FilePath& patch_file,
const base::FilePath& destination,
PatchCompleteCallback callback) const override {
- patch::Patch(connector_.get(), update_client::kBsdiff, old_file, patch_file,
+ patch::Patch(callback_.Run(), update_client::kBsdiff, old_file, patch_file,
destination, std::move(callback));
}
@@ -29,7 +28,7 @@ class PatcherImpl : public Patcher {
const base::FilePath& patch_file,
const base::FilePath& destination,
PatchCompleteCallback callback) const override {
- patch::Patch(connector_.get(), update_client::kCourgette, old_file,
+ patch::Patch(callback_.Run(), update_client::kCourgette, old_file,
patch_file, destination, std::move(callback));
}
@@ -37,17 +36,16 @@ class PatcherImpl : public Patcher {
~PatcherImpl() override = default;
private:
- std::unique_ptr<service_manager::Connector> connector_;
+ const PatchChromiumFactory::Callback callback_;
};
} // namespace
-PatchChromiumFactory::PatchChromiumFactory(
- std::unique_ptr<service_manager::Connector> connector)
- : connector_(std::move(connector)) {}
+PatchChromiumFactory::PatchChromiumFactory(Callback callback)
+ : callback_(std::move(callback)) {}
scoped_refptr<Patcher> PatchChromiumFactory::Create() const {
- return base::MakeRefCounted<PatcherImpl>(connector_->Clone());
+ return base::MakeRefCounted<PatcherImpl>(callback_);
}
PatchChromiumFactory::~PatchChromiumFactory() = default;
diff --git a/chromium/components/update_client/patch/patch_impl.h b/chromium/components/update_client/patch/patch_impl.h
index d6abbc1254c..e76666d4917 100644
--- a/chromium/components/update_client/patch/patch_impl.h
+++ b/chromium/components/update_client/patch/patch_impl.h
@@ -7,20 +7,20 @@
#include <memory>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "components/services/patch/public/mojom/file_patcher.mojom.h"
#include "components/update_client/patcher.h"
-
-namespace service_manager {
-class Connector;
-}
+#include "mojo/public/cpp/bindings/pending_remote.h"
namespace update_client {
class PatchChromiumFactory : public PatcherFactory {
public:
- explicit PatchChromiumFactory(
- std::unique_ptr<service_manager::Connector> connector);
+ using Callback =
+ base::RepeatingCallback<mojo::PendingRemote<patch::mojom::FilePatcher>()>;
+ explicit PatchChromiumFactory(Callback callback);
scoped_refptr<Patcher> Create() const override;
@@ -28,7 +28,7 @@ class PatchChromiumFactory : public PatcherFactory {
~PatchChromiumFactory() override;
private:
- std::unique_ptr<service_manager::Connector> connector_;
+ const Callback callback_;
DISALLOW_COPY_AND_ASSIGN(PatchChromiumFactory);
};
diff --git a/chromium/components/update_client/ping_manager_unittest.cc b/chromium/components/update_client/ping_manager_unittest.cc
index 60d078cc982..0277b9b36fd 100644
--- a/chromium/components/update_client/ping_manager_unittest.cc
+++ b/chromium/components/update_client/ping_manager_unittest.cc
@@ -16,7 +16,7 @@
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
#include "components/update_client/component.h"
@@ -58,13 +58,12 @@ class PingManagerTest : public testing::Test,
std::string response_;
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::OnceClosure quit_closure_;
};
PingManagerTest::PingManagerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO) {
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {
config_ = base::MakeRefCounted<TestConfigurator>();
}
@@ -75,7 +74,7 @@ void PingManagerTest::SetUp() {
void PingManagerTest::TearDown() {
// Run the threads until they are idle to allow the clean up
// of the network interceptors on the IO thread.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
ping_manager_ = nullptr;
}
diff --git a/chromium/components/update_client/protocol_serializer_json.cc b/chromium/components/update_client/protocol_serializer_json.cc
index b94d2c05bdc..8e7aee8895c 100644
--- a/chromium/components/update_client/protocol_serializer_json.cc
+++ b/chromium/components/update_client/protocol_serializer_json.cc
@@ -10,8 +10,8 @@
#include "base/json/json_writer.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
-
#include "components/update_client/updater_state.h"
namespace update_client {
@@ -67,7 +67,7 @@ std::string ProtocolSerializerJSON::Serialize(
if (!request.os.service_pack.empty())
os_node->SetKey("sp", Value(request.os.service_pack));
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
if (request.updater) {
const auto& updater = *request.updater;
auto* updater_node =
diff --git a/chromium/components/update_client/protocol_serializer_json_unittest.cc b/chromium/components/update_client/protocol_serializer_json_unittest.cc
index 1f4ce4a9e94..4cf2666f5df 100644
--- a/chromium/components/update_client/protocol_serializer_json_unittest.cc
+++ b/chromium/components/update_client/protocol_serializer_json_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/update_client/protocol_serializer_json.h"
+
#include <memory>
#include <string>
#include <utility>
@@ -10,12 +12,12 @@
#include "base/optional.h"
#include "base/values.h"
#include "base/version.h"
+#include "build/branding_buildflags.h"
#include "components/prefs/testing_pref_service.h"
#include "components/update_client/activity_data_service.h"
#include "components/update_client/persisted_data.h"
#include "components/update_client/protocol_definition.h"
#include "components/update_client/protocol_serializer.h"
-#include "components/update_client/protocol_serializer_json.h"
#include "components/update_client/updater_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/re2/src/re2/re2.h"
@@ -114,11 +116,11 @@ TEST(SerializeRequestJSON, UpdaterStateAttributes) {
R"("os":{"arch":"[,-.\w]+","platform":"OS",("sp":"[\s\w]+",)?)"
R"("version":"[-.\w]+"},"prodchannel":"channel","prodversion":"1.0",)"
R"("protocol":"3.1","requestid":"{[-\w]{36}}","sessionid":"{[-\w]{36}}",)"
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
R"("updater":{"autoupdatecheckenabled":false,"ismachine":true,)"
R"("lastchecked":2,"laststarted":1,"name":"Omaha","updatepolicy":-1,)"
R"("version":"1\.2\.3\.4"},)"
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
R"("updaterchannel":"channel","updaterversion":"1.0"(,"wow64":true)?}})";
EXPECT_TRUE(RE2::FullMatch(request, regex)) << request;
}
diff --git a/chromium/components/update_client/request_sender_unittest.cc b/chromium/components/update_client/request_sender_unittest.cc
index e1e16d86043..cb0e09c4728 100644
--- a/chromium/components/update_client/request_sender_unittest.cc
+++ b/chromium/components/update_client/request_sender_unittest.cc
@@ -13,7 +13,7 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/update_client/net/url_loader_post_interceptor.h"
#include "components/update_client/test_configurator.h"
@@ -57,7 +57,7 @@ class RequestSenderTest : public testing::Test,
void Quit();
void RunThreads();
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
scoped_refptr<TestConfigurator> config_;
std::unique_ptr<RequestSender> request_sender_;
@@ -76,8 +76,7 @@ class RequestSenderTest : public testing::Test,
INSTANTIATE_TEST_SUITE_P(IsForeground, RequestSenderTest, ::testing::Bool());
RequestSenderTest::RequestSenderTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
RequestSenderTest::~RequestSenderTest() {}
@@ -101,7 +100,7 @@ void RequestSenderTest::TearDown() {
// Run the threads until they are idle to allow the clean up
// of the network interceptors on the IO thread.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
config_ = nullptr;
}
diff --git a/chromium/components/update_client/task_traits.h b/chromium/components/update_client/task_traits.h
index d14bbea8e00..1f675e7af86 100644
--- a/chromium/components/update_client/task_traits.h
+++ b/chromium/components/update_client/task_traits.h
@@ -10,16 +10,16 @@
namespace update_client {
constexpr base::TaskTraits kTaskTraits = {
- base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
constexpr base::TaskTraits kTaskTraitsBackgroundDownloader = {
- base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
// This task joins a process, hence .WithBaseSyncPrimitives().
constexpr base::TaskTraits kTaskTraitsRunCommand = {
- base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(),
base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
diff --git a/chromium/components/update_client/test_configurator.cc b/chromium/components/update_client/test_configurator.cc
index 8b8ffb95c10..9365726bb8c 100644
--- a/chromium/components/update_client/test_configurator.cc
+++ b/chromium/components/update_client/test_configurator.cc
@@ -9,8 +9,8 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
#include "components/prefs/pref_service.h"
-#include "components/services/patch/public/mojom/constants.mojom.h"
-#include "components/services/unzip/public/mojom/constants.mojom.h"
+#include "components/services/patch/in_process_file_patcher.h"
+#include "components/services/unzip/in_process_unzipper.h"
#include "components/update_client/activity_data_service.h"
#include "components/update_client/net/network_chromium.h"
#include "components/update_client/patch/patch_impl.h"
@@ -19,7 +19,6 @@
#include "components/update_client/unzip/unzip_impl.h"
#include "components/update_client/unzipper.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "url/gurl.h"
namespace update_client {
@@ -42,21 +41,15 @@ TestConfigurator::TestConfigurator()
enabled_cup_signing_(false),
enabled_component_updates_(true),
unzip_factory_(base::MakeRefCounted<update_client::UnzipChromiumFactory>(
- connector_factory_.CreateConnector())),
+ base::BindRepeating(&unzip::LaunchInProcessUnzipper))),
patch_factory_(base::MakeRefCounted<update_client::PatchChromiumFactory>(
- connector_factory_.CreateConnector())),
- unzip_service_(
- connector_factory_.RegisterInstance(unzip::mojom::kServiceName)),
- patch_service_(
- connector_factory_.RegisterInstance(patch::mojom::kServiceName)),
+ base::BindRepeating(&patch::LaunchInProcessFilePatcher))),
test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)),
network_fetcher_factory_(
base::MakeRefCounted<NetworkFetcherChromiumFactory>(
- test_shared_loader_factory_)) {
- connector_factory_.set_ignore_quit_requests(true);
-}
+ test_shared_loader_factory_)) {}
TestConfigurator::~TestConfigurator() {
}
diff --git a/chromium/components/update_client/test_configurator.h b/chromium/components/update_client/test_configurator.h
index 6de974c97e5..69353475ddb 100644
--- a/chromium/components/update_client/test_configurator.h
+++ b/chromium/components/update_client/test_configurator.h
@@ -15,11 +15,8 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "components/services/patch/patch_service.h"
-#include "components/services/unzip/unzip_service.h"
#include "components/update_client/configurator.h"
#include "services/network/test/test_url_loader_factory.h"
-#include "services/service_manager/public/cpp/test/test_connector_factory.h"
#include "url/gurl.h"
class PrefService;
@@ -134,13 +131,9 @@ class TestConfigurator : public Configurator {
GURL ping_url_;
std::string app_guid_;
- service_manager::TestConnectorFactory connector_factory_;
scoped_refptr<update_client::UnzipChromiumFactory> unzip_factory_;
scoped_refptr<update_client::PatchChromiumFactory> patch_factory_;
- unzip::UnzipService unzip_service_;
- patch::PatchService patch_service_;
-
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<NetworkFetcherFactory> network_fetcher_factory_;
diff --git a/chromium/components/update_client/test_installer.cc b/chromium/components/update_client/test_installer.cc
index c6e5b8aa466..0285af0f8ce 100644
--- a/chromium/components/update_client/test_installer.cc
+++ b/chromium/components/update_client/test_installer.cc
@@ -44,8 +44,8 @@ void TestInstaller::Install(const base::FilePath& unpack_path,
void TestInstaller::InstallComplete(Callback callback,
const Result& result) const {
- base::PostTaskWithTraits(FROM_HERE, {base::MayBlock()},
- base::BindOnce(std::move(callback), result));
+ base::PostTask(FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::BindOnce(std::move(callback), result));
}
bool TestInstaller::GetInstalledFile(const std::string& file,
diff --git a/chromium/components/update_client/unzip/unzip_impl.cc b/chromium/components/update_client/unzip/unzip_impl.cc
index 3deea178427..1fa905818c0 100644
--- a/chromium/components/update_client/unzip/unzip_impl.cc
+++ b/chromium/components/update_client/unzip/unzip_impl.cc
@@ -5,7 +5,6 @@
#include "components/update_client/unzip/unzip_impl.h"
#include "components/services/unzip/public/cpp/unzip.h"
-#include "services/service_manager/public/cpp/connector.h"
namespace update_client {
@@ -13,28 +12,26 @@ namespace {
class UnzipperImpl : public Unzipper {
public:
- explicit UnzipperImpl(std::unique_ptr<service_manager::Connector> connector)
- : connector_(std::move(connector)) {}
+ explicit UnzipperImpl(UnzipChromiumFactory::Callback callback)
+ : callback_(std::move(callback)) {}
void Unzip(const base::FilePath& zip_file,
const base::FilePath& destination,
UnzipCompleteCallback callback) override {
- unzip::Unzip(connector_->Clone(), zip_file, destination,
- std::move(callback));
+ unzip::Unzip(callback_.Run(), zip_file, destination, std::move(callback));
}
private:
- std::unique_ptr<service_manager::Connector> connector_;
+ const UnzipChromiumFactory::Callback callback_;
};
} // namespace
-UnzipChromiumFactory::UnzipChromiumFactory(
- std::unique_ptr<service_manager::Connector> connector)
- : connector_(std::move(connector)) {}
+UnzipChromiumFactory::UnzipChromiumFactory(Callback callback)
+ : callback_(std::move(callback)) {}
std::unique_ptr<Unzipper> UnzipChromiumFactory::Create() const {
- return std::make_unique<UnzipperImpl>(connector_->Clone());
+ return std::make_unique<UnzipperImpl>(callback_);
}
UnzipChromiumFactory::~UnzipChromiumFactory() = default;
diff --git a/chromium/components/update_client/unzip/unzip_impl.h b/chromium/components/update_client/unzip/unzip_impl.h
index 1eb4cdee63b..bbf9156e664 100644
--- a/chromium/components/update_client/unzip/unzip_impl.h
+++ b/chromium/components/update_client/unzip/unzip_impl.h
@@ -7,20 +7,20 @@
#include <memory>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "components/services/unzip/public/mojom/unzipper.mojom.h"
#include "components/update_client/unzipper.h"
-
-namespace service_manager {
-class Connector;
-}
+#include "mojo/public/cpp/bindings/pending_remote.h"
namespace update_client {
class UnzipChromiumFactory : public UnzipperFactory {
public:
- explicit UnzipChromiumFactory(
- std::unique_ptr<service_manager::Connector> connector);
+ using Callback =
+ base::RepeatingCallback<mojo::PendingRemote<unzip::mojom::Unzipper>()>;
+ explicit UnzipChromiumFactory(Callback callback);
std::unique_ptr<Unzipper> Create() const override;
@@ -28,7 +28,7 @@ class UnzipChromiumFactory : public UnzipperFactory {
~UnzipChromiumFactory() override;
private:
- std::unique_ptr<service_manager::Connector> connector_;
+ const Callback callback_;
DISALLOW_COPY_AND_ASSIGN(UnzipChromiumFactory);
};
diff --git a/chromium/components/update_client/update_checker.cc b/chromium/components/update_client/update_checker.cc
index b9d83ba4bbd..cfc25787280 100644
--- a/chromium/components/update_client/update_checker.cc
+++ b/chromium/components/update_client/update_checker.cc
@@ -130,7 +130,7 @@ void UpdateCheckerImpl::CheckForUpdates(
ids_checked_ = ids_checked;
update_check_callback_ = std::move(update_check_callback);
- base::PostTaskWithTraitsAndReply(
+ base::PostTaskAndReply(
FROM_HERE, kTaskTraits,
base::BindOnce(&UpdateCheckerImpl::ReadUpdaterStateAttributes,
base::Unretained(this)),
diff --git a/chromium/components/update_client/update_checker_unittest.cc b/chromium/components/update_client/update_checker_unittest.cc
index b7f2540f551..24fc086faff 100644
--- a/chromium/components/update_client/update_checker_unittest.cc
+++ b/chromium/components/update_client/update_checker_unittest.cc
@@ -22,9 +22,10 @@
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/version.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/prefs/testing_pref_service.h"
#include "components/update_client/activity_data_service.h"
@@ -151,7 +152,7 @@ class UpdateCheckerTest : public testing::TestWithParam<bool> {
private:
scoped_refptr<UpdateContext> MakeMockUpdateContext() const;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::OnceClosure quit_closure_;
DISALLOW_COPY_AND_ASSIGN(UpdateCheckerTest);
@@ -161,8 +162,7 @@ class UpdateCheckerTest : public testing::TestWithParam<bool> {
INSTANTIATE_TEST_SUITE_P(Parameterized, UpdateCheckerTest, testing::Bool());
UpdateCheckerTest::UpdateCheckerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
UpdateCheckerTest::~UpdateCheckerTest() {
}
@@ -199,7 +199,7 @@ void UpdateCheckerTest::TearDown() {
// The PostInterceptor requires the message loop to run to destruct correctly.
// TODO(sorin): This is fragile and should be fixed.
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
void UpdateCheckerTest::RunThreads() {
@@ -325,14 +325,14 @@ TEST_P(UpdateCheckerTest, UpdateCheckSuccess) {
#if defined(OS_WIN)
EXPECT_TRUE(request->FindKey("domainjoined"));
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
const auto* updater = request->FindKey("updater");
EXPECT_TRUE(updater);
EXPECT_EQ("Omaha", updater->FindKey("name")->GetString());
EXPECT_TRUE(updater->FindKey("autoupdatecheckenabled")->is_bool());
EXPECT_TRUE(updater->FindKey("ismachine")->is_bool());
EXPECT_TRUE(updater->FindKey("updatepolicy")->is_int());
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
#endif // OS_WIN
// Sanity check the arguments of the callback after parsing.
diff --git a/chromium/components/update_client/update_client_unittest.cc b/chromium/components/update_client/update_client_unittest.cc
index d580470e1ed..c986dd6a740 100644
--- a/chromium/components/update_client/update_client_unittest.cc
+++ b/chromium/components/update_client/update_client_unittest.cc
@@ -19,7 +19,7 @@
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/test/scoped_path_override.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "base/version.h"
@@ -177,7 +177,7 @@ class UpdateClientTest : public testing::Test {
private:
static constexpr int kNumWorkerThreads_ = 2;
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::RunLoop runloop_;
scoped_refptr<update_client::TestConfigurator> config_ =
@@ -201,7 +201,7 @@ UpdateClientTest::~UpdateClientTest() {
void UpdateClientTest::RunThreads() {
runloop_.Run();
- scoped_task_environment_.RunUntilIdle();
+ task_environment_.RunUntilIdle();
}
base::FilePath UpdateClientTest::TestFilePath(const char* file) {
@@ -226,7 +226,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
std::vector<base::Optional<CrxComponent>> component = {crx};
return component;
}
@@ -338,14 +338,14 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1.version = base::Version("0.9");
crx1.installer = base::MakeRefCounted<TestInstaller>();
- crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
CrxComponent crx2;
crx2.name = "test_abag";
crx2.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
crx2.version = base::Version("2.2");
crx2.installer = base::MakeRefCounted<TestInstaller>();
- crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx1, crx2};
}
@@ -387,8 +387,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -411,7 +411,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -555,14 +555,14 @@ TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1.version = base::Version("0.9");
crx1.installer = base::MakeRefCounted<TestInstaller>();
- crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
CrxComponent crx2;
crx2.name = "test_abag";
crx2.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
crx2.version = base::Version("2.2");
crx2.installer = base::MakeRefCounted<TestInstaller>();
- crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx1, crx2};
}
@@ -604,8 +604,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -625,7 +625,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf";
@@ -771,7 +771,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx, base::nullopt};
}
};
@@ -812,8 +812,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -833,7 +833,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = id;
@@ -1059,14 +1059,14 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1.version = base::Version("0.9");
crx1.installer = base::MakeRefCounted<TestInstaller>();
- crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
CrxComponent crx2;
crx2.name = "test_ihfo";
crx2.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx2.version = base::Version("0.8");
crx2.installer = base::MakeRefCounted<TestInstaller>();
- crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx1, crx2};
}
@@ -1108,8 +1108,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -1122,8 +1122,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
- hash_sha256='813c59747e139a608b3b5fc49633affc6db574373f
- 309f156ea6d27229c0b3f9'/>
+ hash_sha256='8f5aa190311237cae00675af87ff457f278cd1a05
+ 895470ac5d46647d4a3c2ea'/>
</packages>
</manifest>
</updatecheck>
@@ -1144,7 +1144,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = id;
@@ -1164,7 +1164,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
ProtocolParser::Result::Manifest::Package package;
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
package.hash_sha256 =
- "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
+ "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
ProtocolParser::Result result;
result.extension_id = id;
@@ -1334,7 +1334,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
crx.name = "test_ihfo";
crx.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx.installer = installer;
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
if (num_calls == 1) {
crx.version = base::Version("0.8");
} else if (num_calls == 2) {
@@ -1405,7 +1405,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
ProtocolParser::Result::Manifest::Package package;
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
package.hash_sha256 =
- "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
+ "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
ProtocolParser::Result result;
result.extension_id = id;
@@ -1430,11 +1430,11 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
<packages>
<package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
- hash_sha256='1af337fbd19c72db0f870753bcd7711c3ae9dcaa
- 0ecde26c262bad942b112990'
+ hash_sha256='c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea6361
+ 8086a7db1c5be5300e1d4d6b6'
fp='22'
- hashdiff_sha256='73c6e2d4f783fc4ca5481e89e0b8bfce7aec
- 8ead3686290c94792658ec06f2f2'/>
+ hashdiff_sha256='0fd48a5dd87006a709756cfc47198cbc4c4
+ 928f33ac4277d79573c15164a33eb'/>
</packages>
</manifest>
</updatecheck>
@@ -1449,9 +1449,9 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
package.hash_sha256 =
- "1af337fbd19c72db0f870753bcd7711c3ae9dcaa0ecde26c262bad942b112990";
+ "c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea63618086a7db1c5be5300e1d4d6b6";
package.hashdiff_sha256 =
- "73c6e2d4f783fc4ca5481e89e0b8bfce7aec8ead3686290c94792658ec06f2f2";
+ "0fd48a5dd87006a709756cfc47198cbc4c4928f33ac4277d79573c15164a33eb";
package.fingerprint = "22";
ProtocolParser::Result result;
@@ -1633,8 +1633,8 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
unpack_path_ = unpack_path;
EXPECT_TRUE(base::DirectoryExists(unpack_path_));
- base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock()},
+ base::PostTask(
+ FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(std::move(callback),
CrxInstaller::Result(InstallError::GENERIC_ERROR)));
}
@@ -1670,7 +1670,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = installer;
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx};
}
@@ -1712,8 +1712,8 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -1729,7 +1729,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = id;
@@ -1855,7 +1855,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
crx.name = "test_ihfo";
crx.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx.installer = installer;
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
if (num_calls == 1) {
crx.version = base::Version("0.8");
} else if (num_calls == 2) {
@@ -1927,7 +1927,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
ProtocolParser::Result::Manifest::Package package;
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
package.hash_sha256 =
- "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
+ "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
package.fingerprint = "1";
ProtocolParser::Result result;
@@ -1953,11 +1953,11 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
<packages>
<package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx'
namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx'
- hash_sha256='1af337fbd19c72db0f870753bcd7711c3ae9dcaa
- 0ecde26c262bad942b112990'
+ hash_sha256='c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea6361
+ 8086a7db1c5be5300e1d4d6b6'
fp='22'
- hashdiff_sha256='73c6e2d4f783fc4ca5481e89e0b8bfce7aec
- 8ead3686290c94792658ec06f2f2'/>
+ hashdiff_sha256='0fd48a5dd87006a709756cfc47198cbc4c4
+ 928f33ac4277d79573c15164a33eb'/>
</packages>
</manifest>
</updatecheck>
@@ -1972,9 +1972,9 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx";
package.hash_sha256 =
- "1af337fbd19c72db0f870753bcd7711c3ae9dcaa0ecde26c262bad942b112990";
+ "c87d8742c3ff3d7a0cb6f3c91aa2fcf3dea63618086a7db1c5be5300e1d4d6b6";
package.hashdiff_sha256 =
- "73c6e2d4f783fc4ca5481e89e0b8bfce7aec8ead3686290c94792658ec06f2f2";
+ "0fd48a5dd87006a709756cfc47198cbc4c4928f33ac4277d79573c15164a33eb";
package.fingerprint = "22";
ProtocolParser::Result result;
@@ -2159,7 +2159,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx};
}
};
@@ -2280,7 +2280,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.0");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx};
}
};
@@ -2321,8 +2321,8 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -2340,7 +2340,7 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = id;
@@ -2563,7 +2563,7 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.0");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx};
}
};
@@ -2831,7 +2831,7 @@ TEST_F(UpdateClientTest, RetryAfter) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx};
}
};
@@ -3025,7 +3025,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
crx1.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx1.version = base::Version("0.9");
crx1.installer = base::MakeRefCounted<TestInstaller>();
- crx1.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx1.crx_format_requirement = crx_file::VerifierFormat::CRX3;
crx1.supports_group_policy_enable_component_updates = true;
CrxComponent crx2;
@@ -3033,7 +3033,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
crx2.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx2.version = base::Version("0.8");
crx2.installer = base::MakeRefCounted<TestInstaller>();
- crx2.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx2.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx1, crx2};
}
@@ -3075,8 +3075,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='jebgalgnebhfojomionfpkfelancnnkf.crx'
- hash_sha256='6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd
- 7c9b12cb7cc067667bde87'/>
+ hash_sha256='7ab32f071cd9b5ef8e0d7913be161f532d98b3e9f
+ a284a7cd8059c3409ce0498'/>
</packages>
</manifest>
</updatecheck>
@@ -3089,8 +3089,8 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
<manifest version='1.0' prodversionmin='11.0.1.0'>
<packages>
<package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'
- hash_sha256='813c59747e139a608b3b5fc49633affc6db574373f
- 309f156ea6d27229c0b3f9'/>
+ hash_sha256='8f5aa190311237cae00675af87ff457f278cd1a05
+ 895470ac5d46647d4a3c2ea'/>
</packages>
</manifest>
</updatecheck>
@@ -3115,7 +3115,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
ProtocolParser::Result::Manifest::Package package;
package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
package.hash_sha256 =
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87";
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498";
ProtocolParser::Result result;
result.extension_id = id;
@@ -3135,7 +3135,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
ProtocolParser::Result::Manifest::Package package;
package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
package.hash_sha256 =
- "813c59747e139a608b3b5fc49633affc6db574373f309f156ea6d27229c0b3f9";
+ "8f5aa190311237cae00675af87ff457f278cd1a05895470ac5d46647d4a3c2ea";
ProtocolParser::Result result;
result.extension_id = id;
@@ -3281,7 +3281,7 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return {crx};
}
};
@@ -3393,7 +3393,7 @@ TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
crx.pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
component.push_back(crx);
}
{
@@ -3402,7 +3402,7 @@ TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
crx.pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
crx.version = base::Version("0.1");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
component.push_back(crx);
}
{
@@ -3411,7 +3411,7 @@ TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
crx.pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
crx.version = base::Version("0.2");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
component.push_back(crx);
}
{
@@ -3420,7 +3420,7 @@ TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
crx.pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
crx.version = base::Version("0.3");
crx.installer = base::MakeRefCounted<TestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
component.push_back(crx);
}
return component;
@@ -3761,7 +3761,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
crx.pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
crx.version = base::Version("0.0");
crx.installer = base::MakeRefCounted<VersionedTestInstaller>();
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return std::vector<base::Optional<CrxComponent>>{crx};
}),
base::BindOnce(
@@ -3869,8 +3869,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
std::vector<uint8_t>(std::begin(gjpm_hash), std::end(gjpm_hash)),
TestFilePath("runaction_test_win.crx3"), nullptr,
config->GetUnzipperFactory()->Create(),
- config->GetPatcherFactory()->Create(),
- crx_file::VerifierFormat::CRX2_OR_CRX3);
+ config->GetPatcherFactory()->Create(), crx_file::VerifierFormat::CRX3);
component_unpacker->Unpack(base::BindOnce(
[](base::FilePath* unpack_path, base::OnceClosure quit_closure,
@@ -3913,7 +3912,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
crx.version = base::Version("1.0");
crx.installer =
base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path);
- crx.crx_format_requirement = crx_file::VerifierFormat::CRX2_OR_CRX3;
+ crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
return std::vector<base::Optional<CrxComponent>>{crx};
},
unpack_path),
diff --git a/chromium/components/update_client/update_query_params.cc b/chromium/components/update_client/update_query_params.cc
index 119e71a2cba..56aea40c92a 100644
--- a/chromium/components/update_client/update_query_params.cc
+++ b/chromium/components/update_client/update_query_params.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/update_client/update_query_params_delegate.h"
#include "components/version_info/version_info.h"
@@ -63,11 +64,11 @@ const char kArch[] =
const char kChrome[] = "chrome";
-#if defined(GOOGLE_CHROME_BUILD)
-const char kChromeCrx[] = "chromecrx";
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+const char kCrx[] = "chromecrx";
#else
-const char kChromiumCrx[] = "chromiumcrx";
-#endif // defined(GOOGLE_CHROME_BUILD)
+const char kCrx[] = "chromiumcrx";
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
UpdateQueryParamsDelegate* g_delegate = nullptr;
@@ -76,8 +77,8 @@ UpdateQueryParamsDelegate* g_delegate = nullptr;
// static
std::string UpdateQueryParams::Get(ProdId prod) {
return base::StringPrintf(
- "os=%s&arch=%s&os_arch=%s&nacl_arch=%s&prod=%s%s&acceptformat=crx2,crx3",
- kOs, kArch, base::SysInfo().OperatingSystemArchitecture().c_str(),
+ "os=%s&arch=%s&os_arch=%s&nacl_arch=%s&prod=%s%s&acceptformat=crx3", kOs,
+ kArch, base::SysInfo().OperatingSystemArchitecture().c_str(),
GetNaclArch(), GetProdIdString(prod),
g_delegate ? g_delegate->GetExtraParams().c_str() : "");
}
@@ -89,11 +90,7 @@ const char* UpdateQueryParams::GetProdIdString(UpdateQueryParams::ProdId prod) {
return kChrome;
break;
case UpdateQueryParams::CRX:
-#if defined(GOOGLE_CHROME_BUILD)
- return kChromeCrx;
-#else
- return kChromiumCrx;
-#endif
+ return kCrx;
break;
}
return kUnknown;
diff --git a/chromium/components/update_client/updater_state.cc b/chromium/components/update_client/updater_state.cc
index 7178b540665..5d05c8663aa 100644
--- a/chromium/components/update_client/updater_state.cc
+++ b/chromium/components/update_client/updater_state.cc
@@ -11,6 +11,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
namespace update_client {
@@ -40,14 +41,14 @@ std::unique_ptr<UpdaterState::Attributes> UpdaterState::GetState(
void UpdaterState::ReadState() {
is_enterprise_managed_ = base::IsMachineExternallyManaged();
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
updater_name_ = GetUpdaterName();
updater_version_ = GetUpdaterVersion(is_machine_);
last_autoupdate_started_ = GetUpdaterLastStartedAU(is_machine_);
last_checked_ = GetUpdaterLastChecked(is_machine_);
is_autoupdate_check_enabled_ = IsAutoupdateCheckEnabled();
update_policy_ = GetUpdatePolicy();
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}
#endif // OS_WIN or Mac
diff --git a/chromium/components/update_client/updater_state_unittest.cc b/chromium/components/update_client/updater_state_unittest.cc
index 20fa0f711ec..e916adfe352 100644
--- a/chromium/components/update_client/updater_state_unittest.cc
+++ b/chromium/components/update_client/updater_state_unittest.cc
@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/update_client/updater_state.h"
+
#include "base/macros.h"
#include "base/time/time.h"
#include "base/version.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
-#include "components/update_client/updater_state.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace update_client {
@@ -42,7 +44,7 @@ TEST_F(UpdaterStateTest, Serialize) {
EXPECT_STREQ("1", attributes.at("autoupdatecheckenabled").c_str());
EXPECT_STREQ("1", attributes.at("updatepolicy").c_str());
-#if defined(GOOGLE_CHROME_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#if defined(OS_WIN)
// The value of "ismachine".
EXPECT_STREQ("0", UpdaterState::GetState(false)->at("ismachine").c_str());
@@ -56,7 +58,7 @@ TEST_F(UpdaterStateTest, Serialize) {
EXPECT_EQ(0UL, UpdaterState::GetState(true)->count("ismachine"));
EXPECT_STREQ("Keystone", UpdaterState::GetState(false)->at("name").c_str());
#endif // OS_WIN
-#endif // GOOGLE_CHROME_BUILD
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Tests some of the remaining values.
updater_state = UpdaterState(false);
diff --git a/chromium/components/update_client/url_fetcher_downloader.cc b/chromium/components/update_client/url_fetcher_downloader.cc
index 7a550febd1c..eaf78ad04be 100644
--- a/chromium/components/update_client/url_fetcher_downloader.cc
+++ b/chromium/components/update_client/url_fetcher_downloader.cc
@@ -21,7 +21,7 @@
namespace {
constexpr base::TaskTraits kTaskTraits = {
- base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
} // namespace
@@ -40,7 +40,7 @@ UrlFetcherDownloader::~UrlFetcherDownloader() {
void UrlFetcherDownloader::DoStartDownload(const GURL& url) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- base::PostTaskWithTraitsAndReply(
+ base::PostTaskAndReply(
FROM_HERE, kTaskTraits,
base::BindOnce(&UrlFetcherDownloader::CreateDownloadDir,
base::Unretained(this)),
@@ -136,7 +136,7 @@ void UrlFetcherDownloader::OnNetworkFetcherComplete(base::FilePath file_path,
// Delete the download directory in the error cases.
if (error && !download_dir_.empty())
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, kTaskTraits,
base::BindOnce(IgnoreResult(&base::DeleteFile), download_dir_, true));
diff --git a/chromium/components/update_client/utils_unittest.cc b/chromium/components/update_client/utils_unittest.cc
index 71a8b886827..14882d5ba31 100644
--- a/chromium/components/update_client/utils_unittest.cc
+++ b/chromium/components/update_client/utils_unittest.cc
@@ -31,7 +31,7 @@ TEST(UpdateClientUtils, VerifyFileHash256) {
EXPECT_TRUE(VerifyFileHash256(
MakeTestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"),
std::string(
- "6fc4b93fd11134de1300c2c0bb88c12b644a4ec0fd7c9b12cb7cc067667bde87")));
+ "7ab32f071cd9b5ef8e0d7913be161f532d98b3e9fa284a7cd8059c3409ce0498")));
EXPECT_FALSE(VerifyFileHash256(
MakeTestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"),
diff --git a/chromium/components/upload_list/text_log_upload_list_unittest.cc b/chromium/components/upload_list/text_log_upload_list_unittest.cc
index ec03b3b8185..b92f464e6d2 100644
--- a/chromium/components/upload_list/text_log_upload_list_unittest.cc
+++ b/chromium/components/upload_list/text_log_upload_list_unittest.cc
@@ -13,7 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -44,7 +44,7 @@ class TextLogUploadListTest : public testing::Test {
}
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
DISALLOW_COPY_AND_ASSIGN(TextLogUploadListTest);
diff --git a/chromium/components/upload_list/upload_list.cc b/chromium/components/upload_list/upload_list.cc
index 18e49bcfd03..78e67359d35 100644
--- a/chromium/components/upload_list/upload_list.cc
+++ b/chromium/components/upload_list/upload_list.cc
@@ -17,7 +17,7 @@ namespace {
// USER_VISIBLE because loading uploads blocks chrome://crashes,
// chrome://webrtc-logs and the feedback UI. See https://crbug.com/972526.
constexpr base::TaskTraits kLoadingTaskTraits = {
- base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+ base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
} // namespace
@@ -63,7 +63,7 @@ UploadList::~UploadList() = default;
void UploadList::Load(base::OnceClosure callback) {
DCHECK(sequence_checker_.CalledOnValidSequence());
load_callback_ = std::move(callback);
- base::PostTaskWithTraitsAndReplyWithResult(
+ base::PostTaskAndReplyWithResult(
FROM_HERE, kLoadingTaskTraits,
base::Bind(&UploadList::LoadUploadList, this),
base::Bind(&UploadList::OnLoadComplete, this));
@@ -74,7 +74,7 @@ void UploadList::Clear(const base::Time& begin,
base::OnceClosure callback) {
DCHECK(sequence_checker_.CalledOnValidSequence());
clear_callback_ = std::move(callback);
- base::PostTaskWithTraitsAndReply(
+ base::PostTaskAndReply(
FROM_HERE, kLoadingTaskTraits,
base::BindOnce(&UploadList::ClearUploadList, this, begin, end),
base::BindOnce(&UploadList::OnClearComplete, this));
@@ -86,7 +86,7 @@ void UploadList::CancelLoadCallback() {
void UploadList::RequestSingleUploadAsync(const std::string& local_id) {
DCHECK(sequence_checker_.CalledOnValidSequence());
- base::PostTaskWithTraits(
+ base::PostTask(
FROM_HERE, kLoadingTaskTraits,
base::BindOnce(&UploadList::RequestSingleUpload, this, local_id));
}
diff --git a/chromium/components/url_formatter/BUILD.gn b/chromium/components/url_formatter/BUILD.gn
index 485aab8a0f5..1fe9bb96dd5 100644
--- a/chromium/components/url_formatter/BUILD.gn
+++ b/chromium/components/url_formatter/BUILD.gn
@@ -31,8 +31,8 @@ jumbo_static_library("url_formatter") {
deps = [
"//base",
"//base:i18n",
- "//components/url_formatter/top_domains:common",
- "//components/url_formatter/top_domains:generate_top_domains_trie",
+ "//components/url_formatter/spoof_checks/top_domains:common",
+ "//components/url_formatter/spoof_checks/top_domains:generate_top_domains_trie",
"//net",
"//net:preload_decoder",
"//third_party/icu",
@@ -58,7 +58,7 @@ jumbo_source_set("unit_tests") {
":url_formatter",
"//base",
"//base/test:test_support",
- "//components/url_formatter/top_domains:generate_top_domains_test_trie",
+ "//components/url_formatter/spoof_checks/top_domains:generate_top_domains_test_trie",
"//net",
"//net:preload_decoder",
"//testing/gtest",
diff --git a/chromium/components/url_formatter/OWNERS b/chromium/components/url_formatter/OWNERS
index 6e9e1614ab0..a7cab0abe00 100644
--- a/chromium/components/url_formatter/OWNERS
+++ b/chromium/components/url_formatter/OWNERS
@@ -1,5 +1,6 @@
pkasting@chromium.org
tommycli@chromium.org
+meacer@chromium.org
# Changes to FormatUrlForSecurityDisplay and FormatOriginForSecurityDisplay
# require a security review to avoid introducing security bugs.
diff --git a/chromium/components/url_formatter/elide_url_unittest.cc b/chromium/components/url_formatter/elide_url_unittest.cc
index 90b919f47fc..2aba82234a3 100644
--- a/chromium/components/url_formatter/elide_url_unittest.cc
+++ b/chromium/components/url_formatter/elide_url_unittest.cc
@@ -9,7 +9,7 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/url_formatter/url_formatter.h"
#include "net/base/escape.h"
@@ -266,8 +266,8 @@ TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack) {
TEST(TextEliderTest, TestElisionSpecialCases) {
#if defined(OS_WIN)
// Needed to bypass DCHECK in GetFallbackFont.
- base::test::ScopedTaskEnvironment task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::UI);
+ base::test::SingleThreadTaskEnvironment task_environment(
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI);
#endif
const std::string kEllipsisStr(gfx::kEllipsis);
const std::vector<Testcase> testcases = {
diff --git a/chromium/components/url_formatter/spoof_checks/OWNERS b/chromium/components/url_formatter/spoof_checks/OWNERS
deleted file mode 100644
index 6771584f910..00000000000
--- a/chromium/components/url_formatter/spoof_checks/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-meacer@chromium.org
diff --git a/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.cc b/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.cc
index aea26994ead..63941790f54 100644
--- a/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.cc
+++ b/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.cc
@@ -35,35 +35,38 @@ class TopDomainPreloadDecoder : public net::extras::PreloadDecoder {
if (!reader->Next(&is_same_skeleton))
return false;
- std::string top_domain;
+ TopDomainEntry top_domain;
+ if (!reader->Next(&top_domain.is_top_500))
+ return false;
+
if (is_same_skeleton) {
- top_domain = search;
+ top_domain.domain = search;
} else {
bool has_com_suffix = false;
if (!reader->Next(&has_com_suffix))
return false;
- for (char c;; top_domain += c) {
+ for (char c;; top_domain.domain += c) {
huffman_decoder().Decode(reader, &c);
if (c == net::extras::PreloadDecoder::kEndOfTable)
break;
}
if (has_com_suffix)
- top_domain += ".com";
+ top_domain.domain += ".com";
}
if (current_search_offset == 0) {
*out_found = true;
- DCHECK(!top_domain.empty());
+ DCHECK(!top_domain.domain.empty());
result_ = top_domain;
}
return true;
}
- std::string matching_top_domain() const { return result_; }
+ TopDomainEntry matching_top_domain() const { return result_; }
private:
- std::string result_;
+ TopDomainEntry result_;
};
void OnThreadTermination(void* regex_matcher) {
@@ -76,10 +79,10 @@ base::ThreadLocalStorage::Slot& DangerousPatternTLS() {
return *dangerous_pattern_tls;
}
-#include "components/url_formatter/top_domains/alexa_domains-trie-inc.cc"
+#include "components/url_formatter/spoof_checks/top_domains/domains-trie-inc.cc"
-// All the domains in the above file have 3 or fewer labels.
-const size_t kNumberOfLabelsToCheck = 3;
+// All the domains in the above file have 4 or fewer labels.
+const size_t kNumberOfLabelsToCheck = 4;
IDNSpoofChecker::HuffmanTrieParams g_trie_params{
kTopDomainsHuffmanTree, sizeof(kTopDomainsHuffmanTree), kTopDomainsTrie,
@@ -185,11 +188,12 @@ IDNSpoofChecker::IDNSpoofChecker() {
// U+04C8 (ӈ), U+04CA (ӊ), U+050B (ԋ), U+0527 (ԧ), U+0529 (ԩ)} => h
// - {U+0138 (ĸ), U+03BA (κ), U+043A (к), U+049B (қ), U+049D (ҝ),
// U+049F (ҟ), U+04A1(ҡ), U+04C4 (ӄ), U+051F (ԟ)} => k
- // - {U+014B (ŋ), U+043F (п), U+0525 (ԥ), U+0E01 (ก)} => n
+ // - {U+014B (ŋ), U+043F (п), U+0525 (ԥ), U+0E01 (ก), U+05D7 (ח)} => n
// - U+0153 (œ) => "ce"
// TODO: see https://crbug.com/843352 for further work on
// U+0525 and U+0153.
- // - {U+0167 (ŧ), U+0442 (т), U+04AD (ҭ), U+050F (ԏ)} => t
+ // - {U+0167 (ŧ), U+0442 (т), U+04AD (ҭ), U+050F (ԏ), U+4E03 (七),
+ // U+4E05 (丅), U+4E06 (丆)} => t
// - {U+0185 (ƅ), U+044C (ь), U+048D (ҍ), U+0432 (в)} => b
// - {U+03C9 (ω), U+0448 (ш), U+0449 (щ), U+0E1E (พ),
// U+0E1F (ฟ), U+0E9E (ພ), U+0E9F (ຟ)} => w
@@ -198,8 +202,8 @@ IDNSpoofChecker::IDNSpoofChecker() {
// - U+0491 (ґ) => r
// - {U+0493 (ғ), U+04FB (ӻ)} => f
// - {U+04AB (ҫ), U+1004 (င)} => c
- // - U+04B1 (ұ) => y
- // - {U+03C7 (χ), U+04B3 (ҳ), U+04FD (ӽ), U+04FF (ӿ)} => x
+ // - {U+04B1 (ұ), U+4E2B (丫)} => y
+ // - {U+03C7 (χ), U+04B3 (ҳ), U+04FD (ӽ), U+04FF (ӿ), U+4E42 (乂)} => x
// - {U+0503 (ԃ), U+10EB (ძ)} => d
// - {U+050D (ԍ), U+100c (ဌ)} => g
// - {U+0D1F (ട), U+0E23 (ร), U+0EA3 (ຣ), U+0EAE (ຮ)} => s
@@ -207,32 +211,40 @@ IDNSpoofChecker::IDNSpoofChecker() {
// - {U+0966 (०), U+09E6 (০), U+0A66 (੦), U+0AE6 (૦), U+0B30 (ଠ),
// U+0B66 (୦), U+0CE6 (೦)} => o,
// - {U+09ED (৭), U+0A67 (੧), U+0AE7 (૧)} => q,
- // - {U+0E1A (บ), U+0E9A (ບ)} => u
+ // - {U+0E1A (บ), U+0E9A (ບ)} => u,
+ // - {U+03B8 (θ)} => 0,
// - {U+0968 (२), U+09E8 (২), U+0A68 (੨), U+0A68 (੨), U+0AE8 (૨),
- // U+0ce9 (೩), U+0ced (೭)} => 2,
+ // U+0ce9 (೩), U+0ced (೭), U+0577 (շ)} => 2,
// - {U+0437 (з), U+0499 (ҙ), U+04E1 (ӡ), U+0909 (उ), U+0993 (ও),
// U+0A24 (ਤ), U+0A69 (੩), U+0AE9 (૩), U+0C69 (౩),
// U+1012 (ဒ), U+10D5 (ვ), U+10DE (პ)} => 3
- // - {U+0A6B (੫)} => 4,
+ // - {U+0A6B (੫), U+4E29 (丩), U+3110 (ㄐ)} => 4,
+ // - U+0573 (ճ) => 6
// - {U+09EA (৪), U+0A6A (੪), U+0b6b (୫)} => 8,
// - {U+0AED (૭), U+0b68 (୨), U+0C68 (౨)} => 9,
+ // Map a few dashes that ICU doesn't map. These are already blocked by ICU,
+ // but mapping them allows us to detect same skeletons.
+ // - {U+2014 (—), U+4E00 (一), U+2015 (―), U+23EA (⸺), U+2E3B (⸻)} => -,
extra_confusable_mapper_.reset(icu::Transliterator::createFromRules(
UNICODE_STRING_SIMPLE("ExtraConf"),
icu::UnicodeString::fromUTF8(
"[æӕ] > ae; [þϼҏ] > p; [ħнћңҥӈӊԋԧԩ] > h;"
- "[ĸκкқҝҟҡӄԟ] > k; [ŋпԥก] > n; œ > ce;"
- "[ŧтҭԏ] > t; [ƅьҍв] > b; [ωшщพฟພຟ] > w;"
+ "[ĸκкқҝҟҡӄԟ] > k; [ŋпԥกח] > n; œ > ce;"
+ "[ŧтҭԏ七丅丆] > t; [ƅьҍв] > b; [ωшщพฟພຟ] > w;"
"[мӎ] > m; [єҽҿၔ] > e; ґ > r; [ғӻ] > f;"
- "[ҫင] > c; ұ > y; [χҳӽӿ] > x;"
+ "[ҫင] > c; [ұ丫] > y; [χҳӽӿ乂] > x;"
"[ԃძ] > d; [ԍဌ] > g; [ടรຣຮ] > s; ၂ > j;"
"[०০੦૦ଠ୦೦] > o;"
"[৭੧૧] > q;"
"[บບ] > u;"
- "[२২੨੨૨೩೭] > 2;"
+ "[θ] > 0;"
+ "[२২੨੨૨೩೭շ] > 2;"
"[зҙӡउওਤ੩૩౩ဒვპ] > 3;"
- "[੫] > 4;"
+ "[੫丩ㄐ] > 4;"
+ "[ճ] > 6;"
"[৪੪୫] > 8;"
- "[૭୨౨] > 9;"),
+ "[૭୨౨] > 9;"
+ "[—一―⸺⸻] > \\-;"),
UTRANS_FORWARD, parse_error, status));
DCHECK(U_SUCCESS(status))
<< "Spoofchecker initalization failed due to an error: "
@@ -310,8 +322,8 @@ bool IDNSpoofChecker::SafeToDisplayAsUnicode(base::StringPiece16 label,
dangerous_pattern = new icu::RegexMatcher(
icu::UnicodeString(
// Disallow the following as they may be mistaken for slashes when
- // they're surrounded by non-Japanese scripts (i.e. scripts other
- // than Katakana, Hiragana or Han):
+ // they're surrounded by non-Japanese scripts (i.e. has non-Katakana
+ // Hiragana or Han scripts on both sides):
// "ノ" (Katakana no, U+30ce), "ソ" (Katakana so, U+30bd),
// "ゾ" (Katakana zo, U+30be), "ン" (Katakana n, U+30f3),
// "丶" (CJK unified ideograph, U+4E36),
@@ -377,16 +389,17 @@ bool IDNSpoofChecker::SafeToDisplayAsUnicode(base::StringPiece16 label,
return !dangerous_pattern->find();
}
-std::string IDNSpoofChecker::GetSimilarTopDomain(base::StringPiece16 hostname) {
+TopDomainEntry IDNSpoofChecker::GetSimilarTopDomain(
+ base::StringPiece16 hostname) {
DCHECK(!hostname.empty());
for (const std::string& skeleton : GetSkeletons(hostname)) {
DCHECK(!skeleton.empty());
- std::string matching_top_domain = LookupSkeletonInTopDomains(skeleton);
- if (!matching_top_domain.empty()) {
+ TopDomainEntry matching_top_domain = LookupSkeletonInTopDomains(skeleton);
+ if (!matching_top_domain.domain.empty()) {
return matching_top_domain;
}
}
- return std::string();
+ return TopDomainEntry();
}
Skeletons IDNSpoofChecker::GetSkeletons(base::StringPiece16 hostname) {
@@ -433,7 +446,7 @@ Skeletons IDNSpoofChecker::GetSkeletons(base::StringPiece16 hostname) {
return skeletons;
}
-std::string IDNSpoofChecker::LookupSkeletonInTopDomains(
+TopDomainEntry IDNSpoofChecker::LookupSkeletonInTopDomains(
const std::string& skeleton) {
DCHECK(!skeleton.empty());
// There are no other guarantees about a skeleton string such as not including
@@ -456,14 +469,14 @@ std::string IDNSpoofChecker::LookupSkeletonInTopDomains(
bool decoded = preload_decoder.Decode(partial_skeleton, &match);
DCHECK(decoded);
if (!decoded)
- return std::string();
+ return TopDomainEntry();
if (match)
return preload_decoder.matching_top_domain();
labels.erase(labels.begin());
}
- return std::string();
+ return TopDomainEntry();
}
void IDNSpoofChecker::SetAllowedUnicodeSet(UErrorCode* status) {
diff --git a/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.h b/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.h
index 1a30355caab..ae156843df5 100644
--- a/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.h
+++ b/chromium/components/url_formatter/spoof_checks/idn_spoof_checker.h
@@ -33,11 +33,18 @@ FORWARD_DECLARE_TEST(UrlFormatterTest, IDNToUnicode);
using Skeletons = base::flat_set<std::string>;
+// Represents a top domain entry in the trie.
+struct TopDomainEntry {
+ // The domain name.
+ std::string domain;
+ // True if the domain is in the top 500.
+ bool is_top_500 = false;
+};
+
// A helper class for IDN Spoof checking, used to ensure that no IDN input is
// spoofable per Chromium's standard of spoofability. For a more thorough
// explanation of how spoof checking works in Chromium, see
// http://dev.chromium.org/developers/design-documents/idn-in-google-chrome .
-
class IDNSpoofChecker {
public:
struct HuffmanTrieParams {
@@ -65,14 +72,18 @@ class IDNSpoofChecker {
// top domains.
// 2. Look up the diacritic-free version of |hostname| in the list of
// top domains. Note that non-IDN hostnames will not get here.
- std::string GetSimilarTopDomain(base::StringPiece16 hostname);
+ TopDomainEntry GetSimilarTopDomain(base::StringPiece16 hostname);
// Returns skeleton strings computed from |hostname|. This function can apply
// extra mappings to some characters to produce multiple skeletons.
Skeletons GetSkeletons(base::StringPiece16 hostname);
// Returns a top domain from the top 10K list matching the given |skeleton|.
- std::string LookupSkeletonInTopDomains(const std::string& skeleton);
+ TopDomainEntry LookupSkeletonInTopDomains(const std::string& skeleton);
+
+ // Used for unit tests.
+ static void SetTrieParamsForTesting(const HuffmanTrieParams& trie_params);
+ static void RestoreTrieParamsForTesting();
private:
// Sets allowed characters in IDN labels and turns on USPOOF_CHAR_LIMIT.
@@ -82,10 +93,6 @@ class IDNSpoofChecker {
// Cyrillic letters that look like ASCII Latin letters.
bool IsMadeOfLatinAlikeCyrillic(const icu::UnicodeString& label);
- // Used for unit tests.
- static void SetTrieParamsForTesting(const HuffmanTrieParams& trie_params);
- static void RestoreTrieParamsForTesting();
-
USpoofChecker* checker_;
icu::UnicodeSet deviation_characters_;
icu::UnicodeSet non_ascii_latin_letters_;
@@ -97,7 +104,6 @@ class IDNSpoofChecker {
std::unique_ptr<icu::Transliterator> diacritic_remover_;
std::unique_ptr<icu::Transliterator> extra_confusable_mapper_;
- FRIEND_TEST_ALL_PREFIXES(IDNSpoofCheckerTest, IDNToUnicode);
IDNSpoofChecker(const IDNSpoofChecker&) = delete;
void operator=(const IDNSpoofChecker&) = delete;
};
diff --git a/chromium/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc b/chromium/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
index cb7ba5ccb84..e6494eab601 100644
--- a/chromium/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
+++ b/chromium/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
@@ -14,6 +14,7 @@
#include "build/build_config.h"
#include "components/url_formatter/spoof_checks/idn_spoof_checker.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace url_formatter {
@@ -562,6 +563,8 @@ const IDNTestCase kIdnCases[] = {
// ӏԍԃ.com
{"xn--s5a8h3a.com", L"\x04cf\x050d\x0503.com", false},
+ // 1շ34567890.com
+ {"xn--134567890-gnk.com", L"1շ34567890.com", false},
// ꓲ2345б7890.com
{"xn--23457890-e7g93622b.com",
L"\xa4f2"
@@ -619,6 +622,8 @@ const IDNTestCase kIdnCases[] = {
L"12\x10DE"
L"4567890.com",
false},
+ // 123ㄐ567890.com
+ {"xn--123567890-dr5h.com", L"123ㄐ567890.com", false},
// 123Ꮞ567890.com
{"xn--123567890-dm4b.com",
L"123\x13ce"
@@ -629,6 +634,8 @@ const IDNTestCase kIdnCases[] = {
L"12345\x0431"
L"7890.com",
false},
+ // 12345ճ7890.com
+ {"xn--123457890-fmk.com", L"12345ճ7890.com", false},
// 1234567ȣ90.com
{"xn--123456790-6od.com",
L"1234567\x0223"
@@ -1063,21 +1070,42 @@ const IDNTestCase kIdnCases[] = {
// Kana voiced sound marks are not allowed.
{"xn--google-1m4e.com", L"google\x3099.com", false},
{"xn--google-8m4e.com", L"google\x309A.com", false},
-};
+
+ // Small letter theta looks like a zero.
+ {"xn--123456789-yzg.com", L"123456789θ.com", false},
+
+ {"xn--est-118d.net", L"七est.net", false},
+ {"xn--est-918d.net", L"丅est.net", false},
+ {"xn--est-e28d.net", L"丆est.net", false},
+ {"xn--3-cq6a.com", L"丩3.com", false},
+ {"xn--cxe-n68d.com", L"c丫xe.com", false},
+ {"xn--cye-b98d.com", L"cy乂e.com", false},
+
+ // U+05D7 can look like Latin n in many fonts.
+ {"xn--ceba.com", L"חח.com", false},
+
+}; // namespace
namespace test {
-#include "components/url_formatter/top_domains/test_domains-trie-inc.cc"
+#include "components/url_formatter/spoof_checks/top_domains/test_domains-trie-inc.cc"
}
} // namespace
-TEST(IDNSpoofCheckerTest, IDNToUnicode) {
- IDNSpoofChecker::HuffmanTrieParams trie_params{
- test::kTopDomainsHuffmanTree, sizeof(test::kTopDomainsHuffmanTree),
- test::kTopDomainsTrie, test::kTopDomainsTrieBits,
- test::kTopDomainsRootPosition};
- IDNSpoofChecker::SetTrieParamsForTesting(trie_params);
+class IDNSpoofCheckerTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ IDNSpoofChecker::HuffmanTrieParams trie_params{
+ test::kTopDomainsHuffmanTree, sizeof(test::kTopDomainsHuffmanTree),
+ test::kTopDomainsTrie, test::kTopDomainsTrieBits,
+ test::kTopDomainsRootPosition};
+ IDNSpoofChecker::SetTrieParamsForTesting(trie_params);
+ }
+
+ void TearDown() override { IDNSpoofChecker::RestoreTrieParamsForTesting(); }
+};
+TEST_F(IDNSpoofCheckerTest, IDNToUnicode) {
for (size_t i = 0; i < base::size(kIdnCases); i++) {
base::string16 output(IDNToUnicode(kIdnCases[i].input));
base::string16 expected(kIdnCases[i].unicode_allowed
@@ -1086,12 +1114,44 @@ TEST(IDNSpoofCheckerTest, IDNToUnicode) {
EXPECT_EQ(expected, output)
<< "input # " << i << ": \"" << kIdnCases[i].input << "\"";
}
- IDNSpoofChecker::RestoreTrieParamsForTesting();
+}
+
+TEST_F(IDNSpoofCheckerTest, LookupSkeletonInTopDomains) {
+ {
+ TopDomainEntry entry =
+ IDNSpoofChecker().LookupSkeletonInTopDomains("d4OOO.corn");
+ EXPECT_EQ("d4000.com", entry.domain);
+ EXPECT_TRUE(entry.is_top_500);
+ }
+ {
+ TopDomainEntry entry =
+ IDNSpoofChecker().LookupSkeletonInTopDomains("digklrno68.corn");
+ EXPECT_EQ("digklmo68.com", entry.domain);
+ EXPECT_FALSE(entry.is_top_500);
+ }
+}
+
+// Same test as LookupSkeletonInTopDomains but using the real top domain list.
+TEST(IDNSpoofCheckerNoFixtureTest, LookupSkeletonInTopDomains) {
+ {
+ TopDomainEntry entry =
+ IDNSpoofChecker().LookupSkeletonInTopDomains("google.corn");
+ EXPECT_EQ("google.com", entry.domain);
+ EXPECT_TRUE(entry.is_top_500);
+ }
+ {
+ // This is data dependent, must be updated when the top domain list
+ // is updated.
+ TopDomainEntry entry =
+ IDNSpoofChecker().LookupSkeletonInTopDomains("google.sk");
+ EXPECT_EQ("google.sk", entry.domain);
+ EXPECT_FALSE(entry.is_top_500);
+ }
}
// Check the unsafe version of IDNToUnicode. Even though the input domain
// matches a top domain, it should still be converted to unicode.
-TEST(IDNSpoofCheckerTest, UnsafeIDNToUnicodeWithDetails) {
+TEST(IDNSpoofCheckerNoFixtureTest, UnsafeIDNToUnicodeWithDetails) {
const struct TestCase {
// The IDNA/Punycode version of the domain (plain ASCII).
const char* const punycode;
@@ -1101,25 +1161,30 @@ TEST(IDNSpoofCheckerTest, UnsafeIDNToUnicodeWithDetails) {
const bool expected_has_idn;
// The top domain that |punycode| matched to, if any.
const char* const expected_matching_domain;
+ // If true, the matching top domain is expected to be in top 500.
+ const bool expected_is_top_500;
} kTestCases[] = {
{// An ASCII, top domain.
"google.com", L"google.com", false,
// Since it's not unicode, we won't attempt to match it to a top domain.
- ""},
+ "",
+ // ...And since we don't match it to a top domain, we don't know if it's
+ // a top 500 domain.
+ false},
{// An ASCII domain that's not a top domain.
- "not-top-domain.com", L"not-top-domain.com", false, ""},
+ "not-top-domain.com", L"not-top-domain.com", false, "", false},
{// A unicode domain that's valid according to all of the rules in IDN
// spoof checker except that it matches a top domain. Should be
// converted to punycode.
- "xn--googl-fsa.com", L"googlé.com", true, "google.com"},
+ "xn--googl-fsa.com", L"googlé.com", true, "google.com", true},
{// A unicode domain that's not valid according to the rules in IDN spoof
// checker (mixed script) and it matches a top domain. Should be
// converted to punycode.
- "xn--80ak6aa92e.com", L"аррӏе.com", true, "apple.com"},
+ "xn--80ak6aa92e.com", L"аррӏе.com", true, "apple.com", true},
{// A unicode domain that's not valid according to the rules in IDN spoof
// checker (mixed script) but it doesn't match a top domain.
- "xn--o-o-oai-26a223aia177a7ab7649d.com", L"ɴoτ-τoρ-ďoᛖaiɴ.com", true,
- ""},
+ "xn--o-o-oai-26a223aia177a7ab7649d.com", L"ɴoτ-τoρ-ďoᛖaiɴ.com", true, "",
+ false},
};
for (const TestCase& test_case : kTestCases) {
@@ -1127,7 +1192,47 @@ TEST(IDNSpoofCheckerTest, UnsafeIDNToUnicodeWithDetails) {
UnsafeIDNToUnicodeWithDetails(test_case.punycode);
EXPECT_EQ(base::WideToUTF16(test_case.expected_unicode), result.result);
EXPECT_EQ(test_case.expected_has_idn, result.has_idn_component);
- EXPECT_EQ(test_case.expected_matching_domain, result.matching_top_domain);
+ EXPECT_EQ(test_case.expected_matching_domain,
+ result.matching_top_domain.domain);
+ EXPECT_EQ(test_case.expected_is_top_500,
+ result.matching_top_domain.is_top_500);
+ }
+}
+
+// Checks that skeletons are properly generated for domains with blocked
+// characters after using UnsafeIDNToUnicodeWithDetails.
+TEST(IDNSpoofCheckerNoFixtureTest, Skeletons) {
+ // All of these should produce the same skeleton. Not all of these are
+ // explicitly mapped in idn_spoof_checker.cc, ICU already handles some.
+ const char kDashSite[] = "test-site";
+ const struct TestCase {
+ const GURL url;
+ const char* const expected_skeleton;
+ } kTestCases[] = {
+ {GURL("http://test‐site"), kDashSite}, // U+2010 (Hyphen)
+ {GURL("http://test‑site"), kDashSite}, // U+2011 (Non breaking hyphen)
+ {GURL("http://test‒site"), kDashSite}, // U+2012 (Figure dash)
+ {GURL("http://test–site"), kDashSite}, // U+2013 (En dash)
+ {GURL("http://test—site"), kDashSite}, // U+2014 (Em dash)
+ {GURL("http://test―site"), kDashSite}, // U+2015 (Horizontal bar)
+ {GURL("http://test一site"), kDashSite}, // U+4E00 (一)
+ {GURL("http://test−site"), kDashSite}, // U+2212 (minus sign)
+ {GURL("http://test⸺site"), kDashSite}, // U+2E3A (two-em dash)
+ {GURL("http://test⸻site"), kDashSite}, // U+2E3B (three-em dash)
+ {GURL("http://七est.net"), "test.net"},
+ {GURL("http://丅est.net"), "test.net"},
+ {GURL("http://丆est.net"), "test.net"},
+ {GURL("http://c丫xe.com"), "cyxe.corn"},
+ {GURL("http://cy乂e.com"), "cyxe.corn"},
+ {GURL("http://丩3.com"), "43.corn"}};
+
+ IDNSpoofChecker checker;
+ for (const TestCase& test_case : kTestCases) {
+ const url_formatter::IDNConversionResult result =
+ UnsafeIDNToUnicodeWithDetails(test_case.url.host());
+ Skeletons skeletons = checker.GetSkeletons(result.result);
+ EXPECT_EQ(1u, skeletons.size());
+ EXPECT_EQ(test_case.expected_skeleton, *skeletons.begin());
}
}
diff --git a/chromium/components/url_formatter/top_domains/BUILD.gn b/chromium/components/url_formatter/spoof_checks/top_domains/BUILD.gn
index 26b55ad5f6d..e5ac5ee9a7a 100644
--- a/chromium/components/url_formatter/top_domains/BUILD.gn
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/BUILD.gn
@@ -40,11 +40,11 @@ compiled_action("generate_top_domains_trie") {
# Inputs in order expected by the command line of the tool.
inputs = [
- "//components/url_formatter/top_domains/alexa_domains.skeletons",
- "//components/url_formatter/top_domains/top_domains_trie.template",
+ "//components/url_formatter/spoof_checks/top_domains/domains.skeletons",
+ "//components/url_formatter/spoof_checks/top_domains/top_domains_trie.template",
]
outputs = [
- "$target_gen_dir/alexa_domains-trie-inc.cc",
+ "$target_gen_dir/domains-trie-inc.cc",
]
args =
rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
@@ -57,14 +57,16 @@ compiled_action("generate_top_domains_test_trie") {
# Inputs in order expected by the command line of the tool.
inputs = [
- "//components/url_formatter/top_domains/test_domains.skeletons",
- "//components/url_formatter/top_domains/top_domains_trie.template",
+ "//components/url_formatter/spoof_checks/top_domains/test_domains.skeletons",
+ "//components/url_formatter/spoof_checks/top_domains/top_domains_trie.template",
]
outputs = [
"$target_gen_dir/test_domains-trie-inc.cc",
]
- args =
- rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
+
+ # Passing --for_testing flag marks only the first site with is_top_500.
+ args = rebase_path(inputs, root_build_dir) +
+ rebase_path(outputs, root_build_dir) + [ "--for_testing" ]
}
executable("make_top_domain_list_for_edit_distance") {
@@ -111,7 +113,7 @@ compiled_action("generate_top_domains_for_edit_distance") {
# Inputs in order expected by the command line of the tool.
inputs = [
- "//components/url_formatter/top_domains/alexa_domains.list",
+ "//components/url_formatter/spoof_checks/top_domains/domains.list",
]
outputs = [
"$target_gen_dir/top500-domains-inc.cc",
diff --git a/chromium/components/url_formatter/spoof_checks/top_domains/README b/chromium/components/url_formatter/spoof_checks/top_domains/README
new file mode 100644
index 00000000000..f883e3b6478
--- /dev/null
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/README
@@ -0,0 +1,23 @@
+* domains.list
+
+ A top domain list, one per line. Used as an input to
+ make_top_domain_skeletons. See http://go/chrome-top-domains-update for update
+ instructions.
+
+* domains.skeletons
+
+ The checked-in output of make_top_domain_skeletons. Processed during the
+ build to generate domains-trie-inc.cc, which is used by
+ idn_spoof_checker.cc. This must be regenerated as follows if ICU is updated,
+ since skeletons can differ across ICU versions:
+
+ $ ninja -C $build_outdir make_top_domain_skeletons
+ $ $build_outdir/make_top_domain_skeletons
+
+* test_domains.list
+ A list of domains to use in IDNToUnicode test instead of the actual
+ top domain list. Manually edited to match what's in IDNToUnicode test.
+
+* test_domains.skeletons
+ Generated output of test_domains.list along with domains.skeletons
+ by make_top_domain_skeletons.
diff --git a/chromium/components/url_formatter/spoof_checks/top_domains/domains.list b/chromium/components/url_formatter/spoof_checks/top_domains/domains.list
new file mode 100644
index 00000000000..5504f1c8c73
--- /dev/null
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/domains.list
@@ -0,0 +1,5001 @@
+17track.net
+24h.com.vn
+academia.edu
+academic.ru
+accuweather.com
+adobe.com
+adp.com
+agoda.com
+aif.ru
+airbnb.com
+alibaba.com
+aliexpress.com
+allegro.pl
+allocine.fr
+alodokter.com
+amazon.ca
+amazon.co.jp
+amazon.co.uk
+amazon.com
+amazon.com.mx
+amazon.de
+amazon.es
+amazon.fr
+amazon.in
+amazon.it
+ameblo.jp
+americanexpress.com
+ancestry.com
+animeflv.net
+anyxxx.pro
+aol.com
+apkpure.com
+apple.com
+appledaily.com
+archive.org
+asahi.com
+ask.com
+asos.com
+asus.com
+autotrader.com
+avito.ru
+azlyrics.com
+badoo.com
+baidu.com
+baixaki.com.br
+banggood.com
+bankofamerica.com
+battle.net
+bbc.co.uk
+bbc.com
+beeg.com
+bestbuy.com
+bet365.com
+biblegateway.com
+biglobe.ne.jp
+bild.de
+bilibili.com
+bing.com
+blackboard.com
+blogspot.com
+bloomberg.com
+booking.com
+bookmyshow.com
+britannica.com
+bukalapak.com
+businessinsider.com
+bustle.com
+buzzfeed.com
+ca.gov
+caixa.gov.br
+canada.ca
+canalrcn.com
+canva.com
+capitalone.com
+cargurus.com
+cbsnews.com
+cbssports.com
+ccm.net
+cdc.gov
+cdiscount.com
+ceneo.pl
+chase.com
+chaturbate.com
+chegg.com
+chinatimes.com
+chip.de
+chron.com
+cinecalidad.to
+clarin.com
+cnbc.com
+cnet.com
+cnn.com
+collegedunia.com
+convert2mp3.net
+correios.com.br
+craigslist.org
+cricbuzz.com
+dailymail.co.uk
+dailymotion.com
+daum.net
+dell.com
+depositphotos.com
+detik.com
+deviantart.com
+dhgate.com
+dhl.de
+dictionary.com
+discordapp.com
+dmm.co.jp
+dmm.com
+doorblog.jp
+drom.ru
+dropbox.com
+ebay-kleinanzeigen.de
+ebay.co.uk
+ebay.com
+ebay.com.au
+ebay.de
+ebay.es
+ebay.fr
+ebay.it
+egy.best
+eksisozluk.com
+elconfidencial.com
+elintransigente.com
+elmundo.es
+elpais.com
+eluniversal.com.mx
+emag.ro
+engadget.com
+epicgames.com
+espn.com
+etsy.com
+europa.eu
+eventbrite.com
+excite.co.jp
+expedia.com
+express.co.uk
+facebook.com
+fandango.com
+fandom.com
+fast.com
+fazenda.gov.br
+fc2.com
+fedex.com
+filmweb.pl
+flickr.com
+flipkart.com
+fnac.com
+forbes.com
+foxnews.com
+francetvinfo.fr
+free.fr
+gaana.com
+gamepedia.com
+gamespot.com
+gearbest.com
+genius.com
+gfycat.com
+giphy.com
+gismeteo.ru
+github.com
+glassdoor.com
+globo.com
+glosbe.com
+go.com
+goal.com
+gofundme.com
+goo.ne.jp
+goodreads.com
+google.ca
+google.cl
+google.co.id
+google.co.in
+google.co.jp
+google.co.kr
+google.co.th
+google.co.uk
+google.com
+google.com.ar
+google.com.au
+google.com.br
+google.com.co
+google.com.mx
+google.com.tr
+google.com.tw
+google.de
+google.es
+google.fr
+google.it
+google.nl
+google.pl
+google.pt
+google.ru
+gotporn.com
+gsmarena.com
+gumtree.com
+haberler.com
+hatenablog.com
+hdfcbank.com
+hdrezka.ag
+healthline.com
+hilton.com
+hindustantimes.com
+homedepot.com
+hotels.com
+hotpepper.jp
+hotstar.com
+hp.com
+huawei.com
+huffpost.com
+hulu.com
+icicibank.com
+icloud.com
+ign.com
+ikea.com
+ilmeteo.it
+ilovepdf.com
+imdb.com
+imgur.com
+impress.co.jp
+indeed.com
+indiamart.com
+indiatimes.com
+indiatoday.in
+infobae.com
+instagram.com
+instructables.com
+instructure.com
+interia.pl
+intuit.com
+investing.com
+investopedia.com
+irecommend.ru
+irs.gov
+itau.com.br
+itmedia.co.jp
+jobrapido.com
+justdial.com
+jw.org
+kahoot.it
+kakaku.com
+kakao.com
+kayak.com
+kenh14.vn
+khanacademy.org
+kinopoisk.ru
+kizlarsoruyor.com
+kknews.cc
+kohls.com
+kompas.com
+kotobank.jp
+kp.ru
+lazada.co.th
+leagueoflegends.com
+leboncoin.fr
+lemonde.fr
+lenta.ru
+letmejerk.com
+lifewire.com
+line.me
+linkedin.com
+live.com
+livedoor.biz
+livedoor.com
+livedoor.jp
+livejournal.com
+livescore.com
+livestrong.com
+mail.ru
+makemytrip.com
+malavida.com
+marca.com
+mawdoo3.com
+mayoclinic.org
+meb.gov.tr
+mediafire.com
+medium.com
+mega.nz
+mercadolibre.com
+mercadolibre.com.ar
+mercadolibre.com.co
+mercadolibre.com.mx
+mercadolivre.com.br
+mercari.com
+messenger.com
+mi.com
+microsoft.com
+microsoftonline.com
+milliyet.com.tr
+mk.ru
+mlb.com
+mobile.de
+mobile01.com
+monografias.com
+msn.com
+mundodeportivo.com
+myanimelist.net
+mynavi.jp
+mynet.com
+n11.com
+namu.wiki
+naver.com
+naver.jp
+nba.com
+nbcnews.com
+nbcsports.com
+ndtv.com
+netflix.com
+news18.com
+nextdoor.com
+nhk.or.jp
+nicovideo.jp
+nifty.com
+nih.gov
+nike.com
+nikkansports.com
+nikkei.com
+nvidia.com
+nypost.com
+nytimes.com
+office.com
+office365.com
+ok.ru
+okdiario.com
+olx.co.id
+olx.com.br
+olx.pl
+olx.ua
+onet.pl
+onlinesbi.com
+onlinevideoconverter.com
+op.gg
+orange.fr
+otto.de
+otvfoco.com.br
+otzovik.com
+over-blog.com
+pantip.com
+passeidireto.com
+patreon.com
+paypal.com
+perfectgirls.net
+pinterest.co.uk
+pinterest.com
+pinterest.es
+pixiv.net
+pixnet.net
+playstation.com
+politico.com
+polygon.com
+pornhub.com
+prezi.com
+primevideo.com
+programme-tv.net
+qq.com
+qualtrics.com
+quizlet.com
+quora.com
+rakuten.co.jp
+rambler.ru
+ranker.com
+reddit.com
+redtube.com
+researchgate.net
+reverso.net
+rg.ru
+rightmove.co.uk
+roblox.com
+rottentomatoes.com
+rozetka.com.ua
+rt.com
+sabah.com.tr
+sahibinden.com
+samsung.com
+sanook.com
+sarkariresult.com
+savefrom.net
+sciencedirect.com
+scribd.com
+sfgate.com
+shopee.co.th
+shutterstock.com
+sinoptik.ua
+sky.com
+skyscanner.net
+skysports.com
+slideshare.net
+smallpdf.com
+smi2.ru
+softonic.com
+soundcloud.com
+souq.com
+sozcu.com.tr
+spankbang.com
+speedtest.net
+spiegel.de
+spotify.com
+sputniknews.com
+stackexchange.com
+stackoverflow.com
+steamcommunity.com
+steampowered.com
+study.com
+surveymonkey.com
+t-online.de
+tabelog.com
+taleo.net
+taobao.com
+target.com
+techradar.com
+techtudo.com.br
+telegraph.co.uk
+termometropolitico.it
+thebalancecareers.com
+thedailybeast.com
+thefreedictionary.com
+theguardian.com
+thepiratebay.org
+thesaurus.com
+theverge.com
+thoughtco.com
+tim.it
+tistory.com
+tnaflix.com
+tokopedia.com
+trello.com
+tribunnews.com
+tripadvisor.com
+trulia.com
+trustpilot.com
+tumblr.com
+tutorialspoint.com
+twitch.tv
+twitter.com
+uber.com
+ubisoft.com
+udemy.com
+udn.com
+ultimate-guitar.com
+unam.mx
+uniqlo.com
+uol.com.br
+ups.com
+uptodown.com
+urbandictionary.com
+usatoday.com
+usps.com
+vice.com
+vimeo.com
+vk.com
+vnexpress.net
+w3schools.com
+walmart.com
+washingtonpost.com
+wattpad.com
+weather.com
+web.de
+webmd.com
+weebly.com
+wellsfargo.com
+wetransfer.com
+whatsapp.com
+wikihow.com
+wikipedia.org
+wiktionary.org
+wish.com
+wixsite.com
+wondershare.com
+wordpress.com
+wordreference.com
+wp.pl
+wsj.com
+www.gob.mx
+www.gov.uk
+xbox.com
+xe.com
+xfinity.com
+xhamster.com
+xnxx.com
+xnxx2.pro
+xozilla.com
+xvideos.com
+y2mate.com
+yahoo.co.jp
+yahoo.com
+yandex.ru
+yelp.com
+yenisafak.com
+youjizz.com
+youm7.com
+youporn.com
+yourdictionary.com
+youtube.com
+yts.am
+zendesk.com
+zillow.com
+zing.vn
+znanija.com
+zomato.com
+###
+01net.com
+1000.menu
+10086.cn
+103.by
+104.com.tw
+1111.com.tw
+112.ua
+114la.com
+1177.se
+11st.co.kr
+123doc.org
+123link.vip
+123movies.la
+123rf.com
+126.com
+13.cl
+1337x.to
+1377x.to
+15min.lt
+163.com
+1688.com
+16personalities.com
+17173.com
+178.com
+1fichier.com
+1mg.com
+1news.com.br
+1plus1.ua
+1tv.ru
+1und1.de
+20minutes.fr
+20minutos.es
+21cineplex.com
+23andme.com
+24-horas.mx
+24.hu
+247sports.com
+24horas.cl
+24porn.com
+24sata.hr
+24smi.org
+24timezones.com
+24tv.ua
+24video.sexy
+27.ua
+2ch-c.net
+2ch.net
+2chblog.jp
+2dehands.be
+2ememain.be
+2gis.ru
+2m.ma
+2movierulz.gs
+2movierulz.st
+2sao.vn
+360.cn
+360.com
+360doc.com
+36kr.com
+3bmeteo.com
+3djuegos.com
+3dlat.com
+3dmgame.com
+3dnews.ru
+3movs.com
+4399.com
+444.hu
+4chan.org
+4channel.org
+4gamer.net
+4pda.ru
+4shared.com
+4travel.jp
+4tube.com
+5-tv.ru
+51.la
+51cto.com
+51job.com
+51sole.com
+52pojie.cn
+58.com
+58pic.com
+5ch.net
+6.cn
+720p-izle.com
+750g.com
+7ya.ru
+81.cn
+8maple.ru
+90min.com
+91jm.com
+91mobiles.com
+99114.com
+99acres.com
+9gag.com
+9news.com.au
+a1.ro
+a101.com.tr
+a9vg.com
+aa.com
+aa.com.tr
+aaa.com
+aajtak.in
+aarp.org
+aastocks.com
+abc.com.py
+abc.es
+abc.net.au
+abc13.com
+abczdrowie.pl
+abdwap2.com
+abema.tv
+abematimes.com
+abola.pt
+about.google
+aboutespanol.com
+aboutyou.de
+abplive.in
+abril.com.br
+abs-cbn.com
+abv.bg
+academy.com
+accenture.com
+accorhotels.com
+acehardware.com
+acer.com
+acfun.cn
+acs.org
+action.com
+active.com
+actu.fr
+ad.nl
+adac.de
+adayroi.com
+addthis.com
+adevarul.ro
+adidas.com
+adidas.com.br
+adme.ru
+administradores.com.br
+adnradio.cl
+adoptapet.com
+adorocinema.com
+adslzone.net
+adultfriendfinder.com
+advanceautoparts.com
+ae.com
+aemet.es
+aemps.es
+aeon.co.jp
+aeoncinema.com
+aerolineas.com.ar
+affaritaliani.it
+afip.gob.ar
+afisha.ru
+afreecatv.com
+aftonbladet.se
+agenciatributaria.es
+aglasem.com
+ah.nl
+ahaber.com.tr
+ahaonline.cz
+ahlmasrnews.com
+ahoranoticias.cl
+ahram.org.eg
+airasia.com
+airbnb.co.uk
+airbnb.com.br
+airbnb.es
+airbnb.fr
+aircanada.com
+airedesantafe.com.ar
+airtel.in
+ais.co.th
+ajc.com
+ajio.com
+akakce.com
+akamaihd.net
+akamaized.net
+akc.org
+akket.com
+akoam.net
+aksam.com.tr
+aktuality.sk
+aktualne.cz
+akurat.co
+al3omk.com
+alamaula.com
+alamy.com
+alaskaair.com
+albawabhnews.com
+alberta.ca
+alc.co.jp
+aldi-sued.de
+aldi.co.uk
+alfemminile.com
+ali213.net
+alicdn.com
+alipay.com
+aliyun.com
+aljaras.com
+aljazeera.com
+aljazeera.net
+alkosto.com
+allabout.co.jp
+allaboutvision.com
+allbest.ru
+allkpop.com
+allmusic.com
+allo.ua
+allodocteurs.fr
+allrecipes.co.uk
+allrecipes.com
+allscrabblewords.com
+allstate.com
+ally.com
+almaany.com
+almasryalyoum.com
+almrsal.com
+alnaharegypt.com
+alo.rs
+alphacoders.com
+alphaporno.com
+altema.jp
+altervista.org
+altibbi.com
+alukah.net
+alvolante.it
+alwafd.news
+alwatanvoice.com
+alza.cz
+am.com.mx
+amalgama-lab.com
+amarujala.com
+amazon.cn
+amazon.com.au
+amazon.com.br
+amazon.jobs
+amazonaws.com
+ambito.com
+amctheatres.com
+amd.com
+ameba.jp
+ameli.fr
+americanas.com.br
+americatv.com.pe
+ameritrade.com
+aminoapps.com
+amtrak.com
+ana.co.jp
+anadolu.edu.tr
+analdin.com
+anandtech.com
+andhrajyothy.com
+andro4all.com
+androeed.ru
+android-1.com
+android.com
+androidauthority.com
+androidcentral.com
+androidfilehost.com
+androidoyun.club
+androidpolice.com
+angieslist.com
+animatetimes.com
+anime-planet.com
+anime-sugoi.com
+animenewsnetwork.com
+animevost.org
+anjuke.com
+anninhthudo.vn
+annuaire-telechargement.com
+ansa.it
+anses.gob.ar
+answers.com
+antena3.com
+antena3.ro
+antyradio.pl
+anwb.nl
+anyporn.com
+anysex.com
+ap.gov.in
+apache.org
+aparat.com
+apartmentguide.com
+apartmenthomeliving.com
+apartments.com
+apkhere.com
+apkmirror.com
+apkmonk.com
+apnews.com
+apost.com
+apostrophe.ua
+apotheken-umschau.de
+app-liv.jp
+appbank.net
+appfolio.com
+applebees.com
+appllio.com
+applocal.com.br
+appmedia.jp
+appspot.com
+apteka.ru
+aptoide.com
+arabam.com
+arabsong.top
+arbeitsagentur.de
+arcgis.com
+archiveofourown.org
+arduino.cc
+argaam.com
+argentina.gob.ar
+argentino.com.ar
+argos.co.uk
+arine.jp
+aristeguinoticias.com
+arstechnica.com
+artstation.com
+aruba.it
+arukereso.hu
+arxiv.org
+as.com
+asagei.com
+asajo.jp
+asana.com
+ascii.jp
+asda.com
+ashemaletube.com
+ashleyfurniture.com
+ashleymadison.com
+asianetnews.com
+ask.fm
+askubuntu.com
+asos.fr
+aspor.com.tr
+asriran.com
+astrology.com
+astrologyanswers.com
+atelevisao.com
+athensmagazine.gr
+athome.co.jp
+atlantablackstar.com
+atlassian.com
+atlassian.net
+atptour.com
+atrapalo.com
+atresplayer.com
+att.com
+att.net
+atv.com.tr
+atwiki.jp
+au.com
+auchan.fr
+auction.co.kr
+audible.com
+aufeminin.com
+auone.jp
+auspost.com.au
+auto-swiat.pl
+auto.ru
+autobild.de
+autoblog.com
+autocarindia.com
+autodesk.com
+autohome.com.cn
+autokult.pl
+automobile.it
+autoplus.fr
+autoscout24.de
+autoscout24.it
+autotrader.ca
+autotrader.co.uk
+autozone.com
+avast.com
+avaz.ba
+avclub.com
+avg.com
+avgle.com
+avianca.com
+aviasales.ru
+avito.ma
+avon.com
+avon.com.br
+avvo.com
+aweber.com
+axisbank.com
+axs.com
+azcentral.com
+azet.sk
+azure.com
+azurewebsites.net
+b-cdn.net
+b1.ro
+b2b.cn
+b92.net
+bab.la
+babbel.com
+baby.ru
+babyblog.ru
+babycenter.com
+babycentre.co.uk
+babyhome.com.tw
+babytree.com
+backpackers.com.tw
+badorno.xxx
+bahn.de
+baiducontent.com
+baike.com
+bakeca.it
+bakusai.com
+banamex.com
+banco.bradesco
+bancogalicia.com.ar
+bancomer.com
+bancosantander.es
+band.us
+bandcamp.com
+bang.com
+bankbazaar.com
+banki.ru
+bankifsccode.com
+bankmellat.ir
+bankrate.com
+baomoi.com
+barnesandnoble.com
+bartleby.com
+baseball-reference.com
+basketball-reference.com
+baskino.me
+basspro.com
+bathandbodyworks.com
+bauhaus.info
+bayt.com
+bazos.cz
+bazos.sk
+bb.com.br
+bbb.org
+bbcgoodfood.com
+bbva.es
+bebesymas.com
+bedbathandbeyond.com
+beeline.ru
+beenverified.com
+behance.net
+beinsports.com
+belastingdienst.nl
+belcy.jp
+belezanaweb.com.br
+belk.com
+bell.ca
+bellemaison.jp
+belnovosti.by
+benesse.ne.jp
+bengo4.com
+berkeley.edu
+berlin.de
+bershka.com
+beslist.nl
+bestbuy.ca
+bestdeals.today
+bestfreetube.xxx
+besthugecocks.com
+bestprice.gr
+bestreviews.guide
+bethesda.net
+betterhealth.vic.gov.au
+bettycrocker.com
+beyazperde.com
+beytoote.com
+bfmtv.com
+bg-mamma.com
+bgr.com
+bhaskar.com
+bhg.com
+bhphotovideo.com
+bible.com
+biblehub.com
+biblestudytools.com
+bibliaon.com
+bibliaonline.com.br
+biccamera.com
+bienpublic.com
+bigbasket.com
+bigcartel.com
+biggo.com.tw
+bigl.ua
+biglots.com
+bigw.com.au
+bihar.gov.in
+bikedekho.com
+bikewale.com
+billboard.com
+bilutv.org
+binance.com
+binbaz.org.sa
+bingoporno.com
+biobiochile.cl
+biografiasyvidas.com
+biography.com
+bitbucket.org
+biteki.com
+bitly.com
+biz-journal.jp
+biz.ua
+bizjournals.com
+blabbermouth.net
+blastingnews.com
+bldaily.com
+bleacherreport.com
+bleepingcomputer.com
+blesk.cz
+blibli.com
+blic.rs
+blikk.hu
+blizzard.com
+blockchain.com
+blocket.se
+blog.hu
+blog.ir
+blog.jp
+blog.me
+blogfa.com
+blogger.com
+blogimg.jp
+blogos.com
+bloomberght.com
+bluehost.com
+blueporns.com
+bluestacks.com
+bluradio.com
+bmi.ir
+bmj.com
+bmo.com
+bmstores.co.uk
+bne.com.br
+boafoda.com
+boardgamegeek.com
+boc.cn
+bodybuilding.com
+bokepxv.com
+bol.com
+bola.net
+bolasport.com
+bolavip.com
+bolshoyvopros.ru
+bom.gov.au
+bonappetit.com
+bongacams.com
+bongdanet.vn
+bongdaplus.vn
+bonprix.de
+boohoo.com
+bookdepository.com
+books.com.tw
+boostmobile.com
+boots.com
+boredpanda.com
+bostonglobe.com
+boticario.com.br
+boulanger.com
+boursorama.com
+bouyguestelecom.fr
+box.com
+box.net
+boxofficemojo.com
+boyfriendtv.com
+boyner.com.tr
+br.com
+br.de
+bradesco.com.br
+brainly.co.id
+brainly.com
+brainly.com.br
+brainly.in
+brainly.lat
+brainly.pl
+brainly.ro
+brainyquote.com
+brasil247.com
+brassring.com
+bravotube.net
+bravotv.com
+brazzers.com
+brazzersnetwork.com
+breitbart.com
+brigitte.de
+brilio.net
+britishairways.com
+britishcouncil.org
+brother.com
+brunch.co.kr
+bryk.pl
+bt.com
+bt.dk
+buenastareas.com
+buenosaires.gob.ar
+buentema.org
+buffer.com
+bugaboo.tv
+buienradar.nl
+bulbagarden.net
+bulbul.su
+bulurum.com
+bunnings.com.au
+bunshun.jp
+bunte.de
+busbud.com
+buscaonibus.com.br
+buscapalabra.com
+buscapalabras.com.ar
+buscape.com.br
+business-standard.com
+business.site
+businessdictionary.com
+businessinsider.com.pl
+businessinsider.de
+businessweekly.com.tw
+but.fr
+buzzfeednews.com
+byjus.com
+byoinnavi.jp
+byr.cn
+bz-berlin.de
+c-and-a.com
+c-ij.com
+cabelas.com
+cadenaser.com
+caf.fr
+cafedelites.com
+cafef.vn
+caijing.com.cn
+cainiao.com
+caisse-epargne.fr
+caixabank.es
+calameo.com
+calciomercato.com
+calculator.net
+calendly.com
+caliente.mx
+callofduty.com
+cam4.com
+camara.leg.br
+cambridge.org
+cameraprive.com
+campograndenews.com.br
+campus-star.com
+canadapost.ca
+canadiantire.ca
+canal1.com.co
+canalblog.com
+canaltech.com.br
+cancan.ro
+cancaonova.com
+cancer.gov
+cancer.org
+capital.fr
+car-moby.jp
+car.gr
+caracol.com.co
+caracoltv.com
+caracteristicas.co
+caradisiac.com
+caranddriver.com
+carbuzz.com
+carcarekiosk.com
+cardekho.com
+care.com
+careerbuilder.com
+careers360.com
+carfax.com
+carid.com
+carmax.com
+carnival.com
+carousell.com
+carrefour.com.br
+carrefour.es
+carrefour.fr
+carrosnaweb.com.br
+cars.com
+carsensor.net
+carsforsale.com
+carters.com
+carview.co.jp
+carwale.com
+cas.sk
+casa.it
+casadellibro.com
+casasbahia.com.br
+castorama.fr
+castorama.pl
+catchnews.com
+catho.com.br
+catracalivre.com.br
+cbc.ca
+cbr.com
+cbs.com
+cbslocal.com
+ccleaner.com
+ccn.com
+cda.pl
+cdmx.gob.mx
+cdninstagram.com
+cdstm.cn
+cea.com.br
+cec.com.br
+cekresi.com
+celebjihad.com
+cellphones.com.vn
+cengage.com
+censor.net.ua
+centauro.com.br
+centurylink.com
+cerdas.com
+ceskatelevize.cz
+ch3thailand.com
+champion.gg
+championat.com
+change.org
+channel4.com
+channelnewsasia.com
+cheapflights.com
+cheapoair.com
+cheaptickets.com
+cheatsheet.com
+check24.de
+checkraka.com
+cheezburger.com
+chefkoch.de
+chess.com
+chevrolet.com
+chewy.com
+chicagotribune.com
+chick-fil-a.com
+childrensplace.com
+chilevision.cl
+chillizet.pl
+china.com
+china.com.cn
+chinadaily.com.cn
+chinaz.com
+chiphell.com
+chiquipedia.com
+chochox.com
+chollometro.com
+chordify.net
+chordtabs.in.th
+chosun.com
+chotot.com
+chouftv.ma
+chp.org.tr
+chsi.com.cn
+cian.ru
+ciatr.jp
+cic.gc.ca
+ciceksepeti.com
+cienradios.com
+cifraclub.com.br
+cima4u.tv
+cimaclub.com
+cimri.com
+cinecolombia.com
+cinemablend.com
+cinemagia.ro
+cinemark.com
+cinematoday.jp
+cinemex.com
+cineplex.com
+cinepolis.com
+cisco.com
+citi.com
+citilink.ru
+citrus.ua
+city-data.com
+cityheaven.net
+ciudad.com.ar
+civico.com
+ck101.com
+clalit.co.il
+claro.com.ar
+claro.com.br
+clasohlson.com
+classmates.com
+cleartax.in
+cleartrip.com
+clevelandclinic.org
+clever.com
+clicccar.com
+clickfunnels.com
+clicrbs.com.br
+clien.net
+clima.com
+climatempo.com.br
+clipconverter.cc
+clips4sale.com
+closermag.fr
+cloudflare.com
+clubedohardware.com.br
+clubfactory.com
+clubic.com
+cmjornal.pt
+cmoa.jp
+cmu.edu
+cnbcindonesia.com
+cnbeta.com
+cnblogs.com
+cne.gob.ec
+cnki.com.cn
+cnki.net
+cnnamador.com
+cnnic.cn
+cnnindonesia.com
+cnnturk.com
+cnrtl.fr
+cnzz.com
+coches.net
+cochrane.org
+cocolog-nifty.com
+codashop.com
+codecanyon.net
+codepen.io
+codeproject.com
+codycross.info
+codycrossanswers.org
+coinbase.com
+coinmarketcap.com
+coinmill.com
+coldwellbankerhomes.com
+colgate.com
+collegeboard.org
+collinsdictionary.com
+colombia.com
+colorlib.com
+columbia.edu
+com.ru
+comandotorrents.com
+comicbook.com
+comingsoon.it
+commbank.com.au
+commentcamarche.com
+commentcamarche.net
+commonhealth.com.tw
+commonsensemedia.org
+companieshouse.gov.uk
+comparethemarket.com
+complex.com
+computerbild.de
+computerhope.com
+computerhoy.com
+computrabajo.com.co
+computrabajo.com.mx
+concepto.de
+conceptodefinicion.de
+confirmit.com
+conforama.fr
+conicyt.cl
+conjur.com.br
+conmishijos.com
+constantcontact.com
+consultant.ru
+consultaremedios.com.br
+consumer.es
+consumeraffairs.com
+consumerreports.org
+contabeis.com.br
+converse.com
+coocan.jp
+cookieandkate.com
+cookpad.com
+coolblue.nl
+coolinarika.com
+coolrom.com.au
+cooperativa.cl
+coppel.com
+cornell.edu
+correio24horas.com.br
+correiobraziliense.com.br
+correos.es
+corriere.it
+corrieredellosport.it
+cosme.net
+cosmo.ru
+cosmopolitan.com
+cosmopolitan.fr
+costco.ca
+costco.com
+coub.com
+countryliving.com
+coupang.com
+coupons.com
+coursehero.com
+coursera.org
+cox.com
+cr173.com
+cra-arc.gc.ca
+creativemarket.com
+credit-agricole.fr
+creditkarma.com
+creditmutuel.fr
+crhoy.com
+cricketwireless.com
+crictracker.com
+criteo.com
+cronica.com.ar
+cronista.com
+crunchbase.com
+crunchyroll.com
+crutchfield.com
+csdn.net
+csfd.cz
+csod.com
+css-tricks.com
+ctfile.com
+ctrip.com
+ctvnews.ca
+cuatro.com
+cucchiaio.it
+cuisineactuelle.fr
+cuisineaz.com
+culturamix.com
+cumhuriyet.com.tr
+cumlouder.com
+cure-naturali.it
+curiouscat.me
+currys.co.uk
+curseforge.com
+custhelp.com
+cutestat.com
+cvs.com
+cwb.gov.tw
+cyberleninka.ru
+cylex.de
+cyzowoman.com
+dafiti.com.br
+dafont.com
+dagbladet.no
+dagospia.com
+daily.co.jp
+dailycaller.com
+dailyhive.com
+dailyhunt.in
+dailymedicalinfo.com
+dailynews.co.th
+dailypost.ng
+dailystar.co.uk
+dailywire.com
+dallasnews.com
+danawa.com
+dangdang.com
+dantri.com.vn
+daraz.pk
+darty.com
+daserste.de
+dasoertliche.de
+dastelefonbuch.de
+davidsbridal.com
+dawn.com
+dazn.com
+dcard.tw
+dcinside.com
+dcm-b.jp
+ddnavi.com
+deadline.com
+deadspin.com
+dealabs.com
+debate.com.mx
+debenhams.com
+decathlon.es
+decathlon.fr
+decathlon.it
+deccanherald.com
+decolar.com
+decorfacil.com
+dedeman.ro
+deepl.com
+deezer.com
+definicion.de
+definicionabc.com
+deichmann.com
+deita.ru
+dek-d.com
+delfi.lt
+delfi.lv
+delish.com
+delta.com
+denfaminicogamer.jp
+dengeki.com
+dengekionline.com
+denik.cz
+depor.com
+derwesten.de
+descomplica.com.br
+desjardins.com
+deskgram.net
+desmos.com
+despegar.com.ar
+despegar.com.mx
+detmir.ru
+detran.mg.gov.br
+detran.sp.gov.br
+deunopostehoje.com
+deutschepost.de
+dexerto.com
+dexonline.ro
+dhl.com
+dhnet.be
+dhs.gov
+dialog.ua
+diamond.jp
+dianping.com
+diariobasta.com
+diariocorreo.pe
+diariodocentrodomundo.com.br
+diariolaprovinciasj.com
+diariomotor.com
+diarioonline.com.br
+diariopopular.com.ar
+dicio.com.br
+dicionarioinformal.com.br
+dickssportinggoods.com
+dict.cc
+dienmayxanh.com
+dietdoctor.com
+digi24.ro
+digikala.com
+digisport.ro
+digitalocean.com
+digitalspy.com
+digitaltrends.com
+dikaiologitika.gr
+dilei.it
+dillards.com
+directv.com
+diretta.it
+discogs.com
+discover.com
+discuss.com.hk
+disney.com
+disqus.com
+distractify.com
+divar.ir
+divinity.es
+divxtotal3.net
+diy.com
+diyadinnet.com
+diyanet.gov.tr
+dkn.tv
+dlsite.com
+dm.de
+dmkt-sp.jp
+dmzj.com
+dnaindia.com
+dndbeyond.com
+dndnha.com
+dnevnik.hr
+dnevnik.ru
+dni.ru
+dns-shop.ru
+dobreprogramy.pl
+docin.com
+docker.com
+docomo.ne.jp
+docsity.com
+doctissimo.fr
+doctolib.fr
+doctoralia.com.br
+doctoralia.com.mx
+doctoralia.es
+docusign.com
+doityourself.com
+doktersehat.com
+doktorsitesi.com
+doktortakvimi.com
+dollargeneral.com
+dollartree.com
+domain.com.au
+dominos.com
+domodi.pl
+donanimhaber.com
+donga.com
+donpornogratis.com
+donya-e-eqtesad.com
+doodle.com
+doordash.com
+doramatv.ru
+douban.com
+douyu.com
+doviz.com
+downdetector.com
+download.com.vn
+downloadastro.com
+doz.pl
+dpd.de
+dpreview.com
+dr.com.tr
+dr.dk
+draxe.com
+dream.co.id
+dreamstime.com
+dribbble.com
+drikpanchang.com
+drive2.ru
+drivemusic.me
+drogaraia.com.br
+droid-life.com
+drtuber.com
+drudgereport.com
+drugs.com
+dstv.com
+dsw.com
+dtac.co.th
+duckduckgo.com
+duden.de
+dummies.com
+duolingo.com
+dw.com
+dy2018.com
+dytt8.net
+dziennikzachodni.pl
+e-hentai.org
+e-katalog.ru
+e-map.ne.jp
+e-monsite.com
+e1.ru
+ea.com
+easeus.com
+easports.com
+eastday.com
+eastmoney.com
+easybib.com
+easyjet.com
+eater.com
+eb.mil.br
+eba.gov.tr
+ebah.com.br
+ebates.com
+ebay.ca
+ebay.ie
+ebc.net.tw
+ebscohost.com
+ecartelera.com
+economia.gov.br
+economictimes.com
+economist.com
+ecosia.org
+ecured.cu
+ed.gov
+eda.ru
+edf.fr
+edimdoma.ru
+edmodo.com
+edmunds.com
+edomex.gob.mx
+edreams.es
+educacion.es
+educamaisbrasil.com.br
+edupage.org
+edx.org
+ee.co.uk
+eenadu.net
+ef.com
+eg.ru
+egitimhane.com
+eiga.com
+eitb.eus
+ekitan.com
+ekstrabladet.dk
+el-nacional.com
+elbalad.news
+elbilad.net
+elbotola.com
+elcolombiano.com
+elcomercio.com
+elcomercio.pe
+elcorteingles.es
+eldestapeweb.com
+eldia.com
+eldiario.es
+eldiariony.com
+eldinamo.cl
+eldorado.ru
+eleconomista.es
+elektroda.pl
+elempleo.com
+elespanol.com
+elespectador.com
+elfagr.com
+elgenero.com
+elgrafico.mx
+elheraldo.co
+elimparcial.com
+elitedaily.com
+elkhabar.com
+elle.com
+elle.fr
+elmogaz.com
+elnuevodia.com
+elnuevoherald.com
+elo7.com.br
+elobservador.com.uy
+elpais.com.co
+elpais.com.uy
+elperiodico.com
+elsalvador.com
+elsevier.com
+elsevier.es
+elsol.com.ar
+elsoldemexico.com.mx
+elsoldepuebla.com.mx
+eltiempo.com
+eltiempo.es
+eltrecetv.com.ar
+eluniversal.com.co
+eluniverso.com
+elwatannews.com
+em.com.br
+emag.hu
+emedicinehealth.com
+emirates.com
+emlakkulisi.com
+emojipedia.org
+emol.com
+empflix.com
+empik.com
+empregos.com.br
+emuparadise.me
+en-hyouban.com
+en-japan.com
+encyclo.nl
+enfemenino.com
+eniro.se
+enjoei.com.br
+enotes.com
+enrt.eu
+ensonhaber.com
+enterprise.com
+entrepreneur.com
+enuygun.com
+envato.com
+eobuwie.com.pl
+eodev.com
+eonline.com
+epark.jp
+epey.com
+epicurious.com
+eplus.jp
+epochtimes.com
+eporner.com
+epttavm.com
+erail.in
+ero-video.net
+eroterest.net
+escavador.com
+eset.com
+eska.pl
+espn.com.br
+espn.com.mx
+espncricinfo.com
+espreso.rs
+esquire.com
+essen-und-trinken.de
+estacio.br
+estadao.com.br
+estantevirtual.com.br
+estrategiaconcursos.com.br
+estrepublicain.fr
+esuteru.com
+etonline.com
+etrade.com
+ettoday.net
+euro.com.pl
+eurogamer.net
+euronews.com
+europapress.es
+europe1.fr
+euroresidentes.com
+eurosport.com
+eurosport.fr
+eurosport.ru
+eurozpravy.cz
+eva.vn
+eventbrite.co.uk
+eventim.de
+evernote.com
+everydayhealth.com
+everydayhealth.com.tw
+evite.com
+ew.com
+exblog.jp
+excelsior.com.mx
+exchange-rates.org
+exhentai.org
+exito.com
+exlibrisgroup.com
+exoclick.com
+expansion.com
+expedia.ca
+expedia.co.uk
+experian.com
+express.de
+expressbydgoski.pl
+expressen.se
+expressilustrowany.pl
+expressvpn.com
+extra.com.br
+extratipp.com
+eyny.com
+eztv.io
+faapy.com
+facilisimo.com
+fakt.pl
+fakti.bg
+fakty.ua
+falabella.com
+falabella.com.co
+falabella.com.pe
+familydoctor.com.cn
+familyhandyman.com
+familysearch.org
+famitsu.com
+famousbirthdays.com
+fanatik.com.tr
+fanatik.ro
+fandango.lat
+fanfiction.net
+fang.com
+fanpage.it
+fantasti.cc
+fap18.net
+fapality.com
+farfetch.com
+farpost.ru
+farsnews.com
+fashion-press.net
+fashionnova.com
+fastcompany.com
+fastpeoplesearch.com
+fastshop.com.br
+fatakat.com
+fatalmodel.com
+fatosdesconhecidos.com.br
+fayerwayer.com
+faz.net
+fazenda.sp.gov.br
+fb.ru
+fda.gov
+fdj.fr
+feebee.com.tw
+feedly.com
+femina.hu
+femmeactuelle.fr
+feng.com
+fernsehserien.de
+fetlife.com
+fextralife.com
+fff.fr
+fgv.br
+fiat.com.br
+ficbook.net
+fidelity.com
+file-up.org
+filecrypt.cc
+filehippo.com
+filgoal.com
+film2movie.ws
+filmaffinity.com
+filmibeat.com
+filmow.com
+filmstarts.de
+fimela.com
+finance.ua
+financialexpress.com
+findagrave.com
+finddreamjobs.com
+findlaw.com
+fingerhut.com
+finishline.com
+finn.no
+firmasec.com
+firmy.cz
+firstcry.com
+firstpost.com
+fishki.net
+fitbit.com
+fiverr.com
+fixya.com
+flashback.org
+flashscore.com
+flaticon.com
+flightaware.com
+flightradar24.com
+flightstats.com
+flirt4free.com
+flo.com.tr
+floryday.com
+fluentu.com
+flypgs.com
+fmdos.cl
+fmkorea.com
+fmovies.to
+fnac.pt
+fnn.jp
+focus.cn
+focus.de
+folhadirigida.com.br
+folhavitoria.com.br
+fontawesome.com
+food52.com
+foodnetwork.com
+foody.vn
+fool.com
+foot01.com
+footlocker.com
+footmercato.net
+forbes.com.mx
+force.com
+ford.com
+forever21.com
+forgeofempires.com
+formula1.com
+formulatv.com
+forocoches.com
+fortnitetracker.com
+forum.hr
+fotocasa.es
+fotogramas.es
+fotomac.com.tr
+fotostrana.ru
+foursquare.com
+fox.com.tr
+foxbusiness.com
+foxporns.com
+foxsports.com
+foxsports.com.br
+foxtube.com
+fptshop.com.vn
+france.tv
+francebleu.fr
+frandroid.com
+fravega.com
+free-sex-video.net
+freearabsexx.com
+freebitco.in
+freecodecamp.org
+freejobalert.com
+freelancer.com
+freep.com
+freepik.com
+freshdesk.com
+fresherslive.com
+fril.jp
+friv.com
+frmtr.com
+from-ua.com
+ft.com
+fudan.edu.cn
+fujitv.co.jp
+funda.nl
+fuq.com
+furaffinity.net
+futbin.com
+futhead.com
+futura-sciences.com
+g2a.com
+gaadiwaadi.com
+gadgethacks.com
+gadgetsnow.com
+gala.de
+gala.fr
+game8.jp
+gameanswers.net
+gamebase.com.tw
+gameguardian.net
+gamek.vn
+gameloft.com
+gamepress.gg
+gamepressure.com
+gamer.com.tw
+gamerant.com
+gamerch.com
+gamersky.com
+gamesradar.com
+gamestop.com
+gamewith.jp
+gamma.nl
+ganeshaspeaks.com
+gap.com
+garanti.com.tr
+garbarino.com
+gardeningknowhow.com
+garena.com
+garena.tw
+garena.vn
+garmin.com
+gasbuddy.com
+gazeta.pl
+gazeta.ru
+gazetadopovo.com.br
+gazetaesportiva.com
+gazetaexpress.com
+gazetaonline.com.br
+gazetawroclawska.pl
+gazeteduvar.com.tr
+gazzetta.gr
+gazzetta.it
+gdz.ru
+gearpatrol.com
+geeksforgeeks.org
+geforce.com
+geico.com
+gelocal.it
+gencat.cat
+geneanet.org
+generation-nt.com
+geniuskitchen.com
+genk.vn
+genndi.com
+gentside.com
+geocities.jp
+geogebra.org
+gestiopolis.com
+getbootstrap.com
+getintopc.com
+getjar.com
+getninjas.com.br
+getpocket.com
+gettyimages.com
+getyourguide.com
+getyourguide.es
+ghanaweb.com
+giallozafferano.it
+gidfilm.ru
+giffgaff.com
+gifi.fr
+giga.de
+gigazine.net
+girlschannel.net
+gismeteo.ua
+github.io
+gitlab.com
+gittigidiyor.com
+gizmochina.com
+gizmodo.com
+gizmodo.jp
+gl5.ru
+glamour.es
+glassdoor.co.in
+gleam.io
+globalnews.ca
+globe.com.ph
+gls-group.eu
+gmail.com
+gmanetwork.com
+gmarket.co.kr
+gmw.cn
+gmx.net
+gnavi.co.jp
+gnula.nu
+godaddy.com
+godlife.com
+gofeminin.de
+gog.com
+gogoanime.io
+goibibo.com
+goindigo.in
+golos.ua
+gome.com.cn
+goo-net.com
+goodhousekeeping.com
+goodrx.com
+google.ae
+google.at
+google.az
+google.be
+google.bg
+google.ch
+google.cn
+google.co.ao
+google.co.il
+google.co.nz
+google.co.ve
+google.co.za
+google.com.ec
+google.com.eg
+google.com.hk
+google.com.kw
+google.com.ly
+google.com.my
+google.com.ng
+google.com.pe
+google.com.ph
+google.com.pk
+google.com.sa
+google.com.sg
+google.com.ua
+google.com.vn
+google.cz
+google.dk
+google.dz
+google.fi
+google.gr
+google.hr
+google.hu
+google.ie
+google.kz
+google.lk
+google.no
+google.ro
+google.rs
+google.se
+google.sk
+googleusercontent.com
+googlevideo.com
+googleweblight.com
+gopro.com
+gordonua.com
+gossip-tv.gr
+gosunoob.com
+gosuslugi.ru
+gotomeeting.com
+gotowebinar.com
+gotquestions.org
+gouv.qc.ca
+gov.hu
+governmentjobs.com
+grab.com
+gradeup.co
+grainger.com
+grammarly.com
+granbluefantasy.jp
+grancursosonline.com.br
+gratka.pl
+greasyfork.org
+greatandhra.com
+greenme.com.br
+greenme.it
+grid.id
+gridoto.com
+groupon.co.uk
+groupon.com
+groupon.fr
+groupon.it
+grubhub.com
+gry-online.pl
+gsmmaniak.pl
+gsp.ro
+gst.gov.in
+gstatic.com
+gtarcade.com
+gtrk.tv
+guarrasdelporno.xxx
+gucci.com
+guiainfantil.com
+guiamais.com.br
+guichevirtual.com.br
+guioteca.com
+guitarcenter.com
+gulf365.co
+gulfnews.com
+gumtree.co.za
+gumtree.com.au
+gunbroker.com
+guru99.com
+gutefrage.net
+gutekueche.at
+gva.es
+gyakorikerdesek.hu
+gyazo.com
+haber7.com
+haberturk.com
+habitaclia.com
+habr.com
+hackernoon.com
+halfords.com
+halktv.com.tr
+hamariweb.com
+hanihoh.com
+hanime.tv
+hankyung.com
+hao123.com
+happymod.com
+haraj.com.sa
+harborfreight.com
+harpersbazaar.com
+harvard.edu
+hasil.gov.my
+hasznaltauto.hu
+hateblo.jp
+hatena.ne.jp
+hatenablog.jp
+hatenadiary.jp
+havadurumu15gunluk.xyz
+havan.com.br
+hawaaworld.com
+hbo.com
+hclips.com
+hdblog.it
+hdlava.com
+hdpornvideo.xxx
+hdzog.com
+health.com
+health.zone
+health24.com
+healthgrades.com
+healthychildren.org
+heart.org
+heavy.com
+heilpraxisnet.de
+heise.de
+hellomagazine.com
+helpshift.com
+hepsiburada.com
+heroichollywood.com
+herokuapp.com
+hespress.com
+heureka.cz
+heureka.sk
+heuteporno.com
+hexun.com
+hgtv.com
+hh.ru
+hiamag.com
+himado.in
+hinative.com
+hinet.net
+hipertextual.com
+hipwee.com
+history.com
+hitomi.la
+hitosara.com
+hitta.se
+hk01.com
+hket.com
+hln.be
+hltv.org
+hm.com
+hmv.co.jp
+hnonline.sk
+hobbyconsolas.com
+hobbylobby.com
+hoc24.vn
+hochi.news
+hoerzu.de
+hogarmania.com
+hojeemdia.com.br
+hola.com
+holidaycheck.de
+hollisterco.com
+holloporn.win
+hollywoodlife.com
+hollywoodreporter.com
+homeadvisor.com
+homebase.co.uk
+homecenter.com.co
+homedepot.ca
+homedepot.com.mx
+homepornking.com
+homes.co.jp
+homes.com
+honda.co.jp
+honda.com
+honda.com.br
+honestdocs.co
+hootsuite.com
+hopkinsmedicine.org
+hornbach.de
+horoscope.com
+horriblesubs.info
+hostelworld.com
+hostgator.com
+hot-sex-tube.com
+hoteis.com
+hoteles.com
+hotelscan.com
+hotelurbano.com
+hotline.ua
+hotmart.com
+hotmovs.com
+hotnewhiphop.com
+hotnews.ro
+hotpads.com
+hottopic.com
+hotukdeals.com
+hotwire.com
+houzz.com
+howstuffworks.com
+howtogeek.com
+hpjav.tv
+hpplus.jp
+hrblock.com
+hsbc.com.hk
+hsn.com
+huaban.com
+huanqiu.com
+hubspot.com
+huffingtonpost.ca
+huffingtonpost.co.uk
+huffingtonpost.es
+huffingtonpost.fr
+huffingtonpost.it
+huffingtonpost.jp
+hugedomains.com
+hujiang.com
+humblebundle.com
+hungama.com
+hunker.com
+hupu.com
+hurriyet.com.tr
+hurriyetemlak.com
+huya.com
+hvg.hu
+hwupgrade.it
+hyatt.com
+hypebeast.com
+i.ua
+ibahia.com
+iberia.com
+ibm.com
+ibps.in
+ibtimes.co.in
+ica.se
+icarros.com.br
+iceporn.com
+icims.com
+icotto.jp
+ideal.es
+idealista.com
+idealista.it
+idealo.de
+idnes.cz
+idntimes.com
+ieee.org
+iefimerida.gr
+iett.istanbul
+ifeng.com
+ifixit.com
+iflix.com
+iflscience.com
+ifood.com.br
+ig.com.br
+igg-games.com
+iheart.com
+iherb.com
+ihg.com
+iko-yo.net
+ikyu.com
+ilacrehberi.com
+ilbe.com
+ilfattoquotidiano.it
+ilgiornale.it
+illinois.edu
+ilmessaggero.it
+ilmkidunya.com
+ilpost.it
+ilsole24ore.com
+iltalehti.fi
+imagebam.com
+imagefap.com
+imgflip.com
+immobiliare.it
+immobilienscout24.de
+immonet.de
+immowelt.de
+imooc.com
+imore.com
+imovelweb.com.br
+impots.gouv.fr
+imss.gob.mx
+in.gov
+in.gr
+inc.com
+incruit.com
+indeed.co.in
+indeed.co.uk
+indeed.com.br
+indeed.com.mx
+indeed.es
+indeed.fr
+independent.co.uk
+independent.ie
+index.hr
+index.hu
+india.com
+indianexpress.com
+indianporn.xxx
+indianrail.gov.in
+indianrailways.gov.in
+indiapost.gov.in
+indiarailinfo.com
+indiaresults.com
+indiatvnews.com
+indiegogo.com
+indoxxi.bz
+indoxxi.cx
+inep.gov.br
+info.com
+info7.mx
+infoescola.com
+infojobs.com.br
+infojobs.net
+infomoney.com.br
+infonu.nl
+infopedia.pt
+infor.pl
+informer.com
+informer.rs
+infoseek.co.jp
+infourok.ru
+ing.nl
+ingresso.com
+ingressorapido.com.br
+inoreader.com
+inpost.pl
+inps.it
+inquirer.net
+inss.gov.br
+insta-stalker.com
+instacart.com
+instant-gaming.com
+instantcheckmate.com
+intel.com
+intentmedia.net
+interfax.ru
+internethaber.com
+interpark.com
+intoday.in
+inven.co.kr
+inverse.com
+invisionapp.com
+iobit.com
+iol.co.za
+iol.pt
+iplt20.com
+ipornogratis.xxx
+ipornovideos.xxx
+ipornox.xxx
+iprima.cz
+iqiyi.com
+iqoption.com
+irctc.co.in
+irishtimes.com
+is.fi
+isalna.com
+isciii.es
+iskur.gov.tr
+islamicfinder.org
+islamway.net
+islamweb.net
+ismedia.jp
+isna.ir
+issuu.com
+istockphoto.com
+istoe.com.br
+it168.com
+itc.ua
+itch.io
+its.porn
+itv.com
+ivi.ru
+ixbt.com
+ixl.com
+ixxx.com
+iyiou.com
+iz.ru
+j-cast.com
+j-lyric.net
+jagran.com
+jagranjosh.com
+jal.co.jp
+jalan.net
+jalantikus.com
+jalopnik.com
+jameda.de
+jamieoliver.com
+jandan.net
+japanpost.jp
+java.com
+javatpoint.com
+javbus.com
+javdoe.com
+javfor.me
+javmost.com
+javzz.net
+jb51.net
+jbhifi.com.au
+jcb.co.jp
+jcpenney.com
+jcrew.com
+jd.com
+jdsports.co.uk
+jeanmarcmorandini.com
+jetblue.com
+jetbrains.com
+jetcost.com
+jetstar.com
+jeuxvideo.com
+jezebel.com
+jiameng.com
+jianshu.com
+jiji.com
+jimdo.com
+jimmyjohns.com
+jin115.com
+jio.com
+jiosaavn.com
+jisin.jp
+jizzbunker.com
+jjwxc.net
+jma.go.jp
+jmty.jp
+jmw.com.cn
+jn.pt
+joann.com
+jobstreet.co.id
+jobtome.com
+jofogas.hu
+johnlewis.com
+joinhoney.com
+joins.com
+jooble.org
+jora.com
+jornada.com.mx
+jornaldebrasilia.com.br
+jornalggn.com.br
+jorudan.co.jp
+journaldemontreal.com
+journaldesfemmes.fr
+journaldugeek.com
+jovemnerd.com.br
+jovencitas.gratis
+jpnn.com
+jpnumber.com
+jprime.jp
+jquery.com
+jqw.com
+jr-central.co.jp
+jr-odekake.net
+jra.go.jp
+jra.jp
+jreast.co.jp
+jrj.com.cn
+jstor.org
+jtb.co.jp
+juegos.com
+jugantor.com
+jugem.jp
+jumia.com.ng
+juntadeandalucia.es
+jus.com.br
+jusbrasil.com.br
+just-eat.co.uk
+justanswer.com
+justia.com
+justporno.tv
+justwatch.com
+jutarnji.hr
+k-manga.jp
+k2s.cc
+kabum.com.br
+kadinlarkulubu.com
+kafan.cn
+kafeteria.pl
+kaidee.com
+kaiserpermanente.org
+kalunga.com.br
+kamigame.jp
+kamupersoneli.net
+kanald.com.tr
+kanobu.ru
+kanui.com.br
+kapanlagi.com
+kapook.com
+kariyer.net
+kaskus.co.id
+kaspersky.com
+katestube.com
+kaufda.de
+kbb.com
+keezmovies.com
+keizai.biz
+kemdikbud.go.id
+keonhacai.net
+ketqua.net
+khaberni.com
+khaleejtimes.com
+khaosod.co.th
+khoai.tv
+kia.com
+kiabi.com
+kicker.de
+kickstarter.com
+kidshealth.org
+kidstaff.com.ua
+kiji.is
+kijiji.ca
+kijiji.it
+kimovil.com
+kinarino.jp
+kino-teatr.ru
+kino.de
+kinokrad.co
+kissanime.ru
+kissasian.sh
+kissmanga.com
+kisspng.com
+kitapyurdu.com
+klarna.com
+klikbca.com
+klm.com
+klook.com
+kmart.com.au
+knowing-jesus.com
+knowyourmeme.com
+kochbar.de
+kommersant.ru
+kompasiana.com
+kompass.com
+kompoz.me
+komputerswiat.pl
+kooora.com
+koreaboo.com
+korrespondent.net
+kotak.com
+kotaku.com
+koton.com
+kp.org
+kp.ua
+kroger.com
+krone.at
+kruidvat.nl
+ksl.com
+ksu.edu.sa
+kumparan.com
+kundelik.kz
+kupujemprodajem.com
+kurashi-no.jp
+kurashinista.jp
+kurir.rs
+kuronekoyamato.co.jp
+kwestiasmaku.com
+l-tike.com
+labirint.ru
+lacentrale.fr
+lachainemeteo.com
+lacuarta.com
+lacuerda.net
+ladbible.com
+ladenzeile.de
+ladepeche.fr
+lafm.com.co
+laleggepertutti.it
+lamoda.ru
+lanacion.com.ar
+lance.com.br
+lanetanoticias.com
+laodong.vn
+laopinion.com
+lapatilla.com
+laposte.fr
+laprensa.hn
+lapresse.ca
+laprovence.com
+laptopmag.com
+larazon.es
+laredoute.fr
+larepublica.pe
+largeporntube.com
+larousse.fr
+las2orillas.co
+lasestrellas.tv
+lasexta.com
+lasillarota.com
+lasprovincias.es
+last.fm
+lastampa.it
+lastminute.com
+lastpass.com
+latam.com
+latercera.com
+latimes.com
+lavanguardia.com
+laverdadnoticias.com
+lavoixdunord.fr
+lavoz.com.ar
+lavozdegalicia.es
+lazada.co.id
+lazada.com.my
+lazada.com.ph
+lazada.vn
+lazi.vn
+lci.fr
+lcwaikiki.com
+ldblog.jp
+lds.org
+le10sport.com
+le360.ma
+leafly.com
+leagueofgraphs.com
+lecker.de
+lecturas.com
+ledauphine.com
+lefigaro.fr
+legacy.com
+leggo.it
+legit.ng
+lego.com
+lenovo.com
+lentainform.com
+leo.org
+leparisien.fr
+lepoint.fr
+leprogres.fr
+lequipe.fr
+leroymerlin.com.br
+leroymerlin.es
+leroymerlin.fr
+leroymerlin.it
+leroymerlin.ru
+lesechos.fr
+lesnumeriques.com
+lesoir.be
+letgo.com
+letras.com
+letras.mus.br
+letribunaldunet.fr
+lettera43.it
+lettuceclub.net
+levante-emv.com
+levi.com
+lexpress.fr
+lg.com
+lianjia.com
+liberation.fr
+libero.it
+liberoquotidiano.it
+libertaddigital.com
+libertatea.ro
+lichess.org
+licindia.in
+lider.cl
+lidl.de
+lidl.es
+lieferando.de
+liepin.com
+life.hu
+life.ru
+lifeder.com
+lifehack.org
+lifehacker.com
+lifehacker.jp
+lifehacker.ru
+lifo.gr
+liga.net
+lightinthebox.com
+lineblog.me
+linguee.com
+linguee.com.br
+linguee.de
+linguee.es
+linguee.fr
+linkshrink.net
+linternaute.com
+linternaute.fr
+linustechtips.com
+lipstickalley.com
+liputan6.com
+liquipedia.net
+list-manage.com
+listindiario.com
+literotica.com
+litres.ru
+live.net
+livechatinc.com
+livehindustan.com
+liveinternet.ru
+livejasmin.com
+liveleak.com
+livelib.ru
+livemint.com
+livenation.com
+liverpool.com.mx
+liverpoolecho.co.uk
+livescience.com
+livetv.sx
+lmneuquen.com
+lne.es
+lnk.to
+lofter.com
+logic-immo.com
+logistics.dhl
+logitech.com
+lohaco.jp
+loigiaihay.com
+lojadomecanico.com.br
+lojasrenner.com.br
+lolesports.com
+lonelyplanet.com
+longdo.com
+looper.com
+loopnet.com
+lordfilms.tv
+losandes.com.ar
+lostfilm.tv
+loteriasyapuestas.es
+lotterypost.com
+loudwire.com
+louisvuitton.com
+lovemondays.com.br
+lovetoknow.com
+lowes.com
+ltn.com.tw
+lufthansa.com
+lulus.com
+lumenlearning.com
+lun.com
+lyft.com
+lyricstranslate.com
+maariv.co.il
+macaro-ni.jp
+mackolik.com
+macrumors.com
+macys.com
+made-in-china.com
+madeiramadeira.com.br
+madrid.org
+maduras.xxx
+magazineluiza.com.br
+magicbricks.com
+magicmaman.com
+mail.com
+mailchi.mp
+mailchimp.com
+mainichi.jp
+maisonsdumonde.com
+makeleio.gr
+makeup.com.ua
+makeuseof.com
+mako.co.il
+malaysiakini.com
+mamari.jp
+mamastar.jp
+manchestereveningnews.co.uk
+mangakakalot.com
+manganelo.com
+mangarock.com
+mango.com
+manhuagui.com
+manomano.es
+manomano.fr
+manomano.it
+manoramaonline.com
+manta.com
+mantan-web.jp
+manualslib.com
+manyvids.com
+mapion.co.jp
+mappy.com
+mapquest.com
+mapsofindia.com
+mapy.cz
+marica.bg
+marieclaire.com
+marieclaire.fr
+marinetraffic.com
+marisa.com.br
+marketwatch.com
+marksandspencer.com
+marktplaats.nl
+marmiton.org
+marriott.com
+marthastewart.com
+marvel.com
+mashable.com
+masrawy.com
+matalan.co.uk
+match.com
+mathrubhumi.com
+mathsisfun.com
+mathway.com
+mathworks.com
+matichon.co.th
+matomedane.jp
+matterport.com
+maxmilhas.com.br
+maxpreps.com
+maybank2u.com.my
+mbank.pl
+mbga.jp
+mcafee.com
+mcdonalds.co.jp
+mcdonalds.com
+mcetv.fr
+mdpr.jp
+mdr.de
+me.me
+meb.k12.tr
+mec.es
+mec.gov.br
+mecha.cc
+medaboutme.ru
+mediaexpert.pl
+mediamarkt.com.tr
+mediamarkt.de
+mediamarkt.es
+mediamarkt.nl
+mediamarkt.pl
+mediaset.it
+mediaworld.it
+medicalnewstoday.com
+medicinanet.com.br
+medicinenet.com
+medicines.org.uk
+medicitalia.it
+mediotiempo.com
+medlineplus.gov
+medportal.ru
+medscape.com
+meduza.io
+meetup.com
+mega.cl
+megafon.ru
+megatube.xxx
+meinestadt.de
+meituan.com
+mejorconsalud.com
+mello.me
+melty.fr
+memurlar.net
+menards.com
+mensagenscomamor.com
+menshealth.com
+mentalfloss.com
+merca2.es
+mercadolibre.cl
+mercadolibre.com.ec
+mercadolibre.com.pe
+mercadolibre.com.uy
+mercadolibre.com.ve
+mercadolivre.com
+mercadopago.com
+mercadopago.com.br
+merdeka.com
+merkur.de
+merriam-webster.com
+metacritic.com
+meteo.gr
+meteofrance.com
+meteored.com.ar
+meteored.mx
+metoffice.gov.uk
+metric-conversions.org
+metro.co.uk
+metro.tokyo.jp
+metroecuador.com.ec
+metrojornal.com.br
+metrolagu.online
+metrolyrics.com
+metropcs.com
+metropoles.com
+meutimao.com.br
+mgid.com
+mgronline.com
+mgtv.com
+mheducation.com
+mhlw.go.jp
+mi.tv
+miamiherald.com
+mibebeyyo.com
+michaels.com
+michigan.gov
+mid-day.com
+midiamax.com.br
+midilibre.fr
+migalhas.com.br
+migros.com.tr
+mijnwoordenboek.nl
+milanuncios.com
+milenio.com
+mileroticos.com
+milffox.com
+mindmegette.hu
+minecraft.net
+minecraftforum.net
+minfin.com.ua
+minhavida.com.br
+minhngoc.net.vn
+minkou.jp
+minube.com
+minuto30.com
+minutouno.com
+mirror.co.uk
+mis-suenos.org
+misionesonline.net
+mismarcadores.com
+mit.edu
+mitsui-shopping-park.com
+mitula.com.br
+miui.com
+mixcloud.com
+mixer.com
+mixi.jp
+mixvale.com.br
+mizuhobank.co.jp
+mk.co.kr
+mob.org
+mobafire.com
+mobly.com.br
+modanisa.com
+modapkdown.com
+moe.gov.my
+moe.gov.sa
+moi.gov.sa
+mojang.com
+mojim.com
+momjunction.com
+momoshop.com.tw
+monday.com
+mondo.rs
+monetizze.com.br
+money.pl
+moneycontrol.com
+moneysavingexpert.com
+moneysupermarket.com
+monotaro.com
+monster.com
+monsterindia.com
+moovitapp.com
+morhipo.com
+morrisons.com
+mos.ru
+mosaiquefm.net
+mosreg.ru
+motherless.com
+motogp.com
+motor-talk.de
+motor1.com
+motorola.com
+motorola.com.br
+motorsport.com
+mouthshut.com
+moviefone.com
+moviepilot.de
+movieweb.com
+movistar.cl
+movistar.com
+movistar.com.ar
+movistar.es
+movistarplus.es
+movoto.com
+mozilla.org
+mp.pl
+mp3-youtube.download
+mp3indirdur.mobi
+mp3party.net
+mp3xd.com
+mrvideospornogratis.xxx
+msdmanuals.com
+msi.com
+msk.ru
+msnbc.com
+mt.co.kr
+mthai.com
+mtime.com
+mts.ru
+mtv.it
+mtvuutiset.fi
+mudah.my
+mufg.jp
+muji.net
+multiurok.ru
+mumsnet.com
+mumyazh.com
+mundohispanico.com
+muratordom.pl
+musescore.com
+musica.com
+musixmatch.com
+muyzorras.com
+muzikmp3indir.com
+muzofond.fm
+mvideo.ru
+my-best.com
+my-personaltrainer.it
+myanmarload.com
+mydealz.de
+mydiba.xyz
+mydramalist.com
+mydrivers.com
+myfitnesspal.com
+myfreecams.com
+myheritage.com
+myjitsu.jp
+mylust.com
+mymovies.it
+myntra.com
+myrecipes.com
+myshopify.com
+myspace.com
+mysql.com
+mytoys.de
+myway.com
+myworkdayjobs.com
+n-tv.de
+n1info.com
+nadaguides.com
+naewna.com
+nairaland.com
+nalog.ru
+namasha.com
+namazzamani.net
+nameberry.com
+namecheap.com
+namnak.com
+nap-camp.com
+napi.hu
+naranja.com
+narcity.com
+narod.ru
+nasa.gov
+naszemiasto.pl
+nat.gov.tw
+natalie.mu
+nate.com
+natemat.pl
+nation.co.ke
+nationalgeographic.com
+nationalinterest.org
+nationalrail.co.uk
+natura.com.br
+natura.net
+nature.com
+naukri.com
+navitime.co.jp
+nbc.com
+ncaa.com
+nczas.com
+ndr.de
+neaselida.gr
+nefisyemektarifleri.com
+negocio.site
+neobux.com
+neoldu.com
+nerdwallet.com
+nesine.com
+nespresso.com
+nest.com
+net.com.br
+net.hr
+netcombo.com.br
+netdoctor.co.uk
+netdoktor.de
+netgear.com
+netkeiba.com
+netmoms.de
+netmums.com
+netshoes.com.br
+netsuite.com
+nettavisen.no
+nettruyen.com
+netzwelt.de
+newatlas.com
+newchic.com
+newegg.com
+newidea.com.au
+newlook.com
+news-postseven.com
+news-r.ru
+news.com.au
+news24.com
+news247.gr
+newsbeast.gr
+newsbomb.gr
+newsbytesapp.com
+newsit.gr
+newsmth.net
+newsnow.co.uk
+newsweek.com
+newsweekjapan.jp
+newyorker.com
+nexon.com
+next.co.uk
+nexusmods.com
+nfl.com
+nga.cn
+ngoisao.net
+nhaccuatui.com
+nhentai.net
+nhl.com
+nicematin.com
+niche.com
+nickfinder.com
+nickiswift.com
+nieuwsblad.be
+nike.com.br
+nikkan-gendai.com
+nikkeibp.co.jp
+nine.com.au
+ninisite.com
+nintendo.co.jp
+nintendo.com
+nintendolife.com
+nit.pt
+nitori-net.jp
+nj.com
+njuskalo.hr
+nlcafe.hu
+nld.com.vn
+nme.com
+nnu.ng
+noaa.gov
+nocookie.net
+nokia.com
+nolo.com
+nordstrom.com
+nordstromrack.com
+nordvpn.com
+norton.com
+norwegian.com
+nos.nl
+nosalty.hu
+note.mu
+notebookcheck.net
+noticiasaominuto.com
+nouvelobs.com
+nova.cz
+novaescola.org.br
+novaposhta.ua
+novinky.cz
+novosti.rs
+nownews.com
+nowtv.com
+npmjs.com
+npr.org
+nps.gov
+nptel.ac.in
+nrc.nl
+nrk.no
+ns.nl
+nsportal.ru
+nsw.gov.au
+nto.pl
+nttdocomo.co.jp
+ntv.co.jp
+ntv.com.tr
+ntv.ru
+ntvspor.net
+nu.nl
+nudevista.club
+nuevamujer.com
+numerama.com
+nur.kz
+nurxxx.mobi
+nutaku.net
+nuvid.com
+nv.ua
+nvsp.in
+ny.gov
+nyaa.si
+nyc.gov
+nydailynews.com
+nykaa.com
+nymag.com
+nyu.edu
+nzherald.co.nz
+o2.co.uk
+o2.pl
+o2online.de
+oa.com
+oantagonista.com
+oath.com
+obi.de
+obilet.com
+obozrevatel.com
+observador.pt
+observator.tv
+occ.com.mx
+oceanofgames.com
+oceans-nadia.com
+odatv.com
+odishatv.in
+oe24.at
+oeffnungszeitenbuch.de
+offers.com
+offerup.com
+office.net
+officedepot.com
+ofuxico.com.br
+ohio.gov
+ohmymag.com
+oi.com.br
+ojo.pe
+okcupid.com
+okezone.com
+okta.com
+ole.com.ar
+olhardigital.com.br
+olivegarden.com
+olx.bg
+olx.com.ar
+olx.com.co
+olx.com.eg
+olx.com.pk
+olx.in
+olx.ph
+olx.pt
+olx.ro
+omegle.com
+omelete.com.br
+omni7.jp
+on.cc
+onedio.com
+oneindia.com
+oneplus.com
+online-convert.com
+onlinedown.net
+onliner.by
+onlineradiobox.com
+onlyfans.com
+onthemarket.com
+ooreka.fr
+op9.com.br
+openrice.com
+opensooq.com
+opensubtitles.org
+opentable.com
+opera.com
+opinautos.com
+opopular.com.br
+opossumsauce.com
+opovo.com.br
+oppo.com
+optus.com.au
+oracle.com
+orange.es
+orange.pl
+oraridiapertura24.it
+orbitz.com
+oreilly.com
+oreillyauto.com
+orf.at
+org.ru
+oricon.co.jp
+orientaltrading.com
+oriflame.com
+origin.com
+origo.hu
+os.tc
+oscaro.com
+oschina.net
+osym.gov.tr
+otempo.com.br
+otodom.pl
+otomoto.pl
+ouedkniss.com
+ouest-france.fr
+oui.sncf
+ouo.io
+oup.com
+outbrain.com
+outlook.com
+ouvirmusica.com.br
+overdrive.com
+overleaf.com
+overstock.com
+owlcation.com
+oxforddictionaries.com
+ozmall.co.jp
+ozon.ru
+p-world.co.jp
+pa.gov
+padlet.com
+pagenews.gr
+pagesix.com
+pagesjaunes.fr
+pagina12.com.ar
+paginasamarillas.com.ar
+paginasamarillas.com.co
+paginasamarillas.es
+paginebianche.it
+paginegialle.it
+paguemenos.com.br
+paheal.net
+paisabazaar.com
+pajak.go.id
+pan-pan.co
+panasonic.com
+panasonic.jp
+panda.tv
+pandora.com
+pandora.net
+panerabread.com
+panet.co.il
+papajohns.com
+papy.co.jp
+parenting.pl
+parents.com
+parents.fr
+paris.cl
+parismatch.com
+parliament.uk
+partsgeek.com
+partycity.com
+paruvendu.fr
+pasion.com
+passeportsante.net
+pastebin.com
+patch.com
+pathofexile.com
+payoneer.com
+payscale.com
+paytm.com
+paytm.in
+pbs.org
+pc6.com
+pcbaby.com.cn
+pccomponentes.com
+pcgamer.com
+pcgamesn.com
+pch.com
+pchome.com.tw
+pciconcursos.com.br
+pcmag.com
+pcpartpicker.com
+pcstore.com.tw
+pcworld.com
+pdalife.ru
+pdfdrive.com
+pdffiller.com
+pearsoncmg.com
+pearsoned.com
+peing.net
+peixeurbano.com.br
+pelispedia.tv
+pelisplus.to
+pensador.com
+people.com
+people.com.cn
+peopleenespanol.com
+perfil.com
+periodistadigital.com
+persgroep.net
+personal.com.ar
+peru21.pe
+pervclips.com
+petardas.com
+petco.com
+petfinder.com
+petlove.com.br
+petmd.com
+petsmart.com
+pexels.com
+pgatour.com
+phimmoi.net
+phimsexnhanh.net
+phonandroid.com
+phonearena.com
+photoacompanhantes.com
+php.net
+pia.jp
+piazza.com
+picclick.com
+picdeer.com
+picgra.com
+pictame.com
+pikabu.ru
+pikio.pl
+piluli.ru
+pinflix.com
+pinimg.com
+pinkvilla.com
+pinky-media.jp
+pinterest.ca
+pinterest.cl
+pinterest.co.kr
+pinterest.com.au
+pinterest.com.mx
+pinterest.de
+pinterest.fr
+pinterest.it
+pinterest.jp
+pinterest.ph
+pinterest.pt
+pinterest.ru
+pirateproxy.id
+pisos.com
+pistonheads.com
+pitchfork.com
+pixabay.com
+pixlr.com
+pizzahut.com
+pku.edu.cn
+plala.or.jp
+planalto.gov.br
+planetabrasileiro.com
+planetminecraft.com
+plannedparenthood.org
+play.pl
+playbuzz.com
+player.pl
+playground.ru
+playvk.com
+plejada.pl
+plex.tv
+plotek.pl
+plurk.com
+plus.pl
+pluska.sk
+pnc.com
+pngtree.com
+pochta.ru
+poczta-polska.pl
+podrobnosti.ua
+poetryfoundation.org
+poezdato.net
+pof.com
+point2homes.com
+pokemon.com
+pole-emploi.fr
+policybazaar.com
+politeka.net
+politico.mx
+polki.pl
+pomorska.pl
+pomponik.pl
+pons.com
+pontofrio.com.br
+popculture.com
+popsugar.com
+popularmechanics.com
+poradnikzdrowie.pl
+porn-plus.com
+porn.biz
+porn.com
+porn.es
+porn18sex.com
+porn300.com
+porn555.com
+porn7.xxx
+pornadoo.com
+porndick.org
+porndoe.com
+porndroids.com
+porngames.adult
+pornhat.com
+pornhd.com
+pornhdvideos.net
+pornhubpremium.com
+pornicom.com
+pornmd.com
+pornocarioca.com
+pornodoido.com
+pornohirsch.com
+pornolab.net
+pornolandia.xxx
+pornomovies.com
+pornoreino.com
+pornorussia.tv
+pornoxo.com
+pornpics.com
+pornq.com
+porntrex.com
+porntube.com
+porntv.com
+pornwatchers.com
+pornwhite.com
+pornxs.com
+portaldoholanda.com.br
+portaleducacao.com.br
+portfolio.hu
+poshmark.com
+posta.com.tr
+postbank.de
+poste.it
+posthaus.com.br
+postimees.ee
+postmates.com
+postnl.nl
+posttoday.com
+pottermore.com
+povar.ru
+povarenok.ru
+powerschool.com
+pozdravok.ru
+pptv.com
+pptvhd36.com
+ppy.sh
+practo.com
+pracuj.pl
+pravda.com.ua
+pravda.sk
+prefeitura.sp.gov.br
+premierleague.com
+president.jp
+presse-citron.net
+presseportal.de
+pressreader.com
+prevention.com
+priberam.org
+priceline.com
+priceprice.com
+priceza.com
+primark.com
+primiciasya.com
+privalia.com
+privatbank.ua
+prnewswire.com
+prnt.sc
+proceso.com.mx
+programme-television.org
+progressive.com
+prokerala.com
+prom.ua
+promoqui.it
+pronto.com
+proprofs.com
+proquest.com
+prosieben.de
+prothomalo.com
+protothema.gr
+provincial.com
+prtimes.jp
+przyslijprzepis.pl
+psicologia-online.com
+psicologiaymente.com
+psu.edu
+psychologytoday.com
+ptt.cc
+ptt.gov.tr
+pubg.com
+publi24.ro
+public.fr
+publico.es
+publico.pt
+publimetro.cl
+publimetro.co
+publimetro.com.mx
+publinews.gt
+publix.com
+pudelek.pl
+puhutv.com
+pullandbear.com
+pulzo.com
+puma.com
+punchng.com
+purdue.edu
+purelovers.com
+purepeople.com
+purepeople.com.br
+puritanas.com
+pushsquare.com
+putasdesnudos.com
+putlockers.co
+pwn.pl
+python.org
+qatarairways.com
+qconcursos.com
+qichacha.com
+qidian.com
+qihoo.com
+qiita.com
+qiwi.com
+qoo10.jp
+quattroruote.it
+querobolsa.com.br
+queropassagem.com.br
+quien.com
+quikr.com
+quizizz.com
+quizur.com
+qunar.com
+quoka.de
+quotidiano.net
+qvc.com
+qwant.com
+qz.com
+r7.com
+rabobank.nl
+rabota.ua
+rad-ar.or.jp
+radaronline.com
+radio-canada.ca
+radio.com
+radioagricultura.cl
+radioformula.com.mx
+radiosvoboda.org
+radiotimes.com
+radiozet.pl
+rae.es
+raftaar.in
+rai.it
+railyatri.in
+raiplay.it
+rajasthan.gov.in
+rajwap.xyz
+rakuten-bank.co.jp
+rakuten.com
+rakuten.com.tw
+rakuten.ne.jp
+rapidgator.net
+rapidvideo.com
+rappler.com
+rarbg.to
+rarbgprx.org
+ratemyprofessors.com
+ray-ban.com
+razer.com
+rbc.ru
+rbc.ua
+rbcroyalbank.com
+rcnradio.com
+rd.com
+rd.go.th
+rd1.com.br
+readms.net
+readthedocs.io
+real.de
+realclearpolitics.com
+realestate.com.au
+realsimple.com
+realsound.jp
+realtor.com
+recantodasletras.com.br
+recipetineats.com
+reclameaqui.com.br
+record.pt
+recruit.co.jp
+redalyc.org
+redbox.com
+redbubble.com
+redbull.com
+redbus.in
+redd.it
+redfin.com
+redflagdeals.com
+redhdtube.xxx
+rediff.com
+rednet.cn
+redporn.xxx
+redtube.com.br
+redwap.me
+redwap.pro
+reed.co.uk
+refinery29.com
+regeneracion.mx
+regmovies.com
+regnum.ru
+rei.com
+remax.com
+renfe.com
+rent.com
+rentalcars.com
+repairpal.com
+replyua.net
+reporteindigo.com
+repubblica.it
+research.net
+reserved.com
+response.jp
+resultados.com
+retailmenot.com
+retty.me
+reuters.com
+revdl.com
+reverb.com
+revistaforum.com.br
+rewe.de
+rexdl.com
+rhymezone.com
+ria.com
+ria.ru
+riachuelo.com.br
+riafan.ru
+ridus.ru
+rikunabi.com
+rincondelvago.com
+ring.com
+ringon.pro
+riotgames.com
+ripley.cl
+riverisland.com
+rjeem.com
+rk.com
+rlsnet.ru
+rmf24.pl
+rockauto.com
+rocketnews24.com
+rockol.it
+rockpapershotgun.com
+rockstargames.com
+rogers.com
+roku.com
+roll20.net
+rollingstone.com
+rome2rio.com
+romper.com
+routard.com
+royalcaribbean.com
+royalmail.com
+rozklad-pkp.pl
+rp-online.de
+rp.pl
+rp5.ru
+rpfonlinereg.org
+rpp.pe
+rsc.org
+rst.ua
+rt.ru
+rtbf.be
+rte.ie
+rtl.de
+rtl.fr
+rtl.hr
+rtlboulevard.nl
+rtlnieuws.nl
+rtve.es
+ru-clip.net
+rueducommerce.fr
+rule34.xxx
+ruliweb.com
+rund-ums-baby.de
+runnersworld.com
+runoob.com
+rus.ec
+rushporn.com
+russianfood.com
+rusvesna.su
+ruten.com.tw
+rutracker.org
+rutube.ru
+rxlist.com
+ryanair.com
+rzd.ru
+sabq.org
+safety.google
+sagawa-exp.co.jp
+sagepub.com
+saglik.gov.tr
+sainsburys.co.uk
+saisoncard.co.jp
+sakshi.com
+sakura.ne.jp
+salamdl.info
+salesforce.com
+sallybeauty.com
+salon.com
+sambaporno.com
+sammobile.com
+samsclub.com
+sanborns.com.mx
+sanitas.es
+sankei.com
+sanspo.com
+santander.com.br
+santemagazine.fr
+santeplusmag.com
+sap.com
+sapo.pt
+saraba1st.com
+saraiva.com.br
+sarayanews.com
+sarkariexam.com
+sat.gob.mx
+saturn.de
+saude.gov.br
+sayidaty.net
+sbazar.cz
+sberbank.ru
+sbi.co.in
+sbisec.co.jp
+sbrf.ru
+sbs.co.kr
+sbs.com.au
+sbt.com.br
+scarymommy.com
+scholastic.com
+schwab.com
+sciaga.pl
+scielo.br
+sciencedaily.com
+sciencing.com
+scientificamerican.com
+scmp.com
+scol.com.cn
+scotiabank.com
+screenrant.com
+screwfix.com
+scroll.in
+sdamgia.ru
+sdna.gr
+sdpnoticias.com
+se.pl
+searchnow.com
+sears.com
+sears.com.mx
+seasonvar.ru
+seatgeek.com
+seccionamarilla.com.mx
+secreto.site
+securecafe.com
+secureserver.net
+seek.com.au
+seekingalpha.com
+seesaa.net
+sefamerve.com
+sefon.me
+seg-social.es
+segmentfault.com
+segodnya.ua
+segundamano.mx
+sej.co.jp
+seloger.com
+semana.com
+semanticscholar.org
+senac.br
+senado.leg.br
+sendo.vn
+sensacine.com
+sep.gob.mx
+sephora.com
+seriouseats.com
+serverfault.com
+service-now.com
+service-public.fr
+service.gov.uk
+serviporno.com
+seslisozluk.net
+setare.com
+setlist.fm
+setn.com
+sex.com
+sexporntube.us
+sexstories.com
+sexu.com
+sexvid.xxx
+seznam.cz
+sf-express.com
+sfatulmedicului.ro
+sfr.fr
+shabdkosh.com
+shadbase.com
+shameless.com
+share-videos.se
+sharecare.com
+sharepoint.com
+shazam.com
+shein.com
+sheknows.com
+sheypoor.com
+shiftdelete.net
+shiksha.com
+shindanmaker.com
+shine.com
+shmoop.com
+shop-apotheke.com
+shop-pro.jp
+shopclues.com
+shopdisney.com
+shopee.co.id
+shopee.com.my
+shopee.ph
+shopee.tw
+shopee.vn
+shopify.com
+shoponn.in
+shoptime.com.br
+showtv.com.tr
+shueisha.co.jp
+shufoo.net
+shutterfly.com
+si.com
+siamsport.co.th
+significados.com
+significados.com.br
+signupgenius.com
+sii.cl
+sikayetvar.com
+simplyhired.com
+simplyrecipes.com
+sina.cn
+sina.com.cn
+sinaimg.cn
+sindonews.com
+sinemalar.com
+sinembargo.mx
+sinonimos.com.br
+sirabee.com
+siriusxm.com
+sistacafe.com
+sjtu.edu.cn
+skatteverket.se
+skechers.com
+skelbiu.lt
+sketchup.com
+skokka.com
+skoob.com.br
+skroutz.gr
+skuola.net
+sky.com.br
+sky.de
+sky.it
+skynewsarabia.com
+skype.com
+skyrock.mobi
+skyscanner.com
+skyscanner.com.br
+skyscanner.es
+skyscanner.it
+slack.com
+slader.com
+slate.com
+sld.cu
+sleazyneasy.com
+slickdeals.net
+slideplayer.com
+sling.com
+slobodnadalmacija.hr
+sltrib.com
+sm3ha.com
+smaker.pl
+smallseotools.com
+smartasset.com
+smarter.com
+smartsheet.com
+smbc-card.com
+smbc.co.jp
+sme.sk
+smh.com.au
+smithsonianmag.com
+smugmug.com
+smule.com
+smythstoys.com
+smzdm.com
+snagajob.com
+snapchat.com
+snapdeal.com
+sncf.com
+snjpn.net
+snopes.com
+so-net.ne.jp
+so.com
+socialblade.com
+societe.com
+socratic.org
+sodimac.cl
+sofascore.com
+sofort.com
+soft98.ir
+softbank.jp
+softcore69.com
+softpedia.com
+sogou.com
+soha.vn
+sohu.com
+sol.org.tr
+soloporno.xxx
+solvusoft.com
+sondakika.com
+songkick.com
+songmeanings.com
+songsterr.com
+songtexte.com
+sonhoo.com
+sonhos.com.br
+sony.com
+sony.jp
+sonyentertainmentnetwork.com
+sonyliv.com
+sonymobile.com
+soompi.com
+sopitas.com
+sorularlaislamiyet.com
+soso.com
+sourceforge.net
+southcn.com
+southwest.com
+space.com
+spanishdict.com
+spankwire.com
+sparknotes.com
+spb.ru
+spectrum.com
+spectrum.net
+spendwithpennies.com
+spiceworks.com
+spidersweb.pl
+spine-health.com
+spirit.com
+spokeo.com
+sponichi.co.jp
+sporcle.com
+sport-express.ru
+sport.cz
+sport.es
+sport.pl
+sport1.de
+sport24.gr
+sportbible.com
+sportbox.ru
+sportmail.ru
+sportmaster.ru
+sports.ru
+sportsdirect.com
+sportskeeda.com
+springer.com
+sprint.com
+sprintpcs.com
+sprzedajemy.pl
+square-enix.com
+squarespace.com
+squareup.com
+sravni.ru
+srbijadanas.com
+ssa.gov
+ssc.nic.in
+ssl-images-amazon.com
+standard.co.uk
+standardmedia.co.ke
+stanford.edu
+staples.com
+starbucks.com
+starhit.ru
+startpage.com
+startpagina.nl
+startribune.com
+startv.com.tr
+state.gov
+statefarm.com
+statista.com
+steamcn.com
+steemit.com
+stepstone.de
+stern.de
+stileproject.com
+stirileprotv.ro
+stockx.com
+storm.mg
+stps.gob.mx
+stradivarius.com
+straighttalk.com
+straitstimes.com
+strana.ua
+strava.com
+streamable.com
+streamango.com
+streamlabs.com
+stripchat.com
+stripe.com
+stubhub.com
+studenti.it
+studfiles.net
+studocu.com
+stuff.co.nz
+stylecaster.com
+suamusica.com.br
+suapesquisa.com
+suara.com
+subito.it
+submarino.com.br
+subscene.com
+subway.com
+successfactors.com
+successfactors.eu
+sudinfo.be
+sudouest.fr
+sueddeutsche.de
+sulekha.com
+summitracing.com
+sunat.gob.pe
+suntory.co.jp
+super.cz
+superdrug.com
+superela.com
+superesportes.com.br
+superuser.com
+surveygizmo.com
+suumo.jp
+svpressa.ru
+svt.se
+svyaznoy.ru
+swatchseries.to
+sweatco.in
+sweetwater.com
+swiggy.com
+sympla.com.br
+synxis.com
+syosetu.com
+t-mobile.com
+t.co
+t.me
+t13.cl
+t24.com.tr
+t3.com
+t66y.com
+tableau.com
+tabletki.ua
+tabnak.ir
+taboola.com
+tacobell.com
+tagesschau.de
+tagged.com
+tailieu.vn
+taimienphi.vn
+taishu.jp
+takvim.com.tr
+tamasha.com
+tamilrockerrs.co
+tandfonline.com
+taniomania.pl
+tap.az
+tarafdari.com
+targeo.pl
+taringa.net
+tass.ru
+taste.com.au
+tasteofhome.com
+tatacliq.com
+tatasky.com
+tawk.to
+taxi69.com
+tbs.co.jp
+tchibo.de
+tci.ir
+td.com
+tdk.gov.tr
+teacherspayteachers.com
+teamviewer.com
+teatroporno.com
+tebyan.net
+techbang.com
+techcrunch.com
+techspot.com
+techtarget.com
+techwalla.com
+tecmundo.com.br
+tecnoandroid.it
+tecnoblog.net
+ted.com
+teenee.com
+teespring.com
+teknosa.com
+tekstowo.pl
+telcel.com
+tele2.ru
+telecinco.es
+telefe.com
+telegraaf.nl
+telegraf.com.ua
+telegraf.rs
+telegram.org
+telekom.com
+telekom.de
+telekom.hu
+telemagazyn.pl
+telemundo.com
+teleprogramma.pro
+televisa.com
+telewebion.com
+telkomsel.com
+telmex.com
+telnavi.jp
+telstra.com.au
+temonibus.com
+tempo.co
+tencent.com
+tengrinews.kz
+tenki.jp
+tenor.co
+tenor.com
+termgame.com
+terra.com.br
+tes.com
+tesco.com
+tesla.com
+testbook.com
+texas.gov
+tf1.fr
+tfl.gov.uk
+thaipost.net
+thairath.co.th
+thanhnien.vn
+theaa.com
+theasianparent.com
+theatlantic.com
+thebalance.com
+thebalancesmb.com
+thebump.com
+theconversation.com
+thecrazytourist.com
+theculturetrip.com
+thecut.com
+thedrive.com
+theepochtimes.com
+thefappeningblog.com
+thegioididong.com
+theglobeandmail.com
+thehill.com
+thehindu.com
+thehindubusinessline.com
+thekitchn.com
+theknot.com
+themeforest.net
+themuse.com
+thenest.com
+thenews.com.pk
+thenewsminute.com
+theporndude.com
+thequestion.ru
+therange.co.uk
+thesource.com
+thespruce.com
+thespruceeats.com
+thesprucepets.com
+thestar.com.my
+thestartmagazine.com
+thestudentroom.co.uk
+thesun.co.uk
+thethao247.vn
+thethaovanhoa.vn
+thetimes.co.uk
+thetoptens.com
+thetrainline.com
+thetv.jp
+theweathernetwork.com
+thewrap.com
+thingiverse.com
+thisisinsider.com
+thomann.de
+thomascook.com
+thoughtcatalog.com
+three.co.uk
+thrillist.com
+thumbtack.com
+thumbzilla.com
+thuvienphapluat.vn
+tianya.cn
+ticketmaster.co.uk
+ticketmaster.com
+ticketmaster.com.mx
+ticketone.it
+tickets-center.com
+tickets.com
+tieba.com
+tiempo.com
+tiempo.com.mx
+tiempodesanjuan.com
+tiendeo.com.br
+tigo.com
+tiket.com
+tiki.vn
+tiktok.com
+tim.com.br
+time.com
+time.is
+timeanddate.com
+timeout.com
+timeslive.co.za
+timesnownews.com
+timesofindia.com
+tinder.com
+tinhte.vn
+tinkoff.ru
+tinmoi.vn
+tirto.id
+tiu.ru
+tjsp.jus.br
+tjx.com
+tmall.com
+tmearn.com
+tmofans.com
+tmz.com
+tn.com.ar
+today.com
+today.it
+todoexpertos.com
+togetter.com
+tohotheater.jp
+tokubai.co.jp
+tokyo-sports.co.jp
+tokyodisneyresort.jp
+tokyomotion.net
+toluna.com
+tommy.com
+tomsguide.com
+tomshardware.com
+toofab.com
+topky.sk
+topnews.ru
+topporno.tv
+torcedores.com
+torrent9.uno
+torrentfreak.com
+torrenthaja.com
+torrentwal.com
+torrentz2.eu
+torrid.com
+totaljobs.com
+toutelatele.com
+toutiao.com
+townandcountrymag.com
+townwork.net
+toyokeizai.net
+toyota.com
+tp-link.com
+tportal.hr
+tpu.ro
+trabalhabrasil.com.br
+trabalhosfeitos.com
+tractorsupply.com
+tradingview.com
+trafficnews.jp
+trak.in
+transfermarkt.de
+transferwise.com
+trashbox.ru
+travel.co.jp
+travelocity.com
+traveloka.com
+traveltriangle.com
+travelzoo.com
+treccani.it
+trendyol.com
+trenitalia.com
+tribuna.com.mx
+trilltrill.jp
+trip.com
+tripadvisor.ca
+tripadvisor.co
+tripadvisor.co.uk
+tripadvisor.co.za
+tripadvisor.com.ar
+tripadvisor.com.au
+tripadvisor.com.br
+tripadvisor.com.mx
+tripadvisor.com.ph
+tripadvisor.com.tr
+tripadvisor.de
+tripadvisor.es
+tripadvisor.fr
+tripadvisor.in
+tripadvisor.it
+tripadvisor.jp
+tripadvisor.ru
+tripod.com
+tripsavvy.com
+trivago.com
+trivago.com.br
+trivago.com.mx
+trivago.es
+trivago.in
+trome.pe
+trovaprezzi.it
+trovit.com
+trovit.com.br
+trovit.com.mx
+trovit.es
+trovit.it
+trt1.com.tr
+truecaller.com
+truecar.com
+truecorp.co.th
+trueid.net
+trustedreviews.com
+truthfinder.com
+truyenfull.vn
+tsa-algerie.com
+tsite.jp
+tsn.ua
+tuasaude.com
+tube2017.com
+tube8.com
+tubedupe.com
+tubegalore.com
+tubev.sex
+tubexo.net
+tubidy.mobi
+tubsexer.com
+tucarro.com.co
+tudocelular.com
+tudogostoso.com.br
+tui.co.uk
+tukif.com
+tuko.co.ke
+tunein.com
+tuoitre.vn
+turbo.az
+turbobit.net
+tureng.com
+turkcell.com.tr
+turkishairlines.com
+turkiye.gov.tr
+turkiyegazetesi.com.tr
+turktelekom.com.tr
+turnitin.com
+tut.by
+tutsplus.com
+tutu.ru
+tv-asahi.co.jp
+tv-tokyo.co.jp
+tv.ua
+tv2.dk
+tv2.no
+tvanouvelles.ca
+tvbs.com.tw
+tver.jp
+tvguide.com
+tvline.com
+tvmovie.de
+tvn.pl
+tvn24.pl
+tvnotas.com.mx
+tvnow.de
+tvp.pl
+tvspielfilm.de
+tvtropes.org
+tvzvezda.ru
+tweakers.net
+twentytwowords.com
+twimg.com
+twinfinite.net
+twoo.com
+txxx.com
+tycsports.com
+typeform.com
+tz.de
+u-f.ru
+uba.ar
+ubc.ca
+ubereats.com
+ubi.com
+ubuntu.com
+ucla.edu
+ucoz.ru
+ucsd.edu
+uefa.com
+ufrgs.br
+uhaul.com
+uidai.gov.in
+uk.com
+ukr.net
+ukraina.ru
+ukranews.com
+ulifestyle.com.hk
+uloz.to
+ulta.com
+ultimateclassicrock.com
+ultipro.com
+ulub.pl
+uludagsozluk.com
+umblr.com
+umich.edu
+umn.edu
+un.org
+unblocked.krd
+uncomo.com
+underarmour.com
+unext.jp
+unian.net
+unian.ua
+unicredit.it
+unieuro.it
+united.com
+unity.com
+unity3d.com
+univision.com
+unocero.com
+unotv.com
+unrealengine.com
+unsplash.com
+updatetribun.org
+uploaded.net
+uploadfiles.io
+uplus.co.kr
+upornia.com
+uproxx.com
+uptobox.com
+upwork.com
+ura.news
+urbanoutfitters.com
+urbia.de
+urdupoint.com
+urssaf.fr
+usa.gov
+usaa.com
+usajobs.gov
+usbank.com
+usc.edu
+uscis.gov
+usda.gov
+usembassy.gov
+usenet.nl
+userapi.com
+useraudio.net
+userbenchmark.com
+usgamer.net
+usmagazine.com
+usnews.com
+usp.br
+uta-net.com
+utexas.edu
+utoronto.ca
+utorrent.com
+utro.ru
+uzimusic.ru
+uzmantv.com
+uznayvse.ru
+uzone.id
+v-s.mobi
+v2ex.com
+va.gov
+vademecum.es
+vagalume.com.br
+vagas.com.br
+valuecommerce.com
+vanguard.com
+vanguardia.com.mx
+vanguardngr.com
+vanityfair.com
+vanityfair.it
+vans.com
+variety.com
+varzesh3.com
+vatanbilgisayar.com
+vatera.hu
+vatgia.com
+vecernji.hr
+vecteezy.com
+vente-privee.com
+vercomicsporno.com
+verdesmares.com.br
+verizon.com
+verizonwireless.com
+versus.com
+very.co.uk
+verywellfamily.com
+verywellfit.com
+verywellhealth.com
+verywellmind.com
+vesti-ukr.com
+vesti.ru
+vforum.vn
+vg.no
+vg247.com
+vgorode.ua
+viagogo.com
+viamichelin.fr
+viapais.com.ar
+viator.com
+vibbo.com
+viber.com
+victoriassecret.com
+vidal.fr
+videa.hu
+videohive.net
+videolan.org
+videosdemadurasx.com
+videospornogratisx.net
+vidio.com
+vidxxx.info
+vietcombank.com.vn
+vietjack.com
+vietnamnet.vn
+vietsubtv.com
+viki.com
+vikiporn.com
+villaporno.com
+violet.vn
+vip.de
+vip.pt
+viptube.com
+virgilio.it
+virginmedia.com
+vistaprint.com
+visualstudio.com
+vitals.com
+viu.com
+viva.co.id
+vivalocal.com
+vivanuncios.com.mx
+vivareal.com.br
+vivense.com
+vividseats.com
+vivo.com.br
+vivud.com
+vix.com
+vjav.com
+vladtime.ru
+vlive.tv
+vlxx.tv
+vmall.com
+vmware.com
+vocabulary.com
+vodafone.co.uk
+vodafone.com
+vodafone.com.tr
+vodafone.de
+vodafone.es
+vodafone.in
+vodafone.it
+voeazul.com.br
+voegol.com.br
+voetbalprimeur.nl
+voh.com.vn
+voici.fr
+vokrug.tv
+volkskrant.nl
+volvocars.com
+voot.com
+vox.com
+vporn.com
+vrbo.com
+vrisko.gr
+vtc.vn
+vtv.vn
+vtv16.com
+vudu.com
+vueling.com
+vulture.com
+vz.ru
+w3school.com.cn
+wa.gov
+wagwalking.com
+walgreens.com
+walkerplus.com
+walla.co.il
+wallapop.com
+walmart.ca
+walmart.com.br
+walmart.com.mx
+wamiz.com
+wankoz.com
+wapmight.net
+warframe.com
+wargaming.net
+washington.edu
+washingtonexaminer.com
+watchmygf.me
+wayfair.ca
+wayfair.co.uk
+wayfair.com
+waze.com
+wday.ru
+wdr.de
+wear.jp
+weather.gov
+weathernews.jp
+webbeteg.hu
+webconsultas.com
+webcrawler.com
+webex.com
+weblio.jp
+webmotors.com.br
+webofknowledge.com
+webry.info
+websiteoutlook.com
+webstaurantstore.com
+webtekno.com
+webtoons.com
+webtretho.com
+webuy.com
+weeronline.nl
+weheartit.com
+wehkamp.nl
+weibo.cn
+weibo.com
+weightwatchers.com
+welt.de
+wemakeprice.com
+wendys.com
+wenxuecity.com
+westernjournal.com
+westernunion.com
+wetter.com
+wetter.de
+wetteronline.de
+wezz-y.com
+whatmobile.com.pk
+whattoexpect.com
+which.co.uk
+whitepages.com
+who.int
+wickes.co.uk
+wikia.com
+wikibooks.org
+wikidot.com
+wikimapia.org
+wikimedia.org
+wikiquote.org
+wikisource.org
+wikiwand.com
+wikiwiki.jp
+wildberries.ru
+wiley.com
+wilko.com
+willhaben.at
+win-rar.com
+wind.it
+windguru.cz
+windows.net
+windowscentral.com
+wiocha.pl
+wired.co.uk
+wired.com
+wisc.edu
+wisdomjobs.com
+withgoogle.com
+wix.com
+wizards.com
+wizaz.pl
+wizzair.com
+wolframalpha.com
+woman.ru
+womanadvice.ru
+womenshealthmag.com
+wonderhowto.com
+wongnai.com
+woolworths.com.au
+wordhippo.com
+wordplays.com
+wordpress.org
+work.ua
+worldatlas.com
+worldcat.org
+worldoftanks.ru
+worldofwarcraft.com
+worldstarhiphop.com
+wort-suchen.de
+worten.pt
+wowcher.co.uk
+wowhead.com
+wowkeren.com
+wowkorea.jp
+wowma.jp
+wp.com
+wprost.pl
+wradio.com.co
+wunderground.com
+wunderweib.de
+wuxiaworld.com
+wwe.com
+www.gov.cn
+www.nhs.uk
+wyborcza.pl
+wykop.pl
+wyndhamhotels.com
+xataka.com
+xatakandroid.com
+xbabe.com
+xbombo.com
+xcafe.com
+xda-developers.com
+xero.com
+xfantasy.tv
+xhamster.one
+xhamsterlive.com
+xhamsterpremium.com
+xiami.com
+xiaohongshu.com
+xiaomi.com
+ximalaya.com
+xing.com
+xinhuanet.com
+xlxx.com
+xnxx.net
+xnxx.tv
+xnxxs.mobi
+xo.gr
+xomusic.ru
+xoso.me
+xskt.com.vn
+xsmn.me
+xsrv.jp
+xtube.com
+xueqiu.com
+xuite.net
+xunlei.com
+xvideos.es
+xvideos.net
+xvideos.red
+xvideos2.com
+xvideosex.site
+xvidzz.com
+xvxxx.club
+xxlmag.com
+xxx.com
+xxxbucetas.net
+xxxvideos247.com
+y8.com
+yabiladi.com
+yad2.co.il
+yadi.sk
+yallakora.com
+yammer.com
+yandex.by
+yandex.com
+yandex.com.tr
+yandex.kz
+yandex.net
+yaplakal.com
+yapo.cl
+yasemin.com
+yatra.com
+ycwb.com
+yell.com
+yellowpages.ca
+yellowpages.com
+yelp.ca
+yelp.de
+yemek.com
+yemeksepeti.com
+yeniakit.com.tr
+yeniasir.com.tr
+yenicaggazetesi.com.tr
+yespornplease.com
+yifysubtitles.com
+yjc.ir
+yle.fi
+ymobile.jp
+yna.co.kr
+ynet.co.il
+yodobashi.com
+yomiuri.co.jp
+yoo7.com
+yoox.com
+yooying.com
+yoreparo.com
+youdao.com
+youku.com
+youla.ru
+youporngay.com
+yourmechanic.com
+yourporn.sexy
+yourtango.com
+youth.cn
+youweekly.gr
+youzan.com
+yr.no
+ytimg.com
+yucatan.com.mx
+yxdown.com
+yy.com
+z1.fm
+zaful.com
+zakon.kz
+zakzak.co.jp
+zalando.de
+zalando.es
+zalando.fr
+zalando.it
+zalando.nl
+zalando.pl
+zalo.me
+zap.co.il
+zapimoveis.com.br
+zappit.gr
+zappos.com
+zara.com
+zattini.com.br
+zaubacorp.com
+zaycev.net
+zazzle.com
+zbporn.com
+zcool.com.cn
+zdf.de
+zdnet.com
+zedge.net
+zee5.com
+zeebiz.com
+zeit.de
+zergnet.com
+zerodha.com
+zerohedge.com
+zhanqi.tv
+zhaopin.com
+zhibo8.cc
+zhiding.cn
+zhihu.com
+zi.media
+ziare.com
+ziggo.nl
+zigwheels.com
+zippyshare.com
+ziprecruiter.com
+zmenu.com
+znaj.ua
+znanylekarz.pl
+zocdoc.com
+zoho.com
+zol.com.cn
+zoom.com.br
+zoom.us
+zoominfo.com
+zoomit.ir
+zoon.ru
+zoopla.co.uk
+zoosk.com
+zopim.com
+zougla.gr
+zoznam.sk
+zozo.jp
+zulily.com
+zybang.com
diff --git a/chromium/components/url_formatter/spoof_checks/top_domains/domains.skeletons b/chromium/components/url_formatter/spoof_checks/top_domains/domains.skeletons
new file mode 100644
index 00000000000..121c73eaaa6
--- /dev/null
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/domains.skeletons
@@ -0,0 +1,5011 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is generated by
+# components/url_formatter/spoof_checks/make_top_domain_skeletons.cc
+# DO NOT MANUALLY EDIT!
+
+# Each entry is the skeleton of a top domain for the confusability check
+# in components/url_formatter/url_formatter.cc.
+
+l7track.net, 17track.net
+24h.corn.vn, 24h.com.vn
+acadernia.edu, academia.edu
+acadernic.ru, academic.ru
+accuweather.corn, accuweather.com
+adobe.corn, adobe.com
+adp.corn, adp.com
+agoda.corn, agoda.com
+aif.ru, aif.ru
+airbnb.corn, airbnb.com
+alibaba.corn, alibaba.com
+aliexpress.corn, aliexpress.com
+allegro.pl, allegro.pl
+allocine.fr, allocine.fr
+alodokter.corn, alodokter.com
+arnazon.ca, amazon.ca
+arnazon.co.jp, amazon.co.jp
+arnazon.co.uk, amazon.co.uk
+arnazon.corn, amazon.com
+arnazon.corn.rnx, amazon.com.mx
+arnazon.de, amazon.de
+arnazon.es, amazon.es
+arnazon.fr, amazon.fr
+arnazon.in, amazon.in
+arnazon.it, amazon.it
+arneblo.jp, ameblo.jp
+arnericanexpress.corn, americanexpress.com
+ancestry.corn, ancestry.com
+anirneflv.net, animeflv.net
+anyxxx.pro, anyxxx.pro
+aol.corn, aol.com
+apkpure.corn, apkpure.com
+apple.corn, apple.com
+appledaily.corn, appledaily.com
+archive.org, archive.org
+asahi.corn, asahi.com
+ask.corn, ask.com
+asos.corn, asos.com
+asus.corn, asus.com
+autotrader.corn, autotrader.com
+avito.ru, avito.ru
+azlyrics.corn, azlyrics.com
+badoo.corn, badoo.com
+baidu.corn, baidu.com
+baixaki.corn.br, baixaki.com.br
+banggood.corn, banggood.com
+bankofarnerica.corn, bankofamerica.com
+battle.net, battle.net
+bbc.co.uk, bbc.co.uk
+bbc.corn, bbc.com
+beeg.corn, beeg.com
+bestbuy.corn, bestbuy.com
+bet365.corn, bet365.com
+biblegateway.corn, biblegateway.com
+biglobe.ne.jp, biglobe.ne.jp
+bild.de, bild.de
+bilibili.corn, bilibili.com
+bing.corn, bing.com
+blackboard.corn, blackboard.com
+blogspot.corn, blogspot.com
+bloornberg.corn, bloomberg.com
+booking.corn, booking.com
+bookrnyshow.corn, bookmyshow.com
+britannica.corn, britannica.com
+bukalapak.corn, bukalapak.com
+businessinsider.corn, businessinsider.com
+bustle.corn, bustle.com
+buzzfeed.corn, buzzfeed.com
+ca.gov, ca.gov
+caixa.gov.br, caixa.gov.br
+canada.ca, canada.ca
+canalrcn.corn, canalrcn.com
+canva.corn, canva.com
+capitalone.corn, capitalone.com
+cargurus.corn, cargurus.com
+cbsnews.corn, cbsnews.com
+cbssports.corn, cbssports.com
+ccrn.net, ccm.net
+cdc.gov, cdc.gov
+cdiscount.corn, cdiscount.com
+ceneo.pl, ceneo.pl
+chase.corn, chase.com
+chaturbate.corn, chaturbate.com
+chegg.corn, chegg.com
+chinatirnes.corn, chinatimes.com
+chip.de, chip.de
+chron.corn, chron.com
+cinecalidad.to, cinecalidad.to
+clarin.corn, clarin.com
+cnbc.corn, cnbc.com
+cnet.corn, cnet.com
+cnn.corn, cnn.com
+collegedunia.corn, collegedunia.com
+convert2rnp3.net, convert2mp3.net
+correios.corn.br, correios.com.br
+craigslist.org, craigslist.org
+cricbuzz.corn, cricbuzz.com
+dailyrnail.co.uk, dailymail.co.uk
+dailyrnotion.corn, dailymotion.com
+daurn.net, daum.net
+dell.corn, dell.com
+depositphotos.corn, depositphotos.com
+detik.corn, detik.com
+deviantart.corn, deviantart.com
+dhgate.corn, dhgate.com
+dhl.de, dhl.de
+dictionary.corn, dictionary.com
+discordapp.corn, discordapp.com
+drnrn.co.jp, dmm.co.jp
+drnrn.corn, dmm.com
+doorblog.jp, doorblog.jp
+drorn.ru, drom.ru
+dropbox.corn, dropbox.com
+ebay-kleinanzeigen.de, ebay-kleinanzeigen.de
+ebay.co.uk, ebay.co.uk
+ebay.corn, ebay.com
+ebay.corn.au, ebay.com.au
+ebay.de, ebay.de
+ebay.es, ebay.es
+ebay.fr, ebay.fr
+ebay.it, ebay.it
+egy.best, egy.best
+eksisozluk.corn, eksisozluk.com
+elconfidencial.corn, elconfidencial.com
+elintransigente.corn, elintransigente.com
+elrnundo.es, elmundo.es
+elpais.corn, elpais.com
+eluniversal.corn.rnx, eluniversal.com.mx
+ernag.ro, emag.ro
+engadget.corn, engadget.com
+epicgarnes.corn, epicgames.com
+espn.corn, espn.com
+etsy.corn, etsy.com
+europa.eu, europa.eu
+eventbrite.corn, eventbrite.com
+excite.co.jp, excite.co.jp
+expedia.corn, expedia.com
+express.co.uk, express.co.uk
+facebook.corn, facebook.com
+fandango.corn, fandango.com
+fandorn.corn, fandom.com
+fast.corn, fast.com
+fazenda.gov.br, fazenda.gov.br
+fc2.corn, fc2.com
+fedex.corn, fedex.com
+filrnweb.pl, filmweb.pl
+flickr.corn, flickr.com
+flipkart.corn, flipkart.com
+fnac.corn, fnac.com
+forbes.corn, forbes.com
+foxnews.corn, foxnews.com
+francetvinfo.fr, francetvinfo.fr
+free.fr, free.fr
+gaana.corn, gaana.com
+garnepedia.corn, gamepedia.com
+garnespot.corn, gamespot.com
+gearbest.corn, gearbest.com
+genius.corn, genius.com
+gfycat.corn, gfycat.com
+giphy.corn, giphy.com
+gisrneteo.ru, gismeteo.ru
+github.corn, github.com
+glassdoor.corn, glassdoor.com
+globo.corn, globo.com
+glosbe.corn, glosbe.com
+go.corn, go.com
+goal.corn, goal.com
+gofundrne.corn, gofundme.com
+goo.ne.jp, goo.ne.jp
+goodreads.corn, goodreads.com
+google.ca, google.ca
+google.cl, google.cl
+google.co.id, google.co.id
+google.co.in, google.co.in
+google.co.jp, google.co.jp
+google.co.kr, google.co.kr
+google.co.th, google.co.th
+google.co.uk, google.co.uk
+google.corn, google.com
+google.corn.ar, google.com.ar
+google.corn.au, google.com.au
+google.corn.br, google.com.br
+google.corn.co, google.com.co
+google.corn.rnx, google.com.mx
+google.corn.tr, google.com.tr
+google.corn.tw, google.com.tw
+google.de, google.de
+google.es, google.es
+google.fr, google.fr
+google.it, google.it
+google.nl, google.nl
+google.pl, google.pl
+google.pt, google.pt
+google.ru, google.ru
+gotporn.corn, gotporn.com
+gsrnarena.corn, gsmarena.com
+gurntree.corn, gumtree.com
+haberler.corn, haberler.com
+hatenablog.corn, hatenablog.com
+hdfcbank.corn, hdfcbank.com
+hdrezka.ag, hdrezka.ag
+healthline.corn, healthline.com
+hilton.corn, hilton.com
+hindustantirnes.corn, hindustantimes.com
+hornedepot.corn, homedepot.com
+hotels.corn, hotels.com
+hotpepper.jp, hotpepper.jp
+hotstar.corn, hotstar.com
+hp.corn, hp.com
+huawei.corn, huawei.com
+huffpost.corn, huffpost.com
+hulu.corn, hulu.com
+icicibank.corn, icicibank.com
+icloud.corn, icloud.com
+ign.corn, ign.com
+ikea.corn, ikea.com
+ilrneteo.it, ilmeteo.it
+ilovepdf.corn, ilovepdf.com
+irndb.corn, imdb.com
+irngur.corn, imgur.com
+irnpress.co.jp, impress.co.jp
+indeed.corn, indeed.com
+indiarnart.corn, indiamart.com
+indiatirnes.corn, indiatimes.com
+indiatoday.in, indiatoday.in
+infobae.corn, infobae.com
+instagrarn.corn, instagram.com
+instructables.corn, instructables.com
+instructure.corn, instructure.com
+interia.pl, interia.pl
+intuit.corn, intuit.com
+investing.corn, investing.com
+investopedia.corn, investopedia.com
+irecornrnend.ru, irecommend.ru
+irs.gov, irs.gov
+itau.corn.br, itau.com.br
+itrnedia.co.jp, itmedia.co.jp
+jobrapido.corn, jobrapido.com
+justdial.corn, justdial.com
+jw.org, jw.org
+kahoot.it, kahoot.it
+kakaku.corn, kakaku.com
+kakao.corn, kakao.com
+kayak.corn, kayak.com
+kenhl4.vn, kenh14.vn
+khanacaderny.org, khanacademy.org
+kinopoisk.ru, kinopoisk.ru
+kizlarsoruyor.corn, kizlarsoruyor.com
+kknews.cc, kknews.cc
+kohls.corn, kohls.com
+kornpas.corn, kompas.com
+kotobank.jp, kotobank.jp
+kp.ru, kp.ru
+lazada.co.th, lazada.co.th
+leagueoflegends.corn, leagueoflegends.com
+leboncoin.fr, leboncoin.fr
+lernonde.fr, lemonde.fr
+lenta.ru, lenta.ru
+letrnejerk.corn, letmejerk.com
+lifewire.corn, lifewire.com
+line.rne, line.me
+linkedin.corn, linkedin.com
+live.corn, live.com
+livedoor.biz, livedoor.biz
+livedoor.corn, livedoor.com
+livedoor.jp, livedoor.jp
+livejournal.corn, livejournal.com
+livescore.corn, livescore.com
+livestrong.corn, livestrong.com
+rnail.ru, mail.ru
+rnakernytrip.corn, makemytrip.com
+rnalavida.corn, malavida.com
+rnarca.corn, marca.com
+rnawdoo3.corn, mawdoo3.com
+rnayoclinic.org, mayoclinic.org
+rneb.gov.tr, meb.gov.tr
+rnediafire.corn, mediafire.com
+rnediurn.corn, medium.com
+rnega.nz, mega.nz
+rnercadolibre.corn, mercadolibre.com
+rnercadolibre.corn.ar, mercadolibre.com.ar
+rnercadolibre.corn.co, mercadolibre.com.co
+rnercadolibre.corn.rnx, mercadolibre.com.mx
+rnercadolivre.corn.br, mercadolivre.com.br
+rnercari.corn, mercari.com
+rnessenger.corn, messenger.com
+rni.corn, mi.com
+rnicrosoft.corn, microsoft.com
+rnicrosoftonline.corn, microsoftonline.com
+rnilliyet.corn.tr, milliyet.com.tr
+rnk.ru, mk.ru
+rnlb.corn, mlb.com
+rnobile.de, mobile.de
+rnobileOl.corn, mobile01.com
+rnonografias.corn, monografias.com
+rnsn.corn, msn.com
+rnundodeportivo.corn, mundodeportivo.com
+rnyanirnelist.net, myanimelist.net
+rnynavi.jp, mynavi.jp
+rnynet.corn, mynet.com
+nll.corn, n11.com
+narnu.wiki, namu.wiki
+naver.corn, naver.com
+naver.jp, naver.jp
+nba.corn, nba.com
+nbcnews.corn, nbcnews.com
+nbcsports.corn, nbcsports.com
+ndtv.corn, ndtv.com
+netflix.corn, netflix.com
+newsl8.corn, news18.com
+nextdoor.corn, nextdoor.com
+nhk.or.jp, nhk.or.jp
+nicovideo.jp, nicovideo.jp
+nifty.corn, nifty.com
+nih.gov, nih.gov
+nike.corn, nike.com
+nikkansports.corn, nikkansports.com
+nikkei.corn, nikkei.com
+nvidia.corn, nvidia.com
+nypost.corn, nypost.com
+nytirnes.corn, nytimes.com
+office.corn, office.com
+office365.corn, office365.com
+ok.ru, ok.ru
+okdiario.corn, okdiario.com
+olx.co.id, olx.co.id
+olx.corn.br, olx.com.br
+olx.pl, olx.pl
+olx.ua, olx.ua
+onet.pl, onet.pl
+onlinesbi.corn, onlinesbi.com
+onlinevideoconverter.corn, onlinevideoconverter.com
+op.gg, op.gg
+orange.fr, orange.fr
+otto.de, otto.de
+otvfoco.corn.br, otvfoco.com.br
+otzovik.corn, otzovik.com
+over-blog.corn, over-blog.com
+pantip.corn, pantip.com
+passeidireto.corn, passeidireto.com
+patreon.corn, patreon.com
+paypal.corn, paypal.com
+perfectgirls.net, perfectgirls.net
+pinterest.co.uk, pinterest.co.uk
+pinterest.corn, pinterest.com
+pinterest.es, pinterest.es
+pixiv.net, pixiv.net
+pixnet.net, pixnet.net
+playstation.corn, playstation.com
+politico.corn, politico.com
+polygon.corn, polygon.com
+pornhub.corn, pornhub.com
+prezi.corn, prezi.com
+prirnevideo.corn, primevideo.com
+prograrnrne-tv.net, programme-tv.net
+qq.corn, qq.com
+qualtrics.corn, qualtrics.com
+quizlet.corn, quizlet.com
+quora.corn, quora.com
+rakuten.co.jp, rakuten.co.jp
+rarnbler.ru, rambler.ru
+ranker.corn, ranker.com
+reddit.corn, reddit.com
+redtube.corn, redtube.com
+researchgate.net, researchgate.net
+reverso.net, reverso.net
+rg.ru, rg.ru
+rightrnove.co.uk, rightmove.co.uk
+roblox.corn, roblox.com
+rottentornatoes.corn, rottentomatoes.com
+rozetka.corn.ua, rozetka.com.ua
+rt.corn, rt.com
+sabah.corn.tr, sabah.com.tr
+sahibinden.corn, sahibinden.com
+sarnsung.corn, samsung.com
+sanook.corn, sanook.com
+sarkariresult.corn, sarkariresult.com
+savefrorn.net, savefrom.net
+sciencedirect.corn, sciencedirect.com
+scribd.corn, scribd.com
+sfgate.corn, sfgate.com
+shopee.co.th, shopee.co.th
+shutterstock.corn, shutterstock.com
+sinoptik.ua, sinoptik.ua
+sky.corn, sky.com
+skyscanner.net, skyscanner.net
+skysports.corn, skysports.com
+slideshare.net, slideshare.net
+srnallpdf.corn, smallpdf.com
+srni2.ru, smi2.ru
+softonic.corn, softonic.com
+soundcloud.corn, soundcloud.com
+souq.corn, souq.com
+sozcu.corn.tr, sozcu.com.tr
+spankbang.corn, spankbang.com
+speedtest.net, speedtest.net
+spiegel.de, spiegel.de
+spotify.corn, spotify.com
+sputniknews.corn, sputniknews.com
+stackexchange.corn, stackexchange.com
+stackoverflow.corn, stackoverflow.com
+stearncornrnunity.corn, steamcommunity.com
+stearnpowered.corn, steampowered.com
+study.corn, study.com
+surveyrnonkey.corn, surveymonkey.com
+t-online.de, t-online.de
+tabelog.corn, tabelog.com
+taleo.net, taleo.net
+taobao.corn, taobao.com
+target.corn, target.com
+techradar.corn, techradar.com
+techtudo.corn.br, techtudo.com.br
+telegraph.co.uk, telegraph.co.uk
+terrnornetropolitico.it, termometropolitico.it
+thebalancecareers.corn, thebalancecareers.com
+thedailybeast.corn, thedailybeast.com
+thefreedictionary.corn, thefreedictionary.com
+theguardian.corn, theguardian.com
+thepiratebay.org, thepiratebay.org
+thesaurus.corn, thesaurus.com
+theverge.corn, theverge.com
+thoughtco.corn, thoughtco.com
+tirn.it, tim.it
+tistory.corn, tistory.com
+tnaflix.corn, tnaflix.com
+tokopedia.corn, tokopedia.com
+trello.corn, trello.com
+tribunnews.corn, tribunnews.com
+tripadvisor.corn, tripadvisor.com
+trulia.corn, trulia.com
+trustpilot.corn, trustpilot.com
+turnblr.corn, tumblr.com
+tutorialspoint.corn, tutorialspoint.com
+twitch.tv, twitch.tv
+twitter.corn, twitter.com
+uber.corn, uber.com
+ubisoft.corn, ubisoft.com
+uderny.corn, udemy.com
+udn.corn, udn.com
+ultirnate-guitar.corn, ultimate-guitar.com
+unarn.rnx, unam.mx
+uniqlo.corn, uniqlo.com
+uol.corn.br, uol.com.br
+ups.corn, ups.com
+uptodown.corn, uptodown.com
+urbandictionary.corn, urbandictionary.com
+usatoday.corn, usatoday.com
+usps.corn, usps.com
+vice.corn, vice.com
+virneo.corn, vimeo.com
+vk.corn, vk.com
+vnexpress.net, vnexpress.net
+w3schools.corn, w3schools.com
+walrnart.corn, walmart.com
+washingtonpost.corn, washingtonpost.com
+wattpad.corn, wattpad.com
+weather.corn, weather.com
+web.de, web.de
+webrnd.corn, webmd.com
+weebly.corn, weebly.com
+wellsfargo.corn, wellsfargo.com
+wetransfer.corn, wetransfer.com
+whatsapp.corn, whatsapp.com
+wikihow.corn, wikihow.com
+wikipedia.org, wikipedia.org
+wiktionary.org, wiktionary.org
+wish.corn, wish.com
+wixsite.corn, wixsite.com
+wondershare.corn, wondershare.com
+wordpress.corn, wordpress.com
+wordreference.corn, wordreference.com
+wp.pl, wp.pl
+wsj.corn, wsj.com
+www.gob.rnx, www.gob.mx
+www.gov.uk, www.gov.uk
+xbox.corn, xbox.com
+xe.corn, xe.com
+xfinity.corn, xfinity.com
+xharnster.corn, xhamster.com
+xnxx.corn, xnxx.com
+xnxx2.pro, xnxx2.pro
+xozilla.corn, xozilla.com
+xvideos.corn, xvideos.com
+y2rnate.corn, y2mate.com
+yahoo.co.jp, yahoo.co.jp
+yahoo.corn, yahoo.com
+yandex.ru, yandex.ru
+yelp.corn, yelp.com
+yenisafak.corn, yenisafak.com
+youjizz.corn, youjizz.com
+yourn7.corn, youm7.com
+youporn.corn, youporn.com
+yourdictionary.corn, yourdictionary.com
+youtube.corn, youtube.com
+yts.arn, yts.am
+zendesk.corn, zendesk.com
+zillow.corn, zillow.com
+zing.vn, zing.vn
+znanija.corn, znanija.com
+zornato.corn, zomato.com
+Olnet.corn, 01net.com
+lOOO.rnenu, 1000.menu
+lOO86.cn, 10086.cn
+lO3.by, 103.by
+lO4.corn.tw, 104.com.tw
+llll.corn.tw, 1111.com.tw
+ll2.ua, 112.ua
+ll4la.corn, 114la.com
+ll77.se, 1177.se
+llst.co.kr, 11st.co.kr
+l23doc.org, 123doc.org
+l23link.vip, 123link.vip
+l23rnovies.la, 123movies.la
+l23rf.corn, 123rf.com
+l26.corn, 126.com
+l3.cl, 13.cl
+l337x.to, 1337x.to
+l377x.to, 1377x.to
+l5rnin.lt, 15min.lt
+l63.corn, 163.com
+l688.corn, 1688.com
+l6personalities.corn, 16personalities.com
+l7l73.corn, 17173.com
+l78.corn, 178.com
+lfichier.corn, 1fichier.com
+lrng.corn, 1mg.com
+lnews.corn.br, 1news.com.br
+lplusl.ua, 1plus1.ua
+ltv.ru, 1tv.ru
+lundl.de, 1und1.de
+2Orninutes.fr, 20minutes.fr
+2Orninutos.es, 20minutos.es
+2lcineplex.corn, 21cineplex.com
+23andrne.corn, 23andme.com
+24-horas.rnx, 24-horas.mx
+24.hu, 24.hu
+247sports.corn, 247sports.com
+24horas.cl, 24horas.cl
+24porn.corn, 24porn.com
+24sata.hr, 24sata.hr
+24srni.org, 24smi.org
+24tirnezones.corn, 24timezones.com
+24tv.ua, 24tv.ua
+24video.sexy, 24video.sexy
+27.ua, 27.ua
+2ch-c.net, 2ch-c.net
+2ch.net, 2ch.net
+2chblog.jp, 2chblog.jp
+2dehands.be, 2dehands.be
+2ernernain.be, 2ememain.be
+2gis.ru, 2gis.ru
+2rn.rna, 2m.ma
+2rnovierulz.gs, 2movierulz.gs
+2rnovierulz.st, 2movierulz.st
+2sao.vn, 2sao.vn
+36O.cn, 360.cn
+36O.corn, 360.com
+36Odoc.corn, 360doc.com
+36kr.corn, 36kr.com
+3brneteo.corn, 3bmeteo.com
+3djuegos.corn, 3djuegos.com
+3dlat.corn, 3dlat.com
+3drngarne.corn, 3dmgame.com
+3dnews.ru, 3dnews.ru
+3rnovs.corn, 3movs.com
+4399.corn, 4399.com
+444.hu, 444.hu
+4chan.org, 4chan.org
+4channel.org, 4channel.org
+4garner.net, 4gamer.net
+4pda.ru, 4pda.ru
+4shared.corn, 4shared.com
+4travel.jp, 4travel.jp
+4tube.corn, 4tube.com
+5-tv.ru, 5-tv.ru
+5l.la, 51.la
+5lcto.corn, 51cto.com
+5ljob.corn, 51job.com
+5lsole.corn, 51sole.com
+52pojie.cn, 52pojie.cn
+58.corn, 58.com
+58pic.corn, 58pic.com
+5ch.net, 5ch.net
+6.cn, 6.cn
+72Op-izle.corn, 720p-izle.com
+75Og.corn, 750g.com
+7ya.ru, 7ya.ru
+8l.cn, 81.cn
+8rnaple.ru, 8maple.ru
+9Ornin.corn, 90min.com
+9ljrn.corn, 91jm.com
+9lrnobiles.corn, 91mobiles.com
+99ll4.corn, 99114.com
+99acres.corn, 99acres.com
+9gag.corn, 9gag.com
+9news.corn.au, 9news.com.au
+al.ro, a1.ro
+alOl.corn.tr, a101.com.tr
+a9vg.corn, a9vg.com
+aa.corn, aa.com
+aa.corn.tr, aa.com.tr
+aaa.corn, aaa.com
+aajtak.in, aajtak.in
+aarp.org, aarp.org
+aastocks.corn, aastocks.com
+abc.corn.py, abc.com.py
+abc.es, abc.es
+abc.net.au, abc.net.au
+abcl3.corn, abc13.com
+abczdrowie.pl, abczdrowie.pl
+abdwap2.corn, abdwap2.com
+aberna.tv, abema.tv
+abernatirnes.corn, abematimes.com
+abola.pt, abola.pt
+about.google, about.google
+aboutespanol.corn, aboutespanol.com
+aboutyou.de, aboutyou.de
+abplive.in, abplive.in
+abril.corn.br, abril.com.br
+abs-cbn.corn, abs-cbn.com
+abv.bg, abv.bg
+acaderny.corn, academy.com
+accenture.corn, accenture.com
+accorhotels.corn, accorhotels.com
+acehardware.corn, acehardware.com
+acer.corn, acer.com
+acfun.cn, acfun.cn
+acs.org, acs.org
+action.corn, action.com
+active.corn, active.com
+actu.fr, actu.fr
+ad.nl, ad.nl
+adac.de, adac.de
+adayroi.corn, adayroi.com
+addthis.corn, addthis.com
+adevarul.ro, adevarul.ro
+adidas.corn, adidas.com
+adidas.corn.br, adidas.com.br
+adrne.ru, adme.ru
+adrninistradores.corn.br, administradores.com.br
+adnradio.cl, adnradio.cl
+adoptapet.corn, adoptapet.com
+adorocinerna.corn, adorocinema.com
+adslzone.net, adslzone.net
+adultfriendfinder.corn, adultfriendfinder.com
+advanceautoparts.corn, advanceautoparts.com
+ae.corn, ae.com
+aernet.es, aemet.es
+aernps.es, aemps.es
+aeon.co.jp, aeon.co.jp
+aeoncinerna.corn, aeoncinema.com
+aerolineas.corn.ar, aerolineas.com.ar
+affaritaliani.it, affaritaliani.it
+afip.gob.ar, afip.gob.ar
+afisha.ru, afisha.ru
+afreecatv.corn, afreecatv.com
+aftonbladet.se, aftonbladet.se
+agenciatributaria.es, agenciatributaria.es
+aglasern.corn, aglasem.com
+ah.nl, ah.nl
+ahaber.corn.tr, ahaber.com.tr
+ahaonline.cz, ahaonline.cz
+ahlrnasrnews.corn, ahlmasrnews.com
+ahoranoticias.cl, ahoranoticias.cl
+ahrarn.org.eg, ahram.org.eg
+airasia.corn, airasia.com
+airbnb.co.uk, airbnb.co.uk
+airbnb.corn.br, airbnb.com.br
+airbnb.es, airbnb.es
+airbnb.fr, airbnb.fr
+aircanada.corn, aircanada.com
+airedesantafe.corn.ar, airedesantafe.com.ar
+airtel.in, airtel.in
+ais.co.th, ais.co.th
+ajc.corn, ajc.com
+ajio.corn, ajio.com
+akakce.corn, akakce.com
+akarnaihd.net, akamaihd.net
+akarnaized.net, akamaized.net
+akc.org, akc.org
+akket.corn, akket.com
+akoarn.net, akoam.net
+aksarn.corn.tr, aksam.com.tr
+aktuality.sk, aktuality.sk
+aktualne.cz, aktualne.cz
+akurat.co, akurat.co
+al3ornk.corn, al3omk.com
+alarnaula.corn, alamaula.com
+alarny.corn, alamy.com
+alaskaair.corn, alaskaair.com
+albawabhnews.corn, albawabhnews.com
+alberta.ca, alberta.ca
+alc.co.jp, alc.co.jp
+aldi-sued.de, aldi-sued.de
+aldi.co.uk, aldi.co.uk
+alfernrninile.corn, alfemminile.com
+ali2l3.net, ali213.net
+alicdn.corn, alicdn.com
+alipay.corn, alipay.com
+aliyun.corn, aliyun.com
+aljaras.corn, aljaras.com
+aljazeera.corn, aljazeera.com
+aljazeera.net, aljazeera.net
+alkosto.corn, alkosto.com
+allabout.co.jp, allabout.co.jp
+allaboutvision.corn, allaboutvision.com
+allbest.ru, allbest.ru
+allkpop.corn, allkpop.com
+allrnusic.corn, allmusic.com
+allo.ua, allo.ua
+allodocteurs.fr, allodocteurs.fr
+allrecipes.co.uk, allrecipes.co.uk
+allrecipes.corn, allrecipes.com
+allscrabblewords.corn, allscrabblewords.com
+allstate.corn, allstate.com
+ally.corn, ally.com
+alrnaany.corn, almaany.com
+alrnasryalyourn.corn, almasryalyoum.com
+alrnrsal.corn, almrsal.com
+alnaharegypt.corn, alnaharegypt.com
+alo.rs, alo.rs
+alphacoders.corn, alphacoders.com
+alphaporno.corn, alphaporno.com
+alterna.jp, altema.jp
+altervista.org, altervista.org
+altibbi.corn, altibbi.com
+alukah.net, alukah.net
+alvolante.it, alvolante.it
+alwafd.news, alwafd.news
+alwatanvoice.corn, alwatanvoice.com
+alza.cz, alza.cz
+arn.corn.rnx, am.com.mx
+arnalgarna-lab.corn, amalgama-lab.com
+arnarujala.corn, amarujala.com
+arnazon.cn, amazon.cn
+arnazon.corn.au, amazon.com.au
+arnazon.corn.br, amazon.com.br
+arnazon.jobs, amazon.jobs
+arnazonaws.corn, amazonaws.com
+arnbito.corn, ambito.com
+arnctheatres.corn, amctheatres.com
+arnd.corn, amd.com
+arneba.jp, ameba.jp
+arneli.fr, ameli.fr
+arnericanas.corn.br, americanas.com.br
+arnericatv.corn.pe, americatv.com.pe
+arneritrade.corn, ameritrade.com
+arninoapps.corn, aminoapps.com
+arntrak.corn, amtrak.com
+ana.co.jp, ana.co.jp
+anadolu.edu.tr, anadolu.edu.tr
+analdin.corn, analdin.com
+anandtech.corn, anandtech.com
+andhrajyothy.corn, andhrajyothy.com
+andro4all.corn, andro4all.com
+androeed.ru, androeed.ru
+android-l.corn, android-1.com
+android.corn, android.com
+androidauthority.corn, androidauthority.com
+androidcentral.corn, androidcentral.com
+androidfilehost.corn, androidfilehost.com
+androidoyun.club, androidoyun.club
+androidpolice.corn, androidpolice.com
+angieslist.corn, angieslist.com
+anirnatetirnes.corn, animatetimes.com
+anirne-planet.corn, anime-planet.com
+anirne-sugoi.corn, anime-sugoi.com
+anirnenewsnetwork.corn, animenewsnetwork.com
+anirnevost.org, animevost.org
+anjuke.corn, anjuke.com
+anninhthudo.vn, anninhthudo.vn
+annuaire-telechargernent.corn, annuaire-telechargement.com
+ansa.it, ansa.it
+anses.gob.ar, anses.gob.ar
+answers.corn, answers.com
+antena3.corn, antena3.com
+antena3.ro, antena3.ro
+antyradio.pl, antyradio.pl
+anwb.nl, anwb.nl
+anyporn.corn, anyporn.com
+anysex.corn, anysex.com
+ap.gov.in, ap.gov.in
+apache.org, apache.org
+aparat.corn, aparat.com
+apartrnentguide.corn, apartmentguide.com
+apartrnenthorneliving.corn, apartmenthomeliving.com
+apartrnents.corn, apartments.com
+apkhere.corn, apkhere.com
+apkrnirror.corn, apkmirror.com
+apkrnonk.corn, apkmonk.com
+apnews.corn, apnews.com
+apost.corn, apost.com
+apostrophe.ua, apostrophe.ua
+apotheken-urnschau.de, apotheken-umschau.de
+app-liv.jp, app-liv.jp
+appbank.net, appbank.net
+appfolio.corn, appfolio.com
+applebees.corn, applebees.com
+appllio.corn, appllio.com
+applocal.corn.br, applocal.com.br
+apprnedia.jp, appmedia.jp
+appspot.corn, appspot.com
+apteka.ru, apteka.ru
+aptoide.corn, aptoide.com
+arabarn.corn, arabam.com
+arabsong.top, arabsong.top
+arbeitsagentur.de, arbeitsagentur.de
+arcgis.corn, arcgis.com
+archiveofourown.org, archiveofourown.org
+arduino.cc, arduino.cc
+argaarn.corn, argaam.com
+argentina.gob.ar, argentina.gob.ar
+argentino.corn.ar, argentino.com.ar
+argos.co.uk, argos.co.uk
+arine.jp, arine.jp
+aristeguinoticias.corn, aristeguinoticias.com
+arstechnica.corn, arstechnica.com
+artstation.corn, artstation.com
+aruba.it, aruba.it
+arukereso.hu, arukereso.hu
+arxiv.org, arxiv.org
+as.corn, as.com
+asagei.corn, asagei.com
+asajo.jp, asajo.jp
+asana.corn, asana.com
+ascii.jp, ascii.jp
+asda.corn, asda.com
+ashernaletube.corn, ashemaletube.com
+ashleyfurniture.corn, ashleyfurniture.com
+ashleyrnadison.corn, ashleymadison.com
+asianetnews.corn, asianetnews.com
+ask.frn, ask.fm
+askubuntu.corn, askubuntu.com
+asos.fr, asos.fr
+aspor.corn.tr, aspor.com.tr
+asriran.corn, asriran.com
+astrology.corn, astrology.com
+astrologyanswers.corn, astrologyanswers.com
+atelevisao.corn, atelevisao.com
+athensrnagazine.gr, athensmagazine.gr
+athorne.co.jp, athome.co.jp
+atlantablackstar.corn, atlantablackstar.com
+atlassian.corn, atlassian.com
+atlassian.net, atlassian.net
+atptour.corn, atptour.com
+atrapalo.corn, atrapalo.com
+atresplayer.corn, atresplayer.com
+att.corn, att.com
+att.net, att.net
+atv.corn.tr, atv.com.tr
+atwiki.jp, atwiki.jp
+au.corn, au.com
+auchan.fr, auchan.fr
+auction.co.kr, auction.co.kr
+audible.corn, audible.com
+auferninin.corn, aufeminin.com
+auone.jp, auone.jp
+auspost.corn.au, auspost.com.au
+auto-swiat.pl, auto-swiat.pl
+auto.ru, auto.ru
+autobild.de, autobild.de
+autoblog.corn, autoblog.com
+autocarindia.corn, autocarindia.com
+autodesk.corn, autodesk.com
+autohorne.corn.cn, autohome.com.cn
+autokult.pl, autokult.pl
+autornobile.it, automobile.it
+autoplus.fr, autoplus.fr
+autoscout24.de, autoscout24.de
+autoscout24.it, autoscout24.it
+autotrader.ca, autotrader.ca
+autotrader.co.uk, autotrader.co.uk
+autozone.corn, autozone.com
+avast.corn, avast.com
+avaz.ba, avaz.ba
+avclub.corn, avclub.com
+avg.corn, avg.com
+avgle.corn, avgle.com
+avianca.corn, avianca.com
+aviasales.ru, aviasales.ru
+avito.rna, avito.ma
+avon.corn, avon.com
+avon.corn.br, avon.com.br
+avvo.corn, avvo.com
+aweber.corn, aweber.com
+axisbank.corn, axisbank.com
+axs.corn, axs.com
+azcentral.corn, azcentral.com
+azet.sk, azet.sk
+azure.corn, azure.com
+azurewebsites.net, azurewebsites.net
+b-cdn.net, b-cdn.net
+bl.ro, b1.ro
+b2b.cn, b2b.cn
+b92.net, b92.net
+bab.la, bab.la
+babbel.corn, babbel.com
+baby.ru, baby.ru
+babyblog.ru, babyblog.ru
+babycenter.corn, babycenter.com
+babycentre.co.uk, babycentre.co.uk
+babyhorne.corn.tw, babyhome.com.tw
+babytree.corn, babytree.com
+backpackers.corn.tw, backpackers.com.tw
+badorno.xxx, badorno.xxx
+bahn.de, bahn.de
+baiducontent.corn, baiducontent.com
+baike.corn, baike.com
+bakeca.it, bakeca.it
+bakusai.corn, bakusai.com
+banarnex.corn, banamex.com
+banco.bradesco, banco.bradesco
+bancogalicia.corn.ar, bancogalicia.com.ar
+bancorner.corn, bancomer.com
+bancosantander.es, bancosantander.es
+band.us, band.us
+bandcarnp.corn, bandcamp.com
+bang.corn, bang.com
+bankbazaar.corn, bankbazaar.com
+banki.ru, banki.ru
+bankifsccode.corn, bankifsccode.com
+bankrnellat.ir, bankmellat.ir
+bankrate.corn, bankrate.com
+baornoi.corn, baomoi.com
+barnesandnoble.corn, barnesandnoble.com
+bartleby.corn, bartleby.com
+baseball-reference.corn, baseball-reference.com
+basketball-reference.corn, basketball-reference.com
+baskino.rne, baskino.me
+basspro.corn, basspro.com
+bathandbodyworks.corn, bathandbodyworks.com
+bauhaus.info, bauhaus.info
+bayt.corn, bayt.com
+bazos.cz, bazos.cz
+bazos.sk, bazos.sk
+bb.corn.br, bb.com.br
+bbb.org, bbb.org
+bbcgoodfood.corn, bbcgoodfood.com
+bbva.es, bbva.es
+bebesyrnas.corn, bebesymas.com
+bedbathandbeyond.corn, bedbathandbeyond.com
+beeline.ru, beeline.ru
+beenverified.corn, beenverified.com
+behance.net, behance.net
+beinsports.corn, beinsports.com
+belastingdienst.nl, belastingdienst.nl
+belcy.jp, belcy.jp
+belezanaweb.corn.br, belezanaweb.com.br
+belk.corn, belk.com
+bell.ca, bell.ca
+bellernaison.jp, bellemaison.jp
+belnovosti.by, belnovosti.by
+benesse.ne.jp, benesse.ne.jp
+bengo4.corn, bengo4.com
+berkeley.edu, berkeley.edu
+berlin.de, berlin.de
+bershka.corn, bershka.com
+beslist.nl, beslist.nl
+bestbuy.ca, bestbuy.ca
+bestdeals.today, bestdeals.today
+bestfreetube.xxx, bestfreetube.xxx
+besthugecocks.corn, besthugecocks.com
+bestprice.gr, bestprice.gr
+bestreviews.guide, bestreviews.guide
+bethesda.net, bethesda.net
+betterhealth.vic.gov.au, betterhealth.vic.gov.au
+bettycrocker.corn, bettycrocker.com
+beyazperde.corn, beyazperde.com
+beytoote.corn, beytoote.com
+bfrntv.corn, bfmtv.com
+bg-rnarnrna.corn, bg-mamma.com
+bgr.corn, bgr.com
+bhaskar.corn, bhaskar.com
+bhg.corn, bhg.com
+bhphotovideo.corn, bhphotovideo.com
+bible.corn, bible.com
+biblehub.corn, biblehub.com
+biblestudytools.corn, biblestudytools.com
+bibliaon.corn, bibliaon.com
+bibliaonline.corn.br, bibliaonline.com.br
+biccarnera.corn, biccamera.com
+bienpublic.corn, bienpublic.com
+bigbasket.corn, bigbasket.com
+bigcartel.corn, bigcartel.com
+biggo.corn.tw, biggo.com.tw
+bigl.ua, bigl.ua
+biglots.corn, biglots.com
+bigw.corn.au, bigw.com.au
+bihar.gov.in, bihar.gov.in
+bikedekho.corn, bikedekho.com
+bikewale.corn, bikewale.com
+billboard.corn, billboard.com
+bilutv.org, bilutv.org
+binance.corn, binance.com
+binbaz.org.sa, binbaz.org.sa
+bingoporno.corn, bingoporno.com
+biobiochile.cl, biobiochile.cl
+biografiasyvidas.corn, biografiasyvidas.com
+biography.corn, biography.com
+bitbucket.org, bitbucket.org
+biteki.corn, biteki.com
+bitly.corn, bitly.com
+biz-journal.jp, biz-journal.jp
+biz.ua, biz.ua
+bizjournals.corn, bizjournals.com
+blabberrnouth.net, blabbermouth.net
+blastingnews.corn, blastingnews.com
+bldaily.corn, bldaily.com
+bleacherreport.corn, bleacherreport.com
+bleepingcornputer.corn, bleepingcomputer.com
+blesk.cz, blesk.cz
+blibli.corn, blibli.com
+blic.rs, blic.rs
+blikk.hu, blikk.hu
+blizzard.corn, blizzard.com
+blockchain.corn, blockchain.com
+blocket.se, blocket.se
+blog.hu, blog.hu
+blog.ir, blog.ir
+blog.jp, blog.jp
+blog.rne, blog.me
+blogfa.corn, blogfa.com
+blogger.corn, blogger.com
+blogirng.jp, blogimg.jp
+blogos.corn, blogos.com
+bloornberght.corn, bloomberght.com
+bluehost.corn, bluehost.com
+blueporns.corn, blueporns.com
+bluestacks.corn, bluestacks.com
+bluradio.corn, bluradio.com
+brni.ir, bmi.ir
+brnj.corn, bmj.com
+brno.corn, bmo.com
+brnstores.co.uk, bmstores.co.uk
+bne.corn.br, bne.com.br
+boafoda.corn, boafoda.com
+boardgarnegeek.corn, boardgamegeek.com
+boc.cn, boc.cn
+bodybuilding.corn, bodybuilding.com
+bokepxv.corn, bokepxv.com
+bol.corn, bol.com
+bola.net, bola.net
+bolasport.corn, bolasport.com
+bolavip.corn, bolavip.com
+bolshoyvopros.ru, bolshoyvopros.ru
+born.gov.au, bom.gov.au
+bonappetit.corn, bonappetit.com
+bongacarns.corn, bongacams.com
+bongdanet.vn, bongdanet.vn
+bongdaplus.vn, bongdaplus.vn
+bonprix.de, bonprix.de
+boohoo.corn, boohoo.com
+bookdepository.corn, bookdepository.com
+books.corn.tw, books.com.tw
+boostrnobile.corn, boostmobile.com
+boots.corn, boots.com
+boredpanda.corn, boredpanda.com
+bostonglobe.corn, bostonglobe.com
+boticario.corn.br, boticario.com.br
+boulanger.corn, boulanger.com
+boursorarna.corn, boursorama.com
+bouyguestelecorn.fr, bouyguestelecom.fr
+box.corn, box.com
+box.net, box.net
+boxofficernojo.corn, boxofficemojo.com
+boyfriendtv.corn, boyfriendtv.com
+boyner.corn.tr, boyner.com.tr
+br.corn, br.com
+br.de, br.de
+bradesco.corn.br, bradesco.com.br
+brainly.co.id, brainly.co.id
+brainly.corn, brainly.com
+brainly.corn.br, brainly.com.br
+brainly.in, brainly.in
+brainly.lat, brainly.lat
+brainly.pl, brainly.pl
+brainly.ro, brainly.ro
+brainyquote.corn, brainyquote.com
+brasil247.corn, brasil247.com
+brassring.corn, brassring.com
+bravotube.net, bravotube.net
+bravotv.corn, bravotv.com
+brazzers.corn, brazzers.com
+brazzersnetwork.corn, brazzersnetwork.com
+breitbart.corn, breitbart.com
+brigitte.de, brigitte.de
+brilio.net, brilio.net
+britishairways.corn, britishairways.com
+britishcouncil.org, britishcouncil.org
+brother.corn, brother.com
+brunch.co.kr, brunch.co.kr
+bryk.pl, bryk.pl
+bt.corn, bt.com
+bt.dk, bt.dk
+buenastareas.corn, buenastareas.com
+buenosaires.gob.ar, buenosaires.gob.ar
+buenterna.org, buentema.org
+buffer.corn, buffer.com
+bugaboo.tv, bugaboo.tv
+buienradar.nl, buienradar.nl
+bulbagarden.net, bulbagarden.net
+bulbul.su, bulbul.su
+bulururn.corn, bulurum.com
+bunnings.corn.au, bunnings.com.au
+bunshun.jp, bunshun.jp
+bunte.de, bunte.de
+busbud.corn, busbud.com
+buscaonibus.corn.br, buscaonibus.com.br
+buscapalabra.corn, buscapalabra.com
+buscapalabras.corn.ar, buscapalabras.com.ar
+buscape.corn.br, buscape.com.br
+business-standard.corn, business-standard.com
+business.site, business.site
+businessdictionary.corn, businessdictionary.com
+businessinsider.corn.pl, businessinsider.com.pl
+businessinsider.de, businessinsider.de
+businessweekly.corn.tw, businessweekly.com.tw
+but.fr, but.fr
+buzzfeednews.corn, buzzfeednews.com
+byjus.corn, byjus.com
+byoinnavi.jp, byoinnavi.jp
+byr.cn, byr.cn
+bz-berlin.de, bz-berlin.de
+c-and-a.corn, c-and-a.com
+c-ij.corn, c-ij.com
+cabelas.corn, cabelas.com
+cadenaser.corn, cadenaser.com
+caf.fr, caf.fr
+cafedelites.corn, cafedelites.com
+cafef.vn, cafef.vn
+caijing.corn.cn, caijing.com.cn
+cainiao.corn, cainiao.com
+caisse-epargne.fr, caisse-epargne.fr
+caixabank.es, caixabank.es
+calarneo.corn, calameo.com
+calciornercato.corn, calciomercato.com
+calculator.net, calculator.net
+calendly.corn, calendly.com
+caliente.rnx, caliente.mx
+callofduty.corn, callofduty.com
+carn4.corn, cam4.com
+carnara.leg.br, camara.leg.br
+carnbridge.org, cambridge.org
+carneraprive.corn, cameraprive.com
+carnpograndenews.corn.br, campograndenews.com.br
+carnpus-star.corn, campus-star.com
+canadapost.ca, canadapost.ca
+canadiantire.ca, canadiantire.ca
+canall.corn.co, canal1.com.co
+canalblog.corn, canalblog.com
+canaltech.corn.br, canaltech.com.br
+cancan.ro, cancan.ro
+cancaonova.corn, cancaonova.com
+cancer.gov, cancer.gov
+cancer.org, cancer.org
+capital.fr, capital.fr
+car-rnoby.jp, car-moby.jp
+car.gr, car.gr
+caracol.corn.co, caracol.com.co
+caracoltv.corn, caracoltv.com
+caracteristicas.co, caracteristicas.co
+caradisiac.corn, caradisiac.com
+caranddriver.corn, caranddriver.com
+carbuzz.corn, carbuzz.com
+carcarekiosk.corn, carcarekiosk.com
+cardekho.corn, cardekho.com
+care.corn, care.com
+careerbuilder.corn, careerbuilder.com
+careers36O.corn, careers360.com
+carfax.corn, carfax.com
+carid.corn, carid.com
+carrnax.corn, carmax.com
+carnival.corn, carnival.com
+carousell.corn, carousell.com
+carrefour.corn.br, carrefour.com.br
+carrefour.es, carrefour.es
+carrefour.fr, carrefour.fr
+carrosnaweb.corn.br, carrosnaweb.com.br
+cars.corn, cars.com
+carsensor.net, carsensor.net
+carsforsale.corn, carsforsale.com
+carters.corn, carters.com
+carview.co.jp, carview.co.jp
+carwale.corn, carwale.com
+cas.sk, cas.sk
+casa.it, casa.it
+casadellibro.corn, casadellibro.com
+casasbahia.corn.br, casasbahia.com.br
+castorarna.fr, castorama.fr
+castorarna.pl, castorama.pl
+catchnews.corn, catchnews.com
+catho.corn.br, catho.com.br
+catracalivre.corn.br, catracalivre.com.br
+cbc.ca, cbc.ca
+cbr.corn, cbr.com
+cbs.corn, cbs.com
+cbslocal.corn, cbslocal.com
+ccleaner.corn, ccleaner.com
+ccn.corn, ccn.com
+cda.pl, cda.pl
+cdrnx.gob.rnx, cdmx.gob.mx
+cdninstagrarn.corn, cdninstagram.com
+cdstrn.cn, cdstm.cn
+cea.corn.br, cea.com.br
+cec.corn.br, cec.com.br
+cekresi.corn, cekresi.com
+celebjihad.corn, celebjihad.com
+cellphones.corn.vn, cellphones.com.vn
+cengage.corn, cengage.com
+censor.net.ua, censor.net.ua
+centauro.corn.br, centauro.com.br
+centurylink.corn, centurylink.com
+cerdas.corn, cerdas.com
+ceskatelevize.cz, ceskatelevize.cz
+ch3thailand.corn, ch3thailand.com
+charnpion.gg, champion.gg
+charnpionat.corn, championat.com
+change.org, change.org
+channel4.corn, channel4.com
+channelnewsasia.corn, channelnewsasia.com
+cheapflights.corn, cheapflights.com
+cheapoair.corn, cheapoair.com
+cheaptickets.corn, cheaptickets.com
+cheatsheet.corn, cheatsheet.com
+check24.de, check24.de
+checkraka.corn, checkraka.com
+cheezburger.corn, cheezburger.com
+chefkoch.de, chefkoch.de
+chess.corn, chess.com
+chevrolet.corn, chevrolet.com
+chewy.corn, chewy.com
+chicagotribune.corn, chicagotribune.com
+chick-fil-a.corn, chick-fil-a.com
+childrensplace.corn, childrensplace.com
+chilevision.cl, chilevision.cl
+chillizet.pl, chillizet.pl
+china.corn, china.com
+china.corn.cn, china.com.cn
+chinadaily.corn.cn, chinadaily.com.cn
+chinaz.corn, chinaz.com
+chiphell.corn, chiphell.com
+chiquipedia.corn, chiquipedia.com
+chochox.corn, chochox.com
+chollornetro.corn, chollometro.com
+chordify.net, chordify.net
+chordtabs.in.th, chordtabs.in.th
+chosun.corn, chosun.com
+chotot.corn, chotot.com
+chouftv.rna, chouftv.ma
+chp.org.tr, chp.org.tr
+chsi.corn.cn, chsi.com.cn
+cian.ru, cian.ru
+ciatr.jp, ciatr.jp
+cic.gc.ca, cic.gc.ca
+ciceksepeti.corn, ciceksepeti.com
+cienradios.corn, cienradios.com
+cifraclub.corn.br, cifraclub.com.br
+cirna4u.tv, cima4u.tv
+cirnaclub.corn, cimaclub.com
+cirnri.corn, cimri.com
+cinecolornbia.corn, cinecolombia.com
+cinernablend.corn, cinemablend.com
+cinernagia.ro, cinemagia.ro
+cinernark.corn, cinemark.com
+cinernatoday.jp, cinematoday.jp
+cinernex.corn, cinemex.com
+cineplex.corn, cineplex.com
+cinepolis.corn, cinepolis.com
+cisco.corn, cisco.com
+citi.corn, citi.com
+citilink.ru, citilink.ru
+citrus.ua, citrus.ua
+city-data.corn, city-data.com
+cityheaven.net, cityheaven.net
+ciudad.corn.ar, ciudad.com.ar
+civico.corn, civico.com
+cklOl.corn, ck101.com
+clalit.co.il, clalit.co.il
+claro.corn.ar, claro.com.ar
+claro.corn.br, claro.com.br
+clasohlson.corn, clasohlson.com
+classrnates.corn, classmates.com
+cleartax.in, cleartax.in
+cleartrip.corn, cleartrip.com
+clevelandclinic.org, clevelandclinic.org
+clever.corn, clever.com
+clicccar.corn, clicccar.com
+clickfunnels.corn, clickfunnels.com
+clicrbs.corn.br, clicrbs.com.br
+clien.net, clien.net
+clirna.corn, clima.com
+clirnaternpo.corn.br, climatempo.com.br
+clipconverter.cc, clipconverter.cc
+clips4sale.corn, clips4sale.com
+closerrnag.fr, closermag.fr
+cloudflare.corn, cloudflare.com
+clubedohardware.corn.br, clubedohardware.com.br
+clubfactory.corn, clubfactory.com
+clubic.corn, clubic.com
+crnjornal.pt, cmjornal.pt
+crnoa.jp, cmoa.jp
+crnu.edu, cmu.edu
+cnbcindonesia.corn, cnbcindonesia.com
+cnbeta.corn, cnbeta.com
+cnblogs.corn, cnblogs.com
+cne.gob.ec, cne.gob.ec
+cnki.corn.cn, cnki.com.cn
+cnki.net, cnki.net
+cnnarnador.corn, cnnamador.com
+cnnic.cn, cnnic.cn
+cnnindonesia.corn, cnnindonesia.com
+cnnturk.corn, cnnturk.com
+cnrtl.fr, cnrtl.fr
+cnzz.corn, cnzz.com
+coches.net, coches.net
+cochrane.org, cochrane.org
+cocolog-nifty.corn, cocolog-nifty.com
+codashop.corn, codashop.com
+codecanyon.net, codecanyon.net
+codepen.io, codepen.io
+codeproject.corn, codeproject.com
+codycross.info, codycross.info
+codycrossanswers.org, codycrossanswers.org
+coinbase.corn, coinbase.com
+coinrnarketcap.corn, coinmarketcap.com
+coinrnill.corn, coinmill.com
+coldwellbankerhornes.corn, coldwellbankerhomes.com
+colgate.corn, colgate.com
+collegeboard.org, collegeboard.org
+collinsdictionary.corn, collinsdictionary.com
+colornbia.corn, colombia.com
+colorlib.corn, colorlib.com
+colurnbia.edu, columbia.edu
+corn.ru, com.ru
+cornandotorrents.corn, comandotorrents.com
+cornicbook.corn, comicbook.com
+corningsoon.it, comingsoon.it
+cornrnbank.corn.au, commbank.com.au
+cornrnentcarnarche.corn, commentcamarche.com
+cornrnentcarnarche.net, commentcamarche.net
+cornrnonhealth.corn.tw, commonhealth.com.tw
+cornrnonsensernedia.org, commonsensemedia.org
+cornpanieshouse.gov.uk, companieshouse.gov.uk
+cornparethernarket.corn, comparethemarket.com
+cornplex.corn, complex.com
+cornputerbild.de, computerbild.de
+cornputerhope.corn, computerhope.com
+cornputerhoy.corn, computerhoy.com
+cornputrabajo.corn.co, computrabajo.com.co
+cornputrabajo.corn.rnx, computrabajo.com.mx
+concepto.de, concepto.de
+conceptodefinicion.de, conceptodefinicion.de
+confirrnit.corn, confirmit.com
+conforarna.fr, conforama.fr
+conicyt.cl, conicyt.cl
+conjur.corn.br, conjur.com.br
+conrnishijos.corn, conmishijos.com
+constantcontact.corn, constantcontact.com
+consultant.ru, consultant.ru
+consultarernedios.corn.br, consultaremedios.com.br
+consurner.es, consumer.es
+consurneraffairs.corn, consumeraffairs.com
+consurnerreports.org, consumerreports.org
+contabeis.corn.br, contabeis.com.br
+converse.corn, converse.com
+coocan.jp, coocan.jp
+cookieandkate.corn, cookieandkate.com
+cookpad.corn, cookpad.com
+coolblue.nl, coolblue.nl
+coolinarika.corn, coolinarika.com
+coolrorn.corn.au, coolrom.com.au
+cooperativa.cl, cooperativa.cl
+coppel.corn, coppel.com
+cornell.edu, cornell.edu
+correio24horas.corn.br, correio24horas.com.br
+correiobraziliense.corn.br, correiobraziliense.com.br
+correos.es, correos.es
+corriere.it, corriere.it
+corrieredellosport.it, corrieredellosport.it
+cosrne.net, cosme.net
+cosrno.ru, cosmo.ru
+cosrnopolitan.corn, cosmopolitan.com
+cosrnopolitan.fr, cosmopolitan.fr
+costco.ca, costco.ca
+costco.corn, costco.com
+coub.corn, coub.com
+countryliving.corn, countryliving.com
+coupang.corn, coupang.com
+coupons.corn, coupons.com
+coursehero.corn, coursehero.com
+coursera.org, coursera.org
+cox.corn, cox.com
+crl73.corn, cr173.com
+cra-arc.gc.ca, cra-arc.gc.ca
+creativernarket.corn, creativemarket.com
+credit-agricole.fr, credit-agricole.fr
+creditkarrna.corn, creditkarma.com
+creditrnutuel.fr, creditmutuel.fr
+crhoy.corn, crhoy.com
+cricketwireless.corn, cricketwireless.com
+crictracker.corn, crictracker.com
+criteo.corn, criteo.com
+cronica.corn.ar, cronica.com.ar
+cronista.corn, cronista.com
+crunchbase.corn, crunchbase.com
+crunchyroll.corn, crunchyroll.com
+crutchfield.corn, crutchfield.com
+csdn.net, csdn.net
+csfd.cz, csfd.cz
+csod.corn, csod.com
+css-tricks.corn, css-tricks.com
+ctfile.corn, ctfile.com
+ctrip.corn, ctrip.com
+ctvnews.ca, ctvnews.ca
+cuatro.corn, cuatro.com
+cucchiaio.it, cucchiaio.it
+cuisineactuelle.fr, cuisineactuelle.fr
+cuisineaz.corn, cuisineaz.com
+culturarnix.corn, culturamix.com
+curnhuriyet.corn.tr, cumhuriyet.com.tr
+curnlouder.corn, cumlouder.com
+cure-naturali.it, cure-naturali.it
+curiouscat.rne, curiouscat.me
+currys.co.uk, currys.co.uk
+curseforge.corn, curseforge.com
+custhelp.corn, custhelp.com
+cutestat.corn, cutestat.com
+cvs.corn, cvs.com
+cwb.gov.tw, cwb.gov.tw
+cyberleninka.ru, cyberleninka.ru
+cylex.de, cylex.de
+cyzowornan.corn, cyzowoman.com
+dafiti.corn.br, dafiti.com.br
+dafont.corn, dafont.com
+dagbladet.no, dagbladet.no
+dagospia.corn, dagospia.com
+daily.co.jp, daily.co.jp
+dailycaller.corn, dailycaller.com
+dailyhive.corn, dailyhive.com
+dailyhunt.in, dailyhunt.in
+dailyrnedicalinfo.corn, dailymedicalinfo.com
+dailynews.co.th, dailynews.co.th
+dailypost.ng, dailypost.ng
+dailystar.co.uk, dailystar.co.uk
+dailywire.corn, dailywire.com
+dallasnews.corn, dallasnews.com
+danawa.corn, danawa.com
+dangdang.corn, dangdang.com
+dantri.corn.vn, dantri.com.vn
+daraz.pk, daraz.pk
+darty.corn, darty.com
+daserste.de, daserste.de
+dasoertliche.de, dasoertliche.de
+dastelefonbuch.de, dastelefonbuch.de
+davidsbridal.corn, davidsbridal.com
+dawn.corn, dawn.com
+dazn.corn, dazn.com
+dcard.tw, dcard.tw
+dcinside.corn, dcinside.com
+dcrn-b.jp, dcm-b.jp
+ddnavi.corn, ddnavi.com
+deadline.corn, deadline.com
+deadspin.corn, deadspin.com
+dealabs.corn, dealabs.com
+debate.corn.rnx, debate.com.mx
+debenharns.corn, debenhams.com
+decathlon.es, decathlon.es
+decathlon.fr, decathlon.fr
+decathlon.it, decathlon.it
+deccanherald.corn, deccanherald.com
+decolar.corn, decolar.com
+decorfacil.corn, decorfacil.com
+dedernan.ro, dedeman.ro
+deepl.corn, deepl.com
+deezer.corn, deezer.com
+definicion.de, definicion.de
+definicionabc.corn, definicionabc.com
+deichrnann.corn, deichmann.com
+deita.ru, deita.ru
+dek-d.corn, dek-d.com
+delfi.lt, delfi.lt
+delfi.lv, delfi.lv
+delish.corn, delish.com
+delta.corn, delta.com
+denfarninicogarner.jp, denfaminicogamer.jp
+dengeki.corn, dengeki.com
+dengekionline.corn, dengekionline.com
+denik.cz, denik.cz
+depor.corn, depor.com
+derwesten.de, derwesten.de
+descornplica.corn.br, descomplica.com.br
+desjardins.corn, desjardins.com
+deskgrarn.net, deskgram.net
+desrnos.corn, desmos.com
+despegar.corn.ar, despegar.com.ar
+despegar.corn.rnx, despegar.com.mx
+detrnir.ru, detmir.ru
+detran.rng.gov.br, detran.mg.gov.br
+detran.sp.gov.br, detran.sp.gov.br
+deunopostehoje.corn, deunopostehoje.com
+deutschepost.de, deutschepost.de
+dexerto.corn, dexerto.com
+dexonline.ro, dexonline.ro
+dhl.corn, dhl.com
+dhnet.be, dhnet.be
+dhs.gov, dhs.gov
+dialog.ua, dialog.ua
+diarnond.jp, diamond.jp
+dianping.corn, dianping.com
+diariobasta.corn, diariobasta.com
+diariocorreo.pe, diariocorreo.pe
+diariodocentrodornundo.corn.br, diariodocentrodomundo.com.br
+diariolaprovinciasj.corn, diariolaprovinciasj.com
+diariornotor.corn, diariomotor.com
+diarioonline.corn.br, diarioonline.com.br
+diariopopular.corn.ar, diariopopular.com.ar
+dicio.corn.br, dicio.com.br
+dicionarioinforrnal.corn.br, dicionarioinformal.com.br
+dickssportinggoods.corn, dickssportinggoods.com
+dict.cc, dict.cc
+dienrnayxanh.corn, dienmayxanh.com
+dietdoctor.corn, dietdoctor.com
+digi24.ro, digi24.ro
+digikala.corn, digikala.com
+digisport.ro, digisport.ro
+digitalocean.corn, digitalocean.com
+digitalspy.corn, digitalspy.com
+digitaltrends.corn, digitaltrends.com
+dikaiologitika.gr, dikaiologitika.gr
+dilei.it, dilei.it
+dillards.corn, dillards.com
+directv.corn, directv.com
+diretta.it, diretta.it
+discogs.corn, discogs.com
+discover.corn, discover.com
+discuss.corn.hk, discuss.com.hk
+disney.corn, disney.com
+disqus.corn, disqus.com
+distractify.corn, distractify.com
+divar.ir, divar.ir
+divinity.es, divinity.es
+divxtotal3.net, divxtotal3.net
+diy.corn, diy.com
+diyadinnet.corn, diyadinnet.com
+diyanet.gov.tr, diyanet.gov.tr
+dkn.tv, dkn.tv
+dlsite.corn, dlsite.com
+drn.de, dm.de
+drnkt-sp.jp, dmkt-sp.jp
+drnzj.corn, dmzj.com
+dnaindia.corn, dnaindia.com
+dndbeyond.corn, dndbeyond.com
+dndnha.corn, dndnha.com
+dnevnik.hr, dnevnik.hr
+dnevnik.ru, dnevnik.ru
+dni.ru, dni.ru
+dns-shop.ru, dns-shop.ru
+dobreprograrny.pl, dobreprogramy.pl
+docin.corn, docin.com
+docker.corn, docker.com
+docorno.ne.jp, docomo.ne.jp
+docsity.corn, docsity.com
+doctissirno.fr, doctissimo.fr
+doctolib.fr, doctolib.fr
+doctoralia.corn.br, doctoralia.com.br
+doctoralia.corn.rnx, doctoralia.com.mx
+doctoralia.es, doctoralia.es
+docusign.corn, docusign.com
+doityourself.corn, doityourself.com
+doktersehat.corn, doktersehat.com
+doktorsitesi.corn, doktorsitesi.com
+doktortakvirni.corn, doktortakvimi.com
+dollargeneral.corn, dollargeneral.com
+dollartree.corn, dollartree.com
+dornain.corn.au, domain.com.au
+dorninos.corn, dominos.com
+dornodi.pl, domodi.pl
+donanirnhaber.corn, donanimhaber.com
+donga.corn, donga.com
+donpornogratis.corn, donpornogratis.com
+donya-e-eqtesad.corn, donya-e-eqtesad.com
+doodle.corn, doodle.com
+doordash.corn, doordash.com
+dorarnatv.ru, doramatv.ru
+douban.corn, douban.com
+douyu.corn, douyu.com
+doviz.corn, doviz.com
+downdetector.corn, downdetector.com
+download.corn.vn, download.com.vn
+downloadastro.corn, downloadastro.com
+doz.pl, doz.pl
+dpd.de, dpd.de
+dpreview.corn, dpreview.com
+dr.corn.tr, dr.com.tr
+dr.dk, dr.dk
+draxe.corn, draxe.com
+drearn.co.id, dream.co.id
+drearnstirne.corn, dreamstime.com
+dribbble.corn, dribbble.com
+drikpanchang.corn, drikpanchang.com
+drive2.ru, drive2.ru
+drivernusic.rne, drivemusic.me
+drogaraia.corn.br, drogaraia.com.br
+droid-life.corn, droid-life.com
+drtuber.corn, drtuber.com
+drudgereport.corn, drudgereport.com
+drugs.corn, drugs.com
+dstv.corn, dstv.com
+dsw.corn, dsw.com
+dtac.co.th, dtac.co.th
+duckduckgo.corn, duckduckgo.com
+duden.de, duden.de
+durnrnies.corn, dummies.com
+duolingo.corn, duolingo.com
+dw.corn, dw.com
+dy2Ol8.corn, dy2018.com
+dytt8.net, dytt8.net
+dziennikzachodni.pl, dziennikzachodni.pl
+e-hentai.org, e-hentai.org
+e-katalog.ru, e-katalog.ru
+e-rnap.ne.jp, e-map.ne.jp
+e-rnonsite.corn, e-monsite.com
+el.ru, e1.ru
+ea.corn, ea.com
+easeus.corn, easeus.com
+easports.corn, easports.com
+eastday.corn, eastday.com
+eastrnoney.corn, eastmoney.com
+easybib.corn, easybib.com
+easyjet.corn, easyjet.com
+eater.corn, eater.com
+eb.rnil.br, eb.mil.br
+eba.gov.tr, eba.gov.tr
+ebah.corn.br, ebah.com.br
+ebates.corn, ebates.com
+ebay.ca, ebay.ca
+ebay.ie, ebay.ie
+ebc.net.tw, ebc.net.tw
+ebscohost.corn, ebscohost.com
+ecartelera.corn, ecartelera.com
+econornia.gov.br, economia.gov.br
+econornictirnes.corn, economictimes.com
+econornist.corn, economist.com
+ecosia.org, ecosia.org
+ecured.cu, ecured.cu
+ed.gov, ed.gov
+eda.ru, eda.ru
+edf.fr, edf.fr
+edirndorna.ru, edimdoma.ru
+edrnodo.corn, edmodo.com
+edrnunds.corn, edmunds.com
+edornex.gob.rnx, edomex.gob.mx
+edrearns.es, edreams.es
+educacion.es, educacion.es
+educarnaisbrasil.corn.br, educamaisbrasil.com.br
+edupage.org, edupage.org
+edx.org, edx.org
+ee.co.uk, ee.co.uk
+eenadu.net, eenadu.net
+ef.corn, ef.com
+eg.ru, eg.ru
+egitirnhane.corn, egitimhane.com
+eiga.corn, eiga.com
+eitb.eus, eitb.eus
+ekitan.corn, ekitan.com
+ekstrabladet.dk, ekstrabladet.dk
+el-nacional.corn, el-nacional.com
+elbalad.news, elbalad.news
+elbilad.net, elbilad.net
+elbotola.corn, elbotola.com
+elcolornbiano.corn, elcolombiano.com
+elcornercio.corn, elcomercio.com
+elcornercio.pe, elcomercio.pe
+elcorteingles.es, elcorteingles.es
+eldestapeweb.corn, eldestapeweb.com
+eldia.corn, eldia.com
+eldiario.es, eldiario.es
+eldiariony.corn, eldiariony.com
+eldinarno.cl, eldinamo.cl
+eldorado.ru, eldorado.ru
+eleconornista.es, eleconomista.es
+elektroda.pl, elektroda.pl
+elernpleo.corn, elempleo.com
+elespanol.corn, elespanol.com
+elespectador.corn, elespectador.com
+elfagr.corn, elfagr.com
+elgenero.corn, elgenero.com
+elgrafico.rnx, elgrafico.mx
+elheraldo.co, elheraldo.co
+elirnparcial.corn, elimparcial.com
+elitedaily.corn, elitedaily.com
+elkhabar.corn, elkhabar.com
+elle.corn, elle.com
+elle.fr, elle.fr
+elrnogaz.corn, elmogaz.com
+elnuevodia.corn, elnuevodia.com
+elnuevoherald.corn, elnuevoherald.com
+elo7.corn.br, elo7.com.br
+elobservador.corn.uy, elobservador.com.uy
+elpais.corn.co, elpais.com.co
+elpais.corn.uy, elpais.com.uy
+elperiodico.corn, elperiodico.com
+elsalvador.corn, elsalvador.com
+elsevier.corn, elsevier.com
+elsevier.es, elsevier.es
+elsol.corn.ar, elsol.com.ar
+elsoldernexico.corn.rnx, elsoldemexico.com.mx
+elsoldepuebla.corn.rnx, elsoldepuebla.com.mx
+eltiernpo.corn, eltiempo.com
+eltiernpo.es, eltiempo.es
+eltrecetv.corn.ar, eltrecetv.com.ar
+eluniversal.corn.co, eluniversal.com.co
+eluniverso.corn, eluniverso.com
+elwatannews.corn, elwatannews.com
+ern.corn.br, em.com.br
+ernag.hu, emag.hu
+ernedicinehealth.corn, emedicinehealth.com
+ernirates.corn, emirates.com
+ernlakkulisi.corn, emlakkulisi.com
+ernojipedia.org, emojipedia.org
+ernol.corn, emol.com
+ernpflix.corn, empflix.com
+ernpik.corn, empik.com
+ernpregos.corn.br, empregos.com.br
+ernuparadise.rne, emuparadise.me
+en-hyouban.corn, en-hyouban.com
+en-japan.corn, en-japan.com
+encyclo.nl, encyclo.nl
+enfernenino.corn, enfemenino.com
+eniro.se, eniro.se
+enjoei.corn.br, enjoei.com.br
+enotes.corn, enotes.com
+enrt.eu, enrt.eu
+ensonhaber.corn, ensonhaber.com
+enterprise.corn, enterprise.com
+entrepreneur.corn, entrepreneur.com
+enuygun.corn, enuygun.com
+envato.corn, envato.com
+eobuwie.corn.pl, eobuwie.com.pl
+eodev.corn, eodev.com
+eonline.corn, eonline.com
+epark.jp, epark.jp
+epey.corn, epey.com
+epicurious.corn, epicurious.com
+eplus.jp, eplus.jp
+epochtirnes.corn, epochtimes.com
+eporner.corn, eporner.com
+epttavrn.corn, epttavm.com
+erail.in, erail.in
+ero-video.net, ero-video.net
+eroterest.net, eroterest.net
+escavador.corn, escavador.com
+eset.corn, eset.com
+eska.pl, eska.pl
+espn.corn.br, espn.com.br
+espn.corn.rnx, espn.com.mx
+espncricinfo.corn, espncricinfo.com
+espreso.rs, espreso.rs
+esquire.corn, esquire.com
+essen-und-trinken.de, essen-und-trinken.de
+estacio.br, estacio.br
+estadao.corn.br, estadao.com.br
+estantevirtual.corn.br, estantevirtual.com.br
+estrategiaconcursos.corn.br, estrategiaconcursos.com.br
+estrepublicain.fr, estrepublicain.fr
+esuteru.corn, esuteru.com
+etonline.corn, etonline.com
+etrade.corn, etrade.com
+ettoday.net, ettoday.net
+euro.corn.pl, euro.com.pl
+eurogarner.net, eurogamer.net
+euronews.corn, euronews.com
+europapress.es, europapress.es
+europel.fr, europe1.fr
+euroresidentes.corn, euroresidentes.com
+eurosport.corn, eurosport.com
+eurosport.fr, eurosport.fr
+eurosport.ru, eurosport.ru
+eurozpravy.cz, eurozpravy.cz
+eva.vn, eva.vn
+eventbrite.co.uk, eventbrite.co.uk
+eventirn.de, eventim.de
+evernote.corn, evernote.com
+everydayhealth.corn, everydayhealth.com
+everydayhealth.corn.tw, everydayhealth.com.tw
+evite.corn, evite.com
+ew.corn, ew.com
+exblog.jp, exblog.jp
+excelsior.corn.rnx, excelsior.com.mx
+exchange-rates.org, exchange-rates.org
+exhentai.org, exhentai.org
+exito.corn, exito.com
+exlibrisgroup.corn, exlibrisgroup.com
+exoclick.corn, exoclick.com
+expansion.corn, expansion.com
+expedia.ca, expedia.ca
+expedia.co.uk, expedia.co.uk
+experian.corn, experian.com
+express.de, express.de
+expressbydgoski.pl, expressbydgoski.pl
+expressen.se, expressen.se
+expressilustrowany.pl, expressilustrowany.pl
+expressvpn.corn, expressvpn.com
+extra.corn.br, extra.com.br
+extratipp.corn, extratipp.com
+eyny.corn, eyny.com
+eztv.io, eztv.io
+faapy.corn, faapy.com
+facilisirno.corn, facilisimo.com
+fakt.pl, fakt.pl
+fakti.bg, fakti.bg
+fakty.ua, fakty.ua
+falabella.corn, falabella.com
+falabella.corn.co, falabella.com.co
+falabella.corn.pe, falabella.com.pe
+farnilydoctor.corn.cn, familydoctor.com.cn
+farnilyhandyrnan.corn, familyhandyman.com
+farnilysearch.org, familysearch.org
+farnitsu.corn, famitsu.com
+farnousbirthdays.corn, famousbirthdays.com
+fanatik.corn.tr, fanatik.com.tr
+fanatik.ro, fanatik.ro
+fandango.lat, fandango.lat
+fanfiction.net, fanfiction.net
+fang.corn, fang.com
+fanpage.it, fanpage.it
+fantasti.cc, fantasti.cc
+fapl8.net, fap18.net
+fapality.corn, fapality.com
+farfetch.corn, farfetch.com
+farpost.ru, farpost.ru
+farsnews.corn, farsnews.com
+fashion-press.net, fashion-press.net
+fashionnova.corn, fashionnova.com
+fastcornpany.corn, fastcompany.com
+fastpeoplesearch.corn, fastpeoplesearch.com
+fastshop.corn.br, fastshop.com.br
+fatakat.corn, fatakat.com
+fatalrnodel.corn, fatalmodel.com
+fatosdesconhecidos.corn.br, fatosdesconhecidos.com.br
+fayerwayer.corn, fayerwayer.com
+faz.net, faz.net
+fazenda.sp.gov.br, fazenda.sp.gov.br
+fb.ru, fb.ru
+fda.gov, fda.gov
+fdj.fr, fdj.fr
+feebee.corn.tw, feebee.com.tw
+feedly.corn, feedly.com
+fernina.hu, femina.hu
+fernrneactuelle.fr, femmeactuelle.fr
+feng.corn, feng.com
+fernsehserien.de, fernsehserien.de
+fetlife.corn, fetlife.com
+fextralife.corn, fextralife.com
+fff.fr, fff.fr
+fgv.br, fgv.br
+fiat.corn.br, fiat.com.br
+ficbook.net, ficbook.net
+fidelity.corn, fidelity.com
+file-up.org, file-up.org
+filecrypt.cc, filecrypt.cc
+filehippo.corn, filehippo.com
+filgoal.corn, filgoal.com
+filrn2rnovie.ws, film2movie.ws
+filrnaffinity.corn, filmaffinity.com
+filrnibeat.corn, filmibeat.com
+filrnow.corn, filmow.com
+filrnstarts.de, filmstarts.de
+firnela.corn, fimela.com
+finance.ua, finance.ua
+financialexpress.corn, financialexpress.com
+findagrave.corn, findagrave.com
+finddrearnjobs.corn, finddreamjobs.com
+findlaw.corn, findlaw.com
+fingerhut.corn, fingerhut.com
+finishline.corn, finishline.com
+finn.no, finn.no
+firrnasec.corn, firmasec.com
+firrny.cz, firmy.cz
+firstcry.corn, firstcry.com
+firstpost.corn, firstpost.com
+fishki.net, fishki.net
+fitbit.corn, fitbit.com
+fiverr.corn, fiverr.com
+fixya.corn, fixya.com
+flashback.org, flashback.org
+flashscore.corn, flashscore.com
+flaticon.corn, flaticon.com
+flightaware.corn, flightaware.com
+flightradar24.corn, flightradar24.com
+flightstats.corn, flightstats.com
+flirt4free.corn, flirt4free.com
+flo.corn.tr, flo.com.tr
+floryday.corn, floryday.com
+fluentu.corn, fluentu.com
+flypgs.corn, flypgs.com
+frndos.cl, fmdos.cl
+frnkorea.corn, fmkorea.com
+frnovies.to, fmovies.to
+fnac.pt, fnac.pt
+fnn.jp, fnn.jp
+focus.cn, focus.cn
+focus.de, focus.de
+folhadirigida.corn.br, folhadirigida.com.br
+folhavitoria.corn.br, folhavitoria.com.br
+fontawesorne.corn, fontawesome.com
+food52.corn, food52.com
+foodnetwork.corn, foodnetwork.com
+foody.vn, foody.vn
+fool.corn, fool.com
+footOl.corn, foot01.com
+footlocker.corn, footlocker.com
+footrnercato.net, footmercato.net
+forbes.corn.rnx, forbes.com.mx
+force.corn, force.com
+ford.corn, ford.com
+forever2l.corn, forever21.com
+forgeofernpires.corn, forgeofempires.com
+forrnulal.corn, formula1.com
+forrnulatv.corn, formulatv.com
+forocoches.corn, forocoches.com
+fortnitetracker.corn, fortnitetracker.com
+forurn.hr, forum.hr
+fotocasa.es, fotocasa.es
+fotograrnas.es, fotogramas.es
+fotornac.corn.tr, fotomac.com.tr
+fotostrana.ru, fotostrana.ru
+foursquare.corn, foursquare.com
+fox.corn.tr, fox.com.tr
+foxbusiness.corn, foxbusiness.com
+foxporns.corn, foxporns.com
+foxsports.corn, foxsports.com
+foxsports.corn.br, foxsports.com.br
+foxtube.corn, foxtube.com
+fptshop.corn.vn, fptshop.com.vn
+france.tv, france.tv
+francebleu.fr, francebleu.fr
+frandroid.corn, frandroid.com
+fravega.corn, fravega.com
+free-sex-video.net, free-sex-video.net
+freearabsexx.corn, freearabsexx.com
+freebitco.in, freebitco.in
+freecodecarnp.org, freecodecamp.org
+freejobalert.corn, freejobalert.com
+freelancer.corn, freelancer.com
+freep.corn, freep.com
+freepik.corn, freepik.com
+freshdesk.corn, freshdesk.com
+fresherslive.corn, fresherslive.com
+fril.jp, fril.jp
+friv.corn, friv.com
+frrntr.corn, frmtr.com
+frorn-ua.corn, from-ua.com
+ft.corn, ft.com
+fudan.edu.cn, fudan.edu.cn
+fujitv.co.jp, fujitv.co.jp
+funda.nl, funda.nl
+fuq.corn, fuq.com
+furaffinity.net, furaffinity.net
+futbin.corn, futbin.com
+futhead.corn, futhead.com
+futura-sciences.corn, futura-sciences.com
+g2a.corn, g2a.com
+gaadiwaadi.corn, gaadiwaadi.com
+gadgethacks.corn, gadgethacks.com
+gadgetsnow.corn, gadgetsnow.com
+gala.de, gala.de
+gala.fr, gala.fr
+garne8.jp, game8.jp
+garneanswers.net, gameanswers.net
+garnebase.corn.tw, gamebase.com.tw
+garneguardian.net, gameguardian.net
+garnek.vn, gamek.vn
+garneloft.corn, gameloft.com
+garnepress.gg, gamepress.gg
+garnepressure.corn, gamepressure.com
+garner.corn.tw, gamer.com.tw
+garnerant.corn, gamerant.com
+garnerch.corn, gamerch.com
+garnersky.corn, gamersky.com
+garnesradar.corn, gamesradar.com
+garnestop.corn, gamestop.com
+garnewith.jp, gamewith.jp
+garnrna.nl, gamma.nl
+ganeshaspeaks.corn, ganeshaspeaks.com
+gap.corn, gap.com
+garanti.corn.tr, garanti.com.tr
+garbarino.corn, garbarino.com
+gardeningknowhow.corn, gardeningknowhow.com
+garena.corn, garena.com
+garena.tw, garena.tw
+garena.vn, garena.vn
+garrnin.corn, garmin.com
+gasbuddy.corn, gasbuddy.com
+gazeta.pl, gazeta.pl
+gazeta.ru, gazeta.ru
+gazetadopovo.corn.br, gazetadopovo.com.br
+gazetaesportiva.corn, gazetaesportiva.com
+gazetaexpress.corn, gazetaexpress.com
+gazetaonline.corn.br, gazetaonline.com.br
+gazetawroclawska.pl, gazetawroclawska.pl
+gazeteduvar.corn.tr, gazeteduvar.com.tr
+gazzetta.gr, gazzetta.gr
+gazzetta.it, gazzetta.it
+gdz.ru, gdz.ru
+gearpatrol.corn, gearpatrol.com
+geeksforgeeks.org, geeksforgeeks.org
+geforce.corn, geforce.com
+geico.corn, geico.com
+gelocal.it, gelocal.it
+gencat.cat, gencat.cat
+geneanet.org, geneanet.org
+generation-nt.corn, generation-nt.com
+geniuskitchen.corn, geniuskitchen.com
+genk.vn, genk.vn
+genndi.corn, genndi.com
+gentside.corn, gentside.com
+geocities.jp, geocities.jp
+geogebra.org, geogebra.org
+gestiopolis.corn, gestiopolis.com
+getbootstrap.corn, getbootstrap.com
+getintopc.corn, getintopc.com
+getjar.corn, getjar.com
+getninjas.corn.br, getninjas.com.br
+getpocket.corn, getpocket.com
+gettyirnages.corn, gettyimages.com
+getyourguide.corn, getyourguide.com
+getyourguide.es, getyourguide.es
+ghanaweb.corn, ghanaweb.com
+giallozafferano.it, giallozafferano.it
+gidfilrn.ru, gidfilm.ru
+giffgaff.corn, giffgaff.com
+gifi.fr, gifi.fr
+giga.de, giga.de
+gigazine.net, gigazine.net
+girlschannel.net, girlschannel.net
+gisrneteo.ua, gismeteo.ua
+github.io, github.io
+gitlab.corn, gitlab.com
+gittigidiyor.corn, gittigidiyor.com
+gizrnochina.corn, gizmochina.com
+gizrnodo.corn, gizmodo.com
+gizrnodo.jp, gizmodo.jp
+gl5.ru, gl5.ru
+glarnour.es, glamour.es
+glassdoor.co.in, glassdoor.co.in
+glearn.io, gleam.io
+globalnews.ca, globalnews.ca
+globe.corn.ph, globe.com.ph
+gls-group.eu, gls-group.eu
+grnail.corn, gmail.com
+grnanetwork.corn, gmanetwork.com
+grnarket.co.kr, gmarket.co.kr
+grnw.cn, gmw.cn
+grnx.net, gmx.net
+gnavi.co.jp, gnavi.co.jp
+gnula.nu, gnula.nu
+godaddy.corn, godaddy.com
+godlife.corn, godlife.com
+goferninin.de, gofeminin.de
+gog.corn, gog.com
+gogoanirne.io, gogoanime.io
+goibibo.corn, goibibo.com
+goindigo.in, goindigo.in
+golos.ua, golos.ua
+gorne.corn.cn, gome.com.cn
+goo-net.corn, goo-net.com
+goodhousekeeping.corn, goodhousekeeping.com
+goodrx.corn, goodrx.com
+google.ae, google.ae
+google.at, google.at
+google.az, google.az
+google.be, google.be
+google.bg, google.bg
+google.ch, google.ch
+google.cn, google.cn
+google.co.ao, google.co.ao
+google.co.il, google.co.il
+google.co.nz, google.co.nz
+google.co.ve, google.co.ve
+google.co.za, google.co.za
+google.corn.ec, google.com.ec
+google.corn.eg, google.com.eg
+google.corn.hk, google.com.hk
+google.corn.kw, google.com.kw
+google.corn.ly, google.com.ly
+google.corn.rny, google.com.my
+google.corn.ng, google.com.ng
+google.corn.pe, google.com.pe
+google.corn.ph, google.com.ph
+google.corn.pk, google.com.pk
+google.corn.sa, google.com.sa
+google.corn.sg, google.com.sg
+google.corn.ua, google.com.ua
+google.corn.vn, google.com.vn
+google.cz, google.cz
+google.dk, google.dk
+google.dz, google.dz
+google.fi, google.fi
+google.gr, google.gr
+google.hr, google.hr
+google.hu, google.hu
+google.ie, google.ie
+google.kz, google.kz
+google.lk, google.lk
+google.no, google.no
+google.ro, google.ro
+google.rs, google.rs
+google.se, google.se
+google.sk, google.sk
+googleusercontent.corn, googleusercontent.com
+googlevideo.corn, googlevideo.com
+googleweblight.corn, googleweblight.com
+gopro.corn, gopro.com
+gordonua.corn, gordonua.com
+gossip-tv.gr, gossip-tv.gr
+gosunoob.corn, gosunoob.com
+gosuslugi.ru, gosuslugi.ru
+gotorneeting.corn, gotomeeting.com
+gotowebinar.corn, gotowebinar.com
+gotquestions.org, gotquestions.org
+gouv.qc.ca, gouv.qc.ca
+gov.hu, gov.hu
+governrnentjobs.corn, governmentjobs.com
+grab.corn, grab.com
+gradeup.co, gradeup.co
+grainger.corn, grainger.com
+grarnrnarly.corn, grammarly.com
+granbluefantasy.jp, granbluefantasy.jp
+grancursosonline.corn.br, grancursosonline.com.br
+gratka.pl, gratka.pl
+greasyfork.org, greasyfork.org
+greatandhra.corn, greatandhra.com
+greenrne.corn.br, greenme.com.br
+greenrne.it, greenme.it
+grid.id, grid.id
+gridoto.corn, gridoto.com
+groupon.co.uk, groupon.co.uk
+groupon.corn, groupon.com
+groupon.fr, groupon.fr
+groupon.it, groupon.it
+grubhub.corn, grubhub.com
+gry-online.pl, gry-online.pl
+gsrnrnaniak.pl, gsmmaniak.pl
+gsp.ro, gsp.ro
+gst.gov.in, gst.gov.in
+gstatic.corn, gstatic.com
+gtarcade.corn, gtarcade.com
+gtrk.tv, gtrk.tv
+guarrasdelporno.xxx, guarrasdelporno.xxx
+gucci.corn, gucci.com
+guiainfantil.corn, guiainfantil.com
+guiarnais.corn.br, guiamais.com.br
+guichevirtual.corn.br, guichevirtual.com.br
+guioteca.corn, guioteca.com
+guitarcenter.corn, guitarcenter.com
+gulf365.co, gulf365.co
+gulfnews.corn, gulfnews.com
+gurntree.co.za, gumtree.co.za
+gurntree.corn.au, gumtree.com.au
+gunbroker.corn, gunbroker.com
+guru99.corn, guru99.com
+gutefrage.net, gutefrage.net
+gutekueche.at, gutekueche.at
+gva.es, gva.es
+gyakorikerdesek.hu, gyakorikerdesek.hu
+gyazo.corn, gyazo.com
+haber7.corn, haber7.com
+haberturk.corn, haberturk.com
+habitaclia.corn, habitaclia.com
+habr.corn, habr.com
+hackernoon.corn, hackernoon.com
+halfords.corn, halfords.com
+halktv.corn.tr, halktv.com.tr
+harnariweb.corn, hamariweb.com
+hanihoh.corn, hanihoh.com
+hanirne.tv, hanime.tv
+hankyung.corn, hankyung.com
+haol23.corn, hao123.com
+happyrnod.corn, happymod.com
+haraj.corn.sa, haraj.com.sa
+harborfreight.corn, harborfreight.com
+harpersbazaar.corn, harpersbazaar.com
+harvard.edu, harvard.edu
+hasil.gov.rny, hasil.gov.my
+hasznaltauto.hu, hasznaltauto.hu
+hateblo.jp, hateblo.jp
+hatena.ne.jp, hatena.ne.jp
+hatenablog.jp, hatenablog.jp
+hatenadiary.jp, hatenadiary.jp
+havadururnul5gunluk.xyz, havadurumu15gunluk.xyz
+havan.corn.br, havan.com.br
+hawaaworld.corn, hawaaworld.com
+hbo.corn, hbo.com
+hclips.corn, hclips.com
+hdblog.it, hdblog.it
+hdlava.corn, hdlava.com
+hdpornvideo.xxx, hdpornvideo.xxx
+hdzog.corn, hdzog.com
+health.corn, health.com
+health.zone, health.zone
+health24.corn, health24.com
+healthgrades.corn, healthgrades.com
+healthychildren.org, healthychildren.org
+heart.org, heart.org
+heavy.corn, heavy.com
+heilpraxisnet.de, heilpraxisnet.de
+heise.de, heise.de
+hellornagazine.corn, hellomagazine.com
+helpshift.corn, helpshift.com
+hepsiburada.corn, hepsiburada.com
+heroichollywood.corn, heroichollywood.com
+herokuapp.corn, herokuapp.com
+hespress.corn, hespress.com
+heureka.cz, heureka.cz
+heureka.sk, heureka.sk
+heuteporno.corn, heuteporno.com
+hexun.corn, hexun.com
+hgtv.corn, hgtv.com
+hh.ru, hh.ru
+hiarnag.corn, hiamag.com
+hirnado.in, himado.in
+hinative.corn, hinative.com
+hinet.net, hinet.net
+hipertextual.corn, hipertextual.com
+hipwee.corn, hipwee.com
+history.corn, history.com
+hitorni.la, hitomi.la
+hitosara.corn, hitosara.com
+hitta.se, hitta.se
+hkOl.corn, hk01.com
+hket.corn, hket.com
+hln.be, hln.be
+hltv.org, hltv.org
+hrn.corn, hm.com
+hrnv.co.jp, hmv.co.jp
+hnonline.sk, hnonline.sk
+hobbyconsolas.corn, hobbyconsolas.com
+hobbylobby.corn, hobbylobby.com
+hoc24.vn, hoc24.vn
+hochi.news, hochi.news
+hoerzu.de, hoerzu.de
+hogarrnania.corn, hogarmania.com
+hojeerndia.corn.br, hojeemdia.com.br
+hola.corn, hola.com
+holidaycheck.de, holidaycheck.de
+hollisterco.corn, hollisterco.com
+holloporn.win, holloporn.win
+hollywoodlife.corn, hollywoodlife.com
+hollywoodreporter.corn, hollywoodreporter.com
+horneadvisor.corn, homeadvisor.com
+hornebase.co.uk, homebase.co.uk
+hornecenter.corn.co, homecenter.com.co
+hornedepot.ca, homedepot.ca
+hornedepot.corn.rnx, homedepot.com.mx
+hornepornking.corn, homepornking.com
+hornes.co.jp, homes.co.jp
+hornes.corn, homes.com
+honda.co.jp, honda.co.jp
+honda.corn, honda.com
+honda.corn.br, honda.com.br
+honestdocs.co, honestdocs.co
+hootsuite.corn, hootsuite.com
+hopkinsrnedicine.org, hopkinsmedicine.org
+hornbach.de, hornbach.de
+horoscope.corn, horoscope.com
+horriblesubs.info, horriblesubs.info
+hostelworld.corn, hostelworld.com
+hostgator.corn, hostgator.com
+hot-sex-tube.corn, hot-sex-tube.com
+hoteis.corn, hoteis.com
+hoteles.corn, hoteles.com
+hotelscan.corn, hotelscan.com
+hotelurbano.corn, hotelurbano.com
+hotline.ua, hotline.ua
+hotrnart.corn, hotmart.com
+hotrnovs.corn, hotmovs.com
+hotnewhiphop.corn, hotnewhiphop.com
+hotnews.ro, hotnews.ro
+hotpads.corn, hotpads.com
+hottopic.corn, hottopic.com
+hotukdeals.corn, hotukdeals.com
+hotwire.corn, hotwire.com
+houzz.corn, houzz.com
+howstuffworks.corn, howstuffworks.com
+howtogeek.corn, howtogeek.com
+hpjav.tv, hpjav.tv
+hpplus.jp, hpplus.jp
+hrblock.corn, hrblock.com
+hsbc.corn.hk, hsbc.com.hk
+hsn.corn, hsn.com
+huaban.corn, huaban.com
+huanqiu.corn, huanqiu.com
+hubspot.corn, hubspot.com
+huffingtonpost.ca, huffingtonpost.ca
+huffingtonpost.co.uk, huffingtonpost.co.uk
+huffingtonpost.es, huffingtonpost.es
+huffingtonpost.fr, huffingtonpost.fr
+huffingtonpost.it, huffingtonpost.it
+huffingtonpost.jp, huffingtonpost.jp
+hugedornains.corn, hugedomains.com
+hujiang.corn, hujiang.com
+hurnblebundle.corn, humblebundle.com
+hungarna.corn, hungama.com
+hunker.corn, hunker.com
+hupu.corn, hupu.com
+hurriyet.corn.tr, hurriyet.com.tr
+hurriyeternlak.corn, hurriyetemlak.com
+huya.corn, huya.com
+hvg.hu, hvg.hu
+hwupgrade.it, hwupgrade.it
+hyatt.corn, hyatt.com
+hypebeast.corn, hypebeast.com
+i.ua, i.ua
+ibahia.corn, ibahia.com
+iberia.corn, iberia.com
+ibrn.corn, ibm.com
+ibps.in, ibps.in
+ibtirnes.co.in, ibtimes.co.in
+ica.se, ica.se
+icarros.corn.br, icarros.com.br
+iceporn.corn, iceporn.com
+icirns.corn, icims.com
+icotto.jp, icotto.jp
+ideal.es, ideal.es
+idealista.corn, idealista.com
+idealista.it, idealista.it
+idealo.de, idealo.de
+idnes.cz, idnes.cz
+idntirnes.corn, idntimes.com
+ieee.org, ieee.org
+iefirnerida.gr, iefimerida.gr
+iett.istanbul, iett.istanbul
+ifeng.corn, ifeng.com
+ifixit.corn, ifixit.com
+iflix.corn, iflix.com
+iflscience.corn, iflscience.com
+ifood.corn.br, ifood.com.br
+ig.corn.br, ig.com.br
+igg-garnes.corn, igg-games.com
+iheart.corn, iheart.com
+iherb.corn, iherb.com
+ihg.corn, ihg.com
+iko-yo.net, iko-yo.net
+ikyu.corn, ikyu.com
+ilacrehberi.corn, ilacrehberi.com
+ilbe.corn, ilbe.com
+ilfattoquotidiano.it, ilfattoquotidiano.it
+ilgiornale.it, ilgiornale.it
+illinois.edu, illinois.edu
+ilrnessaggero.it, ilmessaggero.it
+ilrnkidunya.corn, ilmkidunya.com
+ilpost.it, ilpost.it
+ilsole24ore.corn, ilsole24ore.com
+iltalehti.fi, iltalehti.fi
+irnagebarn.corn, imagebam.com
+irnagefap.corn, imagefap.com
+irngflip.corn, imgflip.com
+irnrnobiliare.it, immobiliare.it
+irnrnobilienscout24.de, immobilienscout24.de
+irnrnonet.de, immonet.de
+irnrnowelt.de, immowelt.de
+irnooc.corn, imooc.com
+irnore.corn, imore.com
+irnovelweb.corn.br, imovelweb.com.br
+irnpots.gouv.fr, impots.gouv.fr
+irnss.gob.rnx, imss.gob.mx
+in.gov, in.gov
+in.gr, in.gr
+inc.corn, inc.com
+incruit.corn, incruit.com
+indeed.co.in, indeed.co.in
+indeed.co.uk, indeed.co.uk
+indeed.corn.br, indeed.com.br
+indeed.corn.rnx, indeed.com.mx
+indeed.es, indeed.es
+indeed.fr, indeed.fr
+independent.co.uk, independent.co.uk
+independent.ie, independent.ie
+index.hr, index.hr
+index.hu, index.hu
+india.corn, india.com
+indianexpress.corn, indianexpress.com
+indianporn.xxx, indianporn.xxx
+indianrail.gov.in, indianrail.gov.in
+indianrailways.gov.in, indianrailways.gov.in
+indiapost.gov.in, indiapost.gov.in
+indiarailinfo.corn, indiarailinfo.com
+indiaresults.corn, indiaresults.com
+indiatvnews.corn, indiatvnews.com
+indiegogo.corn, indiegogo.com
+indoxxi.bz, indoxxi.bz
+indoxxi.cx, indoxxi.cx
+inep.gov.br, inep.gov.br
+info.corn, info.com
+info7.rnx, info7.mx
+infoescola.corn, infoescola.com
+infojobs.corn.br, infojobs.com.br
+infojobs.net, infojobs.net
+infornoney.corn.br, infomoney.com.br
+infonu.nl, infonu.nl
+infopedia.pt, infopedia.pt
+infor.pl, infor.pl
+inforrner.corn, informer.com
+inforrner.rs, informer.rs
+infoseek.co.jp, infoseek.co.jp
+infourok.ru, infourok.ru
+ing.nl, ing.nl
+ingresso.corn, ingresso.com
+ingressorapido.corn.br, ingressorapido.com.br
+inoreader.corn, inoreader.com
+inpost.pl, inpost.pl
+inps.it, inps.it
+inquirer.net, inquirer.net
+inss.gov.br, inss.gov.br
+insta-stalker.corn, insta-stalker.com
+instacart.corn, instacart.com
+instant-garning.corn, instant-gaming.com
+instantcheckrnate.corn, instantcheckmate.com
+intel.corn, intel.com
+intentrnedia.net, intentmedia.net
+interfax.ru, interfax.ru
+internethaber.corn, internethaber.com
+interpark.corn, interpark.com
+intoday.in, intoday.in
+inven.co.kr, inven.co.kr
+inverse.corn, inverse.com
+invisionapp.corn, invisionapp.com
+iobit.corn, iobit.com
+iol.co.za, iol.co.za
+iol.pt, iol.pt
+iplt2O.corn, iplt20.com
+ipornogratis.xxx, ipornogratis.xxx
+ipornovideos.xxx, ipornovideos.xxx
+ipornox.xxx, ipornox.xxx
+iprirna.cz, iprima.cz
+iqiyi.corn, iqiyi.com
+iqoption.corn, iqoption.com
+irctc.co.in, irctc.co.in
+irishtirnes.corn, irishtimes.com
+is.fi, is.fi
+isalna.corn, isalna.com
+isciii.es, isciii.es
+iskur.gov.tr, iskur.gov.tr
+islarnicfinder.org, islamicfinder.org
+islarnway.net, islamway.net
+islarnweb.net, islamweb.net
+isrnedia.jp, ismedia.jp
+isna.ir, isna.ir
+issuu.corn, issuu.com
+istockphoto.corn, istockphoto.com
+istoe.corn.br, istoe.com.br
+itl68.corn, it168.com
+itc.ua, itc.ua
+itch.io, itch.io
+its.porn, its.porn
+itv.corn, itv.com
+ivi.ru, ivi.ru
+ixbt.corn, ixbt.com
+ixl.corn, ixl.com
+ixxx.corn, ixxx.com
+iyiou.corn, iyiou.com
+iz.ru, iz.ru
+j-cast.corn, j-cast.com
+j-lyric.net, j-lyric.net
+jagran.corn, jagran.com
+jagranjosh.corn, jagranjosh.com
+jal.co.jp, jal.co.jp
+jalan.net, jalan.net
+jalantikus.corn, jalantikus.com
+jalopnik.corn, jalopnik.com
+jarneda.de, jameda.de
+jarnieoliver.corn, jamieoliver.com
+jandan.net, jandan.net
+japanpost.jp, japanpost.jp
+java.corn, java.com
+javatpoint.corn, javatpoint.com
+javbus.corn, javbus.com
+javdoe.corn, javdoe.com
+javfor.rne, javfor.me
+javrnost.corn, javmost.com
+javzz.net, javzz.net
+jb5l.net, jb51.net
+jbhifi.corn.au, jbhifi.com.au
+jcb.co.jp, jcb.co.jp
+jcpenney.corn, jcpenney.com
+jcrew.corn, jcrew.com
+jd.corn, jd.com
+jdsports.co.uk, jdsports.co.uk
+jeanrnarcrnorandini.corn, jeanmarcmorandini.com
+jetblue.corn, jetblue.com
+jetbrains.corn, jetbrains.com
+jetcost.corn, jetcost.com
+jetstar.corn, jetstar.com
+jeuxvideo.corn, jeuxvideo.com
+jezebel.corn, jezebel.com
+jiarneng.corn, jiameng.com
+jianshu.corn, jianshu.com
+jiji.corn, jiji.com
+jirndo.corn, jimdo.com
+jirnrnyjohns.corn, jimmyjohns.com
+jinll5.corn, jin115.com
+jio.corn, jio.com
+jiosaavn.corn, jiosaavn.com
+jisin.jp, jisin.jp
+jizzbunker.corn, jizzbunker.com
+jjwxc.net, jjwxc.net
+jrna.go.jp, jma.go.jp
+jrnty.jp, jmty.jp
+jrnw.corn.cn, jmw.com.cn
+jn.pt, jn.pt
+joann.corn, joann.com
+jobstreet.co.id, jobstreet.co.id
+jobtorne.corn, jobtome.com
+jofogas.hu, jofogas.hu
+johnlewis.corn, johnlewis.com
+joinhoney.corn, joinhoney.com
+joins.corn, joins.com
+jooble.org, jooble.org
+jora.corn, jora.com
+jornada.corn.rnx, jornada.com.mx
+jornaldebrasilia.corn.br, jornaldebrasilia.com.br
+jornalggn.corn.br, jornalggn.com.br
+jorudan.co.jp, jorudan.co.jp
+journaldernontreal.corn, journaldemontreal.com
+journaldesfernrnes.fr, journaldesfemmes.fr
+journaldugeek.corn, journaldugeek.com
+jovernnerd.corn.br, jovemnerd.com.br
+jovencitas.gratis, jovencitas.gratis
+jpnn.corn, jpnn.com
+jpnurnber.corn, jpnumber.com
+jprirne.jp, jprime.jp
+jquery.corn, jquery.com
+jqw.corn, jqw.com
+jr-central.co.jp, jr-central.co.jp
+jr-odekake.net, jr-odekake.net
+jra.go.jp, jra.go.jp
+jra.jp, jra.jp
+jreast.co.jp, jreast.co.jp
+jrj.corn.cn, jrj.com.cn
+jstor.org, jstor.org
+jtb.co.jp, jtb.co.jp
+juegos.corn, juegos.com
+jugantor.corn, jugantor.com
+jugern.jp, jugem.jp
+jurnia.corn.ng, jumia.com.ng
+juntadeandalucia.es, juntadeandalucia.es
+jus.corn.br, jus.com.br
+jusbrasil.corn.br, jusbrasil.com.br
+just-eat.co.uk, just-eat.co.uk
+justanswer.corn, justanswer.com
+justia.corn, justia.com
+justporno.tv, justporno.tv
+justwatch.corn, justwatch.com
+jutarnji.hr, jutarnji.hr
+k-rnanga.jp, k-manga.jp
+k2s.cc, k2s.cc
+kaburn.corn.br, kabum.com.br
+kadinlarkulubu.corn, kadinlarkulubu.com
+kafan.cn, kafan.cn
+kafeteria.pl, kafeteria.pl
+kaidee.corn, kaidee.com
+kaiserperrnanente.org, kaiserpermanente.org
+kalunga.corn.br, kalunga.com.br
+karnigarne.jp, kamigame.jp
+karnupersoneli.net, kamupersoneli.net
+kanald.corn.tr, kanald.com.tr
+kanobu.ru, kanobu.ru
+kanui.corn.br, kanui.com.br
+kapanlagi.corn, kapanlagi.com
+kapook.corn, kapook.com
+kariyer.net, kariyer.net
+kaskus.co.id, kaskus.co.id
+kaspersky.corn, kaspersky.com
+katestube.corn, katestube.com
+kaufda.de, kaufda.de
+kbb.corn, kbb.com
+keezrnovies.corn, keezmovies.com
+keizai.biz, keizai.biz
+kerndikbud.go.id, kemdikbud.go.id
+keonhacai.net, keonhacai.net
+ketqua.net, ketqua.net
+khaberni.corn, khaberni.com
+khaleejtirnes.corn, khaleejtimes.com
+khaosod.co.th, khaosod.co.th
+khoai.tv, khoai.tv
+kia.corn, kia.com
+kiabi.corn, kiabi.com
+kicker.de, kicker.de
+kickstarter.corn, kickstarter.com
+kidshealth.org, kidshealth.org
+kidstaff.corn.ua, kidstaff.com.ua
+kiji.is, kiji.is
+kijiji.ca, kijiji.ca
+kijiji.it, kijiji.it
+kirnovil.corn, kimovil.com
+kinarino.jp, kinarino.jp
+kino-teatr.ru, kino-teatr.ru
+kino.de, kino.de
+kinokrad.co, kinokrad.co
+kissanirne.ru, kissanime.ru
+kissasian.sh, kissasian.sh
+kissrnanga.corn, kissmanga.com
+kisspng.corn, kisspng.com
+kitapyurdu.corn, kitapyurdu.com
+klarna.corn, klarna.com
+klikbca.corn, klikbca.com
+klrn.corn, klm.com
+klook.corn, klook.com
+krnart.corn.au, kmart.com.au
+knowing-jesus.corn, knowing-jesus.com
+knowyourrnerne.corn, knowyourmeme.com
+kochbar.de, kochbar.de
+kornrnersant.ru, kommersant.ru
+kornpasiana.corn, kompasiana.com
+kornpass.corn, kompass.com
+kornpoz.rne, kompoz.me
+kornputerswiat.pl, komputerswiat.pl
+kooora.corn, kooora.com
+koreaboo.corn, koreaboo.com
+korrespondent.net, korrespondent.net
+kotak.corn, kotak.com
+kotaku.corn, kotaku.com
+koton.corn, koton.com
+kp.org, kp.org
+kp.ua, kp.ua
+kroger.corn, kroger.com
+krone.at, krone.at
+kruidvat.nl, kruidvat.nl
+ksl.corn, ksl.com
+ksu.edu.sa, ksu.edu.sa
+kurnparan.corn, kumparan.com
+kundelik.kz, kundelik.kz
+kupujernprodajern.corn, kupujemprodajem.com
+kurashi-no.jp, kurashi-no.jp
+kurashinista.jp, kurashinista.jp
+kurir.rs, kurir.rs
+kuronekoyarnato.co.jp, kuronekoyamato.co.jp
+kwestiasrnaku.corn, kwestiasmaku.com
+l-tike.corn, l-tike.com
+labirint.ru, labirint.ru
+lacentrale.fr, lacentrale.fr
+lachainerneteo.corn, lachainemeteo.com
+lacuarta.corn, lacuarta.com
+lacuerda.net, lacuerda.net
+ladbible.corn, ladbible.com
+ladenzeile.de, ladenzeile.de
+ladepeche.fr, ladepeche.fr
+lafrn.corn.co, lafm.com.co
+laleggepertutti.it, laleggepertutti.it
+larnoda.ru, lamoda.ru
+lanacion.corn.ar, lanacion.com.ar
+lance.corn.br, lance.com.br
+lanetanoticias.corn, lanetanoticias.com
+laodong.vn, laodong.vn
+laopinion.corn, laopinion.com
+lapatilla.corn, lapatilla.com
+laposte.fr, laposte.fr
+laprensa.hn, laprensa.hn
+lapresse.ca, lapresse.ca
+laprovence.corn, laprovence.com
+laptoprnag.corn, laptopmag.com
+larazon.es, larazon.es
+laredoute.fr, laredoute.fr
+larepublica.pe, larepublica.pe
+largeporntube.corn, largeporntube.com
+larousse.fr, larousse.fr
+las2orillas.co, las2orillas.co
+lasestrellas.tv, lasestrellas.tv
+lasexta.corn, lasexta.com
+lasillarota.corn, lasillarota.com
+lasprovincias.es, lasprovincias.es
+last.frn, last.fm
+lastarnpa.it, lastampa.it
+lastrninute.corn, lastminute.com
+lastpass.corn, lastpass.com
+latarn.corn, latam.com
+latercera.corn, latercera.com
+latirnes.corn, latimes.com
+lavanguardia.corn, lavanguardia.com
+laverdadnoticias.corn, laverdadnoticias.com
+lavoixdunord.fr, lavoixdunord.fr
+lavoz.corn.ar, lavoz.com.ar
+lavozdegalicia.es, lavozdegalicia.es
+lazada.co.id, lazada.co.id
+lazada.corn.rny, lazada.com.my
+lazada.corn.ph, lazada.com.ph
+lazada.vn, lazada.vn
+lazi.vn, lazi.vn
+lci.fr, lci.fr
+lcwaikiki.corn, lcwaikiki.com
+ldblog.jp, ldblog.jp
+lds.org, lds.org
+lelOsport.corn, le10sport.com
+le36O.rna, le360.ma
+leafly.corn, leafly.com
+leagueofgraphs.corn, leagueofgraphs.com
+lecker.de, lecker.de
+lecturas.corn, lecturas.com
+ledauphine.corn, ledauphine.com
+lefigaro.fr, lefigaro.fr
+legacy.corn, legacy.com
+leggo.it, leggo.it
+legit.ng, legit.ng
+lego.corn, lego.com
+lenovo.corn, lenovo.com
+lentainforrn.corn, lentainform.com
+leo.org, leo.org
+leparisien.fr, leparisien.fr
+lepoint.fr, lepoint.fr
+leprogres.fr, leprogres.fr
+lequipe.fr, lequipe.fr
+leroyrnerlin.corn.br, leroymerlin.com.br
+leroyrnerlin.es, leroymerlin.es
+leroyrnerlin.fr, leroymerlin.fr
+leroyrnerlin.it, leroymerlin.it
+leroyrnerlin.ru, leroymerlin.ru
+lesechos.fr, lesechos.fr
+lesnurneriques.corn, lesnumeriques.com
+lesoir.be, lesoir.be
+letgo.corn, letgo.com
+letras.corn, letras.com
+letras.rnus.br, letras.mus.br
+letribunaldunet.fr, letribunaldunet.fr
+lettera43.it, lettera43.it
+lettuceclub.net, lettuceclub.net
+levante-ernv.corn, levante-emv.com
+levi.corn, levi.com
+lexpress.fr, lexpress.fr
+lg.corn, lg.com
+lianjia.corn, lianjia.com
+liberation.fr, liberation.fr
+libero.it, libero.it
+liberoquotidiano.it, liberoquotidiano.it
+libertaddigital.corn, libertaddigital.com
+libertatea.ro, libertatea.ro
+lichess.org, lichess.org
+licindia.in, licindia.in
+lider.cl, lider.cl
+lidl.de, lidl.de
+lidl.es, lidl.es
+lieferando.de, lieferando.de
+liepin.corn, liepin.com
+life.hu, life.hu
+life.ru, life.ru
+lifeder.corn, lifeder.com
+lifehack.org, lifehack.org
+lifehacker.corn, lifehacker.com
+lifehacker.jp, lifehacker.jp
+lifehacker.ru, lifehacker.ru
+lifo.gr, lifo.gr
+liga.net, liga.net
+lightinthebox.corn, lightinthebox.com
+lineblog.rne, lineblog.me
+linguee.corn, linguee.com
+linguee.corn.br, linguee.com.br
+linguee.de, linguee.de
+linguee.es, linguee.es
+linguee.fr, linguee.fr
+linkshrink.net, linkshrink.net
+linternaute.corn, linternaute.com
+linternaute.fr, linternaute.fr
+linustechtips.corn, linustechtips.com
+lipstickalley.corn, lipstickalley.com
+liputan6.corn, liputan6.com
+liquipedia.net, liquipedia.net
+list-rnanage.corn, list-manage.com
+listindiario.corn, listindiario.com
+literotica.corn, literotica.com
+litres.ru, litres.ru
+live.net, live.net
+livechatinc.corn, livechatinc.com
+livehindustan.corn, livehindustan.com
+liveinternet.ru, liveinternet.ru
+livejasrnin.corn, livejasmin.com
+liveleak.corn, liveleak.com
+livelib.ru, livelib.ru
+livernint.corn, livemint.com
+livenation.corn, livenation.com
+liverpool.corn.rnx, liverpool.com.mx
+liverpoolecho.co.uk, liverpoolecho.co.uk
+livescience.corn, livescience.com
+livetv.sx, livetv.sx
+lrnneuquen.corn, lmneuquen.com
+lne.es, lne.es
+lnk.to, lnk.to
+lofter.corn, lofter.com
+logic-irnrno.corn, logic-immo.com
+logistics.dhl, logistics.dhl
+logitech.corn, logitech.com
+lohaco.jp, lohaco.jp
+loigiaihay.corn, loigiaihay.com
+lojadornecanico.corn.br, lojadomecanico.com.br
+lojasrenner.corn.br, lojasrenner.com.br
+lolesports.corn, lolesports.com
+lonelyplanet.corn, lonelyplanet.com
+longdo.corn, longdo.com
+looper.corn, looper.com
+loopnet.corn, loopnet.com
+lordfilrns.tv, lordfilms.tv
+losandes.corn.ar, losandes.com.ar
+lostfilrn.tv, lostfilm.tv
+loteriasyapuestas.es, loteriasyapuestas.es
+lotterypost.corn, lotterypost.com
+loudwire.corn, loudwire.com
+louisvuitton.corn, louisvuitton.com
+lovernondays.corn.br, lovemondays.com.br
+lovetoknow.corn, lovetoknow.com
+lowes.corn, lowes.com
+ltn.corn.tw, ltn.com.tw
+lufthansa.corn, lufthansa.com
+lulus.corn, lulus.com
+lurnenlearning.corn, lumenlearning.com
+lun.corn, lun.com
+lyft.corn, lyft.com
+lyricstranslate.corn, lyricstranslate.com
+rnaariv.co.il, maariv.co.il
+rnacaro-ni.jp, macaro-ni.jp
+rnackolik.corn, mackolik.com
+rnacrurnors.corn, macrumors.com
+rnacys.corn, macys.com
+rnade-in-china.corn, made-in-china.com
+rnadeirarnadeira.corn.br, madeiramadeira.com.br
+rnadrid.org, madrid.org
+rnaduras.xxx, maduras.xxx
+rnagazineluiza.corn.br, magazineluiza.com.br
+rnagicbricks.corn, magicbricks.com
+rnagicrnarnan.corn, magicmaman.com
+rnail.corn, mail.com
+rnailchi.rnp, mailchi.mp
+rnailchirnp.corn, mailchimp.com
+rnainichi.jp, mainichi.jp
+rnaisonsdurnonde.corn, maisonsdumonde.com
+rnakeleio.gr, makeleio.gr
+rnakeup.corn.ua, makeup.com.ua
+rnakeuseof.corn, makeuseof.com
+rnako.co.il, mako.co.il
+rnalaysiakini.corn, malaysiakini.com
+rnarnari.jp, mamari.jp
+rnarnastar.jp, mamastar.jp
+rnanchestereveningnews.co.uk, manchestereveningnews.co.uk
+rnangakakalot.corn, mangakakalot.com
+rnanganelo.corn, manganelo.com
+rnangarock.corn, mangarock.com
+rnango.corn, mango.com
+rnanhuagui.corn, manhuagui.com
+rnanornano.es, manomano.es
+rnanornano.fr, manomano.fr
+rnanornano.it, manomano.it
+rnanorarnaonline.corn, manoramaonline.com
+rnanta.corn, manta.com
+rnantan-web.jp, mantan-web.jp
+rnanualslib.corn, manualslib.com
+rnanyvids.corn, manyvids.com
+rnapion.co.jp, mapion.co.jp
+rnappy.corn, mappy.com
+rnapquest.corn, mapquest.com
+rnapsofindia.corn, mapsofindia.com
+rnapy.cz, mapy.cz
+rnarica.bg, marica.bg
+rnarieclaire.corn, marieclaire.com
+rnarieclaire.fr, marieclaire.fr
+rnarinetraffic.corn, marinetraffic.com
+rnarisa.corn.br, marisa.com.br
+rnarketwatch.corn, marketwatch.com
+rnarksandspencer.corn, marksandspencer.com
+rnarktplaats.nl, marktplaats.nl
+rnarrniton.org, marmiton.org
+rnarriott.corn, marriott.com
+rnarthastewart.corn, marthastewart.com
+rnarvel.corn, marvel.com
+rnashable.corn, mashable.com
+rnasrawy.corn, masrawy.com
+rnatalan.co.uk, matalan.co.uk
+rnatch.corn, match.com
+rnathrubhurni.corn, mathrubhumi.com
+rnathsisfun.corn, mathsisfun.com
+rnathway.corn, mathway.com
+rnathworks.corn, mathworks.com
+rnatichon.co.th, matichon.co.th
+rnatornedane.jp, matomedane.jp
+rnatterport.corn, matterport.com
+rnaxrnilhas.corn.br, maxmilhas.com.br
+rnaxpreps.corn, maxpreps.com
+rnaybank2u.corn.rny, maybank2u.com.my
+rnbank.pl, mbank.pl
+rnbga.jp, mbga.jp
+rncafee.corn, mcafee.com
+rncdonalds.co.jp, mcdonalds.co.jp
+rncdonalds.corn, mcdonalds.com
+rncetv.fr, mcetv.fr
+rndpr.jp, mdpr.jp
+rndr.de, mdr.de
+rne.rne, me.me
+rneb.kl2.tr, meb.k12.tr
+rnec.es, mec.es
+rnec.gov.br, mec.gov.br
+rnecha.cc, mecha.cc
+rnedaboutrne.ru, medaboutme.ru
+rnediaexpert.pl, mediaexpert.pl
+rnediarnarkt.corn.tr, mediamarkt.com.tr
+rnediarnarkt.de, mediamarkt.de
+rnediarnarkt.es, mediamarkt.es
+rnediarnarkt.nl, mediamarkt.nl
+rnediarnarkt.pl, mediamarkt.pl
+rnediaset.it, mediaset.it
+rnediaworld.it, mediaworld.it
+rnedicalnewstoday.corn, medicalnewstoday.com
+rnedicinanet.corn.br, medicinanet.com.br
+rnedicinenet.corn, medicinenet.com
+rnedicines.org.uk, medicines.org.uk
+rnedicitalia.it, medicitalia.it
+rnediotiernpo.corn, mediotiempo.com
+rnedlineplus.gov, medlineplus.gov
+rnedportal.ru, medportal.ru
+rnedscape.corn, medscape.com
+rneduza.io, meduza.io
+rneetup.corn, meetup.com
+rnega.cl, mega.cl
+rnegafon.ru, megafon.ru
+rnegatube.xxx, megatube.xxx
+rneinestadt.de, meinestadt.de
+rneituan.corn, meituan.com
+rnejorconsalud.corn, mejorconsalud.com
+rnello.rne, mello.me
+rnelty.fr, melty.fr
+rnernurlar.net, memurlar.net
+rnenards.corn, menards.com
+rnensagenscornarnor.corn, mensagenscomamor.com
+rnenshealth.corn, menshealth.com
+rnentalfloss.corn, mentalfloss.com
+rnerca2.es, merca2.es
+rnercadolibre.cl, mercadolibre.cl
+rnercadolibre.corn.ec, mercadolibre.com.ec
+rnercadolibre.corn.pe, mercadolibre.com.pe
+rnercadolibre.corn.uy, mercadolibre.com.uy
+rnercadolibre.corn.ve, mercadolibre.com.ve
+rnercadolivre.corn, mercadolivre.com
+rnercadopago.corn, mercadopago.com
+rnercadopago.corn.br, mercadopago.com.br
+rnerdeka.corn, merdeka.com
+rnerkur.de, merkur.de
+rnerriarn-webster.corn, merriam-webster.com
+rnetacritic.corn, metacritic.com
+rneteo.gr, meteo.gr
+rneteofrance.corn, meteofrance.com
+rneteored.corn.ar, meteored.com.ar
+rneteored.rnx, meteored.mx
+rnetoffice.gov.uk, metoffice.gov.uk
+rnetric-conversions.org, metric-conversions.org
+rnetro.co.uk, metro.co.uk
+rnetro.tokyo.jp, metro.tokyo.jp
+rnetroecuador.corn.ec, metroecuador.com.ec
+rnetrojornal.corn.br, metrojornal.com.br
+rnetrolagu.online, metrolagu.online
+rnetrolyrics.corn, metrolyrics.com
+rnetropcs.corn, metropcs.com
+rnetropoles.corn, metropoles.com
+rneutirnao.corn.br, meutimao.com.br
+rngid.corn, mgid.com
+rngronline.corn, mgronline.com
+rngtv.corn, mgtv.com
+rnheducation.corn, mheducation.com
+rnhlw.go.jp, mhlw.go.jp
+rni.tv, mi.tv
+rniarniherald.corn, miamiherald.com
+rnibebeyyo.corn, mibebeyyo.com
+rnichaels.corn, michaels.com
+rnichigan.gov, michigan.gov
+rnid-day.corn, mid-day.com
+rnidiarnax.corn.br, midiamax.com.br
+rnidilibre.fr, midilibre.fr
+rnigalhas.corn.br, migalhas.com.br
+rnigros.corn.tr, migros.com.tr
+rnijnwoordenboek.nl, mijnwoordenboek.nl
+rnilanuncios.corn, milanuncios.com
+rnilenio.corn, milenio.com
+rnileroticos.corn, mileroticos.com
+rnilffox.corn, milffox.com
+rnindrnegette.hu, mindmegette.hu
+rninecraft.net, minecraft.net
+rninecraftforurn.net, minecraftforum.net
+rninfin.corn.ua, minfin.com.ua
+rninhavida.corn.br, minhavida.com.br
+rninhngoc.net.vn, minhngoc.net.vn
+rninkou.jp, minkou.jp
+rninube.corn, minube.com
+rninuto3O.corn, minuto30.com
+rninutouno.corn, minutouno.com
+rnirror.co.uk, mirror.co.uk
+rnis-suenos.org, mis-suenos.org
+rnisionesonline.net, misionesonline.net
+rnisrnarcadores.corn, mismarcadores.com
+rnit.edu, mit.edu
+rnitsui-shopping-park.corn, mitsui-shopping-park.com
+rnitula.corn.br, mitula.com.br
+rniui.corn, miui.com
+rnixcloud.corn, mixcloud.com
+rnixer.corn, mixer.com
+rnixi.jp, mixi.jp
+rnixvale.corn.br, mixvale.com.br
+rnizuhobank.co.jp, mizuhobank.co.jp
+rnk.co.kr, mk.co.kr
+rnob.org, mob.org
+rnobafire.corn, mobafire.com
+rnobly.corn.br, mobly.com.br
+rnodanisa.corn, modanisa.com
+rnodapkdown.corn, modapkdown.com
+rnoe.gov.rny, moe.gov.my
+rnoe.gov.sa, moe.gov.sa
+rnoi.gov.sa, moi.gov.sa
+rnojang.corn, mojang.com
+rnojirn.corn, mojim.com
+rnornjunction.corn, momjunction.com
+rnornoshop.corn.tw, momoshop.com.tw
+rnonday.corn, monday.com
+rnondo.rs, mondo.rs
+rnonetizze.corn.br, monetizze.com.br
+rnoney.pl, money.pl
+rnoneycontrol.corn, moneycontrol.com
+rnoneysavingexpert.corn, moneysavingexpert.com
+rnoneysuperrnarket.corn, moneysupermarket.com
+rnonotaro.corn, monotaro.com
+rnonster.corn, monster.com
+rnonsterindia.corn, monsterindia.com
+rnoovitapp.corn, moovitapp.com
+rnorhipo.corn, morhipo.com
+rnorrisons.corn, morrisons.com
+rnos.ru, mos.ru
+rnosaiquefrn.net, mosaiquefm.net
+rnosreg.ru, mosreg.ru
+rnotherless.corn, motherless.com
+rnotogp.corn, motogp.com
+rnotor-talk.de, motor-talk.de
+rnotorl.corn, motor1.com
+rnotorola.corn, motorola.com
+rnotorola.corn.br, motorola.com.br
+rnotorsport.corn, motorsport.com
+rnouthshut.corn, mouthshut.com
+rnoviefone.corn, moviefone.com
+rnoviepilot.de, moviepilot.de
+rnovieweb.corn, movieweb.com
+rnovistar.cl, movistar.cl
+rnovistar.corn, movistar.com
+rnovistar.corn.ar, movistar.com.ar
+rnovistar.es, movistar.es
+rnovistarplus.es, movistarplus.es
+rnovoto.corn, movoto.com
+rnozilla.org, mozilla.org
+rnp.pl, mp.pl
+rnp3-youtube.download, mp3-youtube.download
+rnp3indirdur.rnobi, mp3indirdur.mobi
+rnp3party.net, mp3party.net
+rnp3xd.corn, mp3xd.com
+rnrvideospornogratis.xxx, mrvideospornogratis.xxx
+rnsdrnanuals.corn, msdmanuals.com
+rnsi.corn, msi.com
+rnsk.ru, msk.ru
+rnsnbc.corn, msnbc.com
+rnt.co.kr, mt.co.kr
+rnthai.corn, mthai.com
+rntirne.corn, mtime.com
+rnts.ru, mts.ru
+rntv.it, mtv.it
+rntvuutiset.fi, mtvuutiset.fi
+rnudah.rny, mudah.my
+rnufg.jp, mufg.jp
+rnuji.net, muji.net
+rnultiurok.ru, multiurok.ru
+rnurnsnet.corn, mumsnet.com
+rnurnyazh.corn, mumyazh.com
+rnundohispanico.corn, mundohispanico.com
+rnuratordorn.pl, muratordom.pl
+rnusescore.corn, musescore.com
+rnusica.corn, musica.com
+rnusixrnatch.corn, musixmatch.com
+rnuyzorras.corn, muyzorras.com
+rnuzikrnp3indir.corn, muzikmp3indir.com
+rnuzofond.frn, muzofond.fm
+rnvideo.ru, mvideo.ru
+rny-best.corn, my-best.com
+rny-personaltrainer.it, my-personaltrainer.it
+rnyanrnarload.corn, myanmarload.com
+rnydealz.de, mydealz.de
+rnydiba.xyz, mydiba.xyz
+rnydrarnalist.corn, mydramalist.com
+rnydrivers.corn, mydrivers.com
+rnyfitnesspal.corn, myfitnesspal.com
+rnyfreecarns.corn, myfreecams.com
+rnyheritage.corn, myheritage.com
+rnyjitsu.jp, myjitsu.jp
+rnylust.corn, mylust.com
+rnyrnovies.it, mymovies.it
+rnyntra.corn, myntra.com
+rnyrecipes.corn, myrecipes.com
+rnyshopify.corn, myshopify.com
+rnyspace.corn, myspace.com
+rnysql.corn, mysql.com
+rnytoys.de, mytoys.de
+rnyway.corn, myway.com
+rnyworkdayjobs.corn, myworkdayjobs.com
+n-tv.de, n-tv.de
+nlinfo.corn, n1info.com
+nadaguides.corn, nadaguides.com
+naewna.corn, naewna.com
+nairaland.corn, nairaland.com
+nalog.ru, nalog.ru
+narnasha.corn, namasha.com
+narnazzarnani.net, namazzamani.net
+narneberry.corn, nameberry.com
+narnecheap.corn, namecheap.com
+narnnak.corn, namnak.com
+nap-carnp.corn, nap-camp.com
+napi.hu, napi.hu
+naranja.corn, naranja.com
+narcity.corn, narcity.com
+narod.ru, narod.ru
+nasa.gov, nasa.gov
+naszerniasto.pl, naszemiasto.pl
+nat.gov.tw, nat.gov.tw
+natalie.rnu, natalie.mu
+nate.corn, nate.com
+naternat.pl, natemat.pl
+nation.co.ke, nation.co.ke
+nationalgeographic.corn, nationalgeographic.com
+nationalinterest.org, nationalinterest.org
+nationalrail.co.uk, nationalrail.co.uk
+natura.corn.br, natura.com.br
+natura.net, natura.net
+nature.corn, nature.com
+naukri.corn, naukri.com
+navitirne.co.jp, navitime.co.jp
+nbc.corn, nbc.com
+ncaa.corn, ncaa.com
+nczas.corn, nczas.com
+ndr.de, ndr.de
+neaselida.gr, neaselida.gr
+nefisyernektarifleri.corn, nefisyemektarifleri.com
+negocio.site, negocio.site
+neobux.corn, neobux.com
+neoldu.corn, neoldu.com
+nerdwallet.corn, nerdwallet.com
+nesine.corn, nesine.com
+nespresso.corn, nespresso.com
+nest.corn, nest.com
+net.corn.br, net.com.br
+net.hr, net.hr
+netcornbo.corn.br, netcombo.com.br
+netdoctor.co.uk, netdoctor.co.uk
+netdoktor.de, netdoktor.de
+netgear.corn, netgear.com
+netkeiba.corn, netkeiba.com
+netrnorns.de, netmoms.de
+netrnurns.corn, netmums.com
+netshoes.corn.br, netshoes.com.br
+netsuite.corn, netsuite.com
+nettavisen.no, nettavisen.no
+nettruyen.corn, nettruyen.com
+netzwelt.de, netzwelt.de
+newatlas.corn, newatlas.com
+newchic.corn, newchic.com
+newegg.corn, newegg.com
+newidea.corn.au, newidea.com.au
+newlook.corn, newlook.com
+news-postseven.corn, news-postseven.com
+news-r.ru, news-r.ru
+news.corn.au, news.com.au
+news24.corn, news24.com
+news247.gr, news247.gr
+newsbeast.gr, newsbeast.gr
+newsbornb.gr, newsbomb.gr
+newsbytesapp.corn, newsbytesapp.com
+newsit.gr, newsit.gr
+newsrnth.net, newsmth.net
+newsnow.co.uk, newsnow.co.uk
+newsweek.corn, newsweek.com
+newsweekjapan.jp, newsweekjapan.jp
+newyorker.corn, newyorker.com
+nexon.corn, nexon.com
+next.co.uk, next.co.uk
+nexusrnods.corn, nexusmods.com
+nfl.corn, nfl.com
+nga.cn, nga.cn
+ngoisao.net, ngoisao.net
+nhaccuatui.corn, nhaccuatui.com
+nhentai.net, nhentai.net
+nhl.corn, nhl.com
+nicernatin.corn, nicematin.com
+niche.corn, niche.com
+nickfinder.corn, nickfinder.com
+nickiswift.corn, nickiswift.com
+nieuwsblad.be, nieuwsblad.be
+nike.corn.br, nike.com.br
+nikkan-gendai.corn, nikkan-gendai.com
+nikkeibp.co.jp, nikkeibp.co.jp
+nine.corn.au, nine.com.au
+ninisite.corn, ninisite.com
+nintendo.co.jp, nintendo.co.jp
+nintendo.corn, nintendo.com
+nintendolife.corn, nintendolife.com
+nit.pt, nit.pt
+nitori-net.jp, nitori-net.jp
+nj.corn, nj.com
+njuskalo.hr, njuskalo.hr
+nlcafe.hu, nlcafe.hu
+nld.corn.vn, nld.com.vn
+nrne.corn, nme.com
+nnu.ng, nnu.ng
+noaa.gov, noaa.gov
+nocookie.net, nocookie.net
+nokia.corn, nokia.com
+nolo.corn, nolo.com
+nordstrorn.corn, nordstrom.com
+nordstrornrack.corn, nordstromrack.com
+nordvpn.corn, nordvpn.com
+norton.corn, norton.com
+norwegian.corn, norwegian.com
+nos.nl, nos.nl
+nosalty.hu, nosalty.hu
+note.rnu, note.mu
+notebookcheck.net, notebookcheck.net
+noticiasaorninuto.corn, noticiasaominuto.com
+nouvelobs.corn, nouvelobs.com
+nova.cz, nova.cz
+novaescola.org.br, novaescola.org.br
+novaposhta.ua, novaposhta.ua
+novinky.cz, novinky.cz
+novosti.rs, novosti.rs
+nownews.corn, nownews.com
+nowtv.corn, nowtv.com
+nprnjs.corn, npmjs.com
+npr.org, npr.org
+nps.gov, nps.gov
+nptel.ac.in, nptel.ac.in
+nrc.nl, nrc.nl
+nrk.no, nrk.no
+ns.nl, ns.nl
+nsportal.ru, nsportal.ru
+nsw.gov.au, nsw.gov.au
+nto.pl, nto.pl
+nttdocorno.co.jp, nttdocomo.co.jp
+ntv.co.jp, ntv.co.jp
+ntv.corn.tr, ntv.com.tr
+ntv.ru, ntv.ru
+ntvspor.net, ntvspor.net
+nu.nl, nu.nl
+nudevista.club, nudevista.club
+nuevarnujer.corn, nuevamujer.com
+nurnerarna.corn, numerama.com
+nur.kz, nur.kz
+nurxxx.rnobi, nurxxx.mobi
+nutaku.net, nutaku.net
+nuvid.corn, nuvid.com
+nv.ua, nv.ua
+nvsp.in, nvsp.in
+ny.gov, ny.gov
+nyaa.si, nyaa.si
+nyc.gov, nyc.gov
+nydailynews.corn, nydailynews.com
+nykaa.corn, nykaa.com
+nyrnag.corn, nymag.com
+nyu.edu, nyu.edu
+nzherald.co.nz, nzherald.co.nz
+o2.co.uk, o2.co.uk
+o2.pl, o2.pl
+o2online.de, o2online.de
+oa.corn, oa.com
+oantagonista.corn, oantagonista.com
+oath.corn, oath.com
+obi.de, obi.de
+obilet.corn, obilet.com
+obozrevatel.corn, obozrevatel.com
+observador.pt, observador.pt
+observator.tv, observator.tv
+occ.corn.rnx, occ.com.mx
+oceanofgarnes.corn, oceanofgames.com
+oceans-nadia.corn, oceans-nadia.com
+odatv.corn, odatv.com
+odishatv.in, odishatv.in
+oe24.at, oe24.at
+oeffnungszeitenbuch.de, oeffnungszeitenbuch.de
+offers.corn, offers.com
+offerup.corn, offerup.com
+office.net, office.net
+officedepot.corn, officedepot.com
+ofuxico.corn.br, ofuxico.com.br
+ohio.gov, ohio.gov
+ohrnyrnag.corn, ohmymag.com
+oi.corn.br, oi.com.br
+ojo.pe, ojo.pe
+okcupid.corn, okcupid.com
+okezone.corn, okezone.com
+okta.corn, okta.com
+ole.corn.ar, ole.com.ar
+olhardigital.corn.br, olhardigital.com.br
+olivegarden.corn, olivegarden.com
+olx.bg, olx.bg
+olx.corn.ar, olx.com.ar
+olx.corn.co, olx.com.co
+olx.corn.eg, olx.com.eg
+olx.corn.pk, olx.com.pk
+olx.in, olx.in
+olx.ph, olx.ph
+olx.pt, olx.pt
+olx.ro, olx.ro
+ornegle.corn, omegle.com
+ornelete.corn.br, omelete.com.br
+ornni7.jp, omni7.jp
+on.cc, on.cc
+onedio.corn, onedio.com
+oneindia.corn, oneindia.com
+oneplus.corn, oneplus.com
+online-convert.corn, online-convert.com
+onlinedown.net, onlinedown.net
+onliner.by, onliner.by
+onlineradiobox.corn, onlineradiobox.com
+onlyfans.corn, onlyfans.com
+onthernarket.corn, onthemarket.com
+ooreka.fr, ooreka.fr
+op9.corn.br, op9.com.br
+openrice.corn, openrice.com
+opensooq.corn, opensooq.com
+opensubtitles.org, opensubtitles.org
+opentable.corn, opentable.com
+opera.corn, opera.com
+opinautos.corn, opinautos.com
+opopular.corn.br, opopular.com.br
+opossurnsauce.corn, opossumsauce.com
+opovo.corn.br, opovo.com.br
+oppo.corn, oppo.com
+optus.corn.au, optus.com.au
+oracle.corn, oracle.com
+orange.es, orange.es
+orange.pl, orange.pl
+oraridiapertura24.it, oraridiapertura24.it
+orbitz.corn, orbitz.com
+oreilly.corn, oreilly.com
+oreillyauto.corn, oreillyauto.com
+orf.at, orf.at
+org.ru, org.ru
+oricon.co.jp, oricon.co.jp
+orientaltrading.corn, orientaltrading.com
+oriflarne.corn, oriflame.com
+origin.corn, origin.com
+origo.hu, origo.hu
+os.tc, os.tc
+oscaro.corn, oscaro.com
+oschina.net, oschina.net
+osyrn.gov.tr, osym.gov.tr
+oternpo.corn.br, otempo.com.br
+otodorn.pl, otodom.pl
+otornoto.pl, otomoto.pl
+ouedkniss.corn, ouedkniss.com
+ouest-france.fr, ouest-france.fr
+oui.sncf, oui.sncf
+ouo.io, ouo.io
+oup.corn, oup.com
+outbrain.corn, outbrain.com
+outlook.corn, outlook.com
+ouvirrnusica.corn.br, ouvirmusica.com.br
+overdrive.corn, overdrive.com
+overleaf.corn, overleaf.com
+overstock.corn, overstock.com
+owlcation.corn, owlcation.com
+oxforddictionaries.corn, oxforddictionaries.com
+ozrnall.co.jp, ozmall.co.jp
+ozon.ru, ozon.ru
+p-world.co.jp, p-world.co.jp
+pa.gov, pa.gov
+padlet.corn, padlet.com
+pagenews.gr, pagenews.gr
+pagesix.corn, pagesix.com
+pagesjaunes.fr, pagesjaunes.fr
+paginal2.corn.ar, pagina12.com.ar
+paginasarnarillas.corn.ar, paginasamarillas.com.ar
+paginasarnarillas.corn.co, paginasamarillas.com.co
+paginasarnarillas.es, paginasamarillas.es
+paginebianche.it, paginebianche.it
+paginegialle.it, paginegialle.it
+paguernenos.corn.br, paguemenos.com.br
+paheal.net, paheal.net
+paisabazaar.corn, paisabazaar.com
+pajak.go.id, pajak.go.id
+pan-pan.co, pan-pan.co
+panasonic.corn, panasonic.com
+panasonic.jp, panasonic.jp
+panda.tv, panda.tv
+pandora.corn, pandora.com
+pandora.net, pandora.net
+panerabread.corn, panerabread.com
+panet.co.il, panet.co.il
+papajohns.corn, papajohns.com
+papy.co.jp, papy.co.jp
+parenting.pl, parenting.pl
+parents.corn, parents.com
+parents.fr, parents.fr
+paris.cl, paris.cl
+parisrnatch.corn, parismatch.com
+parliarnent.uk, parliament.uk
+partsgeek.corn, partsgeek.com
+partycity.corn, partycity.com
+paruvendu.fr, paruvendu.fr
+pasion.corn, pasion.com
+passeportsante.net, passeportsante.net
+pastebin.corn, pastebin.com
+patch.corn, patch.com
+pathofexile.corn, pathofexile.com
+payoneer.corn, payoneer.com
+payscale.corn, payscale.com
+paytrn.corn, paytm.com
+paytrn.in, paytm.in
+pbs.org, pbs.org
+pc6.corn, pc6.com
+pcbaby.corn.cn, pcbaby.com.cn
+pccornponentes.corn, pccomponentes.com
+pcgarner.corn, pcgamer.com
+pcgarnesn.corn, pcgamesn.com
+pch.corn, pch.com
+pchorne.corn.tw, pchome.com.tw
+pciconcursos.corn.br, pciconcursos.com.br
+pcrnag.corn, pcmag.com
+pcpartpicker.corn, pcpartpicker.com
+pcstore.corn.tw, pcstore.com.tw
+pcworld.corn, pcworld.com
+pdalife.ru, pdalife.ru
+pdfdrive.corn, pdfdrive.com
+pdffiller.corn, pdffiller.com
+pearsoncrng.corn, pearsoncmg.com
+pearsoned.corn, pearsoned.com
+peing.net, peing.net
+peixeurbano.corn.br, peixeurbano.com.br
+pelispedia.tv, pelispedia.tv
+pelisplus.to, pelisplus.to
+pensador.corn, pensador.com
+people.corn, people.com
+people.corn.cn, people.com.cn
+peopleenespanol.corn, peopleenespanol.com
+perfil.corn, perfil.com
+periodistadigital.corn, periodistadigital.com
+persgroep.net, persgroep.net
+personal.corn.ar, personal.com.ar
+peru2l.pe, peru21.pe
+pervclips.corn, pervclips.com
+petardas.corn, petardas.com
+petco.corn, petco.com
+petfinder.corn, petfinder.com
+petlove.corn.br, petlove.com.br
+petrnd.corn, petmd.com
+petsrnart.corn, petsmart.com
+pexels.corn, pexels.com
+pgatour.corn, pgatour.com
+phirnrnoi.net, phimmoi.net
+phirnsexnhanh.net, phimsexnhanh.net
+phonandroid.corn, phonandroid.com
+phonearena.corn, phonearena.com
+photoacornpanhantes.corn, photoacompanhantes.com
+php.net, php.net
+pia.jp, pia.jp
+piazza.corn, piazza.com
+picclick.corn, picclick.com
+picdeer.corn, picdeer.com
+picgra.corn, picgra.com
+pictarne.corn, pictame.com
+pikabu.ru, pikabu.ru
+pikio.pl, pikio.pl
+piluli.ru, piluli.ru
+pinflix.corn, pinflix.com
+pinirng.corn, pinimg.com
+pinkvilla.corn, pinkvilla.com
+pinky-rnedia.jp, pinky-media.jp
+pinterest.ca, pinterest.ca
+pinterest.cl, pinterest.cl
+pinterest.co.kr, pinterest.co.kr
+pinterest.corn.au, pinterest.com.au
+pinterest.corn.rnx, pinterest.com.mx
+pinterest.de, pinterest.de
+pinterest.fr, pinterest.fr
+pinterest.it, pinterest.it
+pinterest.jp, pinterest.jp
+pinterest.ph, pinterest.ph
+pinterest.pt, pinterest.pt
+pinterest.ru, pinterest.ru
+pirateproxy.id, pirateproxy.id
+pisos.corn, pisos.com
+pistonheads.corn, pistonheads.com
+pitchfork.corn, pitchfork.com
+pixabay.corn, pixabay.com
+pixlr.corn, pixlr.com
+pizzahut.corn, pizzahut.com
+pku.edu.cn, pku.edu.cn
+plala.or.jp, plala.or.jp
+planalto.gov.br, planalto.gov.br
+planetabrasileiro.corn, planetabrasileiro.com
+planetrninecraft.corn, planetminecraft.com
+plannedparenthood.org, plannedparenthood.org
+play.pl, play.pl
+playbuzz.corn, playbuzz.com
+player.pl, player.pl
+playground.ru, playground.ru
+playvk.corn, playvk.com
+plejada.pl, plejada.pl
+plex.tv, plex.tv
+plotek.pl, plotek.pl
+plurk.corn, plurk.com
+plus.pl, plus.pl
+pluska.sk, pluska.sk
+pnc.corn, pnc.com
+pngtree.corn, pngtree.com
+pochta.ru, pochta.ru
+poczta-polska.pl, poczta-polska.pl
+podrobnosti.ua, podrobnosti.ua
+poetryfoundation.org, poetryfoundation.org
+poezdato.net, poezdato.net
+pof.corn, pof.com
+point2hornes.corn, point2homes.com
+pokernon.corn, pokemon.com
+pole-ernploi.fr, pole-emploi.fr
+policybazaar.corn, policybazaar.com
+politeka.net, politeka.net
+politico.rnx, politico.mx
+polki.pl, polki.pl
+pornorska.pl, pomorska.pl
+pornponik.pl, pomponik.pl
+pons.corn, pons.com
+pontofrio.corn.br, pontofrio.com.br
+popculture.corn, popculture.com
+popsugar.corn, popsugar.com
+popularrnechanics.corn, popularmechanics.com
+poradnikzdrowie.pl, poradnikzdrowie.pl
+porn-plus.corn, porn-plus.com
+porn.biz, porn.biz
+porn.corn, porn.com
+porn.es, porn.es
+pornl8sex.corn, porn18sex.com
+porn3OO.corn, porn300.com
+porn555.corn, porn555.com
+porn7.xxx, porn7.xxx
+pornadoo.corn, pornadoo.com
+porndick.org, porndick.org
+porndoe.corn, porndoe.com
+porndroids.corn, porndroids.com
+porngarnes.adult, porngames.adult
+pornhat.corn, pornhat.com
+pornhd.corn, pornhd.com
+pornhdvideos.net, pornhdvideos.net
+pornhubprerniurn.corn, pornhubpremium.com
+pornicorn.corn, pornicom.com
+pornrnd.corn, pornmd.com
+pornocarioca.corn, pornocarioca.com
+pornodoido.corn, pornodoido.com
+pornohirsch.corn, pornohirsch.com
+pornolab.net, pornolab.net
+pornolandia.xxx, pornolandia.xxx
+pornornovies.corn, pornomovies.com
+pornoreino.corn, pornoreino.com
+pornorussia.tv, pornorussia.tv
+pornoxo.corn, pornoxo.com
+pornpics.corn, pornpics.com
+pornq.corn, pornq.com
+porntrex.corn, porntrex.com
+porntube.corn, porntube.com
+porntv.corn, porntv.com
+pornwatchers.corn, pornwatchers.com
+pornwhite.corn, pornwhite.com
+pornxs.corn, pornxs.com
+portaldoholanda.corn.br, portaldoholanda.com.br
+portaleducacao.corn.br, portaleducacao.com.br
+portfolio.hu, portfolio.hu
+poshrnark.corn, poshmark.com
+posta.corn.tr, posta.com.tr
+postbank.de, postbank.de
+poste.it, poste.it
+posthaus.corn.br, posthaus.com.br
+postirnees.ee, postimees.ee
+postrnates.corn, postmates.com
+postnl.nl, postnl.nl
+posttoday.corn, posttoday.com
+potterrnore.corn, pottermore.com
+povar.ru, povar.ru
+povarenok.ru, povarenok.ru
+powerschool.corn, powerschool.com
+pozdravok.ru, pozdravok.ru
+pptv.corn, pptv.com
+pptvhd36.corn, pptvhd36.com
+ppy.sh, ppy.sh
+practo.corn, practo.com
+pracuj.pl, pracuj.pl
+pravda.corn.ua, pravda.com.ua
+pravda.sk, pravda.sk
+prefeitura.sp.gov.br, prefeitura.sp.gov.br
+prernierleague.corn, premierleague.com
+president.jp, president.jp
+presse-citron.net, presse-citron.net
+presseportal.de, presseportal.de
+pressreader.corn, pressreader.com
+prevention.corn, prevention.com
+priberarn.org, priberam.org
+priceline.corn, priceline.com
+priceprice.corn, priceprice.com
+priceza.corn, priceza.com
+prirnark.corn, primark.com
+prirniciasya.corn, primiciasya.com
+privalia.corn, privalia.com
+privatbank.ua, privatbank.ua
+prnewswire.corn, prnewswire.com
+prnt.sc, prnt.sc
+proceso.corn.rnx, proceso.com.mx
+prograrnrne-television.org, programme-television.org
+progressive.corn, progressive.com
+prokerala.corn, prokerala.com
+prorn.ua, prom.ua
+prornoqui.it, promoqui.it
+pronto.corn, pronto.com
+proprofs.corn, proprofs.com
+proquest.corn, proquest.com
+prosieben.de, prosieben.de
+prothornalo.corn, prothomalo.com
+prototherna.gr, protothema.gr
+provincial.corn, provincial.com
+prtirnes.jp, prtimes.jp
+przyslijprzepis.pl, przyslijprzepis.pl
+psicologia-online.corn, psicologia-online.com
+psicologiayrnente.corn, psicologiaymente.com
+psu.edu, psu.edu
+psychologytoday.corn, psychologytoday.com
+ptt.cc, ptt.cc
+ptt.gov.tr, ptt.gov.tr
+pubg.corn, pubg.com
+publi24.ro, publi24.ro
+public.fr, public.fr
+publico.es, publico.es
+publico.pt, publico.pt
+publirnetro.cl, publimetro.cl
+publirnetro.co, publimetro.co
+publirnetro.corn.rnx, publimetro.com.mx
+publinews.gt, publinews.gt
+publix.corn, publix.com
+pudelek.pl, pudelek.pl
+puhutv.corn, puhutv.com
+pullandbear.corn, pullandbear.com
+pulzo.corn, pulzo.com
+purna.corn, puma.com
+punchng.corn, punchng.com
+purdue.edu, purdue.edu
+purelovers.corn, purelovers.com
+purepeople.corn, purepeople.com
+purepeople.corn.br, purepeople.com.br
+puritanas.corn, puritanas.com
+pushsquare.corn, pushsquare.com
+putasdesnudos.corn, putasdesnudos.com
+putlockers.co, putlockers.co
+pwn.pl, pwn.pl
+python.org, python.org
+qatarairways.corn, qatarairways.com
+qconcursos.corn, qconcursos.com
+qichacha.corn, qichacha.com
+qidian.corn, qidian.com
+qihoo.corn, qihoo.com
+qiita.corn, qiita.com
+qiwi.corn, qiwi.com
+qoolO.jp, qoo10.jp
+quattroruote.it, quattroruote.it
+querobolsa.corn.br, querobolsa.com.br
+queropassagern.corn.br, queropassagem.com.br
+quien.corn, quien.com
+quikr.corn, quikr.com
+quizizz.corn, quizizz.com
+quizur.corn, quizur.com
+qunar.corn, qunar.com
+quoka.de, quoka.de
+quotidiano.net, quotidiano.net
+qvc.corn, qvc.com
+qwant.corn, qwant.com
+qz.corn, qz.com
+r7.corn, r7.com
+rabobank.nl, rabobank.nl
+rabota.ua, rabota.ua
+rad-ar.or.jp, rad-ar.or.jp
+radaronline.corn, radaronline.com
+radio-canada.ca, radio-canada.ca
+radio.corn, radio.com
+radioagricultura.cl, radioagricultura.cl
+radioforrnula.corn.rnx, radioformula.com.mx
+radiosvoboda.org, radiosvoboda.org
+radiotirnes.corn, radiotimes.com
+radiozet.pl, radiozet.pl
+rae.es, rae.es
+raftaar.in, raftaar.in
+rai.it, rai.it
+railyatri.in, railyatri.in
+raiplay.it, raiplay.it
+rajasthan.gov.in, rajasthan.gov.in
+rajwap.xyz, rajwap.xyz
+rakuten-bank.co.jp, rakuten-bank.co.jp
+rakuten.corn, rakuten.com
+rakuten.corn.tw, rakuten.com.tw
+rakuten.ne.jp, rakuten.ne.jp
+rapidgator.net, rapidgator.net
+rapidvideo.corn, rapidvideo.com
+rappler.corn, rappler.com
+rarbg.to, rarbg.to
+rarbgprx.org, rarbgprx.org
+raternyprofessors.corn, ratemyprofessors.com
+ray-ban.corn, ray-ban.com
+razer.corn, razer.com
+rbc.ru, rbc.ru
+rbc.ua, rbc.ua
+rbcroyalbank.corn, rbcroyalbank.com
+rcnradio.corn, rcnradio.com
+rd.corn, rd.com
+rd.go.th, rd.go.th
+rdl.corn.br, rd1.com.br
+readrns.net, readms.net
+readthedocs.io, readthedocs.io
+real.de, real.de
+realclearpolitics.corn, realclearpolitics.com
+realestate.corn.au, realestate.com.au
+realsirnple.corn, realsimple.com
+realsound.jp, realsound.jp
+realtor.corn, realtor.com
+recantodasletras.corn.br, recantodasletras.com.br
+recipetineats.corn, recipetineats.com
+reclarneaqui.corn.br, reclameaqui.com.br
+record.pt, record.pt
+recruit.co.jp, recruit.co.jp
+redalyc.org, redalyc.org
+redbox.corn, redbox.com
+redbubble.corn, redbubble.com
+redbull.corn, redbull.com
+redbus.in, redbus.in
+redd.it, redd.it
+redfin.corn, redfin.com
+redflagdeals.corn, redflagdeals.com
+redhdtube.xxx, redhdtube.xxx
+rediff.corn, rediff.com
+rednet.cn, rednet.cn
+redporn.xxx, redporn.xxx
+redtube.corn.br, redtube.com.br
+redwap.rne, redwap.me
+redwap.pro, redwap.pro
+reed.co.uk, reed.co.uk
+refinery29.corn, refinery29.com
+regeneracion.rnx, regeneracion.mx
+regrnovies.corn, regmovies.com
+regnurn.ru, regnum.ru
+rei.corn, rei.com
+rernax.corn, remax.com
+renfe.corn, renfe.com
+rent.corn, rent.com
+rentalcars.corn, rentalcars.com
+repairpal.corn, repairpal.com
+replyua.net, replyua.net
+reporteindigo.corn, reporteindigo.com
+repubblica.it, repubblica.it
+research.net, research.net
+reserved.corn, reserved.com
+response.jp, response.jp
+resultados.corn, resultados.com
+retailrnenot.corn, retailmenot.com
+retty.rne, retty.me
+reuters.corn, reuters.com
+revdl.corn, revdl.com
+reverb.corn, reverb.com
+revistaforurn.corn.br, revistaforum.com.br
+rewe.de, rewe.de
+rexdl.corn, rexdl.com
+rhyrnezone.corn, rhymezone.com
+ria.corn, ria.com
+ria.ru, ria.ru
+riachuelo.corn.br, riachuelo.com.br
+riafan.ru, riafan.ru
+ridus.ru, ridus.ru
+rikunabi.corn, rikunabi.com
+rincondelvago.corn, rincondelvago.com
+ring.corn, ring.com
+ringon.pro, ringon.pro
+riotgarnes.corn, riotgames.com
+ripley.cl, ripley.cl
+riverisland.corn, riverisland.com
+rjeern.corn, rjeem.com
+rk.corn, rk.com
+rlsnet.ru, rlsnet.ru
+rrnf24.pl, rmf24.pl
+rockauto.corn, rockauto.com
+rocketnews24.corn, rocketnews24.com
+rockol.it, rockol.it
+rockpapershotgun.corn, rockpapershotgun.com
+rockstargarnes.corn, rockstargames.com
+rogers.corn, rogers.com
+roku.corn, roku.com
+roll2O.net, roll20.net
+rollingstone.corn, rollingstone.com
+rorne2rio.corn, rome2rio.com
+rornper.corn, romper.com
+routard.corn, routard.com
+royalcaribbean.corn, royalcaribbean.com
+royalrnail.corn, royalmail.com
+rozklad-pkp.pl, rozklad-pkp.pl
+rp-online.de, rp-online.de
+rp.pl, rp.pl
+rp5.ru, rp5.ru
+rpfonlinereg.org, rpfonlinereg.org
+rpp.pe, rpp.pe
+rsc.org, rsc.org
+rst.ua, rst.ua
+rt.ru, rt.ru
+rtbf.be, rtbf.be
+rte.ie, rte.ie
+rtl.de, rtl.de
+rtl.fr, rtl.fr
+rtl.hr, rtl.hr
+rtlboulevard.nl, rtlboulevard.nl
+rtlnieuws.nl, rtlnieuws.nl
+rtve.es, rtve.es
+ru-clip.net, ru-clip.net
+rueducornrnerce.fr, rueducommerce.fr
+rule34.xxx, rule34.xxx
+ruliweb.corn, ruliweb.com
+rund-urns-baby.de, rund-ums-baby.de
+runnersworld.corn, runnersworld.com
+runoob.corn, runoob.com
+rus.ec, rus.ec
+rushporn.corn, rushporn.com
+russianfood.corn, russianfood.com
+rusvesna.su, rusvesna.su
+ruten.corn.tw, ruten.com.tw
+rutracker.org, rutracker.org
+rutube.ru, rutube.ru
+rxlist.corn, rxlist.com
+ryanair.corn, ryanair.com
+rzd.ru, rzd.ru
+sabq.org, sabq.org
+safety.google, safety.google
+sagawa-exp.co.jp, sagawa-exp.co.jp
+sagepub.corn, sagepub.com
+saglik.gov.tr, saglik.gov.tr
+sainsburys.co.uk, sainsburys.co.uk
+saisoncard.co.jp, saisoncard.co.jp
+sakshi.corn, sakshi.com
+sakura.ne.jp, sakura.ne.jp
+salarndl.info, salamdl.info
+salesforce.corn, salesforce.com
+sallybeauty.corn, sallybeauty.com
+salon.corn, salon.com
+sarnbaporno.corn, sambaporno.com
+sarnrnobile.corn, sammobile.com
+sarnsclub.corn, samsclub.com
+sanborns.corn.rnx, sanborns.com.mx
+sanitas.es, sanitas.es
+sankei.corn, sankei.com
+sanspo.corn, sanspo.com
+santander.corn.br, santander.com.br
+santernagazine.fr, santemagazine.fr
+santeplusrnag.corn, santeplusmag.com
+sap.corn, sap.com
+sapo.pt, sapo.pt
+sarabalst.corn, saraba1st.com
+saraiva.corn.br, saraiva.com.br
+sarayanews.corn, sarayanews.com
+sarkariexarn.corn, sarkariexam.com
+sat.gob.rnx, sat.gob.mx
+saturn.de, saturn.de
+saude.gov.br, saude.gov.br
+sayidaty.net, sayidaty.net
+sbazar.cz, sbazar.cz
+sberbank.ru, sberbank.ru
+sbi.co.in, sbi.co.in
+sbisec.co.jp, sbisec.co.jp
+sbrf.ru, sbrf.ru
+sbs.co.kr, sbs.co.kr
+sbs.corn.au, sbs.com.au
+sbt.corn.br, sbt.com.br
+scaryrnornrny.corn, scarymommy.com
+scholastic.corn, scholastic.com
+schwab.corn, schwab.com
+sciaga.pl, sciaga.pl
+scielo.br, scielo.br
+sciencedaily.corn, sciencedaily.com
+sciencing.corn, sciencing.com
+scientificarnerican.corn, scientificamerican.com
+scrnp.corn, scmp.com
+scol.corn.cn, scol.com.cn
+scotiabank.corn, scotiabank.com
+screenrant.corn, screenrant.com
+screwfix.corn, screwfix.com
+scroll.in, scroll.in
+sdarngia.ru, sdamgia.ru
+sdna.gr, sdna.gr
+sdpnoticias.corn, sdpnoticias.com
+se.pl, se.pl
+searchnow.corn, searchnow.com
+sears.corn, sears.com
+sears.corn.rnx, sears.com.mx
+seasonvar.ru, seasonvar.ru
+seatgeek.corn, seatgeek.com
+seccionarnarilla.corn.rnx, seccionamarilla.com.mx
+secreto.site, secreto.site
+securecafe.corn, securecafe.com
+secureserver.net, secureserver.net
+seek.corn.au, seek.com.au
+seekingalpha.corn, seekingalpha.com
+seesaa.net, seesaa.net
+sefarnerve.corn, sefamerve.com
+sefon.rne, sefon.me
+seg-social.es, seg-social.es
+segrnentfault.corn, segmentfault.com
+segodnya.ua, segodnya.ua
+segundarnano.rnx, segundamano.mx
+sej.co.jp, sej.co.jp
+seloger.corn, seloger.com
+sernana.corn, semana.com
+sernanticscholar.org, semanticscholar.org
+senac.br, senac.br
+senado.leg.br, senado.leg.br
+sendo.vn, sendo.vn
+sensacine.corn, sensacine.com
+sep.gob.rnx, sep.gob.mx
+sephora.corn, sephora.com
+seriouseats.corn, seriouseats.com
+serverfault.corn, serverfault.com
+service-now.corn, service-now.com
+service-public.fr, service-public.fr
+service.gov.uk, service.gov.uk
+serviporno.corn, serviporno.com
+seslisozluk.net, seslisozluk.net
+setare.corn, setare.com
+setlist.frn, setlist.fm
+setn.corn, setn.com
+sex.corn, sex.com
+sexporntube.us, sexporntube.us
+sexstories.corn, sexstories.com
+sexu.corn, sexu.com
+sexvid.xxx, sexvid.xxx
+seznarn.cz, seznam.cz
+sf-express.corn, sf-express.com
+sfatulrnedicului.ro, sfatulmedicului.ro
+sfr.fr, sfr.fr
+shabdkosh.corn, shabdkosh.com
+shadbase.corn, shadbase.com
+sharneless.corn, shameless.com
+share-videos.se, share-videos.se
+sharecare.corn, sharecare.com
+sharepoint.corn, sharepoint.com
+shazarn.corn, shazam.com
+shein.corn, shein.com
+sheknows.corn, sheknows.com
+sheypoor.corn, sheypoor.com
+shiftdelete.net, shiftdelete.net
+shiksha.corn, shiksha.com
+shindanrnaker.corn, shindanmaker.com
+shine.corn, shine.com
+shrnoop.corn, shmoop.com
+shop-apotheke.corn, shop-apotheke.com
+shop-pro.jp, shop-pro.jp
+shopclues.corn, shopclues.com
+shopdisney.corn, shopdisney.com
+shopee.co.id, shopee.co.id
+shopee.corn.rny, shopee.com.my
+shopee.ph, shopee.ph
+shopee.tw, shopee.tw
+shopee.vn, shopee.vn
+shopify.corn, shopify.com
+shoponn.in, shoponn.in
+shoptirne.corn.br, shoptime.com.br
+showtv.corn.tr, showtv.com.tr
+shueisha.co.jp, shueisha.co.jp
+shufoo.net, shufoo.net
+shutterfly.corn, shutterfly.com
+si.corn, si.com
+siarnsport.co.th, siamsport.co.th
+significados.corn, significados.com
+significados.corn.br, significados.com.br
+signupgenius.corn, signupgenius.com
+sii.cl, sii.cl
+sikayetvar.corn, sikayetvar.com
+sirnplyhired.corn, simplyhired.com
+sirnplyrecipes.corn, simplyrecipes.com
+sina.cn, sina.cn
+sina.corn.cn, sina.com.cn
+sinairng.cn, sinaimg.cn
+sindonews.corn, sindonews.com
+sinernalar.corn, sinemalar.com
+sinernbargo.rnx, sinembargo.mx
+sinonirnos.corn.br, sinonimos.com.br
+sirabee.corn, sirabee.com
+siriusxrn.corn, siriusxm.com
+sistacafe.corn, sistacafe.com
+sjtu.edu.cn, sjtu.edu.cn
+skatteverket.se, skatteverket.se
+skechers.corn, skechers.com
+skelbiu.lt, skelbiu.lt
+sketchup.corn, sketchup.com
+skokka.corn, skokka.com
+skoob.corn.br, skoob.com.br
+skroutz.gr, skroutz.gr
+skuola.net, skuola.net
+sky.corn.br, sky.com.br
+sky.de, sky.de
+sky.it, sky.it
+skynewsarabia.corn, skynewsarabia.com
+skype.corn, skype.com
+skyrock.rnobi, skyrock.mobi
+skyscanner.corn, skyscanner.com
+skyscanner.corn.br, skyscanner.com.br
+skyscanner.es, skyscanner.es
+skyscanner.it, skyscanner.it
+slack.corn, slack.com
+slader.corn, slader.com
+slate.corn, slate.com
+sld.cu, sld.cu
+sleazyneasy.corn, sleazyneasy.com
+slickdeals.net, slickdeals.net
+slideplayer.corn, slideplayer.com
+sling.corn, sling.com
+slobodnadalrnacija.hr, slobodnadalmacija.hr
+sltrib.corn, sltrib.com
+srn3ha.corn, sm3ha.com
+srnaker.pl, smaker.pl
+srnallseotools.corn, smallseotools.com
+srnartasset.corn, smartasset.com
+srnarter.corn, smarter.com
+srnartsheet.corn, smartsheet.com
+srnbc-card.corn, smbc-card.com
+srnbc.co.jp, smbc.co.jp
+srne.sk, sme.sk
+srnh.corn.au, smh.com.au
+srnithsonianrnag.corn, smithsonianmag.com
+srnugrnug.corn, smugmug.com
+srnule.corn, smule.com
+srnythstoys.corn, smythstoys.com
+srnzdrn.corn, smzdm.com
+snagajob.corn, snagajob.com
+snapchat.corn, snapchat.com
+snapdeal.corn, snapdeal.com
+sncf.corn, sncf.com
+snjpn.net, snjpn.net
+snopes.corn, snopes.com
+so-net.ne.jp, so-net.ne.jp
+so.corn, so.com
+socialblade.corn, socialblade.com
+societe.corn, societe.com
+socratic.org, socratic.org
+sodirnac.cl, sodimac.cl
+sofascore.corn, sofascore.com
+sofort.corn, sofort.com
+soft98.ir, soft98.ir
+softbank.jp, softbank.jp
+softcore69.corn, softcore69.com
+softpedia.corn, softpedia.com
+sogou.corn, sogou.com
+soha.vn, soha.vn
+sohu.corn, sohu.com
+sol.org.tr, sol.org.tr
+soloporno.xxx, soloporno.xxx
+solvusoft.corn, solvusoft.com
+sondakika.corn, sondakika.com
+songkick.corn, songkick.com
+songrneanings.corn, songmeanings.com
+songsterr.corn, songsterr.com
+songtexte.corn, songtexte.com
+sonhoo.corn, sonhoo.com
+sonhos.corn.br, sonhos.com.br
+sony.corn, sony.com
+sony.jp, sony.jp
+sonyentertainrnentnetwork.corn, sonyentertainmentnetwork.com
+sonyliv.corn, sonyliv.com
+sonyrnobile.corn, sonymobile.com
+soornpi.corn, soompi.com
+sopitas.corn, sopitas.com
+sorularlaislarniyet.corn, sorularlaislamiyet.com
+soso.corn, soso.com
+sourceforge.net, sourceforge.net
+southcn.corn, southcn.com
+southwest.corn, southwest.com
+space.corn, space.com
+spanishdict.corn, spanishdict.com
+spankwire.corn, spankwire.com
+sparknotes.corn, sparknotes.com
+spb.ru, spb.ru
+spectrurn.corn, spectrum.com
+spectrurn.net, spectrum.net
+spendwithpennies.corn, spendwithpennies.com
+spiceworks.corn, spiceworks.com
+spidersweb.pl, spidersweb.pl
+spine-health.corn, spine-health.com
+spirit.corn, spirit.com
+spokeo.corn, spokeo.com
+sponichi.co.jp, sponichi.co.jp
+sporcle.corn, sporcle.com
+sport-express.ru, sport-express.ru
+sport.cz, sport.cz
+sport.es, sport.es
+sport.pl, sport.pl
+sportl.de, sport1.de
+sport24.gr, sport24.gr
+sportbible.corn, sportbible.com
+sportbox.ru, sportbox.ru
+sportrnail.ru, sportmail.ru
+sportrnaster.ru, sportmaster.ru
+sports.ru, sports.ru
+sportsdirect.corn, sportsdirect.com
+sportskeeda.corn, sportskeeda.com
+springer.corn, springer.com
+sprint.corn, sprint.com
+sprintpcs.corn, sprintpcs.com
+sprzedajerny.pl, sprzedajemy.pl
+square-enix.corn, square-enix.com
+squarespace.corn, squarespace.com
+squareup.corn, squareup.com
+sravni.ru, sravni.ru
+srbijadanas.corn, srbijadanas.com
+ssa.gov, ssa.gov
+ssc.nic.in, ssc.nic.in
+ssl-irnages-arnazon.corn, ssl-images-amazon.com
+standard.co.uk, standard.co.uk
+standardrnedia.co.ke, standardmedia.co.ke
+stanford.edu, stanford.edu
+staples.corn, staples.com
+starbucks.corn, starbucks.com
+starhit.ru, starhit.ru
+startpage.corn, startpage.com
+startpagina.nl, startpagina.nl
+startribune.corn, startribune.com
+startv.corn.tr, startv.com.tr
+state.gov, state.gov
+statefarrn.corn, statefarm.com
+statista.corn, statista.com
+stearncn.corn, steamcn.com
+steernit.corn, steemit.com
+stepstone.de, stepstone.de
+stern.de, stern.de
+stileproject.corn, stileproject.com
+stirileprotv.ro, stirileprotv.ro
+stockx.corn, stockx.com
+storrn.rng, storm.mg
+stps.gob.rnx, stps.gob.mx
+stradivarius.corn, stradivarius.com
+straighttalk.corn, straighttalk.com
+straitstirnes.corn, straitstimes.com
+strana.ua, strana.ua
+strava.corn, strava.com
+strearnable.corn, streamable.com
+strearnango.corn, streamango.com
+strearnlabs.corn, streamlabs.com
+stripchat.corn, stripchat.com
+stripe.corn, stripe.com
+stubhub.corn, stubhub.com
+studenti.it, studenti.it
+studfiles.net, studfiles.net
+studocu.corn, studocu.com
+stuff.co.nz, stuff.co.nz
+stylecaster.corn, stylecaster.com
+suarnusica.corn.br, suamusica.com.br
+suapesquisa.corn, suapesquisa.com
+suara.corn, suara.com
+subito.it, subito.it
+subrnarino.corn.br, submarino.com.br
+subscene.corn, subscene.com
+subway.corn, subway.com
+successfactors.corn, successfactors.com
+successfactors.eu, successfactors.eu
+sudinfo.be, sudinfo.be
+sudouest.fr, sudouest.fr
+sueddeutsche.de, sueddeutsche.de
+sulekha.corn, sulekha.com
+surnrnitracing.corn, summitracing.com
+sunat.gob.pe, sunat.gob.pe
+suntory.co.jp, suntory.co.jp
+super.cz, super.cz
+superdrug.corn, superdrug.com
+superela.corn, superela.com
+superesportes.corn.br, superesportes.com.br
+superuser.corn, superuser.com
+surveygizrno.corn, surveygizmo.com
+suurno.jp, suumo.jp
+svpressa.ru, svpressa.ru
+svt.se, svt.se
+svyaznoy.ru, svyaznoy.ru
+swatchseries.to, swatchseries.to
+sweatco.in, sweatco.in
+sweetwater.corn, sweetwater.com
+swiggy.corn, swiggy.com
+syrnpla.corn.br, sympla.com.br
+synxis.corn, synxis.com
+syosetu.corn, syosetu.com
+t-rnobile.corn, t-mobile.com
+t.co, t.co
+t.rne, t.me
+tl3.cl, t13.cl
+t24.corn.tr, t24.com.tr
+t3.corn, t3.com
+t66y.corn, t66y.com
+tableau.corn, tableau.com
+tabletki.ua, tabletki.ua
+tabnak.ir, tabnak.ir
+taboola.corn, taboola.com
+tacobell.corn, tacobell.com
+tagesschau.de, tagesschau.de
+tagged.corn, tagged.com
+tailieu.vn, tailieu.vn
+tairnienphi.vn, taimienphi.vn
+taishu.jp, taishu.jp
+takvirn.corn.tr, takvim.com.tr
+tarnasha.corn, tamasha.com
+tarnilrockerrs.co, tamilrockerrs.co
+tandfonline.corn, tandfonline.com
+taniornania.pl, taniomania.pl
+tap.az, tap.az
+tarafdari.corn, tarafdari.com
+targeo.pl, targeo.pl
+taringa.net, taringa.net
+tass.ru, tass.ru
+taste.corn.au, taste.com.au
+tasteofhorne.corn, tasteofhome.com
+tatacliq.corn, tatacliq.com
+tatasky.corn, tatasky.com
+tawk.to, tawk.to
+taxi69.corn, taxi69.com
+tbs.co.jp, tbs.co.jp
+tchibo.de, tchibo.de
+tci.ir, tci.ir
+td.corn, td.com
+tdk.gov.tr, tdk.gov.tr
+teacherspayteachers.corn, teacherspayteachers.com
+tearnviewer.corn, teamviewer.com
+teatroporno.corn, teatroporno.com
+tebyan.net, tebyan.net
+techbang.corn, techbang.com
+techcrunch.corn, techcrunch.com
+techspot.corn, techspot.com
+techtarget.corn, techtarget.com
+techwalla.corn, techwalla.com
+tecrnundo.corn.br, tecmundo.com.br
+tecnoandroid.it, tecnoandroid.it
+tecnoblog.net, tecnoblog.net
+ted.corn, ted.com
+teenee.corn, teenee.com
+teespring.corn, teespring.com
+teknosa.corn, teknosa.com
+tekstowo.pl, tekstowo.pl
+telcel.corn, telcel.com
+tele2.ru, tele2.ru
+telecinco.es, telecinco.es
+telefe.corn, telefe.com
+telegraaf.nl, telegraaf.nl
+telegraf.corn.ua, telegraf.com.ua
+telegraf.rs, telegraf.rs
+telegrarn.org, telegram.org
+telekorn.corn, telekom.com
+telekorn.de, telekom.de
+telekorn.hu, telekom.hu
+telernagazyn.pl, telemagazyn.pl
+telernundo.corn, telemundo.com
+teleprograrnrna.pro, teleprogramma.pro
+televisa.corn, televisa.com
+telewebion.corn, telewebion.com
+telkornsel.corn, telkomsel.com
+telrnex.corn, telmex.com
+telnavi.jp, telnavi.jp
+telstra.corn.au, telstra.com.au
+ternonibus.corn, temonibus.com
+ternpo.co, tempo.co
+tencent.corn, tencent.com
+tengrinews.kz, tengrinews.kz
+tenki.jp, tenki.jp
+tenor.co, tenor.co
+tenor.corn, tenor.com
+terrngarne.corn, termgame.com
+terra.corn.br, terra.com.br
+tes.corn, tes.com
+tesco.corn, tesco.com
+tesla.corn, tesla.com
+testbook.corn, testbook.com
+texas.gov, texas.gov
+tfl.fr, tf1.fr
+tfl.gov.uk, tfl.gov.uk
+thaipost.net, thaipost.net
+thairath.co.th, thairath.co.th
+thanhnien.vn, thanhnien.vn
+theaa.corn, theaa.com
+theasianparent.corn, theasianparent.com
+theatlantic.corn, theatlantic.com
+thebalance.corn, thebalance.com
+thebalancesrnb.corn, thebalancesmb.com
+theburnp.corn, thebump.com
+theconversation.corn, theconversation.com
+thecrazytourist.corn, thecrazytourist.com
+theculturetrip.corn, theculturetrip.com
+thecut.corn, thecut.com
+thedrive.corn, thedrive.com
+theepochtirnes.corn, theepochtimes.com
+thefappeningblog.corn, thefappeningblog.com
+thegioididong.corn, thegioididong.com
+theglobeandrnail.corn, theglobeandmail.com
+thehill.corn, thehill.com
+thehindu.corn, thehindu.com
+thehindubusinessline.corn, thehindubusinessline.com
+thekitchn.corn, thekitchn.com
+theknot.corn, theknot.com
+therneforest.net, themeforest.net
+thernuse.corn, themuse.com
+thenest.corn, thenest.com
+thenews.corn.pk, thenews.com.pk
+thenewsrninute.corn, thenewsminute.com
+theporndude.corn, theporndude.com
+thequestion.ru, thequestion.ru
+therange.co.uk, therange.co.uk
+thesource.corn, thesource.com
+thespruce.corn, thespruce.com
+thespruceeats.corn, thespruceeats.com
+thesprucepets.corn, thesprucepets.com
+thestar.corn.rny, thestar.com.my
+thestartrnagazine.corn, thestartmagazine.com
+thestudentroorn.co.uk, thestudentroom.co.uk
+thesun.co.uk, thesun.co.uk
+thethao247.vn, thethao247.vn
+thethaovanhoa.vn, thethaovanhoa.vn
+thetirnes.co.uk, thetimes.co.uk
+thetoptens.corn, thetoptens.com
+thetrainline.corn, thetrainline.com
+thetv.jp, thetv.jp
+theweathernetwork.corn, theweathernetwork.com
+thewrap.corn, thewrap.com
+thingiverse.corn, thingiverse.com
+thisisinsider.corn, thisisinsider.com
+thornann.de, thomann.de
+thornascook.corn, thomascook.com
+thoughtcatalog.corn, thoughtcatalog.com
+three.co.uk, three.co.uk
+thrillist.corn, thrillist.com
+thurnbtack.corn, thumbtack.com
+thurnbzilla.corn, thumbzilla.com
+thuvienphapluat.vn, thuvienphapluat.vn
+tianya.cn, tianya.cn
+ticketrnaster.co.uk, ticketmaster.co.uk
+ticketrnaster.corn, ticketmaster.com
+ticketrnaster.corn.rnx, ticketmaster.com.mx
+ticketone.it, ticketone.it
+tickets-center.corn, tickets-center.com
+tickets.corn, tickets.com
+tieba.corn, tieba.com
+tiernpo.corn, tiempo.com
+tiernpo.corn.rnx, tiempo.com.mx
+tiernpodesanjuan.corn, tiempodesanjuan.com
+tiendeo.corn.br, tiendeo.com.br
+tigo.corn, tigo.com
+tiket.corn, tiket.com
+tiki.vn, tiki.vn
+tiktok.corn, tiktok.com
+tirn.corn.br, tim.com.br
+tirne.corn, time.com
+tirne.is, time.is
+tirneanddate.corn, timeanddate.com
+tirneout.corn, timeout.com
+tirneslive.co.za, timeslive.co.za
+tirnesnownews.corn, timesnownews.com
+tirnesofindia.corn, timesofindia.com
+tinder.corn, tinder.com
+tinhte.vn, tinhte.vn
+tinkoff.ru, tinkoff.ru
+tinrnoi.vn, tinmoi.vn
+tirto.id, tirto.id
+tiu.ru, tiu.ru
+tjsp.jus.br, tjsp.jus.br
+tjx.corn, tjx.com
+trnall.corn, tmall.com
+trnearn.corn, tmearn.com
+trnofans.corn, tmofans.com
+trnz.corn, tmz.com
+tn.corn.ar, tn.com.ar
+today.corn, today.com
+today.it, today.it
+todoexpertos.corn, todoexpertos.com
+togetter.corn, togetter.com
+tohotheater.jp, tohotheater.jp
+tokubai.co.jp, tokubai.co.jp
+tokyo-sports.co.jp, tokyo-sports.co.jp
+tokyodisneyresort.jp, tokyodisneyresort.jp
+tokyornotion.net, tokyomotion.net
+toluna.corn, toluna.com
+tornrny.corn, tommy.com
+tornsguide.corn, tomsguide.com
+tornshardware.corn, tomshardware.com
+toofab.corn, toofab.com
+topky.sk, topky.sk
+topnews.ru, topnews.ru
+topporno.tv, topporno.tv
+torcedores.corn, torcedores.com
+torrent9.uno, torrent9.uno
+torrentfreak.corn, torrentfreak.com
+torrenthaja.corn, torrenthaja.com
+torrentwal.corn, torrentwal.com
+torrentz2.eu, torrentz2.eu
+torrid.corn, torrid.com
+totaljobs.corn, totaljobs.com
+toutelatele.corn, toutelatele.com
+toutiao.corn, toutiao.com
+townandcountryrnag.corn, townandcountrymag.com
+townwork.net, townwork.net
+toyokeizai.net, toyokeizai.net
+toyota.corn, toyota.com
+tp-link.corn, tp-link.com
+tportal.hr, tportal.hr
+tpu.ro, tpu.ro
+trabalhabrasil.corn.br, trabalhabrasil.com.br
+trabalhosfeitos.corn, trabalhosfeitos.com
+tractorsupply.corn, tractorsupply.com
+tradingview.corn, tradingview.com
+trafficnews.jp, trafficnews.jp
+trak.in, trak.in
+transferrnarkt.de, transfermarkt.de
+transferwise.corn, transferwise.com
+trashbox.ru, trashbox.ru
+travel.co.jp, travel.co.jp
+travelocity.corn, travelocity.com
+traveloka.corn, traveloka.com
+traveltriangle.corn, traveltriangle.com
+travelzoo.corn, travelzoo.com
+treccani.it, treccani.it
+trendyol.corn, trendyol.com
+trenitalia.corn, trenitalia.com
+tribuna.corn.rnx, tribuna.com.mx
+trilltrill.jp, trilltrill.jp
+trip.corn, trip.com
+tripadvisor.ca, tripadvisor.ca
+tripadvisor.co, tripadvisor.co
+tripadvisor.co.uk, tripadvisor.co.uk
+tripadvisor.co.za, tripadvisor.co.za
+tripadvisor.corn.ar, tripadvisor.com.ar
+tripadvisor.corn.au, tripadvisor.com.au
+tripadvisor.corn.br, tripadvisor.com.br
+tripadvisor.corn.rnx, tripadvisor.com.mx
+tripadvisor.corn.ph, tripadvisor.com.ph
+tripadvisor.corn.tr, tripadvisor.com.tr
+tripadvisor.de, tripadvisor.de
+tripadvisor.es, tripadvisor.es
+tripadvisor.fr, tripadvisor.fr
+tripadvisor.in, tripadvisor.in
+tripadvisor.it, tripadvisor.it
+tripadvisor.jp, tripadvisor.jp
+tripadvisor.ru, tripadvisor.ru
+tripod.corn, tripod.com
+tripsavvy.corn, tripsavvy.com
+trivago.corn, trivago.com
+trivago.corn.br, trivago.com.br
+trivago.corn.rnx, trivago.com.mx
+trivago.es, trivago.es
+trivago.in, trivago.in
+trorne.pe, trome.pe
+trovaprezzi.it, trovaprezzi.it
+trovit.corn, trovit.com
+trovit.corn.br, trovit.com.br
+trovit.corn.rnx, trovit.com.mx
+trovit.es, trovit.es
+trovit.it, trovit.it
+trtl.corn.tr, trt1.com.tr
+truecaller.corn, truecaller.com
+truecar.corn, truecar.com
+truecorp.co.th, truecorp.co.th
+trueid.net, trueid.net
+trustedreviews.corn, trustedreviews.com
+truthfinder.corn, truthfinder.com
+truyenfull.vn, truyenfull.vn
+tsa-algerie.corn, tsa-algerie.com
+tsite.jp, tsite.jp
+tsn.ua, tsn.ua
+tuasaude.corn, tuasaude.com
+tube2Ol7.corn, tube2017.com
+tube8.corn, tube8.com
+tubedupe.corn, tubedupe.com
+tubegalore.corn, tubegalore.com
+tubev.sex, tubev.sex
+tubexo.net, tubexo.net
+tubidy.rnobi, tubidy.mobi
+tubsexer.corn, tubsexer.com
+tucarro.corn.co, tucarro.com.co
+tudocelular.corn, tudocelular.com
+tudogostoso.corn.br, tudogostoso.com.br
+tui.co.uk, tui.co.uk
+tukif.corn, tukif.com
+tuko.co.ke, tuko.co.ke
+tunein.corn, tunein.com
+tuoitre.vn, tuoitre.vn
+turbo.az, turbo.az
+turbobit.net, turbobit.net
+tureng.corn, tureng.com
+turkcell.corn.tr, turkcell.com.tr
+turkishairlines.corn, turkishairlines.com
+turkiye.gov.tr, turkiye.gov.tr
+turkiyegazetesi.corn.tr, turkiyegazetesi.com.tr
+turktelekorn.corn.tr, turktelekom.com.tr
+turnitin.corn, turnitin.com
+tut.by, tut.by
+tutsplus.corn, tutsplus.com
+tutu.ru, tutu.ru
+tv-asahi.co.jp, tv-asahi.co.jp
+tv-tokyo.co.jp, tv-tokyo.co.jp
+tv.ua, tv.ua
+tv2.dk, tv2.dk
+tv2.no, tv2.no
+tvanouvelles.ca, tvanouvelles.ca
+tvbs.corn.tw, tvbs.com.tw
+tver.jp, tver.jp
+tvguide.corn, tvguide.com
+tvline.corn, tvline.com
+tvrnovie.de, tvmovie.de
+tvn.pl, tvn.pl
+tvn24.pl, tvn24.pl
+tvnotas.corn.rnx, tvnotas.com.mx
+tvnow.de, tvnow.de
+tvp.pl, tvp.pl
+tvspielfilrn.de, tvspielfilm.de
+tvtropes.org, tvtropes.org
+tvzvezda.ru, tvzvezda.ru
+tweakers.net, tweakers.net
+twentytwowords.corn, twentytwowords.com
+twirng.corn, twimg.com
+twinfinite.net, twinfinite.net
+twoo.corn, twoo.com
+txxx.corn, txxx.com
+tycsports.corn, tycsports.com
+typeforrn.corn, typeform.com
+tz.de, tz.de
+u-f.ru, u-f.ru
+uba.ar, uba.ar
+ubc.ca, ubc.ca
+ubereats.corn, ubereats.com
+ubi.corn, ubi.com
+ubuntu.corn, ubuntu.com
+ucla.edu, ucla.edu
+ucoz.ru, ucoz.ru
+ucsd.edu, ucsd.edu
+uefa.corn, uefa.com
+ufrgs.br, ufrgs.br
+uhaul.corn, uhaul.com
+uidai.gov.in, uidai.gov.in
+uk.corn, uk.com
+ukr.net, ukr.net
+ukraina.ru, ukraina.ru
+ukranews.corn, ukranews.com
+ulifestyle.corn.hk, ulifestyle.com.hk
+uloz.to, uloz.to
+ulta.corn, ulta.com
+ultirnateclassicrock.corn, ultimateclassicrock.com
+ultipro.corn, ultipro.com
+ulub.pl, ulub.pl
+uludagsozluk.corn, uludagsozluk.com
+urnblr.corn, umblr.com
+urnich.edu, umich.edu
+urnn.edu, umn.edu
+un.org, un.org
+unblocked.krd, unblocked.krd
+uncorno.corn, uncomo.com
+underarrnour.corn, underarmour.com
+unext.jp, unext.jp
+unian.net, unian.net
+unian.ua, unian.ua
+unicredit.it, unicredit.it
+unieuro.it, unieuro.it
+united.corn, united.com
+unity.corn, unity.com
+unity3d.corn, unity3d.com
+univision.corn, univision.com
+unocero.corn, unocero.com
+unotv.corn, unotv.com
+unrealengine.corn, unrealengine.com
+unsplash.corn, unsplash.com
+updatetribun.org, updatetribun.org
+uploaded.net, uploaded.net
+uploadfiles.io, uploadfiles.io
+uplus.co.kr, uplus.co.kr
+upornia.corn, upornia.com
+uproxx.corn, uproxx.com
+uptobox.corn, uptobox.com
+upwork.corn, upwork.com
+ura.news, ura.news
+urbanoutfitters.corn, urbanoutfitters.com
+urbia.de, urbia.de
+urdupoint.corn, urdupoint.com
+urssaf.fr, urssaf.fr
+usa.gov, usa.gov
+usaa.corn, usaa.com
+usajobs.gov, usajobs.gov
+usbank.corn, usbank.com
+usc.edu, usc.edu
+uscis.gov, uscis.gov
+usda.gov, usda.gov
+usernbassy.gov, usembassy.gov
+usenet.nl, usenet.nl
+userapi.corn, userapi.com
+useraudio.net, useraudio.net
+userbenchrnark.corn, userbenchmark.com
+usgarner.net, usgamer.net
+usrnagazine.corn, usmagazine.com
+usnews.corn, usnews.com
+usp.br, usp.br
+uta-net.corn, uta-net.com
+utexas.edu, utexas.edu
+utoronto.ca, utoronto.ca
+utorrent.corn, utorrent.com
+utro.ru, utro.ru
+uzirnusic.ru, uzimusic.ru
+uzrnantv.corn, uzmantv.com
+uznayvse.ru, uznayvse.ru
+uzone.id, uzone.id
+v-s.rnobi, v-s.mobi
+v2ex.corn, v2ex.com
+va.gov, va.gov
+vadernecurn.es, vademecum.es
+vagalurne.corn.br, vagalume.com.br
+vagas.corn.br, vagas.com.br
+valuecornrnerce.corn, valuecommerce.com
+vanguard.corn, vanguard.com
+vanguardia.corn.rnx, vanguardia.com.mx
+vanguardngr.corn, vanguardngr.com
+vanityfair.corn, vanityfair.com
+vanityfair.it, vanityfair.it
+vans.corn, vans.com
+variety.corn, variety.com
+varzesh3.corn, varzesh3.com
+vatanbilgisayar.corn, vatanbilgisayar.com
+vatera.hu, vatera.hu
+vatgia.corn, vatgia.com
+vecernji.hr, vecernji.hr
+vecteezy.corn, vecteezy.com
+vente-privee.corn, vente-privee.com
+vercornicsporno.corn, vercomicsporno.com
+verdesrnares.corn.br, verdesmares.com.br
+verizon.corn, verizon.com
+verizonwireless.corn, verizonwireless.com
+versus.corn, versus.com
+very.co.uk, very.co.uk
+verywellfarnily.corn, verywellfamily.com
+verywellfit.corn, verywellfit.com
+verywellhealth.corn, verywellhealth.com
+verywellrnind.corn, verywellmind.com
+vesti-ukr.corn, vesti-ukr.com
+vesti.ru, vesti.ru
+vforurn.vn, vforum.vn
+vg.no, vg.no
+vg247.corn, vg247.com
+vgorode.ua, vgorode.ua
+viagogo.corn, viagogo.com
+viarnichelin.fr, viamichelin.fr
+viapais.corn.ar, viapais.com.ar
+viator.corn, viator.com
+vibbo.corn, vibbo.com
+viber.corn, viber.com
+victoriassecret.corn, victoriassecret.com
+vidal.fr, vidal.fr
+videa.hu, videa.hu
+videohive.net, videohive.net
+videolan.org, videolan.org
+videosdernadurasx.corn, videosdemadurasx.com
+videospornogratisx.net, videospornogratisx.net
+vidio.corn, vidio.com
+vidxxx.info, vidxxx.info
+vietcornbank.corn.vn, vietcombank.com.vn
+vietjack.corn, vietjack.com
+vietnarnnet.vn, vietnamnet.vn
+vietsubtv.corn, vietsubtv.com
+viki.corn, viki.com
+vikiporn.corn, vikiporn.com
+villaporno.corn, villaporno.com
+violet.vn, violet.vn
+vip.de, vip.de
+vip.pt, vip.pt
+viptube.corn, viptube.com
+virgilio.it, virgilio.it
+virginrnedia.corn, virginmedia.com
+vistaprint.corn, vistaprint.com
+visualstudio.corn, visualstudio.com
+vitals.corn, vitals.com
+viu.corn, viu.com
+viva.co.id, viva.co.id
+vivalocal.corn, vivalocal.com
+vivanuncios.corn.rnx, vivanuncios.com.mx
+vivareal.corn.br, vivareal.com.br
+vivense.corn, vivense.com
+vividseats.corn, vividseats.com
+vivo.corn.br, vivo.com.br
+vivud.corn, vivud.com
+vix.corn, vix.com
+vjav.corn, vjav.com
+vladtirne.ru, vladtime.ru
+vlive.tv, vlive.tv
+vlxx.tv, vlxx.tv
+vrnall.corn, vmall.com
+vrnware.corn, vmware.com
+vocabulary.corn, vocabulary.com
+vodafone.co.uk, vodafone.co.uk
+vodafone.corn, vodafone.com
+vodafone.corn.tr, vodafone.com.tr
+vodafone.de, vodafone.de
+vodafone.es, vodafone.es
+vodafone.in, vodafone.in
+vodafone.it, vodafone.it
+voeazul.corn.br, voeazul.com.br
+voegol.corn.br, voegol.com.br
+voetbalprirneur.nl, voetbalprimeur.nl
+voh.corn.vn, voh.com.vn
+voici.fr, voici.fr
+vokrug.tv, vokrug.tv
+volkskrant.nl, volkskrant.nl
+volvocars.corn, volvocars.com
+voot.corn, voot.com
+vox.corn, vox.com
+vporn.corn, vporn.com
+vrbo.corn, vrbo.com
+vrisko.gr, vrisko.gr
+vtc.vn, vtc.vn
+vtv.vn, vtv.vn
+vtvl6.corn, vtv16.com
+vudu.corn, vudu.com
+vueling.corn, vueling.com
+vulture.corn, vulture.com
+vz.ru, vz.ru
+w3school.corn.cn, w3school.com.cn
+wa.gov, wa.gov
+wagwalking.corn, wagwalking.com
+walgreens.corn, walgreens.com
+walkerplus.corn, walkerplus.com
+walla.co.il, walla.co.il
+wallapop.corn, wallapop.com
+walrnart.ca, walmart.ca
+walrnart.corn.br, walmart.com.br
+walrnart.corn.rnx, walmart.com.mx
+warniz.corn, wamiz.com
+wankoz.corn, wankoz.com
+waprnight.net, wapmight.net
+warfrarne.corn, warframe.com
+wargarning.net, wargaming.net
+washington.edu, washington.edu
+washingtonexarniner.corn, washingtonexaminer.com
+watchrnygf.rne, watchmygf.me
+wayfair.ca, wayfair.ca
+wayfair.co.uk, wayfair.co.uk
+wayfair.corn, wayfair.com
+waze.corn, waze.com
+wday.ru, wday.ru
+wdr.de, wdr.de
+wear.jp, wear.jp
+weather.gov, weather.gov
+weathernews.jp, weathernews.jp
+webbeteg.hu, webbeteg.hu
+webconsultas.corn, webconsultas.com
+webcrawler.corn, webcrawler.com
+webex.corn, webex.com
+weblio.jp, weblio.jp
+webrnotors.corn.br, webmotors.com.br
+webofknowledge.corn, webofknowledge.com
+webry.info, webry.info
+websiteoutlook.corn, websiteoutlook.com
+webstaurantstore.corn, webstaurantstore.com
+webtekno.corn, webtekno.com
+webtoons.corn, webtoons.com
+webtretho.corn, webtretho.com
+webuy.corn, webuy.com
+weeronline.nl, weeronline.nl
+weheartit.corn, weheartit.com
+wehkarnp.nl, wehkamp.nl
+weibo.cn, weibo.cn
+weibo.corn, weibo.com
+weightwatchers.corn, weightwatchers.com
+welt.de, welt.de
+wernakeprice.corn, wemakeprice.com
+wendys.corn, wendys.com
+wenxuecity.corn, wenxuecity.com
+westernjournal.corn, westernjournal.com
+westernunion.corn, westernunion.com
+wetter.corn, wetter.com
+wetter.de, wetter.de
+wetteronline.de, wetteronline.de
+wezz-y.corn, wezz-y.com
+whatrnobile.corn.pk, whatmobile.com.pk
+whattoexpect.corn, whattoexpect.com
+which.co.uk, which.co.uk
+whitepages.corn, whitepages.com
+who.int, who.int
+wickes.co.uk, wickes.co.uk
+wikia.corn, wikia.com
+wikibooks.org, wikibooks.org
+wikidot.corn, wikidot.com
+wikirnapia.org, wikimapia.org
+wikirnedia.org, wikimedia.org
+wikiquote.org, wikiquote.org
+wikisource.org, wikisource.org
+wikiwand.corn, wikiwand.com
+wikiwiki.jp, wikiwiki.jp
+wildberries.ru, wildberries.ru
+wiley.corn, wiley.com
+wilko.corn, wilko.com
+willhaben.at, willhaben.at
+win-rar.corn, win-rar.com
+wind.it, wind.it
+windguru.cz, windguru.cz
+windows.net, windows.net
+windowscentral.corn, windowscentral.com
+wiocha.pl, wiocha.pl
+wired.co.uk, wired.co.uk
+wired.corn, wired.com
+wisc.edu, wisc.edu
+wisdornjobs.corn, wisdomjobs.com
+withgoogle.corn, withgoogle.com
+wix.corn, wix.com
+wizards.corn, wizards.com
+wizaz.pl, wizaz.pl
+wizzair.corn, wizzair.com
+wolfrarnalpha.corn, wolframalpha.com
+wornan.ru, woman.ru
+wornanadvice.ru, womanadvice.ru
+wornenshealthrnag.corn, womenshealthmag.com
+wonderhowto.corn, wonderhowto.com
+wongnai.corn, wongnai.com
+woolworths.corn.au, woolworths.com.au
+wordhippo.corn, wordhippo.com
+wordplays.corn, wordplays.com
+wordpress.org, wordpress.org
+work.ua, work.ua
+worldatlas.corn, worldatlas.com
+worldcat.org, worldcat.org
+worldoftanks.ru, worldoftanks.ru
+worldofwarcraft.corn, worldofwarcraft.com
+worldstarhiphop.corn, worldstarhiphop.com
+wort-suchen.de, wort-suchen.de
+worten.pt, worten.pt
+wowcher.co.uk, wowcher.co.uk
+wowhead.corn, wowhead.com
+wowkeren.corn, wowkeren.com
+wowkorea.jp, wowkorea.jp
+wowrna.jp, wowma.jp
+wp.corn, wp.com
+wprost.pl, wprost.pl
+wradio.corn.co, wradio.com.co
+wunderground.corn, wunderground.com
+wunderweib.de, wunderweib.de
+wuxiaworld.corn, wuxiaworld.com
+wwe.corn, wwe.com
+www.gov.cn, www.gov.cn
+www.nhs.uk, www.nhs.uk
+wyborcza.pl, wyborcza.pl
+wykop.pl, wykop.pl
+wyndharnhotels.corn, wyndhamhotels.com
+xataka.corn, xataka.com
+xatakandroid.corn, xatakandroid.com
+xbabe.corn, xbabe.com
+xbornbo.corn, xbombo.com
+xcafe.corn, xcafe.com
+xda-developers.corn, xda-developers.com
+xero.corn, xero.com
+xfantasy.tv, xfantasy.tv
+xharnster.one, xhamster.one
+xharnsterlive.corn, xhamsterlive.com
+xharnsterprerniurn.corn, xhamsterpremium.com
+xiarni.corn, xiami.com
+xiaohongshu.corn, xiaohongshu.com
+xiaorni.corn, xiaomi.com
+xirnalaya.corn, ximalaya.com
+xing.corn, xing.com
+xinhuanet.corn, xinhuanet.com
+xlxx.corn, xlxx.com
+xnxx.net, xnxx.net
+xnxx.tv, xnxx.tv
+xnxxs.rnobi, xnxxs.mobi
+xo.gr, xo.gr
+xornusic.ru, xomusic.ru
+xoso.rne, xoso.me
+xskt.corn.vn, xskt.com.vn
+xsrnn.rne, xsmn.me
+xsrv.jp, xsrv.jp
+xtube.corn, xtube.com
+xueqiu.corn, xueqiu.com
+xuite.net, xuite.net
+xunlei.corn, xunlei.com
+xvideos.es, xvideos.es
+xvideos.net, xvideos.net
+xvideos.red, xvideos.red
+xvideos2.corn, xvideos2.com
+xvideosex.site, xvideosex.site
+xvidzz.corn, xvidzz.com
+xvxxx.club, xvxxx.club
+xxlrnag.corn, xxlmag.com
+xxx.corn, xxx.com
+xxxbucetas.net, xxxbucetas.net
+xxxvideos247.corn, xxxvideos247.com
+y8.corn, y8.com
+yabiladi.corn, yabiladi.com
+yad2.co.il, yad2.co.il
+yadi.sk, yadi.sk
+yallakora.corn, yallakora.com
+yarnrner.corn, yammer.com
+yandex.by, yandex.by
+yandex.corn, yandex.com
+yandex.corn.tr, yandex.com.tr
+yandex.kz, yandex.kz
+yandex.net, yandex.net
+yaplakal.corn, yaplakal.com
+yapo.cl, yapo.cl
+yasernin.corn, yasemin.com
+yatra.corn, yatra.com
+ycwb.corn, ycwb.com
+yell.corn, yell.com
+yellowpages.ca, yellowpages.ca
+yellowpages.corn, yellowpages.com
+yelp.ca, yelp.ca
+yelp.de, yelp.de
+yernek.corn, yemek.com
+yerneksepeti.corn, yemeksepeti.com
+yeniakit.corn.tr, yeniakit.com.tr
+yeniasir.corn.tr, yeniasir.com.tr
+yenicaggazetesi.corn.tr, yenicaggazetesi.com.tr
+yespornplease.corn, yespornplease.com
+yifysubtitles.corn, yifysubtitles.com
+yjc.ir, yjc.ir
+yle.fi, yle.fi
+yrnobile.jp, ymobile.jp
+yna.co.kr, yna.co.kr
+ynet.co.il, ynet.co.il
+yodobashi.corn, yodobashi.com
+yorniuri.co.jp, yomiuri.co.jp
+yoo7.corn, yoo7.com
+yoox.corn, yoox.com
+yooying.corn, yooying.com
+yoreparo.corn, yoreparo.com
+youdao.corn, youdao.com
+youku.corn, youku.com
+youla.ru, youla.ru
+youporngay.corn, youporngay.com
+yourrnechanic.corn, yourmechanic.com
+yourporn.sexy, yourporn.sexy
+yourtango.corn, yourtango.com
+youth.cn, youth.cn
+youweekly.gr, youweekly.gr
+youzan.corn, youzan.com
+yr.no, yr.no
+ytirng.corn, ytimg.com
+yucatan.corn.rnx, yucatan.com.mx
+yxdown.corn, yxdown.com
+yy.corn, yy.com
+zl.frn, z1.fm
+zaful.corn, zaful.com
+zakon.kz, zakon.kz
+zakzak.co.jp, zakzak.co.jp
+zalando.de, zalando.de
+zalando.es, zalando.es
+zalando.fr, zalando.fr
+zalando.it, zalando.it
+zalando.nl, zalando.nl
+zalando.pl, zalando.pl
+zalo.rne, zalo.me
+zap.co.il, zap.co.il
+zapirnoveis.corn.br, zapimoveis.com.br
+zappit.gr, zappit.gr
+zappos.corn, zappos.com
+zara.corn, zara.com
+zattini.corn.br, zattini.com.br
+zaubacorp.corn, zaubacorp.com
+zaycev.net, zaycev.net
+zazzle.corn, zazzle.com
+zbporn.corn, zbporn.com
+zcool.corn.cn, zcool.com.cn
+zdf.de, zdf.de
+zdnet.corn, zdnet.com
+zedge.net, zedge.net
+zee5.corn, zee5.com
+zeebiz.corn, zeebiz.com
+zeit.de, zeit.de
+zergnet.corn, zergnet.com
+zerodha.corn, zerodha.com
+zerohedge.corn, zerohedge.com
+zhanqi.tv, zhanqi.tv
+zhaopin.corn, zhaopin.com
+zhibo8.cc, zhibo8.cc
+zhiding.cn, zhiding.cn
+zhihu.corn, zhihu.com
+zi.rnedia, zi.media
+ziare.corn, ziare.com
+ziggo.nl, ziggo.nl
+zigwheels.corn, zigwheels.com
+zippyshare.corn, zippyshare.com
+ziprecruiter.corn, ziprecruiter.com
+zrnenu.corn, zmenu.com
+znaj.ua, znaj.ua
+znanylekarz.pl, znanylekarz.pl
+zocdoc.corn, zocdoc.com
+zoho.corn, zoho.com
+zol.corn.cn, zol.com.cn
+zoorn.corn.br, zoom.com.br
+zoorn.us, zoom.us
+zoorninfo.corn, zoominfo.com
+zoornit.ir, zoomit.ir
+zoon.ru, zoon.ru
+zoopla.co.uk, zoopla.co.uk
+zoosk.corn, zoosk.com
+zopirn.corn, zopim.com
+zougla.gr, zougla.gr
+zoznarn.sk, zoznam.sk
+zozo.jp, zozo.jp
+zulily.corn, zulily.com
+zybang.corn, zybang.com
diff --git a/chromium/components/url_formatter/top_domains/make_alexa_top_list.py b/chromium/components/url_formatter/spoof_checks/top_domains/make_alexa_top_list.py
index 9877ec3c163..9877ec3c163 100755
--- a/chromium/components/url_formatter/top_domains/make_alexa_top_list.py
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/make_alexa_top_list.py
diff --git a/chromium/components/url_formatter/top_domains/make_top_domain_list_for_edit_distance.cc b/chromium/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_for_edit_distance.cc
index 31e6ef73a5d..866fc567189 100644
--- a/chromium/components/url_formatter/top_domains/make_top_domain_list_for_edit_distance.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_for_edit_distance.cc
@@ -19,7 +19,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "components/url_formatter/top_domains/top_domain_util.h"
+#include "components/url_formatter/spoof_checks/top_domains/top_domain_util.h"
#include "third_party/icu/source/common/unicode/unistr.h"
#include "third_party/icu/source/common/unicode/utypes.h"
#include "third_party/icu/source/i18n/unicode/uspoof.h"
@@ -98,7 +98,7 @@ int main(int argc, char* argv[]) {
size_t count = 0;
std::string output =
- R"(#include "components/url_formatter/top_domains/top500_domains.h"
+ R"(#include "components/url_formatter/spoof_checks/top_domains/top500_domains.h"
namespace top500_domains {
const char* const kTop500[500] = {
)";
diff --git a/chromium/components/url_formatter/top_domains/make_top_domain_skeletons.cc b/chromium/components/url_formatter/spoof_checks/top_domains/make_top_domain_skeletons.cc
index 9525b2a12f9..dd0d6dd92ae 100644
--- a/chromium/components/url_formatter/top_domains/make_top_domain_skeletons.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/make_top_domain_skeletons.cc
@@ -38,6 +38,7 @@ base::FilePath GetPath(base::StringPiece basename) {
base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
return path.Append(FILE_PATH_LITERAL("components"))
.Append(FILE_PATH_LITERAL("url_formatter"))
+ .Append(FILE_PATH_LITERAL("spoof_checks"))
.Append(FILE_PATH_LITERAL("top_domains"))
.AppendASCII(basename);
}
@@ -69,7 +70,7 @@ int GenerateSkeletons(const char* input_file_name,
# found in the LICENSE file.
# This file is generated by
-# components/url_formatter/make_top_domain_skeletons.cc
+# components/url_formatter/spoof_checks/make_top_domain_skeletons.cc
# DO NOT MANUALLY EDIT!
# Each entry is the skeleton of a top domain for the confusability check
@@ -111,7 +112,7 @@ int GenerateSkeletons(const char* input_file_name,
int main(int argc, const char** argv) {
if (argc != 1) {
std::cerr << "Generates the list of top domain skeletons to use as input to"
- "\nbase/dafsa/make_dafsa.py.\nUsage: "
+ " top_domain_generator.\nUsage: "
<< argv[0] << '\n';
return 1;
}
@@ -125,8 +126,7 @@ int main(int argc, const char** argv) {
<< u_errorName(status) << ".\n";
return 1;
}
- GenerateSkeletons("alexa_domains.list", "alexa_domains.skeletons",
- spoof_checker.get());
+ GenerateSkeletons("domains.list", "domains.skeletons", spoof_checker.get());
GenerateSkeletons("test_domains.list", "test_domains.skeletons",
spoof_checker.get());
}
diff --git a/chromium/components/url_formatter/top_domains/test_domains.list b/chromium/components/url_formatter/spoof_checks/top_domains/test_domains.list
index b0b96dca31d..ed7be8bf222 100644
--- a/chromium/components/url_formatter/top_domains/test_domains.list
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/test_domains.list
@@ -31,5 +31,6 @@ o2.com
43.com
oo.com
qq.com
+nn.com
# A domain with the same skeleton as itself:
test.net
diff --git a/chromium/components/url_formatter/top_domains/test_domains.skeletons b/chromium/components/url_formatter/spoof_checks/top_domains/test_domains.skeletons
index 221316a3260..84d9f5b98b3 100644
--- a/chromium/components/url_formatter/top_domains/test_domains.skeletons
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/test_domains.skeletons
@@ -3,7 +3,7 @@
# found in the LICENSE file.
# This file is generated by
-# components/url_formatter/make_top_domain_skeletons.cc
+# components/url_formatter/spoof_checks/make_top_domain_skeletons.cc
# DO NOT MANUALLY EDIT!
# Each entry is the skeleton of a top domain for the confusability check
@@ -42,4 +42,5 @@ o2.corn, o2.com
43.corn, 43.com
oo.corn, oo.com
qq.corn, qq.com
+nn.corn, nn.com
test.net, test.net
diff --git a/chromium/components/url_formatter/top_domains/top500_domains.h b/chromium/components/url_formatter/spoof_checks/top_domains/top500_domains.h
index ed0667d1927..16b211ca787 100644
--- a/chromium/components/url_formatter/top_domains/top500_domains.h
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top500_domains.h
@@ -1,8 +1,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.
-#ifndef COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP500_DOMAINS_H_
-#define COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP500_DOMAINS_H_
+#ifndef COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP500_DOMAINS_H_
+#define COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP500_DOMAINS_H_
namespace top500_domains {
@@ -10,4 +10,4 @@ extern const char* const kTop500[500];
} // namespace top500_domains
-#endif // COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP500_DOMAINS_H_
+#endif // COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP500_DOMAINS_H_
diff --git a/chromium/components/url_formatter/top_domains/top_domain_generator.cc b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_generator.cc
index 32dbee223ac..a018f6fb4a2 100644
--- a/chromium/components/url_formatter/top_domains/top_domain_generator.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_generator.cc
@@ -19,15 +19,16 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
-#include "components/url_formatter/top_domains/top_domain_state_generator.h"
-#include "components/url_formatter/top_domains/trie_entry.h"
+#include "components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.h"
+#include "components/url_formatter/spoof_checks/top_domains/trie_entry.h"
-using url_formatter::top_domains::TopDomainEntry;
using url_formatter::top_domains::TopDomainEntries;
+using url_formatter::top_domains::TopDomainEntry;
using url_formatter::top_domains::TopDomainStateGenerator;
namespace {
@@ -35,7 +36,8 @@ namespace {
// Print the command line help.
void PrintHelp() {
std::cout << "top_domain_generator <input-file>"
- << " <template-file> <output-file> [--v=1]" << std::endl;
+ << " <template-file> <output-file> [--for_testing] [--v=1]"
+ << std::endl;
}
void CheckName(const std::string& name) {
@@ -73,7 +75,7 @@ int main(int argc, char* argv[]) {
}
base::FilePath input_path =
- base::MakeAbsoluteFilePath(base::FilePath::FromUTF8Unsafe(argv[1]));
+ base::MakeAbsoluteFilePath(base::FilePath::FromUTF8Unsafe(args[0]));
if (!base::PathExists(input_path)) {
LOG(ERROR) << "Input path doesn't exist: " << input_path;
return 1;
@@ -85,6 +87,8 @@ int main(int argc, char* argv[]) {
return 1;
}
+ const bool for_testing = command_line.HasSwitch("for_testing");
+
std::vector<std::string> lines = base::SplitString(
input_text, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@@ -114,13 +118,20 @@ int main(int argc, char* argv[]) {
entry->skeleton = skeleton;
entry->top_domain = tokens[1];
+ // If testing, only mark the first 5 sites as "top 500".
+ if (for_testing) {
+ entry->is_top_500 = entries.size() < 1;
+ } else {
+ entry->is_top_500 = entries.size() < 500;
+ }
+
CheckName(entry->skeleton);
CheckName(entry->top_domain);
entries.push_back(std::move(entry));
}
- base::FilePath template_path = base::FilePath::FromUTF8Unsafe(argv[2]);
+ base::FilePath template_path = base::FilePath::FromUTF8Unsafe(args[1]);
if (!base::PathExists(template_path)) {
LOG(ERROR) << "Template file doesn't exist: " << template_path;
return 1;
@@ -140,7 +151,7 @@ int main(int argc, char* argv[]) {
return 1;
}
- base::FilePath output_path = base::FilePath::FromUTF8Unsafe(argv[3]);
+ base::FilePath output_path = base::FilePath::FromUTF8Unsafe(args[2]);
if (base::WriteFile(output_path, output.c_str(),
static_cast<uint32_t>(output.size())) <= 0) {
LOG(ERROR) << "Failed to write output: " << output_path;
diff --git a/chromium/components/url_formatter/top_domains/top_domain_state_generator.cc b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.cc
index c4e90d350a2..159eeacf5f1 100644
--- a/chromium/components/url_formatter/top_domains/top_domain_state_generator.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.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 "components/url_formatter/top_domains/top_domain_state_generator.h"
+#include "components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.h"
#include <cstdint>
#include <memory>
@@ -15,8 +15,8 @@
#include "net/tools/huffman_trie/trie/trie_bit_buffer.h"
#include "net/tools/huffman_trie/trie/trie_writer.h"
-using net::huffman_trie::HuffmanRepresentationTable;
using net::huffman_trie::HuffmanBuilder;
+using net::huffman_trie::HuffmanRepresentationTable;
using net::huffman_trie::TrieWriter;
namespace url_formatter {
diff --git a/chromium/components/url_formatter/top_domains/top_domain_state_generator.h b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.h
index 4daa56dd85a..7adbd427855 100644
--- a/chromium/components/url_formatter/top_domains/top_domain_state_generator.h
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_state_generator.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 COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
-#define COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
+#ifndef COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
+#define COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
#include <string>
-#include "components/url_formatter/top_domains/trie_entry.h"
+#include "components/url_formatter/spoof_checks/top_domains/trie_entry.h"
namespace url_formatter {
@@ -34,4 +34,4 @@ class TopDomainStateGenerator {
} // namespace url_formatter
-#endif // COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
+#endif // COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP_DOMAIN_STATE_GENERATOR_H_
diff --git a/chromium/components/url_formatter/top_domains/top_domain_util.cc b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util.cc
index 68c7401858c..bb9bead9e6c 100644
--- a/chromium/components/url_formatter/top_domains/top_domain_util.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util.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 "components/url_formatter/top_domains/top_domain_util.h"
+#include "components/url_formatter/spoof_checks/top_domains/top_domain_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
namespace url_formatter {
diff --git a/chromium/components/url_formatter/top_domains/top_domain_util.h b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util.h
index 33818581af8..3f47fd04543 100644
--- a/chromium/components/url_formatter/top_domains/top_domain_util.h
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util.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 COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_UTIL_H_
-#define COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_UTIL_H_
+#ifndef COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP_DOMAIN_UTIL_H_
+#define COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP_DOMAIN_UTIL_H_
#include <string>
@@ -27,4 +27,4 @@ std::string HostnameWithoutRegistry(const std::string& hostname);
} // namespace url_formatter
-#endif // COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TOP_DOMAIN_UTIL_H_
+#endif // COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TOP_DOMAIN_UTIL_H_
diff --git a/chromium/components/url_formatter/top_domains/top_domain_util_unittest.cc b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util_unittest.cc
index 65e2edc126c..5def1d57f4c 100644
--- a/chromium/components/url_formatter/top_domains/top_domain_util_unittest.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domain_util_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 "components/url_formatter/top_domains/top_domain_util.h"
+#include "components/url_formatter/spoof_checks/top_domains/top_domain_util.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/url_formatter/top_domains/top_domains_trie.template b/chromium/components/url_formatter/spoof_checks/top_domains/top_domains_trie.template
index 80dd4c178ce..80dd4c178ce 100644
--- a/chromium/components/url_formatter/top_domains/top_domains_trie.template
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/top_domains_trie.template
diff --git a/chromium/components/url_formatter/top_domains/trie_entry.cc b/chromium/components/url_formatter/spoof_checks/top_domains/trie_entry.cc
index 459d9378b27..13ebcd0b589 100644
--- a/chromium/components/url_formatter/top_domains/trie_entry.cc
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/trie_entry.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 "components/url_formatter/top_domains/trie_entry.h"
+#include "components/url_formatter/spoof_checks/top_domains/trie_entry.h"
#include "base/strings/string_util.h"
#include "net/tools/huffman_trie/trie/trie_bit_buffer.h"
#include "net/tools/huffman_trie/trie/trie_writer.h"
@@ -29,9 +29,11 @@ bool TopDomainTrieEntry::WriteEntry(
net::huffman_trie::TrieBitBuffer* writer) const {
if (entry_->skeleton == entry_->top_domain) {
writer->WriteBit(1);
+ writer->WriteBit(entry_->is_top_500 ? 1 : 0);
return true;
}
writer->WriteBit(0);
+ writer->WriteBit(entry_->is_top_500 ? 1 : 0);
std::string top_domain = entry_->top_domain;
// With the current top 10,000 domains, this optimization reduces the
diff --git a/chromium/components/url_formatter/top_domains/trie_entry.h b/chromium/components/url_formatter/spoof_checks/top_domains/trie_entry.h
index d48fcc4a75a..20b7c1aa28d 100644
--- a/chromium/components/url_formatter/top_domains/trie_entry.h
+++ b/chromium/components/url_formatter/spoof_checks/top_domains/trie_entry.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 COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TRIE_ENTRY_H_
-#define COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TRIE_ENTRY_H_
+#ifndef COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TRIE_ENTRY_H_
+#define COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TRIE_ENTRY_H_
#include <string>
#include <vector>
@@ -18,6 +18,7 @@ namespace top_domains {
struct TopDomainEntry {
std::string skeleton;
std::string top_domain;
+ bool is_top_500;
};
class TopDomainTrieEntry : public net::huffman_trie::TrieEntry {
@@ -44,4 +45,4 @@ using TopDomainEntries = std::vector<std::unique_ptr<TopDomainEntry>>;
} // namespace url_formatter
-#endif // COMPONENTS_URL_FORMATTER_TOP_DOMAINS_TRIE_ENTRY_H_
+#endif // COMPONENTS_URL_FORMATTER_SPOOF_CHECKS_TOP_DOMAINS_TRIE_ENTRY_H_
diff --git a/chromium/components/url_formatter/top_domains/README b/chromium/components/url_formatter/top_domains/README
deleted file mode 100644
index eafbcd2b7ff..00000000000
--- a/chromium/components/url_formatter/top_domains/README
+++ /dev/null
@@ -1,24 +0,0 @@
-* alexa_domains.list
-
- The Alexa top 10k domains, one per line, constructed by running
- make_alexa_top_list.py. Used as an input to make_top_domain_gperf.
- It's derived from
- src/tools/perf/page_sets/alexa1-10000-urls.json with make_alexa_top_list.py
-
-* alexa_domains.skeletons
-
- The checked-in output of make_top_domain_skeletons. Processed during the
- build to generate alexa_domains-trie-inc.cc, which is used by
- url_formatter.cc. This must be regenerated as follows if ICU is updated,
- since skeletons can differ across ICU versions:
-
- $ ninja -C $build_outdir make_top_domain_skeletons
- $ $build_outdir/make_top_domain_skeletons
-
-* test_domains.list
- A list of domains to use in IDNToUnicode test instead of the actual
- top domain list. Manually edited to match what's in IDNToUnicode test.
-
-* test_domains.skeletons
- Generated output of test_domains.list along with alexa_domains.skeletons
- by make_top_domain_skeletons.
diff --git a/chromium/components/url_formatter/top_domains/alexa_domains.list b/chromium/components/url_formatter/top_domains/alexa_domains.list
deleted file mode 100644
index 84581b46bb0..00000000000
--- a/chromium/components/url_formatter/top_domains/alexa_domains.list
+++ /dev/null
@@ -1,9174 +0,0 @@
-facebook.com
-google.com
-youtube.com
-yahoo.com
-baidu.com
-amazon.com
-wikipedia.org
-qq.com
-live.com
-taobao.com
-google.co.in
-twitter.com
-blogspot.com
-linkedin.com
-bing.com
-yandex.ru
-vk.com
-ask.com
-ebay.com
-wordpress.com
-google.de
-msn.com
-tumblr.com
-163.com
-google.com.hk
-mail.ru
-google.co.uk
-hao123.com
-google.com.br
-weibo.com
-xvideos.com
-microsoft.com
-delta-search.com
-google.fr
-conduit.com
-fc2.com
-craigslist.org
-google.ru
-pinterest.com
-instagram.com
-tmall.com
-xhamster.com
-odnoklassniki.ru
-google.it
-sohu.com
-paypal.com
-babylon.com
-google.es
-imdb.com
-apple.com
-amazon.de
-bbc.co.uk
-adobe.com
-soso.com
-pornhub.com
-google.com.mx
-blogger.com
-neobux.com
-amazon.co.uk
-ifeng.com
-google.ca
-avg.com
-go.com
-xnxx.com
-blogspot.in
-alibaba.com
-aol.com
-buildathome.info
-cnn.com
-mywebsearch.com
-ku6.com
-alipay.com
-vube.com
-google.com.tr
-youku.com
-redtube.com
-dailymotion.com
-google.com.au
-adf.ly
-netflix.com
-adcash.com
-about.com
-google.pl
-imgur.com
-ebay.de
-amazon.fr
-flickr.com
-thepiratebay.sx
-youporn.com
-uol.com.br
-huffingtonpost.com
-stackoverflow.com
-jd.com
-t.co
-livejasmin.com
-ebay.co.uk
-yieldmanager.com
-sogou.com
-globo.com
-softonic.com
-cnet.com
-livedoor.com
-directrev.com
-espn.go.com
-indiatimes.com
-wordpress.org
-weather.com
-pixnet.net
-google.com.sa
-clkmon.com
-reddit.com
-amazon.it
-google.com.eg
-booking.com
-google.nl
-douban.com
-slideshare.net
-google.com.ar
-badoo.com
-dailymail.co.uk
-google.co.th
-ask.fm
-wikia.com
-godaddy.com
-xinhuanet.com
-mediafire.com
-deviantart.com
-google.com.pk
-bankofamerica.com
-amazon.es
-blogfa.com
-nytimes.com
-4shared.com
-google.co.id
-youjizz.com
-amazonaws.com
-tube8.com
-kickass.to
-livejournal.com
-snapdo.com
-google.co.za
-vimeo.com
-wigetmedia.com
-yelp.com
-outbrain.com
-dropbox.com
-siteadvisor.com
-foxnews.com
-renren.com
-aliexpress.com
-walmart.com
-skype.com
-ilivid.com
-bizcoaching.info
-wikimedia.org
-flipkart.com
-zedo.com
-searchnu.com
-indeed.com
-leboncoin.fr
-liveinternet.ru
-google.co.ve
-56.com
-google.com.vn
-google.gr
-comcast.net
-torrentz.eu
-etsy.com
-orange.fr
-systweak.com
-onet.pl
-wellsfargo.com
-letv.com
-goodgamestudios.com
-secureserver.net
-allegro.pl
-themeforest.net
-tripadvisor.com
-web.de
-answers.com
-amazon.ca
-mozilla.org
-guardian.co.uk
-stumbleupon.com
-hardsextube.com
-espncricinfo.com
-gmx.net
-photobucket.com
-ehow.com
-rediff.com
-popads.net
-wikihow.com
-search-results.com
-fiverr.com
-google.com.ua
-files.wordpress.com
-onlineaway.net
-nbcnews.com
-google.com.co
-hootsuite.com
-4dsply.com
-google.ro
-sourceforge.net
-cnzz.com
-java.com
-hudong.com
-ucoz.ru
-tudou.com
-addthis.com
-google.com.ng
-soundcloud.com
-onclickads.net
-google.com.ph
-reference.com
-google.be
-wp.pl
-interbiz.me
-beeg.com
-rambler.ru
-sweetim.com
-aweber.com
-google.com.my
-pandora.com
-w3schools.com
-pengyou.com
-archive.org
-qvo6.com
-bet365.com
-etao.com
-lollipop-network.com
-qtrax.com
-google.se
-google.dz
-usatoday.com
-zillow.com
-goal.com
-avito.ru
-kaixin001.com
-yesky.com
-mobile01.com
-soufun.com
-tagged.com
-warriorforum.com
-statcounter.com
-google.com.pe
-libero.it
-thefreedictionary.com
-soku.com
-incredibar.com
-kaskus.co.id
-likes.com
-weebly.com
-iqiyi.com
-pch.com
-samsung.com
-linkbucks.com
-uploaded.net
-bild.de
-google.com.bd
-google.at
-webcrawler.com
-t-online.de
-iminent.com
-google.pt
-detik.com
-ganji.com
-milliyet.com.tr
-bleacherreport.com
-forbes.com
-twoo.com
-olx.in
-mercadolivre.com.br
-hurriyet.com.tr
-pof.com
-wsj.com
-hostgator.com
-naver.com
-putlocker.com
-varzesh3.com
-rutracker.org
-optmd.com
-youm7.com
-google.cl
-ikea.com
-4399.com
-salesforce.com
-scribd.com
-google.com.sg
-it168.com
-goodreads.com
-target.com
-xunlei.com
-hulu.com
-github.com
-hp.com
-buzzfeed.com
-google.ch
-youdao.com
-blogspot.com.es
-so.com
-ups.com
-extratorrent.com
-match.com
-seznam.cz
-naukri.com
-drtuber.com
-spiegel.de
-marca.com
-ign.com
-domaintools.com
-free.fr
-telegraph.co.uk
-mypcbackup.com
-kakaku.com
-imageshack.us
-reuters.com
-ndtv.com
-ig.com.br
-bestbuy.com
-glispa.com
-quikr.com
-deadlyblessing.com
-wix.com
-paipai.com
-ebay.com.au
-yandex.ua
-chinanews.com
-clixsense.com
-nih.gov
-aili.com
-zing.vn
-pchome.net
-webmd.com
-terra.com.br
-pixiv.net
-in.com
-csdn.net
-pcpop.com
-google.co.hu
-lnksr.com
-jobrapido.com
-inbox.com
-dianping.com
-gsmarena.com
-mlb.com
-clicksor.com
-hdfcbank.com
-acesse.com
-homedepot.com
-twitch.tv
-morefreecamsecrets.com
-groupon.com
-lnksdata.com
-google.cz
-usps.com
-xyxy.net
-att.com
-webs.com
-51job.com
-mashable.com
-yihaodian.com
-taringa.net
-fedex.com
-blogspot.co.uk
-ck101.com
-abcnews.go.com
-washingtonpost.com
-narod.ru
-china.com
-doubleclick.com
-cam4.com
-google.ie
-dangdang.com
-americanexpress.com
-disqus.com
-ixxx.com
-39.net
-isohunt.com
-php.net
-exoclick.com
-shutterstock.com
-dell.com
-google.ae
-histats.com
-outlook.com
-wordreference.com
-sahibinden.com
-126.com
-oyodomo.com
-gazeta.pl
-expedia.com
-kijiji.ca
-myfreecams.com
-capitalone.com
-moz.com
-qunar.com
-taleo.net
-google.co.il
-microsoftonline.com
-datasrvrs.com
-zippyshare.com
-google.no
-justdial.com
-2345.com
-adultfriendfinder.com
-shaadi.com
-mobile.de
-abril.com.br
-empowernetwork.com
-icicibank.com
-xe.com
-mailchimp.com
-fbcdn.net
-ccb.com
-huanqiu.com
-seesaa.net
-jimdo.com
-fucked-tube.com
-google.dk
-yellowpages.com
-constantcontact.com
-tinyurl.com
-mysearchresults.com
-friv.com
-ebay.it
-aizhan.com
-accuweather.com
-51buy.com
-snapdeal.com
-google.az
-pogo.com
-adultadworld.com
-nifty.com
-bitauto.com
-drudgereport.com
-bloomberg.com
-vnexpress.net
-eastmoney.com
-verizonwireless.com
-onlinesbi.com
-2ch.net
-speedtest.net
-largeporntube.com
-stackexchange.com
-roblox.com
-miniclip.com
-tmz.com
-google.fi
-ning.com
-monster.com
-mihanblog.com
-steampowered.com
-nuvid.com
-kooora.com
-ebay.in
-mp3skull.com
-blogspot.ru
-duowan.com
-blogspot.de
-fhserve.com
-moneycontrol.com
-pornerbros.com
-eazel.com
-daum.net
-lady8844.com
-rapidgator.net
-thesun.co.uk
-youtube-mp3.org
-v9.com
-disney.go.com
-porntube.com
-surveymonkey.com
-meetup.com
-ero-advertising.com
-bravotube.net
-appround.biz
-blogspot.it
-ctrip.com
-9gag.com
-odesk.com
-kinopoisk.ru
-trulia.com
-mercadolibre.com.ar
-repubblica.it
-hupu.com
-imesh.com
-searchfunmoods.com
-backpage.com
-latimes.com
-news.com.au
-gc.ca
-hubpages.com
-clickbank.com
-mapquest.com
-sweetpacks.com
-hypergames.net
-alimama.com
-cnblogs.com
-vancl.com
-bitly.com
-tokobagus.com
-webmoney.ru
-google.sk
-shopathome.com
-elpais.com
-oneindia.in
-codecanyon.net
-businessinsider.com
-blackhatworld.com
-farsnews.com
-spankwire.com
-mynet.com
-sape.ru
-bhaskar.com
-lenta.ru
-gutefrage.net
-nba.com
-feedly.com
-chaturbate.com
-elmundo.es
-ad6media.fr
-sberbank.ru
-lockyourhome.com
-kinox.to
-subito.it
-rbc.ru
-sfr.fr
-skyrock.com
-priceline.com
-jabong.com
-y8.com
-wunderground.com
-habrahabr.ru
-softpedia.com
-ancestry.com
-bluehost.com
-123rf.com
-lowes.com
-free-tv-video-online.me
-tabelog.com
-vehnix.com
-55bbs.com
-swagbucks.com
-speedanalysis.net
-virgilio.it
-peyvandha.ir
-infusionsoft.com
-newegg.com
-sulekha.com
-myspace.com
-yxlady.com
-haber7.com
-w3.org
-squidoo.com
-hotels.com
-oracle.com
-fatakat.com
-joomla.org
-qidian.com
-adbooth.net
-wretch.cc
-freelancer.com
-typepad.com
-foxsports.com
-allrecipes.com
-searchengines.ru
-babytree.com
-interia.pl
-xhamstercams.com
-verizon.com
-intoday.in
-sears.com
-okcupid.com
-kompas.com
-cj.com
-4tube.com
-chip.de
-force.com
-advertserve.com
-maktoob.com
-24h.com.vn
-foursquare.com
-cbsnews.com
-pornhublive.com
-xda-developers.com
-milanuncios.com
-retailmenot.com
-keezmovies.com
-nydailynews.com
-h2porn.com
-careerbuilder.com
-xing.com
-citibank.com
-linkwithin.com
-singlessalad.com
-altervista.org
-turbobit.net
-zoosk.com
-digg.com
-hespress.com
-bigpoint.com
-yourlust.com
-myntra.com
-issuu.com
-macys.com
-google.bg
-github.io
-filestube.com
-cmbchina.com
-irctc.co.in
-filehippo.com
-mop.com
-bodybuilding.com
-paidui.com
-zimbio.com
-panet.co.il
-mgid.com
-ya.ru
-probux.com
-haberturk.com
-persianblog.ir
-meituan.com
-mercadolibre.com.mx
-ppstream.com
-sunporno.com
-vodly.to
-forgeofempires.com
-elance.com
-adscale.de
-vipshop.com
-babycenter.com
-istockphoto.com
-commentcamarche.net
-upworthy.com
-download.com
-battle.net
-beva.com
-list-manage.com
-corriere.it
-noticias24.com
-ucoz.com
-porn.com
-google.lk
-lifehacker.com
-today.com
-chinabyte.com
-southwest.com
-ca.gov
-nudevista.com
-yandex.com.tr
-people.com
-docin.com
-norton.com
-perfectgirls.net
-engadget.com
-realtor.com
-techcrunch.com
-time.com
-indianrail.gov.in
-dtiblog.com
-way2sms.com
-foodnetwork.com
-subscene.com
-worldstarhiphop.com
-tabnak.ir
-aeriagames.com
-leagueoflegends.com
-51.la
-facenama.com
-sapo.pt
-bitshare.com
-gamespot.com
-cy-pr.com
-kankan.com
-google.co.nz
-liveleak.com
-video-one.com
-marktplaats.nl
-elwatannews.com
-roulettebotplus.com
-adserverplus.com
-akhbarak.net
-gumtree.com
-weheartit.com
-openadserving.com
-sporx.com
-mercadolibre.com.ve
-zendesk.com
-houzz.com
-asos.com
-letitbit.net
-quora.com
-yandex.kz
-mcafee.com
-ensonhaber.com
-gamefaqs.com
-vk.me
-avast.com
-website-unavailable.com
-22find.com
-admagnet.net
-rottentomatoes.com
-google.com.kw
-cloob.com
-nokia.com
-wetter.com
-taboola.com
-tenpay.com
-888.com
-flipora.com
-adhitprofits.com
-timeanddate.com
-as.com
-fanpop.com
-informer.com
-over-blog.com
-itau.com.br
-balagana.net
-ellechina.com
-avazutracking.net
-gap.com
-examiner.com
-vporn.com
-lenovo.com
-eonline.com
-r7.com
-majesticseo.com
-immobilienscout24.de
-google.kz
-goo.gl
-zwaar.net
-bankmellat.ir
-alphaporno.com
-whitepages.com
-viva.co.id
-rutor.org
-wiktionary.org
-intuit.com
-gismeteo.ru
-dantri.com.vn
-xbox.com
-myegy.com
-xtube.com
-masrawy.com
-urbandictionary.com
-agoda.com
-ebay.fr
-kickstarter.com
-6park.com
-metacafe.com
-yamahaonlinestore.com
-anysex.com
-azlyrics.com
-rt.com
-ibm.com
-nordstrom.com
-ezinearticles.com
-cnbc.com
-redtubelive.com
-clicksvenue.com
-tradus.com
-m2newmedia.com
-custhelp.com
-4chan.org
-kioskea.net
-yoka.com
-7k7k.com
-opensiteexplorer.org
-musica.com
-coupons.com
-cracked.com
-caixa.gov.br
-skysports.com
-kizi.com
-getresponse.com
-sky.com
-marketwatch.com
-google.com.ec
-cbslocal.com
-zhihu.com
-888poker.com
-digitalpoint.com
-blog.163.com
-rantsports.com
-videosexarchive.com
-who.is
-gogetlinks.net
-idnes.cz
-king.com
-say-move.org
-motherless.com
-npr.org
-legacy.com
-aljazeera.net
-barnesandnoble.com
-overstock.com
-drom.ru
-weather.gov
-gstatic.com
-amung.us
-traidnt.net
-ovh.net
-rtl.de
-howstuffworks.com
-digikala.com
-bannersbroker.com
-kohls.com
-google.com.do
-dealfish.co.th
-19lou.com
-ezpowerads.com
-lemonde.fr
-chexun.com
-imagebam.com
-viooz.co
-prothom-alo.com
-360doc.com
-m-w.com
-fanfiction.net
-semrush.com
-ci123.com
-plugrush.com
-cafemom.com
-mangareader.net
-haizhangs.com
-cdiscount.com
-zappos.com
-manta.com
-novinky.cz
-hi5.com
-pr-cy.ru
-movie4k.to
-patch.com
-alarabiya.net
-indiamart.com
-cartrailor.com
-almasryalyoum.com
-315che.com
-google.by
-tomshardware.com
-minecraft.net
-gulfup.com
-rr.com
-spotify.com
-airtel.in
-espnfc.com
-sanook.com
-ria.ru
-google.com.qa
-jquery.com
-pinshan.com
-onlylady.com
-pornoxo.com
-cookpad.com
-pagesjaunes.fr
-usmagazine.com
-google.lt
-nu.nl
-hm.com
-fixya.com
-theblaze.com
-cbssports.com
-eyny.com
-17173.com
-hc360.com
-cbs.com
-telegraaf.nl
-netlog.com
-slickdeals.net
-yobt.com
-certified-toolbar.com
-miercn.com
-aparat.com
-billdesk.com
-yandex.by
-888casino.com
-twitpic.com
-google.hr
-tubegalore.com
-dhgate.com
-makemytrip.com
-shop.com
-nike.com
-kayak.com
-fandango.com
-tutsplus.com
-gotomeeting.com
-shareasale.com
-mpnrs.com
-keepvid.com
-lequipe.fr
-namecheap.com
-doublepimp.com
-softigloo.com
-givemesport.com
-mtime.com
-letras.mus.br
-pole-emploi.fr
-biblegateway.com
-independent.co.uk
-e-hentai.org
-gumtree.com.au
-livestrong.com
-game321.com
-comcast.com
-clubpenguin.com
-rightmove.co.uk
-steamcommunity.com
-sockshare.com
-globalconsumersurvey.com
-rapidshare.com
-auto.ru
-staples.com
-anitube.se
-rozblog.com
-reliancenetconnect.co.in
-credit-agricole.fr
-exposedwebcams.com
-webalta.ru
-usbank.com
-google.com.ly
-pantip.com
-aftonbladet.se
-scoop.it
-mayoclinic.com
-evernote.com
-nyaa.eu
-livingsocial.com
-noaa.gov
-imagefap.com
-abchina.com
-google.rs
-amazon.in
-tnaflix.com
-xici.net
-united.com
-templatemonster.com
-deezer.com
-pixlr.com
-tradedoubler.com
-gumtree.co.za
-r10.net
-kongregate.com
-jeuxvideo.com
-gawker.com
-chewen.com
-r2games.com
-mayajo.com
-topix.com
-easyhits4u.com
-netteller.com
-ing.nl
-tripadvisor.co.uk
-udn.com
-cheezburger.com
-fotostrana.ru
-bbc.com
-behance.net
-lefigaro.fr
-nikkei.com
-fidelity.com
-baomihua.com
-fool.com
-nairaland.com
-sendspace.com
-woot.com
-travelocity.com
-shopclues.com
-sureonlinefind.com
-gizmodo.com
-hidemyass.com
-o2.pl
-clickbank.net
-fotolia.com
-opera.com
-sabah.com.tr
-n-mobile.net
-chacha.com
-autotrader.com
-anonym.to
-walmart.com.br
-yjc.ir
-autoscout24.de
-gobookee.net
-yaolan.com
-india.com
-tribalfusion.com
-gittigidiyor.com
-otto.de
-adclickxpress.com
-made-in-china.com
-ahram.org.eg
-asriran.com
-blackberry.com
-beytoote.com
-piriform.com
-ilmeteo.it
-att.net
-brainyquote.com
-last.fm
-directadvert.ru
-slate.com
-mangahere.com
-jalan.net
-blog.com
-tuvaro.com
-doc88.com
-mbc.net
-europa.eu
-onlinedown.net
-jcpenney.com
-myplaycity.com
-bahn.de
-laredoute.fr
-alexa.com
-flashx.tv
-51.com
-mail.com
-costco.com
-mirror.co.uk
-hubspot.com
-tf1.fr
-merdeka.com
-nypost.com
-1mall.com
-wmtransfer.com
-pcmag.com
-univision.com
-nationalgeographic.com
-sourtimes.org
-iciba.com
-petardas.com
-wmmail.ru
-light-dark.net
-ultimate-guitar.com
-koramgame.com
-megavod.fr
-smh.com.au
-ticketmaster.com
-admin5.com
-get-a-fuck-tonight.com
-eenadu.net
-argos.co.uk
-nipic.com
-google.iq
-alhea.com
-citrixonline.com
-girlsgogames.com
-fanatik.com.tr
-google.tn
-usaa.com
-earthlink.net
-ryanair.com
-city-data.com
-lloydstsb.co.uk
-pornsharia.com
-baixing.com
-all-free-download.com
-qianyan001.com
-hellporno.com
-pornmd.com
-conferenceplus.com
-docstoc.com
-christian-dogma.com
-dmoz.org
-perezhilton.com
-mega.co.nz
-zazzle.com
-echoroukonline.com
-ea.com
-yiqifa.com
-mysearchdial.com
-hotwire.com
-ninemsn.com.au
-tablica.pl
-brazzers.com
-americanas.com.br
-extremetube.com
-zynga.com
-buscape.com.br
-t-mobile.com
-portaldosites.com
-businessweek.com
-feedburner.com
-contenko.com
-homeshop18.com
-bmi.ir
-wwe.com
-adult-empire.com
-nfl.com
-globososo.com
-sfgate.com
-mmotraffic.com
-zalando.de
-warthunder.com
-icloud.com
-xiami.com
-newsmax.com
-solarmovie.so
-junglee.com
-discovercard.com
-hh.ru
-searchengineland.com
-labanquepostale.fr
-51cto.com
-fling.com
-liveperson.net
-sulit.com.ph
-tinypic.com
-meilishuo.com
-googleadservices.com
-boston.com
-chron.com
-breitbart.com
-youjizzlive.com
-commbank.com.au
-axisbank.com
-wired.com
-trialpay.com
-berniaga.com
-cnmo.com
-tunein.com
-hotfile.com
-dubizzle.com
-olx.com.br
-haxiu.com
-zulily.com
-infolinks.com
-yourgirlfriends.com
-logmein.com
-irs.gov
-noticiadeldia.com
-nbcsports.com
-holasearch.com
-indianexpress.com
-depositfiles.com
-elfagr.org
-himado.in
-lumosity.com
-mbank.com.pl
-primewire.ag
-dreamstime.com
-sootoo.com
-souq.com
-craigslist.ca
-zara.com
-groupon.it
-mangafox.me
-casino.com
-armorgames.com
-zanox.com
-finn.no
-qihoo.com
-toysrus.com
-airasia.com
-dafont.com
-tvmuse.eu
-pnc.com
-donanimhaber.com
-cnbeta.com
-prntscr.com
-cox.net
-bloglovin.com
-picmonkey.com
-zoho.com
-glassdoor.com
-myfitnesspal.com
-change.org
-aa.com
-playstation.com
-b1.org
-correios.com.br
-hindustantimes.com
-softlayer.com
-imagevenue.com
-windowsphone.com
-wikimapia.org
-transfermarkt.de
-dict.cc
-blocket.se
-lacaixa.es
-hilton.com
-mtv.com
-cbc.ca
-msn.ca
-box.com
-szn.cz
-haodf.com
-monsterindia.com
-okezone.com
-entertainment-factory.com
-linternaute.com
-break.com
-ustream.tv
-songspk.name
-bilibili.tv
-avira.com
-thehindu.com
-watchmygf.com
-google.co.ma
-nick.com
-sp.gov.br
-zeobit.com
-sprint.com
-khabaronline.ir
-magentocommerce.com
-hsbc.co.uk
-trafficholder.com
-gamestop.com
-cartoonnetwork.com
-fifa.com
-ebay.ca
-vatanim.com.tr
-qvc.com
-marriott.com
-eventbrite.com
-gi-akademie.com
-intel.com
-oschina.net
-dojki.com
-thechive.com
-viadeo.com
-walgreens.com
-leo.org
-statscrop.com
-brothersoft.com
-allocine.fr
-slutload.com
-google.com.gt
-santabanta.com
-stardoll.com
-polyvore.com
-focus.de
-duckduckgo.com
-funshion.com
-marieclairechina.com
-internethaber.com
-worldoftanks.ru
-1und1.de
-anyporn.com
-cars.com
-asg.to
-alice.it
-hongkiat.com
-bhphotovideo.com
-bdnews24.com
-sdo.com
-cerdas.com
-clarin.com
-victoriassecret.com
-instructables.com
-state.gov
-agame.com
-xiaomi.com
-adfoc.us
-telekom.com
-skycn.com
-orbitz.com
-nhl.com
-vistaprint.com
-trklnks.com
-basecamp.com
-hot-sex-tube.com
-incredibar-search.com
-qingdaonews.com
-sabq.org
-nasa.gov
-dx.com
-addmefast.com
-yepi.com
-xxx-ok.com
-sex.com
-food.com
-freeones.com
-tesco.com
-a10.com
-abc.net.au
-internetdownloadmanager.com
-seowhy.com
-otomoto.pl
-idealo.de
-laposte.net
-eroprofile.com
-bbb.org
-tiu.ru
-blogsky.com
-bigfishgames.com
-weiphone.com
-livescore.com
-tubepleasure.com
-jagran.com
-livestream.com
-stagram.com
-vine.co
-olx.com.pk
-edmunds.com
-banglanews24.com
-reverso.net
-stargames.at
-postimg.org
-overthumbs.com
-iteye.com
-yify-torrents.com
-forexfactory.com
-hefei.cc
-thefreecamsecret.com
-lanacion.com.ar
-jeu-a-telecharger.com
-spartoo.com
-adv-adserver.com
-asus.com
-91.com
-wimbledon.com
-yam.com
-grooveshark.com
-tdcanadatrust.com
-lovetime.com
-iltalehti.fi
-alnaddy.com
-bb.com.br
-tebyan.net
-redbox.com
-filecrop.com
-aliyun.com
-21cn.com
-news24.com
-infowars.com
-thetaoofbadass.com
-juegos.com
-p5w.net
-vg.no
-discovery.com
-gazzetta.it
-tvguide.com
-khabarfarsi.com
-bradesco.com.br
-autotrader.co.uk
-wetransfer.com
-jinti.com
-xhamsterhq.com
-appround.net
-lotour.com
-reverbnation.com
-thedailybeast.com
-vente-privee.com
-subscribe.ru
-marketgid.com
-super.cz
-jvzoo.com
-shine.com
-screencast.com
-picofile.com
-manoramaonline.com
-kbb.com
-seasonvar.ru
-android.com
-egrana.com.br
-ettoday.net
-webstatsdomain.net
-haberler.com
-vesti.ru
-fastpic.ru
-dpreview.com
-google.si
-ouedkniss.com
-crackle.com
-chefkoch.de
-mogujie.com
-brassring.com
-govome.com
-copyscape.com
-minecraftforum.net
-mit.edu
-cvs.com
-timesjobs.com
-ksl.com
-verizon.net
-direct.gov.uk
-miralinks.ru
-elheddaf.com
-stockphoto9.com
-ashemaletube.com
-dmm.com
-abckj123.com
-smzdm.com
-cox.com
-welt.de
-guyspy.com
-makeuseof.com
-tiscali.it
-178.com
-metrolyrics.com
-vsuch.com
-seosprint.net
-samanyoluhaber.com
-garanti.com.tr
-chicagotribune.com
-hinet.net
-kp.ru
-chomikuj.pl
-nk.pl
-webhostingtalk.com
-dnaindia.com
-programme-tv.net
-ievbz.com
-mysql.com
-perfectmoney.is
-liveundnackt.com
-flippa.com
-vevo.com
-jappy.de
-bidvertiser.com
-bankmandiri.co.id
-letour.fr
-yr.no
-suning.com
-nosub.tv
-delicious.com
-pornpoly.com
-echo.msk.ru
-coingeneration.com
-shutterfly.com
-royalbank.com
-techradar.com
-114la.com
-bizrate.com
-srvey.net
-heavy-r.com
-telexfree.com
-lego.com
-battlefield.com
-shahrekhabar.com
-tuenti.com
-bookmyshow.com
-ft.com
-prweb.com
-1337x.org
-networkedblogs.com
-pbskids.org
-aipai.com
-jang.com.pk
-dribbble.com
-ezdownloadpro.info
-gonzoxxxmovies.com
-aufeminin.com
-6pm.com
-azet.sk
-trustedoffer.com
-simplyhired.com
-adserverpub.com
-privalia.com
-bedbathandbeyond.com
-yyets.com
-verycd.com
-sbnation.com
-blogspot.nl
-ikariam.com
-sitepoint.com
-gazeta.ru
-tataindicom.com
-chekb.com
-literotica.com
-ah-me.com
-eztv.it
-onliner.by
-pptv.com
-macrumors.com
-xvideo-jp.com
-state.tx.us
-jamnews.ir
-etoro.com
-ny.gov
-searchenginewatch.com
-google.co.cr
-td.com
-ahrefs.com
-337.com
-klout.com
-ebay.es
-theverge.com
-kapook.com
-barclays.co.uk
-nuomi.com
-index-of-mp3s.com
-ohfreesex.com
-mts.ru
-instantcheckmate.com
-sport.es
-sitescout.com
-irr.ru
-tuniu.com
-startimes.com
-tvn24.pl
-kenh14.vn
-myvideo.de
-speedbit.com
-aljazeera.com
-pudelek.pl
-mmgp.ru
-empflix.com
-tigerdirect.com
-elegantthemes.com
-ted.com
-down1oads.com
-bancobrasil.com.br
-qip.ru
-fapdu.com
-softango.com
-ap.org
-meteofrance.com
-gentenocturna.com
-2ch-c.net
-orf.at
-maybank2u.com.my
-minecraftwiki.net
-tv.com
-orkut.com
-adp.com
-woorank.com
-imagetwist.com
-pastebin.com
-airtel.com
-ew.com
-forever21.com
-adam4adam.com
-voyages-sncf.com
-nextag.com
-usnews.com
-dinamalar.com
-virginmedia.com
-investopedia.com
-seekingalpha.com
-jumponhottie.com
-national-lottery.co.uk
-mobifiesta.com
-kapanlagi.com
-segundamano.es
-gfan.com
-xdating.com
-ynet.com
-medu.ir
-hsn.com
-newsru.com
-minus.com
-sitetalk.com
-aarp.org
-clickpaid.com
-panoramio.com
-webcamo.com
-yobt.tv
-slutfinder.com
-freelotto.com
-mudah.my
-toptenreviews.com
-caisse-epargne.fr
-wimp.com
-woothemes.com
-css-tricks.com
-coolmath-games.com
-tagu.com.ar
-sheknows.com
-advancedfileoptimizer.com
-drupal.org
-centrum.cz
-charter.net
-adxhosting.net
-squarespace.com
-trademe.co.nz
-sitesell.com
-birthrecods.com
-megashare.info
-freepornvs.com
-isna.ir
-ziddu.com
-airtelforum.com
-justin.tv
-01net.com
-ed.gov
-no-ip.com
-nikkansports.com
-smashingmagazine.com
-salon.com
-nmisr.com
-wanggou.com
-bayt.com
-codeproject.com
-downloadha.com
-local.com
-abola.pt
-delta-homes.com
-filmweb.pl
-gov.uk
-worldoftanks.eu
-ads-id.com
-sergey-mavrodi.com
-pornoid.com
-freakshare.com
-51fanli.com
-bankrate.com
-grindtv.com
-webmasterworld.com
-torrentz.in
-bwin.com
-watchtower.com
-payza.com
-anz.com
-vagalume.com.br
-ozon.ru
-tonicmovies.com
-arbeitsagentur.de
-graphicriver.net
-theweathernetwork.com
-samsclub.com
-tribunnews.com
-soldonsmart.com
-tut.by
-voila.fr
-doctissimo.fr
-sueddeutsche.de
-mamba.ru
-kmart.com
-abc.es
-manager.co.th
-spokeo.com
-apache.org
-tdbank.com
-asklaila.com
-admin5.net
-rtve.es
-ynet.co.il
-infospace.com
-yimg.com
-torcache.net
-zap2it.com
-smallseotools.com
-privatbank.ua
-nnm-club.ru
-payoneer.com
-bidorbuy.co.za
-islamweb.net
-juicyads.com
-vid2c.com
-dnsrsearch.com
-the-bux.net
-yaplakal.com
-ex.ua
-mtsindia.in
-reclameaqui.com.br
-postbank.de
-gogvo.com
-bearshare.net
-socialsex.com
-yebhi.com
-mktmobi.com
-dfiles.eu
-citibank.co.in
-gamersky.com
-kotaku.com
-teamviewer.com
-kwejk.pl
-hamariweb.com
-tom.com
-gayromeo.com
-sony.com
-westpac.com.au
-gtmetrix.com
-shorouknews.com
-xl.pt
-networksolutions.com
-500px.com
-ypmate.com
-indowebster.com
-sports.ru
-netshoes.com.br
-dfiles.ru
-cpasbien.me
-webgame.web.id
-tuto4pc.com
-poponclick.com
-complex.com
-sakshi.com
-infobae.com
-sify.com
-4pda.ru
-starsue.net
-newgrounds.com
-mehrnews.com
-depositphotos.com
-keek.com
-indeed.co.in
-stanford.edu
-hepsiburada.com
-20minutos.es
-paper.li
-prizee.com
-xlovecam.com
-criteo.com
-endlessmatches.com
-dyndns.org
-lightinthebox.com
-easyjet.com
-vice.com
-tiexue.net
-monstermarketplace.com
-mojang.com
-cams.com
-pingdom.com
-askmen.com
-list-manage1.com
-express.com.pk
-priceminister.com
-duba.com
-meinestadt.de
-mediatakeout.com
-terere.info
-streamate.com
-garmin.com
-a-telecharger.com
-vipzona.info
-coffetube.com
-discuz.net
-directv.com
-foreningssparbanken.se
-fatwallet.com
-mackolik.com
-megacinema.fr
-chess.com
-suntrust.com
-investing.com
-whois.com
-dummies.com
-yinyuetai.com
-mihandownload.com
-freapp.com
-theage.com.au
-audible.com
-hotelurbano.com.br
-vatgia.com
-wizard101.com
-ceneo.pl
-1ting.com
-meetic.fr
-cardekho.com
-tripadvisor.it
-dhl.com
-aibang.com
-asp.net
-toing.com.br
-zhubajie.com
-telecomitalia.it
-claro-search.com
-nickjr.com
-iconfinder.com
-mobile9.com
-cisco.com
-cpanel.net
-indiegogo.com
-egotastic.com
-hforcare.com
-pbs.org
-realestate.com.au
-abv.bg
-drugs.com
-bt.com
-wildberries.ru
-edreams.it
-statigr.am
-prestashop.com
-adxite.com
-birthdaypeoms.com
-exbii.com
-blogmura.com
-sciencedirect.com
-sanspo.com
-nextmedia.com
-tvoyauda4a.ru
-tangdou.com
-blackboard.com
-qiyou.com
-prezentacya.ru
-clicrbs.com.br
-wayfair.com
-xvideos-field.com
-national.com.au
-friendfeed.com
-plurk.com
-lolmake.com
-b9dm.com
-afkarnews.ir
-dhl.de
-championat.com
-moviefone.com
-popcash.net
-cliphunter.com
-sharebeast.com
-wowhead.com
-firstpost.com
-lloydstsb.com
-fazenda.gov.br
-lonelyplanet.com
-freenet.de
-justanswer.com
-qiwi.com
-shufuni.com
-drive2.ru
-slando.ua
-caribbeancom.com
-uniblue.com
-real.com
-addictinggames.com
-wnd.com
-col3negoriginal.org
-loltrk.com
-videodownloadconverter.com
-google.lv
-seriesyonkis.com
-ryushare.com
-s1979.com
-cheapoair.com
-submarino.com.br
-topface.com
-hotelscombined.com
-whatismyipaddress.com
-z6.com
-sozcu.com.tr
-sonymobile.com
-planetminecraft.com
-optimum.net
-google.com.pr
-mthai.com
-onlinecreditcenter6.com
-tharunaya.co.uk
-sfimg.com
-natwest.com
-zergnet.com
-alotporn.com
-urbanspoon.com
-punishtube.com
-proboards.com
-betfair.com
-iltasanomat.fi
-ssisurveys.com
-harvard.edu
-blic.rs
-clicksia.com
-skillpages.com
-mobilewap.com
-fiducia.de
-torntvz.org
-leparisien.fr
-anjuke.com
-rabobank.nl
-sport.pl
-schwab.com
-buenastareas.com
-befuck.com
-smart-search.com
-ivi.ru
-dvdvideosoft.com
-ubi.com
-makepolo.com
-1and1.com
-pcworld.com
-caf.fr
-fnb.co.za
-vanguardngr.com
-floozycity.com
-ubuntu.com
-my-link.pro
-centurylink.com
-slashdot.org
-mirrorcreator.com
-rutube.ru
-tubeplus.me
-kicker.de
-unibet.com
-pornyaz.com
-learntotradethemarket.com
-tokyo-porn-tube.com
-luvcow.com
-i.ua
-ole.com.ar
-redfin.com
-cnki.net
-2shared.com
-infibeam.com
-zdnet.com
-fishki.net
-ukr.net
-jiameng.com
-utorrent.com
-elkhabar.com
-anime44.com
-societegenerale.fr
-livememe.com
-startertv.fr
-pingomatic.com
-indeed.co.uk
-dpstream.net
-mundodeportivo.com
-gravatar.com
-ip138.com
-yandex.net
-barbie.com
-wattpad.com
-dzwww.com
-technorati.com
-meishichina.com
-russianpost.ru
-kboing.com.br
-lzjl.com
-newsnow.co.uk
-dw.de
-inetglobal.com
-tripadvisor.in
-ashleyrnadison.com
-rapgenius.com
-xuite.net
-nowvideo.eu
-search.us.com
-usagc.org
-santander.co.uk
-99acres.com
-bigcartel.com
-haivl.com
-jsfiddle.net
-io9.com
-lg.com
-veoh.com
-dafiti.com.br
-heise.de
-wikispaces.com
-google.com.bo
-skyscrapercity.com
-zaobao.com
-pirateproxy.net
-muyzorras.com
-entrepreneur.com
-sxc.hu
-superuser.com
-jb51.net
-bitsnoop.com
-index.hu
-tubexclips.com
-symantec.com
-sedo.com
-gongchang.com
-newsmth.net
-srclick.ru
-bomnegocio.com
-omegle.com
-sweetpacks-search.com
-000webhost.com
-rencontreshard.com
-jumei.com
-acfun.tv
-celebuzz.com
-el-balad.com
-wajam.com
-zoopla.co.uk
-sc4888.com
-mobileaziende.it
-officialsurvey.org
-googleapis.com
-jobsdb.com
-google.com.sv
-freejobalert.com
-walla.co.il
-hollywoodreporter.com
-inc.com
-bbandt.com
-williamhill.com
-jeu.info
-vrbo.com
-arabseed.com
-spielaffe.de
-wykop.pl
-name.com
-web-opinions.com
-ehowenespanol.com
-uuzu.com
-cafepress.com
-beeline.ru
-searchenginejournal.com
-webex.com
-zerohedge.com
-cityads.ru
-columbia.edu
-jia.com
-tistory.com
-100bestbuy.com
-realitykings.com
-shopify.com
-gametop.com
-eharmony.com
-ngoisao.net
-angieslist.com
-grotal.com
-manhunt.net
-adslgate.com
-demotywatory.pl
-enfemenino.com
-yallakora.com
-careesma.in
-draugiem.lv
-greatandhra.com
-lifescript.com
-androidcentral.com
-wiley.com
-alot.com
-10010.com
-next.co.uk
-115.com
-omgpm.com
-mycalendarbook.com
-playxn.com
-niksalehi.com
-serviporno.com
-poste.it
-kimiss.com
-bearshare.com
-clickpoint.com
-seek.com.au
-bab.la
-ads8.com
-viewster.com
-ideacellular.com
-tympanus.net
-wwwblogto.com
-tblop.com
-elong.com
-funnyordie.com
-radikal.ru
-rk.com
-alarab.net
-willhaben.at
-beyond.com
-punchng.com
-viglink.com
-microsoftstore.com
-tripleclicks.com
-m1905.com
-ofreegames.com
-s2d6.com
-360buy.com
-rakuten.com
-evite.com
-kompasiana.com
-dailycaller.com
-holidaycheck.de
-imvu.com
-nate.com
-fnac.com
-htc.com
-savenkeep.com
-alfabank.ru
-zaycev.net
-vidtomp3.com
-eluniversal.com.mx
-theatlantic.com
-gamigo.de
-lolking.net
-wer-kennt-wen.de
-stern.de
-sport1.de
-goalunited.org
-discogs.com
-whirlpool.net.au
-savefrom.net
-eurosport.fr
-juegosjuegos.com
-open24news.tv
-sinaapp.com
-fuq.com
-index.hr
-realpopbid.com
-rollingstone.com
-globaltestmarket.com
-seopult.ru
-wumii.com
-ford.com
-cabelas.com
-securepaynet.net
-zhibo8.cc
-jiji.com
-gezinti.com
-meb.gov.tr
-classifiedads.com
-kitco.com
-incredimail.com
-esmas.com
-soccerway.com
-rivals.com
-prezi.com
-shopping.com
-superjob.ru
-chinaacc.com
-amoureux.com
-mysmartprice.com
-eleconomista.es
-mercola.com
-imlive.com
-teacup.com
-modelmayhem.com
-nic.ru
-brazzersnetwork.com
-everything.org.uk
-bhg.com
-longhoo.net
-superpages.com
-tny.cz
-yourfilezone.com
-tuan800.com
-streev.com
-sedty.com
-boxofficemojo.com
-hollyscoop.com
-safecart.com
-almogaz.com
-cashnhits.com
-wetplace.com
-freepik.com
-rarbg.com
-xxxbunker.com
-prchecker.info
-halifax-online.co.uk
-trafficfactory.biz
-telecinco.es
-searchtermresults.com
-unam.mx
-akhbar-elwatan.com
-lynda.com
-yougetlaid.com
-smart.com.au
-advfn.com
-unicredit.it
-zomato.com
-flirt.com
-netease.com
-bnpparibas.net
-elcomercio.pe
-mathrubhumi.com
-koyotesoft.com
-filmix.net
-xnxxhdtube.com
-ennaharonline.com
-junbi-tracker.com
-buzzdock.com
-emirates.com
-vivanuncios.com.mx
-infojobs.net
-smi2.ru
-lotterypost.com
-bandcamp.com
-ekstrabladet.dk
-nownews.com
-bc.vc
-google.com.af
-ulmart.ru
-estadao.com.br
-politico.com
-kl688.com
-resellerclub.com
-whois.net
-seobuilding.ru
-t411.me
-googlesyndication.com
-delfi.lt
-eqla3.com
-ali213.net
-fanpage.it
-uptobox.com
-google.jo
-cncn.com
-sme.sk
-kinozal.tv
-ceconline.com
-billboard.com
-citi.com
-naughtyamerica.com
-classmates.com
-coursera.org
-pingan.com
-voanews.com
-tankionline.com
-jetblue.com
-spainshtranslation.com
-ebookbrowse.com
-met-art.com
-megafon.ru
-quibids.com
-smartfren.com
-cleartrip.com
-pixmania.com
-vivastreet.com
-thegfnetwork.com
-paytm.com
-meinsextagebuch.net
-memecenter.com
-ixbt.com
-dagbladet.no
-basecamphq.com
-chinatimes.com
-bubblews.com
-xtool.ru
-opodo.co.uk
-hattrick.org
-zopim.com
-aol.co.uk
-gazzetta.gr
-18andabused.com
-mcssl.com
-economist.com
-zeit.de
-google.com.uy
-pinoy-ako.info
-lazada.co.id
-filgoal.com
-rozetka.com.ua
-almesryoon.com
-csmonitor.com
-bizjournals.com
-rackspace.com
-webgozar.com
-opencart.com
-mediaplex.com
-deutsche-bank.de
-similarsites.com
-sotmarket.ru
-chatzum.com
-huffingtonpost.co.uk
-carwale.com
-memez.com
-hostmonster.com
-muzofon.com
-elephanttube.com
-crunchbase.com
-imhonet.ru
-lusongsong.com
-filmesonlinegratis.net
-giaoduc.net.vn
-manhub.com
-tatadocomo.com
-realitatea.net
-freemp3x.com
-freemail.hu
-ganool.com
-feedreader.com
-sportsdirect.com
-videolan.org
-watchseries.lt
-rotapost.ru
-nwolb.com
-searchquotes.com
-kaspersky.com
-go2cloud.org
-grepolis.com
-profit-partner.ru
-articlesbase.com
-dns-shop.ru
-radikal.com.tr
-justjared.com
-lancenet.com.br
-mangapanda.com
-theglobeandmail.com
-ecollege.com
-myanimelist.net
-fotomac.com.tr
-imanhua.com
-travelzoo.com
-jjwxc.net
-q.gs
-naaptol.com
-sambaporno.com
-macrojuegos.com
-ooo-sex.com
-fab.com
-roflzone.com
-searchcompletion.com
-jezebel.com
-bizdec.ru
-torrentino.com
-multitran.ru
-tune-up.com
-sparkpeople.com
-desi-tashan.com
-mashreghnews.ir
-talktalk.co.uk
-hinkhoj.com
-20minutes.fr
-sulia.com
-icims.com
-dizi-mag.com
-webaslan.com
-en.wordpress.com
-funmoods.com
-softgozar.com
-starwoodhotels.com
-studiopress.com
-click.in
-meetcheap.com
-angel-live.com
-beforeitsnews.com
-trello.com
-icontact.com
-prlog.org
-incentria.com
-bouyguestelecom.fr
-dstv.com
-arstechnica.com
-diigo.com
-consumers-research.com
-metaffiliation.com
-telekom.de
-izlesene.com
-newsit.gr
-fuckingawesome.com
-osym.gov.tr
-svyaznoy.ru
-watchfreemovies.ch
-gumtree.pl
-sportbox.ru
-reserverunessai.com
-hsbc.com.hk
-cricbuzz.com
-djelfa.info
-nouvelobs.com
-aruba.it
-homes.com
-allezleslions.com
-orkut.com.br
-aionfreetoplay.com
-academia.edu
-consumerreports.org
-ilsole24ore.com
-sephora.com
-lds.org
-vmall.com
-ultimasnoticias.com.ve
-healthgrades.com
-imgbox.com
-dlsite.com
-whitesmoke.com
-thenextweb.com
-qire123.com
-peeplo.com
-chitika.com
-alwafd.org
-phonearena.com
-ovh.com
-tusfiles.net
-18schoolgirlz.com
-bongacams.com
-home.pl
-footmercato.net
-sprashivai.ru
-megafilmeshd.net
-premium-display.com
-clickey.com
-tokyo-tube.com
-watch32.com
-pornolab.net
-timewarnercable.com
-naturalnews.com
-afimet.com
-telderi.ru
-ioffer.com
-lapatilla.com
-livetv.ru
-cloudflare.com
-lupoporno.com
-nhaccuatui.com
-thepostgame.com
-ipage.com
-banesconline.com
-cdc.gov
-adonweb.ru
-zone-telechargement.com
-intellicast.com
-uloz.to
-pikabu.ru
-megogo.net
-wenxuecity.com
-xml-sitemaps.com
-webdunia.com
-justhost.com
-starbucks.com
-wargaming.net
-hugedomains.com
-magicbricks.com
-gigporno.com
-rikunabi.com
-51auto.com
-warriorplus.com
-gudvin.tv
-bigmir.net
-ansa.it
-standardbank.co.za
-toshiba.com
-xinnet.com
-geico.com
-funnyjunk.com
-affaritaliani.it
-cityheaven.net
-tubewolf.com
-google.org
-ad.nl
-tutorialspoint.com
-uidai.gov.in
-everydayhealth.com
-jzip.com
-lolspotsarticles.com
-rueducommerce.fr
-lvmama.com
-roboform.com
-zoznam.sk
-livesmi.com
-die-boersenformel.com
-watchcartoononline.com
-abclocal.go.com
-techrepublic.com
-just-fuck.com
-camster.com
-akairan.com
-yeslibertin.com
-abc.go.com
-searchtherightwords.com
-scotiabank.com
-justclick.ru
-douguo.com
-discover.com
-britishairways.com
-mobafire.com
-gi-akademie.ning.com
-desirulez.net
-qiushibaike.com
-moonbasa.com
-all.biz
-springer.com
-emai.com
-deadspin.com
-hulkshare.com
-fast-torrent.ru
-oriflame.com
-imgchili.net
-mega-juegos.mx
-gyazo.com
-persianv.com
-adk2.com
-ingbank.pl
-nationalconsumercenter.com
-xxxkinky.com
-mywot.com
-gaymaletube.com
-1tv.ru
-manutd.com
-merchantcircle.com
-canalblog.com
-capitalone360.com
-tlbb8.com
-softonic.fr
-ccavenue.com
-tyroodr.com
-exam8.com
-allmusic.com
-stubhub.com
-arcor.de
-yolasite.com
-haraj.com.sa
-mypopup.ir
-memurlar.net
-smugmug.com
-filefactory.com
-fantasti.cc
-bokra.net
-goarticles.com
-moneysavingexpert.com
-donga.com
-lastminute.com
-xkcd.com
-sou300.com
-magnovideo.com
-inquirer.net
-phoenix.edu
-videogenesis.com
-thestar.com
-tripadvisor.es
-blankrefer.com
-yle.fi
-beamtele.com
-oanda.com
-iheart.com
-google.co.tz
-stargazete.com
-bossip.com
-defaultsear.ch
-thaiseoboard.com
-qinbei.com
-ninisite.com
-j.gs
-nos.nl
-qualtrics.com
-kommersant.ru
-urban-rivals.com
-computerbild.de
-fararu.com
-menshealth.com
-jobstreet.com
-rbcroyalbank.com
-inmotionhosting.com
-surveyrouter.com
-kankanews.com
-aol.de
-bol.com
-datpiff.com
-mplife.com
-sale-fire.com
-inbox.lv
-offeratum.com
-pandora.tv
-eltiempo.com
-indiarailinfo.com
-solidtrustpay.com
-warthunder.ru
-novamov.com
-folkd.com
-envato.com
-wetpaint.com
-tempo.co
-howtogeek.com
-foundationapi.com
-care2.com
-bendibao.com
-mazika2day.com
-asda.com
-nowvideo.ch
-hiapk.com
-17u.com
-tutu.ru
-ncdownloader.com
-warez-bb.org
-jsoftj.com
-xmarks.com
-36kr.com
-runetki.com
-quoka.de
-heureka.cz
-monografias.com
-zhenai.com
-4porn.com
-antena3.com
-lintas.me
-seroundtable.com
-e1.ru
-berkeley.edu
-officedepot.com
-myflorida.com
-parispornmovies.com
-uniqlo.com
-topky.sk
-lumovies.com
-buysellads.com
-stirileprotv.ro
-scottrade.com
-mmtrends.net
-wholesale-dress.net
-metacritic.com
-pichunter.com
-moneybookers.com
-idealista.com
-buzzle.com
-rcom.co.in
-weightwatchers.com
-itv.com
-inilah.com
-vic.gov.au
-prom.ua
-with2.net
-doodle.com
-trafficbroker.com
-h33t.com
-avaaz.org
-maultalk.com
-bmo.com
-nerdbux.com
-abnamro.nl
-didigames.com
-pornorama.com
-forumotion.com
-woman.ru
-thaivisa.com
-lexpress.fr
-forumcommunity.net
-regions.com
-sf-express.com
-donkeymails.com
-clubic.com
-aucfan.com
-enterfactory.com
-yandex.com
-iherb.com
-in.gr
-olx.pt
-fbdownloader.com
-autoscout24.it
-siteground.com
-psicofxp.com
-persiangig.com
-metroer.com
-tokopedia.com
-seccam.info
-sport-express.ru
-vodafone.it
-blekko.com
-entekhab.ir
-expressen.se
-zalando.fr
-hawaaworld.com
-freeonlinegames.com
-google.com.lb
-ab-in-den-urlaub.de
-android4tw.com
-alriyadh.com
-drugstore.com
-iobit.com
-rei.com
-racing-games.com
-mommyfucktube.com
-pideo.net
-gogoanime.com
-avaxho.me
-christianmingle.com
-activesearchresults.com
-trendsonline.biz
-planetsuzy.org
-rubias19.com
-cleverbridge.com
-jeevansathi.com
-washingtontimes.com
-lcl.fr
-98ia.com
-mercadolibre.com.co
-n-tv.de
-divyabhaskar.co.in
-airbnb.com
-mybrowserbar.com
-travian.com
-autoblog.com
-blesk.cz
-playboy.com
-p30download.com
-pazienti.net
-uast.ac.ir
-logsoku.com
-zedge.net
-creditmutuel.fr
-absa.co.za
-milliyet.tv
-jiathis.com
-liverpoolfc.tv
-dospy.com
-calameo.com
-netsuite.com
-angelfire.com
-snagajob.com
-hollywoodlife.com
-techtudo.com.br
-payserve.com
-portalnet.cl
-worldadult-videos.info
-indianpornvideos.com
-france24.com
-discuss.com.hk
-theplanet.com
-advego.ru
-eltiempo.es
-55tuan.com
-snopes.com
-startnow.com
-tucarro.com
-skyscanner.net
-wchonline.com
-gaadi.com
-lindaikeji.blogspot.com
-keywordblocks.com
-apsense.com
-avangate.com
-gandul.info
-google.com.gh
-mybigcommerce.com
-homeaway.com
-wikitravel.org
-etxt.ru
-zerx.ru
-sidereel.com
-edreams.es
-india-forums.com
-infonews.com
-zoominfo.com
-stylebistro.com
-dominos.com
-591hx.com
-authorize.net
-61baobao.com
-digitalspy.co.uk
-godvine.com
-rednowtube.com
-appbank.net
-woozgo.fr
-expireddomains.net
-my-uq.com
-peliculasyonkis.com
-forumfree.it
-shangdu.com
-startmyripple.com
-hottube.me
-members.webs.com
-blick.ch
-google.cm
-tomtom.com
-rzd.ru
-opensooq.com
-pizzahut.com
-marksandspencer.com
-filenuke.com
-filelist.ro
-akharinnews.com
-etrade.com
-planetromeo.com
-wpbeginner.com
-bancomercantil.com
-pastdate.com
-webutation.net
-mywebgrocer.com
-mobile.ir
-seemorgh.com
-nhs.uk
-google.ba
-ileehoo.com
-seobook.com
-wetteronline.de
-happy-porn.com
-theonion.com
-webnode.com
-svaiza.com
-newsbomb.gr
-t88u.com
-tsn.ca
-unity3d.com
-nseindia.com
-juegosdiarios.com
-genieo.com
-kelkoo.com
-shabdkosh.com
-tecmundo.com.br
-chinaunix.net
-goo-net.com
-asana.com
-hdporn.in
-virtapay.com
-jobdiagnosis.com
-guokr.com
-clickpoint.it
-3dmgame.com
-ashleymadison.com
-utsprofitads.com
-google.ee
-oyunskor.com
-metro.co.uk
-ebaumsworld.com
-realsimple.com
-3file.info
-xcams.com
-cyberforum.ru
-babble.com
-lidl.de
-pixer.mobi
-yell.com
-alnilin.com
-lurkmore.to
-olx.co.za
-eorezo.com
-baby.ru
-redporntube.com
-extabit.com
-wayn.com
-gaana.com
-islamicfinder.org
-venturebeat.com
-played.to
-alrakoba.net
-mouthshut.com
-banquepopulaire.fr
-dasoertliche.de
-1stwebdesigner.com
-tam.com.br
-nature.com
-camfrog.com
-philly.com
-zemtv.com
-oprah.com
-wmaraci.com
-ruvr.ru
-gsn.com
-acrobat.com
-depositfiles.org
-smartresponder.ru
-huxiu.com
-porn-wanted.com
-tripadvisor.fr
-3366.com
-ranker.com
-cibc.com
-trend.az
-whatsapp.com
-07073.com
-netload.in
-channel4.com
-yatra.com
-elconfidencial.com
-labnol.org
-google.co.ke
-disneylatino.com
-pconverter.com
-cqnews.net
-blog.co.uk
-immowelt.de
-crunchyroll.com
-gamesgames.com
-protothema.gr
-vmoptions.com
-go2jump.org
-psu.edu
-sanjesh.org
-sportingnews.com
-televisionfanatic.com
-fansshare.com
-xcams4u.com
-madthumbs.com
-ebates.com
-eromon.net
-copyblogger.com
-flirt4free.com
-gaytube.com
-notdoppler.com
-allmyvideos.net
-cam4.de.com
-chosun.com
-adme.ru
-codeplex.com
-jumia.com.ng
-digitaltrends.com
-b92.net
-miniinthebox.com
-radaronline.com
-hujiang.com
-gardenweb.com
-pizap.com
-iptorrents.com
-yuku.com
-mega-giochi.it
-nrk.no
-99designs.com
-uscis.gov
-lostfilm.tv
-mileroticos.com
-republika.co.id
-sharethis.com
-samplicio.us
-1saleaday.com
-vonelo.com
-oyunmoyun.com
-flightradar24.com
-geo.tv
-nexusmods.com
-blogspot.fi
-directtrack.com
-media.net
-bigresource.com
-free-lance.ru
-loveplanet.ru
-ilfattoquotidiano.it
-coolmovs.com
-mango.com
-nj.com
-magazineluiza.com.br
-datehookup.com
-registro.br
-debenhams.com
-jqueryui.com
-palcomp3.com
-opensubtitles.org
-socialmediatoday.com
-allgameshome.com
-pricegrabber.com
-lufthansa.com
-ip-adress.com
-business-standard.com
-games.com
-zaman.com.tr
-jagranjosh.com
-mint.com
-gorillavid.in
-google.com.om
-blogbigtime.com
-korrespondent.net
-nymag.com
-proporn.com
-ycasmd.info
-persiantools.com
-torrenthound.com
-bestsexo.com
-alwatanvoice.com
-jahannews.com
-bluewin.ch
-sap.com
-rzb.ir
-myorderbox.com
-dealsandsavings.net
-goldenline.pl
-stuff.co.nz
-opentable.com
-4738.com
-freshersworld.com
-state.pa.us
-lavanguardia.com
-mob.org
-vodafone.in
-blogdetik.com
-888.it
-passportindia.gov.in
-ssa.gov
-desitvforum.net
-rajasthan.gov.in
-zonealarm.com
-locaweb.com.br
-logme.in
-fetlife.com
-lyricsfreak.com
-te3p.com
-hmrc.gov.uk
-bravoerotica.com
-kolesa.kz
-vinescope.com
-shoplocal.com
-mydrivers.com
-bigideamastermind.com
-uncoverthenet.com
-ragecomic.com
-yodobashi.com
-titan24.com
-nocoty.pl
-turkishairlines.com
-liputan6.com
-3suisses.fr
-cancan.ro
-apetube.com
-kurir-info.rs
-wow.com
-myblogguest.com
-wp.com
-tre.it
-livrariasaraiva.com.br
-ubuntuforums.org
-serverfault.com
-princeton.edu
-experienceproject.com
-ero-video.net
-west263.com
-nguoiduatin.vn
-findthebest.com
-iol.pt
-hotukdeals.com
-filmifullizle.com
-blog.hu
-dailyfinance.com
-bigxvideos.com
-adreactor.com
-fmworld.net
-fumu.com
-ntv.ru
-poringa.net
-syosetu.com
-giantsextube.com
-uuu9.com
-babosas.com
-square-enix.com
-bankia.es
-freedownloadmanager.org
-add-anime.net
-tuttomercatoweb.com
-192.com
-freekaamaal.com
-youngpornvideos.com
-nbc.com
-jne.co.id
-fobshanghai.com
-johnlewis.com
-mvideo.ru
-bhinneka.com
-gooddrama.net
-lobstertube.com
-ovguide.com
-joemonster.org
-editor.wix.com
-wechat.com
-locanto.in
-video2mp3.net
-couchsurfing.org
-tchibo.de
-rol.ro
-toroporno.com
-backlinkwatch.com
-greatergood.com
-smartaddressbar.com
-getgoodlinks.ru
-fitbit.com
-elcorteingles.es
-up2c.com
-rg.ru
-ftalk.com
-apartmenttherapy.com
-blogspot.hu
-e-rewards.com
-weloveshopping.com
-swtor.com
-abs-cbnnews.com
-webpagetest.org
-ricardo.ch
-ghatreh.com
-ibps.in
-moneymakergroup.com
-exist.ru
-kakprosto.ru
-gradeuptube.com
-lastampa.it
-medicinenet.com
-theknot.com
-yale.edu
-okazii.ro
-wa.gov
-gmhuowan.com
-cnhubei.com
-dickssportinggoods.com
-instaforex.com
-zdf.de
-getpocket.com
-takungpao.com
-junkmail.co.za
-tripwiremagazine.com
-popcap.com
-bangbros.com
-shtyle.fm
-jungle.gr
-apserver.net
-mzamin.com
-google.lu
-squarebux.com
-bollywoodhungama.com
-milfmovs.com
-softonic.it
-cyberciti.biz
-scout.com
-teensnow.com
-pornper.com
-torrentreactor.net
-smotri.com
-startpage.com
-climatempo.com.br
-bigrock.in
-kajabi.com
-imgchili.com
-dogpile.com
-thestreet.com
-sport24.gr
-tophotels.ru
-bbva.es
-perfectmoney.com
-cashmachines2.com
-skroutz.gr
-logitech.com
-seriescoco.com
-fastclick.com
-cambridge.org
-fark.com
-krypt.com
-indiangilma.com
-safe-swaps.com
-trenitalia.com
-flycell.com.mx
-livefreefun.com
-ourtoolbar.com
-anandtech.com
-neimanmarcus.com
-lelong.com.my
-pulscen.ru
-paginegialle.it
-intelius.com
-orange.pl
-aktuality.sk
-webgame.in.th
-runescape.com
-rocketnews24.com
-lineadirecta.com
-origin.com
-newsbeast.gr
-justhookup.com
-lifenews.ru
-sitemeter.com
-isbank.com.tr
-commerzbanking.de
-marthastewart.com
-ntvmsnbc.com
-seloger.com
-vend-o.com
-almanar.com.lb
-sifyitest.com
-taojindi.com
-mylife.com
-talkfusion.com
-hichina.com
-paruvendu.fr
-admcsport.com
-faz.net
-narutoget.com
-wufoo.com
-feedads-srv.com
-gophoto.it
-tgju.org
-dynamicdrive.com
-centurylink.net
-ngs.ru
-anyap.info
-dailykos.com
-malaysiakini.com
-uefa.com
-socialmediaexaminer.com
-peperonity.de
-support.wordpress.com
-hola.com
-readmanga.eu
-jstv.com
-irib.ir
-bookingbuddy.com
-computerhope.com
-ilovemobi.com
-pinkrod.com
-videobash.com
-alfemminile.com
-tu.tv
-utro.ru
-urbanoutfitters.com
-autozone.com
-gilt.com
-atpworldtour.com
-goibibo.com
-propellerpops.com
-cornell.edu
-flashscore.com
-babyblog.ru
-sport-fm.gr
-viamichelin.fr
-newyorker.com
-tagesschau.de
-guiamais.com.br
-jeux.fr
-pontofrio.com.br
-dm5.com
-ss.lv
-mirtesen.ru
-money.pl
-tlbsearch.com
-usembassy.gov
-cineblog01.net
-nur.kz
-hotnewhiphop.com
-mp3sheriff.com
-games.co.id
-deviantclip.com
-list.ru
-xitek.com
-netvibes.com
-24sata.hr
-usda.gov
-zerofreeporn.com
-tvb.com
-decolar.com
-worldfree4u.com
-dzone.com
-wikiquote.org
-techtunes.com.bd
-pornup.me
-blogutils.net
-yupoo.com
-peoplesmart.com
-kijiji.it
-usairways.com
-betfred.com
-ow.ly
-nsw.gov.au
-mci.ir
-iranecar.com
-wisegeek.com
-gocomics.com
-bramjnet.com
-bit.ly
-timesofindia.com
-xingcloud.com
-tfl.gov.uk
-derstandard.at
-icq.com
-orange.co.uk
-pornokopilka.info
-88db.com
-house365.com
-collegehumor.com
-gfxtra.com
-borsapernegati.com
-surveygifters.com
-ec21.com
-seoprofiler.com
-goldporntube.com
-tvtropes.org
-techtarget.com
-juno.com
-visual.ly
-dardarkom.com
-showup.tv
-three.co.uk
-shopstyle.com
-penguinvids.com
-trainenquiry.com
-soha.vn
-fengniao.com
-carschina.com
-500wan.com
-perfectinter.net
-elog-ch.com
-thetoptens.com
-1616.net
-nationwide.co.uk
-myhabit.com
-kinomaniak.tv
-googlecode.com
-kddi.com
-wyborcza.biz
-gtbank.com
-zigwheels.com
-lepoint.fr
-formula1.com
-baomoi.com
-apa.az
-movie2k.to
-irpopup.ir
-nps.gov
-lachainemeteo.com
-x-art.com
-bakecaincontrii.com
-longtailvideo.com
-yengo.com
-listentoyoutube.com
-dreamhost.com
-cari.com.my
-sergeymavrodi.com
-boursorama.com
-extra.com.br
-msnbc.com
-uwants.com
-utexas.edu
-minijuegos.com
-mumayi.com
-skorer.tv
-ddmap.com
-ebog.com
-artlebedev.ru
-venere.com
-academic.ru
-mako.co.il
-nabble.com
-autodesk.com
-vertitechnologygroup.com
-leaseweb.com
-yoox.com
-papajohns.com
-unmillondeutilidades.com
-webmasters.ru
-seoclerks.com
-yootheme.com
-google.com.py
-beemp3.com
-yepme.com
-alef.ir
-gotowebinar.com
-onec.dz
-bonprix.de
-landsend.com
-libertatea.ro
-timeout.com
-appnexus.com
-uproxx.com
-alohatube.com
-citilink.ru
-askubuntu.com
-freemake.com
-rockettheme.com
-tupaki.com
-53.com
-tune.pk
-standardchartered.com
-video-i365.com
-knowyourmeme.com
-gofeminin.de
-vmware.com
-vbox7.com
-webfail.com
-onewebsearch.com
-xnxxmovies.com
-blogspot.hk
-hgtv.com
-findagrave.com
-yoast.com
-audiopoisk.com
-sexytube.me
-centerblog.net
-webpronews.com
-prnewswire.com
-vietnamnet.vn
-groupon.co.in
-bom.gov.au
-loxblog.com
-llnw.com
-jcrew.com
-carsensor.net
-aukro.cz
-zoomby.ru
-wallstcheatsheet.com
-17k.com
-secondlife.com
-marmiton.org
-zorpia.com
-searchya.com
-rtl2.de
-wiocha.pl
-28tui.com
-shopzilla.com
-google.com.ni
-lycos.com
-gucheng.com
-rajanews.com
-blackhatteam.com
-mp3.es
-forums.wordpress.com
-micromaxinfo.com
-duden.de
-nyc.gov
-monova.org
-al-wlid.com
-dastelefonbuch.de
-cam4ultimate.com
-inps.it
-nazwa.pl
-beatport.com
-wizzair.com
-thomann.de
-juntadeandalucia.es
-oficialsurveyscenter.co
-zaluu.com
-videarn.com
-azcentral.com
-xvideosmovie.com
-eforosh.com
-movie25.com
-creditkarma.com
-upi.com
-mozook.com
-heavy.com
-worldoftanks.com
-vkrugudruzei.ru
-hourlyrevshare.net
-walkerplus.com
-btyou.com
-adzibiz.com
-tryflirting.com
-moi.gov.sa
-cooltext.com
-dawanda.com
-travian.com.sa
-va.gov
-sunmaker.com
-aaa.com
-dinodirect.com
-cima4u.com
-huaban.com
-nzherald.co.nz
-plotek.pl
-chow.com
-rincondelvago.com
-uzai.com
-stayfriends.de
-reed.co.uk
-rainpow.com
-dallasnews.com
-ntvspor.net
-fonearena.com
-forocoches.com
-myfonts.com
-fenopy.se
-animefreak.tv
-websitewelcome.com
-indonetwork.co.id
-mapsofindia.com
-newlook.com
-holiday-weather.com
-zhe800.com
-recipesfinder.com
-bbom.com.br
-jalopnik.com
-canon.com
-freshbooks.com
-clickcompare.info
-aprod.hu
-thisav.com
-boerse.bz
-orange.es
-forobeta.com
-surfactif.fr
-listverse.com
-feedjit.com
-bni.co.id
-gamemazing.com
-mbalib.com
-topsy.com
-torchbrowser.com
-ieee.org
-tinydeal.com
-playdom.com
-redorbit.com
-inboxdollars.com
-google.com.bh
-pcanalysis.net
-acer.com
-jizzbell.com
-google.com.kh
-mappy.com
-day.az
-euronews.com
-wikidot.com
-creativecommons.org
-quantcast.com
-iconarchive.com
-iyaya.com
-jetstar.com
-diandian.com
-winzip.com
-clixzor.com
-teebik.com
-meilele.com
-gsm.ir
-dek-d.com
-giantbomb.com
-tala.ir
-extremetracking.com
-homevv.com
-truthaboutabs.com
-psychologytoday.com
-vod.pl
-macromill.com
-amd.com
-livescience.com
-dedecms.com
-jin115.com
-ampxchange.com
-profitcentr.com
-webmotors.com.br
-lan.com
-fileice.net
-ingdirect.es
-amtrak.com
-emag.ro
-progressive.com
-balatarin.com
-immonet.de
-e-travel.com
-studymode.com
-go2000.com
-shopbop.com
-filesfetcher.com
-euroresidentes.com
-movistar.es
-lefeng.com
-google.hn
-homestead.com
-filesonar.com
-hsbccreditcard.com
-google.com.np
-parperfeito.com.br
-sciencedaily.com
-realgfporn.com
-wonderhowto.com
-coolrom.com
-wikibooks.org
-archdaily.com
-gigazine.net
-totaljerkface.com
-bezaat.com
-eurosport.com
-fontspace.com
-tirage24.com
-bancomer.com.mx
-nasdaq.com
-bravoteens.com
-bdjobs.com
-zimbra.free.fr
-arsenal.com
-rabota.ru
-lovefilm.com
-tsetmc.com
-movshare.net
-debonairblog.com
-zmovie.co
-peoplefinders.com
-mercadolibre.com
-connectlondoner.com
-forbes.ru
-gagnezauxoptions.com
-taikang.com
-mywapblog.com
-citysearch.com
-novafinanza.com
-gruposantander.es
-relianceada.com
-rankingsandreviews.com
-hjenglish.com
-state.nj.us
-comdirect.de
-claro.com.br
-alluc.to
-godlikeproductions.com
-lowyat.net
-dawn.com
-18xgirls.com
-origo.hu
-loopnet.com
-payu.in
-digitalmedia-comunicacion.com
-newsvine.com
-petfinder.com
-kuaibo.com
-soft32.com
-yellowpages.ca
-1fichier.com
-egyup.com
-iskullgames.com
-androidforums.com
-blogspot.cz
-umich.edu
-madsextube.com
-bigcinema.tv
-donedeal.ie
-winporn.com
-cosmopolitan.com
-reg.ru
-localmoxie.com
-kootation.com
-gidonline.ru
-clipconverter.cc
-gioco.it
-ravelry.com
-gettyimages.com
-medicalnewsreporter.com
-shop411.com
-aif.ru
-journaldesfemmes.com
-blogcu.com
-vanguard.com
-freemp3go.com
-google.ci
-findicons.com
-tineye.com
-webdesignerdepot.com
-nomorerack.com
-iqoo.me
-amarujala.com
-pengfu.com
-leadpages.net
-zalukaj.tv
-avon.com
-casasbahia.com.br
-juegosdechicas.com
-tvrain.ru
-askmefast.com
-stockcharts.com
-footlocker.com
-allanalpass.com
-theoatmeal.com
-storify.com
-santander.com.br
-laughnfiddle.com
-lomadee.com
-aftenposten.no
-lamoda.ru
-tasteofhome.com
-news247.gr
-sherdog.com
-milb.com
-3djuegos.com
-dreammovies.com
-commonfloor.com
-tharunee.lk
-chatrandom.com
-rechargeitnow.com
-am15.net
-sexad.net
-herokuapp.com
-apontador.com.br
-rfi.fr
-woozworld.com
-hitta.se
-comedycentral.com
-fbsbx.com
-aftabnews.ir
-stepstone.de
-filmon.com
-ameritrade.com
-ecitic.com
-bola.net
-hq-sex-tube.com
-gsp.ro
-groupon.co.uk
-20min.ch
-barclaycardus.com
-dice.com
-himasoku.com
-nwsource.com
-gougou.com
-iol.co.za
-thinkgeek.com
-governmentjobs.com
-500.com
-caixin.com
-elsevier.com
-rafflecopter.com
-auctiva.com
-pracuj.pl
-strato.de
-ricardoeletro.com.br
-vodafone.de
-jike.com
-smosh.com
-downlite.net
-to8to.com
-tikona.in
-royalmail.com
-tripadvisor.de
-realclearpolitics.com
-pubdirecte.com
-rassd.com
-ptt.cc
-townhall.com
-theoldreader.com
-viki.com
-one.com
-peopleperhour.com
-desidime.com
-17track.net
-duote.com
-emuch.net
-mlgame.co.uk
-rockstargames.com
-slaati.com
-ibibo.com
-journaldunet.com
-ria.ua
-odatv.com
-comodo.com
-clickfair.com
-system500.com
-wordstream.com
-alexaboostup.com
-yjbys.com
-hsbc.com
-online-convert.com
-miui.com
-totaljobs.com
-travian.fr
-funda.nl
-bazos.sk
-efukt.com
-startlap.com
-hir24.hu
-mrskin.com
-dbs.com
-sevenforums.com
-admitad.com
-graaam.com
-exactme.com
-roadrunner.com
-liberation.fr
-cas.sk
-redbubble.com
-ezilon.com
-hihi2.com
-net.hr
-mediaite.com
-clip2net.com
-wapka.mobi
-dailybasis.com
-o2online.de
-tweetdeck.com
-fakt.pl
-service-public.fr
-bodisparking.com
-corporationwiki.com
-jandan.net
-alisoft.com
-gosuslugi.ru
-grxf.com
-daserste.de
-freedigitalphotos.net
-flirchi.ru
-htmlbook.ru
-independent.ie
-bufferapp.com
-panzar.com
-sport.cz
-matomeantena.com
-thenewporn.com
-iran-tejarat.com
-rotoworld.com
-maalaimalar.com
-poppen.de
-csfd.cz
-2ip.ru
-hawamer.com
-telkomsel.com
-un.org
-autobinaryea.com
-emgoldex.com
-saksfifthavenue.com
-realtor.ca
-hdwallpapers.in
-chinahr.com
-niazerooz.com
-sina.com
-kinopod.ru
-funweek.it
-pornsake.com
-vitacost.com
-110.com
-jobomas.com
-joyreactor.cc
-3dnews.ru
-vedomosti.ru
-stansberryresearch.com
-performersoft.com
-codecademy.com
-petsmart.com
-kissmetrics.com
-infojobs.it
-wealink.com
-rapidtrk.com
-enterprise.com
-iran-forum.ir
-express-files.com
-cyberpresse.ca
-dobreprogramy.pl
-uploading.com
-profitclicking.com
-playwartune.com
-toluna.com
-shoptime.com.br
-totaladperformance.com
-handelsblatt.com
-hamshahrionline.ir
-15min.lt
-wyborcza.pl
-flvto.com
-microsofttranslator.com
-trovaprezzi.it
-eversave.com
-wmzona.com
-hardwarezone.com.sg
-thestar.com.my
-siliconindia.com
-jfranews.com
-emol.com
-nordea.fi
-heroturko.me
-xat.com
-3asq.com
-hlntv.com
-incruit.com
-list-manage2.com
-bulbagarden.net
-blogdohotelurbano.com
-suomi24.fi
-nicozon.net
-tuporno.tv
-perfectworld.com
-ayosdito.ph
-gmx.at
-123greetings.com
-metafilter.com
-g9g.com
-searchnfind.org
-pcgamer.com
-on.cc
-rentalcars.com
-mail2web.com
-zalando.it
-freevideo.cz
-source-wave.com
-iranjib.ir
-societe.com
-160by2.com
-berooztarinha.com
-popmog.com
-fantasy8.com
-motortrend.com
-huffingtonpost.ca
-51test.net
-ringtonematcher.com
-ourtime.com
-standardchartered.co.in
-rdio.com
-parsiblog.com
-btvguide.com
-sport.ro
-freep.com
-gismeteo.ua
-rojadirecta.me
-babol.pl
-lun.com
-epicurious.com
-fetishok.com
-mystart.com
-wn.com
-nationalrail.co.uk
-feedsportal.com
-rai.it
-sportlemon.tv
-groupon.com.br
-ebay.at
-yourdictionary.com
-360safe.com
-statefarm.com
-desjardins.com
-biblehub.com
-mercadolibre.cl
-eluniversal.com
-lrytas.lt
-youboy.com
-gratka.pl
-etype.com
-reallifecam.com
-imp.free.fr
-jobstreet.co.id
-geenstijl.nl
-aebn.net
-openoffice.org
-diythemes.com
-2gis.ru
-wpmu.org
-scrubtheweb.com
-domain.com.au
-buyma.com
-ccbill.com
-tui18.com
-goforfiles.com
-billionuploads.com
-blogtalkradio.com
-pipl.com
-wallpaperswide.com
-tuttosport.com
-astucecherry.com
-tradingfornewbies.com
-umn.edu
-rj.gov.br
-mlive.com
-justfab.com
-ijreview.com
-daniweb.com
-quickmeme.com
-safeway.com
-virtualedge.com
-saudiairlines.com
-elbotola.com
-holtgames.com
-boots.com
-potterybarn.com
-mediamarkt.de
-mangastream.com
-mypoints.com
-torrentdownloads.me
-subtitleseeker.com
-idlebrain.com
-ekantipur.com
-nowgamez.com
-neoseeker.com
-christianpost.com
-joystiq.com
-iphone-winners.info
-quizlet.com
-prosport.ro
-quanjing.com
-gamechit.com
-teleshow.pl
-corrieredellosport.it
-yoo7.com
-fotocasa.es
-attracta.com
-hyatt.com
-confirmit.com
-xyu.tv
-yoolplay.com
-active.com
-gizmag.com
-hostelworld.com
-pc6.com
-lacentrale.fr
-megasesso.com
-thairath.co.th
-thinkprogress.org
-400gb.com
-manageflitter.com
-pronto.com
-erotube.org
-luxtarget.com
-vui.vn
-screenrant.com
-nationalreview.com
-ikman.lk
-aboutus.org
-booloo.com
-klm.com
-aukro.ua
-skladchik.com
-alfalfalfa.com
-ghanaweb.com
-cheetahmail.com
-celebritynetworth.com
-honda.com
-regnum.ru
-mediabistro.com
-template-help.com
-elektroda.pl
-howlifeworks.com
-avjavjav.com
-justunfollow.com
-kindgirls.com
-xrea.com
-songspk.cc
-impiego24.it
-health.com
-whitehouse.gov
-ulozto.cz
-clickindia.com
-zoosnet.net
-yingjiesheng.com
-copacet.com
-fluege.de
-uiuc.edu
-funnymama.com
-popsugar.com
-siyahgazete.com
-ligatus.com
-seomastering.com
-nintendo.com
-kuaidi100.com
-motor-talk.de
-p.ht
-care.com
-ttnet.com.tr
-cifraclub.com.br
-yunfile.com
-telechargement-de-ouf.fr
-hotpornshow.com
-upenn.edu
-brg8.com
-techspot.com
-milli.az
-segundamano.mx
-n4g.com
-blogspot.no
-frys.com
-pixhost.org
-washington.edu
-rte.ie
-lockerdome.com
-qassimy.com
-signup.wordpress.com
-sochiset.com
-mycokerewards.com
-collegeboard.org
-fengyunzhibo.com
-twickerz.com
-bikroy.com
-apkmania.co
-webrankstats.com
-dl-protect.com
-dr.dk
-emoneyspace.com
-rae.es
-theexgirlfriends.com
-gigaom.com
-burmeseclassic.com
-wisc.edu
-ocnk.net
-arcot.com
-paginasamarillas.es
-tunisia-sat.com
-medscape.com
-gameninja.com
-imperiaonline.org
-2ememain.be
-myshopping.com.au
-nvidia.com
-fanhuan.com
-vista.ir
-dish.com
-cartrade.com
-egopay.com
-sonyentertainmentnetwork.com
-myway.com
-kariyer.net
-thanhnien.com.vn
-gulfnews.com
-flagcounter.com
-yfrog.com
-bigstockphoto.com
-occ.com.mx
-3911.net
-naszemiasto.pl
-pgatour.com
-zgjrw.com
-fdj.fr
-motogp.com
-organogold.com
-tamindir.com
-ykb.com
-biglion.ru
-yourfiledownloader.com
-publika.az
-dealnews.com
-warnerbros.com
-wpmudev.org
-pu-results.info
-usajobs.gov
-adsprofitwiz.es
-parallels.com
-thqafawe3lom.com
-xiazaiba.com
-enikos.gr
-m5zn.com
-dir.bg
-ripoffreport.com
-jusbrasil.com.br
-maxifoot.fr
-eva.vn
-dfnhk8.net
-api.ning.com
-ligtv.com.tr
-openrice.com
-999120.net
-pho.to
-indiblogger.in
-tfile.me
-kotak.com
-katproxy.com
-calottery.com
-klmty.net
-endomondo.com
-uploadboy.com
-8tracks.com
-blox.pl
-conrad.de
-sonico.com
-windguru.cz
-tinhte.vn
-grantland.com
-seratnews.ir
-solomono.ru
-foreca.com
-ziprecruiter.com
-chime.in
-intesasanpaolo.com
-softonic.de
-adtech.info
-appgame.com
-opendns.com
-tubekitty.com
-linguee.de
-pepperfry.com
-egou.com
-tweakers.net
-alfavita.gr
-plusnetwork.com
-timeweb.ru
-maybeporn.com
-gharreh.com
-canoe.ca
-parsine.com
-ucla.edu
-freeridegames.com
-doctoroz.com
-tradeindia.com
-socialmediabar.com
-yaske.net
-miniih.com
-blog.me
-dn.se
-almos3a.com
-bbvanet.com.mx
-fcbarcelona.com
-web.com
-raaga.com
-yad2.co.il
-2cto.com
-nx8.com
-modcloth.com
-carsales.com.au
-cooks.com
-fileswap.com
-egyptiansnews.com
-azyya.com
-masreat.com
-airliners.net
-com-1b.info
-virginmobileusa.com
-pleasantharborrv.com
-gsmhosting.com
-foxbusiness.com
-delfi.lv
-flightaware.com
-ameli.fr
-fbxtk.com
-purdue.edu
-sbi.co.in
-fotka.pl
-quicksprout.com
-arjwana.com
-affili.net
-5sing.com
-mozilla.com
-taaza.com
-onetad.com
-vivastreet.it
-leguide.com
-casualclub.com
-wanelo.com
-ipsosinteractive.com
-videohive.net
-fenzhi.com
-lefrecce.it
-bugun.com.tr
-p30world.com
-cuevana.tv
-joins.com
-tvnet.lv
-aliimg.com
-bellanaija.com
-startpagina.nl
-incometaxindiaefiling.gov.in
-michigan.gov
-harborfreight.com
-fineartamerica.com
-mysurvey.com
-kapaza.be
-adxpansion.com
-thefind.com
-priyo.com
-burrp.com
-sky.it
-ipad-winners.info
-usgs.gov
-gavick.com
-ellislab.com
-voegol.com.br
-paginebianche.it
-getwebcake.com
-zeroredirect1.com
-gaiaonline.com
-iqilu.com
-bright.com
-comunidades.net
-webgains.com
-overdrive.com
-bigcommerce.com
-paperpkads.com
-imageporter.com
-listal.com
-rbcdaily.ru
-redbus.in
-3bmeteo.com
-earn-on.com
-ae.com
-shoutmeloud.com
-oeeee.com
-usenet.nl
-mediotiempo.com
-prostoporno.net
-bangyoulater.com
-comunio.de
-pureleads.com
-bakeca.it
-trovit.it
-fakku.net
-indeed.fr
-inquisitr.com
-wizards.com
-straightdope.com
-pornpros.com
-s-oman.net
-facilisimo.com
-dostor.org
-tabloidpulsa.co.id
-shafaf.ir
-bt.dk
-lent.az
-filmaffinity.com
-wjunction.com
-gamefront.com
-photoshelter.com
-cheaptickets.com
-meetic.it
-seochat.com
-livemixtapes.com
-deadline.com
-boingboing.net
-lecai.com
-onetravel.com
-erotictube.me
-svd.se
-pcadvisor.co.uk
-pravda.com.ua
-afisha.ru
-dressupgamesite.com
-mercadopago.com
-bangkokpost.com
-dumpert.nl
-monotaro.com
-bloomingdales.com
-ebayclassifieds.com
-t-online.hu
-2dbook.com
-thekitchn.com
-halifax.co.uk
-tanx.com
-jutarnji.hr
-petardashd.com
-rookee.ru
-showroomprive.com
-sharepoint.com
-liebiao.com
-pumbaporn.com
-dwnews.com
-sanguosha.com
-pp.cc
-myfc.ir
-alicdn.com
-carmax.com
-defencenet.gr
-cuantarazon.com
-westernunion.com
-natunbarta.com
-sekindo.com
-edublogs.org
-hotmail.com
-problogger.net
-amardeshonline.com
-gemius.com
-egynews.net
-indiabix.com
-provincial.com
-play.com
-beslist.nl
-shape.com
-alhilal.com
-irecommend.ru
-cmmnts.com
-1news.az
-kinobanda.net
-banamex.com.mx
-cleanfiles.net
-algeriaforum.net
-zumi.pl
-giallozafferano.it
-news-postseven.com
-firstcry.com
-lookforporn.com
-xxsy.net
-scriptmafia.org
-intodns.com
-famitsu.com
-eclipse.org
-net-a-porter.com
-btemplates.com
-topshop.com
-myvidster.com
-calciomercato.com
-arabyonline.com
-lesechos.fr
-empireavenue.com
-damnlol.com
-nukistream.com
-wayport.net
-buienradar.nl
-vivastreet.co.in
-kroger.com
-geocaching.com
-hunantv.com
-fotolog.net
-gunbroker.com
-flalottery.com
-priples.com
-nlayer.net
-trafficshop.com
-standardmedia.co.ke
-finanzen.net
-meta.ua
-gfy.com
-playground.ru
-rp5.ru
-otnnetwork.net
-tvmao.com
-hir.ma
-twilightsex.com
-haodou.com
-virgin-atlantic.com
-ankieta-online.pl
-kinkytube.me
-123mplayer.com
-elifting.com
-akiba-online.com
-tcsbank.ru
-gametrailers.com
-dihitt.com
-fancy.com
-admaimai.com
-61.com
-hotchatdirect.com
-penesalud.com
-adsupplyads.com
-robokassa.ru
-brooonzyah.net
-moviesmobile.net
-fuck-mates.com
-ch-news.com
-cwan.com
-mec.gov.br
-musiciansfriend.com
-angrybirds.com
-ebrun.com
-kienthuc.net.vn
-morningstar.com
-rasekhoon.net
-techsmith.com
-diy.com
-awwwards.com
-ajc.com
-akismet.com
-itar-tass.com
-60secprofit.com
-videoweed.es
-guitarcenter.com
-tv2.dk
-narutom.com
-bittorrent.com
-unionpaysecure.com
-91jm.com
-licindia.in
-bama.ir
-hertz.com
-propertyguru.com.sg
-city8.com
-blu-ray.com
-abebooks.com
-adidas.com
-sing365.com
-qq163.com
-fashionandyou.com
-lietou.com
-eniro.se
-pengpeng.com
-haibao.com
-jxedt.com
-crsky.com
-nyu.edu
-minecraftskins.com
-yangtse.com
-almstba.co
-parsnews.com
-twiends.com
-dkb.de
-friendscout24.de
-aviny.com
-dig.do
-gamestorrents.com
-guru.com
-bostonglobe.com
-brandalley.fr
-tn.com.ar
-yourwebsite.com
-istgah.com
-e-familynet.com
-hotshame.com
-volkskrant.nl
-karnaval.com
-team-bhp.com
-sinemalar.com
-ipko.pl
-fastcompany.com
-embedupload.com
-gzmama.com
-icicidirect.com
-whatismyip.com
-siasat.pk
-rbi.org.in
-amarillasinternet.com
-netvasco.com.br
-ctvnews.ca
-gad.de
-dailyfx.com
-smartklicks.com
-qoo10.sg
-loc.gov
-playerflv.com
-uta-net.com
-afl.com.au
-mainlink.ru
-pricedekho.com
-wickedfire.com
-rlslog.net
-raiffeisen.at
-easports.com
-groupon.fr
-o2.co.uk
-irangrand.ir
-vuku.tv
-play.pl
-mxtoolbox.com
-promiflash.de
-linode.com
-familysearch.org
-publico.pt
-freepornvideo.me
-uploadbaz.com
-tocmai.ro
-cimbclicks.com.my
-bestporntube.me
-lainformacion.com
-herschina.com
-fontsquirrel.com
-blip.tv
-caranddriver.com
-qld.gov.au
-pons.eu
-nascar.com
-hrsmart.com
-tripadvisor.com.au
-hs.fi
-auspost.com.au
-sponsoredreviews.com
-webopedia.com
-sovsport.ru
-bancsabadell.com
-prettyporntube.com
-sodahead.com
-ovi.com
-aleseriale.pl
-mnwan.com
-callofduty.com
-sportskeeda.com
-cp.cx
-researchgate.net
-michaels.com
-createspace.com
-sprintrade.com
-anonymouse.org
-hautelook.com
-4gamer.net
-accorhotels.com
-roomkey.com
-guildwars2.com
-cargurus.com
-wpengine.com
-iis.net
-vendaria.com
-argentinawarez.com
-webdesigntunes.com
-allvoices.com
-eprize.com
-pmu.fr
-carrefour.fr
-tax.gov.ir
-ruelala.com
-mainspy.ru
-phpwind.net
-loteriasyapuestas.es
-musavat.com
-lenskart.com
-refinery29.com
-888poker.es
-denverpost.com
-who.int
-thesims3.com
-jerkhour.com
-lyricsmode.com
-ivillage.com
-qyer.com
-hktdc.com
-pornoload.com
-bluedart.com
-here.com
-philips.com
-dsebd.org
-tubidy.mobi
-stream.cz
-infojobs.com.br
-soft98.ir
-bolsaparanovatos.com
-mercador.ro
-neogaf.com
-yardbarker.com
-rapidlibrary.com
-xxeronetxx.info
-kaiserpermanente.org
-telstra.com.au
-contra.gr
-laredoute.it
-lipsum.com
-twitlonger.com
-hln.be
-53kf.com
-gofundme.com
-carigold.com
-clips4sale.com
-focalprice.com
-gameaholic.com
-presstv.ir
-puu.sh
-filmlinks4u.net
-traffic-delivery.com
-bebo.com
-enter.ru
-shufoo.net
-vivo.com.br
-jizzhut.com
-1jux.net
-serebii.net
-translate.ru
-mtv3.fi
-njuskalo.hr
-bell.ca
-myheritage.com
-cic.fr
-mercurynews.com
-alaan.tv
-econsultancy.com
-pornhost.com
-a8.net
-netzero.net
-tracklab101.com
-spanishdict.com
-amctv.com
-erepublik.com
-mk.ru
-publico.es
-fux.com
-webcamtoy.com
-rahnama.com
-wanyh.com
-ecplaza.net
-mol.gov.sa
-torrentday.com
-hsbc.com.br
-interoperabilitybridges.com
-billmelater.com
-speedanalysis.com
-volusion.com
-mixcloud.com
-weeronline.nl
-tiancity.com
-thehun.com
-comparisons.org
-eurosport.ru
-trendyol.com
-7120.com
-eldiariodeamerica.com
-fap8.com
-joyme.com
-ufl.edu
-cuantocabron.com
-hotmart.com.br
-wolframalpha.com
-cpasbien.com
-sanalpazar.com
-publipt.com
-9ku.com
-officemax.com
-cuny.edu
-gem.pl
-waelelebrashy.com
-coinmill.com
-bet.com
-moskva.fm
-groupalia.com
-131.com
-pichak.net
-theatlanticwire.com
-laptopmag.com
-worldpay.com
-groupon.pl
-imeimama.com
-torrents.net
-britishcouncil.org
-letsbonus.com
-e-monsite.com
-url.org
-discuz.com
-freepornsite.me
-cheatcc.com
-magicmovies.com
-laterooms.com
-du.ac.in
-uservoice.com
-discas.net
-d1g.com
-explicittube.com
-e-autopay.com
-3lian.com
-oopsmovs.com
-agenziaentrate.gov.it
-ufc.com
-mooshare.biz
-ankang06.org
-betradar.com
-explosm.net
-silkroad.com
-crackberry.com
-toyota.com
-bongda.com.vn
-europapress.es
-mlxchange.com
-plius.lt
-pitchfork.com
-groupon.de
-hollisterco.com
-hasoffers.com
-miami.com
-dslreports.com
-blinkweb.com
-alamaula.com
-leonardo.it
-very.co.uk
-globalsources.com
-viator.com
-greenwichmeantime.com
-appannie.com
-eldorado.ru
-canadiantire.ca
-enjin.com
-szhome.com
-phim3s.net
-bash.im
-immi.gov.au
-enjoydressup.com
-thesuperficial.com
-91mobiles.com
-libertaddigital.com
-po-kaki-to.com
-truelocal.com.au
-centrum24.pl
-zylom.com
-mypornmotion.com
-skybet.com
-soccermanager.com
-poriborton.com
-mozzi.com
-eset.com
-chelseafc.com
-amulyam.in
-argaam.com
-mnn.com
-papystreaming.com
-hostelbookers.com
-vatera.hu
-pciconcursos.com.br
-milenio.com
-yellowbook.com
-mobilepriceindia.co.in
-naked.com
-lazada.vn
-70e.com
-mapy.cz
-vodafone.es
-zbiornik.com
-fc2web.com
-rghost.ru
-avvo.com
-fardanews.com
-pcbeta.com
-hibapress.com
-gamehouse.com
-macworld.com
-qantas.com.au
-dba.dk
-inttrax.com
-conejox.com
-immobiliare.it
-sparkasse.at
-udemy.com
-accenture.com
-pokerstrategy.com
-leroymerlin.fr
-sweetkiss.me
-siriusxm.com
-nieuwsblad.be
-blogun.ru
-ojogos.com.br
-lexilogos.com
-c-and-a.com
-authorstream.com
-newser.com
-minube.com
-yellowpages.com.au
-torrentfreak.com
-expatriates.com
-51credit.com
-rawstory.com
-crictime.com
-ladolcevitae.com
-astro.com
-riverisland.com
-myzamana.com
-xpg.com.br
-svt.se
-ymlp.com
-coupondunia.in
-mymovies.it
-portaleducacao.com.br
-watchabc.go.com
-scrabblefinder.com
-2hua.com
-guiaconsumidor.com
-jzpt.com
-jino.ru
-google.tt
-addwallet.com
-enom.com
-searchfreemp3.com
-spox.com
-ename.net
-researchnow.com
-decathlon.fr
-j-cast.com
-updatetube.com
-polo.com
-asiaone.com
-kkiste.to
-frmtr.com
-skai.gr
-zovi.com
-qiwi.ru
-stfucollege.com
-carros.com.br
-privatejobshub.blogspot.in
-englishtown.com
-info.com
-multiclickbrasil.com.br
-gazeteoku.com
-kinghost.com
-izismile.com
-gopro.com
-uspto.gov
-testberichte.de
-fs.to
-sketchtoy.com
-sinarharian.com.my
-stylemode.com
-v7n.com
-livenation.com
-firstrow1.eu
-joomlaforum.ru
-sharecare.com
-vetogate.com
-series.ly
-property24.com
-payamsara.com
-webstarts.com
-renfe.es
-fatcow.com
-24ur.com
-lide.cz
-sabayacafe.com
-prodavalnik.com
-hyves.nl
-almaany.com
-xero.com
-celluway.com
-mapbar.com
-vecernji.hr
-konga.com
-fresherslive.com
-nova.cz
-onlinefwd.com
-petco.com
-benisonapparel.com
-jango.com
-mangocity.com
-gamefly.com
-igma.tv
-21cineplex.com
-fblife.com
-moe.gov.eg
-heydouga.com
-buildhr.com
-mmo-champion.com
-ithome.com
-krakow.pl
-history.com
-privatehomeclips.com
-bazos.cz
-appchina.com
-helpster.de
-51hejia.com
-fuckbadbitches.com
-toyota-autocenter.com
-alnaharegypt.com
-eastbay.com
-softonic.com.br
-translit.ru
-justcloud.com
-validclick.net
-seneweb.com
-fsiblog.com
-williamhill.it
-twitchy.com
-y4yy.com
-gouv.qc.ca
-nubiles.net
-marvel.com
-helpmefindyour.info
-tripadvisor.ca
-joomlart.com
-m18.com
-orgasmatrix.com
-bidoo.com
-rogers.com
-informationng.com
-voyage-prive.com
-comingsoon.net
-searchmetrics.com
-jetztspielen.de
-mathxl.com
-telmex.com
-purpleporno.com
-coches.net
-hamusoku.com
-link-assistant.com
-gosur.com
-torrentcrazy.com
-funny-games.biz
-bseindia.com
-promosite.ru
-google.mn
-cartoonnetworkarabic.com
-icm.edu.pl
-ttt4.com
-pepperjamnetwork.com
-lolzbook.com
-nationalpost.com
-tukif.com
-club-asteria.com
-7search.com
-kasikornbank.com
-ebay.ie
-sexlunch.com
-qype.com
-sankakucomplex.com
-flashback.org
-streamhunter.eu
-rsb.ru
-royalporntube.com
-diretta.it
-yummly.com
-dom2.ru
-metoffice.gov.uk
-goodbaby.com
-pornbb.org
-formspring.me
-google.com.cy
-purepeople.com
-epnet.com
-penny-arcade.com
-onlinekhabar.com
-vcommission.com
-zimabdk.com
-car.gr
-wat.tv
-nnn.ru
-arvixe.com
-buxp.org
-shaw.ca
-cnyes.com
-casa.it
-233.com
-text.ru
-800notes.com
-banki.ru
-marinetraffic.com
-meteo.gr
-thetrainline.com
-blogspot.ch
-netaffiliation.com
-olx.co.id
-slando.kz
-nordea.se
-xbabe.com
-bibsonomy.org
-moneynews.com
-265g.com
-horoscope.com
-yammer.com
-sextgem.com
-tribune.com.pk
-topeuro.biz
-perfectgirls.xxx
-ssc.nic.in
-8264.com
-flvrunner.com
-gry.pl
-pravda.ru
-fulltiltpoker.com
-kure.tv
-turbo.az
-ujian.cc
-mustseeindia.com
-thithtoolwin.com
-chiphell.com
-spieletipps.de
-portail.free.fr
-hbr.org
-sex-hq.com
-webdeveloper.com
-cloudzer.net
-vagas.com.br
-anspress.com
-beitaichufang.com
-songkick.com
-oyunlari.net
-unfollowers.me
-computrabajo.com.mx
-usp.br
-parseek.com
-salary.com
-navyfcu.org
-bigpond.com
-joann.com
-ajansspor.com
-burnews.com
-myrecipes.com
-mt5.com
-webconfs.com
-offcn.com
-travian.com.tr
-animenewsnetwork.com
-smartshopping.com
-twojapogoda.pl
-tigerairways.com
-archiveofourown.org
-qq937.com
-meneame.net
-joyclub.de
-yy.com
-weddingwire.com
-moddb.com
-acervoamador.com
-stgeorge.com.au
-forumhouse.ru
-mp3xd.com
-lionair.co.id
-needtoporn.com
-playcast.ru
-paheal.net
-finishline.com
-sep.gob.mx
-comenity.net
-tqn.com
-eroticads.com
-svpressa.ru
-dtvideo.com
-mobile.free.fr
-privat24.ua
-mp3sk.net
-atlas.sk
-aib.ie
-shockwave.com
-qatarairways.com
-theladders.com
-dsnetwb.com
-expansiondirecto.com
-povarenok.ru
-moneysupermarket.com
-getchu.com
-gay.com
-hsbc.com.mx
-textsale.ru
-kadinlarkulubu.com
-scientificamerican.com
-hillnews.com
-tori.fi
-6tie.com
-championselect.net
-gtobal.com
-bangkokbank.com
-akakce.com
-smarter.com
-totalvideoplugin.com
-dmir.ru
-rpp.com.pe
-uhaul.com
-kayako.com
-buyvip.com
-sixrevisions.com
-army.mil
-rediffmail.com
-gsis.gr
-destinia.com
-behindwoods.com
-wearehairy.com
-coqnu.com
-soundclick.com
-drive.ru
-cam4.fr
-bakusai.com
-thailandtorrent.com
-videosz.com
-eporner.com
-stltoday.com
-ilmessaggero.it
-theregister.co.uk
-bloggang.com
-nastyvideotube.com
-doityourself.com
-rp-online.de
-wow-impulse.ru
-kar.nic.in
-bershka.com
-neteller.com
-adevarul.ro
-divxtotal.com
-bolshoyvopros.ru
-letudiant.fr
-xinshipu.com
-vh1.com
-excite.com
-somewhereinblog.net
-mcgraw-hill.com
-patheos.com
-webdesignledger.com
-plus28.com
-adultwork.com
-dajuegos.com
-blogs.com
-glopart.ru
-donews.com
-nation.co.ke
-delfi.ee
-lacuerda.net
-jjshouse.com
-megaindex.ru
-darty.com
-maturetube.com
-jokeroo.com
-estekhtam.com
-fnac.es
-ninjakiwi.com
-tovima.gr
-timinternet.it
-citizensbankonline.com
-builtwith.com
-ko499.com
-tastyblacks.com
-currys.co.uk
-jobui.com
-notebookreview.com
-meishij.net
-filerio.in
-cheapflights.co.uk
-puls24.mk
-rumbo.es
-newsbusters.org
-imgdino.com
-oxforddictionaries.com
-ftdownloads.com
-ciudad.com.ar
-latercera.cl
-lankadeepa.lk
-bankier.pl
-hawahome.com
-comicvine.com
-cam4.it
-fok.nl
-iknowthatgirl.com
-hizliresim.com
-ebizmba.com
-twistys.com
-minkchan.com
-dnevnik.hr
-peliculascoco.com
-new-xhamster.com
-freelancer.in
-globalgrind.com
-talkgold.com
-kanui.com.br
-woxikon.de
-jobstreet.com.my
-job.ru
-wowbiz.ro
-yiyi.cc
-sinoptik.ua
-parents.com
-forblabla.com
-trojmiasto.pl
-anyoption.com
-wplocker.com
-paytm.in
-elespectador.com
-mysitecost.ru
-startribune.com
-cam4.co.uk
-bestcoolmobile.com
-soup.io
-starfall.com
-ixl.com
-oreilly.com
-dansmovies.com
-facemoods.com
-google.ge
-sat.gob.mx
-weatherbug.com
-majorgeeks.com
-llbean.com
-catho.com.br
-googlegroups.com
-animoto.com
-alquds.co.uk
-newsday.com
-games2girls.com
-youporngay.com
-spaces.ru
-seriespepito.com
-gelbeseiten.de
-thethirdmedia.com
-watchfomny.com
-freecamsexposed.com
-dinakaran.com
-xxxhost.me
-smartprix.com
-thoughtcatalog.com
-soccersuck.com
-vivanuncios.com
-liba.com
-gog.com
-philstar.com
-cian.ru
-avclub.com
-slon.ru
-stc.com.sa
-jstor.org
-wehkamp.nl
-vodafone.co.uk
-deser.pl
-adscendmedia.com
-getcashforsurveys.com
-glamsham.com
-dressupgames.com
-lifo.gr
-37signals.com
-pdfonline.com
-flipkey.com
-epochtimes.com
-futhead.com
-inlinkz.com
-fx-trend.com
-yasdl.com
-techbang.com
-narenji.ir
-szonline.net
-perfil.com.ar
-mywebface.com
-taknaz.ir
-tradera.com
-golem.de
-its-mo.com
-arabnet5.com
-freerepublic.com
-britannica.com
-deccanchronicle.com
-ohio.gov
-busuu.com
-pricecheck.co.za
-paltalk.com
-sportinglife.com
-google.sn
-meteomedia.com
-push2check.net
-ing-diba.de
-immoweb.be
-oregonlive.com
-ge.tt
-bbspink.com
-business2community.com
-viidii.com
-hrloo.com
-mglradio.com
-cosme.net
-xilu.com
-scbeasy.com
-biglots.com
-dhakatimes24.com
-spankbang.com
-hitleap.com
-proz.com
-php100.com
-tvtoday.de
-funnie.st
-velvet.hu
-dhnet.be
-capital.gr
-inosmi.ru
-healthkart.com
-amway.com
-madmimi.com
-dramafever.com
-oodle.com
-spreadshirt.com
-google.mg
-utarget.ru
-matomy.com
-medhelp.org
-cumlouder.com
-aliorbank.pl
-takepart.com
-myfreshnet.com
-adorama.com
-dhs.gov
-mivo.tv
-nchsoftware.com
-gnc.com
-spiceworks.com
-jeu.fr
-terra.com
-irishtimes.com
-kleiderkreisel.de
-ebay.be
-rt.ru
-radiofarda.com
-atrapalo.com
-southcn.com
-turkcell.com.tr
-themetapicture.com
-aujourdhui.com
-ato.gov.au
-pelis24.com
-saaid.net
-bradsdeals.com
-pirate101.com
-saturn.de
-thisissouthwales.co.uk
-cyberlink.com
-internationalredirects.com
-radardedescontos.com.br
-rapidcontentwizard.com
-kabum.com.br
-webrankinfo.com
-kiabi.com
-farecompare.com
-xinjunshi.com
-vidxden.com
-pvrcinemas.com
-chachaba.com
-wanmei.com
-alternet.org
-rozklad-pkp.pl
-omniture.com
-childrensplace.com
-menards.com
-zhcw.com
-ouest-france.fr
-vitorrent.org
-xanga.com
-zbozi.cz
-radioshack.com
-startv.in
-affiliatewindow.com
-gov.on.ca
-grainger.com
-3rat.com
-indeed.co.za
-rtbf.be
-strava.com
-disneystore.com
-travelagency.travel
-ekitan.com
-volagratis.com
-yiiframework.com
-dramacrazy.net
-addtoany.com
-uzmantv.com
-uline.com
-fitnessmagazine.com
-khmerload.com
-italiafilm.tv
-baseball-reference.com
-neopets.com
-multiupload.nl
-lakii.com
-downloadmaster.ru
-babbel.com
-gossip-tv.gr
-laban.vn
-computerbase.de
-juyouqu.com
-markt.de
-linuxquestions.org
-giveawayoftheday.com
-176.com
-homemademoviez.com
-huffingtonpost.fr
-movieweb.com
-pornzeus.com
-posta.com.tr
-biography.com
-bukkit.org
-spirit.com
-vemale.com
-elnuevodia.com
-pof.com.br
-iranproud.com
-molodost.bz
-netcarshow.com
-ardmediathek.de
-fabfurnish.com
-myfreeblack.com
-antichat.ru
-crocko.com
-b5m.com
-entrance-exam.net
-benaughty.com
-sierratradingpost.com
-apartmentguide.com
-slimspots.com
-sondakika.com
-glamour.com
-ilyke.net
-mybroadband.co.za
-alaskaair.com
-virtualtourist.com
-rexxx.com
-fullhdfilmizle.org
-starpulse.com
-winkal.com
-ad-feeds.net
-irannaz.com
-elahmad.com
-dealspl.us
-moikrug.ru
-olx.com.mx
-rd.com
-newone.org
-naijapals.com
-forgifs.com
-fsjgw.com
-nicoviewer.net
-topeleven.com
-peerfly.com
-softportal.com
-clker.com
-tehran98.com
-weather2umbrella.com
-lookbook.nu
-futureshop.ca
-blackpeoplemeet.com
-adworkmedia.com
-entire.xxx
-bitbucket.org
-transfermarkt.co.uk
-moshimonsters.com
-baimao.com
-khanacademy.org
-2chan.net
-adopteunmec.com
-mochimedia.com
-strawberrynet.com
-gdeivse.com
-speckyboy.com
-radical-foto.ru
-softcoin.com
-cnews.ru
-ubs.com
-lankasri.com
-cylex.de
-imtranslator.net
-homeoffice.gov.uk
-answerbag.com
-chainreactioncycles.com
-sportal.bg
-livemaster.ru
-mercadolibre.com.pe
-mentalfloss.com
-google.am
-mawaly.com
-douban.fm
-abidjan.net
-pricegong.com
-brother.com
-basspro.com
-popsci.com
-olx.com.ar
-python.org
-voetbalzone.nl
-aztecaporno.com
-d-h.st
-voyeurweb.com
-storenvy.com
-aftabir.com
-imgsrc.ru
-peru.com
-mindbodygreen.com
-stereotude.com
-ar15.com
-gogecapital.com
-xipin.me
-gvt.com.br
-today.it
-mastercard.com.au
-hobbyking.com
-hawkhost.com
-thebump.com
-alpari.ru
-gamma-ic.com
-mundome.com
-quotev.com
-animaljam.com
-ohozaa.com
-sayyac.com
-kobobooks.com
-muslima.com
-digsitesvalue.net
-colourlovers.com
-uludagsozluk.com
-mercadolibre.com.uy
-oem.com.mx
-self.com
-kyohk.net
-dillards.com
-eduu.com
-replays.net
-bnpparibasfortis.be
-express.co.uk
-guaixun.com
-750g.com
-craveonline.com
-markafoni.com
-ename.com
-abercrombie.com
-noticiaaldia.com
-seniorpeoplemeet.com
-dhingana.com
-prokerala.com
-iefimerida.gr
-wprazzi.com
-pantipmarket.com
-vueling.com
-newsonlineweekly.com
-cr173.com
-ecp888.com
-diary.ru
-pervclips.com
-sudaneseonline.com
-personal.com.ar
-articlesnatch.com
-mitbbs.com
-techsupportalert.com
-filepost.com
-unblockyoutube.co.uk
-hasznaltauto.hu
-dmv.org
-port.hu
-anastasiadate.com
-adtgs.com
-namejet.com
-ally.com
-djmaza.com
-asstr.org
-corel.com
-interfax.ru
-rozee.pk
-akinator.com
-dominos.co.in
-boardgamegeek.com
-teamliquid.net
-sbrf.ru
-l99.com
-eatingwell.com
-mid-day.com
-blinkogold.it
-rosbalt.ru
-islammemo.cc
-bettycrocker.com
-womenshealthmag.com
-asandownload.com
-twitcasting.tv
-10and9.com
-youngleafs.com
-saharareporters.com
-overclock.net
-mapsgalaxy.com
-internetslang.com
-sokmil.com
-yousendit.com
-forex-mmcis.com
-vador.com
-pagewash.com
-pringotrack.com
-cpmstar.com
-yxdown.com
-surfingbird.ru
-identi.li
-n4hr.com
-elitetorrent.net
-livechatinc.com
-anzhi.com
-2checkout.com
-bancoestado.cl
-epson.com
-twodollarclick.com
-okaz.com.sa
-china-sss.com
-xforex.com
-salliemae.com
-acunn.com
-navyfederal.org
-forumactif.com
-affaire.com
-mediatemple.net
-qdmm.com
-urlm.co
-toofab.com
-yola.com
-sheldonsfans.com
-piratestreaming.com
-frontier.com
-businesswire.com
-rue89.com
-yenisafak.com.tr
-wikimart.ru
-xpressvids.info
-medicalnewstoday.com
-express.de
-grid.mk
-mass.gov
-onlinefinder.net
-yllix.com
-aksam.com.tr
-telegraf.rs
-templatic.com
-kandao.com
-policymic.com
-farfesh.com
-alza.cz
-judgeporn.com
-townwork.net
-3dcartstores.com
-marketingland.com
-okooo.com
-siteduzero.com
-cellbazaar.com
-omb100.com
-danarimedia.com
-nlcafe.hu
-qz.com
-indiapost.gov.in
-kinogo.net
-neverblue.com
-spyfu.com
-shindanmaker.com
-bankpasargad.com
-internetautoguide.com
-allover30.com
-metric-conversions.org
-carid.com
-mofos.com
-kanald.com.tr
-mobikwik.com
-checkpagerank.net
-hotscripts.com
-hornywife.com
-prixmoinscher.com
-worldbank.org
-wsodownloads.info
-his-j.com
-powned.tv
-redmondpie.com
-molotok.ru
-whatmobile.com.pk
-wiziq.com
-excelsior.com.mx
-tradetang.com
-terra.es
-sdchina.com
-rai.tv
-indiansexstories.net
-upbulk.com
-surveygizmo.com
-ulta.com
-tera-europe.com
-tuoitre.vn
-onedio.com
-favim.com
-seo-fast.ru
-twitterfeed.com
-trustedreviews.com
-ztgame.com
-radiojavan.com
-fun698.com
-126.net
-indiaglitz.com
-jdouga.com
-lofter.com
-mysavings.com
-snapfish.com
-i-sux.com
-cebbank.com
-ethnos.gr
-desktop2ch.tv
-expedia.ca
-kinja.com
-rusfolder.com
-expat-blog.com
-8teenxxx.com
-variety.com
-natemat.pl
-niazpardaz.com
-gezginler.net
-baur.de
-tv2.no
-realgm.com
-zamzar.com
-freecharge.in
-ahlamontada.com
-salespider.com
-beanfun.com
-cleveland.com
-truecaller.com
-walmart.ca
-fanbox.com
-designmodo.com
-frip.com
-sammobile.com
-minnano-av.com
-bri.co.id
-creativebloq.com
-anthropologie.com
-afpbb.com
-kingsera.ir
-songspk.co
-sexsearch.com
-dailydot.com
-hayah.cc
-angolotesti.it
-si.kz
-allthingsd.com
-paddypower.com
-canadapost.ca
-qq.cc
-amctheatres.com
-alltop.com
-allkpop.com
-nalog.ru
-dynadot.com
-copart.com
-mexat.com
-skelbiu.lt
-kerala.gov.in
-cathaypacific.com
-clip2ni.com
-tribune.com
-acidcow.com
-amkspor.com
-shiksha.com
-180upload.com
-vietgiaitri.com
-sportsauthority.com
-banki.ir
-vancouversun.com
-hackforums.net
-t-mobile.de
-simplyrecipes.com
-crazyhomesex.com
-thehindubusinessline.com
-kriesi.at
-deyi.com
-plimus.com
-websyndic.com
-express.com
-dougasouko.com
-mmstat.com
-womai.com
-alrajhibank.com.sa
-ice-porn.com
-benchmarkemail.com
-ringcentral.com
-erail.in
-poptropica.com
-search.ch
-meteo.it
-adriver.ru
-ratp.fr
-orgasm.com
-pornme.com
-gameinformer.com
-woobox.com
-advertising.com
-flyflv.com
-chinaren.com
-tube2012.com
-ikhwanonline.com
-iwebtool.com
-ucdavis.edu
-boyfriendtv.com
-rurubu.travel
-kabam.com
-talkingpointsmemo.com
-detnews.com
-sibnet.ru
-camztube.net
-madamenoire.com
-evz.ro
-staseraintv.com
-che168.com
-kidshealth.org
-m24.ru
-zenfolio.com
-webtretho.com
-postjung.com
-supersport.com
-cshtracker.com
-jeuxjeuxjeux.fr
-foxtv.es
-postjoint.com
-podnapisi.net
-prav.tv
-realmadrid.com
-mbs-potsdam.de
-tim.it
-uplus.metroer.com
-esquire.com
-ooopic.com
-castorama.fr
-afamily.vn
-findlaw.com
-smartpassiveincome.com
-sa.ae
-hemnet.se
-diytrade.com
-weblancer.net
-zapmeta.de
-bizsugar.com
-banesco.com
-ideeli.com
-lnx.lu
-divxplanet.com
-aircanada.com
-uzise.com
-sabay.com.kh
-football365.com
-crazydomains.com.au
-qxox.org
-thesmokinggun.com
-w8n3.info
-po.st
-debian.org
-flypgs.com
-craigslist.co.in
-islamway.net
-debate.com.mx
-bitdefender.com
-listindiario.com
-123telugu.com
-ilbe.com
-wordlinx.com
-ebc.com.br
-pr.gov.br
-videoyoum7.com
-ets.org
-exteen.com
-comicbookresources.com
-grammarly.com
-pdapi.com
-adultflash01.com
-orlandosentinel.com
-24option.com
-moviepilot.de
-rfa.org
-crateandbarrel.com
-srv2trking.com
-mercusuar.info
-dofus.com
-myfxbook.com
-madmovs.com
-myffi.biz
-peru21.pe
-bollywoodlife.com
-gametracker.com
-terra.com.mx
-antenam.info
-ihotelier.com
-hypebeast.com
-dramasonline.com
-wordtracker.com
-thefrisky.com
-meritnation.com
-irna.ir
-trovit.com
-cngold.org
-optymalizacja.com
-flexmls.com
-softarchive.net
-divxonline.info
-malaysian-inc.com
-dsw.com
-fantastigames.com
-mattcutts.com
-ziprealty.com
-saavn.com
-ruporn.tv
-e-estekhdam.com
-novafile.com
-tomsguide.fr
-tomshardware.co.uk
-crosswalk.com
-businessdictionary.com
-sharesix.com
-travian.cl
-indiastudychannel.com
-m7shsh.com
-hbogo.com
-888casino.it
-keywordspy.com
-pureleverage.com
-photodune.net
-foreignpolicy.com
-shiftdelete.net
-living360.net
-paixie.net
-barstoolsports.com
-aemet.es
-local.ch
-spermyporn.com
-tasnimnews.com
-imgserve.net
-huawei.com
-pik.ba
-info-dvd.ru
-2domains.ru
-sextube.fm
-searchrocket.info
-dicio.com.br
-ittefaq.com.bd
-fileserve.com
-genteflow.com
-5giay.vn
-elbadil.com
-wizaz.pl
-cyclingnews.com
-southparkstudios.com
-hangseng.com
-mapsofworld.com
-gaokao.com
-antarvasna.com
-televisa.com
-dressupwho.com
-goldprice.org
-directlyrics.com
-v2cigar.net
-peopleclick.com
-moudamepo.com
-baijob.com
-geni.com
-huangye88.com
-phun.org
-kasikornbankgroup.com
-angrymovs.com
-bibliocommons.com
-melateiran.com
-gigya.com
-17ok.com
-xdowns.com
-tportal.hr
-dreamteammoney.com
-prevention.com
-terra.cl
-blinklist.com
-51seer.com
-ruelsoft.com
-kulichki.net
-tatatele.in
-mybloggertricks.com
-ma-bimbo.com
-ftchinese.com
-sergey-mavrodi-mmm.net
-wp.tv
-chevrolet.com
-razerzone.com
-submanga.com
-thomson.co.uk
-syosetu.org
-olx.com
-vplay.ro
-rtnn.net
-55.la
-instructure.com
-lvse.com
-hvg.hu
-androidpolice.com
-cookinglight.com
-madadsmedia.com
-inews.gr
-ktxp.com
-socialsecurity.gov
-equifax.com
-ceskatelevize.cz
-gaaks.com
-chillingeffects.org
-komando.com
-nowpublic.com
-khanwars.ae
-berlin.de
-bleepingcomputer.com
-military.com
-zero10.net
-onekingslane.com
-beget.ru
-get-tune.net
-freewebs.com
-pcfinancial.ca
-sparknotes.com
-tinychat.com
-luxup.ru
-geforce.com
-tatts.com.au
-alweeam.com.sa
-123-reg.co.uk
-sexyswingertube.com
-groupon.es
-guardianlv.com
-hypovereinsbank.de
-usc.edu
-ard.de
-hoovers.com
-tdameritrade.com
-userscripts.org
-app111.com
-al.com
-op.fi
-adbkm.com
-pivithurutv.info
-haber3.com
-shatel.ir
-camonster.com
-weltbild.de
-advanceautoparts.com
-mplssaturn.com
-weeklystandard.com
-popscreen.com
-freelifetimefuckbook.com
-peixeurbano.com.br
-2258.com
-proxfree.com
-zend.com
-citehr.com
-gadyd.com
-tvspielfilm.de
-skapiec.pl
-9see.com
-cndns.com
-hurriyetemlak.com
-census.gov
-collider.com
-cinaplay.com
-aq.com
-aolsearch.com
-ce4arab.com
-cbi.ir
-cjol.com
-brandporno.com
-yicheshi.com
-mydealz.de
-xiachufang.com
-sun-sentinel.com
-flashkhor.com
-join.me
-hankyung.com
-oneandone.co.uk
-derwesten.de
-gammae.com
-webadultdating.biz
-pokerstars.com
-fucked-sex.com
-antaranews.com
-banorte.com
-travian.it
-msu.edu
-ozbargain.com.au
-77vcd.com
-bestooxx.com
-siemens.com
-en-japan.com
-akbank.com
-srf.ch
-meijer.com
-htmldrive.net
-peoplestylewatch.com
-boards.ie
-zhulong.com
-svyaznoybank.ru
-myfilestore.com
-sucuri.net
-redflagdeals.com
-javascriptkit.com
-edreams.fr
-wral.com
-togetter.com
-dmi.dk
-thinkdigit.com
-barclaycard.co.uk
-comm100.com
-christianbook.com
-popularmechanics.com
-taste.com.au
-tripadvisor.ru
-colissimo.fr
-gdposir.info
-rarlab.com
-dcnepalevent.com
-sagepub.com
-markosweb.com
-france3.fr
-mindbodyonline.com
-yapo.cl
-0-6.com
-dilbert.com
-searchqu.com
-usa.gov
-vatandownload.com
-nastymovs.com
-santanderrio.com.ar
-notebookcheck.net
-canalplus.fr
-epa.gov
-disp.cc
-hotsales.net
-interpals.net
-vz.ru
-flyertalk.com
-pjmedia.com
-solomid.net
-megaplan.ru
-hatenablog.com
-getsatisfaction.com
-hotline.ua
-alternativeto.net
-hipfile.com
-247sports.com
-phpnuke.org
-indiaresults.com
-prisjakt.nu
-1tvlive.in
-e-mai.net
-trafficg.com
-ojogo.pt
-totaldomination.com
-eroino.net
-network-tools.com
-unibytes.com
-seriouseats.com
-twicsy.com
-smbc-card.com
-toocle.com
-unbounce.com
-2tu.cc
-computerworld.com
-clicktrackprofit.com
-serialu.net
-realfarmacy.com
-metrodeal.com
-binzhi.com
-smilebox.com
-coderanch.com
-uptodown.com
-vbulletin.com
-teasernet.com
-admob.com
-fingerhut.com
-urlopener.com
-vi.nl
-expedia.de
-thekrazycouponlady.com
-linezing.com
-metropcs.com
-draugas.lt
-minecraftdl.com
-airberlin.com
-eelly.com
-siamsport.co.th
-e-junkie.com
-gulte.com
-lazada.com.ph
-cnwnews.com
-tekstowo.pl
-flavorwire.com
-settrade.com
-francetv.fr
-experian.com
-bravenet.com
-mytoys.de
-inkthemes.com
-brobible.com
-sarenza.com
-curse.com
-7sur7.be
-iberia.com
-trovit.es
-eiga.com
-getuploader.com
-sevendollarptc.com
-amadeus.com
-thedailystar.net
-gofuckbiz.com
-codepen.io
-virginia.gov
-linguee.fr
-space.com
-astrology.com
-whmcs.com
-blogher.com
-netpnb.com
-mojo-themes.com
-cam4.es
-bestwestern.com
-gencat.cat
-healthcentral.com
-ru-board.com
-tjsp.jus.br
-scene7.com
-bukalapak.com
-intporn.com
-xe.gr
-leprosorium.ru
-dytt8.net
-wpcentral.com
-fasttrafficformula.com
-hugefiles.net
-you-sex-tube.com
-naukrigulf.com
-5173.com
-comicvip.com
-jossandmain.com
-motherjones.com
-planet.fr
-thomascook.com
-deseretnews.com
-aawsat.com
-huntington.com
-desimartini.com
-maloumaa.blogspot.com
-rutgers.edu
-gratisjuegos.org
-carsforsale.com
-filestore72.info
-neowin.net
-ilgiornale.it
-download0098.com
-providesupport.com
-postini.com
-sinowaypromo.com
-watchop.com
-docusign.net
-sourcenext.com
-finviz.com
-babyoye.com
-andhrajyothy.com
-gamezer.com
-baozoumanhua.com
-niusnews.com
-yabancidiziizle.net
-fodors.com
-moonsy.com
-lidl.it
-betanews.com
-escapistmagazine.com
-markethealth.com
-clicksure.com
-aircel.com
-metacrawler.com
-aeat.es
-allafrica.com
-watchseries-online.eu
-adpost.com
-adac.de
-similarweb.com
-offervault.com
-uolhost.com.br
-moviestarplanet.com
-overclockers.ru
-rocketlanguages.com
-finya.de
-shahvani.com
-firmy.cz
-incometaxindia.gov.in
-ecostream.tv
-pcwelt.de
-arcadesafari.com
-shoghlanty.com
-videosection.com
-centauro.com.br
-eroanimedouga.net
-orientaltrading.com
-ogone.com
-sexlog.com
-hotair.com
-egypt.gov.eg
-thomasnet.com
-virustotal.com
-hayneedle.com
-fatburningfurnace.com
-lovedgames.com
-23us.com
-trafficcaptain.com
-v2cigs.com
-teknosa.com.tr
-skrill.com
-puritanas.com
-selfgrowth.com
-ikco.com
-cuisineaz.com
-causes.com
-democraticunderground.com
-placesexy.com
-expedia.co.uk
-www-com.co
-topmongol.com
-hikaritube.com
-amakings.com
-fxstreet.com
-consultant.ru
-sacbee.com
-supercheats.com
-sofunnylol.com
-muzy.com
-sparda.de
-caughtoffside.com
-chinawomendating.asia
-xmeeting.com
-google.al
-sovereignbank.com
-animeflv.net
-sky.de
-huatu.com
-payscale.com
-quotidiano.net
-pol.ir
-digital-photography-school.com
-screencrush.com
-netgear.com
-thebiglistofporn.com
-similarsitesearch.com
-peb.pl
-lanrentuku.com
-ksu.edu.sa
-tradetracker.com
-avito.ma
-projectfree.tv
-cmu.edu
-imore.com
-tickld.com
-fitday.com
-dulcebank.com
-careerdonkey.com
-pf.pl
-otzovik.com
-baltimoresun.com
-jobvite.com
-ratemyprofessors.com
-bancodevenezuela.com
-linkafarin.com
-ufxmarkets.com
-lavozdegalicia.es
-99bill.com
-punyu.com
-otodom.pl
-entireweb.com
-fastshop.com.br
-imgnip.com
-goodlife.com
-caringbridge.org
-pistonheads.com
-gun.az
-1and1.es
-photofunia.com
-nme.com
-carfax.com
-gutenberg.org
-youxixiazai.org
-webmastersitesi.com
-skynet.be
-afrointroductions.com
-mp3slash.net
-netzwelt.de
-ecrater.com
-livemint.com
-worldwinner.com
-echosign.com
-cromaretail.com
-freewebcamporntube.com
-admin.ch
-allstate.com
-photoscape.org
-cv-library.co.uk
-voici.fr
-wdr.de
-pbase.com
-mycenturylink.com
-sonicomusica.com
-schema.org
-smashwords.com
-al3ab.net
-muryouav.net
-mocospace.com
-fundsxpress.com
-chrisc.com
-poemhunter.com
-cupid.com
-timescity.com
-banglamail24.com
-motika.com.mk
-sec.gov
-whatculture.com
-namepros.com
-vsemayki.ru
-hip2save.com
-hotnews.ro
-vietbao.vn
-inazumanews2.com
-irokotv.com
-appthemes.com
-tirerack.com
-maxpark.com
-successfactors.com
-sba.gov
-hk-porno.com
-setlinks.ru
-travel24.com
-qatarliving.com
-hotlog.ru
-rapmls.com
-qualityhealth.com
-linkcollider.com
-kashtanka.com
-hightail.com
-appszoom.com
-armagedomfilmes.biz
-pnu.ac.ir
-globalbux.net
-ebay.com.hk
-ladenzeile.de
-thedomainfo.com
-naosalvo.com.br
-perfectcamgirls.com
-verticalresponse.com
-khabardehi.com
-oszone.net
-teamtreehouse.com
-humanservices.gov.au
-bostonherald.com
-kafeteria.pl
-society6.com
-gamevicio.com
-crazyegg.com
-logitravel.com
-williams-sonoma.com
-htmlgoodies.com
-fontanka.ru
-islamuon.com
-tcs.com
-elyrics.net
-vip-prom.net
-jobstreet.com.ph
-designfloat.com
-lavasoft.com
-tianjinwe.com
-telelistas.net
-taglol.com
-jacquieetmicheltv.net
-esprit-online-shop.com
-theeroticreview.com
-boo-box.com
-wandoujia.com
-vgsgaming.com
-yourtango.com
-tianji.com
-jpost.com
-mythemeshop.com
-seattlepi.com
-bultannews.com
-youlikehits.com
-partycity.com
-18qt.com
-yuvutu.com
-gq.com
-wiziwig.tv
-cinejosh.com
-technet.com
-vatanbilgisayar.com
-guangjiela.com
-siteheart.com
-in.gov
-nulled.cc
-mafiashare.net
-tizag.com
-hkjc.com
-restaurant.com
-consumersurveygroup.org
-spin.de
-silverlinetrips.com
-triberr.com
-gamesgirl.net
-qqt38.com
-xiaoshuomm.com
-theopen.com
-campograndenews.com.br
-soonnight.com
-safaribooksonline.com
-main-hosting.com
-caclubindia.com
-alibado.com
-autorambler.ru
-tnt.com
-chatango.com
-satrk.com
-pagesperso-orange.fr
-houseoffraser.co.uk
-nullrefer.com
-work.ua
-inagist.com
-kaban.tv
-cnxad.com
-tarad.com
-masteetv.com
-noblesamurai.com
-lifehacker.ru
-anakbnet.com
-google.co.ug
-webcamsex.nl
-kaoyan.com
-ml.com
-up.nic.in
-bounceme.net
-netfirms.com
-idokep.hu
-wambie.com
-funpatogh.com
-bcash.com.br
-sedo.co.uk
-noupe.com
-mydirtyhobby.com
-neswangy.net
-downloadprovider.me
-utah.gov
-consumerintelligenceusa.com
-itimes.com
-picroma.com
-lustagenten.com
-kemdiknas.go.id
-sitepronews.com
-ruseller.com
-tradecarview.com
-favstar.fm
-bestbuy.ca
-yelp.ca
-stop-sex.com
-rewity.com
-qiqigames.com
-suntimes.com
-hardware.fr
-rxlist.com
-bgr.com
-zalora.co.id
-mandatory.com
-collarme.com
-mycommerce.com
-holidayiq.com
-filecloud.io
-vconnect.com
-66163.com
-tlen.pl
-mmbang.com
-7c.com
-digitalriver.com
-24video.net
-worthofweb.com
-clasicooo.com
-greatschools.net
-tagesanzeiger.ch
-video.az
-osu.edu
-careers360.com
-101.ru
-conforama.fr
-apollo.lv
-netcq.net
-jofogas.hu
-niftylink.com
-midwayusa.com
-collegeteensex.net
-search.com
-naftemporiki.gr
-sainsburys.co.uk
-fitsugar.com
-ifixit.com
-uid.me
-malwarebytes.org
-maxbounty.com
-mensfitness.com
-rtl.be
-yidio.com
-dostorasly.com
-abovetopsecret.com
-sm3na.com
-cam.ac.uk
-gamegape.com
-ocioso.com.br
-register.com
-wwitv.com
-ishangman.com
-gry-online.pl
-ogli.org
-redbull.com
-dyn.com
-freeservers.com
-brandsoftheworld.com
-lorddownload.com
-mybet.com
-brothalove.com
-inchallah.com
-lottomatica.it
-indiamp3.com
-qianbao666.com
-zurb.com
-synxis.com
-baskino.com
-swefilmer.com
-hotstartsearch.com
-cloudmoney.info
-polldaddy.com
-moheet.com
-idhostinger.com
-mp3chief.com
-tao123.com
-channelnewsasia.com
-galeon.com
-aviasales.ru
-datafilehost.com
-travian.com.eg
-ebookee.org
-filmstarts.de
-inccel.com
-chatroulette.com
-it-ebooks.info
-nix.ru
-antena3.ro
-mylifetime.com
-desitorrents.com
-mydigitallife.info
-aeropostale.com
-anilos.com
-macadogru.com
-premiere.fr
-estorebuilder.com
-eventim.de
-expert-offers.com
-deloitte.com
-thetimenow.com
-spicybigbutt.com
-gistmania.com
-pekao24.pl
-linkfeed.ru
-carnival.com
-apherald.com
-choicehotels.com
-revolvermaps.com
-digu.com
-yekmobile.com
-barbarianmovies.com
-poyopara.com
-vse.kz
-socialspark.com
-deutschepost.de
-nokaut.pl
-farpost.ru
-shoebuy.com
-1c-bitrix.ru
-pimproll.com
-startxchange.com
-seocentro.com
-kporno.com
-izvestia.ru
-bathandbodyworks.com
-allhyipmonitors.com
-europe1.fr
-charter.com
-sixflags.com
-abcjuegos.net
-wind.it
-femjoy.com
-humanmetrics.com
-myrealgames.com
-cosmiq.de
-bangbrosteenporn.com
-thepetitionsite.com
-laprensa.com.ni
-investors.com
-techpowerup.com
-prosperityteam.com
-autogidas.lt
-state.ny.us
-techbargains.com
-takvim.com.tr
-kko-appli.com
-liex.ru
-cafe24.com
-definebabe.com
-egirlgames.net
-avangard.ru
-sina.com.hk
-freexcafe.com
-vesti.bg
-francetvinfo.fr
-mathsisfun.com
-easymobilerecharge.com
-dapink.com
-propellerads.com
-devshed.com
-clip.vn
-vidivodo.com
-blogspot.dk
-foxnewsinsider.com
-instapaper.com
-premierleague.com
-elo7.com.br
-teenee.com
-clien.net
-computrabajo.com.co
-komputronik.pl
-livesurf.ru
-123cha.com
-cgg.gov.in
-leadimpact.com
-socialmonkee.com
-speeddate.com
-bet-at-home.com
-huanqiuauto.com
-tadawul.com.sa
-ucsd.edu
-fda.gov
-cint.com
-homedepot.ca
-ciao.de
-gigglesglore.com
-warframe.com
-prosieben.de
-vistaprint.in
-mapple.net
-usafis.org
-truelife.com
-1o26.com
-boldsky.com
-freeforums.org
-lolnexus.com
-ti-da.net
-handelsbanken.se
-khamsat.com
-futbol24.com
-wikifeet.com
-dev-point.com
-ibotoolbox.com
-indeed.de
-ct10000.com
-appleinsider.com
-lyoness.net
-vodafone.com.eg
-aifang.com
-tripadvisor.com.br
-hbo.com
-pricerunner.com
-4everproxy.com
-fc-perspolis.com
-themobileindian.com
-gimp.org
-novayagazeta.ru
-dnfight.com
-coco.fr
-thestudentroom.co.uk
-tiin.vn
-dailystar.co.uk
-unfollowed.me
-aljazeerasport.net
-nasygnale.pl
-somethingawful.com
-scamadviser.com
-mcanime.net
-9stock.com
-boostmobile.com
-oyunkolu.com
-beliefnet.com
-lyrics007.com
-rtv.net
-hasbro.com
-vcp.ir
-fj-p.com
-jetbrains.com
-cpalead.com
-zetaboards.com
-sbobet.com
-v2ex.com
-toggle.com
-lanebryant.com
-girlgames4u.com
-amadershomoy1.com
-planalto.gov.br
-news-choice.net
-sarkarinaukriblog.com
-sudouest.fr
-zdomo.com
-egy-nn.com
-pizzaplot.com
-topgear.com
-sony.co.in
-nosv.org
-beppegrillo.it
-sakshieducation.com
-temagay.com
-stepashka.com
-tmart.com
-readwrite.com
-tudiscoverykids.com
-belfius.be
-submitexpress.com
-autoscout24.ch
-aetna.com
-torrent-anime.com
-superhqporn.com
-kaufda.de
-adorocinema.com
-burning-seri.es
-rlsbb.com
-housing.co.in
-invisionfree.com
-istruzione.it
-desk.com
-lyricsmint.com
-taohuopu.com
-silverdaddies.com
-gov.cl
-vtc.vn
-tanea.gr
-labirint.ru
-sns104.com
-bigpicture.ru
-marketo.com
-ismmagic.com
-c-sharpcorner.com
-synacor.com
-answered-questions.com
-prlog.ru
-vodafone.com.tr
-thenews.com.pk
-galaxygiftcard.com
-job-search-engine.com
-se.pl
-consumercomplaints.in
-265.com
-cba.pl
-humoron.com
-uscourts.gov
-blog.pl
-youtu.be
-play4free.com
-blizko.ru
-uswebproxy.com
-winning-play.com
-yourstory.in
-tinmoi.vn
-yongchuntang.net
-artofmanliness.com
-nadaguides.com
-ndr.de
-kuidle.com
-hopy.com
-roi.ru
-sdpnoticias.com
-nation.com
-gnu.org
-vogue.co.uk
-letsebuy.com
-preloved.co.uk
-yatedo.com
-rs-online.com
-kino-teatr.ru
-meeticaffinity.fr
-clip.dj
-compete.com
-pravda.sk
-oursogo.com
-designyourway.net
-elcorreo.com
-williamhill.es
-lavenir.net
-voyage-prive.es
-teambeachbody.com
-sportdog.gr
-klicktel.de
-ktonanovenkogo.ru
-sbwire.com
-pearsoncmg.com
-bankifsccode.com
-thenationonlineng.net
-bangbros1.com
-tarot.com
-acdsee.com
-blogos.com
-dinnerwithmariah.com
-japan-women-dating.com
-sarzamindownload.com
-timesonline.co.uk
-okbuy.com
-sbb.ch
-mundogaturro.com
-meinvz.net
-trafficadbar.com
-9minecraft.net
-nextbigwhat.com
-eshetab.com
-meristation.com
-kalahari.com
-pimpandhost.com
-pbworks.com
-bokee.net
-google.ps
-seccionamarilla.com.mx
-foroactivo.com
-kalaydo.de
-gomaji.com
-exactseek.com
-cashtaller.ru
-blogspot.co.nz
-volvocars.com
-marathonbet.com
-hk-pub.com
-seriouslyfacts.me
-streetdirectory.com
-mediamasr.tv
-straitstimes.com
-promodj.com
-3dwwwgame.com
-autovit.ro
-ahlalhdeeth.com
-forum-auto.com
-stooorage.com
-mobilism.org
-hideref.org
-mn66.com
-internations.org
-sbicard.com
-dayoo.com
-biquge.com
-theme.wordpress.com
-mrdoob.com
-vpls.net
-alquma-a.com
-bankmillennium.pl
-mitele.es
-tro-ma-ktiko.blogspot.gr
-bookmark4you.com
-tencent.com
-bsi.ir
-fox.com
-payback.de
-tubepornfilm.com
-herold.at
-elperiodico.com
-lolesports.com
-hrs.de
-trustlink.ru
-pricemachine.com
-socialadr.com
-anandabazar.com
-jacquieetmicheltv2.net
-monster.de
-allposters.com
-blog.ir
-ad4game.com
-alkislarlayasiyorum.com
-ptcsolution.com
-moviepilot.com
-ddizi.org
-dmzj.com
-onvasortir.com
-ferronetwork.com
-seagate.com
-starmedia.com
-topit.me
-developpez.net
-papajogos.com.br
-btalah.com
-gateway.gov.uk
-fotki.com
-holidaylettings.co.uk
-rzeczpospolita.pl
-charter97.org
-robtex.com
-bestadbid.com
-unblog.fr
-archive.is
-microworkers.com
-vbulletin.org
-jetswap.com
-badoink.com
-adobeconnect.com
-cutt.us
-lovemake.biz
-xpress.com
-di.se
-jacquielawson.com
-sat1.de
-adshuffle.com
-homepage.com.tr
-treehugger.com
-selectornews.com
-dap-news.com
-tvline.com
-co188.com
-bfmtv.com
-nastygal.com
-cebupacificair.com
-spr.ru
-vazeh.com
-worldmarket.com
-americanlivewire.com
-befunky.com
-movie2k.tl
-coach.com
-whattoexpect.com
-share-online.biz
-fishwrapper.com
-aktifhaber.com
-downxsoft.com
-websurf.ru
-bbcgoodfood.com
-france2.fr
-gyakorikerdesek.hu
-lidovky.cz
-thithtoolwin.info
-psbc.com
-766.com
-co-operativebank.co.uk
-iwriter.com
-bravotv.com
-sbs.com.au
-dtiserv2.com
-watchever.de
-playhub.com
-globovision.com
-intereconomia.com
-poznan.pl
-comicbookmovie.com
-ocomico.net
-housetrip.com
-freewebsubmission.com
-karmaloop.com
-savevid.com
-lastpass.com
-yougou.com
-iafd.com
-casertex.com
-gmail.com
-modhoster.de
-post-gazette.com
-digikey.com
-torrentleech.org
-stamps.com
-lifestyleinsights.org
-pandawill.com
-wm-panel.com
-um-per.com
-straighttalk.com
-xpersonals.com
-bondfaro.com.br
-tvrage.com
-rockongags.com
-4jok.com
-zoom.com.br
-pixabay.com
-path.com
-hiphopdx.com
-ptbus.com
-fussball.de
-windows.net
-adweek.com
-kraftrecipes.com
-redtram.com
-youravon.com
-ladepeche.fr
-jiwu.com
-hobbylobby.com
-otzyv.ru
-sky-fire.com
-fileguru.com
-vandal.net
-haozu.com
-laxteams.net
-cpvtrack202.com
-libraryreserve.com
-tvigle.ru
-hoopshype.com
-worldcat.org
-eventful.com
-nettiauto.com
-generalfiles.org
-ojooo.com
-thatisnotasport.com
-thepioneerwoman.com
-social-bookmarking.net
-lookforithere.info
-americanapparel.net
-protv.ro
-jeux-gratuits.com
-tomoson.com
-jpn.org
-cpz.to
-vrisko.gr
-cbox.ws
-vandelaydesign.com
-macmillandictionary.com
-eventure.com
-niniweblog.com
-ecwid.com
-garuda-indonesia.com
-education.com
-natalie.mu
-gigsandfestivals.co.uk
-onlainfilm.ucoz.ua
-hotwords.com
-jagobd.com
-pageset.com
-sagepay.com
-runkeeper.com
-beeztube.com
-pinla.com
-blizzard.com
-unc.edu
-makememarvellous.com
-wer-weiss-was.de
-ubc.ca
-utoronto.ca
-avsforum.com
-newrelic.com
-orkut.co.in
-wawa-mania.ec
-ncsu.edu
-redhat.com
-nsdl.co.in
-lavoz.com.ar
-navy.mil
-mg.gov.br
-psychcentral.com
-ultipro.com
-unisa.ac.za
-sooperarticles.com
-wondershare.com
-wholefoodsmarket.com
-dumpaday.com
-littlewoods.com
-carscom.net
-meitu.com
-9lwan.com
-emailmeform.com
-arte.tv
-tribalfootball.com
-howtoforge.com
-cvent.com
-fujitsu.com
-silvergames.com
-fatlossfactor.com
-nusport.nl
-todo1.com
-see-tube.com
-lolspots.com
-sucksex.com
-encontreinarede.com
-myarabylinks.com
-v-39.net
-soompi.com
-mltdb.com
-websitetonight.com
-bu.edu
-lazada.co.th
-mature-money.com
-simplemachines.org
-tnt-online.ru
-disput.az
-flirtcafe.de
-d1net.com
-infoplease.com
-unseenimages.co.in
-downloadatoz.com
-norwegian.com
-youtradefx.com
-petapixel.com
-bytes.com
-ht.ly
-jobberman.com
-xenforo.com
-pomponik.pl
-siambit.org
-twoplustwo.com
-videoslasher.com
-onvista.de
-canstockphoto.com
-cash4flirt.com
-flashgames.it
-xxxdessert.com
-cda.pl
-costco.ca
-elnuevodiario.com.ni
-svtplay.se
-ftc.gov
-supersonicads.com
-openstreetmap.org
-chinamobile.com
-fastspring.com
-mcdonalds.com
-egloos.com
-mouser.com
-livemook.com
-woxiu.com
-pingler.com
-ruelsoft.org
-krone.at
-internetbookshop.it
-alibaba-inc.com
-kimsufi.com
-summitracing.com
-parsfootball.com
-standard.co.uk
-photoblog.pl
-bicaps.com
-digitalplayground.com
-zerochan.net
-whosay.com
-qualityseek.org
-say7.info
-rs.gov.br
-google.co.mz
-yourlustmovies.com
-zalando.nl
-jn.pt
-homebase.co.uk
-avis.com
-healthboards.com
-filmizlesene.com.tr
-shoutcast.com
-indiafreestuff.in
-avval.ir
-gamingwonderland.com
-adage.com
-asu.edu
-froma.com
-bezuzyteczna.pl
-workopolis.com
-extranetinvestment.com
-lablue.de
-geotauaisay.com
-bestchange.ru
-ptp22.com
-tehparadox.com
-ox.ac.uk
-radaris.com
-domdigger.com
-lizads.com
-chatvl.com
-elle.com
-soloaqui.es
-tubejuggs.com
-jsonline.com
-ut.ac.ir
-iitv.info
-runetki.tv
-hyundai.com
-turkiye.gov.tr
-jobstreet.com.sg
-jp-sex.com
-soccer.ru
-slashfilm.com
-couchtuner.eu
-quanfan.com
-porsche.com
-craftsy.com
-geizhals.at
-spartoo.it
-yxku.com
-vodonet.net
-photo.net
-raiffeisen.ru
-tablotala.com
-theaa.com
-idownloadblog.com
-rodfile.com
-alabout.com
-f1news.ru
-divxstage.eu
-itusozluk.com
-hicdma.com
-dota2lounge.com
-greensmut.com
-bharatiyamobile.com
-handycafe.com
-regarder-film-gratuit.com
-adultgeek.net
-yintai.com
-brasilescola.com
-verisign.com
-dnslink.com
-standaard.be
-cbengine.com
-pchealthboost.com
-dealdey.com
-cnnturk.com
-trutv.com
-tahrirnews.com
-getit.in
-jquerymobile.com
-girlgames.com
-alhayat.com
-ilpvideo.com
-stihi.ru
-skyscanner.ru
-jamejamonline.ir
-t3n.de
-rent.com
-telerik.com
-tandfonline.com
-argonas.com
-ludokado.com
-luvgag.com
-myspongebob.ru
-z5x.net
-allhyipmon.ru
-fanswong.com
-oddee.com
-guoli.com
-wpzoom.com
-2gheroon.com
-artisteer.com
-share-links.biz
-flightstats.com
-wisegeek.org
-shuangtv.net
-mylikes.com
-0zz0.com
-xiu.com
-pornizle69.com
-sendgrid.com
-theweek.com
-veetle.com
-theanimalrescuesite.com
-sears.ca
-tianpin.com
-thisdaylive.com
-myfunlife.com
-furaffinity.net
-politiken.dk
-youwatch.org
-lesoir.be
-toyokeizai.net
-centos.org
-sunnyplayer.com
-knuddels.de
-mturk.com
-egymodern.com
-semprot.com
-monsterhigh.com
-kompass.com
-olx.com.ve
-hq-xnxx.com
-whorush.com
-bongdaso.com
-centrelink.gov.au
-folha.com.br
-getjetso.com
-ycombinator.com
-chouti.com
-33lc.com
-hostgator.com.br
-emirates247.com
-itpub.net
-fsymbols.com
-bestproducttesters.com
-daodao.com
-virtuemart.net
-hindilinks4u.net
-nnm.me
-xplocial.com
-apartments.com
-ekolay.net
-doviz.com
-flixya.com
-3almthqafa.com
-zamalekfans.com
-imeigu.com
-wikibit.net
-windstream.net
-matichon.co.th
-appshopper.com
-socialbakers.com
-1popov.ru
-blikk.hu
-bdr130.net
-arizona.edu
-madhyamam.com
-mweb.co.za
-affiliates.de
-ebs.in
-bestgfx.com
-share-games.com
-informador.com.mx
-jobsite.co.uk
-carters.com
-kinghost.net
-us1.com
-archives.com
-forosdelweb.com
-siteslike.com
-thedailyshow.com
-68design.net
-imtalk.org
-visualwebsiteoptimizer.com
-glarysoft.com
-xhby.net
-email.cz
-amateurs-gone-wild.com
-davidwalsh.name
-finalfantasyxiv.com
-aa.com.tr
-legalzoom.com
-lifehack.org
-mca.gov.in
-hidrvids.com
-key.com
-thumbtack.com
-nujij.nl
-cinetux.org
-hmetro.com.my
-ignou.ac.in
-affilorama.com
-pokemon.com
-sportsnewsinternational.com
-geek.com
-larepublica.pe
-europacasino.com
-ok-porn.com
-tutorialzine.com
-google.com.bn
-site5.com
-trafficjunky.net
-xueqiu.com
-yournewscorner.com
-metrotvnews.com
-nichegalz.com
-job.com
-koimoi.com
-questionablecontent.net
-volaris.mx
-rakuten.de
-cyworld.com
-yudu.com
-zakon.kz
-msi.com
-darkxxxtube.com
-samakal.net
-appstorm.net
-vulture.com
-racingpost.com
-classicrummy.com
-iegallery.com
-cinemagia.ro
-nullpoantenna.com
-ihned.cz
-vdolady.com
-babes.com
-komli.com
-asianbeauties.com
-onedate.com
-adhitz.com
-jjgirls.com
-dot.tk
-autobild.de
-jobs-to-careers.com
-movietickets.com
-net4.in
-crutchfield.com
-subdivx.com
-sirarcade.com
-sitescoutadserver.com
-fantasy-rivals.com
-chegg.com
-sportsmansguide.com
-extremetech.com
-loft.com
-dirtyamateurtube.com
-socialsex.biz
-opensubtitles.us
-infomoney.com.br
-openstat.ru
-adlandpro.com
-trivago.de
-feiren.com
-lespac.com
-iceporn.com
-animehere.com
-klix.ba
-elitepvpers.com
-mrconservative.com
-tamu.edu
-startv.com.tr
-haber1903.com
-apa.tv
-idbi.com
-golfchannel.com
-pep.ph
-toukoucity.to
-empiremoney.com
-androidauthority.com
-ref4bux.com
-digitaljournal.com
-sporcle.com
-bzwbk.pl
-lalamao.com
-ziare.com
-cliti.com
-thatguywiththeglasses.com
-vodu.ch
-ycwb.com
-bls.gov
-1tubenews.com
-cl.ly
-ing.be
-bitterstrawberry.com
-fubar.com
-arabic-keyboard.org
-mejortorrent.com
-trendmicro.com
-ap7am.com
-windowsazure.com
-q8yat.com
-yyv.co
-tvoy-start.com
-creativetoolbars.com
-forrent.com
-mlstatic.com
-like4like.org
-alpha.gr
-amkey.net
-iwiw.hu
-routard.com
-teacherspayteachers.com
-ahashare.com
-ultoo.com
-oakley.com
-upforit.com
-trafficbee.com
-monster.co.uk
-boulanger.fr
-bloglines.com
-wdc.com
-el-nacional.com
-bloggertipstricks.com
-oreillyauto.com
-hotpads.com
-tubexvideo.com
-mudainodocument.com
-discoverpedia.info
-noobteens.com
-shockmansion.com
-qudsonline.ir
-mec.es
-vt.edu
-akelite.com
-travelandleisure.com
-sunnewsonline.com
-tok2.com
-truste.org
-2dehands.be
-hf365.com
-westelm.com
-real.gr
-downloadming.me
-citromail.hu
-fotocommunity.de
-zapjuegos.com
-aastocks.com
-unb.br
-adchakra.net
-check24.de
-vidto.me
-peekyou.com
-urssaf.fr
-alixixi.com
-winamp.com
-xianguo.com
-indiasextube.net
-fitnea.com
-telemundo.com
-webnode.cz
-kliksaya.com
-wikileaks.org
-myblog.it
-99wed.com
-adorika.com
-siliconrus.com
-dealmoon.com
-ricanadfunds.com
-vietcombank.com.vn
-chemistry.com
-reisen.de
-torlock.com
-wsop.com
-travian.co.id
-ipoll.com
-bpiexpressonline.com
-neeu.com
-beyondtherack.com
-blueidea.com
-tedata.net
-gamesradar.com
-big.az
-h-douga.net
-runnersworld.com
-lumfile.com
-u17.com
-badjojo.com
-nginx.org
-filmfanatic.com
-filmey.com
-mousebreaker.com
-mihanstore.net
-sharebuilder.com
-cnhan.com
-partnerwithtom.com
-synonym.com
-areaconnect.com
-one.lt
-mp3quran.net
-anz.co.nz
-buyincoins.com
-surfline.com
-packtpub.com
-informe21.com
-d4000.com
-blog.cz
-myredbook.com
-seslisozluk.net
-simple2advertise.com
-bookit.com
-eranico.com
-pakwheels.com
-x-rates.com
-ilmatieteenlaitos.fi
-vozforums.com
-galerieslafayette.com
-trafficswirl.com
-mql4.com
-torontosun.com
-lebuteur.com
-cruisecritic.com
-rateyourmusic.com
-binsearch.info
-nrj.fr
-megaflix.net
-dosug.cz
-stop55.com
-qqnz.com
-ibuonline.com
-jobego.com
-euro.com.pl
-quran.com
-ad1.ru
-avaz.ba
-eloqua.com
-educationconnection.com
-dbank.com
-whois.sc
-youmob.com
-101greatgoals.com
-livefyre.com
-sextubebox.com
-shooshtime.com
-tapuz.co.il
-auchan.fr
-pinkvilla.com
-perspolisnews.com
-scholastic.com
-google.mu
-forex4you.org
-mandtbank.com
-gnezdo.ru
-lulu.com
-anniezhang.com
-bharian.com.my
-comprafacil.com.br
-mmafighting.com
-autotrader.ca
-vectorstock.com
-convio.com
-ktunnel.com
-hbs.edu
-mindspark.com
-trovit.com.mx
-thomsonreuters.com
-yupptv.com
-fullsail.edu
-perfectworld.eu
-ju51.com
-newssnip.com
-livemocha.com
-nespresso.com
-uinvest.com.ua
-yazete.com
-malaysiaairlines.com
-clikseguro.com
-marksdailyapple.com
-topnewsquick.com
-ikyu.com
-mydocomo.com
-tampabay.com
-mo.gov
-oxfordjournals.org
-manageyourloans.com
-couponcabin.com
-mrmlsmatrix.com
-knowd.com
-ladbrokes.com
-ikoo.com
-devhub.com
-dropjack.com
-sadistic.pl
-8comic.com
-optimizepress.com
-ofweek.com
-donya-e-eqtesad.com
-arabam.com
-playtv.fr
-yourtv.com.au
-teamtalk.com
-createsend.com
-bitcointalk.org
-microcenter.com
-arcadeprehacks.com
-sublimetext.com
-posindonesia.co.id
-paymaster.ru
-ncore.cc
-wikisource.org
-notebooksbilliger.de
-nayakhabar.com
-tim.com.br
-leggo.it
-swoodoo.com
-perfectgirls.es
-beautystyleliving.com
-xmaduras.com
-e-shop.gr
-belastingdienst.nl
-urbia.de
-lovoo.net
-citizensbank.com
-gulesider.no
-zhongsou.net
-cinemablend.com
-joydownload.com
-telkom.co.id
-nangaspace.com
-panerabread.com
-cinechest.com
-flixjunky.com
-berlin1.de
-tabonito.pt
-snob.ru
-audiovkontakte.ru
-linuxmint.com
-freshdesk.com
-professionali.ru
-primelocation.com
-femina.hu
-jecontacte.com
-celebritytoob.com
-streamiz-filmze.com
-l-tike.com
-collegeconfidential.com
-hafiz.gov.sa
-mega-porno.ru
-ivoox.com
-lmgtfy.com
-pclab.pl
-preisvergleich.de
-weeb.tv
-tnews.ir
-wwtdd.com
-totalfilm.com
-girlfriendvideos.com
-wgt.com
-iu.edu
-topictorch.com
-wenweipo.com
-duitang.com
-madrid.org
-retrogamer.com
-pantheranetwork.com
-someecards.com
-visafone.com.ng
-infopraca.pl
-nrelate.com
-sia.az
-wallbase.cc
-shareflare.net
-sammydress.com
-goldesel.to
-thefiscaltimes.com
-freelogoservices.com
-dealigg.com
-babypips.com
-diynetwork.com
-porn99.net
-skynewsarabia.com
-eweb4.com
-fedoraproject.org
-nolo.com
-megabus.com
-fao.org
-am.ru
-sportowefakty.pl
-kidstaff.com.ua
-jhu.edu
-which.co.uk
-sextubehd.xxx
-swansonvitamins.com
-iran-eng.com
-fakenamegenerator.com
-gosong.net
-24open.ru
-123sdfsdfsdfsd.ru
-gotgayporn.com
-casadellibro.com
-ixwebhosting.com
-buyorbury.com
-getglue.com
-864321.com
-alivv.com
-competitor.com
-iheima.com
-submarinoviagens.com.br
-emailsrvr.com
-udacity.com
-mcafeesecure.com
-laposte.fr
-ppy.sh
-rumah.com
-pullbear.com
-pkt.pl
-jayde.com
-myjoyonline.com
-locopengu.com
-vsnl.net.in
-hornbunny.com
-royalcaribbean.com
-football.ua
-thaifriendly.com
-bankofthewest.com
-indianprice.com
-chodientu.vn
-alison.com
-eveonline.com
-blogg.se
-jetairways.com
-larousse.fr
-noticierodigital.com
-mkfst.com
-anyfiledownloader.com
-tiramillas.net
-telus.com
-paperblog.com
-songsterr.com
-entremujeres.com
-startsiden.no
-hotspotshield.com
-hosteurope.de
-ebags.com
-eenadupratibha.net
-uppit.com
-piaohua.com
-xxxymovies.com
-netbarg.com
-chip.com.tr
-xl.co.id
-kowalskypage.com
-afterdawn.com
-locanto.com
-liilas.com
-superboy.com
-indiavisiontv.com
-ixquick.com
-hotelium.com
-twsela.com
-newsmeback.com
-perfectliving.com
-laughingsquid.com
-designboom.com
-zigil.ir
-coachfactory.com
-kaboodle.com
-fastmail.fm
-threadless.com
-wiseconvert.com
-br.de
-promovacances.com
-wrzuta.pl
-fromdoctopdf.com
-ono.es
-zinio.com
-netcoc.com
-eanswers.com
-wallst.com
-ipiccy.com
-fastweb.it
-kaufmich.com
-groupon.co.za
-cyzo.com
-addic7ed.com
-alintibaha.net
-indiewire.com
-needforspeed.com
-e24.no
-hupso.com
-kathimerini.gr
-worldoffiles.net
-express.pk
-wieszjak.pl
-mobile.bg
-subway.com
-akhbarelyom.com
-thisoldhouse.com
-autoevolution.com
-public-api.wordpress.com
-airarabia.com
-powerball.com
-visa.com
-gendai.net
-gymboree.com
-tvp.pl
-sinhayasocialreader.com
-a963.com
-gamgos.ae
-fx678.com
-mp3round.com
-komonews.com
-contactcars.com
-pdftoword.com
-songtaste.com
-squareup.com
-newsevent24.com
-livestation.com
-oldertube.com
-rtl.fr
-gather.com
-liderendeportes.com
-thewrap.com
-viber.com
-reklama5.mk
-fonts.com
-hrsaccount.com
-bizcommunity.com
-favicon.cc
-totalping.com
-live365.com
-tlife.gr
-imasters.com.br
-n11.com
-iam.ma
-qq5.com
-tvboxnow.com
-limetorrents.com
-bancopopular.es
-ray-ban.com
-drweb.com
-hushmail.com
-resuelvetudeuda.com
-sharpnews.ru
-hellocoton.fr
-buysub.com
-homemoviestube.com
-utsandiego.com
-learn4good.com
-girlsgogames.ru
-talksport.co.uk
-fap.to
-teennick.com
-seitwert.de
-celebritymoviearchive.com
-sukar.com
-astromeridian.ru
-zen-cart.com
-1phads.com
-plaisio.gr
-cplusplus.com
-ewebse.com
-6eat.com
-payless.com
-subaonet.com
-dlisted.com
-kia.com
-lankahotnews.net
-vg247.com
-formstack.com
-jobs.net
-coolchaser.com
-blackplanet.com
-unionbank.com
-record.com.mx
-121ware.com
-inkfrog.com
-cnstock.com
-marineaquariumfree.com
-encuentra24.com
-mixturecloud.com
-yninfo.com
-lesnumeriques.com
-autopartswarehouse.com
-lijit.com
-ti.com
-umd.edu
-zdnet.co.uk
-begin-download.com
-showsiteinfo.us
-uchicago.edu
-whatsmyserp.com
-asos.fr
-ibosocial.com
-amorenlinea.com
-videopremium.tv
-trkjmp.com
-creativecow.net
-webartex.ru
-olx.com.ng
-overclockzone.com
-rongbay.com
-maximustube.com
-priberam.pt
-comsenz.com
-prensaescrita.com
-gameslist.com
-lingualeo.com
-epfoservices.in
-webbirga.net
-pb.com
-fineco.it
-highrisehq.com
-hotgoo.com
-netdoctor.co.uk
-domain.com
-aramex.com
-google.co.uz
-savings.com
-airtelbroadband.in
-postimees.ee
-wallsave.com
-df.gob.mx
-flashgames247.com
-libsyn.com
-goobike.com
-trivago.com
-android-hilfe.de
-anquan.org
-dota2.com
-vladtv.com
-oovoo.com
-mybrowsercash.com
-stafaband.info
-vsao.vn
-smithsonianmag.com
-feedblitz.com
-kibeloco.com.br
-burningcamel.com
-northwestern.edu
-tucows.com
-porn-granny-tube.com
-linksys.com
-avea.com.tr
-ams.se
-canadanepalvid.com
-venmobulo.com
-levi.com
-freshome.com
-loja2.com.br
-gameduell.de
-reserveamerica.com
-fakings.com
-polygon.com
-news.mn
-addictinginfo.org
-bonanza.com
-adlock.in
-apni.tv
-3m.com
-usingenglish.com
-sammsoft.com
-thevault.bz
-groupon.my
-banamex.com
-hualongxiang.com
-bodis.com
-io.ua
-minglebox.com
-forumspecialoffers.com
-remax.com
-makaan.com
-voglioporno.com
-chinaluxus.com
-parenting.com
-superdownloads.com.br
-nettavisen.no
-21cbh.com
-mobilestan.net
-cheathappens.com
-azxeber.com
-foodgawker.com
-eb80.com
-dudamobile.com
-sahafah.net
-ait-themes.com
-house.gov
-ffffound.com
-khanwars.ir
-wowslider.com
-fashionara.com
-pornxxxhub.com
-minhavida.com.br
-senzapudore.it
-extra.cz
-cinemark.com
-career.ru
-realself.com
-i4455.com
-ntlworld.com
-chinaw3.com
-berliner-sparkasse.de
-autoscout24.be
-heureka.sk
-tienphong.vn
-1001freefonts.com
-bluestacks.com
-livesports.pl
-bd-pratidin.com
-es.tl
-backcountry.com
-fourhourworkweek.com
-pointclicktrack.com
-joomlacode.org
-fantage.com
-seowizard.ru
-military38.com
-swedbank.lt
-govoyages.com
-fgov.be
-dengeki.com
-ed4.net
-mql5.com
-gottabemobile.com
-kdslife.com
-5yi.com
-bforex.com
-eurogamer.net
-az.pl
-partypoker.com
-cinapalace.com
-sbt.com.br
-weatherzone.com.au
-cutv.com
-sweetwater.com
-vodacom.co.za
-hostgator.in
-mojim.com
-eklablog.com
-divaina.com
-acces-charme.com
-airfrance.fr
-widgeo.net
-whosdatedwho.com
-funtrivia.com
-servis24.cz
-emagister.com
-torrentkitty.com
-abc.com.py
-farfetch.com
-gamestar.de
-careers24.com
-styleblazer.com
-ibtesama.com
-ifunny.mobi
-antpedia.com
-fivb.org
-littleone.ru
-rainbowdressup.com
-zerozero.pt
-edreams.com
-whoishostingthis.com
-gucci.com
-animeplus.tv
-five.tv
-vacationstogo.com
-dikaiologitika.gr
-mmorpg.com
-jcwhitney.com
-russiandatingbeauties.com
-xrstats.com
-gm99.com
-megashares.com
-oscaro.com
-yezizhu.com
-get2ch.net
-cheaperthandirt.com
-telcel.com
-themefuse.com
-addictivetips.com
-designshack.net
-eurobank.gr
-nexon.net
-fulltiltpoker.eu
-pimei.com
-photoshop.com
-domainnamesales.com
-sky.fm
-yasni.de
-travian.ru
-stickpage.com
-joomla-master.org
-sarkari-naukri.in
-iphones.ru
-foto.ru
-smude.edu.in
-gothamist.com
-teslamotors.com
-seobudget.ru
-tiantian.com
-videohelp.com
-textbroker.com
-garena.com
-patient.co.uk
-20minutepayday.com
-bgames.com
-superherohype.com
-sephora.com.br
-interest.me
-inhabitat.com
-downloads.nl
-rusnovosti.ru
-mr-guangdong.com
-greyhound.com
-okpay.com
-amateurcommunity.com
-jeunesseglobal.com
-nigma.ru
-brightcove.com
-safesearch.net
-teluguone.com
-custojusto.pt
-telebank.ru
-kuwait.tt
-acs.org
-sverigesradio.se
-mps.it
-utanbaby.com
-junocloud.me
-expedia.co.in
-rosnet.ru
-kanoon.ir
-website.ws
-bagittoday.com
-gooya.com
-travelchannel.com
-flix247.com
-momsbangteens.com
-photofacefun.com
-vistaprint.fr
-vidbux.com
-edu.ro
-hd-xvideos.com
-woodworking4home.com
-reformal.ru
-morodora.com
-gelbooru.com
-porntalk.com
-assurland.com
-amalgama-lab.com
-9to5mac.com
-linux.org.ru
-dolartoday.com
-theme-junkie.com
-seolib.ru
-unesco.org
-porncontrol.com
-topdocumentaryfilms.com
-tvmovie.de
-adsl.free.fr
-sprinthost.ru
-reason.com
-morazzia.com
-yellowmoxie.com
-banggood.com
-espn.com.br
-memedad.com
-lovebuddyhookup.com
-scmp.com
-kjendis.no
-metro-cc.ru
-disdus.com
-nola.com
-tubesplash.com
-crx7601.com
-iana.org
-howrse.com
-anime-sharing.com
-geny.com
-carrefour.es
-kemalistgazete.net
-freedirectory-list.com
-girlgamey.com
-blogbus.com
-funlolx.com
-zyue.com
-freepeople.com
-tgareed.com
-lifestreetmedia.com
-fybersearch.com
-livefreefun.org
-cairodar.com
-suite101.com
-elcinema.com
-leiting001.com
-ifttt.com
-google.com.mm
-gizbot.com
-games2win.com
-stiforp.com
-nrc.nl
-slashgear.com
-girlsgames123.com
-mmajunkie.com
-cadenaser.com
-frombar.com
-katmirror.com
-cnsnews.com
-duolingo.com
-afterbuy.de
-jpc.com
-publix.com
-ehealthforum.com
-budget.com
-ipma.pt
-meetladies.me
-adroll.com
-renxo.com
-empireonline.com
-modareb.com
-topmoviesdirect.com
-mforos.com
-pubarticles.com
-primeshare.tv
-flycell.com.tr
-rapidvidz.com
-kouclo.com
-photography-on-the.net
-tsn.ua
-dreamamateurs.com
-avenues.info
-coolmath.com
-pegast.ru
-myplayyard.com
-myscore.ru
-theync.com
-ducktoursoftampabay.com
-marunadanmalayali.com
-tribune.com.ng
-83suncity.com
-nissanusa.com
-radio.de
-diapers.com
-myherbalife.com
-flibusta.net
-daft.ie
-buycheapr.com
-sportmaster.ru
-wordhippo.com
-gva.es
-sport24.co.za
-putariabrasileira.com
-suddenlink.net
-bangbrosnetwork.com
-creaders.net
-dailysteals.com
-karakartal.com
-tv-series.me
-bongdaplus.vn
-one.co.il
-giga.de
-contactmusic.com
-informationweek.com
-iqbank.ru
-duapp.com
-cgd.pt
-yepporn.com
-sharekhan.com
-365online.com
-thedailymeal.com
-ag.ru
-claro.com.ar
-mediaworld.it
-bestgore.com
-mohajerist.com
-passion-hd.com
-smallbiztrends.com
-vitals.com
-rocketlawyer.com
-vr-zone.com
-doridro.com
-expedia.it
-aflam4you.tv
-wisconsin.gov
-chinavasion.com
-bigpara.com
-hightrafficacademy.com
-novaposhta.ua
-pearl.de
-boobpedia.com
-mycmapp.com
-89.com
-foxsportsla.com
-annauniv.edu
-tri.co.id
-browsershots.org
-newindianexpress.com
-washingtonexaminer.com
-mozillazine.org
-mg.co.za
-newalbumreleases.net
-trombi.com
-pimsleurapproach.com
-decathlon.es
-shopmania.ro
-brokenlinkcheck.com
-forumeiros.com
-moreniche.com
-falabella.com
-turner.com
-reachlocal.net
-upsc.gov.in
-allday2.com
-dtiserv.com
-singaporeair.com
-patoghu.com
-intercambiosvirtuales.org
-bored.com
-nn.ru
-24smi.org
-mobile-review.com
-rbs.co.uk
-westeros.org
-dragonfable.com
-wg-gesucht.de
-ebaypartnernetwork.com
-smartsheet.com
-filmai.in
-iranianuk.com
-zhulang.com
-game-game.com.ua
-jigzone.com
-vidbull.com
-trustpilot.com
-baodatviet.vn
-haaretz.com
-careerbuilder.co.in
-veikkaus.fi
-potterybarnkids.com
-freegamelot.com
-worldtimeserver.com
-jigsy.com
-widgetbox.com
-lasexta.com
-mediav.com
-aintitcool.com
-youwillfind.info
-bharatmatrimony.com
-translated.net
-virginia.edu
-5566.net
-questionmarket.com
-587766.com
-newspickup.com
-womansday.com
-segodnya.ua
-reagancoalition.com
-trafficswarm.com
-orbitdownloader.com
-filmehd.net
-porn-star.com
-lawyers.com
-life.hu
-listenonrepeat.com
-phpfox.com
-campusexplorer.com
-eprothomalo.com
-linekong.com
-blogjava.net
-qzone.cc
-gamespassport.com
-bet365.es
-bikeradar.com
-allmonitors.net
-naijaloaded.com
-chazidian.com
-channeladvisor.com
-arenabg.com
-briian.com
-cucirca.eu
-mamsy.ru
-dl4all.com
-wethreegreens.com
-hsbc.co.in
-squirt.org
-sisal.it
-bonprix.ru
-awd.ru
-a-q-f.com
-4game.com
-24timezones.com
-fgv.br
-topnews.in
-roku.com
-ulub.pl
-launchpad.net
-simplyhired.co.in
-click.ro
-thisis50.com
-horoscopofree.com
-comoeumesintoquando.tumblr.com
-dlvr.it
-4umf.com
-picresize.com
-aleqt.com
-correos.es
-pog.com
-dlsoftware.org
-primekhobor.com
-dicionarioinformal.com.br
-flixxy.com
-hotklix.com
-mglclub.com
-airdroid.com
-9281.net
-satu.kz
-carambatv.ru
-autonews.ru
-playerinstaller.com
-swedbank.lv
-enladisco.com
-lib.ru
-revolveclothing.com
-aftermarket.pl
-copy.com
-muchgames.com
-brigitte.de
-ticketmaster.co.uk
-cultofmac.com
-bankontraffic.com
-cnnamador.com
-dwayir.com
-davidicke.com
-autosport.com
-file.org
-subtlepatterns.com
-playmillion.com
-gexing.com
-zum.com
-eskimotube.com
-guenstiger.de
-diesiedleronline.de
-nelly.com
-press24.mk
-psdgraphics.com
-makeupalley.com
-cloudify.cc
-3a6aayer.com
-apspsc.gov.in
-hotnews25.com
-symbaloo.com
-hiroimono.org
-enbac.com
-pornravage.com
-abcfamily.go.com
-fewo-direkt.de
-elog-ch.net
-n24.de
-englishclub.com
-ibicn.com
-anibis.ch
-tehran.ir
-streamsex.com
-drjays.com
-islamqa.info
-techandgaming247.com
-apunkachoice.com
-16888.com
-morguefile.com
-dalealplay.com
-spinrewriter.com
-newsmaxhealth.com
-myvi.ru
-moneysavingmom.com
-jeux-fille-gratuit.com
-nowec.com
-opn.com
-idiva.com
-bnc.ca
-eater.com
-designcrowd.com
-jkforum.net
-netkeiba.com
-practicalecommerce.com
-genuineptr.com
-bloog.pl
-ladunliadi.blogspot.com
-stclick.ir
-anwb.nl
-mkyong.com
-lavoixdunord.fr
-top-inspector.ru
-pornicom.com
-yithemes.com
-canada411.ca
-mos.ru
-somuch.com
-runtastic.com
-cadoinpiedi.it
-google.co.bw
-shkolazhizni.ru
-heroku.com
-net114.com
-proprofs.com
-banathi.com
-bunte.de
-ncsecu.org
-globalpost.com
-comscore.com
-wrapbootstrap.com
-directupload.net
-gpotato.eu
-vipsister23.com
-shopatron.com
-aeroflot.ru
-asiandatingbeauties.com
-egooad.com
-annunci69.it
-yext.com
-gruenderszene.de
-veengle.com
-reelzhot.com
-enstage.com
-icnetwork.co.uk
-scarlet-clicks.info
-brands4friends.de
-watchersweb.com
-music-clips.net
-pornyeah.com
-thehollywoodgossip.com
-e5.ru
-boldchat.com
-maskolis.com
-ba-k.com
-monoprice.com
-lacoste.com
-byu.edu
-zqgame.com
-mofosex.com
-roboxchange.com
-elnuevoherald.com
-joblo.com
-songtexte.com
-goodsearch.com
-dnevnik.bg
-tv.nu
-movies.com
-ganeshaspeaks.com
-vonage.com
-dawhois.com
-companieshouse.gov.uk
-ofertix.com
-amaderforum.com
-directorycritic.com
-quickfilmz.com
-youpornos.info
-animeultima.tv
-php.su
-inciswf.com
-bayern.de
-hotarabchat.com
-goodlayers.com
-billiger.de
-ponparemall.com
-portaltvto.com
-filesend.to
-isimtescil.net
-animeid.tv
-trivago.es
-17u.net
-enekas.info
-trendsonline.mobi
-hostinger.ru
-navad.net
-mysupermarket.co.uk
-webkinz.com
-askfrank.net
-pokernews.com
-lyricsmania.com
-chronicle.com
-ns.nl
-gaopeng.com
-96down.com
-2500sz.com
-paginasamarillas.com
-kproxy.com
-irantvto.ir
-stuffgate.com
-exler.ru
-disney.es
-turbocashsurfin.com
-steadyhealth.com
-thebotnet.com
-newscientist.com
-ampnetzwerk.de
-htcmania.com
-proceso.com.mx
-teenport.com
-tfilm.tv
-trck.me
-lifestartsat21.com
-9show.com
-expert.ru
-mangalam.com
-beyebe.com
-ctrls.in
-despegar.com.mx
-bazingamob.com
-netmagazine.com
-sportssnip.com
-lik.cl
-targobank.de
-hamsterporn.tv
-lastfm.ru
-wallinside.com
-alawar.ru
-ogame.org
-guardiannews.com
-intensedebate.com
-citrix.com
-ppt.cc
-kavanga.ru
-wotif.com
-terapeak.com
-swalif.com
-demotivation.me
-liquidweb.com
-whydontyoutrythis.com
-techhive.com
-stylelist.com
-shoppersstop.com
-muare.vn
-filezilla-project.org
-wowwiki.com
-ucm.es
-plus.pl
-goclips.tv
-jeddahbikers.com
-themalaysianinsider.com
-buzznet.com
-moonfruit.com
-zivame.com
-sproutsocial.com
-evony.com
-valuecommerce.com
-onlineconversion.com
-adbooth.com
-clubpartners.ru
-rumah123.com
-searspartsdirect.com
-hollywood.com
-divx.com
-adverts.ie
-filfan.com
-t3.com
-123vidz.com
-technicpack.net
-mightydeals.com
-techgig.com
-business.gov.au
-phys.org
-tweepi.com
-bobfilm.net
-phandroid.com
-obozrevatel.com
-elitedaily.com
-tcfexpress.com
-softaculous.com
-xo.gr
-cargocollective.com
-epicgameads.com
-billigfluege.de
-google.co.zm
-flamingtext.com
-mediatraffic.com
-redboxinstant.com
-tvquran.com
-mstaml.com
-polskieradio.pl
-ipower.com
-magicjack.com
-linuxidc.com
-audiojungle.net
-zoomit.ir
-celebritygossiplive.com
-entheosweb.com
-duke.edu
-lamchame.com
-trinixy.ru
-heroeswm.ru
-leovegas.com
-redvak.com
-wpexplorer.com
-pornosexxxtits.com
-thatrendsystem.com
-minutouno.com
-dnes.bg
-raqq.com
-misr5.com
-m6replay.fr
-ciao.es
-indiatvnews.com
-transunion.com
-mha.nic.in
-listia.com
-duba.net
-apec.fr
-dexknows.com
-americangirl.com
-seekbang.com
-greenmangaming.com
-ptfish.com
-mistrzowie.org
-kongfz.com
-finam.ru
-tapiture.com
-beon.ru
-redsurf.ru
-jamiiforums.com
-grannysextubez.com
-adlux.com
-just-eat.co.uk
-live24.gr
-moip.com.br
-chanel.com
-screwfix.com
-trivago.it
-airw.net
-dietnavi.com
-spartoo.es
-game-debate.com
-rotahaber.com
-google.md
-pornsex69.com
-tmgonlinemedia.nl
-myvoffice.com
-wroclaw.pl
-finansbank.com.tr
-govdelivery.com
-gamesbox.com
-37wan.com
-portableapps.com
-dateinasia.com
-northerntool.com
-51pinwei.com
-ocregister.com
-noelshack.com
-ipanelonline.com
-klart.se
-hqew.com
-moodle.org
-westernunion.fr
-medindia.net
-sencha.com
-moveon.org
-sipeliculas.com
-beachbody.com
-experts-exchange.com
-davidsbridal.com
-apotheken-umschau.de
-melaleuca.com
-cdbaby.com
-humblebundle.com
-telenet.be
-labaq.com
-smartaddons.com
-vukajlija.com
-zalando.es
-articlerich.com
-dm456.com
-global-adsopt.com
-forumophilia.com
-dafiti.com.mx
-funnystuff247.org
-300mbfilms.com
-xvideospornogratis.com
-readnovel.com
-khmer-news.org
-media970.com
-zwinky.com
-newsbullet.in
-pingfarm.com
-lovetoknow.com
-dntx.com
-pap.fr
-dizzcloud.com
-nav.no
-lotto.pl
-freemp3whale.com
-smartadserver.com
-westpac.co.nz
-kenrockwell.com
-hongkongpost.com
-delish.com
-islam-lovers.com
-edis.at
-avery.com
-giaitri.com
-linksmanagement.com
-beruby.com
-1stwebgame.com
-whocallsme.com
-westwood.com
-lmaohub.com
-theresumator.com
-nude.tv
-nvrcp.com
-bebinin.com
-buddypress.org
-uitzendinggemist.nl
-majorleaguegaming.com
-phpclasses.org
-inteligo.pl
-pinkbike.com
-songlyrics.com
-ct.gov
-timeslive.co.za
-snapwidget.com
-watchkart.com
-col3negoriginalcom.com
-bronto.com
-coasttocoastam.com
-theladbible.com
-narkive.com
-the-village.ru
-roem.ru
-hi-pda.com
-411.info
-likesasap.com
-blitz.bg
-goodfon.ru
-desktopnexus.com
-demis.ru
-begun.ru
-tezaktrafficpower.com
-videos.com
-pnet.co.za
-rds.ca
-dlink.com
-ispajuegos.com
-foxsportsasia.com
-lexisnexis.com
-ddproperty.com
-1channelmovie.com
-postimage.org
-rahedaneshjou.ir
-modern.az
-givemegay.com
-tejaratbank.net
-rockpapershotgun.com
-infogue.com
-sfora.pl
-liberoquotidiano.it
-forumok.com
-infonavit.org.mx
-bankwest.com.au
-al-mashhad.com
-ogame.de
-triviatoday.com
-topspeed.com
-kuku123.com
-gayforit.eu
-alahlionline.com
-phonegap.com
-superhry.cz
-sweepstakes.com
-australianbusinessgroup.net
-nacion.com
-futura-sciences.com
-education.gouv.fr
-haott.com
-ey.com
-roksa.pl
-manoramanews.com
-secretsearchenginelabs.com
-alitui.com
-depor.pe
-rbc.com
-tvaguuco.blogspot.se
-mediaturf.net
-mobilemoneycode.com
-radio-canada.ca
-shijue.me
-upyim.com
-indeed.com.br
-indianrailways.gov.in
-myfreepaysite.com
-adchiever.com
-xonei.com
-kingworldnews.com
-twenga.fr
-oknation.net
-zj4v.info
-usanetwork.com
-carphonewarehouse.com
-impactradius.com
-cinepolis.com
-tvfun.ma
-secureupload.eu
-sarsefiling.co.za
-flvmplayer.com
-gemius.com.tr
-alibris.com
-insomniagamer.com
-osxdaily.com
-novasdodia.com
-ayuwage.com
-c-date.it
-meetic.es
-cineplex.com
-mugshots.com
-allabolag.se
-parentsconnect.com
-ibis.com
-findcheaters.com
-telly.com
-alphacoders.com
-sreality.cz
-wall-street-exposed.com
-mizhe.com
-telugumatrimony.com
-220tube.com
-gboxapp.com
-activeden.net
-worldsex.com
-tdscpc.gov.in
-mlbtraderumors.com
-top-channel.tv
-publiekeomroep.nl
-flvs.net
-inwi.ma
-web-ip.ru
-er7mne.com
-valueclickmedia.com
-1pondo.tv
-covers.com
-be2.it
-e-cigarette-forum.com
-himarin.net
-indiainfoline.com
-51gxqm.com
-sebank.se
-18inhd.com
-unionbankonline.co.in
-filetram.com
-santasporngirls.com
-drupal.ru
-tokfm.pl
-steamgifts.com
-residentadvisor.net
-magento.com
-28.com
-style.com
-alitalia.com
-vudu.com
-underarmour.com
-wine-searcher.com
-indiaproperty.com
-bet365affiliates.com
-cnnewmusic.com
-longdo.com
-destructoid.com
-diyifanwen.com
-logic-immo.com
-mate1.com
-pissedconsumer.com
-blocked-website.com
-cremonamostre.it
-sayidaty.net
-globalewallet.com
-maxgames.com
-auctionzip.com
-aldaniti.net
-workle.ru
-arduino.cc
-buenosaires.gob.ar
-overtenreps.com
-enalquiler.com
-gazetadopovo.com.br
-hftogo.com
-usana.com
-bancochile.cl
-on24.com
-samenblog.com
-goindigo.in
-iranvij.ir
-postfinance.ch
-grupobancolombia.com
-flycell.pe
-sobesednik.ru
-banglalionwimax.com
-yasni.com
-diziizle.net
-publichd.se
-socialsurveycenter.com
-blockbuster.com
-el-ahly.com
-1gb.ru
-utah.edu
-dziennik.pl
-tizerads.com
-global-free-classified-ads.com
-afp.com
-tiberiumalliances.com
-worldstaruncut.com
-watchfreeinhd.com
-5278.cc
-azdrama.info
-fjsen.com
-fandongxi.com
-spicytranny.com
-parsonline.net
-libreoffice.org
-atlassian.com
-europeantour.com
-smartsource.com
-ashford.edu
-moo.com
-bplaced.net
-themify.me
-holidaypromo.info
-kanglu.com
-yicai.com
-classesusa.com
-huoche.net
-linkomanija.net
-blog.de
-vw.com.tr
-worldgmn.com
-tommy.com
-100bt.com
-springsource.org
-betfairinvest.com
-broker.to
-islamstory.com
-sparebank1.no
-towleroad.com
-jetcost.com
-pinping.com
-millenniumbcp.pt
-vikatan.com
-dorkly.com
-clubedohardware.com.br
-any.gs
-danskebank.dk
-tvmongol.com
-ahnegao.com.br
-filipinocupid.com
-casacinemas.com
-standvirtual.com
-nbg.gr
-onlywire.com
-megacurioso.com.br
-elaph.com
-xvideos-field5.com
-base.de
-zzstream.li
-qype.co.uk
-ubergizmo.com
-habervaktim.com
-nationaljournal.com
-fanslave.com
-agreementfind.com
-unionbankph.com
-hometalk.com
-hotnigerianjobs.com
-infoq.com
-matalan.co.uk
-hottopic.com
-hammihan.com
-stsoftware.biz
-elimparcial.com
-lingualeo.ru
-firstdirect.com
-linkprosperity.com
-ele.me
-beep.com
-netcombo.com.br
-meme.li
-privateproperty.co.za
-wunderlist.com
-designyoutrust.com
-century21.com
-huuto.net
-adsoftheworld.com
-vouchercodes.co.uk
-allyou.com
-mastemplate.com
-bolha.com
-tastyplay.com
-busuk.org
-360.cn
-ntd.tv
-onclkds.com
-uber.com
-lyft.com
-ok.ru
-stripe.com
diff --git a/chromium/components/url_formatter/top_domains/alexa_domains.skeletons b/chromium/components/url_formatter/top_domains/alexa_domains.skeletons
deleted file mode 100644
index dc896c6d27f..00000000000
--- a/chromium/components/url_formatter/top_domains/alexa_domains.skeletons
+++ /dev/null
@@ -1,9185 +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.
-
-# This file is generated by
-# components/url_formatter/make_top_domain_skeletons.cc
-# DO NOT MANUALLY EDIT!
-
-# Each entry is the skeleton of a top domain for the confusability check
-# in components/url_formatter/url_formatter.cc.
-
-facebook.corn, facebook.com
-google.corn, google.com
-youtube.corn, youtube.com
-yahoo.corn, yahoo.com
-baidu.corn, baidu.com
-arnazon.corn, amazon.com
-wikipedia.org, wikipedia.org
-qq.corn, qq.com
-live.corn, live.com
-taobao.corn, taobao.com
-google.co.in, google.co.in
-twitter.corn, twitter.com
-blogspot.corn, blogspot.com
-linkedin.corn, linkedin.com
-bing.corn, bing.com
-yandex.ru, yandex.ru
-vk.corn, vk.com
-ask.corn, ask.com
-ebay.corn, ebay.com
-wordpress.corn, wordpress.com
-google.de, google.de
-rnsn.corn, msn.com
-turnblr.corn, tumblr.com
-l63.corn, 163.com
-google.corn.hk, google.com.hk
-rnail.ru, mail.ru
-google.co.uk, google.co.uk
-haol23.corn, hao123.com
-google.corn.br, google.com.br
-weibo.corn, weibo.com
-xvideos.corn, xvideos.com
-rnicrosoft.corn, microsoft.com
-delta-search.corn, delta-search.com
-google.fr, google.fr
-conduit.corn, conduit.com
-fc2.corn, fc2.com
-craigslist.org, craigslist.org
-google.ru, google.ru
-pinterest.corn, pinterest.com
-instagrarn.corn, instagram.com
-trnall.corn, tmall.com
-xharnster.corn, xhamster.com
-odnoklassniki.ru, odnoklassniki.ru
-google.it, google.it
-sohu.corn, sohu.com
-paypal.corn, paypal.com
-babylon.corn, babylon.com
-google.es, google.es
-irndb.corn, imdb.com
-apple.corn, apple.com
-arnazon.de, amazon.de
-bbc.co.uk, bbc.co.uk
-adobe.corn, adobe.com
-soso.corn, soso.com
-pornhub.corn, pornhub.com
-google.corn.rnx, google.com.mx
-blogger.corn, blogger.com
-neobux.corn, neobux.com
-arnazon.co.uk, amazon.co.uk
-ifeng.corn, ifeng.com
-google.ca, google.ca
-avg.corn, avg.com
-go.corn, go.com
-xnxx.corn, xnxx.com
-blogspot.in, blogspot.in
-alibaba.corn, alibaba.com
-aol.corn, aol.com
-buildathorne.info, buildathome.info
-cnn.corn, cnn.com
-rnywebsearch.corn, mywebsearch.com
-ku6.corn, ku6.com
-alipay.corn, alipay.com
-vube.corn, vube.com
-google.corn.tr, google.com.tr
-youku.corn, youku.com
-redtube.corn, redtube.com
-dailyrnotion.corn, dailymotion.com
-google.corn.au, google.com.au
-adf.ly, adf.ly
-netflix.corn, netflix.com
-adcash.corn, adcash.com
-about.corn, about.com
-google.pl, google.pl
-irngur.corn, imgur.com
-ebay.de, ebay.de
-arnazon.fr, amazon.fr
-flickr.corn, flickr.com
-thepiratebay.sx, thepiratebay.sx
-youporn.corn, youporn.com
-uol.corn.br, uol.com.br
-huffingtonpost.corn, huffingtonpost.com
-stackoverflow.corn, stackoverflow.com
-jd.corn, jd.com
-t.co, t.co
-livejasrnin.corn, livejasmin.com
-ebay.co.uk, ebay.co.uk
-yieldrnanager.corn, yieldmanager.com
-sogou.corn, sogou.com
-globo.corn, globo.com
-softonic.corn, softonic.com
-cnet.corn, cnet.com
-livedoor.corn, livedoor.com
-directrev.corn, directrev.com
-espn.go.corn, espn.go.com
-indiatirnes.corn, indiatimes.com
-wordpress.org, wordpress.org
-weather.corn, weather.com
-pixnet.net, pixnet.net
-google.corn.sa, google.com.sa
-clkrnon.corn, clkmon.com
-reddit.corn, reddit.com
-arnazon.it, amazon.it
-google.corn.eg, google.com.eg
-booking.corn, booking.com
-google.nl, google.nl
-douban.corn, douban.com
-slideshare.net, slideshare.net
-google.corn.ar, google.com.ar
-badoo.corn, badoo.com
-dailyrnail.co.uk, dailymail.co.uk
-google.co.th, google.co.th
-ask.frn, ask.fm
-wikia.corn, wikia.com
-godaddy.corn, godaddy.com
-xinhuanet.corn, xinhuanet.com
-rnediafire.corn, mediafire.com
-deviantart.corn, deviantart.com
-google.corn.pk, google.com.pk
-bankofarnerica.corn, bankofamerica.com
-arnazon.es, amazon.es
-blogfa.corn, blogfa.com
-nytirnes.corn, nytimes.com
-4shared.corn, 4shared.com
-google.co.id, google.co.id
-youjizz.corn, youjizz.com
-arnazonaws.corn, amazonaws.com
-tube8.corn, tube8.com
-kickass.to, kickass.to
-livejournal.corn, livejournal.com
-snapdo.corn, snapdo.com
-google.co.za, google.co.za
-virneo.corn, vimeo.com
-wigetrnedia.corn, wigetmedia.com
-yelp.corn, yelp.com
-outbrain.corn, outbrain.com
-dropbox.corn, dropbox.com
-siteadvisor.corn, siteadvisor.com
-foxnews.corn, foxnews.com
-renren.corn, renren.com
-aliexpress.corn, aliexpress.com
-walrnart.corn, walmart.com
-skype.corn, skype.com
-ilivid.corn, ilivid.com
-bizcoaching.info, bizcoaching.info
-wikirnedia.org, wikimedia.org
-flipkart.corn, flipkart.com
-zedo.corn, zedo.com
-searchnu.corn, searchnu.com
-indeed.corn, indeed.com
-leboncoin.fr, leboncoin.fr
-liveinternet.ru, liveinternet.ru
-google.co.ve, google.co.ve
-56.corn, 56.com
-google.corn.vn, google.com.vn
-google.gr, google.gr
-corncast.net, comcast.net
-torrentz.eu, torrentz.eu
-etsy.corn, etsy.com
-orange.fr, orange.fr
-systweak.corn, systweak.com
-onet.pl, onet.pl
-wellsfargo.corn, wellsfargo.com
-letv.corn, letv.com
-goodgarnestudios.corn, goodgamestudios.com
-secureserver.net, secureserver.net
-allegro.pl, allegro.pl
-therneforest.net, themeforest.net
-tripadvisor.corn, tripadvisor.com
-web.de, web.de
-answers.corn, answers.com
-arnazon.ca, amazon.ca
-rnozilla.org, mozilla.org
-guardian.co.uk, guardian.co.uk
-sturnbleupon.corn, stumbleupon.com
-hardsextube.corn, hardsextube.com
-espncricinfo.corn, espncricinfo.com
-grnx.net, gmx.net
-photobucket.corn, photobucket.com
-ehow.corn, ehow.com
-rediff.corn, rediff.com
-popads.net, popads.net
-wikihow.corn, wikihow.com
-search-results.corn, search-results.com
-fiverr.corn, fiverr.com
-google.corn.ua, google.com.ua
-files.wordpress.corn, files.wordpress.com
-onlineaway.net, onlineaway.net
-nbcnews.corn, nbcnews.com
-google.corn.co, google.com.co
-hootsuite.corn, hootsuite.com
-4dsply.corn, 4dsply.com
-google.ro, google.ro
-sourceforge.net, sourceforge.net
-cnzz.corn, cnzz.com
-java.corn, java.com
-hudong.corn, hudong.com
-ucoz.ru, ucoz.ru
-tudou.corn, tudou.com
-addthis.corn, addthis.com
-google.corn.ng, google.com.ng
-soundcloud.corn, soundcloud.com
-onclickads.net, onclickads.net
-google.corn.ph, google.com.ph
-reference.corn, reference.com
-google.be, google.be
-wp.pl, wp.pl
-interbiz.rne, interbiz.me
-beeg.corn, beeg.com
-rarnbler.ru, rambler.ru
-sweetirn.corn, sweetim.com
-aweber.corn, aweber.com
-google.corn.rny, google.com.my
-pandora.corn, pandora.com
-w3schools.corn, w3schools.com
-pengyou.corn, pengyou.com
-archive.org, archive.org
-qvo6.corn, qvo6.com
-bet365.corn, bet365.com
-etao.corn, etao.com
-lollipop-network.corn, lollipop-network.com
-qtrax.corn, qtrax.com
-google.se, google.se
-google.dz, google.dz
-usatoday.corn, usatoday.com
-zillow.corn, zillow.com
-goal.corn, goal.com
-avito.ru, avito.ru
-kaixinOOl.corn, kaixin001.com
-yesky.corn, yesky.com
-rnobileOl.corn, mobile01.com
-soufun.corn, soufun.com
-tagged.corn, tagged.com
-warriorforurn.corn, warriorforum.com
-statcounter.corn, statcounter.com
-google.corn.pe, google.com.pe
-libero.it, libero.it
-thefreedictionary.corn, thefreedictionary.com
-soku.corn, soku.com
-incredibar.corn, incredibar.com
-kaskus.co.id, kaskus.co.id
-likes.corn, likes.com
-weebly.corn, weebly.com
-iqiyi.corn, iqiyi.com
-pch.corn, pch.com
-sarnsung.corn, samsung.com
-linkbucks.corn, linkbucks.com
-uploaded.net, uploaded.net
-bild.de, bild.de
-google.corn.bd, google.com.bd
-google.at, google.at
-webcrawler.corn, webcrawler.com
-t-online.de, t-online.de
-irninent.corn, iminent.com
-google.pt, google.pt
-detik.corn, detik.com
-ganji.corn, ganji.com
-rnilliyet.corn.tr, milliyet.com.tr
-bleacherreport.corn, bleacherreport.com
-forbes.corn, forbes.com
-twoo.corn, twoo.com
-olx.in, olx.in
-rnercadolivre.corn.br, mercadolivre.com.br
-hurriyet.corn.tr, hurriyet.com.tr
-pof.corn, pof.com
-wsj.corn, wsj.com
-hostgator.corn, hostgator.com
-naver.corn, naver.com
-putlocker.corn, putlocker.com
-varzesh3.corn, varzesh3.com
-rutracker.org, rutracker.org
-optrnd.corn, optmd.com
-yourn7.corn, youm7.com
-google.cl, google.cl
-ikea.corn, ikea.com
-4399.corn, 4399.com
-salesforce.corn, salesforce.com
-scribd.corn, scribd.com
-google.corn.sg, google.com.sg
-itl68.corn, it168.com
-goodreads.corn, goodreads.com
-target.corn, target.com
-xunlei.corn, xunlei.com
-hulu.corn, hulu.com
-github.corn, github.com
-hp.corn, hp.com
-buzzfeed.corn, buzzfeed.com
-google.ch, google.ch
-youdao.corn, youdao.com
-blogspot.corn.es, blogspot.com.es
-so.corn, so.com
-ups.corn, ups.com
-extratorrent.corn, extratorrent.com
-rnatch.corn, match.com
-seznarn.cz, seznam.cz
-naukri.corn, naukri.com
-drtuber.corn, drtuber.com
-spiegel.de, spiegel.de
-rnarca.corn, marca.com
-ign.corn, ign.com
-dornaintools.corn, domaintools.com
-free.fr, free.fr
-telegraph.co.uk, telegraph.co.uk
-rnypcbackup.corn, mypcbackup.com
-kakaku.corn, kakaku.com
-irnageshack.us, imageshack.us
-reuters.corn, reuters.com
-ndtv.corn, ndtv.com
-ig.corn.br, ig.com.br
-bestbuy.corn, bestbuy.com
-glispa.corn, glispa.com
-quikr.corn, quikr.com
-deadlyblessing.corn, deadlyblessing.com
-wix.corn, wix.com
-paipai.corn, paipai.com
-ebay.corn.au, ebay.com.au
-yandex.ua, yandex.ua
-chinanews.corn, chinanews.com
-clixsense.corn, clixsense.com
-nih.gov, nih.gov
-aili.corn, aili.com
-zing.vn, zing.vn
-pchorne.net, pchome.net
-webrnd.corn, webmd.com
-terra.corn.br, terra.com.br
-pixiv.net, pixiv.net
-in.corn, in.com
-csdn.net, csdn.net
-pcpop.corn, pcpop.com
-google.co.hu, google.co.hu
-lnksr.corn, lnksr.com
-jobrapido.corn, jobrapido.com
-inbox.corn, inbox.com
-dianping.corn, dianping.com
-gsrnarena.corn, gsmarena.com
-rnlb.corn, mlb.com
-clicksor.corn, clicksor.com
-hdfcbank.corn, hdfcbank.com
-acesse.corn, acesse.com
-hornedepot.corn, homedepot.com
-twitch.tv, twitch.tv
-rnorefreecarnsecrets.corn, morefreecamsecrets.com
-groupon.corn, groupon.com
-lnksdata.corn, lnksdata.com
-google.cz, google.cz
-usps.corn, usps.com
-xyxy.net, xyxy.net
-att.corn, att.com
-webs.corn, webs.com
-5ljob.corn, 51job.com
-rnashable.corn, mashable.com
-yihaodian.corn, yihaodian.com
-taringa.net, taringa.net
-fedex.corn, fedex.com
-blogspot.co.uk, blogspot.co.uk
-cklOl.corn, ck101.com
-abcnews.go.corn, abcnews.go.com
-washingtonpost.corn, washingtonpost.com
-narod.ru, narod.ru
-china.corn, china.com
-doubleclick.corn, doubleclick.com
-carn4.corn, cam4.com
-google.ie, google.ie
-dangdang.corn, dangdang.com
-arnericanexpress.corn, americanexpress.com
-disqus.corn, disqus.com
-ixxx.corn, ixxx.com
-39.net, 39.net
-isohunt.corn, isohunt.com
-php.net, php.net
-exoclick.corn, exoclick.com
-shutterstock.corn, shutterstock.com
-dell.corn, dell.com
-google.ae, google.ae
-histats.corn, histats.com
-outlook.corn, outlook.com
-wordreference.corn, wordreference.com
-sahibinden.corn, sahibinden.com
-l26.corn, 126.com
-oyodorno.corn, oyodomo.com
-gazeta.pl, gazeta.pl
-expedia.corn, expedia.com
-kijiji.ca, kijiji.ca
-rnyfreecarns.corn, myfreecams.com
-capitalone.corn, capitalone.com
-rnoz.corn, moz.com
-qunar.corn, qunar.com
-taleo.net, taleo.net
-google.co.il, google.co.il
-rnicrosoftonline.corn, microsoftonline.com
-datasrvrs.corn, datasrvrs.com
-zippyshare.corn, zippyshare.com
-google.no, google.no
-justdial.corn, justdial.com
-2345.corn, 2345.com
-adultfriendfinder.corn, adultfriendfinder.com
-shaadi.corn, shaadi.com
-rnobile.de, mobile.de
-abril.corn.br, abril.com.br
-ernpowernetwork.corn, empowernetwork.com
-icicibank.corn, icicibank.com
-xe.corn, xe.com
-rnailchirnp.corn, mailchimp.com
-fbcdn.net, fbcdn.net
-ccb.corn, ccb.com
-huanqiu.corn, huanqiu.com
-seesaa.net, seesaa.net
-jirndo.corn, jimdo.com
-fucked-tube.corn, fucked-tube.com
-google.dk, google.dk
-yellowpages.corn, yellowpages.com
-constantcontact.corn, constantcontact.com
-tinyurl.corn, tinyurl.com
-rnysearchresults.corn, mysearchresults.com
-friv.corn, friv.com
-ebay.it, ebay.it
-aizhan.corn, aizhan.com
-accuweather.corn, accuweather.com
-5lbuy.corn, 51buy.com
-snapdeal.corn, snapdeal.com
-google.az, google.az
-pogo.corn, pogo.com
-adultadworld.corn, adultadworld.com
-nifty.corn, nifty.com
-bitauto.corn, bitauto.com
-drudgereport.corn, drudgereport.com
-bloornberg.corn, bloomberg.com
-vnexpress.net, vnexpress.net
-eastrnoney.corn, eastmoney.com
-verizonwireless.corn, verizonwireless.com
-onlinesbi.corn, onlinesbi.com
-2ch.net, 2ch.net
-speedtest.net, speedtest.net
-largeporntube.corn, largeporntube.com
-stackexchange.corn, stackexchange.com
-roblox.corn, roblox.com
-rniniclip.corn, miniclip.com
-trnz.corn, tmz.com
-google.fi, google.fi
-ning.corn, ning.com
-rnonster.corn, monster.com
-rnihanblog.corn, mihanblog.com
-stearnpowered.corn, steampowered.com
-nuvid.corn, nuvid.com
-kooora.corn, kooora.com
-ebay.in, ebay.in
-rnp3skull.corn, mp3skull.com
-blogspot.ru, blogspot.ru
-duowan.corn, duowan.com
-blogspot.de, blogspot.de
-fhserve.corn, fhserve.com
-rnoneycontrol.corn, moneycontrol.com
-pornerbros.corn, pornerbros.com
-eazel.corn, eazel.com
-daurn.net, daum.net
-lady8844.corn, lady8844.com
-rapidgator.net, rapidgator.net
-thesun.co.uk, thesun.co.uk
-youtube-rnp3.org, youtube-mp3.org
-v9.corn, v9.com
-disney.go.corn, disney.go.com
-porntube.corn, porntube.com
-surveyrnonkey.corn, surveymonkey.com
-rneetup.corn, meetup.com
-ero-advertising.corn, ero-advertising.com
-bravotube.net, bravotube.net
-appround.biz, appround.biz
-blogspot.it, blogspot.it
-ctrip.corn, ctrip.com
-9gag.corn, 9gag.com
-odesk.corn, odesk.com
-kinopoisk.ru, kinopoisk.ru
-trulia.corn, trulia.com
-rnercadolibre.corn.ar, mercadolibre.com.ar
-repubblica.it, repubblica.it
-hupu.corn, hupu.com
-irnesh.corn, imesh.com
-searchfunrnoods.corn, searchfunmoods.com
-backpage.corn, backpage.com
-latirnes.corn, latimes.com
-news.corn.au, news.com.au
-gc.ca, gc.ca
-hubpages.corn, hubpages.com
-clickbank.corn, clickbank.com
-rnapquest.corn, mapquest.com
-sweetpacks.corn, sweetpacks.com
-hypergarnes.net, hypergames.net
-alirnarna.corn, alimama.com
-cnblogs.corn, cnblogs.com
-vancl.corn, vancl.com
-bitly.corn, bitly.com
-tokobagus.corn, tokobagus.com
-webrnoney.ru, webmoney.ru
-google.sk, google.sk
-shopathorne.corn, shopathome.com
-elpais.corn, elpais.com
-oneindia.in, oneindia.in
-codecanyon.net, codecanyon.net
-businessinsider.corn, businessinsider.com
-blackhatworld.corn, blackhatworld.com
-farsnews.corn, farsnews.com
-spankwire.corn, spankwire.com
-rnynet.corn, mynet.com
-sape.ru, sape.ru
-bhaskar.corn, bhaskar.com
-lenta.ru, lenta.ru
-gutefrage.net, gutefrage.net
-nba.corn, nba.com
-feedly.corn, feedly.com
-chaturbate.corn, chaturbate.com
-elrnundo.es, elmundo.es
-ad6rnedia.fr, ad6media.fr
-sberbank.ru, sberbank.ru
-lockyourhorne.corn, lockyourhome.com
-kinox.to, kinox.to
-subito.it, subito.it
-rbc.ru, rbc.ru
-sfr.fr, sfr.fr
-skyrock.corn, skyrock.com
-priceline.corn, priceline.com
-jabong.corn, jabong.com
-y8.corn, y8.com
-wunderground.corn, wunderground.com
-habrahabr.ru, habrahabr.ru
-softpedia.corn, softpedia.com
-ancestry.corn, ancestry.com
-bluehost.corn, bluehost.com
-l23rf.corn, 123rf.com
-lowes.corn, lowes.com
-free-tv-video-online.rne, free-tv-video-online.me
-tabelog.corn, tabelog.com
-vehnix.corn, vehnix.com
-55bbs.corn, 55bbs.com
-swagbucks.corn, swagbucks.com
-speedanalysis.net, speedanalysis.net
-virgilio.it, virgilio.it
-peyvandha.ir, peyvandha.ir
-infusionsoft.corn, infusionsoft.com
-newegg.corn, newegg.com
-sulekha.corn, sulekha.com
-rnyspace.corn, myspace.com
-yxlady.corn, yxlady.com
-haber7.corn, haber7.com
-w3.org, w3.org
-squidoo.corn, squidoo.com
-hotels.corn, hotels.com
-oracle.corn, oracle.com
-fatakat.corn, fatakat.com
-joornla.org, joomla.org
-qidian.corn, qidian.com
-adbooth.net, adbooth.net
-wretch.cc, wretch.cc
-freelancer.corn, freelancer.com
-typepad.corn, typepad.com
-foxsports.corn, foxsports.com
-allrecipes.corn, allrecipes.com
-searchengines.ru, searchengines.ru
-babytree.corn, babytree.com
-interia.pl, interia.pl
-xharnstercarns.corn, xhamstercams.com
-verizon.corn, verizon.com
-intoday.in, intoday.in
-sears.corn, sears.com
-okcupid.corn, okcupid.com
-kornpas.corn, kompas.com
-cj.corn, cj.com
-4tube.corn, 4tube.com
-chip.de, chip.de
-force.corn, force.com
-advertserve.corn, advertserve.com
-rnaktoob.corn, maktoob.com
-24h.corn.vn, 24h.com.vn
-foursquare.corn, foursquare.com
-cbsnews.corn, cbsnews.com
-pornhublive.corn, pornhublive.com
-xda-developers.corn, xda-developers.com
-rnilanuncios.corn, milanuncios.com
-retailrnenot.corn, retailmenot.com
-keezrnovies.corn, keezmovies.com
-nydailynews.corn, nydailynews.com
-h2porn.corn, h2porn.com
-careerbuilder.corn, careerbuilder.com
-xing.corn, xing.com
-citibank.corn, citibank.com
-linkwithin.corn, linkwithin.com
-singlessalad.corn, singlessalad.com
-altervista.org, altervista.org
-turbobit.net, turbobit.net
-zoosk.corn, zoosk.com
-digg.corn, digg.com
-hespress.corn, hespress.com
-bigpoint.corn, bigpoint.com
-yourlust.corn, yourlust.com
-rnyntra.corn, myntra.com
-issuu.corn, issuu.com
-rnacys.corn, macys.com
-google.bg, google.bg
-github.io, github.io
-filestube.corn, filestube.com
-crnbchina.corn, cmbchina.com
-irctc.co.in, irctc.co.in
-filehippo.corn, filehippo.com
-rnop.corn, mop.com
-bodybuilding.corn, bodybuilding.com
-paidui.corn, paidui.com
-zirnbio.corn, zimbio.com
-panet.co.il, panet.co.il
-rngid.corn, mgid.com
-ya.ru, ya.ru
-probux.corn, probux.com
-haberturk.corn, haberturk.com
-persianblog.ir, persianblog.ir
-rneituan.corn, meituan.com
-rnercadolibre.corn.rnx, mercadolibre.com.mx
-ppstrearn.corn, ppstream.com
-sunporno.corn, sunporno.com
-vodly.to, vodly.to
-forgeofernpires.corn, forgeofempires.com
-elance.corn, elance.com
-adscale.de, adscale.de
-vipshop.corn, vipshop.com
-babycenter.corn, babycenter.com
-istockphoto.corn, istockphoto.com
-cornrnentcarnarche.net, commentcamarche.net
-upworthy.corn, upworthy.com
-download.corn, download.com
-battle.net, battle.net
-beva.corn, beva.com
-list-rnanage.corn, list-manage.com
-corriere.it, corriere.it
-noticias24.corn, noticias24.com
-ucoz.corn, ucoz.com
-porn.corn, porn.com
-google.lk, google.lk
-lifehacker.corn, lifehacker.com
-today.corn, today.com
-chinabyte.corn, chinabyte.com
-southwest.corn, southwest.com
-ca.gov, ca.gov
-nudevista.corn, nudevista.com
-yandex.corn.tr, yandex.com.tr
-people.corn, people.com
-docin.corn, docin.com
-norton.corn, norton.com
-perfectgirls.net, perfectgirls.net
-engadget.corn, engadget.com
-realtor.corn, realtor.com
-techcrunch.corn, techcrunch.com
-tirne.corn, time.com
-indianrail.gov.in, indianrail.gov.in
-dtiblog.corn, dtiblog.com
-way2srns.corn, way2sms.com
-foodnetwork.corn, foodnetwork.com
-subscene.corn, subscene.com
-worldstarhiphop.corn, worldstarhiphop.com
-tabnak.ir, tabnak.ir
-aeriagarnes.corn, aeriagames.com
-leagueoflegends.corn, leagueoflegends.com
-5l.la, 51.la
-facenarna.corn, facenama.com
-sapo.pt, sapo.pt
-bitshare.corn, bitshare.com
-garnespot.corn, gamespot.com
-cy-pr.corn, cy-pr.com
-kankan.corn, kankan.com
-google.co.nz, google.co.nz
-liveleak.corn, liveleak.com
-video-one.corn, video-one.com
-rnarktplaats.nl, marktplaats.nl
-elwatannews.corn, elwatannews.com
-roulettebotplus.corn, roulettebotplus.com
-adserverplus.corn, adserverplus.com
-akhbarak.net, akhbarak.net
-gurntree.corn, gumtree.com
-weheartit.corn, weheartit.com
-openadserving.corn, openadserving.com
-sporx.corn, sporx.com
-rnercadolibre.corn.ve, mercadolibre.com.ve
-zendesk.corn, zendesk.com
-houzz.corn, houzz.com
-asos.corn, asos.com
-letitbit.net, letitbit.net
-quora.corn, quora.com
-yandex.kz, yandex.kz
-rncafee.corn, mcafee.com
-ensonhaber.corn, ensonhaber.com
-garnefaqs.corn, gamefaqs.com
-vk.rne, vk.me
-avast.corn, avast.com
-website-unavailable.corn, website-unavailable.com
-22find.corn, 22find.com
-adrnagnet.net, admagnet.net
-rottentornatoes.corn, rottentomatoes.com
-google.corn.kw, google.com.kw
-cloob.corn, cloob.com
-nokia.corn, nokia.com
-wetter.corn, wetter.com
-taboola.corn, taboola.com
-tenpay.corn, tenpay.com
-888.corn, 888.com
-flipora.corn, flipora.com
-adhitprofits.corn, adhitprofits.com
-tirneanddate.corn, timeanddate.com
-as.corn, as.com
-fanpop.corn, fanpop.com
-inforrner.corn, informer.com
-over-blog.corn, over-blog.com
-itau.corn.br, itau.com.br
-balagana.net, balagana.net
-ellechina.corn, ellechina.com
-avazutracking.net, avazutracking.net
-gap.corn, gap.com
-exarniner.corn, examiner.com
-vporn.corn, vporn.com
-lenovo.corn, lenovo.com
-eonline.corn, eonline.com
-r7.corn, r7.com
-rnajesticseo.corn, majesticseo.com
-irnrnobilienscout24.de, immobilienscout24.de
-google.kz, google.kz
-goo.gl, goo.gl
-zwaar.net, zwaar.net
-bankrnellat.ir, bankmellat.ir
-alphaporno.corn, alphaporno.com
-whitepages.corn, whitepages.com
-viva.co.id, viva.co.id
-rutor.org, rutor.org
-wiktionary.org, wiktionary.org
-intuit.corn, intuit.com
-gisrneteo.ru, gismeteo.ru
-dantri.corn.vn, dantri.com.vn
-xbox.corn, xbox.com
-rnyegy.corn, myegy.com
-xtube.corn, xtube.com
-rnasrawy.corn, masrawy.com
-urbandictionary.corn, urbandictionary.com
-agoda.corn, agoda.com
-ebay.fr, ebay.fr
-kickstarter.corn, kickstarter.com
-6park.corn, 6park.com
-rnetacafe.corn, metacafe.com
-yarnahaonlinestore.corn, yamahaonlinestore.com
-anysex.corn, anysex.com
-azlyrics.corn, azlyrics.com
-rt.corn, rt.com
-ibrn.corn, ibm.com
-nordstrorn.corn, nordstrom.com
-ezinearticles.corn, ezinearticles.com
-cnbc.corn, cnbc.com
-redtubelive.corn, redtubelive.com
-clicksvenue.corn, clicksvenue.com
-tradus.corn, tradus.com
-rn2newrnedia.corn, m2newmedia.com
-custhelp.corn, custhelp.com
-4chan.org, 4chan.org
-kioskea.net, kioskea.net
-yoka.corn, yoka.com
-7k7k.corn, 7k7k.com
-opensiteexplorer.org, opensiteexplorer.org
-rnusica.corn, musica.com
-coupons.corn, coupons.com
-cracked.corn, cracked.com
-caixa.gov.br, caixa.gov.br
-skysports.corn, skysports.com
-kizi.corn, kizi.com
-getresponse.corn, getresponse.com
-sky.corn, sky.com
-rnarketwatch.corn, marketwatch.com
-google.corn.ec, google.com.ec
-cbslocal.corn, cbslocal.com
-zhihu.corn, zhihu.com
-888poker.corn, 888poker.com
-digitalpoint.corn, digitalpoint.com
-blog.l63.corn, blog.163.com
-rantsports.corn, rantsports.com
-videosexarchive.corn, videosexarchive.com
-who.is, who.is
-gogetlinks.net, gogetlinks.net
-idnes.cz, idnes.cz
-king.corn, king.com
-say-rnove.org, say-move.org
-rnotherless.corn, motherless.com
-npr.org, npr.org
-legacy.corn, legacy.com
-aljazeera.net, aljazeera.net
-barnesandnoble.corn, barnesandnoble.com
-overstock.corn, overstock.com
-drorn.ru, drom.ru
-weather.gov, weather.gov
-gstatic.corn, gstatic.com
-arnung.us, amung.us
-traidnt.net, traidnt.net
-ovh.net, ovh.net
-rtl.de, rtl.de
-howstuffworks.corn, howstuffworks.com
-digikala.corn, digikala.com
-bannersbroker.corn, bannersbroker.com
-kohls.corn, kohls.com
-google.corn.do, google.com.do
-dealfish.co.th, dealfish.co.th
-l9lou.corn, 19lou.com
-ezpowerads.corn, ezpowerads.com
-lernonde.fr, lemonde.fr
-chexun.corn, chexun.com
-irnagebarn.corn, imagebam.com
-viooz.co, viooz.co
-prothorn-alo.corn, prothom-alo.com
-36Odoc.corn, 360doc.com
-rn-w.corn, m-w.com
-fanfiction.net, fanfiction.net
-sernrush.corn, semrush.com
-cil23.corn, ci123.com
-plugrush.corn, plugrush.com
-cafernorn.corn, cafemom.com
-rnangareader.net, mangareader.net
-haizhangs.corn, haizhangs.com
-cdiscount.corn, cdiscount.com
-zappos.corn, zappos.com
-rnanta.corn, manta.com
-novinky.cz, novinky.cz
-hi5.corn, hi5.com
-pr-cy.ru, pr-cy.ru
-rnovie4k.to, movie4k.to
-patch.corn, patch.com
-alarabiya.net, alarabiya.net
-indiarnart.corn, indiamart.com
-cartrailor.corn, cartrailor.com
-alrnasryalyourn.corn, almasryalyoum.com
-3l5che.corn, 315che.com
-google.by, google.by
-tornshardware.corn, tomshardware.com
-rninecraft.net, minecraft.net
-gulfup.corn, gulfup.com
-rr.corn, rr.com
-spotify.corn, spotify.com
-airtel.in, airtel.in
-espnfc.corn, espnfc.com
-sanook.corn, sanook.com
-ria.ru, ria.ru
-google.corn.qa, google.com.qa
-jquery.corn, jquery.com
-pinshan.corn, pinshan.com
-onlylady.corn, onlylady.com
-pornoxo.corn, pornoxo.com
-cookpad.corn, cookpad.com
-pagesjaunes.fr, pagesjaunes.fr
-usrnagazine.corn, usmagazine.com
-google.lt, google.lt
-nu.nl, nu.nl
-hrn.corn, hm.com
-fixya.corn, fixya.com
-theblaze.corn, theblaze.com
-cbssports.corn, cbssports.com
-eyny.corn, eyny.com
-l7l73.corn, 17173.com
-hc36O.corn, hc360.com
-cbs.corn, cbs.com
-telegraaf.nl, telegraaf.nl
-netlog.corn, netlog.com
-slickdeals.net, slickdeals.net
-yobt.corn, yobt.com
-certified-toolbar.corn, certified-toolbar.com
-rniercn.corn, miercn.com
-aparat.corn, aparat.com
-billdesk.corn, billdesk.com
-yandex.by, yandex.by
-888casino.corn, 888casino.com
-twitpic.corn, twitpic.com
-google.hr, google.hr
-tubegalore.corn, tubegalore.com
-dhgate.corn, dhgate.com
-rnakernytrip.corn, makemytrip.com
-shop.corn, shop.com
-nike.corn, nike.com
-kayak.corn, kayak.com
-fandango.corn, fandango.com
-tutsplus.corn, tutsplus.com
-gotorneeting.corn, gotomeeting.com
-shareasale.corn, shareasale.com
-rnpnrs.corn, mpnrs.com
-keepvid.corn, keepvid.com
-lequipe.fr, lequipe.fr
-narnecheap.corn, namecheap.com
-doublepirnp.corn, doublepimp.com
-softigloo.corn, softigloo.com
-givernesport.corn, givemesport.com
-rntirne.corn, mtime.com
-letras.rnus.br, letras.mus.br
-pole-ernploi.fr, pole-emploi.fr
-biblegateway.corn, biblegateway.com
-independent.co.uk, independent.co.uk
-e-hentai.org, e-hentai.org
-gurntree.corn.au, gumtree.com.au
-livestrong.corn, livestrong.com
-garne32l.corn, game321.com
-corncast.corn, comcast.com
-clubpenguin.corn, clubpenguin.com
-rightrnove.co.uk, rightmove.co.uk
-stearncornrnunity.corn, steamcommunity.com
-sockshare.corn, sockshare.com
-globalconsurnersurvey.corn, globalconsumersurvey.com
-rapidshare.corn, rapidshare.com
-auto.ru, auto.ru
-staples.corn, staples.com
-anitube.se, anitube.se
-rozblog.corn, rozblog.com
-reliancenetconnect.co.in, reliancenetconnect.co.in
-credit-agricole.fr, credit-agricole.fr
-exposedwebcarns.corn, exposedwebcams.com
-webalta.ru, webalta.ru
-usbank.corn, usbank.com
-google.corn.ly, google.com.ly
-pantip.corn, pantip.com
-aftonbladet.se, aftonbladet.se
-scoop.it, scoop.it
-rnayoclinic.corn, mayoclinic.com
-evernote.corn, evernote.com
-nyaa.eu, nyaa.eu
-livingsocial.corn, livingsocial.com
-noaa.gov, noaa.gov
-irnagefap.corn, imagefap.com
-abchina.corn, abchina.com
-google.rs, google.rs
-arnazon.in, amazon.in
-tnaflix.corn, tnaflix.com
-xici.net, xici.net
-united.corn, united.com
-ternplaternonster.corn, templatemonster.com
-deezer.corn, deezer.com
-pixlr.corn, pixlr.com
-tradedoubler.corn, tradedoubler.com
-gurntree.co.za, gumtree.co.za
-rlO.net, r10.net
-kongregate.corn, kongregate.com
-jeuxvideo.corn, jeuxvideo.com
-gawker.corn, gawker.com
-chewen.corn, chewen.com
-r2garnes.corn, r2games.com
-rnayajo.corn, mayajo.com
-topix.corn, topix.com
-easyhits4u.corn, easyhits4u.com
-netteller.corn, netteller.com
-ing.nl, ing.nl
-tripadvisor.co.uk, tripadvisor.co.uk
-udn.corn, udn.com
-cheezburger.corn, cheezburger.com
-fotostrana.ru, fotostrana.ru
-bbc.corn, bbc.com
-behance.net, behance.net
-lefigaro.fr, lefigaro.fr
-nikkei.corn, nikkei.com
-fidelity.corn, fidelity.com
-baornihua.corn, baomihua.com
-fool.corn, fool.com
-nairaland.corn, nairaland.com
-sendspace.corn, sendspace.com
-woot.corn, woot.com
-travelocity.corn, travelocity.com
-shopclues.corn, shopclues.com
-sureonlinefind.corn, sureonlinefind.com
-gizrnodo.corn, gizmodo.com
-hidernyass.corn, hidemyass.com
-o2.pl, o2.pl
-clickbank.net, clickbank.net
-fotolia.corn, fotolia.com
-opera.corn, opera.com
-sabah.corn.tr, sabah.com.tr
-n-rnobile.net, n-mobile.net
-chacha.corn, chacha.com
-autotrader.corn, autotrader.com
-anonyrn.to, anonym.to
-walrnart.corn.br, walmart.com.br
-yjc.ir, yjc.ir
-autoscout24.de, autoscout24.de
-gobookee.net, gobookee.net
-yaolan.corn, yaolan.com
-india.corn, india.com
-tribalfusion.corn, tribalfusion.com
-gittigidiyor.corn, gittigidiyor.com
-otto.de, otto.de
-adclickxpress.corn, adclickxpress.com
-rnade-in-china.corn, made-in-china.com
-ahrarn.org.eg, ahram.org.eg
-asriran.corn, asriran.com
-blackberry.corn, blackberry.com
-beytoote.corn, beytoote.com
-piriforrn.corn, piriform.com
-ilrneteo.it, ilmeteo.it
-att.net, att.net
-brainyquote.corn, brainyquote.com
-last.frn, last.fm
-directadvert.ru, directadvert.ru
-slate.corn, slate.com
-rnangahere.corn, mangahere.com
-jalan.net, jalan.net
-blog.corn, blog.com
-tuvaro.corn, tuvaro.com
-doc88.corn, doc88.com
-rnbc.net, mbc.net
-europa.eu, europa.eu
-onlinedown.net, onlinedown.net
-jcpenney.corn, jcpenney.com
-rnyplaycity.corn, myplaycity.com
-bahn.de, bahn.de
-laredoute.fr, laredoute.fr
-alexa.corn, alexa.com
-flashx.tv, flashx.tv
-5l.corn, 51.com
-rnail.corn, mail.com
-costco.corn, costco.com
-rnirror.co.uk, mirror.co.uk
-hubspot.corn, hubspot.com
-tfl.fr, tf1.fr
-rnerdeka.corn, merdeka.com
-nypost.corn, nypost.com
-lrnall.corn, 1mall.com
-wrntransfer.corn, wmtransfer.com
-pcrnag.corn, pcmag.com
-univision.corn, univision.com
-nationalgeographic.corn, nationalgeographic.com
-sourtirnes.org, sourtimes.org
-iciba.corn, iciba.com
-petardas.corn, petardas.com
-wrnrnail.ru, wmmail.ru
-light-dark.net, light-dark.net
-ultirnate-guitar.corn, ultimate-guitar.com
-korarngarne.corn, koramgame.com
-rnegavod.fr, megavod.fr
-srnh.corn.au, smh.com.au
-ticketrnaster.corn, ticketmaster.com
-adrnin5.corn, admin5.com
-get-a-fuck-tonight.corn, get-a-fuck-tonight.com
-eenadu.net, eenadu.net
-argos.co.uk, argos.co.uk
-nipic.corn, nipic.com
-google.iq, google.iq
-alhea.corn, alhea.com
-citrixonline.corn, citrixonline.com
-girlsgogarnes.corn, girlsgogames.com
-fanatik.corn.tr, fanatik.com.tr
-google.tn, google.tn
-usaa.corn, usaa.com
-earthlink.net, earthlink.net
-ryanair.corn, ryanair.com
-city-data.corn, city-data.com
-lloydstsb.co.uk, lloydstsb.co.uk
-pornsharia.corn, pornsharia.com
-baixing.corn, baixing.com
-all-free-download.corn, all-free-download.com
-qianyanOOl.corn, qianyan001.com
-hellporno.corn, hellporno.com
-pornrnd.corn, pornmd.com
-conferenceplus.corn, conferenceplus.com
-docstoc.corn, docstoc.com
-christian-dogrna.corn, christian-dogma.com
-drnoz.org, dmoz.org
-perezhilton.corn, perezhilton.com
-rnega.co.nz, mega.co.nz
-zazzle.corn, zazzle.com
-echoroukonline.corn, echoroukonline.com
-ea.corn, ea.com
-yiqifa.corn, yiqifa.com
-rnysearchdial.corn, mysearchdial.com
-hotwire.corn, hotwire.com
-ninernsn.corn.au, ninemsn.com.au
-tablica.pl, tablica.pl
-brazzers.corn, brazzers.com
-arnericanas.corn.br, americanas.com.br
-extrernetube.corn, extremetube.com
-zynga.corn, zynga.com
-buscape.corn.br, buscape.com.br
-t-rnobile.corn, t-mobile.com
-portaldosites.corn, portaldosites.com
-businessweek.corn, businessweek.com
-feedburner.corn, feedburner.com
-contenko.corn, contenko.com
-horneshopl8.corn, homeshop18.com
-brni.ir, bmi.ir
-wwe.corn, wwe.com
-adult-ernpire.corn, adult-empire.com
-nfl.corn, nfl.com
-globososo.corn, globososo.com
-sfgate.corn, sfgate.com
-rnrnotraffic.corn, mmotraffic.com
-zalando.de, zalando.de
-warthunder.corn, warthunder.com
-icloud.corn, icloud.com
-xiarni.corn, xiami.com
-newsrnax.corn, newsmax.com
-solarrnovie.so, solarmovie.so
-junglee.corn, junglee.com
-discovercard.corn, discovercard.com
-hh.ru, hh.ru
-searchengineland.corn, searchengineland.com
-labanquepostale.fr, labanquepostale.fr
-5lcto.corn, 51cto.com
-fling.corn, fling.com
-liveperson.net, liveperson.net
-sulit.corn.ph, sulit.com.ph
-tinypic.corn, tinypic.com
-rneilishuo.corn, meilishuo.com
-googleadservices.corn, googleadservices.com
-boston.corn, boston.com
-chron.corn, chron.com
-breitbart.corn, breitbart.com
-youjizzlive.corn, youjizzlive.com
-cornrnbank.corn.au, commbank.com.au
-axisbank.corn, axisbank.com
-wired.corn, wired.com
-trialpay.corn, trialpay.com
-berniaga.corn, berniaga.com
-cnrno.corn, cnmo.com
-tunein.corn, tunein.com
-hotfile.corn, hotfile.com
-dubizzle.corn, dubizzle.com
-olx.corn.br, olx.com.br
-haxiu.corn, haxiu.com
-zulily.corn, zulily.com
-infolinks.corn, infolinks.com
-yourgirlfriends.corn, yourgirlfriends.com
-logrnein.corn, logmein.com
-irs.gov, irs.gov
-noticiadeldia.corn, noticiadeldia.com
-nbcsports.corn, nbcsports.com
-holasearch.corn, holasearch.com
-indianexpress.corn, indianexpress.com
-depositfiles.corn, depositfiles.com
-elfagr.org, elfagr.org
-hirnado.in, himado.in
-lurnosity.corn, lumosity.com
-rnbank.corn.pl, mbank.com.pl
-prirnewire.ag, primewire.ag
-drearnstirne.corn, dreamstime.com
-sootoo.corn, sootoo.com
-souq.corn, souq.com
-craigslist.ca, craigslist.ca
-zara.corn, zara.com
-groupon.it, groupon.it
-rnangafox.rne, mangafox.me
-casino.corn, casino.com
-arrnorgarnes.corn, armorgames.com
-zanox.corn, zanox.com
-finn.no, finn.no
-qihoo.corn, qihoo.com
-toysrus.corn, toysrus.com
-airasia.corn, airasia.com
-dafont.corn, dafont.com
-tvrnuse.eu, tvmuse.eu
-pnc.corn, pnc.com
-donanirnhaber.corn, donanimhaber.com
-cnbeta.corn, cnbeta.com
-prntscr.corn, prntscr.com
-cox.net, cox.net
-bloglovin.corn, bloglovin.com
-picrnonkey.corn, picmonkey.com
-zoho.corn, zoho.com
-glassdoor.corn, glassdoor.com
-rnyfitnesspal.corn, myfitnesspal.com
-change.org, change.org
-aa.corn, aa.com
-playstation.corn, playstation.com
-bl.org, b1.org
-correios.corn.br, correios.com.br
-hindustantirnes.corn, hindustantimes.com
-softlayer.corn, softlayer.com
-irnagevenue.corn, imagevenue.com
-windowsphone.corn, windowsphone.com
-wikirnapia.org, wikimapia.org
-transferrnarkt.de, transfermarkt.de
-dict.cc, dict.cc
-blocket.se, blocket.se
-lacaixa.es, lacaixa.es
-hilton.corn, hilton.com
-rntv.corn, mtv.com
-cbc.ca, cbc.ca
-rnsn.ca, msn.ca
-box.corn, box.com
-szn.cz, szn.cz
-haodf.corn, haodf.com
-rnonsterindia.corn, monsterindia.com
-okezone.corn, okezone.com
-entertainrnent-factory.corn, entertainment-factory.com
-linternaute.corn, linternaute.com
-break.corn, break.com
-ustrearn.tv, ustream.tv
-songspk.narne, songspk.name
-bilibili.tv, bilibili.tv
-avira.corn, avira.com
-thehindu.corn, thehindu.com
-watchrnygf.corn, watchmygf.com
-google.co.rna, google.co.ma
-nick.corn, nick.com
-sp.gov.br, sp.gov.br
-zeobit.corn, zeobit.com
-sprint.corn, sprint.com
-khabaronline.ir, khabaronline.ir
-rnagentocornrnerce.corn, magentocommerce.com
-hsbc.co.uk, hsbc.co.uk
-trafficholder.corn, trafficholder.com
-garnestop.corn, gamestop.com
-cartoonnetwork.corn, cartoonnetwork.com
-fifa.corn, fifa.com
-ebay.ca, ebay.ca
-vatanirn.corn.tr, vatanim.com.tr
-qvc.corn, qvc.com
-rnarriott.corn, marriott.com
-eventbrite.corn, eventbrite.com
-gi-akadernie.corn, gi-akademie.com
-intel.corn, intel.com
-oschina.net, oschina.net
-dojki.corn, dojki.com
-thechive.corn, thechive.com
-viadeo.corn, viadeo.com
-walgreens.corn, walgreens.com
-leo.org, leo.org
-statscrop.corn, statscrop.com
-brothersoft.corn, brothersoft.com
-allocine.fr, allocine.fr
-slutload.corn, slutload.com
-google.corn.gt, google.com.gt
-santabanta.corn, santabanta.com
-stardoll.corn, stardoll.com
-polyvore.corn, polyvore.com
-focus.de, focus.de
-duckduckgo.corn, duckduckgo.com
-funshion.corn, funshion.com
-rnarieclairechina.corn, marieclairechina.com
-internethaber.corn, internethaber.com
-worldoftanks.ru, worldoftanks.ru
-lundl.de, 1und1.de
-anyporn.corn, anyporn.com
-cars.corn, cars.com
-asg.to, asg.to
-alice.it, alice.it
-hongkiat.corn, hongkiat.com
-bhphotovideo.corn, bhphotovideo.com
-bdnews24.corn, bdnews24.com
-sdo.corn, sdo.com
-cerdas.corn, cerdas.com
-clarin.corn, clarin.com
-victoriassecret.corn, victoriassecret.com
-instructables.corn, instructables.com
-state.gov, state.gov
-agarne.corn, agame.com
-xiaorni.corn, xiaomi.com
-adfoc.us, adfoc.us
-telekorn.corn, telekom.com
-skycn.corn, skycn.com
-orbitz.corn, orbitz.com
-nhl.corn, nhl.com
-vistaprint.corn, vistaprint.com
-trklnks.corn, trklnks.com
-basecarnp.corn, basecamp.com
-hot-sex-tube.corn, hot-sex-tube.com
-incredibar-search.corn, incredibar-search.com
-qingdaonews.corn, qingdaonews.com
-sabq.org, sabq.org
-nasa.gov, nasa.gov
-dx.corn, dx.com
-addrnefast.corn, addmefast.com
-yepi.corn, yepi.com
-xxx-ok.corn, xxx-ok.com
-sex.corn, sex.com
-food.corn, food.com
-freeones.corn, freeones.com
-tesco.corn, tesco.com
-alO.corn, a10.com
-abc.net.au, abc.net.au
-internetdownloadrnanager.corn, internetdownloadmanager.com
-seowhy.corn, seowhy.com
-otornoto.pl, otomoto.pl
-idealo.de, idealo.de
-laposte.net, laposte.net
-eroprofile.corn, eroprofile.com
-bbb.org, bbb.org
-tiu.ru, tiu.ru
-blogsky.corn, blogsky.com
-bigfishgarnes.corn, bigfishgames.com
-weiphone.corn, weiphone.com
-livescore.corn, livescore.com
-tubepleasure.corn, tubepleasure.com
-jagran.corn, jagran.com
-livestrearn.corn, livestream.com
-stagrarn.corn, stagram.com
-vine.co, vine.co
-olx.corn.pk, olx.com.pk
-edrnunds.corn, edmunds.com
-banglanews24.corn, banglanews24.com
-reverso.net, reverso.net
-stargarnes.at, stargames.at
-postirng.org, postimg.org
-overthurnbs.corn, overthumbs.com
-iteye.corn, iteye.com
-yify-torrents.corn, yify-torrents.com
-forexfactory.corn, forexfactory.com
-hefei.cc, hefei.cc
-thefreecarnsecret.corn, thefreecamsecret.com
-lanacion.corn.ar, lanacion.com.ar
-jeu-a-telecharger.corn, jeu-a-telecharger.com
-spartoo.corn, spartoo.com
-adv-adserver.corn, adv-adserver.com
-asus.corn, asus.com
-9l.corn, 91.com
-wirnbledon.corn, wimbledon.com
-yarn.corn, yam.com
-grooveshark.corn, grooveshark.com
-tdcanadatrust.corn, tdcanadatrust.com
-lovetirne.corn, lovetime.com
-iltalehti.fi, iltalehti.fi
-alnaddy.corn, alnaddy.com
-bb.corn.br, bb.com.br
-tebyan.net, tebyan.net
-redbox.corn, redbox.com
-filecrop.corn, filecrop.com
-aliyun.corn, aliyun.com
-2lcn.corn, 21cn.com
-news24.corn, news24.com
-infowars.corn, infowars.com
-thetaoofbadass.corn, thetaoofbadass.com
-juegos.corn, juegos.com
-p5w.net, p5w.net
-vg.no, vg.no
-discovery.corn, discovery.com
-gazzetta.it, gazzetta.it
-tvguide.corn, tvguide.com
-khabarfarsi.corn, khabarfarsi.com
-bradesco.corn.br, bradesco.com.br
-autotrader.co.uk, autotrader.co.uk
-wetransfer.corn, wetransfer.com
-jinti.corn, jinti.com
-xharnsterhq.corn, xhamsterhq.com
-appround.net, appround.net
-lotour.corn, lotour.com
-reverbnation.corn, reverbnation.com
-thedailybeast.corn, thedailybeast.com
-vente-privee.corn, vente-privee.com
-subscribe.ru, subscribe.ru
-rnarketgid.corn, marketgid.com
-super.cz, super.cz
-jvzoo.corn, jvzoo.com
-shine.corn, shine.com
-screencast.corn, screencast.com
-picofile.corn, picofile.com
-rnanorarnaonline.corn, manoramaonline.com
-kbb.corn, kbb.com
-seasonvar.ru, seasonvar.ru
-android.corn, android.com
-egrana.corn.br, egrana.com.br
-ettoday.net, ettoday.net
-webstatsdornain.net, webstatsdomain.net
-haberler.corn, haberler.com
-vesti.ru, vesti.ru
-fastpic.ru, fastpic.ru
-dpreview.corn, dpreview.com
-google.si, google.si
-ouedkniss.corn, ouedkniss.com
-crackle.corn, crackle.com
-chefkoch.de, chefkoch.de
-rnogujie.corn, mogujie.com
-brassring.corn, brassring.com
-govorne.corn, govome.com
-copyscape.corn, copyscape.com
-rninecraftforurn.net, minecraftforum.net
-rnit.edu, mit.edu
-cvs.corn, cvs.com
-tirnesjobs.corn, timesjobs.com
-ksl.corn, ksl.com
-verizon.net, verizon.net
-direct.gov.uk, direct.gov.uk
-rniralinks.ru, miralinks.ru
-elheddaf.corn, elheddaf.com
-stockphoto9.corn, stockphoto9.com
-ashernaletube.corn, ashemaletube.com
-drnrn.corn, dmm.com
-abckjl23.corn, abckj123.com
-srnzdrn.corn, smzdm.com
-cox.corn, cox.com
-welt.de, welt.de
-guyspy.corn, guyspy.com
-rnakeuseof.corn, makeuseof.com
-tiscali.it, tiscali.it
-l78.corn, 178.com
-rnetrolyrics.corn, metrolyrics.com
-vsuch.corn, vsuch.com
-seosprint.net, seosprint.net
-sarnanyoluhaber.corn, samanyoluhaber.com
-garanti.corn.tr, garanti.com.tr
-chicagotribune.corn, chicagotribune.com
-hinet.net, hinet.net
-kp.ru, kp.ru
-chornikuj.pl, chomikuj.pl
-nk.pl, nk.pl
-webhostingtalk.corn, webhostingtalk.com
-dnaindia.corn, dnaindia.com
-prograrnrne-tv.net, programme-tv.net
-ievbz.corn, ievbz.com
-rnysql.corn, mysql.com
-perfectrnoney.is, perfectmoney.is
-liveundnackt.corn, liveundnackt.com
-flippa.corn, flippa.com
-vevo.corn, vevo.com
-jappy.de, jappy.de
-bidvertiser.corn, bidvertiser.com
-bankrnandiri.co.id, bankmandiri.co.id
-letour.fr, letour.fr
-yr.no, yr.no
-suning.corn, suning.com
-nosub.tv, nosub.tv
-delicious.corn, delicious.com
-pornpoly.corn, pornpoly.com
-echo.rnsk.ru, echo.msk.ru
-coingeneration.corn, coingeneration.com
-shutterfly.corn, shutterfly.com
-royalbank.corn, royalbank.com
-techradar.corn, techradar.com
-ll4la.corn, 114la.com
-bizrate.corn, bizrate.com
-srvey.net, srvey.net
-heavy-r.corn, heavy-r.com
-telexfree.corn, telexfree.com
-lego.corn, lego.com
-battlefield.corn, battlefield.com
-shahrekhabar.corn, shahrekhabar.com
-tuenti.corn, tuenti.com
-bookrnyshow.corn, bookmyshow.com
-ft.corn, ft.com
-prweb.corn, prweb.com
-l337x.org, 1337x.org
-networkedblogs.corn, networkedblogs.com
-pbskids.org, pbskids.org
-aipai.corn, aipai.com
-jang.corn.pk, jang.com.pk
-dribbble.corn, dribbble.com
-ezdownloadpro.info, ezdownloadpro.info
-gonzoxxxrnovies.corn, gonzoxxxmovies.com
-auferninin.corn, aufeminin.com
-6prn.corn, 6pm.com
-azet.sk, azet.sk
-trustedoffer.corn, trustedoffer.com
-sirnplyhired.corn, simplyhired.com
-adserverpub.corn, adserverpub.com
-privalia.corn, privalia.com
-bedbathandbeyond.corn, bedbathandbeyond.com
-yyets.corn, yyets.com
-verycd.corn, verycd.com
-sbnation.corn, sbnation.com
-blogspot.nl, blogspot.nl
-ikariarn.corn, ikariam.com
-sitepoint.corn, sitepoint.com
-gazeta.ru, gazeta.ru
-tataindicorn.corn, tataindicom.com
-chekb.corn, chekb.com
-literotica.corn, literotica.com
-ah-rne.corn, ah-me.com
-eztv.it, eztv.it
-onliner.by, onliner.by
-pptv.corn, pptv.com
-rnacrurnors.corn, macrumors.com
-xvideo-jp.corn, xvideo-jp.com
-state.tx.us, state.tx.us
-jarnnews.ir, jamnews.ir
-etoro.corn, etoro.com
-ny.gov, ny.gov
-searchenginewatch.corn, searchenginewatch.com
-google.co.cr, google.co.cr
-td.corn, td.com
-ahrefs.corn, ahrefs.com
-337.corn, 337.com
-klout.corn, klout.com
-ebay.es, ebay.es
-theverge.corn, theverge.com
-kapook.corn, kapook.com
-barclays.co.uk, barclays.co.uk
-nuorni.corn, nuomi.com
-index-of-rnp3s.corn, index-of-mp3s.com
-ohfreesex.corn, ohfreesex.com
-rnts.ru, mts.ru
-instantcheckrnate.corn, instantcheckmate.com
-sport.es, sport.es
-sitescout.corn, sitescout.com
-irr.ru, irr.ru
-tuniu.corn, tuniu.com
-startirnes.corn, startimes.com
-tvn24.pl, tvn24.pl
-kenhl4.vn, kenh14.vn
-rnyvideo.de, myvideo.de
-speedbit.corn, speedbit.com
-aljazeera.corn, aljazeera.com
-pudelek.pl, pudelek.pl
-rnrngp.ru, mmgp.ru
-ernpflix.corn, empflix.com
-tigerdirect.corn, tigerdirect.com
-elegantthernes.corn, elegantthemes.com
-ted.corn, ted.com
-downloads.corn, down1oads.com
-bancobrasil.corn.br, bancobrasil.com.br
-qip.ru, qip.ru
-fapdu.corn, fapdu.com
-softango.corn, softango.com
-ap.org, ap.org
-rneteofrance.corn, meteofrance.com
-gentenocturna.corn, gentenocturna.com
-2ch-c.net, 2ch-c.net
-orf.at, orf.at
-rnaybank2u.corn.rny, maybank2u.com.my
-rninecraftwiki.net, minecraftwiki.net
-tv.corn, tv.com
-orkut.corn, orkut.com
-adp.corn, adp.com
-woorank.corn, woorank.com
-irnagetwist.corn, imagetwist.com
-pastebin.corn, pastebin.com
-airtel.corn, airtel.com
-ew.corn, ew.com
-forever2l.corn, forever21.com
-adarn4adarn.corn, adam4adam.com
-voyages-sncf.corn, voyages-sncf.com
-nextag.corn, nextag.com
-usnews.corn, usnews.com
-dinarnalar.corn, dinamalar.com
-virginrnedia.corn, virginmedia.com
-investopedia.corn, investopedia.com
-seekingalpha.corn, seekingalpha.com
-jurnponhottie.corn, jumponhottie.com
-national-lottery.co.uk, national-lottery.co.uk
-rnobifiesta.corn, mobifiesta.com
-kapanlagi.corn, kapanlagi.com
-segundarnano.es, segundamano.es
-gfan.corn, gfan.com
-xdating.corn, xdating.com
-ynet.corn, ynet.com
-rnedu.ir, medu.ir
-hsn.corn, hsn.com
-newsru.corn, newsru.com
-rninus.corn, minus.com
-sitetalk.corn, sitetalk.com
-aarp.org, aarp.org
-clickpaid.corn, clickpaid.com
-panorarnio.corn, panoramio.com
-webcarno.corn, webcamo.com
-yobt.tv, yobt.tv
-slutfinder.corn, slutfinder.com
-freelotto.corn, freelotto.com
-rnudah.rny, mudah.my
-toptenreviews.corn, toptenreviews.com
-caisse-epargne.fr, caisse-epargne.fr
-wirnp.corn, wimp.com
-woothernes.corn, woothemes.com
-css-tricks.corn, css-tricks.com
-coolrnath-garnes.corn, coolmath-games.com
-tagu.corn.ar, tagu.com.ar
-sheknows.corn, sheknows.com
-advancedfileoptirnizer.corn, advancedfileoptimizer.com
-drupal.org, drupal.org
-centrurn.cz, centrum.cz
-charter.net, charter.net
-adxhosting.net, adxhosting.net
-squarespace.corn, squarespace.com
-traderne.co.nz, trademe.co.nz
-sitesell.corn, sitesell.com
-birthrecods.corn, birthrecods.com
-rnegashare.info, megashare.info
-freepornvs.corn, freepornvs.com
-isna.ir, isna.ir
-ziddu.corn, ziddu.com
-airtelforurn.corn, airtelforum.com
-justin.tv, justin.tv
-Olnet.corn, 01net.com
-ed.gov, ed.gov
-no-ip.corn, no-ip.com
-nikkansports.corn, nikkansports.com
-srnashingrnagazine.corn, smashingmagazine.com
-salon.corn, salon.com
-nrnisr.corn, nmisr.com
-wanggou.corn, wanggou.com
-bayt.corn, bayt.com
-codeproject.corn, codeproject.com
-downloadha.corn, downloadha.com
-local.corn, local.com
-abola.pt, abola.pt
-delta-hornes.corn, delta-homes.com
-filrnweb.pl, filmweb.pl
-gov.uk, gov.uk
-worldoftanks.eu, worldoftanks.eu
-ads-id.corn, ads-id.com
-sergey-rnavrodi.corn, sergey-mavrodi.com
-pornoid.corn, pornoid.com
-freakshare.corn, freakshare.com
-5lfanli.corn, 51fanli.com
-bankrate.corn, bankrate.com
-grindtv.corn, grindtv.com
-webrnasterworld.corn, webmasterworld.com
-torrentz.in, torrentz.in
-bwin.corn, bwin.com
-watchtower.corn, watchtower.com
-payza.corn, payza.com
-anz.corn, anz.com
-vagalurne.corn.br, vagalume.com.br
-ozon.ru, ozon.ru
-tonicrnovies.corn, tonicmovies.com
-arbeitsagentur.de, arbeitsagentur.de
-graphicriver.net, graphicriver.net
-theweathernetwork.corn, theweathernetwork.com
-sarnsclub.corn, samsclub.com
-tribunnews.corn, tribunnews.com
-soldonsrnart.corn, soldonsmart.com
-tut.by, tut.by
-voila.fr, voila.fr
-doctissirno.fr, doctissimo.fr
-sueddeutsche.de, sueddeutsche.de
-rnarnba.ru, mamba.ru
-krnart.corn, kmart.com
-abc.es, abc.es
-rnanager.co.th, manager.co.th
-spokeo.corn, spokeo.com
-apache.org, apache.org
-tdbank.corn, tdbank.com
-asklaila.corn, asklaila.com
-adrnin5.net, admin5.net
-rtve.es, rtve.es
-ynet.co.il, ynet.co.il
-infospace.corn, infospace.com
-yirng.corn, yimg.com
-torcache.net, torcache.net
-zap2it.corn, zap2it.com
-srnallseotools.corn, smallseotools.com
-privatbank.ua, privatbank.ua
-nnrn-club.ru, nnm-club.ru
-payoneer.corn, payoneer.com
-bidorbuy.co.za, bidorbuy.co.za
-islarnweb.net, islamweb.net
-juicyads.corn, juicyads.com
-vid2c.corn, vid2c.com
-dnsrsearch.corn, dnsrsearch.com
-the-bux.net, the-bux.net
-yaplakal.corn, yaplakal.com
-ex.ua, ex.ua
-rntsindia.in, mtsindia.in
-reclarneaqui.corn.br, reclameaqui.com.br
-postbank.de, postbank.de
-gogvo.corn, gogvo.com
-bearshare.net, bearshare.net
-socialsex.corn, socialsex.com
-yebhi.corn, yebhi.com
-rnktrnobi.corn, mktmobi.com
-dfiles.eu, dfiles.eu
-citibank.co.in, citibank.co.in
-garnersky.corn, gamersky.com
-kotaku.corn, kotaku.com
-tearnviewer.corn, teamviewer.com
-kwejk.pl, kwejk.pl
-harnariweb.corn, hamariweb.com
-torn.corn, tom.com
-gayrorneo.corn, gayromeo.com
-sony.corn, sony.com
-westpac.corn.au, westpac.com.au
-gtrnetrix.corn, gtmetrix.com
-shorouknews.corn, shorouknews.com
-xl.pt, xl.pt
-networksolutions.corn, networksolutions.com
-5OOpx.corn, 500px.com
-yprnate.corn, ypmate.com
-indowebster.corn, indowebster.com
-sports.ru, sports.ru
-netshoes.corn.br, netshoes.com.br
-dfiles.ru, dfiles.ru
-cpasbien.rne, cpasbien.me
-webgarne.web.id, webgame.web.id
-tuto4pc.corn, tuto4pc.com
-poponclick.corn, poponclick.com
-cornplex.corn, complex.com
-sakshi.corn, sakshi.com
-infobae.corn, infobae.com
-sify.corn, sify.com
-4pda.ru, 4pda.ru
-starsue.net, starsue.net
-newgrounds.corn, newgrounds.com
-rnehrnews.corn, mehrnews.com
-depositphotos.corn, depositphotos.com
-keek.corn, keek.com
-indeed.co.in, indeed.co.in
-stanford.edu, stanford.edu
-hepsiburada.corn, hepsiburada.com
-2Orninutos.es, 20minutos.es
-paper.li, paper.li
-prizee.corn, prizee.com
-xlovecarn.corn, xlovecam.com
-criteo.corn, criteo.com
-endlessrnatches.corn, endlessmatches.com
-dyndns.org, dyndns.org
-lightinthebox.corn, lightinthebox.com
-easyjet.corn, easyjet.com
-vice.corn, vice.com
-tiexue.net, tiexue.net
-rnonsterrnarketplace.corn, monstermarketplace.com
-rnojang.corn, mojang.com
-carns.corn, cams.com
-pingdorn.corn, pingdom.com
-askrnen.corn, askmen.com
-list-rnanagel.corn, list-manage1.com
-express.corn.pk, express.com.pk
-pricerninister.corn, priceminister.com
-duba.corn, duba.com
-rneinestadt.de, meinestadt.de
-rnediatakeout.corn, mediatakeout.com
-terere.info, terere.info
-strearnate.corn, streamate.com
-garrnin.corn, garmin.com
-a-telecharger.corn, a-telecharger.com
-vipzona.info, vipzona.info
-coffetube.corn, coffetube.com
-discuz.net, discuz.net
-directv.corn, directv.com
-foreningssparbanken.se, foreningssparbanken.se
-fatwallet.corn, fatwallet.com
-rnackolik.corn, mackolik.com
-rnegacinerna.fr, megacinema.fr
-chess.corn, chess.com
-suntrust.corn, suntrust.com
-investing.corn, investing.com
-whois.corn, whois.com
-durnrnies.corn, dummies.com
-yinyuetai.corn, yinyuetai.com
-rnihandownload.corn, mihandownload.com
-freapp.corn, freapp.com
-theage.corn.au, theage.com.au
-audible.corn, audible.com
-hotelurbano.corn.br, hotelurbano.com.br
-vatgia.corn, vatgia.com
-wizardlOl.corn, wizard101.com
-ceneo.pl, ceneo.pl
-lting.corn, 1ting.com
-rneetic.fr, meetic.fr
-cardekho.corn, cardekho.com
-tripadvisor.it, tripadvisor.it
-dhl.corn, dhl.com
-aibang.corn, aibang.com
-asp.net, asp.net
-toing.corn.br, toing.com.br
-zhubajie.corn, zhubajie.com
-telecornitalia.it, telecomitalia.it
-claro-search.corn, claro-search.com
-nickjr.corn, nickjr.com
-iconfinder.corn, iconfinder.com
-rnobile9.corn, mobile9.com
-cisco.corn, cisco.com
-cpanel.net, cpanel.net
-indiegogo.corn, indiegogo.com
-egotastic.corn, egotastic.com
-hforcare.corn, hforcare.com
-pbs.org, pbs.org
-realestate.corn.au, realestate.com.au
-abv.bg, abv.bg
-drugs.corn, drugs.com
-bt.corn, bt.com
-wildberries.ru, wildberries.ru
-edrearns.it, edreams.it
-statigr.arn, statigr.am
-prestashop.corn, prestashop.com
-adxite.corn, adxite.com
-birthdaypeorns.corn, birthdaypeoms.com
-exbii.corn, exbii.com
-blogrnura.corn, blogmura.com
-sciencedirect.corn, sciencedirect.com
-sanspo.corn, sanspo.com
-nextrnedia.corn, nextmedia.com
-tvoyauda4a.ru, tvoyauda4a.ru
-tangdou.corn, tangdou.com
-blackboard.corn, blackboard.com
-qiyou.corn, qiyou.com
-prezentacya.ru, prezentacya.ru
-clicrbs.corn.br, clicrbs.com.br
-wayfair.corn, wayfair.com
-xvideos-field.corn, xvideos-field.com
-national.corn.au, national.com.au
-friendfeed.corn, friendfeed.com
-plurk.corn, plurk.com
-lolrnake.corn, lolmake.com
-b9drn.corn, b9dm.com
-afkarnews.ir, afkarnews.ir
-dhl.de, dhl.de
-charnpionat.corn, championat.com
-rnoviefone.corn, moviefone.com
-popcash.net, popcash.net
-cliphunter.corn, cliphunter.com
-sharebeast.corn, sharebeast.com
-wowhead.corn, wowhead.com
-firstpost.corn, firstpost.com
-lloydstsb.corn, lloydstsb.com
-fazenda.gov.br, fazenda.gov.br
-lonelyplanet.corn, lonelyplanet.com
-freenet.de, freenet.de
-justanswer.corn, justanswer.com
-qiwi.corn, qiwi.com
-shufuni.corn, shufuni.com
-drive2.ru, drive2.ru
-slando.ua, slando.ua
-caribbeancorn.corn, caribbeancom.com
-uniblue.corn, uniblue.com
-real.corn, real.com
-addictinggarnes.corn, addictinggames.com
-wnd.corn, wnd.com
-col3negoriginal.org, col3negoriginal.org
-loltrk.corn, loltrk.com
-videodownloadconverter.corn, videodownloadconverter.com
-google.lv, google.lv
-seriesyonkis.corn, seriesyonkis.com
-ryushare.corn, ryushare.com
-sl979.corn, s1979.com
-cheapoair.corn, cheapoair.com
-subrnarino.corn.br, submarino.com.br
-topface.corn, topface.com
-hotelscornbined.corn, hotelscombined.com
-whatisrnyipaddress.corn, whatismyipaddress.com
-z6.corn, z6.com
-sozcu.corn.tr, sozcu.com.tr
-sonyrnobile.corn, sonymobile.com
-planetrninecraft.corn, planetminecraft.com
-optirnurn.net, optimum.net
-google.corn.pr, google.com.pr
-rnthai.corn, mthai.com
-onlinecreditcenter6.corn, onlinecreditcenter6.com
-tharunaya.co.uk, tharunaya.co.uk
-sfirng.corn, sfimg.com
-natwest.corn, natwest.com
-zergnet.corn, zergnet.com
-alotporn.corn, alotporn.com
-urbanspoon.corn, urbanspoon.com
-punishtube.corn, punishtube.com
-proboards.corn, proboards.com
-betfair.corn, betfair.com
-iltasanornat.fi, iltasanomat.fi
-ssisurveys.corn, ssisurveys.com
-harvard.edu, harvard.edu
-blic.rs, blic.rs
-clicksia.corn, clicksia.com
-skillpages.corn, skillpages.com
-rnobilewap.corn, mobilewap.com
-fiducia.de, fiducia.de
-torntvz.org, torntvz.org
-leparisien.fr, leparisien.fr
-anjuke.corn, anjuke.com
-rabobank.nl, rabobank.nl
-sport.pl, sport.pl
-schwab.corn, schwab.com
-buenastareas.corn, buenastareas.com
-befuck.corn, befuck.com
-srnart-search.corn, smart-search.com
-ivi.ru, ivi.ru
-dvdvideosoft.corn, dvdvideosoft.com
-ubi.corn, ubi.com
-rnakepolo.corn, makepolo.com
-landl.corn, 1and1.com
-pcworld.corn, pcworld.com
-caf.fr, caf.fr
-fnb.co.za, fnb.co.za
-vanguardngr.corn, vanguardngr.com
-floozycity.corn, floozycity.com
-ubuntu.corn, ubuntu.com
-rny-link.pro, my-link.pro
-centurylink.corn, centurylink.com
-slashdot.org, slashdot.org
-rnirrorcreator.corn, mirrorcreator.com
-rutube.ru, rutube.ru
-tubeplus.rne, tubeplus.me
-kicker.de, kicker.de
-unibet.corn, unibet.com
-pornyaz.corn, pornyaz.com
-learntotradethernarket.corn, learntotradethemarket.com
-tokyo-porn-tube.corn, tokyo-porn-tube.com
-luvcow.corn, luvcow.com
-i.ua, i.ua
-ole.corn.ar, ole.com.ar
-redfin.corn, redfin.com
-cnki.net, cnki.net
-2shared.corn, 2shared.com
-infibearn.corn, infibeam.com
-zdnet.corn, zdnet.com
-fishki.net, fishki.net
-ukr.net, ukr.net
-jiarneng.corn, jiameng.com
-utorrent.corn, utorrent.com
-elkhabar.corn, elkhabar.com
-anirne44.corn, anime44.com
-societegenerale.fr, societegenerale.fr
-livernerne.corn, livememe.com
-startertv.fr, startertv.fr
-pingornatic.corn, pingomatic.com
-indeed.co.uk, indeed.co.uk
-dpstrearn.net, dpstream.net
-rnundodeportivo.corn, mundodeportivo.com
-gravatar.corn, gravatar.com
-ipl38.corn, ip138.com
-yandex.net, yandex.net
-barbie.corn, barbie.com
-wattpad.corn, wattpad.com
-dzwww.corn, dzwww.com
-technorati.corn, technorati.com
-rneishichina.corn, meishichina.com
-russianpost.ru, russianpost.ru
-kboing.corn.br, kboing.com.br
-lzjl.corn, lzjl.com
-newsnow.co.uk, newsnow.co.uk
-dw.de, dw.de
-inetglobal.corn, inetglobal.com
-tripadvisor.in, tripadvisor.in
-ashleyrnadison.corn, ashleyrnadison.com
-rapgenius.corn, rapgenius.com
-xuite.net, xuite.net
-nowvideo.eu, nowvideo.eu
-search.us.corn, search.us.com
-usagc.org, usagc.org
-santander.co.uk, santander.co.uk
-99acres.corn, 99acres.com
-bigcartel.corn, bigcartel.com
-haivl.corn, haivl.com
-jsfiddle.net, jsfiddle.net
-io9.corn, io9.com
-lg.corn, lg.com
-veoh.corn, veoh.com
-dafiti.corn.br, dafiti.com.br
-heise.de, heise.de
-wikispaces.corn, wikispaces.com
-google.corn.bo, google.com.bo
-skyscrapercity.corn, skyscrapercity.com
-zaobao.corn, zaobao.com
-pirateproxy.net, pirateproxy.net
-rnuyzorras.corn, muyzorras.com
-entrepreneur.corn, entrepreneur.com
-sxc.hu, sxc.hu
-superuser.corn, superuser.com
-jb5l.net, jb51.net
-bitsnoop.corn, bitsnoop.com
-index.hu, index.hu
-tubexclips.corn, tubexclips.com
-syrnantec.corn, symantec.com
-sedo.corn, sedo.com
-gongchang.corn, gongchang.com
-newsrnth.net, newsmth.net
-srclick.ru, srclick.ru
-bornnegocio.corn, bomnegocio.com
-ornegle.corn, omegle.com
-sweetpacks-search.corn, sweetpacks-search.com
-OOOwebhost.corn, 000webhost.com
-rencontreshard.corn, rencontreshard.com
-jurnei.corn, jumei.com
-acfun.tv, acfun.tv
-celebuzz.corn, celebuzz.com
-el-balad.corn, el-balad.com
-wajarn.corn, wajam.com
-zoopla.co.uk, zoopla.co.uk
-sc4888.corn, sc4888.com
-rnobileaziende.it, mobileaziende.it
-officialsurvey.org, officialsurvey.org
-googleapis.corn, googleapis.com
-jobsdb.corn, jobsdb.com
-google.corn.sv, google.com.sv
-freejobalert.corn, freejobalert.com
-walla.co.il, walla.co.il
-hollywoodreporter.corn, hollywoodreporter.com
-inc.corn, inc.com
-bbandt.corn, bbandt.com
-williarnhill.corn, williamhill.com
-jeu.info, jeu.info
-vrbo.corn, vrbo.com
-arabseed.corn, arabseed.com
-spielaffe.de, spielaffe.de
-wykop.pl, wykop.pl
-narne.corn, name.com
-web-opinions.corn, web-opinions.com
-ehowenespanol.corn, ehowenespanol.com
-uuzu.corn, uuzu.com
-cafepress.corn, cafepress.com
-beeline.ru, beeline.ru
-searchenginejournal.corn, searchenginejournal.com
-webex.corn, webex.com
-zerohedge.corn, zerohedge.com
-cityads.ru, cityads.ru
-colurnbia.edu, columbia.edu
-jia.corn, jia.com
-tistory.corn, tistory.com
-lOObestbuy.corn, 100bestbuy.com
-realitykings.corn, realitykings.com
-shopify.corn, shopify.com
-garnetop.corn, gametop.com
-eharrnony.corn, eharmony.com
-ngoisao.net, ngoisao.net
-angieslist.corn, angieslist.com
-grotal.corn, grotal.com
-rnanhunt.net, manhunt.net
-adslgate.corn, adslgate.com
-dernotywatory.pl, demotywatory.pl
-enfernenino.corn, enfemenino.com
-yallakora.corn, yallakora.com
-careesrna.in, careesma.in
-draugiern.lv, draugiem.lv
-greatandhra.corn, greatandhra.com
-lifescript.corn, lifescript.com
-androidcentral.corn, androidcentral.com
-wiley.corn, wiley.com
-alot.corn, alot.com
-lOOlO.corn, 10010.com
-next.co.uk, next.co.uk
-ll5.corn, 115.com
-orngprn.corn, omgpm.com
-rnycalendarbook.corn, mycalendarbook.com
-playxn.corn, playxn.com
-niksalehi.corn, niksalehi.com
-serviporno.corn, serviporno.com
-poste.it, poste.it
-kirniss.corn, kimiss.com
-bearshare.corn, bearshare.com
-clickpoint.corn, clickpoint.com
-seek.corn.au, seek.com.au
-bab.la, bab.la
-ads8.corn, ads8.com
-viewster.corn, viewster.com
-ideacellular.corn, ideacellular.com
-tyrnpanus.net, tympanus.net
-wwwblogto.corn, wwwblogto.com
-tblop.corn, tblop.com
-elong.corn, elong.com
-funnyordie.corn, funnyordie.com
-radikal.ru, radikal.ru
-rk.corn, rk.com
-alarab.net, alarab.net
-willhaben.at, willhaben.at
-beyond.corn, beyond.com
-punchng.corn, punchng.com
-viglink.corn, viglink.com
-rnicrosoftstore.corn, microsoftstore.com
-tripleclicks.corn, tripleclicks.com
-rnl9O5.corn, m1905.com
-ofreegarnes.corn, ofreegames.com
-s2d6.corn, s2d6.com
-36Obuy.corn, 360buy.com
-rakuten.corn, rakuten.com
-evite.corn, evite.com
-kornpasiana.corn, kompasiana.com
-dailycaller.corn, dailycaller.com
-holidaycheck.de, holidaycheck.de
-irnvu.corn, imvu.com
-nate.corn, nate.com
-fnac.corn, fnac.com
-htc.corn, htc.com
-savenkeep.corn, savenkeep.com
-alfabank.ru, alfabank.ru
-zaycev.net, zaycev.net
-vidtornp3.corn, vidtomp3.com
-eluniversal.corn.rnx, eluniversal.com.mx
-theatlantic.corn, theatlantic.com
-garnigo.de, gamigo.de
-lolking.net, lolking.net
-wer-kennt-wen.de, wer-kennt-wen.de
-stern.de, stern.de
-sportl.de, sport1.de
-goalunited.org, goalunited.org
-discogs.corn, discogs.com
-whirlpool.net.au, whirlpool.net.au
-savefrorn.net, savefrom.net
-eurosport.fr, eurosport.fr
-juegosjuegos.corn, juegosjuegos.com
-open24news.tv, open24news.tv
-sinaapp.corn, sinaapp.com
-fuq.corn, fuq.com
-index.hr, index.hr
-realpopbid.corn, realpopbid.com
-rollingstone.corn, rollingstone.com
-globaltestrnarket.corn, globaltestmarket.com
-seopult.ru, seopult.ru
-wurnii.corn, wumii.com
-ford.corn, ford.com
-cabelas.corn, cabelas.com
-securepaynet.net, securepaynet.net
-zhibo8.cc, zhibo8.cc
-jiji.corn, jiji.com
-gezinti.corn, gezinti.com
-rneb.gov.tr, meb.gov.tr
-classifiedads.corn, classifiedads.com
-kitco.corn, kitco.com
-incredirnail.corn, incredimail.com
-esrnas.corn, esmas.com
-soccerway.corn, soccerway.com
-rivals.corn, rivals.com
-prezi.corn, prezi.com
-shopping.corn, shopping.com
-superjob.ru, superjob.ru
-chinaacc.corn, chinaacc.com
-arnoureux.corn, amoureux.com
-rnysrnartprice.corn, mysmartprice.com
-eleconornista.es, eleconomista.es
-rnercola.corn, mercola.com
-irnlive.corn, imlive.com
-teacup.corn, teacup.com
-rnodelrnayhern.corn, modelmayhem.com
-nic.ru, nic.ru
-brazzersnetwork.corn, brazzersnetwork.com
-everything.org.uk, everything.org.uk
-bhg.corn, bhg.com
-longhoo.net, longhoo.net
-superpages.corn, superpages.com
-tny.cz, tny.cz
-yourfilezone.corn, yourfilezone.com
-tuan8OO.corn, tuan800.com
-streev.corn, streev.com
-sedty.corn, sedty.com
-boxofficernojo.corn, boxofficemojo.com
-hollyscoop.corn, hollyscoop.com
-safecart.corn, safecart.com
-alrnogaz.corn, almogaz.com
-cashnhits.corn, cashnhits.com
-wetplace.corn, wetplace.com
-freepik.corn, freepik.com
-rarbg.corn, rarbg.com
-xxxbunker.corn, xxxbunker.com
-prchecker.info, prchecker.info
-halifax-online.co.uk, halifax-online.co.uk
-trafficfactory.biz, trafficfactory.biz
-telecinco.es, telecinco.es
-searchterrnresults.corn, searchtermresults.com
-unarn.rnx, unam.mx
-akhbar-elwatan.corn, akhbar-elwatan.com
-lynda.corn, lynda.com
-yougetlaid.corn, yougetlaid.com
-srnart.corn.au, smart.com.au
-advfn.corn, advfn.com
-unicredit.it, unicredit.it
-zornato.corn, zomato.com
-flirt.corn, flirt.com
-netease.corn, netease.com
-bnpparibas.net, bnpparibas.net
-elcornercio.pe, elcomercio.pe
-rnathrubhurni.corn, mathrubhumi.com
-koyotesoft.corn, koyotesoft.com
-filrnix.net, filmix.net
-xnxxhdtube.corn, xnxxhdtube.com
-ennaharonline.corn, ennaharonline.com
-junbi-tracker.corn, junbi-tracker.com
-buzzdock.corn, buzzdock.com
-ernirates.corn, emirates.com
-vivanuncios.corn.rnx, vivanuncios.com.mx
-infojobs.net, infojobs.net
-srni2.ru, smi2.ru
-lotterypost.corn, lotterypost.com
-bandcarnp.corn, bandcamp.com
-ekstrabladet.dk, ekstrabladet.dk
-nownews.corn, nownews.com
-bc.vc, bc.vc
-google.corn.af, google.com.af
-ulrnart.ru, ulmart.ru
-estadao.corn.br, estadao.com.br
-politico.corn, politico.com
-kl688.corn, kl688.com
-resellerclub.corn, resellerclub.com
-whois.net, whois.net
-seobuilding.ru, seobuilding.ru
-t4ll.rne, t411.me
-googlesyndication.corn, googlesyndication.com
-delfi.lt, delfi.lt
-eqla3.corn, eqla3.com
-ali2l3.net, ali213.net
-fanpage.it, fanpage.it
-uptobox.corn, uptobox.com
-google.jo, google.jo
-cncn.corn, cncn.com
-srne.sk, sme.sk
-kinozal.tv, kinozal.tv
-ceconline.corn, ceconline.com
-billboard.corn, billboard.com
-citi.corn, citi.com
-naughtyarnerica.corn, naughtyamerica.com
-classrnates.corn, classmates.com
-coursera.org, coursera.org
-pingan.corn, pingan.com
-voanews.corn, voanews.com
-tankionline.corn, tankionline.com
-jetblue.corn, jetblue.com
-spainshtranslation.corn, spainshtranslation.com
-ebookbrowse.corn, ebookbrowse.com
-rnet-art.corn, met-art.com
-rnegafon.ru, megafon.ru
-quibids.corn, quibids.com
-srnartfren.corn, smartfren.com
-cleartrip.corn, cleartrip.com
-pixrnania.corn, pixmania.com
-vivastreet.corn, vivastreet.com
-thegfnetwork.corn, thegfnetwork.com
-paytrn.corn, paytm.com
-rneinsextagebuch.net, meinsextagebuch.net
-rnernecenter.corn, memecenter.com
-ixbt.corn, ixbt.com
-dagbladet.no, dagbladet.no
-basecarnphq.corn, basecamphq.com
-chinatirnes.corn, chinatimes.com
-bubblews.corn, bubblews.com
-xtool.ru, xtool.ru
-opodo.co.uk, opodo.co.uk
-hattrick.org, hattrick.org
-zopirn.corn, zopim.com
-aol.co.uk, aol.co.uk
-gazzetta.gr, gazzetta.gr
-l8andabused.corn, 18andabused.com
-rncssl.corn, mcssl.com
-econornist.corn, economist.com
-zeit.de, zeit.de
-google.corn.uy, google.com.uy
-pinoy-ako.info, pinoy-ako.info
-lazada.co.id, lazada.co.id
-filgoal.corn, filgoal.com
-rozetka.corn.ua, rozetka.com.ua
-alrnesryoon.corn, almesryoon.com
-csrnonitor.corn, csmonitor.com
-bizjournals.corn, bizjournals.com
-rackspace.corn, rackspace.com
-webgozar.corn, webgozar.com
-opencart.corn, opencart.com
-rnediaplex.corn, mediaplex.com
-deutsche-bank.de, deutsche-bank.de
-sirnilarsites.corn, similarsites.com
-sotrnarket.ru, sotmarket.ru
-chatzurn.corn, chatzum.com
-huffingtonpost.co.uk, huffingtonpost.co.uk
-carwale.corn, carwale.com
-rnernez.corn, memez.com
-hostrnonster.corn, hostmonster.com
-rnuzofon.corn, muzofon.com
-elephanttube.corn, elephanttube.com
-crunchbase.corn, crunchbase.com
-irnhonet.ru, imhonet.ru
-lusongsong.corn, lusongsong.com
-filrnesonlinegratis.net, filmesonlinegratis.net
-giaoduc.net.vn, giaoduc.net.vn
-rnanhub.corn, manhub.com
-tatadocorno.corn, tatadocomo.com
-realitatea.net, realitatea.net
-freernp3x.corn, freemp3x.com
-freernail.hu, freemail.hu
-ganool.corn, ganool.com
-feedreader.corn, feedreader.com
-sportsdirect.corn, sportsdirect.com
-videolan.org, videolan.org
-watchseries.lt, watchseries.lt
-rotapost.ru, rotapost.ru
-nwolb.corn, nwolb.com
-searchquotes.corn, searchquotes.com
-kaspersky.corn, kaspersky.com
-go2cloud.org, go2cloud.org
-grepolis.corn, grepolis.com
-profit-partner.ru, profit-partner.ru
-articlesbase.corn, articlesbase.com
-dns-shop.ru, dns-shop.ru
-radikal.corn.tr, radikal.com.tr
-justjared.corn, justjared.com
-lancenet.corn.br, lancenet.com.br
-rnangapanda.corn, mangapanda.com
-theglobeandrnail.corn, theglobeandmail.com
-ecollege.corn, ecollege.com
-rnyanirnelist.net, myanimelist.net
-fotornac.corn.tr, fotomac.com.tr
-irnanhua.corn, imanhua.com
-travelzoo.corn, travelzoo.com
-jjwxc.net, jjwxc.net
-q.gs, q.gs
-naaptol.corn, naaptol.com
-sarnbaporno.corn, sambaporno.com
-rnacrojuegos.corn, macrojuegos.com
-ooo-sex.corn, ooo-sex.com
-fab.corn, fab.com
-roflzone.corn, roflzone.com
-searchcornpletion.corn, searchcompletion.com
-jezebel.corn, jezebel.com
-bizdec.ru, bizdec.ru
-torrentino.corn, torrentino.com
-rnultitran.ru, multitran.ru
-tune-up.corn, tune-up.com
-sparkpeople.corn, sparkpeople.com
-desi-tashan.corn, desi-tashan.com
-rnashreghnews.ir, mashreghnews.ir
-talktalk.co.uk, talktalk.co.uk
-hinkhoj.corn, hinkhoj.com
-2Orninutes.fr, 20minutes.fr
-sulia.corn, sulia.com
-icirns.corn, icims.com
-dizi-rnag.corn, dizi-mag.com
-webaslan.corn, webaslan.com
-en.wordpress.corn, en.wordpress.com
-funrnoods.corn, funmoods.com
-softgozar.corn, softgozar.com
-starwoodhotels.corn, starwoodhotels.com
-studiopress.corn, studiopress.com
-click.in, click.in
-rneetcheap.corn, meetcheap.com
-angel-live.corn, angel-live.com
-beforeitsnews.corn, beforeitsnews.com
-trello.corn, trello.com
-icontact.corn, icontact.com
-prlog.org, prlog.org
-incentria.corn, incentria.com
-bouyguestelecorn.fr, bouyguestelecom.fr
-dstv.corn, dstv.com
-arstechnica.corn, arstechnica.com
-diigo.corn, diigo.com
-consurners-research.corn, consumers-research.com
-rnetaffiliation.corn, metaffiliation.com
-telekorn.de, telekom.de
-izlesene.corn, izlesene.com
-newsit.gr, newsit.gr
-fuckingawesorne.corn, fuckingawesome.com
-osyrn.gov.tr, osym.gov.tr
-svyaznoy.ru, svyaznoy.ru
-watchfreernovies.ch, watchfreemovies.ch
-gurntree.pl, gumtree.pl
-sportbox.ru, sportbox.ru
-reserverunessai.corn, reserverunessai.com
-hsbc.corn.hk, hsbc.com.hk
-cricbuzz.corn, cricbuzz.com
-djelfa.info, djelfa.info
-nouvelobs.corn, nouvelobs.com
-aruba.it, aruba.it
-hornes.corn, homes.com
-allezleslions.corn, allezleslions.com
-orkut.corn.br, orkut.com.br
-aionfreetoplay.corn, aionfreetoplay.com
-acadernia.edu, academia.edu
-consurnerreports.org, consumerreports.org
-ilsole24ore.corn, ilsole24ore.com
-sephora.corn, sephora.com
-lds.org, lds.org
-vrnall.corn, vmall.com
-ultirnasnoticias.corn.ve, ultimasnoticias.com.ve
-healthgrades.corn, healthgrades.com
-irngbox.corn, imgbox.com
-dlsite.corn, dlsite.com
-whitesrnoke.corn, whitesmoke.com
-thenextweb.corn, thenextweb.com
-qirel23.corn, qire123.com
-peeplo.corn, peeplo.com
-chitika.corn, chitika.com
-alwafd.org, alwafd.org
-phonearena.corn, phonearena.com
-ovh.corn, ovh.com
-tusfiles.net, tusfiles.net
-l8schoolgirlz.corn, 18schoolgirlz.com
-bongacarns.corn, bongacams.com
-horne.pl, home.pl
-footrnercato.net, footmercato.net
-sprashivai.ru, sprashivai.ru
-rnegafilrneshd.net, megafilmeshd.net
-prerniurn-display.corn, premium-display.com
-clickey.corn, clickey.com
-tokyo-tube.corn, tokyo-tube.com
-watch32.corn, watch32.com
-pornolab.net, pornolab.net
-tirnewarnercable.corn, timewarnercable.com
-naturalnews.corn, naturalnews.com
-afirnet.corn, afimet.com
-telderi.ru, telderi.ru
-ioffer.corn, ioffer.com
-lapatilla.corn, lapatilla.com
-livetv.ru, livetv.ru
-cloudflare.corn, cloudflare.com
-lupoporno.corn, lupoporno.com
-nhaccuatui.corn, nhaccuatui.com
-thepostgarne.corn, thepostgame.com
-ipage.corn, ipage.com
-banesconline.corn, banesconline.com
-cdc.gov, cdc.gov
-adonweb.ru, adonweb.ru
-zone-telechargernent.corn, zone-telechargement.com
-intellicast.corn, intellicast.com
-uloz.to, uloz.to
-pikabu.ru, pikabu.ru
-rnegogo.net, megogo.net
-wenxuecity.corn, wenxuecity.com
-xrnl-siternaps.corn, xml-sitemaps.com
-webdunia.corn, webdunia.com
-justhost.corn, justhost.com
-starbucks.corn, starbucks.com
-wargarning.net, wargaming.net
-hugedornains.corn, hugedomains.com
-rnagicbricks.corn, magicbricks.com
-gigporno.corn, gigporno.com
-rikunabi.corn, rikunabi.com
-5lauto.corn, 51auto.com
-warriorplus.corn, warriorplus.com
-gudvin.tv, gudvin.tv
-bigrnir.net, bigmir.net
-ansa.it, ansa.it
-standardbank.co.za, standardbank.co.za
-toshiba.corn, toshiba.com
-xinnet.corn, xinnet.com
-geico.corn, geico.com
-funnyjunk.corn, funnyjunk.com
-affaritaliani.it, affaritaliani.it
-cityheaven.net, cityheaven.net
-tubewolf.corn, tubewolf.com
-google.org, google.org
-ad.nl, ad.nl
-tutorialspoint.corn, tutorialspoint.com
-uidai.gov.in, uidai.gov.in
-everydayhealth.corn, everydayhealth.com
-jzip.corn, jzip.com
-lolspotsarticles.corn, lolspotsarticles.com
-rueducornrnerce.fr, rueducommerce.fr
-lvrnarna.corn, lvmama.com
-roboforrn.corn, roboform.com
-zoznarn.sk, zoznam.sk
-livesrni.corn, livesmi.com
-die-boersenforrnel.corn, die-boersenformel.com
-watchcartoononline.corn, watchcartoononline.com
-abclocal.go.corn, abclocal.go.com
-techrepublic.corn, techrepublic.com
-just-fuck.corn, just-fuck.com
-carnster.corn, camster.com
-akairan.corn, akairan.com
-yeslibertin.corn, yeslibertin.com
-abc.go.corn, abc.go.com
-searchtherightwords.corn, searchtherightwords.com
-scotiabank.corn, scotiabank.com
-justclick.ru, justclick.ru
-douguo.corn, douguo.com
-discover.corn, discover.com
-britishairways.corn, britishairways.com
-rnobafire.corn, mobafire.com
-gi-akadernie.ning.corn, gi-akademie.ning.com
-desirulez.net, desirulez.net
-qiushibaike.corn, qiushibaike.com
-rnoonbasa.corn, moonbasa.com
-all.biz, all.biz
-springer.corn, springer.com
-ernai.corn, emai.com
-deadspin.corn, deadspin.com
-hulkshare.corn, hulkshare.com
-fast-torrent.ru, fast-torrent.ru
-oriflarne.corn, oriflame.com
-irngchili.net, imgchili.net
-rnega-juegos.rnx, mega-juegos.mx
-gyazo.corn, gyazo.com
-persianv.corn, persianv.com
-adk2.corn, adk2.com
-ingbank.pl, ingbank.pl
-nationalconsurnercenter.corn, nationalconsumercenter.com
-xxxkinky.corn, xxxkinky.com
-rnywot.corn, mywot.com
-gayrnaletube.corn, gaymaletube.com
-ltv.ru, 1tv.ru
-rnanutd.corn, manutd.com
-rnerchantcircle.corn, merchantcircle.com
-canalblog.corn, canalblog.com
-capitalone36O.corn, capitalone360.com
-tlbb8.corn, tlbb8.com
-softonic.fr, softonic.fr
-ccavenue.corn, ccavenue.com
-tyroodr.corn, tyroodr.com
-exarn8.corn, exam8.com
-allrnusic.corn, allmusic.com
-stubhub.corn, stubhub.com
-arcor.de, arcor.de
-yolasite.corn, yolasite.com
-haraj.corn.sa, haraj.com.sa
-rnypopup.ir, mypopup.ir
-rnernurlar.net, memurlar.net
-srnugrnug.corn, smugmug.com
-filefactory.corn, filefactory.com
-fantasti.cc, fantasti.cc
-bokra.net, bokra.net
-goarticles.corn, goarticles.com
-rnoneysavingexpert.corn, moneysavingexpert.com
-donga.corn, donga.com
-lastrninute.corn, lastminute.com
-xkcd.corn, xkcd.com
-sou3OO.corn, sou300.com
-rnagnovideo.corn, magnovideo.com
-inquirer.net, inquirer.net
-phoenix.edu, phoenix.edu
-videogenesis.corn, videogenesis.com
-thestar.corn, thestar.com
-tripadvisor.es, tripadvisor.es
-blankrefer.corn, blankrefer.com
-yle.fi, yle.fi
-bearntele.corn, beamtele.com
-oanda.corn, oanda.com
-iheart.corn, iheart.com
-google.co.tz, google.co.tz
-stargazete.corn, stargazete.com
-bossip.corn, bossip.com
-defaultsear.ch, defaultsear.ch
-thaiseoboard.corn, thaiseoboard.com
-qinbei.corn, qinbei.com
-ninisite.corn, ninisite.com
-j.gs, j.gs
-nos.nl, nos.nl
-qualtrics.corn, qualtrics.com
-kornrnersant.ru, kommersant.ru
-urban-rivals.corn, urban-rivals.com
-cornputerbild.de, computerbild.de
-fararu.corn, fararu.com
-rnenshealth.corn, menshealth.com
-jobstreet.corn, jobstreet.com
-rbcroyalbank.corn, rbcroyalbank.com
-inrnotionhosting.corn, inmotionhosting.com
-surveyrouter.corn, surveyrouter.com
-kankanews.corn, kankanews.com
-aol.de, aol.de
-bol.corn, bol.com
-datpiff.corn, datpiff.com
-rnplife.corn, mplife.com
-sale-fire.corn, sale-fire.com
-inbox.lv, inbox.lv
-offeraturn.corn, offeratum.com
-pandora.tv, pandora.tv
-eltiernpo.corn, eltiempo.com
-indiarailinfo.corn, indiarailinfo.com
-solidtrustpay.corn, solidtrustpay.com
-warthunder.ru, warthunder.ru
-novarnov.corn, novamov.com
-folkd.corn, folkd.com
-envato.corn, envato.com
-wetpaint.corn, wetpaint.com
-ternpo.co, tempo.co
-howtogeek.corn, howtogeek.com
-foundationapi.corn, foundationapi.com
-care2.corn, care2.com
-bendibao.corn, bendibao.com
-rnazika2day.corn, mazika2day.com
-asda.corn, asda.com
-nowvideo.ch, nowvideo.ch
-hiapk.corn, hiapk.com
-l7u.corn, 17u.com
-tutu.ru, tutu.ru
-ncdownloader.corn, ncdownloader.com
-warez-bb.org, warez-bb.org
-jsoftj.corn, jsoftj.com
-xrnarks.corn, xmarks.com
-36kr.corn, 36kr.com
-runetki.corn, runetki.com
-quoka.de, quoka.de
-heureka.cz, heureka.cz
-rnonografias.corn, monografias.com
-zhenai.corn, zhenai.com
-4porn.corn, 4porn.com
-antena3.corn, antena3.com
-lintas.rne, lintas.me
-seroundtable.corn, seroundtable.com
-el.ru, e1.ru
-berkeley.edu, berkeley.edu
-officedepot.corn, officedepot.com
-rnyflorida.corn, myflorida.com
-parispornrnovies.corn, parispornmovies.com
-uniqlo.corn, uniqlo.com
-topky.sk, topky.sk
-lurnovies.corn, lumovies.com
-buysellads.corn, buysellads.com
-stirileprotv.ro, stirileprotv.ro
-scottrade.corn, scottrade.com
-rnrntrends.net, mmtrends.net
-wholesale-dress.net, wholesale-dress.net
-rnetacritic.corn, metacritic.com
-pichunter.corn, pichunter.com
-rnoneybookers.corn, moneybookers.com
-idealista.corn, idealista.com
-buzzle.corn, buzzle.com
-rcorn.co.in, rcom.co.in
-weightwatchers.corn, weightwatchers.com
-itv.corn, itv.com
-inilah.corn, inilah.com
-vic.gov.au, vic.gov.au
-prorn.ua, prom.ua
-with2.net, with2.net
-doodle.corn, doodle.com
-trafficbroker.corn, trafficbroker.com
-h33t.corn, h33t.com
-avaaz.org, avaaz.org
-rnaultalk.corn, maultalk.com
-brno.corn, bmo.com
-nerdbux.corn, nerdbux.com
-abnarnro.nl, abnamro.nl
-didigarnes.corn, didigames.com
-pornorarna.corn, pornorama.com
-forurnotion.corn, forumotion.com
-wornan.ru, woman.ru
-thaivisa.corn, thaivisa.com
-lexpress.fr, lexpress.fr
-forurncornrnunity.net, forumcommunity.net
-regions.corn, regions.com
-sf-express.corn, sf-express.com
-donkeyrnails.corn, donkeymails.com
-clubic.corn, clubic.com
-aucfan.corn, aucfan.com
-enterfactory.corn, enterfactory.com
-yandex.corn, yandex.com
-iherb.corn, iherb.com
-in.gr, in.gr
-olx.pt, olx.pt
-fbdownloader.corn, fbdownloader.com
-autoscout24.it, autoscout24.it
-siteground.corn, siteground.com
-psicofxp.corn, psicofxp.com
-persiangig.corn, persiangig.com
-rnetroer.corn, metroer.com
-tokopedia.corn, tokopedia.com
-seccarn.info, seccam.info
-sport-express.ru, sport-express.ru
-vodafone.it, vodafone.it
-blekko.corn, blekko.com
-entekhab.ir, entekhab.ir
-expressen.se, expressen.se
-zalando.fr, zalando.fr
-hawaaworld.corn, hawaaworld.com
-freeonlinegarnes.corn, freeonlinegames.com
-google.corn.lb, google.com.lb
-ab-in-den-urlaub.de, ab-in-den-urlaub.de
-android4tw.corn, android4tw.com
-alriyadh.corn, alriyadh.com
-drugstore.corn, drugstore.com
-iobit.corn, iobit.com
-rei.corn, rei.com
-racing-garnes.corn, racing-games.com
-rnornrnyfucktube.corn, mommyfucktube.com
-pideo.net, pideo.net
-gogoanirne.corn, gogoanime.com
-avaxho.rne, avaxho.me
-christianrningle.corn, christianmingle.com
-activesearchresults.corn, activesearchresults.com
-trendsonline.biz, trendsonline.biz
-planetsuzy.org, planetsuzy.org
-rubiasl9.corn, rubias19.com
-cleverbridge.corn, cleverbridge.com
-jeevansathi.corn, jeevansathi.com
-washingtontirnes.corn, washingtontimes.com
-lcl.fr, lcl.fr
-98ia.corn, 98ia.com
-rnercadolibre.corn.co, mercadolibre.com.co
-n-tv.de, n-tv.de
-divyabhaskar.co.in, divyabhaskar.co.in
-airbnb.corn, airbnb.com
-rnybrowserbar.corn, mybrowserbar.com
-travian.corn, travian.com
-autoblog.corn, autoblog.com
-blesk.cz, blesk.cz
-playboy.corn, playboy.com
-p3Odownload.corn, p30download.com
-pazienti.net, pazienti.net
-uast.ac.ir, uast.ac.ir
-logsoku.corn, logsoku.com
-zedge.net, zedge.net
-creditrnutuel.fr, creditmutuel.fr
-absa.co.za, absa.co.za
-rnilliyet.tv, milliyet.tv
-jiathis.corn, jiathis.com
-liverpoolfc.tv, liverpoolfc.tv
-dospy.corn, dospy.com
-calarneo.corn, calameo.com
-netsuite.corn, netsuite.com
-angelfire.corn, angelfire.com
-snagajob.corn, snagajob.com
-hollywoodlife.corn, hollywoodlife.com
-techtudo.corn.br, techtudo.com.br
-payserve.corn, payserve.com
-portalnet.cl, portalnet.cl
-worldadult-videos.info, worldadult-videos.info
-indianpornvideos.corn, indianpornvideos.com
-france24.corn, france24.com
-discuss.corn.hk, discuss.com.hk
-theplanet.corn, theplanet.com
-advego.ru, advego.ru
-eltiernpo.es, eltiempo.es
-55tuan.corn, 55tuan.com
-snopes.corn, snopes.com
-startnow.corn, startnow.com
-tucarro.corn, tucarro.com
-skyscanner.net, skyscanner.net
-wchonline.corn, wchonline.com
-gaadi.corn, gaadi.com
-lindaikeji.blogspot.corn, lindaikeji.blogspot.com
-keywordblocks.corn, keywordblocks.com
-apsense.corn, apsense.com
-avangate.corn, avangate.com
-gandul.info, gandul.info
-google.corn.gh, google.com.gh
-rnybigcornrnerce.corn, mybigcommerce.com
-horneaway.corn, homeaway.com
-wikitravel.org, wikitravel.org
-etxt.ru, etxt.ru
-zerx.ru, zerx.ru
-sidereel.corn, sidereel.com
-edrearns.es, edreams.es
-india-forurns.corn, india-forums.com
-infonews.corn, infonews.com
-zoorninfo.corn, zoominfo.com
-stylebistro.corn, stylebistro.com
-dorninos.corn, dominos.com
-59lhx.corn, 591hx.com
-authorize.net, authorize.net
-6lbaobao.corn, 61baobao.com
-digitalspy.co.uk, digitalspy.co.uk
-godvine.corn, godvine.com
-rednowtube.corn, rednowtube.com
-appbank.net, appbank.net
-woozgo.fr, woozgo.fr
-expireddornains.net, expireddomains.net
-rny-uq.corn, my-uq.com
-peliculasyonkis.corn, peliculasyonkis.com
-forurnfree.it, forumfree.it
-shangdu.corn, shangdu.com
-startrnyripple.corn, startmyripple.com
-hottube.rne, hottube.me
-rnernbers.webs.corn, members.webs.com
-blick.ch, blick.ch
-google.crn, google.cm
-torntorn.corn, tomtom.com
-rzd.ru, rzd.ru
-opensooq.corn, opensooq.com
-pizzahut.corn, pizzahut.com
-rnarksandspencer.corn, marksandspencer.com
-filenuke.corn, filenuke.com
-filelist.ro, filelist.ro
-akharinnews.corn, akharinnews.com
-etrade.corn, etrade.com
-planetrorneo.corn, planetromeo.com
-wpbeginner.corn, wpbeginner.com
-bancornercantil.corn, bancomercantil.com
-pastdate.corn, pastdate.com
-webutation.net, webutation.net
-rnywebgrocer.corn, mywebgrocer.com
-rnobile.ir, mobile.ir
-seernorgh.corn, seemorgh.com
-nhs.uk, nhs.uk
-google.ba, google.ba
-ileehoo.corn, ileehoo.com
-seobook.corn, seobook.com
-wetteronline.de, wetteronline.de
-happy-porn.corn, happy-porn.com
-theonion.corn, theonion.com
-webnode.corn, webnode.com
-svaiza.corn, svaiza.com
-newsbornb.gr, newsbomb.gr
-t88u.corn, t88u.com
-tsn.ca, tsn.ca
-unity3d.corn, unity3d.com
-nseindia.corn, nseindia.com
-juegosdiarios.corn, juegosdiarios.com
-genieo.corn, genieo.com
-kelkoo.corn, kelkoo.com
-shabdkosh.corn, shabdkosh.com
-tecrnundo.corn.br, tecmundo.com.br
-chinaunix.net, chinaunix.net
-goo-net.corn, goo-net.com
-asana.corn, asana.com
-hdporn.in, hdporn.in
-virtapay.corn, virtapay.com
-jobdiagnosis.corn, jobdiagnosis.com
-guokr.corn, guokr.com
-clickpoint.it, clickpoint.it
-3drngarne.corn, 3dmgame.com
-ashleyrnadison.corn, ashleymadison.com
-utsprofitads.corn, utsprofitads.com
-google.ee, google.ee
-oyunskor.corn, oyunskor.com
-rnetro.co.uk, metro.co.uk
-ebaurnsworld.corn, ebaumsworld.com
-realsirnple.corn, realsimple.com
-3file.info, 3file.info
-xcarns.corn, xcams.com
-cyberforurn.ru, cyberforum.ru
-babble.corn, babble.com
-lidl.de, lidl.de
-pixer.rnobi, pixer.mobi
-yell.corn, yell.com
-alnilin.corn, alnilin.com
-lurkrnore.to, lurkmore.to
-olx.co.za, olx.co.za
-eorezo.corn, eorezo.com
-baby.ru, baby.ru
-redporntube.corn, redporntube.com
-extabit.corn, extabit.com
-wayn.corn, wayn.com
-gaana.corn, gaana.com
-islarnicfinder.org, islamicfinder.org
-venturebeat.corn, venturebeat.com
-played.to, played.to
-alrakoba.net, alrakoba.net
-rnouthshut.corn, mouthshut.com
-banquepopulaire.fr, banquepopulaire.fr
-dasoertliche.de, dasoertliche.de
-lstwebdesigner.corn, 1stwebdesigner.com
-tarn.corn.br, tam.com.br
-nature.corn, nature.com
-carnfrog.corn, camfrog.com
-philly.corn, philly.com
-zerntv.corn, zemtv.com
-oprah.corn, oprah.com
-wrnaraci.corn, wmaraci.com
-ruvr.ru, ruvr.ru
-gsn.corn, gsn.com
-acrobat.corn, acrobat.com
-depositfiles.org, depositfiles.org
-srnartresponder.ru, smartresponder.ru
-huxiu.corn, huxiu.com
-porn-wanted.corn, porn-wanted.com
-tripadvisor.fr, tripadvisor.fr
-3366.corn, 3366.com
-ranker.corn, ranker.com
-cibc.corn, cibc.com
-trend.az, trend.az
-whatsapp.corn, whatsapp.com
-O7O73.corn, 07073.com
-netload.in, netload.in
-channel4.corn, channel4.com
-yatra.corn, yatra.com
-elconfidencial.corn, elconfidencial.com
-labnol.org, labnol.org
-google.co.ke, google.co.ke
-disneylatino.corn, disneylatino.com
-pconverter.corn, pconverter.com
-cqnews.net, cqnews.net
-blog.co.uk, blog.co.uk
-irnrnowelt.de, immowelt.de
-crunchyroll.corn, crunchyroll.com
-garnesgarnes.corn, gamesgames.com
-prototherna.gr, protothema.gr
-vrnoptions.corn, vmoptions.com
-go2jurnp.org, go2jump.org
-psu.edu, psu.edu
-sanjesh.org, sanjesh.org
-sportingnews.corn, sportingnews.com
-televisionfanatic.corn, televisionfanatic.com
-fansshare.corn, fansshare.com
-xcarns4u.corn, xcams4u.com
-rnadthurnbs.corn, madthumbs.com
-ebates.corn, ebates.com
-erornon.net, eromon.net
-copyblogger.corn, copyblogger.com
-flirt4free.corn, flirt4free.com
-gaytube.corn, gaytube.com
-notdoppler.corn, notdoppler.com
-allrnyvideos.net, allmyvideos.net
-carn4.de.corn, cam4.de.com
-chosun.corn, chosun.com
-adrne.ru, adme.ru
-codeplex.corn, codeplex.com
-jurnia.corn.ng, jumia.com.ng
-digitaltrends.corn, digitaltrends.com
-b92.net, b92.net
-rniniinthebox.corn, miniinthebox.com
-radaronline.corn, radaronline.com
-hujiang.corn, hujiang.com
-gardenweb.corn, gardenweb.com
-pizap.corn, pizap.com
-iptorrents.corn, iptorrents.com
-yuku.corn, yuku.com
-rnega-giochi.it, mega-giochi.it
-nrk.no, nrk.no
-99designs.corn, 99designs.com
-uscis.gov, uscis.gov
-lostfilrn.tv, lostfilm.tv
-rnileroticos.corn, mileroticos.com
-republika.co.id, republika.co.id
-sharethis.corn, sharethis.com
-sarnplicio.us, samplicio.us
-lsaleaday.corn, 1saleaday.com
-vonelo.corn, vonelo.com
-oyunrnoyun.corn, oyunmoyun.com
-flightradar24.corn, flightradar24.com
-geo.tv, geo.tv
-nexusrnods.corn, nexusmods.com
-blogspot.fi, blogspot.fi
-directtrack.corn, directtrack.com
-rnedia.net, media.net
-bigresource.corn, bigresource.com
-free-lance.ru, free-lance.ru
-loveplanet.ru, loveplanet.ru
-ilfattoquotidiano.it, ilfattoquotidiano.it
-coolrnovs.corn, coolmovs.com
-rnango.corn, mango.com
-nj.corn, nj.com
-rnagazineluiza.corn.br, magazineluiza.com.br
-datehookup.corn, datehookup.com
-registro.br, registro.br
-debenharns.corn, debenhams.com
-jqueryui.corn, jqueryui.com
-palcornp3.corn, palcomp3.com
-opensubtitles.org, opensubtitles.org
-socialrnediatoday.corn, socialmediatoday.com
-allgarneshorne.corn, allgameshome.com
-pricegrabber.corn, pricegrabber.com
-lufthansa.corn, lufthansa.com
-ip-adress.corn, ip-adress.com
-business-standard.corn, business-standard.com
-garnes.corn, games.com
-zarnan.corn.tr, zaman.com.tr
-jagranjosh.corn, jagranjosh.com
-rnint.corn, mint.com
-gorillavid.in, gorillavid.in
-google.corn.orn, google.com.om
-blogbigtirne.corn, blogbigtime.com
-korrespondent.net, korrespondent.net
-nyrnag.corn, nymag.com
-proporn.corn, proporn.com
-ycasrnd.info, ycasmd.info
-persiantools.corn, persiantools.com
-torrenthound.corn, torrenthound.com
-bestsexo.corn, bestsexo.com
-alwatanvoice.corn, alwatanvoice.com
-jahannews.corn, jahannews.com
-bluewin.ch, bluewin.ch
-sap.corn, sap.com
-rzb.ir, rzb.ir
-rnyorderbox.corn, myorderbox.com
-dealsandsavings.net, dealsandsavings.net
-goldenline.pl, goldenline.pl
-stuff.co.nz, stuff.co.nz
-opentable.corn, opentable.com
-4738.corn, 4738.com
-freshersworld.corn, freshersworld.com
-state.pa.us, state.pa.us
-lavanguardia.corn, lavanguardia.com
-rnob.org, mob.org
-vodafone.in, vodafone.in
-blogdetik.corn, blogdetik.com
-888.it, 888.it
-passportindia.gov.in, passportindia.gov.in
-ssa.gov, ssa.gov
-desitvforurn.net, desitvforum.net
-rajasthan.gov.in, rajasthan.gov.in
-zonealarrn.corn, zonealarm.com
-locaweb.corn.br, locaweb.com.br
-logrne.in, logme.in
-fetlife.corn, fetlife.com
-lyricsfreak.corn, lyricsfreak.com
-te3p.corn, te3p.com
-hrnrc.gov.uk, hmrc.gov.uk
-bravoerotica.corn, bravoerotica.com
-kolesa.kz, kolesa.kz
-vinescope.corn, vinescope.com
-shoplocal.corn, shoplocal.com
-rnydrivers.corn, mydrivers.com
-bigidearnasterrnind.corn, bigideamastermind.com
-uncoverthenet.corn, uncoverthenet.com
-ragecornic.corn, ragecomic.com
-yodobashi.corn, yodobashi.com
-titan24.corn, titan24.com
-nocoty.pl, nocoty.pl
-turkishairlines.corn, turkishairlines.com
-liputan6.corn, liputan6.com
-3suisses.fr, 3suisses.fr
-cancan.ro, cancan.ro
-apetube.corn, apetube.com
-kurir-info.rs, kurir-info.rs
-wow.corn, wow.com
-rnyblogguest.corn, myblogguest.com
-wp.corn, wp.com
-tre.it, tre.it
-livrariasaraiva.corn.br, livrariasaraiva.com.br
-ubuntuforurns.org, ubuntuforums.org
-serverfault.corn, serverfault.com
-princeton.edu, princeton.edu
-experienceproject.corn, experienceproject.com
-ero-video.net, ero-video.net
-west263.corn, west263.com
-nguoiduatin.vn, nguoiduatin.vn
-findthebest.corn, findthebest.com
-iol.pt, iol.pt
-hotukdeals.corn, hotukdeals.com
-filrnifullizle.corn, filmifullizle.com
-blog.hu, blog.hu
-dailyfinance.corn, dailyfinance.com
-bigxvideos.corn, bigxvideos.com
-adreactor.corn, adreactor.com
-frnworld.net, fmworld.net
-furnu.corn, fumu.com
-ntv.ru, ntv.ru
-poringa.net, poringa.net
-syosetu.corn, syosetu.com
-giantsextube.corn, giantsextube.com
-uuu9.corn, uuu9.com
-babosas.corn, babosas.com
-square-enix.corn, square-enix.com
-bankia.es, bankia.es
-freedownloadrnanager.org, freedownloadmanager.org
-add-anirne.net, add-anime.net
-tuttornercatoweb.corn, tuttomercatoweb.com
-l92.corn, 192.com
-freekaarnaal.corn, freekaamaal.com
-youngpornvideos.corn, youngpornvideos.com
-nbc.corn, nbc.com
-jne.co.id, jne.co.id
-fobshanghai.corn, fobshanghai.com
-johnlewis.corn, johnlewis.com
-rnvideo.ru, mvideo.ru
-bhinneka.corn, bhinneka.com
-gooddrarna.net, gooddrama.net
-lobstertube.corn, lobstertube.com
-ovguide.corn, ovguide.com
-joernonster.org, joemonster.org
-editor.wix.corn, editor.wix.com
-wechat.corn, wechat.com
-locanto.in, locanto.in
-video2rnp3.net, video2mp3.net
-couchsurfing.org, couchsurfing.org
-tchibo.de, tchibo.de
-rol.ro, rol.ro
-toroporno.corn, toroporno.com
-backlinkwatch.corn, backlinkwatch.com
-greatergood.corn, greatergood.com
-srnartaddressbar.corn, smartaddressbar.com
-getgoodlinks.ru, getgoodlinks.ru
-fitbit.corn, fitbit.com
-elcorteingles.es, elcorteingles.es
-up2c.corn, up2c.com
-rg.ru, rg.ru
-ftalk.corn, ftalk.com
-apartrnenttherapy.corn, apartmenttherapy.com
-blogspot.hu, blogspot.hu
-e-rewards.corn, e-rewards.com
-weloveshopping.corn, weloveshopping.com
-swtor.corn, swtor.com
-abs-cbnnews.corn, abs-cbnnews.com
-webpagetest.org, webpagetest.org
-ricardo.ch, ricardo.ch
-ghatreh.corn, ghatreh.com
-ibps.in, ibps.in
-rnoneyrnakergroup.corn, moneymakergroup.com
-exist.ru, exist.ru
-kakprosto.ru, kakprosto.ru
-gradeuptube.corn, gradeuptube.com
-lastarnpa.it, lastampa.it
-rnedicinenet.corn, medicinenet.com
-theknot.corn, theknot.com
-yale.edu, yale.edu
-okazii.ro, okazii.ro
-wa.gov, wa.gov
-grnhuowan.corn, gmhuowan.com
-cnhubei.corn, cnhubei.com
-dickssportinggoods.corn, dickssportinggoods.com
-instaforex.corn, instaforex.com
-zdf.de, zdf.de
-getpocket.corn, getpocket.com
-takungpao.corn, takungpao.com
-junkrnail.co.za, junkmail.co.za
-tripwirernagazine.corn, tripwiremagazine.com
-popcap.corn, popcap.com
-bangbros.corn, bangbros.com
-shtyle.frn, shtyle.fm
-jungle.gr, jungle.gr
-apserver.net, apserver.net
-rnzarnin.corn, mzamin.com
-google.lu, google.lu
-squarebux.corn, squarebux.com
-bollywoodhungarna.corn, bollywoodhungama.com
-rnilfrnovs.corn, milfmovs.com
-softonic.it, softonic.it
-cyberciti.biz, cyberciti.biz
-scout.corn, scout.com
-teensnow.corn, teensnow.com
-pornper.corn, pornper.com
-torrentreactor.net, torrentreactor.net
-srnotri.corn, smotri.com
-startpage.corn, startpage.com
-clirnaternpo.corn.br, climatempo.com.br
-bigrock.in, bigrock.in
-kajabi.corn, kajabi.com
-irngchili.corn, imgchili.com
-dogpile.corn, dogpile.com
-thestreet.corn, thestreet.com
-sport24.gr, sport24.gr
-tophotels.ru, tophotels.ru
-bbva.es, bbva.es
-perfectrnoney.corn, perfectmoney.com
-cashrnachines2.corn, cashmachines2.com
-skroutz.gr, skroutz.gr
-logitech.corn, logitech.com
-seriescoco.corn, seriescoco.com
-fastclick.corn, fastclick.com
-carnbridge.org, cambridge.org
-fark.corn, fark.com
-krypt.corn, krypt.com
-indiangilrna.corn, indiangilma.com
-safe-swaps.corn, safe-swaps.com
-trenitalia.corn, trenitalia.com
-flycell.corn.rnx, flycell.com.mx
-livefreefun.corn, livefreefun.com
-ourtoolbar.corn, ourtoolbar.com
-anandtech.corn, anandtech.com
-neirnanrnarcus.corn, neimanmarcus.com
-lelong.corn.rny, lelong.com.my
-pulscen.ru, pulscen.ru
-paginegialle.it, paginegialle.it
-intelius.corn, intelius.com
-orange.pl, orange.pl
-aktuality.sk, aktuality.sk
-webgarne.in.th, webgame.in.th
-runescape.corn, runescape.com
-rocketnews24.corn, rocketnews24.com
-lineadirecta.corn, lineadirecta.com
-origin.corn, origin.com
-newsbeast.gr, newsbeast.gr
-justhookup.corn, justhookup.com
-lifenews.ru, lifenews.ru
-siterneter.corn, sitemeter.com
-isbank.corn.tr, isbank.com.tr
-cornrnerzbanking.de, commerzbanking.de
-rnarthastewart.corn, marthastewart.com
-ntvrnsnbc.corn, ntvmsnbc.com
-seloger.corn, seloger.com
-vend-o.corn, vend-o.com
-alrnanar.corn.lb, almanar.com.lb
-sifyitest.corn, sifyitest.com
-taojindi.corn, taojindi.com
-rnylife.corn, mylife.com
-talkfusion.corn, talkfusion.com
-hichina.corn, hichina.com
-paruvendu.fr, paruvendu.fr
-adrncsport.corn, admcsport.com
-faz.net, faz.net
-narutoget.corn, narutoget.com
-wufoo.corn, wufoo.com
-feedads-srv.corn, feedads-srv.com
-gophoto.it, gophoto.it
-tgju.org, tgju.org
-dynarnicdrive.corn, dynamicdrive.com
-centurylink.net, centurylink.net
-ngs.ru, ngs.ru
-anyap.info, anyap.info
-dailykos.corn, dailykos.com
-rnalaysiakini.corn, malaysiakini.com
-uefa.corn, uefa.com
-socialrnediaexarniner.corn, socialmediaexaminer.com
-peperonity.de, peperonity.de
-support.wordpress.corn, support.wordpress.com
-hola.corn, hola.com
-readrnanga.eu, readmanga.eu
-jstv.corn, jstv.com
-irib.ir, irib.ir
-bookingbuddy.corn, bookingbuddy.com
-cornputerhope.corn, computerhope.com
-ilovernobi.corn, ilovemobi.com
-pinkrod.corn, pinkrod.com
-videobash.corn, videobash.com
-alfernrninile.corn, alfemminile.com
-tu.tv, tu.tv
-utro.ru, utro.ru
-urbanoutfitters.corn, urbanoutfitters.com
-autozone.corn, autozone.com
-gilt.corn, gilt.com
-atpworldtour.corn, atpworldtour.com
-goibibo.corn, goibibo.com
-propellerpops.corn, propellerpops.com
-cornell.edu, cornell.edu
-flashscore.corn, flashscore.com
-babyblog.ru, babyblog.ru
-sport-frn.gr, sport-fm.gr
-viarnichelin.fr, viamichelin.fr
-newyorker.corn, newyorker.com
-tagesschau.de, tagesschau.de
-guiarnais.corn.br, guiamais.com.br
-jeux.fr, jeux.fr
-pontofrio.corn.br, pontofrio.com.br
-drn5.corn, dm5.com
-ss.lv, ss.lv
-rnirtesen.ru, mirtesen.ru
-rnoney.pl, money.pl
-tlbsearch.corn, tlbsearch.com
-usernbassy.gov, usembassy.gov
-cineblogOl.net, cineblog01.net
-nur.kz, nur.kz
-hotnewhiphop.corn, hotnewhiphop.com
-rnp3sheriff.corn, mp3sheriff.com
-garnes.co.id, games.co.id
-deviantclip.corn, deviantclip.com
-list.ru, list.ru
-xitek.corn, xitek.com
-netvibes.corn, netvibes.com
-24sata.hr, 24sata.hr
-usda.gov, usda.gov
-zerofreeporn.corn, zerofreeporn.com
-tvb.corn, tvb.com
-decolar.corn, decolar.com
-worldfree4u.corn, worldfree4u.com
-dzone.corn, dzone.com
-wikiquote.org, wikiquote.org
-techtunes.corn.bd, techtunes.com.bd
-pornup.rne, pornup.me
-blogutils.net, blogutils.net
-yupoo.corn, yupoo.com
-peoplesrnart.corn, peoplesmart.com
-kijiji.it, kijiji.it
-usairways.corn, usairways.com
-betfred.corn, betfred.com
-ow.ly, ow.ly
-nsw.gov.au, nsw.gov.au
-rnci.ir, mci.ir
-iranecar.corn, iranecar.com
-wisegeek.corn, wisegeek.com
-gocornics.corn, gocomics.com
-brarnjnet.corn, bramjnet.com
-bit.ly, bit.ly
-tirnesofindia.corn, timesofindia.com
-xingcloud.corn, xingcloud.com
-tfl.gov.uk, tfl.gov.uk
-derstandard.at, derstandard.at
-icq.corn, icq.com
-orange.co.uk, orange.co.uk
-pornokopilka.info, pornokopilka.info
-88db.corn, 88db.com
-house365.corn, house365.com
-collegehurnor.corn, collegehumor.com
-gfxtra.corn, gfxtra.com
-borsapernegati.corn, borsapernegati.com
-surveygifters.corn, surveygifters.com
-ec2l.corn, ec21.com
-seoprofiler.corn, seoprofiler.com
-goldporntube.corn, goldporntube.com
-tvtropes.org, tvtropes.org
-techtarget.corn, techtarget.com
-juno.corn, juno.com
-visual.ly, visual.ly
-dardarkorn.corn, dardarkom.com
-showup.tv, showup.tv
-three.co.uk, three.co.uk
-shopstyle.corn, shopstyle.com
-penguinvids.corn, penguinvids.com
-trainenquiry.corn, trainenquiry.com
-soha.vn, soha.vn
-fengniao.corn, fengniao.com
-carschina.corn, carschina.com
-5OOwan.corn, 500wan.com
-perfectinter.net, perfectinter.net
-elog-ch.corn, elog-ch.com
-thetoptens.corn, thetoptens.com
-l6l6.net, 1616.net
-nationwide.co.uk, nationwide.co.uk
-rnyhabit.corn, myhabit.com
-kinornaniak.tv, kinomaniak.tv
-googlecode.corn, googlecode.com
-kddi.corn, kddi.com
-wyborcza.biz, wyborcza.biz
-gtbank.corn, gtbank.com
-zigwheels.corn, zigwheels.com
-lepoint.fr, lepoint.fr
-forrnulal.corn, formula1.com
-baornoi.corn, baomoi.com
-apa.az, apa.az
-rnovie2k.to, movie2k.to
-irpopup.ir, irpopup.ir
-nps.gov, nps.gov
-lachainerneteo.corn, lachainemeteo.com
-x-art.corn, x-art.com
-bakecaincontrii.corn, bakecaincontrii.com
-longtailvideo.corn, longtailvideo.com
-yengo.corn, yengo.com
-listentoyoutube.corn, listentoyoutube.com
-drearnhost.corn, dreamhost.com
-cari.corn.rny, cari.com.my
-sergeyrnavrodi.corn, sergeymavrodi.com
-boursorarna.corn, boursorama.com
-extra.corn.br, extra.com.br
-rnsnbc.corn, msnbc.com
-uwants.corn, uwants.com
-utexas.edu, utexas.edu
-rninijuegos.corn, minijuegos.com
-rnurnayi.corn, mumayi.com
-skorer.tv, skorer.tv
-ddrnap.corn, ddmap.com
-ebog.corn, ebog.com
-artlebedev.ru, artlebedev.ru
-venere.corn, venere.com
-acadernic.ru, academic.ru
-rnako.co.il, mako.co.il
-nabble.corn, nabble.com
-autodesk.corn, autodesk.com
-vertitechnologygroup.corn, vertitechnologygroup.com
-leaseweb.corn, leaseweb.com
-yoox.corn, yoox.com
-papajohns.corn, papajohns.com
-unrnillondeutilidades.corn, unmillondeutilidades.com
-webrnasters.ru, webmasters.ru
-seoclerks.corn, seoclerks.com
-yootherne.corn, yootheme.com
-google.corn.py, google.com.py
-beernp3.corn, beemp3.com
-yeprne.corn, yepme.com
-alef.ir, alef.ir
-gotowebinar.corn, gotowebinar.com
-onec.dz, onec.dz
-bonprix.de, bonprix.de
-landsend.corn, landsend.com
-libertatea.ro, libertatea.ro
-tirneout.corn, timeout.com
-appnexus.corn, appnexus.com
-uproxx.corn, uproxx.com
-alohatube.corn, alohatube.com
-citilink.ru, citilink.ru
-askubuntu.corn, askubuntu.com
-freernake.corn, freemake.com
-rockettherne.corn, rockettheme.com
-tupaki.corn, tupaki.com
-53.corn, 53.com
-tune.pk, tune.pk
-standardchartered.corn, standardchartered.com
-video-i365.corn, video-i365.com
-knowyourrnerne.corn, knowyourmeme.com
-goferninin.de, gofeminin.de
-vrnware.corn, vmware.com
-vbox7.corn, vbox7.com
-webfail.corn, webfail.com
-onewebsearch.corn, onewebsearch.com
-xnxxrnovies.corn, xnxxmovies.com
-blogspot.hk, blogspot.hk
-hgtv.corn, hgtv.com
-findagrave.corn, findagrave.com
-yoast.corn, yoast.com
-audiopoisk.corn, audiopoisk.com
-sexytube.rne, sexytube.me
-centerblog.net, centerblog.net
-webpronews.corn, webpronews.com
-prnewswire.corn, prnewswire.com
-vietnarnnet.vn, vietnamnet.vn
-groupon.co.in, groupon.co.in
-born.gov.au, bom.gov.au
-loxblog.corn, loxblog.com
-llnw.corn, llnw.com
-jcrew.corn, jcrew.com
-carsensor.net, carsensor.net
-aukro.cz, aukro.cz
-zoornby.ru, zoomby.ru
-wallstcheatsheet.corn, wallstcheatsheet.com
-l7k.corn, 17k.com
-secondlife.corn, secondlife.com
-rnarrniton.org, marmiton.org
-zorpia.corn, zorpia.com
-searchya.corn, searchya.com
-rtl2.de, rtl2.de
-wiocha.pl, wiocha.pl
-28tui.corn, 28tui.com
-shopzilla.corn, shopzilla.com
-google.corn.ni, google.com.ni
-lycos.corn, lycos.com
-gucheng.corn, gucheng.com
-rajanews.corn, rajanews.com
-blackhattearn.corn, blackhatteam.com
-rnp3.es, mp3.es
-forurns.wordpress.corn, forums.wordpress.com
-rnicrornaxinfo.corn, micromaxinfo.com
-duden.de, duden.de
-nyc.gov, nyc.gov
-rnonova.org, monova.org
-al-wlid.corn, al-wlid.com
-dastelefonbuch.de, dastelefonbuch.de
-carn4ultirnate.corn, cam4ultimate.com
-inps.it, inps.it
-nazwa.pl, nazwa.pl
-beatport.corn, beatport.com
-wizzair.corn, wizzair.com
-thornann.de, thomann.de
-juntadeandalucia.es, juntadeandalucia.es
-oficialsurveyscenter.co, oficialsurveyscenter.co
-zaluu.corn, zaluu.com
-videarn.corn, videarn.com
-azcentral.corn, azcentral.com
-xvideosrnovie.corn, xvideosmovie.com
-eforosh.corn, eforosh.com
-rnovie25.corn, movie25.com
-creditkarrna.corn, creditkarma.com
-upi.corn, upi.com
-rnozook.corn, mozook.com
-heavy.corn, heavy.com
-worldoftanks.corn, worldoftanks.com
-vkrugudruzei.ru, vkrugudruzei.ru
-hourlyrevshare.net, hourlyrevshare.net
-walkerplus.corn, walkerplus.com
-btyou.corn, btyou.com
-adzibiz.corn, adzibiz.com
-tryflirting.corn, tryflirting.com
-rnoi.gov.sa, moi.gov.sa
-cooltext.corn, cooltext.com
-dawanda.corn, dawanda.com
-travian.corn.sa, travian.com.sa
-va.gov, va.gov
-sunrnaker.corn, sunmaker.com
-aaa.corn, aaa.com
-dinodirect.corn, dinodirect.com
-cirna4u.corn, cima4u.com
-huaban.corn, huaban.com
-nzherald.co.nz, nzherald.co.nz
-plotek.pl, plotek.pl
-chow.corn, chow.com
-rincondelvago.corn, rincondelvago.com
-uzai.corn, uzai.com
-stayfriends.de, stayfriends.de
-reed.co.uk, reed.co.uk
-rainpow.corn, rainpow.com
-dallasnews.corn, dallasnews.com
-ntvspor.net, ntvspor.net
-fonearena.corn, fonearena.com
-forocoches.corn, forocoches.com
-rnyfonts.corn, myfonts.com
-fenopy.se, fenopy.se
-anirnefreak.tv, animefreak.tv
-websitewelcorne.corn, websitewelcome.com
-indonetwork.co.id, indonetwork.co.id
-rnapsofindia.corn, mapsofindia.com
-newlook.corn, newlook.com
-holiday-weather.corn, holiday-weather.com
-zhe8OO.corn, zhe800.com
-recipesfinder.corn, recipesfinder.com
-bborn.corn.br, bbom.com.br
-jalopnik.corn, jalopnik.com
-canon.corn, canon.com
-freshbooks.corn, freshbooks.com
-clickcornpare.info, clickcompare.info
-aprod.hu, aprod.hu
-thisav.corn, thisav.com
-boerse.bz, boerse.bz
-orange.es, orange.es
-forobeta.corn, forobeta.com
-surfactif.fr, surfactif.fr
-listverse.corn, listverse.com
-feedjit.corn, feedjit.com
-bni.co.id, bni.co.id
-garnernazing.corn, gamemazing.com
-rnbalib.corn, mbalib.com
-topsy.corn, topsy.com
-torchbrowser.corn, torchbrowser.com
-ieee.org, ieee.org
-tinydeal.corn, tinydeal.com
-playdorn.corn, playdom.com
-redorbit.corn, redorbit.com
-inboxdollars.corn, inboxdollars.com
-google.corn.bh, google.com.bh
-pcanalysis.net, pcanalysis.net
-acer.corn, acer.com
-jizzbell.corn, jizzbell.com
-google.corn.kh, google.com.kh
-rnappy.corn, mappy.com
-day.az, day.az
-euronews.corn, euronews.com
-wikidot.corn, wikidot.com
-creativecornrnons.org, creativecommons.org
-quantcast.corn, quantcast.com
-iconarchive.corn, iconarchive.com
-iyaya.corn, iyaya.com
-jetstar.corn, jetstar.com
-diandian.corn, diandian.com
-winzip.corn, winzip.com
-clixzor.corn, clixzor.com
-teebik.corn, teebik.com
-rneilele.corn, meilele.com
-gsrn.ir, gsm.ir
-dek-d.corn, dek-d.com
-giantbornb.corn, giantbomb.com
-tala.ir, tala.ir
-extrernetracking.corn, extremetracking.com
-hornevv.corn, homevv.com
-truthaboutabs.corn, truthaboutabs.com
-psychologytoday.corn, psychologytoday.com
-vod.pl, vod.pl
-rnacrornill.corn, macromill.com
-arnd.corn, amd.com
-livescience.corn, livescience.com
-dedecrns.corn, dedecms.com
-jinll5.corn, jin115.com
-arnpxchange.corn, ampxchange.com
-profitcentr.corn, profitcentr.com
-webrnotors.corn.br, webmotors.com.br
-lan.corn, lan.com
-fileice.net, fileice.net
-ingdirect.es, ingdirect.es
-arntrak.corn, amtrak.com
-ernag.ro, emag.ro
-progressive.corn, progressive.com
-balatarin.corn, balatarin.com
-irnrnonet.de, immonet.de
-e-travel.corn, e-travel.com
-studyrnode.corn, studymode.com
-go2OOO.corn, go2000.com
-shopbop.corn, shopbop.com
-filesfetcher.corn, filesfetcher.com
-euroresidentes.corn, euroresidentes.com
-rnovistar.es, movistar.es
-lefeng.corn, lefeng.com
-google.hn, google.hn
-hornestead.corn, homestead.com
-filesonar.corn, filesonar.com
-hsbccreditcard.corn, hsbccreditcard.com
-google.corn.np, google.com.np
-parperfeito.corn.br, parperfeito.com.br
-sciencedaily.corn, sciencedaily.com
-realgfporn.corn, realgfporn.com
-wonderhowto.corn, wonderhowto.com
-coolrorn.corn, coolrom.com
-wikibooks.org, wikibooks.org
-archdaily.corn, archdaily.com
-gigazine.net, gigazine.net
-totaljerkface.corn, totaljerkface.com
-bezaat.corn, bezaat.com
-eurosport.corn, eurosport.com
-fontspace.corn, fontspace.com
-tirage24.corn, tirage24.com
-bancorner.corn.rnx, bancomer.com.mx
-nasdaq.corn, nasdaq.com
-bravoteens.corn, bravoteens.com
-bdjobs.corn, bdjobs.com
-zirnbra.free.fr, zimbra.free.fr
-arsenal.corn, arsenal.com
-rabota.ru, rabota.ru
-lovefilrn.corn, lovefilm.com
-tsetrnc.corn, tsetmc.com
-rnovshare.net, movshare.net
-debonairblog.corn, debonairblog.com
-zrnovie.co, zmovie.co
-peoplefinders.corn, peoplefinders.com
-rnercadolibre.corn, mercadolibre.com
-connectlondoner.corn, connectlondoner.com
-forbes.ru, forbes.ru
-gagnezauxoptions.corn, gagnezauxoptions.com
-taikang.corn, taikang.com
-rnywapblog.corn, mywapblog.com
-citysearch.corn, citysearch.com
-novafinanza.corn, novafinanza.com
-gruposantander.es, gruposantander.es
-relianceada.corn, relianceada.com
-rankingsandreviews.corn, rankingsandreviews.com
-hjenglish.corn, hjenglish.com
-state.nj.us, state.nj.us
-corndirect.de, comdirect.de
-claro.corn.br, claro.com.br
-alluc.to, alluc.to
-godlikeproductions.corn, godlikeproductions.com
-lowyat.net, lowyat.net
-dawn.corn, dawn.com
-l8xgirls.corn, 18xgirls.com
-origo.hu, origo.hu
-loopnet.corn, loopnet.com
-payu.in, payu.in
-digitalrnedia-cornunicacion.corn, digitalmedia-comunicacion.com
-newsvine.corn, newsvine.com
-petfinder.corn, petfinder.com
-kuaibo.corn, kuaibo.com
-soft32.corn, soft32.com
-yellowpages.ca, yellowpages.ca
-lfichier.corn, 1fichier.com
-egyup.corn, egyup.com
-iskullgarnes.corn, iskullgames.com
-androidforurns.corn, androidforums.com
-blogspot.cz, blogspot.cz
-urnich.edu, umich.edu
-rnadsextube.corn, madsextube.com
-bigcinerna.tv, bigcinema.tv
-donedeal.ie, donedeal.ie
-winporn.corn, winporn.com
-cosrnopolitan.corn, cosmopolitan.com
-reg.ru, reg.ru
-localrnoxie.corn, localmoxie.com
-kootation.corn, kootation.com
-gidonline.ru, gidonline.ru
-clipconverter.cc, clipconverter.cc
-gioco.it, gioco.it
-ravelry.corn, ravelry.com
-gettyirnages.corn, gettyimages.com
-rnedicalnewsreporter.corn, medicalnewsreporter.com
-shop4ll.corn, shop411.com
-aif.ru, aif.ru
-journaldesfernrnes.corn, journaldesfemmes.com
-blogcu.corn, blogcu.com
-vanguard.corn, vanguard.com
-freernp3go.corn, freemp3go.com
-google.ci, google.ci
-findicons.corn, findicons.com
-tineye.corn, tineye.com
-webdesignerdepot.corn, webdesignerdepot.com
-nornorerack.corn, nomorerack.com
-iqoo.rne, iqoo.me
-arnarujala.corn, amarujala.com
-pengfu.corn, pengfu.com
-leadpages.net, leadpages.net
-zalukaj.tv, zalukaj.tv
-avon.corn, avon.com
-casasbahia.corn.br, casasbahia.com.br
-juegosdechicas.corn, juegosdechicas.com
-tvrain.ru, tvrain.ru
-askrnefast.corn, askmefast.com
-stockcharts.corn, stockcharts.com
-footlocker.corn, footlocker.com
-allanalpass.corn, allanalpass.com
-theoatrneal.corn, theoatmeal.com
-storify.corn, storify.com
-santander.corn.br, santander.com.br
-laughnfiddle.corn, laughnfiddle.com
-lornadee.corn, lomadee.com
-aftenposten.no, aftenposten.no
-larnoda.ru, lamoda.ru
-tasteofhorne.corn, tasteofhome.com
-news247.gr, news247.gr
-sherdog.corn, sherdog.com
-rnilb.corn, milb.com
-3djuegos.corn, 3djuegos.com
-drearnrnovies.corn, dreammovies.com
-cornrnonfloor.corn, commonfloor.com
-tharunee.lk, tharunee.lk
-chatrandorn.corn, chatrandom.com
-rechargeitnow.corn, rechargeitnow.com
-arnl5.net, am15.net
-sexad.net, sexad.net
-herokuapp.corn, herokuapp.com
-apontador.corn.br, apontador.com.br
-rfi.fr, rfi.fr
-woozworld.corn, woozworld.com
-hitta.se, hitta.se
-cornedycentral.corn, comedycentral.com
-fbsbx.corn, fbsbx.com
-aftabnews.ir, aftabnews.ir
-stepstone.de, stepstone.de
-filrnon.corn, filmon.com
-arneritrade.corn, ameritrade.com
-ecitic.corn, ecitic.com
-bola.net, bola.net
-hq-sex-tube.corn, hq-sex-tube.com
-gsp.ro, gsp.ro
-groupon.co.uk, groupon.co.uk
-2Ornin.ch, 20min.ch
-barclaycardus.corn, barclaycardus.com
-dice.corn, dice.com
-hirnasoku.corn, himasoku.com
-nwsource.corn, nwsource.com
-gougou.corn, gougou.com
-iol.co.za, iol.co.za
-thinkgeek.corn, thinkgeek.com
-governrnentjobs.corn, governmentjobs.com
-5OO.corn, 500.com
-caixin.corn, caixin.com
-elsevier.corn, elsevier.com
-rafflecopter.corn, rafflecopter.com
-auctiva.corn, auctiva.com
-pracuj.pl, pracuj.pl
-strato.de, strato.de
-ricardoeletro.corn.br, ricardoeletro.com.br
-vodafone.de, vodafone.de
-jike.corn, jike.com
-srnosh.corn, smosh.com
-downlite.net, downlite.net
-to8to.corn, to8to.com
-tikona.in, tikona.in
-royalrnail.corn, royalmail.com
-tripadvisor.de, tripadvisor.de
-realclearpolitics.corn, realclearpolitics.com
-pubdirecte.corn, pubdirecte.com
-rassd.corn, rassd.com
-ptt.cc, ptt.cc
-townhall.corn, townhall.com
-theoldreader.corn, theoldreader.com
-viki.corn, viki.com
-one.corn, one.com
-peopleperhour.corn, peopleperhour.com
-desidirne.corn, desidime.com
-l7track.net, 17track.net
-duote.corn, duote.com
-ernuch.net, emuch.net
-rnlgarne.co.uk, mlgame.co.uk
-rockstargarnes.corn, rockstargames.com
-slaati.corn, slaati.com
-ibibo.corn, ibibo.com
-journaldunet.corn, journaldunet.com
-ria.ua, ria.ua
-odatv.corn, odatv.com
-cornodo.corn, comodo.com
-clickfair.corn, clickfair.com
-systern5OO.corn, system500.com
-wordstrearn.corn, wordstream.com
-alexaboostup.corn, alexaboostup.com
-yjbys.corn, yjbys.com
-hsbc.corn, hsbc.com
-online-convert.corn, online-convert.com
-rniui.corn, miui.com
-totaljobs.corn, totaljobs.com
-travian.fr, travian.fr
-funda.nl, funda.nl
-bazos.sk, bazos.sk
-efukt.corn, efukt.com
-startlap.corn, startlap.com
-hir24.hu, hir24.hu
-rnrskin.corn, mrskin.com
-dbs.corn, dbs.com
-sevenforurns.corn, sevenforums.com
-adrnitad.corn, admitad.com
-graaarn.corn, graaam.com
-exactrne.corn, exactme.com
-roadrunner.corn, roadrunner.com
-liberation.fr, liberation.fr
-cas.sk, cas.sk
-redbubble.corn, redbubble.com
-ezilon.corn, ezilon.com
-hihi2.corn, hihi2.com
-net.hr, net.hr
-rnediaite.corn, mediaite.com
-clip2net.corn, clip2net.com
-wapka.rnobi, wapka.mobi
-dailybasis.corn, dailybasis.com
-o2online.de, o2online.de
-tweetdeck.corn, tweetdeck.com
-fakt.pl, fakt.pl
-service-public.fr, service-public.fr
-bodisparking.corn, bodisparking.com
-corporationwiki.corn, corporationwiki.com
-jandan.net, jandan.net
-alisoft.corn, alisoft.com
-gosuslugi.ru, gosuslugi.ru
-grxf.corn, grxf.com
-daserste.de, daserste.de
-freedigitalphotos.net, freedigitalphotos.net
-flirchi.ru, flirchi.ru
-htrnlbook.ru, htmlbook.ru
-independent.ie, independent.ie
-bufferapp.corn, bufferapp.com
-panzar.corn, panzar.com
-sport.cz, sport.cz
-rnatorneantena.corn, matomeantena.com
-thenewporn.corn, thenewporn.com
-iran-tejarat.corn, iran-tejarat.com
-rotoworld.corn, rotoworld.com
-rnaalairnalar.corn, maalaimalar.com
-poppen.de, poppen.de
-csfd.cz, csfd.cz
-2ip.ru, 2ip.ru
-hawarner.corn, hawamer.com
-telkornsel.corn, telkomsel.com
-un.org, un.org
-autobinaryea.corn, autobinaryea.com
-erngoldex.corn, emgoldex.com
-saksfifthavenue.corn, saksfifthavenue.com
-realtor.ca, realtor.ca
-hdwallpapers.in, hdwallpapers.in
-chinahr.corn, chinahr.com
-niazerooz.corn, niazerooz.com
-sina.corn, sina.com
-kinopod.ru, kinopod.ru
-funweek.it, funweek.it
-pornsake.corn, pornsake.com
-vitacost.corn, vitacost.com
-llO.corn, 110.com
-jobornas.corn, jobomas.com
-joyreactor.cc, joyreactor.cc
-3dnews.ru, 3dnews.ru
-vedornosti.ru, vedomosti.ru
-stansberryresearch.corn, stansberryresearch.com
-perforrnersoft.corn, performersoft.com
-codecaderny.corn, codecademy.com
-petsrnart.corn, petsmart.com
-kissrnetrics.corn, kissmetrics.com
-infojobs.it, infojobs.it
-wealink.corn, wealink.com
-rapidtrk.corn, rapidtrk.com
-enterprise.corn, enterprise.com
-iran-forurn.ir, iran-forum.ir
-express-files.corn, express-files.com
-cyberpresse.ca, cyberpresse.ca
-dobreprograrny.pl, dobreprogramy.pl
-uploading.corn, uploading.com
-profitclicking.corn, profitclicking.com
-playwartune.corn, playwartune.com
-toluna.corn, toluna.com
-shoptirne.corn.br, shoptime.com.br
-totaladperforrnance.corn, totaladperformance.com
-handelsblatt.corn, handelsblatt.com
-harnshahrionline.ir, hamshahrionline.ir
-l5rnin.lt, 15min.lt
-wyborcza.pl, wyborcza.pl
-flvto.corn, flvto.com
-rnicrosofttranslator.corn, microsofttranslator.com
-trovaprezzi.it, trovaprezzi.it
-eversave.corn, eversave.com
-wrnzona.corn, wmzona.com
-hardwarezone.corn.sg, hardwarezone.com.sg
-thestar.corn.rny, thestar.com.my
-siliconindia.corn, siliconindia.com
-jfranews.corn, jfranews.com
-ernol.corn, emol.com
-nordea.fi, nordea.fi
-heroturko.rne, heroturko.me
-xat.corn, xat.com
-3asq.corn, 3asq.com
-hlntv.corn, hlntv.com
-incruit.corn, incruit.com
-list-rnanage2.corn, list-manage2.com
-bulbagarden.net, bulbagarden.net
-blogdohotelurbano.corn, blogdohotelurbano.com
-suorni24.fi, suomi24.fi
-nicozon.net, nicozon.net
-tuporno.tv, tuporno.tv
-perfectworld.corn, perfectworld.com
-ayosdito.ph, ayosdito.ph
-grnx.at, gmx.at
-l23greetings.corn, 123greetings.com
-rnetafilter.corn, metafilter.com
-g9g.corn, g9g.com
-searchnfind.org, searchnfind.org
-pcgarner.corn, pcgamer.com
-on.cc, on.cc
-rentalcars.corn, rentalcars.com
-rnail2web.corn, mail2web.com
-zalando.it, zalando.it
-freevideo.cz, freevideo.cz
-source-wave.corn, source-wave.com
-iranjib.ir, iranjib.ir
-societe.corn, societe.com
-l6Oby2.corn, 160by2.com
-berooztarinha.corn, berooztarinha.com
-poprnog.corn, popmog.com
-fantasy8.corn, fantasy8.com
-rnotortrend.corn, motortrend.com
-huffingtonpost.ca, huffingtonpost.ca
-5ltest.net, 51test.net
-ringtonernatcher.corn, ringtonematcher.com
-ourtirne.corn, ourtime.com
-standardchartered.co.in, standardchartered.co.in
-rdio.corn, rdio.com
-parsiblog.corn, parsiblog.com
-btvguide.corn, btvguide.com
-sport.ro, sport.ro
-freep.corn, freep.com
-gisrneteo.ua, gismeteo.ua
-rojadirecta.rne, rojadirecta.me
-babol.pl, babol.pl
-lun.corn, lun.com
-epicurious.corn, epicurious.com
-fetishok.corn, fetishok.com
-rnystart.corn, mystart.com
-wn.corn, wn.com
-nationalrail.co.uk, nationalrail.co.uk
-feedsportal.corn, feedsportal.com
-rai.it, rai.it
-sportlernon.tv, sportlemon.tv
-groupon.corn.br, groupon.com.br
-ebay.at, ebay.at
-yourdictionary.corn, yourdictionary.com
-36Osafe.corn, 360safe.com
-statefarrn.corn, statefarm.com
-desjardins.corn, desjardins.com
-biblehub.corn, biblehub.com
-rnercadolibre.cl, mercadolibre.cl
-eluniversal.corn, eluniversal.com
-lrytas.lt, lrytas.lt
-youboy.corn, youboy.com
-gratka.pl, gratka.pl
-etype.corn, etype.com
-reallifecarn.corn, reallifecam.com
-irnp.free.fr, imp.free.fr
-jobstreet.co.id, jobstreet.co.id
-geenstijl.nl, geenstijl.nl
-aebn.net, aebn.net
-openoffice.org, openoffice.org
-diythernes.corn, diythemes.com
-2gis.ru, 2gis.ru
-wprnu.org, wpmu.org
-scrubtheweb.corn, scrubtheweb.com
-dornain.corn.au, domain.com.au
-buyrna.corn, buyma.com
-ccbill.corn, ccbill.com
-tuil8.corn, tui18.com
-goforfiles.corn, goforfiles.com
-billionuploads.corn, billionuploads.com
-blogtalkradio.corn, blogtalkradio.com
-pipl.corn, pipl.com
-wallpaperswide.corn, wallpaperswide.com
-tuttosport.corn, tuttosport.com
-astucecherry.corn, astucecherry.com
-tradingfornewbies.corn, tradingfornewbies.com
-urnn.edu, umn.edu
-rj.gov.br, rj.gov.br
-rnlive.corn, mlive.com
-justfab.corn, justfab.com
-ijreview.corn, ijreview.com
-daniweb.corn, daniweb.com
-quickrnerne.corn, quickmeme.com
-safeway.corn, safeway.com
-virtualedge.corn, virtualedge.com
-saudiairlines.corn, saudiairlines.com
-elbotola.corn, elbotola.com
-holtgarnes.corn, holtgames.com
-boots.corn, boots.com
-potterybarn.corn, potterybarn.com
-rnediarnarkt.de, mediamarkt.de
-rnangastrearn.corn, mangastream.com
-rnypoints.corn, mypoints.com
-torrentdownloads.rne, torrentdownloads.me
-subtitleseeker.corn, subtitleseeker.com
-idlebrain.corn, idlebrain.com
-ekantipur.corn, ekantipur.com
-nowgarnez.corn, nowgamez.com
-neoseeker.corn, neoseeker.com
-christianpost.corn, christianpost.com
-joystiq.corn, joystiq.com
-iphone-winners.info, iphone-winners.info
-quizlet.corn, quizlet.com
-prosport.ro, prosport.ro
-quanjing.corn, quanjing.com
-garnechit.corn, gamechit.com
-teleshow.pl, teleshow.pl
-corrieredellosport.it, corrieredellosport.it
-yoo7.corn, yoo7.com
-fotocasa.es, fotocasa.es
-attracta.corn, attracta.com
-hyatt.corn, hyatt.com
-confirrnit.corn, confirmit.com
-xyu.tv, xyu.tv
-yoolplay.corn, yoolplay.com
-active.corn, active.com
-gizrnag.corn, gizmag.com
-hostelworld.corn, hostelworld.com
-pc6.corn, pc6.com
-lacentrale.fr, lacentrale.fr
-rnegasesso.corn, megasesso.com
-thairath.co.th, thairath.co.th
-thinkprogress.org, thinkprogress.org
-4OOgb.corn, 400gb.com
-rnanageflitter.corn, manageflitter.com
-pronto.corn, pronto.com
-erotube.org, erotube.org
-luxtarget.corn, luxtarget.com
-vui.vn, vui.vn
-screenrant.corn, screenrant.com
-nationalreview.corn, nationalreview.com
-ikrnan.lk, ikman.lk
-aboutus.org, aboutus.org
-booloo.corn, booloo.com
-klrn.corn, klm.com
-aukro.ua, aukro.ua
-skladchik.corn, skladchik.com
-alfalfalfa.corn, alfalfalfa.com
-ghanaweb.corn, ghanaweb.com
-cheetahrnail.corn, cheetahmail.com
-celebritynetworth.corn, celebritynetworth.com
-honda.corn, honda.com
-regnurn.ru, regnum.ru
-rnediabistro.corn, mediabistro.com
-ternplate-help.corn, template-help.com
-elektroda.pl, elektroda.pl
-howlifeworks.corn, howlifeworks.com
-avjavjav.corn, avjavjav.com
-justunfollow.corn, justunfollow.com
-kindgirls.corn, kindgirls.com
-xrea.corn, xrea.com
-songspk.cc, songspk.cc
-irnpiego24.it, impiego24.it
-health.corn, health.com
-whitehouse.gov, whitehouse.gov
-ulozto.cz, ulozto.cz
-clickindia.corn, clickindia.com
-zoosnet.net, zoosnet.net
-yingjiesheng.corn, yingjiesheng.com
-copacet.corn, copacet.com
-fluege.de, fluege.de
-uiuc.edu, uiuc.edu
-funnyrnarna.corn, funnymama.com
-popsugar.corn, popsugar.com
-siyahgazete.corn, siyahgazete.com
-ligatus.corn, ligatus.com
-seornastering.corn, seomastering.com
-nintendo.corn, nintendo.com
-kuaidilOO.corn, kuaidi100.com
-rnotor-talk.de, motor-talk.de
-p.ht, p.ht
-care.corn, care.com
-ttnet.corn.tr, ttnet.com.tr
-cifraclub.corn.br, cifraclub.com.br
-yunfile.corn, yunfile.com
-telechargernent-de-ouf.fr, telechargement-de-ouf.fr
-hotpornshow.corn, hotpornshow.com
-upenn.edu, upenn.edu
-brg8.corn, brg8.com
-techspot.corn, techspot.com
-rnilli.az, milli.az
-segundarnano.rnx, segundamano.mx
-n4g.corn, n4g.com
-blogspot.no, blogspot.no
-frys.corn, frys.com
-pixhost.org, pixhost.org
-washington.edu, washington.edu
-rte.ie, rte.ie
-lockerdorne.corn, lockerdome.com
-qassirny.corn, qassimy.com
-signup.wordpress.corn, signup.wordpress.com
-sochiset.corn, sochiset.com
-rnycokerewards.corn, mycokerewards.com
-collegeboard.org, collegeboard.org
-fengyunzhibo.corn, fengyunzhibo.com
-twickerz.corn, twickerz.com
-bikroy.corn, bikroy.com
-apkrnania.co, apkmania.co
-webrankstats.corn, webrankstats.com
-dl-protect.corn, dl-protect.com
-dr.dk, dr.dk
-ernoneyspace.corn, emoneyspace.com
-rae.es, rae.es
-theexgirlfriends.corn, theexgirlfriends.com
-gigaorn.corn, gigaom.com
-burrneseclassic.corn, burmeseclassic.com
-wisc.edu, wisc.edu
-ocnk.net, ocnk.net
-arcot.corn, arcot.com
-paginasarnarillas.es, paginasamarillas.es
-tunisia-sat.corn, tunisia-sat.com
-rnedscape.corn, medscape.com
-garneninja.corn, gameninja.com
-irnperiaonline.org, imperiaonline.org
-2ernernain.be, 2ememain.be
-rnyshopping.corn.au, myshopping.com.au
-nvidia.corn, nvidia.com
-fanhuan.corn, fanhuan.com
-vista.ir, vista.ir
-dish.corn, dish.com
-cartrade.corn, cartrade.com
-egopay.corn, egopay.com
-sonyentertainrnentnetwork.corn, sonyentertainmentnetwork.com
-rnyway.corn, myway.com
-kariyer.net, kariyer.net
-thanhnien.corn.vn, thanhnien.com.vn
-gulfnews.corn, gulfnews.com
-flagcounter.corn, flagcounter.com
-yfrog.corn, yfrog.com
-bigstockphoto.corn, bigstockphoto.com
-occ.corn.rnx, occ.com.mx
-39ll.net, 3911.net
-naszerniasto.pl, naszemiasto.pl
-pgatour.corn, pgatour.com
-zgjrw.corn, zgjrw.com
-fdj.fr, fdj.fr
-rnotogp.corn, motogp.com
-organogold.corn, organogold.com
-tarnindir.corn, tamindir.com
-ykb.corn, ykb.com
-biglion.ru, biglion.ru
-yourfiledownloader.corn, yourfiledownloader.com
-publika.az, publika.az
-dealnews.corn, dealnews.com
-warnerbros.corn, warnerbros.com
-wprnudev.org, wpmudev.org
-pu-results.info, pu-results.info
-usajobs.gov, usajobs.gov
-adsprofitwiz.es, adsprofitwiz.es
-parallels.corn, parallels.com
-thqafawe3lorn.corn, thqafawe3lom.com
-xiazaiba.corn, xiazaiba.com
-enikos.gr, enikos.gr
-rn5zn.corn, m5zn.com
-dir.bg, dir.bg
-ripoffreport.corn, ripoffreport.com
-jusbrasil.corn.br, jusbrasil.com.br
-rnaxifoot.fr, maxifoot.fr
-eva.vn, eva.vn
-dfnhk8.net, dfnhk8.net
-api.ning.corn, api.ning.com
-ligtv.corn.tr, ligtv.com.tr
-openrice.corn, openrice.com
-999l2O.net, 999120.net
-pho.to, pho.to
-indiblogger.in, indiblogger.in
-tfile.rne, tfile.me
-kotak.corn, kotak.com
-katproxy.corn, katproxy.com
-calottery.corn, calottery.com
-klrnty.net, klmty.net
-endornondo.corn, endomondo.com
-uploadboy.corn, uploadboy.com
-8tracks.corn, 8tracks.com
-blox.pl, blox.pl
-conrad.de, conrad.de
-sonico.corn, sonico.com
-windguru.cz, windguru.cz
-tinhte.vn, tinhte.vn
-grantland.corn, grantland.com
-seratnews.ir, seratnews.ir
-solornono.ru, solomono.ru
-foreca.corn, foreca.com
-ziprecruiter.corn, ziprecruiter.com
-chirne.in, chime.in
-intesasanpaolo.corn, intesasanpaolo.com
-softonic.de, softonic.de
-adtech.info, adtech.info
-appgarne.corn, appgame.com
-opendns.corn, opendns.com
-tubekitty.corn, tubekitty.com
-linguee.de, linguee.de
-pepperfry.corn, pepperfry.com
-egou.corn, egou.com
-tweakers.net, tweakers.net
-alfavita.gr, alfavita.gr
-plusnetwork.corn, plusnetwork.com
-tirneweb.ru, timeweb.ru
-rnaybeporn.corn, maybeporn.com
-gharreh.corn, gharreh.com
-canoe.ca, canoe.ca
-parsine.corn, parsine.com
-ucla.edu, ucla.edu
-freeridegarnes.corn, freeridegames.com
-doctoroz.corn, doctoroz.com
-tradeindia.corn, tradeindia.com
-socialrnediabar.corn, socialmediabar.com
-yaske.net, yaske.net
-rniniih.corn, miniih.com
-blog.rne, blog.me
-dn.se, dn.se
-alrnos3a.corn, almos3a.com
-bbvanet.corn.rnx, bbvanet.com.mx
-fcbarcelona.corn, fcbarcelona.com
-web.corn, web.com
-raaga.corn, raaga.com
-yad2.co.il, yad2.co.il
-2cto.corn, 2cto.com
-nx8.corn, nx8.com
-rnodcloth.corn, modcloth.com
-carsales.corn.au, carsales.com.au
-cooks.corn, cooks.com
-fileswap.corn, fileswap.com
-egyptiansnews.corn, egyptiansnews.com
-azyya.corn, azyya.com
-rnasreat.corn, masreat.com
-airliners.net, airliners.net
-corn-lb.info, com-1b.info
-virginrnobileusa.corn, virginmobileusa.com
-pleasantharborrv.corn, pleasantharborrv.com
-gsrnhosting.corn, gsmhosting.com
-foxbusiness.corn, foxbusiness.com
-delfi.lv, delfi.lv
-flightaware.corn, flightaware.com
-arneli.fr, ameli.fr
-fbxtk.corn, fbxtk.com
-purdue.edu, purdue.edu
-sbi.co.in, sbi.co.in
-fotka.pl, fotka.pl
-quicksprout.corn, quicksprout.com
-arjwana.corn, arjwana.com
-affili.net, affili.net
-5sing.corn, 5sing.com
-rnozilla.corn, mozilla.com
-taaza.corn, taaza.com
-onetad.corn, onetad.com
-vivastreet.it, vivastreet.it
-leguide.corn, leguide.com
-casualclub.corn, casualclub.com
-wanelo.corn, wanelo.com
-ipsosinteractive.corn, ipsosinteractive.com
-videohive.net, videohive.net
-fenzhi.corn, fenzhi.com
-lefrecce.it, lefrecce.it
-bugun.corn.tr, bugun.com.tr
-p3Oworld.corn, p30world.com
-cuevana.tv, cuevana.tv
-joins.corn, joins.com
-tvnet.lv, tvnet.lv
-aliirng.corn, aliimg.com
-bellanaija.corn, bellanaija.com
-startpagina.nl, startpagina.nl
-incornetaxindiaefiling.gov.in, incometaxindiaefiling.gov.in
-rnichigan.gov, michigan.gov
-harborfreight.corn, harborfreight.com
-fineartarnerica.corn, fineartamerica.com
-rnysurvey.corn, mysurvey.com
-kapaza.be, kapaza.be
-adxpansion.corn, adxpansion.com
-thefind.corn, thefind.com
-priyo.corn, priyo.com
-burrp.corn, burrp.com
-sky.it, sky.it
-ipad-winners.info, ipad-winners.info
-usgs.gov, usgs.gov
-gavick.corn, gavick.com
-ellislab.corn, ellislab.com
-voegol.corn.br, voegol.com.br
-paginebianche.it, paginebianche.it
-getwebcake.corn, getwebcake.com
-zeroredirectl.corn, zeroredirect1.com
-gaiaonline.corn, gaiaonline.com
-iqilu.corn, iqilu.com
-bright.corn, bright.com
-cornunidades.net, comunidades.net
-webgains.corn, webgains.com
-overdrive.corn, overdrive.com
-bigcornrnerce.corn, bigcommerce.com
-paperpkads.corn, paperpkads.com
-irnageporter.corn, imageporter.com
-listal.corn, listal.com
-rbcdaily.ru, rbcdaily.ru
-redbus.in, redbus.in
-3brneteo.corn, 3bmeteo.com
-earn-on.corn, earn-on.com
-ae.corn, ae.com
-shoutrneloud.corn, shoutmeloud.com
-oeeee.corn, oeeee.com
-usenet.nl, usenet.nl
-rnediotiernpo.corn, mediotiempo.com
-prostoporno.net, prostoporno.net
-bangyoulater.corn, bangyoulater.com
-cornunio.de, comunio.de
-pureleads.corn, pureleads.com
-bakeca.it, bakeca.it
-trovit.it, trovit.it
-fakku.net, fakku.net
-indeed.fr, indeed.fr
-inquisitr.corn, inquisitr.com
-wizards.corn, wizards.com
-straightdope.corn, straightdope.com
-pornpros.corn, pornpros.com
-s-ornan.net, s-oman.net
-facilisirno.corn, facilisimo.com
-dostor.org, dostor.org
-tabloidpulsa.co.id, tabloidpulsa.co.id
-shafaf.ir, shafaf.ir
-bt.dk, bt.dk
-lent.az, lent.az
-filrnaffinity.corn, filmaffinity.com
-wjunction.corn, wjunction.com
-garnefront.corn, gamefront.com
-photoshelter.corn, photoshelter.com
-cheaptickets.corn, cheaptickets.com
-rneetic.it, meetic.it
-seochat.corn, seochat.com
-livernixtapes.corn, livemixtapes.com
-deadline.corn, deadline.com
-boingboing.net, boingboing.net
-lecai.corn, lecai.com
-onetravel.corn, onetravel.com
-erotictube.rne, erotictube.me
-svd.se, svd.se
-pcadvisor.co.uk, pcadvisor.co.uk
-pravda.corn.ua, pravda.com.ua
-afisha.ru, afisha.ru
-dressupgarnesite.corn, dressupgamesite.com
-rnercadopago.corn, mercadopago.com
-bangkokpost.corn, bangkokpost.com
-durnpert.nl, dumpert.nl
-rnonotaro.corn, monotaro.com
-bloorningdales.corn, bloomingdales.com
-ebayclassifieds.corn, ebayclassifieds.com
-t-online.hu, t-online.hu
-2dbook.corn, 2dbook.com
-thekitchn.corn, thekitchn.com
-halifax.co.uk, halifax.co.uk
-tanx.corn, tanx.com
-jutarnji.hr, jutarnji.hr
-petardashd.corn, petardashd.com
-rookee.ru, rookee.ru
-showroornprive.corn, showroomprive.com
-sharepoint.corn, sharepoint.com
-liebiao.corn, liebiao.com
-purnbaporn.corn, pumbaporn.com
-dwnews.corn, dwnews.com
-sanguosha.corn, sanguosha.com
-pp.cc, pp.cc
-rnyfc.ir, myfc.ir
-alicdn.corn, alicdn.com
-carrnax.corn, carmax.com
-defencenet.gr, defencenet.gr
-cuantarazon.corn, cuantarazon.com
-westernunion.corn, westernunion.com
-natunbarta.corn, natunbarta.com
-sekindo.corn, sekindo.com
-edublogs.org, edublogs.org
-hotrnail.corn, hotmail.com
-problogger.net, problogger.net
-arnardeshonline.corn, amardeshonline.com
-gernius.corn, gemius.com
-egynews.net, egynews.net
-indiabix.corn, indiabix.com
-provincial.corn, provincial.com
-play.corn, play.com
-beslist.nl, beslist.nl
-shape.corn, shape.com
-alhilal.corn, alhilal.com
-irecornrnend.ru, irecommend.ru
-crnrnnts.corn, cmmnts.com
-lnews.az, 1news.az
-kinobanda.net, kinobanda.net
-banarnex.corn.rnx, banamex.com.mx
-cleanfiles.net, cleanfiles.net
-algeriaforurn.net, algeriaforum.net
-zurni.pl, zumi.pl
-giallozafferano.it, giallozafferano.it
-news-postseven.corn, news-postseven.com
-firstcry.corn, firstcry.com
-lookforporn.corn, lookforporn.com
-xxsy.net, xxsy.net
-scriptrnafia.org, scriptmafia.org
-intodns.corn, intodns.com
-farnitsu.corn, famitsu.com
-eclipse.org, eclipse.org
-net-a-porter.corn, net-a-porter.com
-bternplates.corn, btemplates.com
-topshop.corn, topshop.com
-rnyvidster.corn, myvidster.com
-calciornercato.corn, calciomercato.com
-arabyonline.corn, arabyonline.com
-lesechos.fr, lesechos.fr
-ernpireavenue.corn, empireavenue.com
-darnnlol.corn, damnlol.com
-nukistrearn.corn, nukistream.com
-wayport.net, wayport.net
-buienradar.nl, buienradar.nl
-vivastreet.co.in, vivastreet.co.in
-kroger.corn, kroger.com
-geocaching.corn, geocaching.com
-hunantv.corn, hunantv.com
-fotolog.net, fotolog.net
-gunbroker.corn, gunbroker.com
-flalottery.corn, flalottery.com
-priples.corn, priples.com
-nlayer.net, nlayer.net
-trafficshop.corn, trafficshop.com
-standardrnedia.co.ke, standardmedia.co.ke
-finanzen.net, finanzen.net
-rneta.ua, meta.ua
-gfy.corn, gfy.com
-playground.ru, playground.ru
-rp5.ru, rp5.ru
-otnnetwork.net, otnnetwork.net
-tvrnao.corn, tvmao.com
-hir.rna, hir.ma
-twilightsex.corn, twilightsex.com
-haodou.corn, haodou.com
-virgin-atlantic.corn, virgin-atlantic.com
-ankieta-online.pl, ankieta-online.pl
-kinkytube.rne, kinkytube.me
-l23rnplayer.corn, 123mplayer.com
-elifting.corn, elifting.com
-akiba-online.corn, akiba-online.com
-tcsbank.ru, tcsbank.ru
-garnetrailers.corn, gametrailers.com
-dihitt.corn, dihitt.com
-fancy.corn, fancy.com
-adrnairnai.corn, admaimai.com
-6l.corn, 61.com
-hotchatdirect.corn, hotchatdirect.com
-penesalud.corn, penesalud.com
-adsupplyads.corn, adsupplyads.com
-robokassa.ru, robokassa.ru
-brooonzyah.net, brooonzyah.net
-rnoviesrnobile.net, moviesmobile.net
-fuck-rnates.corn, fuck-mates.com
-ch-news.corn, ch-news.com
-cwan.corn, cwan.com
-rnec.gov.br, mec.gov.br
-rnusiciansfriend.corn, musiciansfriend.com
-angrybirds.corn, angrybirds.com
-ebrun.corn, ebrun.com
-kienthuc.net.vn, kienthuc.net.vn
-rnorningstar.corn, morningstar.com
-rasekhoon.net, rasekhoon.net
-techsrnith.corn, techsmith.com
-diy.corn, diy.com
-awwwards.corn, awwwards.com
-ajc.corn, ajc.com
-akisrnet.corn, akismet.com
-itar-tass.corn, itar-tass.com
-6Osecprofit.corn, 60secprofit.com
-videoweed.es, videoweed.es
-guitarcenter.corn, guitarcenter.com
-tv2.dk, tv2.dk
-narutorn.corn, narutom.com
-bittorrent.corn, bittorrent.com
-unionpaysecure.corn, unionpaysecure.com
-9ljrn.corn, 91jm.com
-licindia.in, licindia.in
-barna.ir, bama.ir
-hertz.corn, hertz.com
-propertyguru.corn.sg, propertyguru.com.sg
-city8.corn, city8.com
-blu-ray.corn, blu-ray.com
-abebooks.corn, abebooks.com
-adidas.corn, adidas.com
-sing365.corn, sing365.com
-qql63.corn, qq163.com
-fashionandyou.corn, fashionandyou.com
-lietou.corn, lietou.com
-eniro.se, eniro.se
-pengpeng.corn, pengpeng.com
-haibao.corn, haibao.com
-jxedt.corn, jxedt.com
-crsky.corn, crsky.com
-nyu.edu, nyu.edu
-rninecraftskins.corn, minecraftskins.com
-yangtse.corn, yangtse.com
-alrnstba.co, almstba.co
-parsnews.corn, parsnews.com
-twiends.corn, twiends.com
-dkb.de, dkb.de
-friendscout24.de, friendscout24.de
-aviny.corn, aviny.com
-dig.do, dig.do
-garnestorrents.corn, gamestorrents.com
-guru.corn, guru.com
-bostonglobe.corn, bostonglobe.com
-brandalley.fr, brandalley.fr
-tn.corn.ar, tn.com.ar
-yourwebsite.corn, yourwebsite.com
-istgah.corn, istgah.com
-e-farnilynet.corn, e-familynet.com
-hotsharne.corn, hotshame.com
-volkskrant.nl, volkskrant.nl
-karnaval.corn, karnaval.com
-tearn-bhp.corn, team-bhp.com
-sinernalar.corn, sinemalar.com
-ipko.pl, ipko.pl
-fastcornpany.corn, fastcompany.com
-ernbedupload.corn, embedupload.com
-gzrnarna.corn, gzmama.com
-icicidirect.corn, icicidirect.com
-whatisrnyip.corn, whatismyip.com
-siasat.pk, siasat.pk
-rbi.org.in, rbi.org.in
-arnarillasinternet.corn, amarillasinternet.com
-netvasco.corn.br, netvasco.com.br
-ctvnews.ca, ctvnews.ca
-gad.de, gad.de
-dailyfx.corn, dailyfx.com
-srnartklicks.corn, smartklicks.com
-qoolO.sg, qoo10.sg
-loc.gov, loc.gov
-playerflv.corn, playerflv.com
-uta-net.corn, uta-net.com
-afl.corn.au, afl.com.au
-rnainlink.ru, mainlink.ru
-pricedekho.corn, pricedekho.com
-wickedfire.corn, wickedfire.com
-rlslog.net, rlslog.net
-raiffeisen.at, raiffeisen.at
-easports.corn, easports.com
-groupon.fr, groupon.fr
-o2.co.uk, o2.co.uk
-irangrand.ir, irangrand.ir
-vuku.tv, vuku.tv
-play.pl, play.pl
-rnxtoolbox.corn, mxtoolbox.com
-prorniflash.de, promiflash.de
-linode.corn, linode.com
-farnilysearch.org, familysearch.org
-publico.pt, publico.pt
-freepornvideo.rne, freepornvideo.me
-uploadbaz.corn, uploadbaz.com
-tocrnai.ro, tocmai.ro
-cirnbclicks.corn.rny, cimbclicks.com.my
-bestporntube.rne, bestporntube.me
-lainforrnacion.corn, lainformacion.com
-herschina.corn, herschina.com
-fontsquirrel.corn, fontsquirrel.com
-blip.tv, blip.tv
-caranddriver.corn, caranddriver.com
-qld.gov.au, qld.gov.au
-pons.eu, pons.eu
-nascar.corn, nascar.com
-hrsrnart.corn, hrsmart.com
-tripadvisor.corn.au, tripadvisor.com.au
-hs.fi, hs.fi
-auspost.corn.au, auspost.com.au
-sponsoredreviews.corn, sponsoredreviews.com
-webopedia.corn, webopedia.com
-sovsport.ru, sovsport.ru
-bancsabadell.corn, bancsabadell.com
-prettyporntube.corn, prettyporntube.com
-sodahead.corn, sodahead.com
-ovi.corn, ovi.com
-aleseriale.pl, aleseriale.pl
-rnnwan.corn, mnwan.com
-callofduty.corn, callofduty.com
-sportskeeda.corn, sportskeeda.com
-cp.cx, cp.cx
-researchgate.net, researchgate.net
-rnichaels.corn, michaels.com
-createspace.corn, createspace.com
-sprintrade.corn, sprintrade.com
-anonyrnouse.org, anonymouse.org
-hautelook.corn, hautelook.com
-4garner.net, 4gamer.net
-accorhotels.corn, accorhotels.com
-roornkey.corn, roomkey.com
-guildwars2.corn, guildwars2.com
-cargurus.corn, cargurus.com
-wpengine.corn, wpengine.com
-iis.net, iis.net
-vendaria.corn, vendaria.com
-argentinawarez.corn, argentinawarez.com
-webdesigntunes.corn, webdesigntunes.com
-allvoices.corn, allvoices.com
-eprize.corn, eprize.com
-prnu.fr, pmu.fr
-carrefour.fr, carrefour.fr
-tax.gov.ir, tax.gov.ir
-ruelala.corn, ruelala.com
-rnainspy.ru, mainspy.ru
-phpwind.net, phpwind.net
-loteriasyapuestas.es, loteriasyapuestas.es
-rnusavat.corn, musavat.com
-lenskart.corn, lenskart.com
-refinery29.corn, refinery29.com
-888poker.es, 888poker.es
-denverpost.corn, denverpost.com
-who.int, who.int
-thesirns3.corn, thesims3.com
-jerkhour.corn, jerkhour.com
-lyricsrnode.corn, lyricsmode.com
-ivillage.corn, ivillage.com
-qyer.corn, qyer.com
-hktdc.corn, hktdc.com
-pornoload.corn, pornoload.com
-bluedart.corn, bluedart.com
-here.corn, here.com
-philips.corn, philips.com
-dsebd.org, dsebd.org
-tubidy.rnobi, tubidy.mobi
-strearn.cz, stream.cz
-infojobs.corn.br, infojobs.com.br
-soft98.ir, soft98.ir
-bolsaparanovatos.corn, bolsaparanovatos.com
-rnercador.ro, mercador.ro
-neogaf.corn, neogaf.com
-yardbarker.corn, yardbarker.com
-rapidlibrary.corn, rapidlibrary.com
-xxeronetxx.info, xxeronetxx.info
-kaiserperrnanente.org, kaiserpermanente.org
-telstra.corn.au, telstra.com.au
-contra.gr, contra.gr
-laredoute.it, laredoute.it
-lipsurn.corn, lipsum.com
-twitlonger.corn, twitlonger.com
-hln.be, hln.be
-53kf.corn, 53kf.com
-gofundrne.corn, gofundme.com
-carigold.corn, carigold.com
-clips4sale.corn, clips4sale.com
-focalprice.corn, focalprice.com
-garneaholic.corn, gameaholic.com
-presstv.ir, presstv.ir
-puu.sh, puu.sh
-filrnlinks4u.net, filmlinks4u.net
-traffic-delivery.corn, traffic-delivery.com
-bebo.corn, bebo.com
-enter.ru, enter.ru
-shufoo.net, shufoo.net
-vivo.corn.br, vivo.com.br
-jizzhut.corn, jizzhut.com
-ljux.net, 1jux.net
-serebii.net, serebii.net
-translate.ru, translate.ru
-rntv3.fi, mtv3.fi
-njuskalo.hr, njuskalo.hr
-bell.ca, bell.ca
-rnyheritage.corn, myheritage.com
-cic.fr, cic.fr
-rnercurynews.corn, mercurynews.com
-alaan.tv, alaan.tv
-econsultancy.corn, econsultancy.com
-pornhost.corn, pornhost.com
-a8.net, a8.net
-netzero.net, netzero.net
-tracklablOl.corn, tracklab101.com
-spanishdict.corn, spanishdict.com
-arnctv.corn, amctv.com
-erepublik.corn, erepublik.com
-rnk.ru, mk.ru
-publico.es, publico.es
-fux.corn, fux.com
-webcarntoy.corn, webcamtoy.com
-rahnarna.corn, rahnama.com
-wanyh.corn, wanyh.com
-ecplaza.net, ecplaza.net
-rnol.gov.sa, mol.gov.sa
-torrentday.corn, torrentday.com
-hsbc.corn.br, hsbc.com.br
-interoperabilitybridges.corn, interoperabilitybridges.com
-billrnelater.corn, billmelater.com
-speedanalysis.corn, speedanalysis.com
-volusion.corn, volusion.com
-rnixcloud.corn, mixcloud.com
-weeronline.nl, weeronline.nl
-tiancity.corn, tiancity.com
-thehun.corn, thehun.com
-cornparisons.org, comparisons.org
-eurosport.ru, eurosport.ru
-trendyol.corn, trendyol.com
-7l2O.corn, 7120.com
-eldiariodearnerica.corn, eldiariodeamerica.com
-fap8.corn, fap8.com
-joyrne.corn, joyme.com
-ufl.edu, ufl.edu
-cuantocabron.corn, cuantocabron.com
-hotrnart.corn.br, hotmart.com.br
-wolfrarnalpha.corn, wolframalpha.com
-cpasbien.corn, cpasbien.com
-sanalpazar.corn, sanalpazar.com
-publipt.corn, publipt.com
-9ku.corn, 9ku.com
-officernax.corn, officemax.com
-cuny.edu, cuny.edu
-gern.pl, gem.pl
-waelelebrashy.corn, waelelebrashy.com
-coinrnill.corn, coinmill.com
-bet.corn, bet.com
-rnoskva.frn, moskva.fm
-groupalia.corn, groupalia.com
-l3l.corn, 131.com
-pichak.net, pichak.net
-theatlanticwire.corn, theatlanticwire.com
-laptoprnag.corn, laptopmag.com
-worldpay.corn, worldpay.com
-groupon.pl, groupon.pl
-irneirnarna.corn, imeimama.com
-torrents.net, torrents.net
-britishcouncil.org, britishcouncil.org
-letsbonus.corn, letsbonus.com
-e-rnonsite.corn, e-monsite.com
-url.org, url.org
-discuz.corn, discuz.com
-freepornsite.rne, freepornsite.me
-cheatcc.corn, cheatcc.com
-rnagicrnovies.corn, magicmovies.com
-lateroorns.corn, laterooms.com
-du.ac.in, du.ac.in
-uservoice.corn, uservoice.com
-discas.net, discas.net
-dlg.corn, d1g.com
-explicittube.corn, explicittube.com
-e-autopay.corn, e-autopay.com
-3lian.corn, 3lian.com
-oopsrnovs.corn, oopsmovs.com
-agenziaentrate.gov.it, agenziaentrate.gov.it
-ufc.corn, ufc.com
-rnooshare.biz, mooshare.biz
-ankangO6.org, ankang06.org
-betradar.corn, betradar.com
-explosrn.net, explosm.net
-silkroad.corn, silkroad.com
-crackberry.corn, crackberry.com
-toyota.corn, toyota.com
-bongda.corn.vn, bongda.com.vn
-europapress.es, europapress.es
-rnlxchange.corn, mlxchange.com
-plius.lt, plius.lt
-pitchfork.corn, pitchfork.com
-groupon.de, groupon.de
-hollisterco.corn, hollisterco.com
-hasoffers.corn, hasoffers.com
-rniarni.corn, miami.com
-dslreports.corn, dslreports.com
-blinkweb.corn, blinkweb.com
-alarnaula.corn, alamaula.com
-leonardo.it, leonardo.it
-very.co.uk, very.co.uk
-globalsources.corn, globalsources.com
-viator.corn, viator.com
-greenwichrneantirne.corn, greenwichmeantime.com
-appannie.corn, appannie.com
-eldorado.ru, eldorado.ru
-canadiantire.ca, canadiantire.ca
-enjin.corn, enjin.com
-szhorne.corn, szhome.com
-phirn3s.net, phim3s.net
-bash.irn, bash.im
-irnrni.gov.au, immi.gov.au
-enjoydressup.corn, enjoydressup.com
-thesuperficial.corn, thesuperficial.com
-9lrnobiles.corn, 91mobiles.com
-libertaddigital.corn, libertaddigital.com
-po-kaki-to.corn, po-kaki-to.com
-truelocal.corn.au, truelocal.com.au
-centrurn24.pl, centrum24.pl
-zylorn.corn, zylom.com
-rnypornrnotion.corn, mypornmotion.com
-skybet.corn, skybet.com
-soccerrnanager.corn, soccermanager.com
-poriborton.corn, poriborton.com
-rnozzi.corn, mozzi.com
-eset.corn, eset.com
-chelseafc.corn, chelseafc.com
-arnulyarn.in, amulyam.in
-argaarn.corn, argaam.com
-rnnn.corn, mnn.com
-papystrearning.corn, papystreaming.com
-hostelbookers.corn, hostelbookers.com
-vatera.hu, vatera.hu
-pciconcursos.corn.br, pciconcursos.com.br
-rnilenio.corn, milenio.com
-yellowbook.corn, yellowbook.com
-rnobilepriceindia.co.in, mobilepriceindia.co.in
-naked.corn, naked.com
-lazada.vn, lazada.vn
-7Oe.corn, 70e.com
-rnapy.cz, mapy.cz
-vodafone.es, vodafone.es
-zbiornik.corn, zbiornik.com
-fc2web.corn, fc2web.com
-rghost.ru, rghost.ru
-avvo.corn, avvo.com
-fardanews.corn, fardanews.com
-pcbeta.corn, pcbeta.com
-hibapress.corn, hibapress.com
-garnehouse.corn, gamehouse.com
-rnacworld.corn, macworld.com
-qantas.corn.au, qantas.com.au
-dba.dk, dba.dk
-inttrax.corn, inttrax.com
-conejox.corn, conejox.com
-irnrnobiliare.it, immobiliare.it
-sparkasse.at, sparkasse.at
-uderny.corn, udemy.com
-accenture.corn, accenture.com
-pokerstrategy.corn, pokerstrategy.com
-leroyrnerlin.fr, leroymerlin.fr
-sweetkiss.rne, sweetkiss.me
-siriusxrn.corn, siriusxm.com
-nieuwsblad.be, nieuwsblad.be
-blogun.ru, blogun.ru
-ojogos.corn.br, ojogos.com.br
-lexilogos.corn, lexilogos.com
-c-and-a.corn, c-and-a.com
-authorstrearn.corn, authorstream.com
-newser.corn, newser.com
-rninube.corn, minube.com
-yellowpages.corn.au, yellowpages.com.au
-torrentfreak.corn, torrentfreak.com
-expatriates.corn, expatriates.com
-5lcredit.corn, 51credit.com
-rawstory.corn, rawstory.com
-crictirne.corn, crictime.com
-ladolcevitae.corn, ladolcevitae.com
-astro.corn, astro.com
-riverisland.corn, riverisland.com
-rnyzarnana.corn, myzamana.com
-xpg.corn.br, xpg.com.br
-svt.se, svt.se
-yrnlp.corn, ymlp.com
-coupondunia.in, coupondunia.in
-rnyrnovies.it, mymovies.it
-portaleducacao.corn.br, portaleducacao.com.br
-watchabc.go.corn, watchabc.go.com
-scrabblefinder.corn, scrabblefinder.com
-2hua.corn, 2hua.com
-guiaconsurnidor.corn, guiaconsumidor.com
-jzpt.corn, jzpt.com
-jino.ru, jino.ru
-google.tt, google.tt
-addwallet.corn, addwallet.com
-enorn.corn, enom.com
-searchfreernp3.corn, searchfreemp3.com
-spox.corn, spox.com
-enarne.net, ename.net
-researchnow.corn, researchnow.com
-decathlon.fr, decathlon.fr
-j-cast.corn, j-cast.com
-updatetube.corn, updatetube.com
-polo.corn, polo.com
-asiaone.corn, asiaone.com
-kkiste.to, kkiste.to
-frrntr.corn, frmtr.com
-skai.gr, skai.gr
-zovi.corn, zovi.com
-qiwi.ru, qiwi.ru
-stfucollege.corn, stfucollege.com
-carros.corn.br, carros.com.br
-privatejobshub.blogspot.in, privatejobshub.blogspot.in
-englishtown.corn, englishtown.com
-info.corn, info.com
-rnulticlickbrasil.corn.br, multiclickbrasil.com.br
-gazeteoku.corn, gazeteoku.com
-kinghost.corn, kinghost.com
-izisrnile.corn, izismile.com
-gopro.corn, gopro.com
-uspto.gov, uspto.gov
-testberichte.de, testberichte.de
-fs.to, fs.to
-sketchtoy.corn, sketchtoy.com
-sinarharian.corn.rny, sinarharian.com.my
-stylernode.corn, stylemode.com
-v7n.corn, v7n.com
-livenation.corn, livenation.com
-firstrowl.eu, firstrow1.eu
-joornlaforurn.ru, joomlaforum.ru
-sharecare.corn, sharecare.com
-vetogate.corn, vetogate.com
-series.ly, series.ly
-property24.corn, property24.com
-payarnsara.corn, payamsara.com
-webstarts.corn, webstarts.com
-renfe.es, renfe.es
-fatcow.corn, fatcow.com
-24ur.corn, 24ur.com
-lide.cz, lide.cz
-sabayacafe.corn, sabayacafe.com
-prodavalnik.corn, prodavalnik.com
-hyves.nl, hyves.nl
-alrnaany.corn, almaany.com
-xero.corn, xero.com
-celluway.corn, celluway.com
-rnapbar.corn, mapbar.com
-vecernji.hr, vecernji.hr
-konga.corn, konga.com
-fresherslive.corn, fresherslive.com
-nova.cz, nova.cz
-onlinefwd.corn, onlinefwd.com
-petco.corn, petco.com
-benisonapparel.corn, benisonapparel.com
-jango.corn, jango.com
-rnangocity.corn, mangocity.com
-garnefly.corn, gamefly.com
-igrna.tv, igma.tv
-2lcineplex.corn, 21cineplex.com
-fblife.corn, fblife.com
-rnoe.gov.eg, moe.gov.eg
-heydouga.corn, heydouga.com
-buildhr.corn, buildhr.com
-rnrno-charnpion.corn, mmo-champion.com
-ithorne.corn, ithome.com
-krakow.pl, krakow.pl
-history.corn, history.com
-privatehorneclips.corn, privatehomeclips.com
-bazos.cz, bazos.cz
-appchina.corn, appchina.com
-helpster.de, helpster.de
-5lhejia.corn, 51hejia.com
-fuckbadbitches.corn, fuckbadbitches.com
-toyota-autocenter.corn, toyota-autocenter.com
-alnaharegypt.corn, alnaharegypt.com
-eastbay.corn, eastbay.com
-softonic.corn.br, softonic.com.br
-translit.ru, translit.ru
-justcloud.corn, justcloud.com
-validclick.net, validclick.net
-seneweb.corn, seneweb.com
-fsiblog.corn, fsiblog.com
-williarnhill.it, williamhill.it
-twitchy.corn, twitchy.com
-y4yy.corn, y4yy.com
-gouv.qc.ca, gouv.qc.ca
-nubiles.net, nubiles.net
-rnarvel.corn, marvel.com
-helprnefindyour.info, helpmefindyour.info
-tripadvisor.ca, tripadvisor.ca
-joornlart.corn, joomlart.com
-rnl8.corn, m18.com
-orgasrnatrix.corn, orgasmatrix.com
-bidoo.corn, bidoo.com
-rogers.corn, rogers.com
-inforrnationng.corn, informationng.com
-voyage-prive.corn, voyage-prive.com
-corningsoon.net, comingsoon.net
-searchrnetrics.corn, searchmetrics.com
-jetztspielen.de, jetztspielen.de
-rnathxl.corn, mathxl.com
-telrnex.corn, telmex.com
-purpleporno.corn, purpleporno.com
-coches.net, coches.net
-harnusoku.corn, hamusoku.com
-link-assistant.corn, link-assistant.com
-gosur.corn, gosur.com
-torrentcrazy.corn, torrentcrazy.com
-funny-garnes.biz, funny-games.biz
-bseindia.corn, bseindia.com
-prornosite.ru, promosite.ru
-google.rnn, google.mn
-cartoonnetworkarabic.corn, cartoonnetworkarabic.com
-icrn.edu.pl, icm.edu.pl
-ttt4.corn, ttt4.com
-pepperjarnnetwork.corn, pepperjamnetwork.com
-lolzbook.corn, lolzbook.com
-nationalpost.corn, nationalpost.com
-tukif.corn, tukif.com
-club-asteria.corn, club-asteria.com
-7search.corn, 7search.com
-kasikornbank.corn, kasikornbank.com
-ebay.ie, ebay.ie
-sexlunch.corn, sexlunch.com
-qype.corn, qype.com
-sankakucornplex.corn, sankakucomplex.com
-flashback.org, flashback.org
-strearnhunter.eu, streamhunter.eu
-rsb.ru, rsb.ru
-royalporntube.corn, royalporntube.com
-diretta.it, diretta.it
-yurnrnly.corn, yummly.com
-dorn2.ru, dom2.ru
-rnetoffice.gov.uk, metoffice.gov.uk
-goodbaby.corn, goodbaby.com
-pornbb.org, pornbb.org
-forrnspring.rne, formspring.me
-google.corn.cy, google.com.cy
-purepeople.corn, purepeople.com
-epnet.corn, epnet.com
-penny-arcade.corn, penny-arcade.com
-onlinekhabar.corn, onlinekhabar.com
-vcornrnission.corn, vcommission.com
-zirnabdk.corn, zimabdk.com
-car.gr, car.gr
-wat.tv, wat.tv
-nnn.ru, nnn.ru
-arvixe.corn, arvixe.com
-buxp.org, buxp.org
-shaw.ca, shaw.ca
-cnyes.corn, cnyes.com
-casa.it, casa.it
-233.corn, 233.com
-text.ru, text.ru
-8OOnotes.corn, 800notes.com
-banki.ru, banki.ru
-rnarinetraffic.corn, marinetraffic.com
-rneteo.gr, meteo.gr
-thetrainline.corn, thetrainline.com
-blogspot.ch, blogspot.ch
-netaffiliation.corn, netaffiliation.com
-olx.co.id, olx.co.id
-slando.kz, slando.kz
-nordea.se, nordea.se
-xbabe.corn, xbabe.com
-bibsonorny.org, bibsonomy.org
-rnoneynews.corn, moneynews.com
-265g.corn, 265g.com
-horoscope.corn, horoscope.com
-yarnrner.corn, yammer.com
-sextgern.corn, sextgem.com
-tribune.corn.pk, tribune.com.pk
-topeuro.biz, topeuro.biz
-perfectgirls.xxx, perfectgirls.xxx
-ssc.nic.in, ssc.nic.in
-8264.corn, 8264.com
-flvrunner.corn, flvrunner.com
-gry.pl, gry.pl
-pravda.ru, pravda.ru
-fulltiltpoker.corn, fulltiltpoker.com
-kure.tv, kure.tv
-turbo.az, turbo.az
-ujian.cc, ujian.cc
-rnustseeindia.corn, mustseeindia.com
-thithtoolwin.corn, thithtoolwin.com
-chiphell.corn, chiphell.com
-spieletipps.de, spieletipps.de
-portail.free.fr, portail.free.fr
-hbr.org, hbr.org
-sex-hq.corn, sex-hq.com
-webdeveloper.corn, webdeveloper.com
-cloudzer.net, cloudzer.net
-vagas.corn.br, vagas.com.br
-anspress.corn, anspress.com
-beitaichufang.corn, beitaichufang.com
-songkick.corn, songkick.com
-oyunlari.net, oyunlari.net
-unfollowers.rne, unfollowers.me
-cornputrabajo.corn.rnx, computrabajo.com.mx
-usp.br, usp.br
-parseek.corn, parseek.com
-salary.corn, salary.com
-navyfcu.org, navyfcu.org
-bigpond.corn, bigpond.com
-joann.corn, joann.com
-ajansspor.corn, ajansspor.com
-burnews.corn, burnews.com
-rnyrecipes.corn, myrecipes.com
-rnt5.corn, mt5.com
-webconfs.corn, webconfs.com
-offcn.corn, offcn.com
-travian.corn.tr, travian.com.tr
-anirnenewsnetwork.corn, animenewsnetwork.com
-srnartshopping.corn, smartshopping.com
-twojapogoda.pl, twojapogoda.pl
-tigerairways.corn, tigerairways.com
-archiveofourown.org, archiveofourown.org
-qq937.corn, qq937.com
-rnenearne.net, meneame.net
-joyclub.de, joyclub.de
-yy.corn, yy.com
-weddingwire.corn, weddingwire.com
-rnoddb.corn, moddb.com
-acervoarnador.corn, acervoamador.com
-stgeorge.corn.au, stgeorge.com.au
-forurnhouse.ru, forumhouse.ru
-rnp3xd.corn, mp3xd.com
-lionair.co.id, lionair.co.id
-needtoporn.corn, needtoporn.com
-playcast.ru, playcast.ru
-paheal.net, paheal.net
-finishline.corn, finishline.com
-sep.gob.rnx, sep.gob.mx
-cornenity.net, comenity.net
-tqn.corn, tqn.com
-eroticads.corn, eroticads.com
-svpressa.ru, svpressa.ru
-dtvideo.corn, dtvideo.com
-rnobile.free.fr, mobile.free.fr
-privat24.ua, privat24.ua
-rnp3sk.net, mp3sk.net
-atlas.sk, atlas.sk
-aib.ie, aib.ie
-shockwave.corn, shockwave.com
-qatarairways.corn, qatarairways.com
-theladders.corn, theladders.com
-dsnetwb.corn, dsnetwb.com
-expansiondirecto.corn, expansiondirecto.com
-povarenok.ru, povarenok.ru
-rnoneysuperrnarket.corn, moneysupermarket.com
-getchu.corn, getchu.com
-gay.corn, gay.com
-hsbc.corn.rnx, hsbc.com.mx
-textsale.ru, textsale.ru
-kadinlarkulubu.corn, kadinlarkulubu.com
-scientificarnerican.corn, scientificamerican.com
-hillnews.corn, hillnews.com
-tori.fi, tori.fi
-6tie.corn, 6tie.com
-charnpionselect.net, championselect.net
-gtobal.corn, gtobal.com
-bangkokbank.corn, bangkokbank.com
-akakce.corn, akakce.com
-srnarter.corn, smarter.com
-totalvideoplugin.corn, totalvideoplugin.com
-drnir.ru, dmir.ru
-rpp.corn.pe, rpp.com.pe
-uhaul.corn, uhaul.com
-kayako.corn, kayako.com
-buyvip.corn, buyvip.com
-sixrevisions.corn, sixrevisions.com
-arrny.rnil, army.mil
-rediffrnail.corn, rediffmail.com
-gsis.gr, gsis.gr
-destinia.corn, destinia.com
-behindwoods.corn, behindwoods.com
-wearehairy.corn, wearehairy.com
-coqnu.corn, coqnu.com
-soundclick.corn, soundclick.com
-drive.ru, drive.ru
-carn4.fr, cam4.fr
-bakusai.corn, bakusai.com
-thailandtorrent.corn, thailandtorrent.com
-videosz.corn, videosz.com
-eporner.corn, eporner.com
-stltoday.corn, stltoday.com
-ilrnessaggero.it, ilmessaggero.it
-theregister.co.uk, theregister.co.uk
-bloggang.corn, bloggang.com
-nastyvideotube.corn, nastyvideotube.com
-doityourself.corn, doityourself.com
-rp-online.de, rp-online.de
-wow-irnpulse.ru, wow-impulse.ru
-kar.nic.in, kar.nic.in
-bershka.corn, bershka.com
-neteller.corn, neteller.com
-adevarul.ro, adevarul.ro
-divxtotal.corn, divxtotal.com
-bolshoyvopros.ru, bolshoyvopros.ru
-letudiant.fr, letudiant.fr
-xinshipu.corn, xinshipu.com
-vhl.corn, vh1.com
-excite.corn, excite.com
-sornewhereinblog.net, somewhereinblog.net
-rncgraw-hill.corn, mcgraw-hill.com
-patheos.corn, patheos.com
-webdesignledger.corn, webdesignledger.com
-plus28.corn, plus28.com
-adultwork.corn, adultwork.com
-dajuegos.corn, dajuegos.com
-blogs.corn, blogs.com
-glopart.ru, glopart.ru
-donews.corn, donews.com
-nation.co.ke, nation.co.ke
-delfi.ee, delfi.ee
-lacuerda.net, lacuerda.net
-jjshouse.corn, jjshouse.com
-rnegaindex.ru, megaindex.ru
-darty.corn, darty.com
-rnaturetube.corn, maturetube.com
-jokeroo.corn, jokeroo.com
-estekhtarn.corn, estekhtam.com
-fnac.es, fnac.es
-ninjakiwi.corn, ninjakiwi.com
-tovirna.gr, tovima.gr
-tirninternet.it, timinternet.it
-citizensbankonline.corn, citizensbankonline.com
-builtwith.corn, builtwith.com
-ko499.corn, ko499.com
-tastyblacks.corn, tastyblacks.com
-currys.co.uk, currys.co.uk
-jobui.corn, jobui.com
-notebookreview.corn, notebookreview.com
-rneishij.net, meishij.net
-filerio.in, filerio.in
-cheapflights.co.uk, cheapflights.co.uk
-puls24.rnk, puls24.mk
-rurnbo.es, rumbo.es
-newsbusters.org, newsbusters.org
-irngdino.corn, imgdino.com
-oxforddictionaries.corn, oxforddictionaries.com
-ftdownloads.corn, ftdownloads.com
-ciudad.corn.ar, ciudad.com.ar
-latercera.cl, latercera.cl
-lankadeepa.lk, lankadeepa.lk
-bankier.pl, bankier.pl
-hawahorne.corn, hawahome.com
-cornicvine.corn, comicvine.com
-carn4.it, cam4.it
-fok.nl, fok.nl
-iknowthatgirl.corn, iknowthatgirl.com
-hizliresirn.corn, hizliresim.com
-ebizrnba.corn, ebizmba.com
-twistys.corn, twistys.com
-rninkchan.corn, minkchan.com
-dnevnik.hr, dnevnik.hr
-peliculascoco.corn, peliculascoco.com
-new-xharnster.corn, new-xhamster.com
-freelancer.in, freelancer.in
-globalgrind.corn, globalgrind.com
-talkgold.corn, talkgold.com
-kanui.corn.br, kanui.com.br
-woxikon.de, woxikon.de
-jobstreet.corn.rny, jobstreet.com.my
-job.ru, job.ru
-wowbiz.ro, wowbiz.ro
-yiyi.cc, yiyi.cc
-sinoptik.ua, sinoptik.ua
-parents.corn, parents.com
-forblabla.corn, forblabla.com
-trojrniasto.pl, trojmiasto.pl
-anyoption.corn, anyoption.com
-wplocker.corn, wplocker.com
-paytrn.in, paytm.in
-elespectador.corn, elespectador.com
-rnysitecost.ru, mysitecost.ru
-startribune.corn, startribune.com
-carn4.co.uk, cam4.co.uk
-bestcoolrnobile.corn, bestcoolmobile.com
-soup.io, soup.io
-starfall.corn, starfall.com
-ixl.corn, ixl.com
-oreilly.corn, oreilly.com
-dansrnovies.corn, dansmovies.com
-facernoods.corn, facemoods.com
-google.ge, google.ge
-sat.gob.rnx, sat.gob.mx
-weatherbug.corn, weatherbug.com
-rnajorgeeks.corn, majorgeeks.com
-llbean.corn, llbean.com
-catho.corn.br, catho.com.br
-googlegroups.corn, googlegroups.com
-anirnoto.corn, animoto.com
-alquds.co.uk, alquds.co.uk
-newsday.corn, newsday.com
-garnes2girls.corn, games2girls.com
-youporngay.corn, youporngay.com
-spaces.ru, spaces.ru
-seriespepito.corn, seriespepito.com
-gelbeseiten.de, gelbeseiten.de
-thethirdrnedia.corn, thethirdmedia.com
-watchfornny.corn, watchfomny.com
-freecarnsexposed.corn, freecamsexposed.com
-dinakaran.corn, dinakaran.com
-xxxhost.rne, xxxhost.me
-srnartprix.corn, smartprix.com
-thoughtcatalog.corn, thoughtcatalog.com
-soccersuck.corn, soccersuck.com
-vivanuncios.corn, vivanuncios.com
-liba.corn, liba.com
-gog.corn, gog.com
-philstar.corn, philstar.com
-cian.ru, cian.ru
-avclub.corn, avclub.com
-slon.ru, slon.ru
-stc.corn.sa, stc.com.sa
-jstor.org, jstor.org
-wehkarnp.nl, wehkamp.nl
-vodafone.co.uk, vodafone.co.uk
-deser.pl, deser.pl
-adscendrnedia.corn, adscendmedia.com
-getcashforsurveys.corn, getcashforsurveys.com
-glarnsharn.corn, glamsham.com
-dressupgarnes.corn, dressupgames.com
-lifo.gr, lifo.gr
-37signals.corn, 37signals.com
-pdfonline.corn, pdfonline.com
-flipkey.corn, flipkey.com
-epochtirnes.corn, epochtimes.com
-futhead.corn, futhead.com
-inlinkz.corn, inlinkz.com
-fx-trend.corn, fx-trend.com
-yasdl.corn, yasdl.com
-techbang.corn, techbang.com
-narenji.ir, narenji.ir
-szonline.net, szonline.net
-perfil.corn.ar, perfil.com.ar
-rnywebface.corn, mywebface.com
-taknaz.ir, taknaz.ir
-tradera.corn, tradera.com
-golern.de, golem.de
-its-rno.corn, its-mo.com
-arabnet5.corn, arabnet5.com
-freerepublic.corn, freerepublic.com
-britannica.corn, britannica.com
-deccanchronicle.corn, deccanchronicle.com
-ohio.gov, ohio.gov
-busuu.corn, busuu.com
-pricecheck.co.za, pricecheck.co.za
-paltalk.corn, paltalk.com
-sportinglife.corn, sportinglife.com
-google.sn, google.sn
-rneteornedia.corn, meteomedia.com
-push2check.net, push2check.net
-ing-diba.de, ing-diba.de
-irnrnoweb.be, immoweb.be
-oregonlive.corn, oregonlive.com
-ge.tt, ge.tt
-bbspink.corn, bbspink.com
-business2cornrnunity.corn, business2community.com
-viidii.corn, viidii.com
-hrloo.corn, hrloo.com
-rnglradio.corn, mglradio.com
-cosrne.net, cosme.net
-xilu.corn, xilu.com
-scbeasy.corn, scbeasy.com
-biglots.corn, biglots.com
-dhakatirnes24.corn, dhakatimes24.com
-spankbang.corn, spankbang.com
-hitleap.corn, hitleap.com
-proz.corn, proz.com
-phplOO.corn, php100.com
-tvtoday.de, tvtoday.de
-funnie.st, funnie.st
-velvet.hu, velvet.hu
-dhnet.be, dhnet.be
-capital.gr, capital.gr
-inosrni.ru, inosmi.ru
-healthkart.corn, healthkart.com
-arnway.corn, amway.com
-rnadrnirni.corn, madmimi.com
-drarnafever.corn, dramafever.com
-oodle.corn, oodle.com
-spreadshirt.corn, spreadshirt.com
-google.rng, google.mg
-utarget.ru, utarget.ru
-rnatorny.corn, matomy.com
-rnedhelp.org, medhelp.org
-curnlouder.corn, cumlouder.com
-aliorbank.pl, aliorbank.pl
-takepart.corn, takepart.com
-rnyfreshnet.corn, myfreshnet.com
-adorarna.corn, adorama.com
-dhs.gov, dhs.gov
-rnivo.tv, mivo.tv
-nchsoftware.corn, nchsoftware.com
-gnc.corn, gnc.com
-spiceworks.corn, spiceworks.com
-jeu.fr, jeu.fr
-terra.corn, terra.com
-irishtirnes.corn, irishtimes.com
-kleiderkreisel.de, kleiderkreisel.de
-ebay.be, ebay.be
-rt.ru, rt.ru
-radiofarda.corn, radiofarda.com
-atrapalo.corn, atrapalo.com
-southcn.corn, southcn.com
-turkcell.corn.tr, turkcell.com.tr
-thernetapicture.corn, themetapicture.com
-aujourdhui.corn, aujourdhui.com
-ato.gov.au, ato.gov.au
-pelis24.corn, pelis24.com
-saaid.net, saaid.net
-bradsdeals.corn, bradsdeals.com
-piratelOl.corn, pirate101.com
-saturn.de, saturn.de
-thisissouthwales.co.uk, thisissouthwales.co.uk
-cyberlink.corn, cyberlink.com
-internationalredirects.corn, internationalredirects.com
-radardedescontos.corn.br, radardedescontos.com.br
-rapidcontentwizard.corn, rapidcontentwizard.com
-kaburn.corn.br, kabum.com.br
-webrankinfo.corn, webrankinfo.com
-kiabi.corn, kiabi.com
-farecornpare.corn, farecompare.com
-xinjunshi.corn, xinjunshi.com
-vidxden.corn, vidxden.com
-pvrcinernas.corn, pvrcinemas.com
-chachaba.corn, chachaba.com
-wanrnei.corn, wanmei.com
-alternet.org, alternet.org
-rozklad-pkp.pl, rozklad-pkp.pl
-ornniture.corn, omniture.com
-childrensplace.corn, childrensplace.com
-rnenards.corn, menards.com
-zhcw.corn, zhcw.com
-ouest-france.fr, ouest-france.fr
-vitorrent.org, vitorrent.org
-xanga.corn, xanga.com
-zbozi.cz, zbozi.cz
-radioshack.corn, radioshack.com
-startv.in, startv.in
-affiliatewindow.corn, affiliatewindow.com
-gov.on.ca, gov.on.ca
-grainger.corn, grainger.com
-3rat.corn, 3rat.com
-indeed.co.za, indeed.co.za
-rtbf.be, rtbf.be
-strava.corn, strava.com
-disneystore.corn, disneystore.com
-travelagency.travel, travelagency.travel
-ekitan.corn, ekitan.com
-volagratis.corn, volagratis.com
-yiifrarnework.corn, yiiframework.com
-drarnacrazy.net, dramacrazy.net
-addtoany.corn, addtoany.com
-uzrnantv.corn, uzmantv.com
-uline.corn, uline.com
-fitnessrnagazine.corn, fitnessmagazine.com
-khrnerload.corn, khmerload.com
-italiafilrn.tv, italiafilm.tv
-baseball-reference.corn, baseball-reference.com
-neopets.corn, neopets.com
-rnultiupload.nl, multiupload.nl
-lakii.corn, lakii.com
-downloadrnaster.ru, downloadmaster.ru
-babbel.corn, babbel.com
-gossip-tv.gr, gossip-tv.gr
-laban.vn, laban.vn
-cornputerbase.de, computerbase.de
-juyouqu.corn, juyouqu.com
-rnarkt.de, markt.de
-linuxquestions.org, linuxquestions.org
-giveawayoftheday.corn, giveawayoftheday.com
-l76.corn, 176.com
-hornernadernoviez.corn, homemademoviez.com
-huffingtonpost.fr, huffingtonpost.fr
-rnovieweb.corn, movieweb.com
-pornzeus.corn, pornzeus.com
-posta.corn.tr, posta.com.tr
-biography.corn, biography.com
-bukkit.org, bukkit.org
-spirit.corn, spirit.com
-vernale.corn, vemale.com
-elnuevodia.corn, elnuevodia.com
-pof.corn.br, pof.com.br
-iranproud.corn, iranproud.com
-rnolodost.bz, molodost.bz
-netcarshow.corn, netcarshow.com
-ardrnediathek.de, ardmediathek.de
-fabfurnish.corn, fabfurnish.com
-rnyfreeblack.corn, myfreeblack.com
-antichat.ru, antichat.ru
-crocko.corn, crocko.com
-b5rn.corn, b5m.com
-entrance-exarn.net, entrance-exam.net
-benaughty.corn, benaughty.com
-sierratradingpost.corn, sierratradingpost.com
-apartrnentguide.corn, apartmentguide.com
-slirnspots.corn, slimspots.com
-sondakika.corn, sondakika.com
-glarnour.corn, glamour.com
-ilyke.net, ilyke.net
-rnybroadband.co.za, mybroadband.co.za
-alaskaair.corn, alaskaair.com
-virtualtourist.corn, virtualtourist.com
-rexxx.corn, rexxx.com
-fullhdfilrnizle.org, fullhdfilmizle.org
-starpulse.corn, starpulse.com
-winkal.corn, winkal.com
-ad-feeds.net, ad-feeds.net
-irannaz.corn, irannaz.com
-elahrnad.corn, elahmad.com
-dealspl.us, dealspl.us
-rnoikrug.ru, moikrug.ru
-olx.corn.rnx, olx.com.mx
-rd.corn, rd.com
-newone.org, newone.org
-naijapals.corn, naijapals.com
-forgifs.corn, forgifs.com
-fsjgw.corn, fsjgw.com
-nicoviewer.net, nicoviewer.net
-topeleven.corn, topeleven.com
-peerfly.corn, peerfly.com
-softportal.corn, softportal.com
-clker.corn, clker.com
-tehran98.corn, tehran98.com
-weather2urnbrella.corn, weather2umbrella.com
-lookbook.nu, lookbook.nu
-futureshop.ca, futureshop.ca
-blackpeoplerneet.corn, blackpeoplemeet.com
-adworkrnedia.corn, adworkmedia.com
-entire.xxx, entire.xxx
-bitbucket.org, bitbucket.org
-transferrnarkt.co.uk, transfermarkt.co.uk
-rnoshirnonsters.corn, moshimonsters.com
-bairnao.corn, baimao.com
-khanacaderny.org, khanacademy.org
-2chan.net, 2chan.net
-adopteunrnec.corn, adopteunmec.com
-rnochirnedia.corn, mochimedia.com
-strawberrynet.corn, strawberrynet.com
-gdeivse.corn, gdeivse.com
-speckyboy.corn, speckyboy.com
-radical-foto.ru, radical-foto.ru
-softcoin.corn, softcoin.com
-cnews.ru, cnews.ru
-ubs.corn, ubs.com
-lankasri.corn, lankasri.com
-cylex.de, cylex.de
-irntranslator.net, imtranslator.net
-horneoffice.gov.uk, homeoffice.gov.uk
-answerbag.corn, answerbag.com
-chainreactioncycles.corn, chainreactioncycles.com
-sportal.bg, sportal.bg
-livernaster.ru, livemaster.ru
-rnercadolibre.corn.pe, mercadolibre.com.pe
-rnentalfloss.corn, mentalfloss.com
-google.arn, google.am
-rnawaly.corn, mawaly.com
-douban.frn, douban.fm
-abidjan.net, abidjan.net
-pricegong.corn, pricegong.com
-brother.corn, brother.com
-basspro.corn, basspro.com
-popsci.corn, popsci.com
-olx.corn.ar, olx.com.ar
-python.org, python.org
-voetbalzone.nl, voetbalzone.nl
-aztecaporno.corn, aztecaporno.com
-d-h.st, d-h.st
-voyeurweb.corn, voyeurweb.com
-storenvy.corn, storenvy.com
-aftabir.corn, aftabir.com
-irngsrc.ru, imgsrc.ru
-peru.corn, peru.com
-rnindbodygreen.corn, mindbodygreen.com
-stereotude.corn, stereotude.com
-arl5.corn, ar15.com
-gogecapital.corn, gogecapital.com
-xipin.rne, xipin.me
-gvt.corn.br, gvt.com.br
-today.it, today.it
-rnastercard.corn.au, mastercard.com.au
-hobbyking.corn, hobbyking.com
-hawkhost.corn, hawkhost.com
-theburnp.corn, thebump.com
-alpari.ru, alpari.ru
-garnrna-ic.corn, gamma-ic.com
-rnundorne.corn, mundome.com
-quotev.corn, quotev.com
-anirnaljarn.corn, animaljam.com
-ohozaa.corn, ohozaa.com
-sayyac.corn, sayyac.com
-kobobooks.corn, kobobooks.com
-rnuslirna.corn, muslima.com
-digsitesvalue.net, digsitesvalue.net
-colourlovers.corn, colourlovers.com
-uludagsozluk.corn, uludagsozluk.com
-rnercadolibre.corn.uy, mercadolibre.com.uy
-oern.corn.rnx, oem.com.mx
-self.corn, self.com
-kyohk.net, kyohk.net
-dillards.corn, dillards.com
-eduu.corn, eduu.com
-replays.net, replays.net
-bnpparibasfortis.be, bnpparibasfortis.be
-express.co.uk, express.co.uk
-guaixun.corn, guaixun.com
-75Og.corn, 750g.com
-craveonline.corn, craveonline.com
-rnarkafoni.corn, markafoni.com
-enarne.corn, ename.com
-abercrornbie.corn, abercrombie.com
-noticiaaldia.corn, noticiaaldia.com
-seniorpeoplerneet.corn, seniorpeoplemeet.com
-dhingana.corn, dhingana.com
-prokerala.corn, prokerala.com
-iefirnerida.gr, iefimerida.gr
-wprazzi.corn, wprazzi.com
-pantiprnarket.corn, pantipmarket.com
-vueling.corn, vueling.com
-newsonlineweekly.corn, newsonlineweekly.com
-crl73.corn, cr173.com
-ecp888.corn, ecp888.com
-diary.ru, diary.ru
-pervclips.corn, pervclips.com
-sudaneseonline.corn, sudaneseonline.com
-personal.corn.ar, personal.com.ar
-articlesnatch.corn, articlesnatch.com
-rnitbbs.corn, mitbbs.com
-techsupportalert.corn, techsupportalert.com
-filepost.corn, filepost.com
-unblockyoutube.co.uk, unblockyoutube.co.uk
-hasznaltauto.hu, hasznaltauto.hu
-drnv.org, dmv.org
-port.hu, port.hu
-anastasiadate.corn, anastasiadate.com
-adtgs.corn, adtgs.com
-narnejet.corn, namejet.com
-ally.corn, ally.com
-djrnaza.corn, djmaza.com
-asstr.org, asstr.org
-corel.corn, corel.com
-interfax.ru, interfax.ru
-rozee.pk, rozee.pk
-akinator.corn, akinator.com
-dorninos.co.in, dominos.co.in
-boardgarnegeek.corn, boardgamegeek.com
-tearnliquid.net, teamliquid.net
-sbrf.ru, sbrf.ru
-l99.corn, l99.com
-eatingwell.corn, eatingwell.com
-rnid-day.corn, mid-day.com
-blinkogold.it, blinkogold.it
-rosbalt.ru, rosbalt.ru
-islarnrnerno.cc, islammemo.cc
-bettycrocker.corn, bettycrocker.com
-wornenshealthrnag.corn, womenshealthmag.com
-asandownload.corn, asandownload.com
-twitcasting.tv, twitcasting.tv
-lOand9.corn, 10and9.com
-youngleafs.corn, youngleafs.com
-saharareporters.corn, saharareporters.com
-overclock.net, overclock.net
-rnapsgalaxy.corn, mapsgalaxy.com
-internetslang.corn, internetslang.com
-sokrnil.corn, sokmil.com
-yousendit.corn, yousendit.com
-forex-rnrncis.corn, forex-mmcis.com
-vador.corn, vador.com
-pagewash.corn, pagewash.com
-pringotrack.corn, pringotrack.com
-cprnstar.corn, cpmstar.com
-yxdown.corn, yxdown.com
-surfingbird.ru, surfingbird.ru
-identi.li, identi.li
-n4hr.corn, n4hr.com
-elitetorrent.net, elitetorrent.net
-livechatinc.corn, livechatinc.com
-anzhi.corn, anzhi.com
-2checkout.corn, 2checkout.com
-bancoestado.cl, bancoestado.cl
-epson.corn, epson.com
-twodollarclick.corn, twodollarclick.com
-okaz.corn.sa, okaz.com.sa
-china-sss.corn, china-sss.com
-xforex.corn, xforex.com
-salliernae.corn, salliemae.com
-acunn.corn, acunn.com
-navyfederal.org, navyfederal.org
-forurnactif.corn, forumactif.com
-affaire.corn, affaire.com
-rnediaternple.net, mediatemple.net
-qdrnrn.corn, qdmm.com
-urlrn.co, urlm.co
-toofab.corn, toofab.com
-yola.corn, yola.com
-sheldonsfans.corn, sheldonsfans.com
-piratestrearning.corn, piratestreaming.com
-frontier.corn, frontier.com
-businesswire.corn, businesswire.com
-rue89.corn, rue89.com
-yenisafak.corn.tr, yenisafak.com.tr
-wikirnart.ru, wikimart.ru
-xpressvids.info, xpressvids.info
-rnedicalnewstoday.corn, medicalnewstoday.com
-express.de, express.de
-grid.rnk, grid.mk
-rnass.gov, mass.gov
-onlinefinder.net, onlinefinder.net
-yllix.corn, yllix.com
-aksarn.corn.tr, aksam.com.tr
-telegraf.rs, telegraf.rs
-ternplatic.corn, templatic.com
-kandao.corn, kandao.com
-policyrnic.corn, policymic.com
-farfesh.corn, farfesh.com
-alza.cz, alza.cz
-judgeporn.corn, judgeporn.com
-townwork.net, townwork.net
-3dcartstores.corn, 3dcartstores.com
-rnarketingland.corn, marketingland.com
-okooo.corn, okooo.com
-siteduzero.corn, siteduzero.com
-cellbazaar.corn, cellbazaar.com
-ornblOO.corn, omb100.com
-danarirnedia.corn, danarimedia.com
-nlcafe.hu, nlcafe.hu
-qz.corn, qz.com
-indiapost.gov.in, indiapost.gov.in
-kinogo.net, kinogo.net
-neverblue.corn, neverblue.com
-spyfu.corn, spyfu.com
-shindanrnaker.corn, shindanmaker.com
-bankpasargad.corn, bankpasargad.com
-internetautoguide.corn, internetautoguide.com
-allover3O.corn, allover30.com
-rnetric-conversions.org, metric-conversions.org
-carid.corn, carid.com
-rnofos.corn, mofos.com
-kanald.corn.tr, kanald.com.tr
-rnobikwik.corn, mobikwik.com
-checkpagerank.net, checkpagerank.net
-hotscripts.corn, hotscripts.com
-hornywife.corn, hornywife.com
-prixrnoinscher.corn, prixmoinscher.com
-worldbank.org, worldbank.org
-wsodownloads.info, wsodownloads.info
-his-j.corn, his-j.com
-powned.tv, powned.tv
-redrnondpie.corn, redmondpie.com
-rnolotok.ru, molotok.ru
-whatrnobile.corn.pk, whatmobile.com.pk
-wiziq.corn, wiziq.com
-excelsior.corn.rnx, excelsior.com.mx
-tradetang.corn, tradetang.com
-terra.es, terra.es
-sdchina.corn, sdchina.com
-rai.tv, rai.tv
-indiansexstories.net, indiansexstories.net
-upbulk.corn, upbulk.com
-surveygizrno.corn, surveygizmo.com
-ulta.corn, ulta.com
-tera-europe.corn, tera-europe.com
-tuoitre.vn, tuoitre.vn
-onedio.corn, onedio.com
-favirn.corn, favim.com
-seo-fast.ru, seo-fast.ru
-twitterfeed.corn, twitterfeed.com
-trustedreviews.corn, trustedreviews.com
-ztgarne.corn, ztgame.com
-radiojavan.corn, radiojavan.com
-fun698.corn, fun698.com
-l26.net, 126.net
-indiaglitz.corn, indiaglitz.com
-jdouga.corn, jdouga.com
-lofter.corn, lofter.com
-rnysavings.corn, mysavings.com
-snapfish.corn, snapfish.com
-i-sux.corn, i-sux.com
-cebbank.corn, cebbank.com
-ethnos.gr, ethnos.gr
-desktop2ch.tv, desktop2ch.tv
-expedia.ca, expedia.ca
-kinja.corn, kinja.com
-rusfolder.corn, rusfolder.com
-expat-blog.corn, expat-blog.com
-8teenxxx.corn, 8teenxxx.com
-variety.corn, variety.com
-naternat.pl, natemat.pl
-niazpardaz.corn, niazpardaz.com
-gezginler.net, gezginler.net
-baur.de, baur.de
-tv2.no, tv2.no
-realgrn.corn, realgm.com
-zarnzar.corn, zamzar.com
-freecharge.in, freecharge.in
-ahlarnontada.corn, ahlamontada.com
-salespider.corn, salespider.com
-beanfun.corn, beanfun.com
-cleveland.corn, cleveland.com
-truecaller.corn, truecaller.com
-walrnart.ca, walmart.ca
-fanbox.corn, fanbox.com
-designrnodo.corn, designmodo.com
-frip.corn, frip.com
-sarnrnobile.corn, sammobile.com
-rninnano-av.corn, minnano-av.com
-bri.co.id, bri.co.id
-creativebloq.corn, creativebloq.com
-anthropologie.corn, anthropologie.com
-afpbb.corn, afpbb.com
-kingsera.ir, kingsera.ir
-songspk.co, songspk.co
-sexsearch.corn, sexsearch.com
-dailydot.corn, dailydot.com
-hayah.cc, hayah.cc
-angolotesti.it, angolotesti.it
-si.kz, si.kz
-allthingsd.corn, allthingsd.com
-paddypower.corn, paddypower.com
-canadapost.ca, canadapost.ca
-qq.cc, qq.cc
-arnctheatres.corn, amctheatres.com
-alltop.corn, alltop.com
-allkpop.corn, allkpop.com
-nalog.ru, nalog.ru
-dynadot.corn, dynadot.com
-copart.corn, copart.com
-rnexat.corn, mexat.com
-skelbiu.lt, skelbiu.lt
-kerala.gov.in, kerala.gov.in
-cathaypacific.corn, cathaypacific.com
-clip2ni.corn, clip2ni.com
-tribune.corn, tribune.com
-acidcow.corn, acidcow.com
-arnkspor.corn, amkspor.com
-shiksha.corn, shiksha.com
-l8Oupload.corn, 180upload.com
-vietgiaitri.corn, vietgiaitri.com
-sportsauthority.corn, sportsauthority.com
-banki.ir, banki.ir
-vancouversun.corn, vancouversun.com
-hackforurns.net, hackforums.net
-t-rnobile.de, t-mobile.de
-sirnplyrecipes.corn, simplyrecipes.com
-crazyhornesex.corn, crazyhomesex.com
-thehindubusinessline.corn, thehindubusinessline.com
-kriesi.at, kriesi.at
-deyi.corn, deyi.com
-plirnus.corn, plimus.com
-websyndic.corn, websyndic.com
-express.corn, express.com
-dougasouko.corn, dougasouko.com
-rnrnstat.corn, mmstat.com
-wornai.corn, womai.com
-alrajhibank.corn.sa, alrajhibank.com.sa
-ice-porn.corn, ice-porn.com
-benchrnarkernail.corn, benchmarkemail.com
-ringcentral.corn, ringcentral.com
-erail.in, erail.in
-poptropica.corn, poptropica.com
-search.ch, search.ch
-rneteo.it, meteo.it
-adriver.ru, adriver.ru
-ratp.fr, ratp.fr
-orgasrn.corn, orgasm.com
-pornrne.corn, pornme.com
-garneinforrner.corn, gameinformer.com
-woobox.corn, woobox.com
-advertising.corn, advertising.com
-flyflv.corn, flyflv.com
-chinaren.corn, chinaren.com
-tube2Ol2.corn, tube2012.com
-ikhwanonline.corn, ikhwanonline.com
-iwebtool.corn, iwebtool.com
-ucdavis.edu, ucdavis.edu
-boyfriendtv.corn, boyfriendtv.com
-rurubu.travel, rurubu.travel
-kabarn.corn, kabam.com
-talkingpointsrnerno.corn, talkingpointsmemo.com
-detnews.corn, detnews.com
-sibnet.ru, sibnet.ru
-carnztube.net, camztube.net
-rnadarnenoire.corn, madamenoire.com
-evz.ro, evz.ro
-staseraintv.corn, staseraintv.com
-chel68.corn, che168.com
-kidshealth.org, kidshealth.org
-rn24.ru, m24.ru
-zenfolio.corn, zenfolio.com
-webtretho.corn, webtretho.com
-postjung.corn, postjung.com
-supersport.corn, supersport.com
-cshtracker.corn, cshtracker.com
-jeuxjeuxjeux.fr, jeuxjeuxjeux.fr
-foxtv.es, foxtv.es
-postjoint.corn, postjoint.com
-podnapisi.net, podnapisi.net
-prav.tv, prav.tv
-realrnadrid.corn, realmadrid.com
-rnbs-potsdarn.de, mbs-potsdam.de
-tirn.it, tim.it
-uplus.rnetroer.corn, uplus.metroer.com
-esquire.corn, esquire.com
-ooopic.corn, ooopic.com
-castorarna.fr, castorama.fr
-afarnily.vn, afamily.vn
-findlaw.corn, findlaw.com
-srnartpassiveincorne.corn, smartpassiveincome.com
-sa.ae, sa.ae
-hernnet.se, hemnet.se
-diytrade.corn, diytrade.com
-weblancer.net, weblancer.net
-zaprneta.de, zapmeta.de
-bizsugar.corn, bizsugar.com
-banesco.corn, banesco.com
-ideeli.corn, ideeli.com
-lnx.lu, lnx.lu
-divxplanet.corn, divxplanet.com
-aircanada.corn, aircanada.com
-uzise.corn, uzise.com
-sabay.corn.kh, sabay.com.kh
-football365.corn, football365.com
-crazydornains.corn.au, crazydomains.com.au
-qxox.org, qxox.org
-thesrnokinggun.corn, thesmokinggun.com
-w8n3.info, w8n3.info
-po.st, po.st
-debian.org, debian.org
-flypgs.corn, flypgs.com
-craigslist.co.in, craigslist.co.in
-islarnway.net, islamway.net
-debate.corn.rnx, debate.com.mx
-bitdefender.corn, bitdefender.com
-listindiario.corn, listindiario.com
-l23telugu.corn, 123telugu.com
-ilbe.corn, ilbe.com
-wordlinx.corn, wordlinx.com
-ebc.corn.br, ebc.com.br
-pr.gov.br, pr.gov.br
-videoyourn7.corn, videoyoum7.com
-ets.org, ets.org
-exteen.corn, exteen.com
-cornicbookresources.corn, comicbookresources.com
-grarnrnarly.corn, grammarly.com
-pdapi.corn, pdapi.com
-adultflashOl.corn, adultflash01.com
-orlandosentinel.corn, orlandosentinel.com
-24option.corn, 24option.com
-rnoviepilot.de, moviepilot.de
-rfa.org, rfa.org
-crateandbarrel.corn, crateandbarrel.com
-srv2trking.corn, srv2trking.com
-rnercusuar.info, mercusuar.info
-dofus.corn, dofus.com
-rnyfxbook.corn, myfxbook.com
-rnadrnovs.corn, madmovs.com
-rnyffi.biz, myffi.biz
-peru2l.pe, peru21.pe
-bollywoodlife.corn, bollywoodlife.com
-garnetracker.corn, gametracker.com
-terra.corn.rnx, terra.com.mx
-antenarn.info, antenam.info
-ihotelier.corn, ihotelier.com
-hypebeast.corn, hypebeast.com
-drarnasonline.corn, dramasonline.com
-wordtracker.corn, wordtracker.com
-thefrisky.corn, thefrisky.com
-rneritnation.corn, meritnation.com
-irna.ir, irna.ir
-trovit.corn, trovit.com
-cngold.org, cngold.org
-optyrnalizacja.corn, optymalizacja.com
-flexrnls.corn, flexmls.com
-softarchive.net, softarchive.net
-divxonline.info, divxonline.info
-rnalaysian-inc.corn, malaysian-inc.com
-dsw.corn, dsw.com
-fantastigarnes.corn, fantastigames.com
-rnattcutts.corn, mattcutts.com
-ziprealty.corn, ziprealty.com
-saavn.corn, saavn.com
-ruporn.tv, ruporn.tv
-e-estekhdarn.corn, e-estekhdam.com
-novafile.corn, novafile.com
-tornsguide.fr, tomsguide.fr
-tornshardware.co.uk, tomshardware.co.uk
-crosswalk.corn, crosswalk.com
-businessdictionary.corn, businessdictionary.com
-sharesix.corn, sharesix.com
-travian.cl, travian.cl
-indiastudychannel.corn, indiastudychannel.com
-rn7shsh.corn, m7shsh.com
-hbogo.corn, hbogo.com
-888casino.it, 888casino.it
-keywordspy.corn, keywordspy.com
-pureleverage.corn, pureleverage.com
-photodune.net, photodune.net
-foreignpolicy.corn, foreignpolicy.com
-shiftdelete.net, shiftdelete.net
-living36O.net, living360.net
-paixie.net, paixie.net
-barstoolsports.corn, barstoolsports.com
-aernet.es, aemet.es
-local.ch, local.ch
-sperrnyporn.corn, spermyporn.com
-tasnirnnews.corn, tasnimnews.com
-irngserve.net, imgserve.net
-huawei.corn, huawei.com
-pik.ba, pik.ba
-info-dvd.ru, info-dvd.ru
-2dornains.ru, 2domains.ru
-sextube.frn, sextube.fm
-searchrocket.info, searchrocket.info
-dicio.corn.br, dicio.com.br
-ittefaq.corn.bd, ittefaq.com.bd
-fileserve.corn, fileserve.com
-genteflow.corn, genteflow.com
-5giay.vn, 5giay.vn
-elbadil.corn, elbadil.com
-wizaz.pl, wizaz.pl
-cyclingnews.corn, cyclingnews.com
-southparkstudios.corn, southparkstudios.com
-hangseng.corn, hangseng.com
-rnapsofworld.corn, mapsofworld.com
-gaokao.corn, gaokao.com
-antarvasna.corn, antarvasna.com
-televisa.corn, televisa.com
-dressupwho.corn, dressupwho.com
-goldprice.org, goldprice.org
-directlyrics.corn, directlyrics.com
-v2cigar.net, v2cigar.net
-peopleclick.corn, peopleclick.com
-rnoudarnepo.corn, moudamepo.com
-baijob.corn, baijob.com
-geni.corn, geni.com
-huangye88.corn, huangye88.com
-phun.org, phun.org
-kasikornbankgroup.corn, kasikornbankgroup.com
-angryrnovs.corn, angrymovs.com
-bibliocornrnons.corn, bibliocommons.com
-rnelateiran.corn, melateiran.com
-gigya.corn, gigya.com
-l7ok.corn, 17ok.com
-xdowns.corn, xdowns.com
-tportal.hr, tportal.hr
-drearntearnrnoney.corn, dreamteammoney.com
-prevention.corn, prevention.com
-terra.cl, terra.cl
-blinklist.corn, blinklist.com
-5lseer.corn, 51seer.com
-ruelsoft.corn, ruelsoft.com
-kulichki.net, kulichki.net
-tatatele.in, tatatele.in
-rnybloggertricks.corn, mybloggertricks.com
-rna-birnbo.corn, ma-bimbo.com
-ftchinese.corn, ftchinese.com
-sergey-rnavrodi-rnrnrn.net, sergey-mavrodi-mmm.net
-wp.tv, wp.tv
-chevrolet.corn, chevrolet.com
-razerzone.corn, razerzone.com
-subrnanga.corn, submanga.com
-thornson.co.uk, thomson.co.uk
-syosetu.org, syosetu.org
-olx.corn, olx.com
-vplay.ro, vplay.ro
-rtnn.net, rtnn.net
-55.la, 55.la
-instructure.corn, instructure.com
-lvse.corn, lvse.com
-hvg.hu, hvg.hu
-androidpolice.corn, androidpolice.com
-cookinglight.corn, cookinglight.com
-rnadadsrnedia.corn, madadsmedia.com
-inews.gr, inews.gr
-ktxp.corn, ktxp.com
-socialsecurity.gov, socialsecurity.gov
-equifax.corn, equifax.com
-ceskatelevize.cz, ceskatelevize.cz
-gaaks.corn, gaaks.com
-chillingeffects.org, chillingeffects.org
-kornando.corn, komando.com
-nowpublic.corn, nowpublic.com
-khanwars.ae, khanwars.ae
-berlin.de, berlin.de
-bleepingcornputer.corn, bleepingcomputer.com
-rnilitary.corn, military.com
-zerolO.net, zero10.net
-onekingslane.corn, onekingslane.com
-beget.ru, beget.ru
-get-tune.net, get-tune.net
-freewebs.corn, freewebs.com
-pcfinancial.ca, pcfinancial.ca
-sparknotes.corn, sparknotes.com
-tinychat.corn, tinychat.com
-luxup.ru, luxup.ru
-geforce.corn, geforce.com
-tatts.corn.au, tatts.com.au
-alweearn.corn.sa, alweeam.com.sa
-l23-reg.co.uk, 123-reg.co.uk
-sexyswingertube.corn, sexyswingertube.com
-groupon.es, groupon.es
-guardianlv.corn, guardianlv.com
-hypovereinsbank.de, hypovereinsbank.de
-usc.edu, usc.edu
-ard.de, ard.de
-hoovers.corn, hoovers.com
-tdarneritrade.corn, tdameritrade.com
-userscripts.org, userscripts.org
-applll.corn, app111.com
-al.corn, al.com
-op.fi, op.fi
-adbkrn.corn, adbkm.com
-pivithurutv.info, pivithurutv.info
-haber3.corn, haber3.com
-shatel.ir, shatel.ir
-carnonster.corn, camonster.com
-weltbild.de, weltbild.de
-advanceautoparts.corn, advanceautoparts.com
-rnplssaturn.corn, mplssaturn.com
-weeklystandard.corn, weeklystandard.com
-popscreen.corn, popscreen.com
-freelifetirnefuckbook.corn, freelifetimefuckbook.com
-peixeurbano.corn.br, peixeurbano.com.br
-2258.corn, 2258.com
-proxfree.corn, proxfree.com
-zend.corn, zend.com
-citehr.corn, citehr.com
-gadyd.corn, gadyd.com
-tvspielfilrn.de, tvspielfilm.de
-skapiec.pl, skapiec.pl
-9see.corn, 9see.com
-cndns.corn, cndns.com
-hurriyeternlak.corn, hurriyetemlak.com
-census.gov, census.gov
-collider.corn, collider.com
-cinaplay.corn, cinaplay.com
-aq.corn, aq.com
-aolsearch.corn, aolsearch.com
-ce4arab.corn, ce4arab.com
-cbi.ir, cbi.ir
-cjol.corn, cjol.com
-brandporno.corn, brandporno.com
-yicheshi.corn, yicheshi.com
-rnydealz.de, mydealz.de
-xiachufang.corn, xiachufang.com
-sun-sentinel.corn, sun-sentinel.com
-flashkhor.corn, flashkhor.com
-join.rne, join.me
-hankyung.corn, hankyung.com
-oneandone.co.uk, oneandone.co.uk
-derwesten.de, derwesten.de
-garnrnae.corn, gammae.com
-webadultdating.biz, webadultdating.biz
-pokerstars.corn, pokerstars.com
-fucked-sex.corn, fucked-sex.com
-antaranews.corn, antaranews.com
-banorte.corn, banorte.com
-travian.it, travian.it
-rnsu.edu, msu.edu
-ozbargain.corn.au, ozbargain.com.au
-77vcd.corn, 77vcd.com
-bestooxx.corn, bestooxx.com
-siernens.corn, siemens.com
-en-japan.corn, en-japan.com
-akbank.corn, akbank.com
-srf.ch, srf.ch
-rneijer.corn, meijer.com
-htrnldrive.net, htmldrive.net
-peoplestylewatch.corn, peoplestylewatch.com
-boards.ie, boards.ie
-zhulong.corn, zhulong.com
-svyaznoybank.ru, svyaznoybank.ru
-rnyfilestore.corn, myfilestore.com
-sucuri.net, sucuri.net
-redflagdeals.corn, redflagdeals.com
-javascriptkit.corn, javascriptkit.com
-edrearns.fr, edreams.fr
-wral.corn, wral.com
-togetter.corn, togetter.com
-drni.dk, dmi.dk
-thinkdigit.corn, thinkdigit.com
-barclaycard.co.uk, barclaycard.co.uk
-cornrnlOO.corn, comm100.com
-christianbook.corn, christianbook.com
-popularrnechanics.corn, popularmechanics.com
-taste.corn.au, taste.com.au
-tripadvisor.ru, tripadvisor.ru
-colissirno.fr, colissimo.fr
-gdposir.info, gdposir.info
-rarlab.corn, rarlab.com
-dcnepalevent.corn, dcnepalevent.com
-sagepub.corn, sagepub.com
-rnarkosweb.corn, markosweb.com
-france3.fr, france3.fr
-rnindbodyonline.corn, mindbodyonline.com
-yapo.cl, yapo.cl
-O-6.corn, 0-6.com
-dilbert.corn, dilbert.com
-searchqu.corn, searchqu.com
-usa.gov, usa.gov
-vatandownload.corn, vatandownload.com
-nastyrnovs.corn, nastymovs.com
-santanderrio.corn.ar, santanderrio.com.ar
-notebookcheck.net, notebookcheck.net
-canalplus.fr, canalplus.fr
-epa.gov, epa.gov
-disp.cc, disp.cc
-hotsales.net, hotsales.net
-interpals.net, interpals.net
-vz.ru, vz.ru
-flyertalk.corn, flyertalk.com
-pjrnedia.corn, pjmedia.com
-solornid.net, solomid.net
-rnegaplan.ru, megaplan.ru
-hatenablog.corn, hatenablog.com
-getsatisfaction.corn, getsatisfaction.com
-hotline.ua, hotline.ua
-alternativeto.net, alternativeto.net
-hipfile.corn, hipfile.com
-247sports.corn, 247sports.com
-phpnuke.org, phpnuke.org
-indiaresults.corn, indiaresults.com
-prisjakt.nu, prisjakt.nu
-ltvlive.in, 1tvlive.in
-e-rnai.net, e-mai.net
-trafficg.corn, trafficg.com
-ojogo.pt, ojogo.pt
-totaldornination.corn, totaldomination.com
-eroino.net, eroino.net
-network-tools.corn, network-tools.com
-unibytes.corn, unibytes.com
-seriouseats.corn, seriouseats.com
-twicsy.corn, twicsy.com
-srnbc-card.corn, smbc-card.com
-toocle.corn, toocle.com
-unbounce.corn, unbounce.com
-2tu.cc, 2tu.cc
-cornputerworld.corn, computerworld.com
-clicktrackprofit.corn, clicktrackprofit.com
-serialu.net, serialu.net
-realfarrnacy.corn, realfarmacy.com
-rnetrodeal.corn, metrodeal.com
-binzhi.corn, binzhi.com
-srnilebox.corn, smilebox.com
-coderanch.corn, coderanch.com
-uptodown.corn, uptodown.com
-vbulletin.corn, vbulletin.com
-teasernet.corn, teasernet.com
-adrnob.corn, admob.com
-fingerhut.corn, fingerhut.com
-urlopener.corn, urlopener.com
-vi.nl, vi.nl
-expedia.de, expedia.de
-thekrazycouponlady.corn, thekrazycouponlady.com
-linezing.corn, linezing.com
-rnetropcs.corn, metropcs.com
-draugas.lt, draugas.lt
-rninecraftdl.corn, minecraftdl.com
-airberlin.corn, airberlin.com
-eelly.corn, eelly.com
-siarnsport.co.th, siamsport.co.th
-e-junkie.corn, e-junkie.com
-gulte.corn, gulte.com
-lazada.corn.ph, lazada.com.ph
-cnwnews.corn, cnwnews.com
-tekstowo.pl, tekstowo.pl
-flavorwire.corn, flavorwire.com
-settrade.corn, settrade.com
-francetv.fr, francetv.fr
-experian.corn, experian.com
-bravenet.corn, bravenet.com
-rnytoys.de, mytoys.de
-inkthernes.corn, inkthemes.com
-brobible.corn, brobible.com
-sarenza.corn, sarenza.com
-curse.corn, curse.com
-7sur7.be, 7sur7.be
-iberia.corn, iberia.com
-trovit.es, trovit.es
-eiga.corn, eiga.com
-getuploader.corn, getuploader.com
-sevendollarptc.corn, sevendollarptc.com
-arnadeus.corn, amadeus.com
-thedailystar.net, thedailystar.net
-gofuckbiz.corn, gofuckbiz.com
-codepen.io, codepen.io
-virginia.gov, virginia.gov
-linguee.fr, linguee.fr
-space.corn, space.com
-astrology.corn, astrology.com
-whrncs.corn, whmcs.com
-blogher.corn, blogher.com
-netpnb.corn, netpnb.com
-rnojo-thernes.corn, mojo-themes.com
-carn4.es, cam4.es
-bestwestern.corn, bestwestern.com
-gencat.cat, gencat.cat
-healthcentral.corn, healthcentral.com
-ru-board.corn, ru-board.com
-tjsp.jus.br, tjsp.jus.br
-scene7.corn, scene7.com
-bukalapak.corn, bukalapak.com
-intporn.corn, intporn.com
-xe.gr, xe.gr
-leprosoriurn.ru, leprosorium.ru
-dytt8.net, dytt8.net
-wpcentral.corn, wpcentral.com
-fasttrafficforrnula.corn, fasttrafficformula.com
-hugefiles.net, hugefiles.net
-you-sex-tube.corn, you-sex-tube.com
-naukrigulf.corn, naukrigulf.com
-5l73.corn, 5173.com
-cornicvip.corn, comicvip.com
-jossandrnain.corn, jossandmain.com
-rnotherjones.corn, motherjones.com
-planet.fr, planet.fr
-thornascook.corn, thomascook.com
-deseretnews.corn, deseretnews.com
-aawsat.corn, aawsat.com
-huntington.corn, huntington.com
-desirnartini.corn, desimartini.com
-rnalournaa.blogspot.corn, maloumaa.blogspot.com
-rutgers.edu, rutgers.edu
-gratisjuegos.org, gratisjuegos.org
-carsforsale.corn, carsforsale.com
-filestore72.info, filestore72.info
-neowin.net, neowin.net
-ilgiornale.it, ilgiornale.it
-downloadOO98.corn, download0098.com
-providesupport.corn, providesupport.com
-postini.corn, postini.com
-sinowayprorno.corn, sinowaypromo.com
-watchop.corn, watchop.com
-docusign.net, docusign.net
-sourcenext.corn, sourcenext.com
-finviz.corn, finviz.com
-babyoye.corn, babyoye.com
-andhrajyothy.corn, andhrajyothy.com
-garnezer.corn, gamezer.com
-baozournanhua.corn, baozoumanhua.com
-niusnews.corn, niusnews.com
-yabancidiziizle.net, yabancidiziizle.net
-fodors.corn, fodors.com
-rnoonsy.corn, moonsy.com
-lidl.it, lidl.it
-betanews.corn, betanews.com
-escapistrnagazine.corn, escapistmagazine.com
-rnarkethealth.corn, markethealth.com
-clicksure.corn, clicksure.com
-aircel.corn, aircel.com
-rnetacrawler.corn, metacrawler.com
-aeat.es, aeat.es
-allafrica.corn, allafrica.com
-watchseries-online.eu, watchseries-online.eu
-adpost.corn, adpost.com
-adac.de, adac.de
-sirnilarweb.corn, similarweb.com
-offervault.corn, offervault.com
-uolhost.corn.br, uolhost.com.br
-rnoviestarplanet.corn, moviestarplanet.com
-overclockers.ru, overclockers.ru
-rocketlanguages.corn, rocketlanguages.com
-finya.de, finya.de
-shahvani.corn, shahvani.com
-firrny.cz, firmy.cz
-incornetaxindia.gov.in, incometaxindia.gov.in
-ecostrearn.tv, ecostream.tv
-pcwelt.de, pcwelt.de
-arcadesafari.corn, arcadesafari.com
-shoghlanty.corn, shoghlanty.com
-videosection.corn, videosection.com
-centauro.corn.br, centauro.com.br
-eroanirnedouga.net, eroanimedouga.net
-orientaltrading.corn, orientaltrading.com
-ogone.corn, ogone.com
-sexlog.corn, sexlog.com
-hotair.corn, hotair.com
-egypt.gov.eg, egypt.gov.eg
-thornasnet.corn, thomasnet.com
-virustotal.corn, virustotal.com
-hayneedle.corn, hayneedle.com
-fatburningfurnace.corn, fatburningfurnace.com
-lovedgarnes.corn, lovedgames.com
-23us.corn, 23us.com
-trafficcaptain.corn, trafficcaptain.com
-v2cigs.corn, v2cigs.com
-teknosa.corn.tr, teknosa.com.tr
-skrill.corn, skrill.com
-puritanas.corn, puritanas.com
-selfgrowth.corn, selfgrowth.com
-ikco.corn, ikco.com
-cuisineaz.corn, cuisineaz.com
-causes.corn, causes.com
-dernocraticunderground.corn, democraticunderground.com
-placesexy.corn, placesexy.com
-expedia.co.uk, expedia.co.uk
-www-corn.co, www-com.co
-toprnongol.corn, topmongol.com
-hikaritube.corn, hikaritube.com
-arnakings.corn, amakings.com
-fxstreet.corn, fxstreet.com
-consultant.ru, consultant.ru
-sacbee.corn, sacbee.com
-supercheats.corn, supercheats.com
-sofunnylol.corn, sofunnylol.com
-rnuzy.corn, muzy.com
-sparda.de, sparda.de
-caughtoffside.corn, caughtoffside.com
-chinawornendating.asia, chinawomendating.asia
-xrneeting.corn, xmeeting.com
-google.al, google.al
-sovereignbank.corn, sovereignbank.com
-anirneflv.net, animeflv.net
-sky.de, sky.de
-huatu.corn, huatu.com
-payscale.corn, payscale.com
-quotidiano.net, quotidiano.net
-pol.ir, pol.ir
-digital-photography-school.corn, digital-photography-school.com
-screencrush.corn, screencrush.com
-netgear.corn, netgear.com
-thebiglistofporn.corn, thebiglistofporn.com
-sirnilarsitesearch.corn, similarsitesearch.com
-peb.pl, peb.pl
-lanrentuku.corn, lanrentuku.com
-ksu.edu.sa, ksu.edu.sa
-tradetracker.corn, tradetracker.com
-avito.rna, avito.ma
-projectfree.tv, projectfree.tv
-crnu.edu, cmu.edu
-irnore.corn, imore.com
-tickld.corn, tickld.com
-fitday.corn, fitday.com
-dulcebank.corn, dulcebank.com
-careerdonkey.corn, careerdonkey.com
-pf.pl, pf.pl
-otzovik.corn, otzovik.com
-baltirnoresun.corn, baltimoresun.com
-jobvite.corn, jobvite.com
-raternyprofessors.corn, ratemyprofessors.com
-bancodevenezuela.corn, bancodevenezuela.com
-linkafarin.corn, linkafarin.com
-ufxrnarkets.corn, ufxmarkets.com
-lavozdegalicia.es, lavozdegalicia.es
-99bill.corn, 99bill.com
-punyu.corn, punyu.com
-otodorn.pl, otodom.pl
-entireweb.corn, entireweb.com
-fastshop.corn.br, fastshop.com.br
-irngnip.corn, imgnip.com
-goodlife.corn, goodlife.com
-caringbridge.org, caringbridge.org
-pistonheads.corn, pistonheads.com
-gun.az, gun.az
-landl.es, 1and1.es
-photofunia.corn, photofunia.com
-nrne.corn, nme.com
-carfax.corn, carfax.com
-gutenberg.org, gutenberg.org
-youxixiazai.org, youxixiazai.org
-webrnastersitesi.corn, webmastersitesi.com
-skynet.be, skynet.be
-afrointroductions.corn, afrointroductions.com
-rnp3slash.net, mp3slash.net
-netzwelt.de, netzwelt.de
-ecrater.corn, ecrater.com
-livernint.corn, livemint.com
-worldwinner.corn, worldwinner.com
-echosign.corn, echosign.com
-crornaretail.corn, cromaretail.com
-freewebcarnporntube.corn, freewebcamporntube.com
-adrnin.ch, admin.ch
-allstate.corn, allstate.com
-photoscape.org, photoscape.org
-cv-library.co.uk, cv-library.co.uk
-voici.fr, voici.fr
-wdr.de, wdr.de
-pbase.corn, pbase.com
-rnycenturylink.corn, mycenturylink.com
-sonicornusica.corn, sonicomusica.com
-scherna.org, schema.org
-srnashwords.corn, smashwords.com
-al3ab.net, al3ab.net
-rnuryouav.net, muryouav.net
-rnocospace.corn, mocospace.com
-fundsxpress.corn, fundsxpress.com
-chrisc.corn, chrisc.com
-poernhunter.corn, poemhunter.com
-cupid.corn, cupid.com
-tirnescity.corn, timescity.com
-banglarnail24.corn, banglamail24.com
-rnotika.corn.rnk, motika.com.mk
-sec.gov, sec.gov
-whatculture.corn, whatculture.com
-narnepros.corn, namepros.com
-vsernayki.ru, vsemayki.ru
-hip2save.corn, hip2save.com
-hotnews.ro, hotnews.ro
-vietbao.vn, vietbao.vn
-inazurnanews2.corn, inazumanews2.com
-irokotv.corn, irokotv.com
-appthernes.corn, appthemes.com
-tirerack.corn, tirerack.com
-rnaxpark.corn, maxpark.com
-successfactors.corn, successfactors.com
-sba.gov, sba.gov
-hk-porno.corn, hk-porno.com
-setlinks.ru, setlinks.ru
-travel24.corn, travel24.com
-qatarliving.corn, qatarliving.com
-hotlog.ru, hotlog.ru
-raprnls.corn, rapmls.com
-qualityhealth.corn, qualityhealth.com
-linkcollider.corn, linkcollider.com
-kashtanka.corn, kashtanka.com
-hightail.corn, hightail.com
-appszoorn.corn, appszoom.com
-arrnagedornfilrnes.biz, armagedomfilmes.biz
-pnu.ac.ir, pnu.ac.ir
-globalbux.net, globalbux.net
-ebay.corn.hk, ebay.com.hk
-ladenzeile.de, ladenzeile.de
-thedornainfo.corn, thedomainfo.com
-naosalvo.corn.br, naosalvo.com.br
-perfectcarngirls.corn, perfectcamgirls.com
-verticalresponse.corn, verticalresponse.com
-khabardehi.corn, khabardehi.com
-oszone.net, oszone.net
-tearntreehouse.corn, teamtreehouse.com
-hurnanservices.gov.au, humanservices.gov.au
-bostonherald.corn, bostonherald.com
-kafeteria.pl, kafeteria.pl
-society6.corn, society6.com
-garnevicio.corn, gamevicio.com
-crazyegg.corn, crazyegg.com
-logitravel.corn, logitravel.com
-williarns-sonorna.corn, williams-sonoma.com
-htrnlgoodies.corn, htmlgoodies.com
-fontanka.ru, fontanka.ru
-islarnuon.corn, islamuon.com
-tcs.corn, tcs.com
-elyrics.net, elyrics.net
-vip-prorn.net, vip-prom.net
-jobstreet.corn.ph, jobstreet.com.ph
-designfloat.corn, designfloat.com
-lavasoft.corn, lavasoft.com
-tianjinwe.corn, tianjinwe.com
-telelistas.net, telelistas.net
-taglol.corn, taglol.com
-jacquieetrnicheltv.net, jacquieetmicheltv.net
-esprit-online-shop.corn, esprit-online-shop.com
-theeroticreview.corn, theeroticreview.com
-boo-box.corn, boo-box.com
-wandoujia.corn, wandoujia.com
-vgsgarning.corn, vgsgaming.com
-yourtango.corn, yourtango.com
-tianji.corn, tianji.com
-jpost.corn, jpost.com
-rnytherneshop.corn, mythemeshop.com
-seattlepi.corn, seattlepi.com
-bultannews.corn, bultannews.com
-youlikehits.corn, youlikehits.com
-partycity.corn, partycity.com
-l8qt.corn, 18qt.com
-yuvutu.corn, yuvutu.com
-gq.corn, gq.com
-wiziwig.tv, wiziwig.tv
-cinejosh.corn, cinejosh.com
-technet.corn, technet.com
-vatanbilgisayar.corn, vatanbilgisayar.com
-guangjiela.corn, guangjiela.com
-siteheart.corn, siteheart.com
-in.gov, in.gov
-nulled.cc, nulled.cc
-rnafiashare.net, mafiashare.net
-tizag.corn, tizag.com
-hkjc.corn, hkjc.com
-restaurant.corn, restaurant.com
-consurnersurveygroup.org, consumersurveygroup.org
-spin.de, spin.de
-silverlinetrips.corn, silverlinetrips.com
-triberr.corn, triberr.com
-garnesgirl.net, gamesgirl.net
-qqt38.corn, qqt38.com
-xiaoshuornrn.corn, xiaoshuomm.com
-theopen.corn, theopen.com
-carnpograndenews.corn.br, campograndenews.com.br
-soonnight.corn, soonnight.com
-safaribooksonline.corn, safaribooksonline.com
-rnain-hosting.corn, main-hosting.com
-caclubindia.corn, caclubindia.com
-alibado.corn, alibado.com
-autorarnbler.ru, autorambler.ru
-tnt.corn, tnt.com
-chatango.corn, chatango.com
-satrk.corn, satrk.com
-pagesperso-orange.fr, pagesperso-orange.fr
-houseoffraser.co.uk, houseoffraser.co.uk
-nullrefer.corn, nullrefer.com
-work.ua, work.ua
-inagist.corn, inagist.com
-kaban.tv, kaban.tv
-cnxad.corn, cnxad.com
-tarad.corn, tarad.com
-rnasteetv.corn, masteetv.com
-noblesarnurai.corn, noblesamurai.com
-lifehacker.ru, lifehacker.ru
-anakbnet.corn, anakbnet.com
-google.co.ug, google.co.ug
-webcarnsex.nl, webcamsex.nl
-kaoyan.corn, kaoyan.com
-rnl.corn, ml.com
-up.nic.in, up.nic.in
-bouncerne.net, bounceme.net
-netfirrns.corn, netfirms.com
-idokep.hu, idokep.hu
-warnbie.corn, wambie.com
-funpatogh.corn, funpatogh.com
-bcash.corn.br, bcash.com.br
-sedo.co.uk, sedo.co.uk
-noupe.corn, noupe.com
-rnydirtyhobby.corn, mydirtyhobby.com
-neswangy.net, neswangy.net
-downloadprovider.rne, downloadprovider.me
-utah.gov, utah.gov
-consurnerintelligenceusa.corn, consumerintelligenceusa.com
-itirnes.corn, itimes.com
-picrorna.corn, picroma.com
-lustagenten.corn, lustagenten.com
-kerndiknas.go.id, kemdiknas.go.id
-sitepronews.corn, sitepronews.com
-ruseller.corn, ruseller.com
-tradecarview.corn, tradecarview.com
-favstar.frn, favstar.fm
-bestbuy.ca, bestbuy.ca
-yelp.ca, yelp.ca
-stop-sex.corn, stop-sex.com
-rewity.corn, rewity.com
-qiqigarnes.corn, qiqigames.com
-suntirnes.corn, suntimes.com
-hardware.fr, hardware.fr
-rxlist.corn, rxlist.com
-bgr.corn, bgr.com
-zalora.co.id, zalora.co.id
-rnandatory.corn, mandatory.com
-collarrne.corn, collarme.com
-rnycornrnerce.corn, mycommerce.com
-holidayiq.corn, holidayiq.com
-filecloud.io, filecloud.io
-vconnect.corn, vconnect.com
-66l63.corn, 66163.com
-tlen.pl, tlen.pl
-rnrnbang.corn, mmbang.com
-7c.corn, 7c.com
-digitalriver.corn, digitalriver.com
-24video.net, 24video.net
-worthofweb.corn, worthofweb.com
-clasicooo.corn, clasicooo.com
-greatschools.net, greatschools.net
-tagesanzeiger.ch, tagesanzeiger.ch
-video.az, video.az
-osu.edu, osu.edu
-careers36O.corn, careers360.com
-lOl.ru, 101.ru
-conforarna.fr, conforama.fr
-apollo.lv, apollo.lv
-netcq.net, netcq.net
-jofogas.hu, jofogas.hu
-niftylink.corn, niftylink.com
-rnidwayusa.corn, midwayusa.com
-collegeteensex.net, collegeteensex.net
-search.corn, search.com
-nafternporiki.gr, naftemporiki.gr
-sainsburys.co.uk, sainsburys.co.uk
-fitsugar.corn, fitsugar.com
-ifixit.corn, ifixit.com
-uid.rne, uid.me
-rnalwarebytes.org, malwarebytes.org
-rnaxbounty.corn, maxbounty.com
-rnensfitness.corn, mensfitness.com
-rtl.be, rtl.be
-yidio.corn, yidio.com
-dostorasly.corn, dostorasly.com
-abovetopsecret.corn, abovetopsecret.com
-srn3na.corn, sm3na.com
-carn.ac.uk, cam.ac.uk
-garnegape.corn, gamegape.com
-ocioso.corn.br, ocioso.com.br
-register.corn, register.com
-wwitv.corn, wwitv.com
-ishangrnan.corn, ishangman.com
-gry-online.pl, gry-online.pl
-ogli.org, ogli.org
-redbull.corn, redbull.com
-dyn.corn, dyn.com
-freeservers.corn, freeservers.com
-brandsoftheworld.corn, brandsoftheworld.com
-lorddownload.corn, lorddownload.com
-rnybet.corn, mybet.com
-brothalove.corn, brothalove.com
-inchallah.corn, inchallah.com
-lottornatica.it, lottomatica.it
-indiarnp3.corn, indiamp3.com
-qianbao666.corn, qianbao666.com
-zurb.corn, zurb.com
-synxis.corn, synxis.com
-baskino.corn, baskino.com
-swefilrner.corn, swefilmer.com
-hotstartsearch.corn, hotstartsearch.com
-cloudrnoney.info, cloudmoney.info
-polldaddy.corn, polldaddy.com
-rnoheet.corn, moheet.com
-idhostinger.corn, idhostinger.com
-rnp3chief.corn, mp3chief.com
-taol23.corn, tao123.com
-channelnewsasia.corn, channelnewsasia.com
-galeon.corn, galeon.com
-aviasales.ru, aviasales.ru
-datafilehost.corn, datafilehost.com
-travian.corn.eg, travian.com.eg
-ebookee.org, ebookee.org
-filrnstarts.de, filmstarts.de
-inccel.corn, inccel.com
-chatroulette.corn, chatroulette.com
-it-ebooks.info, it-ebooks.info
-nix.ru, nix.ru
-antena3.ro, antena3.ro
-rnylifetirne.corn, mylifetime.com
-desitorrents.corn, desitorrents.com
-rnydigitallife.info, mydigitallife.info
-aeropostale.corn, aeropostale.com
-anilos.corn, anilos.com
-rnacadogru.corn, macadogru.com
-prerniere.fr, premiere.fr
-estorebuilder.corn, estorebuilder.com
-eventirn.de, eventim.de
-expert-offers.corn, expert-offers.com
-deloitte.corn, deloitte.com
-thetirnenow.corn, thetimenow.com
-spicybigbutt.corn, spicybigbutt.com
-gistrnania.corn, gistmania.com
-pekao24.pl, pekao24.pl
-linkfeed.ru, linkfeed.ru
-carnival.corn, carnival.com
-apherald.corn, apherald.com
-choicehotels.corn, choicehotels.com
-revolverrnaps.corn, revolvermaps.com
-digu.corn, digu.com
-yekrnobile.corn, yekmobile.com
-barbarianrnovies.corn, barbarianmovies.com
-poyopara.corn, poyopara.com
-vse.kz, vse.kz
-socialspark.corn, socialspark.com
-deutschepost.de, deutschepost.de
-nokaut.pl, nokaut.pl
-farpost.ru, farpost.ru
-shoebuy.corn, shoebuy.com
-lc-bitrix.ru, 1c-bitrix.ru
-pirnproll.corn, pimproll.com
-startxchange.corn, startxchange.com
-seocentro.corn, seocentro.com
-kporno.corn, kporno.com
-izvestia.ru, izvestia.ru
-bathandbodyworks.corn, bathandbodyworks.com
-allhyiprnonitors.corn, allhyipmonitors.com
-europel.fr, europe1.fr
-charter.corn, charter.com
-sixflags.corn, sixflags.com
-abcjuegos.net, abcjuegos.net
-wind.it, wind.it
-fernjoy.corn, femjoy.com
-hurnanrnetrics.corn, humanmetrics.com
-rnyrealgarnes.corn, myrealgames.com
-cosrniq.de, cosmiq.de
-bangbrosteenporn.corn, bangbrosteenporn.com
-thepetitionsite.corn, thepetitionsite.com
-laprensa.corn.ni, laprensa.com.ni
-investors.corn, investors.com
-techpowerup.corn, techpowerup.com
-prosperitytearn.corn, prosperityteam.com
-autogidas.lt, autogidas.lt
-state.ny.us, state.ny.us
-techbargains.corn, techbargains.com
-takvirn.corn.tr, takvim.com.tr
-kko-appli.corn, kko-appli.com
-liex.ru, liex.ru
-cafe24.corn, cafe24.com
-definebabe.corn, definebabe.com
-egirlgarnes.net, egirlgames.net
-avangard.ru, avangard.ru
-sina.corn.hk, sina.com.hk
-freexcafe.corn, freexcafe.com
-vesti.bg, vesti.bg
-francetvinfo.fr, francetvinfo.fr
-rnathsisfun.corn, mathsisfun.com
-easyrnobilerecharge.corn, easymobilerecharge.com
-dapink.corn, dapink.com
-propellerads.corn, propellerads.com
-devshed.corn, devshed.com
-clip.vn, clip.vn
-vidivodo.corn, vidivodo.com
-blogspot.dk, blogspot.dk
-foxnewsinsider.corn, foxnewsinsider.com
-instapaper.corn, instapaper.com
-prernierleague.corn, premierleague.com
-elo7.corn.br, elo7.com.br
-teenee.corn, teenee.com
-clien.net, clien.net
-cornputrabajo.corn.co, computrabajo.com.co
-kornputronik.pl, komputronik.pl
-livesurf.ru, livesurf.ru
-l23cha.corn, 123cha.com
-cgg.gov.in, cgg.gov.in
-leadirnpact.corn, leadimpact.com
-socialrnonkee.corn, socialmonkee.com
-speeddate.corn, speeddate.com
-bet-at-horne.corn, bet-at-home.com
-huanqiuauto.corn, huanqiuauto.com
-tadawul.corn.sa, tadawul.com.sa
-ucsd.edu, ucsd.edu
-fda.gov, fda.gov
-cint.corn, cint.com
-hornedepot.ca, homedepot.ca
-ciao.de, ciao.de
-gigglesglore.corn, gigglesglore.com
-warfrarne.corn, warframe.com
-prosieben.de, prosieben.de
-vistaprint.in, vistaprint.in
-rnapple.net, mapple.net
-usafis.org, usafis.org
-truelife.corn, truelife.com
-lo26.corn, 1o26.com
-boldsky.corn, boldsky.com
-freeforurns.org, freeforums.org
-lolnexus.corn, lolnexus.com
-ti-da.net, ti-da.net
-handelsbanken.se, handelsbanken.se
-kharnsat.corn, khamsat.com
-futbol24.corn, futbol24.com
-wikifeet.corn, wikifeet.com
-dev-point.corn, dev-point.com
-ibotoolbox.corn, ibotoolbox.com
-indeed.de, indeed.de
-ctlOOOO.corn, ct10000.com
-appleinsider.corn, appleinsider.com
-lyoness.net, lyoness.net
-vodafone.corn.eg, vodafone.com.eg
-aifang.corn, aifang.com
-tripadvisor.corn.br, tripadvisor.com.br
-hbo.corn, hbo.com
-pricerunner.corn, pricerunner.com
-4everproxy.corn, 4everproxy.com
-fc-perspolis.corn, fc-perspolis.com
-thernobileindian.corn, themobileindian.com
-girnp.org, gimp.org
-novayagazeta.ru, novayagazeta.ru
-dnfight.corn, dnfight.com
-coco.fr, coco.fr
-thestudentroorn.co.uk, thestudentroom.co.uk
-tiin.vn, tiin.vn
-dailystar.co.uk, dailystar.co.uk
-unfollowed.rne, unfollowed.me
-aljazeerasport.net, aljazeerasport.net
-nasygnale.pl, nasygnale.pl
-sornethingawful.corn, somethingawful.com
-scarnadviser.corn, scamadviser.com
-rncanirne.net, mcanime.net
-9stock.corn, 9stock.com
-boostrnobile.corn, boostmobile.com
-oyunkolu.corn, oyunkolu.com
-beliefnet.corn, beliefnet.com
-lyricsOO7.corn, lyrics007.com
-rtv.net, rtv.net
-hasbro.corn, hasbro.com
-vcp.ir, vcp.ir
-fj-p.corn, fj-p.com
-jetbrains.corn, jetbrains.com
-cpalead.corn, cpalead.com
-zetaboards.corn, zetaboards.com
-sbobet.corn, sbobet.com
-v2ex.corn, v2ex.com
-toggle.corn, toggle.com
-lanebryant.corn, lanebryant.com
-girlgarnes4u.corn, girlgames4u.com
-arnadershornoyl.corn, amadershomoy1.com
-planalto.gov.br, planalto.gov.br
-news-choice.net, news-choice.net
-sarkarinaukriblog.corn, sarkarinaukriblog.com
-sudouest.fr, sudouest.fr
-zdorno.corn, zdomo.com
-egy-nn.corn, egy-nn.com
-pizzaplot.corn, pizzaplot.com
-topgear.corn, topgear.com
-sony.co.in, sony.co.in
-nosv.org, nosv.org
-beppegrillo.it, beppegrillo.it
-sakshieducation.corn, sakshieducation.com
-ternagay.corn, temagay.com
-stepashka.corn, stepashka.com
-trnart.corn, tmart.com
-readwrite.corn, readwrite.com
-tudiscoverykids.corn, tudiscoverykids.com
-belfius.be, belfius.be
-subrnitexpress.corn, submitexpress.com
-autoscout24.ch, autoscout24.ch
-aetna.corn, aetna.com
-torrent-anirne.corn, torrent-anime.com
-superhqporn.corn, superhqporn.com
-kaufda.de, kaufda.de
-adorocinerna.corn, adorocinema.com
-burning-seri.es, burning-seri.es
-rlsbb.corn, rlsbb.com
-housing.co.in, housing.co.in
-invisionfree.corn, invisionfree.com
-istruzione.it, istruzione.it
-desk.corn, desk.com
-lyricsrnint.corn, lyricsmint.com
-taohuopu.corn, taohuopu.com
-silverdaddies.corn, silverdaddies.com
-gov.cl, gov.cl
-vtc.vn, vtc.vn
-tanea.gr, tanea.gr
-labirint.ru, labirint.ru
-snslO4.corn, sns104.com
-bigpicture.ru, bigpicture.ru
-rnarketo.corn, marketo.com
-isrnrnagic.corn, ismmagic.com
-c-sharpcorner.corn, c-sharpcorner.com
-synacor.corn, synacor.com
-answered-questions.corn, answered-questions.com
-prlog.ru, prlog.ru
-vodafone.corn.tr, vodafone.com.tr
-thenews.corn.pk, thenews.com.pk
-galaxygiftcard.corn, galaxygiftcard.com
-job-search-engine.corn, job-search-engine.com
-se.pl, se.pl
-consurnercornplaints.in, consumercomplaints.in
-265.corn, 265.com
-cba.pl, cba.pl
-hurnoron.corn, humoron.com
-uscourts.gov, uscourts.gov
-blog.pl, blog.pl
-youtu.be, youtu.be
-play4free.corn, play4free.com
-blizko.ru, blizko.ru
-uswebproxy.corn, uswebproxy.com
-winning-play.corn, winning-play.com
-yourstory.in, yourstory.in
-tinrnoi.vn, tinmoi.vn
-yongchuntang.net, yongchuntang.net
-artofrnanliness.corn, artofmanliness.com
-nadaguides.corn, nadaguides.com
-ndr.de, ndr.de
-kuidle.corn, kuidle.com
-hopy.corn, hopy.com
-roi.ru, roi.ru
-sdpnoticias.corn, sdpnoticias.com
-nation.corn, nation.com
-gnu.org, gnu.org
-vogue.co.uk, vogue.co.uk
-letsebuy.corn, letsebuy.com
-preloved.co.uk, preloved.co.uk
-yatedo.corn, yatedo.com
-rs-online.corn, rs-online.com
-kino-teatr.ru, kino-teatr.ru
-rneeticaffinity.fr, meeticaffinity.fr
-clip.dj, clip.dj
-cornpete.corn, compete.com
-pravda.sk, pravda.sk
-oursogo.corn, oursogo.com
-designyourway.net, designyourway.net
-elcorreo.corn, elcorreo.com
-williarnhill.es, williamhill.es
-lavenir.net, lavenir.net
-voyage-prive.es, voyage-prive.es
-tearnbeachbody.corn, teambeachbody.com
-sportdog.gr, sportdog.gr
-klicktel.de, klicktel.de
-ktonanovenkogo.ru, ktonanovenkogo.ru
-sbwire.corn, sbwire.com
-pearsoncrng.corn, pearsoncmg.com
-bankifsccode.corn, bankifsccode.com
-thenationonlineng.net, thenationonlineng.net
-bangbrosl.corn, bangbros1.com
-tarot.corn, tarot.com
-acdsee.corn, acdsee.com
-blogos.corn, blogos.com
-dinnerwithrnariah.corn, dinnerwithmariah.com
-japan-wornen-dating.corn, japan-women-dating.com
-sarzarnindownload.corn, sarzamindownload.com
-tirnesonline.co.uk, timesonline.co.uk
-okbuy.corn, okbuy.com
-sbb.ch, sbb.ch
-rnundogaturro.corn, mundogaturro.com
-rneinvz.net, meinvz.net
-trafficadbar.corn, trafficadbar.com
-9rninecraft.net, 9minecraft.net
-nextbigwhat.corn, nextbigwhat.com
-eshetab.corn, eshetab.com
-rneristation.corn, meristation.com
-kalahari.corn, kalahari.com
-pirnpandhost.corn, pimpandhost.com
-pbworks.corn, pbworks.com
-bokee.net, bokee.net
-google.ps, google.ps
-seccionarnarilla.corn.rnx, seccionamarilla.com.mx
-foroactivo.corn, foroactivo.com
-kalaydo.de, kalaydo.de
-gornaji.corn, gomaji.com
-exactseek.corn, exactseek.com
-cashtaller.ru, cashtaller.ru
-blogspot.co.nz, blogspot.co.nz
-volvocars.corn, volvocars.com
-rnarathonbet.corn, marathonbet.com
-hk-pub.corn, hk-pub.com
-seriouslyfacts.rne, seriouslyfacts.me
-streetdirectory.corn, streetdirectory.com
-rnediarnasr.tv, mediamasr.tv
-straitstirnes.corn, straitstimes.com
-prornodj.corn, promodj.com
-3dwwwgarne.corn, 3dwwwgame.com
-autovit.ro, autovit.ro
-ahlalhdeeth.corn, ahlalhdeeth.com
-forurn-auto.corn, forum-auto.com
-stooorage.corn, stooorage.com
-rnobilisrn.org, mobilism.org
-hideref.org, hideref.org
-rnn66.corn, mn66.com
-internations.org, internations.org
-sbicard.corn, sbicard.com
-dayoo.corn, dayoo.com
-biquge.corn, biquge.com
-therne.wordpress.corn, theme.wordpress.com
-rnrdoob.corn, mrdoob.com
-vpls.net, vpls.net
-alqurna-a.corn, alquma-a.com
-bankrnillenniurn.pl, bankmillennium.pl
-rnitele.es, mitele.es
-tro-rna-ktiko.blogspot.gr, tro-ma-ktiko.blogspot.gr
-bookrnark4you.corn, bookmark4you.com
-tencent.corn, tencent.com
-bsi.ir, bsi.ir
-fox.corn, fox.com
-payback.de, payback.de
-tubepornfilrn.corn, tubepornfilm.com
-herold.at, herold.at
-elperiodico.corn, elperiodico.com
-lolesports.corn, lolesports.com
-hrs.de, hrs.de
-trustlink.ru, trustlink.ru
-pricernachine.corn, pricemachine.com
-socialadr.corn, socialadr.com
-anandabazar.corn, anandabazar.com
-jacquieetrnicheltv2.net, jacquieetmicheltv2.net
-rnonster.de, monster.de
-allposters.corn, allposters.com
-blog.ir, blog.ir
-ad4garne.corn, ad4game.com
-alkislarlayasiyorurn.corn, alkislarlayasiyorum.com
-ptcsolution.corn, ptcsolution.com
-rnoviepilot.corn, moviepilot.com
-ddizi.org, ddizi.org
-drnzj.corn, dmzj.com
-onvasortir.corn, onvasortir.com
-ferronetwork.corn, ferronetwork.com
-seagate.corn, seagate.com
-starrnedia.corn, starmedia.com
-topit.rne, topit.me
-developpez.net, developpez.net
-papajogos.corn.br, papajogos.com.br
-btalah.corn, btalah.com
-gateway.gov.uk, gateway.gov.uk
-fotki.corn, fotki.com
-holidaylettings.co.uk, holidaylettings.co.uk
-rzeczpospolita.pl, rzeczpospolita.pl
-charter97.org, charter97.org
-robtex.corn, robtex.com
-bestadbid.corn, bestadbid.com
-unblog.fr, unblog.fr
-archive.is, archive.is
-rnicroworkers.corn, microworkers.com
-vbulletin.org, vbulletin.org
-jetswap.corn, jetswap.com
-badoink.corn, badoink.com
-adobeconnect.corn, adobeconnect.com
-cutt.us, cutt.us
-lovernake.biz, lovemake.biz
-xpress.corn, xpress.com
-di.se, di.se
-jacquielawson.corn, jacquielawson.com
-satl.de, sat1.de
-adshuffle.corn, adshuffle.com
-hornepage.corn.tr, homepage.com.tr
-treehugger.corn, treehugger.com
-selectornews.corn, selectornews.com
-dap-news.corn, dap-news.com
-tvline.corn, tvline.com
-col88.corn, co188.com
-bfrntv.corn, bfmtv.com
-nastygal.corn, nastygal.com
-cebupacificair.corn, cebupacificair.com
-spr.ru, spr.ru
-vazeh.corn, vazeh.com
-worldrnarket.corn, worldmarket.com
-arnericanlivewire.corn, americanlivewire.com
-befunky.corn, befunky.com
-rnovie2k.tl, movie2k.tl
-coach.corn, coach.com
-whattoexpect.corn, whattoexpect.com
-share-online.biz, share-online.biz
-fishwrapper.corn, fishwrapper.com
-aktifhaber.corn, aktifhaber.com
-downxsoft.corn, downxsoft.com
-websurf.ru, websurf.ru
-bbcgoodfood.corn, bbcgoodfood.com
-france2.fr, france2.fr
-gyakorikerdesek.hu, gyakorikerdesek.hu
-lidovky.cz, lidovky.cz
-thithtoolwin.info, thithtoolwin.info
-psbc.corn, psbc.com
-766.corn, 766.com
-co-operativebank.co.uk, co-operativebank.co.uk
-iwriter.corn, iwriter.com
-bravotv.corn, bravotv.com
-sbs.corn.au, sbs.com.au
-dtiserv2.corn, dtiserv2.com
-watchever.de, watchever.de
-playhub.corn, playhub.com
-globovision.corn, globovision.com
-intereconornia.corn, intereconomia.com
-poznan.pl, poznan.pl
-cornicbookrnovie.corn, comicbookmovie.com
-ocornico.net, ocomico.net
-housetrip.corn, housetrip.com
-freewebsubrnission.corn, freewebsubmission.com
-karrnaloop.corn, karmaloop.com
-savevid.corn, savevid.com
-lastpass.corn, lastpass.com
-yougou.corn, yougou.com
-iafd.corn, iafd.com
-casertex.corn, casertex.com
-grnail.corn, gmail.com
-rnodhoster.de, modhoster.de
-post-gazette.corn, post-gazette.com
-digikey.corn, digikey.com
-torrentleech.org, torrentleech.org
-starnps.corn, stamps.com
-lifestyleinsights.org, lifestyleinsights.org
-pandawill.corn, pandawill.com
-wrn-panel.corn, wm-panel.com
-urn-per.corn, um-per.com
-straighttalk.corn, straighttalk.com
-xpersonals.corn, xpersonals.com
-bondfaro.corn.br, bondfaro.com.br
-tvrage.corn, tvrage.com
-rockongags.corn, rockongags.com
-4jok.corn, 4jok.com
-zoorn.corn.br, zoom.com.br
-pixabay.corn, pixabay.com
-path.corn, path.com
-hiphopdx.corn, hiphopdx.com
-ptbus.corn, ptbus.com
-fussball.de, fussball.de
-windows.net, windows.net
-adweek.corn, adweek.com
-kraftrecipes.corn, kraftrecipes.com
-redtrarn.corn, redtram.com
-youravon.corn, youravon.com
-ladepeche.fr, ladepeche.fr
-jiwu.corn, jiwu.com
-hobbylobby.corn, hobbylobby.com
-otzyv.ru, otzyv.ru
-sky-fire.corn, sky-fire.com
-fileguru.corn, fileguru.com
-vandal.net, vandal.net
-haozu.corn, haozu.com
-laxtearns.net, laxteams.net
-cpvtrack2O2.corn, cpvtrack202.com
-libraryreserve.corn, libraryreserve.com
-tvigle.ru, tvigle.ru
-hoopshype.corn, hoopshype.com
-worldcat.org, worldcat.org
-eventful.corn, eventful.com
-nettiauto.corn, nettiauto.com
-generalfiles.org, generalfiles.org
-ojooo.corn, ojooo.com
-thatisnotasport.corn, thatisnotasport.com
-thepioneerwornan.corn, thepioneerwoman.com
-social-bookrnarking.net, social-bookmarking.net
-lookforithere.info, lookforithere.info
-arnericanapparel.net, americanapparel.net
-protv.ro, protv.ro
-jeux-gratuits.corn, jeux-gratuits.com
-tornoson.corn, tomoson.com
-jpn.org, jpn.org
-cpz.to, cpz.to
-vrisko.gr, vrisko.gr
-cbox.ws, cbox.ws
-vandelaydesign.corn, vandelaydesign.com
-rnacrnillandictionary.corn, macmillandictionary.com
-eventure.corn, eventure.com
-niniweblog.corn, niniweblog.com
-ecwid.corn, ecwid.com
-garuda-indonesia.corn, garuda-indonesia.com
-education.corn, education.com
-natalie.rnu, natalie.mu
-gigsandfestivals.co.uk, gigsandfestivals.co.uk
-onlainfilrn.ucoz.ua, onlainfilm.ucoz.ua
-hotwords.corn, hotwords.com
-jagobd.corn, jagobd.com
-pageset.corn, pageset.com
-sagepay.corn, sagepay.com
-runkeeper.corn, runkeeper.com
-beeztube.corn, beeztube.com
-pinla.corn, pinla.com
-blizzard.corn, blizzard.com
-unc.edu, unc.edu
-rnakernernarvellous.corn, makememarvellous.com
-wer-weiss-was.de, wer-weiss-was.de
-ubc.ca, ubc.ca
-utoronto.ca, utoronto.ca
-avsforurn.corn, avsforum.com
-newrelic.corn, newrelic.com
-orkut.co.in, orkut.co.in
-wawa-rnania.ec, wawa-mania.ec
-ncsu.edu, ncsu.edu
-redhat.corn, redhat.com
-nsdl.co.in, nsdl.co.in
-lavoz.corn.ar, lavoz.com.ar
-navy.rnil, navy.mil
-rng.gov.br, mg.gov.br
-psychcentral.corn, psychcentral.com
-ultipro.corn, ultipro.com
-unisa.ac.za, unisa.ac.za
-sooperarticles.corn, sooperarticles.com
-wondershare.corn, wondershare.com
-wholefoodsrnarket.corn, wholefoodsmarket.com
-durnpaday.corn, dumpaday.com
-littlewoods.corn, littlewoods.com
-carscorn.net, carscom.net
-rneitu.corn, meitu.com
-9lwan.corn, 9lwan.com
-ernailrneforrn.corn, emailmeform.com
-arte.tv, arte.tv
-tribalfootball.corn, tribalfootball.com
-howtoforge.corn, howtoforge.com
-cvent.corn, cvent.com
-fujitsu.corn, fujitsu.com
-silvergarnes.corn, silvergames.com
-fatlossfactor.corn, fatlossfactor.com
-nusport.nl, nusport.nl
-todol.corn, todo1.com
-see-tube.corn, see-tube.com
-lolspots.corn, lolspots.com
-sucksex.corn, sucksex.com
-encontreinarede.corn, encontreinarede.com
-rnyarabylinks.corn, myarabylinks.com
-v-39.net, v-39.net
-soornpi.corn, soompi.com
-rnltdb.corn, mltdb.com
-websitetonight.corn, websitetonight.com
-bu.edu, bu.edu
-lazada.co.th, lazada.co.th
-rnature-rnoney.corn, mature-money.com
-sirnplernachines.org, simplemachines.org
-tnt-online.ru, tnt-online.ru
-disput.az, disput.az
-flirtcafe.de, flirtcafe.de
-dlnet.corn, d1net.com
-infoplease.corn, infoplease.com
-unseenirnages.co.in, unseenimages.co.in
-downloadatoz.corn, downloadatoz.com
-norwegian.corn, norwegian.com
-youtradefx.corn, youtradefx.com
-petapixel.corn, petapixel.com
-bytes.corn, bytes.com
-ht.ly, ht.ly
-jobberrnan.corn, jobberman.com
-xenforo.corn, xenforo.com
-pornponik.pl, pomponik.pl
-siarnbit.org, siambit.org
-twoplustwo.corn, twoplustwo.com
-videoslasher.corn, videoslasher.com
-onvista.de, onvista.de
-canstockphoto.corn, canstockphoto.com
-cash4flirt.corn, cash4flirt.com
-flashgarnes.it, flashgames.it
-xxxdessert.corn, xxxdessert.com
-cda.pl, cda.pl
-costco.ca, costco.ca
-elnuevodiario.corn.ni, elnuevodiario.com.ni
-svtplay.se, svtplay.se
-ftc.gov, ftc.gov
-supersonicads.corn, supersonicads.com
-openstreetrnap.org, openstreetmap.org
-chinarnobile.corn, chinamobile.com
-fastspring.corn, fastspring.com
-rncdonalds.corn, mcdonalds.com
-egloos.corn, egloos.com
-rnouser.corn, mouser.com
-livernook.corn, livemook.com
-woxiu.corn, woxiu.com
-pingler.corn, pingler.com
-ruelsoft.org, ruelsoft.org
-krone.at, krone.at
-internetbookshop.it, internetbookshop.it
-alibaba-inc.corn, alibaba-inc.com
-kirnsufi.corn, kimsufi.com
-surnrnitracing.corn, summitracing.com
-parsfootball.corn, parsfootball.com
-standard.co.uk, standard.co.uk
-photoblog.pl, photoblog.pl
-bicaps.corn, bicaps.com
-digitalplayground.corn, digitalplayground.com
-zerochan.net, zerochan.net
-whosay.corn, whosay.com
-qualityseek.org, qualityseek.org
-say7.info, say7.info
-rs.gov.br, rs.gov.br
-google.co.rnz, google.co.mz
-yourlustrnovies.corn, yourlustmovies.com
-zalando.nl, zalando.nl
-jn.pt, jn.pt
-hornebase.co.uk, homebase.co.uk
-avis.corn, avis.com
-healthboards.corn, healthboards.com
-filrnizlesene.corn.tr, filmizlesene.com.tr
-shoutcast.corn, shoutcast.com
-indiafreestuff.in, indiafreestuff.in
-avval.ir, avval.ir
-garningwonderland.corn, gamingwonderland.com
-adage.corn, adage.com
-asu.edu, asu.edu
-frorna.corn, froma.com
-bezuzyteczna.pl, bezuzyteczna.pl
-workopolis.corn, workopolis.com
-extranetinvestrnent.corn, extranetinvestment.com
-lablue.de, lablue.de
-geotauaisay.corn, geotauaisay.com
-bestchange.ru, bestchange.ru
-ptp22.corn, ptp22.com
-tehparadox.corn, tehparadox.com
-ox.ac.uk, ox.ac.uk
-radaris.corn, radaris.com
-dorndigger.corn, domdigger.com
-lizads.corn, lizads.com
-chatvl.corn, chatvl.com
-elle.corn, elle.com
-soloaqui.es, soloaqui.es
-tubejuggs.corn, tubejuggs.com
-jsonline.corn, jsonline.com
-ut.ac.ir, ut.ac.ir
-iitv.info, iitv.info
-runetki.tv, runetki.tv
-hyundai.corn, hyundai.com
-turkiye.gov.tr, turkiye.gov.tr
-jobstreet.corn.sg, jobstreet.com.sg
-jp-sex.corn, jp-sex.com
-soccer.ru, soccer.ru
-slashfilrn.corn, slashfilm.com
-couchtuner.eu, couchtuner.eu
-quanfan.corn, quanfan.com
-porsche.corn, porsche.com
-craftsy.corn, craftsy.com
-geizhals.at, geizhals.at
-spartoo.it, spartoo.it
-yxku.corn, yxku.com
-vodonet.net, vodonet.net
-photo.net, photo.net
-raiffeisen.ru, raiffeisen.ru
-tablotala.corn, tablotala.com
-theaa.corn, theaa.com
-idownloadblog.corn, idownloadblog.com
-rodfile.corn, rodfile.com
-alabout.corn, alabout.com
-flnews.ru, f1news.ru
-divxstage.eu, divxstage.eu
-itusozluk.corn, itusozluk.com
-hicdrna.corn, hicdma.com
-dota2lounge.corn, dota2lounge.com
-greensrnut.corn, greensmut.com
-bharatiyarnobile.corn, bharatiyamobile.com
-handycafe.corn, handycafe.com
-regarder-filrn-gratuit.corn, regarder-film-gratuit.com
-adultgeek.net, adultgeek.net
-yintai.corn, yintai.com
-brasilescola.corn, brasilescola.com
-verisign.corn, verisign.com
-dnslink.corn, dnslink.com
-standaard.be, standaard.be
-cbengine.corn, cbengine.com
-pchealthboost.corn, pchealthboost.com
-dealdey.corn, dealdey.com
-cnnturk.corn, cnnturk.com
-trutv.corn, trutv.com
-tahrirnews.corn, tahrirnews.com
-getit.in, getit.in
-jqueryrnobile.corn, jquerymobile.com
-girlgarnes.corn, girlgames.com
-alhayat.corn, alhayat.com
-ilpvideo.corn, ilpvideo.com
-stihi.ru, stihi.ru
-skyscanner.ru, skyscanner.ru
-jarnejarnonline.ir, jamejamonline.ir
-t3n.de, t3n.de
-rent.corn, rent.com
-telerik.corn, telerik.com
-tandfonline.corn, tandfonline.com
-argonas.corn, argonas.com
-ludokado.corn, ludokado.com
-luvgag.corn, luvgag.com
-rnyspongebob.ru, myspongebob.ru
-z5x.net, z5x.net
-allhyiprnon.ru, allhyipmon.ru
-fanswong.corn, fanswong.com
-oddee.corn, oddee.com
-guoli.corn, guoli.com
-wpzoorn.corn, wpzoom.com
-2gheroon.corn, 2gheroon.com
-artisteer.corn, artisteer.com
-share-links.biz, share-links.biz
-flightstats.corn, flightstats.com
-wisegeek.org, wisegeek.org
-shuangtv.net, shuangtv.net
-rnylikes.corn, mylikes.com
-OzzO.corn, 0zz0.com
-xiu.corn, xiu.com
-pornizle69.corn, pornizle69.com
-sendgrid.corn, sendgrid.com
-theweek.corn, theweek.com
-veetle.corn, veetle.com
-theanirnalrescuesite.corn, theanimalrescuesite.com
-sears.ca, sears.ca
-tianpin.corn, tianpin.com
-thisdaylive.corn, thisdaylive.com
-rnyfunlife.corn, myfunlife.com
-furaffinity.net, furaffinity.net
-politiken.dk, politiken.dk
-youwatch.org, youwatch.org
-lesoir.be, lesoir.be
-toyokeizai.net, toyokeizai.net
-centos.org, centos.org
-sunnyplayer.corn, sunnyplayer.com
-knuddels.de, knuddels.de
-rnturk.corn, mturk.com
-egyrnodern.corn, egymodern.com
-sernprot.corn, semprot.com
-rnonsterhigh.corn, monsterhigh.com
-kornpass.corn, kompass.com
-olx.corn.ve, olx.com.ve
-hq-xnxx.corn, hq-xnxx.com
-whorush.corn, whorush.com
-bongdaso.corn, bongdaso.com
-centrelink.gov.au, centrelink.gov.au
-folha.corn.br, folha.com.br
-getjetso.corn, getjetso.com
-ycornbinator.corn, ycombinator.com
-chouti.corn, chouti.com
-33lc.corn, 33lc.com
-hostgator.corn.br, hostgator.com.br
-ernirates247.corn, emirates247.com
-itpub.net, itpub.net
-fsyrnbols.corn, fsymbols.com
-bestproducttesters.corn, bestproducttesters.com
-daodao.corn, daodao.com
-virtuernart.net, virtuemart.net
-hindilinks4u.net, hindilinks4u.net
-nnrn.rne, nnm.me
-xplocial.corn, xplocial.com
-apartrnents.corn, apartments.com
-ekolay.net, ekolay.net
-doviz.corn, doviz.com
-flixya.corn, flixya.com
-3alrnthqafa.corn, 3almthqafa.com
-zarnalekfans.corn, zamalekfans.com
-irneigu.corn, imeigu.com
-wikibit.net, wikibit.net
-windstrearn.net, windstream.net
-rnatichon.co.th, matichon.co.th
-appshopper.corn, appshopper.com
-socialbakers.corn, socialbakers.com
-lpopov.ru, 1popov.ru
-blikk.hu, blikk.hu
-bdrl3O.net, bdr130.net
-arizona.edu, arizona.edu
-rnadhyarnarn.corn, madhyamam.com
-rnweb.co.za, mweb.co.za
-affiliates.de, affiliates.de
-ebs.in, ebs.in
-bestgfx.corn, bestgfx.com
-share-garnes.corn, share-games.com
-inforrnador.corn.rnx, informador.com.mx
-jobsite.co.uk, jobsite.co.uk
-carters.corn, carters.com
-kinghost.net, kinghost.net
-usl.corn, us1.com
-archives.corn, archives.com
-forosdelweb.corn, forosdelweb.com
-siteslike.corn, siteslike.com
-thedailyshow.corn, thedailyshow.com
-68design.net, 68design.net
-irntalk.org, imtalk.org
-visualwebsiteoptirnizer.corn, visualwebsiteoptimizer.com
-glarysoft.corn, glarysoft.com
-xhby.net, xhby.net
-ernail.cz, email.cz
-arnateurs-gone-wild.corn, amateurs-gone-wild.com
-davidwalsh.narne, davidwalsh.name
-finalfantasyxiv.corn, finalfantasyxiv.com
-aa.corn.tr, aa.com.tr
-legalzoorn.corn, legalzoom.com
-lifehack.org, lifehack.org
-rnca.gov.in, mca.gov.in
-hidrvids.corn, hidrvids.com
-key.corn, key.com
-thurnbtack.corn, thumbtack.com
-nujij.nl, nujij.nl
-cinetux.org, cinetux.org
-hrnetro.corn.rny, hmetro.com.my
-ignou.ac.in, ignou.ac.in
-affilorarna.corn, affilorama.com
-pokernon.corn, pokemon.com
-sportsnewsinternational.corn, sportsnewsinternational.com
-geek.corn, geek.com
-larepublica.pe, larepublica.pe
-europacasino.corn, europacasino.com
-ok-porn.corn, ok-porn.com
-tutorialzine.corn, tutorialzine.com
-google.corn.bn, google.com.bn
-site5.corn, site5.com
-trafficjunky.net, trafficjunky.net
-xueqiu.corn, xueqiu.com
-yournewscorner.corn, yournewscorner.com
-rnetrotvnews.corn, metrotvnews.com
-nichegalz.corn, nichegalz.com
-job.corn, job.com
-koirnoi.corn, koimoi.com
-questionablecontent.net, questionablecontent.net
-volaris.rnx, volaris.mx
-rakuten.de, rakuten.de
-cyworld.corn, cyworld.com
-yudu.corn, yudu.com
-zakon.kz, zakon.kz
-rnsi.corn, msi.com
-darkxxxtube.corn, darkxxxtube.com
-sarnakal.net, samakal.net
-appstorrn.net, appstorm.net
-vulture.corn, vulture.com
-racingpost.corn, racingpost.com
-classicrurnrny.corn, classicrummy.com
-iegallery.corn, iegallery.com
-cinernagia.ro, cinemagia.ro
-nullpoantenna.corn, nullpoantenna.com
-ihned.cz, ihned.cz
-vdolady.corn, vdolady.com
-babes.corn, babes.com
-kornli.corn, komli.com
-asianbeauties.corn, asianbeauties.com
-onedate.corn, onedate.com
-adhitz.corn, adhitz.com
-jjgirls.corn, jjgirls.com
-dot.tk, dot.tk
-autobild.de, autobild.de
-jobs-to-careers.corn, jobs-to-careers.com
-rnovietickets.corn, movietickets.com
-net4.in, net4.in
-crutchfield.corn, crutchfield.com
-subdivx.corn, subdivx.com
-sirarcade.corn, sirarcade.com
-sitescoutadserver.corn, sitescoutadserver.com
-fantasy-rivals.corn, fantasy-rivals.com
-chegg.corn, chegg.com
-sportsrnansguide.corn, sportsmansguide.com
-extrernetech.corn, extremetech.com
-loft.corn, loft.com
-dirtyarnateurtube.corn, dirtyamateurtube.com
-socialsex.biz, socialsex.biz
-opensubtitles.us, opensubtitles.us
-infornoney.corn.br, infomoney.com.br
-openstat.ru, openstat.ru
-adlandpro.corn, adlandpro.com
-trivago.de, trivago.de
-feiren.corn, feiren.com
-lespac.corn, lespac.com
-iceporn.corn, iceporn.com
-anirnehere.corn, animehere.com
-klix.ba, klix.ba
-elitepvpers.corn, elitepvpers.com
-rnrconservative.corn, mrconservative.com
-tarnu.edu, tamu.edu
-startv.corn.tr, startv.com.tr
-haberl9O3.corn, haber1903.com
-apa.tv, apa.tv
-idbi.corn, idbi.com
-golfchannel.corn, golfchannel.com
-pep.ph, pep.ph
-toukoucity.to, toukoucity.to
-ernpirernoney.corn, empiremoney.com
-androidauthority.corn, androidauthority.com
-ref4bux.corn, ref4bux.com
-digitaljournal.corn, digitaljournal.com
-sporcle.corn, sporcle.com
-bzwbk.pl, bzwbk.pl
-lalarnao.corn, lalamao.com
-ziare.corn, ziare.com
-cliti.corn, cliti.com
-thatguywiththeglasses.corn, thatguywiththeglasses.com
-vodu.ch, vodu.ch
-ycwb.corn, ycwb.com
-bls.gov, bls.gov
-ltubenews.corn, 1tubenews.com
-cl.ly, cl.ly
-ing.be, ing.be
-bitterstrawberry.corn, bitterstrawberry.com
-fubar.corn, fubar.com
-arabic-keyboard.org, arabic-keyboard.org
-rnejortorrent.corn, mejortorrent.com
-trendrnicro.corn, trendmicro.com
-ap7arn.corn, ap7am.com
-windowsazure.corn, windowsazure.com
-q8yat.corn, q8yat.com
-yyv.co, yyv.co
-tvoy-start.corn, tvoy-start.com
-creativetoolbars.corn, creativetoolbars.com
-forrent.corn, forrent.com
-rnlstatic.corn, mlstatic.com
-like4like.org, like4like.org
-alpha.gr, alpha.gr
-arnkey.net, amkey.net
-iwiw.hu, iwiw.hu
-routard.corn, routard.com
-teacherspayteachers.corn, teacherspayteachers.com
-ahashare.corn, ahashare.com
-ultoo.corn, ultoo.com
-oakley.corn, oakley.com
-upforit.corn, upforit.com
-trafficbee.corn, trafficbee.com
-rnonster.co.uk, monster.co.uk
-boulanger.fr, boulanger.fr
-bloglines.corn, bloglines.com
-wdc.corn, wdc.com
-el-nacional.corn, el-nacional.com
-bloggertipstricks.corn, bloggertipstricks.com
-oreillyauto.corn, oreillyauto.com
-hotpads.corn, hotpads.com
-tubexvideo.corn, tubexvideo.com
-rnudainodocurnent.corn, mudainodocument.com
-discoverpedia.info, discoverpedia.info
-noobteens.corn, noobteens.com
-shockrnansion.corn, shockmansion.com
-qudsonline.ir, qudsonline.ir
-rnec.es, mec.es
-vt.edu, vt.edu
-akelite.corn, akelite.com
-travelandleisure.corn, travelandleisure.com
-sunnewsonline.corn, sunnewsonline.com
-tok2.corn, tok2.com
-truste.org, truste.org
-2dehands.be, 2dehands.be
-hf365.corn, hf365.com
-westelrn.corn, westelm.com
-real.gr, real.gr
-downloadrning.rne, downloadming.me
-citrornail.hu, citromail.hu
-fotocornrnunity.de, fotocommunity.de
-zapjuegos.corn, zapjuegos.com
-aastocks.corn, aastocks.com
-unb.br, unb.br
-adchakra.net, adchakra.net
-check24.de, check24.de
-vidto.rne, vidto.me
-peekyou.corn, peekyou.com
-urssaf.fr, urssaf.fr
-alixixi.corn, alixixi.com
-winarnp.corn, winamp.com
-xianguo.corn, xianguo.com
-indiasextube.net, indiasextube.net
-fitnea.corn, fitnea.com
-telernundo.corn, telemundo.com
-webnode.cz, webnode.cz
-kliksaya.corn, kliksaya.com
-wikileaks.org, wikileaks.org
-rnyblog.it, myblog.it
-99wed.corn, 99wed.com
-adorika.corn, adorika.com
-siliconrus.corn, siliconrus.com
-dealrnoon.corn, dealmoon.com
-ricanadfunds.corn, ricanadfunds.com
-vietcornbank.corn.vn, vietcombank.com.vn
-chernistry.corn, chemistry.com
-reisen.de, reisen.de
-torlock.corn, torlock.com
-wsop.corn, wsop.com
-travian.co.id, travian.co.id
-ipoll.corn, ipoll.com
-bpiexpressonline.corn, bpiexpressonline.com
-neeu.corn, neeu.com
-beyondtherack.corn, beyondtherack.com
-blueidea.corn, blueidea.com
-tedata.net, tedata.net
-garnesradar.corn, gamesradar.com
-big.az, big.az
-h-douga.net, h-douga.net
-runnersworld.corn, runnersworld.com
-lurnfile.corn, lumfile.com
-ul7.corn, u17.com
-badjojo.corn, badjojo.com
-nginx.org, nginx.org
-filrnfanatic.corn, filmfanatic.com
-filrney.corn, filmey.com
-rnousebreaker.corn, mousebreaker.com
-rnihanstore.net, mihanstore.net
-sharebuilder.corn, sharebuilder.com
-cnhan.corn, cnhan.com
-partnerwithtorn.corn, partnerwithtom.com
-synonyrn.corn, synonym.com
-areaconnect.corn, areaconnect.com
-one.lt, one.lt
-rnp3quran.net, mp3quran.net
-anz.co.nz, anz.co.nz
-buyincoins.corn, buyincoins.com
-surfline.corn, surfline.com
-packtpub.corn, packtpub.com
-inforrne2l.corn, informe21.com
-d4OOO.corn, d4000.com
-blog.cz, blog.cz
-rnyredbook.corn, myredbook.com
-seslisozluk.net, seslisozluk.net
-sirnple2advertise.corn, simple2advertise.com
-bookit.corn, bookit.com
-eranico.corn, eranico.com
-pakwheels.corn, pakwheels.com
-x-rates.corn, x-rates.com
-ilrnatieteenlaitos.fi, ilmatieteenlaitos.fi
-vozforurns.corn, vozforums.com
-galerieslafayette.corn, galerieslafayette.com
-trafficswirl.corn, trafficswirl.com
-rnql4.corn, mql4.com
-torontosun.corn, torontosun.com
-lebuteur.corn, lebuteur.com
-cruisecritic.corn, cruisecritic.com
-rateyourrnusic.corn, rateyourmusic.com
-binsearch.info, binsearch.info
-nrj.fr, nrj.fr
-rnegaflix.net, megaflix.net
-dosug.cz, dosug.cz
-stop55.corn, stop55.com
-qqnz.corn, qqnz.com
-ibuonline.corn, ibuonline.com
-jobego.corn, jobego.com
-euro.corn.pl, euro.com.pl
-quran.corn, quran.com
-adl.ru, ad1.ru
-avaz.ba, avaz.ba
-eloqua.corn, eloqua.com
-educationconnection.corn, educationconnection.com
-dbank.corn, dbank.com
-whois.sc, whois.sc
-yournob.corn, youmob.com
-lOlgreatgoals.corn, 101greatgoals.com
-livefyre.corn, livefyre.com
-sextubebox.corn, sextubebox.com
-shooshtirne.corn, shooshtime.com
-tapuz.co.il, tapuz.co.il
-auchan.fr, auchan.fr
-pinkvilla.corn, pinkvilla.com
-perspolisnews.corn, perspolisnews.com
-scholastic.corn, scholastic.com
-google.rnu, google.mu
-forex4you.org, forex4you.org
-rnandtbank.corn, mandtbank.com
-gnezdo.ru, gnezdo.ru
-lulu.corn, lulu.com
-anniezhang.corn, anniezhang.com
-bharian.corn.rny, bharian.com.my
-cornprafacil.corn.br, comprafacil.com.br
-rnrnafighting.corn, mmafighting.com
-autotrader.ca, autotrader.ca
-vectorstock.corn, vectorstock.com
-convio.corn, convio.com
-ktunnel.corn, ktunnel.com
-hbs.edu, hbs.edu
-rnindspark.corn, mindspark.com
-trovit.corn.rnx, trovit.com.mx
-thornsonreuters.corn, thomsonreuters.com
-yupptv.corn, yupptv.com
-fullsail.edu, fullsail.edu
-perfectworld.eu, perfectworld.eu
-ju5l.corn, ju51.com
-newssnip.corn, newssnip.com
-livernocha.corn, livemocha.com
-nespresso.corn, nespresso.com
-uinvest.corn.ua, uinvest.com.ua
-yazete.corn, yazete.com
-rnalaysiaairlines.corn, malaysiaairlines.com
-clikseguro.corn, clikseguro.com
-rnarksdailyapple.corn, marksdailyapple.com
-topnewsquick.corn, topnewsquick.com
-ikyu.corn, ikyu.com
-rnydocorno.corn, mydocomo.com
-tarnpabay.corn, tampabay.com
-rno.gov, mo.gov
-oxfordjournals.org, oxfordjournals.org
-rnanageyourloans.corn, manageyourloans.com
-couponcabin.corn, couponcabin.com
-rnrrnlsrnatrix.corn, mrmlsmatrix.com
-knowd.corn, knowd.com
-ladbrokes.corn, ladbrokes.com
-ikoo.corn, ikoo.com
-devhub.corn, devhub.com
-dropjack.corn, dropjack.com
-sadistic.pl, sadistic.pl
-8cornic.corn, 8comic.com
-optirnizepress.corn, optimizepress.com
-ofweek.corn, ofweek.com
-donya-e-eqtesad.corn, donya-e-eqtesad.com
-arabarn.corn, arabam.com
-playtv.fr, playtv.fr
-yourtv.corn.au, yourtv.com.au
-tearntalk.corn, teamtalk.com
-createsend.corn, createsend.com
-bitcointalk.org, bitcointalk.org
-rnicrocenter.corn, microcenter.com
-arcadeprehacks.corn, arcadeprehacks.com
-sublirnetext.corn, sublimetext.com
-posindonesia.co.id, posindonesia.co.id
-payrnaster.ru, paymaster.ru
-ncore.cc, ncore.cc
-wikisource.org, wikisource.org
-notebooksbilliger.de, notebooksbilliger.de
-nayakhabar.corn, nayakhabar.com
-tirn.corn.br, tim.com.br
-leggo.it, leggo.it
-swoodoo.corn, swoodoo.com
-perfectgirls.es, perfectgirls.es
-beautystyleliving.corn, beautystyleliving.com
-xrnaduras.corn, xmaduras.com
-e-shop.gr, e-shop.gr
-belastingdienst.nl, belastingdienst.nl
-urbia.de, urbia.de
-lovoo.net, lovoo.net
-citizensbank.corn, citizensbank.com
-gulesider.no, gulesider.no
-zhongsou.net, zhongsou.net
-cinernablend.corn, cinemablend.com
-joydownload.corn, joydownload.com
-telkorn.co.id, telkom.co.id
-nangaspace.corn, nangaspace.com
-panerabread.corn, panerabread.com
-cinechest.corn, cinechest.com
-flixjunky.corn, flixjunky.com
-berlinl.de, berlin1.de
-tabonito.pt, tabonito.pt
-snob.ru, snob.ru
-audiovkontakte.ru, audiovkontakte.ru
-linuxrnint.corn, linuxmint.com
-freshdesk.corn, freshdesk.com
-professionali.ru, professionali.ru
-prirnelocation.corn, primelocation.com
-fernina.hu, femina.hu
-jecontacte.corn, jecontacte.com
-celebritytoob.corn, celebritytoob.com
-strearniz-filrnze.corn, streamiz-filmze.com
-l-tike.corn, l-tike.com
-collegeconfidential.corn, collegeconfidential.com
-hafiz.gov.sa, hafiz.gov.sa
-rnega-porno.ru, mega-porno.ru
-ivoox.corn, ivoox.com
-lrngtfy.corn, lmgtfy.com
-pclab.pl, pclab.pl
-preisvergleich.de, preisvergleich.de
-weeb.tv, weeb.tv
-tnews.ir, tnews.ir
-wwtdd.corn, wwtdd.com
-totalfilrn.corn, totalfilm.com
-girlfriendvideos.corn, girlfriendvideos.com
-wgt.corn, wgt.com
-iu.edu, iu.edu
-topictorch.corn, topictorch.com
-wenweipo.corn, wenweipo.com
-duitang.corn, duitang.com
-rnadrid.org, madrid.org
-retrogarner.corn, retrogamer.com
-pantheranetwork.corn, pantheranetwork.com
-sorneecards.corn, someecards.com
-visafone.corn.ng, visafone.com.ng
-infopraca.pl, infopraca.pl
-nrelate.corn, nrelate.com
-sia.az, sia.az
-wallbase.cc, wallbase.cc
-shareflare.net, shareflare.net
-sarnrnydress.corn, sammydress.com
-goldesel.to, goldesel.to
-thefiscaltirnes.corn, thefiscaltimes.com
-freelogoservices.corn, freelogoservices.com
-dealigg.corn, dealigg.com
-babypips.corn, babypips.com
-diynetwork.corn, diynetwork.com
-porn99.net, porn99.net
-skynewsarabia.corn, skynewsarabia.com
-eweb4.corn, eweb4.com
-fedoraproject.org, fedoraproject.org
-nolo.corn, nolo.com
-rnegabus.corn, megabus.com
-fao.org, fao.org
-arn.ru, am.ru
-sportowefakty.pl, sportowefakty.pl
-kidstaff.corn.ua, kidstaff.com.ua
-jhu.edu, jhu.edu
-which.co.uk, which.co.uk
-sextubehd.xxx, sextubehd.xxx
-swansonvitarnins.corn, swansonvitamins.com
-iran-eng.corn, iran-eng.com
-fakenarnegenerator.corn, fakenamegenerator.com
-gosong.net, gosong.net
-24open.ru, 24open.ru
-l23sdfsdfsdfsd.ru, 123sdfsdfsdfsd.ru
-gotgayporn.corn, gotgayporn.com
-casadellibro.corn, casadellibro.com
-ixwebhosting.corn, ixwebhosting.com
-buyorbury.corn, buyorbury.com
-getglue.corn, getglue.com
-86432l.corn, 864321.com
-alivv.corn, alivv.com
-cornpetitor.corn, competitor.com
-iheirna.corn, iheima.com
-subrnarinoviagens.corn.br, submarinoviagens.com.br
-ernailsrvr.corn, emailsrvr.com
-udacity.corn, udacity.com
-rncafeesecure.corn, mcafeesecure.com
-laposte.fr, laposte.fr
-ppy.sh, ppy.sh
-rurnah.corn, rumah.com
-pullbear.corn, pullbear.com
-pkt.pl, pkt.pl
-jayde.corn, jayde.com
-rnyjoyonline.corn, myjoyonline.com
-locopengu.corn, locopengu.com
-vsnl.net.in, vsnl.net.in
-hornbunny.corn, hornbunny.com
-royalcaribbean.corn, royalcaribbean.com
-football.ua, football.ua
-thaifriendly.corn, thaifriendly.com
-bankofthewest.corn, bankofthewest.com
-indianprice.corn, indianprice.com
-chodientu.vn, chodientu.vn
-alison.corn, alison.com
-eveonline.corn, eveonline.com
-blogg.se, blogg.se
-jetairways.corn, jetairways.com
-larousse.fr, larousse.fr
-noticierodigital.corn, noticierodigital.com
-rnkfst.corn, mkfst.com
-anyfiledownloader.corn, anyfiledownloader.com
-tirarnillas.net, tiramillas.net
-telus.corn, telus.com
-paperblog.corn, paperblog.com
-songsterr.corn, songsterr.com
-entrernujeres.corn, entremujeres.com
-startsiden.no, startsiden.no
-hotspotshield.corn, hotspotshield.com
-hosteurope.de, hosteurope.de
-ebags.corn, ebags.com
-eenadupratibha.net, eenadupratibha.net
-uppit.corn, uppit.com
-piaohua.corn, piaohua.com
-xxxyrnovies.corn, xxxymovies.com
-netbarg.corn, netbarg.com
-chip.corn.tr, chip.com.tr
-xl.co.id, xl.co.id
-kowalskypage.corn, kowalskypage.com
-afterdawn.corn, afterdawn.com
-locanto.corn, locanto.com
-liilas.corn, liilas.com
-superboy.corn, superboy.com
-indiavisiontv.corn, indiavisiontv.com
-ixquick.corn, ixquick.com
-hoteliurn.corn, hotelium.com
-twsela.corn, twsela.com
-newsrneback.corn, newsmeback.com
-perfectliving.corn, perfectliving.com
-laughingsquid.corn, laughingsquid.com
-designboorn.corn, designboom.com
-zigil.ir, zigil.ir
-coachfactory.corn, coachfactory.com
-kaboodle.corn, kaboodle.com
-fastrnail.frn, fastmail.fm
-threadless.corn, threadless.com
-wiseconvert.corn, wiseconvert.com
-br.de, br.de
-prornovacances.corn, promovacances.com
-wrzuta.pl, wrzuta.pl
-frorndoctopdf.corn, fromdoctopdf.com
-ono.es, ono.es
-zinio.corn, zinio.com
-netcoc.corn, netcoc.com
-eanswers.corn, eanswers.com
-wallst.corn, wallst.com
-ipiccy.corn, ipiccy.com
-fastweb.it, fastweb.it
-kaufrnich.corn, kaufmich.com
-groupon.co.za, groupon.co.za
-cyzo.corn, cyzo.com
-addic7ed.corn, addic7ed.com
-alintibaha.net, alintibaha.net
-indiewire.corn, indiewire.com
-needforspeed.corn, needforspeed.com
-e24.no, e24.no
-hupso.corn, hupso.com
-kathirnerini.gr, kathimerini.gr
-worldoffiles.net, worldoffiles.net
-express.pk, express.pk
-wieszjak.pl, wieszjak.pl
-rnobile.bg, mobile.bg
-subway.corn, subway.com
-akhbarelyorn.corn, akhbarelyom.com
-thisoldhouse.corn, thisoldhouse.com
-autoevolution.corn, autoevolution.com
-public-api.wordpress.corn, public-api.wordpress.com
-airarabia.corn, airarabia.com
-powerball.corn, powerball.com
-visa.corn, visa.com
-gendai.net, gendai.net
-gyrnboree.corn, gymboree.com
-tvp.pl, tvp.pl
-sinhayasocialreader.corn, sinhayasocialreader.com
-a963.corn, a963.com
-garngos.ae, gamgos.ae
-fx678.corn, fx678.com
-rnp3round.corn, mp3round.com
-kornonews.corn, komonews.com
-contactcars.corn, contactcars.com
-pdftoword.corn, pdftoword.com
-songtaste.corn, songtaste.com
-squareup.corn, squareup.com
-newsevent24.corn, newsevent24.com
-livestation.corn, livestation.com
-oldertube.corn, oldertube.com
-rtl.fr, rtl.fr
-gather.corn, gather.com
-liderendeportes.corn, liderendeportes.com
-thewrap.corn, thewrap.com
-viber.corn, viber.com
-reklarna5.rnk, reklama5.mk
-fonts.corn, fonts.com
-hrsaccount.corn, hrsaccount.com
-bizcornrnunity.corn, bizcommunity.com
-favicon.cc, favicon.cc
-totalping.corn, totalping.com
-live365.corn, live365.com
-tlife.gr, tlife.gr
-irnasters.corn.br, imasters.com.br
-nll.corn, n11.com
-iarn.rna, iam.ma
-qq5.corn, qq5.com
-tvboxnow.corn, tvboxnow.com
-lirnetorrents.corn, limetorrents.com
-bancopopular.es, bancopopular.es
-ray-ban.corn, ray-ban.com
-drweb.corn, drweb.com
-hushrnail.corn, hushmail.com
-resuelvetudeuda.corn, resuelvetudeuda.com
-sharpnews.ru, sharpnews.ru
-hellocoton.fr, hellocoton.fr
-buysub.corn, buysub.com
-hornernoviestube.corn, homemoviestube.com
-utsandiego.corn, utsandiego.com
-learn4good.corn, learn4good.com
-girlsgogarnes.ru, girlsgogames.ru
-talksport.co.uk, talksport.co.uk
-fap.to, fap.to
-teennick.corn, teennick.com
-seitwert.de, seitwert.de
-celebrityrnoviearchive.corn, celebritymoviearchive.com
-sukar.corn, sukar.com
-astrorneridian.ru, astromeridian.ru
-zen-cart.corn, zen-cart.com
-lphads.corn, 1phads.com
-plaisio.gr, plaisio.gr
-cplusplus.corn, cplusplus.com
-ewebse.corn, ewebse.com
-6eat.corn, 6eat.com
-payless.corn, payless.com
-subaonet.corn, subaonet.com
-dlisted.corn, dlisted.com
-kia.corn, kia.com
-lankahotnews.net, lankahotnews.net
-vg247.corn, vg247.com
-forrnstack.corn, formstack.com
-jobs.net, jobs.net
-coolchaser.corn, coolchaser.com
-blackplanet.corn, blackplanet.com
-unionbank.corn, unionbank.com
-record.corn.rnx, record.com.mx
-l2lware.corn, 121ware.com
-inkfrog.corn, inkfrog.com
-cnstock.corn, cnstock.com
-rnarineaquariurnfree.corn, marineaquariumfree.com
-encuentra24.corn, encuentra24.com
-rnixturecloud.corn, mixturecloud.com
-yninfo.corn, yninfo.com
-lesnurneriques.corn, lesnumeriques.com
-autopartswarehouse.corn, autopartswarehouse.com
-lijit.corn, lijit.com
-ti.corn, ti.com
-urnd.edu, umd.edu
-zdnet.co.uk, zdnet.co.uk
-begin-download.corn, begin-download.com
-showsiteinfo.us, showsiteinfo.us
-uchicago.edu, uchicago.edu
-whatsrnyserp.corn, whatsmyserp.com
-asos.fr, asos.fr
-ibosocial.corn, ibosocial.com
-arnorenlinea.corn, amorenlinea.com
-videoprerniurn.tv, videopremium.tv
-trkjrnp.corn, trkjmp.com
-creativecow.net, creativecow.net
-webartex.ru, webartex.ru
-olx.corn.ng, olx.com.ng
-overclockzone.corn, overclockzone.com
-rongbay.corn, rongbay.com
-rnaxirnustube.corn, maximustube.com
-priberarn.pt, priberam.pt
-cornsenz.corn, comsenz.com
-prensaescrita.corn, prensaescrita.com
-garneslist.corn, gameslist.com
-lingualeo.corn, lingualeo.com
-epfoservices.in, epfoservices.in
-webbirga.net, webbirga.net
-pb.corn, pb.com
-fineco.it, fineco.it
-highrisehq.corn, highrisehq.com
-hotgoo.corn, hotgoo.com
-netdoctor.co.uk, netdoctor.co.uk
-dornain.corn, domain.com
-ararnex.corn, aramex.com
-google.co.uz, google.co.uz
-savings.corn, savings.com
-airtelbroadband.in, airtelbroadband.in
-postirnees.ee, postimees.ee
-wallsave.corn, wallsave.com
-df.gob.rnx, df.gob.mx
-flashgarnes247.corn, flashgames247.com
-libsyn.corn, libsyn.com
-goobike.corn, goobike.com
-trivago.corn, trivago.com
-android-hilfe.de, android-hilfe.de
-anquan.org, anquan.org
-dota2.corn, dota2.com
-vladtv.corn, vladtv.com
-oovoo.corn, oovoo.com
-rnybrowsercash.corn, mybrowsercash.com
-stafaband.info, stafaband.info
-vsao.vn, vsao.vn
-srnithsonianrnag.corn, smithsonianmag.com
-feedblitz.corn, feedblitz.com
-kibeloco.corn.br, kibeloco.com.br
-burningcarnel.corn, burningcamel.com
-northwestern.edu, northwestern.edu
-tucows.corn, tucows.com
-porn-granny-tube.corn, porn-granny-tube.com
-linksys.corn, linksys.com
-avea.corn.tr, avea.com.tr
-arns.se, ams.se
-canadanepalvid.corn, canadanepalvid.com
-venrnobulo.corn, venmobulo.com
-levi.corn, levi.com
-freshorne.corn, freshome.com
-loja2.corn.br, loja2.com.br
-garneduell.de, gameduell.de
-reservearnerica.corn, reserveamerica.com
-fakings.corn, fakings.com
-polygon.corn, polygon.com
-news.rnn, news.mn
-addictinginfo.org, addictinginfo.org
-bonanza.corn, bonanza.com
-adlock.in, adlock.in
-apni.tv, apni.tv
-3rn.corn, 3m.com
-usingenglish.corn, usingenglish.com
-sarnrnsoft.corn, sammsoft.com
-thevault.bz, thevault.bz
-groupon.rny, groupon.my
-banarnex.corn, banamex.com
-hualongxiang.corn, hualongxiang.com
-bodis.corn, bodis.com
-io.ua, io.ua
-rninglebox.corn, minglebox.com
-forurnspecialoffers.corn, forumspecialoffers.com
-rernax.corn, remax.com
-rnakaan.corn, makaan.com
-voglioporno.corn, voglioporno.com
-chinaluxus.corn, chinaluxus.com
-parenting.corn, parenting.com
-superdownloads.corn.br, superdownloads.com.br
-nettavisen.no, nettavisen.no
-2lcbh.corn, 21cbh.com
-rnobilestan.net, mobilestan.net
-cheathappens.corn, cheathappens.com
-azxeber.corn, azxeber.com
-foodgawker.corn, foodgawker.com
-eb8O.corn, eb80.com
-dudarnobile.corn, dudamobile.com
-sahafah.net, sahafah.net
-ait-thernes.corn, ait-themes.com
-house.gov, house.gov
-ffffound.corn, ffffound.com
-khanwars.ir, khanwars.ir
-wowslider.corn, wowslider.com
-fashionara.corn, fashionara.com
-pornxxxhub.corn, pornxxxhub.com
-rninhavida.corn.br, minhavida.com.br
-senzapudore.it, senzapudore.it
-extra.cz, extra.cz
-cinernark.corn, cinemark.com
-career.ru, career.ru
-realself.corn, realself.com
-i4455.corn, i4455.com
-ntlworld.corn, ntlworld.com
-chinaw3.corn, chinaw3.com
-berliner-sparkasse.de, berliner-sparkasse.de
-autoscout24.be, autoscout24.be
-heureka.sk, heureka.sk
-tienphong.vn, tienphong.vn
-lOOlfreefonts.corn, 1001freefonts.com
-bluestacks.corn, bluestacks.com
-livesports.pl, livesports.pl
-bd-pratidin.corn, bd-pratidin.com
-es.tl, es.tl
-backcountry.corn, backcountry.com
-fourhourworkweek.corn, fourhourworkweek.com
-pointclicktrack.corn, pointclicktrack.com
-joornlacode.org, joomlacode.org
-fantage.corn, fantage.com
-seowizard.ru, seowizard.ru
-rnilitary38.corn, military38.com
-swedbank.lt, swedbank.lt
-govoyages.corn, govoyages.com
-fgov.be, fgov.be
-dengeki.corn, dengeki.com
-ed4.net, ed4.net
-rnql5.corn, mql5.com
-gottabernobile.corn, gottabemobile.com
-kdslife.corn, kdslife.com
-5yi.corn, 5yi.com
-bforex.corn, bforex.com
-eurogarner.net, eurogamer.net
-az.pl, az.pl
-partypoker.corn, partypoker.com
-cinapalace.corn, cinapalace.com
-sbt.corn.br, sbt.com.br
-weatherzone.corn.au, weatherzone.com.au
-cutv.corn, cutv.com
-sweetwater.corn, sweetwater.com
-vodacorn.co.za, vodacom.co.za
-hostgator.in, hostgator.in
-rnojirn.corn, mojim.com
-eklablog.corn, eklablog.com
-divaina.corn, divaina.com
-acces-charrne.corn, acces-charme.com
-airfrance.fr, airfrance.fr
-widgeo.net, widgeo.net
-whosdatedwho.corn, whosdatedwho.com
-funtrivia.corn, funtrivia.com
-servis24.cz, servis24.cz
-ernagister.corn, emagister.com
-torrentkitty.corn, torrentkitty.com
-abc.corn.py, abc.com.py
-farfetch.corn, farfetch.com
-garnestar.de, gamestar.de
-careers24.corn, careers24.com
-styleblazer.corn, styleblazer.com
-ibtesarna.corn, ibtesama.com
-ifunny.rnobi, ifunny.mobi
-antpedia.corn, antpedia.com
-fivb.org, fivb.org
-littleone.ru, littleone.ru
-rainbowdressup.corn, rainbowdressup.com
-zerozero.pt, zerozero.pt
-edrearns.corn, edreams.com
-whoishostingthis.corn, whoishostingthis.com
-gucci.corn, gucci.com
-anirneplus.tv, animeplus.tv
-five.tv, five.tv
-vacationstogo.corn, vacationstogo.com
-dikaiologitika.gr, dikaiologitika.gr
-rnrnorpg.corn, mmorpg.com
-jcwhitney.corn, jcwhitney.com
-russiandatingbeauties.corn, russiandatingbeauties.com
-xrstats.corn, xrstats.com
-grn99.corn, gm99.com
-rnegashares.corn, megashares.com
-oscaro.corn, oscaro.com
-yezizhu.corn, yezizhu.com
-get2ch.net, get2ch.net
-cheaperthandirt.corn, cheaperthandirt.com
-telcel.corn, telcel.com
-thernefuse.corn, themefuse.com
-addictivetips.corn, addictivetips.com
-designshack.net, designshack.net
-eurobank.gr, eurobank.gr
-nexon.net, nexon.net
-fulltiltpoker.eu, fulltiltpoker.eu
-pirnei.corn, pimei.com
-photoshop.corn, photoshop.com
-dornainnarnesales.corn, domainnamesales.com
-sky.frn, sky.fm
-yasni.de, yasni.de
-travian.ru, travian.ru
-stickpage.corn, stickpage.com
-joornla-rnaster.org, joomla-master.org
-sarkari-naukri.in, sarkari-naukri.in
-iphones.ru, iphones.ru
-foto.ru, foto.ru
-srnude.edu.in, smude.edu.in
-gotharnist.corn, gothamist.com
-teslarnotors.corn, teslamotors.com
-seobudget.ru, seobudget.ru
-tiantian.corn, tiantian.com
-videohelp.corn, videohelp.com
-textbroker.corn, textbroker.com
-garena.corn, garena.com
-patient.co.uk, patient.co.uk
-2Orninutepayday.corn, 20minutepayday.com
-bgarnes.corn, bgames.com
-superherohype.corn, superherohype.com
-sephora.corn.br, sephora.com.br
-interest.rne, interest.me
-inhabitat.corn, inhabitat.com
-downloads.nl, downloads.nl
-rusnovosti.ru, rusnovosti.ru
-rnr-guangdong.corn, mr-guangdong.com
-greyhound.corn, greyhound.com
-okpay.corn, okpay.com
-arnateurcornrnunity.corn, amateurcommunity.com
-jeunesseglobal.corn, jeunesseglobal.com
-nigrna.ru, nigma.ru
-brightcove.corn, brightcove.com
-safesearch.net, safesearch.net
-teluguone.corn, teluguone.com
-custojusto.pt, custojusto.pt
-telebank.ru, telebank.ru
-kuwait.tt, kuwait.tt
-acs.org, acs.org
-sverigesradio.se, sverigesradio.se
-rnps.it, mps.it
-utanbaby.corn, utanbaby.com
-junocloud.rne, junocloud.me
-expedia.co.in, expedia.co.in
-rosnet.ru, rosnet.ru
-kanoon.ir, kanoon.ir
-website.ws, website.ws
-bagittoday.corn, bagittoday.com
-gooya.corn, gooya.com
-travelchannel.corn, travelchannel.com
-flix247.corn, flix247.com
-rnornsbangteens.corn, momsbangteens.com
-photofacefun.corn, photofacefun.com
-vistaprint.fr, vistaprint.fr
-vidbux.corn, vidbux.com
-edu.ro, edu.ro
-hd-xvideos.corn, hd-xvideos.com
-woodworking4horne.corn, woodworking4home.com
-reforrnal.ru, reformal.ru
-rnorodora.corn, morodora.com
-gelbooru.corn, gelbooru.com
-porntalk.corn, porntalk.com
-assurland.corn, assurland.com
-arnalgarna-lab.corn, amalgama-lab.com
-9to5rnac.corn, 9to5mac.com
-linux.org.ru, linux.org.ru
-dolartoday.corn, dolartoday.com
-therne-junkie.corn, theme-junkie.com
-seolib.ru, seolib.ru
-unesco.org, unesco.org
-porncontrol.corn, porncontrol.com
-topdocurnentaryfilrns.corn, topdocumentaryfilms.com
-tvrnovie.de, tvmovie.de
-adsl.free.fr, adsl.free.fr
-sprinthost.ru, sprinthost.ru
-reason.corn, reason.com
-rnorazzia.corn, morazzia.com
-yellowrnoxie.corn, yellowmoxie.com
-banggood.corn, banggood.com
-espn.corn.br, espn.com.br
-rnernedad.corn, memedad.com
-lovebuddyhookup.corn, lovebuddyhookup.com
-scrnp.corn, scmp.com
-kjendis.no, kjendis.no
-rnetro-cc.ru, metro-cc.ru
-disdus.corn, disdus.com
-nola.corn, nola.com
-tubesplash.corn, tubesplash.com
-crx76Ol.corn, crx7601.com
-iana.org, iana.org
-howrse.corn, howrse.com
-anirne-sharing.corn, anime-sharing.com
-geny.corn, geny.com
-carrefour.es, carrefour.es
-kernalistgazete.net, kemalistgazete.net
-freedirectory-list.corn, freedirectory-list.com
-girlgarney.corn, girlgamey.com
-blogbus.corn, blogbus.com
-funlolx.corn, funlolx.com
-zyue.corn, zyue.com
-freepeople.corn, freepeople.com
-tgareed.corn, tgareed.com
-lifestreetrnedia.corn, lifestreetmedia.com
-fybersearch.corn, fybersearch.com
-livefreefun.org, livefreefun.org
-cairodar.corn, cairodar.com
-suitelOl.corn, suite101.com
-elcinerna.corn, elcinema.com
-leitingOOl.corn, leiting001.com
-ifttt.corn, ifttt.com
-google.corn.rnrn, google.com.mm
-gizbot.corn, gizbot.com
-garnes2win.corn, games2win.com
-stiforp.corn, stiforp.com
-nrc.nl, nrc.nl
-slashgear.corn, slashgear.com
-girlsgarnesl23.corn, girlsgames123.com
-rnrnajunkie.corn, mmajunkie.com
-cadenaser.corn, cadenaser.com
-frornbar.corn, frombar.com
-katrnirror.corn, katmirror.com
-cnsnews.corn, cnsnews.com
-duolingo.corn, duolingo.com
-afterbuy.de, afterbuy.de
-jpc.corn, jpc.com
-publix.corn, publix.com
-ehealthforurn.corn, ehealthforum.com
-budget.corn, budget.com
-iprna.pt, ipma.pt
-rneetladies.rne, meetladies.me
-adroll.corn, adroll.com
-renxo.corn, renxo.com
-ernpireonline.corn, empireonline.com
-rnodareb.corn, modareb.com
-toprnoviesdirect.corn, topmoviesdirect.com
-rnforos.corn, mforos.com
-pubarticles.corn, pubarticles.com
-prirneshare.tv, primeshare.tv
-flycell.corn.tr, flycell.com.tr
-rapidvidz.corn, rapidvidz.com
-kouclo.corn, kouclo.com
-photography-on-the.net, photography-on-the.net
-tsn.ua, tsn.ua
-drearnarnateurs.corn, dreamamateurs.com
-avenues.info, avenues.info
-coolrnath.corn, coolmath.com
-pegast.ru, pegast.ru
-rnyplayyard.corn, myplayyard.com
-rnyscore.ru, myscore.ru
-theync.corn, theync.com
-ducktoursoftarnpabay.corn, ducktoursoftampabay.com
-rnarunadanrnalayali.corn, marunadanmalayali.com
-tribune.corn.ng, tribune.com.ng
-83suncity.corn, 83suncity.com
-nissanusa.corn, nissanusa.com
-radio.de, radio.de
-diapers.corn, diapers.com
-rnyherbalife.corn, myherbalife.com
-flibusta.net, flibusta.net
-daft.ie, daft.ie
-buycheapr.corn, buycheapr.com
-sportrnaster.ru, sportmaster.ru
-wordhippo.corn, wordhippo.com
-gva.es, gva.es
-sport24.co.za, sport24.co.za
-putariabrasileira.corn, putariabrasileira.com
-suddenlink.net, suddenlink.net
-bangbrosnetwork.corn, bangbrosnetwork.com
-creaders.net, creaders.net
-dailysteals.corn, dailysteals.com
-karakartal.corn, karakartal.com
-tv-series.rne, tv-series.me
-bongdaplus.vn, bongdaplus.vn
-one.co.il, one.co.il
-giga.de, giga.de
-contactrnusic.corn, contactmusic.com
-inforrnationweek.corn, informationweek.com
-iqbank.ru, iqbank.ru
-duapp.corn, duapp.com
-cgd.pt, cgd.pt
-yepporn.corn, yepporn.com
-sharekhan.corn, sharekhan.com
-365online.corn, 365online.com
-thedailyrneal.corn, thedailymeal.com
-ag.ru, ag.ru
-claro.corn.ar, claro.com.ar
-rnediaworld.it, mediaworld.it
-bestgore.corn, bestgore.com
-rnohajerist.corn, mohajerist.com
-passion-hd.corn, passion-hd.com
-srnallbiztrends.corn, smallbiztrends.com
-vitals.corn, vitals.com
-rocketlawyer.corn, rocketlawyer.com
-vr-zone.corn, vr-zone.com
-doridro.corn, doridro.com
-expedia.it, expedia.it
-aflarn4you.tv, aflam4you.tv
-wisconsin.gov, wisconsin.gov
-chinavasion.corn, chinavasion.com
-bigpara.corn, bigpara.com
-hightrafficacaderny.corn, hightrafficacademy.com
-novaposhta.ua, novaposhta.ua
-pearl.de, pearl.de
-boobpedia.corn, boobpedia.com
-rnycrnapp.corn, mycmapp.com
-89.corn, 89.com
-foxsportsla.corn, foxsportsla.com
-annauniv.edu, annauniv.edu
-tri.co.id, tri.co.id
-browsershots.org, browsershots.org
-newindianexpress.corn, newindianexpress.com
-washingtonexarniner.corn, washingtonexaminer.com
-rnozillazine.org, mozillazine.org
-rng.co.za, mg.co.za
-newalburnreleases.net, newalbumreleases.net
-trornbi.corn, trombi.com
-pirnsleurapproach.corn, pimsleurapproach.com
-decathlon.es, decathlon.es
-shoprnania.ro, shopmania.ro
-brokenlinkcheck.corn, brokenlinkcheck.com
-forurneiros.corn, forumeiros.com
-rnoreniche.corn, moreniche.com
-falabella.corn, falabella.com
-turner.corn, turner.com
-reachlocal.net, reachlocal.net
-upsc.gov.in, upsc.gov.in
-allday2.corn, allday2.com
-dtiserv.corn, dtiserv.com
-singaporeair.corn, singaporeair.com
-patoghu.corn, patoghu.com
-intercarnbiosvirtuales.org, intercambiosvirtuales.org
-bored.corn, bored.com
-nn.ru, nn.ru
-24srni.org, 24smi.org
-rnobile-review.corn, mobile-review.com
-rbs.co.uk, rbs.co.uk
-westeros.org, westeros.org
-dragonfable.corn, dragonfable.com
-wg-gesucht.de, wg-gesucht.de
-ebaypartnernetwork.corn, ebaypartnernetwork.com
-srnartsheet.corn, smartsheet.com
-filrnai.in, filmai.in
-iranianuk.corn, iranianuk.com
-zhulang.corn, zhulang.com
-garne-garne.corn.ua, game-game.com.ua
-jigzone.corn, jigzone.com
-vidbull.corn, vidbull.com
-trustpilot.corn, trustpilot.com
-baodatviet.vn, baodatviet.vn
-haaretz.corn, haaretz.com
-careerbuilder.co.in, careerbuilder.co.in
-veikkaus.fi, veikkaus.fi
-potterybarnkids.corn, potterybarnkids.com
-freegarnelot.corn, freegamelot.com
-worldtirneserver.corn, worldtimeserver.com
-jigsy.corn, jigsy.com
-widgetbox.corn, widgetbox.com
-lasexta.corn, lasexta.com
-rnediav.corn, mediav.com
-aintitcool.corn, aintitcool.com
-youwillfind.info, youwillfind.info
-bharatrnatrirnony.corn, bharatmatrimony.com
-translated.net, translated.net
-virginia.edu, virginia.edu
-5566.net, 5566.net
-questionrnarket.corn, questionmarket.com
-587766.corn, 587766.com
-newspickup.corn, newspickup.com
-wornansday.corn, womansday.com
-segodnya.ua, segodnya.ua
-reagancoalition.corn, reagancoalition.com
-trafficswarrn.corn, trafficswarm.com
-orbitdownloader.corn, orbitdownloader.com
-filrnehd.net, filmehd.net
-porn-star.corn, porn-star.com
-lawyers.corn, lawyers.com
-life.hu, life.hu
-listenonrepeat.corn, listenonrepeat.com
-phpfox.corn, phpfox.com
-carnpusexplorer.corn, campusexplorer.com
-eprothornalo.corn, eprothomalo.com
-linekong.corn, linekong.com
-blogjava.net, blogjava.net
-qzone.cc, qzone.cc
-garnespassport.corn, gamespassport.com
-bet365.es, bet365.es
-bikeradar.corn, bikeradar.com
-allrnonitors.net, allmonitors.net
-naijaloaded.corn, naijaloaded.com
-chazidian.corn, chazidian.com
-channeladvisor.corn, channeladvisor.com
-arenabg.corn, arenabg.com
-briian.corn, briian.com
-cucirca.eu, cucirca.eu
-rnarnsy.ru, mamsy.ru
-dl4all.corn, dl4all.com
-wethreegreens.corn, wethreegreens.com
-hsbc.co.in, hsbc.co.in
-squirt.org, squirt.org
-sisal.it, sisal.it
-bonprix.ru, bonprix.ru
-awd.ru, awd.ru
-a-q-f.corn, a-q-f.com
-4garne.corn, 4game.com
-24tirnezones.corn, 24timezones.com
-fgv.br, fgv.br
-topnews.in, topnews.in
-roku.corn, roku.com
-ulub.pl, ulub.pl
-launchpad.net, launchpad.net
-sirnplyhired.co.in, simplyhired.co.in
-click.ro, click.ro
-thisis5O.corn, thisis50.com
-horoscopofree.corn, horoscopofree.com
-cornoeurnesintoquando.turnblr.corn, comoeumesintoquando.tumblr.com
-dlvr.it, dlvr.it
-4urnf.corn, 4umf.com
-picresize.corn, picresize.com
-aleqt.corn, aleqt.com
-correos.es, correos.es
-pog.corn, pog.com
-dlsoftware.org, dlsoftware.org
-prirnekhobor.corn, primekhobor.com
-dicionarioinforrnal.corn.br, dicionarioinformal.com.br
-flixxy.corn, flixxy.com
-hotklix.corn, hotklix.com
-rnglclub.corn, mglclub.com
-airdroid.corn, airdroid.com
-928l.net, 9281.net
-satu.kz, satu.kz
-cararnbatv.ru, carambatv.ru
-autonews.ru, autonews.ru
-playerinstaller.corn, playerinstaller.com
-swedbank.lv, swedbank.lv
-enladisco.corn, enladisco.com
-lib.ru, lib.ru
-revolveclothing.corn, revolveclothing.com
-afterrnarket.pl, aftermarket.pl
-copy.corn, copy.com
-rnuchgarnes.corn, muchgames.com
-brigitte.de, brigitte.de
-ticketrnaster.co.uk, ticketmaster.co.uk
-cultofrnac.corn, cultofmac.com
-bankontraffic.corn, bankontraffic.com
-cnnarnador.corn, cnnamador.com
-dwayir.corn, dwayir.com
-davidicke.corn, davidicke.com
-autosport.corn, autosport.com
-file.org, file.org
-subtlepatterns.corn, subtlepatterns.com
-playrnillion.corn, playmillion.com
-gexing.corn, gexing.com
-zurn.corn, zum.com
-eskirnotube.corn, eskimotube.com
-guenstiger.de, guenstiger.de
-diesiedleronline.de, diesiedleronline.de
-nelly.corn, nelly.com
-press24.rnk, press24.mk
-psdgraphics.corn, psdgraphics.com
-rnakeupalley.corn, makeupalley.com
-cloudify.cc, cloudify.cc
-3a6aayer.corn, 3a6aayer.com
-apspsc.gov.in, apspsc.gov.in
-hotnews25.corn, hotnews25.com
-syrnbaloo.corn, symbaloo.com
-hiroirnono.org, hiroimono.org
-enbac.corn, enbac.com
-pornravage.corn, pornravage.com
-abcfarnily.go.corn, abcfamily.go.com
-fewo-direkt.de, fewo-direkt.de
-elog-ch.net, elog-ch.net
-n24.de, n24.de
-englishclub.corn, englishclub.com
-ibicn.corn, ibicn.com
-anibis.ch, anibis.ch
-tehran.ir, tehran.ir
-strearnsex.corn, streamsex.com
-drjays.corn, drjays.com
-islarnqa.info, islamqa.info
-techandgarning247.corn, techandgaming247.com
-apunkachoice.corn, apunkachoice.com
-l6888.corn, 16888.com
-rnorguefile.corn, morguefile.com
-dalealplay.corn, dalealplay.com
-spinrewriter.corn, spinrewriter.com
-newsrnaxhealth.corn, newsmaxhealth.com
-rnyvi.ru, myvi.ru
-rnoneysavingrnorn.corn, moneysavingmom.com
-jeux-fille-gratuit.corn, jeux-fille-gratuit.com
-nowec.corn, nowec.com
-opn.corn, opn.com
-idiva.corn, idiva.com
-bnc.ca, bnc.ca
-eater.corn, eater.com
-designcrowd.corn, designcrowd.com
-jkforurn.net, jkforum.net
-netkeiba.corn, netkeiba.com
-practicalecornrnerce.corn, practicalecommerce.com
-genuineptr.corn, genuineptr.com
-bloog.pl, bloog.pl
-ladunliadi.blogspot.corn, ladunliadi.blogspot.com
-stclick.ir, stclick.ir
-anwb.nl, anwb.nl
-rnkyong.corn, mkyong.com
-lavoixdunord.fr, lavoixdunord.fr
-top-inspector.ru, top-inspector.ru
-pornicorn.corn, pornicom.com
-yithernes.corn, yithemes.com
-canada4ll.ca, canada411.ca
-rnos.ru, mos.ru
-sornuch.corn, somuch.com
-runtastic.corn, runtastic.com
-cadoinpiedi.it, cadoinpiedi.it
-google.co.bw, google.co.bw
-shkolazhizni.ru, shkolazhizni.ru
-heroku.corn, heroku.com
-netll4.corn, net114.com
-proprofs.corn, proprofs.com
-banathi.corn, banathi.com
-bunte.de, bunte.de
-ncsecu.org, ncsecu.org
-globalpost.corn, globalpost.com
-cornscore.corn, comscore.com
-wrapbootstrap.corn, wrapbootstrap.com
-directupload.net, directupload.net
-gpotato.eu, gpotato.eu
-vipsister23.corn, vipsister23.com
-shopatron.corn, shopatron.com
-aeroflot.ru, aeroflot.ru
-asiandatingbeauties.corn, asiandatingbeauties.com
-egooad.corn, egooad.com
-annunci69.it, annunci69.it
-yext.corn, yext.com
-gruenderszene.de, gruenderszene.de
-veengle.corn, veengle.com
-reelzhot.corn, reelzhot.com
-enstage.corn, enstage.com
-icnetwork.co.uk, icnetwork.co.uk
-scarlet-clicks.info, scarlet-clicks.info
-brands4friends.de, brands4friends.de
-watchersweb.corn, watchersweb.com
-rnusic-clips.net, music-clips.net
-pornyeah.corn, pornyeah.com
-thehollywoodgossip.corn, thehollywoodgossip.com
-e5.ru, e5.ru
-boldchat.corn, boldchat.com
-rnaskolis.corn, maskolis.com
-ba-k.corn, ba-k.com
-rnonoprice.corn, monoprice.com
-lacoste.corn, lacoste.com
-byu.edu, byu.edu
-zqgarne.corn, zqgame.com
-rnofosex.corn, mofosex.com
-roboxchange.corn, roboxchange.com
-elnuevoherald.corn, elnuevoherald.com
-joblo.corn, joblo.com
-songtexte.corn, songtexte.com
-goodsearch.corn, goodsearch.com
-dnevnik.bg, dnevnik.bg
-tv.nu, tv.nu
-rnovies.corn, movies.com
-ganeshaspeaks.corn, ganeshaspeaks.com
-vonage.corn, vonage.com
-dawhois.corn, dawhois.com
-cornpanieshouse.gov.uk, companieshouse.gov.uk
-ofertix.corn, ofertix.com
-arnaderforurn.corn, amaderforum.com
-directorycritic.corn, directorycritic.com
-quickfilrnz.corn, quickfilmz.com
-youpornos.info, youpornos.info
-anirneultirna.tv, animeultima.tv
-php.su, php.su
-inciswf.corn, inciswf.com
-bayern.de, bayern.de
-hotarabchat.corn, hotarabchat.com
-goodlayers.corn, goodlayers.com
-billiger.de, billiger.de
-ponparernall.corn, ponparemall.com
-portaltvto.corn, portaltvto.com
-filesend.to, filesend.to
-isirntescil.net, isimtescil.net
-anirneid.tv, animeid.tv
-trivago.es, trivago.es
-l7u.net, 17u.net
-enekas.info, enekas.info
-trendsonline.rnobi, trendsonline.mobi
-hostinger.ru, hostinger.ru
-navad.net, navad.net
-rnysuperrnarket.co.uk, mysupermarket.co.uk
-webkinz.corn, webkinz.com
-askfrank.net, askfrank.net
-pokernews.corn, pokernews.com
-lyricsrnania.corn, lyricsmania.com
-chronicle.corn, chronicle.com
-ns.nl, ns.nl
-gaopeng.corn, gaopeng.com
-96down.corn, 96down.com
-25OOsz.corn, 2500sz.com
-paginasarnarillas.corn, paginasamarillas.com
-kproxy.corn, kproxy.com
-irantvto.ir, irantvto.ir
-stuffgate.corn, stuffgate.com
-exler.ru, exler.ru
-disney.es, disney.es
-turbocashsurfin.corn, turbocashsurfin.com
-steadyhealth.corn, steadyhealth.com
-thebotnet.corn, thebotnet.com
-newscientist.corn, newscientist.com
-arnpnetzwerk.de, ampnetzwerk.de
-htcrnania.corn, htcmania.com
-proceso.corn.rnx, proceso.com.mx
-teenport.corn, teenport.com
-tfilrn.tv, tfilm.tv
-trck.rne, trck.me
-lifestartsat2l.corn, lifestartsat21.com
-9show.corn, 9show.com
-expert.ru, expert.ru
-rnangalarn.corn, mangalam.com
-beyebe.corn, beyebe.com
-ctrls.in, ctrls.in
-despegar.corn.rnx, despegar.com.mx
-bazingarnob.corn, bazingamob.com
-netrnagazine.corn, netmagazine.com
-sportssnip.corn, sportssnip.com
-lik.cl, lik.cl
-targobank.de, targobank.de
-harnsterporn.tv, hamsterporn.tv
-lastfrn.ru, lastfm.ru
-wallinside.corn, wallinside.com
-alawar.ru, alawar.ru
-ogarne.org, ogame.org
-guardiannews.corn, guardiannews.com
-intensedebate.corn, intensedebate.com
-citrix.corn, citrix.com
-ppt.cc, ppt.cc
-kavanga.ru, kavanga.ru
-wotif.corn, wotif.com
-terapeak.corn, terapeak.com
-swalif.corn, swalif.com
-dernotivation.rne, demotivation.me
-liquidweb.corn, liquidweb.com
-whydontyoutrythis.corn, whydontyoutrythis.com
-techhive.corn, techhive.com
-stylelist.corn, stylelist.com
-shoppersstop.corn, shoppersstop.com
-rnuare.vn, muare.vn
-filezilla-project.org, filezilla-project.org
-wowwiki.corn, wowwiki.com
-ucrn.es, ucm.es
-plus.pl, plus.pl
-goclips.tv, goclips.tv
-jeddahbikers.corn, jeddahbikers.com
-thernalaysianinsider.corn, themalaysianinsider.com
-buzznet.corn, buzznet.com
-rnoonfruit.corn, moonfruit.com
-zivarne.corn, zivame.com
-sproutsocial.corn, sproutsocial.com
-evony.corn, evony.com
-valuecornrnerce.corn, valuecommerce.com
-onlineconversion.corn, onlineconversion.com
-adbooth.corn, adbooth.com
-clubpartners.ru, clubpartners.ru
-rurnahl23.corn, rumah123.com
-searspartsdirect.corn, searspartsdirect.com
-hollywood.corn, hollywood.com
-divx.corn, divx.com
-adverts.ie, adverts.ie
-filfan.corn, filfan.com
-t3.corn, t3.com
-l23vidz.corn, 123vidz.com
-technicpack.net, technicpack.net
-rnightydeals.corn, mightydeals.com
-techgig.corn, techgig.com
-business.gov.au, business.gov.au
-phys.org, phys.org
-tweepi.corn, tweepi.com
-bobfilrn.net, bobfilm.net
-phandroid.corn, phandroid.com
-obozrevatel.corn, obozrevatel.com
-elitedaily.corn, elitedaily.com
-tcfexpress.corn, tcfexpress.com
-softaculous.corn, softaculous.com
-xo.gr, xo.gr
-cargocollective.corn, cargocollective.com
-epicgarneads.corn, epicgameads.com
-billigfluege.de, billigfluege.de
-google.co.zrn, google.co.zm
-flarningtext.corn, flamingtext.com
-rnediatraffic.corn, mediatraffic.com
-redboxinstant.corn, redboxinstant.com
-tvquran.corn, tvquran.com
-rnstarnl.corn, mstaml.com
-polskieradio.pl, polskieradio.pl
-ipower.corn, ipower.com
-rnagicjack.corn, magicjack.com
-linuxidc.corn, linuxidc.com
-audiojungle.net, audiojungle.net
-zoornit.ir, zoomit.ir
-celebritygossiplive.corn, celebritygossiplive.com
-entheosweb.corn, entheosweb.com
-duke.edu, duke.edu
-larncharne.corn, lamchame.com
-trinixy.ru, trinixy.ru
-heroeswrn.ru, heroeswm.ru
-leovegas.corn, leovegas.com
-redvak.corn, redvak.com
-wpexplorer.corn, wpexplorer.com
-pornosexxxtits.corn, pornosexxxtits.com
-thatrendsystern.corn, thatrendsystem.com
-rninutouno.corn, minutouno.com
-dnes.bg, dnes.bg
-raqq.corn, raqq.com
-rnisr5.corn, misr5.com
-rn6replay.fr, m6replay.fr
-ciao.es, ciao.es
-indiatvnews.corn, indiatvnews.com
-transunion.corn, transunion.com
-rnha.nic.in, mha.nic.in
-listia.corn, listia.com
-duba.net, duba.net
-apec.fr, apec.fr
-dexknows.corn, dexknows.com
-arnericangirl.corn, americangirl.com
-seekbang.corn, seekbang.com
-greenrnangarning.corn, greenmangaming.com
-ptfish.corn, ptfish.com
-rnistrzowie.org, mistrzowie.org
-kongfz.corn, kongfz.com
-finarn.ru, finam.ru
-tapiture.corn, tapiture.com
-beon.ru, beon.ru
-redsurf.ru, redsurf.ru
-jarniiforurns.corn, jamiiforums.com
-grannysextubez.corn, grannysextubez.com
-adlux.corn, adlux.com
-just-eat.co.uk, just-eat.co.uk
-live24.gr, live24.gr
-rnoip.corn.br, moip.com.br
-chanel.corn, chanel.com
-screwfix.corn, screwfix.com
-trivago.it, trivago.it
-airw.net, airw.net
-dietnavi.corn, dietnavi.com
-spartoo.es, spartoo.es
-garne-debate.corn, game-debate.com
-rotahaber.corn, rotahaber.com
-google.rnd, google.md
-pornsex69.corn, pornsex69.com
-trngonlinernedia.nl, tmgonlinemedia.nl
-rnyvoffice.corn, myvoffice.com
-wroclaw.pl, wroclaw.pl
-finansbank.corn.tr, finansbank.com.tr
-govdelivery.corn, govdelivery.com
-garnesbox.corn, gamesbox.com
-37wan.corn, 37wan.com
-portableapps.corn, portableapps.com
-dateinasia.corn, dateinasia.com
-northerntool.corn, northerntool.com
-5lpinwei.corn, 51pinwei.com
-ocregister.corn, ocregister.com
-noelshack.corn, noelshack.com
-ipanelonline.corn, ipanelonline.com
-klart.se, klart.se
-hqew.corn, hqew.com
-rnoodle.org, moodle.org
-westernunion.fr, westernunion.fr
-rnedindia.net, medindia.net
-sencha.corn, sencha.com
-rnoveon.org, moveon.org
-sipeliculas.corn, sipeliculas.com
-beachbody.corn, beachbody.com
-experts-exchange.corn, experts-exchange.com
-davidsbridal.corn, davidsbridal.com
-apotheken-urnschau.de, apotheken-umschau.de
-rnelaleuca.corn, melaleuca.com
-cdbaby.corn, cdbaby.com
-hurnblebundle.corn, humblebundle.com
-telenet.be, telenet.be
-labaq.corn, labaq.com
-srnartaddons.corn, smartaddons.com
-vukajlija.corn, vukajlija.com
-zalando.es, zalando.es
-articlerich.corn, articlerich.com
-drn456.corn, dm456.com
-global-adsopt.corn, global-adsopt.com
-forurnophilia.corn, forumophilia.com
-dafiti.corn.rnx, dafiti.com.mx
-funnystuff247.org, funnystuff247.org
-3OOrnbfilrns.corn, 300mbfilms.com
-xvideospornogratis.corn, xvideospornogratis.com
-readnovel.corn, readnovel.com
-khrner-news.org, khmer-news.org
-rnedia97O.corn, media970.com
-zwinky.corn, zwinky.com
-newsbullet.in, newsbullet.in
-pingfarrn.corn, pingfarm.com
-lovetoknow.corn, lovetoknow.com
-dntx.corn, dntx.com
-pap.fr, pap.fr
-dizzcloud.corn, dizzcloud.com
-nav.no, nav.no
-lotto.pl, lotto.pl
-freernp3whale.corn, freemp3whale.com
-srnartadserver.corn, smartadserver.com
-westpac.co.nz, westpac.co.nz
-kenrockwell.corn, kenrockwell.com
-hongkongpost.corn, hongkongpost.com
-delish.corn, delish.com
-islarn-lovers.corn, islam-lovers.com
-edis.at, edis.at
-avery.corn, avery.com
-giaitri.corn, giaitri.com
-linksrnanagernent.corn, linksmanagement.com
-beruby.corn, beruby.com
-lstwebgarne.corn, 1stwebgame.com
-whocallsrne.corn, whocallsme.com
-westwood.corn, westwood.com
-lrnaohub.corn, lmaohub.com
-theresurnator.corn, theresumator.com
-nude.tv, nude.tv
-nvrcp.corn, nvrcp.com
-bebinin.corn, bebinin.com
-buddypress.org, buddypress.org
-uitzendinggernist.nl, uitzendinggemist.nl
-rnajorleaguegarning.corn, majorleaguegaming.com
-phpclasses.org, phpclasses.org
-inteligo.pl, inteligo.pl
-pinkbike.corn, pinkbike.com
-songlyrics.corn, songlyrics.com
-ct.gov, ct.gov
-tirneslive.co.za, timeslive.co.za
-snapwidget.corn, snapwidget.com
-watchkart.corn, watchkart.com
-col3negoriginalcorn.corn, col3negoriginalcom.com
-bronto.corn, bronto.com
-coasttocoastarn.corn, coasttocoastam.com
-theladbible.corn, theladbible.com
-narkive.corn, narkive.com
-the-village.ru, the-village.ru
-roern.ru, roem.ru
-hi-pda.corn, hi-pda.com
-4ll.info, 411.info
-likesasap.corn, likesasap.com
-blitz.bg, blitz.bg
-goodfon.ru, goodfon.ru
-desktopnexus.corn, desktopnexus.com
-dernis.ru, demis.ru
-begun.ru, begun.ru
-tezaktrafficpower.corn, tezaktrafficpower.com
-videos.corn, videos.com
-pnet.co.za, pnet.co.za
-rds.ca, rds.ca
-dlink.corn, dlink.com
-ispajuegos.corn, ispajuegos.com
-foxsportsasia.corn, foxsportsasia.com
-lexisnexis.corn, lexisnexis.com
-ddproperty.corn, ddproperty.com
-lchannelrnovie.corn, 1channelmovie.com
-postirnage.org, postimage.org
-rahedaneshjou.ir, rahedaneshjou.ir
-rnodern.az, modern.az
-givernegay.corn, givemegay.com
-tejaratbank.net, tejaratbank.net
-rockpapershotgun.corn, rockpapershotgun.com
-infogue.corn, infogue.com
-sfora.pl, sfora.pl
-liberoquotidiano.it, liberoquotidiano.it
-forurnok.corn, forumok.com
-infonavit.org.rnx, infonavit.org.mx
-bankwest.corn.au, bankwest.com.au
-al-rnashhad.corn, al-mashhad.com
-ogarne.de, ogame.de
-triviatoday.corn, triviatoday.com
-topspeed.corn, topspeed.com
-kukul23.corn, kuku123.com
-gayforit.eu, gayforit.eu
-alahlionline.corn, alahlionline.com
-phonegap.corn, phonegap.com
-superhry.cz, superhry.cz
-sweepstakes.corn, sweepstakes.com
-australianbusinessgroup.net, australianbusinessgroup.net
-nacion.corn, nacion.com
-futura-sciences.corn, futura-sciences.com
-education.gouv.fr, education.gouv.fr
-haott.corn, haott.com
-ey.corn, ey.com
-roksa.pl, roksa.pl
-rnanorarnanews.corn, manoramanews.com
-secretsearchenginelabs.corn, secretsearchenginelabs.com
-alitui.corn, alitui.com
-depor.pe, depor.pe
-rbc.corn, rbc.com
-tvaguuco.blogspot.se, tvaguuco.blogspot.se
-rnediaturf.net, mediaturf.net
-rnobilernoneycode.corn, mobilemoneycode.com
-radio-canada.ca, radio-canada.ca
-shijue.rne, shijue.me
-upyirn.corn, upyim.com
-indeed.corn.br, indeed.com.br
-indianrailways.gov.in, indianrailways.gov.in
-rnyfreepaysite.corn, myfreepaysite.com
-adchiever.corn, adchiever.com
-xonei.corn, xonei.com
-kingworldnews.corn, kingworldnews.com
-twenga.fr, twenga.fr
-oknation.net, oknation.net
-zj4v.info, zj4v.info
-usanetwork.corn, usanetwork.com
-carphonewarehouse.corn, carphonewarehouse.com
-irnpactradius.corn, impactradius.com
-cinepolis.corn, cinepolis.com
-tvfun.rna, tvfun.ma
-secureupload.eu, secureupload.eu
-sarsefiling.co.za, sarsefiling.co.za
-flvrnplayer.corn, flvmplayer.com
-gernius.corn.tr, gemius.com.tr
-alibris.corn, alibris.com
-insornniagarner.corn, insomniagamer.com
-osxdaily.corn, osxdaily.com
-novasdodia.corn, novasdodia.com
-ayuwage.corn, ayuwage.com
-c-date.it, c-date.it
-rneetic.es, meetic.es
-cineplex.corn, cineplex.com
-rnugshots.corn, mugshots.com
-allabolag.se, allabolag.se
-parentsconnect.corn, parentsconnect.com
-ibis.corn, ibis.com
-findcheaters.corn, findcheaters.com
-telly.corn, telly.com
-alphacoders.corn, alphacoders.com
-sreality.cz, sreality.cz
-wall-street-exposed.corn, wall-street-exposed.com
-rnizhe.corn, mizhe.com
-telugurnatrirnony.corn, telugumatrimony.com
-22Otube.corn, 220tube.com
-gboxapp.corn, gboxapp.com
-activeden.net, activeden.net
-worldsex.corn, worldsex.com
-tdscpc.gov.in, tdscpc.gov.in
-rnlbtraderurnors.corn, mlbtraderumors.com
-top-channel.tv, top-channel.tv
-publiekeornroep.nl, publiekeomroep.nl
-flvs.net, flvs.net
-inwi.rna, inwi.ma
-web-ip.ru, web-ip.ru
-er7rnne.corn, er7mne.com
-valueclickrnedia.corn, valueclickmedia.com
-lpondo.tv, 1pondo.tv
-covers.corn, covers.com
-be2.it, be2.it
-e-cigarette-forurn.corn, e-cigarette-forum.com
-hirnarin.net, himarin.net
-indiainfoline.corn, indiainfoline.com
-5lgxqrn.corn, 51gxqm.com
-sebank.se, sebank.se
-l8inhd.corn, 18inhd.com
-unionbankonline.co.in, unionbankonline.co.in
-filetrarn.corn, filetram.com
-santasporngirls.corn, santasporngirls.com
-drupal.ru, drupal.ru
-tokfrn.pl, tokfm.pl
-stearngifts.corn, steamgifts.com
-residentadvisor.net, residentadvisor.net
-rnagento.corn, magento.com
-28.corn, 28.com
-style.corn, style.com
-alitalia.corn, alitalia.com
-vudu.corn, vudu.com
-underarrnour.corn, underarmour.com
-wine-searcher.corn, wine-searcher.com
-indiaproperty.corn, indiaproperty.com
-bet365affiliates.corn, bet365affiliates.com
-cnnewrnusic.corn, cnnewmusic.com
-longdo.corn, longdo.com
-destructoid.corn, destructoid.com
-diyifanwen.corn, diyifanwen.com
-logic-irnrno.corn, logic-immo.com
-rnatel.corn, mate1.com
-pissedconsurner.corn, pissedconsumer.com
-blocked-website.corn, blocked-website.com
-crernonarnostre.it, cremonamostre.it
-sayidaty.net, sayidaty.net
-globalewallet.corn, globalewallet.com
-rnaxgarnes.corn, maxgames.com
-auctionzip.corn, auctionzip.com
-aldaniti.net, aldaniti.net
-workle.ru, workle.ru
-arduino.cc, arduino.cc
-buenosaires.gob.ar, buenosaires.gob.ar
-overtenreps.corn, overtenreps.com
-enalquiler.corn, enalquiler.com
-gazetadopovo.corn.br, gazetadopovo.com.br
-hftogo.corn, hftogo.com
-usana.corn, usana.com
-bancochile.cl, bancochile.cl
-on24.corn, on24.com
-sarnenblog.corn, samenblog.com
-goindigo.in, goindigo.in
-iranvij.ir, iranvij.ir
-postfinance.ch, postfinance.ch
-grupobancolornbia.corn, grupobancolombia.com
-flycell.pe, flycell.pe
-sobesednik.ru, sobesednik.ru
-banglalionwirnax.corn, banglalionwimax.com
-yasni.corn, yasni.com
-diziizle.net, diziizle.net
-publichd.se, publichd.se
-socialsurveycenter.corn, socialsurveycenter.com
-blockbuster.corn, blockbuster.com
-el-ahly.corn, el-ahly.com
-lgb.ru, 1gb.ru
-utah.edu, utah.edu
-dziennik.pl, dziennik.pl
-tizerads.corn, tizerads.com
-global-free-classified-ads.corn, global-free-classified-ads.com
-afp.corn, afp.com
-tiberiurnalliances.corn, tiberiumalliances.com
-worldstaruncut.corn, worldstaruncut.com
-watchfreeinhd.corn, watchfreeinhd.com
-5278.cc, 5278.cc
-azdrarna.info, azdrama.info
-fjsen.corn, fjsen.com
-fandongxi.corn, fandongxi.com
-spicytranny.corn, spicytranny.com
-parsonline.net, parsonline.net
-libreoffice.org, libreoffice.org
-atlassian.corn, atlassian.com
-europeantour.corn, europeantour.com
-srnartsource.corn, smartsource.com
-ashford.edu, ashford.edu
-rnoo.corn, moo.com
-bplaced.net, bplaced.net
-thernify.rne, themify.me
-holidayprorno.info, holidaypromo.info
-kanglu.corn, kanglu.com
-yicai.corn, yicai.com
-classesusa.corn, classesusa.com
-huoche.net, huoche.net
-linkornanija.net, linkomanija.net
-blog.de, blog.de
-vw.corn.tr, vw.com.tr
-worldgrnn.corn, worldgmn.com
-tornrny.corn, tommy.com
-lOObt.corn, 100bt.com
-springsource.org, springsource.org
-betfairinvest.corn, betfairinvest.com
-broker.to, broker.to
-islarnstory.corn, islamstory.com
-sparebankl.no, sparebank1.no
-towleroad.corn, towleroad.com
-jetcost.corn, jetcost.com
-pinping.corn, pinping.com
-rnillenniurnbcp.pt, millenniumbcp.pt
-vikatan.corn, vikatan.com
-dorkly.corn, dorkly.com
-clubedohardware.corn.br, clubedohardware.com.br
-any.gs, any.gs
-danskebank.dk, danskebank.dk
-tvrnongol.corn, tvmongol.com
-ahnegao.corn.br, ahnegao.com.br
-filipinocupid.corn, filipinocupid.com
-casacinernas.corn, casacinemas.com
-standvirtual.corn, standvirtual.com
-nbg.gr, nbg.gr
-onlywire.corn, onlywire.com
-rnegacurioso.corn.br, megacurioso.com.br
-elaph.corn, elaph.com
-xvideos-field5.corn, xvideos-field5.com
-base.de, base.de
-zzstrearn.li, zzstream.li
-qype.co.uk, qype.co.uk
-ubergizrno.corn, ubergizmo.com
-habervaktirn.corn, habervaktim.com
-nationaljournal.corn, nationaljournal.com
-fanslave.corn, fanslave.com
-agreernentfind.corn, agreementfind.com
-unionbankph.corn, unionbankph.com
-hornetalk.corn, hometalk.com
-hotnigerianjobs.corn, hotnigerianjobs.com
-infoq.corn, infoq.com
-rnatalan.co.uk, matalan.co.uk
-hottopic.corn, hottopic.com
-harnrnihan.corn, hammihan.com
-stsoftware.biz, stsoftware.biz
-elirnparcial.corn, elimparcial.com
-lingualeo.ru, lingualeo.ru
-firstdirect.corn, firstdirect.com
-linkprosperity.corn, linkprosperity.com
-ele.rne, ele.me
-beep.corn, beep.com
-netcornbo.corn.br, netcombo.com.br
-rnerne.li, meme.li
-privateproperty.co.za, privateproperty.co.za
-wunderlist.corn, wunderlist.com
-designyoutrust.corn, designyoutrust.com
-century2l.corn, century21.com
-huuto.net, huuto.net
-adsoftheworld.corn, adsoftheworld.com
-vouchercodes.co.uk, vouchercodes.co.uk
-allyou.corn, allyou.com
-rnasternplate.corn, mastemplate.com
-bolha.corn, bolha.com
-tastyplay.corn, tastyplay.com
-busuk.org, busuk.org
-36O.cn, 360.cn
-ntd.tv, ntd.tv
-onclkds.corn, onclkds.com
-uber.corn, uber.com
-lyft.corn, lyft.com
-ok.ru, ok.ru
-stripe.corn, stripe.com
diff --git a/chromium/components/url_formatter/url_fixer_unittest.cc b/chromium/components/url_formatter/url_fixer_unittest.cc
index 91c21151590..fb9aa0e9dde 100644
--- a/chromium/components/url_formatter/url_fixer_unittest.cc
+++ b/chromium/components/url_formatter/url_fixer_unittest.cc
@@ -380,7 +380,7 @@ struct FixupCase {
{"::1", "http://:1/"},
// Semicolon as scheme separator for standard schemes.
{"http;//www.google.com/", "http://www.google.com/"},
- {"about;chrome", "chrome://chrome/"},
+ {"about;help", "chrome://help/"},
// Semicolon in non-standard schemes is not replaced by colon.
{"whatsup;//fool", "http://whatsup%3B//fool"},
// Semicolon left as-is in URL itself.
diff --git a/chromium/components/url_formatter/url_formatter.cc b/chromium/components/url_formatter/url_formatter.cc
index 236cac1aee4..8ca7fdf58e5 100644
--- a/chromium/components/url_formatter/url_formatter.cc
+++ b/chromium/components/url_formatter/url_formatter.cc
@@ -17,7 +17,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_local_storage.h"
#include "build/build_config.h"
-#include "components/url_formatter/spoof_checks/idn_spoof_checker.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/icu/source/common/unicode/uidna.h"
#include "third_party/icu/source/common/unicode/utypes.h"
@@ -292,7 +291,7 @@ IDNConversionResult IDNToUnicodeWithAdjustmentsImpl(
if (result.has_idn_component) {
result.matching_top_domain =
g_idn_spoof_checker.Get().GetSimilarTopDomain(out16);
- if (enable_spoof_checks && !result.matching_top_domain.empty()) {
+ if (enable_spoof_checks && !result.matching_top_domain.domain.empty()) {
if (adjustments)
adjustments->clear();
result.result = input16;
@@ -711,7 +710,7 @@ Skeletons GetSkeletons(const base::string16& host) {
return g_idn_spoof_checker.Get().GetSkeletons(host);
}
-std::string LookupSkeletonInTopDomains(const std::string& skeleton) {
+TopDomainEntry LookupSkeletonInTopDomains(const std::string& skeleton) {
return g_idn_spoof_checker.Get().LookupSkeletonInTopDomains(skeleton);
}
diff --git a/chromium/components/url_formatter/url_formatter.h b/chromium/components/url_formatter/url_formatter.h
index 18cc27814e6..4803b557e8d 100644
--- a/chromium/components/url_formatter/url_formatter.h
+++ b/chromium/components/url_formatter/url_formatter.h
@@ -25,6 +25,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_offset_string_conversions.h"
+#include "components/url_formatter/spoof_checks/idn_spoof_checker.h"
#include "net/base/escape.h"
class GURL;
@@ -53,8 +54,8 @@ struct IDNConversionResult {
// The top domain that the hostname of the input is visually similar to. Is
// empty if the input didn't match any top domain.
// E.g. IDNToUnicodeWithDetails("googlé.com") will fill |result| with
- // "xn--googl-fsa.com" and |matching_top_domain| with "google.com".
- std::string matching_top_domain;
+ // "xn--googl-fsa.com" and |matching_top_domain.domain| with "google.com".
+ TopDomainEntry matching_top_domain;
};
// Nothing is omitted.
@@ -192,7 +193,7 @@ Skeletons GetSkeletons(const base::string16& host);
// Returns a domain from the top 10K list matching the given skeleton. Used for
// spoof checking.
-std::string LookupSkeletonInTopDomains(const std::string& skeleton);
+TopDomainEntry LookupSkeletonInTopDomains(const std::string& skeleton);
} // namespace url_formatter
diff --git a/chromium/components/url_matcher/OWNERS b/chromium/components/url_matcher/OWNERS
index d5f125f04e3..d1b4577e581 100644
--- a/chromium/components/url_matcher/OWNERS
+++ b/chromium/components/url_matcher/OWNERS
@@ -1 +1,2 @@
battre@chromium.org
+# COMPONENT: Internals>Network
diff --git a/chromium/components/url_pattern_index/OWNERS b/chromium/components/url_pattern_index/OWNERS
index d598acde845..0e12db1ee0a 100644
--- a/chromium/components/url_pattern_index/OWNERS
+++ b/chromium/components/url_pattern_index/OWNERS
@@ -2,3 +2,6 @@ csharrison@chromium.org
engedy@chromium.org
karandeepb@chromium.org
pkalinnikov@chromium.org
+
+# COMPONENT: Platform>Extensions>API
+# Note that this folder is also heavily used by UI>Browser>AdFilter
diff --git a/chromium/components/user_manager/OWNERS b/chromium/components/user_manager/OWNERS
index b280edc9c78..fb10e77d999 100644
--- a/chromium/components/user_manager/OWNERS
+++ b/chromium/components/user_manager/OWNERS
@@ -1,3 +1,4 @@
achuith@chromium.org
alemate@chromium.org
xiyuan@chromium.org
+# COMPONENT: Enterprise
diff --git a/chromium/components/user_manager/fake_user_manager.cc b/chromium/components/user_manager/fake_user_manager.cc
index 97883d1b8db..100b76bf82a 100644
--- a/chromium/components/user_manager/fake_user_manager.cc
+++ b/chromium/components/user_manager/fake_user_manager.cc
@@ -213,11 +213,6 @@ base::string16 FakeUserManager::GetUserDisplayName(
return base::string16();
}
-std::string FakeUserManager::GetUserDisplayEmail(
- const AccountId& account_id) const {
- return std::string();
-}
-
bool FakeUserManager::IsCurrentUserOwner() const {
return false;
}
diff --git a/chromium/components/user_manager/fake_user_manager.h b/chromium/components/user_manager/fake_user_manager.h
index ea7d0bfe899..b4767bc0ffa 100644
--- a/chromium/components/user_manager/fake_user_manager.h
+++ b/chromium/components/user_manager/fake_user_manager.h
@@ -85,7 +85,6 @@ class USER_MANAGER_EXPORT FakeUserManager : public UserManagerBase {
base::string16 GetUserDisplayName(const AccountId& account_id) const override;
void SaveUserDisplayEmail(const AccountId& account_id,
const std::string& display_email) override {}
- std::string GetUserDisplayEmail(const AccountId& account_id) const override;
bool IsCurrentUserOwner() const override;
bool IsCurrentUserNew() const override;
bool IsCurrentUserNonCryptohomeDataEphemeral() const override;
diff --git a/chromium/components/user_manager/user.cc b/chromium/components/user_manager/user.cc
index a23a0ae976c..2e6c2a70b07 100644
--- a/chromium/components/user_manager/user.cc
+++ b/chromium/components/user_manager/user.cc
@@ -263,8 +263,10 @@ bool User::has_gaia_account() const {
}
void User::AddProfileCreatedObserver(base::OnceClosure on_profile_created) {
- DCHECK(!profile_is_created_);
- on_profile_created_observers_.push_back(std::move(on_profile_created));
+ if (profile_is_created_)
+ std::move(on_profile_created).Run();
+ else
+ on_profile_created_observers_.push_back(std::move(on_profile_created));
}
bool User::IsAffiliated() const {
@@ -309,8 +311,11 @@ User* User::CreateSupervisedUser(const AccountId& account_id) {
return new SupervisedUser(account_id);
}
-User* User::CreatePublicAccountUser(const AccountId& account_id) {
- return new PublicAccountUser(account_id);
+User* User::CreatePublicAccountUser(const AccountId& account_id,
+ bool is_using_saml) {
+ User* user = new PublicAccountUser(account_id);
+ user->set_using_saml(is_using_saml);
+ return user;
}
void User::SetAccountLocale(const std::string& resolved_account_locale) {
@@ -476,7 +481,10 @@ std::string SupervisedUser::display_email() const {
}
PublicAccountUser::PublicAccountUser(const AccountId& account_id)
- : DeviceLocalAccountUserBase(account_id) {}
+ : DeviceLocalAccountUserBase(account_id) {
+ // Public accounts do not have a real email address, so they do not set
+ // |display_email_|.
+}
PublicAccountUser::~PublicAccountUser() {
}
diff --git a/chromium/components/user_manager/user.h b/chromium/components/user_manager/user.h
index 41462a9441b..c4033480b52 100644
--- a/chromium/components/user_manager/user.h
+++ b/chromium/components/user_manager/user.h
@@ -217,7 +217,8 @@ class USER_MANAGER_EXPORT User : public UserInfo {
static User* CreateKioskAppUser(const AccountId& kiosk_app_account_id);
static User* CreateArcKioskAppUser(const AccountId& arc_kiosk_account_id);
static User* CreateSupervisedUser(const AccountId& account_id);
- static User* CreatePublicAccountUser(const AccountId& account_id);
+ static User* CreatePublicAccountUser(const AccountId& account_id,
+ bool is_using_saml = false);
const std::string* GetAccountLocale() const { return account_locale_.get(); }
@@ -277,7 +278,10 @@ class USER_MANAGER_EXPORT User : public UserInfo {
AccountId account_id_;
base::string16 display_name_;
base::string16 given_name_;
- // The displayed user email, defaults to |email_|.
+ // User email for display, which may include capitals and non-significant
+ // periods. For example, "John.Steinbeck@gmail.com" is a display email, but
+ // "johnsteinbeck@gmail.com" is the canonical form. Defaults to
+ // account_id_.GetUserEmail().
std::string display_email_;
bool using_saml_ = false;
std::unique_ptr<UserImage> user_image_;
diff --git a/chromium/components/user_manager/user_manager.cc b/chromium/components/user_manager/user_manager.cc
index e02109fef62..caa9a2998b6 100644
--- a/chromium/components/user_manager/user_manager.cc
+++ b/chromium/components/user_manager/user_manager.cc
@@ -9,6 +9,8 @@
namespace user_manager {
+const char kRegularUsersPref[] = "LoggedInUsers";
+
UserManager* UserManager::instance = nullptr;
UserManager::Observer::~Observer() = default;
@@ -26,29 +28,23 @@ void UserManager::Observer::OnUserProfileImageUpdated(
void UserManager::Observer::OnUsersSignInConstraintsChanged() {}
void UserManager::UserSessionStateObserver::ActiveUserChanged(
- const User* active_user) {
-}
+ User* active_user) {}
void UserManager::UserSessionStateObserver::UserAddedToSession(
- const User* active_user) {
-}
+ const User* active_user) {}
void UserManager::UserSessionStateObserver::ActiveUserHashChanged(
- const std::string& hash) {
-}
+ const std::string& hash) {}
-UserManager::UserSessionStateObserver::~UserSessionStateObserver() {
-}
+UserManager::UserSessionStateObserver::~UserSessionStateObserver() {}
UserManager::UserAccountData::UserAccountData(
const base::string16& display_name,
const base::string16& given_name,
const std::string& locale)
- : display_name_(display_name), given_name_(given_name), locale_(locale) {
-}
+ : display_name_(display_name), given_name_(given_name), locale_(locale) {}
-UserManager::UserAccountData::~UserAccountData() {
-}
+UserManager::UserAccountData::~UserAccountData() {}
void UserManager::Initialize() {
DCHECK(!UserManager::instance);
@@ -142,16 +138,4 @@ UserType UserManager::CalculateUserType(const AccountId& account_id,
return USER_TYPE_REGULAR;
}
-ScopedUserSessionStateObserver::ScopedUserSessionStateObserver(
- UserManager::UserSessionStateObserver* observer)
- : observer_(observer) {
- if (UserManager::IsInitialized())
- UserManager::Get()->AddSessionStateObserver(observer_);
-}
-
-ScopedUserSessionStateObserver::~ScopedUserSessionStateObserver() {
- if (UserManager::IsInitialized())
- UserManager::Get()->RemoveSessionStateObserver(observer_);
-}
-
} // namespace user_manager
diff --git a/chromium/components/user_manager/user_manager.h b/chromium/components/user_manager/user_manager.h
index d13ef14307a..0d892fae197 100644
--- a/chromium/components/user_manager/user_manager.h
+++ b/chromium/components/user_manager/user_manager.h
@@ -22,6 +22,10 @@ namespace user_manager {
class ScopedUserManager;
class RemoveUserDelegate;
+// A list pref of the the regular users known on this device, arranged in LRU
+// order, stored in local state.
+USER_MANAGER_EXPORT extern const char kRegularUsersPref[];
+
// Interface for UserManagerBase - that provides base implementation for
// Chrome OS user management. Typical features:
// * Get list of all know users (who have logged into this Chrome OS device)
@@ -62,7 +66,7 @@ class USER_MANAGER_EXPORT UserManager {
class UserSessionStateObserver {
public:
// Called when active user has changed.
- virtual void ActiveUserChanged(const User* active_user);
+ virtual void ActiveUserChanged(User* active_user);
// Called when another user got added to the existing session.
virtual void UserAddedToSession(const User* added_user);
@@ -237,12 +241,6 @@ class USER_MANAGER_EXPORT UserManager {
virtual void SaveUserDisplayEmail(const AccountId& account_id,
const std::string& display_email) = 0;
- // Returns the display email for user |account_id| if it is known (was
- // previously set by a |SaveUserDisplayEmail| call).
- // Otherwise, returns |account_id| itself.
- virtual std::string GetUserDisplayEmail(
- const AccountId& account_id) const = 0;
-
// Saves user's type for |user| into local state preferences.
virtual void SaveUserType(const User* user) = 0;
@@ -410,19 +408,6 @@ class USER_MANAGER_EXPORT UserManager {
static UserManager* SetForTesting(UserManager* user_manager);
};
-// TODO(xiyuan): Move this along with UserSessionStateObserver
-class USER_MANAGER_EXPORT ScopedUserSessionStateObserver {
- public:
- explicit ScopedUserSessionStateObserver(
- UserManager::UserSessionStateObserver* observer);
- ~ScopedUserSessionStateObserver();
-
- private:
- UserManager::UserSessionStateObserver* const observer_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedUserSessionStateObserver);
-};
-
} // namespace user_manager
#endif // COMPONENTS_USER_MANAGER_USER_MANAGER_H_
diff --git a/chromium/components/user_manager/user_manager_base.cc b/chromium/components/user_manager/user_manager_base.cc
index 5e050b7db5e..ec0a254cf12 100644
--- a/chromium/components/user_manager/user_manager_base.cc
+++ b/chromium/components/user_manager/user_manager_base.cc
@@ -34,10 +34,6 @@
namespace user_manager {
namespace {
-// A vector pref of the the regular users known on this device, arranged in LRU
-// order.
-const char kRegularUsers[] = "LoggedInUsers";
-
// A dictionary that maps user IDs to the displayed name.
const char kUserDisplayName[] = "UserDisplayName";
@@ -98,7 +94,7 @@ const base::Feature kHideSupervisedUsers{"HideSupervisedUsers",
// static
void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
- registry->RegisterListPref(kRegularUsers);
+ registry->RegisterListPref(kRegularUsersPref);
registry->RegisterStringPref(kLastLoggedInGaiaUser, std::string());
registry->RegisterDictionaryPref(kUserDisplayName);
registry->RegisterDictionaryPref(kUserGivenName);
@@ -112,7 +108,7 @@ void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
}
UserManagerBase::UserManagerBase(scoped_refptr<base::TaskRunner> task_runner)
- : task_runner_(task_runner), weak_factory_(this) {}
+ : task_runner_(task_runner) {}
UserManagerBase::~UserManagerBase() {
// Can't use STLDeleteElements because of the private destructor of User.
@@ -351,7 +347,7 @@ void UserManagerBase::RemoveUserFromList(const AccountId& account_id) {
DCHECK(IsSupervisedAccountId(account_id));
// Special case, removing partially-constructed supervised user during user
// list loading.
- ListPrefUpdate users_update(GetLocalState(), kRegularUsers);
+ ListPrefUpdate users_update(GetLocalState(), kRegularUsersPref);
users_update->Remove(base::Value(account_id.GetUserEmail()), nullptr);
OnUserRemoved(account_id);
} else {
@@ -489,12 +485,6 @@ void UserManagerBase::SaveUserDisplayEmail(const AccountId& account_id,
base::Value(display_email));
}
-std::string UserManagerBase::GetUserDisplayEmail(
- const AccountId& account_id) const {
- const User* user = FindUser(account_id);
- return user ? user->display_email() : account_id.GetUserEmail();
-}
-
void UserManagerBase::SaveUserType(const User* user) {
DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence());
@@ -805,7 +795,7 @@ void UserManagerBase::EnsureUsersLoaded() {
PrefService* local_state = GetLocalState();
const base::ListValue* prefs_regular_users =
- local_state->GetList(kRegularUsers);
+ local_state->GetList(kRegularUsersPref);
const base::DictionaryValue* prefs_display_names =
local_state->GetDictionary(kUserDisplayName);
@@ -879,7 +869,8 @@ const User* UserManagerBase::FindUserInList(const AccountId& account_id) const {
}
bool UserManagerBase::UserExistsInList(const AccountId& account_id) const {
- const base::ListValue* user_list = GetLocalState()->GetList(kRegularUsers);
+ const base::ListValue* user_list =
+ GetLocalState()->GetList(kRegularUsersPref);
for (size_t i = 0; i < user_list->GetSize(); ++i) {
std::string email;
if (user_list->GetString(i, &email) && (account_id.GetUserEmail() == email))
@@ -904,7 +895,7 @@ void UserManagerBase::GuestUserLoggedIn() {
void UserManagerBase::AddUserRecord(User* user) {
// Add the user to the front of the user list.
- ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
+ ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsersPref);
prefs_users_update->Insert(
0, std::make_unique<base::Value>(user->GetAccountId().GetUserEmail()));
users_.insert(users_.begin(), user);
@@ -949,7 +940,7 @@ void UserManagerBase::RegularUserLoggedInAsEphemeral(
known_user::SetIsEphemeralUser(active_user_->GetAccountId(), true);
}
-void UserManagerBase::NotifyActiveUserChanged(const User* active_user) {
+void UserManagerBase::NotifyActiveUserChanged(User* active_user) {
DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence());
for (auto& observer : session_state_observer_list_)
observer.ActiveUserChanged(active_user);
@@ -1028,7 +1019,7 @@ void UserManagerBase::RemoveNonCryptohomeData(const AccountId& account_id) {
User* UserManagerBase::RemoveRegularOrSupervisedUserFromList(
const AccountId& account_id,
bool notify) {
- ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsers);
+ ListPrefUpdate prefs_users_update(GetLocalState(), kRegularUsersPref);
prefs_users_update->Clear();
User* user = nullptr;
for (UserList::iterator it = users_.begin(); it != users_.end();) {
diff --git a/chromium/components/user_manager/user_manager_base.h b/chromium/components/user_manager/user_manager_base.h
index 886191ca1bd..a4f2d8e58d2 100644
--- a/chromium/components/user_manager/user_manager_base.h
+++ b/chromium/components/user_manager/user_manager_base.h
@@ -79,7 +79,6 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
base::string16 GetUserDisplayName(const AccountId& account_id) const override;
void SaveUserDisplayEmail(const AccountId& account_id,
const std::string& display_email) override;
- std::string GetUserDisplayEmail(const AccountId& account_id) const override;
void SaveUserType(const User* user) override;
void UpdateUserAccountData(const AccountId& account_id,
const UserAccountData& account_data) override;
@@ -169,7 +168,7 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
std::set<AccountId>* device_local_accounts_set) = 0;
// Notifies observers that active user has changed.
- void NotifyActiveUserChanged(const User* active_user);
+ void NotifyActiveUserChanged(User* active_user);
// Notifies that user has logged in.
virtual void NotifyOnLogin();
@@ -389,7 +388,7 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
// TaskRunner for UI thread.
scoped_refptr<base::TaskRunner> task_runner_;
- base::WeakPtrFactory<UserManagerBase> weak_factory_;
+ base::WeakPtrFactory<UserManagerBase> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(UserManagerBase);
};
diff --git a/chromium/components/user_prefs/OWNERS b/chromium/components/user_prefs/OWNERS
index 17dc7671014..ef0ab79b6c7 100644
--- a/chromium/components/user_prefs/OWNERS
+++ b/chromium/components/user_prefs/OWNERS
@@ -2,3 +2,4 @@ battre@chromium.org
gab@chromium.org
# COMPONENT: UI>Browser>Preferences
+# TEAM: chromium-dev@chromium.org
diff --git a/chromium/components/variations/child_process_field_trial_syncer_unittest.cc b/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
index 2dffaa0416b..f258da15517 100644
--- a/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
+++ b/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
@@ -12,7 +12,7 @@
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/variations/variations_crash_keys.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -53,7 +53,7 @@ std::pair<std::string, std::string> MakeStringPair(const std::string& a,
} // namespace
TEST(ChildProcessFieldTrialSyncerTest, FieldTrialState) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
base::FieldTrialList field_trial_list(nullptr);
// We don't use the descriptor here anyways so it's ok to pass -1.
base::FieldTrialList::CreateTrialsFromCommandLine(
diff --git a/chromium/components/variations/client_filterable_state.h b/chromium/components/variations/client_filterable_state.h
index 3b576accf9d..44cc17b6612 100644
--- a/chromium/components/variations/client_filterable_state.h
+++ b/chromium/components/variations/client_filterable_state.h
@@ -51,6 +51,11 @@ struct ClientFilterableState {
// Based on base::SysInfo::IsLowEndDevice().
bool is_low_end_device = false;
+ // Whether this is an enterprise client. Always false on android, iOS, and
+ // linux. Determined by VariationsServiceClient::IsEnterprise for windows,
+ // chromeOs, and mac.
+ bool is_enterprise = false;
+
// The country code to use for studies configured with session consistency.
std::string session_consistency_country;
diff --git a/chromium/components/variations/net/BUILD.gn b/chromium/components/variations/net/BUILD.gn
index 7d103d40010..23bad7c81bb 100644
--- a/chromium/components/variations/net/BUILD.gn
+++ b/chromium/components/variations/net/BUILD.gn
@@ -19,7 +19,7 @@ static_library("net") {
]
deps = [
"//base",
- "//components/google/core/browser",
+ "//components/google/core/common",
"//components/metrics",
"//components/variations/field_trial_config",
"//components/variations/proto",
diff --git a/chromium/components/variations/proto/study.proto b/chromium/components/variations/proto/study.proto
index 69e4e4a9990..699f1d5fba0 100644
--- a/chromium/components/variations/proto/study.proto
+++ b/chromium/components/variations/proto/study.proto
@@ -218,7 +218,7 @@ message Study {
// Filtering criteria specifying whether this study is applicable to a given
// Chrome instance.
//
- // Next tag: 18
+ // Next tag: 19
message Filter {
// The start date of the study in Unix time format. (Seconds since midnight
// January 1, 1970 UTC). See: http://en.wikipedia.org/wiki/Unix_time
@@ -299,7 +299,8 @@ message Study {
// Takes the same range of values as form_factor, e.g. [PHONE, TABLET].
repeated FormFactor exclude_form_factor = 14;
- // List of Chrome OS hardware classes that will receive this study.
+ // List of hardware classes that will receive this study.
+ // This supports Chrome OS and as of M77, Android.
//
// Starting with Chrome M67, this does a case insensitive match on the same
// hardware class field that is reported to UMA in the SystemProfileProto's
@@ -315,7 +316,8 @@ message Study {
// Ex: ["veyron_minnie", "daisy"]
repeated string hardware_class = 8;
- // List of Chrome OS hardware classes that will be excluded in this study.
+ // List of hardware classes that will be excluded in this study.
+ // This supports Chrome OS and as of M77, Android.
//
// Starting with Chrome M67, this does a case insensitive match on the same
// hardware class field that is reported to UMA in the SystemProfileProto's
@@ -346,6 +348,14 @@ message Study {
// Specifies whether the config should apply to low-end devices only. This
// is currently only supported on Android.
optional bool is_low_end_device = 15;
+
+ // Specifies whether the config should apply to enterprise or non-enterprise
+ // only. If omitted, the config applies to both groups.
+ // - On windows and mac, machines on a domain network are considered
+ // enterprise.
+ // - On chromeOS, registered mode determines enterprise status.
+ // - Android, iOS, and linux consider all clients as non-enterprise.
+ optional bool is_enterprise = 18;
}
// Filtering criteria for this study. A study that is filtered out for a given
diff --git a/chromium/components/variations/service/BUILD.gn b/chromium/components/variations/service/BUILD.gn
index 8163600d519..fb0dc78f16a 100644
--- a/chromium/components/variations/service/BUILD.gn
+++ b/chromium/components/variations/service/BUILD.gn
@@ -39,6 +39,7 @@ static_library("service") {
deps = [
":buildflags",
"//base",
+ "//build:branding_buildflags",
"//components/encrypted_messages",
"//components/language/core/browser",
"//components/metrics",
diff --git a/chromium/components/variations/service/variations_field_trial_creator.cc b/chromium/components/variations/service/variations_field_trial_creator.cc
index c35a39c14b7..67447467ccf 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator.cc
@@ -252,6 +252,7 @@ VariationsFieldTrialCreator::GetClientFilterableStateForVersion(
// evaluated, that field trial would not be able to apply for this case.
state->is_low_end_device = base::SysInfo::IsLowEndDevice();
#endif
+ state->is_enterprise = client_->IsEnterprise();
state->session_consistency_country = GetLatestCountry();
state->permanent_consistency_country = LoadPermanentConsistencyCountry(
version, state->session_consistency_country);
@@ -446,6 +447,7 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
const char* kDisableFeatures,
const std::set<std::string>& unforceable_field_trials,
const std::vector<std::string>& variation_ids,
+ const std::vector<base::FeatureList::FeatureOverrideInfo>& extra_overrides,
std::unique_ptr<const base::FieldTrial::EntropyProvider>
low_entropy_provider,
std::unique_ptr<base::FeatureList> feature_list,
@@ -510,6 +512,13 @@ bool VariationsFieldTrialCreator::SetupFieldTrials(
command_line->GetSwitchValueASCII(kEnableFeatures),
command_line->GetSwitchValueASCII(kDisableFeatures));
+ // This needs to happen here: After the InitializeFromCommandLine() call,
+ // because the explicit cmdline --disable-features and --enable-features
+ // should take precedence over these extra overrides. Before the call to
+ // SetInstance(), because overrides cannot be registered after the FeatureList
+ // instance is set.
+ feature_list->RegisterExtraFeatureOverrides(extra_overrides);
+
bool used_testing_config = false;
#if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
if (!command_line->HasSwitch(switches::kDisableFieldTrialTestingConfig) &&
diff --git a/chromium/components/variations/service/variations_field_trial_creator.h b/chromium/components/variations/service/variations_field_trial_creator.h
index 40456a0c3c1..f2ea1364945 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.h
+++ b/chromium/components/variations/service/variations_field_trial_creator.h
@@ -73,16 +73,26 @@ class VariationsFieldTrialCreator {
// |safe_seed_manager| should be notified of the combined server and client
// state that was activated to create the field trials (only when the return
// value is true).
- bool SetupFieldTrials(const char* kEnableGpuBenchmarking,
- const char* kEnableFeatures,
- const char* kDisableFeatures,
- const std::set<std::string>& unforceable_field_trials,
- const std::vector<std::string>& variation_ids,
- std::unique_ptr<const base::FieldTrial::EntropyProvider>
- low_entropy_provider,
- std::unique_ptr<base::FeatureList> feature_list,
- PlatformFieldTrials* platform_field_trials,
- SafeSeedManager* safe_seed_manager);
+ // |extra_overrides| gives a list of feature overrides that should be applied
+ // after the features explicitly disabled/enabled from the command line via
+ // --disable-features and --enable-features, but before field trials.
+ // Note: The ordering of the FeatureList method calls is such that the
+ // explicit --disable-features and --enable-features from the command line
+ // take precedence over the |extra_overrides|, which take precedence over the
+ // field trials.
+ bool SetupFieldTrials(
+ const char* kEnableGpuBenchmarking,
+ const char* kEnableFeatures,
+ const char* kDisableFeatures,
+ const std::set<std::string>& unforceable_field_trials,
+ const std::vector<std::string>& variation_ids,
+ const std::vector<base::FeatureList::FeatureOverrideInfo>&
+ extra_overrides,
+ std::unique_ptr<const base::FieldTrial::EntropyProvider>
+ low_entropy_provider,
+ std::unique_ptr<base::FeatureList> feature_list,
+ PlatformFieldTrials* platform_field_trials,
+ SafeSeedManager* safe_seed_manager);
// Returns all of the client state used for filtering studies.
// As a side-effect, may update the stored permanent consistency country.
diff --git a/chromium/components/variations/service/variations_field_trial_creator_unittest.cc b/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
index 4925a3b0fd4..08020776378 100644
--- a/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
@@ -183,10 +183,7 @@ class TestVariationsServiceClient : public VariationsServiceClient {
*parameter = restrict_parameter_;
return true;
}
-
- void set_restrict_parameter(const std::string& value) {
- restrict_parameter_ = value;
- }
+ bool IsEnterprise() override { return false; }
private:
// VariationsServiceClient:
@@ -260,7 +257,8 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
TestPlatformFieldTrials platform_field_trials;
return VariationsFieldTrialCreator::SetupFieldTrials(
"", "", "", std::set<std::string>(), std::vector<std::string>(),
- nullptr, std::make_unique<base::FeatureList>(), &platform_field_trials,
+ std::vector<base::FeatureList::FeatureOverrideInfo>(), nullptr,
+ std::make_unique<base::FeatureList>(), &platform_field_trials,
safe_seed_manager_);
}
@@ -512,7 +510,8 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_LoadsCountryOnFirstRun) {
// |initial_seed| included the country code for India, this study should be
// active.
EXPECT_TRUE(field_trial_creator.SetupFieldTrials(
- "", "", "", std::set<std::string>(), std::vector<std::string>(), nullptr,
+ "", "", "", std::set<std::string>(), std::vector<std::string>(),
+ std::vector<base::FeatureList::FeatureOverrideInfo>(), nullptr,
std::make_unique<base::FeatureList>(), &platform_field_trials,
&safe_seed_manager));
diff --git a/chromium/components/variations/service/variations_service.cc b/chromium/components/variations/service/variations_service.cc
index 6b6218855a1..29a7f35344c 100644
--- a/chromium/components/variations/service/variations_service.cc
+++ b/chromium/components/variations/service/variations_service.cc
@@ -28,6 +28,7 @@
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "base/version.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
@@ -239,7 +240,7 @@ bool GetInstanceManipulations(const net::HttpResponseHeaders* headers,
// Variations seed fetching is only enabled in official Chrome builds, if a URL
// is specified on the command line, and for testing.
bool IsFetchingEnabled() {
-#if !defined(GOOGLE_CHROME_BUILD)
+#if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kVariationsServerURL) &&
!g_should_fetch_for_testing) {
@@ -535,7 +536,7 @@ bool VariationsService::DoFetchFromURL(const GURL& url, bool is_http_retry) {
})");
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = url;
- resource_request->allow_credentials = false;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
bool enable_deltas = false;
std::string serial_number =
field_trial_creator_.seed_store()->GetLatestSerialNumber();
@@ -608,8 +609,9 @@ bool VariationsService::StoreSeed(const std::string& seed_data,
// activated by this seed. To do this, first get the Chrome version to do a
// simulation with, which must be done on a background thread, and then do the
// actual simulation on the UI thread.
- base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE,
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
client_->GetVersionForSimulationCallback(),
base::Bind(&VariationsService::PerformSimulationWithVersion,
weak_ptr_factory_.GetWeakPtr(), base::Passed(&seed)));
@@ -907,12 +909,14 @@ bool VariationsService::SetupFieldTrials(
const char* kDisableFeatures,
const std::set<std::string>& unforceable_field_trials,
const std::vector<std::string>& variation_ids,
+ const std::vector<base::FeatureList::FeatureOverrideInfo>& extra_overrides,
std::unique_ptr<base::FeatureList> feature_list,
variations::PlatformFieldTrials* platform_field_trials) {
return field_trial_creator_.SetupFieldTrials(
kEnableGpuBenchmarking, kEnableFeatures, kDisableFeatures,
- unforceable_field_trials, variation_ids, CreateLowEntropyProvider(),
- std::move(feature_list), platform_field_trials, &safe_seed_manager_);
+ unforceable_field_trials, variation_ids, extra_overrides,
+ CreateLowEntropyProvider(), std::move(feature_list),
+ platform_field_trials, &safe_seed_manager_);
}
void VariationsService::OverrideCachedUIStrings() {
diff --git a/chromium/components/variations/service/variations_service.h b/chromium/components/variations/service/variations_service.h
index 9943cc501fc..dbc17ce6298 100644
--- a/chromium/components/variations/service/variations_service.h
+++ b/chromium/components/variations/service/variations_service.h
@@ -186,13 +186,16 @@ class VariationsService
}
// Wrapper around VariationsFieldTrialCreator::SetupFieldTrials().
- bool SetupFieldTrials(const char* kEnableGpuBenchmarking,
- const char* kEnableFeatures,
- const char* kDisableFeatures,
- const std::set<std::string>& unforceable_field_trials,
- const std::vector<std::string>& variation_ids,
- std::unique_ptr<base::FeatureList> feature_list,
- variations::PlatformFieldTrials* platform_field_trials);
+ bool SetupFieldTrials(
+ const char* kEnableGpuBenchmarking,
+ const char* kEnableFeatures,
+ const char* kDisableFeatures,
+ const std::set<std::string>& unforceable_field_trials,
+ const std::vector<std::string>& variation_ids,
+ const std::vector<base::FeatureList::FeatureOverrideInfo>&
+ extra_overrides,
+ std::unique_ptr<base::FeatureList> feature_list,
+ variations::PlatformFieldTrials* platform_field_trials);
// Overrides cached UI strings on the resource bundle once it is initialized.
void OverrideCachedUIStrings();
diff --git a/chromium/components/variations/service/variations_service_client.h b/chromium/components/variations/service/variations_service_client.h
index ceff2c541a8..3b16f0603df 100644
--- a/chromium/components/variations/service/variations_service_client.h
+++ b/chromium/components/variations/service/variations_service_client.h
@@ -50,6 +50,20 @@ class VariationsServiceClient {
// (which could be UNKNOWN).
version_info::Channel GetChannelForVariations();
+ // Returns whether the client is enterprise.
+ // TODO(manukh): crbug.com/1003025. This is inconsistent with UMA which
+ // analyzes brand_code to determine if the client is an enterprise user:
+ // - For android, linux, and iOS, they are consistent because both UMA and
+ // chromium consider all such devices as non-enterprise.
+ // - For mac and chromeOS, they are inconsistent because UMA does not consider
+ // any such devices as enterprise, but chromium does.
+ // - For windows, both consider some clients as enterprise, but use different
+ // chromium doesn't use brand_code so they may have inconsistent results.
+ // That being said, studies restricted by finch won't need to filter on UMA as
+ // well. But this could be confusing and could prevent using UMA filters on a
+ // non finch-filtered study to analyze the finch-filtered launch potential.
+ virtual bool IsEnterprise() = 0;
+
private:
// Gets the channel of the embedder. But all variations callers should use
// |GetChannelForVariations()| instead.
diff --git a/chromium/components/variations/service/variations_service_unittest.cc b/chromium/components/variations/service/variations_service_unittest.cc
index a253b9b55f8..f1a6d488d2a 100644
--- a/chromium/components/variations/service/variations_service_unittest.cc
+++ b/chromium/components/variations/service/variations_service_unittest.cc
@@ -23,7 +23,7 @@
#include "base/strings/string_util.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/version.h"
#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/client_info.h"
@@ -102,6 +102,7 @@ class TestVariationsServiceClient : public VariationsServiceClient {
*parameter = restrict_parameter_;
return true;
}
+ bool IsEnterprise() override { return false; }
void set_restrict_parameter(const std::string& value) {
restrict_parameter_ = value;
@@ -336,7 +337,7 @@ class VariationsServiceTest : public ::testing::Test {
network::TestNetworkConnectionTracker* network_tracker_;
private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<metrics::TestEnabledStateProvider> enabled_state_provider_;
std::unique_ptr<metrics::MetricsStateManager> metrics_state_manager_;
diff --git a/chromium/components/variations/study_filtering.cc b/chromium/components/variations/study_filtering.cc
index 93f56b903b3..8338088b60d 100644
--- a/chromium/components/variations/study_filtering.cc
+++ b/chromium/components/variations/study_filtering.cc
@@ -119,6 +119,10 @@ bool CheckStudyLowEndDevice(const Study::Filter& filter,
filter.is_low_end_device() == is_low_end_device;
}
+bool CheckStudyEnterprise(const Study::Filter& filter, bool is_enterprise) {
+ return !filter.has_is_enterprise() || filter.is_enterprise() == is_enterprise;
+}
+
bool CheckStudyStartDate(const Study::Filter& filter,
const base::Time& date_time) {
if (filter.has_start_date()) {
@@ -274,6 +278,12 @@ bool ShouldAddStudy(const Study& study,
return false;
}
+ if (!CheckStudyEnterprise(study.filter(), client_state.is_enterprise)) {
+ DVLOG(1) << "Filtered out study " << study.name()
+ << " due to enterprise state.";
+ return false;
+ }
+
if (!CheckStudyOSVersion(study.filter(), client_state.os_version)) {
DVLOG(1) << "Filtered out study " << study.name()
<< " due to os_version.";
diff --git a/chromium/components/variations/study_filtering.h b/chromium/components/variations/study_filtering.h
index f062544a269..c1cf9c38458 100644
--- a/chromium/components/variations/study_filtering.h
+++ b/chromium/components/variations/study_filtering.h
@@ -45,6 +45,9 @@ bool CheckStudyPlatform(const Study::Filter& filter, Study::Platform platform);
bool CheckStudyLowEndDevice(const Study::Filter& filter,
bool is_low_end_device);
+// Checks whether a study is applicable given |is_enterprise| per |filter|.
+bool CheckStudyEnterprise(const Study::Filter& filter, bool is_enterprise);
+
// Checks whether a study is applicable for the given date/time per |filter|.
bool CheckStudyStartDate(const Study::Filter& filter,
const base::Time& date_time);
diff --git a/chromium/components/variations/study_filtering_unittest.cc b/chromium/components/variations/study_filtering_unittest.cc
index 39732f2d66b..f17149a5634 100644
--- a/chromium/components/variations/study_filtering_unittest.cc
+++ b/chromium/components/variations/study_filtering_unittest.cc
@@ -270,6 +270,23 @@ TEST(VariationsStudyFilteringTest, CheckStudyLowEndDevice) {
EXPECT_TRUE(internal::CheckStudyLowEndDevice(filter, false));
}
+TEST(VariationsStudyFilteringTest, CheckStudyEnterprise) {
+ Study::Filter filter;
+
+ // Check that if the filter is not set, study applies to both enterprise and
+ // non-enterprise clients.
+ EXPECT_TRUE(internal::CheckStudyEnterprise(filter, true));
+ EXPECT_TRUE(internal::CheckStudyEnterprise(filter, false));
+
+ filter.set_is_enterprise(true);
+ EXPECT_TRUE(internal::CheckStudyEnterprise(filter, true));
+ EXPECT_FALSE(internal::CheckStudyEnterprise(filter, false));
+
+ filter.set_is_enterprise(false);
+ EXPECT_FALSE(internal::CheckStudyEnterprise(filter, true));
+ EXPECT_TRUE(internal::CheckStudyEnterprise(filter, false));
+}
+
TEST(VariationsStudyFilteringTest, CheckStudyStartDate) {
const base::Time now = base::Time::Now();
const base::TimeDelta delta = base::TimeDelta::FromHours(1);
diff --git a/chromium/components/variations/synthetic_trial_registry_unittest.cc b/chromium/components/variations/synthetic_trial_registry_unittest.cc
index 0ab93744fd2..77cee92fdef 100644
--- a/chromium/components/variations/synthetic_trial_registry_unittest.cc
+++ b/chromium/components/variations/synthetic_trial_registry_unittest.cc
@@ -8,7 +8,7 @@
#include "base/metrics/field_trial.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/variations/active_field_trials.h"
#include "components/variations/hashing.h"
#include "components/variations/synthetic_trials_active_group_id_provider.h"
@@ -47,7 +47,7 @@ class SyntheticTrialRegistryTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::FieldTrialList field_trial_list_;
diff --git a/chromium/components/variations/variations_associated_data.h b/chromium/components/variations/variations_associated_data.h
index 006ecfd4603..55b9021c896 100644
--- a/chromium/components/variations/variations_associated_data.h
+++ b/chromium/components/variations/variations_associated_data.h
@@ -146,14 +146,12 @@ bool GetVariationParamByFeatureAsBool(const base::Feature& feature,
// Expose some functions for testing.
namespace testing {
-// Clears all of the mapped associations. Deprecated, try to use
-// VariationParamsManager instead as it does a lot of work for you
-// automatically.
+// Clears all of the mapped associations. Deprecated, use ScopedFeatureList
+// instead as it does a lot of work for you automatically.
void ClearAllVariationIDs();
-// Clears all of the associated params. Deprecated, try to use
-// VariationParamsManager instead as it does a lot of work for you
-// automatically.
+// Clears all of the associated params. Deprecated, use ScopedFeatureList
+// instead as it does a lot of work for you automatically.
void ClearAllVariationParams();
} // namespace testing
diff --git a/chromium/components/variations/variations_crash_keys_unittest.cc b/chromium/components/variations/variations_crash_keys_unittest.cc
index 633f2cd5611..115da57f908 100644
--- a/chromium/components/variations/variations_crash_keys_unittest.cc
+++ b/chromium/components/variations/variations_crash_keys_unittest.cc
@@ -8,7 +8,7 @@
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
#include "components/variations/hashing.h"
@@ -42,7 +42,7 @@ class VariationsCrashKeysTest : public ::testing::Test {
}
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::FieldTrialList field_trial_list_;
diff --git a/chromium/components/variations/variations_http_header_provider_unittest.cc b/chromium/components/variations/variations_http_header_provider_unittest.cc
index 6e7823def3f..1ef3cfd10df 100644
--- a/chromium/components/variations/variations_http_header_provider_unittest.cc
+++ b/chromium/components/variations/variations_http_header_provider_unittest.cc
@@ -9,7 +9,7 @@
#include "base/base64.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/variations/entropy_provider.h"
#include "components/variations/proto/client_variations.pb.h"
#include "components/variations/variations_associated_data.h"
@@ -61,7 +61,7 @@ class VariationsHttpHeaderProviderTest : public ::testing::Test {
};
TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_Valid) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
VariationsHttpHeaderProvider provider;
// Valid experiment ids.
@@ -80,7 +80,7 @@ TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_Valid) {
}
TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_ValidCommandLine) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
VariationsHttpHeaderProvider provider;
// Valid experiment ids.
@@ -99,7 +99,7 @@ TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_ValidCommandLine) {
}
TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_Invalid) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
VariationsHttpHeaderProvider provider;
// Invalid experiment ids.
@@ -122,7 +122,7 @@ TEST_F(VariationsHttpHeaderProviderTest, ForceVariationIds_Invalid) {
}
TEST_F(VariationsHttpHeaderProviderTest, OnFieldTrialGroupFinalized) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
base::FieldTrialList field_trial_list(nullptr);
VariationsHttpHeaderProvider provider;
provider.InitVariationIDsCacheIfNeeded();
@@ -171,7 +171,7 @@ TEST_F(VariationsHttpHeaderProviderTest, OnFieldTrialGroupFinalized) {
}
TEST_F(VariationsHttpHeaderProviderTest, GetVariationsString) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
base::FieldTrialList field_trial_list(nullptr);
CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES, 123);
@@ -185,7 +185,7 @@ TEST_F(VariationsHttpHeaderProviderTest, GetVariationsString) {
}
TEST_F(VariationsHttpHeaderProviderTest, GetVariationsVector) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
base::FieldTrialList field_trial_list(nullptr);
CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES, 121);
diff --git a/chromium/components/variations/variations_id_collection_unittest.cc b/chromium/components/variations/variations_id_collection_unittest.cc
index 2c4f4bbb5c9..6a8f6ff5369 100644
--- a/chromium/components/variations/variations_id_collection_unittest.cc
+++ b/chromium/components/variations/variations_id_collection_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/variations/variations_associated_data.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -74,7 +74,7 @@ class VariationsIdCollectionTest : public ::testing::Test {
VariationsIdCollection* collection() { return collection_.get(); }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::FieldTrialList field_trial_list_;
std::unique_ptr<VariationsIdCollection> collection_;
std::vector<VariationID> new_ids_;
diff --git a/chromium/components/variations/variations_request_scheduler_mobile_unittest.cc b/chromium/components/variations/variations_request_scheduler_mobile_unittest.cc
index 05988161374..a457c4dfa65 100644
--- a/chromium/components/variations/variations_request_scheduler_mobile_unittest.cc
+++ b/chromium/components/variations/variations_request_scheduler_mobile_unittest.cc
@@ -5,7 +5,7 @@
#include "components/variations/variations_request_scheduler_mobile.h"
#include "base/bind.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/pref_names.h"
@@ -49,7 +49,7 @@ TEST(VariationsRequestSchedulerMobileTest, StartRun) {
}
TEST(VariationsRequestSchedulerMobileTest, OnAppEnterForegroundNoRun) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
TestingPrefServiceSimple prefs;
@@ -76,7 +76,7 @@ TEST(VariationsRequestSchedulerMobileTest, OnAppEnterForegroundNoRun) {
}
TEST(VariationsRequestSchedulerMobileTest, OnAppEnterForegroundRun) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
TestingPrefServiceSimple prefs;
@@ -102,7 +102,7 @@ TEST(VariationsRequestSchedulerMobileTest, OnAppEnterForegroundRun) {
}
TEST(VariationsRequestSchedulerMobileTest, OnAppEnterForegroundOnStartup) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
TestingPrefServiceSimple prefs;
diff --git a/chromium/components/variations/variations_request_scheduler_unittest.cc b/chromium/components/variations/variations_request_scheduler_unittest.cc
index f751e793044..c035bcda6ba 100644
--- a/chromium/components/variations/variations_request_scheduler_unittest.cc
+++ b/chromium/components/variations/variations_request_scheduler_unittest.cc
@@ -6,13 +6,13 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace variations {
TEST(VariationsRequestSchedulerTest, ScheduleFetchShortly) {
- base::test::ScopedTaskEnvironment task_environment;
+ base::test::SingleThreadTaskEnvironment task_environment;
const base::Closure task = base::DoNothing();
VariationsRequestScheduler scheduler(task);
diff --git a/chromium/components/vector_icons/BUILD.gn b/chromium/components/vector_icons/BUILD.gn
index 912ff8de129..f3f896d4896 100644
--- a/chromium/components/vector_icons/BUILD.gn
+++ b/chromium/components/vector_icons/BUILD.gn
@@ -17,6 +17,7 @@ aggregate_vector_icons("components_vector_icons") {
"check_circle.icon",
"close.icon",
"close_rounded.icon",
+ "devices.icon",
"edit.icon",
"error.icon",
"ethernet.icon",
@@ -44,10 +45,12 @@ aggregate_vector_icons("components_vector_icons") {
"mic.icon",
"midi.icon",
"notifications.icon",
+ "notifications_off.icon",
"open_in_new.icon",
"pause.icon",
"play_arrow.icon",
"protocol_handler.icon",
+ "queue_music.icon",
"reload.icon",
"replay.icon",
"screen_share.icon",
diff --git a/chromium/components/vector_icons/devices.icon b/chromium/components/vector_icons/devices.icon
new file mode 100644
index 00000000000..e29395a5571
--- /dev/null
+++ b/chromium/components/vector_icons/devices.icon
@@ -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.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 4, 6,
+R_H_LINE_TO, 18,
+V_LINE_TO, 4,
+H_LINE_TO, 4,
+R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
+R_V_LINE_TO, 11,
+H_LINE_TO, 0,
+R_V_LINE_TO, 3,
+R_H_LINE_TO, 14,
+R_V_LINE_TO, -3,
+H_LINE_TO, 4,
+V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 19, 2,
+R_H_LINE_TO, -6,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+R_V_LINE_TO, 10,
+R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
+R_H_LINE_TO, 6,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+V_LINE_TO, 9,
+R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
+CLOSE,
+R_MOVE_TO, -1, 9,
+R_H_LINE_TO, -4,
+R_V_LINE_TO, -7,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, 7,
+CLOSE \ No newline at end of file
diff --git a/chromium/components/vector_icons/notifications_off.icon b/chromium/components/vector_icons/notifications_off.icon
new file mode 100644
index 00000000000..8b9654e8089
--- /dev/null
+++ b/chromium/components/vector_icons/notifications_off.icon
@@ -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.
+
+MOVE_TO, 40, 37.39f,
+LINE_TO, 15.68f, 12.3f,
+R_LINE_TO, -5.13f, -5.29f,
+LINE_TO, 8, 9.55f,
+R_LINE_TO, 5.6f, 5.6f,
+R_LINE_TO, 0.01f, 0.01f,
+CUBIC_TO, 12.56f, 17.14f, 12, 19.48f, 12, 22,
+R_V_LINE_TO, 10,
+R_LINE_TO, -4, 4,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 27.46f,
+R_LINE_TO, 4, 4,
+LINE_TO, 42, 39.45f,
+R_LINE_TO, -2, -2.06f,
+CLOSE,
+MOVE_TO, 24, 44,
+R_CUBIC_TO, 2.21f, 0, 4, -1.79f, 4, -4,
+R_H_LINE_TO, -8,
+R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4,
+CLOSE,
+R_MOVE_TO, 12, -14.64f,
+V_LINE_TO, 22,
+R_CUBIC_TO, 0, -6.15f, -3.27f, -11.28f, -9, -12.64f,
+V_LINE_TO, 8,
+R_CUBIC_TO, 0, -1.66f, -1.34f, -3, -3, -3,
+R_CUBIC_TO, -1.66f, 0, -3, 1.34f, -3, 3,
+R_V_LINE_TO, 1.36f,
+R_ARC_TO, 10.95f, 10.95f, 0, 0, 0, -1.46f, 0.46f,
+R_CUBIC_TO, 0, 0, -0.01f, 0, -0.01f, 0.01f,
+R_CUBIC_TO, -0.01f, 0, -0.02f, 0.01f, -0.03f, 0.01f,
+R_CUBIC_TO, -0.46f, 0.18f, -0.91f, 0.39f, -1.35f, 0.62f,
+R_CUBIC_TO, -0.01f, 0, -0.02f, 0.01f, -0.03f, 0.01f,
+LINE_TO, 36, 29.36f,
+CLOSE
diff --git a/chromium/components/vector_icons/queue_music.icon b/chromium/components/vector_icons/queue_music.icon
new file mode 100644
index 00000000000..b29bd25f908
--- /dev/null
+++ b/chromium/components/vector_icons/queue_music.icon
@@ -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.
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 10, 4,
+H_LINE_TO, 2,
+R_V_LINE_TO, 1.33f,
+R_H_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 0, 2.67f,
+H_LINE_TO, 2,
+V_LINE_TO, 8,
+R_H_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, -8, 4,
+R_H_LINE_TO, 5.33f,
+V_LINE_TO, 9.33f,
+H_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 11.33f, 4,
+R_V_LINE_TO, 5.45f,
+R_ARC_TO, 1.98f, 1.98f, 0, 0, 0, -0.66f, -0.12f,
+R_CUBIC_TO, -1.11f, 0, -2, 0.9f, -2, 2,
+R_CUBIC_TO, 0, 1.11f, 0.89f, 2, 2, 2,
+R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
+R_V_LINE_TO, -6,
+R_H_LINE_TO, 2,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 0, 0,
+CLOSE
diff --git a/chromium/components/version_info/BUILD.gn b/chromium/components/version_info/BUILD.gn
index e84edd2dff1..f51beccd391 100644
--- a/chromium/components/version_info/BUILD.gn
+++ b/chromium/components/version_info/BUILD.gn
@@ -21,6 +21,7 @@ static_library("version_info") {
":generate_version_info",
"//base",
"//base:sanitizer_buildflags",
+ "//build:branding_buildflags",
]
public_deps = [
diff --git a/chromium/components/version_info/android/java/VersionConstants.java.version b/chromium/components/version_info/android/java/VersionConstants.java.version
index 6bbce43c534..08a9ba20861 100644
--- a/chromium/components/version_info/android/java/VersionConstants.java.version
+++ b/chromium/components/version_info/android/java/VersionConstants.java.version
@@ -4,14 +4,18 @@
package org.chromium.components.version_info;
+import org.chromium.base.annotations.MainDex;
+
// Constants shared by Android Chrome and WebView. Chrome specific constants are
// in ChromeVersionConstants.
+@MainDex
public class VersionConstants {
public static final String PRODUCT_VERSION = "@MAJOR@.@MINOR@.@BUILD@.@PATCH@";
@SuppressWarnings({"ComplexBooleanConstant", "IdentityBinaryExpression"})
public static final boolean IS_OFFICIAL_BUILD = @OFFICIAL_BUILD@ == 1;
public static final int PRODUCT_MAJOR_VERSION = @MAJOR@;
+ public static final int PRODUCT_BUILD_VERSION = @BUILD@;
public static final int CHANNEL = Channel.@CHANNEL@;
}
diff --git a/chromium/components/version_info/android/java/src/org/chromium/components/version_info/VersionConstantsBridge.java b/chromium/components/version_info/android/java/src/org/chromium/components/version_info/VersionConstantsBridge.java
index 4a5b005ee31..4c124a11e94 100644
--- a/chromium/components/version_info/android/java/src/org/chromium/components/version_info/VersionConstantsBridge.java
+++ b/chromium/components/version_info/android/java/src/org/chromium/components/version_info/VersionConstantsBridge.java
@@ -5,10 +5,12 @@
package org.chromium.components.version_info;
import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.MainDex;
/**
* Bridge between native and VersionConstants.java.
*/
+@MainDex
public class VersionConstantsBridge {
@CalledByNative
public static int getChannel() {
diff --git a/chromium/components/version_info/version_info.cc b/chromium/components/version_info/version_info.cc
index e1742f439cb..57cf7a7fef9 100644
--- a/chromium/components/version_info/version_info.cc
+++ b/chromium/components/version_info/version_info.cc
@@ -9,6 +9,7 @@
#include "base/sanitizer_buildflags.h"
#include "base/strings/string_number_conversions.h"
#include "base/version.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/version_info/version_info_values.h"
@@ -52,7 +53,7 @@ std::string GetOSType() {
#elif defined(OS_MACOSX)
return "Mac OS X";
#elif defined(OS_CHROMEOS)
-# if defined(GOOGLE_CHROME_BUILD)
+# if BUILDFLAG(GOOGLE_CHROME_BRANDING)
return "Chrome OS";
# else
return "Chromium OS";
diff --git a/chromium/components/version_ui/resources/about_version.html b/chromium/components/version_ui/resources/about_version.html
index 427bb0af4f4..9441e421aaa 100644
--- a/chromium/components/version_ui/resources/about_version.html
+++ b/chromium/components/version_ui/resources/about_version.html
@@ -22,6 +22,7 @@ about:version template page
<script src="chrome://resources/js/ios/web_ui.js"></script>
</if>
+ <script src="chrome://resources/js/promise_resolver.js"></script>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/parse_html_subset.js"></script>
diff --git a/chromium/components/version_ui/resources/about_version.js b/chromium/components/version_ui/resources/about_version.js
index 2cbb6debe75..d2f61cff030 100644
--- a/chromium/components/version_ui/resources/about_version.js
+++ b/chromium/components/version_ui/resources/about_version.js
@@ -2,44 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Note: The handle* functions below are called internally on promise
+// resolution, unlike the other return* functions, which are called
+// asynchronously by the host.
+
/**
- * Callback from the backend with the list of variations to display.
- * This call will build the variations section of the version page, or hide that
- * section if there are none to display.
- * @param {!Array<string>} variationsList The list of variations.
+ * Promise resolution handler for variations list and command line equivalent.
+ * @param {{variationsList: !Array<string>, variationsCmd: string=}}
*/
-function returnVariationInfo(variationsList) {
+function handleVariationInfo({variationsList, variationsCmd}) {
$('variations-section').hidden = !variationsList.length;
$('variations-list').appendChild(
parseHtmlSubset(variationsList.join('<br>'), ['BR']));
-}
-/**
- * Callback from the backend with the variations formatted as command line
- * input. This call will build the variations-cmd section of the version page
- * if needed.
- * @param {string} variationsCmd The variations info in command line format.
- */
-function returnVariationCmd(variationsCmd) {
- $('variations-cmd-section').hidden = !variationsCmd;
- $('variations-cmd').textContent = variationsCmd;
+ if (variationsCmd) {
+ $('variations-cmd-section').hidden = !variationsCmd;
+ $('variations-cmd').textContent = variationsCmd;
+ }
}
/**
- * Callback from the backend with the executable and profile paths to display.
+ * Promise resolution handler for the executable and profile paths to display.
* @param {string} execPath The executable path to display.
* @param {string} profilePath The profile path to display.
*/
-function returnFilePaths(execPath, profilePath) {
+function handlePathInfo({execPath, profilePath}) {
$('executable_path').textContent = execPath;
$('profile_path').textContent = profilePath;
}
/**
- * Callback from the backend with the Flash version to display.
+ * Promise resolution handler for the Flash version to display.
* @param {string} flashVersion The Flash version to display.
*/
-function returnFlashVersion(flashVersion) {
+function handlePluginInfo(flashVersion) {
$('flash_version').textContent = flashVersion;
}
@@ -83,6 +79,12 @@ function returnCustomizationId(response) {
/* All the work we do onload. */
function onLoadWork() {
chrome.send('requestVersionInfo');
+ const includeVariationsCmd = location.search.includes("show-variations-cmd");
+ cr.sendWithPromise('requestVariationInfo', includeVariationsCmd)
+ .then(handleVariationInfo);
+ cr.sendWithPromise('requestPluginInfo').then(handlePluginInfo);
+ cr.sendWithPromise('requestPathInfo').then(handlePathInfo);
+
if (cr.isChromeOS) {
$('arc_holder').hidden = true;
chrome.chromeosInfoPrivate.get(['customizationId'], returnCustomizationId);
diff --git a/chromium/components/version_ui/version_ui_constants.cc b/chromium/components/version_ui/version_ui_constants.cc
index 6ad2a1e90ef..53e81e339eb 100644
--- a/chromium/components/version_ui/version_ui_constants.cc
+++ b/chromium/components/version_ui/version_ui_constants.cc
@@ -12,10 +12,15 @@ const char kVersionJS[] = "version.js";
// Message handlers.
const char kRequestVersionInfo[] = "requestVersionInfo";
-const char kReturnFilePaths[] = "returnFilePaths";
-const char kReturnFlashVersion[] = "returnFlashVersion";
-const char kReturnVariationInfo[] = "returnVariationInfo";
-const char kReturnVariationCmd[] = "returnVariationCmd";
+const char kRequestVariationInfo[] = "requestVariationInfo";
+const char kRequestPluginInfo[] = "requestPluginInfo";
+const char kRequestPathInfo[] = "requestPathInfo";
+
+// Named keys used in message handler responses.
+const char kKeyVariationsList[] = "variationsList";
+const char kKeyVariationsCmd[] = "variationsCmd";
+const char kKeyExecPath[] = "execPath";
+const char kKeyProfilePath[] = "profilePath";
// Strings.
const char kApplicationLabel[] = "application_label";
@@ -75,7 +80,6 @@ const char kUserAgent[] = "useragent";
const char kUserAgentName[] = "user_agent_name";
const char kVariationsCmdName[] = "variations_cmd_name";
const char kVariationsName[] = "variations_name";
-const char kVariationsShowCmdQuery[] = "show-variations-cmd";
const char kVersion[] = "version";
const char kVersionBitSize[] = "version_bitsize";
const char kVersionModifier[] = "version_modifier";
diff --git a/chromium/components/version_ui/version_ui_constants.h b/chromium/components/version_ui/version_ui_constants.h
index ebc508658d8..ffd3334a9a7 100644
--- a/chromium/components/version_ui/version_ui_constants.h
+++ b/chromium/components/version_ui/version_ui_constants.h
@@ -17,10 +17,14 @@ extern const char kVersionJS[];
// Message handlers.
// Must match the constants used in the resource files.
extern const char kRequestVersionInfo[];
-extern const char kReturnFilePaths[];
-extern const char kReturnFlashVersion[];
-extern const char kReturnVariationInfo[];
-extern const char kReturnVariationCmd[];
+extern const char kRequestVariationInfo[];
+extern const char kRequestPluginInfo[];
+extern const char kRequestPathInfo[];
+
+extern const char kKeyVariationsList[];
+extern const char kKeyVariationsCmd[];
+extern const char kKeyExecPath[];
+extern const char kKeyProfilePath[];
// Strings.
// Must match the constants used in the resource files.
@@ -81,7 +85,6 @@ extern const char kUserAgent[];
extern const char kUserAgentName[];
extern const char kVariationsCmdName[];
extern const char kVariationsName[];
-extern const char kVariationsShowCmdQuery[];
extern const char kVersion[];
extern const char kVersionBitSize[];
extern const char kVersionModifier[];
diff --git a/chromium/components/visitedlink/browser/visitedlink_master.cc b/chromium/components/visitedlink/browser/visitedlink_master.cc
index 19265ce4d92..1918a684c55 100644
--- a/chromium/components/visitedlink/browser/visitedlink_master.cc
+++ b/chromium/components/visitedlink/browser/visitedlink_master.cc
@@ -617,9 +617,8 @@ void VisitedLinkMaster::LoadFromFile(
scoped_refptr<LoadFromFileResult> load_from_file_result;
bool success = LoadApartFromFile(filename, &load_from_file_result);
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(callback, success, load_from_file_result));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(callback, success, load_from_file_result));
}
// static
@@ -1141,9 +1140,8 @@ void VisitedLinkMaster::TableBuilder::OnComplete(bool success) {
// Marshal to the main thread to notify the VisitedLinkMaster that the
// rebuild is complete.
- base::PostTaskWithTraits(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&TableBuilder::OnCompleteMainThread, this));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&TableBuilder::OnCompleteMainThread, this));
}
void VisitedLinkMaster::TableBuilder::OnCompleteMainThread() {
diff --git a/chromium/components/visitedlink/browser/visitedlink_master.h b/chromium/components/visitedlink/browser/visitedlink_master.h
index 6f8bb3dbdda..08be8c7ddae 100644
--- a/chromium/components/visitedlink/browser/visitedlink_master.h
+++ b/chromium/components/visitedlink/browser/visitedlink_master.h
@@ -405,8 +405,9 @@ class VisitedLinkMaster : public VisitedLinkCommon {
// Task runner for posting file tasks.
scoped_refptr<base::SequencedTaskRunner> file_task_runner_ =
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::CreateSequencedTaskRunner(
+ {base::ThreadPool(), base::MayBlock(),
+ base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
// When non-NULL, indicates we are in database rebuild mode and points to
diff --git a/chromium/components/viz/OWNERS b/chromium/components/viz/OWNERS
index a99a007b66c..0995ad86cbe 100644
--- a/chromium/components/viz/OWNERS
+++ b/chromium/components/viz/OWNERS
@@ -9,7 +9,6 @@
danakj@chromium.org
enne@chromium.org
ericrk@chromium.org
-piman@chromium.org
vmpstr@chromium.org
weiliangc@chromium.org
@@ -36,7 +35,6 @@ jonross@chromium.org
# gpu
danakj@chromium.org
ericrk@chromium.org
-piman@chromium.org
sadrul@chromium.org
# hit testing
diff --git a/chromium/components/viz/client/BUILD.gn b/chromium/components/viz/client/BUILD.gn
index b58252d4e82..6a6af880e2d 100644
--- a/chromium/components/viz/client/BUILD.gn
+++ b/chromium/components/viz/client/BUILD.gn
@@ -15,8 +15,6 @@ viz_component("client") {
"hit_test_data_provider.h",
"hit_test_data_provider_draw_quad.cc",
"hit_test_data_provider_draw_quad.h",
- "local_surface_id_provider.cc",
- "local_surface_id_provider.h",
"shared_bitmap_reporter.cc",
"shared_bitmap_reporter.h",
]
@@ -51,7 +49,7 @@ viz_source_set("unit_tests") {
"//components/viz/client",
"//components/viz/test:test_support",
"//mojo/public/cpp/bindings",
- "//services/viz/public/interfaces",
+ "//services/viz/public/mojom",
"//testing/gmock",
"//testing/gtest",
]
diff --git a/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc b/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
index ee5aae565d3..96add6194ad 100644
--- a/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
+++ b/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
@@ -11,7 +11,6 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
-#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
diff --git a/chromium/components/viz/client/local_surface_id_provider.cc b/chromium/components/viz/client/local_surface_id_provider.cc
deleted file mode 100644
index c01127894a9..00000000000
--- a/chromium/components/viz/client/local_surface_id_provider.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/client/local_surface_id_provider.h"
-
-#include "components/viz/common/quads/compositor_frame.h"
-
-namespace viz {
-
-LocalSurfaceIdProvider::LocalSurfaceIdProvider() = default;
-
-LocalSurfaceIdProvider::~LocalSurfaceIdProvider() = default;
-
-void LocalSurfaceIdProvider::ForceAllocateNewId() {
- parent_local_surface_id_allocator_.GenerateId();
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/client/local_surface_id_provider.h b/chromium/components/viz/client/local_surface_id_provider.h
deleted file mode 100644
index 2319f8d2334..00000000000
--- a/chromium/components/viz/client/local_surface_id_provider.h
+++ /dev/null
@@ -1,35 +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 COMPONENTS_VIZ_CLIENT_LOCAL_SURFACE_ID_PROVIDER_H_
-#define COMPONENTS_VIZ_CLIENT_LOCAL_SURFACE_ID_PROVIDER_H_
-
-#include "components/viz/client/viz_client_export.h"
-#include "components/viz/common/surfaces/local_surface_id.h"
-#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace viz {
-class CompositorFrame;
-
-class VIZ_CLIENT_EXPORT LocalSurfaceIdProvider {
- public:
- LocalSurfaceIdProvider();
- virtual ~LocalSurfaceIdProvider();
-
- virtual const LocalSurfaceIdAllocation&
- GetLocalSurfaceIdAllocationForFrame(const CompositorFrame& frame) = 0;
-
- void ForceAllocateNewId();
-
- protected:
- ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LocalSurfaceIdProvider);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_CLIENT_LOCAL_SURFACE_ID_PROVIDER_H_
diff --git a/chromium/components/viz/common/BUILD.gn b/chromium/components/viz/common/BUILD.gn
index 00d43e3f945..5ea9cd2577b 100644
--- a/chromium/components/viz/common/BUILD.gn
+++ b/chromium/components/viz/common/BUILD.gn
@@ -114,6 +114,8 @@ viz_component("common") {
sources = [
"constants.cc",
"constants.h",
+ "display/de_jelly.cc",
+ "display/de_jelly.h",
"display/overlay_strategy.cc",
"display/overlay_strategy.h",
"display/renderer_settings.cc",
@@ -275,7 +277,10 @@ viz_component("common") {
}
if (is_android) {
- deps += [ "//gpu/config" ]
+ deps += [
+ ":common_jni_headers",
+ "//gpu/config",
+ ]
}
if (is_chromecast) {
@@ -393,3 +398,21 @@ viz_source_set("perf_tests") {
"//testing/perf",
]
}
+
+if (is_android) {
+ android_library("common_java") {
+ deps = [
+ "//base:base_java",
+ ]
+ java_files = [
+ "java/src/org/chromium/components/viz/common/display/DeJellyUtils.java",
+ "java/src/org/chromium/components/viz/common/VizSwitches.java",
+ ]
+ }
+
+ generate_jni("common_jni_headers") {
+ sources = [
+ "java/src/org/chromium/components/viz/common/display/DeJellyUtils.java",
+ ]
+ }
+}
diff --git a/chromium/components/viz/common/display/de_jelly.cc b/chromium/components/viz/common/display/de_jelly.cc
new file mode 100644
index 00000000000..13c4e8813ec
--- /dev/null
+++ b/chromium/components/viz/common/display/de_jelly.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 "components/viz/common/display/de_jelly.h"
+
+#include "base/command_line.h"
+#include "build/build_config.h"
+#include "components/viz/common/features.h"
+#include "components/viz/common/switches.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/time/time.h"
+#include "components/viz/common/common_jni_headers/DeJellyUtils_jni.h"
+#endif
+
+namespace viz {
+
+bool DeJellyEnabled() {
+ if (base::FeatureList::IsEnabled(features::kDisableDeJelly))
+ return false;
+
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDeJelly);
+}
+
+bool DeJellyActive() {
+ if (!DeJellyEnabled())
+ return false;
+
+#if defined(OS_ANDROID)
+ return Java_DeJellyUtils_useDeJelly(base::android::AttachCurrentThread());
+#endif
+
+ return true;
+}
+
+float DeJellyScreenWidth() {
+ std::string value =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kDeJellyScreenWidth);
+ if (!value.empty())
+ return std::atoi(value.c_str());
+
+#if defined(OS_ANDROID)
+ return Java_DeJellyUtils_screenWidth(base::android::AttachCurrentThread());
+#endif
+
+ return 1440.0f;
+}
+
+float MaxDeJellyHeight() {
+ // Not currently configurable.
+ return 30.0f;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/common/display/de_jelly.h b/chromium/components/viz/common/display/de_jelly.h
new file mode 100644
index 00000000000..187f063507a
--- /dev/null
+++ b/chromium/components/viz/common/display/de_jelly.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_DISPLAY_DE_JELLY_H_
+#define COMPONENTS_VIZ_COMMON_DISPLAY_DE_JELLY_H_
+
+#include "components/viz/common/viz_common_export.h"
+
+namespace viz {
+
+// Utility functions for use with de-jelly logic. Used in both viz process and
+// render process.
+
+// Whether experimental de-jelly is enabled. This indicates whether
+// DeJellyActive below may ever return true, and is used by the renderer
+// process to determine whether it should prepare frames for potential
+// de-jelly.
+bool VIZ_COMMON_EXPORT DeJellyEnabled();
+
+// Whether experimental de-jelly is *currently* active. This is different from
+// whether it is generally enabled, and may change frame-over-frame. This is
+// queried from the Viz process, before drawing a frame.
+bool VIZ_COMMON_EXPORT DeJellyActive();
+
+// The screen width to use for de-jelly logic.
+float VIZ_COMMON_EXPORT DeJellyScreenWidth();
+
+// The maximum additional content which may be exposed in a layer by de-jelly
+// skewing.
+float VIZ_COMMON_EXPORT MaxDeJellyHeight();
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_DISPLAY_DE_JELLY_H_
diff --git a/chromium/components/viz/common/display/renderer_settings.h b/chromium/components/viz/common/display/renderer_settings.h
index e33255364c1..389f2ed29bd 100644
--- a/chromium/components/viz/common/display/renderer_settings.h
+++ b/chromium/components/viz/common/display/renderer_settings.h
@@ -31,6 +31,7 @@ class VIZ_COMMON_EXPORT RendererSettings {
bool release_overlay_resources_after_gpu_query = false;
bool tint_gl_composited_content = false;
bool show_overdraw_feedback = false;
+ bool show_aggregated_damage = false;
bool use_skia_renderer = false;
bool allow_overlays = true;
bool dont_round_texture_sizes_for_pixel_tests = false;
@@ -38,6 +39,7 @@ class VIZ_COMMON_EXPORT RendererSettings {
bool auto_resize_output_surface = true;
bool requires_alpha_channel = false;
bool record_sk_picture = false;
+ bool show_dc_layer_debug_borders = false;
int slow_down_compositing_scale_factor = 1;
diff --git a/chromium/components/viz/common/features.cc b/chromium/components/viz/common/features.cc
index b7a29046cac..758902da3f2 100644
--- a/chromium/components/viz/common/features.cc
+++ b/chromium/components/viz/common/features.cc
@@ -14,15 +14,12 @@
namespace features {
-const base::Feature kEnableSurfaceSynchronization{
- "SurfaceSynchronization", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables running the display compositor as part of the viz service in the GPU
// process. This is also referred to as out-of-process display compositor
// (OOP-D).
// TODO(dnicoara): Look at enabling Chromecast support when ChromeOS support is
// ready.
-#if defined(IS_CHROMECAST) || defined(OS_CHROMEOS)
+#if defined(IS_CHROMECAST) && !defined(OS_ANDROID)
const base::Feature kVizDisplayCompositor{"VizDisplayCompositor",
base::FEATURE_DISABLED_BY_DEFAULT};
#else
@@ -45,10 +42,10 @@ const base::Feature kUseSkiaRenderer{"UseSkiaRenderer",
const base::Feature kRecordSkPicture{"RecordSkPicture",
base::FEATURE_DISABLED_BY_DEFAULT};
-bool IsSurfaceSynchronizationEnabled() {
- return IsVizDisplayCompositorEnabled() ||
- base::FeatureList::IsEnabled(kEnableSurfaceSynchronization);
-}
+// Kill-switch to disable de-jelly, even if flags/properties indicate it should
+// be enabled.
+const base::Feature kDisableDeJelly{"DisableDeJelly",
+ base::FEATURE_DISABLED_BY_DEFAULT};
bool IsVizDisplayCompositorEnabled() {
#if defined(OS_MACOSX) || defined(OS_WIN)
@@ -70,10 +67,6 @@ bool IsVizHitTestingDebugEnabled() {
switches::kEnableVizHitTestDebug);
}
-bool IsVizHitTestingDrawQuadEnabled() {
- return !IsVizHitTestingSurfaceLayerEnabled();
-}
-
// VizHitTestSurfaceLayer is enabled when this feature is explicitly enabled on
// chrome://flags, or when it is enabled by finch and chrome://flags does not
// conflict.
diff --git a/chromium/components/viz/common/features.h b/chromium/components/viz/common/features.h
index 1b14d5dd5cc..41e520de1e0 100644
--- a/chromium/components/viz/common/features.h
+++ b/chromium/components/viz/common/features.h
@@ -11,17 +11,15 @@
namespace features {
-VIZ_COMMON_EXPORT extern const base::Feature kEnableSurfaceSynchronization;
VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestSurfaceLayer;
VIZ_COMMON_EXPORT extern const base::Feature kUseSkiaForGLReadback;
VIZ_COMMON_EXPORT extern const base::Feature kUseSkiaRenderer;
VIZ_COMMON_EXPORT extern const base::Feature kRecordSkPicture;
VIZ_COMMON_EXPORT extern const base::Feature kVizDisplayCompositor;
+VIZ_COMMON_EXPORT extern const base::Feature kDisableDeJelly;
-VIZ_COMMON_EXPORT bool IsSurfaceSynchronizationEnabled();
VIZ_COMMON_EXPORT bool IsVizDisplayCompositorEnabled();
VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
-VIZ_COMMON_EXPORT bool IsVizHitTestingDrawQuadEnabled();
VIZ_COMMON_EXPORT bool IsVizHitTestingSurfaceLayerEnabled();
VIZ_COMMON_EXPORT bool IsUsingSkiaForGLReadback();
VIZ_COMMON_EXPORT bool IsUsingSkiaRenderer();
diff --git a/chromium/components/viz/common/frame_sinks/begin_frame_source.cc b/chromium/components/viz/common/frame_sinks/begin_frame_source.cc
index af269c7db78..9470de7bf13 100644
--- a/chromium/components/viz/common/frame_sinks/begin_frame_source.cc
+++ b/chromium/components/viz/common/frame_sinks/begin_frame_source.cc
@@ -140,12 +140,9 @@ bool BeginFrameSource::RequestCallbackOnGpuAvailable() {
switch (gpu_busy_response_state_) {
case GpuBusyThrottlingState::kIdle:
- if (allow_one_begin_frame_after_gpu_busy_) {
gpu_busy_response_state_ =
GpuBusyThrottlingState::kOneBeginFrameAfterBusySent;
return false;
- }
- FALLTHROUGH;
case GpuBusyThrottlingState::kOneBeginFrameAfterBusySent:
gpu_busy_response_state_ = GpuBusyThrottlingState::kThrottled;
return true;
diff --git a/chromium/components/viz/common/frame_sinks/begin_frame_source.h b/chromium/components/viz/common/frame_sinks/begin_frame_source.h
index 5db623ef97c..0eb5691827e 100644
--- a/chromium/components/viz/common/frame_sinks/begin_frame_source.h
+++ b/chromium/components/viz/common/frame_sinks/begin_frame_source.h
@@ -159,11 +159,6 @@ class VIZ_COMMON_EXPORT BeginFrameSource {
virtual void AsValueInto(base::trace_event::TracedValue* state) const;
- void AllowOneBeginFrameAfterGpuBusy() {
- DCHECK(!is_gpu_busy_);
- allow_one_begin_frame_after_gpu_busy_ = true;
- }
-
protected:
// Returns whether begin-frames to clients should be withheld (because the gpu
// is still busy, for example). If this returns true, then OnGpuNoLongerBusy()
@@ -197,8 +192,6 @@ class VIZ_COMMON_EXPORT BeginFrameSource {
GpuBusyThrottlingState gpu_busy_response_state_ =
GpuBusyThrottlingState::kIdle;
- bool allow_one_begin_frame_after_gpu_busy_ = false;
-
DISALLOW_COPY_AND_ASSIGN(BeginFrameSource);
};
diff --git a/chromium/components/viz/common/frame_timing_details.h b/chromium/components/viz/common/frame_timing_details.h
index b901f5f4de4..e07e7f8b227 100644
--- a/chromium/components/viz/common/frame_timing_details.h
+++ b/chromium/components/viz/common/frame_timing_details.h
@@ -11,6 +11,8 @@ namespace viz {
struct FrameTimingDetails {
gfx::PresentationFeedback presentation_feedback;
+ base::TimeTicks received_compositor_frame_timestamp;
+ base::TimeTicks draw_start_timestamp;
};
} // namespace viz
diff --git a/chromium/components/viz/common/gl_helper_benchmark.cc b/chromium/components/viz/common/gl_helper_benchmark.cc
index 5e91c36b27a..6eeac6f04b5 100644
--- a/chromium/components/viz/common/gl_helper_benchmark.cc
+++ b/chromium/components/viz/common/gl_helper_benchmark.cc
@@ -24,7 +24,7 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/viz/common/gl_helper.h"
@@ -118,7 +118,7 @@ class GLHelperBenchmark : public testing::Test {
base::CloseFile(f);
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<gpu::GLInProcessContext> context_;
gpu::gles2::GLES2Interface* gl_;
std::unique_ptr<GLHelper> helper_;
diff --git a/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc b/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc
index a2bd148e75d..c380ea621e7 100644
--- a/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc
+++ b/chromium/components/viz/common/gpu/context_cache_controller_unittest.cc
@@ -176,7 +176,7 @@ TEST(ContextCacheControllerTest, CheckSkiaResourcePurgeAPI) {
std::vector<uint8_t> image_data(image_info.computeMinByteSize());
SkPixmap pixmap(image_info, image_data.data(), image_info.minRowBytes());
auto image = SkImage::MakeRasterCopy(pixmap);
- auto image_gpu = image->makeTextureImage(gr_context, nullptr);
+ auto image_gpu = image->makeTextureImage(gr_context);
gr_context->flush();
}
diff --git a/chromium/components/viz/common/gpu/metal_api_proxy.h b/chromium/components/viz/common/gpu/metal_api_proxy.h
index a062de1a8d4..346b936ba58 100644
--- a/chromium/components/viz/common/gpu/metal_api_proxy.h
+++ b/chromium/components/viz/common/gpu/metal_api_proxy.h
@@ -14,6 +14,8 @@ namespace gl {
class ProgressReporter;
} // namespace gl
+class API_AVAILABLE(macos(10.11)) MTLLibraryCache;
+
// The MTLDeviceProxy wraps all calls to an MTLDevice. It reports progress
// to the GPU watchdog to prevent the watchdog from killing the GPU process
// when progress is being made.
@@ -21,10 +23,6 @@ API_AVAILABLE(macos(10.11))
@interface MTLDeviceProxy : NSObject <MTLDevice> {
base::scoped_nsprotocol<id<MTLDevice>> device_;
- // The number of shaders created so far. Used to see if creation of an
- // excessive number of shaders could be causing hangs.
- uint64_t newLibraryCount_;
-
// Weak pointer to the most vertexMain and fragmentMain MTLFunctions most
// recently present in the result from a -newLibraryWithSource. Used for
// comparison only in -newRenderPipelineStateWithDescriptor.
@@ -40,6 +38,8 @@ API_AVAILABLE(macos(10.11))
// Weak pointer to the progress reporter used to avoid watchdog timeouts.
// This must be re-set to nullptr when it is no longer known to be valid.
gl::ProgressReporter* progressReporter_;
+
+ std::unique_ptr<MTLLibraryCache> libraryCache_;
}
- (id)initWithDevice:(id<MTLDevice>)device;
diff --git a/chromium/components/viz/common/gpu/metal_api_proxy.mm b/chromium/components/viz/common/gpu/metal_api_proxy.mm
index 7edc312f493..98a96297e68 100644
--- a/chromium/components/viz/common/gpu/metal_api_proxy.mm
+++ b/chromium/components/viz/common/gpu/metal_api_proxy.mm
@@ -10,6 +10,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "base/synchronization/condition_variable.h"
+#include "base/trace_event/trace_event.h"
#include "components/crash/core/common/crash_key.h"
#include "ui/gl/progress_reporter.h"
@@ -133,10 +134,99 @@ constexpr uint32_t kShaderCrashDumpLength = 8128;
} // namespace
+// A cache of the result of calls to NewLibraryWithRetry. This will store all
+// resulting MTLLibraries indefinitely, and will grow without bound. This is to
+// minimize the number of calls hitting the MTLCompilerService, which is prone
+// to hangs. Should this significantly help the situation, a more robust (and
+// not indefinitely-growing) cache will be added either here or in Skia.
+// https://crbug.com/974219
+class API_AVAILABLE(macos(10.11)) MTLLibraryCache {
+ public:
+ MTLLibraryCache() = default;
+ ~MTLLibraryCache() = default;
+
+ id<MTLLibrary> NewLibraryWithSource(id<MTLDevice> device,
+ NSString* source,
+ MTLCompileOptions* options,
+ __autoreleasing NSError** error) {
+ LibraryKey key(source, options);
+ auto found = libraries_.find(key);
+ if (found != libraries_.end()) {
+ const LibraryData& data = found->second;
+ *error = [[data.error retain] autorelease];
+ return [data.library retain];
+ }
+ SCOPED_UMA_HISTOGRAM_TIMER("Gpu.MetalProxy.NewLibraryTime");
+ id<MTLLibrary> library =
+ NewLibraryWithRetry(device, source, options, error);
+ LibraryData data(library, *error);
+ libraries_.insert(std::make_pair(key, std::move(data)));
+ return library;
+ }
+ // The number of cache misses is the number of times that we have had to call
+ // the true newLibraryWithSource function.
+ uint64_t CacheMissCount() const { return libraries_.size(); }
+
+ private:
+ struct LibraryKey {
+ LibraryKey(NSString* source, MTLCompileOptions* options)
+ : source_(source, base::scoped_policy::RETAIN),
+ options_(options, base::scoped_policy::RETAIN) {}
+ LibraryKey(const LibraryKey& other) = default;
+ LibraryKey& operator=(const LibraryKey& other) = default;
+ ~LibraryKey() = default;
+
+ bool operator<(const LibraryKey& other) const {
+ switch ([source_ compare:other.source_]) {
+ case NSOrderedAscending:
+ return true;
+ case NSOrderedDescending:
+ return false;
+ case NSOrderedSame:
+ break;
+ }
+#define COMPARE(x) \
+ if ([options_ x] < [other.options_ x]) \
+ return true; \
+ if ([options_ x] > [other.options_ x]) \
+ return false;
+ COMPARE(fastMathEnabled);
+ COMPARE(languageVersion);
+#undef COMPARE
+ // Skia doesn't set any preprocessor macros, and defining an order on two
+ // NSDictionaries is a lot of code, so just assert that there are no
+ // macros. Should this alleviate https://crbug.com/974219, then a more
+ // robust cache should be implemented.
+ DCHECK_EQ([[options_ preprocessorMacros] count], 0u);
+ return false;
+ }
+
+ private:
+ base::scoped_nsobject<NSString> source_;
+ base::scoped_nsobject<MTLCompileOptions> options_;
+ };
+ struct LibraryData {
+ LibraryData(id<MTLLibrary> library_, NSError* error_)
+ : library(library_, base::scoped_policy::RETAIN),
+ error(error_, base::scoped_policy::RETAIN) {}
+ LibraryData(const LibraryData& other) = default;
+ LibraryData& operator=(const LibraryData& other) = default;
+ ~LibraryData() = default;
+
+ base::scoped_nsprotocol<id<MTLLibrary>> library;
+ base::scoped_nsobject<NSError> error;
+ };
+
+ std::map<LibraryKey, LibraryData> libraries_;
+ DISALLOW_COPY_AND_ASSIGN(MTLLibraryCache);
+};
+
@implementation MTLDeviceProxy
- (id)initWithDevice:(id<MTLDevice>)device {
- if (self = [super init])
+ if (self = [super init]) {
device_.reset(device, base::scoped_policy::RETAIN);
+ libraryCache_ = std::make_unique<MTLLibraryCache>();
+ }
return self;
}
@@ -165,28 +255,33 @@ constexpr uint32_t kShaderCrashDumpLength = 8128;
}
#define PROXY_METHOD0_SLOW(R, fn) \
-(R)fn { \
+ TRACE_EVENT0("gpu", "-[MTLDevice " #fn "]"); \
gl::ScopedProgressReporter scoped_reporter(progressReporter_); \
return [device_ fn]; \
}
#define PROXY_METHOD1_SLOW(R, fn, A0) \
-(R)fn : (A0)a0 { \
+ TRACE_EVENT0("gpu", "-[MTLDevice " #fn ":]"); \
gl::ScopedProgressReporter scoped_reporter(progressReporter_); \
return [device_ fn:a0]; \
}
#define PROXY_METHOD2_SLOW(R, fn, A0, a1, A1) \
-(R)fn : (A0)a0 a1 : (A1)a1 { \
+ TRACE_EVENT0("gpu", "-[MTLDevice " #fn ":" #a1 ":]"); \
gl::ScopedProgressReporter scoped_reporter(progressReporter_); \
return [device_ fn:a0 a1:a1]; \
}
#define PROXY_METHOD3_SLOW(R, fn, A0, a1, A1, a2, A2) \
-(R)fn : (A0)a0 a1 : (A1)a1 a2 : (A2)a2 { \
+ TRACE_EVENT0("gpu", "-[MTLDevice " #fn ":" #a1 ":" #a2 ":]"); \
gl::ScopedProgressReporter scoped_reporter(progressReporter_); \
return [device_ fn:a0 a1:a1 a2:a2]; \
}
-#define PROXY_METHOD4_SLOW(R, fn, A0, a1, A1, a2, A2, a3, A3) \
- -(R)fn : (A0)a0 a1 : (A1)a1 a2 : (A2)a2 a3 : (A3)a3 { \
- gl::ScopedProgressReporter scoped_reporter(progressReporter_); \
- return [device_ fn:a0 a1:a1 a2:a2 a3:a3]; \
+#define PROXY_METHOD4_SLOW(R, fn, A0, a1, A1, a2, A2, a3, A3) \
+ -(R)fn : (A0)a0 a1 : (A1)a1 a2 : (A2)a2 a3 : (A3)a3 { \
+ TRACE_EVENT0("gpu", "-[MTLDevice " #fn ":" #a1 ":" #a2 ":" #a3 ":]"); \
+ gl::ScopedProgressReporter scoped_reporter(progressReporter_); \
+ return [device_ fn:a0 a1:a1 a2:a2 a3:a3]; \
}
// Disable availability warnings for the calls to |device_| in the macros. (The
@@ -291,7 +386,7 @@ PROXY_METHOD2_SLOW(nullable id<MTLLibrary>,
newLibraryWithSource:(NSString*)source
options:(nullable MTLCompileOptions*)options
error:(__autoreleasing NSError**)error {
- newLibraryCount_ += 1;
+ TRACE_EVENT0("gpu", "-[MTLDevice newLibraryWithSource:options:error:]");
// Capture the shader's source in a crash key in case newLibraryWithSource
// hangs.
@@ -303,11 +398,15 @@ PROXY_METHOD2_SLOW(nullable id<MTLLibrary>,
DLOG(WARNING) << "Truncating shader in crash log.";
shaderKey.Set(sourceAsSysString);
+ static crash_reporter::CrashKeyString<16> newLibraryCountKey(
+ "MTLNewLibraryCount");
+ newLibraryCountKey.Set(base::NumberToString(libraryCache_->CacheMissCount()));
gl::ScopedProgressReporter scoped_reporter(progressReporter_);
- SCOPED_UMA_HISTOGRAM_TIMER("Gpu.MetalProxy.NewLibraryTime");
- id<MTLLibrary> library = NewLibraryWithRetry(device_, source, options, error);
+ id<MTLLibrary> library =
+ libraryCache_->NewLibraryWithSource(device_, source, options, error);
shaderKey.Clear();
+ newLibraryCountKey.Clear();
// Shaders from Skia will have either a vertexMain or fragmentMain function.
// Save the source and a weak pointer to the function, so we can capture
@@ -339,6 +438,8 @@ PROXY_METHOD3_SLOW(void,
newRenderPipelineStateWithDescriptor:
(MTLRenderPipelineDescriptor*)descriptor
error:(__autoreleasing NSError**)error {
+ TRACE_EVENT0("gpu",
+ "-[MTLDevice newRenderPipelineStateWithDescriptor:error:]");
// Capture the vertex and shader source being used. Skia's use pattern is to
// compile two MTLLibraries before creating a MTLRenderPipelineState -- one
// with vertexMain and the other with fragmentMain. The two immediately
@@ -359,7 +460,7 @@ PROXY_METHOD3_SLOW(void,
DLOG(WARNING) << "Failed to capture fragment shader.";
static crash_reporter::CrashKeyString<16> newLibraryCountKey(
"MTLNewLibraryCount");
- newLibraryCountKey.Set(base::NumberToString(newLibraryCount_));
+ newLibraryCountKey.Set(base::NumberToString(libraryCache_->CacheMissCount()));
gl::ScopedProgressReporter scoped_reporter(progressReporter_);
SCOPED_UMA_HISTOGRAM_TIMER("Gpu.MetalProxy.NewRenderPipelineStateTime");
diff --git a/chromium/components/viz/common/gpu/metal_context_provider.mm b/chromium/components/viz/common/gpu/metal_context_provider.mm
index bdfa518d9fd..9489d94cc32 100644
--- a/chromium/components/viz/common/gpu/metal_context_provider.mm
+++ b/chromium/components/viz/common/gpu/metal_context_provider.mm
@@ -5,6 +5,10 @@
#include "components/viz/common/gpu/metal_context_provider.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/time/time.h"
#include "components/viz/common/gpu/metal_api_proxy.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -14,6 +18,71 @@ namespace viz {
namespace {
+const char* kTestShaderSource =
+ ""
+ "#include <metal_stdlib>\n"
+ "#include <simd/simd.h>\n"
+ "using namespace metal;\n"
+ "typedef struct {\n"
+ " float4 clipSpacePosition [[position]];\n"
+ " float4 color;\n"
+ "} RasterizerData;\n"
+ "\n"
+ "vertex RasterizerData vertexShader(\n"
+ " uint vertexID [[vertex_id]],\n"
+ " constant vector_float2 *positions[[buffer(0)]],\n"
+ " constant vector_float4 *colors[[buffer(1)]]) {\n"
+ " RasterizerData out;\n"
+ " out.clipSpacePosition = vector_float4(0.0, 0.0, 0.0, 1.0);\n"
+ " out.clipSpacePosition.xy = positions[vertexID].xy;\n"
+ " out.color = colors[vertexID];\n"
+ " return out;\n"
+ "}\n"
+ "\n"
+ "fragment float4 fragmentShader(RasterizerData in [[stage_in]]) {\n"
+ " return in.color;\n"
+ "}\n"
+ "";
+
+// The timeout for compiling the test shader. Set to be much longer than any
+// shader compile should take, but still less than the watchdog timeout.
+constexpr base::TimeDelta kTestShaderCompileTimeout =
+ base::TimeDelta::FromSeconds(6);
+
+// State shared between the compiler callback and the caller.
+class API_AVAILABLE(macos(10.11)) TestShaderState
+ : public base::RefCountedThreadSafe<TestShaderState> {
+ public:
+ TestShaderState() {}
+ base::WaitableEvent event;
+
+ protected:
+ friend class base::RefCountedThreadSafe<TestShaderState>;
+ virtual ~TestShaderState() {}
+};
+
+// Attempt to asynchronously compile a test shader. If the compile doesn't
+// complete within a timeout, then return false.
+bool CompileTestShader(id<MTLDevice> device) API_AVAILABLE(macos(10.11)) {
+ auto state = base::MakeRefCounted<TestShaderState>();
+
+ base::scoped_nsobject<NSString> source([[NSString alloc]
+ initWithCString:kTestShaderSource
+ encoding:NSASCIIStringEncoding]);
+ base::scoped_nsobject<MTLCompileOptions> options(
+ [[MTLCompileOptions alloc] init]);
+ MTLNewLibraryCompletionHandler completion_handler =
+ ^(id<MTLLibrary> library, NSError* error) {
+ DCHECK(library);
+ state->event.Signal();
+ };
+ [device newLibraryWithSource:source
+ options:options
+ completionHandler:completion_handler];
+
+ return state->event.TimedWait(kTestShaderCompileTimeout);
+}
+
struct API_AVAILABLE(macos(10.11)) MetalContextProviderImpl
: public MetalContextProvider {
public:
@@ -59,9 +128,20 @@ std::unique_ptr<MetalContextProvider> MetalContextProvider::Create() {
// Failing that, use the system default device.
if (!device_to_use)
device_to_use.reset(MTLCreateSystemDefaultDevice());
- if (device_to_use)
- return std::make_unique<MetalContextProviderImpl>(device_to_use.get());
- DLOG(ERROR) << "Failed to create MTLDevice.";
+ if (!device_to_use) {
+ DLOG(ERROR) << "Failed to find MTLDevice.";
+ return nullptr;
+ }
+ // Compile a test shader, to see if the MTLCompilerService is responding
+ // or not. If the compile times out, then don't try to use Metal.
+ // https://crbug.com/974219
+ bool did_compile = CompileTestShader(device_to_use);
+ UMA_HISTOGRAM_BOOLEAN("Gpu.Metal.TestShaderCompileSucceeded", did_compile);
+ if (!did_compile) {
+ DLOG(ERROR) << "Compiling test MTLLibrary timed out.";
+ return nullptr;
+ }
+ return std::make_unique<MetalContextProviderImpl>(device_to_use.get());
}
// If no device was found, or if the macOS version is too old for Metal,
// return no context provider.
diff --git a/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.cc b/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.cc
index e17419aff99..8ea62aaf52a 100644
--- a/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.cc
+++ b/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.cc
@@ -91,6 +91,9 @@ bool VulkanInProcessContextProvider::Initialize() {
backend_context.fDeviceFeatures2 =
&device_queue_->enabled_device_features_2();
backend_context.fGetProc = get_proc;
+ backend_context.fProtectedContext =
+ vulkan_implementation_->enforce_protected_memory() ? GrProtected::kYes
+ : GrProtected::kNo;
gr_context_ = GrContext::MakeVulkan(backend_context);
diff --git a/chromium/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java b/chromium/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java
new file mode 100644
index 00000000000..38842b22565
--- /dev/null
+++ b/chromium/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java
@@ -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.
+
+package org.chromium.components.viz.common;
+
+/**
+ * Contains command line switches that are specific to the viz/* portion of Chromium on Android.
+ */
+public abstract class VizSwitches {
+ // Enables experimental de-jelly effect.
+ public static final String ENABLE_DE_JELLY = "enable-de-jelly";
+
+ // Prevent instantiation.
+ private VizSwitches() {}
+}
diff --git a/chromium/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java b/chromium/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java
new file mode 100644
index 00000000000..fbfb17813de
--- /dev/null
+++ b/chromium/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java
@@ -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.
+
+package org.chromium.components.viz.common.display;
+
+import android.content.ComponentCallbacks;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Point;
+import android.hardware.display.DisplayManager;
+import android.provider.Settings.Global;
+import android.view.Display;
+import android.view.Surface;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.MainDex;
+
+import java.lang.reflect.Field;
+
+/**
+ * Provides static utility functions to query de-jelly settings.
+ */
+@JNINamespace("viz")
+@MainDex
+public class DeJellyUtils implements DisplayManager.DisplayListener, ComponentCallbacks {
+ /** Singleton DeJellyUtils instance */
+ private static DeJellyUtils sInstance;
+
+ /**
+ * @return The DeJellyUtils singleton.
+ */
+ private static DeJellyUtils getInstance() {
+ if (sInstance == null) sInstance = new DeJellyUtils();
+ return sInstance;
+ }
+
+ /** Whether the last processed rotation should have de-jelly applied. */
+ private boolean mRotationOk;
+ /** Whether the last processed configuration should have de-jelly applied. */
+ private boolean mConfigurationOk;
+ /** The last processed screen width. */
+ private float mScreenWidth;
+ /** Cached DisplayManager. */
+ private DisplayManager mManager;
+ /** Field used to identify in-use screen on some devices. */
+ private Field mDisplayDeviceType;
+
+ /** Int representing the sub-display, used with mDisplayDeviceType. */
+ private static final int SEM_DISPLAY_DEVICE_TYPE_SUB = 5;
+
+ private DeJellyUtils() {
+ // TODO(ericrk): We should probably plumb display information from the
+ // browser process, rather than re-querying it here.
+ mManager = (DisplayManager) ContextUtils.getApplicationContext().getSystemService(
+ Context.DISPLAY_SERVICE);
+ // Register callbacks which will notify of future changes.
+ mManager.registerDisplayListener(this, null);
+ ContextUtils.getApplicationContext().registerComponentCallbacks(this);
+
+ // Get current state, as we may need these values and callbacks will not yet have fired.
+ onDisplayChanged(0);
+ onConfigurationChanged(
+ ContextUtils.getApplicationContext().getResources().getConfiguration());
+
+ // See if we have a display device type field to query.
+ try {
+ Class configurationClass = Configuration.class;
+ mDisplayDeviceType = configurationClass.getDeclaredField("semDisplayDeviceType");
+ } catch (Exception e) {
+ // We do not require mDisplayDeviceType to exist. Continue.
+ }
+ }
+
+ // DisplayManager.DisplayListener implementation.
+ @Override
+ public void onDisplayAdded(int displayId) {}
+ @Override
+ public void onDisplayChanged(int displayId) {
+ // Ignore non-default display.
+ if (displayId != Display.DEFAULT_DISPLAY) return;
+
+ Display display = mManager.getDisplay(displayId);
+
+ // For now only support ROTATION_0.
+ // TODO(ericrk): Allow this to be customized.
+ int rotation = display.getRotation();
+ mRotationOk = rotation == Surface.ROTATION_0;
+
+ Point realSize = new Point();
+ display.getRealSize(realSize);
+ mScreenWidth = realSize.x;
+ }
+ @Override
+ public void onDisplayRemoved(int displayId) {}
+
+ // ComponentCallbacks implementation.
+ @Override
+ public void onConfigurationChanged(Configuration configuration) {
+ if (mDisplayDeviceType != null) {
+ try {
+ mConfigurationOk =
+ mDisplayDeviceType.getInt(configuration) != SEM_DISPLAY_DEVICE_TYPE_SUB;
+ return;
+ } catch (Exception e) {
+ // We don't require that this field exists, continue.
+ }
+ }
+ // Configuration is always ok if we can't query mDisplayDeviceType.
+ mConfigurationOk = true;
+ }
+ @Override
+ public void onLowMemory() {}
+
+ /**
+ * @return Whether de-jelly is externally enabled. This indicates whether
+ * de-jelly may be used on a device in certain orientations /
+ * configurations, not whether it is actively being used.
+ */
+ public static boolean externallyEnableDeJelly() {
+ return Global.getInt(ContextUtils.getApplicationContext().getContentResolver(),
+ "enable_de_jelly_for_chrome", 0)
+ != 0;
+ }
+
+ /**
+ * @return Whether the current screen / configuration should use the de-jelly effect.
+ */
+ @CalledByNative
+ private static boolean useDeJelly() {
+ DeJellyUtils utils = getInstance();
+
+ // Device specific flag which force-disables jelly scroll on a per-frame basis.
+ if (Global.getInt(ContextUtils.getApplicationContext().getContentResolver(),
+ "sem_support_scroll_filter", 1)
+ == 0) {
+ return false;
+ }
+
+ return utils.mRotationOk && utils.mConfigurationOk;
+ }
+
+ /**
+ * @return the current screen width.
+ */
+ @CalledByNative
+ private static float screenWidth() {
+ return getInstance().mScreenWidth;
+ }
+};
diff --git a/chromium/components/viz/common/quads/compositor_frame_metadata.h b/chromium/components/viz/common/quads/compositor_frame_metadata.h
index 66edf1358fe..48f7881c72d 100644
--- a/chromium/components/viz/common/quads/compositor_frame_metadata.h
+++ b/chromium/components/viz/common/quads/compositor_frame_metadata.h
@@ -17,7 +17,6 @@
#include "components/viz/common/surfaces/surface_range.h"
#include "components/viz/common/viz_common_export.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/latency/latency_info.h"
@@ -145,27 +144,6 @@ class VIZ_COMMON_EXPORT CompositorFrameMetadata {
base::Optional<base::TimeDelta> preferred_frame_interval;
- // Union of visible rects of MirrorLayers in the frame, used to force damage
- // on the surface.
- // TODO(crbug/987725): This is a workaround and should be removed when proper
- // damage calculation is implemented in SurfaceAggregator.
- gfx::Rect mirror_rect;
-
-#if defined(OS_ANDROID)
- float max_page_scale_factor = 0.f;
- gfx::SizeF root_layer_size;
- bool root_overflow_y_hidden = false;
-
- // Used to position Android bottom bar, whose position is computed by the
- // renderer compositor.
- float bottom_controls_height = 0.f;
- float bottom_controls_shown_ratio = 0.f;
-
- // Provides selection region updates relative to the current viewport. If the
- // selection is empty or otherwise unused, the bound types will indicate such.
- Selection<gfx::SelectionBound> selection;
-#endif // defined(OS_ANDROID)
-
private:
CompositorFrameMetadata(const CompositorFrameMetadata& other);
CompositorFrameMetadata operator=(const CompositorFrameMetadata&) = delete;
diff --git a/chromium/components/viz/common/quads/draw_quad_unittest.cc b/chromium/components/viz/common/quads/draw_quad_unittest.cc
index 223d974296c..197e9dd884e 100644
--- a/chromium/components/viz/common/quads/draw_quad_unittest.cc
+++ b/chromium/components/viz/common/quads/draw_quad_unittest.cc
@@ -310,7 +310,8 @@ TEST(DrawQuadTest, CopySurfaceDrawQuad) {
CREATE_QUAD_ALL(SurfaceDrawQuad,
SurfaceRange(fallback_surface_id, primary_surface_id),
SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false,
- /*ignores_input_event=*/false, /*is_reflection=*/false);
+ /*ignores_input_event=*/false, /*is_reflection=*/false,
+ /*allow_merge=*/true);
EXPECT_EQ(DrawQuad::Material::kSurfaceContent, copy_quad->material);
EXPECT_EQ(primary_surface_id, copy_quad->surface_range.end());
EXPECT_EQ(fallback_surface_id, *copy_quad->surface_range.start());
diff --git a/chromium/components/viz/common/quads/shared_quad_state.cc b/chromium/components/viz/common/quads/shared_quad_state.cc
index 0c2c3bb461e..42cab6ba363 100644
--- a/chromium/components/viz/common/quads/shared_quad_state.cc
+++ b/chromium/components/viz/common/quads/shared_quad_state.cc
@@ -13,14 +13,8 @@
namespace viz {
-SharedQuadState::SharedQuadState()
- : is_clipped(false),
- opacity(0.f),
- blend_mode(SkBlendMode::kSrcOver),
- sorting_context_id(0) {}
-
+SharedQuadState::SharedQuadState() = default;
SharedQuadState::SharedQuadState(const SharedQuadState& other) = default;
-
SharedQuadState::~SharedQuadState() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(TRACE_DISABLED_BY_DEFAULT("viz.quads"),
"viz::SharedQuadState", this);
diff --git a/chromium/components/viz/common/quads/shared_quad_state.h b/chromium/components/viz/common/quads/shared_quad_state.h
index 647fd47047e..85e6104f58f 100644
--- a/chromium/components/viz/common/quads/shared_quad_state.h
+++ b/chromium/components/viz/common/quads/shared_quad_state.h
@@ -60,21 +60,24 @@ class VIZ_COMMON_EXPORT SharedQuadState {
gfx::RRectF rounded_corner_bounds;
// This rect lives in the target content space.
gfx::Rect clip_rect;
- bool is_clipped;
+ bool is_clipped = false;
// Indicates whether the content in |quad_layer_rect| are fully opaque.
- bool are_contents_opaque;
- float opacity;
- SkBlendMode blend_mode;
- int sorting_context_id;
- // An internal flag used only by the SurfaceAggregator to decide whether to
- // merge quads for a surface into their target render pass. It is a
- // performance optimization by avoiding render passes as much as possible.
+ bool are_contents_opaque = true;
+ float opacity = 1.f;
+ SkBlendMode blend_mode = SkBlendMode::kSrcOver;
+ int sorting_context_id = 0;
+ // Used by SurfaceAggregator to decide whether to merge quads for a surface
+ // into their target render pass. It is a performance optimization by avoiding
+ // render passes as much as possible.
bool is_fast_rounded_corner = false;
// This is for underlay optimization and used only in the SurfaceAggregator
// and the OverlayProcessor. This damage rect contains union of damage from
// occluding surfaces and is only for quads that are the only quad in
// their surface. SetAll() doesn't update this data.
base::Optional<gfx::Rect> occluding_damage_rect;
+
+ // The amount to skew quads in this layer. For experimental de-jelly effect.
+ float de_jelly_delta_y = 0.0f;
};
} // namespace viz
diff --git a/chromium/components/viz/common/quads/surface_draw_quad.cc b/chromium/components/viz/common/quads/surface_draw_quad.cc
index bf6874c6494..be9bef4ac33 100644
--- a/chromium/components/viz/common/quads/surface_draw_quad.cc
+++ b/chromium/components/viz/common/quads/surface_draw_quad.cc
@@ -44,7 +44,8 @@ void SurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
SkColor default_background_color,
bool stretch_content_to_fill_bounds,
bool ignores_input_event,
- bool is_reflection) {
+ bool is_reflection,
+ bool allow_merge) {
DrawQuad::SetAll(shared_quad_state, DrawQuad::Material::kSurfaceContent, rect,
visible_rect, needs_blending);
this->surface_range = surface_range;
@@ -52,6 +53,7 @@ void SurfaceDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
this->stretch_content_to_fill_bounds = stretch_content_to_fill_bounds;
this->ignores_input_event = ignores_input_event;
this->is_reflection = is_reflection;
+ this->allow_merge = allow_merge;
}
const SurfaceDrawQuad* SurfaceDrawQuad::MaterialCast(const DrawQuad* quad) {
diff --git a/chromium/components/viz/common/quads/surface_draw_quad.h b/chromium/components/viz/common/quads/surface_draw_quad.h
index 298f071101d..b91b040c69f 100644
--- a/chromium/components/viz/common/quads/surface_draw_quad.h
+++ b/chromium/components/viz/common/quads/surface_draw_quad.h
@@ -39,7 +39,8 @@ class VIZ_COMMON_EXPORT SurfaceDrawQuad : public DrawQuad {
SkColor default_background_color,
bool stretch_content_to_fill_bounds,
bool ignores_input_event,
- bool is_reflection);
+ bool is_reflection,
+ bool allow_merge);
SurfaceRange surface_range;
SkColor default_background_color = SK_ColorWHITE;
@@ -48,6 +49,9 @@ class VIZ_COMMON_EXPORT SurfaceDrawQuad : public DrawQuad {
// default.
bool ignores_input_event = false;
bool is_reflection = false;
+ // If true, allows this surface to be merged into the embedding surface,
+ // avoiding an intermediate texture.
+ bool allow_merge = true;
static const SurfaceDrawQuad* MaterialCast(const DrawQuad* quad);
diff --git a/chromium/components/viz/common/resources/resource_format_utils.cc b/chromium/components/viz/common/resources/resource_format_utils.cc
index 1c0767d31e4..6d0fe7527d2 100644
--- a/chromium/components/viz/common/resources/resource_format_utils.cc
+++ b/chromium/components/viz/common/resources/resource_format_utils.cc
@@ -239,10 +239,9 @@ gfx::BufferFormat BufferFormat(ResourceFormat format) {
return gfx::BufferFormat::YVU_420;
case YUV_420_BIPLANAR:
return gfx::BufferFormat::YUV_420_BIPLANAR;
- case UYVY_422:
- return gfx::BufferFormat::UYVY_422;
case P010:
return gfx::BufferFormat::P010;
+ case UYVY_422:
case ETC1:
case ALPHA_8:
case LUMINANCE_8:
@@ -393,8 +392,6 @@ ResourceFormat GetResourceFormat(gfx::BufferFormat format) {
return YVU_420;
case gfx::BufferFormat::YUV_420_BIPLANAR:
return YUV_420_BIPLANAR;
- case gfx::BufferFormat::UYVY_422:
- return UYVY_422;
case gfx::BufferFormat::P010:
return P010;
}
@@ -450,9 +447,11 @@ VkFormat ToVkFormat(ResourceFormat format) {
return VK_FORMAT_R8_UNORM;
case LUMINANCE_8:
return VK_FORMAT_R8_UNORM;
- case LUMINANCE_F16:
case YVU_420:
+ return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
case YUV_420_BIPLANAR:
+ return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
+ case LUMINANCE_F16:
case UYVY_422:
case ETC1:
case P010:
diff --git a/chromium/components/viz/common/switches.cc b/chromium/components/viz/common/switches.cc
index 939af7771e9..c007b26a501 100644
--- a/chromium/components/viz/common/switches.cc
+++ b/chromium/components/viz/common/switches.cc
@@ -10,6 +10,10 @@
namespace switches {
+// Screen width is useful for debugging. Shipping implementations should detect
+// this.
+const char kDeJellyScreenWidth[] = "de-jelly-screen-width";
+
// The default number of the BeginFrames to wait to activate a surface with
// dependencies.
const char kDeadlineToSynchronizeSurfaces[] =
@@ -19,6 +23,9 @@ const char kDeadlineToSynchronizeSurfaces[] =
// Also implies --disable-gpu-vsync (see //ui/gl/gl_switches.h).
const char kDisableFrameRateLimit[] = "disable-frame-rate-limit";
+// Experimental de-jelly support.
+const char kEnableDeJelly[] = "enable-de-jelly";
+
// Enable compositing individual elements via hardware overlays when
// permitted by device.
// Setting the flag to "single-fullscreen" will try to promote a single
@@ -37,6 +44,16 @@ const char kEnableVizHitTestDebug[] = "enable-viz-hit-test-debug";
const char kRunAllCompositorStagesBeforeDraw[] =
"run-all-compositor-stages-before-draw";
+// Adds a DebugBorderDrawQuad to the top of the root RenderPass showing the
+// damage rect after surface aggregation. Note that when enabled this feature
+// sets the entire output rect as damaged after adding the quad to highlight the
+// real damage rect, which could hide damage rect problems.
+const char kShowAggregatedDamage[] = "show-aggregated-damage";
+
+// Show debug borders for DC layers - red for overlays and blue for underlays.
+// The debug borders are offset from the layer rect by a few pixels for clarity.
+const char kShowDCLayerDebugBorders[] = "show-dc-layer-debug-borders";
+
// Enables the viz hit-test logic (HitTestAggregator and HitTestQuery), with
// hit-test data coming from surface layer.
const char kUseVizHitTestSurfaceLayer[] = "use-viz-hit-test-surface-layer";
diff --git a/chromium/components/viz/common/switches.h b/chromium/components/viz/common/switches.h
index 8326b1d5d52..87a1d37b66e 100644
--- a/chromium/components/viz/common/switches.h
+++ b/chromium/components/viz/common/switches.h
@@ -14,12 +14,16 @@
namespace switches {
// Keep list in alphabetical order.
+VIZ_COMMON_EXPORT extern const char kDeJellyScreenWidth[];
VIZ_COMMON_EXPORT extern const char kDeadlineToSynchronizeSurfaces[];
VIZ_COMMON_EXPORT extern const char kDisableFrameRateLimit[];
+VIZ_COMMON_EXPORT extern const char kEnableDeJelly[];
VIZ_COMMON_EXPORT extern const char kEnableHardwareOverlays[];
VIZ_COMMON_EXPORT extern const char kEnableVizDevTools[];
VIZ_COMMON_EXPORT extern const char kEnableVizHitTestDebug[];
VIZ_COMMON_EXPORT extern const char kRunAllCompositorStagesBeforeDraw[];
+VIZ_COMMON_EXPORT extern const char kShowAggregatedDamage[];
+VIZ_COMMON_EXPORT extern const char kShowDCLayerDebugBorders[];
VIZ_COMMON_EXPORT extern const char kUseVizHitTestSurfaceLayer[];
VIZ_COMMON_EXPORT base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces();
diff --git a/chromium/components/viz/demo/BUILD.gn b/chromium/components/viz/demo/BUILD.gn
index 55981f9e05a..c1b15adbbaf 100644
--- a/chromium/components/viz/demo/BUILD.gn
+++ b/chromium/components/viz/demo/BUILD.gn
@@ -15,7 +15,7 @@ static_library("client") {
deps = [
"//components/viz/common",
"//mojo/public/cpp/bindings",
- "//services/viz/public/interfaces",
+ "//services/viz/public/mojom",
]
}
@@ -31,7 +31,7 @@ static_library("host") {
"//components/viz/common",
"//components/viz/host",
"//mojo/public/cpp/system",
- "//services/viz/privileged/interfaces",
+ "//services/viz/privileged/mojom",
]
}
@@ -46,7 +46,7 @@ static_library("service") {
"//components/viz/common",
"//components/viz/service/main",
"//mojo/public/cpp/system",
- "//services/viz/privileged/interfaces",
+ "//services/viz/privileged/mojom",
]
}
diff --git a/chromium/components/viz/demo/client/demo_client.h b/chromium/components/viz/demo/client/demo_client.h
index fbe3a531ca4..09ae4136d5a 100644
--- a/chromium/components/viz/demo/client/demo_client.h
+++ b/chromium/components/viz/demo/client/demo_client.h
@@ -14,7 +14,7 @@
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
namespace viz {
class CompositorFrame;
diff --git a/chromium/components/viz/demo/demo_main.cc b/chromium/components/viz/demo/demo_main.cc
index b095759da56..efe7503660a 100644
--- a/chromium/components/viz/demo/demo_main.cc
+++ b/chromium/components/viz/demo/demo_main.cc
@@ -6,9 +6,10 @@
#include "base/command_line.h"
#include "base/i18n/icu_util.h"
#include "base/macros.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_executor.h"
-#include "base/task/thread_pool/thread_pool.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "components/viz/demo/host/demo_host.h"
@@ -30,7 +31,7 @@
#endif
#if defined(USE_X11)
-#include "ui/platform_window/x11/x11_window.h"
+#include "ui/platform_window/x11/x11_window.h" // nogncheck
#endif
namespace {
@@ -49,8 +50,7 @@ class InitBase {
private:
// The exit manager is in charge of calling the dtors of singleton objects.
base::AtExitManager exit_manager_;
- base::SingleThreadTaskExecutor main_task_executor_{
- base::MessagePump::Type::UI};
+ base::SingleThreadTaskExecutor main_task_executor_{base::MessagePumpType::UI};
DISALLOW_COPY_AND_ASSIGN(InitBase);
};
@@ -61,7 +61,7 @@ class InitMojo {
InitMojo() : thread_("Mojo thread") {
mojo::core::Init();
thread_.StartWithOptions(
- base::Thread::Options(base::MessagePump::Type::IO, 0));
+ base::Thread::Options(base::MessagePumpType::IO, 0));
ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
thread_.task_runner(),
mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
@@ -119,7 +119,9 @@ class DemoWindow : public ui::PlatformWindowDelegate {
#elif defined(OS_WIN)
return std::make_unique<ui::WinWindow>(this, props.bounds);
#elif defined(USE_X11)
- return std::make_unique<ui::X11Window>(this, props.bounds);
+ auto x11_window = std::make_unique<ui::X11Window>(this);
+ x11_window->Initialize(std::move(props));
+ return x11_window;
#else
NOTIMPLEMENTED();
return nullptr;
diff --git a/chromium/components/viz/demo/host/demo_host.h b/chromium/components/viz/demo/host/demo_host.h
index e036c6a64fb..e83423d0d54 100644
--- a/chromium/components/viz/demo/host/demo_host.h
+++ b/chromium/components/viz/demo/host/demo_host.h
@@ -13,8 +13,8 @@
#include "components/viz/host/host_display_client.h"
#include "components/viz/host/host_frame_sink_client.h"
#include "components/viz/host/host_frame_sink_manager.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
#include "ui/gfx/native_widget_types.h"
namespace demo {
diff --git a/chromium/components/viz/demo/service/demo_service.cc b/chromium/components/viz/demo/service/demo_service.cc
index cdfe9c7b504..a1cc8aaa068 100644
--- a/chromium/components/viz/demo/service/demo_service.cc
+++ b/chromium/components/viz/demo/service/demo_service.cc
@@ -7,9 +7,8 @@
#include <memory>
#include <utility>
-#include "base/message_loop/message_loop.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
-#include "components/viz/service/main/viz_compositor_thread_runner.h"
+#include "components/viz/service/main/viz_compositor_thread_runner_impl.h"
namespace demo {
@@ -21,8 +20,7 @@ DemoService::DemoService(viz::mojom::FrameSinkManagerRequest request,
params->activation_deadline_in_frames = 0u;
params->frame_sink_manager = std::move(request);
params->frame_sink_manager_client = client.PassInterface();
- runner_ = std::make_unique<viz::VizCompositorThreadRunner>(
- base::MessageLoop::TYPE_DEFAULT);
+ runner_ = std::make_unique<viz::VizCompositorThreadRunnerImpl>();
runner_->CreateFrameSinkManager(std::move(params));
}
diff --git a/chromium/components/viz/demo/service/demo_service.h b/chromium/components/viz/demo/service/demo_service.h
index 8257d2459db..5bd5b0ca6a7 100644
--- a/chromium/components/viz/demo/service/demo_service.h
+++ b/chromium/components/viz/demo/service/demo_service.h
@@ -8,10 +8,10 @@
#include <memory>
#include "base/threading/thread.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
namespace viz {
-class VizCompositorThreadRunner;
+class VizCompositorThreadRunnerImpl;
} // namespace viz
namespace demo {
@@ -27,7 +27,7 @@ class DemoService {
~DemoService();
private:
- std::unique_ptr<viz::VizCompositorThreadRunner> runner_;
+ std::unique_ptr<viz::VizCompositorThreadRunnerImpl> runner_;
DISALLOW_COPY_AND_ASSIGN(DemoService);
};
diff --git a/chromium/components/viz/host/BUILD.gn b/chromium/components/viz/host/BUILD.gn
index 57e211c6d6e..fe68a69936d 100644
--- a/chromium/components/viz/host/BUILD.gn
+++ b/chromium/components/viz/host/BUILD.gn
@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//components/ui_devtools/devtools.gni")
import("//components/viz/viz.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
@@ -41,10 +40,11 @@ viz_component("host") {
deps = [
"//base",
+ "//components/ui_devtools:buildflags",
"//components/viz/common",
"//gpu/ipc/client",
"//gpu/ipc/common",
- "//services/viz/privileged/interfaces",
+ "//services/viz/privileged/mojom",
"//ui/base",
"//ui/gfx",
@@ -56,18 +56,14 @@ viz_component("host") {
public_deps = [
"//gpu/command_buffer/client",
"//gpu/ipc/host",
- "//services/viz/privileged/interfaces/compositing",
- "//services/viz/public/interfaces",
+ "//services/viz/privileged/mojom/compositing",
+ "//services/viz/public/mojom",
"//ui/gfx/geometry",
]
if (is_mac) {
deps += [ "//ui/accelerated_widget_mac" ]
}
-
- if (use_viz_devtools) {
- defines += [ "USE_VIZ_DEVTOOLS" ]
- }
}
viz_source_set("unit_tests") {
@@ -87,8 +83,8 @@ viz_source_set("unit_tests") {
"//gpu",
"//gpu/ipc/host",
"//mojo/public/cpp/bindings",
- "//services/viz/privileged/interfaces",
- "//services/viz/public/interfaces",
+ "//services/viz/privileged/mojom",
+ "//services/viz/public/mojom",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/viz/host/DEPS b/chromium/components/viz/host/DEPS
index 1b7c732202d..e135e148d00 100644
--- a/chromium/components/viz/host/DEPS
+++ b/chromium/components/viz/host/DEPS
@@ -2,6 +2,7 @@
include_rules = [
"+components/discardable_memory/public/mojom",
+ "+components/ui_devtools/buildflags.h",
"+components/viz/common/features.h",
"-components/viz/common/switches.h",
"+media/base/video_types.h",
@@ -14,9 +15,9 @@ include_rules = [
"+media/capture/mojom/video_capture_types.mojom.h",
"+mojo/public/cpp",
"+services/service_manager/public",
- "+services/viz/privileged/interfaces",
- "+services/viz/public/interfaces",
- "+services/viz/public/interfaces/hit_test",
+ "+services/viz/privileged/mojom",
+ "+services/viz/public/mojom",
+ "+services/viz/public/mojom/hit_test",
"+skia",
"+third_party/skia",
"+ui/accelerated_widget_mac",
diff --git a/chromium/components/viz/host/client_frame_sink_video_capturer.h b/chromium/components/viz/host/client_frame_sink_video_capturer.h
index 26ba28adfd2..a5be9bf87bd 100644
--- a/chromium/components/viz/host/client_frame_sink_video_capturer.h
+++ b/chromium/components/viz/host/client_frame_sink_video_capturer.h
@@ -14,7 +14,7 @@
#include "components/viz/host/viz_host_export.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
@@ -34,7 +34,7 @@ class VIZ_HOST_EXPORT ClientFrameSinkVideoCapturer
: private mojom::FrameSinkVideoConsumer {
public:
// A re-connectable FrameSinkVideoCaptureOverlay. See CreateOverlay().
- class Overlay : public mojom::FrameSinkVideoCaptureOverlay {
+ class VIZ_HOST_EXPORT Overlay : public mojom::FrameSinkVideoCaptureOverlay {
public:
Overlay(base::WeakPtr<ClientFrameSinkVideoCapturer> client_capturer,
int32_t stacking_index);
diff --git a/chromium/components/viz/host/gpu_client.cc b/chromium/components/viz/host/gpu_client.cc
index 93f75b1be73..f914de25476 100644
--- a/chromium/components/viz/host/gpu_client.cc
+++ b/chromium/components/viz/host/gpu_client.cc
@@ -12,7 +12,7 @@
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
-#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
namespace viz {
namespace {
diff --git a/chromium/components/viz/host/gpu_client.h b/chromium/components/viz/host/gpu_client.h
index 330bf7ceabb..9b9cdc04631 100644
--- a/chromium/components/viz/host/gpu_client.h
+++ b/chromium/components/viz/host/gpu_client.h
@@ -11,7 +11,7 @@
#include "components/viz/host/gpu_host_impl.h"
#include "components/viz/host/viz_host_export.h"
#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/viz/public/interfaces/gpu.mojom.h"
+#include "services/viz/public/mojom/gpu.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/host/gpu_host_impl.cc b/chromium/components/viz/host/gpu_host_impl.cc
index acdcfb54825..b2442ed8220 100644
--- a/chromium/components/viz/host/gpu_host_impl.cc
+++ b/chromium/components/viz/host/gpu_host_impl.cc
@@ -193,7 +193,7 @@ void GpuHostImpl::ConnectFrameSinkManager(
viz_main_->CreateFrameSinkManager(std::move(params));
}
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
void GpuHostImpl::ConnectVizDevTools(mojom::VizDevToolsParamsPtr params) {
viz_main_->CreateVizDevTools(std::move(params));
}
@@ -272,6 +272,7 @@ mojom::GpuService* GpuHostImpl::gpu_service() {
}
#if defined(USE_OZONE)
+
void GpuHostImpl::InitOzone() {
// Ozone needs to send the primary DRM device to GPU service as early as
// possible to ensure the latter always has a valid device.
@@ -280,9 +281,8 @@ void GpuHostImpl::InitOzone() {
// The Ozone/Wayland requires mojo communication to be established to be
// functional with a separate gpu process. Thus, using the PlatformProperties,
// check if there is such a requirement.
- if (features::IsOzoneDrmMojo() || ui::OzonePlatform::EnsureInstance()
- ->GetPlatformProperties()
- .requires_mojo) {
+ if (features::IsOzoneDrmMojo() ||
+ ui::OzonePlatform::GetInstance()->GetPlatformProperties().requires_mojo) {
// TODO(rjkroege): Remove the legacy IPC code paths when no longer
// necessary. https://crbug.com/806092
auto interface_binder = base::BindRepeating(&GpuHostImpl::BindInterface,
diff --git a/chromium/components/viz/host/gpu_host_impl.h b/chromium/components/viz/host/gpu_host_impl.h
index 231ecc53c13..c3c80f5c831 100644
--- a/chromium/components/viz/host/gpu_host_impl.h
+++ b/chromium/components/viz/host/gpu_host_impl.h
@@ -20,6 +20,7 @@
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom.h"
+#include "components/ui_devtools/buildflags.h"
#include "components/viz/host/viz_host_export.h"
#include "gpu/command_buffer/common/activity_flags.h"
#include "gpu/config/gpu_domain_guilt.h"
@@ -32,10 +33,10 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
-#include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h"
-#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
-#include "services/viz/privileged/interfaces/viz_main.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_host.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
+#include "services/viz/privileged/mojom/viz_main.mojom.h"
#include "url/gurl.h"
namespace gfx {
@@ -152,7 +153,7 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
void ConnectFrameSinkManager(mojom::FrameSinkManagerRequest request,
mojom::FrameSinkManagerClientPtrInfo client);
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
// Connects to Viz DevTools running in the Viz service.
void ConnectVizDevTools(mojom::VizDevToolsParamsPtr params);
#endif
diff --git a/chromium/components/viz/host/hit_test/DEPS b/chromium/components/viz/host/hit_test/DEPS
index 0c23a8bf40b..28690bc5c3f 100644
--- a/chromium/components/viz/host/hit_test/DEPS
+++ b/chromium/components/viz/host/hit_test/DEPS
@@ -1,7 +1,7 @@
# Please consult components/viz/README.md about allowable dependencies.
include_rules = [
- "+services/viz/public/interfaces",
+ "+services/viz/public/mojom",
]
specific_include_rules = {
diff --git a/chromium/components/viz/host/hit_test/hit_test_query.cc b/chromium/components/viz/host/hit_test/hit_test_query.cc
index 7217e98473c..1d2559be0bc 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query.cc
@@ -78,9 +78,7 @@ const std::string GetFlagNames(uint32_t flag) {
} // namespace
-HitTestQuery::HitTestQuery(base::RepeatingClosure bad_message_gpu_callback)
- : bad_message_gpu_callback_(std::move(bad_message_gpu_callback)) {}
-
+HitTestQuery::HitTestQuery() = default;
HitTestQuery::~HitTestQuery() = default;
void HitTestQuery::OnAggregatedHitTestRegionListUpdated(
@@ -179,7 +177,8 @@ Target HitTestQuery::FindTargetForLocationStartingFromImpl(
return Target();
FindTargetInRegionForLocation(event_source, location, start_index,
- is_location_relative_to_parent, &target);
+ is_location_relative_to_parent, frame_sink_id,
+ &target);
UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES("Event.VizHitTest.TargetTimeUs",
target_timer.Elapsed(),
base::TimeDelta::FromMicroseconds(1),
@@ -192,6 +191,7 @@ bool HitTestQuery::FindTargetInRegionForLocation(
const gfx::PointF& location,
size_t region_index,
bool is_location_relative_to_parent,
+ const FrameSinkId& root_view_frame_sink_id,
Target* target) const {
gfx::PointF location_transformed(location);
@@ -228,16 +228,27 @@ bool HitTestQuery::FindTargetInRegionForLocation(
const uint32_t flags = hit_test_data_[region_index].flags;
+ DCHECK(hit_test_data_[region_index].frame_sink_id.is_valid());
+ // Root view should not be overlapped by others. However, the root view
+ // information is not visible to LTHI::BuildHitTestData(). Therefore the
+ // kOverlappedRegion flag could still be set for the root view upon building
+ // hit test data, e.g. overlapped by ShelfApp on ChromeOS.
+ // The kHitTestAsk flag should be ignored in such a case because there is no
+ // need to do async hit testing on the root merely because it was overlapped.
+ // TODO(yigu): Do not set the kHitTestAsk and kOverlappedRegion flags for
+ // root when building hit test data.
+ bool root_view_overlapped =
+ hit_test_data_[region_index].frame_sink_id == root_view_frame_sink_id &&
+ hit_test_data_[region_index].async_hit_test_reasons ==
+ AsyncHitTestReasons::kOverlappedRegion;
+
// Verify that async_hit_test_reasons is set if and only if there's
// a kHitTestAsk flag.
DCHECK_EQ(!!(flags & HitTestRegionFlags::kHitTestAsk),
!!hit_test_data_[region_index].async_hit_test_reasons);
- // TODO(sunxd): v2 doesn't work with drag-n-drop when it still relies on
- // synchronous targeting result for nested OOPIF cases. crbug.com/896786
- if (features::IsVizHitTestingSurfaceLayerEnabled() &&
- ((flags & HitTestRegionFlags::kHitTestAsk) &&
- !(flags & HitTestRegionFlags::kHitTestIgnore))) {
+ if ((flags & HitTestRegionFlags::kHitTestAsk) &&
+ !(flags & HitTestRegionFlags::kHitTestIgnore) && !root_view_overlapped) {
target->frame_sink_id = hit_test_data_[region_index].frame_sink_id;
target->location_in_target = location_in_target;
target->flags = flags;
@@ -246,10 +257,13 @@ bool HitTestQuery::FindTargetInRegionForLocation(
return true;
}
+ // If the current region is not the root view, neither is its children.
+ // Therefore when recursively calling FindTargetInRegionForLocation, pass an
+ // invalid frame sink id as "root".
while (child_region < child_region_end) {
if (FindTargetInRegionForLocation(
event_source, location_in_target, child_region,
- /*is_location_relative_to_parent=*/true, target)) {
+ /*is_location_relative_to_parent=*/true, FrameSinkId(), target)) {
return true;
}
@@ -264,15 +278,22 @@ bool HitTestQuery::FindTargetInRegionForLocation(
if (!RegionMatchEventSource(event_source, flags))
return false;
- if ((flags &
- (HitTestRegionFlags::kHitTestMine | HitTestRegionFlags::kHitTestAsk)) &&
+ if ((flags & HitTestRegionFlags::kHitTestMine) &&
!(flags & HitTestRegionFlags::kHitTestIgnore)) {
target->frame_sink_id = hit_test_data_[region_index].frame_sink_id;
target->location_in_target = location_in_target;
- target->flags = flags;
+ uint32_t async_hit_test_reasons =
+ hit_test_data_[region_index].async_hit_test_reasons;
+ uint32_t target_flags = flags;
+ if (root_view_overlapped) {
+ DCHECK_EQ(hit_test_data_[region_index].async_hit_test_reasons,
+ AsyncHitTestReasons::kOverlappedRegion);
+ target_flags &= ~HitTestRegionFlags::kHitTestAsk;
+ async_hit_test_reasons = AsyncHitTestReasons::kNotAsyncHitTest;
+ }
+ target->flags = target_flags;
// We record fast path hit testing instances with reason kNotAsyncHitTest.
- RecordSlowPathHitTestReasons(
- hit_test_data_[region_index].async_hit_test_reasons);
+ RecordSlowPathHitTestReasons(async_hit_test_reasons);
return true;
}
return false;
@@ -353,11 +374,6 @@ bool HitTestQuery::GetTransformToTargetRecursively(
return false;
}
-void HitTestQuery::ReceivedBadMessageFromGpuProcess() const {
- if (!bad_message_gpu_callback_.is_null())
- bad_message_gpu_callback_.Run();
-}
-
void HitTestQuery::RecordSlowPathHitTestReasons(uint32_t reasons) const {
static const char* kAsyncHitTestReasonsHistogramName =
"Event.VizHitTest.AsyncHitTestReasons";
diff --git a/chromium/components/viz/host/hit_test/hit_test_query.h b/chromium/components/viz/host/hit_test/hit_test_query.h
index 14d5bf215a5..91b5bcd9945 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query.h
+++ b/chromium/components/viz/host/hit_test/hit_test_query.h
@@ -19,7 +19,7 @@ struct Target {
FrameSinkId frame_sink_id;
// Coordinates in the coordinate system of the target FrameSinkId.
gfx::PointF location_in_target;
- // Different flags are defined in services/viz/public/interfaces/hit_test/
+ // Different flags are defined in services/viz/public/mojom/hit_test/
// hit_test_region_list.mojom.
uint32_t flags = 0;
};
@@ -35,8 +35,7 @@ enum class EventSource {
// TODO(crbug.com/966939): Handle 3d space cases correctly.
class VIZ_HOST_EXPORT HitTestQuery {
public:
- explicit HitTestQuery(
- base::RepeatingClosure shut_down_gpu_callback = base::RepeatingClosure());
+ HitTestQuery();
virtual ~HitTestQuery();
// HitTestAggregator has sent the most recent |hit_test_data| for targeting/
@@ -131,6 +130,7 @@ class VIZ_HOST_EXPORT HitTestQuery {
const gfx::PointF& location,
size_t region_index,
bool is_location_relative_to_parent,
+ const FrameSinkId& root_view_frame_sink_id,
Target* target) const;
// Transform |location_in_target| to be in |region_index|'s coordinate space.
@@ -146,8 +146,6 @@ class VIZ_HOST_EXPORT HitTestQuery {
size_t region_index,
gfx::Transform* transform) const;
- void ReceivedBadMessageFromGpuProcess() const;
-
void RecordSlowPathHitTestReasons(uint32_t) const;
// Returns true if |id| is present in |hit_test_data|. If |id| is present
@@ -156,9 +154,6 @@ class VIZ_HOST_EXPORT HitTestQuery {
std::vector<AggregatedHitTestRegion> hit_test_data_;
- // Log bad message and shut down Viz process when it is compromised.
- base::RepeatingClosure bad_message_gpu_callback_;
-
DISALLOW_COPY_AND_ASSIGN(HitTestQuery);
};
diff --git a/chromium/components/viz/host/hit_test/hit_test_query_fuzzer.cc b/chromium/components/viz/host/hit_test/hit_test_query_fuzzer.cc
index 89e3a66ba14..de68fd41b0c 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query_fuzzer.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query_fuzzer.cc
@@ -6,11 +6,12 @@
#include <stdint.h>
#include <string.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
#include <vector>
#include "base/command_line.h"
#include "components/viz/host/hit_test/hit_test_query.h"
-#include "third_party/libFuzzer/src/utils/FuzzedDataProvider.h"
namespace {
diff --git a/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc b/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
index 0c4f06636df..1adf93cb981 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
@@ -1004,7 +1004,7 @@ TEST_F(HitTestQueryTest, RootHitTestAskFlag) {
active_data_.push_back(AggregatedHitTestRegion(
e_id, HitTestRegionFlags::kHitTestAsk | HitTestRegionFlags::kHitTestMouse,
e_bounds, transform_e_to_e, 0,
- AsyncHitTestReasons::kOverlappedRegion)); // e
+ AsyncHitTestReasons::kUseDrawQuadData)); // e
SendHitTestData();
// All points are in e's coordinate system when we reach this case.
@@ -1090,14 +1090,15 @@ TEST_F(HitTestQueryTest, ChildHitTestAskFlag) {
HitTestRegionFlags::kHitTestMouse);
}
-// One embedder with nested OOPIFs.
+// One embedder with nested OOPIFs. When the mid-level iframe has kHitTestAsk
+// flag we should do async hit test and skip checking its descendants.
//
// +e-------------+
// | +c---------| Point maps to
// | 1 | 2 | ----- -------
// | | | 1 e
// | |+b--------| 2 c
-// | || | 3 b
+// | || | 3 c
// | || 3 |
// +--------------+
//
@@ -1143,17 +1144,21 @@ TEST_F(HitTestQueryTest, NestedOOPIFs) {
Target target2 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
EXPECT_EQ(target2.frame_sink_id, c_id);
+ // point2 + transform_e_to_c = (2, 2).
EXPECT_EQ(target2.location_in_target, gfx::PointF(2, 2));
EXPECT_EQ(target2.flags, HitTestRegionFlags::kHitTestChildSurface |
HitTestRegionFlags::kHitTestAsk |
HitTestRegionFlags::kHitTestMouse);
- // b is the deepest OOPIF for point3, return b with ask flag.
+ // b is the deepest OOPIF for point3, but c has the ask flag. Return c
+ // accordingly.
Target target3 =
hit_test_query().FindTargetForLocation(EventSource::MOUSE, point3);
- EXPECT_EQ(target3.frame_sink_id, b_id);
- EXPECT_EQ(target3.location_in_target, gfx::PointF(2, 2));
- EXPECT_EQ(target3.flags, HitTestRegionFlags::kHitTestAsk |
+ EXPECT_EQ(target3.frame_sink_id, c_id);
+ // point3 + transform_e_to_c = (2, 102).
+ EXPECT_EQ(target3.location_in_target, gfx::PointF(2, 102));
+ EXPECT_EQ(target3.flags, HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestAsk |
HitTestRegionFlags::kHitTestMouse);
}
@@ -1343,5 +1348,59 @@ TEST_F(HitTestQueryTest, FindTargetForLocationStartingFrom) {
HitTestRegionFlags::kHitTestMouse);
}
+// One embedder with nested OOPIFs. When the root view is overlapped we should
+// continue checking its descendants rather than doing async hit test.
+//
+// +e-------------+
+// | +c---------| Point maps to
+// | 1 | 2 | ----- -------
+// | | | 1 e
+// | | | 2 c
+// | | |
+// | | |
+// +--------------+
+//
+TEST_F(HitTestQueryTest, OverlappedRootView) {
+ FrameSinkId e_id = FrameSinkId(1, 1);
+ FrameSinkId c_id = FrameSinkId(2, 2);
+ gfx::Rect e_bounds_in_e = gfx::Rect(0, 0, 600, 600);
+ gfx::Rect c_bounds_in_e = gfx::Rect(0, 0, 800, 800);
+ gfx::Transform transform_e_to_e, transform_e_to_c;
+ transform_e_to_c.Translate(-200, -100);
+ active_data_.push_back(AggregatedHitTestRegion(
+ e_id,
+ HitTestRegionFlags::kHitTestMine | HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestAsk,
+ e_bounds_in_e, transform_e_to_e, 1,
+ AsyncHitTestReasons::kOverlappedRegion)); // e
+ active_data_.push_back(AggregatedHitTestRegion(
+ c_id,
+ HitTestRegionFlags::kHitTestChildSurface | kHitTestMine |
+ HitTestRegionFlags::kHitTestMouse,
+ c_bounds_in_e, transform_e_to_c, 0)); // c
+ SendHitTestData();
+
+ // All points are in e's coordinate system when we reach this case.
+ gfx::PointF point1(1, 1);
+ gfx::PointF point2(202, 102);
+
+ Target target1 =
+ hit_test_query().FindTargetForLocation(EventSource::MOUSE, point1);
+ EXPECT_EQ(target1.frame_sink_id, e_id);
+ EXPECT_EQ(target1.location_in_target, point1);
+ // kHitTestAsk should be dropped for overlapped root view.
+ EXPECT_EQ(target1.flags, HitTestRegionFlags::kHitTestMine |
+ HitTestRegionFlags::kHitTestMouse);
+
+ Target target2 =
+ hit_test_query().FindTargetForLocation(EventSource::MOUSE, point2);
+ EXPECT_EQ(target2.frame_sink_id, c_id);
+ // point2 + transform_e_to_c = (2, 2).
+ EXPECT_EQ(target2.location_in_target, gfx::PointF(2, 2));
+ EXPECT_EQ(target2.flags, HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine |
+ HitTestRegionFlags::kHitTestMouse);
+}
+
} // namespace test
} // namespace viz
diff --git a/chromium/components/viz/host/host_display_client.h b/chromium/components/viz/host/host_display_client.h
index 5e5c5da4a3c..b8177277ebc 100644
--- a/chromium/components/viz/host/host_display_client.h
+++ b/chromium/components/viz/host/host_display_client.h
@@ -13,7 +13,7 @@
#include "build/build_config.h"
#include "components/viz/host/viz_host_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
#include "ui/gfx/native_widget_types.h"
namespace viz {
diff --git a/chromium/components/viz/host/host_frame_sink_manager.cc b/chromium/components/viz/host/host_frame_sink_manager.cc
index c4bfe8b49e1..ec1dca946b6 100644
--- a/chromium/components/viz/host/host_frame_sink_manager.cc
+++ b/chromium/components/viz/host/host_frame_sink_manager.cc
@@ -15,7 +15,7 @@
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
namespace viz {
@@ -56,11 +56,6 @@ void HostFrameSinkManager::SetConnectionLostCallback(
connection_lost_callback_ = std::move(callback);
}
-void HostFrameSinkManager::SetBadMessageReceivedFromGpuCallback(
- base::RepeatingClosure callback) {
- bad_message_received_from_gpu_callback_ = std::move(callback);
-}
-
void HostFrameSinkManager::RegisterFrameSinkId(
const FrameSinkId& frame_sink_id,
HostFrameSinkClient* client,
@@ -163,8 +158,7 @@ void HostFrameSinkManager::CreateRootCompositorFrameSink(
data.has_created_compositor_frame_sink = true;
frame_sink_manager_->CreateRootCompositorFrameSink(std::move(params));
- display_hit_test_query_[frame_sink_id] =
- std::make_unique<HitTestQuery>(bad_message_received_from_gpu_callback_);
+ display_hit_test_query_[frame_sink_id] = std::make_unique<HitTestQuery>();
}
void HostFrameSinkManager::CreateCompositorFrameSink(
diff --git a/chromium/components/viz/host/host_frame_sink_manager.h b/chromium/components/viz/host/host_frame_sink_manager.h
index 174c2d2f492..a7c84cce4b5 100644
--- a/chromium/components/viz/host/host_frame_sink_manager.h
+++ b/chromium/components/viz/host/host_frame_sink_manager.h
@@ -25,7 +25,7 @@
#include "components/viz/host/viz_host_export.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
namespace base {
class SingleThreadTaskRunner;
@@ -292,8 +292,6 @@ class VIZ_HOST_EXPORT HostFrameSinkManager
base::RepeatingClosure connection_lost_callback_;
- base::RepeatingClosure bad_message_received_from_gpu_callback_;
-
DisplayHitTestQueryMap display_hit_test_query_;
// TODO(jonross): Separate out all hit testing work into its own separate
diff --git a/chromium/components/viz/host/host_frame_sink_manager_unittest.cc b/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
index ac0229a8166..2c81d20cc82 100644
--- a/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
+++ b/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -25,7 +25,7 @@
#include "components/viz/test/mock_compositor_frame_sink_client.h"
#include "components/viz/test/mock_display_client.h"
#include "components/viz/test/surface_id_allocator_set.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/viz/host/host_gpu_memory_buffer_manager.cc b/chromium/components/viz/host/host_gpu_memory_buffer_manager.cc
index 716393c7ac0..711370d96e6 100644
--- a/chromium/components/viz/host/host_gpu_memory_buffer_manager.cc
+++ b/chromium/components/viz/host/host_gpu_memory_buffer_manager.cc
@@ -14,7 +14,7 @@
#include "gpu/ipc/common/gpu_memory_buffer_impl.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
-#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_usage_util.h"
diff --git a/chromium/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc b/chromium/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
index edcc6992a21..2e9b7156b11 100644
--- a/chromium/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
+++ b/chromium/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
@@ -13,7 +13,7 @@
#include "build/build_config.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "gpu/ipc/host/gpu_memory_buffer_support.h"
-#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/client_native_pixmap_factory.h"
diff --git a/chromium/components/viz/host/layered_window_updater_impl.h b/chromium/components/viz/host/layered_window_updater_impl.h
index d9a9730a78b..ced30727ab6 100644
--- a/chromium/components/viz/host/layered_window_updater_impl.h
+++ b/chromium/components/viz/host/layered_window_updater_impl.h
@@ -13,7 +13,7 @@
#include "base/memory/unsafe_shared_memory_region.h"
#include "components/viz/host/viz_host_export.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
#include "ui/gfx/geometry/size.h"
class SkCanvas;
diff --git a/chromium/components/viz/host/renderer_settings_creation.cc b/chromium/components/viz/host/renderer_settings_creation.cc
index cf3b10af046..f17aa1fa451 100644
--- a/chromium/components/viz/host/renderer_settings_creation.cc
+++ b/chromium/components/viz/host/renderer_settings_creation.cc
@@ -11,6 +11,7 @@
#include "components/viz/common/display/overlay_strategy.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/features.h"
+#include "components/viz/common/switches.h"
#include "ui/base/ui_base_switches.h"
#if defined(OS_MACOSX)
@@ -18,7 +19,6 @@
#endif
#if defined(USE_OZONE)
-#include "components/viz/common/switches.h"
#include "ui/ozone/public/ozone_platform.h"
#endif
@@ -61,6 +61,8 @@ RendererSettings CreateRendererSettings() {
command_line->HasSwitch(switches::kTintGlCompositedContent);
renderer_settings.show_overdraw_feedback =
command_line->HasSwitch(switches::kShowOverdrawFeedback);
+ renderer_settings.show_aggregated_damage =
+ command_line->HasSwitch(switches::kShowAggregatedDamage);
renderer_settings.allow_antialiasing =
!command_line->HasSwitch(switches::kDisableCompositedAntialiasing);
renderer_settings.use_skia_renderer = features::IsUsingSkiaRenderer();
@@ -71,6 +73,8 @@ RendererSettings CreateRendererSettings() {
switches::kDisableMacOverlays);
#endif
renderer_settings.record_sk_picture = features::IsRecordingSkPicture();
+ renderer_settings.show_dc_layer_debug_borders =
+ command_line->HasSwitch(switches::kShowDCLayerDebugBorders);
if (command_line->HasSwitch(switches::kSlowDownCompositingScaleFactor)) {
const int kMinSlowDownScaleFactor = 1;
diff --git a/chromium/components/viz/service/BUILD.gn b/chromium/components/viz/service/BUILD.gn
index 16ef26aa481..a3fc1b3bdc9 100644
--- a/chromium/components/viz/service/BUILD.gn
+++ b/chromium/components/viz/service/BUILD.gn
@@ -21,6 +21,8 @@ viz_component("service") {
"display/ca_layer_overlay.h",
"display/color_lut_cache.cc",
"display/color_lut_cache.h",
+ "display/damage_frame_annotator.cc",
+ "display/damage_frame_annotator.h",
"display/dc_layer_overlay.cc",
"display/dc_layer_overlay.h",
"display/direct_renderer.cc",
@@ -36,6 +38,7 @@ viz_component("service") {
"display/draw_polygon.h",
"display/dynamic_geometry_binding.cc",
"display/dynamic_geometry_binding.h",
+ "display/external_use_client.cc",
"display/external_use_client.h",
"display/frame_rate_decider.cc",
"display/frame_rate_decider.h",
@@ -73,8 +76,6 @@ viz_component("service") {
"display/renderer_utils.cc",
"display/renderer_utils.h",
"display/resource_fence.h",
- "display/resource_metadata.cc",
- "display/resource_metadata.h",
"display/scoped_gpu_memory_buffer_texture.cc",
"display/scoped_gpu_memory_buffer_texture.h",
"display/scoped_render_pass_texture.cc",
@@ -203,7 +204,7 @@ viz_component("service") {
"//media",
"//media/capture:capture_lib",
"//media/mojo/services",
- "//services/viz/privileged/interfaces",
+ "//services/viz/privileged/mojom",
"//ui/display/types",
]
@@ -213,8 +214,8 @@ viz_component("service") {
"//cc",
"//cc/debug",
"//gpu/command_buffer/client:gles2_interface",
- "//services/viz/privileged/interfaces/compositing",
- "//services/viz/public/interfaces",
+ "//services/viz/privileged/mojom/compositing",
+ "//services/viz/public/mojom",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/latency",
@@ -273,6 +274,10 @@ viz_component("service") {
public_deps += [ "//ui/ozone" ]
}
+ if (is_chromecast) {
+ defines += [ "ALWAYS_ENABLE_BLENDING_FOR_PRIMARY" ]
+ }
+
if (is_win) {
sources += [
"display_embedder/output_device_backing.cc",
@@ -306,8 +311,8 @@ viz_component("service") {
# then this build target will no longer be needed.
viz_source_set("gpu_service_dependencies") {
sources = [
- "display_embedder/image_context.cc",
- "display_embedder/image_context.h",
+ "display_embedder/image_context_impl.cc",
+ "display_embedder/image_context_impl.h",
"display_embedder/skia_output_device.cc",
"display_embedder/skia_output_device.h",
"display_embedder/skia_output_device_buffer_queue.cc",
@@ -334,7 +339,7 @@ viz_source_set("gpu_service_dependencies") {
"//gpu/vulkan:buildflags",
"//media/gpu/ipc/service",
"//media/mojo/services",
- "//services/viz/privileged/interfaces/gl",
+ "//services/viz/privileged/mojom/gl",
"//skia",
"//ui/latency:latency",
]
@@ -448,7 +453,7 @@ viz_source_set("unit_tests") {
"//gpu/ipc/service",
"//media",
"//media/capture:capture_lib",
- "//services/viz/public/interfaces",
+ "//services/viz/public/mojom",
"//skia",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/viz/service/DEPS b/chromium/components/viz/service/DEPS
index 01b30d60f04..9adce7e5a9f 100644
--- a/chromium/components/viz/service/DEPS
+++ b/chromium/components/viz/service/DEPS
@@ -8,8 +8,8 @@ include_rules = [
"+components/viz/service/viz_service_export.h",
"+gpu/config/gpu_feature_info.h",
"+gpu/ipc/common/surface_handle.h",
- "+services/viz/privileged/interfaces",
- "+services/viz/public/interfaces",
+ "+services/viz/privileged/mojom",
+ "+services/viz/public/mojom",
"+third_party/skia",
"+ui/latency",
"+ui/ozone/public",
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc b/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc
index 57c602ee951..be2a106056d 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc
@@ -10,6 +10,7 @@
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h"
#include "components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h"
#include "mojo/core/embedder/embedder.h"
+#include "testing/libfuzzer/libfuzzer_exports.h"
#include "testing/libfuzzer/proto/lpm_interface.h"
#include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.pb.h"
diff --git a/chromium/components/viz/service/display/DEPS b/chromium/components/viz/service/display/DEPS
index 46f956addc5..ed57e8e4373 100644
--- a/chromium/components/viz/service/display/DEPS
+++ b/chromium/components/viz/service/display/DEPS
@@ -29,6 +29,8 @@ include_rules = [
"+ui/gl/dc_renderer_layer_params.h",
"+ui/gl/trace_util.h",
"+gpu/ipc/common/vulkan_ycbcr_info.h",
+ "+gpu/ipc/scheduler_sequence.h",
+ "+gpu/config/gpu_driver_bug_workaround_type.h",
]
specific_include_rules = {
diff --git a/chromium/components/viz/service/display/bsp_tree_perftest.cc b/chromium/components/viz/service/display/bsp_tree_perftest.cc
index b9cf2b3d8f0..8b6aad0aa25 100644
--- a/chromium/components/viz/service/display/bsp_tree_perftest.cc
+++ b/chromium/components/viz/service/display/bsp_tree_perftest.cc
@@ -44,7 +44,7 @@ class BspTreePerfTest : public cc::LayerTreeTest {
void SetupTree() override {
gfx::Size viewport = gfx::Size(720, 1038);
- layer_tree_host()->SetViewportSizeAndScale(viewport, 1.f,
+ layer_tree_host()->SetViewportRectAndScale(gfx::Rect(viewport), 1.f,
LocalSurfaceIdAllocation());
scoped_refptr<cc::Layer> root =
ParseTreeFromJson(json_, &content_layer_client_);
@@ -107,9 +107,8 @@ class BspTreePerfTest : public cc::LayerTreeTest {
cc::LayerTreeHostImpl* host_impl) {
cc::RenderSurfaceList update_list;
cc::LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
- active_tree->root_layer_for_testing(),
- active_tree->GetDeviceViewport().size(), host_impl->DrawTransform(),
- active_tree->device_scale_factor(),
+ active_tree->root_layer_for_testing(), active_tree->GetDeviceViewport(),
+ host_impl->DrawTransform(), active_tree->device_scale_factor(),
active_tree->current_page_scale_factor(),
active_tree->InnerViewportContainerLayer(),
active_tree->InnerViewportScrollLayer(),
diff --git a/chromium/components/viz/service/display/damage_frame_annotator.cc b/chromium/components/viz/service/display/damage_frame_annotator.cc
new file mode 100644
index 00000000000..d39992e69d6
--- /dev/null
+++ b/chromium/components/viz/service/display/damage_frame_annotator.cc
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/display/damage_frame_annotator.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "cc/base/math_util.h"
+#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/quads/debug_border_draw_quad.h"
+#include "components/viz/common/quads/render_pass.h"
+#include "components/viz/common/quads/shared_quad_state.h"
+
+namespace viz {
+
+DamageFrameAnnotator::DamageFrameAnnotator() = default;
+DamageFrameAnnotator::~DamageFrameAnnotator() = default;
+
+void DamageFrameAnnotator::AnnotateAggregatedFrame(CompositorFrame* frame) {
+ DCHECK(frame);
+ auto* root_render_pass = frame->render_pass_list.back().get();
+
+ const gfx::Rect& damage_rect = root_render_pass->damage_rect;
+ gfx::Transform transform;
+ transform.Translate(damage_rect.x(), damage_rect.y());
+
+ annotations_.push_back(
+ AnnotationData{gfx::Rect(damage_rect.size()), transform,
+ Highlight{SkColorSetARGB(128, 255, 0, 0), 4}});
+
+ AnnotateRootRenderPass(root_render_pass);
+ annotations_.clear();
+}
+
+void DamageFrameAnnotator::AnnotateRootRenderPass(RenderPass* render_pass) {
+ const size_t num_quads_to_add = annotations_.size();
+
+ // Insert |num_quads_to_add| new SharedQuadState at the start of the list.
+ // This will invalidate all the existing SharedQuadState* in DrawQuads.
+ auto sqs_iter =
+ render_pass->shared_quad_state_list
+ .InsertBeforeAndInvalidateAllPointers<SharedQuadState>(
+ render_pass->shared_quad_state_list.begin(), num_quads_to_add);
+
+ // Insert |num_quads_to_add| new DebugBorderDrawQuad at start of list. The
+ // quads will be drawn on top of the original quads.
+ auto quad_iter =
+ render_pass->quad_list
+ .InsertBeforeAndInvalidateAllPointers<DebugBorderDrawQuad>(
+ render_pass->quad_list.begin(), num_quads_to_add);
+
+ // Initialize the SharedQuadStates and DebugBorderDrawQuads.
+ for (auto& annotation : annotations_) {
+ gfx::Rect output_rect = cc::MathUtil::MapEnclosingClippedRect(
+ annotation.transform, annotation.rect);
+
+ SharedQuadState* new_sqs = *sqs_iter;
+ new_sqs->SetAll(annotation.transform, output_rect, output_rect,
+ gfx::RRectF(), output_rect, true, false, 1.f,
+ SkBlendMode::kSrcOver, 0);
+
+ DebugBorderDrawQuad* new_quad =
+ static_cast<DebugBorderDrawQuad*>(*quad_iter);
+ new_quad->SetNew(new_sqs, annotation.rect, annotation.rect,
+ annotation.highlight.color, annotation.highlight.width);
+
+ ++sqs_iter;
+ ++quad_iter;
+ }
+
+ // At this point |quad_iter| points to the first DrawQuad that needs
+ // |shared_quad_state| fixed. |sqs_iter| points to the new address for the
+ // first original SharedQuadState. Iterate through all DrawQuads updating
+ // |shared_quad_state|.
+ const SharedQuadState* last_quad_from_sqs = (*quad_iter)->shared_quad_state;
+ while (quad_iter != render_pass->quad_list.end()) {
+ DrawQuad* quad = *quad_iter;
+ const SharedQuadState* from_sqs = quad->shared_quad_state;
+
+ // If |shared_quad_state| of the current quad is different than the last
+ // quad we know to advance |sqs_iter| as well.
+ if (from_sqs != last_quad_from_sqs) {
+ DCHECK(sqs_iter != render_pass->shared_quad_state_list.end());
+ ++sqs_iter;
+ last_quad_from_sqs = from_sqs;
+ }
+
+ quad->shared_quad_state = *sqs_iter;
+ ++quad_iter;
+ }
+ DCHECK(++sqs_iter == render_pass->shared_quad_state_list.end());
+
+ // Set the entire frame as damaged.
+ render_pass->damage_rect = render_pass->output_rect;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display/damage_frame_annotator.h b/chromium/components/viz/service/display/damage_frame_annotator.h
new file mode 100644
index 00000000000..cab64d7c611
--- /dev/null
+++ b/chromium/components/viz/service/display/damage_frame_annotator.h
@@ -0,0 +1,50 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_DAMAGE_FRAME_ANNOTATOR_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_DAMAGE_FRAME_ANNOTATOR_H_
+
+#include <vector>
+
+#include "components/viz/service/display/surface_aggregator.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
+
+namespace viz {
+
+class CompositorFrame;
+class RenderPass;
+
+// Draws a red outline around the root RenderPasses damage rect.
+class DamageFrameAnnotator : public SurfaceAggregator::FrameAnnotator {
+ public:
+ DamageFrameAnnotator();
+ ~DamageFrameAnnotator() override;
+
+ // SurfaceAggregator::FrameAnnotator implementation.
+ void AnnotateAggregatedFrame(CompositorFrame* frame) override;
+
+ private:
+ struct Highlight {
+ SkColor color;
+ int width;
+ };
+
+ struct AnnotationData {
+ gfx::Rect rect;
+ gfx::Transform transform;
+ Highlight highlight;
+ };
+
+ void AnnotateRootRenderPass(RenderPass* render_pass);
+
+ std::vector<AnnotationData> annotations_;
+
+ DISALLOW_COPY_AND_ASSIGN(DamageFrameAnnotator);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_DAMAGE_FRAME_ANNOTATOR_H_
diff --git a/chromium/components/viz/service/display/dc_layer_overlay.cc b/chromium/components/viz/service/display/dc_layer_overlay.cc
index 3af9996be7b..4586f58777e 100644
--- a/chromium/components/viz/service/display/dc_layer_overlay.cc
+++ b/chromium/components/viz/service/display/dc_layer_overlay.cc
@@ -7,13 +7,18 @@
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
+#include "components/viz/common/display/renderer_settings.h"
+#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/config/gpu_finch_features.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gl/gl_switches.h"
@@ -21,11 +26,14 @@ namespace viz {
namespace {
+constexpr int kDCLayerDebugBorderWidth = 4;
+constexpr gfx::Insets kDCLayerDebugBorderInsets = gfx::Insets(-2);
+
// This is used for a histogram to determine why overlays are or aren't used,
// so don't remove entries and make sure to update enums.xml if it changes.
enum DCLayerResult {
DC_LAYER_SUCCESS,
- DC_LAYER_FAILED_UNSUPPORTED_QUAD,
+ DC_LAYER_FAILED_UNSUPPORTED_QUAD, // not recorded
DC_LAYER_FAILED_QUAD_BLEND_MODE,
DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE,
DC_LAYER_FAILED_OCCLUDED,
@@ -33,57 +41,85 @@ enum DCLayerResult {
DC_LAYER_FAILED_TRANSPARENT,
DC_LAYER_FAILED_NON_ROOT,
DC_LAYER_FAILED_TOO_MANY_OVERLAYS,
- DC_LAYER_FAILED_NO_HW_OVERLAY_SUPPORT,
- kMaxValue = DC_LAYER_FAILED_NO_HW_OVERLAY_SUPPORT,
+ DC_LAYER_FAILED_NO_HW_OVERLAY_SUPPORT, // deprecated
+ DC_LAYER_FAILED_ROUNDED_CORNERS,
+ DC_LAYER_FAILED_BACKDROP_FILTERS,
+ kMaxValue = DC_LAYER_FAILED_BACKDROP_FILTERS,
+};
+
+enum : size_t {
+ kTextureResourceIndex = 0,
+ kYPlaneResourceIndex = 0,
+ kUVPlaneResourceIndex = 1,
};
+// This returns the smallest rectangle in target space that contains the quad.
+gfx::RectF ClippedQuadRectangle(const DrawQuad* quad) {
+ gfx::RectF quad_rect = cc::MathUtil::MapClippedRect(
+ quad->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(quad->rect));
+ if (quad->shared_quad_state->is_clipped)
+ quad_rect.Intersect(gfx::RectF(quad->shared_quad_state->clip_rect));
+ return quad_rect;
+}
+
DCLayerResult FromYUVQuad(const YUVVideoDrawQuad* quad,
const gfx::Transform& transform_to_root_target,
+ const std::vector<gfx::Rect>& backdrop_filter_rects,
bool has_hw_overlay_support,
int current_frame_processed_overlay_count,
DisplayResourceProvider* resource_provider,
DCLayerOverlay* dc_layer) {
+ // To support software protected video on machines without hardware overlay
+ // capability. Don't do dc layer overlay if no hardware support.
+ gfx::ProtectedVideoType protected_video_type = quad->protected_video_type;
+ bool allow_video_overlay =
+ has_hw_overlay_support ||
+ (protected_video_type == gfx::ProtectedVideoType::kSoftwareProtected &&
+ base::FeatureList::IsEnabled(
+ features::kUseDCOverlaysForSoftwareProtectedVideo));
+ if (!allow_video_overlay)
+ return DC_LAYER_FAILED_UNSUPPORTED_QUAD;
+
// Check that resources are overlay compatible first so that subsequent
// assumptions are valid.
for (const auto& resource : quad->resources) {
if (!resource_provider->IsOverlayCandidate(resource))
return DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE;
}
+
// Hardware protected video must use Direct Composition Overlay
- if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver &&
- quad->protected_video_type !=
- gfx::ProtectedVideoType::kHardwareProtected) {
- return DC_LAYER_FAILED_QUAD_BLEND_MODE;
- }
- // To support software protected video on machines without hardware overlay
- // capability. Don't do dc layer overlay if no hardware support.
- if (!has_hw_overlay_support &&
- quad->protected_video_type !=
- gfx::ProtectedVideoType::kSoftwareProtected) {
- return DC_LAYER_FAILED_NO_HW_OVERLAY_SUPPORT;
- }
+ if (protected_video_type != gfx::ProtectedVideoType::kHardwareProtected) {
+ if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
+ return DC_LAYER_FAILED_QUAD_BLEND_MODE;
+
+ bool is_axis_aligned = quad->shared_quad_state->quad_to_target_transform
+ .Preserves2dAxisAlignment();
+ if (!is_axis_aligned && !base::FeatureList::IsEnabled(
+ features::kDirectCompositionComplexOverlays)) {
+ return DC_LAYER_FAILED_COMPLEX_TRANSFORM;
+ }
- if (!quad->shared_quad_state->quad_to_target_transform
- .Preserves2dAxisAlignment() &&
- quad->protected_video_type !=
- gfx::ProtectedVideoType::kHardwareProtected &&
- !base::FeatureList::IsEnabled(
- features::kDirectCompositionComplexOverlays)) {
- return DC_LAYER_FAILED_COMPLEX_TRANSFORM;
- }
+ if (current_frame_processed_overlay_count > 0)
+ return DC_LAYER_FAILED_TOO_MANY_OVERLAYS;
- if (current_frame_processed_overlay_count > 0 &&
- quad->protected_video_type !=
- gfx::ProtectedVideoType::kHardwareProtected) {
- return DC_LAYER_FAILED_TOO_MANY_OVERLAYS;
+ // Rounded corner on overlays are not supported.
+ if (!quad->shared_quad_state->rounded_corner_bounds.IsEmpty())
+ return DC_LAYER_FAILED_ROUNDED_CORNERS;
+
+ auto quad_target_rect = gfx::ToEnclosingRect(ClippedQuadRectangle(quad));
+ for (const auto& filter_target_rect : backdrop_filter_rects) {
+ if (filter_target_rect.Intersects(quad_target_rect))
+ return DC_LAYER_FAILED_BACKDROP_FILTERS;
+ }
}
// Direct composition path only supports single NV12 buffer, or two buffers
// one each for Y and UV planes.
DCHECK(quad->y_plane_resource_id() && quad->u_plane_resource_id());
DCHECK_EQ(quad->u_plane_resource_id(), quad->v_plane_resource_id());
- dc_layer->y_resource_id = quad->y_plane_resource_id();
- dc_layer->uv_resource_id = quad->u_plane_resource_id();
+ dc_layer->resources[kYPlaneResourceIndex] = quad->y_plane_resource_id();
+ dc_layer->resources[kUVPlaneResourceIndex] = quad->u_plane_resource_id();
dc_layer->z_order = 1;
dc_layer->content_rect = gfx::ToNearestRect(quad->ya_tex_coord_rect);
@@ -94,7 +130,7 @@ DCLayerResult FromYUVQuad(const YUVVideoDrawQuad* quad,
quad->shared_quad_state->quad_to_target_transform);
quad_to_root_transform.ConcatTransform(transform_to_root_target);
// Flatten transform to 2D since DirectComposition doesn't support 3D
- // transforms.
+ // transforms. This only applies when non axis aligned overlays are enabled.
quad_to_root_transform.FlattenTo2d();
dc_layer->transform = quad_to_root_transform;
@@ -112,6 +148,69 @@ DCLayerResult FromYUVQuad(const YUVVideoDrawQuad* quad,
return DC_LAYER_SUCCESS;
}
+DCLayerResult FromTextureQuad(
+ const TextureDrawQuad* quad,
+ const gfx::Transform& transform_to_root_target,
+ const std::vector<gfx::Rect>& backdrop_filter_rects,
+ DisplayResourceProvider* resource_provider,
+ DCLayerOverlay* dc_layer) {
+ // Check that resources are overlay compatible first so that subsequent
+ // assumptions are valid.
+ for (const auto& resource : quad->resources) {
+ if (!resource_provider->IsOverlayCandidate(resource))
+ return DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE;
+ }
+
+ if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
+ return DC_LAYER_FAILED_QUAD_BLEND_MODE;
+
+ if (!quad->shared_quad_state->quad_to_target_transform
+ .Preserves2dAxisAlignment()) {
+ return DC_LAYER_FAILED_COMPLEX_TRANSFORM;
+ }
+
+ // Rounded corner on overlays are not supported.
+ if (!quad->shared_quad_state->rounded_corner_bounds.IsEmpty())
+ return DC_LAYER_FAILED_ROUNDED_CORNERS;
+
+ auto quad_target_rect = gfx::ToEnclosingRect(ClippedQuadRectangle(quad));
+ for (const auto& filter_target_rect : backdrop_filter_rects) {
+ if (filter_target_rect.Intersects(quad_target_rect))
+ return DC_LAYER_FAILED_BACKDROP_FILTERS;
+ }
+
+ dc_layer->resources[kTextureResourceIndex] = quad->resource_id();
+ dc_layer->z_order = 1;
+ dc_layer->content_rect = gfx::Rect(quad->resource_size_in_pixels());
+ dc_layer->quad_rect = quad->rect;
+ // Quad rect is in quad content space so both quad to target, and target to
+ // root transforms must be applied to it.
+ gfx::Transform quad_to_root_transform;
+ if (quad->y_flipped) {
+ quad_to_root_transform.Scale(1.0, -1.0);
+ quad_to_root_transform.PostTranslate(0.0, dc_layer->content_rect.height());
+ }
+ quad_to_root_transform.ConcatTransform(
+ quad->shared_quad_state->quad_to_target_transform);
+ quad_to_root_transform.ConcatTransform(transform_to_root_target);
+ // Flatten transform to 2D since DirectComposition doesn't support 3D
+ // transforms. This only applies when non axis aligned overlays are enabled.
+ quad_to_root_transform.FlattenTo2d();
+ dc_layer->transform = quad_to_root_transform;
+
+ dc_layer->is_clipped = quad->shared_quad_state->is_clipped;
+ if (dc_layer->is_clipped) {
+ // Clip rect is in quad target space, and must be transformed to root target
+ // space.
+ gfx::RectF clip_rect = gfx::RectF(quad->shared_quad_state->clip_rect);
+ transform_to_root_target.TransformRect(&clip_rect);
+ dc_layer->clip_rect = gfx::ToEnclosingRect(clip_rect);
+ }
+ dc_layer->color_space = gfx::ColorSpace::CreateSRGB();
+
+ return DC_LAYER_SUCCESS;
+}
+
DCLayerResult IsUnderlayAllowed(const QuadList::Iterator& it,
bool is_root,
const DCLayerOverlay& dc_layer) {
@@ -130,16 +229,6 @@ DCLayerResult IsUnderlayAllowed(const QuadList::Iterator& it,
return DC_LAYER_SUCCESS;
}
-// This returns the smallest rectangle in target space that contains the quad.
-gfx::RectF ClippedQuadRectangle(const DrawQuad* quad) {
- gfx::RectF quad_rect = cc::MathUtil::MapClippedRect(
- quad->shared_quad_state->quad_to_target_transform,
- gfx::RectF(quad->rect));
- if (quad->shared_quad_state->is_clipped)
- quad_rect.Intersect(gfx::RectF(quad->shared_quad_state->clip_rect));
- return quad_rect;
-}
-
// Any occluding quads in the quad list on top of the overlay/underlay
bool HasOccludingQuads(const gfx::RectF& target_quad,
QuadList::ConstIterator quad_list_begin,
@@ -164,20 +253,41 @@ bool HasOccludingQuads(const gfx::RectF& target_quad,
return false;
}
-void RecordDCLayerResult(DCLayerResult result,
- gfx::ProtectedVideoType protected_video_type) {
+void RecordVideoDCLayerResult(DCLayerResult result,
+ gfx::ProtectedVideoType protected_video_type) {
switch (protected_video_type) {
case gfx::ProtectedVideoType::kClear:
- UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.DCLayerResult2.Clear",
- result);
+ UMA_HISTOGRAM_ENUMERATION(
+ "GPU.DirectComposition.DCLayerResult.Video.Clear", result);
break;
case gfx::ProtectedVideoType::kSoftwareProtected:
UMA_HISTOGRAM_ENUMERATION(
- "GPU.DirectComposition.DCLayerResult2.SoftwareProtected", result);
+ "GPU.DirectComposition.DCLayerResult.Video.SoftwareProtected",
+ result);
break;
case gfx::ProtectedVideoType::kHardwareProtected:
UMA_HISTOGRAM_ENUMERATION(
- "GPU.DirectComposition.DCLayerResult2.HardwareProtected", result);
+ "GPU.DirectComposition.DCLayerResult.Video.HardwareProtected",
+ result);
+ break;
+ }
+}
+
+void RecordDCLayerResult(DCLayerResult result, QuadList::Iterator it) {
+ // Skip recording unsupported quads since that'd dwarf the data we care about.
+ if (result == DC_LAYER_FAILED_UNSUPPORTED_QUAD)
+ return;
+
+ switch (it->material) {
+ case DrawQuad::Material::kYuvVideoContent:
+ RecordVideoDCLayerResult(
+ result, YUVVideoDrawQuad::MaterialCast(*it)->protected_video_type);
+ break;
+ case DrawQuad::Material::kTextureContent:
+ UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.DCLayerResult.Texture",
+ result);
+ break;
+ default:
break;
}
}
@@ -202,18 +312,21 @@ DCLayerOverlay& DCLayerOverlay::operator=(const DCLayerOverlay& other) =
default;
DCLayerOverlay::~DCLayerOverlay() = default;
+DCLayerOverlayProcessor::RenderPassData::RenderPassData() = default;
+DCLayerOverlayProcessor::RenderPassData::RenderPassData(
+ const RenderPassData& other) = default;
+DCLayerOverlayProcessor::RenderPassData::~RenderPassData() = default;
+
DCLayerOverlayProcessor::DCLayerOverlayProcessor(
- const ContextProvider* context_provider) {
-#if defined(OS_WIN)
- if (context_provider) {
- has_hw_overlay_support_ =
- context_provider->ContextCapabilities().dc_layers &&
- context_provider->ContextCapabilities().use_dc_overlays_for_video;
- } else {
- has_hw_overlay_support_ = false;
- }
-#endif
-}
+ const ContextProvider* context_provider,
+ const RendererSettings& settings)
+ : has_hw_overlay_support_(
+ context_provider &&
+ context_provider->ContextCapabilities().use_dc_overlays_for_video),
+ show_debug_borders_(settings.show_dc_layer_debug_borders) {}
+
+DCLayerOverlayProcessor::DCLayerOverlayProcessor()
+ : has_hw_overlay_support_(true), show_debug_borders_(false) {}
DCLayerOverlayProcessor::~DCLayerOverlayProcessor() = default;
@@ -223,7 +336,7 @@ void DCLayerOverlayProcessor::Process(
RenderPassList* render_passes,
gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays) {
- pass_punch_through_rects_.clear();
+ render_pass_data_.clear();
for (auto& pass : *render_passes) {
bool is_root = (pass == render_passes->back());
ProcessRenderPass(resource_provider, display_rect, pass.get(), is_root,
@@ -246,12 +359,21 @@ QuadList::Iterator DCLayerOverlayProcessor::ProcessRenderPassDrawQuad(
const RenderPassDrawQuad* rpdq = RenderPassDrawQuad::MaterialCast(*it);
++it;
- // Check if this quad is broken to avoid corrupting pass_info.
+ // Check if this quad is broken to avoid corrupting |render_pass_data_|.
if (rpdq->render_pass_id == render_pass->id)
return it;
- // |pass_punch_through_rects_| will be empty unless non-root overlays are
- // enabled.
- if (!pass_punch_through_rects_.count(rpdq->render_pass_id))
+
+ // This will be filled in for all render passes even non-root overlays are
+ // disabled.
+ const auto& render_pass_data = render_pass_data_[rpdq->render_pass_id];
+ if (render_pass_data.has_backdrop_filters) {
+ render_pass_data_[render_pass->id].backdrop_filter_rects.push_back(
+ gfx::ToEnclosingRect(ClippedQuadRectangle(rpdq)));
+ }
+
+ // |punch_through_rects| will be empty unless non-root overlays are enabled.
+ const auto& punch_through_rects = render_pass_data.punch_through_rects;
+ if (punch_through_rects.empty())
return it;
// Punch holes through for all child video quads that will be displayed in
@@ -294,24 +416,21 @@ QuadList::Iterator DCLayerOverlayProcessor::ProcessRenderPassDrawQuad(
// color mask in solid color draw quad which we don't have today. Another
// difficulty is undoing the SrcOver blending in child render passes if any
// render pass above has a non-supported blend mode.
- const auto& punch_through_rects =
- pass_punch_through_rects_[rpdq->render_pass_id];
const SharedQuadState* original_shared_quad_state = rpdq->shared_quad_state;
+ // Copy shared state from RPDQ to get the same clip rect.
+ SharedQuadState* new_shared_quad_state =
+ render_pass->shared_quad_state_list.AllocateAndCopyFrom(
+ original_shared_quad_state);
+ // Set opacity to 1 since we're not blending.
+ new_shared_quad_state->opacity = 1.f;
+
// The iterator was advanced above so InsertBefore inserts after the RPDQ.
it = render_pass->quad_list
.InsertBeforeAndInvalidateAllPointers<SolidColorDrawQuad>(
it, punch_through_rects.size());
rpdq = nullptr;
for (const gfx::Rect& punch_through_rect : punch_through_rects) {
- // Copy shared state from RPDQ to get the same clip rect.
- SharedQuadState* new_shared_quad_state =
- render_pass->shared_quad_state_list
- .AllocateAndCopyFrom<SharedQuadState>(original_shared_quad_state);
-
- // Set opacity to 1 since we're not blending.
- new_shared_quad_state->opacity = 1.f;
-
auto* solid_quad = static_cast<SolidColorDrawQuad*>(*it++);
solid_quad->SetAll(new_shared_quad_state, punch_through_rect,
punch_through_rect, false, SK_ColorTRANSPARENT, true);
@@ -326,11 +445,52 @@ QuadList::Iterator DCLayerOverlayProcessor::ProcessRenderPassDrawQuad(
// Add transformed info to list in case this renderpass is included in
// another pass.
- pass_punch_through_rects_[render_pass->id].push_back(clipped_quad_rect);
+ render_pass_data_[render_pass->id].punch_through_rects.push_back(
+ clipped_quad_rect);
}
return it;
}
+void DCLayerOverlayProcessor::InsertDebugBorderDrawQuads(
+ const gfx::RectF& display_rect,
+ const gfx::Rect& overlay_rect,
+ RenderPass* root_render_pass,
+ gfx::Rect* damage_rect) {
+ auto* shared_quad_state = root_render_pass->CreateAndAppendSharedQuadState();
+ auto& quad_list = root_render_pass->quad_list;
+
+ if (!overlay_rect.IsEmpty()) {
+ auto it =
+ quad_list.InsertBeforeAndInvalidateAllPointers<DebugBorderDrawQuad>(
+ quad_list.begin(), 1u);
+ auto* debug_quad = static_cast<DebugBorderDrawQuad*>(*it);
+ gfx::Rect rect = overlay_rect;
+ rect.Inset(kDCLayerDebugBorderInsets);
+ debug_quad->SetNew(shared_quad_state, rect, rect, SK_ColorRED,
+ kDCLayerDebugBorderWidth);
+ }
+
+ const auto& punch_through_rects =
+ render_pass_data_[root_render_pass->id].punch_through_rects;
+
+ auto it = quad_list.InsertBeforeAndInvalidateAllPointers<DebugBorderDrawQuad>(
+ quad_list.begin(), punch_through_rects.size());
+
+ for (const gfx::Rect& punch_through_rect : punch_through_rects) {
+ auto* debug_quad = static_cast<DebugBorderDrawQuad*>(*it++);
+ gfx::Rect rect = punch_through_rect;
+ rect.Inset(kDCLayerDebugBorderInsets);
+ debug_quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLUE,
+ kDCLayerDebugBorderWidth);
+ }
+
+ // Mark the entire output as damaged because the border quads might not be
+ // inside the current damage rect. It's far simpler to mark the entire output
+ // as damaged instead of accounting for individual border quads which can
+ // change positions across frames.
+ damage_rect->Union(gfx::ToEnclosingRect(display_rect));
+}
+
void DCLayerOverlayProcessor::ProcessRenderPass(
DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
@@ -338,8 +498,18 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
bool is_root,
gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays) {
+ gfx::Rect this_frame_overlay_rect;
gfx::Rect this_frame_underlay_rect;
+ // Always fill in |has_backdrop_filters| even if non-root overlays are
+ // disabled because it's needed to reject overlays that are read by backdrop
+ // filters. Note that the backdrop filter rejection doesn't work properly for
+ // overlays that are in non-root render passes since we can't determine if
+ // there's an indirect ancestor render pass which has child RPDQs that could
+ // read this quad's output.
+ render_pass_data_[render_pass->id].has_backdrop_filters =
+ !render_pass->backdrop_filters.IsEmpty();
+
QuadList* quad_list = &render_pass->quad_list;
auto next_it = quad_list->begin();
for (auto it = quad_list->begin(); it != quad_list->end(); it = next_it) {
@@ -355,23 +525,28 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
DCLayerOverlay dc_layer;
DCLayerResult result;
- auto uma_protected_video_type = gfx::ProtectedVideoType::kClear;
switch (it->material) {
case DrawQuad::Material::kYuvVideoContent:
- result = FromYUVQuad(YUVVideoDrawQuad::MaterialCast(*it),
- render_pass->transform_to_root_target,
- has_hw_overlay_support_,
- current_frame_processed_overlay_count_,
- resource_provider, &dc_layer);
- uma_protected_video_type =
- YUVVideoDrawQuad::MaterialCast(*it)->protected_video_type;
+ result = FromYUVQuad(
+ YUVVideoDrawQuad::MaterialCast(*it),
+ render_pass->transform_to_root_target,
+ render_pass_data_[render_pass->id].backdrop_filter_rects,
+ has_hw_overlay_support_, current_frame_processed_overlay_count_,
+ resource_provider, &dc_layer);
+ break;
+ case DrawQuad::Material::kTextureContent:
+ result = FromTextureQuad(
+ TextureDrawQuad::MaterialCast(*it),
+ render_pass->transform_to_root_target,
+ render_pass_data_[render_pass->id].backdrop_filter_rects,
+ resource_provider, &dc_layer);
break;
default:
result = DC_LAYER_FAILED_UNSUPPORTED_QUAD;
}
if (result != DC_LAYER_SUCCESS) {
- RecordDCLayerResult(result, uma_protected_video_type);
+ RecordDCLayerResult(result, it);
continue;
}
@@ -390,10 +565,11 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
if (!is_overlay) {
result = IsUnderlayAllowed(it, is_root, dc_layer);
if (result != DC_LAYER_SUCCESS) {
- RecordDCLayerResult(result, uma_protected_video_type);
+ RecordDCLayerResult(result, it);
continue;
}
}
+ RecordDCLayerResult(DC_LAYER_SUCCESS, it);
// Quad is always promoted to either an underlay or an overlay after this
// point. It should not fail.
@@ -421,11 +597,10 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
// TODO(magchen): Collect all overlay candidates, and filter the list at the
// end to find the best candidates (largest size?).
if (is_overlay) {
- ProcessForOverlay(display_rect, quad_list, quad_rectangle_in_target_space,
- &it, damage_rect);
- // ProcessForOverlay makes the iterator point to the next value on
- // success.
- next_it = it;
+ next_it =
+ ProcessForOverlay(display_rect, render_pass,
+ quad_rectangle_in_target_space, it, damage_rect);
+ this_frame_overlay_rect = quad_rectangle_in_target_space;
} else {
ProcessForUnderlay(display_rect, render_pass,
quad_rectangle_in_target_space, it, is_root,
@@ -436,7 +611,6 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
render_pass->transform_to_root_target, quad_rectangle_in_target_space);
current_frame_overlay_rect_union_.Union(rect_in_root);
- RecordDCLayerResult(DC_LAYER_SUCCESS, dc_layer.protected_video_type);
RecordOverlayHistograms(is_overlay, occluding_damage_rect, damage_rect);
dc_layer_overlays->push_back(dc_layer);
@@ -465,24 +639,31 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
damage_rect->Intersect(gfx::ToEnclosingRect(display_rect));
previous_display_rect_ = display_rect;
previous_frame_underlay_rect_ = this_frame_underlay_rect;
+
+ if (show_debug_borders_) {
+ InsertDebugBorderDrawQuads(display_rect, this_frame_overlay_rect,
+ render_pass, damage_rect);
+ }
}
}
-void DCLayerOverlayProcessor::ProcessForOverlay(const gfx::RectF& display_rect,
- QuadList* quad_list,
- const gfx::Rect& quad_rectangle,
- QuadList::Iterator* it,
- gfx::Rect* damage_rect) {
+QuadList::Iterator DCLayerOverlayProcessor::ProcessForOverlay(
+ const gfx::RectF& display_rect,
+ RenderPass* render_pass,
+ const gfx::Rect& quad_rectangle,
+ const QuadList::Iterator& it,
+ gfx::Rect* damage_rect) {
// The quad is on top, so promote it to an overlay and remove all damage
// underneath it.
- bool display_rect_changed = (display_rect != previous_display_rect_);
- if ((*it)
- ->shared_quad_state->quad_to_target_transform
- .Preserves2dAxisAlignment() &&
- !display_rect_changed && !(*it)->ShouldDrawWithBlending()) {
+ const bool display_rect_changed = (display_rect != previous_display_rect_);
+ const bool is_axis_aligned = it->shared_quad_state->quad_to_target_transform
+ .Preserves2dAxisAlignment();
+ const bool needs_blending = it->ShouldDrawWithBlending();
+
+ if (is_axis_aligned && !display_rect_changed && !needs_blending)
damage_rect->Subtract(quad_rectangle);
- }
- *it = quad_list->EraseAndInvalidateAllPointers(*it);
+
+ return render_pass->quad_list.EraseAndInvalidateAllPointers(it);
}
void DCLayerOverlayProcessor::ProcessForUnderlay(
@@ -500,7 +681,8 @@ void DCLayerOverlayProcessor::ProcessForUnderlay(
dc_layer->z_order = -1 - current_frame_processed_overlay_count_;
const SharedQuadState* shared_quad_state = it->shared_quad_state;
- gfx::Rect rect = it->visible_rect;
+ const gfx::Rect rect = it->visible_rect;
+ const bool needs_blending = it->needs_blending;
// If the video is translucent and uses SrcOver blend mode, we can achieve the
// same result as compositing with video on top if we replace video quad with
@@ -519,12 +701,13 @@ void DCLayerOverlayProcessor::ProcessForUnderlay(
SharedQuadState* new_shared_quad_state =
render_pass->shared_quad_state_list.AllocateAndCopyFrom(
shared_quad_state);
+ new_shared_quad_state->blend_mode = SkBlendMode::kDstOut;
+
auto* replacement =
render_pass->quad_list.ReplaceExistingElement<SolidColorDrawQuad>(it);
- new_shared_quad_state->blend_mode = SkBlendMode::kDstOut;
// Use needs_blending from original quad because blending might be because
// of this flag or opacity.
- replacement->SetAll(new_shared_quad_state, rect, rect, it->needs_blending,
+ replacement->SetAll(new_shared_quad_state, rect, rect, needs_blending,
SK_ColorBLACK, true /* force_anti_aliasing_off */);
} else {
// When the opacity == 1.0, drawing with transparent will be done without
@@ -574,7 +757,7 @@ void DCLayerOverlayProcessor::ProcessForUnderlay(
// Propagate the punched holes up the chain of render passes. Punch through
// rects are in quad target (child render pass) space, and are transformed to
// RPDQ target (parent render pass) in ProcessRenderPassDrawQuad().
- pass_punch_through_rects_[render_pass->id].push_back(
+ render_pass_data_[render_pass->id].punch_through_rects.push_back(
gfx::ToEnclosingRect(ClippedQuadRectangle(*it)));
}
diff --git a/chromium/components/viz/service/display/dc_layer_overlay.h b/chromium/components/viz/service/display/dc_layer_overlay.h
index d358f14098b..8a180655846 100644
--- a/chromium/components/viz/service/display/dc_layer_overlay.h
+++ b/chromium/components/viz/service/display/dc_layer_overlay.h
@@ -17,6 +17,7 @@
namespace viz {
class DisplayResourceProvider;
class ContextProvider;
+class RendererSettings;
// Holds all information necessary to construct a DCLayer from a DrawQuad.
class VIZ_SERVICE_EXPORT DCLayerOverlay {
@@ -36,10 +37,10 @@ class VIZ_SERVICE_EXPORT DCLayerOverlay {
gfx::ProtectedVideoType::kHardwareProtected);
}
- // Resource ids for video Y and UV planes. Can be the same resource.
- // See DirectCompositionSurfaceWin for details.
- ResourceId y_resource_id = 0;
- ResourceId uv_resource_id = 0;
+ // Resource ids for video Y and UV planes, a single NV12 image, or a swap
+ // chain image. See DirectCompositionSurfaceWin for details.
+ enum : size_t { kNumResources = 2 };
+ ResourceId resources[kNumResources] = {kInvalidResourceId};
// Stacking order relative to backbuffer which has z-order 0.
int z_order = 1;
@@ -69,9 +70,12 @@ class VIZ_SERVICE_EXPORT DCLayerOverlay {
typedef std::vector<DCLayerOverlay> DCLayerOverlayList;
-class DCLayerOverlayProcessor {
+class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor {
public:
- explicit DCLayerOverlayProcessor(const ContextProvider* context_provider);
+ DCLayerOverlayProcessor(const ContextProvider* context_provider,
+ const RendererSettings& settings);
+ // For testing.
+ DCLayerOverlayProcessor();
~DCLayerOverlayProcessor();
void Process(DisplayResourceProvider* resource_provider,
@@ -80,7 +84,6 @@ class DCLayerOverlayProcessor {
gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays);
void ClearOverlayState();
- void SetHasHwOverlaySupport() { has_hw_overlay_support_ = true; }
// This is the damage contribution due to previous frame's overlays which can
// be empty.
gfx::Rect previous_frame_overlay_damage_contribution() {
@@ -92,18 +95,18 @@ class DCLayerOverlayProcessor {
QuadList::Iterator ProcessRenderPassDrawQuad(RenderPass* render_pass,
gfx::Rect* damage_rect,
QuadList::Iterator it);
-
void ProcessRenderPass(DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
RenderPass* render_pass,
bool is_root,
gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays);
- void ProcessForOverlay(const gfx::RectF& display_rect,
- QuadList* quad_list,
- const gfx::Rect& quad_rectangle,
- QuadList::Iterator* it,
- gfx::Rect* damage_rect);
+ // Returns an iterator to the element after |it|.
+ QuadList::Iterator ProcessForOverlay(const gfx::RectF& display_rect,
+ RenderPass* render_pass,
+ const gfx::Rect& quad_rectangle,
+ const QuadList::Iterator& it,
+ gfx::Rect* damage_rect);
void ProcessForUnderlay(const gfx::RectF& display_rect,
RenderPass* render_pass,
const gfx::Rect& quad_rectangle,
@@ -113,6 +116,14 @@ class DCLayerOverlayProcessor {
gfx::Rect* this_frame_underlay_rect,
DCLayerOverlay* dc_layer);
+ void InsertDebugBorderDrawQuads(const gfx::RectF& display_rect,
+ const gfx::Rect& overlay_rect,
+ RenderPass* root_render_pass,
+ gfx::Rect* damage_rect);
+
+ const bool has_hw_overlay_support_;
+ const bool show_debug_borders_;
+
gfx::Rect previous_frame_underlay_rect_;
gfx::RectF previous_display_rect_;
// previous and current overlay_rect_union_ include both overlay and underlay
@@ -120,13 +131,26 @@ class DCLayerOverlayProcessor {
gfx::Rect current_frame_overlay_rect_union_;
int previous_frame_processed_overlay_count_ = 0;
int current_frame_processed_overlay_count_ = 0;
- bool has_hw_overlay_support_ = true;
- // Store information about clipped punch-through rects in target space for
- // non-root render passes. These rects are used to clear the corresponding
- // areas in parent render passes.
- base::flat_map<RenderPassId, std::vector<gfx::Rect>>
- pass_punch_through_rects_;
+ struct RenderPassData {
+ RenderPassData();
+ RenderPassData(const RenderPassData& other);
+ ~RenderPassData();
+
+ // Store information about clipped punch-through rects in target space for
+ // non-root render passes. These rects are used to clear the corresponding
+ // areas in parent render passes.
+ std::vector<gfx::Rect> punch_through_rects;
+
+ // Output rects of child render passes that have backdrop filters in target
+ // space. These rects are used to determine if the overlay rect could be
+ // read by backdrop filters.
+ std::vector<gfx::Rect> backdrop_filter_rects;
+
+ // Whether this render pass has backdrop filters.
+ bool has_backdrop_filters = false;
+ };
+ base::flat_map<RenderPassId, RenderPassData> render_pass_data_;
DISALLOW_COPY_AND_ASSIGN(DCLayerOverlayProcessor);
};
diff --git a/chromium/components/viz/service/display/direct_renderer.cc b/chromium/components/viz/service/display/direct_renderer.cc
index 324ed86606b..57afe8186fb 100644
--- a/chromium/components/viz/service/display/direct_renderer.cc
+++ b/chromium/components/viz/service/display/direct_renderer.cc
@@ -114,6 +114,9 @@ DirectRenderer::DirectRenderer(const RendererSettings* settings,
DirectRenderer::~DirectRenderer() = default;
void DirectRenderer::Initialize() {
+ // Create an overlay validator based on the platform and set it on the newly
+ // created processor. This would initialize the strategies on the validator as
+ // well.
// Create overlay validator based on the platform and set it on the newly
// created processor. This would initialize the strategies on the validator as
// well.
@@ -373,19 +376,16 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
// TODO(weiliangc): Remove once reflector code is removed.
overlay_processor_->SetSoftwareMirrorMode(
output_surface_->IsSoftwareMirrorMode());
- // Create the overlay candidate for the output surface, and mark it as
- // always handled.
+
+ // Before ProcessForOverlay calls into the hardware to ask about whether the
+ // overlay setup can be handled, we need to set up the primary plane.
+ OverlayProcessor::OutputSurfaceOverlayPlane* primary_plane = nullptr;
if (output_surface_->IsDisplayedAsOverlayPlane()) {
- OverlayCandidate output_surface_plane;
- output_surface_plane.display_rect =
- gfx::RectF(device_viewport_size.width(), device_viewport_size.height());
- output_surface_plane.resource_size_in_pixels = device_viewport_size;
- output_surface_plane.format = output_surface_->GetOverlayBufferFormat();
- output_surface_plane.color_space = reshape_device_color_space_;
- output_surface_plane.use_output_surface_for_resource = true;
- output_surface_plane.overlay_handled = true;
- output_surface_plane.is_opaque = true;
- current_frame()->overlay_list.push_back(output_surface_plane);
+ current_frame()->output_surface_plane =
+ overlay_processor_->ProcessOutputSurfaceAsOverlay(
+ device_viewport_size, output_surface_->GetOverlayBufferFormat(),
+ reshape_device_color_space_);
+ primary_plane = &(current_frame()->output_surface_plane.value());
}
// Attempt to replace some or all of the quads of the root render pass with
@@ -393,12 +393,15 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
overlay_processor_->ProcessForOverlays(
resource_provider_, render_passes_in_draw_order,
output_surface_->color_matrix(), render_pass_filters_,
- render_pass_backdrop_filters_, &current_frame()->overlay_list,
- &current_frame()->ca_layer_overlay_list,
+ render_pass_backdrop_filters_, primary_plane,
+ &current_frame()->overlay_list, &current_frame()->ca_layer_overlay_list,
&current_frame()->dc_layer_overlay_list,
&current_frame()->root_damage_rect,
&current_frame()->root_content_bounds);
+ overlay_processor_->AdjustOutputSurfaceOverlay(
+ &(current_frame()->output_surface_plane));
+
bool was_using_dc_layers = using_dc_layers_;
if (!current_frame()->dc_layer_overlay_list.empty()) {
DCHECK(supports_dc_layers_);
@@ -445,12 +448,9 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
// through other means on the service side.
// TODO(afrantzis): Consider using per-overlay fences instead of the one
// associated with the output surface when possible.
- if (!current_frame()->overlay_list.empty()) {
- for (auto& overlay : current_frame()->overlay_list) {
- if (overlay.use_output_surface_for_resource)
- overlay.gpu_fence_id = output_surface_->UpdateGpuFence();
- }
- }
+ if (current_frame()->output_surface_plane)
+ current_frame()->output_surface_plane->gpu_fence_id =
+ output_surface_->UpdateGpuFence();
FinishDrawingFrame();
render_passes_in_draw_order->clear();
diff --git a/chromium/components/viz/service/display/direct_renderer.h b/chromium/components/viz/service/display/direct_renderer.h
index 173515a102e..4454da52a6d 100644
--- a/chromium/components/viz/service/display/direct_renderer.h
+++ b/chromium/components/viz/service/display/direct_renderer.h
@@ -93,6 +93,11 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
OverlayCandidateList overlay_list;
CALayerOverlayList ca_layer_overlay_list;
DCLayerOverlayList dc_layer_overlay_list;
+ // When we have a buffer queue, the output surface could be treated as an
+ // overlay plane, and the struct to store that information is in
+ // |output_surface_plane|.
+ base::Optional<OverlayProcessor::OutputSurfaceOverlayPlane>
+ output_surface_plane;
};
void SetCurrentFrameForTesting(const DrawingFrame& frame);
diff --git a/chromium/components/viz/service/display/display.cc b/chromium/components/viz/service/display/display.cc
index 72373b840b5..7e47c53642e 100644
--- a/chromium/components/viz/service/display/display.cc
+++ b/chromium/components/viz/service/display/display.cc
@@ -22,6 +22,7 @@
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/shared_quad_state.h"
+#include "components/viz/service/display/damage_frame_annotator.h"
#include "components/viz/service/display/direct_renderer.h"
#include "components/viz/service/display/display_client.h"
#include "components/viz/service/display/display_scheduler.h"
@@ -35,7 +36,8 @@
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "gpu/command_buffer/client/gles2_interface.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "gpu/ipc/scheduler_sequence.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/overlay_transform_utils.h"
@@ -148,6 +150,10 @@ Display::Display(
}
Display::~Display() {
+#if DCHECK_IS_ON()
+ allow_schedule_gpu_task_during_destruction_.reset(
+ new gpu::ScopedAllowScheduleGpuTask);
+#endif
#if defined(OS_ANDROID)
// In certain cases, drivers hang when tearing down the display. Finishing
// before teardown appears to address this. As we're during display teardown,
@@ -187,6 +193,7 @@ void Display::Initialize(DisplayClient* client,
bool enable_shared_images) {
DCHECK(client);
DCHECK(surface_manager);
+ gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
client_ = client;
surface_manager_ = surface_manager;
if (scheduler_)
@@ -372,9 +379,12 @@ void Display::InitializeRenderer(bool enable_shared_images) {
renderer_->use_partial_swap() && !renderer_->has_overlay_validator();
bool needs_surface_occluding_damage_rect =
renderer_->OverlayNeedsSurfaceOccludingDamageRect();
- aggregator_.reset(new SurfaceAggregator(
+ aggregator_ = std::make_unique<SurfaceAggregator>(
surface_manager_, resource_provider_.get(), output_partial_list,
- needs_surface_occluding_damage_rect));
+ needs_surface_occluding_damage_rect);
+ if (settings_.show_aggregated_damage)
+ aggregator_->SetFrameAnnotator(std::make_unique<DamageFrameAnnotator>());
+
aggregator_->set_output_is_secure(output_is_secure_);
aggregator_->SetOutputColorSpace(device_color_space_);
// Consider adding a softare limit as well.
@@ -403,6 +413,7 @@ void Display::OnContextLost() {
bool Display::DrawAndSwap() {
TRACE_EVENT0("viz", "Display::DrawAndSwap");
+ gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
if (!current_surface_id_.is_valid()) {
TRACE_EVENT_INSTANT0("viz", "No root surface.", TRACE_EVENT_SCOPE_THREAD);
@@ -530,6 +541,22 @@ bool Display::DrawAndSwap() {
UMA_HISTOGRAM_COUNTS_1M("Compositing.DirectRenderer.GL.DrawFrameUs",
draw_timer->Elapsed().InMicroseconds());
}
+
+ std::vector<std::unique_ptr<Surface::PresentationHelper>>
+ presentation_helper_list;
+ for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
+ Surface* surface = surface_manager_->GetSurfaceForId(id_entry.first);
+ if (surface) {
+ std::unique_ptr<Surface::PresentationHelper> helper =
+ surface->TakePresentationHelperForPresentNotification();
+ if (helper) {
+ surface->OnWasDrawn(helper->frame_token(), draw_timer->Begin());
+ presentation_helper_list.push_back(std::move(helper));
+ }
+ }
+ }
+ pending_surfaces_with_presentation_helpers_.emplace_back(
+ std::make_pair(now_time, std::move(presentation_helper_list)));
} else {
TRACE_EVENT_INSTANT0("viz", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD);
}
@@ -549,18 +576,6 @@ bool Display::DrawAndSwap() {
scheduler_->current_frame_time());
}
- std::vector<std::unique_ptr<Surface::PresentationHelper>>
- presentation_helper_list;
- for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
- Surface* surface = surface_manager_->GetSurfaceForId(id_entry.first);
- if (surface) {
- presentation_helper_list.push_back(
- surface->TakePresentationHelperForPresentNotification());
- }
- }
- pending_surfaces_with_presentation_helpers_.emplace_back(
- std::make_pair(now_time, std::move(presentation_helper_list)));
-
ui::LatencyInfo::TraceIntermediateFlowEvents(frame.metadata.latency_info,
"Display::DrawAndSwap");
@@ -681,8 +696,7 @@ void Display::DidReceivePresentationFeedback(
"benchmark,viz", "Display::FrameDisplayed", TRACE_EVENT_SCOPE_THREAD,
copy_feedback.timestamp);
for (auto& presentation_helper : presentation_helper_list) {
- if (presentation_helper)
- presentation_helper->DidPresent(feedback);
+ presentation_helper->DidPresent(copy_feedback);
}
pending_surfaces_with_presentation_helpers_.pop_front();
}
@@ -738,6 +752,16 @@ bool Display::SurfaceHasUnackedFrame(const SurfaceId& surface_id) const {
void Display::DidFinishFrame(const BeginFrameAck& ack) {
for (auto& observer : observers_)
observer.OnDisplayDidFinishFrame(ack);
+
+ // Only used with experimental de-jelly effect. Forces us to produce a new
+ // un-skewed frame if the last one had a de-jelly skew applied. This prevents
+ // de-jelly skew from staying on screen for more than one frame.
+ if (aggregator_ && aggregator_->last_frame_had_jelly()) {
+ if (scheduler_) {
+ scheduler_->SetNeedsOneBeginFrame();
+ scheduler_->set_needs_draw();
+ }
+ }
}
const SurfaceId& Display::CurrentSurfaceId() {
diff --git a/chromium/components/viz/service/display/display.h b/chromium/components/viz/service/display/display.h
index f50f05a7a07..1e01b183224 100644
--- a/chromium/components/viz/service/display/display.h
+++ b/chromium/components/viz/service/display/display.h
@@ -37,6 +37,10 @@ namespace gfx {
class Size;
}
+namespace gpu {
+class ScopedAllowScheduleGpuTask;
+}
+
namespace viz {
class DirectRenderer;
class DisplayClient;
@@ -197,6 +201,10 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
bool swapped_since_resize_ = false;
bool output_is_secure_ = false;
+#if DCHECK_IS_ON()
+ std::unique_ptr<gpu::ScopedAllowScheduleGpuTask>
+ allow_schedule_gpu_task_during_destruction_;
+#endif
std::unique_ptr<OutputSurface> output_surface_;
SkiaOutputSurface* const skia_output_surface_;
std::unique_ptr<DisplayScheduler> scheduler_;
diff --git a/chromium/components/viz/service/display/display_resource_provider.cc b/chromium/components/viz/service/display/display_resource_provider.cc
index 3036bc79025..d7988806b69 100644
--- a/chromium/components/viz/service/display/display_resource_provider.cc
+++ b/chromium/components/viz/service/display/display_resource_provider.cc
@@ -4,6 +4,9 @@
#include "components/viz/service/display/display_resource_provider.h"
+#include <algorithm>
+#include <string>
+
#include "base/atomic_sequence_num.h"
#include "base/numerics/safe_math.h"
#include "base/stl_util.h"
@@ -486,7 +489,8 @@ DisplayResourceProvider::LockForRead(ResourceId id) {
}
resource->SetLocallyUsed();
}
- if (mailbox.IsSharedImage() && enable_shared_images_) {
+ if (mailbox.IsSharedImage() && enable_shared_images_ &&
+ resource->lock_for_read_count == 0) {
gl->BeginSharedImageAccessDirectCHROMIUM(
resource->gl_id, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
}
@@ -528,73 +532,19 @@ void DisplayResourceProvider::UnlockForRead(ResourceId id) {
ChildResource* resource = &it->second;
DCHECK_GT(resource->lock_for_read_count, 0);
if (resource->transferable.mailbox_holder.mailbox.IsSharedImage() &&
- resource->is_gpu_resource_type() && enable_shared_images_) {
+ resource->is_gpu_resource_type() && enable_shared_images_ &&
+ resource->lock_for_read_count == 1) {
DCHECK(resource->gl_id);
GLES2Interface* gl = ContextGL();
DCHECK(gl);
gl->EndSharedImageAccessDirectCHROMIUM(resource->gl_id);
}
resource->lock_for_read_count--;
- TryReleaseResource(it);
+ TryReleaseResource(id, resource);
}
-ResourceMetadata DisplayResourceProvider::LockForExternalUse(ResourceId id) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- auto it = resources_.find(id);
- DCHECK(it != resources_.end());
-
- ChildResource* resource = &it->second;
- ResourceMetadata metadata;
- // Make sure there is no outstanding LockForExternalUse without calling
- // UnlockForExternalUse.
- DCHECK(!resource->locked_for_external_use);
- // TODO(penghuang): support software resource.
- DCHECK(resource->is_gpu_resource_type());
-
- metadata.resource_id = id;
- metadata.mailbox_holder = resource->transferable.mailbox_holder;
- metadata.size = resource->transferable.size;
- metadata.resource_format = resource->transferable.format;
- metadata.mailbox_holder.sync_token = resource->sync_token();
- metadata.color_space = resource->transferable.color_space;
- metadata.origin = kTopLeft_GrSurfaceOrigin;
-
- resource->locked_for_external_use = true;
-
- if (resource->transferable.read_lock_fences_enabled)
- resource->read_lock_fence = current_read_lock_fence_;
-
- return metadata;
-}
-
-void DisplayResourceProvider::UnlockForExternalUse(
- ResourceId id,
- const gpu::SyncToken& sync_token) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- auto it = resources_.find(id);
- DCHECK(it != resources_.end());
- DCHECK(sync_token.verified_flush());
-
- ChildResource* resource = &it->second;
- DCHECK(resource->locked_for_external_use);
- // TODO(penghuang): support software resource.
- DCHECK(resource->is_gpu_resource_type());
-
- // Update the resource sync token to |sync_token|. When the next frame is
- // being composited, the DeclareUsedResourcesFromChild() will be called with
- // resources belong to every child for the next frame. If the resource is not
- // used by the next frame, the resource will be returned to a child which
- // owns it with the |sync_token|. The child is responsible for issuing a
- // WaitSyncToken GL command with the |sync_token| before reusing it.
- resource->UpdateSyncToken(sync_token);
- resource->locked_for_external_use = false;
-
- TryReleaseResource(it);
-}
-
-void DisplayResourceProvider::TryReleaseResource(ResourceMap::iterator it) {
- ResourceId id = it->first;
- ChildResource* resource = &it->second;
+void DisplayResourceProvider::TryReleaseResource(ResourceId id,
+ ChildResource* resource) {
if (resource->marked_for_deletion && !resource->lock_for_read_count &&
!resource->locked_for_external_use) {
auto child_it = children_.find(resource->child_id);
@@ -677,6 +627,10 @@ void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild(
std::vector<ReturnedResource*> need_synchronization_resources;
std::vector<GLbyte*> unverified_sync_tokens;
+ std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
+ image_contexts_to_return;
+ image_contexts_to_return.reserve(unused.size());
+
GLES2Interface* gl = ContextGL();
for (ResourceId local_id : unused) {
auto it = resources_.find(local_id);
@@ -712,6 +666,9 @@ void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild(
is_lost = true;
}
+ if (resource.image_context)
+ image_contexts_to_return.emplace_back(std::move(resource.image_context));
+
if (resource.is_gpu_resource_type() &&
resource.filter != resource.transferable.filter) {
DCHECK(resource.transferable.mailbox_holder.texture_target);
@@ -766,8 +723,10 @@ void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild(
for (ReturnedResource* returned : need_synchronization_resources)
returned->sync_token = new_sync_token;
- if (external_use_client_ && !unused.empty())
- external_use_client_->ReleaseCachedResources(unused);
+ if (external_use_client_ && !image_contexts_to_return.empty()) {
+ external_use_client_->ReleaseImageContexts(
+ std::move(image_contexts_to_return));
+ }
if (!to_return.empty())
child_info->return_callback.Run(to_return);
@@ -938,17 +897,66 @@ DisplayResourceProvider::LockSetForExternalUse::~LockSetForExternalUse() {
DCHECK(resources_.empty());
}
-ResourceMetadata DisplayResourceProvider::LockSetForExternalUse::LockResource(
- ResourceId id) {
- DCHECK(!base::Contains(resources_, id));
- resources_.push_back(id);
- return resource_provider_->LockForExternalUse(id);
+ExternalUseClient::ImageContext*
+DisplayResourceProvider::LockSetForExternalUse::LockResource(
+ ResourceId id,
+ bool is_video_plane) {
+ auto it = resource_provider_->resources_.find(id);
+ DCHECK(it != resource_provider_->resources_.end());
+
+ ChildResource& resource = it->second;
+ DCHECK(resource.is_gpu_resource_type());
+
+ if (!resource.locked_for_external_use) {
+ DCHECK(!base::Contains(resources_, std::make_pair(id, &resource)));
+ resources_.emplace_back(id, &resource);
+
+ if (!resource.image_context) {
+ resource.image_context =
+ resource_provider_->external_use_client_->CreateImageContext(
+ resource.transferable.mailbox_holder, resource.transferable.size,
+ resource.transferable.format,
+ // The resource |color_space| is ignored by SkiaRenderer for video
+ // planes and usually cannot be converted to SkColorSpace.
+ is_video_plane
+ ? nullptr
+ : resource.transferable.color_space.ToSkColorSpace());
+ }
+ resource.locked_for_external_use = true;
+
+ if (resource.transferable.read_lock_fences_enabled) {
+ if (resource_provider_->current_read_lock_fence_.get())
+ resource_provider_->current_read_lock_fence_->Set();
+ resource.read_lock_fence = resource_provider_->current_read_lock_fence_;
+ }
+ }
+
+ DCHECK(base::Contains(resources_, std::make_pair(id, &resource)));
+ return resource.image_context.get();
}
void DisplayResourceProvider::LockSetForExternalUse::UnlockResources(
const gpu::SyncToken& sync_token) {
- for (const auto& id : resources_)
- resource_provider_->UnlockForExternalUse(id, sync_token);
+ DCHECK(sync_token.verified_flush());
+ for (const auto& pair : resources_) {
+ auto id = pair.first;
+ auto* resource = pair.second;
+ DCHECK(resource->locked_for_external_use);
+
+ // TODO(penghuang): support software resource.
+ DCHECK(resource->is_gpu_resource_type());
+
+ // Update the resource sync token to |sync_token|. When the next frame is
+ // being composited, the DeclareUsedResourcesFromChild() will be called with
+ // resources belong to every child for the next frame. If the resource is
+ // not used by the next frame, the resource will be returned to a child
+ // which owns it with the |sync_token|. The child is responsible for issuing
+ // a WaitSyncToken GL command with the |sync_token| before reusing it.
+ resource->UpdateSyncToken(sync_token);
+ resource->locked_for_external_use = false;
+
+ resource_provider_->TryReleaseResource(id, resource);
+ }
resources_.clear();
}
diff --git a/chromium/components/viz/service/display/display_resource_provider.h b/chromium/components/viz/service/display/display_resource_provider.h
index 7ebd79fa77f..33e0da4baf4 100644
--- a/chromium/components/viz/service/display/display_resource_provider.h
+++ b/chromium/components/viz/service/display/display_resource_provider.h
@@ -6,8 +6,11 @@
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
#include <stddef.h>
+
#include <map>
+#include <memory>
#include <unordered_map>
+#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
@@ -23,7 +26,6 @@
#include "components/viz/service/display/external_use_client.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/resource_fence.h"
-#include "components/viz/service/display/resource_metadata.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -195,6 +197,11 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSkImage);
};
+ private:
+ // Forward declared for LockSetForExternalUse below.
+ struct ChildResource;
+
+ public:
// Maintains set of resources locked for external use by SkiaRenderer.
class VIZ_SERVICE_EXPORT LockSetForExternalUse {
public:
@@ -205,17 +212,20 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
ExternalUseClient* client);
~LockSetForExternalUse();
- // Lock a resource for external use.
- ResourceMetadata LockResource(ResourceId resource_id);
+ // Lock a resource for external use. The return value was created by
+ // |client| at some point in the past.
+ ExternalUseClient::ImageContext* LockResource(ResourceId resource_id,
+ bool is_video_plane = false);
- // Unlock all locked resources with a |sync_token|.
- // See UnlockForExternalUse for the detail. All resources must be unlocked
- // before destroying this class.
+ // Unlock all locked resources with a |sync_token|. The |sync_token| should
+ // be waited on before reusing the resource's backing to ensure that any
+ // external use of it is completed. This |sync_token| should have been
+ // verified. All resources must be unlocked before destroying this class.
void UnlockResources(const gpu::SyncToken& sync_token);
private:
DisplayResourceProvider* const resource_provider_;
- std::vector<ResourceId> resources_;
+ std::vector<std::pair<ResourceId, ChildResource*>> resources_;
DISALLOW_COPY_AND_ASSIGN(LockSetForExternalUse);
};
@@ -415,6 +425,10 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
// texture.
scoped_refptr<ResourceFence> read_lock_fence;
+ // SkiaRenderer specific details about this resource. Added to ChildResource
+ // to avoid map lookups further down the pipeline.
+ std::unique_ptr<ExternalUseClient::ImageContext> image_context;
+
private:
// Tracks if a sync token needs to be waited on before using the resource.
SynchronizationState synchronization_state_;
@@ -448,16 +462,7 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
const ChildResource* LockForRead(ResourceId id);
void UnlockForRead(ResourceId id);
- // Lock a resource for external use.
- ResourceMetadata LockForExternalUse(ResourceId id);
-
- // Unlock a resource which locked by LockForExternalUse.
- // The |sync_token| should be waited on before reusing the resouce's backing
- // to ensure that any external use of it is completed. This |sync_token|
- // should have been verified.
- void UnlockForExternalUse(ResourceId id, const gpu::SyncToken& sync_token);
-
- void TryReleaseResource(ResourceMap::iterator it);
+ void TryReleaseResource(ResourceId id, ChildResource* resource);
// Binds the given GL resource to a texture target for sampling using the
// specified filter for both minification and magnification. Returns the
// texture target used. The resource must be locked for reading.
diff --git a/chromium/components/viz/service/display/display_resource_provider_unittest.cc b/chromium/components/viz/service/display/display_resource_provider_unittest.cc
index 46fae88c913..29109fdcc1b 100644
--- a/chromium/components/viz/service/display/display_resource_provider_unittest.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_unittest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "components/viz/service/display/display_resource_provider.h"
-#include "components/viz/client/client_resource_provider.h"
#include <stddef.h>
#include <stdint.h>
@@ -24,6 +23,7 @@
#include "build/build_config.h"
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/resource_provider_test_utils.h"
+#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/returned_resource.h"
@@ -43,6 +43,8 @@
#include "ui/gfx/gpu_memory_buffer.h"
using testing::_;
+using testing::ByMove;
+using testing::DoAll;
using testing::Return;
using testing::SaveArg;
@@ -60,6 +62,10 @@ MATCHER_P(MatchesSyncToken, sync_token, "") {
return other == sync_token;
}
+MATCHER_P(SamePtr, ptr_to_expected, "") {
+ return arg.get() == ptr_to_expected;
+}
+
static void CollectResources(std::vector<ReturnedResource>* array,
const std::vector<ReturnedResource>& returned) {
array->insert(array->end(), returned.begin(), returned.end());
@@ -223,8 +229,13 @@ INSTANTIATE_TEST_SUITE_P(DisplayResourceProviderTests,
class MockExternalUseClient : public ExternalUseClient {
public:
MockExternalUseClient() = default;
- MOCK_METHOD1(ReleaseCachedResources,
- void(const std::vector<ResourceId>& resource_ids));
+ MOCK_METHOD1(ReleaseImageContexts,
+ void(std::vector<std::unique_ptr<ImageContext>> image_contexts));
+ MOCK_METHOD4(CreateImageContext,
+ std::unique_ptr<ImageContext>(const gpu::MailboxHolder&,
+ const gfx::Size&,
+ ResourceFormat,
+ sk_sp<SkColorSpace>));
};
TEST_P(DisplayResourceProviderTest, LockForExternalUse) {
@@ -262,17 +273,29 @@ TEST_P(DisplayResourceProviderTest, LockForExternalUse) {
unsigned parent_id = resource_map[list.front().id];
+ auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
+ gpu::MailboxHolder(mailbox, sync_token1, GL_TEXTURE_2D), size, RGBA_8888,
+ /*color_space=*/nullptr);
+ auto* image_context = owned_image_context.get();
+
testing::StrictMock<MockExternalUseClient> client;
DisplayResourceProvider::LockSetForExternalUse lock_set(
resource_provider_.get(), &client);
-
- ResourceMetadata metadata = lock_set.LockResource(parent_id);
- ASSERT_EQ(metadata.mailbox_holder.mailbox, mailbox);
- ASSERT_TRUE(metadata.mailbox_holder.sync_token.HasData());
-
- // Expect the resource to be passed to ReleaseCachedResources when no longer
- // used.
- EXPECT_CALL(client, ReleaseCachedResources(testing::ElementsAre(parent_id)));
+ gpu::MailboxHolder holder;
+ EXPECT_CALL(client, CreateImageContext(_, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&holder),
+ Return(ByMove(std::move(owned_image_context)))));
+
+ ExternalUseClient::ImageContext* locked_image_context =
+ lock_set.LockResource(parent_id);
+ EXPECT_EQ(image_context, locked_image_context);
+ ASSERT_EQ(holder.mailbox, mailbox);
+ ASSERT_TRUE(holder.sync_token.HasData());
+
+ // Don't release while locked.
+ EXPECT_CALL(client, ReleaseImageContexts(_)).Times(0);
+ // Return the resources back to the child. Nothing should happen because
+ // of the resource lock.
resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
// The resource should not be returned due to the external use lock.
EXPECT_EQ(0u, returned_to_child.size());
@@ -284,7 +307,8 @@ TEST_P(DisplayResourceProviderTest, LockForExternalUse) {
// We will get a second release of |parent_id| now that we've released our
// external lock.
- EXPECT_CALL(client, ReleaseCachedResources(testing::ElementsAre(parent_id)));
+ EXPECT_CALL(client, ReleaseImageContexts(
+ testing::ElementsAre(SamePtr(locked_image_context))));
// UnlockResources will also call DeclareUsedResourcesFromChild.
lock_set.UnlockResources(sync_token2);
// The resource should be returned after the lock is released.
diff --git a/chromium/components/viz/service/display/display_scheduler.h b/chromium/components/viz/service/display/display_scheduler.h
index 8e76737b5cf..826ca5fdee4 100644
--- a/chromium/components/viz/service/display/display_scheduler.h
+++ b/chromium/components/viz/service/display/display_scheduler.h
@@ -88,6 +88,7 @@ class VIZ_SERVICE_EXPORT DisplayScheduler : public BeginFrameObserverBase,
void OnSurfaceDestroyed(const SurfaceId& surface_id) override;
void OnSurfaceDamageExpected(const SurfaceId& surface_id,
const BeginFrameArgs& args) override;
+ void set_needs_draw() { needs_draw_ = true; }
protected:
// These values inidicate how a response to the BeginFrame should be
diff --git a/chromium/components/viz/service/display/display_scheduler_unittest.cc b/chromium/components/viz/service/display/display_scheduler_unittest.cc
index f0cd9bd1c99..41ed71468d4 100644
--- a/chromium/components/viz/service/display/display_scheduler_unittest.cc
+++ b/chromium/components/viz/service/display/display_scheduler_unittest.cc
@@ -796,8 +796,6 @@ TEST_F(DisplaySchedulerTest, SetNeedsOneBeginFrame) {
}
TEST_F(DisplaySchedulerTest, GpuBusyNotifications) {
- fake_begin_frame_source_.AllowOneBeginFrameAfterGpuBusy();
-
SurfaceId root_surface_id(
kArbitraryFrameSinkId,
LocalSurfaceId(1, base::UnguessableToken::Create()));
diff --git a/chromium/components/viz/service/display/external_use_client.cc b/chromium/components/viz/service/display/external_use_client.cc
new file mode 100644
index 00000000000..e9a2297253a
--- /dev/null
+++ b/chromium/components/viz/service/display/external_use_client.cc
@@ -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.
+
+#include "components/viz/service/display/external_use_client.h"
+
+namespace viz {
+
+ExternalUseClient::ImageContext::ImageContext(
+ const gpu::MailboxHolder& mailbox_holder,
+ const gfx::Size& size,
+ ResourceFormat resource_format,
+ sk_sp<SkColorSpace> color_space)
+ : mailbox_holder_(mailbox_holder),
+ size_(size),
+ resource_format_(resource_format),
+ color_space_(std::move(color_space)) {}
+
+ExternalUseClient::ImageContext::~ImageContext() = default;
+
+void ExternalUseClient::ImageContext::SetImage(sk_sp<SkImage> image,
+ GrBackendFormat backend_format) {
+ DCHECK(!image_);
+ image_ = std::move(image);
+ backend_format_ = backend_format;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display/external_use_client.h b/chromium/components/viz/service/display/external_use_client.h
index dd3f52e5c09..31ab2d0aacf 100644
--- a/chromium/components/viz/service/display/external_use_client.h
+++ b/chromium/components/viz/service/display/external_use_client.h
@@ -5,20 +5,104 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EXTERNAL_USE_CLIENT_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EXTERNAL_USE_CLIENT_H_
+#include <memory>
+#include <utility>
#include <vector>
-#include "components/viz/common/resources/resource_id.h"
+#include "base/optional.h"
+#include "components/viz/common/resources/resource_format.h"
#include "components/viz/service/viz_service_export.h"
+#include "gpu/command_buffer/common/mailbox_holder.h"
+#include "gpu/ipc/common/vulkan_ycbcr_info.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
+#include "third_party/skia/include/gpu/GrTypes.h"
+#include "ui/gfx/geometry/size.h"
namespace viz {
-// Interface used by DisplayResourceProvider::LockSetForExternalUse to notify
-// the external client about resource removal.
+// DisplayResourceProvider takes ownership
+// of ImageContext from ExternalUseClient when it calls CreateImage.
+// DisplayResourceProvider returns ownership when it calls ReleaseImageContexts.
+// An ExternalUseClient will only ever release an ImageContext that it has
+// created.
class VIZ_SERVICE_EXPORT ExternalUseClient {
public:
- // Release cached data associated with the given |resource_ids|.
- virtual void ReleaseCachedResources(
- const std::vector<ResourceId>& resource_ids) = 0;
+ class VIZ_SERVICE_EXPORT ImageContext {
+ public:
+ ImageContext(const gpu::MailboxHolder& mailbox_holder,
+ const gfx::Size& size,
+ ResourceFormat resource_format,
+ sk_sp<SkColorSpace> color_space);
+ virtual ~ImageContext();
+
+ //
+ // Thread safety is guaranteed by these invariants: (a) only the compositor
+ // thread modifies ImageContext, (b) ImageContext is not modified after
+ // |image| is set, and (c) GPU thread only reads ImageContext after |image|
+ // is set.
+ //
+ const gpu::MailboxHolder& mailbox_holder() const { return mailbox_holder_; }
+ gpu::MailboxHolder* mutable_mailbox_holder() { return &mailbox_holder_; }
+ const gfx::Size& size() const { return size_; }
+ ResourceFormat resource_format() const { return resource_format_; }
+ sk_sp<SkColorSpace> color_space() const { return color_space_; }
+
+ SkAlphaType alpha_type() const { return alpha_type_; }
+ void set_alpha_type(SkAlphaType alpha_type) {
+ DCHECK(!image_);
+ alpha_type_ = alpha_type;
+ }
+
+ GrSurfaceOrigin origin() const { return origin_; }
+ void set_origin(GrSurfaceOrigin origin) {
+ DCHECK(!image_);
+ origin_ = origin;
+ }
+
+ base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info() { return ycbcr_info_; }
+ void set_ycbcr_info(const gpu::VulkanYCbCrInfo& ycbcr_info) {
+ DCHECK(!image_);
+ *ycbcr_info_ = ycbcr_info;
+ }
+
+ bool has_image() { return !!image_; }
+ sk_sp<SkImage> image() { return image_; }
+ void SetImage(sk_sp<SkImage> image, GrBackendFormat backend_format);
+ void clear_image() { image_.reset(); }
+ const GrBackendFormat& backend_format() { return backend_format_; }
+
+ private:
+ gpu::MailboxHolder mailbox_holder_;
+
+ const gfx::Size size_;
+ const ResourceFormat resource_format_;
+ const sk_sp<SkColorSpace> color_space_;
+
+ SkAlphaType alpha_type_ = kPremul_SkAlphaType;
+ GrSurfaceOrigin origin_ = kTopLeft_GrSurfaceOrigin;
+
+ // Sampler conversion information which is used in vulkan context for
+ // android video.
+ base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info_;
+
+ // The promise image which is used on display thread.
+ sk_sp<SkImage> image_;
+ GrBackendFormat backend_format_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageContext);
+ };
+
+ virtual std::unique_ptr<ImageContext> CreateImageContext(
+ const gpu::MailboxHolder& holder,
+ const gfx::Size& size,
+ ResourceFormat format,
+ sk_sp<SkColorSpace> color_space) = 0;
+
+ virtual void ReleaseImageContexts(
+ std::vector<std::unique_ptr<ImageContext>> image_contexts) = 0;
};
} // namespace viz
diff --git a/chromium/components/viz/service/display/gl_renderer.cc b/chromium/components/viz/service/display/gl_renderer.cc
index bc58f3ea501..64ef9025a4b 100644
--- a/chromium/components/viz/service/display/gl_renderer.cc
+++ b/chromium/components/viz/service/display/gl_renderer.cc
@@ -59,6 +59,8 @@
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
+#include "gpu/config/gpu_feature_info.h"
#include "media/base/media_switches.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -367,7 +369,9 @@ GLRenderer::GLRenderer(
context_caps.blend_equation_advanced_coherent;
use_occlusion_query_ = context_caps.occlusion_query;
use_swap_with_bounds_ = context_caps.swap_buffers_with_bounds;
-
+ prefer_draw_to_copy_ = output_surface_->context_provider()
+ ->GetGpuFeatureInfo()
+ .IsWorkaroundEnabled(gpu::PREFER_DRAW_TO_COPY);
InitializeSharedObjects();
}
@@ -782,6 +786,12 @@ gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
*unclipped_rect = backdrop_rect;
backdrop_rect.Intersect(MoveFromDrawToWindowSpace(
current_frame()->current_render_pass->output_rect));
+ if (ShouldApplyBackdropFilters(params->backdrop_filters)) {
+ float max_pixel_movement = params->backdrop_filters->MaximumPixelMovement();
+ gfx::Rect scissor_rect(current_window_space_viewport_);
+ scissor_rect.Inset(-max_pixel_movement, -max_pixel_movement);
+ backdrop_rect.Intersect(scissor_rect);
+ }
// The frame buffer flip is already included in the captured backdrop image,
// and it is included in |contents_device_transform| (through
@@ -842,16 +852,42 @@ uint32_t GLRenderer::GetBackdropTexture(const gfx::Rect& window_rect,
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);
- *internal_format = GetFramebufferCopyTextureFormat();
- // CopyTexImage2D requires inernalformat channels to be a subset of
- // the channels of the source texture internalformat.
- DCHECK(*internal_format == GL_RGB || *internal_format == GL_RGBA ||
- *internal_format == GL_BGRA_EXT);
- if (*internal_format == GL_BGRA_EXT)
- *internal_format = GL_RGBA;
- gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, *internal_format, window_rect.x(),
- window_rect.y(), window_rect.width(),
- window_rect.height(), 0);
+ // If there is a source texture |current_framebuffer_texture_| and the
+ // workaround |prefer_draw_to_copy_| is enabled, then do texture to texture
+ // copy via draw instead of glCopyTexImage2D.
+ if (prefer_draw_to_copy_ && current_framebuffer_texture_) {
+ // Copying from a non-root renderpass, so will use the format of the bound
+ // texture.
+ ResourceFormat resource_format = BackbufferFormat();
+
+ // Get gl_format, gl_type and internal_format.
+ DCHECK(GLSupportsFormat(resource_format));
+ *internal_format = GLInternalFormat(resource_format);
+ GLenum gl_format = GLDataFormat(resource_format);
+ GLenum gl_type = GLDataType(resource_format);
+
+ // Size the destination texture with empty data. This is required since
+ // CopySubTextureCHROMIUM() does not sizes the texture but CopyTexImage2D
+ // does.
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, *internal_format, window_rect.width(),
+ window_rect.height(), 0, gl_format, gl_type, nullptr);
+ gl_->CopySubTextureCHROMIUM(
+ current_framebuffer_texture_->id(), 0, GL_TEXTURE_2D, texture_id, 0, 0,
+ 0, window_rect.x(), window_rect.y(), window_rect.width(),
+ window_rect.height(), GL_FALSE, GL_FALSE, GL_FALSE);
+ } else {
+ *internal_format = GetFramebufferCopyTextureFormat();
+
+ // CopyTexImage2D requires inernalformat channels to be a subset of
+ // the channels of the source texture internalformat.
+ DCHECK(*internal_format == GL_RGB || *internal_format == GL_RGBA ||
+ *internal_format == GL_BGRA_EXT);
+ if (*internal_format == GL_BGRA_EXT)
+ *internal_format = GL_RGBA;
+ gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, *internal_format, window_rect.x(),
+ window_rect.y(), window_rect.width(),
+ window_rect.height(), 0);
+ }
gl_->BindTexture(GL_TEXTURE_2D, 0);
return texture_id;
}
@@ -1016,7 +1052,8 @@ sk_sp<SkImage> GLRenderer::ApplyBackdropFilters(
/*unpack_premultiply_alpha=*/false,
/*unpack_unmultiply_alpha=*/false);
mask_image = WrapTexture(dest_id, GL_TEXTURE_2D, quad->mask_texture_size,
- use_gr_context->context(), false,
+ use_gr_context->context(),
+ /*flip_texture=*/!FlippedFramebuffer(),
GlFormatToSkFormat(internalformat),
/*adopt_texture=*/true);
} else {
@@ -2448,6 +2485,11 @@ void GLRenderer::DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
current_program_->tex_matrix_location(), false, gl_matrix);
SetShaderOpacity(quad->shared_quad_state->opacity);
+ if (current_program_->rounded_corner_rect_location() != -1) {
+ SetShaderRoundedCorner(
+ quad->shared_quad_state->rounded_corner_bounds,
+ current_frame()->window_matrix * current_frame()->projection_matrix);
+ }
gfx::Size texture_size = lock.size();
gfx::RectF uv_visible_rect(quad->uv_top_left.x(), quad->uv_top_left.y(),
quad->uv_bottom_right.x() - quad->uv_top_left.x(),
@@ -2705,6 +2747,10 @@ void GLRenderer::FinishDrawingFrame() {
gl_->Disable(GL_BLEND);
blend_shadow_ = false;
+ // Schedule output surface as overlay first to preserve existing ordering
+ // semantics during overlay refactoring.
+ ScheduleOutputSurfaceAsOverlay();
+
ScheduleCALayers();
ScheduleDCLayers();
ScheduleOverlays();
@@ -3413,24 +3459,21 @@ void GLRenderer::ScheduleCALayers() {
void GLRenderer::ScheduleDCLayers() {
for (DCLayerOverlay& dc_layer_overlay :
current_frame()->dc_layer_overlay_list) {
- ResourceId resource_ids[] = {dc_layer_overlay.y_resource_id,
- dc_layer_overlay.uv_resource_id};
- GLuint texture_ids[2] = {};
- size_t i = 0;
- for (ResourceId resource_id : resource_ids) {
- DCHECK(resource_id);
+ DCHECK_EQ(DCLayerOverlay::kNumResources, 2u);
+ GLuint texture_ids[DCLayerOverlay::kNumResources] = {};
+ for (size_t i = 0; i < DCLayerOverlay::kNumResources; i++) {
+ ResourceId resource_id = dc_layer_overlay.resources[i];
+ if (resource_id == kInvalidResourceId)
+ break;
pending_overlay_resources_.push_back(
std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
resource_provider_, resource_id));
- texture_ids[i++] = pending_overlay_resources_.back()->texture_id();
+ texture_ids[i] = pending_overlay_resources_.back()->texture_id();
}
- GLuint y_texture_id = texture_ids[0];
- GLuint uv_texture_id = texture_ids[1];
- DCHECK(y_texture_id && uv_texture_id);
-
+ DCHECK(texture_ids[0]);
// TODO(sunnyps): Set color space in renderer like we do for tiles.
gl_->SetColorSpaceMetadataCHROMIUM(
- y_texture_id,
+ texture_ids[0],
reinterpret_cast<GLColorSpace>(&dc_layer_overlay.color_space));
int z_order = dc_layer_overlay.z_order;
@@ -3444,7 +3487,7 @@ void GLRenderer::ScheduleDCLayers() {
static_cast<unsigned>(dc_layer_overlay.protected_video_type);
gl_->ScheduleDCLayerCHROMIUM(
- y_texture_id, uv_texture_id, z_order, content_rect.x(),
+ texture_ids[0], texture_ids[1], z_order, content_rect.x(),
content_rect.y(), content_rect.width(), content_rect.height(),
quad_rect.x(), quad_rect.y(), quad_rect.width(), quad_rect.height(),
transform.get(0, 0), transform.get(0, 1), transform.get(1, 0),
@@ -3460,16 +3503,10 @@ void GLRenderer::ScheduleOverlays() {
OverlayCandidateList& overlays = current_frame()->overlay_list;
for (const auto& overlay_candidate : overlays) {
- unsigned texture_id = 0;
- if (overlay_candidate.use_output_surface_for_resource) {
- texture_id = output_surface_->GetOverlayTextureId();
- DCHECK(texture_id || IsContextLost());
- } else {
- pending_overlay_resources_.push_back(
- std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
- resource_provider_, overlay_candidate.resource_id));
- texture_id = pending_overlay_resources_.back()->texture_id();
- }
+ pending_overlay_resources_.push_back(
+ std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
+ resource_provider_, overlay_candidate.resource_id));
+ unsigned texture_id = pending_overlay_resources_.back()->texture_id();
context_support_->ScheduleOverlayPlane(
overlay_candidate.plane_z_order, overlay_candidate.transform,
@@ -3479,6 +3516,25 @@ void GLRenderer::ScheduleOverlays() {
}
}
+void GLRenderer::ScheduleOutputSurfaceAsOverlay() {
+ if (!current_frame()->output_surface_plane)
+ return;
+
+ // Initialize correct values to use an output surface as overlay candidate.
+ auto& overlay_candidate = *(current_frame()->output_surface_plane);
+ unsigned texture_id = output_surface_->GetOverlayTextureId();
+ DCHECK(texture_id || IsContextLost());
+ // Output surface is also z-order 0.
+ int plane_z_order = 0;
+ // Output surface always uses the full texture.
+ gfx::RectF uv_rect(0.f, 0.f, 1.f, 1.f);
+
+ context_support_->ScheduleOverlayPlane(
+ plane_z_order, overlay_candidate.transform, texture_id,
+ ToNearestRect(overlay_candidate.display_rect), uv_rect,
+ overlay_candidate.enable_blending, overlay_candidate.gpu_fence_id);
+}
+
// This function draws the RenderPassDrawQuad into a temporary
// texture/framebuffer, and then copies the result into an IOSurface. The
// inefficient (but simple) way to do this would be to:
diff --git a/chromium/components/viz/service/display/gl_renderer.h b/chromium/components/viz/service/display/gl_renderer.h
index 4a43066ee56..2ef26fff071 100644
--- a/chromium/components/viz/service/display/gl_renderer.h
+++ b/chromium/components/viz/service/display/gl_renderer.h
@@ -293,6 +293,13 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
void ReinitializeGLState();
void RestoreGLState();
+ // TODO(weiliangc): Once the overlay processor could schedule overlays, remove
+ // these functions.
+ // Sends over output surface information as it is a overlay plane. This is
+ // used for BufferQueue. For non-BufferQueue cases, this function will do
+ // nothing.
+ void ScheduleOutputSurfaceAsOverlay();
+ // Schedule overlays sends overlay candidate to the GPU.
void ScheduleCALayers();
void ScheduleDCLayers();
void ScheduleOverlays();
@@ -419,6 +426,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
gfx::Size offscreen_stencil_renderbuffer_size_;
unsigned num_triangles_drawn_ = 0;
+ bool prefer_draw_to_copy_ = false;
// This may be null if the compositor is run on a thread without a
// MessageLoop.
diff --git a/chromium/components/viz/service/display/gl_renderer_unittest.cc b/chromium/components/viz/service/display/gl_renderer_unittest.cc
index e5da1ca1968..ca6d7b9a9fe 100644
--- a/chromium/components/viz/service/display/gl_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/gl_renderer_unittest.cc
@@ -2179,14 +2179,16 @@ class TestOverlayProcessor : public OverlayProcessor {
Strategy() = default;
~Strategy() override = default;
- MOCK_METHOD6(Attempt,
- bool(const SkMatrix44& output_color_matrix,
- const OverlayProcessor::FilterOperationsMap&
- render_pass_backdrop_filters,
- DisplayResourceProvider* resource_provider,
- RenderPassList* render_pass_list,
- OverlayCandidateList* candidates,
- std::vector<gfx::Rect>* content_bounds));
+ MOCK_METHOD7(
+ Attempt,
+ bool(const SkMatrix44& output_color_matrix,
+ const OverlayProcessor::FilterOperationsMap&
+ render_pass_backdrop_filters,
+ DisplayResourceProvider* resource_provider,
+ RenderPassList* render_pass_list,
+ const OverlayProcessor::OutputSurfaceOverlayPlane* primary_surface,
+ OverlayCandidateList* candidates,
+ std::vector<gfx::Rect>* content_bounds));
};
class Validator : public OverlayCandidateValidator {
@@ -2206,7 +2208,8 @@ class TestOverlayProcessor : public OverlayProcessor {
// to be traditionally composited. Candidates with |overlay_handled| set to
// true must also have their |display_rect| converted to integer
// coordinates if necessary.
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
Strategy& strategy() {
auto* strategy = strategies_.back().get();
@@ -2215,11 +2218,8 @@ class TestOverlayProcessor : public OverlayProcessor {
};
explicit TestOverlayProcessor(
- ContextProvider* context_provider,
std::unique_ptr<OverlayCandidateValidator> overlay_validator)
- : OverlayProcessor(context_provider) {
- SetOverlayCandidateValidator(std::move(overlay_validator));
- }
+ : OverlayProcessor(std::move(overlay_validator)) {}
~TestOverlayProcessor() override = default;
const Validator* GetTestValidator() const {
@@ -2288,7 +2288,6 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
renderer.SetVisible(true);
TestOverlayProcessor* processor = new TestOverlayProcessor(
- output_surface->context_provider(),
std::make_unique<TestOverlayProcessor::Validator>());
renderer.SetOverlayProcessor(processor);
const TestOverlayProcessor::Validator* validator =
@@ -2321,7 +2320,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
// added a fake strategy, so checking for Attempt calls checks if there was
// any attempt to overlay, which there shouldn't be. We can't use the quad
// list because the render pass is cleaned up by DrawFrame.
- EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _, _)).Times(0);
EXPECT_CALL(*validator, AllowCALayerOverlays()).Times(0);
EXPECT_CALL(*validator, AllowDCLayerOverlays()).Times(0);
DrawFrame(&renderer, viewport_size);
@@ -2348,7 +2347,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
EXPECT_CALL(*validator, AllowDCLayerOverlays())
.Times(1)
.WillOnce(::testing::Return(false));
- EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _)).Times(1);
+ EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _, _)).Times(1);
DrawFrame(&renderer, viewport_size);
// If the CALayerOverlay path is taken, then the ordinary overlay path should
@@ -2368,7 +2367,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
EXPECT_CALL(*validator, AllowCALayerOverlays())
.Times(1)
.WillOnce(::testing::Return(true));
- EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(processor->strategy(), Attempt(_, _, _, _, _, _, _)).Times(0);
DrawFrame(&renderer, viewport_size);
// Transfer resources back from the parent to the child. Set no resources as
@@ -2393,7 +2392,8 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
bool AllowDCLayerOverlays() const override { return false; }
bool NeedsSurfaceOccludingDamageRect() const override { return true; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {
if (!multiple_candidates_)
ASSERT_EQ(1U, surfaces->size());
OverlayCandidate& candidate = surfaces->back();
@@ -2408,10 +2408,8 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
bool multiple_candidates_ = false;
};
- explicit SingleOverlayOnTopProcessor(ContextProvider* context_provider)
- : OverlayProcessor(context_provider) {
- SetOverlayCandidateValidator(std::make_unique<SingleOverlayValidator>());
- }
+ SingleOverlayOnTopProcessor()
+ : OverlayProcessor(std::make_unique<SingleOverlayValidator>()) {}
void AllowMultipleCandidates() {
// Cast away const from the validator pointer to set on it.
@@ -2500,8 +2498,7 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
renderer.Initialize();
renderer.SetVisible(true);
- SingleOverlayOnTopProcessor* processor = new SingleOverlayOnTopProcessor(
- output_surface->context_provider());
+ SingleOverlayOnTopProcessor* processor = new SingleOverlayOnTopProcessor();
renderer.SetOverlayProcessor(processor);
gfx::Size viewport_size(1, 1);
@@ -2825,7 +2822,8 @@ class DCLayerValidator : public OverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return false; }
bool AllowDCLayerOverlays() const override { return true; }
bool NeedsSurfaceOccludingDamageRect() const override { return true; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
};
// Test that SetEnableDCLayersCHROMIUM is properly called when enabling
@@ -2885,9 +2883,8 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
parent_resource_provider.get());
renderer.Initialize();
renderer.SetVisible(true);
- TestOverlayProcessor* processor = new TestOverlayProcessor(
- output_surface->context_provider(), std::make_unique<DCLayerValidator>());
- processor->SetDCHasHwOverlaySupportForTesting();
+ TestOverlayProcessor* processor =
+ new TestOverlayProcessor(std::make_unique<DCLayerValidator>());
renderer.SetOverlayProcessor(processor);
gfx::Size viewport_size(100, 100);
@@ -3008,6 +3005,7 @@ class ContentBoundsOverlayProcessor : public OverlayProcessor {
render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidates,
std::vector<gfx::Rect>* content_bounds) override {
content_bounds->insert(content_bounds->end(), content_bounds_.begin(),
@@ -3039,7 +3037,8 @@ class ContentBoundsOverlayProcessor : public OverlayProcessor {
// to be traditionally composited. Candidates with |overlay_handled| set to
// true must also have their |display_rect| converted to integer
// coordinates if necessary.
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
Strategy& strategy() { return static_cast<Strategy&>(*strategies_.back()); }
@@ -3047,11 +3046,9 @@ class ContentBoundsOverlayProcessor : public OverlayProcessor {
std::vector<gfx::Rect> content_bounds_;
};
- ContentBoundsOverlayProcessor(OutputSurface* surface,
- const std::vector<gfx::Rect>& content_bounds)
- : OverlayProcessor(surface->context_provider()) {
- SetOverlayCandidateValidator(std::make_unique<Validator>(content_bounds));
- }
+ explicit ContentBoundsOverlayProcessor(
+ const std::vector<gfx::Rect>& content_bounds)
+ : OverlayProcessor(std::make_unique<Validator>(content_bounds)) {}
Strategy& strategy() {
DCHECK(overlay_validator_);
@@ -3087,7 +3084,7 @@ class GLRendererSwapWithBoundsTest : public GLRendererTest {
renderer.SetVisible(true);
OverlayProcessor* processor =
- new ContentBoundsOverlayProcessor(output_surface.get(), content_bounds);
+ new ContentBoundsOverlayProcessor(content_bounds);
renderer.SetOverlayProcessor(processor);
gfx::Size viewport_size(100, 100);
@@ -3127,7 +3124,8 @@ class CALayerValidator : public OverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return true; }
bool AllowDCLayerOverlays() const override { return false; }
bool NeedsSurfaceOccludingDamageRect() const override { return false; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
};
class MockCALayerGLES2Interface : public TestGLES2Interface {
@@ -3191,8 +3189,7 @@ class CALayerGLRendererTest : public GLRendererTest {
// quads can be turned into CALayer overlays, then all damage is removed and
// we can skip the root RenderPass, swapping empty.
TestOverlayProcessor* processor =
- new TestOverlayProcessor(output_surface_->context_provider(),
- std::make_unique<CALayerValidator>());
+ new TestOverlayProcessor(std::make_unique<CALayerValidator>());
renderer_->SetOverlayProcessor(processor);
}
@@ -4188,13 +4185,13 @@ class GLRendererWithGpuFenceTest : public GLRendererTest {
renderer_->Initialize();
renderer_->SetVisible(true);
- auto* processor = new SingleOverlayOnTopProcessor(
- output_surface_->context_provider());
+ auto* processor = new SingleOverlayOnTopProcessor();
processor->AllowMultipleCandidates();
renderer_->SetOverlayProcessor(processor);
- test_context_support_->SetScheduleOverlayPlaneCallback(base::BindRepeating(
- &MockOverlayScheduler::Schedule, base::Unretained(&overlay_scheduler)));
+ test_context_support_->SetScheduleOverlayPlaneCallback(
+ base::BindRepeating(&MockOverlayScheduler::Schedule,
+ base::Unretained(&overlay_scheduler_)));
}
~GLRendererWithGpuFenceTest() override {
@@ -4233,7 +4230,7 @@ class GLRendererWithGpuFenceTest : public GLRendererTest {
std::unique_ptr<ClientResourceProvider> child_resource_provider_;
RendererSettings settings_;
std::unique_ptr<FakeRendererGL> renderer_;
- MockOverlayScheduler overlay_scheduler;
+ MockOverlayScheduler overlay_scheduler_;
};
TEST_F(GLRendererWithGpuFenceTest, GpuFenceIdIsUsedWithRootRenderPassOverlay) {
@@ -4243,7 +4240,7 @@ TEST_F(GLRendererWithGpuFenceTest, GpuFenceIdIsUsedWithRootRenderPassOverlay) {
gfx::Transform(), cc::FilterOperations());
root_pass->has_transparent_background = false;
- EXPECT_CALL(overlay_scheduler,
+ EXPECT_CALL(overlay_scheduler_,
Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, kSurfaceOverlayTextureId,
gfx::Rect(viewport_size), _, _, kGpuFenceId))
.Times(1);
@@ -4280,11 +4277,11 @@ TEST_F(GLRendererWithGpuFenceTest,
flipped, nearest_neighbor,
/*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
- EXPECT_CALL(overlay_scheduler,
+ EXPECT_CALL(overlay_scheduler_,
Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, kSurfaceOverlayTextureId,
gfx::Rect(viewport_size), _, _, kGpuFenceId))
.Times(1);
- EXPECT_CALL(overlay_scheduler,
+ EXPECT_CALL(overlay_scheduler_,
Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _,
gfx::Rect(viewport_size), _, _, kGpuNoFenceId))
.Times(1);
diff --git a/chromium/components/viz/service/display/overlay_candidate.cc b/chromium/components/viz/service/display/overlay_candidate.cc
index 75f797eec69..68adc584421 100644
--- a/chromium/components/viz/service/display/overlay_candidate.cc
+++ b/chromium/components/viz/service/display/overlay_candidate.cc
@@ -87,7 +87,6 @@ OverlayCandidate::OverlayCandidate()
uv_rect(0.f, 0.f, 1.f, 1.f),
is_clipped(false),
is_opaque(false),
- use_output_surface_for_resource(false),
no_occluding_damage(false),
resource_id(0),
#if defined(OS_ANDROID)
@@ -118,6 +117,9 @@ bool OverlayCandidate::FromDrawQuad(DisplayResourceProvider* resource_provider,
// We don't support an opacity value different than one for an overlay plane.
if (quad->shared_quad_state->opacity != 1.f)
return false;
+ // We can't support overlays with rounded corner clipping.
+ if (!quad->shared_quad_state->rounded_corner_bounds.IsEmpty())
+ return false;
// We support only kSrc (no blending) and kSrcOver (blending with premul).
if (!(quad->shared_quad_state->blend_mode == SkBlendMode::kSrc ||
quad->shared_quad_state->blend_mode == SkBlendMode::kSrcOver)) {
diff --git a/chromium/components/viz/service/display/overlay_candidate.h b/chromium/components/viz/service/display/overlay_candidate.h
index 1399fe265fe..e2604e8ff4c 100644
--- a/chromium/components/viz/service/display/overlay_candidate.h
+++ b/chromium/components/viz/service/display/overlay_candidate.h
@@ -86,9 +86,6 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
bool is_clipped;
// If the quad doesn't require blending.
bool is_opaque;
- // True if the texture for this overlay should be the same one used by the
- // output surface's main overlay.
- bool use_output_surface_for_resource;
// The quad's occluding damage rect is empty.
bool no_occluding_damage;
// Texture resource to present in an overlay.
diff --git a/chromium/components/viz/service/display/overlay_candidate_validator.cc b/chromium/components/viz/service/display/overlay_candidate_validator.cc
index 95aa337a1aa..d21c31273fd 100644
--- a/chromium/components/viz/service/display/overlay_candidate_validator.cc
+++ b/chromium/components/viz/service/display/overlay_candidate_validator.cc
@@ -56,15 +56,8 @@ CreateOverlayCandidateValidatorOzone(
std::unique_ptr<OverlayCandidateValidatorWin>
CreateOverlayCandidateValidatorWin(const ContextProvider* context_provider) {
DCHECK(context_provider);
-
const auto& capabilities = context_provider->ContextCapabilities();
- const bool use_overlays_for_sw_protected_video = base::FeatureList::IsEnabled(
- features::kUseDCOverlaysForSoftwareProtectedVideo);
- const bool use_overlays =
- capabilities.dc_layers && (capabilities.use_dc_overlays_for_video ||
- use_overlays_for_sw_protected_video);
-
- if (use_overlays) {
+ if (capabilities.dc_layers) {
return std::make_unique<OverlayCandidateValidatorWin>();
} else {
return nullptr;
@@ -128,6 +121,12 @@ std::unique_ptr<OverlayCandidateValidator> OverlayCandidateValidator::Create(
return CreateOverlayCandidateValidatorWin(context_provider);
#elif defined(OS_ANDROID)
return CreateOverlayCandidateValidatorAndroid(context_provider);
+#elif defined(USE_OZONE)
+ // Chromecast could either be backed by Ozone-DRM, which is covered by
+ // Surfaceless code path above, or Ozone-Cast, which is the type of Ozone
+ // platform that doesn't use Surfaceless Surface.
+ return CreateOverlayCandidateValidatorOzone(surface_handle,
+ renderer_settings);
#else
return nullptr;
#endif
@@ -143,14 +142,20 @@ bool OverlayCandidateValidator::AttemptWithStrategies(
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ PrimaryPlane* primary_plane,
OverlayCandidateList* candidates,
- std::vector<gfx::Rect>* content_bounds) const {
+ std::vector<gfx::Rect>* content_bounds) {
+ last_successful_strategy_ = nullptr;
for (const auto& strategy : strategies_) {
if (strategy->Attempt(output_color_matrix, render_pass_backdrop_filters,
- resource_provider, render_pass_list, candidates,
- content_bounds)) {
+ resource_provider, render_pass_list, primary_plane,
+ candidates, content_bounds)) {
+ // This function is used by the underlay strategy to mark the primary
+ // plane as enable_blending.
+ strategy->AdjustOutputSurfaceOverlay(primary_plane);
UMA_HISTOGRAM_ENUMERATION("Viz.DisplayCompositor.OverlayStrategy",
strategy->GetUMAEnum());
+ last_successful_strategy_ = strategy.get();
return true;
}
}
@@ -164,4 +169,13 @@ gfx::Rect OverlayCandidateValidator::GetOverlayDamageRectForOutputSurface(
return ToEnclosedRect(candidate.display_rect);
}
+bool OverlayCandidateValidator::StrategyNeedsOutputSurfacePlaneRemoved() {
+ // The full screen strategy will remove the output surface as an overlay
+ // plane.
+ if (last_successful_strategy_)
+ return last_successful_strategy_->RemoveOutputSurfaceAsOverlay();
+
+ return false;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_candidate_validator.h b/chromium/components/viz/service/display/overlay_candidate_validator.h
index 224c8174d00..af389dc5463 100644
--- a/chromium/components/viz/service/display/overlay_candidate_validator.h
+++ b/chromium/components/viz/service/display/overlay_candidate_validator.h
@@ -25,6 +25,10 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidator {
const RendererSettings& renderer_settings);
virtual ~OverlayCandidateValidator();
+ // A primary plane is generated when |OutputSurface|'s buffer is supplied by
+ // |BufferQueue|. This is considered as an overlay plane.
+ using PrimaryPlane = OverlayProcessor::OutputSurfaceOverlayPlane;
+
// Populates a list of strategies that may work with this validator. Should be
// called at most once.
virtual void InitializeStrategies() {}
@@ -46,12 +50,16 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidator {
// plane are marked with |overlay_handled| set to true, otherwise they are
// to be traditionally composited. Candidates with |overlay_handled| set to
// true must also have their |display_rect| converted to integer
- // coordinates if necessary.
- virtual void CheckOverlaySupport(OverlayCandidateList* surfaces) = 0;
+ // coordinates if necessary. When the output surface uses buffer from the
+ // buffer queue, it generates a |primary_plane|. The |primary_plane| is
+ // always handled, but its information needs to be passed to the hardware
+ // overlay system though this function.
+ virtual void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) = 0;
// The OverlayCandidate for the OutputSurface. Allows the validator to update
// any properties of the |surface| required by the platform.
- virtual void AdjustOutputSurfaceOverlay(OverlayCandidate* candidate) {}
+ virtual void AdjustOutputSurfaceOverlay(PrimaryPlane* output_surface_plane) {}
// Set the overlay display transform and viewport size. Value only used for
// Android Surface Control.
@@ -61,7 +69,7 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidator {
// Returns the overlay damage rect covering the main plane rendered by the
// OutputSurface. This rect is in the same space where the OutputSurface
// renders the content for the main plane, including the display transform if
- // needed.
+ // needed. Should only be called after the overlays are processed.
virtual gfx::Rect GetOverlayDamageRectForOutputSurface(
const OverlayCandidate& candidate) const;
@@ -71,19 +79,29 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidator {
// Iterate through a list of strategies and attempt to overlay with each.
// Returns true if one of the attempts is successful. Has to be called after
- // InitializeStrategies().
+ // InitializeStrategies(). A |primary_plane| represents the output surface's
+ // buffer that comes from |BufferQueue|. It is passed in here so it could be
+ // pass through to hardware through CheckOverlaySupport. It is not passed in
+ // as a const member because the underlay strategy changes the
+ // |primary_plane|'s blending setting.
bool AttemptWithStrategies(
const SkMatrix44& output_color_matrix,
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ PrimaryPlane* primary_plane,
OverlayCandidateList* candidates,
- std::vector<gfx::Rect>* content_bounds) const;
+ std::vector<gfx::Rect>* content_bounds);
+
+ // If the full screen strategy is successful, we no longer need to overlay the
+ // output surface since it will be fully covered.
+ bool StrategyNeedsOutputSurfacePlaneRemoved();
protected:
OverlayCandidateValidator();
OverlayProcessor::StrategyList strategies_;
+ OverlayProcessor::Strategy* last_successful_strategy_ = nullptr;
};
} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_processor.cc b/chromium/components/viz/service/display/overlay_processor.cc
index 10eb0fde7b0..12d6fc9b591 100644
--- a/chromium/components/viz/service/display/overlay_processor.cc
+++ b/chromium/components/viz/service/display/overlay_processor.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -47,6 +48,12 @@ class SendPromotionHintsBeforeReturning {
} // namespace
+// Default implementation of whether a strategy would remove the output surface
+// as overlay plane.
+bool OverlayProcessor::Strategy::RemoveOutputSurfaceAsOverlay() {
+ return false;
+}
+
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class UnderlayDamage {
@@ -102,27 +109,30 @@ std::unique_ptr<OverlayProcessor> OverlayProcessor::CreateOverlayProcessor(
const ContextProvider* context_provider,
gpu::SurfaceHandle surface_handle,
const RendererSettings& renderer_settings) {
- std::unique_ptr<OverlayProcessor> processor(
- new OverlayProcessor(context_provider));
-
- processor->SetOverlayCandidateValidator(OverlayCandidateValidator::Create(
- surface_handle, context_provider, renderer_settings));
-
- return processor;
+ return base::WrapUnique(new OverlayProcessor(
+ OverlayCandidateValidator::Create(surface_handle, context_provider,
+ renderer_settings),
+ std::make_unique<DCLayerOverlayProcessor>(context_provider,
+ renderer_settings)));
}
-OverlayProcessor::OverlayProcessor(const ContextProvider* context_provider)
- : dc_processor_(
- std::make_unique<DCLayerOverlayProcessor>(context_provider)) {}
-
-void OverlayProcessor::SetOverlayCandidateValidator(
- std::unique_ptr<OverlayCandidateValidator> overlay_validator) {
- overlay_validator_.swap(overlay_validator);
+OverlayProcessor::OverlayProcessor(
+ std::unique_ptr<OverlayCandidateValidator> overlay_validator,
+ std::unique_ptr<DCLayerOverlayProcessor> dc_layer_overlay_processor)
+ : overlay_validator_(std::move(overlay_validator)),
+ dc_layer_overlay_processor_(std::move(dc_layer_overlay_processor)) {
+ DCHECK(dc_layer_overlay_processor_);
if (overlay_validator_)
overlay_validator_->InitializeStrategies();
}
-OverlayProcessor::~OverlayProcessor() {}
+// For testing.
+OverlayProcessor::OverlayProcessor(
+ std::unique_ptr<OverlayCandidateValidator> overlay_validator)
+ : OverlayProcessor(std::move(overlay_validator),
+ std::make_unique<DCLayerOverlayProcessor>()) {}
+
+OverlayProcessor::~OverlayProcessor() = default;
gfx::Rect OverlayProcessor::GetAndResetOverlayDamage() {
gfx::Rect result = overlay_damage_rect_;
@@ -135,7 +145,6 @@ bool OverlayProcessor::ProcessForCALayers(
RenderPass* render_pass,
const OverlayProcessor::FilterOperationsMap& render_pass_filters,
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
- OverlayCandidateList* overlay_candidates,
CALayerOverlayList* ca_layer_overlays,
gfx::Rect* damage_rect) {
if (!overlay_validator_ || !overlay_validator_->AllowCALayerOverlays())
@@ -150,7 +159,7 @@ bool OverlayProcessor::ProcessForCALayers(
// CALayer overlays are all-or-nothing. If all quads were replaced with
// layers then clear the list and remove the backbuffer from the overcandidate
// list.
- overlay_candidates->clear();
+ output_surface_already_handled_ = true;
overlay_damage_rect_ = render_pass->output_rect;
*damage_rect = gfx::Rect();
return true;
@@ -161,17 +170,14 @@ bool OverlayProcessor::ProcessForDCLayers(
RenderPassList* render_passes,
const OverlayProcessor::FilterOperationsMap& render_pass_filters,
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
- OverlayCandidateList* overlay_candidates,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect) {
if (!overlay_validator_ || !overlay_validator_->AllowDCLayerOverlays())
return false;
- dc_processor_->Process(resource_provider,
- gfx::RectF(render_passes->back()->output_rect),
- render_passes, damage_rect, dc_layer_overlays);
-
- DCHECK(overlay_candidates->empty());
+ dc_layer_overlay_processor_->Process(
+ resource_provider, gfx::RectF(render_passes->back()->output_rect),
+ render_passes, damage_rect, dc_layer_overlays);
return true;
}
@@ -181,6 +187,7 @@ void OverlayProcessor::ProcessForOverlays(
const SkMatrix44& output_color_matrix,
const OverlayProcessor::FilterOperationsMap& render_pass_filters,
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
+ OutputSurfaceOverlayPlane* output_surface_plane,
OverlayCandidateList* candidates,
CALayerOverlayList* ca_layer_overlays,
DCLayerOverlayList* dc_layer_overlays,
@@ -194,6 +201,9 @@ void OverlayProcessor::ProcessForOverlays(
SendPromotionHintsBeforeReturning notifier(resource_provider, candidates);
#endif
+ // Clear to get ready to handle output surface as overlay.
+ output_surface_already_handled_ = false;
+
// Reset |previous_frame_underlay_rect_| in case UpdateDamageRect() not being
// invoked. Also reset |previous_frame_underlay_was_unoccluded_|.
const gfx::Rect previous_frame_underlay_rect = previous_frame_underlay_rect_;
@@ -202,60 +212,51 @@ void OverlayProcessor::ProcessForOverlays(
previous_frame_underlay_was_unoccluded_;
previous_frame_underlay_was_unoccluded_ = false;
- RenderPass* render_pass = render_passes->back().get();
+ RenderPass* root_render_pass = render_passes->back().get();
- // If we have any copy requests, we can't remove any quads for overlays or
- // CALayers because the framebuffer would be missing the removed quads'
- // contents.
- if (!render_pass->copy_requests.empty()) {
- damage_rect->Union(
- dc_processor_->previous_frame_overlay_damage_contribution());
+ // If we have any copy requests, we can't remove any quads for overlays,
+ // CALayers, or DCLayers because the framebuffer would be missing the removed
+ // quads' contents.
+ if (!root_render_pass->copy_requests.empty()) {
+ damage_rect->Union(dc_layer_overlay_processor_
+ ->previous_frame_overlay_damage_contribution());
// Update damage rect before calling ClearOverlayState, otherwise
// previous_frame_overlay_rect_union will be empty.
- dc_processor_->ClearOverlayState();
-
+ dc_layer_overlay_processor_->ClearOverlayState();
return;
}
// First attempt to process for CALayers.
- if (ProcessForCALayers(resource_provider, render_passes->back().get(),
+ if (ProcessForCALayers(resource_provider, root_render_pass,
render_pass_filters, render_pass_backdrop_filters,
- candidates, ca_layer_overlays, damage_rect)) {
+ ca_layer_overlays, damage_rect)) {
return;
}
if (ProcessForDCLayers(resource_provider, render_passes, render_pass_filters,
- render_pass_backdrop_filters, candidates,
- dc_layer_overlays, damage_rect)) {
+ render_pass_backdrop_filters, dc_layer_overlays,
+ damage_rect)) {
return;
}
+ DCHECK(candidates->empty());
// Only if that fails, attempt hardware overlay strategies.
bool success = false;
if (overlay_validator_) {
success = overlay_validator_->AttemptWithStrategies(
output_color_matrix, render_pass_backdrop_filters, resource_provider,
- render_passes, candidates, content_bounds);
+ render_passes, output_surface_plane, candidates, content_bounds);
}
if (success) {
UpdateDamageRect(candidates, previous_frame_underlay_rect,
previous_frame_underlay_was_unoccluded,
- &render_pass->quad_list, damage_rect);
+ &root_render_pass->quad_list, damage_rect);
} else {
if (!previous_frame_underlay_rect.IsEmpty())
damage_rect->Union(previous_frame_underlay_rect);
- // If no strategy worked the only remaining overlay in the list is the one
- // backed by the OutputSurface. Make sure the OverlayCandidateValidator
- // applies any modifications if needed.
- if (!candidates->empty() && overlay_validator_) {
- DCHECK_EQ(candidates->size(), 1u);
- DCHECK(candidates->back().use_output_surface_for_resource);
-
- overlay_validator_->AdjustOutputSurfaceOverlay(&candidates->back());
- DCHECK_EQ(candidates->size(), 1u);
- }
+ DCHECK(candidates->empty());
}
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("viz.debug.overlay_planes"),
@@ -279,16 +280,12 @@ void OverlayProcessor::UpdateDamageRect(
for (const OverlayCandidate& overlay : *candidates) {
if (overlay.plane_z_order >= 0) {
const gfx::Rect overlay_display_rect =
- ToEnclosedRect(overlay.display_rect);
+ overlay_validator_->GetOverlayDamageRectForOutputSurface(overlay);
// If an overlay candidate comes from output surface, its z-order should
// be 0.
- DCHECK(!overlay.use_output_surface_for_resource ||
- overlay.plane_z_order == 0);
- if (!overlay.use_output_surface_for_resource) {
- overlay_damage_rect_.Union(overlay_display_rect);
- if (overlay.is_opaque)
- damage_rect->Subtract(overlay_display_rect);
- }
+ overlay_damage_rect_.Union(overlay_display_rect);
+ if (overlay.is_opaque)
+ damage_rect->Subtract(overlay_display_rect);
} else {
// Process underlay candidates:
// Track the underlay_rect from frame to frame. If it is the same and
@@ -339,6 +336,51 @@ void OverlayProcessor::UpdateDamageRect(
previous_frame_underlay_rect_ = this_frame_underlay_rect;
}
+OverlayProcessor::OutputSurfaceOverlayPlane
+OverlayProcessor::ProcessOutputSurfaceAsOverlay(
+ const gfx::Size& viewport_size,
+ const gfx::BufferFormat& buffer_format,
+ const gfx::ColorSpace& color_space) const {
+ OutputSurfaceOverlayPlane overlay_plane;
+ overlay_plane.transform = gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE;
+ overlay_plane.resource_size = viewport_size;
+ overlay_plane.format = buffer_format;
+ overlay_plane.color_space = color_space;
+ overlay_plane.enable_blending = false;
+
+ // Adjust transformation and display_rect based on display rotation.
+ overlay_plane.display_rect =
+ gfx::RectF(viewport_size.width(), viewport_size.height());
+
+#if defined(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
+ // On Chromecast, always use RGBA as the scanout format for the primary plane.
+ overlay_plane.enable_blending = true;
+#endif
+ return overlay_plane;
+}
+
+void OverlayProcessor::AdjustOutputSurfaceOverlay(
+ base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
+ if (!output_surface_plane->has_value())
+ return;
+
+ // This is used by the surface control implementation to adjust the display
+ // transform and the display rect.
+ if (overlay_validator_)
+ overlay_validator_->AdjustOutputSurfaceOverlay(
+ &(output_surface_plane->value()));
+
+ // If the overlay candidates cover the entire screen, the
+ // |output_surface_plane| could be removed.
+ if (overlay_validator_) {
+ output_surface_already_handled_ |=
+ overlay_validator_->StrategyNeedsOutputSurfacePlaneRemoved();
+ }
+
+ if (output_surface_already_handled_)
+ output_surface_plane->reset();
+}
+
bool OverlayProcessor::NeedsSurfaceOccludingDamageRect() const {
return overlay_validator_ &&
overlay_validator_->NeedsSurfaceOccludingDamageRect();
diff --git a/chromium/components/viz/service/display/overlay_processor.h b/chromium/components/viz/service/display/overlay_processor.h
index 008a3dc9091..12a395038f2 100644
--- a/chromium/components/viz/service/display/overlay_processor.h
+++ b/chromium/components/viz/service/display/overlay_processor.h
@@ -37,9 +37,31 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
bool zero_damage_rect,
bool occluding_damage_equal_to_damage_rect);
+ // Data needed to represent |OutputSurface| as an overlay plane. Due to the
+ // default values for the primary plane, this is a partial list of
+ // OverlayCandidate.
+ struct VIZ_SERVICE_EXPORT OutputSurfaceOverlayPlane {
+ // Display's rotation information.
+ gfx::OverlayTransform transform;
+ // Rect on the display to position to. This takes in account of Display's
+ // rotation.
+ gfx::RectF display_rect;
+ // Size of output surface in pixels.
+ gfx::Size resource_size;
+ // Format of the buffer to scanout.
+ gfx::BufferFormat format;
+ // ColorSpace of the buffer for scanout.
+ gfx::ColorSpace color_space;
+ // Enable blending when we have underlay.
+ bool enable_blending;
+ // Gpu fence to wait for before overlay is ready for display.
+ unsigned gpu_fence_id;
+ };
+
class VIZ_SERVICE_EXPORT Strategy {
public:
virtual ~Strategy() {}
+ using PrimaryPlane = OverlayProcessor::OutputSurfaceOverlayPlane;
// Returns false if the strategy cannot be made to work with the
// current set of render passes. Returns true if the strategy was successful
// and adds any additional passes necessary to represent overlays to
@@ -50,9 +72,21 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
const FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidates,
std::vector<gfx::Rect>* content_bounds) = 0;
+ // Currently this is only overridden by the Underlay strategy: the underlay
+ // strategy needs to enable blending for the primary plane in order to show
+ // content underneath.
+ virtual void AdjustOutputSurfaceOverlay(
+ OutputSurfaceOverlayPlane* output_surface_plane) {}
+
+ // Currently this is only overridden by the Fullscreen strategy: the
+ // fullscreen strategy covers the entire screen and there is no need to use
+ // the primary plane.
+ virtual bool RemoveOutputSurfaceAsOverlay();
+
virtual OverlayStrategy GetUMAEnum() const;
};
using StrategyList = std::vector<std::unique_ptr<Strategy>>;
@@ -71,7 +105,11 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
return overlay_validator_.get();
}
+ // Returns true if the platform supports hw overlays and surface occluding
+ // damage rect needs to be computed since it will be used by overlay
+ // processor (currently Windows only).
bool NeedsSurfaceOccludingDamageRect() const;
+
void SetDisplayTransformHint(gfx::OverlayTransform transform);
void SetValidatorViewportSize(const gfx::Size& size);
@@ -83,34 +121,51 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
const SkMatrix44& output_color_matrix,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_backdrop_filters,
+ OutputSurfaceOverlayPlane* output_surface_plane,
OverlayCandidateList* overlay_candidates,
CALayerOverlayList* ca_layer_overlays,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect,
std::vector<gfx::Rect>* content_bounds);
- void SetDCHasHwOverlaySupportForTesting() {
- dc_processor_->SetHasHwOverlaySupport();
- }
+ // TODO(weiliangc): Eventually the asymmetry between primary plane and
+ // non-primary places should be internalized and should not have a special
+ // API.
+ OutputSurfaceOverlayPlane ProcessOutputSurfaceAsOverlay(
+ const gfx::Size& viewport_size,
+ const gfx::BufferFormat& buffer_format,
+ const gfx::ColorSpace& color_space) const;
+
+ // For Mac, if we successfully generated a candidate list for CALayerOverlay,
+ // we no longer need the |output_surface_plane|. This function takes a pointer
+ // to the base::Optional instance so the instance can be reset.
+ // TODO(weiliangc): Internalize the |output_surface_plane| inside the overlay
+ // processor.
+ void AdjustOutputSurfaceOverlay(
+ base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane);
protected:
- explicit OverlayProcessor(const ContextProvider* context_provider);
- void SetOverlayCandidateValidator(
+ // For testing.
+ explicit OverlayProcessor(
std::unique_ptr<OverlayCandidateValidator> overlay_validator);
StrategyList strategies_;
std::unique_ptr<OverlayCandidateValidator> overlay_validator_;
+
gfx::Rect overlay_damage_rect_;
gfx::Rect previous_frame_underlay_rect_;
bool previous_frame_underlay_was_unoccluded_ = false;
private:
+ OverlayProcessor(
+ std::unique_ptr<OverlayCandidateValidator> overlay_validator,
+ std::unique_ptr<DCLayerOverlayProcessor> dc_layer_overlay_processor);
+
bool ProcessForCALayers(
DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_backdrop_filters,
- OverlayCandidateList* overlay_candidates,
CALayerOverlayList* ca_layer_overlays,
gfx::Rect* damage_rect);
bool ProcessForDCLayers(
@@ -118,7 +173,6 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
RenderPassList* render_passes,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_backdrop_filters,
- OverlayCandidateList* overlay_candidates,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect);
// Update |damage_rect| by removing damage casued by |candidates|.
@@ -128,8 +182,9 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
const QuadList* quad_list,
gfx::Rect* damage_rect);
- std::unique_ptr<DCLayerOverlayProcessor> dc_processor_;
+ std::unique_ptr<DCLayerOverlayProcessor> dc_layer_overlay_processor_;
+ bool output_surface_already_handled_;
DISALLOW_COPY_AND_ASSIGN(OverlayProcessor);
};
diff --git a/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc b/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc
index 7515ad52bf9..f5ef58f1fd7 100644
--- a/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc
@@ -25,8 +25,11 @@ bool OverlayStrategyFullscreen::Attempt(
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
+ // Before we attempt an overlay strategy, the candidate list should be empty.
+ DCHECK(candidate_list->empty());
RenderPass* render_pass = render_pass_list->back().get();
QuadList* quad_list = &render_pass->quad_list;
// First quad of quad_list is the top most quad.
@@ -59,7 +62,7 @@ bool OverlayStrategyFullscreen::Attempt(
candidate.plane_z_order = 0;
OverlayCandidateList new_candidate_list;
new_candidate_list.push_back(candidate);
- capability_checker_->CheckOverlaySupport(&new_candidate_list);
+ capability_checker_->CheckOverlaySupport(primary_plane, &new_candidate_list);
if (!new_candidate_list.front().overlay_handled)
return false;
@@ -73,4 +76,11 @@ OverlayStrategy OverlayStrategyFullscreen::GetUMAEnum() const {
return OverlayStrategy::kFullscreen;
}
+bool OverlayStrategyFullscreen::RemoveOutputSurfaceAsOverlay() {
+ // This is called when the strategy is successful. In this case the entire
+ // screen is covered by the overlay candidate and there is no need to overlay
+ // the output surface.
+ return true;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_strategy_fullscreen.h b/chromium/components/viz/service/display/overlay_strategy_fullscreen.h
index a3a76a98b01..258eba21ad2 100644
--- a/chromium/components/viz/service/display/overlay_strategy_fullscreen.h
+++ b/chromium/components/viz/service/display/overlay_strategy_fullscreen.h
@@ -27,9 +27,11 @@ class VIZ_SERVICE_EXPORT OverlayStrategyFullscreen
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
+ bool RemoveOutputSurfaceAsOverlay() override;
OverlayStrategy GetUMAEnum() const override;
private:
diff --git a/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc b/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc
index 937350aa3dd..727a60fe9e7 100644
--- a/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -23,8 +23,11 @@ bool OverlayStrategySingleOnTop::Attempt(
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
+ // Before we attempt an overlay strategy, we shouldn't have a candidate.
+ DCHECK(candidate_list->empty());
RenderPass* render_pass = render_pass_list->back().get();
QuadList* quad_list = &render_pass->quad_list;
// Build a list of candidates with the associated quad.
@@ -54,7 +57,8 @@ bool OverlayStrategySingleOnTop::Attempt(
if (best_quad_it == quad_list->end())
return false;
- if (TryOverlay(quad_list, candidate_list, best_candidate, best_quad_it)) {
+ if (TryOverlay(quad_list, primary_plane, candidate_list, best_candidate,
+ best_quad_it)) {
if (previous_frame_resource_id_ != best_candidate.resource_id) {
previous_frame_resource_id_ = best_candidate.resource_id;
same_resource_id_frames_count_ = 1;
@@ -69,16 +73,19 @@ bool OverlayStrategySingleOnTop::Attempt(
bool OverlayStrategySingleOnTop::TryOverlay(
QuadList* quad_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
const OverlayCandidate& candidate,
QuadList::Iterator candidate_iterator) {
+ // SingleOnTop strategy means we should have one candidate.
+ DCHECK(candidate_list->empty());
// Add the overlay.
OverlayCandidateList new_candidate_list = *candidate_list;
new_candidate_list.push_back(candidate);
new_candidate_list.back().plane_z_order = 1;
// Check for support.
- capability_checker_->CheckOverlaySupport(&new_candidate_list);
+ capability_checker_->CheckOverlaySupport(primary_plane, &new_candidate_list);
const OverlayCandidate& overlay_candidate = new_candidate_list.back();
// If the candidate can be handled by an overlay, create a pass for it.
diff --git a/chromium/components/viz/service/display/overlay_strategy_single_on_top.h b/chromium/components/viz/service/display/overlay_strategy_single_on_top.h
index a7ad251e4d1..b218411f088 100644
--- a/chromium/components/viz/service/display/overlay_strategy_single_on_top.h
+++ b/chromium/components/viz/service/display/overlay_strategy_single_on_top.h
@@ -25,6 +25,7 @@ class VIZ_SERVICE_EXPORT OverlayStrategySingleOnTop
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
@@ -34,6 +35,7 @@ class VIZ_SERVICE_EXPORT OverlayStrategySingleOnTop
static constexpr size_t kMaxFrameCandidateWithSameResourceId = 3;
bool TryOverlay(QuadList* quad_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
const OverlayCandidate& candidate,
QuadList::Iterator candidate_iterator);
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay.cc b/chromium/components/viz/service/display/overlay_strategy_underlay.cc
index 86be7fd7eee..985c34d3d91 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay.cc
@@ -26,8 +26,11 @@ bool OverlayStrategyUnderlay::Attempt(
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
+ // Before we attempt an overlay strategy, the candidate list should be empty.
+ DCHECK(candidate_list->empty());
RenderPass* render_pass = render_pass_list->back().get();
QuadList& quad_list = render_pass->quad_list;
const bool compute_hints =
@@ -62,10 +65,21 @@ bool OverlayStrategyUnderlay::Attempt(
OverlayCandidateList new_candidate_list = *candidate_list;
new_candidate_list.push_back(candidate);
new_candidate_list.back().plane_z_order = -1;
- new_candidate_list.front().is_opaque = false;
- // Check for support.
- capability_checker_->CheckOverlaySupport(&new_candidate_list);
+ if (primary_plane) {
+ // Since there is a list of strategies to go through, each strategy should
+ // not change the input parameters. In this case, we need to keep the
+ // |primary_plane| unchanged. The underlay strategy only works when the
+ // |primary_plane| supports blending. In order to check the hardware
+ // support, make a copy of the |primary_plane| with blending enabled.
+ PrimaryPlane new_plane_candidate(*primary_plane);
+ new_plane_candidate.enable_blending = true;
+ // Check for support.
+ capability_checker_->CheckOverlaySupport(&new_plane_candidate,
+ &new_candidate_list);
+ } else {
+ capability_checker_->CheckOverlaySupport(nullptr, &new_candidate_list);
+ }
// If the candidate can be handled by an overlay, create a pass for it. We
// need to switch out the video quad with a black transparent one.
@@ -100,6 +114,14 @@ bool OverlayStrategyUnderlay::Attempt(
return false;
}
+// Turn on blending for the output surface plane so the underlay could show
+// through.
+void OverlayStrategyUnderlay::AdjustOutputSurfaceOverlay(
+ OverlayProcessor::OutputSurfaceOverlayPlane* output_surface_plane) {
+ if (output_surface_plane)
+ output_surface_plane->enable_blending = true;
+}
+
OverlayStrategy OverlayStrategyUnderlay::GetUMAEnum() const {
return OverlayStrategy::kUnderlay;
}
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay.h b/chromium/components/viz/service/display/overlay_strategy_underlay.h
index 338b8f752a9..263f4ddb8dc 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay.h
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay.h
@@ -41,9 +41,13 @@ class VIZ_SERVICE_EXPORT OverlayStrategyUnderlay
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
+ void AdjustOutputSurfaceOverlay(OverlayProcessor::OutputSurfaceOverlayPlane*
+ output_surface_plane) override;
+
OverlayStrategy GetUMAEnum() const override;
private:
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc
index 2cd6e8830de..b5da82946ce 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc
@@ -31,8 +31,11 @@ bool OverlayStrategyUnderlayCast::Attempt(
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass_list,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
+ // Before we attempt an overlay strategy, the candidate list should be empty.
+ DCHECK(candidate_list->empty());
RenderPass* render_pass = render_pass_list->back().get();
QuadList& quad_list = render_pass->quad_list;
bool found_underlay = false;
@@ -81,14 +84,6 @@ bool OverlayStrategyUnderlayCast::Attempt(
VLOG(1) << (found_underlay ? "Overlay activated" : "Overlay deactivated");
}
- // If the primary plane shows up in the candidates list make sure it isn't
- // opaque otherwise the content underneath won't be visible.
- if (!candidate_list->empty()) {
- DCHECK_EQ(1u, candidate_list->size());
- DCHECK(candidate_list->front().use_output_surface_for_resource);
- candidate_list->front().is_opaque = false;
- }
-
if (found_underlay) {
for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
OverlayCandidate candidate;
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h
index 284df817cdd..83d67f39ed7 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h
@@ -28,6 +28,7 @@ class VIZ_SERVICE_EXPORT OverlayStrategyUnderlayCast
const OverlayProcessor::FilterOperationsMap& render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
RenderPassList* render_pass,
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
diff --git a/chromium/components/viz/service/display/overlay_unittest.cc b/chromium/components/viz/service/display/overlay_unittest.cc
index b07fd06e94d..74c2eca4e7d 100644
--- a/chromium/components/viz/service/display/overlay_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_unittest.cc
@@ -67,6 +67,7 @@ const gfx::Transform kBothMirrorTransform =
gfx::Transform(-0.9f, 0, 0, -0.8f, 1.0f, 1.0f); // x,y -> 1-x,1-y.
const gfx::Transform kSwapTransform =
gfx::Transform(0, 1, 1, 0, 0, 0); // x,y -> y,x.
+const gfx::BufferFormat kDefaultBufferFormat = gfx::BufferFormat::RGBA_8888;
class TestOverlayCandidateValidator : public OverlayCandidateValidator {
public:
@@ -75,7 +76,8 @@ class TestOverlayCandidateValidator : public OverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return false; }
bool AllowDCLayerOverlays() const override { return false; }
bool NeedsSurfaceOccludingDamageRect() const override { return false; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
};
class FullscreenOverlayValidator : public TestOverlayCandidateValidator {
@@ -86,7 +88,8 @@ class FullscreenOverlayValidator : public TestOverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return false; }
bool AllowDCLayerOverlays() const override { return false; }
bool NeedsSurfaceOccludingDamageRect() const override { return true; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {
surfaces->back().overlay_handled = true;
}
};
@@ -102,14 +105,14 @@ class SingleOverlayValidator : public TestOverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return false; }
bool AllowDCLayerOverlays() const override { return false; }
bool NeedsSurfaceOccludingDamageRect() const override { return true; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
- // We may have 1 or 2 surfaces depending on whether this ran through the
- // full renderer and picked up the output surface, or not.
- ASSERT_LE(1U, surfaces->size());
- ASSERT_GE(2U, surfaces->size());
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {
+ // We have one overlay surface to test. The output surface as primary plane
+ // is optional, depending on whether this ran
+ // through the full renderer and picked up the output surface, or not.
+ ASSERT_EQ(1U, surfaces->size());
OverlayCandidate& candidate = surfaces->back();
- EXPECT_TRUE(!candidate.use_output_surface_for_resource);
for (const auto& r : expected_rects_) {
const float kAbsoluteError = 0.01f;
if (std::abs(r.x() - candidate.display_rect.x()) <= kAbsoluteError &&
@@ -145,7 +148,8 @@ class CALayerValidator : public TestOverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return true; }
bool AllowDCLayerOverlays() const override { return false; }
bool NeedsSurfaceOccludingDamageRect() const override { return false; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
};
class DCLayerValidator : public TestOverlayCandidateValidator {
@@ -153,7 +157,8 @@ class DCLayerValidator : public TestOverlayCandidateValidator {
bool AllowCALayerOverlays() const override { return false; }
bool AllowDCLayerOverlays() const override { return true; }
bool NeedsSurfaceOccludingDamageRect() const override { return true; }
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override {}
};
class SingleOnTopOverlayValidator : public SingleOverlayValidator {
@@ -187,23 +192,18 @@ class UnderlayCastOverlayValidator : public SingleOverlayValidator {
class DefaultOverlayProcessor : public OverlayProcessor {
public:
- explicit DefaultOverlayProcessor(ContextProvider* context_provider);
- size_t GetStrategyCount() const;
-};
-
-DefaultOverlayProcessor::DefaultOverlayProcessor(
- ContextProvider* context_provider)
- : OverlayProcessor(context_provider) {
- SetOverlayCandidateValidator(std::make_unique<SingleOverlayValidator>());
-}
+ DefaultOverlayProcessor()
+ : OverlayProcessor(std::make_unique<SingleOverlayValidator>()) {}
-size_t DefaultOverlayProcessor::GetStrategyCount() const {
- if (auto* validator = overlay_validator_.get())
- return static_cast<TestOverlayCandidateValidator*>(validator)
- ->GetStrategyCount();
+ size_t GetStrategyCount() const {
+ if (auto* validator = overlay_validator_.get()) {
+ return static_cast<TestOverlayCandidateValidator*>(validator)
+ ->GetStrategyCount();
+ }
- return 0;
-}
+ return 0;
+ }
+};
class OverlayOutputSurface : public OutputSurface {
public:
@@ -261,11 +261,8 @@ template <typename OverlayCandidateValidatorType>
class TypedOverlayProcessor : public OverlayProcessor {
public:
explicit TypedOverlayProcessor(
- const ContextProvider* context_provider,
std::unique_ptr<OverlayCandidateValidatorType> validator)
- : OverlayProcessor(context_provider) {
- SetOverlayCandidateValidator(std::move(validator));
- }
+ : OverlayProcessor(std::move(validator)) {}
OverlayCandidateValidatorType* GetTypedOverlayCandidateValidator() {
const OverlayCandidateValidator* const_base_validator =
@@ -568,9 +565,7 @@ class OverlayTest : public testing::Test {
child_resource_provider_ = std::make_unique<ClientResourceProvider>(true);
overlay_processor_ = std::make_unique<OverlayProcessorType>(
- output_surface_->context_provider(),
std::make_unique<OverlayCandidateValidatorType>());
- overlay_processor_->SetDCHasHwOverlaySupportForTesting();
}
void TearDown() override {
@@ -622,8 +617,7 @@ TEST(OverlayTest, OverlaysProcessorHasStrategy) {
provider.get(),
shared_bitmap_manager.get());
- auto overlay_processor = std::make_unique<DefaultOverlayProcessor>(
- output_surface.context_provider());
+ auto overlay_processor = std::make_unique<DefaultOverlayProcessor>();
EXPECT_GE(2U, overlay_processor->GetStrategyCount());
}
@@ -649,8 +643,8 @@ TEST_F(FullscreenOverlayTest, SuccessfulOverlay) {
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
// Check that all the quads are gone.
@@ -686,8 +680,8 @@ TEST_F(FullscreenOverlayTest, FailOnOutputColorMatrix) {
// overlays since color matrices are not supported yet.
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetNonIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(0U, candidate_list.size());
// Check that the 2 quads are not gone.
@@ -711,8 +705,8 @@ TEST_F(FullscreenOverlayTest, AlphaFail) {
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
// Check that all the quads are gone.
EXPECT_EQ(1U, main_pass->quad_list.size());
@@ -737,8 +731,8 @@ TEST_F(FullscreenOverlayTest, SuccessfulResourceSizeInPixels) {
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
// Check that the quad is gone.
@@ -767,8 +761,8 @@ TEST_F(FullscreenOverlayTest, OnTopFail) {
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(0U, candidate_list.size());
// Check that the 2 quads are not gone.
@@ -793,8 +787,8 @@ TEST_F(FullscreenOverlayTest, NotCoveringFullscreenFail) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(0U, candidate_list.size());
// Check that the quad is not gone.
@@ -825,8 +819,8 @@ TEST_F(FullscreenOverlayTest, RemoveFullscreenQuadFromQuadList) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
// Check that the fullscreen quad is gone.
@@ -857,8 +851,8 @@ TEST_F(SingleOverlayOnTopTest, SuccessfulOverlay) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
// Check that the quad is gone.
@@ -906,8 +900,8 @@ TEST_F(SingleOverlayOnTopTest, PrioritizeBiggerOne) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
// Check that one quad is gone.
@@ -934,21 +928,14 @@ TEST_F(SingleOverlayOnTopTest, DamageRect) {
// Check for potential candidates.
OverlayCandidateList candidate_list;
- // Primary plane.
- OverlayCandidate output_surface_plane;
- output_surface_plane.display_rect = gfx::RectF(kOverlayRect);
- output_surface_plane.use_output_surface_for_resource = true;
- output_surface_plane.overlay_handled = true;
- candidate_list.push_back(output_surface_plane);
-
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_TRUE(damage_rect_.IsEmpty());
}
@@ -970,8 +957,8 @@ TEST_F(SingleOverlayOnTopTest, NoCandidates) {
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
// There should be nothing new here.
CompareRenderPassLists(pass_list, original_pass_list);
@@ -999,8 +986,8 @@ TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
// There should be nothing new here.
CompareRenderPassLists(pass_list, original_pass_list);
@@ -1027,8 +1014,8 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1047,8 +1034,8 @@ TEST_F(SingleOverlayOnTopTest, AcceptBlending) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
EXPECT_FALSE(damage_rect_.IsEmpty());
gfx::Rect overlay_damage_rect =
@@ -1070,8 +1057,8 @@ TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1089,8 +1076,8 @@ TEST_F(SingleOverlayOnTopTest, AcceptBlackBackgroundColor) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1109,8 +1096,8 @@ TEST_F(SingleOverlayOnTopTest, RejectBlackBackgroundColorWithBlending) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1128,8 +1115,8 @@ TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1147,8 +1134,8 @@ TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1167,8 +1154,8 @@ TEST_F(SingleOverlayOnTopTest, RejectNonAxisAlignedTransform) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1187,8 +1174,8 @@ TEST_F(SingleOverlayOnTopTest, AllowClipped) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1209,8 +1196,8 @@ TEST_F(UnderlayTest, AllowVerticalFlip) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL,
candidate_list.back().transform);
@@ -1234,8 +1221,8 @@ TEST_F(UnderlayTest, AllowHorizontalFlip) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL,
candidate_list.back().transform);
@@ -1257,8 +1244,8 @@ TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1279,8 +1266,8 @@ TEST_F(SingleOverlayOnTopTest, AcceptMirrorYTransform) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
}
@@ -1301,8 +1288,8 @@ TEST_F(UnderlayTest, Allow90DegreeRotation) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_90, candidate_list.back().transform);
}
@@ -1324,8 +1311,8 @@ TEST_F(UnderlayTest, Allow180DegreeRotation) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_180, candidate_list.back().transform);
}
@@ -1347,8 +1334,8 @@ TEST_F(UnderlayTest, Allow270DegreeRotation) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform);
}
@@ -1368,8 +1355,8 @@ TEST_F(UnderlayTest, AllowsOpaqueCandidates) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
}
@@ -1387,8 +1374,8 @@ TEST_F(UnderlayTest, DisallowsTransparentCandidates) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(0U, candidate_list.size());
}
@@ -1421,8 +1408,8 @@ TEST_F(UnderlayTest, DisallowFilteredQuadOnTop) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(0U, candidate_list.size());
}
@@ -1441,8 +1428,8 @@ TEST_F(TransparentUnderlayTest, AllowsOpaqueCandidates) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
}
@@ -1460,8 +1447,8 @@ TEST_F(TransparentUnderlayTest, AllowsTransparentCandidates) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
}
@@ -1484,8 +1471,8 @@ TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1510,8 +1497,8 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1534,8 +1521,8 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, candidate_list.size());
}
@@ -1558,8 +1545,8 @@ TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1580,8 +1567,8 @@ TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, candidate_list.size());
}
@@ -1633,8 +1620,8 @@ TEST_F(SingleOverlayOnTopTest, DoNotPromoteIfContentsDontChange) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
if (i <= kFramesSkippedBeforeNotPromoting) {
EXPECT_EQ(1U, candidate_list.size());
@@ -1668,8 +1655,8 @@ TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(-1, candidate_list[0].plane_z_order);
EXPECT_EQ(2U, main_pass->quad_list.size());
@@ -1699,8 +1686,8 @@ TEST_F(UnderlayTest, AllowOnTop) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_EQ(1U, candidate_list.size());
EXPECT_EQ(-1, candidate_list[0].plane_z_order);
// The overlay quad should have changed to a SOLID_COLOR quad.
@@ -1728,8 +1715,8 @@ TEST_F(UnderlayTest, InitialUnderlayDamageNotSubtracted) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(kOverlayRect, damage_rect_);
}
@@ -1756,8 +1743,8 @@ TEST_F(UnderlayTest, DamageSubtractedForConsecutiveIdenticalUnderlays) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
}
// The second time the same overlay rect is scheduled it will be subtracted
@@ -1788,8 +1775,8 @@ TEST_F(UnderlayTest, DamageNotSubtractedForNonIdenticalConsecutiveUnderlays) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(overlay_rects[i], damage_rect_);
}
@@ -1823,8 +1810,8 @@ TEST_F(UnderlayTest, DamageNotSubtractedForNonConsecutiveIdenticalUnderlays) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
}
EXPECT_EQ(kOverlayRect, damage_rect_);
@@ -1854,8 +1841,8 @@ TEST_F(UnderlayTest, DamageSubtractedForOneFrameAfterBecomingUnoccluded) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
// The damage rect should not be subtracted if the underlay is occluded
// (i==0) or it is unoccluded for the first time (i==1).
@@ -1886,8 +1873,8 @@ TEST_F(UnderlayTest, DamageNotSubtractedWhenQuadsAboveOverlap) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
}
EXPECT_EQ(kOverlayRect, damage_rect_);
@@ -1916,8 +1903,8 @@ TEST_F(UnderlayTest, DamageSubtractedWhenQuadsAboveDontOverlap) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
}
EXPECT_TRUE(damage_rect_.IsEmpty());
@@ -1936,22 +1923,24 @@ TEST_F(UnderlayTest, PrimaryPlaneOverlayIsTransparentWithUnderlay) {
kOverlayRect);
OverlayCandidateList candidate_list;
- OverlayCandidate candidate;
- candidate.use_output_surface_for_resource = true;
- candidate.is_opaque = true;
- candidate_list.push_back(candidate);
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+
+ auto output_surface_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay(
+ kDisplaySize, kDefaultBufferFormat, gfx::ColorSpace());
+ OverlayProcessor::OutputSurfaceOverlayPlane* primary_plane =
+ &output_surface_plane;
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, primary_plane,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
- EXPECT_EQ(2U, candidate_list.size());
- ASSERT_EQ(false, candidate_list[0].is_opaque);
+ EXPECT_EQ(1U, candidate_list.size());
+ ASSERT_EQ(true, output_surface_plane.enable_blending);
}
TEST_F(UnderlayTest, UpdateDamageWhenChangingUnderlays) {
@@ -1979,8 +1968,8 @@ TEST_F(UnderlayTest, UpdateDamageWhenChangingUnderlays) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
}
EXPECT_EQ(kOverlayRect, damage_rect_);
@@ -2021,8 +2010,8 @@ TEST_F(UnderlayTest, UpdateDamageRectWhenNoPromotion) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_background_filters, &candidate_list,
- nullptr, nullptr, &damage_rect, &content_bounds_);
+ render_pass_filters, render_pass_background_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect, &content_bounds_);
EXPECT_EQ(expected_damages[i], damage_rect);
ASSERT_EQ(expected_candidate_size[i], candidate_list.size());
@@ -2064,8 +2053,8 @@ TEST_F(UnderlayTest, CandidateNoDamageWhenQuadSharedStateNoOccludingDamage) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
if (i == 0 || i == 1 || i == 3)
EXPECT_FALSE(damage_rect_.IsEmpty());
@@ -2088,8 +2077,8 @@ TEST_F(UnderlayCastTest, NoOverlayContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, content_bounds_.size());
}
@@ -2105,8 +2094,8 @@ TEST_F(UnderlayCastTest, FullScreenOverlayContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_TRUE(content_bounds_[0].IsEmpty());
@@ -2135,8 +2124,8 @@ TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_TRUE(content_bounds_[0].IsEmpty());
@@ -2157,8 +2146,8 @@ TEST_F(UnderlayCastTest, OverlayOccludedContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(kOverlayTopLeftRect, content_bounds_[0]);
@@ -2182,8 +2171,8 @@ TEST_F(UnderlayCastTest, OverlayOccludedUnionContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(kOverlayRect, content_bounds_[0]);
@@ -2212,8 +2201,8 @@ TEST_F(UnderlayCastTest, RoundOverlayContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(gfx::Rect(0, 0, 11, 11), content_bounds_[0]);
@@ -2243,13 +2232,14 @@ TEST_F(UnderlayCastTest, RoundContentBounds) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(kOverlayRect, content_bounds_[0]);
}
+#if defined(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
TEST_F(UnderlayCastTest, PrimaryPlaneOverlayIsAlwaysTransparent) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
gfx::Rect output_rect = pass->output_rect;
@@ -2258,23 +2248,23 @@ TEST_F(UnderlayCastTest, PrimaryPlaneOverlayIsAlwaysTransparent) {
output_rect, SK_ColorWHITE);
OverlayCandidateList candidate_list;
- OverlayCandidate candidate;
- candidate.use_output_surface_for_resource = true;
- candidate.is_opaque = true;
- candidate_list.push_back(candidate);
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+ auto output_surface_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay(
+ kDisplaySize, kDefaultBufferFormat, gfx::ColorSpace());
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, &output_surface_plane,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
- ASSERT_EQ(false, candidate_list[0].is_opaque);
+ ASSERT_EQ(true, output_surface_plane.enable_blending);
EXPECT_EQ(0U, content_bounds_.size());
}
+#endif
TEST_F(UnderlayCastTest, NoOverlayPromotionWithoutProtectedContent) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
@@ -2290,23 +2280,13 @@ TEST_F(UnderlayCastTest, NoOverlayPromotionWithoutProtectedContent) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &candidate_list,
- nullptr, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &candidate_list, nullptr, nullptr, &damage_rect_, &content_bounds_);
ASSERT_TRUE(candidate_list.empty());
EXPECT_TRUE(content_bounds_.empty());
}
-OverlayCandidateList BackbufferOverlayList(const RenderPass* root_render_pass) {
- OverlayCandidateList list;
- OverlayCandidate output_surface_plane;
- output_surface_plane.display_rect = gfx::RectF(root_render_pass->output_rect);
- output_surface_plane.use_output_surface_for_resource = true;
- output_surface_plane.overlay_handled = true;
- list.push_back(output_surface_plane);
- return list;
-}
-
TEST_F(CALayerOverlayTest, AllowNonAxisAlignedTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
@@ -2314,18 +2294,20 @@ TEST_F(CALayerOverlayTest, AllowNonAxisAlignedTransform) {
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(45.f);
-
+ gfx::Size display_size(pass->output_rect.width(), pass->output_rect.height());
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
&ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
+
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, ca_layer_list.size());
@@ -2339,22 +2321,25 @@ TEST_F(CALayerOverlayTest, ThreeDTransform) {
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutXAxis(45.f);
+ gfx::Size display_size(pass->output_rect.width(), pass->output_rect.height());
CALayerOverlayList ca_layer_list;
- OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
&ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, ca_layer_list.size());
gfx::Transform expected_transform;
expected_transform.RotateAboutXAxis(45.f);
gfx::Transform actual_transform(ca_layer_list.back().shared_state->transform);
+
EXPECT_EQ(expected_transform.ToString(), actual_transform.ToString());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
}
@@ -2366,18 +2351,21 @@ TEST_F(CALayerOverlayTest, AllowContainingClip) {
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = kOverlayRect;
+ gfx::Size display_size(pass->output_rect.width(), pass->output_rect.height());
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
&ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
+
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, ca_layer_list.size());
@@ -2391,18 +2379,21 @@ TEST_F(CALayerOverlayTest, NontrivialClip) {
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(64, 64, 128, 128);
+ gfx::Size display_size(pass->output_rect.width(), pass->output_rect.height());
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
&ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
+
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, ca_layer_list.size());
@@ -2418,17 +2409,19 @@ TEST_F(CALayerOverlayTest, SkipTransparent) {
resource_provider_.get(), child_resource_provider_.get(),
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->opacity = 0;
+ gfx::Size display_size(pass->output_rect.width(), pass->output_rect.height());
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
+
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
&ca_layer_list, nullptr, &damage_rect_, &content_bounds_);
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(0U, overlay_list.size());
@@ -2458,8 +2451,8 @@ TEST_F(DCLayerOverlayTest, AllowNonAxisAlignedTransform) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list, nullptr,
- &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
+ nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(1, dc_layer_list.back().z_order);
@@ -2490,8 +2483,8 @@ TEST_F(DCLayerOverlayTest, AllowRequiredNonAxisAlignedTransform) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list, nullptr,
- &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
+ nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(0U, overlay_list.size());
ASSERT_EQ(1U, dc_layer_list.size());
@@ -2535,8 +2528,9 @@ TEST_F(DCLayerOverlayTest, Occluded) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(2U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2576,8 +2570,9 @@ TEST_F(DCLayerOverlayTest, Occluded) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(2U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2627,8 +2622,9 @@ TEST_F(DCLayerOverlayTest, DamageRectWithoutVideoDamage) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2665,8 +2661,9 @@ TEST_F(DCLayerOverlayTest, DamageRectWithoutVideoDamage) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2708,8 +2705,9 @@ TEST_F(DCLayerOverlayTest, DamageRectWithNonRootOverlay) {
pass_list.push_back(std::move(root_pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2745,8 +2743,9 @@ TEST_F(DCLayerOverlayTest, DamageRectWithNonRootOverlay) {
pass_list.push_back(std::move(root_pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2773,8 +2772,9 @@ TEST_F(DCLayerOverlayTest, DamageRect) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
@@ -2870,8 +2870,8 @@ TEST_F(DCLayerOverlayTest, MultiplePassDamageRect) {
pass_list.push_back(std::move(root_pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list, nullptr,
- &dc_layer_list, &root_damage_rect, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr, &overlay_list,
+ nullptr, &dc_layer_list, &root_damage_rect, &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -2965,8 +2965,9 @@ TEST_F(DCLayerOverlayTest, ClipRect) {
damage_rect_ = gfx::Rect(1, 1, 10, 10);
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
// Because of clip rects the overlay isn't occluded and shouldn't be an
@@ -3002,8 +3003,9 @@ TEST_F(DCLayerOverlayTest, TransparentOnTop) {
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(1, dc_layer_list.back().z_order);
@@ -3045,8 +3047,9 @@ TEST_F(DCLayerOverlayTest, UnderlayDamageRectWithQuadOnTopUnchanged) {
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
- render_pass_filters, render_pass_backdrop_filters, &overlay_list,
- nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
+ render_pass_filters, render_pass_backdrop_filters, nullptr,
+ &overlay_list, nullptr, &dc_layer_list, &damage_rect_,
+ &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -3091,7 +3094,8 @@ class OverlayInfoRendererGL : public GLRenderer {
return;
}
- ASSERT_EQ(2U, current_frame()->overlay_list.size());
+ ASSERT_TRUE(current_frame()->output_surface_plane.has_value());
+ ASSERT_EQ(1U, current_frame()->overlay_list.size());
EXPECT_GE(current_frame()->overlay_list.back().resource_id, 0U);
}
@@ -3108,8 +3112,7 @@ class OverlayInfoRendererGL : public GLRenderer {
void SetOverlayProcessorWithValidator(
std::unique_ptr<SingleOverlayValidator> validator) {
- overlay_processor_.reset(new OverlayProcessorType(
- output_surface_->context_provider(), std::move(validator)));
+ overlay_processor_.reset(new OverlayProcessorType(std::move(validator)));
}
private:
@@ -3401,24 +3404,24 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
DirectRenderer::DrawingFrame frame1;
frame1.render_passes_in_draw_order = &pass_list;
- frame1.overlay_list.resize(2);
- frame1.overlay_list.front().use_output_surface_for_resource = true;
+ frame1.overlay_list.resize(1);
+ frame1.output_surface_plane = OverlayProcessor::OutputSurfaceOverlayPlane();
OverlayCandidate& overlay1 = frame1.overlay_list.back();
overlay1.resource_id = mapped_resource1;
overlay1.plane_z_order = 1;
DirectRenderer::DrawingFrame frame2;
frame2.render_passes_in_draw_order = &pass_list;
- frame2.overlay_list.resize(2);
- frame2.overlay_list.front().use_output_surface_for_resource = true;
+ frame2.overlay_list.resize(1);
+ frame2.output_surface_plane = OverlayProcessor::OutputSurfaceOverlayPlane();
OverlayCandidate& overlay2 = frame2.overlay_list.back();
overlay2.resource_id = mapped_resource2;
overlay2.plane_z_order = 1;
DirectRenderer::DrawingFrame frame3;
frame3.render_passes_in_draw_order = &pass_list;
- frame3.overlay_list.resize(2);
- frame3.overlay_list.front().use_output_surface_for_resource = true;
+ frame3.overlay_list.resize(1);
+ frame3.output_surface_plane = OverlayProcessor::OutputSurfaceOverlayPlane();
OverlayCandidate& overlay3 = frame3.overlay_list.back();
overlay3.resource_id = mapped_resource3;
overlay3.plane_z_order = 1;
@@ -3589,24 +3592,24 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
DirectRenderer::DrawingFrame frame1;
frame1.render_passes_in_draw_order = &pass_list;
- frame1.overlay_list.resize(2);
- frame1.overlay_list.front().use_output_surface_for_resource = true;
+ frame1.overlay_list.resize(1);
+ frame1.output_surface_plane = OverlayProcessor::OutputSurfaceOverlayPlane();
OverlayCandidate& overlay1 = frame1.overlay_list.back();
overlay1.resource_id = mapped_resource1;
overlay1.plane_z_order = 1;
DirectRenderer::DrawingFrame frame2;
frame2.render_passes_in_draw_order = &pass_list;
- frame2.overlay_list.resize(2);
- frame2.overlay_list.front().use_output_surface_for_resource = true;
+ frame2.overlay_list.resize(1);
+ frame2.output_surface_plane = OverlayProcessor::OutputSurfaceOverlayPlane();
OverlayCandidate& overlay2 = frame2.overlay_list.back();
overlay2.resource_id = mapped_resource2;
overlay2.plane_z_order = 1;
DirectRenderer::DrawingFrame frame3;
frame3.render_passes_in_draw_order = &pass_list;
- frame3.overlay_list.resize(2);
- frame3.overlay_list.front().use_output_surface_for_resource = true;
+ frame3.overlay_list.resize(1);
+ frame3.output_surface_plane = OverlayProcessor::OutputSurfaceOverlayPlane();
OverlayCandidate& overlay3 = frame3.overlay_list.back();
overlay3.resource_id = mapped_resource3;
overlay3.plane_z_order = 1;
@@ -3686,11 +3689,12 @@ class CALayerOverlayRPDQTest : public CALayerOverlayTest {
}
void ProcessForOverlays() {
- overlay_list_ = BackbufferOverlayList(pass_);
+ overlay_list_.clear();
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list_, GetIdentityColorMatrix(),
- render_pass_filters_, render_pass_backdrop_filters_, &overlay_list_,
- &ca_layer_list_, nullptr, &damage_rect_, &content_bounds_);
+ render_pass_filters_, render_pass_backdrop_filters_, nullptr,
+ &overlay_list_, &ca_layer_list_, nullptr, &damage_rect_,
+ &content_bounds_);
}
RenderPassList pass_list_;
RenderPass* pass_;
diff --git a/chromium/components/viz/service/display/renderer_perftest.cc b/chromium/components/viz/service/display/renderer_perftest.cc
index 2b857a8c8bc..f6ad154d7fe 100644
--- a/chromium/components/viz/service/display/renderer_perftest.cc
+++ b/chromium/components/viz/service/display/renderer_perftest.cc
@@ -10,14 +10,17 @@
// Example usage:
//
// $ out/release/viz_perftests --gtest_filter="*RendererPerfTest*" \
-// --use-gpu-in-tests
+// --use-gpu-in-tests --test-launcher-timeout=300000 \
+// --perf-test-time-ms=240000
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/lap_timer.h"
@@ -57,6 +60,21 @@ static constexpr FrameSinkId kArbitraryFrameSinkId(3, 3);
static constexpr gfx::Size kSurfaceSize(1000, 1000);
static constexpr gfx::Rect kSurfaceRect(kSurfaceSize);
+base::TimeDelta TestTimeLimit() {
+ static const char kPerfTestTimeMillis[] = "perf-test-time-ms";
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(kPerfTestTimeMillis)) {
+ const std::string delay_millis_string(
+ command_line->GetSwitchValueASCII(kPerfTestTimeMillis));
+ int delay_millis;
+ if (base::StringToInt(delay_millis_string, &delay_millis) &&
+ delay_millis > 0) {
+ return base::TimeDelta::FromMilliseconds(delay_millis);
+ }
+ }
+ return base::TimeDelta::FromSeconds(3);
+}
+
class WaitForSwapDisplayClient : public DisplayClient {
public:
WaitForSwapDisplayClient() = default;
@@ -204,7 +222,10 @@ class RendererPerfTest : public testing::Test {
&manager_,
kArbitraryFrameSinkId,
true /* is_root */,
- true /* needs_sync_points */)) {}
+ true /* needs_sync_points */)),
+ timer_(/*warmup_laps=*/100,
+ /*time_limit=*/TestTimeLimit(),
+ /*check_interval=*/10) {}
// Overloaded for concrete RendererType below.
std::unique_ptr<OutputSurface> CreateOutputSurface(
diff --git a/chromium/components/viz/service/display/renderer_pixeltest.cc b/chromium/components/viz/service/display/renderer_pixeltest.cc
index 11d0ce1d5d8..d69d72132ab 100644
--- a/chromium/components/viz/service/display/renderer_pixeltest.cc
+++ b/chromium/components/viz/service/display/renderer_pixeltest.cc
@@ -28,6 +28,7 @@
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/gl_renderer.h"
+#include "components/viz/service/display/software_renderer.h"
#include "components/viz/test/test_in_process_context_provider.h"
#include "components/viz/test/test_shared_bitmap_manager.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -1320,8 +1321,7 @@ using GLRendererTypes =
::testing::Types<GLRenderer, cc::GLRendererWithExpandedViewport>;
TYPED_TEST_SUITE(IntersectingQuadPixelTest, RendererTypes);
-// TODO(crbug.gom/939442): Enable these tests for SkiaRenderer.
-TYPED_TEST_SUITE(IntersectingVideoQuadPixelTest, GLRendererTypes);
+TYPED_TEST_SUITE(IntersectingVideoQuadPixelTest, GPURendererTypes);
TYPED_TEST_SUITE(IntersectingQuadSoftwareTest, SoftwareRendererTypes);
TYPED_TEST(IntersectingQuadPixelTest, SolidColorQuads) {
@@ -1533,7 +1533,7 @@ TYPED_TEST(IntersectingVideoQuadPixelTest, YUVVideoQuads) {
this->child_context_provider_.get());
this->AppendBackgroundAndRunTest(
- cc::FuzzyPixelOffByOneComparator(false),
+ cc::FuzzyPixelComparator(true, 0.50f, 0.f, 1.2f, 2, 0),
FILE_PATH_LITERAL("intersecting_blue_green_squares_video.png"));
}
@@ -2954,8 +2954,8 @@ class RendererPixelTestWithBackdropFilter
gfx::Rect filter_pass_layer_rect_;
};
-// TODO(916318): The software renderer does not support background filters yet.
using BackdropFilterRendererTypes = ::testing::Types<GLRenderer,
+ SoftwareRenderer,
SkiaRenderer
#if defined(ENABLE_VIZ_VULKAN_TESTS)
,
@@ -2998,7 +2998,7 @@ TYPED_TEST(RendererPixelTestWithBackdropFilter, InvertFilterWithMask) {
EXPECT_TRUE(this->RunPixelTest(
&this->pass_list_,
base::FilePath(FILE_PATH_LITERAL("backdrop_filter_masked.png")),
- cc::ExactPixelComparator(true)));
+ cc::FuzzyPixelOffByOneComparator(false)));
}
template <typename RendererType>
diff --git a/chromium/components/viz/service/display/resource_metadata.cc b/chromium/components/viz/service/display/resource_metadata.cc
deleted file mode 100644
index c46dfab2fb0..00000000000
--- a/chromium/components/viz/service/display/resource_metadata.cc
+++ /dev/null
@@ -1,18 +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 "components/viz/service/display/resource_metadata.h"
-
-namespace viz {
-
-ResourceMetadata::ResourceMetadata() = default;
-
-ResourceMetadata::ResourceMetadata(const ResourceMetadata& other) = default;
-
-ResourceMetadata::~ResourceMetadata() = default;
-
-ResourceMetadata& ResourceMetadata::operator=(const ResourceMetadata& other) =
- default;
-
-} // namespace viz
diff --git a/chromium/components/viz/service/display/resource_metadata.h b/chromium/components/viz/service/display/resource_metadata.h
deleted file mode 100644
index 05860c5ca6e..00000000000
--- a/chromium/components/viz/service/display/resource_metadata.h
+++ /dev/null
@@ -1,57 +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 COMPONENTS_VIZ_SERVICE_DISPLAY_RESOURCE_METADATA_H_
-#define COMPONENTS_VIZ_SERVICE_DISPLAY_RESOURCE_METADATA_H_
-
-#include "base/optional.h"
-#include "components/viz/common/resources/resource_format.h"
-#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/service/viz_service_export.h"
-#include "gpu/command_buffer/common/mailbox_holder.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "gpu/ipc/common/vulkan_ycbcr_info.h"
-#include "third_party/skia/include/gpu/GrTypes.h"
-#include "ui/gfx/color_space.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace viz {
-
-// Metadata for a resource named by a ResourceId in DisplayResourceProvider.
-// Used to construct a promise SkImage for a ResourceId.
-struct VIZ_SERVICE_EXPORT ResourceMetadata {
- ResourceMetadata();
- ResourceMetadata(const ResourceMetadata& other);
- ~ResourceMetadata();
- ResourceMetadata& operator=(const ResourceMetadata& other);
-
- // Resource Id.
- ResourceId resource_id = kInvalidResourceId;
-
- // A mailbox holder for the resource texture.
- gpu::MailboxHolder mailbox_holder;
-
- // The resource size.
- gfx::Size size;
-
- // ResourceFormat from the resource texture.
- ResourceFormat resource_format = RGBA_8888;
-
- // The color space for the resource texture.
- gfx::ColorSpace color_space;
-
- // Whether resource is premultiplied.
- SkAlphaType alpha_type;
-
- // If the SkImage should use top-left or bottom-left for (0,0) uv
- GrSurfaceOrigin origin;
-
- // Sampler conversion information which is used in vulkan context for android
- // video.
- base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info;
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_RESOURCE_METADATA_H_
diff --git a/chromium/components/viz/service/display/skia_output_surface.h b/chromium/components/viz/service/display/skia_output_surface.h
index eaaeebbe212..7e5023de890 100644
--- a/chromium/components/viz/service/display/skia_output_surface.h
+++ b/chromium/components/viz/service/display/skia_output_surface.h
@@ -9,6 +9,7 @@
#include <vector>
#include "components/viz/common/resources/resource_format.h"
+#include "components/viz/common/resources/resource_id.h"
#include "components/viz/service/display/external_use_client.h"
#include "components/viz/service/display/output_surface.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -24,7 +25,6 @@ namespace viz {
class ContextLostObserver;
class CopyOutputRequest;
-struct ResourceMetadata;
namespace copy_output {
struct RenderPassGeometry;
@@ -50,24 +50,24 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface,
// called.
virtual SkCanvas* BeginPaintCurrentFrame() = 0;
- // Make a promise SkImage from the given |metadata|. The SkiaRenderer can use
- // the image with SkCanvas returned by |GetSkCanvasForCurrentFrame|, but Skia
- // will not read the content of the resource until the sync token in the
- // |metadata| is satisfied. The SwapBuffers should take care of this by
- // scheduling a GPU task with all resource sync tokens recorded by
+ // Make a promise SkImage from the given |image_context|. The SkiaRenderer can
+ // use the image with SkCanvas returned by |GetSkCanvasForCurrentFrame|, but
+ // Skia will not read the content of the resource until the |sync_token| in
+ // the |image_context| is satisfied. The SwapBuffers should take care of this
+ // by scheduling a GPU task with all resource sync tokens recorded by
// MakePromiseSkImage for the current frame.
- virtual sk_sp<SkImage> MakePromiseSkImage(
- const ResourceMetadata& metadata) = 0;
-
- // Make a promise SkImage from the given |metadata| and the |yuv_color_space|.
- // For YUV format, at least three resource metadatas should be provided.
- // metadatas[0] contains pixels from y panel, metadatas[1] contains pixels
- // from u panel, metadatas[2] contains pixels from v panel. For NV12 format,
- // at least two resource metadatas should be provided. metadatas[0] contains
- // pixels from y panel, metadatas[1] contains pixels from u and v panels. If
- // has_alpha is true, the last item in metadatas contains alpha panel.
+ virtual void MakePromiseSkImage(
+ ExternalUseClient::ImageContext* image_context) = 0;
+
+ // Make a promise SkImage from the given |contexts| and the |yuv_color_space|.
+ // For YUV format, at least three resource contexts should be provided.
+ // contexts[0] contains pixels from y panel, contexts[1] contains pixels
+ // from u panel, contexts[2] contains pixels from v panel. For NV12 format,
+ // at least two resource contexts should be provided. contexts[0] contains
+ // pixels from y panel, contexts[1] contains pixels from u and v panels. If
+ // has_alpha is true, the last item in contexts contains alpha panel.
virtual sk_sp<SkImage> MakePromiseSkImageFromYUV(
- const std::vector<ResourceMetadata>& metadatas,
+ const std::vector<ExternalUseClient::ImageContext*>& contexts,
SkYUVColorSpace yuv_color_space,
sk_sp<SkColorSpace> dst_color_space,
bool has_alpha) = 0;
@@ -75,8 +75,10 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface,
// Swaps the current backbuffer to the screen.
virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;
- // Schedule overlay planes to be displayed
- virtual void ScheduleOverlays(OverlayCandidateList overlays) = 0;
+ // TODO(weiliangc): This API should move to OverlayProcessor.
+ // Schedule |output_surface_plane| as an overlay plane to be displayed.
+ virtual void ScheduleOutputSurfaceAsOverlay(
+ OverlayProcessor::OutputSurfaceOverlayPlane output_surface_plane) = 0;
// Begin painting a render pass. This method will create a
// SkDeferredDisplayListRecorder and return a SkCanvas of it. The SkiaRenderer
diff --git a/chromium/components/viz/service/display/skia_renderer.cc b/chromium/components/viz/service/display/skia_renderer.cc
index a7019497320..68c6e3a2c4e 100644
--- a/chromium/components/viz/service/display/skia_renderer.cc
+++ b/chromium/components/viz/service/display/skia_renderer.cc
@@ -33,7 +33,6 @@
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/renderer_utils.h"
#include "components/viz/service/display/resource_fence.h"
-#include "components/viz/service/display/resource_metadata.h"
#include "components/viz/service/display/skia_output_surface.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "skia/ext/opacity_filter_canvas.h"
@@ -269,6 +268,12 @@ bool IsAAForcedOff(const DrawQuad* quad) {
return SolidColorDrawQuad::MaterialCast(quad)->force_anti_aliasing_off;
case DrawQuad::Material::kTiledContent:
return TileDrawQuad::MaterialCast(quad)->force_anti_aliasing_off;
+ case DrawQuad::Material::kYuvVideoContent:
+ case DrawQuad::Material::kStreamVideoContent:
+ case DrawQuad::Material::kTextureContent:
+ // This is done to match the behaviour of GLRenderer and we can revisit it
+ // later.
+ return true;
default:
return false;
}
@@ -487,27 +492,28 @@ SkiaRenderer::ScopedSkImageBuilder::ScopedSkImageBuilder(
if (!resource_id)
return;
auto* resource_provider = skia_renderer->resource_provider_;
- if (!skia_renderer->is_using_ddl() ||
- !IsTextureResource(resource_provider, resource_id)) {
+ DCHECK(IsTextureResource(resource_provider, resource_id));
+ if (!skia_renderer->is_using_ddl()) {
// TODO(penghuang): remove this code when DDL is used everywhere.
lock_.emplace(resource_provider, resource_id, alpha_type, origin);
sk_image_ = lock_->sk_image();
} else {
- // Look up the image from promise_images_by resource_id and return the
- // reference. If the resource_id doesn't exist, this statement will
- // allocate it and return reference of it, and the reference will be used
- // to store the new created image later.
- auto& image = skia_renderer->promise_images_[resource_id];
- if (!image) {
- auto metadata =
- skia_renderer->lock_set_for_external_use_->LockResource(resource_id);
- metadata.alpha_type = alpha_type;
- metadata.origin = origin;
- metadata.ycbcr_info = ycbcr_info;
- image = skia_renderer->skia_output_surface_->MakePromiseSkImage(metadata);
- LOG_IF(ERROR, !image) << "Failed to create the promise sk image.";
+ auto* image_context =
+ skia_renderer->lock_set_for_external_use_->LockResource(resource_id);
+ // |ImageContext::image| provides thread safety: (a) this ImageContext is
+ // only accessed by GPU thread after |image| is set and (b) the fields of
+ // ImageContext that are accessed by both compositor and GPU thread are no
+ // longer modified after |image| is set.
+ if (!image_context->has_image()) {
+ image_context->set_alpha_type(alpha_type);
+ image_context->set_origin(origin);
+ if (ycbcr_info)
+ image_context->set_ycbcr_info(*ycbcr_info);
}
- sk_image_ = image.get();
+ skia_renderer->skia_output_surface_->MakePromiseSkImage(image_context);
+ LOG_IF(ERROR, !image_context->has_image())
+ << "Failed to create the promise sk image.";
+ sk_image_ = image_context->image().get();
}
}
@@ -528,59 +534,52 @@ class SkiaRenderer::ScopedYUVSkImageBuilder {
IsTextureResource(skia_renderer->resource_provider_,
quad->a_plane_resource_id()));
- YUVIds ids(quad->y_plane_resource_id(), quad->u_plane_resource_id(),
- quad->v_plane_resource_id(), quad->a_plane_resource_id());
- auto& image = skia_renderer->yuv_promise_images_[std::move(ids)];
-
- if (!image) {
- SkYUVColorSpace yuv_color_space;
- if (has_color_conversion_filter) {
- yuv_color_space = kIdentity_SkYUVColorSpace;
- } else {
- yuv_color_space = kRec601_SkYUVColorSpace;
- quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space);
- }
-
- const bool is_i420 =
- quad->u_plane_resource_id() != quad->v_plane_resource_id();
- const bool has_alpha = quad->a_plane_resource_id() != kInvalidResourceId;
- const size_t number_of_textures = (is_i420 ? 3 : 2) + (has_alpha ? 1 : 0);
- std::vector<ResourceMetadata> metadatas;
- metadatas.reserve(number_of_textures);
- auto y_metadata = skia_renderer->lock_set_for_external_use_->LockResource(
- quad->y_plane_resource_id());
- metadatas.push_back(std::move(y_metadata));
- auto u_metadata = skia_renderer->lock_set_for_external_use_->LockResource(
- quad->u_plane_resource_id());
- metadatas.push_back(std::move(u_metadata));
- if (is_i420) {
- auto v_metadata =
- skia_renderer->lock_set_for_external_use_->LockResource(
- quad->v_plane_resource_id());
- metadatas.push_back(std::move(v_metadata));
- }
+ SkYUVColorSpace yuv_color_space;
+ if (has_color_conversion_filter) {
+ yuv_color_space = kIdentity_SkYUVColorSpace;
+ } else {
+ yuv_color_space = kRec601_SkYUVColorSpace;
+ quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space);
+ }
- if (has_alpha) {
- auto a_metadata =
- skia_renderer->lock_set_for_external_use_->LockResource(
- quad->a_plane_resource_id());
- metadatas.push_back(std::move(a_metadata));
- }
+ const bool is_i420 =
+ quad->u_plane_resource_id() != quad->v_plane_resource_id();
+ const bool has_alpha = quad->a_plane_resource_id() != kInvalidResourceId;
+ const size_t number_of_textures = (is_i420 ? 3 : 2) + (has_alpha ? 1 : 0);
+ std::vector<ExternalUseClient::ImageContext*> contexts;
+ contexts.reserve(number_of_textures);
+ // Skia API ignores the color space information on the individual planes.
+ // Dropping them here avoids some LOG spam.
+ auto* y_context = skia_renderer->lock_set_for_external_use_->LockResource(
+ quad->y_plane_resource_id(), true /* is_video_plane */);
+ contexts.push_back(std::move(y_context));
+ auto* u_context = skia_renderer->lock_set_for_external_use_->LockResource(
+ quad->u_plane_resource_id(), true /* is_video_plane */);
+ contexts.push_back(std::move(u_context));
+ if (is_i420) {
+ auto* v_context = skia_renderer->lock_set_for_external_use_->LockResource(
+ quad->v_plane_resource_id(), true /* is_video_plane */);
+ contexts.push_back(std::move(v_context));
+ }
- image = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV(
- std::move(metadatas), yuv_color_space, dst_color_space, has_alpha);
- LOG_IF(ERROR, !image) << "Failed to create the promise sk yuva image.";
+ if (has_alpha) {
+ auto* a_context = skia_renderer->lock_set_for_external_use_->LockResource(
+ quad->a_plane_resource_id(), true /* is_video_plane */);
+ contexts.push_back(std::move(a_context));
}
- sk_image_ = image.get();
+
+ sk_image_ = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV(
+ std::move(contexts), yuv_color_space, dst_color_space, has_alpha);
+ LOG_IF(ERROR, !sk_image_) << "Failed to create the promise sk yuva image.";
}
~ScopedYUVSkImageBuilder() = default;
- const SkImage* sk_image() const { return sk_image_; }
+ const SkImage* sk_image() const { return sk_image_.get(); }
private:
std::unique_ptr<DisplayResourceProvider::ScopedReadLockSkImage> lock_;
- SkImage* sk_image_ = nullptr;
+ sk_sp<SkImage> sk_image_;
DISALLOW_COPY_AND_ASSIGN(ScopedYUVSkImageBuilder);
};
@@ -615,17 +614,23 @@ SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
SkiaRenderer::~SkiaRenderer() = default;
-class FrameResourceFence : public ResourceFence {
+class SkiaRenderer::FrameResourceFence : public ResourceFence {
public:
FrameResourceFence() = default;
// ResourceFence implementation.
- void Set() override { event_.Signal(); }
+ void Set() override { set_ = true; }
bool HasPassed() override { return event_.IsSignaled(); }
+ bool WasSet() { return set_; }
+ void Signal() { event_.Signal(); }
+
private:
~FrameResourceFence() override = default;
+ // Accessed only from compositor thread.
+ bool set_ = false;
+
base::WaitableEvent event_;
DISALLOW_COPY_AND_ASSIGN(FrameResourceFence);
@@ -656,8 +661,8 @@ void SkiaRenderer::BeginDrawingFrame() {
read_lock_fence = sync_queries_->StartNewFrame();
current_frame_resource_fence_ = nullptr;
} else {
- read_lock_fence = base::MakeRefCounted<FrameResourceFence>();
- current_frame_resource_fence_ = read_lock_fence;
+ current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>();
+ read_lock_fence = current_frame_resource_fence_;
}
resource_provider_->SetReadLockFence(read_lock_fence.get());
@@ -680,6 +685,7 @@ void SkiaRenderer::FinishDrawingFrame() {
if (sync_queries_) {
sync_queries_->EndCurrentFrame();
}
+ current_frame_resource_fence_ = nullptr;
current_canvas_ = nullptr;
current_surface_ = nullptr;
@@ -688,8 +694,10 @@ void SkiaRenderer::FinishDrawingFrame() {
if (use_swap_with_bounds_)
swap_content_bounds_ = current_frame()->root_content_bounds;
- skia_output_surface_->ScheduleOverlays(
- std::move(current_frame()->overlay_list));
+ // TODO(weiliangc): Remove this once OverlayProcessor schedules overlays.
+ if (current_frame()->output_surface_plane)
+ skia_output_surface_->ScheduleOutputSurfaceAsOverlay(
+ current_frame()->output_surface_plane.value());
}
void SkiaRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
@@ -1509,8 +1517,9 @@ sk_sp<SkColorFilter> SkiaRenderer::GetColorFilter(const gfx::ColorSpace& src,
const gfx::ColorSpace& dst,
float resource_offset,
float resource_multiplier) {
- sk_sp<SkColorFilter>& color_filter = color_filter_cache_[dst][src];
- if (!color_filter) {
+ std::unique_ptr<SkRuntimeColorFilterFactory>& factory =
+ color_filter_cache_[dst][src];
+ if (!factory) {
std::unique_ptr<gfx::ColorTransform> transform =
gfx::ColorTransform::NewColorTransform(
src, dst, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
@@ -1519,11 +1528,6 @@ sk_sp<SkColorFilter> SkiaRenderer::GetColorFilter(const gfx::ColorSpace& src,
if (!transform->CanGetShaderSource())
return nullptr;
- YUVInput input;
- input.offset = resource_offset;
- input.multiplier = resource_multiplier;
- sk_sp<SkData> data = SkData::MakeWithCopy(&input, sizeof(input));
-
const char* hdr = R"(
layout(ctype=float) in uniform half offset;
layout(ctype=float) in uniform half multiplier;
@@ -1544,11 +1548,16 @@ void main(inout half4 color) {
std::string shader = hdr + transform->GetSkShaderSource() + ftr;
- color_filter =
- SkRuntimeColorFilterFactory(SkString(shader.c_str(), shader.size()))
- .make(data);
+ factory.reset(new SkRuntimeColorFilterFactory(
+ SkString(shader.c_str(), shader.size())));
}
- return color_filter;
+
+ YUVInput input;
+ input.offset = resource_offset;
+ input.multiplier = resource_multiplier;
+ sk_sp<SkData> data = SkData::MakeWithCopy(&input, sizeof(input));
+
+ return factory->make(std::move(data));
}
SkiaRenderer::DrawRPDQParams SkiaRenderer::CalculateRPDQParams(
@@ -1558,9 +1567,7 @@ SkiaRenderer::DrawRPDQParams SkiaRenderer::CalculateRPDQParams(
DrawRPDQParams rpdq_params(params->visible_rect);
// Prepare mask.
- ResourceId mask_resource_id = quad->mask_applies_to_backdrop
- ? kInvalidResourceId
- : quad->mask_resource_id();
+ ResourceId mask_resource_id = quad->mask_resource_id();
ScopedSkImageBuilder mask_image_builder(this, mask_resource_id);
const SkImage* mask_image = mask_image_builder.sk_image();
DCHECK_EQ(!!mask_resource_id, !!mask_image);
@@ -1764,9 +1771,13 @@ void SkiaRenderer::DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
FlushBatchedQuads();
SkPaint paint = params->paint();
- if (!rpdq_params.image_filter && !rpdq_params.backdrop_filter) {
- // When there are no filters, there is no need to save a layer, but we do
- // have to incorporate the mask directly into the paint then.
+ paint.setImageFilter(rpdq_params.image_filter);
+
+ // When there's no backdrop filter, there's no need to use an explicit layer.
+ // SkCanvas will do so implicitly (if needed) when processing the regular
+ // filter.
+ if (!rpdq_params.backdrop_filter) {
+ // Since there is no layer, use the mask on the paint itself
if (rpdq_params.mask_image) {
paint.setMaskFilter(
SkShaderMaskFilter::Make(rpdq_params.mask_image->makeShader(
@@ -1806,11 +1817,6 @@ void SkiaRenderer::DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
current_canvas_->clipRect(gfx::RectToSkRect(rpdq_params.filter_bounds),
paint.isAntiAlias());
- // Add the image filter to the restoration paint.
- if (rpdq_params.image_filter) {
- paint.setImageFilter(rpdq_params.image_filter);
- }
-
// Save the layer with the restoration paint (which holds the final image
// filters, the backdrop filters, and mask image. If we have a backdrop filter
// the layer will blended with src-over, and the rpdq's blend mode will apply
@@ -1829,15 +1835,26 @@ void SkiaRenderer::DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
rpdq_params.mask_image.get(),
&rpdq_params.mask_to_quad_matrix, layer_flags));
- if (rpdq_params.backdrop_filter_bounds.has_value()) {
+ if (rpdq_params.backdrop_filter_bounds.has_value() ||
+ params->draw_region.has_value()) {
// The initial contents of saved layer is all of the background within
// |bounds| filtered by the backdrop filters. Must set all pixels outside
// of the border rrect to transparent black. This cannot simply be a clip
// when the layer is restored since this rrect should not clip the rest
- // of the render pass content.
+ // of the render pass content. The same logic applies when this draw is
+ // rendering a split quadrilateral from the RPDQ. We don't want to keep the
+ // backdrop filtered contents that are outside of the quad being rendered.
current_canvas_->save();
- current_canvas_->clipRRect(SkRRect(*rpdq_params.backdrop_filter_bounds),
- SkClipOp::kDifference, paint.isAntiAlias());
+ if (rpdq_params.backdrop_filter_bounds.has_value()) {
+ current_canvas_->clipRRect(SkRRect(*rpdq_params.backdrop_filter_bounds),
+ SkClipOp::kDifference, paint.isAntiAlias());
+ }
+ if (params->draw_region.has_value()) {
+ SkPath clipPath;
+ clipPath.addPoly(params->draw_region->points, 4, true /* close */);
+ current_canvas_->clipPath(clipPath, SkClipOp::kDifference,
+ paint.isAntiAlias());
+ }
current_canvas_->clear(SK_ColorTRANSPARENT);
current_canvas_->restore();
}
@@ -1857,7 +1874,6 @@ void SkiaRenderer::DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
params->draw_region.has_value() ? params->draw_region->points : nullptr;
current_canvas_->experimental_DrawEdgeAAImageSet(
&entry, 1, draw_region, nullptr, &content_paint, constraint);
-
// And the saved layer will be auto-restored when |acr| is destructed
}
@@ -1904,21 +1920,17 @@ void SkiaRenderer::FinishDrawingQuadList() {
FlushBatchedQuads();
switch (draw_mode_) {
case DrawMode::DDL: {
- // Skia doesn't support releasing the last promise image ref on the DDL
- // recordering thread. So we clear all cached promise images before
- // SubmitPaint to the GPU thread.
- promise_images_.clear();
- yuv_promise_images_.clear();
-
base::OnceClosure on_finished_callback;
// Signal |current_frame_resource_fence_| when the root render pass is
// finished.
if (current_frame_resource_fence_ &&
+ current_frame_resource_fence_->WasSet() &&
current_frame()->current_render_pass ==
current_frame()->root_render_pass) {
- on_finished_callback = base::BindOnce(
- &ResourceFence::Set, std::move(current_frame_resource_fence_));
+ on_finished_callback =
+ base::BindOnce(&FrameResourceFence::Signal,
+ std::move(current_frame_resource_fence_));
}
gpu::SyncToken sync_token =
skia_output_surface_->SubmitPaint(std::move(on_finished_callback));
diff --git a/chromium/components/viz/service/display/skia_renderer.h b/chromium/components/viz/service/display/skia_renderer.h
index f7134596734..63f24356031 100644
--- a/chromium/components/viz/service/display/skia_renderer.h
+++ b/chromium/components/viz/service/display/skia_renderer.h
@@ -21,6 +21,7 @@
class SkColorFilter;
class SkNWayCanvas;
class SkPictureRecorder;
+class SkRuntimeColorFilterFactory;
namespace gpu {
struct Capabilities;
@@ -204,7 +205,8 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
SkCanvas* root_canvas_ = nullptr;
SkCanvas* current_canvas_ = nullptr;
SkSurface* current_surface_ = nullptr;
- scoped_refptr<ResourceFence> current_frame_resource_fence_;
+ class FrameResourceFence;
+ scoped_refptr<FrameResourceFence> current_frame_resource_fence_;
bool disable_picture_quad_image_filtering_ = false;
bool is_scissor_enabled_ = false;
@@ -251,14 +253,6 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
base::Optional<DisplayResourceProvider::LockSetForExternalUse>
lock_set_for_external_use_;
- // Promise images created from resources used in the current frame. This map
- // will be cleared when the frame is done and before all resources in
- // |lock_set_for_external_use_| are unlocked on the compositor thread.
- // It is only used with DDL.
- base::flat_map<ResourceId, sk_sp<SkImage>> promise_images_;
- using YUVIds = std::tuple<ResourceId, ResourceId, ResourceId, ResourceId>;
- base::flat_map<YUVIds, sk_sp<SkImage>> yuv_promise_images_;
-
// Specific for SkPRecord.
std::unique_ptr<SkPictureRecorder> root_recorder_;
sk_sp<SkPicture> root_picture_;
@@ -267,7 +261,9 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
ContextProvider* context_provider_ = nullptr;
base::Optional<SyncQueryCollection> sync_queries_;
- std::map<gfx::ColorSpace, std::map<gfx::ColorSpace, sk_sp<SkColorFilter>>>
+ std::map<
+ gfx::ColorSpace,
+ std::map<gfx::ColorSpace, std::unique_ptr<SkRuntimeColorFilterFactory>>>
color_filter_cache_;
DISALLOW_COPY_AND_ASSIGN(SkiaRenderer);
diff --git a/chromium/components/viz/service/display/surface_aggregator.cc b/chromium/components/viz/service/display/surface_aggregator.cc
index 0dd3f66eb63..fc85101c475 100644
--- a/chromium/components/viz/service/display/surface_aggregator.cc
+++ b/chromium/components/viz/service/display/surface_aggregator.cc
@@ -18,7 +18,9 @@
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/math_util.h"
+#include "components/viz/common/display/de_jelly.h"
#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/shared_quad_state.h"
@@ -32,6 +34,8 @@
#include "components/viz/service/surfaces/surface_allocation_group.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/surfaces/surface_manager.h"
+#include "ui/gfx/geometry/angle_conversions.h"
+#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/overlay_transform_utils.h"
namespace viz {
@@ -74,9 +78,88 @@ bool CalculateQuadSpaceDamageRect(
} // namespace
-std::string SurfaceAggregator::ClipData::ToString() const {
- return is_clipped ? "clip " + rect.ToString() : "no clip";
-}
+struct SurfaceAggregator::ClipData {
+ std::string ToString() const {
+ return is_clipped ? "clip " + rect.ToString() : "no clip";
+ }
+
+ bool is_clipped = false;
+ gfx::Rect rect;
+};
+
+struct SurfaceAggregator::PrewalkResult {
+ // This is the set of Surfaces that were referenced by another Surface, but
+ // not included in a SurfaceDrawQuad.
+ base::flat_set<SurfaceId> undrawn_surfaces;
+ bool may_contain_video = false;
+};
+
+struct SurfaceAggregator::RoundedCornerInfo {
+ RoundedCornerInfo() = default;
+
+ // |target_transform| is the transform that maps |bounds_arg| from its current
+ // space into the desired target space. It must be a scale+translation matrix.
+ RoundedCornerInfo(const gfx::RRectF& bounds_arg,
+ bool is_fast_rounded_corner,
+ const gfx::Transform target_transform)
+ : bounds(bounds_arg), is_fast_rounded_corner(is_fast_rounded_corner) {
+ if (bounds.IsEmpty())
+ return;
+ DCHECK(target_transform.Preserves2dAxisAlignment());
+ SkMatrix matrix = target_transform.matrix();
+ bounds.Scale(matrix.getScaleX(), matrix.getScaleY());
+ bounds.Offset(target_transform.To2dTranslation());
+ }
+
+ gfx::RRectF bounds;
+ bool is_fast_rounded_corner;
+};
+
+struct SurfaceAggregator::ChildSurfaceInfo {
+ ChildSurfaceInfo(RenderPassId parent_pass_id,
+ const gfx::Transform& quad_to_target_transform,
+ const gfx::Rect& quad_rect,
+ bool stretch_content_to_fill_bounds,
+ bool is_clipped,
+ const gfx::Rect& clip_rect)
+ : parent_pass_id(parent_pass_id),
+ quad_to_target_transform(quad_to_target_transform),
+ quad_rect(quad_rect),
+ stretch_content_to_fill_bounds(stretch_content_to_fill_bounds),
+ is_clipped(is_clipped),
+ clip_rect(clip_rect) {
+ // In most cases there would be one or two different transforms to root
+ // target. Reserve two elements to avoid unnecessary copies.
+ transforms_to_root_target.reserve(2);
+ }
+
+ RenderPassId parent_pass_id;
+ gfx::Transform quad_to_target_transform;
+ gfx::Rect quad_rect;
+ bool stretch_content_to_fill_bounds;
+ bool is_clipped;
+ gfx::Rect clip_rect;
+ bool has_moved_pixels = false;
+ std::vector<gfx::Transform> transforms_to_root_target;
+};
+
+struct SurfaceAggregator::RenderPassMapEntry {
+ RenderPassMapEntry(RenderPass* render_pass,
+ bool has_pixel_moving_backdrop_filter)
+ : render_pass(render_pass),
+ has_pixel_moving_backdrop_filter(has_pixel_moving_backdrop_filter) {}
+
+ // Make this move-only.
+ RenderPassMapEntry(RenderPassMapEntry&&) = default;
+ RenderPassMapEntry(const RenderPassMapEntry&) = delete;
+ RenderPassMapEntry& operator=(RenderPassMapEntry&&) = default;
+ RenderPassMapEntry& operator=(const RenderPassMapEntry&) = delete;
+
+ RenderPass* render_pass;
+ bool has_pixel_moving_backdrop_filter;
+
+ bool is_visited = false;
+};
SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
DisplayResourceProvider* provider,
@@ -86,8 +169,8 @@ SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
provider_(provider),
next_render_pass_id_(1),
aggregate_only_damaged_(aggregate_only_damaged),
- needs_surface_occluding_damage_rect_(
- needs_surface_occluding_damage_rect) {
+ needs_surface_occluding_damage_rect_(needs_surface_occluding_damage_rect),
+ de_jelly_enabled_(DeJellyEnabled()) {
DCHECK(manager_);
}
@@ -98,9 +181,31 @@ SurfaceAggregator::~SurfaceAggregator() {
ProcessAddedAndRemovedSurfaces();
}
-SurfaceAggregator::PrewalkResult::PrewalkResult() {}
-
-SurfaceAggregator::PrewalkResult::~PrewalkResult() {}
+// static
+base::flat_map<RenderPassId, SurfaceAggregator::RenderPassMapEntry>
+SurfaceAggregator::GenerateRenderPassMap(const RenderPassList& render_pass_list,
+ bool is_root_surface) {
+ const auto* root_pass_in_root_surface =
+ is_root_surface ? render_pass_list.back().get() : nullptr;
+ // This data is created once and typically small or empty. Collect all items
+ // and pass to a flat_map to sort once.
+ std::vector<std::pair<RenderPassId, RenderPassMapEntry>> render_pass_data;
+ for (const auto& render_pass : render_pass_list) {
+ bool has_pixel_moving_backdrop_filter =
+ render_pass->backdrop_filters.HasFilterThatMovesPixels();
+ if (has_pixel_moving_backdrop_filter) {
+ DCHECK_NE(render_pass.get(), root_pass_in_root_surface)
+ << "The root render pass on the root surface can not have backdrop "
+ "affecting filters";
+ }
+ render_pass_data.emplace_back(
+ std::piecewise_construct, std::forward_as_tuple(render_pass->id),
+ std::forward_as_tuple(render_pass.get(),
+ has_pixel_moving_backdrop_filter));
+ }
+ return base::flat_map<RenderPassId, RenderPassMapEntry>(
+ std::move(render_pass_data));
+}
// Create a clip rect for an aggregated quad from the original clip rect and
// the clip rect from the surface it's on.
@@ -341,7 +446,7 @@ void SurfaceAggregator::HandleSurfaceQuad(
surface_quad->stretch_content_to_fill_bounds, dest_pass,
ignore_undamaged, damage_rect_in_quad_space,
damage_rect_in_quad_space_valid, rounded_corner_info,
- surface_quad->is_reflection);
+ surface_quad->is_reflection, surface_quad->allow_merge);
}
void SurfaceAggregator::EmitSurfaceContent(
@@ -358,7 +463,8 @@ void SurfaceAggregator::EmitSurfaceContent(
gfx::Rect* damage_rect_in_quad_space,
bool* damage_rect_in_quad_space_valid,
const RoundedCornerInfo& rounded_corner_info,
- bool is_reflection) {
+ bool is_reflection,
+ bool allow_merge) {
// If this surface's id is already in our referenced set then it creates
// a cycle in the graph and should be dropped.
SurfaceId surface_id = surface->surface_id();
@@ -435,11 +541,14 @@ void SurfaceAggregator::EmitSurfaceContent(
is_reflection &&
!scaled_quad_to_target_transform.IsIdentityOrTranslation();
+ // We cannot merge passes if de-jelly is being applied, as we must have a
+ // renderpass to skew.
bool merge_pass =
- !reflected_and_scaled &&
+ allow_merge && !reflected_and_scaled &&
base::IsApproximatelyEqual(source_sqs->opacity, 1.f, kOpacityEpsilon) &&
copy_requests.empty() && combined_transform.Preserves2dAxisAlignment() &&
- CanMergeRoundedCorner(rounded_corner_info, *render_pass_list.back());
+ CanMergeRoundedCorner(rounded_corner_info, *render_pass_list.back()) &&
+ source_sqs->de_jelly_delta_y == 0;
gfx::Rect occluding_damage_rect;
bool occluding_damage_rect_valid = ProcessSurfaceOccludingDamage(
@@ -486,9 +595,9 @@ void SurfaceAggregator::EmitSurfaceContent(
CopyQuadsToPass(source.quad_list, source.shared_quad_state_list,
surface->GetActiveFrame().device_scale_factor(),
- child_to_parent_map, gfx::Transform(), ClipData(),
- copy_pass.get(), surface_id, RoundedCornerInfo(),
- occluding_damage_rect, occluding_damage_rect_valid);
+ child_to_parent_map, gfx::Transform(), {}, copy_pass.get(),
+ surface_id, RoundedCornerInfo(), occluding_damage_rect,
+ occluding_damage_rect_valid);
// If the render pass has copy requests, or should be cached, or has
// moving-pixel filters, or in a moving-pixel surface, we should damage the
@@ -527,9 +636,9 @@ void SurfaceAggregator::EmitSurfaceContent(
// Intersect the transformed visible rect and the clip rect to create a
// smaller cliprect for the quad.
- ClipData surface_quad_clip_rect(
+ ClipData surface_quad_clip_rect = {
true, cc::MathUtil::MapEnclosingClippedRect(
- source_sqs->quad_to_target_transform, source_visible_rect));
+ source_sqs->quad_to_target_transform, source_visible_rect)};
if (source_sqs->is_clipped) {
surface_quad_clip_rect.rect.Intersect(source_sqs->clip_rect);
}
@@ -561,18 +670,44 @@ void SurfaceAggregator::EmitSurfaceContent(
gfx::ScaleToEnclosingRect(source_visible_rect, layer_to_content_scale_x,
layer_to_content_scale_y));
- auto* quad = dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
- RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
- quad->SetNew(shared_quad_state, scaled_rect, scaled_visible_rect,
- remapped_pass_id, 0, gfx::RectF(), gfx::Size(),
- /*mask_applies_to_backdrop=*/false, gfx::Vector2dF(),
- gfx::PointF(), gfx::RectF(scaled_rect),
- /*force_anti_aliasing_off=*/false,
- /* backdrop_filter_quality*/ 1.0f);
+ // TODO(ericrk): Apply this path everywhere (not just de-jelly).
+ // crbug.com/1016677
+ if (de_jelly_enabled_) {
+ // Due to viewport clipping, |last_pass|'s |output_rect| may be smaller
+ // than |source_rect|'s projection into content space. We always use
+ // |output_rect| to avoid sampling outside of RenderPass output.
+ gfx::Rect quad_rect = last_pass.output_rect;
+
+ // We can't produce content outside of |output_rect|, so clip the visible
+ // rect if necessary.
+ scaled_visible_rect.Intersect(quad_rect);
+
+ // |tex_coord_rect| indicates the area of the source texture to sample
+ // from. This is always the size of |quad_rect| which represents the full
+ // render pass |output_rect|.
+ gfx::RectF tex_coord_rect = gfx::RectF(gfx::SizeF(quad_rect.size()));
+
+ auto* quad = dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
+ RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
+ quad->SetNew(shared_quad_state, quad_rect, scaled_visible_rect,
+ remapped_pass_id, 0, gfx::RectF(), gfx::Size(),
+ /*mask_applies_to_backdrop=*/false, gfx::Vector2dF(),
+ gfx::PointF(), tex_coord_rect,
+ /*force_anti_aliasing_off=*/false,
+ /* backdrop_filter_quality*/ 1.0f);
+ } else {
+ auto* quad = dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
+ RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
+ quad->SetNew(shared_quad_state, scaled_rect, scaled_visible_rect,
+ remapped_pass_id, 0, gfx::RectF(), gfx::Size(),
+ /*mask_applies_to_backdrop=*/false, gfx::Vector2dF(),
+ gfx::PointF(), gfx::RectF(scaled_rect),
+ /*force_anti_aliasing_off=*/false,
+ /* backdrop_filter_quality*/ 1.0f);
+ }
}
- // Need to re-query since referenced_surfaces_ iterators are not stable.
- referenced_surfaces_.erase(referenced_surfaces_.find(surface_id));
+ referenced_surfaces_.erase(surface_id);
}
void SurfaceAggregator::EmitDefaultBackgroundColorQuad(
@@ -771,20 +906,6 @@ SharedQuadState* SurfaceAggregator::CopySharedQuadState(
occluding_damage_rect_valid);
}
-SurfaceAggregator::RoundedCornerInfo::RoundedCornerInfo(
- const gfx::RRectF& bounds_arg,
- bool is_fast_rounded_corner_arg,
- const gfx::Transform target_transform) {
- is_fast_rounded_corner = is_fast_rounded_corner_arg;
- if (bounds_arg.IsEmpty())
- return;
- DCHECK(target_transform.Preserves2dAxisAlignment());
- bounds = bounds_arg;
- SkMatrix matrix = target_transform.matrix();
- bounds.Scale(matrix.getScaleX(), matrix.getScaleY());
- bounds.Offset(target_transform.To2dTranslation());
-}
-
SharedQuadState* SurfaceAggregator::CopyAndScaleSharedQuadState(
const SharedQuadState* source_sqs,
const gfx::Transform& scaled_quad_to_target_transform,
@@ -798,7 +919,7 @@ SharedQuadState* SurfaceAggregator::CopyAndScaleSharedQuadState(
bool occluding_damage_rect_valid) {
auto* shared_quad_state = dest_render_pass->CreateAndAppendSharedQuadState();
ClipData new_clip_rect = CalculateClipRect(
- clip_rect, ClipData(source_sqs->is_clipped, source_sqs->clip_rect),
+ clip_rect, {source_sqs->is_clipped, source_sqs->clip_rect},
target_transform);
// target_transform contains any transformation that may exist
@@ -820,6 +941,7 @@ SharedQuadState* SurfaceAggregator::CopyAndScaleSharedQuadState(
if (occluding_damage_rect_valid) {
shared_quad_state->occluding_damage_rect = occluding_damage_rect;
}
+ shared_quad_state->de_jelly_delta_y = source_sqs->de_jelly_delta_y;
return shared_quad_state;
}
@@ -867,7 +989,7 @@ void SurfaceAggregator::CopyQuadsToPass(
// Both cannot be set at once. If this happens then a surface is being
// merged when it should not.
DCHECK(quad->shared_quad_state->rounded_corner_bounds.IsEmpty() ||
- parent_rounded_corner_info.IsEmpty());
+ parent_rounded_corner_info.bounds.IsEmpty());
if (quad->material == DrawQuad::Material::kSurfaceContent) {
const auto* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
@@ -878,7 +1000,7 @@ void SurfaceAggregator::CopyQuadsToPass(
if (!surface_quad->surface_range.end().is_valid())
continue;
- if (parent_rounded_corner_info.IsEmpty()) {
+ if (parent_rounded_corner_info.bounds.IsEmpty()) {
new_rounded_corner_info = RoundedCornerInfo(
quad->shared_quad_state->rounded_corner_bounds,
quad->shared_quad_state->is_fast_rounded_corner, target_transform);
@@ -890,17 +1012,25 @@ void SurfaceAggregator::CopyQuadsToPass(
&damage_rect_in_quad_space_valid, new_rounded_corner_info);
} else {
if (quad->shared_quad_state != last_copied_source_shared_quad_state) {
- if (parent_rounded_corner_info.IsEmpty()) {
+ if (parent_rounded_corner_info.bounds.IsEmpty()) {
new_rounded_corner_info =
RoundedCornerInfo(quad->shared_quad_state->rounded_corner_bounds,
quad->shared_quad_state->is_fast_rounded_corner,
target_transform);
}
- const SharedQuadState* dest_shared_quad_state = CopySharedQuadState(
+ SharedQuadState* dest_shared_quad_state = CopySharedQuadState(
quad->shared_quad_state, target_transform, clip_rect, dest_pass,
new_rounded_corner_info, occluding_damage_rect,
occluding_damage_rect_valid);
+ if (de_jelly_enabled_) {
+ // If a surface is being drawn for a second time, clear our
+ // |de_jelly_delta_y|, as de-jelly is only needed the first time
+ // a surface draws.
+ if (!new_surfaces_.count(surface_id))
+ dest_shared_quad_state->de_jelly_delta_y = 0.0f;
+ }
+
last_copied_source_shared_quad_state = quad->shared_quad_state;
if (ignore_undamaged) {
damage_rect_in_quad_space_valid = CalculateQuadSpaceDamageRect(
@@ -1039,7 +1169,7 @@ void SurfaceAggregator::CopyPasses(const CompositorFrame& frame,
frame.device_scale_factor(), child_to_parent_map,
apply_surface_transform_to_root_pass ? surface_transform
: gfx::Transform(),
- ClipData(), copy_pass.get(), surface->surface_id(),
+ {}, copy_pass.get(), surface->surface_id(),
RoundedCornerInfo(), occluding_damage_rect,
occluding_damage_rect_valid);
@@ -1075,6 +1205,95 @@ void SurfaceAggregator::ProcessAddedAndRemovedSurfaces() {
}
}
+void SurfaceAggregator::FindChildSurfaces(
+ SurfaceId surface_id,
+ base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
+ RenderPassMapEntry* current_pass_entry,
+ const gfx::Transform& transform_to_root_target,
+ base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces,
+ gfx::Rect* pixel_moving_backdrop_filters_rect) {
+ if (current_pass_entry->is_visited) {
+ // This means that this render pass is an ancestor of itself. This is not
+ // supported. Stop processing the render pass again.
+ return;
+ }
+ base::AutoReset<bool> reset_is_visited(&current_pass_entry->is_visited, true);
+ RenderPass* render_pass = current_pass_entry->render_pass;
+ if (current_pass_entry->has_pixel_moving_backdrop_filter) {
+ // If the render pass has a backdrop filter that moves pixels, its entire
+ // bounds, with proper transform applied, should be added to the damage
+ // rect.
+ pixel_moving_backdrop_filters_rect->Union(
+ cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
+ render_pass->output_rect));
+ }
+ RenderPassId remapped_pass_id = RemapPassId(render_pass->id, surface_id);
+ bool has_pixel_moving_filter =
+ render_pass->filters.HasFilterThatMovesPixels();
+ if (has_pixel_moving_filter)
+ moved_pixel_passes_.insert(remapped_pass_id);
+ bool in_moved_pixel_pass =
+ has_pixel_moving_filter ||
+ base::Contains(moved_pixel_passes_, remapped_pass_id);
+ for (auto* quad : render_pass->quad_list) {
+ if (quad->material == DrawQuad::Material::kSurfaceContent) {
+ // A child surface has been found. Add necessary info from this surface to
+ // the set of child surfaces that can be used to update damage rect for
+ // the parent surface. If this child surface has been visited previously,
+ // we only need to update |has_moved_pixels| and add the transform
+ // corresponding to this visit; rest of the info would remain the same.
+ const auto* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
+ auto it = child_surfaces->find(surface_quad->surface_range);
+ if (it == child_surfaces->end()) {
+ auto insert_pair = child_surfaces->emplace(
+ std::piecewise_construct,
+ std::forward_as_tuple(surface_quad->surface_range),
+ std::forward_as_tuple(
+ remapped_pass_id,
+ surface_quad->shared_quad_state->quad_to_target_transform,
+ surface_quad->rect,
+ surface_quad->stretch_content_to_fill_bounds,
+ surface_quad->shared_quad_state->is_clipped,
+ surface_quad->shared_quad_state->clip_rect));
+ DCHECK(insert_pair.second);
+ it = insert_pair.first;
+ }
+ auto& child_surface_info = it->second;
+ if (in_moved_pixel_pass)
+ child_surface_info.has_moved_pixels = true;
+ child_surface_info.transforms_to_root_target.push_back(
+ transform_to_root_target);
+ } else if (quad->material == DrawQuad::Material::kRenderPass) {
+ // A child render pass has been found. Find its child surfaces
+ // recursively.
+ const auto* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad);
+ RenderPassId child_pass_id = render_pass_quad->render_pass_id;
+ RenderPassId remapped_child_pass_id =
+ RemapPassId(child_pass_id, surface_id);
+ if (in_moved_pixel_pass)
+ moved_pixel_passes_.insert(remapped_child_pass_id);
+ auto child_pass_it = render_pass_map->find(child_pass_id);
+ DCHECK(child_pass_it != render_pass_map->end());
+ RenderPassMapEntry& child_pass_entry = child_pass_it->second;
+ // TODO(crbug/1011042): Here, we used to set |in_moved_pixel_pass| to true
+ // if the child render pass has a pixel-moving backdrop filter. This
+ // behavior was added in r687426 to fix another problem, but caused a huge
+ // performance issue in some cases that enabled background blur, by
+ // expanding the damage rect unnecessarily to the entire screen
+ // (crbug/1008740). This is removed now, but a proper fix for the
+ // pixel-moving backdrop filter should be implemented.
+ render_pass_dependencies_[remapped_pass_id].insert(
+ remapped_child_pass_id);
+ FindChildSurfaces(
+ surface_id, render_pass_map, &child_pass_entry,
+ gfx::Transform(
+ transform_to_root_target,
+ render_pass_quad->shared_quad_state->quad_to_target_transform),
+ child_surfaces, pixel_moving_backdrop_filters_rect);
+ }
+ }
+}
+
// Walk the Surface tree from surface_id. Validate the resources of the current
// surface and its descendants, check if there are any copy requests, and
// return the combined damage rect.
@@ -1104,15 +1323,6 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
provider_->ReceiveFromChild(child_id, frame.resource_list);
}
- std::vector<ResourceId> referenced_resources;
- size_t reserve_size = frame.resource_list.size();
- referenced_resources.reserve(reserve_size);
-
- bool invalid_frame = false;
- std::unordered_map<ResourceId, ResourceId> empty_map;
- const auto& child_to_parent_map =
- provider_ ? provider_->GetChildToParentMap(child_id) : empty_map;
-
RenderPassId remapped_pass_id =
RemapPassId(frame.render_pass_list.back()->id, surface->surface_id());
if (in_moved_pixel_surface)
@@ -1122,117 +1332,34 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
const gfx::Transform& root_pass_transform =
IsRootSurface(surface) ? root_surface_transform_ : gfx::Transform();
- struct SurfaceInfo {
- SurfaceInfo(const SurfaceRange& surface_range,
- bool has_moved_pixels,
- RenderPassId parent_pass_id,
- const gfx::Transform& target_to_surface_transform,
- const gfx::Rect& quad_rect,
- bool stretch_content_to_fill_bounds,
- bool is_clipped,
- const gfx::Rect& clip_rect_in_root_target_space)
- : surface_range(surface_range),
- has_moved_pixels(has_moved_pixels),
- parent_pass_id(parent_pass_id),
- target_to_surface_transform(target_to_surface_transform),
- quad_rect(quad_rect),
- stretch_content_to_fill_bounds(stretch_content_to_fill_bounds),
- is_clipped(is_clipped),
- clip_rect_in_root_target_space(clip_rect_in_root_target_space) {}
- SurfaceRange surface_range;
- bool has_moved_pixels;
- RenderPassId parent_pass_id;
- gfx::Transform target_to_surface_transform;
- gfx::Rect quad_rect;
- bool stretch_content_to_fill_bounds;
- bool is_clipped;
- gfx::Rect clip_rect_in_root_target_space;
- };
- std::vector<SurfaceInfo> child_surfaces;
- gfx::Rect pixel_moving_backdrop_filters_rect;
- // This data is created once and typically small or empty. Collect all items
- // and pass to a flat_vector to sort once.
- std::vector<RenderPassId> pixel_moving_background_filter_passes_data;
- const auto* root_pass_in_root_surface =
- IsRootSurface(surface) ? frame.render_pass_list.back().get() : nullptr;
- for (const auto& render_pass : frame.render_pass_list) {
- if (render_pass->backdrop_filters.HasFilterThatMovesPixels()) {
- DCHECK_NE(render_pass.get(), root_pass_in_root_surface)
- << "The root render pass on the root surface can not have backdrop "
- "affecting filters";
-
- pixel_moving_background_filter_passes_data.push_back(
- RemapPassId(render_pass->id, surface->surface_id()));
+ base::flat_map<RenderPassId, RenderPassMapEntry> render_pass_map =
+ GenerateRenderPassMap(frame.render_pass_list, IsRootSurface(surface));
- gfx::Transform transform_to_root_target(
- root_pass_transform, render_pass->transform_to_root_target);
- pixel_moving_backdrop_filters_rect.Union(
- cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
- render_pass->output_rect));
- }
- }
- base::flat_set<RenderPassId> pixel_moving_background_filter_passes(
- std::move(pixel_moving_background_filter_passes_data),
- base::KEEP_FIRST_OF_DUPES);
+ auto root_pass_it = render_pass_map.find(frame.render_pass_list.back()->id);
+ DCHECK(root_pass_it != render_pass_map.end());
+ RenderPassMapEntry& root_pass_entry = root_pass_it->second;
+ base::flat_map<SurfaceRange, ChildSurfaceInfo> child_surfaces;
+ gfx::Rect pixel_moving_backdrop_filters_rect;
+ FindChildSurfaces(surface->surface_id(), &render_pass_map, &root_pass_entry,
+ root_pass_transform, &child_surfaces,
+ &pixel_moving_backdrop_filters_rect);
- for (const auto& render_pass : base::Reversed(frame.render_pass_list)) {
- RenderPassId remapped_pass_id =
- RemapPassId(render_pass->id, surface->surface_id());
- bool has_pixel_moving_filter =
- render_pass->filters.HasFilterThatMovesPixels();
- if (has_pixel_moving_filter)
- moved_pixel_passes_.insert(remapped_pass_id);
- bool in_moved_pixel_pass =
- has_pixel_moving_filter ||
- base::Contains(moved_pixel_passes_, remapped_pass_id);
-
- for (auto* quad : render_pass->quad_list) {
- if (quad->material == DrawQuad::Material::kSurfaceContent) {
- const auto* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
- gfx::Transform transform_to_root_target(
- root_pass_transform, render_pass->transform_to_root_target);
- gfx::Transform target_to_surface_transform(
- transform_to_root_target,
- surface_quad->shared_quad_state->quad_to_target_transform);
-
- gfx::Rect clip_rect_in_root_target_space;
- if (surface_quad->shared_quad_state->is_clipped) {
- // clip_rect is already in quad target space so only
- // transform_to_root_target needs to be applied
- clip_rect_in_root_target_space =
- cc::MathUtil::MapEnclosingClippedRect(
- transform_to_root_target,
- surface_quad->shared_quad_state->clip_rect);
- }
- child_surfaces.emplace_back(
- surface_quad->surface_range, in_moved_pixel_pass, remapped_pass_id,
- target_to_surface_transform, surface_quad->rect,
- surface_quad->stretch_content_to_fill_bounds,
- surface_quad->shared_quad_state->is_clipped,
- clip_rect_in_root_target_space);
- } else if (quad->material == DrawQuad::Material::kRenderPass) {
- const auto* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad);
- if (in_moved_pixel_pass) {
- moved_pixel_passes_.insert(RemapPassId(
- render_pass_quad->render_pass_id, surface->surface_id()));
- }
- if (pixel_moving_background_filter_passes.count(
- render_pass_quad->render_pass_id)) {
- in_moved_pixel_pass = true;
- }
- render_pass_dependencies_[remapped_pass_id].insert(RemapPassId(
- render_pass_quad->render_pass_id, surface->surface_id()));
- }
+ std::vector<ResourceId> referenced_resources;
+ referenced_resources.reserve(frame.resource_list.size());
- if (!provider_)
- continue;
- for (ResourceId resource_id : quad->resources) {
- if (!child_to_parent_map.count(resource_id)) {
- invalid_frame = true;
- break;
+ bool invalid_frame = false;
+ if (provider_) {
+ const auto& child_to_parent_map = provider_->GetChildToParentMap(child_id);
+ for (const auto& render_pass : base::Reversed(frame.render_pass_list)) {
+ for (auto* quad : render_pass->quad_list) {
+ for (ResourceId resource_id : quad->resources) {
+ if (!child_to_parent_map.count(resource_id)) {
+ invalid_frame = true;
+ break;
+ }
+ referenced_resources.push_back(resource_id);
}
- referenced_resources.push_back(resource_id);
}
}
}
@@ -1254,73 +1381,85 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
root_pass_transform, damage_rect);
// Avoid infinite recursion by adding current surface to
- // referenced_surfaces_.
+ // |referenced_surfaces_|.
referenced_surfaces_.insert(surface->surface_id());
- for (const auto& surface_info : child_surfaces) {
+ for (const auto& child_surface_info_pair : child_surfaces) {
+ auto& child_surface_range = child_surface_info_pair.first;
+ auto& child_surface_info = child_surface_info_pair.second;
// TODO(fsamuel): Consider caching this value somewhere so that
// HandleSurfaceQuad doesn't need to call it again.
Surface* child_surface =
- manager_->GetLatestInFlightSurface(surface_info.surface_range);
+ manager_->GetLatestInFlightSurface(child_surface_range);
// If the primary surface is not available then we assume the damage is
// the full size of the SurfaceDrawQuad because we might need to introduce
// gutter.
- gfx::Rect surface_damage;
+ gfx::Rect child_surface_damage;
if (!child_surface ||
- child_surface->surface_id() != surface_info.surface_range.end()) {
- surface_damage = surface_info.quad_rect;
+ child_surface->surface_id() != child_surface_range.end()) {
+ child_surface_damage = child_surface_info.quad_rect;
}
if (child_surface) {
- if (surface_info.stretch_content_to_fill_bounds) {
+ if (child_surface_info.stretch_content_to_fill_bounds) {
// Scale up the damage_quad generated by the child_surface to fit
// the containing quad_rect.
gfx::Rect child_rect =
- PrewalkTree(child_surface, surface_info.has_moved_pixels,
- surface_info.parent_pass_id, will_draw, result);
+ PrewalkTree(child_surface, child_surface_info.has_moved_pixels,
+ child_surface_info.parent_pass_id, will_draw, result);
if (child_surface->size_in_pixels().GetCheckedArea().ValueOrDefault(0) >
0) {
- float y_scale = static_cast<float>(surface_info.quad_rect.height()) /
- child_surface->size_in_pixels().height();
- float x_scale = static_cast<float>(surface_info.quad_rect.width()) /
- child_surface->size_in_pixels().width();
- surface_damage.Union(
+ float y_scale =
+ static_cast<float>(child_surface_info.quad_rect.height()) /
+ child_surface->size_in_pixels().height();
+ float x_scale =
+ static_cast<float>(child_surface_info.quad_rect.width()) /
+ child_surface->size_in_pixels().width();
+ child_surface_damage.Union(
gfx::ScaleToEnclosingRect(child_rect, x_scale, y_scale));
}
} else {
- surface_damage.Union(
- PrewalkTree(child_surface, surface_info.has_moved_pixels,
- surface_info.parent_pass_id, will_draw, result));
+ child_surface_damage.Union(
+ PrewalkTree(child_surface, child_surface_info.has_moved_pixels,
+ child_surface_info.parent_pass_id, will_draw, result));
}
}
- if (surface_damage.IsEmpty())
+ if (child_surface_damage.IsEmpty())
continue;
- if (surface_info.has_moved_pixels) {
+ if (child_surface_info.has_moved_pixels) {
// Areas outside the rect hit by target_to_surface_transform may be
// modified if there is a filter that moves pixels.
damage_rect = full_damage;
continue;
}
- gfx::Rect surface_damage_in_root_target_space =
- cc::MathUtil::MapEnclosingClippedRect(
- surface_info.target_to_surface_transform, surface_damage);
- if (surface_info.is_clipped) {
- surface_damage_in_root_target_space.Intersect(
- surface_info.clip_rect_in_root_target_space);
+ // Add the child surface damage rect to the parent surface damage rect. The
+ // child surface damage rect is first transformed to the parent surface
+ // coordinate space. There would be multiple transforms for a child surface
+ // if it is embedded multiple times which means its damage rect should be
+ // added multiple times.
+ for (const auto& transform_to_root_target :
+ child_surface_info.transforms_to_root_target) {
+ gfx::Transform target_to_surface_transform(
+ transform_to_root_target,
+ child_surface_info.quad_to_target_transform);
+ gfx::Rect child_surface_damage_in_root_target_space =
+ cc::MathUtil::MapEnclosingClippedRect(target_to_surface_transform,
+ child_surface_damage);
+ if (child_surface_info.is_clipped) {
+ gfx::Rect clip_rect_in_root_target_space =
+ cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
+ child_surface_info.clip_rect);
+ child_surface_damage_in_root_target_space.Intersect(
+ clip_rect_in_root_target_space);
+ }
+ damage_rect.Union(child_surface_damage_in_root_target_space);
}
- damage_rect.Union(surface_damage_in_root_target_space);
}
if (!damage_rect.IsEmpty()) {
- // If there is a damage on the surface, boundaries of mirror layers should
- // also be marked as damaged so they can reflect the changes in the
- // sub-surfaces of this surface.
- damage_rect.Union(cc::MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
- root_pass_transform, frame.metadata.mirror_rect));
-
// The following call can cause one or more copy requests to be added to the
// Surface. Therefore, no code before this point should have assumed
// anything about the presence or absence of copy requests after this point.
@@ -1340,6 +1479,9 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
// them too.
surface->TakeCopyOutputRequestsFromClient();
+ if (de_jelly_enabled_ && surface->HasUndrawnActiveFrame())
+ new_surfaces_.insert(surface->surface_id());
+
if (will_draw)
surface->OnWillBeDrawn();
@@ -1371,8 +1513,7 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
has_cached_render_passes_ = true;
}
- auto it = referenced_surfaces_.find(surface->surface_id());
- referenced_surfaces_.erase(it);
+ referenced_surfaces_.erase(surface->surface_id());
if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video)
result->may_contain_video = true;
@@ -1416,8 +1557,7 @@ void SurfaceAggregator::CopyUndrawnSurfaces(PrewalkResult* prewalk_result) {
prewalk_result->undrawn_surfaces.erase(surface_id);
referenced_surfaces_.insert(surface_id);
CopyPasses(surface->GetActiveFrame(), surface);
- // CopyPasses may have mutated container, need to re-query to erase.
- referenced_surfaces_.erase(referenced_surfaces_.find(surface_id));
+ referenced_surfaces_.erase(surface_id);
}
}
}
@@ -1443,7 +1583,7 @@ bool SurfaceAggregator::CanMergeRoundedCorner(
const RoundedCornerInfo& rounded_corner_info,
const RenderPass& root_render_pass) {
// If the quad has no rounded corner, then we do not have to block merging.
- if (rounded_corner_info.IsEmpty())
+ if (rounded_corner_info.bounds.IsEmpty())
return true;
// If the quad has rounded corner and it is not a fast rounded corner, we
@@ -1505,6 +1645,7 @@ CompositorFrame SurfaceAggregator::Aggregate(
has_cached_render_passes_ = false;
damage_ranges_.clear();
damage_rects_union_of_surfaces_on_top_ = gfx::Rect();
+ new_surfaces_.clear();
DCHECK(referenced_surfaces_.empty());
PrewalkResult prewalk_result;
root_damage_rect_ =
@@ -1517,8 +1658,12 @@ CompositorFrame SurfaceAggregator::Aggregate(
CopyUndrawnSurfaces(&prewalk_result);
referenced_surfaces_.insert(surface_id);
CopyPasses(root_surface_frame, surface);
- // CopyPasses may have mutated container, need to re-query to erase.
- referenced_surfaces_.erase(referenced_surfaces_.find(surface_id));
+ referenced_surfaces_.erase(surface_id);
+
+ // Now that we've handled our main surface aggregation, apply de-jelly effect
+ // if enabled.
+ HandleDeJelly(surface);
+
AddColorConversionPass();
moved_pixel_passes_.clear();
@@ -1561,6 +1706,10 @@ CompositorFrame SurfaceAggregator::Aggregate(
break;
}
}
+
+ if (frame_annotator_)
+ frame_annotator_->AnnotateAggregatedFrame(&frame);
+
return frame;
}
@@ -1616,8 +1765,285 @@ bool SurfaceAggregator::NotifySurfaceDamageAndCheckForDisplayDamage(
return false;
}
+void SurfaceAggregator::SetFrameAnnotator(
+ std::unique_ptr<FrameAnnotator> frame_annotator) {
+ DCHECK(!frame_annotator_);
+ frame_annotator_ = std::move(frame_annotator);
+}
+
bool SurfaceAggregator::IsRootSurface(const Surface* surface) const {
return surface->surface_id() == root_surface_id_;
}
+void SurfaceAggregator::HandleDeJelly(Surface* surface) {
+ TRACE_EVENT0("viz", "SurfaceAggregator::HandleDeJelly");
+
+ if (dest_pass_list_->empty() || !DeJellyActive()) {
+ SetLastFrameHadJelly(false);
+ return;
+ }
+
+ // |jelly_clip| is the rect that contains all de-jelly'd quads. It is used as
+ // an approximation for the containing non-skewed clip rect.
+ gfx::Rect jelly_clip;
+ // |max_skew| represents the maximum skew applied to an element. To prevent
+ // tearing due to slight inaccuracies, we apply the max skew to all skewed
+ // elements.
+ float max_skew = 0.0f;
+
+ // Iterate over each SharedQuadState in the root render pass and compute
+ // |max_skew| and |jelly_clip|.
+ auto* root_render_pass = dest_pass_list_->back().get();
+ float screen_width = DeJellyScreenWidth();
+ for (SharedQuadState* state : root_render_pass->shared_quad_state_list) {
+ float delta_y = state->de_jelly_delta_y;
+ if (delta_y == 0.0f)
+ continue;
+
+ // We are going to de-jelly this SharedQuadState. Expand the max clip.
+ jelly_clip.Union(state->clip_rect);
+
+ // Compute the skew angle and update |max_skew|.
+ float de_jelly_angle = gfx::RadToDeg(atan2(delta_y, screen_width));
+ float sign = de_jelly_angle / std::abs(de_jelly_angle);
+ max_skew = std::max(std::abs(de_jelly_angle), std::abs(max_skew)) * sign;
+ }
+
+ // Exit if nothing was skewed.
+ if (max_skew == 0.0f) {
+ SetLastFrameHadJelly(false);
+ return;
+ }
+
+ SetLastFrameHadJelly(true);
+
+ // Remove the existing root render pass and create a new one which we will
+ // re-copy skewed quads / render-passes to.
+ // TODO(ericrk): Handle backdrop filters?
+ // TODO(ericrk): This will end up skewing copy requests. Address if
+ // necessary.
+ std::unique_ptr<RenderPass> old_root = std::move(dest_pass_list_->back());
+ dest_pass_list_->pop_back();
+ auto new_root = root_render_pass->Copy(root_render_pass->id);
+ new_root->copy_requests = std::move(old_root->copy_requests);
+
+ // Data tracking the current sub RenderPass (if any) which is being appended
+ // to. We can keep re-using a sub RenderPass if the skew has not changed and
+ // if we are in the typical kSrcOver blend mode.
+ std::unique_ptr<RenderPass> sub_render_pass;
+ SkBlendMode sub_render_pass_blend_mode;
+ float sub_render_pass_opacity;
+
+ // Apply de-jelly to all quads, promoting quads into render passes as
+ // necessary.
+ for (auto it = root_render_pass->quad_list.begin();
+ it != root_render_pass->quad_list.end();) {
+ auto* state = it->shared_quad_state;
+ bool has_skew = state->de_jelly_delta_y != 0.0f;
+
+ // If we have a sub RenderPass which is not compatible with our current
+ // quad, we must flush and clear it.
+ if (sub_render_pass) {
+ if (!has_skew || sub_render_pass_blend_mode != state->blend_mode ||
+ state->blend_mode != SkBlendMode::kSrcOver) {
+ AppendDeJellyRenderPass(max_skew, jelly_clip, sub_render_pass_opacity,
+ sub_render_pass_blend_mode, new_root.get(),
+ std::move(sub_render_pass));
+ sub_render_pass.reset();
+ }
+ }
+
+ // Create a new render pass if we have a skewed quad which is clipped more
+ // than jelly_clip.
+ bool create_render_pass =
+ has_skew && state->is_clipped && state->clip_rect != jelly_clip;
+ if (!sub_render_pass && create_render_pass) {
+ sub_render_pass = RenderPass::Create(1, 1);
+ gfx::Transform skew_transform;
+ skew_transform.Skew(0.0f, max_skew);
+ // Ignore rectangles for now, these are updated in
+ // CreateDeJellyRenderPassQuads.
+ sub_render_pass->SetNew(next_render_pass_id_++, gfx::Rect(), gfx::Rect(),
+ skew_transform);
+ // If blend mode is not kSrcOver, we apply it in the render pass.
+ if (state->blend_mode != SkBlendMode::kSrcOver) {
+ sub_render_pass_opacity = state->opacity;
+ sub_render_pass_blend_mode = state->blend_mode;
+ } else {
+ sub_render_pass_opacity = 1.0f;
+ sub_render_pass_blend_mode = SkBlendMode::kSrcOver;
+ }
+ }
+
+ if (sub_render_pass) {
+ CreateDeJellyRenderPassQuads(&it, root_render_pass->quad_list.end(),
+ jelly_clip, max_skew, sub_render_pass.get());
+ } else {
+ float skew = has_skew ? max_skew : 0.0f;
+ CreateDeJellyNormalQuads(&it, root_render_pass->quad_list.end(),
+ new_root.get(), skew);
+ }
+ }
+ if (sub_render_pass) {
+ AppendDeJellyRenderPass(max_skew, jelly_clip, sub_render_pass_opacity,
+ sub_render_pass_blend_mode, new_root.get(),
+ std::move(sub_render_pass));
+ }
+
+ dest_pass_list_->push_back(std::move(new_root));
+}
+
+void SurfaceAggregator::CreateDeJellyRenderPassQuads(
+ cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
+ const cc::ListContainer<DrawQuad>::Iterator& end,
+ const gfx::Rect& jelly_clip,
+ float skew,
+ RenderPass* render_pass) {
+ auto* quad = **quad_iterator;
+ const auto* state = quad->shared_quad_state;
+
+ // Heuristic - we may have over-clipped a quad. If a quad is clipped by the
+ // |jelly_clip|, but contains content beyond |jelly_clip|, un-clip the quad by
+ // MaxDeJellyHeight().
+ int un_clip_top = 0;
+ int un_clip_bottom = 0;
+ if (state->clip_rect.y() <= jelly_clip.y()) {
+ un_clip_top = MaxDeJellyHeight();
+ }
+ if (state->clip_rect.bottom() >= jelly_clip.bottom()) {
+ un_clip_bottom = MaxDeJellyHeight();
+ }
+
+ // Compute the required renderpass rect in target space.
+ // First, find the un-transformed visible rect.
+ gfx::RectF render_pass_visible_rect_f(state->visible_quad_layer_rect);
+ // Next, if this is a RenderPass quad, find any filters and expand the
+ // visible rect.
+ if (quad->material == DrawQuad::Material::kRenderPass) {
+ RenderPassId target_id =
+ RenderPassDrawQuad::MaterialCast(quad)->render_pass_id;
+ RenderPass* source_render_pass = nullptr;
+ for (auto& rp : *dest_pass_list_) {
+ if (rp->id == target_id) {
+ source_render_pass = rp.get();
+ break;
+ }
+ }
+ if (source_render_pass) {
+ render_pass_visible_rect_f =
+ gfx::RectF(source_render_pass->filters.MapRect(
+ state->visible_quad_layer_rect, SkMatrix()));
+ }
+ }
+ // Next, find the enclosing Rect for the transformed target space RectF.
+ state->quad_to_target_transform.TransformRect(&render_pass_visible_rect_f);
+ gfx::Rect render_pass_visible_rect =
+ gfx::ToEnclosingRect(render_pass_visible_rect_f);
+ // Finally, expand by our un_clip amounts.
+ render_pass_visible_rect.Inset(0, -un_clip_top, 0, -un_clip_bottom);
+
+ // Expand the |render_pass|'s rects.
+ render_pass->output_rect =
+ gfx::UnionRects(render_pass->output_rect, render_pass_visible_rect);
+ render_pass->damage_rect = render_pass->output_rect;
+
+ // Create a new SharedQuadState based on |state|.
+ {
+ auto* new_state = render_pass->CreateAndAppendSharedQuadState();
+ *new_state = *state;
+ // If blend mode is not kSrcOver, we apply it in the RenderPass.
+ if (state->blend_mode != SkBlendMode::kSrcOver) {
+ new_state->opacity = 1.0f;
+ new_state->blend_mode = SkBlendMode::kSrcOver;
+ }
+
+ // Expand our clip by un clip amounts.
+ new_state->clip_rect.Inset(0, -un_clip_top, 0, -un_clip_bottom);
+ }
+
+ // Append all quads sharing |new_state|.
+ AppendDeJellyQuadsForSharedQuadState(quad_iterator, end, render_pass, state);
+}
+
+void SurfaceAggregator::CreateDeJellyNormalQuads(
+ cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
+ const cc::ListContainer<DrawQuad>::Iterator& end,
+ RenderPass* root_pass,
+ float skew) {
+ auto* quad = **quad_iterator;
+ const auto* state = quad->shared_quad_state;
+
+ // Crearte a new SharedQuadState on |root_pass| and apply skew if any.
+ SharedQuadState* new_state = root_pass->CreateAndAppendSharedQuadState();
+ *new_state = *state;
+ if (skew != 0.0f) {
+ gfx::Transform skew_transform;
+ skew_transform.Skew(0.0f, skew);
+ new_state->quad_to_target_transform =
+ skew_transform * new_state->quad_to_target_transform;
+ }
+
+ // Append all quads sharing |new_state|.
+ AppendDeJellyQuadsForSharedQuadState(quad_iterator, end, root_pass, state);
+}
+
+void SurfaceAggregator::AppendDeJellyRenderPass(
+ float skew,
+ const gfx::Rect& jelly_clip,
+ float opacity,
+ SkBlendMode blend_mode,
+ RenderPass* root_pass,
+ std::unique_ptr<RenderPass> render_pass) {
+ // Create a new quad for this renderpass and append it to the pass list.
+ auto* new_state = root_pass->CreateAndAppendSharedQuadState();
+ gfx::Transform transform;
+ new_state->SetAll(transform, render_pass->output_rect,
+ render_pass->output_rect, gfx::RRectF(), jelly_clip, true,
+ false, opacity, blend_mode, 0);
+ auto* quad = root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
+ quad->SetNew(new_state, render_pass->output_rect, render_pass->output_rect,
+ render_pass->id, 0, gfx::RectF(), gfx::Size(), false,
+ gfx::Vector2dF(), gfx::PointF(),
+ gfx::RectF(gfx::SizeF(render_pass->output_rect.size())), false,
+ 1.0f);
+ gfx::Transform skew_transform;
+ skew_transform.Skew(0.0f, skew);
+ new_state->quad_to_target_transform =
+ skew_transform * new_state->quad_to_target_transform;
+ dest_pass_list_->push_back(std::move(render_pass));
+}
+
+void SurfaceAggregator::AppendDeJellyQuadsForSharedQuadState(
+ cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
+ const cc::ListContainer<DrawQuad>::Iterator& end,
+ RenderPass* render_pass,
+ const SharedQuadState* state) {
+ auto* quad = **quad_iterator;
+ while (quad->shared_quad_state == state) {
+ if (quad->material == DrawQuad::Material::kRenderPass) {
+ const auto* pass_quad = RenderPassDrawQuad::MaterialCast(quad);
+ render_pass->CopyFromAndAppendRenderPassDrawQuad(
+ pass_quad, pass_quad->render_pass_id);
+ } else {
+ render_pass->CopyFromAndAppendDrawQuad(quad);
+ }
+
+ ++(*quad_iterator);
+ if (*quad_iterator == end)
+ break;
+ quad = **quad_iterator;
+ }
+}
+
+void SurfaceAggregator::SetLastFrameHadJelly(bool had_jelly) {
+ // If we've just rendererd a jelly-free frame after one with jelly, we must
+ // damage the entire surface, as we may have removed jelly from an otherwise
+ // unchanged quad.
+ if (last_frame_had_jelly_ && !had_jelly) {
+ RenderPass* root_pass = dest_pass_list_->back().get();
+ root_pass->damage_rect = root_pass->output_rect;
+ }
+ last_frame_had_jelly_ = had_jelly;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/surface_aggregator.h b/chromium/components/viz/service/display/surface_aggregator.h
index d16f76304bd..2454963d95c 100644
--- a/chromium/components/viz/service/display/surface_aggregator.h
+++ b/chromium/components/viz/service/display/surface_aggregator.h
@@ -35,6 +35,15 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
using SurfaceIndexMap = base::flat_map<SurfaceId, uint64_t>;
using FrameSinkIdMap = base::flat_map<FrameSinkId, LocalSurfaceId>;
+ // Interface that can modify the aggregated CompositorFrame to annotate it.
+ // For example it could add extra quads.
+ class FrameAnnotator {
+ public:
+ virtual ~FrameAnnotator() = default;
+
+ virtual void AnnotateAggregatedFrame(CompositorFrame* frame) = 0;
+ };
+
SurfaceAggregator(SurfaceManager* manager,
DisplayResourceProvider* provider,
bool aggregate_only_damaged,
@@ -55,6 +64,9 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
void SetFullDamageForSurface(const SurfaceId& surface_id);
void set_output_is_secure(bool secure) { output_is_secure_ = secure; }
+ // Only used with experimental de-jelly effect.
+ bool last_frame_had_jelly() const { return last_frame_had_jelly_; }
+
// Set the color spaces for the created RenderPasses, which is propagated
// to the output surface.
void SetOutputColorSpace(const gfx::ColorSpace& output_color_space);
@@ -63,26 +75,14 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
bool NotifySurfaceDamageAndCheckForDisplayDamage(const SurfaceId& surface_id);
- private:
- struct ClipData {
- ClipData() : is_clipped(false) {}
- ClipData(bool is_clipped, const gfx::Rect& rect)
- : is_clipped(is_clipped), rect(rect) {}
-
- std::string ToString() const;
-
- bool is_clipped;
- gfx::Rect rect;
- };
+ void SetFrameAnnotator(std::unique_ptr<FrameAnnotator> frame_annotator);
- struct PrewalkResult {
- PrewalkResult();
- ~PrewalkResult();
- // This is the set of Surfaces that were referenced by another Surface, but
- // not included in a SurfaceDrawQuad.
- base::flat_set<SurfaceId> undrawn_surfaces;
- bool may_contain_video = false;
- };
+ private:
+ struct ClipData;
+ struct PrewalkResult;
+ struct RoundedCornerInfo;
+ struct ChildSurfaceInfo;
+ struct RenderPassMapEntry;
struct RenderPassInfo {
// This is the id the pass is mapped to.
@@ -91,19 +91,11 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
bool in_use = true;
};
- struct RoundedCornerInfo {
- RoundedCornerInfo() : is_fast_rounded_corner(false) {}
- // |target_transform| is the transform that maps |bounds| from its current
- // space into the desired target space. It must be a scale+translation
- // matrix.
- RoundedCornerInfo(const gfx::RRectF& bounds,
- bool is_fast_rounded_corner,
- const gfx::Transform target_transform);
-
- bool IsEmpty() const { return bounds.IsEmpty(); }
- gfx::RRectF bounds;
- bool is_fast_rounded_corner;
- };
+ // Helper function that gets a list of render passes and returns a map from
+ // render pass ids to render passes.
+ static base::flat_map<RenderPassId, RenderPassMapEntry> GenerateRenderPassMap(
+ const RenderPassList& render_pass_list,
+ bool is_root_surface);
ClipData CalculateClipRect(const ClipData& surface_clip,
const ClipData& quad_clip,
@@ -135,7 +127,8 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
gfx::Rect* damage_rect_in_quad_space,
bool* damage_rect_in_quad_space_valid,
const RoundedCornerInfo& rounded_corner_info,
- bool is_reflection);
+ bool is_reflection,
+ bool allow_merge);
void EmitDefaultBackgroundColorQuad(
const SurfaceDrawQuad* surface_quad,
@@ -188,6 +181,33 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
const gfx::Rect& occluding_damage_rect,
bool occluding_damage_rect_valid);
+ // Helper function that uses backtracking on the render pass tree of a surface
+ // to find all surfaces embedded in it. If a surface is embedded multiple
+ // times (due to use of a MirrorLayer), it will be reachable via multiple
+ // paths from the root render pass. For each such a path the appropriate
+ // transform is calculated.
+ // - |surface_id| specifies the surface to find all child surfaces of.
+ // - |render_pass_map| is a pre-computed map from render pass id to some info
+ // about the render pass, including the render pass itself and whether it
+ // has pixel moving backdrop filter.
+ // - |current_pass_entry| is the info about the current render pass to
+ // process.
+ // - |transform_to_root_target| is the accumulated transform of all render
+ // passes along the way to the current render pass.
+ // - |child_surfaces| is the main output of the function containing all child
+ // surfaces found in the process.
+ // - |pixel_moving_backdrop_filters_rect| is another output that is union of
+ // bounds of render passes that have a pixel moving backdrop filter.
+ // TODO(mohsen): Consider refactoring this backtracking algorithm into a
+ // self-contained class.
+ void FindChildSurfaces(
+ SurfaceId surface_id,
+ base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
+ RenderPassMapEntry* current_pass_entry,
+ const gfx::Transform& transform_to_root_target,
+ base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces,
+ gfx::Rect* pixel_moving_backdrop_filters_rect);
+
gfx::Rect PrewalkTree(Surface* surface,
bool in_moved_pixel_surface,
int parent_pass,
@@ -233,6 +253,41 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
static void UnrefResources(base::WeakPtr<SurfaceClient> surface_client,
const std::vector<ReturnedResource>& resources);
+ // De-Jelly Effect:
+ // HandleDeJelly applies a de-jelly transform to quads in the root render
+ // pass.
+ void HandleDeJelly(Surface* surface);
+ // CreateDeJellyRenderPassQuads promotes skewed quads from the root render
+ // pass into |render_pass|. Skew is applied when |render_pass| is drawn.
+ void CreateDeJellyRenderPassQuads(
+ cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
+ const cc::ListContainer<DrawQuad>::Iterator& end,
+ const gfx::Rect& jelly_clip,
+ float skew,
+ RenderPass* render_pass);
+ // Appends quads directly to |root_pass|, applying |skew|.
+ void CreateDeJellyNormalQuads(
+ cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
+ const cc::ListContainer<DrawQuad>::Iterator& end,
+ RenderPass* root_pass,
+ float skew);
+ // Appends |render_pass| to |root_pass|, applying |skew|, |jelly_clip|,
+ // |opacity|, and |blend_mode|.
+ void AppendDeJellyRenderPass(float skew,
+ const gfx::Rect& jelly_clip,
+ float opacity,
+ SkBlendMode blend_mode,
+ RenderPass* root_pass,
+ std::unique_ptr<RenderPass> render_pass);
+ // Appends quads from |quad_iterator| to |render_pass| for |state|.
+ void AppendDeJellyQuadsForSharedQuadState(
+ cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
+ const cc::ListContainer<DrawQuad>::Iterator& end,
+ RenderPass* render_pass,
+ const SharedQuadState* state);
+ // Update |last_frame_had_jelly_|, should be called once per frame.
+ void SetLastFrameHadJelly(bool had_jelly);
+
SurfaceManager* manager_;
DisplayResourceProvider* provider_;
@@ -326,9 +381,21 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
// the display if they're damaged.
base::flat_map<FrameSinkId, std::vector<SurfaceRange>> damage_ranges_;
+ // Used to annotate the aggregated frame for debugging.
+ std::unique_ptr<FrameAnnotator> frame_annotator_;
+
int64_t display_trace_id_ = -1;
base::flat_set<SurfaceId> undrawn_surfaces_;
+ // Variables used for de-jelly:
+ // Whether de-jelly may be active.
+ bool de_jelly_enabled_ = false;
+ // The set of surfacees being drawn for the first time. Used to determine if
+ // de-jelly skew should be applied to a surface.
+ base::flat_set<SurfaceId> new_surfaces_;
+ // Whether the last drawn frame had de-jelly skew applied.
+ bool last_frame_had_jelly_ = false;
+
base::WeakPtrFactory<SurfaceAggregator> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SurfaceAggregator);
diff --git a/chromium/components/viz/service/display/surface_aggregator_unittest.cc b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
index 9708b9b4d86..c7ce69ee626 100644
--- a/chromium/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
@@ -196,14 +196,16 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
return quad;
}
- static Quad RenderPassQuad(int id) {
+ static Quad RenderPassQuad(int id, const gfx::Transform& transform) {
Quad quad;
quad.material = DrawQuad::Material::kRenderPass;
quad.render_pass_id = id;
+ quad.transform = transform;
return quad;
}
DrawQuad::Material material;
+
// Set when material==DrawQuad::Material::kSurfaceContent.
SurfaceRange surface_range;
SkColor default_background_color;
@@ -212,13 +214,16 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
gfx::Rect primary_surface_rect;
float opacity;
gfx::Transform to_target_transform;
+ gfx::RRectF rounded_corner_bounds;
+ bool is_fast_rounded_corner;
+
// Set when material==DrawQuad::Material::kSolidColor.
SkColor color;
gfx::Rect rect;
+
// Set when material==DrawQuad::Material::kRenderPass.
RenderPassId render_pass_id;
- gfx::RRectF rounded_corner_bounds;
- bool is_fast_rounded_corner;
+ gfx::Transform transform;
private:
Quad()
@@ -262,7 +267,7 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
desc.is_fast_rounded_corner);
break;
case DrawQuad::Material::kRenderPass:
- AddRenderPassQuad(pass, desc.render_pass_id);
+ AddRenderPassQuad(pass, desc.render_pass_id, desc.transform);
break;
case DrawQuad::Material::kYuvVideoContent:
AddYUVVideoQuad(pass, desc.rect);
@@ -368,12 +373,14 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
stretch_content_to_fill_bounds, ignores_input_event);
}
- static void AddRenderPassQuad(RenderPass* pass, RenderPassId render_pass_id) {
+ static void AddRenderPassQuad(RenderPass* pass,
+ RenderPassId render_pass_id,
+ const gfx::Transform& transform) {
gfx::Rect output_rect = gfx::Rect(0, 0, 5, 5);
auto* shared_state = pass->CreateAndAppendSharedQuadState();
- shared_state->SetAll(gfx::Transform(), output_rect, output_rect,
- gfx::RRectF(), output_rect, false, false, 1,
- SkBlendMode::kSrcOver, 0);
+ shared_state->SetAll(transform, output_rect, output_rect, gfx::RRectF(),
+ output_rect, false, false, 1, SkBlendMode::kSrcOver,
+ 0);
auto* quad = pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, 0,
gfx::RectF(), gfx::Size(), false, gfx::Vector2dF(),
@@ -1486,7 +1493,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {
SurfaceRange(base::nullopt, root_surface_id),
SK_ColorBLACK,
/*stretch_content_to_fill_bounds=*/true,
- /*ignores_input_event=*/false, /*is_reflection=*/true);
+ /*ignores_input_event=*/false, /*is_reflection=*/true,
+ /*allow_merge=*/true);
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
@@ -1567,7 +1575,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {
SurfaceRange(base::nullopt, root_surface_id),
SK_ColorBLACK,
/*stretch_content_to_fill_bounds=*/true,
- /*ignores_input_event=*/false, /*is_reflection=*/true);
+ /*ignores_input_event=*/false, /*is_reflection=*/true,
+ /*allow_merge=*/true);
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
@@ -1737,7 +1746,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
std::vector<Quad> expected_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::RenderPassQuad(aggregated_frame.render_pass_list[0]->id),
+ Quad::RenderPassQuad(aggregated_frame.render_pass_list[0]->id,
+ gfx::Transform()),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(embedded_quads, SurfaceSize()),
Pass(expected_quads, SurfaceSize())};
@@ -1964,9 +1974,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
{Quad::SolidColorQuad(1, gfx::Rect(5, 5)),
Quad::SolidColorQuad(2, gfx::Rect(5, 5))},
{Quad::SolidColorQuad(3, gfx::Rect(5, 5)),
- Quad::RenderPassQuad(pass_ids[0])},
+ Quad::RenderPassQuad(pass_ids[0], gfx::Transform())},
{Quad::SolidColorQuad(4, gfx::Rect(5, 5)),
- Quad::RenderPassQuad(pass_ids[1])}};
+ Quad::RenderPassQuad(pass_ids[1], gfx::Transform())}};
std::vector<Pass> embedded_passes = {
Pass(embedded_quads[0], pass_ids[0], SurfaceSize()),
Pass(embedded_quads[1], pass_ids[1], SurfaceSize()),
@@ -1983,9 +1993,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false),
- Quad::RenderPassQuad(pass_ids[0])},
+ Quad::RenderPassQuad(pass_ids[0], gfx::Transform())},
{Quad::SolidColorQuad(7, gfx::Rect(5, 5)),
- Quad::RenderPassQuad(pass_ids[1])}};
+ Quad::RenderPassQuad(pass_ids[1], gfx::Transform())}};
std::vector<Pass> root_passes = {
Pass(root_quads[0], pass_ids[0], SurfaceSize()),
Pass(root_quads[1], pass_ids[1], SurfaceSize()),
@@ -2273,7 +2283,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
RenderPassId child_pass_id[] = {1u, 2u};
std::vector<Quad> child_quad[2] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
- {Quad::RenderPassQuad(child_pass_id[0])}};
+ {Quad::RenderPassQuad(child_pass_id[0], gfx::Transform())}};
std::vector<Pass> surface_passes = {
Pass(child_quad[0], child_pass_id[0], SurfaceSize()),
Pass(child_quad[1], child_pass_id[1], SurfaceSize())};
@@ -2289,7 +2299,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false)},
- {Quad::RenderPassQuad(parent_pass_id[0])}};
+ {Quad::RenderPassQuad(parent_pass_id[0], gfx::Transform())}};
std::vector<Pass> parent_passes = {
Pass(parent_quad[0], parent_pass_id[0], SurfaceSize()),
Pass(parent_quad[1], parent_pass_id[1], SurfaceSize())};
@@ -2747,7 +2757,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
int child_pass_id[] = {1, 2};
std::vector<Quad> child_quads[2] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
- {Quad::RenderPassQuad(child_pass_id[0])},
+ {Quad::RenderPassQuad(child_pass_id[0], gfx::Transform())},
};
std::vector<Pass> child_passes = {
Pass(child_quads[0], child_pass_id[0], SurfaceSize()),
@@ -2918,7 +2928,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot,
kNeedsSyncPoints);
- std::vector<Quad> child_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, 1, SurfaceSize())};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
@@ -2964,7 +2975,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
SurfaceRange(base::nullopt, parent_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false)};
- std::vector<Quad> root_render_pass_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> root_render_pass_quads = {
+ Quad::RenderPassQuad(1, gfx::Transform())};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, 1, SurfaceSize()),
@@ -3106,7 +3118,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithSquashToFit) {
auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot,
kNeedsSyncPoints);
- std::vector<Quad> child_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, 1, gfx::Size(100, 100))};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
@@ -3152,7 +3165,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithSquashToFit) {
SurfaceRange(base::nullopt, parent_surface_id), SK_ColorWHITE,
gfx::Rect(50, 50), /*stretch_content_to_fill_bounds=*/true,
/*ignores_input_event=*/false)};
- std::vector<Quad> root_render_pass_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> root_render_pass_quads = {
+ Quad::RenderPassQuad(1, gfx::Transform())};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, 1, SurfaceSize()),
@@ -3215,7 +3229,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithStretchToFit) {
auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot,
kNeedsSyncPoints);
- std::vector<Quad> child_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, 1, gfx::Size(100, 100))};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
@@ -3261,7 +3276,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithStretchToFit) {
SurfaceRange(base::nullopt, parent_surface_id), SK_ColorWHITE,
gfx::Rect(200, 200), /*stretch_content_to_fill_bounds=*/true,
/*ignores_input_event=*/false)};
- std::vector<Quad> root_render_pass_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> root_render_pass_quads = {
+ Quad::RenderPassQuad(1, gfx::Transform())};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, 1, SurfaceSize()),
@@ -3638,14 +3654,17 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// the other other with a visible rect of 10,10 2x2 (relative to root target
// space), and one with a non-invertible transform.
{
- int child_pass_id = 1;
- std::vector<Quad> child_quads1 = {Quad::RenderPassQuad(child_pass_id)};
- std::vector<Quad> child_quads2 = {Quad::RenderPassQuad(child_pass_id)};
- std::vector<Quad> child_quads3 = {Quad::RenderPassQuad(child_pass_id)};
+ int child_pass_ids[] = {1, 2, 3};
+ std::vector<Quad> child_quads1 = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
+ std::vector<Quad> child_quads2 = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
+ std::vector<Quad> child_quads3 = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {
- Pass(child_quads1, child_pass_id, SurfaceSize()),
- Pass(child_quads2, child_pass_id, SurfaceSize()),
- Pass(child_quads3, child_pass_id, SurfaceSize())};
+ Pass(child_quads1, child_pass_ids[0], SurfaceSize()),
+ Pass(child_quads2, child_pass_ids[1], SurfaceSize()),
+ Pass(child_quads3, child_pass_ids[2], SurfaceSize())};
RenderPassList child_pass_list;
std::vector<SurfaceRange> referenced_surfaces;
@@ -3754,7 +3773,8 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
{
int child_pass_ids[] = {1, 2};
std::vector<Quad> child_quads1 = {Quad::SolidColorQuad(1, gfx::Rect(5, 5))};
- std::vector<Quad> child_quads2 = {Quad::RenderPassQuad(child_pass_ids[0])};
+ std::vector<Quad> child_quads2 = {
+ Quad::RenderPassQuad(child_pass_ids[0], gfx::Transform())};
std::vector<Pass> child_passes = {
Pass(child_quads1, child_pass_ids[0], SurfaceSize()),
Pass(child_quads2, child_pass_ids[1], SurfaceSize())};
@@ -3821,8 +3841,10 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false)};
- std::vector<Quad> root_quads2 = {Quad::RenderPassQuad(root_pass_ids[0])};
- std::vector<Quad> root_quads3 = {Quad::RenderPassQuad(root_pass_ids[1])};
+ std::vector<Quad> root_quads2 = {
+ Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform())};
+ std::vector<Quad> root_quads3 = {
+ Quad::RenderPassQuad(root_pass_ids[1], gfx::Transform())};
std::vector<Pass> root_passes = {
Pass(root_quads1, root_pass_ids[0], SurfaceSize()),
Pass(root_quads2, root_pass_ids[1], SurfaceSize()),
@@ -3870,7 +3892,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
Quad::SolidColorQuad(1, gfx::Rect(5, 5)),
};
std::vector<Quad> root_quads2 = {
- Quad::RenderPassQuad(root_pass_ids[0]),
+ Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform()),
Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
@@ -3923,7 +3945,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
Quad::SolidColorQuad(1, gfx::Rect(pass_with_filter_size)),
};
std::vector<Quad> root_quads2 = {
- Quad::RenderPassQuad(root_pass_ids[0]),
+ Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform()),
Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
@@ -3961,8 +3983,9 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// therefore the whole render pass should be damaged.
EXPECT_EQ(gfx::Rect(0, 0, 5, 5), aggregated_pass_list[0]->damage_rect);
EXPECT_EQ(1u, aggregated_pass_list[0]->quad_list.size());
- EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[1]->damage_rect);
- EXPECT_EQ(1u, aggregated_pass_list[1]->quad_list.size());
+
+ EXPECT_EQ(gfx::Rect(1, 1), aggregated_pass_list[1]->damage_rect);
+ EXPECT_EQ(0u, aggregated_pass_list[1]->quad_list.size());
// First render pass draw quad overlaps with damage rect and has background
// filter, so it should be damaged. SurfaceDrawQuad is after background
@@ -3980,7 +4003,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
Quad::SolidColorQuad(1, gfx::Rect(pass_with_filter_size)),
};
std::vector<Quad> root_quads2 = {
- Quad::RenderPassQuad(root_pass_ids[0]),
+ Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform()),
Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
@@ -4016,7 +4039,8 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// Pass 0 has background blur filter but does NOT overlap with damage rect.
EXPECT_EQ(gfx::Rect(), aggregated_pass_list[0]->damage_rect);
EXPECT_EQ(0u, aggregated_pass_list[0]->quad_list.size());
- EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[1]->damage_rect);
+
+ EXPECT_EQ(gfx::Rect(1, 1, 3, 3), aggregated_pass_list[1]->damage_rect);
EXPECT_EQ(1u, aggregated_pass_list[1]->quad_list.size());
// First render pass draw quad is outside damage rect, so shouldn't be
@@ -4413,7 +4437,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTest) {
// Tests that has_damage_from_contributing_content is aggregated correctly from
// child surface quads.
TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {
- std::vector<Quad> child_surface_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> child_surface_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_surface_passes = {
Pass(child_surface_quads, 1, SurfaceSize())};
@@ -4494,7 +4519,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot,
kNeedsSyncPoints);
- std::vector<Quad> child_surface_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> child_surface_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_surface_passes = {
Pass(child_surface_quads, 1, SurfaceSize())};
@@ -4538,7 +4564,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
}
// Add a grand_child_frame should cause damage.
- std::vector<Quad> grand_child_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> grand_child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> grand_child_passes = {
Pass(grand_child_quads, 1, SurfaceSize())};
ParentLocalSurfaceIdAllocator grandchild_allocator;
@@ -4616,7 +4643,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// Tests that has_damage_from_contributing_content is aggregated correctly from
// render pass quads.
TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
- std::vector<Quad> child_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, 1, SurfaceSize())};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
@@ -4636,7 +4664,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false)};
- std::vector<Quad> root_render_pass_quads = {Quad::RenderPassQuad(1)};
+ std::vector<Quad> root_render_pass_quads = {
+ Quad::RenderPassQuad(1, gfx::Transform())};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, 1, SurfaceSize()),
@@ -4691,7 +4720,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectOfCachedRenderPass) {
int pass_id[] = {1, 2};
std::vector<Quad> root_quads[2] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
- {Quad::RenderPassQuad(pass_id[0])},
+ {Quad::RenderPassQuad(pass_id[0], gfx::Transform())},
};
std::vector<Pass> root_passes = {
Pass(root_quads[0], pass_id[0], SurfaceSize()),
@@ -4780,7 +4809,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
int pass_id[] = {1, 2};
std::vector<Quad> child_quads[2] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
- {Quad::RenderPassQuad(pass_id[0])},
+ {Quad::RenderPassQuad(pass_id[0], gfx::Transform())},
};
std::vector<Pass> child_passes = {
Pass(child_quads[0], pass_id[0], SurfaceSize()),
@@ -5160,7 +5189,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
int pass_id[] = {1, 2};
std::vector<Quad> child_quads[2] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
- {Quad::RenderPassQuad(pass_id[0])},
+ {Quad::RenderPassQuad(pass_id[0], gfx::Transform())},
};
std::vector<Pass> child_passes = {
Pass(child_quads[0], pass_id[0], SurfaceSize()),
@@ -5193,7 +5222,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false)},
- {Quad::RenderPassQuad(pass_id[0])},
+ {Quad::RenderPassQuad(pass_id[0], gfx::Transform())},
};
std::vector<Pass> root_passes = {
Pass(root_quads[0], pass_id[0], SurfaceSize()),
@@ -5236,7 +5265,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
/*ignores_input_event=*/false)},
- {Quad::RenderPassQuad(pass_id[0])},
+ {Quad::RenderPassQuad(pass_id[0], gfx::Transform())},
};
std::vector<Pass> root_passes = {
Pass(root_quads[0], pass_id[0], SurfaceSize()),
@@ -5637,20 +5666,19 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TransformedRoundedSurfaceQuad) {
aggregated_first_pass_sqs->rounded_corner_bounds);
}
-// Verifies that when a child surface has a damage, the mirror-rect of the
-// parent surface is also included in the total damage.
-TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithMirrorRect) {
+// Verifies that if a child surface is embedded twice in the root surface,
+// SurfaceAggregator considers both occurrences in damage rect calculation.
+TEST_F(SurfaceAggregatorValidSurfaceTest,
+ AggregateDamageRectWithMultiplyEmbeddedSurface) {
// Add a callback for when the surface is damaged.
MockAggregatedDamageCallback aggregated_damage_callback;
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- const gfx::Rect surface_rect(SurfaceSize());
-
// The child surface consists of a single render pass containing a single
// solid color draw quad.
std::vector<Quad> child_quads = {
- Quad::SolidColorQuad(SK_ColorGREEN, surface_rect)};
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, SurfaceSize())};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
@@ -5666,19 +5694,33 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithMirrorRect) {
child_sink_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_frame));
- // The root surface consists of a single render pass containing a surface draw
- // quad referencing the child surface. It also has an area marked as
- // mirror-rect.
- std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
- surface_rect, /*stretch_content_to_fill_bounds=*/false,
- /*ignores_input_event=*/false)};
- std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
+ // The root surface consists of three render passes:
+ // 1) The first one contains a surface draw quad referencing the child
+ // surface.
+ // 2) The second one contains a render pass draw quad referencing the first
+ // render pass with a scale transform applied.
+ // 3) The third one contains two render pass draw quads, one referencing the
+ // second render pass with a translation transform applied, the other
+ // referencing the first render pass with no transform.
+ gfx::Transform scale;
+ scale.Scale(2.f, 2.f);
+ gfx::Transform translation;
+ translation.Translate(30.f, 50.f);
+ std::vector<Quad> root_quads[] = {
+ {Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ SK_ColorWHITE, gfx::Rect(5, 5),
+ /*stretch_content_to_fill_bounds=*/false,
+ /*ignores_input_event=*/false)},
+ {Quad::RenderPassQuad(1, scale)},
+ {Quad::RenderPassQuad(2, translation),
+ Quad::RenderPassQuad(1, gfx::Transform())}};
+ std::vector<Pass> root_passes = {Pass(root_quads[0], 1, SurfaceSize()),
+ Pass(root_quads[1], 2, SurfaceSize()),
+ Pass(root_quads[2], 3, SurfaceSize())};
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_frame.metadata.mirror_rect = gfx::Rect(10, 10, 10, 10);
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
@@ -5686,38 +5728,224 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRectWithMirrorRect) {
SurfaceId root_surface_id(root_sink_->frame_sink_id(),
root_local_surface_id_);
- // Damage rect for the first aggregation would contain entire root surface.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- surface_rect, next_display_time()));
+ // Damage rect for the first aggregation would contain entire root surface
+ // which is union of (0,0 100x100) and (30,50 200x200); i.e. (0,0 230x250).
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ gfx::Rect(0, 0, 230, 250), next_display_time()));
CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// For the second aggregation we only damage the child surface at
- // (20,50 10x10). The aggregated damage rect should be union of that and the
- // root's mirror-rect; i.e. (10,10 20x50).
+ // (10,10 10x10). The aggregated damage rect should reflect that.
CompositorFrame child_frame_2 = MakeEmptyCompositorFrame();
AddPasses(&child_frame_2.render_pass_list, child_passes,
&child_frame_2.metadata.referenced_surfaces);
- child_frame_2.render_pass_list.back()->damage_rect.SetRect(20, 50, 10, 10);
+ child_frame_2.render_pass_list.back()->damage_rect =
+ gfx::Rect(10, 10, 10, 10);
child_sink_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_frame_2));
+ // The child surface is embedded twice in the root surface, so its damage rect
+ // would appear in two locations in the root surface:
+ // 1) The first embedding has no transform, so its damage rect would simply
+ // be (10,10 10x10).
+ // 2) The second embedding is scaled by a factor of 2 and translated by
+ // (30,50). So, its damage rect would be (10*2+30,10*2+50 10*2x10*2) =
+ // (50,70 20x20).
+ // The aggregated damage rect would be union of the above damage rects which
+ // is (10,10 60x80).
+ gfx::Rect expected_damage_rect(10, 10, 60, 80);
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
+ testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
+}
+
+// Verifies that if a child surface is embedded in the root surface inside a
+// render pass cycle, only the first embedding of the child surface is
+// considered in the damage rect and its repeated embeddings are ignored.
+TEST_F(SurfaceAggregatorValidSurfaceTest,
+ AggregateDamageRectWithRenderPassCycle) {
+ // Add a callback for when the surface is damaged.
+ MockAggregatedDamageCallback aggregated_damage_callback;
+ root_sink_->SetAggregatedDamageCallbackForTesting(
+ aggregated_damage_callback.GetCallback());
+
+ // The child surface consists of a single render pass containing a single
+ // solid color draw quad.
+ std::vector<Quad> child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
+ std::vector<Pass> child_passes = {Pass(child_quads, SurfaceSize())};
+
+ CompositorFrame child_frame = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame.render_pass_list, child_passes,
+ &child_frame.metadata.referenced_surfaces);
+
+ ParentLocalSurfaceIdAllocator child_allocator;
+ child_allocator.GenerateId();
+ LocalSurfaceId child_local_surface_id =
+ child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id();
+ SurfaceId child_surface_id(child_sink_->frame_sink_id(),
+ child_local_surface_id);
+ child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame));
+
+ // The root surface consists of two render passes:
+ // 1) The first render pass contains a surface draw quad referencing the
+ // child surface and a render pass draw quad referencing the second render
+ // pass.
+ // 2) The second render pass contains a render pass draw quad with a
+ // transform applied that is referencing the first render pass, creating a
+ // cycle.
+ RenderPassId root_pass_ids[] = {1, 2};
+ std::vector<Quad> root_quads_1 = {
+ Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ SK_ColorWHITE, gfx::Rect(5, 5),
+ /*stretch_content_to_fill_bounds=*/false,
+ /*ignores_input_event=*/false),
+ Quad::RenderPassQuad(root_pass_ids[1], gfx::Transform())};
+ std::vector<Quad> root_quads_2 = {
+ Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform())};
+ std::vector<Pass> root_passes = {
+ Pass(root_quads_2, root_pass_ids[1], SurfaceSize()),
+ Pass(root_quads_1, root_pass_ids[0], SurfaceSize())};
+
+ CompositorFrame root_frame = MakeEmptyCompositorFrame();
+ AddPasses(&root_frame.render_pass_list, root_passes,
+ &root_frame.metadata.referenced_surfaces);
+
+ auto& rpdq_2_transform = root_frame.render_pass_list.front()
+ ->shared_quad_state_list.back()
+ ->quad_to_target_transform;
+ rpdq_2_transform.Translate(30.f, 50.f);
+ rpdq_2_transform.Scale(2.f, 2.f);
+
+ root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ std::move(root_frame));
+
+ SurfaceId root_surface_id(root_sink_->frame_sink_id(),
+ root_local_surface_id_);
+
+ // Damage rect for the first aggregation would contain entire root surface
+ // which is just (0,0 100x100). The child surface is only embedded once and
+ // without any transform, since repeated embeddings caused by the render pass
+ // cycle are ignored.
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- gfx::Rect(10, 10, 20, 50), next_display_time()));
- CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
+ gfx::Rect(0, 0, 100, 100), next_display_time()));
+ CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
- // For the third aggregation nothing is damaged, so no new frame is sent. The
- // mirror-rect should be ignored and aggregated damage rect should be empty,
- // which means OnAggregatedDamage() callback should not be called.
- CompositorFrame aggregated_frame_3 = AggregateFrame(root_surface_id);
+ // For the second aggregation we only damage the child surface at
+ // (10,10 10x10). The aggregated damage rect should reflect that only for the
+ // first embedding.
+ CompositorFrame child_frame_2 = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame_2.render_pass_list, child_passes,
+ &child_frame_2.metadata.referenced_surfaces);
+
+ child_frame_2.render_pass_list.back()->damage_rect =
+ gfx::Rect(10, 10, 10, 10);
+
+ child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame_2));
+
+ gfx::Rect expected_damage_rect(10, 10, 10, 10);
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ CompositorFrame aggregated_frame_2 = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
+// Verify that a SurfaceDrawQuad with !|allow_merge| won't be merged into the
+// parent renderpass.
+TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
+ // Child surface.
+ gfx::Rect child_rect(5, 5);
+ ParentLocalSurfaceIdAllocator child_allocator;
+ child_allocator.GenerateId();
+
+ LocalSurfaceId child_local_surface_id =
+ child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id();
+ SurfaceId child_surface_id(child_sink_->frame_sink_id(),
+ child_local_surface_id);
+ {
+ std::vector<Quad> child_quads = {
+ Quad::SolidColorQuad(SK_ColorGREEN, child_rect)};
+ std::vector<Pass> child_passes = {Pass(child_quads, 1, SurfaceSize())};
+
+ CompositorFrame child_frame = MakeEmptyCompositorFrame();
+ AddPasses(&child_frame.render_pass_list, child_passes,
+ &child_frame.metadata.referenced_surfaces);
+
+ child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ std::move(child_frame));
+ }
+
+ gfx::Rect root_rect(SurfaceSize());
+
+ // Submit a SurfaceDrawQuad that allows merging.
+ {
+ auto pass = RenderPass::Create();
+ pass->SetNew(1, root_rect, root_rect, gfx::Transform());
+ auto* sqs = pass->CreateAndAppendSharedQuadState();
+ sqs->opacity = 1.f;
+
+ auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad->SetAll(sqs, child_rect, child_rect,
+ /*needs_blending=*/false,
+ SurfaceRange(base::nullopt, child_surface_id),
+ SK_ColorWHITE,
+ /*stretch_content_to_fill_bounds=*/false,
+ /*ignores_input_event=*/false, /*is_reflection=*/false,
+ /*allow_merge=*/true);
+
+ CompositorFrame frame =
+ CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
+ root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+
+ SurfaceId root_surface_id(root_sink_->frame_sink_id(),
+ root_local_surface_id_);
+
+ CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+ // Merging allowed, so 1 pass should be present.
+ EXPECT_EQ(1u, aggregated_frame.render_pass_list.size());
+ }
+
+ // Submit a SurfaceDrawQuad that does not allow merging
+ {
+ auto pass = RenderPass::Create();
+ pass->SetNew(1, root_rect, root_rect, gfx::Transform());
+ auto* sqs = pass->CreateAndAppendSharedQuadState();
+ sqs->opacity = 1.f;
+
+ auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad->SetAll(sqs, child_rect, child_rect,
+ /*needs_blending=*/false,
+ SurfaceRange(base::nullopt, child_surface_id),
+ SK_ColorWHITE,
+ /*stretch_content_to_fill_bounds=*/false,
+ /*ignores_input_event=*/false, /*is_reflection=*/false,
+ /*allow_merge=*/false);
+
+ CompositorFrame frame =
+ CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
+ root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+
+ SurfaceId root_surface_id(root_sink_->frame_sink_id(),
+ root_local_surface_id_);
+
+ CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
+ // Merging not allowed, so 2 passes should be present.
+ EXPECT_EQ(2u, aggregated_frame.render_pass_list.size());
+ }
+}
+
} // namespace
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/DEPS b/chromium/components/viz/service/display_embedder/DEPS
index 12d77fdbfa8..af3d14bb4f7 100644
--- a/chromium/components/viz/service/display_embedder/DEPS
+++ b/chromium/components/viz/service/display_embedder/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+cc/output",
"+cc/resources",
"+cc/scheduler",
+ "+components/viz/service/display/external_use_client.h",
"+components/viz/service/display/output_surface_client.h",
"+components/viz/service/display/output_surface_frame.h",
"+components/viz/service/display/output_surface.h",
diff --git a/chromium/components/viz/service/display_embedder/compositing_mode_reporter_impl.h b/chromium/components/viz/service/display_embedder/compositing_mode_reporter_impl.h
index 90852b62a78..14f9758e4e3 100644
--- a/chromium/components/viz/service/display_embedder/compositing_mode_reporter_impl.h
+++ b/chromium/components/viz/service/display_embedder/compositing_mode_reporter_impl.h
@@ -9,7 +9,7 @@
#include "components/viz/service/viz_service_export.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
-#include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
+#include "services/viz/public/mojom/compositing/compositing_mode_watcher.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/display_embedder/direct_context_provider.cc b/chromium/components/viz/service/display_embedder/direct_context_provider.cc
index 8d0a7166e7b..4e4d5048af8 100644
--- a/chromium/components/viz/service/display_embedder/direct_context_provider.cc
+++ b/chromium/components/viz/service/display_embedder/direct_context_provider.cc
@@ -22,6 +22,7 @@
#include "gpu/command_buffer/service/command_buffer_direct.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/memory_tracking.h"
+#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/config/gpu_feature_info.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
@@ -43,9 +44,10 @@ DirectContextProvider::DirectContextProvider(
auto limits = gpu::SharedMemoryLimits::ForMailboxContext();
auto group = base::MakeRefCounted<gpu::gles2::ContextGroup>(
- gpu_preferences, true, &mailbox_manager_, /*memory_tracker=*/nullptr,
- &translator_cache_, &completeness_cache_, feature_info, true,
- &image_manager_, /*image_factory=*/nullptr,
+ gpu_preferences, gpu::gles2::PassthroughCommandDecoderSupported(),
+ &mailbox_manager_, /*memory_tracker=*/nullptr, &translator_cache_,
+ &completeness_cache_, feature_info, true, &image_manager_,
+ /*image_factory=*/nullptr,
/*progress_reporter=*/nullptr, gpu_feature_info_, &discardable_manager_,
&passthrough_discardable_manager_, delegate_->GetSharedImageManager());
@@ -153,6 +155,19 @@ void DirectContextProvider::SetGLRendererCopierRequiredState(
decoder_->RestoreGlobalState();
decoder_->RestoreBufferBindings();
+ // At this point |decoder_| cached state (if any, passthrough doesn't cache)
+ // is synced with GLContext state. But GLES2Implementation caches some state
+ // too and we need to make sure this are in sync with |decoder_| and context
+ constexpr static std::initializer_list<GLuint> caps = {
+ GL_SCISSOR_TEST, GL_STENCIL_TEST, GL_BLEND};
+
+ for (auto cap : caps) {
+ if (gles2_implementation_->IsEnabled(cap))
+ gles2_cmd_helper_->Enable(cap);
+ else
+ gles2_cmd_helper_->Disable(cap);
+ }
+
if (texture_client_id) {
if (!framebuffer_id_)
gles2_implementation_->GenFramebuffers(1, &framebuffer_id_);
diff --git a/chromium/components/viz/service/display_embedder/image_context.cc b/chromium/components/viz/service/display_embedder/image_context.cc
deleted file mode 100644
index cc894f7a69a..00000000000
--- a/chromium/components/viz/service/display_embedder/image_context.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/service/display_embedder/image_context.h"
-
-#include "gpu/command_buffer/service/shared_image_representation.h"
-#include "third_party/skia/include/core/SkPromiseImageTexture.h"
-
-namespace viz {
-
-ImageContext::ImageContext(const gpu::Mailbox& mailbox,
- const gfx::Size& size,
- ResourceFormat resource_format,
- sk_sp<SkColorSpace> color_space,
- SkAlphaType alpha_type,
- GrSurfaceOrigin origin,
- const gpu::SyncToken& sync_token)
- : mailbox(mailbox),
- size(size),
- resource_format(resource_format),
- color_space(std::move(color_space)),
- alpha_type(alpha_type),
- origin(origin),
- sync_token(sync_token) {}
-
-ImageContext::ImageContext(const ResourceMetadata& metadata)
- : ImageContext(metadata.mailbox_holder.mailbox,
- metadata.size,
- metadata.resource_format,
- metadata.color_space.ToSkColorSpace(),
- metadata.alpha_type,
- metadata.origin,
- metadata.mailbox_holder.sync_token) {}
-
-ImageContext::ImageContext(RenderPassId render_pass_id,
- const gfx::Size& size,
- ResourceFormat resource_format,
- bool mipmap,
- sk_sp<SkColorSpace> color_space)
- : render_pass_id(render_pass_id),
- size(size),
- resource_format(resource_format),
- mipmap(mipmap ? GrMipMapped::kYes : GrMipMapped::kNo),
- color_space(std::move(color_space)) {}
-
-ImageContext::~ImageContext() {
- DCHECK(!representation_is_being_accessed);
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/image_context.h b/chromium/components/viz/service/display_embedder/image_context.h
deleted file mode 100644
index 5fb58e62b24..00000000000
--- a/chromium/components/viz/service/display_embedder/image_context.h
+++ /dev/null
@@ -1,87 +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 COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_H_
-#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/viz/common/quads/render_pass.h"
-#include "components/viz/common/resources/resource_format.h"
-#include "components/viz/service/display/resource_metadata.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "third_party/skia/include/core/SkImageInfo.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-#include "third_party/skia/include/gpu/GrBackendSurface.h"
-#include "third_party/skia/include/gpu/GrTypes.h"
-#include "ui/gfx/geometry/size.h"
-
-class SkColorSpace;
-class SkPromiseImageTexture;
-
-namespace gpu {
-class SharedImageRepresentationSkia;
-}
-
-namespace viz {
-
-// Contex for hold promise image related properties.
-struct ImageContext {
- ImageContext(const gpu::Mailbox& mailbox,
- const gfx::Size& size,
- ResourceFormat resource_format,
- sk_sp<SkColorSpace> color_space,
- SkAlphaType alpha_type,
- GrSurfaceOrigin origin,
- const gpu::SyncToken& sync_token);
- explicit ImageContext(const ResourceMetadata& metadata);
- ImageContext(RenderPassId render_pass_id,
- const gfx::Size& size,
- ResourceFormat resource_format,
- bool mipmap,
- sk_sp<SkColorSpace> color_space);
- ~ImageContext();
-
- // Properties for promise images which are created from a resource.
- const gpu::Mailbox mailbox;
-
- // Properties for promise images which are created from a render pass.
- const RenderPassId render_pass_id = 0;
-
- // Const properties which can be accessed by display and GPU threads.
- const gfx::Size size;
- const ResourceFormat resource_format;
- const GrMipMapped mipmap = GrMipMapped::kNo;
- const sk_sp<SkColorSpace> color_space;
- const SkAlphaType alpha_type = kPremul_SkAlphaType;
- const GrSurfaceOrigin origin = kTopLeft_GrSurfaceOrigin;
-
- // The promise image which is used on display thread.
- sk_sp<SkImage> image;
-
- // Fallback in case we cannot produce a |representation|.
- GrBackendTexture fallback_texture;
-
- // |sync_token| is only accessed on display thread.
- gpu::SyncToken sync_token;
-
- // SharedImage |representation| is only accessed on GPU thread.
- std::unique_ptr<gpu::SharedImageRepresentationSkia> representation;
-
- // |representation_is_being_accessed| is used on GPU thread only.
- bool representation_is_being_accessed = false;
-
- // The |promise_image_texture| is used for fulfilling the promise image. It is
- // used on GPU thread.
- sk_sp<SkPromiseImageTexture> promise_image_texture;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ImageContext);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_H_
diff --git a/chromium/components/viz/service/display_embedder/image_context_impl.cc b/chromium/components/viz/service/display_embedder/image_context_impl.cc
new file mode 100644
index 00000000000..629121b0793
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/image_context_impl.cc
@@ -0,0 +1,217 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/service/display_embedder/image_context_impl.h"
+
+#include <utility>
+
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/shared_context_state.h"
+#include "gpu/command_buffer/service/shared_image_factory.h"
+#include "gpu/command_buffer/service/skia_utils.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkPromiseImageTexture.h"
+
+namespace viz {
+
+ImageContextImpl::ImageContextImpl(const gpu::MailboxHolder& mailbox_holder,
+ const gfx::Size& size,
+ ResourceFormat resource_format,
+ sk_sp<SkColorSpace> color_space)
+ : ImageContext(mailbox_holder, size, resource_format, color_space) {}
+
+ImageContextImpl::ImageContextImpl(RenderPassId render_pass_id,
+ const gfx::Size& size,
+ ResourceFormat resource_format,
+ bool mipmap,
+ sk_sp<SkColorSpace> color_space)
+ : ImageContext(gpu::MailboxHolder(),
+ size,
+ resource_format,
+ std::move(color_space)),
+ render_pass_id_(render_pass_id),
+ mipmap_(mipmap ? GrMipMapped::kYes : GrMipMapped::kNo) {}
+
+ImageContextImpl::~ImageContextImpl() {
+ DCHECK(!representation_scoped_read_access_);
+
+ if (fallback_context_state_)
+ gpu::DeleteGrBackendTexture(fallback_context_state_, &fallback_texture_);
+}
+
+void ImageContextImpl::CreateFallbackImage(
+ gpu::SharedContextState* context_state) {
+ DCHECK(!fallback_context_state_);
+ fallback_context_state_ = context_state;
+
+ fallback_texture_ =
+ fallback_context_state_->gr_context()->createBackendTexture(
+ size().width(), size().height(), backend_format(),
+#if DCHECK_IS_ON()
+ SkColors::kRed,
+#else
+ SkColors::kWhite,
+#endif
+ GrMipMapped::kNo, GrRenderable::kYes);
+
+ if (!fallback_texture_.isValid()) {
+ DLOG(ERROR) << "Could not create backend texture.";
+ return;
+ }
+ set_promise_image_texture(SkPromiseImageTexture::Make(fallback_texture_));
+}
+
+void ImageContextImpl::BeginAccessIfNecessary(
+ gpu::SharedContextState* context_state,
+ gpu::SharedImageRepresentationFactory* representation_factory,
+ gpu::MailboxManager* mailbox_manager,
+ std::vector<GrBackendSemaphore>* begin_semaphores,
+ std::vector<GrBackendSemaphore>* end_semaphores) {
+ // Prepare for accessing shared image.
+ if (mailbox_holder().mailbox.IsSharedImage()) {
+ // Skip the context if it has been processed.
+ if (representation_scoped_read_access_) {
+ DCHECK(!owned_promise_image_texture_);
+ DCHECK(promise_image_texture_);
+ return;
+ }
+
+ // promise_image_texture_ is not null here, it means we are using a fallback
+ // image.
+ if (promise_image_texture_) {
+ DCHECK(owned_promise_image_texture_);
+ return;
+ }
+
+ if (!representation_) {
+ auto representation = representation_factory->ProduceSkia(
+ mailbox_holder().mailbox, context_state);
+ if (!representation) {
+ DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
+ "mailbox not found in SharedImageManager.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+
+ if (!(representation->usage() & gpu::SHARED_IMAGE_USAGE_DISPLAY)) {
+ DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
+ "was not created with display usage.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+
+ if (representation->size() != size()) {
+ DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
+ "size does not match TransferableResource size.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+
+ representation_ = std::move(representation);
+ }
+
+ representation_scoped_read_access_.emplace(
+ representation_.get(), begin_semaphores, end_semaphores);
+ if (!representation_scoped_read_access_->success()) {
+ representation_scoped_read_access_.reset();
+ representation_ = nullptr;
+ DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
+ "begin read access failed..";
+ CreateFallbackImage(context_state);
+ return;
+ }
+ promise_image_texture_ =
+ representation_scoped_read_access_->promise_image_texture();
+ return;
+ }
+
+ // Prepare for accessing legacy mailbox.
+ // The promise image has been fulfilled once, so we do need do anything.
+ if (promise_image_texture_)
+ return;
+
+ if (!context_state->GrContextIsGL()) {
+ // Probably this texture is created with wrong interface
+ // (GLES2Interface).
+ DLOG(ERROR) << "Failed to fulfill the promise texture whose backend is not "
+ "compatible with vulkan.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+
+ auto* texture_base =
+ mailbox_manager->ConsumeTexture(mailbox_holder().mailbox);
+ if (!texture_base) {
+ DLOG(ERROR) << "Failed to fulfill the promise texture.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+
+ gfx::Size texture_size;
+ if (BindOrCopyTextureIfNecessary(texture_base, &texture_size) &&
+ texture_size != size()) {
+ DLOG(ERROR) << "Failed to fulfill the promise texture - texture "
+ "size does not match TransferableResource size.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+
+ GrBackendTexture backend_texture;
+ gpu::GetGrBackendTexture(
+ context_state->feature_info(), texture_base->target(), size(),
+ texture_base->service_id(), resource_format(), &backend_texture);
+ if (!backend_texture.isValid()) {
+ DLOG(ERROR) << "Failed to fulfill the promise texture.";
+ CreateFallbackImage(context_state);
+ return;
+ }
+ set_promise_image_texture(SkPromiseImageTexture::Make(backend_texture));
+}
+
+bool ImageContextImpl::BindOrCopyTextureIfNecessary(
+ gpu::TextureBase* texture_base,
+ gfx::Size* size) {
+ if (texture_base->GetType() != gpu::TextureBase::Type::kValidated)
+ return false;
+ // If a texture is validated and bound to an image, we may defer copying the
+ // image to the texture until the texture is used. It is for implementing low
+ // latency drawing (e.g. fast ink) and avoiding unnecessary texture copy. So
+ // we need check the texture image state, and bind or copy the image to the
+ // texture if necessary.
+ auto* texture = gpu::gles2::Texture::CheckedCast(texture_base);
+ gpu::gles2::Texture::ImageState image_state;
+ auto* image = texture->GetLevelImage(GL_TEXTURE_2D, 0, &image_state);
+ if (image && image_state == gpu::gles2::Texture::UNBOUND) {
+ glBindTexture(texture_base->target(), texture_base->service_id());
+ if (image->ShouldBindOrCopy() == gl::GLImage::BIND) {
+ if (!image->BindTexImage(texture_base->target())) {
+ LOG(ERROR) << "Failed to bind a gl image to texture.";
+ return false;
+ }
+ } else {
+ texture->SetLevelImageState(texture_base->target(), 0,
+ gpu::gles2::Texture::COPIED);
+ if (!image->CopyTexImage(texture_base->target())) {
+ LOG(ERROR) << "Failed to copy a gl image to texture.";
+ return false;
+ }
+ }
+ }
+ GLsizei temp_width, temp_height;
+ texture->GetLevelSize(texture_base->target(), 0 /* level */, &temp_width,
+ &temp_height, nullptr /* depth */);
+ *size = gfx::Size(temp_width, temp_height);
+ return true;
+}
+
+void ImageContextImpl::EndAccessIfNecessary() {
+ if (!representation_scoped_read_access_)
+ return;
+ representation_scoped_read_access_.reset();
+ promise_image_texture_ = nullptr;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/image_context_impl.h b/chromium/components/viz/service/display_embedder/image_context_impl.h
new file mode 100644
index 00000000000..e56c19873af
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/image_context_impl.h
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_IMPL_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_IMPL_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "components/viz/common/quads/render_pass.h"
+#include "components/viz/common/resources/resource_format.h"
+#include "components/viz/service/display/external_use_client.h"
+#include "gpu/command_buffer/common/mailbox_holder.h"
+#include "gpu/command_buffer/service/shared_image_representation.h"
+#include "gpu/ipc/common/vulkan_ycbcr_info.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
+#include "third_party/skia/include/gpu/GrTypes.h"
+#include "ui/gfx/geometry/size.h"
+
+class SkColorSpace;
+class SkPromiseImageTexture;
+
+namespace gpu {
+class MailboxManager;
+class SharedContextState;
+class SharedImageRepresentationFactory;
+class TextureBase;
+} // namespace gpu
+
+namespace viz {
+
+// ImageContext can be accessed by compositor and GPU thread. It is a complete
+// enough implementation for use in tests by FakeSkiaOutputSurface.
+//
+// ImageContextImpl adds functionality for use by SkiaOutputSurfaceImpl and
+// SkiaOutputSurfaceImplOnGpu. {Begin,End}Access is called from the GPU thread.
+class ImageContextImpl final : public ExternalUseClient::ImageContext {
+ public:
+ ImageContextImpl(const gpu::MailboxHolder& mailbox_holder,
+ const gfx::Size& size,
+ ResourceFormat resource_format,
+ sk_sp<SkColorSpace> color_space);
+
+ // TODO(https://crbug.com/991659): The use of ImageContext for
+ // SkiaOutputSurfaceImplOnGpu::OffscreenSurface can be factored out. This
+ // would make ImageContextImpl cleaner and handling of render passes less
+ // confusing.
+ ImageContextImpl(RenderPassId render_pass_id,
+ const gfx::Size& size,
+ ResourceFormat resource_format,
+ bool mipmap,
+ sk_sp<SkColorSpace> color_space);
+ ~ImageContextImpl() final;
+
+ RenderPassId render_pass_id() const { return render_pass_id_; }
+ GrMipMapped mipmap() const { return mipmap_; }
+
+ void set_promise_image_texture(
+ sk_sp<SkPromiseImageTexture> promise_image_texture) {
+ owned_promise_image_texture_ = std::move(promise_image_texture);
+ promise_image_texture_ = owned_promise_image_texture_.get();
+ }
+ SkPromiseImageTexture* promise_image_texture() const {
+ return promise_image_texture_;
+ }
+
+ void BeginAccessIfNecessary(
+ gpu::SharedContextState* context_state,
+ gpu::SharedImageRepresentationFactory* representation_factory,
+ gpu::MailboxManager* mailbox_manager,
+ std::vector<GrBackendSemaphore>* begin_semaphores,
+ std::vector<GrBackendSemaphore>* end_semaphores);
+ void EndAccessIfNecessary();
+
+ private:
+ void CreateFallbackImage(gpu::SharedContextState* context_state);
+
+ // Returns true if |texture_base| is a gles2::Texture and all necessary
+ // operations completed successfully. In this case, |*size| is the size of
+ // of level 0.
+ bool BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base,
+ gfx::Size* size);
+
+ const RenderPassId render_pass_id_ = 0;
+ const GrMipMapped mipmap_ = GrMipMapped::kNo;
+
+ // Fallback in case we cannot produce a |representation_|.
+ gpu::SharedContextState* fallback_context_state_ = nullptr;
+ GrBackendTexture fallback_texture_;
+
+ std::unique_ptr<gpu::SharedImageRepresentationSkia> representation_;
+
+ // For scoped read accessing |representation|. It is only accessed on GPU
+ // thread.
+ base::Optional<gpu::SharedImageRepresentationSkia::ScopedReadAccess>
+ representation_scoped_read_access_;
+
+ // For holding SkPromiseImageTexture create from |fallback_texture| or legacy
+ // mailbox.
+ sk_sp<SkPromiseImageTexture> owned_promise_image_texture_;
+
+ // The |promise_image_texture| is used for fulfilling the promise image. It is
+ // used on GPU thread.
+ SkPromiseImageTexture* promise_image_texture_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageContextImpl);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_IMAGE_CONTEXT_IMPL_H_
diff --git a/chromium/components/viz/service/display_embedder/output_surface_provider.h b/chromium/components/viz/service/display_embedder/output_surface_provider.h
index 95dbcb66272..7833b197842 100644
--- a/chromium/components/viz/service/display_embedder/output_surface_provider.h
+++ b/chromium/components/viz/service/display_embedder/output_surface_provider.h
@@ -8,7 +8,7 @@
#include <memory>
#include "gpu/ipc/common/surface_handle.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/display_embedder/output_surface_provider_impl.cc b/chromium/components/viz/service/display_embedder/output_surface_provider_impl.cc
index 7f61cb7c847..e3c8e9dbca6 100644
--- a/chromium/components/viz/service/display_embedder/output_surface_provider_impl.cc
+++ b/chromium/components/viz/service/display_embedder/output_surface_provider_impl.cc
@@ -30,6 +30,7 @@
#include "gpu/config/gpu_finch_features.h"
#include "gpu/ipc/command_buffer_task_executor.h"
#include "gpu/ipc/common/surface_handle.h"
+#include "gpu/ipc/scheduler_sequence.h"
#include "gpu/ipc/service/gpu_channel_manager_delegate.h"
#include "gpu/ipc/service/image_transport_surface.h"
#include "ui/base/ui_base_switches.h"
@@ -117,10 +118,13 @@ std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
NOTIMPLEMENTED();
return nullptr;
#else
- output_surface = SkiaOutputSurfaceImpl::Create(
- std::make_unique<SkiaOutputSurfaceDependencyImpl>(gpu_service_impl_,
- surface_handle),
- renderer_settings);
+ {
+ gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
+ output_surface = SkiaOutputSurfaceImpl::Create(
+ std::make_unique<SkiaOutputSurfaceDependencyImpl>(gpu_service_impl_,
+ surface_handle),
+ renderer_settings);
+ }
if (!output_surface) {
#if defined(OS_CHROMEOS) || defined(IS_CHROMECAST)
// GPU compositing is expected to always work on Chrome OS so we should
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.cc b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.cc
index 0dde3435751..66b6a78c257 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.cc
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.cc
@@ -30,6 +30,7 @@ void OverlayCandidateValidatorAndroid::InitializeStrategies() {
}
void OverlayCandidateValidatorAndroid::CheckOverlaySupport(
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidates) {
// There should only be at most a single overlay candidate: the video quad.
// There's no check that the presented candidate is really a video frame for
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.h b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.h
index b877843b937..68379c47fa7 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.h
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_android.h
@@ -26,7 +26,8 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidatorAndroid
~OverlayCandidateValidatorAndroid() override;
void InitializeStrategies() override;
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override;
bool AllowCALayerOverlays() const override;
bool AllowDCLayerOverlays() const override;
bool NeedsSurfaceOccludingDamageRect() const override;
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.cc b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.cc
index c95051a29b5..3e74eba896a 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.cc
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.cc
@@ -27,6 +27,7 @@ bool OverlayCandidateValidatorMac::NeedsSurfaceOccludingDamageRect() const {
}
void OverlayCandidateValidatorMac::CheckOverlaySupport(
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* surfaces) {}
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.h b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.h
index 7dce043316b..4c6b26f02fe 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.h
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_mac.h
@@ -23,7 +23,8 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidatorMac
bool AllowCALayerOverlays() const override;
bool AllowDCLayerOverlays() const override;
bool NeedsSurfaceOccludingDamageRect() const override;
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override;
private:
const bool ca_layer_disabled_;
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.cc b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.cc
index 53870e28b93..900aa8bae88 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.cc
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.cc
@@ -12,9 +12,42 @@
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
+#include "ui/gfx/geometry/rect_conversions.h"
namespace viz {
+namespace {
+
+// TODO(weiliangc): When difference between primary plane and non-primary plane
+// can be internalized, merge these two helper functions.
+void ConvertToOzoneOverlaySurface(
+ const OverlayCandidateValidatorOzone::PrimaryPlane& primary_plane,
+ ui::OverlaySurfaceCandidate* ozone_candidate) {
+ ozone_candidate->transform = primary_plane.transform;
+ ozone_candidate->format = primary_plane.format;
+ ozone_candidate->display_rect = primary_plane.display_rect;
+ ozone_candidate->crop_rect = gfx::RectF(0.f, 0.f, 1.f, 1.f);
+ ozone_candidate->clip_rect = gfx::ToEnclosingRect(primary_plane.display_rect);
+ ozone_candidate->is_clipped = false;
+ ozone_candidate->plane_z_order = 0;
+ ozone_candidate->buffer_size = primary_plane.resource_size;
+}
+
+void ConvertToOzoneOverlaySurface(
+ const OverlayCandidate& overlay_candidate,
+ ui::OverlaySurfaceCandidate* ozone_candidate) {
+ ozone_candidate->transform = overlay_candidate.transform;
+ ozone_candidate->format = overlay_candidate.format;
+ ozone_candidate->display_rect = overlay_candidate.display_rect;
+ ozone_candidate->crop_rect = overlay_candidate.uv_rect;
+ ozone_candidate->clip_rect = overlay_candidate.clip_rect;
+ ozone_candidate->is_clipped = overlay_candidate.is_clipped;
+ ozone_candidate->plane_z_order = overlay_candidate.plane_z_order;
+ ozone_candidate->buffer_size = overlay_candidate.resource_size_in_pixels;
+}
+
+} // namespace
+
// |overlay_candidates| is an object used to answer questions about possible
// overlays configurations.
// |available_strategies| is a list of overlay strategies that should be
@@ -64,6 +97,7 @@ bool OverlayCandidateValidatorOzone::NeedsSurfaceOccludingDamageRect() const {
}
void OverlayCandidateValidatorOzone::CheckOverlaySupport(
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* surfaces) {
// SW mirroring copies out of the framebuffer, so we can't remove any
// quads for overlaying, otherwise the output is incorrect.
@@ -74,28 +108,53 @@ void OverlayCandidateValidatorOzone::CheckOverlaySupport(
return;
}
- DCHECK_GE(2U, surfaces->size());
- ui::OverlayCandidatesOzone::OverlaySurfaceCandidateList ozone_surface_list;
- ozone_surface_list.resize(surfaces->size());
-
- for (size_t i = 0; i < surfaces->size(); i++) {
- ozone_surface_list.at(i).transform = surfaces->at(i).transform;
- ozone_surface_list.at(i).format = surfaces->at(i).format;
- ozone_surface_list.at(i).display_rect = surfaces->at(i).display_rect;
- ozone_surface_list.at(i).crop_rect = surfaces->at(i).uv_rect;
- ozone_surface_list.at(i).clip_rect = surfaces->at(i).clip_rect;
- ozone_surface_list.at(i).is_clipped = surfaces->at(i).is_clipped;
- ozone_surface_list.at(i).plane_z_order = surfaces->at(i).plane_z_order;
- ozone_surface_list.at(i).buffer_size =
- surfaces->at(i).resource_size_in_pixels;
- }
+ // This number is depended on what type of strategies we have. Currently we
+ // only overlay one video.
+ DCHECK_EQ(1U, surfaces->size());
+ auto full_size = surfaces->size();
+ if (primary_plane)
+ full_size += 1;
+
+ ui::OverlayCandidatesOzone::OverlaySurfaceCandidateList ozone_surface_list(
+ full_size);
+ // Convert OverlayCandidateList to OzoneSurfaceCandidateList.
+ {
+ auto ozone_surface_iterator = ozone_surface_list.begin();
+
+ // For ozone-cast, there will not be a primary_plane.
+ if (primary_plane) {
+ ConvertToOzoneOverlaySurface(*primary_plane, &(*ozone_surface_iterator));
+ ozone_surface_iterator++;
+ }
+
+ auto surface_iterator = surfaces->cbegin();
+ for (; ozone_surface_iterator < ozone_surface_list.end() &&
+ surface_iterator < surfaces->cend();
+ ozone_surface_iterator++, surface_iterator++) {
+ ConvertToOzoneOverlaySurface(*surface_iterator,
+ &(*ozone_surface_iterator));
+ }
+ }
overlay_candidates_->CheckOverlaySupport(&ozone_surface_list);
- DCHECK_EQ(surfaces->size(), ozone_surface_list.size());
- for (size_t i = 0; i < surfaces->size(); i++) {
- surfaces->at(i).overlay_handled = ozone_surface_list.at(i).overlay_handled;
- surfaces->at(i).display_rect = ozone_surface_list.at(i).display_rect;
+ // Copy information from OzoneSurfaceCandidatelist back to
+ // OverlayCandidateList.
+ {
+ DCHECK_EQ(full_size, ozone_surface_list.size());
+ auto ozone_surface_iterator = ozone_surface_list.cbegin();
+ // The primary plane is always handled, and don't need to copy information.
+ if (primary_plane)
+ ozone_surface_iterator++;
+
+ auto surface_iterator = surfaces->begin();
+ for (; surface_iterator < surfaces->end() &&
+ ozone_surface_iterator < ozone_surface_list.cend();
+ surface_iterator++, ozone_surface_iterator++) {
+ surface_iterator->overlay_handled =
+ ozone_surface_iterator->overlay_handled;
+ surface_iterator->display_rect = ozone_surface_iterator->display_rect;
+ }
}
}
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.h b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.h
index 31567d4f591..27b44e5bd52 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.h
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_ozone.h
@@ -30,7 +30,8 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidatorOzone
bool AllowCALayerOverlays() const override;
bool AllowDCLayerOverlays() const override;
bool NeedsSurfaceOccludingDamageRect() const override;
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override;
void SetSoftwareMirrorMode(bool enabled) override;
private:
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.cc b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.cc
index c023b161ed9..afc8a2e55f2 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.cc
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.cc
@@ -56,23 +56,16 @@ bool OverlayCandidateValidatorSurfaceControl::NeedsSurfaceOccludingDamageRect()
}
void OverlayCandidateValidatorSurfaceControl::CheckOverlaySupport(
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* surfaces) {
DCHECK(!surfaces->empty());
for (auto& candidate : *surfaces) {
if (!gl::SurfaceControl::SupportsColorSpace(candidate.color_space)) {
- DCHECK(!candidate.use_output_surface_for_resource)
- << "The main overlay must only use color space supported by the "
- "device";
candidate.overlay_handled = false;
return;
}
- if (candidate.use_output_surface_for_resource) {
- AdjustOutputSurfaceOverlay(&candidate);
- continue;
- }
-
if (candidate.transform != display_transform_) {
candidate.overlay_handled = false;
return;
@@ -106,18 +99,23 @@ void OverlayCandidateValidatorSurfaceControl::CheckOverlaySupport(
}
void OverlayCandidateValidatorSurfaceControl::AdjustOutputSurfaceOverlay(
- OverlayCandidate* candidate) {
- DCHECK_EQ(candidate->transform, gfx::OVERLAY_TRANSFORM_NONE);
- DCHECK(!candidate->is_clipped);
- DCHECK(candidate->display_rect == ClipFromOrigin(candidate->display_rect));
-
- candidate->transform = display_transform_;
+ PrimaryPlane* output_surface_plane) {
+ DCHECK(output_surface_plane);
+ DCHECK(
+ gl::SurfaceControl::SupportsColorSpace(output_surface_plane->color_space))
+ << "The main overlay must only use color space supported by the "
+ "device";
+
+ DCHECK_EQ(output_surface_plane->transform, gfx::OVERLAY_TRANSFORM_NONE);
+ DCHECK(output_surface_plane->display_rect ==
+ ClipFromOrigin(output_surface_plane->display_rect));
+
+ output_surface_plane->transform = display_transform_;
const gfx::Transform display_inverse = gfx::OverlayTransformToTransform(
gfx::InvertOverlayTransform(display_transform_), viewport_size_);
- display_inverse.TransformRect(&candidate->display_rect);
- candidate->display_rect =
- gfx::RectF(gfx::ToEnclosingRect(candidate->display_rect));
- candidate->overlay_handled = true;
+ display_inverse.TransformRect(&output_surface_plane->display_rect);
+ output_surface_plane->display_rect =
+ gfx::RectF(gfx::ToEnclosingRect(output_surface_plane->display_rect));
}
void OverlayCandidateValidatorSurfaceControl::SetDisplayTransform(
@@ -133,6 +131,8 @@ void OverlayCandidateValidatorSurfaceControl::SetViewportSize(
gfx::Rect
OverlayCandidateValidatorSurfaceControl::GetOverlayDamageRectForOutputSurface(
const OverlayCandidate& candidate) const {
+ // Should only be called after ProcessForOverlays on handled candidates.
+ DCHECK(candidate.overlay_handled);
// When the overlay is handled by the validator, we transform its display rect
// to the logical screen space (used by the ui when preparing the frame) that
// the SurfaceControl expects it to be in. So in order to provide a damage
@@ -140,11 +140,6 @@ OverlayCandidateValidatorSurfaceControl::GetOverlayDamageRectForOutputSurface(
// transformation.
// But only if the overlay is in handled state, since the modification above
// is only applied when we mark the overlay as handled.
- if (!candidate.overlay_handled) {
- return OverlayCandidateValidator::GetOverlayDamageRectForOutputSurface(
- candidate);
- }
-
gfx::Size viewport_size_pre_display_transform(viewport_size_.height(),
viewport_size_.width());
auto transform = gfx::OverlayTransformToTransform(
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.h b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.h
index 79fc57b5099..da94b832f29 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.h
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control.h
@@ -23,8 +23,9 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidatorSurfaceControl
bool AllowCALayerOverlays() const override;
bool AllowDCLayerOverlays() const override;
bool NeedsSurfaceOccludingDamageRect() const override;
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
- void AdjustOutputSurfaceOverlay(OverlayCandidate* candidate) override;
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override;
+ void AdjustOutputSurfaceOverlay(PrimaryPlane* output_surface_plane) override;
void SetDisplayTransform(gfx::OverlayTransform transform) override;
void SetViewportSize(const gfx::Size& viewport_size) override;
gfx::Rect GetOverlayDamageRectForOutputSurface(
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control_unittest.cc b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control_unittest.cc
index 5a36faacf66..8ef0985ea87 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_surface_control_unittest.cc
@@ -21,7 +21,7 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, NoClipOrNegativeOffset) {
candidates.push_back(candidate);
OverlayCandidateValidatorSurfaceControl validator;
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_TRUE(candidates.at(0).overlay_handled);
EXPECT_RECTF_EQ(candidates.at(0).display_rect, gfx::RectF(10.f, 10.f));
}
@@ -38,7 +38,7 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, Clipped) {
candidates.push_back(candidate);
OverlayCandidateValidatorSurfaceControl validator;
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_TRUE(candidates.at(0).overlay_handled);
EXPECT_RECTF_EQ(candidates.at(0).display_rect,
gfx::RectF(2.f, 2.f, 5.f, 5.f));
@@ -57,7 +57,7 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, NegativeOffset) {
candidates.push_back(candidate);
OverlayCandidateValidatorSurfaceControl validator;
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_TRUE(candidates.at(0).overlay_handled);
EXPECT_RECTF_EQ(candidates.at(0).display_rect,
gfx::RectF(0.f, 0.f, 8.f, 6.f));
@@ -76,7 +76,7 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, ClipAndNegativeOffset) {
candidates.push_back(candidate);
OverlayCandidateValidatorSurfaceControl validator;
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_TRUE(candidates.at(0).overlay_handled);
EXPECT_RECTF_EQ(candidates.at(0).display_rect,
gfx::RectF(0.f, 0.f, 5.f, 5.f));
@@ -87,7 +87,6 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, ClipAndNegativeOffset) {
TEST(OverlayCandidateValidatorSurfaceControlTest, DisplayTransformOverlay) {
OverlayCandidate candidate;
candidate.display_rect = gfx::RectF(10, 10, 50, 100);
- candidate.use_output_surface_for_resource = false;
candidate.overlay_handled = false;
OverlayCandidateList candidates;
@@ -100,11 +99,11 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, DisplayTransformOverlay) {
// First use a different transform than the display transform, the overlay is
// rejected.
candidates.back().transform = gfx::OVERLAY_TRANSFORM_NONE;
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_FALSE(candidates.back().overlay_handled);
candidates.back().transform = gfx::OVERLAY_TRANSFORM_ROTATE_90;
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_TRUE(candidates.back().overlay_handled);
EXPECT_EQ(candidates.back().transform, gfx::OVERLAY_TRANSFORM_NONE);
EXPECT_RECTF_EQ(candidates.back().display_rect, gfx::RectF(10, 40, 100, 50));
@@ -112,17 +111,14 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, DisplayTransformOverlay) {
TEST(OverlayCandidateValidatorSurfaceControlTest,
DisplayTransformOutputSurfaceOverlay) {
- OverlayCandidate candidate;
+ OverlayProcessor::OutputSurfaceOverlayPlane candidate;
candidate.display_rect = gfx::RectF(100, 200);
- candidate.use_output_surface_for_resource = true;
- candidate.overlay_handled = false;
candidate.transform = gfx::OVERLAY_TRANSFORM_NONE;
OverlayCandidateValidatorSurfaceControl validator;
validator.SetViewportSize(gfx::Size(100, 200));
validator.SetDisplayTransform(gfx::OVERLAY_TRANSFORM_ROTATE_90);
validator.AdjustOutputSurfaceOverlay(&candidate);
- EXPECT_TRUE(candidate.overlay_handled);
EXPECT_RECTF_EQ(candidate.display_rect, gfx::RectF(200, 100));
EXPECT_EQ(candidate.transform, gfx::OVERLAY_TRANSFORM_ROTATE_90);
}
@@ -130,7 +126,6 @@ TEST(OverlayCandidateValidatorSurfaceControlTest,
TEST(OverlayCandidateValidatorTest, OverlayDamageRectForOutputSurface) {
OverlayCandidate candidate;
candidate.display_rect = gfx::RectF(10, 10, 50, 100);
- candidate.use_output_surface_for_resource = false;
candidate.transform = gfx::OVERLAY_TRANSFORM_ROTATE_90;
candidate.overlay_handled = false;
@@ -138,12 +133,9 @@ TEST(OverlayCandidateValidatorTest, OverlayDamageRectForOutputSurface) {
validator.SetViewportSize(gfx::Size(100, 200));
validator.SetDisplayTransform(gfx::OVERLAY_TRANSFORM_ROTATE_90);
- EXPECT_EQ(validator.GetOverlayDamageRectForOutputSurface(candidate),
- gfx::Rect(10, 10, 50, 100));
-
OverlayCandidateList candidates;
candidates.push_back(candidate);
- validator.CheckOverlaySupport(&candidates);
+ validator.CheckOverlaySupport(nullptr, &candidates);
EXPECT_TRUE(candidates.back().overlay_handled);
EXPECT_RECTF_EQ(candidates.back().display_rect, gfx::RectF(10, 40, 100, 50));
EXPECT_EQ(validator.GetOverlayDamageRectForOutputSurface(candidates.back()),
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.cc b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.cc
index 5e365c1c4a5..e8213f27e3b 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.cc
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.cc
@@ -13,6 +13,7 @@ OverlayCandidateValidatorWin::OverlayCandidateValidatorWin() = default;
OverlayCandidateValidatorWin::~OverlayCandidateValidatorWin() = default;
void OverlayCandidateValidatorWin::CheckOverlaySupport(
+ const PrimaryPlane* primary_plane,
OverlayCandidateList* candidates) {
NOTIMPLEMENTED();
}
diff --git a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.h b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.h
index 1d51a7d01fa..f0e39720a5a 100644
--- a/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.h
+++ b/chromium/components/viz/service/display_embedder/overlay_candidate_validator_win.h
@@ -20,7 +20,8 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidatorWin
~OverlayCandidateValidatorWin() override;
// OverlayCandidateValidator implementation.
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(const PrimaryPlane* primary_plane,
+ OverlayCandidateList* surfaces) override;
bool AllowCALayerOverlays() const override;
bool AllowDCLayerOverlays() const override;
bool NeedsSurfaceOccludingDamageRect() const override;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device.cc b/chromium/components/viz/service/display_embedder/skia_output_device.cc
index f5c630816a0..7d59adec9cd 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device.cc
@@ -34,48 +34,36 @@ void SkiaOutputDevice::SetDrawRectangle(const gfx::Rect& draw_rectangle) {}
void SkiaOutputDevice::StartSwapBuffers(
base::Optional<BufferPresentedCallback> feedback) {
- DCHECK(!feedback_);
- DCHECK(!params_);
+ DCHECK_LT(static_cast<int>(pending_swaps_.size()),
+ capabilities_.max_frames_pending);
- feedback_ = std::move(feedback);
- params_.emplace();
- params_->swap_response.swap_id = ++swap_id_;
- params_->swap_response.timings.swap_start = base::TimeTicks::Now();
+ pending_swaps_.emplace(++swap_id_, std::move(feedback));
}
void SkiaOutputDevice::FinishSwapBuffers(
gfx::SwapResult result,
const gfx::Size& size,
std::vector<ui::LatencyInfo> latency_info) {
- DCHECK(params_);
+ DCHECK(!pending_swaps_.empty());
- params_->swap_response.result = result;
- params_->swap_response.timings.swap_end = base::TimeTicks::Now();
- did_swap_buffer_complete_callback_.Run(*params_, size);
+ const gpu::SwapBuffersCompleteParams& params =
+ pending_swaps_.front().Complete(result);
- if (feedback_) {
- std::move(*feedback_)
- .Run(gfx::PresentationFeedback(
- params_->swap_response.timings.swap_start,
- base::TimeDelta() /* interval */,
- params_->swap_response.result == gfx::SwapResult::SWAP_ACK
- ? 0
- : gfx::PresentationFeedback::Flags::kFailure));
- }
+ did_swap_buffer_complete_callback_.Run(params, size);
- feedback_.reset();
- auto& response = params_->swap_response;
+ pending_swaps_.front().CallFeedback();
for (auto& latency : latency_info) {
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, response.timings.swap_start);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT,
+ params.swap_response.timings.swap_start);
latency.AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_FRAME_SWAP_COMPONENT,
- response.timings.swap_end);
+ params.swap_response.timings.swap_end);
}
latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
- params_.reset();
+ pending_swaps_.pop();
}
void SkiaOutputDevice::EnsureBackbuffer() {}
@@ -89,4 +77,36 @@ std::unique_ptr<gfx::GpuFence> SkiaOutputDevice::SubmitOverlayGpuFence() {
return nullptr;
}
+SkiaOutputDevice::SwapInfo::SwapInfo(
+ uint64_t swap_id,
+ base::Optional<SkiaOutputDevice::BufferPresentedCallback> feedback)
+ : feedback_(std::move(feedback)) {
+ params_.swap_response.swap_id = swap_id;
+ params_.swap_response.timings.swap_start = base::TimeTicks::Now();
+}
+
+SkiaOutputDevice::SwapInfo::SwapInfo(SwapInfo&& other) = default;
+
+SkiaOutputDevice::SwapInfo::~SwapInfo() = default;
+
+const gpu::SwapBuffersCompleteParams& SkiaOutputDevice::SwapInfo::Complete(
+ gfx::SwapResult result) {
+ params_.swap_response.result = result;
+ params_.swap_response.timings.swap_end = base::TimeTicks::Now();
+
+ return params_;
+}
+
+void SkiaOutputDevice::SwapInfo::CallFeedback() {
+ if (feedback_) {
+ std::move(*feedback_)
+ .Run(gfx::PresentationFeedback(
+ params_.swap_response.timings.swap_start,
+ base::TimeDelta() /* interval */,
+ params_.swap_response.result == gfx::SwapResult::SWAP_ACK
+ ? 0
+ : gfx::PresentationFeedback::Flags::kFailure));
+ }
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device.h b/chromium/components/viz/service/display_embedder/skia_output_device.h
index 2eceb2466a2..dbd71757f30 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device.h
@@ -6,6 +6,7 @@
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_H_
#include "base/callback.h"
+#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/optional.h"
#include "components/viz/service/display/output_surface.h"
@@ -119,8 +120,21 @@ class SkiaOutputDevice {
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback_;
// Only valid between StartSwapBuffers and FinishSwapBuffers.
- base::Optional<BufferPresentedCallback> feedback_;
- base::Optional<gpu::SwapBuffersCompleteParams> params_;
+ class SwapInfo {
+ public:
+ SwapInfo(uint64_t swap_id,
+ base::Optional<BufferPresentedCallback> feedback);
+ SwapInfo(SwapInfo&& other);
+ ~SwapInfo();
+ const gpu::SwapBuffersCompleteParams& Complete(gfx::SwapResult result);
+ void CallFeedback();
+
+ private:
+ base::Optional<BufferPresentedCallback> feedback_;
+ gpu::SwapBuffersCompleteParams params_;
+ };
+
+ base::queue<SwapInfo> pending_swaps_;
ui::LatencyTracker latency_tracker_;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
index 367b8c39fc5..89cfe05d480 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -22,6 +22,139 @@ static constexpr uint32_t kSharedImageUsage =
gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY |
gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
+class SkiaOutputDeviceBufferQueue::Image {
+ public:
+ Image(gpu::SharedImageFactory* factory,
+ gpu::SharedImageRepresentationFactory* representation_factory);
+ ~Image();
+
+ bool Initialize(const gfx::Size& size,
+ const gfx::ColorSpace& color_space,
+ ResourceFormat format,
+ SkiaOutputSurfaceDependency* deps,
+ uint32_t shared_image_usage);
+
+ SkSurface* BeginWriteSkia();
+ void EndWriteSkia();
+ void BeginPresent();
+ void EndPresent();
+ gl::GLImage* GetGLImage() const;
+ std::unique_ptr<gfx::GpuFence> CreateFence();
+ void ResetFence();
+
+ private:
+ gpu::SharedImageFactory* const factory_;
+ gpu::SharedImageRepresentationFactory* const representation_factory_;
+ gpu::Mailbox mailbox_;
+
+ std::unique_ptr<gpu::SharedImageRepresentationSkia> skia_representation_;
+ std::unique_ptr<gpu::SharedImageRepresentationGLTexture> gl_representation_;
+ base::Optional<gpu::SharedImageRepresentationSkia::ScopedWriteAccess>
+ scoped_write_access_;
+ base::Optional<gpu::SharedImageRepresentationGLTexture::ScopedAccess>
+ scoped_read_access_;
+ std::vector<GrBackendSemaphore> end_semaphores_;
+ std::unique_ptr<gl::GLFence> fence_;
+
+ DISALLOW_COPY_AND_ASSIGN(Image);
+};
+
+SkiaOutputDeviceBufferQueue::Image::Image(
+ gpu::SharedImageFactory* factory,
+ gpu::SharedImageRepresentationFactory* representation_factory)
+ : factory_(factory), representation_factory_(representation_factory) {}
+
+SkiaOutputDeviceBufferQueue::Image::~Image() {
+ scoped_read_access_.reset();
+ scoped_write_access_.reset();
+ skia_representation_.reset();
+ gl_representation_.reset();
+
+ if (!mailbox_.IsZero())
+ factory_->DestroySharedImage(mailbox_);
+}
+
+bool SkiaOutputDeviceBufferQueue::Image::Initialize(
+ const gfx::Size& size,
+ const gfx::ColorSpace& color_space,
+ ResourceFormat format,
+ SkiaOutputSurfaceDependency* deps,
+ uint32_t shared_image_usage) {
+ mailbox_ = gpu::Mailbox::GenerateForSharedImage();
+ if (factory_->CreateSharedImage(mailbox_, format, size, color_space,
+ shared_image_usage)) {
+ skia_representation_ = representation_factory_->ProduceSkia(
+ mailbox_, deps->GetSharedContextState());
+ gl_representation_ = representation_factory_->ProduceGLTexture(mailbox_);
+
+ return true;
+ }
+
+ mailbox_.SetZero();
+ return false;
+}
+
+SkSurface* SkiaOutputDeviceBufferQueue::Image::BeginWriteSkia() {
+ DCHECK(!scoped_write_access_);
+ DCHECK(!scoped_read_access_);
+ DCHECK(end_semaphores_.empty());
+
+ std::vector<GrBackendSemaphore> begin_semaphores;
+ SkSurfaceProps surface_props{0, kUnknown_SkPixelGeometry};
+
+ // TODO(vasilyt): Props and MSAA
+ scoped_write_access_.emplace(skia_representation_.get(),
+ 0 /* final_msaa_count */, surface_props,
+ &begin_semaphores, &end_semaphores_);
+ DCHECK(scoped_write_access_->success());
+ if (!begin_semaphores.empty()) {
+ scoped_write_access_->surface()->wait(begin_semaphores.size(),
+ begin_semaphores.data());
+ }
+
+ return scoped_write_access_->surface();
+}
+
+void SkiaOutputDeviceBufferQueue::Image::EndWriteSkia() {
+ DCHECK(scoped_write_access_);
+ GrFlushInfo flush_info = {
+ .fFlags = kNone_GrFlushFlags,
+ .fNumSemaphores = end_semaphores_.size(),
+ .fSignalSemaphores = end_semaphores_.data(),
+ };
+ scoped_write_access_->surface()->flush(
+ SkSurface::BackendSurfaceAccess::kPresent, flush_info);
+ scoped_write_access_.reset();
+ end_semaphores_.clear();
+}
+
+void SkiaOutputDeviceBufferQueue::Image::BeginPresent() {
+ DCHECK(!scoped_write_access_);
+ DCHECK(!scoped_read_access_);
+ scoped_read_access_.emplace(gl_representation_.get(),
+ GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
+}
+
+void SkiaOutputDeviceBufferQueue::Image::EndPresent() {
+ DCHECK(scoped_read_access_);
+ scoped_read_access_.reset();
+ // If the GpuFence was created for ScheduleOverlayPlane we can release it now.
+ fence_.reset();
+ return;
+}
+
+gl::GLImage* SkiaOutputDeviceBufferQueue::Image::GetGLImage() const {
+ auto* texture = gl_representation_->GetTexture();
+ return texture->GetLevelImage(texture->target(), 0);
+}
+
+std::unique_ptr<gfx::GpuFence>
+SkiaOutputDeviceBufferQueue::Image::CreateFence() {
+ if (!fence_)
+ fence_ = gl::GLFence::CreateForGpuFence();
+ return fence_->GetGpuFence();
+}
+
SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
scoped_refptr<gl::GLSurface> gl_surface,
SkiaOutputSurfaceDependency* deps,
@@ -47,6 +180,7 @@ SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
// TODO(vasilyt): Need to figure out why partial swap isn't working
capabilities_.supports_post_sub_buffer = false;
+ capabilities_.max_frames_pending = 2;
}
SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
@@ -96,10 +230,8 @@ void SkiaOutputDeviceBufferQueue::PageFlipComplete() {
if (displayed_image_)
available_images_.push_back(std::move(displayed_image_));
displayed_image_ = std::move(in_flight_images_.front());
- // If the GpuFence was created for ScheduleOverlayPlane we can release it
- // now
if (displayed_image_)
- displayed_image_->ResetFence();
+ displayed_image_->EndPresent();
}
in_flight_images_.pop_front();
@@ -117,9 +249,8 @@ void SkiaOutputDeviceBufferQueue::FreeAllSurfaces() {
}
gl::GLImage* SkiaOutputDeviceBufferQueue::GetOverlayImage() {
- if (current_image_) {
- return current_image_->GetImage();
- }
+ if (current_image_)
+ return current_image_->GetGLImage();
return nullptr;
}
@@ -134,6 +265,10 @@ SkiaOutputDeviceBufferQueue::SubmitOverlayGpuFence() {
void SkiaOutputDeviceBufferQueue::SwapBuffers(
BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) {
+ // BeginPain() is not called after last SwapBuffer(), if |current_image_| is
+ // nullptr.
+ if (current_image_)
+ current_image_->BeginPresent();
in_flight_images_.push_back(std::move(current_image_));
StartSwapBuffers({});
@@ -204,7 +339,7 @@ void SkiaOutputDeviceBufferQueue::Reshape(const gfx::Size& size,
SkSurface* SkiaOutputDeviceBufferQueue::BeginPaint() {
auto* image = GetCurrentImage();
- return image->BeginWriteSkia().get();
+ return image->BeginWriteSkia();
}
void SkiaOutputDeviceBufferQueue::EndPaint(
const GrBackendSemaphore& semaphore) {
@@ -212,83 +347,4 @@ void SkiaOutputDeviceBufferQueue::EndPaint(
image->EndWriteSkia();
}
-sk_sp<SkSurface> SkiaOutputDeviceBufferQueue::Image::BeginWriteSkia() {
- std::vector<GrBackendSemaphore> begin_semaphores;
- DCHECK(end_semaphores_.empty());
- DCHECK(!sk_surface_);
-
- SkSurfaceProps surface_props{0, kUnknown_SkPixelGeometry};
-
- // TODO(vasilyt): Props and MSAA
- sk_surface_ = skia_representation_->BeginWriteAccess(
- 0, surface_props, &begin_semaphores, &end_semaphores_);
- if (!begin_semaphores.empty()) {
- sk_surface_->wait(begin_semaphores.size(), begin_semaphores.data());
- }
-
- return sk_surface_;
-}
-
-void SkiaOutputDeviceBufferQueue::Image::EndWriteSkia() {
- GrFlushInfo flush_info = {
- .fFlags = kNone_GrFlushFlags,
- .fNumSemaphores = end_semaphores_.size(),
- .fSignalSemaphores = end_semaphores_.data(),
- };
- sk_surface_->flush(SkSurface::BackendSurfaceAccess::kPresent, flush_info);
-
- skia_representation_->EndWriteAccess(std::move(sk_surface_));
-
- end_semaphores_.clear();
-}
-
-gl::GLImage* SkiaOutputDeviceBufferQueue::Image::GetImage() const {
- auto* texture = gl_representation_->GetTexture();
- return texture->GetLevelImage(texture->target(), 0);
-}
-
-bool SkiaOutputDeviceBufferQueue::Image::Initialize(
- const gfx::Size& size,
- const gfx::ColorSpace& color_space,
- ResourceFormat format,
- SkiaOutputSurfaceDependency* deps,
- uint32_t shared_image_usage) {
- mailbox = gpu::Mailbox::GenerateForSharedImage();
- if (factory_->CreateSharedImage(mailbox, format, size, color_space,
- shared_image_usage)) {
- skia_representation_ = representation_factory_->ProduceSkia(
- mailbox, deps->GetSharedContextState());
- gl_representation_ = representation_factory_->ProduceGLTexture(mailbox);
-
- return true;
- }
-
- mailbox.SetZero();
- return false;
-}
-
-SkiaOutputDeviceBufferQueue::Image::Image(
- gpu::SharedImageFactory* factory,
- gpu::SharedImageRepresentationFactory* representation_factory)
- : factory_(factory), representation_factory_(representation_factory) {}
-
-SkiaOutputDeviceBufferQueue::Image::~Image() {
- skia_representation_.reset();
- gl_representation_.reset();
-
- if (!mailbox.IsZero())
- factory_->DestroySharedImage(mailbox);
-}
-
-std::unique_ptr<gfx::GpuFence>
-SkiaOutputDeviceBufferQueue::Image::CreateFence() {
- if (!fence_)
- fence_ = gl::GLFence::CreateForGpuFence();
- return fence_->GetGpuFence();
-}
-
-void SkiaOutputDeviceBufferQueue::Image::ResetFence() {
- fence_.reset();
-}
-
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.h b/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
index 27dcea2acf5..1150fc46c74 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
@@ -11,12 +11,7 @@
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/service/shared_image_factory.h"
-namespace gpu {
-class SharedImageRepresentationSkia;
-} // namespace gpu
-
namespace gl {
-class GLFence;
class GLSurface;
} // namespace gl
@@ -58,36 +53,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final
private:
friend class SkiaOutputDeviceBufferQueueTest;
-
- class VIZ_SERVICE_EXPORT Image {
- public:
- Image(gpu::SharedImageFactory* factory,
- gpu::SharedImageRepresentationFactory* representation_factory);
- ~Image();
-
- bool Initialize(const gfx::Size& size,
- const gfx::ColorSpace& color_space,
- ResourceFormat format,
- SkiaOutputSurfaceDependency* deps,
- uint32_t shared_image_usage);
-
- sk_sp<SkSurface> BeginWriteSkia();
- void EndWriteSkia();
- gl::GLImage* GetImage() const;
- std::unique_ptr<gfx::GpuFence> CreateFence();
- void ResetFence();
-
- private:
- gpu::Mailbox mailbox;
- std::unique_ptr<gpu::SharedImageRepresentationSkia> skia_representation_;
- std::unique_ptr<gpu::SharedImageRepresentationGLTexture> gl_representation_;
- std::vector<GrBackendSemaphore> end_semaphores_;
- sk_sp<SkSurface> sk_surface_;
- std::unique_ptr<gl::GLFence> fence_;
-
- gpu::SharedImageFactory* factory_;
- gpu::SharedImageRepresentationFactory* representation_factory_;
- };
+ class Image;
Image* GetCurrentImage();
std::unique_ptr<Image> GetNextImage();
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_gl.cc b/chromium/components/viz/service/display_embedder/skia_output_device_gl.cc
index 55098e811ae..34cf99235a0 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_gl.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -28,8 +28,14 @@ SkiaOutputDeviceGL::SkiaOutputDeviceGL(
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback)
: SkiaOutputDevice(false /*need_swap_semaphore */,
did_swap_buffer_complete_callback),
- feature_info_(feature_info),
- gl_surface_(gl_surface) {}
+ gl_surface_(gl_surface) {
+ capabilities_.flipped_output_surface = gl_surface_->FlipsVertically();
+ capabilities_.supports_post_sub_buffer = gl_surface_->SupportsPostSubBuffer();
+ if (feature_info->workarounds()
+ .disable_post_sub_buffers_for_onscreen_surfaces)
+ capabilities_.supports_post_sub_buffer = false;
+ capabilities_.max_frames_pending = gl_surface->GetBufferCount() - 1;
+}
void SkiaOutputDeviceGL::Initialize(GrContext* gr_context,
gl::GLContext* gl_context) {
@@ -54,20 +60,10 @@ void SkiaOutputDeviceGL::Initialize(GrContext* gr_context,
}
CHECK_GL_ERROR();
supports_alpha_ = alpha_bits > 0;
-
- capabilities_.flipped_output_surface = gl_surface_->FlipsVertically();
- capabilities_.supports_post_sub_buffer = gl_surface_->SupportsPostSubBuffer();
- if (feature_info_->workarounds()
- .disable_post_sub_buffers_for_onscreen_surfaces)
- capabilities_.supports_post_sub_buffer = false;
}
SkiaOutputDeviceGL::~SkiaOutputDeviceGL() {}
-scoped_refptr<gl::GLSurface> SkiaOutputDeviceGL::gl_surface() {
- return gl_surface_;
-}
-
void SkiaOutputDeviceGL::Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
@@ -172,36 +168,4 @@ SkSurface* SkiaOutputDeviceGL::BeginPaint() {
void SkiaOutputDeviceGL::EndPaint(const GrBackendSemaphore& semaphore) {}
-#if defined(OS_WIN)
-void SkiaOutputDeviceGL::DidCreateAcceleratedSurfaceChildWindow(
- gpu::SurfaceHandle parent_window,
- gpu::SurfaceHandle child_window) {
- NOTREACHED();
-}
-#endif
-
-const gpu::gles2::FeatureInfo* SkiaOutputDeviceGL::GetFeatureInfo() const {
- return feature_info_.get();
-}
-
-const gpu::GpuPreferences& SkiaOutputDeviceGL::GetGpuPreferences() const {
- return gpu_preferences_;
-}
-
-void SkiaOutputDeviceGL::DidSwapBuffersComplete(
- gpu::SwapBuffersCompleteParams params) {
- // TODO(kylechar): Check if this is necessary.
-}
-
-void SkiaOutputDeviceGL::BufferPresented(
- const gfx::PresentationFeedback& feedback) {
- // TODO(kylechar): Check if this is necessary.
-}
-
-GpuVSyncCallback SkiaOutputDeviceGL::GetGpuVSyncCallback() {
- // TODO(sunnyps): Implement GpuVSync with SkiaRenderer.
- NOTIMPLEMENTED();
- return base::DoNothing::Repeatedly<base::TimeTicks, base::TimeDelta>();
-}
-
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_gl.h b/chromium/components/viz/service/display_embedder/skia_output_device_gl.h
index 0f11856e1a4..af8cd56bd75 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_gl.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_gl.h
@@ -12,8 +12,6 @@
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
-#include "gpu/config/gpu_preferences.h"
-#include "gpu/ipc/service/image_transport_surface_delegate.h"
class GrContext;
@@ -34,8 +32,7 @@ class FeatureInfo;
namespace viz {
-class SkiaOutputDeviceGL final : public SkiaOutputDevice,
- public gpu::ImageTransportSurfaceDelegate {
+class SkiaOutputDeviceGL final : public SkiaOutputDevice {
public:
SkiaOutputDeviceGL(
scoped_refptr<gl::GLSurface> gl_surface,
@@ -43,7 +40,6 @@ class SkiaOutputDeviceGL final : public SkiaOutputDevice,
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback);
~SkiaOutputDeviceGL() override;
- scoped_refptr<gl::GLSurface> gl_surface();
void Initialize(GrContext* gr_context, gl::GLContext* gl_context);
bool supports_alpha() {
DCHECK(gr_context_);
@@ -67,22 +63,7 @@ class SkiaOutputDeviceGL final : public SkiaOutputDevice,
SkSurface* BeginPaint() override;
void EndPaint(const GrBackendSemaphore& semaphore) override;
- // gpu::ImageTransportSurfaceDelegate implementation:
-#if defined(OS_WIN)
- void DidCreateAcceleratedSurfaceChildWindow(
- gpu::SurfaceHandle parent_window,
- gpu::SurfaceHandle child_window) override;
-#endif
- const gpu::gles2::FeatureInfo* GetFeatureInfo() const override;
- const gpu::GpuPreferences& GetGpuPreferences() const override;
- void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params) override;
- void BufferPresented(const gfx::PresentationFeedback& feedback) override;
- GpuVSyncCallback GetGpuVSyncCallback() override;
-
private:
- scoped_refptr<gpu::gles2::FeatureInfo> feature_info_;
- gpu::GpuPreferences gpu_preferences_;
-
scoped_refptr<gl::GLSurface> gl_surface_;
GrContext* gr_context_ = nullptr;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.cc
index 547911c8abf..075d613482f 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -6,24 +6,35 @@
#include <utility>
+#include "gpu/command_buffer/service/skia_utils.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace viz {
+namespace {
+
+// Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use
+// kRGBA_8888_SkColorType instead and initialize surface to opaque as necessary.
+constexpr SkColorType kSurfaceColorType = kRGBA_8888_SkColorType;
+
+} // namespace
+
SkiaOutputDeviceOffscreen::SkiaOutputDeviceOffscreen(
- GrContext* gr_context,
+ scoped_refptr<gpu::SharedContextState> context_state,
bool flipped,
bool has_alpha,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
: SkiaOutputDevice(false /*need_swap_semaphore */,
did_swap_buffer_complete_callback),
- gr_context_(gr_context),
+ context_state_(context_state),
has_alpha_(has_alpha) {
capabilities_.flipped_output_surface = flipped;
capabilities_.supports_post_sub_buffer = true;
}
-SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() = default;
+SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() {
+ DiscardBackbuffer();
+}
void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size,
float device_scale_factor,
@@ -32,36 +43,21 @@ void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size,
gfx::OverlayTransform transform) {
DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
- // Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use
- // kRGBA_8888_SkColorType instead and initialize surface to opaque alpha.
- image_info_ =
- SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType,
- has_alpha_ ? kPremul_SkAlphaType : kOpaque_SkAlphaType,
- color_space.ToSkColorSpace());
- sk_surface_ = SkSurface::MakeRenderTarget(
- gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
- capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
- : kBottomLeft_GrSurfaceOrigin,
- nullptr /* surfaceProps */);
- DCHECK(!!sk_surface_);
-
- if (!has_alpha_) {
- is_emulated_rgbx_ = true;
- // Initialize alpha channel to opaque.
- auto* canvas = sk_surface_->getCanvas();
- canvas->clear(SkColorSetARGB(255, 0, 0, 0));
- }
+ DiscardBackbuffer();
+ size_ = size;
+ sk_color_space_ = color_space.ToSkColorSpace();
+ EnsureBackbuffer();
}
void SkiaOutputDeviceOffscreen::SwapBuffers(
BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) {
// Reshape should have been called first.
- DCHECK(sk_surface_);
+ DCHECK(backend_texture_.isValid());
StartSwapBuffers(std::move(feedback));
FinishSwapBuffers(gfx::SwapResult::SWAP_ACK,
- gfx::Size(sk_surface_->width(), sk_surface_->height()),
+ gfx::Size(size_.width(), size_.height()),
std::move(latency_info));
}
@@ -73,23 +69,46 @@ void SkiaOutputDeviceOffscreen::PostSubBuffer(
}
void SkiaOutputDeviceOffscreen::EnsureBackbuffer() {
- if (!image_info_.isEmpty() && !sk_surface_) {
- sk_surface_ = SkSurface::MakeRenderTarget(
- gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
- capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
- : kBottomLeft_GrSurfaceOrigin,
- nullptr /* surfaceProps */);
+ // Ignore EnsureBackbuffer if Reshape has not been called yet.
+ if (size_.IsEmpty())
+ return;
+
+ if (has_alpha_) {
+ backend_texture_ = context_state_->gr_context()->createBackendTexture(
+ size_.width(), size_.height(), kSurfaceColorType, GrMipMapped::kNo,
+ GrRenderable::kYes);
+ } else {
+ is_emulated_rgbx_ = true;
+ // Initialize alpha channel to opaque.
+ backend_texture_ = context_state_->gr_context()->createBackendTexture(
+ size_.width(), size_.height(), kSurfaceColorType, SkColors::kBlack,
+ GrMipMapped::kNo, GrRenderable::kYes);
}
+ DCHECK(backend_texture_.isValid());
}
void SkiaOutputDeviceOffscreen::DiscardBackbuffer() {
- sk_surface_.reset();
+ if (backend_texture_.isValid()) {
+ sk_surface_.reset();
+ DeleteGrBackendTexture(context_state_.get(), &backend_texture_);
+ backend_texture_ = GrBackendTexture();
+ }
}
SkSurface* SkiaOutputDeviceOffscreen::BeginPaint() {
+ DCHECK(backend_texture_.isValid());
+ if (!sk_surface_) {
+ sk_surface_ = SkSurface::MakeFromBackendTexture(
+ context_state_->gr_context(), backend_texture_,
+ capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
+ : kBottomLeft_GrSurfaceOrigin,
+ 0 /* sampleCount */, kSurfaceColorType, sk_color_space_,
+ nullptr /* surfaceProps */);
+ }
return sk_surface_.get();
}
-void SkiaOutputDeviceOffscreen::EndPaint(const GrBackendSemaphore& semaphore) {}
+void SkiaOutputDeviceOffscreen::EndPaint(const GrBackendSemaphore& semaphore) {
+}
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.h b/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.h
index a1c5780b507..1d126478af0 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -5,18 +5,20 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_
+#include <vector>
+
#include "base/macros.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
+#include "gpu/command_buffer/service/shared_context_state.h"
+#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImageInfo.h"
-class GrContext;
-
namespace viz {
class SkiaOutputDeviceOffscreen : public SkiaOutputDevice {
public:
SkiaOutputDeviceOffscreen(
- GrContext* gr_context,
+ scoped_refptr<gpu::SharedContextState> context_state,
bool flipped,
bool has_alpha,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
@@ -39,13 +41,15 @@ class SkiaOutputDeviceOffscreen : public SkiaOutputDevice {
void EndPaint(const GrBackendSemaphore& semaphore) override;
protected:
- GrContext* const gr_context_;
+ scoped_refptr<gpu::SharedContextState> context_state_;
const bool has_alpha_;
sk_sp<SkSurface> sk_surface_;
+ GrBackendTexture backend_texture_;
bool supports_rgbx_ = true;
private:
- SkImageInfo image_info_;
+ gfx::Size size_;
+ sk_sp<SkColorSpace> sk_color_space_;
DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceOffscreen);
};
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.cc
index a07ff29cd74..4b3fc4e6dfe 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -96,7 +96,11 @@ SkSurface* SkiaOutputDeviceVulkan::BeginPaint() {
surface_format == VK_FORMAT_R8G8B8A8_UNORM);
GrVkImageInfo vk_image_info(
scoped_write_->image(), GrVkAlloc(), VK_IMAGE_TILING_OPTIMAL,
- scoped_write_->image_layout(), surface_format, 1 /* level_count */);
+ scoped_write_->image_layout(), surface_format, 1 /* level_count */,
+ VK_QUEUE_FAMILY_IGNORED,
+ vulkan_surface_->swap_chain()->use_protected_memory()
+ ? GrProtected::kYes
+ : GrProtected::kNo);
const auto& vk_image_size = vulkan_surface_->image_size();
GrBackendRenderTarget render_target(vk_image_size.width(),
vk_image_size.height(),
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_x11.cc b/chromium/components/viz/service/display_embedder/skia_output_device_x11.cc
index fec82e4297e..c2a9f301908 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_x11.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_x11.cc
@@ -16,10 +16,10 @@
namespace viz {
SkiaOutputDeviceX11::SkiaOutputDeviceX11(
- GrContext* gr_context,
+ scoped_refptr<gpu::SharedContextState> context_state,
gfx::AcceleratedWidget widget,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
- : SkiaOutputDeviceOffscreen(gr_context,
+ : SkiaOutputDeviceOffscreen(context_state,
true /* flipped */,
true /* has_alpha */,
did_swap_buffer_complete_callback),
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_x11.h b/chromium/components/viz/service/display_embedder/skia_output_device_x11.h
index 327eab49a96..4f9bec069e3 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_x11.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_x11.h
@@ -18,7 +18,7 @@ namespace viz {
class SkiaOutputDeviceX11 final : public SkiaOutputDeviceOffscreen {
public:
SkiaOutputDeviceX11(
- GrContext* gr_context,
+ scoped_refptr<gpu::SharedContextState> context_state,
gfx::AcceleratedWidget widget,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
~SkiaOutputDeviceX11() override;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc
index dc544b2562a..b21a1e82d27 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -20,13 +20,13 @@
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display/resource_metadata.h"
-#include "components/viz/service/display_embedder/image_context.h"
+#include "components/viz/service/display_embedder/image_context_impl.h"
#include "components/viz/service/display_embedder/skia_output_surface_dependency.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/service/scheduler.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
+#include "gpu/command_buffer/service/skia_utils.h"
#include "gpu/ipc/single_task_sequence.h"
#include "gpu/vulkan/buildflags.h"
#include "ui/gfx/skia_util.h"
@@ -39,8 +39,8 @@ namespace {
sk_sp<SkPromiseImageTexture> Fulfill(void* texture_context) {
DCHECK(texture_context);
- auto* image_context = static_cast<ImageContext*>(texture_context);
- return image_context->promise_image_texture;
+ auto* image_context = static_cast<ImageContextImpl*>(texture_context);
+ return sk_ref_sp(image_context->promise_image_texture());
}
void DoNothing(void* texture_context) {}
@@ -88,36 +88,25 @@ SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
recorder_.reset();
- std::vector<std::unique_ptr<ImageContext>> image_contexts;
- image_contexts.reserve(promise_image_cache_.size());
- for (auto& id_and_image_context : promise_image_cache_) {
- id_and_image_context.second->image = nullptr;
- image_contexts.push_back(std::move(id_and_image_context.second));
- }
-
- std::vector<std::unique_ptr<ImageContext>> render_pass_image_contexts;
+ std::vector<std::unique_ptr<ImageContextImpl>> render_pass_image_contexts;
render_pass_image_contexts.reserve(render_pass_image_cache_.size());
for (auto& id_and_image_context : render_pass_image_cache_) {
- id_and_image_context.second->image = nullptr;
+ id_and_image_context.second->clear_image();
render_pass_image_contexts.push_back(
std::move(id_and_image_context.second));
}
base::WaitableEvent event;
auto callback = base::BindOnce(
- [](std::vector<std::unique_ptr<ImageContext>> images,
- std::vector<std::unique_ptr<ImageContext>> render_passes,
+ [](std::vector<std::unique_ptr<ImageContextImpl>> render_passes,
std::unique_ptr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu,
base::WaitableEvent* event) {
- if (!images.empty())
- impl_on_gpu->ReleaseImageContexts(std::move(images));
if (!render_passes.empty())
impl_on_gpu->RemoveRenderPassResource(std::move(render_passes));
impl_on_gpu = nullptr;
event->Signal();
},
- std::move(image_contexts), std::move(render_pass_image_contexts),
- std::move(impl_on_gpu_), &event);
+ std::move(render_pass_image_contexts), std::move(impl_on_gpu_), &event);
ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
event.Wait();
@@ -138,11 +127,8 @@ void SkiaOutputSurfaceImpl::BindFramebuffer() {
void SkiaOutputSurfaceImpl::SetDrawRectangle(const gfx::Rect& draw_rectangle) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
- auto callback =
- base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SetDrawRectangle,
- base::Unretained(impl_on_gpu_.get()), draw_rectangle);
- ScheduleGpuTask(std::move(callback), {});
+ DCHECK(!draw_rectangle_);
+ draw_rectangle_.emplace(draw_rectangle);
}
void SkiaOutputSurfaceImpl::EnsureBackbuffer() {
@@ -151,7 +137,8 @@ void SkiaOutputSurfaceImpl::EnsureBackbuffer() {
// SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::EnsureBackbuffer,
base::Unretained(impl_on_gpu_.get()));
- ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
+ task_sequence_->ScheduleOrRetainTask(std::move(callback),
+ std::vector<gpu::SyncToken>());
}
void SkiaOutputSurfaceImpl::DiscardBackbuffer() {
@@ -160,7 +147,8 @@ void SkiaOutputSurfaceImpl::DiscardBackbuffer() {
// SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::DiscardBackbuffer,
base::Unretained(impl_on_gpu_.get()));
- ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
+ task_sequence_->ScheduleOrRetainTask(std::move(callback),
+ std::vector<gpu::SyncToken>());
}
void SkiaOutputSurfaceImpl::Reshape(const gfx::Size& size,
@@ -242,77 +230,73 @@ SkCanvas* SkiaOutputSurfaceImpl::BeginPaintCurrentFrame() {
return &nway_canvas_.value();
}
-sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImage(
- const ResourceMetadata& metadata) {
+void SkiaOutputSurfaceImpl::MakePromiseSkImage(ImageContext* image_context) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(recorder_);
- DCHECK(!metadata.mailbox_holder.mailbox.IsZero());
+ DCHECK(!image_context->mailbox_holder().mailbox.IsZero());
- auto& image_context = promise_image_cache_[metadata.resource_id];
- if (!image_context) {
- image_context = std::make_unique<ImageContext>(metadata);
- SkColorType color_type = ResourceFormatToClosestSkColorType(
- true /* gpu_compositing */, metadata.resource_format);
-
- GrBackendFormat backend_format = GetGrBackendFormatForTexture(
- metadata.resource_format, metadata.mailbox_holder.texture_target,
- metadata.ycbcr_info);
- image_context->image = recorder_->makePromiseTexture(
- backend_format, metadata.size.width(), metadata.size.height(),
- GrMipMapped::kNo, metadata.origin, color_type, metadata.alpha_type,
- image_context->color_space, Fulfill, DoNothing, DoNothing,
- image_context.get());
- DCHECK(image_context->image);
- }
+ images_in_current_paint_.push_back(
+ static_cast<ImageContextImpl*>(image_context));
- if (image_context->sync_token.HasData()) {
- resource_sync_tokens_.push_back(image_context->sync_token);
- image_context->sync_token.Clear();
- }
- images_in_current_paint_.push_back(image_context.get());
+ if (image_context->has_image())
+ return;
- return image_context->image;
+ SkColorType color_type = ResourceFormatToClosestSkColorType(
+ true /* gpu_compositing */, image_context->resource_format());
+ GrBackendFormat backend_format = GetGrBackendFormatForTexture(
+ image_context->resource_format(),
+ image_context->mailbox_holder().texture_target,
+ image_context->ycbcr_info());
+ image_context->SetImage(
+ recorder_->makePromiseTexture(
+ backend_format, image_context->size().width(),
+ image_context->size().height(), GrMipMapped::kNo,
+ image_context->origin(), color_type, image_context->alpha_type(),
+ image_context->color_space(), Fulfill /* fulfillProc */,
+ DoNothing /* releaseProc */, DoNothing /* doneProc */,
+ image_context /* context */),
+ backend_format);
+
+ if (image_context->mailbox_holder().sync_token.HasData()) {
+ resource_sync_tokens_.push_back(image_context->mailbox_holder().sync_token);
+ image_context->mutable_mailbox_holder()->sync_token.Clear();
+ }
}
sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV(
- const std::vector<ResourceMetadata>& metadatas,
+ const std::vector<ImageContext*>& contexts,
SkYUVColorSpace yuv_color_space,
sk_sp<SkColorSpace> dst_color_space,
bool has_alpha) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(recorder_);
- DCHECK((has_alpha && (metadatas.size() == 3 || metadatas.size() == 4)) ||
- (!has_alpha && (metadatas.size() == 2 || metadatas.size() == 3)));
+ DCHECK((has_alpha && (contexts.size() == 3 || contexts.size() == 4)) ||
+ (!has_alpha && (contexts.size() == 2 || contexts.size() == 3)));
SkYUVAIndex indices[4];
- PrepareYUVATextureIndices(metadatas, has_alpha, indices);
+ PrepareYUVATextureIndices(contexts, has_alpha, indices);
GrBackendFormat formats[4] = {};
SkISize yuva_sizes[4] = {};
SkDeferredDisplayListRecorder::PromiseImageTextureContext
texture_contexts[4] = {};
- for (size_t i = 0; i < metadatas.size(); ++i) {
- const auto& metadata = metadatas[i];
- DCHECK(metadata.origin == kTopLeft_GrSurfaceOrigin);
+ for (size_t i = 0; i < contexts.size(); ++i) {
+ auto* context = static_cast<ImageContextImpl*>(contexts[i]);
+ DCHECK(context->origin() == kTopLeft_GrSurfaceOrigin);
formats[i] = GetGrBackendFormatForTexture(
- metadata.resource_format, metadata.mailbox_holder.texture_target);
- yuva_sizes[i].set(metadata.size.width(), metadata.size.height());
- auto& image_context = promise_image_cache_[metadata.resource_id];
- if (!image_context) {
- // color_space is ignored by makeYUVAPromiseTexture below. Passing nullptr
- // removes some LOG spam.
- image_context = std::make_unique<ImageContext>(
- metadata.mailbox_holder.mailbox, metadata.size,
- metadata.resource_format, nullptr /* color_space */,
- metadata.alpha_type, metadata.origin,
- metadata.mailbox_holder.sync_token);
- }
- if (image_context->sync_token.HasData()) {
- resource_sync_tokens_.push_back(image_context->sync_token);
- image_context->sync_token.Clear();
+ context->resource_format(), context->mailbox_holder().texture_target);
+ yuva_sizes[i].set(context->size().width(), context->size().height());
+
+ // NOTE: We don't have promises for individual planes, but still need format
+ // for fallback
+ context->SetImage(nullptr, formats[i]);
+
+ if (context->mailbox_holder().sync_token.HasData()) {
+ resource_sync_tokens_.push_back(context->mailbox_holder().sync_token);
+ context->mutable_mailbox_holder()->sync_token.Clear();
}
- images_in_current_paint_.push_back(image_context.get());
- texture_contexts[i] = image_context.get();
+ images_in_current_paint_.push_back(context);
+ texture_contexts[i] = context;
}
auto image = recorder_->makeYUVAPromiseTexture(
@@ -323,22 +307,8 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV(
return image;
}
-void SkiaOutputSurfaceImpl::ReleaseCachedResources(
- const std::vector<ResourceId>& ids) {
- if (ids.empty())
- return;
-
- std::vector<std::unique_ptr<ImageContext>> image_contexts;
- for (auto id : ids) {
- auto it = promise_image_cache_.find(id);
- if (it == promise_image_cache_.end())
- continue;
- auto& image_context = it->second;
- image_context->image = nullptr;
- image_contexts.push_back(std::move(image_context));
- promise_image_cache_.erase(it);
- }
-
+void SkiaOutputSurfaceImpl::ReleaseImageContexts(
+ std::vector<std::unique_ptr<ImageContext>> image_contexts) {
if (image_contexts.empty())
return;
@@ -347,7 +317,17 @@ void SkiaOutputSurfaceImpl::ReleaseCachedResources(
auto callback = base::BindOnce(
&SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts,
base::Unretained(impl_on_gpu_.get()), std::move(image_contexts));
- ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
+ task_sequence_->ScheduleOrRetainTask(std::move(callback),
+ std::vector<gpu::SyncToken>());
+}
+
+std::unique_ptr<ExternalUseClient::ImageContext>
+SkiaOutputSurfaceImpl::CreateImageContext(const gpu::MailboxHolder& holder,
+ const gfx::Size& size,
+ ResourceFormat format,
+ sk_sp<SkColorSpace> color_space) {
+ return std::make_unique<ImageContextImpl>(holder, size, format,
+ std::move(color_space));
}
void SkiaOutputSurfaceImpl::SkiaSwapBuffers(OutputSurfaceFrame frame) {
@@ -361,13 +341,14 @@ void SkiaOutputSurfaceImpl::SkiaSwapBuffers(OutputSurfaceFrame frame) {
ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
}
-void SkiaOutputSurfaceImpl::ScheduleOverlays(OverlayCandidateList overlays) {
+void SkiaOutputSurfaceImpl::ScheduleOutputSurfaceAsOverlay(
+ OverlayProcessor::OutputSurfaceOverlayPlane output_surface_plane) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// impl_on_gpu_ is released on the GPU thread by a posted task from
// SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
- auto callback =
- base::BindOnce(&SkiaOutputSurfaceImplOnGpu::ScheduleOverlays,
- base::Unretained(impl_on_gpu_.get()), std::move(overlays));
+ auto callback = base::BindOnce(
+ &SkiaOutputSurfaceImplOnGpu::ScheduleOutputSurfaceAsOverlay,
+ base::Unretained(impl_on_gpu_.get()), std::move(output_surface_plane));
ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
}
@@ -426,7 +407,7 @@ gpu::SyncToken SkiaOutputSurfaceImpl::SubmitPaint(
// We are going to overwrite the render pass, so we need reset the
// image_context, so a new promise image will be created when the
// MakePromiseSkImageFromRenderPass() is called.
- it->second->image = nullptr;
+ it->second->clear_image();
}
DCHECK(!on_finished);
callback = base::BindOnce(
@@ -439,7 +420,9 @@ gpu::SyncToken SkiaOutputSurfaceImpl::SubmitPaint(
&SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame,
base::Unretained(impl_on_gpu_.get()), std::move(ddl),
std::move(overdraw_ddl), std::move(images_in_current_paint_),
- resource_sync_tokens_, sync_fence_release_, std::move(on_finished));
+ resource_sync_tokens_, sync_fence_release_, std::move(on_finished),
+ draw_rectangle_);
+ draw_rectangle_.reset();
}
images_in_current_paint_.clear();
ScheduleGpuTask(std::move(callback), std::move(resource_sync_tokens_));
@@ -458,24 +441,26 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromRenderPass(
auto& image_context = render_pass_image_cache_[id];
if (!image_context) {
- image_context = std::make_unique<ImageContext>(id, size, format, mipmap,
- std::move(color_space));
+ image_context = std::make_unique<ImageContextImpl>(id, size, format, mipmap,
+ std::move(color_space));
}
- if (!image_context->image) {
+ if (!image_context->has_image()) {
SkColorType color_type =
ResourceFormatToClosestSkColorType(true /* gpu_compositing */, format);
GrBackendFormat backend_format =
GetGrBackendFormatForTexture(format, GL_TEXTURE_2D);
- image_context->image = recorder_->makePromiseTexture(
- backend_format, image_context->size.width(),
- image_context->size.height(), image_context->mipmap,
- image_context->origin, color_type, image_context->alpha_type,
- image_context->color_space, Fulfill, DoNothing, DoNothing,
- image_context.get());
- DCHECK(image_context->image);
+ image_context->SetImage(
+ recorder_->makePromiseTexture(
+ backend_format, image_context->size().width(),
+ image_context->size().height(), image_context->mipmap(),
+ image_context->origin(), color_type, image_context->alpha_type(),
+ image_context->color_space(), Fulfill, DoNothing, DoNothing,
+ image_context.get()),
+ backend_format);
+ DCHECK(image_context->has_image());
}
images_in_current_paint_.push_back(image_context.get());
- return image_context->image;
+ return image_context->image();
}
void SkiaOutputSurfaceImpl::RemoveRenderPassResource(
@@ -483,14 +468,14 @@ void SkiaOutputSurfaceImpl::RemoveRenderPassResource(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!ids.empty());
- std::vector<std::unique_ptr<ImageContext>> image_contexts;
+ std::vector<std::unique_ptr<ImageContextImpl>> image_contexts;
image_contexts.reserve(ids.size());
for (const auto id : ids) {
auto it = render_pass_image_cache_.find(id);
// If the render pass was only used for a copy request, there won't be a
// matching entry in |render_pass_image_cache_|.
if (it != render_pass_image_cache_.end()) {
- it->second->image = nullptr;
+ it->second->clear_image();
image_contexts.push_back(std::move(it->second));
render_pass_image_cache_.erase(it);
}
@@ -593,25 +578,14 @@ SkiaOutputSurfaceImpl::CreateSkSurfaceCharacterization(
// LegacyFontHost will get LCD text and skia figures out what type to use.
SkSurfaceProps surface_props(0 /*flags */,
SkSurfaceProps::kLegacyFontHost_InitType);
- SkColorType color_type =
+ auto color_type =
ResourceFormatToClosestSkColorType(true /* gpu_compositing */, format);
- SkImageInfo image_info =
+ auto image_info =
SkImageInfo::Make(surface_size.width(), surface_size.height(), color_type,
kPremul_SkAlphaType, std::move(color_space));
- GrBackendFormat backend_format;
- if (!is_using_vulkan_) {
- const auto* version_info = impl_on_gpu_->gl_version_info();
- unsigned int texture_storage_format = TextureStorageFormat(format);
- backend_format = GrBackendFormat::MakeGL(
- gl::GetInternalFormat(version_info, texture_storage_format),
- GL_TEXTURE_2D);
- } else {
-#if BUILDFLAG(ENABLE_VULKAN)
- backend_format = GrBackendFormat::MakeVk(ToVkFormat(format));
-#else
- NOTREACHED();
-#endif
- }
+ auto backend_format = gr_context_thread_safe->defaultBackendFormat(
+ color_type, GrRenderable::kYes);
+ DCHECK(backend_format.isValid());
auto characterization = gr_context_thread_safe->createCharacterization(
cache_max_resource_bytes, image_info, backend_format, 0 /* sampleCount */,
kTopLeft_GrSurfaceOrigin, surface_props, mipmap);
@@ -668,17 +642,19 @@ GrBackendFormat SkiaOutputSurfaceImpl::GetGrBackendFormatForTexture(
if (!is_using_vulkan_) {
DCHECK(!ycbcr_info);
// Convert internal format from GLES2 to platform GL.
- const auto* version_info = impl_on_gpu_->gl_version_info();
- unsigned int texture_storage_format = TextureStorageFormat(resource_format);
- return GrBackendFormat::MakeGL(
- gl::GetInternalFormat(version_info, texture_storage_format),
- gl_texture_target);
+ unsigned int texture_storage_format = gpu::GetGrGLBackendTextureFormat(
+ impl_on_gpu_->GetFeatureInfo(), resource_format);
+
+ return GrBackendFormat::MakeGL(texture_storage_format, gl_texture_target);
} else {
#if BUILDFLAG(ENABLE_VULKAN)
if (!ycbcr_info)
return GrBackendFormat::MakeVk(ToVkFormat(resource_format));
- GrVkYcbcrConversionInfo fYcbcrConversionInfo(
+ VkFormat format = ycbcr_info->external_format ? VK_FORMAT_UNDEFINED
+ : ToVkFormat(resource_format);
+ GrVkYcbcrConversionInfo gr_ycbcr_info(
+ format, ycbcr_info->external_format,
static_cast<VkSamplerYcbcrModelConversion>(
ycbcr_info->suggested_ycbcr_model),
static_cast<VkSamplerYcbcrRange>(ycbcr_info->suggested_ycbcr_range),
@@ -686,9 +662,8 @@ GrBackendFormat SkiaOutputSurfaceImpl::GetGrBackendFormatForTexture(
static_cast<VkChromaLocation>(ycbcr_info->suggested_ychroma_offset),
VK_FILTER_LINEAR, // VkFilter
0, // VkBool32 forceExplicitReconstruction,
- ycbcr_info->external_format,
static_cast<VkFormatFeatureFlags>(ycbcr_info->format_features));
- return GrBackendFormat::MakeVk(fYcbcrConversionInfo);
+ return GrBackendFormat::MakeVk(gr_ycbcr_info);
#else
NOTREACHED();
return GrBackendFormat();
@@ -750,14 +725,13 @@ void SkiaOutputSurfaceImpl::RemoveContextLostObserver(
}
void SkiaOutputSurfaceImpl::PrepareYUVATextureIndices(
- const std::vector<ResourceMetadata>& metadatas,
+ const std::vector<ImageContext*>& contexts,
bool has_alpha,
SkYUVAIndex indices[4]) {
- DCHECK((has_alpha && (metadatas.size() == 3 || metadatas.size() == 4)) ||
- (!has_alpha && (metadatas.size() == 2 || metadatas.size() == 3)));
+ DCHECK((has_alpha && (contexts.size() == 3 || contexts.size() == 4)) ||
+ (!has_alpha && (contexts.size() == 2 || contexts.size() == 3)));
- bool uv_interleaved =
- has_alpha ? metadatas.size() == 3 : metadatas.size() == 2;
+ bool uv_interleaved = has_alpha ? contexts.size() == 3 : contexts.size() == 2;
indices[SkYUVAIndex::kY_Index].fIndex = 0;
indices[SkYUVAIndex::kY_Index].fChannel = SkColorChannel::kR;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h
index b956564a139..0170edfcad3 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -31,9 +31,9 @@ class WaitableEvent;
namespace viz {
+class ImageContextImpl;
class SkiaOutputSurfaceDependency;
class SkiaOutputSurfaceImplOnGpu;
-struct ImageContext;
// The SkiaOutputSurface implementation. It is the output surface for
// SkiaRenderer. It lives on the compositor thread, but it will post tasks
@@ -85,12 +85,14 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
// SkiaOutputSurface implementation:
SkCanvas* BeginPaintCurrentFrame() override;
sk_sp<SkImage> MakePromiseSkImageFromYUV(
- const std::vector<ResourceMetadata>& metadatas,
+ const std::vector<ImageContext*>& contexts,
SkYUVColorSpace yuv_color_space,
sk_sp<SkColorSpace> dst_color_space,
bool has_alpha) override;
void SkiaSwapBuffers(OutputSurfaceFrame frame) override;
- void ScheduleOverlays(OverlayCandidateList overlays) override;
+ void ScheduleOutputSurfaceAsOverlay(
+ OverlayProcessor::OutputSurfaceOverlayPlane output_surface_plane)
+ override;
SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
const gfx::Size& surface_size,
@@ -98,7 +100,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
bool mipmap,
sk_sp<SkColorSpace> color_space) override;
gpu::SyncToken SubmitPaint(base::OnceClosure on_finished) override;
- sk_sp<SkImage> MakePromiseSkImage(const ResourceMetadata& metadata) override;
+ void MakePromiseSkImage(ImageContext* image_context) override;
sk_sp<SkImage> MakePromiseSkImageFromRenderPass(
const RenderPassId& id,
const gfx::Size& size,
@@ -115,7 +117,13 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
void RemoveContextLostObserver(ContextLostObserver* observer) override;
// ExternalUseClient implementation:
- void ReleaseCachedResources(const std::vector<ResourceId>& ids) override;
+ void ReleaseImageContexts(
+ std::vector<std::unique_ptr<ImageContext>> image_contexts) override;
+ std::unique_ptr<ExternalUseClient::ImageContext> CreateImageContext(
+ const gpu::MailboxHolder& holder,
+ const gfx::Size& size,
+ ResourceFormat format,
+ sk_sp<SkColorSpace> color_space) override;
// Set the fields of |capabilities_| and propagates to |impl_on_gpu_|. Should
// be called after BindToClient().
@@ -143,7 +151,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
ResourceFormat resource_format,
uint32_t gl_texture_target,
base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info = base::nullopt);
- void PrepareYUVATextureIndices(const std::vector<ResourceMetadata>& metadatas,
+ void PrepareYUVATextureIndices(const std::vector<ImageContext*>& contexts,
bool has_alpha,
SkYUVAIndex indices[4]);
void ContextLost();
@@ -151,12 +159,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
OutputSurfaceClient* client_ = nullptr;
bool needs_swap_size_notifications_ = false;
- // Cached promise image.
- base::flat_map<ResourceId, std::unique_ptr<ImageContext>>
- promise_image_cache_;
-
// Images for current frame or render pass.
- std::vector<ImageContext*> images_in_current_paint_;
+ std::vector<ImageContextImpl*> images_in_current_paint_;
THREAD_CHECKER(thread_checker_);
@@ -188,7 +192,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
base::Optional<SkNWayCanvas> nway_canvas_;
// The cache for promise image created from render passes.
- base::flat_map<RenderPassId, std::unique_ptr<ImageContext>>
+ base::flat_map<RenderPassId, std::unique_ptr<ImageContextImpl>>
render_pass_image_cache_;
// Sync tokens for resources which are used for the current frame or render
@@ -210,6 +214,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
// |impl_on_gpu| is created and destroyed on the GPU thread.
std::unique_ptr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_;
+ base::Optional<gfx::Rect> draw_rectangle_;
+
base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr_;
base::WeakPtrFactory<SkiaOutputSurfaceImpl> weak_ptr_factory_{this};
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 17cc49d9645..9ca960a9e7d 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -22,7 +22,7 @@
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/texture_deleter.h"
#include "components/viz/service/display_embedder/direct_context_provider.h"
-#include "components/viz/service/display_embedder/image_context.h"
+#include "components/viz/service/display_embedder/image_context_impl.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "components/viz/service/display_embedder/skia_output_device_buffer_queue.h"
#include "components/viz/service/display_embedder/skia_output_device_gl.h"
@@ -31,6 +31,7 @@
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/service/context_state.h"
+#include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
#include "gpu/command_buffer/service/gr_shader_cache.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/scheduler.h"
@@ -158,7 +159,7 @@ void OnYUVReadbackDone(void* c, const void* data[3], size_t row_bytes[3]) {
class SkiaOutputSurfaceImplOnGpu::ScopedPromiseImageAccess {
public:
ScopedPromiseImageAccess(SkiaOutputSurfaceImplOnGpu* impl_on_gpu,
- std::vector<ImageContext*> image_contexts)
+ std::vector<ImageContextImpl*> image_contexts)
: impl_on_gpu_(impl_on_gpu), image_contexts_(std::move(image_contexts)) {
begin_semaphores_.reserve(image_contexts_.size());
// We may need one more space for the swap buffer semaphore.
@@ -183,7 +184,7 @@ class SkiaOutputSurfaceImplOnGpu::ScopedPromiseImageAccess {
private:
SkiaOutputSurfaceImplOnGpu* const impl_on_gpu_;
- std::vector<ImageContext*> image_contexts_;
+ std::vector<ImageContextImpl*> image_contexts_;
std::vector<GrBackendSemaphore> begin_semaphores_;
std::vector<GrBackendSemaphore> end_semaphores_;
@@ -233,12 +234,6 @@ namespace {
base::AtomicSequenceNumber g_next_command_buffer_id;
-scoped_refptr<gpu::gles2::FeatureInfo> CreateFeatureInfo(
- SkiaOutputSurfaceDependency* deps) {
- return base::MakeRefCounted<gpu::gles2::FeatureInfo>(
- deps->GetGpuDriverBugWorkarounds(), deps->GetGpuFeatureInfo());
-}
-
scoped_refptr<gpu::SyncPointClientState> CreateSyncPointClientState(
SkiaOutputSurfaceDependency* deps,
gpu::SequenceId sequence_id) {
@@ -260,36 +255,62 @@ class ScopedSurfaceToTexture {
public:
ScopedSurfaceToTexture(scoped_refptr<DirectContextProvider> context_provider,
SkSurface* surface)
- : context_provider_(context_provider) {
+ : context_provider_(context_provider),
+ client_id_(context_provider->GenClientTextureId()) {
GrBackendTexture skia_texture =
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
GrGLTextureInfo gl_texture_info;
skia_texture.getGLTextureInfo(&gl_texture_info);
- GLuint client_id = context_provider_->GenClientTextureId();
- auto* texture_manager = context_provider_->texture_manager();
- texture_ref_ =
- texture_manager->CreateTexture(client_id, gl_texture_info.fID);
- texture_manager->SetTarget(texture_ref_.get(), gl_texture_info.fTarget);
- texture_manager->SetLevelInfo(
- texture_ref_.get(), gl_texture_info.fTarget,
- /*level=*/0,
- /*internal_format=*/GL_RGBA, surface->width(), surface->height(),
- /*depth=*/1, /*border=*/0,
- /*format=*/GL_RGBA, /*type=*/GL_UNSIGNED_BYTE,
- /*cleared_rect=*/gfx::Rect(surface->width(), surface->height()));
+
+ auto* group = context_provider->decoder()->GetContextGroup();
+ if (group->use_passthrough_cmd_decoder()) {
+ group->passthrough_resources()->texture_id_map.SetIDMapping(
+ client_id_, gl_texture_info.fID);
+
+ auto texture = base::MakeRefCounted<gpu::gles2::TexturePassthrough>(
+ gl_texture_info.fID, gl_texture_info.fTarget, GL_RGBA,
+ surface->width(), surface->height(),
+ /*depth=*/1, /*border=*/0,
+ /*format=*/GL_RGBA, /*type=*/GL_UNSIGNED_BYTE);
+
+ group->passthrough_resources()->texture_object_map.SetIDMapping(
+ client_id_, texture);
+ } else {
+ auto* texture_manager = context_provider_->texture_manager();
+ texture_ref_ =
+ texture_manager->CreateTexture(client_id_, gl_texture_info.fID);
+ texture_manager->SetTarget(texture_ref_.get(), gl_texture_info.fTarget);
+ texture_manager->SetLevelInfo(
+ texture_ref_.get(), gl_texture_info.fTarget,
+ /*level=*/0,
+ /*internal_format=*/GL_RGBA, surface->width(), surface->height(),
+ /*depth=*/1, /*border=*/0,
+ /*format=*/GL_RGBA, /*type=*/GL_UNSIGNED_BYTE,
+ /*cleared_rect=*/gfx::Rect(surface->width(), surface->height()));
+ }
}
~ScopedSurfaceToTexture() {
- context_provider_->DeleteClientTextureId(client_id());
+ auto* group = context_provider_->decoder()->GetContextGroup();
// Skia owns the texture. It will delete it when it is done.
- texture_ref_->ForceContextLost();
+ if (group->use_passthrough_cmd_decoder()) {
+ group->passthrough_resources()
+ ->texture_object_map.GetServiceIDOrInvalid(client_id_)
+ ->MarkContextLost();
+ } else {
+ texture_ref_->ForceContextLost();
+ }
+
+ context_provider_->DeleteClientTextureId(client_id());
}
- GLuint client_id() { return texture_ref_->client_id(); }
+ GLuint client_id() { return client_id_; }
private:
scoped_refptr<DirectContextProvider> context_provider_;
+ const GLuint client_id_;
+ // This is only used with validating gles cmd decoder
scoped_refptr<gpu::gles2::TextureRef> texture_ref_;
DISALLOW_COPY_AND_ASSIGN(ScopedSurfaceToTexture);
@@ -432,7 +453,6 @@ class DirectContextProviderDelegateImpl : public DirectContextProviderDelegate,
shared_image_factory_.DestroySharedImage(mailbox);
}
-#if defined(OS_WIN)
SwapChainMailboxes CreateSwapChain(ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
@@ -445,7 +465,18 @@ class DirectContextProviderDelegateImpl : public DirectContextProviderDelegate,
const gpu::Mailbox& mailbox) override {
NOTREACHED();
}
-#endif // OS_WIN
+
+#if defined(OS_FUCHSIA)
+ void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id,
+ zx::channel token) override {
+ NOTREACHED();
+ }
+
+ void ReleaseSysmemBufferCollection(
+ gfx::SysmemBufferCollectionId id) override {
+ NOTREACHED();
+ }
+#endif // defined(OS_FUCHSIA)
gpu::SyncToken GenUnverifiedSyncToken() override {
return gpu::SyncToken(sync_point_client_state_->namespace_id(),
@@ -534,14 +565,13 @@ SkSurface* SkiaOutputSurfaceImplOnGpu::OffscreenSurface::surface() const {
return surface_.get();
}
-sk_sp<SkPromiseImageTexture>
-SkiaOutputSurfaceImplOnGpu::OffscreenSurface::fulfill() {
+SkPromiseImageTexture* SkiaOutputSurfaceImplOnGpu::OffscreenSurface::fulfill() {
DCHECK(surface_);
if (!promise_texture_) {
promise_texture_ = SkPromiseImageTexture::Make(
surface_->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
- return promise_texture_;
+ return promise_texture_.get();
}
void SkiaOutputSurfaceImplOnGpu::OffscreenSurface::set_surface(
@@ -577,7 +607,7 @@ SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu(
const BufferPresentedCallback& buffer_presented_callback,
const ContextLostCallback& context_lost_callback)
: dependency_(std::move(deps)),
- feature_info_(CreateFeatureInfo(dependency_)),
+ feature_info_(dependency_->GetSharedContextState()->feature_info()),
sync_point_client_state_(
CreateSyncPointClientState(dependency_, sequence_id)),
shared_image_representation_factory_(
@@ -651,10 +681,11 @@ void SkiaOutputSurfaceImplOnGpu::Reshape(
void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
std::unique_ptr<SkDeferredDisplayList> ddl,
std::unique_ptr<SkDeferredDisplayList> overdraw_ddl,
- std::vector<ImageContext*> image_contexts,
+ std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release,
- base::OnceClosure on_finished) {
+ base::OnceClosure on_finished,
+ base::Optional<gfx::Rect> draw_rectangle) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(ddl);
@@ -663,6 +694,9 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
if (!MakeCurrent(true /* need_fbo0 */))
return;
+ if (draw_rectangle)
+ output_device_->SetDrawRectangle(*draw_rectangle);
+
// We do not reset scoped_output_device_paint_ after drawing the ddl until
// SwapBuffers() is called, because we may need access to output_sk_surface()
// for CopyOutput().
@@ -742,33 +776,27 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release);
}
-void SkiaOutputSurfaceImplOnGpu::ScheduleOverlays(
- const OverlayCandidateList& overlays) {
- if (overlays.empty())
- return;
-
+void SkiaOutputSurfaceImplOnGpu::ScheduleOutputSurfaceAsOverlay(
+ const OverlayProcessor::OutputSurfaceOverlayPlane& output_surface_plane) {
DCHECK(!is_using_vulkan());
if (!MakeCurrent(!dependency_->IsOffscreen() /* need_fbo0 */))
return;
- for (const auto& overlay_candidate : overlays) {
- gl::GLImage* image = nullptr;
- std::unique_ptr<gfx::GpuFence> gpu_fence;
- if (overlay_candidate.use_output_surface_for_resource) {
- image = output_device_->GetOverlayImage();
- gpu_fence = output_device_->SubmitOverlayGpuFence();
- } else {
- NOTIMPLEMENTED_LOG_ONCE();
- }
+ gl::GLImage* image = output_device_->GetOverlayImage();
+ std::unique_ptr<gfx::GpuFence> gpu_fence =
+ output_device_->SubmitOverlayGpuFence();
- if (image) {
- gl_surface_->ScheduleOverlayPlane(
- overlay_candidate.plane_z_order, overlay_candidate.transform, image,
- ToNearestRect(overlay_candidate.display_rect),
- overlay_candidate.uv_rect, !overlay_candidate.is_opaque,
- std::move(gpu_fence));
- }
+ if (image) {
+ // Output surface is also z-order 0.
+ int plane_z_order = 0;
+ // Output surface always uses the full texture.
+ gfx::RectF uv_rect(0.f, 0.f, 1.f, 1.f);
+
+ gl_surface_->ScheduleOverlayPlane(
+ plane_z_order, output_surface_plane.transform, image,
+ ToNearestRect(output_surface_plane.display_rect), uv_rect,
+ output_surface_plane.enable_blending, std::move(gpu_fence));
}
}
@@ -803,7 +831,7 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffers(OutputSurfaceFrame frame) {
void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl,
- std::vector<ImageContext*> image_contexts,
+ std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass");
@@ -865,12 +893,12 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
}
void SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource(
- std::vector<std::unique_ptr<ImageContext>> image_contexts) {
+ std::vector<std::unique_ptr<ImageContextImpl>> image_contexts) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!image_contexts.empty());
for (auto& image_context : image_contexts) {
- auto it = offscreen_surfaces_.find(image_context->render_pass_id);
+ auto it = offscreen_surfaces_.find(image_context->render_pass_id());
DCHECK(it != offscreen_surfaces_.end());
offscreen_surfaces_.erase(it);
}
@@ -1084,180 +1112,39 @@ void SkiaOutputSurfaceImplOnGpu::PerformDelayedWork() {
}
}
-// TODO(backer): Add memory tracking.
-void SkiaOutputSurfaceImplOnGpu::CreateFallbackImage(ImageContext* context) {
- SkColorType color_type = ResourceFormatToClosestSkColorType(
- true /* gpu_compositing */, context->resource_format);
-
- // Don't use a fallback SkColorType because we may fail checks inside Skia
- if (SkColorTypeBytesPerPixel(color_type) * 8 !=
- BitsPerPixel(context->resource_format))
- return;
-
- context->fallback_texture =
- context_state_->gr_context()->createBackendTexture(
- context->size.width(), context->size.height(), color_type,
-#if DCHECK_IS_ON()
- SkColors::kRed,
-#else
- SkColors::kWhite,
-#endif
- GrMipMapped::kNo, GrRenderable::kYes);
- if (!context->fallback_texture.isValid()) {
- DLOG(ERROR) << "Could not create backend texture.";
- return;
- }
- context->promise_image_texture =
- SkPromiseImageTexture::Make(context->fallback_texture);
-}
-
void SkiaOutputSurfaceImplOnGpu::BeginAccessImages(
- const std::vector<ImageContext*>& image_contexts,
+ const std::vector<ImageContextImpl*>& image_contexts,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::BeginAccessImages");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
for (auto* context : image_contexts) {
- // Skip the context if it has been processed.
- if (context->representation_is_being_accessed)
- continue;
// Prepare for accessing render pass.
- if (context->render_pass_id) {
+ if (context->render_pass_id()) {
// We don't cache promise image for render pass, so the it should always
// be nullptr.
- auto it = offscreen_surfaces_.find(context->render_pass_id);
+ auto it = offscreen_surfaces_.find(context->render_pass_id());
DCHECK(it != offscreen_surfaces_.end());
- context->promise_image_texture = it->second.fulfill();
- if (!context->promise_image_texture) {
+ context->set_promise_image_texture(sk_ref_sp(it->second.fulfill()));
+ if (!context->promise_image_texture()) {
DLOG(ERROR) << "Failed to fulfill the promise texture created from "
"RenderPassId:"
- << context->render_pass_id;
- CreateFallbackImage(context);
+ << context->render_pass_id();
}
- continue;
- }
-
- // Prepare for accessing shared image.
- if (context->mailbox.IsSharedImage()) {
- if (context->promise_image_texture) {
- // The promise image has been fulfilled early, so we just need begin
- // access the shared image representation. If representation is nullptr,
- // it means the promise image was not fulfilled successfully last time
- // and a fallback content has been used, in that case, we cannot change
- // the content, so we do nothing.
- if (context->representation) {
- auto promise_image_texture = context->representation->BeginReadAccess(
- begin_semaphores, end_semaphores);
- // The image has been fulfilled and cached. It is too late to tell
- // skia the backing of the cached image is not accessible right now,
- // so crash for now.
- // TODO(penghuang): find a way to notify skia.
- CHECK(promise_image_texture);
- context->representation_is_being_accessed = true;
- }
- continue;
- }
-
- auto representation = shared_image_representation_factory_->ProduceSkia(
- context->mailbox, context_state_.get());
- if (!representation) {
- DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
- "mailbox not found in SharedImageManager.";
- CreateFallbackImage(context);
- continue;
- }
-
- if (!(representation->usage() & gpu::SHARED_IMAGE_USAGE_DISPLAY)) {
- DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
- "was not created with display usage.";
- CreateFallbackImage(context);
- continue;
- }
-
- if (representation->size() != context->size) {
- DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
- "size does not match TransferableResource size.";
- CreateFallbackImage(context);
- continue;
- }
-
- context->representation = std::move(representation);
- context->promise_image_texture = context->representation->BeginReadAccess(
- begin_semaphores, end_semaphores);
- if (!context->promise_image_texture) {
- DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
- "begin read access failed..";
- CreateFallbackImage(context);
- continue;
- }
- context->representation_is_being_accessed = true;
- continue;
- }
-
- // Prepare for accessing legacy mailbox.
- // The promise image has been fulfilled once, so we do need do anything.
- if (context->promise_image_texture)
- continue;
-
- if (is_using_vulkan()) {
- // Probably this texture is created with wrong interface
- // (GLES2Interface).
- DLOG(ERROR)
- << "Failed to fulfill the promise texture whose backend is not "
- "compatible with vulkan.";
- CreateFallbackImage(context);
- continue;
- }
-
- auto* texture_base =
- dependency_->GetMailboxManager()->ConsumeTexture(context->mailbox);
- if (!texture_base) {
- DLOG(ERROR) << "Failed to fulfill the promise texture.";
- CreateFallbackImage(context);
- continue;
- }
-
- gfx::Size texture_size;
- if (BindOrCopyTextureIfNecessary(texture_base, &texture_size) &&
- texture_size != context->size) {
- DLOG(ERROR) << "Failed to fulfill the promise texture - texture "
- "size does not match TransferableResource size.";
- CreateFallbackImage(context);
- continue;
- }
-
- GrBackendTexture backend_texture;
- gpu::GetGrBackendTexture(gl_version_info_, texture_base->target(),
- context->size, texture_base->service_id(),
- context->resource_format, &backend_texture);
- if (!backend_texture.isValid()) {
- DLOG(ERROR) << "Failed to fulfill the promise texture.";
- CreateFallbackImage(context);
- continue;
+ } else {
+ context->BeginAccessIfNecessary(
+ context_state_.get(), shared_image_representation_factory_.get(),
+ dependency_->GetMailboxManager(), begin_semaphores, end_semaphores);
}
- context->promise_image_texture =
- SkPromiseImageTexture::Make(backend_texture);
}
}
void SkiaOutputSurfaceImplOnGpu::EndAccessImages(
- const std::vector<ImageContext*>& image_contexts) {
+ const std::vector<ImageContextImpl*>& image_contexts) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::EndAccessImages");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- for (auto* context : image_contexts) {
- if (!context->representation_is_being_accessed)
- continue;
- // TODO(penghuang): create end read access semaphores and call
- // EndReadAccess() with them. https://crbug.com/944194
- DCHECK(context->representation);
- context->representation->EndReadAccess();
- context->representation_is_being_accessed = false;
- }
-}
-
-void SkiaOutputSurfaceImplOnGpu::SetDrawRectangle(
- const gfx::Rect& draw_rectangle) {
- output_device_->SetDrawRectangle(draw_rectangle);
+ for (auto* context : image_contexts)
+ context->EndAccessIfNecessary();
}
sk_sp<GrContextThreadSafeProxy>
@@ -1266,17 +1153,14 @@ SkiaOutputSurfaceImplOnGpu::GetGrContextThreadSafeProxy() {
}
void SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts(
- std::vector<std::unique_ptr<ImageContext>> image_contexts) {
+ std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
+ image_contexts) {
DCHECK(!image_contexts.empty());
// The window could be destroyed already, and the MakeCurrent will fail with
// an destroyed window, so MakeCurrent without requiring the fbo0.
MakeCurrent(false /* need_fbo0 */);
- for (const auto& image_context : image_contexts) {
- if (image_context->fallback_texture.isValid())
- gpu::DeleteGrBackendTexture(context_state_.get(),
- &image_context->fallback_texture);
- }
+ // |image_contexts| goes out of scope here.
}
void SkiaOutputSurfaceImplOnGpu::SetCapabilitiesForTesting(
@@ -1285,7 +1169,7 @@ void SkiaOutputSurfaceImplOnGpu::SetCapabilitiesForTesting(
// Check that we're using an offscreen surface.
DCHECK(dependency_->IsOffscreen());
output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
- gr_context(), capabilities.flipped_output_surface,
+ context_state_, capabilities.flipped_output_surface,
renderer_settings_.requires_alpha_channel,
did_swap_buffer_complete_callback_);
}
@@ -1326,7 +1210,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() {
return false;
output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
- gr_context(), true /* flipped */,
+ context_state_, true /* flipped */,
renderer_settings_.requires_alpha_channel,
did_swap_buffer_complete_callback_);
supports_alpha_ = renderer_settings_.requires_alpha_channel;
@@ -1370,7 +1254,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForVulkan() {
#if BUILDFLAG(ENABLE_VULKAN)
if (dependency_->IsOffscreen()) {
output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
- gr_context(), false /* flipped */,
+ context_state_, false /* flipped */,
renderer_settings_.requires_alpha_channel,
did_swap_buffer_complete_callback_);
supports_alpha_ = renderer_settings_.requires_alpha_channel;
@@ -1379,7 +1263,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForVulkan() {
supports_alpha_ = true;
if (gpu_preferences_.disable_vulkan_surface) {
output_device_ = std::make_unique<SkiaOutputDeviceX11>(
- gr_context(), dependency_->GetSurfaceHandle(),
+ context_state_, dependency_->GetSurfaceHandle(),
did_swap_buffer_complete_callback_);
} else {
output_device_ = std::make_unique<SkiaOutputDeviceVulkan>(
@@ -1396,43 +1280,6 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForVulkan() {
return true;
}
-bool SkiaOutputSurfaceImplOnGpu::BindOrCopyTextureIfNecessary(
- gpu::TextureBase* texture_base,
- gfx::Size* size) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (texture_base->GetType() != gpu::TextureBase::Type::kValidated)
- return false;
- // If a texture is validated and bound to an image, we may defer copying the
- // image to the texture until the texture is used. It is for implementing low
- // latency drawing (e.g. fast ink) and avoiding unnecessary texture copy. So
- // we need check the texture image state, and bind or copy the image to the
- // texture if necessary.
- auto* texture = gpu::gles2::Texture::CheckedCast(texture_base);
- gpu::gles2::Texture::ImageState image_state;
- auto* image = texture->GetLevelImage(GL_TEXTURE_2D, 0, &image_state);
- if (image && image_state == gpu::gles2::Texture::UNBOUND) {
- glBindTexture(texture_base->target(), texture_base->service_id());
- if (image->ShouldBindOrCopy() == gl::GLImage::BIND) {
- if (!image->BindTexImage(texture_base->target())) {
- LOG(ERROR) << "Failed to bind a gl image to texture.";
- return false;
- }
- } else {
- texture->SetLevelImageState(texture_base->target(), 0,
- gpu::gles2::Texture::COPIED);
- if (!image->CopyTexImage(texture_base->target())) {
- LOG(ERROR) << "Failed to copy a gl image to texture.";
- return false;
- }
- }
- }
- GLsizei temp_width, temp_height;
- texture->GetLevelSize(texture_base->target(), 0 /* level */, &temp_width,
- &temp_height, nullptr /* depth */);
- *size = gfx::Size(temp_width, temp_height);
- return true;
-}
-
bool SkiaOutputSurfaceImplOnGpu::MakeCurrent(bool need_fbo0) {
if (!is_using_vulkan()) {
// Only make current with |gl_surface_|, if following operations will use
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index 36c42e3a8b6..0c1b7dad122 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -16,9 +16,9 @@
#include "build/build_config.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/quads/render_pass.h"
+#include "components/viz/service/display/external_use_client.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_frame.h"
-#include "components/viz/service/display/resource_metadata.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/shared_context_state.h"
@@ -56,8 +56,8 @@ class PlatformWindowSurface;
namespace viz {
-struct ImageContext;
class DirectContextProvider;
+class ImageContextImpl;
class GLRendererCopier;
class SkiaOutputSurfaceDependency;
class TextureDeleter;
@@ -117,38 +117,39 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void FinishPaintCurrentFrame(
std::unique_ptr<SkDeferredDisplayList> ddl,
std::unique_ptr<SkDeferredDisplayList> overdraw_ddl,
- std::vector<ImageContext*> image_contexts,
+ std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release,
- base::OnceClosure on_finished);
- void ScheduleOverlays(const OverlayCandidateList& overlays);
+ base::OnceClosure on_finished,
+ base::Optional<gfx::Rect> draw_rectangle);
+ void ScheduleOutputSurfaceAsOverlay(
+ const OverlayProcessor::OutputSurfaceOverlayPlane& output_surface_plane);
void SwapBuffers(OutputSurfaceFrame frame);
void EnsureBackbuffer() { output_device_->EnsureBackbuffer(); }
void DiscardBackbuffer() { output_device_->DiscardBackbuffer(); }
void FinishPaintRenderPass(RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl,
- std::vector<ImageContext*> image_contexts,
+ std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
uint64_t sync_fence_release);
void RemoveRenderPassResource(
- std::vector<std::unique_ptr<ImageContext>> image_contexts);
+ std::vector<std::unique_ptr<ImageContextImpl>> image_contexts);
void CopyOutput(RenderPassId id,
const copy_output::RenderPassGeometry& geometry,
const gfx::ColorSpace& color_space,
std::unique_ptr<CopyOutputRequest> request);
- void BeginAccessImages(const std::vector<ImageContext*>& image_contexts,
+ void BeginAccessImages(const std::vector<ImageContextImpl*>& image_contexts,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores);
- void EndAccessImages(const std::vector<ImageContext*>& image_contexts);
-
- void SetDrawRectangle(const gfx::Rect& draw_rectangle);
+ void EndAccessImages(const std::vector<ImageContextImpl*>& image_contexts);
sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy();
const gl::GLVersionInfo* gl_version_info() const { return gl_version_info_; }
size_t max_resource_cache_bytes() const { return max_resource_cache_bytes_; }
void ReleaseImageContexts(
- std::vector<std::unique_ptr<ImageContext>> image_contexts);
+ std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
+ image_contexts);
bool was_context_lost() { return context_state_->context_lost(); }
@@ -178,12 +179,6 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
bool InitializeForGL();
bool InitializeForVulkan();
- // Returns true if |texture_base| is a gles2::Texture and all necessary
- // operations completed successfully. In this case, |*size| is the size of
- // of level 0.
- bool BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base,
- gfx::Size* size);
-
// Make context current for GL, and return false if the context is lost.
// It will do nothing when Vulkan is used.
bool MakeCurrent(bool need_fbo0);
@@ -204,8 +199,6 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
return scoped_output_device_paint_->sk_surface();
}
- void CreateFallbackImage(ImageContext* context);
-
SkiaOutputSurfaceDependency* const dependency_;
scoped_refptr<gpu::gles2::FeatureInfo> feature_info_;
scoped_refptr<gpu::SyncPointClientState> sync_point_client_state_;
@@ -249,7 +242,7 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
OffscreenSurface& operator=(OffscreenSurface&& offscreen_surface);
~OffscreenSurface();
SkSurface* surface() const;
- sk_sp<SkPromiseImageTexture> fulfill();
+ SkPromiseImageTexture* fulfill();
void set_surface(sk_sp<SkSurface> surface);
private:
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc b/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
index e624c1f184b..fbd3fa7c9a6 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/macros.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_win.cc b/chromium/components/viz/service/display_embedder/software_output_device_win.cc
index 73ea1986b21..74316edc0e0 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_win.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_device_win.cc
@@ -12,7 +12,7 @@
#include "components/viz/common/resources/resource_sizes.h"
#include "components/viz/service/display_embedder/output_device_backing.h"
#include "mojo/public/cpp/system/platform_handle.h"
-#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h"
#include "third_party/skia/include/core/SkCanvas.h"
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_win.h b/chromium/components/viz/service/display_embedder/software_output_device_win.h
index e45b64add45..8fe214097b5 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_win.h
+++ b/chromium/components/viz/service/display_embedder/software_output_device_win.h
@@ -11,7 +11,7 @@
#include "components/viz/service/display/software_output_device.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc b/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc
index 75524a6eee7..0c2a3cc5879 100644
--- a/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc
+++ b/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc
@@ -297,6 +297,14 @@ bool VizProcessContextProvider::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) {
DCHECK_EQ(context_result_, gpu::ContextResult::kSuccess);
+ if (args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ if (gr_context_)
+ gpu::raster::DumpBackgroundGrMemoryStatistics(gr_context_->get(), pmd);
+
+ // Early out, no need for more detail in a BACKGROUND dump.
+ return true;
+ }
gles2_implementation_->OnMemoryDump(args, pmd);
gles2_helper_->OnMemoryDump(args, pmd);
diff --git a/chromium/components/viz/service/display_embedder/vsync_parameter_listener.h b/chromium/components/viz/service/display_embedder/vsync_parameter_listener.h
index 9dafba2105b..f6fcf101a04 100644
--- a/chromium/components/viz/service/display_embedder/vsync_parameter_listener.h
+++ b/chromium/components/viz/service/display_embedder/vsync_parameter_listener.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/privileged/interfaces/compositing/vsync_parameter_observer.mojom.h"
+#include "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
index 8eb02da6e6e..63088674014 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
@@ -11,7 +11,7 @@
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index b2953971471..5fe7ecd8194 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -150,12 +150,20 @@ void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
MaybeEvictSurfaces();
}
-void CompositorFrameSinkSupport::OnSurfaceDrawn(Surface* surface) {
+void CompositorFrameSinkSupport::OnSurfaceWillDraw(Surface* surface) {
if (last_drawn_frame_index_ >= surface->GetActiveFrameIndex())
return;
last_drawn_frame_index_ = surface->GetActiveFrameIndex();
}
+void CompositorFrameSinkSupport::OnSurfaceWasDrawn(
+ uint32_t frame_token,
+ base::TimeTicks draw_start_timestamp) {
+ auto frame_timing_details = pending_frame_timing_details_.find(frame_token);
+ DCHECK(frame_timing_details != pending_frame_timing_details_.end());
+ frame_timing_details->second.draw_start_timestamp = draw_start_timestamp;
+}
+
void CompositorFrameSinkSupport::OnFrameTokenChanged(uint32_t frame_token) {
frame_sink_manager_->OnFrameTokenChanged(frame_sink_id_, frame_token);
}
@@ -382,6 +390,11 @@ SubmitResult CompositorFrameSinkSupport::MaybeSubmitCompositorFrameInternal(
UpdateNeedsBeginFramesInternal();
}
+ base::TimeTicks now_time = base::TimeTicks::Now();
+ FrameTimingDetails details;
+ details.received_compositor_frame_timestamp = now_time;
+ pending_frame_timing_details_.emplace(frame.metadata.frame_token, details);
+
// Ensure no CopyOutputRequests have been submitted if they are banned.
if (!allow_copy_output_requests_ && frame.HasCopyOutputRequests()) {
TRACE_EVENT_INSTANT0("viz", "CopyOutputRequests not allowed",
@@ -407,7 +420,8 @@ SubmitResult CompositorFrameSinkSupport::MaybeSubmitCompositorFrameInternal(
}
for (ui::LatencyInfo& latency : frame.metadata.latency_info) {
if (latency.latency_components().size() > 0) {
- latency.AddLatencyNumber(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT);
+ latency.AddLatencyNumberWithTimestamp(
+ ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, now_time);
}
}
@@ -555,24 +569,35 @@ void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
}
void CompositorFrameSinkSupport::DidPresentCompositorFrame(
- uint32_t presentation_token,
+ uint32_t frame_token,
const gfx::PresentationFeedback& feedback) {
- DCHECK(presentation_token);
- FrameTimingDetails details;
+ DCHECK(frame_token);
+
+ DCHECK_LE(pending_frame_timing_details_.size(), 25u);
+ auto pending_details = pending_frame_timing_details_.find(frame_token);
+ DCHECK(pending_details != pending_frame_timing_details_.end());
+
+ FrameTimingDetails details = pending_details->second;
details.presentation_feedback = feedback;
- frame_timing_details_.emplace(presentation_token, details);
+
+ pending_frame_timing_details_.erase(pending_details);
+
+ // We should only ever get one PresentationFeedback per frame_token.
+ DCHECK(frame_timing_details_.find(frame_token) ==
+ frame_timing_details_.end());
+ frame_timing_details_.emplace(frame_token, details);
+
UpdateNeedsBeginFramesInternal();
}
void CompositorFrameSinkSupport::DidRejectCompositorFrame(
- uint32_t presentation_token,
+ uint32_t frame_token,
std::vector<TransferableResource> frame_resource_list) {
std::vector<ReturnedResource> resources =
TransferableResource::ReturnResources(frame_resource_list);
ReturnResources(resources);
DidReceiveCompositorFrameAck();
- DidPresentCompositorFrame(presentation_token,
- gfx::PresentationFeedback::Failure());
+ DidPresentCompositorFrame(frame_token, gfx::PresentationFeedback::Failure());
}
void CompositorFrameSinkSupport::UpdateDisplayRootReference(
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 8ec28d320b7..280aedde17a 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -25,8 +25,8 @@
#include "components/viz/service/hit_test/hit_test_aggregator.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
-#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom.h"
namespace viz {
@@ -111,7 +111,9 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
// SurfaceClient implementation.
void OnSurfaceActivated(Surface* surface) override;
void OnSurfaceDestroyed(Surface* surface) override;
- void OnSurfaceDrawn(Surface* surface) override;
+ void OnSurfaceWillDraw(Surface* surface) override;
+ void OnSurfaceWasDrawn(uint32_t frame_token,
+ base::TimeTicks draw_start_timestamp) override;
void RefResources(
const std::vector<TransferableResource>& resources) override;
void UnrefResources(const std::vector<ReturnedResource>& resources) override;
@@ -211,10 +213,10 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
SurfaceReference MakeTopLevelRootReference(const SurfaceId& surface_id);
void DidReceiveCompositorFrameAck();
- void DidPresentCompositorFrame(uint32_t presentation_token,
+ void DidPresentCompositorFrame(uint32_t frame_token,
const gfx::PresentationFeedback& feedback);
void DidRejectCompositorFrame(
- uint32_t presentation_token,
+ uint32_t frame_token,
std::vector<TransferableResource> frame_resource_list);
// Update the display root reference with |surface|.
@@ -324,6 +326,11 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
bool callback_received_receive_ack_ = true;
uint32_t trace_sequence_ = 0;
+ // Contains FrameTimingDetails for in-flight frames that have not yet been
+ // presented or aborted. After presentation the details are moved into
+ // |frame_timing_details_| which is sent to the client and cleared with each
+ // OnBeginFrame()
+ FrameTimingDetailsMap pending_frame_timing_details_;
FrameTimingDetailsMap frame_timing_details_;
LocalSurfaceId last_evicted_local_surface_id_;
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index 14ab075d5a6..21de0625c57 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -22,8 +22,8 @@
#include "components/viz/test/fake_external_begin_frame_source.h"
#include "components/viz/test/fake_surface_observer.h"
#include "components/viz/test/mock_compositor_frame_sink_client.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -225,6 +225,7 @@ class CompositorFrameSinkSupportTest : public testing::Test {
void SendPresentationFeedback(CompositorFrameSinkSupport* support,
uint32_t frame_token) {
+ support->OnSurfaceWasDrawn(frame_token, base::TimeTicks::Now());
support->DidPresentCompositorFrame(
frame_token,
gfx::PresentationFeedback(base::TimeTicks::Now(),
@@ -1241,4 +1242,87 @@ TEST_F(CompositorFrameSinkSupportTest, EvictThenReparent) {
GetSurfaceForId(SurfaceId(support_->frame_sink_id(), local_surface_id2)));
}
+// Verifies that invalid hit test region does not get submitted.
+TEST_F(CompositorFrameSinkSupportTest, HitTestRegionValidation) {
+ constexpr FrameSinkId frame_sink_id(1234, 5678);
+ manager_.RegisterFrameSinkId(frame_sink_id, true /* report_activation */);
+ auto support = std::make_unique<CompositorFrameSinkSupport>(
+ &fake_support_client_, &manager_, frame_sink_id, kIsRoot,
+ kNeedsSyncPoints);
+ LocalSurfaceId local_surface_id(6, 1, base::UnguessableToken::Create());
+
+ HitTestRegionList hit_test_region_list;
+
+ // kHitTestAsk not set, async_hit_test_reasons not set.
+ HitTestRegion hit_test_region_1;
+ hit_test_region_1.frame_sink_id = frame_sink_id;
+ hit_test_region_1.flags = HitTestRegionFlags::kHitTestMine;
+ hit_test_region_1.rect.SetRect(100, 100, 200, 400);
+
+ hit_test_region_list.regions.push_back(std::move(hit_test_region_1));
+
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 0u);
+ support->MaybeSubmitCompositorFrame(
+ local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+ // hit_test_region_1 is valid. Submitted region count increases.
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 1u);
+ hit_test_region_list.regions.clear();
+
+ // kHitTestAsk set, async_hit_test_reasons not set.
+ HitTestRegion hit_test_region_2;
+ hit_test_region_2.frame_sink_id = frame_sink_id;
+ hit_test_region_2.flags = HitTestRegionFlags::kHitTestAsk;
+ hit_test_region_2.rect.SetRect(400, 100, 300, 400);
+
+ hit_test_region_list.regions.push_back(std::move(hit_test_region_2));
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 1u);
+ support->MaybeSubmitCompositorFrame(
+ local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+ // hit_test_region_2 is invalid. Submitted region count does not change.
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 1u);
+
+ // kHitTestAsk not set, async_hit_test_reasons set.
+ HitTestRegion hit_test_region_3;
+ hit_test_region_3.frame_sink_id = frame_sink_id;
+ hit_test_region_3.async_hit_test_reasons =
+ AsyncHitTestReasons::kOverlappedRegion;
+ hit_test_region_3.rect.SetRect(400, 100, 300, 400);
+
+ hit_test_region_list.regions.clear();
+ hit_test_region_list.regions.push_back(std::move(hit_test_region_3));
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 1u);
+ support->MaybeSubmitCompositorFrame(
+ local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+ // hit_test_region_3 is invalid. Submitted region count does not change.
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 1u);
+
+ // kHitTestAsk set, async_hit_test_reasons set.
+ HitTestRegion hit_test_region_4;
+ hit_test_region_4.frame_sink_id = frame_sink_id;
+ hit_test_region_4.flags = HitTestRegionFlags::kHitTestAsk;
+ hit_test_region_4.async_hit_test_reasons =
+ AsyncHitTestReasons::kOverlappedRegion;
+ hit_test_region_4.rect.SetRect(400, 100, 300, 400);
+
+ hit_test_region_list.regions.clear();
+ hit_test_region_list.regions.push_back(std::move(hit_test_region_4));
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 1u);
+ support->MaybeSubmitCompositorFrame(
+ local_surface_id, MakeDefaultCompositorFrame(), hit_test_region_list, 0,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
+ // hit_test_region_4 is valid. Submitted region count increases.
+ EXPECT_EQ(manager_.hit_test_manager()->submit_hit_test_region_list_index(),
+ 2u);
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index 26e97b80ea7..6a1979ccddb 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -72,7 +72,8 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
scoped_refptr<ContextProvider> context_provider,
scoped_refptr<RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ bool hit_test_data_from_surface_layer)
: LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
std::move(compositor_task_runner),
@@ -87,7 +88,8 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
cc::GetClientNameForMetrics())),
submit_begin_frame_histogram_(GetHistogramNamed(
"GraphicsPipeline.%s.SubmitCompositorFrameAfterBeginFrame",
- cc::GetClientNameForMetrics())) {
+ cc::GetClientNameForMetrics())),
+ hit_test_data_from_surface_layer_(hit_test_data_from_surface_layer) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
@@ -163,13 +165,19 @@ void DirectLayerTreeFrameSink::SubmitCompositorFrame(
TRACE_EVENT_FLAG_FLOW_OUT, "step",
"SubmitHitTestData");
- base::Optional<HitTestRegionList> hit_test_region_list(
- HitTestDataBuilder::CreateHitTestData(
- frame, /*root_accepts_events=*/true,
- /*should_ask_for_child_region=*/false));
+ base::Optional<HitTestRegionList> hit_test_region_list;
+ if (!hit_test_data_from_surface_layer_) {
+ hit_test_region_list = HitTestDataBuilder::CreateHitTestData(
+ frame, /*root_accepts_events=*/true,
+ /*should_ask_for_child_region=*/false);
+ } else {
+ hit_test_region_list = client_->BuildHitTestData();
+ }
- // Do not send duplicate hit-test data.
- if (!hit_test_data_changed) {
+ if (!hit_test_region_list) {
+ last_hit_test_data_ = HitTestRegionList();
+ } else if (!hit_test_data_changed) {
+ // Do not send duplicate hit-test data.
if (HitTestRegionList::IsEqual(*hit_test_region_list,
last_hit_test_data_)) {
DCHECK(!HitTestRegionList::IsEqual(*hit_test_region_list,
@@ -179,7 +187,7 @@ void DirectLayerTreeFrameSink::SubmitCompositorFrame(
last_hit_test_data_ = *hit_test_region_list;
}
} else {
- last_hit_test_data_ = HitTestRegionList();
+ last_hit_test_data_ = *hit_test_region_list;
}
support_->SubmitCompositorFrame(
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
index f8d3d1f1fc7..7147396ec9f 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -16,8 +16,8 @@
#include "components/viz/service/display/display_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
namespace base {
class HistogramBase;
@@ -73,7 +73,8 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
scoped_refptr<ContextProvider> context_provider,
scoped_refptr<RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ bool hit_test_data_from_surface_layer);
~DirectLayerTreeFrameSink() override;
// LayerTreeFrameSink implementation.
@@ -149,6 +150,8 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
// GraphicsPipeline.ClientName.SubmitCompositorFrameAfterBeginFrame
base::HistogramBase* const submit_begin_frame_histogram_;
+ const bool hit_test_data_from_surface_layer_;
+
base::WeakPtrFactory<DirectLayerTreeFrameSink> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DirectLayerTreeFrameSink);
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index cfd16480313..0f910e308af 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -87,7 +87,8 @@ class DirectLayerTreeFrameSinkTest : public testing::Test {
layer_tree_frame_sink_ = std::make_unique<TestDirectLayerTreeFrameSink>(
kArbitraryFrameSinkId, &support_manager_, &frame_sink_manager_,
display_.get(), nullptr /* display_client */, context_provider_,
- nullptr, task_runner_, &gpu_memory_buffer_manager_);
+ nullptr, task_runner_, &gpu_memory_buffer_manager_,
+ false /* use surface layer to create hit test data */);
layer_tree_frame_sink_->BindToClient(&layer_tree_frame_sink_client_);
display_->Resize(display_size_);
display_->SetVisible(true);
diff --git a/chromium/components/viz/service/frame_sinks/external_begin_frame_source_mojo.h b/chromium/components/viz/service/frame_sinks/external_begin_frame_source_mojo.h
index 13460b3ef8c..ca394c1063d 100644
--- a/chromium/components/viz/service/frame_sinks/external_begin_frame_source_mojo.h
+++ b/chromium/components/viz/service/frame_sinks/external_begin_frame_source_mojo.h
@@ -11,7 +11,7 @@
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/service/display/display.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "services/viz/privileged/interfaces/compositing/external_begin_frame_controller.mojom.h"
+#include "services/viz/privileged/mojom/compositing/external_begin_frame_controller.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index 10288edc82b..8284c162b46 100644
--- a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -35,9 +35,9 @@
#include "components/viz/service/viz_service_export.h"
#include "gpu/ipc/common/surface_handle.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
-#include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
+#include "services/viz/public/mojom/compositing/video_detector_observer.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
index f457d18bc0c..7af0101848b 100644
--- a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -78,10 +78,6 @@ RootCompositorFrameSinkImpl::Create(
external_begin_frame_source =
std::make_unique<ExternalBeginFrameSourceAndroid>(restart_id,
params->refresh_rate);
- if (output_surface->context_provider() &&
- output_surface->context_provider()->ContextCapabilities().surfaceless) {
- external_begin_frame_source->AllowOneBeginFrameAfterGpuBusy();
- }
#else
if (params->disable_frame_rate_limit) {
synthetic_begin_frame_source =
@@ -135,10 +131,14 @@ RootCompositorFrameSinkImpl::Create(
std::move(synthetic_begin_frame_source),
std::move(external_begin_frame_source), std::move(display)));
- // TODO(kylechar): For the cases where we expect browser to providing vsync
- // parameter updates over mojo we shouldn't create |update_vsync_callback|.
- // I think this is always the case on mac.
- if (impl->synthetic_begin_frame_source_) {
+#if defined(OS_MACOSX)
+ // On Mac vsync parameter updates come from the browser process. We don't need
+ // to provide a callback to the OutputSurface since it should never use it.
+ constexpr bool wants_vsync_updates = false;
+#else
+ constexpr bool wants_vsync_updates = true;
+#endif
+ if (wants_vsync_updates && impl->synthetic_begin_frame_source_) {
// |impl| owns and outlives display, and display owns the output surface so
// unretained is safe.
output_surface_ptr->SetUpdateVSyncParametersCallback(base::BindRepeating(
diff --git a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
index 0e4428284a6..34e18572b09 100644
--- a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
+++ b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -15,9 +15,9 @@
#include "components/viz/service/display/display_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
index 17eb480b87a..f9e8595c67e 100644
--- a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -3073,4 +3073,20 @@ TEST_F(SurfaceSynchronizationTest,
EXPECT_EQ(parent_id2, parent_support().last_activated_surface_id());
}
+// Regression test for https://crbug.com/1000868. Verify that the output of
+// GetLatestInFlightSurface is correct when there is a conflict between the last
+// surface in the group and the queried SurfaceRange.
+TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceConflict) {
+ const SurfaceId id1 = MakeSurfaceId(kParentFrameSink, 1, 1);
+ const SurfaceId id2 = MakeSurfaceId(kParentFrameSink, 2, 2);
+ const SurfaceId id3 = MakeSurfaceId(kParentFrameSink, 1, 3);
+
+ parent_support().SubmitCompositorFrame(id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ parent_support().SubmitCompositorFrame(id2.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ EXPECT_EQ(GetSurfaceForId(id1),
+ GetLatestInFlightSurface(SurfaceRange(base::nullopt, id3)));
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index 5da57fc3bee..64c1dcbc25c 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -11,7 +11,9 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/read_only_shared_memory_region.h"
+#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -31,6 +33,13 @@ using media::VideoCaptureOracle;
using media::VideoFrame;
using media::VideoFrameMetadata;
+#define UMA_HISTOGRAM_CAPTURE_DURATION_CUSTOM_TIMES(name, sample) \
+ UMA_HISTOGRAM_CUSTOM_TIMES( \
+ base::StringPrintf("Viz.FrameSinkVideoCapturer.%s.CaptureDuration", \
+ name), \
+ sample, base::TimeDelta::FromMilliseconds(1), \
+ base::TimeDelta::FromSeconds(1), 50)
+
namespace viz {
namespace {
@@ -587,7 +596,7 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
oracle_frame_number, content_version_, content_rect,
VideoCaptureOverlay::MakeCombinedRenderer(
GetOverlaysInOrder(), content_rect, frame->format()),
- std::move(frame))));
+ std::move(frame), base::TimeTicks::Now())));
request->set_source(copy_request_source_);
request->set_area(gfx::Rect(source_size));
request->SetScaleRatio(
@@ -612,6 +621,7 @@ void FrameSinkVideoCapturerImpl::DidCopyFrame(
const gfx::Rect& content_rect,
VideoCaptureOverlay::OnceRenderer overlay_renderer,
scoped_refptr<VideoFrame> frame,
+ base::TimeTicks request_time,
std::unique_ptr<CopyOutputResult> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_GE(capture_frame_number, next_delivery_frame_number_);
@@ -639,23 +649,34 @@ void FrameSinkVideoCapturerImpl::DidCopyFrame(
uint8_t* const v = frame->visible_data(VideoFrame::kVPlane) +
(content_rect.y() / 2) * v_stride +
(content_rect.x() / 2);
- if (result->ReadI420Planes(y, y_stride, u, u_stride, v, v_stride)) {
+ bool success =
+ result->ReadI420Planes(y, y_stride, u, u_stride, v, v_stride);
+ if (success) {
// Per CopyOutputResult header comments, I420_PLANES results are always in
// the Rec.709 color space.
frame->set_color_space(gfx::ColorSpace::CreateREC709());
+ UMA_HISTOGRAM_CAPTURE_DURATION_CUSTOM_TIMES(
+ "I420", base::TimeTicks::Now() - request_time);
} else {
frame = nullptr;
}
+ UMA_HISTOGRAM_BOOLEAN("Viz.FrameSinkVideoCapturer.I420.CaptureSucceeded",
+ success);
} else {
int stride = frame->stride(VideoFrame::kARGBPlane);
DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format_);
uint8_t* const pixels = frame->visible_data(VideoFrame::kARGBPlane) +
content_rect.y() * stride + content_rect.x() * 4;
- if (result->ReadRGBAPlane(pixels, stride)) {
+ bool success = result->ReadRGBAPlane(pixels, stride);
+ if (success) {
frame->set_color_space(result->GetRGBAColorSpace());
+ UMA_HISTOGRAM_CAPTURE_DURATION_CUSTOM_TIMES(
+ "RGBA", base::TimeTicks::Now() - request_time);
} else {
frame = nullptr;
}
+ UMA_HISTOGRAM_BOOLEAN("Viz.FrameSinkVideoCapturer.RGBA.CaptureSucceeded",
+ success);
}
if (frame) {
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
index bef63ca58d8..e92ff6c5afa 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -30,7 +30,7 @@
#include "media/base/video_frame.h"
#include "media/capture/content/video_capture_oracle.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -195,6 +195,7 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
const gfx::Rect& content_rect,
VideoCaptureOverlay::OnceRenderer overlay_renderer,
scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks request_time,
std::unique_ptr<CopyOutputResult> result);
// Places the frame in the |delivery_queue_| and calls MaybeDeliverFrame(),
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
index 68b0214e1ae..c99df2b02c7 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -22,7 +22,7 @@
#include "media/base/limits.h"
#include "media/base/video_util.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h b/chromium/components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h
index 0e7ff88e709..871f8a497b7 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h
@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay.h b/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay.h
index e48d28645ad..2de2e7ed62f 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay.h
@@ -17,7 +17,7 @@
#include "components/viz/service/viz_service_export.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/color_transform.h"
diff --git a/chromium/components/viz/service/frame_sinks/video_detector.h b/chromium/components/viz/service/frame_sinks/video_detector.h
index e0784b4d368..970b8b144a0 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector.h
+++ b/chromium/components/viz/service/frame_sinks/video_detector.h
@@ -14,7 +14,7 @@
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/viz_service_export.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
-#include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h"
+#include "services/viz/public/mojom/compositing/video_detector_observer.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc b/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
index f09973e8542..1c411e990cc 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
@@ -21,7 +21,7 @@
#include "components/viz/test/fake_compositor_frame_sink_client.h"
#include "components/viz/test/surface_id_allocator_set.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h"
+#include "services/viz/public/mojom/compositing/video_detector_observer.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/components/viz/service/gl/DEPS b/chromium/components/viz/service/gl/DEPS
index acdf01cd623..a24294a1e7c 100644
--- a/chromium/components/viz/service/gl/DEPS
+++ b/chromium/components/viz/service/gl/DEPS
@@ -15,6 +15,6 @@ include_rules = [
"+media/gpu",
"+media/mojo",
"+mojo/public/cpp",
- "+services/viz/privileged/interfaces",
+ "+services/viz/privileged/mojom",
"+ui/gl",
]
diff --git a/chromium/components/viz/service/gl/OWNERS b/chromium/components/viz/service/gl/OWNERS
index 46bc527274b..2a2fdb63697 100644
--- a/chromium/components/viz/service/gl/OWNERS
+++ b/chromium/components/viz/service/gl/OWNERS
@@ -1,5 +1,4 @@
kbr@chromium.org
-piman@chromium.org
file://gpu/OWNERS
# COMPONENT: Internals>GPU>Internals
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.cc b/chromium/components/viz/service/gl/gpu_service_impl.cc
index 4ea81228a1b..3dd511bad54 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl.cc
@@ -63,7 +63,7 @@
#include "url/gurl.h"
#if BUILDFLAG(USE_VAAPI)
-#include "media/gpu/vaapi/vaapi_jpeg_decode_accelerator_worker.h"
+#include "media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h"
#endif // BUILDFLAG(USE_VAAPI)
#if defined(OS_ANDROID)
@@ -188,11 +188,8 @@ GpuServiceImpl::GpuServiceImpl(
#endif
#if BUILDFLAG(USE_VAAPI)
- if (base::FeatureList::IsEnabled(
- features::kVaapiJpegImageDecodeAcceleration)) {
- jpeg_decode_accelerator_worker_ =
- media::VaapiJpegDecodeAcceleratorWorker::Create();
- }
+ image_decode_accelerator_worker_ =
+ media::VaapiImageDecodeAcceleratorWorker::Create();
#endif
#if defined(OS_MACOSX)
@@ -223,6 +220,9 @@ GpuServiceImpl::~GpuServiceImpl() {
wait.Wait();
}
+ if (watchdog_thread_)
+ watchdog_thread_->OnGpuProcessTearDown();
+
media_gpu_channel_manager_.reset();
gpu_channel_manager_.reset();
@@ -234,7 +234,7 @@ GpuServiceImpl::~GpuServiceImpl() {
// The image decode accelerator worker must outlive the GPU channel manager so
// that it doesn't get any decode requests during/after destruction.
DCHECK(!gpu_channel_manager_);
- jpeg_decode_accelerator_worker_.reset();
+ image_decode_accelerator_worker_.reset();
// Signal this event before destroying the child process. That way all
// background threads can cleanup. For example, in the renderer the
@@ -259,9 +259,9 @@ void GpuServiceImpl::UpdateGPUInfo() {
gpu_info_.jpeg_decode_accelerator_supported =
IsAcceleratedJpegDecodeSupported();
- if (jpeg_decode_accelerator_worker_) {
+ if (image_decode_accelerator_worker_) {
gpu_info_.image_decode_accelerator_supported_profiles =
- jpeg_decode_accelerator_worker_->GetSupportedProfiles();
+ image_decode_accelerator_worker_->GetSupportedProfiles();
}
// Record initialization only after collecting the GPU info because that can
@@ -324,7 +324,7 @@ void GpuServiceImpl::InitializeWithHost(
scheduler_.get(), sync_point_manager, shared_image_manager,
gpu_memory_buffer_factory_.get(), gpu_feature_info_,
std::move(activity_flags), std::move(default_offscreen_surface),
- jpeg_decode_accelerator_worker_.get(), vulkan_context_provider(),
+ image_decode_accelerator_worker_.get(), vulkan_context_provider(),
metal_context_provider_.get());
media_gpu_channel_manager_.reset(
@@ -592,8 +592,8 @@ void GpuServiceImpl::UpdateGpuInfoPlatform(
// We can continue on shutdown here because we're not writing any critical
// state in this task.
base::PostTaskAndReplyWithResult(
- base::CreateCOMSTATaskRunnerWithTraits(
- {base::TaskPriority::USER_VISIBLE,
+ base::CreateCOMSTATaskRunner(
+ {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})
.get(),
FROM_HERE, base::BindOnce([]() {
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.h b/chromium/components/viz/service/gl/gpu_service_impl.h
index 56cd51045c6..71f5ca88a18 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.h
+++ b/chromium/components/viz/service/gl/gpu_service_impl.h
@@ -32,8 +32,8 @@
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
-#include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h"
-#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_host.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/native_widget_types.h"
@@ -259,7 +259,6 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void UpdateGpuInfoPlatform(base::OnceClosure on_gpu_info_updated);
-
#if defined(OS_CHROMEOS)
void CreateArcVideoDecodeAcceleratorOnMainThread(
arc::mojom::VideoDecodeAcceleratorRequest vda_request);
@@ -282,6 +281,8 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
scoped_refptr<base::SingleThreadTaskRunner> main_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
+ // Do not change the class member order here. watchdog_thread_ should be the
+ // last one to be destroyed before main_runner_ and io_runner_.
std::unique_ptr<gpu::GpuWatchdogThread> watchdog_thread_;
const gpu::GpuPreferences gpu_preferences_;
@@ -329,10 +330,10 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
base::OnceClosure exit_callback_;
base::AtomicFlag is_exiting_;
- // Used for performing hardware decode acceleration of JPEG images. This is
- // shared by all the GPU channels.
+ // Used for performing hardware decode acceleration of images. This is shared
+ // by all the GPU channels.
std::unique_ptr<gpu::ImageDecodeAcceleratorWorker>
- jpeg_decode_accelerator_worker_;
+ image_decode_accelerator_worker_;
base::Time start_time_;
diff --git a/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc b/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
index 70e0a75a30d..72ec7d5d9f2 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
@@ -18,7 +18,7 @@
#include "gpu/ipc/service/gpu_watchdog_thread.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/viz/public/interfaces/gpu.mojom.h"
+#include "services/viz/public/mojom/gpu.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/init/gl_factory.h"
diff --git a/chromium/components/viz/service/hit_test/hit_test_manager.cc b/chromium/components/viz/service/hit_test/hit_test_manager.cc
index 8c2239d64d3..2f8178ccc36 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.cc
@@ -14,6 +14,16 @@ namespace {
// TODO(gklassen): Review and select appropriate sizes based on
// telemetry / UMA.
constexpr uint32_t kMaxRegionsPerSurface = 1024;
+
+// Whenever a hit test region is marked as kHitTestAsk there must be a reason
+// for async hit test and vice versa.
+bool FlagsAndAsyncReasonsMatch(uint32_t flags,
+ uint32_t async_hit_test_reasons) {
+ if (flags & kHitTestAsk)
+ return async_hit_test_reasons != kNotAsyncHitTest;
+ return async_hit_test_reasons == kNotAsyncHitTest;
+}
+
} // namespace
HitTestManager::HitTestAsyncQueriedDebugRegion::
@@ -156,6 +166,11 @@ bool HitTestManager::ValidateHitTestRegionList(
HitTestRegionList* hit_test_region_list) {
if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
return false;
+ if (!FlagsAndAsyncReasonsMatch(
+ hit_test_region_list->flags,
+ hit_test_region_list->async_hit_test_reasons)) {
+ return false;
+ }
for (auto& region : hit_test_region_list->regions) {
// TODO(gklassen): Ensure that |region->frame_sink_id| is a child of
// |frame_sink_id|.
@@ -163,6 +178,8 @@ bool HitTestManager::ValidateHitTestRegionList(
region.frame_sink_id = FrameSinkId(surface_id.frame_sink_id().client_id(),
region.frame_sink_id.sink_id());
}
+ if (!FlagsAndAsyncReasonsMatch(region.flags, region.async_hit_test_reasons))
+ return false;
}
return true;
}
diff --git a/chromium/components/viz/service/hit_test/hit_test_manager.h b/chromium/components/viz/service/hit_test/hit_test_manager.h
index f2bc9afd97e..ce2c6abc1b4 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.h
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.h
@@ -12,7 +12,7 @@
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
+#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom.h"
namespace viz {
diff --git a/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc b/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc
index cb9ed54c995..4e51905ec82 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
#include <string.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
#include <vector>
#include "base/command_line.h"
@@ -16,7 +18,6 @@
#include "components/viz/service/hit_test/hit_test_manager.h"
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/test_latest_local_surface_id_lookup_delegate.h"
-#include "third_party/libFuzzer/src/utils/FuzzedDataProvider.h"
namespace {
diff --git a/chromium/components/viz/service/main/BUILD.gn b/chromium/components/viz/service/main/BUILD.gn
index 6a8487ac429..e4f4444f206 100644
--- a/chromium/components/viz/service/main/BUILD.gn
+++ b/chromium/components/viz/service/main/BUILD.gn
@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/config/ui.gni")
-import("//components/ui_devtools/devtools.gni")
import("//testing/test.gni")
source_set("main") {
@@ -12,8 +11,9 @@ source_set("main") {
defines = []
sources = [
- "viz_compositor_thread_runner.cc",
"viz_compositor_thread_runner.h",
+ "viz_compositor_thread_runner_impl.cc",
+ "viz_compositor_thread_runner_impl.h",
"viz_main_impl.cc",
"viz_main_impl.h",
]
@@ -33,7 +33,7 @@ source_set("main") {
"//services/metrics/public/cpp:metrics_cpp",
"//services/metrics/public/mojom",
"//services/service_manager/public/cpp",
- "//services/viz/privileged/interfaces",
+ "//services/viz/privileged/mojom",
"//ui/gfx:memory_buffer",
"//ui/gl/init",
]
@@ -49,8 +49,4 @@ source_set("main") {
if (is_chromeos) {
deps += [ "//media/gpu" ]
}
-
- if (use_viz_devtools) {
- defines += [ "USE_VIZ_DEVTOOLS" ]
- }
}
diff --git a/chromium/components/viz/service/main/DEPS b/chromium/components/viz/service/main/DEPS
index 35e496347ba..5461b0f6d01 100644
--- a/chromium/components/viz/service/main/DEPS
+++ b/chromium/components/viz/service/main/DEPS
@@ -3,6 +3,7 @@
include_rules = [
"+components/discardable_memory/client",
"+components/ui_devtools",
+ "+components/viz/common/features.h",
"+components/viz/common/switches.h",
"+components/viz/service",
"+gpu/command_buffer",
@@ -15,5 +16,5 @@ include_rules = [
"+services/metrics/public",
"+services/network/public/mojom",
"+services/service_manager/public/cpp",
- "+services/viz/privileged/interfaces",
+ "+services/viz/privileged/mojom",
]
diff --git a/chromium/components/viz/service/main/viz_compositor_thread_runner.h b/chromium/components/viz/service/main/viz_compositor_thread_runner.h
index a49118571e9..b45c4517ecb 100644
--- a/chromium/components/viz/service/main/viz_compositor_thread_runner.h
+++ b/chromium/components/viz/service/main/viz_compositor_thread_runner.h
@@ -1,47 +1,25 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_SERVICE_MAIN_VIZ_COMPOSITOR_THREAD_RUNNER_H_
#define COMPONENTS_VIZ_SERVICE_MAIN_VIZ_COMPOSITOR_THREAD_RUNNER_H_
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/message_loop/message_loop.h"
-#include "build/build_config.h"
-#include "services/network/public/mojom/tcp_socket.mojom.h"
-#include "services/viz/privileged/interfaces/viz_main.mojom.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/java_handler_thread.h"
-#endif
+#include "base/callback.h"
+#include "components/ui_devtools/buildflags.h"
+#include "services/viz/privileged/mojom/viz_main.mojom.h"
namespace base {
class SingleThreadTaskRunner;
-class Thread;
-} // namespace base
+}
namespace gpu {
class CommandBufferTaskExecutor;
} // namespace gpu
-namespace ui_devtools {
-class UiDevToolsServer;
-} // namespace ui_devtools
-
namespace viz {
-class OutputSurfaceProvider;
-class FrameSinkManagerImpl;
-class GpuServiceImpl;
-class ServerSharedBitmapManager;
-#if defined(OS_ANDROID)
-using VizCompositorThreadType = base::android::JavaHandlerThread;
-#else
-using VizCompositorThreadType = base::Thread;
-#endif
+class GpuServiceImpl;
// Starts and runs the VizCompositorThread. The thread will be started when this
// object is constructed. Objects on the thread will be initialized after
@@ -49,24 +27,24 @@ using VizCompositorThreadType = base::Thread;
// and then stop the thread.
class VizCompositorThreadRunner {
public:
- explicit VizCompositorThreadRunner(base::MessageLoop::Type message_loop_type);
- // Performs teardown on thread and then stops thread.
- ~VizCompositorThreadRunner();
+ virtual ~VizCompositorThreadRunner() = default;
// Returns the TaskRunner for VizCompositorThread.
- base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); }
+ virtual base::SingleThreadTaskRunner* task_runner() = 0;
// Creates FrameSinkManager from |params|. The version with |gpu_service| and
// |task_executor| supports both GPU and software compositing, while the
// version without supports only software compositing. Should be called from
// the thread that owns |this| to initialize state on VizCompositorThread.
- void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params);
- void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params,
- gpu::CommandBufferTaskExecutor* task_executor,
- GpuServiceImpl* gpu_service);
+ virtual void CreateFrameSinkManager(
+ mojom::FrameSinkManagerParamsPtr params) = 0;
+ virtual void CreateFrameSinkManager(
+ mojom::FrameSinkManagerParamsPtr params,
+ gpu::CommandBufferTaskExecutor* task_executor,
+ GpuServiceImpl* gpu_service) = 0;
-#if defined(USE_VIZ_DEVTOOLS)
- void CreateVizDevTools(mojom::VizDevToolsParamsPtr params);
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
+ virtual void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) = 0;
#endif
// Performs cleanup on VizCompositorThread needed before forcing thread to
@@ -78,37 +56,8 @@ class VizCompositorThreadRunner {
// This is intended to be used when the GPU thread wants to force restart. The
// cleanup is normally handled by the browser process before GPU process
// shutdown, except if the GPU thread is forcing restart.
- void CleanupForShutdown(base::OnceClosure cleanup_finished_callback);
-
- private:
- void CreateFrameSinkManagerOnCompositorThread(
- mojom::FrameSinkManagerParamsPtr params,
- gpu::CommandBufferTaskExecutor* task_executor,
- GpuServiceImpl* gpu_service);
-#if defined(USE_VIZ_DEVTOOLS)
- void CreateVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
- void InitVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
-#endif
- void CleanupForShutdownOnCompositorThread();
- void TearDownOnCompositorThread();
-
- // Start variables to be accessed only on |task_runner_|.
- std::unique_ptr<ServerSharedBitmapManager> server_shared_bitmap_manager_;
- std::unique_ptr<OutputSurfaceProvider> output_surface_provider_;
- std::unique_ptr<FrameSinkManagerImpl> frame_sink_manager_;
-#if defined(USE_VIZ_DEVTOOLS)
- std::unique_ptr<ui_devtools::UiDevToolsServer> devtools_server_;
-
- // If the FrameSinkManager is not ready yet, then we stash the pending
- // VizDevToolsParams.
- mojom::VizDevToolsParamsPtr pending_viz_dev_tools_params_;
-#endif
- // End variables to be accessed only on |task_runner_|.
-
- std::unique_ptr<VizCompositorThreadType> thread_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(VizCompositorThreadRunner);
+ virtual void CleanupForShutdown(
+ base::OnceClosure cleanup_finished_callback) = 0;
};
} // namespace viz
diff --git a/chromium/components/viz/service/main/viz_compositor_thread_runner.cc b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc
index a6434b9d7cb..59b6ff4a68d 100644
--- a/chromium/components/viz/service/main/viz_compositor_thread_runner.cc
+++ b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc
@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/viz/service/main/viz_compositor_thread_runner.h"
+#include "components/viz/service/main/viz_compositor_thread_runner_impl.h"
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "components/viz/common/features.h"
#include "components/viz/common/switches.h"
#include "components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h"
#include "components/viz/service/display_embedder/output_surface_provider_impl.h"
@@ -23,10 +25,11 @@
#include "gpu/config/gpu_finch_features.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/ipc/command_buffer_task_executor.h"
+#include "gpu/ipc/scheduler_sequence.h"
#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
#include "ui/gfx/switches.h"
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
#include "components/ui_devtools/css_agent.h"
#include "components/ui_devtools/devtools_server.h"
#include "components/ui_devtools/viz/dom_agent_viz.h"
@@ -38,8 +41,7 @@ namespace {
const char kThreadName[] = "VizCompositorThread";
-std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread(
- base::MessageLoop::Type message_loop_type) {
+std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread() {
const base::ThreadPriority thread_priority =
base::FeatureList::IsEnabled(features::kGpuUseDisplayThreadPriority)
? base::ThreadPriority::DISPLAY
@@ -53,7 +55,11 @@ std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread(
auto thread = std::make_unique<base::Thread>(kThreadName);
base::Thread::Options thread_options;
- thread_options.message_loop_type = message_loop_type;
+
+#if defined(OS_FUCHSIA)
+ // An IO message pump is needed to use FIDL.
+ thread_options.message_pump_type = base::MessagePumpType::IO;
+#endif
#if defined(OS_MACOSX)
// Increase the thread priority to get more reliable values in performance
@@ -74,71 +80,76 @@ std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread(
} // namespace
-VizCompositorThreadRunner::VizCompositorThreadRunner(
- base::MessageLoop::Type message_loop_type)
- : thread_(CreateAndStartCompositorThread(message_loop_type)),
+VizCompositorThreadRunnerImpl::VizCompositorThreadRunnerImpl()
+ : thread_(CreateAndStartCompositorThread()),
task_runner_(thread_->task_runner()) {}
-VizCompositorThreadRunner::~VizCompositorThreadRunner() {
+VizCompositorThreadRunnerImpl::~VizCompositorThreadRunnerImpl() {
task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&VizCompositorThreadRunner::TearDownOnCompositorThread,
+ base::BindOnce(&VizCompositorThreadRunnerImpl::TearDownOnCompositorThread,
base::Unretained(this)));
thread_->Stop();
}
-void VizCompositorThreadRunner::CreateFrameSinkManager(
+base::SingleThreadTaskRunner* VizCompositorThreadRunnerImpl::task_runner() {
+ return task_runner_.get();
+}
+
+void VizCompositorThreadRunnerImpl::CreateFrameSinkManager(
mojom::FrameSinkManagerParamsPtr params) {
task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread,
- base::Unretained(this), std::move(params), nullptr, nullptr));
+ FROM_HERE, base::BindOnce(&VizCompositorThreadRunnerImpl::
+ CreateFrameSinkManagerOnCompositorThread,
+ base::Unretained(this), std::move(params),
+ nullptr, nullptr));
}
-void VizCompositorThreadRunner::CreateFrameSinkManager(
+void VizCompositorThreadRunnerImpl::CreateFrameSinkManager(
mojom::FrameSinkManagerParamsPtr params,
gpu::CommandBufferTaskExecutor* task_executor,
GpuServiceImpl* gpu_service) {
// All of the unretained objects are owned on the GPU thread and destroyed
// after VizCompositorThread has been shutdown.
task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- &VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread,
- base::Unretained(this), std::move(params),
- base::Unretained(task_executor), base::Unretained(gpu_service)));
+ FROM_HERE, base::BindOnce(&VizCompositorThreadRunnerImpl::
+ CreateFrameSinkManagerOnCompositorThread,
+ base::Unretained(this), std::move(params),
+ base::Unretained(task_executor),
+ base::Unretained(gpu_service)));
}
-#if defined(USE_VIZ_DEVTOOLS)
-void VizCompositorThreadRunner::CreateVizDevTools(
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
+void VizCompositorThreadRunnerImpl::CreateVizDevTools(
mojom::VizDevToolsParamsPtr params) {
// It is safe to use Unretained(this) because |this| owns the |task_runner_|,
// and will outlive it.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
- &VizCompositorThreadRunner::CreateVizDevToolsOnCompositorThread,
+ &VizCompositorThreadRunnerImpl::CreateVizDevToolsOnCompositorThread,
base::Unretained(this), std::move(params)));
}
#endif
-void VizCompositorThreadRunner::CleanupForShutdown(
+void VizCompositorThreadRunnerImpl::CleanupForShutdown(
base::OnceClosure cleanup_finished_callback) {
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(
- &VizCompositorThreadRunner::CleanupForShutdownOnCompositorThread,
+ &VizCompositorThreadRunnerImpl::CleanupForShutdownOnCompositorThread,
base::Unretained(this)),
std::move(cleanup_finished_callback));
}
-void VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread(
+void VizCompositorThreadRunnerImpl::CreateFrameSinkManagerOnCompositorThread(
mojom::FrameSinkManagerParamsPtr params,
gpu::CommandBufferTaskExecutor* task_executor,
GpuServiceImpl* gpu_service) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!frame_sink_manager_);
+ if (features::IsUsingSkiaRenderer())
+ gpu::SchedulerSequence::DefaultDisallowScheduleTaskOnCurrentThread();
server_shared_bitmap_manager_ = std::make_unique<ServerSharedBitmapManager>();
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
@@ -187,14 +198,14 @@ void VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread(
mojom::FrameSinkManagerClientPtr(
std::move(params->frame_sink_manager_client)));
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
if (pending_viz_dev_tools_params_)
InitVizDevToolsOnCompositorThread(std::move(pending_viz_dev_tools_params_));
#endif
}
-#if defined(USE_VIZ_DEVTOOLS)
-void VizCompositorThreadRunner::CreateVizDevToolsOnCompositorThread(
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
+void VizCompositorThreadRunnerImpl::CreateVizDevToolsOnCompositorThread(
mojom::VizDevToolsParamsPtr params) {
if (!frame_sink_manager_) {
DCHECK(!pending_viz_dev_tools_params_);
@@ -204,7 +215,7 @@ void VizCompositorThreadRunner::CreateVizDevToolsOnCompositorThread(
InitVizDevToolsOnCompositorThread(std::move(params));
}
-void VizCompositorThreadRunner::InitVizDevToolsOnCompositorThread(
+void VizCompositorThreadRunnerImpl::InitVizDevToolsOnCompositorThread(
mojom::VizDevToolsParamsPtr params) {
DCHECK(frame_sink_manager_);
devtools_server_ = ui_devtools::UiDevToolsServer::CreateForViz(
@@ -224,14 +235,14 @@ void VizCompositorThreadRunner::InitVizDevToolsOnCompositorThread(
}
#endif
-void VizCompositorThreadRunner::CleanupForShutdownOnCompositorThread() {
+void VizCompositorThreadRunnerImpl::CleanupForShutdownOnCompositorThread() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (frame_sink_manager_)
frame_sink_manager_->ForceShutdown();
}
-void VizCompositorThreadRunner::TearDownOnCompositorThread() {
+void VizCompositorThreadRunnerImpl::TearDownOnCompositorThread() {
DCHECK(task_runner_->BelongsToCurrentThread());
if (server_shared_bitmap_manager_) {
@@ -239,7 +250,7 @@ void VizCompositorThreadRunner::TearDownOnCompositorThread() {
server_shared_bitmap_manager_.get());
}
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
devtools_server_.reset();
#endif
frame_sink_manager_.reset();
diff --git a/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h
new file mode 100644
index 00000000000..2cbcce4306c
--- /dev/null
+++ b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h
@@ -0,0 +1,91 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_MAIN_VIZ_COMPOSITOR_THREAD_RUNNER_IMPL_H_
+#define COMPONENTS_VIZ_SERVICE_MAIN_VIZ_COMPOSITOR_THREAD_RUNNER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/message_loop/message_loop.h"
+#include "build/build_config.h"
+#include "components/ui_devtools/buildflags.h"
+#include "components/viz/service/main/viz_compositor_thread_runner.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/java_handler_thread.h"
+#endif
+
+namespace base {
+class Thread;
+} // namespace base
+
+namespace ui_devtools {
+class UiDevToolsServer;
+} // namespace ui_devtools
+
+namespace viz {
+class OutputSurfaceProvider;
+class FrameSinkManagerImpl;
+class ServerSharedBitmapManager;
+
+#if defined(OS_ANDROID)
+using VizCompositorThreadType = base::android::JavaHandlerThread;
+#else
+using VizCompositorThreadType = base::Thread;
+#endif
+
+class VizCompositorThreadRunnerImpl : public VizCompositorThreadRunner {
+ public:
+ VizCompositorThreadRunnerImpl();
+ // Performs teardown on thread and then stops thread.
+ ~VizCompositorThreadRunnerImpl() override;
+
+ // VizCompositorThreadRunner overrides.
+ base::SingleThreadTaskRunner* task_runner() override;
+ void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params) override;
+ void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params,
+ gpu::CommandBufferTaskExecutor* task_executor,
+ GpuServiceImpl* gpu_service) override;
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
+ void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) override;
+#endif
+ void CleanupForShutdown(base::OnceClosure cleanup_finished_callback) override;
+
+ private:
+ void CreateFrameSinkManagerOnCompositorThread(
+ mojom::FrameSinkManagerParamsPtr params,
+ gpu::CommandBufferTaskExecutor* task_executor,
+ GpuServiceImpl* gpu_service);
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
+ void CreateVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
+ void InitVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
+#endif
+ void CleanupForShutdownOnCompositorThread();
+ void TearDownOnCompositorThread();
+
+ // Start variables to be accessed only on |task_runner_|.
+ std::unique_ptr<ServerSharedBitmapManager> server_shared_bitmap_manager_;
+ std::unique_ptr<OutputSurfaceProvider> output_surface_provider_;
+ std::unique_ptr<FrameSinkManagerImpl> frame_sink_manager_;
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
+ std::unique_ptr<ui_devtools::UiDevToolsServer> devtools_server_;
+
+ // If the FrameSinkManager is not ready yet, then we stash the pending
+ // VizDevToolsParams.
+ mojom::VizDevToolsParamsPtr pending_viz_dev_tools_params_;
+#endif
+ // End variables to be accessed only on |task_runner_|.
+
+ std::unique_ptr<VizCompositorThreadType> thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(VizCompositorThreadRunnerImpl);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_MAIN_VIZ_COMPOSITOR_THREAD_RUNNER_IMPL_H_
diff --git a/chromium/components/viz/service/main/viz_main_impl.cc b/chromium/components/viz/service/main/viz_main_impl.cc
index bfa49200242..36760c6e398 100644
--- a/chromium/components/viz/service/main/viz_main_impl.cc
+++ b/chromium/components/viz/service/main/viz_main_impl.cc
@@ -9,12 +9,13 @@
#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
#include "base/single_thread_task_runner.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
+#include "components/ui_devtools/buildflags.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "gpu/command_buffer/common/activity_flags.h"
#include "gpu/config/gpu_finch_features.h"
@@ -37,7 +38,7 @@ namespace {
std::unique_ptr<base::Thread> CreateAndStartIOThread() {
// TODO(sad): We do not need the IO thread once gpu has a separate process.
// It should be possible to use |main_task_runner_| for doing IO tasks.
- base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
+ base::Thread::Options thread_options(base::MessagePumpType::IO, 0);
// TODO(reveman): Remove this in favor of setting it explicitly for each
// type of process.
if (base::FeatureList::IsEnabled(features::kGpuUseDisplayThreadPriority))
@@ -81,8 +82,13 @@ VizMainImpl::VizMainImpl(Delegate* delegate,
if (!dependencies_.io_thread_task_runner)
io_thread_ = CreateAndStartIOThread();
if (dependencies_.create_display_compositor) {
- viz_compositor_thread_runner_ = std::make_unique<VizCompositorThreadRunner>(
- gpu_init_->gpu_preferences().message_loop_type);
+ if (dependencies.viz_compositor_thread_runner) {
+ viz_compositor_thread_runner_ = dependencies.viz_compositor_thread_runner;
+ } else {
+ viz_compositor_thread_runner_impl_ =
+ std::make_unique<VizCompositorThreadRunnerImpl>();
+ viz_compositor_thread_runner_ = viz_compositor_thread_runner_impl_.get();
+ }
if (delegate_) {
delegate_->PostCompositorThreadCreated(
viz_compositor_thread_runner_->task_runner());
@@ -115,11 +121,14 @@ VizMainImpl::~VizMainImpl() {
// need to process commands from the host as it is shutting down.
receiver_.reset();
- // If the VizCompositorThread was started then this will block until the
- // thread has been shutdown. All RootCompositorFrameSinks must be destroyed
- // before now, otherwise the compositor thread will deadlock waiting for a
- // response from the blocked GPU thread.
- viz_compositor_thread_runner_.reset();
+ // If the VizCompositorThread was started and owned by VizMainImpl, then this
+ // will block until the thread has been shutdown. All RootCompositorFrameSinks
+ // must be destroyed before now, otherwise the compositor thread will deadlock
+ // waiting for a response from the blocked GPU thread.
+ // For the non-owned case for Android WebView, Viz does not communicate with
+ // this thread so there is no need to shutdown viz first.
+ viz_compositor_thread_runner_ = nullptr;
+ viz_compositor_thread_runner_impl_.reset();
if (ukm_recorder_)
ukm::DelegatingUkmRecorder::Get()->RemoveDelegate(ukm_recorder_.get());
@@ -267,7 +276,7 @@ void VizMainImpl::CreateFrameSinkManagerInternal(
}
void VizMainImpl::CreateVizDevTools(mojom::VizDevToolsParamsPtr params) {
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
viz_compositor_thread_runner_->CreateVizDevTools(std::move(params));
#endif
}
diff --git a/chromium/components/viz/service/main/viz_main_impl.h b/chromium/components/viz/service/main/viz_main_impl.h
index c7cb93e4550..66f57eab59f 100644
--- a/chromium/components/viz/service/main/viz_main_impl.h
+++ b/chromium/components/viz/service/main/viz_main_impl.h
@@ -11,15 +11,15 @@
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
-#include "components/viz/service/main/viz_compositor_thread_runner.h"
+#include "components/viz/service/main/viz_compositor_thread_runner_impl.h"
#include "gpu/ipc/in_process_command_buffer.h"
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
-#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
-#include "services/viz/privileged/interfaces/viz_main.mojom.h"
+#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
+#include "services/viz/privileged/mojom/viz_main.mojom.h"
#include "ui/gfx/font_render_params.h"
#if defined(USE_OZONE)
@@ -84,6 +84,7 @@ class VizMainImpl : public mojom::VizMain {
base::WaitableEvent* shutdown_event = nullptr;
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner;
service_manager::Connector* connector = nullptr;
+ VizCompositorThreadRunner* viz_compositor_thread_runner = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(ExternalDependencies);
@@ -165,7 +166,13 @@ class VizMainImpl : public mojom::VizMain {
mojom::FrameSinkManagerParamsPtr pending_frame_sink_manager_params_;
// Runs the VizCompositorThread for the display compositor with OOP-D.
- std::unique_ptr<VizCompositorThreadRunner> viz_compositor_thread_runner_;
+ std::unique_ptr<VizCompositorThreadRunnerImpl>
+ viz_compositor_thread_runner_impl_;
+ // Note under Android WebView where VizCompositorThreadRunner is not created
+ // and owned by this, Viz does not interact with other objects in this class,
+ // such as GpuServiceImpl or CommandBufferTaskExecutor. Code should take care
+ // to avoid introducing such assumptions.
+ VizCompositorThreadRunner* viz_compositor_thread_runner_ = nullptr;
const scoped_refptr<base::SingleThreadTaskRunner> gpu_thread_task_runner_;
diff --git a/chromium/components/viz/service/surfaces/surface.cc b/chromium/components/viz/service/surfaces/surface.cc
index 8498fad225f..09987648bfe 100644
--- a/chromium/components/viz/service/surfaces/surface.cc
+++ b/chromium/components/viz/service/surfaces/surface.cc
@@ -26,9 +26,10 @@
namespace viz {
-Surface::PresentationHelper::PresentationHelper(base::WeakPtr<Surface> surface,
- uint32_t frame_token)
- : surface_(std::move(surface)), frame_token_(frame_token) {}
+Surface::PresentationHelper::PresentationHelper(
+ base::WeakPtr<SurfaceClient> surface_client,
+ uint32_t frame_token)
+ : surface_client_(std::move(surface_client)), frame_token_(frame_token) {}
Surface::PresentationHelper::~PresentationHelper() {
// The class that called TakePresentationHelperForPresentNotification
@@ -39,10 +40,10 @@ Surface::PresentationHelper::~PresentationHelper() {
void Surface::PresentationHelper::DidPresent(
const gfx::PresentationFeedback& feedback) {
- if (surface_ && frame_token_)
- surface_->DidPresentSurface(frame_token_, feedback);
+ if (surface_client_ && frame_token_)
+ surface_client_->OnSurfacePresented(frame_token_, feedback);
- surface_ = nullptr;
+ surface_client_ = nullptr;
}
Surface::Surface(const SurfaceInfo& surface_info,
@@ -589,17 +590,11 @@ Surface::TakePresentationHelperForPresentNotification() {
!active_frame_data_->will_be_notified_of_presentation) {
active_frame_data_->will_be_notified_of_presentation = true;
return std::make_unique<PresentationHelper>(
- GetWeakPtr(), active_frame_data_->frame.metadata.frame_token);
+ client(), active_frame_data_->frame.metadata.frame_token);
}
return nullptr;
}
-void Surface::DidPresentSurface(uint32_t presentation_token,
- const gfx::PresentationFeedback& feedback) {
- if (surface_client_)
- surface_client_->OnSurfacePresented(presentation_token, feedback);
-}
-
void Surface::SendAckToClient() {
if (!active_frame_data_ || active_frame_data_->frame_acked)
return;
@@ -613,7 +608,7 @@ void Surface::MarkAsDrawn() {
return;
active_frame_data_->frame_drawn = true;
if (surface_client_)
- surface_client_->OnSurfaceDrawn(this);
+ surface_client_->OnSurfaceWillDraw(this);
}
void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect,
@@ -642,9 +637,9 @@ void Surface::UnrefFrameResourcesAndRunCallbacks(
// If we won't be getting a presented notification, we'll notify the client
// when the frame is unref'd.
- if (!frame_data->will_be_notified_of_presentation)
- DidPresentSurface(frame_data->frame.metadata.frame_token,
- gfx::PresentationFeedback::Failure());
+ if (!frame_data->will_be_notified_of_presentation && surface_client_)
+ surface_client_->OnSurfacePresented(frame_data->frame.metadata.frame_token,
+ gfx::PresentationFeedback::Failure());
}
void Surface::ClearCopyRequests() {
@@ -715,6 +710,14 @@ void Surface::OnWillBeDrawn() {
MarkAsDrawn();
}
+void Surface::OnWasDrawn(uint32_t frame_token,
+ base::TimeTicks draw_start_timestamp) {
+ if (!surface_client_)
+ return;
+
+ surface_client_->OnSurfaceWasDrawn(frame_token, draw_start_timestamp);
+}
+
void Surface::ActivatePendingFrameForInheritedDeadline() {
DCHECK(HasPendingFrame());
// Deadline inheritance implies that this surface was blocking the embedder,
diff --git a/chromium/components/viz/service/surfaces/surface.h b/chromium/components/viz/service/surfaces/surface.h
index c57118ffb45..21aef17ca20 100644
--- a/chromium/components/viz/service/surfaces/surface.h
+++ b/chromium/components/viz/service/surfaces/surface.h
@@ -78,13 +78,15 @@ class VIZ_SERVICE_EXPORT Surface final {
public:
class PresentationHelper {
public:
- PresentationHelper(base::WeakPtr<Surface> surface, uint32_t frame_token);
+ PresentationHelper(base::WeakPtr<SurfaceClient> surface_client,
+ uint32_t frame_token);
~PresentationHelper();
void DidPresent(const gfx::PresentationFeedback& feedback);
+ uint32_t frame_token() const { return frame_token_; }
private:
- base::WeakPtr<Surface> surface_;
+ base::WeakPtr<SurfaceClient> surface_client_;
const uint32_t frame_token_;
DISALLOW_COPY_AND_ASSIGN(PresentationHelper);
@@ -186,8 +188,6 @@ class VIZ_SERVICE_EXPORT Surface final {
// PresentationHelper, at the appropriate point in the future.
std::unique_ptr<Surface::PresentationHelper>
TakePresentationHelperForPresentNotification();
- void DidPresentSurface(uint32_t presentation_token,
- const gfx::PresentationFeedback& feedback);
void SendAckToClient();
void MarkAsDrawn();
void NotifyAggregatedDamage(const gfx::Rect& damage_rect,
@@ -221,6 +221,10 @@ class VIZ_SERVICE_EXPORT Surface final {
// Called when this surface will be included in the next display frame.
void OnWillBeDrawn();
+ // Called after the display compositor finishes drawing the frame
+ // associated with frame_token.
+ void OnWasDrawn(uint32_t frame_token, base::TimeTicks draw_start_timestamp);
+
// Called when |surface_id| is activated for the first time and its part of a
// referenced SurfaceRange.
void OnChildActivatedForActiveFrame(const SurfaceId& surface_id);
diff --git a/chromium/components/viz/service/surfaces/surface_allocation_group.cc b/chromium/components/viz/service/surfaces/surface_allocation_group.cc
index 3104b56c2ff..d6308a5b112 100644
--- a/chromium/components/viz/service/surfaces/surface_allocation_group.cc
+++ b/chromium/components/viz/service/surfaces/surface_allocation_group.cc
@@ -188,7 +188,7 @@ SurfaceAllocationGroup::FindLatestSurfaceUpTo(
// If even the first surface is newer than |surface_id|, we can't find a
// surface that is older than or equal to |surface_id|.
- if (surfaces_[0]->surface_id().IsNewerThan(surface_id))
+ if (!surface_id.IsSameOrNewerThan(surfaces_[0]->surface_id()))
return surfaces_.end();
// Perform a binary search the find the latest surface that is older than or
@@ -197,12 +197,13 @@ SurfaceAllocationGroup::FindLatestSurfaceUpTo(
int end = surfaces_.size();
while (end - begin > 1) {
int avg = (begin + end) / 2;
- if (surfaces_[avg]->surface_id().IsNewerThan(surface_id))
+ if (!surface_id.IsSameOrNewerThan(surfaces_[avg]->surface_id()))
end = avg;
else
begin = avg;
}
+ DCHECK(surface_id.IsSameOrNewerThan(surfaces_[begin]->surface_id()));
return surfaces_.begin() + begin;
}
diff --git a/chromium/components/viz/service/surfaces/surface_client.h b/chromium/components/viz/service/surfaces/surface_client.h
index f7b71b275db..d46505a89c9 100644
--- a/chromium/components/viz/service/surfaces/surface_client.h
+++ b/chromium/components/viz/service/surfaces/surface_client.h
@@ -41,7 +41,11 @@ class VIZ_SERVICE_EXPORT SurfaceClient {
virtual void OnSurfaceDestroyed(Surface* surface) = 0;
// Called when a |surface| is about to be drawn.
- virtual void OnSurfaceDrawn(Surface* surface) = 0;
+ virtual void OnSurfaceWillDraw(Surface* surface) = 0;
+
+ // Called when a |surface| has been successfully drawn.
+ virtual void OnSurfaceWasDrawn(uint32_t frame_token,
+ base::TimeTicks draw_start_timestamp) = 0;
// Increments the reference count on resources specified by |resources|.
virtual void RefResources(
diff --git a/chromium/components/viz/test/BUILD.gn b/chromium/components/viz/test/BUILD.gn
index 57e32f87bc1..ec7227f11fd 100644
--- a/chromium/components/viz/test/BUILD.gn
+++ b/chromium/components/viz/test/BUILD.gn
@@ -79,7 +79,7 @@ viz_static_library("test_support") {
"//gpu:test_support",
"//gpu/command_buffer/client:gles2_implementation",
"//gpu/skia_bindings",
- "//services/viz/privileged/interfaces",
+ "//services/viz/privileged/mojom",
"//testing/gmock",
"//testing/gtest",
"//ui/gfx/geometry",
diff --git a/chromium/components/web_cache/OWNERS b/chromium/components/web_cache/OWNERS
index 3463baf5785..e8a333cdf98 100644
--- a/chromium/components/web_cache/OWNERS
+++ b/chromium/components/web_cache/OWNERS
@@ -3,3 +3,4 @@ jochen@chromium.org
sky@chromium.org
thakis@chromium.org
thestig@chromium.org
+# COMPONENT: Internals
diff --git a/chromium/components/web_cache/browser/web_cache_manager_unittest.cc b/chromium/components/web_cache/browser/web_cache_manager_unittest.cc
index 131fe00f969..b60551443a0 100644
--- a/chromium/components/web_cache/browser/web_cache_manager_unittest.cc
+++ b/chromium/components/web_cache/browser/web_cache_manager_unittest.cc
@@ -7,7 +7,7 @@
#include <string>
#include "components/web_cache/browser/web_cache_manager.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
@@ -94,7 +94,7 @@ class WebCacheManagerTest : public testing::Test {
private:
WebCacheManager manager_;
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
};
// static
diff --git a/chromium/components/web_modal/OWNERS b/chromium/components/web_modal/OWNERS
index 12a9b0975ce..f8ca2ece7b3 100644
--- a/chromium/components/web_modal/OWNERS
+++ b/chromium/components/web_modal/OWNERS
@@ -1 +1,2 @@
wittman@chromium.org
+# COMPONENT: UI>Browser>Core
diff --git a/chromium/components/web_resource/BUILD.gn b/chromium/components/web_resource/BUILD.gn
index ac70b7e89a0..e0e010a517e 100644
--- a/chromium/components/web_resource/BUILD.gn
+++ b/chromium/components/web_resource/BUILD.gn
@@ -16,7 +16,8 @@ static_library("web_resource") {
deps = [
"//base",
- "//components/google/core/browser",
+ "//build:branding_buildflags",
+ "//components/google/core/common",
"//components/pref_registry",
"//components/prefs",
"//components/version_info",
diff --git a/chromium/components/web_resource/OWNERS b/chromium/components/web_resource/OWNERS
index 0173e252934..d029a522e74 100644
--- a/chromium/components/web_resource/OWNERS
+++ b/chromium/components/web_resource/OWNERS
@@ -2,5 +2,6 @@ achuith@chromium.org
rsesek@chromium.org
# For ResourceRequestAllowedNotifier and EulaAcceptedNotifier:
-per-file eula_accepted_notifier*=file://components/variations/OWNERS
-per-file resource_request_allowed_notifier*=file://components/variations/OWNERS
+per-file eula_accepted_notifier*=file://components/variations/OWNERS
+per-file resource_request_allowed_notifier*=file://components/variations/OWNERS
+# COMPONENT: UI>Shell
diff --git a/chromium/components/web_resource/eula_accepted_notifier.cc b/chromium/components/web_resource/eula_accepted_notifier.cc
index 9f01882bf8d..75a6b75cbc4 100644
--- a/chromium/components/web_resource/eula_accepted_notifier.cc
+++ b/chromium/components/web_resource/eula_accepted_notifier.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/prefs/pref_service.h"
#include "components/web_resource/web_resource_pref_names.h"
@@ -42,7 +43,7 @@ bool EulaAcceptedNotifier::IsEulaAccepted() {
EulaAcceptedNotifier* EulaAcceptedNotifier::Create(PrefService* local_state) {
// First run EULA only exists on ChromeOS, Android and iOS. On ChromeOS, it is
// only shown in official builds.
-#if (defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)) || \
+#if (defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)) || \
defined(OS_ANDROID) || defined(OS_IOS)
// Tests that use higher-level classes that use EulaAcceptNotifier may not
// have local state or may not register this pref. Return null to indicate not
diff --git a/chromium/components/web_resource/resource_request_allowed_notifier_unittest.cc b/chromium/components/web_resource/resource_request_allowed_notifier_unittest.cc
index 58578123de9..05a55123be2 100644
--- a/chromium/components/web_resource/resource_request_allowed_notifier_unittest.cc
+++ b/chromium/components/web_resource/resource_request_allowed_notifier_unittest.cc
@@ -5,7 +5,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "components/prefs/testing_pref_service.h"
#include "components/web_resource/eula_accepted_notifier.h"
#include "components/web_resource/resource_request_allowed_notifier_test_util.h"
@@ -119,8 +119,8 @@ class ResourceRequestAllowedNotifierTest
}
private:
- base::test::ScopedTaskEnvironment task_environment_{
- base::test::ScopedTaskEnvironment::MainThreadType::UI};
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
TestRequestAllowedNotifier resource_request_allowed_notifier_;
TestingPrefServiceSimple prefs_;
TestEulaAcceptedNotifier* eula_notifier_; // Weak, owned by RRAN.
diff --git a/chromium/components/web_resource/web_resource_service.cc b/chromium/components/web_resource/web_resource_service.cc
index e5eec285196..d1c0d4e9975 100644
--- a/chromium/components/web_resource/web_resource_service.cc
+++ b/chromium/components/web_resource/web_resource_service.cc
@@ -154,9 +154,8 @@ void WebResourceService::StartFetch() {
resource_request->url = web_resource_server;
// Do not let url fetcher affect existing state in system context
// (by setting cookies, for example).
- resource_request->load_flags = net::LOAD_DISABLE_CACHE |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DO_NOT_SAVE_COOKIES;
+ resource_request->load_flags = net::LOAD_DISABLE_CACHE;
+ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation_);
simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
diff --git a/chromium/components/web_resource/web_resource_service_unittest.cc b/chromium/components/web_resource/web_resource_service_unittest.cc
index cfb127cc1fc..4db1636c44c 100644
--- a/chromium/components/web_resource/web_resource_service_unittest.cc
+++ b/chromium/components/web_resource/web_resource_service_unittest.cc
@@ -6,7 +6,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/test/scoped_task_environment.h"
+#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
@@ -144,7 +144,7 @@ class WebResourceServiceTest : public testing::Test {
void CallStartFetch() { test_web_resource_service_->StartFetch(); }
private:
- base::test::ScopedTaskEnvironment task_environment_;
+ base::test::SingleThreadTaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
std::unique_ptr<TestingPrefServiceSimple> local_state_;
diff --git a/chromium/components/webdata/common/BUILD.gn b/chromium/components/webdata/common/BUILD.gn
index 74bd4b7b671..ae00fbffae9 100644
--- a/chromium/components/webdata/common/BUILD.gn
+++ b/chromium/components/webdata/common/BUILD.gn
@@ -68,6 +68,7 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/web_database/version_78.sql",
"//components/test/data/web_database/version_79.sql",
"//components/test/data/web_database/version_80.sql",
+ "//components/test/data/web_database/version_81.sql",
]
outputs = [
"{{bundle_resources_dir}}/" +
diff --git a/chromium/components/webdata/common/web_database.cc b/chromium/components/webdata/common/web_database.cc
index 1b78846c635..6606b78b014 100644
--- a/chromium/components/webdata/common/web_database.cc
+++ b/chromium/components/webdata/common/web_database.cc
@@ -13,7 +13,7 @@
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
// static
-const int WebDatabase::kCurrentVersionNumber = 81;
+const int WebDatabase::kCurrentVersionNumber = 82;
const int WebDatabase::kDeprecatedVersionNumber = 51;
diff --git a/chromium/components/webdata/common/web_database_migration_unittest.cc b/chromium/components/webdata/common/web_database_migration_unittest.cc
index de2b8d63364..1db9a9ec2e1 100644
--- a/chromium/components/webdata/common/web_database_migration_unittest.cc
+++ b/chromium/components/webdata/common/web_database_migration_unittest.cc
@@ -126,7 +126,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 81;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 82;
void WebDatabaseMigrationTest::LoadDatabase(
const base::FilePath::StringType& file) {
@@ -1758,3 +1758,36 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion80ToCurrent) {
EXPECT_FALSE(s2.Step());
}
}
+
+// Tests addition of created_from_play_api column in keywords table.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion81ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_81.sql")));
+
+ // Verify pre-conditions.
+ {
+ sql::Database connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(&connection, 81, 79));
+
+ EXPECT_FALSE(
+ connection.DoesColumnExist("keywords", "created_from_play_api"));
+ }
+
+ DoMigration();
+
+ // Verify post-conditions.
+ {
+ sql::Database connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ EXPECT_TRUE(
+ connection.DoesColumnExist("keywords", "created_from_play_api"));
+ }
+}
diff --git a/chromium/components/webdata_services/web_data_service_wrapper.cc b/chromium/components/webdata_services/web_data_service_wrapper.cc
index baf03a4a532..e0088bb8f0d 100644
--- a/chromium/components/webdata_services/web_data_service_wrapper.cc
+++ b/chromium/components/webdata_services/web_data_service_wrapper.cc
@@ -17,7 +17,6 @@
#include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h"
-#include "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
#include "components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_features.h"
@@ -37,7 +36,7 @@
namespace {
-void InitProfileSyncBridgesOnDBSequence(
+void InitAutofillSyncBridgesOnDBSequence(
scoped_refptr<base::SingleThreadTaskRunner> db_task_runner,
const scoped_refptr<autofill::AutofillWebDataService>& autofill_web_data,
const std::string& app_locale,
@@ -50,9 +49,7 @@ void InitProfileSyncBridgesOnDBSequence(
app_locale, autofill_backend, autofill_web_data.get());
}
-// TODO(jkrcal): Rename this function when the last webdata sync type get
-// converted to USS, e.g. to InitAccountSyncBridgesOnDBSequence().
-void InitSyncableAccountServicesOnDBSequence(
+void InitWalletSyncBridgesOnDBSequence(
scoped_refptr<base::SingleThreadTaskRunner> db_task_runner,
const scoped_refptr<autofill::AutofillWebDataService>& autofill_web_data,
const base::FilePath& context_path,
@@ -60,32 +57,10 @@ void InitSyncableAccountServicesOnDBSequence(
autofill::AutofillWebDataBackend* autofill_backend) {
DCHECK(db_task_runner->RunsTasksInCurrentSequence());
- base::RepeatingCallback<void(bool)> wallet_active_callback;
- if (base::FeatureList::IsEnabled(switches::kSyncUSSAutofillWalletMetadata)) {
- autofill::AutofillWalletMetadataSyncBridge::
- CreateForWebDataServiceAndBackend(app_locale, autofill_backend,
- autofill_web_data.get());
- wallet_active_callback = base::BindRepeating(
- &autofill::AutofillWalletMetadataSyncBridge::
- OnWalletDataTrackingStateChanged,
- autofill::AutofillWalletMetadataSyncBridge::FromWebDataService(
- autofill_web_data.get())
- ->GetWeakPtr());
- } else {
- autofill::AutofillWalletMetadataSyncableService::
- CreateForWebDataServiceAndBackend(autofill_web_data.get(),
- autofill_backend, app_locale);
- wallet_active_callback = base::BindRepeating(
- &autofill::AutofillWalletMetadataSyncableService::
- OnWalletDataTrackingStateChanged,
- autofill::AutofillWalletMetadataSyncableService::FromWebDataService(
- autofill_web_data.get())
- ->GetWeakPtr());
- }
-
autofill::AutofillWalletSyncBridge::CreateForWebDataServiceAndBackend(
- app_locale, wallet_active_callback, autofill_backend,
- autofill_web_data.get());
+ app_locale, autofill_backend, autofill_web_data.get());
+ autofill::AutofillWalletMetadataSyncBridge::CreateForWebDataServiceAndBackend(
+ app_locale, autofill_backend, autofill_web_data.get());
}
} // namespace
@@ -101,8 +76,8 @@ WebDataServiceWrapper::WebDataServiceWrapper(
// TODO(pkasting): http://crbug.com/740773 This should likely be sequenced,
// not single-threaded; it's also possible the various uses of this below
// should each use their own sequences instead of sharing this one.
- auto db_task_runner = base::CreateSingleThreadTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ auto db_task_runner = base::CreateSingleThreadTaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
profile_database_ =
new WebDatabaseService(path, ui_task_runner, db_task_runner);
@@ -143,10 +118,10 @@ WebDataServiceWrapper::WebDataServiceWrapper(
#endif
profile_autofill_web_data_->GetAutofillBackend(
- base::Bind(&InitProfileSyncBridgesOnDBSequence, db_task_runner,
+ base::Bind(&InitAutofillSyncBridgesOnDBSequence, db_task_runner,
profile_autofill_web_data_, application_locale));
profile_autofill_web_data_->GetAutofillBackend(
- base::Bind(&InitSyncableAccountServicesOnDBSequence, db_task_runner,
+ base::Bind(&InitWalletSyncBridgesOnDBSequence, db_task_runner,
profile_autofill_web_data_, context_path, application_locale));
if (base::FeatureList::IsEnabled(
@@ -162,7 +137,7 @@ WebDataServiceWrapper::WebDataServiceWrapper(
base::Bind(show_error_callback, ERROR_LOADING_ACCOUNT_AUTOFILL));
account_autofill_web_data_->Init();
account_autofill_web_data_->GetAutofillBackend(base::Bind(
- &InitSyncableAccountServicesOnDBSequence, db_task_runner,
+ &InitWalletSyncBridgesOnDBSequence, db_task_runner,
account_autofill_web_data_, context_path, application_locale));
}
}
diff --git a/chromium/components/webrtc_logging/OWNERS b/chromium/components/webrtc_logging/OWNERS
index aa82f4fd437..2046f2283ee 100644
--- a/chromium/components/webrtc_logging/OWNERS
+++ b/chromium/components/webrtc_logging/OWNERS
@@ -2,3 +2,4 @@ grunell@chromium.org
tommi@chromium.org
# COMPONENT: Blink>WebRTC>Tools
+# TEAM: webrtc-dev@chromium.org
diff --git a/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc b/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc
index 1de8bdd50dd..35f1f1cfbd0 100644
--- a/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc
+++ b/chromium/components/webrtc_logging/browser/log_cleanup_unittest.cc
@@ -9,7 +9,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/time/time.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace webrtc_logging {
@@ -57,7 +57,7 @@ class WebRtcLogCleanupTest : public testing::Test {
EXPECT_EQ(expected_files, file_counter);
}
- content::TestBrowserThreadBundle test_browser_thread_bundle_;
+ content::BrowserTaskEnvironment task_environment_;
base::ScopedTempDir dir_;
};
diff --git a/chromium/components/wifi/wifi_test.cc b/chromium/components/wifi/wifi_test.cc
index e4c5779322e..378498bce3d 100644
--- a/chromium/components/wifi/wifi_test.cc
+++ b/chromium/components/wifi/wifi_test.cc
@@ -14,14 +14,15 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_current.h"
+#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/single_thread_task_executor.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/wifi/wifi_service.h"
@@ -103,7 +104,6 @@ WiFiTest::Result WiFiTest::Main(int argc, const char* argv[]) {
return RESULT_WRONG_USAGE;
}
- base::MessageLoopForIO loop;
result_ = RESULT_PENDING;
return result_;
@@ -135,10 +135,10 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) {
MessageBoxA(nullptr, __FUNCTION__, "Debug Me!", MB_OK);
#endif
- base::MessageLoopForIO loop;
+ base::SingleThreadTaskExecutor executor(base::MessagePumpType::IO);
wifi_service_.reset(WiFiService::Create());
- wifi_service_->Initialize(loop.task_runner());
+ wifi_service_->Initialize(executor.task_runner());
if (parsed_command_line.HasSwitch("list")) {
base::ListValue network_list;
@@ -198,7 +198,7 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) {
}
wifi_service_->SetEventObservers(
- loop.task_runner(),
+ executor.task_runner(),
base::Bind(&WiFiTest::OnNetworksChanged, base::Unretained(this)),
base::Bind(&WiFiTest::OnNetworkListChanged, base::Unretained(this)));
@@ -231,7 +231,7 @@ bool WiFiTest::ParseCommandLine(int argc, const char* argv[]) {
if (parsed_command_line.HasSwitch("scan")) {
wifi_service_->SetEventObservers(
- loop.task_runner(),
+ executor.task_runner(),
base::Bind(&WiFiTest::OnNetworksChanged, base::Unretained(this)),
base::Bind(&WiFiTest::OnNetworkListChanged, base::Unretained(this)));
wifi_service_->RequestNetworkScan();
diff --git a/chromium/components/zucchini/zucchini_main.cc b/chromium/components/zucchini/zucchini_main.cc
index ab2c3e7c2a5..9b5e50507a1 100644
--- a/chromium/components/zucchini/zucchini_main.cc
+++ b/chromium/components/zucchini/zucchini_main.cc
@@ -20,7 +20,7 @@ void InitLogging() {
logging::LoggingSettings settings;
settings.logging_dest =
logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
- settings.log_file = nullptr;
+ settings.log_file_path = nullptr;
settings.lock_log = logging::DONT_LOCK_LOG_FILE;
settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
bool logging_res = logging::InitLogging(settings);